arm.md revision 132718
1;;- Machine description for ARM for GNU compiler 2;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000, 3;; 2001, 2002, 2003 2004 Free Software Foundation, Inc. 4;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl) 5;; and Martin Simmons (@harleqn.co.uk). 6;; More major hacks by Richard Earnshaw (rearnsha@arm.com). 7 8;; This file is part of GCC. 9 10;; GCC is free software; you can redistribute it and/or modify it 11;; under the terms of the GNU General Public License as published 12;; by the Free Software Foundation; either version 2, or (at your 13;; option) any later version. 14 15;; GCC is distributed in the hope that it will be useful, but WITHOUT 16;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 17;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 18;; License for more details. 19 20;; You should have received a copy of the GNU General Public License 21;; along with GCC; see the file COPYING. If not, write to 22;; the Free Software Foundation, 59 Temple Place - Suite 330, 23;; Boston, MA 02111-1307, USA. 24 25;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. 26 27 28;;--------------------------------------------------------------------------- 29;; Constants 30 31;; Register numbers 32(define_constants 33 [(IP_REGNUM 12) ; Scratch register 34 (SP_REGNUM 13) ; Stack pointer 35 (LR_REGNUM 14) ; Return address register 36 (PC_REGNUM 15) ; Program counter 37 (CC_REGNUM 24) ; Condition code pseudo register 38 (LAST_ARM_REGNUM 15) 39 ] 40) 41;; 3rd operand to select_dominance_cc_mode 42(define_constants 43 [(DOM_CC_X_AND_Y 0) 44 (DOM_CC_NX_OR_Y 1) 45 (DOM_CC_X_OR_Y 2) 46 ] 47) 48 49;; UNSPEC Usage: 50;; Note: sin and cos are no-longer used. 51 52(define_constants 53 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT): 54 ; operand 0 is the result, 55 ; operand 1 the parameter. 56 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT): 57 ; operand 0 is the result, 58 ; operand 1 the parameter. 59 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation: 60 ; operand 0 is the first register, 61 ; subsequent registers are in parallel (use ...) 62 ; expressions. 63 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic 64 ; usage, that is, we will add the pic_register 65 ; value to it before trying to dereference it. 66 (UNSPEC_PIC_BASE 4) ; Adding the PC value to the offset to the 67 ; GLOBAL_OFFSET_TABLE. The operation is fully 68 ; described by the RTL but must be wrapped to 69 ; prevent combine from trying to rip it apart. 70 (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses 71 ; being scheduled before the stack adjustment insn. 72 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload, 73 ; this unspec is used to prevent the deletion of 74 ; instructions setting registers for EH handling 75 ; and stack frame generation. Operand 0 is the 76 ; register to "use". 77 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode. 78 (UNSPEC_WSHUFH 8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction. 79 (UNSPEC_WACC 9) ; Used by the intrinsic form of the iWMMXt WACC instruction. 80 (UNSPEC_TMOVMSK 10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction. 81 (UNSPEC_WSAD 11) ; Used by the intrinsic form of the iWMMXt WSAD instruction. 82 (UNSPEC_WSADZ 12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction. 83 (UNSPEC_WMACS 13) ; Used by the intrinsic form of the iWMMXt WMACS instruction. 84 (UNSPEC_WMACU 14) ; Used by the intrinsic form of the iWMMXt WMACU instruction. 85 (UNSPEC_WMACSZ 15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction. 86 (UNSPEC_WMACUZ 16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction. 87 (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction. 88 (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction. 89 (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction. 90 ] 91) 92 93;; UNSPEC_VOLATILE Usage: 94 95(define_constants 96 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an 97 ; insn in the code. 98 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the 99 ; instruction epilogue sequence that isn't expanded 100 ; into normal RTL. Used for both normal and sibcall 101 ; epilogues. 102 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table 103 ; for inlined constants. 104 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool 105 ; table. 106 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for 107 ; an 8-bit object. 108 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for 109 ; a 16-bit object. 110 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for 111 ; a 32-bit object. 112 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for 113 ; a 64-bit object. 114 (VUNSPEC_TMRC 8) ; Used by the iWMMXt TMRC instruction. 115 (VUNSPEC_TMCR 9) ; Used by the iWMMXt TMCR instruction. 116 (VUNSPEC_ALIGN8 10) ; 8-byte alignment version of VUNSPEC_ALIGN 117 (VUNSPEC_WCMP_EQ 11) ; Used by the iWMMXt WCMPEQ instructions 118 (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions 119 (VUNSPEC_WCMP_GT 13) ; Used by the iwMMXT WCMPGT instructions 120 ] 121) 122 123;;--------------------------------------------------------------------------- 124;; Attributes 125 126; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when 127; generating ARM code. This is used to control the length of some insn 128; patterns that share the same RTL in both ARM and Thumb code. 129(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code"))) 130 131; PROG_MODE attribute is used to determine whether condition codes are 132; clobbered by a call insn: they are if in prog32 mode. This is controlled 133; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option. 134(define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode"))) 135 136; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects 137; scheduling decisions for the load unit and the multiplier. 138(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong"))) 139 140;; Operand number of an input operand that is shifted. Zero if the 141;; given instruction does not shift one of its input operands. 142(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale"))) 143(define_attr "shift" "" (const_int 0)) 144 145; Floating Point Unit. If we only have floating point emulation, then there 146; is no point in scheduling the floating point insns. (Well, for best 147; performance we should try and group them together). 148(define_attr "fpu" "softfpa,fpa,fpe2,fpe3,maverick" 149 (const (symbol_ref "arm_fpu_attr"))) 150 151; LENGTH of an instruction (in bytes) 152(define_attr "length" "" (const_int 4)) 153 154; POOL_RANGE is how far away from a constant pool entry that this insn 155; can be placed. If the distance is zero, then this insn will never 156; reference the pool. 157; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry 158; before its address. 159(define_attr "pool_range" "" (const_int 0)) 160(define_attr "neg_pool_range" "" (const_int 0)) 161 162; An assembler sequence may clobber the condition codes without us knowing. 163; If such an insn references the pool, then we have no way of knowing how, 164; so use the most conservative value for pool_range. 165(define_asm_attributes 166 [(set_attr "conds" "clob") 167 (set_attr "length" "4") 168 (set_attr "pool_range" "250")]) 169 170; TYPE attribute is used to detect floating point instructions which, if 171; running on a co-processor can run in parallel with other, basic instructions 172; If write-buffer scheduling is enabled then it can also be used in the 173; scheduling of writes. 174 175; Classification of each insn 176; normal any data instruction that doesn't hit memory or fp regs 177; mult a multiply instruction 178; block blockage insn, this blocks all functional units 179; float a floating point arithmetic operation (subject to expansion) 180; fdivd DFmode floating point division 181; fdivs SFmode floating point division 182; fmul Floating point multiply 183; ffmul Fast floating point multiply 184; farith Floating point arithmetic (4 cycle) 185; ffarith Fast floating point arithmetic (2 cycle) 186; float_em a floating point arithmetic operation that is normally emulated 187; even on a machine with an fpa. 188; f_load a floating point load from memory 189; f_store a floating point store to memory 190; f_mem_r a transfer of a floating point register to a real reg via mem 191; r_mem_f the reverse of f_mem_r 192; f_2_r fast transfer float to arm (no memory needed) 193; r_2_f fast transfer arm to float 194; call a subroutine call 195; load any load from memory 196; store1 store 1 word to memory from arm registers 197; store2 store 2 words 198; store3 store 3 words 199; store4 store 4 words 200; Additions for Cirrus Maverick co-processor: 201; mav_farith Floating point arithmetic (4 cycle) 202; mav_dmult Double multiplies (7 cycle) 203; 204(define_attr "type" 205 "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,mav_farith,mav_dmult" 206 (const_string "normal")) 207 208; Load scheduling, set from the arm_ld_sched variable 209; initialized by arm_override_options() 210(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched"))) 211 212; condition codes: this one is used by final_prescan_insn to speed up 213; conditionalizing instructions. It saves having to scan the rtl to see if 214; it uses or alters the condition codes. 215; 216; USE means that the condition codes are used by the insn in the process of 217; outputting code, this means (at present) that we can't use the insn in 218; inlined branches 219; 220; SET means that the purpose of the insn is to set the condition codes in a 221; well defined manner. 222; 223; CLOB means that the condition codes are altered in an undefined manner, if 224; they are altered at all 225; 226; JUMP_CLOB is used when the condition cannot be represented by a single 227; instruction (UNEQ and LTGT). These cannot be predicated. 228; 229; NOCOND means that the condition codes are neither altered nor affect the 230; output of this insn 231 232(define_attr "conds" "use,set,clob,jump_clob,nocond" 233 (if_then_else (eq_attr "type" "call") 234 (if_then_else (eq_attr "prog_mode" "prog32") 235 (const_string "clob") (const_string "nocond")) 236 (const_string "nocond"))) 237 238; Predicable means that the insn can be conditionally executed based on 239; an automatically added predicate (additional patterns are generated by 240; gen...). We default to 'no' because no Thumb patterns match this rule 241; and not all ARM patterns do. 242(define_attr "predicable" "no,yes" (const_string "no")) 243 244; Only model the write buffer for ARM6 and ARM7. Earlier processors don't 245; have one. Later ones, such as StrongARM, have write-back caches, so don't 246; suffer blockages enough to warrant modelling this (and it can adversely 247; affect the schedule). 248(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7"))) 249 250; WRITE_CONFLICT implies that a read following an unrelated write is likely 251; to stall the processor. Used with model_wbuf above. 252(define_attr "write_conflict" "no,yes" 253 (if_then_else (eq_attr "type" 254 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load") 255 (const_string "yes") 256 (const_string "no"))) 257 258; Classify the insns into those that take one cycle and those that take more 259; than one on the main cpu execution unit. 260(define_attr "core_cycles" "single,multi" 261 (if_then_else (eq_attr "type" 262 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith") 263 (const_string "single") 264 (const_string "multi"))) 265 266;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a 267;; distant label. Only applicable to Thumb code. 268(define_attr "far_jump" "yes,no" (const_string "no")) 269 270(define_automaton "arm") 271 272;; Write buffer 273; 274; Strictly, we should model a 4-deep write buffer for ARM7xx based chips 275; 276; The write buffer on some of the arm6 processors is hard to model exactly. 277; There is room in the buffer for up to two addresses and up to eight words 278; of memory, but the two needn't be split evenly. When writing the two 279; addresses are fully pipelined. However, a read from memory that is not 280; currently in the cache will block until the writes have completed. 281; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so 282; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous 283; (they aren't allowed to be at present) then there is a startup cost of 1MCLK 284; cycle to add as well. 285(define_cpu_unit "write_buf" "arm") 286 287;; Write blockage unit 288; 289; The write_blockage unit models (partially), the fact that reads will stall 290; until the write buffer empties. 291; The f_mem_r and r_mem_f could also block, but they are to the stack, 292; so we don't model them here 293(define_cpu_unit "write_blockage" "arm") 294 295;; Core 296; 297(define_cpu_unit "core" "arm") 298 299(define_insn_reservation "r_mem_f_wbuf" 5 300 (and (eq_attr "model_wbuf" "yes") 301 (eq_attr "type" "r_mem_f")) 302 "core+write_buf*3") 303 304(define_insn_reservation "store1_wbuf" 5 305 (and (eq_attr "model_wbuf" "yes") 306 (eq_attr "type" "store1")) 307 "core+write_buf*3+write_blockage*5") 308 309(define_insn_reservation "store2_wbuf" 7 310 (and (eq_attr "model_wbuf" "yes") 311 (eq_attr "type" "store2")) 312 "core+write_buf*4+write_blockage*7") 313 314(define_insn_reservation "store3_wbuf" 9 315 (and (eq_attr "model_wbuf" "yes") 316 (eq_attr "type" "store3")) 317 "core+write_buf*5+write_blockage*9") 318 319(define_insn_reservation "store4_wbuf" 11 320 (and (eq_attr "model_wbuf" "yes") 321 (eq_attr "type" "store4")) 322 "core+write_buf*6+write_blockage*11") 323 324(define_insn_reservation "store2" 3 325 (and (eq_attr "model_wbuf" "no") 326 (eq_attr "type" "store2")) 327 "core*3") 328 329(define_insn_reservation "store3" 4 330 (and (eq_attr "model_wbuf" "no") 331 (eq_attr "type" "store3")) 332 "core*4") 333 334(define_insn_reservation "store4" 5 335 (and (eq_attr "model_wbuf" "no") 336 (eq_attr "type" "store4")) 337 "core*5") 338 339(define_insn_reservation "store1_ldsched" 1 340 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 341 "core") 342 343(define_insn_reservation "load_ldsched_xscale" 3 344 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 345 (eq_attr "is_xscale" "yes")) 346 "core") 347 348(define_insn_reservation "load_ldsched" 2 349 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 350 (eq_attr "is_xscale" "no")) 351 "core") 352 353(define_insn_reservation "load_or_store" 2 354 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 355 "core*2") 356 357(define_insn_reservation "mult" 16 358 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 359 "core*16") 360 361(define_insn_reservation "mult_ldsched_strongarm" 3 362 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes")) 363 (eq_attr "type" "mult")) 364 "core*2") 365 366(define_insn_reservation "mult_ldsched" 4 367 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no")) 368 (eq_attr "type" "mult")) 369 "core*4") 370 371(define_insn_reservation "multi_cycle" 32 372 (and (eq_attr "core_cycles" "multi") 373 (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 374 "core*32") 375 376(define_insn_reservation "single_cycle" 1 377 (eq_attr "core_cycles" "single") 378 "core") 379 380 381;;--------------------------------------------------------------------------- 382;; Insn patterns 383;; 384;; Addition insns. 385 386;; Note: For DImode insns, there is normally no reason why operands should 387;; not be in the same register, what we don't want is for something being 388;; written to partially overlap something that is an input. 389;; Cirrus 64bit additions should not be split because we have a native 390;; 64bit addition instructions. 391 392(define_expand "adddi3" 393 [(parallel 394 [(set (match_operand:DI 0 "s_register_operand" "") 395 (plus:DI (match_operand:DI 1 "s_register_operand" "") 396 (match_operand:DI 2 "s_register_operand" ""))) 397 (clobber (reg:CC CC_REGNUM))])] 398 "TARGET_EITHER" 399 " 400 if (TARGET_CIRRUS) 401 { 402 if (!cirrus_fp_register (operands[0], DImode)) 403 operands[0] = force_reg (DImode, operands[0]); 404 if (!cirrus_fp_register (operands[1], DImode)) 405 operands[1] = force_reg (DImode, operands[1]); 406 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2])); 407 DONE; 408 } 409 410 if (TARGET_THUMB) 411 { 412 if (GET_CODE (operands[1]) != REG) 413 operands[1] = force_reg (SImode, operands[1]); 414 if (GET_CODE (operands[2]) != REG) 415 operands[2] = force_reg (SImode, operands[2]); 416 } 417 " 418) 419 420(define_insn "*thumb_adddi3" 421 [(set (match_operand:DI 0 "register_operand" "=l") 422 (plus:DI (match_operand:DI 1 "register_operand" "%0") 423 (match_operand:DI 2 "register_operand" "l"))) 424 (clobber (reg:CC CC_REGNUM)) 425 ] 426 "TARGET_THUMB" 427 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2" 428 [(set_attr "length" "4")] 429) 430 431(define_insn_and_split "*arm_adddi3" 432 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 433 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0") 434 (match_operand:DI 2 "s_register_operand" "r, 0"))) 435 (clobber (reg:CC CC_REGNUM))] 436 "TARGET_ARM && !TARGET_CIRRUS" 437 "#" 438 "TARGET_ARM && reload_completed" 439 [(parallel [(set (reg:CC_C CC_REGNUM) 440 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) 441 (match_dup 1))) 442 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) 443 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 444 (plus:SI (match_dup 4) (match_dup 5))))] 445 " 446 { 447 operands[3] = gen_highpart (SImode, operands[0]); 448 operands[0] = gen_lowpart (SImode, operands[0]); 449 operands[4] = gen_highpart (SImode, operands[1]); 450 operands[1] = gen_lowpart (SImode, operands[1]); 451 operands[5] = gen_highpart (SImode, operands[2]); 452 operands[2] = gen_lowpart (SImode, operands[2]); 453 }" 454 [(set_attr "conds" "clob") 455 (set_attr "length" "8")] 456) 457 458(define_insn_and_split "*adddi_sesidi_di" 459 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 460 (plus:DI (sign_extend:DI 461 (match_operand:SI 2 "s_register_operand" "r,r")) 462 (match_operand:DI 1 "s_register_operand" "r,0"))) 463 (clobber (reg:CC CC_REGNUM))] 464 "TARGET_ARM && !TARGET_CIRRUS" 465 "#" 466 "TARGET_ARM && reload_completed" 467 [(parallel [(set (reg:CC_C CC_REGNUM) 468 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) 469 (match_dup 1))) 470 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) 471 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 472 (plus:SI (ashiftrt:SI (match_dup 2) 473 (const_int 31)) 474 (match_dup 4))))] 475 " 476 { 477 operands[3] = gen_highpart (SImode, operands[0]); 478 operands[0] = gen_lowpart (SImode, operands[0]); 479 operands[4] = gen_highpart (SImode, operands[1]); 480 operands[1] = gen_lowpart (SImode, operands[1]); 481 operands[2] = gen_lowpart (SImode, operands[2]); 482 }" 483 [(set_attr "conds" "clob") 484 (set_attr "length" "8")] 485) 486 487(define_insn_and_split "*adddi_zesidi_di" 488 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 489 (plus:DI (zero_extend:DI 490 (match_operand:SI 2 "s_register_operand" "r,r")) 491 (match_operand:DI 1 "s_register_operand" "r,0"))) 492 (clobber (reg:CC CC_REGNUM))] 493 "TARGET_ARM && !TARGET_CIRRUS" 494 "#" 495 "TARGET_ARM && reload_completed" 496 [(parallel [(set (reg:CC_C CC_REGNUM) 497 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) 498 (match_dup 1))) 499 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) 500 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 501 (plus:SI (match_dup 4) (const_int 0))))] 502 " 503 { 504 operands[3] = gen_highpart (SImode, operands[0]); 505 operands[0] = gen_lowpart (SImode, operands[0]); 506 operands[4] = gen_highpart (SImode, operands[1]); 507 operands[1] = gen_lowpart (SImode, operands[1]); 508 operands[2] = gen_lowpart (SImode, operands[2]); 509 }" 510 [(set_attr "conds" "clob") 511 (set_attr "length" "8")] 512) 513 514(define_expand "addsi3" 515 [(set (match_operand:SI 0 "s_register_operand" "") 516 (plus:SI (match_operand:SI 1 "s_register_operand" "") 517 (match_operand:SI 2 "reg_or_int_operand" "")))] 518 "TARGET_EITHER" 519 " 520 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT) 521 { 522 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0], 523 operands[1], 524 (no_new_pseudos ? 0 : preserve_subexpressions_p ())); 525 DONE; 526 } 527 " 528) 529 530; If there is a scratch available, this will be faster than synthesizing the 531; addition. 532(define_peephole2 533 [(match_scratch:SI 3 "r") 534 (set (match_operand:SI 0 "s_register_operand" "") 535 (plus:SI (match_operand:SI 1 "s_register_operand" "") 536 (match_operand:SI 2 "const_int_operand" "")))] 537 "TARGET_ARM && 538 !(const_ok_for_arm (INTVAL (operands[2])) 539 || const_ok_for_arm (-INTVAL (operands[2]))) 540 && const_ok_for_arm (~INTVAL (operands[2]))" 541 [(set (match_dup 3) (match_dup 2)) 542 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))] 543 "" 544) 545 546(define_insn_and_split "*arm_addsi3" 547 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 548 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r") 549 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))] 550 "TARGET_ARM" 551 "@ 552 add%?\\t%0, %1, %2 553 sub%?\\t%0, %1, #%n2 554 #" 555 "TARGET_ARM && 556 GET_CODE (operands[2]) == CONST_INT 557 && !(const_ok_for_arm (INTVAL (operands[2])) 558 || const_ok_for_arm (-INTVAL (operands[2])))" 559 [(clobber (const_int 0))] 560 " 561 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0], 562 operands[1], 0); 563 DONE; 564 " 565 [(set_attr "length" "4,4,16") 566 (set_attr "predicable" "yes")] 567) 568 569;; Register group 'k' is a single register group containing only the stack 570;; register. Trying to reload it will always fail catastrophically, 571;; so never allow those alternatives to match if reloading is needed. 572 573(define_insn "*thumb_addsi3" 574 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k") 575 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k") 576 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))] 577 "TARGET_THUMB" 578 "* 579 static const char * const asms[] = 580 { 581 \"add\\t%0, %0, %2\", 582 \"sub\\t%0, %0, #%n2\", 583 \"add\\t%0, %1, %2\", 584 \"add\\t%0, %0, %2\", 585 \"add\\t%0, %0, %2\", 586 \"add\\t%0, %1, %2\", 587 \"add\\t%0, %1, %2\" 588 }; 589 if ((which_alternative == 2 || which_alternative == 6) 590 && GET_CODE (operands[2]) == CONST_INT 591 && INTVAL (operands[2]) < 0) 592 return \"sub\\t%0, %1, #%n2\"; 593 return asms[which_alternative]; 594 " 595 [(set_attr "length" "2")] 596) 597 598;; Reloading and elimination of the frame pointer can 599;; sometimes cause this optimization to be missed. 600(define_peephole2 601 [(set (match_operand:SI 0 "register_operand" "") 602 (match_operand:SI 1 "const_int_operand" "")) 603 (set (match_dup 0) 604 (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))] 605 "TARGET_THUMB 606 && REGNO (operands[2]) == STACK_POINTER_REGNUM 607 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024 608 && (INTVAL (operands[1]) & 3) == 0" 609 [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))] 610 "" 611) 612 613(define_insn "*addsi3_compare0" 614 [(set (reg:CC_NOOV CC_REGNUM) 615 (compare:CC_NOOV 616 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r") 617 (match_operand:SI 2 "arm_add_operand" "rI,L")) 618 (const_int 0))) 619 (set (match_operand:SI 0 "s_register_operand" "=r,r") 620 (plus:SI (match_dup 1) (match_dup 2)))] 621 "TARGET_ARM" 622 "@ 623 add%?s\\t%0, %1, %2 624 sub%?s\\t%0, %1, #%n2" 625 [(set_attr "conds" "set")] 626) 627 628(define_insn "*addsi3_compare0_scratch" 629 [(set (reg:CC_NOOV CC_REGNUM) 630 (compare:CC_NOOV 631 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r") 632 (match_operand:SI 1 "arm_add_operand" "rI,L")) 633 (const_int 0)))] 634 "TARGET_ARM" 635 "@ 636 cmn%?\\t%0, %1 637 cmp%?\\t%0, #%n1" 638 [(set_attr "conds" "set")] 639) 640 641;; These patterns are the same ones as the two regular addsi3_compare0 642;; patterns, except we write them slightly different - the combiner 643;; tends to generate them this way. 644(define_insn "*addsi3_compare0_for_combiner" 645 [(set (reg:CC CC_REGNUM) 646 (compare:CC 647 (match_operand:SI 1 "s_register_operand" "r,r") 648 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L")))) 649 (set (match_operand:SI 0 "s_register_operand" "=r,r") 650 (plus:SI (match_dup 1) (match_dup 2)))] 651 "TARGET_ARM" 652 "@ 653 add%?s\\t%0, %1, %2 654 sub%?s\\t%0, %1, #%n2" 655 [(set_attr "conds" "set")] 656) 657 658(define_insn "*addsi3_compare0_scratch_for_combiner" 659 [(set (reg:CC CC_REGNUM) 660 (compare:CC 661 (match_operand:SI 0 "s_register_operand" "r,r") 662 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))] 663 "TARGET_ARM" 664 "@ 665 cmn%?\\t%0, %1 666 cmp%?\\t%0, #%n1" 667 [(set_attr "conds" "set")] 668) 669 670;; This is the canonicalization of addsi3_compare0_for_combiner when the 671;; addend is a constant. 672(define_insn "*cmpsi2_addneg" 673 [(set (reg:CC CC_REGNUM) 674 (compare:CC 675 (match_operand:SI 1 "s_register_operand" "r,r") 676 (match_operand:SI 2 "arm_addimm_operand" "I,L"))) 677 (set (match_operand:SI 0 "s_register_operand" "=r,r") 678 (plus:SI (match_dup 1) 679 (match_operand:SI 3 "arm_addimm_operand" "L,I")))] 680 "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])" 681 "@ 682 sub%?s\\t%0, %1, %2 683 add%?s\\t%0, %1, #%n2" 684 [(set_attr "conds" "set")] 685) 686 687;; Convert the sequence 688;; sub rd, rn, #1 689;; cmn rd, #1 (equivalent to cmp rd, #-1) 690;; bne dest 691;; into 692;; subs rd, rn, #1 693;; bcs dest ((unsigned)rn >= 1) 694;; similarly for the beq variant using bcc. 695;; This is a common looping idiom (while (n--)) 696(define_peephole2 697 [(set (match_operand:SI 0 "s_register_operand" "") 698 (plus:SI (match_operand:SI 1 "s_register_operand" "") 699 (const_int -1))) 700 (set (match_operand 2 "cc_register" "") 701 (compare (match_dup 0) (const_int -1))) 702 (set (pc) 703 (if_then_else (match_operator 3 "equality_operator" 704 [(match_dup 2) (const_int 0)]) 705 (match_operand 4 "" "") 706 (match_operand 5 "" "")))] 707 "TARGET_ARM && peep2_reg_dead_p (3, operands[2])" 708 [(parallel[ 709 (set (match_dup 2) 710 (compare:CC 711 (match_dup 1) (const_int 1))) 712 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))]) 713 (set (pc) 714 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)]) 715 (match_dup 4) 716 (match_dup 5)))] 717 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM); 718 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE 719 ? GEU : LTU), 720 VOIDmode, 721 operands[2], const0_rtx);" 722) 723 724;; The next four insns work because they compare the result with one of 725;; the operands, and we know that the use of the condition code is 726;; either GEU or LTU, so we can use the carry flag from the addition 727;; instead of doing the compare a second time. 728(define_insn "*addsi3_compare_op1" 729 [(set (reg:CC_C CC_REGNUM) 730 (compare:CC_C 731 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r") 732 (match_operand:SI 2 "arm_add_operand" "rI,L")) 733 (match_dup 1))) 734 (set (match_operand:SI 0 "s_register_operand" "=r,r") 735 (plus:SI (match_dup 1) (match_dup 2)))] 736 "TARGET_ARM" 737 "@ 738 add%?s\\t%0, %1, %2 739 sub%?s\\t%0, %1, #%n2" 740 [(set_attr "conds" "set")] 741) 742 743(define_insn "*addsi3_compare_op2" 744 [(set (reg:CC_C CC_REGNUM) 745 (compare:CC_C 746 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r") 747 (match_operand:SI 2 "arm_add_operand" "rI,L")) 748 (match_dup 2))) 749 (set (match_operand:SI 0 "s_register_operand" "=r,r") 750 (plus:SI (match_dup 1) (match_dup 2)))] 751 "TARGET_ARM" 752 "@ 753 add%?s\\t%0, %1, %2 754 sub%?s\\t%0, %1, #%n2" 755 [(set_attr "conds" "set")] 756) 757 758(define_insn "*compare_addsi2_op0" 759 [(set (reg:CC_C CC_REGNUM) 760 (compare:CC_C 761 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r") 762 (match_operand:SI 1 "arm_add_operand" "rI,L")) 763 (match_dup 0)))] 764 "TARGET_ARM" 765 "@ 766 cmn%?\\t%0, %1 767 cmp%?\\t%0, #%n1" 768 [(set_attr "conds" "set")] 769) 770 771(define_insn "*compare_addsi2_op1" 772 [(set (reg:CC_C CC_REGNUM) 773 (compare:CC_C 774 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r") 775 (match_operand:SI 1 "arm_add_operand" "rI,L")) 776 (match_dup 1)))] 777 "TARGET_ARM" 778 "@ 779 cmn%?\\t%0, %1 780 cmp%?\\t%0, #%n1" 781 [(set_attr "conds" "set")] 782) 783 784(define_insn "*addsi3_carryin" 785 [(set (match_operand:SI 0 "s_register_operand" "=r") 786 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 787 (plus:SI (match_operand:SI 1 "s_register_operand" "r") 788 (match_operand:SI 2 "arm_rhs_operand" "rI"))))] 789 "TARGET_ARM" 790 "adc%?\\t%0, %1, %2" 791 [(set_attr "conds" "use")] 792) 793 794(define_insn "*addsi3_carryin_shift" 795 [(set (match_operand:SI 0 "s_register_operand" "=r") 796 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 797 (plus:SI 798 (match_operator:SI 2 "shift_operator" 799 [(match_operand:SI 3 "s_register_operand" "r") 800 (match_operand:SI 4 "reg_or_int_operand" "rM")]) 801 (match_operand:SI 1 "s_register_operand" "r"))))] 802 "TARGET_ARM" 803 "adc%?\\t%0, %1, %3%S2" 804 [(set_attr "conds" "use")] 805) 806 807(define_insn "*addsi3_carryin_alt1" 808 [(set (match_operand:SI 0 "s_register_operand" "=r") 809 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r") 810 (match_operand:SI 2 "arm_rhs_operand" "rI")) 811 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] 812 "TARGET_ARM" 813 "adc%?\\t%0, %1, %2" 814 [(set_attr "conds" "use")] 815) 816 817(define_insn "*addsi3_carryin_alt2" 818 [(set (match_operand:SI 0 "s_register_operand" "=r") 819 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 820 (match_operand:SI 1 "s_register_operand" "r")) 821 (match_operand:SI 2 "arm_rhs_operand" "rI")))] 822 "TARGET_ARM" 823 "adc%?\\t%0, %1, %2" 824 [(set_attr "conds" "use")] 825) 826 827(define_insn "*addsi3_carryin_alt3" 828 [(set (match_operand:SI 0 "s_register_operand" "=r") 829 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 830 (match_operand:SI 2 "arm_rhs_operand" "rI")) 831 (match_operand:SI 1 "s_register_operand" "r")))] 832 "TARGET_ARM" 833 "adc%?\\t%0, %1, %2" 834 [(set_attr "conds" "use")] 835) 836 837(define_insn "incscc" 838 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 839 (plus:SI (match_operator:SI 2 "arm_comparison_operator" 840 [(match_operand:CC 3 "cc_register" "") (const_int 0)]) 841 (match_operand:SI 1 "s_register_operand" "0,?r")))] 842 "TARGET_ARM" 843 "@ 844 add%d2\\t%0, %1, #1 845 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1" 846 [(set_attr "conds" "use") 847 (set_attr "length" "4,8")] 848) 849 850; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant. 851(define_split 852 [(set (match_operand:SI 0 "s_register_operand" "") 853 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "") 854 (match_operand:SI 2 "s_register_operand" "")) 855 (const_int -1))) 856 (clobber (match_operand:SI 3 "s_register_operand" ""))] 857 "TARGET_ARM" 858 [(set (match_dup 3) (match_dup 1)) 859 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))] 860 " 861 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1)); 862") 863 864(define_expand "addsf3" 865 [(set (match_operand:SF 0 "s_register_operand" "") 866 (plus:SF (match_operand:SF 1 "s_register_operand" "") 867 (match_operand:SF 2 "fpa_add_operand" "")))] 868 "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 869 " 870 if (TARGET_CIRRUS 871 && !cirrus_fp_register (operands[2], SFmode)) 872 operands[2] = force_reg (SFmode, operands[2]); 873") 874 875(define_expand "adddf3" 876 [(set (match_operand:DF 0 "s_register_operand" "") 877 (plus:DF (match_operand:DF 1 "s_register_operand" "") 878 (match_operand:DF 2 "fpa_add_operand" "")))] 879 "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 880 " 881 if (TARGET_CIRRUS 882 && !cirrus_fp_register (operands[2], DFmode)) 883 operands[2] = force_reg (DFmode, operands[2]); 884") 885 886(define_expand "subdi3" 887 [(parallel 888 [(set (match_operand:DI 0 "s_register_operand" "") 889 (minus:DI (match_operand:DI 1 "s_register_operand" "") 890 (match_operand:DI 2 "s_register_operand" ""))) 891 (clobber (reg:CC CC_REGNUM))])] 892 "TARGET_EITHER" 893 " 894 if (TARGET_CIRRUS 895 && TARGET_ARM 896 && cirrus_fp_register (operands[0], DImode) 897 && cirrus_fp_register (operands[1], DImode)) 898 { 899 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2])); 900 DONE; 901 } 902 903 if (TARGET_THUMB) 904 { 905 if (GET_CODE (operands[1]) != REG) 906 operands[1] = force_reg (SImode, operands[1]); 907 if (GET_CODE (operands[2]) != REG) 908 operands[2] = force_reg (SImode, operands[2]); 909 } 910 " 911) 912 913(define_insn "*arm_subdi3" 914 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r") 915 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0") 916 (match_operand:DI 2 "s_register_operand" "r,0,0"))) 917 (clobber (reg:CC CC_REGNUM))] 918 "TARGET_ARM" 919 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2" 920 [(set_attr "conds" "clob") 921 (set_attr "length" "8")] 922) 923 924(define_insn "*thumb_subdi3" 925 [(set (match_operand:DI 0 "register_operand" "=l") 926 (minus:DI (match_operand:DI 1 "register_operand" "0") 927 (match_operand:DI 2 "register_operand" "l"))) 928 (clobber (reg:CC CC_REGNUM))] 929 "TARGET_THUMB" 930 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2" 931 [(set_attr "length" "4")] 932) 933 934(define_insn "*subdi_di_zesidi" 935 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 936 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0") 937 (zero_extend:DI 938 (match_operand:SI 2 "s_register_operand" "r,r")))) 939 (clobber (reg:CC CC_REGNUM))] 940 "TARGET_ARM" 941 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0" 942 [(set_attr "conds" "clob") 943 (set_attr "length" "8")] 944) 945 946(define_insn "*subdi_di_sesidi" 947 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 948 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0") 949 (sign_extend:DI 950 (match_operand:SI 2 "s_register_operand" "r,r")))) 951 (clobber (reg:CC CC_REGNUM))] 952 "TARGET_ARM" 953 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31" 954 [(set_attr "conds" "clob") 955 (set_attr "length" "8")] 956) 957 958(define_insn "*subdi_zesidi_di" 959 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 960 (minus:DI (zero_extend:DI 961 (match_operand:SI 2 "s_register_operand" "r,r")) 962 (match_operand:DI 1 "s_register_operand" "?r,0"))) 963 (clobber (reg:CC CC_REGNUM))] 964 "TARGET_ARM" 965 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0" 966 [(set_attr "conds" "clob") 967 (set_attr "length" "8")] 968) 969 970(define_insn "*subdi_sesidi_di" 971 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 972 (minus:DI (sign_extend:DI 973 (match_operand:SI 2 "s_register_operand" "r,r")) 974 (match_operand:DI 1 "s_register_operand" "?r,0"))) 975 (clobber (reg:CC CC_REGNUM))] 976 "TARGET_ARM" 977 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31" 978 [(set_attr "conds" "clob") 979 (set_attr "length" "8")] 980) 981 982(define_insn "*subdi_zesidi_zesidi" 983 [(set (match_operand:DI 0 "s_register_operand" "=r") 984 (minus:DI (zero_extend:DI 985 (match_operand:SI 1 "s_register_operand" "r")) 986 (zero_extend:DI 987 (match_operand:SI 2 "s_register_operand" "r")))) 988 (clobber (reg:CC CC_REGNUM))] 989 "TARGET_ARM" 990 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1" 991 [(set_attr "conds" "clob") 992 (set_attr "length" "8")] 993) 994 995(define_expand "subsi3" 996 [(set (match_operand:SI 0 "s_register_operand" "") 997 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "") 998 (match_operand:SI 2 "s_register_operand" "")))] 999 "TARGET_EITHER" 1000 " 1001 if (GET_CODE (operands[1]) == CONST_INT) 1002 { 1003 if (TARGET_ARM) 1004 { 1005 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0], 1006 operands[2], 1007 (no_new_pseudos ? 0 1008 : preserve_subexpressions_p ())); 1009 DONE; 1010 } 1011 else /* TARGET_THUMB */ 1012 operands[1] = force_reg (SImode, operands[1]); 1013 } 1014 " 1015) 1016 1017(define_insn "*thumb_subsi3_insn" 1018 [(set (match_operand:SI 0 "register_operand" "=l") 1019 (minus:SI (match_operand:SI 1 "register_operand" "l") 1020 (match_operand:SI 2 "register_operand" "l")))] 1021 "TARGET_THUMB" 1022 "sub\\t%0, %1, %2" 1023 [(set_attr "length" "2")] 1024) 1025 1026(define_insn_and_split "*arm_subsi3_insn" 1027 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 1028 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n") 1029 (match_operand:SI 2 "s_register_operand" "r,r")))] 1030 "TARGET_ARM" 1031 "@ 1032 rsb%?\\t%0, %2, %1 1033 #" 1034 "TARGET_ARM 1035 && GET_CODE (operands[1]) == CONST_INT 1036 && !const_ok_for_arm (INTVAL (operands[1]))" 1037 [(clobber (const_int 0))] 1038 " 1039 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0], 1040 operands[2], 0); 1041 DONE; 1042 " 1043 [(set_attr "length" "4,16") 1044 (set_attr "predicable" "yes")] 1045) 1046 1047(define_peephole2 1048 [(match_scratch:SI 3 "r") 1049 (set (match_operand:SI 0 "s_register_operand" "") 1050 (minus:SI (match_operand:SI 1 "const_int_operand" "") 1051 (match_operand:SI 2 "s_register_operand" "")))] 1052 "TARGET_ARM 1053 && !const_ok_for_arm (INTVAL (operands[1])) 1054 && const_ok_for_arm (~INTVAL (operands[1]))" 1055 [(set (match_dup 3) (match_dup 1)) 1056 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))] 1057 "" 1058) 1059 1060(define_insn "*subsi3_compare0" 1061 [(set (reg:CC_NOOV CC_REGNUM) 1062 (compare:CC_NOOV 1063 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I") 1064 (match_operand:SI 2 "arm_rhs_operand" "rI,r")) 1065 (const_int 0))) 1066 (set (match_operand:SI 0 "s_register_operand" "=r,r") 1067 (minus:SI (match_dup 1) (match_dup 2)))] 1068 "TARGET_ARM" 1069 "@ 1070 sub%?s\\t%0, %1, %2 1071 rsb%?s\\t%0, %2, %1" 1072 [(set_attr "conds" "set")] 1073) 1074 1075(define_insn "decscc" 1076 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 1077 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r") 1078 (match_operator:SI 2 "arm_comparison_operator" 1079 [(match_operand 3 "cc_register" "") (const_int 0)])))] 1080 "TARGET_ARM" 1081 "@ 1082 sub%d2\\t%0, %1, #1 1083 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1" 1084 [(set_attr "conds" "use") 1085 (set_attr "length" "*,8")] 1086) 1087 1088(define_expand "subsf3" 1089 [(set (match_operand:SF 0 "s_register_operand" "") 1090 (minus:SF (match_operand:SF 1 "fpa_rhs_operand" "") 1091 (match_operand:SF 2 "fpa_rhs_operand" "")))] 1092 "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 1093 " 1094 if (TARGET_CIRRUS) 1095 { 1096 if (!cirrus_fp_register (operands[1], SFmode)) 1097 operands[1] = force_reg (SFmode, operands[1]); 1098 if (!cirrus_fp_register (operands[2], SFmode)) 1099 operands[2] = force_reg (SFmode, operands[2]); 1100 } 1101") 1102 1103(define_expand "subdf3" 1104 [(set (match_operand:DF 0 "s_register_operand" "") 1105 (minus:DF (match_operand:DF 1 "fpa_rhs_operand" "") 1106 (match_operand:DF 2 "fpa_rhs_operand" "")))] 1107 "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 1108 " 1109 if (TARGET_CIRRUS) 1110 { 1111 if (!cirrus_fp_register (operands[1], DFmode)) 1112 operands[1] = force_reg (DFmode, operands[1]); 1113 if (!cirrus_fp_register (operands[2], DFmode)) 1114 operands[2] = force_reg (DFmode, operands[2]); 1115 } 1116") 1117 1118 1119;; Multiplication insns 1120 1121(define_expand "mulsi3" 1122 [(set (match_operand:SI 0 "s_register_operand" "") 1123 (mult:SI (match_operand:SI 2 "s_register_operand" "") 1124 (match_operand:SI 1 "s_register_operand" "")))] 1125 "TARGET_EITHER" 1126 "" 1127) 1128 1129;; Use `&' and then `0' to prevent the operands 0 and 1 being the same 1130(define_insn "*arm_mulsi3" 1131 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r") 1132 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r") 1133 (match_operand:SI 1 "s_register_operand" "%?r,0")))] 1134 "TARGET_ARM" 1135 "mul%?\\t%0, %2, %1" 1136 [(set_attr "type" "mult") 1137 (set_attr "predicable" "yes")] 1138) 1139 1140; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 1141; 1 and 2; are the same, because reload will make operand 0 match 1142; operand 1 without realizing that this conflicts with operand 2. We fix 1143; this by adding another alternative to match this case, and then `reload' 1144; it ourselves. This alternative must come first. 1145(define_insn "*thumb_mulsi3" 1146 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l") 1147 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0") 1148 (match_operand:SI 2 "register_operand" "l,l,l")))] 1149 "TARGET_THUMB" 1150 "* 1151 if (which_alternative < 2) 1152 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\"; 1153 else 1154 return \"mul\\t%0, %0, %2\"; 1155 " 1156 [(set_attr "length" "4,4,2") 1157 (set_attr "type" "mult")] 1158) 1159 1160(define_insn "*mulsi3_compare0" 1161 [(set (reg:CC_NOOV CC_REGNUM) 1162 (compare:CC_NOOV (mult:SI 1163 (match_operand:SI 2 "s_register_operand" "r,r") 1164 (match_operand:SI 1 "s_register_operand" "%?r,0")) 1165 (const_int 0))) 1166 (set (match_operand:SI 0 "s_register_operand" "=&r,&r") 1167 (mult:SI (match_dup 2) (match_dup 1)))] 1168 "TARGET_ARM && !arm_arch_xscale" 1169 "mul%?s\\t%0, %2, %1" 1170 [(set_attr "conds" "set") 1171 (set_attr "type" "mult")] 1172) 1173 1174(define_insn "*mulsi_compare0_scratch" 1175 [(set (reg:CC_NOOV CC_REGNUM) 1176 (compare:CC_NOOV (mult:SI 1177 (match_operand:SI 2 "s_register_operand" "r,r") 1178 (match_operand:SI 1 "s_register_operand" "%?r,0")) 1179 (const_int 0))) 1180 (clobber (match_scratch:SI 0 "=&r,&r"))] 1181 "TARGET_ARM && !arm_arch_xscale" 1182 "mul%?s\\t%0, %2, %1" 1183 [(set_attr "conds" "set") 1184 (set_attr "type" "mult")] 1185) 1186 1187;; Unnamed templates to match MLA instruction. 1188 1189(define_insn "*mulsi3addsi" 1190 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r") 1191 (plus:SI 1192 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r") 1193 (match_operand:SI 1 "s_register_operand" "%r,0,r,0")) 1194 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))] 1195 "TARGET_ARM" 1196 "mla%?\\t%0, %2, %1, %3" 1197 [(set_attr "type" "mult") 1198 (set_attr "predicable" "yes")] 1199) 1200 1201(define_insn "*mulsi3addsi_compare0" 1202 [(set (reg:CC_NOOV CC_REGNUM) 1203 (compare:CC_NOOV 1204 (plus:SI (mult:SI 1205 (match_operand:SI 2 "s_register_operand" "r,r,r,r") 1206 (match_operand:SI 1 "s_register_operand" "%r,0,r,0")) 1207 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")) 1208 (const_int 0))) 1209 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r") 1210 (plus:SI (mult:SI (match_dup 2) (match_dup 1)) 1211 (match_dup 3)))] 1212 "TARGET_ARM && !arm_arch_xscale" 1213 "mla%?s\\t%0, %2, %1, %3" 1214 [(set_attr "conds" "set") 1215 (set_attr "type" "mult")] 1216) 1217 1218(define_insn "*mulsi3addsi_compare0_scratch" 1219 [(set (reg:CC_NOOV CC_REGNUM) 1220 (compare:CC_NOOV 1221 (plus:SI (mult:SI 1222 (match_operand:SI 2 "s_register_operand" "r,r,r,r") 1223 (match_operand:SI 1 "s_register_operand" "%r,0,r,0")) 1224 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")) 1225 (const_int 0))) 1226 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))] 1227 "TARGET_ARM && !arm_arch_xscale" 1228 "mla%?s\\t%0, %2, %1, %3" 1229 [(set_attr "conds" "set") 1230 (set_attr "type" "mult")] 1231) 1232 1233;; Unnamed template to match long long multiply-accumulate (smlal) 1234 1235(define_insn "*mulsidi3adddi" 1236 [(set (match_operand:DI 0 "s_register_operand" "=&r") 1237 (plus:DI 1238 (mult:DI 1239 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r")) 1240 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r"))) 1241 (match_operand:DI 1 "s_register_operand" "0")))] 1242 "TARGET_ARM && arm_fast_multiply" 1243 "smlal%?\\t%Q0, %R0, %3, %2" 1244 [(set_attr "type" "mult") 1245 (set_attr "predicable" "yes")] 1246) 1247 1248(define_insn "mulsidi3" 1249 [(set (match_operand:DI 0 "s_register_operand" "=&r") 1250 (mult:DI 1251 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r")) 1252 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))] 1253 "TARGET_ARM && arm_fast_multiply" 1254 "smull%?\\t%Q0, %R0, %1, %2" 1255 [(set_attr "type" "mult") 1256 (set_attr "predicable" "yes")] 1257) 1258 1259(define_insn "umulsidi3" 1260 [(set (match_operand:DI 0 "s_register_operand" "=&r") 1261 (mult:DI 1262 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r")) 1263 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))] 1264 "TARGET_ARM && arm_fast_multiply" 1265 "umull%?\\t%Q0, %R0, %1, %2" 1266 [(set_attr "type" "mult") 1267 (set_attr "predicable" "yes")] 1268) 1269 1270;; Unnamed template to match long long unsigned multiply-accumulate (umlal) 1271 1272(define_insn "*umulsidi3adddi" 1273 [(set (match_operand:DI 0 "s_register_operand" "=&r") 1274 (plus:DI 1275 (mult:DI 1276 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r")) 1277 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r"))) 1278 (match_operand:DI 1 "s_register_operand" "0")))] 1279 "TARGET_ARM && arm_fast_multiply" 1280 "umlal%?\\t%Q0, %R0, %3, %2" 1281 [(set_attr "type" "mult") 1282 (set_attr "predicable" "yes")] 1283) 1284 1285(define_insn "smulsi3_highpart" 1286 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r") 1287 (truncate:SI 1288 (lshiftrt:DI 1289 (mult:DI 1290 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0")) 1291 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r"))) 1292 (const_int 32)))) 1293 (clobber (match_scratch:SI 3 "=&r,&r"))] 1294 "TARGET_ARM && arm_fast_multiply" 1295 "smull%?\\t%3, %0, %2, %1" 1296 [(set_attr "type" "mult") 1297 (set_attr "predicable" "yes")] 1298) 1299 1300(define_insn "umulsi3_highpart" 1301 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r") 1302 (truncate:SI 1303 (lshiftrt:DI 1304 (mult:DI 1305 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0")) 1306 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r"))) 1307 (const_int 32)))) 1308 (clobber (match_scratch:SI 3 "=&r,&r"))] 1309 "TARGET_ARM && arm_fast_multiply" 1310 "umull%?\\t%3, %0, %2, %1" 1311 [(set_attr "type" "mult") 1312 (set_attr "predicable" "yes")] 1313) 1314 1315(define_insn "mulhisi3" 1316 [(set (match_operand:SI 0 "s_register_operand" "=r") 1317 (mult:SI (sign_extend:SI 1318 (match_operand:HI 1 "s_register_operand" "%r")) 1319 (sign_extend:SI 1320 (match_operand:HI 2 "s_register_operand" "r"))))] 1321 "TARGET_ARM && arm_arch5e" 1322 "smulbb%?\\t%0, %1, %2" 1323 [(set_attr "type" "mult") 1324 (set_attr "predicable" "yes")] 1325) 1326 1327(define_insn "*mulhisi3tb" 1328 [(set (match_operand:SI 0 "s_register_operand" "=r") 1329 (mult:SI (ashiftrt:SI 1330 (match_operand:SI 1 "s_register_operand" "r") 1331 (const_int 16)) 1332 (sign_extend:SI 1333 (match_operand:HI 2 "s_register_operand" "r"))))] 1334 "TARGET_ARM && arm_arch5e" 1335 "smultb%?\\t%0, %1, %2" 1336 [(set_attr "type" "mult") 1337 (set_attr "predicable" "yes")] 1338) 1339 1340(define_insn "*mulhisi3bt" 1341 [(set (match_operand:SI 0 "s_register_operand" "=r") 1342 (mult:SI (sign_extend:SI 1343 (match_operand:HI 1 "s_register_operand" "r")) 1344 (ashiftrt:SI 1345 (match_operand:SI 2 "s_register_operand" "r") 1346 (const_int 16))))] 1347 "TARGET_ARM && arm_arch5e" 1348 "smulbt%?\\t%0, %1, %2" 1349 [(set_attr "type" "mult") 1350 (set_attr "predicable" "yes")] 1351) 1352 1353(define_insn "*mulhisi3tt" 1354 [(set (match_operand:SI 0 "s_register_operand" "=r") 1355 (mult:SI (ashiftrt:SI 1356 (match_operand:SI 1 "s_register_operand" "r") 1357 (const_int 16)) 1358 (ashiftrt:SI 1359 (match_operand:SI 2 "s_register_operand" "r") 1360 (const_int 16))))] 1361 "TARGET_ARM && arm_arch5e" 1362 "smultt%?\\t%0, %1, %2" 1363 [(set_attr "type" "mult") 1364 (set_attr "predicable" "yes")] 1365) 1366 1367(define_insn "*mulhisi3addsi" 1368 [(set (match_operand:SI 0 "s_register_operand" "=r") 1369 (plus:SI (match_operand:SI 1 "s_register_operand" "r") 1370 (mult:SI (sign_extend:SI 1371 (match_operand:HI 2 "s_register_operand" "%r")) 1372 (sign_extend:SI 1373 (match_operand:HI 3 "s_register_operand" "r")))))] 1374 "TARGET_ARM && arm_arch5e" 1375 "smlabb%?\\t%0, %2, %3, %1" 1376 [(set_attr "type" "mult") 1377 (set_attr "predicable" "yes")] 1378) 1379 1380(define_insn "*mulhidi3adddi" 1381 [(set (match_operand:DI 0 "s_register_operand" "=r") 1382 (plus:DI 1383 (match_operand:DI 1 "s_register_operand" "0") 1384 (mult:DI (sign_extend:DI 1385 (match_operand:HI 2 "s_register_operand" "%r")) 1386 (sign_extend:DI 1387 (match_operand:HI 3 "s_register_operand" "r")))))] 1388 "TARGET_ARM && arm_arch5e" 1389 "smlalbb%?\\t%Q0, %R0, %2, %3" 1390 [(set_attr "type" "mult") 1391 (set_attr "predicable" "yes")]) 1392 1393(define_expand "mulsf3" 1394 [(set (match_operand:SF 0 "s_register_operand" "") 1395 (mult:SF (match_operand:SF 1 "s_register_operand" "") 1396 (match_operand:SF 2 "fpa_rhs_operand" "")))] 1397 "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 1398 " 1399 if (TARGET_CIRRUS 1400 && !cirrus_fp_register (operands[2], SFmode)) 1401 operands[2] = force_reg (SFmode, operands[2]); 1402") 1403 1404(define_expand "muldf3" 1405 [(set (match_operand:DF 0 "s_register_operand" "") 1406 (mult:DF (match_operand:DF 1 "s_register_operand" "") 1407 (match_operand:DF 2 "fpa_rhs_operand" "")))] 1408 "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 1409 " 1410 if (TARGET_CIRRUS 1411 && !cirrus_fp_register (operands[2], DFmode)) 1412 operands[2] = force_reg (DFmode, operands[2]); 1413") 1414 1415;; Division insns 1416 1417(define_expand "divsf3" 1418 [(set (match_operand:SF 0 "s_register_operand" "") 1419 (div:SF (match_operand:SF 1 "fpa_rhs_operand" "") 1420 (match_operand:SF 2 "fpa_rhs_operand" "")))] 1421 "TARGET_ARM && TARGET_HARD_FLOAT" 1422 "") 1423 1424(define_expand "divdf3" 1425 [(set (match_operand:DF 0 "s_register_operand" "") 1426 (div:DF (match_operand:DF 1 "fpa_rhs_operand" "") 1427 (match_operand:DF 2 "fpa_rhs_operand" "")))] 1428 "TARGET_ARM && TARGET_HARD_FLOAT" 1429 "") 1430 1431;; Modulo insns 1432 1433(define_expand "modsf3" 1434 [(set (match_operand:SF 0 "s_register_operand" "") 1435 (mod:SF (match_operand:SF 1 "s_register_operand" "") 1436 (match_operand:SF 2 "fpa_rhs_operand" "")))] 1437 "TARGET_ARM && TARGET_HARD_FLOAT" 1438 "") 1439 1440(define_expand "moddf3" 1441 [(set (match_operand:DF 0 "s_register_operand" "") 1442 (mod:DF (match_operand:DF 1 "s_register_operand" "") 1443 (match_operand:DF 2 "fpa_rhs_operand" "")))] 1444 "TARGET_ARM && TARGET_HARD_FLOAT" 1445 "") 1446 1447;; Boolean and,ior,xor insns 1448 1449;; Split up double word logical operations 1450 1451;; Split up simple DImode logical operations. Simply perform the logical 1452;; operation on the upper and lower halves of the registers. 1453(define_split 1454 [(set (match_operand:DI 0 "s_register_operand" "") 1455 (match_operator:DI 6 "logical_binary_operator" 1456 [(match_operand:DI 1 "s_register_operand" "") 1457 (match_operand:DI 2 "s_register_operand" "")]))] 1458 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))" 1459 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)])) 1460 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))] 1461 " 1462 { 1463 operands[3] = gen_highpart (SImode, operands[0]); 1464 operands[0] = gen_lowpart (SImode, operands[0]); 1465 operands[4] = gen_highpart (SImode, operands[1]); 1466 operands[1] = gen_lowpart (SImode, operands[1]); 1467 operands[5] = gen_highpart (SImode, operands[2]); 1468 operands[2] = gen_lowpart (SImode, operands[2]); 1469 }" 1470) 1471 1472(define_split 1473 [(set (match_operand:DI 0 "s_register_operand" "") 1474 (match_operator:DI 6 "logical_binary_operator" 1475 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" "")) 1476 (match_operand:DI 1 "s_register_operand" "")]))] 1477 "TARGET_ARM && reload_completed" 1478 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)])) 1479 (set (match_dup 3) (match_op_dup:SI 6 1480 [(ashiftrt:SI (match_dup 2) (const_int 31)) 1481 (match_dup 4)]))] 1482 " 1483 { 1484 operands[3] = gen_highpart (SImode, operands[0]); 1485 operands[0] = gen_lowpart (SImode, operands[0]); 1486 operands[4] = gen_highpart (SImode, operands[1]); 1487 operands[1] = gen_lowpart (SImode, operands[1]); 1488 operands[5] = gen_highpart (SImode, operands[2]); 1489 operands[2] = gen_lowpart (SImode, operands[2]); 1490 }" 1491) 1492 1493;; The zero extend of operand 2 means we can just copy the high part of 1494;; operand1 into operand0. 1495(define_split 1496 [(set (match_operand:DI 0 "s_register_operand" "") 1497 (ior:DI 1498 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")) 1499 (match_operand:DI 1 "s_register_operand" "")))] 1500 "TARGET_ARM && operands[0] != operands[1] && reload_completed" 1501 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2))) 1502 (set (match_dup 3) (match_dup 4))] 1503 " 1504 { 1505 operands[4] = gen_highpart (SImode, operands[1]); 1506 operands[3] = gen_highpart (SImode, operands[0]); 1507 operands[0] = gen_lowpart (SImode, operands[0]); 1508 operands[1] = gen_lowpart (SImode, operands[1]); 1509 }" 1510) 1511 1512;; The zero extend of operand 2 means we can just copy the high part of 1513;; operand1 into operand0. 1514(define_split 1515 [(set (match_operand:DI 0 "s_register_operand" "") 1516 (xor:DI 1517 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")) 1518 (match_operand:DI 1 "s_register_operand" "")))] 1519 "TARGET_ARM && operands[0] != operands[1] && reload_completed" 1520 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2))) 1521 (set (match_dup 3) (match_dup 4))] 1522 " 1523 { 1524 operands[4] = gen_highpart (SImode, operands[1]); 1525 operands[3] = gen_highpart (SImode, operands[0]); 1526 operands[0] = gen_lowpart (SImode, operands[0]); 1527 operands[1] = gen_lowpart (SImode, operands[1]); 1528 }" 1529) 1530 1531(define_insn "anddi3" 1532 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 1533 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r") 1534 (match_operand:DI 2 "s_register_operand" "r,r")))] 1535 "TARGET_ARM && ! TARGET_IWMMXT" 1536 "#" 1537 [(set_attr "length" "8")] 1538) 1539 1540(define_insn_and_split "*anddi_zesidi_di" 1541 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 1542 (and:DI (zero_extend:DI 1543 (match_operand:SI 2 "s_register_operand" "r,r")) 1544 (match_operand:DI 1 "s_register_operand" "?r,0")))] 1545 "TARGET_ARM" 1546 "#" 1547 "TARGET_ARM && reload_completed" 1548 ; The zero extend of operand 2 clears the high word of the output 1549 ; operand. 1550 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2))) 1551 (set (match_dup 3) (const_int 0))] 1552 " 1553 { 1554 operands[3] = gen_highpart (SImode, operands[0]); 1555 operands[0] = gen_lowpart (SImode, operands[0]); 1556 operands[1] = gen_lowpart (SImode, operands[1]); 1557 }" 1558 [(set_attr "length" "8")] 1559) 1560 1561(define_insn "*anddi_sesdi_di" 1562 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 1563 (and:DI (sign_extend:DI 1564 (match_operand:SI 2 "s_register_operand" "r,r")) 1565 (match_operand:DI 1 "s_register_operand" "?r,0")))] 1566 "TARGET_ARM" 1567 "#" 1568 [(set_attr "length" "8")] 1569) 1570 1571(define_expand "andsi3" 1572 [(set (match_operand:SI 0 "s_register_operand" "") 1573 (and:SI (match_operand:SI 1 "s_register_operand" "") 1574 (match_operand:SI 2 "reg_or_int_operand" "")))] 1575 "TARGET_EITHER" 1576 " 1577 if (TARGET_ARM) 1578 { 1579 if (GET_CODE (operands[2]) == CONST_INT) 1580 { 1581 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0], 1582 operands[1], 1583 (no_new_pseudos 1584 ? 0 : preserve_subexpressions_p ())); 1585 DONE; 1586 } 1587 } 1588 else /* TARGET_THUMB */ 1589 { 1590 if (GET_CODE (operands[2]) != CONST_INT) 1591 operands[2] = force_reg (SImode, operands[2]); 1592 else 1593 { 1594 int i; 1595 1596 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256) 1597 { 1598 operands[2] = force_reg (SImode, 1599 GEN_INT (~INTVAL (operands[2]))); 1600 1601 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1])); 1602 1603 DONE; 1604 } 1605 1606 for (i = 9; i <= 31; i++) 1607 { 1608 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2])) 1609 { 1610 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i), 1611 const0_rtx)); 1612 DONE; 1613 } 1614 else if ((((HOST_WIDE_INT) 1) << i) - 1 1615 == ~INTVAL (operands[2])) 1616 { 1617 rtx shift = GEN_INT (i); 1618 rtx reg = gen_reg_rtx (SImode); 1619 1620 emit_insn (gen_lshrsi3 (reg, operands[1], shift)); 1621 emit_insn (gen_ashlsi3 (operands[0], reg, shift)); 1622 1623 DONE; 1624 } 1625 } 1626 1627 operands[2] = force_reg (SImode, operands[2]); 1628 } 1629 } 1630 " 1631) 1632 1633(define_insn_and_split "*arm_andsi3_insn" 1634 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 1635 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r") 1636 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))] 1637 "TARGET_ARM" 1638 "@ 1639 and%?\\t%0, %1, %2 1640 bic%?\\t%0, %1, #%B2 1641 #" 1642 "TARGET_ARM 1643 && GET_CODE (operands[2]) == CONST_INT 1644 && !(const_ok_for_arm (INTVAL (operands[2])) 1645 || const_ok_for_arm (~INTVAL (operands[2])))" 1646 [(clobber (const_int 0))] 1647 " 1648 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0], 1649 operands[1], 0); 1650 DONE; 1651 " 1652 [(set_attr "length" "4,4,16") 1653 (set_attr "predicable" "yes")] 1654) 1655 1656(define_insn "*thumb_andsi3_insn" 1657 [(set (match_operand:SI 0 "register_operand" "=l") 1658 (and:SI (match_operand:SI 1 "register_operand" "%0") 1659 (match_operand:SI 2 "register_operand" "l")))] 1660 "TARGET_THUMB" 1661 "and\\t%0, %0, %2" 1662 [(set_attr "length" "2")] 1663) 1664 1665(define_insn "*andsi3_compare0" 1666 [(set (reg:CC_NOOV CC_REGNUM) 1667 (compare:CC_NOOV 1668 (and:SI (match_operand:SI 1 "s_register_operand" "r,r") 1669 (match_operand:SI 2 "arm_not_operand" "rI,K")) 1670 (const_int 0))) 1671 (set (match_operand:SI 0 "s_register_operand" "=r,r") 1672 (and:SI (match_dup 1) (match_dup 2)))] 1673 "TARGET_ARM" 1674 "@ 1675 and%?s\\t%0, %1, %2 1676 bic%?s\\t%0, %1, #%B2" 1677 [(set_attr "conds" "set")] 1678) 1679 1680(define_insn "*andsi3_compare0_scratch" 1681 [(set (reg:CC_NOOV CC_REGNUM) 1682 (compare:CC_NOOV 1683 (and:SI (match_operand:SI 0 "s_register_operand" "r,r") 1684 (match_operand:SI 1 "arm_not_operand" "rI,K")) 1685 (const_int 0))) 1686 (clobber (match_scratch:SI 2 "=X,r"))] 1687 "TARGET_ARM" 1688 "@ 1689 tst%?\\t%0, %1 1690 bic%?s\\t%2, %0, #%B1" 1691 [(set_attr "conds" "set")] 1692) 1693 1694(define_insn "*zeroextractsi_compare0_scratch" 1695 [(set (reg:CC_NOOV CC_REGNUM) 1696 (compare:CC_NOOV (zero_extract:SI 1697 (match_operand:SI 0 "s_register_operand" "r") 1698 (match_operand 1 "const_int_operand" "n") 1699 (match_operand 2 "const_int_operand" "n")) 1700 (const_int 0)))] 1701 "TARGET_ARM 1702 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32 1703 && INTVAL (operands[1]) > 0 1704 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8 1705 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)" 1706 "* 1707 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1) 1708 << INTVAL (operands[2])); 1709 output_asm_insn (\"tst%?\\t%0, %1\", operands); 1710 return \"\"; 1711 " 1712 [(set_attr "conds" "set")] 1713) 1714 1715(define_insn "*ne_zeroextractsi" 1716 [(set (match_operand:SI 0 "s_register_operand" "=r") 1717 (ne:SI (zero_extract:SI 1718 (match_operand:SI 1 "s_register_operand" "r") 1719 (match_operand:SI 2 "const_int_operand" "n") 1720 (match_operand:SI 3 "const_int_operand" "n")) 1721 (const_int 0))) 1722 (clobber (reg:CC CC_REGNUM))] 1723 "TARGET_ARM 1724 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32 1725 && INTVAL (operands[2]) > 0 1726 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8 1727 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)" 1728 "* 1729 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1) 1730 << INTVAL (operands[3])); 1731 output_asm_insn (\"ands\\t%0, %1, %2\", operands); 1732 return \"movne\\t%0, #1\"; 1733 " 1734 [(set_attr "conds" "clob") 1735 (set_attr "length" "8")] 1736) 1737 1738(define_split 1739 [(set (match_operand:SI 0 "s_register_operand" "") 1740 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "") 1741 (match_operand:SI 2 "const_int_operand" "") 1742 (match_operand:SI 3 "const_int_operand" ""))) 1743 (clobber (match_operand:SI 4 "s_register_operand" ""))] 1744 "TARGET_THUMB" 1745 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2))) 1746 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))] 1747 "{ 1748 HOST_WIDE_INT temp = INTVAL (operands[2]); 1749 1750 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3])); 1751 operands[3] = GEN_INT (32 - temp); 1752 }" 1753) 1754 1755(define_split 1756 [(set (match_operand:SI 0 "s_register_operand" "") 1757 (match_operator:SI 1 "shiftable_operator" 1758 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "") 1759 (match_operand:SI 3 "const_int_operand" "") 1760 (match_operand:SI 4 "const_int_operand" "")) 1761 (match_operand:SI 5 "s_register_operand" "")])) 1762 (clobber (match_operand:SI 6 "s_register_operand" ""))] 1763 "TARGET_ARM" 1764 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3))) 1765 (set (match_dup 0) 1766 (match_op_dup 1 1767 [(lshiftrt:SI (match_dup 6) (match_dup 4)) 1768 (match_dup 5)]))] 1769 "{ 1770 HOST_WIDE_INT temp = INTVAL (operands[3]); 1771 1772 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4])); 1773 operands[4] = GEN_INT (32 - temp); 1774 }" 1775) 1776 1777(define_split 1778 [(set (match_operand:SI 0 "s_register_operand" "") 1779 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "") 1780 (match_operand:SI 2 "const_int_operand" "") 1781 (match_operand:SI 3 "const_int_operand" "")))] 1782 "TARGET_THUMB" 1783 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2))) 1784 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))] 1785 "{ 1786 HOST_WIDE_INT temp = INTVAL (operands[2]); 1787 1788 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3])); 1789 operands[3] = GEN_INT (32 - temp); 1790 }" 1791) 1792 1793(define_split 1794 [(set (match_operand:SI 0 "s_register_operand" "") 1795 (match_operator:SI 1 "shiftable_operator" 1796 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "") 1797 (match_operand:SI 3 "const_int_operand" "") 1798 (match_operand:SI 4 "const_int_operand" "")) 1799 (match_operand:SI 5 "s_register_operand" "")])) 1800 (clobber (match_operand:SI 6 "s_register_operand" ""))] 1801 "TARGET_ARM" 1802 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3))) 1803 (set (match_dup 0) 1804 (match_op_dup 1 1805 [(ashiftrt:SI (match_dup 6) (match_dup 4)) 1806 (match_dup 5)]))] 1807 "{ 1808 HOST_WIDE_INT temp = INTVAL (operands[3]); 1809 1810 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4])); 1811 operands[4] = GEN_INT (32 - temp); 1812 }" 1813) 1814 1815;;; ??? This pattern is bogus. If operand3 has bits outside the range 1816;;; represented by the bitfield, then this will produce incorrect results. 1817;;; Somewhere, the value needs to be truncated. On targets like the m68k, 1818;;; which have a real bit-field insert instruction, the truncation happens 1819;;; in the bit-field insert instruction itself. Since arm does not have a 1820;;; bit-field insert instruction, we would have to emit code here to truncate 1821;;; the value before we insert. This loses some of the advantage of having 1822;;; this insv pattern, so this pattern needs to be reevalutated. 1823 1824(define_expand "insv" 1825 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "") 1826 (match_operand:SI 1 "general_operand" "") 1827 (match_operand:SI 2 "general_operand" "")) 1828 (match_operand:SI 3 "reg_or_int_operand" ""))] 1829 "TARGET_ARM" 1830 " 1831 { 1832 int start_bit = INTVAL (operands[2]); 1833 int width = INTVAL (operands[1]); 1834 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1; 1835 rtx target, subtarget; 1836 1837 target = operands[0]; 1838 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 1839 subreg as the final target. */ 1840 if (GET_CODE (target) == SUBREG) 1841 { 1842 subtarget = gen_reg_rtx (SImode); 1843 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target))) 1844 < GET_MODE_SIZE (SImode)) 1845 target = SUBREG_REG (target); 1846 } 1847 else 1848 subtarget = target; 1849 1850 if (GET_CODE (operands[3]) == CONST_INT) 1851 { 1852 /* Since we are inserting a known constant, we may be able to 1853 reduce the number of bits that we have to clear so that 1854 the mask becomes simple. */ 1855 /* ??? This code does not check to see if the new mask is actually 1856 simpler. It may not be. */ 1857 rtx op1 = gen_reg_rtx (SImode); 1858 /* ??? Truncate operand3 to fit in the bitfield. See comment before 1859 start of this pattern. */ 1860 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]); 1861 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit); 1862 1863 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2))); 1864 emit_insn (gen_iorsi3 (subtarget, op1, 1865 GEN_INT (op3_value << start_bit))); 1866 } 1867 else if (start_bit == 0 1868 && !(const_ok_for_arm (mask) 1869 || const_ok_for_arm (~mask))) 1870 { 1871 /* A Trick, since we are setting the bottom bits in the word, 1872 we can shift operand[3] up, operand[0] down, OR them together 1873 and rotate the result back again. This takes 3 insns, and 1874 the third might be mergeable into another op. */ 1875 /* The shift up copes with the possibility that operand[3] is 1876 wider than the bitfield. */ 1877 rtx op0 = gen_reg_rtx (SImode); 1878 rtx op1 = gen_reg_rtx (SImode); 1879 1880 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width))); 1881 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1])); 1882 emit_insn (gen_iorsi3 (op1, op1, op0)); 1883 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1])); 1884 } 1885 else if ((width + start_bit == 32) 1886 && !(const_ok_for_arm (mask) 1887 || const_ok_for_arm (~mask))) 1888 { 1889 /* Similar trick, but slightly less efficient. */ 1890 1891 rtx op0 = gen_reg_rtx (SImode); 1892 rtx op1 = gen_reg_rtx (SImode); 1893 1894 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width))); 1895 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1])); 1896 emit_insn (gen_lshrsi3 (op1, op1, operands[1])); 1897 emit_insn (gen_iorsi3 (subtarget, op1, op0)); 1898 } 1899 else 1900 { 1901 rtx op0 = GEN_INT (mask); 1902 rtx op1 = gen_reg_rtx (SImode); 1903 rtx op2 = gen_reg_rtx (SImode); 1904 1905 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask))) 1906 { 1907 rtx tmp = gen_reg_rtx (SImode); 1908 1909 emit_insn (gen_movsi (tmp, op0)); 1910 op0 = tmp; 1911 } 1912 1913 /* Mask out any bits in operand[3] that are not needed. */ 1914 emit_insn (gen_andsi3 (op1, operands[3], op0)); 1915 1916 if (GET_CODE (op0) == CONST_INT 1917 && (const_ok_for_arm (mask << start_bit) 1918 || const_ok_for_arm (~(mask << start_bit)))) 1919 { 1920 op0 = GEN_INT (~(mask << start_bit)); 1921 emit_insn (gen_andsi3 (op2, operands[0], op0)); 1922 } 1923 else 1924 { 1925 if (GET_CODE (op0) == CONST_INT) 1926 { 1927 rtx tmp = gen_reg_rtx (SImode); 1928 1929 emit_insn (gen_movsi (tmp, op0)); 1930 op0 = tmp; 1931 } 1932 1933 if (start_bit != 0) 1934 emit_insn (gen_ashlsi3 (op0, op0, operands[2])); 1935 1936 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0)); 1937 } 1938 1939 if (start_bit != 0) 1940 emit_insn (gen_ashlsi3 (op1, op1, operands[2])); 1941 1942 emit_insn (gen_iorsi3 (subtarget, op1, op2)); 1943 } 1944 1945 if (subtarget != target) 1946 { 1947 /* If TARGET is still a SUBREG, then it must be wider than a word, 1948 so we must be careful only to set the subword we were asked to. */ 1949 if (GET_CODE (target) == SUBREG) 1950 emit_move_insn (target, subtarget); 1951 else 1952 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget)); 1953 } 1954 1955 DONE; 1956 }" 1957) 1958 1959; constants for op 2 will never be given to these patterns. 1960(define_insn_and_split "*anddi_notdi_di" 1961 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 1962 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0")) 1963 (match_operand:DI 2 "s_register_operand" "0,r")))] 1964 "TARGET_ARM" 1965 "#" 1966 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))" 1967 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2))) 1968 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))] 1969 " 1970 { 1971 operands[3] = gen_highpart (SImode, operands[0]); 1972 operands[0] = gen_lowpart (SImode, operands[0]); 1973 operands[4] = gen_highpart (SImode, operands[1]); 1974 operands[1] = gen_lowpart (SImode, operands[1]); 1975 operands[5] = gen_highpart (SImode, operands[2]); 1976 operands[2] = gen_lowpart (SImode, operands[2]); 1977 }" 1978 [(set_attr "length" "8") 1979 (set_attr "predicable" "yes")] 1980) 1981 1982(define_insn_and_split "*anddi_notzesidi_di" 1983 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 1984 (and:DI (not:DI (zero_extend:DI 1985 (match_operand:SI 2 "s_register_operand" "r,r"))) 1986 (match_operand:DI 1 "s_register_operand" "0,?r")))] 1987 "TARGET_ARM" 1988 "@ 1989 bic%?\\t%Q0, %Q1, %2 1990 #" 1991 ; (not (zero_extend ...)) allows us to just copy the high word from 1992 ; operand1 to operand0. 1993 "TARGET_ARM 1994 && reload_completed 1995 && operands[0] != operands[1]" 1996 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1))) 1997 (set (match_dup 3) (match_dup 4))] 1998 " 1999 { 2000 operands[3] = gen_highpart (SImode, operands[0]); 2001 operands[0] = gen_lowpart (SImode, operands[0]); 2002 operands[4] = gen_highpart (SImode, operands[1]); 2003 operands[1] = gen_lowpart (SImode, operands[1]); 2004 }" 2005 [(set_attr "length" "4,8") 2006 (set_attr "predicable" "yes")] 2007) 2008 2009(define_insn_and_split "*anddi_notsesidi_di" 2010 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 2011 (and:DI (not:DI (sign_extend:DI 2012 (match_operand:SI 2 "s_register_operand" "r,r"))) 2013 (match_operand:DI 1 "s_register_operand" "0,r")))] 2014 "TARGET_ARM" 2015 "#" 2016 "TARGET_ARM && reload_completed" 2017 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1))) 2018 (set (match_dup 3) (and:SI (not:SI 2019 (ashiftrt:SI (match_dup 2) (const_int 31))) 2020 (match_dup 4)))] 2021 " 2022 { 2023 operands[3] = gen_highpart (SImode, operands[0]); 2024 operands[0] = gen_lowpart (SImode, operands[0]); 2025 operands[4] = gen_highpart (SImode, operands[1]); 2026 operands[1] = gen_lowpart (SImode, operands[1]); 2027 }" 2028 [(set_attr "length" "8") 2029 (set_attr "predicable" "yes")] 2030) 2031 2032(define_insn "andsi_notsi_si" 2033 [(set (match_operand:SI 0 "s_register_operand" "=r") 2034 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) 2035 (match_operand:SI 1 "s_register_operand" "r")))] 2036 "TARGET_ARM" 2037 "bic%?\\t%0, %1, %2" 2038 [(set_attr "predicable" "yes")] 2039) 2040 2041(define_insn "bicsi3" 2042 [(set (match_operand:SI 0 "register_operand" "=l") 2043 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l")) 2044 (match_operand:SI 2 "register_operand" "0")))] 2045 "TARGET_THUMB" 2046 "bic\\t%0, %0, %1" 2047 [(set_attr "length" "2")] 2048) 2049 2050(define_insn "andsi_not_shiftsi_si" 2051 [(set (match_operand:SI 0 "s_register_operand" "=r") 2052 (and:SI (not:SI (match_operator:SI 4 "shift_operator" 2053 [(match_operand:SI 2 "s_register_operand" "r") 2054 (match_operand:SI 3 "arm_rhs_operand" "rM")])) 2055 (match_operand:SI 1 "s_register_operand" "r")))] 2056 "TARGET_ARM" 2057 "bic%?\\t%0, %1, %2%S4" 2058 [(set_attr "predicable" "yes") 2059 (set_attr "shift" "2") 2060 ] 2061) 2062 2063(define_insn "*andsi_notsi_si_compare0" 2064 [(set (reg:CC_NOOV CC_REGNUM) 2065 (compare:CC_NOOV 2066 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) 2067 (match_operand:SI 1 "s_register_operand" "r")) 2068 (const_int 0))) 2069 (set (match_operand:SI 0 "s_register_operand" "=r") 2070 (and:SI (not:SI (match_dup 2)) (match_dup 1)))] 2071 "TARGET_ARM" 2072 "bic%?s\\t%0, %1, %2" 2073 [(set_attr "conds" "set")] 2074) 2075 2076(define_insn "*andsi_notsi_si_compare0_scratch" 2077 [(set (reg:CC_NOOV CC_REGNUM) 2078 (compare:CC_NOOV 2079 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) 2080 (match_operand:SI 1 "s_register_operand" "r")) 2081 (const_int 0))) 2082 (clobber (match_scratch:SI 0 "=r"))] 2083 "TARGET_ARM" 2084 "bic%?s\\t%0, %1, %2" 2085 [(set_attr "conds" "set")] 2086) 2087 2088(define_insn "iordi3" 2089 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 2090 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r") 2091 (match_operand:DI 2 "s_register_operand" "r,r")))] 2092 "TARGET_ARM && ! TARGET_IWMMXT" 2093 "#" 2094 [(set_attr "length" "8") 2095 (set_attr "predicable" "yes")] 2096) 2097 2098(define_insn "*iordi_zesidi_di" 2099 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 2100 (ior:DI (zero_extend:DI 2101 (match_operand:SI 2 "s_register_operand" "r,r")) 2102 (match_operand:DI 1 "s_register_operand" "0,?r")))] 2103 "TARGET_ARM" 2104 "@ 2105 orr%?\\t%Q0, %Q1, %2 2106 #" 2107 [(set_attr "length" "4,8") 2108 (set_attr "predicable" "yes")] 2109) 2110 2111(define_insn "*iordi_sesidi_di" 2112 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 2113 (ior:DI (sign_extend:DI 2114 (match_operand:SI 2 "s_register_operand" "r,r")) 2115 (match_operand:DI 1 "s_register_operand" "?r,0")))] 2116 "TARGET_ARM" 2117 "#" 2118 [(set_attr "length" "8") 2119 (set_attr "predicable" "yes")] 2120) 2121 2122(define_expand "iorsi3" 2123 [(set (match_operand:SI 0 "s_register_operand" "") 2124 (ior:SI (match_operand:SI 1 "s_register_operand" "") 2125 (match_operand:SI 2 "reg_or_int_operand" "")))] 2126 "TARGET_EITHER" 2127 " 2128 if (GET_CODE (operands[2]) == CONST_INT) 2129 { 2130 if (TARGET_ARM) 2131 { 2132 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0], 2133 operands[1], 2134 (no_new_pseudos 2135 ? 0 : preserve_subexpressions_p ())); 2136 DONE; 2137 } 2138 else /* TARGET_THUMB */ 2139 operands [2] = force_reg (SImode, operands [2]); 2140 } 2141 " 2142) 2143 2144(define_insn_and_split "*arm_iorsi3" 2145 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 2146 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r") 2147 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))] 2148 "TARGET_ARM" 2149 "@ 2150 orr%?\\t%0, %1, %2 2151 #" 2152 "TARGET_ARM 2153 && GET_CODE (operands[2]) == CONST_INT 2154 && !const_ok_for_arm (INTVAL (operands[2]))" 2155 [(clobber (const_int 0))] 2156 " 2157 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0], 2158 operands[1], 0); 2159 DONE; 2160 " 2161 [(set_attr "length" "4,16") 2162 (set_attr "predicable" "yes")] 2163) 2164 2165(define_insn "*thumb_iorsi3" 2166 [(set (match_operand:SI 0 "register_operand" "=l") 2167 (ior:SI (match_operand:SI 1 "register_operand" "%0") 2168 (match_operand:SI 2 "register_operand" "l")))] 2169 "TARGET_THUMB" 2170 "orr\\t%0, %0, %2" 2171 [(set_attr "length" "2")] 2172) 2173 2174(define_peephole2 2175 [(match_scratch:SI 3 "r") 2176 (set (match_operand:SI 0 "s_register_operand" "") 2177 (ior:SI (match_operand:SI 1 "s_register_operand" "") 2178 (match_operand:SI 2 "const_int_operand" "")))] 2179 "TARGET_ARM 2180 && !const_ok_for_arm (INTVAL (operands[2])) 2181 && const_ok_for_arm (~INTVAL (operands[2]))" 2182 [(set (match_dup 3) (match_dup 2)) 2183 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))] 2184 "" 2185) 2186 2187(define_insn "*iorsi3_compare0" 2188 [(set (reg:CC_NOOV CC_REGNUM) 2189 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r") 2190 (match_operand:SI 2 "arm_rhs_operand" "rI")) 2191 (const_int 0))) 2192 (set (match_operand:SI 0 "s_register_operand" "=r") 2193 (ior:SI (match_dup 1) (match_dup 2)))] 2194 "TARGET_ARM" 2195 "orr%?s\\t%0, %1, %2" 2196 [(set_attr "conds" "set")] 2197) 2198 2199(define_insn "*iorsi3_compare0_scratch" 2200 [(set (reg:CC_NOOV CC_REGNUM) 2201 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r") 2202 (match_operand:SI 2 "arm_rhs_operand" "rI")) 2203 (const_int 0))) 2204 (clobber (match_scratch:SI 0 "=r"))] 2205 "TARGET_ARM" 2206 "orr%?s\\t%0, %1, %2" 2207 [(set_attr "conds" "set")] 2208) 2209 2210(define_insn "xordi3" 2211 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 2212 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r") 2213 (match_operand:DI 2 "s_register_operand" "r,r")))] 2214 "TARGET_ARM && !TARGET_IWMMXT" 2215 "#" 2216 [(set_attr "length" "8") 2217 (set_attr "predicable" "yes")] 2218) 2219 2220(define_insn "*xordi_zesidi_di" 2221 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 2222 (xor:DI (zero_extend:DI 2223 (match_operand:SI 2 "s_register_operand" "r,r")) 2224 (match_operand:DI 1 "s_register_operand" "0,?r")))] 2225 "TARGET_ARM" 2226 "@ 2227 eor%?\\t%Q0, %Q1, %2 2228 #" 2229 [(set_attr "length" "4,8") 2230 (set_attr "predicable" "yes")] 2231) 2232 2233(define_insn "*xordi_sesidi_di" 2234 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 2235 (xor:DI (sign_extend:DI 2236 (match_operand:SI 2 "s_register_operand" "r,r")) 2237 (match_operand:DI 1 "s_register_operand" "?r,0")))] 2238 "TARGET_ARM" 2239 "#" 2240 [(set_attr "length" "8") 2241 (set_attr "predicable" "yes")] 2242) 2243 2244(define_expand "xorsi3" 2245 [(set (match_operand:SI 0 "s_register_operand" "") 2246 (xor:SI (match_operand:SI 1 "s_register_operand" "") 2247 (match_operand:SI 2 "arm_rhs_operand" "")))] 2248 "TARGET_EITHER" 2249 "if (TARGET_THUMB) 2250 if (GET_CODE (operands[2]) == CONST_INT) 2251 operands[2] = force_reg (SImode, operands[2]); 2252 " 2253) 2254 2255(define_insn "*arm_xorsi3" 2256 [(set (match_operand:SI 0 "s_register_operand" "=r") 2257 (xor:SI (match_operand:SI 1 "s_register_operand" "r") 2258 (match_operand:SI 2 "arm_rhs_operand" "rI")))] 2259 "TARGET_ARM" 2260 "eor%?\\t%0, %1, %2" 2261 [(set_attr "predicable" "yes")] 2262) 2263 2264(define_insn "*thumb_xorsi3" 2265 [(set (match_operand:SI 0 "register_operand" "=l") 2266 (xor:SI (match_operand:SI 1 "register_operand" "%0") 2267 (match_operand:SI 2 "register_operand" "l")))] 2268 "TARGET_THUMB" 2269 "eor\\t%0, %0, %2" 2270 [(set_attr "length" "2")] 2271) 2272 2273(define_insn "*xorsi3_compare0" 2274 [(set (reg:CC_NOOV CC_REGNUM) 2275 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r") 2276 (match_operand:SI 2 "arm_rhs_operand" "rI")) 2277 (const_int 0))) 2278 (set (match_operand:SI 0 "s_register_operand" "=r") 2279 (xor:SI (match_dup 1) (match_dup 2)))] 2280 "TARGET_ARM" 2281 "eor%?s\\t%0, %1, %2" 2282 [(set_attr "conds" "set")] 2283) 2284 2285(define_insn "*xorsi3_compare0_scratch" 2286 [(set (reg:CC_NOOV CC_REGNUM) 2287 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r") 2288 (match_operand:SI 1 "arm_rhs_operand" "rI")) 2289 (const_int 0)))] 2290 "TARGET_ARM" 2291 "teq%?\\t%0, %1" 2292 [(set_attr "conds" "set")] 2293) 2294 2295; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 2296; (NOT D) we can sometimes merge the final NOT into one of the following 2297; insns. 2298 2299(define_split 2300 [(set (match_operand:SI 0 "s_register_operand" "") 2301 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "")) 2302 (not:SI (match_operand:SI 2 "arm_rhs_operand" ""))) 2303 (match_operand:SI 3 "arm_rhs_operand" ""))) 2304 (clobber (match_operand:SI 4 "s_register_operand" ""))] 2305 "TARGET_ARM" 2306 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2)) 2307 (not:SI (match_dup 3)))) 2308 (set (match_dup 0) (not:SI (match_dup 4)))] 2309 "" 2310) 2311 2312(define_insn "*andsi_iorsi3_notsi" 2313 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r") 2314 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0") 2315 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")) 2316 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))] 2317 "TARGET_ARM" 2318 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3" 2319 [(set_attr "length" "8") 2320 (set_attr "predicable" "yes")] 2321) 2322 2323(define_split 2324 [(set (match_operand:SI 0 "s_register_operand" "") 2325 (match_operator:SI 1 "logical_binary_operator" 2326 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "") 2327 (match_operand:SI 3 "const_int_operand" "") 2328 (match_operand:SI 4 "const_int_operand" "")) 2329 (match_operator:SI 9 "logical_binary_operator" 2330 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "") 2331 (match_operand:SI 6 "const_int_operand" "")) 2332 (match_operand:SI 7 "s_register_operand" "")])])) 2333 (clobber (match_operand:SI 8 "s_register_operand" ""))] 2334 "TARGET_ARM 2335 && GET_CODE (operands[1]) == GET_CODE (operands[9]) 2336 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])" 2337 [(set (match_dup 8) 2338 (match_op_dup 1 2339 [(ashift:SI (match_dup 2) (match_dup 4)) 2340 (match_dup 5)])) 2341 (set (match_dup 0) 2342 (match_op_dup 1 2343 [(lshiftrt:SI (match_dup 8) (match_dup 6)) 2344 (match_dup 7)]))] 2345 " 2346 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4]))); 2347") 2348 2349(define_split 2350 [(set (match_operand:SI 0 "s_register_operand" "") 2351 (match_operator:SI 1 "logical_binary_operator" 2352 [(match_operator:SI 9 "logical_binary_operator" 2353 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "") 2354 (match_operand:SI 6 "const_int_operand" "")) 2355 (match_operand:SI 7 "s_register_operand" "")]) 2356 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "") 2357 (match_operand:SI 3 "const_int_operand" "") 2358 (match_operand:SI 4 "const_int_operand" ""))])) 2359 (clobber (match_operand:SI 8 "s_register_operand" ""))] 2360 "TARGET_ARM 2361 && GET_CODE (operands[1]) == GET_CODE (operands[9]) 2362 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])" 2363 [(set (match_dup 8) 2364 (match_op_dup 1 2365 [(ashift:SI (match_dup 2) (match_dup 4)) 2366 (match_dup 5)])) 2367 (set (match_dup 0) 2368 (match_op_dup 1 2369 [(lshiftrt:SI (match_dup 8) (match_dup 6)) 2370 (match_dup 7)]))] 2371 " 2372 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4]))); 2373") 2374 2375(define_split 2376 [(set (match_operand:SI 0 "s_register_operand" "") 2377 (match_operator:SI 1 "logical_binary_operator" 2378 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "") 2379 (match_operand:SI 3 "const_int_operand" "") 2380 (match_operand:SI 4 "const_int_operand" "")) 2381 (match_operator:SI 9 "logical_binary_operator" 2382 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "") 2383 (match_operand:SI 6 "const_int_operand" "")) 2384 (match_operand:SI 7 "s_register_operand" "")])])) 2385 (clobber (match_operand:SI 8 "s_register_operand" ""))] 2386 "TARGET_ARM 2387 && GET_CODE (operands[1]) == GET_CODE (operands[9]) 2388 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])" 2389 [(set (match_dup 8) 2390 (match_op_dup 1 2391 [(ashift:SI (match_dup 2) (match_dup 4)) 2392 (match_dup 5)])) 2393 (set (match_dup 0) 2394 (match_op_dup 1 2395 [(ashiftrt:SI (match_dup 8) (match_dup 6)) 2396 (match_dup 7)]))] 2397 " 2398 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4]))); 2399") 2400 2401(define_split 2402 [(set (match_operand:SI 0 "s_register_operand" "") 2403 (match_operator:SI 1 "logical_binary_operator" 2404 [(match_operator:SI 9 "logical_binary_operator" 2405 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "") 2406 (match_operand:SI 6 "const_int_operand" "")) 2407 (match_operand:SI 7 "s_register_operand" "")]) 2408 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "") 2409 (match_operand:SI 3 "const_int_operand" "") 2410 (match_operand:SI 4 "const_int_operand" ""))])) 2411 (clobber (match_operand:SI 8 "s_register_operand" ""))] 2412 "TARGET_ARM 2413 && GET_CODE (operands[1]) == GET_CODE (operands[9]) 2414 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])" 2415 [(set (match_dup 8) 2416 (match_op_dup 1 2417 [(ashift:SI (match_dup 2) (match_dup 4)) 2418 (match_dup 5)])) 2419 (set (match_dup 0) 2420 (match_op_dup 1 2421 [(ashiftrt:SI (match_dup 8) (match_dup 6)) 2422 (match_dup 7)]))] 2423 " 2424 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4]))); 2425") 2426 2427 2428;; Minimum and maximum insns 2429 2430(define_insn "smaxsi3" 2431 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 2432 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") 2433 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 2434 (clobber (reg:CC CC_REGNUM))] 2435 "TARGET_ARM" 2436 "@ 2437 cmp\\t%1, %2\;movlt\\t%0, %2 2438 cmp\\t%1, %2\;movge\\t%0, %1 2439 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2" 2440 [(set_attr "conds" "clob") 2441 (set_attr "length" "8,8,12")] 2442) 2443 2444(define_insn "sminsi3" 2445 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 2446 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") 2447 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 2448 (clobber (reg:CC CC_REGNUM))] 2449 "TARGET_ARM" 2450 "@ 2451 cmp\\t%1, %2\;movge\\t%0, %2 2452 cmp\\t%1, %2\;movlt\\t%0, %1 2453 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2" 2454 [(set_attr "conds" "clob") 2455 (set_attr "length" "8,8,12")] 2456) 2457 2458(define_insn "umaxsi3" 2459 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 2460 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") 2461 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 2462 (clobber (reg:CC CC_REGNUM))] 2463 "TARGET_ARM" 2464 "@ 2465 cmp\\t%1, %2\;movcc\\t%0, %2 2466 cmp\\t%1, %2\;movcs\\t%0, %1 2467 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2" 2468 [(set_attr "conds" "clob") 2469 (set_attr "length" "8,8,12")] 2470) 2471 2472(define_insn "uminsi3" 2473 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 2474 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") 2475 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 2476 (clobber (reg:CC CC_REGNUM))] 2477 "TARGET_ARM" 2478 "@ 2479 cmp\\t%1, %2\;movcs\\t%0, %2 2480 cmp\\t%1, %2\;movcc\\t%0, %1 2481 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2" 2482 [(set_attr "conds" "clob") 2483 (set_attr "length" "8,8,12")] 2484) 2485 2486(define_insn "*store_minmaxsi" 2487 [(set (match_operand:SI 0 "memory_operand" "=m") 2488 (match_operator:SI 3 "minmax_operator" 2489 [(match_operand:SI 1 "s_register_operand" "r") 2490 (match_operand:SI 2 "s_register_operand" "r")])) 2491 (clobber (reg:CC CC_REGNUM))] 2492 "TARGET_ARM" 2493 "* 2494 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1], 2495 operands[2]); 2496 output_asm_insn (\"cmp\\t%1, %2\", operands); 2497 output_asm_insn (\"str%d3\\t%1, %0\", operands); 2498 output_asm_insn (\"str%D3\\t%2, %0\", operands); 2499 return \"\"; 2500 " 2501 [(set_attr "conds" "clob") 2502 (set_attr "length" "12") 2503 (set_attr "type" "store1")] 2504) 2505 2506; Reject the frame pointer in operand[1], since reloading this after 2507; it has been eliminated can cause carnage. 2508(define_insn "*minmax_arithsi" 2509 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 2510 (match_operator:SI 4 "shiftable_operator" 2511 [(match_operator:SI 5 "minmax_operator" 2512 [(match_operand:SI 2 "s_register_operand" "r,r") 2513 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) 2514 (match_operand:SI 1 "s_register_operand" "0,?r")])) 2515 (clobber (reg:CC CC_REGNUM))] 2516 "TARGET_ARM 2517 && (GET_CODE (operands[1]) != REG 2518 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM 2519 && REGNO(operands[1]) != ARG_POINTER_REGNUM))" 2520 "* 2521 { 2522 enum rtx_code code = GET_CODE (operands[4]); 2523 2524 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2], 2525 operands[3]); 2526 output_asm_insn (\"cmp\\t%2, %3\", operands); 2527 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands); 2528 if (which_alternative != 0 || operands[3] != const0_rtx 2529 || (code != PLUS && code != MINUS && code != IOR && code != XOR)) 2530 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands); 2531 return \"\"; 2532 }" 2533 [(set_attr "conds" "clob") 2534 (set_attr "length" "12")] 2535) 2536 2537 2538;; Shift and rotation insns 2539 2540(define_expand "ashlsi3" 2541 [(set (match_operand:SI 0 "s_register_operand" "") 2542 (ashift:SI (match_operand:SI 1 "s_register_operand" "") 2543 (match_operand:SI 2 "arm_rhs_operand" "")))] 2544 "TARGET_EITHER" 2545 " 2546 if (GET_CODE (operands[2]) == CONST_INT 2547 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) 2548 { 2549 emit_insn (gen_movsi (operands[0], const0_rtx)); 2550 DONE; 2551 } 2552 " 2553) 2554 2555(define_insn "*thumb_ashlsi3" 2556 [(set (match_operand:SI 0 "register_operand" "=l,l") 2557 (ashift:SI (match_operand:SI 1 "register_operand" "l,0") 2558 (match_operand:SI 2 "nonmemory_operand" "N,l")))] 2559 "TARGET_THUMB" 2560 "lsl\\t%0, %1, %2" 2561 [(set_attr "length" "2")] 2562) 2563 2564(define_expand "ashrsi3" 2565 [(set (match_operand:SI 0 "s_register_operand" "") 2566 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "") 2567 (match_operand:SI 2 "arm_rhs_operand" "")))] 2568 "TARGET_EITHER" 2569 " 2570 if (GET_CODE (operands[2]) == CONST_INT 2571 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) 2572 operands[2] = GEN_INT (31); 2573 " 2574) 2575 2576(define_insn "*thumb_ashrsi3" 2577 [(set (match_operand:SI 0 "register_operand" "=l,l") 2578 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0") 2579 (match_operand:SI 2 "nonmemory_operand" "N,l")))] 2580 "TARGET_THUMB" 2581 "asr\\t%0, %1, %2" 2582 [(set_attr "length" "2")] 2583) 2584 2585(define_expand "lshrsi3" 2586 [(set (match_operand:SI 0 "s_register_operand" "") 2587 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "") 2588 (match_operand:SI 2 "arm_rhs_operand" "")))] 2589 "TARGET_EITHER" 2590 " 2591 if (GET_CODE (operands[2]) == CONST_INT 2592 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) 2593 { 2594 emit_insn (gen_movsi (operands[0], const0_rtx)); 2595 DONE; 2596 } 2597 " 2598) 2599 2600(define_insn "*thumb_lshrsi3" 2601 [(set (match_operand:SI 0 "register_operand" "=l,l") 2602 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0") 2603 (match_operand:SI 2 "nonmemory_operand" "N,l")))] 2604 "TARGET_THUMB" 2605 "lsr\\t%0, %1, %2" 2606 [(set_attr "length" "2")] 2607) 2608 2609(define_expand "rotlsi3" 2610 [(set (match_operand:SI 0 "s_register_operand" "") 2611 (rotatert:SI (match_operand:SI 1 "s_register_operand" "") 2612 (match_operand:SI 2 "reg_or_int_operand" "")))] 2613 "TARGET_ARM" 2614 " 2615 if (GET_CODE (operands[2]) == CONST_INT) 2616 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32); 2617 else 2618 { 2619 rtx reg = gen_reg_rtx (SImode); 2620 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2])); 2621 operands[2] = reg; 2622 } 2623 " 2624) 2625 2626(define_expand "rotrsi3" 2627 [(set (match_operand:SI 0 "s_register_operand" "") 2628 (rotatert:SI (match_operand:SI 1 "s_register_operand" "") 2629 (match_operand:SI 2 "arm_rhs_operand" "")))] 2630 "TARGET_EITHER" 2631 " 2632 if (TARGET_ARM) 2633 { 2634 if (GET_CODE (operands[2]) == CONST_INT 2635 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) 2636 operands[2] = GEN_INT (INTVAL (operands[2]) % 32); 2637 } 2638 else /* TARGET_THUMB */ 2639 { 2640 if (GET_CODE (operands [2]) == CONST_INT) 2641 operands [2] = force_reg (SImode, operands[2]); 2642 } 2643 " 2644) 2645 2646(define_insn "*thumb_rotrsi3" 2647 [(set (match_operand:SI 0 "register_operand" "=l") 2648 (rotatert:SI (match_operand:SI 1 "register_operand" "0") 2649 (match_operand:SI 2 "register_operand" "l")))] 2650 "TARGET_THUMB" 2651 "ror\\t%0, %0, %2" 2652 [(set_attr "length" "2")] 2653) 2654 2655(define_expand "ashldi3" 2656 [(set (match_operand:DI 0 "s_register_operand" "") 2657 (ashift:DI (match_operand:DI 1 "general_operand" "") 2658 (match_operand:SI 2 "general_operand" "")))] 2659 "TARGET_ARM && (TARGET_IWMMXT || TARGET_CIRRUS)" 2660 " 2661 if (! s_register_operand (operands[1], DImode)) 2662 operands[1] = copy_to_mode_reg (DImode, operands[1]); 2663 if (! s_register_operand (operands[2], SImode)) 2664 operands[2] = copy_to_mode_reg (SImode, operands[2]); 2665 " 2666) 2667 2668(define_insn "*arm_shiftsi3" 2669 [(set (match_operand:SI 0 "s_register_operand" "=r") 2670 (match_operator:SI 3 "shift_operator" 2671 [(match_operand:SI 1 "s_register_operand" "r") 2672 (match_operand:SI 2 "reg_or_int_operand" "rM")]))] 2673 "TARGET_ARM" 2674 "mov%?\\t%0, %1%S3" 2675 [(set_attr "predicable" "yes") 2676 (set_attr "shift" "1") 2677 ] 2678) 2679 2680(define_insn "*shiftsi3_compare0" 2681 [(set (reg:CC_NOOV CC_REGNUM) 2682 (compare:CC_NOOV (match_operator:SI 3 "shift_operator" 2683 [(match_operand:SI 1 "s_register_operand" "r") 2684 (match_operand:SI 2 "arm_rhs_operand" "rM")]) 2685 (const_int 0))) 2686 (set (match_operand:SI 0 "s_register_operand" "=r") 2687 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))] 2688 "TARGET_ARM" 2689 "mov%?s\\t%0, %1%S3" 2690 [(set_attr "conds" "set") 2691 (set_attr "shift" "1") 2692 ] 2693) 2694 2695(define_insn "*shiftsi3_compare0_scratch" 2696 [(set (reg:CC_NOOV CC_REGNUM) 2697 (compare:CC_NOOV (match_operator:SI 3 "shift_operator" 2698 [(match_operand:SI 1 "s_register_operand" "r") 2699 (match_operand:SI 2 "arm_rhs_operand" "rM")]) 2700 (const_int 0))) 2701 (clobber (match_scratch:SI 0 "=r"))] 2702 "TARGET_ARM" 2703 "mov%?s\\t%0, %1%S3" 2704 [(set_attr "conds" "set") 2705 (set_attr "shift" "1") 2706 ] 2707) 2708 2709(define_insn "*notsi_shiftsi" 2710 [(set (match_operand:SI 0 "s_register_operand" "=r") 2711 (not:SI (match_operator:SI 3 "shift_operator" 2712 [(match_operand:SI 1 "s_register_operand" "r") 2713 (match_operand:SI 2 "arm_rhs_operand" "rM")])))] 2714 "TARGET_ARM" 2715 "mvn%?\\t%0, %1%S3" 2716 [(set_attr "predicable" "yes") 2717 (set_attr "shift" "1") 2718 ] 2719) 2720 2721(define_insn "*notsi_shiftsi_compare0" 2722 [(set (reg:CC_NOOV CC_REGNUM) 2723 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator" 2724 [(match_operand:SI 1 "s_register_operand" "r") 2725 (match_operand:SI 2 "arm_rhs_operand" "rM")])) 2726 (const_int 0))) 2727 (set (match_operand:SI 0 "s_register_operand" "=r") 2728 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))] 2729 "TARGET_ARM" 2730 "mvn%?s\\t%0, %1%S3" 2731 [(set_attr "conds" "set") 2732 (set_attr "shift" "1") 2733 ] 2734) 2735 2736(define_insn "*not_shiftsi_compare0_scratch" 2737 [(set (reg:CC_NOOV CC_REGNUM) 2738 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator" 2739 [(match_operand:SI 1 "s_register_operand" "r") 2740 (match_operand:SI 2 "arm_rhs_operand" "rM")])) 2741 (const_int 0))) 2742 (clobber (match_scratch:SI 0 "=r"))] 2743 "TARGET_ARM" 2744 "mvn%?s\\t%0, %1%S3" 2745 [(set_attr "conds" "set") 2746 (set_attr "shift" "1") 2747 ] 2748) 2749 2750;; We don't really have extzv, but defining this using shifts helps 2751;; to reduce register pressure later on. 2752 2753(define_expand "extzv" 2754 [(set (match_dup 4) 2755 (ashift:SI (match_operand:SI 1 "register_operand" "") 2756 (match_operand:SI 2 "const_int_operand" ""))) 2757 (set (match_operand:SI 0 "register_operand" "") 2758 (lshiftrt:SI (match_dup 4) 2759 (match_operand:SI 3 "const_int_operand" "")))] 2760 "TARGET_THUMB" 2761 " 2762 { 2763 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]); 2764 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]); 2765 2766 operands[3] = GEN_INT (rshift); 2767 2768 if (lshift == 0) 2769 { 2770 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3])); 2771 DONE; 2772 } 2773 2774 operands[2] = GEN_INT (lshift); 2775 operands[4] = gen_reg_rtx (SImode); 2776 }" 2777) 2778 2779 2780;; Unary arithmetic insns 2781 2782(define_expand "negdi2" 2783 [(parallel 2784 [(set (match_operand:DI 0 "s_register_operand" "") 2785 (neg:DI (match_operand:DI 1 "s_register_operand" ""))) 2786 (clobber (reg:CC CC_REGNUM))])] 2787 "TARGET_EITHER" 2788 " 2789 if (TARGET_THUMB) 2790 { 2791 if (GET_CODE (operands[1]) != REG) 2792 operands[1] = force_reg (SImode, operands[1]); 2793 } 2794 " 2795) 2796 2797;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1). 2798;; The second alternative is to allow the common case of a *full* overlap. 2799(define_insn "*arm_negdi2" 2800 [(set (match_operand:DI 0 "s_register_operand" "=&r,r") 2801 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0"))) 2802 (clobber (reg:CC CC_REGNUM))] 2803 "TARGET_ARM" 2804 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0" 2805 [(set_attr "conds" "clob") 2806 (set_attr "length" "8")] 2807) 2808 2809(define_insn "*thumb_negdi2" 2810 [(set (match_operand:DI 0 "register_operand" "=&l") 2811 (neg:DI (match_operand:DI 1 "register_operand" "l"))) 2812 (clobber (reg:CC CC_REGNUM))] 2813 "TARGET_THUMB" 2814 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1" 2815 [(set_attr "length" "6")] 2816) 2817 2818(define_expand "negsi2" 2819 [(set (match_operand:SI 0 "s_register_operand" "") 2820 (neg:SI (match_operand:SI 1 "s_register_operand" "")))] 2821 "TARGET_EITHER" 2822 "" 2823) 2824 2825(define_insn "*arm_negsi2" 2826 [(set (match_operand:SI 0 "s_register_operand" "=r") 2827 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))] 2828 "TARGET_ARM" 2829 "rsb%?\\t%0, %1, #0" 2830 [(set_attr "predicable" "yes")] 2831) 2832 2833(define_insn "*thumb_negsi2" 2834 [(set (match_operand:SI 0 "register_operand" "=l") 2835 (neg:SI (match_operand:SI 1 "register_operand" "l")))] 2836 "TARGET_THUMB" 2837 "neg\\t%0, %1" 2838 [(set_attr "length" "2")] 2839) 2840 2841(define_expand "negsf2" 2842 [(set (match_operand:SF 0 "s_register_operand" "") 2843 (neg:SF (match_operand:SF 1 "s_register_operand" "")))] 2844 "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 2845 "" 2846) 2847 2848(define_expand "negdf2" 2849 [(set (match_operand:DF 0 "s_register_operand" "") 2850 (neg:DF (match_operand:DF 1 "s_register_operand" "")))] 2851 "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 2852 "") 2853 2854;; abssi2 doesn't really clobber the condition codes if a different register 2855;; is being set. To keep things simple, assume during rtl manipulations that 2856;; it does, but tell the final scan operator the truth. Similarly for 2857;; (neg (abs...)) 2858 2859(define_expand "abssi2" 2860 [(parallel 2861 [(set (match_operand:SI 0 "s_register_operand" "") 2862 (abs:SI (match_operand:SI 1 "s_register_operand" ""))) 2863 (clobber (reg:CC CC_REGNUM))])] 2864 "TARGET_ARM" 2865 "") 2866 2867(define_insn "*arm_abssi2" 2868 [(set (match_operand:SI 0 "s_register_operand" "=r,&r") 2869 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))) 2870 (clobber (reg:CC CC_REGNUM))] 2871 "TARGET_ARM" 2872 "@ 2873 cmp\\t%0, #0\;rsblt\\t%0, %0, #0 2874 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31" 2875 [(set_attr "conds" "clob,*") 2876 (set_attr "shift" "1") 2877 ;; predicable can't be set based on the variant, so left as no 2878 (set_attr "length" "8")] 2879) 2880 2881(define_insn "*neg_abssi2" 2882 [(set (match_operand:SI 0 "s_register_operand" "=r,&r") 2883 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))) 2884 (clobber (reg:CC CC_REGNUM))] 2885 "TARGET_ARM" 2886 "@ 2887 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0 2888 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31" 2889 [(set_attr "conds" "clob,*") 2890 (set_attr "shift" "1") 2891 ;; predicable can't be set based on the variant, so left as no 2892 (set_attr "length" "8")] 2893) 2894 2895(define_expand "abssf2" 2896 [(set (match_operand:SF 0 "s_register_operand" "") 2897 (abs:SF (match_operand:SF 1 "s_register_operand" "")))] 2898 "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 2899 "") 2900 2901(define_expand "absdf2" 2902 [(set (match_operand:DF 0 "s_register_operand" "") 2903 (abs:DF (match_operand:DF 1 "s_register_operand" "")))] 2904 "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 2905 "") 2906 2907(define_expand "sqrtsf2" 2908 [(set (match_operand:SF 0 "s_register_operand" "") 2909 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))] 2910 "TARGET_ARM && TARGET_HARD_FLOAT" 2911 "") 2912 2913(define_expand "sqrtdf2" 2914 [(set (match_operand:DF 0 "s_register_operand" "") 2915 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))] 2916 "TARGET_ARM && TARGET_HARD_FLOAT" 2917 "") 2918 2919(define_insn_and_split "one_cmpldi2" 2920 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 2921 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))] 2922 "TARGET_ARM" 2923 "#" 2924 "TARGET_ARM && reload_completed" 2925 [(set (match_dup 0) (not:SI (match_dup 1))) 2926 (set (match_dup 2) (not:SI (match_dup 3)))] 2927 " 2928 { 2929 operands[2] = gen_highpart (SImode, operands[0]); 2930 operands[0] = gen_lowpart (SImode, operands[0]); 2931 operands[3] = gen_highpart (SImode, operands[1]); 2932 operands[1] = gen_lowpart (SImode, operands[1]); 2933 }" 2934 [(set_attr "length" "8") 2935 (set_attr "predicable" "yes")] 2936) 2937 2938(define_expand "one_cmplsi2" 2939 [(set (match_operand:SI 0 "s_register_operand" "") 2940 (not:SI (match_operand:SI 1 "s_register_operand" "")))] 2941 "TARGET_EITHER" 2942 "" 2943) 2944 2945(define_insn "*arm_one_cmplsi2" 2946 [(set (match_operand:SI 0 "s_register_operand" "=r") 2947 (not:SI (match_operand:SI 1 "s_register_operand" "r")))] 2948 "TARGET_ARM" 2949 "mvn%?\\t%0, %1" 2950 [(set_attr "predicable" "yes")] 2951) 2952 2953(define_insn "*thumb_one_cmplsi2" 2954 [(set (match_operand:SI 0 "register_operand" "=l") 2955 (not:SI (match_operand:SI 1 "register_operand" "l")))] 2956 "TARGET_THUMB" 2957 "mvn\\t%0, %1" 2958 [(set_attr "length" "2")] 2959) 2960 2961(define_insn "*notsi_compare0" 2962 [(set (reg:CC_NOOV CC_REGNUM) 2963 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r")) 2964 (const_int 0))) 2965 (set (match_operand:SI 0 "s_register_operand" "=r") 2966 (not:SI (match_dup 1)))] 2967 "TARGET_ARM" 2968 "mvn%?s\\t%0, %1" 2969 [(set_attr "conds" "set")] 2970) 2971 2972(define_insn "*notsi_compare0_scratch" 2973 [(set (reg:CC_NOOV CC_REGNUM) 2974 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r")) 2975 (const_int 0))) 2976 (clobber (match_scratch:SI 0 "=r"))] 2977 "TARGET_ARM" 2978 "mvn%?s\\t%0, %1" 2979 [(set_attr "conds" "set")] 2980) 2981 2982;; Fixed <--> Floating conversion insns 2983 2984(define_expand "floatsisf2" 2985 [(set (match_operand:SF 0 "s_register_operand" "") 2986 (float:SF (match_operand:SI 1 "s_register_operand" "")))] 2987 "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 2988 " 2989 if (TARGET_CIRRUS) 2990 { 2991 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1])); 2992 DONE; 2993 } 2994") 2995 2996(define_expand "floatsidf2" 2997 [(set (match_operand:DF 0 "s_register_operand" "") 2998 (float:DF (match_operand:SI 1 "s_register_operand" "")))] 2999 "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 3000 " 3001 if (TARGET_CIRRUS) 3002 { 3003 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1])); 3004 DONE; 3005 } 3006") 3007 3008(define_expand "fix_truncsfsi2" 3009 [(set (match_operand:SI 0 "s_register_operand" "") 3010 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))] 3011 "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 3012 " 3013 if (TARGET_CIRRUS) 3014 { 3015 if (!cirrus_fp_register (operands[0], SImode)) 3016 operands[0] = force_reg (SImode, operands[0]); 3017 if (!cirrus_fp_register (operands[1], SFmode)) 3018 operands[1] = force_reg (SFmode, operands[0]); 3019 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1])); 3020 DONE; 3021 } 3022") 3023 3024(define_expand "fix_truncdfsi2" 3025 [(set (match_operand:SI 0 "s_register_operand" "") 3026 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))] 3027 "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 3028 " 3029 if (TARGET_CIRRUS) 3030 { 3031 if (!cirrus_fp_register (operands[1], DFmode)) 3032 operands[1] = force_reg (DFmode, operands[0]); 3033 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1])); 3034 DONE; 3035 } 3036") 3037 3038;; Truncation insns 3039 3040(define_expand "truncdfsf2" 3041 [(set (match_operand:SF 0 "s_register_operand" "") 3042 (float_truncate:SF 3043 (match_operand:DF 1 "s_register_operand" "")))] 3044 "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 3045 "" 3046) 3047 3048;; Zero and sign extension instructions. 3049 3050(define_insn "zero_extendsidi2" 3051 [(set (match_operand:DI 0 "s_register_operand" "=r") 3052 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))] 3053 "TARGET_ARM" 3054 "* 3055 if (REGNO (operands[1]) 3056 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0)) 3057 output_asm_insn (\"mov%?\\t%Q0, %1\", operands); 3058 return \"mov%?\\t%R0, #0\"; 3059 " 3060 [(set_attr "length" "8") 3061 (set_attr "predicable" "yes")] 3062) 3063 3064(define_insn "zero_extendqidi2" 3065 [(set (match_operand:DI 0 "s_register_operand" "=r,r") 3066 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] 3067 "TARGET_ARM" 3068 "@ 3069 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0 3070 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0" 3071 [(set_attr "length" "8") 3072 (set_attr "predicable" "yes") 3073 (set_attr "type" "*,load") 3074 (set_attr "pool_range" "*,4092") 3075 (set_attr "neg_pool_range" "*,4084")] 3076) 3077 3078(define_insn "extendsidi2" 3079 [(set (match_operand:DI 0 "s_register_operand" "=r") 3080 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))] 3081 "TARGET_ARM" 3082 "* 3083 if (REGNO (operands[1]) 3084 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0)) 3085 output_asm_insn (\"mov%?\\t%Q0, %1\", operands); 3086 return \"mov%?\\t%R0, %Q0, asr #31\"; 3087 " 3088 [(set_attr "length" "8") 3089 (set_attr "shift" "1") 3090 (set_attr "predicable" "yes")] 3091) 3092 3093(define_expand "zero_extendhisi2" 3094 [(set (match_dup 2) 3095 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "") 3096 (const_int 16))) 3097 (set (match_operand:SI 0 "s_register_operand" "") 3098 (lshiftrt:SI (match_dup 2) (const_int 16)))] 3099 "TARGET_EITHER" 3100 " 3101 { 3102 if (TARGET_ARM) 3103 { 3104 if (arm_arch4 && GET_CODE (operands[1]) == MEM) 3105 { 3106 /* Note: We do not have to worry about TARGET_MMU_TRAPS 3107 here because the insn below will generate an LDRH instruction 3108 rather than an LDR instruction, so we cannot get an unaligned 3109 word access. */ 3110 emit_insn (gen_rtx_SET (VOIDmode, operands[0], 3111 gen_rtx_ZERO_EXTEND (SImode, 3112 operands[1]))); 3113 DONE; 3114 } 3115 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM) 3116 { 3117 emit_insn (gen_movhi_bytes (operands[0], operands[1])); 3118 DONE; 3119 } 3120 if (!s_register_operand (operands[1], HImode)) 3121 operands[1] = copy_to_mode_reg (HImode, operands[1]); 3122 operands[1] = gen_lowpart (SImode, operands[1]); 3123 operands[2] = gen_reg_rtx (SImode); 3124 } 3125 else /* TARGET_THUMB */ 3126 { 3127 if (GET_CODE (operands[1]) == MEM) 3128 { 3129 rtx tmp; 3130 3131 tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]); 3132 tmp = gen_rtx_SET (VOIDmode, operands[0], tmp); 3133 emit_insn (tmp); 3134 } 3135 else 3136 { 3137 rtx ops[3]; 3138 3139 if (!s_register_operand (operands[1], HImode)) 3140 operands[1] = copy_to_mode_reg (HImode, operands[1]); 3141 operands[1] = gen_lowpart (SImode, operands[1]); 3142 operands[2] = gen_reg_rtx (SImode); 3143 3144 ops[0] = operands[2]; 3145 ops[1] = operands[1]; 3146 ops[2] = GEN_INT (16); 3147 3148 emit_insn (gen_rtx_SET (VOIDmode, ops[0], 3149 gen_rtx_ASHIFT (SImode, ops[1], ops[2]))); 3150 3151 ops[0] = operands[0]; 3152 ops[1] = operands[2]; 3153 ops[2] = GEN_INT (16); 3154 3155 emit_insn (gen_rtx_SET (VOIDmode, ops[0], 3156 gen_rtx_LSHIFTRT (SImode, ops[1], 3157 ops[2]))); 3158 } 3159 DONE; 3160 } 3161 }" 3162) 3163 3164(define_insn "*thumb_zero_extendhisi2" 3165 [(set (match_operand:SI 0 "register_operand" "=l") 3166 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] 3167 "TARGET_THUMB" 3168 "* 3169 rtx mem = XEXP (operands[1], 0); 3170 3171 if (GET_CODE (mem) == CONST) 3172 mem = XEXP (mem, 0); 3173 3174 if (GET_CODE (mem) == LABEL_REF) 3175 return \"ldr\\t%0, %1\"; 3176 3177 if (GET_CODE (mem) == PLUS) 3178 { 3179 rtx a = XEXP (mem, 0); 3180 rtx b = XEXP (mem, 1); 3181 3182 /* This can happen due to bugs in reload. */ 3183 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM) 3184 { 3185 rtx ops[2]; 3186 ops[0] = operands[0]; 3187 ops[1] = a; 3188 3189 output_asm_insn (\"mov %0, %1\", ops); 3190 3191 XEXP (mem, 0) = operands[0]; 3192 } 3193 3194 else if ( GET_CODE (a) == LABEL_REF 3195 && GET_CODE (b) == CONST_INT) 3196 return \"ldr\\t%0, %1\"; 3197 } 3198 3199 return \"ldrh\\t%0, %1\"; 3200 " 3201 [(set_attr "length" "4") 3202 (set_attr "type" "load") 3203 (set_attr "pool_range" "60")] 3204) 3205 3206(define_insn "*arm_zero_extendhisi2" 3207 [(set (match_operand:SI 0 "s_register_operand" "=r") 3208 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] 3209 "TARGET_ARM && arm_arch4" 3210 "ldr%?h\\t%0, %1" 3211 [(set_attr "type" "load") 3212 (set_attr "predicable" "yes") 3213 (set_attr "pool_range" "256") 3214 (set_attr "neg_pool_range" "244")] 3215) 3216 3217(define_split 3218 [(set (match_operand:SI 0 "s_register_operand" "") 3219 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))) 3220 (clobber (match_operand:SI 2 "s_register_operand" ""))] 3221 "TARGET_ARM && (!arm_arch4)" 3222 [(set (match_dup 2) (match_dup 1)) 3223 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))] 3224 " 3225 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL) 3226 FAIL; 3227 " 3228) 3229 3230(define_split 3231 [(set (match_operand:SI 0 "s_register_operand" "") 3232 (match_operator:SI 3 "shiftable_operator" 3233 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")) 3234 (match_operand:SI 4 "s_register_operand" "")])) 3235 (clobber (match_operand:SI 2 "s_register_operand" ""))] 3236 "TARGET_ARM && (!arm_arch4)" 3237 [(set (match_dup 2) (match_dup 1)) 3238 (set (match_dup 0) 3239 (match_op_dup 3 3240 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))] 3241 " 3242 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL) 3243 FAIL; 3244 " 3245) 3246 3247(define_expand "zero_extendqisi2" 3248 [(set (match_operand:SI 0 "s_register_operand" "") 3249 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] 3250 "TARGET_EITHER" 3251 " 3252 if (GET_CODE (operands[1]) != MEM) 3253 { 3254 if (TARGET_ARM) 3255 { 3256 emit_insn (gen_andsi3 (operands[0], 3257 gen_lowpart (SImode, operands[1]), 3258 GEN_INT (255))); 3259 } 3260 else /* TARGET_THUMB */ 3261 { 3262 rtx temp = gen_reg_rtx (SImode); 3263 rtx ops[3]; 3264 3265 operands[1] = copy_to_mode_reg (QImode, operands[1]); 3266 operands[1] = gen_lowpart (SImode, operands[1]); 3267 3268 ops[0] = temp; 3269 ops[1] = operands[1]; 3270 ops[2] = GEN_INT (24); 3271 3272 emit_insn (gen_rtx_SET (VOIDmode, ops[0], 3273 gen_rtx_ASHIFT (SImode, ops[1], ops[2]))); 3274 3275 ops[0] = operands[0]; 3276 ops[1] = temp; 3277 ops[2] = GEN_INT (24); 3278 3279 emit_insn (gen_rtx_SET (VOIDmode, ops[0], 3280 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2]))); 3281 } 3282 DONE; 3283 } 3284 " 3285) 3286 3287(define_insn "*thumb_zero_extendqisi2" 3288 [(set (match_operand:SI 0 "register_operand" "=l") 3289 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] 3290 "TARGET_THUMB" 3291 "ldrb\\t%0, %1" 3292 [(set_attr "length" "2") 3293 (set_attr "type" "load") 3294 (set_attr "pool_range" "32")] 3295) 3296 3297(define_insn "*arm_zero_extendqisi2" 3298 [(set (match_operand:SI 0 "s_register_operand" "=r") 3299 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] 3300 "TARGET_ARM" 3301 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2" 3302 [(set_attr "type" "load") 3303 (set_attr "predicable" "yes") 3304 (set_attr "pool_range" "4096") 3305 (set_attr "neg_pool_range" "4084")] 3306) 3307 3308(define_split 3309 [(set (match_operand:SI 0 "s_register_operand" "") 3310 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0))) 3311 (clobber (match_operand:SI 2 "s_register_operand" ""))] 3312 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN" 3313 [(set (match_dup 2) (match_dup 1)) 3314 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))] 3315 "" 3316) 3317 3318(define_insn "*compareqi_eq0" 3319 [(set (reg:CC_Z CC_REGNUM) 3320 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r") 3321 (const_int 0)))] 3322 "TARGET_ARM" 3323 "tst\\t%0, #255" 3324 [(set_attr "conds" "set")] 3325) 3326 3327(define_expand "extendhisi2" 3328 [(set (match_dup 2) 3329 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "") 3330 (const_int 16))) 3331 (set (match_operand:SI 0 "s_register_operand" "") 3332 (ashiftrt:SI (match_dup 2) 3333 (const_int 16)))] 3334 "TARGET_EITHER" 3335 " 3336 { 3337 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM) 3338 { 3339 /* Note: We do not have to worry about TARGET_MMU_TRAPS 3340 here because the insn below will generate an LDRH instruction 3341 rather than an LDR instruction, so we cannot get an unaligned 3342 word access. */ 3343 emit_insn (gen_rtx_SET (VOIDmode, operands[0], 3344 gen_rtx_SIGN_EXTEND (SImode, operands[1]))); 3345 DONE; 3346 } 3347 3348 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM) 3349 { 3350 emit_insn (gen_extendhisi2_mem (operands[0], operands[1])); 3351 DONE; 3352 } 3353 if (!s_register_operand (operands[1], HImode)) 3354 operands[1] = copy_to_mode_reg (HImode, operands[1]); 3355 operands[1] = gen_lowpart (SImode, operands[1]); 3356 operands[2] = gen_reg_rtx (SImode); 3357 3358 if (TARGET_THUMB) 3359 { 3360 rtx ops[3]; 3361 3362 ops[0] = operands[2]; 3363 ops[1] = operands[1]; 3364 ops[2] = GEN_INT (16); 3365 3366 emit_insn (gen_rtx_SET (VOIDmode, ops[0], 3367 gen_rtx_ASHIFT (SImode, ops[1], ops[2]))); 3368 3369 ops[0] = operands[0]; 3370 ops[1] = operands[2]; 3371 ops[2] = GEN_INT (16); 3372 3373 emit_insn (gen_rtx_SET (VOIDmode, ops[0], 3374 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2]))); 3375 3376 DONE; 3377 } 3378 }" 3379) 3380 3381(define_insn "*thumb_extendhisi2_insn" 3382 [(set (match_operand:SI 0 "register_operand" "=l") 3383 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m"))) 3384 (clobber (match_scratch:SI 2 "=&l"))] 3385 "TARGET_THUMB" 3386 "* 3387 { 3388 rtx ops[4]; 3389 rtx mem = XEXP (operands[1], 0); 3390 3391 /* This code used to try to use 'V', and fix the address only if it was 3392 offsettable, but this fails for e.g. REG+48 because 48 is outside the 3393 range of QImode offsets, and offsettable_address_p does a QImode 3394 address check. */ 3395 3396 if (GET_CODE (mem) == CONST) 3397 mem = XEXP (mem, 0); 3398 3399 if (GET_CODE (mem) == LABEL_REF) 3400 return \"ldr\\t%0, %1\"; 3401 3402 if (GET_CODE (mem) == PLUS) 3403 { 3404 rtx a = XEXP (mem, 0); 3405 rtx b = XEXP (mem, 1); 3406 3407 if (GET_CODE (a) == LABEL_REF 3408 && GET_CODE (b) == CONST_INT) 3409 return \"ldr\\t%0, %1\"; 3410 3411 if (GET_CODE (b) == REG) 3412 return \"ldrsh\\t%0, %1\"; 3413 3414 ops[1] = a; 3415 ops[2] = b; 3416 } 3417 else 3418 { 3419 ops[1] = mem; 3420 ops[2] = const0_rtx; 3421 } 3422 3423 if (GET_CODE (ops[1]) != REG) 3424 { 3425 debug_rtx (ops[1]); 3426 abort (); 3427 } 3428 3429 ops[0] = operands[0]; 3430 ops[3] = operands[2]; 3431 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops); 3432 return \"\"; 3433 }" 3434 [(set_attr "length" "4") 3435 (set_attr "type" "load") 3436 (set_attr "pool_range" "1020")] 3437) 3438 3439(define_expand "extendhisi2_mem" 3440 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" ""))) 3441 (set (match_dup 3) 3442 (zero_extend:SI (match_dup 7))) 3443 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24))) 3444 (set (match_operand:SI 0 "" "") 3445 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))] 3446 "TARGET_ARM" 3447 " 3448 { 3449 rtx mem1, mem2; 3450 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); 3451 3452 mem1 = gen_rtx_MEM (QImode, addr); 3453 MEM_COPY_ATTRIBUTES (mem1, operands[1]); 3454 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1)); 3455 MEM_COPY_ATTRIBUTES (mem2, operands[1]); 3456 operands[0] = gen_lowpart (SImode, operands[0]); 3457 operands[1] = mem1; 3458 operands[2] = gen_reg_rtx (SImode); 3459 operands[3] = gen_reg_rtx (SImode); 3460 operands[6] = gen_reg_rtx (SImode); 3461 operands[7] = mem2; 3462 3463 if (BYTES_BIG_ENDIAN) 3464 { 3465 operands[4] = operands[2]; 3466 operands[5] = operands[3]; 3467 } 3468 else 3469 { 3470 operands[4] = operands[3]; 3471 operands[5] = operands[2]; 3472 } 3473 }" 3474) 3475 3476(define_insn "*arm_extendhisi_insn" 3477 [(set (match_operand:SI 0 "s_register_operand" "=r") 3478 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))] 3479 "TARGET_ARM && arm_arch4" 3480 "ldr%?sh\\t%0, %1" 3481 [(set_attr "type" "load") 3482 (set_attr "predicable" "yes") 3483 (set_attr "pool_range" "256") 3484 (set_attr "neg_pool_range" "244")] 3485) 3486 3487(define_split 3488 [(set (match_operand:SI 0 "s_register_operand" "") 3489 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))) 3490 (clobber (match_operand:SI 2 "s_register_operand" ""))] 3491 "TARGET_ARM && (!arm_arch4)" 3492 [(set (match_dup 2) (match_dup 1)) 3493 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))] 3494 " 3495 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL) 3496 FAIL; 3497 " 3498) 3499 3500(define_split 3501 [(set (match_operand:SI 0 "s_register_operand" "") 3502 (match_operator:SI 3 "shiftable_operator" 3503 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")) 3504 (match_operand:SI 4 "s_register_operand" "")])) 3505 (clobber (match_operand:SI 2 "s_register_operand" ""))] 3506 "TARGET_ARM && (!arm_arch4)" 3507 [(set (match_dup 2) (match_dup 1)) 3508 (set (match_dup 0) 3509 (match_op_dup 3 3510 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))] 3511 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL) 3512 FAIL; 3513 " 3514) 3515 3516(define_expand "extendqihi2" 3517 [(set (match_dup 2) 3518 (ashift:SI (match_operand:QI 1 "general_operand" "") 3519 (const_int 24))) 3520 (set (match_operand:HI 0 "s_register_operand" "") 3521 (ashiftrt:SI (match_dup 2) 3522 (const_int 24)))] 3523 "TARGET_ARM" 3524 " 3525 { 3526 if (arm_arch4 && GET_CODE (operands[1]) == MEM) 3527 { 3528 emit_insn (gen_rtx_SET (VOIDmode, 3529 operands[0], 3530 gen_rtx_SIGN_EXTEND (HImode, operands[1]))); 3531 DONE; 3532 } 3533 if (!s_register_operand (operands[1], QImode)) 3534 operands[1] = copy_to_mode_reg (QImode, operands[1]); 3535 operands[0] = gen_lowpart (SImode, operands[0]); 3536 operands[1] = gen_lowpart (SImode, operands[1]); 3537 operands[2] = gen_reg_rtx (SImode); 3538 }" 3539) 3540 3541; Rather than restricting all byte accesses to memory addresses that ldrsb 3542; can handle, we fix up the ones that ldrsb can't grok with a split. 3543(define_insn "*extendqihi_insn" 3544 [(set (match_operand:HI 0 "s_register_operand" "=r") 3545 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))] 3546 "TARGET_ARM && arm_arch4" 3547 "* 3548 /* If the address is invalid, this will split the instruction into two. */ 3549 if (bad_signed_byte_operand (operands[1], VOIDmode)) 3550 return \"#\"; 3551 return \"ldr%?sb\\t%0, %1\"; 3552 " 3553 [(set_attr "type" "load") 3554 (set_attr "predicable" "yes") 3555 (set_attr "length" "8") 3556 (set_attr "pool_range" "256") 3557 (set_attr "neg_pool_range" "244")] 3558) 3559 3560(define_split 3561 [(set (match_operand:HI 0 "s_register_operand" "") 3562 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))] 3563 "TARGET_ARM && arm_arch4 && reload_completed" 3564 [(set (match_dup 3) (match_dup 1)) 3565 (set (match_dup 0) (sign_extend:HI (match_dup 2)))] 3566 " 3567 { 3568 HOST_WIDE_INT offset; 3569 3570 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0])); 3571 operands[2] = gen_rtx_MEM (QImode, operands[3]); 3572 MEM_COPY_ATTRIBUTES (operands[2], operands[1]); 3573 operands[1] = XEXP (operands[1], 0); 3574 if (GET_CODE (operands[1]) == PLUS 3575 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT 3576 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1))) 3577 || const_ok_for_arm (-offset))) 3578 { 3579 HOST_WIDE_INT low = (offset > 0 3580 ? (offset & 0xff) : -((-offset) & 0xff)); 3581 XEXP (operands[2], 0) = plus_constant (operands[3], low); 3582 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low); 3583 } 3584 /* Ensure the sum is in correct canonical form. */ 3585 else if (GET_CODE (operands[1]) == PLUS 3586 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT 3587 && !s_register_operand (XEXP (operands[1], 1), VOIDmode)) 3588 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]), 3589 XEXP (operands[1], 1), 3590 XEXP (operands[1], 0)); 3591 }" 3592) 3593 3594(define_expand "extendqisi2" 3595 [(set (match_dup 2) 3596 (ashift:SI (match_operand:QI 1 "general_operand" "") 3597 (const_int 24))) 3598 (set (match_operand:SI 0 "s_register_operand" "") 3599 (ashiftrt:SI (match_dup 2) 3600 (const_int 24)))] 3601 "TARGET_EITHER" 3602 " 3603 { 3604 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM) 3605 { 3606 emit_insn (gen_rtx_SET (VOIDmode, 3607 operands[0], 3608 gen_rtx_SIGN_EXTEND (SImode, operands[1]))); 3609 DONE; 3610 } 3611 if (!s_register_operand (operands[1], QImode)) 3612 operands[1] = copy_to_mode_reg (QImode, operands[1]); 3613 operands[1] = gen_lowpart (SImode, operands[1]); 3614 operands[2] = gen_reg_rtx (SImode); 3615 3616 if (TARGET_THUMB) 3617 { 3618 rtx ops[3]; 3619 3620 ops[0] = operands[2]; 3621 ops[1] = operands[1]; 3622 ops[2] = GEN_INT (24); 3623 3624 emit_insn (gen_rtx_SET (VOIDmode, ops[0], 3625 gen_rtx_ASHIFT (SImode, ops[1], ops[2]))); 3626 3627 ops[0] = operands[0]; 3628 ops[1] = operands[2]; 3629 ops[2] = GEN_INT (24); 3630 3631 emit_insn (gen_rtx_SET (VOIDmode, ops[0], 3632 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2]))); 3633 3634 DONE; 3635 } 3636 }" 3637) 3638 3639; Rather than restricting all byte accesses to memory addresses that ldrsb 3640; can handle, we fix up the ones that ldrsb can't grok with a split. 3641(define_insn "*arm_extendqisi_insn" 3642 [(set (match_operand:SI 0 "s_register_operand" "=r") 3643 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))] 3644 "TARGET_ARM && arm_arch4" 3645 "* 3646 /* If the address is invalid, this will split the instruction into two. */ 3647 if (bad_signed_byte_operand (operands[1], VOIDmode)) 3648 return \"#\"; 3649 return \"ldr%?sb\\t%0, %1\"; 3650 " 3651 [(set_attr "type" "load") 3652 (set_attr "predicable" "yes") 3653 (set_attr "length" "8") 3654 (set_attr "pool_range" "256") 3655 (set_attr "neg_pool_range" "244")] 3656) 3657 3658(define_split 3659 [(set (match_operand:SI 0 "s_register_operand" "") 3660 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))] 3661 "TARGET_ARM && arm_arch4 && reload_completed" 3662 [(set (match_dup 0) (match_dup 1)) 3663 (set (match_dup 0) (sign_extend:SI (match_dup 2)))] 3664 " 3665 { 3666 HOST_WIDE_INT offset; 3667 3668 operands[2] = gen_rtx_MEM (QImode, operands[0]); 3669 MEM_COPY_ATTRIBUTES (operands[2], operands[1]); 3670 operands[1] = XEXP (operands[1], 0); 3671 if (GET_CODE (operands[1]) == PLUS 3672 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT 3673 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1))) 3674 || const_ok_for_arm (-offset))) 3675 { 3676 HOST_WIDE_INT low = (offset > 0 3677 ? (offset & 0xff) : -((-offset) & 0xff)); 3678 XEXP (operands[2], 0) = plus_constant (operands[0], low); 3679 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low); 3680 } 3681 /* Ensure the sum is in correct canonical form. */ 3682 else if (GET_CODE (operands[1]) == PLUS 3683 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT 3684 && !s_register_operand (XEXP (operands[1], 1), VOIDmode)) 3685 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]), 3686 XEXP (operands[1], 1), 3687 XEXP (operands[1], 0)); 3688 }" 3689) 3690 3691(define_insn "*thumb_extendqisi2_insn" 3692 [(set (match_operand:SI 0 "register_operand" "=l,l") 3693 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))] 3694 "TARGET_THUMB" 3695 "* 3696 { 3697 rtx ops[3]; 3698 rtx mem = XEXP (operands[1], 0); 3699 3700 if (GET_CODE (mem) == CONST) 3701 mem = XEXP (mem, 0); 3702 3703 if (GET_CODE (mem) == LABEL_REF) 3704 return \"ldr\\t%0, %1\"; 3705 3706 if (GET_CODE (mem) == PLUS 3707 && GET_CODE (XEXP (mem, 0)) == LABEL_REF) 3708 return \"ldr\\t%0, %1\"; 3709 3710 if (which_alternative == 0) 3711 return \"ldrsb\\t%0, %1\"; 3712 3713 ops[0] = operands[0]; 3714 3715 if (GET_CODE (mem) == PLUS) 3716 { 3717 rtx a = XEXP (mem, 0); 3718 rtx b = XEXP (mem, 1); 3719 3720 ops[1] = a; 3721 ops[2] = b; 3722 3723 if (GET_CODE (a) == REG) 3724 { 3725 if (GET_CODE (b) == REG) 3726 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops); 3727 else if (REGNO (a) == REGNO (ops[0])) 3728 { 3729 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops); 3730 output_asm_insn (\"lsl\\t%0, %0, #24\", ops); 3731 output_asm_insn (\"asr\\t%0, %0, #24\", ops); 3732 } 3733 else 3734 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); 3735 } 3736 else if (GET_CODE (b) != REG) 3737 abort (); 3738 else 3739 { 3740 if (REGNO (b) == REGNO (ops[0])) 3741 { 3742 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops); 3743 output_asm_insn (\"lsl\\t%0, %0, #24\", ops); 3744 output_asm_insn (\"asr\\t%0, %0, #24\", ops); 3745 } 3746 else 3747 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); 3748 } 3749 } 3750 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem)) 3751 { 3752 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops); 3753 output_asm_insn (\"lsl\\t%0, %0, #24\", ops); 3754 output_asm_insn (\"asr\\t%0, %0, #24\", ops); 3755 } 3756 else 3757 { 3758 ops[1] = mem; 3759 ops[2] = const0_rtx; 3760 3761 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); 3762 } 3763 return \"\"; 3764 }" 3765 [(set_attr "length" "2,6") 3766 (set_attr "type" "load,load") 3767 (set_attr "pool_range" "32,32")] 3768) 3769 3770(define_expand "extendsfdf2" 3771 [(set (match_operand:DF 0 "s_register_operand" "") 3772 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))] 3773 "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 3774 "" 3775) 3776 3777;; Move insns (including loads and stores) 3778 3779;; XXX Just some ideas about movti. 3780;; I don't think these are a good idea on the arm, there just aren't enough 3781;; registers 3782;;(define_expand "loadti" 3783;; [(set (match_operand:TI 0 "s_register_operand" "") 3784;; (mem:TI (match_operand:SI 1 "address_operand" "")))] 3785;; "" "") 3786 3787;;(define_expand "storeti" 3788;; [(set (mem:TI (match_operand:TI 0 "address_operand" "")) 3789;; (match_operand:TI 1 "s_register_operand" ""))] 3790;; "" "") 3791 3792;;(define_expand "movti" 3793;; [(set (match_operand:TI 0 "general_operand" "") 3794;; (match_operand:TI 1 "general_operand" ""))] 3795;; "" 3796;; " 3797;;{ 3798;; rtx insn; 3799;; 3800;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) 3801;; operands[1] = copy_to_reg (operands[1]); 3802;; if (GET_CODE (operands[0]) == MEM) 3803;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]); 3804;; else if (GET_CODE (operands[1]) == MEM) 3805;; insn = gen_loadti (operands[0], XEXP (operands[1], 0)); 3806;; else 3807;; FAIL; 3808;; 3809;; emit_insn (insn); 3810;; DONE; 3811;;}") 3812 3813;; Recognize garbage generated above. 3814 3815;;(define_insn "" 3816;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m") 3817;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))] 3818;; "" 3819;; "* 3820;; { 3821;; register mem = (which_alternative < 3); 3822;; register const char *template; 3823;; 3824;; operands[mem] = XEXP (operands[mem], 0); 3825;; switch (which_alternative) 3826;; { 3827;; case 0: template = \"ldmdb\\t%1!, %M0\"; break; 3828;; case 1: template = \"ldmia\\t%1!, %M0\"; break; 3829;; case 2: template = \"ldmia\\t%1, %M0\"; break; 3830;; case 3: template = \"stmdb\\t%0!, %M1\"; break; 3831;; case 4: template = \"stmia\\t%0!, %M1\"; break; 3832;; case 5: template = \"stmia\\t%0, %M1\"; break; 3833;; } 3834;; output_asm_insn (template, operands); 3835;; return \"\"; 3836;; }") 3837 3838(define_expand "movdi" 3839 [(set (match_operand:DI 0 "general_operand" "") 3840 (match_operand:DI 1 "general_operand" ""))] 3841 "TARGET_EITHER" 3842 " 3843 if (TARGET_THUMB) 3844 { 3845 if (!no_new_pseudos) 3846 { 3847 if (GET_CODE (operands[0]) != REG) 3848 operands[1] = force_reg (DImode, operands[1]); 3849 } 3850 } 3851 " 3852) 3853 3854(define_insn "*arm_movdi" 3855 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>") 3856 (match_operand:DI 1 "di_operand" "rIK,mi,r"))] 3857 "TARGET_ARM && !TARGET_CIRRUS && ! TARGET_IWMMXT" 3858 "* 3859 return (output_move_double (operands)); 3860 " 3861 [(set_attr "length" "8") 3862 (set_attr "type" "*,load,store2") 3863 (set_attr "pool_range" "*,1020,*") 3864 (set_attr "neg_pool_range" "*,1008,*")] 3865) 3866 3867;;; ??? This should have alternatives for constants. 3868;;; ??? This was originally identical to the movdf_insn pattern. 3869;;; ??? The 'i' constraint looks funny, but it should always be replaced by 3870;;; thumb_reorg with a memory reference. 3871(define_insn "*thumb_movdi_insn" 3872 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r") 3873 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))] 3874 "TARGET_THUMB 3875 && !TARGET_CIRRUS 3876 && ( register_operand (operands[0], DImode) 3877 || register_operand (operands[1], DImode))" 3878 "* 3879 { 3880 switch (which_alternative) 3881 { 3882 default: 3883 case 0: 3884 if (REGNO (operands[1]) == REGNO (operands[0]) + 1) 3885 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\"; 3886 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\"; 3887 case 1: 3888 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\"; 3889 case 2: 3890 operands[1] = GEN_INT (- INTVAL (operands[1])); 3891 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\"; 3892 case 3: 3893 return \"ldmia\\t%1, {%0, %H0}\"; 3894 case 4: 3895 return \"stmia\\t%0, {%1, %H1}\"; 3896 case 5: 3897 return thumb_load_double_from_address (operands); 3898 case 6: 3899 operands[2] = gen_rtx (MEM, SImode, 3900 plus_constant (XEXP (operands[0], 0), 4)); 3901 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands); 3902 return \"\"; 3903 case 7: 3904 if (REGNO (operands[1]) == REGNO (operands[0]) + 1) 3905 return \"mov\\t%0, %1\;mov\\t%H0, %H1\"; 3906 return \"mov\\t%H0, %H1\;mov\\t%0, %1\"; 3907 } 3908 }" 3909 [(set_attr "length" "4,4,6,2,2,6,4,4") 3910 (set_attr "type" "*,*,*,load,store2,load,store2,*") 3911 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")] 3912) 3913 3914(define_expand "movsi" 3915 [(set (match_operand:SI 0 "general_operand" "") 3916 (match_operand:SI 1 "general_operand" ""))] 3917 "TARGET_EITHER" 3918 " 3919 if (TARGET_ARM) 3920 { 3921 /* Everything except mem = const or mem = mem can be done easily. */ 3922 if (GET_CODE (operands[0]) == MEM) 3923 operands[1] = force_reg (SImode, operands[1]); 3924 if (GET_CODE (operands[1]) == CONST_INT 3925 && !(const_ok_for_arm (INTVAL (operands[1])) 3926 || const_ok_for_arm (~INTVAL (operands[1])))) 3927 { 3928 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0], 3929 NULL_RTX, 3930 (no_new_pseudos ? 0 3931 : preserve_subexpressions_p ())); 3932 DONE; 3933 } 3934 } 3935 else /* TARGET_THUMB.... */ 3936 { 3937 if (!no_new_pseudos) 3938 { 3939 if (GET_CODE (operands[0]) != REG) 3940 operands[1] = force_reg (SImode, operands[1]); 3941 } 3942 } 3943 3944 if (flag_pic 3945 && (CONSTANT_P (operands[1]) 3946 || symbol_mentioned_p (operands[1]) 3947 || label_mentioned_p (operands[1]))) 3948 operands[1] = legitimize_pic_address (operands[1], SImode, 3949 (no_new_pseudos ? operands[0] : 0)); 3950 " 3951) 3952 3953(define_insn "*arm_movsi_insn" 3954 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m") 3955 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))] 3956 "TARGET_ARM && ! TARGET_IWMMXT 3957 && ( register_operand (operands[0], SImode) 3958 || register_operand (operands[1], SImode))" 3959 "@ 3960 mov%?\\t%0, %1 3961 mvn%?\\t%0, #%B1 3962 ldr%?\\t%0, %1 3963 str%?\\t%1, %0" 3964 [(set_attr "type" "*,*,load,store1") 3965 (set_attr "predicable" "yes") 3966 (set_attr "pool_range" "*,*,4096,*") 3967 (set_attr "neg_pool_range" "*,*,4084,*")] 3968) 3969 3970(define_split 3971 [(set (match_operand:SI 0 "s_register_operand" "") 3972 (match_operand:SI 1 "const_int_operand" ""))] 3973 "TARGET_ARM 3974 && (!(const_ok_for_arm (INTVAL (operands[1])) 3975 || const_ok_for_arm (~INTVAL (operands[1]))))" 3976 [(clobber (const_int 0))] 3977 " 3978 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0], 3979 NULL_RTX, 0); 3980 DONE; 3981 " 3982) 3983 3984(define_insn "*thumb_movsi_insn" 3985 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh") 3986 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))] 3987 "TARGET_THUMB 3988 && ( register_operand (operands[0], SImode) 3989 || register_operand (operands[1], SImode))" 3990 "@ 3991 mov %0, %1 3992 mov %0, %1 3993 # 3994 # 3995 ldmia\\t%1, {%0} 3996 stmia\\t%0, {%1} 3997 ldr\\t%0, %1 3998 str\\t%1, %0 3999 mov\\t%0, %1" 4000 [(set_attr "length" "2,2,4,4,2,2,2,2,2") 4001 (set_attr "type" "*,*,*,*,load,store1,load,store1,*") 4002 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")] 4003) 4004 4005(define_split 4006 [(set (match_operand:SI 0 "register_operand" "") 4007 (match_operand:SI 1 "const_int_operand" ""))] 4008 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')" 4009 [(set (match_dup 0) (match_dup 1)) 4010 (set (match_dup 0) (neg:SI (match_dup 0)))] 4011 "operands[1] = GEN_INT (- INTVAL (operands[1]));" 4012) 4013 4014(define_split 4015 [(set (match_operand:SI 0 "register_operand" "") 4016 (match_operand:SI 1 "const_int_operand" ""))] 4017 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')" 4018 [(set (match_dup 0) (match_dup 1)) 4019 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))] 4020 " 4021 { 4022 unsigned HOST_WIDE_INT val = INTVAL (operands[1]); 4023 unsigned HOST_WIDE_INT mask = 0xff; 4024 int i; 4025 4026 for (i = 0; i < 25; i++) 4027 if ((val & (mask << i)) == val) 4028 break; 4029 4030 /* Shouldn't happen, but we don't want to split if the shift is zero. */ 4031 if (i == 0) 4032 FAIL; 4033 4034 operands[1] = GEN_INT (val >> i); 4035 operands[2] = GEN_INT (i); 4036 }" 4037) 4038 4039;; When generating pic, we need to load the symbol offset into a register. 4040;; So that the optimizer does not confuse this with a normal symbol load 4041;; we use an unspec. The offset will be loaded from a constant pool entry, 4042;; since that is the only type of relocation we can use. 4043 4044;; The rather odd constraints on the following are to force reload to leave 4045;; the insn alone, and to force the minipool generation pass to then move 4046;; the GOT symbol to memory. 4047 4048(define_insn "pic_load_addr_arm" 4049 [(set (match_operand:SI 0 "s_register_operand" "=r") 4050 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))] 4051 "TARGET_ARM && flag_pic" 4052 "ldr%?\\t%0, %1" 4053 [(set_attr "type" "load") 4054 (set (attr "pool_range") (const_int 4096)) 4055 (set (attr "neg_pool_range") (const_int 4084))] 4056) 4057 4058(define_insn "pic_load_addr_thumb" 4059 [(set (match_operand:SI 0 "s_register_operand" "=l") 4060 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))] 4061 "TARGET_THUMB && flag_pic" 4062 "ldr\\t%0, %1" 4063 [(set_attr "type" "load") 4064 (set (attr "pool_range") (const_int 1024))] 4065) 4066 4067;; This variant is used for AOF assembly, since it needs to mention the 4068;; pic register in the rtl. 4069(define_expand "pic_load_addr_based" 4070 [(set (match_operand:SI 0 "s_register_operand" "") 4071 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))] 4072 "TARGET_ARM && flag_pic" 4073 "operands[2] = pic_offset_table_rtx;" 4074) 4075 4076(define_insn "*pic_load_addr_based_insn" 4077 [(set (match_operand:SI 0 "s_register_operand" "=r") 4078 (unspec:SI [(match_operand 1 "" "") 4079 (match_operand 2 "s_register_operand" "r")] 4080 UNSPEC_PIC_SYM))] 4081 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx" 4082 "* 4083#ifdef AOF_ASSEMBLER 4084 operands[1] = aof_pic_entry (operands[1]); 4085#endif 4086 output_asm_insn (\"ldr%?\\t%0, %a1\", operands); 4087 return \"\"; 4088 " 4089 [(set_attr "type" "load") 4090 (set (attr "pool_range") 4091 (if_then_else (eq_attr "is_thumb" "yes") 4092 (const_int 1024) 4093 (const_int 4096))) 4094 (set (attr "neg_pool_range") 4095 (if_then_else (eq_attr "is_thumb" "yes") 4096 (const_int 0) 4097 (const_int 4084)))] 4098) 4099 4100(define_insn "pic_add_dot_plus_four" 4101 [(set (match_operand:SI 0 "register_operand" "+r") 4102 (unspec:SI [(plus:SI (match_dup 0) 4103 (const (plus:SI (pc) (const_int 4))))] 4104 UNSPEC_PIC_BASE)) 4105 (use (label_ref (match_operand 1 "" "")))] 4106 "TARGET_THUMB && flag_pic" 4107 "* 4108 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", 4109 CODE_LABEL_NUMBER (operands[1])); 4110 return \"add\\t%0, %|pc\"; 4111 " 4112 [(set_attr "length" "2")] 4113) 4114 4115(define_insn "pic_add_dot_plus_eight" 4116 [(set (match_operand:SI 0 "register_operand" "+r") 4117 (unspec:SI [(plus:SI (match_dup 0) 4118 (const (plus:SI (pc) (const_int 8))))] 4119 UNSPEC_PIC_BASE)) 4120 (use (label_ref (match_operand 1 "" "")))] 4121 "TARGET_ARM && flag_pic" 4122 "* 4123 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", 4124 CODE_LABEL_NUMBER (operands[1])); 4125 return \"add%?\\t%0, %|pc, %0\"; 4126 " 4127 [(set_attr "predicable" "yes")] 4128) 4129 4130(define_expand "builtin_setjmp_receiver" 4131 [(label_ref (match_operand 0 "" ""))] 4132 "flag_pic" 4133 " 4134{ 4135 arm_finalize_pic (0); 4136 DONE; 4137}") 4138 4139;; If copying one reg to another we can set the condition codes according to 4140;; its value. Such a move is common after a return from subroutine and the 4141;; result is being tested against zero. 4142 4143(define_insn "*movsi_compare0" 4144 [(set (reg:CC CC_REGNUM) 4145 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r") 4146 (const_int 0))) 4147 (set (match_operand:SI 0 "s_register_operand" "=r,r") 4148 (match_dup 1))] 4149 "TARGET_ARM" 4150 "@ 4151 cmp%?\\t%0, #0 4152 sub%?s\\t%0, %1, #0" 4153 [(set_attr "conds" "set")] 4154) 4155 4156;; Subroutine to store a half word from a register into memory. 4157;; Operand 0 is the source register (HImode) 4158;; Operand 1 is the destination address in a register (SImode) 4159 4160;; In both this routine and the next, we must be careful not to spill 4161;; a memory address of reg+large_const into a separate PLUS insn, since this 4162;; can generate unrecognizable rtl. 4163 4164(define_expand "storehi" 4165 [;; store the low byte 4166 (set (match_operand 1 "" "") (match_dup 3)) 4167 ;; extract the high byte 4168 (set (match_dup 2) 4169 (ashiftrt:SI (match_operand 0 "" "") (const_int 8))) 4170 ;; store the high byte 4171 (set (match_dup 4) (match_dup 5))] 4172 "TARGET_ARM" 4173 " 4174 { 4175 rtx op1 = operands[1]; 4176 rtx addr = XEXP (op1, 0); 4177 enum rtx_code code = GET_CODE (addr); 4178 4179 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT) 4180 || code == MINUS) 4181 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr)); 4182 4183 operands[4] = adjust_address (op1, QImode, 1); 4184 operands[1] = adjust_address (operands[1], QImode, 0); 4185 operands[3] = gen_lowpart (QImode, operands[0]); 4186 operands[0] = gen_lowpart (SImode, operands[0]); 4187 operands[2] = gen_reg_rtx (SImode); 4188 operands[5] = gen_lowpart (QImode, operands[2]); 4189 }" 4190) 4191 4192(define_expand "storehi_bigend" 4193 [(set (match_dup 4) (match_dup 3)) 4194 (set (match_dup 2) 4195 (ashiftrt:SI (match_operand 0 "" "") (const_int 8))) 4196 (set (match_operand 1 "" "") (match_dup 5))] 4197 "TARGET_ARM" 4198 " 4199 { 4200 rtx op1 = operands[1]; 4201 rtx addr = XEXP (op1, 0); 4202 enum rtx_code code = GET_CODE (addr); 4203 4204 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT) 4205 || code == MINUS) 4206 op1 = replace_equiv_address (op1, force_reg (SImode, addr)); 4207 4208 operands[4] = adjust_address (op1, QImode, 1); 4209 operands[1] = adjust_address (operands[1], QImode, 0); 4210 operands[3] = gen_lowpart (QImode, operands[0]); 4211 operands[0] = gen_lowpart (SImode, operands[0]); 4212 operands[2] = gen_reg_rtx (SImode); 4213 operands[5] = gen_lowpart (QImode, operands[2]); 4214 }" 4215) 4216 4217;; Subroutine to store a half word integer constant into memory. 4218(define_expand "storeinthi" 4219 [(set (match_operand 0 "" "") 4220 (match_operand 1 "" "")) 4221 (set (match_dup 3) (match_dup 2))] 4222 "TARGET_ARM" 4223 " 4224 { 4225 HOST_WIDE_INT value = INTVAL (operands[1]); 4226 rtx addr = XEXP (operands[0], 0); 4227 rtx op0 = operands[0]; 4228 enum rtx_code code = GET_CODE (addr); 4229 4230 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT) 4231 || code == MINUS) 4232 op0 = replace_equiv_address (op0, force_reg (SImode, addr)); 4233 4234 operands[1] = gen_reg_rtx (SImode); 4235 if (BYTES_BIG_ENDIAN) 4236 { 4237 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255))); 4238 if ((value & 255) == ((value >> 8) & 255)) 4239 operands[2] = operands[1]; 4240 else 4241 { 4242 operands[2] = gen_reg_rtx (SImode); 4243 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255))); 4244 } 4245 } 4246 else 4247 { 4248 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255))); 4249 if ((value & 255) == ((value >> 8) & 255)) 4250 operands[2] = operands[1]; 4251 else 4252 { 4253 operands[2] = gen_reg_rtx (SImode); 4254 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255))); 4255 } 4256 } 4257 4258 operands[3] = adjust_address (op0, QImode, 1); 4259 operands[0] = adjust_address (operands[0], QImode, 0); 4260 operands[2] = gen_lowpart (QImode, operands[2]); 4261 operands[1] = gen_lowpart (QImode, operands[1]); 4262 }" 4263) 4264 4265(define_expand "storehi_single_op" 4266 [(set (match_operand:HI 0 "memory_operand" "") 4267 (match_operand:HI 1 "general_operand" ""))] 4268 "TARGET_ARM && arm_arch4" 4269 " 4270 if (!s_register_operand (operands[1], HImode)) 4271 operands[1] = copy_to_mode_reg (HImode, operands[1]); 4272 " 4273) 4274 4275(define_expand "movhi" 4276 [(set (match_operand:HI 0 "general_operand" "") 4277 (match_operand:HI 1 "general_operand" ""))] 4278 "TARGET_EITHER" 4279 " 4280 if (TARGET_ARM) 4281 { 4282 if (!no_new_pseudos) 4283 { 4284 if (GET_CODE (operands[0]) == MEM) 4285 { 4286 if (arm_arch4) 4287 { 4288 emit_insn (gen_storehi_single_op (operands[0], operands[1])); 4289 DONE; 4290 } 4291 if (GET_CODE (operands[1]) == CONST_INT) 4292 emit_insn (gen_storeinthi (operands[0], operands[1])); 4293 else 4294 { 4295 if (GET_CODE (operands[1]) == MEM) 4296 operands[1] = force_reg (HImode, operands[1]); 4297 if (BYTES_BIG_ENDIAN) 4298 emit_insn (gen_storehi_bigend (operands[1], operands[0])); 4299 else 4300 emit_insn (gen_storehi (operands[1], operands[0])); 4301 } 4302 DONE; 4303 } 4304 /* Sign extend a constant, and keep it in an SImode reg. */ 4305 else if (GET_CODE (operands[1]) == CONST_INT) 4306 { 4307 rtx reg = gen_reg_rtx (SImode); 4308 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff; 4309 4310 /* If the constant is already valid, leave it alone. */ 4311 if (!const_ok_for_arm (val)) 4312 { 4313 /* If setting all the top bits will make the constant 4314 loadable in a single instruction, then set them. 4315 Otherwise, sign extend the number. */ 4316 4317 if (const_ok_for_arm (~(val | ~0xffff))) 4318 val |= ~0xffff; 4319 else if (val & 0x8000) 4320 val |= ~0xffff; 4321 } 4322 4323 emit_insn (gen_movsi (reg, GEN_INT (val))); 4324 operands[1] = gen_lowpart (HImode, reg); 4325 } 4326 else if (arm_arch4 && !no_new_pseudos && optimize > 0 4327 && GET_CODE (operands[1]) == MEM) 4328 { 4329 rtx reg = gen_reg_rtx (SImode); 4330 4331 emit_insn (gen_zero_extendhisi2 (reg, operands[1])); 4332 operands[1] = gen_lowpart (HImode, reg); 4333 } 4334 else if (!arm_arch4) 4335 { 4336 /* Note: We do not have to worry about TARGET_MMU_TRAPS 4337 for v4 and up architectures because LDRH instructions will 4338 be used to access the HI values, and these cannot generate 4339 unaligned word access faults in the MMU. */ 4340 if (GET_CODE (operands[1]) == MEM) 4341 { 4342 if (TARGET_MMU_TRAPS) 4343 { 4344 rtx base; 4345 rtx offset = const0_rtx; 4346 rtx reg = gen_reg_rtx (SImode); 4347 4348 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG 4349 || (GET_CODE (base) == PLUS 4350 && (GET_CODE (offset = XEXP (base, 1)) 4351 == CONST_INT) 4352 && ((INTVAL(offset) & 1) != 1) 4353 && GET_CODE (base = XEXP (base, 0)) == REG)) 4354 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32) 4355 { 4356 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3; 4357 rtx new; 4358 4359 new = gen_rtx_MEM (SImode, 4360 plus_constant (base, new_offset)); 4361 MEM_COPY_ATTRIBUTES (new, operands[1]); 4362 emit_insn (gen_movsi (reg, new)); 4363 if (((INTVAL (offset) & 2) != 0) 4364 ^ (BYTES_BIG_ENDIAN ? 1 : 0)) 4365 { 4366 rtx reg2 = gen_reg_rtx (SImode); 4367 4368 emit_insn (gen_lshrsi3 (reg2, reg, 4369 GEN_INT (16))); 4370 reg = reg2; 4371 } 4372 } 4373 else 4374 emit_insn (gen_movhi_bytes (reg, operands[1])); 4375 4376 operands[1] = gen_lowpart (HImode, reg); 4377 } 4378 else if (BYTES_BIG_ENDIAN) 4379 { 4380 rtx base; 4381 rtx offset = const0_rtx; 4382 4383 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG 4384 || (GET_CODE (base) == PLUS 4385 && (GET_CODE (offset = XEXP (base, 1)) 4386 == CONST_INT) 4387 && GET_CODE (base = XEXP (base, 0)) == REG)) 4388 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32) 4389 { 4390 rtx reg = gen_reg_rtx (SImode); 4391 rtx new; 4392 4393 if ((INTVAL (offset) & 2) == 2) 4394 { 4395 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2; 4396 new = gen_rtx_MEM (SImode, 4397 plus_constant (base, 4398 new_offset)); 4399 MEM_COPY_ATTRIBUTES (new, operands[1]); 4400 emit_insn (gen_movsi (reg, new)); 4401 } 4402 else 4403 { 4404 new = gen_rtx_MEM (SImode, 4405 XEXP (operands[1], 0)); 4406 MEM_COPY_ATTRIBUTES (new, operands[1]); 4407 emit_insn (gen_rotated_loadsi (reg, new)); 4408 } 4409 4410 operands[1] = gen_lowpart (HImode, reg); 4411 } 4412 else 4413 { 4414 emit_insn (gen_movhi_bigend (operands[0], 4415 operands[1])); 4416 DONE; 4417 } 4418 } 4419 } 4420 } 4421 } 4422 /* Handle loading a large integer during reload. */ 4423 else if (GET_CODE (operands[1]) == CONST_INT 4424 && !const_ok_for_arm (INTVAL (operands[1])) 4425 && !const_ok_for_arm (~INTVAL (operands[1]))) 4426 { 4427 /* Writing a constant to memory needs a scratch, which should 4428 be handled with SECONDARY_RELOADs. */ 4429 if (GET_CODE (operands[0]) != REG) 4430 abort (); 4431 4432 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0); 4433 emit_insn (gen_movsi (operands[0], operands[1])); 4434 DONE; 4435 } 4436 } 4437 else /* TARGET_THUMB */ 4438 { 4439 if (!no_new_pseudos) 4440 { 4441 if (GET_CODE (operands[0]) != REG) 4442 operands[1] = force_reg (HImode, operands[1]); 4443 4444 /* ??? We shouldn't really get invalid addresses here, but this can 4445 happen if we are passed a SP (never OK for HImode/QImode) or 4446 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 4447 HImode/QImode) relative address. */ 4448 /* ??? This should perhaps be fixed elsewhere, for instance, in 4449 fixup_stack_1, by checking for other kinds of invalid addresses, 4450 e.g. a bare reference to a virtual register. This may confuse the 4451 alpha though, which must handle this case differently. */ 4452 if (GET_CODE (operands[0]) == MEM 4453 && !memory_address_p (GET_MODE (operands[0]), 4454 XEXP (operands[0], 0))) 4455 operands[0] 4456 = replace_equiv_address (operands[0], 4457 copy_to_reg (XEXP (operands[0], 0))); 4458 4459 if (GET_CODE (operands[1]) == MEM 4460 && !memory_address_p (GET_MODE (operands[1]), 4461 XEXP (operands[1], 0))) 4462 operands[1] 4463 = replace_equiv_address (operands[1], 4464 copy_to_reg (XEXP (operands[1], 0))); 4465 } 4466 /* Handle loading a large integer during reload. */ 4467 else if (GET_CODE (operands[1]) == CONST_INT 4468 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I')) 4469 { 4470 /* Writing a constant to memory needs a scratch, which should 4471 be handled with SECONDARY_RELOADs. */ 4472 if (GET_CODE (operands[0]) != REG) 4473 abort (); 4474 4475 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0); 4476 emit_insn (gen_movsi (operands[0], operands[1])); 4477 DONE; 4478 } 4479 } 4480 " 4481) 4482 4483(define_insn "*thumb_movhi_insn" 4484 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l") 4485 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))] 4486 "TARGET_THUMB 4487 && ( register_operand (operands[0], HImode) 4488 || register_operand (operands[1], HImode))" 4489 "* 4490 switch (which_alternative) 4491 { 4492 case 0: return \"add %0, %1, #0\"; 4493 case 2: return \"strh %1, %0\"; 4494 case 3: return \"mov %0, %1\"; 4495 case 4: return \"mov %0, %1\"; 4496 case 5: return \"mov %0, %1\"; 4497 default: abort (); 4498 case 1: 4499 /* The stack pointer can end up being taken as an index register. 4500 Catch this case here and deal with it. */ 4501 if (GET_CODE (XEXP (operands[1], 0)) == PLUS 4502 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG 4503 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM) 4504 { 4505 rtx ops[2]; 4506 ops[0] = operands[0]; 4507 ops[1] = XEXP (XEXP (operands[1], 0), 0); 4508 4509 output_asm_insn (\"mov %0, %1\", ops); 4510 4511 XEXP (XEXP (operands[1], 0), 0) = operands[0]; 4512 4513 } 4514 return \"ldrh %0, %1\"; 4515 }" 4516 [(set_attr "length" "2,4,2,2,2,2") 4517 (set_attr "type" "*,load,store1,*,*,*")] 4518) 4519 4520 4521(define_insn "rotated_loadsi" 4522 [(set (match_operand:SI 0 "s_register_operand" "=r") 4523 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o") 4524 (const_int 16)))] 4525 "TARGET_ARM && (!TARGET_MMU_TRAPS)" 4526 "* 4527 { 4528 rtx ops[2]; 4529 4530 ops[0] = operands[0]; 4531 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2)); 4532 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops); 4533 return \"\"; 4534 }" 4535 [(set_attr "type" "load") 4536 (set_attr "predicable" "yes")] 4537) 4538 4539(define_expand "movhi_bytes" 4540 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" ""))) 4541 (set (match_dup 3) 4542 (zero_extend:SI (match_dup 6))) 4543 (set (match_operand:SI 0 "" "") 4544 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))] 4545 "TARGET_ARM" 4546 " 4547 { 4548 rtx mem1, mem2; 4549 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); 4550 4551 mem1 = gen_rtx_MEM (QImode, addr); 4552 MEM_COPY_ATTRIBUTES (mem1, operands[1]); 4553 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1)); 4554 MEM_COPY_ATTRIBUTES (mem2, operands[1]); 4555 operands[0] = gen_lowpart (SImode, operands[0]); 4556 operands[1] = mem1; 4557 operands[2] = gen_reg_rtx (SImode); 4558 operands[3] = gen_reg_rtx (SImode); 4559 operands[6] = mem2; 4560 4561 if (BYTES_BIG_ENDIAN) 4562 { 4563 operands[4] = operands[2]; 4564 operands[5] = operands[3]; 4565 } 4566 else 4567 { 4568 operands[4] = operands[3]; 4569 operands[5] = operands[2]; 4570 } 4571 }" 4572) 4573 4574(define_expand "movhi_bigend" 4575 [(set (match_dup 2) 4576 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0) 4577 (const_int 16))) 4578 (set (match_dup 3) 4579 (ashiftrt:SI (match_dup 2) (const_int 16))) 4580 (set (match_operand:HI 0 "s_register_operand" "") 4581 (match_dup 4))] 4582 "TARGET_ARM" 4583 " 4584 operands[2] = gen_reg_rtx (SImode); 4585 operands[3] = gen_reg_rtx (SImode); 4586 operands[4] = gen_lowpart (HImode, operands[3]); 4587 " 4588) 4589 4590;; Pattern to recognize insn generated default case above 4591(define_insn "*movhi_insn_arch4" 4592 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r") 4593 (match_operand:HI 1 "general_operand" "rI,K,r,m"))] 4594 "TARGET_ARM 4595 && arm_arch4 4596 && (GET_CODE (operands[1]) != CONST_INT 4597 || const_ok_for_arm (INTVAL (operands[1])) 4598 || const_ok_for_arm (~INTVAL (operands[1])))" 4599 "@ 4600 mov%?\\t%0, %1\\t%@ movhi 4601 mvn%?\\t%0, #%B1\\t%@ movhi 4602 str%?h\\t%1, %0\\t%@ movhi 4603 ldr%?h\\t%0, %1\\t%@ movhi" 4604 [(set_attr "type" "*,*,store1,load") 4605 (set_attr "predicable" "yes") 4606 (set_attr "pool_range" "*,*,*,256") 4607 (set_attr "neg_pool_range" "*,*,*,244")] 4608) 4609 4610(define_insn "*movhi_insn_littleend" 4611 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r") 4612 (match_operand:HI 1 "general_operand" "rI,K,m"))] 4613 "TARGET_ARM 4614 && !arm_arch4 4615 && !BYTES_BIG_ENDIAN 4616 && !TARGET_MMU_TRAPS 4617 && (GET_CODE (operands[1]) != CONST_INT 4618 || const_ok_for_arm (INTVAL (operands[1])) 4619 || const_ok_for_arm (~INTVAL (operands[1])))" 4620 "@ 4621 mov%?\\t%0, %1\\t%@ movhi 4622 mvn%?\\t%0, #%B1\\t%@ movhi 4623 ldr%?\\t%0, %1\\t%@ movhi" 4624 [(set_attr "type" "*,*,load") 4625 (set_attr "predicable" "yes") 4626 (set_attr "pool_range" "4096") 4627 (set_attr "neg_pool_range" "4084")] 4628) 4629 4630(define_insn "*movhi_insn_bigend" 4631 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r") 4632 (match_operand:HI 1 "general_operand" "rI,K,m"))] 4633 "TARGET_ARM 4634 && !arm_arch4 4635 && BYTES_BIG_ENDIAN 4636 && !TARGET_MMU_TRAPS 4637 && (GET_CODE (operands[1]) != CONST_INT 4638 || const_ok_for_arm (INTVAL (operands[1])) 4639 || const_ok_for_arm (~INTVAL (operands[1])))" 4640 "@ 4641 mov%?\\t%0, %1\\t%@ movhi 4642 mvn%?\\t%0, #%B1\\t%@ movhi 4643 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16" 4644 [(set_attr "type" "*,*,load") 4645 (set_attr "predicable" "yes") 4646 (set_attr "length" "4,4,8") 4647 (set_attr "pool_range" "*,*,4092") 4648 (set_attr "neg_pool_range" "*,*,4084")] 4649) 4650 4651(define_insn "*loadhi_si_bigend" 4652 [(set (match_operand:SI 0 "s_register_operand" "=r") 4653 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0) 4654 (const_int 16)))] 4655 "TARGET_ARM 4656 && BYTES_BIG_ENDIAN 4657 && !TARGET_MMU_TRAPS" 4658 "ldr%?\\t%0, %1\\t%@ movhi_bigend" 4659 [(set_attr "type" "load") 4660 (set_attr "predicable" "yes") 4661 (set_attr "pool_range" "4096") 4662 (set_attr "neg_pool_range" "4084")] 4663) 4664 4665(define_insn "*movhi_bytes" 4666 [(set (match_operand:HI 0 "s_register_operand" "=r,r") 4667 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))] 4668 "TARGET_ARM && TARGET_MMU_TRAPS" 4669 "@ 4670 mov%?\\t%0, %1\\t%@ movhi 4671 mvn%?\\t%0, #%B1\\t%@ movhi" 4672 [(set_attr "predicable" "yes")] 4673) 4674 4675(define_insn "thumb_movhi_clobber" 4676 [(set (match_operand:HI 0 "memory_operand" "=m") 4677 (match_operand:HI 1 "register_operand" "l")) 4678 (clobber (match_operand:SI 2 "register_operand" "=&l"))] 4679 "TARGET_THUMB" 4680 "* 4681 abort ();" 4682) 4683 4684;; We use a DImode scratch because we may occasionally need an additional 4685;; temporary if the address isn't offsettable -- push_reload doesn't seem 4686;; to take any notice of the "o" constraints on reload_memory_operand operand. 4687(define_expand "reload_outhi" 4688 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o") 4689 (match_operand:HI 1 "s_register_operand" "r") 4690 (match_operand:DI 2 "s_register_operand" "=&l")])] 4691 "TARGET_EITHER" 4692 "if (TARGET_ARM) 4693 arm_reload_out_hi (operands); 4694 else 4695 thumb_reload_out_hi (operands); 4696 DONE; 4697 " 4698) 4699 4700(define_expand "reload_inhi" 4701 [(parallel [(match_operand:HI 0 "s_register_operand" "=r") 4702 (match_operand:HI 1 "arm_reload_memory_operand" "o") 4703 (match_operand:DI 2 "s_register_operand" "=&r")])] 4704 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)" 4705 " 4706 if (TARGET_ARM) 4707 arm_reload_in_hi (operands); 4708 else 4709 thumb_reload_out_hi (operands); 4710 DONE; 4711") 4712 4713(define_expand "movqi" 4714 [(set (match_operand:QI 0 "general_operand" "") 4715 (match_operand:QI 1 "general_operand" ""))] 4716 "TARGET_EITHER" 4717 " 4718 if (TARGET_ARM) 4719 { 4720 /* Everything except mem = const or mem = mem can be done easily */ 4721 4722 if (!no_new_pseudos) 4723 { 4724 if (GET_CODE (operands[1]) == CONST_INT) 4725 { 4726 rtx reg = gen_reg_rtx (SImode); 4727 4728 emit_insn (gen_movsi (reg, operands[1])); 4729 operands[1] = gen_lowpart (QImode, reg); 4730 } 4731 if (GET_CODE (operands[1]) == MEM && optimize > 0) 4732 { 4733 rtx reg = gen_reg_rtx (SImode); 4734 4735 emit_insn (gen_zero_extendqisi2 (reg, operands[1])); 4736 operands[1] = gen_lowpart (QImode, reg); 4737 } 4738 if (GET_CODE (operands[0]) == MEM) 4739 operands[1] = force_reg (QImode, operands[1]); 4740 } 4741 } 4742 else /* TARGET_THUMB */ 4743 { 4744 if (!no_new_pseudos) 4745 { 4746 if (GET_CODE (operands[0]) != REG) 4747 operands[1] = force_reg (QImode, operands[1]); 4748 4749 /* ??? We shouldn't really get invalid addresses here, but this can 4750 happen if we are passed a SP (never OK for HImode/QImode) or 4751 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 4752 HImode/QImode) relative address. */ 4753 /* ??? This should perhaps be fixed elsewhere, for instance, in 4754 fixup_stack_1, by checking for other kinds of invalid addresses, 4755 e.g. a bare reference to a virtual register. This may confuse the 4756 alpha though, which must handle this case differently. */ 4757 if (GET_CODE (operands[0]) == MEM 4758 && !memory_address_p (GET_MODE (operands[0]), 4759 XEXP (operands[0], 0))) 4760 operands[0] 4761 = replace_equiv_address (operands[0], 4762 copy_to_reg (XEXP (operands[0], 0))); 4763 if (GET_CODE (operands[1]) == MEM 4764 && !memory_address_p (GET_MODE (operands[1]), 4765 XEXP (operands[1], 0))) 4766 operands[1] 4767 = replace_equiv_address (operands[1], 4768 copy_to_reg (XEXP (operands[1], 0))); 4769 } 4770 /* Handle loading a large integer during reload. */ 4771 else if (GET_CODE (operands[1]) == CONST_INT 4772 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I')) 4773 { 4774 /* Writing a constant to memory needs a scratch, which should 4775 be handled with SECONDARY_RELOADs. */ 4776 if (GET_CODE (operands[0]) != REG) 4777 abort (); 4778 4779 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0); 4780 emit_insn (gen_movsi (operands[0], operands[1])); 4781 DONE; 4782 } 4783 } 4784 " 4785) 4786 4787 4788(define_insn "*arm_movqi_insn" 4789 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m") 4790 (match_operand:QI 1 "general_operand" "rI,K,m,r"))] 4791 "TARGET_ARM 4792 && ( register_operand (operands[0], QImode) 4793 || register_operand (operands[1], QImode))" 4794 "@ 4795 mov%?\\t%0, %1 4796 mvn%?\\t%0, #%B1 4797 ldr%?b\\t%0, %1 4798 str%?b\\t%1, %0" 4799 [(set_attr "type" "*,*,load,store1") 4800 (set_attr "predicable" "yes")] 4801) 4802 4803(define_insn "*thumb_movqi_insn" 4804 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l") 4805 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))] 4806 "TARGET_THUMB 4807 && ( register_operand (operands[0], QImode) 4808 || register_operand (operands[1], QImode))" 4809 "@ 4810 add\\t%0, %1, #0 4811 ldrb\\t%0, %1 4812 strb\\t%1, %0 4813 mov\\t%0, %1 4814 mov\\t%0, %1 4815 mov\\t%0, %1" 4816 [(set_attr "length" "2") 4817 (set_attr "type" "*,load,store1,*,*,*") 4818 (set_attr "pool_range" "*,32,*,*,*,*")] 4819) 4820 4821(define_expand "movsf" 4822 [(set (match_operand:SF 0 "general_operand" "") 4823 (match_operand:SF 1 "general_operand" ""))] 4824 "TARGET_EITHER" 4825 " 4826 if (TARGET_ARM) 4827 { 4828 if (GET_CODE (operands[0]) == MEM) 4829 operands[1] = force_reg (SFmode, operands[1]); 4830 } 4831 else /* TARGET_THUMB */ 4832 { 4833 if (!no_new_pseudos) 4834 { 4835 if (GET_CODE (operands[0]) != REG) 4836 operands[1] = force_reg (SFmode, operands[1]); 4837 } 4838 } 4839 " 4840) 4841 4842(define_split 4843 [(set (match_operand:SF 0 "nonimmediate_operand" "") 4844 (match_operand:SF 1 "immediate_operand" ""))] 4845 "TARGET_ARM 4846 && !TARGET_HARD_FLOAT 4847 && reload_completed 4848 && GET_CODE (operands[1]) == CONST_DOUBLE" 4849 [(set (match_dup 2) (match_dup 3))] 4850 " 4851 operands[2] = gen_lowpart (SImode, operands[0]); 4852 operands[3] = gen_lowpart (SImode, operands[1]); 4853 if (operands[2] == 0 || operands[3] == 0) 4854 FAIL; 4855 " 4856) 4857 4858(define_insn "*arm_movsf_soft_insn" 4859 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m") 4860 (match_operand:SF 1 "general_operand" "r,mE,r"))] 4861 "TARGET_ARM 4862 && !TARGET_CIRRUS 4863 && TARGET_SOFT_FLOAT 4864 && (GET_CODE (operands[0]) != MEM 4865 || register_operand (operands[1], SFmode))" 4866 "@ 4867 mov%?\\t%0, %1 4868 ldr%?\\t%0, %1\\t%@ float 4869 str%?\\t%1, %0\\t%@ float" 4870 [(set_attr "length" "4,4,4") 4871 (set_attr "predicable" "yes") 4872 (set_attr "type" "*,load,store1") 4873 (set_attr "pool_range" "*,4096,*") 4874 (set_attr "neg_pool_range" "*,4084,*")] 4875) 4876 4877;;; ??? This should have alternatives for constants. 4878(define_insn "*thumb_movsf_insn" 4879 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h") 4880 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))] 4881 "TARGET_THUMB 4882 && ( register_operand (operands[0], SFmode) 4883 || register_operand (operands[1], SFmode))" 4884 "@ 4885 add\\t%0, %1, #0 4886 ldmia\\t%1, {%0} 4887 stmia\\t%0, {%1} 4888 ldr\\t%0, %1 4889 str\\t%1, %0 4890 mov\\t%0, %1 4891 mov\\t%0, %1" 4892 [(set_attr "length" "2") 4893 (set_attr "type" "*,load,store1,load,store1,*,*") 4894 (set_attr "pool_range" "*,*,*,1020,*,*,*")] 4895) 4896 4897(define_expand "movdf" 4898 [(set (match_operand:DF 0 "general_operand" "") 4899 (match_operand:DF 1 "general_operand" ""))] 4900 "TARGET_EITHER" 4901 " 4902 if (TARGET_ARM) 4903 { 4904 if (GET_CODE (operands[0]) == MEM) 4905 operands[1] = force_reg (DFmode, operands[1]); 4906 } 4907 else /* TARGET_THUMB */ 4908 { 4909 if (!no_new_pseudos) 4910 { 4911 if (GET_CODE (operands[0]) != REG) 4912 operands[1] = force_reg (DFmode, operands[1]); 4913 } 4914 } 4915 " 4916) 4917 4918;; Reloading a df mode value stored in integer regs to memory can require a 4919;; scratch reg. 4920(define_expand "reload_outdf" 4921 [(match_operand:DF 0 "arm_reload_memory_operand" "=o") 4922 (match_operand:DF 1 "s_register_operand" "r") 4923 (match_operand:SI 2 "s_register_operand" "=&r")] 4924 "TARGET_ARM" 4925 " 4926 { 4927 enum rtx_code code = GET_CODE (XEXP (operands[0], 0)); 4928 4929 if (code == REG) 4930 operands[2] = XEXP (operands[0], 0); 4931 else if (code == POST_INC || code == PRE_DEC) 4932 { 4933 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); 4934 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0); 4935 emit_insn (gen_movdi (operands[0], operands[1])); 4936 DONE; 4937 } 4938 else if (code == PRE_INC) 4939 { 4940 rtx reg = XEXP (XEXP (operands[0], 0), 0); 4941 4942 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8))); 4943 operands[2] = reg; 4944 } 4945 else if (code == POST_DEC) 4946 operands[2] = XEXP (XEXP (operands[0], 0), 0); 4947 else 4948 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0), 4949 XEXP (XEXP (operands[0], 0), 1))); 4950 4951 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]), 4952 operands[1])); 4953 4954 if (code == POST_DEC) 4955 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8))); 4956 4957 DONE; 4958 }" 4959) 4960 4961(define_insn "*movdf_soft_insn" 4962 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m") 4963 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))] 4964 "TARGET_ARM && TARGET_SOFT_FLOAT 4965 && !TARGET_CIRRUS 4966 " 4967 "* return output_move_double (operands);" 4968 [(set_attr "length" "8,8,8") 4969 (set_attr "type" "*,load,store2") 4970 (set_attr "pool_range" "1020") 4971 (set_attr "neg_pool_range" "1008")] 4972) 4973 4974;;; ??? This should have alternatives for constants. 4975;;; ??? This was originally identical to the movdi_insn pattern. 4976;;; ??? The 'F' constraint looks funny, but it should always be replaced by 4977;;; thumb_reorg with a memory reference. 4978(define_insn "*thumb_movdf_insn" 4979 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r") 4980 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))] 4981 "TARGET_THUMB 4982 && ( register_operand (operands[0], DFmode) 4983 || register_operand (operands[1], DFmode))" 4984 "* 4985 switch (which_alternative) 4986 { 4987 default: 4988 case 0: 4989 if (REGNO (operands[1]) == REGNO (operands[0]) + 1) 4990 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\"; 4991 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\"; 4992 case 1: 4993 return \"ldmia\\t%1, {%0, %H0}\"; 4994 case 2: 4995 return \"stmia\\t%0, {%1, %H1}\"; 4996 case 3: 4997 return thumb_load_double_from_address (operands); 4998 case 4: 4999 operands[2] = gen_rtx (MEM, SImode, 5000 plus_constant (XEXP (operands[0], 0), 4)); 5001 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands); 5002 return \"\"; 5003 case 5: 5004 if (REGNO (operands[1]) == REGNO (operands[0]) + 1) 5005 return \"mov\\t%0, %1\;mov\\t%H0, %H1\"; 5006 return \"mov\\t%H0, %H1\;mov\\t%0, %1\"; 5007 } 5008 " 5009 [(set_attr "length" "4,2,2,6,4,4") 5010 (set_attr "type" "*,load,store2,load,store2,*") 5011 (set_attr "pool_range" "*,*,*,1020,*,*")] 5012) 5013 5014;; Vector Moves 5015(define_expand "movv2si" 5016 [(set (match_operand:V2SI 0 "nonimmediate_operand" "") 5017 (match_operand:V2SI 1 "general_operand" ""))] 5018 "TARGET_REALLY_IWMMXT" 5019{ 5020}) 5021 5022(define_expand "movv4hi" 5023 [(set (match_operand:V4HI 0 "nonimmediate_operand" "") 5024 (match_operand:V4HI 1 "general_operand" ""))] 5025 "TARGET_REALLY_IWMMXT" 5026{ 5027}) 5028 5029(define_expand "movv8qi" 5030 [(set (match_operand:V8QI 0 "nonimmediate_operand" "") 5031 (match_operand:V8QI 1 "general_operand" ""))] 5032 "TARGET_REALLY_IWMMXT" 5033{ 5034}) 5035 5036 5037;; load- and store-multiple insns 5038;; The arm can load/store any set of registers, provided that they are in 5039;; ascending order; but that is beyond GCC so stick with what it knows. 5040 5041(define_expand "load_multiple" 5042 [(match_par_dup 3 [(set (match_operand:SI 0 "" "") 5043 (match_operand:SI 1 "" "")) 5044 (use (match_operand:SI 2 "" ""))])] 5045 "TARGET_ARM" 5046 " 5047 /* Support only fixed point registers. */ 5048 if (GET_CODE (operands[2]) != CONST_INT 5049 || INTVAL (operands[2]) > 14 5050 || INTVAL (operands[2]) < 2 5051 || GET_CODE (operands[1]) != MEM 5052 || GET_CODE (operands[0]) != REG 5053 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1) 5054 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM) 5055 FAIL; 5056 5057 operands[3] 5058 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]), 5059 force_reg (SImode, XEXP (operands[1], 0)), 5060 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]), 5061 MEM_IN_STRUCT_P(operands[1]), 5062 MEM_SCALAR_P (operands[1])); 5063 " 5064) 5065 5066;; Load multiple with write-back 5067 5068(define_insn "*ldmsi_postinc4" 5069 [(match_parallel 0 "load_multiple_operation" 5070 [(set (match_operand:SI 1 "s_register_operand" "=r") 5071 (plus:SI (match_operand:SI 2 "s_register_operand" "1") 5072 (const_int 16))) 5073 (set (match_operand:SI 3 "arm_hard_register_operand" "") 5074 (mem:SI (match_dup 2))) 5075 (set (match_operand:SI 4 "arm_hard_register_operand" "") 5076 (mem:SI (plus:SI (match_dup 2) (const_int 4)))) 5077 (set (match_operand:SI 5 "arm_hard_register_operand" "") 5078 (mem:SI (plus:SI (match_dup 2) (const_int 8)))) 5079 (set (match_operand:SI 6 "arm_hard_register_operand" "") 5080 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])] 5081 "TARGET_ARM && XVECLEN (operands[0], 0) == 5" 5082 "ldm%?ia\\t%1!, {%3, %4, %5, %6}" 5083 [(set_attr "type" "load") 5084 (set_attr "predicable" "yes")] 5085) 5086 5087(define_insn "*ldmsi_postinc3" 5088 [(match_parallel 0 "load_multiple_operation" 5089 [(set (match_operand:SI 1 "s_register_operand" "=r") 5090 (plus:SI (match_operand:SI 2 "s_register_operand" "1") 5091 (const_int 12))) 5092 (set (match_operand:SI 3 "arm_hard_register_operand" "") 5093 (mem:SI (match_dup 2))) 5094 (set (match_operand:SI 4 "arm_hard_register_operand" "") 5095 (mem:SI (plus:SI (match_dup 2) (const_int 4)))) 5096 (set (match_operand:SI 5 "arm_hard_register_operand" "") 5097 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])] 5098 "TARGET_ARM && XVECLEN (operands[0], 0) == 4" 5099 "ldm%?ia\\t%1!, {%3, %4, %5}" 5100 [(set_attr "type" "load") 5101 (set_attr "predicable" "yes")] 5102) 5103 5104(define_insn "*ldmsi_postinc2" 5105 [(match_parallel 0 "load_multiple_operation" 5106 [(set (match_operand:SI 1 "s_register_operand" "=r") 5107 (plus:SI (match_operand:SI 2 "s_register_operand" "1") 5108 (const_int 8))) 5109 (set (match_operand:SI 3 "arm_hard_register_operand" "") 5110 (mem:SI (match_dup 2))) 5111 (set (match_operand:SI 4 "arm_hard_register_operand" "") 5112 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])] 5113 "TARGET_ARM && XVECLEN (operands[0], 0) == 3" 5114 "ldm%?ia\\t%1!, {%3, %4}" 5115 [(set_attr "type" "load") 5116 (set_attr "predicable" "yes")] 5117) 5118 5119;; Ordinary load multiple 5120 5121(define_insn "*ldmsi4" 5122 [(match_parallel 0 "load_multiple_operation" 5123 [(set (match_operand:SI 2 "arm_hard_register_operand" "") 5124 (mem:SI (match_operand:SI 1 "s_register_operand" "r"))) 5125 (set (match_operand:SI 3 "arm_hard_register_operand" "") 5126 (mem:SI (plus:SI (match_dup 1) (const_int 4)))) 5127 (set (match_operand:SI 4 "arm_hard_register_operand" "") 5128 (mem:SI (plus:SI (match_dup 1) (const_int 8)))) 5129 (set (match_operand:SI 5 "arm_hard_register_operand" "") 5130 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])] 5131 "TARGET_ARM && XVECLEN (operands[0], 0) == 4" 5132 "ldm%?ia\\t%1, {%2, %3, %4, %5}" 5133 [(set_attr "type" "load") 5134 (set_attr "predicable" "yes")] 5135) 5136 5137(define_insn "*ldmsi3" 5138 [(match_parallel 0 "load_multiple_operation" 5139 [(set (match_operand:SI 2 "arm_hard_register_operand" "") 5140 (mem:SI (match_operand:SI 1 "s_register_operand" "r"))) 5141 (set (match_operand:SI 3 "arm_hard_register_operand" "") 5142 (mem:SI (plus:SI (match_dup 1) (const_int 4)))) 5143 (set (match_operand:SI 4 "arm_hard_register_operand" "") 5144 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])] 5145 "TARGET_ARM && XVECLEN (operands[0], 0) == 3" 5146 "ldm%?ia\\t%1, {%2, %3, %4}" 5147 [(set_attr "type" "load") 5148 (set_attr "predicable" "yes")] 5149) 5150 5151(define_insn "*ldmsi2" 5152 [(match_parallel 0 "load_multiple_operation" 5153 [(set (match_operand:SI 2 "arm_hard_register_operand" "") 5154 (mem:SI (match_operand:SI 1 "s_register_operand" "r"))) 5155 (set (match_operand:SI 3 "arm_hard_register_operand" "") 5156 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])] 5157 "TARGET_ARM && XVECLEN (operands[0], 0) == 2" 5158 "ldm%?ia\\t%1, {%2, %3}" 5159 [(set_attr "type" "load") 5160 (set_attr "predicable" "yes")] 5161) 5162 5163(define_expand "store_multiple" 5164 [(match_par_dup 3 [(set (match_operand:SI 0 "" "") 5165 (match_operand:SI 1 "" "")) 5166 (use (match_operand:SI 2 "" ""))])] 5167 "TARGET_ARM" 5168 " 5169 /* Support only fixed point registers. */ 5170 if (GET_CODE (operands[2]) != CONST_INT 5171 || INTVAL (operands[2]) > 14 5172 || INTVAL (operands[2]) < 2 5173 || GET_CODE (operands[1]) != REG 5174 || GET_CODE (operands[0]) != MEM 5175 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1) 5176 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM) 5177 FAIL; 5178 5179 operands[3] 5180 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]), 5181 force_reg (SImode, XEXP (operands[0], 0)), 5182 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]), 5183 MEM_IN_STRUCT_P(operands[0]), 5184 MEM_SCALAR_P (operands[0])); 5185 " 5186) 5187 5188;; Store multiple with write-back 5189 5190(define_insn "*stmsi_postinc4" 5191 [(match_parallel 0 "store_multiple_operation" 5192 [(set (match_operand:SI 1 "s_register_operand" "=r") 5193 (plus:SI (match_operand:SI 2 "s_register_operand" "1") 5194 (const_int 16))) 5195 (set (mem:SI (match_dup 2)) 5196 (match_operand:SI 3 "arm_hard_register_operand" "")) 5197 (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 5198 (match_operand:SI 4 "arm_hard_register_operand" "")) 5199 (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) 5200 (match_operand:SI 5 "arm_hard_register_operand" "")) 5201 (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) 5202 (match_operand:SI 6 "arm_hard_register_operand" ""))])] 5203 "TARGET_ARM && XVECLEN (operands[0], 0) == 5" 5204 "stm%?ia\\t%1!, {%3, %4, %5, %6}" 5205 [(set_attr "predicable" "yes") 5206 (set_attr "type" "store4")] 5207) 5208 5209(define_insn "*stmsi_postinc3" 5210 [(match_parallel 0 "store_multiple_operation" 5211 [(set (match_operand:SI 1 "s_register_operand" "=r") 5212 (plus:SI (match_operand:SI 2 "s_register_operand" "1") 5213 (const_int 12))) 5214 (set (mem:SI (match_dup 2)) 5215 (match_operand:SI 3 "arm_hard_register_operand" "")) 5216 (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 5217 (match_operand:SI 4 "arm_hard_register_operand" "")) 5218 (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) 5219 (match_operand:SI 5 "arm_hard_register_operand" ""))])] 5220 "TARGET_ARM && XVECLEN (operands[0], 0) == 4" 5221 "stm%?ia\\t%1!, {%3, %4, %5}" 5222 [(set_attr "predicable" "yes") 5223 (set_attr "type" "store3")] 5224) 5225 5226(define_insn "*stmsi_postinc2" 5227 [(match_parallel 0 "store_multiple_operation" 5228 [(set (match_operand:SI 1 "s_register_operand" "=r") 5229 (plus:SI (match_operand:SI 2 "s_register_operand" "1") 5230 (const_int 8))) 5231 (set (mem:SI (match_dup 2)) 5232 (match_operand:SI 3 "arm_hard_register_operand" "")) 5233 (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 5234 (match_operand:SI 4 "arm_hard_register_operand" ""))])] 5235 "TARGET_ARM && XVECLEN (operands[0], 0) == 3" 5236 "stm%?ia\\t%1!, {%3, %4}" 5237 [(set_attr "predicable" "yes") 5238 (set_attr "type" "store2")] 5239) 5240 5241;; Ordinary store multiple 5242 5243(define_insn "*stmsi4" 5244 [(match_parallel 0 "store_multiple_operation" 5245 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r")) 5246 (match_operand:SI 2 "arm_hard_register_operand" "")) 5247 (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) 5248 (match_operand:SI 3 "arm_hard_register_operand" "")) 5249 (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) 5250 (match_operand:SI 4 "arm_hard_register_operand" "")) 5251 (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) 5252 (match_operand:SI 5 "arm_hard_register_operand" ""))])] 5253 "TARGET_ARM && XVECLEN (operands[0], 0) == 4" 5254 "stm%?ia\\t%1, {%2, %3, %4, %5}" 5255 [(set_attr "predicable" "yes") 5256 (set_attr "type" "store4")] 5257) 5258 5259(define_insn "*stmsi3" 5260 [(match_parallel 0 "store_multiple_operation" 5261 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r")) 5262 (match_operand:SI 2 "arm_hard_register_operand" "")) 5263 (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) 5264 (match_operand:SI 3 "arm_hard_register_operand" "")) 5265 (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) 5266 (match_operand:SI 4 "arm_hard_register_operand" ""))])] 5267 "TARGET_ARM && XVECLEN (operands[0], 0) == 3" 5268 "stm%?ia\\t%1, {%2, %3, %4}" 5269 [(set_attr "predicable" "yes") 5270 (set_attr "type" "store3")] 5271) 5272 5273(define_insn "*stmsi2" 5274 [(match_parallel 0 "store_multiple_operation" 5275 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r")) 5276 (match_operand:SI 2 "arm_hard_register_operand" "")) 5277 (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) 5278 (match_operand:SI 3 "arm_hard_register_operand" ""))])] 5279 "TARGET_ARM && XVECLEN (operands[0], 0) == 2" 5280 "stm%?ia\\t%1, {%2, %3}" 5281 [(set_attr "predicable" "yes") 5282 (set_attr "type" "store2")] 5283) 5284 5285;; Move a block of memory if it is word aligned and MORE than 2 words long. 5286;; We could let this apply for blocks of less than this, but it clobbers so 5287;; many registers that there is then probably a better way. 5288 5289(define_expand "movstrqi" 5290 [(match_operand:BLK 0 "general_operand" "") 5291 (match_operand:BLK 1 "general_operand" "") 5292 (match_operand:SI 2 "const_int_operand" "") 5293 (match_operand:SI 3 "const_int_operand" "")] 5294 "TARGET_EITHER" 5295 " 5296 if (TARGET_ARM) 5297 { 5298 if (arm_gen_movstrqi (operands)) 5299 DONE; 5300 FAIL; 5301 } 5302 else /* TARGET_THUMB */ 5303 { 5304 if ( INTVAL (operands[3]) != 4 5305 || INTVAL (operands[2]) > 48) 5306 FAIL; 5307 5308 thumb_expand_movstrqi (operands); 5309 DONE; 5310 } 5311 " 5312) 5313 5314;; Thumb block-move insns 5315 5316(define_insn "movmem12b" 5317 [(set (mem:SI (match_operand:SI 2 "register_operand" "0")) 5318 (mem:SI (match_operand:SI 3 "register_operand" "1"))) 5319 (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 5320 (mem:SI (plus:SI (match_dup 3) (const_int 4)))) 5321 (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) 5322 (mem:SI (plus:SI (match_dup 3) (const_int 8)))) 5323 (set (match_operand:SI 0 "register_operand" "=l") 5324 (plus:SI (match_dup 2) (const_int 12))) 5325 (set (match_operand:SI 1 "register_operand" "=l") 5326 (plus:SI (match_dup 3) (const_int 12))) 5327 (clobber (match_scratch:SI 4 "=&l")) 5328 (clobber (match_scratch:SI 5 "=&l")) 5329 (clobber (match_scratch:SI 6 "=&l"))] 5330 "TARGET_THUMB" 5331 "* return thumb_output_move_mem_multiple (3, operands);" 5332 [(set_attr "length" "4") 5333 ; This isn't entirely accurate... It loads as well, but in terms of 5334 ; scheduling the following insn it is better to consider it as a store 5335 (set_attr "type" "store3")] 5336) 5337 5338(define_insn "movmem8b" 5339 [(set (mem:SI (match_operand:SI 2 "register_operand" "0")) 5340 (mem:SI (match_operand:SI 3 "register_operand" "1"))) 5341 (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 5342 (mem:SI (plus:SI (match_dup 3) (const_int 4)))) 5343 (set (match_operand:SI 0 "register_operand" "=l") 5344 (plus:SI (match_dup 2) (const_int 8))) 5345 (set (match_operand:SI 1 "register_operand" "=l") 5346 (plus:SI (match_dup 3) (const_int 8))) 5347 (clobber (match_scratch:SI 4 "=&l")) 5348 (clobber (match_scratch:SI 5 "=&l"))] 5349 "TARGET_THUMB" 5350 "* return thumb_output_move_mem_multiple (2, operands);" 5351 [(set_attr "length" "4") 5352 ; This isn't entirely accurate... It loads as well, but in terms of 5353 ; scheduling the following insn it is better to consider it as a store 5354 (set_attr "type" "store2")] 5355) 5356 5357 5358 5359;; Compare & branch insns 5360;; The range calculations are based as follows: 5361;; For forward branches, the address calculation returns the address of 5362;; the next instruction. This is 2 beyond the branch instruction. 5363;; For backward branches, the address calculation returns the address of 5364;; the first instruction in this pattern (cmp). This is 2 before the branch 5365;; instruction for the shortest sequence, and 4 before the branch instruction 5366;; if we have to jump around an unconditional branch. 5367;; To the basic branch range the PC offset must be added (this is +4). 5368;; So for forward branches we have 5369;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4). 5370;; And for backward branches we have 5371;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4). 5372;; 5373;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048). 5374;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256). 5375 5376(define_expand "cbranchsi4" 5377 [(set (pc) (if_then_else 5378 (match_operator 0 "arm_comparison_operator" 5379 [(match_operand:SI 1 "s_register_operand" "") 5380 (match_operand:SI 2 "nonmemory_operand" "")]) 5381 (label_ref (match_operand 3 "" "")) 5382 (pc)))] 5383 "TARGET_THUMB" 5384 " 5385 if (thumb_cmpneg_operand (operands[2], SImode)) 5386 { 5387 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2], 5388 operands[3], operands[0])); 5389 DONE; 5390 } 5391 if (!thumb_cmp_operand (operands[2], SImode)) 5392 operands[2] = force_reg (SImode, operands[2]); 5393 ") 5394 5395(define_insn "*cbranchsi4_insn" 5396 [(set (pc) (if_then_else 5397 (match_operator 0 "arm_comparison_operator" 5398 [(match_operand:SI 1 "s_register_operand" "l,*h") 5399 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")]) 5400 (label_ref (match_operand 3 "" "")) 5401 (pc)))] 5402 "TARGET_THUMB" 5403 "* 5404 output_asm_insn (\"cmp\\t%1, %2\", operands); 5405 5406 switch (get_attr_length (insn)) 5407 { 5408 case 4: return \"b%d0\\t%l3\"; 5409 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 5410 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 5411 } 5412 " 5413 [(set (attr "far_jump") 5414 (if_then_else 5415 (eq_attr "length" "8") 5416 (const_string "yes") 5417 (const_string "no"))) 5418 (set (attr "length") 5419 (if_then_else 5420 (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 5421 (le (minus (match_dup 3) (pc)) (const_int 256))) 5422 (const_int 4) 5423 (if_then_else 5424 (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 5425 (le (minus (match_dup 3) (pc)) (const_int 2048))) 5426 (const_int 6) 5427 (const_int 8))))] 5428) 5429 5430(define_insn "cbranchsi4_scratch" 5431 [(set (pc) (if_then_else 5432 (match_operator 4 "arm_comparison_operator" 5433 [(match_operand:SI 1 "s_register_operand" "l,0") 5434 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")]) 5435 (label_ref (match_operand 3 "" "")) 5436 (pc))) 5437 (clobber (match_scratch:SI 0 "=l,l"))] 5438 "TARGET_THUMB" 5439 "* 5440 output_asm_insn (\"add\\t%0, %1, #%n2\", operands); 5441 5442 switch (get_attr_length (insn)) 5443 { 5444 case 4: return \"b%d4\\t%l3\"; 5445 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 5446 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 5447 } 5448 " 5449 [(set (attr "far_jump") 5450 (if_then_else 5451 (eq_attr "length" "8") 5452 (const_string "yes") 5453 (const_string "no"))) 5454 (set (attr "length") 5455 (if_then_else 5456 (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 5457 (le (minus (match_dup 3) (pc)) (const_int 256))) 5458 (const_int 4) 5459 (if_then_else 5460 (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 5461 (le (minus (match_dup 3) (pc)) (const_int 2048))) 5462 (const_int 6) 5463 (const_int 8))))] 5464) 5465(define_insn "*movsi_cbranchsi4" 5466 [(set (pc) 5467 (if_then_else 5468 (match_operator 3 "arm_comparison_operator" 5469 [(match_operand:SI 1 "s_register_operand" "0,l,l,l") 5470 (const_int 0)]) 5471 (label_ref (match_operand 2 "" "")) 5472 (pc))) 5473 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m") 5474 (match_dup 1))] 5475 "TARGET_THUMB" 5476 "*{ 5477 if (which_alternative == 0) 5478 output_asm_insn (\"cmp\t%0, #0\", operands); 5479 else if (which_alternative == 1) 5480 output_asm_insn (\"sub\t%0, %1, #0\", operands); 5481 else 5482 { 5483 output_asm_insn (\"cmp\t%1, #0\", operands); 5484 if (which_alternative == 2) 5485 output_asm_insn (\"mov\t%0, %1\", operands); 5486 else 5487 output_asm_insn (\"str\t%1, %0\", operands); 5488 } 5489 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0)) 5490 { 5491 case 4: return \"b%d3\\t%l2\"; 5492 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\"; 5493 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\"; 5494 } 5495 }" 5496 [(set (attr "far_jump") 5497 (if_then_else 5498 (ior (and (gt (symbol_ref ("which_alternative")) 5499 (const_int 1)) 5500 (eq_attr "length" "8")) 5501 (eq_attr "length" "10")) 5502 (const_string "yes") 5503 (const_string "no"))) 5504 (set (attr "length") 5505 (if_then_else 5506 (le (symbol_ref ("which_alternative")) 5507 (const_int 1)) 5508 (if_then_else 5509 (and (ge (minus (match_dup 2) (pc)) (const_int -250)) 5510 (le (minus (match_dup 2) (pc)) (const_int 256))) 5511 (const_int 4) 5512 (if_then_else 5513 (and (ge (minus (match_dup 2) (pc)) (const_int -2040)) 5514 (le (minus (match_dup 2) (pc)) (const_int 2048))) 5515 (const_int 6) 5516 (const_int 8))) 5517 (if_then_else 5518 (and (ge (minus (match_dup 2) (pc)) (const_int -248)) 5519 (le (minus (match_dup 2) (pc)) (const_int 256))) 5520 (const_int 6) 5521 (if_then_else 5522 (and (ge (minus (match_dup 2) (pc)) (const_int -2038)) 5523 (le (minus (match_dup 2) (pc)) (const_int 2048))) 5524 (const_int 8) 5525 (const_int 10)))))] 5526) 5527 5528(define_insn "*negated_cbranchsi4" 5529 [(set (pc) 5530 (if_then_else 5531 (match_operator 0 "arm_comparison_operator" 5532 [(match_operand:SI 1 "s_register_operand" "l") 5533 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))]) 5534 (label_ref (match_operand 3 "" "")) 5535 (pc)))] 5536 "TARGET_THUMB" 5537 "* 5538 output_asm_insn (\"cmn\\t%1, %2\", operands); 5539 switch (get_attr_length (insn)) 5540 { 5541 case 4: return \"b%d0\\t%l3\"; 5542 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 5543 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 5544 } 5545 " 5546 [(set (attr "far_jump") 5547 (if_then_else 5548 (eq_attr "length" "8") 5549 (const_string "yes") 5550 (const_string "no"))) 5551 (set (attr "length") 5552 (if_then_else 5553 (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 5554 (le (minus (match_dup 3) (pc)) (const_int 256))) 5555 (const_int 4) 5556 (if_then_else 5557 (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 5558 (le (minus (match_dup 3) (pc)) (const_int 2048))) 5559 (const_int 6) 5560 (const_int 8))))] 5561) 5562 5563(define_insn "*tbit_cbranch" 5564 [(set (pc) 5565 (if_then_else 5566 (match_operator 0 "equality_operator" 5567 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l") 5568 (const_int 1) 5569 (match_operand:SI 2 "const_int_operand" "i")) 5570 (const_int 0)]) 5571 (label_ref (match_operand 3 "" "")) 5572 (pc))) 5573 (clobber (match_scratch:SI 4 "=l"))] 5574 "TARGET_THUMB" 5575 "* 5576 { 5577 rtx op[3]; 5578 op[0] = operands[4]; 5579 op[1] = operands[1]; 5580 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2])); 5581 5582 output_asm_insn (\"lsl\\t%0, %1, %2\", op); 5583 switch (get_attr_length (insn)) 5584 { 5585 case 4: return \"b%d0\\t%l3\"; 5586 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 5587 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 5588 } 5589 }" 5590 [(set (attr "far_jump") 5591 (if_then_else 5592 (eq_attr "length" "8") 5593 (const_string "yes") 5594 (const_string "no"))) 5595 (set (attr "length") 5596 (if_then_else 5597 (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 5598 (le (minus (match_dup 3) (pc)) (const_int 256))) 5599 (const_int 4) 5600 (if_then_else 5601 (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 5602 (le (minus (match_dup 3) (pc)) (const_int 2048))) 5603 (const_int 6) 5604 (const_int 8))))] 5605) 5606 5607(define_insn "*tstsi3_cbranch" 5608 [(set (pc) 5609 (if_then_else 5610 (match_operator 3 "equality_operator" 5611 [(and:SI (match_operand:SI 0 "s_register_operand" "%l") 5612 (match_operand:SI 1 "s_register_operand" "l")) 5613 (const_int 0)]) 5614 (label_ref (match_operand 2 "" "")) 5615 (pc)))] 5616 "TARGET_THUMB" 5617 "* 5618 { 5619 output_asm_insn (\"tst\\t%0, %1\", operands); 5620 switch (get_attr_length (insn)) 5621 { 5622 case 4: return \"b%d3\\t%l2\"; 5623 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\"; 5624 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\"; 5625 } 5626 }" 5627 [(set (attr "far_jump") 5628 (if_then_else 5629 (eq_attr "length" "8") 5630 (const_string "yes") 5631 (const_string "no"))) 5632 (set (attr "length") 5633 (if_then_else 5634 (and (ge (minus (match_dup 2) (pc)) (const_int -250)) 5635 (le (minus (match_dup 2) (pc)) (const_int 256))) 5636 (const_int 4) 5637 (if_then_else 5638 (and (ge (minus (match_dup 2) (pc)) (const_int -2040)) 5639 (le (minus (match_dup 2) (pc)) (const_int 2048))) 5640 (const_int 6) 5641 (const_int 8))))] 5642) 5643 5644(define_insn "*andsi3_cbranch" 5645 [(set (pc) 5646 (if_then_else 5647 (match_operator 5 "equality_operator" 5648 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1") 5649 (match_operand:SI 3 "s_register_operand" "l,l,l,l")) 5650 (const_int 0)]) 5651 (label_ref (match_operand 4 "" "")) 5652 (pc))) 5653 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") 5654 (and:SI (match_dup 2) (match_dup 3))) 5655 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] 5656 "TARGET_THUMB" 5657 "* 5658 { 5659 if (which_alternative == 0) 5660 output_asm_insn (\"and\\t%0, %3\", operands); 5661 else if (which_alternative == 1) 5662 { 5663 output_asm_insn (\"and\\t%1, %3\", operands); 5664 output_asm_insn (\"mov\\t%0, %1\", operands); 5665 } 5666 else 5667 { 5668 output_asm_insn (\"and\\t%1, %3\", operands); 5669 output_asm_insn (\"str\\t%1, %0\", operands); 5670 } 5671 5672 switch (get_attr_length (insn) - (which_alternative ? 2 : 0)) 5673 { 5674 case 4: return \"b%d5\\t%l4\"; 5675 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\"; 5676 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\"; 5677 } 5678 }" 5679 [(set (attr "far_jump") 5680 (if_then_else 5681 (ior (and (eq (symbol_ref ("which_alternative")) 5682 (const_int 0)) 5683 (eq_attr "length" "8")) 5684 (eq_attr "length" "10")) 5685 (const_string "yes") 5686 (const_string "no"))) 5687 (set (attr "length") 5688 (if_then_else 5689 (eq (symbol_ref ("which_alternative")) 5690 (const_int 0)) 5691 (if_then_else 5692 (and (ge (minus (match_dup 4) (pc)) (const_int -250)) 5693 (le (minus (match_dup 4) (pc)) (const_int 256))) 5694 (const_int 4) 5695 (if_then_else 5696 (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) 5697 (le (minus (match_dup 4) (pc)) (const_int 2048))) 5698 (const_int 6) 5699 (const_int 8))) 5700 (if_then_else 5701 (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 5702 (le (minus (match_dup 4) (pc)) (const_int 256))) 5703 (const_int 6) 5704 (if_then_else 5705 (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 5706 (le (minus (match_dup 4) (pc)) (const_int 2048))) 5707 (const_int 8) 5708 (const_int 10)))))] 5709) 5710 5711(define_insn "*orrsi3_cbranch_scratch" 5712 [(set (pc) 5713 (if_then_else 5714 (match_operator 4 "equality_operator" 5715 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0") 5716 (match_operand:SI 2 "s_register_operand" "l")) 5717 (const_int 0)]) 5718 (label_ref (match_operand 3 "" "")) 5719 (pc))) 5720 (clobber (match_scratch:SI 0 "=l"))] 5721 "TARGET_THUMB" 5722 "* 5723 { 5724 output_asm_insn (\"orr\\t%0, %2\", operands); 5725 switch (get_attr_length (insn)) 5726 { 5727 case 4: return \"b%d4\\t%l3\"; 5728 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 5729 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 5730 } 5731 }" 5732 [(set (attr "far_jump") 5733 (if_then_else 5734 (eq_attr "length" "8") 5735 (const_string "yes") 5736 (const_string "no"))) 5737 (set (attr "length") 5738 (if_then_else 5739 (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 5740 (le (minus (match_dup 3) (pc)) (const_int 256))) 5741 (const_int 4) 5742 (if_then_else 5743 (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 5744 (le (minus (match_dup 3) (pc)) (const_int 2048))) 5745 (const_int 6) 5746 (const_int 8))))] 5747) 5748 5749(define_insn "*orrsi3_cbranch" 5750 [(set (pc) 5751 (if_then_else 5752 (match_operator 5 "equality_operator" 5753 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1") 5754 (match_operand:SI 3 "s_register_operand" "l,l,l,l")) 5755 (const_int 0)]) 5756 (label_ref (match_operand 4 "" "")) 5757 (pc))) 5758 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") 5759 (ior:SI (match_dup 2) (match_dup 3))) 5760 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] 5761 "TARGET_THUMB" 5762 "* 5763 { 5764 if (which_alternative == 0) 5765 output_asm_insn (\"orr\\t%0, %3\", operands); 5766 else if (which_alternative == 1) 5767 { 5768 output_asm_insn (\"orr\\t%1, %3\", operands); 5769 output_asm_insn (\"mov\\t%0, %1\", operands); 5770 } 5771 else 5772 { 5773 output_asm_insn (\"orr\\t%1, %3\", operands); 5774 output_asm_insn (\"str\\t%1, %0\", operands); 5775 } 5776 5777 switch (get_attr_length (insn) - (which_alternative ? 2 : 0)) 5778 { 5779 case 4: return \"b%d5\\t%l4\"; 5780 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\"; 5781 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\"; 5782 } 5783 }" 5784 [(set (attr "far_jump") 5785 (if_then_else 5786 (ior (and (eq (symbol_ref ("which_alternative")) 5787 (const_int 0)) 5788 (eq_attr "length" "8")) 5789 (eq_attr "length" "10")) 5790 (const_string "yes") 5791 (const_string "no"))) 5792 (set (attr "length") 5793 (if_then_else 5794 (eq (symbol_ref ("which_alternative")) 5795 (const_int 0)) 5796 (if_then_else 5797 (and (ge (minus (match_dup 4) (pc)) (const_int -250)) 5798 (le (minus (match_dup 4) (pc)) (const_int 256))) 5799 (const_int 4) 5800 (if_then_else 5801 (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) 5802 (le (minus (match_dup 4) (pc)) (const_int 2048))) 5803 (const_int 6) 5804 (const_int 8))) 5805 (if_then_else 5806 (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 5807 (le (minus (match_dup 4) (pc)) (const_int 256))) 5808 (const_int 6) 5809 (if_then_else 5810 (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 5811 (le (minus (match_dup 4) (pc)) (const_int 2048))) 5812 (const_int 8) 5813 (const_int 10)))))] 5814) 5815 5816(define_insn "*xorsi3_cbranch_scratch" 5817 [(set (pc) 5818 (if_then_else 5819 (match_operator 4 "equality_operator" 5820 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0") 5821 (match_operand:SI 2 "s_register_operand" "l")) 5822 (const_int 0)]) 5823 (label_ref (match_operand 3 "" "")) 5824 (pc))) 5825 (clobber (match_scratch:SI 0 "=l"))] 5826 "TARGET_THUMB" 5827 "* 5828 { 5829 output_asm_insn (\"eor\\t%0, %2\", operands); 5830 switch (get_attr_length (insn)) 5831 { 5832 case 4: return \"b%d4\\t%l3\"; 5833 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 5834 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 5835 } 5836 }" 5837 [(set (attr "far_jump") 5838 (if_then_else 5839 (eq_attr "length" "8") 5840 (const_string "yes") 5841 (const_string "no"))) 5842 (set (attr "length") 5843 (if_then_else 5844 (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 5845 (le (minus (match_dup 3) (pc)) (const_int 256))) 5846 (const_int 4) 5847 (if_then_else 5848 (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 5849 (le (minus (match_dup 3) (pc)) (const_int 2048))) 5850 (const_int 6) 5851 (const_int 8))))] 5852) 5853 5854(define_insn "*xorsi3_cbranch" 5855 [(set (pc) 5856 (if_then_else 5857 (match_operator 5 "equality_operator" 5858 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1") 5859 (match_operand:SI 3 "s_register_operand" "l,l,l,l")) 5860 (const_int 0)]) 5861 (label_ref (match_operand 4 "" "")) 5862 (pc))) 5863 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") 5864 (xor:SI (match_dup 2) (match_dup 3))) 5865 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] 5866 "TARGET_THUMB" 5867 "* 5868 { 5869 if (which_alternative == 0) 5870 output_asm_insn (\"eor\\t%0, %3\", operands); 5871 else if (which_alternative == 1) 5872 { 5873 output_asm_insn (\"eor\\t%1, %3\", operands); 5874 output_asm_insn (\"mov\\t%0, %1\", operands); 5875 } 5876 else 5877 { 5878 output_asm_insn (\"eor\\t%1, %3\", operands); 5879 output_asm_insn (\"str\\t%1, %0\", operands); 5880 } 5881 5882 switch (get_attr_length (insn) - (which_alternative ? 2 : 0)) 5883 { 5884 case 4: return \"b%d5\\t%l4\"; 5885 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\"; 5886 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\"; 5887 } 5888 }" 5889 [(set (attr "far_jump") 5890 (if_then_else 5891 (ior (and (eq (symbol_ref ("which_alternative")) 5892 (const_int 0)) 5893 (eq_attr "length" "8")) 5894 (eq_attr "length" "10")) 5895 (const_string "yes") 5896 (const_string "no"))) 5897 (set (attr "length") 5898 (if_then_else 5899 (eq (symbol_ref ("which_alternative")) 5900 (const_int 0)) 5901 (if_then_else 5902 (and (ge (minus (match_dup 4) (pc)) (const_int -250)) 5903 (le (minus (match_dup 4) (pc)) (const_int 256))) 5904 (const_int 4) 5905 (if_then_else 5906 (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) 5907 (le (minus (match_dup 4) (pc)) (const_int 2048))) 5908 (const_int 6) 5909 (const_int 8))) 5910 (if_then_else 5911 (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 5912 (le (minus (match_dup 4) (pc)) (const_int 256))) 5913 (const_int 6) 5914 (if_then_else 5915 (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 5916 (le (minus (match_dup 4) (pc)) (const_int 2048))) 5917 (const_int 8) 5918 (const_int 10)))))] 5919) 5920 5921(define_insn "*bicsi3_cbranch_scratch" 5922 [(set (pc) 5923 (if_then_else 5924 (match_operator 4 "equality_operator" 5925 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l")) 5926 (match_operand:SI 1 "s_register_operand" "0")) 5927 (const_int 0)]) 5928 (label_ref (match_operand 3 "" "")) 5929 (pc))) 5930 (clobber (match_scratch:SI 0 "=l"))] 5931 "TARGET_THUMB" 5932 "* 5933 { 5934 output_asm_insn (\"bic\\t%0, %2\", operands); 5935 switch (get_attr_length (insn)) 5936 { 5937 case 4: return \"b%d4\\t%l3\"; 5938 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 5939 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 5940 } 5941 }" 5942 [(set (attr "far_jump") 5943 (if_then_else 5944 (eq_attr "length" "8") 5945 (const_string "yes") 5946 (const_string "no"))) 5947 (set (attr "length") 5948 (if_then_else 5949 (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 5950 (le (minus (match_dup 3) (pc)) (const_int 256))) 5951 (const_int 4) 5952 (if_then_else 5953 (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 5954 (le (minus (match_dup 3) (pc)) (const_int 2048))) 5955 (const_int 6) 5956 (const_int 8))))] 5957) 5958 5959(define_insn "*bicsi3_cbranch" 5960 [(set (pc) 5961 (if_then_else 5962 (match_operator 5 "equality_operator" 5963 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l")) 5964 (match_operand:SI 2 "s_register_operand" "0,1,1,1")) 5965 (const_int 0)]) 5966 (label_ref (match_operand 4 "" "")) 5967 (pc))) 5968 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") 5969 (and:SI (not:SI (match_dup 3)) (match_dup 2))) 5970 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] 5971 "TARGET_THUMB" 5972 "* 5973 { 5974 if (which_alternative == 0) 5975 output_asm_insn (\"bic\\t%0, %3\", operands); 5976 else if (which_alternative == 1) 5977 { 5978 output_asm_insn (\"bic\\t%1, %3\", operands); 5979 output_asm_insn (\"mov\\t%0, %1\", operands); 5980 } 5981 else 5982 { 5983 output_asm_insn (\"bic\\t%1, %3\", operands); 5984 output_asm_insn (\"str\\t%1, %0\", operands); 5985 } 5986 5987 switch (get_attr_length (insn) - (which_alternative ? 2 : 0)) 5988 { 5989 case 4: return \"b%d5\\t%l4\"; 5990 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\"; 5991 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\"; 5992 } 5993 }" 5994 [(set (attr "far_jump") 5995 (if_then_else 5996 (ior (and (eq (symbol_ref ("which_alternative")) 5997 (const_int 0)) 5998 (eq_attr "length" "8")) 5999 (eq_attr "length" "10")) 6000 (const_string "yes") 6001 (const_string "no"))) 6002 (set (attr "length") 6003 (if_then_else 6004 (eq (symbol_ref ("which_alternative")) 6005 (const_int 0)) 6006 (if_then_else 6007 (and (ge (minus (match_dup 4) (pc)) (const_int -250)) 6008 (le (minus (match_dup 4) (pc)) (const_int 256))) 6009 (const_int 4) 6010 (if_then_else 6011 (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) 6012 (le (minus (match_dup 4) (pc)) (const_int 2048))) 6013 (const_int 6) 6014 (const_int 8))) 6015 (if_then_else 6016 (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 6017 (le (minus (match_dup 4) (pc)) (const_int 256))) 6018 (const_int 6) 6019 (if_then_else 6020 (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 6021 (le (minus (match_dup 4) (pc)) (const_int 2048))) 6022 (const_int 8) 6023 (const_int 10)))))] 6024) 6025 6026(define_insn "*cbranchne_decr1" 6027 [(set (pc) 6028 (if_then_else (match_operator 3 "equality_operator" 6029 [(match_operand:SI 2 "s_register_operand" "l,l,1,l") 6030 (const_int 0)]) 6031 (label_ref (match_operand 4 "" "")) 6032 (pc))) 6033 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") 6034 (plus:SI (match_dup 2) (const_int -1))) 6035 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] 6036 "TARGET_THUMB" 6037 "* 6038 { 6039 rtx cond[2]; 6040 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE 6041 ? GEU : LTU), 6042 VOIDmode, operands[2], const1_rtx); 6043 cond[1] = operands[4]; 6044 6045 if (which_alternative == 0) 6046 output_asm_insn (\"sub\\t%0, %2, #1\", operands); 6047 else if (which_alternative == 1) 6048 { 6049 /* We must provide an alternative for a hi reg because reload 6050 cannot handle output reloads on a jump instruction, but we 6051 can't subtract into that. Fortunately a mov from lo to hi 6052 does not clobber the condition codes. */ 6053 output_asm_insn (\"sub\\t%1, %2, #1\", operands); 6054 output_asm_insn (\"mov\\t%0, %1\", operands); 6055 } 6056 else 6057 { 6058 /* Similarly, but the target is memory. */ 6059 output_asm_insn (\"sub\\t%1, %2, #1\", operands); 6060 output_asm_insn (\"str\\t%1, %0\", operands); 6061 } 6062 6063 switch (get_attr_length (insn) - (which_alternative ? 2 : 0)) 6064 { 6065 case 4: 6066 output_asm_insn (\"b%d0\\t%l1\", cond); 6067 return \"\"; 6068 case 6: 6069 output_asm_insn (\"b%D0\\t.LCB%=\", cond); 6070 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\"; 6071 default: 6072 output_asm_insn (\"b%D0\\t.LCB%=\", cond); 6073 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\"; 6074 } 6075 } 6076 " 6077 [(set (attr "far_jump") 6078 (if_then_else 6079 (ior (and (eq (symbol_ref ("which_alternative")) 6080 (const_int 0)) 6081 (eq_attr "length" "8")) 6082 (eq_attr "length" "10")) 6083 (const_string "yes") 6084 (const_string "no"))) 6085 (set_attr_alternative "length" 6086 [ 6087 ;; Alternative 0 6088 (if_then_else 6089 (and (ge (minus (match_dup 4) (pc)) (const_int -250)) 6090 (le (minus (match_dup 4) (pc)) (const_int 256))) 6091 (const_int 4) 6092 (if_then_else 6093 (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) 6094 (le (minus (match_dup 4) (pc)) (const_int 2048))) 6095 (const_int 6) 6096 (const_int 8))) 6097 ;; Alternative 1 6098 (if_then_else 6099 (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 6100 (le (minus (match_dup 4) (pc)) (const_int 256))) 6101 (const_int 6) 6102 (if_then_else 6103 (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 6104 (le (minus (match_dup 4) (pc)) (const_int 2048))) 6105 (const_int 8) 6106 (const_int 10))) 6107 ;; Alternative 2 6108 (if_then_else 6109 (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 6110 (le (minus (match_dup 4) (pc)) (const_int 256))) 6111 (const_int 6) 6112 (if_then_else 6113 (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 6114 (le (minus (match_dup 4) (pc)) (const_int 2048))) 6115 (const_int 8) 6116 (const_int 10))) 6117 ;; Alternative 3 6118 (if_then_else 6119 (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 6120 (le (minus (match_dup 4) (pc)) (const_int 256))) 6121 (const_int 6) 6122 (if_then_else 6123 (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 6124 (le (minus (match_dup 4) (pc)) (const_int 2048))) 6125 (const_int 8) 6126 (const_int 10)))])] 6127) 6128 6129(define_insn "*addsi3_cbranch" 6130 [(set (pc) 6131 (if_then_else 6132 (match_operator 4 "comparison_operator" 6133 [(plus:SI 6134 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1") 6135 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ")) 6136 (const_int 0)]) 6137 (label_ref (match_operand 5 "" "")) 6138 (pc))) 6139 (set 6140 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m") 6141 (plus:SI (match_dup 2) (match_dup 3))) 6142 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))] 6143 "TARGET_THUMB 6144 && (GET_CODE (operands[4]) == EQ 6145 || GET_CODE (operands[4]) == NE 6146 || GET_CODE (operands[4]) == GE 6147 || GET_CODE (operands[4]) == LT)" 6148 "* 6149 { 6150 rtx cond[3]; 6151 6152 6153 cond[0] = (which_alternative < 3) ? operands[0] : operands[1]; 6154 cond[1] = operands[2]; 6155 cond[2] = operands[3]; 6156 6157 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0) 6158 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond); 6159 else 6160 output_asm_insn (\"add\\t%0, %1, %2\", cond); 6161 6162 if (which_alternative >= 3 6163 && which_alternative < 4) 6164 output_asm_insn (\"mov\\t%0, %1\", operands); 6165 else if (which_alternative >= 4) 6166 output_asm_insn (\"str\\t%1, %0\", operands); 6167 6168 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0)) 6169 { 6170 case 4: 6171 return \"b%d4\\t%l5\"; 6172 case 6: 6173 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\"; 6174 default: 6175 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\"; 6176 } 6177 } 6178 " 6179 [(set (attr "far_jump") 6180 (if_then_else 6181 (ior (and (lt (symbol_ref ("which_alternative")) 6182 (const_int 3)) 6183 (eq_attr "length" "8")) 6184 (eq_attr "length" "10")) 6185 (const_string "yes") 6186 (const_string "no"))) 6187 (set (attr "length") 6188 (if_then_else 6189 (lt (symbol_ref ("which_alternative")) 6190 (const_int 3)) 6191 (if_then_else 6192 (and (ge (minus (match_dup 5) (pc)) (const_int -250)) 6193 (le (minus (match_dup 5) (pc)) (const_int 256))) 6194 (const_int 4) 6195 (if_then_else 6196 (and (ge (minus (match_dup 5) (pc)) (const_int -2040)) 6197 (le (minus (match_dup 5) (pc)) (const_int 2048))) 6198 (const_int 6) 6199 (const_int 8))) 6200 (if_then_else 6201 (and (ge (minus (match_dup 5) (pc)) (const_int -248)) 6202 (le (minus (match_dup 5) (pc)) (const_int 256))) 6203 (const_int 6) 6204 (if_then_else 6205 (and (ge (minus (match_dup 5) (pc)) (const_int -2038)) 6206 (le (minus (match_dup 5) (pc)) (const_int 2048))) 6207 (const_int 8) 6208 (const_int 10)))))] 6209) 6210 6211(define_insn "*addsi3_cbranch_scratch" 6212 [(set (pc) 6213 (if_then_else 6214 (match_operator 3 "comparison_operator" 6215 [(plus:SI 6216 (match_operand:SI 1 "s_register_operand" "%l,l,l,0") 6217 (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L")) 6218 (const_int 0)]) 6219 (label_ref (match_operand 4 "" "")) 6220 (pc))) 6221 (clobber (match_scratch:SI 0 "=X,X,l,l"))] 6222 "TARGET_THUMB 6223 && (GET_CODE (operands[3]) == EQ 6224 || GET_CODE (operands[3]) == NE 6225 || GET_CODE (operands[3]) == GE 6226 || GET_CODE (operands[3]) == LT)" 6227 "* 6228 { 6229 switch (which_alternative) 6230 { 6231 case 0: 6232 output_asm_insn (\"cmp\t%1, #%n2\", operands); 6233 break; 6234 case 1: 6235 output_asm_insn (\"cmn\t%1, %2\", operands); 6236 break; 6237 case 3: 6238 output_asm_insn (\"add\t%0, %1, %2\", operands); 6239 break; 6240 case 4: 6241 output_asm_insn (\"add\t%0, %0, %2\", operands); 6242 break; 6243 } 6244 6245 switch (get_attr_length (insn)) 6246 { 6247 case 4: 6248 return \"b%d3\\t%l4\"; 6249 case 6: 6250 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\"; 6251 default: 6252 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\"; 6253 } 6254 } 6255 " 6256 [(set (attr "far_jump") 6257 (if_then_else 6258 (eq_attr "length" "8") 6259 (const_string "yes") 6260 (const_string "no"))) 6261 (set (attr "length") 6262 (if_then_else 6263 (and (ge (minus (match_dup 4) (pc)) (const_int -250)) 6264 (le (minus (match_dup 4) (pc)) (const_int 256))) 6265 (const_int 4) 6266 (if_then_else 6267 (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) 6268 (le (minus (match_dup 4) (pc)) (const_int 2048))) 6269 (const_int 6) 6270 (const_int 8))))] 6271) 6272 6273(define_insn "*subsi3_cbranch" 6274 [(set (pc) 6275 (if_then_else 6276 (match_operator 4 "comparison_operator" 6277 [(minus:SI 6278 (match_operand:SI 2 "s_register_operand" "l,l,1,l") 6279 (match_operand:SI 3 "s_register_operand" "l,l,l,l")) 6280 (const_int 0)]) 6281 (label_ref (match_operand 5 "" "")) 6282 (pc))) 6283 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") 6284 (minus:SI (match_dup 2) (match_dup 3))) 6285 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] 6286 "TARGET_THUMB 6287 && (GET_CODE (operands[4]) == EQ 6288 || GET_CODE (operands[4]) == NE 6289 || GET_CODE (operands[4]) == GE 6290 || GET_CODE (operands[4]) == LT)" 6291 "* 6292 { 6293 if (which_alternative == 0) 6294 output_asm_insn (\"sub\\t%0, %2, %3\", operands); 6295 else if (which_alternative == 1) 6296 { 6297 /* We must provide an alternative for a hi reg because reload 6298 cannot handle output reloads on a jump instruction, but we 6299 can't subtract into that. Fortunately a mov from lo to hi 6300 does not clobber the condition codes. */ 6301 output_asm_insn (\"sub\\t%1, %2, %3\", operands); 6302 output_asm_insn (\"mov\\t%0, %1\", operands); 6303 } 6304 else 6305 { 6306 /* Similarly, but the target is memory. */ 6307 output_asm_insn (\"sub\\t%1, %2, %3\", operands); 6308 output_asm_insn (\"str\\t%1, %0\", operands); 6309 } 6310 6311 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0)) 6312 { 6313 case 4: 6314 return \"b%d4\\t%l5\"; 6315 case 6: 6316 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\"; 6317 default: 6318 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\"; 6319 } 6320 } 6321 " 6322 [(set (attr "far_jump") 6323 (if_then_else 6324 (ior (and (eq (symbol_ref ("which_alternative")) 6325 (const_int 0)) 6326 (eq_attr "length" "8")) 6327 (eq_attr "length" "10")) 6328 (const_string "yes") 6329 (const_string "no"))) 6330 (set (attr "length") 6331 (if_then_else 6332 (eq (symbol_ref ("which_alternative")) 6333 (const_int 0)) 6334 (if_then_else 6335 (and (ge (minus (match_dup 5) (pc)) (const_int -250)) 6336 (le (minus (match_dup 5) (pc)) (const_int 256))) 6337 (const_int 4) 6338 (if_then_else 6339 (and (ge (minus (match_dup 5) (pc)) (const_int -2040)) 6340 (le (minus (match_dup 5) (pc)) (const_int 2048))) 6341 (const_int 6) 6342 (const_int 8))) 6343 (if_then_else 6344 (and (ge (minus (match_dup 5) (pc)) (const_int -248)) 6345 (le (minus (match_dup 5) (pc)) (const_int 256))) 6346 (const_int 6) 6347 (if_then_else 6348 (and (ge (minus (match_dup 5) (pc)) (const_int -2038)) 6349 (le (minus (match_dup 5) (pc)) (const_int 2048))) 6350 (const_int 8) 6351 (const_int 10)))))] 6352) 6353 6354(define_insn "*subsi3_cbranch_scratch" 6355 [(set (pc) 6356 (if_then_else 6357 (match_operator 0 "arm_comparison_operator" 6358 [(minus:SI (match_operand:SI 1 "register_operand" "l") 6359 (match_operand:SI 2 "nonmemory_operand" "l")) 6360 (const_int 0)]) 6361 (label_ref (match_operand 3 "" "")) 6362 (pc)))] 6363 "TARGET_THUMB 6364 && (GET_CODE (operands[0]) == EQ 6365 || GET_CODE (operands[0]) == NE 6366 || GET_CODE (operands[0]) == GE 6367 || GET_CODE (operands[0]) == LT)" 6368 "* 6369 output_asm_insn (\"cmp\\t%1, %2\", operands); 6370 switch (get_attr_length (insn)) 6371 { 6372 case 4: return \"b%d0\\t%l3\"; 6373 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 6374 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 6375 } 6376 " 6377 [(set (attr "far_jump") 6378 (if_then_else 6379 (eq_attr "length" "8") 6380 (const_string "yes") 6381 (const_string "no"))) 6382 (set (attr "length") 6383 (if_then_else 6384 (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 6385 (le (minus (match_dup 3) (pc)) (const_int 256))) 6386 (const_int 4) 6387 (if_then_else 6388 (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 6389 (le (minus (match_dup 3) (pc)) (const_int 2048))) 6390 (const_int 6) 6391 (const_int 8))))] 6392) 6393 6394;; Comparison and test insns 6395 6396(define_expand "cmpsi" 6397 [(match_operand:SI 0 "s_register_operand" "") 6398 (match_operand:SI 1 "arm_add_operand" "")] 6399 "TARGET_ARM" 6400 "{ 6401 arm_compare_op0 = operands[0]; 6402 arm_compare_op1 = operands[1]; 6403 DONE; 6404 }" 6405) 6406 6407(define_expand "cmpsf" 6408 [(match_operand:SF 0 "s_register_operand" "") 6409 (match_operand:SF 1 "fpa_rhs_operand" "")] 6410 "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 6411 " 6412 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode)) 6413 operands[1] = force_reg (SFmode, operands[1]); 6414 6415 arm_compare_op0 = operands[0]; 6416 arm_compare_op1 = operands[1]; 6417 DONE; 6418 " 6419) 6420 6421(define_expand "cmpdf" 6422 [(match_operand:DF 0 "s_register_operand" "") 6423 (match_operand:DF 1 "fpa_rhs_operand" "")] 6424 "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 6425 " 6426 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode)) 6427 operands[1] = force_reg (DFmode, operands[1]); 6428 6429 arm_compare_op0 = operands[0]; 6430 arm_compare_op1 = operands[1]; 6431 DONE; 6432 " 6433) 6434 6435(define_insn "*arm_cmpsi_insn" 6436 [(set (reg:CC CC_REGNUM) 6437 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r") 6438 (match_operand:SI 1 "arm_add_operand" "rI,L")))] 6439 "TARGET_ARM" 6440 "@ 6441 cmp%?\\t%0, %1 6442 cmn%?\\t%0, #%n1" 6443 [(set_attr "conds" "set")] 6444) 6445 6446(define_insn "*cmpsi_shiftsi" 6447 [(set (reg:CC CC_REGNUM) 6448 (compare:CC (match_operand:SI 0 "s_register_operand" "r") 6449 (match_operator:SI 3 "shift_operator" 6450 [(match_operand:SI 1 "s_register_operand" "r") 6451 (match_operand:SI 2 "arm_rhs_operand" "rM")])))] 6452 "TARGET_ARM" 6453 "cmp%?\\t%0, %1%S3" 6454 [(set_attr "conds" "set") 6455 (set_attr "shift" "1") 6456 ] 6457) 6458 6459(define_insn "*cmpsi_shiftsi_swp" 6460 [(set (reg:CC_SWP CC_REGNUM) 6461 (compare:CC_SWP (match_operator:SI 3 "shift_operator" 6462 [(match_operand:SI 1 "s_register_operand" "r") 6463 (match_operand:SI 2 "reg_or_int_operand" "rM")]) 6464 (match_operand:SI 0 "s_register_operand" "r")))] 6465 "TARGET_ARM" 6466 "cmp%?\\t%0, %1%S3" 6467 [(set_attr "conds" "set") 6468 (set_attr "shift" "1") 6469 ] 6470) 6471 6472(define_insn "*cmpsi_neg_shiftsi" 6473 [(set (reg:CC CC_REGNUM) 6474 (compare:CC (match_operand:SI 0 "s_register_operand" "r") 6475 (neg:SI (match_operator:SI 3 "shift_operator" 6476 [(match_operand:SI 1 "s_register_operand" "r") 6477 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))] 6478 "TARGET_ARM" 6479 "cmn%?\\t%0, %1%S3" 6480 [(set_attr "conds" "set") 6481 (set_attr "shift" "1") 6482 ] 6483) 6484 6485;; Cirrus SF compare instruction 6486(define_insn "*cirrus_cmpsf" 6487 [(set (reg:CCFP CC_REGNUM) 6488 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v") 6489 (match_operand:SF 1 "cirrus_fp_register" "v")))] 6490 "TARGET_ARM && TARGET_CIRRUS" 6491 "cfcmps%?\\tr15, %V0, %V1" 6492 [(set_attr "type" "mav_farith") 6493 (set_attr "cirrus" "compare")] 6494) 6495 6496;; Cirrus DF compare instruction 6497(define_insn "*cirrus_cmpdf" 6498 [(set (reg:CCFP CC_REGNUM) 6499 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v") 6500 (match_operand:DF 1 "cirrus_fp_register" "v")))] 6501 "TARGET_ARM && TARGET_CIRRUS" 6502 "cfcmpd%?\\tr15, %V0, %V1" 6503 [(set_attr "type" "mav_farith") 6504 (set_attr "cirrus" "compare")] 6505) 6506 6507;; Cirrus DI compare instruction 6508(define_expand "cmpdi" 6509 [(match_operand:DI 0 "cirrus_fp_register" "") 6510 (match_operand:DI 1 "cirrus_fp_register" "")] 6511 "TARGET_ARM && TARGET_CIRRUS" 6512 "{ 6513 arm_compare_op0 = operands[0]; 6514 arm_compare_op1 = operands[1]; 6515 DONE; 6516 }") 6517 6518(define_insn "*cirrus_cmpdi" 6519 [(set (reg:CC CC_REGNUM) 6520 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v") 6521 (match_operand:DI 1 "cirrus_fp_register" "v")))] 6522 "TARGET_ARM && TARGET_CIRRUS" 6523 "cfcmp64%?\\tr15, %V0, %V1" 6524 [(set_attr "type" "mav_farith") 6525 (set_attr "cirrus" "compare")] 6526) 6527 6528; This insn allows redundant compares to be removed by cse, nothing should 6529; ever appear in the output file since (set (reg x) (reg x)) is a no-op that 6530; is deleted later on. The match_dup will match the mode here, so that 6531; mode changes of the condition codes aren't lost by this even though we don't 6532; specify what they are. 6533 6534(define_insn "*deleted_compare" 6535 [(set (match_operand 0 "cc_register" "") (match_dup 0))] 6536 "TARGET_ARM" 6537 "\\t%@ deleted compare" 6538 [(set_attr "conds" "set") 6539 (set_attr "length" "0")] 6540) 6541 6542 6543;; Conditional branch insns 6544 6545(define_expand "beq" 6546 [(set (pc) 6547 (if_then_else (eq (match_dup 1) (const_int 0)) 6548 (label_ref (match_operand 0 "" "")) 6549 (pc)))] 6550 "TARGET_ARM" 6551 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);" 6552) 6553 6554(define_expand "bne" 6555 [(set (pc) 6556 (if_then_else (ne (match_dup 1) (const_int 0)) 6557 (label_ref (match_operand 0 "" "")) 6558 (pc)))] 6559 "TARGET_ARM" 6560 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);" 6561) 6562 6563(define_expand "bgt" 6564 [(set (pc) 6565 (if_then_else (gt (match_dup 1) (const_int 0)) 6566 (label_ref (match_operand 0 "" "")) 6567 (pc)))] 6568 "TARGET_ARM" 6569 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);" 6570) 6571 6572(define_expand "ble" 6573 [(set (pc) 6574 (if_then_else (le (match_dup 1) (const_int 0)) 6575 (label_ref (match_operand 0 "" "")) 6576 (pc)))] 6577 "TARGET_ARM" 6578 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);" 6579) 6580 6581(define_expand "bge" 6582 [(set (pc) 6583 (if_then_else (ge (match_dup 1) (const_int 0)) 6584 (label_ref (match_operand 0 "" "")) 6585 (pc)))] 6586 "TARGET_ARM" 6587 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);" 6588) 6589 6590(define_expand "blt" 6591 [(set (pc) 6592 (if_then_else (lt (match_dup 1) (const_int 0)) 6593 (label_ref (match_operand 0 "" "")) 6594 (pc)))] 6595 "TARGET_ARM" 6596 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);" 6597) 6598 6599(define_expand "bgtu" 6600 [(set (pc) 6601 (if_then_else (gtu (match_dup 1) (const_int 0)) 6602 (label_ref (match_operand 0 "" "")) 6603 (pc)))] 6604 "TARGET_ARM" 6605 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);" 6606) 6607 6608(define_expand "bleu" 6609 [(set (pc) 6610 (if_then_else (leu (match_dup 1) (const_int 0)) 6611 (label_ref (match_operand 0 "" "")) 6612 (pc)))] 6613 "TARGET_ARM" 6614 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);" 6615) 6616 6617(define_expand "bgeu" 6618 [(set (pc) 6619 (if_then_else (geu (match_dup 1) (const_int 0)) 6620 (label_ref (match_operand 0 "" "")) 6621 (pc)))] 6622 "TARGET_ARM" 6623 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);" 6624) 6625 6626(define_expand "bltu" 6627 [(set (pc) 6628 (if_then_else (ltu (match_dup 1) (const_int 0)) 6629 (label_ref (match_operand 0 "" "")) 6630 (pc)))] 6631 "TARGET_ARM" 6632 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);" 6633) 6634 6635(define_expand "bunordered" 6636 [(set (pc) 6637 (if_then_else (unordered (match_dup 1) (const_int 0)) 6638 (label_ref (match_operand 0 "" "")) 6639 (pc)))] 6640 "TARGET_ARM && TARGET_HARD_FLOAT" 6641 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0, 6642 arm_compare_op1);" 6643) 6644 6645(define_expand "bordered" 6646 [(set (pc) 6647 (if_then_else (ordered (match_dup 1) (const_int 0)) 6648 (label_ref (match_operand 0 "" "")) 6649 (pc)))] 6650 "TARGET_ARM && TARGET_HARD_FLOAT" 6651 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0, 6652 arm_compare_op1);" 6653) 6654 6655(define_expand "bungt" 6656 [(set (pc) 6657 (if_then_else (ungt (match_dup 1) (const_int 0)) 6658 (label_ref (match_operand 0 "" "")) 6659 (pc)))] 6660 "TARGET_ARM && TARGET_HARD_FLOAT" 6661 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);" 6662) 6663 6664(define_expand "bunlt" 6665 [(set (pc) 6666 (if_then_else (unlt (match_dup 1) (const_int 0)) 6667 (label_ref (match_operand 0 "" "")) 6668 (pc)))] 6669 "TARGET_ARM && TARGET_HARD_FLOAT" 6670 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);" 6671) 6672 6673(define_expand "bunge" 6674 [(set (pc) 6675 (if_then_else (unge (match_dup 1) (const_int 0)) 6676 (label_ref (match_operand 0 "" "")) 6677 (pc)))] 6678 "TARGET_ARM && TARGET_HARD_FLOAT" 6679 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);" 6680) 6681 6682(define_expand "bunle" 6683 [(set (pc) 6684 (if_then_else (unle (match_dup 1) (const_int 0)) 6685 (label_ref (match_operand 0 "" "")) 6686 (pc)))] 6687 "TARGET_ARM && TARGET_HARD_FLOAT" 6688 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);" 6689) 6690 6691;; The following two patterns need two branch instructions, since there is 6692;; no single instruction that will handle all cases. 6693(define_expand "buneq" 6694 [(set (pc) 6695 (if_then_else (uneq (match_dup 1) (const_int 0)) 6696 (label_ref (match_operand 0 "" "")) 6697 (pc)))] 6698 "TARGET_ARM && TARGET_HARD_FLOAT" 6699 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);" 6700) 6701 6702(define_expand "bltgt" 6703 [(set (pc) 6704 (if_then_else (ltgt (match_dup 1) (const_int 0)) 6705 (label_ref (match_operand 0 "" "")) 6706 (pc)))] 6707 "TARGET_ARM && TARGET_HARD_FLOAT" 6708 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);" 6709) 6710 6711;; 6712;; Patterns to match conditional branch insns. 6713;; 6714 6715; Special pattern to match UNEQ. 6716(define_insn "*arm_buneq" 6717 [(set (pc) 6718 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0)) 6719 (label_ref (match_operand 0 "" "")) 6720 (pc)))] 6721 "TARGET_ARM && TARGET_HARD_FLOAT" 6722 "* 6723 if (arm_ccfsm_state != 0) 6724 abort (); 6725 6726 return \"bvs\\t%l0\;beq\\t%l0\"; 6727 " 6728 [(set_attr "conds" "jump_clob") 6729 (set_attr "length" "8")] 6730) 6731 6732; Special pattern to match LTGT. 6733(define_insn "*arm_bltgt" 6734 [(set (pc) 6735 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0)) 6736 (label_ref (match_operand 0 "" "")) 6737 (pc)))] 6738 "TARGET_ARM && TARGET_HARD_FLOAT" 6739 "* 6740 if (arm_ccfsm_state != 0) 6741 abort (); 6742 6743 return \"bmi\\t%l0\;bgt\\t%l0\"; 6744 " 6745 [(set_attr "conds" "jump_clob") 6746 (set_attr "length" "8")] 6747) 6748 6749(define_insn "*arm_cond_branch" 6750 [(set (pc) 6751 (if_then_else (match_operator 1 "arm_comparison_operator" 6752 [(match_operand 2 "cc_register" "") (const_int 0)]) 6753 (label_ref (match_operand 0 "" "")) 6754 (pc)))] 6755 "TARGET_ARM" 6756 "* 6757 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) 6758 { 6759 arm_ccfsm_state += 2; 6760 return \"\"; 6761 } 6762 return \"b%d1\\t%l0\"; 6763 " 6764 [(set_attr "conds" "use")] 6765) 6766 6767; Special pattern to match reversed UNEQ. 6768(define_insn "*arm_buneq_reversed" 6769 [(set (pc) 6770 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0)) 6771 (pc) 6772 (label_ref (match_operand 0 "" ""))))] 6773 "TARGET_ARM && TARGET_HARD_FLOAT" 6774 "* 6775 if (arm_ccfsm_state != 0) 6776 abort (); 6777 6778 return \"bmi\\t%l0\;bgt\\t%l0\"; 6779 " 6780 [(set_attr "conds" "jump_clob") 6781 (set_attr "length" "8")] 6782) 6783 6784; Special pattern to match reversed LTGT. 6785(define_insn "*arm_bltgt_reversed" 6786 [(set (pc) 6787 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0)) 6788 (pc) 6789 (label_ref (match_operand 0 "" ""))))] 6790 "TARGET_ARM && TARGET_HARD_FLOAT" 6791 "* 6792 if (arm_ccfsm_state != 0) 6793 abort (); 6794 6795 return \"bvs\\t%l0\;beq\\t%l0\"; 6796 " 6797 [(set_attr "conds" "jump_clob") 6798 (set_attr "length" "8")] 6799) 6800 6801(define_insn "*arm_cond_branch_reversed" 6802 [(set (pc) 6803 (if_then_else (match_operator 1 "arm_comparison_operator" 6804 [(match_operand 2 "cc_register" "") (const_int 0)]) 6805 (pc) 6806 (label_ref (match_operand 0 "" ""))))] 6807 "TARGET_ARM" 6808 "* 6809 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) 6810 { 6811 arm_ccfsm_state += 2; 6812 return \"\"; 6813 } 6814 return \"b%D1\\t%l0\"; 6815 " 6816 [(set_attr "conds" "use")] 6817) 6818 6819 6820 6821; scc insns 6822 6823(define_expand "seq" 6824 [(set (match_operand:SI 0 "s_register_operand" "") 6825 (eq:SI (match_dup 1) (const_int 0)))] 6826 "TARGET_ARM" 6827 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);" 6828) 6829 6830(define_expand "sne" 6831 [(set (match_operand:SI 0 "s_register_operand" "") 6832 (ne:SI (match_dup 1) (const_int 0)))] 6833 "TARGET_ARM" 6834 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);" 6835) 6836 6837(define_expand "sgt" 6838 [(set (match_operand:SI 0 "s_register_operand" "") 6839 (gt:SI (match_dup 1) (const_int 0)))] 6840 "TARGET_ARM" 6841 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);" 6842) 6843 6844(define_expand "sle" 6845 [(set (match_operand:SI 0 "s_register_operand" "") 6846 (le:SI (match_dup 1) (const_int 0)))] 6847 "TARGET_ARM" 6848 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);" 6849) 6850 6851(define_expand "sge" 6852 [(set (match_operand:SI 0 "s_register_operand" "") 6853 (ge:SI (match_dup 1) (const_int 0)))] 6854 "TARGET_ARM" 6855 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);" 6856) 6857 6858(define_expand "slt" 6859 [(set (match_operand:SI 0 "s_register_operand" "") 6860 (lt:SI (match_dup 1) (const_int 0)))] 6861 "TARGET_ARM" 6862 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);" 6863) 6864 6865(define_expand "sgtu" 6866 [(set (match_operand:SI 0 "s_register_operand" "") 6867 (gtu:SI (match_dup 1) (const_int 0)))] 6868 "TARGET_ARM" 6869 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);" 6870) 6871 6872(define_expand "sleu" 6873 [(set (match_operand:SI 0 "s_register_operand" "") 6874 (leu:SI (match_dup 1) (const_int 0)))] 6875 "TARGET_ARM" 6876 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);" 6877) 6878 6879(define_expand "sgeu" 6880 [(set (match_operand:SI 0 "s_register_operand" "") 6881 (geu:SI (match_dup 1) (const_int 0)))] 6882 "TARGET_ARM" 6883 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);" 6884) 6885 6886(define_expand "sltu" 6887 [(set (match_operand:SI 0 "s_register_operand" "") 6888 (ltu:SI (match_dup 1) (const_int 0)))] 6889 "TARGET_ARM" 6890 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);" 6891) 6892 6893(define_expand "sunordered" 6894 [(set (match_operand:SI 0 "s_register_operand" "") 6895 (unordered:SI (match_dup 1) (const_int 0)))] 6896 "TARGET_ARM && TARGET_HARD_FLOAT" 6897 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0, 6898 arm_compare_op1);" 6899) 6900 6901(define_expand "sordered" 6902 [(set (match_operand:SI 0 "s_register_operand" "") 6903 (ordered:SI (match_dup 1) (const_int 0)))] 6904 "TARGET_ARM && TARGET_HARD_FLOAT" 6905 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0, 6906 arm_compare_op1);" 6907) 6908 6909(define_expand "sungt" 6910 [(set (match_operand:SI 0 "s_register_operand" "") 6911 (ungt:SI (match_dup 1) (const_int 0)))] 6912 "TARGET_ARM && TARGET_HARD_FLOAT" 6913 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, 6914 arm_compare_op1);" 6915) 6916 6917(define_expand "sunge" 6918 [(set (match_operand:SI 0 "s_register_operand" "") 6919 (unge:SI (match_dup 1) (const_int 0)))] 6920 "TARGET_ARM && TARGET_HARD_FLOAT" 6921 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, 6922 arm_compare_op1);" 6923) 6924 6925(define_expand "sunlt" 6926 [(set (match_operand:SI 0 "s_register_operand" "") 6927 (unlt:SI (match_dup 1) (const_int 0)))] 6928 "TARGET_ARM && TARGET_HARD_FLOAT" 6929 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, 6930 arm_compare_op1);" 6931) 6932 6933(define_expand "sunle" 6934 [(set (match_operand:SI 0 "s_register_operand" "") 6935 (unle:SI (match_dup 1) (const_int 0)))] 6936 "TARGET_ARM && TARGET_HARD_FLOAT" 6937 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, 6938 arm_compare_op1);" 6939) 6940 6941;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with 6942;;; simple ARM instructions. 6943; 6944; (define_expand "suneq" 6945; [(set (match_operand:SI 0 "s_register_operand" "") 6946; (uneq:SI (match_dup 1) (const_int 0)))] 6947; "TARGET_ARM && TARGET_HARD_FLOAT" 6948; "abort ();" 6949; ) 6950; 6951; (define_expand "sltgt" 6952; [(set (match_operand:SI 0 "s_register_operand" "") 6953; (ltgt:SI (match_dup 1) (const_int 0)))] 6954; "TARGET_ARM && TARGET_HARD_FLOAT" 6955; "abort ();" 6956; ) 6957 6958(define_insn "*mov_scc" 6959 [(set (match_operand:SI 0 "s_register_operand" "=r") 6960 (match_operator:SI 1 "arm_comparison_operator" 6961 [(match_operand 2 "cc_register" "") (const_int 0)]))] 6962 "TARGET_ARM" 6963 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1" 6964 [(set_attr "conds" "use") 6965 (set_attr "length" "8")] 6966) 6967 6968(define_insn "*mov_negscc" 6969 [(set (match_operand:SI 0 "s_register_operand" "=r") 6970 (neg:SI (match_operator:SI 1 "arm_comparison_operator" 6971 [(match_operand 2 "cc_register" "") (const_int 0)])))] 6972 "TARGET_ARM" 6973 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0" 6974 [(set_attr "conds" "use") 6975 (set_attr "length" "8")] 6976) 6977 6978(define_insn "*mov_notscc" 6979 [(set (match_operand:SI 0 "s_register_operand" "=r") 6980 (not:SI (match_operator:SI 1 "arm_comparison_operator" 6981 [(match_operand 2 "cc_register" "") (const_int 0)])))] 6982 "TARGET_ARM" 6983 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1" 6984 [(set_attr "conds" "use") 6985 (set_attr "length" "8")] 6986) 6987 6988 6989;; Conditional move insns 6990 6991(define_expand "movsicc" 6992 [(set (match_operand:SI 0 "s_register_operand" "") 6993 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "") 6994 (match_operand:SI 2 "arm_not_operand" "") 6995 (match_operand:SI 3 "arm_not_operand" "")))] 6996 "TARGET_ARM" 6997 " 6998 { 6999 enum rtx_code code = GET_CODE (operands[1]); 7000 rtx ccreg; 7001 7002 if (code == UNEQ || code == LTGT) 7003 FAIL; 7004 7005 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); 7006 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); 7007 }" 7008) 7009 7010(define_expand "movsfcc" 7011 [(set (match_operand:SF 0 "s_register_operand" "") 7012 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "") 7013 (match_operand:SF 2 "s_register_operand" "") 7014 (match_operand:SF 3 "nonmemory_operand" "")))] 7015 "TARGET_ARM" 7016 " 7017 { 7018 enum rtx_code code = GET_CODE (operands[1]); 7019 rtx ccreg; 7020 7021 if (code == UNEQ || code == LTGT) 7022 FAIL; 7023 7024 /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 7025 Otherwise, ensure it is a valid FP add operand. */ 7026 if ((!TARGET_HARD_FLOAT) 7027 || (!fpa_add_operand (operands[3], SFmode))) 7028 operands[3] = force_reg (SFmode, operands[3]); 7029 7030 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); 7031 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); 7032 }" 7033) 7034 7035(define_expand "movdfcc" 7036 [(set (match_operand:DF 0 "s_register_operand" "") 7037 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "") 7038 (match_operand:DF 2 "s_register_operand" "") 7039 (match_operand:DF 3 "fpa_add_operand" "")))] 7040 "TARGET_ARM && TARGET_HARD_FLOAT" 7041 " 7042 { 7043 enum rtx_code code = GET_CODE (operands[1]); 7044 rtx ccreg; 7045 7046 if (code == UNEQ || code == LTGT) 7047 FAIL; 7048 7049 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); 7050 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); 7051 }" 7052) 7053 7054(define_insn "*movsicc_insn" 7055 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r") 7056 (if_then_else:SI 7057 (match_operator 3 "arm_comparison_operator" 7058 [(match_operand 4 "cc_register" "") (const_int 0)]) 7059 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K") 7060 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))] 7061 "TARGET_ARM" 7062 "@ 7063 mov%D3\\t%0, %2 7064 mvn%D3\\t%0, #%B2 7065 mov%d3\\t%0, %1 7066 mvn%d3\\t%0, #%B1 7067 mov%d3\\t%0, %1\;mov%D3\\t%0, %2 7068 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2 7069 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2 7070 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2" 7071 [(set_attr "length" "4,4,4,4,8,8,8,8") 7072 (set_attr "conds" "use")] 7073) 7074 7075(define_insn "*movsfcc_soft_insn" 7076 [(set (match_operand:SF 0 "s_register_operand" "=r,r") 7077 (if_then_else:SF (match_operator 3 "arm_comparison_operator" 7078 [(match_operand 4 "cc_register" "") (const_int 0)]) 7079 (match_operand:SF 1 "s_register_operand" "0,r") 7080 (match_operand:SF 2 "s_register_operand" "r,0")))] 7081 "TARGET_ARM && TARGET_SOFT_FLOAT" 7082 "@ 7083 mov%D3\\t%0, %2 7084 mov%d3\\t%0, %1" 7085 [(set_attr "conds" "use")] 7086) 7087 7088 7089;; Jump and linkage insns 7090 7091(define_expand "jump" 7092 [(set (pc) 7093 (label_ref (match_operand 0 "" "")))] 7094 "TARGET_EITHER" 7095 "" 7096) 7097 7098(define_insn "*arm_jump" 7099 [(set (pc) 7100 (label_ref (match_operand 0 "" "")))] 7101 "TARGET_ARM" 7102 "* 7103 { 7104 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) 7105 { 7106 arm_ccfsm_state += 2; 7107 return \"\"; 7108 } 7109 return \"b%?\\t%l0\"; 7110 } 7111 " 7112 [(set_attr "predicable" "yes")] 7113) 7114 7115(define_insn "*thumb_jump" 7116 [(set (pc) 7117 (label_ref (match_operand 0 "" "")))] 7118 "TARGET_THUMB" 7119 "* 7120 if (get_attr_length (insn) == 2) 7121 return \"b\\t%l0\"; 7122 return \"bl\\t%l0\\t%@ far jump\"; 7123 " 7124 [(set (attr "far_jump") 7125 (if_then_else 7126 (eq_attr "length" "4") 7127 (const_string "yes") 7128 (const_string "no"))) 7129 (set (attr "length") 7130 (if_then_else 7131 (and (ge (minus (match_dup 0) (pc)) (const_int -2048)) 7132 (le (minus (match_dup 0) (pc)) (const_int 2044))) 7133 (const_int 2) 7134 (const_int 4)))] 7135) 7136 7137(define_expand "call" 7138 [(parallel [(call (match_operand 0 "memory_operand" "") 7139 (match_operand 1 "general_operand" "")) 7140 (use (match_operand 2 "" "")) 7141 (clobber (reg:SI LR_REGNUM))])] 7142 "TARGET_EITHER" 7143 " 7144 { 7145 rtx callee; 7146 7147 /* In an untyped call, we can get NULL for operand 2. */ 7148 if (operands[2] == NULL_RTX) 7149 operands[2] = const0_rtx; 7150 7151 /* This is to decide if we should generate indirect calls by loading the 7152 32 bit address of the callee into a register before performing the 7153 branch and link. operand[2] encodes the long_call/short_call 7154 attribute of the function being called. This attribute is set whenever 7155 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call 7156 is used, and the short_call attribute can also be set if function is 7157 declared as static or if it has already been defined in the current 7158 compilation unit. See arm.c and arm.h for info about this. The third 7159 parameter to arm_is_longcall_p is used to tell it which pattern 7160 invoked it. */ 7161 callee = XEXP (operands[0], 0); 7162 7163 if (GET_CODE (callee) != REG 7164 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0)) 7165 XEXP (operands[0], 0) = force_reg (Pmode, callee); 7166 }" 7167) 7168 7169(define_insn "*call_reg" 7170 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r")) 7171 (match_operand 1 "" "")) 7172 (use (match_operand 2 "" "")) 7173 (clobber (reg:SI LR_REGNUM))] 7174 "TARGET_ARM" 7175 "* 7176 return output_call (operands); 7177 " 7178 ;; length is worst case, normally it is only two 7179 [(set_attr "length" "12") 7180 (set_attr "type" "call")] 7181) 7182 7183(define_insn "*call_mem" 7184 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m")) 7185 (match_operand 1 "" "")) 7186 (use (match_operand 2 "" "")) 7187 (clobber (reg:SI LR_REGNUM))] 7188 "TARGET_ARM" 7189 "* 7190 return output_call_mem (operands); 7191 " 7192 [(set_attr "length" "12") 7193 (set_attr "type" "call")] 7194) 7195 7196(define_insn "*call_indirect" 7197 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r")) 7198 (match_operand 1 "" "")) 7199 (use (match_operand 2 "" "")) 7200 (clobber (reg:SI LR_REGNUM))] 7201 "TARGET_THUMB" 7202 "* 7203 { 7204 if (TARGET_CALLER_INTERWORKING) 7205 return \"bl\\t%__interwork_call_via_%0\"; 7206 else 7207 return \"bl\\t%__call_via_%0\"; 7208 }" 7209 [(set_attr "type" "call")] 7210) 7211 7212(define_insn "*call_value_indirect" 7213 [(set (match_operand 0 "" "") 7214 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r")) 7215 (match_operand 2 "" ""))) 7216 (use (match_operand 3 "" "")) 7217 (clobber (reg:SI LR_REGNUM))] 7218 "TARGET_THUMB" 7219 "* 7220 { 7221 if (TARGET_CALLER_INTERWORKING) 7222 return \"bl\\t%__interwork_call_via_%1\"; 7223 else 7224 return \"bl\\t%__call_via_%1\"; 7225 }" 7226 [(set_attr "type" "call")] 7227) 7228 7229(define_expand "call_value" 7230 [(parallel [(set (match_operand 0 "" "") 7231 (call (match_operand 1 "memory_operand" "") 7232 (match_operand 2 "general_operand" ""))) 7233 (use (match_operand 3 "" "")) 7234 (clobber (reg:SI LR_REGNUM))])] 7235 "TARGET_EITHER" 7236 " 7237 { 7238 rtx callee = XEXP (operands[1], 0); 7239 7240 /* In an untyped call, we can get NULL for operand 2. */ 7241 if (operands[3] == 0) 7242 operands[3] = const0_rtx; 7243 7244 /* See the comment in define_expand \"call\". */ 7245 if (GET_CODE (callee) != REG 7246 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0)) 7247 XEXP (operands[1], 0) = force_reg (Pmode, callee); 7248 }" 7249) 7250 7251(define_insn "*call_value_reg" 7252 [(set (match_operand 0 "" "") 7253 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r")) 7254 (match_operand 2 "" ""))) 7255 (use (match_operand 3 "" "")) 7256 (clobber (reg:SI LR_REGNUM))] 7257 "TARGET_ARM" 7258 "* 7259 return output_call (&operands[1]); 7260 " 7261 [(set_attr "length" "12") 7262 (set_attr "type" "call")] 7263) 7264 7265(define_insn "*call_value_mem" 7266 [(set (match_operand 0 "" "") 7267 (call (mem:SI (match_operand:SI 1 "memory_operand" "m")) 7268 (match_operand 2 "" ""))) 7269 (use (match_operand 3 "" "")) 7270 (clobber (reg:SI LR_REGNUM))] 7271 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))" 7272 "* 7273 return output_call_mem (&operands[1]); 7274 " 7275 [(set_attr "length" "12") 7276 (set_attr "type" "call")] 7277) 7278 7279;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses 7280;; The 'a' causes the operand to be treated as an address, i.e. no '#' output. 7281 7282(define_insn "*call_symbol" 7283 [(call (mem:SI (match_operand:SI 0 "" "")) 7284 (match_operand 1 "" "")) 7285 (use (match_operand 2 "" "")) 7286 (clobber (reg:SI LR_REGNUM))] 7287 "TARGET_ARM 7288 && (GET_CODE (operands[0]) == SYMBOL_REF) 7289 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)" 7290 "* 7291 { 7292 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\"; 7293 }" 7294 [(set_attr "type" "call")] 7295) 7296 7297(define_insn "*call_value_symbol" 7298 [(set (match_operand 0 "s_register_operand" "") 7299 (call (mem:SI (match_operand:SI 1 "" "")) 7300 (match_operand:SI 2 "" ""))) 7301 (use (match_operand 3 "" "")) 7302 (clobber (reg:SI LR_REGNUM))] 7303 "TARGET_ARM 7304 && (GET_CODE (operands[1]) == SYMBOL_REF) 7305 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)" 7306 "* 7307 { 7308 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\"; 7309 }" 7310 [(set_attr "type" "call")] 7311) 7312 7313(define_insn "*call_insn" 7314 [(call (mem:SI (match_operand:SI 0 "" "")) 7315 (match_operand:SI 1 "" "")) 7316 (use (match_operand 2 "" "")) 7317 (clobber (reg:SI LR_REGNUM))] 7318 "TARGET_THUMB 7319 && GET_CODE (operands[0]) == SYMBOL_REF 7320 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)" 7321 "bl\\t%a0" 7322 [(set_attr "length" "4") 7323 (set_attr "type" "call")] 7324) 7325 7326(define_insn "*call_value_insn" 7327 [(set (match_operand 0 "register_operand" "") 7328 (call (mem:SI (match_operand 1 "" "")) 7329 (match_operand 2 "" ""))) 7330 (use (match_operand 3 "" "")) 7331 (clobber (reg:SI LR_REGNUM))] 7332 "TARGET_THUMB 7333 && GET_CODE (operands[1]) == SYMBOL_REF 7334 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)" 7335 "bl\\t%a1" 7336 [(set_attr "length" "4") 7337 (set_attr "type" "call")] 7338) 7339 7340;; We may also be able to do sibcalls for Thumb, but it's much harder... 7341(define_expand "sibcall" 7342 [(parallel [(call (match_operand 0 "memory_operand" "") 7343 (match_operand 1 "general_operand" "")) 7344 (return) 7345 (use (match_operand 2 "" ""))])] 7346 "TARGET_ARM" 7347 " 7348 { 7349 if (operands[2] == NULL_RTX) 7350 operands[2] = const0_rtx; 7351 }" 7352) 7353 7354(define_expand "sibcall_value" 7355 [(parallel [(set (match_operand 0 "register_operand" "") 7356 (call (match_operand 1 "memory_operand" "") 7357 (match_operand 2 "general_operand" ""))) 7358 (return) 7359 (use (match_operand 3 "" ""))])] 7360 "TARGET_ARM" 7361 " 7362 { 7363 if (operands[3] == NULL_RTX) 7364 operands[3] = const0_rtx; 7365 }" 7366) 7367 7368(define_insn "*sibcall_insn" 7369 [(call (mem:SI (match_operand:SI 0 "" "X")) 7370 (match_operand 1 "" "")) 7371 (return) 7372 (use (match_operand 2 "" ""))] 7373 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF" 7374 "* 7375 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\"; 7376 " 7377 [(set_attr "type" "call")] 7378) 7379 7380(define_insn "*sibcall_value_insn" 7381 [(set (match_operand 0 "s_register_operand" "") 7382 (call (mem:SI (match_operand:SI 1 "" "X")) 7383 (match_operand 2 "" ""))) 7384 (return) 7385 (use (match_operand 3 "" ""))] 7386 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF" 7387 "* 7388 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\"; 7389 " 7390 [(set_attr "type" "call")] 7391) 7392 7393;; Often the return insn will be the same as loading from memory, so set attr 7394(define_insn "return" 7395 [(return)] 7396 "TARGET_ARM && USE_RETURN_INSN (FALSE)" 7397 "* 7398 { 7399 if (arm_ccfsm_state == 2) 7400 { 7401 arm_ccfsm_state += 2; 7402 return \"\"; 7403 } 7404 return output_return_instruction (const_true_rtx, TRUE, FALSE); 7405 }" 7406 [(set_attr "type" "load") 7407 (set_attr "length" "12") 7408 (set_attr "predicable" "yes")] 7409) 7410 7411(define_insn "*cond_return" 7412 [(set (pc) 7413 (if_then_else (match_operator 0 "arm_comparison_operator" 7414 [(match_operand 1 "cc_register" "") (const_int 0)]) 7415 (return) 7416 (pc)))] 7417 "TARGET_ARM && USE_RETURN_INSN (TRUE)" 7418 "* 7419 { 7420 if (arm_ccfsm_state == 2) 7421 { 7422 arm_ccfsm_state += 2; 7423 return \"\"; 7424 } 7425 return output_return_instruction (operands[0], TRUE, FALSE); 7426 }" 7427 [(set_attr "conds" "use") 7428 (set_attr "length" "12") 7429 (set_attr "type" "load")] 7430) 7431 7432(define_insn "*cond_return_inverted" 7433 [(set (pc) 7434 (if_then_else (match_operator 0 "arm_comparison_operator" 7435 [(match_operand 1 "cc_register" "") (const_int 0)]) 7436 (pc) 7437 (return)))] 7438 "TARGET_ARM && USE_RETURN_INSN (TRUE)" 7439 "* 7440 { 7441 if (arm_ccfsm_state == 2) 7442 { 7443 arm_ccfsm_state += 2; 7444 return \"\"; 7445 } 7446 return output_return_instruction (operands[0], TRUE, TRUE); 7447 }" 7448 [(set_attr "conds" "use") 7449 (set_attr "type" "load")] 7450) 7451 7452;; Generate a sequence of instructions to determine if the processor is 7453;; in 26-bit or 32-bit mode, and return the appropriate return address 7454;; mask. 7455 7456(define_expand "return_addr_mask" 7457 [(set (match_dup 1) 7458 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH) 7459 (const_int 0))) 7460 (set (match_operand:SI 0 "s_register_operand" "") 7461 (if_then_else:SI (eq (match_dup 1) (const_int 0)) 7462 (const_int -1) 7463 (const_int 67108860)))] ; 0x03fffffc 7464 "TARGET_ARM" 7465 " 7466 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM); 7467 ") 7468 7469(define_insn "*check_arch2" 7470 [(set (match_operand:CC_NOOV 0 "cc_register" "") 7471 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH) 7472 (const_int 0)))] 7473 "TARGET_ARM" 7474 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc" 7475 [(set_attr "length" "8") 7476 (set_attr "conds" "set")] 7477) 7478 7479;; Call subroutine returning any type. 7480 7481(define_expand "untyped_call" 7482 [(parallel [(call (match_operand 0 "" "") 7483 (const_int 0)) 7484 (match_operand 1 "" "") 7485 (match_operand 2 "" "")])] 7486 "TARGET_ARM" 7487 " 7488 { 7489 int i; 7490 7491 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); 7492 7493 for (i = 0; i < XVECLEN (operands[2], 0); i++) 7494 { 7495 rtx set = XVECEXP (operands[2], 0, i); 7496 7497 emit_move_insn (SET_DEST (set), SET_SRC (set)); 7498 } 7499 7500 /* The optimizer does not know that the call sets the function value 7501 registers we stored in the result block. We avoid problems by 7502 claiming that all hard registers are used and clobbered at this 7503 point. */ 7504 emit_insn (gen_blockage ()); 7505 7506 DONE; 7507 }" 7508) 7509 7510;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and 7511;; all of memory. This blocks insns from being moved across this point. 7512 7513(define_insn "blockage" 7514 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)] 7515 "TARGET_EITHER" 7516 "" 7517 [(set_attr "length" "0") 7518 (set_attr "type" "block")] 7519) 7520 7521(define_expand "casesi" 7522 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on 7523 (match_operand:SI 1 "const_int_operand" "") ; lower bound 7524 (match_operand:SI 2 "const_int_operand" "") ; total range 7525 (match_operand:SI 3 "" "") ; table label 7526 (match_operand:SI 4 "" "")] ; Out of range label 7527 "TARGET_ARM" 7528 " 7529 { 7530 rtx reg; 7531 if (operands[1] != const0_rtx) 7532 { 7533 reg = gen_reg_rtx (SImode); 7534 7535 emit_insn (gen_addsi3 (reg, operands[0], 7536 GEN_INT (-INTVAL (operands[1])))); 7537 operands[0] = reg; 7538 } 7539 7540 if (!const_ok_for_arm (INTVAL (operands[2]))) 7541 operands[2] = force_reg (SImode, operands[2]); 7542 7543 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3], 7544 operands[4])); 7545 DONE; 7546 }" 7547) 7548 7549;; The USE in this pattern is needed to tell flow analysis that this is 7550;; a CASESI insn. It has no other purpose. 7551(define_insn "casesi_internal" 7552 [(parallel [(set (pc) 7553 (if_then_else 7554 (leu (match_operand:SI 0 "s_register_operand" "r") 7555 (match_operand:SI 1 "arm_rhs_operand" "rI")) 7556 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4)) 7557 (label_ref (match_operand 2 "" "")))) 7558 (label_ref (match_operand 3 "" "")))) 7559 (clobber (reg:CC CC_REGNUM)) 7560 (use (label_ref (match_dup 2)))])] 7561 "TARGET_ARM" 7562 "* 7563 if (flag_pic) 7564 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\"; 7565 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\"; 7566 " 7567 [(set_attr "conds" "clob") 7568 (set_attr "length" "12")] 7569) 7570 7571(define_expand "indirect_jump" 7572 [(set (pc) 7573 (match_operand:SI 0 "s_register_operand" ""))] 7574 "TARGET_EITHER" 7575 "" 7576) 7577 7578(define_insn "*arm_indirect_jump" 7579 [(set (pc) 7580 (match_operand:SI 0 "s_register_operand" "r"))] 7581 "TARGET_ARM" 7582 "mov%?\\t%|pc, %0\\t%@ indirect register jump" 7583 [(set_attr "predicable" "yes")] 7584) 7585 7586;; Although not supported by the define_expand above, 7587;; cse/combine may generate this form. 7588(define_insn "*load_indirect_jump" 7589 [(set (pc) 7590 (match_operand:SI 0 "memory_operand" "m"))] 7591 "TARGET_ARM" 7592 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump" 7593 [(set_attr "type" "load") 7594 (set_attr "pool_range" "4096") 7595 (set_attr "neg_pool_range" "4084") 7596 (set_attr "predicable" "yes")] 7597) 7598 7599(define_insn "*thumb_indirect_jump" 7600 [(set (pc) 7601 (match_operand:SI 0 "register_operand" "l*r"))] 7602 "TARGET_THUMB" 7603 "mov\\tpc, %0" 7604 [(set_attr "conds" "clob") 7605 (set_attr "length" "2")] 7606) 7607 7608 7609;; Misc insns 7610 7611(define_insn "nop" 7612 [(const_int 0)] 7613 "TARGET_EITHER" 7614 "* 7615 if (TARGET_ARM) 7616 return \"mov%?\\t%|r0, %|r0\\t%@ nop\"; 7617 return \"mov\\tr8, r8\"; 7618 " 7619 [(set (attr "length") 7620 (if_then_else (eq_attr "is_thumb" "yes") 7621 (const_int 2) 7622 (const_int 4)))] 7623) 7624 7625 7626;; Patterns to allow combination of arithmetic, cond code and shifts 7627 7628(define_insn "*arith_shiftsi" 7629 [(set (match_operand:SI 0 "s_register_operand" "=r") 7630 (match_operator:SI 1 "shiftable_operator" 7631 [(match_operator:SI 3 "shift_operator" 7632 [(match_operand:SI 4 "s_register_operand" "r") 7633 (match_operand:SI 5 "reg_or_int_operand" "rI")]) 7634 (match_operand:SI 2 "s_register_operand" "r")]))] 7635 "TARGET_ARM" 7636 "%i1%?\\t%0, %2, %4%S3" 7637 [(set_attr "predicable" "yes") 7638 (set_attr "shift" "4") 7639 ] 7640) 7641 7642(define_split 7643 [(set (match_operand:SI 0 "s_register_operand" "") 7644 (match_operator:SI 1 "shiftable_operator" 7645 [(match_operator:SI 2 "shiftable_operator" 7646 [(match_operator:SI 3 "shift_operator" 7647 [(match_operand:SI 4 "s_register_operand" "") 7648 (match_operand:SI 5 "reg_or_int_operand" "")]) 7649 (match_operand:SI 6 "s_register_operand" "")]) 7650 (match_operand:SI 7 "arm_rhs_operand" "")])) 7651 (clobber (match_operand:SI 8 "s_register_operand" ""))] 7652 "TARGET_ARM" 7653 [(set (match_dup 8) 7654 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)]) 7655 (match_dup 6)])) 7656 (set (match_dup 0) 7657 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))] 7658 "") 7659 7660(define_insn "*arith_shiftsi_compare0" 7661 [(set (reg:CC_NOOV CC_REGNUM) 7662 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" 7663 [(match_operator:SI 3 "shift_operator" 7664 [(match_operand:SI 4 "s_register_operand" "r") 7665 (match_operand:SI 5 "reg_or_int_operand" "rI")]) 7666 (match_operand:SI 2 "s_register_operand" "r")]) 7667 (const_int 0))) 7668 (set (match_operand:SI 0 "s_register_operand" "=r") 7669 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)]) 7670 (match_dup 2)]))] 7671 "TARGET_ARM" 7672 "%i1%?s\\t%0, %2, %4%S3" 7673 [(set_attr "conds" "set") 7674 (set_attr "shift" "4") 7675 ] 7676) 7677 7678(define_insn "*arith_shiftsi_compare0_scratch" 7679 [(set (reg:CC_NOOV CC_REGNUM) 7680 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" 7681 [(match_operator:SI 3 "shift_operator" 7682 [(match_operand:SI 4 "s_register_operand" "r") 7683 (match_operand:SI 5 "reg_or_int_operand" "rI")]) 7684 (match_operand:SI 2 "s_register_operand" "r")]) 7685 (const_int 0))) 7686 (clobber (match_scratch:SI 0 "=r"))] 7687 "TARGET_ARM" 7688 "%i1%?s\\t%0, %2, %4%S3" 7689 [(set_attr "conds" "set") 7690 (set_attr "shift" "4") 7691 ] 7692) 7693 7694(define_insn "*sub_shiftsi" 7695 [(set (match_operand:SI 0 "s_register_operand" "=r") 7696 (minus:SI (match_operand:SI 1 "s_register_operand" "r") 7697 (match_operator:SI 2 "shift_operator" 7698 [(match_operand:SI 3 "s_register_operand" "r") 7699 (match_operand:SI 4 "reg_or_int_operand" "rM")])))] 7700 "TARGET_ARM" 7701 "sub%?\\t%0, %1, %3%S2" 7702 [(set_attr "predicable" "yes") 7703 (set_attr "shift" "3") 7704 ] 7705) 7706 7707(define_insn "*sub_shiftsi_compare0" 7708 [(set (reg:CC_NOOV CC_REGNUM) 7709 (compare:CC_NOOV 7710 (minus:SI (match_operand:SI 1 "s_register_operand" "r") 7711 (match_operator:SI 2 "shift_operator" 7712 [(match_operand:SI 3 "s_register_operand" "r") 7713 (match_operand:SI 4 "reg_or_int_operand" "rM")])) 7714 (const_int 0))) 7715 (set (match_operand:SI 0 "s_register_operand" "=r") 7716 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 7717 (match_dup 4)])))] 7718 "TARGET_ARM" 7719 "sub%?s\\t%0, %1, %3%S2" 7720 [(set_attr "conds" "set") 7721 (set_attr "shift" "3") 7722 ] 7723) 7724 7725(define_insn "*sub_shiftsi_compare0_scratch" 7726 [(set (reg:CC_NOOV CC_REGNUM) 7727 (compare:CC_NOOV 7728 (minus:SI (match_operand:SI 1 "s_register_operand" "r") 7729 (match_operator:SI 2 "shift_operator" 7730 [(match_operand:SI 3 "s_register_operand" "r") 7731 (match_operand:SI 4 "reg_or_int_operand" "rM")])) 7732 (const_int 0))) 7733 (clobber (match_scratch:SI 0 "=r"))] 7734 "TARGET_ARM" 7735 "sub%?s\\t%0, %1, %3%S2" 7736 [(set_attr "conds" "set") 7737 (set_attr "shift" "3") 7738 ] 7739) 7740 7741 7742 7743(define_insn "*and_scc" 7744 [(set (match_operand:SI 0 "s_register_operand" "=r") 7745 (and:SI (match_operator:SI 1 "arm_comparison_operator" 7746 [(match_operand 3 "cc_register" "") (const_int 0)]) 7747 (match_operand:SI 2 "s_register_operand" "r")))] 7748 "TARGET_ARM" 7749 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1" 7750 [(set_attr "conds" "use") 7751 (set_attr "length" "8")] 7752) 7753 7754(define_insn "*ior_scc" 7755 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7756 (ior:SI (match_operator:SI 2 "arm_comparison_operator" 7757 [(match_operand 3 "cc_register" "") (const_int 0)]) 7758 (match_operand:SI 1 "s_register_operand" "0,?r")))] 7759 "TARGET_ARM" 7760 "@ 7761 orr%d2\\t%0, %1, #1 7762 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1" 7763 [(set_attr "conds" "use") 7764 (set_attr "length" "4,8")] 7765) 7766 7767(define_insn "*compare_scc" 7768 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7769 (match_operator:SI 1 "arm_comparison_operator" 7770 [(match_operand:SI 2 "s_register_operand" "r,r") 7771 (match_operand:SI 3 "arm_add_operand" "rI,L")])) 7772 (clobber (reg:CC CC_REGNUM))] 7773 "TARGET_ARM" 7774 "* 7775 if (operands[3] == const0_rtx) 7776 { 7777 if (GET_CODE (operands[1]) == LT) 7778 return \"mov\\t%0, %2, lsr #31\"; 7779 7780 if (GET_CODE (operands[1]) == GE) 7781 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\"; 7782 7783 if (GET_CODE (operands[1]) == EQ) 7784 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\"; 7785 } 7786 7787 if (GET_CODE (operands[1]) == NE) 7788 { 7789 if (which_alternative == 1) 7790 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\"; 7791 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\"; 7792 } 7793 if (which_alternative == 1) 7794 output_asm_insn (\"cmn\\t%2, #%n3\", operands); 7795 else 7796 output_asm_insn (\"cmp\\t%2, %3\", operands); 7797 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\"; 7798 " 7799 [(set_attr "conds" "clob") 7800 (set_attr "length" "12")] 7801) 7802 7803(define_insn "*cond_move" 7804 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 7805 (if_then_else:SI (match_operator 3 "equality_operator" 7806 [(match_operator 4 "arm_comparison_operator" 7807 [(match_operand 5 "cc_register" "") (const_int 0)]) 7808 (const_int 0)]) 7809 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI") 7810 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))] 7811 "TARGET_ARM" 7812 "* 7813 if (GET_CODE (operands[3]) == NE) 7814 { 7815 if (which_alternative != 1) 7816 output_asm_insn (\"mov%D4\\t%0, %2\", operands); 7817 if (which_alternative != 0) 7818 output_asm_insn (\"mov%d4\\t%0, %1\", operands); 7819 return \"\"; 7820 } 7821 if (which_alternative != 0) 7822 output_asm_insn (\"mov%D4\\t%0, %1\", operands); 7823 if (which_alternative != 1) 7824 output_asm_insn (\"mov%d4\\t%0, %2\", operands); 7825 return \"\"; 7826 " 7827 [(set_attr "conds" "use") 7828 (set_attr "length" "4,4,8")] 7829) 7830 7831(define_insn "*cond_arith" 7832 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7833 (match_operator:SI 5 "shiftable_operator" 7834 [(match_operator:SI 4 "arm_comparison_operator" 7835 [(match_operand:SI 2 "s_register_operand" "r,r") 7836 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) 7837 (match_operand:SI 1 "s_register_operand" "0,?r")])) 7838 (clobber (reg:CC CC_REGNUM))] 7839 "TARGET_ARM" 7840 "* 7841 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx) 7842 return \"%i5\\t%0, %1, %2, lsr #31\"; 7843 7844 output_asm_insn (\"cmp\\t%2, %3\", operands); 7845 if (GET_CODE (operands[5]) == AND) 7846 output_asm_insn (\"mov%D4\\t%0, #0\", operands); 7847 else if (GET_CODE (operands[5]) == MINUS) 7848 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands); 7849 else if (which_alternative != 0) 7850 output_asm_insn (\"mov%D4\\t%0, %1\", operands); 7851 return \"%i5%d4\\t%0, %1, #1\"; 7852 " 7853 [(set_attr "conds" "clob") 7854 (set_attr "length" "12")] 7855) 7856 7857(define_insn "*cond_sub" 7858 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7859 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r") 7860 (match_operator:SI 4 "arm_comparison_operator" 7861 [(match_operand:SI 2 "s_register_operand" "r,r") 7862 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]))) 7863 (clobber (reg:CC CC_REGNUM))] 7864 "TARGET_ARM" 7865 "* 7866 output_asm_insn (\"cmp\\t%2, %3\", operands); 7867 if (which_alternative != 0) 7868 output_asm_insn (\"mov%D4\\t%0, %1\", operands); 7869 return \"sub%d4\\t%0, %1, #1\"; 7870 " 7871 [(set_attr "conds" "clob") 7872 (set_attr "length" "8,12")] 7873) 7874 7875(define_insn "*cmp_ite0" 7876 [(set (match_operand 6 "dominant_cc_register" "") 7877 (compare 7878 (if_then_else:SI 7879 (match_operator 4 "arm_comparison_operator" 7880 [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 7881 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 7882 (match_operator:SI 5 "arm_comparison_operator" 7883 [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 7884 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]) 7885 (const_int 0)) 7886 (const_int 0)))] 7887 "TARGET_ARM" 7888 "* 7889 { 7890 static const char * const opcodes[4][2] = 7891 { 7892 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\", 7893 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"}, 7894 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", 7895 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"}, 7896 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", 7897 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"}, 7898 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\", 7899 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"} 7900 }; 7901 int swap = 7902 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])); 7903 7904 return opcodes[which_alternative][swap]; 7905 }" 7906 [(set_attr "conds" "set") 7907 (set_attr "length" "8")] 7908) 7909 7910(define_insn "*cmp_ite1" 7911 [(set (match_operand 6 "dominant_cc_register" "") 7912 (compare 7913 (if_then_else:SI 7914 (match_operator 4 "arm_comparison_operator" 7915 [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 7916 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 7917 (match_operator:SI 5 "arm_comparison_operator" 7918 [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 7919 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]) 7920 (const_int 1)) 7921 (const_int 0)))] 7922 "TARGET_ARM" 7923 "* 7924 { 7925 static const char * const opcodes[4][2] = 7926 { 7927 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\", 7928 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"}, 7929 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\", 7930 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"}, 7931 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\", 7932 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"}, 7933 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\", 7934 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"} 7935 }; 7936 int swap = 7937 comparison_dominates_p (GET_CODE (operands[5]), 7938 reverse_condition (GET_CODE (operands[4]))); 7939 7940 return opcodes[which_alternative][swap]; 7941 }" 7942 [(set_attr "conds" "set") 7943 (set_attr "length" "8")] 7944) 7945 7946(define_insn "*cmp_and" 7947 [(set (match_operand 6 "dominant_cc_register" "") 7948 (compare 7949 (and:SI 7950 (match_operator 4 "arm_comparison_operator" 7951 [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 7952 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 7953 (match_operator:SI 5 "arm_comparison_operator" 7954 [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 7955 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])) 7956 (const_int 0)))] 7957 "TARGET_ARM" 7958 "* 7959 { 7960 static const char *const opcodes[4][2] = 7961 { 7962 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\", 7963 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"}, 7964 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", 7965 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"}, 7966 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", 7967 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"}, 7968 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\", 7969 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"} 7970 }; 7971 int swap = 7972 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])); 7973 7974 return opcodes[which_alternative][swap]; 7975 }" 7976 [(set_attr "conds" "set") 7977 (set_attr "predicable" "no") 7978 (set_attr "length" "8")] 7979) 7980 7981(define_insn "*cmp_ior" 7982 [(set (match_operand 6 "dominant_cc_register" "") 7983 (compare 7984 (ior:SI 7985 (match_operator 4 "arm_comparison_operator" 7986 [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 7987 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 7988 (match_operator:SI 5 "arm_comparison_operator" 7989 [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 7990 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])) 7991 (const_int 0)))] 7992 "TARGET_ARM" 7993 "* 7994{ 7995 static const char *const opcodes[4][2] = 7996 { 7997 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\", 7998 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"}, 7999 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\", 8000 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"}, 8001 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\", 8002 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"}, 8003 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\", 8004 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"} 8005 }; 8006 int swap = 8007 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])); 8008 8009 return opcodes[which_alternative][swap]; 8010} 8011" 8012 [(set_attr "conds" "set") 8013 (set_attr "length" "8")] 8014) 8015 8016(define_insn_and_split "*ior_scc_scc" 8017 [(set (match_operand:SI 0 "s_register_operand" "=r") 8018 (ior:SI (match_operator:SI 3 "arm_comparison_operator" 8019 [(match_operand:SI 1 "s_register_operand" "r") 8020 (match_operand:SI 2 "arm_add_operand" "rIL")]) 8021 (match_operator:SI 6 "arm_comparison_operator" 8022 [(match_operand:SI 4 "s_register_operand" "r") 8023 (match_operand:SI 5 "arm_add_operand" "rIL")]))) 8024 (clobber (reg:CC CC_REGNUM))] 8025 "TARGET_ARM 8026 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y) 8027 != CCmode)" 8028 "#" 8029 "TARGET_ARM && reload_completed" 8030 [(set (match_dup 7) 8031 (compare 8032 (ior:SI 8033 (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8034 (match_op_dup 6 [(match_dup 4) (match_dup 5)])) 8035 (const_int 0))) 8036 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))] 8037 "operands[7] 8038 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6], 8039 DOM_CC_X_OR_Y), 8040 CC_REGNUM);" 8041 [(set_attr "conds" "clob") 8042 (set_attr "length" "16")]) 8043 8044; If the above pattern is followed by a CMP insn, then the compare is 8045; redundant, since we can rework the conditional instruction that follows. 8046(define_insn_and_split "*ior_scc_scc_cmp" 8047 [(set (match_operand 0 "dominant_cc_register" "") 8048 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator" 8049 [(match_operand:SI 1 "s_register_operand" "r") 8050 (match_operand:SI 2 "arm_add_operand" "rIL")]) 8051 (match_operator:SI 6 "arm_comparison_operator" 8052 [(match_operand:SI 4 "s_register_operand" "r") 8053 (match_operand:SI 5 "arm_add_operand" "rIL")])) 8054 (const_int 0))) 8055 (set (match_operand:SI 7 "s_register_operand" "=r") 8056 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8057 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))] 8058 "TARGET_ARM" 8059 "#" 8060 "TARGET_ARM && reload_completed" 8061 [(set (match_dup 0) 8062 (compare 8063 (ior:SI 8064 (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8065 (match_op_dup 6 [(match_dup 4) (match_dup 5)])) 8066 (const_int 0))) 8067 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))] 8068 "" 8069 [(set_attr "conds" "set") 8070 (set_attr "length" "16")]) 8071 8072(define_insn_and_split "*and_scc_scc" 8073 [(set (match_operand:SI 0 "s_register_operand" "=r") 8074 (and:SI (match_operator:SI 3 "arm_comparison_operator" 8075 [(match_operand:SI 1 "s_register_operand" "r") 8076 (match_operand:SI 2 "arm_add_operand" "rIL")]) 8077 (match_operator:SI 6 "arm_comparison_operator" 8078 [(match_operand:SI 4 "s_register_operand" "r") 8079 (match_operand:SI 5 "arm_add_operand" "rIL")]))) 8080 (clobber (reg:CC CC_REGNUM))] 8081 "TARGET_ARM 8082 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y) 8083 != CCmode)" 8084 "#" 8085 "TARGET_ARM && reload_completed 8086 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y) 8087 != CCmode)" 8088 [(set (match_dup 7) 8089 (compare 8090 (and:SI 8091 (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8092 (match_op_dup 6 [(match_dup 4) (match_dup 5)])) 8093 (const_int 0))) 8094 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))] 8095 "operands[7] 8096 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6], 8097 DOM_CC_X_AND_Y), 8098 CC_REGNUM);" 8099 [(set_attr "conds" "clob") 8100 (set_attr "length" "16")]) 8101 8102; If the above pattern is followed by a CMP insn, then the compare is 8103; redundant, since we can rework the conditional instruction that follows. 8104(define_insn_and_split "*and_scc_scc_cmp" 8105 [(set (match_operand 0 "dominant_cc_register" "") 8106 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator" 8107 [(match_operand:SI 1 "s_register_operand" "r") 8108 (match_operand:SI 2 "arm_add_operand" "rIL")]) 8109 (match_operator:SI 6 "arm_comparison_operator" 8110 [(match_operand:SI 4 "s_register_operand" "r") 8111 (match_operand:SI 5 "arm_add_operand" "rIL")])) 8112 (const_int 0))) 8113 (set (match_operand:SI 7 "s_register_operand" "=r") 8114 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8115 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))] 8116 "TARGET_ARM" 8117 "#" 8118 "TARGET_ARM && reload_completed" 8119 [(set (match_dup 0) 8120 (compare 8121 (and:SI 8122 (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8123 (match_op_dup 6 [(match_dup 4) (match_dup 5)])) 8124 (const_int 0))) 8125 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))] 8126 "" 8127 [(set_attr "conds" "set") 8128 (set_attr "length" "16")]) 8129 8130;; If there is no dominance in the comparison, then we can still save an 8131;; instruction in the AND case, since we can know that the second compare 8132;; need only zero the value if false (if true, then the value is already 8133;; correct). 8134(define_insn_and_split "*and_scc_scc_nodom" 8135 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r") 8136 (and:SI (match_operator:SI 3 "arm_comparison_operator" 8137 [(match_operand:SI 1 "s_register_operand" "r,r,0") 8138 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")]) 8139 (match_operator:SI 6 "arm_comparison_operator" 8140 [(match_operand:SI 4 "s_register_operand" "r,r,r") 8141 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")]))) 8142 (clobber (reg:CC CC_REGNUM))] 8143 "TARGET_ARM 8144 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y) 8145 == CCmode)" 8146 "#" 8147 "TARGET_ARM && reload_completed" 8148 [(parallel [(set (match_dup 0) 8149 (match_op_dup 3 [(match_dup 1) (match_dup 2)])) 8150 (clobber (reg:CC CC_REGNUM))]) 8151 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)])) 8152 (set (match_dup 0) 8153 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)]) 8154 (match_dup 0) 8155 (const_int 0)))] 8156 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]), 8157 operands[4], operands[5]), 8158 CC_REGNUM); 8159 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4], 8160 operands[5]);" 8161 [(set_attr "conds" "clob") 8162 (set_attr "length" "20")]) 8163 8164(define_split 8165 [(set (reg:CC_NOOV CC_REGNUM) 8166 (compare:CC_NOOV (ior:SI 8167 (and:SI (match_operand:SI 0 "s_register_operand" "") 8168 (const_int 1)) 8169 (match_operator:SI 1 "comparison_operator" 8170 [(match_operand:SI 2 "s_register_operand" "") 8171 (match_operand:SI 3 "arm_add_operand" "")])) 8172 (const_int 0))) 8173 (clobber (match_operand:SI 4 "s_register_operand" ""))] 8174 "TARGET_ARM" 8175 [(set (match_dup 4) 8176 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)]) 8177 (match_dup 0))) 8178 (set (reg:CC_NOOV CC_REGNUM) 8179 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1)) 8180 (const_int 0)))] 8181 "") 8182 8183(define_split 8184 [(set (reg:CC_NOOV CC_REGNUM) 8185 (compare:CC_NOOV (ior:SI 8186 (match_operator:SI 1 "comparison_operator" 8187 [(match_operand:SI 2 "s_register_operand" "") 8188 (match_operand:SI 3 "arm_add_operand" "")]) 8189 (and:SI (match_operand:SI 0 "s_register_operand" "") 8190 (const_int 1))) 8191 (const_int 0))) 8192 (clobber (match_operand:SI 4 "s_register_operand" ""))] 8193 "TARGET_ARM" 8194 [(set (match_dup 4) 8195 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)]) 8196 (match_dup 0))) 8197 (set (reg:CC_NOOV CC_REGNUM) 8198 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1)) 8199 (const_int 0)))] 8200 "") 8201 8202(define_insn "*negscc" 8203 [(set (match_operand:SI 0 "s_register_operand" "=r") 8204 (neg:SI (match_operator 3 "arm_comparison_operator" 8205 [(match_operand:SI 1 "s_register_operand" "r") 8206 (match_operand:SI 2 "arm_rhs_operand" "rI")]))) 8207 (clobber (reg:CC CC_REGNUM))] 8208 "TARGET_ARM" 8209 "* 8210 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx) 8211 return \"mov\\t%0, %1, asr #31\"; 8212 8213 if (GET_CODE (operands[3]) == NE) 8214 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\"; 8215 8216 if (GET_CODE (operands[3]) == GT) 8217 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\"; 8218 8219 output_asm_insn (\"cmp\\t%1, %2\", operands); 8220 output_asm_insn (\"mov%D3\\t%0, #0\", operands); 8221 return \"mvn%d3\\t%0, #0\"; 8222 " 8223 [(set_attr "conds" "clob") 8224 (set_attr "length" "12")] 8225) 8226 8227(define_insn "movcond" 8228 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 8229 (if_then_else:SI 8230 (match_operator 5 "arm_comparison_operator" 8231 [(match_operand:SI 3 "s_register_operand" "r,r,r") 8232 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")]) 8233 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI") 8234 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 8235 (clobber (reg:CC CC_REGNUM))] 8236 "TARGET_ARM" 8237 "* 8238 if (GET_CODE (operands[5]) == LT 8239 && (operands[4] == const0_rtx)) 8240 { 8241 if (which_alternative != 1 && GET_CODE (operands[1]) == REG) 8242 { 8243 if (operands[2] == const0_rtx) 8244 return \"and\\t%0, %1, %3, asr #31\"; 8245 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\"; 8246 } 8247 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG) 8248 { 8249 if (operands[1] == const0_rtx) 8250 return \"bic\\t%0, %2, %3, asr #31\"; 8251 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\"; 8252 } 8253 /* The only case that falls through to here is when both ops 1 & 2 8254 are constants. */ 8255 } 8256 8257 if (GET_CODE (operands[5]) == GE 8258 && (operands[4] == const0_rtx)) 8259 { 8260 if (which_alternative != 1 && GET_CODE (operands[1]) == REG) 8261 { 8262 if (operands[2] == const0_rtx) 8263 return \"bic\\t%0, %1, %3, asr #31\"; 8264 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\"; 8265 } 8266 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG) 8267 { 8268 if (operands[1] == const0_rtx) 8269 return \"and\\t%0, %2, %3, asr #31\"; 8270 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\"; 8271 } 8272 /* The only case that falls through to here is when both ops 1 & 2 8273 are constants. */ 8274 } 8275 if (GET_CODE (operands[4]) == CONST_INT 8276 && !const_ok_for_arm (INTVAL (operands[4]))) 8277 output_asm_insn (\"cmn\\t%3, #%n4\", operands); 8278 else 8279 output_asm_insn (\"cmp\\t%3, %4\", operands); 8280 if (which_alternative != 0) 8281 output_asm_insn (\"mov%d5\\t%0, %1\", operands); 8282 if (which_alternative != 1) 8283 output_asm_insn (\"mov%D5\\t%0, %2\", operands); 8284 return \"\"; 8285 " 8286 [(set_attr "conds" "clob") 8287 (set_attr "length" "8,8,12")] 8288) 8289 8290(define_insn "*ifcompare_plus_move" 8291 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8292 (if_then_else:SI (match_operator 6 "arm_comparison_operator" 8293 [(match_operand:SI 4 "s_register_operand" "r,r") 8294 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 8295 (plus:SI 8296 (match_operand:SI 2 "s_register_operand" "r,r") 8297 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")) 8298 (match_operand:SI 1 "arm_rhs_operand" "0,?rI"))) 8299 (clobber (reg:CC CC_REGNUM))] 8300 "TARGET_ARM" 8301 "#" 8302 [(set_attr "conds" "clob") 8303 (set_attr "length" "8,12")] 8304) 8305 8306(define_insn "*if_plus_move" 8307 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r") 8308 (if_then_else:SI 8309 (match_operator 4 "arm_comparison_operator" 8310 [(match_operand 5 "cc_register" "") (const_int 0)]) 8311 (plus:SI 8312 (match_operand:SI 2 "s_register_operand" "r,r,r,r") 8313 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L")) 8314 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))] 8315 "TARGET_ARM" 8316 "@ 8317 add%d4\\t%0, %2, %3 8318 sub%d4\\t%0, %2, #%n3 8319 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1 8320 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1" 8321 [(set_attr "conds" "use") 8322 (set_attr "length" "4,4,8,8") 8323 (set_attr "type" "*,*,*,*")] 8324) 8325 8326(define_insn "*ifcompare_move_plus" 8327 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8328 (if_then_else:SI (match_operator 6 "arm_comparison_operator" 8329 [(match_operand:SI 4 "s_register_operand" "r,r") 8330 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 8331 (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 8332 (plus:SI 8333 (match_operand:SI 2 "s_register_operand" "r,r") 8334 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")))) 8335 (clobber (reg:CC CC_REGNUM))] 8336 "TARGET_ARM" 8337 "#" 8338 [(set_attr "conds" "clob") 8339 (set_attr "length" "8,12")] 8340) 8341 8342(define_insn "*if_move_plus" 8343 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r") 8344 (if_then_else:SI 8345 (match_operator 4 "arm_comparison_operator" 8346 [(match_operand 5 "cc_register" "") (const_int 0)]) 8347 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI") 8348 (plus:SI 8349 (match_operand:SI 2 "s_register_operand" "r,r,r,r") 8350 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))] 8351 "TARGET_ARM" 8352 "@ 8353 add%D4\\t%0, %2, %3 8354 sub%D4\\t%0, %2, #%n3 8355 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1 8356 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1" 8357 [(set_attr "conds" "use") 8358 (set_attr "length" "4,4,8,8") 8359 (set_attr "type" "*,*,*,*")] 8360) 8361 8362(define_insn "*ifcompare_arith_arith" 8363 [(set (match_operand:SI 0 "s_register_operand" "=r") 8364 (if_then_else:SI (match_operator 9 "arm_comparison_operator" 8365 [(match_operand:SI 5 "s_register_operand" "r") 8366 (match_operand:SI 6 "arm_add_operand" "rIL")]) 8367 (match_operator:SI 8 "shiftable_operator" 8368 [(match_operand:SI 1 "s_register_operand" "r") 8369 (match_operand:SI 2 "arm_rhs_operand" "rI")]) 8370 (match_operator:SI 7 "shiftable_operator" 8371 [(match_operand:SI 3 "s_register_operand" "r") 8372 (match_operand:SI 4 "arm_rhs_operand" "rI")]))) 8373 (clobber (reg:CC CC_REGNUM))] 8374 "TARGET_ARM" 8375 "#" 8376 [(set_attr "conds" "clob") 8377 (set_attr "length" "12")] 8378) 8379 8380(define_insn "*if_arith_arith" 8381 [(set (match_operand:SI 0 "s_register_operand" "=r") 8382 (if_then_else:SI (match_operator 5 "arm_comparison_operator" 8383 [(match_operand 8 "cc_register" "") (const_int 0)]) 8384 (match_operator:SI 6 "shiftable_operator" 8385 [(match_operand:SI 1 "s_register_operand" "r") 8386 (match_operand:SI 2 "arm_rhs_operand" "rI")]) 8387 (match_operator:SI 7 "shiftable_operator" 8388 [(match_operand:SI 3 "s_register_operand" "r") 8389 (match_operand:SI 4 "arm_rhs_operand" "rI")])))] 8390 "TARGET_ARM" 8391 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4" 8392 [(set_attr "conds" "use") 8393 (set_attr "length" "8")] 8394) 8395 8396(define_insn "*ifcompare_arith_move" 8397 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8398 (if_then_else:SI (match_operator 6 "arm_comparison_operator" 8399 [(match_operand:SI 2 "s_register_operand" "r,r") 8400 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")]) 8401 (match_operator:SI 7 "shiftable_operator" 8402 [(match_operand:SI 4 "s_register_operand" "r,r") 8403 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")]) 8404 (match_operand:SI 1 "arm_rhs_operand" "0,?rI"))) 8405 (clobber (reg:CC CC_REGNUM))] 8406 "TARGET_ARM" 8407 "* 8408 /* If we have an operation where (op x 0) is the identity operation and 8409 the conditional operator is LT or GE and we are comparing against zero and 8410 everything is in registers then we can do this in two instructions. */ 8411 if (operands[3] == const0_rtx 8412 && GET_CODE (operands[7]) != AND 8413 && GET_CODE (operands[5]) == REG 8414 && GET_CODE (operands[1]) == REG 8415 && REGNO (operands[1]) == REGNO (operands[4]) 8416 && REGNO (operands[4]) != REGNO (operands[0])) 8417 { 8418 if (GET_CODE (operands[6]) == LT) 8419 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\"; 8420 else if (GET_CODE (operands[6]) == GE) 8421 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\"; 8422 } 8423 if (GET_CODE (operands[3]) == CONST_INT 8424 && !const_ok_for_arm (INTVAL (operands[3]))) 8425 output_asm_insn (\"cmn\\t%2, #%n3\", operands); 8426 else 8427 output_asm_insn (\"cmp\\t%2, %3\", operands); 8428 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands); 8429 if (which_alternative != 0) 8430 return \"mov%D6\\t%0, %1\"; 8431 return \"\"; 8432 " 8433 [(set_attr "conds" "clob") 8434 (set_attr "length" "8,12")] 8435) 8436 8437(define_insn "*if_arith_move" 8438 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8439 (if_then_else:SI (match_operator 4 "arm_comparison_operator" 8440 [(match_operand 6 "cc_register" "") (const_int 0)]) 8441 (match_operator:SI 5 "shiftable_operator" 8442 [(match_operand:SI 2 "s_register_operand" "r,r") 8443 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) 8444 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))] 8445 "TARGET_ARM" 8446 "@ 8447 %I5%d4\\t%0, %2, %3 8448 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1" 8449 [(set_attr "conds" "use") 8450 (set_attr "length" "4,8") 8451 (set_attr "type" "*,*")] 8452) 8453 8454(define_insn "*ifcompare_move_arith" 8455 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8456 (if_then_else:SI (match_operator 6 "arm_comparison_operator" 8457 [(match_operand:SI 4 "s_register_operand" "r,r") 8458 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 8459 (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 8460 (match_operator:SI 7 "shiftable_operator" 8461 [(match_operand:SI 2 "s_register_operand" "r,r") 8462 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]))) 8463 (clobber (reg:CC CC_REGNUM))] 8464 "TARGET_ARM" 8465 "* 8466 /* If we have an operation where (op x 0) is the identity operation and 8467 the conditional operator is LT or GE and we are comparing against zero and 8468 everything is in registers then we can do this in two instructions */ 8469 if (operands[5] == const0_rtx 8470 && GET_CODE (operands[7]) != AND 8471 && GET_CODE (operands[3]) == REG 8472 && GET_CODE (operands[1]) == REG 8473 && REGNO (operands[1]) == REGNO (operands[2]) 8474 && REGNO (operands[2]) != REGNO (operands[0])) 8475 { 8476 if (GET_CODE (operands[6]) == GE) 8477 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\"; 8478 else if (GET_CODE (operands[6]) == LT) 8479 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\"; 8480 } 8481 8482 if (GET_CODE (operands[5]) == CONST_INT 8483 && !const_ok_for_arm (INTVAL (operands[5]))) 8484 output_asm_insn (\"cmn\\t%4, #%n5\", operands); 8485 else 8486 output_asm_insn (\"cmp\\t%4, %5\", operands); 8487 8488 if (which_alternative != 0) 8489 output_asm_insn (\"mov%d6\\t%0, %1\", operands); 8490 return \"%I7%D6\\t%0, %2, %3\"; 8491 " 8492 [(set_attr "conds" "clob") 8493 (set_attr "length" "8,12")] 8494) 8495 8496(define_insn "*if_move_arith" 8497 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8498 (if_then_else:SI 8499 (match_operator 4 "arm_comparison_operator" 8500 [(match_operand 6 "cc_register" "") (const_int 0)]) 8501 (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 8502 (match_operator:SI 5 "shiftable_operator" 8503 [(match_operand:SI 2 "s_register_operand" "r,r") 8504 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))] 8505 "TARGET_ARM" 8506 "@ 8507 %I5%D4\\t%0, %2, %3 8508 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1" 8509 [(set_attr "conds" "use") 8510 (set_attr "length" "4,8") 8511 (set_attr "type" "*,*")] 8512) 8513 8514(define_insn "*ifcompare_move_not" 8515 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8516 (if_then_else:SI 8517 (match_operator 5 "arm_comparison_operator" 8518 [(match_operand:SI 3 "s_register_operand" "r,r") 8519 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 8520 (match_operand:SI 1 "arm_not_operand" "0,?rIK") 8521 (not:SI 8522 (match_operand:SI 2 "s_register_operand" "r,r")))) 8523 (clobber (reg:CC CC_REGNUM))] 8524 "TARGET_ARM" 8525 "#" 8526 [(set_attr "conds" "clob") 8527 (set_attr "length" "8,12")] 8528) 8529 8530(define_insn "*if_move_not" 8531 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 8532 (if_then_else:SI 8533 (match_operator 4 "arm_comparison_operator" 8534 [(match_operand 3 "cc_register" "") (const_int 0)]) 8535 (match_operand:SI 1 "arm_not_operand" "0,?rI,K") 8536 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))] 8537 "TARGET_ARM" 8538 "@ 8539 mvn%D4\\t%0, %2 8540 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2 8541 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2" 8542 [(set_attr "conds" "use") 8543 (set_attr "length" "4,8,8")] 8544) 8545 8546(define_insn "*ifcompare_not_move" 8547 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8548 (if_then_else:SI 8549 (match_operator 5 "arm_comparison_operator" 8550 [(match_operand:SI 3 "s_register_operand" "r,r") 8551 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 8552 (not:SI 8553 (match_operand:SI 2 "s_register_operand" "r,r")) 8554 (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) 8555 (clobber (reg:CC CC_REGNUM))] 8556 "TARGET_ARM" 8557 "#" 8558 [(set_attr "conds" "clob") 8559 (set_attr "length" "8,12")] 8560) 8561 8562(define_insn "*if_not_move" 8563 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 8564 (if_then_else:SI 8565 (match_operator 4 "arm_comparison_operator" 8566 [(match_operand 3 "cc_register" "") (const_int 0)]) 8567 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r")) 8568 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] 8569 "TARGET_ARM" 8570 "@ 8571 mvn%d4\\t%0, %2 8572 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2 8573 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2" 8574 [(set_attr "conds" "use") 8575 (set_attr "length" "4,8,8")] 8576) 8577 8578(define_insn "*ifcompare_shift_move" 8579 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8580 (if_then_else:SI 8581 (match_operator 6 "arm_comparison_operator" 8582 [(match_operand:SI 4 "s_register_operand" "r,r") 8583 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 8584 (match_operator:SI 7 "shift_operator" 8585 [(match_operand:SI 2 "s_register_operand" "r,r") 8586 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")]) 8587 (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) 8588 (clobber (reg:CC CC_REGNUM))] 8589 "TARGET_ARM" 8590 "#" 8591 [(set_attr "conds" "clob") 8592 (set_attr "length" "8,12")] 8593) 8594 8595(define_insn "*if_shift_move" 8596 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 8597 (if_then_else:SI 8598 (match_operator 5 "arm_comparison_operator" 8599 [(match_operand 6 "cc_register" "") (const_int 0)]) 8600 (match_operator:SI 4 "shift_operator" 8601 [(match_operand:SI 2 "s_register_operand" "r,r,r") 8602 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")]) 8603 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] 8604 "TARGET_ARM" 8605 "@ 8606 mov%d5\\t%0, %2%S4 8607 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4 8608 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4" 8609 [(set_attr "conds" "use") 8610 (set_attr "shift" "2") 8611 (set_attr "length" "4,8,8")] 8612) 8613 8614(define_insn "*ifcompare_move_shift" 8615 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8616 (if_then_else:SI 8617 (match_operator 6 "arm_comparison_operator" 8618 [(match_operand:SI 4 "s_register_operand" "r,r") 8619 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 8620 (match_operand:SI 1 "arm_not_operand" "0,?rIK") 8621 (match_operator:SI 7 "shift_operator" 8622 [(match_operand:SI 2 "s_register_operand" "r,r") 8623 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")]))) 8624 (clobber (reg:CC CC_REGNUM))] 8625 "TARGET_ARM" 8626 "#" 8627 [(set_attr "conds" "clob") 8628 (set_attr "length" "8,12")] 8629) 8630 8631(define_insn "*if_move_shift" 8632 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 8633 (if_then_else:SI 8634 (match_operator 5 "arm_comparison_operator" 8635 [(match_operand 6 "cc_register" "") (const_int 0)]) 8636 (match_operand:SI 1 "arm_not_operand" "0,?rI,K") 8637 (match_operator:SI 4 "shift_operator" 8638 [(match_operand:SI 2 "s_register_operand" "r,r,r") 8639 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))] 8640 "TARGET_ARM" 8641 "@ 8642 mov%D5\\t%0, %2%S4 8643 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4 8644 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4" 8645 [(set_attr "conds" "use") 8646 (set_attr "shift" "2") 8647 (set_attr "length" "4,8,8")] 8648) 8649 8650(define_insn "*ifcompare_shift_shift" 8651 [(set (match_operand:SI 0 "s_register_operand" "=r") 8652 (if_then_else:SI 8653 (match_operator 7 "arm_comparison_operator" 8654 [(match_operand:SI 5 "s_register_operand" "r") 8655 (match_operand:SI 6 "arm_add_operand" "rIL")]) 8656 (match_operator:SI 8 "shift_operator" 8657 [(match_operand:SI 1 "s_register_operand" "r") 8658 (match_operand:SI 2 "arm_rhs_operand" "rM")]) 8659 (match_operator:SI 9 "shift_operator" 8660 [(match_operand:SI 3 "s_register_operand" "r") 8661 (match_operand:SI 4 "arm_rhs_operand" "rM")]))) 8662 (clobber (reg:CC CC_REGNUM))] 8663 "TARGET_ARM" 8664 "#" 8665 [(set_attr "conds" "clob") 8666 (set_attr "length" "12")] 8667) 8668 8669(define_insn "*if_shift_shift" 8670 [(set (match_operand:SI 0 "s_register_operand" "=r") 8671 (if_then_else:SI 8672 (match_operator 5 "arm_comparison_operator" 8673 [(match_operand 8 "cc_register" "") (const_int 0)]) 8674 (match_operator:SI 6 "shift_operator" 8675 [(match_operand:SI 1 "s_register_operand" "r") 8676 (match_operand:SI 2 "arm_rhs_operand" "rM")]) 8677 (match_operator:SI 7 "shift_operator" 8678 [(match_operand:SI 3 "s_register_operand" "r") 8679 (match_operand:SI 4 "arm_rhs_operand" "rM")])))] 8680 "TARGET_ARM" 8681 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7" 8682 [(set_attr "conds" "use") 8683 (set_attr "shift" "1") 8684 (set_attr "length" "8")] 8685) 8686 8687(define_insn "*ifcompare_not_arith" 8688 [(set (match_operand:SI 0 "s_register_operand" "=r") 8689 (if_then_else:SI 8690 (match_operator 6 "arm_comparison_operator" 8691 [(match_operand:SI 4 "s_register_operand" "r") 8692 (match_operand:SI 5 "arm_add_operand" "rIL")]) 8693 (not:SI (match_operand:SI 1 "s_register_operand" "r")) 8694 (match_operator:SI 7 "shiftable_operator" 8695 [(match_operand:SI 2 "s_register_operand" "r") 8696 (match_operand:SI 3 "arm_rhs_operand" "rI")]))) 8697 (clobber (reg:CC CC_REGNUM))] 8698 "TARGET_ARM" 8699 "#" 8700 [(set_attr "conds" "clob") 8701 (set_attr "length" "12")] 8702) 8703 8704(define_insn "*if_not_arith" 8705 [(set (match_operand:SI 0 "s_register_operand" "=r") 8706 (if_then_else:SI 8707 (match_operator 5 "arm_comparison_operator" 8708 [(match_operand 4 "cc_register" "") (const_int 0)]) 8709 (not:SI (match_operand:SI 1 "s_register_operand" "r")) 8710 (match_operator:SI 6 "shiftable_operator" 8711 [(match_operand:SI 2 "s_register_operand" "r") 8712 (match_operand:SI 3 "arm_rhs_operand" "rI")])))] 8713 "TARGET_ARM" 8714 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3" 8715 [(set_attr "conds" "use") 8716 (set_attr "length" "8")] 8717) 8718 8719(define_insn "*ifcompare_arith_not" 8720 [(set (match_operand:SI 0 "s_register_operand" "=r") 8721 (if_then_else:SI 8722 (match_operator 6 "arm_comparison_operator" 8723 [(match_operand:SI 4 "s_register_operand" "r") 8724 (match_operand:SI 5 "arm_add_operand" "rIL")]) 8725 (match_operator:SI 7 "shiftable_operator" 8726 [(match_operand:SI 2 "s_register_operand" "r") 8727 (match_operand:SI 3 "arm_rhs_operand" "rI")]) 8728 (not:SI (match_operand:SI 1 "s_register_operand" "r")))) 8729 (clobber (reg:CC CC_REGNUM))] 8730 "TARGET_ARM" 8731 "#" 8732 [(set_attr "conds" "clob") 8733 (set_attr "length" "12")] 8734) 8735 8736(define_insn "*if_arith_not" 8737 [(set (match_operand:SI 0 "s_register_operand" "=r") 8738 (if_then_else:SI 8739 (match_operator 5 "arm_comparison_operator" 8740 [(match_operand 4 "cc_register" "") (const_int 0)]) 8741 (match_operator:SI 6 "shiftable_operator" 8742 [(match_operand:SI 2 "s_register_operand" "r") 8743 (match_operand:SI 3 "arm_rhs_operand" "rI")]) 8744 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))] 8745 "TARGET_ARM" 8746 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3" 8747 [(set_attr "conds" "use") 8748 (set_attr "length" "8")] 8749) 8750 8751(define_insn "*ifcompare_neg_move" 8752 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8753 (if_then_else:SI 8754 (match_operator 5 "arm_comparison_operator" 8755 [(match_operand:SI 3 "s_register_operand" "r,r") 8756 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 8757 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r")) 8758 (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) 8759 (clobber (reg:CC CC_REGNUM))] 8760 "TARGET_ARM" 8761 "#" 8762 [(set_attr "conds" "clob") 8763 (set_attr "length" "8,12")] 8764) 8765 8766(define_insn "*if_neg_move" 8767 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 8768 (if_then_else:SI 8769 (match_operator 4 "arm_comparison_operator" 8770 [(match_operand 3 "cc_register" "") (const_int 0)]) 8771 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r")) 8772 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] 8773 "TARGET_ARM" 8774 "@ 8775 rsb%d4\\t%0, %2, #0 8776 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0 8777 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0" 8778 [(set_attr "conds" "use") 8779 (set_attr "length" "4,8,8")] 8780) 8781 8782(define_insn "*ifcompare_move_neg" 8783 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8784 (if_then_else:SI 8785 (match_operator 5 "arm_comparison_operator" 8786 [(match_operand:SI 3 "s_register_operand" "r,r") 8787 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 8788 (match_operand:SI 1 "arm_not_operand" "0,?rIK") 8789 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r")))) 8790 (clobber (reg:CC CC_REGNUM))] 8791 "TARGET_ARM" 8792 "#" 8793 [(set_attr "conds" "clob") 8794 (set_attr "length" "8,12")] 8795) 8796 8797(define_insn "*if_move_neg" 8798 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 8799 (if_then_else:SI 8800 (match_operator 4 "arm_comparison_operator" 8801 [(match_operand 3 "cc_register" "") (const_int 0)]) 8802 (match_operand:SI 1 "arm_not_operand" "0,?rI,K") 8803 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))] 8804 "TARGET_ARM" 8805 "@ 8806 rsb%D4\\t%0, %2, #0 8807 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0 8808 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0" 8809 [(set_attr "conds" "use") 8810 (set_attr "length" "4,8,8")] 8811) 8812 8813(define_insn "*arith_adjacentmem" 8814 [(set (match_operand:SI 0 "s_register_operand" "=r") 8815 (match_operator:SI 1 "shiftable_operator" 8816 [(match_operand:SI 2 "memory_operand" "m") 8817 (match_operand:SI 3 "memory_operand" "m")])) 8818 (clobber (match_scratch:SI 4 "=r"))] 8819 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])" 8820 "* 8821 { 8822 rtx ldm[3]; 8823 rtx arith[4]; 8824 int val1 = 0, val2 = 0; 8825 8826 if (REGNO (operands[0]) > REGNO (operands[4])) 8827 { 8828 ldm[1] = operands[4]; 8829 ldm[2] = operands[0]; 8830 } 8831 else 8832 { 8833 ldm[1] = operands[0]; 8834 ldm[2] = operands[4]; 8835 } 8836 if (GET_CODE (XEXP (operands[2], 0)) != REG) 8837 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1)); 8838 if (GET_CODE (XEXP (operands[3], 0)) != REG) 8839 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1)); 8840 arith[0] = operands[0]; 8841 arith[3] = operands[1]; 8842 if (val1 < val2) 8843 { 8844 arith[1] = ldm[1]; 8845 arith[2] = ldm[2]; 8846 } 8847 else 8848 { 8849 arith[1] = ldm[2]; 8850 arith[2] = ldm[1]; 8851 } 8852 if (val1 && val2) 8853 { 8854 rtx ops[3]; 8855 ldm[0] = ops[0] = operands[4]; 8856 ops[1] = XEXP (XEXP (operands[2], 0), 0); 8857 ops[2] = XEXP (XEXP (operands[2], 0), 1); 8858 output_add_immediate (ops); 8859 if (val1 < val2) 8860 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); 8861 else 8862 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); 8863 } 8864 else if (val1) 8865 { 8866 ldm[0] = XEXP (operands[3], 0); 8867 if (val1 < val2) 8868 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); 8869 else 8870 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); 8871 } 8872 else 8873 { 8874 ldm[0] = XEXP (operands[2], 0); 8875 if (val1 < val2) 8876 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); 8877 else 8878 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); 8879 } 8880 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith); 8881 return \"\"; 8882 }" 8883 [(set_attr "length" "12") 8884 (set_attr "predicable" "yes") 8885 (set_attr "type" "load")] 8886) 8887 8888;; the arm can support extended pre-inc instructions 8889 8890;; In all these cases, we use operands 0 and 1 for the register being 8891;; incremented because those are the operands that local-alloc will 8892;; tie and these are the pair most likely to be tieable (and the ones 8893;; that will benefit the most). 8894 8895;; We reject the frame pointer if it occurs anywhere in these patterns since 8896;; elimination will cause too many headaches. 8897 8898(define_insn "*strqi_preinc" 8899 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 8900 (match_operand:SI 2 "index_operand" "rJ"))) 8901 (match_operand:QI 3 "s_register_operand" "r")) 8902 (set (match_operand:SI 0 "s_register_operand" "=r") 8903 (plus:SI (match_dup 1) (match_dup 2)))] 8904 "TARGET_ARM 8905 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8906 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8907 && (GET_CODE (operands[2]) != REG 8908 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8909 "str%?b\\t%3, [%0, %2]!" 8910 [(set_attr "type" "store1") 8911 (set_attr "predicable" "yes")] 8912) 8913 8914(define_insn "*strqi_predec" 8915 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8916 (match_operand:SI 2 "s_register_operand" "r"))) 8917 (match_operand:QI 3 "s_register_operand" "r")) 8918 (set (match_operand:SI 0 "s_register_operand" "=r") 8919 (minus:SI (match_dup 1) (match_dup 2)))] 8920 "TARGET_ARM 8921 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8922 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8923 && (GET_CODE (operands[2]) != REG 8924 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8925 "str%?b\\t%3, [%0, -%2]!" 8926 [(set_attr "type" "store1") 8927 (set_attr "predicable" "yes")] 8928) 8929 8930(define_insn "*loadqi_preinc" 8931 [(set (match_operand:QI 3 "s_register_operand" "=r") 8932 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 8933 (match_operand:SI 2 "index_operand" "rJ")))) 8934 (set (match_operand:SI 0 "s_register_operand" "=r") 8935 (plus:SI (match_dup 1) (match_dup 2)))] 8936 "TARGET_ARM 8937 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8938 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8939 && (GET_CODE (operands[2]) != REG 8940 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8941 "ldr%?b\\t%3, [%0, %2]!" 8942 [(set_attr "type" "load") 8943 (set_attr "predicable" "yes")] 8944) 8945 8946(define_insn "*loadqi_predec" 8947 [(set (match_operand:QI 3 "s_register_operand" "=r") 8948 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8949 (match_operand:SI 2 "s_register_operand" "r")))) 8950 (set (match_operand:SI 0 "s_register_operand" "=r") 8951 (minus:SI (match_dup 1) (match_dup 2)))] 8952 "TARGET_ARM 8953 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8954 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8955 && (GET_CODE (operands[2]) != REG 8956 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8957 "ldr%?b\\t%3, [%0, -%2]!" 8958 [(set_attr "type" "load") 8959 (set_attr "predicable" "yes")] 8960) 8961 8962(define_insn "*loadqisi_preinc" 8963 [(set (match_operand:SI 3 "s_register_operand" "=r") 8964 (zero_extend:SI 8965 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 8966 (match_operand:SI 2 "index_operand" "rJ"))))) 8967 (set (match_operand:SI 0 "s_register_operand" "=r") 8968 (plus:SI (match_dup 1) (match_dup 2)))] 8969 "TARGET_ARM 8970 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8971 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8972 && (GET_CODE (operands[2]) != REG 8973 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8974 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi" 8975 [(set_attr "type" "load") 8976 (set_attr "predicable" "yes")] 8977) 8978 8979(define_insn "*loadqisi_predec" 8980 [(set (match_operand:SI 3 "s_register_operand" "=r") 8981 (zero_extend:SI 8982 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8983 (match_operand:SI 2 "s_register_operand" "r"))))) 8984 (set (match_operand:SI 0 "s_register_operand" "=r") 8985 (minus:SI (match_dup 1) (match_dup 2)))] 8986 "TARGET_ARM 8987 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8988 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8989 && (GET_CODE (operands[2]) != REG 8990 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8991 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi" 8992 [(set_attr "type" "load") 8993 (set_attr "predicable" "yes")] 8994) 8995 8996(define_insn "*strsi_preinc" 8997 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 8998 (match_operand:SI 2 "index_operand" "rJ"))) 8999 (match_operand:SI 3 "s_register_operand" "r")) 9000 (set (match_operand:SI 0 "s_register_operand" "=r") 9001 (plus:SI (match_dup 1) (match_dup 2)))] 9002 "TARGET_ARM 9003 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9004 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9005 && (GET_CODE (operands[2]) != REG 9006 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 9007 "str%?\\t%3, [%0, %2]!" 9008 [(set_attr "type" "store1") 9009 (set_attr "predicable" "yes")] 9010) 9011 9012(define_insn "*strsi_predec" 9013 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 9014 (match_operand:SI 2 "s_register_operand" "r"))) 9015 (match_operand:SI 3 "s_register_operand" "r")) 9016 (set (match_operand:SI 0 "s_register_operand" "=r") 9017 (minus:SI (match_dup 1) (match_dup 2)))] 9018 "TARGET_ARM 9019 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9020 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9021 && (GET_CODE (operands[2]) != REG 9022 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 9023 "str%?\\t%3, [%0, -%2]!" 9024 [(set_attr "type" "store1") 9025 (set_attr "predicable" "yes")] 9026) 9027 9028(define_insn "*loadsi_preinc" 9029 [(set (match_operand:SI 3 "s_register_operand" "=r") 9030 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 9031 (match_operand:SI 2 "index_operand" "rJ")))) 9032 (set (match_operand:SI 0 "s_register_operand" "=r") 9033 (plus:SI (match_dup 1) (match_dup 2)))] 9034 "TARGET_ARM 9035 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9036 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9037 && (GET_CODE (operands[2]) != REG 9038 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 9039 "ldr%?\\t%3, [%0, %2]!" 9040 [(set_attr "type" "load") 9041 (set_attr "predicable" "yes")] 9042) 9043 9044(define_insn "*loadsi_predec" 9045 [(set (match_operand:SI 3 "s_register_operand" "=r") 9046 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 9047 (match_operand:SI 2 "s_register_operand" "r")))) 9048 (set (match_operand:SI 0 "s_register_operand" "=r") 9049 (minus:SI (match_dup 1) (match_dup 2)))] 9050 "TARGET_ARM 9051 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9052 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9053 && (GET_CODE (operands[2]) != REG 9054 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 9055 "ldr%?\\t%3, [%0, -%2]!" 9056 [(set_attr "type" "load") 9057 (set_attr "predicable" "yes")] 9058) 9059 9060(define_insn "*loadhi_preinc" 9061 [(set (match_operand:HI 3 "s_register_operand" "=r") 9062 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 9063 (match_operand:SI 2 "index_operand" "rJ")))) 9064 (set (match_operand:SI 0 "s_register_operand" "=r") 9065 (plus:SI (match_dup 1) (match_dup 2)))] 9066 "TARGET_ARM 9067 && !BYTES_BIG_ENDIAN 9068 && !TARGET_MMU_TRAPS 9069 && !arm_arch4 9070 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9071 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9072 && (GET_CODE (operands[2]) != REG 9073 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 9074 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi" 9075 [(set_attr "type" "load") 9076 (set_attr "predicable" "yes")] 9077) 9078 9079(define_insn "*loadhi_predec" 9080 [(set (match_operand:HI 3 "s_register_operand" "=r") 9081 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 9082 (match_operand:SI 2 "s_register_operand" "r")))) 9083 (set (match_operand:SI 0 "s_register_operand" "=r") 9084 (minus:SI (match_dup 1) (match_dup 2)))] 9085 "TARGET_ARM 9086 && !BYTES_BIG_ENDIAN 9087 && !TARGET_MMU_TRAPS 9088 && !arm_arch4 9089 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9090 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9091 && (GET_CODE (operands[2]) != REG 9092 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 9093 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi" 9094 [(set_attr "type" "load") 9095 (set_attr "predicable" "yes")] 9096) 9097 9098(define_insn "*strqi_shiftpreinc" 9099 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator" 9100 [(match_operand:SI 3 "s_register_operand" "r") 9101 (match_operand:SI 4 "const_shift_operand" "n")]) 9102 (match_operand:SI 1 "s_register_operand" "0"))) 9103 (match_operand:QI 5 "s_register_operand" "r")) 9104 (set (match_operand:SI 0 "s_register_operand" "=r") 9105 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 9106 (match_dup 1)))] 9107 "TARGET_ARM 9108 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9109 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9110 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 9111 "str%?b\\t%5, [%0, %3%S2]!" 9112 [(set_attr "type" "store1") 9113 (set_attr "predicable" "yes")] 9114) 9115 9116(define_insn "*strqi_shiftpredec" 9117 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 9118 (match_operator:SI 2 "shift_operator" 9119 [(match_operand:SI 3 "s_register_operand" "r") 9120 (match_operand:SI 4 "const_shift_operand" "n")]))) 9121 (match_operand:QI 5 "s_register_operand" "r")) 9122 (set (match_operand:SI 0 "s_register_operand" "=r") 9123 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 9124 (match_dup 4)])))] 9125 "TARGET_ARM 9126 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9127 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9128 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 9129 "str%?b\\t%5, [%0, -%3%S2]!" 9130 [(set_attr "type" "store1") 9131 (set_attr "predicable" "yes")] 9132) 9133 9134(define_insn "*loadqi_shiftpreinc" 9135 [(set (match_operand:QI 5 "s_register_operand" "=r") 9136 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator" 9137 [(match_operand:SI 3 "s_register_operand" "r") 9138 (match_operand:SI 4 "const_shift_operand" "n")]) 9139 (match_operand:SI 1 "s_register_operand" "0")))) 9140 (set (match_operand:SI 0 "s_register_operand" "=r") 9141 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 9142 (match_dup 1)))] 9143 "TARGET_ARM 9144 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9145 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9146 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 9147 "ldr%?b\\t%5, [%0, %3%S2]!" 9148 [(set_attr "type" "load") 9149 (set_attr "predicable" "yes")] 9150) 9151 9152(define_insn "*loadqi_shiftpredec" 9153 [(set (match_operand:QI 5 "s_register_operand" "=r") 9154 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 9155 (match_operator:SI 2 "shift_operator" 9156 [(match_operand:SI 3 "s_register_operand" "r") 9157 (match_operand:SI 4 "const_shift_operand" "n")])))) 9158 (set (match_operand:SI 0 "s_register_operand" "=r") 9159 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 9160 (match_dup 4)])))] 9161 "TARGET_ARM 9162 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9163 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9164 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 9165 "ldr%?b\\t%5, [%0, -%3%S2]!" 9166 [(set_attr "type" "load") 9167 (set_attr "predicable" "yes")] 9168) 9169 9170(define_insn "*strsi_shiftpreinc" 9171 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator" 9172 [(match_operand:SI 3 "s_register_operand" "r") 9173 (match_operand:SI 4 "const_shift_operand" "n")]) 9174 (match_operand:SI 1 "s_register_operand" "0"))) 9175 (match_operand:SI 5 "s_register_operand" "r")) 9176 (set (match_operand:SI 0 "s_register_operand" "=r") 9177 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 9178 (match_dup 1)))] 9179 "TARGET_ARM 9180 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9181 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9182 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 9183 "str%?\\t%5, [%0, %3%S2]!" 9184 [(set_attr "type" "store1") 9185 (set_attr "predicable" "yes")] 9186) 9187 9188(define_insn "*strsi_shiftpredec" 9189 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 9190 (match_operator:SI 2 "shift_operator" 9191 [(match_operand:SI 3 "s_register_operand" "r") 9192 (match_operand:SI 4 "const_shift_operand" "n")]))) 9193 (match_operand:SI 5 "s_register_operand" "r")) 9194 (set (match_operand:SI 0 "s_register_operand" "=r") 9195 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 9196 (match_dup 4)])))] 9197 "TARGET_ARM 9198 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9199 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9200 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 9201 "str%?\\t%5, [%0, -%3%S2]!" 9202 [(set_attr "type" "store1") 9203 (set_attr "predicable" "yes")] 9204) 9205 9206(define_insn "*loadsi_shiftpreinc" 9207 [(set (match_operand:SI 5 "s_register_operand" "=r") 9208 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator" 9209 [(match_operand:SI 3 "s_register_operand" "r") 9210 (match_operand:SI 4 "const_shift_operand" "n")]) 9211 (match_operand:SI 1 "s_register_operand" "0")))) 9212 (set (match_operand:SI 0 "s_register_operand" "=r") 9213 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 9214 (match_dup 1)))] 9215 "TARGET_ARM 9216 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9217 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9218 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 9219 "ldr%?\\t%5, [%0, %3%S2]!" 9220 [(set_attr "type" "load") 9221 (set_attr "predicable" "yes")] 9222) 9223 9224(define_insn "*loadsi_shiftpredec" 9225 [(set (match_operand:SI 5 "s_register_operand" "=r") 9226 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 9227 (match_operator:SI 2 "shift_operator" 9228 [(match_operand:SI 3 "s_register_operand" "r") 9229 (match_operand:SI 4 "const_shift_operand" "n")])))) 9230 (set (match_operand:SI 0 "s_register_operand" "=r") 9231 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 9232 (match_dup 4)])))] 9233 "TARGET_ARM 9234 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9235 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9236 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 9237 "ldr%?\\t%5, [%0, -%3%S2]!" 9238 [(set_attr "type" "load") 9239 (set_attr "predicable" "yes")]) 9240 9241(define_insn "*loadhi_shiftpreinc" 9242 [(set (match_operand:HI 5 "s_register_operand" "=r") 9243 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator" 9244 [(match_operand:SI 3 "s_register_operand" "r") 9245 (match_operand:SI 4 "const_shift_operand" "n")]) 9246 (match_operand:SI 1 "s_register_operand" "0")))) 9247 (set (match_operand:SI 0 "s_register_operand" "=r") 9248 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 9249 (match_dup 1)))] 9250 "TARGET_ARM 9251 && !BYTES_BIG_ENDIAN 9252 && !TARGET_MMU_TRAPS 9253 && !arm_arch4 9254 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9255 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9256 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 9257 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi" 9258 [(set_attr "type" "load") 9259 (set_attr "predicable" "yes")] 9260) 9261 9262(define_insn "*loadhi_shiftpredec" 9263 [(set (match_operand:HI 5 "s_register_operand" "=r") 9264 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 9265 (match_operator:SI 2 "shift_operator" 9266 [(match_operand:SI 3 "s_register_operand" "r") 9267 (match_operand:SI 4 "const_shift_operand" "n")])))) 9268 (set (match_operand:SI 0 "s_register_operand" "=r") 9269 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 9270 (match_dup 4)])))] 9271 "TARGET_ARM 9272 && !BYTES_BIG_ENDIAN 9273 && !TARGET_MMU_TRAPS 9274 && !arm_arch4 9275 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9276 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9277 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 9278 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi" 9279 [(set_attr "type" "load") 9280 (set_attr "predicable" "yes")] 9281) 9282 9283; It can also support extended post-inc expressions, but combine doesn't 9284; try these.... 9285; It doesn't seem worth adding peepholes for anything but the most common 9286; cases since, unlike combine, the increment must immediately follow the load 9287; for this pattern to match. 9288; We must watch to see that the source/destination register isn't also the 9289; same as the base address register, and that if the index is a register, 9290; that it is not the same as the base address register. In such cases the 9291; instruction that we would generate would have UNPREDICTABLE behavior so 9292; we cannot use it. 9293 9294(define_peephole 9295 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r")) 9296 (match_operand:QI 2 "s_register_operand" "r")) 9297 (set (match_dup 0) 9298 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))] 9299 "TARGET_ARM 9300 && (REGNO (operands[2]) != REGNO (operands[0])) 9301 && (GET_CODE (operands[1]) != REG 9302 || (REGNO (operands[1]) != REGNO (operands[0])))" 9303 "str%?b\\t%2, [%0], %1" 9304) 9305 9306(define_peephole 9307 [(set (match_operand:QI 0 "s_register_operand" "=r") 9308 (mem:QI (match_operand:SI 1 "s_register_operand" "+r"))) 9309 (set (match_dup 1) 9310 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))] 9311 "TARGET_ARM 9312 && REGNO (operands[0]) != REGNO(operands[1]) 9313 && (GET_CODE (operands[2]) != REG 9314 || REGNO(operands[0]) != REGNO (operands[2]))" 9315 "ldr%?b\\t%0, [%1], %2" 9316) 9317 9318(define_peephole 9319 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r")) 9320 (match_operand:SI 2 "s_register_operand" "r")) 9321 (set (match_dup 0) 9322 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))] 9323 "TARGET_ARM 9324 && (REGNO (operands[2]) != REGNO (operands[0])) 9325 && (GET_CODE (operands[1]) != REG 9326 || (REGNO (operands[1]) != REGNO (operands[0])))" 9327 "str%?\\t%2, [%0], %1" 9328) 9329 9330(define_peephole 9331 [(set (match_operand:HI 0 "s_register_operand" "=r") 9332 (mem:HI (match_operand:SI 1 "s_register_operand" "+r"))) 9333 (set (match_dup 1) 9334 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))] 9335 "TARGET_ARM 9336 && !BYTES_BIG_ENDIAN 9337 && !TARGET_MMU_TRAPS 9338 && !arm_arch4 9339 && REGNO (operands[0]) != REGNO(operands[1]) 9340 && (GET_CODE (operands[2]) != REG 9341 || REGNO(operands[0]) != REGNO (operands[2]))" 9342 "ldr%?\\t%0, [%1], %2\\t%@ loadhi" 9343) 9344 9345(define_peephole 9346 [(set (match_operand:SI 0 "s_register_operand" "=r") 9347 (mem:SI (match_operand:SI 1 "s_register_operand" "+r"))) 9348 (set (match_dup 1) 9349 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))] 9350 "TARGET_ARM 9351 && REGNO (operands[0]) != REGNO(operands[1]) 9352 && (GET_CODE (operands[2]) != REG 9353 || REGNO(operands[0]) != REGNO (operands[2]))" 9354 "ldr%?\\t%0, [%1], %2" 9355) 9356 9357(define_peephole 9358 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r") 9359 (match_operand:SI 1 "index_operand" "rJ"))) 9360 (match_operand:QI 2 "s_register_operand" "r")) 9361 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))] 9362 "TARGET_ARM 9363 && (REGNO (operands[2]) != REGNO (operands[0])) 9364 && (GET_CODE (operands[1]) != REG 9365 || (REGNO (operands[1]) != REGNO (operands[0])))" 9366 "str%?b\\t%2, [%0, %1]!" 9367) 9368 9369(define_peephole 9370 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator" 9371 [(match_operand:SI 0 "s_register_operand" "r") 9372 (match_operand:SI 1 "const_int_operand" "n")]) 9373 (match_operand:SI 2 "s_register_operand" "+r"))) 9374 (match_operand:QI 3 "s_register_operand" "r")) 9375 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)]) 9376 (match_dup 2)))] 9377 "TARGET_ARM 9378 && (REGNO (operands[3]) != REGNO (operands[2])) 9379 && (REGNO (operands[0]) != REGNO (operands[2]))" 9380 "str%?b\\t%3, [%2, %0%S4]!" 9381) 9382 9383; This pattern is never tried by combine, so do it as a peephole 9384 9385(define_peephole2 9386 [(set (match_operand:SI 0 "s_register_operand" "") 9387 (match_operand:SI 1 "s_register_operand" "")) 9388 (set (reg:CC CC_REGNUM) 9389 (compare:CC (match_dup 1) (const_int 0)))] 9390 "TARGET_ARM 9391 && (!TARGET_CIRRUS 9392 || (!cirrus_fp_register (operands[0], SImode) 9393 && !cirrus_fp_register (operands[1], SImode))) 9394 " 9395 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0))) 9396 (set (match_dup 0) (match_dup 1))])] 9397 "" 9398) 9399 9400; Peepholes to spot possible load- and store-multiples, if the ordering is 9401; reversed, check that the memory references aren't volatile. 9402 9403(define_peephole 9404 [(set (match_operand:SI 0 "s_register_operand" "=r") 9405 (match_operand:SI 4 "memory_operand" "m")) 9406 (set (match_operand:SI 1 "s_register_operand" "=r") 9407 (match_operand:SI 5 "memory_operand" "m")) 9408 (set (match_operand:SI 2 "s_register_operand" "=r") 9409 (match_operand:SI 6 "memory_operand" "m")) 9410 (set (match_operand:SI 3 "s_register_operand" "=r") 9411 (match_operand:SI 7 "memory_operand" "m"))] 9412 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)" 9413 "* 9414 return emit_ldm_seq (operands, 4); 9415 " 9416) 9417 9418(define_peephole 9419 [(set (match_operand:SI 0 "s_register_operand" "=r") 9420 (match_operand:SI 3 "memory_operand" "m")) 9421 (set (match_operand:SI 1 "s_register_operand" "=r") 9422 (match_operand:SI 4 "memory_operand" "m")) 9423 (set (match_operand:SI 2 "s_register_operand" "=r") 9424 (match_operand:SI 5 "memory_operand" "m"))] 9425 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)" 9426 "* 9427 return emit_ldm_seq (operands, 3); 9428 " 9429) 9430 9431(define_peephole 9432 [(set (match_operand:SI 0 "s_register_operand" "=r") 9433 (match_operand:SI 2 "memory_operand" "m")) 9434 (set (match_operand:SI 1 "s_register_operand" "=r") 9435 (match_operand:SI 3 "memory_operand" "m"))] 9436 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)" 9437 "* 9438 return emit_ldm_seq (operands, 2); 9439 " 9440) 9441 9442(define_peephole 9443 [(set (match_operand:SI 4 "memory_operand" "=m") 9444 (match_operand:SI 0 "s_register_operand" "r")) 9445 (set (match_operand:SI 5 "memory_operand" "=m") 9446 (match_operand:SI 1 "s_register_operand" "r")) 9447 (set (match_operand:SI 6 "memory_operand" "=m") 9448 (match_operand:SI 2 "s_register_operand" "r")) 9449 (set (match_operand:SI 7 "memory_operand" "=m") 9450 (match_operand:SI 3 "s_register_operand" "r"))] 9451 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)" 9452 "* 9453 return emit_stm_seq (operands, 4); 9454 " 9455) 9456 9457(define_peephole 9458 [(set (match_operand:SI 3 "memory_operand" "=m") 9459 (match_operand:SI 0 "s_register_operand" "r")) 9460 (set (match_operand:SI 4 "memory_operand" "=m") 9461 (match_operand:SI 1 "s_register_operand" "r")) 9462 (set (match_operand:SI 5 "memory_operand" "=m") 9463 (match_operand:SI 2 "s_register_operand" "r"))] 9464 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)" 9465 "* 9466 return emit_stm_seq (operands, 3); 9467 " 9468) 9469 9470(define_peephole 9471 [(set (match_operand:SI 2 "memory_operand" "=m") 9472 (match_operand:SI 0 "s_register_operand" "r")) 9473 (set (match_operand:SI 3 "memory_operand" "=m") 9474 (match_operand:SI 1 "s_register_operand" "r"))] 9475 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)" 9476 "* 9477 return emit_stm_seq (operands, 2); 9478 " 9479) 9480 9481(define_split 9482 [(set (match_operand:SI 0 "s_register_operand" "") 9483 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "") 9484 (const_int 0)) 9485 (neg:SI (match_operator:SI 2 "arm_comparison_operator" 9486 [(match_operand:SI 3 "s_register_operand" "") 9487 (match_operand:SI 4 "arm_rhs_operand" "")])))) 9488 (clobber (match_operand:SI 5 "s_register_operand" ""))] 9489 "TARGET_ARM" 9490 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31)))) 9491 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 9492 (match_dup 5)))] 9493 "" 9494) 9495 9496;; This split can be used because CC_Z mode implies that the following 9497;; branch will be an equality, or an unsigned inequality, so the sign 9498;; extension is not needed. 9499 9500(define_split 9501 [(set (reg:CC_Z CC_REGNUM) 9502 (compare:CC_Z 9503 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0) 9504 (const_int 24)) 9505 (match_operand 1 "const_int_operand" ""))) 9506 (clobber (match_scratch:SI 2 ""))] 9507 "TARGET_ARM 9508 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) 9509 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)" 9510 [(set (match_dup 2) (zero_extend:SI (match_dup 0))) 9511 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))] 9512 " 9513 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24); 9514 " 9515) 9516 9517(define_expand "prologue" 9518 [(clobber (const_int 0))] 9519 "TARGET_EITHER" 9520 "if (TARGET_ARM) 9521 arm_expand_prologue (); 9522 else 9523 thumb_expand_prologue (); 9524 DONE; 9525 " 9526) 9527 9528(define_expand "epilogue" 9529 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)] 9530 "TARGET_EITHER" 9531 " 9532 if (TARGET_THUMB) 9533 thumb_expand_epilogue (); 9534 else if (USE_RETURN_INSN (FALSE)) 9535 { 9536 emit_jump_insn (gen_return ()); 9537 DONE; 9538 } 9539 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode, 9540 gen_rtvec (1, 9541 gen_rtx_RETURN (VOIDmode)), 9542 VUNSPEC_EPILOGUE)); 9543 DONE; 9544 " 9545) 9546 9547;; Note - although unspec_volatile's USE all hard registers, 9548;; USEs are ignored after relaod has completed. Thus we need 9549;; to add an unspec of the link register to ensure that flow 9550;; does not think that it is unused by the sibcall branch that 9551;; will replace the standard function epilogue. 9552(define_insn "sibcall_epilogue" 9553 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE) 9554 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])] 9555 "TARGET_ARM" 9556 "* 9557 if (use_return_insn (FALSE, next_nonnote_insn (insn))) 9558 return output_return_instruction (const_true_rtx, FALSE, FALSE); 9559 return arm_output_epilogue (next_nonnote_insn (insn)); 9560 " 9561;; Length is absolute worst case 9562 [(set_attr "length" "44") 9563 (set_attr "type" "block") 9564 ;; We don't clobber the conditions, but the potential length of this 9565 ;; operation is sufficient to make conditionalizing the sequence 9566 ;; unlikely to be profitable. 9567 (set_attr "conds" "clob")] 9568) 9569 9570(define_insn "*epilogue_insns" 9571 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)] 9572 "TARGET_EITHER" 9573 "* 9574 if (TARGET_ARM) 9575 return arm_output_epilogue (NULL); 9576 else /* TARGET_THUMB */ 9577 return thumb_unexpanded_epilogue (); 9578 " 9579 ; Length is absolute worst case 9580 [(set_attr "length" "44") 9581 (set_attr "type" "block") 9582 ;; We don't clobber the conditions, but the potential length of this 9583 ;; operation is sufficient to make conditionalizing the sequence 9584 ;; unlikely to be profitable. 9585 (set_attr "conds" "clob")] 9586) 9587 9588(define_expand "eh_epilogue" 9589 [(use (match_operand:SI 0 "register_operand" "")) 9590 (use (match_operand:SI 1 "register_operand" "")) 9591 (use (match_operand:SI 2 "register_operand" ""))] 9592 "TARGET_EITHER" 9593 " 9594 { 9595 cfun->machine->eh_epilogue_sp_ofs = operands[1]; 9596 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2) 9597 { 9598 rtx ra = gen_rtx_REG (Pmode, 2); 9599 9600 emit_move_insn (ra, operands[2]); 9601 operands[2] = ra; 9602 } 9603 /* This is a hack -- we may have crystalized the function type too 9604 early. */ 9605 cfun->machine->func_type = 0; 9606 }" 9607) 9608 9609;; This split is only used during output to reduce the number of patterns 9610;; that need assembler instructions adding to them. We allowed the setting 9611;; of the conditions to be implicit during rtl generation so that 9612;; the conditional compare patterns would work. However this conflicts to 9613;; some extent with the conditional data operations, so we have to split them 9614;; up again here. 9615 9616(define_split 9617 [(set (match_operand:SI 0 "s_register_operand" "") 9618 (if_then_else:SI (match_operator 1 "arm_comparison_operator" 9619 [(match_operand 2 "" "") (match_operand 3 "" "")]) 9620 (match_dup 0) 9621 (match_operand 4 "" ""))) 9622 (clobber (reg:CC CC_REGNUM))] 9623 "TARGET_ARM && reload_completed" 9624 [(set (match_dup 5) (match_dup 6)) 9625 (cond_exec (match_dup 7) 9626 (set (match_dup 0) (match_dup 4)))] 9627 " 9628 { 9629 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 9630 operands[2], operands[3]); 9631 enum rtx_code rc = GET_CODE (operands[1]); 9632 9633 operands[5] = gen_rtx_REG (mode, CC_REGNUM); 9634 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]); 9635 if (mode == CCFPmode || mode == CCFPEmode) 9636 rc = reverse_condition_maybe_unordered (rc); 9637 else 9638 rc = reverse_condition (rc); 9639 9640 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx); 9641 }" 9642) 9643 9644(define_split 9645 [(set (match_operand:SI 0 "s_register_operand" "") 9646 (if_then_else:SI (match_operator 1 "arm_comparison_operator" 9647 [(match_operand 2 "" "") (match_operand 3 "" "")]) 9648 (match_operand 4 "" "") 9649 (match_dup 0))) 9650 (clobber (reg:CC CC_REGNUM))] 9651 "TARGET_ARM && reload_completed" 9652 [(set (match_dup 5) (match_dup 6)) 9653 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)]) 9654 (set (match_dup 0) (match_dup 4)))] 9655 " 9656 { 9657 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 9658 operands[2], operands[3]); 9659 9660 operands[5] = gen_rtx_REG (mode, CC_REGNUM); 9661 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]); 9662 }" 9663) 9664 9665(define_split 9666 [(set (match_operand:SI 0 "s_register_operand" "") 9667 (if_then_else:SI (match_operator 1 "arm_comparison_operator" 9668 [(match_operand 2 "" "") (match_operand 3 "" "")]) 9669 (match_operand 4 "" "") 9670 (match_operand 5 "" ""))) 9671 (clobber (reg:CC CC_REGNUM))] 9672 "TARGET_ARM && reload_completed" 9673 [(set (match_dup 6) (match_dup 7)) 9674 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)]) 9675 (set (match_dup 0) (match_dup 4))) 9676 (cond_exec (match_dup 8) 9677 (set (match_dup 0) (match_dup 5)))] 9678 " 9679 { 9680 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 9681 operands[2], operands[3]); 9682 enum rtx_code rc = GET_CODE (operands[1]); 9683 9684 operands[6] = gen_rtx_REG (mode, CC_REGNUM); 9685 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]); 9686 if (mode == CCFPmode || mode == CCFPEmode) 9687 rc = reverse_condition_maybe_unordered (rc); 9688 else 9689 rc = reverse_condition (rc); 9690 9691 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx); 9692 }" 9693) 9694 9695(define_split 9696 [(set (match_operand:SI 0 "s_register_operand" "") 9697 (if_then_else:SI (match_operator 1 "arm_comparison_operator" 9698 [(match_operand:SI 2 "s_register_operand" "") 9699 (match_operand:SI 3 "arm_add_operand" "")]) 9700 (match_operand:SI 4 "arm_rhs_operand" "") 9701 (not:SI 9702 (match_operand:SI 5 "s_register_operand" "")))) 9703 (clobber (reg:CC CC_REGNUM))] 9704 "TARGET_ARM && reload_completed" 9705 [(set (match_dup 6) (match_dup 7)) 9706 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)]) 9707 (set (match_dup 0) (match_dup 4))) 9708 (cond_exec (match_dup 8) 9709 (set (match_dup 0) (not:SI (match_dup 5))))] 9710 " 9711 { 9712 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 9713 operands[2], operands[3]); 9714 enum rtx_code rc = GET_CODE (operands[1]); 9715 9716 operands[6] = gen_rtx_REG (mode, CC_REGNUM); 9717 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]); 9718 if (mode == CCFPmode || mode == CCFPEmode) 9719 rc = reverse_condition_maybe_unordered (rc); 9720 else 9721 rc = reverse_condition (rc); 9722 9723 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx); 9724 }" 9725) 9726 9727(define_insn "*cond_move_not" 9728 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 9729 (if_then_else:SI (match_operator 4 "arm_comparison_operator" 9730 [(match_operand 3 "cc_register" "") (const_int 0)]) 9731 (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 9732 (not:SI 9733 (match_operand:SI 2 "s_register_operand" "r,r"))))] 9734 "TARGET_ARM" 9735 "@ 9736 mvn%D4\\t%0, %2 9737 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2" 9738 [(set_attr "conds" "use") 9739 (set_attr "length" "4,8")] 9740) 9741 9742;; The next two patterns occur when an AND operation is followed by a 9743;; scc insn sequence 9744 9745(define_insn "*sign_extract_onebit" 9746 [(set (match_operand:SI 0 "s_register_operand" "=r") 9747 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r") 9748 (const_int 1) 9749 (match_operand:SI 2 "const_int_operand" "n"))) 9750 (clobber (reg:CC CC_REGNUM))] 9751 "TARGET_ARM" 9752 "* 9753 operands[2] = GEN_INT (1 << INTVAL (operands[2])); 9754 output_asm_insn (\"ands\\t%0, %1, %2\", operands); 9755 return \"mvnne\\t%0, #0\"; 9756 " 9757 [(set_attr "conds" "clob") 9758 (set_attr "length" "8")] 9759) 9760 9761(define_insn "*not_signextract_onebit" 9762 [(set (match_operand:SI 0 "s_register_operand" "=r") 9763 (not:SI 9764 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r") 9765 (const_int 1) 9766 (match_operand:SI 2 "const_int_operand" "n")))) 9767 (clobber (reg:CC CC_REGNUM))] 9768 "TARGET_ARM" 9769 "* 9770 operands[2] = GEN_INT (1 << INTVAL (operands[2])); 9771 output_asm_insn (\"tst\\t%1, %2\", operands); 9772 output_asm_insn (\"mvneq\\t%0, #0\", operands); 9773 return \"movne\\t%0, #0\"; 9774 " 9775 [(set_attr "conds" "clob") 9776 (set_attr "length" "12")] 9777) 9778 9779;; Push multiple registers to the stack. Registers are in parallel (use ...) 9780;; expressions. For simplicity, the first register is also in the unspec 9781;; part. 9782(define_insn "*push_multi" 9783 [(match_parallel 2 "multi_register_push" 9784 [(set (match_operand:BLK 0 "memory_operand" "=m") 9785 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 9786 UNSPEC_PUSH_MULT))])] 9787 "TARGET_ARM" 9788 "* 9789 { 9790 int num_saves = XVECLEN (operands[2], 0); 9791 9792 /* For the StrongARM at least it is faster to 9793 use STR to store only a single register. */ 9794 if (num_saves == 1) 9795 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands); 9796 else 9797 { 9798 int i; 9799 char pattern[100]; 9800 9801 strcpy (pattern, \"stmfd\\t%m0!, {%1\"); 9802 9803 for (i = 1; i < num_saves; i++) 9804 { 9805 strcat (pattern, \", %|\"); 9806 strcat (pattern, 9807 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]); 9808 } 9809 9810 strcat (pattern, \"}\"); 9811 output_asm_insn (pattern, operands); 9812 } 9813 9814 return \"\"; 9815 }" 9816 [(set_attr "type" "store4")] 9817) 9818 9819(define_insn "stack_tie" 9820 [(set (mem:BLK (scratch)) 9821 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r") 9822 (match_operand:SI 1 "s_register_operand" "r")] 9823 UNSPEC_PRLG_STK))] 9824 "" 9825 "" 9826 [(set_attr "length" "0")] 9827) 9828 9829;; Similarly for the floating point registers 9830(define_insn "*push_fp_multi" 9831 [(match_parallel 2 "multi_register_push" 9832 [(set (match_operand:BLK 0 "memory_operand" "=m") 9833 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")] 9834 UNSPEC_PUSH_MULT))])] 9835 "TARGET_ARM" 9836 "* 9837 { 9838 char pattern[100]; 9839 9840 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0)); 9841 output_asm_insn (pattern, operands); 9842 return \"\"; 9843 }" 9844 [(set_attr "type" "f_store")] 9845) 9846 9847;; Special patterns for dealing with the constant pool 9848 9849(define_insn "align_4" 9850 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)] 9851 "TARGET_EITHER" 9852 "* 9853 assemble_align (32); 9854 return \"\"; 9855 " 9856) 9857 9858(define_insn "align_8" 9859 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)] 9860 "TARGET_REALLY_IWMMXT" 9861 "* 9862 assemble_align (64); 9863 return \"\"; 9864 " 9865) 9866 9867(define_insn "consttable_end" 9868 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)] 9869 "TARGET_EITHER" 9870 "* 9871 making_const_table = FALSE; 9872 return \"\"; 9873 " 9874) 9875 9876(define_insn "consttable_1" 9877 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)] 9878 "TARGET_THUMB" 9879 "* 9880 making_const_table = TRUE; 9881 assemble_integer (operands[0], 1, BITS_PER_WORD, 1); 9882 assemble_zeros (3); 9883 return \"\"; 9884 " 9885 [(set_attr "length" "4")] 9886) 9887 9888(define_insn "consttable_2" 9889 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)] 9890 "TARGET_THUMB" 9891 "* 9892 making_const_table = TRUE; 9893 assemble_integer (operands[0], 2, BITS_PER_WORD, 1); 9894 assemble_zeros (2); 9895 return \"\"; 9896 " 9897 [(set_attr "length" "4")] 9898) 9899 9900(define_insn "consttable_4" 9901 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)] 9902 "TARGET_EITHER" 9903 "* 9904 { 9905 making_const_table = TRUE; 9906 switch (GET_MODE_CLASS (GET_MODE (operands[0]))) 9907 { 9908 case MODE_FLOAT: 9909 { 9910 REAL_VALUE_TYPE r; 9911 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]); 9912 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD); 9913 break; 9914 } 9915 default: 9916 assemble_integer (operands[0], 4, BITS_PER_WORD, 1); 9917 break; 9918 } 9919 return \"\"; 9920 }" 9921 [(set_attr "length" "4")] 9922) 9923 9924(define_insn "consttable_8" 9925 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)] 9926 "TARGET_EITHER" 9927 "* 9928 { 9929 making_const_table = TRUE; 9930 switch (GET_MODE_CLASS (GET_MODE (operands[0]))) 9931 { 9932 case MODE_FLOAT: 9933 { 9934 REAL_VALUE_TYPE r; 9935 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]); 9936 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD); 9937 break; 9938 } 9939 default: 9940 assemble_integer (operands[0], 8, BITS_PER_WORD, 1); 9941 break; 9942 } 9943 return \"\"; 9944 }" 9945 [(set_attr "length" "8")] 9946) 9947 9948;; Miscellaneous Thumb patterns 9949 9950(define_expand "tablejump" 9951 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "")) 9952 (use (label_ref (match_operand 1 "" "")))])] 9953 "TARGET_THUMB" 9954 " 9955 if (flag_pic) 9956 { 9957 /* Hopefully, CSE will eliminate this copy. */ 9958 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1])); 9959 rtx reg2 = gen_reg_rtx (SImode); 9960 9961 emit_insn (gen_addsi3 (reg2, operands[0], reg1)); 9962 operands[0] = reg2; 9963 } 9964 " 9965) 9966 9967(define_insn "*thumb_tablejump" 9968 [(set (pc) (match_operand:SI 0 "register_operand" "l*r")) 9969 (use (label_ref (match_operand 1 "" "")))] 9970 "TARGET_THUMB" 9971 "mov\\t%|pc, %0" 9972 [(set_attr "length" "2")] 9973) 9974 9975;; V5 Instructions, 9976 9977(define_insn "clzsi2" 9978 [(set (match_operand:SI 0 "s_register_operand" "=r") 9979 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))] 9980 "TARGET_ARM && arm_arch5" 9981 "clz%?\\t%0, %1" 9982 [(set_attr "predicable" "yes")]) 9983 9984(define_expand "ffssi2" 9985 [(set (match_operand:SI 0 "s_register_operand" "") 9986 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))] 9987 "TARGET_ARM && arm_arch5" 9988 " 9989 { 9990 rtx t1, t2, t3; 9991 9992 t1 = gen_reg_rtx (SImode); 9993 t2 = gen_reg_rtx (SImode); 9994 t3 = gen_reg_rtx (SImode); 9995 9996 emit_insn (gen_negsi2 (t1, operands[1])); 9997 emit_insn (gen_andsi3 (t2, operands[1], t1)); 9998 emit_insn (gen_clzsi2 (t3, t2)); 9999 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3)); 10000 DONE; 10001 }" 10002) 10003 10004(define_expand "ctzsi2" 10005 [(set (match_operand:SI 0 "s_register_operand" "") 10006 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))] 10007 "TARGET_ARM && arm_arch5" 10008 " 10009 { 10010 rtx t1, t2, t3; 10011 10012 t1 = gen_reg_rtx (SImode); 10013 t2 = gen_reg_rtx (SImode); 10014 t3 = gen_reg_rtx (SImode); 10015 10016 emit_insn (gen_negsi2 (t1, operands[1])); 10017 emit_insn (gen_andsi3 (t2, operands[1], t1)); 10018 emit_insn (gen_clzsi2 (t3, t2)); 10019 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3)); 10020 DONE; 10021 }" 10022) 10023 10024;; V5E instructions. 10025 10026(define_insn "prefetch" 10027 [(prefetch (match_operand:SI 0 "address_operand" "p") 10028 (match_operand:SI 1 "" "") 10029 (match_operand:SI 2 "" ""))] 10030 "TARGET_ARM && arm_arch5e" 10031 "pld\\t%a0") 10032 10033;; General predication pattern 10034 10035(define_cond_exec 10036 [(match_operator 0 "arm_comparison_operator" 10037 [(match_operand 1 "cc_register" "") 10038 (const_int 0)])] 10039 "TARGET_ARM" 10040 "" 10041) 10042 10043(define_insn "prologue_use" 10044 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)] 10045 "" 10046 "%@ %0 needed for prologue" 10047) 10048 10049;; Load the FPA co-processor patterns 10050(include "fpa.md") 10051;; Load the Maverick co-processor patterns 10052(include "cirrus.md") 10053;; Load the Intel Wireless Multimedia Extension patterns 10054(include "iwmmxt.md") 10055