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