arm.md revision 146895
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,l")) 5964 (match_operand:SI 2 "s_register_operand" "0,1,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,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,&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 <= 2) 5977 { 5978 output_asm_insn (\"bic\\t%1, %3\", operands); 5979 /* It's ok if OP0 is a lo-reg, even though the mov will set the 5980 conditions again, since we're only testing for equality. */ 5981 output_asm_insn (\"mov\\t%0, %1\", operands); 5982 } 5983 else 5984 { 5985 output_asm_insn (\"bic\\t%1, %3\", operands); 5986 output_asm_insn (\"str\\t%1, %0\", operands); 5987 } 5988 5989 switch (get_attr_length (insn) - (which_alternative ? 2 : 0)) 5990 { 5991 case 4: return \"b%d5\\t%l4\"; 5992 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\"; 5993 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\"; 5994 } 5995 }" 5996 [(set (attr "far_jump") 5997 (if_then_else 5998 (ior (and (eq (symbol_ref ("which_alternative")) 5999 (const_int 0)) 6000 (eq_attr "length" "8")) 6001 (eq_attr "length" "10")) 6002 (const_string "yes") 6003 (const_string "no"))) 6004 (set (attr "length") 6005 (if_then_else 6006 (eq (symbol_ref ("which_alternative")) 6007 (const_int 0)) 6008 (if_then_else 6009 (and (ge (minus (match_dup 4) (pc)) (const_int -250)) 6010 (le (minus (match_dup 4) (pc)) (const_int 256))) 6011 (const_int 4) 6012 (if_then_else 6013 (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) 6014 (le (minus (match_dup 4) (pc)) (const_int 2048))) 6015 (const_int 6) 6016 (const_int 8))) 6017 (if_then_else 6018 (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 6019 (le (minus (match_dup 4) (pc)) (const_int 256))) 6020 (const_int 6) 6021 (if_then_else 6022 (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 6023 (le (minus (match_dup 4) (pc)) (const_int 2048))) 6024 (const_int 8) 6025 (const_int 10)))))] 6026) 6027 6028(define_insn "*cbranchne_decr1" 6029 [(set (pc) 6030 (if_then_else (match_operator 3 "equality_operator" 6031 [(match_operand:SI 2 "s_register_operand" "l,l,1,l") 6032 (const_int 0)]) 6033 (label_ref (match_operand 4 "" "")) 6034 (pc))) 6035 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") 6036 (plus:SI (match_dup 2) (const_int -1))) 6037 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] 6038 "TARGET_THUMB" 6039 "* 6040 { 6041 rtx cond[2]; 6042 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE 6043 ? GEU : LTU), 6044 VOIDmode, operands[2], const1_rtx); 6045 cond[1] = operands[4]; 6046 6047 if (which_alternative == 0) 6048 output_asm_insn (\"sub\\t%0, %2, #1\", operands); 6049 else if (which_alternative == 1) 6050 { 6051 /* We must provide an alternative for a hi reg because reload 6052 cannot handle output reloads on a jump instruction, but we 6053 can't subtract into that. Fortunately a mov from lo to hi 6054 does not clobber the condition codes. */ 6055 output_asm_insn (\"sub\\t%1, %2, #1\", operands); 6056 output_asm_insn (\"mov\\t%0, %1\", operands); 6057 } 6058 else 6059 { 6060 /* Similarly, but the target is memory. */ 6061 output_asm_insn (\"sub\\t%1, %2, #1\", operands); 6062 output_asm_insn (\"str\\t%1, %0\", operands); 6063 } 6064 6065 switch (get_attr_length (insn) - (which_alternative ? 2 : 0)) 6066 { 6067 case 4: 6068 output_asm_insn (\"b%d0\\t%l1\", cond); 6069 return \"\"; 6070 case 6: 6071 output_asm_insn (\"b%D0\\t.LCB%=\", cond); 6072 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\"; 6073 default: 6074 output_asm_insn (\"b%D0\\t.LCB%=\", cond); 6075 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\"; 6076 } 6077 } 6078 " 6079 [(set (attr "far_jump") 6080 (if_then_else 6081 (ior (and (eq (symbol_ref ("which_alternative")) 6082 (const_int 0)) 6083 (eq_attr "length" "8")) 6084 (eq_attr "length" "10")) 6085 (const_string "yes") 6086 (const_string "no"))) 6087 (set_attr_alternative "length" 6088 [ 6089 ;; Alternative 0 6090 (if_then_else 6091 (and (ge (minus (match_dup 4) (pc)) (const_int -250)) 6092 (le (minus (match_dup 4) (pc)) (const_int 256))) 6093 (const_int 4) 6094 (if_then_else 6095 (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) 6096 (le (minus (match_dup 4) (pc)) (const_int 2048))) 6097 (const_int 6) 6098 (const_int 8))) 6099 ;; Alternative 1 6100 (if_then_else 6101 (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 6102 (le (minus (match_dup 4) (pc)) (const_int 256))) 6103 (const_int 6) 6104 (if_then_else 6105 (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 6106 (le (minus (match_dup 4) (pc)) (const_int 2048))) 6107 (const_int 8) 6108 (const_int 10))) 6109 ;; Alternative 2 6110 (if_then_else 6111 (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 6112 (le (minus (match_dup 4) (pc)) (const_int 256))) 6113 (const_int 6) 6114 (if_then_else 6115 (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 6116 (le (minus (match_dup 4) (pc)) (const_int 2048))) 6117 (const_int 8) 6118 (const_int 10))) 6119 ;; Alternative 3 6120 (if_then_else 6121 (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 6122 (le (minus (match_dup 4) (pc)) (const_int 256))) 6123 (const_int 6) 6124 (if_then_else 6125 (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 6126 (le (minus (match_dup 4) (pc)) (const_int 2048))) 6127 (const_int 8) 6128 (const_int 10)))])] 6129) 6130 6131(define_insn "*addsi3_cbranch" 6132 [(set (pc) 6133 (if_then_else 6134 (match_operator 4 "comparison_operator" 6135 [(plus:SI 6136 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1") 6137 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ")) 6138 (const_int 0)]) 6139 (label_ref (match_operand 5 "" "")) 6140 (pc))) 6141 (set 6142 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m") 6143 (plus:SI (match_dup 2) (match_dup 3))) 6144 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))] 6145 "TARGET_THUMB 6146 && (GET_CODE (operands[4]) == EQ 6147 || GET_CODE (operands[4]) == NE 6148 || GET_CODE (operands[4]) == GE 6149 || GET_CODE (operands[4]) == LT)" 6150 "* 6151 { 6152 rtx cond[3]; 6153 6154 6155 cond[0] = (which_alternative < 3) ? operands[0] : operands[1]; 6156 cond[1] = operands[2]; 6157 cond[2] = operands[3]; 6158 6159 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0) 6160 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond); 6161 else 6162 output_asm_insn (\"add\\t%0, %1, %2\", cond); 6163 6164 if (which_alternative >= 3 6165 && which_alternative < 4) 6166 output_asm_insn (\"mov\\t%0, %1\", operands); 6167 else if (which_alternative >= 4) 6168 output_asm_insn (\"str\\t%1, %0\", operands); 6169 6170 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0)) 6171 { 6172 case 4: 6173 return \"b%d4\\t%l5\"; 6174 case 6: 6175 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\"; 6176 default: 6177 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\"; 6178 } 6179 } 6180 " 6181 [(set (attr "far_jump") 6182 (if_then_else 6183 (ior (and (lt (symbol_ref ("which_alternative")) 6184 (const_int 3)) 6185 (eq_attr "length" "8")) 6186 (eq_attr "length" "10")) 6187 (const_string "yes") 6188 (const_string "no"))) 6189 (set (attr "length") 6190 (if_then_else 6191 (lt (symbol_ref ("which_alternative")) 6192 (const_int 3)) 6193 (if_then_else 6194 (and (ge (minus (match_dup 5) (pc)) (const_int -250)) 6195 (le (minus (match_dup 5) (pc)) (const_int 256))) 6196 (const_int 4) 6197 (if_then_else 6198 (and (ge (minus (match_dup 5) (pc)) (const_int -2040)) 6199 (le (minus (match_dup 5) (pc)) (const_int 2048))) 6200 (const_int 6) 6201 (const_int 8))) 6202 (if_then_else 6203 (and (ge (minus (match_dup 5) (pc)) (const_int -248)) 6204 (le (minus (match_dup 5) (pc)) (const_int 256))) 6205 (const_int 6) 6206 (if_then_else 6207 (and (ge (minus (match_dup 5) (pc)) (const_int -2038)) 6208 (le (minus (match_dup 5) (pc)) (const_int 2048))) 6209 (const_int 8) 6210 (const_int 10)))))] 6211) 6212 6213(define_insn "*addsi3_cbranch_scratch" 6214 [(set (pc) 6215 (if_then_else 6216 (match_operator 3 "comparison_operator" 6217 [(plus:SI 6218 (match_operand:SI 1 "s_register_operand" "%l,l,l,0") 6219 (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L")) 6220 (const_int 0)]) 6221 (label_ref (match_operand 4 "" "")) 6222 (pc))) 6223 (clobber (match_scratch:SI 0 "=X,X,l,l"))] 6224 "TARGET_THUMB 6225 && (GET_CODE (operands[3]) == EQ 6226 || GET_CODE (operands[3]) == NE 6227 || GET_CODE (operands[3]) == GE 6228 || GET_CODE (operands[3]) == LT)" 6229 "* 6230 { 6231 switch (which_alternative) 6232 { 6233 case 0: 6234 output_asm_insn (\"cmp\t%1, #%n2\", operands); 6235 break; 6236 case 1: 6237 output_asm_insn (\"cmn\t%1, %2\", operands); 6238 break; 6239 case 2: 6240 output_asm_insn (\"add\t%0, %1, %2\", operands); 6241 break; 6242 case 3: 6243 output_asm_insn (\"add\t%0, %0, %2\", operands); 6244 break; 6245 } 6246 6247 switch (get_attr_length (insn)) 6248 { 6249 case 4: 6250 return \"b%d3\\t%l4\"; 6251 case 6: 6252 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\"; 6253 default: 6254 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\"; 6255 } 6256 } 6257 " 6258 [(set (attr "far_jump") 6259 (if_then_else 6260 (eq_attr "length" "8") 6261 (const_string "yes") 6262 (const_string "no"))) 6263 (set (attr "length") 6264 (if_then_else 6265 (and (ge (minus (match_dup 4) (pc)) (const_int -250)) 6266 (le (minus (match_dup 4) (pc)) (const_int 256))) 6267 (const_int 4) 6268 (if_then_else 6269 (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) 6270 (le (minus (match_dup 4) (pc)) (const_int 2048))) 6271 (const_int 6) 6272 (const_int 8))))] 6273) 6274 6275(define_insn "*subsi3_cbranch" 6276 [(set (pc) 6277 (if_then_else 6278 (match_operator 4 "comparison_operator" 6279 [(minus:SI 6280 (match_operand:SI 2 "s_register_operand" "l,l,1,l") 6281 (match_operand:SI 3 "s_register_operand" "l,l,l,l")) 6282 (const_int 0)]) 6283 (label_ref (match_operand 5 "" "")) 6284 (pc))) 6285 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") 6286 (minus:SI (match_dup 2) (match_dup 3))) 6287 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] 6288 "TARGET_THUMB 6289 && (GET_CODE (operands[4]) == EQ 6290 || GET_CODE (operands[4]) == NE 6291 || GET_CODE (operands[4]) == GE 6292 || GET_CODE (operands[4]) == LT)" 6293 "* 6294 { 6295 if (which_alternative == 0) 6296 output_asm_insn (\"sub\\t%0, %2, %3\", operands); 6297 else if (which_alternative == 1) 6298 { 6299 /* We must provide an alternative for a hi reg because reload 6300 cannot handle output reloads on a jump instruction, but we 6301 can't subtract into that. Fortunately a mov from lo to hi 6302 does not clobber the condition codes. */ 6303 output_asm_insn (\"sub\\t%1, %2, %3\", operands); 6304 output_asm_insn (\"mov\\t%0, %1\", operands); 6305 } 6306 else 6307 { 6308 /* Similarly, but the target is memory. */ 6309 output_asm_insn (\"sub\\t%1, %2, %3\", operands); 6310 output_asm_insn (\"str\\t%1, %0\", operands); 6311 } 6312 6313 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0)) 6314 { 6315 case 4: 6316 return \"b%d4\\t%l5\"; 6317 case 6: 6318 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\"; 6319 default: 6320 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\"; 6321 } 6322 } 6323 " 6324 [(set (attr "far_jump") 6325 (if_then_else 6326 (ior (and (eq (symbol_ref ("which_alternative")) 6327 (const_int 0)) 6328 (eq_attr "length" "8")) 6329 (eq_attr "length" "10")) 6330 (const_string "yes") 6331 (const_string "no"))) 6332 (set (attr "length") 6333 (if_then_else 6334 (eq (symbol_ref ("which_alternative")) 6335 (const_int 0)) 6336 (if_then_else 6337 (and (ge (minus (match_dup 5) (pc)) (const_int -250)) 6338 (le (minus (match_dup 5) (pc)) (const_int 256))) 6339 (const_int 4) 6340 (if_then_else 6341 (and (ge (minus (match_dup 5) (pc)) (const_int -2040)) 6342 (le (minus (match_dup 5) (pc)) (const_int 2048))) 6343 (const_int 6) 6344 (const_int 8))) 6345 (if_then_else 6346 (and (ge (minus (match_dup 5) (pc)) (const_int -248)) 6347 (le (minus (match_dup 5) (pc)) (const_int 256))) 6348 (const_int 6) 6349 (if_then_else 6350 (and (ge (minus (match_dup 5) (pc)) (const_int -2038)) 6351 (le (minus (match_dup 5) (pc)) (const_int 2048))) 6352 (const_int 8) 6353 (const_int 10)))))] 6354) 6355 6356(define_insn "*subsi3_cbranch_scratch" 6357 [(set (pc) 6358 (if_then_else 6359 (match_operator 0 "arm_comparison_operator" 6360 [(minus:SI (match_operand:SI 1 "register_operand" "l") 6361 (match_operand:SI 2 "nonmemory_operand" "l")) 6362 (const_int 0)]) 6363 (label_ref (match_operand 3 "" "")) 6364 (pc)))] 6365 "TARGET_THUMB 6366 && (GET_CODE (operands[0]) == EQ 6367 || GET_CODE (operands[0]) == NE 6368 || GET_CODE (operands[0]) == GE 6369 || GET_CODE (operands[0]) == LT)" 6370 "* 6371 output_asm_insn (\"cmp\\t%1, %2\", operands); 6372 switch (get_attr_length (insn)) 6373 { 6374 case 4: return \"b%d0\\t%l3\"; 6375 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 6376 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 6377 } 6378 " 6379 [(set (attr "far_jump") 6380 (if_then_else 6381 (eq_attr "length" "8") 6382 (const_string "yes") 6383 (const_string "no"))) 6384 (set (attr "length") 6385 (if_then_else 6386 (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 6387 (le (minus (match_dup 3) (pc)) (const_int 256))) 6388 (const_int 4) 6389 (if_then_else 6390 (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 6391 (le (minus (match_dup 3) (pc)) (const_int 2048))) 6392 (const_int 6) 6393 (const_int 8))))] 6394) 6395 6396;; Comparison and test insns 6397 6398(define_expand "cmpsi" 6399 [(match_operand:SI 0 "s_register_operand" "") 6400 (match_operand:SI 1 "arm_add_operand" "")] 6401 "TARGET_ARM" 6402 "{ 6403 arm_compare_op0 = operands[0]; 6404 arm_compare_op1 = operands[1]; 6405 DONE; 6406 }" 6407) 6408 6409(define_expand "cmpsf" 6410 [(match_operand:SF 0 "s_register_operand" "") 6411 (match_operand:SF 1 "fpa_rhs_operand" "")] 6412 "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 6413 " 6414 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode)) 6415 operands[1] = force_reg (SFmode, operands[1]); 6416 6417 arm_compare_op0 = operands[0]; 6418 arm_compare_op1 = operands[1]; 6419 DONE; 6420 " 6421) 6422 6423(define_expand "cmpdf" 6424 [(match_operand:DF 0 "s_register_operand" "") 6425 (match_operand:DF 1 "fpa_rhs_operand" "")] 6426 "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 6427 " 6428 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode)) 6429 operands[1] = force_reg (DFmode, operands[1]); 6430 6431 arm_compare_op0 = operands[0]; 6432 arm_compare_op1 = operands[1]; 6433 DONE; 6434 " 6435) 6436 6437(define_insn "*arm_cmpsi_insn" 6438 [(set (reg:CC CC_REGNUM) 6439 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r") 6440 (match_operand:SI 1 "arm_add_operand" "rI,L")))] 6441 "TARGET_ARM" 6442 "@ 6443 cmp%?\\t%0, %1 6444 cmn%?\\t%0, #%n1" 6445 [(set_attr "conds" "set")] 6446) 6447 6448(define_insn "*cmpsi_shiftsi" 6449 [(set (reg:CC CC_REGNUM) 6450 (compare:CC (match_operand:SI 0 "s_register_operand" "r") 6451 (match_operator:SI 3 "shift_operator" 6452 [(match_operand:SI 1 "s_register_operand" "r") 6453 (match_operand:SI 2 "arm_rhs_operand" "rM")])))] 6454 "TARGET_ARM" 6455 "cmp%?\\t%0, %1%S3" 6456 [(set_attr "conds" "set") 6457 (set_attr "shift" "1") 6458 ] 6459) 6460 6461(define_insn "*cmpsi_shiftsi_swp" 6462 [(set (reg:CC_SWP CC_REGNUM) 6463 (compare:CC_SWP (match_operator:SI 3 "shift_operator" 6464 [(match_operand:SI 1 "s_register_operand" "r") 6465 (match_operand:SI 2 "reg_or_int_operand" "rM")]) 6466 (match_operand:SI 0 "s_register_operand" "r")))] 6467 "TARGET_ARM" 6468 "cmp%?\\t%0, %1%S3" 6469 [(set_attr "conds" "set") 6470 (set_attr "shift" "1") 6471 ] 6472) 6473 6474(define_insn "*cmpsi_neg_shiftsi" 6475 [(set (reg:CC CC_REGNUM) 6476 (compare:CC (match_operand:SI 0 "s_register_operand" "r") 6477 (neg:SI (match_operator:SI 3 "shift_operator" 6478 [(match_operand:SI 1 "s_register_operand" "r") 6479 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))] 6480 "TARGET_ARM" 6481 "cmn%?\\t%0, %1%S3" 6482 [(set_attr "conds" "set") 6483 (set_attr "shift" "1") 6484 ] 6485) 6486 6487;; Cirrus SF compare instruction 6488(define_insn "*cirrus_cmpsf" 6489 [(set (reg:CCFP CC_REGNUM) 6490 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v") 6491 (match_operand:SF 1 "cirrus_fp_register" "v")))] 6492 "TARGET_ARM && TARGET_CIRRUS" 6493 "cfcmps%?\\tr15, %V0, %V1" 6494 [(set_attr "type" "mav_farith") 6495 (set_attr "cirrus" "compare")] 6496) 6497 6498;; Cirrus DF compare instruction 6499(define_insn "*cirrus_cmpdf" 6500 [(set (reg:CCFP CC_REGNUM) 6501 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v") 6502 (match_operand:DF 1 "cirrus_fp_register" "v")))] 6503 "TARGET_ARM && TARGET_CIRRUS" 6504 "cfcmpd%?\\tr15, %V0, %V1" 6505 [(set_attr "type" "mav_farith") 6506 (set_attr "cirrus" "compare")] 6507) 6508 6509;; Cirrus DI compare instruction 6510(define_expand "cmpdi" 6511 [(match_operand:DI 0 "cirrus_fp_register" "") 6512 (match_operand:DI 1 "cirrus_fp_register" "")] 6513 "TARGET_ARM && TARGET_CIRRUS" 6514 "{ 6515 arm_compare_op0 = operands[0]; 6516 arm_compare_op1 = operands[1]; 6517 DONE; 6518 }") 6519 6520(define_insn "*cirrus_cmpdi" 6521 [(set (reg:CC CC_REGNUM) 6522 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v") 6523 (match_operand:DI 1 "cirrus_fp_register" "v")))] 6524 "TARGET_ARM && TARGET_CIRRUS" 6525 "cfcmp64%?\\tr15, %V0, %V1" 6526 [(set_attr "type" "mav_farith") 6527 (set_attr "cirrus" "compare")] 6528) 6529 6530; This insn allows redundant compares to be removed by cse, nothing should 6531; ever appear in the output file since (set (reg x) (reg x)) is a no-op that 6532; is deleted later on. The match_dup will match the mode here, so that 6533; mode changes of the condition codes aren't lost by this even though we don't 6534; specify what they are. 6535 6536(define_insn "*deleted_compare" 6537 [(set (match_operand 0 "cc_register" "") (match_dup 0))] 6538 "TARGET_ARM" 6539 "\\t%@ deleted compare" 6540 [(set_attr "conds" "set") 6541 (set_attr "length" "0")] 6542) 6543 6544 6545;; Conditional branch insns 6546 6547(define_expand "beq" 6548 [(set (pc) 6549 (if_then_else (eq (match_dup 1) (const_int 0)) 6550 (label_ref (match_operand 0 "" "")) 6551 (pc)))] 6552 "TARGET_ARM" 6553 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);" 6554) 6555 6556(define_expand "bne" 6557 [(set (pc) 6558 (if_then_else (ne (match_dup 1) (const_int 0)) 6559 (label_ref (match_operand 0 "" "")) 6560 (pc)))] 6561 "TARGET_ARM" 6562 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);" 6563) 6564 6565(define_expand "bgt" 6566 [(set (pc) 6567 (if_then_else (gt (match_dup 1) (const_int 0)) 6568 (label_ref (match_operand 0 "" "")) 6569 (pc)))] 6570 "TARGET_ARM" 6571 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);" 6572) 6573 6574(define_expand "ble" 6575 [(set (pc) 6576 (if_then_else (le (match_dup 1) (const_int 0)) 6577 (label_ref (match_operand 0 "" "")) 6578 (pc)))] 6579 "TARGET_ARM" 6580 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);" 6581) 6582 6583(define_expand "bge" 6584 [(set (pc) 6585 (if_then_else (ge (match_dup 1) (const_int 0)) 6586 (label_ref (match_operand 0 "" "")) 6587 (pc)))] 6588 "TARGET_ARM" 6589 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);" 6590) 6591 6592(define_expand "blt" 6593 [(set (pc) 6594 (if_then_else (lt (match_dup 1) (const_int 0)) 6595 (label_ref (match_operand 0 "" "")) 6596 (pc)))] 6597 "TARGET_ARM" 6598 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);" 6599) 6600 6601(define_expand "bgtu" 6602 [(set (pc) 6603 (if_then_else (gtu (match_dup 1) (const_int 0)) 6604 (label_ref (match_operand 0 "" "")) 6605 (pc)))] 6606 "TARGET_ARM" 6607 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);" 6608) 6609 6610(define_expand "bleu" 6611 [(set (pc) 6612 (if_then_else (leu (match_dup 1) (const_int 0)) 6613 (label_ref (match_operand 0 "" "")) 6614 (pc)))] 6615 "TARGET_ARM" 6616 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);" 6617) 6618 6619(define_expand "bgeu" 6620 [(set (pc) 6621 (if_then_else (geu (match_dup 1) (const_int 0)) 6622 (label_ref (match_operand 0 "" "")) 6623 (pc)))] 6624 "TARGET_ARM" 6625 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);" 6626) 6627 6628(define_expand "bltu" 6629 [(set (pc) 6630 (if_then_else (ltu (match_dup 1) (const_int 0)) 6631 (label_ref (match_operand 0 "" "")) 6632 (pc)))] 6633 "TARGET_ARM" 6634 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);" 6635) 6636 6637(define_expand "bunordered" 6638 [(set (pc) 6639 (if_then_else (unordered (match_dup 1) (const_int 0)) 6640 (label_ref (match_operand 0 "" "")) 6641 (pc)))] 6642 "TARGET_ARM && TARGET_HARD_FLOAT" 6643 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0, 6644 arm_compare_op1);" 6645) 6646 6647(define_expand "bordered" 6648 [(set (pc) 6649 (if_then_else (ordered (match_dup 1) (const_int 0)) 6650 (label_ref (match_operand 0 "" "")) 6651 (pc)))] 6652 "TARGET_ARM && TARGET_HARD_FLOAT" 6653 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0, 6654 arm_compare_op1);" 6655) 6656 6657(define_expand "bungt" 6658 [(set (pc) 6659 (if_then_else (ungt (match_dup 1) (const_int 0)) 6660 (label_ref (match_operand 0 "" "")) 6661 (pc)))] 6662 "TARGET_ARM && TARGET_HARD_FLOAT" 6663 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);" 6664) 6665 6666(define_expand "bunlt" 6667 [(set (pc) 6668 (if_then_else (unlt (match_dup 1) (const_int 0)) 6669 (label_ref (match_operand 0 "" "")) 6670 (pc)))] 6671 "TARGET_ARM && TARGET_HARD_FLOAT" 6672 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);" 6673) 6674 6675(define_expand "bunge" 6676 [(set (pc) 6677 (if_then_else (unge (match_dup 1) (const_int 0)) 6678 (label_ref (match_operand 0 "" "")) 6679 (pc)))] 6680 "TARGET_ARM && TARGET_HARD_FLOAT" 6681 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);" 6682) 6683 6684(define_expand "bunle" 6685 [(set (pc) 6686 (if_then_else (unle (match_dup 1) (const_int 0)) 6687 (label_ref (match_operand 0 "" "")) 6688 (pc)))] 6689 "TARGET_ARM && TARGET_HARD_FLOAT" 6690 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);" 6691) 6692 6693;; The following two patterns need two branch instructions, since there is 6694;; no single instruction that will handle all cases. 6695(define_expand "buneq" 6696 [(set (pc) 6697 (if_then_else (uneq (match_dup 1) (const_int 0)) 6698 (label_ref (match_operand 0 "" "")) 6699 (pc)))] 6700 "TARGET_ARM && TARGET_HARD_FLOAT" 6701 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);" 6702) 6703 6704(define_expand "bltgt" 6705 [(set (pc) 6706 (if_then_else (ltgt (match_dup 1) (const_int 0)) 6707 (label_ref (match_operand 0 "" "")) 6708 (pc)))] 6709 "TARGET_ARM && TARGET_HARD_FLOAT" 6710 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);" 6711) 6712 6713;; 6714;; Patterns to match conditional branch insns. 6715;; 6716 6717; Special pattern to match UNEQ. 6718(define_insn "*arm_buneq" 6719 [(set (pc) 6720 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0)) 6721 (label_ref (match_operand 0 "" "")) 6722 (pc)))] 6723 "TARGET_ARM && TARGET_HARD_FLOAT" 6724 "* 6725 if (arm_ccfsm_state != 0) 6726 abort (); 6727 6728 return \"bvs\\t%l0\;beq\\t%l0\"; 6729 " 6730 [(set_attr "conds" "jump_clob") 6731 (set_attr "length" "8")] 6732) 6733 6734; Special pattern to match LTGT. 6735(define_insn "*arm_bltgt" 6736 [(set (pc) 6737 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0)) 6738 (label_ref (match_operand 0 "" "")) 6739 (pc)))] 6740 "TARGET_ARM && TARGET_HARD_FLOAT" 6741 "* 6742 if (arm_ccfsm_state != 0) 6743 abort (); 6744 6745 return \"bmi\\t%l0\;bgt\\t%l0\"; 6746 " 6747 [(set_attr "conds" "jump_clob") 6748 (set_attr "length" "8")] 6749) 6750 6751(define_insn "*arm_cond_branch" 6752 [(set (pc) 6753 (if_then_else (match_operator 1 "arm_comparison_operator" 6754 [(match_operand 2 "cc_register" "") (const_int 0)]) 6755 (label_ref (match_operand 0 "" "")) 6756 (pc)))] 6757 "TARGET_ARM" 6758 "* 6759 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) 6760 { 6761 arm_ccfsm_state += 2; 6762 return \"\"; 6763 } 6764 return \"b%d1\\t%l0\"; 6765 " 6766 [(set_attr "conds" "use")] 6767) 6768 6769; Special pattern to match reversed UNEQ. 6770(define_insn "*arm_buneq_reversed" 6771 [(set (pc) 6772 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0)) 6773 (pc) 6774 (label_ref (match_operand 0 "" ""))))] 6775 "TARGET_ARM && TARGET_HARD_FLOAT" 6776 "* 6777 if (arm_ccfsm_state != 0) 6778 abort (); 6779 6780 return \"bmi\\t%l0\;bgt\\t%l0\"; 6781 " 6782 [(set_attr "conds" "jump_clob") 6783 (set_attr "length" "8")] 6784) 6785 6786; Special pattern to match reversed LTGT. 6787(define_insn "*arm_bltgt_reversed" 6788 [(set (pc) 6789 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0)) 6790 (pc) 6791 (label_ref (match_operand 0 "" ""))))] 6792 "TARGET_ARM && TARGET_HARD_FLOAT" 6793 "* 6794 if (arm_ccfsm_state != 0) 6795 abort (); 6796 6797 return \"bvs\\t%l0\;beq\\t%l0\"; 6798 " 6799 [(set_attr "conds" "jump_clob") 6800 (set_attr "length" "8")] 6801) 6802 6803(define_insn "*arm_cond_branch_reversed" 6804 [(set (pc) 6805 (if_then_else (match_operator 1 "arm_comparison_operator" 6806 [(match_operand 2 "cc_register" "") (const_int 0)]) 6807 (pc) 6808 (label_ref (match_operand 0 "" ""))))] 6809 "TARGET_ARM" 6810 "* 6811 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) 6812 { 6813 arm_ccfsm_state += 2; 6814 return \"\"; 6815 } 6816 return \"b%D1\\t%l0\"; 6817 " 6818 [(set_attr "conds" "use")] 6819) 6820 6821 6822 6823; scc insns 6824 6825(define_expand "seq" 6826 [(set (match_operand:SI 0 "s_register_operand" "") 6827 (eq:SI (match_dup 1) (const_int 0)))] 6828 "TARGET_ARM" 6829 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);" 6830) 6831 6832(define_expand "sne" 6833 [(set (match_operand:SI 0 "s_register_operand" "") 6834 (ne:SI (match_dup 1) (const_int 0)))] 6835 "TARGET_ARM" 6836 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);" 6837) 6838 6839(define_expand "sgt" 6840 [(set (match_operand:SI 0 "s_register_operand" "") 6841 (gt:SI (match_dup 1) (const_int 0)))] 6842 "TARGET_ARM" 6843 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);" 6844) 6845 6846(define_expand "sle" 6847 [(set (match_operand:SI 0 "s_register_operand" "") 6848 (le:SI (match_dup 1) (const_int 0)))] 6849 "TARGET_ARM" 6850 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);" 6851) 6852 6853(define_expand "sge" 6854 [(set (match_operand:SI 0 "s_register_operand" "") 6855 (ge:SI (match_dup 1) (const_int 0)))] 6856 "TARGET_ARM" 6857 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);" 6858) 6859 6860(define_expand "slt" 6861 [(set (match_operand:SI 0 "s_register_operand" "") 6862 (lt:SI (match_dup 1) (const_int 0)))] 6863 "TARGET_ARM" 6864 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);" 6865) 6866 6867(define_expand "sgtu" 6868 [(set (match_operand:SI 0 "s_register_operand" "") 6869 (gtu:SI (match_dup 1) (const_int 0)))] 6870 "TARGET_ARM" 6871 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);" 6872) 6873 6874(define_expand "sleu" 6875 [(set (match_operand:SI 0 "s_register_operand" "") 6876 (leu:SI (match_dup 1) (const_int 0)))] 6877 "TARGET_ARM" 6878 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);" 6879) 6880 6881(define_expand "sgeu" 6882 [(set (match_operand:SI 0 "s_register_operand" "") 6883 (geu:SI (match_dup 1) (const_int 0)))] 6884 "TARGET_ARM" 6885 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);" 6886) 6887 6888(define_expand "sltu" 6889 [(set (match_operand:SI 0 "s_register_operand" "") 6890 (ltu:SI (match_dup 1) (const_int 0)))] 6891 "TARGET_ARM" 6892 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);" 6893) 6894 6895(define_expand "sunordered" 6896 [(set (match_operand:SI 0 "s_register_operand" "") 6897 (unordered:SI (match_dup 1) (const_int 0)))] 6898 "TARGET_ARM && TARGET_HARD_FLOAT" 6899 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0, 6900 arm_compare_op1);" 6901) 6902 6903(define_expand "sordered" 6904 [(set (match_operand:SI 0 "s_register_operand" "") 6905 (ordered:SI (match_dup 1) (const_int 0)))] 6906 "TARGET_ARM && TARGET_HARD_FLOAT" 6907 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0, 6908 arm_compare_op1);" 6909) 6910 6911(define_expand "sungt" 6912 [(set (match_operand:SI 0 "s_register_operand" "") 6913 (ungt:SI (match_dup 1) (const_int 0)))] 6914 "TARGET_ARM && TARGET_HARD_FLOAT" 6915 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, 6916 arm_compare_op1);" 6917) 6918 6919(define_expand "sunge" 6920 [(set (match_operand:SI 0 "s_register_operand" "") 6921 (unge:SI (match_dup 1) (const_int 0)))] 6922 "TARGET_ARM && TARGET_HARD_FLOAT" 6923 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, 6924 arm_compare_op1);" 6925) 6926 6927(define_expand "sunlt" 6928 [(set (match_operand:SI 0 "s_register_operand" "") 6929 (unlt:SI (match_dup 1) (const_int 0)))] 6930 "TARGET_ARM && TARGET_HARD_FLOAT" 6931 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, 6932 arm_compare_op1);" 6933) 6934 6935(define_expand "sunle" 6936 [(set (match_operand:SI 0 "s_register_operand" "") 6937 (unle:SI (match_dup 1) (const_int 0)))] 6938 "TARGET_ARM && TARGET_HARD_FLOAT" 6939 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, 6940 arm_compare_op1);" 6941) 6942 6943;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with 6944;;; simple ARM instructions. 6945; 6946; (define_expand "suneq" 6947; [(set (match_operand:SI 0 "s_register_operand" "") 6948; (uneq:SI (match_dup 1) (const_int 0)))] 6949; "TARGET_ARM && TARGET_HARD_FLOAT" 6950; "abort ();" 6951; ) 6952; 6953; (define_expand "sltgt" 6954; [(set (match_operand:SI 0 "s_register_operand" "") 6955; (ltgt:SI (match_dup 1) (const_int 0)))] 6956; "TARGET_ARM && TARGET_HARD_FLOAT" 6957; "abort ();" 6958; ) 6959 6960(define_insn "*mov_scc" 6961 [(set (match_operand:SI 0 "s_register_operand" "=r") 6962 (match_operator:SI 1 "arm_comparison_operator" 6963 [(match_operand 2 "cc_register" "") (const_int 0)]))] 6964 "TARGET_ARM" 6965 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1" 6966 [(set_attr "conds" "use") 6967 (set_attr "length" "8")] 6968) 6969 6970(define_insn "*mov_negscc" 6971 [(set (match_operand:SI 0 "s_register_operand" "=r") 6972 (neg:SI (match_operator:SI 1 "arm_comparison_operator" 6973 [(match_operand 2 "cc_register" "") (const_int 0)])))] 6974 "TARGET_ARM" 6975 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0" 6976 [(set_attr "conds" "use") 6977 (set_attr "length" "8")] 6978) 6979 6980(define_insn "*mov_notscc" 6981 [(set (match_operand:SI 0 "s_register_operand" "=r") 6982 (not:SI (match_operator:SI 1 "arm_comparison_operator" 6983 [(match_operand 2 "cc_register" "") (const_int 0)])))] 6984 "TARGET_ARM" 6985 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1" 6986 [(set_attr "conds" "use") 6987 (set_attr "length" "8")] 6988) 6989 6990 6991;; Conditional move insns 6992 6993(define_expand "movsicc" 6994 [(set (match_operand:SI 0 "s_register_operand" "") 6995 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "") 6996 (match_operand:SI 2 "arm_not_operand" "") 6997 (match_operand:SI 3 "arm_not_operand" "")))] 6998 "TARGET_ARM" 6999 " 7000 { 7001 enum rtx_code code = GET_CODE (operands[1]); 7002 rtx ccreg; 7003 7004 if (code == UNEQ || code == LTGT) 7005 FAIL; 7006 7007 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); 7008 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); 7009 }" 7010) 7011 7012(define_expand "movsfcc" 7013 [(set (match_operand:SF 0 "s_register_operand" "") 7014 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "") 7015 (match_operand:SF 2 "s_register_operand" "") 7016 (match_operand:SF 3 "nonmemory_operand" "")))] 7017 "TARGET_ARM" 7018 " 7019 { 7020 enum rtx_code code = GET_CODE (operands[1]); 7021 rtx ccreg; 7022 7023 if (code == UNEQ || code == LTGT) 7024 FAIL; 7025 7026 /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 7027 Otherwise, ensure it is a valid FP add operand. */ 7028 if ((!TARGET_HARD_FLOAT) 7029 || (!fpa_add_operand (operands[3], SFmode))) 7030 operands[3] = force_reg (SFmode, operands[3]); 7031 7032 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); 7033 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); 7034 }" 7035) 7036 7037(define_expand "movdfcc" 7038 [(set (match_operand:DF 0 "s_register_operand" "") 7039 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "") 7040 (match_operand:DF 2 "s_register_operand" "") 7041 (match_operand:DF 3 "fpa_add_operand" "")))] 7042 "TARGET_ARM && TARGET_HARD_FLOAT" 7043 " 7044 { 7045 enum rtx_code code = GET_CODE (operands[1]); 7046 rtx ccreg; 7047 7048 if (code == UNEQ || code == LTGT) 7049 FAIL; 7050 7051 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); 7052 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); 7053 }" 7054) 7055 7056(define_insn "*movsicc_insn" 7057 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r") 7058 (if_then_else:SI 7059 (match_operator 3 "arm_comparison_operator" 7060 [(match_operand 4 "cc_register" "") (const_int 0)]) 7061 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K") 7062 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))] 7063 "TARGET_ARM" 7064 "@ 7065 mov%D3\\t%0, %2 7066 mvn%D3\\t%0, #%B2 7067 mov%d3\\t%0, %1 7068 mvn%d3\\t%0, #%B1 7069 mov%d3\\t%0, %1\;mov%D3\\t%0, %2 7070 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2 7071 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2 7072 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2" 7073 [(set_attr "length" "4,4,4,4,8,8,8,8") 7074 (set_attr "conds" "use")] 7075) 7076 7077(define_insn "*movsfcc_soft_insn" 7078 [(set (match_operand:SF 0 "s_register_operand" "=r,r") 7079 (if_then_else:SF (match_operator 3 "arm_comparison_operator" 7080 [(match_operand 4 "cc_register" "") (const_int 0)]) 7081 (match_operand:SF 1 "s_register_operand" "0,r") 7082 (match_operand:SF 2 "s_register_operand" "r,0")))] 7083 "TARGET_ARM && TARGET_SOFT_FLOAT" 7084 "@ 7085 mov%D3\\t%0, %2 7086 mov%d3\\t%0, %1" 7087 [(set_attr "conds" "use")] 7088) 7089 7090 7091;; Jump and linkage insns 7092 7093(define_expand "jump" 7094 [(set (pc) 7095 (label_ref (match_operand 0 "" "")))] 7096 "TARGET_EITHER" 7097 "" 7098) 7099 7100(define_insn "*arm_jump" 7101 [(set (pc) 7102 (label_ref (match_operand 0 "" "")))] 7103 "TARGET_ARM" 7104 "* 7105 { 7106 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) 7107 { 7108 arm_ccfsm_state += 2; 7109 return \"\"; 7110 } 7111 return \"b%?\\t%l0\"; 7112 } 7113 " 7114 [(set_attr "predicable" "yes")] 7115) 7116 7117(define_insn "*thumb_jump" 7118 [(set (pc) 7119 (label_ref (match_operand 0 "" "")))] 7120 "TARGET_THUMB" 7121 "* 7122 if (get_attr_length (insn) == 2) 7123 return \"b\\t%l0\"; 7124 return \"bl\\t%l0\\t%@ far jump\"; 7125 " 7126 [(set (attr "far_jump") 7127 (if_then_else 7128 (eq_attr "length" "4") 7129 (const_string "yes") 7130 (const_string "no"))) 7131 (set (attr "length") 7132 (if_then_else 7133 (and (ge (minus (match_dup 0) (pc)) (const_int -2044)) 7134 (le (minus (match_dup 0) (pc)) (const_int 2048))) 7135 (const_int 2) 7136 (const_int 4)))] 7137) 7138 7139(define_expand "call" 7140 [(parallel [(call (match_operand 0 "memory_operand" "") 7141 (match_operand 1 "general_operand" "")) 7142 (use (match_operand 2 "" "")) 7143 (clobber (reg:SI LR_REGNUM))])] 7144 "TARGET_EITHER" 7145 " 7146 { 7147 rtx callee; 7148 7149 /* In an untyped call, we can get NULL for operand 2. */ 7150 if (operands[2] == NULL_RTX) 7151 operands[2] = const0_rtx; 7152 7153 /* This is to decide if we should generate indirect calls by loading the 7154 32 bit address of the callee into a register before performing the 7155 branch and link. operand[2] encodes the long_call/short_call 7156 attribute of the function being called. This attribute is set whenever 7157 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call 7158 is used, and the short_call attribute can also be set if function is 7159 declared as static or if it has already been defined in the current 7160 compilation unit. See arm.c and arm.h for info about this. The third 7161 parameter to arm_is_longcall_p is used to tell it which pattern 7162 invoked it. */ 7163 callee = XEXP (operands[0], 0); 7164 7165 if (GET_CODE (callee) != REG 7166 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0)) 7167 XEXP (operands[0], 0) = force_reg (Pmode, callee); 7168 }" 7169) 7170 7171(define_insn "*call_reg" 7172 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r")) 7173 (match_operand 1 "" "")) 7174 (use (match_operand 2 "" "")) 7175 (clobber (reg:SI LR_REGNUM))] 7176 "TARGET_ARM" 7177 "* 7178 return output_call (operands); 7179 " 7180 ;; length is worst case, normally it is only two 7181 [(set_attr "length" "12") 7182 (set_attr "type" "call")] 7183) 7184 7185(define_insn "*call_mem" 7186 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m")) 7187 (match_operand 1 "" "")) 7188 (use (match_operand 2 "" "")) 7189 (clobber (reg:SI LR_REGNUM))] 7190 "TARGET_ARM" 7191 "* 7192 return output_call_mem (operands); 7193 " 7194 [(set_attr "length" "12") 7195 (set_attr "type" "call")] 7196) 7197 7198(define_insn "*call_indirect" 7199 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r")) 7200 (match_operand 1 "" "")) 7201 (use (match_operand 2 "" "")) 7202 (clobber (reg:SI LR_REGNUM))] 7203 "TARGET_THUMB" 7204 "* 7205 { 7206 if (TARGET_CALLER_INTERWORKING) 7207 return \"bl\\t%__interwork_call_via_%0\"; 7208 else 7209 return \"bl\\t%__call_via_%0\"; 7210 }" 7211 [(set_attr "type" "call")] 7212) 7213 7214(define_insn "*call_value_indirect" 7215 [(set (match_operand 0 "" "") 7216 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r")) 7217 (match_operand 2 "" ""))) 7218 (use (match_operand 3 "" "")) 7219 (clobber (reg:SI LR_REGNUM))] 7220 "TARGET_THUMB" 7221 "* 7222 { 7223 if (TARGET_CALLER_INTERWORKING) 7224 return \"bl\\t%__interwork_call_via_%1\"; 7225 else 7226 return \"bl\\t%__call_via_%1\"; 7227 }" 7228 [(set_attr "type" "call")] 7229) 7230 7231(define_expand "call_value" 7232 [(parallel [(set (match_operand 0 "" "") 7233 (call (match_operand 1 "memory_operand" "") 7234 (match_operand 2 "general_operand" ""))) 7235 (use (match_operand 3 "" "")) 7236 (clobber (reg:SI LR_REGNUM))])] 7237 "TARGET_EITHER" 7238 " 7239 { 7240 rtx callee = XEXP (operands[1], 0); 7241 7242 /* In an untyped call, we can get NULL for operand 2. */ 7243 if (operands[3] == 0) 7244 operands[3] = const0_rtx; 7245 7246 /* See the comment in define_expand \"call\". */ 7247 if (GET_CODE (callee) != REG 7248 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0)) 7249 XEXP (operands[1], 0) = force_reg (Pmode, callee); 7250 }" 7251) 7252 7253(define_insn "*call_value_reg" 7254 [(set (match_operand 0 "" "") 7255 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r")) 7256 (match_operand 2 "" ""))) 7257 (use (match_operand 3 "" "")) 7258 (clobber (reg:SI LR_REGNUM))] 7259 "TARGET_ARM" 7260 "* 7261 return output_call (&operands[1]); 7262 " 7263 [(set_attr "length" "12") 7264 (set_attr "type" "call")] 7265) 7266 7267(define_insn "*call_value_mem" 7268 [(set (match_operand 0 "" "") 7269 (call (mem:SI (match_operand:SI 1 "memory_operand" "m")) 7270 (match_operand 2 "" ""))) 7271 (use (match_operand 3 "" "")) 7272 (clobber (reg:SI LR_REGNUM))] 7273 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))" 7274 "* 7275 return output_call_mem (&operands[1]); 7276 " 7277 [(set_attr "length" "12") 7278 (set_attr "type" "call")] 7279) 7280 7281;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses 7282;; The 'a' causes the operand to be treated as an address, i.e. no '#' output. 7283 7284(define_insn "*call_symbol" 7285 [(call (mem:SI (match_operand:SI 0 "" "")) 7286 (match_operand 1 "" "")) 7287 (use (match_operand 2 "" "")) 7288 (clobber (reg:SI LR_REGNUM))] 7289 "TARGET_ARM 7290 && (GET_CODE (operands[0]) == SYMBOL_REF) 7291 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)" 7292 "* 7293 { 7294 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\"; 7295 }" 7296 [(set_attr "type" "call")] 7297) 7298 7299(define_insn "*call_value_symbol" 7300 [(set (match_operand 0 "s_register_operand" "") 7301 (call (mem:SI (match_operand:SI 1 "" "")) 7302 (match_operand:SI 2 "" ""))) 7303 (use (match_operand 3 "" "")) 7304 (clobber (reg:SI LR_REGNUM))] 7305 "TARGET_ARM 7306 && (GET_CODE (operands[1]) == SYMBOL_REF) 7307 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)" 7308 "* 7309 { 7310 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\"; 7311 }" 7312 [(set_attr "type" "call")] 7313) 7314 7315(define_insn "*call_insn" 7316 [(call (mem:SI (match_operand:SI 0 "" "")) 7317 (match_operand:SI 1 "" "")) 7318 (use (match_operand 2 "" "")) 7319 (clobber (reg:SI LR_REGNUM))] 7320 "TARGET_THUMB 7321 && GET_CODE (operands[0]) == SYMBOL_REF 7322 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)" 7323 "bl\\t%a0" 7324 [(set_attr "length" "4") 7325 (set_attr "type" "call")] 7326) 7327 7328(define_insn "*call_value_insn" 7329 [(set (match_operand 0 "register_operand" "") 7330 (call (mem:SI (match_operand 1 "" "")) 7331 (match_operand 2 "" ""))) 7332 (use (match_operand 3 "" "")) 7333 (clobber (reg:SI LR_REGNUM))] 7334 "TARGET_THUMB 7335 && GET_CODE (operands[1]) == SYMBOL_REF 7336 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)" 7337 "bl\\t%a1" 7338 [(set_attr "length" "4") 7339 (set_attr "type" "call")] 7340) 7341 7342;; We may also be able to do sibcalls for Thumb, but it's much harder... 7343(define_expand "sibcall" 7344 [(parallel [(call (match_operand 0 "memory_operand" "") 7345 (match_operand 1 "general_operand" "")) 7346 (return) 7347 (use (match_operand 2 "" ""))])] 7348 "TARGET_ARM" 7349 " 7350 { 7351 if (operands[2] == NULL_RTX) 7352 operands[2] = const0_rtx; 7353 }" 7354) 7355 7356(define_expand "sibcall_value" 7357 [(parallel [(set (match_operand 0 "register_operand" "") 7358 (call (match_operand 1 "memory_operand" "") 7359 (match_operand 2 "general_operand" ""))) 7360 (return) 7361 (use (match_operand 3 "" ""))])] 7362 "TARGET_ARM" 7363 " 7364 { 7365 if (operands[3] == NULL_RTX) 7366 operands[3] = const0_rtx; 7367 }" 7368) 7369 7370(define_insn "*sibcall_insn" 7371 [(call (mem:SI (match_operand:SI 0 "" "X")) 7372 (match_operand 1 "" "")) 7373 (return) 7374 (use (match_operand 2 "" ""))] 7375 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF" 7376 "* 7377 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\"; 7378 " 7379 [(set_attr "type" "call")] 7380) 7381 7382(define_insn "*sibcall_value_insn" 7383 [(set (match_operand 0 "s_register_operand" "") 7384 (call (mem:SI (match_operand:SI 1 "" "X")) 7385 (match_operand 2 "" ""))) 7386 (return) 7387 (use (match_operand 3 "" ""))] 7388 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF" 7389 "* 7390 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\"; 7391 " 7392 [(set_attr "type" "call")] 7393) 7394 7395;; Often the return insn will be the same as loading from memory, so set attr 7396(define_insn "return" 7397 [(return)] 7398 "TARGET_ARM && USE_RETURN_INSN (FALSE)" 7399 "* 7400 { 7401 if (arm_ccfsm_state == 2) 7402 { 7403 arm_ccfsm_state += 2; 7404 return \"\"; 7405 } 7406 return output_return_instruction (const_true_rtx, TRUE, FALSE); 7407 }" 7408 [(set_attr "type" "load") 7409 (set_attr "length" "12") 7410 (set_attr "predicable" "yes")] 7411) 7412 7413(define_insn "*cond_return" 7414 [(set (pc) 7415 (if_then_else (match_operator 0 "arm_comparison_operator" 7416 [(match_operand 1 "cc_register" "") (const_int 0)]) 7417 (return) 7418 (pc)))] 7419 "TARGET_ARM && USE_RETURN_INSN (TRUE)" 7420 "* 7421 { 7422 if (arm_ccfsm_state == 2) 7423 { 7424 arm_ccfsm_state += 2; 7425 return \"\"; 7426 } 7427 return output_return_instruction (operands[0], TRUE, FALSE); 7428 }" 7429 [(set_attr "conds" "use") 7430 (set_attr "length" "12") 7431 (set_attr "type" "load")] 7432) 7433 7434(define_insn "*cond_return_inverted" 7435 [(set (pc) 7436 (if_then_else (match_operator 0 "arm_comparison_operator" 7437 [(match_operand 1 "cc_register" "") (const_int 0)]) 7438 (pc) 7439 (return)))] 7440 "TARGET_ARM && USE_RETURN_INSN (TRUE)" 7441 "* 7442 { 7443 if (arm_ccfsm_state == 2) 7444 { 7445 arm_ccfsm_state += 2; 7446 return \"\"; 7447 } 7448 return output_return_instruction (operands[0], TRUE, TRUE); 7449 }" 7450 [(set_attr "conds" "use") 7451 (set_attr "type" "load")] 7452) 7453 7454;; Generate a sequence of instructions to determine if the processor is 7455;; in 26-bit or 32-bit mode, and return the appropriate return address 7456;; mask. 7457 7458(define_expand "return_addr_mask" 7459 [(set (match_dup 1) 7460 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH) 7461 (const_int 0))) 7462 (set (match_operand:SI 0 "s_register_operand" "") 7463 (if_then_else:SI (eq (match_dup 1) (const_int 0)) 7464 (const_int -1) 7465 (const_int 67108860)))] ; 0x03fffffc 7466 "TARGET_ARM" 7467 " 7468 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM); 7469 ") 7470 7471(define_insn "*check_arch2" 7472 [(set (match_operand:CC_NOOV 0 "cc_register" "") 7473 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH) 7474 (const_int 0)))] 7475 "TARGET_ARM" 7476 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc" 7477 [(set_attr "length" "8") 7478 (set_attr "conds" "set")] 7479) 7480 7481;; Call subroutine returning any type. 7482 7483(define_expand "untyped_call" 7484 [(parallel [(call (match_operand 0 "" "") 7485 (const_int 0)) 7486 (match_operand 1 "" "") 7487 (match_operand 2 "" "")])] 7488 "TARGET_ARM" 7489 " 7490 { 7491 int i; 7492 7493 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); 7494 7495 for (i = 0; i < XVECLEN (operands[2], 0); i++) 7496 { 7497 rtx set = XVECEXP (operands[2], 0, i); 7498 7499 emit_move_insn (SET_DEST (set), SET_SRC (set)); 7500 } 7501 7502 /* The optimizer does not know that the call sets the function value 7503 registers we stored in the result block. We avoid problems by 7504 claiming that all hard registers are used and clobbered at this 7505 point. */ 7506 emit_insn (gen_blockage ()); 7507 7508 DONE; 7509 }" 7510) 7511 7512;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and 7513;; all of memory. This blocks insns from being moved across this point. 7514 7515(define_insn "blockage" 7516 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)] 7517 "TARGET_EITHER" 7518 "" 7519 [(set_attr "length" "0") 7520 (set_attr "type" "block")] 7521) 7522 7523(define_expand "casesi" 7524 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on 7525 (match_operand:SI 1 "const_int_operand" "") ; lower bound 7526 (match_operand:SI 2 "const_int_operand" "") ; total range 7527 (match_operand:SI 3 "" "") ; table label 7528 (match_operand:SI 4 "" "")] ; Out of range label 7529 "TARGET_ARM" 7530 " 7531 { 7532 rtx reg; 7533 if (operands[1] != const0_rtx) 7534 { 7535 reg = gen_reg_rtx (SImode); 7536 7537 emit_insn (gen_addsi3 (reg, operands[0], 7538 GEN_INT (-INTVAL (operands[1])))); 7539 operands[0] = reg; 7540 } 7541 7542 if (!const_ok_for_arm (INTVAL (operands[2]))) 7543 operands[2] = force_reg (SImode, operands[2]); 7544 7545 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3], 7546 operands[4])); 7547 DONE; 7548 }" 7549) 7550 7551;; The USE in this pattern is needed to tell flow analysis that this is 7552;; a CASESI insn. It has no other purpose. 7553(define_insn "casesi_internal" 7554 [(parallel [(set (pc) 7555 (if_then_else 7556 (leu (match_operand:SI 0 "s_register_operand" "r") 7557 (match_operand:SI 1 "arm_rhs_operand" "rI")) 7558 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4)) 7559 (label_ref (match_operand 2 "" "")))) 7560 (label_ref (match_operand 3 "" "")))) 7561 (clobber (reg:CC CC_REGNUM)) 7562 (use (label_ref (match_dup 2)))])] 7563 "TARGET_ARM" 7564 "* 7565 if (flag_pic) 7566 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\"; 7567 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\"; 7568 " 7569 [(set_attr "conds" "clob") 7570 (set_attr "length" "12")] 7571) 7572 7573(define_expand "indirect_jump" 7574 [(set (pc) 7575 (match_operand:SI 0 "s_register_operand" ""))] 7576 "TARGET_EITHER" 7577 "" 7578) 7579 7580(define_insn "*arm_indirect_jump" 7581 [(set (pc) 7582 (match_operand:SI 0 "s_register_operand" "r"))] 7583 "TARGET_ARM" 7584 "mov%?\\t%|pc, %0\\t%@ indirect register jump" 7585 [(set_attr "predicable" "yes")] 7586) 7587 7588;; Although not supported by the define_expand above, 7589;; cse/combine may generate this form. 7590(define_insn "*load_indirect_jump" 7591 [(set (pc) 7592 (match_operand:SI 0 "memory_operand" "m"))] 7593 "TARGET_ARM" 7594 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump" 7595 [(set_attr "type" "load") 7596 (set_attr "pool_range" "4096") 7597 (set_attr "neg_pool_range" "4084") 7598 (set_attr "predicable" "yes")] 7599) 7600 7601(define_insn "*thumb_indirect_jump" 7602 [(set (pc) 7603 (match_operand:SI 0 "register_operand" "l*r"))] 7604 "TARGET_THUMB" 7605 "mov\\tpc, %0" 7606 [(set_attr "conds" "clob") 7607 (set_attr "length" "2")] 7608) 7609 7610 7611;; Misc insns 7612 7613(define_insn "nop" 7614 [(const_int 0)] 7615 "TARGET_EITHER" 7616 "* 7617 if (TARGET_ARM) 7618 return \"mov%?\\t%|r0, %|r0\\t%@ nop\"; 7619 return \"mov\\tr8, r8\"; 7620 " 7621 [(set (attr "length") 7622 (if_then_else (eq_attr "is_thumb" "yes") 7623 (const_int 2) 7624 (const_int 4)))] 7625) 7626 7627 7628;; Patterns to allow combination of arithmetic, cond code and shifts 7629 7630(define_insn "*arith_shiftsi" 7631 [(set (match_operand:SI 0 "s_register_operand" "=r") 7632 (match_operator:SI 1 "shiftable_operator" 7633 [(match_operator:SI 3 "shift_operator" 7634 [(match_operand:SI 4 "s_register_operand" "r") 7635 (match_operand:SI 5 "reg_or_int_operand" "rI")]) 7636 (match_operand:SI 2 "s_register_operand" "r")]))] 7637 "TARGET_ARM" 7638 "%i1%?\\t%0, %2, %4%S3" 7639 [(set_attr "predicable" "yes") 7640 (set_attr "shift" "4") 7641 ] 7642) 7643 7644(define_split 7645 [(set (match_operand:SI 0 "s_register_operand" "") 7646 (match_operator:SI 1 "shiftable_operator" 7647 [(match_operator:SI 2 "shiftable_operator" 7648 [(match_operator:SI 3 "shift_operator" 7649 [(match_operand:SI 4 "s_register_operand" "") 7650 (match_operand:SI 5 "reg_or_int_operand" "")]) 7651 (match_operand:SI 6 "s_register_operand" "")]) 7652 (match_operand:SI 7 "arm_rhs_operand" "")])) 7653 (clobber (match_operand:SI 8 "s_register_operand" ""))] 7654 "TARGET_ARM" 7655 [(set (match_dup 8) 7656 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)]) 7657 (match_dup 6)])) 7658 (set (match_dup 0) 7659 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))] 7660 "") 7661 7662(define_insn "*arith_shiftsi_compare0" 7663 [(set (reg:CC_NOOV CC_REGNUM) 7664 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" 7665 [(match_operator:SI 3 "shift_operator" 7666 [(match_operand:SI 4 "s_register_operand" "r") 7667 (match_operand:SI 5 "reg_or_int_operand" "rI")]) 7668 (match_operand:SI 2 "s_register_operand" "r")]) 7669 (const_int 0))) 7670 (set (match_operand:SI 0 "s_register_operand" "=r") 7671 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)]) 7672 (match_dup 2)]))] 7673 "TARGET_ARM" 7674 "%i1%?s\\t%0, %2, %4%S3" 7675 [(set_attr "conds" "set") 7676 (set_attr "shift" "4") 7677 ] 7678) 7679 7680(define_insn "*arith_shiftsi_compare0_scratch" 7681 [(set (reg:CC_NOOV CC_REGNUM) 7682 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" 7683 [(match_operator:SI 3 "shift_operator" 7684 [(match_operand:SI 4 "s_register_operand" "r") 7685 (match_operand:SI 5 "reg_or_int_operand" "rI")]) 7686 (match_operand:SI 2 "s_register_operand" "r")]) 7687 (const_int 0))) 7688 (clobber (match_scratch:SI 0 "=r"))] 7689 "TARGET_ARM" 7690 "%i1%?s\\t%0, %2, %4%S3" 7691 [(set_attr "conds" "set") 7692 (set_attr "shift" "4") 7693 ] 7694) 7695 7696(define_insn "*sub_shiftsi" 7697 [(set (match_operand:SI 0 "s_register_operand" "=r") 7698 (minus:SI (match_operand:SI 1 "s_register_operand" "r") 7699 (match_operator:SI 2 "shift_operator" 7700 [(match_operand:SI 3 "s_register_operand" "r") 7701 (match_operand:SI 4 "reg_or_int_operand" "rM")])))] 7702 "TARGET_ARM" 7703 "sub%?\\t%0, %1, %3%S2" 7704 [(set_attr "predicable" "yes") 7705 (set_attr "shift" "3") 7706 ] 7707) 7708 7709(define_insn "*sub_shiftsi_compare0" 7710 [(set (reg:CC_NOOV CC_REGNUM) 7711 (compare:CC_NOOV 7712 (minus:SI (match_operand:SI 1 "s_register_operand" "r") 7713 (match_operator:SI 2 "shift_operator" 7714 [(match_operand:SI 3 "s_register_operand" "r") 7715 (match_operand:SI 4 "reg_or_int_operand" "rM")])) 7716 (const_int 0))) 7717 (set (match_operand:SI 0 "s_register_operand" "=r") 7718 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 7719 (match_dup 4)])))] 7720 "TARGET_ARM" 7721 "sub%?s\\t%0, %1, %3%S2" 7722 [(set_attr "conds" "set") 7723 (set_attr "shift" "3") 7724 ] 7725) 7726 7727(define_insn "*sub_shiftsi_compare0_scratch" 7728 [(set (reg:CC_NOOV CC_REGNUM) 7729 (compare:CC_NOOV 7730 (minus:SI (match_operand:SI 1 "s_register_operand" "r") 7731 (match_operator:SI 2 "shift_operator" 7732 [(match_operand:SI 3 "s_register_operand" "r") 7733 (match_operand:SI 4 "reg_or_int_operand" "rM")])) 7734 (const_int 0))) 7735 (clobber (match_scratch:SI 0 "=r"))] 7736 "TARGET_ARM" 7737 "sub%?s\\t%0, %1, %3%S2" 7738 [(set_attr "conds" "set") 7739 (set_attr "shift" "3") 7740 ] 7741) 7742 7743 7744 7745(define_insn "*and_scc" 7746 [(set (match_operand:SI 0 "s_register_operand" "=r") 7747 (and:SI (match_operator:SI 1 "arm_comparison_operator" 7748 [(match_operand 3 "cc_register" "") (const_int 0)]) 7749 (match_operand:SI 2 "s_register_operand" "r")))] 7750 "TARGET_ARM" 7751 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1" 7752 [(set_attr "conds" "use") 7753 (set_attr "length" "8")] 7754) 7755 7756(define_insn "*ior_scc" 7757 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7758 (ior:SI (match_operator:SI 2 "arm_comparison_operator" 7759 [(match_operand 3 "cc_register" "") (const_int 0)]) 7760 (match_operand:SI 1 "s_register_operand" "0,?r")))] 7761 "TARGET_ARM" 7762 "@ 7763 orr%d2\\t%0, %1, #1 7764 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1" 7765 [(set_attr "conds" "use") 7766 (set_attr "length" "4,8")] 7767) 7768 7769(define_insn "*compare_scc" 7770 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7771 (match_operator:SI 1 "arm_comparison_operator" 7772 [(match_operand:SI 2 "s_register_operand" "r,r") 7773 (match_operand:SI 3 "arm_add_operand" "rI,L")])) 7774 (clobber (reg:CC CC_REGNUM))] 7775 "TARGET_ARM" 7776 "* 7777 if (operands[3] == const0_rtx) 7778 { 7779 if (GET_CODE (operands[1]) == LT) 7780 return \"mov\\t%0, %2, lsr #31\"; 7781 7782 if (GET_CODE (operands[1]) == GE) 7783 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\"; 7784 7785 if (GET_CODE (operands[1]) == EQ) 7786 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\"; 7787 } 7788 7789 if (GET_CODE (operands[1]) == NE) 7790 { 7791 if (which_alternative == 1) 7792 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\"; 7793 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\"; 7794 } 7795 if (which_alternative == 1) 7796 output_asm_insn (\"cmn\\t%2, #%n3\", operands); 7797 else 7798 output_asm_insn (\"cmp\\t%2, %3\", operands); 7799 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\"; 7800 " 7801 [(set_attr "conds" "clob") 7802 (set_attr "length" "12")] 7803) 7804 7805(define_insn "*cond_move" 7806 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 7807 (if_then_else:SI (match_operator 3 "equality_operator" 7808 [(match_operator 4 "arm_comparison_operator" 7809 [(match_operand 5 "cc_register" "") (const_int 0)]) 7810 (const_int 0)]) 7811 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI") 7812 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))] 7813 "TARGET_ARM" 7814 "* 7815 if (GET_CODE (operands[3]) == NE) 7816 { 7817 if (which_alternative != 1) 7818 output_asm_insn (\"mov%D4\\t%0, %2\", operands); 7819 if (which_alternative != 0) 7820 output_asm_insn (\"mov%d4\\t%0, %1\", operands); 7821 return \"\"; 7822 } 7823 if (which_alternative != 0) 7824 output_asm_insn (\"mov%D4\\t%0, %1\", operands); 7825 if (which_alternative != 1) 7826 output_asm_insn (\"mov%d4\\t%0, %2\", operands); 7827 return \"\"; 7828 " 7829 [(set_attr "conds" "use") 7830 (set_attr "length" "4,4,8")] 7831) 7832 7833(define_insn "*cond_arith" 7834 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7835 (match_operator:SI 5 "shiftable_operator" 7836 [(match_operator:SI 4 "arm_comparison_operator" 7837 [(match_operand:SI 2 "s_register_operand" "r,r") 7838 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) 7839 (match_operand:SI 1 "s_register_operand" "0,?r")])) 7840 (clobber (reg:CC CC_REGNUM))] 7841 "TARGET_ARM" 7842 "* 7843 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx) 7844 return \"%i5\\t%0, %1, %2, lsr #31\"; 7845 7846 output_asm_insn (\"cmp\\t%2, %3\", operands); 7847 if (GET_CODE (operands[5]) == AND) 7848 output_asm_insn (\"mov%D4\\t%0, #0\", operands); 7849 else if (GET_CODE (operands[5]) == MINUS) 7850 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands); 7851 else if (which_alternative != 0) 7852 output_asm_insn (\"mov%D4\\t%0, %1\", operands); 7853 return \"%i5%d4\\t%0, %1, #1\"; 7854 " 7855 [(set_attr "conds" "clob") 7856 (set_attr "length" "12")] 7857) 7858 7859(define_insn "*cond_sub" 7860 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7861 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r") 7862 (match_operator:SI 4 "arm_comparison_operator" 7863 [(match_operand:SI 2 "s_register_operand" "r,r") 7864 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]))) 7865 (clobber (reg:CC CC_REGNUM))] 7866 "TARGET_ARM" 7867 "* 7868 output_asm_insn (\"cmp\\t%2, %3\", operands); 7869 if (which_alternative != 0) 7870 output_asm_insn (\"mov%D4\\t%0, %1\", operands); 7871 return \"sub%d4\\t%0, %1, #1\"; 7872 " 7873 [(set_attr "conds" "clob") 7874 (set_attr "length" "8,12")] 7875) 7876 7877(define_insn "*cmp_ite0" 7878 [(set (match_operand 6 "dominant_cc_register" "") 7879 (compare 7880 (if_then_else:SI 7881 (match_operator 4 "arm_comparison_operator" 7882 [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 7883 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 7884 (match_operator:SI 5 "arm_comparison_operator" 7885 [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 7886 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]) 7887 (const_int 0)) 7888 (const_int 0)))] 7889 "TARGET_ARM" 7890 "* 7891 { 7892 static const char * const opcodes[4][2] = 7893 { 7894 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\", 7895 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"}, 7896 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", 7897 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"}, 7898 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", 7899 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"}, 7900 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\", 7901 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"} 7902 }; 7903 int swap = 7904 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])); 7905 7906 return opcodes[which_alternative][swap]; 7907 }" 7908 [(set_attr "conds" "set") 7909 (set_attr "length" "8")] 7910) 7911 7912(define_insn "*cmp_ite1" 7913 [(set (match_operand 6 "dominant_cc_register" "") 7914 (compare 7915 (if_then_else:SI 7916 (match_operator 4 "arm_comparison_operator" 7917 [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 7918 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 7919 (match_operator:SI 5 "arm_comparison_operator" 7920 [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 7921 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]) 7922 (const_int 1)) 7923 (const_int 0)))] 7924 "TARGET_ARM" 7925 "* 7926 { 7927 static const char * const opcodes[4][2] = 7928 { 7929 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\", 7930 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"}, 7931 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\", 7932 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"}, 7933 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\", 7934 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"}, 7935 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\", 7936 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"} 7937 }; 7938 int swap = 7939 comparison_dominates_p (GET_CODE (operands[5]), 7940 reverse_condition (GET_CODE (operands[4]))); 7941 7942 return opcodes[which_alternative][swap]; 7943 }" 7944 [(set_attr "conds" "set") 7945 (set_attr "length" "8")] 7946) 7947 7948(define_insn "*cmp_and" 7949 [(set (match_operand 6 "dominant_cc_register" "") 7950 (compare 7951 (and:SI 7952 (match_operator 4 "arm_comparison_operator" 7953 [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 7954 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 7955 (match_operator:SI 5 "arm_comparison_operator" 7956 [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 7957 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])) 7958 (const_int 0)))] 7959 "TARGET_ARM" 7960 "* 7961 { 7962 static const char *const opcodes[4][2] = 7963 { 7964 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\", 7965 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"}, 7966 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", 7967 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"}, 7968 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", 7969 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"}, 7970 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\", 7971 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"} 7972 }; 7973 int swap = 7974 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])); 7975 7976 return opcodes[which_alternative][swap]; 7977 }" 7978 [(set_attr "conds" "set") 7979 (set_attr "predicable" "no") 7980 (set_attr "length" "8")] 7981) 7982 7983(define_insn "*cmp_ior" 7984 [(set (match_operand 6 "dominant_cc_register" "") 7985 (compare 7986 (ior:SI 7987 (match_operator 4 "arm_comparison_operator" 7988 [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 7989 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 7990 (match_operator:SI 5 "arm_comparison_operator" 7991 [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 7992 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])) 7993 (const_int 0)))] 7994 "TARGET_ARM" 7995 "* 7996{ 7997 static const char *const opcodes[4][2] = 7998 { 7999 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\", 8000 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"}, 8001 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\", 8002 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"}, 8003 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\", 8004 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"}, 8005 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\", 8006 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"} 8007 }; 8008 int swap = 8009 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])); 8010 8011 return opcodes[which_alternative][swap]; 8012} 8013" 8014 [(set_attr "conds" "set") 8015 (set_attr "length" "8")] 8016) 8017 8018(define_insn_and_split "*ior_scc_scc" 8019 [(set (match_operand:SI 0 "s_register_operand" "=r") 8020 (ior:SI (match_operator:SI 3 "arm_comparison_operator" 8021 [(match_operand:SI 1 "s_register_operand" "r") 8022 (match_operand:SI 2 "arm_add_operand" "rIL")]) 8023 (match_operator:SI 6 "arm_comparison_operator" 8024 [(match_operand:SI 4 "s_register_operand" "r") 8025 (match_operand:SI 5 "arm_add_operand" "rIL")]))) 8026 (clobber (reg:CC CC_REGNUM))] 8027 "TARGET_ARM 8028 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y) 8029 != CCmode)" 8030 "#" 8031 "TARGET_ARM && reload_completed" 8032 [(set (match_dup 7) 8033 (compare 8034 (ior:SI 8035 (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8036 (match_op_dup 6 [(match_dup 4) (match_dup 5)])) 8037 (const_int 0))) 8038 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))] 8039 "operands[7] 8040 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6], 8041 DOM_CC_X_OR_Y), 8042 CC_REGNUM);" 8043 [(set_attr "conds" "clob") 8044 (set_attr "length" "16")]) 8045 8046; If the above pattern is followed by a CMP insn, then the compare is 8047; redundant, since we can rework the conditional instruction that follows. 8048(define_insn_and_split "*ior_scc_scc_cmp" 8049 [(set (match_operand 0 "dominant_cc_register" "") 8050 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator" 8051 [(match_operand:SI 1 "s_register_operand" "r") 8052 (match_operand:SI 2 "arm_add_operand" "rIL")]) 8053 (match_operator:SI 6 "arm_comparison_operator" 8054 [(match_operand:SI 4 "s_register_operand" "r") 8055 (match_operand:SI 5 "arm_add_operand" "rIL")])) 8056 (const_int 0))) 8057 (set (match_operand:SI 7 "s_register_operand" "=r") 8058 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8059 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))] 8060 "TARGET_ARM" 8061 "#" 8062 "TARGET_ARM && reload_completed" 8063 [(set (match_dup 0) 8064 (compare 8065 (ior:SI 8066 (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8067 (match_op_dup 6 [(match_dup 4) (match_dup 5)])) 8068 (const_int 0))) 8069 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))] 8070 "" 8071 [(set_attr "conds" "set") 8072 (set_attr "length" "16")]) 8073 8074(define_insn_and_split "*and_scc_scc" 8075 [(set (match_operand:SI 0 "s_register_operand" "=r") 8076 (and:SI (match_operator:SI 3 "arm_comparison_operator" 8077 [(match_operand:SI 1 "s_register_operand" "r") 8078 (match_operand:SI 2 "arm_add_operand" "rIL")]) 8079 (match_operator:SI 6 "arm_comparison_operator" 8080 [(match_operand:SI 4 "s_register_operand" "r") 8081 (match_operand:SI 5 "arm_add_operand" "rIL")]))) 8082 (clobber (reg:CC CC_REGNUM))] 8083 "TARGET_ARM 8084 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y) 8085 != CCmode)" 8086 "#" 8087 "TARGET_ARM && reload_completed 8088 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y) 8089 != CCmode)" 8090 [(set (match_dup 7) 8091 (compare 8092 (and:SI 8093 (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8094 (match_op_dup 6 [(match_dup 4) (match_dup 5)])) 8095 (const_int 0))) 8096 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))] 8097 "operands[7] 8098 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6], 8099 DOM_CC_X_AND_Y), 8100 CC_REGNUM);" 8101 [(set_attr "conds" "clob") 8102 (set_attr "length" "16")]) 8103 8104; If the above pattern is followed by a CMP insn, then the compare is 8105; redundant, since we can rework the conditional instruction that follows. 8106(define_insn_and_split "*and_scc_scc_cmp" 8107 [(set (match_operand 0 "dominant_cc_register" "") 8108 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator" 8109 [(match_operand:SI 1 "s_register_operand" "r") 8110 (match_operand:SI 2 "arm_add_operand" "rIL")]) 8111 (match_operator:SI 6 "arm_comparison_operator" 8112 [(match_operand:SI 4 "s_register_operand" "r") 8113 (match_operand:SI 5 "arm_add_operand" "rIL")])) 8114 (const_int 0))) 8115 (set (match_operand:SI 7 "s_register_operand" "=r") 8116 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8117 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))] 8118 "TARGET_ARM" 8119 "#" 8120 "TARGET_ARM && reload_completed" 8121 [(set (match_dup 0) 8122 (compare 8123 (and:SI 8124 (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8125 (match_op_dup 6 [(match_dup 4) (match_dup 5)])) 8126 (const_int 0))) 8127 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))] 8128 "" 8129 [(set_attr "conds" "set") 8130 (set_attr "length" "16")]) 8131 8132;; If there is no dominance in the comparison, then we can still save an 8133;; instruction in the AND case, since we can know that the second compare 8134;; need only zero the value if false (if true, then the value is already 8135;; correct). 8136(define_insn_and_split "*and_scc_scc_nodom" 8137 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r") 8138 (and:SI (match_operator:SI 3 "arm_comparison_operator" 8139 [(match_operand:SI 1 "s_register_operand" "r,r,0") 8140 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")]) 8141 (match_operator:SI 6 "arm_comparison_operator" 8142 [(match_operand:SI 4 "s_register_operand" "r,r,r") 8143 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")]))) 8144 (clobber (reg:CC CC_REGNUM))] 8145 "TARGET_ARM 8146 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y) 8147 == CCmode)" 8148 "#" 8149 "TARGET_ARM && reload_completed" 8150 [(parallel [(set (match_dup 0) 8151 (match_op_dup 3 [(match_dup 1) (match_dup 2)])) 8152 (clobber (reg:CC CC_REGNUM))]) 8153 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)])) 8154 (set (match_dup 0) 8155 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)]) 8156 (match_dup 0) 8157 (const_int 0)))] 8158 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]), 8159 operands[4], operands[5]), 8160 CC_REGNUM); 8161 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4], 8162 operands[5]);" 8163 [(set_attr "conds" "clob") 8164 (set_attr "length" "20")]) 8165 8166(define_split 8167 [(set (reg:CC_NOOV CC_REGNUM) 8168 (compare:CC_NOOV (ior:SI 8169 (and:SI (match_operand:SI 0 "s_register_operand" "") 8170 (const_int 1)) 8171 (match_operator:SI 1 "comparison_operator" 8172 [(match_operand:SI 2 "s_register_operand" "") 8173 (match_operand:SI 3 "arm_add_operand" "")])) 8174 (const_int 0))) 8175 (clobber (match_operand:SI 4 "s_register_operand" ""))] 8176 "TARGET_ARM" 8177 [(set (match_dup 4) 8178 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)]) 8179 (match_dup 0))) 8180 (set (reg:CC_NOOV CC_REGNUM) 8181 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1)) 8182 (const_int 0)))] 8183 "") 8184 8185(define_split 8186 [(set (reg:CC_NOOV CC_REGNUM) 8187 (compare:CC_NOOV (ior:SI 8188 (match_operator:SI 1 "comparison_operator" 8189 [(match_operand:SI 2 "s_register_operand" "") 8190 (match_operand:SI 3 "arm_add_operand" "")]) 8191 (and:SI (match_operand:SI 0 "s_register_operand" "") 8192 (const_int 1))) 8193 (const_int 0))) 8194 (clobber (match_operand:SI 4 "s_register_operand" ""))] 8195 "TARGET_ARM" 8196 [(set (match_dup 4) 8197 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)]) 8198 (match_dup 0))) 8199 (set (reg:CC_NOOV CC_REGNUM) 8200 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1)) 8201 (const_int 0)))] 8202 "") 8203 8204(define_insn "*negscc" 8205 [(set (match_operand:SI 0 "s_register_operand" "=r") 8206 (neg:SI (match_operator 3 "arm_comparison_operator" 8207 [(match_operand:SI 1 "s_register_operand" "r") 8208 (match_operand:SI 2 "arm_rhs_operand" "rI")]))) 8209 (clobber (reg:CC CC_REGNUM))] 8210 "TARGET_ARM" 8211 "* 8212 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx) 8213 return \"mov\\t%0, %1, asr #31\"; 8214 8215 if (GET_CODE (operands[3]) == NE) 8216 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\"; 8217 8218 if (GET_CODE (operands[3]) == GT) 8219 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\"; 8220 8221 output_asm_insn (\"cmp\\t%1, %2\", operands); 8222 output_asm_insn (\"mov%D3\\t%0, #0\", operands); 8223 return \"mvn%d3\\t%0, #0\"; 8224 " 8225 [(set_attr "conds" "clob") 8226 (set_attr "length" "12")] 8227) 8228 8229(define_insn "movcond" 8230 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 8231 (if_then_else:SI 8232 (match_operator 5 "arm_comparison_operator" 8233 [(match_operand:SI 3 "s_register_operand" "r,r,r") 8234 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")]) 8235 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI") 8236 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 8237 (clobber (reg:CC CC_REGNUM))] 8238 "TARGET_ARM" 8239 "* 8240 if (GET_CODE (operands[5]) == LT 8241 && (operands[4] == const0_rtx)) 8242 { 8243 if (which_alternative != 1 && GET_CODE (operands[1]) == REG) 8244 { 8245 if (operands[2] == const0_rtx) 8246 return \"and\\t%0, %1, %3, asr #31\"; 8247 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\"; 8248 } 8249 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG) 8250 { 8251 if (operands[1] == const0_rtx) 8252 return \"bic\\t%0, %2, %3, asr #31\"; 8253 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\"; 8254 } 8255 /* The only case that falls through to here is when both ops 1 & 2 8256 are constants. */ 8257 } 8258 8259 if (GET_CODE (operands[5]) == GE 8260 && (operands[4] == const0_rtx)) 8261 { 8262 if (which_alternative != 1 && GET_CODE (operands[1]) == REG) 8263 { 8264 if (operands[2] == const0_rtx) 8265 return \"bic\\t%0, %1, %3, asr #31\"; 8266 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\"; 8267 } 8268 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG) 8269 { 8270 if (operands[1] == const0_rtx) 8271 return \"and\\t%0, %2, %3, asr #31\"; 8272 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\"; 8273 } 8274 /* The only case that falls through to here is when both ops 1 & 2 8275 are constants. */ 8276 } 8277 if (GET_CODE (operands[4]) == CONST_INT 8278 && !const_ok_for_arm (INTVAL (operands[4]))) 8279 output_asm_insn (\"cmn\\t%3, #%n4\", operands); 8280 else 8281 output_asm_insn (\"cmp\\t%3, %4\", operands); 8282 if (which_alternative != 0) 8283 output_asm_insn (\"mov%d5\\t%0, %1\", operands); 8284 if (which_alternative != 1) 8285 output_asm_insn (\"mov%D5\\t%0, %2\", operands); 8286 return \"\"; 8287 " 8288 [(set_attr "conds" "clob") 8289 (set_attr "length" "8,8,12")] 8290) 8291 8292(define_insn "*ifcompare_plus_move" 8293 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8294 (if_then_else:SI (match_operator 6 "arm_comparison_operator" 8295 [(match_operand:SI 4 "s_register_operand" "r,r") 8296 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 8297 (plus:SI 8298 (match_operand:SI 2 "s_register_operand" "r,r") 8299 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")) 8300 (match_operand:SI 1 "arm_rhs_operand" "0,?rI"))) 8301 (clobber (reg:CC CC_REGNUM))] 8302 "TARGET_ARM" 8303 "#" 8304 [(set_attr "conds" "clob") 8305 (set_attr "length" "8,12")] 8306) 8307 8308(define_insn "*if_plus_move" 8309 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r") 8310 (if_then_else:SI 8311 (match_operator 4 "arm_comparison_operator" 8312 [(match_operand 5 "cc_register" "") (const_int 0)]) 8313 (plus:SI 8314 (match_operand:SI 2 "s_register_operand" "r,r,r,r") 8315 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L")) 8316 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))] 8317 "TARGET_ARM" 8318 "@ 8319 add%d4\\t%0, %2, %3 8320 sub%d4\\t%0, %2, #%n3 8321 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1 8322 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1" 8323 [(set_attr "conds" "use") 8324 (set_attr "length" "4,4,8,8") 8325 (set_attr "type" "*,*,*,*")] 8326) 8327 8328(define_insn "*ifcompare_move_plus" 8329 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8330 (if_then_else:SI (match_operator 6 "arm_comparison_operator" 8331 [(match_operand:SI 4 "s_register_operand" "r,r") 8332 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 8333 (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 8334 (plus:SI 8335 (match_operand:SI 2 "s_register_operand" "r,r") 8336 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")))) 8337 (clobber (reg:CC CC_REGNUM))] 8338 "TARGET_ARM" 8339 "#" 8340 [(set_attr "conds" "clob") 8341 (set_attr "length" "8,12")] 8342) 8343 8344(define_insn "*if_move_plus" 8345 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r") 8346 (if_then_else:SI 8347 (match_operator 4 "arm_comparison_operator" 8348 [(match_operand 5 "cc_register" "") (const_int 0)]) 8349 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI") 8350 (plus:SI 8351 (match_operand:SI 2 "s_register_operand" "r,r,r,r") 8352 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))] 8353 "TARGET_ARM" 8354 "@ 8355 add%D4\\t%0, %2, %3 8356 sub%D4\\t%0, %2, #%n3 8357 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1 8358 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1" 8359 [(set_attr "conds" "use") 8360 (set_attr "length" "4,4,8,8") 8361 (set_attr "type" "*,*,*,*")] 8362) 8363 8364(define_insn "*ifcompare_arith_arith" 8365 [(set (match_operand:SI 0 "s_register_operand" "=r") 8366 (if_then_else:SI (match_operator 9 "arm_comparison_operator" 8367 [(match_operand:SI 5 "s_register_operand" "r") 8368 (match_operand:SI 6 "arm_add_operand" "rIL")]) 8369 (match_operator:SI 8 "shiftable_operator" 8370 [(match_operand:SI 1 "s_register_operand" "r") 8371 (match_operand:SI 2 "arm_rhs_operand" "rI")]) 8372 (match_operator:SI 7 "shiftable_operator" 8373 [(match_operand:SI 3 "s_register_operand" "r") 8374 (match_operand:SI 4 "arm_rhs_operand" "rI")]))) 8375 (clobber (reg:CC CC_REGNUM))] 8376 "TARGET_ARM" 8377 "#" 8378 [(set_attr "conds" "clob") 8379 (set_attr "length" "12")] 8380) 8381 8382(define_insn "*if_arith_arith" 8383 [(set (match_operand:SI 0 "s_register_operand" "=r") 8384 (if_then_else:SI (match_operator 5 "arm_comparison_operator" 8385 [(match_operand 8 "cc_register" "") (const_int 0)]) 8386 (match_operator:SI 6 "shiftable_operator" 8387 [(match_operand:SI 1 "s_register_operand" "r") 8388 (match_operand:SI 2 "arm_rhs_operand" "rI")]) 8389 (match_operator:SI 7 "shiftable_operator" 8390 [(match_operand:SI 3 "s_register_operand" "r") 8391 (match_operand:SI 4 "arm_rhs_operand" "rI")])))] 8392 "TARGET_ARM" 8393 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4" 8394 [(set_attr "conds" "use") 8395 (set_attr "length" "8")] 8396) 8397 8398(define_insn "*ifcompare_arith_move" 8399 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8400 (if_then_else:SI (match_operator 6 "arm_comparison_operator" 8401 [(match_operand:SI 2 "s_register_operand" "r,r") 8402 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")]) 8403 (match_operator:SI 7 "shiftable_operator" 8404 [(match_operand:SI 4 "s_register_operand" "r,r") 8405 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")]) 8406 (match_operand:SI 1 "arm_rhs_operand" "0,?rI"))) 8407 (clobber (reg:CC CC_REGNUM))] 8408 "TARGET_ARM" 8409 "* 8410 /* If we have an operation where (op x 0) is the identity operation and 8411 the conditional operator is LT or GE and we are comparing against zero and 8412 everything is in registers then we can do this in two instructions. */ 8413 if (operands[3] == const0_rtx 8414 && GET_CODE (operands[7]) != AND 8415 && GET_CODE (operands[5]) == REG 8416 && GET_CODE (operands[1]) == REG 8417 && REGNO (operands[1]) == REGNO (operands[4]) 8418 && REGNO (operands[4]) != REGNO (operands[0])) 8419 { 8420 if (GET_CODE (operands[6]) == LT) 8421 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\"; 8422 else if (GET_CODE (operands[6]) == GE) 8423 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\"; 8424 } 8425 if (GET_CODE (operands[3]) == CONST_INT 8426 && !const_ok_for_arm (INTVAL (operands[3]))) 8427 output_asm_insn (\"cmn\\t%2, #%n3\", operands); 8428 else 8429 output_asm_insn (\"cmp\\t%2, %3\", operands); 8430 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands); 8431 if (which_alternative != 0) 8432 return \"mov%D6\\t%0, %1\"; 8433 return \"\"; 8434 " 8435 [(set_attr "conds" "clob") 8436 (set_attr "length" "8,12")] 8437) 8438 8439(define_insn "*if_arith_move" 8440 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8441 (if_then_else:SI (match_operator 4 "arm_comparison_operator" 8442 [(match_operand 6 "cc_register" "") (const_int 0)]) 8443 (match_operator:SI 5 "shiftable_operator" 8444 [(match_operand:SI 2 "s_register_operand" "r,r") 8445 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) 8446 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))] 8447 "TARGET_ARM" 8448 "@ 8449 %I5%d4\\t%0, %2, %3 8450 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1" 8451 [(set_attr "conds" "use") 8452 (set_attr "length" "4,8") 8453 (set_attr "type" "*,*")] 8454) 8455 8456(define_insn "*ifcompare_move_arith" 8457 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8458 (if_then_else:SI (match_operator 6 "arm_comparison_operator" 8459 [(match_operand:SI 4 "s_register_operand" "r,r") 8460 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 8461 (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 8462 (match_operator:SI 7 "shiftable_operator" 8463 [(match_operand:SI 2 "s_register_operand" "r,r") 8464 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]))) 8465 (clobber (reg:CC CC_REGNUM))] 8466 "TARGET_ARM" 8467 "* 8468 /* If we have an operation where (op x 0) is the identity operation and 8469 the conditional operator is LT or GE and we are comparing against zero and 8470 everything is in registers then we can do this in two instructions */ 8471 if (operands[5] == const0_rtx 8472 && GET_CODE (operands[7]) != AND 8473 && GET_CODE (operands[3]) == REG 8474 && GET_CODE (operands[1]) == REG 8475 && REGNO (operands[1]) == REGNO (operands[2]) 8476 && REGNO (operands[2]) != REGNO (operands[0])) 8477 { 8478 if (GET_CODE (operands[6]) == GE) 8479 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\"; 8480 else if (GET_CODE (operands[6]) == LT) 8481 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\"; 8482 } 8483 8484 if (GET_CODE (operands[5]) == CONST_INT 8485 && !const_ok_for_arm (INTVAL (operands[5]))) 8486 output_asm_insn (\"cmn\\t%4, #%n5\", operands); 8487 else 8488 output_asm_insn (\"cmp\\t%4, %5\", operands); 8489 8490 if (which_alternative != 0) 8491 output_asm_insn (\"mov%d6\\t%0, %1\", operands); 8492 return \"%I7%D6\\t%0, %2, %3\"; 8493 " 8494 [(set_attr "conds" "clob") 8495 (set_attr "length" "8,12")] 8496) 8497 8498(define_insn "*if_move_arith" 8499 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8500 (if_then_else:SI 8501 (match_operator 4 "arm_comparison_operator" 8502 [(match_operand 6 "cc_register" "") (const_int 0)]) 8503 (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 8504 (match_operator:SI 5 "shiftable_operator" 8505 [(match_operand:SI 2 "s_register_operand" "r,r") 8506 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))] 8507 "TARGET_ARM" 8508 "@ 8509 %I5%D4\\t%0, %2, %3 8510 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1" 8511 [(set_attr "conds" "use") 8512 (set_attr "length" "4,8") 8513 (set_attr "type" "*,*")] 8514) 8515 8516(define_insn "*ifcompare_move_not" 8517 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8518 (if_then_else:SI 8519 (match_operator 5 "arm_comparison_operator" 8520 [(match_operand:SI 3 "s_register_operand" "r,r") 8521 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 8522 (match_operand:SI 1 "arm_not_operand" "0,?rIK") 8523 (not:SI 8524 (match_operand:SI 2 "s_register_operand" "r,r")))) 8525 (clobber (reg:CC CC_REGNUM))] 8526 "TARGET_ARM" 8527 "#" 8528 [(set_attr "conds" "clob") 8529 (set_attr "length" "8,12")] 8530) 8531 8532(define_insn "*if_move_not" 8533 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 8534 (if_then_else:SI 8535 (match_operator 4 "arm_comparison_operator" 8536 [(match_operand 3 "cc_register" "") (const_int 0)]) 8537 (match_operand:SI 1 "arm_not_operand" "0,?rI,K") 8538 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))] 8539 "TARGET_ARM" 8540 "@ 8541 mvn%D4\\t%0, %2 8542 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2 8543 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2" 8544 [(set_attr "conds" "use") 8545 (set_attr "length" "4,8,8")] 8546) 8547 8548(define_insn "*ifcompare_not_move" 8549 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8550 (if_then_else:SI 8551 (match_operator 5 "arm_comparison_operator" 8552 [(match_operand:SI 3 "s_register_operand" "r,r") 8553 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 8554 (not:SI 8555 (match_operand:SI 2 "s_register_operand" "r,r")) 8556 (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) 8557 (clobber (reg:CC CC_REGNUM))] 8558 "TARGET_ARM" 8559 "#" 8560 [(set_attr "conds" "clob") 8561 (set_attr "length" "8,12")] 8562) 8563 8564(define_insn "*if_not_move" 8565 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 8566 (if_then_else:SI 8567 (match_operator 4 "arm_comparison_operator" 8568 [(match_operand 3 "cc_register" "") (const_int 0)]) 8569 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r")) 8570 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] 8571 "TARGET_ARM" 8572 "@ 8573 mvn%d4\\t%0, %2 8574 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2 8575 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2" 8576 [(set_attr "conds" "use") 8577 (set_attr "length" "4,8,8")] 8578) 8579 8580(define_insn "*ifcompare_shift_move" 8581 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8582 (if_then_else:SI 8583 (match_operator 6 "arm_comparison_operator" 8584 [(match_operand:SI 4 "s_register_operand" "r,r") 8585 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 8586 (match_operator:SI 7 "shift_operator" 8587 [(match_operand:SI 2 "s_register_operand" "r,r") 8588 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")]) 8589 (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) 8590 (clobber (reg:CC CC_REGNUM))] 8591 "TARGET_ARM" 8592 "#" 8593 [(set_attr "conds" "clob") 8594 (set_attr "length" "8,12")] 8595) 8596 8597(define_insn "*if_shift_move" 8598 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 8599 (if_then_else:SI 8600 (match_operator 5 "arm_comparison_operator" 8601 [(match_operand 6 "cc_register" "") (const_int 0)]) 8602 (match_operator:SI 4 "shift_operator" 8603 [(match_operand:SI 2 "s_register_operand" "r,r,r") 8604 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")]) 8605 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] 8606 "TARGET_ARM" 8607 "@ 8608 mov%d5\\t%0, %2%S4 8609 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4 8610 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4" 8611 [(set_attr "conds" "use") 8612 (set_attr "shift" "2") 8613 (set_attr "length" "4,8,8")] 8614) 8615 8616(define_insn "*ifcompare_move_shift" 8617 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8618 (if_then_else:SI 8619 (match_operator 6 "arm_comparison_operator" 8620 [(match_operand:SI 4 "s_register_operand" "r,r") 8621 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 8622 (match_operand:SI 1 "arm_not_operand" "0,?rIK") 8623 (match_operator:SI 7 "shift_operator" 8624 [(match_operand:SI 2 "s_register_operand" "r,r") 8625 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")]))) 8626 (clobber (reg:CC CC_REGNUM))] 8627 "TARGET_ARM" 8628 "#" 8629 [(set_attr "conds" "clob") 8630 (set_attr "length" "8,12")] 8631) 8632 8633(define_insn "*if_move_shift" 8634 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 8635 (if_then_else:SI 8636 (match_operator 5 "arm_comparison_operator" 8637 [(match_operand 6 "cc_register" "") (const_int 0)]) 8638 (match_operand:SI 1 "arm_not_operand" "0,?rI,K") 8639 (match_operator:SI 4 "shift_operator" 8640 [(match_operand:SI 2 "s_register_operand" "r,r,r") 8641 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))] 8642 "TARGET_ARM" 8643 "@ 8644 mov%D5\\t%0, %2%S4 8645 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4 8646 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4" 8647 [(set_attr "conds" "use") 8648 (set_attr "shift" "2") 8649 (set_attr "length" "4,8,8")] 8650) 8651 8652(define_insn "*ifcompare_shift_shift" 8653 [(set (match_operand:SI 0 "s_register_operand" "=r") 8654 (if_then_else:SI 8655 (match_operator 7 "arm_comparison_operator" 8656 [(match_operand:SI 5 "s_register_operand" "r") 8657 (match_operand:SI 6 "arm_add_operand" "rIL")]) 8658 (match_operator:SI 8 "shift_operator" 8659 [(match_operand:SI 1 "s_register_operand" "r") 8660 (match_operand:SI 2 "arm_rhs_operand" "rM")]) 8661 (match_operator:SI 9 "shift_operator" 8662 [(match_operand:SI 3 "s_register_operand" "r") 8663 (match_operand:SI 4 "arm_rhs_operand" "rM")]))) 8664 (clobber (reg:CC CC_REGNUM))] 8665 "TARGET_ARM" 8666 "#" 8667 [(set_attr "conds" "clob") 8668 (set_attr "length" "12")] 8669) 8670 8671(define_insn "*if_shift_shift" 8672 [(set (match_operand:SI 0 "s_register_operand" "=r") 8673 (if_then_else:SI 8674 (match_operator 5 "arm_comparison_operator" 8675 [(match_operand 8 "cc_register" "") (const_int 0)]) 8676 (match_operator:SI 6 "shift_operator" 8677 [(match_operand:SI 1 "s_register_operand" "r") 8678 (match_operand:SI 2 "arm_rhs_operand" "rM")]) 8679 (match_operator:SI 7 "shift_operator" 8680 [(match_operand:SI 3 "s_register_operand" "r") 8681 (match_operand:SI 4 "arm_rhs_operand" "rM")])))] 8682 "TARGET_ARM" 8683 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7" 8684 [(set_attr "conds" "use") 8685 (set_attr "shift" "1") 8686 (set_attr "length" "8")] 8687) 8688 8689(define_insn "*ifcompare_not_arith" 8690 [(set (match_operand:SI 0 "s_register_operand" "=r") 8691 (if_then_else:SI 8692 (match_operator 6 "arm_comparison_operator" 8693 [(match_operand:SI 4 "s_register_operand" "r") 8694 (match_operand:SI 5 "arm_add_operand" "rIL")]) 8695 (not:SI (match_operand:SI 1 "s_register_operand" "r")) 8696 (match_operator:SI 7 "shiftable_operator" 8697 [(match_operand:SI 2 "s_register_operand" "r") 8698 (match_operand:SI 3 "arm_rhs_operand" "rI")]))) 8699 (clobber (reg:CC CC_REGNUM))] 8700 "TARGET_ARM" 8701 "#" 8702 [(set_attr "conds" "clob") 8703 (set_attr "length" "12")] 8704) 8705 8706(define_insn "*if_not_arith" 8707 [(set (match_operand:SI 0 "s_register_operand" "=r") 8708 (if_then_else:SI 8709 (match_operator 5 "arm_comparison_operator" 8710 [(match_operand 4 "cc_register" "") (const_int 0)]) 8711 (not:SI (match_operand:SI 1 "s_register_operand" "r")) 8712 (match_operator:SI 6 "shiftable_operator" 8713 [(match_operand:SI 2 "s_register_operand" "r") 8714 (match_operand:SI 3 "arm_rhs_operand" "rI")])))] 8715 "TARGET_ARM" 8716 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3" 8717 [(set_attr "conds" "use") 8718 (set_attr "length" "8")] 8719) 8720 8721(define_insn "*ifcompare_arith_not" 8722 [(set (match_operand:SI 0 "s_register_operand" "=r") 8723 (if_then_else:SI 8724 (match_operator 6 "arm_comparison_operator" 8725 [(match_operand:SI 4 "s_register_operand" "r") 8726 (match_operand:SI 5 "arm_add_operand" "rIL")]) 8727 (match_operator:SI 7 "shiftable_operator" 8728 [(match_operand:SI 2 "s_register_operand" "r") 8729 (match_operand:SI 3 "arm_rhs_operand" "rI")]) 8730 (not:SI (match_operand:SI 1 "s_register_operand" "r")))) 8731 (clobber (reg:CC CC_REGNUM))] 8732 "TARGET_ARM" 8733 "#" 8734 [(set_attr "conds" "clob") 8735 (set_attr "length" "12")] 8736) 8737 8738(define_insn "*if_arith_not" 8739 [(set (match_operand:SI 0 "s_register_operand" "=r") 8740 (if_then_else:SI 8741 (match_operator 5 "arm_comparison_operator" 8742 [(match_operand 4 "cc_register" "") (const_int 0)]) 8743 (match_operator:SI 6 "shiftable_operator" 8744 [(match_operand:SI 2 "s_register_operand" "r") 8745 (match_operand:SI 3 "arm_rhs_operand" "rI")]) 8746 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))] 8747 "TARGET_ARM" 8748 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3" 8749 [(set_attr "conds" "use") 8750 (set_attr "length" "8")] 8751) 8752 8753(define_insn "*ifcompare_neg_move" 8754 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8755 (if_then_else:SI 8756 (match_operator 5 "arm_comparison_operator" 8757 [(match_operand:SI 3 "s_register_operand" "r,r") 8758 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 8759 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r")) 8760 (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) 8761 (clobber (reg:CC CC_REGNUM))] 8762 "TARGET_ARM" 8763 "#" 8764 [(set_attr "conds" "clob") 8765 (set_attr "length" "8,12")] 8766) 8767 8768(define_insn "*if_neg_move" 8769 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 8770 (if_then_else:SI 8771 (match_operator 4 "arm_comparison_operator" 8772 [(match_operand 3 "cc_register" "") (const_int 0)]) 8773 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r")) 8774 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] 8775 "TARGET_ARM" 8776 "@ 8777 rsb%d4\\t%0, %2, #0 8778 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0 8779 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0" 8780 [(set_attr "conds" "use") 8781 (set_attr "length" "4,8,8")] 8782) 8783 8784(define_insn "*ifcompare_move_neg" 8785 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8786 (if_then_else:SI 8787 (match_operator 5 "arm_comparison_operator" 8788 [(match_operand:SI 3 "s_register_operand" "r,r") 8789 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 8790 (match_operand:SI 1 "arm_not_operand" "0,?rIK") 8791 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r")))) 8792 (clobber (reg:CC CC_REGNUM))] 8793 "TARGET_ARM" 8794 "#" 8795 [(set_attr "conds" "clob") 8796 (set_attr "length" "8,12")] 8797) 8798 8799(define_insn "*if_move_neg" 8800 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 8801 (if_then_else:SI 8802 (match_operator 4 "arm_comparison_operator" 8803 [(match_operand 3 "cc_register" "") (const_int 0)]) 8804 (match_operand:SI 1 "arm_not_operand" "0,?rI,K") 8805 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))] 8806 "TARGET_ARM" 8807 "@ 8808 rsb%D4\\t%0, %2, #0 8809 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0 8810 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0" 8811 [(set_attr "conds" "use") 8812 (set_attr "length" "4,8,8")] 8813) 8814 8815(define_insn "*arith_adjacentmem" 8816 [(set (match_operand:SI 0 "s_register_operand" "=r") 8817 (match_operator:SI 1 "shiftable_operator" 8818 [(match_operand:SI 2 "memory_operand" "m") 8819 (match_operand:SI 3 "memory_operand" "m")])) 8820 (clobber (match_scratch:SI 4 "=r"))] 8821 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])" 8822 "* 8823 { 8824 rtx ldm[3]; 8825 rtx arith[4]; 8826 int val1 = 0, val2 = 0; 8827 8828 if (REGNO (operands[0]) > REGNO (operands[4])) 8829 { 8830 ldm[1] = operands[4]; 8831 ldm[2] = operands[0]; 8832 } 8833 else 8834 { 8835 ldm[1] = operands[0]; 8836 ldm[2] = operands[4]; 8837 } 8838 if (GET_CODE (XEXP (operands[2], 0)) != REG) 8839 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1)); 8840 if (GET_CODE (XEXP (operands[3], 0)) != REG) 8841 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1)); 8842 arith[0] = operands[0]; 8843 arith[3] = operands[1]; 8844 if (val1 < val2) 8845 { 8846 arith[1] = ldm[1]; 8847 arith[2] = ldm[2]; 8848 } 8849 else 8850 { 8851 arith[1] = ldm[2]; 8852 arith[2] = ldm[1]; 8853 } 8854 if (val1 && val2) 8855 { 8856 rtx ops[3]; 8857 ldm[0] = ops[0] = operands[4]; 8858 ops[1] = XEXP (XEXP (operands[2], 0), 0); 8859 ops[2] = XEXP (XEXP (operands[2], 0), 1); 8860 output_add_immediate (ops); 8861 if (val1 < val2) 8862 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); 8863 else 8864 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); 8865 } 8866 else if (val1) 8867 { 8868 ldm[0] = XEXP (operands[3], 0); 8869 if (val1 < val2) 8870 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); 8871 else 8872 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); 8873 } 8874 else 8875 { 8876 ldm[0] = XEXP (operands[2], 0); 8877 if (val1 < val2) 8878 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); 8879 else 8880 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); 8881 } 8882 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith); 8883 return \"\"; 8884 }" 8885 [(set_attr "length" "12") 8886 (set_attr "predicable" "yes") 8887 (set_attr "type" "load")] 8888) 8889 8890;; the arm can support extended pre-inc instructions 8891 8892;; In all these cases, we use operands 0 and 1 for the register being 8893;; incremented because those are the operands that local-alloc will 8894;; tie and these are the pair most likely to be tieable (and the ones 8895;; that will benefit the most). 8896 8897;; We reject the frame pointer if it occurs anywhere in these patterns since 8898;; elimination will cause too many headaches. 8899 8900(define_insn "*strqi_preinc" 8901 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 8902 (match_operand:SI 2 "index_operand" "rJ"))) 8903 (match_operand:QI 3 "s_register_operand" "r")) 8904 (set (match_operand:SI 0 "s_register_operand" "=r") 8905 (plus:SI (match_dup 1) (match_dup 2)))] 8906 "TARGET_ARM 8907 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8908 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8909 && (GET_CODE (operands[2]) != REG 8910 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8911 "str%?b\\t%3, [%0, %2]!" 8912 [(set_attr "type" "store1") 8913 (set_attr "predicable" "yes")] 8914) 8915 8916(define_insn "*strqi_predec" 8917 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8918 (match_operand:SI 2 "s_register_operand" "r"))) 8919 (match_operand:QI 3 "s_register_operand" "r")) 8920 (set (match_operand:SI 0 "s_register_operand" "=r") 8921 (minus:SI (match_dup 1) (match_dup 2)))] 8922 "TARGET_ARM 8923 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8924 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8925 && (GET_CODE (operands[2]) != REG 8926 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8927 "str%?b\\t%3, [%0, -%2]!" 8928 [(set_attr "type" "store1") 8929 (set_attr "predicable" "yes")] 8930) 8931 8932(define_insn "*loadqi_preinc" 8933 [(set (match_operand:QI 3 "s_register_operand" "=r") 8934 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 8935 (match_operand:SI 2 "index_operand" "rJ")))) 8936 (set (match_operand:SI 0 "s_register_operand" "=r") 8937 (plus:SI (match_dup 1) (match_dup 2)))] 8938 "TARGET_ARM 8939 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8940 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8941 && (GET_CODE (operands[2]) != REG 8942 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8943 "ldr%?b\\t%3, [%0, %2]!" 8944 [(set_attr "type" "load") 8945 (set_attr "predicable" "yes")] 8946) 8947 8948(define_insn "*loadqi_predec" 8949 [(set (match_operand:QI 3 "s_register_operand" "=r") 8950 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8951 (match_operand:SI 2 "s_register_operand" "r")))) 8952 (set (match_operand:SI 0 "s_register_operand" "=r") 8953 (minus:SI (match_dup 1) (match_dup 2)))] 8954 "TARGET_ARM 8955 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8956 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8957 && (GET_CODE (operands[2]) != REG 8958 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8959 "ldr%?b\\t%3, [%0, -%2]!" 8960 [(set_attr "type" "load") 8961 (set_attr "predicable" "yes")] 8962) 8963 8964(define_insn "*loadqisi_preinc" 8965 [(set (match_operand:SI 3 "s_register_operand" "=r") 8966 (zero_extend:SI 8967 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 8968 (match_operand:SI 2 "index_operand" "rJ"))))) 8969 (set (match_operand:SI 0 "s_register_operand" "=r") 8970 (plus:SI (match_dup 1) (match_dup 2)))] 8971 "TARGET_ARM 8972 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8973 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8974 && (GET_CODE (operands[2]) != REG 8975 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8976 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi" 8977 [(set_attr "type" "load") 8978 (set_attr "predicable" "yes")] 8979) 8980 8981(define_insn "*loadqisi_predec" 8982 [(set (match_operand:SI 3 "s_register_operand" "=r") 8983 (zero_extend:SI 8984 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8985 (match_operand:SI 2 "s_register_operand" "r"))))) 8986 (set (match_operand:SI 0 "s_register_operand" "=r") 8987 (minus:SI (match_dup 1) (match_dup 2)))] 8988 "TARGET_ARM 8989 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8990 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8991 && (GET_CODE (operands[2]) != REG 8992 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8993 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi" 8994 [(set_attr "type" "load") 8995 (set_attr "predicable" "yes")] 8996) 8997 8998(define_insn "*strsi_preinc" 8999 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 9000 (match_operand:SI 2 "index_operand" "rJ"))) 9001 (match_operand:SI 3 "s_register_operand" "r")) 9002 (set (match_operand:SI 0 "s_register_operand" "=r") 9003 (plus:SI (match_dup 1) (match_dup 2)))] 9004 "TARGET_ARM 9005 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9006 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9007 && (GET_CODE (operands[2]) != REG 9008 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 9009 "str%?\\t%3, [%0, %2]!" 9010 [(set_attr "type" "store1") 9011 (set_attr "predicable" "yes")] 9012) 9013 9014(define_insn "*strsi_predec" 9015 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 9016 (match_operand:SI 2 "s_register_operand" "r"))) 9017 (match_operand:SI 3 "s_register_operand" "r")) 9018 (set (match_operand:SI 0 "s_register_operand" "=r") 9019 (minus:SI (match_dup 1) (match_dup 2)))] 9020 "TARGET_ARM 9021 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9022 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9023 && (GET_CODE (operands[2]) != REG 9024 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 9025 "str%?\\t%3, [%0, -%2]!" 9026 [(set_attr "type" "store1") 9027 (set_attr "predicable" "yes")] 9028) 9029 9030(define_insn "*loadsi_preinc" 9031 [(set (match_operand:SI 3 "s_register_operand" "=r") 9032 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 9033 (match_operand:SI 2 "index_operand" "rJ")))) 9034 (set (match_operand:SI 0 "s_register_operand" "=r") 9035 (plus:SI (match_dup 1) (match_dup 2)))] 9036 "TARGET_ARM 9037 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9038 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9039 && (GET_CODE (operands[2]) != REG 9040 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 9041 "ldr%?\\t%3, [%0, %2]!" 9042 [(set_attr "type" "load") 9043 (set_attr "predicable" "yes")] 9044) 9045 9046(define_insn "*loadsi_predec" 9047 [(set (match_operand:SI 3 "s_register_operand" "=r") 9048 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 9049 (match_operand:SI 2 "s_register_operand" "r")))) 9050 (set (match_operand:SI 0 "s_register_operand" "=r") 9051 (minus:SI (match_dup 1) (match_dup 2)))] 9052 "TARGET_ARM 9053 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9054 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9055 && (GET_CODE (operands[2]) != REG 9056 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 9057 "ldr%?\\t%3, [%0, -%2]!" 9058 [(set_attr "type" "load") 9059 (set_attr "predicable" "yes")] 9060) 9061 9062(define_insn "*loadhi_preinc" 9063 [(set (match_operand:HI 3 "s_register_operand" "=r") 9064 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 9065 (match_operand:SI 2 "index_operand" "rJ")))) 9066 (set (match_operand:SI 0 "s_register_operand" "=r") 9067 (plus:SI (match_dup 1) (match_dup 2)))] 9068 "TARGET_ARM 9069 && !BYTES_BIG_ENDIAN 9070 && !TARGET_MMU_TRAPS 9071 && !arm_arch4 9072 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9073 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9074 && (GET_CODE (operands[2]) != REG 9075 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 9076 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi" 9077 [(set_attr "type" "load") 9078 (set_attr "predicable" "yes")] 9079) 9080 9081(define_insn "*loadhi_predec" 9082 [(set (match_operand:HI 3 "s_register_operand" "=r") 9083 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 9084 (match_operand:SI 2 "s_register_operand" "r")))) 9085 (set (match_operand:SI 0 "s_register_operand" "=r") 9086 (minus:SI (match_dup 1) (match_dup 2)))] 9087 "TARGET_ARM 9088 && !BYTES_BIG_ENDIAN 9089 && !TARGET_MMU_TRAPS 9090 && !arm_arch4 9091 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9092 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9093 && (GET_CODE (operands[2]) != REG 9094 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 9095 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi" 9096 [(set_attr "type" "load") 9097 (set_attr "predicable" "yes")] 9098) 9099 9100(define_insn "*strqi_shiftpreinc" 9101 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator" 9102 [(match_operand:SI 3 "s_register_operand" "r") 9103 (match_operand:SI 4 "const_shift_operand" "n")]) 9104 (match_operand:SI 1 "s_register_operand" "0"))) 9105 (match_operand:QI 5 "s_register_operand" "r")) 9106 (set (match_operand:SI 0 "s_register_operand" "=r") 9107 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 9108 (match_dup 1)))] 9109 "TARGET_ARM 9110 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9111 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9112 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 9113 "str%?b\\t%5, [%0, %3%S2]!" 9114 [(set_attr "type" "store1") 9115 (set_attr "predicable" "yes")] 9116) 9117 9118(define_insn "*strqi_shiftpredec" 9119 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 9120 (match_operator:SI 2 "shift_operator" 9121 [(match_operand:SI 3 "s_register_operand" "r") 9122 (match_operand:SI 4 "const_shift_operand" "n")]))) 9123 (match_operand:QI 5 "s_register_operand" "r")) 9124 (set (match_operand:SI 0 "s_register_operand" "=r") 9125 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 9126 (match_dup 4)])))] 9127 "TARGET_ARM 9128 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9129 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9130 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 9131 "str%?b\\t%5, [%0, -%3%S2]!" 9132 [(set_attr "type" "store1") 9133 (set_attr "predicable" "yes")] 9134) 9135 9136(define_insn "*loadqi_shiftpreinc" 9137 [(set (match_operand:QI 5 "s_register_operand" "=r") 9138 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator" 9139 [(match_operand:SI 3 "s_register_operand" "r") 9140 (match_operand:SI 4 "const_shift_operand" "n")]) 9141 (match_operand:SI 1 "s_register_operand" "0")))) 9142 (set (match_operand:SI 0 "s_register_operand" "=r") 9143 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 9144 (match_dup 1)))] 9145 "TARGET_ARM 9146 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9147 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9148 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 9149 "ldr%?b\\t%5, [%0, %3%S2]!" 9150 [(set_attr "type" "load") 9151 (set_attr "predicable" "yes")] 9152) 9153 9154(define_insn "*loadqi_shiftpredec" 9155 [(set (match_operand:QI 5 "s_register_operand" "=r") 9156 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 9157 (match_operator:SI 2 "shift_operator" 9158 [(match_operand:SI 3 "s_register_operand" "r") 9159 (match_operand:SI 4 "const_shift_operand" "n")])))) 9160 (set (match_operand:SI 0 "s_register_operand" "=r") 9161 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 9162 (match_dup 4)])))] 9163 "TARGET_ARM 9164 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9165 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9166 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 9167 "ldr%?b\\t%5, [%0, -%3%S2]!" 9168 [(set_attr "type" "load") 9169 (set_attr "predicable" "yes")] 9170) 9171 9172(define_insn "*strsi_shiftpreinc" 9173 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator" 9174 [(match_operand:SI 3 "s_register_operand" "r") 9175 (match_operand:SI 4 "const_shift_operand" "n")]) 9176 (match_operand:SI 1 "s_register_operand" "0"))) 9177 (match_operand:SI 5 "s_register_operand" "r")) 9178 (set (match_operand:SI 0 "s_register_operand" "=r") 9179 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 9180 (match_dup 1)))] 9181 "TARGET_ARM 9182 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9183 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9184 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 9185 "str%?\\t%5, [%0, %3%S2]!" 9186 [(set_attr "type" "store1") 9187 (set_attr "predicable" "yes")] 9188) 9189 9190(define_insn "*strsi_shiftpredec" 9191 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 9192 (match_operator:SI 2 "shift_operator" 9193 [(match_operand:SI 3 "s_register_operand" "r") 9194 (match_operand:SI 4 "const_shift_operand" "n")]))) 9195 (match_operand:SI 5 "s_register_operand" "r")) 9196 (set (match_operand:SI 0 "s_register_operand" "=r") 9197 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 9198 (match_dup 4)])))] 9199 "TARGET_ARM 9200 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9201 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9202 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 9203 "str%?\\t%5, [%0, -%3%S2]!" 9204 [(set_attr "type" "store1") 9205 (set_attr "predicable" "yes")] 9206) 9207 9208(define_insn "*loadsi_shiftpreinc" 9209 [(set (match_operand:SI 5 "s_register_operand" "=r") 9210 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator" 9211 [(match_operand:SI 3 "s_register_operand" "r") 9212 (match_operand:SI 4 "const_shift_operand" "n")]) 9213 (match_operand:SI 1 "s_register_operand" "0")))) 9214 (set (match_operand:SI 0 "s_register_operand" "=r") 9215 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 9216 (match_dup 1)))] 9217 "TARGET_ARM 9218 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9219 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9220 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 9221 "ldr%?\\t%5, [%0, %3%S2]!" 9222 [(set_attr "type" "load") 9223 (set_attr "predicable" "yes")] 9224) 9225 9226(define_insn "*loadsi_shiftpredec" 9227 [(set (match_operand:SI 5 "s_register_operand" "=r") 9228 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 9229 (match_operator:SI 2 "shift_operator" 9230 [(match_operand:SI 3 "s_register_operand" "r") 9231 (match_operand:SI 4 "const_shift_operand" "n")])))) 9232 (set (match_operand:SI 0 "s_register_operand" "=r") 9233 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 9234 (match_dup 4)])))] 9235 "TARGET_ARM 9236 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9237 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9238 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 9239 "ldr%?\\t%5, [%0, -%3%S2]!" 9240 [(set_attr "type" "load") 9241 (set_attr "predicable" "yes")]) 9242 9243(define_insn "*loadhi_shiftpreinc" 9244 [(set (match_operand:HI 5 "s_register_operand" "=r") 9245 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator" 9246 [(match_operand:SI 3 "s_register_operand" "r") 9247 (match_operand:SI 4 "const_shift_operand" "n")]) 9248 (match_operand:SI 1 "s_register_operand" "0")))) 9249 (set (match_operand:SI 0 "s_register_operand" "=r") 9250 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 9251 (match_dup 1)))] 9252 "TARGET_ARM 9253 && !BYTES_BIG_ENDIAN 9254 && !TARGET_MMU_TRAPS 9255 && !arm_arch4 9256 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9257 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9258 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 9259 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi" 9260 [(set_attr "type" "load") 9261 (set_attr "predicable" "yes")] 9262) 9263 9264(define_insn "*loadhi_shiftpredec" 9265 [(set (match_operand:HI 5 "s_register_operand" "=r") 9266 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 9267 (match_operator:SI 2 "shift_operator" 9268 [(match_operand:SI 3 "s_register_operand" "r") 9269 (match_operand:SI 4 "const_shift_operand" "n")])))) 9270 (set (match_operand:SI 0 "s_register_operand" "=r") 9271 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 9272 (match_dup 4)])))] 9273 "TARGET_ARM 9274 && !BYTES_BIG_ENDIAN 9275 && !TARGET_MMU_TRAPS 9276 && !arm_arch4 9277 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 9278 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 9279 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 9280 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi" 9281 [(set_attr "type" "load") 9282 (set_attr "predicable" "yes")] 9283) 9284 9285; It can also support extended post-inc expressions, but combine doesn't 9286; try these.... 9287; It doesn't seem worth adding peepholes for anything but the most common 9288; cases since, unlike combine, the increment must immediately follow the load 9289; for this pattern to match. 9290; We must watch to see that the source/destination register isn't also the 9291; same as the base address register, and that if the index is a register, 9292; that it is not the same as the base address register. In such cases the 9293; instruction that we would generate would have UNPREDICTABLE behavior so 9294; we cannot use it. 9295 9296(define_peephole 9297 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r")) 9298 (match_operand:QI 2 "s_register_operand" "r")) 9299 (set (match_dup 0) 9300 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))] 9301 "TARGET_ARM 9302 && (REGNO (operands[2]) != REGNO (operands[0])) 9303 && (GET_CODE (operands[1]) != REG 9304 || (REGNO (operands[1]) != REGNO (operands[0])))" 9305 "str%?b\\t%2, [%0], %1" 9306) 9307 9308(define_peephole 9309 [(set (match_operand:QI 0 "s_register_operand" "=r") 9310 (mem:QI (match_operand:SI 1 "s_register_operand" "+r"))) 9311 (set (match_dup 1) 9312 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))] 9313 "TARGET_ARM 9314 && REGNO (operands[0]) != REGNO(operands[1]) 9315 && (GET_CODE (operands[2]) != REG 9316 || REGNO(operands[0]) != REGNO (operands[2]))" 9317 "ldr%?b\\t%0, [%1], %2" 9318) 9319 9320(define_peephole 9321 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r")) 9322 (match_operand:SI 2 "s_register_operand" "r")) 9323 (set (match_dup 0) 9324 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))] 9325 "TARGET_ARM 9326 && (REGNO (operands[2]) != REGNO (operands[0])) 9327 && (GET_CODE (operands[1]) != REG 9328 || (REGNO (operands[1]) != REGNO (operands[0])))" 9329 "str%?\\t%2, [%0], %1" 9330) 9331 9332(define_peephole 9333 [(set (match_operand:HI 0 "s_register_operand" "=r") 9334 (mem:HI (match_operand:SI 1 "s_register_operand" "+r"))) 9335 (set (match_dup 1) 9336 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))] 9337 "TARGET_ARM 9338 && !BYTES_BIG_ENDIAN 9339 && !TARGET_MMU_TRAPS 9340 && !arm_arch4 9341 && REGNO (operands[0]) != REGNO(operands[1]) 9342 && (GET_CODE (operands[2]) != REG 9343 || REGNO(operands[0]) != REGNO (operands[2]))" 9344 "ldr%?\\t%0, [%1], %2\\t%@ loadhi" 9345) 9346 9347(define_peephole 9348 [(set (match_operand:SI 0 "s_register_operand" "=r") 9349 (mem:SI (match_operand:SI 1 "s_register_operand" "+r"))) 9350 (set (match_dup 1) 9351 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))] 9352 "TARGET_ARM 9353 && REGNO (operands[0]) != REGNO(operands[1]) 9354 && (GET_CODE (operands[2]) != REG 9355 || REGNO(operands[0]) != REGNO (operands[2]))" 9356 "ldr%?\\t%0, [%1], %2" 9357) 9358 9359(define_peephole 9360 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r") 9361 (match_operand:SI 1 "index_operand" "rJ"))) 9362 (match_operand:QI 2 "s_register_operand" "r")) 9363 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))] 9364 "TARGET_ARM 9365 && (REGNO (operands[2]) != REGNO (operands[0])) 9366 && (GET_CODE (operands[1]) != REG 9367 || (REGNO (operands[1]) != REGNO (operands[0])))" 9368 "str%?b\\t%2, [%0, %1]!" 9369) 9370 9371(define_peephole 9372 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator" 9373 [(match_operand:SI 0 "s_register_operand" "r") 9374 (match_operand:SI 1 "const_int_operand" "n")]) 9375 (match_operand:SI 2 "s_register_operand" "+r"))) 9376 (match_operand:QI 3 "s_register_operand" "r")) 9377 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)]) 9378 (match_dup 2)))] 9379 "TARGET_ARM 9380 && (REGNO (operands[3]) != REGNO (operands[2])) 9381 && (REGNO (operands[0]) != REGNO (operands[2]))" 9382 "str%?b\\t%3, [%2, %0%S4]!" 9383) 9384 9385; This pattern is never tried by combine, so do it as a peephole 9386 9387(define_peephole2 9388 [(set (match_operand:SI 0 "s_register_operand" "") 9389 (match_operand:SI 1 "s_register_operand" "")) 9390 (set (reg:CC CC_REGNUM) 9391 (compare:CC (match_dup 1) (const_int 0)))] 9392 "TARGET_ARM 9393 && (!TARGET_CIRRUS 9394 || (!cirrus_fp_register (operands[0], SImode) 9395 && !cirrus_fp_register (operands[1], SImode))) 9396 " 9397 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0))) 9398 (set (match_dup 0) (match_dup 1))])] 9399 "" 9400) 9401 9402; Peepholes to spot possible load- and store-multiples, if the ordering is 9403; reversed, check that the memory references aren't volatile. 9404 9405(define_peephole 9406 [(set (match_operand:SI 0 "s_register_operand" "=r") 9407 (match_operand:SI 4 "memory_operand" "m")) 9408 (set (match_operand:SI 1 "s_register_operand" "=r") 9409 (match_operand:SI 5 "memory_operand" "m")) 9410 (set (match_operand:SI 2 "s_register_operand" "=r") 9411 (match_operand:SI 6 "memory_operand" "m")) 9412 (set (match_operand:SI 3 "s_register_operand" "=r") 9413 (match_operand:SI 7 "memory_operand" "m"))] 9414 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)" 9415 "* 9416 return emit_ldm_seq (operands, 4); 9417 " 9418) 9419 9420(define_peephole 9421 [(set (match_operand:SI 0 "s_register_operand" "=r") 9422 (match_operand:SI 3 "memory_operand" "m")) 9423 (set (match_operand:SI 1 "s_register_operand" "=r") 9424 (match_operand:SI 4 "memory_operand" "m")) 9425 (set (match_operand:SI 2 "s_register_operand" "=r") 9426 (match_operand:SI 5 "memory_operand" "m"))] 9427 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)" 9428 "* 9429 return emit_ldm_seq (operands, 3); 9430 " 9431) 9432 9433(define_peephole 9434 [(set (match_operand:SI 0 "s_register_operand" "=r") 9435 (match_operand:SI 2 "memory_operand" "m")) 9436 (set (match_operand:SI 1 "s_register_operand" "=r") 9437 (match_operand:SI 3 "memory_operand" "m"))] 9438 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)" 9439 "* 9440 return emit_ldm_seq (operands, 2); 9441 " 9442) 9443 9444(define_peephole 9445 [(set (match_operand:SI 4 "memory_operand" "=m") 9446 (match_operand:SI 0 "s_register_operand" "r")) 9447 (set (match_operand:SI 5 "memory_operand" "=m") 9448 (match_operand:SI 1 "s_register_operand" "r")) 9449 (set (match_operand:SI 6 "memory_operand" "=m") 9450 (match_operand:SI 2 "s_register_operand" "r")) 9451 (set (match_operand:SI 7 "memory_operand" "=m") 9452 (match_operand:SI 3 "s_register_operand" "r"))] 9453 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)" 9454 "* 9455 return emit_stm_seq (operands, 4); 9456 " 9457) 9458 9459(define_peephole 9460 [(set (match_operand:SI 3 "memory_operand" "=m") 9461 (match_operand:SI 0 "s_register_operand" "r")) 9462 (set (match_operand:SI 4 "memory_operand" "=m") 9463 (match_operand:SI 1 "s_register_operand" "r")) 9464 (set (match_operand:SI 5 "memory_operand" "=m") 9465 (match_operand:SI 2 "s_register_operand" "r"))] 9466 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)" 9467 "* 9468 return emit_stm_seq (operands, 3); 9469 " 9470) 9471 9472(define_peephole 9473 [(set (match_operand:SI 2 "memory_operand" "=m") 9474 (match_operand:SI 0 "s_register_operand" "r")) 9475 (set (match_operand:SI 3 "memory_operand" "=m") 9476 (match_operand:SI 1 "s_register_operand" "r"))] 9477 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)" 9478 "* 9479 return emit_stm_seq (operands, 2); 9480 " 9481) 9482 9483(define_split 9484 [(set (match_operand:SI 0 "s_register_operand" "") 9485 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "") 9486 (const_int 0)) 9487 (neg:SI (match_operator:SI 2 "arm_comparison_operator" 9488 [(match_operand:SI 3 "s_register_operand" "") 9489 (match_operand:SI 4 "arm_rhs_operand" "")])))) 9490 (clobber (match_operand:SI 5 "s_register_operand" ""))] 9491 "TARGET_ARM" 9492 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31)))) 9493 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 9494 (match_dup 5)))] 9495 "" 9496) 9497 9498;; This split can be used because CC_Z mode implies that the following 9499;; branch will be an equality, or an unsigned inequality, so the sign 9500;; extension is not needed. 9501 9502(define_split 9503 [(set (reg:CC_Z CC_REGNUM) 9504 (compare:CC_Z 9505 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0) 9506 (const_int 24)) 9507 (match_operand 1 "const_int_operand" ""))) 9508 (clobber (match_scratch:SI 2 ""))] 9509 "TARGET_ARM 9510 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) 9511 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)" 9512 [(set (match_dup 2) (zero_extend:SI (match_dup 0))) 9513 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))] 9514 " 9515 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24); 9516 " 9517) 9518 9519(define_expand "prologue" 9520 [(clobber (const_int 0))] 9521 "TARGET_EITHER" 9522 "if (TARGET_ARM) 9523 arm_expand_prologue (); 9524 else 9525 thumb_expand_prologue (); 9526 DONE; 9527 " 9528) 9529 9530(define_expand "epilogue" 9531 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)] 9532 "TARGET_EITHER" 9533 " 9534 if (TARGET_THUMB) 9535 thumb_expand_epilogue (); 9536 else if (USE_RETURN_INSN (FALSE)) 9537 { 9538 emit_jump_insn (gen_return ()); 9539 DONE; 9540 } 9541 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode, 9542 gen_rtvec (1, 9543 gen_rtx_RETURN (VOIDmode)), 9544 VUNSPEC_EPILOGUE)); 9545 DONE; 9546 " 9547) 9548 9549;; Note - although unspec_volatile's USE all hard registers, 9550;; USEs are ignored after relaod has completed. Thus we need 9551;; to add an unspec of the link register to ensure that flow 9552;; does not think that it is unused by the sibcall branch that 9553;; will replace the standard function epilogue. 9554(define_insn "sibcall_epilogue" 9555 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE) 9556 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])] 9557 "TARGET_ARM" 9558 "* 9559 if (use_return_insn (FALSE, next_nonnote_insn (insn))) 9560 return output_return_instruction (const_true_rtx, FALSE, FALSE); 9561 return arm_output_epilogue (next_nonnote_insn (insn)); 9562 " 9563;; Length is absolute worst case 9564 [(set_attr "length" "44") 9565 (set_attr "type" "block") 9566 ;; We don't clobber the conditions, but the potential length of this 9567 ;; operation is sufficient to make conditionalizing the sequence 9568 ;; unlikely to be profitable. 9569 (set_attr "conds" "clob")] 9570) 9571 9572(define_insn "*epilogue_insns" 9573 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)] 9574 "TARGET_EITHER" 9575 "* 9576 if (TARGET_ARM) 9577 return arm_output_epilogue (NULL); 9578 else /* TARGET_THUMB */ 9579 return thumb_unexpanded_epilogue (); 9580 " 9581 ; Length is absolute worst case 9582 [(set_attr "length" "44") 9583 (set_attr "type" "block") 9584 ;; We don't clobber the conditions, but the potential length of this 9585 ;; operation is sufficient to make conditionalizing the sequence 9586 ;; unlikely to be profitable. 9587 (set_attr "conds" "clob")] 9588) 9589 9590(define_expand "eh_epilogue" 9591 [(use (match_operand:SI 0 "register_operand" "")) 9592 (use (match_operand:SI 1 "register_operand" "")) 9593 (use (match_operand:SI 2 "register_operand" ""))] 9594 "TARGET_EITHER" 9595 " 9596 { 9597 cfun->machine->eh_epilogue_sp_ofs = operands[1]; 9598 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2) 9599 { 9600 rtx ra = gen_rtx_REG (Pmode, 2); 9601 9602 emit_move_insn (ra, operands[2]); 9603 operands[2] = ra; 9604 } 9605 /* This is a hack -- we may have crystalized the function type too 9606 early. */ 9607 cfun->machine->func_type = 0; 9608 }" 9609) 9610 9611;; This split is only used during output to reduce the number of patterns 9612;; that need assembler instructions adding to them. We allowed the setting 9613;; of the conditions to be implicit during rtl generation so that 9614;; the conditional compare patterns would work. However this conflicts to 9615;; some extent with the conditional data operations, so we have to split them 9616;; up again here. 9617 9618(define_split 9619 [(set (match_operand:SI 0 "s_register_operand" "") 9620 (if_then_else:SI (match_operator 1 "arm_comparison_operator" 9621 [(match_operand 2 "" "") (match_operand 3 "" "")]) 9622 (match_dup 0) 9623 (match_operand 4 "" ""))) 9624 (clobber (reg:CC CC_REGNUM))] 9625 "TARGET_ARM && reload_completed" 9626 [(set (match_dup 5) (match_dup 6)) 9627 (cond_exec (match_dup 7) 9628 (set (match_dup 0) (match_dup 4)))] 9629 " 9630 { 9631 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 9632 operands[2], operands[3]); 9633 enum rtx_code rc = GET_CODE (operands[1]); 9634 9635 operands[5] = gen_rtx_REG (mode, CC_REGNUM); 9636 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]); 9637 if (mode == CCFPmode || mode == CCFPEmode) 9638 rc = reverse_condition_maybe_unordered (rc); 9639 else 9640 rc = reverse_condition (rc); 9641 9642 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx); 9643 }" 9644) 9645 9646(define_split 9647 [(set (match_operand:SI 0 "s_register_operand" "") 9648 (if_then_else:SI (match_operator 1 "arm_comparison_operator" 9649 [(match_operand 2 "" "") (match_operand 3 "" "")]) 9650 (match_operand 4 "" "") 9651 (match_dup 0))) 9652 (clobber (reg:CC CC_REGNUM))] 9653 "TARGET_ARM && reload_completed" 9654 [(set (match_dup 5) (match_dup 6)) 9655 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)]) 9656 (set (match_dup 0) (match_dup 4)))] 9657 " 9658 { 9659 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 9660 operands[2], operands[3]); 9661 9662 operands[5] = gen_rtx_REG (mode, CC_REGNUM); 9663 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]); 9664 }" 9665) 9666 9667(define_split 9668 [(set (match_operand:SI 0 "s_register_operand" "") 9669 (if_then_else:SI (match_operator 1 "arm_comparison_operator" 9670 [(match_operand 2 "" "") (match_operand 3 "" "")]) 9671 (match_operand 4 "" "") 9672 (match_operand 5 "" ""))) 9673 (clobber (reg:CC CC_REGNUM))] 9674 "TARGET_ARM && reload_completed" 9675 [(set (match_dup 6) (match_dup 7)) 9676 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)]) 9677 (set (match_dup 0) (match_dup 4))) 9678 (cond_exec (match_dup 8) 9679 (set (match_dup 0) (match_dup 5)))] 9680 " 9681 { 9682 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 9683 operands[2], operands[3]); 9684 enum rtx_code rc = GET_CODE (operands[1]); 9685 9686 operands[6] = gen_rtx_REG (mode, CC_REGNUM); 9687 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]); 9688 if (mode == CCFPmode || mode == CCFPEmode) 9689 rc = reverse_condition_maybe_unordered (rc); 9690 else 9691 rc = reverse_condition (rc); 9692 9693 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx); 9694 }" 9695) 9696 9697(define_split 9698 [(set (match_operand:SI 0 "s_register_operand" "") 9699 (if_then_else:SI (match_operator 1 "arm_comparison_operator" 9700 [(match_operand:SI 2 "s_register_operand" "") 9701 (match_operand:SI 3 "arm_add_operand" "")]) 9702 (match_operand:SI 4 "arm_rhs_operand" "") 9703 (not:SI 9704 (match_operand:SI 5 "s_register_operand" "")))) 9705 (clobber (reg:CC CC_REGNUM))] 9706 "TARGET_ARM && reload_completed" 9707 [(set (match_dup 6) (match_dup 7)) 9708 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)]) 9709 (set (match_dup 0) (match_dup 4))) 9710 (cond_exec (match_dup 8) 9711 (set (match_dup 0) (not:SI (match_dup 5))))] 9712 " 9713 { 9714 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 9715 operands[2], operands[3]); 9716 enum rtx_code rc = GET_CODE (operands[1]); 9717 9718 operands[6] = gen_rtx_REG (mode, CC_REGNUM); 9719 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]); 9720 if (mode == CCFPmode || mode == CCFPEmode) 9721 rc = reverse_condition_maybe_unordered (rc); 9722 else 9723 rc = reverse_condition (rc); 9724 9725 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx); 9726 }" 9727) 9728 9729(define_insn "*cond_move_not" 9730 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 9731 (if_then_else:SI (match_operator 4 "arm_comparison_operator" 9732 [(match_operand 3 "cc_register" "") (const_int 0)]) 9733 (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 9734 (not:SI 9735 (match_operand:SI 2 "s_register_operand" "r,r"))))] 9736 "TARGET_ARM" 9737 "@ 9738 mvn%D4\\t%0, %2 9739 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2" 9740 [(set_attr "conds" "use") 9741 (set_attr "length" "4,8")] 9742) 9743 9744;; The next two patterns occur when an AND operation is followed by a 9745;; scc insn sequence 9746 9747(define_insn "*sign_extract_onebit" 9748 [(set (match_operand:SI 0 "s_register_operand" "=r") 9749 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r") 9750 (const_int 1) 9751 (match_operand:SI 2 "const_int_operand" "n"))) 9752 (clobber (reg:CC CC_REGNUM))] 9753 "TARGET_ARM" 9754 "* 9755 operands[2] = GEN_INT (1 << INTVAL (operands[2])); 9756 output_asm_insn (\"ands\\t%0, %1, %2\", operands); 9757 return \"mvnne\\t%0, #0\"; 9758 " 9759 [(set_attr "conds" "clob") 9760 (set_attr "length" "8")] 9761) 9762 9763(define_insn "*not_signextract_onebit" 9764 [(set (match_operand:SI 0 "s_register_operand" "=r") 9765 (not:SI 9766 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r") 9767 (const_int 1) 9768 (match_operand:SI 2 "const_int_operand" "n")))) 9769 (clobber (reg:CC CC_REGNUM))] 9770 "TARGET_ARM" 9771 "* 9772 operands[2] = GEN_INT (1 << INTVAL (operands[2])); 9773 output_asm_insn (\"tst\\t%1, %2\", operands); 9774 output_asm_insn (\"mvneq\\t%0, #0\", operands); 9775 return \"movne\\t%0, #0\"; 9776 " 9777 [(set_attr "conds" "clob") 9778 (set_attr "length" "12")] 9779) 9780 9781;; Push multiple registers to the stack. Registers are in parallel (use ...) 9782;; expressions. For simplicity, the first register is also in the unspec 9783;; part. 9784(define_insn "*push_multi" 9785 [(match_parallel 2 "multi_register_push" 9786 [(set (match_operand:BLK 0 "memory_operand" "=m") 9787 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 9788 UNSPEC_PUSH_MULT))])] 9789 "TARGET_ARM" 9790 "* 9791 { 9792 int num_saves = XVECLEN (operands[2], 0); 9793 9794 /* For the StrongARM at least it is faster to 9795 use STR to store only a single register. */ 9796 if (num_saves == 1) 9797 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands); 9798 else 9799 { 9800 int i; 9801 char pattern[100]; 9802 9803 strcpy (pattern, \"stmfd\\t%m0!, {%1\"); 9804 9805 for (i = 1; i < num_saves; i++) 9806 { 9807 strcat (pattern, \", %|\"); 9808 strcat (pattern, 9809 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]); 9810 } 9811 9812 strcat (pattern, \"}\"); 9813 output_asm_insn (pattern, operands); 9814 } 9815 9816 return \"\"; 9817 }" 9818 [(set_attr "type" "store4")] 9819) 9820 9821(define_insn "stack_tie" 9822 [(set (mem:BLK (scratch)) 9823 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r") 9824 (match_operand:SI 1 "s_register_operand" "r")] 9825 UNSPEC_PRLG_STK))] 9826 "" 9827 "" 9828 [(set_attr "length" "0")] 9829) 9830 9831;; Similarly for the floating point registers 9832(define_insn "*push_fp_multi" 9833 [(match_parallel 2 "multi_register_push" 9834 [(set (match_operand:BLK 0 "memory_operand" "=m") 9835 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")] 9836 UNSPEC_PUSH_MULT))])] 9837 "TARGET_ARM" 9838 "* 9839 { 9840 char pattern[100]; 9841 9842 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0)); 9843 output_asm_insn (pattern, operands); 9844 return \"\"; 9845 }" 9846 [(set_attr "type" "f_store")] 9847) 9848 9849;; Special patterns for dealing with the constant pool 9850 9851(define_insn "align_4" 9852 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)] 9853 "TARGET_EITHER" 9854 "* 9855 assemble_align (32); 9856 return \"\"; 9857 " 9858) 9859 9860(define_insn "align_8" 9861 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)] 9862 "TARGET_REALLY_IWMMXT" 9863 "* 9864 assemble_align (64); 9865 return \"\"; 9866 " 9867) 9868 9869(define_insn "consttable_end" 9870 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)] 9871 "TARGET_EITHER" 9872 "* 9873 making_const_table = FALSE; 9874 return \"\"; 9875 " 9876) 9877 9878(define_insn "consttable_1" 9879 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)] 9880 "TARGET_THUMB" 9881 "* 9882 making_const_table = TRUE; 9883 assemble_integer (operands[0], 1, BITS_PER_WORD, 1); 9884 assemble_zeros (3); 9885 return \"\"; 9886 " 9887 [(set_attr "length" "4")] 9888) 9889 9890(define_insn "consttable_2" 9891 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)] 9892 "TARGET_THUMB" 9893 "* 9894 making_const_table = TRUE; 9895 assemble_integer (operands[0], 2, BITS_PER_WORD, 1); 9896 assemble_zeros (2); 9897 return \"\"; 9898 " 9899 [(set_attr "length" "4")] 9900) 9901 9902(define_insn "consttable_4" 9903 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)] 9904 "TARGET_EITHER" 9905 "* 9906 { 9907 making_const_table = TRUE; 9908 switch (GET_MODE_CLASS (GET_MODE (operands[0]))) 9909 { 9910 case MODE_FLOAT: 9911 { 9912 REAL_VALUE_TYPE r; 9913 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]); 9914 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD); 9915 break; 9916 } 9917 default: 9918 assemble_integer (operands[0], 4, BITS_PER_WORD, 1); 9919 break; 9920 } 9921 return \"\"; 9922 }" 9923 [(set_attr "length" "4")] 9924) 9925 9926(define_insn "consttable_8" 9927 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)] 9928 "TARGET_EITHER" 9929 "* 9930 { 9931 making_const_table = TRUE; 9932 switch (GET_MODE_CLASS (GET_MODE (operands[0]))) 9933 { 9934 case MODE_FLOAT: 9935 { 9936 REAL_VALUE_TYPE r; 9937 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]); 9938 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD); 9939 break; 9940 } 9941 default: 9942 assemble_integer (operands[0], 8, BITS_PER_WORD, 1); 9943 break; 9944 } 9945 return \"\"; 9946 }" 9947 [(set_attr "length" "8")] 9948) 9949 9950;; Miscellaneous Thumb patterns 9951 9952(define_expand "tablejump" 9953 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "")) 9954 (use (label_ref (match_operand 1 "" "")))])] 9955 "TARGET_THUMB" 9956 " 9957 if (flag_pic) 9958 { 9959 /* Hopefully, CSE will eliminate this copy. */ 9960 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1])); 9961 rtx reg2 = gen_reg_rtx (SImode); 9962 9963 emit_insn (gen_addsi3 (reg2, operands[0], reg1)); 9964 operands[0] = reg2; 9965 } 9966 " 9967) 9968 9969(define_insn "*thumb_tablejump" 9970 [(set (pc) (match_operand:SI 0 "register_operand" "l*r")) 9971 (use (label_ref (match_operand 1 "" "")))] 9972 "TARGET_THUMB" 9973 "mov\\t%|pc, %0" 9974 [(set_attr "length" "2")] 9975) 9976 9977;; V5 Instructions, 9978 9979(define_insn "clzsi2" 9980 [(set (match_operand:SI 0 "s_register_operand" "=r") 9981 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))] 9982 "TARGET_ARM && arm_arch5" 9983 "clz%?\\t%0, %1" 9984 [(set_attr "predicable" "yes")]) 9985 9986(define_expand "ffssi2" 9987 [(set (match_operand:SI 0 "s_register_operand" "") 9988 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))] 9989 "TARGET_ARM && arm_arch5" 9990 " 9991 { 9992 rtx t1, t2, t3; 9993 9994 t1 = gen_reg_rtx (SImode); 9995 t2 = gen_reg_rtx (SImode); 9996 t3 = gen_reg_rtx (SImode); 9997 9998 emit_insn (gen_negsi2 (t1, operands[1])); 9999 emit_insn (gen_andsi3 (t2, operands[1], t1)); 10000 emit_insn (gen_clzsi2 (t3, t2)); 10001 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3)); 10002 DONE; 10003 }" 10004) 10005 10006(define_expand "ctzsi2" 10007 [(set (match_operand:SI 0 "s_register_operand" "") 10008 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))] 10009 "TARGET_ARM && arm_arch5" 10010 " 10011 { 10012 rtx t1, t2, t3; 10013 10014 t1 = gen_reg_rtx (SImode); 10015 t2 = gen_reg_rtx (SImode); 10016 t3 = gen_reg_rtx (SImode); 10017 10018 emit_insn (gen_negsi2 (t1, operands[1])); 10019 emit_insn (gen_andsi3 (t2, operands[1], t1)); 10020 emit_insn (gen_clzsi2 (t3, t2)); 10021 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3)); 10022 DONE; 10023 }" 10024) 10025 10026;; V5E instructions. 10027 10028(define_insn "prefetch" 10029 [(prefetch (match_operand:SI 0 "address_operand" "p") 10030 (match_operand:SI 1 "" "") 10031 (match_operand:SI 2 "" ""))] 10032 "TARGET_ARM && arm_arch5e" 10033 "pld\\t%a0") 10034 10035;; General predication pattern 10036 10037(define_cond_exec 10038 [(match_operator 0 "arm_comparison_operator" 10039 [(match_operand 1 "cc_register" "") 10040 (const_int 0)])] 10041 "TARGET_ARM" 10042 "" 10043) 10044 10045(define_insn "prologue_use" 10046 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)] 10047 "" 10048 "%@ %0 needed for prologue" 10049) 10050 10051;; Load the FPA co-processor patterns 10052(include "fpa.md") 10053;; Load the Maverick co-processor patterns 10054(include "cirrus.md") 10055;; Load the Intel Wireless Multimedia Extension patterns 10056(include "iwmmxt.md") 10057