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