arm.md revision 96263
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)" 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) 0))] 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) (subreg:QI (match_dup 2) 0))] 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 }" 4355) 4356 4357(define_expand "storehi_single_op" 4358 [(set (match_operand:HI 0 "memory_operand" "") 4359 (match_operand:HI 1 "general_operand" ""))] 4360 "TARGET_ARM && arm_arch4" 4361 " 4362 if (!s_register_operand (operands[1], HImode)) 4363 operands[1] = copy_to_mode_reg (HImode, operands[1]); 4364 " 4365) 4366 4367(define_expand "movhi" 4368 [(set (match_operand:HI 0 "general_operand" "") 4369 (match_operand:HI 1 "general_operand" ""))] 4370 "TARGET_EITHER" 4371 " 4372 if (TARGET_ARM) 4373 { 4374 if (!no_new_pseudos) 4375 { 4376 if (GET_CODE (operands[0]) == MEM) 4377 { 4378 if (arm_arch4) 4379 { 4380 emit_insn (gen_storehi_single_op (operands[0], operands[1])); 4381 DONE; 4382 } 4383 if (GET_CODE (operands[1]) == CONST_INT) 4384 emit_insn (gen_storeinthi (operands[0], operands[1])); 4385 else 4386 { 4387 if (GET_CODE (operands[1]) == MEM) 4388 operands[1] = force_reg (HImode, operands[1]); 4389 if (BYTES_BIG_ENDIAN) 4390 emit_insn (gen_storehi_bigend (operands[1], operands[0])); 4391 else 4392 emit_insn (gen_storehi (operands[1], operands[0])); 4393 } 4394 DONE; 4395 } 4396 /* Sign extend a constant, and keep it in an SImode reg. */ 4397 else if (GET_CODE (operands[1]) == CONST_INT) 4398 { 4399 rtx reg = gen_reg_rtx (SImode); 4400 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff; 4401 4402 /* If the constant is already valid, leave it alone. */ 4403 if (!const_ok_for_arm (val)) 4404 { 4405 /* If setting all the top bits will make the constant 4406 loadable in a single instruction, then set them. 4407 Otherwise, sign extend the number. */ 4408 4409 if (const_ok_for_arm (~(val | ~0xffff))) 4410 val |= ~0xffff; 4411 else if (val & 0x8000) 4412 val |= ~0xffff; 4413 } 4414 4415 emit_insn (gen_movsi (reg, GEN_INT (val))); 4416 operands[1] = gen_rtx_SUBREG (HImode, reg, 0); 4417 } 4418 else if (!arm_arch4) 4419 { 4420 /* Note: We do not have to worry about TARGET_MMU_TRAPS 4421 for v4 and up architectures because LDRH instructions will 4422 be used to access the HI values, and these cannot generate 4423 unaligned word access faults in the MMU. */ 4424 if (GET_CODE (operands[1]) == MEM) 4425 { 4426 if (TARGET_MMU_TRAPS) 4427 { 4428 rtx base; 4429 rtx offset = const0_rtx; 4430 rtx reg = gen_reg_rtx (SImode); 4431 4432 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG 4433 || (GET_CODE (base) == PLUS 4434 && (GET_CODE (offset = XEXP (base, 1)) 4435 == CONST_INT) 4436 && ((INTVAL(offset) & 1) != 1) 4437 && GET_CODE (base = XEXP (base, 0)) == REG)) 4438 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32) 4439 { 4440 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3; 4441 rtx new; 4442 4443 new = gen_rtx_MEM (SImode, 4444 plus_constant (base, new_offset)); 4445 MEM_COPY_ATTRIBUTES (new, operands[1]); 4446 emit_insn (gen_movsi (reg, new)); 4447 if (((INTVAL (offset) & 2) != 0) 4448 ^ (BYTES_BIG_ENDIAN ? 1 : 0)) 4449 { 4450 rtx reg2 = gen_reg_rtx (SImode); 4451 4452 emit_insn (gen_lshrsi3 (reg2, reg, 4453 GEN_INT (16))); 4454 reg = reg2; 4455 } 4456 } 4457 else 4458 emit_insn (gen_movhi_bytes (reg, operands[1])); 4459 4460 operands[1] = gen_lowpart (HImode, reg); 4461 } 4462 else if (BYTES_BIG_ENDIAN) 4463 { 4464 rtx base; 4465 rtx offset = const0_rtx; 4466 4467 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG 4468 || (GET_CODE (base) == PLUS 4469 && (GET_CODE (offset = XEXP (base, 1)) 4470 == CONST_INT) 4471 && GET_CODE (base = XEXP (base, 0)) == REG)) 4472 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32) 4473 { 4474 rtx reg = gen_reg_rtx (SImode); 4475 rtx new; 4476 4477 if ((INTVAL (offset) & 2) == 2) 4478 { 4479 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2; 4480 new = gen_rtx_MEM (SImode, 4481 plus_constant (base, 4482 new_offset)); 4483 MEM_COPY_ATTRIBUTES (new, operands[1]); 4484 emit_insn (gen_movsi (reg, new)); 4485 } 4486 else 4487 { 4488 new = gen_rtx_MEM (SImode, 4489 XEXP (operands[1], 0)); 4490 MEM_COPY_ATTRIBUTES (new, operands[1]); 4491 emit_insn (gen_rotated_loadsi (reg, new)); 4492 } 4493 4494 operands[1] = gen_lowpart (HImode, reg); 4495 } 4496 else 4497 { 4498 emit_insn (gen_movhi_bigend (operands[0], 4499 operands[1])); 4500 DONE; 4501 } 4502 } 4503 } 4504 } 4505 } 4506 /* Handle loading a large integer during reload */ 4507 else if (GET_CODE (operands[1]) == CONST_INT 4508 && !const_ok_for_arm (INTVAL (operands[1])) 4509 && !const_ok_for_arm (~INTVAL (operands[1]))) 4510 { 4511 /* Writing a constant to memory needs a scratch, which should 4512 be handled with SECONDARY_RELOADs. */ 4513 if (GET_CODE (operands[0]) != REG) 4514 abort (); 4515 4516 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0); 4517 emit_insn (gen_movsi (operands[0], operands[1])); 4518 DONE; 4519 } 4520 } 4521 else /* TARGET_THUMB */ 4522 { 4523 if (!no_new_pseudos) 4524 { 4525 if (GET_CODE (operands[0]) != REG) 4526 operands[1] = force_reg (HImode, operands[1]); 4527 4528 /* ??? We shouldn't really get invalid addresses here, but this can 4529 happen if we are passed a SP (never OK for HImode/QImode) or 4530 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 4531 HImode/QImode) relative address. */ 4532 /* ??? This should perhaps be fixed elsewhere, for instance, in 4533 fixup_stack_1, by checking for other kinds of invalid addresses, 4534 e.g. a bare reference to a virtual register. This may confuse the 4535 alpha though, which must handle this case differently. */ 4536 if (GET_CODE (operands[0]) == MEM 4537 && !memory_address_p (GET_MODE (operands[0]), 4538 XEXP (operands[0], 0))) 4539 operands[0] 4540 = replace_equiv_address (operands[0], 4541 copy_to_reg (XEXP (operands[0], 0))); 4542 4543 if (GET_CODE (operands[1]) == MEM 4544 && !memory_address_p (GET_MODE (operands[1]), 4545 XEXP (operands[1], 0))) 4546 operands[1] 4547 = replace_equiv_address (operands[1], 4548 copy_to_reg (XEXP (operands[1], 0))); 4549 } 4550 /* Handle loading a large integer during reload */ 4551 else if (GET_CODE (operands[1]) == CONST_INT 4552 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I')) 4553 { 4554 /* Writing a constant to memory needs a scratch, which should 4555 be handled with SECONDARY_RELOADs. */ 4556 if (GET_CODE (operands[0]) != REG) 4557 abort (); 4558 4559 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0); 4560 emit_insn (gen_movsi (operands[0], operands[1])); 4561 DONE; 4562 } 4563 } 4564 " 4565) 4566 4567(define_insn "*thumb_movhi_insn" 4568 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l") 4569 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))] 4570 "TARGET_THUMB 4571 && ( register_operand (operands[0], HImode) 4572 || register_operand (operands[1], HImode))" 4573 "* 4574 switch (which_alternative) 4575 { 4576 case 0: return \"add %0, %1, #0\"; 4577 case 2: return \"strh %1, %0\"; 4578 case 3: return \"mov %0, %1\"; 4579 case 4: return \"mov %0, %1\"; 4580 case 5: return \"mov %0, %1\"; 4581 default: abort (); 4582 case 1: 4583 /* The stack pointer can end up being taken as an index register. 4584 Catch this case here and deal with it. */ 4585 if (GET_CODE (XEXP (operands[1], 0)) == PLUS 4586 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG 4587 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM) 4588 { 4589 rtx ops[2]; 4590 ops[0] = operands[0]; 4591 ops[1] = XEXP (XEXP (operands[1], 0), 0); 4592 4593 output_asm_insn (\"mov %0, %1\", ops); 4594 4595 XEXP (XEXP (operands[1], 0), 0) = operands[0]; 4596 4597 } 4598 return \"ldrh %0, %1\"; 4599 }" 4600 [(set_attr "length" "2,4,2,2,2,2") 4601 (set_attr "type" "*,load,store1,*,*,*") 4602 (set_attr "pool_range" "*,64,*,*,*,*")] 4603) 4604 4605 4606(define_insn "rotated_loadsi" 4607 [(set (match_operand:SI 0 "s_register_operand" "=r") 4608 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o") 4609 (const_int 16)))] 4610 "TARGET_ARM && (!TARGET_MMU_TRAPS)" 4611 "* 4612 { 4613 rtx ops[2]; 4614 4615 ops[0] = operands[0]; 4616 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2)); 4617 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops); 4618 return \"\"; 4619 }" 4620 [(set_attr "type" "load") 4621 (set_attr "predicable" "yes")] 4622) 4623 4624(define_expand "movhi_bytes" 4625 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" ""))) 4626 (set (match_dup 3) 4627 (zero_extend:SI (match_dup 6))) 4628 (set (match_operand:SI 0 "" "") 4629 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))] 4630 "TARGET_ARM" 4631 " 4632 { 4633 rtx mem1, mem2; 4634 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); 4635 4636 mem1 = gen_rtx_MEM (QImode, addr); 4637 MEM_COPY_ATTRIBUTES (mem1, operands[1]); 4638 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1)); 4639 MEM_COPY_ATTRIBUTES (mem2, operands[1]); 4640 operands[0] = gen_lowpart (SImode, operands[0]); 4641 operands[1] = mem1; 4642 operands[2] = gen_reg_rtx (SImode); 4643 operands[3] = gen_reg_rtx (SImode); 4644 operands[6] = mem2; 4645 4646 if (BYTES_BIG_ENDIAN) 4647 { 4648 operands[4] = operands[2]; 4649 operands[5] = operands[3]; 4650 } 4651 else 4652 { 4653 operands[4] = operands[3]; 4654 operands[5] = operands[2]; 4655 } 4656 }" 4657) 4658 4659(define_expand "movhi_bigend" 4660 [(set (match_dup 2) 4661 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0) 4662 (const_int 16))) 4663 (set (match_dup 3) 4664 (ashiftrt:SI (match_dup 2) (const_int 16))) 4665 (set (match_operand:HI 0 "s_register_operand" "") 4666 (subreg:HI (match_dup 3) 0))] 4667 "TARGET_ARM" 4668 " 4669 operands[2] = gen_reg_rtx (SImode); 4670 operands[3] = gen_reg_rtx (SImode); 4671 " 4672) 4673 4674;; Pattern to recognise insn generated default case above 4675(define_insn "*movhi_insn_arch4" 4676 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r") 4677 (match_operand:HI 1 "general_operand" "rI,K,r,m"))] 4678 "TARGET_ARM 4679 && arm_arch4 4680 && (GET_CODE (operands[1]) != CONST_INT 4681 || const_ok_for_arm (INTVAL (operands[1])) 4682 || const_ok_for_arm (~INTVAL (operands[1])))" 4683 "@ 4684 mov%?\\t%0, %1\\t%@ movhi 4685 mvn%?\\t%0, #%B1\\t%@ movhi 4686 str%?h\\t%1, %0\\t%@ movhi 4687 ldr%?h\\t%0, %1\\t%@ movhi" 4688 [(set_attr "type" "*,*,store1,load") 4689 (set_attr "predicable" "yes") 4690 (set_attr "pool_range" "*,*,*,256") 4691 (set_attr "neg_pool_range" "*,*,*,244")] 4692) 4693 4694(define_insn "*movhi_insn_littleend" 4695 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r") 4696 (match_operand:HI 1 "general_operand" "rI,K,m"))] 4697 "TARGET_ARM 4698 && !arm_arch4 4699 && !BYTES_BIG_ENDIAN 4700 && !TARGET_MMU_TRAPS 4701 && (GET_CODE (operands[1]) != CONST_INT 4702 || const_ok_for_arm (INTVAL (operands[1])) 4703 || const_ok_for_arm (~INTVAL (operands[1])))" 4704 "@ 4705 mov%?\\t%0, %1\\t%@ movhi 4706 mvn%?\\t%0, #%B1\\t%@ movhi 4707 ldr%?\\t%0, %1\\t%@ movhi" 4708 [(set_attr "type" "*,*,load") 4709 (set_attr "predicable" "yes") 4710 (set_attr "pool_range" "4096") 4711 (set_attr "neg_pool_range" "4084")] 4712) 4713 4714(define_insn "*movhi_insn_bigend" 4715 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r") 4716 (match_operand:HI 1 "general_operand" "rI,K,m"))] 4717 "TARGET_ARM 4718 && !arm_arch4 4719 && BYTES_BIG_ENDIAN 4720 && !TARGET_MMU_TRAPS 4721 && (GET_CODE (operands[1]) != CONST_INT 4722 || const_ok_for_arm (INTVAL (operands[1])) 4723 || const_ok_for_arm (~INTVAL (operands[1])))" 4724 "@ 4725 mov%?\\t%0, %1\\t%@ movhi 4726 mvn%?\\t%0, #%B1\\t%@ movhi 4727 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16" 4728 [(set_attr "type" "*,*,load") 4729 (set_attr "predicable" "yes") 4730 (set_attr "length" "4,4,8") 4731 (set_attr "pool_range" "*,*,4092") 4732 (set_attr "neg_pool_range" "*,*,4084")] 4733) 4734 4735(define_insn "*loadhi_si_bigend" 4736 [(set (match_operand:SI 0 "s_register_operand" "=r") 4737 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0) 4738 (const_int 16)))] 4739 "TARGET_ARM 4740 && BYTES_BIG_ENDIAN 4741 && !TARGET_MMU_TRAPS" 4742 "ldr%?\\t%0, %1\\t%@ movhi_bigend" 4743 [(set_attr "type" "load") 4744 (set_attr "predicable" "yes") 4745 (set_attr "pool_range" "4096") 4746 (set_attr "neg_pool_range" "4084")] 4747) 4748 4749(define_insn "*movhi_bytes" 4750 [(set (match_operand:HI 0 "s_register_operand" "=r,r") 4751 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))] 4752 "TARGET_ARM && TARGET_MMU_TRAPS" 4753 "@ 4754 mov%?\\t%0, %1\\t%@ movhi 4755 mvn%?\\t%0, #%B1\\t%@ movhi" 4756 [(set_attr "predicable" "yes")] 4757) 4758 4759(define_insn "thumb_movhi_clobber" 4760 [(set (match_operand:HI 0 "memory_operand" "=m") 4761 (match_operand:HI 1 "register_operand" "l")) 4762 (clobber (match_operand:SI 2 "register_operand" "=&l"))] 4763 "TARGET_THUMB" 4764 "* 4765 abort ();" 4766) 4767 4768;; We use a DImode scratch because we may occasionally need an additional 4769;; temporary if the address isn't offsettable -- push_reload doesn't seem 4770;; to take any notice of the "o" constraints on reload_memory_operand operand. 4771(define_expand "reload_outhi" 4772 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o") 4773 (match_operand:HI 1 "s_register_operand" "r") 4774 (match_operand:DI 2 "s_register_operand" "=&l")])] 4775 "TARGET_EITHER" 4776 "if (TARGET_ARM) 4777 arm_reload_out_hi (operands); 4778 else 4779 thumb_reload_out_hi (operands); 4780 DONE; 4781 " 4782) 4783 4784(define_expand "reload_inhi" 4785 [(parallel [(match_operand:HI 0 "s_register_operand" "=r") 4786 (match_operand:HI 1 "arm_reload_memory_operand" "o") 4787 (match_operand:DI 2 "s_register_operand" "=&r")])] 4788 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)" 4789 " 4790 if (TARGET_ARM) 4791 arm_reload_in_hi (operands); 4792 else 4793 thumb_reload_out_hi (operands); 4794 DONE; 4795") 4796 4797(define_expand "movqi" 4798 [(set (match_operand:QI 0 "general_operand" "") 4799 (match_operand:QI 1 "general_operand" ""))] 4800 "TARGET_EITHER" 4801 " 4802 if (TARGET_ARM) 4803 { 4804 /* Everything except mem = const or mem = mem can be done easily */ 4805 4806 if (!no_new_pseudos) 4807 { 4808 if (GET_CODE (operands[1]) == CONST_INT) 4809 { 4810 rtx reg = gen_reg_rtx (SImode); 4811 4812 emit_insn (gen_movsi (reg, operands[1])); 4813 operands[1] = gen_rtx_SUBREG (QImode, reg, 0); 4814 } 4815 if (GET_CODE (operands[0]) == MEM) 4816 operands[1] = force_reg (QImode, operands[1]); 4817 } 4818 } 4819 else /* TARGET_THUMB */ 4820 { 4821 if (!no_new_pseudos) 4822 { 4823 if (GET_CODE (operands[0]) != REG) 4824 operands[1] = force_reg (QImode, operands[1]); 4825 4826 /* ??? We shouldn't really get invalid addresses here, but this can 4827 happen if we are passed a SP (never OK for HImode/QImode) or 4828 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 4829 HImode/QImode) relative address. */ 4830 /* ??? This should perhaps be fixed elsewhere, for instance, in 4831 fixup_stack_1, by checking for other kinds of invalid addresses, 4832 e.g. a bare reference to a virtual register. This may confuse the 4833 alpha though, which must handle this case differently. */ 4834 if (GET_CODE (operands[0]) == MEM 4835 && !memory_address_p (GET_MODE (operands[0]), 4836 XEXP (operands[0], 0))) 4837 operands[0] 4838 = replace_equiv_address (operands[0], 4839 copy_to_reg (XEXP (operands[0], 0))); 4840 if (GET_CODE (operands[1]) == MEM 4841 && !memory_address_p (GET_MODE (operands[1]), 4842 XEXP (operands[1], 0))) 4843 operands[1] 4844 = replace_equiv_address (operands[1], 4845 copy_to_reg (XEXP (operands[1], 0))); 4846 } 4847 /* Handle loading a large integer during reload */ 4848 else if (GET_CODE (operands[1]) == CONST_INT 4849 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I')) 4850 { 4851 /* Writing a constant to memory needs a scratch, which should 4852 be handled with SECONDARY_RELOADs. */ 4853 if (GET_CODE (operands[0]) != REG) 4854 abort (); 4855 4856 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0); 4857 emit_insn (gen_movsi (operands[0], operands[1])); 4858 DONE; 4859 } 4860 } 4861 " 4862) 4863 4864 4865(define_insn "*arm_movqi_insn" 4866 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m") 4867 (match_operand:QI 1 "general_operand" "rI,K,m,r"))] 4868 "TARGET_ARM 4869 && ( register_operand (operands[0], QImode) 4870 || register_operand (operands[1], QImode))" 4871 "@ 4872 mov%?\\t%0, %1 4873 mvn%?\\t%0, #%B1 4874 ldr%?b\\t%0, %1 4875 str%?b\\t%1, %0" 4876 [(set_attr "type" "*,*,load,store1") 4877 (set_attr "predicable" "yes")] 4878) 4879 4880(define_insn "*thumb_movqi_insn" 4881 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l") 4882 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))] 4883 "TARGET_THUMB 4884 && ( register_operand (operands[0], QImode) 4885 || register_operand (operands[1], QImode))" 4886 "@ 4887 add\\t%0, %1, #0 4888 ldrb\\t%0, %1 4889 strb\\t%1, %0 4890 mov\\t%0, %1 4891 mov\\t%0, %1 4892 mov\\t%0, %1" 4893 [(set_attr "length" "2") 4894 (set_attr "type" "*,load,store1,*,*,*") 4895 (set_attr "pool_range" "*,32,*,*,*,*")] 4896) 4897 4898(define_expand "movsf" 4899 [(set (match_operand:SF 0 "general_operand" "") 4900 (match_operand:SF 1 "general_operand" ""))] 4901 "TARGET_EITHER" 4902 " 4903 if (TARGET_ARM) 4904 { 4905 if (GET_CODE (operands[0]) == MEM) 4906 operands[1] = force_reg (SFmode, operands[1]); 4907 } 4908 else /* TARGET_THUMB */ 4909 { 4910 if (!no_new_pseudos) 4911 { 4912 if (GET_CODE (operands[0]) != REG) 4913 operands[1] = force_reg (SFmode, operands[1]); 4914 } 4915 } 4916 " 4917) 4918 4919(define_split 4920 [(set (match_operand:SF 0 "nonimmediate_operand" "") 4921 (match_operand:SF 1 "immediate_operand" ""))] 4922 "TARGET_ARM 4923 && !TARGET_HARD_FLOAT 4924 && reload_completed 4925 && GET_CODE (operands[1]) == CONST_DOUBLE" 4926 [(set (match_dup 2) (match_dup 3))] 4927 " 4928 operands[2] = gen_lowpart (SImode, operands[0]); 4929 operands[3] = gen_lowpart (SImode, operands[1]); 4930 if (operands[2] == 0 || operands[3] == 0) 4931 FAIL; 4932 " 4933) 4934 4935(define_insn "*arm_movsf_hard_insn" 4936 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m") 4937 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))] 4938 "TARGET_ARM 4939 && TARGET_HARD_FLOAT 4940 && (GET_CODE (operands[0]) != MEM 4941 || register_operand (operands[1], SFmode))" 4942 "@ 4943 mvf%?s\\t%0, %1 4944 mnf%?s\\t%0, #%N1 4945 ldf%?s\\t%0, %1 4946 stf%?s\\t%1, %0 4947 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4 4948 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4 4949 mov%?\\t%0, %1 4950 ldr%?\\t%0, %1\\t%@ float 4951 str%?\\t%1, %0\\t%@ float" 4952 [(set_attr "length" "4,4,4,4,8,8,4,4,4") 4953 (set_attr "predicable" "yes") 4954 (set_attr "type" 4955 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1") 4956 (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*") 4957 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")] 4958) 4959 4960;; Exactly the same as above, except that all `f' cases are deleted. 4961;; This is necessary to prevent reload from ever trying to use a `f' reg 4962;; when -msoft-float. 4963 4964(define_insn "*arm_movsf_soft_insn" 4965 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m") 4966 (match_operand:SF 1 "general_operand" "r,mE,r"))] 4967 "TARGET_ARM 4968 && TARGET_SOFT_FLOAT 4969 && (GET_CODE (operands[0]) != MEM 4970 || register_operand (operands[1], SFmode))" 4971 "@ 4972 mov%?\\t%0, %1 4973 ldr%?\\t%0, %1\\t%@ float 4974 str%?\\t%1, %0\\t%@ float" 4975 [(set_attr "length" "4,4,4") 4976 (set_attr "predicable" "yes") 4977 (set_attr "type" "*,load,store1") 4978 (set_attr "pool_range" "*,4096,*") 4979 (set_attr "neg_pool_range" "*,4084,*")] 4980) 4981 4982;;; ??? This should have alternatives for constants. 4983(define_insn "*thumb_movsf_insn" 4984 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h") 4985 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))] 4986 "TARGET_THUMB 4987 && ( register_operand (operands[0], SFmode) 4988 || register_operand (operands[1], SFmode))" 4989 "@ 4990 add\\t%0, %1, #0 4991 ldmia\\t%1, {%0} 4992 stmia\\t%0, {%1} 4993 ldr\\t%0, %1 4994 str\\t%1, %0 4995 mov\\t%0, %1 4996 mov\\t%0, %1" 4997 [(set_attr "length" "2") 4998 (set_attr "type" "*,load,store1,load,store1,*,*") 4999 (set_attr "pool_range" "*,*,*,1020,*,*,*")] 5000) 5001 5002(define_expand "movdf" 5003 [(set (match_operand:DF 0 "general_operand" "") 5004 (match_operand:DF 1 "general_operand" ""))] 5005 "TARGET_EITHER" 5006 " 5007 if (TARGET_ARM) 5008 { 5009 if (GET_CODE (operands[0]) == MEM) 5010 operands[1] = force_reg (DFmode, operands[1]); 5011 } 5012 else /* TARGET_THUMB */ 5013 { 5014 if (!no_new_pseudos) 5015 { 5016 if (GET_CODE (operands[0]) != REG) 5017 operands[1] = force_reg (DFmode, operands[1]); 5018 } 5019 } 5020 " 5021) 5022 5023;; Reloading a df mode value stored in integer regs to memory can require a 5024;; scratch reg. 5025(define_expand "reload_outdf" 5026 [(match_operand:DF 0 "arm_reload_memory_operand" "=o") 5027 (match_operand:DF 1 "s_register_operand" "r") 5028 (match_operand:SI 2 "s_register_operand" "=&r")] 5029 "TARGET_ARM" 5030 " 5031 { 5032 enum rtx_code code = GET_CODE (XEXP (operands[0], 0)); 5033 5034 if (code == REG) 5035 operands[2] = XEXP (operands[0], 0); 5036 else if (code == POST_INC || code == PRE_DEC) 5037 { 5038 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); 5039 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0); 5040 emit_insn (gen_movdi (operands[0], operands[1])); 5041 DONE; 5042 } 5043 else if (code == PRE_INC) 5044 { 5045 rtx reg = XEXP (XEXP (operands[0], 0), 0); 5046 5047 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8))); 5048 operands[2] = reg; 5049 } 5050 else if (code == POST_DEC) 5051 operands[2] = XEXP (XEXP (operands[0], 0), 0); 5052 else 5053 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0), 5054 XEXP (XEXP (operands[0], 0), 1))); 5055 5056 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]), 5057 operands[1])); 5058 5059 if (code == POST_DEC) 5060 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8))); 5061 5062 DONE; 5063 }" 5064) 5065 5066(define_insn "*movdf_hard_insn" 5067 [(set (match_operand:DF 0 "nonimmediate_operand" 5068 "=r,Q,r,m,r, f, f,f, m,!f,!r") 5069 (match_operand:DF 1 "general_operand" 5070 "Q, r,r,r,mF,fG,H,mF,f,r, f"))] 5071 "TARGET_ARM 5072 && TARGET_HARD_FLOAT 5073 && (GET_CODE (operands[0]) != MEM 5074 || register_operand (operands[1], DFmode))" 5075 "* 5076 { 5077 switch (which_alternative) 5078 { 5079 default: 5080 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\"; 5081 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\"; 5082 case 2: case 3: case 4: return output_move_double (operands); 5083 case 5: return \"mvf%?d\\t%0, %1\"; 5084 case 6: return \"mnf%?d\\t%0, #%N1\"; 5085 case 7: return \"ldf%?d\\t%0, %1\"; 5086 case 8: return \"stf%?d\\t%1, %0\"; 5087 case 9: return output_mov_double_fpu_from_arm (operands); 5088 case 10: return output_mov_double_arm_from_fpu (operands); 5089 } 5090 } 5091 " 5092 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8") 5093 (set_attr "predicable" "yes") 5094 (set_attr "type" 5095 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r") 5096 (set_attr "pool_range" "*,*,*,*,1020,*,*,1024,*,*,*") 5097 (set_attr "neg_pool_range" "*,*,*,*,1008,*,*,1008,*,*,*")] 5098) 5099 5100;; Software floating point version. This is essentially the same as movdi. 5101;; Do not use `f' as a constraint to prevent reload from ever trying to use 5102;; an `f' reg. 5103 5104(define_insn "*movdf_soft_insn" 5105 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m") 5106 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))] 5107 "TARGET_ARM && TARGET_SOFT_FLOAT 5108 " 5109 "* return output_move_double (operands);" 5110 [(set_attr "length" "8,8,8") 5111 (set_attr "type" "*,load,store2") 5112 (set_attr "pool_range" "1020") 5113 (set_attr "neg_pool_range" "1008")] 5114) 5115 5116;;; ??? This should have alternatives for constants. 5117;;; ??? This was originally identical to the movdi_insn pattern. 5118;;; ??? The 'F' constraint looks funny, but it should always be replaced by 5119;;; thumb_reorg with a memory reference. 5120(define_insn "*thumb_movdf_insn" 5121 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r") 5122 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))] 5123 "TARGET_THUMB 5124 && ( register_operand (operands[0], DFmode) 5125 || register_operand (operands[1], DFmode))" 5126 "* 5127 switch (which_alternative) 5128 { 5129 default: 5130 case 0: 5131 if (REGNO (operands[1]) == REGNO (operands[0]) + 1) 5132 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\"; 5133 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\"; 5134 case 1: 5135 return \"ldmia\\t%1, {%0, %H0}\"; 5136 case 2: 5137 return \"stmia\\t%0, {%1, %H1}\"; 5138 case 3: 5139 return thumb_load_double_from_address (operands); 5140 case 4: 5141 operands[2] = gen_rtx (MEM, SImode, 5142 plus_constant (XEXP (operands[0], 0), 4)); 5143 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands); 5144 return \"\"; 5145 case 5: 5146 if (REGNO (operands[1]) == REGNO (operands[0]) + 1) 5147 return \"mov\\t%0, %1\;mov\\t%H0, %H1\"; 5148 return \"mov\\t%H0, %H1\;mov\\t%0, %1\"; 5149 } 5150 " 5151 [(set_attr "length" "4,2,2,6,4,4") 5152 (set_attr "type" "*,load,store2,load,store2,*") 5153 (set_attr "pool_range" "*,*,*,1020,*,*")] 5154) 5155 5156 5157(define_expand "movxf" 5158 [(set (match_operand:XF 0 "general_operand" "") 5159 (match_operand:XF 1 "general_operand" ""))] 5160 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 5161 "") 5162 5163;; Even when the XFmode patterns aren't enabled, we enable this after 5164;; reloading so that we can push floating point registers in the prologue. 5165 5166(define_insn "*movxf_hard_insn" 5167 [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r") 5168 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))] 5169 "TARGET_ARM && TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)" 5170 "* 5171 switch (which_alternative) 5172 { 5173 default: 5174 case 0: return \"mvf%?e\\t%0, %1\"; 5175 case 1: return \"mnf%?e\\t%0, #%N1\"; 5176 case 2: return \"ldf%?e\\t%0, %1\"; 5177 case 3: return \"stf%?e\\t%1, %0\"; 5178 case 4: return output_mov_long_double_fpu_from_arm (operands); 5179 case 5: return output_mov_long_double_arm_from_fpu (operands); 5180 case 6: return output_mov_long_double_arm_from_arm (operands); 5181 } 5182 " 5183 [(set_attr "length" "4,4,4,4,8,8,12") 5184 (set_attr "predicable" "yes") 5185 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*") 5186 (set_attr "pool_range" "*,*,1024,*,*,*,*") 5187 (set_attr "neg_pool_range" "*,*,1004,*,*,*,*")] 5188) 5189 5190 5191;; load- and store-multiple insns 5192;; The arm can load/store any set of registers, provided that they are in 5193;; ascending order; but that is beyond GCC so stick with what it knows. 5194 5195(define_expand "load_multiple" 5196 [(match_par_dup 3 [(set (match_operand:SI 0 "" "") 5197 (match_operand:SI 1 "" "")) 5198 (use (match_operand:SI 2 "" ""))])] 5199 "TARGET_ARM" 5200 " 5201 /* Support only fixed point registers. */ 5202 if (GET_CODE (operands[2]) != CONST_INT 5203 || INTVAL (operands[2]) > 14 5204 || INTVAL (operands[2]) < 2 5205 || GET_CODE (operands[1]) != MEM 5206 || GET_CODE (operands[0]) != REG 5207 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1) 5208 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM) 5209 FAIL; 5210 5211 operands[3] 5212 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]), 5213 force_reg (SImode, XEXP (operands[1], 0)), 5214 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]), 5215 MEM_IN_STRUCT_P(operands[1]), 5216 MEM_SCALAR_P (operands[1])); 5217 " 5218) 5219 5220;; Load multiple with write-back 5221 5222(define_insn "*ldmsi_postinc4" 5223 [(match_parallel 0 "load_multiple_operation" 5224 [(set (match_operand:SI 1 "s_register_operand" "=r") 5225 (plus:SI (match_operand:SI 2 "s_register_operand" "1") 5226 (const_int 16))) 5227 (set (match_operand:SI 3 "arm_hard_register_operand" "") 5228 (mem:SI (match_dup 2))) 5229 (set (match_operand:SI 4 "arm_hard_register_operand" "") 5230 (mem:SI (plus:SI (match_dup 2) (const_int 4)))) 5231 (set (match_operand:SI 5 "arm_hard_register_operand" "") 5232 (mem:SI (plus:SI (match_dup 2) (const_int 8)))) 5233 (set (match_operand:SI 6 "arm_hard_register_operand" "") 5234 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])] 5235 "TARGET_ARM && XVECLEN (operands[0], 0) == 5" 5236 "ldm%?ia\\t%1!, {%3, %4, %5, %6}" 5237 [(set_attr "type" "load") 5238 (set_attr "predicable" "yes")] 5239) 5240 5241(define_insn "*ldmsi_postinc3" 5242 [(match_parallel 0 "load_multiple_operation" 5243 [(set (match_operand:SI 1 "s_register_operand" "=r") 5244 (plus:SI (match_operand:SI 2 "s_register_operand" "1") 5245 (const_int 12))) 5246 (set (match_operand:SI 3 "arm_hard_register_operand" "") 5247 (mem:SI (match_dup 2))) 5248 (set (match_operand:SI 4 "arm_hard_register_operand" "") 5249 (mem:SI (plus:SI (match_dup 2) (const_int 4)))) 5250 (set (match_operand:SI 5 "arm_hard_register_operand" "") 5251 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])] 5252 "TARGET_ARM && XVECLEN (operands[0], 0) == 4" 5253 "ldm%?ia\\t%1!, {%3, %4, %5}" 5254 [(set_attr "type" "load") 5255 (set_attr "predicable" "yes")] 5256) 5257 5258(define_insn "*ldmsi_postinc2" 5259 [(match_parallel 0 "load_multiple_operation" 5260 [(set (match_operand:SI 1 "s_register_operand" "=r") 5261 (plus:SI (match_operand:SI 2 "s_register_operand" "1") 5262 (const_int 8))) 5263 (set (match_operand:SI 3 "arm_hard_register_operand" "") 5264 (mem:SI (match_dup 2))) 5265 (set (match_operand:SI 4 "arm_hard_register_operand" "") 5266 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])] 5267 "TARGET_ARM && XVECLEN (operands[0], 0) == 3" 5268 "ldm%?ia\\t%1!, {%3, %4}" 5269 [(set_attr "type" "load") 5270 (set_attr "predicable" "yes")] 5271) 5272 5273;; Ordinary load multiple 5274 5275(define_insn "*ldmsi4" 5276 [(match_parallel 0 "load_multiple_operation" 5277 [(set (match_operand:SI 2 "arm_hard_register_operand" "") 5278 (mem:SI (match_operand:SI 1 "s_register_operand" "r"))) 5279 (set (match_operand:SI 3 "arm_hard_register_operand" "") 5280 (mem:SI (plus:SI (match_dup 1) (const_int 4)))) 5281 (set (match_operand:SI 4 "arm_hard_register_operand" "") 5282 (mem:SI (plus:SI (match_dup 1) (const_int 8)))) 5283 (set (match_operand:SI 5 "arm_hard_register_operand" "") 5284 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])] 5285 "TARGET_ARM && XVECLEN (operands[0], 0) == 4" 5286 "ldm%?ia\\t%1, {%2, %3, %4, %5}" 5287 [(set_attr "type" "load") 5288 (set_attr "predicable" "yes")] 5289) 5290 5291(define_insn "*ldmsi3" 5292 [(match_parallel 0 "load_multiple_operation" 5293 [(set (match_operand:SI 2 "arm_hard_register_operand" "") 5294 (mem:SI (match_operand:SI 1 "s_register_operand" "r"))) 5295 (set (match_operand:SI 3 "arm_hard_register_operand" "") 5296 (mem:SI (plus:SI (match_dup 1) (const_int 4)))) 5297 (set (match_operand:SI 4 "arm_hard_register_operand" "") 5298 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])] 5299 "TARGET_ARM && XVECLEN (operands[0], 0) == 3" 5300 "ldm%?ia\\t%1, {%2, %3, %4}" 5301 [(set_attr "type" "load") 5302 (set_attr "predicable" "yes")] 5303) 5304 5305(define_insn "*ldmsi2" 5306 [(match_parallel 0 "load_multiple_operation" 5307 [(set (match_operand:SI 2 "arm_hard_register_operand" "") 5308 (mem:SI (match_operand:SI 1 "s_register_operand" "r"))) 5309 (set (match_operand:SI 3 "arm_hard_register_operand" "") 5310 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])] 5311 "TARGET_ARM && XVECLEN (operands[0], 0) == 2" 5312 "ldm%?ia\\t%1, {%2, %3}" 5313 [(set_attr "type" "load") 5314 (set_attr "predicable" "yes")] 5315) 5316 5317(define_expand "store_multiple" 5318 [(match_par_dup 3 [(set (match_operand:SI 0 "" "") 5319 (match_operand:SI 1 "" "")) 5320 (use (match_operand:SI 2 "" ""))])] 5321 "TARGET_ARM" 5322 " 5323 /* Support only fixed point registers */ 5324 if (GET_CODE (operands[2]) != CONST_INT 5325 || INTVAL (operands[2]) > 14 5326 || INTVAL (operands[2]) < 2 5327 || GET_CODE (operands[1]) != REG 5328 || GET_CODE (operands[0]) != MEM 5329 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1) 5330 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM) 5331 FAIL; 5332 5333 operands[3] 5334 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]), 5335 force_reg (SImode, XEXP (operands[0], 0)), 5336 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]), 5337 MEM_IN_STRUCT_P(operands[0]), 5338 MEM_SCALAR_P (operands[0])); 5339 " 5340) 5341 5342;; Store multiple with write-back 5343 5344(define_insn "*stmsi_postinc4" 5345 [(match_parallel 0 "store_multiple_operation" 5346 [(set (match_operand:SI 1 "s_register_operand" "=r") 5347 (plus:SI (match_operand:SI 2 "s_register_operand" "1") 5348 (const_int 16))) 5349 (set (mem:SI (match_dup 2)) 5350 (match_operand:SI 3 "arm_hard_register_operand" "")) 5351 (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 5352 (match_operand:SI 4 "arm_hard_register_operand" "")) 5353 (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) 5354 (match_operand:SI 5 "arm_hard_register_operand" "")) 5355 (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) 5356 (match_operand:SI 6 "arm_hard_register_operand" ""))])] 5357 "TARGET_ARM && XVECLEN (operands[0], 0) == 5" 5358 "stm%?ia\\t%1!, {%3, %4, %5, %6}" 5359 [(set_attr "predicable" "yes") 5360 (set_attr "type" "store4")] 5361) 5362 5363(define_insn "*stmsi_postinc3" 5364 [(match_parallel 0 "store_multiple_operation" 5365 [(set (match_operand:SI 1 "s_register_operand" "=r") 5366 (plus:SI (match_operand:SI 2 "s_register_operand" "1") 5367 (const_int 12))) 5368 (set (mem:SI (match_dup 2)) 5369 (match_operand:SI 3 "arm_hard_register_operand" "")) 5370 (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 5371 (match_operand:SI 4 "arm_hard_register_operand" "")) 5372 (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) 5373 (match_operand:SI 5 "arm_hard_register_operand" ""))])] 5374 "TARGET_ARM && XVECLEN (operands[0], 0) == 4" 5375 "stm%?ia\\t%1!, {%3, %4, %5}" 5376 [(set_attr "predicable" "yes") 5377 (set_attr "type" "store3")] 5378) 5379 5380(define_insn "*stmsi_postinc2" 5381 [(match_parallel 0 "store_multiple_operation" 5382 [(set (match_operand:SI 1 "s_register_operand" "=r") 5383 (plus:SI (match_operand:SI 2 "s_register_operand" "1") 5384 (const_int 8))) 5385 (set (mem:SI (match_dup 2)) 5386 (match_operand:SI 3 "arm_hard_register_operand" "")) 5387 (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 5388 (match_operand:SI 4 "arm_hard_register_operand" ""))])] 5389 "TARGET_ARM && XVECLEN (operands[0], 0) == 3" 5390 "stm%?ia\\t%1!, {%3, %4}" 5391 [(set_attr "predicable" "yes") 5392 (set_attr "type" "store2")] 5393) 5394 5395;; Ordinary store multiple 5396 5397(define_insn "*stmsi4" 5398 [(match_parallel 0 "store_multiple_operation" 5399 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r")) 5400 (match_operand:SI 2 "arm_hard_register_operand" "")) 5401 (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) 5402 (match_operand:SI 3 "arm_hard_register_operand" "")) 5403 (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) 5404 (match_operand:SI 4 "arm_hard_register_operand" "")) 5405 (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) 5406 (match_operand:SI 5 "arm_hard_register_operand" ""))])] 5407 "TARGET_ARM && XVECLEN (operands[0], 0) == 4" 5408 "stm%?ia\\t%1, {%2, %3, %4, %5}" 5409 [(set_attr "predicable" "yes") 5410 (set_attr "type" "store4")] 5411) 5412 5413(define_insn "*stmsi3" 5414 [(match_parallel 0 "store_multiple_operation" 5415 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r")) 5416 (match_operand:SI 2 "arm_hard_register_operand" "")) 5417 (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) 5418 (match_operand:SI 3 "arm_hard_register_operand" "")) 5419 (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) 5420 (match_operand:SI 4 "arm_hard_register_operand" ""))])] 5421 "TARGET_ARM && XVECLEN (operands[0], 0) == 3" 5422 "stm%?ia\\t%1, {%2, %3, %4}" 5423 [(set_attr "predicable" "yes") 5424 (set_attr "type" "store3")] 5425) 5426 5427(define_insn "*stmsi2" 5428 [(match_parallel 0 "store_multiple_operation" 5429 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r")) 5430 (match_operand:SI 2 "arm_hard_register_operand" "")) 5431 (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) 5432 (match_operand:SI 3 "arm_hard_register_operand" ""))])] 5433 "TARGET_ARM && XVECLEN (operands[0], 0) == 2" 5434 "stm%?ia\\t%1, {%2, %3}" 5435 [(set_attr "predicable" "yes") 5436 (set_attr "type" "store2")] 5437) 5438 5439;; Move a block of memory if it is word aligned and MORE than 2 words long. 5440;; We could let this apply for blocks of less than this, but it clobbers so 5441;; many registers that there is then probably a better way. 5442 5443(define_expand "movstrqi" 5444 [(match_operand:BLK 0 "general_operand" "") 5445 (match_operand:BLK 1 "general_operand" "") 5446 (match_operand:SI 2 "const_int_operand" "") 5447 (match_operand:SI 3 "const_int_operand" "")] 5448 "TARGET_EITHER" 5449 " 5450 if (TARGET_ARM) 5451 { 5452 if (arm_gen_movstrqi (operands)) 5453 DONE; 5454 FAIL; 5455 } 5456 else /* TARGET_THUMB */ 5457 { 5458 if ( INTVAL (operands[3]) != 4 5459 || INTVAL (operands[2]) > 48) 5460 FAIL; 5461 5462 thumb_expand_movstrqi (operands); 5463 DONE; 5464 } 5465 " 5466) 5467 5468;; Thumb block-move insns 5469 5470(define_insn "movmem12b" 5471 [(set (mem:SI (match_operand:SI 2 "register_operand" "0")) 5472 (mem:SI (match_operand:SI 3 "register_operand" "1"))) 5473 (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 5474 (mem:SI (plus:SI (match_dup 3) (const_int 4)))) 5475 (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) 5476 (mem:SI (plus:SI (match_dup 3) (const_int 8)))) 5477 (set (match_operand:SI 0 "register_operand" "=l") 5478 (plus:SI (match_dup 2) (const_int 12))) 5479 (set (match_operand:SI 1 "register_operand" "=l") 5480 (plus:SI (match_dup 3) (const_int 12))) 5481 (clobber (match_scratch:SI 4 "=&l")) 5482 (clobber (match_scratch:SI 5 "=&l")) 5483 (clobber (match_scratch:SI 6 "=&l"))] 5484 "TARGET_THUMB" 5485 "* return thumb_output_move_mem_multiple (3, operands);" 5486 [(set_attr "length" "4") 5487 ; This isn't entirely accurate... It loads as well, but in terms of 5488 ; scheduling the following insn it is better to consider it as a store 5489 (set_attr "type" "store3")] 5490) 5491 5492(define_insn "movmem8b" 5493 [(set (mem:SI (match_operand:SI 2 "register_operand" "0")) 5494 (mem:SI (match_operand:SI 3 "register_operand" "1"))) 5495 (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 5496 (mem:SI (plus:SI (match_dup 3) (const_int 4)))) 5497 (set (match_operand:SI 0 "register_operand" "=l") 5498 (plus:SI (match_dup 2) (const_int 8))) 5499 (set (match_operand:SI 1 "register_operand" "=l") 5500 (plus:SI (match_dup 3) (const_int 8))) 5501 (clobber (match_scratch:SI 4 "=&l")) 5502 (clobber (match_scratch:SI 5 "=&l"))] 5503 "TARGET_THUMB" 5504 "* return thumb_output_move_mem_multiple (2, operands);" 5505 [(set_attr "length" "4") 5506 ; This isn't entirely accurate... It loads as well, but in terms of 5507 ; scheduling the following insn it is better to consider it as a store 5508 (set_attr "type" "store2")] 5509) 5510 5511 5512 5513;; Compare & branch insns 5514;; The range calcualations are based as follows: 5515;; For forward branches, the address calculation returns the address of 5516;; the next instruction. This is 2 beyond the branch instruction. 5517;; For backward branches, the address calculation returns the address of 5518;; the first instruction in this pattern (cmp). This is 2 before the branch 5519;; instruction for the shortest sequence, and 4 before the branch instruction 5520;; if we have to jump around an unconditional branch. 5521;; To the basic branch range the PC offset must be added (this is +4). 5522;; So for forward branches we have 5523;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4). 5524;; And for backward branches we have 5525;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4). 5526;; 5527;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048). 5528;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256). 5529 5530(define_insn "cbranchsi4" 5531 [(set (pc) 5532 (if_then_else 5533 (match_operator 0 "arm_comparison_operator" 5534 [(match_operand:SI 1 "register_operand" "l,r") 5535 (match_operand:SI 2 "nonmemory_operand" "rI,r")]) 5536 (label_ref (match_operand 3 "" "")) 5537 (pc)))] 5538 "TARGET_THUMB" 5539 "* 5540 output_asm_insn (\"cmp\\t%1, %2\", operands); 5541 switch (get_attr_length (insn)) 5542 { 5543 case 4: return \"b%d0\\t%l3\"; 5544 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 5545 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 5546 } 5547 " 5548 [(set (attr "far_jump") 5549 (if_then_else 5550 (eq_attr "length" "8") 5551 (const_string "yes") 5552 (const_string "no"))) 5553 (set (attr "length") 5554 (if_then_else 5555 (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 5556 (le (minus (match_dup 3) (pc)) (const_int 256))) 5557 (const_int 4) 5558 (if_then_else 5559 (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 5560 (le (minus (match_dup 3) (pc)) (const_int 2048))) 5561 (const_int 6) 5562 (const_int 8))))] 5563) 5564 5565(define_insn "*negated_cbranchsi4" 5566 [(set (pc) 5567 (if_then_else 5568 (match_operator 0 "arm_comparison_operator" 5569 [(match_operand:SI 1 "register_operand" "l") 5570 (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))]) 5571 (label_ref (match_operand 3 "" "")) 5572 (pc)))] 5573 "TARGET_THUMB" 5574 "* 5575 output_asm_insn (\"cmn\\t%1, %2\", operands); 5576 switch (get_attr_length (insn)) 5577 { 5578 case 4: return \"b%d0\\t%l3\"; 5579 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 5580 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 5581 } 5582 " 5583 [(set (attr "far_jump") 5584 (if_then_else 5585 (eq_attr "length" "8") 5586 (const_string "yes") 5587 (const_string "no"))) 5588 (set (attr "length") 5589 (if_then_else 5590 (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 5591 (le (minus (match_dup 3) (pc)) (const_int 256))) 5592 (const_int 4) 5593 (if_then_else 5594 (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 5595 (le (minus (match_dup 3) (pc)) (const_int 2048))) 5596 (const_int 6) 5597 (const_int 8))))] 5598) 5599 5600 5601;; Comparison and test insns 5602 5603(define_expand "cmpsi" 5604 [(match_operand:SI 0 "s_register_operand" "") 5605 (match_operand:SI 1 "arm_add_operand" "")] 5606 "TARGET_ARM" 5607 "{ 5608 arm_compare_op0 = operands[0]; 5609 arm_compare_op1 = operands[1]; 5610 DONE; 5611 }" 5612) 5613 5614(define_expand "cmpsf" 5615 [(match_operand:SF 0 "s_register_operand" "") 5616 (match_operand:SF 1 "fpu_rhs_operand" "")] 5617 "TARGET_ARM && TARGET_HARD_FLOAT" 5618 " 5619 arm_compare_op0 = operands[0]; 5620 arm_compare_op1 = operands[1]; 5621 DONE; 5622 " 5623) 5624 5625(define_expand "cmpdf" 5626 [(match_operand:DF 0 "s_register_operand" "") 5627 (match_operand:DF 1 "fpu_rhs_operand" "")] 5628 "TARGET_ARM && TARGET_HARD_FLOAT" 5629 " 5630 arm_compare_op0 = operands[0]; 5631 arm_compare_op1 = operands[1]; 5632 DONE; 5633 " 5634) 5635 5636(define_expand "cmpxf" 5637 [(match_operand:XF 0 "s_register_operand" "") 5638 (match_operand:XF 1 "fpu_rhs_operand" "")] 5639 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 5640 " 5641 arm_compare_op0 = operands[0]; 5642 arm_compare_op1 = operands[1]; 5643 DONE; 5644 " 5645) 5646 5647(define_insn "*arm_cmpsi_insn" 5648 [(set (reg:CC CC_REGNUM) 5649 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r") 5650 (match_operand:SI 1 "arm_add_operand" "rI,L")))] 5651 "TARGET_ARM" 5652 "@ 5653 cmp%?\\t%0, %1 5654 cmn%?\\t%0, #%n1" 5655 [(set_attr "conds" "set")] 5656) 5657 5658(define_insn "*cmpsi_shiftsi" 5659 [(set (reg:CC CC_REGNUM) 5660 (compare:CC (match_operand:SI 0 "s_register_operand" "r") 5661 (match_operator:SI 3 "shift_operator" 5662 [(match_operand:SI 1 "s_register_operand" "r") 5663 (match_operand:SI 2 "arm_rhs_operand" "rM")])))] 5664 "TARGET_ARM" 5665 "cmp%?\\t%0, %1%S3" 5666 [(set_attr "conds" "set") 5667 (set_attr "shift" "1") 5668 ] 5669) 5670 5671(define_insn "*cmpsi_shiftsi_swp" 5672 [(set (reg:CC_SWP CC_REGNUM) 5673 (compare:CC_SWP (match_operator:SI 3 "shift_operator" 5674 [(match_operand:SI 1 "s_register_operand" "r") 5675 (match_operand:SI 2 "reg_or_int_operand" "rM")]) 5676 (match_operand:SI 0 "s_register_operand" "r")))] 5677 "TARGET_ARM" 5678 "cmp%?\\t%0, %1%S3" 5679 [(set_attr "conds" "set") 5680 (set_attr "shift" "1") 5681 ] 5682) 5683 5684(define_insn "*cmpsi_neg_shiftsi" 5685 [(set (reg:CC CC_REGNUM) 5686 (compare:CC (match_operand:SI 0 "s_register_operand" "r") 5687 (neg:SI (match_operator:SI 3 "shift_operator" 5688 [(match_operand:SI 1 "s_register_operand" "r") 5689 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))] 5690 "TARGET_ARM" 5691 "cmn%?\\t%0, %1%S3" 5692 [(set_attr "conds" "set") 5693 (set_attr "shift" "1") 5694 ] 5695) 5696 5697(define_insn "*cmpsf_insn" 5698 [(set (reg:CCFP CC_REGNUM) 5699 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f") 5700 (match_operand:SF 1 "fpu_add_operand" "fG,H")))] 5701 "TARGET_ARM && TARGET_HARD_FLOAT" 5702 "@ 5703 cmf%?\\t%0, %1 5704 cnf%?\\t%0, #%N1" 5705 [(set_attr "conds" "set") 5706 (set_attr "type" "f_2_r")] 5707) 5708 5709(define_insn "*cmpdf_insn" 5710 [(set (reg:CCFP CC_REGNUM) 5711 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f") 5712 (match_operand:DF 1 "fpu_add_operand" "fG,H")))] 5713 "TARGET_ARM && TARGET_HARD_FLOAT" 5714 "@ 5715 cmf%?\\t%0, %1 5716 cnf%?\\t%0, #%N1" 5717 [(set_attr "conds" "set") 5718 (set_attr "type" "f_2_r")] 5719) 5720 5721(define_insn "*cmpesfdf_df" 5722 [(set (reg:CCFP CC_REGNUM) 5723 (compare:CCFP (float_extend:DF 5724 (match_operand:SF 0 "s_register_operand" "f,f")) 5725 (match_operand:DF 1 "fpu_add_operand" "fG,H")))] 5726 "TARGET_ARM && TARGET_HARD_FLOAT" 5727 "@ 5728 cmf%?\\t%0, %1 5729 cnf%?\\t%0, #%N1" 5730 [(set_attr "conds" "set") 5731 (set_attr "type" "f_2_r")] 5732) 5733 5734(define_insn "*cmpdf_esfdf" 5735 [(set (reg:CCFP CC_REGNUM) 5736 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f") 5737 (float_extend:DF 5738 (match_operand:SF 1 "s_register_operand" "f"))))] 5739 "TARGET_ARM && TARGET_HARD_FLOAT" 5740 "cmf%?\\t%0, %1" 5741 [(set_attr "conds" "set") 5742 (set_attr "type" "f_2_r")] 5743) 5744 5745(define_insn "*cmpxf_insn" 5746 [(set (reg:CCFP CC_REGNUM) 5747 (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f") 5748 (match_operand:XF 1 "fpu_add_operand" "fG,H")))] 5749 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 5750 "@ 5751 cmf%?\\t%0, %1 5752 cnf%?\\t%0, #%N1" 5753 [(set_attr "conds" "set") 5754 (set_attr "type" "f_2_r")] 5755) 5756 5757(define_insn "*cmpsf_trap" 5758 [(set (reg:CCFPE CC_REGNUM) 5759 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f") 5760 (match_operand:SF 1 "fpu_add_operand" "fG,H")))] 5761 "TARGET_ARM && TARGET_HARD_FLOAT" 5762 "@ 5763 cmf%?e\\t%0, %1 5764 cnf%?e\\t%0, #%N1" 5765 [(set_attr "conds" "set") 5766 (set_attr "type" "f_2_r")] 5767) 5768 5769(define_insn "*cmpdf_trap" 5770 [(set (reg:CCFPE CC_REGNUM) 5771 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f") 5772 (match_operand:DF 1 "fpu_add_operand" "fG,H")))] 5773 "TARGET_ARM && TARGET_HARD_FLOAT" 5774 "@ 5775 cmf%?e\\t%0, %1 5776 cnf%?e\\t%0, #%N1" 5777 [(set_attr "conds" "set") 5778 (set_attr "type" "f_2_r")] 5779) 5780 5781(define_insn "*cmp_esfdf_df_trap" 5782 [(set (reg:CCFPE CC_REGNUM) 5783 (compare:CCFPE (float_extend:DF 5784 (match_operand:SF 0 "s_register_operand" "f,f")) 5785 (match_operand:DF 1 "fpu_add_operand" "fG,H")))] 5786 "TARGET_ARM && TARGET_HARD_FLOAT" 5787 "@ 5788 cmf%?e\\t%0, %1 5789 cnf%?e\\t%0, #%N1" 5790 [(set_attr "conds" "set") 5791 (set_attr "type" "f_2_r")] 5792) 5793 5794(define_insn "*cmp_df_esfdf_trap" 5795 [(set (reg:CCFPE CC_REGNUM) 5796 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f") 5797 (float_extend:DF 5798 (match_operand:SF 1 "s_register_operand" "f"))))] 5799 "TARGET_ARM && TARGET_HARD_FLOAT" 5800 "cmf%?e\\t%0, %1" 5801 [(set_attr "conds" "set") 5802 (set_attr "type" "f_2_r")] 5803) 5804 5805(define_insn "*cmpxf_trap" 5806 [(set (reg:CCFPE CC_REGNUM) 5807 (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f") 5808 (match_operand:XF 1 "fpu_add_operand" "fG,H")))] 5809 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 5810 "@ 5811 cmf%?e\\t%0, %1 5812 cnf%?e\\t%0, #%N1" 5813 [(set_attr "conds" "set") 5814 (set_attr "type" "f_2_r")] 5815) 5816 5817; This insn allows redundant compares to be removed by cse, nothing should 5818; ever appear in the output file since (set (reg x) (reg x)) is a no-op that 5819; is deleted later on. The match_dup will match the mode here, so that 5820; mode changes of the condition codes aren't lost by this even though we don't 5821; specify what they are. 5822 5823(define_insn "*deleted_compare" 5824 [(set (match_operand 0 "cc_register" "") (match_dup 0))] 5825 "TARGET_ARM" 5826 "\\t%@ deleted compare" 5827 [(set_attr "conds" "set") 5828 (set_attr "length" "0")] 5829) 5830 5831 5832;; Conditional branch insns 5833 5834(define_expand "beq" 5835 [(set (pc) 5836 (if_then_else (eq (match_dup 1) (const_int 0)) 5837 (label_ref (match_operand 0 "" "")) 5838 (pc)))] 5839 "TARGET_ARM" 5840 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);" 5841) 5842 5843(define_expand "bne" 5844 [(set (pc) 5845 (if_then_else (ne (match_dup 1) (const_int 0)) 5846 (label_ref (match_operand 0 "" "")) 5847 (pc)))] 5848 "TARGET_ARM" 5849 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);" 5850) 5851 5852(define_expand "bgt" 5853 [(set (pc) 5854 (if_then_else (gt (match_dup 1) (const_int 0)) 5855 (label_ref (match_operand 0 "" "")) 5856 (pc)))] 5857 "TARGET_ARM" 5858 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);" 5859) 5860 5861(define_expand "ble" 5862 [(set (pc) 5863 (if_then_else (le (match_dup 1) (const_int 0)) 5864 (label_ref (match_operand 0 "" "")) 5865 (pc)))] 5866 "TARGET_ARM" 5867 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);" 5868) 5869 5870(define_expand "bge" 5871 [(set (pc) 5872 (if_then_else (ge (match_dup 1) (const_int 0)) 5873 (label_ref (match_operand 0 "" "")) 5874 (pc)))] 5875 "TARGET_ARM" 5876 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);" 5877) 5878 5879(define_expand "blt" 5880 [(set (pc) 5881 (if_then_else (lt (match_dup 1) (const_int 0)) 5882 (label_ref (match_operand 0 "" "")) 5883 (pc)))] 5884 "TARGET_ARM" 5885 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);" 5886) 5887 5888(define_expand "bgtu" 5889 [(set (pc) 5890 (if_then_else (gtu (match_dup 1) (const_int 0)) 5891 (label_ref (match_operand 0 "" "")) 5892 (pc)))] 5893 "TARGET_ARM" 5894 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);" 5895) 5896 5897(define_expand "bleu" 5898 [(set (pc) 5899 (if_then_else (leu (match_dup 1) (const_int 0)) 5900 (label_ref (match_operand 0 "" "")) 5901 (pc)))] 5902 "TARGET_ARM" 5903 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);" 5904) 5905 5906(define_expand "bgeu" 5907 [(set (pc) 5908 (if_then_else (geu (match_dup 1) (const_int 0)) 5909 (label_ref (match_operand 0 "" "")) 5910 (pc)))] 5911 "TARGET_ARM" 5912 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);" 5913) 5914 5915(define_expand "bltu" 5916 [(set (pc) 5917 (if_then_else (ltu (match_dup 1) (const_int 0)) 5918 (label_ref (match_operand 0 "" "")) 5919 (pc)))] 5920 "TARGET_ARM" 5921 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);" 5922) 5923 5924(define_expand "bunordered" 5925 [(set (pc) 5926 (if_then_else (unordered (match_dup 1) (const_int 0)) 5927 (label_ref (match_operand 0 "" "")) 5928 (pc)))] 5929 "TARGET_ARM && TARGET_HARD_FLOAT" 5930 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0, 5931 arm_compare_op1);" 5932) 5933 5934(define_expand "bordered" 5935 [(set (pc) 5936 (if_then_else (ordered (match_dup 1) (const_int 0)) 5937 (label_ref (match_operand 0 "" "")) 5938 (pc)))] 5939 "TARGET_ARM && TARGET_HARD_FLOAT" 5940 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0, 5941 arm_compare_op1);" 5942) 5943 5944(define_expand "bungt" 5945 [(set (pc) 5946 (if_then_else (ungt (match_dup 1) (const_int 0)) 5947 (label_ref (match_operand 0 "" "")) 5948 (pc)))] 5949 "TARGET_ARM && TARGET_HARD_FLOAT" 5950 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);" 5951) 5952 5953(define_expand "bunlt" 5954 [(set (pc) 5955 (if_then_else (unlt (match_dup 1) (const_int 0)) 5956 (label_ref (match_operand 0 "" "")) 5957 (pc)))] 5958 "TARGET_ARM && TARGET_HARD_FLOAT" 5959 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);" 5960) 5961 5962(define_expand "bunge" 5963 [(set (pc) 5964 (if_then_else (unge (match_dup 1) (const_int 0)) 5965 (label_ref (match_operand 0 "" "")) 5966 (pc)))] 5967 "TARGET_ARM && TARGET_HARD_FLOAT" 5968 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);" 5969) 5970 5971(define_expand "bunle" 5972 [(set (pc) 5973 (if_then_else (unle (match_dup 1) (const_int 0)) 5974 (label_ref (match_operand 0 "" "")) 5975 (pc)))] 5976 "TARGET_ARM && TARGET_HARD_FLOAT" 5977 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);" 5978) 5979 5980;; The following two patterns need two branch instructions, since there is 5981;; no single instruction that will handle all cases. 5982(define_expand "buneq" 5983 [(set (pc) 5984 (if_then_else (uneq (match_dup 1) (const_int 0)) 5985 (label_ref (match_operand 0 "" "")) 5986 (pc)))] 5987 "TARGET_ARM && TARGET_HARD_FLOAT" 5988 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);" 5989) 5990 5991(define_expand "bltgt" 5992 [(set (pc) 5993 (if_then_else (ltgt (match_dup 1) (const_int 0)) 5994 (label_ref (match_operand 0 "" "")) 5995 (pc)))] 5996 "TARGET_ARM && TARGET_HARD_FLOAT" 5997 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);" 5998) 5999 6000;; 6001;; Patterns to match conditional branch insns. 6002;; 6003 6004; Special pattern to match UNEQ. 6005(define_insn "*arm_buneq" 6006 [(set (pc) 6007 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0)) 6008 (label_ref (match_operand 0 "" "")) 6009 (pc)))] 6010 "TARGET_ARM && TARGET_HARD_FLOAT" 6011 "* 6012 if (arm_ccfsm_state != 0) 6013 abort (); 6014 6015 return \"bvs\\t%l0;beq\\t%l0\"; 6016 " 6017 [(set_attr "conds" "jump_clob") 6018 (set_attr "length" "8")] 6019) 6020 6021; Special pattern to match LTGT. 6022(define_insn "*arm_bltgt" 6023 [(set (pc) 6024 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0)) 6025 (label_ref (match_operand 0 "" "")) 6026 (pc)))] 6027 "TARGET_ARM && TARGET_HARD_FLOAT" 6028 "* 6029 if (arm_ccfsm_state != 0) 6030 abort (); 6031 6032 return \"bmi\\t%l0;bgt\\t%l0\"; 6033 " 6034 [(set_attr "conds" "jump_clob") 6035 (set_attr "length" "8")] 6036) 6037 6038(define_insn "*arm_cond_branch" 6039 [(set (pc) 6040 (if_then_else (match_operator 1 "arm_comparison_operator" 6041 [(match_operand 2 "cc_register" "") (const_int 0)]) 6042 (label_ref (match_operand 0 "" "")) 6043 (pc)))] 6044 "TARGET_ARM" 6045 "* 6046 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) 6047 { 6048 arm_ccfsm_state += 2; 6049 return \"\"; 6050 } 6051 return \"b%d1\\t%l0\"; 6052 " 6053 [(set_attr "conds" "use")] 6054) 6055 6056; Special pattern to match reversed UNEQ. 6057(define_insn "*arm_buneq_reversed" 6058 [(set (pc) 6059 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0)) 6060 (pc) 6061 (label_ref (match_operand 0 "" ""))))] 6062 "TARGET_ARM && TARGET_HARD_FLOAT" 6063 "* 6064 if (arm_ccfsm_state != 0) 6065 abort (); 6066 6067 return \"bmi\\t%l0;bgt\\t%l0\"; 6068 " 6069 [(set_attr "conds" "jump_clob") 6070 (set_attr "length" "8")] 6071) 6072 6073; Special pattern to match reversed LTGT. 6074(define_insn "*arm_bltgt_reversed" 6075 [(set (pc) 6076 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0)) 6077 (pc) 6078 (label_ref (match_operand 0 "" ""))))] 6079 "TARGET_ARM && TARGET_HARD_FLOAT" 6080 "* 6081 if (arm_ccfsm_state != 0) 6082 abort (); 6083 6084 return \"bvs\\t%l0;beq\\t%l0\"; 6085 " 6086 [(set_attr "conds" "jump_clob") 6087 (set_attr "length" "8")] 6088) 6089 6090(define_insn "*arm_cond_branch_reversed" 6091 [(set (pc) 6092 (if_then_else (match_operator 1 "arm_comparison_operator" 6093 [(match_operand 2 "cc_register" "") (const_int 0)]) 6094 (pc) 6095 (label_ref (match_operand 0 "" ""))))] 6096 "TARGET_ARM" 6097 "* 6098 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) 6099 { 6100 arm_ccfsm_state += 2; 6101 return \"\"; 6102 } 6103 return \"b%D1\\t%l0\"; 6104 " 6105 [(set_attr "conds" "use")] 6106) 6107 6108 6109 6110; scc insns 6111 6112(define_expand "seq" 6113 [(set (match_operand:SI 0 "s_register_operand" "=r") 6114 (eq:SI (match_dup 1) (const_int 0)))] 6115 "TARGET_ARM" 6116 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);" 6117) 6118 6119(define_expand "sne" 6120 [(set (match_operand:SI 0 "s_register_operand" "=r") 6121 (ne:SI (match_dup 1) (const_int 0)))] 6122 "TARGET_ARM" 6123 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);" 6124) 6125 6126(define_expand "sgt" 6127 [(set (match_operand:SI 0 "s_register_operand" "=r") 6128 (gt:SI (match_dup 1) (const_int 0)))] 6129 "TARGET_ARM" 6130 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);" 6131) 6132 6133(define_expand "sle" 6134 [(set (match_operand:SI 0 "s_register_operand" "=r") 6135 (le:SI (match_dup 1) (const_int 0)))] 6136 "TARGET_ARM" 6137 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);" 6138) 6139 6140(define_expand "sge" 6141 [(set (match_operand:SI 0 "s_register_operand" "=r") 6142 (ge:SI (match_dup 1) (const_int 0)))] 6143 "TARGET_ARM" 6144 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);" 6145) 6146 6147(define_expand "slt" 6148 [(set (match_operand:SI 0 "s_register_operand" "=r") 6149 (lt:SI (match_dup 1) (const_int 0)))] 6150 "TARGET_ARM" 6151 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);" 6152) 6153 6154(define_expand "sgtu" 6155 [(set (match_operand:SI 0 "s_register_operand" "=r") 6156 (gtu:SI (match_dup 1) (const_int 0)))] 6157 "TARGET_ARM" 6158 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);" 6159) 6160 6161(define_expand "sleu" 6162 [(set (match_operand:SI 0 "s_register_operand" "=r") 6163 (leu:SI (match_dup 1) (const_int 0)))] 6164 "TARGET_ARM" 6165 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);" 6166) 6167 6168(define_expand "sgeu" 6169 [(set (match_operand:SI 0 "s_register_operand" "=r") 6170 (geu:SI (match_dup 1) (const_int 0)))] 6171 "TARGET_ARM" 6172 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);" 6173) 6174 6175(define_expand "sltu" 6176 [(set (match_operand:SI 0 "s_register_operand" "=r") 6177 (ltu:SI (match_dup 1) (const_int 0)))] 6178 "TARGET_ARM" 6179 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);" 6180) 6181 6182(define_expand "sunordered" 6183 [(set (match_operand:SI 0 "s_register_operand" "=r") 6184 (unordered:SI (match_dup 1) (const_int 0)))] 6185 "TARGET_ARM && TARGET_HARD_FLOAT" 6186 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0, 6187 arm_compare_op1);" 6188) 6189 6190(define_expand "sordered" 6191 [(set (match_operand:SI 0 "s_register_operand" "=r") 6192 (ordered:SI (match_dup 1) (const_int 0)))] 6193 "TARGET_ARM && TARGET_HARD_FLOAT" 6194 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0, 6195 arm_compare_op1);" 6196) 6197 6198(define_expand "sungt" 6199 [(set (match_operand:SI 0 "s_register_operand" "=r") 6200 (ungt:SI (match_dup 1) (const_int 0)))] 6201 "TARGET_ARM && TARGET_HARD_FLOAT" 6202 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, 6203 arm_compare_op1);" 6204) 6205 6206(define_expand "sunge" 6207 [(set (match_operand:SI 0 "s_register_operand" "=r") 6208 (unge:SI (match_dup 1) (const_int 0)))] 6209 "TARGET_ARM && TARGET_HARD_FLOAT" 6210 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, 6211 arm_compare_op1);" 6212) 6213 6214(define_expand "sunlt" 6215 [(set (match_operand:SI 0 "s_register_operand" "=r") 6216 (unlt:SI (match_dup 1) (const_int 0)))] 6217 "TARGET_ARM && TARGET_HARD_FLOAT" 6218 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, 6219 arm_compare_op1);" 6220) 6221 6222(define_expand "sunle" 6223 [(set (match_operand:SI 0 "s_register_operand" "=r") 6224 (unle:SI (match_dup 1) (const_int 0)))] 6225 "TARGET_ARM && TARGET_HARD_FLOAT" 6226 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, 6227 arm_compare_op1);" 6228) 6229 6230;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with 6231;;; simple ARM instructions. 6232; 6233; (define_expand "suneq" 6234; [(set (match_operand:SI 0 "s_register_operand" "=r") 6235; (uneq:SI (match_dup 1) (const_int 0)))] 6236; "TARGET_ARM && TARGET_HARD_FLOAT" 6237; "abort ();" 6238; ) 6239; 6240; (define_expand "sltgt" 6241; [(set (match_operand:SI 0 "s_register_operand" "=r") 6242; (ltgt:SI (match_dup 1) (const_int 0)))] 6243; "TARGET_ARM && TARGET_HARD_FLOAT" 6244; "abort ();" 6245; ) 6246 6247(define_insn "*mov_scc" 6248 [(set (match_operand:SI 0 "s_register_operand" "=r") 6249 (match_operator:SI 1 "arm_comparison_operator" 6250 [(match_operand 2 "cc_register" "") (const_int 0)]))] 6251 "TARGET_ARM" 6252 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1" 6253 [(set_attr "conds" "use") 6254 (set_attr "length" "8")] 6255) 6256 6257(define_insn "*mov_negscc" 6258 [(set (match_operand:SI 0 "s_register_operand" "=r") 6259 (neg:SI (match_operator:SI 1 "arm_comparison_operator" 6260 [(match_operand 2 "cc_register" "") (const_int 0)])))] 6261 "TARGET_ARM" 6262 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0" 6263 [(set_attr "conds" "use") 6264 (set_attr "length" "8")] 6265) 6266 6267(define_insn "*mov_notscc" 6268 [(set (match_operand:SI 0 "s_register_operand" "=r") 6269 (not:SI (match_operator:SI 1 "arm_comparison_operator" 6270 [(match_operand 2 "cc_register" "") (const_int 0)])))] 6271 "TARGET_ARM" 6272 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1" 6273 [(set_attr "conds" "use") 6274 (set_attr "length" "8")] 6275) 6276 6277 6278;; Conditional move insns 6279 6280(define_expand "movsicc" 6281 [(set (match_operand:SI 0 "s_register_operand" "") 6282 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "") 6283 (match_operand:SI 2 "arm_not_operand" "") 6284 (match_operand:SI 3 "arm_not_operand" "")))] 6285 "TARGET_ARM" 6286 " 6287 { 6288 enum rtx_code code = GET_CODE (operands[1]); 6289 rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); 6290 6291 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); 6292 }" 6293) 6294 6295(define_expand "movsfcc" 6296 [(set (match_operand:SF 0 "s_register_operand" "") 6297 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "") 6298 (match_operand:SF 2 "s_register_operand" "") 6299 (match_operand:SF 3 "nonmemory_operand" "")))] 6300 "TARGET_ARM" 6301 " 6302 { 6303 enum rtx_code code = GET_CODE (operands[1]); 6304 rtx ccreg; 6305 6306 /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 6307 Otherwise, ensure it is a valid FP add operand */ 6308 if ((!TARGET_HARD_FLOAT) 6309 || (!fpu_add_operand (operands[3], SFmode))) 6310 operands[3] = force_reg (SFmode, operands[3]); 6311 6312 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); 6313 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); 6314 }" 6315) 6316 6317(define_expand "movdfcc" 6318 [(set (match_operand:DF 0 "s_register_operand" "") 6319 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "") 6320 (match_operand:DF 2 "s_register_operand" "") 6321 (match_operand:DF 3 "fpu_add_operand" "")))] 6322 "TARGET_ARM && TARGET_HARD_FLOAT" 6323 " 6324 { 6325 enum rtx_code code = GET_CODE (operands[1]); 6326 rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); 6327 6328 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); 6329 }" 6330) 6331 6332(define_insn "*movsicc_insn" 6333 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r") 6334 (if_then_else:SI 6335 (match_operator 3 "arm_comparison_operator" 6336 [(match_operand 4 "cc_register" "") (const_int 0)]) 6337 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K") 6338 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))] 6339 "TARGET_ARM" 6340 "@ 6341 mov%D3\\t%0, %2 6342 mvn%D3\\t%0, #%B2 6343 mov%d3\\t%0, %1 6344 mvn%d3\\t%0, #%B1 6345 mov%d3\\t%0, %1\;mov%D3\\t%0, %2 6346 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2 6347 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2 6348 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2" 6349 [(set_attr "length" "4,4,4,4,8,8,8,8") 6350 (set_attr "conds" "use")] 6351) 6352 6353(define_insn "*movsfcc_hard_insn" 6354 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f") 6355 (if_then_else:SF 6356 (match_operator 3 "arm_comparison_operator" 6357 [(match_operand 4 "cc_register" "") (const_int 0)]) 6358 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H") 6359 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))] 6360 "TARGET_ARM && TARGET_HARD_FLOAT" 6361 "@ 6362 mvf%D3s\\t%0, %2 6363 mnf%D3s\\t%0, #%N2 6364 mvf%d3s\\t%0, %1 6365 mnf%d3s\\t%0, #%N1 6366 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2 6367 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2 6368 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2 6369 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2" 6370 [(set_attr "length" "4,4,4,4,8,8,8,8") 6371 (set_attr "type" "ffarith") 6372 (set_attr "conds" "use")] 6373) 6374 6375(define_insn "*movsfcc_soft_insn" 6376 [(set (match_operand:SF 0 "s_register_operand" "=r,r") 6377 (if_then_else:SF (match_operator 3 "arm_comparison_operator" 6378 [(match_operand 4 "cc_register" "") (const_int 0)]) 6379 (match_operand:SF 1 "s_register_operand" "0,r") 6380 (match_operand:SF 2 "s_register_operand" "r,0")))] 6381 "TARGET_ARM && TARGET_SOFT_FLOAT" 6382 "@ 6383 mov%D3\\t%0, %2 6384 mov%d3\\t%0, %1" 6385 [(set_attr "conds" "use")] 6386) 6387 6388(define_insn "*movdfcc_insn" 6389 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f") 6390 (if_then_else:DF 6391 (match_operator 3 "arm_comparison_operator" 6392 [(match_operand 4 "cc_register" "") (const_int 0)]) 6393 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H") 6394 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))] 6395 "TARGET_ARM && TARGET_HARD_FLOAT" 6396 "@ 6397 mvf%D3d\\t%0, %2 6398 mnf%D3d\\t%0, #%N2 6399 mvf%d3d\\t%0, %1 6400 mnf%d3d\\t%0, #%N1 6401 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2 6402 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2 6403 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2 6404 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2" 6405 [(set_attr "length" "4,4,4,4,8,8,8,8") 6406 (set_attr "type" "ffarith") 6407 (set_attr "conds" "use")] 6408) 6409 6410 6411;; Jump and linkage insns 6412 6413(define_expand "jump" 6414 [(set (pc) 6415 (label_ref (match_operand 0 "" "")))] 6416 "TARGET_EITHER" 6417 "" 6418) 6419 6420(define_insn "*arm_jump" 6421 [(set (pc) 6422 (label_ref (match_operand 0 "" "")))] 6423 "TARGET_ARM" 6424 "* 6425 { 6426 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) 6427 { 6428 arm_ccfsm_state += 2; 6429 return \"\"; 6430 } 6431 return \"b%?\\t%l0\"; 6432 } 6433 " 6434 [(set_attr "predicable" "yes")] 6435) 6436 6437(define_insn "*thumb_jump" 6438 [(set (pc) 6439 (label_ref (match_operand 0 "" "")))] 6440 "TARGET_THUMB" 6441 "* 6442 if (get_attr_length (insn) == 2) 6443 return \"b\\t%l0\"; 6444 return \"bl\\t%l0\\t%@ far jump\"; 6445 " 6446 [(set (attr "far_jump") 6447 (if_then_else 6448 (eq_attr "length" "4") 6449 (const_string "yes") 6450 (const_string "no"))) 6451 (set (attr "length") 6452 (if_then_else 6453 (and (ge (minus (match_dup 0) (pc)) (const_int -2048)) 6454 (le (minus (match_dup 0) (pc)) (const_int 2044))) 6455 (const_int 2) 6456 (const_int 4)))] 6457) 6458 6459(define_expand "call" 6460 [(parallel [(call (match_operand 0 "memory_operand" "") 6461 (match_operand 1 "general_operand" "")) 6462 (use (match_operand 2 "" "")) 6463 (clobber (reg:SI LR_REGNUM))])] 6464 "TARGET_EITHER" 6465 " 6466 { 6467 rtx callee; 6468 6469 /* In an untyped call, we can get NULL for operand 2. */ 6470 if (operands[2] == NULL_RTX) 6471 operands[2] = const0_rtx; 6472 6473 /* This is to decide if we should generate indirect calls by loading the 6474 32 bit address of the callee into a register before performing the 6475 branch and link. operand[2] encodes the long_call/short_call 6476 attribute of the function being called. This attribute is set whenever 6477 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call 6478 is used, and the short_call attribute can also be set if function is 6479 declared as static or if it has already been defined in the current 6480 compilation unit. See arm.c and arm.h for info about this. The third 6481 parameter to arm_is_longcall_p is used to tell it which pattern 6482 invoked it. */ 6483 callee = XEXP (operands[0], 0); 6484 6485 if (GET_CODE (callee) != REG 6486 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0)) 6487 XEXP (operands[0], 0) = force_reg (Pmode, callee); 6488 }" 6489) 6490 6491(define_insn "*call_reg" 6492 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r")) 6493 (match_operand 1 "" "")) 6494 (use (match_operand 2 "" "")) 6495 (clobber (reg:SI LR_REGNUM))] 6496 "TARGET_ARM" 6497 "* 6498 return output_call (operands); 6499 " 6500 ;; length is worst case, normally it is only two 6501 [(set_attr "length" "12") 6502 (set_attr "type" "call")] 6503) 6504 6505(define_insn "*call_mem" 6506 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m")) 6507 (match_operand 1 "" "")) 6508 (use (match_operand 2 "" "")) 6509 (clobber (reg:SI LR_REGNUM))] 6510 "TARGET_ARM" 6511 "* 6512 return output_call_mem (operands); 6513 " 6514 [(set_attr "length" "12") 6515 (set_attr "type" "call")] 6516) 6517 6518(define_insn "*call_indirect" 6519 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r")) 6520 (match_operand 1 "" "")) 6521 (use (match_operand 2 "" "")) 6522 (clobber (reg:SI LR_REGNUM))] 6523 "TARGET_THUMB" 6524 "* 6525 { 6526 if (TARGET_CALLER_INTERWORKING) 6527 return \"bl\\t%__interwork_call_via_%0\"; 6528 else 6529 return \"bl\\t%__call_via_%0\"; 6530 }" 6531 [(set_attr "type" "call")] 6532) 6533 6534(define_insn "*call_value_indirect" 6535 [(set (match_operand 0 "" "=l") 6536 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r")) 6537 (match_operand 2 "" ""))) 6538 (use (match_operand 3 "" "")) 6539 (clobber (reg:SI LR_REGNUM))] 6540 "TARGET_THUMB" 6541 "* 6542 { 6543 if (TARGET_CALLER_INTERWORKING) 6544 return \"bl\\t%__interwork_call_via_%1\"; 6545 else 6546 return \"bl\\t%__call_via_%1\"; 6547 }" 6548 [(set_attr "type" "call")] 6549) 6550 6551(define_expand "call_value" 6552 [(parallel [(set (match_operand 0 "" "") 6553 (call (match_operand 1 "memory_operand" "") 6554 (match_operand 2 "general_operand" ""))) 6555 (use (match_operand 3 "" "")) 6556 (clobber (reg:SI LR_REGNUM))])] 6557 "TARGET_EITHER" 6558 " 6559 { 6560 rtx callee = XEXP (operands[1], 0); 6561 6562 /* In an untyped call, we can get NULL for operand 2. */ 6563 if (operands[3] == 0) 6564 operands[3] = const0_rtx; 6565 6566 /* See the comment in define_expand \"call\". */ 6567 if (GET_CODE (callee) != REG 6568 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0)) 6569 XEXP (operands[1], 0) = force_reg (Pmode, callee); 6570 }" 6571) 6572 6573(define_insn "*call_value_reg" 6574 [(set (match_operand 0 "" "=r,f") 6575 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r")) 6576 (match_operand 2 "" ""))) 6577 (use (match_operand 3 "" "")) 6578 (clobber (reg:SI LR_REGNUM))] 6579 "TARGET_ARM" 6580 "* 6581 return output_call (&operands[1]); 6582 " 6583 [(set_attr "length" "12") 6584 (set_attr "type" "call")] 6585) 6586 6587(define_insn "*call_value_mem" 6588 [(set (match_operand 0 "" "=r,f") 6589 (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m")) 6590 (match_operand 2 "" ""))) 6591 (use (match_operand 3 "" "")) 6592 (clobber (reg:SI LR_REGNUM))] 6593 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))" 6594 "* 6595 return output_call_mem (&operands[1]); 6596 " 6597 [(set_attr "length" "12") 6598 (set_attr "type" "call")] 6599) 6600 6601;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses 6602;; The 'a' causes the operand to be treated as an address, i.e. no '#' output. 6603 6604(define_insn "*call_symbol" 6605 [(call (mem:SI (match_operand:SI 0 "" "X")) 6606 (match_operand 1 "" "")) 6607 (use (match_operand 2 "" "")) 6608 (clobber (reg:SI LR_REGNUM))] 6609 "TARGET_ARM 6610 && (GET_CODE (operands[0]) == SYMBOL_REF) 6611 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)" 6612 "* 6613 { 6614 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\"; 6615 }" 6616 [(set_attr "type" "call")] 6617) 6618 6619(define_insn "*call_value_symbol" 6620 [(set (match_operand 0 "s_register_operand" "=r,f") 6621 (call (mem:SI (match_operand:SI 1 "" "X,X")) 6622 (match_operand:SI 2 "" ""))) 6623 (use (match_operand 3 "" "")) 6624 (clobber (reg:SI LR_REGNUM))] 6625 "TARGET_ARM 6626 && (GET_CODE (operands[1]) == SYMBOL_REF) 6627 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)" 6628 "* 6629 { 6630 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\"; 6631 }" 6632 [(set_attr "type" "call")] 6633) 6634 6635(define_insn "*call_insn" 6636 [(call (mem:SI (match_operand:SI 0 "" "X")) 6637 (match_operand:SI 1 "" "")) 6638 (use (match_operand 2 "" "")) 6639 (clobber (reg:SI LR_REGNUM))] 6640 "TARGET_THUMB 6641 && GET_CODE (operands[0]) == SYMBOL_REF 6642 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)" 6643 "bl\\t%a0" 6644 [(set_attr "length" "4") 6645 (set_attr "type" "call")] 6646) 6647 6648(define_insn "*call_value_insn" 6649 [(set (match_operand 0 "register_operand" "=l") 6650 (call (mem:SI (match_operand 1 "" "X")) 6651 (match_operand 2 "" ""))) 6652 (use (match_operand 3 "" "")) 6653 (clobber (reg:SI LR_REGNUM))] 6654 "TARGET_THUMB 6655 && GET_CODE (operands[1]) == SYMBOL_REF 6656 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)" 6657 "bl\\t%a1" 6658 [(set_attr "length" "4") 6659 (set_attr "type" "call")] 6660) 6661 6662;; We may also be able to do sibcalls for Thumb, but it's much harder... 6663(define_expand "sibcall" 6664 [(parallel [(call (match_operand 0 "memory_operand" "") 6665 (match_operand 1 "general_operand" "")) 6666 (use (match_operand 2 "" "")) 6667 (use (reg:SI LR_REGNUM))])] 6668 "TARGET_ARM" 6669 " 6670 { 6671 if (operands[2] == NULL_RTX) 6672 operands[2] = const0_rtx; 6673 }" 6674) 6675 6676(define_expand "sibcall_value" 6677 [(parallel [(set (match_operand 0 "register_operand" "") 6678 (call (match_operand 1 "memory_operand" "") 6679 (match_operand 2 "general_operand" ""))) 6680 (use (match_operand 3 "" "")) 6681 (use (reg:SI LR_REGNUM))])] 6682 "TARGET_ARM" 6683 " 6684 { 6685 if (operands[3] == NULL_RTX) 6686 operands[3] = const0_rtx; 6687 }" 6688) 6689 6690(define_insn "*sibcall_insn" 6691 [(call (mem:SI (match_operand:SI 0 "" "X")) 6692 (match_operand 1 "" "")) 6693 (use (match_operand 2 "" "")) 6694 (use (reg:SI LR_REGNUM))] 6695 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF" 6696 "* 6697 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\"; 6698 " 6699 [(set_attr "type" "call")] 6700) 6701 6702(define_insn "*sibcall_value_insn" 6703 [(set (match_operand 0 "s_register_operand" "=r,f") 6704 (call (mem:SI (match_operand:SI 1 "" "X,X")) 6705 (match_operand 2 "" ""))) 6706 (use (match_operand 3 "" "")) 6707 (use (reg:SI LR_REGNUM))] 6708 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF" 6709 "* 6710 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\"; 6711 " 6712 [(set_attr "type" "call")] 6713) 6714 6715;; Often the return insn will be the same as loading from memory, so set attr 6716(define_insn "return" 6717 [(return)] 6718 "TARGET_ARM && USE_RETURN_INSN (FALSE)" 6719 "* 6720 { 6721 if (arm_ccfsm_state == 2) 6722 { 6723 arm_ccfsm_state += 2; 6724 return \"\"; 6725 } 6726 return output_return_instruction (NULL, TRUE, FALSE); 6727 }" 6728 [(set_attr "type" "load") 6729 (set_attr "predicable" "yes")] 6730) 6731 6732(define_insn "*cond_return" 6733 [(set (pc) 6734 (if_then_else (match_operator 0 "arm_comparison_operator" 6735 [(match_operand 1 "cc_register" "") (const_int 0)]) 6736 (return) 6737 (pc)))] 6738 "TARGET_ARM && USE_RETURN_INSN (TRUE)" 6739 "* 6740 { 6741 if (arm_ccfsm_state == 2) 6742 { 6743 arm_ccfsm_state += 2; 6744 return \"\"; 6745 } 6746 return output_return_instruction (operands[0], TRUE, FALSE); 6747 }" 6748 [(set_attr "conds" "use") 6749 (set_attr "type" "load")] 6750) 6751 6752(define_insn "*cond_return_inverted" 6753 [(set (pc) 6754 (if_then_else (match_operator 0 "arm_comparison_operator" 6755 [(match_operand 1 "cc_register" "") (const_int 0)]) 6756 (pc) 6757 (return)))] 6758 "TARGET_ARM && USE_RETURN_INSN (TRUE)" 6759 "* 6760 { 6761 if (arm_ccfsm_state == 2) 6762 { 6763 arm_ccfsm_state += 2; 6764 return \"\"; 6765 } 6766 return output_return_instruction (operands[0], TRUE, TRUE); 6767 }" 6768 [(set_attr "conds" "use") 6769 (set_attr "type" "load")] 6770) 6771 6772;; Call subroutine returning any type. 6773 6774(define_expand "untyped_call" 6775 [(parallel [(call (match_operand 0 "" "") 6776 (const_int 0)) 6777 (match_operand 1 "" "") 6778 (match_operand 2 "" "")])] 6779 "TARGET_ARM" 6780 " 6781 { 6782 int i; 6783 6784 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); 6785 6786 for (i = 0; i < XVECLEN (operands[2], 0); i++) 6787 { 6788 rtx set = XVECEXP (operands[2], 0, i); 6789 6790 emit_move_insn (SET_DEST (set), SET_SRC (set)); 6791 } 6792 6793 /* The optimizer does not know that the call sets the function value 6794 registers we stored in the result block. We avoid problems by 6795 claiming that all hard registers are used and clobbered at this 6796 point. */ 6797 emit_insn (gen_blockage ()); 6798 6799 DONE; 6800 }" 6801) 6802 6803;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and 6804;; all of memory. This blocks insns from being moved across this point. 6805 6806(define_insn "blockage" 6807 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)] 6808 "TARGET_EITHER" 6809 "" 6810 [(set_attr "length" "0") 6811 (set_attr "type" "block")] 6812) 6813 6814(define_expand "casesi" 6815 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on 6816 (match_operand:SI 1 "const_int_operand" "") ; lower bound 6817 (match_operand:SI 2 "const_int_operand" "") ; total range 6818 (match_operand:SI 3 "" "") ; table label 6819 (match_operand:SI 4 "" "")] ; Out of range label 6820 "TARGET_ARM" 6821 " 6822 { 6823 rtx reg; 6824 if (operands[1] != const0_rtx) 6825 { 6826 reg = gen_reg_rtx (SImode); 6827 6828 emit_insn (gen_addsi3 (reg, operands[0], 6829 GEN_INT (-INTVAL (operands[1])))); 6830 operands[0] = reg; 6831 } 6832 6833 if (!const_ok_for_arm (INTVAL (operands[2]))) 6834 operands[2] = force_reg (SImode, operands[2]); 6835 6836 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3], 6837 operands[4])); 6838 DONE; 6839 }" 6840) 6841 6842;; The USE in this pattern is needed to tell flow analysis that this is 6843;; a CASESI insn. It has no other purpose. 6844(define_insn "casesi_internal" 6845 [(parallel [(set (pc) 6846 (if_then_else 6847 (leu (match_operand:SI 0 "s_register_operand" "r") 6848 (match_operand:SI 1 "arm_rhs_operand" "rI")) 6849 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4)) 6850 (label_ref (match_operand 2 "" "")))) 6851 (label_ref (match_operand 3 "" "")))) 6852 (clobber (reg:CC CC_REGNUM)) 6853 (use (label_ref (match_dup 2)))])] 6854 "TARGET_ARM" 6855 "* 6856 if (flag_pic) 6857 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\"; 6858 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\"; 6859 " 6860 [(set_attr "conds" "clob") 6861 (set_attr "length" "12")] 6862) 6863 6864(define_expand "indirect_jump" 6865 [(set (pc) 6866 (match_operand:SI 0 "s_register_operand" ""))] 6867 "TARGET_EITHER" 6868 "" 6869) 6870 6871(define_insn "*arm_indirect_jump" 6872 [(set (pc) 6873 (match_operand:SI 0 "s_register_operand" "r"))] 6874 "TARGET_ARM" 6875 "mov%?\\t%|pc, %0\\t%@ indirect register jump" 6876 [(set_attr "predicable" "yes")] 6877) 6878 6879;; Although not supported by the define_expand above, 6880;; cse/combine may generate this form. 6881(define_insn "*load_indirect_jump" 6882 [(set (pc) 6883 (match_operand:SI 0 "memory_operand" "m"))] 6884 "TARGET_ARM" 6885 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump" 6886 [(set_attr "type" "load") 6887 (set_attr "pool_range" "4096") 6888 (set_attr "neg_pool_range" "4084") 6889 (set_attr "predicable" "yes")] 6890) 6891 6892(define_insn "*thumb_indirect_jump" 6893 [(set (pc) 6894 (match_operand:SI 0 "register_operand" "l*r"))] 6895 "TARGET_THUMB" 6896 "mov\\tpc, %0" 6897 [(set_attr "conds" "clob") 6898 (set_attr "length" "2")] 6899) 6900 6901 6902;; Misc insns 6903 6904(define_insn "nop" 6905 [(const_int 0)] 6906 "TARGET_EITHER" 6907 "* 6908 if (TARGET_ARM) 6909 return \"mov%?\\t%|r0, %|r0\\t%@ nop\"; 6910 return \"mov\\tr8, r8\"; 6911 " 6912 [(set (attr "length") 6913 (if_then_else (eq_attr "is_thumb" "yes") 6914 (const_int 2) 6915 (const_int 4)))] 6916) 6917 6918 6919;; Patterns to allow combination of arithmetic, cond code and shifts 6920 6921(define_insn "*arith_shiftsi" 6922 [(set (match_operand:SI 0 "s_register_operand" "=r") 6923 (match_operator:SI 1 "shiftable_operator" 6924 [(match_operator:SI 3 "shift_operator" 6925 [(match_operand:SI 4 "s_register_operand" "r") 6926 (match_operand:SI 5 "reg_or_int_operand" "rI")]) 6927 (match_operand:SI 2 "s_register_operand" "r")]))] 6928 "TARGET_ARM" 6929 "%i1%?\\t%0, %2, %4%S3" 6930 [(set_attr "predicable" "yes") 6931 (set_attr "shift" "4") 6932 ] 6933) 6934 6935(define_insn "*arith_shiftsi_compare0" 6936 [(set (reg:CC_NOOV CC_REGNUM) 6937 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" 6938 [(match_operator:SI 3 "shift_operator" 6939 [(match_operand:SI 4 "s_register_operand" "r") 6940 (match_operand:SI 5 "reg_or_int_operand" "rI")]) 6941 (match_operand:SI 2 "s_register_operand" "r")]) 6942 (const_int 0))) 6943 (set (match_operand:SI 0 "s_register_operand" "=r") 6944 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)]) 6945 (match_dup 2)]))] 6946 "TARGET_ARM" 6947 "%i1%?s\\t%0, %2, %4%S3" 6948 [(set_attr "conds" "set") 6949 (set_attr "shift" "4") 6950 ] 6951) 6952 6953(define_insn "*arith_shiftsi_compare0_scratch" 6954 [(set (reg:CC_NOOV CC_REGNUM) 6955 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" 6956 [(match_operator:SI 3 "shift_operator" 6957 [(match_operand:SI 4 "s_register_operand" "r") 6958 (match_operand:SI 5 "reg_or_int_operand" "rI")]) 6959 (match_operand:SI 2 "s_register_operand" "r")]) 6960 (const_int 0))) 6961 (clobber (match_scratch:SI 0 "=r"))] 6962 "TARGET_ARM" 6963 "%i1%?s\\t%0, %2, %4%S3" 6964 [(set_attr "conds" "set") 6965 (set_attr "shift" "4") 6966 ] 6967) 6968 6969(define_insn "*sub_shiftsi" 6970 [(set (match_operand:SI 0 "s_register_operand" "=r") 6971 (minus:SI (match_operand:SI 1 "s_register_operand" "r") 6972 (match_operator:SI 2 "shift_operator" 6973 [(match_operand:SI 3 "s_register_operand" "r") 6974 (match_operand:SI 4 "reg_or_int_operand" "rM")])))] 6975 "TARGET_ARM" 6976 "sub%?\\t%0, %1, %3%S2" 6977 [(set_attr "predicable" "yes") 6978 (set_attr "shift" "3") 6979 ] 6980) 6981 6982(define_insn "*sub_shiftsi_compare0" 6983 [(set (reg:CC_NOOV CC_REGNUM) 6984 (compare:CC_NOOV 6985 (minus:SI (match_operand:SI 1 "s_register_operand" "r") 6986 (match_operator:SI 2 "shift_operator" 6987 [(match_operand:SI 3 "s_register_operand" "r") 6988 (match_operand:SI 4 "reg_or_int_operand" "rM")])) 6989 (const_int 0))) 6990 (set (match_operand:SI 0 "s_register_operand" "=r") 6991 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 6992 (match_dup 4)])))] 6993 "TARGET_ARM" 6994 "sub%?s\\t%0, %1, %3%S2" 6995 [(set_attr "conds" "set") 6996 (set_attr "shift" "3") 6997 ] 6998) 6999 7000(define_insn "*sub_shiftsi_compare0_scratch" 7001 [(set (reg:CC_NOOV CC_REGNUM) 7002 (compare:CC_NOOV 7003 (minus:SI (match_operand:SI 1 "s_register_operand" "r") 7004 (match_operator:SI 2 "shift_operator" 7005 [(match_operand:SI 3 "s_register_operand" "r") 7006 (match_operand:SI 4 "reg_or_int_operand" "rM")])) 7007 (const_int 0))) 7008 (clobber (match_scratch:SI 0 "=r"))] 7009 "TARGET_ARM" 7010 "sub%?s\\t%0, %1, %3%S2" 7011 [(set_attr "conds" "set") 7012 (set_attr "shift" "3") 7013 ] 7014) 7015 7016;; These variants of the above insns can occur if the first operand is the 7017;; frame pointer and we eliminate that. This is a kludge, but there doesn't 7018;; seem to be a way around it. Most of the predicates have to be null 7019;; because the format can be generated part way through reload, so 7020;; if we don't match it as soon as it becomes available, reload doesn't know 7021;; how to reload pseudos that haven't got hard registers; the constraints will 7022;; sort everything out. 7023 7024(define_insn "*reload_mulsi3" 7025 [(set (match_operand:SI 0 "" "=&r") 7026 (plus:SI (plus:SI (match_operator:SI 5 "shift_operator" 7027 [(match_operand:SI 3 "" "r") 7028 (match_operand:SI 4 "" "rM")]) 7029 (match_operand:SI 2 "" "r")) 7030 (match_operand:SI 1 "const_int_operand" "n")))] 7031 "TARGET_ARM && reload_in_progress" 7032 "* 7033 output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands); 7034 operands[2] = operands[1]; 7035 operands[1] = operands[0]; 7036 return output_add_immediate (operands); 7037 " 7038 [ 7039 ; we have no idea how long the add_immediate is, it could be up to 4. 7040 (set_attr "length" "20")] 7041) 7042 7043(define_insn "*reload_mulsi_compare0" 7044 [(set (reg:CC_NOOV CC_REGNUM) 7045 (compare:CC_NOOV (plus:SI 7046 (plus:SI 7047 (match_operator:SI 5 "shift_operator" 7048 [(match_operand:SI 3 "" "r") 7049 (match_operand:SI 4 "" "rM")]) 7050 (match_operand:SI 1 "" "r")) 7051 (match_operand:SI 2 "const_int_operand" "n")) 7052 (const_int 0))) 7053 (set (match_operand:SI 0 "" "=&r") 7054 (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)]) 7055 (match_dup 1)) 7056 (match_dup 2)))] 7057 "TARGET_ARM && reload_in_progress && !arm_is_xscale" 7058 "* 7059 output_add_immediate (operands); 7060 return \"add%?s\\t%0, %0, %3%S5\"; 7061 " 7062 [(set_attr "conds" "set") 7063 (set_attr "shift" "3") 7064 (set_attr "length" "20")] 7065) 7066 7067(define_insn "*reload_mulsi_compare0_scratch" 7068 [(set (reg:CC_NOOV CC_REGNUM) 7069 (compare:CC_NOOV (plus:SI 7070 (plus:SI 7071 (match_operator:SI 5 "shift_operator" 7072 [(match_operand:SI 3 "" "r") 7073 (match_operand:SI 4 "" "rM")]) 7074 (match_operand:SI 1 "" "r")) 7075 (match_operand:SI 2 "const_int_operand" "n")) 7076 (const_int 0))) 7077 (clobber (match_scratch:SI 0 "=&r"))] 7078 "TARGET_ARM && reload_in_progress && !arm_is_xscale" 7079 "* 7080 output_add_immediate (operands); 7081 return \"add%?s\\t%0, %0, %3%S5\"; 7082 " 7083 [(set_attr "conds" "set") 7084 (set_attr "shift" "3") 7085 (set_attr "length" "20")] 7086) 7087 7088;; These are similar, but are needed when the mla pattern contains the 7089;; eliminated register as operand 3. 7090 7091(define_insn "*reload_muladdsi" 7092 [(set (match_operand:SI 0 "" "=&r,&r") 7093 (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r") 7094 (match_operand:SI 2 "" "r,r")) 7095 (match_operand:SI 3 "" "r,r")) 7096 (match_operand:SI 4 "const_int_operand" "n,n")))] 7097 "TARGET_ARM && reload_in_progress" 7098 "* 7099 output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands); 7100 operands[2] = operands[4]; 7101 operands[1] = operands[0]; 7102 return output_add_immediate (operands); 7103 " 7104 [(set_attr "length" "20") 7105 (set_attr "type" "mult")] 7106) 7107 7108(define_insn "*reload_muladdsi_compare0" 7109 [(set (reg:CC_NOOV CC_REGNUM) 7110 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI 7111 (match_operand:SI 3 "" "r") 7112 (match_operand:SI 4 "" "r")) 7113 (match_operand:SI 1 "" "r")) 7114 (match_operand:SI 2 "const_int_operand" "n")) 7115 (const_int 0))) 7116 (set (match_operand:SI 0 "" "=&r") 7117 (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1)) 7118 (match_dup 2)))] 7119 "TARGET_ARM && reload_in_progress && !arm_is_xscale" 7120 "* 7121 output_add_immediate (operands); 7122 output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands); 7123 return \"\"; 7124 " 7125 [(set_attr "length" "20") 7126 (set_attr "conds" "set") 7127 (set_attr "type" "mult")] 7128) 7129 7130(define_insn "*reload_muladdsi_compare0_scratch" 7131 [(set (reg:CC_NOOV CC_REGNUM) 7132 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI 7133 (match_operand:SI 3 "" "r") 7134 (match_operand:SI 4 "" "r")) 7135 (match_operand:SI 1 "" "r")) 7136 (match_operand:SI 2 "const_int_operand" "n")) 7137 (const_int 0))) 7138 (clobber (match_scratch:SI 0 "=&r"))] 7139 "TARGET_ARM && reload_in_progress" 7140 "* 7141 output_add_immediate (operands); 7142 return \"mla%?s\\t%0, %3, %4, %0\"; 7143 " 7144 [(set_attr "length" "20") 7145 (set_attr "conds" "set") 7146 (set_attr "type" "mult")] 7147) 7148 7149 7150 7151(define_insn "*and_scc" 7152 [(set (match_operand:SI 0 "s_register_operand" "=r") 7153 (and:SI (match_operator:SI 1 "arm_comparison_operator" 7154 [(match_operand 3 "cc_register" "") (const_int 0)]) 7155 (match_operand:SI 2 "s_register_operand" "r")))] 7156 "TARGET_ARM" 7157 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1" 7158 [(set_attr "conds" "use") 7159 (set_attr "length" "8")] 7160) 7161 7162(define_insn "*ior_scc" 7163 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7164 (ior:SI (match_operator:SI 2 "arm_comparison_operator" 7165 [(match_operand 3 "cc_register" "") (const_int 0)]) 7166 (match_operand:SI 1 "s_register_operand" "0,?r")))] 7167 "TARGET_ARM" 7168 "@ 7169 orr%d2\\t%0, %1, #1 7170 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1" 7171 [(set_attr "conds" "use") 7172 (set_attr "length" "4,8")] 7173) 7174 7175(define_insn "*compare_scc" 7176 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7177 (match_operator:SI 1 "arm_comparison_operator" 7178 [(match_operand:SI 2 "s_register_operand" "r,r") 7179 (match_operand:SI 3 "arm_add_operand" "rI,L")])) 7180 (clobber (reg:CC CC_REGNUM))] 7181 "TARGET_ARM" 7182 "* 7183 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx) 7184 return \"mov\\t%0, %2, lsr #31\"; 7185 7186 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx) 7187 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\"; 7188 7189 if (GET_CODE (operands[1]) == NE) 7190 { 7191 if (which_alternative == 1) 7192 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\"; 7193 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\"; 7194 } 7195 if (which_alternative == 1) 7196 output_asm_insn (\"cmn\\t%2, #%n3\", operands); 7197 else 7198 output_asm_insn (\"cmp\\t%2, %3\", operands); 7199 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\"; 7200 " 7201 [(set_attr "conds" "clob") 7202 (set_attr "length" "12")] 7203) 7204 7205(define_insn "*cond_move" 7206 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 7207 (if_then_else:SI (match_operator 3 "equality_operator" 7208 [(match_operator 4 "arm_comparison_operator" 7209 [(match_operand 5 "cc_register" "") (const_int 0)]) 7210 (const_int 0)]) 7211 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI") 7212 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))] 7213 "TARGET_ARM" 7214 "* 7215 if (GET_CODE (operands[3]) == NE) 7216 { 7217 if (which_alternative != 1) 7218 output_asm_insn (\"mov%D4\\t%0, %2\", operands); 7219 if (which_alternative != 0) 7220 output_asm_insn (\"mov%d4\\t%0, %1\", operands); 7221 return \"\"; 7222 } 7223 if (which_alternative != 0) 7224 output_asm_insn (\"mov%D4\\t%0, %1\", operands); 7225 if (which_alternative != 1) 7226 output_asm_insn (\"mov%d4\\t%0, %2\", operands); 7227 return \"\"; 7228 " 7229 [(set_attr "conds" "use") 7230 (set_attr "length" "4,4,8")] 7231) 7232 7233(define_insn "*cond_arith" 7234 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7235 (match_operator:SI 5 "shiftable_operator" 7236 [(match_operator:SI 4 "arm_comparison_operator" 7237 [(match_operand:SI 2 "s_register_operand" "r,r") 7238 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) 7239 (match_operand:SI 1 "s_register_operand" "0,?r")])) 7240 (clobber (reg:CC CC_REGNUM))] 7241 "TARGET_ARM" 7242 "* 7243 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx) 7244 return \"%i5\\t%0, %1, %2, lsr #31\"; 7245 7246 output_asm_insn (\"cmp\\t%2, %3\", operands); 7247 if (GET_CODE (operands[5]) == AND) 7248 output_asm_insn (\"mov%D4\\t%0, #0\", operands); 7249 else if (GET_CODE (operands[5]) == MINUS) 7250 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands); 7251 else if (which_alternative != 0) 7252 output_asm_insn (\"mov%D4\\t%0, %1\", operands); 7253 return \"%i5%d4\\t%0, %1, #1\"; 7254 " 7255 [(set_attr "conds" "clob") 7256 (set_attr "length" "12")] 7257) 7258 7259(define_insn "*cond_sub" 7260 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7261 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r") 7262 (match_operator:SI 4 "arm_comparison_operator" 7263 [(match_operand:SI 2 "s_register_operand" "r,r") 7264 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]))) 7265 (clobber (reg:CC CC_REGNUM))] 7266 "TARGET_ARM" 7267 "* 7268 output_asm_insn (\"cmp\\t%2, %3\", operands); 7269 if (which_alternative != 0) 7270 output_asm_insn (\"mov%D4\\t%0, %1\", operands); 7271 return \"sub%d4\\t%0, %1, #1\"; 7272 " 7273 [(set_attr "conds" "clob") 7274 (set_attr "length" "8,12")] 7275) 7276 7277(define_insn "*cmp_ite0" 7278 [(set (match_operand 6 "dominant_cc_register" "") 7279 (compare 7280 (if_then_else:SI 7281 (match_operator 4 "arm_comparison_operator" 7282 [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 7283 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 7284 (match_operator:SI 5 "arm_comparison_operator" 7285 [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 7286 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]) 7287 (const_int 0)) 7288 (const_int 0)))] 7289 "TARGET_ARM" 7290 "* 7291 { 7292 static const char * const opcodes[4][2] = 7293 { 7294 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\", 7295 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"}, 7296 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", 7297 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"}, 7298 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", 7299 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"}, 7300 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\", 7301 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"} 7302 }; 7303 int swap = 7304 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])); 7305 7306 return opcodes[which_alternative][swap]; 7307 }" 7308 [(set_attr "conds" "set") 7309 (set_attr "length" "8")] 7310) 7311 7312(define_insn "*cmp_ite1" 7313 [(set (match_operand 6 "dominant_cc_register" "") 7314 (compare 7315 (if_then_else:SI 7316 (match_operator 4 "arm_comparison_operator" 7317 [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 7318 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 7319 (match_operator:SI 5 "arm_comparison_operator" 7320 [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 7321 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]) 7322 (const_int 1)) 7323 (const_int 0)))] 7324 "TARGET_ARM" 7325 "* 7326 { 7327 static const char * const opcodes[4][2] = 7328 { 7329 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\", 7330 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"}, 7331 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\", 7332 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"}, 7333 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\", 7334 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"}, 7335 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\", 7336 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"} 7337 }; 7338 int swap = 7339 comparison_dominates_p (GET_CODE (operands[5]), 7340 reverse_condition (GET_CODE (operands[4]))); 7341 7342 return opcodes[which_alternative][swap]; 7343 }" 7344 [(set_attr "conds" "set") 7345 (set_attr "length" "8")] 7346) 7347 7348(define_insn "*cmp_and" 7349 [(set (match_operand 6 "dominant_cc_register" "") 7350 (compare 7351 (and:SI 7352 (match_operator 4 "arm_comparison_operator" 7353 [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 7354 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 7355 (match_operator:SI 5 "arm_comparison_operator" 7356 [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 7357 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])) 7358 (const_int 0)))] 7359 "TARGET_ARM" 7360 "* 7361 { 7362 static const char *const opcodes[4][2] = 7363 { 7364 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\", 7365 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"}, 7366 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", 7367 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"}, 7368 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", 7369 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"}, 7370 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\", 7371 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"} 7372 }; 7373 int swap = 7374 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])); 7375 7376 return opcodes[which_alternative][swap]; 7377 }" 7378 [(set_attr "conds" "set") 7379 (set_attr "predicable" "no") 7380 (set_attr "length" "8")] 7381) 7382 7383(define_insn "*cmp_ior" 7384 [(set (match_operand 6 "dominant_cc_register" "") 7385 (compare 7386 (ior:SI 7387 (match_operator 4 "arm_comparison_operator" 7388 [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 7389 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 7390 (match_operator:SI 5 "arm_comparison_operator" 7391 [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 7392 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])) 7393 (const_int 0)))] 7394 "TARGET_ARM" 7395 "* 7396{ 7397 static const char *const opcodes[4][2] = 7398 { 7399 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\", 7400 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"}, 7401 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\", 7402 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"}, 7403 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\", 7404 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"}, 7405 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\", 7406 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"} 7407 }; 7408 int swap = 7409 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])); 7410 7411 return opcodes[which_alternative][swap]; 7412} 7413" 7414 [(set_attr "conds" "set") 7415 (set_attr "length" "8")] 7416) 7417 7418(define_insn "*negscc" 7419 [(set (match_operand:SI 0 "s_register_operand" "=r") 7420 (neg:SI (match_operator 3 "arm_comparison_operator" 7421 [(match_operand:SI 1 "s_register_operand" "r") 7422 (match_operand:SI 2 "arm_rhs_operand" "rI")]))) 7423 (clobber (reg:CC CC_REGNUM))] 7424 "TARGET_ARM" 7425 "* 7426 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx) 7427 return \"mov\\t%0, %1, asr #31\"; 7428 7429 if (GET_CODE (operands[3]) == NE) 7430 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\"; 7431 7432 if (GET_CODE (operands[3]) == GT) 7433 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\"; 7434 7435 output_asm_insn (\"cmp\\t%1, %2\", operands); 7436 output_asm_insn (\"mov%D3\\t%0, #0\", operands); 7437 return \"mvn%d3\\t%0, #0\"; 7438 " 7439 [(set_attr "conds" "clob") 7440 (set_attr "length" "12")] 7441) 7442 7443(define_insn "movcond" 7444 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 7445 (if_then_else:SI 7446 (match_operator 5 "arm_comparison_operator" 7447 [(match_operand:SI 3 "s_register_operand" "r,r,r") 7448 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")]) 7449 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI") 7450 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 7451 (clobber (reg:CC CC_REGNUM))] 7452 "TARGET_ARM" 7453 "* 7454 if (GET_CODE (operands[5]) == LT 7455 && (operands[4] == const0_rtx)) 7456 { 7457 if (which_alternative != 1 && GET_CODE (operands[1]) == REG) 7458 { 7459 if (operands[2] == const0_rtx) 7460 return \"and\\t%0, %1, %3, asr #31\"; 7461 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\"; 7462 } 7463 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG) 7464 { 7465 if (operands[1] == const0_rtx) 7466 return \"bic\\t%0, %2, %3, asr #31\"; 7467 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\"; 7468 } 7469 /* The only case that falls through to here is when both ops 1 & 2 7470 are constants */ 7471 } 7472 7473 if (GET_CODE (operands[5]) == GE 7474 && (operands[4] == const0_rtx)) 7475 { 7476 if (which_alternative != 1 && GET_CODE (operands[1]) == REG) 7477 { 7478 if (operands[2] == const0_rtx) 7479 return \"bic\\t%0, %1, %3, asr #31\"; 7480 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\"; 7481 } 7482 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG) 7483 { 7484 if (operands[1] == const0_rtx) 7485 return \"and\\t%0, %2, %3, asr #31\"; 7486 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\"; 7487 } 7488 /* The only case that falls through to here is when both ops 1 & 2 7489 are constants */ 7490 } 7491 if (GET_CODE (operands[4]) == CONST_INT 7492 && !const_ok_for_arm (INTVAL (operands[4]))) 7493 output_asm_insn (\"cmn\\t%3, #%n4\", operands); 7494 else 7495 output_asm_insn (\"cmp\\t%3, %4\", operands); 7496 if (which_alternative != 0) 7497 output_asm_insn (\"mov%d5\\t%0, %1\", operands); 7498 if (which_alternative != 1) 7499 output_asm_insn (\"mov%D5\\t%0, %2\", operands); 7500 return \"\"; 7501 " 7502 [(set_attr "conds" "clob") 7503 (set_attr "length" "8,8,12")] 7504) 7505 7506(define_insn "*ifcompare_plus_move" 7507 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7508 (if_then_else:SI (match_operator 6 "arm_comparison_operator" 7509 [(match_operand:SI 4 "s_register_operand" "r,r") 7510 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 7511 (plus:SI 7512 (match_operand:SI 2 "s_register_operand" "r,r") 7513 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")) 7514 (match_operand:SI 1 "arm_rhs_operand" "0,?rI"))) 7515 (clobber (reg:CC CC_REGNUM))] 7516 "TARGET_ARM" 7517 "#" 7518 [(set_attr "conds" "clob") 7519 (set_attr "length" "8,12")] 7520) 7521 7522(define_insn "*if_plus_move" 7523 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r") 7524 (if_then_else:SI 7525 (match_operator 4 "arm_comparison_operator" 7526 [(match_operand 5 "cc_register" "") (const_int 0)]) 7527 (plus:SI 7528 (match_operand:SI 2 "s_register_operand" "r,r,r,r") 7529 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L")) 7530 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))] 7531 "TARGET_ARM" 7532 "@ 7533 add%d4\\t%0, %2, %3 7534 sub%d4\\t%0, %2, #%n3 7535 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1 7536 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1" 7537 [(set_attr "conds" "use") 7538 (set_attr "length" "4,4,8,8") 7539 (set_attr "type" "*,*,*,*")] 7540) 7541 7542(define_insn "*ifcompare_move_plus" 7543 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7544 (if_then_else:SI (match_operator 6 "arm_comparison_operator" 7545 [(match_operand:SI 4 "s_register_operand" "r,r") 7546 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 7547 (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 7548 (plus:SI 7549 (match_operand:SI 2 "s_register_operand" "r,r") 7550 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")))) 7551 (clobber (reg:CC CC_REGNUM))] 7552 "TARGET_ARM" 7553 "#" 7554 [(set_attr "conds" "clob") 7555 (set_attr "length" "8,12")] 7556) 7557 7558(define_insn "*if_move_plus" 7559 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r") 7560 (if_then_else:SI 7561 (match_operator 4 "arm_comparison_operator" 7562 [(match_operand 5 "cc_register" "") (const_int 0)]) 7563 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI") 7564 (plus:SI 7565 (match_operand:SI 2 "s_register_operand" "r,r,r,r") 7566 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))] 7567 "TARGET_ARM" 7568 "@ 7569 add%D4\\t%0, %2, %3 7570 sub%D4\\t%0, %2, #%n3 7571 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1 7572 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1" 7573 [(set_attr "conds" "use") 7574 (set_attr "length" "4,4,8,8") 7575 (set_attr "type" "*,*,*,*")] 7576) 7577 7578(define_insn "*ifcompare_arith_arith" 7579 [(set (match_operand:SI 0 "s_register_operand" "=r") 7580 (if_then_else:SI (match_operator 9 "arm_comparison_operator" 7581 [(match_operand:SI 5 "s_register_operand" "r") 7582 (match_operand:SI 6 "arm_add_operand" "rIL")]) 7583 (match_operator:SI 8 "shiftable_operator" 7584 [(match_operand:SI 1 "s_register_operand" "r") 7585 (match_operand:SI 2 "arm_rhs_operand" "rI")]) 7586 (match_operator:SI 7 "shiftable_operator" 7587 [(match_operand:SI 3 "s_register_operand" "r") 7588 (match_operand:SI 4 "arm_rhs_operand" "rI")]))) 7589 (clobber (reg:CC CC_REGNUM))] 7590 "TARGET_ARM" 7591 "#" 7592 [(set_attr "conds" "clob") 7593 (set_attr "length" "12")] 7594) 7595 7596(define_insn "*if_arith_arith" 7597 [(set (match_operand:SI 0 "s_register_operand" "=r") 7598 (if_then_else:SI (match_operator 5 "arm_comparison_operator" 7599 [(match_operand 8 "cc_register" "") (const_int 0)]) 7600 (match_operator:SI 6 "shiftable_operator" 7601 [(match_operand:SI 1 "s_register_operand" "r") 7602 (match_operand:SI 2 "arm_rhs_operand" "rI")]) 7603 (match_operator:SI 7 "shiftable_operator" 7604 [(match_operand:SI 3 "s_register_operand" "r") 7605 (match_operand:SI 4 "arm_rhs_operand" "rI")])))] 7606 "TARGET_ARM" 7607 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4" 7608 [(set_attr "conds" "use") 7609 (set_attr "length" "8")] 7610) 7611 7612(define_insn "*ifcompare_arith_move" 7613 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7614 (if_then_else:SI (match_operator 6 "arm_comparison_operator" 7615 [(match_operand:SI 2 "s_register_operand" "r,r") 7616 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")]) 7617 (match_operator:SI 7 "shiftable_operator" 7618 [(match_operand:SI 4 "s_register_operand" "r,r") 7619 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")]) 7620 (match_operand:SI 1 "arm_rhs_operand" "0,?rI"))) 7621 (clobber (reg:CC CC_REGNUM))] 7622 "TARGET_ARM" 7623 "* 7624 /* If we have an operation where (op x 0) is the identity operation and 7625 the conditional operator is LT or GE and we are comparing against zero and 7626 everything is in registers then we can do this in two instructions */ 7627 if (operands[3] == const0_rtx 7628 && GET_CODE (operands[7]) != AND 7629 && GET_CODE (operands[5]) == REG 7630 && GET_CODE (operands[1]) == REG 7631 && REGNO (operands[1]) == REGNO (operands[4]) 7632 && REGNO (operands[4]) != REGNO (operands[0])) 7633 { 7634 if (GET_CODE (operands[6]) == LT) 7635 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\"; 7636 else if (GET_CODE (operands[6]) == GE) 7637 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\"; 7638 } 7639 if (GET_CODE (operands[3]) == CONST_INT 7640 && !const_ok_for_arm (INTVAL (operands[3]))) 7641 output_asm_insn (\"cmn\\t%2, #%n3\", operands); 7642 else 7643 output_asm_insn (\"cmp\\t%2, %3\", operands); 7644 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands); 7645 if (which_alternative != 0) 7646 return \"mov%D6\\t%0, %1\"; 7647 return \"\"; 7648 " 7649 [(set_attr "conds" "clob") 7650 (set_attr "length" "8,12")] 7651) 7652 7653(define_insn "*if_arith_move" 7654 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7655 (if_then_else:SI (match_operator 4 "arm_comparison_operator" 7656 [(match_operand 6 "cc_register" "") (const_int 0)]) 7657 (match_operator:SI 5 "shiftable_operator" 7658 [(match_operand:SI 2 "s_register_operand" "r,r") 7659 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) 7660 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))] 7661 "TARGET_ARM" 7662 "@ 7663 %I5%d4\\t%0, %2, %3 7664 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1" 7665 [(set_attr "conds" "use") 7666 (set_attr "length" "4,8") 7667 (set_attr "type" "*,*")] 7668) 7669 7670(define_insn "*ifcompare_move_arith" 7671 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7672 (if_then_else:SI (match_operator 6 "arm_comparison_operator" 7673 [(match_operand:SI 4 "s_register_operand" "r,r") 7674 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 7675 (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 7676 (match_operator:SI 7 "shiftable_operator" 7677 [(match_operand:SI 2 "s_register_operand" "r,r") 7678 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]))) 7679 (clobber (reg:CC CC_REGNUM))] 7680 "TARGET_ARM" 7681 "* 7682 /* If we have an operation where (op x 0) is the identity operation and 7683 the conditional operator is LT or GE and we are comparing against zero and 7684 everything is in registers then we can do this in two instructions */ 7685 if (operands[5] == const0_rtx 7686 && GET_CODE (operands[7]) != AND 7687 && GET_CODE (operands[3]) == REG 7688 && GET_CODE (operands[1]) == REG 7689 && REGNO (operands[1]) == REGNO (operands[2]) 7690 && REGNO (operands[2]) != REGNO (operands[0])) 7691 { 7692 if (GET_CODE (operands[6]) == GE) 7693 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\"; 7694 else if (GET_CODE (operands[6]) == LT) 7695 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\"; 7696 } 7697 7698 if (GET_CODE (operands[5]) == CONST_INT 7699 && !const_ok_for_arm (INTVAL (operands[5]))) 7700 output_asm_insn (\"cmn\\t%4, #%n5\", operands); 7701 else 7702 output_asm_insn (\"cmp\\t%4, %5\", operands); 7703 7704 if (which_alternative != 0) 7705 output_asm_insn (\"mov%d6\\t%0, %1\", operands); 7706 return \"%I7%D6\\t%0, %2, %3\"; 7707 " 7708 [(set_attr "conds" "clob") 7709 (set_attr "length" "8,12")] 7710) 7711 7712(define_insn "*if_move_arith" 7713 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7714 (if_then_else:SI 7715 (match_operator 4 "arm_comparison_operator" 7716 [(match_operand 6 "cc_register" "") (const_int 0)]) 7717 (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 7718 (match_operator:SI 5 "shiftable_operator" 7719 [(match_operand:SI 2 "s_register_operand" "r,r") 7720 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))] 7721 "TARGET_ARM" 7722 "@ 7723 %I5%D4\\t%0, %2, %3 7724 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1" 7725 [(set_attr "conds" "use") 7726 (set_attr "length" "4,8") 7727 (set_attr "type" "*,*")] 7728) 7729 7730(define_insn "*ifcompare_move_not" 7731 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7732 (if_then_else:SI 7733 (match_operator 5 "arm_comparison_operator" 7734 [(match_operand:SI 3 "s_register_operand" "r,r") 7735 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 7736 (match_operand:SI 1 "arm_not_operand" "0,?rIK") 7737 (not:SI 7738 (match_operand:SI 2 "s_register_operand" "r,r")))) 7739 (clobber (reg:CC CC_REGNUM))] 7740 "TARGET_ARM" 7741 "#" 7742 [(set_attr "conds" "clob") 7743 (set_attr "length" "8,12")] 7744) 7745 7746(define_insn "*if_move_not" 7747 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 7748 (if_then_else:SI 7749 (match_operator 4 "arm_comparison_operator" 7750 [(match_operand 3 "cc_register" "") (const_int 0)]) 7751 (match_operand:SI 1 "arm_not_operand" "0,?rI,K") 7752 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))] 7753 "TARGET_ARM" 7754 "@ 7755 mvn%D4\\t%0, %2 7756 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2 7757 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2" 7758 [(set_attr "conds" "use") 7759 (set_attr "length" "4,8,8")] 7760) 7761 7762(define_insn "*ifcompare_not_move" 7763 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7764 (if_then_else:SI 7765 (match_operator 5 "arm_comparison_operator" 7766 [(match_operand:SI 3 "s_register_operand" "r,r") 7767 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 7768 (not:SI 7769 (match_operand:SI 2 "s_register_operand" "r,r")) 7770 (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) 7771 (clobber (reg:CC CC_REGNUM))] 7772 "TARGET_ARM" 7773 "#" 7774 [(set_attr "conds" "clob") 7775 (set_attr "length" "8,12")] 7776) 7777 7778(define_insn "*if_not_move" 7779 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 7780 (if_then_else:SI 7781 (match_operator 4 "arm_comparison_operator" 7782 [(match_operand 3 "cc_register" "") (const_int 0)]) 7783 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r")) 7784 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] 7785 "TARGET_ARM" 7786 "@ 7787 mvn%d4\\t%0, %2 7788 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2 7789 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2" 7790 [(set_attr "conds" "use") 7791 (set_attr "length" "4,8,8")] 7792) 7793 7794(define_insn "*ifcompare_shift_move" 7795 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7796 (if_then_else:SI 7797 (match_operator 6 "arm_comparison_operator" 7798 [(match_operand:SI 4 "s_register_operand" "r,r") 7799 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 7800 (match_operator:SI 7 "shift_operator" 7801 [(match_operand:SI 2 "s_register_operand" "r,r") 7802 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")]) 7803 (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) 7804 (clobber (reg:CC CC_REGNUM))] 7805 "TARGET_ARM" 7806 "#" 7807 [(set_attr "conds" "clob") 7808 (set_attr "length" "8,12")] 7809) 7810 7811(define_insn "*if_shift_move" 7812 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 7813 (if_then_else:SI 7814 (match_operator 5 "arm_comparison_operator" 7815 [(match_operand 6 "cc_register" "") (const_int 0)]) 7816 (match_operator:SI 4 "shift_operator" 7817 [(match_operand:SI 2 "s_register_operand" "r,r,r") 7818 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")]) 7819 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] 7820 "TARGET_ARM" 7821 "@ 7822 mov%d5\\t%0, %2%S4 7823 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4 7824 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4" 7825 [(set_attr "conds" "use") 7826 (set_attr "shift" "2") 7827 (set_attr "length" "4,8,8")] 7828) 7829 7830(define_insn "*ifcompare_move_shift" 7831 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7832 (if_then_else:SI 7833 (match_operator 6 "arm_comparison_operator" 7834 [(match_operand:SI 4 "s_register_operand" "r,r") 7835 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 7836 (match_operand:SI 1 "arm_not_operand" "0,?rIK") 7837 (match_operator:SI 7 "shift_operator" 7838 [(match_operand:SI 2 "s_register_operand" "r,r") 7839 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")]))) 7840 (clobber (reg:CC CC_REGNUM))] 7841 "TARGET_ARM" 7842 "#" 7843 [(set_attr "conds" "clob") 7844 (set_attr "length" "8,12")] 7845) 7846 7847(define_insn "*if_move_shift" 7848 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 7849 (if_then_else:SI 7850 (match_operator 5 "arm_comparison_operator" 7851 [(match_operand 6 "cc_register" "") (const_int 0)]) 7852 (match_operand:SI 1 "arm_not_operand" "0,?rI,K") 7853 (match_operator:SI 4 "shift_operator" 7854 [(match_operand:SI 2 "s_register_operand" "r,r,r") 7855 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))] 7856 "TARGET_ARM" 7857 "@ 7858 mov%D5\\t%0, %2%S4 7859 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4 7860 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4" 7861 [(set_attr "conds" "use") 7862 (set_attr "shift" "2") 7863 (set_attr "length" "4,8,8")] 7864) 7865 7866(define_insn "*ifcompare_shift_shift" 7867 [(set (match_operand:SI 0 "s_register_operand" "=r") 7868 (if_then_else:SI 7869 (match_operator 7 "arm_comparison_operator" 7870 [(match_operand:SI 5 "s_register_operand" "r") 7871 (match_operand:SI 6 "arm_add_operand" "rIL")]) 7872 (match_operator:SI 8 "shift_operator" 7873 [(match_operand:SI 1 "s_register_operand" "r") 7874 (match_operand:SI 2 "arm_rhs_operand" "rM")]) 7875 (match_operator:SI 9 "shift_operator" 7876 [(match_operand:SI 3 "s_register_operand" "r") 7877 (match_operand:SI 4 "arm_rhs_operand" "rM")]))) 7878 (clobber (reg:CC CC_REGNUM))] 7879 "TARGET_ARM" 7880 "#" 7881 [(set_attr "conds" "clob") 7882 (set_attr "length" "12")] 7883) 7884 7885(define_insn "*if_shift_shift" 7886 [(set (match_operand:SI 0 "s_register_operand" "=r") 7887 (if_then_else:SI 7888 (match_operator 5 "arm_comparison_operator" 7889 [(match_operand 8 "cc_register" "") (const_int 0)]) 7890 (match_operator:SI 6 "shift_operator" 7891 [(match_operand:SI 1 "s_register_operand" "r") 7892 (match_operand:SI 2 "arm_rhs_operand" "rM")]) 7893 (match_operator:SI 7 "shift_operator" 7894 [(match_operand:SI 3 "s_register_operand" "r") 7895 (match_operand:SI 4 "arm_rhs_operand" "rM")])))] 7896 "TARGET_ARM" 7897 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7" 7898 [(set_attr "conds" "use") 7899 (set_attr "shift" "1") 7900 (set_attr "length" "8")] 7901) 7902 7903(define_insn "*ifcompare_not_arith" 7904 [(set (match_operand:SI 0 "s_register_operand" "=r") 7905 (if_then_else:SI 7906 (match_operator 6 "arm_comparison_operator" 7907 [(match_operand:SI 4 "s_register_operand" "r") 7908 (match_operand:SI 5 "arm_add_operand" "rIL")]) 7909 (not:SI (match_operand:SI 1 "s_register_operand" "r")) 7910 (match_operator:SI 7 "shiftable_operator" 7911 [(match_operand:SI 2 "s_register_operand" "r") 7912 (match_operand:SI 3 "arm_rhs_operand" "rI")]))) 7913 (clobber (reg:CC CC_REGNUM))] 7914 "TARGET_ARM" 7915 "#" 7916 [(set_attr "conds" "clob") 7917 (set_attr "length" "12")] 7918) 7919 7920(define_insn "*if_not_arith" 7921 [(set (match_operand:SI 0 "s_register_operand" "=r") 7922 (if_then_else:SI 7923 (match_operator 5 "arm_comparison_operator" 7924 [(match_operand 4 "cc_register" "") (const_int 0)]) 7925 (not:SI (match_operand:SI 1 "s_register_operand" "r")) 7926 (match_operator:SI 6 "shiftable_operator" 7927 [(match_operand:SI 2 "s_register_operand" "r") 7928 (match_operand:SI 3 "arm_rhs_operand" "rI")])))] 7929 "TARGET_ARM" 7930 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3" 7931 [(set_attr "conds" "use") 7932 (set_attr "length" "8")] 7933) 7934 7935(define_insn "*ifcompare_arith_not" 7936 [(set (match_operand:SI 0 "s_register_operand" "=r") 7937 (if_then_else:SI 7938 (match_operator 6 "arm_comparison_operator" 7939 [(match_operand:SI 4 "s_register_operand" "r") 7940 (match_operand:SI 5 "arm_add_operand" "rIL")]) 7941 (match_operator:SI 7 "shiftable_operator" 7942 [(match_operand:SI 2 "s_register_operand" "r") 7943 (match_operand:SI 3 "arm_rhs_operand" "rI")]) 7944 (not:SI (match_operand:SI 1 "s_register_operand" "r")))) 7945 (clobber (reg:CC CC_REGNUM))] 7946 "TARGET_ARM" 7947 "#" 7948 [(set_attr "conds" "clob") 7949 (set_attr "length" "12")] 7950) 7951 7952(define_insn "*if_arith_not" 7953 [(set (match_operand:SI 0 "s_register_operand" "=r") 7954 (if_then_else:SI 7955 (match_operator 5 "arm_comparison_operator" 7956 [(match_operand 4 "cc_register" "") (const_int 0)]) 7957 (match_operator:SI 6 "shiftable_operator" 7958 [(match_operand:SI 2 "s_register_operand" "r") 7959 (match_operand:SI 3 "arm_rhs_operand" "rI")]) 7960 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))] 7961 "TARGET_ARM" 7962 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3" 7963 [(set_attr "conds" "use") 7964 (set_attr "length" "8")] 7965) 7966 7967(define_insn "*ifcompare_neg_move" 7968 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 7969 (if_then_else:SI 7970 (match_operator 5 "arm_comparison_operator" 7971 [(match_operand:SI 3 "s_register_operand" "r,r") 7972 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 7973 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r")) 7974 (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) 7975 (clobber (reg:CC CC_REGNUM))] 7976 "TARGET_ARM" 7977 "#" 7978 [(set_attr "conds" "clob") 7979 (set_attr "length" "8,12")] 7980) 7981 7982(define_insn "*if_neg_move" 7983 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 7984 (if_then_else:SI 7985 (match_operator 4 "arm_comparison_operator" 7986 [(match_operand 3 "cc_register" "") (const_int 0)]) 7987 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r")) 7988 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] 7989 "TARGET_ARM" 7990 "@ 7991 rsb%d4\\t%0, %2, #0 7992 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0 7993 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0" 7994 [(set_attr "conds" "use") 7995 (set_attr "length" "4,8,8")] 7996) 7997 7998(define_insn "*ifcompare_move_neg" 7999 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8000 (if_then_else:SI 8001 (match_operator 5 "arm_comparison_operator" 8002 [(match_operand:SI 3 "s_register_operand" "r,r") 8003 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 8004 (match_operand:SI 1 "arm_not_operand" "0,?rIK") 8005 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r")))) 8006 (clobber (reg:CC CC_REGNUM))] 8007 "TARGET_ARM" 8008 "#" 8009 [(set_attr "conds" "clob") 8010 (set_attr "length" "8,12")] 8011) 8012 8013(define_insn "*if_move_neg" 8014 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 8015 (if_then_else:SI 8016 (match_operator 4 "arm_comparison_operator" 8017 [(match_operand 3 "cc_register" "") (const_int 0)]) 8018 (match_operand:SI 1 "arm_not_operand" "0,?rI,K") 8019 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))] 8020 "TARGET_ARM" 8021 "@ 8022 rsb%D4\\t%0, %2, #0 8023 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0 8024 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0" 8025 [(set_attr "conds" "use") 8026 (set_attr "length" "4,8,8")] 8027) 8028 8029(define_insn "*arith_adjacentmem" 8030 [(set (match_operand:SI 0 "s_register_operand" "=r") 8031 (match_operator:SI 1 "shiftable_operator" 8032 [(match_operand:SI 2 "memory_operand" "m") 8033 (match_operand:SI 3 "memory_operand" "m")])) 8034 (clobber (match_scratch:SI 4 "=r"))] 8035 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])" 8036 "* 8037 { 8038 rtx ldm[3]; 8039 rtx arith[4]; 8040 int val1 = 0, val2 = 0; 8041 8042 if (REGNO (operands[0]) > REGNO (operands[4])) 8043 { 8044 ldm[1] = operands[4]; 8045 ldm[2] = operands[0]; 8046 } 8047 else 8048 { 8049 ldm[1] = operands[0]; 8050 ldm[2] = operands[4]; 8051 } 8052 if (GET_CODE (XEXP (operands[2], 0)) != REG) 8053 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1)); 8054 if (GET_CODE (XEXP (operands[3], 0)) != REG) 8055 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1)); 8056 arith[0] = operands[0]; 8057 arith[3] = operands[1]; 8058 if (val1 < val2) 8059 { 8060 arith[1] = ldm[1]; 8061 arith[2] = ldm[2]; 8062 } 8063 else 8064 { 8065 arith[1] = ldm[2]; 8066 arith[2] = ldm[1]; 8067 } 8068 if (val1 && val2) 8069 { 8070 rtx ops[3]; 8071 ldm[0] = ops[0] = operands[4]; 8072 ops[1] = XEXP (XEXP (operands[2], 0), 0); 8073 ops[2] = XEXP (XEXP (operands[2], 0), 1); 8074 output_add_immediate (ops); 8075 if (val1 < val2) 8076 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); 8077 else 8078 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); 8079 } 8080 else if (val1) 8081 { 8082 ldm[0] = XEXP (operands[3], 0); 8083 if (val1 < val2) 8084 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); 8085 else 8086 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); 8087 } 8088 else 8089 { 8090 ldm[0] = XEXP (operands[2], 0); 8091 if (val1 < val2) 8092 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); 8093 else 8094 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); 8095 } 8096 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith); 8097 return \"\"; 8098 }" 8099 [(set_attr "length" "12") 8100 (set_attr "predicable" "yes") 8101 (set_attr "type" "load")] 8102) 8103 8104;; the arm can support extended pre-inc instructions 8105 8106;; In all these cases, we use operands 0 and 1 for the register being 8107;; incremented because those are the operands that local-alloc will 8108;; tie and these are the pair most likely to be tieable (and the ones 8109;; that will benefit the most). 8110 8111;; We reject the frame pointer if it occurs anywhere in these patterns since 8112;; elimination will cause too many headaches. 8113 8114(define_insn "*strqi_preinc" 8115 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 8116 (match_operand:SI 2 "index_operand" "rJ"))) 8117 (match_operand:QI 3 "s_register_operand" "r")) 8118 (set (match_operand:SI 0 "s_register_operand" "=r") 8119 (plus:SI (match_dup 1) (match_dup 2)))] 8120 "TARGET_ARM 8121 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8122 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8123 && (GET_CODE (operands[2]) != REG 8124 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8125 "str%?b\\t%3, [%0, %2]!" 8126 [(set_attr "type" "store1") 8127 (set_attr "predicable" "yes")] 8128) 8129 8130(define_insn "*strqi_predec" 8131 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8132 (match_operand:SI 2 "s_register_operand" "r"))) 8133 (match_operand:QI 3 "s_register_operand" "r")) 8134 (set (match_operand:SI 0 "s_register_operand" "=r") 8135 (minus:SI (match_dup 1) (match_dup 2)))] 8136 "TARGET_ARM 8137 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8138 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8139 && (GET_CODE (operands[2]) != REG 8140 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8141 "str%?b\\t%3, [%0, -%2]!" 8142 [(set_attr "type" "store1") 8143 (set_attr "predicable" "yes")] 8144) 8145 8146(define_insn "*loadqi_preinc" 8147 [(set (match_operand:QI 3 "s_register_operand" "=r") 8148 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 8149 (match_operand:SI 2 "index_operand" "rJ")))) 8150 (set (match_operand:SI 0 "s_register_operand" "=r") 8151 (plus:SI (match_dup 1) (match_dup 2)))] 8152 "TARGET_ARM 8153 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8154 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8155 && (GET_CODE (operands[2]) != REG 8156 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8157 "ldr%?b\\t%3, [%0, %2]!" 8158 [(set_attr "type" "load") 8159 (set_attr "predicable" "yes")] 8160) 8161 8162(define_insn "*loadqi_predec" 8163 [(set (match_operand:QI 3 "s_register_operand" "=r") 8164 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8165 (match_operand:SI 2 "s_register_operand" "r")))) 8166 (set (match_operand:SI 0 "s_register_operand" "=r") 8167 (minus:SI (match_dup 1) (match_dup 2)))] 8168 "TARGET_ARM 8169 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8170 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8171 && (GET_CODE (operands[2]) != REG 8172 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8173 "ldr%?b\\t%3, [%0, -%2]!" 8174 [(set_attr "type" "load") 8175 (set_attr "predicable" "yes")] 8176) 8177 8178(define_insn "*loadqisi_preinc" 8179 [(set (match_operand:SI 3 "s_register_operand" "=r") 8180 (zero_extend:SI 8181 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 8182 (match_operand:SI 2 "index_operand" "rJ"))))) 8183 (set (match_operand:SI 0 "s_register_operand" "=r") 8184 (plus:SI (match_dup 1) (match_dup 2)))] 8185 "TARGET_ARM 8186 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8187 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8188 && (GET_CODE (operands[2]) != REG 8189 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8190 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi" 8191 [(set_attr "type" "load") 8192 (set_attr "predicable" "yes")] 8193) 8194 8195(define_insn "*loadqisi_predec" 8196 [(set (match_operand:SI 3 "s_register_operand" "=r") 8197 (zero_extend:SI 8198 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8199 (match_operand:SI 2 "s_register_operand" "r"))))) 8200 (set (match_operand:SI 0 "s_register_operand" "=r") 8201 (minus:SI (match_dup 1) (match_dup 2)))] 8202 "TARGET_ARM 8203 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8204 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8205 && (GET_CODE (operands[2]) != REG 8206 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8207 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi" 8208 [(set_attr "type" "load") 8209 (set_attr "predicable" "yes")] 8210) 8211 8212(define_insn "*strsi_preinc" 8213 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 8214 (match_operand:SI 2 "index_operand" "rJ"))) 8215 (match_operand:SI 3 "s_register_operand" "r")) 8216 (set (match_operand:SI 0 "s_register_operand" "=r") 8217 (plus:SI (match_dup 1) (match_dup 2)))] 8218 "TARGET_ARM 8219 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8220 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8221 && (GET_CODE (operands[2]) != REG 8222 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8223 "str%?\\t%3, [%0, %2]!" 8224 [(set_attr "type" "store1") 8225 (set_attr "predicable" "yes")] 8226) 8227 8228(define_insn "*strsi_predec" 8229 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8230 (match_operand:SI 2 "s_register_operand" "r"))) 8231 (match_operand:SI 3 "s_register_operand" "r")) 8232 (set (match_operand:SI 0 "s_register_operand" "=r") 8233 (minus:SI (match_dup 1) (match_dup 2)))] 8234 "TARGET_ARM 8235 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8236 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8237 && (GET_CODE (operands[2]) != REG 8238 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8239 "str%?\\t%3, [%0, -%2]!" 8240 [(set_attr "type" "store1") 8241 (set_attr "predicable" "yes")] 8242) 8243 8244(define_insn "*loadsi_preinc" 8245 [(set (match_operand:SI 3 "s_register_operand" "=r") 8246 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 8247 (match_operand:SI 2 "index_operand" "rJ")))) 8248 (set (match_operand:SI 0 "s_register_operand" "=r") 8249 (plus:SI (match_dup 1) (match_dup 2)))] 8250 "TARGET_ARM 8251 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8252 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8253 && (GET_CODE (operands[2]) != REG 8254 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8255 "ldr%?\\t%3, [%0, %2]!" 8256 [(set_attr "type" "load") 8257 (set_attr "predicable" "yes")] 8258) 8259 8260(define_insn "*loadsi_predec" 8261 [(set (match_operand:SI 3 "s_register_operand" "=r") 8262 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8263 (match_operand:SI 2 "s_register_operand" "r")))) 8264 (set (match_operand:SI 0 "s_register_operand" "=r") 8265 (minus:SI (match_dup 1) (match_dup 2)))] 8266 "TARGET_ARM 8267 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8268 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8269 && (GET_CODE (operands[2]) != REG 8270 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8271 "ldr%?\\t%3, [%0, -%2]!" 8272 [(set_attr "type" "load") 8273 (set_attr "predicable" "yes")] 8274) 8275 8276(define_insn "*loadhi_preinc" 8277 [(set (match_operand:HI 3 "s_register_operand" "=r") 8278 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 8279 (match_operand:SI 2 "index_operand" "rJ")))) 8280 (set (match_operand:SI 0 "s_register_operand" "=r") 8281 (plus:SI (match_dup 1) (match_dup 2)))] 8282 "TARGET_ARM 8283 && !BYTES_BIG_ENDIAN 8284 && !TARGET_MMU_TRAPS 8285 && !arm_arch4 8286 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8287 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8288 && (GET_CODE (operands[2]) != REG 8289 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8290 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi" 8291 [(set_attr "type" "load") 8292 (set_attr "predicable" "yes")] 8293) 8294 8295(define_insn "*loadhi_predec" 8296 [(set (match_operand:HI 3 "s_register_operand" "=r") 8297 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8298 (match_operand:SI 2 "s_register_operand" "r")))) 8299 (set (match_operand:SI 0 "s_register_operand" "=r") 8300 (minus:SI (match_dup 1) (match_dup 2)))] 8301 "TARGET_ARM 8302 && !BYTES_BIG_ENDIAN 8303 && !TARGET_MMU_TRAPS 8304 && !arm_arch4 8305 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8306 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8307 && (GET_CODE (operands[2]) != REG 8308 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 8309 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi" 8310 [(set_attr "type" "load") 8311 (set_attr "predicable" "yes")] 8312) 8313 8314(define_insn "*strqi_shiftpreinc" 8315 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator" 8316 [(match_operand:SI 3 "s_register_operand" "r") 8317 (match_operand:SI 4 "const_shift_operand" "n")]) 8318 (match_operand:SI 1 "s_register_operand" "0"))) 8319 (match_operand:QI 5 "s_register_operand" "r")) 8320 (set (match_operand:SI 0 "s_register_operand" "=r") 8321 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 8322 (match_dup 1)))] 8323 "TARGET_ARM 8324 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8325 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8326 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 8327 "str%?b\\t%5, [%0, %3%S2]!" 8328 [(set_attr "type" "store1") 8329 (set_attr "predicable" "yes")] 8330) 8331 8332(define_insn "*strqi_shiftpredec" 8333 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8334 (match_operator:SI 2 "shift_operator" 8335 [(match_operand:SI 3 "s_register_operand" "r") 8336 (match_operand:SI 4 "const_shift_operand" "n")]))) 8337 (match_operand:QI 5 "s_register_operand" "r")) 8338 (set (match_operand:SI 0 "s_register_operand" "=r") 8339 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 8340 (match_dup 4)])))] 8341 "TARGET_ARM 8342 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8343 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8344 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 8345 "str%?b\\t%5, [%0, -%3%S2]!" 8346 [(set_attr "type" "store1") 8347 (set_attr "predicable" "yes")] 8348) 8349 8350(define_insn "*loadqi_shiftpreinc" 8351 [(set (match_operand:QI 5 "s_register_operand" "=r") 8352 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator" 8353 [(match_operand:SI 3 "s_register_operand" "r") 8354 (match_operand:SI 4 "const_shift_operand" "n")]) 8355 (match_operand:SI 1 "s_register_operand" "0")))) 8356 (set (match_operand:SI 0 "s_register_operand" "=r") 8357 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 8358 (match_dup 1)))] 8359 "TARGET_ARM 8360 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8361 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8362 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 8363 "ldr%?b\\t%5, [%0, %3%S2]!" 8364 [(set_attr "type" "load") 8365 (set_attr "predicable" "yes")] 8366) 8367 8368(define_insn "*loadqi_shiftpredec" 8369 [(set (match_operand:QI 5 "s_register_operand" "=r") 8370 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8371 (match_operator:SI 2 "shift_operator" 8372 [(match_operand:SI 3 "s_register_operand" "r") 8373 (match_operand:SI 4 "const_shift_operand" "n")])))) 8374 (set (match_operand:SI 0 "s_register_operand" "=r") 8375 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 8376 (match_dup 4)])))] 8377 "TARGET_ARM 8378 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8379 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8380 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 8381 "ldr%?b\\t%5, [%0, -%3%S2]!" 8382 [(set_attr "type" "load") 8383 (set_attr "predicable" "yes")] 8384) 8385 8386(define_insn "*strsi_shiftpreinc" 8387 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator" 8388 [(match_operand:SI 3 "s_register_operand" "r") 8389 (match_operand:SI 4 "const_shift_operand" "n")]) 8390 (match_operand:SI 1 "s_register_operand" "0"))) 8391 (match_operand:SI 5 "s_register_operand" "r")) 8392 (set (match_operand:SI 0 "s_register_operand" "=r") 8393 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 8394 (match_dup 1)))] 8395 "TARGET_ARM 8396 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8397 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8398 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 8399 "str%?\\t%5, [%0, %3%S2]!" 8400 [(set_attr "type" "store1") 8401 (set_attr "predicable" "yes")] 8402) 8403 8404(define_insn "*strsi_shiftpredec" 8405 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8406 (match_operator:SI 2 "shift_operator" 8407 [(match_operand:SI 3 "s_register_operand" "r") 8408 (match_operand:SI 4 "const_shift_operand" "n")]))) 8409 (match_operand:SI 5 "s_register_operand" "r")) 8410 (set (match_operand:SI 0 "s_register_operand" "=r") 8411 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 8412 (match_dup 4)])))] 8413 "TARGET_ARM 8414 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8415 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8416 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 8417 "str%?\\t%5, [%0, -%3%S2]!" 8418 [(set_attr "type" "store1") 8419 (set_attr "predicable" "yes")] 8420) 8421 8422(define_insn "*loadsi_shiftpreinc" 8423 [(set (match_operand:SI 5 "s_register_operand" "=r") 8424 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator" 8425 [(match_operand:SI 3 "s_register_operand" "r") 8426 (match_operand:SI 4 "const_shift_operand" "n")]) 8427 (match_operand:SI 1 "s_register_operand" "0")))) 8428 (set (match_operand:SI 0 "s_register_operand" "=r") 8429 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 8430 (match_dup 1)))] 8431 "TARGET_ARM 8432 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8433 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8434 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 8435 "ldr%?\\t%5, [%0, %3%S2]!" 8436 [(set_attr "type" "load") 8437 (set_attr "predicable" "yes")] 8438) 8439 8440(define_insn "*loadsi_shiftpredec" 8441 [(set (match_operand:SI 5 "s_register_operand" "=r") 8442 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8443 (match_operator:SI 2 "shift_operator" 8444 [(match_operand:SI 3 "s_register_operand" "r") 8445 (match_operand:SI 4 "const_shift_operand" "n")])))) 8446 (set (match_operand:SI 0 "s_register_operand" "=r") 8447 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 8448 (match_dup 4)])))] 8449 "TARGET_ARM 8450 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8451 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8452 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 8453 "ldr%?\\t%5, [%0, -%3%S2]!" 8454 [(set_attr "type" "load") 8455 (set_attr "predicable" "yes")]) 8456 8457(define_insn "*loadhi_shiftpreinc" 8458 [(set (match_operand:HI 5 "s_register_operand" "=r") 8459 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator" 8460 [(match_operand:SI 3 "s_register_operand" "r") 8461 (match_operand:SI 4 "const_shift_operand" "n")]) 8462 (match_operand:SI 1 "s_register_operand" "0")))) 8463 (set (match_operand:SI 0 "s_register_operand" "=r") 8464 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 8465 (match_dup 1)))] 8466 "TARGET_ARM 8467 && !BYTES_BIG_ENDIAN 8468 && !TARGET_MMU_TRAPS 8469 && !arm_arch4 8470 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8471 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8472 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 8473 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi" 8474 [(set_attr "type" "load") 8475 (set_attr "predicable" "yes")] 8476) 8477 8478(define_insn "*loadhi_shiftpredec" 8479 [(set (match_operand:HI 5 "s_register_operand" "=r") 8480 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 8481 (match_operator:SI 2 "shift_operator" 8482 [(match_operand:SI 3 "s_register_operand" "r") 8483 (match_operand:SI 4 "const_shift_operand" "n")])))) 8484 (set (match_operand:SI 0 "s_register_operand" "=r") 8485 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 8486 (match_dup 4)])))] 8487 "TARGET_ARM 8488 && !BYTES_BIG_ENDIAN 8489 && !TARGET_MMU_TRAPS 8490 && !arm_arch4 8491 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 8492 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 8493 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 8494 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi" 8495 [(set_attr "type" "load") 8496 (set_attr "predicable" "yes")] 8497) 8498 8499; It can also support extended post-inc expressions, but combine doesn't 8500; try these.... 8501; It doesn't seem worth adding peepholes for anything but the most common 8502; cases since, unlike combine, the increment must immediately follow the load 8503; for this pattern to match. 8504; We must watch to see that the source/destination register isn't also the 8505; same as the base address register, and that if the index is a register, 8506; that it is not the same as the base address register. In such cases the 8507; instruction that we would generate would have UNPREDICTABLE behaviour so 8508; we cannot use it. 8509 8510(define_peephole 8511 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r")) 8512 (match_operand:QI 2 "s_register_operand" "r")) 8513 (set (match_dup 0) 8514 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))] 8515 "TARGET_ARM 8516 && (REGNO (operands[2]) != REGNO (operands[0])) 8517 && (GET_CODE (operands[1]) != REG 8518 || (REGNO (operands[1]) != REGNO (operands[0])))" 8519 "str%?b\\t%2, [%0], %1" 8520) 8521 8522(define_peephole 8523 [(set (match_operand:QI 0 "s_register_operand" "=r") 8524 (mem:QI (match_operand:SI 1 "s_register_operand" "+r"))) 8525 (set (match_dup 1) 8526 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))] 8527 "TARGET_ARM 8528 && REGNO (operands[0]) != REGNO(operands[1]) 8529 && (GET_CODE (operands[2]) != REG 8530 || REGNO(operands[0]) != REGNO (operands[2]))" 8531 "ldr%?b\\t%0, [%1], %2" 8532) 8533 8534(define_peephole 8535 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r")) 8536 (match_operand:SI 2 "s_register_operand" "r")) 8537 (set (match_dup 0) 8538 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))] 8539 "TARGET_ARM 8540 && (REGNO (operands[2]) != REGNO (operands[0])) 8541 && (GET_CODE (operands[1]) != REG 8542 || (REGNO (operands[1]) != REGNO (operands[0])))" 8543 "str%?\\t%2, [%0], %1" 8544) 8545 8546(define_peephole 8547 [(set (match_operand:HI 0 "s_register_operand" "=r") 8548 (mem:HI (match_operand:SI 1 "s_register_operand" "+r"))) 8549 (set (match_dup 1) 8550 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))] 8551 "TARGET_ARM 8552 && !BYTES_BIG_ENDIAN 8553 && !TARGET_MMU_TRAPS 8554 && !arm_arch4 8555 && REGNO (operands[0]) != REGNO(operands[1]) 8556 && (GET_CODE (operands[2]) != REG 8557 || REGNO(operands[0]) != REGNO (operands[2]))" 8558 "ldr%?\\t%0, [%1], %2\\t%@ loadhi" 8559) 8560 8561(define_peephole 8562 [(set (match_operand:SI 0 "s_register_operand" "=r") 8563 (mem:SI (match_operand:SI 1 "s_register_operand" "+r"))) 8564 (set (match_dup 1) 8565 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))] 8566 "TARGET_ARM 8567 && REGNO (operands[0]) != REGNO(operands[1]) 8568 && (GET_CODE (operands[2]) != REG 8569 || REGNO(operands[0]) != REGNO (operands[2]))" 8570 "ldr%?\\t%0, [%1], %2" 8571) 8572 8573(define_peephole 8574 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r") 8575 (match_operand:SI 1 "index_operand" "rJ"))) 8576 (match_operand:QI 2 "s_register_operand" "r")) 8577 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))] 8578 "TARGET_ARM 8579 && (REGNO (operands[2]) != REGNO (operands[0])) 8580 && (GET_CODE (operands[1]) != REG 8581 || (REGNO (operands[1]) != REGNO (operands[0])))" 8582 "str%?b\\t%2, [%0, %1]!" 8583) 8584 8585(define_peephole 8586 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator" 8587 [(match_operand:SI 0 "s_register_operand" "r") 8588 (match_operand:SI 1 "const_int_operand" "n")]) 8589 (match_operand:SI 2 "s_register_operand" "+r"))) 8590 (match_operand:QI 3 "s_register_operand" "r")) 8591 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)]) 8592 (match_dup 2)))] 8593 "TARGET_ARM 8594 && (REGNO (operands[3]) != REGNO (operands[2])) 8595 && (REGNO (operands[0]) != REGNO (operands[2]))" 8596 "str%?b\\t%3, [%2, %0%S4]!" 8597) 8598 8599; This pattern is never tried by combine, so do it as a peephole 8600 8601(define_peephole2 8602 [(set (match_operand:SI 0 "s_register_operand" "") 8603 (match_operand:SI 1 "s_register_operand" "")) 8604 (set (reg:CC CC_REGNUM) 8605 (compare:CC (match_dup 1) (const_int 0)))] 8606 "TARGET_ARM 8607 " 8608 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0))) 8609 (set (match_dup 0) (match_dup 1))])] 8610 "" 8611) 8612 8613; Peepholes to spot possible load- and store-multiples, if the ordering is 8614; reversed, check that the memory references aren't volatile. 8615 8616(define_peephole 8617 [(set (match_operand:SI 0 "s_register_operand" "=r") 8618 (match_operand:SI 4 "memory_operand" "m")) 8619 (set (match_operand:SI 1 "s_register_operand" "=r") 8620 (match_operand:SI 5 "memory_operand" "m")) 8621 (set (match_operand:SI 2 "s_register_operand" "=r") 8622 (match_operand:SI 6 "memory_operand" "m")) 8623 (set (match_operand:SI 3 "s_register_operand" "=r") 8624 (match_operand:SI 7 "memory_operand" "m"))] 8625 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)" 8626 "* 8627 return emit_ldm_seq (operands, 4); 8628 " 8629) 8630 8631(define_peephole 8632 [(set (match_operand:SI 0 "s_register_operand" "=r") 8633 (match_operand:SI 3 "memory_operand" "m")) 8634 (set (match_operand:SI 1 "s_register_operand" "=r") 8635 (match_operand:SI 4 "memory_operand" "m")) 8636 (set (match_operand:SI 2 "s_register_operand" "=r") 8637 (match_operand:SI 5 "memory_operand" "m"))] 8638 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)" 8639 "* 8640 return emit_ldm_seq (operands, 3); 8641 " 8642) 8643 8644(define_peephole 8645 [(set (match_operand:SI 0 "s_register_operand" "=r") 8646 (match_operand:SI 2 "memory_operand" "m")) 8647 (set (match_operand:SI 1 "s_register_operand" "=r") 8648 (match_operand:SI 3 "memory_operand" "m"))] 8649 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)" 8650 "* 8651 return emit_ldm_seq (operands, 2); 8652 " 8653) 8654 8655(define_peephole 8656 [(set (match_operand:SI 4 "memory_operand" "=m") 8657 (match_operand:SI 0 "s_register_operand" "r")) 8658 (set (match_operand:SI 5 "memory_operand" "=m") 8659 (match_operand:SI 1 "s_register_operand" "r")) 8660 (set (match_operand:SI 6 "memory_operand" "=m") 8661 (match_operand:SI 2 "s_register_operand" "r")) 8662 (set (match_operand:SI 7 "memory_operand" "=m") 8663 (match_operand:SI 3 "s_register_operand" "r"))] 8664 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)" 8665 "* 8666 return emit_stm_seq (operands, 4); 8667 " 8668) 8669 8670(define_peephole 8671 [(set (match_operand:SI 3 "memory_operand" "=m") 8672 (match_operand:SI 0 "s_register_operand" "r")) 8673 (set (match_operand:SI 4 "memory_operand" "=m") 8674 (match_operand:SI 1 "s_register_operand" "r")) 8675 (set (match_operand:SI 5 "memory_operand" "=m") 8676 (match_operand:SI 2 "s_register_operand" "r"))] 8677 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)" 8678 "* 8679 return emit_stm_seq (operands, 3); 8680 " 8681) 8682 8683(define_peephole 8684 [(set (match_operand:SI 2 "memory_operand" "=m") 8685 (match_operand:SI 0 "s_register_operand" "r")) 8686 (set (match_operand:SI 3 "memory_operand" "=m") 8687 (match_operand:SI 1 "s_register_operand" "r"))] 8688 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)" 8689 "* 8690 return emit_stm_seq (operands, 2); 8691 " 8692) 8693 8694(define_split 8695 [(set (match_operand:SI 0 "s_register_operand" "") 8696 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "") 8697 (const_int 0)) 8698 (neg:SI (match_operator:SI 2 "arm_comparison_operator" 8699 [(match_operand:SI 3 "s_register_operand" "") 8700 (match_operand:SI 4 "arm_rhs_operand" "")])))) 8701 (clobber (match_operand:SI 5 "s_register_operand" ""))] 8702 "TARGET_ARM" 8703 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31)))) 8704 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 8705 (match_dup 5)))] 8706 "" 8707) 8708 8709;; This split can be used because CC_Z mode implies that the following 8710;; branch will be an equality, or an unsigned inequality, so the sign 8711;; extension is not needed. 8712 8713(define_split 8714 [(set (reg:CC_Z CC_REGNUM) 8715 (compare:CC_Z 8716 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0) 8717 (const_int 24)) 8718 (match_operand 1 "const_int_operand" ""))) 8719 (clobber (match_scratch:SI 2 ""))] 8720 "TARGET_ARM 8721 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) 8722 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)" 8723 [(set (match_dup 2) (zero_extend:SI (match_dup 0))) 8724 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))] 8725 " 8726 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24); 8727 " 8728) 8729 8730(define_expand "prologue" 8731 [(clobber (const_int 0))] 8732 "TARGET_EITHER" 8733 "if (TARGET_ARM) 8734 arm_expand_prologue (); 8735 else 8736 thumb_expand_prologue (); 8737 DONE; 8738 " 8739) 8740 8741(define_expand "epilogue" 8742 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)] 8743 "TARGET_EITHER" 8744 " 8745 if (TARGET_THUMB) 8746 thumb_expand_epilogue (); 8747 else if (USE_RETURN_INSN (FALSE)) 8748 { 8749 emit_jump_insn (gen_return ()); 8750 DONE; 8751 } 8752 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode, 8753 gen_rtvec (1, 8754 gen_rtx_RETURN (VOIDmode)), 8755 VUNSPEC_EPILOGUE)); 8756 DONE; 8757 " 8758) 8759 8760(define_insn "sibcall_epilogue" 8761 [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)] 8762 "TARGET_ARM" 8763 "* 8764 output_asm_insn (\"%@ Sibcall epilogue\", operands); 8765 if (USE_RETURN_INSN (FALSE)) 8766 return output_return_instruction (NULL, FALSE, FALSE); 8767 return arm_output_epilogue (FALSE); 8768 " 8769;; Length is absolute worst case 8770 [(set_attr "length" "44") 8771 (set_attr "type" "block")] 8772) 8773 8774(define_insn "*epilogue_insns" 8775 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)] 8776 "TARGET_EITHER" 8777 "* 8778 if (TARGET_ARM) 8779 return arm_output_epilogue (TRUE); 8780 else /* TARGET_THUMB */ 8781 return thumb_unexpanded_epilogue (); 8782 " 8783 ; Length is absolute worst case 8784 [(set_attr "length" "44") 8785 (set_attr "type" "block")] 8786) 8787 8788(define_expand "eh_epilogue" 8789 [(use (match_operand:SI 0 "register_operand" "r")) 8790 (use (match_operand:SI 1 "register_operand" "r")) 8791 (use (match_operand:SI 2 "register_operand" "r"))] 8792 "TARGET_EITHER" 8793 " 8794 { 8795 cfun->machine->eh_epilogue_sp_ofs = operands[1]; 8796 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2) 8797 { 8798 rtx ra = gen_rtx_REG (Pmode, 2); 8799 8800 emit_move_insn (ra, operands[2]); 8801 operands[2] = ra; 8802 } 8803 /* This is a hack -- we may have crystalized the function type too 8804 early. */ 8805 cfun->machine->func_type = 0; 8806 }" 8807) 8808 8809;; This split is only used during output to reduce the number of patterns 8810;; that need assembler instructions adding to them. We allowed the setting 8811;; of the conditions to be implicit during rtl generation so that 8812;; the conditional compare patterns would work. However this conflicts to 8813;; some extent with the conditional data operations, so we have to split them 8814;; up again here. 8815 8816(define_split 8817 [(set (match_operand:SI 0 "s_register_operand" "") 8818 (if_then_else:SI (match_operator 1 "arm_comparison_operator" 8819 [(match_operand 2 "" "") (match_operand 3 "" "")]) 8820 (match_dup 0) 8821 (match_operand 4 "" ""))) 8822 (clobber (reg:CC CC_REGNUM))] 8823 "TARGET_ARM && reload_completed" 8824 [(set (match_dup 5) (match_dup 6)) 8825 (cond_exec (match_dup 7) 8826 (set (match_dup 0) (match_dup 4)))] 8827 " 8828 { 8829 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 8830 operands[2], operands[3]); 8831 enum rtx_code rc = GET_CODE (operands[1]); 8832 8833 operands[5] = gen_rtx_REG (mode, CC_REGNUM); 8834 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]); 8835 if (mode == CCFPmode || mode == CCFPEmode) 8836 rc = reverse_condition_maybe_unordered (rc); 8837 else 8838 rc = reverse_condition (rc); 8839 8840 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx); 8841 }" 8842) 8843 8844(define_split 8845 [(set (match_operand:SI 0 "s_register_operand" "") 8846 (if_then_else:SI (match_operator 1 "arm_comparison_operator" 8847 [(match_operand 2 "" "") (match_operand 3 "" "")]) 8848 (match_operand 4 "" "") 8849 (match_dup 0))) 8850 (clobber (reg:CC CC_REGNUM))] 8851 "TARGET_ARM && reload_completed" 8852 [(set (match_dup 5) (match_dup 6)) 8853 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)]) 8854 (set (match_dup 0) (match_dup 4)))] 8855 " 8856 { 8857 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 8858 operands[2], operands[3]); 8859 8860 operands[5] = gen_rtx_REG (mode, CC_REGNUM); 8861 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]); 8862 }" 8863) 8864 8865(define_split 8866 [(set (match_operand:SI 0 "s_register_operand" "") 8867 (if_then_else:SI (match_operator 1 "arm_comparison_operator" 8868 [(match_operand 2 "" "") (match_operand 3 "" "")]) 8869 (match_operand 4 "" "") 8870 (match_operand 5 "" ""))) 8871 (clobber (reg:CC CC_REGNUM))] 8872 "TARGET_ARM && reload_completed" 8873 [(set (match_dup 6) (match_dup 7)) 8874 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)]) 8875 (set (match_dup 0) (match_dup 4))) 8876 (cond_exec (match_dup 8) 8877 (set (match_dup 0) (match_dup 5)))] 8878 " 8879 { 8880 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 8881 operands[2], operands[3]); 8882 enum rtx_code rc = GET_CODE (operands[1]); 8883 8884 operands[6] = gen_rtx_REG (mode, CC_REGNUM); 8885 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]); 8886 if (mode == CCFPmode || mode == CCFPEmode) 8887 rc = reverse_condition_maybe_unordered (rc); 8888 else 8889 rc = reverse_condition (rc); 8890 8891 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx); 8892 }" 8893) 8894 8895(define_split 8896 [(set (match_operand:SI 0 "s_register_operand" "") 8897 (if_then_else:SI (match_operator 1 "arm_comparison_operator" 8898 [(match_operand:SI 2 "s_register_operand" "") 8899 (match_operand:SI 3 "arm_add_operand" "")]) 8900 (match_operand:SI 4 "arm_rhs_operand" "") 8901 (not:SI 8902 (match_operand:SI 5 "s_register_operand" "")))) 8903 (clobber (reg:CC CC_REGNUM))] 8904 "TARGET_ARM && reload_completed" 8905 [(set (match_dup 6) (match_dup 7)) 8906 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)]) 8907 (set (match_dup 0) (match_dup 4))) 8908 (cond_exec (match_dup 8) 8909 (set (match_dup 0) (not:SI (match_dup 5))))] 8910 " 8911 { 8912 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 8913 operands[2], operands[3]); 8914 enum rtx_code rc = GET_CODE (operands[1]); 8915 8916 operands[6] = gen_rtx_REG (mode, CC_REGNUM); 8917 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]); 8918 if (mode == CCFPmode || mode == CCFPEmode) 8919 rc = reverse_condition_maybe_unordered (rc); 8920 else 8921 rc = reverse_condition (rc); 8922 8923 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx); 8924 }" 8925) 8926 8927(define_insn "*cond_move_not" 8928 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 8929 (if_then_else:SI (match_operator 4 "arm_comparison_operator" 8930 [(match_operand 3 "cc_register" "") (const_int 0)]) 8931 (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 8932 (not:SI 8933 (match_operand:SI 2 "s_register_operand" "r,r"))))] 8934 "TARGET_ARM" 8935 "@ 8936 mvn%D4\\t%0, %2 8937 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2" 8938 [(set_attr "conds" "use") 8939 (set_attr "length" "4,8")] 8940) 8941 8942;; The next two patterns occur when an AND operation is followed by a 8943;; scc insn sequence 8944 8945(define_insn "*sign_extract_onebit" 8946 [(set (match_operand:SI 0 "s_register_operand" "=r") 8947 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r") 8948 (const_int 1) 8949 (match_operand:SI 2 "const_int_operand" "n")))] 8950 "TARGET_ARM" 8951 "* 8952 operands[2] = GEN_INT (1 << INTVAL (operands[2])); 8953 output_asm_insn (\"ands\\t%0, %1, %2\", operands); 8954 return \"mvnne\\t%0, #0\"; 8955 " 8956 [(set_attr "conds" "clob") 8957 (set_attr "length" "8")] 8958) 8959 8960(define_insn "*not_signextract_onebit" 8961 [(set (match_operand:SI 0 "s_register_operand" "=r") 8962 (not:SI 8963 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r") 8964 (const_int 1) 8965 (match_operand:SI 2 "const_int_operand" "n"))))] 8966 "TARGET_ARM" 8967 "* 8968 operands[2] = GEN_INT (1 << INTVAL (operands[2])); 8969 output_asm_insn (\"tst\\t%1, %2\", operands); 8970 output_asm_insn (\"mvneq\\t%0, #0\", operands); 8971 return \"movne\\t%0, #0\"; 8972 " 8973 [(set_attr "conds" "clob") 8974 (set_attr "length" "12")] 8975) 8976 8977;; Push multiple registers to the stack. Registers are in parallel (use ...) 8978;; expressions. For simplicity, the first register is also in the unspec 8979;; part. 8980(define_insn "*push_multi" 8981 [(match_parallel 2 "multi_register_push" 8982 [(set (match_operand:BLK 0 "memory_operand" "=m") 8983 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 8984 UNSPEC_PUSH_MULT))])] 8985 "TARGET_ARM" 8986 "* 8987 { 8988 int num_saves = XVECLEN (operands[2], 0); 8989 8990 /* For the StrongARM at least it is faster to 8991 use STR to store only a single register. */ 8992 if (num_saves == 1) 8993 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands); 8994 else 8995 { 8996 int i; 8997 char pattern[100]; 8998 8999 strcpy (pattern, \"stmfd\\t%m0!, {%1\"); 9000 9001 for (i = 1; i < num_saves; i++) 9002 { 9003 strcat (pattern, \", %|\"); 9004 strcat (pattern, 9005 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]); 9006 } 9007 9008 strcat (pattern, \"}\"); 9009 output_asm_insn (pattern, operands); 9010 } 9011 9012 return \"\"; 9013 }" 9014 [(set_attr "type" "store4")] 9015) 9016 9017;; Similarly for the floating point registers 9018(define_insn "*push_fp_multi" 9019 [(match_parallel 2 "multi_register_push" 9020 [(set (match_operand:BLK 0 "memory_operand" "=m") 9021 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")] 9022 UNSPEC_PUSH_MULT))])] 9023 "TARGET_ARM" 9024 "* 9025 { 9026 char pattern[100]; 9027 9028 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0)); 9029 output_asm_insn (pattern, operands); 9030 return \"\"; 9031 }" 9032 [(set_attr "type" "f_store")] 9033) 9034 9035;; Special patterns for dealing with the constant pool 9036 9037(define_insn "align_4" 9038 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)] 9039 "TARGET_EITHER" 9040 "* 9041 assemble_align (32); 9042 return \"\"; 9043 " 9044) 9045 9046(define_insn "consttable_end" 9047 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)] 9048 "TARGET_EITHER" 9049 "* 9050 making_const_table = FALSE; 9051 return \"\"; 9052 " 9053) 9054 9055(define_insn "consttable_1" 9056 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)] 9057 "TARGET_THUMB" 9058 "* 9059 making_const_table = TRUE; 9060 assemble_integer (operands[0], 1, BITS_PER_WORD, 1); 9061 assemble_zeros (3); 9062 return \"\"; 9063 " 9064 [(set_attr "length" "4")] 9065) 9066 9067(define_insn "consttable_2" 9068 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)] 9069 "TARGET_THUMB" 9070 "* 9071 making_const_table = TRUE; 9072 assemble_integer (operands[0], 2, BITS_PER_WORD, 1); 9073 assemble_zeros (2); 9074 return \"\"; 9075 " 9076 [(set_attr "length" "4")] 9077) 9078 9079(define_insn "consttable_4" 9080 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)] 9081 "TARGET_EITHER" 9082 "* 9083 { 9084 making_const_table = TRUE; 9085 switch (GET_MODE_CLASS (GET_MODE (operands[0]))) 9086 { 9087 case MODE_FLOAT: 9088 { 9089 union real_extract u; 9090 memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u); 9091 assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD); 9092 break; 9093 } 9094 default: 9095 assemble_integer (operands[0], 4, BITS_PER_WORD, 1); 9096 break; 9097 } 9098 return \"\"; 9099 }" 9100 [(set_attr "length" "4")] 9101) 9102 9103(define_insn "consttable_8" 9104 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)] 9105 "TARGET_EITHER" 9106 "* 9107 { 9108 making_const_table = TRUE; 9109 switch (GET_MODE_CLASS (GET_MODE (operands[0]))) 9110 { 9111 case MODE_FLOAT: 9112 { 9113 union real_extract u; 9114 memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u); 9115 assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD); 9116 break; 9117 } 9118 default: 9119 assemble_integer (operands[0], 8, BITS_PER_WORD, 1); 9120 break; 9121 } 9122 return \"\"; 9123 }" 9124 [(set_attr "length" "8")] 9125) 9126 9127;; Miscellaneous Thumb patterns 9128 9129(define_expand "tablejump" 9130 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "l*r")) 9131 (use (label_ref (match_operand 1 "" "")))])] 9132 "TARGET_THUMB" 9133 " 9134 if (flag_pic) 9135 { 9136 /* Hopefully, CSE will eliminate this copy. */ 9137 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1])); 9138 rtx reg2 = gen_reg_rtx (SImode); 9139 9140 emit_insn (gen_addsi3 (reg2, operands[0], reg1)); 9141 operands[0] = reg2; 9142 } 9143 " 9144) 9145 9146(define_insn "*thumb_tablejump" 9147 [(set (pc) (match_operand:SI 0 "register_operand" "l*r")) 9148 (use (label_ref (match_operand 1 "" "")))] 9149 "TARGET_THUMB" 9150 "mov\\t%|pc, %0" 9151 [(set_attr "length" "2")] 9152) 9153 9154;; V5 Instructions, 9155 9156(define_insn "clz" 9157 [(set (match_operand:SI 0 "s_register_operand" "=r") 9158 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] 9159 UNSPEC_CLZ))] 9160 "TARGET_ARM && arm_arch5" 9161 "clz\\t%0, %1") 9162 9163(define_expand "ffssi2" 9164 [(set (match_operand:SI 0 "s_register_operand" "") 9165 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))] 9166 "TARGET_ARM && arm_arch5" 9167 " 9168 { 9169 rtx t1, t2, t3; 9170 9171 t1 = gen_reg_rtx (SImode); 9172 t2 = gen_reg_rtx (SImode); 9173 t3 = gen_reg_rtx (SImode); 9174 9175 emit_insn (gen_negsi2 (t1, operands[1])); 9176 emit_insn (gen_andsi3 (t2, operands[1], t1)); 9177 emit_insn (gen_clz (t3, t2)); 9178 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3)); 9179 DONE; 9180 }" 9181) 9182 9183;; V5E instructions. 9184 9185(define_insn "prefetch" 9186 [(prefetch (match_operand:SI 0 "address_operand" "p") 9187 (match_operand:SI 1 "" "") 9188 (match_operand:SI 2 "" ""))] 9189 "TARGET_ARM && arm_arch5e" 9190 "pld\\t%a0") 9191 9192;; General predication pattern 9193 9194(define_cond_exec 9195 [(match_operator 0 "arm_comparison_operator" 9196 [(match_operand 1 "cc_register" "") 9197 (const_int 0)])] 9198 "TARGET_ARM" 9199 "" 9200) 9201 9202(define_insn "prologue_use" 9203 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)] 9204 "" 9205 "%@ %0 needed for prologue" 9206) 9207