1;;- Machine description for the Hitachi SH. 2;; Copyright (C) 1993 - 1999 Free Software Foundation, Inc. 3;; Contributed by Steve Chamberlain (sac@cygnus.com). 4;; Improved by Jim Wilson (wilson@cygnus.com). 5 6;; This file is part of GNU CC. 7 8;; GNU CC is free software; you can redistribute it and/or modify 9;; it under the terms of the GNU General Public License as published by 10;; the Free Software Foundation; either version 2, or (at your option) 11;; any later version. 12 13;; GNU CC is distributed in the hope that it will be useful, 14;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16;; GNU General Public License for more details. 17 18;; You should have received a copy of the GNU General Public License 19;; along with GNU CC; see the file COPYING. If not, write to 20;; the Free Software Foundation, 59 Temple Place - Suite 330, 21;; Boston, MA 02111-1307, USA. 22 23 24;; ??? Should prepend a * to all pattern names which are not used. 25;; This will make the compiler smaller, and rebuilds after changes faster. 26 27;; ??? Should be enhanced to include support for many more GNU superoptimizer 28;; sequences. Especially the sequences for arithmetic right shifts. 29 30;; ??? Should check all DImode patterns for consistency and usefulness. 31 32;; ??? The MAC.W and MAC.L instructions are not supported. There is no 33;; way to generate them. 34 35;; ??? The cmp/str instruction is not supported. Perhaps it can be used 36;; for a str* inline function. 37 38;; BSR is not generated by the compiler proper, but when relaxing, it 39;; generates .uses pseudo-ops that allow linker relaxation to create 40;; BSR. This is actually implemented in bfd/{coff,elf32}-sh.c 41 42;; Special constraints for SH machine description: 43;; 44;; t -- T 45;; x -- mac 46;; l -- pr 47;; z -- r0 48;; 49;; Special formats used for outputting SH instructions: 50;; 51;; %. -- print a .s if insn needs delay slot 52;; %@ -- print rte/rts if is/isn't an interrupt function 53;; %# -- output a nop if there is nothing to put in the delay slot 54;; %O -- print a constant without the # 55;; %R -- print the lsw reg of a double 56;; %S -- print the msw reg of a double 57;; %T -- print next word of a double REG or MEM 58;; 59;; Special predicates: 60;; 61;; arith_operand -- operand is valid source for arithmetic op 62;; arith_reg_operand -- operand is valid register for arithmetic op 63;; general_movdst_operand -- operand is valid move destination 64;; general_movsrc_operand -- operand is valid move source 65;; logical_operand -- operand is valid source for logical op 66;; ------------------------------------------------------------------------- 67;; Attributes 68;; ------------------------------------------------------------------------- 69 70;; Target CPU. 71 72(define_attr "cpu" 73 "sh1,sh2,sh3,sh3e,sh4" 74 (const (symbol_ref "sh_cpu_attr"))) 75 76(define_attr "endian" "big,little" 77 (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN") 78 (const_string "little") (const_string "big")))) 79 80(define_attr "fmovd" "yes,no" 81 (const (if_then_else (symbol_ref "TARGET_FMOVD") 82 (const_string "yes") (const_string "no")))) 83;; issues/clock 84(define_attr "issues" "1,2" 85 (const (if_then_else (symbol_ref "TARGET_SUPERSCALAR") (const_string "2") (const_string "1")))) 86 87;; cbranch conditional branch instructions 88;; jump unconditional jumps 89;; arith ordinary arithmetic 90;; arith3 a compound insn that behaves similarly to a sequence of 91;; three insns of type arith 92;; arith3b like above, but might end with a redirected branch 93;; load from memory 94;; load_si Likewise, SImode variant for general register. 95;; store to memory 96;; move register to register 97;; fmove register to register, floating point 98;; smpy word precision integer multiply 99;; dmpy longword or doublelongword precision integer multiply 100;; return rts 101;; pload load of pr reg, which can't be put into delay slot of rts 102;; pstore store of pr reg, which can't be put into delay slot of jsr 103;; pcload pc relative load of constant value 104;; pcload_si Likewise, SImode variant for general register. 105;; rte return from exception 106;; sfunc special function call with known used registers 107;; call function call 108;; fp floating point 109;; fdiv floating point divide (or square root) 110;; gp_fpul move between general purpose register and fpul 111;; dfp_arith, dfp_cmp,dfp_conv 112;; dfdiv double precision floating point divide (or square root) 113;; nil no-op move, will be deleted. 114 115(define_attr "type" 116 "cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,other,load,load_si,store,move,fmove,smpy,dmpy,return,pload,pstore,pcload,pcload_si,rte,sfunc,call,fp,fdiv,dfp_arith,dfp_cmp,dfp_conv,dfdiv,gp_fpul,nil" 117 (const_string "other")) 118 119; If a conditional branch destination is within -252..258 bytes away 120; from the instruction it can be 2 bytes long. Something in the 121; range -4090..4100 bytes can be 6 bytes long. All other conditional 122; branches are initially assumed to be 16 bytes long. 123; In machine_dependent_reorg, we split all branches that are longer than 124; 2 bytes. 125 126;; The maximum range used for SImode constant pool entrys is 1018. A final 127;; instruction can add 8 bytes while only being 4 bytes in size, thus we 128;; can have a total of 1022 bytes in the pool. Add 4 bytes for a branch 129;; instruction around the pool table, 2 bytes of alignment before the table, 130;; and 30 bytes of alignment after the table. That gives a maximum total 131;; pool size of 1058 bytes. 132;; Worst case code/pool content size ratio is 1:2 (using asms). 133;; Thus, in the worst case, there is one instruction in front of a maximum 134;; sized pool, and then there are 1052 bytes of pool for every 508 bytes of 135;; code. For the last n bytes of code, there are 2n + 36 bytes of pool. 136;; If we have a forward branch, the initial table will be put after the 137;; unconditional branch. 138;; 139;; ??? We could do much better by keeping track of the actual pcloads within 140;; the branch range and in the pcload range in front of the branch range. 141 142;; ??? This looks ugly because genattrtab won't allow if_then_else or cond 143;; inside an le. 144(define_attr "short_cbranch_p" "no,yes" 145 (cond [(ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0)) 146 (const_string "no") 147 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506)) 148 (const_string "yes") 149 (ne (symbol_ref "NEXT_INSN (PREV_INSN (insn)) != insn") (const_int 0)) 150 (const_string "no") 151 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508)) 152 (const_string "yes") 153 ] (const_string "no"))) 154 155(define_attr "med_branch_p" "no,yes" 156 (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990)) 157 (const_int 1988)) 158 (const_string "yes") 159 (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0)) 160 (const_string "no") 161 (leu (plus (minus (match_dup 0) (pc)) (const_int 4092)) 162 (const_int 8186)) 163 (const_string "yes") 164 ] (const_string "no"))) 165 166(define_attr "med_cbranch_p" "no,yes" 167 (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988)) 168 (const_int 1986)) 169 (const_string "yes") 170 (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0)) 171 (const_string "no") 172 (leu (plus (minus (match_dup 0) (pc)) (const_int 4090)) 173 (const_int 8184)) 174 (const_string "yes") 175 ] (const_string "no"))) 176 177(define_attr "braf_branch_p" "no,yes" 178 (cond [(ne (symbol_ref "! TARGET_SH2") (const_int 0)) 179 (const_string "no") 180 (leu (plus (minus (match_dup 0) (pc)) (const_int 10330)) 181 (const_int 20660)) 182 (const_string "yes") 183 (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0)) 184 (const_string "no") 185 (leu (plus (minus (match_dup 0) (pc)) (const_int 32764)) 186 (const_int 65530)) 187 (const_string "yes") 188 ] (const_string "no"))) 189 190(define_attr "braf_cbranch_p" "no,yes" 191 (cond [(ne (symbol_ref "! TARGET_SH2") (const_int 0)) 192 (const_string "no") 193 (leu (plus (minus (match_dup 0) (pc)) (const_int 10328)) 194 (const_int 20658)) 195 (const_string "yes") 196 (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0)) 197 (const_string "no") 198 (leu (plus (minus (match_dup 0) (pc)) (const_int 32762)) 199 (const_int 65528)) 200 (const_string "yes") 201 ] (const_string "no"))) 202 203; An unconditional jump in the range -4092..4098 can be 2 bytes long. 204; For wider ranges, we need a combination of a code and a data part. 205; If we can get a scratch register for a long range jump, the code 206; part can be 4 bytes long; otherwise, it must be 8 bytes long. 207; If the jump is in the range -32764..32770, the data part can be 2 bytes 208; long; otherwise, it must be 6 bytes long. 209 210; All other instructions are two bytes long by default. 211 212;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)), 213;; but getattrtab doesn't understand this. 214(define_attr "length" "" 215 (cond [(eq_attr "type" "cbranch") 216 (cond [(eq_attr "short_cbranch_p" "yes") 217 (const_int 2) 218 (eq_attr "med_cbranch_p" "yes") 219 (const_int 6) 220 (eq_attr "braf_cbranch_p" "yes") 221 (const_int 12) 222;; ??? using pc is not computed transitively. 223 (ne (match_dup 0) (match_dup 0)) 224 (const_int 14) 225 ] (const_int 16)) 226 (eq_attr "type" "jump") 227 (cond [(eq_attr "med_branch_p" "yes") 228 (const_int 2) 229 (and (eq (symbol_ref "GET_CODE (PREV_INSN (insn))") 230 (symbol_ref "INSN")) 231 (eq (symbol_ref "INSN_CODE (PREV_INSN (insn))") 232 (symbol_ref "code_for_indirect_jump_scratch"))) 233 (if_then_else (eq_attr "braf_branch_p" "yes") 234 (const_int 6) 235 (const_int 10)) 236 (eq_attr "braf_branch_p" "yes") 237 (const_int 10) 238;; ??? using pc is not computed transitively. 239 (ne (match_dup 0) (match_dup 0)) 240 (const_int 12) 241 ] (const_int 14)) 242 ] (const_int 2))) 243 244;; (define_function_unit {name} {num-units} {n-users} {test} 245;; {ready-delay} {issue-delay} [{conflict-list}]) 246 247;; Load and store instructions save a cycle if they are aligned on a 248;; four byte boundary. Using a function unit for stores encourages 249;; gcc to separate load and store instructions by one instruction, 250;; which makes it more likely that the linker will be able to word 251;; align them when relaxing. 252 253;; Loads have a latency of two. 254;; However, call insns can have a delay slot, so that we want one more 255;; insn to be scheduled between the load of the function address and the call. 256;; This is equivalent to a latency of three. 257;; We cannot use a conflict list for this, because we need to distinguish 258;; between the actual call address and the function arguments. 259;; ADJUST_COST can only properly handle reductions of the cost, so we 260;; use a latency of three here. 261;; We only do this for SImode loads of general registers, to make the work 262;; for ADJUST_COST easier. 263(define_function_unit "memory" 1 0 264 (and (eq_attr "issues" "1") 265 (eq_attr "type" "load_si,pcload_si")) 266 3 2) 267(define_function_unit "memory" 1 0 268 (and (eq_attr "issues" "1") 269 (eq_attr "type" "load,pcload,pload,store,pstore")) 270 2 2) 271 272(define_function_unit "int" 1 0 273 (and (eq_attr "issues" "1") (eq_attr "type" "arith3,arith3b")) 3 3) 274 275(define_function_unit "int" 1 0 276 (and (eq_attr "issues" "1") (eq_attr "type" "dyn_shift")) 2 2) 277 278(define_function_unit "int" 1 0 279 (and (eq_attr "issues" "1") (eq_attr "type" "!arith3,arith3b,dyn_shift")) 1 1) 280 281;; ??? These are approximations. 282(define_function_unit "mpy" 1 0 283 (and (eq_attr "issues" "1") (eq_attr "type" "smpy")) 2 2) 284(define_function_unit "mpy" 1 0 285 (and (eq_attr "issues" "1") (eq_attr "type" "dmpy")) 3 3) 286 287(define_function_unit "fp" 1 0 288 (and (eq_attr "issues" "1") (eq_attr "type" "fp,fmove")) 2 1) 289(define_function_unit "fp" 1 0 290 (and (eq_attr "issues" "1") (eq_attr "type" "fdiv")) 13 12) 291 292 293;; SH4 scheduling 294;; The SH4 is a dual-issue implementation, thus we have to multiply all 295;; costs by at least two. 296;; There will be single increments of the modeled that don't correspond 297;; to the actual target ;; whenever two insns to be issued depend one a 298;; single resource, and the scheduler picks to be the first one. 299;; If we multiplied the costs just by two, just two of these single 300;; increments would amount to an actual cycle. By picking a larger 301;; factor, we can ameliorate the effect; However, we then have to make sure 302;; that only two insns are modeled as issued per actual cycle. 303;; Moreover, we need a way to specify the latency of insns that don't 304;; use an actual function unit. 305;; We use an 'issue' function unit to do that, and a cost factor of 10. 306 307(define_function_unit "issue" 2 0 308 (and (eq_attr "issues" "2") (eq_attr "type" "!nil,arith3")) 309 10 10) 310 311(define_function_unit "issue" 2 0 312 (and (eq_attr "issues" "2") (eq_attr "type" "arith3")) 313 30 30) 314 315;; There is no point in providing exact scheduling information about branches, 316;; because they are at the starts / ends of basic blocks anyways. 317 318;; Some insns cannot be issued before/after another insn in the same cycle, 319;; irrespective of the type of the other insn. 320 321;; default is dual-issue, but can't be paired with an insn that 322;; uses multiple function units. 323(define_function_unit "single_issue" 1 0 324 (and (eq_attr "issues" "2") 325 (eq_attr "type" "!smpy,dmpy,pload,pstore,dfp_cmp,gp_fpul,call,sfunc,arith3,arith3b")) 326 1 10 327 [(eq_attr "type" "smpy,dmpy,pload,pstore,dfp_cmp,gp_fpul")]) 328 329(define_function_unit "single_issue" 1 0 330 (and (eq_attr "issues" "2") 331 (eq_attr "type" "smpy,dmpy,pload,pstore,dfp_cmp,gp_fpul")) 332 10 10 333 [(const_int 1)]) 334 335;; arith3 insns are always pairable at the start, but not inecessarily at 336;; the end; however, there doesn;t seem to be a way to express that. 337(define_function_unit "single_issue" 1 0 338 (and (eq_attr "issues" "2") 339 (eq_attr "type" "arith3")) 340 30 20 341 [(const_int 1)]) 342 343;; arith3b insn are pairable at the end and have latency that prevents pairing 344;; with the following branch, but we don't want this latency be respected; 345;; When the following branch is immediately adjacent, we can redirect the 346;; internal branch, which is likly to be a larger win. 347(define_function_unit "single_issue" 1 0 348 (and (eq_attr "issues" "2") 349 (eq_attr "type" "arith3b")) 350 20 20 351 [(const_int 1)]) 352 353;; calls introduce a longisch delay that is likely to flush the pipelines. 354(define_function_unit "single_issue" 1 0 355 (and (eq_attr "issues" "2") 356 (eq_attr "type" "call,sfunc")) 357 160 160 358 [(eq_attr "type" "!call") (eq_attr "type" "call")]) 359 360;; Load and store instructions have no alignment peculiarities for the SH4, 361;; but they use the load-store unit, which they share with the fmove type 362;; insns (fldi[01]; fmov frn,frm; flds; fsts; fabs; fneg) . 363;; Loads have a latency of two. 364;; However, call insns can only paired with a preceding insn, and have 365;; a delay slot, so that we want two more insns to be scheduled between the 366;; load of the function address and the call. This is equivalent to a 367;; latency of three. 368;; We cannot use a conflict list for this, because we need to distinguish 369;; between the actual call address and the function arguments. 370;; ADJUST_COST can only properly handle reductions of the cost, so we 371;; use a latency of three here, which gets multiplied by 10 to yield 30. 372;; We only do this for SImode loads of general registers, to make the work 373;; for ADJUST_COST easier. 374 375;; When specifying different latencies for different insns using the 376;; the same function unit, genattrtab.c assumes a 'FIFO constraint' 377;; so that the blockage is at least READY-COST (E) + 1 - READY-COST (C) 378;; for an executing insn E and a candidate insn C. 379;; Therefore, we define three different function units for load_store: 380;; load_store, load and load_si. 381 382(define_function_unit "load_si" 1 0 383 (and (eq_attr "issues" "2") 384 (eq_attr "type" "load_si,pcload_si")) 30 10) 385(define_function_unit "load" 1 0 386 (and (eq_attr "issues" "2") 387 (eq_attr "type" "load,pcload,pload")) 20 10) 388(define_function_unit "load_store" 1 0 389 (and (eq_attr "issues" "2") 390 (eq_attr "type" "load_si,pcload_si,load,pcload,pload,store,pstore,fmove")) 391 10 10) 392 393(define_function_unit "int" 1 0 394 (and (eq_attr "issues" "2") (eq_attr "type" "arith,dyn_shift")) 10 10) 395 396;; Again, we have to pretend a lower latency for the "int" unit to avoid a 397;; spurious FIFO constraint; the multiply instructions use the "int" 398;; unit actually only for two cycles. 399(define_function_unit "int" 1 0 400 (and (eq_attr "issues" "2") (eq_attr "type" "smpy,dmpy")) 20 20) 401 402;; We use a fictous "mpy" unit to express the actual latency. 403(define_function_unit "mpy" 1 0 404 (and (eq_attr "issues" "2") (eq_attr "type" "smpy,dmpy")) 40 20) 405 406;; Again, we have to pretend a lower latency for the "int" unit to avoid a 407;; spurious FIFO constraint. 408(define_function_unit "int" 1 0 409 (and (eq_attr "issues" "2") (eq_attr "type" "gp_fpul")) 10 10) 410 411;; We use a fictous "gp_fpul" unit to express the actual latency. 412(define_function_unit "gp_fpul" 1 0 413 (and (eq_attr "issues" "2") (eq_attr "type" "gp_fpul")) 20 10) 414 415;; ??? multiply uses the floating point unit, but with a two cycle delay. 416;; Thus, a simple single-precision fp operation could finish if issued in 417;; the very next cycle, but stalls when issued two or three cycles later. 418;; Similarily, a divide / sqrt can work without stalls if issued in 419;; the very next cycle, while it would have to block if issued two or 420;; three cycles later. 421;; There is no way to model this with gcc's function units. This problem is 422;; actually mentioned in md.texi. Tackling this problem requires first that 423;; it is possible to speak about the target in an open discussion. 424;; 425;; However, simple double-precision operations always conflict. 426 427(define_function_unit "fp" 1 0 428 (and (eq_attr "issues" "2") (eq_attr "type" "smpy,dmpy")) 40 40 429 [(eq_attr "type" "dfp_cmp,dfp_conv,dfp_arith")]) 430 431;; The "fp" unit is for pipeline stages F1 and F2. 432 433(define_function_unit "fp" 1 0 434 (and (eq_attr "issues" "2") (eq_attr "type" "fp")) 30 10) 435 436;; Again, we have to pretend a lower latency for the "fp" unit to avoid a 437;; spurious FIFO constraint; the bulk of the fdiv type insns executes in 438;; the F3 stage. 439(define_function_unit "fp" 1 0 440 (and (eq_attr "issues" "2") (eq_attr "type" "fdiv")) 30 10) 441 442;; The "fdiv" function unit models the aggregate effect of the F1, F2 and F3 443;; pipeline stages on the pipelining of fdiv/fsqrt insns. 444;; We also use it to give the actual latency here. 445;; fsqrt is actually one cycle faster than fdiv (and the value used here), 446;; but that will hardly matter in practice for scheduling. 447(define_function_unit "fdiv" 1 0 448 (and (eq_attr "issues" "2") (eq_attr "type" "fdiv")) 120 100) 449 450;; There is again a late use of the "fp" unit by [d]fdiv type insns 451;; that we can't express. 452 453(define_function_unit "fp" 1 0 454 (and (eq_attr "issues" "2") (eq_attr "type" "dfp_cmp,dfp_conv")) 40 20) 455 456(define_function_unit "fp" 1 0 457 (and (eq_attr "issues" "2") (eq_attr "type" "dfp_arith")) 80 60) 458 459(define_function_unit "fp" 1 0 460 (and (eq_attr "issues" "2") (eq_attr "type" "dfdiv")) 230 10) 461 462(define_function_unit "fdiv" 1 0 463 (and (eq_attr "issues" "2") (eq_attr "type" "dfdiv")) 230 210) 464 465; Definitions for filling branch delay slots. 466 467(define_attr "needs_delay_slot" "yes,no" (const_string "no")) 468 469;; ??? This should be (nil) instead of (const_int 0) 470(define_attr "hit_stack" "yes,no" 471 (cond [(eq (symbol_ref "find_regno_note (insn, REG_INC, 15)") (const_int 0)) 472 (const_string "no")] 473 (const_string "yes"))) 474 475(define_attr "interrupt_function" "no,yes" 476 (const (symbol_ref "pragma_interrupt"))) 477 478(define_attr "in_delay_slot" "yes,no" 479 (cond [(eq_attr "type" "cbranch") (const_string "no") 480 (eq_attr "type" "pcload,pcload_si") (const_string "no") 481 (eq_attr "needs_delay_slot" "yes") (const_string "no") 482 (eq_attr "length" "2") (const_string "yes") 483 ] (const_string "no"))) 484 485(define_attr "is_sfunc" "" 486 (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0))) 487 488(define_delay 489 (eq_attr "needs_delay_slot" "yes") 490 [(eq_attr "in_delay_slot" "yes") (nil) (nil)]) 491 492;; On the SH and SH2, the rte instruction reads the return pc from the stack, 493;; and thus we can't put a pop instruction in its delay slot. 494;; ??? On the SH3, the rte instruction does not use the stack, so a pop 495;; instruction can go in the delay slot. 496 497;; Since a normal return (rts) implicitly uses the PR register, 498;; we can't allow PR register loads in an rts delay slot. 499 500(define_delay 501 (eq_attr "type" "return") 502 [(and (eq_attr "in_delay_slot" "yes") 503 (ior (and (eq_attr "interrupt_function" "no") 504 (eq_attr "type" "!pload")) 505 (and (eq_attr "interrupt_function" "yes") 506 (eq_attr "hit_stack" "no")))) (nil) (nil)]) 507 508;; Since a call implicitly uses the PR register, we can't allow 509;; a PR register store in a jsr delay slot. 510 511(define_delay 512 (ior (eq_attr "type" "call") (eq_attr "type" "sfunc")) 513 [(and (eq_attr "in_delay_slot" "yes") 514 (eq_attr "type" "!pstore")) (nil) (nil)]) 515 516;; Say that we have annulled true branches, since this gives smaller and 517;; faster code when branches are predicted as not taken. 518 519(define_delay 520 (and (eq_attr "type" "cbranch") 521 (ne (symbol_ref "TARGET_SH2") (const_int 0))) 522 [(eq_attr "in_delay_slot" "yes") (eq_attr "in_delay_slot" "yes") (nil)]) 523 524;; ------------------------------------------------------------------------- 525;; SImode signed integer comparisons 526;; ------------------------------------------------------------------------- 527 528(define_insn "" 529 [(set (reg:SI 18) 530 (eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "z,r") 531 (match_operand:SI 1 "arith_operand" "L,r")) 532 (const_int 0)))] 533 "" 534 "tst %1,%0") 535 536;; ??? Perhaps should only accept reg/constant if the register is reg 0. 537;; That would still allow reload to create cmpi instructions, but would 538;; perhaps allow forcing the constant into a register when that is better. 539;; Probably should use r0 for mem/imm compares, but force constant into a 540;; register for pseudo/imm compares. 541 542(define_insn "cmpeqsi_t" 543 [(set (reg:SI 18) (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r") 544 (match_operand:SI 1 "arith_operand" "N,rI,r")))] 545 "" 546 "@ 547 tst %0,%0 548 cmp/eq %1,%0 549 cmp/eq %1,%0") 550 551(define_insn "cmpgtsi_t" 552 [(set (reg:SI 18) (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r") 553 (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))] 554 "" 555 "@ 556 cmp/gt %1,%0 557 cmp/pl %0") 558 559(define_insn "cmpgesi_t" 560 [(set (reg:SI 18) (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r") 561 (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))] 562 "" 563 "@ 564 cmp/ge %1,%0 565 cmp/pz %0") 566 567;; ------------------------------------------------------------------------- 568;; SImode unsigned integer comparisons 569;; ------------------------------------------------------------------------- 570 571(define_insn "cmpgeusi_t" 572 [(set (reg:SI 18) (geu:SI (match_operand:SI 0 "arith_reg_operand" "r") 573 (match_operand:SI 1 "arith_reg_operand" "r")))] 574 "" 575 "cmp/hs %1,%0") 576 577(define_insn "cmpgtusi_t" 578 [(set (reg:SI 18) (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r") 579 (match_operand:SI 1 "arith_reg_operand" "r")))] 580 "" 581 "cmp/hi %1,%0") 582 583;; We save the compare operands in the cmpxx patterns and use them when 584;; we generate the branch. 585 586(define_expand "cmpsi" 587 [(set (reg:SI 18) (compare (match_operand:SI 0 "arith_operand" "") 588 (match_operand:SI 1 "arith_operand" "")))] 589 "" 590 " 591{ 592 sh_compare_op0 = operands[0]; 593 sh_compare_op1 = operands[1]; 594 DONE; 595}") 596 597;; ------------------------------------------------------------------------- 598;; DImode signed integer comparisons 599;; ------------------------------------------------------------------------- 600 601;; ??? Could get better scheduling by splitting the initial test from the 602;; rest of the insn after reload. However, the gain would hardly justify 603;; the sh.md size increase necessary to do that. 604 605(define_insn "" 606 [(set (reg:SI 18) 607 (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r") 608 (match_operand:DI 1 "arith_operand" "r")) 609 (const_int 0)))] 610 "" 611 "* return output_branchy_insn (EQ, \"tst\\t%S1,%S0\;bf\\t%l9\;tst\\t%R1,%R0\", 612 insn, operands);" 613 [(set_attr "length" "6") 614 (set_attr "type" "arith3b")]) 615 616(define_insn "cmpeqdi_t" 617 [(set (reg:SI 18) (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r") 618 (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))] 619 "" 620 "* 621 return output_branchy_insn 622 (EQ, 623 (which_alternative 624 ? \"cmp/eq\\t%S1,%S0\;bf\\t%l9\;cmp/eq\\t%R1,%R0\" 625 : \"tst\\t%S0,%S0\;bf\\t%l9\;tst\\t%R0,%R0\"), 626 insn, operands);" 627 [(set_attr "length" "6") 628 (set_attr "type" "arith3b")]) 629 630(define_insn "cmpgtdi_t" 631 [(set (reg:SI 18) (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r") 632 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))] 633 "TARGET_SH2" 634 "@ 635 cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/gt\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=: 636 tst\\t%S0,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/pl\\t%S0\;cmp/hi\\t%S0,%R0\\n%,Ldi%=:" 637 [(set_attr "length" "8") 638 (set_attr "type" "arith3")]) 639 640(define_insn "cmpgedi_t" 641 [(set (reg:SI 18) (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r") 642 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))] 643 "TARGET_SH2" 644 "@ 645 cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/ge\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=: 646 cmp/pz\\t%S0" 647 [(set_attr "length" "8,2") 648 (set_attr "type" "arith3,arith")]) 649 650;; ------------------------------------------------------------------------- 651;; DImode unsigned integer comparisons 652;; ------------------------------------------------------------------------- 653 654(define_insn "cmpgeudi_t" 655 [(set (reg:SI 18) (geu:SI (match_operand:DI 0 "arith_reg_operand" "r") 656 (match_operand:DI 1 "arith_reg_operand" "r")))] 657 "TARGET_SH2" 658 "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hs\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:" 659 [(set_attr "length" "8") 660 (set_attr "type" "arith3")]) 661 662(define_insn "cmpgtudi_t" 663 [(set (reg:SI 18) (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r") 664 (match_operand:DI 1 "arith_reg_operand" "r")))] 665 "TARGET_SH2" 666 "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hi\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:" 667 [(set_attr "length" "8") 668 (set_attr "type" "arith3")]) 669 670;; We save the compare operands in the cmpxx patterns and use them when 671;; we generate the branch. 672 673(define_expand "cmpdi" 674 [(set (reg:SI 18) (compare (match_operand:DI 0 "arith_operand" "") 675 (match_operand:DI 1 "arith_operand" "")))] 676 "TARGET_SH2" 677 " 678{ 679 sh_compare_op0 = operands[0]; 680 sh_compare_op1 = operands[1]; 681 DONE; 682}") 683 684;; ------------------------------------------------------------------------- 685;; Addition instructions 686;; ------------------------------------------------------------------------- 687 688;; ??? This should be a define expand. 689 690(define_insn "adddi3" 691 [(set (match_operand:DI 0 "arith_reg_operand" "=r") 692 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0") 693 (match_operand:DI 2 "arith_reg_operand" "r"))) 694 (clobber (reg:SI 18))] 695 "" 696 "#" 697 [(set_attr "length" "6")]) 698 699(define_split 700 [(set (match_operand:DI 0 "arith_reg_operand" "=r") 701 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0") 702 (match_operand:DI 2 "arith_reg_operand" "r"))) 703 (clobber (reg:SI 18))] 704 "reload_completed" 705 [(const_int 0)] 706 " 707{ 708 rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]); 709 high0 = gen_rtx (REG, SImode, 710 true_regnum (operands[0]) + (TARGET_LITTLE_ENDIAN ? 1 : 0)); 711 high2 = gen_rtx (REG, SImode, 712 true_regnum (operands[2]) + (TARGET_LITTLE_ENDIAN ? 1 : 0)); 713 emit_insn (gen_clrt ()); 714 emit_insn (gen_addc (low0, low0, gen_lowpart (SImode, operands[2]))); 715 emit_insn (gen_addc1 (high0, high0, high2)); 716 DONE; 717}") 718 719(define_insn "addc" 720 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 721 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0") 722 (match_operand:SI 2 "arith_reg_operand" "r")) 723 (reg:SI 18))) 724 (set (reg:SI 18) 725 (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))] 726 "" 727 "addc %2,%0" 728 [(set_attr "type" "arith")]) 729 730(define_insn "addc1" 731 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 732 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0") 733 (match_operand:SI 2 "arith_reg_operand" "r")) 734 (reg:SI 18))) 735 (clobber (reg:SI 18))] 736 "" 737 "addc %2,%0" 738 [(set_attr "type" "arith")]) 739 740(define_insn "addsi3" 741 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 742 (plus:SI (match_operand:SI 1 "arith_operand" "%0") 743 (match_operand:SI 2 "arith_operand" "rI")))] 744 "" 745 "add %2,%0" 746 [(set_attr "type" "arith")]) 747 748;; ------------------------------------------------------------------------- 749;; Subtraction instructions 750;; ------------------------------------------------------------------------- 751 752;; ??? This should be a define expand. 753 754(define_insn "subdi3" 755 [(set (match_operand:DI 0 "arith_reg_operand" "=r") 756 (minus:DI (match_operand:DI 1 "arith_reg_operand" "0") 757 (match_operand:DI 2 "arith_reg_operand" "r"))) 758 (clobber (reg:SI 18))] 759 "" 760 "#" 761 [(set_attr "length" "6")]) 762 763(define_split 764 [(set (match_operand:DI 0 "arith_reg_operand" "=r") 765 (minus:DI (match_operand:DI 1 "arith_reg_operand" "0") 766 (match_operand:DI 2 "arith_reg_operand" "r"))) 767 (clobber (reg:SI 18))] 768 "reload_completed" 769 [(const_int 0)] 770 " 771{ 772 rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]); 773 high0 = gen_rtx (REG, SImode, 774 true_regnum (operands[0]) + (TARGET_LITTLE_ENDIAN ? 1 : 0)); 775 high2 = gen_rtx (REG, SImode, 776 true_regnum (operands[2]) + (TARGET_LITTLE_ENDIAN ? 1 : 0)); 777 emit_insn (gen_clrt ()); 778 emit_insn (gen_subc (low0, low0, gen_lowpart (SImode, operands[2]))); 779 emit_insn (gen_subc1 (high0, high0, high2)); 780 DONE; 781}") 782 783(define_insn "subc" 784 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 785 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0") 786 (match_operand:SI 2 "arith_reg_operand" "r")) 787 (reg:SI 18))) 788 (set (reg:SI 18) 789 (gtu:SI (minus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))] 790 "" 791 "subc %2,%0" 792 [(set_attr "type" "arith")]) 793 794(define_insn "subc1" 795 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 796 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0") 797 (match_operand:SI 2 "arith_reg_operand" "r")) 798 (reg:SI 18))) 799 (clobber (reg:SI 18))] 800 "" 801 "subc %2,%0" 802 [(set_attr "type" "arith")]) 803 804(define_insn "*subsi3_internal" 805 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 806 (minus:SI (match_operand:SI 1 "arith_reg_operand" "0") 807 (match_operand:SI 2 "arith_reg_operand" "r")))] 808 "" 809 "sub %2,%0" 810 [(set_attr "type" "arith")]) 811 812;; Convert `constant - reg' to `neg rX; add rX, #const' since this 813;; will sometimes save one instruction. Otherwise we might get 814;; `mov #const, rY; sub rY,rX; mov rX, rY' if the source and dest regs 815;; are the same. 816 817(define_expand "subsi3" 818 [(set (match_operand:SI 0 "arith_reg_operand" "") 819 (minus:SI (match_operand:SI 1 "arith_operand" "") 820 (match_operand:SI 2 "arith_reg_operand" "")))] 821 "" 822 " 823{ 824 if (GET_CODE (operands[1]) == CONST_INT) 825 { 826 emit_insn (gen_negsi2 (operands[0], operands[2])); 827 emit_insn (gen_addsi3 (operands[0], operands[0], operands[1])); 828 DONE; 829 } 830}") 831 832;; ------------------------------------------------------------------------- 833;; Division instructions 834;; ------------------------------------------------------------------------- 835 836;; We take advantage of the library routines which don't clobber as many 837;; registers as a normal function call would. 838 839;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it 840;; also has an effect on the register that holds the address of the sfunc. 841;; To make this work, we have an extra dummy insns that shows the use 842;; of this register for reorg. 843 844(define_insn "use_sfunc_addr" 845 [(set (reg:SI 17) (unspec [(match_operand:SI 0 "register_operand" "r")] 5))] 846 "" 847 "" 848 [(set_attr "length" "0")]) 849 850;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than 851;; hard register 0. If we used hard register 0, then the next instruction 852;; would be a move from hard register 0 to a pseudo-reg. If the pseudo-reg 853;; gets allocated to a stack slot that needs its address reloaded, then 854;; there is nothing to prevent reload from using r0 to reload the address. 855;; This reload would clobber the value in r0 we are trying to store. 856;; If we let reload allocate r0, then this problem can never happen. 857 858(define_insn "" 859 [(set (match_operand:SI 0 "register_operand" "=z") 860 (udiv:SI (reg:SI 4) (reg:SI 5))) 861 (clobber (reg:SI 18)) 862 (clobber (reg:SI 17)) 863 (clobber (reg:SI 4)) 864 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 865 "! TARGET_SH4" 866 "jsr @%1%#" 867 [(set_attr "type" "sfunc") 868 (set_attr "needs_delay_slot" "yes")]) 869 870(define_insn "udivsi3_i4" 871 [(set (match_operand:SI 0 "register_operand" "=y") 872 (udiv:SI (reg:SI 4) (reg:SI 5))) 873 (clobber (reg:SI 17)) 874 (clobber (reg:DF 24)) 875 (clobber (reg:DF 26)) 876 (clobber (reg:DF 28)) 877 (clobber (reg:SI 0)) 878 (clobber (reg:SI 1)) 879 (clobber (reg:SI 4)) 880 (clobber (reg:SI 5)) 881 (use (reg:PSI 48)) 882 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 883 "TARGET_SH4 && ! TARGET_FPU_SINGLE" 884 "jsr @%1%#" 885 [(set_attr "type" "sfunc") 886 (set_attr "needs_delay_slot" "yes")]) 887 888(define_insn "udivsi3_i4_single" 889 [(set (match_operand:SI 0 "register_operand" "=y") 890 (udiv:SI (reg:SI 4) (reg:SI 5))) 891 (clobber (reg:SI 17)) 892 (clobber (reg:DF 24)) 893 (clobber (reg:DF 26)) 894 (clobber (reg:DF 28)) 895 (clobber (reg:SI 0)) 896 (clobber (reg:SI 1)) 897 (clobber (reg:SI 4)) 898 (clobber (reg:SI 5)) 899 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 900 "TARGET_HARD_SH4 && TARGET_FPU_SINGLE" 901 "jsr @%1%#" 902 [(set_attr "type" "sfunc") 903 (set_attr "needs_delay_slot" "yes")]) 904 905(define_expand "udivsi3" 906 [(set (reg:SI 4) (match_operand:SI 1 "general_operand" "")) 907 (set (reg:SI 5) (match_operand:SI 2 "general_operand" "")) 908 (set (match_dup 3) (symbol_ref:SI "__udivsi3")) 909 (parallel [(set (match_operand:SI 0 "register_operand" "") 910 (udiv:SI (reg:SI 4) 911 (reg:SI 5))) 912 (clobber (reg:SI 18)) 913 (clobber (reg:SI 17)) 914 (clobber (reg:SI 4)) 915 (use (match_dup 3))])] 916 "" 917 " 918{ 919 operands[3] = gen_reg_rtx(SImode); 920 if (TARGET_HARD_SH4) 921 { 922 emit_move_insn (gen_rtx (REG, SImode, 4), operands[1]); 923 emit_move_insn (gen_rtx (REG, SImode, 5), operands[2]); 924 emit_move_insn (operands[3], 925 gen_rtx_SYMBOL_REF (SImode, \"__udivsi3_i4\")); 926 if (TARGET_FPU_SINGLE) 927 emit_insn (gen_udivsi3_i4_single (operands[0], operands[3])); 928 else 929 emit_insn (gen_udivsi3_i4 (operands[0], operands[3])); 930 DONE; 931 } 932}") 933 934(define_insn "" 935 [(set (match_operand:SI 0 "register_operand" "=z") 936 (div:SI (reg:SI 4) (reg:SI 5))) 937 (clobber (reg:SI 18)) 938 (clobber (reg:SI 17)) 939 (clobber (reg:SI 1)) 940 (clobber (reg:SI 2)) 941 (clobber (reg:SI 3)) 942 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 943 "! TARGET_SH4" 944 "jsr @%1%#" 945 [(set_attr "type" "sfunc") 946 (set_attr "needs_delay_slot" "yes")]) 947 948(define_insn "divsi3_i4" 949 [(set (match_operand:SI 0 "register_operand" "=y") 950 (div:SI (reg:SI 4) (reg:SI 5))) 951 (clobber (reg:SI 17)) 952 (clobber (reg:DF 24)) 953 (clobber (reg:DF 26)) 954 (use (reg:PSI 48)) 955 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 956 "TARGET_SH4 && ! TARGET_FPU_SINGLE" 957 "jsr @%1%#" 958 [(set_attr "type" "sfunc") 959 (set_attr "needs_delay_slot" "yes")]) 960 961(define_insn "divsi3_i4_single" 962 [(set (match_operand:SI 0 "register_operand" "=y") 963 (div:SI (reg:SI 4) (reg:SI 5))) 964 (clobber (reg:SI 17)) 965 (clobber (reg:DF 24)) 966 (clobber (reg:DF 26)) 967 (clobber (reg:SI 2)) 968 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 969 "TARGET_HARD_SH4 && TARGET_FPU_SINGLE" 970 "jsr @%1%#" 971 [(set_attr "type" "sfunc") 972 (set_attr "needs_delay_slot" "yes")]) 973 974(define_expand "divsi3" 975 [(set (reg:SI 4) (match_operand:SI 1 "general_operand" "")) 976 (set (reg:SI 5) (match_operand:SI 2 "general_operand" "")) 977 (set (match_dup 3) (symbol_ref:SI "__sdivsi3")) 978 (parallel [(set (match_operand:SI 0 "register_operand" "") 979 (div:SI (reg:SI 4) 980 (reg:SI 5))) 981 (clobber (reg:SI 18)) 982 (clobber (reg:SI 17)) 983 (clobber (reg:SI 1)) 984 (clobber (reg:SI 2)) 985 (clobber (reg:SI 3)) 986 (use (match_dup 3))])] 987 "" 988 " 989{ 990 operands[3] = gen_reg_rtx(SImode); 991 if (TARGET_HARD_SH4) 992 { 993 emit_move_insn (gen_rtx (REG, SImode, 4), operands[1]); 994 emit_move_insn (gen_rtx (REG, SImode, 5), operands[2]); 995 emit_move_insn (operands[3], 996 gen_rtx_SYMBOL_REF (SImode, \"__sdivsi3_i4\")); 997 if (TARGET_FPU_SINGLE) 998 emit_insn (gen_divsi3_i4_single (operands[0], operands[3])); 999 else 1000 emit_insn (gen_divsi3_i4 (operands[0], operands[3])); 1001 DONE; 1002 } 1003}") 1004 1005;; ------------------------------------------------------------------------- 1006;; Multiplication instructions 1007;; ------------------------------------------------------------------------- 1008 1009(define_insn "" 1010 [(set (reg:SI 21) 1011 (mult:SI (zero_extend:SI (match_operand:HI 0 "arith_reg_operand" "r")) 1012 (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r"))))] 1013 "" 1014 "mulu %1,%0" 1015 [(set_attr "type" "smpy")]) 1016 1017(define_insn "" 1018 [(set (reg:SI 21) 1019 (mult:SI (sign_extend:SI 1020 (match_operand:HI 0 "arith_reg_operand" "r")) 1021 (sign_extend:SI 1022 (match_operand:HI 1 "arith_reg_operand" "r"))))] 1023 "" 1024 "muls %1,%0" 1025 [(set_attr "type" "smpy")]) 1026 1027(define_expand "mulhisi3" 1028 [(set (reg:SI 21) 1029 (mult:SI (sign_extend:SI 1030 (match_operand:HI 1 "arith_reg_operand" "")) 1031 (sign_extend:SI 1032 (match_operand:HI 2 "arith_reg_operand" "")))) 1033 (set (match_operand:SI 0 "arith_reg_operand" "") 1034 (reg:SI 21))] 1035 "" 1036 "") 1037 1038(define_expand "umulhisi3" 1039 [(set (reg:SI 21) 1040 (mult:SI (zero_extend:SI 1041 (match_operand:HI 1 "arith_reg_operand" "")) 1042 (zero_extend:SI 1043 (match_operand:HI 2 "arith_reg_operand" "")))) 1044 (set (match_operand:SI 0 "arith_reg_operand" "") 1045 (reg:SI 21))] 1046 "" 1047 "") 1048 1049;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate 1050;; a call to a routine which clobbers known registers. 1051 1052(define_insn "" 1053 [(set (match_operand:SI 1 "register_operand" "=z") 1054 (mult:SI (reg:SI 4) (reg:SI 5))) 1055 (clobber (reg:SI 21)) 1056 (clobber (reg:SI 18)) 1057 (clobber (reg:SI 17)) 1058 (clobber (reg:SI 3)) 1059 (clobber (reg:SI 2)) 1060 (clobber (reg:SI 1)) 1061 (use (match_operand:SI 0 "arith_reg_operand" "r"))] 1062 "" 1063 "jsr @%0%#" 1064 [(set_attr "type" "sfunc") 1065 (set_attr "needs_delay_slot" "yes")]) 1066 1067(define_expand "mulsi3_call" 1068 [(set (reg:SI 4) (match_operand:SI 1 "general_operand" "")) 1069 (set (reg:SI 5) (match_operand:SI 2 "general_operand" "")) 1070 (parallel[(set (match_operand:SI 0 "register_operand" "") 1071 (mult:SI (reg:SI 4) 1072 (reg:SI 5))) 1073 (clobber (reg:SI 21)) 1074 (clobber (reg:SI 18)) 1075 (clobber (reg:SI 17)) 1076 (clobber (reg:SI 3)) 1077 (clobber (reg:SI 2)) 1078 (clobber (reg:SI 1)) 1079 (use (match_operand:SI 3 "register_operand" ""))])] 1080 "" 1081 "") 1082 1083(define_insn "mul_l" 1084 [(set (reg:SI 21) 1085 (mult:SI (match_operand:SI 0 "arith_reg_operand" "r") 1086 (match_operand:SI 1 "arith_reg_operand" "r")))] 1087 "TARGET_SH2" 1088 "mul.l %1,%0" 1089 [(set_attr "type" "dmpy")]) 1090 1091(define_expand "mulsi3" 1092 [(set (reg:SI 21) 1093 (mult:SI (match_operand:SI 1 "arith_reg_operand" "") 1094 (match_operand:SI 2 "arith_reg_operand" ""))) 1095 (set (match_operand:SI 0 "arith_reg_operand" "") 1096 (reg:SI 21))] 1097 "" 1098 " 1099{ 1100 rtx first, last; 1101 1102 if (!TARGET_SH2) 1103 { 1104 /* The address must be set outside the libcall, 1105 since it goes into a pseudo. */ 1106 rtx addr = force_reg (SImode, gen_rtx_SYMBOL_REF (SImode, \"__mulsi3\")); 1107 rtx insns = gen_mulsi3_call (operands[0], operands[1], operands[2], addr); 1108 first = XVECEXP (insns, 0, 0); 1109 last = XVECEXP (insns, 0, XVECLEN (insns, 0) - 1); 1110 emit_insn (insns); 1111 } 1112 else 1113 { 1114 rtx macl = gen_rtx_REG (SImode, MACL_REG); 1115 rtx giv_insn; 1116 1117 first = emit_insn (gen_mul_l (operands[1], operands[2])); 1118 /* consec_sets_giv can only recognize the first insn that sets a 1119 giv as the giv insn. So we must tag this also with a REG_EQUAL 1120 note. */ 1121 giv_insn = emit_insn (gen_movsi_i ((operands[0]), macl)); 1122 REG_NOTES (giv_insn) 1123 = gen_rtx_EXPR_LIST (REG_EQUAL, 1124 gen_rtx_MULT (SImode, operands[1], operands[2]), 1125 REG_NOTES (giv_insn)); 1126 /* The sequence must end in a no-op move, lest cse puts macl in its 1127 tables and does invalid substitutions. */ 1128 last = emit_insn (gen_movsi_i ((operands[0]), operands[0])); 1129 } 1130 /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop 1131 invariant code motion can move it. */ 1132 REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first)); 1133 REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last)); 1134 DONE; 1135}") 1136 1137(define_insn "mulsidi3_i" 1138 [(set (reg:DI 20) 1139 (mult:DI (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) 1140 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))))] 1141 "TARGET_SH2" 1142 "dmuls.l %1,%0" 1143 [(set_attr "type" "dmpy")]) 1144 1145(define_expand "mulsidi3" 1146 [(set (reg:DI 20) 1147 (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) 1148 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))) 1149 (set (match_operand:DI 0 "arith_reg_operand" "") 1150 (reg:DI 20))] 1151 "TARGET_SH2" 1152 " 1153{ 1154 /* We must swap the two words when copying them from MACH/MACL to the 1155 output register. */ 1156 if (TARGET_LITTLE_ENDIAN) 1157 { 1158 rtx low_dst = operand_subword (operands[0], 0, 1, DImode); 1159 rtx high_dst = operand_subword (operands[0], 1, 1, DImode); 1160 1161 emit_insn (gen_mulsidi3_i (operands[1], operands[2])); 1162 1163 emit_insn (gen_rtx (CLOBBER, VOIDmode, operands[0])); 1164 emit_move_insn (low_dst, gen_rtx (REG, SImode, 21)); 1165 emit_move_insn (high_dst, gen_rtx (REG, SImode, 20)); 1166 DONE; 1167 } 1168}") 1169 1170(define_insn "umulsidi3_i" 1171 [(set (reg:DI 20) 1172 (mult:DI (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) 1173 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))))] 1174 "TARGET_SH2" 1175 "dmulu.l %1,%0" 1176 [(set_attr "type" "dmpy")]) 1177 1178(define_expand "umulsidi3" 1179 [(set (reg:DI 20) 1180 (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) 1181 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))) 1182 (set (match_operand:DI 0 "arith_reg_operand" "") 1183 (reg:DI 20))] 1184 "TARGET_SH2" 1185 " 1186{ 1187 /* We must swap the two words when copying them from MACH/MACL to the 1188 output register. */ 1189 if (TARGET_LITTLE_ENDIAN) 1190 { 1191 rtx low_dst = operand_subword (operands[0], 0, 1, DImode); 1192 rtx high_dst = operand_subword (operands[0], 1, 1, DImode); 1193 1194 emit_insn (gen_umulsidi3_i (operands[1], operands[2])); 1195 1196 emit_insn (gen_rtx (CLOBBER, VOIDmode, operands[0])); 1197 emit_move_insn (low_dst, gen_rtx (REG, SImode, 21)); 1198 emit_move_insn (high_dst, gen_rtx (REG, SImode, 20)); 1199 DONE; 1200 } 1201}") 1202 1203(define_insn "" 1204 [(set (reg:SI 20) 1205 (truncate:SI 1206 (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) 1207 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))) 1208 (const_int 32)))) 1209 (clobber (reg:SI 21))] 1210 "TARGET_SH2" 1211 "dmuls.l %1,%0" 1212 [(set_attr "type" "dmpy")]) 1213 1214(define_expand "smulsi3_highpart" 1215 [(parallel [(set (reg:SI 20) 1216 (truncate:SI 1217 (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) 1218 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))) 1219 (const_int 32)))) 1220 (clobber (reg:SI 21))]) 1221 (set (match_operand:SI 0 "arith_reg_operand" "") 1222 (reg:SI 20))] 1223 "TARGET_SH2" 1224 "") 1225 1226(define_insn "" 1227 [(set (reg:SI 20) 1228 (truncate:SI 1229 (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) 1230 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))) 1231 (const_int 32)))) 1232 (clobber (reg:SI 21))] 1233 "TARGET_SH2" 1234 "dmulu.l %1,%0" 1235 [(set_attr "type" "dmpy")]) 1236 1237(define_expand "umulsi3_highpart" 1238 [(parallel [(set (reg:SI 20) 1239 (truncate:SI 1240 (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) 1241 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))) 1242 (const_int 32)))) 1243 (clobber (reg:SI 21))]) 1244 (set (match_operand:SI 0 "arith_reg_operand" "") 1245 (reg:SI 20))] 1246 "TARGET_SH2" 1247 "") 1248 1249;; ------------------------------------------------------------------------- 1250;; Logical operations 1251;; ------------------------------------------------------------------------- 1252 1253(define_insn "" 1254 [(set (match_operand:SI 0 "arith_reg_operand" "=r,z") 1255 (and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") 1256 (match_operand:SI 2 "logical_operand" "r,L")))] 1257 "" 1258 "and %2,%0" 1259 [(set_attr "type" "arith")]) 1260 1261;; If the constant is 255, then emit a extu.b instruction instead of an 1262;; and, since that will give better code. 1263 1264(define_expand "andsi3" 1265 [(set (match_operand:SI 0 "arith_reg_operand" "") 1266 (and:SI (match_operand:SI 1 "arith_reg_operand" "") 1267 (match_operand:SI 2 "logical_operand" "")))] 1268 "" 1269 " 1270{ 1271 if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 255) 1272 { 1273 emit_insn (gen_zero_extendqisi2 (operands[0], 1274 gen_lowpart (QImode, operands[1]))); 1275 DONE; 1276 } 1277}") 1278 1279(define_insn "iorsi3" 1280 [(set (match_operand:SI 0 "arith_reg_operand" "=r,z") 1281 (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") 1282 (match_operand:SI 2 "logical_operand" "r,L")))] 1283 "" 1284 "or %2,%0" 1285 [(set_attr "type" "arith")]) 1286 1287(define_insn "xorsi3" 1288 [(set (match_operand:SI 0 "arith_reg_operand" "=z,r") 1289 (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") 1290 (match_operand:SI 2 "logical_operand" "L,r")))] 1291 "" 1292 "xor %2,%0" 1293 [(set_attr "type" "arith")]) 1294 1295;; ------------------------------------------------------------------------- 1296;; Shifts and rotates 1297;; ------------------------------------------------------------------------- 1298 1299(define_insn "rotlsi3_1" 1300 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 1301 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0") 1302 (const_int 1))) 1303 (set (reg:SI 18) 1304 (lshiftrt:SI (match_dup 1) (const_int 31)))] 1305 "" 1306 "rotl %0" 1307 [(set_attr "type" "arith")]) 1308 1309(define_insn "rotlsi3_31" 1310 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 1311 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0") 1312 (const_int 31))) 1313 (clobber (reg:SI 18))] 1314 "" 1315 "rotr %0" 1316 [(set_attr "type" "arith")]) 1317 1318(define_insn "rotlsi3_16" 1319 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 1320 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r") 1321 (const_int 16)))] 1322 "" 1323 "swap.w %1,%0" 1324 [(set_attr "type" "arith")]) 1325 1326(define_expand "rotlsi3" 1327 [(set (match_operand:SI 0 "arith_reg_operand" "") 1328 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "") 1329 (match_operand:SI 2 "immediate_operand" "")))] 1330 "" 1331 " 1332{ 1333 static char rot_tab[] = { 1334 000, 000, 000, 000, 000, 000, 010, 001, 1335 001, 001, 011, 013, 003, 003, 003, 003, 1336 003, 003, 003, 003, 003, 013, 012, 002, 1337 002, 002, 010, 000, 000, 000, 000, 000, 1338 }; 1339 1340 int count, choice; 1341 1342 if (GET_CODE (operands[2]) != CONST_INT) 1343 FAIL; 1344 count = INTVAL (operands[2]); 1345 choice = rot_tab[count]; 1346 if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1) 1347 FAIL; 1348 choice &= 7; 1349 switch (choice) 1350 { 1351 case 0: 1352 emit_move_insn (operands[0], operands[1]); 1353 count -= (count & 16) * 2; 1354 break; 1355 case 3: 1356 emit_insn (gen_rotlsi3_16 (operands[0], operands[1])); 1357 count -= 16; 1358 break; 1359 case 1: 1360 case 2: 1361 { 1362 rtx parts[2]; 1363 parts[0] = gen_reg_rtx (SImode); 1364 parts[1] = gen_reg_rtx (SImode); 1365 emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1])); 1366 parts[choice-1] = operands[1]; 1367 emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8))); 1368 emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8))); 1369 emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1])); 1370 count = (count & ~16) - 8; 1371 } 1372 } 1373 1374 for (; count > 0; count--) 1375 emit_insn (gen_rotlsi3_1 (operands[0], operands[0])); 1376 for (; count < 0; count++) 1377 emit_insn (gen_rotlsi3_31 (operands[0], operands[0])); 1378 1379 DONE; 1380}") 1381 1382(define_insn "*rotlhi3_8" 1383 [(set (match_operand:HI 0 "arith_reg_operand" "=r") 1384 (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r") 1385 (const_int 8)))] 1386 "" 1387 "swap.b %1,%0" 1388 [(set_attr "type" "arith")]) 1389 1390(define_expand "rotlhi3" 1391 [(set (match_operand:HI 0 "arith_reg_operand" "") 1392 (rotate:HI (match_operand:HI 1 "arith_reg_operand" "") 1393 (match_operand:HI 2 "immediate_operand" "")))] 1394 "" 1395 " 1396{ 1397 if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 8) 1398 FAIL; 1399}") 1400 1401;; 1402;; shift left 1403 1404(define_insn "ashlsi3_d" 1405 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 1406 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") 1407 (match_operand:SI 2 "arith_reg_operand" "r")))] 1408 "TARGET_SH3" 1409 "shld %2,%0" 1410 [(set_attr "type" "dyn_shift")]) 1411 1412(define_insn "ashlsi3_k" 1413 [(set (match_operand:SI 0 "arith_reg_operand" "=r,r") 1414 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0") 1415 (match_operand:SI 2 "const_int_operand" "M,K")))] 1416 "CONST_OK_FOR_K (INTVAL (operands[2]))" 1417 "@ 1418 add %0,%0 1419 shll%O2 %0" 1420 [(set_attr "type" "arith")]) 1421 1422(define_insn "ashlhi3_k" 1423 [(set (match_operand:HI 0 "arith_reg_operand" "=r,r") 1424 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0") 1425 (match_operand:HI 2 "const_int_operand" "M,K")))] 1426 "CONST_OK_FOR_K (INTVAL (operands[2]))" 1427 "@ 1428 add %0,%0 1429 shll%O2 %0" 1430 [(set_attr "type" "arith")]) 1431 1432(define_insn "ashlsi3_n" 1433 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 1434 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") 1435 (match_operand:SI 2 "const_int_operand" "n"))) 1436 (clobber (reg:SI 18))] 1437 "! sh_dynamicalize_shift_p (operands[2])" 1438 "#" 1439 [(set (attr "length") 1440 (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1)) 1441 (const_string "2") 1442 (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2)) 1443 (const_string "4") 1444 (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3)) 1445 (const_string "6")] 1446 (const_string "8"))) 1447 (set_attr "type" "arith")]) 1448 1449(define_split 1450 [(set (match_operand:SI 0 "arith_reg_operand" "") 1451 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "") 1452 (match_operand:SI 2 "const_int_operand" "n"))) 1453 (clobber (reg:SI 18))] 1454 "" 1455 [(use (reg:SI 0))] 1456 " 1457{ 1458 gen_shifty_op (ASHIFT, operands); 1459 DONE; 1460}") 1461 1462(define_expand "ashlsi3" 1463 [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "") 1464 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "") 1465 (match_operand:SI 2 "nonmemory_operand" ""))) 1466 (clobber (reg:SI 18))])] 1467 "" 1468 " 1469{ 1470 if (GET_CODE (operands[2]) == CONST_INT 1471 && sh_dynamicalize_shift_p (operands[2])) 1472 operands[2] = force_reg (SImode, operands[2]); 1473 if (TARGET_SH3 && arith_reg_operand (operands[2], GET_MODE (operands[2]))) 1474 { 1475 emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2])); 1476 DONE; 1477 } 1478 if (! immediate_operand (operands[2], GET_MODE (operands[2]))) 1479 FAIL; 1480}") 1481 1482(define_insn "ashlhi3" 1483 [(set (match_operand:HI 0 "arith_reg_operand" "=r") 1484 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0") 1485 (match_operand:HI 2 "const_int_operand" "n"))) 1486 (clobber (reg:SI 18))] 1487 "" 1488 "#" 1489 [(set (attr "length") 1490 (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1)) 1491 (const_string "2") 1492 (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2)) 1493 (const_string "4")] 1494 (const_string "6"))) 1495 (set_attr "type" "arith")]) 1496 1497(define_split 1498 [(set (match_operand:HI 0 "arith_reg_operand" "") 1499 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "") 1500 (match_operand:HI 2 "const_int_operand" "n"))) 1501 (clobber (reg:SI 18))] 1502 "" 1503 [(use (reg:SI 0))] 1504 " 1505{ 1506 gen_shifty_hi_op (ASHIFT, operands); 1507 DONE; 1508}") 1509 1510; 1511; arithmetic shift right 1512; 1513 1514(define_insn "ashrsi3_k" 1515 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 1516 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 1517 (match_operand:SI 2 "const_int_operand" "M"))) 1518 (clobber (reg:SI 18))] 1519 "INTVAL (operands[2]) == 1" 1520 "shar %0" 1521 [(set_attr "type" "arith")]) 1522 1523;; We can't do HImode right shifts correctly unless we start out with an 1524;; explicit zero / sign extension; doing that would result in worse overall 1525;; code, so just let the machine independent code widen the mode. 1526;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 . 1527 1528 1529;; ??? This should be a define expand. 1530 1531(define_insn "ashrsi2_16" 1532 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 1533 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r") 1534 (const_int 16)))] 1535 "" 1536 "#" 1537 [(set_attr "length" "4")]) 1538 1539(define_split 1540 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 1541 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r") 1542 (const_int 16)))] 1543 "" 1544 [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16))) 1545 (set (match_dup 0) (sign_extend:SI (match_dup 2)))] 1546 "operands[2] = gen_lowpart (HImode, operands[0]);") 1547 1548;; ??? This should be a define expand. 1549 1550(define_insn "ashrsi2_31" 1551 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 1552 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 1553 (const_int 31))) 1554 (clobber (reg:SI 18))] 1555 "" 1556 "#" 1557 [(set_attr "length" "4")]) 1558 1559(define_split 1560 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 1561 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 1562 (const_int 31))) 1563 (clobber (reg:SI 18))] 1564 "" 1565 [(const_int 0)] 1566 " 1567{ 1568 emit_insn (gen_ashlsi_c (operands[0], operands[1])); 1569 emit_insn (gen_subc1 (operands[0], operands[0], operands[0])); 1570 DONE; 1571}") 1572 1573(define_insn "ashlsi_c" 1574 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 1575 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1))) 1576 (set (reg:SI 18) (lt:SI (match_dup 1) 1577 (const_int 0)))] 1578 "" 1579 "shll %0" 1580 [(set_attr "type" "arith")]) 1581 1582(define_insn "ashrsi3_d" 1583 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 1584 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 1585 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))] 1586 "TARGET_SH3" 1587 "shad %2,%0" 1588 [(set_attr "type" "dyn_shift")]) 1589 1590(define_insn "ashrsi3_n" 1591 [(set (reg:SI 4) 1592 (ashiftrt:SI (reg:SI 4) 1593 (match_operand:SI 0 "const_int_operand" "i"))) 1594 (clobber (reg:SI 18)) 1595 (clobber (reg:SI 17)) 1596 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 1597 "" 1598 "jsr @%1%#" 1599 [(set_attr "type" "sfunc") 1600 (set_attr "needs_delay_slot" "yes")]) 1601 1602(define_expand "ashrsi3" 1603 [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "") 1604 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "") 1605 (match_operand:SI 2 "nonmemory_operand" ""))) 1606 (clobber (reg:SI 18))])] 1607 "" 1608 "if (expand_ashiftrt (operands)) DONE; else FAIL;") 1609 1610;; logical shift right 1611 1612(define_insn "lshrsi3_d" 1613 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 1614 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 1615 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))] 1616 "TARGET_SH3" 1617 "shld %2,%0" 1618 [(set_attr "type" "dyn_shift")]) 1619 1620;; Only the single bit shift clobbers the T bit. 1621 1622(define_insn "lshrsi3_m" 1623 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 1624 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 1625 (match_operand:SI 2 "const_int_operand" "M"))) 1626 (clobber (reg:SI 18))] 1627 "CONST_OK_FOR_M (INTVAL (operands[2]))" 1628 "shlr %0" 1629 [(set_attr "type" "arith")]) 1630 1631(define_insn "lshrsi3_k" 1632 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 1633 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 1634 (match_operand:SI 2 "const_int_operand" "K")))] 1635 "CONST_OK_FOR_K (INTVAL (operands[2])) 1636 && ! CONST_OK_FOR_M (INTVAL (operands[2]))" 1637 "shlr%O2 %0" 1638 [(set_attr "type" "arith")]) 1639 1640(define_insn "lshrsi3_n" 1641 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 1642 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 1643 (match_operand:SI 2 "const_int_operand" "n"))) 1644 (clobber (reg:SI 18))] 1645 "! sh_dynamicalize_shift_p (operands[2])" 1646 "#" 1647 [(set (attr "length") 1648 (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1)) 1649 (const_string "2") 1650 (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2)) 1651 (const_string "4") 1652 (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3)) 1653 (const_string "6")] 1654 (const_string "8"))) 1655 (set_attr "type" "arith")]) 1656 1657(define_split 1658 [(set (match_operand:SI 0 "arith_reg_operand" "") 1659 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "") 1660 (match_operand:SI 2 "const_int_operand" "n"))) 1661 (clobber (reg:SI 18))] 1662 "" 1663 [(use (reg:SI 0))] 1664 " 1665{ 1666 gen_shifty_op (LSHIFTRT, operands); 1667 DONE; 1668}") 1669 1670(define_expand "lshrsi3" 1671 [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "") 1672 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "") 1673 (match_operand:SI 2 "nonmemory_operand" ""))) 1674 (clobber (reg:SI 18))])] 1675 "" 1676 " 1677{ 1678 if (GET_CODE (operands[2]) == CONST_INT 1679 && sh_dynamicalize_shift_p (operands[2])) 1680 operands[2] = force_reg (SImode, operands[2]); 1681 if (TARGET_SH3 && arith_reg_operand (operands[2], GET_MODE (operands[2]))) 1682 { 1683 rtx count = copy_to_mode_reg (SImode, operands[2]); 1684 emit_insn (gen_negsi2 (count, count)); 1685 emit_insn (gen_lshrsi3_d (operands[0], operands[1], count)); 1686 DONE; 1687 } 1688 if (! immediate_operand (operands[2], GET_MODE (operands[2]))) 1689 FAIL; 1690}") 1691 1692;; ??? This should be a define expand. 1693 1694(define_insn "ashldi3_k" 1695 [(set (match_operand:DI 0 "arith_reg_operand" "=r") 1696 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0") 1697 (const_int 1))) 1698 (clobber (reg:SI 18))] 1699 "" 1700 "shll %R0\;rotcl %S0" 1701 [(set_attr "length" "4") 1702 (set_attr "type" "arith")]) 1703 1704(define_expand "ashldi3" 1705 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "") 1706 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "") 1707 (match_operand:DI 2 "immediate_operand" ""))) 1708 (clobber (reg:SI 18))])] 1709 "" 1710 "{ if (GET_CODE (operands[2]) != CONST_INT 1711 || INTVAL (operands[2]) != 1) FAIL;} ") 1712 1713;; ??? This should be a define expand. 1714 1715(define_insn "lshrdi3_k" 1716 [(set (match_operand:DI 0 "arith_reg_operand" "=r") 1717 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0") 1718 (const_int 1))) 1719 (clobber (reg:SI 18))] 1720 "" 1721 "shlr %S0\;rotcr %R0" 1722 [(set_attr "length" "4") 1723 (set_attr "type" "arith")]) 1724 1725(define_expand "lshrdi3" 1726 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "") 1727 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "") 1728 (match_operand:DI 2 "immediate_operand" ""))) 1729 (clobber (reg:SI 18))])] 1730 "" 1731 "{ if (GET_CODE (operands[2]) != CONST_INT 1732 || INTVAL (operands[2]) != 1) FAIL;} ") 1733 1734;; ??? This should be a define expand. 1735 1736(define_insn "ashrdi3_k" 1737 [(set (match_operand:DI 0 "arith_reg_operand" "=r") 1738 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0") 1739 (const_int 1))) 1740 (clobber (reg:SI 18))] 1741 "" 1742 "shar %S0\;rotcr %R0" 1743 [(set_attr "length" "4") 1744 (set_attr "type" "arith")]) 1745 1746(define_expand "ashrdi3" 1747 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "") 1748 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "") 1749 (match_operand:DI 2 "immediate_operand" ""))) 1750 (clobber (reg:SI 18))])] 1751 "" 1752 "{ if (GET_CODE (operands[2]) != CONST_INT 1753 || INTVAL (operands[2]) != 1) FAIL; } ") 1754 1755;; combined left/right shift 1756 1757(define_split 1758 [(set (match_operand:SI 0 "register_operand" "") 1759 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "") 1760 (match_operand:SI 2 "const_int_operand" "n")) 1761 (match_operand:SI 3 "const_int_operand" "n")))] 1762 "(unsigned)INTVAL (operands[2]) < 32" 1763 [(use (reg:SI 0))] 1764 "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL; 1765 DONE;") 1766 1767(define_split 1768 [(set (match_operand:SI 0 "register_operand" "") 1769 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "") 1770 (match_operand:SI 2 "const_int_operand" "n")) 1771 (match_operand:SI 3 "const_int_operand" "n"))) 1772 (clobber (reg:SI 18))] 1773 "(unsigned)INTVAL (operands[2]) < 32" 1774 [(use (reg:SI 0))] 1775 "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL; 1776 DONE;") 1777 1778(define_insn "" 1779 [(set (match_operand:SI 0 "register_operand" "=r") 1780 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0") 1781 (match_operand:SI 2 "const_int_operand" "n")) 1782 (match_operand:SI 3 "const_int_operand" "n"))) 1783 (clobber (reg:SI 18))] 1784 "shl_and_kind (operands[2], operands[3], 0) == 1" 1785 "#" 1786 [(set (attr "length") 1787 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2)) 1788 (const_string "4") 1789 (eq (symbol_ref "shl_and_length (insn)") (const_int 3)) 1790 (const_string "6") 1791 (eq (symbol_ref "shl_and_length (insn)") (const_int 4)) 1792 (const_string "8") 1793 (eq (symbol_ref "shl_and_length (insn)") (const_int 5)) 1794 (const_string "10") 1795 (eq (symbol_ref "shl_and_length (insn)") (const_int 6)) 1796 (const_string "12") 1797 (eq (symbol_ref "shl_and_length (insn)") (const_int 7)) 1798 (const_string "14") 1799 (eq (symbol_ref "shl_and_length (insn)") (const_int 8)) 1800 (const_string "16")] 1801 (const_string "18"))) 1802 (set_attr "type" "arith")]) 1803 1804(define_insn "" 1805 [(set (match_operand:SI 0 "register_operand" "=z") 1806 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0") 1807 (match_operand:SI 2 "const_int_operand" "n")) 1808 (match_operand:SI 3 "const_int_operand" "n"))) 1809 (clobber (reg:SI 18))] 1810 "shl_and_kind (operands[2], operands[3], 0) == 2" 1811 "#" 1812 [(set (attr "length") 1813 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2)) 1814 (const_string "4") 1815 (eq (symbol_ref "shl_and_length (insn)") (const_int 3)) 1816 (const_string "6") 1817 (eq (symbol_ref "shl_and_length (insn)") (const_int 4)) 1818 (const_string "8")] 1819 (const_string "10"))) 1820 (set_attr "type" "arith")]) 1821 1822;; shift left / and combination with a scratch register: The combine pass 1823;; does not accept the individual instructions, even though they are 1824;; cheap. But it needs a precise description so that it is usable after 1825;; reload. 1826(define_insn "and_shl_scratch" 1827 [(set (match_operand:SI 0 "register_operand" "=r,&r") 1828 (lshiftrt:SI (ashift:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0") 1829 (match_operand:SI 2 "const_int_operand" "N,n")) 1830 (match_operand:SI 3 "" "0,r")) 1831 (match_operand:SI 4 "const_int_operand" "n,n")) 1832 (match_operand:SI 5 "const_int_operand" "n,n"))) 1833 (clobber (reg:SI 18))] 1834 "" 1835 "#" 1836 [(set (attr "length") 1837 (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2)) 1838 (const_string "4") 1839 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3)) 1840 (const_string "6") 1841 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4)) 1842 (const_string "8") 1843 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5)) 1844 (const_string "10")] 1845 (const_string "12"))) 1846 (set_attr "type" "arith")]) 1847 1848(define_split 1849 [(set (match_operand:SI 0 "register_operand" "=r,&r") 1850 (lshiftrt:SI (ashift:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0") 1851 (match_operand:SI 2 "const_int_operand" "N,n")) 1852 (match_operand:SI 3 "register_operand" "0,r")) 1853 (match_operand:SI 4 "const_int_operand" "n,n")) 1854 (match_operand:SI 5 "const_int_operand" "n,n"))) 1855 (clobber (reg:SI 18))] 1856 "" 1857 [(use (reg:SI 0))] 1858 " 1859{ 1860 rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1]; 1861 1862 if (INTVAL (operands[2])) 1863 { 1864 gen_shifty_op (LSHIFTRT, operands); 1865 } 1866 emit_insn (gen_andsi3 (operands[0], operands[0], and_source)); 1867 operands[2] = operands[4]; 1868 gen_shifty_op (ASHIFT, operands); 1869 if (INTVAL (operands[5])) 1870 { 1871 operands[2] = operands[5]; 1872 gen_shifty_op (LSHIFTRT, operands); 1873 } 1874 DONE; 1875}") 1876 1877;; signed left/right shift combination. 1878(define_split 1879 [(set (match_operand:SI 0 "register_operand" "=r") 1880 (sign_extract:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") 1881 (match_operand:SI 2 "const_int_operand" "n")) 1882 (match_operand:SI 3 "const_int_operand" "n") 1883 (const_int 0))) 1884 (clobber (reg:SI 18))] 1885 "" 1886 [(use (reg:SI 0))] 1887 "if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1])) FAIL; 1888 DONE;") 1889 1890(define_insn "shl_sext_ext" 1891 [(set (match_operand:SI 0 "register_operand" "=r") 1892 (sign_extract:SI (ashift:SI (match_operand:SI 1 "register_operand" "0") 1893 (match_operand:SI 2 "const_int_operand" "n")) 1894 (match_operand:SI 3 "const_int_operand" "n") 1895 (const_int 0))) 1896 (clobber (reg:SI 18))] 1897 "(unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5" 1898 "#" 1899 [(set (attr "length") 1900 (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 1)) 1901 (const_string "2") 1902 (eq (symbol_ref "shl_sext_length (insn)") (const_int 2)) 1903 (const_string "4") 1904 (eq (symbol_ref "shl_sext_length (insn)") (const_int 3)) 1905 (const_string "6") 1906 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4)) 1907 (const_string "8") 1908 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5)) 1909 (const_string "10") 1910 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6)) 1911 (const_string "12") 1912 (eq (symbol_ref "shl_sext_length (insn)") (const_int 7)) 1913 (const_string "14") 1914 (eq (symbol_ref "shl_sext_length (insn)") (const_int 8)) 1915 (const_string "16")] 1916 (const_string "18"))) 1917 (set_attr "type" "arith")]) 1918 1919(define_insn "shl_sext_sub" 1920 [(set (match_operand:SI 0 "register_operand" "=z") 1921 (sign_extract:SI (ashift:SI (match_operand:SI 1 "register_operand" "0") 1922 (match_operand:SI 2 "const_int_operand" "n")) 1923 (match_operand:SI 3 "const_int_operand" "n") 1924 (const_int 0))) 1925 (clobber (reg:SI 18))] 1926 "(shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6" 1927 "#" 1928 [(set (attr "length") 1929 (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3)) 1930 (const_string "6") 1931 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4)) 1932 (const_string "8") 1933 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5)) 1934 (const_string "10") 1935 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6)) 1936 (const_string "12")] 1937 (const_string "14"))) 1938 (set_attr "type" "arith")]) 1939 1940;; These patterns are found in expansions of DImode shifts by 16, and 1941;; allow the xtrct instruction to be generated from C source. 1942 1943(define_insn "xtrct_left" 1944 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 1945 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r") 1946 (const_int 16)) 1947 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0") 1948 (const_int 16))))] 1949 "" 1950 "xtrct %1,%0" 1951 [(set_attr "type" "arith")]) 1952 1953(define_insn "xtrct_right" 1954 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 1955 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 1956 (const_int 16)) 1957 (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r") 1958 (const_int 16))))] 1959 "" 1960 "xtrct %2,%0" 1961 [(set_attr "type" "arith")]) 1962 1963;; ------------------------------------------------------------------------- 1964;; Unary arithmetic 1965;; ------------------------------------------------------------------------- 1966 1967(define_insn "negc" 1968 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 1969 (neg:SI (plus:SI (reg:SI 18) 1970 (match_operand:SI 1 "arith_reg_operand" "r")))) 1971 (set (reg:SI 18) 1972 (ne:SI (ior:SI (reg:SI 18) (match_dup 1)) 1973 (const_int 0)))] 1974 "" 1975 "negc %1,%0" 1976 [(set_attr "type" "arith")]) 1977 1978(define_expand "negdi2" 1979 [(set (match_operand:DI 0 "arith_reg_operand" "") 1980 (neg:DI (match_operand:DI 1 "arith_reg_operand" ""))) 1981 (clobber (reg:SI 18))] 1982 "" 1983 " 1984{ 1985 int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1); 1986 int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0); 1987 1988 rtx low_src = operand_subword (operands[1], low_word, 0, DImode); 1989 rtx high_src = operand_subword (operands[1], high_word, 0, DImode); 1990 1991 rtx low_dst = operand_subword (operands[0], low_word, 1, DImode); 1992 rtx high_dst = operand_subword (operands[0], high_word, 1, DImode); 1993 1994 emit_insn (gen_clrt ()); 1995 emit_insn (gen_negc (low_dst, low_src)); 1996 emit_insn (gen_negc (high_dst, high_src)); 1997 DONE; 1998}") 1999 2000(define_insn "negsi2" 2001 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 2002 (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))] 2003 "" 2004 "neg %1,%0" 2005 [(set_attr "type" "arith")]) 2006 2007(define_insn "one_cmplsi2" 2008 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 2009 (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))] 2010 "" 2011 "not %1,%0" 2012 [(set_attr "type" "arith")]) 2013 2014;; ------------------------------------------------------------------------- 2015;; Zero extension instructions 2016;; ------------------------------------------------------------------------- 2017 2018(define_insn "zero_extendhisi2" 2019 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 2020 (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r")))] 2021 "" 2022 "extu.w %1,%0" 2023 [(set_attr "type" "arith")]) 2024 2025(define_insn "zero_extendqisi2" 2026 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 2027 (zero_extend:SI (match_operand:QI 1 "arith_reg_operand" "r")))] 2028 "" 2029 "extu.b %1,%0" 2030 [(set_attr "type" "arith")]) 2031 2032(define_insn "zero_extendqihi2" 2033 [(set (match_operand:HI 0 "arith_reg_operand" "=r") 2034 (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))] 2035 "" 2036 "extu.b %1,%0" 2037 [(set_attr "type" "arith")]) 2038 2039;; ------------------------------------------------------------------------- 2040;; Sign extension instructions 2041;; ------------------------------------------------------------------------- 2042 2043;; ??? This should be a define expand. 2044;; ??? Or perhaps it should be dropped? 2045 2046/* There is no point in defining extendsidi2; convert_move generates good 2047 code for that. */ 2048 2049(define_insn "extendhisi2" 2050 [(set (match_operand:SI 0 "arith_reg_operand" "=r,r") 2051 (sign_extend:SI (match_operand:HI 1 "general_movsrc_operand" "r,m")))] 2052 "" 2053 "@ 2054 exts.w %1,%0 2055 mov.w %1,%0" 2056 [(set_attr "type" "arith,load")]) 2057 2058(define_insn "extendqisi2" 2059 [(set (match_operand:SI 0 "arith_reg_operand" "=r,r") 2060 (sign_extend:SI (match_operand:QI 1 "general_movsrc_operand" "r,m")))] 2061 "" 2062 "@ 2063 exts.b %1,%0 2064 mov.b %1,%0" 2065 [(set_attr "type" "arith,load")]) 2066 2067(define_insn "extendqihi2" 2068 [(set (match_operand:HI 0 "arith_reg_operand" "=r,r") 2069 (sign_extend:HI (match_operand:QI 1 "general_movsrc_operand" "r,m")))] 2070 "" 2071 "@ 2072 exts.b %1,%0 2073 mov.b %1,%0" 2074 [(set_attr "type" "arith,load")]) 2075 2076;; ------------------------------------------------------------------------- 2077;; Move instructions 2078;; ------------------------------------------------------------------------- 2079 2080;; define push and pop so it is easy for sh.c 2081 2082(define_expand "push" 2083 [(set (mem:SI (pre_dec:SI (reg:SI 15))) 2084 (match_operand:SI 0 "register_operand" "r,l,x"))] 2085 "" 2086 "") 2087 2088(define_expand "pop" 2089 [(set (match_operand:SI 0 "register_operand" "=r,l,x") 2090 (mem:SI (post_inc:SI (reg:SI 15))))] 2091 "" 2092 "") 2093 2094(define_expand "push_e" 2095 [(parallel [(set (mem:SF (pre_dec:SI (reg:SI 15))) 2096 (match_operand:SF 0 "" "")) 2097 (use (reg:PSI 48)) 2098 (clobber (scratch:SI))])] 2099 "" 2100 "") 2101 2102(define_insn "push_fpul" 2103 [(set (mem:SF (pre_dec:SI (reg:SI 15))) (reg:SF 22))] 2104 "TARGET_SH3E" 2105 "sts.l fpul,@-r15" 2106 [(set_attr "type" "store") 2107 (set_attr "hit_stack" "yes")]) 2108 2109;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4, 2110;; so use that. 2111(define_expand "push_4" 2112 [(parallel [(set (mem:DF (pre_dec:SI (reg:SI 15))) (match_operand:DF 0 "" "")) 2113 (use (reg:PSI 48)) 2114 (clobber (scratch:SI))])] 2115 "" 2116 "") 2117 2118(define_expand "pop_e" 2119 [(parallel [(set (match_operand:SF 0 "" "") 2120 (mem:SF (post_inc:SI (reg:SI 15)))) 2121 (use (reg:PSI 48)) 2122 (clobber (scratch:SI))])] 2123 "" 2124 "") 2125 2126(define_insn "pop_fpul" 2127 [(set (reg:SF 22) (mem:SF (post_inc:SI (reg:SI 15))))] 2128 "TARGET_SH3E" 2129 "lds.l @r15+,fpul" 2130 [(set_attr "type" "load") 2131 (set_attr "hit_stack" "yes")]) 2132 2133(define_expand "pop_4" 2134 [(parallel [(set (match_operand:DF 0 "" "") 2135 (mem:DF (post_inc:SI (reg:SI 15)))) 2136 (use (reg:PSI 48)) 2137 (clobber (scratch:SI))])] 2138 "" 2139 "") 2140 2141;; These two patterns can happen as the result of optimization, when 2142;; comparisons get simplified to a move of zero or 1 into the T reg. 2143;; They don't disappear completely, because the T reg is a fixed hard reg. 2144 2145(define_insn "clrt" 2146 [(set (reg:SI 18) (const_int 0))] 2147 "" 2148 "clrt") 2149 2150(define_insn "sett" 2151 [(set (reg:SI 18) (const_int 1))] 2152 "" 2153 "sett") 2154 2155;; t/r must come after r/r, lest reload will try to reload stuff like 2156;; (set (subreg:SI (mem:QI (plus:SI (reg:SI 15 r15) (const_int 12)) 0) 0) 2157;; (made from (set (subreg:SI (reg:QI 73) 0) ) into T. 2158(define_insn "movsi_i" 2159 [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,t,r,r,r,m,<,<,xl,x,l,r") 2160 (match_operand:SI 1 "general_movsrc_operand" "Q,rI,r,mr,xl,t,r,x,l,r,>,>,i"))] 2161 " 2162 ! TARGET_SH3E 2163 && (register_operand (operands[0], SImode) 2164 || register_operand (operands[1], SImode))" 2165 "@ 2166 mov.l %1,%0 2167 mov %1,%0 2168 cmp/pl %1 2169 mov.l %1,%0 2170 sts %1,%0 2171 movt %0 2172 mov.l %1,%0 2173 sts.l %1,%0 2174 sts.l %1,%0 2175 lds %1,%0 2176 lds.l %1,%0 2177 lds.l %1,%0 2178 fake %1,%0" 2179 [(set_attr "type" "pcload_si,move,*,load_si,move,move,store,store,pstore,move,load,pload,pcload_si") 2180 (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*")]) 2181 2182;; t/r must come after r/r, lest reload will try to reload stuff like 2183;; (subreg:SI (reg:SF 38 fr14) 0) into T (compiling stdlib/strtod.c -m3e -O2) 2184;; ??? This allows moves from macl to fpul to be recognized, but these moves 2185;; will require a reload. 2186(define_insn "movsi_ie" 2187 [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,t,r,r,r,m,<,<,xl,x,l,y,r,y,r,y") 2188 (match_operand:SI 1 "general_movsrc_operand" "Q,rI,r,mr,xl,t,r,x,l,r,>,>,>,i,r,y,y"))] 2189 "TARGET_SH3E 2190 && (register_operand (operands[0], SImode) 2191 || register_operand (operands[1], SImode))" 2192 "@ 2193 mov.l %1,%0 2194 mov %1,%0 2195 cmp/pl %1 2196 mov.l %1,%0 2197 sts %1,%0 2198 movt %0 2199 mov.l %1,%0 2200 sts.l %1,%0 2201 sts.l %1,%0 2202 lds %1,%0 2203 lds.l %1,%0 2204 lds.l %1,%0 2205 lds.l %1,%0 2206 fake %1,%0 2207 lds %1,%0 2208 sts %1,%0 2209 ! move optimized away" 2210 [(set_attr "type" "pcload_si,move,*,load_si,move,move,store,store,pstore,move,load,pload,load,pcload_si,gp_fpul,gp_fpul,nil") 2211 (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,0")]) 2212 2213(define_insn "movsi_i_lowpart" 2214 [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "=r,r,r,r,r,m,r")) 2215 (match_operand:SI 1 "general_movsrc_operand" "Q,rI,mr,xl,t,r,i"))] 2216 "register_operand (operands[0], SImode) 2217 || register_operand (operands[1], SImode)" 2218 "@ 2219 mov.l %1,%0 2220 mov %1,%0 2221 mov.l %1,%0 2222 sts %1,%0 2223 movt %0 2224 mov.l %1,%0 2225 fake %1,%0" 2226 [(set_attr "type" "pcload,move,load,move,move,store,pcload")]) 2227(define_expand "movsi" 2228 [(set (match_operand:SI 0 "general_movdst_operand" "") 2229 (match_operand:SI 1 "general_movsrc_operand" ""))] 2230 "" 2231 "{ if (prepare_move_operands (operands, SImode)) DONE; }") 2232 2233(define_expand "ic_invalidate_line" 2234 [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r") 2235 (match_dup 1)] 12) 2236 (clobber (scratch:SI))])] 2237 "TARGET_HARD_SH4" 2238 " 2239{ 2240 operands[0] = force_reg (Pmode, operands[0]); 2241 operands[1] = force_reg (Pmode, GEN_INT (0xf0000008)); 2242}") 2243 2244;; The address %0 is assumed to be 4-aligned at least. Thus, by ORing 2245;; 0xf0000008, we get the low-oder bits *1*00 (binary), ;; which fits 2246;; the requirement *0*00 for associative address writes. The alignment of 2247;; %0 implies that its least significant bit is cleared, 2248;; thus we clear the V bit of a matching entry if there is one. 2249(define_insn "ic_invalidate_line_i" 2250 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r,r") 2251 (match_operand:SI 1 "register_operand" "r,r")] 12) 2252 (clobber (match_scratch:SI 2 "=&r,1"))] 2253 "TARGET_HARD_SH4" 2254 "ocbwb\\t@%0\;extu.w\\t%0,%2\;or\\t%r1,%r2\;mov.l\\t%0,@%2" 2255 [(set_attr "length" "8")]) 2256 2257(define_insn "movqi_i" 2258 [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,m,r,r,l") 2259 (match_operand:QI 1 "general_movsrc_operand" "ri,m,r,t,l,r"))] 2260 "arith_reg_operand (operands[0], QImode) 2261 || arith_reg_operand (operands[1], QImode)" 2262 "@ 2263 mov %1,%0 2264 mov.b %1,%0 2265 mov.b %1,%0 2266 movt %0 2267 sts %1,%0 2268 lds %1,%0" 2269 [(set_attr "type" "move,load,store,move,move,move")]) 2270 2271(define_expand "movqi" 2272 [(set (match_operand:QI 0 "general_operand" "") 2273 (match_operand:QI 1 "general_operand" ""))] 2274 "" 2275 "{ if (prepare_move_operands (operands, QImode)) DONE; }") 2276 2277(define_insn "movhi_i" 2278 [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m,r,l,r") 2279 (match_operand:HI 1 "general_movsrc_operand" "Q,rI,m,t,r,l,r,i"))] 2280 "arith_reg_operand (operands[0], HImode) 2281 || arith_reg_operand (operands[1], HImode)" 2282 "@ 2283 mov.w %1,%0 2284 mov %1,%0 2285 mov.w %1,%0 2286 movt %0 2287 mov.w %1,%0 2288 sts %1,%0 2289 lds %1,%0 2290 fake %1,%0" 2291 [(set_attr "type" "pcload,move,load,move,store,move,move,pcload")]) 2292 2293(define_expand "movhi" 2294 [(set (match_operand:HI 0 "general_movdst_operand" "") 2295 (match_operand:HI 1 "general_movsrc_operand" ""))] 2296 "" 2297 "{ if (prepare_move_operands (operands, HImode)) DONE; }") 2298 2299;; ??? This should be a define expand. 2300 2301;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c 2302;; compiled with -m2 -ml -O3 -funroll-loops 2303(define_insn "" 2304 [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x") 2305 (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I,i,x,r"))] 2306 "arith_reg_operand (operands[0], DImode) 2307 || arith_reg_operand (operands[1], DImode)" 2308 "* return output_movedouble (insn, operands, DImode);" 2309 [(set_attr "length" "4") 2310 (set_attr "type" "pcload,move,load,store,move,pcload,move,move")]) 2311 2312;; If the output is a register and the input is memory or a register, we have 2313;; to be careful and see which word needs to be loaded first. 2314 2315(define_split 2316 [(set (match_operand:DI 0 "general_movdst_operand" "") 2317 (match_operand:DI 1 "general_movsrc_operand" ""))] 2318 "reload_completed" 2319 [(set (match_dup 2) (match_dup 3)) 2320 (set (match_dup 4) (match_dup 5))] 2321 " 2322{ 2323 int regno; 2324 2325 if ((GET_CODE (operands[0]) == MEM 2326 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) 2327 || (GET_CODE (operands[1]) == MEM 2328 && GET_CODE (XEXP (operands[1], 0)) == POST_INC)) 2329 FAIL; 2330 2331 if (GET_CODE (operands[0]) == REG) 2332 regno = REGNO (operands[0]); 2333 else if (GET_CODE (operands[0]) == SUBREG) 2334 regno = REGNO (SUBREG_REG (operands[0])) + SUBREG_WORD (operands[0]); 2335 else if (GET_CODE (operands[0]) == MEM) 2336 regno = -1; 2337 2338 if (regno == -1 2339 || ! refers_to_regno_p (regno, regno + 1, operands[1], 0)) 2340 { 2341 operands[2] = operand_subword (operands[0], 0, 0, DImode); 2342 operands[3] = operand_subword (operands[1], 0, 0, DImode); 2343 operands[4] = operand_subword (operands[0], 1, 0, DImode); 2344 operands[5] = operand_subword (operands[1], 1, 0, DImode); 2345 } 2346 else 2347 { 2348 operands[2] = operand_subword (operands[0], 1, 0, DImode); 2349 operands[3] = operand_subword (operands[1], 1, 0, DImode); 2350 operands[4] = operand_subword (operands[0], 0, 0, DImode); 2351 operands[5] = operand_subword (operands[1], 0, 0, DImode); 2352 } 2353 2354 if (operands[2] == 0 || operands[3] == 0 2355 || operands[4] == 0 || operands[5] == 0) 2356 FAIL; 2357}") 2358 2359(define_expand "movdi" 2360 [(set (match_operand:DI 0 "general_movdst_operand" "") 2361 (match_operand:DI 1 "general_movsrc_operand" ""))] 2362 "" 2363 "{ if ( prepare_move_operands (operands, DImode)) DONE; }") 2364 2365;; ??? This should be a define expand. 2366 2367(define_insn "movdf_k" 2368 [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m") 2369 (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))] 2370 "(! TARGET_SH4 || reload_completed 2371 /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */ 2372 || GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3 2373 || GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3) 2374 && (arith_reg_operand (operands[0], DFmode) 2375 || arith_reg_operand (operands[1], DFmode))" 2376 "* return output_movedouble (insn, operands, DFmode);" 2377 [(set_attr "length" "4") 2378 (set_attr "type" "move,pcload,load,store")]) 2379 2380;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD. 2381;; However, the d/F/c/z alternative cannot be split directly; it is converted 2382;; with special code in machine_dependent_reorg into a load of the R0_REG and 2383;; the d/m/c/X alternative, which is split later into single-precision 2384;; instructions. And when not optimizing, no splits are done before fixing 2385;; up pcloads, so we need usable length information for that. 2386(define_insn "movdf_i4" 2387 [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d") 2388 (match_operand:DF 1 "general_movsrc_operand" "d,r,F,m,d,FQ,m,r,d,r")) 2389 (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c")) 2390 (clobber (match_scratch:SI 3 "=X,X,&z,X,X,X,X,X,X,X"))] 2391 "TARGET_SH4 2392 && (arith_reg_operand (operands[0], DFmode) 2393 || arith_reg_operand (operands[1], DFmode))" 2394 "@ 2395 fmov %1,%0 2396 # 2397 # 2398 fmov.d %1,%0 2399 fmov.d %1,%0 2400 # 2401 # 2402 # 2403 # 2404 #" 2405 [(set_attr_alternative "length" 2406 [(if_then_else (eq_attr "fmovd" "yes") (const_int 2) (const_int 4)) 2407 (const_int 4) 2408 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6)) 2409 (if_then_else (eq_attr "fmovd" "yes") (const_int 2) (const_int 6)) 2410 (if_then_else (eq_attr "fmovd" "yes") (const_int 2) (const_int 6)) 2411 (const_int 4) 2412 (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn) 2413 (const_int 8) (const_int 8)]) 2414 (set_attr "type" "fmove,move,pcload,load,store,pcload,load,store,load,load")]) 2415 2416;; Moving DFmode between fp/general registers through memory 2417;; (the top of the stack) is faster than moving through fpul even for 2418;; little endian. Because the type of an instruction is important for its 2419;; scheduling, it is beneficial to split these operations, rather than 2420;; emitting them in one single chunk, even if this will expose a stack 2421;; use that will prevent scheduling of other stack accesses beyond this 2422;; instruction. 2423(define_split 2424 [(set (match_operand:DF 0 "register_operand" "") 2425 (match_operand:DF 1 "register_operand" "")) 2426 (use (match_operand:PSI 2 "fpscr_operand" "c")) 2427 (clobber (match_scratch:SI 3 "=X"))] 2428 "TARGET_SH4 && reload_completed 2429 && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)" 2430 [(const_int 0)] 2431 " 2432{ 2433 rtx insn, tos; 2434 2435 tos = gen_rtx (MEM, DFmode, gen_rtx (PRE_DEC, Pmode, stack_pointer_rtx)); 2436 insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2])); 2437 REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, stack_pointer_rtx, NULL_RTX); 2438 tos = gen_rtx (MEM, DFmode, gen_rtx (POST_INC, Pmode, stack_pointer_rtx)); 2439 insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2])); 2440 REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, stack_pointer_rtx, NULL_RTX); 2441 DONE; 2442}") 2443 2444;; local-alloc sometimes allocates scratch registers even when not required, 2445;; so we must be prepared to handle these. 2446 2447;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k. 2448(define_split 2449 [(set (match_operand:DF 0 "general_movdst_operand" "") 2450 (match_operand:DF 1 "general_movsrc_operand" "")) 2451 (use (match_operand:PSI 2 "fpscr_operand" "c")) 2452 (clobber (match_scratch:SI 3 "X"))] 2453 "TARGET_SH4 2454 && reload_completed 2455 && true_regnum (operands[0]) < 16 2456 && true_regnum (operands[1]) < 16" 2457 [(set (match_dup 0) (match_dup 1))] 2458 " 2459{ 2460 /* If this was a reg <-> mem operation with base + index reg addressing, 2461 we have to handle this in a special way. */ 2462 rtx mem = operands[0]; 2463 int store_p = 1; 2464 if (! memory_operand (mem, DFmode)) 2465 { 2466 mem = operands[1]; 2467 store_p = 0; 2468 } 2469 if (GET_CODE (mem) == SUBREG && SUBREG_WORD (mem) == 0) 2470 mem = SUBREG_REG (mem); 2471 if (GET_CODE (mem) == MEM) 2472 { 2473 rtx addr = XEXP (mem, 0); 2474 if (GET_CODE (addr) == PLUS 2475 && GET_CODE (XEXP (addr, 0)) == REG 2476 && GET_CODE (XEXP (addr, 1)) == REG) 2477 { 2478 int offset; 2479 rtx reg0 = gen_rtx (REG, Pmode, 0); 2480 rtx regop = operands[store_p], word0 ,word1; 2481 2482 if (GET_CODE (regop) == SUBREG) 2483 regop = alter_subreg (regop); 2484 if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1))) 2485 offset = 2; 2486 else 2487 offset = 4; 2488 mem = copy_rtx (mem); 2489 PUT_MODE (mem, SImode); 2490 word0 = gen_rtx(SUBREG, SImode, regop, 0); 2491 emit_insn (store_p 2492 ? gen_movsi_ie (mem, word0) : gen_movsi_ie (word0, mem)); 2493 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset))); 2494 mem = copy_rtx (mem); 2495 word1 = gen_rtx(SUBREG, SImode, regop, 1); 2496 emit_insn (store_p 2497 ? gen_movsi_ie (mem, word1) : gen_movsi_ie (word1, mem)); 2498 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset))); 2499 DONE; 2500 } 2501 } 2502}") 2503 2504;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads. 2505(define_split 2506 [(set (match_operand:DF 0 "register_operand" "") 2507 (match_operand:DF 1 "memory_operand" "")) 2508 (use (match_operand:PSI 2 "fpscr_operand" "c")) 2509 (clobber (reg:SI 0))] 2510 "TARGET_SH4 && reload_completed" 2511 [(parallel [(set (match_dup 0) (match_dup 1)) 2512 (use (match_dup 2)) 2513 (clobber (scratch:SI))])] 2514 "") 2515 2516(define_expand "reload_indf" 2517 [(parallel [(set (match_operand:DF 0 "register_operand" "=f") 2518 (match_operand:DF 1 "immediate_operand" "FQ")) 2519 (use (reg:PSI 48)) 2520 (clobber (match_operand:SI 2 "register_operand" "=&z"))])] 2521 "" 2522 "") 2523 2524(define_expand "reload_outdf" 2525 [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f") 2526 (match_operand:DF 1 "register_operand" "af,r")) 2527 (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])] 2528 "" 2529 "") 2530 2531;; Simplify no-op moves. 2532(define_split 2533 [(set (match_operand:SF 0 "register_operand" "") 2534 (match_operand:SF 1 "register_operand" "")) 2535 (use (match_operand:PSI 2 "fpscr_operand" "")) 2536 (clobber (match_scratch:SI 3 "X"))] 2537 "TARGET_SH3E && reload_completed 2538 && true_regnum (operands[0]) == true_regnum (operands[1])" 2539 [(set (match_dup 0) (match_dup 0))] 2540 "") 2541 2542;; fmovd substitute post-reload splits 2543(define_split 2544 [(set (match_operand:DF 0 "register_operand" "") 2545 (match_operand:DF 1 "register_operand" "")) 2546 (use (match_operand:PSI 2 "fpscr_operand" "c")) 2547 (clobber (match_scratch:SI 3 "X"))] 2548 "TARGET_SH4 && ! TARGET_FMOVD && reload_completed 2549 && true_regnum (operands[0]) >= FIRST_FP_REG 2550 && true_regnum (operands[1]) >= FIRST_FP_REG" 2551 [(const_int 0)] 2552 " 2553{ 2554 int dst = true_regnum (operands[0]), src = true_regnum (operands[1]); 2555 emit_insn (gen_movsf_ie (gen_rtx (REG, SFmode, dst), 2556 gen_rtx (REG, SFmode, src), operands[2])); 2557 emit_insn (gen_movsf_ie (gen_rtx (REG, SFmode, dst + 1), 2558 gen_rtx (REG, SFmode, src + 1), operands[2])); 2559 DONE; 2560}") 2561 2562(define_split 2563 [(set (match_operand:DF 0 "register_operand" "") 2564 (mem:DF (match_operand:SI 1 "register_operand" ""))) 2565 (use (match_operand:PSI 2 "fpscr_operand" "c")) 2566 (clobber (match_scratch:SI 3 "X"))] 2567 "TARGET_SH4 && ! TARGET_FMOVD && reload_completed 2568 && true_regnum (operands[0]) >= FIRST_FP_REG 2569 && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))" 2570 [(const_int 0)] 2571 " 2572{ 2573 int regno = true_regnum (operands[0]); 2574 rtx insn; 2575 rtx mem2 = gen_rtx (MEM, SFmode, gen_rtx (POST_INC, Pmode, operands[1])); 2576 2577 insn = emit_insn (gen_movsf_ie (gen_rtx (REG, SFmode, 2578 regno + !! TARGET_LITTLE_ENDIAN), 2579 mem2, operands[2])); 2580 REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, operands[1], NULL_RTX); 2581 insn = emit_insn (gen_movsf_ie (gen_rtx (REG, SFmode, 2582 regno + ! TARGET_LITTLE_ENDIAN), 2583 gen_rtx (MEM, SFmode, operands[1]), 2584 operands[2])); 2585 DONE; 2586}") 2587 2588(define_split 2589 [(set (match_operand:DF 0 "register_operand" "") 2590 (match_operand:DF 1 "memory_operand" "")) 2591 (use (match_operand:PSI 2 "fpscr_operand" "c")) 2592 (clobber (match_scratch:SI 3 "X"))] 2593 "TARGET_SH4 && ! TARGET_FMOVD && reload_completed 2594 && true_regnum (operands[0]) >= FIRST_FP_REG" 2595 [(const_int 0)] 2596 " 2597{ 2598 int regno = true_regnum (operands[0]); 2599 rtx addr, insn, adjust = NULL_RTX; 2600 rtx mem2 = copy_rtx (operands[1]); 2601 rtx reg0 = gen_rtx_REG (SFmode, regno + !! TARGET_LITTLE_ENDIAN); 2602 rtx reg1 = gen_rtx_REG (SFmode, regno + ! TARGET_LITTLE_ENDIAN); 2603 2604 PUT_MODE (mem2, SFmode); 2605 operands[1] = copy_rtx (mem2); 2606 addr = XEXP (mem2, 0); 2607 if (GET_CODE (addr) != POST_INC) 2608 { 2609 /* If we have to modify the stack pointer, the value that we have 2610 read with post-increment might be modified by an interrupt, 2611 so write it back. */ 2612 if (REGNO (addr) == STACK_POINTER_REGNUM) 2613 adjust = gen_push_e (reg0); 2614 else 2615 adjust = gen_addsi3 (addr, addr, GEN_INT (-4)); 2616 XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr); 2617 } 2618 addr = XEXP (addr, 0); 2619 insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2])); 2620 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX); 2621 insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2])); 2622 if (adjust) 2623 emit_insn (adjust); 2624 else 2625 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX); 2626 DONE; 2627}") 2628 2629(define_split 2630 [(set (match_operand:DF 0 "memory_operand" "") 2631 (match_operand:DF 1 "register_operand" "")) 2632 (use (match_operand:PSI 2 "fpscr_operand" "c")) 2633 (clobber (match_scratch:SI 3 "X"))] 2634 "TARGET_SH4 && ! TARGET_FMOVD && reload_completed 2635 && true_regnum (operands[1]) >= FIRST_FP_REG" 2636 [(const_int 0)] 2637 " 2638{ 2639 int regno = true_regnum (operands[1]); 2640 rtx insn, addr, adjust = NULL_RTX; 2641 2642 operands[0] = copy_rtx (operands[0]); 2643 PUT_MODE (operands[0], SFmode); 2644 insn = emit_insn (gen_movsf_ie (operands[0], 2645 gen_rtx (REG, SFmode, 2646 regno + ! TARGET_LITTLE_ENDIAN), 2647 operands[2])); 2648 operands[0] = copy_rtx (operands[0]); 2649 addr = XEXP (operands[0], 0); 2650 if (GET_CODE (addr) != PRE_DEC) 2651 { 2652 adjust = gen_addsi3 (addr, addr, GEN_INT (4)); 2653 emit_insn_before (adjust, insn); 2654 XEXP (operands[0], 0) = addr = gen_rtx (PRE_DEC, SImode, addr); 2655 } 2656 addr = XEXP (addr, 0); 2657 if (! adjust) 2658 REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, addr, NULL_RTX); 2659 insn = emit_insn (gen_movsf_ie (operands[0], 2660 gen_rtx (REG, SFmode, 2661 regno + !! TARGET_LITTLE_ENDIAN), 2662 operands[2])); 2663 REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, addr, NULL_RTX); 2664 DONE; 2665}") 2666 2667;; The '&' for operand 2 is not really true, but push_secondary_reload 2668;; insists on it. 2669;; Operand 1 must accept FPUL_REGS in case fpul is reloaded to memory, 2670;; to avoid a bogus tertiary reload. 2671;; We need a tertiary reload when a floating point register is reloaded 2672;; to memory, so the predicate for operand 0 must accept this, while the 2673;; constraint of operand 1 must reject the secondary reload register. 2674;; Thus, the secondary reload register for this case has to be GENERAL_REGS, 2675;; too. 2676;; By having the predicate for operand 0 reject any register, we make 2677;; sure that the ordinary moves that just need an intermediate register 2678;; won't get a bogus tertiary reload. 2679;; We use tertiary_reload_operand instead of memory_operand here because 2680;; memory_operand rejects operands that are not directly addressible, e.g.: 2681;; (mem:SF (plus:SI (reg:SI 14 r14) 2682;; (const_int 132))) 2683 2684(define_expand "reload_outsf" 2685 [(parallel [(set (match_operand:SF 2 "register_operand" "=&r") 2686 (match_operand:SF 1 "register_operand" "y")) 2687 (clobber (scratch:SI))]) 2688 (parallel [(set (match_operand:SF 0 "tertiary_reload_operand" "=m") 2689 (match_dup 2)) 2690 (clobber (scratch:SI))])] 2691 "" 2692 "") 2693 2694;; If the output is a register and the input is memory or a register, we have 2695;; to be careful and see which word needs to be loaded first. 2696 2697(define_split 2698 [(set (match_operand:DF 0 "general_movdst_operand" "") 2699 (match_operand:DF 1 "general_movsrc_operand" ""))] 2700 "reload_completed" 2701 [(set (match_dup 2) (match_dup 3)) 2702 (set (match_dup 4) (match_dup 5))] 2703 " 2704{ 2705 int regno; 2706 2707 if ((GET_CODE (operands[0]) == MEM 2708 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) 2709 || (GET_CODE (operands[1]) == MEM 2710 && GET_CODE (XEXP (operands[1], 0)) == POST_INC)) 2711 FAIL; 2712 2713 if (GET_CODE (operands[0]) == REG) 2714 regno = REGNO (operands[0]); 2715 else if (GET_CODE (operands[0]) == SUBREG) 2716 regno = REGNO (SUBREG_REG (operands[0])) + SUBREG_WORD (operands[0]); 2717 else if (GET_CODE (operands[0]) == MEM) 2718 regno = -1; 2719 2720 if (regno == -1 2721 || ! refers_to_regno_p (regno, regno + 1, operands[1], 0)) 2722 { 2723 operands[2] = operand_subword (operands[0], 0, 0, DFmode); 2724 operands[3] = operand_subword (operands[1], 0, 0, DFmode); 2725 operands[4] = operand_subword (operands[0], 1, 0, DFmode); 2726 operands[5] = operand_subword (operands[1], 1, 0, DFmode); 2727 } 2728 else 2729 { 2730 operands[2] = operand_subword (operands[0], 1, 0, DFmode); 2731 operands[3] = operand_subword (operands[1], 1, 0, DFmode); 2732 operands[4] = operand_subword (operands[0], 0, 0, DFmode); 2733 operands[5] = operand_subword (operands[1], 0, 0, DFmode); 2734 } 2735 2736 if (operands[2] == 0 || operands[3] == 0 2737 || operands[4] == 0 || operands[5] == 0) 2738 FAIL; 2739}") 2740 2741;; If a base address generated by LEGITIMIZE_ADDRESS for SImode is 2742;; used only once, let combine add in the index again. 2743 2744(define_split 2745 [(set (match_operand:SI 0 "register_operand" "") 2746 (match_operand:SI 1 "" "")) 2747 (clobber (match_operand 2 "register_operand" ""))] 2748 "! reload_in_progress && ! reload_completed" 2749 [(use (reg:SI 0))] 2750 " 2751{ 2752 rtx addr, reg, const_int; 2753 2754 if (GET_CODE (operands[1]) != MEM) 2755 FAIL; 2756 addr = XEXP (operands[1], 0); 2757 if (GET_CODE (addr) != PLUS) 2758 FAIL; 2759 reg = XEXP (addr, 0); 2760 const_int = XEXP (addr, 1); 2761 if (GET_CODE (reg) != REG || GET_CODE (const_int) != CONST_INT) 2762 FAIL; 2763 emit_move_insn (operands[2], const_int); 2764 emit_move_insn (operands[0], 2765 change_address (operands[1], VOIDmode, 2766 gen_rtx (PLUS, SImode, reg, operands[2]))); 2767 DONE; 2768}") 2769 2770(define_split 2771 [(set (match_operand:SI 1 "" "") 2772 (match_operand:SI 0 "register_operand" "")) 2773 (clobber (match_operand 2 "register_operand" ""))] 2774 "! reload_in_progress && ! reload_completed" 2775 [(use (reg:SI 0))] 2776 " 2777{ 2778 rtx addr, reg, const_int; 2779 2780 if (GET_CODE (operands[1]) != MEM) 2781 FAIL; 2782 addr = XEXP (operands[1], 0); 2783 if (GET_CODE (addr) != PLUS) 2784 FAIL; 2785 reg = XEXP (addr, 0); 2786 const_int = XEXP (addr, 1); 2787 if (GET_CODE (reg) != REG || GET_CODE (const_int) != CONST_INT) 2788 FAIL; 2789 emit_move_insn (operands[2], const_int); 2790 emit_move_insn (change_address (operands[1], VOIDmode, 2791 gen_rtx (PLUS, SImode, reg, operands[2])), 2792 operands[0]); 2793 DONE; 2794}") 2795 2796(define_expand "movdf" 2797 [(set (match_operand:DF 0 "general_movdst_operand" "") 2798 (match_operand:DF 1 "general_movsrc_operand" ""))] 2799 "" 2800 " 2801{ 2802 if (prepare_move_operands (operands, DFmode)) DONE; 2803 if (TARGET_SH4) 2804 { 2805 if (no_new_pseudos) 2806 { 2807 /* ??? FIXME: This is only a stopgap fix. There is no guarantee 2808 that fpscr is in the right state. */ 2809 emit_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ())); 2810 DONE; 2811 } 2812 emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ())); 2813 /* We need something to tag possible REG_LIBCALL notes on to. */ 2814 if (TARGET_FPU_SINGLE && rtx_equal_function_value_matters 2815 && GET_CODE (operands[0]) == REG) 2816 emit_insn (gen_mov_nop (operands[0])); 2817 DONE; 2818 } 2819}") 2820 2821 2822(define_insn "movsf_i" 2823 [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r") 2824 (match_operand:SF 1 "general_movsrc_operand" "r,I,FQ,mr,r,r,l"))] 2825 " 2826 (! TARGET_SH3E 2827 /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */ 2828 || GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3 2829 || GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3) 2830 && (arith_reg_operand (operands[0], SFmode) 2831 || arith_reg_operand (operands[1], SFmode))" 2832 "@ 2833 mov %1,%0 2834 mov %1,%0 2835 mov.l %1,%0 2836 mov.l %1,%0 2837 mov.l %1,%0 2838 lds %1,%0 2839 sts %1,%0" 2840 [(set_attr "type" "move,move,pcload,load,store,move,move")]) 2841 2842;; We may not split the ry/yr/XX alternatives to movsi_ie, since 2843;; update_flow_info would not know where to put REG_EQUAL notes 2844;; when the destination changes mode. 2845(define_insn "movsf_ie" 2846 [(set (match_operand:SF 0 "general_movdst_operand" 2847 "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,y") 2848 (match_operand:SF 1 "general_movsrc_operand" 2849 "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y")) 2850 (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c")) 2851 (clobber (match_scratch:SI 3 "=X,X,X,X,&z,X,X,X,X,X,X,X,X,y,X,X,X"))] 2852 2853 "TARGET_SH3E 2854 && (arith_reg_operand (operands[0], SFmode) 2855 || arith_reg_operand (operands[1], SFmode))" 2856 "@ 2857 fmov %1,%0 2858 mov %1,%0 2859 fldi0 %0 2860 fldi1 %0 2861 # 2862 fmov.s %1,%0 2863 fmov.s %1,%0 2864 mov.l %1,%0 2865 mov.l %1,%0 2866 mov.l %1,%0 2867 fsts fpul,%0 2868 flds %1,fpul 2869 lds.l %1,%0 2870 # 2871 sts %1,%0 2872 lds %1,%0 2873 ! move optimized away" 2874 [(set_attr "type" "fmove,move,fmove,fmove,pcload,load,store,pcload,load,store,fmove,fmove,load,*,gp_fpul,gp_fpul,nil") 2875 (set_attr "length" "*,*,*,*,4,*,*,*,*,*,2,2,2,4,2,2,0")]) 2876 2877(define_split 2878 [(set (match_operand:SF 0 "register_operand" "") 2879 (match_operand:SF 1 "register_operand" "")) 2880 (use (match_operand:PSI 2 "fpscr_operand" "c")) 2881 (clobber (reg:SI 22))] 2882 "" 2883 [(parallel [(set (reg:SF 22) (match_dup 1)) 2884 (use (match_dup 2)) 2885 (clobber (scratch:SI))]) 2886 (parallel [(set (match_dup 0) (reg:SF 22)) 2887 (use (match_dup 2)) 2888 (clobber (scratch:SI))])] 2889 "") 2890 2891(define_expand "movsf" 2892 [(set (match_operand:SF 0 "general_movdst_operand" "") 2893 (match_operand:SF 1 "general_movsrc_operand" ""))] 2894 "" 2895 " 2896{ 2897 if (prepare_move_operands (operands, SFmode)) 2898 DONE; 2899 if (TARGET_SH3E) 2900 { 2901 if (no_new_pseudos) 2902 { 2903 /* ??? FIXME: This is only a stopgap fix. There is no guarantee 2904 that fpscr is in the right state. */ 2905 emit_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ())); 2906 DONE; 2907 } 2908 emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ())); 2909 /* We need something to tag possible REG_LIBCALL notes on to. */ 2910 if (! TARGET_FPU_SINGLE && rtx_equal_function_value_matters 2911 && GET_CODE (operands[0]) == REG) 2912 emit_insn (gen_mov_nop (operands[0])); 2913 DONE; 2914 } 2915}") 2916 2917(define_insn "mov_nop" 2918 [(set (match_operand 0 "register_operand" "") (match_dup 0))] 2919 "TARGET_SH3E" 2920 "" 2921 [(set_attr "length" "0") 2922 (set_attr "type" "nil")]) 2923 2924(define_expand "reload_insf" 2925 [(parallel [(set (match_operand:SF 0 "register_operand" "=f") 2926 (match_operand:SF 1 "immediate_operand" "FQ")) 2927 (use (reg:PSI 48)) 2928 (clobber (match_operand:SI 2 "register_operand" "=&z"))])] 2929 "" 2930 "") 2931 2932(define_expand "reload_insi" 2933 [(parallel [(set (match_operand:SF 0 "register_operand" "=y") 2934 (match_operand:SF 1 "immediate_operand" "FQ")) 2935 (clobber (match_operand:SI 2 "register_operand" "=&z"))])] 2936 "" 2937 "") 2938 2939(define_insn "*movsi_y" 2940 [(set (match_operand:SI 0 "register_operand" "=y,y") 2941 (match_operand:SI 1 "immediate_operand" "Qi,I")) 2942 (clobber (match_scratch:SI 3 "=&z,r"))] 2943 "TARGET_SH3E 2944 && (reload_in_progress || reload_completed)" 2945 "#" 2946 [(set_attr "length" "4") 2947 (set_attr "type" "pcload,move")]) 2948 2949(define_split 2950 [(set (match_operand:SI 0 "register_operand" "y") 2951 (match_operand:SI 1 "immediate_operand" "I")) 2952 (clobber (match_operand:SI 2 "register_operand" "r"))] 2953 "" 2954 [(set (match_dup 2) (match_dup 1)) 2955 (set (match_dup 0) (match_dup 2))] 2956 "") 2957 2958(define_split 2959 [(set (match_operand:SI 0 "register_operand" "y") 2960 (match_operand:SI 1 "memory_operand" ">")) 2961 (clobber (reg:SI 0))] 2962 "" 2963 [(set (match_dup 0) (match_dup 1))] 2964 "") 2965 2966;; ------------------------------------------------------------------------ 2967;; Define the real conditional branch instructions. 2968;; ------------------------------------------------------------------------ 2969 2970(define_insn "branch_true" 2971 [(set (pc) (if_then_else (ne (reg:SI 18) (const_int 0)) 2972 (label_ref (match_operand 0 "" "")) 2973 (pc)))] 2974 "" 2975 "* return output_branch (1, insn, operands);" 2976 [(set_attr "type" "cbranch")]) 2977 2978(define_insn "branch_false" 2979 [(set (pc) (if_then_else (eq (reg:SI 18) (const_int 0)) 2980 (label_ref (match_operand 0 "" "")) 2981 (pc)))] 2982 "" 2983 "* return output_branch (0, insn, operands);" 2984 [(set_attr "type" "cbranch")]) 2985 2986;; Patterns to prevent reorg from re-combining a condbranch with a branch 2987;; which destination is too far away. 2988;; The const_int_operand is distinct for each branch target; it avoids 2989;; unwanted matches with redundant_insn. 2990(define_insn "block_branch_redirect" 2991 [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] 4))] 2992 "" 2993 "" 2994 [(set_attr "length" "0")]) 2995 2996;; This one has the additional purpose to record a possible scratch register 2997;; for the following branch. 2998(define_insn "indirect_jump_scratch" 2999 [(set (match_operand 0 "register_operand" "r") 3000 (unspec [(match_operand 1 "const_int_operand" "")] 4))] 3001 "" 3002 "" 3003 [(set_attr "length" "0")]) 3004 3005;; Conditional branch insns 3006 3007(define_expand "beq" 3008 [(set (pc) 3009 (if_then_else (ne (reg:SI 18) (const_int 0)) 3010 (label_ref (match_operand 0 "" "")) 3011 (pc)))] 3012 "" 3013 "from_compare (operands, EQ);") 3014 3015(define_expand "bne" 3016 [(set (pc) 3017 (if_then_else (eq (reg:SI 18) (const_int 0)) 3018 (label_ref (match_operand 0 "" "")) 3019 (pc)))] 3020 "" 3021 "from_compare (operands, EQ);") 3022 3023(define_expand "bgt" 3024 [(set (pc) 3025 (if_then_else (ne (reg:SI 18) (const_int 0)) 3026 (label_ref (match_operand 0 "" "")) 3027 (pc)))] 3028 "" 3029 "from_compare (operands, GT);") 3030 3031(define_expand "blt" 3032 [(set (pc) 3033 (if_then_else (eq (reg:SI 18) (const_int 0)) 3034 (label_ref (match_operand 0 "" "")) 3035 (pc)))] 3036 "" 3037 " 3038{ 3039 if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT) 3040 { 3041 rtx tmp = sh_compare_op0; 3042 sh_compare_op0 = sh_compare_op1; 3043 sh_compare_op1 = tmp; 3044 emit_insn (gen_bgt (operands[0])); 3045 DONE; 3046 } 3047 from_compare (operands, GE); 3048}") 3049 3050(define_expand "ble" 3051 [(set (pc) 3052 (if_then_else (eq (reg:SI 18) (const_int 0)) 3053 (label_ref (match_operand 0 "" "")) 3054 (pc)))] 3055 "" 3056 " 3057{ 3058 if (TARGET_SH3E 3059 && TARGET_IEEE 3060 && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT) 3061 { 3062 rtx tmp = sh_compare_op0; 3063 sh_compare_op0 = sh_compare_op1; 3064 sh_compare_op1 = tmp; 3065 emit_insn (gen_bge (operands[0])); 3066 DONE; 3067 } 3068 from_compare (operands, GT); 3069}") 3070 3071(define_expand "bge" 3072 [(set (pc) 3073 (if_then_else (ne (reg:SI 18) (const_int 0)) 3074 (label_ref (match_operand 0 "" "")) 3075 (pc)))] 3076 "" 3077 " 3078{ 3079 if (TARGET_SH3E 3080 && ! TARGET_IEEE 3081 && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT) 3082 { 3083 rtx tmp = sh_compare_op0; 3084 sh_compare_op0 = sh_compare_op1; 3085 sh_compare_op1 = tmp; 3086 emit_insn (gen_ble (operands[0])); 3087 DONE; 3088 } 3089 from_compare (operands, GE); 3090}") 3091 3092(define_expand "bgtu" 3093 [(set (pc) 3094 (if_then_else (ne (reg:SI 18) (const_int 0)) 3095 (label_ref (match_operand 0 "" "")) 3096 (pc)))] 3097 "" 3098 "from_compare (operands, GTU); ") 3099 3100(define_expand "bltu" 3101 [(set (pc) 3102 (if_then_else (eq (reg:SI 18) (const_int 0)) 3103 (label_ref (match_operand 0 "" "")) 3104 (pc)))] 3105 "" 3106 "from_compare (operands, GEU);") 3107 3108(define_expand "bgeu" 3109 [(set (pc) 3110 (if_then_else (ne (reg:SI 18) (const_int 0)) 3111 (label_ref (match_operand 0 "" "")) 3112 (pc)))] 3113 "" 3114 "from_compare (operands, GEU);") 3115 3116(define_expand "bleu" 3117 [(set (pc) 3118 (if_then_else (eq (reg:SI 18) (const_int 0)) 3119 (label_ref (match_operand 0 "" "")) 3120 (pc)))] 3121 "" 3122 "from_compare (operands, GTU);") 3123 3124;; ------------------------------------------------------------------------ 3125;; Jump and linkage insns 3126;; ------------------------------------------------------------------------ 3127 3128(define_insn "jump" 3129 [(set (pc) 3130 (label_ref (match_operand 0 "" "")))] 3131 "" 3132 "* 3133{ 3134 /* The length is 16 if the delay slot is unfilled. */ 3135 if (get_attr_length(insn) > 4) 3136 return output_far_jump(insn, operands[0]); 3137 else 3138 return \"bra %l0%#\"; 3139}" 3140 [(set_attr "type" "jump") 3141 (set_attr "needs_delay_slot" "yes")]) 3142 3143(define_insn "calli" 3144 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) 3145 (match_operand 1 "" "")) 3146 (use (reg:SI 48)) 3147 (clobber (reg:SI 17))] 3148 "" 3149 "jsr @%0%#" 3150 [(set_attr "type" "call") 3151 (set_attr "needs_delay_slot" "yes")]) 3152 3153(define_insn "call_valuei" 3154 [(set (match_operand 0 "" "=rf") 3155 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) 3156 (match_operand 2 "" ""))) 3157 (use (reg:SI 48)) 3158 (clobber (reg:SI 17))] 3159 "" 3160 "jsr @%1%#" 3161 [(set_attr "type" "call") 3162 (set_attr "needs_delay_slot" "yes")]) 3163 3164(define_expand "call" 3165 [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" "")) 3166 (match_operand 1 "" "")) 3167 (use (reg:SI 48)) 3168 (clobber (reg:SI 17))])] 3169 "" 3170 "operands[0] = force_reg (SImode, XEXP (operands[0], 0));") 3171 3172(define_expand "call_value" 3173 [(parallel [(set (match_operand 0 "arith_reg_operand" "") 3174 (call (mem:SI (match_operand 1 "arith_reg_operand" "")) 3175 (match_operand 2 "" ""))) 3176 (use (reg:SI 48)) 3177 (clobber (reg:SI 17))])] 3178 "" 3179 "operands[1] = force_reg (SImode, XEXP (operands[1], 0));") 3180 3181(define_insn "indirect_jump" 3182 [(set (pc) 3183 (match_operand:SI 0 "arith_reg_operand" "r"))] 3184 "" 3185 "jmp @%0%#" 3186 [(set_attr "needs_delay_slot" "yes") 3187 (set_attr "type" "jump_ind")]) 3188 3189;; The use of operand 1 / 2 helps us distinguish case table jumps 3190;; which can be present in structured code from indirect jumps which can not 3191;; be present in structured code. This allows -fprofile-arcs to work. 3192 3193;; For SH1 processors. 3194(define_insn "casesi_jump_1" 3195 [(set (pc) 3196 (match_operand:SI 0 "register_operand" "r")) 3197 (use (label_ref (match_operand 1 "" "")))] 3198 "" 3199 "jmp @%0%#" 3200 [(set_attr "needs_delay_slot" "yes") 3201 (set_attr "type" "jump_ind")]) 3202 3203;; For all later processors. 3204(define_insn "casesi_jump_2" 3205 [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r") 3206 (label_ref (match_operand 1 "" "")))) 3207 (use (label_ref (match_operand 2 "" "")))] 3208 "! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn" 3209 "braf %0%#" 3210 [(set_attr "needs_delay_slot" "yes") 3211 (set_attr "type" "jump_ind")]) 3212 3213;; Call subroutine returning any type. 3214;; ??? This probably doesn't work. 3215 3216(define_expand "untyped_call" 3217 [(parallel [(call (match_operand 0 "" "") 3218 (const_int 0)) 3219 (match_operand 1 "" "") 3220 (match_operand 2 "" "")])] 3221 "TARGET_SH3E" 3222 " 3223{ 3224 int i; 3225 3226 emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx, const0_rtx)); 3227 3228 for (i = 0; i < XVECLEN (operands[2], 0); i++) 3229 { 3230 rtx set = XVECEXP (operands[2], 0, i); 3231 emit_move_insn (SET_DEST (set), SET_SRC (set)); 3232 } 3233 3234 /* The optimizer does not know that the call sets the function value 3235 registers we stored in the result block. We avoid problems by 3236 claiming that all hard registers are used and clobbered at this 3237 point. */ 3238 emit_insn (gen_blockage ()); 3239 3240 DONE; 3241}") 3242 3243;; ------------------------------------------------------------------------ 3244;; Misc insns 3245;; ------------------------------------------------------------------------ 3246 3247(define_insn "dect" 3248 [(set (reg:SI 18) 3249 (eq:SI (match_operand:SI 0 "arith_reg_operand" "+r") (const_int 1))) 3250 (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))] 3251 "TARGET_SH2" 3252 "dt %0" 3253 [(set_attr "type" "arith")]) 3254 3255(define_insn "nop" 3256 [(const_int 0)] 3257 "" 3258 "nop") 3259 3260;; Load address of a label. This is only generated by the casesi expand, 3261;; and by machine_dependent_reorg (fixing up fp moves). 3262;; This must use unspec, because this only works for labels that are 3263;; within range, 3264 3265(define_insn "mova" 3266 [(set (reg:SI 0) 3267 (unspec [(label_ref (match_operand 0 "" ""))] 1))] 3268 "" 3269 "mova %O0,r0" 3270 [(set_attr "in_delay_slot" "no") 3271 (set_attr "type" "arith")]) 3272 3273;; case instruction for switch statements. 3274 3275;; Operand 0 is index 3276;; operand 1 is the minimum bound 3277;; operand 2 is the maximum bound - minimum bound + 1 3278;; operand 3 is CODE_LABEL for the table; 3279;; operand 4 is the CODE_LABEL to go to if index out of range. 3280 3281(define_expand "casesi" 3282 [(match_operand:SI 0 "arith_reg_operand" "") 3283 (match_operand:SI 1 "arith_reg_operand" "") 3284 (match_operand:SI 2 "arith_reg_operand" "") 3285 (match_operand 3 "" "") (match_operand 4 "" "")] 3286 "" 3287 " 3288{ 3289 rtx reg = gen_reg_rtx (SImode); 3290 rtx reg2 = gen_reg_rtx (SImode); 3291 operands[1] = copy_to_mode_reg (SImode, operands[1]); 3292 operands[2] = copy_to_mode_reg (SImode, operands[2]); 3293 /* If optimizing, casesi_worker depends on the mode of the instruction 3294 before label it 'uses' - operands[3]. */ 3295 emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4], 3296 reg)); 3297 emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3])); 3298 if (TARGET_SH2) 3299 emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3])); 3300 else 3301 emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3])); 3302 /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to 3303 operands[3], but to lab. We will fix this up in 3304 machine_dependent_reorg. */ 3305 emit_barrier (); 3306 DONE; 3307}") 3308 3309(define_expand "casesi_0" 3310 [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" "")) 3311 (set (match_dup 4) (minus:SI (match_dup 4) 3312 (match_operand:SI 1 "arith_operand" ""))) 3313 (set (reg:SI 18) 3314 (gtu:SI (match_dup 4) 3315 (match_operand:SI 2 "arith_reg_operand" ""))) 3316 (set (pc) 3317 (if_then_else (ne (reg:SI 18) 3318 (const_int 0)) 3319 (label_ref (match_operand 3 "" "")) 3320 (pc)))] 3321 "" 3322 "") 3323 3324;; ??? reload might clobber r0 if we use it explicitly in the RTL before 3325;; reload; using a R0_REGS pseudo reg is likely to give poor code. 3326;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload. 3327 3328(define_insn "casesi_worker_0" 3329 [(set (match_operand:SI 0 "register_operand" "=r,r") 3330 (unspec [(match_operand 1 "register_operand" "0,r") 3331 (label_ref (match_operand 2 "" ""))] 2)) 3332 (clobber (match_scratch:SI 3 "=X,1")) 3333 (clobber (match_scratch:SI 4 "=&z,z"))] 3334 "" 3335 "#") 3336 3337(define_split 3338 [(set (match_operand:SI 0 "register_operand" "") 3339 (unspec [(match_operand 1 "register_operand" "") 3340 (label_ref (match_operand 2 "" ""))] 2)) 3341 (clobber (match_scratch:SI 3 "")) 3342 (clobber (match_scratch:SI 4 ""))] 3343 "! TARGET_SH2 && reload_completed" 3344 [(set (reg:SI 0) (unspec [(label_ref (match_dup 2))] 1)) 3345 (parallel [(set (match_dup 0) 3346 (unspec [(reg:SI 0) (match_dup 1) (label_ref (match_dup 2))] 2)) 3347 (clobber (match_dup 3))]) 3348 (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI 0)))] 3349 "LABEL_NUSES (operands[2])++;") 3350 3351(define_split 3352 [(set (match_operand:SI 0 "register_operand" "") 3353 (unspec [(match_operand 1 "register_operand" "") 3354 (label_ref (match_operand 2 "" ""))] 2)) 3355 (clobber (match_scratch:SI 3 "")) 3356 (clobber (match_scratch:SI 4 ""))] 3357 "TARGET_SH2 && reload_completed" 3358 [(set (reg:SI 0) (unspec [(label_ref (match_dup 2))] 1)) 3359 (parallel [(set (match_dup 0) 3360 (unspec [(reg:SI 0) (match_dup 1) (label_ref (match_dup 2))] 2)) 3361 (clobber (match_dup 3))])] 3362 "LABEL_NUSES (operands[2])++;") 3363 3364(define_insn "*casesi_worker" 3365 [(set (match_operand:SI 0 "register_operand" "=r,r") 3366 (unspec [(reg:SI 0) (match_operand 1 "register_operand" "0,r") 3367 (label_ref (match_operand 2 "" ""))] 2)) 3368 (clobber (match_scratch:SI 3 "=X,1"))] 3369 "" 3370 "* 3371{ 3372 rtx diff_vec = PATTERN (next_real_insn (operands[2])); 3373 3374 if (GET_CODE (diff_vec) != ADDR_DIFF_VEC) 3375 abort (); 3376 3377 switch (GET_MODE (diff_vec)) 3378 { 3379 case SImode: 3380 return \"shll2 %1\;mov.l @(r0,%1),%0\"; 3381 case HImode: 3382 return \"add %1,%1\;mov.w @(r0,%1),%0\"; 3383 case QImode: 3384 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned) 3385 return \"mov.b @(r0,%1),%0\;extu.b %0,%0\"; 3386 return \"mov.b @(r0,%1),%0\"; 3387 default: 3388 abort (); 3389 } 3390}" 3391 [(set_attr "length" "4")]) 3392 3393;; ??? This is not the proper place to invoke another compiler pass; 3394;; Alas, there is no proper place to put it. 3395;; ??? This is also an odd place for the call to emit_fpscr_use. It 3396;; would be all right if it were for an define_expand for return, but 3397;; that doesn't mix with emitting a prologue. 3398(define_insn "return" 3399 [(return)] 3400 "emit_fpscr_use (), 3401 remove_dead_before_cse (), 3402 reload_completed" 3403 "%@ %#" 3404 [(set_attr "type" "return") 3405 (set_attr "needs_delay_slot" "yes")]) 3406 3407(define_expand "prologue" 3408 [(const_int 0)] 3409 "" 3410 "sh_expand_prologue (); DONE;") 3411 3412(define_expand "epilogue" 3413 [(return)] 3414 "" 3415 "sh_expand_epilogue ();") 3416 3417(define_insn "blockage" 3418 [(unspec_volatile [(const_int 0)] 0)] 3419 "" 3420 "" 3421 [(set_attr "length" "0")]) 3422 3423;; ------------------------------------------------------------------------ 3424;; Scc instructions 3425;; ------------------------------------------------------------------------ 3426 3427(define_insn "movt" 3428 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 3429 (eq:SI (reg:SI 18) (const_int 1)))] 3430 "" 3431 "movt %0" 3432 [(set_attr "type" "arith")]) 3433 3434(define_expand "seq" 3435 [(set (match_operand:SI 0 "arith_reg_operand" "") 3436 (match_dup 1))] 3437 "" 3438 "operands[1] = prepare_scc_operands (EQ);") 3439 3440(define_expand "slt" 3441 [(set (match_operand:SI 0 "arith_reg_operand" "") 3442 (match_dup 1))] 3443 "" 3444 "operands[1] = prepare_scc_operands (LT);") 3445 3446(define_expand "sle" 3447 [(match_operand:SI 0 "arith_reg_operand" "")] 3448 "" 3449 " 3450{ 3451 rtx tmp = sh_compare_op0; 3452 sh_compare_op0 = sh_compare_op1; 3453 sh_compare_op1 = tmp; 3454 emit_insn (gen_sge (operands[0])); 3455 DONE; 3456}") 3457 3458(define_expand "sgt" 3459 [(set (match_operand:SI 0 "arith_reg_operand" "") 3460 (match_dup 1))] 3461 "" 3462 "operands[1] = prepare_scc_operands (GT);") 3463 3464(define_expand "sge" 3465 [(set (match_operand:SI 0 "arith_reg_operand" "") 3466 (match_dup 1))] 3467 "" 3468 " 3469{ 3470 if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT) 3471 { 3472 if (TARGET_IEEE) 3473 { 3474 rtx t_reg = gen_rtx (REG, SImode, T_REG); 3475 rtx lab = gen_label_rtx (); 3476 prepare_scc_operands (EQ); 3477 emit_jump_insn (gen_branch_true (lab)); 3478 prepare_scc_operands (GT); 3479 emit_label (lab); 3480 emit_insn (gen_movt (operands[0])); 3481 } 3482 else 3483 emit_insn (gen_movnegt (operands[0], prepare_scc_operands (LT))); 3484 DONE; 3485 } 3486 operands[1] = prepare_scc_operands (GE); 3487}") 3488 3489(define_expand "sgtu" 3490 [(set (match_operand:SI 0 "arith_reg_operand" "") 3491 (match_dup 1))] 3492 "" 3493 "operands[1] = prepare_scc_operands (GTU);") 3494 3495(define_expand "sltu" 3496 [(set (match_operand:SI 0 "arith_reg_operand" "") 3497 (match_dup 1))] 3498 "" 3499 "operands[1] = prepare_scc_operands (LTU);") 3500 3501(define_expand "sleu" 3502 [(set (match_operand:SI 0 "arith_reg_operand" "") 3503 (match_dup 1))] 3504 "" 3505 "operands[1] = prepare_scc_operands (LEU);") 3506 3507(define_expand "sgeu" 3508 [(set (match_operand:SI 0 "arith_reg_operand" "") 3509 (match_dup 1))] 3510 "" 3511 "operands[1] = prepare_scc_operands (GEU);") 3512 3513;; sne moves the complement of the T reg to DEST like this: 3514;; cmp/eq ... 3515;; mov #-1,temp 3516;; negc temp,dest 3517;; This is better than xoring compare result with 1 because it does 3518;; not require r0 and further, the -1 may be CSE-ed or lifted out of a 3519;; loop. 3520 3521(define_expand "sne" 3522 [(set (match_dup 2) (const_int -1)) 3523 (parallel [(set (match_operand:SI 0 "arith_reg_operand" "") 3524 (neg:SI (plus:SI (match_dup 1) 3525 (match_dup 2)))) 3526 (set (reg:SI 18) 3527 (ne:SI (ior:SI (match_dup 1) (match_dup 2)) 3528 (const_int 0)))])] 3529 "" 3530 " 3531{ 3532 operands[1] = prepare_scc_operands (EQ); 3533 operands[2] = gen_reg_rtx (SImode); 3534}") 3535 3536;; Use the same trick for FP sle / sge 3537(define_expand "movnegt" 3538 [(set (match_dup 2) (const_int -1)) 3539 (parallel [(set (match_operand 0 "" "") 3540 (neg:SI (plus:SI (match_dup 1) 3541 (match_dup 2)))) 3542 (set (reg:SI 18) 3543 (ne:SI (ior:SI (match_operand 1 "" "") (match_dup 2)) 3544 (const_int 0)))])] 3545 "" 3546 "operands[2] = gen_reg_rtx (SImode);") 3547 3548;; Recognize mov #-1/negc/neg sequence, and change it to movt/add #-1. 3549;; This prevents a regression that occurred when we switched from xor to 3550;; mov/neg for sne. 3551 3552(define_split 3553 [(set (match_operand:SI 0 "arith_reg_operand" "") 3554 (plus:SI (reg:SI 18) 3555 (const_int -1)))] 3556 "" 3557 [(set (match_dup 0) (eq:SI (reg:SI 18) (const_int 1))) 3558 (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))] 3559 "") 3560 3561;; ------------------------------------------------------------------------- 3562;; Instructions to cope with inline literal tables 3563;; ------------------------------------------------------------------------- 3564 3565; 2 byte integer in line 3566 3567(define_insn "consttable_2" 3568 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")] 2)] 3569 "" 3570 "* 3571{ 3572 assemble_integer (operands[0], 2, 1); 3573 return \"\"; 3574}" 3575 [(set_attr "length" "2") 3576 (set_attr "in_delay_slot" "no")]) 3577 3578; 4 byte integer in line 3579 3580(define_insn "consttable_4" 3581 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")] 4)] 3582 "" 3583 "* 3584{ 3585 assemble_integer (operands[0], 4, 1); 3586 return \"\"; 3587}" 3588 [(set_attr "length" "4") 3589 (set_attr "in_delay_slot" "no")]) 3590 3591; 8 byte integer in line 3592 3593(define_insn "consttable_8" 3594 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")] 6)] 3595 "" 3596 "* 3597{ 3598 assemble_integer (operands[0], 8, 1); 3599 return \"\"; 3600}" 3601 [(set_attr "length" "8") 3602 (set_attr "in_delay_slot" "no")]) 3603 3604; 4 byte floating point 3605 3606(define_insn "consttable_sf" 3607 [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")] 4)] 3608 "" 3609 "* 3610{ 3611 union real_extract u; 3612 bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u); 3613 assemble_real (u.d, SFmode); 3614 return \"\"; 3615}" 3616 [(set_attr "length" "4") 3617 (set_attr "in_delay_slot" "no")]) 3618 3619; 8 byte floating point 3620 3621(define_insn "consttable_df" 3622 [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")] 6)] 3623 "" 3624 "* 3625{ 3626 union real_extract u; 3627 bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u); 3628 assemble_real (u.d, DFmode); 3629 return \"\"; 3630}" 3631 [(set_attr "length" "8") 3632 (set_attr "in_delay_slot" "no")]) 3633 3634;; Alignment is needed for some constant tables; it may also be added for 3635;; Instructions at the start of loops, or after unconditional branches. 3636;; ??? We would get more accurate lengths if we did instruction 3637;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used 3638;; here is too conservative. 3639 3640; align to a two byte boundary 3641 3642(define_expand "align_2" 3643 [(unspec_volatile [(const_int 1)] 1)] 3644 "" 3645 "") 3646 3647; align to a four byte boundary 3648;; align_4 and align_log are instructions for the starts of loops, or 3649;; after unconditional branches, which may take up extra room. 3650 3651(define_expand "align_4" 3652 [(unspec_volatile [(const_int 2)] 1)] 3653 "" 3654 "") 3655 3656; align to a cache line boundary 3657 3658(define_insn "align_log" 3659 [(unspec_volatile [(match_operand 0 "const_int_operand" "")] 1)] 3660 "" 3661 "" 3662 [(set_attr "length" "0") 3663 (set_attr "in_delay_slot" "no")]) 3664 3665; emitted at the end of the literal table, used to emit the 3666; 32bit branch labels if needed. 3667 3668(define_insn "consttable_end" 3669 [(unspec_volatile [(const_int 0)] 11)] 3670 "" 3671 "* return output_jump_label_table ();" 3672 [(set_attr "in_delay_slot" "no")]) 3673 3674;; ------------------------------------------------------------------------- 3675;; Misc 3676;; ------------------------------------------------------------------------- 3677 3678;; String/block move insn. 3679 3680(define_expand "movstrsi" 3681 [(parallel [(set (mem:BLK (match_operand:BLK 0 "" "")) 3682 (mem:BLK (match_operand:BLK 1 "" ""))) 3683 (use (match_operand:SI 2 "nonmemory_operand" "")) 3684 (use (match_operand:SI 3 "immediate_operand" "")) 3685 (clobber (reg:SI 17)) 3686 (clobber (reg:SI 4)) 3687 (clobber (reg:SI 5)) 3688 (clobber (reg:SI 0))])] 3689 "" 3690 " 3691{ 3692 if(expand_block_move (operands)) 3693 DONE; 3694 else FAIL; 3695}") 3696 3697(define_insn "block_move_real" 3698 [(parallel [(set (mem:BLK (reg:SI 4)) 3699 (mem:BLK (reg:SI 5))) 3700 (use (match_operand:SI 0 "arith_reg_operand" "r")) 3701 (clobber (reg:SI 17)) 3702 (clobber (reg:SI 0))])] 3703 "! TARGET_HARD_SH4" 3704 "jsr @%0%#" 3705 [(set_attr "type" "sfunc") 3706 (set_attr "needs_delay_slot" "yes")]) 3707 3708(define_insn "block_lump_real" 3709 [(parallel [(set (mem:BLK (reg:SI 4)) 3710 (mem:BLK (reg:SI 5))) 3711 (use (match_operand:SI 0 "arith_reg_operand" "r")) 3712 (use (reg:SI 6)) 3713 (clobber (reg:SI 17)) 3714 (clobber (reg:SI 4)) 3715 (clobber (reg:SI 5)) 3716 (clobber (reg:SI 6)) 3717 (clobber (reg:SI 0))])] 3718 "! TARGET_HARD_SH4" 3719 "jsr @%0%#" 3720 [(set_attr "type" "sfunc") 3721 (set_attr "needs_delay_slot" "yes")]) 3722 3723(define_insn "block_move_real_i4" 3724 [(parallel [(set (mem:BLK (reg:SI 4)) 3725 (mem:BLK (reg:SI 5))) 3726 (use (match_operand:SI 0 "arith_reg_operand" "r")) 3727 (clobber (reg:SI 17)) 3728 (clobber (reg:SI 0)) 3729 (clobber (reg:SI 1)) 3730 (clobber (reg:SI 2))])] 3731 "TARGET_HARD_SH4" 3732 "jsr @%0%#" 3733 [(set_attr "type" "sfunc") 3734 (set_attr "needs_delay_slot" "yes")]) 3735 3736(define_insn "block_lump_real_i4" 3737 [(parallel [(set (mem:BLK (reg:SI 4)) 3738 (mem:BLK (reg:SI 5))) 3739 (use (match_operand:SI 0 "arith_reg_operand" "r")) 3740 (use (reg:SI 6)) 3741 (clobber (reg:SI 17)) 3742 (clobber (reg:SI 4)) 3743 (clobber (reg:SI 5)) 3744 (clobber (reg:SI 6)) 3745 (clobber (reg:SI 0)) 3746 (clobber (reg:SI 1)) 3747 (clobber (reg:SI 2)) 3748 (clobber (reg:SI 3))])] 3749 "TARGET_HARD_SH4" 3750 "jsr @%0%#" 3751 [(set_attr "type" "sfunc") 3752 (set_attr "needs_delay_slot" "yes")]) 3753 3754;; ------------------------------------------------------------------------- 3755;; Floating point instructions. 3756;; ------------------------------------------------------------------------- 3757 3758;; ??? All patterns should have a type attribute. 3759 3760(define_expand "fpu_switch0" 3761 [(set (match_operand:SI 0 "" "") (symbol_ref "__fpscr_values")) 3762 (set (match_dup 2) (match_dup 1))] 3763 "" 3764 " 3765{ 3766 operands[1] = gen_rtx (MEM, PSImode, operands[0]); 3767 RTX_UNCHANGING_P (operands[1]) = 1; 3768 operands[2] = get_fpscr_rtx (); 3769}") 3770 3771(define_expand "fpu_switch1" 3772 [(set (match_operand:SI 0 "" "") (symbol_ref "__fpscr_values")) 3773 (set (match_dup 1) (plus:SI (match_dup 0) (const_int 4))) 3774 (set (match_dup 3) (match_dup 2))] 3775 "" 3776 " 3777{ 3778 operands[1] = gen_reg_rtx (SImode); 3779 operands[2] = gen_rtx (MEM, PSImode, operands[1]); 3780 RTX_UNCHANGING_P (operands[2]) = 1; 3781 operands[3] = get_fpscr_rtx (); 3782}") 3783 3784(define_expand "movpsi" 3785 [(set (match_operand:PSI 0 "register_operand" "") 3786 (match_operand:PSI 1 "general_movsrc_operand" ""))] 3787 "" 3788 "") 3789 3790;; The c / m alternative is a fake to guide reload to load directly into 3791;; fpscr, since reload doesn't know how to use post-increment. 3792;; GO_IF_LEGITIMATE_ADDRESS guards about bogus addresses before reload, 3793;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's 3794;; predicate after reload. 3795;; The gp_fpul type for r/!c might look a bit odd, but it actually schedules 3796;; like a gpr <-> fpul move. 3797(define_insn "fpu_switch" 3798 [(set (match_operand:PSI 0 "register_operand" "c,c,r,c,c,r,m,r") 3799 (match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c"))] 3800 "! reload_completed 3801 || true_regnum (operands[0]) != FPSCR_REG || GET_CODE (operands[1]) != MEM 3802 || GET_CODE (XEXP (operands[1], 0)) != PLUS" 3803 "@ 3804 ! precision stays the same 3805 lds.l %1,fpscr 3806 mov.l %1,%0 3807 # 3808 lds %1,fpscr 3809 mov %1,%0 3810 mov.l %1,%0 3811 sts fpscr,%0" 3812 [(set_attr "length" "0,2,2,4,2,2,2,2") 3813 (set_attr "type" "dfp_conv,dfp_conv,load,dfp_conv,dfp_conv,move,store,gp_fpul")]) 3814 3815(define_split 3816 [(set (reg:PSI 48) (mem:PSI (match_operand:SI 0 "register_operand" "r")))] 3817 "find_regno_note (insn, REG_DEAD, true_regnum (operands[0]))" 3818 [(set (match_dup 0) (match_dup 0))] 3819 " 3820{ 3821 rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (), 3822 gen_rtx (MEM, PSImode, 3823 gen_rtx (POST_INC, Pmode, 3824 operands[0])))); 3825 REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, operands[0], NULL_RTX); 3826}") 3827 3828(define_split 3829 [(set (reg:PSI 48) (mem:PSI (match_operand:SI 0 "register_operand" "r")))] 3830 "" 3831 [(set (match_dup 0) (plus:SI (match_dup 0) (const_int -4)))] 3832 " 3833{ 3834 rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (), 3835 gen_rtx (MEM, PSImode, 3836 gen_rtx (POST_INC, Pmode, 3837 operands[0])))); 3838 REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, operands[0], NULL_RTX); 3839}") 3840 3841;; ??? This uses the fp unit, but has no type indicating that. 3842;; If we did that, this would either give a bogus latency or introduce 3843;; a bogus FIFO constraint. 3844;; Since this insn is currently only used for prologues/epilogues, 3845;; it is probably best to claim no function unit, which matches the 3846;; current setting. 3847(define_insn "toggle_sz" 3848 [(set (reg:PSI 48) (xor:PSI (reg:PSI 48) (const_int 1048576)))] 3849 "TARGET_SH4" 3850 "fschg") 3851 3852(define_expand "addsf3" 3853 [(match_operand:SF 0 "arith_reg_operand" "") 3854 (match_operand:SF 1 "arith_reg_operand" "") 3855 (match_operand:SF 2 "arith_reg_operand" "")] 3856 "TARGET_SH3E" 3857 "{ expand_sf_binop (&gen_addsf3_i, operands); DONE; }") 3858 3859(define_insn "addsf3_i" 3860 [(set (match_operand:SF 0 "arith_reg_operand" "=f") 3861 (plus:SF (match_operand:SF 1 "arith_reg_operand" "%0") 3862 (match_operand:SF 2 "arith_reg_operand" "f"))) 3863 (use (match_operand:PSI 3 "fpscr_operand" "c"))] 3864 "TARGET_SH3E" 3865 "fadd %2,%0" 3866 [(set_attr "type" "fp")]) 3867 3868(define_expand "subsf3" 3869 [(match_operand:SF 0 "fp_arith_reg_operand" "") 3870 (match_operand:SF 1 "fp_arith_reg_operand" "") 3871 (match_operand:SF 2 "fp_arith_reg_operand" "")] 3872 "TARGET_SH3E" 3873 "{ expand_sf_binop (&gen_subsf3_i, operands); DONE; }") 3874 3875(define_insn "subsf3_i" 3876 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 3877 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0") 3878 (match_operand:SF 2 "fp_arith_reg_operand" "f"))) 3879 (use (match_operand:PSI 3 "fpscr_operand" "c"))] 3880 "TARGET_SH3E" 3881 "fsub %2,%0" 3882 [(set_attr "type" "fp")]) 3883 3884;; Unfortunately, the combiner is unable to cope with the USE of the FPSCR 3885;; register in feeding fp instructions. Thus, we cannot generate fmac for 3886;; mixed-precision SH4 targets. To allow it to be still generated for the 3887;; SH3E, we use a separate insn for SH3E mulsf3. 3888 3889(define_expand "mulsf3" 3890 [(match_operand:SF 0 "arith_reg_operand" "") 3891 (match_operand:SF 1 "arith_reg_operand" "") 3892 (match_operand:SF 2 "arith_reg_operand" "")] 3893 "TARGET_SH3E" 3894 " 3895{ 3896 if (TARGET_SH4) 3897 expand_sf_binop (&gen_mulsf3_i4, operands); 3898 else 3899 emit_insn (gen_mulsf3_ie (operands[0], operands[1], operands[2])); 3900 DONE; 3901}") 3902 3903(define_insn "mulsf3_i4" 3904 [(set (match_operand:SF 0 "arith_reg_operand" "=f") 3905 (mult:SF (match_operand:SF 1 "arith_reg_operand" "%0") 3906 (match_operand:SF 2 "arith_reg_operand" "f"))) 3907 (use (match_operand:PSI 3 "fpscr_operand" "c"))] 3908 "TARGET_SH3E" 3909 "fmul %2,%0" 3910 [(set_attr "type" "fp")]) 3911 3912(define_insn "mulsf3_ie" 3913 [(set (match_operand:SF 0 "arith_reg_operand" "=f") 3914 (mult:SF (match_operand:SF 1 "arith_reg_operand" "%0") 3915 (match_operand:SF 2 "arith_reg_operand" "f")))] 3916 "TARGET_SH3E && ! TARGET_SH4" 3917 "fmul %2,%0" 3918 [(set_attr "type" "fp")]) 3919 3920(define_insn "*macsf3" 3921 [(set (match_operand:SF 0 "arith_reg_operand" "=f") 3922 (plus:SF (mult:SF (match_operand:SF 1 "arith_reg_operand" "%w") 3923 (match_operand:SF 2 "arith_reg_operand" "f")) 3924 (match_operand:SF 3 "arith_reg_operand" "0"))) 3925 (use (match_operand:PSI 4 "fpscr_operand" "c"))] 3926 "TARGET_SH3E && ! TARGET_SH4" 3927 "fmac fr0,%2,%0" 3928 [(set_attr "type" "fp")]) 3929 3930(define_expand "divsf3" 3931 [(match_operand:SF 0 "arith_reg_operand" "") 3932 (match_operand:SF 1 "arith_reg_operand" "") 3933 (match_operand:SF 2 "arith_reg_operand" "")] 3934 "TARGET_SH3E" 3935 "{ expand_sf_binop (&gen_divsf3_i, operands); DONE; }") 3936 3937(define_insn "divsf3_i" 3938 [(set (match_operand:SF 0 "arith_reg_operand" "=f") 3939 (div:SF (match_operand:SF 1 "arith_reg_operand" "0") 3940 (match_operand:SF 2 "arith_reg_operand" "f"))) 3941 (use (match_operand:PSI 3 "fpscr_operand" "c"))] 3942 "TARGET_SH3E" 3943 "fdiv %2,%0" 3944 [(set_attr "type" "fdiv")]) 3945 3946(define_expand "floatsisf2" 3947 [(set (reg:SI 22) 3948 (match_operand:SI 1 "arith_reg_operand" "")) 3949 (parallel [(set (match_operand:SF 0 "arith_reg_operand" "") 3950 (float:SF (reg:SI 22))) 3951 (use (match_dup 2))])] 3952 "TARGET_SH3E" 3953 " 3954{ 3955 if (TARGET_SH4) 3956 { 3957 emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, 22), 3958 operands[1])); 3959 emit_sf_insn (gen_floatsisf2_i4 (operands[0], get_fpscr_rtx ())); 3960 DONE; 3961 } 3962 operands[2] = get_fpscr_rtx (); 3963}") 3964 3965(define_insn "floatsisf2_i4" 3966 [(set (match_operand:SF 0 "arith_reg_operand" "=f") 3967 (float:SF (reg:SI 22))) 3968 (use (match_operand:PSI 1 "fpscr_operand" "c"))] 3969 "TARGET_SH3E" 3970 "float fpul,%0" 3971 [(set_attr "type" "fp")]) 3972 3973(define_insn "*floatsisf2_ie" 3974 [(set (match_operand:SF 0 "arith_reg_operand" "=f") 3975 (float:SF (reg:SI 22)))] 3976 "TARGET_SH3E && ! TARGET_SH4" 3977 "float fpul,%0" 3978 [(set_attr "type" "fp")]) 3979 3980(define_expand "fix_truncsfsi2" 3981 [(set (reg:SI 22) 3982 (fix:SI (match_operand:SF 1 "arith_reg_operand" "f"))) 3983 (set (match_operand:SI 0 "arith_reg_operand" "=r") 3984 (reg:SI 22))] 3985 "TARGET_SH3E" 3986 " 3987{ 3988 if (TARGET_SH4) 3989 { 3990 emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[1], get_fpscr_rtx ())); 3991 emit_insn (gen_rtx (SET, VOIDmode, operands[0], 3992 gen_rtx (REG, SImode, 22))); 3993 DONE; 3994 } 3995}") 3996 3997(define_insn "fix_truncsfsi2_i4" 3998 [(set (reg:SI 22) 3999 (fix:SI (match_operand:SF 0 "arith_reg_operand" "f"))) 4000 (use (match_operand:PSI 1 "fpscr_operand" "c"))] 4001 "TARGET_SH4" 4002 "ftrc %0,fpul" 4003 [(set_attr "type" "fp")]) 4004 4005(define_insn "fix_truncsfsi2_i4_2" 4006 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 4007 (fix:SI (match_operand:SF 1 "arith_reg_operand" "f"))) 4008 (use (reg:SI 48)) 4009 (clobber (reg:SI 22))] 4010 "TARGET_SH4" 4011 "#" 4012 [(set_attr "length" "4")]) 4013 4014(define_split 4015 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 4016 (fix:SI (match_operand:SF 1 "arith_reg_operand" "f"))) 4017 (use (match_operand:PSI 2 "fpscr_operand" "c")) 4018 (clobber (reg:SI 22))] 4019 "TARGET_SH4" 4020 [(parallel [(set (reg:SI 22) (fix:SI (match_dup 1))) 4021 (use (match_dup 2))]) 4022 (set (match_dup 0) (reg:SI 22))]) 4023 4024(define_insn "*fixsfsi" 4025 [(set (reg:SI 22) 4026 (fix:SI (match_operand:SF 0 "arith_reg_operand" "f")))] 4027 "TARGET_SH3E && ! TARGET_SH4" 4028 "ftrc %0,fpul" 4029 [(set_attr "type" "fp")]) 4030 4031(define_insn "cmpgtsf_t" 4032 [(set (reg:SI 18) (gt:SI (match_operand:SF 0 "arith_reg_operand" "f") 4033 (match_operand:SF 1 "arith_reg_operand" "f")))] 4034 "TARGET_SH3E && ! TARGET_SH4" 4035 "fcmp/gt %1,%0" 4036 [(set_attr "type" "fp")]) 4037 4038(define_insn "cmpeqsf_t" 4039 [(set (reg:SI 18) (eq:SI (match_operand:SF 0 "arith_reg_operand" "f") 4040 (match_operand:SF 1 "arith_reg_operand" "f")))] 4041 "TARGET_SH3E && ! TARGET_SH4" 4042 "fcmp/eq %1,%0" 4043 [(set_attr "type" "fp")]) 4044 4045(define_insn "ieee_ccmpeqsf_t" 4046 [(set (reg:SI 18) (ior:SI (reg:SI 18) 4047 (eq:SI (match_operand:SF 0 "arith_reg_operand" "f") 4048 (match_operand:SF 1 "arith_reg_operand" "f"))))] 4049 "TARGET_SH3E && TARGET_IEEE && ! TARGET_SH4" 4050 "* return output_ieee_ccmpeq (insn, operands);" 4051 [(set_attr "length" "4")]) 4052 4053 4054(define_insn "cmpgtsf_t_i4" 4055 [(set (reg:SI 18) (gt:SI (match_operand:SF 0 "arith_reg_operand" "f") 4056 (match_operand:SF 1 "arith_reg_operand" "f"))) 4057 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 4058 "TARGET_SH4" 4059 "fcmp/gt %1,%0" 4060 [(set_attr "type" "fp")]) 4061 4062(define_insn "cmpeqsf_t_i4" 4063 [(set (reg:SI 18) (eq:SI (match_operand:SF 0 "arith_reg_operand" "f") 4064 (match_operand:SF 1 "arith_reg_operand" "f"))) 4065 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 4066 "TARGET_SH4" 4067 "fcmp/eq %1,%0" 4068 [(set_attr "type" "fp")]) 4069 4070(define_insn "*ieee_ccmpeqsf_t_4" 4071 [(set (reg:SI 18) (ior:SI (reg:SI 18) 4072 (eq:SI (match_operand:SF 0 "arith_reg_operand" "f") 4073 (match_operand:SF 1 "arith_reg_operand" "f")))) 4074 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 4075 "TARGET_IEEE && TARGET_SH4" 4076 "* return output_ieee_ccmpeq (insn, operands);" 4077 [(set_attr "length" "4")]) 4078 4079(define_expand "cmpsf" 4080 [(set (reg:SI 18) (compare (match_operand:SF 0 "arith_operand" "") 4081 (match_operand:SF 1 "arith_operand" "")))] 4082 "TARGET_SH3E" 4083 " 4084{ 4085 sh_compare_op0 = operands[0]; 4086 sh_compare_op1 = operands[1]; 4087 DONE; 4088}") 4089 4090(define_expand "negsf2" 4091 [(match_operand:SF 0 "arith_reg_operand" "") 4092 (match_operand:SF 1 "arith_reg_operand" "")] 4093 "TARGET_SH3E" 4094 "{ expand_sf_unop (&gen_negsf2_i, operands); DONE; }") 4095 4096(define_insn "negsf2_i" 4097 [(set (match_operand:SF 0 "arith_reg_operand" "=f") 4098 (neg:SF (match_operand:SF 1 "arith_reg_operand" "0"))) 4099 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 4100 "TARGET_SH3E" 4101 "fneg %0" 4102 [(set_attr "type" "fmove")]) 4103 4104(define_expand "sqrtsf2" 4105 [(match_operand:SF 0 "arith_reg_operand" "") 4106 (match_operand:SF 1 "arith_reg_operand" "")] 4107 "TARGET_SH3E" 4108 "{ expand_sf_unop (&gen_sqrtsf2_i, operands); DONE; }") 4109 4110(define_insn "sqrtsf2_i" 4111 [(set (match_operand:SF 0 "arith_reg_operand" "=f") 4112 (sqrt:SF (match_operand:SF 1 "arith_reg_operand" "0"))) 4113 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 4114 "TARGET_SH3E" 4115 "fsqrt %0" 4116 [(set_attr "type" "fdiv")]) 4117 4118(define_expand "abssf2" 4119 [(match_operand:SF 0 "arith_reg_operand" "") 4120 (match_operand:SF 1 "arith_reg_operand" "")] 4121 "TARGET_SH3E" 4122 "{ expand_sf_unop (&gen_abssf2_i, operands); DONE; }") 4123 4124(define_insn "abssf2_i" 4125 [(set (match_operand:SF 0 "arith_reg_operand" "=f") 4126 (abs:SF (match_operand:SF 1 "arith_reg_operand" "0"))) 4127 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 4128 "TARGET_SH3E" 4129 "fabs %0" 4130 [(set_attr "type" "fmove")]) 4131 4132(define_expand "adddf3" 4133 [(match_operand:DF 0 "arith_reg_operand" "") 4134 (match_operand:DF 1 "arith_reg_operand" "") 4135 (match_operand:DF 2 "arith_reg_operand" "")] 4136 "TARGET_SH4" 4137 "{ expand_df_binop (&gen_adddf3_i, operands); DONE; }") 4138 4139(define_insn "adddf3_i" 4140 [(set (match_operand:DF 0 "arith_reg_operand" "=f") 4141 (plus:DF (match_operand:DF 1 "arith_reg_operand" "%0") 4142 (match_operand:DF 2 "arith_reg_operand" "f"))) 4143 (use (match_operand:PSI 3 "fpscr_operand" "c"))] 4144 "TARGET_SH4" 4145 "fadd %2,%0" 4146 [(set_attr "type" "dfp_arith")]) 4147 4148(define_expand "subdf3" 4149 [(match_operand:DF 0 "arith_reg_operand" "") 4150 (match_operand:DF 1 "arith_reg_operand" "") 4151 (match_operand:DF 2 "arith_reg_operand" "")] 4152 "TARGET_SH4" 4153 "{ expand_df_binop (&gen_subdf3_i, operands); DONE; }") 4154 4155(define_insn "subdf3_i" 4156 [(set (match_operand:DF 0 "arith_reg_operand" "=f") 4157 (minus:DF (match_operand:DF 1 "arith_reg_operand" "0") 4158 (match_operand:DF 2 "arith_reg_operand" "f"))) 4159 (use (match_operand:PSI 3 "fpscr_operand" "c"))] 4160 "TARGET_SH4" 4161 "fsub %2,%0" 4162 [(set_attr "type" "dfp_arith")]) 4163 4164(define_expand "muldf3" 4165 [(match_operand:DF 0 "arith_reg_operand" "") 4166 (match_operand:DF 1 "arith_reg_operand" "") 4167 (match_operand:DF 2 "arith_reg_operand" "")] 4168 "TARGET_SH4" 4169 "{ expand_df_binop (&gen_muldf3_i, operands); DONE; }") 4170 4171(define_insn "muldf3_i" 4172 [(set (match_operand:DF 0 "arith_reg_operand" "=f") 4173 (mult:DF (match_operand:DF 1 "arith_reg_operand" "%0") 4174 (match_operand:DF 2 "arith_reg_operand" "f"))) 4175 (use (match_operand:PSI 3 "fpscr_operand" "c"))] 4176 "TARGET_SH4" 4177 "fmul %2,%0" 4178 [(set_attr "type" "dfp_arith")]) 4179 4180(define_expand "divdf3" 4181 [(match_operand:DF 0 "arith_reg_operand" "") 4182 (match_operand:DF 1 "arith_reg_operand" "") 4183 (match_operand:DF 2 "arith_reg_operand" "")] 4184 "TARGET_SH4" 4185 "{ expand_df_binop (&gen_divdf3_i, operands); DONE; }") 4186 4187(define_insn "divdf3_i" 4188 [(set (match_operand:DF 0 "arith_reg_operand" "=f") 4189 (div:DF (match_operand:DF 1 "arith_reg_operand" "0") 4190 (match_operand:DF 2 "arith_reg_operand" "f"))) 4191 (use (match_operand:PSI 3 "fpscr_operand" "c"))] 4192 "TARGET_SH4" 4193 "fdiv %2,%0" 4194 [(set_attr "type" "dfdiv")]) 4195 4196(define_expand "floatsidf2" 4197 [(match_operand:DF 0 "arith_reg_operand" "") 4198 (match_operand:SI 1 "arith_reg_operand" "")] 4199 "TARGET_SH4" 4200 " 4201{ 4202 emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, 22), operands[1])); 4203 emit_df_insn (gen_floatsidf2_i (operands[0], get_fpscr_rtx ())); 4204 DONE; 4205}") 4206 4207(define_insn "floatsidf2_i" 4208 [(set (match_operand:DF 0 "arith_reg_operand" "=f") 4209 (float:DF (reg:SI 22))) 4210 (use (match_operand:PSI 1 "fpscr_operand" "c"))] 4211 "TARGET_SH4" 4212 "float fpul,%0" 4213 [(set_attr "type" "dfp_conv")]) 4214 4215(define_expand "fix_truncdfsi2" 4216 [(match_operand:SI 0 "arith_reg_operand" "=r") 4217 (match_operand:DF 1 "arith_reg_operand" "f")] 4218 "TARGET_SH4" 4219 " 4220{ 4221 emit_df_insn (gen_fix_truncdfsi2_i (operands[1], get_fpscr_rtx ())); 4222 emit_insn (gen_rtx (SET, VOIDmode, operands[0], gen_rtx (REG, SImode, 22))); 4223 DONE; 4224}") 4225 4226(define_insn "fix_truncdfsi2_i" 4227 [(set (reg:SI 22) 4228 (fix:SI (match_operand:DF 0 "arith_reg_operand" "f"))) 4229 (use (match_operand:PSI 1 "fpscr_operand" "c"))] 4230 "TARGET_SH4" 4231 "ftrc %0,fpul" 4232 [(set_attr "type" "dfp_conv")]) 4233 4234(define_insn "fix_truncdfsi2_i4" 4235 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 4236 (fix:SI (match_operand:DF 1 "arith_reg_operand" "f"))) 4237 (use (match_operand:PSI 2 "fpscr_operand" "c")) 4238 (clobber (reg:SI 22))] 4239 "TARGET_SH4" 4240 "#" 4241 [(set_attr "length" "4")]) 4242 4243(define_split 4244 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 4245 (fix:SI (match_operand:DF 1 "arith_reg_operand" "f"))) 4246 (use (match_operand:PSI 2 "fpscr_operand" "c")) 4247 (clobber (reg:SI 22))] 4248 "TARGET_SH4" 4249 [(parallel [(set (reg:SI 22) (fix:SI (match_dup 1))) 4250 (use (match_dup 2))]) 4251 (set (match_dup 0) (reg:SI 22))]) 4252 4253(define_insn "cmpgtdf_t" 4254 [(set (reg:SI 18) (gt:SI (match_operand:DF 0 "arith_reg_operand" "f") 4255 (match_operand:DF 1 "arith_reg_operand" "f"))) 4256 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 4257 "TARGET_SH4" 4258 "fcmp/gt %1,%0" 4259 [(set_attr "type" "dfp_cmp")]) 4260 4261(define_insn "cmpeqdf_t" 4262 [(set (reg:SI 18) (eq:SI (match_operand:DF 0 "arith_reg_operand" "f") 4263 (match_operand:DF 1 "arith_reg_operand" "f"))) 4264 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 4265 "TARGET_SH4" 4266 "fcmp/eq %1,%0" 4267 [(set_attr "type" "dfp_cmp")]) 4268 4269(define_insn "*ieee_ccmpeqdf_t" 4270 [(set (reg:SI 18) (ior:SI (reg:SI 18) 4271 (eq:SI (match_operand:DF 0 "arith_reg_operand" "f") 4272 (match_operand:DF 1 "arith_reg_operand" "f")))) 4273 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 4274 "TARGET_IEEE && TARGET_SH4" 4275 "* return output_ieee_ccmpeq (insn, operands);" 4276 [(set_attr "length" "4")]) 4277 4278(define_expand "cmpdf" 4279 [(set (reg:SI 18) (compare (match_operand:DF 0 "arith_operand" "") 4280 (match_operand:DF 1 "arith_operand" "")))] 4281 "TARGET_SH4" 4282 " 4283{ 4284 sh_compare_op0 = operands[0]; 4285 sh_compare_op1 = operands[1]; 4286 DONE; 4287}") 4288 4289(define_expand "negdf2" 4290 [(match_operand:DF 0 "arith_reg_operand" "") 4291 (match_operand:DF 1 "arith_reg_operand" "")] 4292 "TARGET_SH4" 4293 "{ expand_df_unop (&gen_negdf2_i, operands); DONE; }") 4294 4295(define_insn "negdf2_i" 4296 [(set (match_operand:DF 0 "arith_reg_operand" "=f") 4297 (neg:DF (match_operand:DF 1 "arith_reg_operand" "0"))) 4298 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 4299 "TARGET_SH4" 4300 "fneg %0" 4301 [(set_attr "type" "fmove")]) 4302 4303(define_expand "sqrtdf2" 4304 [(match_operand:DF 0 "arith_reg_operand" "") 4305 (match_operand:DF 1 "arith_reg_operand" "")] 4306 "TARGET_SH4" 4307 "{ expand_df_unop (&gen_sqrtdf2_i, operands); DONE; }") 4308 4309(define_insn "sqrtdf2_i" 4310 [(set (match_operand:DF 0 "arith_reg_operand" "=f") 4311 (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "0"))) 4312 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 4313 "TARGET_SH4" 4314 "fsqrt %0" 4315 [(set_attr "type" "dfdiv")]) 4316 4317(define_expand "absdf2" 4318 [(match_operand:DF 0 "arith_reg_operand" "") 4319 (match_operand:DF 1 "arith_reg_operand" "")] 4320 "TARGET_SH4" 4321 "{ expand_df_unop (&gen_absdf2_i, operands); DONE; }") 4322 4323(define_insn "absdf2_i" 4324 [(set (match_operand:DF 0 "arith_reg_operand" "=f") 4325 (abs:DF (match_operand:DF 1 "arith_reg_operand" "0"))) 4326 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 4327 "TARGET_SH4" 4328 "fabs %0" 4329 [(set_attr "type" "fmove")]) 4330 4331(define_expand "extendsfdf2" 4332 [(match_operand:DF 0 "arith_reg_operand" "") 4333 (match_operand:SF 1 "arith_reg_operand" "")] 4334 "TARGET_SH4" 4335 " 4336{ 4337 emit_sf_insn (gen_movsf_ie (gen_rtx (REG, SFmode, 22), operands[1], 4338 get_fpscr_rtx ())); 4339 emit_df_insn (gen_extendsfdf2_i4 (operands[0], get_fpscr_rtx ())); 4340 DONE; 4341}") 4342 4343(define_insn "extendsfdf2_i4" 4344 [(set (match_operand:DF 0 "arith_reg_operand" "=f") 4345 (float_extend:DF (reg:SF 22))) 4346 (use (match_operand:PSI 1 "fpscr_operand" "c"))] 4347 "TARGET_SH4" 4348 "fcnvsd fpul,%0" 4349 [(set_attr "type" "fp")]) 4350 4351(define_expand "truncdfsf2" 4352 [(match_operand:SF 0 "arith_reg_operand" "") 4353 (match_operand:DF 1 "arith_reg_operand" "")] 4354 "TARGET_SH4" 4355 " 4356{ 4357 emit_df_insn (gen_truncdfsf2_i4 (operands[1], get_fpscr_rtx ())); 4358 emit_sf_insn (gen_movsf_ie (operands[0], gen_rtx (REG, SFmode, 22), 4359 get_fpscr_rtx ())); 4360 DONE; 4361}") 4362 4363(define_insn "truncdfsf2_i4" 4364 [(set (reg:SF 22) 4365 (float_truncate:SF (match_operand:DF 0 "arith_reg_operand" "f"))) 4366 (use (match_operand:PSI 1 "fpscr_operand" "c"))] 4367 "TARGET_SH4" 4368 "fcnvds %0,fpul" 4369 [(set_attr "type" "fp")]) 4370 4371;; Bit field extract patterns. These give better code for packed bitfields, 4372;; because they allow auto-increment addresses to be generated. 4373 4374(define_expand "insv" 4375 [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "") 4376 (match_operand:SI 1 "immediate_operand" "") 4377 (match_operand:SI 2 "immediate_operand" "")) 4378 (match_operand:SI 3 "general_operand" ""))] 4379 "! TARGET_LITTLE_ENDIAN" 4380 " 4381{ 4382 rtx addr_target, orig_address, shift_reg; 4383 HOST_WIDE_INT size; 4384 4385 /* ??? expmed doesn't care for non-register predicates. */ 4386 if (! memory_operand (operands[0], VOIDmode) 4387 || ! immediate_operand (operands[1], VOIDmode) 4388 || ! immediate_operand (operands[2], VOIDmode) 4389 || ! general_operand (operands[3], VOIDmode)) 4390 FAIL; 4391 /* If this isn't a 16 / 24 / 32 bit field, or if 4392 it doesn't start on a byte boundary, then fail. */ 4393 size = INTVAL (operands[1]); 4394 if (size < 16 || size > 32 || size % 8 != 0 4395 || (INTVAL (operands[2]) % 8) != 0) 4396 FAIL; 4397 4398 size /= 8; 4399 orig_address = XEXP (operands[0], 0); 4400 shift_reg = gen_reg_rtx (SImode); 4401 emit_insn (gen_movsi (shift_reg, operands[3])); 4402 addr_target = copy_addr_to_reg (plus_constant (orig_address, size - 1)); 4403 4404 operands[0] = change_address (operands[0], QImode, addr_target); 4405 emit_insn (gen_movqi (operands[0], gen_rtx (SUBREG, QImode, shift_reg, 0))); 4406 4407 while (size -= 1) 4408 { 4409 emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8))); 4410 emit_insn (gen_addsi3 (addr_target, addr_target, GEN_INT (-1))); 4411 emit_insn (gen_movqi (operands[0], 4412 gen_rtx (SUBREG, QImode, shift_reg, 0))); 4413 } 4414 4415 DONE; 4416}") 4417 4418;; ------------------------------------------------------------------------- 4419;; Peepholes 4420;; ------------------------------------------------------------------------- 4421 4422;; This matches cases where a stack pointer increment at the start of the 4423;; epilogue combines with a stack slot read loading the return value. 4424 4425(define_peephole 4426 [(set (match_operand:SI 0 "arith_reg_operand" "") 4427 (mem:SI (match_operand:SI 1 "arith_reg_operand" ""))) 4428 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))] 4429 "REGNO (operands[1]) != REGNO (operands[0])" 4430 "mov.l @%1+,%0") 4431 4432;; See the comment on the dt combiner pattern above. 4433 4434(define_peephole 4435 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 4436 (plus:SI (match_dup 0) 4437 (const_int -1))) 4438 (set (reg:SI 18) 4439 (eq:SI (match_dup 0) 4440 (const_int 0)))] 4441 "TARGET_SH2" 4442 "dt %0") 4443 4444;; These convert sequences such as `mov #k,r0; add r15,r0; mov.l @r0,rn' 4445;; to `mov #k,r0; mov.l @(r0,r15),rn'. These sequences are generated by 4446;; reload when the constant is too large for a reg+offset address. 4447 4448;; ??? We would get much better code if this was done in reload. This would 4449;; require modifying find_reloads_address to recognize that if the constant 4450;; is out-of-range for an immediate add, then we get better code by reloading 4451;; the constant into a register than by reloading the sum into a register, 4452;; since the former is one instruction shorter if the address does not need 4453;; to be offsettable. Unfortunately this does not work, because there is 4454;; only one register, r0, that can be used as an index register. This register 4455;; is also the function return value register. So, if we try to force reload 4456;; to use double-reg addresses, then we end up with some instructions that 4457;; need to use r0 twice. The only way to fix this is to change the calling 4458;; convention so that r0 is not used to return values. 4459 4460(define_peephole 4461 [(set (match_operand:SI 0 "register_operand" "=r") 4462 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) 4463 (set (mem:SI (match_dup 0)) 4464 (match_operand:SI 2 "general_movsrc_operand" ""))] 4465 "REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)" 4466 "mov.l %2,@(%0,%1)") 4467 4468(define_peephole 4469 [(set (match_operand:SI 0 "register_operand" "=r") 4470 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) 4471 (set (match_operand:SI 2 "general_movdst_operand" "") 4472 (mem:SI (match_dup 0)))] 4473 "REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)" 4474 "mov.l @(%0,%1),%2") 4475 4476(define_peephole 4477 [(set (match_operand:SI 0 "register_operand" "=r") 4478 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) 4479 (set (mem:HI (match_dup 0)) 4480 (match_operand:HI 2 "general_movsrc_operand" ""))] 4481 "REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)" 4482 "mov.w %2,@(%0,%1)") 4483 4484(define_peephole 4485 [(set (match_operand:SI 0 "register_operand" "=r") 4486 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) 4487 (set (match_operand:HI 2 "general_movdst_operand" "") 4488 (mem:HI (match_dup 0)))] 4489 "REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)" 4490 "mov.w @(%0,%1),%2") 4491 4492(define_peephole 4493 [(set (match_operand:SI 0 "register_operand" "=r") 4494 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) 4495 (set (mem:QI (match_dup 0)) 4496 (match_operand:QI 2 "general_movsrc_operand" ""))] 4497 "REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)" 4498 "mov.b %2,@(%0,%1)") 4499 4500(define_peephole 4501 [(set (match_operand:SI 0 "register_operand" "=r") 4502 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) 4503 (set (match_operand:QI 2 "general_movdst_operand" "") 4504 (mem:QI (match_dup 0)))] 4505 "REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)" 4506 "mov.b @(%0,%1),%2") 4507 4508(define_peephole 4509 [(set (match_operand:SI 0 "register_operand" "=r") 4510 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) 4511 (set (mem:SF (match_dup 0)) 4512 (match_operand:SF 2 "general_movsrc_operand" ""))] 4513 "REGNO (operands[0]) == 0 4514 && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16) 4515 || (GET_CODE (operands[2]) == SUBREG 4516 && REGNO (SUBREG_REG (operands[2])) < 16)) 4517 && reg_unused_after (operands[0], insn)" 4518 "mov.l %2,@(%0,%1)") 4519 4520(define_peephole 4521 [(set (match_operand:SI 0 "register_operand" "=r") 4522 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) 4523 (set (match_operand:SF 2 "general_movdst_operand" "") 4524 4525 (mem:SF (match_dup 0)))] 4526 "REGNO (operands[0]) == 0 4527 && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16) 4528 || (GET_CODE (operands[2]) == SUBREG 4529 && REGNO (SUBREG_REG (operands[2])) < 16)) 4530 && reg_unused_after (operands[0], insn)" 4531 "mov.l @(%0,%1),%2") 4532 4533(define_peephole 4534 [(set (match_operand:SI 0 "register_operand" "=r") 4535 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) 4536 (set (mem:SF (match_dup 0)) 4537 (match_operand:SF 2 "general_movsrc_operand" ""))] 4538 "REGNO (operands[0]) == 0 4539 && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) >= FIRST_FP_REG) 4540 || (GET_CODE (operands[2]) == SUBREG 4541 && REGNO (SUBREG_REG (operands[2])) >= FIRST_FP_REG)) 4542 && reg_unused_after (operands[0], insn)" 4543 "fmov{.s|} %2,@(%0,%1)") 4544 4545(define_peephole 4546 [(set (match_operand:SI 0 "register_operand" "=r") 4547 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) 4548 (set (match_operand:SF 2 "general_movdst_operand" "") 4549 4550 (mem:SF (match_dup 0)))] 4551 "REGNO (operands[0]) == 0 4552 && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) >= FIRST_FP_REG) 4553 || (GET_CODE (operands[2]) == SUBREG 4554 && REGNO (SUBREG_REG (operands[2])) >= FIRST_FP_REG)) 4555 && reg_unused_after (operands[0], insn)" 4556 "fmov{.s|} @(%0,%1),%2") 4557 4558;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF). */ 4559(define_insn "sp_switch_1" 4560 [(const_int 1)] 4561 "" 4562 "* 4563{ 4564 rtx xoperands[1]; 4565 4566 xoperands[0] = sp_switch; 4567 output_asm_insn (\"mov.l r0,@-r15\;mov.l %0,r0\", xoperands); 4568 output_asm_insn (\"mov.l @r0,r0\;mov.l r15,@-r0\", xoperands); 4569 return \"mov r0,r15\"; 4570}" 4571 [(set_attr "length" "10")]) 4572 4573;; Switch back to the original stack for interrupt functions with the 4574;; sp_switch attribute. */ 4575(define_insn "sp_switch_2" 4576 [(const_int 2)] 4577 "" 4578 "mov.l @r15+,r15\;mov.l @r15+,r0" 4579 [(set_attr "length" "4")]) 4580