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