arm.md revision 117395
1252867Sdelphij;;- Machine description for ARM for GNU compiler 2252867Sdelphij;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000, 3252867Sdelphij;; 2001, 2002 Free Software Foundation, Inc. 4252867Sdelphij;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl) 5252867Sdelphij;; and Martin Simmons (@harleqn.co.uk). 6252867Sdelphij;; More major hacks by Richard Earnshaw (rearnsha@arm.com). 7252867Sdelphij 8252867Sdelphij;; This file is part of GNU CC. 9252867Sdelphij 10252867Sdelphij;; GNU CC is free software; you can redistribute it and/or modify 11252867Sdelphij;; it under the terms of the GNU General Public License as published by 12252867Sdelphij;; the Free Software Foundation; either version 2, or (at your option) 13252867Sdelphij;; any later version. 14252867Sdelphij 15252867Sdelphij;; GNU CC is distributed in the hope that it will be useful, 16252867Sdelphij;; but WITHOUT ANY WARRANTY; without even the implied warranty of 17252867Sdelphij;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18252867Sdelphij;; GNU General Public License for more details. 19252867Sdelphij 20252867Sdelphij;; You should have received a copy of the GNU General Public License 21252867Sdelphij;; along with GNU CC; see the file COPYING. If not, write to 22252867Sdelphij;; the Free Software Foundation, 59 Temple Place - Suite 330, 23252867Sdelphij;; Boston, MA 02111-1307, USA. 24252867Sdelphij 25252867Sdelphij;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. 26252867Sdelphij 27252867Sdelphij;; There are patterns in this file to support XFmode arithmetic. 28252867Sdelphij;; Unfortunately RISC iX doesn't work well with these so they are disabled. 29252867Sdelphij;; (See arm.h) 30252867Sdelphij 31252867Sdelphij;;--------------------------------------------------------------------------- 32252867Sdelphij;; Constants 33252867Sdelphij 34252867Sdelphij;; Register numbers 35252867Sdelphij(define_constants 36252867Sdelphij [(IP_REGNUM 12) ; Scratch register 37252867Sdelphij (SP_REGNUM 13) ; Stack pointer 38252867Sdelphij (LR_REGNUM 14) ; Return address register 39252867Sdelphij (PC_REGNUM 15) ; Program counter 40252867Sdelphij (CC_REGNUM 24) ; Condition code pseudo register 41252867Sdelphij (LAST_ARM_REGNUM 15) 42252867Sdelphij ] 43252867Sdelphij) 44252867Sdelphij 45252867Sdelphij;; UNSPEC Usage: 46252867Sdelphij;; Note: sin and cos are no-longer used. 47252867Sdelphij 48252867Sdelphij(define_constants 49252867Sdelphij [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT): 50252867Sdelphij ; operand 0 is the result, 51252867Sdelphij ; operand 1 the parameter. 52252867Sdelphij (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT): 53252867Sdelphij ; operand 0 is the result, 54252867Sdelphij ; operand 1 the parameter. 55252867Sdelphij (UNSPEC_PUSH_MULT 2) ; `push multiple' operation: 56252867Sdelphij ; operand 0 is the first register, 57252867Sdelphij ; subsequent registers are in parallel (use ...) 58252867Sdelphij ; expressions. 59252867Sdelphij (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic 60252867Sdelphij ; usage, that is, we will add the pic_register 61252867Sdelphij ; value to it before trying to dereference it. 62252867Sdelphij (UNSPEC_PIC_BASE 4) ; Adding the PC value to the offset to the 63252867Sdelphij ; GLOBAL_OFFSET_TABLE. The operation is fully 64252867Sdelphij ; described by the RTL but must be wrapped to 65252867Sdelphij ; prevent combine from trying to rip it apart. 66252867Sdelphij (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses 67252867Sdelphij ; being scheduled before the stack adjustment insn. 68252867Sdelphij (UNSPEC_CLZ 5) ; `clz' instruction, count leading zeros (SImode): 69252867Sdelphij ; operand 0 is the result, 70252867Sdelphij ; operand 1 is the parameter. 71252867Sdelphij (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload, 72252867Sdelphij ; this unspec is used to prevent the deletion of 73252867Sdelphij ; instructions setting registers for EH handling 74252867Sdelphij ; and stack frame generation. Operand 0 is the 75252867Sdelphij ; register to "use". 76252867Sdelphij (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode. 77252867Sdelphij ] 78252867Sdelphij) 79252867Sdelphij 80252867Sdelphij;; UNSPEC_VOLATILE Usage: 81252867Sdelphij 82252867Sdelphij(define_constants 83252867Sdelphij [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an 84252867Sdelphij ; insn in the code. 85252867Sdelphij (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the 86252867Sdelphij ; instruction epilogue sequence that isn't expanded 87252867Sdelphij ; into normal RTL. Used for both normal and sibcall 88252867Sdelphij ; epilogues. 89252867Sdelphij (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table 90252867Sdelphij ; for inlined constants. 91252867Sdelphij (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool 92252867Sdelphij ; table. 93 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for 94 ; an 8-bit object. 95 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for 96 ; a 16-bit object. 97 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for 98 ; a 32-bit object. 99 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for 100 ; a 64-bit object. 101 ] 102) 103 104;;--------------------------------------------------------------------------- 105;; Attributes 106 107; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when 108; generating ARM code. This is used to control the length of some insn 109; patterns that share the same RTL in both ARM and Thumb code. 110(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code"))) 111 112; PROG_MODE attribute is used to determine whether condition codes are 113; clobbered by a call insn: they are if in prog32 mode. This is controlled 114; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option. 115(define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode"))) 116 117; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects 118; scheduling decisions for the load unit and the multiplier. 119(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong"))) 120 121;; Operand number of an input operand that is shifted. Zero if the 122;; given instruction does not shift one of its input operands. 123(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_is_xscale"))) 124(define_attr "shift" "" (const_int 0)) 125 126; Floating Point Unit. If we only have floating point emulation, then there 127; is no point in scheduling the floating point insns. (Well, for best 128; performance we should try and group them together). 129(define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr"))) 130 131; LENGTH of an instruction (in bytes) 132(define_attr "length" "" (const_int 4)) 133 134; POOL_RANGE is how far away from a constant pool entry that this insn 135; can be placed. If the distance is zero, then this insn will never 136; reference the pool. 137; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry 138; before its address. 139(define_attr "pool_range" "" (const_int 0)) 140(define_attr "neg_pool_range" "" (const_int 0)) 141 142; An assembler sequence may clobber the condition codes without us knowing. 143; If such an insn references the pool, then we have no way of knowing how, 144; so use the most conservative value for pool_range. 145(define_asm_attributes 146 [(set_attr "conds" "clob") 147 (set_attr "length" "4") 148 (set_attr "pool_range" "250")]) 149 150; TYPE attribute is used to detect floating point instructions which, if 151; running on a co-processor can run in parallel with other, basic instructions 152; If write-buffer scheduling is enabled then it can also be used in the 153; scheduling of writes. 154 155; Classification of each insn 156; normal any data instruction that doesn't hit memory or fp regs 157; mult a multiply instruction 158; block blockage insn, this blocks all functional units 159; float a floating point arithmetic operation (subject to expansion) 160; fdivx XFmode floating point division 161; fdivd DFmode floating point division 162; fdivs SFmode floating point division 163; fmul Floating point multiply 164; ffmul Fast floating point multiply 165; farith Floating point arithmetic (4 cycle) 166; ffarith Fast floating point arithmetic (2 cycle) 167; float_em a floating point arithmetic operation that is normally emulated 168; even on a machine with an fpa. 169; f_load a floating point load from memory 170; f_store a floating point store to memory 171; f_mem_r a transfer of a floating point register to a real reg via mem 172; r_mem_f the reverse of f_mem_r 173; f_2_r fast transfer float to arm (no memory needed) 174; r_2_f fast transfer arm to float 175; call a subroutine call 176; load any load from memory 177; store1 store 1 word to memory from arm registers 178; store2 store 2 words 179; store3 store 3 words 180; store4 store 4 words 181; 182(define_attr "type" 183 "normal,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,call,load,store1,store2,store3,store4" 184 (const_string "normal")) 185 186; Load scheduling, set from the arm_ld_sched variable 187; initialized by arm_override_options() 188(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched"))) 189 190; condition codes: this one is used by final_prescan_insn to speed up 191; conditionalizing instructions. It saves having to scan the rtl to see if 192; it uses or alters the condition codes. 193; 194; USE means that the condition codes are used by the insn in the process of 195; outputting code, this means (at present) that we can't use the insn in 196; inlined branches 197; 198; SET means that the purpose of the insn is to set the condition codes in a 199; well defined manner. 200; 201; CLOB means that the condition codes are altered in an undefined manner, if 202; they are altered at all 203; 204; JUMP_CLOB is used when the condition cannot be represented by a single 205; instruction (UNEQ and LTGT). These cannot be predicated. 206; 207; NOCOND means that the condition codes are neither altered nor affect the 208; output of this insn 209 210(define_attr "conds" "use,set,clob,jump_clob,nocond" 211 (if_then_else (eq_attr "type" "call") 212 (if_then_else (eq_attr "prog_mode" "prog32") 213 (const_string "clob") (const_string "nocond")) 214 (const_string "nocond"))) 215 216; Predicable means that the insn can be conditionally executed based on 217; an automatically added predicate (additional patterns are generated by 218; gen...). We default to 'no' because no Thumb patterns match this rule 219; and not all ARM patterns do. 220(define_attr "predicable" "no,yes" (const_string "no")) 221 222; Only model the write buffer for ARM6 and ARM7. Earlier processors don't 223; have one. Later ones, such as StrongARM, have write-back caches, so don't 224; suffer blockages enough to warrent modelling this (and it can adversely 225; affect the schedule). 226(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7"))) 227 228; WRITE_CONFLICT implies that a read following an unrelated write is likely 229; to stall the processor. Used with model_wbuf above. 230(define_attr "write_conflict" "no,yes" 231 (if_then_else (eq_attr "type" 232 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load") 233 (const_string "yes") 234 (const_string "no"))) 235 236; Classify the insns into those that take one cycle and those that take more 237; than one on the main cpu execution unit. 238(define_attr "core_cycles" "single,multi" 239 (if_then_else (eq_attr "type" 240 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith") 241 (const_string "single") 242 (const_string "multi"))) 243 244;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a 245;; distant label. Only applicable to Thumb code. 246(define_attr "far_jump" "yes,no" (const_string "no")) 247 248;; (define_function_unit {name} {num-units} {n-users} {test} 249;; {ready-delay} {issue-delay} [{conflict-list}]) 250 251;;-------------------------------------------------------------------- 252;; Floating point unit (FPA) 253;;-------------------------------------------------------------------- 254(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") 255 (eq_attr "type" "fdivx")) 71 69) 256 257(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") 258 (eq_attr "type" "fdivd")) 59 57) 259 260(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") 261 (eq_attr "type" "fdivs")) 31 29) 262 263(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") 264 (eq_attr "type" "fmul")) 9 7) 265 266(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") 267 (eq_attr "type" "ffmul")) 6 4) 268 269(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") 270 (eq_attr "type" "farith")) 4 2) 271 272(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") 273 (eq_attr "type" "ffarith")) 2 2) 274 275(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") 276 (eq_attr "type" "r_2_f")) 5 3) 277 278(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") 279 (eq_attr "type" "f_2_r")) 1 2) 280 281; The fpa10 doesn't really have a memory read unit, but it can start to 282; speculatively execute the instruction in the pipeline, provided the data 283; is already loaded, so pretend reads have a delay of 2 (and that the 284; pipeline is infinite). 285 286(define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa") 287 (eq_attr "type" "f_load")) 3 1) 288 289;;-------------------------------------------------------------------- 290;; Write buffer 291;;-------------------------------------------------------------------- 292; Strictly, we should model a 4-deep write buffer for ARM7xx based chips 293; 294; The write buffer on some of the arm6 processors is hard to model exactly. 295; There is room in the buffer for up to two addresses and up to eight words 296; of memory, but the two needn't be split evenly. When writing the two 297; addresses are fully pipelined. However, a read from memory that is not 298; currently in the cache will block until the writes have completed. 299; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so 300; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous 301; (they aren't allowed to be at present) then there is a startup cost of 1MCLK 302; cycle to add as well. 303 304(define_function_unit "write_buf" 1 2 305 (and (eq_attr "model_wbuf" "yes") 306 (eq_attr "type" "store1,r_mem_f")) 5 3) 307(define_function_unit "write_buf" 1 2 308 (and (eq_attr "model_wbuf" "yes") 309 (eq_attr "type" "store2")) 7 4) 310(define_function_unit "write_buf" 1 2 311 (and (eq_attr "model_wbuf" "yes") 312 (eq_attr "type" "store3")) 9 5) 313(define_function_unit "write_buf" 1 2 314 (and (eq_attr "model_wbuf" "yes") 315 (eq_attr "type" "store4")) 11 6) 316 317;;-------------------------------------------------------------------- 318;; Write blockage unit 319;;-------------------------------------------------------------------- 320; The write_blockage unit models (partially), the fact that reads will stall 321; until the write buffer empties. 322; The f_mem_r and r_mem_f could also block, but they are to the stack, 323; so we don't model them here 324(define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes") 325 (eq_attr "type" "store1")) 5 5 326 [(eq_attr "write_conflict" "yes")]) 327(define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes") 328 (eq_attr "type" "store2")) 7 7 329 [(eq_attr "write_conflict" "yes")]) 330(define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes") 331 (eq_attr "type" "store3")) 9 9 332 [(eq_attr "write_conflict" "yes")]) 333(define_function_unit "write_blockage" 1 0 334 (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11 335 [(eq_attr "write_conflict" "yes")]) 336(define_function_unit "write_blockage" 1 0 337 (and (eq_attr "model_wbuf" "yes") 338 (eq_attr "write_conflict" "yes")) 1 1) 339 340;;-------------------------------------------------------------------- 341;; Core unit 342;;-------------------------------------------------------------------- 343; Everything must spend at least one cycle in the core unit 344(define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1) 345 346(define_function_unit "core" 1 0 347 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1) 348 349(define_function_unit "core" 1 0 350 (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1) 351 352;; We do not need to conditionalize the define_function_unit immediately 353;; above. This one will be ignored for anything other than xscale 354;; compiles and for xscale compiles it provides a larger delay 355;; and the scheduler will DTRT. 356;; FIXME: this test needs to be revamped to not depend on this feature 357;; of the scheduler. 358 359(define_function_unit "core" 1 0 360 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 361 (eq_attr "is_xscale" "yes")) 362 3 1) 363 364(define_function_unit "core" 1 0 365 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2) 366 367(define_function_unit "core" 1 0 368 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3) 369 370(define_function_unit "core" 1 0 371 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4) 372 373(define_function_unit "core" 1 0 374 (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6) 375 376(define_function_unit "core" 1 0 377 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7) 378 379(define_function_unit "core" 1 0 380 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16) 381 382(define_function_unit "core" 1 0 383 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no")) 384 (eq_attr "type" "mult")) 4 4) 385 386(define_function_unit "core" 1 0 387 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes")) 388 (eq_attr "type" "mult")) 3 2) 389 390(define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3) 391 392(define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4) 393 394(define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5) 395 396(define_function_unit "core" 1 0 397 (and (eq_attr "core_cycles" "multi") 398 (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32) 399 400;;--------------------------------------------------------------------------- 401;; Insn patterns 402;; 403;; Addition insns. 404 405;; Note: For DImode insns, there is normally no reason why operands should 406;; not be in the same register, what we don't want is for something being 407;; written to partially overlap something that is an input. 408 409(define_expand "adddi3" 410 [(parallel 411 [(set (match_operand:DI 0 "s_register_operand" "") 412 (plus:DI (match_operand:DI 1 "s_register_operand" "") 413 (match_operand:DI 2 "s_register_operand" ""))) 414 (clobber (reg:CC CC_REGNUM))])] 415 "TARGET_EITHER" 416 " 417 if (TARGET_THUMB) 418 { 419 if (GET_CODE (operands[1]) != REG) 420 operands[1] = force_reg (SImode, operands[1]); 421 if (GET_CODE (operands[2]) != REG) 422 operands[2] = force_reg (SImode, operands[2]); 423 } 424 " 425) 426 427(define_insn "*thumb_adddi3" 428 [(set (match_operand:DI 0 "register_operand" "=l") 429 (plus:DI (match_operand:DI 1 "register_operand" "%0") 430 (match_operand:DI 2 "register_operand" "l"))) 431 (clobber (reg:CC CC_REGNUM)) 432 ] 433 "TARGET_THUMB" 434 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2" 435 [(set_attr "length" "4")] 436) 437 438(define_insn_and_split "*arm_adddi3" 439 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 440 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0") 441 (match_operand:DI 2 "s_register_operand" "r, 0"))) 442 (clobber (reg:CC CC_REGNUM))] 443 "TARGET_ARM" 444 "#" 445 "TARGET_ARM && reload_completed" 446 [(parallel [(set (reg:CC_C CC_REGNUM) 447 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) 448 (match_dup 1))) 449 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) 450 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 451 (plus:SI (match_dup 4) (match_dup 5))))] 452 " 453 { 454 operands[3] = gen_highpart (SImode, operands[0]); 455 operands[0] = gen_lowpart (SImode, operands[0]); 456 operands[4] = gen_highpart (SImode, operands[1]); 457 operands[1] = gen_lowpart (SImode, operands[1]); 458 operands[5] = gen_highpart (SImode, operands[2]); 459 operands[2] = gen_lowpart (SImode, operands[2]); 460 }" 461 [(set_attr "conds" "clob") 462 (set_attr "length" "8")] 463) 464 465(define_insn_and_split "*adddi_sesidi_di" 466 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 467 (plus:DI (sign_extend:DI 468 (match_operand:SI 2 "s_register_operand" "r,r")) 469 (match_operand:DI 1 "s_register_operand" "r,0"))) 470 (clobber (reg:CC CC_REGNUM))] 471 "TARGET_ARM" 472 "#" 473 "TARGET_ARM && reload_completed" 474 [(parallel [(set (reg:CC_C CC_REGNUM) 475 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) 476 (match_dup 1))) 477 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) 478 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 479 (plus:SI (ashiftrt:SI (match_dup 2) 480 (const_int 31)) 481 (match_dup 4))))] 482 " 483 { 484 operands[3] = gen_highpart (SImode, operands[0]); 485 operands[0] = gen_lowpart (SImode, operands[0]); 486 operands[4] = gen_highpart (SImode, operands[1]); 487 operands[1] = gen_lowpart (SImode, operands[1]); 488 operands[2] = gen_lowpart (SImode, operands[2]); 489 }" 490 [(set_attr "conds" "clob") 491 (set_attr "length" "8")] 492) 493 494(define_insn_and_split "*adddi_zesidi_di" 495 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 496 (plus:DI (zero_extend:DI 497 (match_operand:SI 2 "s_register_operand" "r,r")) 498 (match_operand:DI 1 "s_register_operand" "r,0"))) 499 (clobber (reg:CC CC_REGNUM))] 500 "TARGET_ARM" 501 "#" 502 "TARGET_ARM && reload_completed" 503 [(parallel [(set (reg:CC_C CC_REGNUM) 504 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) 505 (match_dup 1))) 506 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) 507 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 508 (plus:SI (match_dup 4) (const_int 0))))] 509 " 510 { 511 operands[3] = gen_highpart (SImode, operands[0]); 512 operands[0] = gen_lowpart (SImode, operands[0]); 513 operands[4] = gen_highpart (SImode, operands[1]); 514 operands[1] = gen_lowpart (SImode, operands[1]); 515 operands[2] = gen_lowpart (SImode, operands[2]); 516 }" 517 [(set_attr "conds" "clob") 518 (set_attr "length" "8")] 519) 520 521(define_expand "addsi3" 522 [(set (match_operand:SI 0 "s_register_operand" "") 523 (plus:SI (match_operand:SI 1 "s_register_operand" "") 524 (match_operand:SI 2 "reg_or_int_operand" "")))] 525 "TARGET_EITHER" 526 " 527 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT) 528 { 529 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0], 530 operands[1], 531 (no_new_pseudos ? 0 : preserve_subexpressions_p ())); 532 DONE; 533 } 534 " 535) 536 537; If there is a scratch available, this will be faster than synthesising the 538; addition. 539(define_peephole2 540 [(match_scratch:SI 3 "r") 541 (set (match_operand:SI 0 "s_register_operand" "") 542 (plus:SI (match_operand:SI 1 "s_register_operand" "") 543 (match_operand:SI 2 "const_int_operand" "")))] 544 "TARGET_ARM && 545 !(const_ok_for_arm (INTVAL (operands[2])) 546 || const_ok_for_arm (-INTVAL (operands[2]))) 547 && const_ok_for_arm (~INTVAL (operands[2]))" 548 [(set (match_dup 3) (match_dup 2)) 549 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))] 550 "" 551) 552 553(define_insn_and_split "*arm_addsi3" 554 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 555 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r") 556 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))] 557 "TARGET_ARM" 558 "@ 559 add%?\\t%0, %1, %2 560 sub%?\\t%0, %1, #%n2 561 #" 562 "TARGET_ARM && 563 GET_CODE (operands[2]) == CONST_INT 564 && !(const_ok_for_arm (INTVAL (operands[2])) 565 || const_ok_for_arm (-INTVAL (operands[2])))" 566 [(clobber (const_int 0))] 567 " 568 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0], 569 operands[1], 0); 570 DONE; 571 " 572 [(set_attr "length" "4,4,16") 573 (set_attr "predicable" "yes")] 574) 575 576;; Register group 'k' is a single register group containing only the stack 577;; register. Trying to reload it will always fail catastrophically, 578;; so never allow those alternatives to match if reloading is needed. 579 580(define_insn "*thumb_addsi3" 581 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k") 582 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k") 583 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))] 584 "TARGET_THUMB" 585 "* 586 static const char * const asms[] = 587 { 588 \"add\\t%0, %0, %2\", 589 \"sub\\t%0, %0, #%n2\", 590 \"add\\t%0, %1, %2\", 591 \"add\\t%0, %0, %2\", 592 \"add\\t%0, %0, %2\", 593 \"add\\t%0, %1, %2\", 594 \"add\\t%0, %1, %2\" 595 }; 596 if ((which_alternative == 2 || which_alternative == 6) 597 && GET_CODE (operands[2]) == CONST_INT 598 && INTVAL (operands[2]) < 0) 599 return \"sub\\t%0, %1, #%n2\"; 600 return asms[which_alternative]; 601 " 602 [(set_attr "length" "2")] 603) 604 605;; Reloading and elimination of the frame pointer can 606;; sometimes cause this optimization to be missed. 607(define_peephole2 608 [(set (match_operand:SI 0 "register_operand" "") 609 (match_operand:SI 1 "const_int_operand" "")) 610 (set (match_dup 0) 611 (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))] 612 "TARGET_THUMB 613 && REGNO (operands[2]) == STACK_POINTER_REGNUM 614 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024 615 && (INTVAL (operands[1]) & 3) == 0" 616 [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))] 617 "" 618) 619 620(define_insn "*addsi3_compare0" 621 [(set (reg:CC_NOOV CC_REGNUM) 622 (compare:CC_NOOV 623 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r") 624 (match_operand:SI 2 "arm_add_operand" "rI,L")) 625 (const_int 0))) 626 (set (match_operand:SI 0 "s_register_operand" "=r,r") 627 (plus:SI (match_dup 1) (match_dup 2)))] 628 "TARGET_ARM" 629 "@ 630 add%?s\\t%0, %1, %2 631 sub%?s\\t%0, %1, #%n2" 632 [(set_attr "conds" "set")] 633) 634 635(define_insn "*addsi3_compare0_scratch" 636 [(set (reg:CC_NOOV CC_REGNUM) 637 (compare:CC_NOOV 638 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r") 639 (match_operand:SI 1 "arm_add_operand" "rI,L")) 640 (const_int 0)))] 641 "TARGET_ARM" 642 "@ 643 cmn%?\\t%0, %1 644 cmp%?\\t%0, #%n1" 645 [(set_attr "conds" "set")] 646) 647 648;; These patterns are the same ones as the two regular addsi3_compare0 649;; patterns, except we write them slightly different - the combiner 650;; tends to generate them this way. 651(define_insn "*addsi3_compare0_for_combiner" 652 [(set (reg:CC CC_REGNUM) 653 (compare:CC 654 (match_operand:SI 1 "s_register_operand" "r,r") 655 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L")))) 656 (set (match_operand:SI 0 "s_register_operand" "=r,r") 657 (plus:SI (match_dup 1) (match_dup 2)))] 658 "TARGET_ARM" 659 "@ 660 add%?s\\t%0, %1, %2 661 sub%?s\\t%0, %1, #%n2" 662 [(set_attr "conds" "set")] 663) 664 665(define_insn "*addsi3_compare0_scratch_for_combiner" 666 [(set (reg:CC CC_REGNUM) 667 (compare:CC 668 (match_operand:SI 0 "s_register_operand" "r,r") 669 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))] 670 "TARGET_ARM" 671 "@ 672 cmn%?\\t%0, %1 673 cmp%?\\t%0, #%n1" 674 [(set_attr "conds" "set")] 675) 676 677;; The next four insns work because they compare the result with one of 678;; the operands, and we know that the use of the condition code is 679;; either GEU or LTU, so we can use the carry flag from the addition 680;; instead of doing the compare a second time. 681(define_insn "*addsi3_compare_op1" 682 [(set (reg:CC_C CC_REGNUM) 683 (compare:CC_C 684 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r") 685 (match_operand:SI 2 "arm_add_operand" "rI,L")) 686 (match_dup 1))) 687 (set (match_operand:SI 0 "s_register_operand" "=r,r") 688 (plus:SI (match_dup 1) (match_dup 2)))] 689 "TARGET_ARM" 690 "@ 691 add%?s\\t%0, %1, %2 692 sub%?s\\t%0, %1, #%n2" 693 [(set_attr "conds" "set")] 694) 695 696(define_insn "*addsi3_compare_op2" 697 [(set (reg:CC_C CC_REGNUM) 698 (compare:CC_C 699 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r") 700 (match_operand:SI 2 "arm_add_operand" "rI,L")) 701 (match_dup 2))) 702 (set (match_operand:SI 0 "s_register_operand" "=r,r") 703 (plus:SI (match_dup 1) (match_dup 2)))] 704 "TARGET_ARM" 705 "@ 706 add%?s\\t%0, %1, %2 707 sub%?s\\t%0, %1, #%n2" 708 [(set_attr "conds" "set")] 709) 710 711(define_insn "*compare_addsi2_op0" 712 [(set (reg:CC_C CC_REGNUM) 713 (compare:CC_C 714 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r") 715 (match_operand:SI 1 "arm_add_operand" "rI,L")) 716 (match_dup 0)))] 717 "TARGET_ARM" 718 "@ 719 cmn%?\\t%0, %1 720 cmp%?\\t%0, #%n1" 721 [(set_attr "conds" "set")] 722) 723 724(define_insn "*compare_addsi2_op1" 725 [(set (reg:CC_C CC_REGNUM) 726 (compare:CC_C 727 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r") 728 (match_operand:SI 1 "arm_add_operand" "rI,L")) 729 (match_dup 1)))] 730 "TARGET_ARM" 731 "@ 732 cmn%?\\t%0, %1 733 cmp%?\\t%0, #%n1" 734 [(set_attr "conds" "set")] 735) 736 737(define_insn "*addsi3_carryin" 738 [(set (match_operand:SI 0 "s_register_operand" "=r") 739 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 740 (plus:SI (match_operand:SI 1 "s_register_operand" "r") 741 (match_operand:SI 2 "arm_rhs_operand" "rI"))))] 742 "TARGET_ARM" 743 "adc%?\\t%0, %1, %2" 744 [(set_attr "conds" "use")] 745) 746 747(define_insn "*addsi3_carryin_shift" 748 [(set (match_operand:SI 0 "s_register_operand" "") 749 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 750 (plus:SI 751 (match_operator:SI 2 "shift_operator" 752 [(match_operand:SI 3 "s_register_operand" "") 753 (match_operand:SI 4 "reg_or_int_operand" "")]) 754 (match_operand:SI 1 "s_register_operand" ""))))] 755 "TARGET_ARM" 756 "adc%?\\t%0, %1, %3%S2" 757 [(set_attr "conds" "use")] 758) 759 760(define_insn "*addsi3_carryin_alt1" 761 [(set (match_operand:SI 0 "s_register_operand" "=r") 762 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r") 763 (match_operand:SI 2 "arm_rhs_operand" "rI")) 764 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] 765 "TARGET_ARM" 766 "adc%?\\t%0, %1, %2" 767 [(set_attr "conds" "use")] 768) 769 770(define_insn "*addsi3_carryin_alt2" 771 [(set (match_operand:SI 0 "s_register_operand" "=r") 772 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 773 (match_operand:SI 1 "s_register_operand" "r")) 774 (match_operand:SI 2 "arm_rhs_operand" "rI")))] 775 "TARGET_ARM" 776 "adc%?\\t%0, %1, %2" 777 [(set_attr "conds" "use")] 778) 779 780(define_insn "*addsi3_carryin_alt3" 781 [(set (match_operand:SI 0 "s_register_operand" "=r") 782 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 783 (match_operand:SI 2 "arm_rhs_operand" "rI")) 784 (match_operand:SI 1 "s_register_operand" "r")))] 785 "TARGET_ARM" 786 "adc%?\\t%0, %1, %2" 787 [(set_attr "conds" "use")] 788) 789 790(define_insn "incscc" 791 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 792 (plus:SI (match_operator:SI 2 "arm_comparison_operator" 793 [(match_operand:CC 3 "cc_register" "") (const_int 0)]) 794 (match_operand:SI 1 "s_register_operand" "0,?r")))] 795 "TARGET_ARM" 796 "@ 797 add%d2\\t%0, %1, #1 798 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1" 799 [(set_attr "conds" "use") 800 (set_attr "length" "4,8")] 801) 802 803(define_insn "addsf3" 804 [(set (match_operand:SF 0 "s_register_operand" "=f,f") 805 (plus:SF (match_operand:SF 1 "s_register_operand" "%f,f") 806 (match_operand:SF 2 "fpu_add_operand" "fG,H")))] 807 "TARGET_ARM && TARGET_HARD_FLOAT" 808 "@ 809 adf%?s\\t%0, %1, %2 810 suf%?s\\t%0, %1, #%N2" 811 [(set_attr "type" "farith") 812 (set_attr "predicable" "yes")] 813) 814 815(define_insn "adddf3" 816 [(set (match_operand:DF 0 "s_register_operand" "=f,f") 817 (plus:DF (match_operand:DF 1 "s_register_operand" "%f,f") 818 (match_operand:DF 2 "fpu_add_operand" "fG,H")))] 819 "TARGET_ARM && TARGET_HARD_FLOAT" 820 "@ 821 adf%?d\\t%0, %1, %2 822 suf%?d\\t%0, %1, #%N2" 823 [(set_attr "type" "farith") 824 (set_attr "predicable" "yes")] 825) 826 827(define_insn "*adddf_esfdf_df" 828 [(set (match_operand:DF 0 "s_register_operand" "=f,f") 829 (plus:DF (float_extend:DF 830 (match_operand:SF 1 "s_register_operand" "f,f")) 831 (match_operand:DF 2 "fpu_add_operand" "fG,H")))] 832 "TARGET_ARM && TARGET_HARD_FLOAT" 833 "@ 834 adf%?d\\t%0, %1, %2 835 suf%?d\\t%0, %1, #%N2" 836 [(set_attr "type" "farith") 837 (set_attr "predicable" "yes")] 838) 839 840(define_insn "*adddf_df_esfdf" 841 [(set (match_operand:DF 0 "s_register_operand" "=f") 842 (plus:DF (match_operand:DF 1 "s_register_operand" "f") 843 (float_extend:DF 844 (match_operand:SF 2 "s_register_operand" "f"))))] 845 "TARGET_ARM && TARGET_HARD_FLOAT" 846 "adf%?d\\t%0, %1, %2" 847 [(set_attr "type" "farith") 848 (set_attr "predicable" "yes")] 849) 850 851(define_insn "*adddf_esfdf_esfdf" 852 [(set (match_operand:DF 0 "s_register_operand" "=f") 853 (plus:DF (float_extend:DF 854 (match_operand:SF 1 "s_register_operand" "f")) 855 (float_extend:DF 856 (match_operand:SF 2 "s_register_operand" "f"))))] 857 "TARGET_ARM && TARGET_HARD_FLOAT" 858 "adf%?d\\t%0, %1, %2" 859 [(set_attr "type" "farith") 860 (set_attr "predicable" "yes")] 861) 862 863(define_insn "addxf3" 864 [(set (match_operand:XF 0 "s_register_operand" "=f,f") 865 (plus:XF (match_operand:XF 1 "s_register_operand" "f,f") 866 (match_operand:XF 2 "fpu_add_operand" "fG,H")))] 867 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 868 "@ 869 adf%?e\\t%0, %1, %2 870 suf%?e\\t%0, %1, #%N2" 871 [(set_attr "type" "farith") 872 (set_attr "predicable" "yes")] 873) 874 875(define_expand "subdi3" 876 [(parallel 877 [(set (match_operand:DI 0 "s_register_operand" "") 878 (minus:DI (match_operand:DI 1 "s_register_operand" "") 879 (match_operand:DI 2 "s_register_operand" ""))) 880 (clobber (reg:CC CC_REGNUM))])] 881 "TARGET_EITHER" 882 " 883 if (TARGET_THUMB) 884 { 885 if (GET_CODE (operands[1]) != REG) 886 operands[1] = force_reg (SImode, operands[1]); 887 if (GET_CODE (operands[2]) != REG) 888 operands[2] = force_reg (SImode, operands[2]); 889 } 890 " 891) 892 893(define_insn "*arm_subdi3" 894 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r") 895 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0") 896 (match_operand:DI 2 "s_register_operand" "r,0,0"))) 897 (clobber (reg:CC CC_REGNUM))] 898 "TARGET_ARM" 899 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2" 900 [(set_attr "conds" "clob") 901 (set_attr "length" "8")] 902) 903 904(define_insn "*thumb_subdi3" 905 [(set (match_operand:DI 0 "register_operand" "=l") 906 (minus:DI (match_operand:DI 1 "register_operand" "0") 907 (match_operand:DI 2 "register_operand" "l"))) 908 (clobber (reg:CC CC_REGNUM))] 909 "TARGET_THUMB" 910 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2" 911 [(set_attr "length" "4")] 912) 913 914(define_insn "*subdi_di_zesidi" 915 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 916 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0") 917 (zero_extend:DI 918 (match_operand:SI 2 "s_register_operand" "r,r")))) 919 (clobber (reg:CC CC_REGNUM))] 920 "TARGET_ARM" 921 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0" 922 [(set_attr "conds" "clob") 923 (set_attr "length" "8")] 924) 925 926(define_insn "*subdi_di_sesidi" 927 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 928 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0") 929 (sign_extend:DI 930 (match_operand:SI 2 "s_register_operand" "r,r")))) 931 (clobber (reg:CC CC_REGNUM))] 932 "TARGET_ARM" 933 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31" 934 [(set_attr "conds" "clob") 935 (set_attr "length" "8")] 936) 937 938(define_insn "*subdi_zesidi_di" 939 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 940 (minus:DI (zero_extend:DI 941 (match_operand:SI 2 "s_register_operand" "r,r")) 942 (match_operand:DI 1 "s_register_operand" "?r,0"))) 943 (clobber (reg:CC CC_REGNUM))] 944 "TARGET_ARM" 945 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0" 946 [(set_attr "conds" "clob") 947 (set_attr "length" "8")] 948) 949 950(define_insn "*subdi_sesidi_di" 951 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 952 (minus:DI (sign_extend:DI 953 (match_operand:SI 2 "s_register_operand" "r,r")) 954 (match_operand:DI 1 "s_register_operand" "?r,0"))) 955 (clobber (reg:CC CC_REGNUM))] 956 "TARGET_ARM" 957 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31" 958 [(set_attr "conds" "clob") 959 (set_attr "length" "8")] 960) 961 962(define_insn "*subdi_zesidi_zesidi" 963 [(set (match_operand:DI 0 "s_register_operand" "=r") 964 (minus:DI (zero_extend:DI 965 (match_operand:SI 1 "s_register_operand" "r")) 966 (zero_extend:DI 967 (match_operand:SI 2 "s_register_operand" "r")))) 968 (clobber (reg:CC CC_REGNUM))] 969 "TARGET_ARM" 970 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1" 971 [(set_attr "conds" "clob") 972 (set_attr "length" "8")] 973) 974 975(define_expand "subsi3" 976 [(set (match_operand:SI 0 "s_register_operand" "") 977 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "") 978 (match_operand:SI 2 "s_register_operand" "")))] 979 "TARGET_EITHER" 980 " 981 if (GET_CODE (operands[1]) == CONST_INT) 982 { 983 if (TARGET_ARM) 984 { 985 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0], 986 operands[2], 987 (no_new_pseudos ? 0 988 : preserve_subexpressions_p ())); 989 DONE; 990 } 991 else /* TARGET_THUMB */ 992 operands[1] = force_reg (SImode, operands[1]); 993 } 994 " 995) 996 997(define_insn "*thumb_subsi3_insn" 998 [(set (match_operand:SI 0 "register_operand" "=l") 999 (minus:SI (match_operand:SI 1 "register_operand" "l") 1000 (match_operand:SI 2 "register_operand" "l")))] 1001 "TARGET_THUMB" 1002 "sub\\t%0, %1, %2" 1003 [(set_attr "length" "2")] 1004) 1005 1006(define_insn_and_split "*arm_subsi3_insn" 1007 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 1008 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n") 1009 (match_operand:SI 2 "s_register_operand" "r,r")))] 1010 "TARGET_ARM" 1011 "@ 1012 rsb%?\\t%0, %2, %1 1013 #" 1014 "TARGET_ARM 1015 && GET_CODE (operands[1]) == CONST_INT 1016 && !const_ok_for_arm (INTVAL (operands[1]))" 1017 [(clobber (const_int 0))] 1018 " 1019 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0], 1020 operands[2], 0); 1021 DONE; 1022 " 1023 [(set_attr "length" "4,16") 1024 (set_attr "predicable" "yes")] 1025) 1026 1027(define_peephole2 1028 [(match_scratch:SI 3 "r") 1029 (set (match_operand:SI 0 "s_register_operand" "") 1030 (minus:SI (match_operand:SI 1 "const_int_operand" "") 1031 (match_operand:SI 2 "s_register_operand" "")))] 1032 "TARGET_ARM 1033 && !const_ok_for_arm (INTVAL (operands[1])) 1034 && const_ok_for_arm (~INTVAL (operands[1]))" 1035 [(set (match_dup 3) (match_dup 1)) 1036 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))] 1037 "" 1038) 1039 1040(define_insn "*subsi3_compare0" 1041 [(set (reg:CC_NOOV CC_REGNUM) 1042 (compare:CC_NOOV 1043 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I") 1044 (match_operand:SI 2 "arm_rhs_operand" "rI,r")) 1045 (const_int 0))) 1046 (set (match_operand:SI 0 "s_register_operand" "=r,r") 1047 (minus:SI (match_dup 1) (match_dup 2)))] 1048 "TARGET_ARM" 1049 "@ 1050 sub%?s\\t%0, %1, %2 1051 rsb%?s\\t%0, %2, %1" 1052 [(set_attr "conds" "set")] 1053) 1054 1055(define_insn "decscc" 1056 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 1057 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r") 1058 (match_operator:SI 2 "arm_comparison_operator" 1059 [(match_operand 3 "cc_register" "") (const_int 0)])))] 1060 "TARGET_ARM" 1061 "@ 1062 sub%d2\\t%0, %1, #1 1063 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1" 1064 [(set_attr "conds" "use") 1065 (set_attr "length" "*,8")] 1066) 1067 1068(define_insn "subsf3" 1069 [(set (match_operand:SF 0 "s_register_operand" "=f,f") 1070 (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G") 1071 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))] 1072 "TARGET_ARM && TARGET_HARD_FLOAT" 1073 "@ 1074 suf%?s\\t%0, %1, %2 1075 rsf%?s\\t%0, %2, %1" 1076 [(set_attr "type" "farith")] 1077) 1078 1079(define_insn "subdf3" 1080 [(set (match_operand:DF 0 "s_register_operand" "=f,f") 1081 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G") 1082 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))] 1083 "TARGET_ARM && TARGET_HARD_FLOAT" 1084 "@ 1085 suf%?d\\t%0, %1, %2 1086 rsf%?d\\t%0, %2, %1" 1087 [(set_attr "type" "farith") 1088 (set_attr "predicable" "yes")] 1089) 1090 1091(define_insn "*subdf_esfdf_df" 1092 [(set (match_operand:DF 0 "s_register_operand" "=f") 1093 (minus:DF (float_extend:DF 1094 (match_operand:SF 1 "s_register_operand" "f")) 1095 (match_operand:DF 2 "fpu_rhs_operand" "fG")))] 1096 "TARGET_ARM && TARGET_HARD_FLOAT" 1097 "suf%?d\\t%0, %1, %2" 1098 [(set_attr "type" "farith") 1099 (set_attr "predicable" "yes")] 1100) 1101 1102(define_insn "*subdf_df_esfdf" 1103 [(set (match_operand:DF 0 "s_register_operand" "=f,f") 1104 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G") 1105 (float_extend:DF 1106 (match_operand:SF 2 "s_register_operand" "f,f"))))] 1107 "TARGET_ARM && TARGET_HARD_FLOAT" 1108 "@ 1109 suf%?d\\t%0, %1, %2 1110 rsf%?d\\t%0, %2, %1" 1111 [(set_attr "type" "farith") 1112 (set_attr "predicable" "yes")] 1113) 1114 1115(define_insn "*subdf_esfdf_esfdf" 1116 [(set (match_operand:DF 0 "s_register_operand" "=f") 1117 (minus:DF (float_extend:DF 1118 (match_operand:SF 1 "s_register_operand" "f")) 1119 (float_extend:DF 1120 (match_operand:SF 2 "s_register_operand" "f"))))] 1121 "TARGET_ARM && TARGET_HARD_FLOAT" 1122 "suf%?d\\t%0, %1, %2" 1123 [(set_attr "type" "farith") 1124 (set_attr "predicable" "yes")] 1125) 1126 1127(define_insn "subxf3" 1128 [(set (match_operand:XF 0 "s_register_operand" "=f,f") 1129 (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G") 1130 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))] 1131 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 1132 "@ 1133 suf%?e\\t%0, %1, %2 1134 rsf%?e\\t%0, %2, %1" 1135 [(set_attr "type" "farith") 1136 (set_attr "predicable" "yes")] 1137) 1138 1139;; Multiplication insns 1140 1141(define_expand "mulsi3" 1142 [(set (match_operand:SI 0 "s_register_operand" "") 1143 (mult:SI (match_operand:SI 2 "s_register_operand" "") 1144 (match_operand:SI 1 "s_register_operand" "")))] 1145 "TARGET_EITHER" 1146 "" 1147) 1148 1149;; Use `&' and then `0' to prevent the operands 0 and 1 being the same 1150(define_insn "*arm_mulsi3" 1151 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r") 1152 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r") 1153 (match_operand:SI 1 "s_register_operand" "%?r,0")))] 1154 "TARGET_ARM" 1155 "mul%?\\t%0, %2, %1" 1156 [(set_attr "type" "mult") 1157 (set_attr "predicable" "yes")] 1158) 1159 1160; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 1161; 1 and 2; are the same, because reload will make operand 0 match 1162; operand 1 without realizing that this conflicts with operand 2. We fix 1163; this by adding another alternative to match this case, and then `reload' 1164; it ourselves. This alternative must come first. 1165(define_insn "*thumb_mulsi3" 1166 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l") 1167 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0") 1168 (match_operand:SI 2 "register_operand" "l,l,l")))] 1169 "TARGET_THUMB" 1170 "* 1171 if (which_alternative < 2) 1172 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\"; 1173 else 1174 return \"mul\\t%0, %0, %2\"; 1175 " 1176 [(set_attr "length" "4,4,2") 1177 (set_attr "type" "mult")] 1178) 1179 1180(define_insn "*mulsi3_compare0" 1181 [(set (reg:CC_NOOV CC_REGNUM) 1182 (compare:CC_NOOV (mult:SI 1183 (match_operand:SI 2 "s_register_operand" "r,r") 1184 (match_operand:SI 1 "s_register_operand" "%?r,0")) 1185 (const_int 0))) 1186 (set (match_operand:SI 0 "s_register_operand" "=&r,&r") 1187 (mult:SI (match_dup 2) (match_dup 1)))] 1188 "TARGET_ARM && !arm_is_xscale" 1189 "mul%?s\\t%0, %2, %1" 1190 [(set_attr "conds" "set") 1191 (set_attr "type" "mult")] 1192) 1193 1194(define_insn "*mulsi_compare0_scratch" 1195 [(set (reg:CC_NOOV CC_REGNUM) 1196 (compare:CC_NOOV (mult:SI 1197 (match_operand:SI 2 "s_register_operand" "r,r") 1198 (match_operand:SI 1 "s_register_operand" "%?r,0")) 1199 (const_int 0))) 1200 (clobber (match_scratch:SI 0 "=&r,&r"))] 1201 "TARGET_ARM && !arm_is_xscale" 1202 "mul%?s\\t%0, %2, %1" 1203 [(set_attr "conds" "set") 1204 (set_attr "type" "mult")] 1205) 1206 1207;; Unnamed templates to match MLA instruction. 1208 1209(define_insn "*mulsi3addsi" 1210 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r") 1211 (plus:SI 1212 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r") 1213 (match_operand:SI 1 "s_register_operand" "%r,0,r,0")) 1214 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))] 1215 "TARGET_ARM" 1216 "mla%?\\t%0, %2, %1, %3" 1217 [(set_attr "type" "mult") 1218 (set_attr "predicable" "yes")] 1219) 1220 1221(define_insn "*mulsi3addsi_compare0" 1222 [(set (reg:CC_NOOV CC_REGNUM) 1223 (compare:CC_NOOV 1224 (plus:SI (mult:SI 1225 (match_operand:SI 2 "s_register_operand" "r,r,r,r") 1226 (match_operand:SI 1 "s_register_operand" "%r,0,r,0")) 1227 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")) 1228 (const_int 0))) 1229 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r") 1230 (plus:SI (mult:SI (match_dup 2) (match_dup 1)) 1231 (match_dup 3)))] 1232 "TARGET_ARM && !arm_is_xscale" 1233 "mla%?s\\t%0, %2, %1, %3" 1234 [(set_attr "conds" "set") 1235 (set_attr "type" "mult")] 1236) 1237 1238(define_insn "*mulsi3addsi_compare0_scratch" 1239 [(set (reg:CC_NOOV CC_REGNUM) 1240 (compare:CC_NOOV 1241 (plus:SI (mult:SI 1242 (match_operand:SI 2 "s_register_operand" "r,r,r,r") 1243 (match_operand:SI 1 "s_register_operand" "%r,0,r,0")) 1244 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")) 1245 (const_int 0))) 1246 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))] 1247 "TARGET_ARM && !arm_is_xscale" 1248 "mla%?s\\t%0, %2, %1, %3" 1249 [(set_attr "conds" "set") 1250 (set_attr "type" "mult")] 1251) 1252 1253;; Unnamed template to match long long multiply-accumlate (smlal) 1254 1255(define_insn "*mulsidi3adddi" 1256 [(set (match_operand:DI 0 "s_register_operand" "=&r") 1257 (plus:DI 1258 (mult:DI 1259 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r")) 1260 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r"))) 1261 (match_operand:DI 1 "s_register_operand" "0")))] 1262 "TARGET_ARM && arm_fast_multiply" 1263 "smlal%?\\t%Q0, %R0, %3, %2" 1264 [(set_attr "type" "mult") 1265 (set_attr "predicable" "yes")] 1266) 1267 1268(define_insn "mulsidi3" 1269 [(set (match_operand:DI 0 "s_register_operand" "=&r") 1270 (mult:DI 1271 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r")) 1272 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))] 1273 "TARGET_ARM && arm_fast_multiply" 1274 "smull%?\\t%Q0, %R0, %1, %2" 1275 [(set_attr "type" "mult") 1276 (set_attr "predicable" "yes")] 1277) 1278 1279(define_insn "umulsidi3" 1280 [(set (match_operand:DI 0 "s_register_operand" "=&r") 1281 (mult:DI 1282 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r")) 1283 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))] 1284 "TARGET_ARM && arm_fast_multiply" 1285 "umull%?\\t%Q0, %R0, %1, %2" 1286 [(set_attr "type" "mult") 1287 (set_attr "predicable" "yes")] 1288) 1289 1290;; Unnamed template to match long long unsigned multiply-accumlate (umlal) 1291 1292(define_insn "*umulsidi3adddi" 1293 [(set (match_operand:DI 0 "s_register_operand" "=&r") 1294 (plus:DI 1295 (mult:DI 1296 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r")) 1297 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r"))) 1298 (match_operand:DI 1 "s_register_operand" "0")))] 1299 "TARGET_ARM && arm_fast_multiply" 1300 "umlal%?\\t%Q0, %R0, %3, %2" 1301 [(set_attr "type" "mult") 1302 (set_attr "predicable" "yes")] 1303) 1304 1305(define_insn "smulsi3_highpart" 1306 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r") 1307 (truncate:SI 1308 (lshiftrt:DI 1309 (mult:DI 1310 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0")) 1311 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r"))) 1312 (const_int 32)))) 1313 (clobber (match_scratch:SI 3 "=&r,&r"))] 1314 "TARGET_ARM && arm_fast_multiply" 1315 "smull%?\\t%3, %0, %2, %1" 1316 [(set_attr "type" "mult") 1317 (set_attr "predicable" "yes")] 1318) 1319 1320(define_insn "umulsi3_highpart" 1321 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r") 1322 (truncate:SI 1323 (lshiftrt:DI 1324 (mult:DI 1325 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0")) 1326 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r"))) 1327 (const_int 32)))) 1328 (clobber (match_scratch:SI 3 "=&r,&r"))] 1329 "TARGET_ARM && arm_fast_multiply" 1330 "umull%?\\t%3, %0, %2, %1" 1331 [(set_attr "type" "mult") 1332 (set_attr "predicable" "yes")] 1333) 1334 1335(define_insn "mulhisi3" 1336 [(set (match_operand:SI 0 "s_register_operand" "=r") 1337 (mult:SI (sign_extend:SI 1338 (match_operand:HI 1 "s_register_operand" "%r")) 1339 (sign_extend:SI 1340 (match_operand:HI 2 "s_register_operand" "r"))))] 1341 "TARGET_ARM && arm_is_xscale" 1342 "smulbb%?\\t%0, %1, %2" 1343 [(set_attr "type" "mult")] 1344) 1345 1346(define_insn "*mulhisi3addsi" 1347 [(set (match_operand:SI 0 "s_register_operand" "=r") 1348 (plus:SI (match_operand:SI 1 "s_register_operand" "r") 1349 (mult:SI (sign_extend:SI 1350 (match_operand:HI 2 "s_register_operand" "%r")) 1351 (sign_extend:SI 1352 (match_operand:HI 3 "s_register_operand" "r")))))] 1353 "TARGET_ARM && arm_is_xscale" 1354 "smlabb%?\\t%0, %2, %3, %1" 1355 [(set_attr "type" "mult")] 1356) 1357 1358(define_insn "*mulhidi3adddi" 1359 [(set (match_operand:DI 0 "s_register_operand" "=r") 1360 (plus:DI 1361 (match_operand:DI 1 "s_register_operand" "0") 1362 (mult:DI (sign_extend:DI 1363 (match_operand:HI 2 "s_register_operand" "%r")) 1364 (sign_extend:DI 1365 (match_operand:HI 3 "s_register_operand" "r")))))] 1366 "TARGET_ARM && arm_is_xscale" 1367 "smlalbb%?\\t%Q0, %R0, %2, %3" 1368[(set_attr "type" "mult")]) 1369 1370(define_insn "mulsf3" 1371 [(set (match_operand:SF 0 "s_register_operand" "=f") 1372 (mult:SF (match_operand:SF 1 "s_register_operand" "f") 1373 (match_operand:SF 2 "fpu_rhs_operand" "fG")))] 1374 "TARGET_ARM && TARGET_HARD_FLOAT" 1375 "fml%?s\\t%0, %1, %2" 1376 [(set_attr "type" "ffmul") 1377 (set_attr "predicable" "yes")] 1378) 1379 1380(define_insn "muldf3" 1381 [(set (match_operand:DF 0 "s_register_operand" "=f") 1382 (mult:DF (match_operand:DF 1 "s_register_operand" "f") 1383 (match_operand:DF 2 "fpu_rhs_operand" "fG")))] 1384 "TARGET_ARM && TARGET_HARD_FLOAT" 1385 "muf%?d\\t%0, %1, %2" 1386 [(set_attr "type" "fmul") 1387 (set_attr "predicable" "yes")] 1388) 1389 1390(define_insn "*muldf_esfdf_df" 1391 [(set (match_operand:DF 0 "s_register_operand" "=f") 1392 (mult:DF (float_extend:DF 1393 (match_operand:SF 1 "s_register_operand" "f")) 1394 (match_operand:DF 2 "fpu_rhs_operand" "fG")))] 1395 "TARGET_ARM && TARGET_HARD_FLOAT" 1396 "muf%?d\\t%0, %1, %2" 1397 [(set_attr "type" "fmul") 1398 (set_attr "predicable" "yes")] 1399) 1400 1401(define_insn "*muldf_df_esfdf" 1402 [(set (match_operand:DF 0 "s_register_operand" "=f") 1403 (mult:DF (match_operand:DF 1 "s_register_operand" "f") 1404 (float_extend:DF 1405 (match_operand:SF 2 "s_register_operand" "f"))))] 1406 "TARGET_ARM && TARGET_HARD_FLOAT" 1407 "muf%?d\\t%0, %1, %2" 1408 [(set_attr "type" "fmul") 1409 (set_attr "predicable" "yes")] 1410) 1411 1412(define_insn "*muldf_esfdf_esfdf" 1413 [(set (match_operand:DF 0 "s_register_operand" "=f") 1414 (mult:DF 1415 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")) 1416 (float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))] 1417 "TARGET_ARM && TARGET_HARD_FLOAT" 1418 "muf%?d\\t%0, %1, %2" 1419 [(set_attr "type" "fmul") 1420 (set_attr "predicable" "yes")] 1421) 1422 1423(define_insn "mulxf3" 1424 [(set (match_operand:XF 0 "s_register_operand" "=f") 1425 (mult:XF (match_operand:XF 1 "s_register_operand" "f") 1426 (match_operand:XF 2 "fpu_rhs_operand" "fG")))] 1427 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 1428 "muf%?e\\t%0, %1, %2" 1429 [(set_attr "type" "fmul") 1430 (set_attr "predicable" "yes")] 1431) 1432 1433;; Division insns 1434 1435(define_insn "divsf3" 1436 [(set (match_operand:SF 0 "s_register_operand" "=f,f") 1437 (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G") 1438 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))] 1439 "TARGET_ARM && TARGET_HARD_FLOAT" 1440 "@ 1441 fdv%?s\\t%0, %1, %2 1442 frd%?s\\t%0, %2, %1" 1443 [(set_attr "type" "fdivs") 1444 (set_attr "predicable" "yes")] 1445) 1446 1447(define_insn "divdf3" 1448 [(set (match_operand:DF 0 "s_register_operand" "=f,f") 1449 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G") 1450 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))] 1451 "TARGET_ARM && TARGET_HARD_FLOAT" 1452 "@ 1453 dvf%?d\\t%0, %1, %2 1454 rdf%?d\\t%0, %2, %1" 1455 [(set_attr "type" "fdivd") 1456 (set_attr "predicable" "yes")] 1457) 1458 1459(define_insn "*divdf_esfdf_df" 1460 [(set (match_operand:DF 0 "s_register_operand" "=f") 1461 (div:DF (float_extend:DF 1462 (match_operand:SF 1 "s_register_operand" "f")) 1463 (match_operand:DF 2 "fpu_rhs_operand" "fG")))] 1464 "TARGET_ARM && TARGET_HARD_FLOAT" 1465 "dvf%?d\\t%0, %1, %2" 1466 [(set_attr "type" "fdivd") 1467 (set_attr "predicable" "yes")] 1468) 1469 1470(define_insn "*divdf_df_esfdf" 1471 [(set (match_operand:DF 0 "s_register_operand" "=f") 1472 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG") 1473 (float_extend:DF 1474 (match_operand:SF 2 "s_register_operand" "f"))))] 1475 "TARGET_ARM && TARGET_HARD_FLOAT" 1476 "rdf%?d\\t%0, %2, %1" 1477 [(set_attr "type" "fdivd") 1478 (set_attr "predicable" "yes")] 1479) 1480 1481(define_insn "*divdf_esfdf_esfdf" 1482 [(set (match_operand:DF 0 "s_register_operand" "=f") 1483 (div:DF (float_extend:DF 1484 (match_operand:SF 1 "s_register_operand" "f")) 1485 (float_extend:DF 1486 (match_operand:SF 2 "s_register_operand" "f"))))] 1487 "TARGET_ARM && TARGET_HARD_FLOAT" 1488 "dvf%?d\\t%0, %1, %2" 1489 [(set_attr "type" "fdivd") 1490 (set_attr "predicable" "yes")] 1491) 1492 1493(define_insn "divxf3" 1494 [(set (match_operand:XF 0 "s_register_operand" "=f,f") 1495 (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G") 1496 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))] 1497 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 1498 "@ 1499 dvf%?e\\t%0, %1, %2 1500 rdf%?e\\t%0, %2, %1" 1501 [(set_attr "type" "fdivx") 1502 (set_attr "predicable" "yes")] 1503) 1504 1505;; Modulo insns 1506 1507(define_insn "modsf3" 1508 [(set (match_operand:SF 0 "s_register_operand" "=f") 1509 (mod:SF (match_operand:SF 1 "s_register_operand" "f") 1510 (match_operand:SF 2 "fpu_rhs_operand" "fG")))] 1511 "TARGET_ARM && TARGET_HARD_FLOAT" 1512 "rmf%?s\\t%0, %1, %2" 1513 [(set_attr "type" "fdivs") 1514 (set_attr "predicable" "yes")] 1515) 1516 1517(define_insn "moddf3" 1518 [(set (match_operand:DF 0 "s_register_operand" "=f") 1519 (mod:DF (match_operand:DF 1 "s_register_operand" "f") 1520 (match_operand:DF 2 "fpu_rhs_operand" "fG")))] 1521 "TARGET_ARM && TARGET_HARD_FLOAT" 1522 "rmf%?d\\t%0, %1, %2" 1523 [(set_attr "type" "fdivd") 1524 (set_attr "predicable" "yes")] 1525) 1526 1527(define_insn "*moddf_esfdf_df" 1528 [(set (match_operand:DF 0 "s_register_operand" "=f") 1529 (mod:DF (float_extend:DF 1530 (match_operand:SF 1 "s_register_operand" "f")) 1531 (match_operand:DF 2 "fpu_rhs_operand" "fG")))] 1532 "TARGET_ARM && TARGET_HARD_FLOAT" 1533 "rmf%?d\\t%0, %1, %2" 1534 [(set_attr "type" "fdivd") 1535 (set_attr "predicable" "yes")] 1536) 1537 1538(define_insn "*moddf_df_esfdf" 1539 [(set (match_operand:DF 0 "s_register_operand" "=f") 1540 (mod:DF (match_operand:DF 1 "s_register_operand" "f") 1541 (float_extend:DF 1542 (match_operand:SF 2 "s_register_operand" "f"))))] 1543 "TARGET_ARM && TARGET_HARD_FLOAT" 1544 "rmf%?d\\t%0, %1, %2" 1545 [(set_attr "type" "fdivd") 1546 (set_attr "predicable" "yes")] 1547) 1548 1549(define_insn "*moddf_esfdf_esfdf" 1550 [(set (match_operand:DF 0 "s_register_operand" "=f") 1551 (mod:DF (float_extend:DF 1552 (match_operand:SF 1 "s_register_operand" "f")) 1553 (float_extend:DF 1554 (match_operand:SF 2 "s_register_operand" "f"))))] 1555 "TARGET_ARM && TARGET_HARD_FLOAT" 1556 "rmf%?d\\t%0, %1, %2" 1557 [(set_attr "type" "fdivd") 1558 (set_attr "predicable" "yes")] 1559) 1560 1561(define_insn "modxf3" 1562 [(set (match_operand:XF 0 "s_register_operand" "=f") 1563 (mod:XF (match_operand:XF 1 "s_register_operand" "f") 1564 (match_operand:XF 2 "fpu_rhs_operand" "fG")))] 1565 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 1566 "rmf%?e\\t%0, %1, %2" 1567 [(set_attr "type" "fdivx") 1568 (set_attr "predicable" "yes")] 1569) 1570 1571;; Boolean and,ior,xor insns 1572 1573;; Split up double word logical operations 1574 1575;; Split up simple DImode logical operations. Simply perform the logical 1576;; operation on the upper and lower halves of the registers. 1577(define_split 1578 [(set (match_operand:DI 0 "s_register_operand" "") 1579 (match_operator:DI 6 "logical_binary_operator" 1580 [(match_operand:DI 1 "s_register_operand" "") 1581 (match_operand:DI 2 "s_register_operand" "")]))] 1582 "TARGET_ARM && reload_completed" 1583 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)])) 1584 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))] 1585 " 1586 { 1587 operands[3] = gen_highpart (SImode, operands[0]); 1588 operands[0] = gen_lowpart (SImode, operands[0]); 1589 operands[4] = gen_highpart (SImode, operands[1]); 1590 operands[1] = gen_lowpart (SImode, operands[1]); 1591 operands[5] = gen_highpart (SImode, operands[2]); 1592 operands[2] = gen_lowpart (SImode, operands[2]); 1593 }" 1594) 1595 1596(define_split 1597 [(set (match_operand:DI 0 "s_register_operand" "") 1598 (match_operator:DI 6 "logical_binary_operator" 1599 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" "")) 1600 (match_operand:DI 1 "s_register_operand" "")]))] 1601 "TARGET_ARM && reload_completed" 1602 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)])) 1603 (set (match_dup 3) (match_op_dup:SI 6 1604 [(ashiftrt:SI (match_dup 2) (const_int 31)) 1605 (match_dup 4)]))] 1606 " 1607 { 1608 operands[3] = gen_highpart (SImode, operands[0]); 1609 operands[0] = gen_lowpart (SImode, operands[0]); 1610 operands[4] = gen_highpart (SImode, operands[1]); 1611 operands[1] = gen_lowpart (SImode, operands[1]); 1612 operands[5] = gen_highpart (SImode, operands[2]); 1613 operands[2] = gen_lowpart (SImode, operands[2]); 1614 }" 1615) 1616 1617;; The zero extend of operand 2 means we can just copy the high part of 1618;; operand1 into operand0. 1619(define_split 1620 [(set (match_operand:DI 0 "s_register_operand" "") 1621 (ior:DI 1622 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")) 1623 (match_operand:DI 1 "s_register_operand" "")))] 1624 "TARGET_ARM && operands[0] != operands[1] && reload_completed" 1625 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2))) 1626 (set (match_dup 3) (match_dup 4))] 1627 " 1628 { 1629 operands[4] = gen_highpart (SImode, operands[1]); 1630 operands[3] = gen_highpart (SImode, operands[0]); 1631 operands[0] = gen_lowpart (SImode, operands[0]); 1632 operands[1] = gen_lowpart (SImode, operands[1]); 1633 }" 1634) 1635 1636;; The zero extend of operand 2 means we can just copy the high part of 1637;; operand1 into operand0. 1638(define_split 1639 [(set (match_operand:DI 0 "s_register_operand" "") 1640 (xor:DI 1641 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")) 1642 (match_operand:DI 1 "s_register_operand" "")))] 1643 "TARGET_ARM && operands[0] != operands[1] && reload_completed" 1644 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2))) 1645 (set (match_dup 3) (match_dup 4))] 1646 " 1647 { 1648 operands[4] = gen_highpart (SImode, operands[1]); 1649 operands[3] = gen_highpart (SImode, operands[0]); 1650 operands[0] = gen_lowpart (SImode, operands[0]); 1651 operands[1] = gen_lowpart (SImode, operands[1]); 1652 }" 1653) 1654 1655(define_insn "anddi3" 1656 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 1657 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r") 1658 (match_operand:DI 2 "s_register_operand" "r,r")))] 1659 "TARGET_ARM" 1660 "#" 1661 [(set_attr "length" "8")] 1662) 1663 1664(define_insn_and_split "*anddi_zesidi_di" 1665 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 1666 (and:DI (zero_extend:DI 1667 (match_operand:SI 2 "s_register_operand" "r,r")) 1668 (match_operand:DI 1 "s_register_operand" "?r,0")))] 1669 "TARGET_ARM" 1670 "#" 1671 "TARGET_ARM && reload_completed" 1672 ; The zero extend of operand 2 clears the high word of the output 1673 ; operand. 1674 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2))) 1675 (set (match_dup 3) (const_int 0))] 1676 " 1677 { 1678 operands[3] = gen_highpart (SImode, operands[0]); 1679 operands[0] = gen_lowpart (SImode, operands[0]); 1680 operands[1] = gen_lowpart (SImode, operands[1]); 1681 }" 1682 [(set_attr "length" "8")] 1683) 1684 1685(define_insn "*anddi_sesdi_di" 1686 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 1687 (and:DI (sign_extend:DI 1688 (match_operand:SI 2 "s_register_operand" "r,r")) 1689 (match_operand:DI 1 "s_register_operand" "?r,0")))] 1690 "TARGET_ARM" 1691 "#" 1692 [(set_attr "length" "8")] 1693) 1694 1695(define_expand "andsi3" 1696 [(set (match_operand:SI 0 "s_register_operand" "") 1697 (and:SI (match_operand:SI 1 "s_register_operand" "") 1698 (match_operand:SI 2 "reg_or_int_operand" "")))] 1699 "TARGET_EITHER" 1700 " 1701 if (TARGET_ARM) 1702 { 1703 if (GET_CODE (operands[2]) == CONST_INT) 1704 { 1705 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0], 1706 operands[1], 1707 (no_new_pseudos 1708 ? 0 : preserve_subexpressions_p ())); 1709 DONE; 1710 } 1711 } 1712 else /* TARGET_THUMB */ 1713 { 1714 if (GET_CODE (operands[2]) != CONST_INT) 1715 operands[2] = force_reg (SImode, operands[2]); 1716 else 1717 { 1718 int i; 1719 1720 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256) 1721 { 1722 operands[2] = force_reg (SImode, 1723 GEN_INT (~INTVAL (operands[2]))); 1724 1725 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1])); 1726 1727 DONE; 1728 } 1729 1730 for (i = 9; i <= 31; i++) 1731 { 1732 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2])) 1733 { 1734 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i), 1735 const0_rtx)); 1736 DONE; 1737 } 1738 else if ((((HOST_WIDE_INT) 1) << i) - 1 1739 == ~INTVAL (operands[2])) 1740 { 1741 rtx shift = GEN_INT (i); 1742 rtx reg = gen_reg_rtx (SImode); 1743 1744 emit_insn (gen_lshrsi3 (reg, operands[1], shift)); 1745 emit_insn (gen_ashlsi3 (operands[0], reg, shift)); 1746 1747 DONE; 1748 } 1749 } 1750 1751 operands[2] = force_reg (SImode, operands[2]); 1752 } 1753 } 1754 " 1755) 1756 1757(define_insn_and_split "*arm_andsi3_insn" 1758 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 1759 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r") 1760 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))] 1761 "TARGET_ARM" 1762 "@ 1763 and%?\\t%0, %1, %2 1764 bic%?\\t%0, %1, #%B2 1765 #" 1766 "TARGET_ARM 1767 && GET_CODE (operands[2]) == CONST_INT 1768 && !(const_ok_for_arm (INTVAL (operands[2])) 1769 || const_ok_for_arm (~INTVAL (operands[2])))" 1770 [(clobber (const_int 0))] 1771 " 1772 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0], 1773 operands[1], 0); 1774 DONE; 1775 " 1776 [(set_attr "length" "4,4,16") 1777 (set_attr "predicable" "yes")] 1778) 1779 1780(define_insn "*thumb_andsi3_insn" 1781 [(set (match_operand:SI 0 "register_operand" "=l") 1782 (and:SI (match_operand:SI 1 "register_operand" "%0") 1783 (match_operand:SI 2 "register_operand" "l")))] 1784 "TARGET_THUMB" 1785 "and\\t%0, %0, %2" 1786 [(set_attr "length" "2")] 1787) 1788 1789(define_insn "*andsi3_compare0" 1790 [(set (reg:CC_NOOV CC_REGNUM) 1791 (compare:CC_NOOV 1792 (and:SI (match_operand:SI 1 "s_register_operand" "r,r") 1793 (match_operand:SI 2 "arm_not_operand" "rI,K")) 1794 (const_int 0))) 1795 (set (match_operand:SI 0 "s_register_operand" "=r,r") 1796 (and:SI (match_dup 1) (match_dup 2)))] 1797 "TARGET_ARM" 1798 "@ 1799 and%?s\\t%0, %1, %2 1800 bic%?s\\t%0, %1, #%B2" 1801 [(set_attr "conds" "set")] 1802) 1803 1804(define_insn "*andsi3_compare0_scratch" 1805 [(set (reg:CC_NOOV CC_REGNUM) 1806 (compare:CC_NOOV 1807 (and:SI (match_operand:SI 0 "s_register_operand" "r,r") 1808 (match_operand:SI 1 "arm_not_operand" "rI,K")) 1809 (const_int 0))) 1810 (clobber (match_scratch:SI 2 "=X,r"))] 1811 "TARGET_ARM" 1812 "@ 1813 tst%?\\t%0, %1 1814 bic%?s\\t%2, %0, #%B1" 1815 [(set_attr "conds" "set")] 1816) 1817 1818(define_insn "*zeroextractsi_compare0_scratch" 1819 [(set (reg:CC_NOOV CC_REGNUM) 1820 (compare:CC_NOOV (zero_extract:SI 1821 (match_operand:SI 0 "s_register_operand" "r") 1822 (match_operand 1 "const_int_operand" "n") 1823 (match_operand 2 "const_int_operand" "n")) 1824 (const_int 0)))] 1825 "TARGET_ARM 1826 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32 1827 && INTVAL (operands[1]) > 0 1828 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8 1829 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)" 1830 "* 1831 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1) 1832 << INTVAL (operands[2])); 1833 output_asm_insn (\"tst%?\\t%0, %1\", operands); 1834 return \"\"; 1835 " 1836 [(set_attr "conds" "set")] 1837) 1838 1839(define_insn "*ne_zeroextractsi" 1840 [(set (match_operand:SI 0 "s_register_operand" "=r") 1841 (ne:SI (zero_extract:SI 1842 (match_operand:SI 1 "s_register_operand" "r") 1843 (match_operand:SI 2 "const_int_operand" "n") 1844 (match_operand:SI 3 "const_int_operand" "n")) 1845 (const_int 0))) 1846 (clobber (reg:CC CC_REGNUM))] 1847 "TARGET_ARM 1848 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32 1849 && INTVAL (operands[2]) > 0 1850 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8 1851 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)" 1852 "* 1853 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1) 1854 << INTVAL (operands[3])); 1855 output_asm_insn (\"ands\\t%0, %1, %2\", operands); 1856 return \"movne\\t%0, #1\"; 1857 " 1858 [(set_attr "conds" "clob") 1859 (set_attr "length" "8")] 1860) 1861 1862;;; ??? This pattern is bogus. If operand3 has bits outside the range 1863;;; represented by the bitfield, then this will produce incorrect results. 1864;;; Somewhere, the value needs to be truncated. On targets like the m68k, 1865;;; which have a real bit-field insert instruction, the truncation happens 1866;;; in the bit-field insert instruction itself. Since arm does not have a 1867;;; bit-field insert instruction, we would have to emit code here to truncate 1868;;; the value before we insert. This loses some of the advantage of having 1869;;; this insv pattern, so this pattern needs to be reevalutated. 1870 1871(define_expand "insv" 1872 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "") 1873 (match_operand:SI 1 "general_operand" "") 1874 (match_operand:SI 2 "general_operand" "")) 1875 (match_operand:SI 3 "reg_or_int_operand" ""))] 1876 "TARGET_ARM" 1877 " 1878 { 1879 int start_bit = INTVAL (operands[2]); 1880 int width = INTVAL (operands[1]); 1881 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1; 1882 rtx target, subtarget; 1883 1884 target = operands[0]; 1885 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 1886 subreg as the final target. */ 1887 if (GET_CODE (target) == SUBREG) 1888 { 1889 subtarget = gen_reg_rtx (SImode); 1890 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target))) 1891 < GET_MODE_SIZE (SImode)) 1892 target = SUBREG_REG (target); 1893 } 1894 else 1895 subtarget = target; 1896 1897 if (GET_CODE (operands[3]) == CONST_INT) 1898 { 1899 /* Since we are inserting a known constant, we may be able to 1900 reduce the number of bits that we have to clear so that 1901 the mask becomes simple. */ 1902 /* ??? This code does not check to see if the new mask is actually 1903 simpler. It may not be. */ 1904 rtx op1 = gen_reg_rtx (SImode); 1905 /* ??? Truncate operand3 to fit in the bitfield. See comment before 1906 start of this pattern. */ 1907 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]); 1908 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit); 1909 1910 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2))); 1911 emit_insn (gen_iorsi3 (subtarget, op1, 1912 GEN_INT (op3_value << start_bit))); 1913 } 1914 else if (start_bit == 0 1915 && !(const_ok_for_arm (mask) 1916 || const_ok_for_arm (~mask))) 1917 { 1918 /* A Trick, since we are setting the bottom bits in the word, 1919 we can shift operand[3] up, operand[0] down, OR them together 1920 and rotate the result back again. This takes 3 insns, and 1921 the third might be mergable into another op. */ 1922 /* The shift up copes with the possibility that operand[3] is 1923 wider than the bitfield. */ 1924 rtx op0 = gen_reg_rtx (SImode); 1925 rtx op1 = gen_reg_rtx (SImode); 1926 1927 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width))); 1928 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1])); 1929 emit_insn (gen_iorsi3 (op1, op1, op0)); 1930 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1])); 1931 } 1932 else if ((width + start_bit == 32) 1933 && !(const_ok_for_arm (mask) 1934 || const_ok_for_arm (~mask))) 1935 { 1936 /* Similar trick, but slightly less efficient. */ 1937 1938 rtx op0 = gen_reg_rtx (SImode); 1939 rtx op1 = gen_reg_rtx (SImode); 1940 1941 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width))); 1942 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1])); 1943 emit_insn (gen_lshrsi3 (op1, op1, operands[1])); 1944 emit_insn (gen_iorsi3 (subtarget, op1, op0)); 1945 } 1946 else 1947 { 1948 rtx op0 = GEN_INT (mask); 1949 rtx op1 = gen_reg_rtx (SImode); 1950 rtx op2 = gen_reg_rtx (SImode); 1951 1952 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask))) 1953 { 1954 rtx tmp = gen_reg_rtx (SImode); 1955 1956 emit_insn (gen_movsi (tmp, op0)); 1957 op0 = tmp; 1958 } 1959 1960 /* Mask out any bits in operand[3] that are not needed. */ 1961 emit_insn (gen_andsi3 (op1, operands[3], op0)); 1962 1963 if (GET_CODE (op0) == CONST_INT 1964 && (const_ok_for_arm (mask << start_bit) 1965 || const_ok_for_arm (~(mask << start_bit)))) 1966 { 1967 op0 = GEN_INT (~(mask << start_bit)); 1968 emit_insn (gen_andsi3 (op2, operands[0], op0)); 1969 } 1970 else 1971 { 1972 if (GET_CODE (op0) == CONST_INT) 1973 { 1974 rtx tmp = gen_reg_rtx (SImode); 1975 1976 emit_insn (gen_movsi (tmp, op0)); 1977 op0 = tmp; 1978 } 1979 1980 if (start_bit != 0) 1981 emit_insn (gen_ashlsi3 (op0, op0, operands[2])); 1982 1983 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0)); 1984 } 1985 1986 if (start_bit != 0) 1987 emit_insn (gen_ashlsi3 (op1, op1, operands[2])); 1988 1989 emit_insn (gen_iorsi3 (subtarget, op1, op2)); 1990 } 1991 1992 if (subtarget != target) 1993 { 1994 /* If TARGET is still a SUBREG, then it must be wider than a word, 1995 so we must be careful only to set the subword we were asked to. */ 1996 if (GET_CODE (target) == SUBREG) 1997 emit_move_insn (target, subtarget); 1998 else 1999 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget)); 2000 } 2001 2002 DONE; 2003 }" 2004) 2005 2006; constants for op 2 will never be given to these patterns. 2007(define_insn_and_split "*anddi_notdi_di" 2008 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 2009 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0")) 2010 (match_operand:DI 2 "s_register_operand" "0,r")))] 2011 "TARGET_ARM" 2012 "#" 2013 "TARGET_ARM && reload_completed" 2014 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2))) 2015 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))] 2016 " 2017 { 2018 operands[3] = gen_highpart (SImode, operands[0]); 2019 operands[0] = gen_lowpart (SImode, operands[0]); 2020 operands[4] = gen_highpart (SImode, operands[1]); 2021 operands[1] = gen_lowpart (SImode, operands[1]); 2022 operands[5] = gen_highpart (SImode, operands[2]); 2023 operands[2] = gen_lowpart (SImode, operands[2]); 2024 }" 2025 [(set_attr "length" "8") 2026 (set_attr "predicable" "yes")] 2027) 2028 2029(define_insn_and_split "*anddi_notzesidi_di" 2030 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 2031 (and:DI (not:DI (zero_extend:DI 2032 (match_operand:SI 2 "s_register_operand" "r,r"))) 2033 (match_operand:DI 1 "s_register_operand" "0,?r")))] 2034 "TARGET_ARM" 2035 "@ 2036 bic%?\\t%Q0, %Q1, %2 2037 #" 2038 ; (not (zero_extend ...)) allows us to just copy the high word from 2039 ; operand1 to operand0. 2040 "TARGET_ARM 2041 && reload_completed 2042 && operands[0] != operands[1]" 2043 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1))) 2044 (set (match_dup 3) (match_dup 4))] 2045 " 2046 { 2047 operands[3] = gen_highpart (SImode, operands[0]); 2048 operands[0] = gen_lowpart (SImode, operands[0]); 2049 operands[4] = gen_highpart (SImode, operands[1]); 2050 operands[1] = gen_lowpart (SImode, operands[1]); 2051 }" 2052 [(set_attr "length" "4,8") 2053 (set_attr "predicable" "yes")] 2054) 2055 2056(define_insn_and_split "*anddi_notsesidi_di" 2057 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 2058 (and:DI (not:DI (sign_extend:DI 2059 (match_operand:SI 2 "s_register_operand" "r,r"))) 2060 (match_operand:DI 1 "s_register_operand" "0,r")))] 2061 "TARGET_ARM" 2062 "#" 2063 "TARGET_ARM && reload_completed" 2064 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1))) 2065 (set (match_dup 3) (and:SI (not:SI 2066 (ashiftrt:SI (match_dup 2) (const_int 31))) 2067 (match_dup 4)))] 2068 " 2069 { 2070 operands[3] = gen_highpart (SImode, operands[0]); 2071 operands[0] = gen_lowpart (SImode, operands[0]); 2072 operands[4] = gen_highpart (SImode, operands[1]); 2073 operands[1] = gen_lowpart (SImode, operands[1]); 2074 }" 2075 [(set_attr "length" "8") 2076 (set_attr "predicable" "yes")] 2077) 2078 2079(define_insn "andsi_notsi_si" 2080 [(set (match_operand:SI 0 "s_register_operand" "=r") 2081 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) 2082 (match_operand:SI 1 "s_register_operand" "r")))] 2083 "TARGET_ARM" 2084 "bic%?\\t%0, %1, %2" 2085 [(set_attr "predicable" "yes")] 2086) 2087 2088(define_insn "bicsi3" 2089 [(set (match_operand:SI 0 "register_operand" "=l") 2090 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l")) 2091 (match_operand:SI 2 "register_operand" "0")))] 2092 "TARGET_THUMB" 2093 "bic\\t%0, %0, %1" 2094 [(set_attr "length" "2")] 2095) 2096 2097(define_insn "andsi_not_shiftsi_si" 2098 [(set (match_operand:SI 0 "s_register_operand" "=r") 2099 (and:SI (not:SI (match_operator:SI 4 "shift_operator" 2100 [(match_operand:SI 2 "s_register_operand" "r") 2101 (match_operand:SI 3 "arm_rhs_operand" "rM")])) 2102 (match_operand:SI 1 "s_register_operand" "r")))] 2103 "TARGET_ARM" 2104 "bic%?\\t%0, %1, %2%S4" 2105 [(set_attr "predicable" "yes") 2106 (set_attr "shift" "2") 2107 ] 2108) 2109 2110(define_insn "*andsi_notsi_si_compare0" 2111 [(set (reg:CC_NOOV CC_REGNUM) 2112 (compare:CC_NOOV 2113 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) 2114 (match_operand:SI 1 "s_register_operand" "r")) 2115 (const_int 0))) 2116 (set (match_operand:SI 0 "s_register_operand" "=r") 2117 (and:SI (not:SI (match_dup 2)) (match_dup 1)))] 2118 "TARGET_ARM" 2119 "bic%?s\\t%0, %1, %2" 2120 [(set_attr "conds" "set")] 2121) 2122 2123(define_insn "*andsi_notsi_si_compare0_scratch" 2124 [(set (reg:CC_NOOV CC_REGNUM) 2125 (compare:CC_NOOV 2126 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) 2127 (match_operand:SI 1 "s_register_operand" "r")) 2128 (const_int 0))) 2129 (clobber (match_scratch:SI 0 "=r"))] 2130 "TARGET_ARM" 2131 "bic%?s\\t%0, %1, %2" 2132 [(set_attr "conds" "set")] 2133) 2134 2135(define_insn "iordi3" 2136 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 2137 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r") 2138 (match_operand:DI 2 "s_register_operand" "r,r")))] 2139 "TARGET_ARM" 2140 "#" 2141 [(set_attr "length" "8") 2142 (set_attr "predicable" "yes")] 2143) 2144 2145(define_insn "*iordi_zesidi_di" 2146 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 2147 (ior:DI (zero_extend:DI 2148 (match_operand:SI 2 "s_register_operand" "r,r")) 2149 (match_operand:DI 1 "s_register_operand" "0,?r")))] 2150 "TARGET_ARM" 2151 "@ 2152 orr%?\\t%Q0, %Q1, %2 2153 #" 2154 [(set_attr "length" "4,8") 2155 (set_attr "predicable" "yes")] 2156) 2157 2158(define_insn "*iordi_sesidi_di" 2159 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 2160 (ior:DI (sign_extend:DI 2161 (match_operand:SI 2 "s_register_operand" "r,r")) 2162 (match_operand:DI 1 "s_register_operand" "?r,0")))] 2163 "TARGET_ARM" 2164 "#" 2165 [(set_attr "length" "8") 2166 (set_attr "predicable" "yes")] 2167) 2168 2169(define_expand "iorsi3" 2170 [(set (match_operand:SI 0 "s_register_operand" "") 2171 (ior:SI (match_operand:SI 1 "s_register_operand" "") 2172 (match_operand:SI 2 "reg_or_int_operand" "")))] 2173 "TARGET_EITHER" 2174 " 2175 if (GET_CODE (operands[2]) == CONST_INT) 2176 { 2177 if (TARGET_ARM) 2178 { 2179 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0], 2180 operands[1], 2181 (no_new_pseudos 2182 ? 0 : preserve_subexpressions_p ())); 2183 DONE; 2184 } 2185 else /* TARGET_THUMB */ 2186 operands [2] = force_reg (SImode, operands [2]); 2187 } 2188 " 2189) 2190 2191(define_insn_and_split "*arm_iorsi3" 2192 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 2193 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r") 2194 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))] 2195 "TARGET_ARM" 2196 "@ 2197 orr%?\\t%0, %1, %2 2198 #" 2199 "TARGET_ARM 2200 && GET_CODE (operands[2]) == CONST_INT 2201 && !const_ok_for_arm (INTVAL (operands[2]))" 2202 [(clobber (const_int 0))] 2203 " 2204 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0], 2205 operands[1], 0); 2206 DONE; 2207 " 2208 [(set_attr "length" "4,16") 2209 (set_attr "predicable" "yes")] 2210) 2211 2212(define_insn "*thumb_iorsi3" 2213 [(set (match_operand:SI 0 "register_operand" "=l") 2214 (ior:SI (match_operand:SI 1 "register_operand" "%0") 2215 (match_operand:SI 2 "register_operand" "l")))] 2216 "TARGET_THUMB" 2217 "orr\\t%0, %0, %2" 2218 [(set_attr "length" "2")] 2219) 2220 2221(define_peephole2 2222 [(match_scratch:SI 3 "r") 2223 (set (match_operand:SI 0 "s_register_operand" "") 2224 (ior:SI (match_operand:SI 1 "s_register_operand" "") 2225 (match_operand:SI 2 "const_int_operand" "")))] 2226 "TARGET_ARM 2227 && !const_ok_for_arm (INTVAL (operands[2])) 2228 && const_ok_for_arm (~INTVAL (operands[2]))" 2229 [(set (match_dup 3) (match_dup 2)) 2230 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))] 2231 "" 2232) 2233 2234(define_insn "*iorsi3_compare0" 2235 [(set (reg:CC_NOOV CC_REGNUM) 2236 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r") 2237 (match_operand:SI 2 "arm_rhs_operand" "rI")) 2238 (const_int 0))) 2239 (set (match_operand:SI 0 "s_register_operand" "=r") 2240 (ior:SI (match_dup 1) (match_dup 2)))] 2241 "TARGET_ARM" 2242 "orr%?s\\t%0, %1, %2" 2243 [(set_attr "conds" "set")] 2244) 2245 2246(define_insn "*iorsi3_compare0_scratch" 2247 [(set (reg:CC_NOOV CC_REGNUM) 2248 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r") 2249 (match_operand:SI 2 "arm_rhs_operand" "rI")) 2250 (const_int 0))) 2251 (clobber (match_scratch:SI 0 "=r"))] 2252 "TARGET_ARM" 2253 "orr%?s\\t%0, %1, %2" 2254 [(set_attr "conds" "set")] 2255) 2256 2257(define_insn "xordi3" 2258 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 2259 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r") 2260 (match_operand:DI 2 "s_register_operand" "r,r")))] 2261 "TARGET_ARM" 2262 "#" 2263 [(set_attr "length" "8") 2264 (set_attr "predicable" "yes")] 2265) 2266 2267(define_insn "*xordi_zesidi_di" 2268 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 2269 (xor:DI (zero_extend:DI 2270 (match_operand:SI 2 "s_register_operand" "r,r")) 2271 (match_operand:DI 1 "s_register_operand" "0,?r")))] 2272 "TARGET_ARM" 2273 "@ 2274 eor%?\\t%Q0, %Q1, %2 2275 #" 2276 [(set_attr "length" "4,8") 2277 (set_attr "predicable" "yes")] 2278) 2279 2280(define_insn "*xordi_sesidi_di" 2281 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 2282 (xor:DI (sign_extend:DI 2283 (match_operand:SI 2 "s_register_operand" "r,r")) 2284 (match_operand:DI 1 "s_register_operand" "?r,0")))] 2285 "TARGET_ARM" 2286 "#" 2287 [(set_attr "length" "8") 2288 (set_attr "predicable" "yes")] 2289) 2290 2291(define_expand "xorsi3" 2292 [(set (match_operand:SI 0 "s_register_operand" "") 2293 (xor:SI (match_operand:SI 1 "s_register_operand" "") 2294 (match_operand:SI 2 "arm_rhs_operand" "")))] 2295 "TARGET_EITHER" 2296 "if (TARGET_THUMB) 2297 if (GET_CODE (operands[2]) == CONST_INT) 2298 operands[2] = force_reg (SImode, operands[2]); 2299 " 2300) 2301 2302(define_insn "*arm_xorsi3" 2303 [(set (match_operand:SI 0 "s_register_operand" "=r") 2304 (xor:SI (match_operand:SI 1 "s_register_operand" "r") 2305 (match_operand:SI 2 "arm_rhs_operand" "rI")))] 2306 "TARGET_ARM" 2307 "eor%?\\t%0, %1, %2" 2308 [(set_attr "predicable" "yes")] 2309) 2310 2311(define_insn "*thumb_xorsi3" 2312 [(set (match_operand:SI 0 "register_operand" "=l") 2313 (xor:SI (match_operand:SI 1 "register_operand" "%0") 2314 (match_operand:SI 2 "register_operand" "l")))] 2315 "TARGET_THUMB" 2316 "eor\\t%0, %0, %2" 2317 [(set_attr "length" "2")] 2318) 2319 2320(define_insn "*xorsi3_compare0" 2321 [(set (reg:CC_NOOV CC_REGNUM) 2322 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r") 2323 (match_operand:SI 2 "arm_rhs_operand" "rI")) 2324 (const_int 0))) 2325 (set (match_operand:SI 0 "s_register_operand" "=r") 2326 (xor:SI (match_dup 1) (match_dup 2)))] 2327 "TARGET_ARM" 2328 "eor%?s\\t%0, %1, %2" 2329 [(set_attr "conds" "set")] 2330) 2331 2332(define_insn "*xorsi3_compare0_scratch" 2333 [(set (reg:CC_NOOV CC_REGNUM) 2334 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r") 2335 (match_operand:SI 1 "arm_rhs_operand" "rI")) 2336 (const_int 0)))] 2337 "TARGET_ARM" 2338 "teq%?\\t%0, %1" 2339 [(set_attr "conds" "set")] 2340) 2341 2342; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 2343; (NOT D) we can sometimes merge the final NOT into one of the following 2344; insns. 2345 2346(define_split 2347 [(set (match_operand:SI 0 "s_register_operand" "") 2348 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "")) 2349 (not:SI (match_operand:SI 2 "arm_rhs_operand" ""))) 2350 (match_operand:SI 3 "arm_rhs_operand" ""))) 2351 (clobber (match_operand:SI 4 "s_register_operand" ""))] 2352 "TARGET_ARM" 2353 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2)) 2354 (not:SI (match_dup 3)))) 2355 (set (match_dup 0) (not:SI (match_dup 4)))] 2356 "" 2357) 2358 2359(define_insn "*andsi_iorsi3_notsi" 2360 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r") 2361 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0") 2362 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")) 2363 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))] 2364 "TARGET_ARM" 2365 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3" 2366 [(set_attr "length" "8") 2367 (set_attr "predicable" "yes")] 2368) 2369 2370 2371 2372;; Minimum and maximum insns 2373 2374(define_insn "smaxsi3" 2375 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 2376 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") 2377 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 2378 (clobber (reg:CC CC_REGNUM))] 2379 "TARGET_ARM" 2380 "@ 2381 cmp\\t%1, %2\;movlt\\t%0, %2 2382 cmp\\t%1, %2\;movge\\t%0, %1 2383 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2" 2384 [(set_attr "conds" "clob") 2385 (set_attr "length" "8,8,12")] 2386) 2387 2388(define_insn "sminsi3" 2389 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 2390 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") 2391 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 2392 (clobber (reg:CC CC_REGNUM))] 2393 "TARGET_ARM" 2394 "@ 2395 cmp\\t%1, %2\;movge\\t%0, %2 2396 cmp\\t%1, %2\;movlt\\t%0, %1 2397 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2" 2398 [(set_attr "conds" "clob") 2399 (set_attr "length" "8,8,12")] 2400) 2401 2402(define_insn "umaxsi3" 2403 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 2404 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") 2405 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 2406 (clobber (reg:CC CC_REGNUM))] 2407 "TARGET_ARM" 2408 "@ 2409 cmp\\t%1, %2\;movcc\\t%0, %2 2410 cmp\\t%1, %2\;movcs\\t%0, %1 2411 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2" 2412 [(set_attr "conds" "clob") 2413 (set_attr "length" "8,8,12")] 2414) 2415 2416(define_insn "uminsi3" 2417 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 2418 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") 2419 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 2420 (clobber (reg:CC CC_REGNUM))] 2421 "TARGET_ARM" 2422 "@ 2423 cmp\\t%1, %2\;movcs\\t%0, %2 2424 cmp\\t%1, %2\;movcc\\t%0, %1 2425 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2" 2426 [(set_attr "conds" "clob") 2427 (set_attr "length" "8,8,12")] 2428) 2429 2430(define_insn "*store_minmaxsi" 2431 [(set (match_operand:SI 0 "memory_operand" "=m") 2432 (match_operator:SI 3 "minmax_operator" 2433 [(match_operand:SI 1 "s_register_operand" "r") 2434 (match_operand:SI 2 "s_register_operand" "r")])) 2435 (clobber (reg:CC CC_REGNUM))] 2436 "TARGET_ARM" 2437 "* 2438 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1], 2439 operands[2]); 2440 output_asm_insn (\"cmp\\t%1, %2\", operands); 2441 output_asm_insn (\"str%d3\\t%1, %0\", operands); 2442 output_asm_insn (\"str%D3\\t%2, %0\", operands); 2443 return \"\"; 2444 " 2445 [(set_attr "conds" "clob") 2446 (set_attr "length" "12") 2447 (set_attr "type" "store1")] 2448) 2449 2450; Reject the frame pointer in operand[1], since reloading this after 2451; it has been eliminated can cause carnage. 2452(define_insn "*minmax_arithsi" 2453 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 2454 (match_operator:SI 4 "shiftable_operator" 2455 [(match_operator:SI 5 "minmax_operator" 2456 [(match_operand:SI 2 "s_register_operand" "r,r") 2457 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) 2458 (match_operand:SI 1 "s_register_operand" "0,?r")])) 2459 (clobber (reg:CC CC_REGNUM))] 2460 "TARGET_ARM 2461 && (GET_CODE (operands[1]) != REG 2462 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM 2463 && REGNO(operands[1]) != ARG_POINTER_REGNUM))" 2464 "* 2465 { 2466 enum rtx_code code = GET_CODE (operands[4]); 2467 2468 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2], 2469 operands[3]); 2470 output_asm_insn (\"cmp\\t%2, %3\", operands); 2471 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands); 2472 if (which_alternative != 0 || operands[3] != const0_rtx 2473 || (code != PLUS && code != MINUS && code != IOR && code != XOR)) 2474 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands); 2475 return \"\"; 2476 }" 2477 [(set_attr "conds" "clob") 2478 (set_attr "length" "12")] 2479) 2480 2481 2482;; Shift and rotation insns 2483 2484(define_expand "ashlsi3" 2485 [(set (match_operand:SI 0 "s_register_operand" "") 2486 (ashift:SI (match_operand:SI 1 "s_register_operand" "") 2487 (match_operand:SI 2 "arm_rhs_operand" "")))] 2488 "TARGET_EITHER" 2489 " 2490 if (GET_CODE (operands[2]) == CONST_INT 2491 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) 2492 { 2493 emit_insn (gen_movsi (operands[0], const0_rtx)); 2494 DONE; 2495 } 2496 " 2497) 2498 2499(define_insn "*thumb_ashlsi3" 2500 [(set (match_operand:SI 0 "register_operand" "=l,l") 2501 (ashift:SI (match_operand:SI 1 "register_operand" "l,0") 2502 (match_operand:SI 2 "nonmemory_operand" "N,l")))] 2503 "TARGET_THUMB" 2504 "lsl\\t%0, %1, %2" 2505 [(set_attr "length" "2")] 2506) 2507 2508(define_expand "ashrsi3" 2509 [(set (match_operand:SI 0 "s_register_operand" "") 2510 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "") 2511 (match_operand:SI 2 "arm_rhs_operand" "")))] 2512 "TARGET_EITHER" 2513 " 2514 if (GET_CODE (operands[2]) == CONST_INT 2515 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) 2516 operands[2] = GEN_INT (31); 2517 " 2518) 2519 2520(define_insn "*thumb_ashrsi3" 2521 [(set (match_operand:SI 0 "register_operand" "=l,l") 2522 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0") 2523 (match_operand:SI 2 "nonmemory_operand" "N,l")))] 2524 "TARGET_THUMB" 2525 "asr\\t%0, %1, %2" 2526 [(set_attr "length" "2")] 2527) 2528 2529(define_expand "lshrsi3" 2530 [(set (match_operand:SI 0 "s_register_operand" "") 2531 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "") 2532 (match_operand:SI 2 "arm_rhs_operand" "")))] 2533 "TARGET_EITHER" 2534 " 2535 if (GET_CODE (operands[2]) == CONST_INT 2536 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) 2537 { 2538 emit_insn (gen_movsi (operands[0], const0_rtx)); 2539 DONE; 2540 } 2541 " 2542) 2543 2544(define_insn "*thumb_lshrsi3" 2545 [(set (match_operand:SI 0 "register_operand" "=l,l") 2546 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0") 2547 (match_operand:SI 2 "nonmemory_operand" "N,l")))] 2548 "TARGET_THUMB" 2549 "lsr\\t%0, %1, %2" 2550 [(set_attr "length" "2")] 2551) 2552 2553(define_expand "rotlsi3" 2554 [(set (match_operand:SI 0 "s_register_operand" "") 2555 (rotatert:SI (match_operand:SI 1 "s_register_operand" "") 2556 (match_operand:SI 2 "reg_or_int_operand" "")))] 2557 "TARGET_ARM" 2558 " 2559 if (GET_CODE (operands[2]) == CONST_INT) 2560 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32); 2561 else 2562 { 2563 rtx reg = gen_reg_rtx (SImode); 2564 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2])); 2565 operands[2] = reg; 2566 } 2567 " 2568) 2569 2570(define_expand "rotrsi3" 2571 [(set (match_operand:SI 0 "s_register_operand" "") 2572 (rotatert:SI (match_operand:SI 1 "s_register_operand" "") 2573 (match_operand:SI 2 "arm_rhs_operand" "")))] 2574 "TARGET_EITHER" 2575 " 2576 if (TARGET_ARM) 2577 { 2578 if (GET_CODE (operands[2]) == CONST_INT 2579 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) 2580 operands[2] = GEN_INT (INTVAL (operands[2]) % 32); 2581 } 2582 else /* TARGET_THUMB */ 2583 { 2584 if (GET_CODE (operands [2]) == CONST_INT) 2585 operands [2] = force_reg (SImode, operands[2]); 2586 } 2587 " 2588) 2589 2590(define_insn "*thumb_rotrsi3" 2591 [(set (match_operand:SI 0 "register_operand" "=l") 2592 (rotatert:SI (match_operand:SI 1 "register_operand" "0") 2593 (match_operand:SI 2 "register_operand" "l")))] 2594 "TARGET_THUMB" 2595 "ror\\t%0, %0, %2" 2596 [(set_attr "length" "2")] 2597) 2598 2599(define_insn "*arm_shiftsi3" 2600 [(set (match_operand:SI 0 "s_register_operand" "=r") 2601 (match_operator:SI 3 "shift_operator" 2602 [(match_operand:SI 1 "s_register_operand" "r") 2603 (match_operand:SI 2 "reg_or_int_operand" "rM")]))] 2604 "TARGET_ARM" 2605 "mov%?\\t%0, %1%S3" 2606 [(set_attr "predicable" "yes") 2607 (set_attr "shift" "1") 2608 ] 2609) 2610 2611(define_insn "*shiftsi3_compare0" 2612 [(set (reg:CC_NOOV CC_REGNUM) 2613 (compare:CC_NOOV (match_operator:SI 3 "shift_operator" 2614 [(match_operand:SI 1 "s_register_operand" "r") 2615 (match_operand:SI 2 "arm_rhs_operand" "rM")]) 2616 (const_int 0))) 2617 (set (match_operand:SI 0 "s_register_operand" "=r") 2618 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))] 2619 "TARGET_ARM" 2620 "mov%?s\\t%0, %1%S3" 2621 [(set_attr "conds" "set") 2622 (set_attr "shift" "1") 2623 ] 2624) 2625 2626(define_insn "*shiftsi3_compare0_scratch" 2627 [(set (reg:CC_NOOV CC_REGNUM) 2628 (compare:CC_NOOV (match_operator:SI 3 "shift_operator" 2629 [(match_operand:SI 1 "s_register_operand" "r") 2630 (match_operand:SI 2 "arm_rhs_operand" "rM")]) 2631 (const_int 0))) 2632 (clobber (match_scratch:SI 0 "=r"))] 2633 "TARGET_ARM" 2634 "mov%?s\\t%0, %1%S3" 2635 [(set_attr "conds" "set") 2636 (set_attr "shift" "1") 2637 ] 2638) 2639 2640(define_insn "*notsi_shiftsi" 2641 [(set (match_operand:SI 0 "s_register_operand" "=r") 2642 (not:SI (match_operator:SI 3 "shift_operator" 2643 [(match_operand:SI 1 "s_register_operand" "r") 2644 (match_operand:SI 2 "arm_rhs_operand" "rM")])))] 2645 "TARGET_ARM" 2646 "mvn%?\\t%0, %1%S3" 2647 [(set_attr "predicable" "yes") 2648 (set_attr "shift" "1") 2649 ] 2650) 2651 2652(define_insn "*notsi_shiftsi_compare0" 2653 [(set (reg:CC_NOOV CC_REGNUM) 2654 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator" 2655 [(match_operand:SI 1 "s_register_operand" "r") 2656 (match_operand:SI 2 "arm_rhs_operand" "rM")])) 2657 (const_int 0))) 2658 (set (match_operand:SI 0 "s_register_operand" "=r") 2659 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))] 2660 "TARGET_ARM" 2661 "mvn%?s\\t%0, %1%S3" 2662 [(set_attr "conds" "set") 2663 (set_attr "shift" "1") 2664 ] 2665) 2666 2667(define_insn "*not_shiftsi_compare0_scratch" 2668 [(set (reg:CC_NOOV CC_REGNUM) 2669 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator" 2670 [(match_operand:SI 1 "s_register_operand" "r") 2671 (match_operand:SI 2 "arm_rhs_operand" "rM")])) 2672 (const_int 0))) 2673 (clobber (match_scratch:SI 0 "=r"))] 2674 "TARGET_ARM" 2675 "mvn%?s\\t%0, %1%S3" 2676 [(set_attr "conds" "set") 2677 (set_attr "shift" "1") 2678 ] 2679) 2680 2681;; We don't really have extzv, but defining this using shifts helps 2682;; to reduce register pressure later on. 2683 2684(define_expand "extzv" 2685 [(set (match_dup 4) 2686 (ashift:SI (match_operand:SI 1 "register_operand" "") 2687 (match_operand:SI 2 "const_int_operand" ""))) 2688 (set (match_operand:SI 0 "register_operand" "") 2689 (lshiftrt:SI (match_dup 4) 2690 (match_operand:SI 3 "const_int_operand" "")))] 2691 "TARGET_THUMB" 2692 " 2693 { 2694 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]); 2695 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]); 2696 2697 operands[3] = GEN_INT (rshift); 2698 2699 if (lshift == 0) 2700 { 2701 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3])); 2702 DONE; 2703 } 2704 2705 operands[2] = GEN_INT (lshift); 2706 operands[4] = gen_reg_rtx (SImode); 2707 }" 2708) 2709 2710 2711;; Unary arithmetic insns 2712 2713(define_expand "negdi2" 2714 [(parallel 2715 [(set (match_operand:DI 0 "s_register_operand" "") 2716 (neg:DI (match_operand:DI 1 "s_register_operand" ""))) 2717 (clobber (reg:CC CC_REGNUM))])] 2718 "TARGET_EITHER" 2719 " 2720 if (TARGET_THUMB) 2721 { 2722 if (GET_CODE (operands[1]) != REG) 2723 operands[1] = force_reg (SImode, operands[1]); 2724 } 2725 " 2726) 2727 2728;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1). 2729;; The second alternative is to allow the common case of a *full* overlap. 2730(define_insn "*arm_negdi2" 2731 [(set (match_operand:DI 0 "s_register_operand" "=&r,r") 2732 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0"))) 2733 (clobber (reg:CC CC_REGNUM))] 2734 "TARGET_ARM" 2735 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0" 2736 [(set_attr "conds" "clob") 2737 (set_attr "length" "8")] 2738) 2739 2740(define_insn "*thumb_negdi2" 2741 [(set (match_operand:DI 0 "register_operand" "=&l") 2742 (neg:DI (match_operand:DI 1 "register_operand" "l"))) 2743 (clobber (reg:CC CC_REGNUM))] 2744 "TARGET_THUMB" 2745 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1" 2746 [(set_attr "length" "6")] 2747) 2748 2749(define_expand "negsi2" 2750 [(set (match_operand:SI 0 "s_register_operand" "") 2751 (neg:SI (match_operand:SI 1 "s_register_operand" "")))] 2752 "TARGET_EITHER" 2753 "" 2754) 2755 2756(define_insn "*arm_negsi2" 2757 [(set (match_operand:SI 0 "s_register_operand" "=r") 2758 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))] 2759 "TARGET_ARM" 2760 "rsb%?\\t%0, %1, #0" 2761 [(set_attr "predicable" "yes")] 2762) 2763 2764(define_insn "*thumb_negsi2" 2765 [(set (match_operand:SI 0 "register_operand" "=l") 2766 (neg:SI (match_operand:SI 1 "register_operand" "l")))] 2767 "TARGET_THUMB" 2768 "neg\\t%0, %1" 2769 [(set_attr "length" "2")] 2770) 2771 2772(define_insn "negsf2" 2773 [(set (match_operand:SF 0 "s_register_operand" "=f") 2774 (neg:SF (match_operand:SF 1 "s_register_operand" "f")))] 2775 "TARGET_ARM && TARGET_HARD_FLOAT" 2776 "mnf%?s\\t%0, %1" 2777 [(set_attr "type" "ffarith") 2778 (set_attr "predicable" "yes")] 2779) 2780 2781(define_insn "negdf2" 2782 [(set (match_operand:DF 0 "s_register_operand" "=f") 2783 (neg:DF (match_operand:DF 1 "s_register_operand" "f")))] 2784 "TARGET_ARM && TARGET_HARD_FLOAT" 2785 "mnf%?d\\t%0, %1" 2786 [(set_attr "type" "ffarith") 2787 (set_attr "predicable" "yes")] 2788) 2789 2790(define_insn "*negdf_esfdf" 2791 [(set (match_operand:DF 0 "s_register_operand" "=f") 2792 (neg:DF (float_extend:DF 2793 (match_operand:SF 1 "s_register_operand" "f"))))] 2794 "TARGET_ARM && TARGET_HARD_FLOAT" 2795 "mnf%?d\\t%0, %1" 2796 [(set_attr "type" "ffarith") 2797 (set_attr "predicable" "yes")] 2798) 2799 2800(define_insn "negxf2" 2801 [(set (match_operand:XF 0 "s_register_operand" "=f") 2802 (neg:XF (match_operand:XF 1 "s_register_operand" "f")))] 2803 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 2804 "mnf%?e\\t%0, %1" 2805 [(set_attr "type" "ffarith") 2806 (set_attr "predicable" "yes")] 2807) 2808 2809;; abssi2 doesn't really clobber the condition codes if a different register 2810;; is being set. To keep things simple, assume during rtl manipulations that 2811;; it does, but tell the final scan operator the truth. Similarly for 2812;; (neg (abs...)) 2813 2814(define_insn "abssi2" 2815 [(set (match_operand:SI 0 "s_register_operand" "=r,&r") 2816 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))) 2817 (clobber (reg:CC CC_REGNUM))] 2818 "TARGET_ARM" 2819 "@ 2820 cmp\\t%0, #0\;rsblt\\t%0, %0, #0 2821 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31" 2822 [(set_attr "conds" "clob,*") 2823 (set_attr "shift" "1") 2824 ;; predicable can't be set based on the variant, so left as no 2825 (set_attr "length" "8")] 2826) 2827 2828(define_insn "*neg_abssi2" 2829 [(set (match_operand:SI 0 "s_register_operand" "=r,&r") 2830 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))) 2831 (clobber (reg:CC CC_REGNUM))] 2832 "TARGET_ARM" 2833 "@ 2834 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0 2835 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31" 2836 [(set_attr "conds" "clob,*") 2837 (set_attr "shift" "1") 2838 ;; predicable can't be set based on the variant, so left as no 2839 (set_attr "length" "8")] 2840) 2841 2842(define_insn "abssf2" 2843 [(set (match_operand:SF 0 "s_register_operand" "=f") 2844 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))] 2845 "TARGET_ARM && TARGET_HARD_FLOAT" 2846 "abs%?s\\t%0, %1" 2847 [(set_attr "type" "ffarith") 2848 (set_attr "predicable" "yes")] 2849) 2850 2851(define_insn "absdf2" 2852 [(set (match_operand:DF 0 "s_register_operand" "=f") 2853 (abs:DF (match_operand:DF 1 "s_register_operand" "f")))] 2854 "TARGET_ARM && TARGET_HARD_FLOAT" 2855 "abs%?d\\t%0, %1" 2856 [(set_attr "type" "ffarith") 2857 (set_attr "predicable" "yes")] 2858) 2859 2860(define_insn "*absdf_esfdf" 2861 [(set (match_operand:DF 0 "s_register_operand" "=f") 2862 (abs:DF (float_extend:DF 2863 (match_operand:SF 1 "s_register_operand" "f"))))] 2864 "TARGET_ARM && TARGET_HARD_FLOAT" 2865 "abs%?d\\t%0, %1" 2866 [(set_attr "type" "ffarith") 2867 (set_attr "predicable" "yes")] 2868) 2869 2870(define_insn "absxf2" 2871 [(set (match_operand:XF 0 "s_register_operand" "=f") 2872 (abs:XF (match_operand:XF 1 "s_register_operand" "f")))] 2873 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 2874 "abs%?e\\t%0, %1" 2875 [(set_attr "type" "ffarith") 2876 (set_attr "predicable" "yes")] 2877) 2878 2879(define_insn "sqrtsf2" 2880 [(set (match_operand:SF 0 "s_register_operand" "=f") 2881 (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))] 2882 "TARGET_ARM && TARGET_HARD_FLOAT" 2883 "sqt%?s\\t%0, %1" 2884 [(set_attr "type" "float_em") 2885 (set_attr "predicable" "yes")] 2886) 2887 2888(define_insn "sqrtdf2" 2889 [(set (match_operand:DF 0 "s_register_operand" "=f") 2890 (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))] 2891 "TARGET_ARM && TARGET_HARD_FLOAT" 2892 "sqt%?d\\t%0, %1" 2893 [(set_attr "type" "float_em") 2894 (set_attr "predicable" "yes")] 2895) 2896 2897(define_insn "*sqrtdf_esfdf" 2898 [(set (match_operand:DF 0 "s_register_operand" "=f") 2899 (sqrt:DF (float_extend:DF 2900 (match_operand:SF 1 "s_register_operand" "f"))))] 2901 "TARGET_ARM && TARGET_HARD_FLOAT" 2902 "sqt%?d\\t%0, %1" 2903 [(set_attr "type" "float_em") 2904 (set_attr "predicable" "yes")] 2905) 2906 2907(define_insn "sqrtxf2" 2908 [(set (match_operand:XF 0 "s_register_operand" "=f") 2909 (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))] 2910 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 2911 "sqt%?e\\t%0, %1" 2912 [(set_attr "type" "float_em") 2913 (set_attr "predicable" "yes")] 2914) 2915 2916;; SIN COS TAN and family are always emulated, so it's probably better 2917;; to always call a library function. 2918;(define_insn "sinsf2" 2919; [(set (match_operand:SF 0 "s_register_operand" "=f") 2920; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 2921; UNSPEC_SIN))] 2922; "TARGET_ARM && TARGET_HARD_FLOAT" 2923; "sin%?s\\t%0, %1" 2924;[(set_attr "type" "float_em")]) 2925; 2926;(define_insn "sindf2" 2927; [(set (match_operand:DF 0 "s_register_operand" "=f") 2928; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 2929; UNSPEC_SIN))] 2930; "TARGET_ARM && TARGET_HARD_FLOAT" 2931; "sin%?d\\t%0, %1" 2932;[(set_attr "type" "float_em")]) 2933; 2934;(define_insn "*sindf_esfdf" 2935; [(set (match_operand:DF 0 "s_register_operand" "=f") 2936; (unspec:DF [(float_extend:DF 2937; (match_operand:SF 1 "s_register_operand" "f"))] 2938; UNSPEC_SIN))] 2939; "TARGET_ARM && TARGET_HARD_FLOAT" 2940; "sin%?d\\t%0, %1" 2941;[(set_attr "type" "float_em")]) 2942; 2943;(define_insn "sinxf2" 2944; [(set (match_operand:XF 0 "s_register_operand" "=f") 2945; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 2946; UNSPEC_SIN))] 2947; "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 2948; "sin%?e\\t%0, %1" 2949;[(set_attr "type" "float_em")]) 2950; 2951;(define_insn "cossf2" 2952; [(set (match_operand:SF 0 "s_register_operand" "=f") 2953; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 2954; UNSPEC_COS))] 2955; "TARGET_ARM && TARGET_HARD_FLOAT" 2956; "cos%?s\\t%0, %1" 2957;[(set_attr "type" "float_em")]) 2958; 2959;(define_insn "cosdf2" 2960; [(set (match_operand:DF 0 "s_register_operand" "=f") 2961; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 2962; UNSPEC_COS))] 2963; "TARGET_ARM && TARGET_HARD_FLOAT" 2964; "cos%?d\\t%0, %1" 2965;[(set_attr "type" "float_em")]) 2966; 2967;(define_insn "*cosdf_esfdf" 2968; [(set (match_operand:DF 0 "s_register_operand" "=f") 2969; (unspec:DF [(float_extend:DF 2970; (match_operand:SF 1 "s_register_operand" "f"))] 2971; UNSPEC_COS))] 2972; "TARGET_ARM && TARGET_HARD_FLOAT" 2973; "cos%?d\\t%0, %1" 2974;[(set_attr "type" "float_em")]) 2975; 2976;(define_insn "cosxf2" 2977; [(set (match_operand:XF 0 "s_register_operand" "=f") 2978; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 2979; UNSEPC_COS))] 2980; "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 2981; "cos%?e\\t%0, %1" 2982;[(set_attr "type" "float_em")]) 2983 2984(define_insn_and_split "one_cmpldi2" 2985 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 2986 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))] 2987 "TARGET_ARM" 2988 "#" 2989 "TARGET_ARM && reload_completed" 2990 [(set (match_dup 0) (not:SI (match_dup 1))) 2991 (set (match_dup 2) (not:SI (match_dup 3)))] 2992 " 2993 { 2994 operands[2] = gen_highpart (SImode, operands[0]); 2995 operands[0] = gen_lowpart (SImode, operands[0]); 2996 operands[3] = gen_highpart (SImode, operands[1]); 2997 operands[1] = gen_lowpart (SImode, operands[1]); 2998 }" 2999 [(set_attr "length" "8") 3000 (set_attr "predicable" "yes")] 3001) 3002 3003(define_expand "one_cmplsi2" 3004 [(set (match_operand:SI 0 "s_register_operand" "") 3005 (not:SI (match_operand:SI 1 "s_register_operand" "")))] 3006 "TARGET_EITHER" 3007 "" 3008) 3009 3010(define_insn "*arm_one_cmplsi2" 3011 [(set (match_operand:SI 0 "s_register_operand" "=r") 3012 (not:SI (match_operand:SI 1 "s_register_operand" "r")))] 3013 "TARGET_ARM" 3014 "mvn%?\\t%0, %1" 3015 [(set_attr "predicable" "yes")] 3016) 3017 3018(define_insn "*thumb_one_cmplsi2" 3019 [(set (match_operand:SI 0 "register_operand" "=l") 3020 (not:SI (match_operand:SI 1 "register_operand" "l")))] 3021 "TARGET_THUMB" 3022 "mvn\\t%0, %1" 3023 [(set_attr "length" "2")] 3024) 3025 3026(define_insn "*notsi_compare0" 3027 [(set (reg:CC_NOOV CC_REGNUM) 3028 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r")) 3029 (const_int 0))) 3030 (set (match_operand:SI 0 "s_register_operand" "=r") 3031 (not:SI (match_dup 1)))] 3032 "TARGET_ARM" 3033 "mvn%?s\\t%0, %1" 3034 [(set_attr "conds" "set")] 3035) 3036 3037(define_insn "*notsi_compare0_scratch" 3038 [(set (reg:CC_NOOV CC_REGNUM) 3039 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r")) 3040 (const_int 0))) 3041 (clobber (match_scratch:SI 0 "=r"))] 3042 "TARGET_ARM" 3043 "mvn%?s\\t%0, %1" 3044 [(set_attr "conds" "set")] 3045) 3046 3047;; Fixed <--> Floating conversion insns 3048 3049(define_insn "floatsisf2" 3050 [(set (match_operand:SF 0 "s_register_operand" "=f") 3051 (float:SF (match_operand:SI 1 "s_register_operand" "r")))] 3052 "TARGET_ARM && TARGET_HARD_FLOAT" 3053 "flt%?s\\t%0, %1" 3054 [(set_attr "type" "r_2_f") 3055 (set_attr "predicable" "yes")] 3056) 3057 3058(define_insn "floatsidf2" 3059 [(set (match_operand:DF 0 "s_register_operand" "=f") 3060 (float:DF (match_operand:SI 1 "s_register_operand" "r")))] 3061 "TARGET_ARM && TARGET_HARD_FLOAT" 3062 "flt%?d\\t%0, %1" 3063 [(set_attr "type" "r_2_f") 3064 (set_attr "predicable" "yes")] 3065) 3066 3067(define_insn "floatsixf2" 3068 [(set (match_operand:XF 0 "s_register_operand" "=f") 3069 (float:XF (match_operand:SI 1 "s_register_operand" "r")))] 3070 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 3071 "flt%?e\\t%0, %1" 3072 [(set_attr "type" "r_2_f") 3073 (set_attr "predicable" "yes")] 3074) 3075 3076(define_insn "fix_truncsfsi2" 3077 [(set (match_operand:SI 0 "s_register_operand" "=r") 3078 (fix:SI (match_operand:SF 1 "s_register_operand" "f")))] 3079 "TARGET_ARM && TARGET_HARD_FLOAT" 3080 "fix%?z\\t%0, %1" 3081 [(set_attr "type" "f_2_r") 3082 (set_attr "predicable" "yes")] 3083) 3084 3085(define_insn "fix_truncdfsi2" 3086 [(set (match_operand:SI 0 "s_register_operand" "=r") 3087 (fix:SI (match_operand:DF 1 "s_register_operand" "f")))] 3088 "TARGET_ARM && TARGET_HARD_FLOAT" 3089 "fix%?z\\t%0, %1" 3090 [(set_attr "type" "f_2_r") 3091 (set_attr "predicable" "yes")] 3092) 3093 3094(define_insn "fix_truncxfsi2" 3095 [(set (match_operand:SI 0 "s_register_operand" "=r") 3096 (fix:SI (match_operand:XF 1 "s_register_operand" "f")))] 3097 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 3098 "fix%?z\\t%0, %1" 3099 [(set_attr "type" "f_2_r") 3100 (set_attr "predicable" "yes")] 3101) 3102 3103;; Truncation insns 3104 3105(define_insn "truncdfsf2" 3106 [(set (match_operand:SF 0 "s_register_operand" "=f") 3107 (float_truncate:SF 3108 (match_operand:DF 1 "s_register_operand" "f")))] 3109 "TARGET_ARM && TARGET_HARD_FLOAT" 3110 "mvf%?s\\t%0, %1" 3111 [(set_attr "type" "ffarith") 3112 (set_attr "predicable" "yes")] 3113) 3114 3115(define_insn "truncxfsf2" 3116 [(set (match_operand:SF 0 "s_register_operand" "=f") 3117 (float_truncate:SF 3118 (match_operand:XF 1 "s_register_operand" "f")))] 3119 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 3120 "mvf%?s\\t%0, %1" 3121 [(set_attr "type" "ffarith") 3122 (set_attr "predicable" "yes")] 3123) 3124 3125(define_insn "truncxfdf2" 3126 [(set (match_operand:DF 0 "s_register_operand" "=f") 3127 (float_truncate:DF 3128 (match_operand:XF 1 "s_register_operand" "f")))] 3129 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 3130 "mvf%?d\\t%0, %1" 3131 [(set_attr "type" "ffarith") 3132 (set_attr "predicable" "yes")] 3133) 3134 3135;; Zero and sign extension instructions. 3136 3137(define_insn "zero_extendsidi2" 3138 [(set (match_operand:DI 0 "s_register_operand" "=r") 3139 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))] 3140 "TARGET_ARM" 3141 "* 3142 if (REGNO (operands[1]) 3143 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0)) 3144 output_asm_insn (\"mov%?\\t%Q0, %1\", operands); 3145 return \"mov%?\\t%R0, #0\"; 3146 " 3147 [(set_attr "length" "8") 3148 (set_attr "predicable" "yes")] 3149) 3150 3151(define_insn "zero_extendqidi2" 3152 [(set (match_operand:DI 0 "s_register_operand" "=r,r") 3153 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] 3154 "TARGET_ARM" 3155 "@ 3156 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0 3157 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0" 3158 [(set_attr "length" "8") 3159 (set_attr "predicable" "yes") 3160 (set_attr "type" "*,load") 3161 (set_attr "pool_range" "*,4092") 3162 (set_attr "neg_pool_range" "*,4084")] 3163) 3164 3165(define_insn "extendsidi2" 3166 [(set (match_operand:DI 0 "s_register_operand" "=r") 3167 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))] 3168 "TARGET_ARM" 3169 "* 3170 if (REGNO (operands[1]) 3171 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0)) 3172 output_asm_insn (\"mov%?\\t%Q0, %1\", operands); 3173 return \"mov%?\\t%R0, %Q0, asr #31\"; 3174 " 3175 [(set_attr "length" "8") 3176 (set_attr "shift" "1") 3177 (set_attr "predicable" "yes")] 3178) 3179 3180(define_expand "zero_extendhisi2" 3181 [(set (match_dup 2) 3182 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "") 3183 (const_int 16))) 3184 (set (match_operand:SI 0 "s_register_operand" "") 3185 (lshiftrt:SI (match_dup 2) (const_int 16)))] 3186 "TARGET_EITHER" 3187 " 3188 { 3189 if (TARGET_ARM) 3190 { 3191 if (arm_arch4 && GET_CODE (operands[1]) == MEM) 3192 { 3193 /* Note: We do not have to worry about TARGET_MMU_TRAPS 3194 here because the insn below will generate an LDRH instruction 3195 rather than an LDR instruction, so we cannot get an unaligned 3196 word access. */ 3197 emit_insn (gen_rtx_SET (VOIDmode, operands[0], 3198 gen_rtx_ZERO_EXTEND (SImode, 3199 operands[1]))); 3200 DONE; 3201 } 3202 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM) 3203 { 3204 emit_insn (gen_movhi_bytes (operands[0], operands[1])); 3205 DONE; 3206 } 3207 if (!s_register_operand (operands[1], HImode)) 3208 operands[1] = copy_to_mode_reg (HImode, operands[1]); 3209 operands[1] = gen_lowpart (SImode, operands[1]); 3210 operands[2] = gen_reg_rtx (SImode); 3211 } 3212 else /* TARGET_THUMB */ 3213 { 3214 if (GET_CODE (operands[1]) == MEM) 3215 { 3216 rtx tmp; 3217 3218 tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]); 3219 tmp = gen_rtx_SET (VOIDmode, operands[0], tmp); 3220 emit_insn (tmp); 3221 } 3222 else 3223 { 3224 rtx ops[3]; 3225 3226 if (!s_register_operand (operands[1], HImode)) 3227 operands[1] = copy_to_mode_reg (HImode, operands[1]); 3228 operands[1] = gen_lowpart (SImode, operands[1]); 3229 operands[2] = gen_reg_rtx (SImode); 3230 3231 ops[0] = operands[2]; 3232 ops[1] = operands[1]; 3233 ops[2] = GEN_INT (16); 3234 3235 emit_insn (gen_rtx_SET (VOIDmode, ops[0], 3236 gen_rtx_ASHIFT (SImode, ops[1], ops[2]))); 3237 3238 ops[0] = operands[0]; 3239 ops[1] = operands[2]; 3240 ops[2] = GEN_INT (16); 3241 3242 emit_insn (gen_rtx_SET (VOIDmode, ops[0], 3243 gen_rtx_LSHIFTRT (SImode, ops[1], 3244 ops[2]))); 3245 } 3246 DONE; 3247 } 3248 }" 3249) 3250 3251(define_insn "*thumb_zero_extendhisi2" 3252 [(set (match_operand:SI 0 "register_operand" "=l") 3253 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] 3254 "TARGET_THUMB" 3255 "* 3256 rtx mem = XEXP (operands[1], 0); 3257 3258 if (GET_CODE (mem) == CONST) 3259 mem = XEXP (mem, 0); 3260 3261 if (GET_CODE (mem) == LABEL_REF) 3262 return \"ldr\\t%0, %1\"; 3263 3264 if (GET_CODE (mem) == PLUS) 3265 { 3266 rtx a = XEXP (mem, 0); 3267 rtx b = XEXP (mem, 1); 3268 3269 /* This can happen due to bugs in reload. */ 3270 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM) 3271 { 3272 rtx ops[2]; 3273 ops[0] = operands[0]; 3274 ops[1] = a; 3275 3276 output_asm_insn (\"mov %0, %1\", ops); 3277 3278 XEXP (mem, 0) = operands[0]; 3279 } 3280 3281 else if ( GET_CODE (a) == LABEL_REF 3282 && GET_CODE (b) == CONST_INT) 3283 return \"ldr\\t%0, %1\"; 3284 } 3285 3286 return \"ldrh\\t%0, %1\"; 3287 " 3288 [(set_attr "length" "4") 3289 (set_attr "type" "load") 3290 (set_attr "pool_range" "60")] 3291) 3292 3293(define_insn "*arm_zero_extendhisi2" 3294 [(set (match_operand:SI 0 "s_register_operand" "=r") 3295 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] 3296 "TARGET_ARM && arm_arch4" 3297 "ldr%?h\\t%0, %1" 3298 [(set_attr "type" "load") 3299 (set_attr "predicable" "yes") 3300 (set_attr "pool_range" "256") 3301 (set_attr "neg_pool_range" "244")] 3302) 3303 3304(define_split 3305 [(set (match_operand:SI 0 "s_register_operand" "") 3306 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))) 3307 (clobber (match_operand:SI 2 "s_register_operand" ""))] 3308 "TARGET_ARM && (!arm_arch4)" 3309 [(set (match_dup 2) (match_dup 1)) 3310 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))] 3311 " 3312 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL) 3313 FAIL; 3314 " 3315) 3316 3317(define_split 3318 [(set (match_operand:SI 0 "s_register_operand" "") 3319 (match_operator:SI 3 "shiftable_operator" 3320 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")) 3321 (match_operand:SI 4 "s_register_operand" "")])) 3322 (clobber (match_operand:SI 2 "s_register_operand" ""))] 3323 "TARGET_ARM && (!arm_arch4)" 3324 [(set (match_dup 2) (match_dup 1)) 3325 (set (match_dup 0) 3326 (match_op_dup 3 3327 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))] 3328 " 3329 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL) 3330 FAIL; 3331 " 3332) 3333 3334(define_expand "zero_extendqisi2" 3335 [(set (match_operand:SI 0 "s_register_operand" "") 3336 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] 3337 "TARGET_EITHER" 3338 " 3339 if (GET_CODE (operands[1]) != MEM) 3340 { 3341 if (TARGET_ARM) 3342 { 3343 emit_insn (gen_andsi3 (operands[0], 3344 gen_lowpart (SImode, operands[1]), 3345 GEN_INT (255))); 3346 } 3347 else /* TARGET_THUMB */ 3348 { 3349 rtx temp = gen_reg_rtx (SImode); 3350 rtx ops[3]; 3351 3352 operands[1] = copy_to_mode_reg (QImode, operands[1]); 3353 operands[1] = gen_lowpart (SImode, operands[1]); 3354 3355 ops[0] = temp; 3356 ops[1] = operands[1]; 3357 ops[2] = GEN_INT (24); 3358 3359 emit_insn (gen_rtx_SET (VOIDmode, ops[0], 3360 gen_rtx_ASHIFT (SImode, ops[1], ops[2]))); 3361 3362 ops[0] = operands[0]; 3363 ops[1] = temp; 3364 ops[2] = GEN_INT (24); 3365 3366 emit_insn (gen_rtx_SET (VOIDmode, ops[0], 3367 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2]))); 3368 } 3369 DONE; 3370 } 3371 " 3372) 3373 3374(define_insn "*thumb_zero_extendqisi2" 3375 [(set (match_operand:SI 0 "register_operand" "=l") 3376 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] 3377 "TARGET_THUMB" 3378 "ldrb\\t%0, %1" 3379 [(set_attr "length" "2") 3380 (set_attr "type" "load") 3381 (set_attr "pool_range" "32")] 3382) 3383 3384(define_insn "*arm_zero_extendqisi2" 3385 [(set (match_operand:SI 0 "s_register_operand" "=r") 3386 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] 3387 "TARGET_ARM" 3388 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2" 3389 [(set_attr "type" "load") 3390 (set_attr "predicable" "yes") 3391 (set_attr "pool_range" "4096") 3392 (set_attr "neg_pool_range" "4084")] 3393) 3394 3395(define_split 3396 [(set (match_operand:SI 0 "s_register_operand" "") 3397 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0))) 3398 (clobber (match_operand:SI 2 "s_register_operand" ""))] 3399 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN" 3400 [(set (match_dup 2) (match_dup 1)) 3401 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))] 3402 "" 3403) 3404 3405(define_insn "*compareqi_eq0" 3406 [(set (reg:CC_Z CC_REGNUM) 3407 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r") 3408 (const_int 0)))] 3409 "TARGET_ARM" 3410 "tst\\t%0, #255" 3411 [(set_attr "conds" "set")] 3412) 3413 3414(define_expand "extendhisi2" 3415 [(set (match_dup 2) 3416 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "") 3417 (const_int 16))) 3418 (set (match_operand:SI 0 "s_register_operand" "") 3419 (ashiftrt:SI (match_dup 2) 3420 (const_int 16)))] 3421 "TARGET_EITHER" 3422 " 3423 { 3424 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM) 3425 { 3426 /* Note: We do not have to worry about TARGET_MMU_TRAPS 3427 here because the insn below will generate an LDRH instruction 3428 rather than an LDR instruction, so we cannot get an unaligned 3429 word access. */ 3430 emit_insn (gen_rtx_SET (VOIDmode, operands[0], 3431 gen_rtx_SIGN_EXTEND (SImode, operands[1]))); 3432 DONE; 3433 } 3434 3435 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM) 3436 { 3437 emit_insn (gen_extendhisi2_mem (operands[0], operands[1])); 3438 DONE; 3439 } 3440 if (!s_register_operand (operands[1], HImode)) 3441 operands[1] = copy_to_mode_reg (HImode, operands[1]); 3442 operands[1] = gen_lowpart (SImode, operands[1]); 3443 operands[2] = gen_reg_rtx (SImode); 3444 3445 if (TARGET_THUMB) 3446 { 3447 rtx ops[3]; 3448 3449 ops[0] = operands[2]; 3450 ops[1] = operands[1]; 3451 ops[2] = GEN_INT (16); 3452 3453 emit_insn (gen_rtx_SET (VOIDmode, ops[0], 3454 gen_rtx_ASHIFT (SImode, ops[1], ops[2]))); 3455 3456 ops[0] = operands[0]; 3457 ops[1] = operands[2]; 3458 ops[2] = GEN_INT (16); 3459 3460 emit_insn (gen_rtx_SET (VOIDmode, ops[0], 3461 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2]))); 3462 3463 DONE; 3464 } 3465 }" 3466) 3467 3468(define_insn "*thumb_extendhisi2_insn" 3469 [(set (match_operand:SI 0 "register_operand" "=l") 3470 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m"))) 3471 (clobber (match_scratch:SI 2 "=&l"))] 3472 "TARGET_THUMB" 3473 "* 3474 { 3475 rtx ops[4]; 3476 rtx mem = XEXP (operands[1], 0); 3477 3478 /* This code used to try to use 'V', and fix the address only if it was 3479 offsettable, but this fails for e.g. REG+48 because 48 is outside the 3480 range of QImode offsets, and offsettable_address_p does a QImode 3481 address check. */ 3482 3483 if (GET_CODE (mem) == CONST) 3484 mem = XEXP (mem, 0); 3485 3486 if (GET_CODE (mem) == LABEL_REF) 3487 return \"ldr\\t%0, %1\"; 3488 3489 if (GET_CODE (mem) == PLUS) 3490 { 3491 rtx a = XEXP (mem, 0); 3492 rtx b = XEXP (mem, 1); 3493 3494 if (GET_CODE (a) == LABEL_REF 3495 && GET_CODE (b) == CONST_INT) 3496 return \"ldr\\t%0, %1\"; 3497 3498 if (GET_CODE (b) == REG) 3499 return \"ldrsh\\t%0, %1\"; 3500 3501 ops[1] = a; 3502 ops[2] = b; 3503 } 3504 else 3505 { 3506 ops[1] = mem; 3507 ops[2] = const0_rtx; 3508 } 3509 3510 if (GET_CODE (ops[1]) != REG) 3511 { 3512 debug_rtx (ops[1]); 3513 abort (); 3514 } 3515 3516 ops[0] = operands[0]; 3517 ops[3] = operands[2]; 3518 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops); 3519 return \"\"; 3520 }" 3521 [(set_attr "length" "4") 3522 (set_attr "type" "load") 3523 (set_attr "pool_range" "1020")] 3524) 3525 3526(define_expand "extendhisi2_mem" 3527 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" ""))) 3528 (set (match_dup 3) 3529 (zero_extend:SI (match_dup 7))) 3530 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24))) 3531 (set (match_operand:SI 0 "" "") 3532 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))] 3533 "TARGET_ARM" 3534 " 3535 { 3536 rtx mem1, mem2; 3537 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); 3538 3539 mem1 = gen_rtx_MEM (QImode, addr); 3540 MEM_COPY_ATTRIBUTES (mem1, operands[1]); 3541 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1)); 3542 MEM_COPY_ATTRIBUTES (mem2, operands[1]); 3543 operands[0] = gen_lowpart (SImode, operands[0]); 3544 operands[1] = mem1; 3545 operands[2] = gen_reg_rtx (SImode); 3546 operands[3] = gen_reg_rtx (SImode); 3547 operands[6] = gen_reg_rtx (SImode); 3548 operands[7] = mem2; 3549 3550 if (BYTES_BIG_ENDIAN) 3551 { 3552 operands[4] = operands[2]; 3553 operands[5] = operands[3]; 3554 } 3555 else 3556 { 3557 operands[4] = operands[3]; 3558 operands[5] = operands[2]; 3559 } 3560 }" 3561) 3562 3563(define_insn "*arm_extendhisi_insn" 3564 [(set (match_operand:SI 0 "s_register_operand" "=r") 3565 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))] 3566 "TARGET_ARM && arm_arch4" 3567 "ldr%?sh\\t%0, %1" 3568 [(set_attr "type" "load") 3569 (set_attr "predicable" "yes") 3570 (set_attr "pool_range" "256") 3571 (set_attr "neg_pool_range" "244")] 3572) 3573 3574(define_split 3575 [(set (match_operand:SI 0 "s_register_operand" "") 3576 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))) 3577 (clobber (match_operand:SI 2 "s_register_operand" ""))] 3578 "TARGET_ARM && (!arm_arch4)" 3579 [(set (match_dup 2) (match_dup 1)) 3580 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))] 3581 " 3582 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL) 3583 FAIL; 3584 " 3585) 3586 3587(define_split 3588 [(set (match_operand:SI 0 "s_register_operand" "") 3589 (match_operator:SI 3 "shiftable_operator" 3590 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")) 3591 (match_operand:SI 4 "s_register_operand" "")])) 3592 (clobber (match_operand:SI 2 "s_register_operand" ""))] 3593 "TARGET_ARM && (!arm_arch4)" 3594 [(set (match_dup 2) (match_dup 1)) 3595 (set (match_dup 0) 3596 (match_op_dup 3 3597 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))] 3598 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL) 3599 FAIL; 3600 " 3601) 3602 3603(define_expand "extendqihi2" 3604 [(set (match_dup 2) 3605 (ashift:SI (match_operand:QI 1 "general_operand" "") 3606 (const_int 24))) 3607 (set (match_operand:HI 0 "s_register_operand" "") 3608 (ashiftrt:SI (match_dup 2) 3609 (const_int 24)))] 3610 "TARGET_ARM" 3611 " 3612 { 3613 if (arm_arch4 && GET_CODE (operands[1]) == MEM) 3614 { 3615 emit_insn (gen_rtx_SET (VOIDmode, 3616 operands[0], 3617 gen_rtx_SIGN_EXTEND (HImode, operands[1]))); 3618 DONE; 3619 } 3620 if (!s_register_operand (operands[1], QImode)) 3621 operands[1] = copy_to_mode_reg (QImode, operands[1]); 3622 operands[0] = gen_lowpart (SImode, operands[0]); 3623 operands[1] = gen_lowpart (SImode, operands[1]); 3624 operands[2] = gen_reg_rtx (SImode); 3625 }" 3626) 3627 3628; Rather than restricting all byte accesses to memory addresses that ldrsb 3629; can handle, we fix up the ones that ldrsb can't grok with a split. 3630(define_insn "*extendqihi_insn" 3631 [(set (match_operand:HI 0 "s_register_operand" "=r") 3632 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))] 3633 "TARGET_ARM && arm_arch4" 3634 "* 3635 /* If the address is invalid, this will split the instruction into two. */ 3636 if (bad_signed_byte_operand (operands[1], VOIDmode)) 3637 return \"#\"; 3638 return \"ldr%?sb\\t%0, %1\"; 3639 " 3640 [(set_attr "type" "load") 3641 (set_attr "predicable" "yes") 3642 (set_attr "length" "8") 3643 (set_attr "pool_range" "256") 3644 (set_attr "neg_pool_range" "244")] 3645) 3646 3647(define_split 3648 [(set (match_operand:HI 0 "s_register_operand" "") 3649 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))] 3650 "TARGET_ARM && arm_arch4 && reload_completed" 3651 [(set (match_dup 3) (match_dup 1)) 3652 (set (match_dup 0) (sign_extend:HI (match_dup 2)))] 3653 " 3654 { 3655 HOST_WIDE_INT offset; 3656 3657 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0])); 3658 operands[2] = gen_rtx_MEM (QImode, operands[3]); 3659 MEM_COPY_ATTRIBUTES (operands[2], operands[1]); 3660 operands[1] = XEXP (operands[1], 0); 3661 if (GET_CODE (operands[1]) == PLUS 3662 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT 3663 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1))) 3664 || const_ok_for_arm (-offset))) 3665 { 3666 HOST_WIDE_INT low = (offset > 0 3667 ? (offset & 0xff) : -((-offset) & 0xff)); 3668 XEXP (operands[2], 0) = plus_constant (operands[3], low); 3669 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low); 3670 } 3671 /* Ensure the sum is in correct canonical form */ 3672 else if (GET_CODE (operands[1]) == PLUS 3673 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT 3674 && !s_register_operand (XEXP (operands[1], 1), VOIDmode)) 3675 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]), 3676 XEXP (operands[1], 1), 3677 XEXP (operands[1], 0)); 3678 }" 3679) 3680 3681(define_expand "extendqisi2" 3682 [(set (match_dup 2) 3683 (ashift:SI (match_operand:QI 1 "general_operand" "") 3684 (const_int 24))) 3685 (set (match_operand:SI 0 "s_register_operand" "") 3686 (ashiftrt:SI (match_dup 2) 3687 (const_int 24)))] 3688 "TARGET_EITHER" 3689 " 3690 { 3691 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM) 3692 { 3693 emit_insn (gen_rtx_SET (VOIDmode, 3694 operands[0], 3695 gen_rtx_SIGN_EXTEND (SImode, operands[1]))); 3696 DONE; 3697 } 3698 if (!s_register_operand (operands[1], QImode)) 3699 operands[1] = copy_to_mode_reg (QImode, operands[1]); 3700 operands[1] = gen_lowpart (SImode, operands[1]); 3701 operands[2] = gen_reg_rtx (SImode); 3702 3703 if (TARGET_THUMB) 3704 { 3705 rtx ops[3]; 3706 3707 ops[0] = operands[2]; 3708 ops[1] = operands[1]; 3709 ops[2] = GEN_INT (24); 3710 3711 emit_insn (gen_rtx_SET (VOIDmode, ops[0], 3712 gen_rtx_ASHIFT (SImode, ops[1], ops[2]))); 3713 3714 ops[0] = operands[0]; 3715 ops[1] = operands[2]; 3716 ops[2] = GEN_INT (24); 3717 3718 emit_insn (gen_rtx_SET (VOIDmode, ops[0], 3719 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2]))); 3720 3721 DONE; 3722 } 3723 }" 3724) 3725 3726; Rather than restricting all byte accesses to memory addresses that ldrsb 3727; can handle, we fix up the ones that ldrsb can't grok with a split. 3728(define_insn "*arm_extendqisi_insn" 3729 [(set (match_operand:SI 0 "s_register_operand" "=r") 3730 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))] 3731 "TARGET_ARM && arm_arch4" 3732 "* 3733 /* If the address is invalid, this will split the instruction into two. */ 3734 if (bad_signed_byte_operand (operands[1], VOIDmode)) 3735 return \"#\"; 3736 return \"ldr%?sb\\t%0, %1\"; 3737 " 3738 [(set_attr "type" "load") 3739 (set_attr "predicable" "yes") 3740 (set_attr "length" "8") 3741 (set_attr "pool_range" "256") 3742 (set_attr "neg_pool_range" "244")] 3743) 3744 3745(define_split 3746 [(set (match_operand:SI 0 "s_register_operand" "") 3747 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))] 3748 "TARGET_ARM && arm_arch4 && reload_completed" 3749 [(set (match_dup 0) (match_dup 1)) 3750 (set (match_dup 0) (sign_extend:SI (match_dup 2)))] 3751 " 3752 { 3753 HOST_WIDE_INT offset; 3754 3755 operands[2] = gen_rtx_MEM (QImode, operands[0]); 3756 MEM_COPY_ATTRIBUTES (operands[2], operands[1]); 3757 operands[1] = XEXP (operands[1], 0); 3758 if (GET_CODE (operands[1]) == PLUS 3759 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT 3760 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1))) 3761 || const_ok_for_arm (-offset))) 3762 { 3763 HOST_WIDE_INT low = (offset > 0 3764 ? (offset & 0xff) : -((-offset) & 0xff)); 3765 XEXP (operands[2], 0) = plus_constant (operands[0], low); 3766 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low); 3767 } 3768 /* Ensure the sum is in correct canonical form */ 3769 else if (GET_CODE (operands[1]) == PLUS 3770 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT 3771 && !s_register_operand (XEXP (operands[1], 1), VOIDmode)) 3772 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]), 3773 XEXP (operands[1], 1), 3774 XEXP (operands[1], 0)); 3775 }" 3776) 3777 3778(define_insn "*thumb_extendqisi2_insn" 3779 [(set (match_operand:SI 0 "register_operand" "=l,l") 3780 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))] 3781 "TARGET_THUMB" 3782 "* 3783 { 3784 rtx ops[3]; 3785 rtx mem = XEXP (operands[1], 0); 3786 3787 if (GET_CODE (mem) == CONST) 3788 mem = XEXP (mem, 0); 3789 3790 if (GET_CODE (mem) == LABEL_REF) 3791 return \"ldr\\t%0, %1\"; 3792 3793 if (GET_CODE (mem) == PLUS 3794 && GET_CODE (XEXP (mem, 0)) == LABEL_REF) 3795 return \"ldr\\t%0, %1\"; 3796 3797 if (which_alternative == 0) 3798 return \"ldrsb\\t%0, %1\"; 3799 3800 ops[0] = operands[0]; 3801 3802 if (GET_CODE (mem) == PLUS) 3803 { 3804 rtx a = XEXP (mem, 0); 3805 rtx b = XEXP (mem, 1); 3806 3807 ops[1] = a; 3808 ops[2] = b; 3809 3810 if (GET_CODE (a) == REG) 3811 { 3812 if (GET_CODE (b) == REG) 3813 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops); 3814 else if (REGNO (a) == REGNO (ops[0])) 3815 { 3816 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops); 3817 output_asm_insn (\"lsl\\t%0, %0, #24\", ops); 3818 output_asm_insn (\"asr\\t%0, %0, #24\", ops); 3819 } 3820 else 3821 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); 3822 } 3823 else if (GET_CODE (b) != REG) 3824 abort (); 3825 else 3826 { 3827 if (REGNO (b) == REGNO (ops[0])) 3828 { 3829 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops); 3830 output_asm_insn (\"lsl\\t%0, %0, #24\", ops); 3831 output_asm_insn (\"asr\\t%0, %0, #24\", ops); 3832 } 3833 else 3834 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); 3835 } 3836 } 3837 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem)) 3838 { 3839 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops); 3840 output_asm_insn (\"lsl\\t%0, %0, #24\", ops); 3841 output_asm_insn (\"asr\\t%0, %0, #24\", ops); 3842 } 3843 else 3844 { 3845 ops[1] = mem; 3846 ops[2] = const0_rtx; 3847 3848 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); 3849 } 3850 return \"\"; 3851 }" 3852 [(set_attr "length" "2,6") 3853 (set_attr "type" "load,load") 3854 (set_attr "pool_range" "32,32")] 3855) 3856 3857(define_insn "extendsfdf2" 3858 [(set (match_operand:DF 0 "s_register_operand" "=f") 3859 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))] 3860 "TARGET_ARM && TARGET_HARD_FLOAT" 3861 "mvf%?d\\t%0, %1" 3862 [(set_attr "type" "ffarith") 3863 (set_attr "predicable" "yes")] 3864) 3865 3866(define_insn "extendsfxf2" 3867 [(set (match_operand:XF 0 "s_register_operand" "=f") 3868 (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))] 3869 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 3870 "mvf%?e\\t%0, %1" 3871 [(set_attr "type" "ffarith") 3872 (set_attr "predicable" "yes")] 3873) 3874 3875(define_insn "extenddfxf2" 3876 [(set (match_operand:XF 0 "s_register_operand" "=f") 3877 (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))] 3878 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 3879 "mvf%?e\\t%0, %1" 3880 [(set_attr "type" "ffarith") 3881 (set_attr "predicable" "yes")] 3882) 3883 3884 3885;; Move insns (including loads and stores) 3886 3887;; XXX Just some ideas about movti. 3888;; I don't think these are a good idea on the arm, there just aren't enough 3889;; registers 3890;;(define_expand "loadti" 3891;; [(set (match_operand:TI 0 "s_register_operand" "") 3892;; (mem:TI (match_operand:SI 1 "address_operand" "")))] 3893;; "" "") 3894 3895;;(define_expand "storeti" 3896;; [(set (mem:TI (match_operand:TI 0 "address_operand" "")) 3897;; (match_operand:TI 1 "s_register_operand" ""))] 3898;; "" "") 3899 3900;;(define_expand "movti" 3901;; [(set (match_operand:TI 0 "general_operand" "") 3902;; (match_operand:TI 1 "general_operand" ""))] 3903;; "" 3904;; " 3905;;{ 3906;; rtx insn; 3907;; 3908;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) 3909;; operands[1] = copy_to_reg (operands[1]); 3910;; if (GET_CODE (operands[0]) == MEM) 3911;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]); 3912;; else if (GET_CODE (operands[1]) == MEM) 3913;; insn = gen_loadti (operands[0], XEXP (operands[1], 0)); 3914;; else 3915;; FAIL; 3916;; 3917;; emit_insn (insn); 3918;; DONE; 3919;;}") 3920 3921;; Recognize garbage generated above. 3922 3923;;(define_insn "" 3924;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m") 3925;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))] 3926;; "" 3927;; "* 3928;; { 3929;; register mem = (which_alternative < 3); 3930;; register const char *template; 3931;; 3932;; operands[mem] = XEXP (operands[mem], 0); 3933;; switch (which_alternative) 3934;; { 3935;; case 0: template = \"ldmdb\\t%1!, %M0\"; break; 3936;; case 1: template = \"ldmia\\t%1!, %M0\"; break; 3937;; case 2: template = \"ldmia\\t%1, %M0\"; break; 3938;; case 3: template = \"stmdb\\t%0!, %M1\"; break; 3939;; case 4: template = \"stmia\\t%0!, %M1\"; break; 3940;; case 5: template = \"stmia\\t%0, %M1\"; break; 3941;; } 3942;; output_asm_insn (template, operands); 3943;; return \"\"; 3944;; }") 3945 3946(define_expand "movdi" 3947 [(set (match_operand:DI 0 "general_operand" "") 3948 (match_operand:DI 1 "general_operand" ""))] 3949 "TARGET_EITHER" 3950 " 3951 if (TARGET_THUMB) 3952 { 3953 if (!no_new_pseudos) 3954 { 3955 if (GET_CODE (operands[0]) != REG) 3956 operands[1] = force_reg (DImode, operands[1]); 3957 } 3958 } 3959 " 3960) 3961 3962(define_insn "*arm_movdi" 3963 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>") 3964 (match_operand:DI 1 "di_operand" "rIK,mi,r"))] 3965 "TARGET_ARM" 3966 "* 3967 return (output_move_double (operands)); 3968 " 3969 [(set_attr "length" "8") 3970 (set_attr "type" "*,load,store2") 3971 (set_attr "pool_range" "*,1020,*") 3972 (set_attr "neg_pool_range" "*,1008,*")] 3973) 3974 3975;;; ??? This should have alternatives for constants. 3976;;; ??? This was originally identical to the movdf_insn pattern. 3977;;; ??? The 'i' constraint looks funny, but it should always be replaced by 3978;;; thumb_reorg with a memory reference. 3979(define_insn "*thumb_movdi_insn" 3980 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r") 3981 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))] 3982 "TARGET_THUMB 3983 && ( register_operand (operands[0], DImode) 3984 || register_operand (operands[1], DImode))" 3985 "* 3986 { 3987 switch (which_alternative) 3988 { 3989 default: 3990 case 0: 3991 if (REGNO (operands[1]) == REGNO (operands[0]) + 1) 3992 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\"; 3993 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\"; 3994 case 1: 3995 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\"; 3996 case 2: 3997 operands[1] = GEN_INT (- INTVAL (operands[1])); 3998 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\"; 3999 case 3: 4000 return \"ldmia\\t%1, {%0, %H0}\"; 4001 case 4: 4002 return \"stmia\\t%0, {%1, %H1}\"; 4003 case 5: 4004 return thumb_load_double_from_address (operands); 4005 case 6: 4006 operands[2] = gen_rtx (MEM, SImode, 4007 plus_constant (XEXP (operands[0], 0), 4)); 4008 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands); 4009 return \"\"; 4010 case 7: 4011 if (REGNO (operands[1]) == REGNO (operands[0]) + 1) 4012 return \"mov\\t%0, %1\;mov\\t%H0, %H1\"; 4013 return \"mov\\t%H0, %H1\;mov\\t%0, %1\"; 4014 } 4015 }" 4016 [(set_attr "length" "4,4,6,2,2,6,4,4") 4017 (set_attr "type" "*,*,*,load,store2,load,store2,*") 4018 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")] 4019) 4020 4021(define_expand "movsi" 4022 [(set (match_operand:SI 0 "general_operand" "") 4023 (match_operand:SI 1 "general_operand" ""))] 4024 "TARGET_EITHER" 4025 " 4026 if (TARGET_ARM) 4027 { 4028 /* Everything except mem = const or mem = mem can be done easily */ 4029 if (GET_CODE (operands[0]) == MEM) 4030 operands[1] = force_reg (SImode, operands[1]); 4031 if (GET_CODE (operands[1]) == CONST_INT 4032 && !(const_ok_for_arm (INTVAL (operands[1])) 4033 || const_ok_for_arm (~INTVAL (operands[1])))) 4034 { 4035 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0], 4036 NULL_RTX, 4037 (no_new_pseudos ? 0 4038 : preserve_subexpressions_p ())); 4039 DONE; 4040 } 4041 } 4042 else /* TARGET_THUMB.... */ 4043 { 4044 if (!no_new_pseudos) 4045 { 4046 if (GET_CODE (operands[0]) != REG) 4047 operands[1] = force_reg (SImode, operands[1]); 4048 } 4049 } 4050 4051 if (flag_pic 4052 && (CONSTANT_P (operands[1]) 4053 || symbol_mentioned_p (operands[1]) 4054 || label_mentioned_p (operands[1]))) 4055 operands[1] = legitimize_pic_address (operands[1], SImode, 4056 (no_new_pseudos ? operands[0] : 0)); 4057 " 4058) 4059 4060(define_insn "*arm_movsi_insn" 4061 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m") 4062 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))] 4063 "TARGET_ARM 4064 && ( register_operand (operands[0], SImode) 4065 || register_operand (operands[1], SImode))" 4066 "@ 4067 mov%?\\t%0, %1 4068 mvn%?\\t%0, #%B1 4069 ldr%?\\t%0, %1 4070 str%?\\t%1, %0" 4071 [(set_attr "type" "*,*,load,store1") 4072 (set_attr "predicable" "yes") 4073 (set_attr "pool_range" "*,*,4096,*") 4074 (set_attr "neg_pool_range" "*,*,4084,*")] 4075) 4076 4077(define_split 4078 [(set (match_operand:SI 0 "s_register_operand" "") 4079 (match_operand:SI 1 "const_int_operand" ""))] 4080 "TARGET_ARM 4081 && (!(const_ok_for_arm (INTVAL (operands[1])) 4082 || const_ok_for_arm (~INTVAL (operands[1]))))" 4083 [(clobber (const_int 0))] 4084 " 4085 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0], 4086 NULL_RTX, 0); 4087 DONE; 4088 " 4089) 4090 4091(define_insn "*thumb_movsi_insn" 4092 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh") 4093 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))] 4094 "TARGET_THUMB 4095 && ( register_operand (operands[0], SImode) 4096 || register_operand (operands[1], SImode))" 4097 "@ 4098 mov %0, %1 4099 mov %0, %1 4100 # 4101 # 4102 ldmia\\t%1, {%0} 4103 stmia\\t%0, {%1} 4104 ldr\\t%0, %1 4105 str\\t%1, %0 4106 mov\\t%0, %1" 4107 [(set_attr "length" "2,2,4,4,2,2,2,2,2") 4108 (set_attr "type" "*,*,*,*,load,store1,load,store1,*") 4109 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")] 4110) 4111 4112(define_split 4113 [(set (match_operand:SI 0 "register_operand" "") 4114 (match_operand:SI 1 "const_int_operand" ""))] 4115 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')" 4116 [(set (match_dup 0) (match_dup 1)) 4117 (set (match_dup 0) (neg:SI (match_dup 0)))] 4118 "operands[1] = GEN_INT (- INTVAL (operands[1]));" 4119) 4120 4121(define_split 4122 [(set (match_operand:SI 0 "register_operand" "") 4123 (match_operand:SI 1 "const_int_operand" ""))] 4124 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')" 4125 [(set (match_dup 0) (match_dup 1)) 4126 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))] 4127 " 4128 { 4129 unsigned HOST_WIDE_INT val = INTVAL (operands[1]); 4130 unsigned HOST_WIDE_INT mask = 0xff; 4131 int i; 4132 4133 for (i = 0; i < 25; i++) 4134 if ((val & (mask << i)) == val) 4135 break; 4136 4137 /* Shouldn't happen, but we don't want to split if the shift is zero. */ 4138 if (i == 0) 4139 FAIL; 4140 4141 operands[1] = GEN_INT (val >> i); 4142 operands[2] = GEN_INT (i); 4143 }" 4144) 4145 4146;; When generating pic, we need to load the symbol offset into a register. 4147;; So that the optimizer does not confuse this with a normal symbol load 4148;; we use an unspec. The offset will be loaded from a constant pool entry, 4149;; since that is the only type of relocation we can use. 4150 4151;; The rather odd constraints on the following are to force reload to leave 4152;; the insn alone, and to force the minipool generation pass to then move 4153;; the GOT symbol to memory. 4154 4155(define_insn "pic_load_addr_arm" 4156 [(set (match_operand:SI 0 "s_register_operand" "=r") 4157 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))] 4158 "TARGET_ARM && flag_pic" 4159 "ldr%?\\t%0, %1" 4160 [(set_attr "type" "load") 4161 (set (attr "pool_range") (const_int 4096)) 4162 (set (attr "neg_pool_range") (const_int 4084))] 4163) 4164 4165(define_insn "pic_load_addr_thumb" 4166 [(set (match_operand:SI 0 "s_register_operand" "=l") 4167 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))] 4168 "TARGET_THUMB && flag_pic" 4169 "ldr\\t%0, %1" 4170 [(set_attr "type" "load") 4171 (set (attr "pool_range") (const_int 1024))] 4172) 4173 4174;; This variant is used for AOF assembly, since it needs to mention the 4175;; pic register in the rtl. 4176(define_expand "pic_load_addr_based" 4177 [(set (match_operand:SI 0 "s_register_operand" "=r") 4178 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))] 4179 "TARGET_ARM && flag_pic" 4180 "operands[2] = pic_offset_table_rtx;" 4181) 4182 4183(define_insn "*pic_load_addr_based_insn" 4184 [(set (match_operand:SI 0 "s_register_operand" "=r") 4185 (unspec:SI [(match_operand 1 "" "") 4186 (match_operand 2 "s_register_operand" "r")] 4187 UNSPEC_PIC_SYM))] 4188 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx" 4189 "* 4190#ifdef AOF_ASSEMBLER 4191 operands[1] = aof_pic_entry (operands[1]); 4192#endif 4193 output_asm_insn (\"ldr%?\\t%0, %a1\", operands); 4194 return \"\"; 4195 " 4196 [(set_attr "type" "load") 4197 (set (attr "pool_range") 4198 (if_then_else (eq_attr "is_thumb" "yes") 4199 (const_int 1024) 4200 (const_int 4096))) 4201 (set (attr "neg_pool_range") 4202 (if_then_else (eq_attr "is_thumb" "yes") 4203 (const_int 0) 4204 (const_int 4084)))] 4205) 4206 4207(define_insn "pic_add_dot_plus_four" 4208 [(set (match_operand:SI 0 "register_operand" "+r") 4209 (unspec:SI [(plus:SI (match_dup 0) 4210 (const (plus:SI (pc) (const_int 4))))] 4211 UNSPEC_PIC_BASE)) 4212 (use (label_ref (match_operand 1 "" "")))] 4213 "TARGET_THUMB && flag_pic" 4214 "* 4215 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", 4216 CODE_LABEL_NUMBER (operands[1])); 4217 return \"add\\t%0, %|pc\"; 4218 " 4219 [(set_attr "length" "2")] 4220) 4221 4222(define_insn "pic_add_dot_plus_eight" 4223 [(set (match_operand:SI 0 "register_operand" "+r") 4224 (unspec:SI [(plus:SI (match_dup 0) 4225 (const (plus:SI (pc) (const_int 8))))] 4226 UNSPEC_PIC_BASE)) 4227 (use (label_ref (match_operand 1 "" "")))] 4228 "TARGET_ARM && flag_pic" 4229 "* 4230 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", 4231 CODE_LABEL_NUMBER (operands[1])); 4232 return \"add%?\\t%0, %|pc, %0\"; 4233 " 4234 [(set_attr "predicable" "yes")] 4235) 4236 4237(define_expand "builtin_setjmp_receiver" 4238 [(label_ref (match_operand 0 "" ""))] 4239 "flag_pic" 4240 " 4241{ 4242 arm_finalize_pic (0); 4243 DONE; 4244}") 4245 4246;; If copying one reg to another we can set the condition codes according to 4247;; its value. Such a move is common after a return from subroutine and the 4248;; result is being tested against zero. 4249 4250(define_insn "*movsi_compare0" 4251 [(set (reg:CC CC_REGNUM) 4252 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r") 4253 (const_int 0))) 4254 (set (match_operand:SI 0 "s_register_operand" "=r,r") 4255 (match_dup 1))] 4256 "TARGET_ARM" 4257 "@ 4258 cmp%?\\t%0, #0 4259 sub%?s\\t%0, %1, #0" 4260 [(set_attr "conds" "set")] 4261) 4262 4263;; Subroutine to store a half word from a register into memory. 4264;; Operand 0 is the source register (HImode) 4265;; Operand 1 is the destination address in a register (SImode) 4266 4267;; In both this routine and the next, we must be careful not to spill 4268;; a memory address of reg+large_const into a separate PLUS insn, since this 4269;; can generate unrecognizable rtl. 4270 4271(define_expand "storehi" 4272 [;; store the low byte 4273 (set (match_operand 1 "" "") (match_dup 3)) 4274 ;; extract the high byte 4275 (set (match_dup 2) 4276 (ashiftrt:SI (match_operand 0 "" "") (const_int 8))) 4277 ;; store the high byte 4278 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe 4279 "TARGET_ARM" 4280 " 4281 { 4282 rtx op1 = operands[1]; 4283 rtx addr = XEXP (op1, 0); 4284 enum rtx_code code = GET_CODE (addr); 4285 4286 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT) 4287 || code == MINUS) 4288 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr)); 4289 4290 operands[4] = adjust_address (op1, QImode, 1); 4291 operands[1] = adjust_address (operands[1], QImode, 0); 4292 operands[3] = gen_lowpart (QImode, operands[0]); 4293 operands[0] = gen_lowpart (SImode, operands[0]); 4294 operands[2] = gen_reg_rtx (SImode); 4295 }" 4296) 4297 4298(define_expand "storehi_bigend" 4299 [(set (match_dup 4) (match_dup 3)) 4300 (set (match_dup 2) 4301 (ashiftrt:SI (match_operand 0 "" "") (const_int 8))) 4302 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 3))] 4303 "TARGET_ARM" 4304 " 4305 { 4306 rtx op1 = operands[1]; 4307 rtx addr = XEXP (op1, 0); 4308 enum rtx_code code = GET_CODE (addr); 4309 4310 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT) 4311 || code == MINUS) 4312 op1 = replace_equiv_address (op1, force_reg (SImode, addr)); 4313 4314 operands[4] = adjust_address (op1, QImode, 1); 4315 operands[1] = adjust_address (operands[1], QImode, 0); 4316 operands[3] = gen_lowpart (QImode, operands[0]); 4317 operands[0] = gen_lowpart (SImode, operands[0]); 4318 operands[2] = gen_reg_rtx (SImode); 4319 }" 4320) 4321 4322;; Subroutine to store a half word integer constant into memory. 4323(define_expand "storeinthi" 4324 [(set (match_operand 0 "" "") 4325 (subreg:QI (match_operand 1 "" "") 0)) 4326 (set (match_dup 3) (match_dup 2))] 4327 "TARGET_ARM" 4328 " 4329 { 4330 HOST_WIDE_INT value = INTVAL (operands[1]); 4331 rtx addr = XEXP (operands[0], 0); 4332 rtx op0 = operands[0]; 4333 enum rtx_code code = GET_CODE (addr); 4334 4335 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT) 4336 || code == MINUS) 4337 op0 = replace_equiv_address (op0, force_reg (SImode, addr)); 4338 4339 operands[1] = gen_reg_rtx (SImode); 4340 if (BYTES_BIG_ENDIAN) 4341 { 4342 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255))); 4343 if ((value & 255) == ((value >> 8) & 255)) 4344 operands[2] = operands[1]; 4345 else 4346 { 4347 operands[2] = gen_reg_rtx (SImode); 4348 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255))); 4349 } 4350 } 4351 else 4352 { 4353 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255))); 4354 if ((value & 255) == ((value >> 8) & 255)) 4355 operands[2] = operands[1]; 4356 else 4357 { 4358 operands[2] = gen_reg_rtx (SImode); 4359 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255))); 4360 } 4361 } 4362 4363 operands[3] = adjust_address (op0, QImode, 1); 4364 operands[0] = adjust_address (operands[0], QImode, 0); 4365 operands[2] = gen_lowpart (QImode, operands[2]); 4366 }" 4367) 4368 4369(define_expand "storehi_single_op" 4370 [(set (match_operand:HI 0 "memory_operand" "") 4371 (match_operand:HI 1 "general_operand" ""))] 4372 "TARGET_ARM && arm_arch4" 4373 " 4374 if (!s_register_operand (operands[1], HImode)) 4375 operands[1] = copy_to_mode_reg (HImode, operands[1]); 4376 " 4377) 4378 4379(define_expand "movhi" 4380 [(set (match_operand:HI 0 "general_operand" "") 4381 (match_operand:HI 1 "general_operand" ""))] 4382 "TARGET_EITHER" 4383 " 4384 if (TARGET_ARM) 4385 { 4386 if (!no_new_pseudos) 4387 { 4388 if (GET_CODE (operands[0]) == MEM) 4389 { 4390 if (arm_arch4) 4391 { 4392 emit_insn (gen_storehi_single_op (operands[0], operands[1])); 4393 DONE; 4394 } 4395 if (GET_CODE (operands[1]) == CONST_INT) 4396 emit_insn (gen_storeinthi (operands[0], operands[1])); 4397 else 4398 { 4399 if (GET_CODE (operands[1]) == MEM) 4400 operands[1] = force_reg (HImode, operands[1]); 4401 if (BYTES_BIG_ENDIAN) 4402 emit_insn (gen_storehi_bigend (operands[1], operands[0])); 4403 else 4404 emit_insn (gen_storehi (operands[1], operands[0])); 4405 } 4406 DONE; 4407 } 4408 /* Sign extend a constant, and keep it in an SImode reg. */ 4409 else if (GET_CODE (operands[1]) == CONST_INT) 4410 { 4411 rtx reg = gen_reg_rtx (SImode); 4412 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff; 4413 4414 /* If the constant is already valid, leave it alone. */ 4415 if (!const_ok_for_arm (val)) 4416 { 4417 /* If setting all the top bits will make the constant 4418 loadable in a single instruction, then set them. 4419 Otherwise, sign extend the number. */ 4420 4421 if (const_ok_for_arm (~(val | ~0xffff))) 4422 val |= ~0xffff; 4423 else if (val & 0x8000) 4424 val |= ~0xffff; 4425 } 4426 4427 emit_insn (gen_movsi (reg, GEN_INT (val))); 4428 operands[1] = gen_lowpart (HImode, reg); 4429 } 4430 else if (arm_arch4 && !no_new_pseudos && optimize > 0 4431 && GET_CODE (operands[1]) == MEM) 4432 { 4433 rtx reg = gen_reg_rtx (SImode); 4434 4435 emit_insn (gen_zero_extendhisi2 (reg, operands[1])); 4436 operands[1] = gen_lowpart (HImode, reg); 4437 } 4438 else if (!arm_arch4) 4439 { 4440 /* Note: We do not have to worry about TARGET_MMU_TRAPS 4441 for v4 and up architectures because LDRH instructions will 4442 be used to access the HI values, and these cannot generate 4443 unaligned word access faults in the MMU. */ 4444 if (GET_CODE (operands[1]) == MEM) 4445 { 4446 if (TARGET_MMU_TRAPS) 4447 { 4448 rtx base; 4449 rtx offset = const0_rtx; 4450 rtx reg = gen_reg_rtx (SImode); 4451 4452 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG 4453 || (GET_CODE (base) == PLUS 4454 && (GET_CODE (offset = XEXP (base, 1)) 4455 == CONST_INT) 4456 && ((INTVAL(offset) & 1) != 1) 4457 && GET_CODE (base = XEXP (base, 0)) == REG)) 4458 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32) 4459 { 4460 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3; 4461 rtx new; 4462 4463 new = gen_rtx_MEM (SImode, 4464 plus_constant (base, new_offset)); 4465 MEM_COPY_ATTRIBUTES (new, operands[1]); 4466 emit_insn (gen_movsi (reg, new)); 4467 if (((INTVAL (offset) & 2) != 0) 4468 ^ (BYTES_BIG_ENDIAN ? 1 : 0)) 4469 { 4470 rtx reg2 = gen_reg_rtx (SImode); 4471 4472 emit_insn (gen_lshrsi3 (reg2, reg, 4473 GEN_INT (16))); 4474 reg = reg2; 4475 } 4476 } 4477 else 4478 emit_insn (gen_movhi_bytes (reg, operands[1])); 4479 4480 operands[1] = gen_lowpart (HImode, reg); 4481 } 4482 else if (BYTES_BIG_ENDIAN) 4483 { 4484 rtx base; 4485 rtx offset = const0_rtx; 4486 4487 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG 4488 || (GET_CODE (base) == PLUS 4489 && (GET_CODE (offset = XEXP (base, 1)) 4490 == CONST_INT) 4491 && GET_CODE (base = XEXP (base, 0)) == REG)) 4492 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32) 4493 { 4494 rtx reg = gen_reg_rtx (SImode); 4495 rtx new; 4496 4497 if ((INTVAL (offset) & 2) == 2) 4498 { 4499 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2; 4500 new = gen_rtx_MEM (SImode, 4501 plus_constant (base, 4502 new_offset)); 4503 MEM_COPY_ATTRIBUTES (new, operands[1]); 4504 emit_insn (gen_movsi (reg, new)); 4505 } 4506 else 4507 { 4508 new = gen_rtx_MEM (SImode, 4509 XEXP (operands[1], 0)); 4510 MEM_COPY_ATTRIBUTES (new, operands[1]); 4511 emit_insn (gen_rotated_loadsi (reg, new)); 4512 } 4513 4514 operands[1] = gen_lowpart (HImode, reg); 4515 } 4516 else 4517 { 4518 emit_insn (gen_movhi_bigend (operands[0], 4519 operands[1])); 4520 DONE; 4521 } 4522 } 4523 } 4524 } 4525 } 4526 /* Handle loading a large integer during reload */ 4527 else if (GET_CODE (operands[1]) == CONST_INT 4528 && !const_ok_for_arm (INTVAL (operands[1])) 4529 && !const_ok_for_arm (~INTVAL (operands[1]))) 4530 { 4531 /* Writing a constant to memory needs a scratch, which should 4532 be handled with SECONDARY_RELOADs. */ 4533 if (GET_CODE (operands[0]) != REG) 4534 abort (); 4535 4536 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0); 4537 emit_insn (gen_movsi (operands[0], operands[1])); 4538 DONE; 4539 } 4540 } 4541 else /* TARGET_THUMB */ 4542 { 4543 if (!no_new_pseudos) 4544 { 4545 if (GET_CODE (operands[0]) != REG) 4546 operands[1] = force_reg (HImode, operands[1]); 4547 4548 /* ??? We shouldn't really get invalid addresses here, but this can 4549 happen if we are passed a SP (never OK for HImode/QImode) or 4550 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 4551 HImode/QImode) relative address. */ 4552 /* ??? This should perhaps be fixed elsewhere, for instance, in 4553 fixup_stack_1, by checking for other kinds of invalid addresses, 4554 e.g. a bare reference to a virtual register. This may confuse the 4555 alpha though, which must handle this case differently. */ 4556 if (GET_CODE (operands[0]) == MEM 4557 && !memory_address_p (GET_MODE (operands[0]), 4558 XEXP (operands[0], 0))) 4559 operands[0] 4560 = replace_equiv_address (operands[0], 4561 copy_to_reg (XEXP (operands[0], 0))); 4562 4563 if (GET_CODE (operands[1]) == MEM 4564 && !memory_address_p (GET_MODE (operands[1]), 4565 XEXP (operands[1], 0))) 4566 operands[1] 4567 = replace_equiv_address (operands[1], 4568 copy_to_reg (XEXP (operands[1], 0))); 4569 } 4570 /* Handle loading a large integer during reload */ 4571 else if (GET_CODE (operands[1]) == CONST_INT 4572 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I')) 4573 { 4574 /* Writing a constant to memory needs a scratch, which should 4575 be handled with SECONDARY_RELOADs. */ 4576 if (GET_CODE (operands[0]) != REG) 4577 abort (); 4578 4579 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0); 4580 emit_insn (gen_movsi (operands[0], operands[1])); 4581 DONE; 4582 } 4583 } 4584 " 4585) 4586 4587(define_insn "*thumb_movhi_insn" 4588 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l") 4589 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))] 4590 "TARGET_THUMB 4591 && ( register_operand (operands[0], HImode) 4592 || register_operand (operands[1], HImode))" 4593 "* 4594 switch (which_alternative) 4595 { 4596 case 0: return \"add %0, %1, #0\"; 4597 case 2: return \"strh %1, %0\"; 4598 case 3: return \"mov %0, %1\"; 4599 case 4: return \"mov %0, %1\"; 4600 case 5: return \"mov %0, %1\"; 4601 default: abort (); 4602 case 1: 4603 /* The stack pointer can end up being taken as an index register. 4604 Catch this case here and deal with it. */ 4605 if (GET_CODE (XEXP (operands[1], 0)) == PLUS 4606 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG 4607 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM) 4608 { 4609 rtx ops[2]; 4610 ops[0] = operands[0]; 4611 ops[1] = XEXP (XEXP (operands[1], 0), 0); 4612 4613 output_asm_insn (\"mov %0, %1\", ops); 4614 4615 XEXP (XEXP (operands[1], 0), 0) = operands[0]; 4616 4617 } 4618 return \"ldrh %0, %1\"; 4619 }" 4620 [(set_attr "length" "2,4,2,2,2,2") 4621 (set_attr "type" "*,load,store1,*,*,*") 4622 (set_attr "pool_range" "*,64,*,*,*,*")] 4623) 4624 4625 4626(define_insn "rotated_loadsi" 4627 [(set (match_operand:SI 0 "s_register_operand" "=r") 4628 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o") 4629 (const_int 16)))] 4630 "TARGET_ARM && (!TARGET_MMU_TRAPS)" 4631 "* 4632 { 4633 rtx ops[2]; 4634 4635 ops[0] = operands[0]; 4636 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2)); 4637 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops); 4638 return \"\"; 4639 }" 4640 [(set_attr "type" "load") 4641 (set_attr "predicable" "yes")] 4642) 4643 4644(define_expand "movhi_bytes" 4645 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" ""))) 4646 (set (match_dup 3) 4647 (zero_extend:SI (match_dup 6))) 4648 (set (match_operand:SI 0 "" "") 4649 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))] 4650 "TARGET_ARM" 4651 " 4652 { 4653 rtx mem1, mem2; 4654 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); 4655 4656 mem1 = gen_rtx_MEM (QImode, addr); 4657 MEM_COPY_ATTRIBUTES (mem1, operands[1]); 4658 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1)); 4659 MEM_COPY_ATTRIBUTES (mem2, operands[1]); 4660 operands[0] = gen_lowpart (SImode, operands[0]); 4661 operands[1] = mem1; 4662 operands[2] = gen_reg_rtx (SImode); 4663 operands[3] = gen_reg_rtx (SImode); 4664 operands[6] = mem2; 4665 4666 if (BYTES_BIG_ENDIAN) 4667 { 4668 operands[4] = operands[2]; 4669 operands[5] = operands[3]; 4670 } 4671 else 4672 { 4673 operands[4] = operands[3]; 4674 operands[5] = operands[2]; 4675 } 4676 }" 4677) 4678 4679(define_expand "movhi_bigend" 4680 [(set (match_dup 2) 4681 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0) 4682 (const_int 16))) 4683 (set (match_dup 3) 4684 (ashiftrt:SI (match_dup 2) (const_int 16))) 4685 (set (match_operand:HI 0 "s_register_operand" "") 4686 (subreg:HI (match_dup 3) 0))] 4687 "TARGET_ARM" 4688 " 4689 operands[2] = gen_reg_rtx (SImode); 4690 operands[3] = gen_reg_rtx (SImode); 4691 " 4692) 4693 4694;; Pattern to recognize insn generated default case above 4695(define_insn "*movhi_insn_arch4" 4696 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r") 4697 (match_operand:HI 1 "general_operand" "rI,K,r,m"))] 4698 "TARGET_ARM 4699 && arm_arch4 4700 && (GET_CODE (operands[1]) != CONST_INT 4701 || const_ok_for_arm (INTVAL (operands[1])) 4702 || const_ok_for_arm (~INTVAL (operands[1])))" 4703 "@ 4704 mov%?\\t%0, %1\\t%@ movhi 4705 mvn%?\\t%0, #%B1\\t%@ movhi 4706 str%?h\\t%1, %0\\t%@ movhi 4707 ldr%?h\\t%0, %1\\t%@ movhi" 4708 [(set_attr "type" "*,*,store1,load") 4709 (set_attr "predicable" "yes") 4710 (set_attr "pool_range" "*,*,*,256") 4711 (set_attr "neg_pool_range" "*,*,*,244")] 4712) 4713 4714(define_insn "*movhi_insn_littleend" 4715 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r") 4716 (match_operand:HI 1 "general_operand" "rI,K,m"))] 4717 "TARGET_ARM 4718 && !arm_arch4 4719 && !BYTES_BIG_ENDIAN 4720 && !TARGET_MMU_TRAPS 4721 && (GET_CODE (operands[1]) != CONST_INT 4722 || const_ok_for_arm (INTVAL (operands[1])) 4723 || const_ok_for_arm (~INTVAL (operands[1])))" 4724 "@ 4725 mov%?\\t%0, %1\\t%@ movhi 4726 mvn%?\\t%0, #%B1\\t%@ movhi 4727 ldr%?\\t%0, %1\\t%@ movhi" 4728 [(set_attr "type" "*,*,load") 4729 (set_attr "predicable" "yes") 4730 (set_attr "pool_range" "4096") 4731 (set_attr "neg_pool_range" "4084")] 4732) 4733 4734(define_insn "*movhi_insn_bigend" 4735 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r") 4736 (match_operand:HI 1 "general_operand" "rI,K,m"))] 4737 "TARGET_ARM 4738 && !arm_arch4 4739 && BYTES_BIG_ENDIAN 4740 && !TARGET_MMU_TRAPS 4741 && (GET_CODE (operands[1]) != CONST_INT 4742 || const_ok_for_arm (INTVAL (operands[1])) 4743 || const_ok_for_arm (~INTVAL (operands[1])))" 4744 "@ 4745 mov%?\\t%0, %1\\t%@ movhi 4746 mvn%?\\t%0, #%B1\\t%@ movhi 4747 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16" 4748 [(set_attr "type" "*,*,load") 4749 (set_attr "predicable" "yes") 4750 (set_attr "length" "4,4,8") 4751 (set_attr "pool_range" "*,*,4092") 4752 (set_attr "neg_pool_range" "*,*,4084")] 4753) 4754 4755(define_insn "*loadhi_si_bigend" 4756 [(set (match_operand:SI 0 "s_register_operand" "=r") 4757 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0) 4758 (const_int 16)))] 4759 "TARGET_ARM 4760 && BYTES_BIG_ENDIAN 4761 && !TARGET_MMU_TRAPS" 4762 "ldr%?\\t%0, %1\\t%@ movhi_bigend" 4763 [(set_attr "type" "load") 4764 (set_attr "predicable" "yes") 4765 (set_attr "pool_range" "4096") 4766 (set_attr "neg_pool_range" "4084")] 4767) 4768 4769(define_insn "*movhi_bytes" 4770 [(set (match_operand:HI 0 "s_register_operand" "=r,r") 4771 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))] 4772 "TARGET_ARM && TARGET_MMU_TRAPS" 4773 "@ 4774 mov%?\\t%0, %1\\t%@ movhi 4775 mvn%?\\t%0, #%B1\\t%@ movhi" 4776 [(set_attr "predicable" "yes")] 4777) 4778 4779(define_insn "thumb_movhi_clobber" 4780 [(set (match_operand:HI 0 "memory_operand" "=m") 4781 (match_operand:HI 1 "register_operand" "l")) 4782 (clobber (match_operand:SI 2 "register_operand" "=&l"))] 4783 "TARGET_THUMB" 4784 "* 4785 abort ();" 4786) 4787 4788;; We use a DImode scratch because we may occasionally need an additional 4789;; temporary if the address isn't offsettable -- push_reload doesn't seem 4790;; to take any notice of the "o" constraints on reload_memory_operand operand. 4791(define_expand "reload_outhi" 4792 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o") 4793 (match_operand:HI 1 "s_register_operand" "r") 4794 (match_operand:DI 2 "s_register_operand" "=&l")])] 4795 "TARGET_EITHER" 4796 "if (TARGET_ARM) 4797 arm_reload_out_hi (operands); 4798 else 4799 thumb_reload_out_hi (operands); 4800 DONE; 4801 " 4802) 4803 4804(define_expand "reload_inhi" 4805 [(parallel [(match_operand:HI 0 "s_register_operand" "=r") 4806 (match_operand:HI 1 "arm_reload_memory_operand" "o") 4807 (match_operand:DI 2 "s_register_operand" "=&r")])] 4808 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)" 4809 " 4810 if (TARGET_ARM) 4811 arm_reload_in_hi (operands); 4812 else 4813 thumb_reload_out_hi (operands); 4814 DONE; 4815") 4816 4817(define_expand "movqi" 4818 [(set (match_operand:QI 0 "general_operand" "") 4819 (match_operand:QI 1 "general_operand" ""))] 4820 "TARGET_EITHER" 4821 " 4822 if (TARGET_ARM) 4823 { 4824 /* Everything except mem = const or mem = mem can be done easily */ 4825 4826 if (!no_new_pseudos) 4827 { 4828 if (GET_CODE (operands[1]) == CONST_INT) 4829 { 4830 rtx reg = gen_reg_rtx (SImode); 4831 4832 emit_insn (gen_movsi (reg, operands[1])); 4833 operands[1] = gen_lowpart (QImode, reg); 4834 } 4835 if (GET_CODE (operands[1]) == MEM && optimize > 0) 4836 { 4837 rtx reg = gen_reg_rtx (SImode); 4838 4839 emit_insn (gen_zero_extendqisi2 (reg, operands[1])); 4840 operands[1] = gen_lowpart (QImode, reg); 4841 } 4842 if (GET_CODE (operands[0]) == MEM) 4843 operands[1] = force_reg (QImode, operands[1]); 4844 } 4845 } 4846 else /* TARGET_THUMB */ 4847 { 4848 if (!no_new_pseudos) 4849 { 4850 if (GET_CODE (operands[0]) != REG) 4851 operands[1] = force_reg (QImode, operands[1]); 4852 4853 /* ??? We shouldn't really get invalid addresses here, but this can 4854 happen if we are passed a SP (never OK for HImode/QImode) or 4855 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 4856 HImode/QImode) relative address. */ 4857 /* ??? This should perhaps be fixed elsewhere, for instance, in 4858 fixup_stack_1, by checking for other kinds of invalid addresses, 4859 e.g. a bare reference to a virtual register. This may confuse the 4860 alpha though, which must handle this case differently. */ 4861 if (GET_CODE (operands[0]) == MEM 4862 && !memory_address_p (GET_MODE (operands[0]), 4863 XEXP (operands[0], 0))) 4864 operands[0] 4865 = replace_equiv_address (operands[0], 4866 copy_to_reg (XEXP (operands[0], 0))); 4867 if (GET_CODE (operands[1]) == MEM 4868 && !memory_address_p (GET_MODE (operands[1]), 4869 XEXP (operands[1], 0))) 4870 operands[1] 4871 = replace_equiv_address (operands[1], 4872 copy_to_reg (XEXP (operands[1], 0))); 4873 } 4874 /* Handle loading a large integer during reload */ 4875 else if (GET_CODE (operands[1]) == CONST_INT 4876 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I')) 4877 { 4878 /* Writing a constant to memory needs a scratch, which should 4879 be handled with SECONDARY_RELOADs. */ 4880 if (GET_CODE (operands[0]) != REG) 4881 abort (); 4882 4883 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0); 4884 emit_insn (gen_movsi (operands[0], operands[1])); 4885 DONE; 4886 } 4887 } 4888 " 4889) 4890 4891 4892(define_insn "*arm_movqi_insn" 4893 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m") 4894 (match_operand:QI 1 "general_operand" "rI,K,m,r"))] 4895 "TARGET_ARM 4896 && ( register_operand (operands[0], QImode) 4897 || register_operand (operands[1], QImode))" 4898 "@ 4899 mov%?\\t%0, %1 4900 mvn%?\\t%0, #%B1 4901 ldr%?b\\t%0, %1 4902 str%?b\\t%1, %0" 4903 [(set_attr "type" "*,*,load,store1") 4904 (set_attr "predicable" "yes")] 4905) 4906 4907(define_insn "*thumb_movqi_insn" 4908 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l") 4909 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))] 4910 "TARGET_THUMB 4911 && ( register_operand (operands[0], QImode) 4912 || register_operand (operands[1], QImode))" 4913 "@ 4914 add\\t%0, %1, #0 4915 ldrb\\t%0, %1 4916 strb\\t%1, %0 4917 mov\\t%0, %1 4918 mov\\t%0, %1 4919 mov\\t%0, %1" 4920 [(set_attr "length" "2") 4921 (set_attr "type" "*,load,store1,*,*,*") 4922 (set_attr "pool_range" "*,32,*,*,*,*")] 4923) 4924 4925(define_expand "movsf" 4926 [(set (match_operand:SF 0 "general_operand" "") 4927 (match_operand:SF 1 "general_operand" ""))] 4928 "TARGET_EITHER" 4929 " 4930 if (TARGET_ARM) 4931 { 4932 if (GET_CODE (operands[0]) == MEM) 4933 operands[1] = force_reg (SFmode, operands[1]); 4934 } 4935 else /* TARGET_THUMB */ 4936 { 4937 if (!no_new_pseudos) 4938 { 4939 if (GET_CODE (operands[0]) != REG) 4940 operands[1] = force_reg (SFmode, operands[1]); 4941 } 4942 } 4943 " 4944) 4945 4946(define_split 4947 [(set (match_operand:SF 0 "nonimmediate_operand" "") 4948 (match_operand:SF 1 "immediate_operand" ""))] 4949 "TARGET_ARM 4950 && !TARGET_HARD_FLOAT 4951 && reload_completed 4952 && GET_CODE (operands[1]) == CONST_DOUBLE" 4953 [(set (match_dup 2) (match_dup 3))] 4954 " 4955 operands[2] = gen_lowpart (SImode, operands[0]); 4956 operands[3] = gen_lowpart (SImode, operands[1]); 4957 if (operands[2] == 0 || operands[3] == 0) 4958 FAIL; 4959 " 4960) 4961 4962(define_insn "*arm_movsf_hard_insn" 4963 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m") 4964 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))] 4965 "TARGET_ARM 4966 && TARGET_HARD_FLOAT 4967 && (GET_CODE (operands[0]) != MEM 4968 || register_operand (operands[1], SFmode))" 4969 "@ 4970 mvf%?s\\t%0, %1 4971 mnf%?s\\t%0, #%N1 4972 ldf%?s\\t%0, %1 4973 stf%?s\\t%1, %0 4974 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4 4975 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4 4976 mov%?\\t%0, %1 4977 ldr%?\\t%0, %1\\t%@ float 4978 str%?\\t%1, %0\\t%@ float" 4979 [(set_attr "length" "4,4,4,4,8,8,4,4,4") 4980 (set_attr "predicable" "yes") 4981 (set_attr "type" 4982 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1") 4983 (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*") 4984 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")] 4985) 4986 4987;; Exactly the same as above, except that all `f' cases are deleted. 4988;; This is necessary to prevent reload from ever trying to use a `f' reg 4989;; when -msoft-float. 4990 4991(define_insn "*arm_movsf_soft_insn" 4992 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m") 4993 (match_operand:SF 1 "general_operand" "r,mE,r"))] 4994 "TARGET_ARM 4995 && TARGET_SOFT_FLOAT 4996 && (GET_CODE (operands[0]) != MEM 4997 || register_operand (operands[1], SFmode))" 4998 "@ 4999 mov%?\\t%0, %1 5000 ldr%?\\t%0, %1\\t%@ float 5001 str%?\\t%1, %0\\t%@ float" 5002 [(set_attr "length" "4,4,4") 5003 (set_attr "predicable" "yes") 5004 (set_attr "type" "*,load,store1") 5005 (set_attr "pool_range" "*,4096,*") 5006 (set_attr "neg_pool_range" "*,4084,*")] 5007) 5008 5009;;; ??? This should have alternatives for constants. 5010(define_insn "*thumb_movsf_insn" 5011 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h") 5012 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))] 5013 "TARGET_THUMB 5014 && ( register_operand (operands[0], SFmode) 5015 || register_operand (operands[1], SFmode))" 5016 "@ 5017 add\\t%0, %1, #0 5018 ldmia\\t%1, {%0} 5019 stmia\\t%0, {%1} 5020 ldr\\t%0, %1 5021 str\\t%1, %0 5022 mov\\t%0, %1 5023 mov\\t%0, %1" 5024 [(set_attr "length" "2") 5025 (set_attr "type" "*,load,store1,load,store1,*,*") 5026 (set_attr "pool_range" "*,*,*,1020,*,*,*")] 5027) 5028 5029(define_expand "movdf" 5030 [(set (match_operand:DF 0 "general_operand" "") 5031 (match_operand:DF 1 "general_operand" ""))] 5032 "TARGET_EITHER" 5033 " 5034 if (TARGET_ARM) 5035 { 5036 if (GET_CODE (operands[0]) == MEM) 5037 operands[1] = force_reg (DFmode, operands[1]); 5038 } 5039 else /* TARGET_THUMB */ 5040 { 5041 if (!no_new_pseudos) 5042 { 5043 if (GET_CODE (operands[0]) != REG) 5044 operands[1] = force_reg (DFmode, operands[1]); 5045 } 5046 } 5047 " 5048) 5049 5050;; Reloading a df mode value stored in integer regs to memory can require a 5051;; scratch reg. 5052(define_expand "reload_outdf" 5053 [(match_operand:DF 0 "arm_reload_memory_operand" "=o") 5054 (match_operand:DF 1 "s_register_operand" "r") 5055 (match_operand:SI 2 "s_register_operand" "=&r")] 5056 "TARGET_ARM" 5057 " 5058 { 5059 enum rtx_code code = GET_CODE (XEXP (operands[0], 0)); 5060 5061 if (code == REG) 5062 operands[2] = XEXP (operands[0], 0); 5063 else if (code == POST_INC || code == PRE_DEC) 5064 { 5065 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); 5066 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0); 5067 emit_insn (gen_movdi (operands[0], operands[1])); 5068 DONE; 5069 } 5070 else if (code == PRE_INC) 5071 { 5072 rtx reg = XEXP (XEXP (operands[0], 0), 0); 5073 5074 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8))); 5075 operands[2] = reg; 5076 } 5077 else if (code == POST_DEC) 5078 operands[2] = XEXP (XEXP (operands[0], 0), 0); 5079 else 5080 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0), 5081 XEXP (XEXP (operands[0], 0), 1))); 5082 5083 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]), 5084 operands[1])); 5085 5086 if (code == POST_DEC) 5087 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8))); 5088 5089 DONE; 5090 }" 5091) 5092 5093(define_insn "*movdf_hard_insn" 5094 [(set (match_operand:DF 0 "nonimmediate_operand" 5095 "=r,Q,r,m,r, f, f,f, m,!f,!r") 5096 (match_operand:DF 1 "general_operand" 5097 "Q, r,r,r,mF,fG,H,mF,f,r, f"))] 5098 "TARGET_ARM 5099 && TARGET_HARD_FLOAT 5100 && (GET_CODE (operands[0]) != MEM 5101 || register_operand (operands[1], DFmode))" 5102 "* 5103 { 5104 switch (which_alternative) 5105 { 5106 default: 5107 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\"; 5108 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\"; 5109 case 2: case 3: case 4: return output_move_double (operands); 5110 case 5: return \"mvf%?d\\t%0, %1\"; 5111 case 6: return \"mnf%?d\\t%0, #%N1\"; 5112 case 7: return \"ldf%?d\\t%0, %1\"; 5113 case 8: return \"stf%?d\\t%1, %0\"; 5114 case 9: return output_mov_double_fpu_from_arm (operands); 5115 case 10: return output_mov_double_arm_from_fpu (operands); 5116 } 5117 } 5118 " 5119 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8") 5120 (set_attr "predicable" "yes") 5121 (set_attr "type" 5122 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r") 5123 (set_attr "pool_range" "*,*,*,*,1020,*,*,1024,*,*,*") 5124 (set_attr "neg_pool_range" "*,*,*,*,1008,*,*,1008,*,*,*")] 5125) 5126 5127;; Software floating point version. This is essentially the same as movdi. 5128;; Do not use `f' as a constraint to prevent reload from ever trying to use 5129;; an `f' reg. 5130 5131(define_insn "*movdf_soft_insn" 5132 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m") 5133 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))] 5134 "TARGET_ARM && TARGET_SOFT_FLOAT 5135 " 5136 "* return output_move_double (operands);" 5137 [(set_attr "length" "8,8,8") 5138 (set_attr "type" "*,load,store2") 5139 (set_attr "pool_range" "1020") 5140 (set_attr "neg_pool_range" "1008")] 5141) 5142 5143;;; ??? This should have alternatives for constants. 5144;;; ??? This was originally identical to the movdi_insn pattern. 5145;;; ??? The 'F' constraint looks funny, but it should always be replaced by 5146;;; thumb_reorg with a memory reference. 5147(define_insn "*thumb_movdf_insn" 5148 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r") 5149 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))] 5150 "TARGET_THUMB 5151 && ( register_operand (operands[0], DFmode) 5152 || register_operand (operands[1], DFmode))" 5153 "* 5154 switch (which_alternative) 5155 { 5156 default: 5157 case 0: 5158 if (REGNO (operands[1]) == REGNO (operands[0]) + 1) 5159 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\"; 5160 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\"; 5161 case 1: 5162 return \"ldmia\\t%1, {%0, %H0}\"; 5163 case 2: 5164 return \"stmia\\t%0, {%1, %H1}\"; 5165 case 3: 5166 return thumb_load_double_from_address (operands); 5167 case 4: 5168 operands[2] = gen_rtx (MEM, SImode, 5169 plus_constant (XEXP (operands[0], 0), 4)); 5170 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands); 5171 return \"\"; 5172 case 5: 5173 if (REGNO (operands[1]) == REGNO (operands[0]) + 1) 5174 return \"mov\\t%0, %1\;mov\\t%H0, %H1\"; 5175 return \"mov\\t%H0, %H1\;mov\\t%0, %1\"; 5176 } 5177 " 5178 [(set_attr "length" "4,2,2,6,4,4") 5179 (set_attr "type" "*,load,store2,load,store2,*") 5180 (set_attr "pool_range" "*,*,*,1020,*,*")] 5181) 5182 5183 5184(define_expand "movxf" 5185 [(set (match_operand:XF 0 "general_operand" "") 5186 (match_operand:XF 1 "general_operand" ""))] 5187 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 5188 "") 5189 5190;; Even when the XFmode patterns aren't enabled, we enable this after 5191;; reloading so that we can push floating point registers in the prologue. 5192 5193(define_insn "*movxf_hard_insn" 5194 [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r") 5195 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))] 5196 "TARGET_ARM && TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)" 5197 "* 5198 switch (which_alternative) 5199 { 5200 default: 5201 case 0: return \"mvf%?e\\t%0, %1\"; 5202 case 1: return \"mnf%?e\\t%0, #%N1\"; 5203 case 2: return \"ldf%?e\\t%0, %1\"; 5204 case 3: return \"stf%?e\\t%1, %0\"; 5205 case 4: return output_mov_long_double_fpu_from_arm (operands); 5206 case 5: return output_mov_long_double_arm_from_fpu (operands); 5207 case 6: return output_mov_long_double_arm_from_arm (operands); 5208 } 5209 " 5210 [(set_attr "length" "4,4,4,4,8,8,12") 5211 (set_attr "predicable" "yes") 5212 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*") 5213 (set_attr "pool_range" "*,*,1024,*,*,*,*") 5214 (set_attr "neg_pool_range" "*,*,1004,*,*,*,*")] 5215) 5216 5217 5218;; load- and store-multiple insns 5219;; The arm can load/store any set of registers, provided that they are in 5220;; ascending order; but that is beyond GCC so stick with what it knows. 5221 5222(define_expand "load_multiple" 5223 [(match_par_dup 3 [(set (match_operand:SI 0 "" "") 5224 (match_operand:SI 1 "" "")) 5225 (use (match_operand:SI 2 "" ""))])] 5226 "TARGET_ARM" 5227 " 5228 /* Support only fixed point registers. */ 5229 if (GET_CODE (operands[2]) != CONST_INT 5230 || INTVAL (operands[2]) > 14 5231 || INTVAL (operands[2]) < 2 5232 || GET_CODE (operands[1]) != MEM 5233 || GET_CODE (operands[0]) != REG 5234 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1) 5235 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM) 5236 FAIL; 5237 5238 operands[3] 5239 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]), 5240 force_reg (SImode, XEXP (operands[1], 0)), 5241 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]), 5242 MEM_IN_STRUCT_P(operands[1]), 5243 MEM_SCALAR_P (operands[1])); 5244 " 5245) 5246 5247;; Load multiple with write-back 5248 5249(define_insn "*ldmsi_postinc4" 5250 [(match_parallel 0 "load_multiple_operation" 5251 [(set (match_operand:SI 1 "s_register_operand" "=r") 5252 (plus:SI (match_operand:SI 2 "s_register_operand" "1") 5253 (const_int 16))) 5254 (set (match_operand:SI 3 "arm_hard_register_operand" "") 5255 (mem:SI (match_dup 2))) 5256 (set (match_operand:SI 4 "arm_hard_register_operand" "") 5257 (mem:SI (plus:SI (match_dup 2) (const_int 4)))) 5258 (set (match_operand:SI 5 "arm_hard_register_operand" "") 5259 (mem:SI (plus:SI (match_dup 2) (const_int 8)))) 5260 (set (match_operand:SI 6 "arm_hard_register_operand" "") 5261 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])] 5262 "TARGET_ARM && XVECLEN (operands[0], 0) == 5" 5263 "ldm%?ia\\t%1!, {%3, %4, %5, %6}" 5264 [(set_attr "type" "load") 5265 (set_attr "predicable" "yes")] 5266) 5267 5268(define_insn "*ldmsi_postinc3" 5269 [(match_parallel 0 "load_multiple_operation" 5270 [(set (match_operand:SI 1 "s_register_operand" "=r") 5271 (plus:SI (match_operand:SI 2 "s_register_operand" "1") 5272 (const_int 12))) 5273 (set (match_operand:SI 3 "arm_hard_register_operand" "") 5274 (mem:SI (match_dup 2))) 5275 (set (match_operand:SI 4 "arm_hard_register_operand" "") 5276 (mem:SI (plus:SI (match_dup 2) (const_int 4)))) 5277 (set (match_operand:SI 5 "arm_hard_register_operand" "") 5278 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])] 5279 "TARGET_ARM && XVECLEN (operands[0], 0) == 4" 5280 "ldm%?ia\\t%1!, {%3, %4, %5}" 5281 [(set_attr "type" "load") 5282 (set_attr "predicable" "yes")] 5283) 5284 5285(define_insn "*ldmsi_postinc2" 5286 [(match_parallel 0 "load_multiple_operation" 5287 [(set (match_operand:SI 1 "s_register_operand" "=r") 5288 (plus:SI (match_operand:SI 2 "s_register_operand" "1") 5289 (const_int 8))) 5290 (set (match_operand:SI 3 "arm_hard_register_operand" "") 5291 (mem:SI (match_dup 2))) 5292 (set (match_operand:SI 4 "arm_hard_register_operand" "") 5293 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])] 5294 "TARGET_ARM && XVECLEN (operands[0], 0) == 3" 5295 "ldm%?ia\\t%1!, {%3, %4}" 5296 [(set_attr "type" "load") 5297 (set_attr "predicable" "yes")] 5298) 5299 5300;; Ordinary load multiple 5301 5302(define_insn "*ldmsi4" 5303 [(match_parallel 0 "load_multiple_operation" 5304 [(set (match_operand:SI 2 "arm_hard_register_operand" "") 5305 (mem:SI (match_operand:SI 1 "s_register_operand" "r"))) 5306 (set (match_operand:SI 3 "arm_hard_register_operand" "") 5307 (mem:SI (plus:SI (match_dup 1) (const_int 4)))) 5308 (set (match_operand:SI 4 "arm_hard_register_operand" "") 5309 (mem:SI (plus:SI (match_dup 1) (const_int 8)))) 5310 (set (match_operand:SI 5 "arm_hard_register_operand" "") 5311 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])] 5312 "TARGET_ARM && XVECLEN (operands[0], 0) == 4" 5313 "ldm%?ia\\t%1, {%2, %3, %4, %5}" 5314 [(set_attr "type" "load") 5315 (set_attr "predicable" "yes")] 5316) 5317 5318(define_insn "*ldmsi3" 5319 [(match_parallel 0 "load_multiple_operation" 5320 [(set (match_operand:SI 2 "arm_hard_register_operand" "") 5321 (mem:SI (match_operand:SI 1 "s_register_operand" "r"))) 5322 (set (match_operand:SI 3 "arm_hard_register_operand" "") 5323 (mem:SI (plus:SI (match_dup 1) (const_int 4)))) 5324 (set (match_operand:SI 4 "arm_hard_register_operand" "") 5325 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])] 5326 "TARGET_ARM && XVECLEN (operands[0], 0) == 3" 5327 "ldm%?ia\\t%1, {%2, %3, %4}" 5328 [(set_attr "type" "load") 5329 (set_attr "predicable" "yes")] 5330) 5331 5332(define_insn "*ldmsi2" 5333 [(match_parallel 0 "load_multiple_operation" 5334 [(set (match_operand:SI 2 "arm_hard_register_operand" "") 5335 (mem:SI (match_operand:SI 1 "s_register_operand" "r"))) 5336 (set (match_operand:SI 3 "arm_hard_register_operand" "") 5337 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])] 5338 "TARGET_ARM && XVECLEN (operands[0], 0) == 2" 5339 "ldm%?ia\\t%1, {%2, %3}" 5340 [(set_attr "type" "load") 5341 (set_attr "predicable" "yes")] 5342) 5343 5344(define_expand "store_multiple" 5345 [(match_par_dup 3 [(set (match_operand:SI 0 "" "") 5346 (match_operand:SI 1 "" "")) 5347 (use (match_operand:SI 2 "" ""))])] 5348 "TARGET_ARM" 5349 " 5350 /* Support only fixed point registers */ 5351 if (GET_CODE (operands[2]) != CONST_INT 5352 || INTVAL (operands[2]) > 14 5353 || INTVAL (operands[2]) < 2 5354 || GET_CODE (operands[1]) != REG 5355 || GET_CODE (operands[0]) != MEM 5356 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1) 5357 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM) 5358 FAIL; 5359 5360 operands[3] 5361 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]), 5362 force_reg (SImode, XEXP (operands[0], 0)), 5363 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]), 5364 MEM_IN_STRUCT_P(operands[0]), 5365 MEM_SCALAR_P (operands[0])); 5366 " 5367) 5368 5369;; Store multiple with write-back 5370 5371(define_insn "*stmsi_postinc4" 5372 [(match_parallel 0 "store_multiple_operation" 5373 [(set (match_operand:SI 1 "s_register_operand" "=r") 5374 (plus:SI (match_operand:SI 2 "s_register_operand" "1") 5375 (const_int 16))) 5376 (set (mem:SI (match_dup 2)) 5377 (match_operand:SI 3 "arm_hard_register_operand" "")) 5378 (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 5379 (match_operand:SI 4 "arm_hard_register_operand" "")) 5380 (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) 5381 (match_operand:SI 5 "arm_hard_register_operand" "")) 5382 (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) 5383 (match_operand:SI 6 "arm_hard_register_operand" ""))])] 5384 "TARGET_ARM && XVECLEN (operands[0], 0) == 5" 5385 "stm%?ia\\t%1!, {%3, %4, %5, %6}" 5386 [(set_attr "predicable" "yes") 5387 (set_attr "type" "store4")] 5388) 5389 5390(define_insn "*stmsi_postinc3" 5391 [(match_parallel 0 "store_multiple_operation" 5392 [(set (match_operand:SI 1 "s_register_operand" "=r") 5393 (plus:SI (match_operand:SI 2 "s_register_operand" "1") 5394 (const_int 12))) 5395 (set (mem:SI (match_dup 2)) 5396 (match_operand:SI 3 "arm_hard_register_operand" "")) 5397 (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 5398 (match_operand:SI 4 "arm_hard_register_operand" "")) 5399 (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) 5400 (match_operand:SI 5 "arm_hard_register_operand" ""))])] 5401 "TARGET_ARM && XVECLEN (operands[0], 0) == 4" 5402 "stm%?ia\\t%1!, {%3, %4, %5}" 5403 [(set_attr "predicable" "yes") 5404 (set_attr "type" "store3")] 5405) 5406 5407(define_insn "*stmsi_postinc2" 5408 [(match_parallel 0 "store_multiple_operation" 5409 [(set (match_operand:SI 1 "s_register_operand" "=r") 5410 (plus:SI (match_operand:SI 2 "s_register_operand" "1") 5411 (const_int 8))) 5412 (set (mem:SI (match_dup 2)) 5413 (match_operand:SI 3 "arm_hard_register_operand" "")) 5414 (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 5415 (match_operand:SI 4 "arm_hard_register_operand" ""))])] 5416 "TARGET_ARM && XVECLEN (operands[0], 0) == 3" 5417 "stm%?ia\\t%1!, {%3, %4}" 5418 [(set_attr "predicable" "yes") 5419 (set_attr "type" "store2")] 5420) 5421 5422;; Ordinary store multiple 5423 5424(define_insn "*stmsi4" 5425 [(match_parallel 0 "store_multiple_operation" 5426 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r")) 5427 (match_operand:SI 2 "arm_hard_register_operand" "")) 5428 (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) 5429 (match_operand:SI 3 "arm_hard_register_operand" "")) 5430 (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) 5431 (match_operand:SI 4 "arm_hard_register_operand" "")) 5432 (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) 5433 (match_operand:SI 5 "arm_hard_register_operand" ""))])] 5434 "TARGET_ARM && XVECLEN (operands[0], 0) == 4" 5435 "stm%?ia\\t%1, {%2, %3, %4, %5}" 5436 [(set_attr "predicable" "yes") 5437 (set_attr "type" "store4")] 5438) 5439 5440(define_insn "*stmsi3" 5441 [(match_parallel 0 "store_multiple_operation" 5442 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r")) 5443 (match_operand:SI 2 "arm_hard_register_operand" "")) 5444 (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) 5445 (match_operand:SI 3 "arm_hard_register_operand" "")) 5446 (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) 5447 (match_operand:SI 4 "arm_hard_register_operand" ""))])] 5448 "TARGET_ARM && XVECLEN (operands[0], 0) == 3" 5449 "stm%?ia\\t%1, {%2, %3, %4}" 5450 [(set_attr "predicable" "yes") 5451 (set_attr "type" "store3")] 5452) 5453 5454(define_insn "*stmsi2" 5455 [(match_parallel 0 "store_multiple_operation" 5456 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r")) 5457 (match_operand:SI 2 "arm_hard_register_operand" "")) 5458 (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) 5459 (match_operand:SI 3 "arm_hard_register_operand" ""))])] 5460 "TARGET_ARM && XVECLEN (operands[0], 0) == 2" 5461 "stm%?ia\\t%1, {%2, %3}" 5462 [(set_attr "predicable" "yes") 5463 (set_attr "type" "store2")] 5464) 5465 5466;; Move a block of memory if it is word aligned and MORE than 2 words long. 5467;; We could let this apply for blocks of less than this, but it clobbers so 5468;; many registers that there is then probably a better way. 5469 5470(define_expand "movstrqi" 5471 [(match_operand:BLK 0 "general_operand" "") 5472 (match_operand:BLK 1 "general_operand" "") 5473 (match_operand:SI 2 "const_int_operand" "") 5474 (match_operand:SI 3 "const_int_operand" "")] 5475 "TARGET_EITHER" 5476 " 5477 if (TARGET_ARM) 5478 { 5479 if (arm_gen_movstrqi (operands)) 5480 DONE; 5481 FAIL; 5482 } 5483 else /* TARGET_THUMB */ 5484 { 5485 if ( INTVAL (operands[3]) != 4 5486 || INTVAL (operands[2]) > 48) 5487 FAIL; 5488 5489 thumb_expand_movstrqi (operands); 5490 DONE; 5491 } 5492 " 5493) 5494 5495;; Thumb block-move insns 5496 5497(define_insn "movmem12b" 5498 [(set (mem:SI (match_operand:SI 2 "register_operand" "0")) 5499 (mem:SI (match_operand:SI 3 "register_operand" "1"))) 5500 (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 5501 (mem:SI (plus:SI (match_dup 3) (const_int 4)))) 5502 (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) 5503 (mem:SI (plus:SI (match_dup 3) (const_int 8)))) 5504 (set (match_operand:SI 0 "register_operand" "=l") 5505 (plus:SI (match_dup 2) (const_int 12))) 5506 (set (match_operand:SI 1 "register_operand" "=l") 5507 (plus:SI (match_dup 3) (const_int 12))) 5508 (clobber (match_scratch:SI 4 "=&l")) 5509 (clobber (match_scratch:SI 5 "=&l")) 5510 (clobber (match_scratch:SI 6 "=&l"))] 5511 "TARGET_THUMB" 5512 "* return thumb_output_move_mem_multiple (3, operands);" 5513 [(set_attr "length" "4") 5514 ; This isn't entirely accurate... It loads as well, but in terms of 5515 ; scheduling the following insn it is better to consider it as a store 5516 (set_attr "type" "store3")] 5517) 5518 5519(define_insn "movmem8b" 5520 [(set (mem:SI (match_operand:SI 2 "register_operand" "0")) 5521 (mem:SI (match_operand:SI 3 "register_operand" "1"))) 5522 (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 5523 (mem:SI (plus:SI (match_dup 3) (const_int 4)))) 5524 (set (match_operand:SI 0 "register_operand" "=l") 5525 (plus:SI (match_dup 2) (const_int 8))) 5526 (set (match_operand:SI 1 "register_operand" "=l") 5527 (plus:SI (match_dup 3) (const_int 8))) 5528 (clobber (match_scratch:SI 4 "=&l")) 5529 (clobber (match_scratch:SI 5 "=&l"))] 5530 "TARGET_THUMB" 5531 "* return thumb_output_move_mem_multiple (2, operands);" 5532 [(set_attr "length" "4") 5533 ; This isn't entirely accurate... It loads as well, but in terms of 5534 ; scheduling the following insn it is better to consider it as a store 5535 (set_attr "type" "store2")] 5536) 5537 5538 5539 5540;; Compare & branch insns 5541;; The range calcualations are based as follows: 5542;; For forward branches, the address calculation returns the address of 5543;; the next instruction. This is 2 beyond the branch instruction. 5544;; For backward branches, the address calculation returns the address of 5545;; the first instruction in this pattern (cmp). This is 2 before the branch 5546;; instruction for the shortest sequence, and 4 before the branch instruction 5547;; if we have to jump around an unconditional branch. 5548;; To the basic branch range the PC offset must be added (this is +4). 5549;; So for forward branches we have 5550;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4). 5551;; And for backward branches we have 5552;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4). 5553;; 5554;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048). 5555;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256). 5556 5557(define_insn "cbranchsi4" 5558 [(set (pc) 5559 (if_then_else 5560 (match_operator 0 "arm_comparison_operator" 5561 [(match_operand:SI 1 "register_operand" "l,r") 5562 (match_operand:SI 2 "nonmemory_operand" "rI,r")]) 5563 (label_ref (match_operand 3 "" "")) 5564 (pc)))] 5565 "TARGET_THUMB" 5566 "* 5567 output_asm_insn (\"cmp\\t%1, %2\", operands); 5568 switch (get_attr_length (insn)) 5569 { 5570 case 4: return \"b%d0\\t%l3\"; 5571 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 5572 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 5573 } 5574 " 5575 [(set (attr "far_jump") 5576 (if_then_else 5577 (eq_attr "length" "8") 5578 (const_string "yes") 5579 (const_string "no"))) 5580 (set (attr "length") 5581 (if_then_else 5582 (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 5583 (le (minus (match_dup 3) (pc)) (const_int 256))) 5584 (const_int 4) 5585 (if_then_else 5586 (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 5587 (le (minus (match_dup 3) (pc)) (const_int 2048))) 5588 (const_int 6) 5589 (const_int 8))))] 5590) 5591 5592(define_insn "*negated_cbranchsi4" 5593 [(set (pc) 5594 (if_then_else 5595 (match_operator 0 "arm_comparison_operator" 5596 [(match_operand:SI 1 "register_operand" "l") 5597 (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))]) 5598 (label_ref (match_operand 3 "" "")) 5599 (pc)))] 5600 "TARGET_THUMB" 5601 "* 5602 output_asm_insn (\"cmn\\t%1, %2\", operands); 5603 switch (get_attr_length (insn)) 5604 { 5605 case 4: return \"b%d0\\t%l3\"; 5606 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 5607 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 5608 } 5609 " 5610 [(set (attr "far_jump") 5611 (if_then_else 5612 (eq_attr "length" "8") 5613 (const_string "yes") 5614 (const_string "no"))) 5615 (set (attr "length") 5616 (if_then_else 5617 (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 5618 (le (minus (match_dup 3) (pc)) (const_int 256))) 5619 (const_int 4) 5620 (if_then_else 5621 (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 5622 (le (minus (match_dup 3) (pc)) (const_int 2048))) 5623 (const_int 6) 5624 (const_int 8))))] 5625) 5626 5627 5628;; Comparison and test insns 5629 5630(define_expand "cmpsi" 5631 [(match_operand:SI 0 "s_register_operand" "") 5632 (match_operand:SI 1 "arm_add_operand" "")] 5633 "TARGET_ARM" 5634 "{ 5635 arm_compare_op0 = operands[0]; 5636 arm_compare_op1 = operands[1]; 5637 DONE; 5638 }" 5639) 5640 5641(define_expand "cmpsf" 5642 [(match_operand:SF 0 "s_register_operand" "") 5643 (match_operand:SF 1 "fpu_rhs_operand" "")] 5644 "TARGET_ARM && TARGET_HARD_FLOAT" 5645 " 5646 arm_compare_op0 = operands[0]; 5647 arm_compare_op1 = operands[1]; 5648 DONE; 5649 " 5650) 5651 5652(define_expand "cmpdf" 5653 [(match_operand:DF 0 "s_register_operand" "") 5654 (match_operand:DF 1 "fpu_rhs_operand" "")] 5655 "TARGET_ARM && TARGET_HARD_FLOAT" 5656 " 5657 arm_compare_op0 = operands[0]; 5658 arm_compare_op1 = operands[1]; 5659 DONE; 5660 " 5661) 5662 5663(define_expand "cmpxf" 5664 [(match_operand:XF 0 "s_register_operand" "") 5665 (match_operand:XF 1 "fpu_rhs_operand" "")] 5666 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 5667 " 5668 arm_compare_op0 = operands[0]; 5669 arm_compare_op1 = operands[1]; 5670 DONE; 5671 " 5672) 5673 5674(define_insn "*arm_cmpsi_insn" 5675 [(set (reg:CC CC_REGNUM) 5676 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r") 5677 (match_operand:SI 1 "arm_add_operand" "rI,L")))] 5678 "TARGET_ARM" 5679 "@ 5680 cmp%?\\t%0, %1 5681 cmn%?\\t%0, #%n1" 5682 [(set_attr "conds" "set")] 5683) 5684 5685(define_insn "*cmpsi_shiftsi" 5686 [(set (reg:CC CC_REGNUM) 5687 (compare:CC (match_operand:SI 0 "s_register_operand" "r") 5688 (match_operator:SI 3 "shift_operator" 5689 [(match_operand:SI 1 "s_register_operand" "r") 5690 (match_operand:SI 2 "arm_rhs_operand" "rM")])))] 5691 "TARGET_ARM" 5692 "cmp%?\\t%0, %1%S3" 5693 [(set_attr "conds" "set") 5694 (set_attr "shift" "1") 5695 ] 5696) 5697 5698(define_insn "*cmpsi_shiftsi_swp" 5699 [(set (reg:CC_SWP CC_REGNUM) 5700 (compare:CC_SWP (match_operator:SI 3 "shift_operator" 5701 [(match_operand:SI 1 "s_register_operand" "r") 5702 (match_operand:SI 2 "reg_or_int_operand" "rM")]) 5703 (match_operand:SI 0 "s_register_operand" "r")))] 5704 "TARGET_ARM" 5705 "cmp%?\\t%0, %1%S3" 5706 [(set_attr "conds" "set") 5707 (set_attr "shift" "1") 5708 ] 5709) 5710 5711(define_insn "*cmpsi_neg_shiftsi" 5712 [(set (reg:CC CC_REGNUM) 5713 (compare:CC (match_operand:SI 0 "s_register_operand" "r") 5714 (neg:SI (match_operator:SI 3 "shift_operator" 5715 [(match_operand:SI 1 "s_register_operand" "r") 5716 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))] 5717 "TARGET_ARM" 5718 "cmn%?\\t%0, %1%S3" 5719 [(set_attr "conds" "set") 5720 (set_attr "shift" "1") 5721 ] 5722) 5723 5724(define_insn "*cmpsf_insn" 5725 [(set (reg:CCFP CC_REGNUM) 5726 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f") 5727 (match_operand:SF 1 "fpu_add_operand" "fG,H")))] 5728 "TARGET_ARM && TARGET_HARD_FLOAT" 5729 "@ 5730 cmf%?\\t%0, %1 5731 cnf%?\\t%0, #%N1" 5732 [(set_attr "conds" "set") 5733 (set_attr "type" "f_2_r")] 5734) 5735 5736(define_insn "*cmpdf_insn" 5737 [(set (reg:CCFP CC_REGNUM) 5738 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f") 5739 (match_operand:DF 1 "fpu_add_operand" "fG,H")))] 5740 "TARGET_ARM && TARGET_HARD_FLOAT" 5741 "@ 5742 cmf%?\\t%0, %1 5743 cnf%?\\t%0, #%N1" 5744 [(set_attr "conds" "set") 5745 (set_attr "type" "f_2_r")] 5746) 5747 5748(define_insn "*cmpesfdf_df" 5749 [(set (reg:CCFP CC_REGNUM) 5750 (compare:CCFP (float_extend:DF 5751 (match_operand:SF 0 "s_register_operand" "f,f")) 5752 (match_operand:DF 1 "fpu_add_operand" "fG,H")))] 5753 "TARGET_ARM && TARGET_HARD_FLOAT" 5754 "@ 5755 cmf%?\\t%0, %1 5756 cnf%?\\t%0, #%N1" 5757 [(set_attr "conds" "set") 5758 (set_attr "type" "f_2_r")] 5759) 5760 5761(define_insn "*cmpdf_esfdf" 5762 [(set (reg:CCFP CC_REGNUM) 5763 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f") 5764 (float_extend:DF 5765 (match_operand:SF 1 "s_register_operand" "f"))))] 5766 "TARGET_ARM && TARGET_HARD_FLOAT" 5767 "cmf%?\\t%0, %1" 5768 [(set_attr "conds" "set") 5769 (set_attr "type" "f_2_r")] 5770) 5771 5772(define_insn "*cmpxf_insn" 5773 [(set (reg:CCFP CC_REGNUM) 5774 (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f") 5775 (match_operand:XF 1 "fpu_add_operand" "fG,H")))] 5776 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 5777 "@ 5778 cmf%?\\t%0, %1 5779 cnf%?\\t%0, #%N1" 5780 [(set_attr "conds" "set") 5781 (set_attr "type" "f_2_r")] 5782) 5783 5784(define_insn "*cmpsf_trap" 5785 [(set (reg:CCFPE CC_REGNUM) 5786 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f") 5787 (match_operand:SF 1 "fpu_add_operand" "fG,H")))] 5788 "TARGET_ARM && TARGET_HARD_FLOAT" 5789 "@ 5790 cmf%?e\\t%0, %1 5791 cnf%?e\\t%0, #%N1" 5792 [(set_attr "conds" "set") 5793 (set_attr "type" "f_2_r")] 5794) 5795 5796(define_insn "*cmpdf_trap" 5797 [(set (reg:CCFPE CC_REGNUM) 5798 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f") 5799 (match_operand:DF 1 "fpu_add_operand" "fG,H")))] 5800 "TARGET_ARM && TARGET_HARD_FLOAT" 5801 "@ 5802 cmf%?e\\t%0, %1 5803 cnf%?e\\t%0, #%N1" 5804 [(set_attr "conds" "set") 5805 (set_attr "type" "f_2_r")] 5806) 5807 5808(define_insn "*cmp_esfdf_df_trap" 5809 [(set (reg:CCFPE CC_REGNUM) 5810 (compare:CCFPE (float_extend:DF 5811 (match_operand:SF 0 "s_register_operand" "f,f")) 5812 (match_operand:DF 1 "fpu_add_operand" "fG,H")))] 5813 "TARGET_ARM && TARGET_HARD_FLOAT" 5814 "@ 5815 cmf%?e\\t%0, %1 5816 cnf%?e\\t%0, #%N1" 5817 [(set_attr "conds" "set") 5818 (set_attr "type" "f_2_r")] 5819) 5820 5821(define_insn "*cmp_df_esfdf_trap" 5822 [(set (reg:CCFPE CC_REGNUM) 5823 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f") 5824 (float_extend:DF 5825 (match_operand:SF 1 "s_register_operand" "f"))))] 5826 "TARGET_ARM && TARGET_HARD_FLOAT" 5827 "cmf%?e\\t%0, %1" 5828 [(set_attr "conds" "set") 5829 (set_attr "type" "f_2_r")] 5830) 5831 5832(define_insn "*cmpxf_trap" 5833 [(set (reg:CCFPE CC_REGNUM) 5834 (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f") 5835 (match_operand:XF 1 "fpu_add_operand" "fG,H")))] 5836 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 5837 "@ 5838 cmf%?e\\t%0, %1 5839 cnf%?e\\t%0, #%N1" 5840 [(set_attr "conds" "set") 5841 (set_attr "type" "f_2_r")] 5842) 5843 5844; This insn allows redundant compares to be removed by cse, nothing should 5845; ever appear in the output file since (set (reg x) (reg x)) is a no-op that 5846; is deleted later on. The match_dup will match the mode here, so that 5847; mode changes of the condition codes aren't lost by this even though we don't 5848; specify what they are. 5849 5850(define_insn "*deleted_compare" 5851 [(set (match_operand 0 "cc_register" "") (match_dup 0))] 5852 "TARGET_ARM" 5853 "\\t%@ deleted compare" 5854 [(set_attr "conds" "set") 5855 (set_attr "length" "0")] 5856) 5857 5858 5859;; Conditional branch insns 5860 5861(define_expand "beq" 5862 [(set (pc) 5863 (if_then_else (eq (match_dup 1) (const_int 0)) 5864 (label_ref (match_operand 0 "" "")) 5865 (pc)))] 5866 "TARGET_ARM" 5867 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);" 5868) 5869 5870(define_expand "bne" 5871 [(set (pc) 5872 (if_then_else (ne (match_dup 1) (const_int 0)) 5873 (label_ref (match_operand 0 "" "")) 5874 (pc)))] 5875 "TARGET_ARM" 5876 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);" 5877) 5878 5879(define_expand "bgt" 5880 [(set (pc) 5881 (if_then_else (gt (match_dup 1) (const_int 0)) 5882 (label_ref (match_operand 0 "" "")) 5883 (pc)))] 5884 "TARGET_ARM" 5885 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);" 5886) 5887 5888(define_expand "ble" 5889 [(set (pc) 5890 (if_then_else (le (match_dup 1) (const_int 0)) 5891 (label_ref (match_operand 0 "" "")) 5892 (pc)))] 5893 "TARGET_ARM" 5894 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);" 5895) 5896 5897(define_expand "bge" 5898 [(set (pc) 5899 (if_then_else (ge (match_dup 1) (const_int 0)) 5900 (label_ref (match_operand 0 "" "")) 5901 (pc)))] 5902 "TARGET_ARM" 5903 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);" 5904) 5905 5906(define_expand "blt" 5907 [(set (pc) 5908 (if_then_else (lt (match_dup 1) (const_int 0)) 5909 (label_ref (match_operand 0 "" "")) 5910 (pc)))] 5911 "TARGET_ARM" 5912 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);" 5913) 5914 5915(define_expand "bgtu" 5916 [(set (pc) 5917 (if_then_else (gtu (match_dup 1) (const_int 0)) 5918 (label_ref (match_operand 0 "" "")) 5919 (pc)))] 5920 "TARGET_ARM" 5921 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);" 5922) 5923 5924(define_expand "bleu" 5925 [(set (pc) 5926 (if_then_else (leu (match_dup 1) (const_int 0)) 5927 (label_ref (match_operand 0 "" "")) 5928 (pc)))] 5929 "TARGET_ARM" 5930 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);" 5931) 5932 5933(define_expand "bgeu" 5934 [(set (pc) 5935 (if_then_else (geu (match_dup 1) (const_int 0)) 5936 (label_ref (match_operand 0 "" "")) 5937 (pc)))] 5938 "TARGET_ARM" 5939 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);" 5940) 5941 5942(define_expand "bltu" 5943 [(set (pc) 5944 (if_then_else (ltu (match_dup 1) (const_int 0)) 5945 (label_ref (match_operand 0 "" "")) 5946 (pc)))] 5947 "TARGET_ARM" 5948 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);" 5949) 5950 5951(define_expand "bunordered" 5952 [(set (pc) 5953 (if_then_else (unordered (match_dup 1) (const_int 0)) 5954 (label_ref (match_operand 0 "" "")) 5955 (pc)))] 5956 "TARGET_ARM && TARGET_HARD_FLOAT" 5957 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0, 5958 arm_compare_op1);" 5959) 5960 5961(define_expand "bordered" 5962 [(set (pc) 5963 (if_then_else (ordered (match_dup 1) (const_int 0)) 5964 (label_ref (match_operand 0 "" "")) 5965 (pc)))] 5966 "TARGET_ARM && TARGET_HARD_FLOAT" 5967 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0, 5968 arm_compare_op1);" 5969) 5970 5971(define_expand "bungt" 5972 [(set (pc) 5973 (if_then_else (ungt (match_dup 1) (const_int 0)) 5974 (label_ref (match_operand 0 "" "")) 5975 (pc)))] 5976 "TARGET_ARM && TARGET_HARD_FLOAT" 5977 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);" 5978) 5979 5980(define_expand "bunlt" 5981 [(set (pc) 5982 (if_then_else (unlt (match_dup 1) (const_int 0)) 5983 (label_ref (match_operand 0 "" "")) 5984 (pc)))] 5985 "TARGET_ARM && TARGET_HARD_FLOAT" 5986 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);" 5987) 5988 5989(define_expand "bunge" 5990 [(set (pc) 5991 (if_then_else (unge (match_dup 1) (const_int 0)) 5992 (label_ref (match_operand 0 "" "")) 5993 (pc)))] 5994 "TARGET_ARM && TARGET_HARD_FLOAT" 5995 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);" 5996) 5997 5998(define_expand "bunle" 5999 [(set (pc) 6000 (if_then_else (unle (match_dup 1) (const_int 0)) 6001 (label_ref (match_operand 0 "" "")) 6002 (pc)))] 6003 "TARGET_ARM && TARGET_HARD_FLOAT" 6004 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);" 6005) 6006 6007;; The following two patterns need two branch instructions, since there is 6008;; no single instruction that will handle all cases. 6009(define_expand "buneq" 6010 [(set (pc) 6011 (if_then_else (uneq (match_dup 1) (const_int 0)) 6012 (label_ref (match_operand 0 "" "")) 6013 (pc)))] 6014 "TARGET_ARM && TARGET_HARD_FLOAT" 6015 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);" 6016) 6017 6018(define_expand "bltgt" 6019 [(set (pc) 6020 (if_then_else (ltgt (match_dup 1) (const_int 0)) 6021 (label_ref (match_operand 0 "" "")) 6022 (pc)))] 6023 "TARGET_ARM && TARGET_HARD_FLOAT" 6024 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);" 6025) 6026 6027;; 6028;; Patterns to match conditional branch insns. 6029;; 6030 6031; Special pattern to match UNEQ. 6032(define_insn "*arm_buneq" 6033 [(set (pc) 6034 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0)) 6035 (label_ref (match_operand 0 "" "")) 6036 (pc)))] 6037 "TARGET_ARM && TARGET_HARD_FLOAT" 6038 "* 6039 if (arm_ccfsm_state != 0) 6040 abort (); 6041 6042 return \"bvs\\t%l0\;beq\\t%l0\"; 6043 " 6044 [(set_attr "conds" "jump_clob") 6045 (set_attr "length" "8")] 6046) 6047 6048; Special pattern to match LTGT. 6049(define_insn "*arm_bltgt" 6050 [(set (pc) 6051 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0)) 6052 (label_ref (match_operand 0 "" "")) 6053 (pc)))] 6054 "TARGET_ARM && TARGET_HARD_FLOAT" 6055 "* 6056 if (arm_ccfsm_state != 0) 6057 abort (); 6058 6059 return \"bmi\\t%l0\;bgt\\t%l0\"; 6060 " 6061 [(set_attr "conds" "jump_clob") 6062 (set_attr "length" "8")] 6063) 6064 6065(define_insn "*arm_cond_branch" 6066 [(set (pc) 6067 (if_then_else (match_operator 1 "arm_comparison_operator" 6068 [(match_operand 2 "cc_register" "") (const_int 0)]) 6069 (label_ref (match_operand 0 "" "")) 6070 (pc)))] 6071 "TARGET_ARM" 6072 "* 6073 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) 6074 { 6075 arm_ccfsm_state += 2; 6076 return \"\"; 6077 } 6078 return \"b%d1\\t%l0\"; 6079 " 6080 [(set_attr "conds" "use")] 6081) 6082 6083; Special pattern to match reversed UNEQ. 6084(define_insn "*arm_buneq_reversed" 6085 [(set (pc) 6086 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0)) 6087 (pc) 6088 (label_ref (match_operand 0 "" ""))))] 6089 "TARGET_ARM && TARGET_HARD_FLOAT" 6090 "* 6091 if (arm_ccfsm_state != 0) 6092 abort (); 6093 6094 return \"bmi\\t%l0\;bgt\\t%l0\"; 6095 " 6096 [(set_attr "conds" "jump_clob") 6097 (set_attr "length" "8")] 6098) 6099 6100; Special pattern to match reversed LTGT. 6101(define_insn "*arm_bltgt_reversed" 6102 [(set (pc) 6103 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0)) 6104 (pc) 6105 (label_ref (match_operand 0 "" ""))))] 6106 "TARGET_ARM && TARGET_HARD_FLOAT" 6107 "* 6108 if (arm_ccfsm_state != 0) 6109 abort (); 6110 6111 return \"bvs\\t%l0\;beq\\t%l0\"; 6112 " 6113 [(set_attr "conds" "jump_clob") 6114 (set_attr "length" "8")] 6115) 6116 6117(define_insn "*arm_cond_branch_reversed" 6118 [(set (pc) 6119 (if_then_else (match_operator 1 "arm_comparison_operator" 6120 [(match_operand 2 "cc_register" "") (const_int 0)]) 6121 (pc) 6122 (label_ref (match_operand 0 "" ""))))] 6123 "TARGET_ARM" 6124 "* 6125 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) 6126 { 6127 arm_ccfsm_state += 2; 6128 return \"\"; 6129 } 6130 return \"b%D1\\t%l0\"; 6131 " 6132 [(set_attr "conds" "use")] 6133) 6134 6135 6136 6137; scc insns 6138 6139(define_expand "seq" 6140 [(set (match_operand:SI 0 "s_register_operand" "=r") 6141 (eq:SI (match_dup 1) (const_int 0)))] 6142 "TARGET_ARM" 6143 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);" 6144) 6145 6146(define_expand "sne" 6147 [(set (match_operand:SI 0 "s_register_operand" "=r") 6148 (ne:SI (match_dup 1) (const_int 0)))] 6149 "TARGET_ARM" 6150 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);" 6151) 6152 6153(define_expand "sgt" 6154 [(set (match_operand:SI 0 "s_register_operand" "=r") 6155 (gt:SI (match_dup 1) (const_int 0)))] 6156 "TARGET_ARM" 6157 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);" 6158) 6159 6160(define_expand "sle" 6161 [(set (match_operand:SI 0 "s_register_operand" "=r") 6162 (le:SI (match_dup 1) (const_int 0)))] 6163 "TARGET_ARM" 6164 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);" 6165) 6166 6167(define_expand "sge" 6168 [(set (match_operand:SI 0 "s_register_operand" "=r") 6169 (ge:SI (match_dup 1) (const_int 0)))] 6170 "TARGET_ARM" 6171 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);" 6172) 6173 6174(define_expand "slt" 6175 [(set (match_operand:SI 0 "s_register_operand" "=r") 6176 (lt:SI (match_dup 1) (const_int 0)))] 6177 "TARGET_ARM" 6178 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);" 6179) 6180 6181(define_expand "sgtu" 6182 [(set (match_operand:SI 0 "s_register_operand" "=r") 6183 (gtu:SI (match_dup 1) (const_int 0)))] 6184 "TARGET_ARM" 6185 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);" 6186) 6187 6188(define_expand "sleu" 6189 [(set (match_operand:SI 0 "s_register_operand" "=r") 6190 (leu:SI (match_dup 1) (const_int 0)))] 6191 "TARGET_ARM" 6192 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);" 6193) 6194 6195(define_expand "sgeu" 6196 [(set (match_operand:SI 0 "s_register_operand" "=r") 6197 (geu:SI (match_dup 1) (const_int 0)))] 6198 "TARGET_ARM" 6199 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);" 6200) 6201 6202(define_expand "sltu" 6203 [(set (match_operand:SI 0 "s_register_operand" "=r") 6204 (ltu:SI (match_dup 1) (const_int 0)))] 6205 "TARGET_ARM" 6206 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);" 6207) 6208 6209(define_expand "sunordered" 6210 [(set (match_operand:SI 0 "s_register_operand" "=r") 6211 (unordered:SI (match_dup 1) (const_int 0)))] 6212 "TARGET_ARM && TARGET_HARD_FLOAT" 6213 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0, 6214 arm_compare_op1);" 6215) 6216 6217(define_expand "sordered" 6218 [(set (match_operand:SI 0 "s_register_operand" "=r") 6219 (ordered:SI (match_dup 1) (const_int 0)))] 6220 "TARGET_ARM && TARGET_HARD_FLOAT" 6221 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0, 6222 arm_compare_op1);" 6223) 6224 6225(define_expand "sungt" 6226 [(set (match_operand:SI 0 "s_register_operand" "=r") 6227 (ungt:SI (match_dup 1) (const_int 0)))] 6228 "TARGET_ARM && TARGET_HARD_FLOAT" 6229 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, 6230 arm_compare_op1);" 6231) 6232 6233(define_expand "sunge" 6234 [(set (match_operand:SI 0 "s_register_operand" "=r") 6235 (unge:SI (match_dup 1) (const_int 0)))] 6236 "TARGET_ARM && TARGET_HARD_FLOAT" 6237 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, 6238 arm_compare_op1);" 6239) 6240 6241(define_expand "sunlt" 6242 [(set (match_operand:SI 0 "s_register_operand" "=r") 6243 (unlt:SI (match_dup 1) (const_int 0)))] 6244 "TARGET_ARM && TARGET_HARD_FLOAT" 6245 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, 6246 arm_compare_op1);" 6247) 6248 6249(define_expand "sunle" 6250 [(set (match_operand:SI 0 "s_register_operand" "=r") 6251 (unle:SI (match_dup 1) (const_int 0)))] 6252 "TARGET_ARM && TARGET_HARD_FLOAT" 6253 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, 6254 arm_compare_op1);" 6255) 6256 6257;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with 6258;;; simple ARM instructions. 6259; 6260; (define_expand "suneq" 6261; [(set (match_operand:SI 0 "s_register_operand" "=r") 6262; (uneq:SI (match_dup 1) (const_int 0)))] 6263; "TARGET_ARM && TARGET_HARD_FLOAT" 6264; "abort ();" 6265; ) 6266; 6267; (define_expand "sltgt" 6268; [(set (match_operand:SI 0 "s_register_operand" "=r") 6269; (ltgt:SI (match_dup 1) (const_int 0)))] 6270; "TARGET_ARM && TARGET_HARD_FLOAT" 6271; "abort ();" 6272; ) 6273 6274(define_insn "*mov_scc" 6275 [(set (match_operand:SI 0 "s_register_operand" "=r") 6276 (match_operator:SI 1 "arm_comparison_operator" 6277 [(match_operand 2 "cc_register" "") (const_int 0)]))] 6278 "TARGET_ARM" 6279 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1" 6280 [(set_attr "conds" "use") 6281 (set_attr "length" "8")] 6282) 6283 6284(define_insn "*mov_negscc" 6285 [(set (match_operand:SI 0 "s_register_operand" "=r") 6286 (neg:SI (match_operator:SI 1 "arm_comparison_operator" 6287 [(match_operand 2 "cc_register" "") (const_int 0)])))] 6288 "TARGET_ARM" 6289 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0" 6290 [(set_attr "conds" "use") 6291 (set_attr "length" "8")] 6292) 6293 6294(define_insn "*mov_notscc" 6295 [(set (match_operand:SI 0 "s_register_operand" "=r") 6296 (not:SI (match_operator:SI 1 "arm_comparison_operator" 6297 [(match_operand 2 "cc_register" "") (const_int 0)])))] 6298 "TARGET_ARM" 6299 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1" 6300 [(set_attr "conds" "use") 6301 (set_attr "length" "8")] 6302) 6303 6304 6305;; Conditional move insns 6306 6307(define_expand "movsicc" 6308 [(set (match_operand:SI 0 "s_register_operand" "") 6309 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "") 6310 (match_operand:SI 2 "arm_not_operand" "") 6311 (match_operand:SI 3 "arm_not_operand" "")))] 6312 "TARGET_ARM" 6313 " 6314 { 6315 enum rtx_code code = GET_CODE (operands[1]); 6316 rtx ccreg; 6317 6318 if (code == UNEQ || code == LTGT) 6319 FAIL; 6320 6321 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); 6322 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); 6323 }" 6324) 6325 6326(define_expand "movsfcc" 6327 [(set (match_operand:SF 0 "s_register_operand" "") 6328 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "") 6329 (match_operand:SF 2 "s_register_operand" "") 6330 (match_operand:SF 3 "nonmemory_operand" "")))] 6331 "TARGET_ARM" 6332 " 6333 { 6334 enum rtx_code code = GET_CODE (operands[1]); 6335 rtx ccreg; 6336 6337 if (code == UNEQ || code == LTGT) 6338 FAIL; 6339 6340 /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 6341 Otherwise, ensure it is a valid FP add operand */ 6342 if ((!TARGET_HARD_FLOAT) 6343 || (!fpu_add_operand (operands[3], SFmode))) 6344 operands[3] = force_reg (SFmode, operands[3]); 6345 6346 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); 6347 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); 6348 }" 6349) 6350 6351(define_expand "movdfcc" 6352 [(set (match_operand:DF 0 "s_register_operand" "") 6353 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "") 6354 (match_operand:DF 2 "s_register_operand" "") 6355 (match_operand:DF 3 "fpu_add_operand" "")))] 6356 "TARGET_ARM && TARGET_HARD_FLOAT" 6357 " 6358 { 6359 enum rtx_code code = GET_CODE (operands[1]); 6360 rtx ccreg; 6361 6362 if (code == UNEQ || code == LTGT) 6363 FAIL; 6364 6365 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); 6366 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); 6367 }" 6368) 6369 6370(define_insn "*movsicc_insn" 6371 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r") 6372 (if_then_else:SI 6373 (match_operator 3 "arm_comparison_operator" 6374 [(match_operand 4 "cc_register" "") (const_int 0)]) 6375 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K") 6376 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))] 6377 "TARGET_ARM" 6378 "@ 6379 mov%D3\\t%0, %2 6380 mvn%D3\\t%0, #%B2 6381 mov%d3\\t%0, %1 6382 mvn%d3\\t%0, #%B1 6383 mov%d3\\t%0, %1\;mov%D3\\t%0, %2 6384 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2 6385 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2 6386 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2" 6387 [(set_attr "length" "4,4,4,4,8,8,8,8") 6388 (set_attr "conds" "use")] 6389) 6390 6391(define_insn "*movsfcc_hard_insn" 6392 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f") 6393 (if_then_else:SF 6394 (match_operator 3 "arm_comparison_operator" 6395 [(match_operand 4 "cc_register" "") (const_int 0)]) 6396 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H") 6397 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))] 6398 "TARGET_ARM && TARGET_HARD_FLOAT" 6399 "@ 6400 mvf%D3s\\t%0, %2 6401 mnf%D3s\\t%0, #%N2 6402 mvf%d3s\\t%0, %1 6403 mnf%d3s\\t%0, #%N1 6404 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2 6405 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2 6406 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2 6407 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2" 6408 [(set_attr "length" "4,4,4,4,8,8,8,8") 6409 (set_attr "type" "ffarith") 6410 (set_attr "conds" "use")] 6411) 6412 6413(define_insn "*movsfcc_soft_insn" 6414 [(set (match_operand:SF 0 "s_register_operand" "=r,r") 6415 (if_then_else:SF (match_operator 3 "arm_comparison_operator" 6416 [(match_operand 4 "cc_register" "") (const_int 0)]) 6417 (match_operand:SF 1 "s_register_operand" "0,r") 6418 (match_operand:SF 2 "s_register_operand" "r,0")))] 6419 "TARGET_ARM && TARGET_SOFT_FLOAT" 6420 "@ 6421 mov%D3\\t%0, %2 6422 mov%d3\\t%0, %1" 6423 [(set_attr "conds" "use")] 6424) 6425 6426(define_insn "*movdfcc_insn" 6427 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f") 6428 (if_then_else:DF 6429 (match_operator 3 "arm_comparison_operator" 6430 [(match_operand 4 "cc_register" "") (const_int 0)]) 6431 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H") 6432 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))] 6433 "TARGET_ARM && TARGET_HARD_FLOAT" 6434 "@ 6435 mvf%D3d\\t%0, %2 6436 mnf%D3d\\t%0, #%N2 6437 mvf%d3d\\t%0, %1 6438 mnf%d3d\\t%0, #%N1 6439 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2 6440 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2 6441 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2 6442 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2" 6443 [(set_attr "length" "4,4,4,4,8,8,8,8") 6444 (set_attr "type" "ffarith") 6445 (set_attr "conds" "use")] 6446) 6447 6448 6449;; Jump and linkage insns 6450 6451(define_expand "jump" 6452 [(set (pc) 6453 (label_ref (match_operand 0 "" "")))] 6454 "TARGET_EITHER" 6455 "" 6456) 6457 6458(define_insn "*arm_jump" 6459 [(set (pc) 6460 (label_ref (match_operand 0 "" "")))] 6461 "TARGET_ARM" 6462 "* 6463 { 6464 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) 6465 { 6466 arm_ccfsm_state += 2; 6467 return \"\"; 6468 } 6469 return \"b%?\\t%l0\"; 6470 } 6471 " 6472 [(set_attr "predicable" "yes")] 6473) 6474 6475(define_insn "*thumb_jump" 6476 [(set (pc) 6477 (label_ref (match_operand 0 "" "")))] 6478 "TARGET_THUMB" 6479 "* 6480 if (get_attr_length (insn) == 2) 6481 return \"b\\t%l0\"; 6482 return \"bl\\t%l0\\t%@ far jump\"; 6483 " 6484 [(set (attr "far_jump") 6485 (if_then_else 6486 (eq_attr "length" "4") 6487 (const_string "yes") 6488 (const_string "no"))) 6489 (set (attr "length") 6490 (if_then_else 6491 (and (ge (minus (match_dup 0) (pc)) (const_int -2048)) 6492 (le (minus (match_dup 0) (pc)) (const_int 2044))) 6493 (const_int 2) 6494 (const_int 4)))] 6495) 6496 6497(define_expand "call" 6498 [(parallel [(call (match_operand 0 "memory_operand" "") 6499 (match_operand 1 "general_operand" "")) 6500 (use (match_operand 2 "" "")) 6501 (clobber (reg:SI LR_REGNUM))])] 6502 "TARGET_EITHER" 6503 " 6504 { 6505 rtx callee; 6506 6507 /* In an untyped call, we can get NULL for operand 2. */ 6508 if (operands[2] == NULL_RTX) 6509 operands[2] = const0_rtx; 6510 6511 /* This is to decide if we should generate indirect calls by loading the 6512 32 bit address of the callee into a register before performing the 6513 branch and link. operand[2] encodes the long_call/short_call 6514 attribute of the function being called. This attribute is set whenever 6515 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call 6516 is used, and the short_call attribute can also be set if function is 6517 declared as static or if it has already been defined in the current 6518 compilation unit. See arm.c and arm.h for info about this. The third 6519 parameter to arm_is_longcall_p is used to tell it which pattern 6520 invoked it. */ 6521 callee = XEXP (operands[0], 0); 6522 6523 if (GET_CODE (callee) != REG 6524 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0)) 6525 XEXP (operands[0], 0) = force_reg (Pmode, callee); 6526 }" 6527) 6528 6529(define_insn "*call_reg" 6530 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r")) 6531 (match_operand 1 "" "")) 6532 (use (match_operand 2 "" "")) 6533 (clobber (reg:SI LR_REGNUM))] 6534 "TARGET_ARM" 6535 "* 6536 return output_call (operands); 6537 " 6538 ;; length is worst case, normally it is only two 6539 [(set_attr "length" "12") 6540 (set_attr "type" "call")] 6541) 6542 6543(define_insn "*call_mem" 6544 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m")) 6545 (match_operand 1 "" "")) 6546 (use (match_operand 2 "" "")) 6547 (clobber (reg:SI LR_REGNUM))] 6548 "TARGET_ARM" 6549 "* 6550 return output_call_mem (operands); 6551 " 6552 [(set_attr "length" "12") 6553 (set_attr "type" "call")] 6554) 6555 6556(define_insn "*call_indirect" 6557 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r")) 6558 (match_operand 1 "" "")) 6559 (use (match_operand 2 "" "")) 6560 (clobber (reg:SI LR_REGNUM))] 6561 "TARGET_THUMB" 6562 "* 6563 { 6564 if (TARGET_CALLER_INTERWORKING) 6565 return \"bl\\t%__interwork_call_via_%0\"; 6566 else 6567 return \"bl\\t%__call_via_%0\"; 6568 }" 6569 [(set_attr "type" "call")] 6570) 6571 6572(define_insn "*call_value_indirect" 6573 [(set (match_operand 0 "" "=l") 6574 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r")) 6575 (match_operand 2 "" ""))) 6576 (use (match_operand 3 "" "")) 6577 (clobber (reg:SI LR_REGNUM))] 6578 "TARGET_THUMB" 6579 "* 6580 { 6581 if (TARGET_CALLER_INTERWORKING) 6582 return \"bl\\t%__interwork_call_via_%1\"; 6583 else 6584 return \"bl\\t%__call_via_%1\"; 6585 }" 6586 [(set_attr "type" "call")] 6587) 6588 6589(define_expand "call_value" 6590 [(parallel [(set (match_operand 0 "" "") 6591 (call (match_operand 1 "memory_operand" "") 6592 (match_operand 2 "general_operand" ""))) 6593 (use (match_operand 3 "" "")) 6594 (clobber (reg:SI LR_REGNUM))])] 6595 "TARGET_EITHER" 6596 " 6597 { 6598 rtx callee = XEXP (operands[1], 0); 6599 6600 /* In an untyped call, we can get NULL for operand 2. */ 6601 if (operands[3] == 0) 6602 operands[3] = const0_rtx; 6603 6604 /* See the comment in define_expand \"call\". */ 6605 if (GET_CODE (callee) != REG 6606 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0)) 6607 XEXP (operands[1], 0) = force_reg (Pmode, callee); 6608 }" 6609) 6610 6611(define_insn "*call_value_reg" 6612 [(set (match_operand 0 "" "=r,f") 6613 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r")) 6614 (match_operand 2 "" ""))) 6615 (use (match_operand 3 "" "")) 6616 (clobber (reg:SI LR_REGNUM))] 6617 "TARGET_ARM" 6618 "* 6619 return output_call (&operands[1]); 6620 " 6621 [(set_attr "length" "12") 6622 (set_attr "type" "call")] 6623) 6624 6625(define_insn "*call_value_mem" 6626 [(set (match_operand 0 "" "=r,f") 6627 (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m")) 6628 (match_operand 2 "" ""))) 6629 (use (match_operand 3 "" "")) 6630 (clobber (reg:SI LR_REGNUM))] 6631 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))" 6632 "* 6633 return output_call_mem (&operands[1]); 6634 " 6635 [(set_attr "length" "12") 6636 (set_attr "type" "call")] 6637) 6638 6639;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses 6640;; The 'a' causes the operand to be treated as an address, i.e. no '#' output. 6641 6642(define_insn "*call_symbol" 6643 [(call (mem:SI (match_operand:SI 0 "" "X")) 6644 (match_operand 1 "" "")) 6645 (use (match_operand 2 "" "")) 6646 (clobber (reg:SI LR_REGNUM))] 6647 "TARGET_ARM 6648 && (GET_CODE (operands[0]) == SYMBOL_REF) 6649 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)" 6650 "* 6651 { 6652 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\"; 6653 }" 6654 [(set_attr "type" "call")] 6655) 6656 6657(define_insn "*call_value_symbol" 6658 [(set (match_operand 0 "s_register_operand" "=r,f") 6659 (call (mem:SI (match_operand:SI 1 "" "X,X")) 6660 (match_operand:SI 2 "" ""))) 6661 (use (match_operand 3 "" "")) 6662 (clobber (reg:SI LR_REGNUM))] 6663 "TARGET_ARM 6664 && (GET_CODE (operands[1]) == SYMBOL_REF) 6665 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)" 6666 "* 6667 { 6668 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\"; 6669 }" 6670 [(set_attr "type" "call")] 6671) 6672 6673(define_insn "*call_insn" 6674 [(call (mem:SI (match_operand:SI 0 "" "X")) 6675 (match_operand:SI 1 "" "")) 6676 (use (match_operand 2 "" "")) 6677 (clobber (reg:SI LR_REGNUM))] 6678 "TARGET_THUMB 6679 && GET_CODE (operands[0]) == SYMBOL_REF 6680 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)" 6681 "bl\\t%a0" 6682 [(set_attr "length" "4") 6683 (set_attr "type" "call")] 6684) 6685 6686(define_insn "*call_value_insn" 6687 [(set (match_operand 0 "register_operand" "=l") 6688 (call (mem:SI (match_operand 1 "" "X")) 6689 (match_operand 2 "" ""))) 6690 (use (match_operand 3 "" "")) 6691 (clobber (reg:SI LR_REGNUM))] 6692 "TARGET_THUMB 6693 && GET_CODE (operands[1]) == SYMBOL_REF 6694 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)" 6695 "bl\\t%a1" 6696 [(set_attr "length" "4") 6697 (set_attr "type" "call")] 6698) 6699 6700;; We may also be able to do sibcalls for Thumb, but it's much harder... 6701(define_expand "sibcall" 6702 [(parallel [(call (match_operand 0 "memory_operand" "") 6703 (match_operand 1 "general_operand" "")) 6704 (return) 6705 (use (match_operand 2 "" ""))])] 6706 "TARGET_ARM" 6707 " 6708 { 6709 if (operands[2] == NULL_RTX) 6710 operands[2] = const0_rtx; 6711 }" 6712) 6713 6714(define_expand "sibcall_value" 6715 [(parallel [(set (match_operand 0 "register_operand" "") 6716 (call (match_operand 1 "memory_operand" "") 6717 (match_operand 2 "general_operand" ""))) 6718 (return) 6719 (use (match_operand 3 "" ""))])] 6720 "TARGET_ARM" 6721 " 6722 { 6723 if (operands[3] == NULL_RTX) 6724 operands[3] = const0_rtx; 6725 }" 6726) 6727 6728(define_insn "*sibcall_insn" 6729 [(call (mem:SI (match_operand:SI 0 "" "X")) 6730 (match_operand 1 "" "")) 6731 (return) 6732 (use (match_operand 2 "" ""))] 6733 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF" 6734 "* 6735 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\"; 6736 " 6737 [(set_attr "type" "call")] 6738) 6739 6740(define_insn "*sibcall_value_insn" 6741 [(set (match_operand 0 "s_register_operand" "=r,f") 6742 (call (mem:SI (match_operand:SI 1 "" "X,X")) 6743 (match_operand 2 "" ""))) 6744 (return) 6745 (use (match_operand 3 "" ""))] 6746 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF" 6747 "* 6748 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\"; 6749 " 6750 [(set_attr "type" "call")] 6751) 6752 6753;; Often the return insn will be the same as loading from memory, so set attr 6754(define_insn "return" 6755 [(return)] 6756 "TARGET_ARM && USE_RETURN_INSN (FALSE)" 6757 "* 6758 { 6759 if (arm_ccfsm_state == 2) 6760 { 6761 arm_ccfsm_state += 2; 6762 return \"\"; 6763 } 6764 return output_return_instruction (const_true_rtx, TRUE, FALSE); 6765 }" 6766 [(set_attr "type" "load") 6767 (set_attr "predicable" "yes")] 6768) 6769 6770(define_insn "*cond_return" 6771 [(set (pc) 6772 (if_then_else (match_operator 0 "arm_comparison_operator" 6773 [(match_operand 1 "cc_register" "") (const_int 0)]) 6774 (return) 6775 (pc)))] 6776 "TARGET_ARM && USE_RETURN_INSN (TRUE)" 6777 "* 6778 { 6779 if (arm_ccfsm_state == 2) 6780 { 6781 arm_ccfsm_state += 2; 6782 return \"\"; 6783 } 6784 return output_return_instruction (operands[0], TRUE, FALSE); 6785 }" 6786 [(set_attr "conds" "use") 6787 (set_attr "type" "load")] 6788) 6789 6790(define_insn "*cond_return_inverted" 6791 [(set (pc) 6792 (if_then_else (match_operator 0 "arm_comparison_operator" 6793 [(match_operand 1 "cc_register" "") (const_int 0)]) 6794 (pc) 6795 (return)))] 6796 "TARGET_ARM && USE_RETURN_INSN (TRUE)" 6797 "* 6798 { 6799 if (arm_ccfsm_state == 2) 6800 { 6801 arm_ccfsm_state += 2; 6802 return \"\"; 6803 } 6804 return output_return_instruction (operands[0], TRUE, TRUE); 6805 }" 6806 [(set_attr "conds" "use") 6807 (set_attr "type" "load")] 6808) 6809 6810;; Generate a sequence of instructions to determine if the processor is 6811;; in 26-bit or 32-bit mode, and return the appropriate return address 6812;; mask. 6813 6814(define_expand "return_addr_mask" 6815 [(set (match_dup 1) 6816 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH) 6817 (const_int 0))) 6818 (set (match_operand:SI 0 "s_register_operand" "") 6819 (if_then_else:SI (eq (match_dup 1) (const_int 0)) 6820 (const_int -1) 6821 (const_int 67108860)))] ; 0x03fffffc 6822 "TARGET_ARM" 6823 " 6824 operands[1] = gen_rtx_REG (CC_NOOVmode, 24); 6825 ") 6826 6827(define_insn "*check_arch2" 6828 [(set (match_operand:CC_NOOV 0 "cc_register" "") 6829 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH) 6830 (const_int 0)))] 6831 "TARGET_ARM" 6832 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc" 6833 [(set_attr "length" "8") 6834 (set_attr "conds" "set")] 6835) 6836 6837;; Call subroutine returning any type. 6838 6839(define_expand "untyped_call" 6840 [(parallel [(call (match_operand 0 "" "") 6841 (const_int 0)) 6842 (match_operand 1 "" "") 6843 (match_operand 2 "" "")])] 6844 "TARGET_ARM" 6845 " 6846 { 6847 int i; 6848 6849 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); 6850 6851 for (i = 0; i < XVECLEN (operands[2], 0); i++) 6852 { 6853 rtx set = XVECEXP (operands[2], 0, i); 6854 6855 emit_move_insn (SET_DEST (set), SET_SRC (set)); 6856 } 6857 6858 /* The optimizer does not know that the call sets the function value 6859 registers we stored in the result block. We avoid problems by 6860 claiming that all hard registers are used and clobbered at this 6861 point. */ 6862 emit_insn (gen_blockage ()); 6863 6864 DONE; 6865 }" 6866) 6867 6868;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and 6869;; all of memory. This blocks insns from being moved across this point. 6870 6871(define_insn "blockage" 6872 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)] 6873 "TARGET_EITHER" 6874 "" 6875 [(set_attr "length" "0") 6876 (set_attr "type" "block")] 6877) 6878 6879(define_expand "casesi" 6880 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on 6881 (match_operand:SI 1 "const_int_operand" "") ; lower bound 6882 (match_operand:SI 2 "const_int_operand" "") ; total range 6883 (match_operand:SI 3 "" "") ; table label 6884 (match_operand:SI 4 "" "")] ; Out of range label 6885 "TARGET_ARM" 6886 " 6887 { 6888 rtx reg; 6889 if (operands[1] != const0_rtx) 6890 { 6891 reg = gen_reg_rtx (SImode); 6892 6893 emit_insn (gen_addsi3 (reg, operands[0], 6894 GEN_INT (-INTVAL (operands[1])))); 6895 operands[0] = reg; 6896 } 6897 6898 if (!const_ok_for_arm (INTVAL (operands[2]))) 6899 operands[2] = force_reg (SImode, operands[2]); 6900 6901 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3], 6902 operands[4])); 6903 DONE; 6904 }" 6905) 6906 6907;; The USE in this pattern is needed to tell flow analysis that this is 6908;; a CASESI insn. It has no other purpose. 6909(define_insn "casesi_internal" 6910 [(parallel [(set (pc) 6911 (if_then_else 6912 (leu (match_operand:SI 0 "s_register_operand" "r") 6913 (match_operand:SI 1 "arm_rhs_operand" "rI")) 6914 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4)) 6915 (label_ref (match_operand 2 "" "")))) 6916 (label_ref (match_operand 3 "" "")))) 6917 (clobber (reg:CC CC_REGNUM)) 6918 (use (label_ref (match_dup 2)))])] 6919 "TARGET_ARM" 6920 "* 6921 if (flag_pic) 6922 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\"; 6923 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\"; 6924 " 6925 [(set_attr "conds" "clob") 6926 (set_attr "length" "12")] 6927) 6928 6929(define_expand "indirect_jump" 6930 [(set (pc) 6931 (match_operand:SI 0 "s_register_operand" ""))] 6932 "TARGET_EITHER" 6933 "" 6934) 6935 6936(define_insn "*arm_indirect_jump" 6937 [(set (pc) 6938 (match_operand:SI 0 "s_register_operand" "r"))] 6939 "TARGET_ARM" 6940 "mov%?\\t%|pc, %0\\t%@ indirect register jump" 6941 [(set_attr "predicable" "yes")] 6942) 6943 6944;; Although not supported by the define_expand above, 6945;; cse/combine may generate this form. 6946(define_insn "*load_indirect_jump" 6947 [(set (pc) 6948 (match_operand:SI 0 "memory_operand" "m"))] 6949 "TARGET_ARM" 6950 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump" 6951 [(set_attr "type" "load") 6952 (set_attr "pool_range" "4096") 6953 (set_attr "neg_pool_range" "4084") 6954 (set_attr "predicable" "yes")] 6955) 6956 6957(define_insn "*thumb_indirect_jump" 6958 [(set (pc) 6959 (match_operand:SI 0 "register_operand" "l*r"))] 6960 "TARGET_THUMB" 6961 "mov\\tpc, %0" 6962 [(set_attr "conds" "clob") 6963 (set_attr "length" "2")] 6964) 6965 6966 6967;; Misc insns 6968 6969(define_insn "nop" 6970 [(const_int 0)] 6971 "TARGET_EITHER" 6972 "* 6973 if (TARGET_ARM) 6974 return \"mov%?\\t%|r0, %|r0\\t%@ nop\"; 6975 return \"mov\\tr8, r8\"; 6976 " 6977 [(set (attr "length") 6978 (if_then_else (eq_attr "is_thumb" "yes") 6979 (const_int 2) 6980 (const_int 4)))] 6981) 6982 6983 6984;; Patterns to allow combination of arithmetic, cond code and shifts 6985 6986(define_insn "*arith_shiftsi" 6987 [(set (match_operand:SI 0 "s_register_operand" "=r") 6988 (match_operator:SI 1 "shiftable_operator" 6989 [(match_operator:SI 3 "shift_operator" 6990 [(match_operand:SI 4 "s_register_operand" "r") 6991 (match_operand:SI 5 "reg_or_int_operand" "rI")]) 6992 (match_operand:SI 2 "s_register_operand" "r")]))] 6993 "TARGET_ARM" 6994 "%i1%?\\t%0, %2, %4%S3" 6995 [(set_attr "predicable" "yes") 6996 (set_attr "shift" "4") 6997 ] 6998) 6999 7000(define_insn "*arith_shiftsi_compare0" 7001 [(set (reg:CC_NOOV CC_REGNUM) 7002 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" 7003 [(match_operator:SI 3 "shift_operator" 7004 [(match_operand:SI 4 "s_register_operand" "r") 7005 (match_operand:SI 5 "reg_or_int_operand" "rI")]) 7006 (match_operand:SI 2 "s_register_operand" "r")]) 7007 (const_int 0))) 7008 (set (match_operand:SI 0 "s_register_operand" "=r") 7009 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)]) 7010 (match_dup 2)]))] 7011 "TARGET_ARM" 7012 "%i1%?s\\t%0, %2, %4%S3" 7013 [(set_attr "conds" "set") 7014 (set_attr "shift" "4") 7015 ] 7016) 7017 7018(define_insn "*arith_shiftsi_compare0_scratch" 7019 [(set (reg:CC_NOOV CC_REGNUM) 7020 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" 7021 [(match_operator:SI 3 "shift_operator" 7022 [(match_operand:SI 4 "s_register_operand" "r") 7023 (match_operand:SI 5 "reg_or_int_operand" "rI")]) 7024 (match_operand:SI 2 "s_register_operand" "r")]) 7025 (const_int 0))) 7026 (clobber (match_scratch:SI 0 "=r"))] 7027 "TARGET_ARM" 7028 "%i1%?s\\t%0, %2, %4%S3" 7029 [(set_attr "conds" "set") 7030 (set_attr "shift" "4") 7031 ] 7032) 7033 7034(define_insn "*sub_shiftsi" 7035 [(set (match_operand:SI 0 "s_register_operand" "=r") 7036 (minus:SI (match_operand:SI 1 "s_register_operand" "r") 7037 (match_operator:SI 2 "shift_operator" 7038 [(match_operand:SI 3 "s_register_operand" "r") 7039 (match_operand:SI 4 "reg_or_int_operand" "rM")])))] 7040 "TARGET_ARM" 7041 "sub%?\\t%0, %1, %3%S2" 7042 [(set_attr "predicable" "yes") 7043 (set_attr "shift" "3") 7044 ] 7045) 7046 7047(define_insn "*sub_shiftsi_compare0" 7048 [(set (reg:CC_NOOV CC_REGNUM) 7049 (compare:CC_NOOV 7050 (minus:SI (match_operand:SI 1 "s_register_operand" "r") 7051 (match_operator:SI 2 "shift_operator" 7052 [(match_operand:SI 3 "s_register_operand" "r") 7053 (match_operand:SI 4 "reg_or_int_operand" "rM")])) 7054 (const_int 0))) 7055 (set (match_operand:SI 0 "s_register_operand" "=r") 7056 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 7057 (match_dup 4)])))] 7058 "TARGET_ARM" 7059 "sub%?s\\t%0, %1, %3%S2" 7060 [(set_attr "conds" "set") 7061 (set_attr "shift" "3") 7062 ] 7063) 7064 7065(define_insn "*sub_shiftsi_compare0_scratch" 7066 [(set (reg:CC_NOOV CC_REGNUM) 7067 (compare:CC_NOOV 7068 (minus:SI (match_operand:SI 1 "s_register_operand" "r") 7069 (match_operator:SI 2 "shift_operator" 7070 [(match_operand:SI 3 "s_register_operand" "r") 7071 (match_operand:SI 4 "reg_or_int_operand" "rM")])) 7072 (const_int 0))) 7073 (clobber (match_scratch:SI 0 "=r"))] 7074 "TARGET_ARM" 7075 "sub%?s\\t%0, %1, %3%S2" 7076 [(set_attr "conds" "set") 7077 (set_attr "shift" "3") 7078 ] 7079) 7080 7081 7082 7083(define_insn "*and_scc" 7084 [(set (match_operand:SI 0 "s_register_operand" "=r") 7085 (and:SI (match_operator:SI 1 "arm_comparison_operator" 7086 [(match_operand 3 "cc_register" "") (const_int 0)]) 7087 (match_operand:SI 2 "s_register_operand" "r")))] 7088 "TARGET_ARM" 7089 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1" 7090 [(set_attr "conds" "use") 7091 (set_attr "length" "8")] 7092) 7093 7094(define_insn "*ior_scc" 7095 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7096 (ior:SI (match_operator:SI 2 "arm_comparison_operator" 7097 [(match_operand 3 "cc_register" "") (const_int 0)]) 7098 (match_operand:SI 1 "s_register_operand" "0,?r")))] 7099 "TARGET_ARM" 7100 "@ 7101 orr%d2\\t%0, %1, #1 7102 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1" 7103 [(set_attr "conds" "use") 7104 (set_attr "length" "4,8")] 7105) 7106 7107(define_insn "*compare_scc" 7108 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7109 (match_operator:SI 1 "arm_comparison_operator" 7110 [(match_operand:SI 2 "s_register_operand" "r,r") 7111 (match_operand:SI 3 "arm_add_operand" "rI,L")])) 7112 (clobber (reg:CC CC_REGNUM))] 7113 "TARGET_ARM" 7114 "* 7115 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx) 7116 return \"mov\\t%0, %2, lsr #31\"; 7117 7118 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx) 7119 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\"; 7120 7121 if (GET_CODE (operands[1]) == NE) 7122 { 7123 if (which_alternative == 1) 7124 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\"; 7125 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\"; 7126 } 7127 if (which_alternative == 1) 7128 output_asm_insn (\"cmn\\t%2, #%n3\", operands); 7129 else 7130 output_asm_insn (\"cmp\\t%2, %3\", operands); 7131 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\"; 7132 " 7133 [(set_attr "conds" "clob") 7134 (set_attr "length" "12")] 7135) 7136 7137(define_insn "*cond_move" 7138 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 7139 (if_then_else:SI (match_operator 3 "equality_operator" 7140 [(match_operator 4 "arm_comparison_operator" 7141 [(match_operand 5 "cc_register" "") (const_int 0)]) 7142 (const_int 0)]) 7143 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI") 7144 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))] 7145 "TARGET_ARM" 7146 "* 7147 if (GET_CODE (operands[3]) == NE) 7148 { 7149 if (which_alternative != 1) 7150 output_asm_insn (\"mov%D4\\t%0, %2\", operands); 7151 if (which_alternative != 0) 7152 output_asm_insn (\"mov%d4\\t%0, %1\", operands); 7153 return \"\"; 7154 } 7155 if (which_alternative != 0) 7156 output_asm_insn (\"mov%D4\\t%0, %1\", operands); 7157 if (which_alternative != 1) 7158 output_asm_insn (\"mov%d4\\t%0, %2\", operands); 7159 return \"\"; 7160 " 7161 [(set_attr "conds" "use") 7162 (set_attr "length" "4,4,8")] 7163) 7164 7165(define_insn "*cond_arith" 7166 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7167 (match_operator:SI 5 "shiftable_operator" 7168 [(match_operator:SI 4 "arm_comparison_operator" 7169 [(match_operand:SI 2 "s_register_operand" "r,r") 7170 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) 7171 (match_operand:SI 1 "s_register_operand" "0,?r")])) 7172 (clobber (reg:CC CC_REGNUM))] 7173 "TARGET_ARM" 7174 "* 7175 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx) 7176 return \"%i5\\t%0, %1, %2, lsr #31\"; 7177 7178 output_asm_insn (\"cmp\\t%2, %3\", operands); 7179 if (GET_CODE (operands[5]) == AND) 7180 output_asm_insn (\"mov%D4\\t%0, #0\", operands); 7181 else if (GET_CODE (operands[5]) == MINUS) 7182 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands); 7183 else if (which_alternative != 0) 7184 output_asm_insn (\"mov%D4\\t%0, %1\", operands); 7185 return \"%i5%d4\\t%0, %1, #1\"; 7186 " 7187 [(set_attr "conds" "clob") 7188 (set_attr "length" "12")] 7189) 7190 7191(define_insn "*cond_sub" 7192 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7193 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r") 7194 (match_operator:SI 4 "arm_comparison_operator" 7195 [(match_operand:SI 2 "s_register_operand" "r,r") 7196 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]))) 7197 (clobber (reg:CC CC_REGNUM))] 7198 "TARGET_ARM" 7199 "* 7200 output_asm_insn (\"cmp\\t%2, %3\", operands); 7201 if (which_alternative != 0) 7202 output_asm_insn (\"mov%D4\\t%0, %1\", operands); 7203 return \"sub%d4\\t%0, %1, #1\"; 7204 " 7205 [(set_attr "conds" "clob") 7206 (set_attr "length" "8,12")] 7207) 7208 7209(define_insn "*cmp_ite0" 7210 [(set (match_operand 6 "dominant_cc_register" "") 7211 (compare 7212 (if_then_else:SI 7213 (match_operator 4 "arm_comparison_operator" 7214 [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 7215 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 7216 (match_operator:SI 5 "arm_comparison_operator" 7217 [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 7218 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]) 7219 (const_int 0)) 7220 (const_int 0)))] 7221 "TARGET_ARM" 7222 "* 7223 { 7224 static const char * const opcodes[4][2] = 7225 { 7226 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\", 7227 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"}, 7228 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", 7229 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"}, 7230 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", 7231 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"}, 7232 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\", 7233 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"} 7234 }; 7235 int swap = 7236 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])); 7237 7238 return opcodes[which_alternative][swap]; 7239 }" 7240 [(set_attr "conds" "set") 7241 (set_attr "length" "8")] 7242) 7243 7244(define_insn "*cmp_ite1" 7245 [(set (match_operand 6 "dominant_cc_register" "") 7246 (compare 7247 (if_then_else:SI 7248 (match_operator 4 "arm_comparison_operator" 7249 [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 7250 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 7251 (match_operator:SI 5 "arm_comparison_operator" 7252 [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 7253 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]) 7254 (const_int 1)) 7255 (const_int 0)))] 7256 "TARGET_ARM" 7257 "* 7258 { 7259 static const char * const opcodes[4][2] = 7260 { 7261 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\", 7262 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"}, 7263 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\", 7264 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"}, 7265 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\", 7266 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"}, 7267 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\", 7268 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"} 7269 }; 7270 int swap = 7271 comparison_dominates_p (GET_CODE (operands[5]), 7272 reverse_condition (GET_CODE (operands[4]))); 7273 7274 return opcodes[which_alternative][swap]; 7275 }" 7276 [(set_attr "conds" "set") 7277 (set_attr "length" "8")] 7278) 7279 7280(define_insn "*cmp_and" 7281 [(set (match_operand 6 "dominant_cc_register" "") 7282 (compare 7283 (and:SI 7284 (match_operator 4 "arm_comparison_operator" 7285 [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 7286 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 7287 (match_operator:SI 5 "arm_comparison_operator" 7288 [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 7289 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])) 7290 (const_int 0)))] 7291 "TARGET_ARM" 7292 "* 7293 { 7294 static const char *const opcodes[4][2] = 7295 { 7296 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\", 7297 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"}, 7298 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", 7299 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"}, 7300 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", 7301 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"}, 7302 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\", 7303 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"} 7304 }; 7305 int swap = 7306 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])); 7307 7308 return opcodes[which_alternative][swap]; 7309 }" 7310 [(set_attr "conds" "set") 7311 (set_attr "predicable" "no") 7312 (set_attr "length" "8")] 7313) 7314 7315(define_insn "*cmp_ior" 7316 [(set (match_operand 6 "dominant_cc_register" "") 7317 (compare 7318 (ior:SI 7319 (match_operator 4 "arm_comparison_operator" 7320 [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 7321 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 7322 (match_operator:SI 5 "arm_comparison_operator" 7323 [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 7324 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])) 7325 (const_int 0)))] 7326 "TARGET_ARM" 7327 "* 7328{ 7329 static const char *const opcodes[4][2] = 7330 { 7331 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\", 7332 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"}, 7333 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\", 7334 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"}, 7335 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\", 7336 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"}, 7337 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\", 7338 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"} 7339 }; 7340 int swap = 7341 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])); 7342 7343 return opcodes[which_alternative][swap]; 7344} 7345" 7346 [(set_attr "conds" "set") 7347 (set_attr "length" "8")] 7348) 7349 7350(define_insn "*negscc" 7351 [(set (match_operand:SI 0 "s_register_operand" "=r") 7352 (neg:SI (match_operator 3 "arm_comparison_operator" 7353 [(match_operand:SI 1 "s_register_operand" "r") 7354 (match_operand:SI 2 "arm_rhs_operand" "rI")]))) 7355 (clobber (reg:CC CC_REGNUM))] 7356 "TARGET_ARM" 7357 "* 7358 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx) 7359 return \"mov\\t%0, %1, asr #31\"; 7360 7361 if (GET_CODE (operands[3]) == NE) 7362 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\"; 7363 7364 if (GET_CODE (operands[3]) == GT) 7365 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\"; 7366 7367 output_asm_insn (\"cmp\\t%1, %2\", operands); 7368 output_asm_insn (\"mov%D3\\t%0, #0\", operands); 7369 return \"mvn%d3\\t%0, #0\"; 7370 " 7371 [(set_attr "conds" "clob") 7372 (set_attr "length" "12")] 7373) 7374 7375(define_insn "movcond" 7376 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 7377 (if_then_else:SI 7378 (match_operator 5 "arm_comparison_operator" 7379 [(match_operand:SI 3 "s_register_operand" "r,r,r") 7380 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")]) 7381 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI") 7382 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 7383 (clobber (reg:CC CC_REGNUM))] 7384 "TARGET_ARM" 7385 "* 7386 if (GET_CODE (operands[5]) == LT 7387 && (operands[4] == const0_rtx)) 7388 { 7389 if (which_alternative != 1 && GET_CODE (operands[1]) == REG) 7390 { 7391 if (operands[2] == const0_rtx) 7392 return \"and\\t%0, %1, %3, asr #31\"; 7393 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\"; 7394 } 7395 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG) 7396 { 7397 if (operands[1] == const0_rtx) 7398 return \"bic\\t%0, %2, %3, asr #31\"; 7399 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\"; 7400 } 7401 /* The only case that falls through to here is when both ops 1 & 2 7402 are constants */ 7403 } 7404 7405 if (GET_CODE (operands[5]) == GE 7406 && (operands[4] == const0_rtx)) 7407 { 7408 if (which_alternative != 1 && GET_CODE (operands[1]) == REG) 7409 { 7410 if (operands[2] == const0_rtx) 7411 return \"bic\\t%0, %1, %3, asr #31\"; 7412 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\"; 7413 } 7414 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG) 7415 { 7416 if (operands[1] == const0_rtx) 7417 return \"and\\t%0, %2, %3, asr #31\"; 7418 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\"; 7419 } 7420 /* The only case that falls through to here is when both ops 1 & 2 7421 are constants */ 7422 } 7423 if (GET_CODE (operands[4]) == CONST_INT 7424 && !const_ok_for_arm (INTVAL (operands[4]))) 7425 output_asm_insn (\"cmn\\t%3, #%n4\", operands); 7426 else 7427 output_asm_insn (\"cmp\\t%3, %4\", operands); 7428 if (which_alternative != 0) 7429 output_asm_insn (\"mov%d5\\t%0, %1\", operands); 7430 if (which_alternative != 1) 7431 output_asm_insn (\"mov%D5\\t%0, %2\", operands); 7432 return \"\"; 7433 " 7434 [(set_attr "conds" "clob") 7435 (set_attr "length" "8,8,12")] 7436) 7437 7438(define_insn "*ifcompare_plus_move" 7439 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7440 (if_then_else:SI (match_operator 6 "arm_comparison_operator" 7441 [(match_operand:SI 4 "s_register_operand" "r,r") 7442 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 7443 (plus:SI 7444 (match_operand:SI 2 "s_register_operand" "r,r") 7445 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")) 7446 (match_operand:SI 1 "arm_rhs_operand" "0,?rI"))) 7447 (clobber (reg:CC CC_REGNUM))] 7448 "TARGET_ARM" 7449 "#" 7450 [(set_attr "conds" "clob") 7451 (set_attr "length" "8,12")] 7452) 7453 7454(define_insn "*if_plus_move" 7455 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r") 7456 (if_then_else:SI 7457 (match_operator 4 "arm_comparison_operator" 7458 [(match_operand 5 "cc_register" "") (const_int 0)]) 7459 (plus:SI 7460 (match_operand:SI 2 "s_register_operand" "r,r,r,r") 7461 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L")) 7462 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))] 7463 "TARGET_ARM" 7464 "@ 7465 add%d4\\t%0, %2, %3 7466 sub%d4\\t%0, %2, #%n3 7467 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1 7468 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1" 7469 [(set_attr "conds" "use") 7470 (set_attr "length" "4,4,8,8") 7471 (set_attr "type" "*,*,*,*")] 7472) 7473 7474(define_insn "*ifcompare_move_plus" 7475 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7476 (if_then_else:SI (match_operator 6 "arm_comparison_operator" 7477 [(match_operand:SI 4 "s_register_operand" "r,r") 7478 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 7479 (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 7480 (plus:SI 7481 (match_operand:SI 2 "s_register_operand" "r,r") 7482 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")))) 7483 (clobber (reg:CC CC_REGNUM))] 7484 "TARGET_ARM" 7485 "#" 7486 [(set_attr "conds" "clob") 7487 (set_attr "length" "8,12")] 7488) 7489 7490(define_insn "*if_move_plus" 7491 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r") 7492 (if_then_else:SI 7493 (match_operator 4 "arm_comparison_operator" 7494 [(match_operand 5 "cc_register" "") (const_int 0)]) 7495 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI") 7496 (plus:SI 7497 (match_operand:SI 2 "s_register_operand" "r,r,r,r") 7498 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))] 7499 "TARGET_ARM" 7500 "@ 7501 add%D4\\t%0, %2, %3 7502 sub%D4\\t%0, %2, #%n3 7503 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1 7504 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1" 7505 [(set_attr "conds" "use") 7506 (set_attr "length" "4,4,8,8") 7507 (set_attr "type" "*,*,*,*")] 7508) 7509 7510(define_insn "*ifcompare_arith_arith" 7511 [(set (match_operand:SI 0 "s_register_operand" "=r") 7512 (if_then_else:SI (match_operator 9 "arm_comparison_operator" 7513 [(match_operand:SI 5 "s_register_operand" "r") 7514 (match_operand:SI 6 "arm_add_operand" "rIL")]) 7515 (match_operator:SI 8 "shiftable_operator" 7516 [(match_operand:SI 1 "s_register_operand" "r") 7517 (match_operand:SI 2 "arm_rhs_operand" "rI")]) 7518 (match_operator:SI 7 "shiftable_operator" 7519 [(match_operand:SI 3 "s_register_operand" "r") 7520 (match_operand:SI 4 "arm_rhs_operand" "rI")]))) 7521 (clobber (reg:CC CC_REGNUM))] 7522 "TARGET_ARM" 7523 "#" 7524 [(set_attr "conds" "clob") 7525 (set_attr "length" "12")] 7526) 7527 7528(define_insn "*if_arith_arith" 7529 [(set (match_operand:SI 0 "s_register_operand" "=r") 7530 (if_then_else:SI (match_operator 5 "arm_comparison_operator" 7531 [(match_operand 8 "cc_register" "") (const_int 0)]) 7532 (match_operator:SI 6 "shiftable_operator" 7533 [(match_operand:SI 1 "s_register_operand" "r") 7534 (match_operand:SI 2 "arm_rhs_operand" "rI")]) 7535 (match_operator:SI 7 "shiftable_operator" 7536 [(match_operand:SI 3 "s_register_operand" "r") 7537 (match_operand:SI 4 "arm_rhs_operand" "rI")])))] 7538 "TARGET_ARM" 7539 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4" 7540 [(set_attr "conds" "use") 7541 (set_attr "length" "8")] 7542) 7543 7544(define_insn "*ifcompare_arith_move" 7545 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7546 (if_then_else:SI (match_operator 6 "arm_comparison_operator" 7547 [(match_operand:SI 2 "s_register_operand" "r,r") 7548 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")]) 7549 (match_operator:SI 7 "shiftable_operator" 7550 [(match_operand:SI 4 "s_register_operand" "r,r") 7551 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")]) 7552 (match_operand:SI 1 "arm_rhs_operand" "0,?rI"))) 7553 (clobber (reg:CC CC_REGNUM))] 7554 "TARGET_ARM" 7555 "* 7556 /* If we have an operation where (op x 0) is the identity operation and 7557 the conditional operator is LT or GE and we are comparing against zero and 7558 everything is in registers then we can do this in two instructions */ 7559 if (operands[3] == const0_rtx 7560 && GET_CODE (operands[7]) != AND 7561 && GET_CODE (operands[5]) == REG 7562 && GET_CODE (operands[1]) == REG 7563 && REGNO (operands[1]) == REGNO (operands[4]) 7564 && REGNO (operands[4]) != REGNO (operands[0])) 7565 { 7566 if (GET_CODE (operands[6]) == LT) 7567 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\"; 7568 else if (GET_CODE (operands[6]) == GE) 7569 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\"; 7570 } 7571 if (GET_CODE (operands[3]) == CONST_INT 7572 && !const_ok_for_arm (INTVAL (operands[3]))) 7573 output_asm_insn (\"cmn\\t%2, #%n3\", operands); 7574 else 7575 output_asm_insn (\"cmp\\t%2, %3\", operands); 7576 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands); 7577 if (which_alternative != 0) 7578 return \"mov%D6\\t%0, %1\"; 7579 return \"\"; 7580 " 7581 [(set_attr "conds" "clob") 7582 (set_attr "length" "8,12")] 7583) 7584 7585(define_insn "*if_arith_move" 7586 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7587 (if_then_else:SI (match_operator 4 "arm_comparison_operator" 7588 [(match_operand 6 "cc_register" "") (const_int 0)]) 7589 (match_operator:SI 5 "shiftable_operator" 7590 [(match_operand:SI 2 "s_register_operand" "r,r") 7591 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) 7592 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))] 7593 "TARGET_ARM" 7594 "@ 7595 %I5%d4\\t%0, %2, %3 7596 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1" 7597 [(set_attr "conds" "use") 7598 (set_attr "length" "4,8") 7599 (set_attr "type" "*,*")] 7600) 7601 7602(define_insn "*ifcompare_move_arith" 7603 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7604 (if_then_else:SI (match_operator 6 "arm_comparison_operator" 7605 [(match_operand:SI 4 "s_register_operand" "r,r") 7606 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 7607 (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 7608 (match_operator:SI 7 "shiftable_operator" 7609 [(match_operand:SI 2 "s_register_operand" "r,r") 7610 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]))) 7611 (clobber (reg:CC CC_REGNUM))] 7612 "TARGET_ARM" 7613 "* 7614 /* If we have an operation where (op x 0) is the identity operation and 7615 the conditional operator is LT or GE and we are comparing against zero and 7616 everything is in registers then we can do this in two instructions */ 7617 if (operands[5] == const0_rtx 7618 && GET_CODE (operands[7]) != AND 7619 && GET_CODE (operands[3]) == REG 7620 && GET_CODE (operands[1]) == REG 7621 && REGNO (operands[1]) == REGNO (operands[2]) 7622 && REGNO (operands[2]) != REGNO (operands[0])) 7623 { 7624 if (GET_CODE (operands[6]) == GE) 7625 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\"; 7626 else if (GET_CODE (operands[6]) == LT) 7627 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\"; 7628 } 7629 7630 if (GET_CODE (operands[5]) == CONST_INT 7631 && !const_ok_for_arm (INTVAL (operands[5]))) 7632 output_asm_insn (\"cmn\\t%4, #%n5\", operands); 7633 else 7634 output_asm_insn (\"cmp\\t%4, %5\", operands); 7635 7636 if (which_alternative != 0) 7637 output_asm_insn (\"mov%d6\\t%0, %1\", operands); 7638 return \"%I7%D6\\t%0, %2, %3\"; 7639 " 7640 [(set_attr "conds" "clob") 7641 (set_attr "length" "8,12")] 7642) 7643 7644(define_insn "*if_move_arith" 7645 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7646 (if_then_else:SI 7647 (match_operator 4 "arm_comparison_operator" 7648 [(match_operand 6 "cc_register" "") (const_int 0)]) 7649 (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 7650 (match_operator:SI 5 "shiftable_operator" 7651 [(match_operand:SI 2 "s_register_operand" "r,r") 7652 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))] 7653 "TARGET_ARM" 7654 "@ 7655 %I5%D4\\t%0, %2, %3 7656 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1" 7657 [(set_attr "conds" "use") 7658 (set_attr "length" "4,8") 7659 (set_attr "type" "*,*")] 7660) 7661 7662(define_insn "*ifcompare_move_not" 7663 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7664 (if_then_else:SI 7665 (match_operator 5 "arm_comparison_operator" 7666 [(match_operand:SI 3 "s_register_operand" "r,r") 7667 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 7668 (match_operand:SI 1 "arm_not_operand" "0,?rIK") 7669 (not:SI 7670 (match_operand:SI 2 "s_register_operand" "r,r")))) 7671 (clobber (reg:CC CC_REGNUM))] 7672 "TARGET_ARM" 7673 "#" 7674 [(set_attr "conds" "clob") 7675 (set_attr "length" "8,12")] 7676) 7677 7678(define_insn "*if_move_not" 7679 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 7680 (if_then_else:SI 7681 (match_operator 4 "arm_comparison_operator" 7682 [(match_operand 3 "cc_register" "") (const_int 0)]) 7683 (match_operand:SI 1 "arm_not_operand" "0,?rI,K") 7684 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))] 7685 "TARGET_ARM" 7686 "@ 7687 mvn%D4\\t%0, %2 7688 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2 7689 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2" 7690 [(set_attr "conds" "use") 7691 (set_attr "length" "4,8,8")] 7692) 7693 7694(define_insn "*ifcompare_not_move" 7695 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7696 (if_then_else:SI 7697 (match_operator 5 "arm_comparison_operator" 7698 [(match_operand:SI 3 "s_register_operand" "r,r") 7699 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 7700 (not:SI 7701 (match_operand:SI 2 "s_register_operand" "r,r")) 7702 (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) 7703 (clobber (reg:CC CC_REGNUM))] 7704 "TARGET_ARM" 7705 "#" 7706 [(set_attr "conds" "clob") 7707 (set_attr "length" "8,12")] 7708) 7709 7710(define_insn "*if_not_move" 7711 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 7712 (if_then_else:SI 7713 (match_operator 4 "arm_comparison_operator" 7714 [(match_operand 3 "cc_register" "") (const_int 0)]) 7715 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r")) 7716 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] 7717 "TARGET_ARM" 7718 "@ 7719 mvn%d4\\t%0, %2 7720 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2 7721 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2" 7722 [(set_attr "conds" "use") 7723 (set_attr "length" "4,8,8")] 7724) 7725 7726(define_insn "*ifcompare_shift_move" 7727 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7728 (if_then_else:SI 7729 (match_operator 6 "arm_comparison_operator" 7730 [(match_operand:SI 4 "s_register_operand" "r,r") 7731 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 7732 (match_operator:SI 7 "shift_operator" 7733 [(match_operand:SI 2 "s_register_operand" "r,r") 7734 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")]) 7735 (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) 7736 (clobber (reg:CC CC_REGNUM))] 7737 "TARGET_ARM" 7738 "#" 7739 [(set_attr "conds" "clob") 7740 (set_attr "length" "8,12")] 7741) 7742 7743(define_insn "*if_shift_move" 7744 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 7745 (if_then_else:SI 7746 (match_operator 5 "arm_comparison_operator" 7747 [(match_operand 6 "cc_register" "") (const_int 0)]) 7748 (match_operator:SI 4 "shift_operator" 7749 [(match_operand:SI 2 "s_register_operand" "r,r,r") 7750 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")]) 7751 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] 7752 "TARGET_ARM" 7753 "@ 7754 mov%d5\\t%0, %2%S4 7755 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4 7756 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4" 7757 [(set_attr "conds" "use") 7758 (set_attr "shift" "2") 7759 (set_attr "length" "4,8,8")] 7760) 7761 7762(define_insn "*ifcompare_move_shift" 7763 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7764 (if_then_else:SI 7765 (match_operator 6 "arm_comparison_operator" 7766 [(match_operand:SI 4 "s_register_operand" "r,r") 7767 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 7768 (match_operand:SI 1 "arm_not_operand" "0,?rIK") 7769 (match_operator:SI 7 "shift_operator" 7770 [(match_operand:SI 2 "s_register_operand" "r,r") 7771 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")]))) 7772 (clobber (reg:CC CC_REGNUM))] 7773 "TARGET_ARM" 7774 "#" 7775 [(set_attr "conds" "clob") 7776 (set_attr "length" "8,12")] 7777) 7778 7779(define_insn "*if_move_shift" 7780 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 7781 (if_then_else:SI 7782 (match_operator 5 "arm_comparison_operator" 7783 [(match_operand 6 "cc_register" "") (const_int 0)]) 7784 (match_operand:SI 1 "arm_not_operand" "0,?rI,K") 7785 (match_operator:SI 4 "shift_operator" 7786 [(match_operand:SI 2 "s_register_operand" "r,r,r") 7787 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))] 7788 "TARGET_ARM" 7789 "@ 7790 mov%D5\\t%0, %2%S4 7791 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4 7792 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4" 7793 [(set_attr "conds" "use") 7794 (set_attr "shift" "2") 7795 (set_attr "length" "4,8,8")] 7796) 7797 7798(define_insn "*ifcompare_shift_shift" 7799 [(set (match_operand:SI 0 "s_register_operand" "=r") 7800 (if_then_else:SI 7801 (match_operator 7 "arm_comparison_operator" 7802 [(match_operand:SI 5 "s_register_operand" "r") 7803 (match_operand:SI 6 "arm_add_operand" "rIL")]) 7804 (match_operator:SI 8 "shift_operator" 7805 [(match_operand:SI 1 "s_register_operand" "r") 7806 (match_operand:SI 2 "arm_rhs_operand" "rM")]) 7807 (match_operator:SI 9 "shift_operator" 7808 [(match_operand:SI 3 "s_register_operand" "r") 7809 (match_operand:SI 4 "arm_rhs_operand" "rM")]))) 7810 (clobber (reg:CC CC_REGNUM))] 7811 "TARGET_ARM" 7812 "#" 7813 [(set_attr "conds" "clob") 7814 (set_attr "length" "12")] 7815) 7816 7817(define_insn "*if_shift_shift" 7818 [(set (match_operand:SI 0 "s_register_operand" "=r") 7819 (if_then_else:SI 7820 (match_operator 5 "arm_comparison_operator" 7821 [(match_operand 8 "cc_register" "") (const_int 0)]) 7822 (match_operator:SI 6 "shift_operator" 7823 [(match_operand:SI 1 "s_register_operand" "r") 7824 (match_operand:SI 2 "arm_rhs_operand" "rM")]) 7825 (match_operator:SI 7 "shift_operator" 7826 [(match_operand:SI 3 "s_register_operand" "r") 7827 (match_operand:SI 4 "arm_rhs_operand" "rM")])))] 7828 "TARGET_ARM" 7829 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7" 7830 [(set_attr "conds" "use") 7831 (set_attr "shift" "1") 7832 (set_attr "length" "8")] 7833) 7834 7835(define_insn "*ifcompare_not_arith" 7836 [(set (match_operand:SI 0 "s_register_operand" "=r") 7837 (if_then_else:SI 7838 (match_operator 6 "arm_comparison_operator" 7839 [(match_operand:SI 4 "s_register_operand" "r") 7840 (match_operand:SI 5 "arm_add_operand" "rIL")]) 7841 (not:SI (match_operand:SI 1 "s_register_operand" "r")) 7842 (match_operator:SI 7 "shiftable_operator" 7843 [(match_operand:SI 2 "s_register_operand" "r") 7844 (match_operand:SI 3 "arm_rhs_operand" "rI")]))) 7845 (clobber (reg:CC CC_REGNUM))] 7846 "TARGET_ARM" 7847 "#" 7848 [(set_attr "conds" "clob") 7849 (set_attr "length" "12")] 7850) 7851 7852(define_insn "*if_not_arith" 7853 [(set (match_operand:SI 0 "s_register_operand" "=r") 7854 (if_then_else:SI 7855 (match_operator 5 "arm_comparison_operator" 7856 [(match_operand 4 "cc_register" "") (const_int 0)]) 7857 (not:SI (match_operand:SI 1 "s_register_operand" "r")) 7858 (match_operator:SI 6 "shiftable_operator" 7859 [(match_operand:SI 2 "s_register_operand" "r") 7860 (match_operand:SI 3 "arm_rhs_operand" "rI")])))] 7861 "TARGET_ARM" 7862 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3" 7863 [(set_attr "conds" "use") 7864 (set_attr "length" "8")] 7865) 7866 7867(define_insn "*ifcompare_arith_not" 7868 [(set (match_operand:SI 0 "s_register_operand" "=r") 7869 (if_then_else:SI 7870 (match_operator 6 "arm_comparison_operator" 7871 [(match_operand:SI 4 "s_register_operand" "r") 7872 (match_operand:SI 5 "arm_add_operand" "rIL")]) 7873 (match_operator:SI 7 "shiftable_operator" 7874 [(match_operand:SI 2 "s_register_operand" "r") 7875 (match_operand:SI 3 "arm_rhs_operand" "rI")]) 7876 (not:SI (match_operand:SI 1 "s_register_operand" "r")))) 7877 (clobber (reg:CC CC_REGNUM))] 7878 "TARGET_ARM" 7879 "#" 7880 [(set_attr "conds" "clob") 7881 (set_attr "length" "12")] 7882) 7883 7884(define_insn "*if_arith_not" 7885 [(set (match_operand:SI 0 "s_register_operand" "=r") 7886 (if_then_else:SI 7887 (match_operator 5 "arm_comparison_operator" 7888 [(match_operand 4 "cc_register" "") (const_int 0)]) 7889 (match_operator:SI 6 "shiftable_operator" 7890 [(match_operand:SI 2 "s_register_operand" "r") 7891 (match_operand:SI 3 "arm_rhs_operand" "rI")]) 7892 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))] 7893 "TARGET_ARM" 7894 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3" 7895 [(set_attr "conds" "use") 7896 (set_attr "length" "8")] 7897) 7898 7899(define_insn "*ifcompare_neg_move" 7900 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7901 (if_then_else:SI 7902 (match_operator 5 "arm_comparison_operator" 7903 [(match_operand:SI 3 "s_register_operand" "r,r") 7904 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 7905 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r")) 7906 (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) 7907 (clobber (reg:CC CC_REGNUM))] 7908 "TARGET_ARM" 7909 "#" 7910 [(set_attr "conds" "clob") 7911 (set_attr "length" "8,12")] 7912) 7913 7914(define_insn "*if_neg_move" 7915 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 7916 (if_then_else:SI 7917 (match_operator 4 "arm_comparison_operator" 7918 [(match_operand 3 "cc_register" "") (const_int 0)]) 7919 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r")) 7920 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] 7921 "TARGET_ARM" 7922 "@ 7923 rsb%d4\\t%0, %2, #0 7924 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0 7925 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0" 7926 [(set_attr "conds" "use") 7927 (set_attr "length" "4,8,8")] 7928) 7929 7930(define_insn "*ifcompare_move_neg" 7931 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7932 (if_then_else:SI 7933 (match_operator 5 "arm_comparison_operator" 7934 [(match_operand:SI 3 "s_register_operand" "r,r") 7935 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 7936 (match_operand:SI 1 "arm_not_operand" "0,?rIK") 7937 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r")))) 7938 (clobber (reg:CC CC_REGNUM))] 7939 "TARGET_ARM" 7940 "#" 7941 [(set_attr "conds" "clob") 7942 (set_attr "length" "8,12")] 7943) 7944 7945(define_insn "*if_move_neg" 7946 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 7947 (if_then_else:SI 7948 (match_operator 4 "arm_comparison_operator" 7949 [(match_operand 3 "cc_register" "") (const_int 0)]) 7950 (match_operand:SI 1 "arm_not_operand" "0,?rI,K") 7951 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))] 7952 "TARGET_ARM" 7953 "@ 7954 rsb%D4\\t%0, %2, #0 7955 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0 7956 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0" 7957 [(set_attr "conds" "use") 7958 (set_attr "length" "4,8,8")] 7959) 7960 7961(define_insn "*arith_adjacentmem" 7962 [(set (match_operand:SI 0 "s_register_operand" "=r") 7963 (match_operator:SI 1 "shiftable_operator" 7964 [(match_operand:SI 2 "memory_operand" "m") 7965 (match_operand:SI 3 "memory_operand" "m")])) 7966 (clobber (match_scratch:SI 4 "=r"))] 7967 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])" 7968 "* 7969 { 7970 rtx ldm[3]; 7971 rtx arith[4]; 7972 int val1 = 0, val2 = 0; 7973 7974 if (REGNO (operands[0]) > REGNO (operands[4])) 7975 { 7976 ldm[1] = operands[4]; 7977 ldm[2] = operands[0]; 7978 } 7979 else 7980 { 7981 ldm[1] = operands[0]; 7982 ldm[2] = operands[4]; 7983 } 7984 if (GET_CODE (XEXP (operands[2], 0)) != REG) 7985 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1)); 7986 if (GET_CODE (XEXP (operands[3], 0)) != REG) 7987 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1)); 7988 arith[0] = operands[0]; 7989 arith[3] = operands[1]; 7990 if (val1 < val2) 7991 { 7992 arith[1] = ldm[1]; 7993 arith[2] = ldm[2]; 7994 } 7995 else 7996 { 7997 arith[1] = ldm[2]; 7998 arith[2] = ldm[1]; 7999 } 8000 if (val1 && val2) 8001 { 8002 rtx ops[3]; 8003 ldm[0] = ops[0] = operands[4]; 8004 ops[1] = XEXP (XEXP (operands[2], 0), 0); 8005 ops[2] = XEXP (XEXP (operands[2], 0), 1); 8006 output_add_immediate (ops); 8007 if (val1 < val2) 8008 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); 8009 else 8010 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); 8011 } 8012 else if (val1) 8013 { 8014 ldm[0] = XEXP (operands[3], 0); 8015 if (val1 < val2) 8016 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); 8017 else 8018 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); 8019 } 8020 else 8021 { 8022 ldm[0] = XEXP (operands[2], 0); 8023 if (val1 < val2) 8024 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); 8025 else 8026 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); 8027 } 8028 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith); 8029 return \"\"; 8030 }" 8031 [(set_attr "length" "12") 8032 (set_attr "predicable" "yes") 8033 (set_attr "type" "load")] 8034) 8035 8036;; the arm can support extended pre-inc instructions 8037 8038;; In all these cases, we use operands 0 and 1 for the register being 8039;; incremented because those are the operands that local-alloc will 8040;; tie and these are the pair most likely to be tieable (and the ones 8041;; that will benefit the most). 8042 8043;; We reject the frame pointer if it occurs anywhere in these patterns since 8044;; elimination will cause too many headaches. 8045 8046(define_insn "*strqi_preinc" 8047 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 8048 (match_operand:SI 2 "index_operand" "rJ"))) 8049 (match_operand:QI 3 "s_register_operand" "r")) 8050 (set (match_operand:SI 0 "s_register_operand" "=r") 8051 (plus:SI (match_dup 1) (match_dup 2)))] 8052 "TARGET_ARM 8053 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8054 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8055 && (GET_CODE (operands[2]) != REG 8056 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8057 "str%?b\\t%3, [%0, %2]!" 8058 [(set_attr "type" "store1") 8059 (set_attr "predicable" "yes")] 8060) 8061 8062(define_insn "*strqi_predec" 8063 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8064 (match_operand:SI 2 "s_register_operand" "r"))) 8065 (match_operand:QI 3 "s_register_operand" "r")) 8066 (set (match_operand:SI 0 "s_register_operand" "=r") 8067 (minus:SI (match_dup 1) (match_dup 2)))] 8068 "TARGET_ARM 8069 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8070 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8071 && (GET_CODE (operands[2]) != REG 8072 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8073 "str%?b\\t%3, [%0, -%2]!" 8074 [(set_attr "type" "store1") 8075 (set_attr "predicable" "yes")] 8076) 8077 8078(define_insn "*loadqi_preinc" 8079 [(set (match_operand:QI 3 "s_register_operand" "=r") 8080 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 8081 (match_operand:SI 2 "index_operand" "rJ")))) 8082 (set (match_operand:SI 0 "s_register_operand" "=r") 8083 (plus:SI (match_dup 1) (match_dup 2)))] 8084 "TARGET_ARM 8085 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8086 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8087 && (GET_CODE (operands[2]) != REG 8088 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8089 "ldr%?b\\t%3, [%0, %2]!" 8090 [(set_attr "type" "load") 8091 (set_attr "predicable" "yes")] 8092) 8093 8094(define_insn "*loadqi_predec" 8095 [(set (match_operand:QI 3 "s_register_operand" "=r") 8096 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8097 (match_operand:SI 2 "s_register_operand" "r")))) 8098 (set (match_operand:SI 0 "s_register_operand" "=r") 8099 (minus:SI (match_dup 1) (match_dup 2)))] 8100 "TARGET_ARM 8101 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8102 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8103 && (GET_CODE (operands[2]) != REG 8104 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8105 "ldr%?b\\t%3, [%0, -%2]!" 8106 [(set_attr "type" "load") 8107 (set_attr "predicable" "yes")] 8108) 8109 8110(define_insn "*loadqisi_preinc" 8111 [(set (match_operand:SI 3 "s_register_operand" "=r") 8112 (zero_extend:SI 8113 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 8114 (match_operand:SI 2 "index_operand" "rJ"))))) 8115 (set (match_operand:SI 0 "s_register_operand" "=r") 8116 (plus:SI (match_dup 1) (match_dup 2)))] 8117 "TARGET_ARM 8118 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8119 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8120 && (GET_CODE (operands[2]) != REG 8121 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8122 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi" 8123 [(set_attr "type" "load") 8124 (set_attr "predicable" "yes")] 8125) 8126 8127(define_insn "*loadqisi_predec" 8128 [(set (match_operand:SI 3 "s_register_operand" "=r") 8129 (zero_extend:SI 8130 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8131 (match_operand:SI 2 "s_register_operand" "r"))))) 8132 (set (match_operand:SI 0 "s_register_operand" "=r") 8133 (minus:SI (match_dup 1) (match_dup 2)))] 8134 "TARGET_ARM 8135 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8136 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8137 && (GET_CODE (operands[2]) != REG 8138 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8139 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi" 8140 [(set_attr "type" "load") 8141 (set_attr "predicable" "yes")] 8142) 8143 8144(define_insn "*strsi_preinc" 8145 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 8146 (match_operand:SI 2 "index_operand" "rJ"))) 8147 (match_operand:SI 3 "s_register_operand" "r")) 8148 (set (match_operand:SI 0 "s_register_operand" "=r") 8149 (plus:SI (match_dup 1) (match_dup 2)))] 8150 "TARGET_ARM 8151 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8152 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8153 && (GET_CODE (operands[2]) != REG 8154 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8155 "str%?\\t%3, [%0, %2]!" 8156 [(set_attr "type" "store1") 8157 (set_attr "predicable" "yes")] 8158) 8159 8160(define_insn "*strsi_predec" 8161 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8162 (match_operand:SI 2 "s_register_operand" "r"))) 8163 (match_operand:SI 3 "s_register_operand" "r")) 8164 (set (match_operand:SI 0 "s_register_operand" "=r") 8165 (minus:SI (match_dup 1) (match_dup 2)))] 8166 "TARGET_ARM 8167 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8168 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8169 && (GET_CODE (operands[2]) != REG 8170 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8171 "str%?\\t%3, [%0, -%2]!" 8172 [(set_attr "type" "store1") 8173 (set_attr "predicable" "yes")] 8174) 8175 8176(define_insn "*loadsi_preinc" 8177 [(set (match_operand:SI 3 "s_register_operand" "=r") 8178 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 8179 (match_operand:SI 2 "index_operand" "rJ")))) 8180 (set (match_operand:SI 0 "s_register_operand" "=r") 8181 (plus:SI (match_dup 1) (match_dup 2)))] 8182 "TARGET_ARM 8183 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8184 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8185 && (GET_CODE (operands[2]) != REG 8186 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8187 "ldr%?\\t%3, [%0, %2]!" 8188 [(set_attr "type" "load") 8189 (set_attr "predicable" "yes")] 8190) 8191 8192(define_insn "*loadsi_predec" 8193 [(set (match_operand:SI 3 "s_register_operand" "=r") 8194 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8195 (match_operand:SI 2 "s_register_operand" "r")))) 8196 (set (match_operand:SI 0 "s_register_operand" "=r") 8197 (minus:SI (match_dup 1) (match_dup 2)))] 8198 "TARGET_ARM 8199 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8200 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8201 && (GET_CODE (operands[2]) != REG 8202 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8203 "ldr%?\\t%3, [%0, -%2]!" 8204 [(set_attr "type" "load") 8205 (set_attr "predicable" "yes")] 8206) 8207 8208(define_insn "*loadhi_preinc" 8209 [(set (match_operand:HI 3 "s_register_operand" "=r") 8210 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 8211 (match_operand:SI 2 "index_operand" "rJ")))) 8212 (set (match_operand:SI 0 "s_register_operand" "=r") 8213 (plus:SI (match_dup 1) (match_dup 2)))] 8214 "TARGET_ARM 8215 && !BYTES_BIG_ENDIAN 8216 && !TARGET_MMU_TRAPS 8217 && !arm_arch4 8218 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8219 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8220 && (GET_CODE (operands[2]) != REG 8221 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8222 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi" 8223 [(set_attr "type" "load") 8224 (set_attr "predicable" "yes")] 8225) 8226 8227(define_insn "*loadhi_predec" 8228 [(set (match_operand:HI 3 "s_register_operand" "=r") 8229 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8230 (match_operand:SI 2 "s_register_operand" "r")))) 8231 (set (match_operand:SI 0 "s_register_operand" "=r") 8232 (minus:SI (match_dup 1) (match_dup 2)))] 8233 "TARGET_ARM 8234 && !BYTES_BIG_ENDIAN 8235 && !TARGET_MMU_TRAPS 8236 && !arm_arch4 8237 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8238 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8239 && (GET_CODE (operands[2]) != REG 8240 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8241 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi" 8242 [(set_attr "type" "load") 8243 (set_attr "predicable" "yes")] 8244) 8245 8246(define_insn "*strqi_shiftpreinc" 8247 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator" 8248 [(match_operand:SI 3 "s_register_operand" "r") 8249 (match_operand:SI 4 "const_shift_operand" "n")]) 8250 (match_operand:SI 1 "s_register_operand" "0"))) 8251 (match_operand:QI 5 "s_register_operand" "r")) 8252 (set (match_operand:SI 0 "s_register_operand" "=r") 8253 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 8254 (match_dup 1)))] 8255 "TARGET_ARM 8256 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8257 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8258 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 8259 "str%?b\\t%5, [%0, %3%S2]!" 8260 [(set_attr "type" "store1") 8261 (set_attr "predicable" "yes")] 8262) 8263 8264(define_insn "*strqi_shiftpredec" 8265 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8266 (match_operator:SI 2 "shift_operator" 8267 [(match_operand:SI 3 "s_register_operand" "r") 8268 (match_operand:SI 4 "const_shift_operand" "n")]))) 8269 (match_operand:QI 5 "s_register_operand" "r")) 8270 (set (match_operand:SI 0 "s_register_operand" "=r") 8271 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 8272 (match_dup 4)])))] 8273 "TARGET_ARM 8274 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8275 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8276 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 8277 "str%?b\\t%5, [%0, -%3%S2]!" 8278 [(set_attr "type" "store1") 8279 (set_attr "predicable" "yes")] 8280) 8281 8282(define_insn "*loadqi_shiftpreinc" 8283 [(set (match_operand:QI 5 "s_register_operand" "=r") 8284 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator" 8285 [(match_operand:SI 3 "s_register_operand" "r") 8286 (match_operand:SI 4 "const_shift_operand" "n")]) 8287 (match_operand:SI 1 "s_register_operand" "0")))) 8288 (set (match_operand:SI 0 "s_register_operand" "=r") 8289 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 8290 (match_dup 1)))] 8291 "TARGET_ARM 8292 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8293 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8294 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 8295 "ldr%?b\\t%5, [%0, %3%S2]!" 8296 [(set_attr "type" "load") 8297 (set_attr "predicable" "yes")] 8298) 8299 8300(define_insn "*loadqi_shiftpredec" 8301 [(set (match_operand:QI 5 "s_register_operand" "=r") 8302 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8303 (match_operator:SI 2 "shift_operator" 8304 [(match_operand:SI 3 "s_register_operand" "r") 8305 (match_operand:SI 4 "const_shift_operand" "n")])))) 8306 (set (match_operand:SI 0 "s_register_operand" "=r") 8307 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 8308 (match_dup 4)])))] 8309 "TARGET_ARM 8310 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8311 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8312 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 8313 "ldr%?b\\t%5, [%0, -%3%S2]!" 8314 [(set_attr "type" "load") 8315 (set_attr "predicable" "yes")] 8316) 8317 8318(define_insn "*strsi_shiftpreinc" 8319 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator" 8320 [(match_operand:SI 3 "s_register_operand" "r") 8321 (match_operand:SI 4 "const_shift_operand" "n")]) 8322 (match_operand:SI 1 "s_register_operand" "0"))) 8323 (match_operand:SI 5 "s_register_operand" "r")) 8324 (set (match_operand:SI 0 "s_register_operand" "=r") 8325 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 8326 (match_dup 1)))] 8327 "TARGET_ARM 8328 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8329 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8330 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 8331 "str%?\\t%5, [%0, %3%S2]!" 8332 [(set_attr "type" "store1") 8333 (set_attr "predicable" "yes")] 8334) 8335 8336(define_insn "*strsi_shiftpredec" 8337 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8338 (match_operator:SI 2 "shift_operator" 8339 [(match_operand:SI 3 "s_register_operand" "r") 8340 (match_operand:SI 4 "const_shift_operand" "n")]))) 8341 (match_operand:SI 5 "s_register_operand" "r")) 8342 (set (match_operand:SI 0 "s_register_operand" "=r") 8343 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 8344 (match_dup 4)])))] 8345 "TARGET_ARM 8346 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8347 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8348 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 8349 "str%?\\t%5, [%0, -%3%S2]!" 8350 [(set_attr "type" "store1") 8351 (set_attr "predicable" "yes")] 8352) 8353 8354(define_insn "*loadsi_shiftpreinc" 8355 [(set (match_operand:SI 5 "s_register_operand" "=r") 8356 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator" 8357 [(match_operand:SI 3 "s_register_operand" "r") 8358 (match_operand:SI 4 "const_shift_operand" "n")]) 8359 (match_operand:SI 1 "s_register_operand" "0")))) 8360 (set (match_operand:SI 0 "s_register_operand" "=r") 8361 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 8362 (match_dup 1)))] 8363 "TARGET_ARM 8364 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8365 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8366 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 8367 "ldr%?\\t%5, [%0, %3%S2]!" 8368 [(set_attr "type" "load") 8369 (set_attr "predicable" "yes")] 8370) 8371 8372(define_insn "*loadsi_shiftpredec" 8373 [(set (match_operand:SI 5 "s_register_operand" "=r") 8374 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8375 (match_operator:SI 2 "shift_operator" 8376 [(match_operand:SI 3 "s_register_operand" "r") 8377 (match_operand:SI 4 "const_shift_operand" "n")])))) 8378 (set (match_operand:SI 0 "s_register_operand" "=r") 8379 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 8380 (match_dup 4)])))] 8381 "TARGET_ARM 8382 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8383 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8384 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 8385 "ldr%?\\t%5, [%0, -%3%S2]!" 8386 [(set_attr "type" "load") 8387 (set_attr "predicable" "yes")]) 8388 8389(define_insn "*loadhi_shiftpreinc" 8390 [(set (match_operand:HI 5 "s_register_operand" "=r") 8391 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator" 8392 [(match_operand:SI 3 "s_register_operand" "r") 8393 (match_operand:SI 4 "const_shift_operand" "n")]) 8394 (match_operand:SI 1 "s_register_operand" "0")))) 8395 (set (match_operand:SI 0 "s_register_operand" "=r") 8396 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 8397 (match_dup 1)))] 8398 "TARGET_ARM 8399 && !BYTES_BIG_ENDIAN 8400 && !TARGET_MMU_TRAPS 8401 && !arm_arch4 8402 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8403 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8404 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 8405 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi" 8406 [(set_attr "type" "load") 8407 (set_attr "predicable" "yes")] 8408) 8409 8410(define_insn "*loadhi_shiftpredec" 8411 [(set (match_operand:HI 5 "s_register_operand" "=r") 8412 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8413 (match_operator:SI 2 "shift_operator" 8414 [(match_operand:SI 3 "s_register_operand" "r") 8415 (match_operand:SI 4 "const_shift_operand" "n")])))) 8416 (set (match_operand:SI 0 "s_register_operand" "=r") 8417 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 8418 (match_dup 4)])))] 8419 "TARGET_ARM 8420 && !BYTES_BIG_ENDIAN 8421 && !TARGET_MMU_TRAPS 8422 && !arm_arch4 8423 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8424 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8425 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 8426 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi" 8427 [(set_attr "type" "load") 8428 (set_attr "predicable" "yes")] 8429) 8430 8431; It can also support extended post-inc expressions, but combine doesn't 8432; try these.... 8433; It doesn't seem worth adding peepholes for anything but the most common 8434; cases since, unlike combine, the increment must immediately follow the load 8435; for this pattern to match. 8436; We must watch to see that the source/destination register isn't also the 8437; same as the base address register, and that if the index is a register, 8438; that it is not the same as the base address register. In such cases the 8439; instruction that we would generate would have UNPREDICTABLE behavior so 8440; we cannot use it. 8441 8442(define_peephole 8443 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r")) 8444 (match_operand:QI 2 "s_register_operand" "r")) 8445 (set (match_dup 0) 8446 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))] 8447 "TARGET_ARM 8448 && (REGNO (operands[2]) != REGNO (operands[0])) 8449 && (GET_CODE (operands[1]) != REG 8450 || (REGNO (operands[1]) != REGNO (operands[0])))" 8451 "str%?b\\t%2, [%0], %1" 8452) 8453 8454(define_peephole 8455 [(set (match_operand:QI 0 "s_register_operand" "=r") 8456 (mem:QI (match_operand:SI 1 "s_register_operand" "+r"))) 8457 (set (match_dup 1) 8458 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))] 8459 "TARGET_ARM 8460 && REGNO (operands[0]) != REGNO(operands[1]) 8461 && (GET_CODE (operands[2]) != REG 8462 || REGNO(operands[0]) != REGNO (operands[2]))" 8463 "ldr%?b\\t%0, [%1], %2" 8464) 8465 8466(define_peephole 8467 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r")) 8468 (match_operand:SI 2 "s_register_operand" "r")) 8469 (set (match_dup 0) 8470 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))] 8471 "TARGET_ARM 8472 && (REGNO (operands[2]) != REGNO (operands[0])) 8473 && (GET_CODE (operands[1]) != REG 8474 || (REGNO (operands[1]) != REGNO (operands[0])))" 8475 "str%?\\t%2, [%0], %1" 8476) 8477 8478(define_peephole 8479 [(set (match_operand:HI 0 "s_register_operand" "=r") 8480 (mem:HI (match_operand:SI 1 "s_register_operand" "+r"))) 8481 (set (match_dup 1) 8482 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))] 8483 "TARGET_ARM 8484 && !BYTES_BIG_ENDIAN 8485 && !TARGET_MMU_TRAPS 8486 && !arm_arch4 8487 && REGNO (operands[0]) != REGNO(operands[1]) 8488 && (GET_CODE (operands[2]) != REG 8489 || REGNO(operands[0]) != REGNO (operands[2]))" 8490 "ldr%?\\t%0, [%1], %2\\t%@ loadhi" 8491) 8492 8493(define_peephole 8494 [(set (match_operand:SI 0 "s_register_operand" "=r") 8495 (mem:SI (match_operand:SI 1 "s_register_operand" "+r"))) 8496 (set (match_dup 1) 8497 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))] 8498 "TARGET_ARM 8499 && REGNO (operands[0]) != REGNO(operands[1]) 8500 && (GET_CODE (operands[2]) != REG 8501 || REGNO(operands[0]) != REGNO (operands[2]))" 8502 "ldr%?\\t%0, [%1], %2" 8503) 8504 8505(define_peephole 8506 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r") 8507 (match_operand:SI 1 "index_operand" "rJ"))) 8508 (match_operand:QI 2 "s_register_operand" "r")) 8509 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))] 8510 "TARGET_ARM 8511 && (REGNO (operands[2]) != REGNO (operands[0])) 8512 && (GET_CODE (operands[1]) != REG 8513 || (REGNO (operands[1]) != REGNO (operands[0])))" 8514 "str%?b\\t%2, [%0, %1]!" 8515) 8516 8517(define_peephole 8518 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator" 8519 [(match_operand:SI 0 "s_register_operand" "r") 8520 (match_operand:SI 1 "const_int_operand" "n")]) 8521 (match_operand:SI 2 "s_register_operand" "+r"))) 8522 (match_operand:QI 3 "s_register_operand" "r")) 8523 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)]) 8524 (match_dup 2)))] 8525 "TARGET_ARM 8526 && (REGNO (operands[3]) != REGNO (operands[2])) 8527 && (REGNO (operands[0]) != REGNO (operands[2]))" 8528 "str%?b\\t%3, [%2, %0%S4]!" 8529) 8530 8531; This pattern is never tried by combine, so do it as a peephole 8532 8533(define_peephole2 8534 [(set (match_operand:SI 0 "s_register_operand" "") 8535 (match_operand:SI 1 "s_register_operand" "")) 8536 (set (reg:CC CC_REGNUM) 8537 (compare:CC (match_dup 1) (const_int 0)))] 8538 "TARGET_ARM 8539 " 8540 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0))) 8541 (set (match_dup 0) (match_dup 1))])] 8542 "" 8543) 8544 8545; Peepholes to spot possible load- and store-multiples, if the ordering is 8546; reversed, check that the memory references aren't volatile. 8547 8548(define_peephole 8549 [(set (match_operand:SI 0 "s_register_operand" "=r") 8550 (match_operand:SI 4 "memory_operand" "m")) 8551 (set (match_operand:SI 1 "s_register_operand" "=r") 8552 (match_operand:SI 5 "memory_operand" "m")) 8553 (set (match_operand:SI 2 "s_register_operand" "=r") 8554 (match_operand:SI 6 "memory_operand" "m")) 8555 (set (match_operand:SI 3 "s_register_operand" "=r") 8556 (match_operand:SI 7 "memory_operand" "m"))] 8557 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)" 8558 "* 8559 return emit_ldm_seq (operands, 4); 8560 " 8561) 8562 8563(define_peephole 8564 [(set (match_operand:SI 0 "s_register_operand" "=r") 8565 (match_operand:SI 3 "memory_operand" "m")) 8566 (set (match_operand:SI 1 "s_register_operand" "=r") 8567 (match_operand:SI 4 "memory_operand" "m")) 8568 (set (match_operand:SI 2 "s_register_operand" "=r") 8569 (match_operand:SI 5 "memory_operand" "m"))] 8570 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)" 8571 "* 8572 return emit_ldm_seq (operands, 3); 8573 " 8574) 8575 8576(define_peephole 8577 [(set (match_operand:SI 0 "s_register_operand" "=r") 8578 (match_operand:SI 2 "memory_operand" "m")) 8579 (set (match_operand:SI 1 "s_register_operand" "=r") 8580 (match_operand:SI 3 "memory_operand" "m"))] 8581 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)" 8582 "* 8583 return emit_ldm_seq (operands, 2); 8584 " 8585) 8586 8587(define_peephole 8588 [(set (match_operand:SI 4 "memory_operand" "=m") 8589 (match_operand:SI 0 "s_register_operand" "r")) 8590 (set (match_operand:SI 5 "memory_operand" "=m") 8591 (match_operand:SI 1 "s_register_operand" "r")) 8592 (set (match_operand:SI 6 "memory_operand" "=m") 8593 (match_operand:SI 2 "s_register_operand" "r")) 8594 (set (match_operand:SI 7 "memory_operand" "=m") 8595 (match_operand:SI 3 "s_register_operand" "r"))] 8596 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)" 8597 "* 8598 return emit_stm_seq (operands, 4); 8599 " 8600) 8601 8602(define_peephole 8603 [(set (match_operand:SI 3 "memory_operand" "=m") 8604 (match_operand:SI 0 "s_register_operand" "r")) 8605 (set (match_operand:SI 4 "memory_operand" "=m") 8606 (match_operand:SI 1 "s_register_operand" "r")) 8607 (set (match_operand:SI 5 "memory_operand" "=m") 8608 (match_operand:SI 2 "s_register_operand" "r"))] 8609 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)" 8610 "* 8611 return emit_stm_seq (operands, 3); 8612 " 8613) 8614 8615(define_peephole 8616 [(set (match_operand:SI 2 "memory_operand" "=m") 8617 (match_operand:SI 0 "s_register_operand" "r")) 8618 (set (match_operand:SI 3 "memory_operand" "=m") 8619 (match_operand:SI 1 "s_register_operand" "r"))] 8620 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)" 8621 "* 8622 return emit_stm_seq (operands, 2); 8623 " 8624) 8625 8626(define_split 8627 [(set (match_operand:SI 0 "s_register_operand" "") 8628 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "") 8629 (const_int 0)) 8630 (neg:SI (match_operator:SI 2 "arm_comparison_operator" 8631 [(match_operand:SI 3 "s_register_operand" "") 8632 (match_operand:SI 4 "arm_rhs_operand" "")])))) 8633 (clobber (match_operand:SI 5 "s_register_operand" ""))] 8634 "TARGET_ARM" 8635 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31)))) 8636 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 8637 (match_dup 5)))] 8638 "" 8639) 8640 8641;; This split can be used because CC_Z mode implies that the following 8642;; branch will be an equality, or an unsigned inequality, so the sign 8643;; extension is not needed. 8644 8645(define_split 8646 [(set (reg:CC_Z CC_REGNUM) 8647 (compare:CC_Z 8648 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0) 8649 (const_int 24)) 8650 (match_operand 1 "const_int_operand" ""))) 8651 (clobber (match_scratch:SI 2 ""))] 8652 "TARGET_ARM 8653 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) 8654 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)" 8655 [(set (match_dup 2) (zero_extend:SI (match_dup 0))) 8656 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))] 8657 " 8658 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24); 8659 " 8660) 8661 8662(define_expand "prologue" 8663 [(clobber (const_int 0))] 8664 "TARGET_EITHER" 8665 "if (TARGET_ARM) 8666 arm_expand_prologue (); 8667 else 8668 thumb_expand_prologue (); 8669 DONE; 8670 " 8671) 8672 8673(define_expand "epilogue" 8674 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)] 8675 "TARGET_EITHER" 8676 " 8677 if (TARGET_THUMB) 8678 thumb_expand_epilogue (); 8679 else if (USE_RETURN_INSN (FALSE)) 8680 { 8681 emit_jump_insn (gen_return ()); 8682 DONE; 8683 } 8684 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode, 8685 gen_rtvec (1, 8686 gen_rtx_RETURN (VOIDmode)), 8687 VUNSPEC_EPILOGUE)); 8688 DONE; 8689 " 8690) 8691 8692;; Note - although unspec_volatile's USE all hard registers, 8693;; USEs are ignored after relaod has completed. Thus we need 8694;; to add an unspec of the link register to ensure that flow 8695;; does not think that it is unused by the sibcall branch that 8696;; will replace the standard function epilogue. 8697(define_insn "sibcall_epilogue" 8698 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE) 8699 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])] 8700 "TARGET_ARM" 8701 "* 8702 if (USE_RETURN_INSN (FALSE)) 8703 return output_return_instruction (const_true_rtx, FALSE, FALSE); 8704 return arm_output_epilogue (FALSE); 8705 " 8706;; Length is absolute worst case 8707 [(set_attr "length" "44") 8708 (set_attr "type" "block") 8709 ;; We don't clobber the conditions, but the potential length of this 8710 ;; operation is sufficient to make conditionalizing the sequence 8711 ;; unlikely to be profitable. 8712 (set_attr "conds" "clob")] 8713) 8714 8715(define_insn "*epilogue_insns" 8716 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)] 8717 "TARGET_EITHER" 8718 "* 8719 if (TARGET_ARM) 8720 return arm_output_epilogue (TRUE); 8721 else /* TARGET_THUMB */ 8722 return thumb_unexpanded_epilogue (); 8723 " 8724 ; Length is absolute worst case 8725 [(set_attr "length" "44") 8726 (set_attr "type" "block") 8727 ;; We don't clobber the conditions, but the potential length of this 8728 ;; operation is sufficient to make conditionalizing the sequence 8729 ;; unlikely to be profitable. 8730 (set_attr "conds" "clob")] 8731) 8732 8733(define_expand "eh_epilogue" 8734 [(use (match_operand:SI 0 "register_operand" "r")) 8735 (use (match_operand:SI 1 "register_operand" "r")) 8736 (use (match_operand:SI 2 "register_operand" "r"))] 8737 "TARGET_EITHER" 8738 " 8739 { 8740 cfun->machine->eh_epilogue_sp_ofs = operands[1]; 8741 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2) 8742 { 8743 rtx ra = gen_rtx_REG (Pmode, 2); 8744 8745 emit_move_insn (ra, operands[2]); 8746 operands[2] = ra; 8747 } 8748 /* This is a hack -- we may have crystalized the function type too 8749 early. */ 8750 cfun->machine->func_type = 0; 8751 }" 8752) 8753 8754;; This split is only used during output to reduce the number of patterns 8755;; that need assembler instructions adding to them. We allowed the setting 8756;; of the conditions to be implicit during rtl generation so that 8757;; the conditional compare patterns would work. However this conflicts to 8758;; some extent with the conditional data operations, so we have to split them 8759;; up again here. 8760 8761(define_split 8762 [(set (match_operand:SI 0 "s_register_operand" "") 8763 (if_then_else:SI (match_operator 1 "arm_comparison_operator" 8764 [(match_operand 2 "" "") (match_operand 3 "" "")]) 8765 (match_dup 0) 8766 (match_operand 4 "" ""))) 8767 (clobber (reg:CC CC_REGNUM))] 8768 "TARGET_ARM && reload_completed" 8769 [(set (match_dup 5) (match_dup 6)) 8770 (cond_exec (match_dup 7) 8771 (set (match_dup 0) (match_dup 4)))] 8772 " 8773 { 8774 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 8775 operands[2], operands[3]); 8776 enum rtx_code rc = GET_CODE (operands[1]); 8777 8778 operands[5] = gen_rtx_REG (mode, CC_REGNUM); 8779 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]); 8780 if (mode == CCFPmode || mode == CCFPEmode) 8781 rc = reverse_condition_maybe_unordered (rc); 8782 else 8783 rc = reverse_condition (rc); 8784 8785 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx); 8786 }" 8787) 8788 8789(define_split 8790 [(set (match_operand:SI 0 "s_register_operand" "") 8791 (if_then_else:SI (match_operator 1 "arm_comparison_operator" 8792 [(match_operand 2 "" "") (match_operand 3 "" "")]) 8793 (match_operand 4 "" "") 8794 (match_dup 0))) 8795 (clobber (reg:CC CC_REGNUM))] 8796 "TARGET_ARM && reload_completed" 8797 [(set (match_dup 5) (match_dup 6)) 8798 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)]) 8799 (set (match_dup 0) (match_dup 4)))] 8800 " 8801 { 8802 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 8803 operands[2], operands[3]); 8804 8805 operands[5] = gen_rtx_REG (mode, CC_REGNUM); 8806 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]); 8807 }" 8808) 8809 8810(define_split 8811 [(set (match_operand:SI 0 "s_register_operand" "") 8812 (if_then_else:SI (match_operator 1 "arm_comparison_operator" 8813 [(match_operand 2 "" "") (match_operand 3 "" "")]) 8814 (match_operand 4 "" "") 8815 (match_operand 5 "" ""))) 8816 (clobber (reg:CC CC_REGNUM))] 8817 "TARGET_ARM && reload_completed" 8818 [(set (match_dup 6) (match_dup 7)) 8819 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)]) 8820 (set (match_dup 0) (match_dup 4))) 8821 (cond_exec (match_dup 8) 8822 (set (match_dup 0) (match_dup 5)))] 8823 " 8824 { 8825 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 8826 operands[2], operands[3]); 8827 enum rtx_code rc = GET_CODE (operands[1]); 8828 8829 operands[6] = gen_rtx_REG (mode, CC_REGNUM); 8830 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]); 8831 if (mode == CCFPmode || mode == CCFPEmode) 8832 rc = reverse_condition_maybe_unordered (rc); 8833 else 8834 rc = reverse_condition (rc); 8835 8836 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx); 8837 }" 8838) 8839 8840(define_split 8841 [(set (match_operand:SI 0 "s_register_operand" "") 8842 (if_then_else:SI (match_operator 1 "arm_comparison_operator" 8843 [(match_operand:SI 2 "s_register_operand" "") 8844 (match_operand:SI 3 "arm_add_operand" "")]) 8845 (match_operand:SI 4 "arm_rhs_operand" "") 8846 (not:SI 8847 (match_operand:SI 5 "s_register_operand" "")))) 8848 (clobber (reg:CC CC_REGNUM))] 8849 "TARGET_ARM && reload_completed" 8850 [(set (match_dup 6) (match_dup 7)) 8851 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)]) 8852 (set (match_dup 0) (match_dup 4))) 8853 (cond_exec (match_dup 8) 8854 (set (match_dup 0) (not:SI (match_dup 5))))] 8855 " 8856 { 8857 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 8858 operands[2], operands[3]); 8859 enum rtx_code rc = GET_CODE (operands[1]); 8860 8861 operands[6] = gen_rtx_REG (mode, CC_REGNUM); 8862 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]); 8863 if (mode == CCFPmode || mode == CCFPEmode) 8864 rc = reverse_condition_maybe_unordered (rc); 8865 else 8866 rc = reverse_condition (rc); 8867 8868 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx); 8869 }" 8870) 8871 8872(define_insn "*cond_move_not" 8873 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8874 (if_then_else:SI (match_operator 4 "arm_comparison_operator" 8875 [(match_operand 3 "cc_register" "") (const_int 0)]) 8876 (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 8877 (not:SI 8878 (match_operand:SI 2 "s_register_operand" "r,r"))))] 8879 "TARGET_ARM" 8880 "@ 8881 mvn%D4\\t%0, %2 8882 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2" 8883 [(set_attr "conds" "use") 8884 (set_attr "length" "4,8")] 8885) 8886 8887;; The next two patterns occur when an AND operation is followed by a 8888;; scc insn sequence 8889 8890(define_insn "*sign_extract_onebit" 8891 [(set (match_operand:SI 0 "s_register_operand" "=r") 8892 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r") 8893 (const_int 1) 8894 (match_operand:SI 2 "const_int_operand" "n"))) 8895 (clobber (reg:CC CC_REGNUM))] 8896 "TARGET_ARM" 8897 "* 8898 operands[2] = GEN_INT (1 << INTVAL (operands[2])); 8899 output_asm_insn (\"ands\\t%0, %1, %2\", operands); 8900 return \"mvnne\\t%0, #0\"; 8901 " 8902 [(set_attr "conds" "clob") 8903 (set_attr "length" "8")] 8904) 8905 8906(define_insn "*not_signextract_onebit" 8907 [(set (match_operand:SI 0 "s_register_operand" "=r") 8908 (not:SI 8909 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r") 8910 (const_int 1) 8911 (match_operand:SI 2 "const_int_operand" "n")))) 8912 (clobber (reg:CC CC_REGNUM))] 8913 "TARGET_ARM" 8914 "* 8915 operands[2] = GEN_INT (1 << INTVAL (operands[2])); 8916 output_asm_insn (\"tst\\t%1, %2\", operands); 8917 output_asm_insn (\"mvneq\\t%0, #0\", operands); 8918 return \"movne\\t%0, #0\"; 8919 " 8920 [(set_attr "conds" "clob") 8921 (set_attr "length" "12")] 8922) 8923 8924;; Push multiple registers to the stack. Registers are in parallel (use ...) 8925;; expressions. For simplicity, the first register is also in the unspec 8926;; part. 8927(define_insn "*push_multi" 8928 [(match_parallel 2 "multi_register_push" 8929 [(set (match_operand:BLK 0 "memory_operand" "=m") 8930 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 8931 UNSPEC_PUSH_MULT))])] 8932 "TARGET_ARM" 8933 "* 8934 { 8935 int num_saves = XVECLEN (operands[2], 0); 8936 8937 /* For the StrongARM at least it is faster to 8938 use STR to store only a single register. */ 8939 if (num_saves == 1) 8940 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands); 8941 else 8942 { 8943 int i; 8944 char pattern[100]; 8945 8946 strcpy (pattern, \"stmfd\\t%m0!, {%1\"); 8947 8948 for (i = 1; i < num_saves; i++) 8949 { 8950 strcat (pattern, \", %|\"); 8951 strcat (pattern, 8952 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]); 8953 } 8954 8955 strcat (pattern, \"}\"); 8956 output_asm_insn (pattern, operands); 8957 } 8958 8959 return \"\"; 8960 }" 8961 [(set_attr "type" "store4")] 8962) 8963 8964(define_insn "stack_tie" 8965 [(set (mem:BLK (scratch)) 8966 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r") 8967 (match_operand:SI 1 "s_register_operand" "r")] 8968 UNSPEC_PRLG_STK))] 8969 "" 8970 "" 8971 [(set_attr "length" "0")] 8972) 8973 8974;; Similarly for the floating point registers 8975(define_insn "*push_fp_multi" 8976 [(match_parallel 2 "multi_register_push" 8977 [(set (match_operand:BLK 0 "memory_operand" "=m") 8978 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")] 8979 UNSPEC_PUSH_MULT))])] 8980 "TARGET_ARM" 8981 "* 8982 { 8983 char pattern[100]; 8984 8985 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0)); 8986 output_asm_insn (pattern, operands); 8987 return \"\"; 8988 }" 8989 [(set_attr "type" "f_store")] 8990) 8991 8992;; Special patterns for dealing with the constant pool 8993 8994(define_insn "align_4" 8995 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)] 8996 "TARGET_EITHER" 8997 "* 8998 assemble_align (32); 8999 return \"\"; 9000 " 9001) 9002 9003(define_insn "consttable_end" 9004 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)] 9005 "TARGET_EITHER" 9006 "* 9007 making_const_table = FALSE; 9008 return \"\"; 9009 " 9010) 9011 9012(define_insn "consttable_1" 9013 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)] 9014 "TARGET_THUMB" 9015 "* 9016 making_const_table = TRUE; 9017 assemble_integer (operands[0], 1, BITS_PER_WORD, 1); 9018 assemble_zeros (3); 9019 return \"\"; 9020 " 9021 [(set_attr "length" "4")] 9022) 9023 9024(define_insn "consttable_2" 9025 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)] 9026 "TARGET_THUMB" 9027 "* 9028 making_const_table = TRUE; 9029 assemble_integer (operands[0], 2, BITS_PER_WORD, 1); 9030 assemble_zeros (2); 9031 return \"\"; 9032 " 9033 [(set_attr "length" "4")] 9034) 9035 9036(define_insn "consttable_4" 9037 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)] 9038 "TARGET_EITHER" 9039 "* 9040 { 9041 making_const_table = TRUE; 9042 switch (GET_MODE_CLASS (GET_MODE (operands[0]))) 9043 { 9044 case MODE_FLOAT: 9045 { 9046 REAL_VALUE_TYPE r; 9047 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]); 9048 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD); 9049 break; 9050 } 9051 default: 9052 assemble_integer (operands[0], 4, BITS_PER_WORD, 1); 9053 break; 9054 } 9055 return \"\"; 9056 }" 9057 [(set_attr "length" "4")] 9058) 9059 9060(define_insn "consttable_8" 9061 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)] 9062 "TARGET_EITHER" 9063 "* 9064 { 9065 making_const_table = TRUE; 9066 switch (GET_MODE_CLASS (GET_MODE (operands[0]))) 9067 { 9068 case MODE_FLOAT: 9069 { 9070 REAL_VALUE_TYPE r; 9071 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]); 9072 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD); 9073 break; 9074 } 9075 default: 9076 assemble_integer (operands[0], 8, BITS_PER_WORD, 1); 9077 break; 9078 } 9079 return \"\"; 9080 }" 9081 [(set_attr "length" "8")] 9082) 9083 9084;; Miscellaneous Thumb patterns 9085 9086(define_expand "tablejump" 9087 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "l*r")) 9088 (use (label_ref (match_operand 1 "" "")))])] 9089 "TARGET_THUMB" 9090 " 9091 if (flag_pic) 9092 { 9093 /* Hopefully, CSE will eliminate this copy. */ 9094 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1])); 9095 rtx reg2 = gen_reg_rtx (SImode); 9096 9097 emit_insn (gen_addsi3 (reg2, operands[0], reg1)); 9098 operands[0] = reg2; 9099 } 9100 " 9101) 9102 9103(define_insn "*thumb_tablejump" 9104 [(set (pc) (match_operand:SI 0 "register_operand" "l*r")) 9105 (use (label_ref (match_operand 1 "" "")))] 9106 "TARGET_THUMB" 9107 "mov\\t%|pc, %0" 9108 [(set_attr "length" "2")] 9109) 9110 9111;; V5 Instructions, 9112 9113(define_insn "clz" 9114 [(set (match_operand:SI 0 "s_register_operand" "=r") 9115 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] 9116 UNSPEC_CLZ))] 9117 "TARGET_ARM && arm_arch5" 9118 "clz\\t%0, %1") 9119 9120(define_expand "ffssi2" 9121 [(set (match_operand:SI 0 "s_register_operand" "") 9122 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))] 9123 "TARGET_ARM && arm_arch5" 9124 " 9125 { 9126 rtx t1, t2, t3; 9127 9128 t1 = gen_reg_rtx (SImode); 9129 t2 = gen_reg_rtx (SImode); 9130 t3 = gen_reg_rtx (SImode); 9131 9132 emit_insn (gen_negsi2 (t1, operands[1])); 9133 emit_insn (gen_andsi3 (t2, operands[1], t1)); 9134 emit_insn (gen_clz (t3, t2)); 9135 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3)); 9136 DONE; 9137 }" 9138) 9139 9140;; V5E instructions. 9141 9142(define_insn "prefetch" 9143 [(prefetch (match_operand:SI 0 "address_operand" "p") 9144 (match_operand:SI 1 "" "") 9145 (match_operand:SI 2 "" ""))] 9146 "TARGET_ARM && arm_arch5e" 9147 "pld\\t%a0") 9148 9149;; General predication pattern 9150 9151(define_cond_exec 9152 [(match_operator 0 "arm_comparison_operator" 9153 [(match_operand 1 "cc_register" "") 9154 (const_int 0)])] 9155 "TARGET_ARM" 9156 "" 9157) 9158 9159(define_insn "prologue_use" 9160 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)] 9161 "" 9162 "%@ %0 needed for prologue" 9163) 9164