1;;- Machine description for ARM for GNU compiler 2;; Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 3;; 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;; UNSPEC Usage: 32;; 0 `sin' operation: operand 0 is the result, operand 1 the parameter, 33;; the mode is MODE_FLOAT 34;; 1 `cos' operation: operand 0 is the result, operand 1 the parameter, 35;; the mode is MODE_FLOAT 36;; 2 `push multiple' operation: operand 0 is the first register. Subsequent 37;; registers are in parallel (use...) expressions. 38;; 3 A symbol that has been treated properly for pic usage, that is, we 39;; will add the pic_register value to it before trying to dereference it. 40;; Note: sin and cos are no-longer used. 41 42;; Attributes 43 44; PROG_MODE attribute is used to determine whether condition codes are 45; clobbered by a call insn: they are if in prog32 mode. This is controlled 46; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option. 47(define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode"))) 48 49(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong"))) 50 51; Floating Point Unit. If we only have floating point emulation, then there 52; is no point in scheduling the floating point insns. (Well, for best 53; performance we should try and group them together). 54 55(define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr"))) 56 57; LENGTH of an instruction (in bytes) 58(define_attr "length" "" (const_int 4)) 59 60; An assembler sequence may clobber the condition codes without us knowing 61(define_asm_attributes 62 [(set_attr "conds" "clob") 63 (set_attr "length" "4")]) 64 65; TYPE attribute is used to detect floating point instructions which, if 66; running on a co-processor can run in parallel with other, basic instructions 67; If write-buffer scheduling is enabled then it can also be used in the 68; scheduling of writes. 69 70; Classification of each insn 71; normal any data instruction that doesn't hit memory or fp regs 72; mult a multiply instruction 73; block blockage insn, this blocks all functional units 74; float a floating point arithmetic operation (subject to expansion) 75; fdivx XFmode floating point division 76; fdivd DFmode floating point division 77; fdivs SFmode floating point division 78; fmul Floating point multiply 79; ffmul Fast floating point multiply 80; farith Floating point arithmetic (4 cycle) 81; ffarith Fast floating point arithmetic (2 cycle) 82; float_em a floating point arithmetic operation that is normally emulated 83; even on a machine with an fpa. 84; f_load a floating point load from memory 85; f_store a floating point store to memory 86; f_mem_r a transfer of a floating point register to a real reg via mem 87; r_mem_f the reverse of f_mem_r 88; f_2_r fast transfer float to arm (no memory needed) 89; r_2_f fast transfer arm to float 90; call a subroutine call 91; load any load from memory 92; store1 store 1 word to memory from arm registers 93; store2 store 2 words 94; store3 store 3 words 95; store4 store 4 words 96; 97(define_attr "type" 98 "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" 99 (const_string "normal")) 100 101; Load scheduling, set from the arm_ld_sched variable 102; initialised by arm_override_options() 103(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched"))) 104 105; condition codes: this one is used by final_prescan_insn to speed up 106; conditionalizing instructions. It saves having to scan the rtl to see if 107; it uses or alters the condition codes. 108 109; USE means that the condition codes are used by the insn in the process of 110; outputting code, this means (at present) that we can't use the insn in 111; inlined branches 112 113; SET means that the purpose of the insn is to set the condition codes in a 114; well defined manner. 115 116; CLOB means that the condition codes are altered in an undefined manner, if 117; they are altered at all 118 119; JUMP_CLOB is used when the conditions are not defined if a branch is taken, 120; but are if the branch wasn't taken; the effect is to limit the branch 121; elimination scanning. 122 123; NOCOND means that the condition codes are neither altered nor affect the 124; output of this insn 125 126(define_attr "conds" "use,set,clob,jump_clob,nocond" 127 (if_then_else (eq_attr "type" "call") 128 (if_then_else (eq_attr "prog_mode" "prog32") 129 (const_string "clob") (const_string "nocond")) 130 (const_string "nocond"))) 131 132; Only model the write buffer for ARM6 and ARM7. Earlier processors don't 133; have one. Later ones, such as StrongARM, have write-back caches, so don't 134; suffer blockages enough to warrent modelling this (and it can adversely 135; affect the schedule). 136(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7"))) 137 138(define_attr "write_conflict" "no,yes" 139 (if_then_else (eq_attr "type" 140 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load") 141 (const_string "yes") 142 (const_string "no"))) 143 144(define_attr "core_cycles" "single,multi" 145 (if_then_else (eq_attr "type" 146 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith") 147 (const_string "single") 148 (const_string "multi"))) 149 150; The write buffer on some of the arm6 processors is hard to model exactly. 151; There is room in the buffer for up to two addresses and up to eight words 152; of memory, but the two needn't be split evenly. When writing the two 153; addresses are fully pipelined. However, a read from memory that is not 154; currently in the cache will block until the writes have completed. 155; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so 156; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous 157; (they aren't allowed to be at present) then there is a startup cost of 1MCLK 158; cycle to add as well. 159 160;; (define_function_unit {name} {num-units} {n-users} {test} 161;; {ready-delay} {issue-delay} [{conflict-list}]) 162(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") 163 (eq_attr "type" "fdivx")) 71 69) 164 165(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") 166 (eq_attr "type" "fdivd")) 59 57) 167 168(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") 169 (eq_attr "type" "fdivs")) 31 29) 170 171(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") 172 (eq_attr "type" "fmul")) 9 7) 173 174(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") 175 (eq_attr "type" "ffmul")) 6 4) 176 177(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") 178 (eq_attr "type" "farith")) 4 2) 179 180(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") 181 (eq_attr "type" "ffarith")) 2 2) 182 183(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") 184 (eq_attr "type" "r_2_f")) 5 3) 185 186(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa") 187 (eq_attr "type" "f_2_r")) 1 2) 188 189;; The fpa10 doesn't really have a memory read unit, but it can start to 190;; speculatively execute the instruction in the pipeline, provided the data 191;; is already loaded, so pretend reads have a delay of 2 (and that the 192;; pipeline is infinite. 193 194(define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa") 195 (eq_attr "type" "f_load")) 3 1) 196 197;;-------------------------------------------------------------------- 198;; Write buffer 199;;-------------------------------------------------------------------- 200;; Strictly we should model a 4-deep write buffer for ARM7xx based chips 201(define_function_unit "write_buf" 1 2 202 (and (eq_attr "model_wbuf" "yes") 203 (eq_attr "type" "store1,r_mem_f")) 5 3) 204(define_function_unit "write_buf" 1 2 205 (and (eq_attr "model_wbuf" "yes") 206 (eq_attr "type" "store2")) 7 4) 207(define_function_unit "write_buf" 1 2 208 (and (eq_attr "model_wbuf" "yes") 209 (eq_attr "type" "store3")) 9 5) 210(define_function_unit "write_buf" 1 2 211 (and (eq_attr "model_wbuf" "yes") 212 (eq_attr "type" "store4")) 11 6) 213 214;;-------------------------------------------------------------------- 215;; Write blockage unit 216;;-------------------------------------------------------------------- 217;; The write_blockage unit models (partially), the fact that reads will stall 218;; until the write buffer empties. 219;; The f_mem_r and r_mem_f could also block, but they are to the stack, 220;; so we don't model them here 221(define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes") 222 (eq_attr "type" "store1")) 5 5 223 [(eq_attr "write_conflict" "yes")]) 224(define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes") 225 (eq_attr "type" "store2")) 7 7 226 [(eq_attr "write_conflict" "yes")]) 227(define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes") 228 (eq_attr "type" "store3")) 9 9 229 [(eq_attr "write_conflict" "yes")]) 230(define_function_unit "write_blockage" 1 0 231 (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11 232 [(eq_attr "write_conflict" "yes")]) 233(define_function_unit "write_blockage" 1 0 234 (and (eq_attr "model_wbuf" "yes") 235 (eq_attr "write_conflict" "yes")) 1 1) 236 237;;-------------------------------------------------------------------- 238;; Core unit 239;;-------------------------------------------------------------------- 240;; Everything must spend at least one cycle in the core unit 241(define_function_unit "core" 1 0 242 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1) 243 244(define_function_unit "core" 1 0 245 (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1) 246 247(define_function_unit "core" 1 0 248 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2) 249 250(define_function_unit "core" 1 0 251 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3) 252 253(define_function_unit "core" 1 0 254 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4) 255 256(define_function_unit "core" 1 0 257 (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6) 258 259(define_function_unit "core" 1 0 260 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7) 261 262(define_function_unit "core" 1 0 263 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16) 264 265(define_function_unit "core" 1 0 266 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no")) 267 (eq_attr "type" "mult")) 4 4) 268 269(define_function_unit "core" 1 0 270 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes")) 271 (eq_attr "type" "mult")) 3 2) 272 273(define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3) 274 275(define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4) 276 277(define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5) 278 279;; Note: For DImode insns, there is normally no reason why operands should 280;; not be in the same register, what we don't want is for something being 281;; written to partially overlap something that is an input. 282 283;; Addition insns. 284 285(define_insn "adddi3" 286 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 287 (plus:DI (match_operand:DI 1 "s_register_operand" "%0,0") 288 (match_operand:DI 2 "s_register_operand" "r,0"))) 289 (clobber (reg:CC 24))] 290 "" 291 "adds\\t%Q0, %Q1, %Q2\;adc\\t%R0, %R1, %R2" 292[(set_attr "conds" "clob") 293 (set_attr "length" "8")]) 294 295(define_insn "*adddi_sesidi_di" 296 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 297 (plus:DI (sign_extend:DI 298 (match_operand:SI 2 "s_register_operand" "r,r")) 299 (match_operand:DI 1 "s_register_operand" "r,0"))) 300 (clobber (reg:CC 24))] 301 "" 302 "adds\\t%Q0, %Q1, %2\;adc\\t%R0, %R1, %2, asr #31" 303[(set_attr "conds" "clob") 304 (set_attr "length" "8")]) 305 306(define_insn "*adddi_zesidi_di" 307 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 308 (plus:DI (zero_extend:DI 309 (match_operand:SI 2 "s_register_operand" "r,r")) 310 (match_operand:DI 1 "s_register_operand" "r,0"))) 311 (clobber (reg:CC 24))] 312 "" 313 "adds\\t%Q0, %Q1, %2\;adc\\t%R0, %R1, #0" 314[(set_attr "conds" "clob") 315 (set_attr "length" "8")]) 316 317(define_expand "addsi3" 318 [(set (match_operand:SI 0 "s_register_operand" "") 319 (plus:SI (match_operand:SI 1 "s_register_operand" "") 320 (match_operand:SI 2 "reg_or_int_operand" "")))] 321 "" 322 " 323 if (GET_CODE (operands[2]) == CONST_INT) 324 { 325 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0], 326 operands[1], 327 (reload_in_progress || reload_completed ? 0 328 : preserve_subexpressions_p ())); 329 DONE; 330 } 331") 332 333(define_split 334 [(set (match_operand:SI 0 "s_register_operand" "") 335 (plus:SI (match_operand:SI 1 "s_register_operand" "") 336 (match_operand:SI 2 "const_int_operand" "")))] 337 "! (const_ok_for_arm (INTVAL (operands[2])) 338 || const_ok_for_arm (-INTVAL (operands[2])))" 339 [(clobber (const_int 0))] 340 " 341 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0], 342 operands[1], 0); 343 DONE; 344") 345 346(define_insn "*addsi3_insn" 347 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 348 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r") 349 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))] 350 "" 351 "@ 352 add%?\\t%0, %1, %2 353 sub%?\\t%0, %1, #%n2 354 #" 355[(set_attr "length" "4,4,16")]) 356 357(define_insn "*addsi3_compare0" 358 [(set (reg:CC_NOOV 24) 359 (compare:CC_NOOV 360 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r") 361 (match_operand:SI 2 "arm_add_operand" "rI,L")) 362 (const_int 0))) 363 (set (match_operand:SI 0 "s_register_operand" "=r,r") 364 (plus:SI (match_dup 1) (match_dup 2)))] 365 "" 366 "@ 367 add%?s\\t%0, %1, %2 368 sub%?s\\t%0, %1, #%n2" 369[(set_attr "conds" "set")]) 370 371(define_insn "*addsi3_compare0_scratch" 372 [(set (reg:CC_NOOV 24) 373 (compare:CC_NOOV 374 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r") 375 (match_operand:SI 1 "arm_add_operand" "rI,L")) 376 (const_int 0)))] 377 "" 378 "@ 379 cmn%?\\t%0, %1 380 cmp%?\\t%0, #%n1" 381[(set_attr "conds" "set")]) 382 383;; The next four insns work because they compare the result with one of 384;; the operands, and we know that the use of the condition code is 385;; either GEU or LTU, so we can use the carry flag from the addition 386;; instead of doing the compare a second time. 387(define_insn "*addsi3_compare_op1" 388 [(set (reg:CC_C 24) 389 (compare:CC_C 390 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r") 391 (match_operand:SI 2 "arm_add_operand" "rI,L")) 392 (match_dup 1))) 393 (set (match_operand:SI 0 "s_register_operand" "=r,r") 394 (plus:SI (match_dup 1) (match_dup 2)))] 395 "" 396 "@ 397 add%?s\\t%0, %1, %2 398 sub%?s\\t%0, %1, #%n2" 399[(set_attr "conds" "set")]) 400 401(define_insn "*addsi3_compare_op2" 402 [(set (reg:CC_C 24) 403 (compare:CC_C 404 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r") 405 (match_operand:SI 2 "arm_add_operand" "rI,L")) 406 (match_dup 2))) 407 (set (match_operand:SI 0 "s_register_operand" "=r,r") 408 (plus:SI (match_dup 1) (match_dup 2)))] 409 "" 410 "@ 411 add%?s\\t%0, %1, %2 412 sub%?s\\t%0, %1, #%n2" 413[(set_attr "conds" "set")]) 414 415(define_insn "*compare_addsi2_op0" 416 [(set (reg:CC_C 24) 417 (compare:CC_C 418 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r") 419 (match_operand:SI 1 "arm_add_operand" "rI,L")) 420 (match_dup 0)))] 421 "" 422 "@ 423 cmn%?\\t%0, %1 424 cmp%?\\t%0, #%n1" 425[(set_attr "conds" "set")]) 426 427(define_insn "*compare_addsi2_op1" 428 [(set (reg:CC_C 24) 429 (compare:CC_C 430 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r") 431 (match_operand:SI 1 "arm_add_operand" "rI,L")) 432 (match_dup 1)))] 433 "" 434 "@ 435 cmn%?\\t%0, %1 436 cmp%?\\t%0, #%n1" 437[(set_attr "conds" "set")]) 438 439(define_insn "*addsi3_carryin" 440 [(set (match_operand:SI 0 "s_register_operand" "=r") 441 (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0)) 442 (plus:SI (match_operand:SI 1 "s_register_operand" "r") 443 (match_operand:SI 2 "arm_rhs_operand" "rI"))))] 444 "" 445 "adc%?\\t%0, %1, %2" 446[(set_attr "conds" "use")]) 447 448(define_insn "*addsi3_carryin_alt1" 449 [(set (match_operand:SI 0 "s_register_operand" "=r") 450 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r") 451 (match_operand:SI 2 "arm_rhs_operand" "rI")) 452 (ltu:SI (reg:CC_C 24) (const_int 0))))] 453 "" 454 "adc%?\\t%0, %1, %2" 455[(set_attr "conds" "use")]) 456 457(define_insn "*addsi3_carryin_alt2" 458 [(set (match_operand:SI 0 "s_register_operand" "=r") 459 (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0)) 460 (match_operand:SI 1 "s_register_operand" "r")) 461 (match_operand:SI 2 "arm_rhs_operand" "rI")))] 462 "" 463 "adc%?\\t%0, %1, %2" 464[(set_attr "conds" "use")]) 465 466(define_insn "*addsi3_carryin_alt3" 467 [(set (match_operand:SI 0 "s_register_operand" "=r") 468 (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0)) 469 (match_operand:SI 2 "arm_rhs_operand" "rI")) 470 (match_operand:SI 1 "s_register_operand" "r")))] 471 "" 472 "adc%?\\t%0, %1, %2" 473[(set_attr "conds" "use")]) 474 475(define_insn "incscc" 476 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 477 (plus:SI (match_operator:SI 2 "comparison_operator" 478 [(match_operand 3 "cc_register" "") (const_int 0)]) 479 (match_operand:SI 1 "s_register_operand" "0,?r")))] 480 "" 481 "@ 482 add%d2\\t%0, %1, #1 483 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1" 484[(set_attr "conds" "use") 485 (set_attr "length" "4,8")]) 486 487; If a constant is too big to fit in a single instruction then the constant 488; will be pre-loaded into a register taking at least two insns, we might be 489; able to merge it with an add, but it depends on the exact value. 490 491(define_split 492 [(set (match_operand:SI 0 "s_register_operand" "=r") 493 (plus:SI (match_operand:SI 1 "s_register_operand" "r") 494 (match_operand:SI 2 "const_int_operand" "n")))] 495 "!(const_ok_for_arm (INTVAL (operands[2])) 496 || const_ok_for_arm (-INTVAL (operands[2])))" 497 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2))) 498 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))] 499 " 500{ 501 unsigned int val = (unsigned) INTVAL (operands[2]); 502 int i; 503 unsigned int temp; 504 505 /* this code is similar to the approach followed in movsi, but it must 506 generate exactly two insns */ 507 508 for (i = 30; i >= 0; i -= 2) 509 { 510 if (val & (3 << i)) 511 { 512 i -= 6; 513 if (i < 0) i = 0; 514 if (const_ok_for_arm (temp = (val & ~(255 << i)))) 515 { 516 val &= 255 << i; 517 break; 518 } 519 /* we might be able to do this as (larger number - small number) */ 520 temp = ((val >> i) & 255) + 1; 521 if (temp > 255 && i < 24) 522 { 523 i += 2; 524 temp = ((val >> i) & 255) + 1; 525 } 526 if (const_ok_for_arm ((temp << i) - val)) 527 { 528 i = temp << i; 529 temp = (unsigned) - (int) (i - val); 530 val = i; 531 break; 532 } 533 FAIL; 534 } 535 } 536 /* if we got here, we have found a way of doing it in two instructions. 537 the two constants are in val and temp */ 538 operands[2] = GEN_INT ((int)val); 539 operands[3] = GEN_INT ((int)temp); 540} 541") 542 543(define_insn "addsf3" 544 [(set (match_operand:SF 0 "s_register_operand" "=f,f") 545 (plus:SF (match_operand:SF 1 "s_register_operand" "f,f") 546 (match_operand:SF 2 "fpu_add_operand" "fG,H")))] 547 "TARGET_HARD_FLOAT" 548 "@ 549 adf%?s\\t%0, %1, %2 550 suf%?s\\t%0, %1, #%N2" 551[(set_attr "type" "farith")]) 552 553(define_insn "adddf3" 554 [(set (match_operand:DF 0 "s_register_operand" "=f,f") 555 (plus:DF (match_operand:DF 1 "s_register_operand" "f,f") 556 (match_operand:DF 2 "fpu_add_operand" "fG,H")))] 557 "TARGET_HARD_FLOAT" 558 "@ 559 adf%?d\\t%0, %1, %2 560 suf%?d\\t%0, %1, #%N2" 561[(set_attr "type" "farith")]) 562 563(define_insn "*adddf_df_esfdf" 564 [(set (match_operand:DF 0 "s_register_operand" "=f,f") 565 (plus:DF (float_extend:DF 566 (match_operand:SF 1 "s_register_operand" "f,f")) 567 (match_operand:DF 2 "fpu_add_operand" "fG,H")))] 568 "TARGET_HARD_FLOAT" 569 "@ 570 adf%?d\\t%0, %1, %2 571 suf%?d\\t%0, %1, #%N2" 572[(set_attr "type" "farith")]) 573 574(define_insn "*adddf_df_esfdf" 575 [(set (match_operand:DF 0 "s_register_operand" "=f") 576 (plus:DF (match_operand:DF 1 "s_register_operand" "f") 577 (float_extend:DF 578 (match_operand:SF 2 "s_register_operand" "f"))))] 579 "TARGET_HARD_FLOAT" 580 "adf%?d\\t%0, %1, %2" 581[(set_attr "type" "farith")]) 582 583(define_insn "*adddf_esfdf_esfdf" 584 [(set (match_operand:DF 0 "s_register_operand" "=f") 585 (plus:DF (float_extend:DF 586 (match_operand:SF 1 "s_register_operand" "f")) 587 (float_extend:DF 588 (match_operand:SF 2 "s_register_operand" "f"))))] 589 "TARGET_HARD_FLOAT" 590 "adf%?d\\t%0, %1, %2" 591[(set_attr "type" "farith")]) 592 593(define_insn "addxf3" 594 [(set (match_operand:XF 0 "s_register_operand" "=f,f") 595 (plus:XF (match_operand:XF 1 "s_register_operand" "f,f") 596 (match_operand:XF 2 "fpu_add_operand" "fG,H")))] 597 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 598 "@ 599 adf%?e\\t%0, %1, %2 600 suf%?e\\t%0, %1, #%N2" 601[(set_attr "type" "farith")]) 602 603(define_insn "subdi3" 604 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r") 605 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0") 606 (match_operand:DI 2 "s_register_operand" "r,0,0"))) 607 (clobber (reg:CC 24))] 608 "" 609 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2" 610[(set_attr "conds" "clob") 611 (set_attr "length" "8")]) 612 613(define_insn "*subdi_di_zesidi" 614 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 615 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0") 616 (zero_extend:DI 617 (match_operand:SI 2 "s_register_operand" "r,r")))) 618 (clobber (reg:CC 24))] 619 "" 620 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0" 621[(set_attr "conds" "clob") 622 (set_attr "length" "8")]) 623 624(define_insn "*subdi_di_sesidi" 625 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 626 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0") 627 (sign_extend:DI 628 (match_operand:SI 2 "s_register_operand" "r,r")))) 629 (clobber (reg:CC 24))] 630 "" 631 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31" 632[(set_attr "conds" "clob") 633 (set_attr "length" "8")]) 634 635(define_insn "*subdi_zesidi_di" 636 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 637 (minus:DI (zero_extend:DI 638 (match_operand:SI 2 "s_register_operand" "r,r")) 639 (match_operand:DI 1 "s_register_operand" "?r,0"))) 640 (clobber (reg:CC 24))] 641 "" 642 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0" 643[(set_attr "conds" "clob") 644 (set_attr "length" "8")]) 645 646(define_insn "*subdi_sesidi_di" 647 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 648 (minus:DI (sign_extend:DI 649 (match_operand:SI 2 "s_register_operand" "r,r")) 650 (match_operand:DI 1 "s_register_operand" "?r,0"))) 651 (clobber (reg:CC 24))] 652 "" 653 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31" 654[(set_attr "conds" "clob") 655 (set_attr "length" "8")]) 656 657(define_insn "*subdi_zesidi_zesidi" 658 [(set (match_operand:DI 0 "s_register_operand" "=r") 659 (minus:DI (zero_extend:DI 660 (match_operand:SI 1 "s_register_operand" "r")) 661 (zero_extend:DI 662 (match_operand:SI 2 "s_register_operand" "r")))) 663 (clobber (reg:CC 24))] 664 "" 665 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1" 666[(set_attr "conds" "clob") 667 (set_attr "length" "8")]) 668 669(define_expand "subsi3" 670 [(set (match_operand:SI 0 "s_register_operand" "") 671 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "") 672 (match_operand:SI 2 "s_register_operand" "")))] 673 "" 674 " 675 if (GET_CODE (operands[1]) == CONST_INT) 676 { 677 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0], 678 operands[2], 679 (reload_in_progress || reload_completed ? 0 680 : preserve_subexpressions_p ())); 681 DONE; 682 } 683") 684 685(define_insn "*subsi3_insn" 686 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 687 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n") 688 (match_operand:SI 2 "s_register_operand" "r,r")))] 689 "" 690 "@ 691 rsb%?\\t%0, %2, %1 692 #" 693[(set_attr "length" "4,16")]) 694 695(define_split 696 [(set (match_operand:SI 0 "s_register_operand" "") 697 (minus:SI (match_operand:SI 1 "const_int_operand" "") 698 (match_operand:SI 2 "s_register_operand" "")))] 699 "! const_ok_for_arm (INTVAL (operands[1]))" 700 [(clobber (const_int 0))] 701 " 702 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0], 703 operands[2], 0); 704 DONE; 705") 706 707(define_insn "*subsi3_compare0" 708 [(set (reg:CC_NOOV 24) 709 (compare:CC_NOOV (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I") 710 (match_operand:SI 2 "arm_rhs_operand" "rI,r")) 711 (const_int 0))) 712 (set (match_operand:SI 0 "s_register_operand" "=r,r") 713 (minus:SI (match_dup 1) (match_dup 2)))] 714 "" 715 "@ 716 sub%?s\\t%0, %1, %2 717 rsb%?s\\t%0, %2, %1" 718[(set_attr "conds" "set")]) 719 720(define_insn "decscc" 721 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 722 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r") 723 (match_operator:SI 2 "comparison_operator" 724 [(match_operand 3 "cc_register" "") (const_int 0)])))] 725 "" 726 "@ 727 sub%d2\\t%0, %1, #1 728 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1" 729[(set_attr "conds" "use") 730 (set_attr "length" "*,8")]) 731 732(define_insn "subsf3" 733 [(set (match_operand:SF 0 "s_register_operand" "=f,f") 734 (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G") 735 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))] 736 "TARGET_HARD_FLOAT" 737 "@ 738 suf%?s\\t%0, %1, %2 739 rsf%?s\\t%0, %2, %1" 740[(set_attr "type" "farith")]) 741 742(define_insn "subdf3" 743 [(set (match_operand:DF 0 "s_register_operand" "=f,f") 744 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G") 745 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))] 746 "TARGET_HARD_FLOAT" 747 "@ 748 suf%?d\\t%0, %1, %2 749 rsf%?d\\t%0, %2, %1" 750[(set_attr "type" "farith")]) 751 752(define_insn "*subdf_esfdf_df" 753 [(set (match_operand:DF 0 "s_register_operand" "=f") 754 (minus:DF (float_extend:DF 755 (match_operand:SF 1 "s_register_operand" "f")) 756 (match_operand:DF 2 "fpu_rhs_operand" "fG")))] 757 "TARGET_HARD_FLOAT" 758 "suf%?d\\t%0, %1, %2" 759[(set_attr "type" "farith")]) 760 761(define_insn "*subdf_df_esfdf" 762 [(set (match_operand:DF 0 "s_register_operand" "=f,f") 763 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G") 764 (float_extend:DF 765 (match_operand:SF 2 "s_register_operand" "f,f"))))] 766 "TARGET_HARD_FLOAT" 767 "@ 768 suf%?d\\t%0, %1, %2 769 rsf%?d\\t%0, %2, %1" 770[(set_attr "type" "farith")]) 771 772(define_insn "*subdf_esfdf_esfdf" 773 [(set (match_operand:DF 0 "s_register_operand" "=f") 774 (minus:DF (float_extend:DF 775 (match_operand:SF 1 "s_register_operand" "f")) 776 (float_extend:DF 777 (match_operand:SF 2 "s_register_operand" "f"))))] 778 "TARGET_HARD_FLOAT" 779 "suf%?d\\t%0, %1, %2" 780[(set_attr "type" "farith")]) 781 782(define_insn "subxf3" 783 [(set (match_operand:XF 0 "s_register_operand" "=f,f") 784 (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G") 785 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))] 786 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 787 "@ 788 suf%?e\\t%0, %1, %2 789 rsf%?e\\t%0, %2, %1" 790[(set_attr "type" "farith")]) 791 792;; Multiplication insns 793 794;; Use `&' and then `0' to prevent the operands 0 and 1 being the same 795(define_insn "mulsi3" 796 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r") 797 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r") 798 (match_operand:SI 1 "s_register_operand" "%?r,0")))] 799 "" 800 "mul%?\\t%0, %2, %1" 801[(set_attr "type" "mult")]) 802 803(define_insn "*mulsi3_compare0" 804 [(set (reg:CC_NOOV 24) 805 (compare:CC_NOOV (mult:SI 806 (match_operand:SI 2 "s_register_operand" "r,r") 807 (match_operand:SI 1 "s_register_operand" "%?r,0")) 808 (const_int 0))) 809 (set (match_operand:SI 0 "s_register_operand" "=&r,&r") 810 (mult:SI (match_dup 2) (match_dup 1)))] 811 "" 812 "mul%?s\\t%0, %2, %1" 813[(set_attr "conds" "set") 814 (set_attr "type" "mult")]) 815 816(define_insn "*mulsi_compare0_scratch" 817 [(set (reg:CC_NOOV 24) 818 (compare:CC_NOOV (mult:SI 819 (match_operand:SI 2 "s_register_operand" "r,r") 820 (match_operand:SI 1 "s_register_operand" "%?r,0")) 821 (const_int 0))) 822 (clobber (match_scratch:SI 0 "=&r,&r"))] 823 "" 824 "mul%?s\\t%0, %2, %1" 825[(set_attr "conds" "set") 826 (set_attr "type" "mult")]) 827 828;; Unnamed templates to match MLA instruction. 829 830(define_insn "*mulsi3addsi" 831 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r") 832 (plus:SI 833 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r") 834 (match_operand:SI 1 "s_register_operand" "%r,0,r,0")) 835 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))] 836 "" 837 "mla%?\\t%0, %2, %1, %3" 838[(set_attr "type" "mult")]) 839 840(define_insn "*mulsi3addsi_compare0" 841 [(set (reg:CC_NOOV 24) 842 (compare:CC_NOOV (plus:SI 843 (mult:SI 844 (match_operand:SI 2 "s_register_operand" "r,r,r,r") 845 (match_operand:SI 1 "s_register_operand" "%r,0,r,0")) 846 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")) 847 (const_int 0))) 848 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r") 849 (plus:SI (mult:SI (match_dup 2) (match_dup 1)) 850 (match_dup 3)))] 851 "" 852 "mla%?s\\t%0, %2, %1, %3" 853[(set_attr "conds" "set") 854 (set_attr "type" "mult")]) 855 856(define_insn "*mulsi3addsi_compare0_scratch" 857 [(set (reg:CC_NOOV 24) 858 (compare:CC_NOOV (plus:SI 859 (mult:SI 860 (match_operand:SI 2 "s_register_operand" "r,r,r,r") 861 (match_operand:SI 1 "s_register_operand" "%r,0,r,0")) 862 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")) 863 (const_int 0))) 864 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))] 865 "" 866 "mla%?s\\t%0, %2, %1, %3" 867[(set_attr "conds" "set") 868 (set_attr "type" "mult")]) 869 870(define_insn "mulsidi3" 871 [(set (match_operand:DI 0 "s_register_operand" "=&r") 872 (mult:DI (sign_extend:DI 873 (match_operand:SI 1 "s_register_operand" "%r")) 874 (sign_extend:DI 875 (match_operand:SI 2 "s_register_operand" "r"))))] 876 "arm_fast_multiply" 877 "smull%?\\t%Q0, %R0, %1, %2" 878[(set_attr "type" "mult")]) 879 880(define_insn "umulsidi3" 881 [(set (match_operand:DI 0 "s_register_operand" "=&r") 882 (mult:DI (zero_extend:DI 883 (match_operand:SI 1 "s_register_operand" "%r")) 884 (zero_extend:DI 885 (match_operand:SI 2 "s_register_operand" "r"))))] 886 "arm_fast_multiply" 887 "umull%?\\t%Q0, %R0, %1, %2" 888[(set_attr "type" "mult")]) 889 890(define_insn "smulsi3_highpart" 891 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r") 892 (truncate:SI 893 (lshiftrt:DI 894 (mult:DI (sign_extend:DI 895 (match_operand:SI 1 "s_register_operand" "%r,0")) 896 (sign_extend:DI 897 (match_operand:SI 2 "s_register_operand" "r,r"))) 898 (const_int 32)))) 899 (clobber (match_scratch:SI 3 "=&r,&r"))] 900 "arm_fast_multiply" 901 "smull%?\\t%3, %0, %2, %1" 902[(set_attr "type" "mult")]) 903 904(define_insn "umulsi3_highpart" 905 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r") 906 (truncate:SI 907 (lshiftrt:DI 908 (mult:DI (zero_extend:DI 909 (match_operand:SI 1 "s_register_operand" "%r,0")) 910 (zero_extend:DI 911 (match_operand:SI 2 "s_register_operand" "r,r"))) 912 (const_int 32)))) 913 (clobber (match_scratch:SI 3 "=&r,&r"))] 914 "arm_fast_multiply" 915 "umull%?\\t%3, %0, %2, %1" 916[(set_attr "type" "mult")]) 917 918(define_insn "mulsf3" 919 [(set (match_operand:SF 0 "s_register_operand" "=f") 920 (mult:SF (match_operand:SF 1 "s_register_operand" "f") 921 (match_operand:SF 2 "fpu_rhs_operand" "fG")))] 922 "TARGET_HARD_FLOAT" 923 "fml%?s\\t%0, %1, %2" 924[(set_attr "type" "ffmul")]) 925 926(define_insn "muldf3" 927 [(set (match_operand:DF 0 "s_register_operand" "=f") 928 (mult:DF (match_operand:DF 1 "s_register_operand" "f") 929 (match_operand:DF 2 "fpu_rhs_operand" "fG")))] 930 "TARGET_HARD_FLOAT" 931 "muf%?d\\t%0, %1, %2" 932[(set_attr "type" "fmul")]) 933 934(define_insn "*muldf_esfdf_df" 935 [(set (match_operand:DF 0 "s_register_operand" "=f") 936 (mult:DF (float_extend:DF 937 (match_operand:SF 1 "s_register_operand" "f")) 938 (match_operand:DF 2 "fpu_rhs_operand" "fG")))] 939 "TARGET_HARD_FLOAT" 940 "muf%?d\\t%0, %1, %2" 941[(set_attr "type" "fmul")]) 942 943(define_insn "*muldf_df_esfdf" 944 [(set (match_operand:DF 0 "s_register_operand" "=f") 945 (mult:DF (match_operand:DF 1 "s_register_operand" "f") 946 (float_extend:DF 947 (match_operand:SF 2 "s_register_operand" "f"))))] 948 "TARGET_HARD_FLOAT" 949 "muf%?d\\t%0, %1, %2" 950[(set_attr "type" "fmul")]) 951 952(define_insn "*muldf_esfdf_esfdf" 953 [(set (match_operand:DF 0 "s_register_operand" "=f") 954 (mult:DF (float_extend:DF 955 (match_operand:SF 1 "s_register_operand" "f")) 956 (float_extend:DF 957 (match_operand:SF 2 "s_register_operand" "f"))))] 958 "TARGET_HARD_FLOAT" 959 "muf%?d\\t%0, %1, %2" 960[(set_attr "type" "fmul")]) 961 962(define_insn "mulxf3" 963 [(set (match_operand:XF 0 "s_register_operand" "=f") 964 (mult:XF (match_operand:XF 1 "s_register_operand" "f") 965 (match_operand:XF 2 "fpu_rhs_operand" "fG")))] 966 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 967 "muf%?e\\t%0, %1, %2" 968[(set_attr "type" "fmul")]) 969 970;; Division insns 971 972(define_insn "divsf3" 973 [(set (match_operand:SF 0 "s_register_operand" "=f,f") 974 (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G") 975 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))] 976 "TARGET_HARD_FLOAT" 977 "@ 978 fdv%?s\\t%0, %1, %2 979 frd%?s\\t%0, %2, %1" 980[(set_attr "type" "fdivs")]) 981 982(define_insn "divdf3" 983 [(set (match_operand:DF 0 "s_register_operand" "=f,f") 984 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G") 985 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))] 986 "TARGET_HARD_FLOAT" 987 "@ 988 dvf%?d\\t%0, %1, %2 989 rdf%?d\\t%0, %2, %1" 990[(set_attr "type" "fdivd")]) 991 992(define_insn "*divdf_esfdf_df" 993 [(set (match_operand:DF 0 "s_register_operand" "=f") 994 (div:DF (float_extend:DF 995 (match_operand:SF 1 "s_register_operand" "f")) 996 (match_operand:DF 2 "fpu_rhs_operand" "fG")))] 997 "TARGET_HARD_FLOAT" 998 "dvf%?d\\t%0, %1, %2" 999[(set_attr "type" "fdivd")]) 1000 1001(define_insn "*divdf_df_esfdf" 1002 [(set (match_operand:DF 0 "s_register_operand" "=f") 1003 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG") 1004 (float_extend:DF 1005 (match_operand:SF 2 "s_register_operand" "f"))))] 1006 "TARGET_HARD_FLOAT" 1007 "rdf%?d\\t%0, %2, %1" 1008[(set_attr "type" "fdivd")]) 1009 1010(define_insn "*divdf_esfdf_esfdf" 1011 [(set (match_operand:DF 0 "s_register_operand" "=f") 1012 (div:DF (float_extend:DF 1013 (match_operand:SF 1 "s_register_operand" "f")) 1014 (float_extend:DF 1015 (match_operand:SF 2 "s_register_operand" "f"))))] 1016 "TARGET_HARD_FLOAT" 1017 "dvf%?d\\t%0, %1, %2" 1018[(set_attr "type" "fdivd")]) 1019 1020(define_insn "divxf3" 1021 [(set (match_operand:XF 0 "s_register_operand" "=f,f") 1022 (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G") 1023 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))] 1024 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 1025 "@ 1026 dvf%?e\\t%0, %1, %2 1027 rdf%?e\\t%0, %2, %1" 1028[(set_attr "type" "fdivx")]) 1029 1030;; Modulo insns 1031 1032(define_insn "modsf3" 1033 [(set (match_operand:SF 0 "s_register_operand" "=f") 1034 (mod:SF (match_operand:SF 1 "s_register_operand" "f") 1035 (match_operand:SF 2 "fpu_rhs_operand" "fG")))] 1036 "TARGET_HARD_FLOAT" 1037 "rmf%?s\\t%0, %1, %2" 1038[(set_attr "type" "fdivs")]) 1039 1040(define_insn "moddf3" 1041 [(set (match_operand:DF 0 "s_register_operand" "=f") 1042 (mod:DF (match_operand:DF 1 "s_register_operand" "f") 1043 (match_operand:DF 2 "fpu_rhs_operand" "fG")))] 1044 "TARGET_HARD_FLOAT" 1045 "rmf%?d\\t%0, %1, %2" 1046[(set_attr "type" "fdivd")]) 1047 1048(define_insn "*moddf_esfdf_df" 1049 [(set (match_operand:DF 0 "s_register_operand" "=f") 1050 (mod:DF (float_extend:DF 1051 (match_operand:SF 1 "s_register_operand" "f")) 1052 (match_operand:DF 2 "fpu_rhs_operand" "fG")))] 1053 "TARGET_HARD_FLOAT" 1054 "rmf%?d\\t%0, %1, %2" 1055[(set_attr "type" "fdivd")]) 1056 1057(define_insn "*moddf_df_esfdf" 1058 [(set (match_operand:DF 0 "s_register_operand" "=f") 1059 (mod:DF (match_operand:DF 1 "s_register_operand" "f") 1060 (float_extend:DF 1061 (match_operand:SF 2 "s_register_operand" "f"))))] 1062 "TARGET_HARD_FLOAT" 1063 "rmf%?d\\t%0, %1, %2" 1064[(set_attr "type" "fdivd")]) 1065 1066(define_insn "*moddf_esfdf_esfdf" 1067 [(set (match_operand:DF 0 "s_register_operand" "=f") 1068 (mod:DF (float_extend:DF 1069 (match_operand:SF 1 "s_register_operand" "f")) 1070 (float_extend:DF 1071 (match_operand:SF 2 "s_register_operand" "f"))))] 1072 "TARGET_HARD_FLOAT" 1073 "rmf%?d\\t%0, %1, %2" 1074[(set_attr "type" "fdivd")]) 1075 1076(define_insn "modxf3" 1077 [(set (match_operand:XF 0 "s_register_operand" "=f") 1078 (mod:XF (match_operand:XF 1 "s_register_operand" "f") 1079 (match_operand:XF 2 "fpu_rhs_operand" "fG")))] 1080 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 1081 "rmf%?e\\t%0, %1, %2" 1082[(set_attr "type" "fdivx")]) 1083 1084;; Boolean and,ior,xor insns 1085 1086(define_insn "anddi3" 1087 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 1088 (and:DI (match_operand:DI 1 "s_register_operand" "%0,0") 1089 (match_operand:DI 2 "s_register_operand" "r,0")))] 1090 "" 1091 "and%?\\t%Q0, %Q1, %Q2\;and%?\\t%R0, %R1, %R2" 1092[(set_attr "length" "8")]) 1093 1094(define_insn "*anddi_zesidi_di" 1095 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 1096 (and:DI (zero_extend:DI 1097 (match_operand:SI 2 "s_register_operand" "r,r")) 1098 (match_operand:DI 1 "s_register_operand" "?r,0")))] 1099 "" 1100 "and%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, #0" 1101[(set_attr "length" "8")]) 1102 1103(define_insn "*anddi_sesdi_di" 1104 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 1105 (and:DI (sign_extend:DI 1106 (match_operand:SI 2 "s_register_operand" "r,r")) 1107 (match_operand:DI 1 "s_register_operand" "?r,0")))] 1108 "" 1109 "and%?\\t%Q0, %Q1, %2\;and%?\\t%R0, %R1, %2, asr #31" 1110[(set_attr "length" "8")]) 1111 1112(define_expand "andsi3" 1113 [(set (match_operand:SI 0 "s_register_operand" "") 1114 (and:SI (match_operand:SI 1 "s_register_operand" "") 1115 (match_operand:SI 2 "reg_or_int_operand" "")))] 1116 "" 1117 " 1118 if (GET_CODE (operands[2]) == CONST_INT) 1119 { 1120 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0], 1121 operands[1], 1122 (reload_in_progress || reload_completed 1123 ? 0 : preserve_subexpressions_p ())); 1124 DONE; 1125 } 1126") 1127 1128(define_insn "*andsi3_insn" 1129 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 1130 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r") 1131 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))] 1132 "" 1133 "@ 1134 and%?\\t%0, %1, %2 1135 bic%?\\t%0, %1, #%B2 1136 #" 1137[(set_attr "length" "4,4,16")]) 1138 1139(define_split 1140 [(set (match_operand:SI 0 "s_register_operand" "") 1141 (and:SI (match_operand:SI 1 "s_register_operand" "") 1142 (match_operand:SI 2 "const_int_operand" "")))] 1143 "! (const_ok_for_arm (INTVAL (operands[2])) 1144 || const_ok_for_arm (~ INTVAL (operands[2])))" 1145 [(clobber (const_int 0))] 1146 " 1147 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0], 1148 operands[1], 0); 1149 DONE; 1150") 1151 1152(define_insn "*andsi3_compare0" 1153 [(set (reg:CC_NOOV 24) 1154 (compare:CC_NOOV 1155 (and:SI (match_operand:SI 1 "s_register_operand" "r,r") 1156 (match_operand:SI 2 "arm_not_operand" "rI,K")) 1157 (const_int 0))) 1158 (set (match_operand:SI 0 "s_register_operand" "=r,r") 1159 (and:SI (match_dup 1) (match_dup 2)))] 1160 "" 1161 "@ 1162 and%?s\\t%0, %1, %2 1163 bic%?s\\t%0, %1, #%B2" 1164[(set_attr "conds" "set")]) 1165 1166(define_insn "*andsi3_compare0_scratch" 1167 [(set (reg:CC_NOOV 24) 1168 (compare:CC_NOOV 1169 (and:SI (match_operand:SI 0 "s_register_operand" "r,r") 1170 (match_operand:SI 1 "arm_not_operand" "rI,K")) 1171 (const_int 0))) 1172 (clobber (match_scratch:SI 3 "=X,r"))] 1173 "" 1174 "@ 1175 tst%?\\t%0, %1 1176 bic%?s\\t%3, %0, #%B1" 1177[(set_attr "conds" "set")]) 1178 1179(define_insn "*zeroextractsi_compare0_scratch" 1180 [(set (reg:CC_NOOV 24) 1181 (compare:CC_NOOV (zero_extract:SI 1182 (match_operand:SI 0 "s_register_operand" "r") 1183 (match_operand 1 "const_int_operand" "n") 1184 (match_operand 2 "const_int_operand" "n")) 1185 (const_int 0)))] 1186 "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32 1187 && INTVAL (operands[1]) > 0 1188 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8 1189 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32" 1190 "* 1191 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1) 1192 << INTVAL (operands[2])); 1193 output_asm_insn (\"tst%?\\t%0, %1\", operands); 1194 return \"\"; 1195" 1196[(set_attr "conds" "set")]) 1197 1198(define_insn "*ne_zeroextractsi" 1199 [(set (match_operand:SI 0 "s_register_operand" "=r") 1200 (ne:SI (zero_extract:SI 1201 (match_operand:SI 1 "s_register_operand" "r") 1202 (match_operand:SI 2 "const_int_operand" "n") 1203 (match_operand:SI 3 "const_int_operand" "n")) 1204 (const_int 0)))] 1205 "INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32 1206 && INTVAL (operands[2]) > 0 1207 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8 1208 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32" 1209 "* 1210 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1) 1211 << INTVAL (operands[3])); 1212 output_asm_insn (\"ands\\t%0, %1, %2\", operands); 1213 return \"movne\\t%0, #1\"; 1214" 1215[(set_attr "conds" "clob") 1216 (set_attr "length" "8")]) 1217 1218;;; ??? This pattern is bogus. If operand3 has bits outside the range 1219;;; represented by the bitfield, then this will produce incorrect results. 1220;;; Somewhere, the value needs to be truncated. On targets like the m68k, 1221;;; which have a real bitfield insert instruction, the truncation happens 1222;;; in the bitfield insert instruction itself. Since arm does not have a 1223;;; bitfield insert instruction, we would have to emit code here to truncate 1224;;; the value before we insert. This loses some of the advantage of having 1225;;; this insv pattern, so this pattern needs to be reevalutated. 1226 1227(define_expand "insv" 1228 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "") 1229 (match_operand:SI 1 "general_operand" "") 1230 (match_operand:SI 2 "general_operand" "")) 1231 (match_operand:SI 3 "nonmemory_operand" ""))] 1232 "" 1233 " 1234{ 1235 int start_bit = INTVAL (operands[2]); 1236 int width = INTVAL (operands[1]); 1237 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1; 1238 rtx target, subtarget; 1239 1240 target = operands[0]; 1241 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 1242 subreg as the final target. */ 1243 if (GET_CODE (target) == SUBREG) 1244 { 1245 subtarget = gen_reg_rtx (SImode); 1246 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target))) 1247 < GET_MODE_SIZE (SImode)) 1248 target = SUBREG_REG (target); 1249 } 1250 else 1251 subtarget = target; 1252 1253 if (GET_CODE (operands[3]) == CONST_INT) 1254 { 1255 /* Since we are inserting a known constant, we may be able to 1256 reduce the number of bits that we have to clear so that 1257 the mask becomes simple. */ 1258 /* ??? This code does not check to see if the new mask is actually 1259 simpler. It may not be. */ 1260 rtx op1 = gen_reg_rtx (SImode); 1261 /* ??? Truncate operand3 to fit in the bitfield. See comment before 1262 start of this pattern. */ 1263 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]); 1264 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit); 1265 1266 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2))); 1267 emit_insn (gen_iorsi3 (subtarget, op1, 1268 GEN_INT (op3_value << start_bit))); 1269 } 1270 else if (start_bit == 0 1271 && ! (const_ok_for_arm (mask) 1272 || const_ok_for_arm (~mask))) 1273 { 1274 /* A Trick, since we are setting the bottom bits in the word, 1275 we can shift operand[3] up, operand[0] down, OR them together 1276 and rotate the result back again. This takes 3 insns, and 1277 the third might be mergable into another op. */ 1278 /* The shift up copes with the possibility that operand[3] is 1279 wider than the bitfield. */ 1280 rtx op0 = gen_reg_rtx (SImode); 1281 rtx op1 = gen_reg_rtx (SImode); 1282 1283 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width))); 1284 emit_insn (gen_iorsi3 (op1, gen_rtx_LSHIFTRT (SImode, operands[0], 1285 operands[1]), 1286 op0)); 1287 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1])); 1288 } 1289 else if ((width + start_bit == 32) 1290 && ! (const_ok_for_arm (mask) 1291 || const_ok_for_arm (~mask))) 1292 { 1293 /* Similar trick, but slightly less efficient. */ 1294 1295 rtx op0 = gen_reg_rtx (SImode); 1296 rtx op1 = gen_reg_rtx (SImode); 1297 1298 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width))); 1299 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1])); 1300 emit_insn (gen_iorsi3 (subtarget, 1301 gen_rtx_LSHIFTRT (SImode, op1, operands[1]), 1302 op0)); 1303 } 1304 else 1305 { 1306 rtx op0 = GEN_INT (mask); 1307 rtx op1 = gen_reg_rtx (SImode); 1308 rtx op2 = gen_reg_rtx (SImode); 1309 1310 if (! (const_ok_for_arm (mask) || const_ok_for_arm (~mask))) 1311 { 1312 rtx tmp = gen_reg_rtx (SImode); 1313 1314 emit_insn (gen_movsi (tmp, op0)); 1315 op0 = tmp; 1316 } 1317 1318 /* Mask out any bits in operand[3] that are not needed. */ 1319 emit_insn (gen_andsi3 (op1, operands[3], op0)); 1320 1321 if (GET_CODE (op0) == CONST_INT 1322 && (const_ok_for_arm (mask << start_bit) 1323 || const_ok_for_arm (~ (mask << start_bit)))) 1324 { 1325 op0 = GEN_INT (~(mask << start_bit)); 1326 emit_insn (gen_andsi3 (op2, operands[0], op0)); 1327 } 1328 else 1329 { 1330 if (GET_CODE (op0) == CONST_INT) 1331 { 1332 rtx tmp = gen_reg_rtx (SImode); 1333 1334 emit_insn (gen_movsi (tmp, op0)); 1335 op0 = tmp; 1336 } 1337 1338 if (start_bit != 0) 1339 op0 = gen_rtx_ASHIFT (SImode, op0, operands[2]); 1340 1341 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0)); 1342 } 1343 1344 if (start_bit != 0) 1345 op1 = gen_rtx_ASHIFT (SImode, op1, operands[2]); 1346 1347 emit_insn (gen_iorsi3 (subtarget, op1, op2)); 1348 } 1349 1350 if (subtarget != target) 1351 { 1352 /* If TARGET is still a SUBREG, then it must be wider than a word, 1353 so we must be careful only to set the subword we were asked to. */ 1354 if (GET_CODE (target) == SUBREG) 1355 emit_move_insn (target, subtarget); 1356 else 1357 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget)); 1358 } 1359 1360 DONE; 1361} 1362") 1363 1364;; constants for op 2 will never be given to these patterns. 1365(define_insn "*anddi_notdi_di" 1366 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 1367 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r,0")) 1368 (match_operand:DI 1 "s_register_operand" "0,r")))] 1369 "" 1370 "bic%?\\t%Q0, %Q1, %Q2\;bic%?\\t%R0, %R1, %R2" 1371[(set_attr "length" "8")]) 1372 1373(define_insn "*anddi_notzesidi_di" 1374 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 1375 (and:DI (not:DI (zero_extend:DI 1376 (match_operand:SI 2 "s_register_operand" "r,r"))) 1377 (match_operand:DI 1 "s_register_operand" "0,?r")))] 1378 "" 1379 "@ 1380 bic%?\\t%Q0, %Q1, %2 1381 bic%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1" 1382[(set_attr "length" "4,8")]) 1383 1384(define_insn "*anddi_notsesidi_di" 1385 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 1386 (and:DI (not:DI (sign_extend:DI 1387 (match_operand:SI 2 "s_register_operand" "r,r"))) 1388 (match_operand:DI 1 "s_register_operand" "?r,0")))] 1389 "" 1390 "bic%?\\t%Q0, %Q1, %2\;bic%?\\t%R0, %R1, %2, asr #31" 1391[(set_attr "length" "8")]) 1392 1393(define_insn "andsi_notsi_si" 1394 [(set (match_operand:SI 0 "s_register_operand" "=r") 1395 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) 1396 (match_operand:SI 1 "s_register_operand" "r")))] 1397 "" 1398 "bic%?\\t%0, %1, %2") 1399 1400(define_insn "andsi_not_shiftsi_si" 1401 [(set (match_operand:SI 0 "s_register_operand" "=r") 1402 (and:SI (not:SI (match_operator:SI 4 "shift_operator" 1403 [(match_operand:SI 2 "s_register_operand" "r") 1404 (match_operand:SI 3 "arm_rhs_operand" "rM")])) 1405 (match_operand:SI 1 "s_register_operand" "r")))] 1406 "" 1407 "bic%?\\t%0, %1, %2%S4") 1408 1409(define_insn "*andsi_notsi_si_compare0" 1410 [(set (reg:CC_NOOV 24) 1411 (compare:CC_NOOV 1412 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) 1413 (match_operand:SI 1 "s_register_operand" "r")) 1414 (const_int 0))) 1415 (set (match_operand:SI 0 "s_register_operand" "=r") 1416 (and:SI (not:SI (match_dup 2)) (match_dup 1)))] 1417 "" 1418 "bic%?s\\t%0, %1, %2" 1419[(set_attr "conds" "set")]) 1420 1421(define_insn "*andsi_notsi_si_compare0_scratch" 1422 [(set (reg:CC_NOOV 24) 1423 (compare:CC_NOOV 1424 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) 1425 (match_operand:SI 1 "s_register_operand" "r")) 1426 (const_int 0))) 1427 (clobber (match_scratch:SI 0 "=r"))] 1428 "" 1429 "bic%?s\\t%0, %1, %2" 1430[(set_attr "conds" "set")]) 1431 1432(define_insn "iordi3" 1433 [(set (match_operand:DI 0 "s_register_operand" "=&r") 1434 (ior:DI (match_operand:DI 1 "s_register_operand" "%0") 1435 (match_operand:DI 2 "s_register_operand" "r")))] 1436 "" 1437 "orr%?\\t%Q0, %Q1, %Q2\;orr%?\\t%R0, %R1, %R2" 1438[(set_attr "length" "8")]) 1439 1440(define_insn "*iordi_zesidi_di" 1441 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 1442 (ior:DI (zero_extend:DI 1443 (match_operand:SI 2 "s_register_operand" "r,r")) 1444 (match_operand:DI 1 "s_register_operand" "0,?r")))] 1445 "" 1446 "@ 1447 orr%?\\t%Q0, %Q1, %2 1448 orr%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1" 1449[(set_attr "length" "4,8")]) 1450 1451(define_insn "*iordi_sesidi_di" 1452 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 1453 (ior:DI (sign_extend:DI 1454 (match_operand:SI 2 "s_register_operand" "r,r")) 1455 (match_operand:DI 1 "s_register_operand" "?r,0")))] 1456 "" 1457 "orr%?\\t%Q0, %Q1, %2\;orr%?\\t%R0, %R1, %2, asr #31" 1458[(set_attr "length" "8")]) 1459 1460(define_expand "iorsi3" 1461 [(set (match_operand:SI 0 "s_register_operand" "") 1462 (ior:SI (match_operand:SI 1 "s_register_operand" "") 1463 (match_operand:SI 2 "reg_or_int_operand" "")))] 1464 "" 1465 " 1466 if (GET_CODE (operands[2]) == CONST_INT) 1467 { 1468 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0], 1469 operands[1], 1470 (reload_in_progress || reload_completed 1471 ? 0 : preserve_subexpressions_p ())); 1472 DONE; 1473 } 1474") 1475 1476(define_insn "*iorsi3_insn" 1477 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 1478 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r") 1479 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))] 1480 "" 1481 "@ 1482 orr%?\\t%0, %1, %2 1483 #" 1484[(set_attr "length" "4,16")]) 1485 1486(define_split 1487 [(set (match_operand:SI 0 "s_register_operand" "") 1488 (ior:SI (match_operand:SI 1 "s_register_operand" "") 1489 (match_operand:SI 2 "const_int_operand" "")))] 1490 "! const_ok_for_arm (INTVAL (operands[2]))" 1491 [(clobber (const_int 0))] 1492 " 1493 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0], 1494 operands[1], 0); 1495 DONE; 1496") 1497 1498(define_insn "*iorsi3_compare0" 1499 [(set (reg:CC_NOOV 24) 1500 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r") 1501 (match_operand:SI 2 "arm_rhs_operand" "rI")) 1502 (const_int 0))) 1503 (set (match_operand:SI 0 "s_register_operand" "=r") 1504 (ior:SI (match_dup 1) (match_dup 2)))] 1505 "" 1506 "orr%?s\\t%0, %1, %2" 1507[(set_attr "conds" "set")]) 1508 1509(define_insn "*iorsi3_compare0_scratch" 1510 [(set (reg:CC_NOOV 24) 1511 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r") 1512 (match_operand:SI 2 "arm_rhs_operand" "rI")) 1513 (const_int 0))) 1514 (clobber (match_scratch:SI 0 "=r"))] 1515 "" 1516 "orr%?s\\t%0, %1, %2" 1517[(set_attr "conds" "set")]) 1518 1519(define_insn "xordi3" 1520 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 1521 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,0") 1522 (match_operand:DI 2 "s_register_operand" "r,0")))] 1523 "" 1524 "eor%?\\t%Q0, %Q1, %Q2\;eor%?\\t%R0, %R1, %R2" 1525[(set_attr "length" "8")]) 1526 1527(define_insn "*xordi_zesidi_di" 1528 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 1529 (xor:DI (zero_extend:DI 1530 (match_operand:SI 2 "s_register_operand" "r,r")) 1531 (match_operand:DI 1 "s_register_operand" "0,?r")))] 1532 "" 1533 "@ 1534 eor%?\\t%Q0, %Q1, %2 1535 eor%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1" 1536[(set_attr "length" "4,8")]) 1537 1538(define_insn "*xordi_sesidi_di" 1539 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 1540 (xor:DI (sign_extend:DI 1541 (match_operand:SI 2 "s_register_operand" "r,r")) 1542 (match_operand:DI 1 "s_register_operand" "?r,0")))] 1543 "" 1544 "eor%?\\t%Q0, %Q1, %2\;eor%?\\t%R0, %R1, %2, asr #31" 1545[(set_attr "length" "8")]) 1546 1547(define_insn "xorsi3" 1548 [(set (match_operand:SI 0 "s_register_operand" "=r") 1549 (xor:SI (match_operand:SI 1 "s_register_operand" "r") 1550 (match_operand:SI 2 "arm_rhs_operand" "rI")))] 1551 "" 1552 "eor%?\\t%0, %1, %2") 1553 1554(define_insn "*xorsi3_compare0" 1555 [(set (reg:CC_NOOV 24) 1556 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r") 1557 (match_operand:SI 2 "arm_rhs_operand" "rI")) 1558 (const_int 0))) 1559 (set (match_operand:SI 0 "s_register_operand" "=r") 1560 (xor:SI (match_dup 1) (match_dup 2)))] 1561 "" 1562 "eor%?s\\t%0, %1, %2" 1563[(set_attr "conds" "set")]) 1564 1565(define_insn "*xorsi3_compare0_scratch" 1566 [(set (reg:CC_NOOV 24) 1567 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r") 1568 (match_operand:SI 1 "arm_rhs_operand" "rI")) 1569 (const_int 0)))] 1570 "" 1571 "teq%?\\t%0, %1" 1572[(set_attr "conds" "set")]) 1573 1574;; by splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 1575;; (NOT D) we can sometimes merge the final NOT into one of the following 1576;; insns 1577 1578(define_split 1579 [(set (match_operand:SI 0 "s_register_operand" "=r") 1580 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r")) 1581 (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI"))) 1582 (match_operand:SI 3 "arm_rhs_operand" "rI"))) 1583 (clobber (match_operand:SI 4 "s_register_operand" "=r"))] 1584 "" 1585 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2)) 1586 (not:SI (match_dup 3)))) 1587 (set (match_dup 0) (not:SI (match_dup 4)))] 1588 "" 1589) 1590 1591(define_insn "*andsi_iorsi3_notsi" 1592 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r") 1593 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0") 1594 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")) 1595 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))] 1596 "" 1597 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3" 1598[(set_attr "length" "8")]) 1599 1600 1601 1602;; Minimum and maximum insns 1603 1604(define_insn "smaxsi3" 1605 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 1606 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") 1607 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 1608 (clobber (reg:CC 24))] 1609 "" 1610 "@ 1611 cmp\\t%1, %2\;movlt\\t%0, %2 1612 cmp\\t%1, %2\;movge\\t%0, %1 1613 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2" 1614[(set_attr "conds" "clob") 1615 (set_attr "length" "8,8,12")]) 1616 1617(define_insn "sminsi3" 1618 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 1619 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") 1620 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 1621 (clobber (reg:CC 24))] 1622 "" 1623 "@ 1624 cmp\\t%1, %2\;movge\\t%0, %2 1625 cmp\\t%1, %2\;movlt\\t%0, %1 1626 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2" 1627[(set_attr "conds" "clob") 1628 (set_attr "length" "8,8,12")]) 1629 1630(define_insn "umaxsi3" 1631 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 1632 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") 1633 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 1634 (clobber (reg:CC 24))] 1635 "" 1636 "@ 1637 cmp\\t%1, %2\;movcc\\t%0, %2 1638 cmp\\t%1, %2\;movcs\\t%0, %1 1639 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2" 1640[(set_attr "conds" "clob") 1641 (set_attr "length" "8,8,12")]) 1642 1643(define_insn "uminsi3" 1644 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 1645 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") 1646 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 1647 (clobber (reg:CC 24))] 1648 "" 1649 "@ 1650 cmp\\t%1, %2\;movcs\\t%0, %2 1651 cmp\\t%1, %2\;movcc\\t%0, %1 1652 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2" 1653[(set_attr "conds" "clob") 1654 (set_attr "length" "8,8,12")]) 1655 1656(define_insn "*store_minmaxsi" 1657 [(set (match_operand:SI 0 "memory_operand" "=m") 1658 (match_operator:SI 3 "minmax_operator" 1659 [(match_operand:SI 1 "s_register_operand" "r") 1660 (match_operand:SI 2 "s_register_operand" "r")])) 1661 (clobber (reg:CC 24))] 1662 "" 1663 "* 1664 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1], 1665 operands[2]); 1666 output_asm_insn (\"cmp\\t%1, %2\", operands); 1667 output_asm_insn (\"str%d3\\t%1, %0\", operands); 1668 output_asm_insn (\"str%D3\\t%2, %0\", operands); 1669 return \"\"; 1670" 1671[(set_attr "conds" "clob") 1672 (set_attr "length" "12") 1673 (set_attr "type" "store1")]) 1674 1675; Reject the frame pointer in operand[1], since reloading this after 1676; it has been eliminated can cause carnage. 1677(define_insn "*minmax_arithsi" 1678 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 1679 (match_operator:SI 4 "shiftable_operator" 1680 [(match_operator:SI 5 "minmax_operator" 1681 [(match_operand:SI 2 "s_register_operand" "r,r") 1682 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) 1683 (match_operand:SI 1 "s_register_operand" "0,?r")])) 1684 (clobber (reg:CC 24))] 1685 "GET_CODE (operands[1]) != REG 1686 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM 1687 && REGNO(operands[1]) != ARG_POINTER_REGNUM)" 1688 "* 1689{ 1690 enum rtx_code code = GET_CODE (operands[4]); 1691 1692 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2], 1693 operands[3]); 1694 output_asm_insn (\"cmp\\t%2, %3\", operands); 1695 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands); 1696 if (which_alternative != 0 || operands[3] != const0_rtx 1697 || (code != PLUS && code != MINUS && code != IOR && code != XOR)) 1698 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands); 1699 return \"\"; 1700} 1701" 1702[(set_attr "conds" "clob") 1703 (set_attr "length" "12")]) 1704 1705 1706;; Shift and rotation insns 1707 1708(define_expand "ashlsi3" 1709 [(set (match_operand:SI 0 "s_register_operand" "") 1710 (ashift:SI (match_operand:SI 1 "s_register_operand" "") 1711 (match_operand:SI 2 "arm_rhs_operand" "")))] 1712 "" 1713 " 1714 if (GET_CODE (operands[2]) == CONST_INT 1715 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) 1716 { 1717 emit_insn (gen_movsi (operands[0], const0_rtx)); 1718 DONE; 1719 } 1720") 1721 1722(define_expand "ashrsi3" 1723 [(set (match_operand:SI 0 "s_register_operand" "") 1724 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "") 1725 (match_operand:SI 2 "arm_rhs_operand" "")))] 1726 "" 1727 " 1728 if (GET_CODE (operands[2]) == CONST_INT 1729 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) 1730 operands[2] = GEN_INT (31); 1731") 1732 1733(define_expand "lshrsi3" 1734 [(set (match_operand:SI 0 "s_register_operand" "") 1735 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "") 1736 (match_operand:SI 2 "arm_rhs_operand" "")))] 1737 "" 1738 " 1739 if (GET_CODE (operands[2]) == CONST_INT 1740 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) 1741 { 1742 emit_insn (gen_movsi (operands[0], const0_rtx)); 1743 DONE; 1744 } 1745") 1746 1747(define_expand "rotlsi3" 1748 [(set (match_operand:SI 0 "s_register_operand" "") 1749 (rotatert:SI (match_operand:SI 1 "s_register_operand" "") 1750 (match_operand:SI 2 "reg_or_int_operand" "")))] 1751 "" 1752 " 1753 if (GET_CODE (operands[2]) == CONST_INT) 1754 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32); 1755 else 1756 { 1757 rtx reg = gen_reg_rtx (SImode); 1758 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2])); 1759 operands[2] = reg; 1760 } 1761") 1762 1763(define_expand "rotrsi3" 1764 [(set (match_operand:SI 0 "s_register_operand" "") 1765 (rotatert:SI (match_operand:SI 1 "s_register_operand" "") 1766 (match_operand:SI 2 "arm_rhs_operand" "")))] 1767 "" 1768 " 1769 if (GET_CODE (operands[2]) == CONST_INT 1770 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) 1771 operands[2] = GEN_INT (INTVAL (operands[2]) % 32); 1772") 1773 1774(define_insn "*shiftsi3" 1775 [(set (match_operand:SI 0 "s_register_operand" "=r") 1776 (match_operator:SI 3 "shift_operator" 1777 [(match_operand:SI 1 "s_register_operand" "r") 1778 (match_operand:SI 2 "reg_or_int_operand" "rM")]))] 1779 "" 1780 "mov%?\\t%0, %1%S3") 1781 1782(define_insn "*shiftsi3_compare0" 1783 [(set (reg:CC_NOOV 24) 1784 (compare:CC_NOOV (match_operator:SI 3 "shift_operator" 1785 [(match_operand:SI 1 "s_register_operand" "r") 1786 (match_operand:SI 2 "arm_rhs_operand" "rM")]) 1787 (const_int 0))) 1788 (set (match_operand:SI 0 "s_register_operand" "=r") 1789 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))] 1790 "" 1791 "mov%?s\\t%0, %1%S3" 1792[(set_attr "conds" "set")]) 1793 1794(define_insn "*shiftsi3_compare0_scratch" 1795 [(set (reg:CC_NOOV 24) 1796 (compare:CC_NOOV (match_operator:SI 3 "shift_operator" 1797 [(match_operand:SI 1 "s_register_operand" "r") 1798 (match_operand:SI 2 "arm_rhs_operand" "rM")]) 1799 (const_int 0))) 1800 (clobber (match_scratch:SI 0 "=r"))] 1801 "" 1802 "mov%?s\\t%0, %1%S3" 1803[(set_attr "conds" "set")]) 1804 1805(define_insn "*notsi_shiftsi" 1806 [(set (match_operand:SI 0 "s_register_operand" "=r") 1807 (not:SI (match_operator:SI 3 "shift_operator" 1808 [(match_operand:SI 1 "s_register_operand" "r") 1809 (match_operand:SI 2 "arm_rhs_operand" "rM")])))] 1810 "" 1811 "mvn%?\\t%0, %1%S3") 1812 1813(define_insn "*notsi_shiftsi_compare0" 1814 [(set (reg:CC_NOOV 24) 1815 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator" 1816 [(match_operand:SI 1 "s_register_operand" "r") 1817 (match_operand:SI 2 "arm_rhs_operand" "rM")])) 1818 (const_int 0))) 1819 (set (match_operand:SI 0 "s_register_operand" "=r") 1820 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))] 1821 "" 1822 "mvn%?s\\t%0, %1%S3" 1823[(set_attr "conds" "set")]) 1824 1825(define_insn "*not_shiftsi_compare0_scratch" 1826 [(set (reg:CC_NOOV 24) 1827 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator" 1828 [(match_operand:SI 1 "s_register_operand" "r") 1829 (match_operand:SI 2 "arm_rhs_operand" "rM")])) 1830 (const_int 0))) 1831 (clobber (match_scratch:SI 0 "=r"))] 1832 "" 1833 "mvn%?s\\t%0, %1%S3" 1834[(set_attr "conds" "set")]) 1835 1836 1837;; Unary arithmetic insns 1838 1839(define_insn "negdi2" 1840 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 1841 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0"))) 1842 (clobber (reg:CC 24))] 1843 "" 1844 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0" 1845[(set_attr "conds" "clob") 1846 (set_attr "length" "8")]) 1847 1848(define_insn "negsi2" 1849 [(set (match_operand:SI 0 "s_register_operand" "=r") 1850 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))] 1851 "" 1852 "rsb%?\\t%0, %1, #0") 1853 1854(define_insn "negsf2" 1855 [(set (match_operand:SF 0 "s_register_operand" "=f") 1856 (neg:SF (match_operand:SF 1 "s_register_operand" "f")))] 1857 "TARGET_HARD_FLOAT" 1858 "mnf%?s\\t%0, %1" 1859[(set_attr "type" "ffarith")]) 1860 1861(define_insn "negdf2" 1862 [(set (match_operand:DF 0 "s_register_operand" "=f") 1863 (neg:DF (match_operand:DF 1 "s_register_operand" "f")))] 1864 "TARGET_HARD_FLOAT" 1865 "mnf%?d\\t%0, %1" 1866[(set_attr "type" "ffarith")]) 1867 1868(define_insn "*negdf_esfdf" 1869 [(set (match_operand:DF 0 "s_register_operand" "=f") 1870 (neg:DF (float_extend:DF 1871 (match_operand:SF 1 "s_register_operand" "f"))))] 1872 "TARGET_HARD_FLOAT" 1873 "mnf%?d\\t%0, %1" 1874[(set_attr "type" "ffarith")]) 1875 1876(define_insn "negxf2" 1877 [(set (match_operand:XF 0 "s_register_operand" "=f") 1878 (neg:XF (match_operand:XF 1 "s_register_operand" "f")))] 1879 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 1880 "mnf%?e\\t%0, %1" 1881[(set_attr "type" "ffarith")]) 1882 1883;; abssi2 doesn't really clobber the condition codes if a different register 1884;; is being set. To keep things simple, assume during rtl manipulations that 1885;; it does, but tell the final scan operator the truth. Similarly for 1886;; (neg (abs...)) 1887 1888(define_insn "abssi2" 1889 [(set (match_operand:SI 0 "s_register_operand" "=r,&r") 1890 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))) 1891 (clobber (reg:CC 24))] 1892 "" 1893 "@ 1894 cmp\\t%0, #0\;rsblt\\t%0, %0, #0 1895 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31" 1896[(set_attr "conds" "clob,*") 1897 (set_attr "length" "8")]) 1898 1899(define_insn "*neg_abssi2" 1900 [(set (match_operand:SI 0 "s_register_operand" "=r,&r") 1901 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))) 1902 (clobber (reg:CC 24))] 1903 "" 1904 "@ 1905 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0 1906 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31" 1907[(set_attr "conds" "clob,*") 1908 (set_attr "length" "8")]) 1909 1910(define_insn "abssf2" 1911 [(set (match_operand:SF 0 "s_register_operand" "=f") 1912 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))] 1913 "TARGET_HARD_FLOAT" 1914 "abs%?s\\t%0, %1" 1915[(set_attr "type" "ffarith")]) 1916 1917(define_insn "absdf2" 1918 [(set (match_operand:DF 0 "s_register_operand" "=f") 1919 (abs:DF (match_operand:DF 1 "s_register_operand" "f")))] 1920 "TARGET_HARD_FLOAT" 1921 "abs%?d\\t%0, %1" 1922[(set_attr "type" "ffarith")]) 1923 1924(define_insn "*absdf_esfdf" 1925 [(set (match_operand:DF 0 "s_register_operand" "=f") 1926 (abs:DF (float_extend:DF 1927 (match_operand:SF 1 "s_register_operand" "f"))))] 1928 "TARGET_HARD_FLOAT" 1929 "abs%?d\\t%0, %1" 1930[(set_attr "type" "ffarith")]) 1931 1932(define_insn "absxf2" 1933 [(set (match_operand:XF 0 "s_register_operand" "=f") 1934 (abs:XF (match_operand:XF 1 "s_register_operand" "f")))] 1935 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 1936 "abs%?e\\t%0, %1" 1937[(set_attr "type" "ffarith")]) 1938 1939(define_insn "sqrtsf2" 1940 [(set (match_operand:SF 0 "s_register_operand" "=f") 1941 (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))] 1942 "TARGET_HARD_FLOAT" 1943 "sqt%?s\\t%0, %1" 1944[(set_attr "type" "float_em")]) 1945 1946(define_insn "sqrtdf2" 1947 [(set (match_operand:DF 0 "s_register_operand" "=f") 1948 (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))] 1949 "TARGET_HARD_FLOAT" 1950 "sqt%?d\\t%0, %1" 1951[(set_attr "type" "float_em")]) 1952 1953(define_insn "*sqrtdf_esfdf" 1954 [(set (match_operand:DF 0 "s_register_operand" "=f") 1955 (sqrt:DF (float_extend:DF 1956 (match_operand:SF 1 "s_register_operand" "f"))))] 1957 "TARGET_HARD_FLOAT" 1958 "sqt%?d\\t%0, %1" 1959[(set_attr "type" "float_em")]) 1960 1961(define_insn "sqrtxf2" 1962 [(set (match_operand:XF 0 "s_register_operand" "=f") 1963 (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))] 1964 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 1965 "sqt%?e\\t%0, %1" 1966[(set_attr "type" "float_em")]) 1967 1968;; SIN COS TAN and family are always emulated, so it's probably better 1969;; to always call a library function. 1970;(define_insn "sinsf2" 1971; [(set (match_operand:SF 0 "s_register_operand" "=f") 1972; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 0))] 1973; "TARGET_HARD_FLOAT" 1974; "sin%?s\\t%0, %1" 1975;[(set_attr "type" "float_em")]) 1976; 1977;(define_insn "sindf2" 1978; [(set (match_operand:DF 0 "s_register_operand" "=f") 1979; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 0))] 1980; "TARGET_HARD_FLOAT" 1981; "sin%?d\\t%0, %1" 1982;[(set_attr "type" "float_em")]) 1983; 1984;(define_insn "*sindf_esfdf" 1985; [(set (match_operand:DF 0 "s_register_operand" "=f") 1986; (unspec:DF [(float_extend:DF 1987; (match_operand:SF 1 "s_register_operand" "f"))] 0))] 1988; "TARGET_HARD_FLOAT" 1989; "sin%?d\\t%0, %1" 1990;[(set_attr "type" "float_em")]) 1991; 1992;(define_insn "sinxf2" 1993; [(set (match_operand:XF 0 "s_register_operand" "=f") 1994; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 0))] 1995; "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 1996; "sin%?e\\t%0, %1" 1997;[(set_attr "type" "float_em")]) 1998; 1999;(define_insn "cossf2" 2000; [(set (match_operand:SF 0 "s_register_operand" "=f") 2001; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 1))] 2002; "TARGET_HARD_FLOAT" 2003; "cos%?s\\t%0, %1" 2004;[(set_attr "type" "float_em")]) 2005; 2006;(define_insn "cosdf2" 2007; [(set (match_operand:DF 0 "s_register_operand" "=f") 2008; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 1))] 2009; "TARGET_HARD_FLOAT" 2010; "cos%?d\\t%0, %1" 2011;[(set_attr "type" "float_em")]) 2012; 2013;(define_insn "*cosdf_esfdf" 2014; [(set (match_operand:DF 0 "s_register_operand" "=f") 2015; (unspec:DF [(float_extend:DF 2016; (match_operand:SF 1 "s_register_operand" "f"))] 1))] 2017; "TARGET_HARD_FLOAT" 2018; "cos%?d\\t%0, %1" 2019;[(set_attr "type" "float_em")]) 2020; 2021;(define_insn "cosxf2" 2022; [(set (match_operand:XF 0 "s_register_operand" "=f") 2023; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 1))] 2024; "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 2025; "cos%?e\\t%0, %1" 2026;[(set_attr "type" "float_em")]) 2027 2028(define_insn "one_cmpldi2" 2029 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 2030 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))] 2031 "" 2032 "mvn%?\\t%Q0, %Q1\;mvn%?\\t%R0, %R1" 2033[(set_attr "length" "8")]) 2034 2035(define_insn "one_cmplsi2" 2036 [(set (match_operand:SI 0 "s_register_operand" "=r") 2037 (not:SI (match_operand:SI 1 "s_register_operand" "r")))] 2038 "" 2039 "mvn%?\\t%0, %1") 2040 2041(define_insn "*notsi_compare0" 2042 [(set (reg:CC_NOOV 24) 2043 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r")) 2044 (const_int 0))) 2045 (set (match_operand:SI 0 "s_register_operand" "=r") 2046 (not:SI (match_dup 1)))] 2047 "" 2048 "mvn%?s\\t%0, %1" 2049[(set_attr "conds" "set")]) 2050 2051(define_insn "*notsi_compare0_scratch" 2052 [(set (reg:CC_NOOV 24) 2053 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r")) 2054 (const_int 0))) 2055 (clobber (match_scratch:SI 0 "=r"))] 2056 "" 2057 "mvn%?s\\t%0, %1" 2058[(set_attr "conds" "set")]) 2059 2060;; Fixed <--> Floating conversion insns 2061 2062(define_insn "floatsisf2" 2063 [(set (match_operand:SF 0 "s_register_operand" "=f") 2064 (float:SF (match_operand:SI 1 "s_register_operand" "r")))] 2065 "TARGET_HARD_FLOAT" 2066 "flt%?s\\t%0, %1" 2067[(set_attr "type" "r_2_f")]) 2068 2069(define_insn "floatsidf2" 2070 [(set (match_operand:DF 0 "s_register_operand" "=f") 2071 (float:DF (match_operand:SI 1 "s_register_operand" "r")))] 2072 "TARGET_HARD_FLOAT" 2073 "flt%?d\\t%0, %1" 2074[(set_attr "type" "r_2_f")]) 2075 2076(define_insn "floatsixf2" 2077 [(set (match_operand:XF 0 "s_register_operand" "=f") 2078 (float:XF (match_operand:SI 1 "s_register_operand" "r")))] 2079 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 2080 "flt%?e\\t%0, %1" 2081[(set_attr "type" "r_2_f")]) 2082 2083(define_insn "fix_truncsfsi2" 2084 [(set (match_operand:SI 0 "s_register_operand" "=r") 2085 (fix:SI (match_operand:SF 1 "s_register_operand" "f")))] 2086 "TARGET_HARD_FLOAT" 2087 "fix%?z\\t%0, %1" 2088[(set_attr "type" "f_2_r")]) 2089 2090(define_insn "fix_truncdfsi2" 2091 [(set (match_operand:SI 0 "s_register_operand" "=r") 2092 (fix:SI (match_operand:DF 1 "s_register_operand" "f")))] 2093 "TARGET_HARD_FLOAT" 2094 "fix%?z\\t%0, %1" 2095[(set_attr "type" "f_2_r")]) 2096 2097(define_insn "fix_truncxfsi2" 2098 [(set (match_operand:SI 0 "s_register_operand" "=r") 2099 (fix:SI (match_operand:XF 1 "s_register_operand" "f")))] 2100 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 2101 "fix%?z\\t%0, %1" 2102[(set_attr "type" "f_2_r")]) 2103 2104;; Truncation insns 2105 2106(define_insn "truncdfsf2" 2107 [(set (match_operand:SF 0 "s_register_operand" "=f") 2108 (float_truncate:SF 2109 (match_operand:DF 1 "s_register_operand" "f")))] 2110 "TARGET_HARD_FLOAT" 2111 "mvf%?s\\t%0, %1" 2112[(set_attr "type" "ffarith")]) 2113 2114(define_insn "truncxfsf2" 2115 [(set (match_operand:SF 0 "s_register_operand" "=f") 2116 (float_truncate:SF 2117 (match_operand:XF 1 "s_register_operand" "f")))] 2118 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 2119 "mvf%?s\\t%0, %1" 2120[(set_attr "type" "ffarith")]) 2121 2122(define_insn "truncxfdf2" 2123 [(set (match_operand:DF 0 "s_register_operand" "=f") 2124 (float_truncate:DF 2125 (match_operand:XF 1 "s_register_operand" "f")))] 2126 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 2127 "mvf%?d\\t%0, %1" 2128[(set_attr "type" "ffarith")]) 2129 2130;; Zero and sign extension instructions. 2131 2132(define_insn "zero_extendsidi2" 2133 [(set (match_operand:DI 0 "s_register_operand" "=r") 2134 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))] 2135 "" 2136 "* 2137 if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0)) 2138 output_asm_insn (\"mov%?\\t%Q0, %1\", operands); 2139 return \"mov%?\\t%R0, #0\"; 2140" 2141[(set_attr "length" "8")]) 2142 2143(define_insn "zero_extendqidi2" 2144 [(set (match_operand:DI 0 "s_register_operand" "=r") 2145 (zero_extend:DI (match_operand:QI 1 "s_register_operand" "r")))] 2146 "" 2147 "and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0" 2148[(set_attr "length" "8") 2149 (set_attr "type" "*")]) 2150 2151(define_insn "extendsidi2" 2152 [(set (match_operand:DI 0 "s_register_operand" "=r") 2153 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))] 2154 "" 2155 "* 2156 if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0)) 2157 output_asm_insn (\"mov%?\\t%Q0, %1\", operands); 2158 return \"mov%?\\t%R0, %Q0, asr #31\"; 2159" 2160[(set_attr "length" "8")]) 2161 2162(define_expand "zero_extendhisi2" 2163 [(set (match_dup 2) (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "") 2164 (const_int 16))) 2165 (set (match_operand:SI 0 "s_register_operand" "") 2166 (lshiftrt:SI (match_dup 2) (const_int 16)))] 2167 "" 2168 " 2169{ 2170 if (arm_arch4 && GET_CODE (operands[1]) == MEM) 2171 { 2172 /* Note: We do not have to worry about TARGET_SHORT_BY_BYTES 2173 here because the insn below will generate an LDRH instruction 2174 rather than an LDR instruction, so we cannot get an unaligned 2175 word access. */ 2176 emit_insn (gen_rtx_SET (VOIDmode, operands[0], 2177 gen_rtx_ZERO_EXTEND (SImode, operands[1]))); 2178 DONE; 2179 } 2180 if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM) 2181 { 2182 emit_insn (gen_movhi_bytes (operands[0], operands[1])); 2183 DONE; 2184 } 2185 if (! s_register_operand (operands[1], HImode)) 2186 operands[1] = copy_to_mode_reg (HImode, operands[1]); 2187 operands[1] = gen_lowpart (SImode, operands[1]); 2188 operands[2] = gen_reg_rtx (SImode); 2189}") 2190 2191(define_insn "*zero_extendhisi_insn" 2192 [(set (match_operand:SI 0 "s_register_operand" "=r") 2193 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] 2194 "arm_arch4" 2195 "ldr%?h\\t%0, %1" 2196[(set_attr "type" "load")]) 2197 2198(define_split 2199 [(set (match_operand:SI 0 "s_register_operand" "") 2200 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))) 2201 (clobber (match_operand:SI 2 "s_register_operand" ""))] 2202 "! arm_arch4" 2203 [(set (match_dup 2) (match_dup 1)) 2204 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))] 2205 " 2206{ 2207 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL) 2208 FAIL; 2209}") 2210 2211(define_split 2212 [(set (match_operand:SI 0 "s_register_operand" "") 2213 (match_operator:SI 3 "shiftable_operator" 2214 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")) 2215 (match_operand:SI 4 "s_register_operand" "")])) 2216 (clobber (match_operand:SI 2 "s_register_operand" ""))] 2217 "! arm_arch4" 2218 [(set (match_dup 2) (match_dup 1)) 2219 (set (match_dup 0) 2220 (match_op_dup 3 2221 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))] 2222 " 2223{ 2224 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL) 2225 FAIL; 2226}") 2227 2228(define_expand "zero_extendqisi2" 2229 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 2230 (zero_extend:SI 2231 (match_operand:QI 1 "nonimmediate_operand" "r,m")))] 2232 "" 2233 " 2234 if (GET_CODE (operands[1]) != MEM) 2235 { 2236 emit_insn (gen_andsi3 (operands[0], gen_lowpart (SImode, operands[1]), 2237 GEN_INT (255))); 2238 DONE; 2239 } 2240") 2241 2242(define_insn "*load_extendqisi" 2243 [(set (match_operand:SI 0 "s_register_operand" "=r") 2244 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] 2245 "" 2246 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2" 2247[(set_attr "type" "load")]) 2248 2249(define_split 2250 [(set (match_operand:SI 0 "s_register_operand" "") 2251 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0))) 2252 (clobber (match_operand:SI 2 "s_register_operand" ""))] 2253 "GET_CODE (operands[1]) != MEM" 2254 [(set (match_dup 2) (match_dup 1)) 2255 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))] 2256 "") 2257 2258(define_insn "*compareqi_eq0" 2259 [(set (reg:CC_Z 24) 2260 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r") 2261 (const_int 0)))] 2262 "" 2263 "tst\\t%0, #255" 2264[(set_attr "conds" "set")]) 2265 2266(define_expand "extendhisi2" 2267 [(set (match_dup 2) 2268 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "") 2269 (const_int 16))) 2270 (set (match_operand:SI 0 "s_register_operand" "") 2271 (ashiftrt:SI (match_dup 2) 2272 (const_int 16)))] 2273 "" 2274 " 2275{ 2276 if (arm_arch4 && GET_CODE (operands[1]) == MEM) 2277 { 2278 /* Note: We do not have to worry about TARGET_SHORT_BY_BYTES 2279 here because the insn below will generate an LDRH instruction 2280 rather than an LDR instruction, so we cannot get an unaligned 2281 word access. */ 2282 emit_insn (gen_rtx_SET (VOIDmode, operands[0], 2283 gen_rtx_SIGN_EXTEND (SImode, operands[1]))); 2284 DONE; 2285 } 2286 2287 if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM) 2288 { 2289 emit_insn (gen_extendhisi2_mem (operands[0], operands[1])); 2290 DONE; 2291 } 2292 if (! s_register_operand (operands[1], HImode)) 2293 operands[1] = copy_to_mode_reg (HImode, operands[1]); 2294 operands[1] = gen_lowpart (SImode, operands[1]); 2295 operands[2] = gen_reg_rtx (SImode); 2296}") 2297 2298(define_expand "extendhisi2_mem" 2299 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" ""))) 2300 (set (match_dup 3) 2301 (zero_extend:SI (match_dup 7))) 2302 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24))) 2303 (set (match_operand:SI 0 "" "") 2304 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))] 2305 "" 2306 " 2307{ 2308 rtx mem1, mem2; 2309 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); 2310 2311 mem1 = gen_rtx_MEM (QImode, addr); 2312 MEM_COPY_ATTRIBUTES (mem1, operands[1]); 2313 RTX_UNCHANGING_P (mem1) = RTX_UNCHANGING_P (operands[1]); 2314 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1)); 2315 MEM_COPY_ATTRIBUTES (mem2, operands[1]); 2316 RTX_UNCHANGING_P (mem2) = RTX_UNCHANGING_P (operands[1]); 2317 operands[0] = gen_lowpart (SImode, operands[0]); 2318 operands[1] = mem1; 2319 operands[2] = gen_reg_rtx (SImode); 2320 operands[3] = gen_reg_rtx (SImode); 2321 operands[6] = gen_reg_rtx (SImode); 2322 operands[7] = mem2; 2323 2324 if (BYTES_BIG_ENDIAN) 2325 { 2326 operands[4] = operands[2]; 2327 operands[5] = operands[3]; 2328 } 2329 else 2330 { 2331 operands[4] = operands[3]; 2332 operands[5] = operands[2]; 2333 } 2334} 2335") 2336 2337(define_insn "*extendhisi_insn" 2338 [(set (match_operand:SI 0 "s_register_operand" "=r") 2339 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))] 2340 "arm_arch4" 2341 "ldr%?sh\\t%0, %1" 2342[(set_attr "type" "load")]) 2343 2344(define_split 2345 [(set (match_operand:SI 0 "s_register_operand" "") 2346 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))) 2347 (clobber (match_operand:SI 2 "s_register_operand" ""))] 2348 "! arm_arch4" 2349 [(set (match_dup 2) (match_dup 1)) 2350 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))] 2351 " 2352{ 2353 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL) 2354 FAIL; 2355}") 2356 2357(define_split 2358 [(set (match_operand:SI 0 "s_register_operand" "") 2359 (match_operator:SI 3 "shiftable_operator" 2360 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")) 2361 (match_operand:SI 4 "s_register_operand" "")])) 2362 (clobber (match_operand:SI 2 "s_register_operand" ""))] 2363 "! arm_arch4" 2364 [(set (match_dup 2) (match_dup 1)) 2365 (set (match_dup 0) 2366 (match_op_dup 3 2367 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))] 2368 " 2369{ 2370 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL) 2371 FAIL; 2372}") 2373 2374(define_expand "extendqihi2" 2375 [(set (match_dup 2) 2376 (ashift:SI (match_operand:QI 1 "general_operand" "") 2377 (const_int 24))) 2378 (set (match_operand:HI 0 "s_register_operand" "") 2379 (ashiftrt:SI (match_dup 2) 2380 (const_int 24)))] 2381 "" 2382 " 2383{ 2384 if (arm_arch4 && GET_CODE (operands[1]) == MEM) 2385 { 2386 emit_insn (gen_rtx_SET (VOIDmode, 2387 operands[0], 2388 gen_rtx_SIGN_EXTEND (HImode, operands[1]))); 2389 DONE; 2390 } 2391 if (! s_register_operand (operands[1], QImode)) 2392 operands[1] = copy_to_mode_reg (QImode, operands[1]); 2393 operands[0] = gen_lowpart (SImode, operands[0]); 2394 operands[1] = gen_lowpart (SImode, operands[1]); 2395 operands[2] = gen_reg_rtx (SImode); 2396}") 2397 2398; Rather than restricting all byte accesses to memory addresses that ldrsb 2399; can handle, we fix up the ones that ldrsb can't grok with a split. 2400(define_insn "*extendqihi_insn" 2401 [(set (match_operand:HI 0 "s_register_operand" "=r") 2402 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))] 2403 "arm_arch4" 2404 "* 2405 /* If the address is invalid, this will split the instruction into two. */ 2406 if (bad_signed_byte_operand (operands[1], QImode)) 2407 return \"#\"; 2408 return \"ldr%?sb\\t%0, %1\"; 2409" 2410[(set_attr "type" "load") 2411 (set_attr "length" "8")]) 2412 2413(define_split 2414 [(set (match_operand:HI 0 "s_register_operand" "") 2415 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))] 2416 "arm_arch4 && reload_completed" 2417 [(set (match_dup 3) (match_dup 1)) 2418 (set (match_dup 0) (sign_extend:HI (match_dup 2)))] 2419 " 2420 { 2421 HOST_WIDE_INT offset; 2422 2423 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0])); 2424 operands[2] = gen_rtx_MEM (QImode, operands[3]); 2425 MEM_COPY_ATTRIBUTES (operands[2], operands[1]); 2426 RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]); 2427 operands[1] = XEXP (operands[1], 0); 2428 if (GET_CODE (operands[1]) == PLUS 2429 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT 2430 && ! (const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1))) 2431 || const_ok_for_arm (-offset))) 2432 { 2433 HOST_WIDE_INT low = (offset > 0 2434 ? (offset & 0xff) : -((-offset) & 0xff)); 2435 XEXP (operands[2], 0) = plus_constant (operands[3], low); 2436 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low); 2437 } 2438 /* Ensure the sum is in correct canonical form */ 2439 else if (GET_CODE (operands[1]) == PLUS 2440 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT 2441 && ! s_register_operand (XEXP (operands[1], 1), VOIDmode)) 2442 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]), 2443 XEXP (operands[1], 1), 2444 XEXP (operands[1], 0)); 2445 } 2446") 2447 2448(define_expand "extendqisi2" 2449 [(set (match_dup 2) 2450 (ashift:SI (match_operand:QI 1 "general_operand" "") 2451 (const_int 24))) 2452 (set (match_operand:SI 0 "s_register_operand" "") 2453 (ashiftrt:SI (match_dup 2) 2454 (const_int 24)))] 2455 "" 2456 " 2457{ 2458 if (arm_arch4 && GET_CODE (operands[1]) == MEM) 2459 { 2460 emit_insn (gen_rtx_SET (VOIDmode, 2461 operands[0], 2462 gen_rtx_SIGN_EXTEND (SImode, operands[1]))); 2463 DONE; 2464 } 2465 if (! s_register_operand (operands[1], QImode)) 2466 operands[1] = copy_to_mode_reg (QImode, operands[1]); 2467 operands[1] = gen_lowpart (SImode, operands[1]); 2468 operands[2] = gen_reg_rtx (SImode); 2469}") 2470 2471; Rather than restricting all byte accesses to memory addresses that ldrsb 2472; can handle, we fix up the ones that ldrsb can't grok with a split. 2473(define_insn "*extendqisi_insn" 2474 [(set (match_operand:SI 0 "s_register_operand" "=r") 2475 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))] 2476 "arm_arch4" 2477 "* 2478 /* If the address is invalid, this will split the instruction into two. */ 2479 if (bad_signed_byte_operand (operands[1], QImode)) 2480 return \"#\"; 2481 return \"ldr%?sb\\t%0, %1\"; 2482" 2483[(set_attr "type" "load") 2484 (set_attr "length" "8")]) 2485 2486(define_split 2487 [(set (match_operand:SI 0 "s_register_operand" "") 2488 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))] 2489 "arm_arch4 && reload_completed" 2490 [(set (match_dup 0) (match_dup 1)) 2491 (set (match_dup 0) (sign_extend:SI (match_dup 2)))] 2492 " 2493 { 2494 HOST_WIDE_INT offset; 2495 2496 operands[2] = gen_rtx_MEM (QImode, operands[0]); 2497 MEM_COPY_ATTRIBUTES (operands[2], operands[1]); 2498 RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]); 2499 operands[1] = XEXP (operands[1], 0); 2500 if (GET_CODE (operands[1]) == PLUS 2501 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT 2502 && ! (const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1))) 2503 || const_ok_for_arm (-offset))) 2504 { 2505 HOST_WIDE_INT low = (offset > 0 2506 ? (offset & 0xff) : -((-offset) & 0xff)); 2507 XEXP (operands[2], 0) = plus_constant (operands[0], low); 2508 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low); 2509 } 2510 /* Ensure the sum is in correct canonical form */ 2511 else if (GET_CODE (operands[1]) == PLUS 2512 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT 2513 && ! s_register_operand (XEXP (operands[1], 1), VOIDmode)) 2514 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]), 2515 XEXP (operands[1], 1), 2516 XEXP (operands[1], 0)); 2517 } 2518") 2519 2520(define_insn "extendsfdf2" 2521 [(set (match_operand:DF 0 "s_register_operand" "=f") 2522 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))] 2523 "TARGET_HARD_FLOAT" 2524 "mvf%?d\\t%0, %1" 2525[(set_attr "type" "ffarith")]) 2526 2527(define_insn "extendsfxf2" 2528 [(set (match_operand:XF 0 "s_register_operand" "=f") 2529 (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))] 2530 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 2531 "mvf%?e\\t%0, %1" 2532[(set_attr "type" "ffarith")]) 2533 2534(define_insn "extenddfxf2" 2535 [(set (match_operand:XF 0 "s_register_operand" "=f") 2536 (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))] 2537 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 2538 "mvf%?e\\t%0, %1" 2539[(set_attr "type" "ffarith")]) 2540 2541 2542;; Move insns (including loads and stores) 2543 2544;; XXX Just some ideas about movti. 2545;; I don't think these are a good idea on the arm, there just aren't enough 2546;; registers 2547;;(define_expand "loadti" 2548;; [(set (match_operand:TI 0 "s_register_operand" "") 2549;; (mem:TI (match_operand:SI 1 "address_operand" "")))] 2550;; "" "") 2551 2552;;(define_expand "storeti" 2553;; [(set (mem:TI (match_operand:TI 0 "address_operand" "")) 2554;; (match_operand:TI 1 "s_register_operand" ""))] 2555;; "" "") 2556 2557;;(define_expand "movti" 2558;; [(set (match_operand:TI 0 "general_operand" "") 2559;; (match_operand:TI 1 "general_operand" ""))] 2560;; "" 2561;; " 2562;;{ 2563;; rtx insn; 2564;; 2565;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) 2566;; operands[1] = copy_to_reg (operands[1]); 2567;; if (GET_CODE (operands[0]) == MEM) 2568;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]); 2569;; else if (GET_CODE (operands[1]) == MEM) 2570;; insn = gen_loadti (operands[0], XEXP (operands[1], 0)); 2571;; else 2572;; FAIL; 2573;; 2574;; emit_insn (insn); 2575;; DONE; 2576;;}") 2577 2578;; Recognise garbage generated above. 2579 2580;;(define_insn "" 2581;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m") 2582;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))] 2583;; "" 2584;; "* 2585;; { 2586;; register mem = (which_alternative < 3); 2587;; register char *template; 2588;; 2589;; operands[mem] = XEXP (operands[mem], 0); 2590;; switch (which_alternative) 2591;; { 2592;; case 0: template = \"ldmdb\\t%1!, %M0\"; break; 2593;; case 1: template = \"ldmia\\t%1!, %M0\"; break; 2594;; case 2: template = \"ldmia\\t%1, %M0\"; break; 2595;; case 3: template = \"stmdb\\t%0!, %M1\"; break; 2596;; case 4: template = \"stmia\\t%0!, %M1\"; break; 2597;; case 5: template = \"stmia\\t%0, %M1\"; break; 2598;; } 2599;; output_asm_insn (template, operands); 2600;; return \"\"; 2601;; }") 2602 2603 2604(define_insn "movdi" 2605 [(set (match_operand:DI 0 "di_operand" "=r,r,o<>") 2606 (match_operand:DI 1 "di_operand" "rIK,mi,r"))] 2607 "" 2608 "* 2609 return (output_move_double (operands)); 2610" 2611[(set_attr "length" "8,8,8") 2612 (set_attr "type" "*,load,store2")]) 2613 2614(define_expand "movsi" 2615 [(set (match_operand:SI 0 "general_operand" "") 2616 (match_operand:SI 1 "general_operand" ""))] 2617 "" 2618 " 2619 /* Everything except mem = const or mem = mem can be done easily */ 2620 if (GET_CODE (operands[0]) == MEM) 2621 operands[1] = force_reg (SImode, operands[1]); 2622 if (GET_CODE (operands[1]) == CONST_INT 2623 && !(const_ok_for_arm (INTVAL (operands[1])) 2624 || const_ok_for_arm (~INTVAL (operands[1])))) 2625 { 2626 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0], 2627 NULL_RTX, 2628 (reload_in_progress || reload_completed ? 0 2629 : preserve_subexpressions_p ())); 2630 DONE; 2631 } 2632 if (CONSTANT_P (operands[1]) && flag_pic) 2633 operands[1] = legitimize_pic_address (operands[1], SImode, 2634 ((reload_in_progress 2635 || reload_completed) 2636 ? operands[0] : 0)); 2637") 2638 2639(define_insn "*movsi_insn" 2640 [(set (match_operand:SI 0 "general_operand" "=r,r,r,m") 2641 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))] 2642 "register_operand (operands[0], SImode) 2643 || register_operand (operands[1], SImode)" 2644 "@ 2645 mov%?\\t%0, %1 2646 mvn%?\\t%0, #%B1 2647 ldr%?\\t%0, %1 2648 str%?\\t%1, %0" 2649[(set_attr "type" "*,*,load,store1")]) 2650 2651(define_split 2652 [(set (match_operand:SI 0 "s_register_operand" "") 2653 (match_operand:SI 1 "const_int_operand" ""))] 2654 "! (const_ok_for_arm (INTVAL (operands[1])) 2655 || const_ok_for_arm (~INTVAL (operands[1])))" 2656 [(clobber (const_int 0))] 2657 " 2658 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0], 2659 NULL_RTX, 0); 2660 DONE; 2661") 2662 2663(define_expand "movaddr" 2664 [(set (match_operand:SI 0 "s_register_operand" "") 2665 (match_operand:DI 1 "address_operand" ""))] 2666 "" 2667 "") 2668 2669(define_insn "*movaddr_insn" 2670 [(set (match_operand:SI 0 "s_register_operand" "=r") 2671 (match_operand:DI 1 "address_operand" "p"))] 2672 "reload_completed 2673 && (GET_CODE (operands[1]) == LABEL_REF 2674 || (GET_CODE (operands[1]) == CONST 2675 && GET_CODE (XEXP (operands[1], 0)) == PLUS 2676 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF 2677 && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))" 2678 "adr%?\\t%0, %a1") 2679 2680/* When generating pic, we need to load the symbol offset into a register. 2681 So that the optimizer does not confuse this with a normal symbol load 2682 we use an unspec. The offset will be loaded from a constant pool entry, 2683 since that is the only type of relocation we can use. */ 2684 2685(define_insn "pic_load_addr" 2686 [(set (match_operand:SI 0 "s_register_operand" "=r") 2687 (unspec:SI [(match_operand 1 "" "")] 3))] 2688 "flag_pic" 2689 "ldr%?\\t%0, %a1" 2690 [(set_attr "type" "load")]) 2691 2692;; This variant is used for AOF assembly, since it needs to mention the 2693;; pic register in the rtl. 2694(define_expand "pic_load_addr_based" 2695 [(set (match_operand:SI 0 "s_register_operand" "=r") 2696 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] 3))] 2697 "flag_pic" 2698 "operands[2] = pic_offset_table_rtx;") 2699 2700(define_insn "*pic_load_addr_based_insn" 2701 [(set (match_operand:SI 0 "s_register_operand" "=r") 2702 (unspec:SI [(match_operand 1 "" "") 2703 (match_operand 2 "s_register_operand" "r")] 3))] 2704 "flag_pic && operands[2] == pic_offset_table_rtx" 2705 "* 2706#ifdef AOF_ASSEMBLER 2707 operands[1] = aof_pic_entry (operands[1]); 2708#endif 2709 output_asm_insn (\"ldr%?\\t%0, %a1\", operands); 2710 return \"\"; 2711" [(set_attr "type" "load")]) 2712 2713(define_insn "pic_add_dot_plus_eight" 2714 [(set (match_operand 0 "register_operand" "+r") 2715 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8))))) 2716 (use (label_ref (match_operand 1 "" "")))] 2717 "flag_pic" 2718 "* 2719 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", 2720 CODE_LABEL_NUMBER (operands[1])); 2721 return \"add%?\\t%0, %|pc, %0\"; 2722") 2723 2724;; If copying one reg to another we can set the condition codes according to 2725;; its value. Such a move is common after a return from subroutine and the 2726;; result is being tested against zero. 2727 2728(define_insn "*movsi_compare0" 2729 [(set (reg:CC 24) (compare:CC (match_operand:SI 1 "s_register_operand" "0,r") 2730 (const_int 0))) 2731 (set (match_operand:SI 0 "s_register_operand" "=r,r") (match_dup 1))] 2732 "" 2733 "@ 2734 cmp%?\\t%0, #0 2735 sub%?s\\t%0, %1, #0" 2736[(set_attr "conds" "set")]) 2737 2738;; Subroutine to store a half word from a register into memory. 2739;; Operand 0 is the source register (HImode) 2740;; Operand 1 is the destination address in a register (SImode) 2741 2742;; In both this routine and the next, we must be careful not to spill 2743;; a memory address of reg+large_const into a separate PLUS insn, since this 2744;; can generate unrecognizable rtl. 2745 2746(define_expand "storehi" 2747 [;; store the low byte 2748 (set (match_operand 1 "" "") (match_dup 3)) 2749 ;; extract the high byte 2750 (set (match_dup 2) 2751 (ashiftrt:SI (match_operand 0 "" "") (const_int 8))) 2752 ;; store the high byte 2753 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe 2754 "" 2755 " 2756{ 2757 rtx addr = XEXP (operands[1], 0); 2758 enum rtx_code code = GET_CODE (addr); 2759 2760 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT) 2761 || code == MINUS) 2762 addr = force_reg (SImode, addr); 2763 2764 operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1)); 2765 operands[1] = change_address (operands[1], QImode, NULL_RTX); 2766 operands[3] = gen_lowpart (QImode, operands[0]); 2767 operands[0] = gen_lowpart (SImode, operands[0]); 2768 operands[2] = gen_reg_rtx (SImode); 2769} 2770") 2771 2772(define_expand "storehi_bigend" 2773 [(set (match_dup 4) (match_dup 3)) 2774 (set (match_dup 2) 2775 (ashiftrt:SI (match_operand 0 "" "") (const_int 8))) 2776 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 0))] 2777 "" 2778 " 2779{ 2780 rtx addr = XEXP (operands[1], 0); 2781 enum rtx_code code = GET_CODE (addr); 2782 2783 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT) 2784 || code == MINUS) 2785 addr = force_reg (SImode, addr); 2786 2787 operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1)); 2788 operands[1] = change_address (operands[1], QImode, NULL_RTX); 2789 operands[3] = gen_lowpart (QImode, operands[0]); 2790 operands[0] = gen_lowpart (SImode, operands[0]); 2791 operands[2] = gen_reg_rtx (SImode); 2792} 2793") 2794 2795;; Subroutine to store a half word integer constant into memory. 2796(define_expand "storeinthi" 2797 [(set (match_operand 0 "" "") 2798 (subreg:QI (match_operand 1 "" "") 0)) 2799 (set (match_dup 3) (subreg:QI (match_dup 2) 0))] 2800 "" 2801 " 2802{ 2803 HOST_WIDE_INT value = INTVAL (operands[1]); 2804 rtx addr = XEXP (operands[0], 0); 2805 enum rtx_code code = GET_CODE (addr); 2806 2807 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT) 2808 || code == MINUS) 2809 addr = force_reg (SImode, addr); 2810 2811 operands[1] = gen_reg_rtx (SImode); 2812 if (BYTES_BIG_ENDIAN) 2813 { 2814 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255))); 2815 if ((value & 255) == ((value >> 8) & 255)) 2816 operands[2] = operands[1]; 2817 else 2818 { 2819 operands[2] = gen_reg_rtx (SImode); 2820 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255))); 2821 } 2822 } 2823 else 2824 { 2825 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255))); 2826 if ((value & 255) == ((value >> 8) & 255)) 2827 operands[2] = operands[1]; 2828 else 2829 { 2830 operands[2] = gen_reg_rtx (SImode); 2831 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255))); 2832 } 2833 } 2834 2835 operands[3] = change_address (operands[0], QImode, plus_constant (addr, 1)); 2836 operands[0] = change_address (operands[0], QImode, NULL_RTX); 2837} 2838") 2839 2840(define_expand "storehi_single_op" 2841 [(set (match_operand:HI 0 "memory_operand" "") 2842 (match_operand:HI 1 "general_operand" ""))] 2843 "arm_arch4" 2844 " 2845 if (! s_register_operand (operands[1], HImode)) 2846 operands[1] = copy_to_mode_reg (HImode, operands[1]); 2847") 2848 2849(define_expand "movhi" 2850 [(set (match_operand:HI 0 "general_operand" "") 2851 (match_operand:HI 1 "general_operand" ""))] 2852 "" 2853 " 2854{ 2855 if (! (reload_in_progress || reload_completed)) 2856 { 2857 if (GET_CODE (operands[0]) == MEM) 2858 { 2859 if (arm_arch4) 2860 { 2861 emit_insn (gen_storehi_single_op (operands[0], operands[1])); 2862 DONE; 2863 } 2864 if (GET_CODE (operands[1]) == CONST_INT) 2865 emit_insn (gen_storeinthi (operands[0], operands[1])); 2866 else 2867 { 2868 if (GET_CODE (operands[1]) == MEM) 2869 operands[1] = force_reg (HImode, operands[1]); 2870 if (BYTES_BIG_ENDIAN) 2871 emit_insn (gen_storehi_bigend (operands[1], operands[0])); 2872 else 2873 emit_insn (gen_storehi (operands[1], operands[0])); 2874 } 2875 DONE; 2876 } 2877 /* Sign extend a constant, and keep it in an SImode reg. */ 2878 else if (GET_CODE (operands[1]) == CONST_INT) 2879 { 2880 rtx reg = gen_reg_rtx (SImode); 2881 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff; 2882 2883 /* If the constant is already valid, leave it alone. */ 2884 if (! const_ok_for_arm (val)) 2885 { 2886 /* If setting all the top bits will make the constant 2887 loadable in a single instruction, then set them. 2888 Otherwise, sign extend the number. */ 2889 2890 if (const_ok_for_arm (~ (val | ~0xffff))) 2891 val |= ~0xffff; 2892 else if (val & 0x8000) 2893 val |= ~0xffff; 2894 } 2895 2896 emit_insn (gen_movsi (reg, GEN_INT (val))); 2897 operands[1] = gen_rtx_SUBREG (HImode, reg, 0); 2898 } 2899 else if (! arm_arch4) 2900 { 2901 /* Note: We do not have to worry about TARGET_SHORT_BY_BYTES 2902 for v4 and up architectures because LDRH instructions will 2903 be used to access the HI values, and these cannot generate 2904 unaligned word access faults in the MMU. */ 2905 if (GET_CODE (operands[1]) == MEM) 2906 { 2907 if (TARGET_SHORT_BY_BYTES) 2908 { 2909 rtx base; 2910 rtx offset = const0_rtx; 2911 rtx reg = gen_reg_rtx (SImode); 2912 2913 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG 2914 || (GET_CODE (base) == PLUS 2915 && GET_CODE (offset = XEXP (base, 1)) == CONST_INT 2916 && ((INTVAL(offset) & 1) != 1) 2917 && GET_CODE (base = XEXP (base, 0)) == REG)) 2918 && REGNO_POINTER_ALIGN (REGNO (base)) >= 4) 2919 { 2920 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3; 2921 rtx new; 2922 2923 new = gen_rtx_MEM (SImode, 2924 plus_constant (base, new_offset)); 2925 MEM_COPY_ATTRIBUTES (new, operands[1]); 2926 RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]); 2927 emit_insn (gen_movsi (reg, new)); 2928 if (((INTVAL (offset) & 2) != 0) 2929 ^ (BYTES_BIG_ENDIAN ? 1 : 0)) 2930 { 2931 rtx reg2 = gen_reg_rtx (SImode); 2932 2933 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16))); 2934 reg = reg2; 2935 } 2936 } 2937 else 2938 emit_insn (gen_movhi_bytes (reg, operands[1])); 2939 2940 operands[1] = gen_lowpart (HImode, reg); 2941 } 2942 else if (BYTES_BIG_ENDIAN) 2943 { 2944 rtx base; 2945 rtx offset = const0_rtx; 2946 2947 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG 2948 || (GET_CODE (base) == PLUS 2949 && GET_CODE (offset = XEXP (base, 1)) == CONST_INT 2950 && GET_CODE (base = XEXP (base, 0)) == REG)) 2951 && REGNO_POINTER_ALIGN (REGNO (base)) >= 4) 2952 { 2953 rtx reg = gen_reg_rtx (SImode); 2954 rtx new; 2955 2956 if ((INTVAL (offset) & 2) == 2) 2957 { 2958 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2; 2959 new = gen_rtx_MEM (SImode, 2960 plus_constant (base, new_offset)); 2961 MEM_COPY_ATTRIBUTES (new, operands[1]); 2962 RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]); 2963 emit_insn (gen_movsi (reg, new)); 2964 } 2965 else 2966 { 2967 new = gen_rtx_MEM (SImode, XEXP (operands[1], 0)); 2968 MEM_COPY_ATTRIBUTES (new, operands[1]); 2969 RTX_UNCHANGING_P (new) 2970 = RTX_UNCHANGING_P (operands[1]); 2971 emit_insn (gen_rotated_loadsi (reg, new)); 2972 } 2973 2974 operands[1] = gen_lowpart (HImode, reg); 2975 } 2976 else 2977 { 2978 emit_insn (gen_movhi_bigend (operands[0], operands[1])); 2979 DONE; 2980 } 2981 } 2982 } 2983 } 2984 } 2985 /* Handle loading a large integer during reload */ 2986 else if (GET_CODE (operands[1]) == CONST_INT 2987 && ! const_ok_for_arm (INTVAL (operands[1])) 2988 && ! const_ok_for_arm (~INTVAL (operands[1]))) 2989 { 2990 /* Writing a constant to memory needs a scratch, which should 2991 be handled with SECONDARY_RELOADs. */ 2992 if (GET_CODE (operands[0]) != REG) 2993 abort (); 2994 2995 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0); 2996 emit_insn (gen_movsi (operands[0], operands[1])); 2997 DONE; 2998 } 2999} 3000") 3001 3002(define_insn "rotated_loadsi" 3003 [(set (match_operand:SI 0 "s_register_operand" "=r") 3004 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o") 3005 (const_int 16)))] 3006 "! TARGET_SHORT_BY_BYTES" 3007 "* 3008{ 3009 rtx ops[2]; 3010 3011 ops[0] = operands[0]; 3012 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2)); 3013 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops); 3014 return \"\"; 3015}" 3016[(set_attr "type" "load")]) 3017 3018(define_expand "movhi_bytes" 3019 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" ""))) 3020 (set (match_dup 3) 3021 (zero_extend:SI (match_dup 6))) 3022 (set (match_operand:SI 0 "" "") 3023 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))] 3024 "" 3025 " 3026{ 3027 rtx mem1, mem2; 3028 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); 3029 3030 mem1 = gen_rtx_MEM (QImode, addr); 3031 MEM_COPY_ATTRIBUTES (mem1, operands[1]); 3032 RTX_UNCHANGING_P (mem1) = RTX_UNCHANGING_P (operands[1]); 3033 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1)); 3034 MEM_COPY_ATTRIBUTES (mem2, operands[1]); 3035 RTX_UNCHANGING_P (mem2) = RTX_UNCHANGING_P (operands[1]); 3036 operands[0] = gen_lowpart (SImode, operands[0]); 3037 operands[1] = mem1; 3038 operands[2] = gen_reg_rtx (SImode); 3039 operands[3] = gen_reg_rtx (SImode); 3040 operands[6] = mem2; 3041 3042 if (BYTES_BIG_ENDIAN) 3043 { 3044 operands[4] = operands[2]; 3045 operands[5] = operands[3]; 3046 } 3047 else 3048 { 3049 operands[4] = operands[3]; 3050 operands[5] = operands[2]; 3051 } 3052} 3053") 3054 3055(define_expand "movhi_bigend" 3056 [(set (match_dup 2) 3057 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0) 3058 (const_int 16))) 3059 (set (match_dup 3) 3060 (ashiftrt:SI (match_dup 2) (const_int 16))) 3061 (set (match_operand:HI 0 "s_register_operand" "") 3062 (subreg:HI (match_dup 3) 0))] 3063 "" 3064 " 3065 operands[2] = gen_reg_rtx (SImode); 3066 operands[3] = gen_reg_rtx (SImode); 3067") 3068 3069;; Pattern to recognise insn generated default case above 3070(define_insn "*movhi_insn_arch4" 3071 [(set (match_operand:HI 0 "general_operand" "=r,r,r,m") 3072 (match_operand:HI 1 "general_operand" "rI,K,m,r"))] 3073 "arm_arch4 3074 && (GET_CODE (operands[1]) != CONST_INT 3075 || const_ok_for_arm (INTVAL (operands[1])) 3076 || const_ok_for_arm (~INTVAL (operands[1])))" 3077 "@ 3078 mov%?\\t%0, %1\\t%@ movhi 3079 mvn%?\\t%0, #%B1\\t%@ movhi 3080 ldr%?h\\t%0, %1\\t%@ movhi 3081 str%?h\\t%1, %0\\t%@ movhi" 3082[(set_attr "type" "*,*,load,store1")]) 3083 3084(define_insn "*movhi_insn_littleend" 3085 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r") 3086 (match_operand:HI 1 "general_operand" "rI,K,m"))] 3087 "! arm_arch4 3088 && ! BYTES_BIG_ENDIAN 3089 && ! TARGET_SHORT_BY_BYTES 3090 && (GET_CODE (operands[1]) != CONST_INT 3091 || const_ok_for_arm (INTVAL (operands[1])) 3092 || const_ok_for_arm (~INTVAL (operands[1])))" 3093 "@ 3094 mov%?\\t%0, %1\\t%@ movhi 3095 mvn%?\\t%0, #%B1\\t%@ movhi 3096 ldr%?\\t%0, %1\\t%@ movhi" 3097[(set_attr "type" "*,*,load")]) 3098 3099(define_insn "*movhi_insn_bigend" 3100 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r") 3101 (match_operand:HI 1 "general_operand" "rI,K,m"))] 3102 "! arm_arch4 3103 && BYTES_BIG_ENDIAN 3104 && ! TARGET_SHORT_BY_BYTES 3105 && (GET_CODE (operands[1]) != CONST_INT 3106 || const_ok_for_arm (INTVAL (operands[1])) 3107 || const_ok_for_arm (~INTVAL (operands[1])))" 3108 "@ 3109 mov%?\\t%0, %1\\t%@ movhi 3110 mvn%?\\t%0, #%B1\\t%@ movhi 3111 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16" 3112[(set_attr "type" "*,*,load") 3113 (set_attr "length" "4,4,8")]) 3114 3115(define_insn "*loadhi_si_bigend" 3116 [(set (match_operand:SI 0 "s_register_operand" "=r") 3117 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0) 3118 (const_int 16)))] 3119 "BYTES_BIG_ENDIAN 3120 && ! TARGET_SHORT_BY_BYTES" 3121 "ldr%?\\t%0, %1\\t%@ movhi_bigend" 3122[(set_attr "type" "load")]) 3123 3124(define_insn "*movhi_bytes" 3125 [(set (match_operand:HI 0 "s_register_operand" "=r,r") 3126 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))] 3127 "TARGET_SHORT_BY_BYTES" 3128 "@ 3129 mov%?\\t%0, %1\\t%@ movhi 3130 mvn%?\\t%0, #%B1\\t%@ movhi") 3131 3132;; We use a DImode scratch because we may occasionally need an additional 3133;; temporary if the address isn't offsettable -- push_reload doesn't seem 3134;; to take any notice of the "o" constraints on reload_memory_operand operand. 3135(define_expand "reload_outhi" 3136 [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o") 3137 (match_operand:HI 1 "s_register_operand" "r") 3138 (match_operand:DI 2 "s_register_operand" "=&r")])] 3139 "" 3140 " 3141 arm_reload_out_hi (operands); 3142 DONE; 3143") 3144 3145(define_expand "reload_inhi" 3146 [(parallel [(match_operand:HI 0 "s_register_operand" "=r") 3147 (match_operand:HI 1 "reload_memory_operand" "o") 3148 (match_operand:DI 2 "s_register_operand" "=&r")])] 3149 "TARGET_SHORT_BY_BYTES" 3150 " 3151 arm_reload_in_hi (operands); 3152 DONE; 3153") 3154 3155(define_expand "movqi" 3156 [(set (match_operand:QI 0 "general_operand" "") 3157 (match_operand:QI 1 "general_operand" ""))] 3158 "" 3159 " 3160 /* Everything except mem = const or mem = mem can be done easily */ 3161 3162 if (!(reload_in_progress || reload_completed)) 3163 { 3164 if (GET_CODE (operands[1]) == CONST_INT) 3165 { 3166 rtx reg = gen_reg_rtx (SImode); 3167 3168 emit_insn (gen_movsi (reg, operands[1])); 3169 operands[1] = gen_rtx_SUBREG (QImode, reg, 0); 3170 } 3171 if (GET_CODE (operands[0]) == MEM) 3172 operands[1] = force_reg (QImode, operands[1]); 3173 } 3174") 3175 3176 3177(define_insn "*movqi_insn" 3178 [(set (match_operand:QI 0 "general_operand" "=r,r,r,m") 3179 (match_operand:QI 1 "general_operand" "rI,K,m,r"))] 3180 "register_operand (operands[0], QImode) 3181 || register_operand (operands[1], QImode)" 3182 "@ 3183 mov%?\\t%0, %1 3184 mvn%?\\t%0, #%B1 3185 ldr%?b\\t%0, %1 3186 str%?b\\t%1, %0" 3187[(set_attr "type" "*,*,load,store1")]) 3188 3189(define_expand "movsf" 3190 [(set (match_operand:SF 0 "general_operand" "") 3191 (match_operand:SF 1 "general_operand" ""))] 3192 "" 3193 " 3194 if (GET_CODE (operands[0]) == MEM) 3195 operands[1] = force_reg (SFmode, operands[1]); 3196") 3197 3198(define_insn "*movsf_hard_insn" 3199 [(set (match_operand:SF 0 "general_operand" "=f,f,f,m,f,r,r,r,m") 3200 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))] 3201 "TARGET_HARD_FLOAT 3202 && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))" 3203 "@ 3204 mvf%?s\\t%0, %1 3205 mnf%?s\\t%0, #%N1 3206 ldf%?s\\t%0, %1 3207 stf%?s\\t%1, %0 3208 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4 3209 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4 3210 mov%?\\t%0, %1 3211 ldr%?\\t%0, %1\\t%@ float 3212 str%?\\t%1, %0\\t%@ float" 3213[(set_attr "length" "4,4,4,4,8,8,4,4,4") 3214 (set_attr "type" 3215 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")]) 3216 3217;; Exactly the same as above, except that all `f' cases are deleted. 3218;; This is necessary to prevent reload from ever trying to use a `f' reg 3219;; when -msoft-float. 3220 3221(define_insn "*movsf_soft_insn" 3222 [(set (match_operand:SF 0 "general_operand" "=r,r,m") 3223 (match_operand:SF 1 "general_operand" "r,mE,r"))] 3224 "TARGET_SOFT_FLOAT 3225 && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))" 3226 "@ 3227 mov%?\\t%0, %1 3228 ldr%?\\t%0, %1\\t%@ float 3229 str%?\\t%1, %0\\t%@ float" 3230[(set_attr "length" "4,4,4") 3231 (set_attr "type" "*,load,store1")]) 3232 3233(define_expand "movdf" 3234 [(set (match_operand:DF 0 "general_operand" "") 3235 (match_operand:DF 1 "general_operand" ""))] 3236 "" 3237 " 3238 if (GET_CODE (operands[0]) == MEM) 3239 operands[1] = force_reg (DFmode, operands[1]); 3240") 3241 3242;; Reloading a df mode value stored in integer regs to memory can require a 3243;; scratch reg. 3244(define_expand "reload_outdf" 3245 [(match_operand:DF 0 "reload_memory_operand" "=o") 3246 (match_operand:DF 1 "s_register_operand" "r") 3247 (match_operand:SI 2 "s_register_operand" "=&r")] 3248 "" 3249 " 3250{ 3251 enum rtx_code code = GET_CODE (XEXP (operands[0], 0)); 3252 3253 if (code == REG) 3254 operands[2] = XEXP (operands[0], 0); 3255 else if (code == POST_INC || code == PRE_DEC) 3256 { 3257 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); 3258 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0); 3259 emit_insn (gen_movdi (operands[0], operands[1])); 3260 DONE; 3261 } 3262 else if (code == PRE_INC) 3263 { 3264 rtx reg = XEXP (XEXP (operands[0], 0), 0); 3265 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8))); 3266 operands[2] = reg; 3267 } 3268 else if (code == POST_DEC) 3269 operands[2] = XEXP (XEXP (operands[0], 0), 0); 3270 else 3271 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0), 3272 XEXP (XEXP (operands[0], 0), 1))); 3273 3274 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]), 3275 operands[1])); 3276 3277 if (code == POST_DEC) 3278 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8))); 3279 3280 DONE; 3281} 3282") 3283 3284(define_insn "*movdf_hard_insn" 3285 [(set (match_operand:DF 0 "general_operand" "=r,Q,r,m,r,f,f,f,m,!f,!r") 3286 (match_operand:DF 1 "general_operand" "Q,r,r,r,mF,fG,H,mF,f,r,f"))] 3287 "TARGET_HARD_FLOAT 3288 && (GET_CODE (operands[0]) != MEM 3289 || register_operand (operands[1], DFmode))" 3290 "* 3291{ 3292 switch (which_alternative) 3293 { 3294 default: 3295 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\"; 3296 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\"; 3297 case 2: case 3: case 4: return output_move_double (operands); 3298 case 5: return \"mvf%?d\\t%0, %1\"; 3299 case 6: return \"mnf%?d\\t%0, #%N1\"; 3300 case 7: return \"ldf%?d\\t%0, %1\"; 3301 case 8: return \"stf%?d\\t%1, %0\"; 3302 case 9: return output_mov_double_fpu_from_arm (operands); 3303 case 10: return output_mov_double_arm_from_fpu (operands); 3304 } 3305} 3306" 3307[(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8") 3308 (set_attr "type" 3309"load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")]) 3310 3311;; Software floating point version. This is essentially the same as movdi. 3312;; Do not use `f' as a constraint to prevent reload from ever trying to use 3313;; an `f' reg. 3314 3315(define_insn "*movdf_soft_insn" 3316 [(set (match_operand:DF 0 "soft_df_operand" "=r,r,m") 3317 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))] 3318 "TARGET_SOFT_FLOAT" 3319 "* return output_move_double (operands);" 3320[(set_attr "length" "8,8,8") 3321 (set_attr "type" "*,load,store2")]) 3322 3323(define_expand "movxf" 3324 [(set (match_operand:XF 0 "general_operand" "") 3325 (match_operand:XF 1 "general_operand" ""))] 3326 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 3327 "") 3328 3329;; Even when the XFmode patterns aren't enabled, we enable this after 3330;; reloading so that we can push floating point registers in the prologue. 3331 3332(define_insn "*movxf_hard_insn" 3333 [(set (match_operand:XF 0 "general_operand" "=f,f,f,m,f,r,r") 3334 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))] 3335 "TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)" 3336 "* 3337 switch (which_alternative) 3338 { 3339 default: 3340 case 0: return \"mvf%?e\\t%0, %1\"; 3341 case 1: return \"mnf%?e\\t%0, #%N1\"; 3342 case 2: return \"ldf%?e\\t%0, %1\"; 3343 case 3: return \"stf%?e\\t%1, %0\"; 3344 case 4: return output_mov_long_double_fpu_from_arm (operands); 3345 case 5: return output_mov_long_double_arm_from_fpu (operands); 3346 case 6: return output_mov_long_double_arm_from_arm (operands); 3347 } 3348" 3349[(set_attr "length" "4,4,4,4,8,8,12") 3350 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")]) 3351 3352 3353;; load- and store-multiple insns 3354;; The arm can load/store any set of registers, provided that they are in 3355;; ascending order; but that is beyond GCC so stick with what it knows. 3356 3357(define_expand "load_multiple" 3358 [(match_par_dup 3 [(set (match_operand:SI 0 "" "") 3359 (match_operand:SI 1 "" "")) 3360 (use (match_operand:SI 2 "" ""))])] 3361 "" 3362 " 3363 /* Support only fixed point registers */ 3364 if (GET_CODE (operands[2]) != CONST_INT 3365 || INTVAL (operands[2]) > 14 3366 || INTVAL (operands[2]) < 2 3367 || GET_CODE (operands[1]) != MEM 3368 || GET_CODE (operands[0]) != REG 3369 || REGNO (operands[0]) > 14 3370 || REGNO (operands[0]) + INTVAL (operands[2]) > 15) 3371 FAIL; 3372 3373 operands[3] 3374 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]), 3375 force_reg (SImode, XEXP (operands[1], 0)), 3376 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]), 3377 MEM_IN_STRUCT_P(operands[1]), 3378 MEM_SCALAR_P (operands[1])); 3379") 3380 3381;; Load multiple with write-back 3382 3383(define_insn "*ldmsi_postinc" 3384 [(match_parallel 0 "load_multiple_operation" 3385 [(set (match_operand:SI 1 "s_register_operand" "+r") 3386 (plus:SI (match_dup 1) 3387 (match_operand:SI 2 "const_int_operand" "n"))) 3388 (set (match_operand:SI 3 "s_register_operand" "=r") 3389 (mem:SI (match_dup 1)))])] 3390 "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))" 3391 "* 3392{ 3393 rtx ops[3]; 3394 int count = XVECLEN (operands[0], 0); 3395 3396 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0); 3397 ops[1] = SET_DEST (XVECEXP (operands[0], 0, 1)); 3398 ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 2)); 3399 3400 output_asm_insn (\"ldm%?ia\\t%0!, {%1-%2}\\t%@ load multiple\", ops); 3401 return \"\"; 3402} 3403" 3404[(set_attr "type" "load")]) 3405 3406;; Ordinary load multiple 3407 3408(define_insn "*ldmsi" 3409 [(match_parallel 0 "load_multiple_operation" 3410 [(set (match_operand:SI 1 "s_register_operand" "=r") 3411 (mem:SI (match_operand:SI 2 "s_register_operand" "r")))])] 3412 "" 3413 "* 3414{ 3415 rtx ops[3]; 3416 int count = XVECLEN (operands[0], 0); 3417 3418 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0); 3419 ops[1] = SET_DEST (XVECEXP (operands[0], 0, 0)); 3420 ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1)); 3421 3422 output_asm_insn (\"ldm%?ia\\t%0, {%1-%2}\\t%@ load multiple\", ops); 3423 return \"\"; 3424} 3425" 3426[(set_attr "type" "load")]) 3427 3428(define_expand "store_multiple" 3429 [(match_par_dup 3 [(set (match_operand:SI 0 "" "") 3430 (match_operand:SI 1 "" "")) 3431 (use (match_operand:SI 2 "" ""))])] 3432 "" 3433 " 3434 /* Support only fixed point registers */ 3435 if (GET_CODE (operands[2]) != CONST_INT 3436 || INTVAL (operands[2]) > 14 3437 || INTVAL (operands[2]) < 2 3438 || GET_CODE (operands[1]) != REG 3439 || GET_CODE (operands[0]) != MEM 3440 || REGNO (operands[1]) > 14 3441 || REGNO (operands[1]) + INTVAL (operands[2]) > 15) 3442 FAIL; 3443 3444 operands[3] 3445 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]), 3446 force_reg (SImode, XEXP (operands[0], 0)), 3447 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]), 3448 MEM_IN_STRUCT_P(operands[0]), 3449 MEM_SCALAR_P (operands[0])); 3450") 3451 3452;; Store multiple with write-back 3453 3454(define_insn "*stmsi_postinc" 3455 [(match_parallel 0 "store_multiple_operation" 3456 [(set (match_operand:SI 1 "s_register_operand" "+r") 3457 (plus:SI (match_dup 1) 3458 (match_operand:SI 2 "const_int_operand" "n"))) 3459 (set (mem:SI (match_dup 1)) 3460 (match_operand:SI 3 "s_register_operand" "r"))])] 3461 "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))" 3462 "* 3463{ 3464 rtx ops[3]; 3465 int count = XVECLEN (operands[0], 0); 3466 3467 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0); 3468 ops[1] = SET_SRC (XVECEXP (operands[0], 0, 1)); 3469 ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 2)); 3470 3471 output_asm_insn (\"stm%?ia\\t%0!, {%1-%2}\\t%@ str multiple\", ops); 3472 return \"\"; 3473} 3474" 3475[(set (attr "type") 3476 (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4)) 3477 (const_string "store2") 3478 (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 5)) 3479 (const_string "store3")] 3480 (const_string "store4")))]) 3481 3482;; Ordinary store multiple 3483 3484(define_insn "*stmsi" 3485 [(match_parallel 0 "store_multiple_operation" 3486 [(set (mem:SI (match_operand:SI 2 "s_register_operand" "r")) 3487 (match_operand:SI 1 "s_register_operand" "r"))])] 3488 "" 3489 "* 3490{ 3491 rtx ops[3]; 3492 int count = XVECLEN (operands[0], 0); 3493 3494 ops[0] = XEXP (SET_DEST (XVECEXP (operands[0], 0, 0)), 0); 3495 ops[1] = SET_SRC (XVECEXP (operands[0], 0, 0)); 3496 ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1)); 3497 3498 output_asm_insn (\"stm%?ia\\t%0, {%1-%2}\\t%@ str multiple\", ops); 3499 return \"\"; 3500} 3501" 3502[(set (attr "type") 3503 (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3)) 3504 (const_string "store2") 3505 (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4)) 3506 (const_string "store3")] 3507 (const_string "store4")))]) 3508 3509;; Move a block of memory if it is word aligned and MORE than 2 words long. 3510;; We could let this apply for blocks of less than this, but it clobbers so 3511;; many registers that there is then probably a better way. 3512 3513(define_expand "movstrqi" 3514 [(match_operand:BLK 0 "general_operand" "") 3515 (match_operand:BLK 1 "general_operand" "") 3516 (match_operand:SI 2 "const_int_operand" "") 3517 (match_operand:SI 3 "const_int_operand" "")] 3518 "" 3519 " 3520 if (arm_gen_movstrqi (operands)) 3521 DONE; 3522 FAIL; 3523") 3524 3525 3526;; Comparison and test insns 3527 3528(define_expand "cmpsi" 3529 [(match_operand:SI 0 "s_register_operand" "") 3530 (match_operand:SI 1 "arm_add_operand" "")] 3531 "" 3532 " 3533{ 3534 arm_compare_op0 = operands[0]; 3535 arm_compare_op1 = operands[1]; 3536 DONE; 3537} 3538") 3539 3540(define_expand "cmpsf" 3541 [(match_operand:SF 0 "s_register_operand" "") 3542 (match_operand:SF 1 "fpu_rhs_operand" "")] 3543 "TARGET_HARD_FLOAT" 3544 " 3545{ 3546 arm_compare_op0 = operands[0]; 3547 arm_compare_op1 = operands[1]; 3548 DONE; 3549} 3550") 3551 3552(define_expand "cmpdf" 3553 [(match_operand:DF 0 "s_register_operand" "") 3554 (match_operand:DF 1 "fpu_rhs_operand" "")] 3555 "TARGET_HARD_FLOAT" 3556 " 3557{ 3558 arm_compare_op0 = operands[0]; 3559 arm_compare_op1 = operands[1]; 3560 DONE; 3561} 3562") 3563 3564(define_expand "cmpxf" 3565 [(match_operand:XF 0 "s_register_operand" "") 3566 (match_operand:XF 1 "fpu_rhs_operand" "")] 3567 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 3568 " 3569{ 3570 arm_compare_op0 = operands[0]; 3571 arm_compare_op1 = operands[1]; 3572 DONE; 3573} 3574") 3575 3576(define_insn "*cmpsi_insn" 3577 [(set (reg:CC 24) 3578 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r") 3579 (match_operand:SI 1 "arm_add_operand" "rI,L")))] 3580 "" 3581 "@ 3582 cmp%?\\t%0, %1 3583 cmn%?\\t%0, #%n1" 3584[(set_attr "conds" "set")]) 3585 3586(define_insn "*cmpsi_shiftsi" 3587 [(set (reg:CC 24) 3588 (compare:CC (match_operand:SI 0 "s_register_operand" "r") 3589 (match_operator:SI 3 "shift_operator" 3590 [(match_operand:SI 1 "s_register_operand" "r") 3591 (match_operand:SI 2 "arm_rhs_operand" "rM")])))] 3592 "" 3593 "cmp%?\\t%0, %1%S3" 3594[(set_attr "conds" "set")]) 3595 3596(define_insn "*cmpsi_shiftsi_swp" 3597 [(set (reg:CC_SWP 24) 3598 (compare:CC_SWP (match_operator:SI 3 "shift_operator" 3599 [(match_operand:SI 1 "s_register_operand" "r") 3600 (match_operand:SI 2 "reg_or_int_operand" "rM")]) 3601 (match_operand:SI 0 "s_register_operand" "r")))] 3602 "" 3603 "cmp%?\\t%0, %1%S3" 3604[(set_attr "conds" "set")]) 3605 3606(define_insn "*cmpsi_neg_shiftsi" 3607 [(set (reg:CC 24) 3608 (compare:CC (match_operand:SI 0 "s_register_operand" "r") 3609 (neg:SI (match_operator:SI 3 "shift_operator" 3610 [(match_operand:SI 1 "s_register_operand" "r") 3611 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))] 3612 "" 3613 "cmn%?\\t%0, %1%S3" 3614[(set_attr "conds" "set")]) 3615 3616(define_insn "*cmpsf_insn" 3617 [(set (reg:CCFP 24) 3618 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f") 3619 (match_operand:SF 1 "fpu_add_operand" "fG,H")))] 3620 "TARGET_HARD_FLOAT" 3621 "@ 3622 cmf%?\\t%0, %1 3623 cnf%?\\t%0, #%N1" 3624[(set_attr "conds" "set") 3625 (set_attr "type" "f_2_r")]) 3626 3627(define_insn "*cmpdf_insn" 3628 [(set (reg:CCFP 24) 3629 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f") 3630 (match_operand:DF 1 "fpu_add_operand" "fG,H")))] 3631 "TARGET_HARD_FLOAT" 3632 "@ 3633 cmf%?\\t%0, %1 3634 cnf%?\\t%0, #%N1" 3635[(set_attr "conds" "set") 3636 (set_attr "type" "f_2_r")]) 3637 3638(define_insn "*cmpesfdf_df" 3639 [(set (reg:CCFP 24) 3640 (compare:CCFP (float_extend:DF 3641 (match_operand:SF 0 "s_register_operand" "f,f")) 3642 (match_operand:DF 1 "fpu_add_operand" "fG,H")))] 3643 "TARGET_HARD_FLOAT" 3644 "@ 3645 cmf%?\\t%0, %1 3646 cnf%?\\t%0, #%N1" 3647[(set_attr "conds" "set") 3648 (set_attr "type" "f_2_r")]) 3649 3650(define_insn "*cmpdf_esfdf" 3651 [(set (reg:CCFP 24) 3652 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f") 3653 (float_extend:DF 3654 (match_operand:SF 1 "s_register_operand" "f"))))] 3655 "TARGET_HARD_FLOAT" 3656 "cmf%?\\t%0, %1" 3657[(set_attr "conds" "set") 3658 (set_attr "type" "f_2_r")]) 3659 3660(define_insn "*cmpxf_insn" 3661 [(set (reg:CCFP 24) 3662 (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f") 3663 (match_operand:XF 1 "fpu_add_operand" "fG,H")))] 3664 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 3665 "@ 3666 cmf%?\\t%0, %1 3667 cnf%?\\t%0, #%N1" 3668[(set_attr "conds" "set") 3669 (set_attr "type" "f_2_r")]) 3670 3671(define_insn "*cmpsf_trap" 3672 [(set (reg:CCFPE 24) 3673 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f") 3674 (match_operand:SF 1 "fpu_add_operand" "fG,H")))] 3675 "TARGET_HARD_FLOAT" 3676 "@ 3677 cmf%?e\\t%0, %1 3678 cnf%?e\\t%0, #%N1" 3679[(set_attr "conds" "set") 3680 (set_attr "type" "f_2_r")]) 3681 3682(define_insn "*cmpdf_trap" 3683 [(set (reg:CCFPE 24) 3684 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f") 3685 (match_operand:DF 1 "fpu_add_operand" "fG,H")))] 3686 "TARGET_HARD_FLOAT" 3687 "@ 3688 cmf%?e\\t%0, %1 3689 cnf%?e\\t%0, #%N1" 3690[(set_attr "conds" "set") 3691 (set_attr "type" "f_2_r")]) 3692 3693(define_insn "*cmp_esfdf_df_trap" 3694 [(set (reg:CCFPE 24) 3695 (compare:CCFPE (float_extend:DF 3696 (match_operand:SF 0 "s_register_operand" "f,f")) 3697 (match_operand:DF 1 "fpu_add_operand" "fG,H")))] 3698 "TARGET_HARD_FLOAT" 3699 "@ 3700 cmf%?e\\t%0, %1 3701 cnf%?e\\t%0, #%N1" 3702[(set_attr "conds" "set") 3703 (set_attr "type" "f_2_r")]) 3704 3705(define_insn "*cmp_df_esfdf_trap" 3706 [(set (reg:CCFPE 24) 3707 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f") 3708 (float_extend:DF 3709 (match_operand:SF 1 "s_register_operand" "f"))))] 3710 "TARGET_HARD_FLOAT" 3711 "cmf%?e\\t%0, %1" 3712[(set_attr "conds" "set") 3713 (set_attr "type" "f_2_r")]) 3714 3715(define_insn "*cmpxf_trap" 3716 [(set (reg:CCFPE 24) 3717 (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f") 3718 (match_operand:XF 1 "fpu_add_operand" "fG,H")))] 3719 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT" 3720 "@ 3721 cmf%?e\\t%0, %1 3722 cnf%?e\\t%0, #%N1" 3723[(set_attr "conds" "set") 3724 (set_attr "type" "f_2_r")]) 3725 3726; This insn allows redundant compares to be removed by cse, nothing should 3727; ever appear in the output file since (set (reg x) (reg x)) is a no-op that 3728; is deleted later on. The match_dup will match the mode here, so that 3729; mode changes of the condition codes aren't lost by this even though we don't 3730; specify what they are. 3731 3732(define_insn "*deleted_compare" 3733 [(set (match_operand 0 "cc_register" "") (match_dup 0))] 3734 "" 3735 "\\t%@ deleted compare" 3736[(set_attr "conds" "set") 3737 (set_attr "length" "0")]) 3738 3739 3740;; Conditional branch insns 3741 3742(define_expand "beq" 3743 [(set (pc) 3744 (if_then_else (eq (match_dup 1) (const_int 0)) 3745 (label_ref (match_operand 0 "" "")) 3746 (pc)))] 3747 "" 3748 " 3749{ 3750 operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1); 3751} 3752") 3753 3754(define_expand "bne" 3755 [(set (pc) 3756 (if_then_else (ne (match_dup 1) (const_int 0)) 3757 (label_ref (match_operand 0 "" "")) 3758 (pc)))] 3759 "" 3760 " 3761{ 3762 operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1); 3763} 3764") 3765 3766(define_expand "bgt" 3767 [(set (pc) 3768 (if_then_else (gt (match_dup 1) (const_int 0)) 3769 (label_ref (match_operand 0 "" "")) 3770 (pc)))] 3771 "" 3772 " 3773{ 3774 operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1); 3775} 3776") 3777 3778(define_expand "ble" 3779 [(set (pc) 3780 (if_then_else (le (match_dup 1) (const_int 0)) 3781 (label_ref (match_operand 0 "" "")) 3782 (pc)))] 3783 "" 3784 " 3785{ 3786 operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1); 3787} 3788") 3789 3790(define_expand "bge" 3791 [(set (pc) 3792 (if_then_else (ge (match_dup 1) (const_int 0)) 3793 (label_ref (match_operand 0 "" "")) 3794 (pc)))] 3795 "" 3796 " 3797{ 3798 operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1); 3799} 3800") 3801 3802(define_expand "blt" 3803 [(set (pc) 3804 (if_then_else (lt (match_dup 1) (const_int 0)) 3805 (label_ref (match_operand 0 "" "")) 3806 (pc)))] 3807 "" 3808 " 3809{ 3810 operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1); 3811} 3812") 3813 3814(define_expand "bgtu" 3815 [(set (pc) 3816 (if_then_else (gtu (match_dup 1) (const_int 0)) 3817 (label_ref (match_operand 0 "" "")) 3818 (pc)))] 3819 "" 3820 " 3821{ 3822 operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1); 3823} 3824") 3825 3826(define_expand "bleu" 3827 [(set (pc) 3828 (if_then_else (leu (match_dup 1) (const_int 0)) 3829 (label_ref (match_operand 0 "" "")) 3830 (pc)))] 3831 "" 3832 " 3833{ 3834 operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1); 3835} 3836") 3837 3838(define_expand "bgeu" 3839 [(set (pc) 3840 (if_then_else (geu (match_dup 1) (const_int 0)) 3841 (label_ref (match_operand 0 "" "")) 3842 (pc)))] 3843 "" 3844 " 3845{ 3846 operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1); 3847} 3848") 3849 3850(define_expand "bltu" 3851 [(set (pc) 3852 (if_then_else (ltu (match_dup 1) (const_int 0)) 3853 (label_ref (match_operand 0 "" "")) 3854 (pc)))] 3855 "" 3856 " 3857{ 3858 operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1); 3859} 3860") 3861 3862;; patterns to match conditional branch insns 3863 3864(define_insn "*condbranch" 3865 [(set (pc) 3866 (if_then_else (match_operator 1 "comparison_operator" 3867 [(match_operand 2 "cc_register" "") (const_int 0)]) 3868 (label_ref (match_operand 0 "" "")) 3869 (pc)))] 3870 "" 3871 "* 3872{ 3873 extern int arm_ccfsm_state; 3874 3875 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) 3876 { 3877 arm_ccfsm_state += 2; 3878 return \"\"; 3879 } 3880 return \"b%d1\\t%l0\"; 3881}" 3882[(set_attr "conds" "use")]) 3883 3884(define_insn "*condbranch_reversed" 3885 [(set (pc) 3886 (if_then_else (match_operator 1 "comparison_operator" 3887 [(match_operand 2 "cc_register" "") (const_int 0)]) 3888 (pc) 3889 (label_ref (match_operand 0 "" ""))))] 3890 "" 3891 "* 3892{ 3893 extern int arm_ccfsm_state; 3894 3895 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) 3896 { 3897 arm_ccfsm_state += 2; 3898 return \"\"; 3899 } 3900 return \"b%D1\\t%l0\"; 3901}" 3902[(set_attr "conds" "use")]) 3903 3904 3905; scc insns 3906 3907(define_expand "seq" 3908 [(set (match_operand:SI 0 "s_register_operand" "=r") 3909 (eq:SI (match_dup 1) (const_int 0)))] 3910 "" 3911 " 3912{ 3913 operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1); 3914} 3915") 3916 3917(define_expand "sne" 3918 [(set (match_operand:SI 0 "s_register_operand" "=r") 3919 (ne:SI (match_dup 1) (const_int 0)))] 3920 "" 3921 " 3922{ 3923 operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1); 3924} 3925") 3926 3927(define_expand "sgt" 3928 [(set (match_operand:SI 0 "s_register_operand" "=r") 3929 (gt:SI (match_dup 1) (const_int 0)))] 3930 "" 3931 " 3932{ 3933 operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1); 3934} 3935") 3936 3937(define_expand "sle" 3938 [(set (match_operand:SI 0 "s_register_operand" "=r") 3939 (le:SI (match_dup 1) (const_int 0)))] 3940 "" 3941 " 3942{ 3943 operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1); 3944} 3945") 3946 3947(define_expand "sge" 3948 [(set (match_operand:SI 0 "s_register_operand" "=r") 3949 (ge:SI (match_dup 1) (const_int 0)))] 3950 "" 3951 " 3952{ 3953 operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1); 3954} 3955") 3956 3957(define_expand "slt" 3958 [(set (match_operand:SI 0 "s_register_operand" "=r") 3959 (lt:SI (match_dup 1) (const_int 0)))] 3960 "" 3961 " 3962{ 3963 operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1); 3964} 3965") 3966 3967(define_expand "sgtu" 3968 [(set (match_operand:SI 0 "s_register_operand" "=r") 3969 (gtu:SI (match_dup 1) (const_int 0)))] 3970 "" 3971 " 3972{ 3973 operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1); 3974} 3975") 3976 3977(define_expand "sleu" 3978 [(set (match_operand:SI 0 "s_register_operand" "=r") 3979 (leu:SI (match_dup 1) (const_int 0)))] 3980 "" 3981 " 3982{ 3983 operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1); 3984} 3985") 3986 3987(define_expand "sgeu" 3988 [(set (match_operand:SI 0 "s_register_operand" "=r") 3989 (geu:SI (match_dup 1) (const_int 0)))] 3990 "" 3991 " 3992{ 3993 operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1); 3994} 3995") 3996 3997(define_expand "sltu" 3998 [(set (match_operand:SI 0 "s_register_operand" "=r") 3999 (ltu:SI (match_dup 1) (const_int 0)))] 4000 "" 4001 " 4002{ 4003 operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1); 4004} 4005") 4006 4007(define_insn "*mov_scc" 4008 [(set (match_operand:SI 0 "s_register_operand" "=r") 4009 (match_operator:SI 1 "comparison_operator" 4010 [(match_operand 2 "cc_register" "") (const_int 0)]))] 4011 "" 4012 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1" 4013[(set_attr "conds" "use") 4014 (set_attr "length" "8")]) 4015 4016(define_insn "*mov_negscc" 4017 [(set (match_operand:SI 0 "s_register_operand" "=r") 4018 (neg:SI (match_operator:SI 1 "comparison_operator" 4019 [(match_operand 2 "cc_register" "") (const_int 0)])))] 4020 "" 4021 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0" 4022[(set_attr "conds" "use") 4023 (set_attr "length" "8")]) 4024 4025(define_insn "*mov_notscc" 4026 [(set (match_operand:SI 0 "s_register_operand" "=r") 4027 (not:SI (match_operator:SI 1 "comparison_operator" 4028 [(match_operand 2 "cc_register" "") (const_int 0)])))] 4029 "" 4030 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1" 4031[(set_attr "conds" "use") 4032 (set_attr "length" "8")]) 4033 4034 4035;; Conditional move insns 4036 4037(define_expand "movsicc" 4038 [(set (match_operand:SI 0 "s_register_operand" "") 4039 (if_then_else:SI (match_operand 1 "comparison_operator" "") 4040 (match_operand:SI 2 "arm_not_operand" "") 4041 (match_operand:SI 3 "arm_not_operand" "")))] 4042 "" 4043 " 4044{ 4045 enum rtx_code code = GET_CODE (operands[1]); 4046 rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1); 4047 4048 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); 4049}") 4050 4051(define_expand "movsfcc" 4052 [(set (match_operand:SF 0 "s_register_operand" "") 4053 (if_then_else:SF (match_operand 1 "comparison_operator" "") 4054 (match_operand:SF 2 "s_register_operand" "") 4055 (match_operand:SF 3 "nonmemory_operand" "")))] 4056 "" 4057 " 4058{ 4059 enum rtx_code code = GET_CODE (operands[1]); 4060 rtx ccreg; 4061 4062 /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 4063 Otherwise, ensure it is a valid FP add operand */ 4064 if ((! TARGET_HARD_FLOAT) 4065 || (! fpu_add_operand (operands[3], SFmode))) 4066 operands[3] = force_reg (SFmode, operands[3]); 4067 4068 ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1); 4069 4070 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); 4071}") 4072 4073(define_expand "movdfcc" 4074 [(set (match_operand:DF 0 "s_register_operand" "") 4075 (if_then_else:DF (match_operand 1 "comparison_operator" "") 4076 (match_operand:DF 2 "s_register_operand" "") 4077 (match_operand:DF 3 "fpu_add_operand" "")))] 4078 "TARGET_HARD_FLOAT" 4079 " 4080{ 4081 enum rtx_code code = GET_CODE (operands[1]); 4082 rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1); 4083 4084 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); 4085}") 4086 4087(define_insn "*movsicc_insn" 4088 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r") 4089 (if_then_else:SI 4090 (match_operator 3 "comparison_operator" 4091 [(match_operand 4 "cc_register" "") (const_int 0)]) 4092 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K") 4093 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))] 4094 "" 4095 "@ 4096 mov%D3\\t%0, %2 4097 mvn%D3\\t%0, #%B2 4098 mov%d3\\t%0, %1 4099 mvn%d3\\t%0, #%B1 4100 mov%d3\\t%0, %1\;mov%D3\\t%0, %2 4101 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2 4102 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2 4103 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2" 4104 [(set_attr "length" "4,4,4,4,8,8,8,8") 4105 (set_attr "conds" "use")]) 4106 4107(define_insn "*movsfcc_hard_insn" 4108 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f") 4109 (if_then_else:SF 4110 (match_operator 3 "comparison_operator" 4111 [(match_operand 4 "cc_register" "") (const_int 0)]) 4112 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H") 4113 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))] 4114 "TARGET_HARD_FLOAT" 4115 "@ 4116 mvf%D3s\\t%0, %2 4117 mnf%D3s\\t%0, #%N2 4118 mvf%d3s\\t%0, %1 4119 mnf%d3s\\t%0, #%N1 4120 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2 4121 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2 4122 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2 4123 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2" 4124 [(set_attr "length" "4,4,4,4,8,8,8,8") 4125 (set_attr "type" "ffarith") 4126 (set_attr "conds" "use")]) 4127 4128(define_insn "*movsfcc_soft_insn" 4129 [(set (match_operand:SF 0 "s_register_operand" "=r,r") 4130 (if_then_else:SF (match_operator 3 "comparison_operator" 4131 [(match_operand 4 "cc_register" "") (const_int 0)]) 4132 (match_operand:SF 1 "s_register_operand" "0,r") 4133 (match_operand:SF 2 "s_register_operand" "r,0")))] 4134 "TARGET_SOFT_FLOAT" 4135 "@ 4136 mov%D3\\t%0, %2 4137 mov%d3\\t%0, %1" 4138 [(set_attr "conds" "use")]) 4139 4140(define_insn "*movdfcc_insn" 4141 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f") 4142 (if_then_else:DF 4143 (match_operator 3 "comparison_operator" 4144 [(match_operand 4 "cc_register" "") (const_int 0)]) 4145 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H") 4146 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))] 4147 "TARGET_HARD_FLOAT" 4148 "@ 4149 mvf%D3d\\t%0, %2 4150 mnf%D3d\\t%0, #%N2 4151 mvf%d3d\\t%0, %1 4152 mnf%d3d\\t%0, #%N1 4153 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2 4154 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2 4155 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2 4156 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2" 4157 [(set_attr "length" "4,4,4,4,8,8,8,8") 4158 (set_attr "type" "ffarith") 4159 (set_attr "conds" "use")]) 4160 4161;; Jump and linkage insns 4162 4163(define_insn "jump" 4164 [(set (pc) 4165 (label_ref (match_operand 0 "" "")))] 4166 "" 4167 "* 4168{ 4169 extern int arm_ccfsm_state; 4170 4171 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) 4172 { 4173 arm_ccfsm_state += 2; 4174 return \"\"; 4175 } 4176 return \"b%?\\t%l0\"; 4177}") 4178 4179(define_expand "call" 4180 [(parallel [(call (match_operand 0 "memory_operand" "") 4181 (match_operand 1 "general_operand" "")) 4182 (clobber (reg:SI 14))])] 4183 "" 4184 "") 4185 4186(define_insn "*call_reg" 4187 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r")) 4188 (match_operand 1 "" "g")) 4189 (clobber (reg:SI 14))] 4190 "" 4191 "* 4192 return output_call (operands); 4193" 4194;; length is worst case, normally it is only two 4195[(set_attr "length" "12") 4196 (set_attr "type" "call")]) 4197 4198(define_insn "*call_mem" 4199 [(call (mem:SI (match_operand 0 "memory_operand" "m")) 4200 (match_operand 1 "general_operand" "g")) 4201 (clobber (reg:SI 14))] 4202 "" 4203 "* 4204 return output_call_mem (operands); 4205" 4206[(set_attr "length" "12") 4207 (set_attr "type" "call")]) 4208 4209(define_expand "call_value" 4210 [(parallel [(set (match_operand 0 "" "=rf") 4211 (call (match_operand 1 "memory_operand" "m") 4212 (match_operand 2 "general_operand" "g"))) 4213 (clobber (reg:SI 14))])] 4214 "" 4215 "") 4216 4217(define_insn "*call_value_reg" 4218 [(set (match_operand 0 "" "=rf") 4219 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r")) 4220 (match_operand 2 "general_operand" "g"))) 4221 (clobber (reg:SI 14))] 4222 "" 4223 "* 4224 return output_call (&operands[1]); 4225" 4226[(set_attr "length" "12") 4227 (set_attr "type" "call")]) 4228 4229(define_insn "*call_value_mem" 4230 [(set (match_operand 0 "" "=rf") 4231 (call (mem:SI (match_operand 1 "memory_operand" "m")) 4232 (match_operand 2 "general_operand" "g"))) 4233 (clobber (reg:SI 14))] 4234 "! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))" 4235 "* 4236 return output_call_mem (&operands[1]); 4237" 4238[(set_attr "length" "12") 4239 (set_attr "type" "call")]) 4240 4241;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses 4242;; The 'a' causes the operand to be treated as an address, i.e. no '#' output. 4243 4244(define_insn "*call_symbol" 4245 [(call (mem:SI (match_operand:SI 0 "" "X")) 4246 (match_operand:SI 1 "general_operand" "g")) 4247 (clobber (reg:SI 14))] 4248 "GET_CODE (operands[0]) == SYMBOL_REF" 4249 "* 4250 { 4251 return NEED_PLT_GOT ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\"; 4252 }" 4253[(set_attr "type" "call")]) 4254 4255(define_insn "*call_value_symbol" 4256 [(set (match_operand 0 "s_register_operand" "=rf") 4257 (call (mem:SI (match_operand:SI 1 "" "X")) 4258 (match_operand:SI 2 "general_operand" "g"))) 4259 (clobber (reg:SI 14))] 4260 "GET_CODE(operands[1]) == SYMBOL_REF" 4261 "* 4262 { 4263 return NEED_PLT_GOT ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\"; 4264 }" 4265[(set_attr "type" "call")]) 4266 4267;; Often the return insn will be the same as loading from memory, so set attr 4268(define_insn "return" 4269 [(return)] 4270 "USE_RETURN_INSN(FALSE)" 4271 "* 4272{ 4273 extern int arm_ccfsm_state; 4274 4275 if (arm_ccfsm_state == 2) 4276 { 4277 arm_ccfsm_state += 2; 4278 return \"\"; 4279 } 4280 return output_return_instruction (NULL, TRUE, FALSE); 4281}" 4282[(set_attr "type" "load")]) 4283 4284(define_insn "*cond_return" 4285 [(set (pc) 4286 (if_then_else (match_operator 0 "comparison_operator" 4287 [(match_operand 1 "cc_register" "") (const_int 0)]) 4288 (return) 4289 (pc)))] 4290 "USE_RETURN_INSN(TRUE)" 4291 "* 4292{ 4293 extern int arm_ccfsm_state; 4294 4295 if (arm_ccfsm_state == 2) 4296 { 4297 arm_ccfsm_state += 2; 4298 return \"\"; 4299 } 4300 return output_return_instruction (operands[0], TRUE, FALSE); 4301}" 4302[(set_attr "conds" "use") 4303 (set_attr "type" "load")]) 4304 4305(define_insn "*cond_return_inverted" 4306 [(set (pc) 4307 (if_then_else (match_operator 0 "comparison_operator" 4308 [(match_operand 1 "cc_register" "") (const_int 0)]) 4309 (pc) 4310 (return)))] 4311 "USE_RETURN_INSN(TRUE)" 4312 "* 4313{ 4314 extern int arm_ccfsm_state; 4315 4316 if (arm_ccfsm_state == 2) 4317 { 4318 arm_ccfsm_state += 2; 4319 return \"\"; 4320 } 4321 return output_return_instruction (operands[0], TRUE, TRUE); 4322}" 4323[(set_attr "conds" "use") 4324 (set_attr "type" "load")]) 4325 4326;; Call subroutine returning any type. 4327 4328(define_expand "untyped_call" 4329 [(parallel [(call (match_operand 0 "" "") 4330 (const_int 0)) 4331 (match_operand 1 "" "") 4332 (match_operand 2 "" "")])] 4333 "" 4334 " 4335{ 4336 int i; 4337 4338 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx)); 4339 4340 for (i = 0; i < XVECLEN (operands[2], 0); i++) 4341 { 4342 rtx set = XVECEXP (operands[2], 0, i); 4343 emit_move_insn (SET_DEST (set), SET_SRC (set)); 4344 } 4345 4346 /* The optimizer does not know that the call sets the function value 4347 registers we stored in the result block. We avoid problems by 4348 claiming that all hard registers are used and clobbered at this 4349 point. */ 4350 emit_insn (gen_blockage ()); 4351 4352 DONE; 4353}") 4354 4355;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and 4356;; all of memory. This blocks insns from being moved across this point. 4357 4358(define_insn "blockage" 4359 [(unspec_volatile [(const_int 0)] 0)] 4360 "" 4361 "" 4362[(set_attr "length" "0") 4363 (set_attr "type" "block")]) 4364 4365(define_expand "casesi" 4366 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on 4367 (match_operand:SI 1 "const_int_operand" "") ; lower bound 4368 (match_operand:SI 2 "const_int_operand" "") ; total range 4369 (match_operand:SI 3 "" "") ; table label 4370 (match_operand:SI 4 "" "")] ; Out of range label 4371 "" 4372 " 4373{ 4374 rtx reg; 4375 if (operands[1] != const0_rtx) 4376 { 4377 reg = gen_reg_rtx (SImode); 4378 emit_insn (gen_addsi3 (reg, operands[0], 4379 GEN_INT (-INTVAL (operands[1])))); 4380 operands[0] = reg; 4381 } 4382 4383 if (! const_ok_for_arm (INTVAL (operands[2]))) 4384 operands[2] = force_reg (SImode, operands[2]); 4385 4386 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3], 4387 operands[4])); 4388 DONE; 4389}") 4390 4391;; The USE in this pattern is needed to tell flow analysis that this is 4392;; a CASESI insn. It has no other purpose. 4393(define_insn "casesi_internal" 4394 [(parallel [(set (pc) 4395 (if_then_else 4396 (leu (match_operand:SI 0 "s_register_operand" "r") 4397 (match_operand:SI 1 "arm_rhs_operand" "rI")) 4398 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4)) 4399 (label_ref (match_operand 2 "" "")))) 4400 (label_ref (match_operand 3 "" "")))) 4401 (use (label_ref (match_dup 2)))])] 4402 "" 4403 "* 4404 if (flag_pic) 4405 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\"; 4406 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\"; 4407" 4408[(set_attr "conds" "clob") 4409 (set_attr "length" "12")]) 4410 4411(define_insn "indirect_jump" 4412 [(set (pc) 4413 (match_operand:SI 0 "s_register_operand" "r"))] 4414 "" 4415 "mov%?\\t%|pc, %0\\t%@ indirect jump") 4416 4417(define_insn "*load_indirect_jump" 4418 [(set (pc) 4419 (match_operand:SI 0 "memory_operand" "m"))] 4420 "" 4421 "ldr%?\\t%|pc, %0\\t%@ indirect jump" 4422[(set_attr "type" "load")]) 4423 4424;; Misc insns 4425 4426(define_insn "nop" 4427 [(const_int 0)] 4428 "" 4429 "mov%?\\t%|r0, %|r0\\t%@ nop") 4430 4431;; Patterns to allow combination of arithmetic, cond code and shifts 4432 4433(define_insn "*arith_shiftsi" 4434 [(set (match_operand:SI 0 "s_register_operand" "=r") 4435 (match_operator:SI 1 "shiftable_operator" 4436 [(match_operator:SI 3 "shift_operator" 4437 [(match_operand:SI 4 "s_register_operand" "r") 4438 (match_operand:SI 5 "reg_or_int_operand" "rI")]) 4439 (match_operand:SI 2 "s_register_operand" "r")]))] 4440 "" 4441 "%i1%?\\t%0, %2, %4%S3") 4442 4443(define_insn "*arith_shiftsi_compare0" 4444 [(set (reg:CC_NOOV 24) 4445 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" 4446 [(match_operator:SI 3 "shift_operator" 4447 [(match_operand:SI 4 "s_register_operand" "r") 4448 (match_operand:SI 5 "reg_or_int_operand" "rI")]) 4449 (match_operand:SI 2 "s_register_operand" "r")]) 4450 (const_int 0))) 4451 (set (match_operand:SI 0 "s_register_operand" "=r") 4452 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)]) 4453 (match_dup 2)]))] 4454 "" 4455 "%i1%?s\\t%0, %2, %4%S3" 4456[(set_attr "conds" "set")]) 4457 4458(define_insn "*arith_shiftsi_compare0_scratch" 4459 [(set (reg:CC_NOOV 24) 4460 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" 4461 [(match_operator:SI 3 "shift_operator" 4462 [(match_operand:SI 4 "s_register_operand" "r") 4463 (match_operand:SI 5 "reg_or_int_operand" "rI")]) 4464 (match_operand:SI 2 "s_register_operand" "r")]) 4465 (const_int 0))) 4466 (clobber (match_scratch:SI 0 "=r"))] 4467 "" 4468 "%i1%?s\\t%0, %2, %4%S3" 4469[(set_attr "conds" "set")]) 4470 4471(define_insn "*sub_shiftsi" 4472 [(set (match_operand:SI 0 "s_register_operand" "=r") 4473 (minus:SI (match_operand:SI 1 "s_register_operand" "r") 4474 (match_operator:SI 2 "shift_operator" 4475 [(match_operand:SI 3 "s_register_operand" "r") 4476 (match_operand:SI 4 "reg_or_int_operand" "rM")])))] 4477 "" 4478 "sub%?\\t%0, %1, %3%S2") 4479 4480(define_insn "*sub_shiftsi_compare0" 4481 [(set (reg:CC_NOOV 24) 4482 (compare:CC_NOOV 4483 (minus:SI (match_operand:SI 1 "s_register_operand" "r") 4484 (match_operator:SI 2 "shift_operator" 4485 [(match_operand:SI 3 "s_register_operand" "r") 4486 (match_operand:SI 4 "reg_or_int_operand" "rM")])) 4487 (const_int 0))) 4488 (set (match_operand:SI 0 "s_register_operand" "=r") 4489 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 4490 (match_dup 4)])))] 4491 "" 4492 "sub%?s\\t%0, %1, %3%S2" 4493[(set_attr "conds" "set")]) 4494 4495(define_insn "*sub_shiftsi_compare0_scratch" 4496 [(set (reg:CC_NOOV 24) 4497 (compare:CC_NOOV 4498 (minus:SI (match_operand:SI 1 "s_register_operand" "r") 4499 (match_operator:SI 2 "shift_operator" 4500 [(match_operand:SI 3 "s_register_operand" "r") 4501 (match_operand:SI 4 "reg_or_int_operand" "rM")])) 4502 (const_int 0))) 4503 (clobber (match_scratch:SI 0 "=r"))] 4504 "" 4505 "sub%?s\\t%0, %1, %3%S2" 4506[(set_attr "conds" "set")]) 4507 4508;; These variants of the above insns can occur if the first operand is the 4509;; frame pointer and we eliminate that. This is a kludge, but there doesn't 4510;; seem to be a way around it. Most of the predicates have to be null 4511;; because the format can be generated part way through reload, so 4512;; if we don't match it as soon as it becomes available, reload doesn't know 4513;; how to reload pseudos that haven't got hard registers; the constraints will 4514;; sort everything out. 4515 4516(define_insn "*reload_mulsi3" 4517 [(set (match_operand:SI 0 "" "=&r") 4518 (plus:SI (plus:SI (match_operator:SI 5 "shift_operator" 4519 [(match_operand:SI 3 "" "r") 4520 (match_operand:SI 4 "" "rM")]) 4521 (match_operand:SI 2 "" "r")) 4522 (match_operand:SI 1 "const_int_operand" "n")))] 4523 "reload_in_progress" 4524 "* 4525 output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands); 4526 operands[2] = operands[1]; 4527 operands[1] = operands[0]; 4528 return output_add_immediate (operands); 4529" 4530; we have no idea how long the add_immediate is, it could be up to 4. 4531[(set_attr "length" "20")]) 4532 4533(define_insn "*reload_mulsi_compare0" 4534 [(set (reg:CC_NOOV 24) 4535 (compare:CC_NOOV (plus:SI 4536 (plus:SI 4537 (match_operator:SI 5 "shift_operator" 4538 [(match_operand:SI 3 "" "r") 4539 (match_operand:SI 4 "" "rM")]) 4540 (match_operand:SI 1 "" "r")) 4541 (match_operand:SI 2 "const_int_operand" "n")) 4542 (const_int 0))) 4543 (set (match_operand:SI 0 "" "=&r") 4544 (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)]) 4545 (match_dup 1)) 4546 (match_dup 2)))] 4547 "reload_in_progress" 4548 "* 4549 output_add_immediate (operands); 4550 return \"add%?s\\t%0, %0, %3%S5\"; 4551" 4552[(set_attr "conds" "set") 4553 (set_attr "length" "20")]) 4554 4555(define_insn "*reload_mulsi_compare0_scratch" 4556 [(set (reg:CC_NOOV 24) 4557 (compare:CC_NOOV (plus:SI 4558 (plus:SI 4559 (match_operator:SI 5 "shift_operator" 4560 [(match_operand:SI 3 "" "r") 4561 (match_operand:SI 4 "" "rM")]) 4562 (match_operand:SI 1 "" "r")) 4563 (match_operand:SI 2 "const_int_operand" "n")) 4564 (const_int 0))) 4565 (clobber (match_scratch:SI 0 "=&r"))] 4566 "reload_in_progress" 4567 "* 4568 output_add_immediate (operands); 4569 return \"add%?s\\t%0, %0, %3%S5\"; 4570" 4571[(set_attr "conds" "set") 4572 (set_attr "length" "20")]) 4573 4574;; These are similar, but are needed when the mla pattern contains the 4575;; eliminated register as operand 3. 4576 4577(define_insn "*reload_muladdsi" 4578 [(set (match_operand:SI 0 "" "=&r,&r") 4579 (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r") 4580 (match_operand:SI 2 "" "r,r")) 4581 (match_operand:SI 3 "" "r,r")) 4582 (match_operand:SI 4 "const_int_operand" "n,n")))] 4583 "reload_in_progress" 4584 "* 4585 output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands); 4586 operands[2] = operands[4]; 4587 operands[1] = operands[0]; 4588 return output_add_immediate (operands); 4589" 4590[(set_attr "length" "20") 4591 (set_attr "type" "mult")]) 4592 4593(define_insn "*reload_muladdsi_compare0" 4594 [(set (reg:CC_NOOV 24) 4595 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI 4596 (match_operand:SI 3 "" "r") 4597 (match_operand:SI 4 "" "r")) 4598 (match_operand:SI 1 "" "r")) 4599 (match_operand:SI 2 "const_int_operand" "n")) 4600 (const_int 0))) 4601 (set (match_operand:SI 0 "" "=&r") 4602 (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1)) 4603 (match_dup 2)))] 4604 "reload_in_progress" 4605 "* 4606 output_add_immediate (operands); 4607 output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands); 4608 return \"\"; 4609" 4610[(set_attr "length" "20") 4611 (set_attr "conds" "set") 4612 (set_attr "type" "mult")]) 4613 4614(define_insn "*reload_muladdsi_compare0_scratch" 4615 [(set (reg:CC_NOOV 24) 4616 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI 4617 (match_operand:SI 3 "" "r") 4618 (match_operand:SI 4 "" "r")) 4619 (match_operand:SI 1 "" "r")) 4620 (match_operand:SI 2 "const_int_operand" "n")) 4621 (const_int 0))) 4622 (clobber (match_scratch:SI 0 "=&r"))] 4623 "reload_in_progress" 4624 "* 4625 output_add_immediate (operands); 4626 return \"mla%?s\\t%0, %3, %4, %0\"; 4627" 4628[(set_attr "length" "20") 4629 (set_attr "conds" "set") 4630 (set_attr "type" "mult")]) 4631 4632 4633 4634(define_insn "*and_scc" 4635 [(set (match_operand:SI 0 "s_register_operand" "=r") 4636 (and:SI (match_operator 1 "comparison_operator" 4637 [(match_operand 3 "cc_register" "") (const_int 0)]) 4638 (match_operand:SI 2 "s_register_operand" "r")))] 4639 "" 4640 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1" 4641[(set_attr "conds" "use") 4642 (set_attr "length" "8")]) 4643 4644(define_insn "*ior_scc" 4645 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 4646 (ior:SI (match_operator 2 "comparison_operator" 4647 [(match_operand 3 "cc_register" "") (const_int 0)]) 4648 (match_operand:SI 1 "s_register_operand" "0,?r")))] 4649 "" 4650 "@ 4651 orr%d2\\t%0, %1, #1 4652 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1" 4653[(set_attr "conds" "use") 4654 (set_attr "length" "4,8")]) 4655 4656(define_insn "*compare_scc" 4657 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 4658 (match_operator 1 "comparison_operator" 4659 [(match_operand:SI 2 "s_register_operand" "r,r") 4660 (match_operand:SI 3 "arm_add_operand" "rI,L")])) 4661 (clobber (reg:CC 24))] 4662 "" 4663 "* 4664 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx) 4665 return \"mov\\t%0, %2, lsr #31\"; 4666 4667 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx) 4668 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\"; 4669 4670 if (GET_CODE (operands[1]) == NE) 4671 { 4672 if (which_alternative == 1) 4673 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\"; 4674 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\"; 4675 } 4676 if (which_alternative == 1) 4677 output_asm_insn (\"cmn\\t%2, #%n3\", operands); 4678 else 4679 output_asm_insn (\"cmp\\t%2, %3\", operands); 4680 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\"; 4681" 4682[(set_attr "conds" "clob") 4683 (set_attr "length" "12")]) 4684 4685(define_insn "*cond_move" 4686 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 4687 (if_then_else:SI (match_operator 3 "equality_operator" 4688 [(match_operator 4 "comparison_operator" 4689 [(match_operand 5 "cc_register" "") (const_int 0)]) 4690 (const_int 0)]) 4691 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI") 4692 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))] 4693 "" 4694 "* 4695 if (GET_CODE (operands[3]) == NE) 4696 { 4697 if (which_alternative != 1) 4698 output_asm_insn (\"mov%D4\\t%0, %2\", operands); 4699 if (which_alternative != 0) 4700 output_asm_insn (\"mov%d4\\t%0, %1\", operands); 4701 return \"\"; 4702 } 4703 if (which_alternative != 0) 4704 output_asm_insn (\"mov%D4\\t%0, %1\", operands); 4705 if (which_alternative != 1) 4706 output_asm_insn (\"mov%d4\\t%0, %2\", operands); 4707 return \"\"; 4708" 4709[(set_attr "conds" "use") 4710 (set_attr "length" "4,4,8")]) 4711 4712(define_insn "*cond_arith" 4713 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 4714 (match_operator:SI 5 "shiftable_operator" 4715 [(match_operator:SI 4 "comparison_operator" 4716 [(match_operand:SI 2 "s_register_operand" "r,r") 4717 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) 4718 (match_operand:SI 1 "s_register_operand" "0,?r")])) 4719 (clobber (reg:CC 24))] 4720 "" 4721 "* 4722 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx) 4723 return \"%i5\\t%0, %1, %2, lsr #31\"; 4724 4725 output_asm_insn (\"cmp\\t%2, %3\", operands); 4726 if (GET_CODE (operands[5]) == AND) 4727 output_asm_insn (\"mov%D4\\t%0, #0\", operands); 4728 else if (GET_CODE (operands[5]) == MINUS) 4729 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands); 4730 else if (which_alternative != 0) 4731 output_asm_insn (\"mov%D4\\t%0, %1\", operands); 4732 return \"%i5%d4\\t%0, %1, #1\"; 4733" 4734[(set_attr "conds" "clob") 4735 (set_attr "length" "12")]) 4736 4737(define_insn "*cond_sub" 4738 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 4739 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r") 4740 (match_operator:SI 4 "comparison_operator" 4741 [(match_operand:SI 2 "s_register_operand" "r,r") 4742 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]))) 4743 (clobber (reg:CC 24))] 4744 "" 4745 "* 4746 output_asm_insn (\"cmp\\t%2, %3\", operands); 4747 if (which_alternative != 0) 4748 output_asm_insn (\"mov%D4\\t%0, %1\", operands); 4749 return \"sub%d4\\t%0, %1, #1\"; 4750" 4751[(set_attr "conds" "clob") 4752 (set_attr "length" "8,12")]) 4753 4754(define_insn "*cmp_ite0" 4755 [(set (match_operand 6 "dominant_cc_register" "") 4756 (compare 4757 (if_then_else:SI 4758 (match_operator 4 "comparison_operator" 4759 [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 4760 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 4761 (match_operator:SI 5 "comparison_operator" 4762 [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 4763 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]) 4764 (const_int 0)) 4765 (const_int 0)))] 4766 "" 4767 "* 4768{ 4769 char* opcodes[4][2] = 4770 { 4771 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"}, 4772 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"}, 4773 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"}, 4774 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\", 4775 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"} 4776 }; 4777 int swap = 4778 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])); 4779 4780 return opcodes[which_alternative][swap]; 4781} 4782" 4783[(set_attr "conds" "set") 4784 (set_attr "length" "8")]) 4785 4786(define_insn "*cmp_ite1" 4787 [(set (match_operand 6 "dominant_cc_register" "") 4788 (compare 4789 (if_then_else:SI 4790 (match_operator 4 "comparison_operator" 4791 [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 4792 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 4793 (match_operator:SI 5 "comparison_operator" 4794 [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 4795 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]) 4796 (const_int 1)) 4797 (const_int 0)))] 4798 "" 4799 "* 4800{ 4801 char* opcodes[4][2] = 4802 { 4803 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"}, 4804 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"}, 4805 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\", \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"}, 4806 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\", 4807 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"} 4808 }; 4809 int swap = 4810 comparison_dominates_p (GET_CODE (operands[5]), 4811 reverse_condition (GET_CODE (operands[4]))); 4812 4813 return opcodes[which_alternative][swap]; 4814} 4815" 4816[(set_attr "conds" "set") 4817 (set_attr "length" "8")]) 4818 4819(define_insn "*negscc" 4820 [(set (match_operand:SI 0 "s_register_operand" "=r") 4821 (neg:SI (match_operator 3 "comparison_operator" 4822 [(match_operand:SI 1 "s_register_operand" "r") 4823 (match_operand:SI 2 "arm_rhs_operand" "rI")]))) 4824 (clobber (reg:CC 24))] 4825 "" 4826 "* 4827 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx) 4828 return \"mov\\t%0, %1, asr #31\"; 4829 4830 if (GET_CODE (operands[3]) == NE) 4831 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\"; 4832 4833 if (GET_CODE (operands[3]) == GT) 4834 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\"; 4835 4836 output_asm_insn (\"cmp\\t%1, %2\", operands); 4837 output_asm_insn (\"mov%D3\\t%0, #0\", operands); 4838 return \"mvn%d3\\t%0, #0\"; 4839" 4840[(set_attr "conds" "clob") 4841 (set_attr "length" "12")]) 4842 4843(define_insn "movcond" 4844 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 4845 (if_then_else:SI 4846 (match_operator 5 "comparison_operator" 4847 [(match_operand:SI 3 "s_register_operand" "r,r,r") 4848 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")]) 4849 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI") 4850 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 4851 (clobber (reg:CC 24))] 4852 "" 4853 "* 4854 if (GET_CODE (operands[5]) == LT 4855 && (operands[4] == const0_rtx)) 4856 { 4857 if (which_alternative != 1 && GET_CODE (operands[1]) == REG) 4858 { 4859 if (operands[2] == const0_rtx) 4860 return \"and\\t%0, %1, %3, asr #31\"; 4861 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\"; 4862 } 4863 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG) 4864 { 4865 if (operands[1] == const0_rtx) 4866 return \"bic\\t%0, %2, %3, asr #31\"; 4867 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\"; 4868 } 4869 /* The only case that falls through to here is when both ops 1 & 2 4870 are constants */ 4871 } 4872 4873 if (GET_CODE (operands[5]) == GE 4874 && (operands[4] == const0_rtx)) 4875 { 4876 if (which_alternative != 1 && GET_CODE (operands[1]) == REG) 4877 { 4878 if (operands[2] == const0_rtx) 4879 return \"bic\\t%0, %1, %3, asr #31\"; 4880 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\"; 4881 } 4882 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG) 4883 { 4884 if (operands[1] == const0_rtx) 4885 return \"and\\t%0, %2, %3, asr #31\"; 4886 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\"; 4887 } 4888 /* The only case that falls through to here is when both ops 1 & 2 4889 are constants */ 4890 } 4891 if (GET_CODE (operands[4]) == CONST_INT 4892 && !const_ok_for_arm (INTVAL (operands[4]))) 4893 output_asm_insn (\"cmn\\t%3, #%n4\", operands); 4894 else 4895 output_asm_insn (\"cmp\\t%3, %4\", operands); 4896 if (which_alternative != 0) 4897 output_asm_insn (\"mov%d5\\t%0, %1\", operands); 4898 if (which_alternative != 1) 4899 output_asm_insn (\"mov%D5\\t%0, %2\", operands); 4900 return \"\"; 4901" 4902[(set_attr "conds" "clob") 4903 (set_attr "length" "8,8,12")]) 4904 4905(define_insn "*ifcompare_plus_move" 4906 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 4907 (if_then_else:SI (match_operator 6 "comparison_operator" 4908 [(match_operand:SI 4 "s_register_operand" "r,r") 4909 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 4910 (plus:SI 4911 (match_operand:SI 2 "s_register_operand" "r,r") 4912 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")) 4913 (match_operand:SI 1 "arm_rhs_operand" "0,?rI"))) 4914 (clobber (reg:CC 24))] 4915 "" 4916 "#" 4917[(set_attr "conds" "clob") 4918 (set_attr "length" "8,12")]) 4919 4920(define_insn "*if_plus_move" 4921 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r") 4922 (if_then_else:SI 4923 (match_operator 4 "comparison_operator" 4924 [(match_operand 5 "cc_register" "") (const_int 0)]) 4925 (plus:SI 4926 (match_operand:SI 2 "s_register_operand" "r,r,r,r") 4927 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L")) 4928 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))] 4929 "" 4930 "@ 4931 add%d4\\t%0, %2, %3 4932 sub%d4\\t%0, %2, #%n3 4933 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1 4934 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1" 4935[(set_attr "conds" "use") 4936 (set_attr "length" "4,4,8,8") 4937 (set_attr "type" "*,*,*,*")]) 4938 4939(define_insn "*ifcompare_move_plus" 4940 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 4941 (if_then_else:SI (match_operator 6 "comparison_operator" 4942 [(match_operand:SI 4 "s_register_operand" "r,r") 4943 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 4944 (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 4945 (plus:SI 4946 (match_operand:SI 2 "s_register_operand" "r,r") 4947 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")))) 4948 (clobber (reg:CC 24))] 4949 "" 4950 "#" 4951[(set_attr "conds" "clob") 4952 (set_attr "length" "8,12")]) 4953 4954(define_insn "*if_move_plus" 4955 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r") 4956 (if_then_else:SI 4957 (match_operator 4 "comparison_operator" 4958 [(match_operand 5 "cc_register" "") (const_int 0)]) 4959 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI") 4960 (plus:SI 4961 (match_operand:SI 2 "s_register_operand" "r,r,r,r") 4962 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))] 4963 "" 4964 "@ 4965 add%D4\\t%0, %2, %3 4966 sub%D4\\t%0, %2, #%n3 4967 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1 4968 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1" 4969[(set_attr "conds" "use") 4970 (set_attr "length" "4,4,8,8") 4971 (set_attr "type" "*,*,*,*")]) 4972 4973(define_insn "*ifcompare_arith_arith" 4974 [(set (match_operand:SI 0 "s_register_operand" "=r") 4975 (if_then_else:SI (match_operator 9 "comparison_operator" 4976 [(match_operand:SI 5 "s_register_operand" "r") 4977 (match_operand:SI 6 "arm_add_operand" "rIL")]) 4978 (match_operator:SI 8 "shiftable_operator" 4979 [(match_operand:SI 1 "s_register_operand" "r") 4980 (match_operand:SI 2 "arm_rhs_operand" "rI")]) 4981 (match_operator:SI 7 "shiftable_operator" 4982 [(match_operand:SI 3 "s_register_operand" "r") 4983 (match_operand:SI 4 "arm_rhs_operand" "rI")]))) 4984 (clobber (reg:CC 24))] 4985 "" 4986 "#" 4987[(set_attr "conds" "clob") 4988 (set_attr "length" "12")]) 4989 4990(define_insn "*if_arith_arith" 4991 [(set (match_operand:SI 0 "s_register_operand" "=r") 4992 (if_then_else:SI (match_operator 5 "comparison_operator" 4993 [(match_operand 8 "cc_register" "") (const_int 0)]) 4994 (match_operator:SI 6 "shiftable_operator" 4995 [(match_operand:SI 1 "s_register_operand" "r") 4996 (match_operand:SI 2 "arm_rhs_operand" "rI")]) 4997 (match_operator:SI 7 "shiftable_operator" 4998 [(match_operand:SI 3 "s_register_operand" "r") 4999 (match_operand:SI 4 "arm_rhs_operand" "rI")])))] 5000 "" 5001 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4" 5002[(set_attr "conds" "use") 5003 (set_attr "length" "8")]) 5004 5005(define_insn "*ifcompare_arith_move" 5006 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 5007 (if_then_else:SI (match_operator 6 "comparison_operator" 5008 [(match_operand:SI 2 "s_register_operand" "r,r") 5009 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")]) 5010 (match_operator:SI 7 "shiftable_operator" 5011 [(match_operand:SI 4 "s_register_operand" "r,r") 5012 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")]) 5013 (match_operand:SI 1 "arm_rhs_operand" "0,?rI"))) 5014 (clobber (reg:CC 24))] 5015 "" 5016 "* 5017 /* If we have an operation where (op x 0) is the identity operation and 5018 the conditional operator is LT or GE and we are comparing against zero and 5019 everything is in registers then we can do this in two instructions */ 5020 if (operands[3] == const0_rtx 5021 && GET_CODE (operands[7]) != AND 5022 && GET_CODE (operands[5]) == REG 5023 && GET_CODE (operands[1]) == REG 5024 && REGNO (operands[1]) == REGNO (operands[4]) 5025 && REGNO (operands[4]) != REGNO (operands[0])) 5026 { 5027 if (GET_CODE (operands[6]) == LT) 5028 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\"; 5029 else if (GET_CODE (operands[6]) == GE) 5030 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\"; 5031 } 5032 if (GET_CODE (operands[3]) == CONST_INT 5033 && !const_ok_for_arm (INTVAL (operands[3]))) 5034 output_asm_insn (\"cmn\\t%2, #%n3\", operands); 5035 else 5036 output_asm_insn (\"cmp\\t%2, %3\", operands); 5037 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands); 5038 if (which_alternative != 0) 5039 return \"mov%D6\\t%0, %1\"; 5040 return \"\"; 5041" 5042[(set_attr "conds" "clob") 5043 (set_attr "length" "8,12")]) 5044 5045(define_insn "*if_arith_move" 5046 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 5047 (if_then_else:SI (match_operator 4 "comparison_operator" 5048 [(match_operand 6 "cc_register" "") (const_int 0)]) 5049 (match_operator:SI 5 "shiftable_operator" 5050 [(match_operand:SI 2 "s_register_operand" "r,r") 5051 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) 5052 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))] 5053 "" 5054 "@ 5055 %I5%d4\\t%0, %2, %3 5056 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1" 5057[(set_attr "conds" "use") 5058 (set_attr "length" "4,8") 5059 (set_attr "type" "*,*")]) 5060 5061(define_insn "*ifcompare_move_arith" 5062 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 5063 (if_then_else:SI (match_operator 6 "comparison_operator" 5064 [(match_operand:SI 4 "s_register_operand" "r,r") 5065 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 5066 (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 5067 (match_operator:SI 7 "shiftable_operator" 5068 [(match_operand:SI 2 "s_register_operand" "r,r") 5069 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]))) 5070 (clobber (reg:CC 24))] 5071 "" 5072 "* 5073 /* If we have an operation where (op x 0) is the identity operation and 5074 the conditional operator is LT or GE and we are comparing against zero and 5075 everything is in registers then we can do this in two instructions */ 5076 if (operands[5] == const0_rtx 5077 && GET_CODE (operands[7]) != AND 5078 && GET_CODE (operands[3]) == REG 5079 && GET_CODE (operands[1]) == REG 5080 && REGNO (operands[1]) == REGNO (operands[2]) 5081 && REGNO (operands[2]) != REGNO (operands[0])) 5082 { 5083 if (GET_CODE (operands[6]) == GE) 5084 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\"; 5085 else if (GET_CODE (operands[6]) == LT) 5086 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\"; 5087 } 5088 5089 if (GET_CODE (operands[5]) == CONST_INT 5090 && !const_ok_for_arm (INTVAL (operands[5]))) 5091 output_asm_insn (\"cmn\\t%4, #%n5\", operands); 5092 else 5093 output_asm_insn (\"cmp\\t%4, %5\", operands); 5094 5095 if (which_alternative != 0) 5096 output_asm_insn (\"mov%d6\\t%0, %1\", operands); 5097 return \"%I7%D6\\t%0, %2, %3\"; 5098" 5099[(set_attr "conds" "clob") 5100 (set_attr "length" "8,12")]) 5101 5102(define_insn "*if_move_arith" 5103 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 5104 (if_then_else:SI 5105 (match_operator 4 "comparison_operator" 5106 [(match_operand 6 "cc_register" "") (const_int 0)]) 5107 (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 5108 (match_operator:SI 5 "shiftable_operator" 5109 [(match_operand:SI 2 "s_register_operand" "r,r") 5110 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))] 5111 "" 5112 "@ 5113 %I5%D4\\t%0, %2, %3 5114 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1" 5115[(set_attr "conds" "use") 5116 (set_attr "length" "4,8") 5117 (set_attr "type" "*,*")]) 5118 5119(define_insn "*ifcompare_move_not" 5120 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 5121 (if_then_else:SI 5122 (match_operator 5 "comparison_operator" 5123 [(match_operand:SI 3 "s_register_operand" "r,r") 5124 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 5125 (match_operand:SI 1 "arm_not_operand" "0,?rIK") 5126 (not:SI 5127 (match_operand:SI 2 "s_register_operand" "r,r")))) 5128 (clobber (reg:CC 24))] 5129 "" 5130 "#" 5131[(set_attr "conds" "clob") 5132 (set_attr "length" "8,12")]) 5133 5134(define_insn "*if_move_not" 5135 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 5136 (if_then_else:SI 5137 (match_operator 4 "comparison_operator" 5138 [(match_operand 3 "cc_register" "") (const_int 0)]) 5139 (match_operand:SI 1 "arm_not_operand" "0,?rI,K") 5140 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))] 5141 "" 5142 "@ 5143 mvn%D4\\t%0, %2 5144 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2 5145 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2" 5146[(set_attr "conds" "use") 5147 (set_attr "length" "4,8,8")]) 5148 5149(define_insn "*ifcompare_not_move" 5150 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 5151 (if_then_else:SI 5152 (match_operator 5 "comparison_operator" 5153 [(match_operand:SI 3 "s_register_operand" "r,r") 5154 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 5155 (not:SI 5156 (match_operand:SI 2 "s_register_operand" "r,r")) 5157 (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) 5158 (clobber (reg:CC 24))] 5159 "" 5160 "#" 5161[(set_attr "conds" "clob") 5162 (set_attr "length" "8,12")]) 5163 5164(define_insn "*if_not_move" 5165 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 5166 (if_then_else:SI 5167 (match_operator 4 "comparison_operator" 5168 [(match_operand 3 "cc_register" "") (const_int 0)]) 5169 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r")) 5170 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] 5171 "" 5172 "@ 5173 mvn%d4\\t%0, %2 5174 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2 5175 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2" 5176[(set_attr "conds" "use") 5177 (set_attr "length" "4,8,8")]) 5178 5179(define_insn "*ifcompare_shift_move" 5180 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 5181 (if_then_else:SI 5182 (match_operator 6 "comparison_operator" 5183 [(match_operand:SI 4 "s_register_operand" "r,r") 5184 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 5185 (match_operator:SI 7 "shift_operator" 5186 [(match_operand:SI 2 "s_register_operand" "r,r") 5187 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")]) 5188 (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) 5189 (clobber (reg:CC 24))] 5190 "" 5191 "#" 5192[(set_attr "conds" "clob") 5193 (set_attr "length" "8,12")]) 5194 5195(define_insn "*if_shift_move" 5196 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 5197 (if_then_else:SI 5198 (match_operator 5 "comparison_operator" 5199 [(match_operand 6 "cc_register" "") (const_int 0)]) 5200 (match_operator:SI 4 "shift_operator" 5201 [(match_operand:SI 2 "s_register_operand" "r,r,r") 5202 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")]) 5203 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] 5204 "" 5205 "@ 5206 mov%d5\\t%0, %2%S4 5207 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4 5208 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4" 5209[(set_attr "conds" "use") 5210 (set_attr "length" "4,8,8")]) 5211 5212(define_insn "*ifcompare_move_shift" 5213 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 5214 (if_then_else:SI 5215 (match_operator 6 "comparison_operator" 5216 [(match_operand:SI 4 "s_register_operand" "r,r") 5217 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 5218 (match_operand:SI 1 "arm_not_operand" "0,?rIK") 5219 (match_operator:SI 7 "shift_operator" 5220 [(match_operand:SI 2 "s_register_operand" "r,r") 5221 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")]))) 5222 (clobber (reg:CC 24))] 5223 "" 5224 "#" 5225[(set_attr "conds" "clob") 5226 (set_attr "length" "8,12")]) 5227 5228(define_insn "*if_move_shift" 5229 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 5230 (if_then_else:SI 5231 (match_operator 5 "comparison_operator" 5232 [(match_operand 6 "cc_register" "") (const_int 0)]) 5233 (match_operand:SI 1 "arm_not_operand" "0,?rI,K") 5234 (match_operator:SI 4 "shift_operator" 5235 [(match_operand:SI 2 "s_register_operand" "r,r,r") 5236 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))] 5237 "" 5238 "@ 5239 mov%D5\\t%0, %2%S4 5240 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4 5241 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4" 5242[(set_attr "conds" "use") 5243 (set_attr "length" "4,8,8")]) 5244 5245(define_insn "*ifcompare_shift_shift" 5246 [(set (match_operand:SI 0 "s_register_operand" "=r") 5247 (if_then_else:SI 5248 (match_operator 7 "comparison_operator" 5249 [(match_operand:SI 5 "s_register_operand" "r") 5250 (match_operand:SI 6 "arm_add_operand" "rIL")]) 5251 (match_operator:SI 8 "shift_operator" 5252 [(match_operand:SI 1 "s_register_operand" "r") 5253 (match_operand:SI 2 "arm_rhs_operand" "rM")]) 5254 (match_operator:SI 9 "shift_operator" 5255 [(match_operand:SI 3 "s_register_operand" "r") 5256 (match_operand:SI 4 "arm_rhs_operand" "rM")]))) 5257 (clobber (reg:CC 24))] 5258 "" 5259 "#" 5260[(set_attr "conds" "clob") 5261 (set_attr "length" "12")]) 5262 5263(define_insn "*if_shift_shift" 5264 [(set (match_operand:SI 0 "s_register_operand" "=r") 5265 (if_then_else:SI 5266 (match_operator 5 "comparison_operator" 5267 [(match_operand 8 "cc_register" "") (const_int 0)]) 5268 (match_operator:SI 6 "shift_operator" 5269 [(match_operand:SI 1 "s_register_operand" "r") 5270 (match_operand:SI 2 "arm_rhs_operand" "rM")]) 5271 (match_operator:SI 7 "shift_operator" 5272 [(match_operand:SI 3 "s_register_operand" "r") 5273 (match_operand:SI 4 "arm_rhs_operand" "rM")])))] 5274 "" 5275 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7" 5276[(set_attr "conds" "use") 5277 (set_attr "length" "8")]) 5278 5279(define_insn "*ifcompare_not_arith" 5280 [(set (match_operand:SI 0 "s_register_operand" "=r") 5281 (if_then_else:SI 5282 (match_operator 6 "comparison_operator" 5283 [(match_operand:SI 4 "s_register_operand" "r") 5284 (match_operand:SI 5 "arm_add_operand" "rIL")]) 5285 (not:SI (match_operand:SI 1 "s_register_operand" "r")) 5286 (match_operator:SI 7 "shiftable_operator" 5287 [(match_operand:SI 2 "s_register_operand" "r") 5288 (match_operand:SI 3 "arm_rhs_operand" "rI")]))) 5289 (clobber (reg:CC 24))] 5290 "" 5291 "#" 5292[(set_attr "conds" "clob") 5293 (set_attr "length" "12")]) 5294 5295(define_insn "*if_not_arith" 5296 [(set (match_operand:SI 0 "s_register_operand" "=r") 5297 (if_then_else:SI 5298 (match_operator 5 "comparison_operator" 5299 [(match_operand 4 "cc_register" "") (const_int 0)]) 5300 (not:SI (match_operand:SI 1 "s_register_operand" "r")) 5301 (match_operator:SI 6 "shiftable_operator" 5302 [(match_operand:SI 2 "s_register_operand" "r") 5303 (match_operand:SI 3 "arm_rhs_operand" "rI")])))] 5304 "" 5305 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3" 5306[(set_attr "conds" "use") 5307 (set_attr "length" "8")]) 5308 5309(define_insn "*ifcompare_arith_not" 5310 [(set (match_operand:SI 0 "s_register_operand" "=r") 5311 (if_then_else:SI 5312 (match_operator 6 "comparison_operator" 5313 [(match_operand:SI 4 "s_register_operand" "r") 5314 (match_operand:SI 5 "arm_add_operand" "rIL")]) 5315 (match_operator:SI 7 "shiftable_operator" 5316 [(match_operand:SI 2 "s_register_operand" "r") 5317 (match_operand:SI 3 "arm_rhs_operand" "rI")]) 5318 (not:SI (match_operand:SI 1 "s_register_operand" "r")))) 5319 (clobber (reg:CC 24))] 5320 "" 5321 "#" 5322[(set_attr "conds" "clob") 5323 (set_attr "length" "12")]) 5324 5325(define_insn "*if_arith_not" 5326 [(set (match_operand:SI 0 "s_register_operand" "=r") 5327 (if_then_else:SI 5328 (match_operator 5 "comparison_operator" 5329 [(match_operand 4 "cc_register" "") (const_int 0)]) 5330 (match_operator:SI 6 "shiftable_operator" 5331 [(match_operand:SI 2 "s_register_operand" "r") 5332 (match_operand:SI 3 "arm_rhs_operand" "rI")]) 5333 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))] 5334 "" 5335 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3" 5336[(set_attr "conds" "use") 5337 (set_attr "length" "8")]) 5338 5339(define_insn "*ifcompare_neg_move" 5340 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 5341 (if_then_else:SI 5342 (match_operator 5 "comparison_operator" 5343 [(match_operand:SI 3 "s_register_operand" "r,r") 5344 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 5345 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r")) 5346 (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) 5347 (clobber (reg:CC 24))] 5348 "" 5349 "#" 5350[(set_attr "conds" "clob") 5351 (set_attr "length" "8,12")]) 5352 5353(define_insn "*if_neg_move" 5354 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 5355 (if_then_else:SI 5356 (match_operator 4 "comparison_operator" 5357 [(match_operand 3 "cc_register" "") (const_int 0)]) 5358 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r")) 5359 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] 5360 "" 5361 "@ 5362 rsb%d4\\t%0, %2, #0 5363 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0 5364 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0" 5365[(set_attr "conds" "use") 5366 (set_attr "length" "4,8,8")]) 5367 5368(define_insn "*ifcompare_move_neg" 5369 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 5370 (if_then_else:SI 5371 (match_operator 5 "comparison_operator" 5372 [(match_operand:SI 3 "s_register_operand" "r,r") 5373 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 5374 (match_operand:SI 1 "arm_not_operand" "0,?rIK") 5375 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r")))) 5376 (clobber (reg:CC 24))] 5377 "" 5378 "#" 5379[(set_attr "conds" "clob") 5380 (set_attr "length" "8,12")]) 5381 5382(define_insn "*if_move_neg" 5383 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 5384 (if_then_else:SI 5385 (match_operator 4 "comparison_operator" 5386 [(match_operand 3 "cc_register" "") (const_int 0)]) 5387 (match_operand:SI 1 "arm_not_operand" "0,?rI,K") 5388 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))] 5389 "" 5390 "@ 5391 rsb%D4\\t%0, %2, #0 5392 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0 5393 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0" 5394[(set_attr "conds" "use") 5395 (set_attr "length" "4,8,8")]) 5396 5397(define_insn "*arith_adjacentmem" 5398 [(set (match_operand:SI 0 "s_register_operand" "=r") 5399 (match_operator:SI 1 "shiftable_operator" 5400 [(match_operand:SI 2 "memory_operand" "m") 5401 (match_operand:SI 3 "memory_operand" "m")])) 5402 (clobber (match_scratch:SI 4 "=r"))] 5403 "adjacent_mem_locations (operands[2], operands[3])" 5404 "* 5405{ 5406 rtx ldm[3]; 5407 rtx arith[4]; 5408 int val1 = 0, val2 = 0; 5409 5410 if (REGNO (operands[0]) > REGNO (operands[4])) 5411 { 5412 ldm[1] = operands[4]; 5413 ldm[2] = operands[0]; 5414 } 5415 else 5416 { 5417 ldm[1] = operands[0]; 5418 ldm[2] = operands[4]; 5419 } 5420 if (GET_CODE (XEXP (operands[2], 0)) != REG) 5421 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1)); 5422 if (GET_CODE (XEXP (operands[3], 0)) != REG) 5423 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1)); 5424 arith[0] = operands[0]; 5425 arith[3] = operands[1]; 5426 if (val1 < val2) 5427 { 5428 arith[1] = ldm[1]; 5429 arith[2] = ldm[2]; 5430 } 5431 else 5432 { 5433 arith[1] = ldm[2]; 5434 arith[2] = ldm[1]; 5435 } 5436 if (val1 && val2) 5437 { 5438 rtx ops[3]; 5439 ldm[0] = ops[0] = operands[4]; 5440 ops[1] = XEXP (XEXP (operands[2], 0), 0); 5441 ops[2] = XEXP (XEXP (operands[2], 0), 1); 5442 output_add_immediate (ops); 5443 if (val1 < val2) 5444 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); 5445 else 5446 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); 5447 } 5448 else if (val1) 5449 { 5450 ldm[0] = XEXP (operands[3], 0); 5451 if (val1 < val2) 5452 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); 5453 else 5454 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); 5455 } 5456 else 5457 { 5458 ldm[0] = XEXP (operands[2], 0); 5459 if (val1 < val2) 5460 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); 5461 else 5462 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); 5463 } 5464 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith); 5465 return \"\"; 5466} 5467" 5468[(set_attr "length" "12") 5469 (set_attr "type" "load")]) 5470 5471;; the arm can support extended pre-inc instructions 5472 5473;; In all these cases, we use operands 0 and 1 for the register being 5474;; incremented because those are the operands that local-alloc will 5475;; tie and these are the pair most likely to be tieable (and the ones 5476;; that will benefit the most). 5477 5478;; We reject the frame pointer if it occurs anywhere in these patterns since 5479;; elimination will cause too many headaches. 5480 5481(define_insn "*strqi_preinc" 5482 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 5483 (match_operand:SI 2 "index_operand" "rJ"))) 5484 (match_operand:QI 3 "s_register_operand" "r")) 5485 (set (match_operand:SI 0 "s_register_operand" "=r") 5486 (plus:SI (match_dup 1) (match_dup 2)))] 5487 "REGNO (operands[0]) != FRAME_POINTER_REGNUM 5488 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 5489 && (GET_CODE (operands[2]) != REG 5490 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 5491 "str%?b\\t%3, [%0, %2]!" 5492[(set_attr "type" "store1")]) 5493 5494(define_insn "*strqi_predec" 5495 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 5496 (match_operand:SI 2 "s_register_operand" "r"))) 5497 (match_operand:QI 3 "s_register_operand" "r")) 5498 (set (match_operand:SI 0 "s_register_operand" "=r") 5499 (minus:SI (match_dup 1) (match_dup 2)))] 5500 "REGNO (operands[0]) != FRAME_POINTER_REGNUM 5501 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 5502 && (GET_CODE (operands[2]) != REG 5503 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 5504 "str%?b\\t%3, [%0, -%2]!" 5505[(set_attr "type" "store1")]) 5506 5507(define_insn "*loadqi_preinc" 5508 [(set (match_operand:QI 3 "s_register_operand" "=r") 5509 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 5510 (match_operand:SI 2 "index_operand" "rJ")))) 5511 (set (match_operand:SI 0 "s_register_operand" "=r") 5512 (plus:SI (match_dup 1) (match_dup 2)))] 5513 "REGNO (operands[0]) != FRAME_POINTER_REGNUM 5514 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 5515 && (GET_CODE (operands[2]) != REG 5516 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 5517 "ldr%?b\\t%3, [%0, %2]!" 5518[(set_attr "type" "load")]) 5519 5520(define_insn "*loadqi_predec" 5521 [(set (match_operand:QI 3 "s_register_operand" "=r") 5522 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 5523 (match_operand:SI 2 "s_register_operand" "r")))) 5524 (set (match_operand:SI 0 "s_register_operand" "=r") 5525 (minus:SI (match_dup 1) (match_dup 2)))] 5526 "REGNO (operands[0]) != FRAME_POINTER_REGNUM 5527 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 5528 && (GET_CODE (operands[2]) != REG 5529 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 5530 "ldr%?b\\t%3, [%0, -%2]!" 5531[(set_attr "type" "load")]) 5532 5533(define_insn "*loadqisi_preinc" 5534 [(set (match_operand:SI 3 "s_register_operand" "=r") 5535 (zero_extend:SI 5536 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 5537 (match_operand:SI 2 "index_operand" "rJ"))))) 5538 (set (match_operand:SI 0 "s_register_operand" "=r") 5539 (plus:SI (match_dup 1) (match_dup 2)))] 5540 "REGNO (operands[0]) != FRAME_POINTER_REGNUM 5541 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 5542 && (GET_CODE (operands[2]) != REG 5543 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 5544 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi" 5545[(set_attr "type" "load")]) 5546 5547(define_insn "*loadqisi_predec" 5548 [(set (match_operand:SI 3 "s_register_operand" "=r") 5549 (zero_extend:SI 5550 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 5551 (match_operand:SI 2 "s_register_operand" "r"))))) 5552 (set (match_operand:SI 0 "s_register_operand" "=r") 5553 (minus:SI (match_dup 1) (match_dup 2)))] 5554 "REGNO (operands[0]) != FRAME_POINTER_REGNUM 5555 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 5556 && (GET_CODE (operands[2]) != REG 5557 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 5558 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi" 5559[(set_attr "type" "load")]) 5560 5561(define_insn "*strsi_preinc" 5562 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 5563 (match_operand:SI 2 "index_operand" "rJ"))) 5564 (match_operand:SI 3 "s_register_operand" "r")) 5565 (set (match_operand:SI 0 "s_register_operand" "=r") 5566 (plus:SI (match_dup 1) (match_dup 2)))] 5567 "REGNO (operands[0]) != FRAME_POINTER_REGNUM 5568 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 5569 && (GET_CODE (operands[2]) != REG 5570 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 5571 "str%?\\t%3, [%0, %2]!" 5572[(set_attr "type" "store1")]) 5573 5574(define_insn "*strqi_predec" 5575 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 5576 (match_operand:SI 2 "s_register_operand" "r"))) 5577 (match_operand:SI 3 "s_register_operand" "r")) 5578 (set (match_operand:SI 0 "s_register_operand" "=r") 5579 (minus:SI (match_dup 1) (match_dup 2)))] 5580 "REGNO (operands[0]) != FRAME_POINTER_REGNUM 5581 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 5582 && (GET_CODE (operands[2]) != REG 5583 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 5584 "str%?\\t%3, [%0, -%2]!" 5585[(set_attr "type" "store1")]) 5586 5587(define_insn "*loadsi_preinc" 5588 [(set (match_operand:SI 3 "s_register_operand" "=r") 5589 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 5590 (match_operand:SI 2 "index_operand" "rJ")))) 5591 (set (match_operand:SI 0 "s_register_operand" "=r") 5592 (plus:SI (match_dup 1) (match_dup 2)))] 5593 "REGNO (operands[0]) != FRAME_POINTER_REGNUM 5594 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 5595 && (GET_CODE (operands[2]) != REG 5596 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 5597 "ldr%?\\t%3, [%0, %2]!" 5598[(set_attr "type" "load")]) 5599 5600(define_insn "*loadsi_predec" 5601 [(set (match_operand:SI 3 "s_register_operand" "=r") 5602 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 5603 (match_operand:SI 2 "s_register_operand" "r")))) 5604 (set (match_operand:SI 0 "s_register_operand" "=r") 5605 (minus:SI (match_dup 1) (match_dup 2)))] 5606 "REGNO (operands[0]) != FRAME_POINTER_REGNUM 5607 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 5608 && (GET_CODE (operands[2]) != REG 5609 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 5610 "ldr%?\\t%3, [%0, -%2]!" 5611[(set_attr "type" "load")]) 5612 5613(define_insn "*loadhi_preinc" 5614 [(set (match_operand:HI 3 "s_register_operand" "=r") 5615 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 5616 (match_operand:SI 2 "index_operand" "rJ")))) 5617 (set (match_operand:SI 0 "s_register_operand" "=r") 5618 (plus:SI (match_dup 1) (match_dup 2)))] 5619 "(! BYTES_BIG_ENDIAN) 5620 && ! TARGET_SHORT_BY_BYTES 5621 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 5622 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 5623 && (GET_CODE (operands[2]) != REG 5624 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 5625 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi" 5626[(set_attr "type" "load")]) 5627 5628(define_insn "*loadhi_predec" 5629 [(set (match_operand:HI 3 "s_register_operand" "=r") 5630 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 5631 (match_operand:SI 2 "s_register_operand" "r")))) 5632 (set (match_operand:SI 0 "s_register_operand" "=r") 5633 (minus:SI (match_dup 1) (match_dup 2)))] 5634 "(!BYTES_BIG_ENDIAN) 5635 && ! TARGET_SHORT_BY_BYTES 5636 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 5637 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 5638 && (GET_CODE (operands[2]) != REG 5639 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 5640 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi" 5641[(set_attr "type" "load")]) 5642 5643(define_insn "*strqi_shiftpreinc" 5644 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator" 5645 [(match_operand:SI 3 "s_register_operand" "r") 5646 (match_operand:SI 4 "const_shift_operand" "n")]) 5647 (match_operand:SI 1 "s_register_operand" "0"))) 5648 (match_operand:QI 5 "s_register_operand" "r")) 5649 (set (match_operand:SI 0 "s_register_operand" "=r") 5650 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 5651 (match_dup 1)))] 5652 "REGNO (operands[0]) != FRAME_POINTER_REGNUM 5653 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 5654 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 5655 "str%?b\\t%5, [%0, %3%S2]!" 5656[(set_attr "type" "store1")]) 5657 5658(define_insn "*strqi_shiftpredec" 5659 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 5660 (match_operator:SI 2 "shift_operator" 5661 [(match_operand:SI 3 "s_register_operand" "r") 5662 (match_operand:SI 4 "const_shift_operand" "n")]))) 5663 (match_operand:QI 5 "s_register_operand" "r")) 5664 (set (match_operand:SI 0 "s_register_operand" "=r") 5665 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 5666 (match_dup 4)])))] 5667 "REGNO (operands[0]) != FRAME_POINTER_REGNUM 5668 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 5669 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 5670 "str%?b\\t%5, [%0, -%3%S2]!" 5671[(set_attr "type" "store1")]) 5672 5673(define_insn "*loadqi_shiftpreinc" 5674 [(set (match_operand:QI 5 "s_register_operand" "=r") 5675 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator" 5676 [(match_operand:SI 3 "s_register_operand" "r") 5677 (match_operand:SI 4 "const_shift_operand" "n")]) 5678 (match_operand:SI 1 "s_register_operand" "0")))) 5679 (set (match_operand:SI 0 "s_register_operand" "=r") 5680 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 5681 (match_dup 1)))] 5682 "REGNO (operands[0]) != FRAME_POINTER_REGNUM 5683 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 5684 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 5685 "ldr%?b\\t%5, [%0, %3%S2]!" 5686[(set_attr "type" "load")]) 5687 5688(define_insn "*loadqi_shiftpredec" 5689 [(set (match_operand:QI 5 "s_register_operand" "=r") 5690 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 5691 (match_operator:SI 2 "shift_operator" 5692 [(match_operand:SI 3 "s_register_operand" "r") 5693 (match_operand:SI 4 "const_shift_operand" "n")])))) 5694 (set (match_operand:SI 0 "s_register_operand" "=r") 5695 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 5696 (match_dup 4)])))] 5697 "REGNO (operands[0]) != FRAME_POINTER_REGNUM 5698 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 5699 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 5700 "ldr%?b\\t%5, [%0, -%3%S2]!" 5701[(set_attr "type" "load")]) 5702 5703(define_insn "*strsi_shiftpreinc" 5704 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator" 5705 [(match_operand:SI 3 "s_register_operand" "r") 5706 (match_operand:SI 4 "const_shift_operand" "n")]) 5707 (match_operand:SI 1 "s_register_operand" "0"))) 5708 (match_operand:SI 5 "s_register_operand" "r")) 5709 (set (match_operand:SI 0 "s_register_operand" "=r") 5710 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 5711 (match_dup 1)))] 5712 "REGNO (operands[0]) != FRAME_POINTER_REGNUM 5713 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 5714 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 5715 "str%?\\t%5, [%0, %3%S2]!" 5716[(set_attr "type" "store1")]) 5717 5718(define_insn "*strsi_shiftpredec" 5719 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 5720 (match_operator:SI 2 "shift_operator" 5721 [(match_operand:SI 3 "s_register_operand" "r") 5722 (match_operand:SI 4 "const_shift_operand" "n")]))) 5723 (match_operand:SI 5 "s_register_operand" "r")) 5724 (set (match_operand:SI 0 "s_register_operand" "=r") 5725 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 5726 (match_dup 4)])))] 5727 "REGNO (operands[0]) != FRAME_POINTER_REGNUM 5728 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 5729 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 5730 "str%?\\t%5, [%0, -%3%S2]!" 5731[(set_attr "type" "store1")]) 5732 5733(define_insn "*loadqi_shiftpreinc" 5734 [(set (match_operand:SI 5 "s_register_operand" "=r") 5735 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator" 5736 [(match_operand:SI 3 "s_register_operand" "r") 5737 (match_operand:SI 4 "const_shift_operand" "n")]) 5738 (match_operand:SI 1 "s_register_operand" "0")))) 5739 (set (match_operand:SI 0 "s_register_operand" "=r") 5740 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 5741 (match_dup 1)))] 5742 "REGNO (operands[0]) != FRAME_POINTER_REGNUM 5743 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 5744 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 5745 "ldr%?\\t%5, [%0, %3%S2]!" 5746[(set_attr "type" "load")]) 5747 5748(define_insn "*loadqi_shiftpredec" 5749 [(set (match_operand:SI 5 "s_register_operand" "=r") 5750 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 5751 (match_operator:SI 2 "shift_operator" 5752 [(match_operand:SI 3 "s_register_operand" "r") 5753 (match_operand:SI 4 "const_shift_operand" "n")])))) 5754 (set (match_operand:SI 0 "s_register_operand" "=r") 5755 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 5756 (match_dup 4)])))] 5757 "REGNO (operands[0]) != FRAME_POINTER_REGNUM 5758 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 5759 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 5760 "ldr%?\\t%5, [%0, -%3%S2]!" 5761[(set_attr "type" "load")]) 5762 5763(define_insn "*loadhi_shiftpreinc" 5764 [(set (match_operand:HI 5 "s_register_operand" "=r") 5765 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator" 5766 [(match_operand:SI 3 "s_register_operand" "r") 5767 (match_operand:SI 4 "const_shift_operand" "n")]) 5768 (match_operand:SI 1 "s_register_operand" "0")))) 5769 (set (match_operand:SI 0 "s_register_operand" "=r") 5770 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 5771 (match_dup 1)))] 5772 "(! BYTES_BIG_ENDIAN) 5773 && ! TARGET_SHORT_BY_BYTES 5774 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 5775 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 5776 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 5777 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi" 5778[(set_attr "type" "load")]) 5779 5780(define_insn "*loadhi_shiftpredec" 5781 [(set (match_operand:HI 5 "s_register_operand" "=r") 5782 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 5783 (match_operator:SI 2 "shift_operator" 5784 [(match_operand:SI 3 "s_register_operand" "r") 5785 (match_operand:SI 4 "const_shift_operand" "n")])))) 5786 (set (match_operand:SI 0 "s_register_operand" "=r") 5787 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 5788 (match_dup 4)])))] 5789 "(! BYTES_BIG_ENDIAN) 5790 && ! TARGET_SHORT_BY_BYTES 5791 && REGNO (operands[0]) != FRAME_POINTER_REGNUM 5792 && REGNO (operands[1]) != FRAME_POINTER_REGNUM 5793 && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 5794 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi" 5795[(set_attr "type" "load")]) 5796 5797; It can also support extended post-inc expressions, but combine doesn't 5798; try these.... 5799; It doesn't seem worth adding peepholes for anything but the most common 5800; cases since, unlike combine, the increment must immediately follow the load 5801; for this pattern to match. 5802; We must watch to see that the source/destination register isn't also the 5803; same as the base address register, and that if the index is a register, 5804; that it is not the same as the base address register. In such cases the 5805; instruction that we would generate would have UNPREDICTABLE behaviour so 5806; we cannot use it. 5807 5808(define_peephole 5809 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r")) 5810 (match_operand:QI 2 "s_register_operand" "r")) 5811 (set (match_dup 0) 5812 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))] 5813 "(REGNO (operands[2]) != REGNO (operands[0])) 5814 && (GET_CODE (operands[1]) != REG || (REGNO (operands[1]) != REGNO (operands[0])))" 5815 "str%?b\\t%2, [%0], %1") 5816 5817(define_peephole 5818 [(set (match_operand:QI 0 "s_register_operand" "=r") 5819 (mem:QI (match_operand:SI 1 "s_register_operand" "+r"))) 5820 (set (match_dup 1) 5821 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))] 5822 "REGNO (operands[0]) != REGNO (operands[1]) 5823 && (GET_CODE (operands[2]) != REG || REGNO (operands[0]) != REGNO (operands[2]))" 5824 "ldr%?b\\t%0, [%1], %2") 5825 5826(define_peephole 5827 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r")) 5828 (match_operand:SI 2 "s_register_operand" "r")) 5829 (set (match_dup 0) 5830 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))] 5831 "(REGNO (operands[2]) != REGNO (operands[0])) 5832 && (GET_CODE (operands[1]) != REG || (REGNO (operands[1]) != REGNO (operands[0])))" 5833 "str%?\\t%2, [%0], %1") 5834 5835(define_peephole 5836 [(set (match_operand:HI 0 "s_register_operand" "=r") 5837 (mem:HI (match_operand:SI 1 "s_register_operand" "+r"))) 5838 (set (match_dup 1) 5839 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))] 5840 "(! BYTES_BIG_ENDIAN) 5841 && ! TARGET_SHORT_BY_BYTES 5842 && REGNO (operands[0]) != REGNO (operands[1]) 5843 && (GET_CODE (operands[2]) != REG || REGNO (operands[0]) != REGNO (operands[2]))" 5844 "ldr%?\\t%0, [%1], %2\\t%@ loadhi") 5845 5846(define_peephole 5847 [(set (match_operand:SI 0 "s_register_operand" "=r") 5848 (mem:SI (match_operand:SI 1 "s_register_operand" "+r"))) 5849 (set (match_dup 1) 5850 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))] 5851 "REGNO (operands[0]) != REGNO (operands[1]) 5852 && (GET_CODE (operands[2]) != REG || REGNO (operands[0]) != REGNO (operands[2]))" 5853 "ldr%?\\t%0, [%1], %2") 5854 5855(define_peephole 5856 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r") 5857 (match_operand:SI 1 "index_operand" "rJ"))) 5858 (match_operand:QI 2 "s_register_operand" "r")) 5859 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))] 5860 "(REGNO (operands[2]) != REGNO (operands[0])) 5861 && (GET_CODE (operands[1]) != REG || (REGNO (operands[1]) != REGNO (operands[0])))" 5862 "str%?b\\t%2, [%0, %1]!") 5863 5864(define_peephole 5865 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator" 5866 [(match_operand:SI 0 "s_register_operand" "r") 5867 (match_operand:SI 1 "const_int_operand" "n")]) 5868 (match_operand:SI 2 "s_register_operand" "+r"))) 5869 (match_operand:QI 3 "s_register_operand" "r")) 5870 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)]) 5871 (match_dup 2)))] 5872 "REGNO (operands[0]) != REGNO (operands[2]) 5873 && REGNO (operands[3]) != REGNO (operands[2])" 5874 "str%?b\\t%3, [%2, %0%S4]!") 5875 5876; This pattern is never tried by combine, so do it as a peephole 5877 5878(define_peephole 5879 [(set (match_operand:SI 0 "s_register_operand" "=r") 5880 (match_operand:SI 1 "s_register_operand" "r")) 5881 (set (reg:CC 24) 5882 (compare:CC (match_dup 1) (const_int 0)))] 5883 "" 5884 "sub%?s\\t%0, %1, #0" 5885[(set_attr "conds" "set")]) 5886 5887; Peepholes to spot possible load- and store-multiples, if the ordering is 5888; reversed, check that the memory references aren't volatile. 5889 5890(define_peephole 5891 [(set (match_operand:SI 0 "s_register_operand" "=r") 5892 (match_operand:SI 4 "memory_operand" "m")) 5893 (set (match_operand:SI 1 "s_register_operand" "=r") 5894 (match_operand:SI 5 "memory_operand" "m")) 5895 (set (match_operand:SI 2 "s_register_operand" "=r") 5896 (match_operand:SI 6 "memory_operand" "m")) 5897 (set (match_operand:SI 3 "s_register_operand" "=r") 5898 (match_operand:SI 7 "memory_operand" "m"))] 5899 "load_multiple_sequence (operands, 4, NULL, NULL, NULL)" 5900 "* 5901 return emit_ldm_seq (operands, 4); 5902") 5903 5904(define_peephole 5905 [(set (match_operand:SI 0 "s_register_operand" "=r") 5906 (match_operand:SI 3 "memory_operand" "m")) 5907 (set (match_operand:SI 1 "s_register_operand" "=r") 5908 (match_operand:SI 4 "memory_operand" "m")) 5909 (set (match_operand:SI 2 "s_register_operand" "=r") 5910 (match_operand:SI 5 "memory_operand" "m"))] 5911 "load_multiple_sequence (operands, 3, NULL, NULL, NULL)" 5912 "* 5913 return emit_ldm_seq (operands, 3); 5914") 5915 5916(define_peephole 5917 [(set (match_operand:SI 0 "s_register_operand" "=r") 5918 (match_operand:SI 2 "memory_operand" "m")) 5919 (set (match_operand:SI 1 "s_register_operand" "=r") 5920 (match_operand:SI 3 "memory_operand" "m"))] 5921 "load_multiple_sequence (operands, 2, NULL, NULL, NULL)" 5922 "* 5923 return emit_ldm_seq (operands, 2); 5924") 5925 5926(define_peephole 5927 [(set (match_operand:SI 4 "memory_operand" "=m") 5928 (match_operand:SI 0 "s_register_operand" "r")) 5929 (set (match_operand:SI 5 "memory_operand" "=m") 5930 (match_operand:SI 1 "s_register_operand" "r")) 5931 (set (match_operand:SI 6 "memory_operand" "=m") 5932 (match_operand:SI 2 "s_register_operand" "r")) 5933 (set (match_operand:SI 7 "memory_operand" "=m") 5934 (match_operand:SI 3 "s_register_operand" "r"))] 5935 "store_multiple_sequence (operands, 4, NULL, NULL, NULL)" 5936 "* 5937 return emit_stm_seq (operands, 4); 5938") 5939 5940(define_peephole 5941 [(set (match_operand:SI 3 "memory_operand" "=m") 5942 (match_operand:SI 0 "s_register_operand" "r")) 5943 (set (match_operand:SI 4 "memory_operand" "=m") 5944 (match_operand:SI 1 "s_register_operand" "r")) 5945 (set (match_operand:SI 5 "memory_operand" "=m") 5946 (match_operand:SI 2 "s_register_operand" "r"))] 5947 "store_multiple_sequence (operands, 3, NULL, NULL, NULL)" 5948 "* 5949 return emit_stm_seq (operands, 3); 5950") 5951 5952(define_peephole 5953 [(set (match_operand:SI 2 "memory_operand" "=m") 5954 (match_operand:SI 0 "s_register_operand" "r")) 5955 (set (match_operand:SI 3 "memory_operand" "=m") 5956 (match_operand:SI 1 "s_register_operand" "r"))] 5957 "store_multiple_sequence (operands, 2, NULL, NULL, NULL)" 5958 "* 5959 return emit_stm_seq (operands, 2); 5960") 5961 5962;; A call followed by return can be replaced by restoring the regs and 5963;; jumping to the subroutine, provided we aren't passing the address of 5964;; any of our local variables. If we call alloca then this is unsafe 5965;; since restoring the frame frees the memory, which is not what we want. 5966;; Sometimes the return might have been targeted by the final prescan: 5967;; if so then emit a proper return insn as well. 5968;; Unfortunately, if the frame pointer is required, we don't know if the 5969;; current function has any implicit stack pointer adjustments that will 5970;; be restored by the return: we can't therefore do a tail call. 5971;; Another unfortunate that we can't handle is if current_function_args_size 5972;; is non-zero: in this case elimination of the argument pointer assumed 5973;; that lr was pushed onto the stack, so eliminating upsets the offset 5974;; calculations. 5975 5976(define_peephole 5977 [(parallel [(call (mem:SI (match_operand:SI 0 "" "X")) 5978 (match_operand:SI 1 "general_operand" "g")) 5979 (clobber (reg:SI 14))]) 5980 (return)] 5981 "(GET_CODE (operands[0]) == SYMBOL_REF && USE_RETURN_INSN(FALSE) 5982 && !get_frame_size () && !current_function_calls_alloca 5983 && !frame_pointer_needed && !current_function_args_size)" 5984 "* 5985{ 5986 extern rtx arm_target_insn; 5987 extern int arm_ccfsm_state; 5988 5989 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn)) 5990 { 5991 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc); 5992 output_return_instruction (NULL, TRUE, FALSE); 5993 arm_ccfsm_state = 0; 5994 arm_target_insn = NULL; 5995 } 5996 5997 output_return_instruction (NULL, FALSE, FALSE); 5998 return NEED_PLT_GOT ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\"; 5999}" 6000[(set_attr "type" "call") 6001 (set_attr "length" "8")]) 6002 6003(define_peephole 6004 [(parallel [(set (match_operand 0 "s_register_operand" "=rf") 6005 (call (mem:SI (match_operand:SI 1 "" "X")) 6006 (match_operand:SI 2 "general_operand" "g"))) 6007 (clobber (reg:SI 14))]) 6008 (return)] 6009 "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN(FALSE) 6010 && !get_frame_size () && !current_function_calls_alloca 6011 && !frame_pointer_needed && !current_function_args_size)" 6012 "* 6013{ 6014 extern rtx arm_target_insn; 6015 extern int arm_ccfsm_state; 6016 6017 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn)) 6018 { 6019 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc); 6020 output_return_instruction (NULL, TRUE, FALSE); 6021 arm_ccfsm_state = 0; 6022 arm_target_insn = NULL; 6023 } 6024 6025 output_return_instruction (NULL, FALSE, FALSE); 6026 return NEED_PLT_GOT ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\"; 6027}" 6028[(set_attr "type" "call") 6029 (set_attr "length" "8")]) 6030 6031;; As above but when this function is not void, we must be returning the 6032;; result of the called subroutine. 6033 6034(define_peephole 6035 [(parallel [(set (match_operand 0 "s_register_operand" "=rf") 6036 (call (mem:SI (match_operand:SI 1 "" "X")) 6037 (match_operand:SI 2 "general_operand" "g"))) 6038 (clobber (reg:SI 14))]) 6039 (use (match_dup 0)) 6040 (return)] 6041 "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN(FALSE) 6042 && !get_frame_size () && !current_function_calls_alloca 6043 && !frame_pointer_needed && !current_function_args_size)" 6044 "* 6045{ 6046 extern rtx arm_target_insn; 6047 extern int arm_ccfsm_state; 6048 6049 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn)) 6050 { 6051 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc); 6052 output_return_instruction (NULL, TRUE, FALSE); 6053 arm_ccfsm_state = 0; 6054 arm_target_insn = NULL; 6055 } 6056 6057 output_return_instruction (NULL, FALSE, FALSE); 6058 return \"b%?\\t%a1\"; 6059}" 6060[(set_attr "type" "call") 6061 (set_attr "length" "8")]) 6062 6063(define_split 6064 [(set (match_operand:SI 0 "s_register_operand" "") 6065 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "") 6066 (const_int 0)) 6067 (neg:SI (match_operator:SI 2 "comparison_operator" 6068 [(match_operand:SI 3 "s_register_operand" "") 6069 (match_operand:SI 4 "arm_rhs_operand" "")])))) 6070 (clobber (match_operand:SI 5 "s_register_operand" ""))] 6071 "" 6072 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31)))) 6073 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 6074 (match_dup 5)))] 6075 "") 6076 6077;; This split can be used because CC_Z mode implies that the following 6078;; branch will be an equality, or an unsigned inequality, so the sign 6079;; extension is not needed. 6080 6081(define_split 6082 [(set (reg:CC_Z 24) 6083 (compare:CC_Z 6084 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0) 6085 (const_int 24)) 6086 (match_operand 1 "const_int_operand" ""))) 6087 (clobber (match_scratch:SI 2 ""))] 6088 "((unsigned HOST_WIDE_INT) INTVAL (operands[1])) 6089 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24" 6090 [(set (match_dup 2) (zero_extend:SI (match_dup 0))) 6091 (set (reg:CC 24) (compare:CC (match_dup 2) (match_dup 1)))] 6092 " 6093 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24); 6094") 6095 6096(define_expand "prologue" 6097 [(clobber (const_int 0))] 6098 "" 6099 " 6100 arm_expand_prologue (); 6101 DONE; 6102") 6103 6104;; This split is only used during output to reduce the number of patterns 6105;; that need assembler instructions adding to them. We allowed the setting 6106;; of the conditions to be implicit during rtl generation so that 6107;; the conditional compare patterns would work. However this conflicts to 6108;; some extent with the conditional data operations, so we have to split them 6109;; up again here. 6110 6111(define_split 6112 [(set (match_operand:SI 0 "s_register_operand" "") 6113 (if_then_else:SI (match_operator 1 "comparison_operator" 6114 [(match_operand 2 "" "") (match_operand 3 "" "")]) 6115 (match_operand 4 "" "") 6116 (match_operand 5 "" ""))) 6117 (clobber (reg:CC 24))] 6118 "reload_completed" 6119 [(set (match_dup 6) (match_dup 7)) 6120 (set (match_dup 0) 6121 (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)]) 6122 (match_dup 4) 6123 (match_dup 5)))] 6124 " 6125{ 6126 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2], 6127 operands[3]); 6128 6129 operands[6] = gen_rtx_REG (mode, 24); 6130 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]); 6131} 6132") 6133 6134;; The next two patterns occur when an AND operation is followed by a 6135;; scc insn sequence 6136 6137(define_insn "*sign_extract_onebit" 6138 [(set (match_operand:SI 0 "s_register_operand" "=r") 6139 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r") 6140 (const_int 1) 6141 (match_operand:SI 2 "const_int_operand" "n")))] 6142 "" 6143 "* 6144 operands[2] = GEN_INT (1 << INTVAL (operands[2])); 6145 output_asm_insn (\"ands\\t%0, %1, %2\", operands); 6146 return \"mvnne\\t%0, #0\"; 6147" 6148[(set_attr "conds" "clob") 6149 (set_attr "length" "8")]) 6150 6151(define_insn "*not_signextract_onebit" 6152 [(set (match_operand:SI 0 "s_register_operand" "=r") 6153 (not:SI 6154 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r") 6155 (const_int 1) 6156 (match_operand:SI 2 "const_int_operand" "n"))))] 6157 "" 6158 "* 6159 operands[2] = GEN_INT (1 << INTVAL (operands[2])); 6160 output_asm_insn (\"tst\\t%1, %2\", operands); 6161 output_asm_insn (\"mvneq\\t%0, #0\", operands); 6162 return \"movne\\t%0, #0\"; 6163" 6164[(set_attr "conds" "clob") 6165 (set_attr "length" "12")]) 6166 6167;; Push multiple registers to the stack. The first register is in the 6168;; unspec part of the insn; subsequent registers are in parallel (use ...) 6169;; expressions. 6170(define_insn "*push_multi" 6171 [(match_parallel 2 "multi_register_push" 6172 [(set (match_operand:BLK 0 "memory_operand" "=m") 6173 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 2))])] 6174 "" 6175 "* 6176{ 6177 char pattern[100]; 6178 int i; 6179 extern int lr_save_eliminated; 6180 6181 if (lr_save_eliminated) 6182 { 6183 if (XVECLEN (operands[2], 0) > 1) 6184 abort (); 6185 return \"\"; 6186 } 6187 strcpy (pattern, \"stmfd\\t%m0!, {%1\"); 6188 for (i = 1; i < XVECLEN (operands[2], 0); i++) 6189 { 6190 strcat (pattern, \", %|\"); 6191 strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 6192 0))]); 6193 } 6194 strcat (pattern, \"}\"); 6195 output_asm_insn (pattern, operands); 6196 return \"\"; 6197}" 6198[(set_attr "type" "store4")]) 6199 6200;; Similarly for the floating point registers 6201(define_insn "*push_fp_multi" 6202 [(match_parallel 2 "multi_register_push" 6203 [(set (match_operand:BLK 0 "memory_operand" "=m") 6204 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")] 2))])] 6205 "" 6206 "* 6207{ 6208 char pattern[100]; 6209 6210 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0)); 6211 output_asm_insn (pattern, operands); 6212 return \"\"; 6213}" 6214[(set_attr "type" "f_store")]) 6215 6216;; Special patterns for dealing with the constant pool 6217 6218(define_insn "consttable_4" 6219 [(unspec_volatile [(match_operand 0 "" "")] 2)] 6220 "" 6221 "* 6222{ 6223 making_const_table = TRUE; 6224 switch (GET_MODE_CLASS (GET_MODE (operands[0]))) 6225 { 6226 case MODE_FLOAT: 6227 { 6228 union real_extract u; 6229 bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u); 6230 assemble_real (u.d, GET_MODE (operands[0])); 6231 break; 6232 } 6233 default: 6234 assemble_integer (operands[0], 4, 1); 6235 break; 6236 } 6237 return \"\"; 6238}" 6239[(set_attr "length" "4")]) 6240 6241(define_insn "consttable_8" 6242 [(unspec_volatile [(match_operand 0 "" "")] 3)] 6243 "" 6244 "* 6245{ 6246 making_const_table = TRUE; 6247 switch (GET_MODE_CLASS (GET_MODE (operands[0]))) 6248 { 6249 case MODE_FLOAT: 6250 { 6251 union real_extract u; 6252 bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u); 6253 assemble_real (u.d, GET_MODE (operands[0])); 6254 break; 6255 } 6256 default: 6257 assemble_integer (operands[0], 8, 1); 6258 break; 6259 } 6260 return \"\"; 6261}" 6262[(set_attr "length" "8")]) 6263 6264(define_insn "consttable_end" 6265 [(unspec_volatile [(const_int 0)] 4)] 6266 "" 6267 "* 6268 making_const_table = FALSE; 6269 return \"\"; 6270") 6271 6272(define_insn "align_4" 6273 [(unspec_volatile [(const_int 0)] 5)] 6274 "" 6275 "* 6276 assemble_align (32); 6277 return \"\"; 6278") 6279