sh.md revision 1.3
1;;- Machine description for Renesas / SuperH SH. 2;; Copyright (C) 1993-2013 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 GCC. 7 8;; GCC 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 3, or (at your option) 11;; any later version. 12 13;; GCC 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 GCC; see the file COPYING3. If not see 20;; <http://www.gnu.org/licenses/>. 21 22 23;; ??? Should prepend a * to all pattern names which are not used. 24;; This will make the compiler smaller, and rebuilds after changes faster. 25 26;; ??? Should be enhanced to include support for many more GNU superoptimizer 27;; sequences. Especially the sequences for arithmetic right shifts. 28 29;; ??? Should check all DImode patterns for consistency and usefulness. 30 31;; ??? The MAC.W and MAC.L instructions are not supported. There is no 32;; way to generate them. 33 34;; ??? The cmp/str instruction is not supported. Perhaps it can be used 35;; for a str* inline function. 36 37;; BSR is not generated by the compiler proper, but when relaxing, it 38;; generates .uses pseudo-ops that allow linker relaxation to create 39;; BSR. This is actually implemented in bfd/{coff,elf32}-sh.c 40 41;; Special constraints for SH machine description: 42;; 43;; t -- T 44;; x -- mac 45;; l -- pr 46;; z -- r0 47;; 48;; Special formats used for outputting SH instructions: 49;; 50;; %. -- print a .s if insn needs delay slot 51;; %@ -- print rte/rts if is/isn't an interrupt function 52;; %# -- output a nop if there is nothing to put in the delay slot 53;; %O -- print a constant without the # 54;; %R -- print the lsw reg of a double 55;; %S -- print the msw reg of a double 56;; %T -- print next word of a double REG or MEM 57;; 58;; Special predicates: 59;; 60;; arith_operand -- operand is valid source for arithmetic op 61;; arith_reg_operand -- operand is valid register for arithmetic op 62;; general_movdst_operand -- operand is valid move destination 63;; general_movsrc_operand -- operand is valid move source 64;; logical_operand -- operand is valid source for logical op 65 66;; ------------------------------------------------------------------------- 67;; Constants 68;; ------------------------------------------------------------------------- 69 70(define_constants [ 71 (AP_REG 145) 72 (PR_REG 146) 73 (T_REG 147) 74 (GBR_REG 144) 75 (MACH_REG 148) 76 (MACL_REG 149) 77 (FPUL_REG 150) 78 (RAP_REG 152) 79 80 (FPSCR_REG 151) 81 82 (PIC_REG 12) 83 (FP_REG 14) 84 (SP_REG 15) 85 86 (PR_MEDIA_REG 18) 87 (T_MEDIA_REG 19) 88 89 (R0_REG 0) 90 (R1_REG 1) 91 (R2_REG 2) 92 (R3_REG 3) 93 (R4_REG 4) 94 (R5_REG 5) 95 (R6_REG 6) 96 (R7_REG 7) 97 (R8_REG 8) 98 (R9_REG 9) 99 (R10_REG 10) 100 (R20_REG 20) 101 (R21_REG 21) 102 (R22_REG 22) 103 (R23_REG 23) 104 105 (DR0_REG 64) 106 (DR2_REG 66) 107 (DR4_REG 68) 108 (FR23_REG 87) 109 110 (TR0_REG 128) 111 (TR1_REG 129) 112 (TR2_REG 130) 113 114 (XD0_REG 136) 115 116 ;; These are used with unspec. 117 (UNSPEC_COMPACT_ARGS 0) 118 (UNSPEC_MOVA 1) 119 (UNSPEC_CASESI 2) 120 (UNSPEC_DATALABEL 3) 121 (UNSPEC_BBR 4) 122 (UNSPEC_SFUNC 5) 123 (UNSPEC_PIC 6) 124 (UNSPEC_GOT 7) 125 (UNSPEC_GOTOFF 8) 126 (UNSPEC_PLT 9) 127 (UNSPEC_CALLER 10) 128 (UNSPEC_GOTPLT 11) 129 (UNSPEC_ICACHE 12) 130 (UNSPEC_INIT_TRAMP 13) 131 (UNSPEC_FCOSA 14) 132 (UNSPEC_FSRRA 15) 133 (UNSPEC_FSINA 16) 134 (UNSPEC_NSB 17) 135 (UNSPEC_ALLOCO 18) 136 (UNSPEC_TLSGD 20) 137 (UNSPEC_TLSLDM 21) 138 (UNSPEC_TLSIE 22) 139 (UNSPEC_DTPOFF 23) 140 (UNSPEC_GOTTPOFF 24) 141 (UNSPEC_TPOFF 25) 142 (UNSPEC_RA 26) 143 (UNSPEC_DIV_INV_M0 30) 144 (UNSPEC_DIV_INV_M1 31) 145 (UNSPEC_DIV_INV_M2 32) 146 (UNSPEC_DIV_INV_M3 33) 147 (UNSPEC_DIV_INV20 34) 148 (UNSPEC_DIV_INV_TABLE 37) 149 (UNSPEC_ASHIFTRT 35) 150 (UNSPEC_THUNK 36) 151 (UNSPEC_CHKADD 38) 152 (UNSPEC_SP_SET 40) 153 (UNSPEC_SP_TEST 41) 154 (UNSPEC_MOVUA 42) 155 156 ;; (unspec [VAL SHIFT] UNSPEC_EXTRACT_S16) computes (short) (VAL >> SHIFT). 157 ;; UNSPEC_EXTRACT_U16 is the unsigned equivalent. 158 (UNSPEC_EXTRACT_S16 43) 159 (UNSPEC_EXTRACT_U16 44) 160 161 ;; (unspec [TARGET ANCHOR] UNSPEC_SYMOFF) == TARGET - ANCHOR. 162 (UNSPEC_SYMOFF 45) 163 164 ;; (unspec [OFFSET ANCHOR] UNSPEC_PCREL_SYMOFF) == OFFSET - (ANCHOR - .). 165 (UNSPEC_PCREL_SYMOFF 46) 166 167 ;; These are used with unspec_volatile. 168 (UNSPECV_BLOCKAGE 0) 169 (UNSPECV_ALIGN 1) 170 (UNSPECV_CONST2 2) 171 (UNSPECV_CONST4 4) 172 (UNSPECV_CONST8 6) 173 (UNSPECV_WINDOW_END 10) 174 (UNSPECV_CONST_END 11) 175 (UNSPECV_EH_RETURN 12) 176 (UNSPECV_GBR 13) 177 (UNSPECV_SP_SWITCH_B 14) 178 (UNSPECV_SP_SWITCH_E 15) 179]) 180 181;; ------------------------------------------------------------------------- 182;; Attributes 183;; ------------------------------------------------------------------------- 184 185;; Target CPU. 186 187(define_attr "cpu" 188 "sh1,sh2,sh2e,sh2a,sh3,sh3e,sh4,sh4a,sh5" 189 (const (symbol_ref "sh_cpu_attr"))) 190 191(define_attr "endian" "big,little" 192 (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN") 193 (const_string "little") (const_string "big")))) 194 195;; Indicate if the default fpu mode is single precision. 196(define_attr "fpu_single" "yes,no" 197 (const (if_then_else (symbol_ref "TARGET_FPU_SINGLE") 198 (const_string "yes") (const_string "no")))) 199 200(define_attr "fmovd" "yes,no" 201 (const (if_then_else (symbol_ref "TARGET_FMOVD") 202 (const_string "yes") (const_string "no")))) 203;; pipeline model 204(define_attr "pipe_model" "sh1,sh4,sh5media" 205 (const 206 (cond [(symbol_ref "TARGET_SHMEDIA") (const_string "sh5media") 207 (symbol_ref "TARGET_SUPERSCALAR") (const_string "sh4")] 208 (const_string "sh1")))) 209 210;; cbranch conditional branch instructions 211;; jump unconditional jumps 212;; arith ordinary arithmetic 213;; arith3 a compound insn that behaves similarly to a sequence of 214;; three insns of type arith 215;; arith3b like above, but might end with a redirected branch 216;; load from memory 217;; load_si Likewise, SImode variant for general register. 218;; fload Likewise, but load to fp register. 219;; store to memory 220;; fstore floating point register to memory 221;; move general purpose register to register 222;; movi8 8-bit immediate to general purpose register 223;; mt_group other sh4 mt instructions 224;; fmove register to register, floating point 225;; smpy word precision integer multiply 226;; dmpy longword or doublelongword precision integer multiply 227;; return rts 228;; pload load of pr reg, which can't be put into delay slot of rts 229;; prset copy register to pr reg, ditto 230;; pstore store of pr reg, which can't be put into delay slot of jsr 231;; prget copy pr to register, ditto 232;; pcload pc relative load of constant value 233;; pcfload Likewise, but load to fp register. 234;; pcload_si Likewise, SImode variant for general register. 235;; rte return from exception 236;; sfunc special function call with known used registers 237;; call function call 238;; fp floating point 239;; fpscr_toggle toggle a bit in the fpscr 240;; fdiv floating point divide (or square root) 241;; gp_fpul move from general purpose register to fpul 242;; fpul_gp move from fpul to general purpose register 243;; mac_gp move from mac[lh] to general purpose register 244;; gp_mac move from general purpose register to mac[lh] 245;; mac_mem move from mac[lh] to memory 246;; mem_mac move from memory to mac[lh] 247;; dfp_arith,dfp_mul, fp_cmp,dfp_cmp,dfp_conv 248;; ftrc_s fix_truncsfsi2_i4 249;; dfdiv double precision floating point divide (or square root) 250;; cwb ic_invalidate_line_i 251;; movua SH4a unaligned load 252;; fsrra square root reciprocal approximate 253;; fsca sine and cosine approximate 254;; tls_load load TLS related address 255;; arith_media SHmedia arithmetic, logical, and shift instructions 256;; cbranch_media SHmedia conditional branch instructions 257;; cmp_media SHmedia compare instructions 258;; dfdiv_media SHmedia double precision divide and square root 259;; dfmul_media SHmedia double precision multiply instruction 260;; dfparith_media SHmedia double precision floating point arithmetic 261;; dfpconv_media SHmedia double precision floating point conversions 262;; dmpy_media SHmedia longword multiply 263;; fcmp_media SHmedia floating point compare instructions 264;; fdiv_media SHmedia single precision divide and square root 265;; fload_media SHmedia floating point register load instructions 266;; fmove_media SHmedia floating point register moves (inc. fabs and fneg) 267;; fparith_media SHmedia single precision floating point arithmetic 268;; fpconv_media SHmedia single precision floating point conversions 269;; fstore_media SHmedia floating point register store instructions 270;; gettr_media SHmedia gettr instruction 271;; invalidate_line_media SHmedia invalidate_line sequence 272;; jump_media SHmedia unconditional branch instructions 273;; load_media SHmedia general register load instructions 274;; pt_media SHmedia pt instruction (expanded by assembler) 275;; ptabs_media SHmedia ptabs instruction 276;; store_media SHmedia general register store instructions 277;; mcmp_media SHmedia multimedia compare, absolute, saturating ops 278;; mac_media SHmedia mac-style fixed point operations 279;; d2mpy_media SHmedia: two 32-bit integer multiplies 280;; atrans_media SHmedia approximate transcendental functions 281;; ustore_media SHmedia unaligned stores 282;; nil no-op move, will be deleted. 283 284(define_attr "type" 285 "mt_group,cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,load,load_si, 286 fload,store,fstore,move,movi8,fmove,smpy,dmpy,return,pload,prset,pstore, 287 prget,pcload,pcload_si,pcfload,rte,sfunc,call,fp,fpscr_toggle,fdiv,ftrc_s, 288 dfp_arith,dfp_mul,fp_cmp,dfp_cmp,dfp_conv,dfdiv,gp_fpul,fpul_gp,mac_gp, 289 gp_mac,mac_mem,mem_mac,mem_fpscr,gp_fpscr,cwb,movua,fsrra,fsca,tls_load, 290 arith_media,cbranch_media,cmp_media,dfdiv_media,dfmul_media,dfparith_media, 291 dfpconv_media,dmpy_media,fcmp_media,fdiv_media,fload_media,fmove_media, 292 fparith_media,fpconv_media,fstore_media,gettr_media,invalidate_line_media, 293 jump_media,load_media,pt_media,ptabs_media,store_media,mcmp_media,mac_media, 294 d2mpy_media,atrans_media,ustore_media,nil,other" 295 (const_string "other")) 296 297;; We define a new attribute namely "insn_class".We use 298;; this for the DFA based pipeline description. 299;; 300;; mt_group SH4 "mt" group instructions. 301;; 302;; ex_group SH4 "ex" group instructions. 303;; 304;; ls_group SH4 "ls" group instructions. 305;; 306(define_attr "insn_class" 307 "mt_group,ex_group,ls_group,br_group,fe_group,co_group,none" 308 (cond [(eq_attr "type" "move,mt_group") (const_string "mt_group") 309 (eq_attr "type" "movi8,arith,dyn_shift") (const_string "ex_group") 310 (eq_attr "type" "fmove,load,pcload,load_si,pcload_si,fload,pcfload, 311 store,fstore,gp_fpul,fpul_gp") (const_string "ls_group") 312 (eq_attr "type" "cbranch,jump") (const_string "br_group") 313 (eq_attr "type" "fp,fp_cmp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv") 314 (const_string "fe_group") 315 (eq_attr "type" "jump_ind,smpy,dmpy,mac_gp,return,pload,prset,pstore, 316 prget,rte,sfunc,call,dfp_cmp,mem_fpscr,gp_fpscr,cwb, 317 gp_mac,mac_mem,mem_mac") (const_string "co_group")] 318 (const_string "none"))) 319 320;; nil are zero instructions, and arith3 / arith3b are multiple instructions, 321;; so these do not belong in an insn group, although they are modeled 322;; with their own define_insn_reservations. 323 324;; Indicate what precision must be selected in fpscr for this insn, if any. 325(define_attr "fp_mode" "single,double,none" (const_string "none")) 326 327;; Indicate if the fpu mode is set by this instruction 328;; "unknown" must have the value as "none" in fp_mode, and means 329;; that the instruction/abi has left the processor in an unknown 330;; state. 331;; "none" means that nothing has changed and no mode is set. 332;; This attribute is only used for the Renesas ABI. 333(define_attr "fp_set" "single,double,unknown,none" (const_string "none")) 334 335; If a conditional branch destination is within -252..258 bytes away 336; from the instruction it can be 2 bytes long. Something in the 337; range -4090..4100 bytes can be 6 bytes long. All other conditional 338; branches are initially assumed to be 16 bytes long. 339; In machine_dependent_reorg, we split all branches that are longer than 340; 2 bytes. 341 342;; The maximum range used for SImode constant pool entries is 1018. A final 343;; instruction can add 8 bytes while only being 4 bytes in size, thus we 344;; can have a total of 1022 bytes in the pool. Add 4 bytes for a branch 345;; instruction around the pool table, 2 bytes of alignment before the table, 346;; and 30 bytes of alignment after the table. That gives a maximum total 347;; pool size of 1058 bytes. 348;; Worst case code/pool content size ratio is 1:2 (using asms). 349;; Thus, in the worst case, there is one instruction in front of a maximum 350;; sized pool, and then there are 1052 bytes of pool for every 508 bytes of 351;; code. For the last n bytes of code, there are 2n + 36 bytes of pool. 352;; If we have a forward branch, the initial table will be put after the 353;; unconditional branch. 354;; 355;; ??? We could do much better by keeping track of the actual pcloads within 356;; the branch range and in the pcload range in front of the branch range. 357 358;; ??? This looks ugly because genattrtab won't allow if_then_else or cond 359;; inside an le. 360(define_attr "short_cbranch_p" "no,yes" 361 (cond [(match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD") 362 (const_string "no") 363 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506)) 364 (const_string "yes") 365 (match_test "NEXT_INSN (PREV_INSN (insn)) != insn") 366 (const_string "no") 367 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508)) 368 (const_string "yes") 369 ] (const_string "no"))) 370 371(define_attr "med_branch_p" "no,yes" 372 (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990)) 373 (const_int 1988)) 374 (const_string "yes") 375 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD") 376 (const_string "no") 377 (leu (plus (minus (match_dup 0) (pc)) (const_int 4092)) 378 (const_int 8186)) 379 (const_string "yes") 380 ] (const_string "no"))) 381 382(define_attr "med_cbranch_p" "no,yes" 383 (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988)) 384 (const_int 1986)) 385 (const_string "yes") 386 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD") 387 (const_string "no") 388 (leu (plus (minus (match_dup 0) (pc)) (const_int 4090)) 389 (const_int 8184)) 390 (const_string "yes") 391 ] (const_string "no"))) 392 393(define_attr "braf_branch_p" "no,yes" 394 (cond [(match_test "! TARGET_SH2") 395 (const_string "no") 396 (leu (plus (minus (match_dup 0) (pc)) (const_int 10330)) 397 (const_int 20660)) 398 (const_string "yes") 399 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD") 400 (const_string "no") 401 (leu (plus (minus (match_dup 0) (pc)) (const_int 32764)) 402 (const_int 65530)) 403 (const_string "yes") 404 ] (const_string "no"))) 405 406(define_attr "braf_cbranch_p" "no,yes" 407 (cond [(match_test "! TARGET_SH2") 408 (const_string "no") 409 (leu (plus (minus (match_dup 0) (pc)) (const_int 10328)) 410 (const_int 20658)) 411 (const_string "yes") 412 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD") 413 (const_string "no") 414 (leu (plus (minus (match_dup 0) (pc)) (const_int 32762)) 415 (const_int 65528)) 416 (const_string "yes") 417 ] (const_string "no"))) 418 419;; An unconditional jump in the range -4092..4098 can be 2 bytes long. 420;; For wider ranges, we need a combination of a code and a data part. 421;; If we can get a scratch register for a long range jump, the code 422;; part can be 4 bytes long; otherwise, it must be 8 bytes long. 423;; If the jump is in the range -32764..32770, the data part can be 2 bytes 424;; long; otherwise, it must be 6 bytes long. 425 426;; All other instructions are two bytes long by default. 427 428;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)), 429;; but getattrtab doesn't understand this. 430(define_attr "length" "" 431 (cond [(eq_attr "type" "cbranch") 432 (cond [(eq_attr "short_cbranch_p" "yes") 433 (const_int 2) 434 (eq_attr "med_cbranch_p" "yes") 435 (const_int 6) 436 (eq_attr "braf_cbranch_p" "yes") 437 (const_int 12) 438;; ??? using pc is not computed transitively. 439 (ne (match_dup 0) (match_dup 0)) 440 (const_int 14) 441 (match_test "flag_pic") 442 (const_int 24) 443 ] (const_int 16)) 444 (eq_attr "type" "jump") 445 (cond [(eq_attr "med_branch_p" "yes") 446 (const_int 2) 447 (and (match_test "prev_nonnote_insn (insn)") 448 (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))") 449 (symbol_ref "INSN")) 450 (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))") 451 (symbol_ref "code_for_indirect_jump_scratch")))) 452 (cond [(eq_attr "braf_branch_p" "yes") 453 (const_int 6) 454 (not (match_test "flag_pic")) 455 (const_int 10) 456 (match_test "TARGET_SH2") 457 (const_int 10)] (const_int 18)) 458 (eq_attr "braf_branch_p" "yes") 459 (const_int 10) 460;; ??? using pc is not computed transitively. 461 (ne (match_dup 0) (match_dup 0)) 462 (const_int 12) 463 (match_test "flag_pic") 464 (const_int 22) 465 ] (const_int 14)) 466 (eq_attr "type" "pt_media") 467 (if_then_else (match_test "TARGET_SHMEDIA64") 468 (const_int 20) (const_int 12)) 469 (and (eq_attr "type" "jump_media") 470 (match_test "TARGET_SH5_CUT2_WORKAROUND")) 471 (const_int 8) 472 ] (if_then_else (match_test "TARGET_SHMEDIA") 473 (const_int 4) 474 (const_int 2)))) 475 476;; DFA descriptions for the pipelines 477 478(include "sh1.md") 479(include "shmedia.md") 480(include "sh4.md") 481 482(include "iterators.md") 483(include "predicates.md") 484(include "constraints.md") 485 486;; Definitions for filling delay slots 487 488(define_attr "needs_delay_slot" "yes,no" (const_string "no")) 489 490(define_attr "banked" "yes,no" 491 (cond [(match_test "sh_loads_bankedreg_p (insn)") 492 (const_string "yes")] 493 (const_string "no"))) 494 495;; ??? This should be (nil) instead of (const_int 0) 496(define_attr "hit_stack" "yes,no" 497 (cond [(not (match_test "find_regno_note (insn, REG_INC, SP_REG)")) 498 (const_string "no")] 499 (const_string "yes"))) 500 501(define_attr "interrupt_function" "no,yes" 502 (const (symbol_ref "current_function_interrupt"))) 503 504(define_attr "in_delay_slot" "yes,no" 505 (cond [(eq_attr "type" "cbranch") (const_string "no") 506 (eq_attr "type" "pcload,pcload_si") (const_string "no") 507 (eq_attr "needs_delay_slot" "yes") (const_string "no") 508 (eq_attr "length" "2") (const_string "yes") 509 ] (const_string "no"))) 510 511(define_attr "cond_delay_slot" "yes,no" 512 (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes") 513 ] (const_string "no"))) 514 515(define_attr "is_sfunc" "" 516 (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0))) 517 518(define_attr "is_mac_media" "" 519 (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0))) 520 521(define_attr "branch_zero" "yes,no" 522 (cond [(eq_attr "type" "!cbranch") (const_string "no") 523 (ne (symbol_ref "(next_active_insn (insn)\ 524 == (prev_active_insn\ 525 (XEXP (SET_SRC (PATTERN (insn)), 1))))\ 526 && get_attr_length (next_active_insn (insn)) == 2") 527 (const_int 0)) 528 (const_string "yes")] 529 (const_string "no"))) 530 531;; SH4 Double-precision computation with double-precision result - 532;; the two halves are ready at different times. 533(define_attr "dfp_comp" "yes,no" 534 (cond [(eq_attr "type" "dfp_arith,dfp_mul,dfp_conv,dfdiv") (const_string "yes")] 535 (const_string "no"))) 536 537;; Insns for which the latency of a preceding fp insn is decreased by one. 538(define_attr "late_fp_use" "yes,no" (const_string "no")) 539;; And feeding insns for which this relevant. 540(define_attr "any_fp_comp" "yes,no" 541 (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv") 542 (const_string "yes")] 543 (const_string "no"))) 544 545(define_attr "any_int_load" "yes,no" 546 (cond [(eq_attr "type" "load,load_si,pcload,pcload_si") 547 (const_string "yes")] 548 (const_string "no"))) 549 550(define_attr "highpart" "user, ignore, extend, depend, must_split" 551 (const_string "user")) 552 553(define_delay 554 (eq_attr "needs_delay_slot" "yes") 555 [(eq_attr "in_delay_slot" "yes") (nil) (nil)]) 556 557;; Since a normal return (rts) implicitly uses the PR register, 558;; we can't allow PR register loads in an rts delay slot. 559;; On the SH1* and SH2*, the rte instruction reads the return pc from the 560;; stack, and thus we can't put a pop instruction in its delay slot. 561;; On the SH3* and SH4*, the rte instruction does not use the stack, so a 562;; pop instruction can go in the delay slot, unless it references a banked 563;; register (the register bank is switched by rte). 564(define_delay 565 (eq_attr "type" "return") 566 [(and (eq_attr "in_delay_slot" "yes") 567 (ior (and (eq_attr "interrupt_function" "no") 568 (eq_attr "type" "!pload,prset")) 569 (and (eq_attr "interrupt_function" "yes") 570 (ior (match_test "TARGET_SH3") (eq_attr "hit_stack" "no")) 571 (eq_attr "banked" "no")))) 572 (nil) (nil)]) 573 574;; Since a call implicitly uses the PR register, we can't allow 575;; a PR register store in a jsr delay slot. 576 577(define_delay 578 (ior (eq_attr "type" "call") (eq_attr "type" "sfunc")) 579 [(and (eq_attr "in_delay_slot" "yes") 580 (eq_attr "type" "!pstore,prget")) (nil) (nil)]) 581 582;; Say that we have annulled true branches, since this gives smaller and 583;; faster code when branches are predicted as not taken. 584 585;; ??? The non-annulled condition should really be "in_delay_slot", 586;; but insns that can be filled in non-annulled get priority over insns 587;; that can only be filled in anulled. 588 589(define_delay 590 (and (eq_attr "type" "cbranch") 591 (match_test "TARGET_SH2")) 592 ;; SH2e has a hardware bug that pretty much prohibits the use of 593 ;; annulled delay slots. 594 [(eq_attr "cond_delay_slot" "yes") (and (eq_attr "cond_delay_slot" "yes") 595 (not (eq_attr "cpu" "sh2e"))) (nil)]) 596 597;; ------------------------------------------------------------------------- 598;; SImode signed integer comparisons 599;; ------------------------------------------------------------------------- 600 601;; Various patterns to generate the TST #imm, R0 instruction. 602;; Although this adds some pressure on the R0 register, it can potentially 603;; result in faster code, even if the operand has to be moved to R0 first. 604;; This is because on SH4 TST #imm, R0 and MOV Rm, Rn are both MT group 605;; instructions and thus will be executed in parallel. On SH4A TST #imm, R0 606;; is an EX group instruction but still can be executed in parallel with the 607;; MT group MOV Rm, Rn instruction. 608 609;; Usual TST #imm, R0 patterns for SI, HI and QI 610;; This is usually used for bit patterns other than contiguous bits 611;; and single bits. 612(define_insn "tstsi_t" 613 [(set (reg:SI T_REG) 614 (eq:SI (and:SI (match_operand:SI 0 "logical_operand" "%z,r") 615 (match_operand:SI 1 "logical_operand" "K08,r")) 616 (const_int 0)))] 617 "TARGET_SH1" 618 "tst %1,%0" 619 [(set_attr "type" "mt_group")]) 620 621(define_insn "tsthi_t" 622 [(set (reg:SI T_REG) 623 (eq:SI (subreg:SI (and:HI (match_operand:HI 0 "logical_operand" "%z") 624 (match_operand 1 "const_int_operand")) 0) 625 (const_int 0)))] 626 "TARGET_SH1 627 && CONST_OK_FOR_K08 (INTVAL (operands[1]))" 628 "tst %1,%0" 629 [(set_attr "type" "mt_group")]) 630 631(define_insn "tstqi_t" 632 [(set (reg:SI T_REG) 633 (eq:SI (subreg:SI (and:QI (match_operand:QI 0 "logical_operand" "%z") 634 (match_operand 1 "const_int_operand")) 0) 635 (const_int 0)))] 636 "TARGET_SH1 637 && (CONST_OK_FOR_K08 (INTVAL (operands[1])) 638 || CONST_OK_FOR_I08 (INTVAL (operands[1])))" 639{ 640 operands[1] = GEN_INT (INTVAL (operands[1]) & 255); 641 return "tst %1,%0"; 642} 643 [(set_attr "type" "mt_group")]) 644 645;; Test low QI subreg against zero. 646;; This avoids unnecessary zero extension before the test. 647(define_insn "*tstqi_t_zero" 648 [(set (reg:SI T_REG) 649 (eq:SI (match_operand:QI 0 "logical_operand" "z") (const_int 0)))] 650 "TARGET_SH1" 651 "tst #255,%0" 652 [(set_attr "type" "mt_group")]) 653 654;; Extract LSB, negate and store in T bit. 655(define_insn "tstsi_t_and_not" 656 [(set (reg:SI T_REG) 657 (and:SI (not:SI (match_operand:SI 0 "logical_operand" "z")) 658 (const_int 1)))] 659 "TARGET_SH1" 660 "tst #1,%0" 661 [(set_attr "type" "mt_group")]) 662 663;; Extract contiguous bits and compare them against zero. 664(define_insn "tst<mode>_t_zero_extract_eq" 665 [(set (reg:SI T_REG) 666 (eq:SI (zero_extract:SI (match_operand:QIHISIDI 0 "logical_operand" "z") 667 (match_operand:SI 1 "const_int_operand") 668 (match_operand:SI 2 "const_int_operand")) 669 (const_int 0)))] 670 "TARGET_SH1 671 && CONST_OK_FOR_K08 (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]))" 672{ 673 operands[1] = GEN_INT (ZERO_EXTRACT_ANDMASK (operands[1], operands[2])); 674 return "tst %1,%0"; 675} 676 [(set_attr "type" "mt_group")]) 677 678;; This split is required when testing bits in a QI subreg. 679(define_split 680 [(set (reg:SI T_REG) 681 (eq:SI 682 (if_then_else:SI 683 (zero_extract:SI (match_operand 0 "logical_operand") 684 (match_operand 1 "const_int_operand") 685 (match_operand 2 "const_int_operand")) 686 (match_operand 3 "const_int_operand") 687 (const_int 0)) 688 (const_int 0)))] 689 "TARGET_SH1 690 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3]) 691 && CONST_OK_FOR_K08 (INTVAL (operands[3]))" 692 [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 3)) 693 (const_int 0)))] 694{ 695 if (GET_MODE (operands[0]) == QImode) 696 operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0); 697}) 698 699;; Extract single bit, negate and store it in the T bit. 700;; Not used for SH4A. 701(define_insn "tstsi_t_zero_extract_xor" 702 [(set (reg:SI T_REG) 703 (zero_extract:SI (xor:SI (match_operand:SI 0 "logical_operand" "z") 704 (match_operand:SI 3 "const_int_operand")) 705 (match_operand:SI 1 "const_int_operand") 706 (match_operand:SI 2 "const_int_operand")))] 707 "TARGET_SH1 708 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3]) 709 && CONST_OK_FOR_K08 (INTVAL (operands[3]))" 710 "tst %3,%0" 711 [(set_attr "type" "mt_group")]) 712 713;; Extract single bit, negate and store it in the T bit. 714;; Used for SH4A little endian. 715(define_insn "tstsi_t_zero_extract_subreg_xor_little" 716 [(set (reg:SI T_REG) 717 (zero_extract:SI 718 (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z") 719 (match_operand:SI 3 "const_int_operand")) 0) 720 (match_operand:SI 1 "const_int_operand") 721 (match_operand:SI 2 "const_int_operand")))] 722 "TARGET_SH1 && TARGET_LITTLE_ENDIAN 723 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) 724 == (INTVAL (operands[3]) & 255) 725 && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)" 726{ 727 operands[3] = GEN_INT (INTVAL (operands[3]) & 255); 728 return "tst %3,%0"; 729} 730 [(set_attr "type" "mt_group")]) 731 732;; Extract single bit, negate and store it in the T bit. 733;; Used for SH4A big endian. 734(define_insn "tstsi_t_zero_extract_subreg_xor_big" 735 [(set (reg:SI T_REG) 736 (zero_extract:SI 737 (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z") 738 (match_operand:SI 3 "const_int_operand")) 3) 739 (match_operand:SI 1 "const_int_operand") 740 (match_operand:SI 2 "const_int_operand")))] 741 "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN 742 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) 743 == (INTVAL (operands[3]) & 255) 744 && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)" 745{ 746 operands[3] = GEN_INT (INTVAL (operands[3]) & 255); 747 return "tst %3,%0"; 748} 749 [(set_attr "type" "mt_group")]) 750 751(define_insn "cmpeqsi_t" 752 [(set (reg:SI T_REG) 753 (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r") 754 (match_operand:SI 1 "arith_operand" "N,rI08,r")))] 755 "TARGET_SH1" 756 "@ 757 tst %0,%0 758 cmp/eq %1,%0 759 cmp/eq %1,%0" 760 [(set_attr "type" "mt_group")]) 761 762;; FIXME: For some reason, on SH4A and SH2A combine fails to simplify this 763;; pattern by itself. What this actually does is: 764;; x == 0: (1 >> 0-0) & 1 = 1 765;; x != 0: (1 >> 0-x) & 1 = 0 766;; Without this the test pr51244-8.c fails on SH2A and SH4A. 767(define_insn_and_split "*cmpeqsi_t" 768 [(set (reg:SI T_REG) 769 (and:SI (lshiftrt:SI 770 (const_int 1) 771 (neg:SI (match_operand:SI 0 "arith_reg_operand" "r"))) 772 (const_int 1)))] 773 "TARGET_SH1" 774 "#" 775 "&& 1" 776 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))]) 777 778(define_insn "cmpgtsi_t" 779 [(set (reg:SI T_REG) 780 (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r") 781 (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))] 782 "TARGET_SH1" 783 "@ 784 cmp/pl %0 785 cmp/gt %1,%0" 786 [(set_attr "type" "mt_group")]) 787 788(define_insn "cmpgesi_t" 789 [(set (reg:SI T_REG) 790 (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r") 791 (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))] 792 "TARGET_SH1" 793 "@ 794 cmp/pz %0 795 cmp/ge %1,%0" 796 [(set_attr "type" "mt_group")]) 797 798;; FIXME: This is actually wrong. There is no way to literally move a 799;; general reg to t reg. Luckily, it seems that this pattern will be only 800;; used when the general reg is known be either '0' or '1' during combine. 801;; What we actually need is reg != 0 -> T, but we have only reg == 0 -> T. 802;; Due to interactions with other patterns, combine fails to pick the latter 803;; and invert the dependent logic. 804(define_insn "*negtstsi" 805 [(set (reg:SI T_REG) (match_operand:SI 0 "arith_reg_operand" "r"))] 806 "TARGET_SH1" 807 "cmp/pl %0" 808 [(set_attr "type" "mt_group")]) 809 810;; Some integer sign comparison patterns can be realized with the div0s insn. 811;; div0s Rm,Rn T = (Rm >> 31) ^ (Rn >> 31) 812(define_insn "cmp_div0s_0" 813 [(set (reg:SI T_REG) 814 (lshiftrt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "%r") 815 (match_operand:SI 1 "arith_reg_operand" "r")) 816 (const_int 31)))] 817 "TARGET_SH1" 818 "div0s %0,%1" 819 [(set_attr "type" "arith")]) 820 821(define_insn "cmp_div0s_1" 822 [(set (reg:SI T_REG) 823 (lt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "%r") 824 (match_operand:SI 1 "arith_reg_operand" "r")) 825 (const_int 0)))] 826 "TARGET_SH1" 827 "div0s %0,%1" 828 [(set_attr "type" "arith")]) 829 830(define_insn_and_split "*cmp_div0s_0" 831 [(set (match_operand:SI 0 "arith_reg_dest" "") 832 (lshiftrt:SI (xor:SI (match_operand:SI 1 "arith_reg_operand" "") 833 (match_operand:SI 2 "arith_reg_operand" "")) 834 (const_int 31))) 835 (clobber (reg:SI T_REG))] 836 "TARGET_SH1" 837 "#" 838 "&& 1" 839 [(set (reg:SI T_REG) 840 (lshiftrt:SI (xor:SI (match_dup 1) (match_dup 2)) (const_int 31))) 841 (set (match_dup 0) (reg:SI T_REG))]) 842 843(define_insn_and_split "*cmp_div0s_1" 844 [(set (match_operand:SI 0 "arith_reg_dest" "") 845 (ge:SI (xor:SI (match_operand:SI 1 "arith_reg_operand" "") 846 (match_operand:SI 2 "arith_reg_operand" "")) 847 (const_int 0))) 848 (clobber (reg:SI T_REG))] 849 "TARGET_SH1" 850 "#" 851 "&& can_create_pseudo_p ()" 852 [(const_int 0)] 853;; We have to go through the movnegt expander here which will handle the 854;; SH2A vs non-SH2A cases. 855{ 856 emit_insn (gen_cmp_div0s_1 (operands[1], operands[2])); 857 emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ())); 858 DONE; 859}) 860 861(define_insn_and_split "*cmp_div0s_1" 862 [(set (reg:SI T_REG) 863 (ge:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "") 864 (match_operand:SI 1 "arith_reg_operand" "")) 865 (const_int 0)))] 866 "TARGET_SH1" 867 "#" 868 "&& can_create_pseudo_p ()" 869 [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 0) (match_dup 1)) 870 (const_int 0))) 871 (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))]) 872 873;; ------------------------------------------------------------------------- 874;; SImode compare and branch 875;; ------------------------------------------------------------------------- 876 877(define_expand "cbranchsi4" 878 [(set (pc) 879 (if_then_else (match_operator 0 "comparison_operator" 880 [(match_operand:SI 1 "arith_operand" "") 881 (match_operand:SI 2 "arith_operand" "")]) 882 (label_ref (match_operand 3 "" "")) 883 (pc))) 884 (clobber (reg:SI T_REG))] 885 "" 886{ 887 if (TARGET_SHMEDIA) 888 emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1], 889 operands[2], operands[3])); 890 else 891 expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1); 892 893 DONE; 894}) 895 896;; Combine patterns to invert compare and branch operations for which we 897;; don't have actual comparison insns. These patterns are used in cases 898;; which appear after the initial cbranchsi expansion, which also does 899;; some condition inversion. 900(define_split 901 [(set (pc) 902 (if_then_else (ne (match_operand:SI 0 "arith_reg_operand" "") 903 (match_operand:SI 1 "arith_reg_or_0_operand" "")) 904 (label_ref (match_operand 2)) 905 (pc))) 906 (clobber (reg:SI T_REG))] 907 "TARGET_SH1" 908 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (match_dup 1))) 909 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 910 (label_ref (match_dup 2)) 911 (pc)))]) 912 913;; FIXME: Similar to the *cmpeqsi_t pattern above, for some reason, on SH4A 914;; and SH2A combine fails to simplify this pattern by itself. 915;; What this actually does is: 916;; x == 0: (1 >> 0-0) & 1 = 1 917;; x != 0: (1 >> 0-x) & 1 = 0 918;; Without this the test pr51244-8.c fails on SH2A and SH4A. 919(define_split 920 [(set (pc) 921 (if_then_else 922 (eq (and:SI (lshiftrt:SI 923 (const_int 1) 924 (neg:SI (match_operand:SI 0 "arith_reg_operand" ""))) 925 (const_int 1)) 926 (const_int 0)) 927 (label_ref (match_operand 2)) 928 (pc))) 929 (clobber (reg:SI T_REG))] 930 "TARGET_SH1" 931 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0))) 932 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 933 (label_ref (match_dup 2)) 934 (pc)))]) 935 936;; FIXME: These could probably use code iterators for the compare op. 937(define_split 938 [(set (pc) 939 (if_then_else (le (match_operand:SI 0 "arith_reg_operand" "") 940 (match_operand:SI 1 "arith_reg_or_0_operand" "")) 941 (label_ref (match_operand 2)) 942 (pc))) 943 (clobber (reg:SI T_REG))] 944 "TARGET_SH1" 945 [(set (reg:SI T_REG) (gt:SI (match_dup 0) (match_dup 1))) 946 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 947 (label_ref (match_dup 2)) 948 (pc)))]) 949 950(define_split 951 [(set (pc) 952 (if_then_else (lt (match_operand:SI 0 "arith_reg_operand" "") 953 (match_operand:SI 1 "arith_reg_or_0_operand" "")) 954 (label_ref (match_operand 2)) 955 (pc))) 956 (clobber (reg:SI T_REG))] 957 "TARGET_SH1" 958 [(set (reg:SI T_REG) (ge:SI (match_dup 0) (match_dup 1))) 959 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 960 (label_ref (match_dup 2)) 961 (pc)))]) 962 963(define_split 964 [(set (pc) 965 (if_then_else (leu (match_operand:SI 0 "arith_reg_operand" "") 966 (match_operand:SI 1 "arith_reg_operand" "")) 967 (label_ref (match_operand 2)) 968 (pc))) 969 (clobber (reg:SI T_REG))] 970 "TARGET_SH1" 971 [(set (reg:SI T_REG) (gtu:SI (match_dup 0) (match_dup 1))) 972 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 973 (label_ref (match_dup 2)) 974 (pc)))]) 975 976(define_split 977 [(set (pc) 978 (if_then_else (ltu (match_operand:SI 0 "arith_reg_operand" "") 979 (match_operand:SI 1 "arith_reg_operand" "")) 980 (label_ref (match_operand 2)) 981 (pc))) 982 (clobber (reg:SI T_REG))] 983 "TARGET_SH1" 984 [(set (reg:SI T_REG) (geu:SI (match_dup 0) (match_dup 1))) 985 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 986 (label_ref (match_dup 2)) 987 (pc)))]) 988 989;; Compare and branch combine patterns for div0s comparisons. 990(define_insn_and_split "*cbranch_div0s" 991 [(set (pc) 992 (if_then_else (lt (xor:SI (match_operand:SI 0 "arith_reg_operand" "") 993 (match_operand:SI 1 "arith_reg_operand" "")) 994 (const_int 0)) 995 (label_ref (match_operand 2)) 996 (pc))) 997 (clobber (reg:SI T_REG))] 998 "TARGET_SH1" 999 "#" 1000 "&& 1" 1001 [(set (reg:SI T_REG) 1002 (lt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 0))) 1003 (set (pc) 1004 (if_then_else (ne (reg:SI T_REG) (const_int 0)) 1005 (label_ref (match_dup 2)) 1006 (pc)))]) 1007 1008(define_insn_and_split "*cbranch_div0s" 1009 [(set (pc) 1010 (if_then_else (ge (xor:SI (match_operand:SI 0 "arith_reg_operand" "") 1011 (match_operand:SI 1 "arith_reg_operand" "")) 1012 (const_int 0)) 1013 (label_ref (match_operand 2)) 1014 (pc))) 1015 (clobber (reg:SI T_REG))] 1016 "TARGET_SH1" 1017 "#" 1018 "&& 1" 1019 [(set (reg:SI T_REG) 1020 (lt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 0))) 1021 (set (pc) 1022 (if_then_else (eq (reg:SI T_REG) (const_int 0)) 1023 (label_ref (match_dup 2)) 1024 (pc)))]) 1025 1026;; Conditional move combine pattern for div0s comparisons. 1027;; This is used when TARGET_PRETEND_CMOVE is in effect. 1028(define_insn_and_split "*movsicc_div0s" 1029 [(set (match_operand:SI 0 "arith_reg_dest" "") 1030 (if_then_else:SI (ge (xor:SI (match_operand:SI 1 "arith_reg_operand" "") 1031 (match_operand:SI 2 "arith_reg_operand" "")) 1032 (const_int 0)) 1033 (match_operand:SI 3 "arith_reg_operand" "") 1034 (match_operand:SI 4 "general_movsrc_operand" ""))) 1035 (clobber (reg:SI T_REG))] 1036 "TARGET_PRETEND_CMOVE" 1037 "#" 1038 "&& 1" 1039 [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 1) (match_dup 2)) 1040 (const_int 0))) 1041 (set (match_dup 0) 1042 (if_then_else (ne (reg:SI T_REG) (const_int 0)) 1043 (match_dup 4) 1044 (match_dup 3)))]) 1045 1046;; ------------------------------------------------------------------------- 1047;; SImode unsigned integer comparisons 1048;; ------------------------------------------------------------------------- 1049 1050;; Usually comparisons of 'unsigned int >= 0' are optimized away completely. 1051;; However, especially when optimizations are off (e.g. -O0) such comparisons 1052;; might remain and we have to handle them. If the '>= 0' case wasn't 1053;; handled here, something else would just load a '0' into the second operand 1054;; and do the comparison. We can do slightly better by just setting the 1055;; T bit to '1'. 1056(define_insn_and_split "cmpgeusi_t" 1057 [(set (reg:SI T_REG) 1058 (geu:SI (match_operand:SI 0 "arith_reg_operand" "r") 1059 (match_operand:SI 1 "arith_reg_or_0_operand" "r")))] 1060 "TARGET_SH1" 1061 "cmp/hs %1,%0" 1062 "&& satisfies_constraint_Z (operands[1])" 1063 [(set (reg:SI T_REG) (const_int 1))] 1064 "" 1065 [(set_attr "type" "mt_group")]) 1066 1067(define_insn "cmpgtusi_t" 1068 [(set (reg:SI T_REG) 1069 (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r") 1070 (match_operand:SI 1 "arith_reg_operand" "r")))] 1071 "TARGET_SH1" 1072 "cmp/hi %1,%0" 1073 [(set_attr "type" "mt_group")]) 1074 1075;; ------------------------------------------------------------------------- 1076;; DImode compare and branch 1077;; ------------------------------------------------------------------------- 1078 1079;; arith3 patterns don't work well with the sh4-300 branch prediction mechanism. 1080;; Therefore, we aim to have a set of three branches that go straight to the 1081;; destination, i.e. only one of them is taken at any one time. 1082;; This mechanism should also be slightly better for the sh4-200. 1083 1084(define_expand "cbranchdi4" 1085 [(set (pc) 1086 (if_then_else (match_operator 0 "comparison_operator" 1087 [(match_operand:DI 1 "arith_operand" "") 1088 (match_operand:DI 2 "arith_operand" "")]) 1089 (label_ref (match_operand 3 "" "")) 1090 (pc))) 1091 (clobber (match_dup 4)) 1092 (clobber (reg:SI T_REG))] 1093 "TARGET_CBRANCHDI4 || TARGET_SH2 || TARGET_SHMEDIA" 1094{ 1095 enum rtx_code comparison; 1096 1097 if (TARGET_SHMEDIA) 1098 { 1099 emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1], 1100 operands[2], operands[3])); 1101 DONE; 1102 } 1103 else if (!TARGET_CBRANCHDI4) 1104 { 1105 sh_emit_compare_and_branch (operands, DImode); 1106 DONE; 1107 } 1108 else 1109 { 1110 if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE)) 1111 DONE; 1112 1113 comparison = prepare_cbranch_operands (operands, DImode, 1114 LAST_AND_UNUSED_RTX_CODE); 1115 if (comparison != GET_CODE (operands[0])) 1116 operands[0] 1117 = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]); 1118 operands[4] = gen_rtx_SCRATCH (SImode); 1119 } 1120}) 1121 1122(define_insn_and_split "cbranchdi4_i" 1123 [(set (pc) 1124 (if_then_else (match_operator 0 "comparison_operator" 1125 [(match_operand:DI 1 "arith_operand" "r,r") 1126 (match_operand:DI 2 "arith_operand" "rN,I08")]) 1127 (label_ref (match_operand 3 "" "")) 1128 (pc))) 1129 (clobber (match_scratch:SI 4 "=X,&r")) 1130 (clobber (reg:SI T_REG))] 1131 "TARGET_CBRANCHDI4" 1132 "#" 1133 "&& reload_completed" 1134 [(pc)] 1135{ 1136 if (!expand_cbranchdi4 (operands, GET_CODE (operands[0]))) 1137 FAIL; 1138 DONE; 1139}) 1140 1141;; ------------------------------------------------------------------------- 1142;; DImode signed integer comparisons 1143;; ------------------------------------------------------------------------- 1144 1145(define_insn "" 1146 [(set (reg:SI T_REG) 1147 (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r") 1148 (match_operand:DI 1 "arith_operand" "r")) 1149 (const_int 0)))] 1150 "TARGET_SH1" 1151{ 1152 return output_branchy_insn (EQ, "tst\t%S1,%S0;bf\t%l9;tst\t%R1,%R0", 1153 insn, operands); 1154} 1155 [(set_attr "length" "6") 1156 (set_attr "type" "arith3b")]) 1157 1158(define_insn "cmpeqdi_t" 1159 [(set (reg:SI T_REG) 1160 (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r") 1161 (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))] 1162 "TARGET_SH1" 1163{ 1164 static const char* alt[] = 1165 { 1166 "tst %S0,%S0" "\n" 1167 " bf 0f" "\n" 1168 " tst %R0,%R0" "\n" 1169 "0:", 1170 1171 "cmp/eq %S1,%S0" "\n" 1172 " bf 0f" "\n" 1173 " cmp/eq %R1,%R0" "\n" 1174 "0:" 1175 }; 1176 return alt[which_alternative]; 1177} 1178 [(set_attr "length" "6") 1179 (set_attr "type" "arith3b")]) 1180 1181(define_split 1182 [(set (reg:SI T_REG) 1183 (eq:SI (match_operand:DI 0 "arith_reg_operand" "") 1184 (match_operand:DI 1 "arith_reg_or_0_operand" "")))] 1185;; If we applied this split when not optimizing, it would only be 1186;; applied during the machine-dependent reorg, when no new basic blocks 1187;; may be created. 1188 "TARGET_SH1 && reload_completed && optimize" 1189 [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3))) 1190 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 1191 (label_ref (match_dup 6)) 1192 (pc))) 1193 (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5))) 1194 (match_dup 6)] 1195{ 1196 operands[2] = gen_highpart (SImode, operands[0]); 1197 operands[3] = operands[1] == const0_rtx 1198 ? const0_rtx 1199 : gen_highpart (SImode, operands[1]); 1200 operands[4] = gen_lowpart (SImode, operands[0]); 1201 operands[5] = gen_lowpart (SImode, operands[1]); 1202 operands[6] = gen_label_rtx (); 1203}) 1204 1205(define_insn "cmpgtdi_t" 1206 [(set (reg:SI T_REG) 1207 (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r") 1208 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))] 1209 "TARGET_SH2" 1210{ 1211 static const char* alt[] = 1212 { 1213 "cmp/eq %S1,%S0" "\n" 1214 " bf{.|/}s 0f" "\n" 1215 " cmp/gt %S1,%S0" "\n" 1216 " cmp/hi %R1,%R0" "\n" 1217 "0:", 1218 1219 "tst %S0,%S0" "\n" 1220 " bf{.|/}s 0f" "\n" 1221 " cmp/pl %S0" "\n" 1222 " cmp/hi %S0,%R0" "\n" 1223 "0:" 1224 }; 1225 return alt[which_alternative]; 1226} 1227 [(set_attr "length" "8") 1228 (set_attr "type" "arith3")]) 1229 1230(define_insn "cmpgedi_t" 1231 [(set (reg:SI T_REG) 1232 (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r") 1233 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))] 1234 "TARGET_SH2" 1235{ 1236 static const char* alt[] = 1237 { 1238 "cmp/eq %S1,%S0" "\n" 1239 " bf{.|/}s 0f" "\n" 1240 " cmp/ge %S1,%S0" "\n" 1241 " cmp/hs %R1,%R0" "\n" 1242 "0:", 1243 1244 "cmp/pz %S0" 1245 }; 1246 return alt[which_alternative]; 1247} 1248 [(set_attr "length" "8,2") 1249 (set_attr "type" "arith3,mt_group")]) 1250 1251;; ------------------------------------------------------------------------- 1252;; DImode unsigned integer comparisons 1253;; ------------------------------------------------------------------------- 1254 1255(define_insn "cmpgeudi_t" 1256 [(set (reg:SI T_REG) 1257 (geu:SI (match_operand:DI 0 "arith_reg_operand" "r") 1258 (match_operand:DI 1 "arith_reg_operand" "r")))] 1259 "TARGET_SH2" 1260{ 1261 return "cmp/eq %S1,%S0" "\n" 1262 " bf{.|/}s 0f" "\n" 1263 " cmp/hs %S1,%S0" "\n" 1264 " cmp/hs %R1,%R0" "\n" 1265 "0:"; 1266} 1267 [(set_attr "length" "8") 1268 (set_attr "type" "arith3")]) 1269 1270(define_insn "cmpgtudi_t" 1271 [(set (reg:SI T_REG) 1272 (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r") 1273 (match_operand:DI 1 "arith_reg_operand" "r")))] 1274 "TARGET_SH2" 1275{ 1276 return "cmp/eq %S1,%S0" "\n" 1277 " bf{.|/}s 0f" "\n" 1278 " cmp/hi %S1,%S0" "\n" 1279 " cmp/hi %R1,%R0" "\n" 1280 "0:"; 1281} 1282 [(set_attr "length" "8") 1283 (set_attr "type" "arith3")]) 1284 1285(define_insn "cmpeqsi_media" 1286 [(set (match_operand:SI 0 "register_operand" "=r") 1287 (eq:SI (match_operand:SI 1 "logical_operand" "%r") 1288 (match_operand:SI 2 "cmp_operand" "Nr")))] 1289 "TARGET_SHMEDIA" 1290 "cmpeq %1, %N2, %0" 1291 [(set_attr "type" "cmp_media")]) 1292 1293(define_insn "cmpeqdi_media" 1294 [(set (match_operand:SI 0 "register_operand" "=r") 1295 (eq:SI (match_operand:DI 1 "register_operand" "%r") 1296 (match_operand:DI 2 "cmp_operand" "Nr")))] 1297 "TARGET_SHMEDIA" 1298 "cmpeq %1, %N2, %0" 1299 [(set_attr "type" "cmp_media")]) 1300 1301(define_insn "cmpgtsi_media" 1302 [(set (match_operand:SI 0 "register_operand" "=r") 1303 (gt:SI (match_operand:SI 1 "cmp_operand" "Nr") 1304 (match_operand:SI 2 "cmp_operand" "rN")))] 1305 "TARGET_SHMEDIA" 1306 "cmpgt %N1, %N2, %0" 1307 [(set_attr "type" "cmp_media")]) 1308 1309(define_insn "cmpgtdi_media" 1310 [(set (match_operand:SI 0 "register_operand" "=r") 1311 (gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr") 1312 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))] 1313 "TARGET_SHMEDIA" 1314 "cmpgt %N1, %N2, %0" 1315 [(set_attr "type" "cmp_media")]) 1316 1317(define_insn "cmpgtusi_media" 1318 [(set (match_operand:SI 0 "register_operand" "=r") 1319 (gtu:SI (match_operand:SI 1 "cmp_operand" "Nr") 1320 (match_operand:SI 2 "cmp_operand" "rN")))] 1321 "TARGET_SHMEDIA" 1322 "cmpgtu %N1, %N2, %0" 1323 [(set_attr "type" "cmp_media")]) 1324 1325(define_insn "cmpgtudi_media" 1326 [(set (match_operand:SI 0 "register_operand" "=r") 1327 (gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr") 1328 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))] 1329 "TARGET_SHMEDIA" 1330 "cmpgtu %N1, %N2, %0" 1331 [(set_attr "type" "cmp_media")]) 1332 1333; This pattern is for combine. 1334(define_insn "*cmpne0sisi_media" 1335 [(set (match_operand:SI 0 "register_operand" "=r") 1336 (ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))] 1337 "TARGET_SHMEDIA" 1338 "cmpgtu %1,r63,%0" 1339 [(set_attr "type" "cmp_media")]) 1340 1341;; ------------------------------------------------------------------------- 1342;; Conditional move instructions 1343;; ------------------------------------------------------------------------- 1344 1345;; The insn names may seem reversed, but note that cmveq performs the move 1346;; if op1 == 0, and cmvne does it if op1 != 0. 1347 1348(define_insn "movdicc_false" 1349 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 1350 (if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r") 1351 (const_int 0)) 1352 (match_operand:DI 2 "arith_reg_or_0_operand" "rN") 1353 (match_operand:DI 3 "arith_reg_operand" "0")))] 1354 "TARGET_SHMEDIA" 1355 "cmveq %1, %N2, %0" 1356 [(set_attr "type" "arith_media")]) 1357 1358(define_insn "movdicc_true" 1359 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 1360 (if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r") 1361 (const_int 0)) 1362 (match_operand:DI 2 "arith_reg_or_0_operand" "rN") 1363 (match_operand:DI 3 "arith_reg_operand" "0")))] 1364 "TARGET_SHMEDIA" 1365 "cmvne %1, %N2, %0" 1366 [(set_attr "type" "arith_media")]) 1367 1368(define_peephole2 1369 [(set (match_operand:DI 0 "arith_reg_dest" "") 1370 (if_then_else:DI (match_operator 3 "equality_comparison_operator" 1371 [(match_operand:DI 1 "arith_reg_operand" "") 1372 (const_int 0)]) 1373 (match_operand:DI 2 "arith_reg_dest" "") 1374 (match_dup 0))) 1375 (set (match_dup 2) (match_dup 0))] 1376 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])" 1377 [(set (match_dup 2) 1378 (if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))] 1379{ 1380 operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])), 1381 VOIDmode, operands[1], CONST0_RTX (DImode)); 1382}) 1383 1384(define_peephole2 1385 [(set (match_operand:DI 0 "general_movdst_operand" "") 1386 (match_operand:DI 1 "arith_reg_or_0_operand" "")) 1387 (set (match_operand:DI 2 "arith_reg_dest" "") 1388 (if_then_else:DI (match_operator 4 "equality_comparison_operator" 1389 [(match_operand:DI 3 "arith_reg_operand" "") 1390 (const_int 0)]) 1391 (match_dup 0) 1392 (match_dup 2)))] 1393 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])" 1394 [(set (match_dup 2) 1395 (if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))] 1396 "") 1397 1398(define_expand "movdicc" 1399 [(set (match_operand:DI 0 "register_operand" "") 1400 (if_then_else:DI (match_operand 1 "comparison_operator" "") 1401 (match_operand:DI 2 "register_operand" "") 1402 (match_operand:DI 3 "register_operand" "")))] 1403 "TARGET_SHMEDIA" 1404{ 1405 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE) 1406 && GET_MODE (XEXP (operands[1], 0)) == DImode 1407 && XEXP (operands[1], 1) == const0_rtx) 1408 ; 1409 else 1410 { 1411 if (!can_create_pseudo_p ()) 1412 FAIL; 1413 1414 operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]), 1415 GET_CODE (operands[1]), 1416 XEXP (operands[1], 0), 1417 XEXP (operands[1], 1)); 1418 if (!operands[1]) 1419 FAIL; 1420 } 1421}) 1422 1423;; Add SImode variants for cmveq / cmvne to compensate for not promoting 1424;; SImode to DImode. 1425(define_insn "movsicc_false" 1426 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 1427 (if_then_else:SI (eq (match_operand:SI 1 "arith_reg_operand" "r") 1428 (const_int 0)) 1429 (match_operand:SI 2 "arith_reg_or_0_operand" "rN") 1430 (match_operand:SI 3 "arith_reg_operand" "0")))] 1431 "TARGET_SHMEDIA" 1432 "cmveq %1, %N2, %0" 1433 [(set_attr "type" "arith_media")]) 1434 1435(define_insn "movsicc_true" 1436 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 1437 (if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r") 1438 (const_int 0)) 1439 (match_operand:SI 2 "arith_reg_or_0_operand" "rN") 1440 (match_operand:SI 3 "arith_reg_operand" "0")))] 1441 "TARGET_SHMEDIA" 1442 "cmvne %1, %N2, %0" 1443 [(set_attr "type" "arith_media")]) 1444 1445(define_peephole2 1446 [(set (match_operand:SI 0 "arith_reg_dest" "") 1447 (if_then_else:SI (match_operator 3 "equality_comparison_operator" 1448 [(match_operand:SI 1 "arith_reg_operand" "") 1449 (const_int 0)]) 1450 (match_operand:SI 2 "arith_reg_dest" "") 1451 (match_dup 0))) 1452 (set (match_dup 2) (match_dup 0))] 1453 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])" 1454 [(set (match_dup 2) 1455 (if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))] 1456{ 1457 operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])), 1458 VOIDmode, operands[1], CONST0_RTX (SImode)); 1459}) 1460 1461(define_peephole2 1462 [(set (match_operand:SI 0 "general_movdst_operand" "") 1463 (match_operand:SI 1 "arith_reg_or_0_operand" "")) 1464 (set (match_operand:SI 2 "arith_reg_dest" "") 1465 (if_then_else:SI (match_operator 4 "equality_comparison_operator" 1466 [(match_operand:SI 3 "arith_reg_operand" "") 1467 (const_int 0)]) 1468 (match_dup 0) 1469 (match_dup 2)))] 1470 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0]) 1471 && (!REG_P (operands[1]) || GENERAL_REGISTER_P (REGNO (operands[1])))" 1472 [(set (match_dup 2) 1473 (if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))] 1474{ 1475 replace_rtx (operands[4], operands[0], operands[1]); 1476}) 1477 1478(define_peephole2 1479 [(set (match_operand 0 "any_register_operand" "") 1480 (match_operand 1 "any_register_operand" "")) 1481 (set (match_operand 2 "any_register_operand" "") (match_operand 3 "" "")) 1482 (set (match_operand 4 "" "") (match_operand 5 "" ""))] 1483 "(HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[2])) 1484 <= HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[0]))) 1485 && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[2]) 1486 && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[0]) 1487 && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[2]) 1488 && ! reg_overlap_mentioned_p (operands[0], operands[3]) 1489 && ! reg_overlap_mentioned_p (operands[2], operands[0]) 1490 && ! reg_overlap_mentioned_p (operands[0], operands[1]) 1491 && (REGNO_REG_CLASS (REGNO (operands[0])) 1492 == REGNO_REG_CLASS (REGNO (operands[2]))) 1493 && (REGNO_REG_CLASS (REGNO (operands[1])) 1494 == REGNO_REG_CLASS (REGNO (operands[0])))" 1495 [(set (match_dup 0) (match_dup 3)) 1496 (set (match_dup 4) (match_dup 5))] 1497{ 1498 rtx set1, set2, insn2; 1499 rtx replacements[4]; 1500 1501 /* We want to replace occurrences of operands[0] with operands[1] and 1502 operands[2] with operands[0] in operands[4]/operands[5]. 1503 Doing just two replace_rtx calls naively would result in the second 1504 replacement undoing all that the first did if operands[1] and operands[2] 1505 are identical, so we must do this simultaneously. */ 1506 replacements[0] = operands[0]; 1507 replacements[1] = operands[1]; 1508 replacements[2] = operands[2]; 1509 replacements[3] = operands[0]; 1510 if (!replace_n_hard_rtx (operands[5], replacements, 2, 0) 1511 || !replace_n_hard_rtx (operands[4], replacements, 2, 0) 1512 || !replace_n_hard_rtx (operands[2], replacements, 2, 0)) 1513 FAIL; 1514 1515 operands[5] = replace_n_hard_rtx (operands[5], replacements, 2, 1); 1516 replace_n_hard_rtx (operands[4], replacements, 2, 1); 1517 operands[2] = replace_n_hard_rtx (operands[2], replacements, 2, 1); 1518 /* The operands array is aliased to recog_data.operand, which gets 1519 clobbered by extract_insn, so finish with it now. */ 1520 set1 = gen_rtx_SET (VOIDmode, operands[2], operands[3]); 1521 set2 = gen_rtx_SET (VOIDmode, operands[4], operands[5]); 1522 /* ??? The last insn might be a jump insn, but the generic peephole2 code 1523 always uses emit_insn. */ 1524 /* Check that we don't violate matching constraints or earlyclobbers. */ 1525 extract_insn (emit_insn (set1)); 1526 if (! constrain_operands (1)) 1527 goto failure; 1528 insn2 = emit (set2); 1529 if (GET_CODE (insn2) == BARRIER) 1530 goto failure; 1531 extract_insn (insn2); 1532 if (! constrain_operands (1)) 1533 { 1534 rtx tmp; 1535 failure: 1536 tmp = replacements[0]; 1537 replacements[0] = replacements[1]; 1538 replacements[1] = tmp; 1539 tmp = replacements[2]; 1540 replacements[2] = replacements[3]; 1541 replacements[3] = tmp; 1542 replace_n_hard_rtx (SET_DEST (set1), replacements, 2, 1); 1543 replace_n_hard_rtx (SET_DEST (set2), replacements, 2, 1); 1544 replace_n_hard_rtx (SET_SRC (set2), replacements, 2, 1); 1545 FAIL; 1546 } 1547 DONE; 1548}) 1549 1550;; The register allocator is rather clumsy in handling multi-way conditional 1551;; moves, so allow the combiner to make them, and we split them up after 1552;; reload. */ 1553(define_insn_and_split "*movsicc_umin" 1554 [(set (match_operand:SI 0 "arith_reg_dest" "=&r") 1555 (umin:SI (if_then_else:SI 1556 (eq (match_operand:SI 1 "arith_reg_operand" "r") 1557 (const_int 0)) 1558 (match_operand:SI 2 "arith_reg_or_0_operand" "rN") 1559 (match_operand:SI 3 "register_operand" "0")) 1560 (match_operand:SI 4 "arith_reg_or_0_operand" "r"))) 1561 (clobber (match_scratch:SI 5 "=&r"))] 1562 "TARGET_SHMEDIA && !can_create_pseudo_p ()" 1563 "#" 1564 "TARGET_SHMEDIA && reload_completed" 1565 [(pc)] 1566{ 1567 emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2], 1568 operands[3])); 1569 emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0])); 1570 emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4], 1571 operands[0])); 1572 DONE; 1573}) 1574 1575(define_insn "*movsicc_t_false" 1576 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 1577 (if_then_else (eq (reg:SI T_REG) (const_int 0)) 1578 (match_operand:SI 1 "general_movsrc_operand" "r,I08") 1579 (match_operand:SI 2 "arith_reg_operand" "0,0")))] 1580 "TARGET_PRETEND_CMOVE 1581 && (arith_reg_operand (operands[1], SImode) 1582 || (immediate_operand (operands[1], SImode) 1583 && satisfies_constraint_I08 (operands[1])))" 1584{ 1585 return "bt 0f" "\n" 1586 " mov %1,%0" "\n" 1587 "0:"; 1588} 1589 [(set_attr "type" "mt_group,arith") ;; poor approximation 1590 (set_attr "length" "4")]) 1591 1592(define_insn "*movsicc_t_true" 1593 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 1594 (if_then_else (ne (reg:SI T_REG) (const_int 0)) 1595 (match_operand:SI 1 "general_movsrc_operand" "r,I08") 1596 (match_operand:SI 2 "arith_reg_operand" "0,0")))] 1597 "TARGET_PRETEND_CMOVE 1598 && (arith_reg_operand (operands[1], SImode) 1599 || (immediate_operand (operands[1], SImode) 1600 && satisfies_constraint_I08 (operands[1])))" 1601{ 1602 return "bf 0f" "\n" 1603 " mov %1,%0" "\n" 1604 "0:"; 1605} 1606 [(set_attr "type" "mt_group,arith") ;; poor approximation 1607 (set_attr "length" "4")]) 1608 1609(define_expand "movsicc" 1610 [(set (match_operand:SI 0 "arith_reg_dest" "") 1611 (if_then_else:SI (match_operand 1 "comparison_operator" "") 1612 (match_operand:SI 2 "arith_reg_or_0_operand" "") 1613 (match_operand:SI 3 "arith_reg_operand" "")))] 1614 "TARGET_SHMEDIA || TARGET_PRETEND_CMOVE" 1615{ 1616 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE) 1617 && GET_MODE (XEXP (operands[1], 0)) == SImode 1618 && (TARGET_SHMEDIA 1619 || (REG_P (XEXP (operands[1], 0)) 1620 && REGNO (XEXP (operands[1], 0)) == T_REG)) 1621 && XEXP (operands[1], 1) == const0_rtx) 1622 ; 1623 1624 else if (TARGET_PRETEND_CMOVE) 1625 { 1626 enum rtx_code code = GET_CODE (operands[1]); 1627 enum rtx_code new_code = code; 1628 rtx op0 = XEXP (operands[1], 0); 1629 rtx op1 = XEXP (operands[1], 1); 1630 1631 if (! currently_expanding_to_rtl) 1632 FAIL; 1633 switch (code) 1634 { 1635 case LT: case LE: case LEU: case LTU: 1636 if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_INT) 1637 break; 1638 case NE: 1639 new_code = reverse_condition (code); 1640 break; 1641 case EQ: case GT: case GE: case GEU: case GTU: 1642 break; 1643 default: 1644 FAIL; 1645 } 1646 sh_emit_scc_to_t (new_code, op0, op1); 1647 operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode, 1648 gen_rtx_REG (SImode, T_REG), const0_rtx); 1649 } 1650 else 1651 { 1652 if (!can_create_pseudo_p ()) 1653 FAIL; 1654 1655 operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]), 1656 GET_CODE (operands[1]), 1657 XEXP (operands[1], 0), 1658 XEXP (operands[1], 1)); 1659 if (!operands[1]) 1660 FAIL; 1661 } 1662}) 1663 1664(define_expand "movqicc" 1665 [(set (match_operand:QI 0 "register_operand" "") 1666 (if_then_else:QI (match_operand 1 "comparison_operator" "") 1667 (match_operand:QI 2 "register_operand" "") 1668 (match_operand:QI 3 "register_operand" "")))] 1669 "TARGET_SHMEDIA" 1670{ 1671 operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0); 1672 operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0); 1673 operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0); 1674 emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3])); 1675 DONE; 1676}) 1677 1678;; ------------------------------------------------------------------------- 1679;; Addition instructions 1680;; ------------------------------------------------------------------------- 1681 1682(define_expand "adddi3" 1683 [(set (match_operand:DI 0 "arith_reg_operand" "") 1684 (plus:DI (match_operand:DI 1 "arith_reg_operand" "") 1685 (match_operand:DI 2 "arith_operand" "")))] 1686 "" 1687{ 1688 if (TARGET_SH1) 1689 { 1690 if (!can_create_pseudo_p () && ! arith_reg_operand (operands[2], DImode)) 1691 FAIL; 1692 operands[2] = force_reg (DImode, operands[2]); 1693 emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2])); 1694 DONE; 1695 } 1696}) 1697 1698(define_insn "*adddi3_media" 1699 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") 1700 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r") 1701 (match_operand:DI 2 "arith_operand" "r,I10")))] 1702 "TARGET_SHMEDIA" 1703 "@ 1704 add %1, %2, %0 1705 addi %1, %2, %0" 1706 [(set_attr "type" "arith_media")]) 1707 1708(define_insn "*adddisi3_media" 1709 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0) 1710 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r") 1711 (match_operand:DI 2 "arith_operand" "r,I10")))] 1712 "TARGET_SHMEDIA" 1713 "@ 1714 add.l %1, %2, %0 1715 addi.l %1, %2, %0" 1716 [(set_attr "type" "arith_media") 1717 (set_attr "highpart" "ignore")]) 1718 1719(define_insn "adddi3z_media" 1720 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 1721 (zero_extend:DI 1722 (plus:SI (match_operand:SI 1 "extend_reg_operand" "r") 1723 (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))] 1724 "TARGET_SHMEDIA" 1725 "addz.l %1, %N2, %0" 1726 [(set_attr "type" "arith_media") 1727 (set_attr "highpart" "ignore")]) 1728 1729(define_insn_and_split "adddi3_compact" 1730 [(set (match_operand:DI 0 "arith_reg_dest" "=&r") 1731 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0") 1732 (match_operand:DI 2 "arith_reg_operand" "r"))) 1733 (clobber (reg:SI T_REG))] 1734 "TARGET_SH1" 1735 "#" 1736 "&& reload_completed" 1737 [(const_int 0)] 1738{ 1739 rtx high0 = gen_highpart (SImode, operands[0]); 1740 rtx high2 = gen_highpart (SImode, operands[2]); 1741 rtx low0 = gen_lowpart (SImode, operands[0]); 1742 1743 emit_insn (gen_clrt ()); 1744 emit_insn (gen_addc (low0, low0, gen_lowpart (SImode, operands[2]))); 1745 emit_insn (gen_addc (high0, high0, high2)); 1746 DONE; 1747}) 1748 1749(define_insn "addc" 1750 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 1751 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0") 1752 (match_operand:SI 2 "arith_reg_operand" "r")) 1753 (reg:SI T_REG))) 1754 (set (reg:SI T_REG) 1755 (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))] 1756 "TARGET_SH1" 1757 "addc %2,%0" 1758 [(set_attr "type" "arith")]) 1759 1760;; A simplified version of the addc insn, where the exact value of the 1761;; T bit doesn't matter. This is easier for combine to pick up. 1762;; We allow a reg or 0 for one of the operands in order to be able to 1763;; do 'reg + T' sequences. Reload will load the constant 0 into the reg 1764;; as needed. 1765(define_insn "*addc" 1766 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 1767 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0") 1768 (match_operand:SI 2 "arith_reg_or_0_operand" "r")) 1769 (match_operand:SI 3 "t_reg_operand" ""))) 1770 (clobber (reg:SI T_REG))] 1771 "TARGET_SH1" 1772 "addc %2,%0" 1773 [(set_attr "type" "arith")]) 1774 1775;; Split 'reg + reg + 1' into a sett addc sequence, as it can be scheduled 1776;; better, if the sett insn can be done early. 1777(define_insn_and_split "*addc" 1778 [(set (match_operand:SI 0 "arith_reg_dest" "") 1779 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "") 1780 (match_operand:SI 2 "arith_reg_operand" "")) 1781 (const_int 1))) 1782 (clobber (reg:SI T_REG))] 1783 "TARGET_SH1" 1784 "#" 1785 "&& 1" 1786 [(set (reg:SI T_REG) (const_int 1)) 1787 (parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (match_dup 2)) 1788 (reg:SI T_REG))) 1789 (clobber (reg:SI T_REG))])]) 1790 1791;; Left shifts by one are usually done with an add insn to avoid T_REG 1792;; clobbers. Thus addc can also be used to do something like '(x << 1) + 1'. 1793(define_insn_and_split "*addc" 1794 [(set (match_operand:SI 0 "arith_reg_dest") 1795 (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand") 1796 (const_int 2)) 1797 (const_int 1))) 1798 (clobber (reg:SI T_REG))] 1799 "TARGET_SH1" 1800 "#" 1801 "&& 1" 1802 [(set (reg:SI T_REG) (const_int 1)) 1803 (parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (match_dup 1)) 1804 (reg:SI T_REG))) 1805 (clobber (reg:SI T_REG))])]) 1806 1807;; Sometimes combine will try to do 'reg + (0-reg) + 1' if the *addc pattern 1808;; matched. Split this up into a simple sub add sequence, as this will save 1809;; us one sett insn. 1810(define_insn_and_split "*minus_plus_one" 1811 [(set (match_operand:SI 0 "arith_reg_dest" "") 1812 (plus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "") 1813 (match_operand:SI 2 "arith_reg_operand" "")) 1814 (const_int 1)))] 1815 "TARGET_SH1" 1816 "#" 1817 "&& 1" 1818 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2))) 1819 (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))]) 1820 1821;; Split 'reg + T' into 'reg + 0 + T' to utilize the addc insn. 1822;; If the 0 constant can be CSE-ed, this becomes a one instruction 1823;; operation, as opposed to sequences such as 1824;; movt r2 1825;; add r2,r3 1826;; 1827;; Even if the constant is not CSE-ed, a sequence such as 1828;; mov #0,r2 1829;; addc r2,r3 1830;; can be scheduled much better since the load of the constant can be 1831;; done earlier, before any comparison insns that store the result in 1832;; the T bit. 1833(define_insn_and_split "*addc" 1834 [(set (match_operand:SI 0 "arith_reg_dest" "") 1835 (plus:SI (match_operand:SI 1 "t_reg_operand" "") 1836 (match_operand:SI 2 "arith_reg_operand" ""))) 1837 (clobber (reg:SI T_REG))] 1838 "TARGET_SH1" 1839 "#" 1840 "&& 1" 1841 [(parallel [(set (match_dup 0) 1842 (plus:SI (plus:SI (match_dup 2) (const_int 0)) 1843 (match_dup 1))) 1844 (clobber (reg:SI T_REG))])]) 1845 1846(define_expand "addsi3" 1847 [(set (match_operand:SI 0 "arith_reg_operand" "") 1848 (plus:SI (match_operand:SI 1 "arith_operand" "") 1849 (match_operand:SI 2 "arith_operand" "")))] 1850 "" 1851{ 1852 if (TARGET_SHMEDIA) 1853 operands[1] = force_reg (SImode, operands[1]); 1854}) 1855 1856(define_insn "addsi3_media" 1857 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 1858 (plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r") 1859 (match_operand:SI 2 "arith_operand" "r,I10")))] 1860 "TARGET_SHMEDIA" 1861 "@ 1862 add.l %1, %2, %0 1863 addi.l %1, %2, %0" 1864 [(set_attr "type" "arith_media") 1865 (set_attr "highpart" "ignore")]) 1866 1867(define_insn "addsidi3_media" 1868 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") 1869 (sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand" 1870 "%r,r") 1871 (match_operand:SI 2 "arith_operand" 1872 "r,I10"))))] 1873 "TARGET_SHMEDIA" 1874 "@ 1875 add.l %1, %2, %0 1876 addi.l %1, %2, %0" 1877 [(set_attr "type" "arith_media") 1878 (set_attr "highpart" "ignore")]) 1879 1880(define_insn "*addsi3_compact" 1881 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 1882 (plus:SI (match_operand:SI 1 "arith_operand" "%0") 1883 (match_operand:SI 2 "arith_operand" "rI08")))] 1884 "TARGET_SH1" 1885 "add %2,%0" 1886 [(set_attr "type" "arith")]) 1887 1888;; ------------------------------------------------------------------------- 1889;; Subtraction instructions 1890;; ------------------------------------------------------------------------- 1891 1892(define_expand "subdi3" 1893 [(set (match_operand:DI 0 "arith_reg_operand" "") 1894 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "") 1895 (match_operand:DI 2 "arith_reg_operand" "")))] 1896 "" 1897{ 1898 if (TARGET_SH1) 1899 { 1900 operands[1] = force_reg (DImode, operands[1]); 1901 emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2])); 1902 DONE; 1903 } 1904}) 1905 1906(define_insn "*subdi3_media" 1907 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 1908 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN") 1909 (match_operand:DI 2 "arith_reg_operand" "r")))] 1910 "TARGET_SHMEDIA" 1911 "sub %N1, %2, %0" 1912 [(set_attr "type" "arith_media")]) 1913 1914(define_insn "subdisi3_media" 1915 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0) 1916 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN") 1917 (match_operand:DI 2 "arith_reg_operand" "r")))] 1918 "TARGET_SHMEDIA" 1919 "sub.l %N1, %2, %0" 1920 [(set_attr "type" "arith_media") 1921 (set_attr "highpart" "ignore")]) 1922 1923(define_insn_and_split "subdi3_compact" 1924 [(set (match_operand:DI 0 "arith_reg_dest" "=&r") 1925 (minus:DI (match_operand:DI 1 "arith_reg_operand" "0") 1926 (match_operand:DI 2 "arith_reg_operand" "r"))) 1927 (clobber (reg:SI T_REG))] 1928 "TARGET_SH1" 1929 "#" 1930 "&& reload_completed" 1931 [(const_int 0)] 1932{ 1933 rtx high0 = gen_highpart (SImode, operands[0]); 1934 rtx high2 = gen_highpart (SImode, operands[2]); 1935 rtx low0 = gen_lowpart (SImode, operands[0]); 1936 1937 emit_insn (gen_clrt ()); 1938 emit_insn (gen_subc (low0, low0, gen_lowpart (SImode, operands[2]))); 1939 emit_insn (gen_subc (high0, high0, high2)); 1940 DONE; 1941}) 1942 1943(define_insn "subc" 1944 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 1945 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0") 1946 (match_operand:SI 2 "arith_reg_operand" "r")) 1947 (reg:SI T_REG))) 1948 (set (reg:SI T_REG) 1949 (gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2)) 1950 (reg:SI T_REG)) 1951 (match_dup 1)))] 1952 "TARGET_SH1" 1953 "subc %2,%0" 1954 [(set_attr "type" "arith")]) 1955 1956;; A simplified version of the subc insn, where the exact value of the 1957;; T bit doesn't matter. This is easier for combine to pick up. 1958;; We allow a reg or 0 for one of the operands in order to be able to 1959;; do 'reg - T' sequences. Reload will load the constant 0 into the reg 1960;; as needed. 1961(define_insn "*subc" 1962 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 1963 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0") 1964 (match_operand:SI 2 "arith_reg_or_0_operand" "r")) 1965 (match_operand:SI 3 "t_reg_operand" ""))) 1966 (clobber (reg:SI T_REG))] 1967 "TARGET_SH1" 1968 "subc %2,%0" 1969 [(set_attr "type" "arith")]) 1970 1971;; Split reg - reg - 1 into a sett subc sequence, as it can be scheduled 1972;; better, if the sett insn can be done early. 1973;; Notice that combine turns 'a - b - 1' into 'a + (~b)'. 1974(define_insn_and_split "*subc" 1975 [(set (match_operand:SI 0 "arith_reg_dest" "") 1976 (plus:SI (not:SI (match_operand:SI 1 "arith_reg_operand" "")) 1977 (match_operand:SI 2 "arith_reg_operand" ""))) 1978 (clobber (reg:SI T_REG))] 1979 "TARGET_SH1" 1980 "#" 1981 "&& 1" 1982 [(set (reg:SI T_REG) (const_int 1)) 1983 (parallel [(set (match_dup 0) 1984 (minus:SI (minus:SI (match_dup 2) (match_dup 1)) 1985 (reg:SI T_REG))) 1986 (clobber (reg:SI T_REG))])]) 1987 1988;; Split 'reg - T' into 'reg - 0 - T' to utilize the subc insn. 1989;; If the 0 constant can be CSE-ed, this becomes a one instruction 1990;; operation, as opposed to sequences such as 1991;; movt r2 1992;; sub r2,r3 1993;; 1994;; Even if the constant is not CSE-ed, a sequence such as 1995;; mov #0,r2 1996;; subc r2,r3 1997;; can be scheduled much better since the load of the constant can be 1998;; done earlier, before any comparison insns that store the result in 1999;; the T bit. 2000(define_insn_and_split "*subc" 2001 [(set (match_operand:SI 0 "arith_reg_dest" "") 2002 (minus:SI (match_operand:SI 1 "arith_reg_operand" "") 2003 (match_operand:SI 2 "t_reg_operand" ""))) 2004 (clobber (reg:SI T_REG))] 2005 "TARGET_SH1" 2006 "#" 2007 "&& 1" 2008 [(parallel [(set (match_dup 0) 2009 (minus:SI (minus:SI (match_dup 1) (const_int 0)) 2010 (match_dup 2))) 2011 (clobber (reg:SI T_REG))])]) 2012 2013(define_insn "*subsi3_internal" 2014 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 2015 (minus:SI (match_operand:SI 1 "arith_reg_operand" "0") 2016 (match_operand:SI 2 "arith_reg_operand" "r")))] 2017 "TARGET_SH1" 2018 "sub %2,%0" 2019 [(set_attr "type" "arith")]) 2020 2021(define_insn_and_split "*subsi3_media" 2022 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 2023 (minus:SI (match_operand:SI 1 "minuend_operand" "rN") 2024 (match_operand:SI 2 "extend_reg_operand" "r")))] 2025 "TARGET_SHMEDIA 2026 && (operands[1] != constm1_rtx 2027 || (GET_CODE (operands[2]) != TRUNCATE 2028 && GET_CODE (operands[2]) != SUBREG))" 2029 "sub.l %N1, %2, %0" 2030 "operands[1] == constm1_rtx" 2031 [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))] 2032 "" 2033 [(set_attr "type" "arith_media") 2034 (set_attr "highpart" "ignore")]) 2035 2036(define_split 2037 [(set (match_operand:SI 0 "arith_reg_dest" "") 2038 (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1 2039 "general_extend_operand" 2040 "") 0)) 0)))] 2041 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN" 2042 [(set (match_dup 0) (zero_extend:SI (match_dup 1))) 2043 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))] 2044 "") 2045 2046(define_split 2047 [(set (match_operand:SI 0 "arith_reg_dest" "") 2048 (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1 2049 "general_extend_operand" 2050 "") 0)) 3)))] 2051 "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN" 2052 [(set (match_dup 0) (zero_extend:SI (match_dup 1))) 2053 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))] 2054 "") 2055 2056;; Convert 2057;; constant - reg 2058;; to 2059;; neg reg 2060;; add reg, #const 2061;; since this will sometimes save one instruction. 2062;; Otherwise we might get a sequence like 2063;; mov #const, rY 2064;; sub rY, rX 2065;; mov rX, rY 2066;; if the source and dest regs are the same. 2067(define_expand "subsi3" 2068 [(set (match_operand:SI 0 "arith_reg_operand" "") 2069 (minus:SI (match_operand:SI 1 "arith_operand" "") 2070 (match_operand:SI 2 "arith_reg_operand" "")))] 2071 "" 2072{ 2073 if (TARGET_SH1 && CONST_INT_P (operands[1])) 2074 { 2075 emit_insn (gen_negsi2 (operands[0], operands[2])); 2076 emit_insn (gen_addsi3 (operands[0], operands[0], operands[1])); 2077 DONE; 2078 } 2079 if (TARGET_SHMEDIA) 2080 { 2081 if (!can_create_pseudo_p () 2082 && ! arith_reg_or_0_operand (operands[1], SImode)) 2083 FAIL; 2084 if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG) 2085 operands[1] = force_reg (SImode, operands[1]); 2086 } 2087}) 2088 2089;; ------------------------------------------------------------------------- 2090;; Division instructions 2091;; ------------------------------------------------------------------------- 2092 2093;; We take advantage of the library routines which don't clobber as many 2094;; registers as a normal function call would. 2095 2096;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it 2097;; also has an effect on the register that holds the address of the sfunc. 2098;; To make this work, we have an extra dummy insn that shows the use 2099;; of this register for reorg. 2100 2101(define_insn "use_sfunc_addr" 2102 [(set (reg:SI PR_REG) 2103 (unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))] 2104 "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])" 2105 "" 2106 [(set_attr "length" "0")]) 2107 2108(define_insn "udivsi3_sh2a" 2109 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 2110 (udiv:SI (match_operand:SI 1 "arith_reg_operand" "0") 2111 (match_operand:SI 2 "arith_reg_operand" "z")))] 2112 "TARGET_SH2A" 2113 "divu %2,%1" 2114 [(set_attr "type" "arith") 2115 (set_attr "in_delay_slot" "no")]) 2116 2117;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than 2118;; hard register 0. If we used hard register 0, then the next instruction 2119;; would be a move from hard register 0 to a pseudo-reg. If the pseudo-reg 2120;; gets allocated to a stack slot that needs its address reloaded, then 2121;; there is nothing to prevent reload from using r0 to reload the address. 2122;; This reload would clobber the value in r0 we are trying to store. 2123;; If we let reload allocate r0, then this problem can never happen. 2124(define_insn "udivsi3_i1" 2125 [(set (match_operand:SI 0 "register_operand" "=z") 2126 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2127 (clobber (reg:SI T_REG)) 2128 (clobber (reg:SI PR_REG)) 2129 (clobber (reg:SI R1_REG)) 2130 (clobber (reg:SI R4_REG)) 2131 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 2132 "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1" 2133 "jsr @%1%#" 2134 [(set_attr "type" "sfunc") 2135 (set_attr "needs_delay_slot" "yes")]) 2136 2137; Since shmedia-nofpu code could be linked against shcompact code, and 2138; the udivsi3 libcall has the same name, we must consider all registers 2139; clobbered that are in the union of the registers clobbered by the 2140; shmedia and the shcompact implementation. Note, if the shcompact 2141; implementation actually used shcompact code, we'd need to clobber 2142; also r23 and fr23. 2143(define_insn "udivsi3_i1_media" 2144 [(set (match_operand:SI 0 "register_operand" "=z") 2145 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2146 (clobber (reg:SI T_MEDIA_REG)) 2147 (clobber (reg:SI PR_MEDIA_REG)) 2148 (clobber (reg:SI R20_REG)) 2149 (clobber (reg:SI R21_REG)) 2150 (clobber (reg:SI R22_REG)) 2151 (clobber (reg:DI TR0_REG)) 2152 (clobber (reg:DI TR1_REG)) 2153 (clobber (reg:DI TR2_REG)) 2154 (use (match_operand 1 "target_reg_operand" "b"))] 2155 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)" 2156 "blink %1, r18" 2157 [(set_attr "type" "sfunc") 2158 (set_attr "needs_delay_slot" "yes")]) 2159 2160(define_expand "udivsi3_i4_media" 2161 [(set (match_dup 3) 2162 (zero_extend:DI (match_operand:SI 1 "register_operand" ""))) 2163 (set (match_dup 4) 2164 (zero_extend:DI (match_operand:SI 2 "register_operand" ""))) 2165 (set (match_dup 5) (float:DF (match_dup 3))) 2166 (set (match_dup 6) (float:DF (match_dup 4))) 2167 (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6))) 2168 (set (match_dup 8) (fix:DI (match_dup 7))) 2169 (set (match_operand:SI 0 "register_operand" "") 2170 (truncate:SI (match_dup 8)))] 2171 "TARGET_SHMEDIA_FPU" 2172{ 2173 operands[3] = gen_reg_rtx (DImode); 2174 operands[4] = gen_reg_rtx (DImode); 2175 operands[5] = gen_reg_rtx (DFmode); 2176 operands[6] = gen_reg_rtx (DFmode); 2177 operands[7] = gen_reg_rtx (DFmode); 2178 operands[8] = gen_reg_rtx (DImode); 2179}) 2180 2181(define_insn "udivsi3_i4" 2182 [(set (match_operand:SI 0 "register_operand" "=y") 2183 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2184 (clobber (reg:SI T_REG)) 2185 (clobber (reg:SI PR_REG)) 2186 (clobber (reg:DF DR0_REG)) 2187 (clobber (reg:DF DR2_REG)) 2188 (clobber (reg:DF DR4_REG)) 2189 (clobber (reg:SI R0_REG)) 2190 (clobber (reg:SI R1_REG)) 2191 (clobber (reg:SI R4_REG)) 2192 (clobber (reg:SI R5_REG)) 2193 (use (reg:PSI FPSCR_REG)) 2194 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 2195 "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE" 2196 "jsr @%1%#" 2197 [(set_attr "type" "sfunc") 2198 (set_attr "fp_mode" "double") 2199 (set_attr "needs_delay_slot" "yes")]) 2200 2201(define_insn "udivsi3_i4_single" 2202 [(set (match_operand:SI 0 "register_operand" "=y") 2203 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2204 (clobber (reg:SI T_REG)) 2205 (clobber (reg:SI PR_REG)) 2206 (clobber (reg:DF DR0_REG)) 2207 (clobber (reg:DF DR2_REG)) 2208 (clobber (reg:DF DR4_REG)) 2209 (clobber (reg:SI R0_REG)) 2210 (clobber (reg:SI R1_REG)) 2211 (clobber (reg:SI R4_REG)) 2212 (clobber (reg:SI R5_REG)) 2213 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 2214 "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT) 2215 && TARGET_FPU_SINGLE" 2216 "jsr @%1%#" 2217 [(set_attr "type" "sfunc") 2218 (set_attr "needs_delay_slot" "yes")]) 2219 2220(define_insn "udivsi3_i4_int" 2221 [(set (match_operand:SI 0 "register_operand" "=z") 2222 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2223 (clobber (reg:SI T_REG)) 2224 (clobber (reg:SI R1_REG)) 2225 (clobber (reg:SI PR_REG)) 2226 (clobber (reg:SI MACH_REG)) 2227 (clobber (reg:SI MACL_REG)) 2228 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 2229 "TARGET_SH1" 2230 "jsr @%1%#" 2231 [(set_attr "type" "sfunc") 2232 (set_attr "needs_delay_slot" "yes")]) 2233 2234 2235(define_expand "udivsi3" 2236 [(set (match_dup 3) (symbol_ref:SI "__udivsi3")) 2237 (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" "")) 2238 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" "")) 2239 (parallel [(set (match_operand:SI 0 "register_operand" "") 2240 (udiv:SI (reg:SI R4_REG) 2241 (reg:SI R5_REG))) 2242 (clobber (reg:SI T_REG)) 2243 (clobber (reg:SI PR_REG)) 2244 (clobber (reg:SI R4_REG)) 2245 (use (match_dup 3))])] 2246 "" 2247{ 2248 rtx last; 2249 2250 operands[3] = gen_reg_rtx (Pmode); 2251 /* Emit the move of the address to a pseudo outside of the libcall. */ 2252 if (TARGET_DIVIDE_CALL_TABLE) 2253 { 2254 /* libgcc2:__udivmoddi4 is not supposed to use an actual division, since 2255 that causes problems when the divide code is supposed to come from a 2256 separate library. Division by zero is undefined, so dividing 1 can be 2257 implemented by comparing with the divisor. */ 2258 if (operands[1] == const1_rtx && currently_expanding_to_rtl) 2259 { 2260 rtx test = gen_rtx_GEU (VOIDmode, operands[1], operands[2]); 2261 emit_insn (gen_cstoresi4 (operands[0], test, 2262 operands[1], operands[2])); 2263 DONE; 2264 } 2265 else if (operands[2] == const0_rtx) 2266 { 2267 emit_move_insn (operands[0], operands[2]); 2268 DONE; 2269 } 2270 function_symbol (operands[3], "__udivsi3_i4i", SFUNC_GOT); 2271 last = gen_udivsi3_i4_int (operands[0], operands[3]); 2272 } 2273 else if (TARGET_DIVIDE_CALL_FP) 2274 { 2275 function_symbol (operands[3], "__udivsi3_i4", SFUNC_STATIC); 2276 if (TARGET_FPU_SINGLE) 2277 last = gen_udivsi3_i4_single (operands[0], operands[3]); 2278 else 2279 last = gen_udivsi3_i4 (operands[0], operands[3]); 2280 } 2281 else if (TARGET_SHMEDIA_FPU) 2282 { 2283 operands[1] = force_reg (SImode, operands[1]); 2284 operands[2] = force_reg (SImode, operands[2]); 2285 emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2])); 2286 DONE; 2287 } 2288 else if (TARGET_SH2A) 2289 { 2290 operands[1] = force_reg (SImode, operands[1]); 2291 operands[2] = force_reg (SImode, operands[2]); 2292 emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2])); 2293 DONE; 2294 } 2295 else if (TARGET_SH5) 2296 { 2297 function_symbol (operands[3], 2298 TARGET_FPU_ANY ? "__udivsi3_i4" : "__udivsi3", 2299 SFUNC_STATIC); 2300 2301 if (TARGET_SHMEDIA) 2302 last = gen_udivsi3_i1_media (operands[0], operands[3]); 2303 else if (TARGET_FPU_ANY) 2304 last = gen_udivsi3_i4_single (operands[0], operands[3]); 2305 else 2306 last = gen_udivsi3_i1 (operands[0], operands[3]); 2307 } 2308 else 2309 { 2310 function_symbol (operands[3], "__udivsi3", SFUNC_STATIC); 2311 last = gen_udivsi3_i1 (operands[0], operands[3]); 2312 } 2313 emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]); 2314 emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]); 2315 emit_insn (last); 2316 DONE; 2317}) 2318 2319(define_insn "divsi3_sh2a" 2320 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 2321 (div:SI (match_operand:SI 1 "arith_reg_operand" "0") 2322 (match_operand:SI 2 "arith_reg_operand" "z")))] 2323 "TARGET_SH2A" 2324 "divs %2,%1" 2325 [(set_attr "type" "arith") 2326 (set_attr "in_delay_slot" "no")]) 2327 2328(define_insn "divsi3_i1" 2329 [(set (match_operand:SI 0 "register_operand" "=z") 2330 (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2331 (clobber (reg:SI T_REG)) 2332 (clobber (reg:SI PR_REG)) 2333 (clobber (reg:SI R1_REG)) 2334 (clobber (reg:SI R2_REG)) 2335 (clobber (reg:SI R3_REG)) 2336 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 2337 "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1" 2338 "jsr @%1%#" 2339 [(set_attr "type" "sfunc") 2340 (set_attr "needs_delay_slot" "yes")]) 2341 2342(define_insn "divsi3_i1_media" 2343 [(set (match_operand:SI 0 "register_operand" "=z") 2344 (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2345 (clobber (reg:SI T_MEDIA_REG)) 2346 (clobber (reg:SI PR_MEDIA_REG)) 2347 (clobber (reg:SI R1_REG)) 2348 (clobber (reg:SI R20_REG)) 2349 (clobber (reg:SI R21_REG)) 2350 (clobber (reg:SI TR0_REG)) 2351 (use (match_operand 1 "target_reg_operand" "b"))] 2352 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)" 2353 "blink %1, r18" 2354 [(set_attr "type" "sfunc")]) 2355 2356(define_insn "divsi3_media_2" 2357 [(set (match_operand:SI 0 "register_operand" "=z") 2358 (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2359 (clobber (reg:SI T_MEDIA_REG)) 2360 (clobber (reg:SI PR_MEDIA_REG)) 2361 (clobber (reg:SI R1_REG)) 2362 (clobber (reg:SI R21_REG)) 2363 (clobber (reg:SI TR0_REG)) 2364 (use (reg:SI R20_REG)) 2365 (use (match_operand 1 "target_reg_operand" "b"))] 2366 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)" 2367 "blink %1, r18" 2368 [(set_attr "type" "sfunc")]) 2369 2370;; This pattern acts as a placeholder for -mdiv=inv:call to carry 2371;; hard reg clobbers and data dependencies that we need when we want 2372;; to rematerialize the division into a call. 2373(define_insn_and_split "divsi_inv_call" 2374 [(set (match_operand:SI 0 "register_operand" "=r") 2375 (div:SI (match_operand:SI 1 "register_operand" "r") 2376 (match_operand:SI 2 "register_operand" "r"))) 2377 (clobber (reg:SI R4_REG)) 2378 (clobber (reg:SI R5_REG)) 2379 (clobber (reg:SI T_MEDIA_REG)) 2380 (clobber (reg:SI PR_MEDIA_REG)) 2381 (clobber (reg:SI R1_REG)) 2382 (clobber (reg:SI R21_REG)) 2383 (clobber (reg:SI TR0_REG)) 2384 (clobber (reg:SI R20_REG)) 2385 (use (match_operand:SI 3 "register_operand" "r"))] 2386 "TARGET_SHMEDIA" 2387 "#" 2388 "&& (reload_in_progress || reload_completed)" 2389 [(set (match_dup 0) (match_dup 3))] 2390 "" 2391 [(set_attr "highpart" "must_split")]) 2392 2393;; This is the combiner pattern for -mdiv=inv:call . 2394(define_insn_and_split "*divsi_inv_call_combine" 2395 [(set (match_operand:SI 0 "register_operand" "=z") 2396 (div:SI (match_operand:SI 1 "register_operand" "r") 2397 (match_operand:SI 2 "register_operand" "r"))) 2398 (clobber (reg:SI R4_REG)) 2399 (clobber (reg:SI R5_REG)) 2400 (clobber (reg:SI T_MEDIA_REG)) 2401 (clobber (reg:SI PR_MEDIA_REG)) 2402 (clobber (reg:SI R1_REG)) 2403 (clobber (reg:SI R21_REG)) 2404 (clobber (reg:SI TR0_REG)) 2405 (clobber (reg:SI R20_REG)) 2406 (use (unspec:SI [(match_dup 1) 2407 (match_operand:SI 3 "" "") 2408 (unspec:SI [(match_operand:SI 4 "" "") 2409 (match_dup 3) 2410 (match_operand:DI 5 "" "")] 2411 UNSPEC_DIV_INV_M2) 2412 (match_operand:DI 6 "" "") 2413 (const_int 0) 2414 (const_int 0)] 2415 UNSPEC_DIV_INV_M3))] 2416 "TARGET_SHMEDIA" 2417 "#" 2418 "&& (reload_in_progress || reload_completed)" 2419 [(pc)] 2420{ 2421 const char *name = sh_divsi3_libfunc; 2422 enum sh_function_kind kind = SFUNC_GOT; 2423 rtx sym; 2424 2425 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]); 2426 emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]); 2427 while (TARGET_DIVIDE_INV_CALL2) 2428 { 2429 rtx x = operands[3]; 2430 2431 if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1) 2432 break; 2433 x = XVECEXP (x, 0, 0); 2434 name = "__sdivsi3_2"; 2435 kind = SFUNC_STATIC; 2436 emit_move_insn (gen_rtx_REG (DImode, R20_REG), x); 2437 break; 2438 } 2439 sym = function_symbol (NULL, name, kind); 2440 emit_insn (gen_divsi3_media_2 (operands[0], sym)); 2441 DONE; 2442} 2443 [(set_attr "highpart" "must_split")]) 2444 2445(define_expand "divsi3_i4_media" 2446 [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r"))) 2447 (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r"))) 2448 (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4))) 2449 (set (match_operand:SI 0 "register_operand" "=r") 2450 (fix:SI (match_dup 5)))] 2451 "TARGET_SHMEDIA_FPU" 2452{ 2453 operands[3] = gen_reg_rtx (DFmode); 2454 operands[4] = gen_reg_rtx (DFmode); 2455 operands[5] = gen_reg_rtx (DFmode); 2456}) 2457 2458(define_insn "divsi3_i4" 2459 [(set (match_operand:SI 0 "register_operand" "=y") 2460 (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2461 (clobber (reg:SI PR_REG)) 2462 (clobber (reg:DF DR0_REG)) 2463 (clobber (reg:DF DR2_REG)) 2464 (use (reg:PSI FPSCR_REG)) 2465 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 2466 "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE" 2467 "jsr @%1%#" 2468 [(set_attr "type" "sfunc") 2469 (set_attr "fp_mode" "double") 2470 (set_attr "needs_delay_slot" "yes")]) 2471 2472(define_insn "divsi3_i4_single" 2473 [(set (match_operand:SI 0 "register_operand" "=y") 2474 (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2475 (clobber (reg:SI PR_REG)) 2476 (clobber (reg:DF DR0_REG)) 2477 (clobber (reg:DF DR2_REG)) 2478 (clobber (reg:SI R2_REG)) 2479 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 2480 "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT) 2481 && TARGET_FPU_SINGLE" 2482 "jsr @%1%#" 2483 [(set_attr "type" "sfunc") 2484 (set_attr "needs_delay_slot" "yes")]) 2485 2486(define_insn "divsi3_i4_int" 2487 [(set (match_operand:SI 0 "register_operand" "=z") 2488 (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2489 (clobber (reg:SI T_REG)) 2490 (clobber (reg:SI PR_REG)) 2491 (clobber (reg:SI R1_REG)) 2492 (clobber (reg:SI MACH_REG)) 2493 (clobber (reg:SI MACL_REG)) 2494 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 2495 "TARGET_SH1" 2496 "jsr @%1%#" 2497 [(set_attr "type" "sfunc") 2498 (set_attr "needs_delay_slot" "yes")]) 2499 2500(define_expand "divsi3" 2501 [(set (match_dup 3) (symbol_ref:SI "__sdivsi3")) 2502 (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" "")) 2503 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" "")) 2504 (parallel [(set (match_operand:SI 0 "register_operand" "") 2505 (div:SI (reg:SI R4_REG) 2506 (reg:SI R5_REG))) 2507 (clobber (reg:SI T_REG)) 2508 (clobber (reg:SI PR_REG)) 2509 (clobber (reg:SI R1_REG)) 2510 (clobber (reg:SI R2_REG)) 2511 (clobber (reg:SI R3_REG)) 2512 (use (match_dup 3))])] 2513 "" 2514{ 2515 rtx last; 2516 2517 operands[3] = gen_reg_rtx (Pmode); 2518 /* Emit the move of the address to a pseudo outside of the libcall. */ 2519 if (TARGET_DIVIDE_CALL_TABLE) 2520 { 2521 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT); 2522 last = gen_divsi3_i4_int (operands[0], operands[3]); 2523 } 2524 else if (TARGET_DIVIDE_CALL_FP) 2525 { 2526 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC); 2527 if (TARGET_FPU_SINGLE) 2528 last = gen_divsi3_i4_single (operands[0], operands[3]); 2529 else 2530 last = gen_divsi3_i4 (operands[0], operands[3]); 2531 } 2532 else if (TARGET_SH2A) 2533 { 2534 operands[1] = force_reg (SImode, operands[1]); 2535 operands[2] = force_reg (SImode, operands[2]); 2536 emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2])); 2537 DONE; 2538 } 2539 else if (TARGET_DIVIDE_INV) 2540 { 2541 rtx dividend = operands[1]; 2542 rtx divisor = operands[2]; 2543 rtx tab_base; 2544 rtx nsb_res = gen_reg_rtx (DImode); 2545 rtx norm64 = gen_reg_rtx (DImode); 2546 rtx tab_ix = gen_reg_rtx (DImode); 2547 rtx norm32 = gen_reg_rtx (SImode); 2548 rtx i92 = force_reg (DImode, GEN_INT (92)); 2549 rtx scratch0a = gen_reg_rtx (DImode); 2550 rtx scratch0b = gen_reg_rtx (DImode); 2551 rtx inv0 = gen_reg_rtx (SImode); 2552 rtx scratch1a = gen_reg_rtx (DImode); 2553 rtx scratch1b = gen_reg_rtx (DImode); 2554 rtx shift = gen_reg_rtx (DImode); 2555 rtx i2p27, i43; 2556 rtx inv1 = gen_reg_rtx (SImode); 2557 rtx scratch2a = gen_reg_rtx (DImode); 2558 rtx scratch2b = gen_reg_rtx (SImode); 2559 rtx inv2 = gen_reg_rtx (SImode); 2560 rtx scratch3a = gen_reg_rtx (DImode); 2561 rtx scratch3b = gen_reg_rtx (DImode); 2562 rtx scratch3c = gen_reg_rtx (DImode); 2563 rtx scratch3d = gen_reg_rtx (SImode); 2564 rtx scratch3e = gen_reg_rtx (DImode); 2565 rtx result = gen_reg_rtx (SImode); 2566 2567 if (! arith_reg_or_0_operand (dividend, SImode)) 2568 dividend = force_reg (SImode, dividend); 2569 if (! arith_reg_operand (divisor, SImode)) 2570 divisor = force_reg (SImode, divisor); 2571 if (flag_pic && Pmode != DImode) 2572 { 2573 tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table"); 2574 tab_base = gen_datalabel_ref (tab_base); 2575 tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base)); 2576 } 2577 else 2578 { 2579 tab_base = gen_rtx_SYMBOL_REF (DImode, "__div_table"); 2580 tab_base = gen_datalabel_ref (tab_base); 2581 tab_base = force_reg (DImode, tab_base); 2582 } 2583 if (TARGET_DIVIDE_INV20U) 2584 i2p27 = force_reg (DImode, GEN_INT (-2 << 27)); 2585 else 2586 i2p27 = GEN_INT (0); 2587 if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L) 2588 i43 = force_reg (DImode, GEN_INT (43)); 2589 else 2590 i43 = GEN_INT (0); 2591 emit_insn (gen_nsbdi (nsb_res, 2592 simplify_gen_subreg (DImode, divisor, SImode, 0))); 2593 emit_insn (gen_ashldi3_media (norm64, 2594 gen_rtx_SUBREG (DImode, divisor, 0), 2595 nsb_res)); 2596 emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58))); 2597 emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32))); 2598 emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32, 2599 inv0, scratch0a, scratch0b, 2600 scratch1a, scratch1b)); 2601 emit_insn (gen_subdi3 (shift, i92, nsb_res)); 2602 emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92, 2603 scratch2a)); 2604 emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift, 2605 i2p27, i43, 2606 scratch3a, scratch3b, scratch3c, 2607 scratch2a, scratch2b, scratch3d, scratch3e)); 2608 if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2) 2609 emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result)); 2610 else if (TARGET_DIVIDE_INV_FP) 2611 emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result, 2612 gen_reg_rtx (SImode), gen_reg_rtx (SImode), 2613 gen_reg_rtx (DFmode), gen_reg_rtx (DFmode), 2614 gen_reg_rtx (DFmode))); 2615 else 2616 emit_move_insn (operands[0], result); 2617 DONE; 2618 } 2619 else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP) 2620 { 2621 operands[1] = force_reg (SImode, operands[1]); 2622 operands[2] = force_reg (SImode, operands[2]); 2623 emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2])); 2624 DONE; 2625 } 2626 else if (TARGET_SH5) 2627 { 2628 if (TARGET_DIVIDE_CALL2) 2629 { 2630 rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table"); 2631 tab_base = gen_datalabel_ref (tab_base); 2632 emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base); 2633 } 2634 if (TARGET_FPU_ANY && TARGET_SH1) 2635 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC); 2636 else if (TARGET_DIVIDE_CALL2) 2637 function_symbol (operands[3], "__sdivsi3_2", SFUNC_STATIC); 2638 else 2639 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT); 2640 2641 if (TARGET_SHMEDIA) 2642 last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media) 2643 (operands[0], operands[3])); 2644 else if (TARGET_FPU_ANY) 2645 last = gen_divsi3_i4_single (operands[0], operands[3]); 2646 else 2647 last = gen_divsi3_i1 (operands[0], operands[3]); 2648 } 2649 else 2650 { 2651 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT); 2652 last = gen_divsi3_i1 (operands[0], operands[3]); 2653 } 2654 emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]); 2655 emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]); 2656 emit_insn (last); 2657 DONE; 2658}) 2659 2660;; operands: scratch, tab_base, tab_ix 2661;; These are unspecs because we could generate an indexed addressing mode 2662;; even if -m5-32media, where INDEX_REG_CLASS == NO_REGS, and this would 2663;; confuse reload. See PR27117. 2664(define_insn "divsi_inv_qitable" 2665 [(set (match_operand:DI 0 "register_operand" "=r") 2666 (zero_extend:DI (unspec:QI [(match_operand:DI 1 "register_operand" "r") 2667 (match_operand:DI 2 "register_operand" "r")] 2668 UNSPEC_DIV_INV_TABLE)))] 2669 "TARGET_SHMEDIA" 2670 "ldx.ub %1, %2, %0" 2671 [(set_attr "type" "load_media") 2672 (set_attr "highpart" "user")]) 2673 2674;; operands: scratch, tab_base, tab_ix 2675(define_insn "divsi_inv_hitable" 2676 [(set (match_operand:DI 0 "register_operand" "=r") 2677 (sign_extend:DI (unspec:HI [(match_operand:DI 1 "register_operand" "r") 2678 (match_operand:DI 2 "register_operand" "r")] 2679 UNSPEC_DIV_INV_TABLE)))] 2680 "TARGET_SHMEDIA" 2681 "ldx.w %1, %2, %0" 2682 [(set_attr "type" "load_media") 2683 (set_attr "highpart" "user")]) 2684 2685;; operands: inv0, tab_base, tab_ix, norm32 2686;; scratch equiv in sdivsi3_2: r19, r21 2687(define_expand "divsi_inv_m0" 2688 [(set (match_operand:SI 0 "register_operand" "=r") 2689 (unspec:SI [(match_operand:DI 1 "register_operand" "r") 2690 (match_operand:DI 2 "register_operand" "r") 2691 (match_operand:SI 3 "register_operand" "r")] 2692 UNSPEC_DIV_INV_M0)) 2693 (clobber (match_operand:DI 4 "register_operand" "=r")) 2694 (clobber (match_operand:DI 5 "register_operand" "=r"))] 2695 "TARGET_SHMEDIA" 2696{ 2697/* 2698tab_base: r20 2699tab_ix: r21 2700norm32: r25 2701 ldx.ub r20, r21, r19 // u0.8 2702 shlli r21, 1, r21 2703 muls.l r25, r19, r19 // s2.38 2704 ldx.w r20, r21, r21 // s2.14 2705 shari r19, 24, r19 // truncate to s2.14 2706 sub r21, r19, r19 // some 11 bit inverse in s1.14 2707*/ 2708 2709 rtx inv0 = operands[0]; 2710 rtx tab_base = operands[1]; 2711 rtx tab_ix = operands[2]; 2712 rtx norm32 = operands[3]; 2713 rtx scratch0 = operands[4]; 2714 rtx scratch0_si = gen_lowpart (SImode, scratch0); 2715 rtx scratch1 = operands[5]; 2716 2717 emit_insn (gen_divsi_inv_qitable (scratch0, tab_base, tab_ix)); 2718 emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1))); 2719 emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si)); 2720 emit_insn (gen_divsi_inv_hitable (scratch1, tab_base, scratch1)); 2721 emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24))); 2722 emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0)); 2723 DONE; 2724}) 2725 2726;; operands: inv1, tab_base, tab_ix, norm32 2727(define_insn_and_split "divsi_inv_m1" 2728 [(set (match_operand:SI 0 "register_operand" "=r") 2729 (unspec:SI [(match_operand:DI 1 "register_operand" "r") 2730 (match_operand:DI 2 "register_operand" "r") 2731 (match_operand:SI 3 "register_operand" "r")] 2732 UNSPEC_DIV_INV_M1)) 2733 (clobber (match_operand:SI 4 "register_operand" "=r")) 2734 (clobber (match_operand:DI 5 "register_operand" "=r")) 2735 (clobber (match_operand:DI 6 "register_operand" "=r")) 2736 (clobber (match_operand:DI 7 "register_operand" "=r")) 2737 (clobber (match_operand:DI 8 "register_operand" "=r"))] 2738 "TARGET_SHMEDIA" 2739 "#" 2740 "&& !can_create_pseudo_p ()" 2741 [(pc)] 2742{ 2743/* inv0: r19 2744 muls.l r19, r19, r18 // u0.28 2745 muls.l r25, r18, r18 // s2.58 2746 shlli r19, 45, r0 // multiply by two and convert to s2.58 2747 sub r0, r18, r18 2748 shari r18, 28, r18 // some 18 bit inverse in s1.30 2749*/ 2750 2751 rtx inv1 = operands[0]; 2752 rtx tab_base = operands[1]; 2753 rtx tab_ix = operands[2]; 2754 rtx norm32 = operands[3]; 2755 rtx inv0 = operands[4]; 2756 rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0); 2757 rtx scratch0a = operands[5]; 2758 rtx scratch0b = operands[6]; 2759 rtx scratch0 = operands[7]; 2760 rtx scratch1 = operands[8]; 2761 rtx scratch1_si = gen_lowpart (SImode, scratch1); 2762 2763 emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32, 2764 scratch0a, scratch0b)); 2765 emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0)); 2766 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si)); 2767 emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45))); 2768 emit_insn (gen_subdi3 (scratch1, scratch0, scratch1)); 2769 emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28))); 2770 DONE; 2771}) 2772 2773;; operands: inv2, norm32, inv1, i92 2774(define_insn_and_split "divsi_inv_m2" 2775 [(set (match_operand:SI 0 "register_operand" "=r") 2776 (unspec:SI [(match_operand:SI 1 "register_operand" "r") 2777 (match_operand:SI 2 "register_operand" "r") 2778 (match_operand:DI 3 "register_operand" "r")] 2779 UNSPEC_DIV_INV_M2)) 2780 (clobber (match_operand:DI 4 "register_operand" "=r"))] 2781 "TARGET_SHMEDIA" 2782 "#" 2783 "&& !can_create_pseudo_p ()" 2784 [(pc)] 2785{ 2786/* 2787 muls.l r18, r25, r0 // s2.60 2788 shari r0, 16, r0 // s-16.44 2789 sub 2790 muls.l r0, r18, r19 // s-16.74 2791 shari r19, 30, r19 // s-16.44 2792*/ 2793 rtx inv2 = operands[0]; 2794 rtx norm32 = operands[1]; 2795 rtx inv1 = operands[2]; 2796 rtx i92 = operands[3]; 2797 rtx scratch0 = operands[4]; 2798 rtx scratch0_si = gen_lowpart (SImode, scratch0); 2799 2800 emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32)); 2801 emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16))); 2802 emit_insn (gen_subdi3 (scratch0, i92, scratch0)); 2803 emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1)); 2804 emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30))); 2805 DONE; 2806}) 2807 2808(define_insn_and_split "divsi_inv_m3" 2809 [(set (match_operand:SI 0 "register_operand" "=r") 2810 (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN") 2811 (match_operand:SI 2 "register_operand" "r") 2812 (match_operand:SI 3 "register_operand" "r") 2813 (match_operand:DI 4 "register_operand" "r") 2814 (match_operand:DI 5 "arith_reg_or_0_operand" "rN") 2815 (match_operand:DI 6 "arith_reg_or_0_operand" "rN")] 2816 UNSPEC_DIV_INV_M3)) 2817 (clobber (match_operand:DI 7 "register_operand" "=r")) 2818 (clobber (match_operand:DI 8 "register_operand" "=r")) 2819 (clobber (match_operand:DI 9 "register_operand" "=r")) 2820 (clobber (match_operand:DI 10 "register_operand" "=r")) 2821 (clobber (match_operand:SI 11 "register_operand" "=r")) 2822 (clobber (match_operand:SI 12 "register_operand" "=r")) 2823 (clobber (match_operand:DI 13 "register_operand" "=r"))] 2824 "TARGET_SHMEDIA" 2825 "#" 2826 "&& !can_create_pseudo_p ()" 2827 [(pc)] 2828{ 2829/* 2830 r0: result r1: shift r4: dividend r18: inv1 r19: inv2 2831 r0: scratch0 r19: scratch1 r21: scratch2 2832 2833 muls.l r18, r4, r25 // s32.30 2834 muls.l r19, r4, r19 // s15.30 2835 shari r25, 63, r21 2836 shari r19, 14, r19 // s18.-14 2837 sub r25, r19, r0 2838 shard r0, r1, r0 2839 sub r0, r21, r0 2840*/ 2841 2842 rtx result = operands[0]; 2843 rtx dividend = operands[1]; 2844 rtx inv1 = operands[2]; 2845 rtx inv2 = operands[3]; 2846 rtx shift = operands[4]; 2847 rtx scratch0 = operands[7]; 2848 rtx scratch1 = operands[8]; 2849 rtx scratch2 = operands[9]; 2850 2851 if (satisfies_constraint_N (dividend)) 2852 { 2853 emit_move_insn (result, dividend); 2854 DONE; 2855 } 2856 2857 emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend)); 2858 emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend)); 2859 emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63))); 2860 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14))); 2861 emit_insn (gen_adddi3 (scratch0, scratch0, scratch1)); 2862 emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift)); 2863 emit_insn (gen_subdisi3_media (result, scratch0, scratch2)); 2864 DONE; 2865}) 2866 2867;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43 2868;; inv1: tab_base, tab_ix, norm32 2869;; inv2: norm32, inv1, i92 2870(define_insn_and_split "divsi_inv_m1_3" 2871 [(set (match_operand:SI 0 "register_operand" "=r") 2872 (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN") 2873 (unspec:SI [(match_operand:DI 2 "register_operand" "r") 2874 (match_operand:DI 3 "register_operand" "r") 2875 (match_operand:SI 4 "register_operand" "r")] 2876 UNSPEC_DIV_INV_M1) 2877 (unspec:SI [(match_dup 4) 2878 (unspec:SI [(match_dup 2) 2879 (match_dup 3) 2880 (match_dup 4)] UNSPEC_DIV_INV_M1) 2881 (match_operand:SI 5 "" "")] 2882 UNSPEC_DIV_INV_M2) 2883 (match_operand:DI 6 "register_operand" "r") 2884 (match_operand:DI 7 "arith_reg_or_0_operand" "rN") 2885 (match_operand:DI 8 "arith_reg_or_0_operand" "rN")] 2886 UNSPEC_DIV_INV_M3)) 2887 (clobber (match_operand:DI 9 "register_operand" "=r")) 2888 (clobber (match_operand:DI 10 "register_operand" "=r")) 2889 (clobber (match_operand:DI 11 "register_operand" "=r")) 2890 (clobber (match_operand:DI 12 "register_operand" "=r")) 2891 (clobber (match_operand:SI 13 "register_operand" "=r")) 2892 (clobber (match_operand:SI 14 "register_operand" "=r")) 2893 (clobber (match_operand:DI 15 "register_operand" "=r"))] 2894 "TARGET_SHMEDIA 2895 && (TARGET_DIVIDE_INV_MINLAT 2896 || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)" 2897 "#" 2898 "&& !can_create_pseudo_p ()" 2899 [(pc)] 2900{ 2901 rtx result = operands[0]; 2902 rtx dividend = operands[1]; 2903 rtx tab_base = operands[2]; 2904 rtx tab_ix = operands[3]; 2905 rtx norm32 = operands[4]; 2906 /* rtx i92 = operands[5]; */ 2907 rtx shift = operands[6]; 2908 rtx i2p27 = operands[7]; 2909 rtx i43 = operands[8]; 2910 rtx scratch0 = operands[9]; 2911 rtx scratch0_si = gen_lowpart (SImode, scratch0); 2912 rtx scratch1 = operands[10]; 2913 rtx scratch1_si = gen_lowpart (SImode, scratch1); 2914 rtx scratch2 = operands[11]; 2915 rtx scratch3 = operands[12]; 2916 rtx scratch4 = operands[13]; 2917 rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0); 2918 rtx scratch5 = operands[14]; 2919 rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0); 2920 rtx scratch6 = operands[15]; 2921 2922 emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32, 2923 scratch0, scratch1)); 2924 /* inv0 == scratch4 */ 2925 if (! TARGET_DIVIDE_INV20U) 2926 { 2927 emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4)); 2928 i2p27 = scratch0; 2929 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si)); 2930 } 2931 else 2932 { 2933 emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4)); 2934 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si)); 2935 } 2936 emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45))); 2937 emit_insn (gen_subdi3 (scratch1, scratch2, scratch1)); 2938 emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28))); 2939 /* inv1 == scratch4 */ 2940 2941 if (TARGET_DIVIDE_INV_MINLAT) 2942 { 2943 emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32)); 2944 emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4)); 2945 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16))); 2946 emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4)); 2947 emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63))); 2948 emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14))); 2949 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30))); 2950 emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5)); 2951 emit_insn (gen_xordi3 (scratch0, scratch3, i2p27)); 2952 emit_insn (gen_adddi3 (scratch2, scratch2, scratch0)); 2953 emit_insn (gen_subdi3 (scratch2, scratch2, scratch1)); 2954 } 2955 else 2956 { 2957 rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ()); 2958 /* Use separate scratch regs for nsb and sign to allow scheduling. */ 2959 emit_insn (gen_nsbdi (scratch6, 2960 simplify_gen_subreg (DImode, dividend, SImode, 0))); 2961 emit_insn (gen_xorsi3 (scratch5, dividend, norm32)); 2962 emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63))); 2963 emit_insn (gen_divsi_inv20 (scratch2, 2964 norm32, scratch4, dividend, 2965 scratch6, scratch3, i43, 2966 /* scratch0 may be shared with i2p27. */ 2967 scratch0, scratch1, scratch5, 2968 label, label, i2p27)); 2969 } 2970 emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift)); 2971 emit_insn (gen_subdisi3_media (result, scratch2, scratch3)); 2972 DONE; 2973}) 2974 2975(define_insn "divsi_inv20" 2976 [(set (match_operand:DI 0 "register_operand" "=&r") 2977 (unspec:DI [(match_operand:SI 1 "register_operand" "r") 2978 (match_operand:SI 2 "register_operand" "r") 2979 (match_operand:SI 3 "register_operand" "r") 2980 (match_operand:DI 4 "register_operand" "r") 2981 (match_operand:DI 5 "register_operand" "r") 2982 (match_operand:DI 6 "register_operand" "r") 2983 (match_operand:DI 12 "register_operand" "r") 2984 (match_operand 10 "target_operand" "b") 2985 (match_operand 11 "immediate_operand" "i")] 2986 UNSPEC_DIV_INV20)) 2987 (clobber (match_operand:DI 7 "register_operand" "=&r")) 2988 (clobber (match_operand:DI 8 "register_operand" "=&r")) 2989 (clobber (match_operand:SI 9 "register_operand" "=r"))] 2990 "TARGET_SHMEDIA 2991 && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)" 2992{ 2993/* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend, 2994 %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27, 2995 %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si) 2996 %10 label (tr), %11 label (imm) 2997 2998 muls.l inv1, norm32, scratch0 // s2.60 2999 muls.l inv1, dividend, result // s32.30 3000 xor i2p27, result_sign, round_scratch 3001 bge/u dividend_nsb, i43, tr.. (label) 3002 shari scratch0, 16, scratch0 // s-16.44 3003 muls.l sratch0_si, inv1, scratch0 // s-16.74 3004 sub result, round_scratch, result 3005 shari dividend, 14, scratch1 // s19.-14 3006 shari scratch0, 30, scratch0 // s-16.44 3007 muls.l scratch0, scratch1, round_scratch // s15.30 3008label: 3009 sub result, round_scratch, result */ 3010 3011 const bool likely = TARGET_DIVIDE_INV20L; 3012 if (likely) 3013 return 3014 "muls.l %2, %3, %0" "\n" 3015 " xor %12, %5, %7" "\n" 3016 " bge/l %4, %6, %10" "\n" 3017 " muls.l %2, %1, %8" "\n" 3018 " shari %8, 16, %8" "\n" 3019 " muls.l %8, %2, %8" "\n" 3020 " shari %3, 14, %9" "\n" 3021 " shari %8, 30, %8" "\n" 3022 " muls.l %8, %9, %8" "\n" 3023 " sub %0, %8, %0" "\n" 3024 "%11: add %0, %7, %0"; 3025 else 3026 return 3027 "muls.l %2, %1, %8" "\n" 3028 " muls.l %2, %3, %0" "\n" 3029 " xor %12, %5, %7" "\n" 3030 " bge/u %4, %6, %10" "\n" 3031 " shari %8, 16, %8" "\n" 3032 " muls.l %8, %2, %8" "\n" 3033 " sub %0, %7, %0" "\n" 3034 " shari %3, 14, %9" "\n" 3035 " shari %8, 30, %8" "\n" 3036 " muls.l %8, %9, %7" "\n" 3037 "%11: sub %0, %7, %0"; 3038}) 3039 3040(define_insn_and_split "divsi_inv_fp" 3041 [(set (match_operand:SI 0 "general_movdst_operand" "=rf") 3042 (div:SI (match_operand:SI 1 "general_movsrc_operand" "rf") 3043 (match_operand:SI 2 "register_operand" "rf"))) 3044 (use (match_operand:SI 3 "general_movsrc_operand" "r")) 3045 (clobber (match_operand:SI 4 "register_operand" "=r")) 3046 (clobber (match_operand:SI 5 "register_operand" "=r")) 3047 (clobber (match_operand:DF 6 "register_operand" "=r")) 3048 (clobber (match_operand:DF 7 "register_operand" "=r")) 3049 (clobber (match_operand:DF 8 "register_operand" "=r"))] 3050 "TARGET_SHMEDIA_FPU" 3051 "#" 3052 "&& (reload_in_progress || reload_completed)" 3053 [(set (match_dup 0) (match_dup 3))] 3054 "" 3055 [(set_attr "highpart" "must_split")]) 3056 3057;; If a matching group of divide-by-inverse instructions is in the same 3058;; basic block after gcse & loop optimizations, we want to transform them 3059;; to a straight division using floating point for TARGET_DIVIDE_INV_FP. 3060(define_insn_and_split "*divsi_inv_fp_combine" 3061 [(set (match_operand:SI 0 "register_operand" "=f") 3062 (div:SI (match_operand:SI 1 "register_operand" "f") 3063 (match_operand:SI 2 "register_operand" "f"))) 3064 (use (unspec:SI [(match_dup 1) 3065 (match_operand:SI 3 "" "") 3066 (unspec:SI [(match_operand:SI 4 "" "") 3067 (match_dup 3) 3068 (match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2) 3069 (match_operand:DI 6 "" "") 3070 (const_int 0) 3071 (const_int 0)] UNSPEC_DIV_INV_M3)) 3072 (clobber (match_operand:SI 7 "fp_arith_reg_operand" "")) 3073 (clobber (match_operand:SI 8 "fp_arith_reg_operand" "")) 3074 (clobber (match_operand:DF 9 "fp_arith_reg_operand" "")) 3075 (clobber (match_operand:DF 10 "fp_arith_reg_operand" "")) 3076 (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))] 3077 "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && !can_create_pseudo_p ()" 3078 "#" 3079 "&& 1" 3080 [(set (match_dup 9) (float:DF (match_dup 1))) 3081 (set (match_dup 10) (float:DF (match_dup 2))) 3082 (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10))) 3083 (set (match_dup 8) 3084 (fix:SI (match_dup 11))) 3085 (set (match_dup 0) (match_dup 8))] 3086{ 3087 if (! fp_arith_reg_operand (operands[1], SImode)) 3088 { 3089 emit_move_insn (operands[7], operands[1]); 3090 operands[1] = operands[7]; 3091 } 3092 if (! fp_arith_reg_operand (operands[2], SImode)) 3093 { 3094 emit_move_insn (operands[8], operands[2]); 3095 operands[2] = operands[8]; 3096 } 3097} 3098 [(set_attr "highpart" "must_split")]) 3099 3100;; ------------------------------------------------------------------------- 3101;; Multiplication instructions 3102;; ------------------------------------------------------------------------- 3103 3104(define_insn "umulhisi3_i" 3105 [(set (reg:SI MACL_REG) 3106 (mult:SI (zero_extend:SI 3107 (match_operand:HI 0 "arith_reg_operand" "r")) 3108 (zero_extend:SI 3109 (match_operand:HI 1 "arith_reg_operand" "r"))))] 3110 "TARGET_SH1" 3111 "mulu.w %1,%0" 3112 [(set_attr "type" "smpy")]) 3113 3114(define_insn "mulhisi3_i" 3115 [(set (reg:SI MACL_REG) 3116 (mult:SI (sign_extend:SI 3117 (match_operand:HI 0 "arith_reg_operand" "r")) 3118 (sign_extend:SI 3119 (match_operand:HI 1 "arith_reg_operand" "r"))))] 3120 "TARGET_SH1" 3121 "muls.w %1,%0" 3122 [(set_attr "type" "smpy")]) 3123 3124(define_expand "mulhisi3" 3125 [(set (reg:SI MACL_REG) 3126 (mult:SI (sign_extend:SI 3127 (match_operand:HI 1 "arith_reg_operand" "")) 3128 (sign_extend:SI 3129 (match_operand:HI 2 "arith_reg_operand" "")))) 3130 (set (match_operand:SI 0 "arith_reg_operand" "") 3131 (reg:SI MACL_REG))] 3132 "TARGET_SH1" 3133{ 3134 rtx insn, macl; 3135 3136 macl = gen_rtx_REG (SImode, MACL_REG); 3137 start_sequence (); 3138 emit_insn (gen_mulhisi3_i (operands[1], operands[2])); 3139 insn = get_insns (); 3140 end_sequence (); 3141 /* expand_binop can't find a suitable code in umul_widen_optab to 3142 make a REG_EQUAL note from, so make one here. 3143 See also smulsi3_highpart. 3144 ??? Alternatively, we could put this at the calling site of expand_binop, 3145 i.e. expand_expr. */ 3146 /* Use emit_libcall_block for loop invariant code motion and to make 3147 a REG_EQUAL note. */ 3148 emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn))); 3149 3150 DONE; 3151}) 3152 3153(define_expand "umulhisi3" 3154 [(set (reg:SI MACL_REG) 3155 (mult:SI (zero_extend:SI 3156 (match_operand:HI 1 "arith_reg_operand" "")) 3157 (zero_extend:SI 3158 (match_operand:HI 2 "arith_reg_operand" "")))) 3159 (set (match_operand:SI 0 "arith_reg_operand" "") 3160 (reg:SI MACL_REG))] 3161 "TARGET_SH1" 3162{ 3163 rtx insn, macl; 3164 3165 macl = gen_rtx_REG (SImode, MACL_REG); 3166 start_sequence (); 3167 emit_insn (gen_umulhisi3_i (operands[1], operands[2])); 3168 insn = get_insns (); 3169 end_sequence (); 3170 /* expand_binop can't find a suitable code in umul_widen_optab to 3171 make a REG_EQUAL note from, so make one here. 3172 See also smulsi3_highpart. 3173 ??? Alternatively, we could put this at the calling site of expand_binop, 3174 i.e. expand_expr. */ 3175 /* Use emit_libcall_block for loop invariant code motion and to make 3176 a REG_EQUAL note. */ 3177 emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn))); 3178 3179 DONE; 3180}) 3181 3182;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate 3183;; a call to a routine which clobbers known registers. 3184(define_insn "" 3185 [(set (match_operand:SI 1 "register_operand" "=z") 3186 (mult:SI (reg:SI R4_REG) (reg:SI R5_REG))) 3187 (clobber (reg:SI MACL_REG)) 3188 (clobber (reg:SI T_REG)) 3189 (clobber (reg:SI PR_REG)) 3190 (clobber (reg:SI R3_REG)) 3191 (clobber (reg:SI R2_REG)) 3192 (clobber (reg:SI R1_REG)) 3193 (use (match_operand:SI 0 "arith_reg_operand" "r"))] 3194 "TARGET_SH1" 3195 "jsr @%0%#" 3196 [(set_attr "type" "sfunc") 3197 (set_attr "needs_delay_slot" "yes")]) 3198 3199(define_expand "mulsi3_call" 3200 [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" "")) 3201 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" "")) 3202 (parallel[(set (match_operand:SI 0 "register_operand" "") 3203 (mult:SI (reg:SI R4_REG) 3204 (reg:SI R5_REG))) 3205 (clobber (reg:SI MACL_REG)) 3206 (clobber (reg:SI T_REG)) 3207 (clobber (reg:SI PR_REG)) 3208 (clobber (reg:SI R3_REG)) 3209 (clobber (reg:SI R2_REG)) 3210 (clobber (reg:SI R1_REG)) 3211 (use (match_operand:SI 3 "register_operand" ""))])] 3212 "TARGET_SH1" 3213 "") 3214 3215(define_insn "mul_r" 3216 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 3217 (mult:SI (match_operand:SI 1 "arith_reg_operand" "0") 3218 (match_operand:SI 2 "arith_reg_operand" "z")))] 3219 "TARGET_SH2A" 3220 "mulr %2,%0" 3221 [(set_attr "type" "dmpy")]) 3222 3223(define_insn "mul_l" 3224 [(set (reg:SI MACL_REG) 3225 (mult:SI (match_operand:SI 0 "arith_reg_operand" "r") 3226 (match_operand:SI 1 "arith_reg_operand" "r")))] 3227 "TARGET_SH2" 3228 "mul.l %1,%0" 3229 [(set_attr "type" "dmpy")]) 3230 3231(define_expand "mulsi3" 3232 [(set (reg:SI MACL_REG) 3233 (mult:SI (match_operand:SI 1 "arith_reg_operand" "") 3234 (match_operand:SI 2 "arith_reg_operand" ""))) 3235 (set (match_operand:SI 0 "arith_reg_operand" "") 3236 (reg:SI MACL_REG))] 3237 "TARGET_SH1" 3238{ 3239 if (!TARGET_SH2) 3240 { 3241 /* The address must be set outside the libcall, 3242 since it goes into a pseudo. */ 3243 rtx sym = function_symbol (NULL, "__mulsi3", SFUNC_STATIC); 3244 rtx addr = force_reg (SImode, sym); 3245 rtx insns = gen_mulsi3_call (operands[0], operands[1], 3246 operands[2], addr); 3247 emit_insn (insns); 3248 } 3249 else 3250 { 3251 rtx macl = gen_rtx_REG (SImode, MACL_REG); 3252 3253 emit_insn (gen_mul_l (operands[1], operands[2])); 3254 /* consec_sets_giv can only recognize the first insn that sets a 3255 giv as the giv insn. So we must tag this also with a REG_EQUAL 3256 note. */ 3257 emit_insn (gen_movsi_i ((operands[0]), macl)); 3258 } 3259 DONE; 3260}) 3261 3262(define_insn "mulsidi3_i" 3263 [(set (reg:SI MACH_REG) 3264 (truncate:SI 3265 (lshiftrt:DI 3266 (mult:DI 3267 (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) 3268 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))) 3269 (const_int 32)))) 3270 (set (reg:SI MACL_REG) 3271 (mult:SI (match_dup 0) 3272 (match_dup 1)))] 3273 "TARGET_SH2" 3274 "dmuls.l %1,%0" 3275 [(set_attr "type" "dmpy")]) 3276 3277(define_expand "mulsidi3" 3278 [(set (match_operand:DI 0 "arith_reg_dest" "") 3279 (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) 3280 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))] 3281 "TARGET_SH2 || TARGET_SHMEDIA" 3282{ 3283 if (TARGET_SH2) 3284 { 3285 emit_insn (gen_mulsidi3_compact (operands[0], operands[1], operands[2])); 3286 DONE; 3287 } 3288}) 3289 3290(define_insn "mulsidi3_media" 3291 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 3292 (mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r")) 3293 (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))] 3294 "TARGET_SHMEDIA" 3295 "muls.l %1, %2, %0" 3296 [(set_attr "type" "dmpy_media") 3297 (set_attr "highpart" "ignore")]) 3298 3299(define_insn_and_split "mulsidi3_compact" 3300 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 3301 (mult:DI 3302 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")) 3303 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r")))) 3304 (clobber (reg:SI MACH_REG)) 3305 (clobber (reg:SI MACL_REG))] 3306 "TARGET_SH2" 3307 "#" 3308 "&& 1" 3309 [(const_int 0)] 3310{ 3311 rtx low_dst = gen_lowpart (SImode, operands[0]); 3312 rtx high_dst = gen_highpart (SImode, operands[0]); 3313 3314 emit_insn (gen_mulsidi3_i (operands[1], operands[2])); 3315 3316 emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG)); 3317 emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG)); 3318 /* We need something to tag the possible REG_EQUAL notes on to. */ 3319 emit_move_insn (operands[0], operands[0]); 3320 DONE; 3321}) 3322 3323(define_insn "umulsidi3_i" 3324 [(set (reg:SI MACH_REG) 3325 (truncate:SI 3326 (lshiftrt:DI 3327 (mult:DI 3328 (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) 3329 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))) 3330 (const_int 32)))) 3331 (set (reg:SI MACL_REG) 3332 (mult:SI (match_dup 0) 3333 (match_dup 1)))] 3334 "TARGET_SH2" 3335 "dmulu.l %1,%0" 3336 [(set_attr "type" "dmpy")]) 3337 3338(define_expand "umulsidi3" 3339 [(set (match_operand:DI 0 "arith_reg_dest" "") 3340 (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) 3341 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))] 3342 "TARGET_SH2 || TARGET_SHMEDIA" 3343{ 3344 if (TARGET_SH2) 3345 { 3346 emit_insn (gen_umulsidi3_compact (operands[0], operands[1], operands[2])); 3347 DONE; 3348 } 3349}) 3350 3351(define_insn "umulsidi3_media" 3352 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 3353 (mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r")) 3354 (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))] 3355 "TARGET_SHMEDIA" 3356 "mulu.l %1, %2, %0" 3357 [(set_attr "type" "dmpy_media") 3358 (set_attr "highpart" "ignore")]) 3359 3360(define_insn_and_split "umulsidi3_compact" 3361 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 3362 (mult:DI 3363 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")) 3364 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r")))) 3365 (clobber (reg:SI MACH_REG)) 3366 (clobber (reg:SI MACL_REG))] 3367 "TARGET_SH2" 3368 "#" 3369 "&& 1" 3370 [(const_int 0)] 3371{ 3372 rtx low_dst = gen_lowpart (SImode, operands[0]); 3373 rtx high_dst = gen_highpart (SImode, operands[0]); 3374 3375 emit_insn (gen_umulsidi3_i (operands[1], operands[2])); 3376 3377 emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG)); 3378 emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG)); 3379 /* We need something to tag the possible REG_EQUAL notes on to. */ 3380 emit_move_insn (operands[0], operands[0]); 3381 DONE; 3382}) 3383 3384(define_insn "smulsi3_highpart_i" 3385 [(set (reg:SI MACH_REG) 3386 (truncate:SI 3387 (lshiftrt:DI 3388 (mult:DI 3389 (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) 3390 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))) 3391 (const_int 32)))) 3392 (clobber (reg:SI MACL_REG))] 3393 "TARGET_SH2" 3394 "dmuls.l %1,%0" 3395 [(set_attr "type" "dmpy")]) 3396 3397(define_expand "smulsi3_highpart" 3398 [(parallel 3399 [(set (reg:SI MACH_REG) 3400 (truncate:SI 3401 (lshiftrt:DI 3402 (mult:DI 3403 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) 3404 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))) 3405 (const_int 32)))) 3406 (clobber (reg:SI MACL_REG))]) 3407 (set (match_operand:SI 0 "arith_reg_operand" "") 3408 (reg:SI MACH_REG))] 3409 "TARGET_SH2" 3410{ 3411 rtx insn, mach; 3412 3413 mach = gen_rtx_REG (SImode, MACH_REG); 3414 start_sequence (); 3415 emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2])); 3416 insn = get_insns (); 3417 end_sequence (); 3418 /* expand_binop can't find a suitable code in mul_highpart_optab to 3419 make a REG_EQUAL note from, so make one here. 3420 See also {,u}mulhisi. 3421 ??? Alternatively, we could put this at the calling site of expand_binop, 3422 i.e. expand_mult_highpart. */ 3423 /* Use emit_libcall_block for loop invariant code motion and to make 3424 a REG_EQUAL note. */ 3425 emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn))); 3426 3427 DONE; 3428}) 3429 3430(define_insn "umulsi3_highpart_i" 3431 [(set (reg:SI MACH_REG) 3432 (truncate:SI 3433 (lshiftrt:DI 3434 (mult:DI 3435 (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) 3436 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))) 3437 (const_int 32)))) 3438 (clobber (reg:SI MACL_REG))] 3439 "TARGET_SH2" 3440 "dmulu.l %1,%0" 3441 [(set_attr "type" "dmpy")]) 3442 3443(define_expand "umulsi3_highpart" 3444 [(parallel 3445 [(set (reg:SI MACH_REG) 3446 (truncate:SI 3447 (lshiftrt:DI 3448 (mult:DI 3449 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) 3450 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))) 3451 (const_int 32)))) 3452 (clobber (reg:SI MACL_REG))]) 3453 (set (match_operand:SI 0 "arith_reg_operand" "") 3454 (reg:SI MACH_REG))] 3455 "TARGET_SH2" 3456{ 3457 rtx insn, mach; 3458 3459 mach = gen_rtx_REG (SImode, MACH_REG); 3460 start_sequence (); 3461 emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2])); 3462 insn = get_insns (); 3463 end_sequence (); 3464 /* Use emit_libcall_block for loop invariant code motion and to make 3465 a REG_EQUAL note. */ 3466 emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn))); 3467 3468 DONE; 3469}) 3470 3471(define_insn_and_split "muldi3" 3472 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 3473 (mult:DI (match_operand:DI 1 "arith_reg_operand" "r") 3474 (match_operand:DI 2 "arith_reg_operand" "r"))) 3475 (clobber (match_scratch:DI 3 "=&r")) 3476 (clobber (match_scratch:DI 4 "=r"))] 3477 "TARGET_SHMEDIA" 3478 "#" 3479 "reload_completed" 3480 [(const_int 0)] 3481{ 3482 rtx op3_v2si, op2_v2si; 3483 3484 op3_v2si = operands[3]; 3485 if (GET_CODE (op3_v2si) == SIGN_EXTEND) 3486 { 3487 op3_v2si = XEXP (op3_v2si, 0); 3488 op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0); 3489 } 3490 op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0); 3491 op2_v2si = operands[2]; 3492 if (GET_CODE (op2_v2si) == SIGN_EXTEND) 3493 { 3494 op2_v2si = XEXP (op2_v2si, 0); 3495 op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0); 3496 } 3497 op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0); 3498 emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32))); 3499 emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si)); 3500 emit_insn (gen_umulsidi3_media (operands[4], 3501 sh_gen_truncate (SImode, operands[1], 0), 3502 sh_gen_truncate (SImode, operands[2], 0))); 3503 emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL))); 3504 emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32))); 3505 emit_insn (gen_adddi3 (operands[0], operands[3], operands[0])); 3506 emit_insn (gen_adddi3 (operands[0], operands[4], operands[0])); 3507 DONE; 3508}) 3509 3510;; ------------------------------------------------------------------------- 3511;; Logical operations 3512;; ------------------------------------------------------------------------- 3513 3514(define_expand "andsi3" 3515 [(set (match_operand:SI 0 "arith_reg_operand" "") 3516 (and:SI (match_operand:SI 1 "logical_reg_operand" "") 3517 (match_operand:SI 2 "logical_and_operand" "")))] 3518 "" 3519{ 3520 /* If it is possible to turn the and insn into a zero extension 3521 already, redundant zero extensions will be folded, which results 3522 in better code. 3523 Ideally the splitter of *andsi_compact would be enough, if redundant 3524 zero extensions were detected after the combine pass, which does not 3525 happen at the moment. */ 3526 if (TARGET_SH1) 3527 { 3528 if (satisfies_constraint_Jmb (operands[2])) 3529 { 3530 emit_insn (gen_zero_extendqisi2 (operands[0], 3531 gen_lowpart (QImode, operands[1]))); 3532 DONE; 3533 } 3534 else if (satisfies_constraint_Jmw (operands[2])) 3535 { 3536 emit_insn (gen_zero_extendhisi2 (operands[0], 3537 gen_lowpart (HImode, operands[1]))); 3538 DONE; 3539 } 3540 } 3541}) 3542 3543(define_insn_and_split "*andsi_compact" 3544 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,z,r") 3545 (and:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,0,0") 3546 (match_operand:SI 2 "logical_and_operand" "Jmb,Jmw,K08,r")))] 3547 "TARGET_SH1" 3548 "@ 3549 extu.b %1,%0 3550 extu.w %1,%0 3551 and %2,%0 3552 and %2,%0" 3553 "&& 1" 3554 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))] 3555{ 3556 if (satisfies_constraint_Jmb (operands[2])) 3557 operands[1] = gen_lowpart (QImode, operands[1]); 3558 else if (satisfies_constraint_Jmw (operands[2])) 3559 operands[1] = gen_lowpart (HImode, operands[1]); 3560 else 3561 FAIL; 3562} 3563 [(set_attr "type" "arith")]) 3564 3565(define_insn "*andsi3_media" 3566 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 3567 (and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r") 3568 (match_operand:SI 2 "logical_operand" "r,I10")))] 3569 "TARGET_SHMEDIA" 3570 "@ 3571 and %1, %2, %0 3572 andi %1, %2, %0" 3573 [(set_attr "type" "arith_media")]) 3574 3575(define_insn "*andsi3_bclr" 3576 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 3577 (and:SI (match_operand:SI 1 "arith_reg_operand" "%0") 3578 (match_operand:SI 2 "const_int_operand" "Psz")))] 3579 "TARGET_SH2A && satisfies_constraint_Psz (operands[2])" 3580 "bclr %W2,%0" 3581 [(set_attr "type" "arith")]) 3582 3583(define_insn_and_split "anddi3" 3584 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r") 3585 (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r") 3586 (match_operand:DI 2 "and_operand" "r,I10,J16")))] 3587 "TARGET_SHMEDIA" 3588 "@ 3589 and %1, %2, %0 3590 andi %1, %2, %0 3591 #" 3592 "reload_completed 3593 && ! logical_operand (operands[2], DImode)" 3594 [(const_int 0)] 3595{ 3596 if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff) 3597 emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode))); 3598 else 3599 emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1])); 3600 DONE; 3601} 3602 [(set_attr "type" "arith_media")]) 3603 3604(define_insn "andcsi3" 3605 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 3606 (and:SI (match_operand:SI 1 "arith_reg_operand" "r") 3607 (not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))] 3608 "TARGET_SHMEDIA" 3609 "andc %1,%2,%0" 3610 [(set_attr "type" "arith_media")]) 3611 3612(define_insn "andcdi3" 3613 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 3614 (and:DI (match_operand:DI 1 "arith_reg_operand" "r") 3615 (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))] 3616 "TARGET_SHMEDIA" 3617 "andc %1,%2,%0" 3618 [(set_attr "type" "arith_media")]) 3619 3620(define_expand "iorsi3" 3621 [(set (match_operand:SI 0 "arith_reg_operand" "") 3622 (ior:SI (match_operand:SI 1 "logical_reg_operand" "") 3623 (match_operand:SI 2 "logical_operand" "")))] 3624 "" 3625 "") 3626 3627(define_insn "*iorsi3_compact" 3628 [(set (match_operand:SI 0 "arith_reg_dest" "=r,z") 3629 (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") 3630 (match_operand:SI 2 "logical_operand" "r,K08")))] 3631 "TARGET_SH1 3632 && !(TARGET_SH2A && satisfies_constraint_Pso (operands[2]))" 3633 "or %2,%0" 3634 [(set_attr "type" "arith")]) 3635 3636(define_insn "*iorsi3_media" 3637 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 3638 (ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r") 3639 (match_operand:SI 2 "logical_operand" "r,I10")))] 3640 "TARGET_SHMEDIA" 3641 "@ 3642 or %1, %2, %0 3643 ori %1, %2, %0" 3644 [(set_attr "type" "arith_media")]) 3645 3646(define_insn "*iorsi3_bset" 3647 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 3648 (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0") 3649 (match_operand:SI 2 "const_int_operand" "Pso")))] 3650 "TARGET_SH2A && satisfies_constraint_Pso (operands[2])" 3651 "bset %V2,%0" 3652 [(set_attr "type" "arith")]) 3653 3654(define_insn "iordi3" 3655 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") 3656 (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r") 3657 (match_operand:DI 2 "logical_operand" "r,I10")))] 3658 "TARGET_SHMEDIA" 3659 "@ 3660 or %1, %2, %0 3661 ori %1, %2, %0" 3662 [(set_attr "type" "arith_media")]) 3663 3664(define_insn_and_split "*logical_sidi3" 3665 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") 3666 (sign_extend:DI (match_operator:SI 3 "logical_operator" 3667 [(match_operand:SI 1 "arith_reg_operand" "%r,r") 3668 (match_operand:SI 2 "logical_operand" "r,I10")])))] 3669 "TARGET_SHMEDIA" 3670 "#" 3671 "&& reload_completed" 3672 [(set (match_dup 0) (match_dup 3))] 3673{ 3674 operands[3] 3675 = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode, 3676 simplify_gen_subreg (DImode, operands[1], SImode, 0), 3677 simplify_gen_subreg (DImode, operands[2], SImode, 0)); 3678}) 3679 3680(define_insn_and_split "*logical_sidisi3" 3681 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 3682 (truncate:SI (sign_extend:DI 3683 (match_operator:SI 3 "logical_operator" 3684 [(match_operand:SI 1 "arith_reg_operand" "%r,r") 3685 (match_operand:SI 2 "logical_operand" "r,I10")]))))] 3686 "TARGET_SHMEDIA" 3687 "#" 3688 "&& 1" 3689 [(set (match_dup 0) (match_dup 3))]) 3690 3691(define_insn_and_split "*logical_sidi3_2" 3692 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") 3693 (sign_extend:DI (truncate:SI (sign_extend:DI 3694 (match_operator:SI 3 "logical_operator" 3695 [(match_operand:SI 1 "arith_reg_operand" "%r,r") 3696 (match_operand:SI 2 "logical_operand" "r,I10")])))))] 3697 "TARGET_SHMEDIA" 3698 "#" 3699 "&& 1" 3700 [(set (match_dup 0) (sign_extend:DI (match_dup 3)))]) 3701 3702(define_expand "xorsi3" 3703 [(set (match_operand:SI 0 "arith_reg_operand" "") 3704 (xor:SI (match_operand:SI 1 "logical_reg_operand" "") 3705 (match_operand:SI 2 "xor_operand" "")))] 3706 "" 3707 "") 3708 3709(define_insn "*xorsi3_compact" 3710 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r") 3711 (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") 3712 (match_operand:SI 2 "logical_operand" "K08,r")))] 3713 "TARGET_SH1" 3714 "xor %2,%0" 3715 [(set_attr "type" "arith")]) 3716 3717;; The *logical_op_t pattern helps combine eliminating sign/zero extensions 3718;; of results where one of the inputs is a T bit store. Notice that this 3719;; pattern must not match during reload. If reload picks this pattern it 3720;; will be impossible to split it afterwards. 3721(define_insn_and_split "*logical_op_t" 3722 [(set (match_operand:SI 0 "arith_reg_dest") 3723 (match_operator:SI 3 "logical_operator" 3724 [(match_operand:SI 1 "arith_reg_operand") 3725 (match_operand:SI 2 "t_reg_operand")]))] 3726 "TARGET_SH1 && can_create_pseudo_p ()" 3727 "#" 3728 "&& 1" 3729 [(set (match_dup 4) (reg:SI T_REG)) 3730 (set (match_dup 0) (match_dup 3))] 3731{ 3732 operands[4] = gen_reg_rtx (SImode); 3733 operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode, 3734 operands[1], operands[4]); 3735}) 3736 3737(define_insn "*xorsi3_media" 3738 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 3739 (xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r") 3740 (match_operand:SI 2 "xor_operand" "r,I06")))] 3741 "TARGET_SHMEDIA" 3742 "@ 3743 xor %1, %2, %0 3744 xori %1, %2, %0" 3745 [(set_attr "type" "arith_media")]) 3746 3747(define_insn "xordi3" 3748 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") 3749 (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r") 3750 (match_operand:DI 2 "xor_operand" "r,I06")))] 3751 "TARGET_SHMEDIA" 3752 "@ 3753 xor %1, %2, %0 3754 xori %1, %2, %0" 3755 [(set_attr "type" "arith_media")]) 3756 3757;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate. 3758;; converts 2 * sign extend -> logical op into logical op -> sign extend 3759(define_split 3760 [(set (match_operand:DI 0 "arith_reg_dest" "") 3761 (sign_extend:DI (match_operator 4 "binary_logical_operator" 3762 [(match_operand 1 "any_register_operand" "") 3763 (match_operand 2 "any_register_operand" "")])))] 3764 "TARGET_SHMEDIA" 3765 [(set (match_dup 5) (match_dup 4)) 3766 (set (match_dup 0) (sign_extend:DI (match_dup 5)))] 3767{ 3768 enum machine_mode inmode = GET_MODE (operands[1]); 3769 int offset = 0; 3770 3771 if (GET_CODE (operands[0]) == SUBREG) 3772 { 3773 offset = SUBREG_BYTE (operands[0]); 3774 operands[0] = SUBREG_REG (operands[0]); 3775 } 3776 gcc_assert (REG_P (operands[0])); 3777 if (! TARGET_LITTLE_ENDIAN) 3778 offset += 8 - GET_MODE_SIZE (inmode); 3779 operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset); 3780}) 3781 3782;; ------------------------------------------------------------------------- 3783;; Shifts and rotates 3784;; ------------------------------------------------------------------------- 3785 3786(define_expand "rotldi3" 3787 [(set (match_operand:DI 0 "arith_reg_dest" "") 3788 (rotate:DI (match_operand:DI 1 "arith_reg_operand" "") 3789 (match_operand:HI 2 "mextr_bit_offset" "")))] 3790 "TARGET_SHMEDIA" 3791{ 3792 if (! mextr_bit_offset (operands[2], HImode)) 3793 FAIL; 3794}) 3795 3796(define_insn "rotldi3_mextr" 3797 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 3798 (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r") 3799 (match_operand:HI 2 "mextr_bit_offset" "i")))] 3800 "TARGET_SHMEDIA" 3801{ 3802 static char templ[16]; 3803 sprintf (templ, "mextr%d %%1,%%1,%%0", 3804 8 - (int) (INTVAL (operands[2]) >> 3)); 3805 return templ; 3806} 3807 [(set_attr "type" "arith_media")]) 3808 3809(define_expand "rotrdi3" 3810 [(set (match_operand:DI 0 "arith_reg_dest" "") 3811 (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "") 3812 (match_operand:HI 2 "mextr_bit_offset" "")))] 3813 "TARGET_SHMEDIA" 3814{ 3815 if (! mextr_bit_offset (operands[2], HImode)) 3816 FAIL; 3817}) 3818 3819(define_insn "rotrdi3_mextr" 3820 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 3821 (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r") 3822 (match_operand:HI 2 "mextr_bit_offset" "i")))] 3823 "TARGET_SHMEDIA" 3824{ 3825 static char templ[16]; 3826 sprintf (templ, "mextr%d %%1,%%1,%%0", (int) INTVAL (operands[2]) >> 3); 3827 return templ; 3828} 3829 [(set_attr "type" "arith_media")]) 3830 3831(define_split 3832 [(set (match_operand:DI 0 "arith_reg_dest" "") 3833 (ior:DI (zero_extend:DI (mem:QI (match_operand 1 3834 "ua_address_operand" ""))) 3835 (ashift:DI (match_operand:DI 2 "arith_reg_operand" "") 3836 (const_int 8)))) 3837 (clobber (match_operand:DI 3 "register_operand" ""))] 3838 "TARGET_SHMEDIA" 3839 [(match_dup 4) (match_dup 5)] 3840{ 3841 operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q) 3842 (operands[3], operands[1])); 3843 operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2], 3844 GEN_INT (56), GEN_INT (8)); 3845}) 3846 3847(define_expand "rotrsi3" 3848 [(set (match_operand:SI 0 "arith_reg_dest") 3849 (rotatert:SI (match_operand:SI 1 "arith_reg_operand") 3850 (match_operand:SI 2 "const_int_operand")))] 3851 "TARGET_SH1" 3852{ 3853 HOST_WIDE_INT ival = INTVAL (operands[2]); 3854 if (ival == 1) 3855 { 3856 emit_insn (gen_rotrsi3_1 (operands[0], operands[1])); 3857 DONE; 3858 } 3859 3860 FAIL; 3861}) 3862 3863(define_insn "rotrsi3_1" 3864 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 3865 (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0") 3866 (const_int 1))) 3867 (set (reg:SI T_REG) 3868 (and:SI (match_dup 1) (const_int 1)))] 3869 "TARGET_SH1" 3870 "rotr %0" 3871 [(set_attr "type" "arith")]) 3872 3873;; A slimplified version of rotr for combine. 3874(define_insn "*rotrsi3_1" 3875 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 3876 (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0") 3877 (const_int 1))) 3878 (clobber (reg:SI T_REG))] 3879 "TARGET_SH1" 3880 "rotr %0" 3881 [(set_attr "type" "arith")]) 3882 3883(define_insn "rotlsi3_1" 3884 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 3885 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0") 3886 (const_int 1))) 3887 (set (reg:SI T_REG) 3888 (lshiftrt:SI (match_dup 1) (const_int 31)))] 3889 "TARGET_SH1" 3890 "rotl %0" 3891 [(set_attr "type" "arith")]) 3892 3893;; A simplified version of rotl for combine. 3894(define_insn "*rotlsi3_1" 3895 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 3896 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0") 3897 (const_int 1))) 3898 (clobber (reg:SI T_REG))] 3899 "TARGET_SH1" 3900 "rotl %0" 3901 [(set_attr "type" "arith")]) 3902 3903(define_insn "rotlsi3_31" 3904 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 3905 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0") 3906 (const_int 31))) 3907 (clobber (reg:SI T_REG))] 3908 "TARGET_SH1" 3909 "rotr %0" 3910 [(set_attr "type" "arith")]) 3911 3912(define_insn "rotlsi3_16" 3913 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 3914 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r") 3915 (const_int 16)))] 3916 "TARGET_SH1" 3917 "swap.w %1,%0" 3918 [(set_attr "type" "arith")]) 3919 3920(define_expand "rotlsi3" 3921 [(set (match_operand:SI 0 "arith_reg_dest") 3922 (rotate:SI (match_operand:SI 1 "arith_reg_operand") 3923 (match_operand:SI 2 "const_int_operand")))] 3924 "TARGET_SH1" 3925{ 3926 static const char rot_tab[] = { 3927 000, 000, 000, 000, 000, 000, 010, 001, 3928 001, 001, 011, 013, 003, 003, 003, 003, 3929 003, 003, 003, 003, 003, 013, 012, 002, 3930 002, 002, 010, 000, 000, 000, 000, 000, 3931 }; 3932 3933 int count = INTVAL (operands[2]); 3934 int choice = rot_tab[count]; 3935 if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1) 3936 FAIL; 3937 choice &= 7; 3938 switch (choice) 3939 { 3940 case 0: 3941 emit_move_insn (operands[0], operands[1]); 3942 count -= (count & 16) * 2; 3943 break; 3944 case 3: 3945 emit_insn (gen_rotlsi3_16 (operands[0], operands[1])); 3946 count -= 16; 3947 break; 3948 case 1: 3949 case 2: 3950 { 3951 rtx parts[2]; 3952 parts[0] = gen_reg_rtx (SImode); 3953 parts[1] = gen_reg_rtx (SImode); 3954 emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1])); 3955 emit_move_insn (parts[choice-1], operands[1]); 3956 emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8))); 3957 emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8))); 3958 emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1])); 3959 count = (count & ~16) - 8; 3960 } 3961 } 3962 3963 for (; count > 0; count--) 3964 emit_insn (gen_rotlsi3_1 (operands[0], operands[0])); 3965 for (; count < 0; count++) 3966 emit_insn (gen_rotlsi3_31 (operands[0], operands[0])); 3967 3968 DONE; 3969}) 3970 3971(define_insn "*rotlhi3_8" 3972 [(set (match_operand:HI 0 "arith_reg_dest" "=r") 3973 (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r") 3974 (const_int 8)))] 3975 "TARGET_SH1" 3976 "swap.b %1,%0" 3977 [(set_attr "type" "arith")]) 3978 3979(define_expand "rotlhi3" 3980 [(set (match_operand:HI 0 "arith_reg_operand") 3981 (rotate:HI (match_operand:HI 1 "arith_reg_operand") 3982 (match_operand:HI 2 "const_int_operand")))] 3983 "TARGET_SH1" 3984{ 3985 if (INTVAL (operands[2]) != 8) 3986 FAIL; 3987}) 3988 3989;; The rotcr and rotcl insns are used primarily in DImode shifts by one. 3990;; They can also be used to implement things like 3991;; bool t = a == b; 3992;; int x0 = (y >> 1) | (t << 31); // rotcr 3993;; int x1 = (y << 1) | t; // rotcl 3994(define_insn "rotcr" 3995 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 3996 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 3997 (const_int 1)) 3998 (ashift:SI (match_operand:SI 2 "t_reg_operand") 3999 (const_int 31)))) 4000 (set (reg:SI T_REG) 4001 (and:SI (match_dup 1) (const_int 1)))] 4002 "TARGET_SH1" 4003 "rotcr %0" 4004 [(set_attr "type" "arith")]) 4005 4006(define_insn "rotcl" 4007 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4008 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") 4009 (const_int 1)) 4010 (match_operand:SI 2 "t_reg_operand"))) 4011 (set (reg:SI T_REG) 4012 (lshiftrt:SI (match_dup 1) (const_int 31)))] 4013 "TARGET_SH1" 4014 "rotcl %0" 4015 [(set_attr "type" "arith")]) 4016 4017;; Simplified rotcr version for combine, which allows arbitrary shift 4018;; amounts for the reg. If the shift amount is '1' rotcr can be used 4019;; directly. Otherwise we have to insert a shift in between. 4020(define_insn_and_split "*rotcr" 4021 [(set (match_operand:SI 0 "arith_reg_dest") 4022 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand") 4023 (match_operand:SI 2 "const_int_operand")) 4024 (ashift:SI (match_operand:SI 3 "arith_reg_or_t_reg_operand") 4025 (const_int 31)))) 4026 (clobber (reg:SI T_REG))] 4027 "TARGET_SH1" 4028 "#" 4029 "&& can_create_pseudo_p ()" 4030 [(const_int 0)] 4031{ 4032 if (INTVAL (operands[2]) > 1) 4033 { 4034 const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1); 4035 rtx prev_set_t_insn = NULL_RTX; 4036 rtx tmp_t_reg = NULL_RTX; 4037 4038 /* If we're going to emit a shift sequence that clobbers the T_REG, 4039 try to find the previous insn that sets the T_REG and emit the 4040 shift insn before that insn, to remove the T_REG dependency. 4041 If the insn that sets the T_REG cannot be found, store the T_REG 4042 in a temporary reg and restore it after the shift. */ 4043 if (sh_lshrsi_clobbers_t_reg_p (shift_count) 4044 && ! sh_dynamicalize_shift_p (shift_count)) 4045 { 4046 prev_set_t_insn = prev_nonnote_insn_bb (curr_insn); 4047 4048 /* Skip the nott insn, which was probably inserted by the splitter 4049 of *rotcr_neg_t. Don't use one of the recog functions 4050 here during insn splitting, since that causes problems in later 4051 passes. */ 4052 if (prev_set_t_insn != NULL_RTX) 4053 { 4054 rtx pat = PATTERN (prev_set_t_insn); 4055 if (GET_CODE (pat) == SET 4056 && t_reg_operand (XEXP (pat, 0), SImode) 4057 && negt_reg_operand (XEXP (pat, 1), SImode)) 4058 prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn); 4059 } 4060 4061 if (! (prev_set_t_insn != NULL_RTX 4062 && reg_set_p (get_t_reg_rtx (), prev_set_t_insn) 4063 && ! reg_referenced_p (get_t_reg_rtx (), 4064 PATTERN (prev_set_t_insn)))) 4065 { 4066 prev_set_t_insn = NULL_RTX; 4067 tmp_t_reg = gen_reg_rtx (SImode); 4068 emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ())); 4069 } 4070 } 4071 4072 rtx shift_result = gen_reg_rtx (SImode); 4073 rtx shift_insn = gen_lshrsi3 (shift_result, operands[1], shift_count); 4074 operands[1] = shift_result; 4075 4076 /* Emit the shift insn before the insn that sets T_REG, if possible. */ 4077 if (prev_set_t_insn != NULL_RTX) 4078 emit_insn_before (shift_insn, prev_set_t_insn); 4079 else 4080 emit_insn (shift_insn); 4081 4082 /* Restore T_REG if it has been saved before. */ 4083 if (tmp_t_reg != NULL_RTX) 4084 emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx)); 4085 } 4086 4087 /* For the rotcr insn to work, operands[3] must be in T_REG. 4088 If it is not we can get it there by shifting it right one bit. 4089 In this case T_REG is not an input for this insn, thus we don't have to 4090 pay attention as of where to insert the shlr insn. */ 4091 if (! t_reg_operand (operands[3], SImode)) 4092 { 4093 /* We don't care about the shifted result here, only the T_REG. */ 4094 emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3])); 4095 operands[3] = get_t_reg_rtx (); 4096 } 4097 4098 emit_insn (gen_rotcr (operands[0], operands[1], operands[3])); 4099 DONE; 4100}) 4101 4102;; If combine tries the same as above but with swapped operands, split 4103;; it so that it will try the pattern above. 4104(define_split 4105 [(set (match_operand:SI 0 "arith_reg_dest") 4106 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_or_t_reg_operand") 4107 (const_int 31)) 4108 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand") 4109 (match_operand:SI 3 "const_int_operand"))))] 4110 "TARGET_SH1 && can_create_pseudo_p ()" 4111 [(parallel [(set (match_dup 0) 4112 (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3)) 4113 (ashift:SI (match_dup 1) (const_int 31)))) 4114 (clobber (reg:SI T_REG))])]) 4115 4116;; Basically the same as the rotcr pattern above, but for rotcl. 4117;; FIXME: Fold copy pasted split code for rotcr and rotcl. 4118(define_insn_and_split "*rotcl" 4119 [(set (match_operand:SI 0 "arith_reg_dest") 4120 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand") 4121 (match_operand:SI 2 "const_int_operand")) 4122 (and:SI (match_operand:SI 3 "arith_reg_or_t_reg_operand") 4123 (const_int 1)))) 4124 (clobber (reg:SI T_REG))] 4125 "TARGET_SH1" 4126 "#" 4127 "&& can_create_pseudo_p ()" 4128 [(const_int 0)] 4129{ 4130 gcc_assert (INTVAL (operands[2]) > 0); 4131 4132 if (INTVAL (operands[2]) > 1) 4133 { 4134 const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1); 4135 rtx prev_set_t_insn = NULL_RTX; 4136 rtx tmp_t_reg = NULL_RTX; 4137 4138 /* If we're going to emit a shift sequence that clobbers the T_REG, 4139 try to find the previous insn that sets the T_REG and emit the 4140 shift insn before that insn, to remove the T_REG dependency. 4141 If the insn that sets the T_REG cannot be found, store the T_REG 4142 in a temporary reg and restore it after the shift. */ 4143 if (sh_ashlsi_clobbers_t_reg_p (shift_count) 4144 && ! sh_dynamicalize_shift_p (shift_count)) 4145 { 4146 prev_set_t_insn = prev_nonnote_insn_bb (curr_insn); 4147 4148 /* Skip the nott insn, which was probably inserted by the splitter 4149 of *rotcl_neg_t. Don't use one of the recog functions 4150 here during insn splitting, since that causes problems in later 4151 passes. */ 4152 if (prev_set_t_insn != NULL_RTX) 4153 { 4154 rtx pat = PATTERN (prev_set_t_insn); 4155 if (GET_CODE (pat) == SET 4156 && t_reg_operand (XEXP (pat, 0), SImode) 4157 && negt_reg_operand (XEXP (pat, 1), SImode)) 4158 prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn); 4159 } 4160 4161 if (! (prev_set_t_insn != NULL_RTX 4162 && reg_set_p (get_t_reg_rtx (), prev_set_t_insn) 4163 && ! reg_referenced_p (get_t_reg_rtx (), 4164 PATTERN (prev_set_t_insn)))) 4165 { 4166 prev_set_t_insn = NULL_RTX; 4167 tmp_t_reg = gen_reg_rtx (SImode); 4168 emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ())); 4169 } 4170 } 4171 4172 rtx shift_result = gen_reg_rtx (SImode); 4173 rtx shift_insn = gen_ashlsi3 (shift_result, operands[1], shift_count); 4174 operands[1] = shift_result; 4175 4176 /* Emit the shift insn before the insn that sets T_REG, if possible. */ 4177 if (prev_set_t_insn != NULL_RTX) 4178 emit_insn_before (shift_insn, prev_set_t_insn); 4179 else 4180 emit_insn (shift_insn); 4181 4182 /* Restore T_REG if it has been saved before. */ 4183 if (tmp_t_reg != NULL_RTX) 4184 emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx)); 4185 } 4186 4187 /* For the rotcl insn to work, operands[3] must be in T_REG. 4188 If it is not we can get it there by shifting it right one bit. 4189 In this case T_REG is not an input for this insn, thus we don't have to 4190 pay attention as of where to insert the shlr insn. */ 4191 if (! t_reg_operand (operands[3], SImode)) 4192 { 4193 /* We don't care about the shifted result here, only the T_REG. */ 4194 emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3])); 4195 operands[3] = get_t_reg_rtx (); 4196 } 4197 4198 emit_insn (gen_rotcl (operands[0], operands[1], operands[3])); 4199 DONE; 4200}) 4201 4202;; rotcl combine pattern variations 4203(define_insn_and_split "*rotcl" 4204 [(set (match_operand:SI 0 "arith_reg_dest") 4205 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand") 4206 (match_operand:SI 2 "const_int_operand")) 4207 (match_operand:SI 3 "t_reg_operand"))) 4208 (clobber (reg:SI T_REG))] 4209 "TARGET_SH1" 4210 "#" 4211 "&& can_create_pseudo_p ()" 4212 [(parallel [(set (match_dup 0) 4213 (ior:SI (ashift:SI (match_dup 1) (match_dup 2)) 4214 (and:SI (match_dup 3) (const_int 1)))) 4215 (clobber (reg:SI T_REG))])]) 4216 4217(define_insn_and_split "*rotcl" 4218 [(set (match_operand:SI 0 "arith_reg_dest") 4219 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_or_t_reg_operand") 4220 (const_int 1)) 4221 (ashift:SI (match_operand:SI 2 "arith_reg_operand") 4222 (match_operand:SI 3 "const_int_operand")))) 4223 (clobber (reg:SI T_REG))] 4224 "TARGET_SH1" 4225 "#" 4226 "&& can_create_pseudo_p ()" 4227 [(parallel [(set (match_dup 0) 4228 (ior:SI (ashift:SI (match_dup 2) (match_dup 3)) 4229 (and:SI (match_dup 1) (const_int 1)))) 4230 (clobber (reg:SI T_REG))])]) 4231 4232(define_insn_and_split "*rotcl" 4233 [(set (match_operand:SI 0 "arith_reg_dest") 4234 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand") 4235 (match_operand:SI 2 "const_int_operand")) 4236 (lshiftrt:SI (match_operand:SI 3 "arith_reg_operand") 4237 (const_int 31)))) 4238 (clobber (reg:SI T_REG))] 4239 "TARGET_SH1" 4240 "#" 4241 "&& can_create_pseudo_p ()" 4242 [(parallel [(set (match_dup 0) 4243 (ior:SI (ashift:SI (match_dup 1) (match_dup 2)) 4244 (and:SI (reg:SI T_REG) (const_int 1)))) 4245 (clobber (reg:SI T_REG))])] 4246{ 4247 /* We don't care about the result of the left shift, only the T_REG. */ 4248 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3])); 4249}) 4250 4251(define_insn_and_split "*rotcl" 4252 [(set (match_operand:SI 0 "arith_reg_dest") 4253 (ior:SI (lshiftrt:SI (match_operand:SI 3 "arith_reg_operand") 4254 (const_int 31)) 4255 (ashift:SI (match_operand:SI 1 "arith_reg_operand") 4256 (match_operand:SI 2 "const_int_operand")))) 4257 (clobber (reg:SI T_REG))] 4258 "TARGET_SH1" 4259 "#" 4260 "&& can_create_pseudo_p ()" 4261 [(parallel [(set (match_dup 0) 4262 (ior:SI (ashift:SI (match_dup 1) (match_dup 2)) 4263 (and:SI (reg:SI T_REG) (const_int 1)))) 4264 (clobber (reg:SI T_REG))])] 4265{ 4266 /* We don't care about the result of the left shift, only the T_REG. */ 4267 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3])); 4268}) 4269 4270;; rotcr combine bridge pattern which will make combine try out more 4271;; complex patterns. 4272(define_insn_and_split "*rotcr" 4273 [(set (match_operand:SI 0 "arith_reg_dest") 4274 (ashift:SI (match_operand:SI 1 "t_reg_operand") (const_int 31)))] 4275 "TARGET_SH1" 4276 "#" 4277 "&& 1" 4278 [(set (match_dup 0) (match_dup 1)) 4279 (parallel [(set (match_dup 0) 4280 (ior:SI (lshiftrt:SI (match_dup 0) (const_int 1)) 4281 (ashift:SI (match_dup 1) (const_int 31)))) 4282 (set (reg:SI T_REG) 4283 (and:SI (match_dup 0) (const_int 1)))])]) 4284 4285(define_insn_and_split "*rotcr" 4286 [(set (match_operand:SI 0 "arith_reg_dest") 4287 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand") 4288 (const_int -2147483648)) ;; 0xffffffff80000000 4289 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand") 4290 (const_int 1)))) 4291 (clobber (reg:SI T_REG))] 4292 "TARGET_SH1" 4293 "#" 4294 "&& can_create_pseudo_p ()" 4295 [(const_int 0)] 4296{ 4297 rtx tmp = gen_reg_rtx (SImode); 4298 emit_insn (gen_shll (tmp, operands[1])); 4299 emit_insn (gen_rotcr (operands[0], operands[2], get_t_reg_rtx ())); 4300 DONE; 4301}) 4302 4303;; rotcr combine patterns for rotating in the negated T_REG value. 4304(define_insn_and_split "*rotcr_neg_t" 4305 [(set (match_operand:SI 0 "arith_reg_dest") 4306 (ior:SI (match_operand:SI 1 "negt_reg_shl31_operand") 4307 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand") 4308 (match_operand:SI 3 "const_int_operand")))) 4309 (clobber (reg:SI T_REG))] 4310 "TARGET_SH1" 4311 "#" 4312 "&& can_create_pseudo_p ()" 4313 [(parallel [(set (match_dup 0) 4314 (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3)) 4315 (ashift:SI (reg:SI T_REG) (const_int 31)))) 4316 (clobber (reg:SI T_REG))])] 4317{ 4318 emit_insn (gen_nott (get_t_reg_rtx ())); 4319}) 4320 4321(define_insn_and_split "*rotcr_neg_t" 4322 [(set (match_operand:SI 0 "arith_reg_dest") 4323 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand") 4324 (match_operand:SI 2 "const_int_operand")) 4325 (match_operand:SI 3 "negt_reg_shl31_operand"))) 4326 (clobber (reg:SI T_REG))] 4327 "TARGET_SH1" 4328 "#" 4329 "&& can_create_pseudo_p ()" 4330 [(parallel [(set (match_dup 0) 4331 (ior:SI (lshiftrt:SI (match_dup 1) (match_dup 2)) 4332 (ashift:SI (reg:SI T_REG) (const_int 31)))) 4333 (clobber (reg:SI T_REG))])] 4334{ 4335 emit_insn (gen_nott (get_t_reg_rtx ())); 4336}) 4337 4338;; rotcl combine patterns for rotating in the negated T_REG value. 4339;; For some strange reason these have to be specified as splits which combine 4340;; will pick up. If they are specified as insn_and_split like the 4341;; *rotcr_neg_t patterns above, combine would recognize them successfully 4342;; but not emit them on non-SH2A targets. 4343(define_split 4344 [(set (match_operand:SI 0 "arith_reg_dest") 4345 (ior:SI (match_operand:SI 1 "negt_reg_operand") 4346 (ashift:SI (match_operand:SI 2 "arith_reg_operand") 4347 (match_operand:SI 3 "const_int_operand"))))] 4348 "TARGET_SH1" 4349 [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1))) 4350 (parallel [(set (match_dup 0) 4351 (ior:SI (ashift:SI (match_dup 2) (match_dup 3)) 4352 (and:SI (reg:SI T_REG) (const_int 1)))) 4353 (clobber (reg:SI T_REG))])]) 4354 4355(define_split 4356 [(set (match_operand:SI 0 "arith_reg_dest") 4357 (ior:SI (ashift:SI (match_operand:SI 2 "arith_reg_operand") 4358 (match_operand:SI 3 "const_int_operand")) 4359 (match_operand:SI 1 "negt_reg_operand")))] 4360 "TARGET_SH1" 4361 [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1))) 4362 (parallel [(set (match_dup 0) 4363 (ior:SI (ashift:SI (match_dup 2) (match_dup 3)) 4364 (and:SI (reg:SI T_REG) (const_int 1)))) 4365 (clobber (reg:SI T_REG))])]) 4366 4367;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4368;; SImode shift left 4369 4370(define_expand "ashlsi3" 4371 [(set (match_operand:SI 0 "arith_reg_operand" "") 4372 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "") 4373 (match_operand:SI 2 "shift_count_operand" "")))] 4374 "" 4375{ 4376 if (TARGET_SHMEDIA) 4377 { 4378 emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2])); 4379 DONE; 4380 } 4381 if (TARGET_DYNSHIFT 4382 && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2])) 4383 operands[2] = force_reg (SImode, operands[2]); 4384 4385 /* If the ashlsi3_* insn is going to clobber the T_REG it must be 4386 expanded here. */ 4387 if (CONST_INT_P (operands[2]) 4388 && sh_ashlsi_clobbers_t_reg_p (operands[2]) 4389 && ! sh_dynamicalize_shift_p (operands[2])) 4390 { 4391 emit_insn (gen_ashlsi3_n_clobbers_t (operands[0], operands[1], 4392 operands[2])); 4393 DONE; 4394 } 4395 4396 /* Expand a library call for the dynamic shift. */ 4397 if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT) 4398 { 4399 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]); 4400 rtx funcaddr = gen_reg_rtx (Pmode); 4401 function_symbol (funcaddr, "__ashlsi3_r0", SFUNC_STATIC); 4402 emit_insn (gen_ashlsi3_d_call (operands[0], operands[2], funcaddr)); 4403 4404 DONE; 4405 } 4406}) 4407 4408(define_insn "ashlsi3_k" 4409 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 4410 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0") 4411 (match_operand:SI 2 "p27_shift_count_operand" "M,P27")))] 4412 "TARGET_SH1" 4413 "@ 4414 add %0,%0 4415 shll%O2 %0" 4416 [(set_attr "type" "arith")]) 4417 4418(define_insn_and_split "ashlsi3_d" 4419 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4420 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") 4421 (match_operand:SI 2 "shift_count_operand" "r")))] 4422 "TARGET_DYNSHIFT" 4423 "shld %2,%0" 4424 "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2]) 4425 && ! sh_ashlsi_clobbers_t_reg_p (operands[2])" 4426 [(const_int 0)] 4427{ 4428 if (satisfies_constraint_P27 (operands[2])) 4429 { 4430 emit_insn (gen_ashlsi3_k (operands[0], operands[1], operands[2])); 4431 DONE; 4432 } 4433 else if (! satisfies_constraint_P27 (operands[2])) 4434 { 4435 /* This must happen before reload, otherwise the constant will be moved 4436 into a register due to the "r" constraint, after which this split 4437 cannot be done anymore. 4438 Unfortunately the move insn will not always be eliminated. 4439 Also, here we must not create a shift sequence that clobbers the 4440 T_REG. */ 4441 emit_move_insn (operands[0], operands[1]); 4442 gen_shifty_op (ASHIFT, operands); 4443 DONE; 4444 } 4445 4446 FAIL; 4447} 4448 [(set_attr "type" "dyn_shift")]) 4449 4450;; If dynamic shifts are not available use a library function. 4451;; By specifying the pattern we reduce the number of call clobbered regs. 4452;; In order to make combine understand the truncation of the shift amount 4453;; operand we have to allow it to use pseudo regs for the shift operands. 4454(define_insn "ashlsi3_d_call" 4455 [(set (match_operand:SI 0 "arith_reg_dest" "=z") 4456 (ashift:SI (reg:SI R4_REG) 4457 (and:SI (match_operand:SI 1 "arith_reg_operand" "z") 4458 (const_int 31)))) 4459 (use (match_operand:SI 2 "arith_reg_operand" "r")) 4460 (clobber (reg:SI T_REG)) 4461 (clobber (reg:SI PR_REG))] 4462 "TARGET_SH1 && !TARGET_DYNSHIFT" 4463 "jsr @%2%#" 4464 [(set_attr "type" "sfunc") 4465 (set_attr "needs_delay_slot" "yes")]) 4466 4467(define_insn_and_split "ashlsi3_n" 4468 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4469 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") 4470 (match_operand:SI 2 "not_p27_shift_count_operand" "")))] 4471 "TARGET_SH1 && ! sh_ashlsi_clobbers_t_reg_p (operands[2])" 4472 "#" 4473 "&& (reload_completed 4474 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))" 4475 [(const_int 0)] 4476{ 4477 if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()) 4478 { 4479 /* If this pattern was picked and dynamic shifts are supported, switch 4480 to dynamic shift pattern before reload. */ 4481 operands[2] = force_reg (SImode, operands[2]); 4482 emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2])); 4483 } 4484 else 4485 gen_shifty_op (ASHIFT, operands); 4486 4487 DONE; 4488}) 4489 4490(define_insn_and_split "ashlsi3_n_clobbers_t" 4491 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4492 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") 4493 (match_operand:SI 2 "not_p27_shift_count_operand" ""))) 4494 (clobber (reg:SI T_REG))] 4495 "TARGET_SH1 && sh_ashlsi_clobbers_t_reg_p (operands[2])" 4496 "#" 4497 "&& (reload_completed || INTVAL (operands[2]) == 31 4498 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))" 4499 [(const_int 0)] 4500{ 4501 if (INTVAL (operands[2]) == 31) 4502 { 4503 /* If the shift amount is 31 we split into a different sequence before 4504 reload so that it gets a chance to allocate R0 for the sequence. 4505 If it fails to do so (due to pressure on R0), it will take one insn 4506 more for the and. */ 4507 emit_insn (gen_andsi3 (operands[0], operands[1], const1_rtx)); 4508 emit_insn (gen_rotlsi3_31 (operands[0], operands[0])); 4509 } 4510 else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()) 4511 { 4512 /* If this pattern was picked and dynamic shifts are supported, switch 4513 to dynamic shift pattern before reload. */ 4514 operands[2] = force_reg (SImode, operands[2]); 4515 emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2])); 4516 } 4517 else 4518 gen_shifty_op (ASHIFT, operands); 4519 4520 DONE; 4521}) 4522 4523(define_insn "shll" 4524 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4525 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1))) 4526 (set (reg:SI T_REG) 4527 (lt:SI (match_dup 1) (const_int 0)))] 4528 "TARGET_SH1" 4529 "shll %0" 4530 [(set_attr "type" "arith")]) 4531 4532(define_insn "*ashlsi_c_void" 4533 [(set (reg:SI T_REG) 4534 (lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0))) 4535 (clobber (match_scratch:SI 1 "=0"))] 4536 "TARGET_SH1 && cse_not_expected" 4537 "shll %0" 4538 [(set_attr "type" "arith")]) 4539 4540(define_peephole2 4541 [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0)) 4542 (set (reg:SI T_REG) 4543 (gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))] 4544 "TARGET_SH1 4545 && peep2_reg_dead_p (2, operands[0]) 4546 && peep2_reg_dead_p (2, operands[1])" 4547 [(const_int 0)] 4548{ 4549 emit_insn (gen_shll (operands[1], operands[1])); 4550 DONE; 4551}) 4552 4553(define_insn "ashlsi3_media" 4554 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 4555 (ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r") 4556 (match_operand:SI 2 "shift_count_operand" "r,n")))] 4557 "TARGET_SHMEDIA" 4558 "@ 4559 shlld.l %1, %2, %0 4560 shlli.l %1, %2, %0" 4561 [(set_attr "type" "arith_media") 4562 (set_attr "highpart" "ignore")]) 4563 4564;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4565;; HImode shift left 4566 4567(define_expand "ashlhi3" 4568 [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "") 4569 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "") 4570 (match_operand:SI 2 "nonmemory_operand" ""))) 4571 (clobber (reg:SI T_REG))])] 4572 "TARGET_SH1" 4573{ 4574 if (!CONST_INT_P (operands[2])) 4575 FAIL; 4576 /* It may be possible to call gen_ashlhi3 directly with more generic 4577 operands. Make sure operands[1] is a HImode register here. */ 4578 if (!arith_reg_operand (operands[1], HImode)) 4579 operands[1] = copy_to_mode_reg (HImode, operands[1]); 4580}) 4581 4582(define_insn "ashlhi3_k" 4583 [(set (match_operand:HI 0 "arith_reg_dest" "=r,r") 4584 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0") 4585 (match_operand:HI 2 "const_int_operand" "M,P27")))] 4586 "TARGET_SH1 && satisfies_constraint_P27 (operands[2])" 4587 "@ 4588 add %0,%0 4589 shll%O2 %0" 4590 [(set_attr "type" "arith")]) 4591 4592(define_insn_and_split "*ashlhi3_n" 4593 [(set (match_operand:HI 0 "arith_reg_dest" "=r") 4594 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0") 4595 (match_operand:HI 2 "const_int_operand" "n"))) 4596 (clobber (reg:SI T_REG))] 4597 "TARGET_SH1" 4598 "#" 4599 "&& reload_completed" 4600 [(use (reg:SI R0_REG))] 4601{ 4602 gen_shifty_hi_op (ASHIFT, operands); 4603 DONE; 4604}) 4605 4606;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4607;; DImode shift left 4608 4609(define_expand "ashldi3" 4610 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "") 4611 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "") 4612 (match_operand:DI 2 "immediate_operand" ""))) 4613 (clobber (reg:SI T_REG))])] 4614 "" 4615{ 4616 if (TARGET_SHMEDIA) 4617 { 4618 emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2])); 4619 DONE; 4620 } 4621 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1) 4622 { 4623 emit_insn (gen_ashldi3_k (operands[0], operands[1])); 4624 DONE; 4625 } 4626 else if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 32) 4627 { 4628 emit_insn (gen_ashldi3_std (operands[0], operands[1], operands[2])); 4629 DONE; 4630 } 4631 else 4632 FAIL; 4633}) 4634 4635;; Expander for DImode shift left with SImode operations. 4636(define_expand "ashldi3_std" 4637 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 4638 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r") 4639 (match_operand:DI 2 "const_int_operand" "n")))] 4640 "TARGET_SH1 && INTVAL (operands[2]) < 32" 4641{ 4642 rtx low_src = gen_lowpart (SImode, operands[1]); 4643 rtx high_src = gen_highpart (SImode, operands[1]); 4644 rtx dst = gen_reg_rtx (DImode); 4645 rtx low_dst = gen_lowpart (SImode, dst); 4646 rtx high_dst = gen_highpart (SImode, dst); 4647 rtx tmp0 = gen_reg_rtx (SImode); 4648 rtx tmp1 = gen_reg_rtx (SImode); 4649 4650 emit_insn (gen_lshrsi3 (tmp0, low_src, GEN_INT (32 - INTVAL (operands[2])))); 4651 emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2])); 4652 emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2])); 4653 emit_insn (gen_iorsi3 (high_dst, tmp0, tmp1)); 4654 emit_move_insn (operands[0], dst); 4655 DONE; 4656}) 4657 4658(define_insn_and_split "ashldi3_k" 4659 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 4660 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0") 4661 (const_int 1))) 4662 (clobber (reg:SI T_REG))] 4663 "TARGET_SH1" 4664 "#" 4665 "&& reload_completed" 4666 [(const_int 0)] 4667{ 4668 rtx high = gen_highpart (SImode, operands[0]); 4669 rtx low = gen_lowpart (SImode, operands[0]); 4670 emit_insn (gen_shll (low, low)); 4671 emit_insn (gen_rotcl (high, high, get_t_reg_rtx ())); 4672 DONE; 4673}) 4674 4675(define_insn "ashldi3_media" 4676 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") 4677 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r") 4678 (match_operand:DI 2 "shift_count_operand" "r,n")))] 4679 "TARGET_SHMEDIA" 4680 "@ 4681 shlld %1, %2, %0 4682 shlli %1, %2, %0" 4683 [(set_attr "type" "arith_media")]) 4684 4685(define_insn "*ashldisi3_media" 4686 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0) 4687 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r") 4688 (match_operand:DI 2 "const_int_operand" "n")))] 4689 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32" 4690 "shlli.l %1, %2, %0" 4691 [(set_attr "type" "arith_media") 4692 (set_attr "highpart" "ignore")]) 4693 4694;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4695;; SImode arithmetic shift right 4696;; 4697;; We can't do HImode right shifts correctly unless we start out with an 4698;; explicit zero / sign extension; doing that would result in worse overall 4699;; code, so just let the machine independent code widen the mode. 4700;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 . 4701 4702(define_expand "ashrsi3" 4703 [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "") 4704 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "") 4705 (match_operand:SI 2 "nonmemory_operand" ""))) 4706 (clobber (reg:SI T_REG))])] 4707 "" 4708{ 4709 if (TARGET_SHMEDIA) 4710 { 4711 emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2])); 4712 DONE; 4713 } 4714 if (expand_ashiftrt (operands)) 4715 DONE; 4716 else 4717 FAIL; 4718}) 4719 4720(define_insn "shar" 4721 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4722 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 4723 (const_int 1))) 4724 (set (reg:SI T_REG) 4725 (and:SI (match_dup 1) (const_int 1)))] 4726 "TARGET_SH1" 4727 "shar %0" 4728 [(set_attr "type" "arith")]) 4729 4730(define_insn "ashrsi3_k" 4731 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4732 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 4733 (match_operand:SI 2 "const_int_operand" "M"))) 4734 (clobber (reg:SI T_REG))] 4735 "TARGET_SH1 && INTVAL (operands[2]) == 1" 4736 "shar %0" 4737 [(set_attr "type" "arith")]) 4738 4739(define_insn_and_split "ashrsi2_16" 4740 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4741 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r") 4742 (const_int 16)))] 4743 "TARGET_SH1" 4744 "#" 4745 "&& 1" 4746 [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16))) 4747 (set (match_dup 0) (sign_extend:SI (match_dup 2)))] 4748{ 4749 operands[2] = gen_lowpart (HImode, operands[0]); 4750}) 4751 4752(define_insn_and_split "ashrsi2_31" 4753 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4754 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 4755 (const_int 31))) 4756 (clobber (reg:SI T_REG))] 4757 "TARGET_SH1" 4758 "#" 4759 "&& 1" 4760 [(const_int 0)] 4761{ 4762 emit_insn (gen_shll (operands[0], operands[1])); 4763 emit_insn (gen_mov_neg_si_t (operands[0], get_t_reg_rtx ())); 4764 DONE; 4765}) 4766 4767(define_insn "ashrsi3_d" 4768 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4769 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 4770 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))] 4771 "TARGET_DYNSHIFT" 4772 "shad %2,%0" 4773 [(set_attr "type" "dyn_shift")]) 4774 4775(define_insn "ashrsi3_n" 4776 [(set (reg:SI R4_REG) 4777 (ashiftrt:SI (reg:SI R4_REG) 4778 (match_operand:SI 0 "const_int_operand" "i"))) 4779 (clobber (reg:SI T_REG)) 4780 (clobber (reg:SI PR_REG)) 4781 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 4782 "TARGET_SH1" 4783 "jsr @%1%#" 4784 [(set_attr "type" "sfunc") 4785 (set_attr "needs_delay_slot" "yes")]) 4786 4787(define_insn "ashrsi3_media" 4788 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 4789 (ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r") 4790 (match_operand:SI 2 "shift_count_operand" "r,n")))] 4791 "TARGET_SHMEDIA" 4792 "@ 4793 shard.l %1, %2, %0 4794 shari.l %1, %2, %0" 4795 [(set_attr "type" "arith_media") 4796 (set_attr "highpart" "ignore")]) 4797 4798;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4799;; DImode arithmetic shift right 4800 4801(define_expand "ashrdi3" 4802 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "") 4803 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "") 4804 (match_operand:DI 2 "immediate_operand" ""))) 4805 (clobber (reg:SI T_REG))])] 4806 "" 4807{ 4808 if (TARGET_SHMEDIA) 4809 { 4810 emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2])); 4811 DONE; 4812 } 4813 if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1) 4814 FAIL; 4815}) 4816 4817(define_insn_and_split "ashrdi3_k" 4818 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 4819 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0") 4820 (const_int 1))) 4821 (clobber (reg:SI T_REG))] 4822 "TARGET_SH1" 4823 "#" 4824 "&& reload_completed" 4825 [(const_int 0)] 4826{ 4827 rtx high = gen_highpart (SImode, operands[0]); 4828 rtx low = gen_lowpart (SImode, operands[0]); 4829 emit_insn (gen_shar (high, high)); 4830 emit_insn (gen_rotcr (low, low, get_t_reg_rtx ())); 4831 DONE; 4832}) 4833 4834(define_insn "ashrdi3_media" 4835 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r") 4836 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r") 4837 (match_operand:DI 2 "shift_count_operand" "r,n")))] 4838 "TARGET_SHMEDIA 4839 && (arith_reg_dest (operands[0], DImode) 4840 || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) >= 32))" 4841 "@ 4842 shard %1, %2, %0 4843 shari %1, %2, %0" 4844 [(set_attr "type" "arith_media")]) 4845 4846(define_insn "*ashrdisi3_media" 4847 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0) 4848 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r") 4849 (match_operand:DI 2 "const_int_operand" "n")))] 4850 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32" 4851 "shari.l %1, %2, %0" 4852 [(set_attr "type" "arith_media") 4853 (set_attr "highpart" "ignore")]) 4854 4855(define_insn "ashrdisi3_media_high" 4856 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4857 (truncate:SI 4858 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r") 4859 (match_operand:DI 2 "const_int_operand" "n"))))] 4860 "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32" 4861 "shari %1, %2, %0" 4862 [(set_attr "type" "arith_media")]) 4863 4864(define_insn "ashrdisi3_media_opaque" 4865 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4866 (unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r") 4867 (match_operand:DI 2 "const_int_operand" "n")] 4868 UNSPEC_ASHIFTRT))] 4869 "TARGET_SHMEDIA" 4870 "shari %1, %2, %0" 4871 [(set_attr "type" "arith_media")]) 4872 4873;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4874;; SImode logical shift right 4875 4876(define_expand "lshrsi3" 4877 [(set (match_operand:SI 0 "arith_reg_dest" "") 4878 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "") 4879 (match_operand:SI 2 "shift_count_operand" "")))] 4880 "" 4881{ 4882 if (TARGET_SHMEDIA) 4883 { 4884 emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2])); 4885 DONE; 4886 } 4887 4888 /* If a dynamic shift is supposed to be used, expand the lshrsi3_d insn 4889 here, otherwise the pattern will never match due to the shift amount reg 4890 negation. */ 4891 if (TARGET_DYNSHIFT 4892 && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2])) 4893 { 4894 rtx neg_count = force_reg (SImode, 4895 gen_int_mode (- INTVAL (operands[2]), SImode)); 4896 emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count)); 4897 DONE; 4898 } 4899 4900 if (TARGET_DYNSHIFT && ! CONST_INT_P (operands[2])) 4901 { 4902 rtx neg_count = gen_reg_rtx (SImode); 4903 emit_insn (gen_negsi2 (neg_count, operands[2])); 4904 emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count)); 4905 DONE; 4906 } 4907 4908 /* If the lshrsi3_* insn is going to clobber the T_REG it must be 4909 expanded here. */ 4910 if (CONST_INT_P (operands[2]) 4911 && sh_lshrsi_clobbers_t_reg_p (operands[2]) 4912 && ! sh_dynamicalize_shift_p (operands[2])) 4913 { 4914 emit_insn (gen_lshrsi3_n_clobbers_t (operands[0], operands[1], 4915 operands[2])); 4916 DONE; 4917 } 4918 4919 /* Expand a library call for the dynamic shift. */ 4920 if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT) 4921 { 4922 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]); 4923 rtx funcaddr = gen_reg_rtx (Pmode); 4924 function_symbol (funcaddr, "__lshrsi3_r0", SFUNC_STATIC); 4925 emit_insn (gen_lshrsi3_d_call (operands[0], operands[2], funcaddr)); 4926 DONE; 4927 } 4928}) 4929 4930(define_insn "lshrsi3_k" 4931 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4932 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 4933 (match_operand:SI 2 "p27_rshift_count_operand" "P27")))] 4934 "TARGET_SH1" 4935 "shlr%O2 %0" 4936 [(set_attr "type" "arith")]) 4937 4938(define_insn_and_split "lshrsi3_d" 4939 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4940 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 4941 (neg:SI (match_operand:SI 2 "shift_count_operand" "r"))))] 4942 "TARGET_DYNSHIFT" 4943 "shld %2,%0" 4944 "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2]) 4945 && ! sh_lshrsi_clobbers_t_reg_p (operands[2])" 4946 [(const_int 0)] 4947{ 4948 if (satisfies_constraint_P27 (operands[2])) 4949 { 4950 /* This will not be done for a shift amount of 1, because it would 4951 clobber the T_REG. */ 4952 emit_insn (gen_lshrsi3_k (operands[0], operands[1], operands[2])); 4953 DONE; 4954 } 4955 else if (! satisfies_constraint_P27 (operands[2])) 4956 { 4957 /* This must happen before reload, otherwise the constant will be moved 4958 into a register due to the "r" constraint, after which this split 4959 cannot be done anymore. 4960 Unfortunately the move insn will not always be eliminated. 4961 Also, here we must not create a shift sequence that clobbers the 4962 T_REG. */ 4963 emit_move_insn (operands[0], operands[1]); 4964 gen_shifty_op (LSHIFTRT, operands); 4965 DONE; 4966 } 4967 4968 FAIL; 4969} 4970 [(set_attr "type" "dyn_shift")]) 4971 4972;; If dynamic shifts are not available use a library function. 4973;; By specifying the pattern we reduce the number of call clobbered regs. 4974;; In order to make combine understand the truncation of the shift amount 4975;; operand we have to allow it to use pseudo regs for the shift operands. 4976(define_insn "lshrsi3_d_call" 4977 [(set (match_operand:SI 0 "arith_reg_dest" "=z") 4978 (lshiftrt:SI (reg:SI R4_REG) 4979 (and:SI (match_operand:SI 1 "arith_reg_operand" "z") 4980 (const_int 31)))) 4981 (use (match_operand:SI 2 "arith_reg_operand" "r")) 4982 (clobber (reg:SI T_REG)) 4983 (clobber (reg:SI PR_REG))] 4984 "TARGET_SH1 && !TARGET_DYNSHIFT" 4985 "jsr @%2%#" 4986 [(set_attr "type" "sfunc") 4987 (set_attr "needs_delay_slot" "yes")]) 4988 4989(define_insn_and_split "lshrsi3_n" 4990 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4991 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 4992 (match_operand:SI 2 "not_p27_rshift_count_operand")))] 4993 "TARGET_SH1 && ! sh_lshrsi_clobbers_t_reg_p (operands[2])" 4994 "#" 4995 "&& (reload_completed 4996 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))" 4997 [(const_int 0)] 4998{ 4999 if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()) 5000 { 5001 /* If this pattern was picked and dynamic shifts are supported, switch 5002 to dynamic shift pattern before reload. */ 5003 operands[2] = force_reg (SImode, 5004 gen_int_mode (- INTVAL (operands[2]), SImode)); 5005 emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2])); 5006 } 5007 else 5008 gen_shifty_op (LSHIFTRT, operands); 5009 5010 DONE; 5011}) 5012 5013;; The lshrsi3_n_clobbers_t pattern also works as a simplified version of 5014;; the shlr pattern. 5015(define_insn_and_split "lshrsi3_n_clobbers_t" 5016 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5017 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 5018 (match_operand:SI 2 "not_p27_rshift_count_operand"))) 5019 (clobber (reg:SI T_REG))] 5020 "TARGET_SH1 && sh_lshrsi_clobbers_t_reg_p (operands[2])" 5021 "#" 5022 "&& (reload_completed || INTVAL (operands[2]) == 31 5023 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))" 5024 [(const_int 0)] 5025{ 5026 if (INTVAL (operands[2]) == 31) 5027 { 5028 emit_insn (gen_shll (operands[0], operands[1])); 5029 emit_insn (gen_movt (operands[0], get_t_reg_rtx ())); 5030 } 5031 else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()) 5032 { 5033 /* If this pattern was picked and dynamic shifts are supported, switch 5034 to dynamic shift pattern before reload. */ 5035 operands[2] = force_reg (SImode, 5036 gen_int_mode (- INTVAL (operands[2]), SImode)); 5037 emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2])); 5038 } 5039 else 5040 gen_shifty_op (LSHIFTRT, operands); 5041 5042 DONE; 5043}) 5044 5045(define_insn "shlr" 5046 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5047 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 5048 (const_int 1))) 5049 (set (reg:SI T_REG) 5050 (and:SI (match_dup 1) (const_int 1)))] 5051 "TARGET_SH1" 5052 "shlr %0" 5053 [(set_attr "type" "arith")]) 5054 5055(define_insn "lshrsi3_media" 5056 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 5057 (lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r") 5058 (match_operand:SI 2 "shift_count_operand" "r,n")))] 5059 "TARGET_SHMEDIA" 5060 "@ 5061 shlrd.l %1, %2, %0 5062 shlri.l %1, %2, %0" 5063 [(set_attr "type" "arith_media") 5064 (set_attr "highpart" "ignore")]) 5065 5066;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5067;; DImode logical shift right 5068 5069(define_expand "lshrdi3" 5070 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "") 5071 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "") 5072 (match_operand:DI 2 "immediate_operand" ""))) 5073 (clobber (reg:SI T_REG))])] 5074 "" 5075{ 5076 if (TARGET_SHMEDIA) 5077 { 5078 emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2])); 5079 DONE; 5080 } 5081 if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1) 5082 FAIL; 5083}) 5084 5085(define_insn_and_split "lshrdi3_k" 5086 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 5087 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0") 5088 (const_int 1))) 5089 (clobber (reg:SI T_REG))] 5090 "TARGET_SH1" 5091 "#" 5092 "&& reload_completed" 5093 [(const_int 0)] 5094{ 5095 rtx high = gen_highpart (SImode, operands[0]); 5096 rtx low = gen_lowpart (SImode, operands[0]); 5097 emit_insn (gen_shlr (high, high)); 5098 emit_insn (gen_rotcr (low, low, get_t_reg_rtx ())); 5099 DONE; 5100}) 5101 5102(define_insn "lshrdi3_media" 5103 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r") 5104 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r") 5105 (match_operand:DI 2 "shift_count_operand" "r,n")))] 5106 "TARGET_SHMEDIA 5107 && (arith_reg_dest (operands[0], DImode) 5108 || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) > 32))" 5109 "@ 5110 shlrd %1, %2, %0 5111 shlri %1, %2, %0" 5112 [(set_attr "type" "arith_media")]) 5113 5114(define_insn "*lshrdisi3_media" 5115 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0) 5116 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r") 5117 (match_operand:DI 2 "const_int_operand" "n")))] 5118 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32" 5119 "shlri.l %1, %2, %0" 5120 [(set_attr "type" "arith_media") 5121 (set_attr "highpart" "ignore")]) 5122 5123;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5124;; Combined left/right shifts 5125 5126(define_split 5127 [(set (match_operand:SI 0 "register_operand" "") 5128 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "") 5129 (match_operand:SI 2 "const_int_operand" "")) 5130 (match_operand:SI 3 "const_int_operand" "")))] 5131 "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32" 5132 [(use (reg:SI R0_REG))] 5133{ 5134 if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) 5135 FAIL; 5136 DONE; 5137}) 5138 5139(define_split 5140 [(set (match_operand:SI 0 "register_operand" "") 5141 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "") 5142 (match_operand:SI 2 "const_int_operand" "")) 5143 (match_operand:SI 3 "const_int_operand" ""))) 5144 (clobber (reg:SI T_REG))] 5145 "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32" 5146 [(use (reg:SI R0_REG))] 5147{ 5148 if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) 5149 FAIL; 5150 DONE; 5151}) 5152 5153(define_insn "" 5154 [(set (match_operand:SI 0 "register_operand" "=r") 5155 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0") 5156 (match_operand:SI 2 "const_int_operand" "n")) 5157 (match_operand:SI 3 "const_int_operand" "n"))) 5158 (clobber (reg:SI T_REG))] 5159 "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1" 5160 "#" 5161 [(set (attr "length") 5162 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2)) 5163 (const_string "4") 5164 (eq (symbol_ref "shl_and_length (insn)") (const_int 3)) 5165 (const_string "6") 5166 (eq (symbol_ref "shl_and_length (insn)") (const_int 4)) 5167 (const_string "8") 5168 (eq (symbol_ref "shl_and_length (insn)") (const_int 5)) 5169 (const_string "10") 5170 (eq (symbol_ref "shl_and_length (insn)") (const_int 6)) 5171 (const_string "12") 5172 (eq (symbol_ref "shl_and_length (insn)") (const_int 7)) 5173 (const_string "14") 5174 (eq (symbol_ref "shl_and_length (insn)") (const_int 8)) 5175 (const_string "16")] 5176 (const_string "18"))) 5177 (set_attr "type" "arith")]) 5178 5179(define_insn "" 5180 [(set (match_operand:SI 0 "register_operand" "=z") 5181 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0") 5182 (match_operand:SI 2 "const_int_operand" "n")) 5183 (match_operand:SI 3 "const_int_operand" "n"))) 5184 (clobber (reg:SI T_REG))] 5185 "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2" 5186 "#" 5187 [(set (attr "length") 5188 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2)) 5189 (const_string "4") 5190 (eq (symbol_ref "shl_and_length (insn)") (const_int 3)) 5191 (const_string "6") 5192 (eq (symbol_ref "shl_and_length (insn)") (const_int 4)) 5193 (const_string "8")] 5194 (const_string "10"))) 5195 (set_attr "type" "arith")]) 5196 5197;; shift left / and combination with a scratch register: The combine pass 5198;; does not accept the individual instructions, even though they are 5199;; cheap. But it needs a precise description so that it is usable after 5200;; reload. 5201(define_insn "and_shl_scratch" 5202 [(set (match_operand:SI 0 "register_operand" "=r,&r") 5203 (lshiftrt:SI 5204 (ashift:SI 5205 (and:SI 5206 (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0") 5207 (match_operand:SI 2 "const_int_operand" "N,n")) 5208 (match_operand:SI 3 "" "0,r")) 5209 (match_operand:SI 4 "const_int_operand" "n,n")) 5210 (match_operand:SI 5 "const_int_operand" "n,n"))) 5211 (clobber (reg:SI T_REG))] 5212 "TARGET_SH1" 5213 "#" 5214 [(set (attr "length") 5215 (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2)) 5216 (const_string "4") 5217 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3)) 5218 (const_string "6") 5219 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4)) 5220 (const_string "8") 5221 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5)) 5222 (const_string "10")] 5223 (const_string "12"))) 5224 (set_attr "type" "arith")]) 5225 5226(define_split 5227 [(set (match_operand:SI 0 "register_operand" "") 5228 (lshiftrt:SI 5229 (ashift:SI 5230 (and:SI 5231 (lshiftrt:SI (match_operand:SI 1 "register_operand" "") 5232 (match_operand:SI 2 "const_int_operand" "")) 5233 (match_operand:SI 3 "register_operand" "")) 5234 (match_operand:SI 4 "const_int_operand" "")) 5235 (match_operand:SI 5 "const_int_operand" ""))) 5236 (clobber (reg:SI T_REG))] 5237 "TARGET_SH1" 5238 [(use (reg:SI R0_REG))] 5239{ 5240 rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1]; 5241 5242 if (INTVAL (operands[2])) 5243 { 5244 gen_shifty_op (LSHIFTRT, operands); 5245 } 5246 emit_insn (gen_andsi3 (operands[0], operands[0], and_source)); 5247 operands[2] = operands[4]; 5248 gen_shifty_op (ASHIFT, operands); 5249 if (INTVAL (operands[5])) 5250 { 5251 operands[2] = operands[5]; 5252 gen_shifty_op (LSHIFTRT, operands); 5253 } 5254 DONE; 5255}) 5256 5257;; signed left/right shift combination. 5258(define_split 5259 [(set (match_operand:SI 0 "register_operand" "") 5260 (sign_extract:SI 5261 (ashift:SI (match_operand:SI 1 "register_operand" "") 5262 (match_operand:SI 2 "const_int_operand" "")) 5263 (match_operand:SI 3 "const_int_operand" "") 5264 (const_int 0))) 5265 (clobber (reg:SI T_REG))] 5266 "TARGET_SH1" 5267 [(use (reg:SI R0_REG))] 5268{ 5269 if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1])) 5270 FAIL; 5271 DONE; 5272}) 5273 5274(define_insn "shl_sext_ext" 5275 [(set (match_operand:SI 0 "register_operand" "=r") 5276 (sign_extract:SI 5277 (ashift:SI (match_operand:SI 1 "register_operand" "0") 5278 (match_operand:SI 2 "const_int_operand" "n")) 5279 (match_operand:SI 3 "const_int_operand" "n") 5280 (const_int 0))) 5281 (clobber (reg:SI T_REG))] 5282 "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5" 5283 "#" 5284 [(set (attr "length") 5285 (cond [(match_test "shl_sext_length (insn)") 5286 (const_string "2") 5287 (eq (symbol_ref "shl_sext_length (insn)") (const_int 2)) 5288 (const_string "4") 5289 (eq (symbol_ref "shl_sext_length (insn)") (const_int 3)) 5290 (const_string "6") 5291 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4)) 5292 (const_string "8") 5293 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5)) 5294 (const_string "10") 5295 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6)) 5296 (const_string "12") 5297 (eq (symbol_ref "shl_sext_length (insn)") (const_int 7)) 5298 (const_string "14") 5299 (eq (symbol_ref "shl_sext_length (insn)") (const_int 8)) 5300 (const_string "16")] 5301 (const_string "18"))) 5302 (set_attr "type" "arith")]) 5303 5304(define_insn "shl_sext_sub" 5305 [(set (match_operand:SI 0 "register_operand" "=z") 5306 (sign_extract:SI 5307 (ashift:SI (match_operand:SI 1 "register_operand" "0") 5308 (match_operand:SI 2 "const_int_operand" "n")) 5309 (match_operand:SI 3 "const_int_operand" "n") 5310 (const_int 0))) 5311 (clobber (reg:SI T_REG))] 5312 "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6" 5313 "#" 5314 [(set (attr "length") 5315 (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3)) 5316 (const_string "6") 5317 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4)) 5318 (const_string "8") 5319 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5)) 5320 (const_string "10") 5321 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6)) 5322 (const_string "12")] 5323 (const_string "14"))) 5324 (set_attr "type" "arith")]) 5325 5326;; The xtrct_left and xtrct_right patterns are used in expansions of DImode 5327;; shifts by 16, and allow the xtrct instruction to be generated from C 5328;; source. 5329(define_insn "xtrct_left" 5330 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5331 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r") 5332 (const_int 16)) 5333 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0") 5334 (const_int 16))))] 5335 "TARGET_SH1" 5336 "xtrct %1,%0" 5337 [(set_attr "type" "arith")]) 5338 5339(define_insn "xtrct_right" 5340 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5341 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 5342 (const_int 16)) 5343 (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r") 5344 (const_int 16))))] 5345 "TARGET_SH1" 5346 "xtrct %2,%0" 5347 [(set_attr "type" "arith")]) 5348 5349;; ------------------------------------------------------------------------- 5350;; Unary arithmetic 5351;; ------------------------------------------------------------------------- 5352 5353(define_insn "negc" 5354 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5355 (neg:SI (plus:SI (reg:SI T_REG) 5356 (match_operand:SI 1 "arith_reg_operand" "r")))) 5357 (set (reg:SI T_REG) 5358 (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1)) 5359 (const_int 0)))] 5360 "TARGET_SH1" 5361 "negc %1,%0" 5362 [(set_attr "type" "arith")]) 5363 5364;; A simplified version of the negc insn, where the exact value of the 5365;; T bit doesn't matter. This is easier for combine to pick up. 5366;; Notice that '0 - x - 1' is the same as '~x', thus we don't specify 5367;; extra patterns for this case. 5368(define_insn "*negc" 5369 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5370 (minus:SI (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")) 5371 (match_operand:SI 2 "t_reg_operand" ""))) 5372 (clobber (reg:SI T_REG))] 5373 "TARGET_SH1" 5374 "negc %1,%0" 5375 [(set_attr "type" "arith")]) 5376 5377(define_insn "*negdi_media" 5378 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 5379 (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))] 5380 "TARGET_SHMEDIA" 5381 "sub r63, %1, %0" 5382 [(set_attr "type" "arith_media")]) 5383 5384;; Don't expand immediately because otherwise neg:DI (abs:DI) will not be 5385;; combined. 5386(define_expand "negdi2" 5387 [(parallel [(set (match_operand:DI 0 "arith_reg_dest") 5388 (neg:DI (match_operand:DI 1 "arith_reg_operand"))) 5389 (clobber (reg:SI T_REG))])] 5390 "TARGET_SH1") 5391 5392(define_insn_and_split "*negdi2" 5393 [(set (match_operand:DI 0 "arith_reg_dest" "=&r") 5394 (neg:DI (match_operand:DI 1 "arith_reg_operand" "r"))) 5395 (clobber (reg:SI T_REG))] 5396 "TARGET_SH1" 5397 "#" 5398 "&& reload_completed" 5399 [(const_int 0)] 5400{ 5401 emit_insn (gen_clrt ()); 5402 emit_insn (gen_negc (gen_lowpart (SImode, operands[0]), 5403 gen_lowpart (SImode, operands[1]))); 5404 emit_insn (gen_negc (gen_highpart (SImode, operands[0]), 5405 gen_highpart (SImode, operands[1]))); 5406 DONE; 5407}) 5408 5409(define_insn "negsi2" 5410 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5411 (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))] 5412 "TARGET_SH1" 5413 "neg %1,%0" 5414 [(set_attr "type" "arith")]) 5415 5416(define_insn_and_split "one_cmplsi2" 5417 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5418 (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))] 5419 "TARGET_SH1" 5420 "not %1,%0" 5421 "&& can_create_pseudo_p ()" 5422 [(set (reg:SI T_REG) (ge:SI (match_dup 1) (const_int 0))) 5423 (set (match_dup 0) (reg:SI T_REG))] 5424{ 5425/* PR 54685 5426 If the result of 'unsigned int <= 0x7FFFFFFF' ends up as the following 5427 sequence: 5428 5429 (set (reg0) (not:SI (reg0) (reg1))) 5430 (parallel [(set (reg2) (lshiftrt:SI (reg0) (const_int 31))) 5431 (clobber (reg:SI T_REG))]) 5432 5433 ... match and combine the sequence manually in the split pass after the 5434 combine pass. Notice that combine does try the target pattern of this 5435 split, but if the pattern is added it interferes with other patterns, in 5436 particular with the div0s comparisons. 5437 This could also be done with a peephole but doing it here before register 5438 allocation can save one temporary. 5439 When we're here, the not:SI pattern obviously has been matched already 5440 and we only have to see whether the following insn is the left shift. */ 5441 5442 rtx i = next_nonnote_insn_bb (curr_insn); 5443 if (i == NULL_RTX || !NONJUMP_INSN_P (i)) 5444 FAIL; 5445 5446 rtx p = PATTERN (i); 5447 if (GET_CODE (p) != PARALLEL || XVECLEN (p, 0) != 2) 5448 FAIL; 5449 5450 rtx p0 = XVECEXP (p, 0, 0); 5451 rtx p1 = XVECEXP (p, 0, 1); 5452 5453 if (/* (set (reg2) (lshiftrt:SI (reg0) (const_int 31))) */ 5454 GET_CODE (p0) == SET 5455 && GET_CODE (XEXP (p0, 1)) == LSHIFTRT 5456 && REG_P (XEXP (XEXP (p0, 1), 0)) 5457 && REGNO (XEXP (XEXP (p0, 1), 0)) == REGNO (operands[0]) 5458 && CONST_INT_P (XEXP (XEXP (p0, 1), 1)) 5459 && INTVAL (XEXP (XEXP (p0, 1), 1)) == 31 5460 5461 /* (clobber (reg:SI T_REG)) */ 5462 && GET_CODE (p1) == CLOBBER && REG_P (XEXP (p1, 0)) 5463 && REGNO (XEXP (p1, 0)) == T_REG) 5464 { 5465 operands[0] = XEXP (p0, 0); 5466 set_insn_deleted (i); 5467 } 5468 else 5469 FAIL; 5470} 5471 [(set_attr "type" "arith")]) 5472 5473(define_expand "one_cmpldi2" 5474 [(set (match_operand:DI 0 "arith_reg_dest" "") 5475 (xor:DI (match_operand:DI 1 "arith_reg_operand" "") 5476 (const_int -1)))] 5477 "TARGET_SHMEDIA" "") 5478 5479(define_expand "abs<mode>2" 5480 [(parallel [(set (match_operand:SIDI 0 "arith_reg_dest") 5481 (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand"))) 5482 (clobber (reg:SI T_REG))])] 5483 "TARGET_SH1") 5484 5485(define_insn_and_split "*abs<mode>2" 5486 [(set (match_operand:SIDI 0 "arith_reg_dest") 5487 (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand"))) 5488 (clobber (reg:SI T_REG))] 5489 "TARGET_SH1" 5490 "#" 5491 "&& can_create_pseudo_p ()" 5492 [(const_int 0)] 5493{ 5494 if (<MODE>mode == SImode) 5495 emit_insn (gen_cmpgesi_t (operands[1], const0_rtx)); 5496 else 5497 { 5498 rtx high_src = gen_highpart (SImode, operands[1]); 5499 emit_insn (gen_cmpgesi_t (high_src, const0_rtx)); 5500 } 5501 5502 emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1], 5503 const1_rtx)); 5504 DONE; 5505}) 5506 5507(define_insn_and_split "*negabs<mode>2" 5508 [(set (match_operand:SIDI 0 "arith_reg_dest") 5509 (neg:SIDI (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand")))) 5510 (clobber (reg:SI T_REG))] 5511 "TARGET_SH1" 5512 "#" 5513 "&& can_create_pseudo_p ()" 5514 [(const_int 0)] 5515{ 5516 if (<MODE>mode == SImode) 5517 emit_insn (gen_cmpgesi_t (operands[1], const0_rtx)); 5518 else 5519 { 5520 rtx high_src = gen_highpart (SImode, operands[1]); 5521 emit_insn (gen_cmpgesi_t (high_src, const0_rtx)); 5522 } 5523 5524 emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1], 5525 const0_rtx)); 5526 DONE; 5527}) 5528 5529;; The SH4 202 can do zero-offset branches without pipeline stalls. 5530;; This can be used as some kind of conditional execution, which is useful 5531;; for abs. 5532;; Actually the instruction scheduling should decide whether to use a 5533;; zero-offset branch or not for any generic case involving a single 5534;; instruction on SH4 202. 5535(define_insn_and_split "negsi_cond" 5536 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 5537 (if_then_else 5538 (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand" "M,N")) 5539 (match_operand:SI 1 "arith_reg_operand" "0,0") 5540 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r,r"))))] 5541 "TARGET_SH1 && TARGET_ZDCBRANCH" 5542{ 5543 static const char* alt[] = 5544 { 5545 "bt 0f" "\n" 5546 " neg %2,%0" "\n" 5547 "0:", 5548 5549 "bf 0f" "\n" 5550 " neg %2,%0" "\n" 5551 "0:" 5552 }; 5553 return alt[which_alternative]; 5554} 5555 "TARGET_SH1 && ! TARGET_ZDCBRANCH" 5556 [(const_int 0)] 5557{ 5558 rtx skip_neg_label = gen_label_rtx (); 5559 5560 emit_move_insn (operands[0], operands[1]); 5561 5562 emit_jump_insn (INTVAL (operands[3]) 5563 ? gen_branch_true (skip_neg_label) 5564 : gen_branch_false (skip_neg_label)); 5565 5566 emit_label_after (skip_neg_label, 5567 emit_insn (gen_negsi2 (operands[0], operands[1]))); 5568 DONE; 5569} 5570 [(set_attr "type" "arith") ;; poor approximation 5571 (set_attr "length" "4")]) 5572 5573(define_insn_and_split "negdi_cond" 5574 [(set (match_operand:DI 0 "arith_reg_dest") 5575 (if_then_else 5576 (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand")) 5577 (match_operand:DI 1 "arith_reg_operand") 5578 (neg:DI (match_operand:DI 2 "arith_reg_operand")))) 5579 (clobber (reg:SI T_REG))] 5580 "TARGET_SH1" 5581 "#" 5582 "&& can_create_pseudo_p ()" 5583 [(const_int 0)] 5584{ 5585 rtx skip_neg_label = gen_label_rtx (); 5586 5587 emit_move_insn (operands[0], operands[1]); 5588 5589 emit_jump_insn (INTVAL (operands[3]) 5590 ? gen_branch_true (skip_neg_label) 5591 : gen_branch_false (skip_neg_label)); 5592 5593 if (!INTVAL (operands[3])) 5594 emit_insn (gen_clrt ()); 5595 5596 emit_insn (gen_negc (gen_lowpart (SImode, operands[0]), 5597 gen_lowpart (SImode, operands[1]))); 5598 emit_label_after (skip_neg_label, 5599 emit_insn (gen_negc (gen_highpart (SImode, operands[0]), 5600 gen_highpart (SImode, operands[1])))); 5601 DONE; 5602}) 5603 5604(define_expand "bswapsi2" 5605 [(set (match_operand:SI 0 "arith_reg_dest" "") 5606 (bswap:SI (match_operand:SI 1 "arith_reg_operand" "")))] 5607 "TARGET_SH1" 5608{ 5609 if (! can_create_pseudo_p ()) 5610 FAIL; 5611 else 5612 { 5613 rtx tmp0 = gen_reg_rtx (SImode); 5614 rtx tmp1 = gen_reg_rtx (SImode); 5615 5616 emit_insn (gen_swapbsi2 (tmp0, operands[1])); 5617 emit_insn (gen_rotlsi3_16 (tmp1, tmp0)); 5618 emit_insn (gen_swapbsi2 (operands[0], tmp1)); 5619 DONE; 5620 } 5621}) 5622 5623(define_insn "swapbsi2" 5624 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5625 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "r") 5626 (const_int -65536)) ;; 0xFFFF0000 5627 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8)) 5628 (const_int 65280)) 5629 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8)) 5630 (const_int 255)))))] 5631 "TARGET_SH1" 5632 "swap.b %1,%0" 5633 [(set_attr "type" "arith")]) 5634 5635;; The *swapbisi2_and_shl8 pattern helps the combine pass simplifying 5636;; partial byte swap expressions such as... 5637;; ((x & 0xFF) << 8) | ((x >> 8) & 0xFF). 5638;; ...which are currently not handled by the tree optimizers. 5639;; The combine pass will not initially try to combine the full expression, 5640;; but only some sub-expressions. In such a case the *swapbisi2_and_shl8 5641;; pattern acts as an intermediate pattern that will eventually lead combine 5642;; to the swapbsi2 pattern above. 5643;; As a side effect this also improves code that does (x & 0xFF) << 8 5644;; or (x << 8) & 0xFF00. 5645(define_insn_and_split "*swapbisi2_and_shl8" 5646 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5647 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r") 5648 (const_int 8)) 5649 (const_int 65280)) 5650 (match_operand:SI 2 "arith_reg_operand" "r")))] 5651 "TARGET_SH1 && ! reload_in_progress && ! reload_completed" 5652 "#" 5653 "&& can_create_pseudo_p ()" 5654 [(const_int 0)] 5655{ 5656 rtx tmp0 = gen_reg_rtx (SImode); 5657 rtx tmp1 = gen_reg_rtx (SImode); 5658 5659 emit_insn (gen_zero_extendqisi2 (tmp0, gen_lowpart (QImode, operands[1]))); 5660 emit_insn (gen_swapbsi2 (tmp1, tmp0)); 5661 emit_insn (gen_iorsi3 (operands[0], tmp1, operands[2])); 5662 DONE; 5663}) 5664 5665;; The *swapbhisi2 pattern is, like the *swapbisi2_and_shl8 pattern, another 5666;; intermediate pattern that will help the combine pass arriving at swapbsi2. 5667(define_insn_and_split "*swapbhisi2" 5668 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5669 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r") 5670 (const_int 8)) 5671 (const_int 65280)) 5672 (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))))] 5673 "TARGET_SH1 && ! reload_in_progress && ! reload_completed" 5674 "#" 5675 "&& can_create_pseudo_p ()" 5676 [(const_int 0)] 5677{ 5678 rtx tmp = gen_reg_rtx (SImode); 5679 5680 emit_insn (gen_zero_extendhisi2 (tmp, gen_lowpart (HImode, operands[1]))); 5681 emit_insn (gen_swapbsi2 (operands[0], tmp)); 5682 DONE; 5683}) 5684 5685;; In some cases the swapbsi2 pattern might leave a sequence such as... 5686;; swap.b r4,r4 5687;; mov r4,r0 5688;; 5689;; which can be simplified to... 5690;; swap.b r4,r0 5691(define_peephole2 5692 [(set (match_operand:SI 0 "arith_reg_dest" "") 5693 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "") 5694 (const_int -65536)) ;; 0xFFFF0000 5695 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8)) 5696 (const_int 65280)) 5697 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8)) 5698 (const_int 255))))) 5699 (set (match_operand:SI 2 "arith_reg_dest" "") 5700 (match_dup 0))] 5701 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])" 5702 [(set (match_dup 2) 5703 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "") 5704 (const_int -65536)) ;; 0xFFFF0000 5705 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8)) 5706 (const_int 65280)) 5707 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8)) 5708 (const_int 255)))))]) 5709 5710;; ------------------------------------------------------------------------- 5711;; Zero extension instructions 5712;; ------------------------------------------------------------------------- 5713 5714(define_insn "zero_extendsidi2" 5715 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 5716 (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))] 5717 "TARGET_SHMEDIA" 5718 "addz.l %1, r63, %0" 5719 [(set_attr "type" "arith_media") 5720 (set_attr "highpart" "extend")]) 5721 5722(define_insn "zero_extendhidi2" 5723 [(set (match_operand:DI 0 "register_operand" "=r,r") 5724 (zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))] 5725 "TARGET_SHMEDIA" 5726 "@ 5727 # 5728 ld%M1.uw %m1, %0" 5729 [(set_attr "type" "*,load_media") 5730 (set (attr "highpart") 5731 (cond [(match_test "sh_contains_memref_p (insn)") 5732 (const_string "user")] 5733 (const_string "ignore")))]) 5734 5735(define_split 5736 [(set (match_operand:DI 0 "register_operand" "") 5737 (zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))] 5738 "TARGET_SHMEDIA && reload_completed" 5739 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48))) 5740 (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))] 5741{ 5742 if (GET_CODE (operands[1]) == TRUNCATE) 5743 operands[1] = XEXP (operands[1], 0); 5744}) 5745 5746;; ??? when a truncated input to a zero_extend is reloaded, reload will 5747;; reload the entire truncate expression. 5748(define_insn_and_split "*loaddi_trunc" 5749 [(set (match_operand 0 "any_register_operand" "=r") 5750 (truncate (match_operand:DI 1 "memory_operand" "m")))] 5751 "TARGET_SHMEDIA && reload_completed" 5752 "#" 5753 "TARGET_SHMEDIA && reload_completed" 5754 [(set (match_dup 0) (match_dup 1))] 5755{ 5756 operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0])); 5757}) 5758 5759(define_insn "zero_extendqidi2" 5760 [(set (match_operand:DI 0 "register_operand" "=r,r") 5761 (zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))] 5762 "TARGET_SHMEDIA" 5763 "@ 5764 andi %1, 255, %0 5765 ld%M1.ub %m1, %0" 5766 [(set_attr "type" "arith_media,load_media") 5767 (set (attr "highpart") 5768 (cond [(match_test "sh_contains_memref_p (insn)") 5769 (const_string "user")] 5770 (const_string "ignore")))]) 5771 5772(define_expand "zero_extend<mode>si2" 5773 [(set (match_operand:SI 0 "arith_reg_dest") 5774 (zero_extend:SI (match_operand:QIHI 1 "zero_extend_operand")))]) 5775 5776(define_insn_and_split "*zero_extend<mode>si2_compact" 5777 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5778 (zero_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))] 5779 "TARGET_SH1" 5780 "extu.<bw> %1,%0" 5781 "&& can_create_pseudo_p ()" 5782 [(set (match_dup 0) (match_dup 2))] 5783{ 5784 /* Sometimes combine fails to combine a T bit or negated T bit store to a 5785 reg with a following zero extension. In the split pass after combine, 5786 try to figure out how the extended reg was set. If it originated from 5787 the T bit we can replace the zero extension with a reg move, which will 5788 be eliminated. Notice that this also helps the *cbranch_t splitter when 5789 it tries to post-combine tests and conditional branches, as it does not 5790 check for zero extensions. */ 5791 operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn); 5792 if (operands[2] == NULL_RTX) 5793 FAIL; 5794} 5795 [(set_attr "type" "arith")]) 5796 5797(define_insn "*zero_extendhisi2_media" 5798 [(set (match_operand:SI 0 "register_operand" "=r,r") 5799 (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))] 5800 "TARGET_SHMEDIA" 5801 "@ 5802 # 5803 ld%M1.uw %m1, %0" 5804 [(set_attr "type" "arith_media,load_media") 5805 (set (attr "highpart") 5806 (cond [(match_test "sh_contains_memref_p (insn)") 5807 (const_string "user")] 5808 (const_string "ignore")))]) 5809 5810(define_split 5811 [(set (match_operand:SI 0 "register_operand" "") 5812 (zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))] 5813 "TARGET_SHMEDIA && reload_completed" 5814 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16))) 5815 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))] 5816{ 5817 rtx op1 = operands[1]; 5818 5819 if (GET_CODE (op1) == TRUNCATE) 5820 op1 = XEXP (op1, 0); 5821 operands[2] 5822 = simplify_gen_subreg (SImode, op1, GET_MODE (op1), 5823 subreg_lowpart_offset (SImode, GET_MODE (op1))); 5824}) 5825 5826(define_insn "*zero_extendqisi2_media" 5827 [(set (match_operand:SI 0 "register_operand" "=r,r") 5828 (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))] 5829 "TARGET_SHMEDIA" 5830 "@ 5831 andi %1, 255, %0 5832 ld%M1.ub %m1, %0" 5833 [(set_attr "type" "arith_media,load_media") 5834 (set (attr "highpart") 5835 (cond [(match_test "sh_contains_memref_p (insn)") 5836 (const_string "user")] 5837 (const_string "ignore")))]) 5838 5839(define_insn "zero_extendqihi2" 5840 [(set (match_operand:HI 0 "arith_reg_dest" "=r") 5841 (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))] 5842 "TARGET_SH1" 5843 "extu.b %1,%0" 5844 [(set_attr "type" "arith")]) 5845 5846;; SH2A supports two zero extending load instructions: movu.b and movu.w. 5847;; They could also be used for simple memory addresses like @Rn by setting 5848;; the displacement value to zero. However, doing so too early results in 5849;; missed opportunities for other optimizations such as post-inc or index 5850;; addressing loads. 5851;; Although the 'zero_extend_movu_operand' predicate does not allow simple 5852;; register addresses (an address without a displacement, index, post-inc), 5853;; zero-displacement addresses might be generated during reload, wich are 5854;; simplified to simple register addresses in turn. Thus, we have to 5855;; provide the Sdd and Sra alternatives in the patterns. 5856(define_insn "*zero_extend<mode>si2_disp_mem" 5857 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 5858 (zero_extend:SI 5859 (match_operand:QIHI 1 "zero_extend_movu_operand" "Sdd,Sra")))] 5860 "TARGET_SH2A" 5861 "@ 5862 movu.<bw> %1,%0 5863 movu.<bw> @(0,%t1),%0" 5864 [(set_attr "type" "load") 5865 (set_attr "length" "4")]) 5866 5867;; Convert the zero extending loads in sequences such as: 5868;; movu.b @(1,r5),r0 movu.w @(2,r5),r0 5869;; mov.b r0,@(1,r4) mov.b r0,@(1,r4) 5870;; 5871;; back to sign extending loads like: 5872;; mov.b @(1,r5),r0 mov.w @(2,r5),r0 5873;; mov.b r0,@(1,r4) mov.b r0,@(1,r4) 5874;; 5875;; if the extension type is irrelevant. The sign extending mov.{b|w} insn 5876;; is only 2 bytes in size if the displacement is {K04|K05}. 5877;; If the displacement is greater it doesn't matter, so we convert anyways. 5878(define_peephole2 5879 [(set (match_operand:SI 0 "arith_reg_dest" "") 5880 (zero_extend:SI (match_operand 1 "displacement_mem_operand" ""))) 5881 (set (match_operand 2 "general_operand" "") 5882 (match_operand 3 "arith_reg_operand" ""))] 5883 "TARGET_SH2A 5884 && REGNO (operands[0]) == REGNO (operands[3]) 5885 && peep2_reg_dead_p (2, operands[0]) 5886 && GET_MODE_SIZE (GET_MODE (operands[2])) 5887 <= GET_MODE_SIZE (GET_MODE (operands[1]))" 5888 [(set (match_dup 0) (sign_extend:SI (match_dup 1))) 5889 (set (match_dup 2) (match_dup 3))]) 5890 5891;; Fold sequences such as 5892;; mov.b @r3,r7 5893;; extu.b r7,r7 5894;; into 5895;; movu.b @(0,r3),r7 5896;; This does not reduce the code size but the number of instructions is 5897;; halved, which results in faster code. 5898(define_peephole2 5899 [(set (match_operand:SI 0 "arith_reg_dest" "") 5900 (sign_extend:SI (match_operand 1 "simple_mem_operand" ""))) 5901 (set (match_operand:SI 2 "arith_reg_dest" "") 5902 (zero_extend:SI (match_operand 3 "arith_reg_operand" "")))] 5903 "TARGET_SH2A 5904 && GET_MODE (operands[1]) == GET_MODE (operands[3]) 5905 && (GET_MODE (operands[1]) == QImode || GET_MODE (operands[1]) == HImode) 5906 && REGNO (operands[0]) == REGNO (operands[3]) 5907 && (REGNO (operands[2]) == REGNO (operands[0]) 5908 || peep2_reg_dead_p (2, operands[0]))" 5909 [(set (match_dup 2) (zero_extend:SI (match_dup 4)))] 5910{ 5911 operands[4] 5912 = replace_equiv_address (operands[1], 5913 gen_rtx_PLUS (SImode, XEXP (operands[1], 0), 5914 const0_rtx)); 5915}) 5916 5917;; ------------------------------------------------------------------------- 5918;; Sign extension instructions 5919;; ------------------------------------------------------------------------- 5920 5921;; ??? This should be a define expand. 5922;; ??? Or perhaps it should be dropped? 5923 5924;; convert_move generates good code for SH[1-4]. 5925(define_insn "extendsidi2" 5926 [(set (match_operand:DI 0 "register_operand" "=r,r,r") 5927 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))] 5928 "TARGET_SHMEDIA" 5929 "@ 5930 add.l %1, r63, %0 5931 ld%M1.l %m1, %0 5932 fmov.sl %1, %0" 5933 [(set_attr "type" "arith_media,load_media,fpconv_media") 5934 (set (attr "highpart") 5935 (cond [(match_test "sh_contains_memref_p (insn)") 5936 (const_string "user")] 5937 (const_string "extend")))]) 5938 5939(define_insn "extendhidi2" 5940 [(set (match_operand:DI 0 "register_operand" "=r,r") 5941 (sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))] 5942 "TARGET_SHMEDIA" 5943 "@ 5944 # 5945 ld%M1.w %m1, %0" 5946 [(set_attr "type" "*,load_media") 5947 (set (attr "highpart") 5948 (cond [(match_test "sh_contains_memref_p (insn)") 5949 (const_string "user")] 5950 (const_string "ignore")))]) 5951 5952(define_split 5953 [(set (match_operand:DI 0 "register_operand" "") 5954 (sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))] 5955 "TARGET_SHMEDIA && reload_completed" 5956 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48))) 5957 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))] 5958{ 5959 if (GET_CODE (operands[1]) == TRUNCATE) 5960 operands[1] = XEXP (operands[1], 0); 5961}) 5962 5963(define_insn "extendqidi2" 5964 [(set (match_operand:DI 0 "register_operand" "=r,r") 5965 (sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))] 5966 "TARGET_SHMEDIA" 5967 "@ 5968 # 5969 ld%M1.b %m1, %0" 5970 [(set_attr "type" "*,load_media") 5971 (set (attr "highpart") 5972 (cond [(match_test "sh_contains_memref_p (insn)") 5973 (const_string "user")] 5974 (const_string "ignore")))]) 5975 5976(define_split 5977 [(set (match_operand:DI 0 "register_operand" "") 5978 (sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))] 5979 "TARGET_SHMEDIA && reload_completed" 5980 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56))) 5981 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))] 5982{ 5983 if (GET_CODE (operands[1]) == TRUNCATE) 5984 operands[1] = XEXP (operands[1], 0); 5985}) 5986 5987(define_expand "extend<mode>si2" 5988 [(set (match_operand:SI 0 "arith_reg_dest") 5989 (sign_extend:SI (match_operand:QIHI 1 "general_extend_operand")))]) 5990 5991(define_insn "*extendhisi2_media" 5992 [(set (match_operand:SI 0 "register_operand" "=r,r") 5993 (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))] 5994 "TARGET_SHMEDIA" 5995 "@ 5996 # 5997 ld%M1.w %m1, %0" 5998 [(set_attr "type" "arith_media,load_media") 5999 (set (attr "highpart") 6000 (cond [(match_test "sh_contains_memref_p (insn)") 6001 (const_string "user")] 6002 (const_string "ignore")))]) 6003 6004(define_split 6005 [(set (match_operand:SI 0 "register_operand" "") 6006 (sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))] 6007 "TARGET_SHMEDIA && reload_completed" 6008 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16))) 6009 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))] 6010{ 6011 rtx op1 = operands[1]; 6012 if (GET_CODE (op1) == TRUNCATE) 6013 op1 = XEXP (op1, 0); 6014 operands[2] 6015 = simplify_gen_subreg (SImode, op1, GET_MODE (op1), 6016 subreg_lowpart_offset (SImode, GET_MODE (op1))); 6017}) 6018 6019(define_insn_and_split "*extend<mode>si2_compact_reg" 6020 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6021 (sign_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))] 6022 "TARGET_SH1" 6023 "exts.<bw> %1,%0" 6024 "&& can_create_pseudo_p ()" 6025 [(set (match_dup 0) (match_dup 2))] 6026{ 6027 /* Sometimes combine fails to combine a T bit or negated T bit store to a 6028 reg with a following sign extension. In the split pass after combine, 6029 try to figure the extended reg was set. If it originated from the T 6030 bit we can replace the sign extension with a reg move, which will be 6031 eliminated. */ 6032 operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn); 6033 if (operands[2] == NULL_RTX) 6034 FAIL; 6035} 6036 [(set_attr "type" "arith")]) 6037 6038;; FIXME: Fold non-SH2A and SH2A alternatives with "enabled" attribute. 6039;; See movqi insns. 6040(define_insn "*extend<mode>si2_compact_mem_disp" 6041 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r") 6042 (sign_extend:SI 6043 (mem:QIHI 6044 (plus:SI 6045 (match_operand:SI 1 "arith_reg_operand" "%r,r") 6046 (match_operand:SI 2 "const_int_operand" "<disp04>,N")))))] 6047 "TARGET_SH1 && ! TARGET_SH2A 6048 && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)" 6049 "@ 6050 mov.<bw> @(%O2,%1),%0 6051 mov.<bw> @%1,%0" 6052 [(set_attr "type" "load")]) 6053 6054(define_insn "*extend<mode>si2_compact_mem_disp" 6055 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r,r") 6056 (sign_extend:SI 6057 (mem:QIHI 6058 (plus:SI 6059 (match_operand:SI 1 "arith_reg_operand" "%r,r,r") 6060 (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>")))))] 6061 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)" 6062 "@ 6063 mov.<bw> @(%O2,%1),%0 6064 mov.<bw> @%1,%0 6065 mov.<bw> @(%O2,%1),%0" 6066 [(set_attr "type" "load") 6067 (set_attr "length" "2,2,4")]) 6068 6069;; The *_snd patterns will take care of other QImode/HImode addressing 6070;; modes than displacement addressing. They must be defined _after_ the 6071;; displacement addressing patterns. Otherwise the displacement addressing 6072;; patterns will not be picked. 6073(define_insn "*extend<mode>si2_compact_snd" 6074 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6075 (sign_extend:SI 6076 (match_operand:QIHI 1 "movsrc_no_disp_mem_operand" "Snd")))] 6077 "TARGET_SH1" 6078 "mov.<bw> %1,%0" 6079 [(set_attr "type" "load")]) 6080 6081(define_insn "*extendqisi2_media" 6082 [(set (match_operand:SI 0 "register_operand" "=r,r") 6083 (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))] 6084 "TARGET_SHMEDIA" 6085 "@ 6086 # 6087 ld%M1.b %m1, %0" 6088 [(set_attr "type" "arith_media,load_media") 6089 (set (attr "highpart") 6090 (cond [(match_test "sh_contains_memref_p (insn)") 6091 (const_string "user")] 6092 (const_string "ignore")))]) 6093 6094(define_split 6095 [(set (match_operand:SI 0 "register_operand" "") 6096 (sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))] 6097 "TARGET_SHMEDIA && reload_completed" 6098 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24))) 6099 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))] 6100{ 6101 rtx op1 = operands[1]; 6102 if (GET_CODE (op1) == TRUNCATE) 6103 op1 = XEXP (op1, 0); 6104 operands[2] 6105 = simplify_gen_subreg (SImode, op1, GET_MODE (op1), 6106 subreg_lowpart_offset (SImode, GET_MODE (op1))); 6107}) 6108 6109(define_expand "extendqihi2" 6110 [(set (match_operand:HI 0 "arith_reg_dest") 6111 (sign_extend:HI (match_operand:QI 1 "arith_reg_operand")))] 6112 "TARGET_SH1") 6113 6114(define_insn "*extendqihi2_compact_reg" 6115 [(set (match_operand:HI 0 "arith_reg_dest" "=r") 6116 (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))] 6117 "TARGET_SH1" 6118 "exts.b %1,%0" 6119 [(set_attr "type" "arith")]) 6120 6121;; It would seem useful to combine the truncXi patterns into the movXi 6122;; patterns, but unary operators are ignored when matching constraints, 6123;; so we need separate patterns. 6124(define_insn "truncdisi2" 6125 [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f") 6126 (truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))] 6127 "TARGET_SHMEDIA" 6128 "@ 6129 add.l %1, r63, %0 6130 st%M0.l %m0, %1 6131 fst%M0.s %m0, %T1 6132 fmov.ls %1, %0 6133 fmov.sl %T1, %0 6134 fmov.s %T1, %0" 6135 [(set_attr "type" "arith_media,store_media,fstore_media,fload_media, 6136 fpconv_media,fmove_media") 6137 (set (attr "highpart") 6138 (cond [(match_test "sh_contains_memref_p (insn)") 6139 (const_string "user")] 6140 (const_string "extend")))]) 6141 6142(define_insn "truncdihi2" 6143 [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m") 6144 (truncate:HI (match_operand:DI 1 "register_operand" "r,r")))] 6145 "TARGET_SHMEDIA" 6146{ 6147 static const char* alt[] = 6148 { 6149 "shlli %1,48,%0" "\n" 6150 " shlri %0,48,%0", 6151 6152 "st%M0.w %m0, %1" 6153 }; 6154 return alt[which_alternative]; 6155} 6156 [(set_attr "type" "arith_media,store_media") 6157 (set_attr "length" "8,4") 6158 (set (attr "highpart") 6159 (cond [(match_test "sh_contains_memref_p (insn)") 6160 (const_string "user")] 6161 (const_string "extend")))]) 6162 6163; N.B. This should agree with LOAD_EXTEND_OP and movqi. 6164; Because we use zero extension, we can't provide signed QImode compares 6165; using a simple compare or conditional branch insn. 6166(define_insn "truncdiqi2" 6167 [(set (match_operand:QI 0 "general_movdst_operand" "=r,m") 6168 (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))] 6169 "TARGET_SHMEDIA" 6170 "@ 6171 andi %1, 255, %0 6172 st%M0.b %m0, %1" 6173 [(set_attr "type" "arith_media,store") 6174 (set (attr "highpart") 6175 (cond [(match_test "sh_contains_memref_p (insn)") 6176 (const_string "user")] 6177 (const_string "extend")))]) 6178 6179;; ------------------------------------------------------------------------- 6180;; Move instructions 6181;; ------------------------------------------------------------------------- 6182 6183;; define push and pop so it is easy for sh.c 6184;; We can't use push and pop on SHcompact because the stack must always 6185;; be 8-byte aligned. 6186(define_expand "push" 6187 [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) 6188 (match_operand:SI 0 "register_operand" "r,l,x"))] 6189 "TARGET_SH1 && ! TARGET_SH5" 6190 "") 6191 6192(define_expand "pop" 6193 [(set (match_operand:SI 0 "register_operand" "=r,l,x") 6194 (mem:SI (post_inc:SI (reg:SI SP_REG))))] 6195 "TARGET_SH1 && ! TARGET_SH5" 6196 "") 6197 6198(define_expand "push_e" 6199 [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) 6200 (match_operand:SF 0 "" "")) 6201 (use (reg:PSI FPSCR_REG)) 6202 (clobber (scratch:SI))])] 6203 "TARGET_SH1 && ! TARGET_SH5" 6204 "") 6205 6206(define_insn "push_fpul" 6207 [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))] 6208 "TARGET_SH2E && ! TARGET_SH5" 6209 "sts.l fpul,@-r15" 6210 [(set_attr "type" "fstore") 6211 (set_attr "late_fp_use" "yes") 6212 (set_attr "hit_stack" "yes")]) 6213 6214;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4, 6215;; so use that. 6216(define_expand "push_4" 6217 [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG))) 6218 (match_operand:DF 0 "" "")) 6219 (use (reg:PSI FPSCR_REG)) 6220 (clobber (scratch:SI))])] 6221 "TARGET_SH1 && ! TARGET_SH5" 6222 "") 6223 6224(define_expand "pop_e" 6225 [(parallel [(set (match_operand:SF 0 "" "") 6226 (mem:SF (post_inc:SI (reg:SI SP_REG)))) 6227 (use (reg:PSI FPSCR_REG)) 6228 (clobber (scratch:SI))])] 6229 "TARGET_SH1 && ! TARGET_SH5" 6230 "") 6231 6232(define_insn "pop_fpul" 6233 [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))] 6234 "TARGET_SH2E && ! TARGET_SH5" 6235 "lds.l @r15+,fpul" 6236 [(set_attr "type" "load") 6237 (set_attr "hit_stack" "yes")]) 6238 6239(define_expand "pop_4" 6240 [(parallel [(set (match_operand:DF 0 "" "") 6241 (mem:DF (post_inc:SI (reg:SI SP_REG)))) 6242 (use (reg:PSI FPSCR_REG)) 6243 (clobber (scratch:SI))])] 6244 "TARGET_SH1 && ! TARGET_SH5" 6245 "") 6246 6247(define_expand "push_fpscr" 6248 [(const_int 0)] 6249 "TARGET_SH2E" 6250{ 6251 rtx insn = emit_insn (gen_fpu_switch (gen_frame_mem (PSImode, 6252 gen_rtx_PRE_DEC (Pmode, 6253 stack_pointer_rtx)), 6254 get_fpscr_rtx ())); 6255 add_reg_note (insn, REG_INC, stack_pointer_rtx); 6256 DONE; 6257}) 6258 6259(define_expand "pop_fpscr" 6260 [(const_int 0)] 6261 "TARGET_SH2E" 6262{ 6263 rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (), 6264 gen_frame_mem (PSImode, 6265 gen_rtx_POST_INC (Pmode, 6266 stack_pointer_rtx)))); 6267 add_reg_note (insn, REG_INC, stack_pointer_rtx); 6268 DONE; 6269}) 6270 6271;; The clrt and sett patterns can happen as the result of optimization and 6272;; insn expansion. 6273;; Comparisons might get simplified to a move of zero or 1 into the T reg. 6274;; In this case they might not disappear completely, because the T reg is 6275;; a fixed hard reg. 6276;; When DImode operations that use the T reg as carry/borrow are split into 6277;; individual SImode operations, the T reg is usually cleared before the 6278;; first SImode insn. 6279(define_insn "clrt" 6280 [(set (reg:SI T_REG) (const_int 0))] 6281 "TARGET_SH1" 6282 "clrt" 6283 [(set_attr "type" "mt_group")]) 6284 6285(define_insn "sett" 6286 [(set (reg:SI T_REG) (const_int 1))] 6287 "TARGET_SH1" 6288 "sett" 6289 [(set_attr "type" "mt_group")]) 6290 6291;; Use the combine pass to transform sequences such as 6292;; mov r5,r0 6293;; add #1,r0 6294;; shll2 r0 6295;; mov.l @(r0,r4),r0 6296;; into 6297;; shll2 r5 6298;; add r4,r5 6299;; mov.l @(4,r5),r0 6300;; 6301;; See also PR 39423. 6302;; Notice that these patterns have a T_REG clobber, because the shift 6303;; sequence that will be split out might clobber the T_REG. Ideally, the 6304;; clobber would be added conditionally, depending on the result of 6305;; sh_ashlsi_clobbers_t_reg_p. When splitting out the shifts we must go 6306;; through the ashlsi3 expander in order to get the right shift insn -- 6307;; a T_REG clobbering or non-clobbering shift sequence or dynamic shift. 6308;; FIXME: Combine never tries this kind of patterns for DImode. 6309(define_insn_and_split "*movsi_index_disp_load" 6310 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6311 (match_operand:SI 1 "mem_index_disp_operand" "m")) 6312 (clobber (reg:SI T_REG))] 6313 "TARGET_SH1" 6314 "#" 6315 "&& can_create_pseudo_p ()" 6316 [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3))) 6317 (set (match_dup 0) (match_dup 7))] 6318{ 6319 rtx mem = operands[1]; 6320 rtx plus0_rtx = XEXP (mem, 0); 6321 rtx plus1_rtx = XEXP (plus0_rtx, 0); 6322 rtx mult_rtx = XEXP (plus1_rtx, 0); 6323 6324 operands[1] = XEXP (mult_rtx, 0); 6325 operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1)))); 6326 operands[3] = XEXP (plus1_rtx, 1); 6327 operands[4] = XEXP (plus0_rtx, 1); 6328 operands[5] = gen_reg_rtx (SImode); 6329 operands[6] = gen_reg_rtx (SImode); 6330 operands[7] = 6331 replace_equiv_address (mem, 6332 gen_rtx_PLUS (SImode, operands[6], operands[4])); 6333 6334 emit_insn (gen_ashlsi3 (operands[5], operands[1], operands[2])); 6335}) 6336 6337(define_insn_and_split "*movhi_index_disp_load" 6338 [(set (match_operand:SI 0 "arith_reg_dest") 6339 (SZ_EXTEND:SI (match_operand:HI 1 "mem_index_disp_operand"))) 6340 (clobber (reg:SI T_REG))] 6341 "TARGET_SH1" 6342 "#" 6343 "&& can_create_pseudo_p ()" 6344 [(const_int 0)] 6345{ 6346 rtx mem = operands[1]; 6347 rtx plus0_rtx = XEXP (mem, 0); 6348 rtx plus1_rtx = XEXP (plus0_rtx, 0); 6349 rtx mult_rtx = XEXP (plus1_rtx, 0); 6350 6351 rtx op_1 = XEXP (mult_rtx, 0); 6352 rtx op_2 = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1)))); 6353 rtx op_3 = XEXP (plus1_rtx, 1); 6354 rtx op_4 = XEXP (plus0_rtx, 1); 6355 rtx op_5 = gen_reg_rtx (SImode); 6356 rtx op_6 = gen_reg_rtx (SImode); 6357 rtx op_7 = replace_equiv_address (mem, gen_rtx_PLUS (SImode, op_6, op_4)); 6358 6359 emit_insn (gen_ashlsi3 (op_5, op_1, op_2)); 6360 emit_insn (gen_addsi3 (op_6, op_5, op_3)); 6361 6362 if (<CODE> == SIGN_EXTEND) 6363 { 6364 emit_insn (gen_extendhisi2 (operands[0], op_7)); 6365 DONE; 6366 } 6367 else if (<CODE> == ZERO_EXTEND) 6368 { 6369 /* On SH2A the movu.w insn can be used for zero extending loads. */ 6370 if (TARGET_SH2A) 6371 emit_insn (gen_zero_extendhisi2 (operands[0], op_7)); 6372 else 6373 { 6374 emit_insn (gen_extendhisi2 (operands[0], op_7)); 6375 emit_insn (gen_zero_extendhisi2 (operands[0], 6376 gen_lowpart (HImode, operands[0]))); 6377 } 6378 DONE; 6379 } 6380 else 6381 FAIL; 6382}) 6383 6384(define_insn_and_split "*mov<mode>_index_disp_store" 6385 [(set (match_operand:HISI 0 "mem_index_disp_operand" "=m") 6386 (match_operand:HISI 1 "arith_reg_operand" "r")) 6387 (clobber (reg:SI T_REG))] 6388 "TARGET_SH1" 6389 "#" 6390 "&& can_create_pseudo_p ()" 6391 [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3))) 6392 (set (match_dup 7) (match_dup 1))] 6393{ 6394 rtx mem = operands[0]; 6395 rtx plus0_rtx = XEXP (mem, 0); 6396 rtx plus1_rtx = XEXP (plus0_rtx, 0); 6397 rtx mult_rtx = XEXP (plus1_rtx, 0); 6398 6399 operands[0] = XEXP (mult_rtx, 0); 6400 operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1)))); 6401 operands[3] = XEXP (plus1_rtx, 1); 6402 operands[4] = XEXP (plus0_rtx, 1); 6403 operands[5] = gen_reg_rtx (SImode); 6404 operands[6] = gen_reg_rtx (SImode); 6405 operands[7] = 6406 replace_equiv_address (mem, 6407 gen_rtx_PLUS (SImode, operands[6], operands[4])); 6408 6409 emit_insn (gen_ashlsi3 (operands[5], operands[0], operands[2])); 6410}) 6411 6412;; t/r must come after r/r, lest reload will try to reload stuff like 6413;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0) 6414;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T. 6415(define_insn "movsi_i" 6416 [(set (match_operand:SI 0 "general_movdst_operand" 6417 "=r,r,r,r,r,r,m,<,<,x,l,x,l,r") 6418 (match_operand:SI 1 "general_movsrc_operand" 6419 "Q,r,I08,mr,x,l,r,x,l,r,r,>,>,i"))] 6420 "TARGET_SH1 6421 && ! TARGET_SH2E 6422 && ! TARGET_SH2A 6423 && (register_operand (operands[0], SImode) 6424 || register_operand (operands[1], SImode))" 6425 "@ 6426 mov.l %1,%0 6427 mov %1,%0 6428 mov %1,%0 6429 mov.l %1,%0 6430 sts %1,%0 6431 sts %1,%0 6432 mov.l %1,%0 6433 sts.l %1,%0 6434 sts.l %1,%0 6435 lds %1,%0 6436 lds %1,%0 6437 lds.l %1,%0 6438 lds.l %1,%0 6439 fake %1,%0" 6440 [(set_attr "type" "pcload_si,move,movi8,load_si,mac_gp,prget,store,mac_mem, 6441 pstore,gp_mac,prset,mem_mac,pload,pcload_si") 6442 (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*")]) 6443 6444;; t/r must come after r/r, lest reload will try to reload stuff like 6445;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2) 6446;; ??? This allows moves from macl to fpul to be recognized, but these moves 6447;; will require a reload. 6448;; ??? We can't include f/f because we need the proper FPSCR setting when 6449;; TARGET_FMOVD is in effect, and mode switching is done before reload. 6450(define_insn "movsi_ie" 6451 [(set (match_operand:SI 0 "general_movdst_operand" 6452 "=r,r,r,r,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y") 6453 (match_operand:SI 1 "general_movsrc_operand" 6454 "Q,r,I08,I20,I28,mr,x,l,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))] 6455 "(TARGET_SH2E || TARGET_SH2A) 6456 && (register_operand (operands[0], SImode) 6457 || register_operand (operands[1], SImode))" 6458 "@ 6459 mov.l %1,%0 6460 mov %1,%0 6461 mov %1,%0 6462 movi20 %1,%0 6463 movi20s %1,%0 6464 mov.l %1,%0 6465 sts %1,%0 6466 sts %1,%0 6467 mov.l %1,%0 6468 sts.l %1,%0 6469 sts.l %1,%0 6470 lds %1,%0 6471 lds %1,%0 6472 lds.l %1,%0 6473 lds.l %1,%0 6474 lds.l %1,%0 6475 sts.l %1,%0 6476 fake %1,%0 6477 lds %1,%0 6478 sts %1,%0 6479 fsts fpul,%0 6480 flds %1,fpul 6481 fmov %1,%0 6482 ! move optimized away" 6483 [(set_attr "type" "pcload_si,move,movi8,move,move,load_si,mac_gp,prget,store, 6484 mac_mem,pstore,gp_mac,prset,mem_mac,pload,load,fstore, 6485 pcload_si,gp_fpul,fpul_gp,fmove,fmove,fmove,nil") 6486 (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*") 6487 (set_attr_alternative "length" 6488 [(const_int 2) 6489 (const_int 2) 6490 (const_int 2) 6491 (const_int 4) 6492 (const_int 4) 6493 (if_then_else 6494 (match_test "TARGET_SH2A") 6495 (const_int 4) (const_int 2)) 6496 (const_int 2) 6497 (const_int 2) 6498 (if_then_else 6499 (match_test "TARGET_SH2A") 6500 (const_int 4) (const_int 2)) 6501 (const_int 2) 6502 (const_int 2) 6503 (const_int 2) 6504 (const_int 2) 6505 (const_int 2) 6506 (const_int 2) 6507 (const_int 2) 6508 (const_int 2) 6509 (const_int 2) 6510 (const_int 2) 6511 (const_int 2) 6512 (const_int 2) 6513 (const_int 2) 6514 (const_int 2) 6515 (const_int 0)])]) 6516 6517(define_insn "movsi_i_lowpart" 6518 [(set (strict_low_part 6519 (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r")) 6520 (match_operand:SI 1 "general_movsrc_operand" "Q,r,I08,mr,x,l,r,i"))] 6521 "TARGET_SH1 6522 && (register_operand (operands[0], SImode) 6523 || register_operand (operands[1], SImode))" 6524 "@ 6525 mov.l %1,%0 6526 mov %1,%0 6527 mov %1,%0 6528 mov.l %1,%0 6529 sts %1,%0 6530 sts %1,%0 6531 mov.l %1,%0 6532 fake %1,%0" 6533 [(set_attr "type" "pcload,move,arith,load,mac_gp,prget,store,pcload")]) 6534 6535(define_insn_and_split "load_ra" 6536 [(set (match_operand:SI 0 "general_movdst_operand" "") 6537 (unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))] 6538 "TARGET_SH1" 6539 "#" 6540 "&& ! currently_expanding_to_rtl" 6541 [(set (match_dup 0) (match_dup 1))] 6542{ 6543 if (TARGET_SHCOMPACT && crtl->saves_all_registers) 6544 operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx); 6545}) 6546 6547;; The '?'s in the following constraints may not reflect the time taken 6548;; to perform the move. They are there to discourage the use of floating- 6549;; point registers for storing integer values. 6550(define_insn "*movsi_media" 6551 [(set (match_operand:SI 0 "general_movdst_operand" 6552 "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b") 6553 (match_operand:SI 1 "general_movsrc_operand" 6554 "r,I16Css,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))] 6555 "TARGET_SHMEDIA_FPU 6556 && (register_operand (operands[0], SImode) 6557 || sh_register_operand (operands[1], SImode) 6558 || GET_CODE (operands[1]) == TRUNCATE)" 6559 "@ 6560 add.l %1, r63, %0 6561 movi %1, %0 6562 # 6563 ld%M1.l %m1, %0 6564 st%M0.l %m0, %N1 6565 fld%M1.s %m1, %0 6566 fst%M0.s %m0, %1 6567 fmov.ls %N1, %0 6568 fmov.sl %1, %0 6569 fmov.s %1, %0 6570 ptabs %1, %0 6571 gettr %1, %0 6572 pt %1, %0" 6573 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media, 6574 fload_media,fstore_media,fload_media,fpconv_media, 6575 fmove_media,ptabs_media,gettr_media,pt_media") 6576 (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12") 6577 (set (attr "highpart") 6578 (cond [(match_test "sh_contains_memref_p (insn)") 6579 (const_string "user")] 6580 (const_string "ignore")))]) 6581 6582(define_insn "*movsi_media_nofpu" 6583 [(set (match_operand:SI 0 "general_movdst_operand" 6584 "=r,r,r,r,m,*b,r,*b") 6585 (match_operand:SI 1 "general_movsrc_operand" 6586 "r,I16Css,nCpg,m,rZ,r,*b,Csy"))] 6587 "TARGET_SHMEDIA 6588 && (register_operand (operands[0], SImode) 6589 || sh_register_operand (operands[1], SImode) 6590 || GET_CODE (operands[1]) == TRUNCATE)" 6591 "@ 6592 add.l %1, r63, %0 6593 movi %1, %0 6594 # 6595 ld%M1.l %m1, %0 6596 st%M0.l %m0, %N1 6597 ptabs %1, %0 6598 gettr %1, %0 6599 pt %1, %0" 6600 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media, 6601 ptabs_media,gettr_media,pt_media") 6602 (set_attr "length" "4,4,8,4,4,4,4,12") 6603 (set (attr "highpart") 6604 (cond [(match_test "sh_contains_memref_p (insn)") 6605 (const_string "user")] 6606 (const_string "ignore")))]) 6607 6608(define_expand "movsi_const" 6609 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 6610 (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s") 6611 (const_int 16)] UNSPEC_EXTRACT_S16))) 6612 (set (match_dup 0) 6613 (ior:SI (ashift:SI (match_dup 0) (const_int 16)) 6614 (const:SI (unspec:SI [(match_dup 1) 6615 (const_int 0)] UNSPEC_EXTRACT_U16))))] 6616 "TARGET_SHMEDIA && reload_completed 6617 && MOVI_SHORI_BASE_OPERAND_P (operands[1])" 6618{ 6619 if (GET_CODE (operands[1]) == LABEL_REF 6620 && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL) 6621 LABEL_NUSES (XEXP (operands[1], 0)) += 2; 6622 else if (GOTOFF_P (operands[1])) 6623 { 6624 rtx unspec = XEXP (operands[1], 0); 6625 6626 if (! UNSPEC_GOTOFF_P (unspec)) 6627 { 6628 unspec = XEXP (unspec, 0); 6629 if (! UNSPEC_GOTOFF_P (unspec)) 6630 abort (); 6631 } 6632 if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF 6633 && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL)) 6634 LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2; 6635 } 6636}) 6637 6638(define_expand "movsi_const_16bit" 6639 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 6640 (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s") 6641 (const_int 0)] UNSPEC_EXTRACT_S16)))] 6642 "TARGET_SHMEDIA && flag_pic && reload_completed 6643 && GET_CODE (operands[1]) == SYMBOL_REF" 6644 "") 6645 6646(define_split 6647 [(set (match_operand:SI 0 "arith_reg_dest" "") 6648 (match_operand:SI 1 "immediate_operand" ""))] 6649 "TARGET_SHMEDIA && reload_completed 6650 && MOVI_SHORI_BASE_OPERAND_P (operands[1])" 6651 [(const_int 0)] 6652{ 6653 rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1])); 6654 6655 set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1])); 6656 6657 DONE; 6658}) 6659 6660(define_split 6661 [(set (match_operand:SI 0 "register_operand" "") 6662 (match_operand:SI 1 "immediate_operand" ""))] 6663 "TARGET_SHMEDIA && reload_completed 6664 && ((CONST_INT_P (operands[1]) 6665 && ! satisfies_constraint_I16 (operands[1])) 6666 || GET_CODE (operands[1]) == CONST_DOUBLE)" 6667 [(set (subreg:DI (match_dup 0) 0) (match_dup 1))]) 6668 6669(define_expand "movsi" 6670 [(set (match_operand:SI 0 "general_movdst_operand" "") 6671 (match_operand:SI 1 "general_movsrc_operand" ""))] 6672 "" 6673{ 6674 prepare_move_operands (operands, SImode); 6675}) 6676 6677(define_expand "ic_invalidate_line" 6678 [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r") 6679 (match_dup 1)] UNSPEC_ICACHE) 6680 (clobber (scratch:SI))])] 6681 "TARGET_HARD_SH4 || TARGET_SH5" 6682{ 6683 if (TARGET_SHMEDIA) 6684 { 6685 emit_insn (gen_ic_invalidate_line_media (operands[0])); 6686 DONE; 6687 } 6688 else if (TARGET_SHCOMPACT) 6689 { 6690 operands[1] = function_symbol (NULL, "__ic_invalidate", SFUNC_STATIC); 6691 operands[1] = force_reg (Pmode, operands[1]); 6692 emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1])); 6693 DONE; 6694 } 6695 else if (TARGET_SH4A_ARCH || TARGET_SH4_300) 6696 { 6697 emit_insn (gen_ic_invalidate_line_sh4a (operands[0])); 6698 DONE; 6699 } 6700 operands[0] = force_reg (Pmode, operands[0]); 6701 operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008, 6702 Pmode))); 6703}) 6704 6705;; The address %0 is assumed to be 4-aligned at least. Thus, by ORing 6706;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits 6707;; the requirement *1*00 for associative address writes. The alignment of 6708;; %0 implies that its least significant bit is cleared, 6709;; thus we clear the V bit of a matching entry if there is one. 6710(define_insn "ic_invalidate_line_i" 6711 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r") 6712 (match_operand:SI 1 "register_operand" "r")] 6713 UNSPEC_ICACHE) 6714 (clobber (match_scratch:SI 2 "=&r"))] 6715 "TARGET_HARD_SH4" 6716{ 6717 return "ocbwb @%0" "\n" 6718 " extu.w %0,%2" "\n" 6719 " or %1,%2" "\n" 6720 " mov.l %0,@%2"; 6721} 6722 [(set_attr "length" "8") 6723 (set_attr "type" "cwb")]) 6724 6725(define_insn "ic_invalidate_line_sh4a" 6726 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] 6727 UNSPEC_ICACHE)] 6728 "TARGET_SH4A_ARCH || TARGET_SH4_300" 6729{ 6730 return "ocbwb @%0" "\n" 6731 " synco" "\n" 6732 " icbi @%0"; 6733} 6734 [(set_attr "length" "16") ;; FIXME: Why 16 and not 6? Looks like typo. 6735 (set_attr "type" "cwb")]) 6736 6737;; ??? could make arg 0 an offsettable memory operand to allow to save 6738;; an add in the code that calculates the address. 6739(define_insn "ic_invalidate_line_media" 6740 [(unspec_volatile [(match_operand 0 "any_register_operand" "r")] 6741 UNSPEC_ICACHE)] 6742 "TARGET_SHMEDIA" 6743{ 6744 return "ocbwb %0,0" "\n" 6745 " synco" "\n" 6746 " icbi %0,0" "\n" 6747 " synci"; 6748} 6749 [(set_attr "length" "16") 6750 (set_attr "type" "invalidate_line_media")]) 6751 6752(define_insn "ic_invalidate_line_compact" 6753 [(unspec_volatile [(match_operand:SI 0 "register_operand" "z") 6754 (match_operand:SI 1 "register_operand" "r")] 6755 UNSPEC_ICACHE) 6756 (clobber (reg:SI PR_REG))] 6757 "TARGET_SHCOMPACT" 6758 "jsr @%1%#" 6759 [(set_attr "type" "sfunc") 6760 (set_attr "needs_delay_slot" "yes")]) 6761 6762(define_expand "initialize_trampoline" 6763 [(match_operand:SI 0 "" "") 6764 (match_operand:SI 1 "" "") 6765 (match_operand:SI 2 "" "")] 6766 "TARGET_SHCOMPACT" 6767{ 6768 rtx sfun, tramp; 6769 6770 tramp = force_reg (Pmode, operands[0]); 6771 sfun = force_reg (Pmode, function_symbol (NULL, "__init_trampoline", 6772 SFUNC_STATIC)); 6773 emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]); 6774 emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]); 6775 6776 emit_insn (gen_initialize_trampoline_compact (tramp, sfun)); 6777 DONE; 6778}) 6779 6780(define_insn "initialize_trampoline_compact" 6781 [(unspec_volatile [(match_operand:SI 0 "register_operand" "z") 6782 (match_operand:SI 1 "register_operand" "r") 6783 (reg:SI R2_REG) (reg:SI R3_REG)] 6784 UNSPEC_INIT_TRAMP) 6785 6786 (clobber (reg:SI PR_REG))] 6787 "TARGET_SHCOMPACT" 6788 "jsr @%1%#" 6789 [(set_attr "type" "sfunc") 6790 (set_attr "needs_delay_slot" "yes")]) 6791 6792(define_expand "movhi" 6793 [(set (match_operand:HI 0 "general_movdst_operand" "") 6794 (match_operand:HI 1 "general_movsrc_operand" ""))] 6795 "" 6796{ 6797 prepare_move_operands (operands, HImode); 6798}) 6799 6800(define_expand "movqi" 6801 [(set (match_operand:QI 0 "general_operand" "") 6802 (match_operand:QI 1 "general_operand" ""))] 6803 "" 6804{ 6805 prepare_move_operands (operands, QImode); 6806}) 6807 6808;; Specifying the displacement addressing load / store patterns separately 6809;; before the generic movqi / movhi pattern allows controlling the order 6810;; in which load / store insns are selected in a more fine grained way. 6811;; FIXME: The non-SH2A and SH2A variants should be combined by adding 6812;; "enabled" attribute as it is done in other targets. 6813(define_insn "*mov<mode>_store_mem_disp04" 6814 [(set (mem:QIHI 6815 (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r,r") 6816 (match_operand:SI 1 "const_int_operand" "<disp04>,N"))) 6817 (match_operand:QIHI 2 "arith_reg_operand" "z,r"))] 6818 "TARGET_SH1 && sh_legitimate_index_p (<MODE>mode, operands[1], false, true)" 6819 "@ 6820 mov.<bw> %2,@(%O1,%0) 6821 mov.<bw> %2,@%0" 6822 [(set_attr "type" "store")]) 6823 6824(define_insn "*mov<mode>_store_mem_disp12" 6825 [(set (mem:QIHI 6826 (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r") 6827 (match_operand:SI 1 "const_int_operand" "<disp12>"))) 6828 (match_operand:QIHI 2 "arith_reg_operand" "r"))] 6829 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[1], true, true)" 6830 "mov.<bw> %2,@(%O1,%0)" 6831 [(set_attr "type" "store") 6832 (set_attr "length" "4")]) 6833 6834(define_insn "*mov<mode>_load_mem_disp04" 6835 [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r") 6836 (mem:QIHI 6837 (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r") 6838 (match_operand:SI 2 "const_int_operand" "<disp04>,N"))))] 6839 "TARGET_SH1 && ! TARGET_SH2A 6840 && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)" 6841 "@ 6842 mov.<bw> @(%O2,%1),%0 6843 mov.<bw> @%1,%0" 6844 [(set_attr "type" "load")]) 6845 6846(define_insn "*mov<mode>_load_mem_disp12" 6847 [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r,r") 6848 (mem:QIHI 6849 (plus:SI 6850 (match_operand:SI 1 "arith_reg_operand" "%r,r,r") 6851 (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>"))))] 6852 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)" 6853 "@ 6854 mov.<bw> @(%O2,%1),%0 6855 mov.<bw> @%1,%0 6856 mov.<bw> @(%O2,%1),%0" 6857 [(set_attr "type" "load") 6858 (set_attr "length" "2,2,4")]) 6859 6860;; The order of the constraint alternatives is important here. 6861;; Q/r has to come first, otherwise PC relative loads might wrongly get 6862;; placed into delay slots. Since there is no QImode PC relative load, the 6863;; Q constraint and general_movsrc_operand will reject it for QImode. 6864;; The Snd alternatives should come before Sdd in order to avoid a preference 6865;; of using r0 als the register operand for addressing modes other than 6866;; displacement addressing. 6867;; The Sdd alternatives allow only r0 as register operand, even though on 6868;; SH2A any register could be allowed by switching to a 32 bit insn. 6869;; Generally sticking to the r0 is preferrable, since it generates smaller 6870;; code. Obvious r0 reloads can then be eliminated with a peephole on SH2A. 6871(define_insn "*mov<mode>" 6872 [(set (match_operand:QIHI 0 "general_movdst_operand" 6873 "=r,r,r,Snd,r, Sdd,z, r,l") 6874 (match_operand:QIHI 1 "general_movsrc_operand" 6875 "Q,r,i,r, Snd,z, Sdd,l,r"))] 6876 "TARGET_SH1 6877 && (arith_reg_operand (operands[0], <MODE>mode) 6878 || arith_reg_operand (operands[1], <MODE>mode))" 6879 "@ 6880 mov.<bw> %1,%0 6881 mov %1,%0 6882 mov %1,%0 6883 mov.<bw> %1,%0 6884 mov.<bw> %1,%0 6885 mov.<bw> %1,%0 6886 mov.<bw> %1,%0 6887 sts %1,%0 6888 lds %1,%0" 6889 [(set_attr "type" "pcload,move,movi8,store,load,store,load,prget,prset") 6890 (set (attr "length") 6891 (cond [(and (match_operand 0 "displacement_mem_operand") 6892 (not (match_operand 0 "short_displacement_mem_operand"))) 6893 (const_int 4) 6894 (and (match_operand 1 "displacement_mem_operand") 6895 (not (match_operand 1 "short_displacement_mem_operand"))) 6896 (const_int 4)] 6897 (const_int 2)))]) 6898 6899(define_insn "*movqi_media" 6900 [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m") 6901 (match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))] 6902 "TARGET_SHMEDIA 6903 && (arith_reg_operand (operands[0], QImode) 6904 || extend_reg_or_0_operand (operands[1], QImode))" 6905 "@ 6906 add.l %1, r63, %0 6907 movi %1, %0 6908 ld%M1.ub %m1, %0 6909 st%M0.b %m0, %N1" 6910 [(set_attr "type" "arith_media,arith_media,load_media,store_media") 6911 (set (attr "highpart") 6912 (cond [(match_test "sh_contains_memref_p (insn)") 6913 (const_string "user")] 6914 (const_string "ignore")))]) 6915 6916(define_expand "reload_inqi" 6917 [(set (match_operand:SI 2 "" "=&r") 6918 (match_operand:QI 1 "inqhi_operand" "")) 6919 (set (match_operand:QI 0 "arith_reg_operand" "=r") 6920 (truncate:QI (match_dup 3)))] 6921 "TARGET_SHMEDIA" 6922{ 6923 rtx inner = XEXP (operands[1], 0); 6924 int regno = REGNO (inner); 6925 6926 regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1; 6927 operands[1] = gen_rtx_REG (SImode, regno); 6928 operands[3] = gen_rtx_REG (DImode, REGNO (operands[2])); 6929}) 6930 6931(define_insn "*movhi_media" 6932 [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m") 6933 (match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))] 6934 "TARGET_SHMEDIA 6935 && (arith_reg_operand (operands[0], HImode) 6936 || arith_reg_or_0_operand (operands[1], HImode))" 6937 "@ 6938 add.l %1, r63, %0 6939 movi %1, %0 6940 # 6941 ld%M1.w %m1, %0 6942 st%M0.w %m0, %N1" 6943 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media") 6944 (set (attr "highpart") 6945 (cond [(match_test "sh_contains_memref_p (insn)") 6946 (const_string "user")] 6947 (const_string "ignore")))]) 6948 6949(define_split 6950 [(set (match_operand:HI 0 "register_operand" "") 6951 (match_operand:HI 1 "immediate_operand" ""))] 6952 "TARGET_SHMEDIA && reload_completed 6953 && ! satisfies_constraint_I16 (operands[1])" 6954 [(set (subreg:DI (match_dup 0) 0) (match_dup 1))]) 6955 6956(define_expand "reload_inhi" 6957 [(set (match_operand:SI 2 "" "=&r") 6958 (match_operand:HI 1 "inqhi_operand" "")) 6959 (set (match_operand:HI 0 "arith_reg_operand" "=r") 6960 (truncate:HI (match_dup 3)))] 6961 "TARGET_SHMEDIA" 6962{ 6963 rtx inner = XEXP (operands[1], 0); 6964 int regno = REGNO (inner); 6965 6966 regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1; 6967 operands[1] = gen_rtx_REG (SImode, regno); 6968 operands[3] = gen_rtx_REG (DImode, REGNO (operands[2])); 6969}) 6970 6971;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c 6972;; compiled with -m2 -ml -O3 -funroll-loops 6973(define_insn "*movdi_i" 6974 [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x") 6975 (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))] 6976 "TARGET_SH1 6977 && (arith_reg_operand (operands[0], DImode) 6978 || arith_reg_operand (operands[1], DImode))" 6979{ 6980 return output_movedouble (insn, operands, DImode); 6981} 6982 [(set_attr "length" "4") 6983 (set_attr "type" "pcload,move,load,store,move,pcload,move,move")]) 6984 6985;; If the output is a register and the input is memory or a register, we have 6986;; to be careful and see which word needs to be loaded first. 6987(define_split 6988 [(set (match_operand:DI 0 "general_movdst_operand" "") 6989 (match_operand:DI 1 "general_movsrc_operand" ""))] 6990 "TARGET_SH1 && reload_completed" 6991 [(set (match_dup 2) (match_dup 3)) 6992 (set (match_dup 4) (match_dup 5))] 6993{ 6994 int regno; 6995 6996 if ((MEM_P (operands[0]) 6997 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) 6998 || (MEM_P (operands[1]) 6999 && GET_CODE (XEXP (operands[1], 0)) == POST_INC)) 7000 FAIL; 7001 7002 switch (GET_CODE (operands[0])) 7003 { 7004 case REG: 7005 regno = REGNO (operands[0]); 7006 break; 7007 case SUBREG: 7008 regno = subreg_regno (operands[0]); 7009 break; 7010 case MEM: 7011 regno = -1; 7012 break; 7013 default: 7014 gcc_unreachable (); 7015 } 7016 7017 if (regno == -1 7018 || ! refers_to_regno_p (regno, regno + 1, operands[1], 0)) 7019 { 7020 operands[2] = operand_subword (operands[0], 0, 0, DImode); 7021 operands[3] = operand_subword (operands[1], 0, 0, DImode); 7022 operands[4] = operand_subword (operands[0], 1, 0, DImode); 7023 operands[5] = operand_subword (operands[1], 1, 0, DImode); 7024 } 7025 else 7026 { 7027 operands[2] = operand_subword (operands[0], 1, 0, DImode); 7028 operands[3] = operand_subword (operands[1], 1, 0, DImode); 7029 operands[4] = operand_subword (operands[0], 0, 0, DImode); 7030 operands[5] = operand_subword (operands[1], 0, 0, DImode); 7031 } 7032 7033 if (operands[2] == 0 || operands[3] == 0 7034 || operands[4] == 0 || operands[5] == 0) 7035 FAIL; 7036}) 7037 7038;; The '?'s in the following constraints may not reflect the time taken 7039;; to perform the move. They are there to discourage the use of floating- 7040;; point registers for storing integer values. 7041(define_insn "*movdi_media" 7042 [(set (match_operand:DI 0 "general_movdst_operand" 7043 "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b") 7044 (match_operand:DI 1 "general_movsrc_operand" 7045 "r,I16Css,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))] 7046 "TARGET_SHMEDIA_FPU 7047 && (register_operand (operands[0], DImode) 7048 || sh_register_operand (operands[1], DImode))" 7049 "@ 7050 add %1, r63, %0 7051 movi %1, %0 7052 # 7053 ld%M1.q %m1, %0 7054 st%M0.q %m0, %N1 7055 fld%M1.d %m1, %0 7056 fst%M0.d %m0, %1 7057 fmov.qd %N1, %0 7058 fmov.dq %1, %0 7059 fmov.d %1, %0 7060 ptabs %1, %0 7061 gettr %1, %0 7062 pt %1, %0" 7063 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media, 7064 fload_media,fstore_media,fload_media,dfpconv_media, 7065 fmove_media,ptabs_media,gettr_media,pt_media") 7066 (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")]) 7067 7068(define_insn "*movdi_media_nofpu" 7069 [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b"); 7070 (match_operand:DI 1 "general_movsrc_operand" "r,I16Css,nCpgF,m,rlZ,r,*b,Csy"))] 7071 "TARGET_SHMEDIA 7072 && (register_operand (operands[0], DImode) 7073 || sh_register_operand (operands[1], DImode))" 7074 "@ 7075 add %1, r63, %0 7076 movi %1, %0 7077 # 7078 ld%M1.q %m1, %0 7079 st%M0.q %m0, %N1 7080 ptabs %1, %0 7081 gettr %1, %0 7082 pt %1, %0" 7083 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media, 7084 ptabs_media,gettr_media,pt_media") 7085 (set_attr "length" "4,4,16,4,4,4,4,*")]) 7086 7087(define_insn "*movdi_media_I16" 7088 [(set (match_operand:DI 0 "ext_dest_operand" "=r") 7089 (match_operand:DI 1 "const_int_operand" "I16"))] 7090 "TARGET_SHMEDIA && reload_completed" 7091 "movi %1, %0" 7092 [(set_attr "type" "arith_media") 7093 (set_attr "length" "4")]) 7094 7095(define_split 7096 [(set (match_operand:DI 0 "arith_reg_dest" "") 7097 (match_operand:DI 1 "immediate_operand" ""))] 7098 "TARGET_SHMEDIA && reload_completed 7099 && MOVI_SHORI_BASE_OPERAND_P (operands[1])" 7100 [(set (match_dup 0) (match_dup 1))] 7101{ 7102 rtx insn; 7103 7104 if (TARGET_SHMEDIA64) 7105 insn = emit_insn (gen_movdi_const (operands[0], operands[1])); 7106 else 7107 insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1])); 7108 7109 set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1])); 7110 7111 DONE; 7112}) 7113 7114(define_expand "movdi_const" 7115 [(set (match_operand:DI 0 "arith_reg_operand" "=r") 7116 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s") 7117 (const_int 48)] UNSPEC_EXTRACT_S16))) 7118 (set (match_dup 0) 7119 (ior:DI (ashift:DI (match_dup 0) (const_int 16)) 7120 (const:DI (unspec:DI [(match_dup 1) 7121 (const_int 32)] UNSPEC_EXTRACT_U16)))) 7122 (set (match_dup 0) 7123 (ior:DI (ashift:DI (match_dup 0) (const_int 16)) 7124 (const:DI (unspec:DI [(match_dup 1) 7125 (const_int 16)] UNSPEC_EXTRACT_U16)))) 7126 (set (match_dup 0) 7127 (ior:DI (ashift:DI (match_dup 0) (const_int 16)) 7128 (const:DI (unspec:DI [(match_dup 1) 7129 (const_int 0)] UNSPEC_EXTRACT_U16))))] 7130 "TARGET_SHMEDIA64 && reload_completed 7131 && MOVI_SHORI_BASE_OPERAND_P (operands[1])" 7132{ 7133 sh_mark_label (operands[1], 4); 7134}) 7135 7136(define_expand "movdi_const_32bit" 7137 [(set (match_operand:DI 0 "arith_reg_operand" "=r") 7138 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s") 7139 (const_int 16)] UNSPEC_EXTRACT_S16))) 7140 (set (match_dup 0) 7141 (ior:DI (ashift:DI (match_dup 0) (const_int 16)) 7142 (const:DI (unspec:DI [(match_dup 1) 7143 (const_int 0)] UNSPEC_EXTRACT_U16))))] 7144 "TARGET_SHMEDIA32 && reload_completed 7145 && MOVI_SHORI_BASE_OPERAND_P (operands[1])" 7146{ 7147 sh_mark_label (operands[1], 2); 7148}) 7149 7150(define_expand "movdi_const_16bit" 7151 [(set (match_operand:DI 0 "arith_reg_operand" "=r") 7152 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s") 7153 (const_int 0)] UNSPEC_EXTRACT_S16)))] 7154 "TARGET_SHMEDIA && flag_pic && reload_completed 7155 && GET_CODE (operands[1]) == SYMBOL_REF" 7156 "") 7157 7158(define_split 7159 [(set (match_operand:DI 0 "ext_dest_operand" "") 7160 (match_operand:DI 1 "immediate_operand" ""))] 7161 "TARGET_SHMEDIA && reload_completed 7162 && CONST_INT_P (operands[1]) 7163 && ! satisfies_constraint_I16 (operands[1])" 7164 [(set (match_dup 0) (match_dup 2)) 7165 (match_dup 1)] 7166{ 7167 unsigned HOST_WIDE_INT val = INTVAL (operands[1]); 7168 unsigned HOST_WIDE_INT low = val; 7169 unsigned HOST_WIDE_INT high = val; 7170 unsigned HOST_WIDE_INT sign; 7171 unsigned HOST_WIDE_INT val2 = val ^ (val-1); 7172 7173 /* Zero-extend the 16 least-significant bits. */ 7174 low &= 0xffff; 7175 7176 /* Arithmetic shift right the word by 16 bits. */ 7177 high >>= 16; 7178 if (GET_CODE (operands[0]) == SUBREG 7179 && GET_MODE (SUBREG_REG (operands[0])) == SImode) 7180 { 7181 high &= 0xffff; 7182 high ^= 0x8000; 7183 high -= 0x8000; 7184 } 7185 else 7186 { 7187 sign = 1; 7188 sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1); 7189 high ^= sign; 7190 high -= sign; 7191 } 7192 do 7193 { 7194 /* If we can't generate the constant with a two-insn movi / shori 7195 sequence, try some other strategies. */ 7196 if (! CONST_OK_FOR_I16 (high)) 7197 { 7198 /* Try constant load / left shift. We know VAL != 0. */ 7199 val2 = val ^ (val-1); 7200 if (val2 > 0x1ffff) 7201 { 7202 int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15; 7203 7204 if (CONST_OK_FOR_I16 (val >> trailing_zeroes) 7205 || (! CONST_OK_FOR_I16 (high >> 16) 7206 && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16)))) 7207 { 7208 val2 = (HOST_WIDE_INT) val >> trailing_zeroes; 7209 operands[1] = gen_ashldi3_media (operands[0], operands[0], 7210 GEN_INT (trailing_zeroes)); 7211 break; 7212 } 7213 } 7214 /* Try constant load / right shift. */ 7215 val2 = (val >> 15) + 1; 7216 if (val2 == (val2 & -val2)) 7217 { 7218 int shift = 49 - exact_log2 (val2); 7219 7220 val2 = trunc_int_for_mode (val << shift, DImode); 7221 if (CONST_OK_FOR_I16 (val2)) 7222 { 7223 operands[1] = gen_lshrdi3_media (operands[0], operands[0], 7224 GEN_INT (shift)); 7225 break; 7226 } 7227 } 7228 /* Try mperm.w . */ 7229 val2 = val & 0xffff; 7230 if ((val >> 16 & 0xffff) == val2 7231 && (val >> 32 & 0xffff) == val2 7232 && (val >> 48 & 0xffff) == val2) 7233 { 7234 val2 = (HOST_WIDE_INT) val >> 48; 7235 operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0])); 7236 operands[1] = gen_mperm_w0 (operands[1], operands[1]); 7237 break; 7238 } 7239 /* Try movi / mshflo.l */ 7240 val2 = (HOST_WIDE_INT) val >> 32; 7241 if (val2 == ((unsigned HOST_WIDE_INT) 7242 trunc_int_for_mode (val, SImode))) 7243 { 7244 operands[1] = gen_mshflo_l_di (operands[0], operands[0], 7245 operands[0]); 7246 break; 7247 } 7248 /* Try movi / mshflo.l w/ r63. */ 7249 val2 = val + ((HOST_WIDE_INT) -1 << 32); 7250 if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2)) 7251 { 7252 operands[1] = gen_mshflo_l_di (operands[0], operands[0], 7253 const0_rtx); 7254 break; 7255 } 7256 } 7257 val2 = high; 7258 operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low)); 7259 } 7260 while (0); 7261 operands[2] = GEN_INT (val2); 7262}) 7263 7264(define_split 7265 [(set (match_operand:DI 0 "ext_dest_operand" "") 7266 (match_operand:DI 1 "immediate_operand" ""))] 7267 "TARGET_SHMEDIA && reload_completed 7268 && GET_CODE (operands[1]) == CONST_DOUBLE" 7269 [(set (match_dup 0) (match_dup 2)) 7270 (set (match_dup 0) 7271 (ior:DI (ashift:DI (match_dup 0) (const_int 16)) (match_dup 1)))] 7272{ 7273 unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]); 7274 unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]); 7275 unsigned HOST_WIDE_INT val = low; 7276 unsigned HOST_WIDE_INT sign; 7277 7278 /* Zero-extend the 16 least-significant bits. */ 7279 val &= 0xffff; 7280 operands[1] = GEN_INT (val); 7281 7282 /* Arithmetic shift right the double-word by 16 bits. */ 7283 low >>= 16; 7284 low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16); 7285 high >>= 16; 7286 sign = 1; 7287 sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1); 7288 high ^= sign; 7289 high -= sign; 7290 7291 /* This will only be true if high is a sign-extension of low, i.e., 7292 it must be either 0 or (unsigned)-1, and be zero iff the 7293 most-significant bit of low is set. */ 7294 if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0) 7295 operands[2] = GEN_INT (low); 7296 else 7297 operands[2] = immed_double_const (low, high, DImode); 7298}) 7299 7300(define_insn "shori_media" 7301 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r") 7302 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0") 7303 (const_int 16)) 7304 (match_operand:DI 2 "immediate_operand" "K16Csu,nF")))] 7305 "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))" 7306 "@ 7307 shori %u2, %0 7308 #" 7309 [(set_attr "type" "arith_media,*")]) 7310 7311(define_insn "*shori_media_si" 7312 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 7313 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") 7314 (const_int 16)) 7315 (match_operand:SI 2 "immediate_operand" "K16Csu")))] 7316 "TARGET_SHMEDIA" 7317 "shori %u2, %0") 7318 7319(define_expand "movdi" 7320 [(set (match_operand:DI 0 "general_movdst_operand" "") 7321 (match_operand:DI 1 "general_movsrc_operand" ""))] 7322 "" 7323{ 7324 prepare_move_operands (operands, DImode); 7325}) 7326 7327(define_insn "movdf_media" 7328 [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m") 7329 (match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))] 7330 "TARGET_SHMEDIA_FPU 7331 && (register_operand (operands[0], DFmode) 7332 || sh_register_operand (operands[1], DFmode))" 7333 "@ 7334 fmov.d %1, %0 7335 fmov.qd %N1, %0 7336 fmov.dq %1, %0 7337 add %1, r63, %0 7338 # 7339 fld%M1.d %m1, %0 7340 fst%M0.d %m0, %1 7341 ld%M1.q %m1, %0 7342 st%M0.q %m0, %N1" 7343 [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*, 7344 fload_media,fstore_media,load_media,store_media")]) 7345 7346(define_insn "movdf_media_nofpu" 7347 [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m") 7348 (match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))] 7349 "TARGET_SHMEDIA 7350 && (register_operand (operands[0], DFmode) 7351 || sh_register_operand (operands[1], DFmode))" 7352 "@ 7353 add %1, r63, %0 7354 # 7355 ld%M1.q %m1, %0 7356 st%M0.q %m0, %N1" 7357 [(set_attr "type" "arith_media,*,load_media,store_media")]) 7358 7359(define_split 7360 [(set (match_operand:DF 0 "arith_reg_dest" "") 7361 (match_operand:DF 1 "immediate_operand" ""))] 7362 "TARGET_SHMEDIA && reload_completed" 7363 [(set (match_dup 3) (match_dup 2))] 7364{ 7365 int endian = WORDS_BIG_ENDIAN ? 1 : 0; 7366 long values[2]; 7367 REAL_VALUE_TYPE value; 7368 7369 REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]); 7370 REAL_VALUE_TO_TARGET_DOUBLE (value, values); 7371 7372 if (HOST_BITS_PER_WIDE_INT >= 64) 7373 operands[2] = immed_double_const ((unsigned long) values[endian] 7374 | ((HOST_WIDE_INT) values[1 - endian] 7375 << 32), 0, DImode); 7376 else 7377 { 7378 gcc_assert (HOST_BITS_PER_WIDE_INT == 32); 7379 operands[2] = immed_double_const (values[endian], values[1 - endian], 7380 DImode); 7381 } 7382 7383 operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0])); 7384}) 7385 7386;; FIXME: This should be a define_insn_and_split. 7387(define_insn "movdf_k" 7388 [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m") 7389 (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))] 7390 "TARGET_SH1 7391 && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed 7392 /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */ 7393 || (REG_P (operands[0]) && REGNO (operands[0]) == 3) 7394 || (REG_P (operands[1]) && REGNO (operands[1]) == 3)) 7395 && (arith_reg_operand (operands[0], DFmode) 7396 || arith_reg_operand (operands[1], DFmode))" 7397{ 7398 return output_movedouble (insn, operands, DFmode); 7399} 7400 [(set_attr "length" "4") 7401 (set_attr "type" "move,pcload,load,store")]) 7402 7403;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD. 7404;; However, the d/F/c/z alternative cannot be split directly; it is converted 7405;; with special code in machine_dependent_reorg into a load of the R0_REG and 7406;; the d/m/c/X alternative, which is split later into single-precision 7407;; instructions. And when not optimizing, no splits are done before fixing 7408;; up pcloads, so we need usable length information for that. 7409(define_insn "movdf_i4" 7410 [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d") 7411 (match_operand:DF 1 "general_movsrc_operand" "d,r,F,m,d,FQ,m,r,d,r")) 7412 (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c")) 7413 (clobber (match_scratch:SI 3 "=X,X,&z,X,X,X,X,X,X,X"))] 7414 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) 7415 && (arith_reg_operand (operands[0], DFmode) 7416 || arith_reg_operand (operands[1], DFmode))" 7417 { 7418 switch (which_alternative) 7419 { 7420 case 0: 7421 if (TARGET_FMOVD) 7422 return "fmov %1,%0"; 7423 else if (REGNO (operands[0]) != REGNO (operands[1]) + 1) 7424 return "fmov %R1,%R0" "\n" 7425 " fmov %S1,%S0"; 7426 else 7427 return "fmov %S1,%S0" "\n" 7428 " fmov %R1,%R0"; 7429 case 3: 7430 case 4: 7431 return "fmov.d %1,%0"; 7432 default: 7433 return "#"; 7434 } 7435 } 7436 [(set_attr_alternative "length" 7437 [(if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 8)) 7438 (const_int 4) 7439 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6)) 7440 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6)) 7441 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6)) 7442 (const_int 4) 7443 (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn) 7444 ;; We can't use 4-byte push/pop on SHcompact, so we have to 7445 ;; increment or decrement r15 explicitly. 7446 (if_then_else 7447 (match_test "TARGET_SHCOMPACT") 7448 (const_int 10) (const_int 8)) 7449 (if_then_else 7450 (match_test "TARGET_SHCOMPACT") 7451 (const_int 10) (const_int 8))]) 7452 (set_attr "type" "fmove,move,pcfload,fload,fstore,pcload,load,store,load,fload") 7453 (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*") 7454 (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes") 7455 (const_string "double") 7456 (const_string "none")))]) 7457 7458;; Moving DFmode between fp/general registers through memory 7459;; (the top of the stack) is faster than moving through fpul even for 7460;; little endian. Because the type of an instruction is important for its 7461;; scheduling, it is beneficial to split these operations, rather than 7462;; emitting them in one single chunk, even if this will expose a stack 7463;; use that will prevent scheduling of other stack accesses beyond this 7464;; instruction. 7465(define_split 7466 [(set (match_operand:DF 0 "register_operand" "") 7467 (match_operand:DF 1 "register_operand" "")) 7468 (use (match_operand:PSI 2 "fpscr_operand" "")) 7469 (clobber (match_scratch:SI 3 "=X"))] 7470 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed 7471 && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)" 7472 [(const_int 0)] 7473{ 7474 rtx insn, tos; 7475 7476 if (TARGET_SH5 && true_regnum (operands[1]) < 16) 7477 { 7478 emit_move_insn (stack_pointer_rtx, 7479 plus_constant (Pmode, stack_pointer_rtx, -8)); 7480 tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx); 7481 } 7482 else 7483 tos = gen_tmp_stack_mem (DFmode, 7484 gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx)); 7485 insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2])); 7486 if (! (TARGET_SH5 && true_regnum (operands[1]) < 16)) 7487 add_reg_note (insn, REG_INC, stack_pointer_rtx); 7488 if (TARGET_SH5 && true_regnum (operands[0]) < 16) 7489 tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx); 7490 else 7491 tos = gen_tmp_stack_mem (DFmode, 7492 gen_rtx_POST_INC (Pmode, stack_pointer_rtx)); 7493 insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2])); 7494 if (TARGET_SH5 && true_regnum (operands[0]) < 16) 7495 emit_move_insn (stack_pointer_rtx, 7496 plus_constant (Pmode, stack_pointer_rtx, 8)); 7497 else 7498 add_reg_note (insn, REG_INC, stack_pointer_rtx); 7499 DONE; 7500}) 7501 7502;; local-alloc sometimes allocates scratch registers even when not required, 7503;; so we must be prepared to handle these. 7504 7505;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k. 7506(define_split 7507 [(set (match_operand:DF 0 "general_movdst_operand" "") 7508 (match_operand:DF 1 "general_movsrc_operand" "")) 7509 (use (match_operand:PSI 2 "fpscr_operand" "")) 7510 (clobber (match_scratch:SI 3 ""))] 7511 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) 7512 && reload_completed 7513 && true_regnum (operands[0]) < 16 7514 && true_regnum (operands[1]) < 16" 7515 [(set (match_dup 0) (match_dup 1))] 7516{ 7517 /* If this was a reg <-> mem operation with base + index reg addressing, 7518 we have to handle this in a special way. */ 7519 rtx mem = operands[0]; 7520 int store_p = 1; 7521 if (! memory_operand (mem, DFmode)) 7522 { 7523 mem = operands[1]; 7524 store_p = 0; 7525 } 7526 if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0) 7527 mem = SUBREG_REG (mem); 7528 if (MEM_P (mem)) 7529 { 7530 rtx addr = XEXP (mem, 0); 7531 if (GET_CODE (addr) == PLUS 7532 && REG_P (XEXP (addr, 0)) 7533 && REG_P (XEXP (addr, 1))) 7534 { 7535 int offset; 7536 rtx reg0 = gen_rtx_REG (Pmode, 0); 7537 rtx regop = operands[store_p], word0 ,word1; 7538 7539 if (GET_CODE (regop) == SUBREG) 7540 alter_subreg (®op, true); 7541 if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1))) 7542 offset = 2; 7543 else 7544 offset = 4; 7545 mem = copy_rtx (mem); 7546 PUT_MODE (mem, SImode); 7547 word0 = gen_rtx_SUBREG (SImode, regop, 0); 7548 alter_subreg (&word0, true); 7549 word1 = gen_rtx_SUBREG (SImode, regop, 4); 7550 alter_subreg (&word1, true); 7551 if (store_p || ! refers_to_regno_p (REGNO (word0), 7552 REGNO (word0) + 1, addr, 0)) 7553 { 7554 emit_insn (store_p 7555 ? gen_movsi_ie (mem, word0) 7556 : gen_movsi_ie (word0, mem)); 7557 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset))); 7558 mem = copy_rtx (mem); 7559 emit_insn (store_p 7560 ? gen_movsi_ie (mem, word1) 7561 : gen_movsi_ie (word1, mem)); 7562 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset))); 7563 } 7564 else 7565 { 7566 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset))); 7567 emit_insn (gen_movsi_ie (word1, mem)); 7568 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset))); 7569 mem = copy_rtx (mem); 7570 emit_insn (gen_movsi_ie (word0, mem)); 7571 } 7572 DONE; 7573 } 7574 } 7575}) 7576 7577;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads. 7578(define_split 7579 [(set (match_operand:DF 0 "register_operand" "") 7580 (match_operand:DF 1 "memory_operand" "")) 7581 (use (match_operand:PSI 2 "fpscr_operand" "")) 7582 (clobber (reg:SI R0_REG))] 7583 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed" 7584 [(parallel [(set (match_dup 0) (match_dup 1)) 7585 (use (match_dup 2)) 7586 (clobber (scratch:SI))])] 7587 "") 7588 7589(define_expand "reload_indf__frn" 7590 [(parallel [(set (match_operand:DF 0 "register_operand" "=a") 7591 (match_operand:DF 1 "immediate_operand" "FQ")) 7592 (use (reg:PSI FPSCR_REG)) 7593 (clobber (match_operand:SI 2 "register_operand" "=&z"))])] 7594 "TARGET_SH1" 7595 "") 7596 7597(define_expand "reload_outdf__RnFRm" 7598 [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f") 7599 (match_operand:DF 1 "register_operand" "af,r")) 7600 (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])] 7601 "TARGET_SH1" 7602 "") 7603 7604;; Simplify no-op moves. 7605(define_split 7606 [(set (match_operand:SF 0 "register_operand" "") 7607 (match_operand:SF 1 "register_operand" "")) 7608 (use (match_operand:PSI 2 "fpscr_operand" "")) 7609 (clobber (match_scratch:SI 3 ""))] 7610 "TARGET_SH2E && reload_completed 7611 && true_regnum (operands[0]) == true_regnum (operands[1])" 7612 [(set (match_dup 0) (match_dup 0))] 7613 "") 7614 7615;; fmovd substitute post-reload splits 7616(define_split 7617 [(set (match_operand:DF 0 "register_operand" "") 7618 (match_operand:DF 1 "register_operand" "")) 7619 (use (match_operand:PSI 2 "fpscr_operand" "")) 7620 (clobber (match_scratch:SI 3 ""))] 7621 "TARGET_SH4 && ! TARGET_FMOVD && reload_completed 7622 && FP_OR_XD_REGISTER_P (true_regnum (operands[0])) 7623 && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))" 7624 [(const_int 0)] 7625{ 7626 int dst = true_regnum (operands[0]), src = true_regnum (operands[1]); 7627 emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst), 7628 gen_rtx_REG (SFmode, src), operands[2])); 7629 emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1), 7630 gen_rtx_REG (SFmode, src + 1), operands[2])); 7631 DONE; 7632}) 7633 7634(define_split 7635 [(set (match_operand:DF 0 "register_operand" "") 7636 (mem:DF (match_operand:SI 1 "register_operand" ""))) 7637 (use (match_operand:PSI 2 "fpscr_operand" "")) 7638 (clobber (match_scratch:SI 3 ""))] 7639 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed 7640 && FP_OR_XD_REGISTER_P (true_regnum (operands[0])) 7641 && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))" 7642 [(const_int 0)] 7643{ 7644 int regno = true_regnum (operands[0]); 7645 rtx insn; 7646 rtx mem = SET_SRC (XVECEXP (PATTERN (curr_insn), 0, 0)); 7647 rtx mem2 7648 = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1])); 7649 insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, 7650 regno + !! TARGET_LITTLE_ENDIAN), 7651 mem2, operands[2])); 7652 add_reg_note (insn, REG_INC, operands[1]); 7653 insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, 7654 regno + ! TARGET_LITTLE_ENDIAN), 7655 change_address (mem, SFmode, NULL_RTX), 7656 operands[2])); 7657 DONE; 7658}) 7659 7660(define_split 7661 [(set (match_operand:DF 0 "register_operand" "") 7662 (match_operand:DF 1 "memory_operand" "")) 7663 (use (match_operand:PSI 2 "fpscr_operand" "")) 7664 (clobber (match_scratch:SI 3 ""))] 7665 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed 7666 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))" 7667 [(const_int 0)] 7668{ 7669 int regno = true_regnum (operands[0]); 7670 rtx addr, insn; 7671 rtx mem2 = change_address (operands[1], SFmode, NULL_RTX); 7672 rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0)); 7673 rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1)); 7674 7675 operands[1] = copy_rtx (mem2); 7676 addr = XEXP (mem2, 0); 7677 7678 switch (GET_CODE (addr)) 7679 { 7680 case REG: 7681 /* This is complicated. If the register is an arithmetic register 7682 we can just fall through to the REG+DISP case below. Otherwise 7683 we have to use a combination of POST_INC and REG addressing... */ 7684 if (! arith_reg_operand (operands[1], SFmode)) 7685 { 7686 XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr); 7687 insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2])); 7688 add_reg_note (insn, REG_INC, XEXP (addr, 0)); 7689 7690 emit_insn (gen_movsf_ie (reg1, operands[1], operands[2])); 7691 7692 /* If we have modified the stack pointer, the value that we have 7693 read with post-increment might be modified by an interrupt, 7694 so write it back. */ 7695 if (REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM) 7696 emit_insn (gen_push_e (reg0)); 7697 else 7698 emit_insn (gen_addsi3 (XEXP (operands[1], 0), XEXP (operands[1], 0), 7699 GEN_INT (-4))); 7700 break; 7701 } 7702 /* Fall through. */ 7703 7704 case PLUS: 7705 emit_insn (gen_movsf_ie (reg0, operands[1], operands[2])); 7706 operands[1] = copy_rtx (operands[1]); 7707 XEXP (operands[1], 0) = plus_constant (Pmode, addr, 4); 7708 emit_insn (gen_movsf_ie (reg1, operands[1], operands[2])); 7709 break; 7710 7711 case POST_INC: 7712 insn = emit_insn (gen_movsf_ie (reg0, operands[1], operands[2])); 7713 add_reg_note (insn, REG_INC, XEXP (addr, 0)); 7714 7715 insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2])); 7716 add_reg_note (insn, REG_INC, XEXP (addr, 0)); 7717 break; 7718 7719 default: 7720 debug_rtx (addr); 7721 gcc_unreachable (); 7722 } 7723 7724 DONE; 7725}) 7726 7727(define_split 7728 [(set (match_operand:DF 0 "memory_operand" "") 7729 (match_operand:DF 1 "register_operand" "")) 7730 (use (match_operand:PSI 2 "fpscr_operand" "")) 7731 (clobber (match_scratch:SI 3 ""))] 7732 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed 7733 && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))" 7734 [(const_int 0)] 7735{ 7736 int regno = true_regnum (operands[1]); 7737 rtx insn, addr; 7738 rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0)); 7739 rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1)); 7740 7741 operands[0] = copy_rtx (operands[0]); 7742 PUT_MODE (operands[0], SFmode); 7743 addr = XEXP (operands[0], 0); 7744 7745 switch (GET_CODE (addr)) 7746 { 7747 case REG: 7748 /* This is complicated. If the register is an arithmetic register 7749 we can just fall through to the REG+DISP case below. Otherwise 7750 we have to use a combination of REG and PRE_DEC addressing... */ 7751 if (! arith_reg_operand (operands[0], SFmode)) 7752 { 7753 emit_insn (gen_addsi3 (addr, addr, GEN_INT (4))); 7754 emit_insn (gen_movsf_ie (operands[0], reg1, operands[2])); 7755 7756 operands[0] = copy_rtx (operands[0]); 7757 XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr); 7758 7759 insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2])); 7760 add_reg_note (insn, REG_INC, XEXP (addr, 0)); 7761 break; 7762 } 7763 /* Fall through. */ 7764 7765 case PLUS: 7766 /* Since REG+DISP addressing has already been decided upon by gcc 7767 we can rely upon it having chosen an arithmetic register as the 7768 register component of the address. Just emit the lower numbered 7769 register first, to the lower address, then the higher numbered 7770 register to the higher address. */ 7771 emit_insn (gen_movsf_ie (operands[0], reg0, operands[2])); 7772 7773 operands[0] = copy_rtx (operands[0]); 7774 XEXP (operands[0], 0) = plus_constant (Pmode, addr, 4); 7775 7776 emit_insn (gen_movsf_ie (operands[0], reg1, operands[2])); 7777 break; 7778 7779 case PRE_DEC: 7780 /* This is easy. Output the word to go to the higher address 7781 first (ie the word in the higher numbered register) then the 7782 word to go to the lower address. */ 7783 7784 insn = emit_insn (gen_movsf_ie (operands[0], reg1, operands[2])); 7785 add_reg_note (insn, REG_INC, XEXP (addr, 0)); 7786 7787 insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2])); 7788 add_reg_note (insn, REG_INC, XEXP (addr, 0)); 7789 break; 7790 7791 default: 7792 /* FAIL; */ 7793 debug_rtx (addr); 7794 gcc_unreachable (); 7795 } 7796 7797 DONE; 7798}) 7799 7800;; If the output is a register and the input is memory or a register, we have 7801;; to be careful and see which word needs to be loaded first. 7802(define_split 7803 [(set (match_operand:DF 0 "general_movdst_operand" "") 7804 (match_operand:DF 1 "general_movsrc_operand" ""))] 7805 "TARGET_SH1 && reload_completed" 7806 [(set (match_dup 2) (match_dup 3)) 7807 (set (match_dup 4) (match_dup 5))] 7808{ 7809 int regno; 7810 7811 if ((MEM_P (operands[0]) 7812 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) 7813 || (MEM_P (operands[1]) 7814 && GET_CODE (XEXP (operands[1], 0)) == POST_INC)) 7815 FAIL; 7816 7817 switch (GET_CODE (operands[0])) 7818 { 7819 case REG: 7820 regno = REGNO (operands[0]); 7821 break; 7822 case SUBREG: 7823 regno = subreg_regno (operands[0]); 7824 break; 7825 case MEM: 7826 regno = -1; 7827 break; 7828 default: 7829 gcc_unreachable (); 7830 } 7831 7832 if (regno == -1 7833 || ! refers_to_regno_p (regno, regno + 1, operands[1], 0)) 7834 { 7835 operands[2] = operand_subword (operands[0], 0, 0, DFmode); 7836 operands[3] = operand_subword (operands[1], 0, 0, DFmode); 7837 operands[4] = operand_subword (operands[0], 1, 0, DFmode); 7838 operands[5] = operand_subword (operands[1], 1, 0, DFmode); 7839 } 7840 else 7841 { 7842 operands[2] = operand_subword (operands[0], 1, 0, DFmode); 7843 operands[3] = operand_subword (operands[1], 1, 0, DFmode); 7844 operands[4] = operand_subword (operands[0], 0, 0, DFmode); 7845 operands[5] = operand_subword (operands[1], 0, 0, DFmode); 7846 } 7847 7848 if (operands[2] == 0 || operands[3] == 0 7849 || operands[4] == 0 || operands[5] == 0) 7850 FAIL; 7851}) 7852 7853(define_expand "movdf" 7854 [(set (match_operand:DF 0 "general_movdst_operand" "") 7855 (match_operand:DF 1 "general_movsrc_operand" ""))] 7856 "" 7857{ 7858 prepare_move_operands (operands, DFmode); 7859 if (TARGET_SHMEDIA) 7860 { 7861 if (TARGET_SHMEDIA_FPU) 7862 emit_insn (gen_movdf_media (operands[0], operands[1])); 7863 else 7864 emit_insn (gen_movdf_media_nofpu (operands[0], operands[1])); 7865 DONE; 7866 } 7867 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 7868 { 7869 emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ())); 7870 DONE; 7871 } 7872}) 7873 7874;;This is incompatible with the way gcc uses subregs. 7875;;(define_insn "movv2sf_i" 7876;; [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m") 7877;; (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))] 7878;; "TARGET_SHMEDIA_FPU 7879;; && (fp_arith_reg_operand (operands[0], V2SFmode) 7880;; || fp_arith_reg_operand (operands[1], V2SFmode))" 7881;; "@ 7882;; # 7883;; fld%M1.p %m1, %0 7884;; fst%M0.p %m0, %1" 7885;; [(set_attr "type" "*,fload_media,fstore_media")]) 7886(define_insn_and_split "movv2sf_i" 7887 [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf") 7888 (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))] 7889 "TARGET_SHMEDIA_FPU" 7890 "#" 7891 "TARGET_SHMEDIA_FPU && reload_completed" 7892 [(set (match_dup 0) (match_dup 1))] 7893{ 7894 operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0); 7895 operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0); 7896}) 7897 7898(define_expand "movv2sf" 7899 [(set (match_operand:V2SF 0 "general_movdst_operand" "") 7900 (match_operand:V2SF 1 "nonimmediate_operand" ""))] 7901 "TARGET_SHMEDIA_FPU" 7902{ 7903 prepare_move_operands (operands, V2SFmode); 7904}) 7905 7906(define_expand "addv2sf3" 7907 [(match_operand:V2SF 0 "fp_arith_reg_operand" "") 7908 (match_operand:V2SF 1 "fp_arith_reg_operand" "") 7909 (match_operand:V2SF 2 "fp_arith_reg_operand" "")] 7910 "TARGET_SHMEDIA_FPU" 7911{ 7912 sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]); 7913 DONE; 7914}) 7915 7916(define_expand "subv2sf3" 7917 [(match_operand:V2SF 0 "fp_arith_reg_operand" "") 7918 (match_operand:V2SF 1 "fp_arith_reg_operand" "") 7919 (match_operand:V2SF 2 "fp_arith_reg_operand" "")] 7920 "TARGET_SHMEDIA_FPU" 7921{ 7922 sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]); 7923 DONE; 7924}) 7925 7926(define_expand "mulv2sf3" 7927 [(match_operand:V2SF 0 "fp_arith_reg_operand" "") 7928 (match_operand:V2SF 1 "fp_arith_reg_operand" "") 7929 (match_operand:V2SF 2 "fp_arith_reg_operand" "")] 7930 "TARGET_SHMEDIA_FPU" 7931{ 7932 sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]); 7933 DONE; 7934}) 7935 7936(define_expand "divv2sf3" 7937 [(match_operand:V2SF 0 "fp_arith_reg_operand" "") 7938 (match_operand:V2SF 1 "fp_arith_reg_operand" "") 7939 (match_operand:V2SF 2 "fp_arith_reg_operand" "")] 7940 "TARGET_SHMEDIA_FPU" 7941{ 7942 sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]); 7943 DONE; 7944}) 7945 7946(define_insn_and_split "*movv4sf_i" 7947 [(set (match_operand:V4SF 0 "general_movdst_operand" "=f,rf,r,m,mf") 7948 (match_operand:V4SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))] 7949 "TARGET_SHMEDIA_FPU" 7950 "#" 7951 "&& reload_completed" 7952 [(const_int 0)] 7953{ 7954 for (int i = 0; i < 4/2; i++) 7955 { 7956 rtx x, y; 7957 7958 if (MEM_P (operands[0])) 7959 x = adjust_address (operands[0], V2SFmode, 7960 i * GET_MODE_SIZE (V2SFmode)); 7961 else 7962 x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8); 7963 7964 if (MEM_P (operands[1])) 7965 y = adjust_address (operands[1], V2SFmode, 7966 i * GET_MODE_SIZE (V2SFmode)); 7967 else 7968 y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8); 7969 7970 emit_insn (gen_movv2sf_i (x, y)); 7971 } 7972 7973 DONE; 7974} 7975 [(set_attr "length" "8")]) 7976 7977(define_expand "movv4sf" 7978 [(set (match_operand:V4SF 0 "nonimmediate_operand" "") 7979 (match_operand:V4SF 1 "general_operand" ""))] 7980 "TARGET_SHMEDIA_FPU" 7981{ 7982 prepare_move_operands (operands, V4SFmode); 7983}) 7984 7985(define_insn_and_split "*movv16sf_i" 7986 [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m") 7987 (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))] 7988 "TARGET_SHMEDIA_FPU" 7989 "#" 7990 "&& reload_completed" 7991 [(const_int 0)] 7992{ 7993 for (int i = 0; i < 16/2; i++) 7994 { 7995 rtx x, y; 7996 7997 if (MEM_P (operands[0])) 7998 x = adjust_address (operands[0], V2SFmode, 7999 i * GET_MODE_SIZE (V2SFmode)); 8000 else 8001 { 8002 x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8); 8003 alter_subreg (&x, true); 8004 } 8005 8006 if (MEM_P (operands[1])) 8007 y = adjust_address (operands[1], V2SFmode, 8008 i * GET_MODE_SIZE (V2SFmode)); 8009 else 8010 { 8011 y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8); 8012 alter_subreg (&y, true); 8013 } 8014 8015 emit_insn (gen_movv2sf_i (x, y)); 8016 } 8017 8018 DONE; 8019} 8020 [(set_attr "length" "32")]) 8021 8022(define_expand "movv16sf" 8023 [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m") 8024 (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))] 8025 "TARGET_SHMEDIA_FPU" 8026{ 8027 prepare_move_operands (operands, V16SFmode); 8028}) 8029 8030(define_insn "movsf_media" 8031 [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m") 8032 (match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))] 8033 "TARGET_SHMEDIA_FPU 8034 && (register_operand (operands[0], SFmode) 8035 || sh_register_operand (operands[1], SFmode))" 8036 "@ 8037 fmov.s %1, %0 8038 fmov.ls %N1, %0 8039 fmov.sl %1, %0 8040 add.l %1, r63, %0 8041 # 8042 fld%M1.s %m1, %0 8043 fst%M0.s %m0, %1 8044 ld%M1.l %m1, %0 8045 st%M0.l %m0, %N1" 8046 [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media") 8047 (set (attr "highpart") 8048 (cond [(match_test "sh_contains_memref_p (insn)") 8049 (const_string "user")] 8050 (const_string "ignore")))]) 8051 8052(define_insn "movsf_media_nofpu" 8053 [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m") 8054 (match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))] 8055 "TARGET_SHMEDIA 8056 && (register_operand (operands[0], SFmode) 8057 || sh_register_operand (operands[1], SFmode))" 8058 "@ 8059 add.l %1, r63, %0 8060 # 8061 ld%M1.l %m1, %0 8062 st%M0.l %m0, %N1" 8063 [(set_attr "type" "arith_media,*,load_media,store_media") 8064 (set (attr "highpart") 8065 (cond [(match_test "sh_contains_memref_p (insn)") 8066 (const_string "user")] 8067 (const_string "ignore")))]) 8068 8069(define_split 8070 [(set (match_operand:SF 0 "arith_reg_dest" "") 8071 (match_operand:SF 1 "immediate_operand" ""))] 8072 "TARGET_SHMEDIA && reload_completed 8073 && ! FP_REGISTER_P (true_regnum (operands[0]))" 8074 [(set (match_dup 3) (match_dup 2))] 8075{ 8076 long values; 8077 REAL_VALUE_TYPE value; 8078 8079 REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]); 8080 REAL_VALUE_TO_TARGET_SINGLE (value, values); 8081 operands[2] = GEN_INT (values); 8082 8083 operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0])); 8084}) 8085 8086(define_insn "movsf_i" 8087 [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r") 8088 (match_operand:SF 1 "general_movsrc_operand" "r,G,FQ,mr,r,r,l"))] 8089 "TARGET_SH1 8090 && (! TARGET_SH2E 8091 /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */ 8092 || (REG_P (operands[0]) && REGNO (operands[0]) == 3) 8093 || (REG_P (operands[1]) && REGNO (operands[1]) == 3)) 8094 && (arith_reg_operand (operands[0], SFmode) 8095 || arith_reg_operand (operands[1], SFmode))" 8096 "@ 8097 mov %1,%0 8098 mov #0,%0 8099 mov.l %1,%0 8100 mov.l %1,%0 8101 mov.l %1,%0 8102 lds %1,%0 8103 sts %1,%0" 8104 [(set_attr "type" "move,move,pcload,load,store,move,move")]) 8105 8106;; We may not split the ry/yr/XX alternatives to movsi_ie, since 8107;; update_flow_info would not know where to put REG_EQUAL notes 8108;; when the destination changes mode. 8109(define_insn "movsf_ie" 8110 [(set (match_operand:SF 0 "general_movdst_operand" 8111 "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y") 8112 (match_operand:SF 1 "general_movsrc_operand" 8113 "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y")) 8114 (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c")) 8115 (clobber (match_scratch:SI 3 "=X,X,Bsc,Bsc,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))] 8116 "TARGET_SH2E 8117 && (arith_reg_operand (operands[0], SFmode) 8118 || arith_reg_operand (operands[1], SFmode) 8119 || arith_reg_operand (operands[3], SImode) 8120 || (fpul_operand (operands[0], SFmode) 8121 && memory_operand (operands[1], SFmode) 8122 && GET_CODE (XEXP (operands[1], 0)) == POST_INC) 8123 || (fpul_operand (operands[1], SFmode) 8124 && memory_operand (operands[0], SFmode) 8125 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))" 8126 "@ 8127 fmov %1,%0 8128 mov %1,%0 8129 fldi0 %0 8130 fldi1 %0 8131 # 8132 fmov.s %1,%0 8133 fmov.s %1,%0 8134 mov.l %1,%0 8135 mov.l %1,%0 8136 mov.l %1,%0 8137 fsts fpul,%0 8138 flds %1,fpul 8139 lds.l %1,%0 8140 # 8141 sts %1,%0 8142 lds %1,%0 8143 sts.l %1,%0 8144 lds.l %1,%0 8145 ! move optimized away" 8146 [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load, 8147 store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil") 8148 (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*") 8149 (set_attr_alternative "length" 8150 [(const_int 2) 8151 (const_int 2) 8152 (const_int 2) 8153 (const_int 2) 8154 (const_int 4) 8155 (if_then_else 8156 (match_test "TARGET_SH2A") 8157 (const_int 4) (const_int 2)) 8158 (if_then_else 8159 (match_test "TARGET_SH2A") 8160 (const_int 4) (const_int 2)) 8161 (const_int 2) 8162 (if_then_else 8163 (match_test "TARGET_SH2A") 8164 (const_int 4) (const_int 2)) 8165 (if_then_else 8166 (match_test "TARGET_SH2A") 8167 (const_int 4) (const_int 2)) 8168 (const_int 2) 8169 (const_int 2) 8170 (const_int 2) 8171 (const_int 4) 8172 (const_int 2) 8173 (const_int 2) 8174 (const_int 2) 8175 (const_int 2) 8176 (const_int 0)]) 8177 (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes") 8178 (const_string "single") 8179 (const_string "single")))]) 8180 8181(define_split 8182 [(set (match_operand:SF 0 "register_operand" "") 8183 (match_operand:SF 1 "register_operand" "")) 8184 (use (match_operand:PSI 2 "fpscr_operand" "")) 8185 (clobber (reg:SI FPUL_REG))] 8186 "TARGET_SH1" 8187 [(parallel [(set (reg:SF FPUL_REG) (match_dup 1)) 8188 (use (match_dup 2)) 8189 (clobber (scratch:SI))]) 8190 (parallel [(set (match_dup 0) (reg:SF FPUL_REG)) 8191 (use (match_dup 2)) 8192 (clobber (scratch:SI))])] 8193 "") 8194 8195(define_expand "movsf" 8196 [(set (match_operand:SF 0 "general_movdst_operand" "") 8197 (match_operand:SF 1 "general_movsrc_operand" ""))] 8198 "" 8199{ 8200 prepare_move_operands (operands, SFmode); 8201 if (TARGET_SHMEDIA) 8202 { 8203 if (TARGET_SHMEDIA_FPU) 8204 emit_insn (gen_movsf_media (operands[0], operands[1])); 8205 else 8206 emit_insn (gen_movsf_media_nofpu (operands[0], operands[1])); 8207 DONE; 8208 } 8209 if (TARGET_SH2E) 8210 { 8211 emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ())); 8212 DONE; 8213 } 8214}) 8215 8216(define_insn "mov_nop" 8217 [(set (match_operand 0 "any_register_operand" "") (match_dup 0))] 8218 "TARGET_SH2E" 8219 "" 8220 [(set_attr "length" "0") 8221 (set_attr "type" "nil")]) 8222 8223(define_expand "reload_insf__frn" 8224 [(parallel [(set (match_operand:SF 0 "register_operand" "=a") 8225 (match_operand:SF 1 "immediate_operand" "FQ")) 8226 (use (reg:PSI FPSCR_REG)) 8227 (clobber (match_operand:SI 2 "register_operand" "=&z"))])] 8228 "TARGET_SH1" 8229 "") 8230 8231(define_expand "reload_insi__i_fpul" 8232 [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y") 8233 (match_operand:SI 1 "immediate_operand" "i")) 8234 (clobber (match_operand:SI 2 "register_operand" "=&z"))])] 8235 "TARGET_SH1" 8236 "") 8237 8238(define_expand "ptabs" 8239 [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))] 8240 "TARGET_SHMEDIA" 8241{ 8242 if (!TARGET_PT_FIXED) 8243 { 8244 rtx eq = operands[1]; 8245 8246 /* ??? For canonical RTL we really should remove any CONST from EQ 8247 before wrapping it in the AND, and finally wrap the EQ into a 8248 const if is constant. However, for reload we must expose the 8249 input register or symbolic constant, and we can't have 8250 different insn structures outside of the operands for different 8251 alternatives of the same pattern. */ 8252 eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)), 8253 GEN_INT (3)); 8254 operands[1] 8255 = (gen_rtx_IF_THEN_ELSE 8256 (PDImode, 8257 eq, 8258 gen_rtx_MEM (PDImode, operands[1]), 8259 gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE, 8260 PDImode, operands[1]))); 8261 } 8262}) 8263 8264;; expanded by ptabs expander. 8265(define_insn "*extendsipdi_media" 8266 [(set (match_operand:PDI 0 "target_reg_operand" "=b,b"); 8267 (if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand" 8268 "r,Csy") 8269 (const_int 3)) 8270 (const_int 3)) 8271 (mem:PDI (match_dup 1)) 8272 (sign_extend:PDI (match_dup 1))))] 8273 "TARGET_SHMEDIA && !TARGET_PT_FIXED" 8274 "@ 8275 ptabs %1, %0 8276 pt %1, %0" 8277 [(set_attr "type" "ptabs_media,pt_media") 8278 (set_attr "length" "4,*")]) 8279 8280(define_insn "*truncdipdi_media" 8281 [(set (match_operand:PDI 0 "target_reg_operand" "=b,b"); 8282 (if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand" 8283 "r,Csy") 8284 (const_int 3)) 8285 (const_int 3)) 8286 (mem:PDI (match_dup 1)) 8287 (truncate:PDI (match_dup 1))))] 8288 "TARGET_SHMEDIA && !TARGET_PT_FIXED" 8289 "@ 8290 ptabs %1, %0 8291 pt %1, %0" 8292 [(set_attr "type" "ptabs_media,pt_media") 8293 (set_attr "length" "4,*")]) 8294 8295(define_insn "*movsi_y" 8296 [(set (match_operand:SI 0 "register_operand" "=y,y") 8297 (match_operand:SI 1 "immediate_operand" "Qi,I08")) 8298 (clobber (match_scratch:SI 2 "=&z,r"))] 8299 "TARGET_SH2E 8300 && (reload_in_progress || reload_completed)" 8301 "#" 8302 [(set_attr "length" "4") 8303 (set_attr "type" "pcload,move")]) 8304 8305(define_split 8306 [(set (match_operand:SI 0 "register_operand" "") 8307 (match_operand:SI 1 "immediate_operand" "")) 8308 (clobber (match_operand:SI 2 "register_operand" ""))] 8309 "TARGET_SH1" 8310 [(set (match_dup 2) (match_dup 1)) 8311 (set (match_dup 0) (match_dup 2))] 8312 "") 8313 8314;; ------------------------------------------------------------------------ 8315;; Define the real conditional branch instructions. 8316;; ------------------------------------------------------------------------ 8317 8318(define_expand "branch_true" 8319 [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0)) 8320 (label_ref (match_operand 0)) 8321 (pc)))] 8322 "TARGET_SH1") 8323 8324(define_expand "branch_false" 8325 [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 8326 (label_ref (match_operand 0)) 8327 (pc)))] 8328 "TARGET_SH1") 8329 8330(define_insn_and_split "*cbranch_t" 8331 [(set (pc) (if_then_else (match_operand 1 "cbranch_treg_value") 8332 (label_ref (match_operand 0)) 8333 (pc)))] 8334 "TARGET_SH1" 8335{ 8336 return output_branch (sh_eval_treg_value (operands[1]), insn, operands); 8337} 8338 "&& 1" 8339 [(set (pc) (if_then_else (eq (reg:SI T_REG) (match_dup 2)) 8340 (label_ref (match_dup 0)) 8341 (pc)))] 8342{ 8343 /* Try to find missed test and branch combine opportunities which result 8344 in redundant T bit tests before conditional branches. 8345 This is done not only after combine (and before reload) but in every 8346 split pass, because some opportunities are formed also after combine. 8347 FIXME: Probably this would not be needed if CCmode was used 8348 together with TARGET_FIXED_CONDITION_CODE_REGS. */ 8349 8350 const int treg_value = sh_eval_treg_value (operands[1]); 8351 operands[2] = NULL_RTX; 8352 8353 /* Scan the insns backwards for an insn that sets the T bit by testing a 8354 reg against zero like: 8355 (set (reg T_REG) (eq (reg) (const_int 0))) */ 8356 rtx testing_insn = NULL_RTX; 8357 rtx tested_reg = NULL_RTX; 8358 8359 set_of_reg s0 = sh_find_set_of_reg (get_t_reg_rtx (), curr_insn, 8360 prev_nonnote_insn_bb); 8361 if (s0.set_src != NULL_RTX 8362 && GET_CODE (s0.set_src) == EQ 8363 && REG_P (XEXP (s0.set_src, 0)) 8364 && satisfies_constraint_Z (XEXP (s0.set_src, 1))) 8365 { 8366 testing_insn = s0.insn; 8367 tested_reg = XEXP (s0.set_src, 0); 8368 } 8369 else 8370 FAIL; 8371 8372 /* Continue scanning the insns backwards and try to find the insn that 8373 sets the tested reg which we found above. If the reg is set by storing 8374 the T bit or the negated T bit we can eliminate the test insn before 8375 the branch. Notice that the branch condition has to be inverted if the 8376 test is eliminated. */ 8377 8378 /* If the T bit is used between the testing insn and the brach insn 8379 leave it alone. */ 8380 if (reg_used_between_p (get_t_reg_rtx (), testing_insn, curr_insn)) 8381 FAIL; 8382 8383 while (true) 8384 { 8385 set_of_reg s1 = sh_find_set_of_reg (tested_reg, s0.insn, 8386 prev_nonnote_insn); 8387 8388 if (s1.set_src == NULL_RTX) 8389 break; 8390 8391 if (t_reg_operand (s1.set_src, VOIDmode)) 8392 operands[2] = GEN_INT (treg_value ^ 1); 8393 else if (negt_reg_operand (s1.set_src, VOIDmode)) 8394 operands[2] = GEN_INT (treg_value); 8395 else if (REG_P (s1.set_src)) 8396 { 8397 /* If it's a reg-reg copy follow the copied reg. This can 8398 happen e.g. when T bit store zero-extensions are 8399 eliminated. */ 8400 tested_reg = s1.set_src; 8401 s0.insn = s1.insn; 8402 continue; 8403 } 8404 8405 /* It's only safe to remove the testing insn if the T bit is not 8406 modified between the testing insn and the insn that stores the 8407 T bit. Notice that some T bit stores such as negc also modify 8408 the T bit. */ 8409 if (modified_between_p (get_t_reg_rtx (), s1.insn, testing_insn) 8410 || modified_in_p (get_t_reg_rtx (), s1.insn) 8411 || !no_labels_between_p (s1.insn, testing_insn)) 8412 operands[2] = NULL_RTX; 8413 else 8414 { 8415 /* If the insn that sets the tested reg has a REG_DEAD note on 8416 the T bit remove that note since we're extending the usage 8417 of the T bit. */ 8418 rtx n = find_regno_note (s1.insn, REG_DEAD, T_REG); 8419 if (n != NULL_RTX) 8420 remove_note (s1.insn, n); 8421 } 8422 8423 break; 8424 } 8425 8426 if (operands[2] == NULL_RTX) 8427 FAIL; 8428 8429 set_insn_deleted (testing_insn); 8430} 8431 [(set_attr "type" "cbranch")]) 8432 8433;; Patterns to prevent reorg from re-combining a condbranch with a branch 8434;; which destination is too far away. 8435;; The const_int_operand is distinct for each branch target; it avoids 8436;; unwanted matches with redundant_insn. 8437(define_insn "block_branch_redirect" 8438 [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))] 8439 "TARGET_SH1" 8440 "" 8441 [(set_attr "length" "0")]) 8442 8443;; This one has the additional purpose to record a possible scratch register 8444;; for the following branch. 8445;; ??? Unfortunately, just setting the scratch register is not good enough, 8446;; because the insn then might be deemed dead and deleted. And we can't 8447;; make the use in the jump insn explicit because that would disable 8448;; delay slot scheduling from the target. 8449(define_insn "indirect_jump_scratch" 8450 [(set (match_operand:SI 0 "register_operand" "=r") 8451 (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR)) 8452 (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))] 8453 "TARGET_SH1" 8454 "" 8455 [(set_attr "length" "0")]) 8456 8457;; This one is used to preemt an insn from beyond the bra / braf / jmp 8458;; being pulled into the delay slot of a condbranch that has been made to 8459;; jump around the unconditional jump because it was out of range. 8460(define_insn "stuff_delay_slot" 8461 [(set (pc) 8462 (unspec [(match_operand:SI 0 "const_int_operand" "") (pc) 8463 (match_operand:SI 1 "const_int_operand" "")] UNSPEC_BBR))] 8464 "TARGET_SH1" 8465 "" 8466 [(set_attr "length" "0") 8467 (set_attr "cond_delay_slot" "yes")]) 8468 8469;; Conditional branch insns 8470 8471(define_expand "cbranchint4_media" 8472 [(set (pc) 8473 (if_then_else (match_operator 0 "shmedia_cbranch_comparison_operator" 8474 [(match_operand 1 "" "") 8475 (match_operand 2 "" "")]) 8476 (match_operand 3 "" "") 8477 (pc)))] 8478 "TARGET_SHMEDIA" 8479{ 8480 enum machine_mode mode = GET_MODE (operands[1]); 8481 if (mode == VOIDmode) 8482 mode = GET_MODE (operands[2]); 8483 if (GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE) 8484 { 8485 operands[1] = force_reg (mode, operands[1]); 8486 if (CONSTANT_P (operands[2]) 8487 && (! satisfies_constraint_I06 (operands[2]))) 8488 operands[2] = force_reg (mode, operands[2]); 8489 } 8490 else 8491 { 8492 if (operands[1] != const0_rtx) 8493 operands[1] = force_reg (mode, operands[1]); 8494 if (operands[2] != const0_rtx) 8495 operands[2] = force_reg (mode, operands[2]); 8496 } 8497 switch (GET_CODE (operands[0])) 8498 { 8499 case LEU: 8500 case LE: 8501 case LTU: 8502 case LT: 8503 operands[0] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[0])), 8504 VOIDmode, operands[2], operands[1]); 8505 operands[1] = XEXP (operands[0], 0); 8506 operands[2] = XEXP (operands[0], 1); 8507 break; 8508 default: 8509 operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]), 8510 VOIDmode, operands[1], operands[2]); 8511 break; 8512 } 8513 operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]); 8514}) 8515 8516(define_expand "cbranchfp4_media" 8517 [(set (pc) 8518 (if_then_else (match_operator 0 "sh_float_comparison_operator" 8519 [(match_operand 1 "" "") 8520 (match_operand 2 "" "")]) 8521 (match_operand 3 "" "") 8522 (pc)))] 8523 "TARGET_SHMEDIA" 8524{ 8525 rtx tmp = gen_reg_rtx (SImode); 8526 rtx cmp; 8527 if (GET_CODE (operands[0]) == NE) 8528 cmp = gen_rtx_EQ (SImode, operands[1], operands[2]); 8529 else 8530 cmp = gen_rtx_fmt_ee (GET_CODE (operands[0]), SImode, 8531 operands[1], operands[2]); 8532 8533 emit_insn (gen_cstore4_media (tmp, cmp, operands[1], operands[2])); 8534 8535 if (GET_CODE (cmp) == GET_CODE (operands[0])) 8536 operands[0] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); 8537 else 8538 operands[0] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); 8539 operands[1] = tmp; 8540 operands[2] = const0_rtx; 8541 operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]); 8542}) 8543 8544(define_insn "*beq_media_i" 8545 [(set (pc) 8546 (if_then_else (match_operator 3 "equality_comparison_operator" 8547 [(match_operand:DI 1 "arith_reg_operand" "r,r") 8548 (match_operand:DI 2 "arith_operand" "r,I06")]) 8549 (match_operand 0 "target_operand" "b,b") 8550 (pc)))] 8551 "TARGET_SHMEDIA" 8552 "@ 8553 b%o3%' %1, %2, %0%> 8554 b%o3i%' %1, %2, %0%>" 8555 [(set_attr "type" "cbranch_media")]) 8556 8557(define_insn "*beq_media_i32" 8558 [(set (pc) 8559 (if_then_else (match_operator 3 "equality_comparison_operator" 8560 [(match_operand:SI 1 "arith_reg_operand" "r,r") 8561 (match_operand:SI 2 "arith_operand" "r,I06")]) 8562 (match_operand 0 "target_operand" "b,b") 8563 (pc)))] 8564 "TARGET_SHMEDIA" 8565 "@ 8566 b%o3%' %1, %2, %0%> 8567 b%o3i%' %1, %2, %0%>" 8568 [(set_attr "type" "cbranch_media")]) 8569 8570(define_insn "*bgt_media_i" 8571 [(set (pc) 8572 (if_then_else (match_operator 3 "greater_comparison_operator" 8573 [(match_operand:DI 1 "arith_reg_or_0_operand" "rN") 8574 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")]) 8575 (match_operand 0 "target_operand" "b") 8576 (pc)))] 8577 "TARGET_SHMEDIA" 8578 "b%o3%' %N1, %N2, %0%>" 8579 [(set_attr "type" "cbranch_media")]) 8580 8581(define_insn "*bgt_media_i32" 8582 [(set (pc) 8583 (if_then_else (match_operator 3 "greater_comparison_operator" 8584 [(match_operand:SI 1 "arith_reg_or_0_operand" "rN") 8585 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")]) 8586 (match_operand 0 "target_operand" "b") 8587 (pc)))] 8588 "TARGET_SHMEDIA" 8589 "b%o3%' %N1, %N2, %0%>" 8590 [(set_attr "type" "cbranch_media")]) 8591 8592;; These are only needed to make invert_jump() happy - otherwise, jump 8593;; optimization will be silently disabled. 8594(define_insn "*blt_media_i" 8595 [(set (pc) 8596 (if_then_else (match_operator 3 "less_comparison_operator" 8597 [(match_operand:DI 1 "arith_reg_or_0_operand" "rN") 8598 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")]) 8599 (match_operand 0 "target_operand" "b") 8600 (pc)))] 8601 "TARGET_SHMEDIA" 8602 "b%o3%' %N2, %N1, %0%>" 8603 [(set_attr "type" "cbranch_media")]) 8604 8605(define_insn "*blt_media_i32" 8606 [(set (pc) 8607 (if_then_else (match_operator 3 "less_comparison_operator" 8608 [(match_operand:SI 1 "arith_reg_or_0_operand" "rN") 8609 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")]) 8610 (match_operand 0 "target_operand" "b") 8611 (pc)))] 8612 "TARGET_SHMEDIA" 8613 "b%o3%' %N2, %N1, %0%>" 8614 [(set_attr "type" "cbranch_media")]) 8615 8616;; combiner splitter for test-and-branch on single bit in register. This 8617;; is endian dependent because the non-paradoxical subreg looks different 8618;; on big endian. 8619(define_split 8620 [(set (pc) 8621 (if_then_else 8622 (match_operator 3 "equality_comparison_operator" 8623 [(subreg:SI 8624 (zero_extract:DI 8625 (subreg:DI (match_operand:SI 1 "extend_reg_operand" "") 0) 8626 (const_int 1) 8627 (match_operand 2 "const_int_operand" "")) 0) 8628 (const_int 0)]) 8629 (match_operand 0 "target_operand" "") 8630 (pc))) 8631 (clobber (match_operand:SI 4 "arith_reg_dest" ""))] 8632 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN" 8633 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5))) 8634 (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))] 8635{ 8636 operands[5] = GEN_INT (31 - INTVAL (operands[2])); 8637 operands[6] = (GET_CODE (operands[3]) == EQ 8638 ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx) 8639 : gen_rtx_GT (VOIDmode, const0_rtx, operands[4])); 8640}) 8641 8642; operand 0 is the loop count pseudo register 8643; operand 1 is the number of loop iterations or 0 if it is unknown 8644; operand 2 is the maximum number of loop iterations 8645; operand 3 is the number of levels of enclosed loops 8646; operand 4 is the label to jump to at the top of the loop 8647(define_expand "doloop_end" 8648 [(parallel [(set (pc) 8649 (if_then_else (ne:SI (match_operand:SI 0 "" "") 8650 (const_int 1)) 8651 (label_ref (match_operand 4 "" "")) 8652 (pc))) 8653 (set (match_dup 0) 8654 (plus:SI (match_dup 0) (const_int -1))) 8655 (clobber (reg:SI T_REG))]) 8656 (match_operand 5 "" "")] 8657 "TARGET_SH2" 8658{ 8659 if (GET_MODE (operands[0]) != SImode) 8660 FAIL; 8661 emit_jump_insn (gen_doloop_end_split (operands[0], operands[4], operands[0])); 8662 DONE; 8663}) 8664 8665(define_insn_and_split "doloop_end_split" 8666 [(set (pc) 8667 (if_then_else (ne:SI (match_operand:SI 2 "arith_reg_dest" "0") 8668 (const_int 1)) 8669 (label_ref (match_operand 1 "" "")) 8670 (pc))) 8671 (set (match_operand:SI 0 "arith_reg_dest" "=r") 8672 (plus (match_dup 2) (const_int -1))) 8673 (clobber (reg:SI T_REG))] 8674 "TARGET_SH2" 8675 "#" 8676 "" 8677 [(parallel [(set (reg:SI T_REG) 8678 (eq:SI (match_dup 2) (const_int 1))) 8679 (set (match_dup 0) (plus:SI (match_dup 2) (const_int -1)))]) 8680 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 8681 (label_ref (match_dup 1)) 8682 (pc)))] 8683 "" 8684 [(set_attr "type" "cbranch")]) 8685 8686;; ------------------------------------------------------------------------ 8687;; Jump and linkage insns 8688;; ------------------------------------------------------------------------ 8689 8690(define_insn "jump_compact" 8691 [(set (pc) 8692 (label_ref (match_operand 0 "" "")))] 8693 "TARGET_SH1 && !find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)" 8694{ 8695 /* The length is 16 if the delay slot is unfilled. */ 8696 if (get_attr_length(insn) > 4) 8697 return output_far_jump(insn, operands[0]); 8698 else 8699 return "bra %l0%#"; 8700} 8701 [(set_attr "type" "jump") 8702 (set_attr "needs_delay_slot" "yes")]) 8703 8704;; ??? It would be much saner to explicitly use the scratch register 8705;; in the jump insn, and have indirect_jump_scratch only set it, 8706;; but fill_simple_delay_slots would refuse to do delay slot filling 8707;; from the target then, as it uses simplejump_p. 8708;;(define_insn "jump_compact_far" 8709;; [(set (pc) 8710;; (label_ref (match_operand 0 "" ""))) 8711;; (use (match_operand 1 "register_operand" "r")] 8712;; "TARGET_SH1" 8713;; "* return output_far_jump(insn, operands[0], operands[1]);" 8714;; [(set_attr "type" "jump") 8715;; (set_attr "needs_delay_slot" "yes")]) 8716 8717(define_insn "jump_media" 8718 [(set (pc) 8719 (match_operand 0 "target_operand" "b"))] 8720 "TARGET_SHMEDIA" 8721 "blink %0, r63%>" 8722 [(set_attr "type" "jump_media")]) 8723 8724(define_expand "jump" 8725 [(set (pc) 8726 (label_ref (match_operand 0 "" "")))] 8727 "" 8728{ 8729 if (TARGET_SH1) 8730 emit_jump_insn (gen_jump_compact (operands[0])); 8731 else if (TARGET_SHMEDIA) 8732 { 8733 if (reload_in_progress || reload_completed) 8734 FAIL; 8735 emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode, operands[0]))); 8736 } 8737 DONE; 8738}) 8739 8740(define_insn "force_mode_for_call" 8741 [(use (reg:PSI FPSCR_REG))] 8742 "TARGET_SHCOMPACT" 8743 "" 8744 [(set_attr "length" "0") 8745 (set (attr "fp_mode") 8746 (if_then_else (eq_attr "fpu_single" "yes") 8747 (const_string "single") (const_string "double")))]) 8748 8749(define_insn "calli" 8750 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) 8751 (match_operand 1 "" "")) 8752 (use (reg:PSI FPSCR_REG)) 8753 (clobber (reg:SI PR_REG))] 8754 "TARGET_SH1" 8755{ 8756 if (TARGET_SH2A && (dbr_sequence_length () == 0)) 8757 return "jsr/n @%0"; 8758 else 8759 return "jsr @%0%#"; 8760} 8761 [(set_attr "type" "call") 8762 (set (attr "fp_mode") 8763 (if_then_else (eq_attr "fpu_single" "yes") 8764 (const_string "single") (const_string "double"))) 8765 (set_attr "needs_delay_slot" "yes") 8766 (set_attr "fp_set" "unknown")]) 8767 8768;; This is TBR relative jump instruction for SH2A architecture. 8769;; Its use is enabled by assigning an attribute "function_vector" 8770;; and the vector number to a function during its declaration. 8771(define_insn "calli_tbr_rel" 8772 [(call (mem (match_operand:SI 0 "symbol_ref_operand" "")) 8773 (match_operand 1 "" "")) 8774 (use (reg:PSI FPSCR_REG)) 8775 (clobber (reg:SI PR_REG))] 8776 "TARGET_SH2A && sh2a_is_function_vector_call (operands[0])" 8777{ 8778 unsigned HOST_WIDE_INT vect_num; 8779 vect_num = sh2a_get_function_vector_number (operands[0]); 8780 operands[2] = GEN_INT (vect_num * 4); 8781 8782 return "jsr/n @@(%O2,tbr)"; 8783} 8784 [(set_attr "type" "call") 8785 (set (attr "fp_mode") 8786 (if_then_else (eq_attr "fpu_single" "yes") 8787 (const_string "single") (const_string "double"))) 8788 (set_attr "needs_delay_slot" "no") 8789 (set_attr "fp_set" "unknown")]) 8790 8791;; This is a pc-rel call, using bsrf, for use with PIC. 8792(define_insn "calli_pcrel" 8793 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) 8794 (match_operand 1 "" "")) 8795 (use (reg:PSI FPSCR_REG)) 8796 (use (reg:SI PIC_REG)) 8797 (use (match_operand 2 "" "")) 8798 (clobber (reg:SI PR_REG))] 8799 "TARGET_SH2" 8800{ 8801 return "bsrf %0" "\n" 8802 "%O2:%#"; 8803} 8804 [(set_attr "type" "call") 8805 (set (attr "fp_mode") 8806 (if_then_else (eq_attr "fpu_single" "yes") 8807 (const_string "single") (const_string "double"))) 8808 (set_attr "needs_delay_slot" "yes") 8809 (set_attr "fp_set" "unknown")]) 8810 8811(define_insn_and_split "call_pcrel" 8812 [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "")) 8813 (match_operand 1 "" "")) 8814 (use (reg:PSI FPSCR_REG)) 8815 (use (reg:SI PIC_REG)) 8816 (clobber (reg:SI PR_REG)) 8817 (clobber (match_scratch:SI 2 "=r"))] 8818 "TARGET_SH2" 8819 "#" 8820 "reload_completed" 8821 [(const_int 0)] 8822{ 8823 rtx lab = PATTERN (gen_call_site ()); 8824 8825 if (SYMBOL_REF_LOCAL_P (operands[0])) 8826 emit_insn (gen_sym_label2reg (operands[2], operands[0], lab)); 8827 else 8828 emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab)); 8829 emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab))); 8830 DONE; 8831} 8832 [(set_attr "type" "call") 8833 (set (attr "fp_mode") 8834 (if_then_else (eq_attr "fpu_single" "yes") 8835 (const_string "single") (const_string "double"))) 8836 (set_attr "needs_delay_slot" "yes") 8837 (set_attr "fp_set" "unknown")]) 8838 8839(define_insn "call_compact" 8840 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) 8841 (match_operand 1 "" "")) 8842 (match_operand 2 "immediate_operand" "n") 8843 (use (reg:SI R0_REG)) 8844 (use (reg:SI R1_REG)) 8845 (use (reg:PSI FPSCR_REG)) 8846 (clobber (reg:SI PR_REG))] 8847 "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))" 8848 "jsr @%0%#" 8849 [(set_attr "type" "call") 8850 (set (attr "fp_mode") 8851 (if_then_else (eq_attr "fpu_single" "yes") 8852 (const_string "single") (const_string "double"))) 8853 (set_attr "needs_delay_slot" "yes")]) 8854 8855(define_insn "call_compact_rettramp" 8856 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) 8857 (match_operand 1 "" "")) 8858 (match_operand 2 "immediate_operand" "n") 8859 (use (reg:SI R0_REG)) 8860 (use (reg:SI R1_REG)) 8861 (use (reg:PSI FPSCR_REG)) 8862 (clobber (reg:SI R10_REG)) 8863 (clobber (reg:SI PR_REG))] 8864 "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))" 8865 "jsr @%0%#" 8866 [(set_attr "type" "call") 8867 (set (attr "fp_mode") 8868 (if_then_else (eq_attr "fpu_single" "yes") 8869 (const_string "single") (const_string "double"))) 8870 (set_attr "needs_delay_slot" "yes")]) 8871 8872(define_insn "call_media" 8873 [(call (mem:DI (match_operand 0 "target_reg_operand" "b")) 8874 (match_operand 1 "" "")) 8875 (clobber (reg:DI PR_MEDIA_REG))] 8876 "TARGET_SHMEDIA" 8877 "blink %0, r18" 8878 [(set_attr "type" "jump_media")]) 8879 8880(define_insn "call_valuei" 8881 [(set (match_operand 0 "" "=rf") 8882 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) 8883 (match_operand 2 "" ""))) 8884 (use (reg:PSI FPSCR_REG)) 8885 (clobber (reg:SI PR_REG))] 8886 "TARGET_SH1" 8887{ 8888 if (TARGET_SH2A && (dbr_sequence_length () == 0)) 8889 return "jsr/n @%1"; 8890 else 8891 return "jsr @%1%#"; 8892} 8893 [(set_attr "type" "call") 8894 (set (attr "fp_mode") 8895 (if_then_else (eq_attr "fpu_single" "yes") 8896 (const_string "single") (const_string "double"))) 8897 (set_attr "needs_delay_slot" "yes") 8898 (set_attr "fp_set" "unknown")]) 8899 8900;; This is TBR relative jump instruction for SH2A architecture. 8901;; Its use is enabled by assigning an attribute "function_vector" 8902;; and the vector number to a function during its declaration. 8903(define_insn "call_valuei_tbr_rel" 8904 [(set (match_operand 0 "" "=rf") 8905 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "")) 8906 (match_operand 2 "" ""))) 8907 (use (reg:PSI FPSCR_REG)) 8908 (clobber (reg:SI PR_REG))] 8909 "TARGET_SH2A && sh2a_is_function_vector_call (operands[1])" 8910{ 8911 unsigned HOST_WIDE_INT vect_num; 8912 vect_num = sh2a_get_function_vector_number (operands[1]); 8913 operands[3] = GEN_INT (vect_num * 4); 8914 8915 return "jsr/n @@(%O3,tbr)"; 8916} 8917 [(set_attr "type" "call") 8918 (set (attr "fp_mode") 8919 (if_then_else (eq_attr "fpu_single" "yes") 8920 (const_string "single") (const_string "double"))) 8921 (set_attr "needs_delay_slot" "no") 8922 (set_attr "fp_set" "unknown")]) 8923 8924(define_insn "call_valuei_pcrel" 8925 [(set (match_operand 0 "" "=rf") 8926 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) 8927 (match_operand 2 "" ""))) 8928 (use (reg:PSI FPSCR_REG)) 8929 (use (reg:SI PIC_REG)) 8930 (use (match_operand 3 "" "")) 8931 (clobber (reg:SI PR_REG))] 8932 "TARGET_SH2" 8933{ 8934 return "bsrf %1" "\n" 8935 "%O3:%#"; 8936} 8937 [(set_attr "type" "call") 8938 (set (attr "fp_mode") 8939 (if_then_else (eq_attr "fpu_single" "yes") 8940 (const_string "single") (const_string "double"))) 8941 (set_attr "needs_delay_slot" "yes") 8942 (set_attr "fp_set" "unknown")]) 8943 8944(define_insn_and_split "call_value_pcrel" 8945 [(set (match_operand 0 "" "=rf") 8946 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "")) 8947 (match_operand 2 "" ""))) 8948 (use (reg:PSI FPSCR_REG)) 8949 (use (reg:SI PIC_REG)) 8950 (clobber (reg:SI PR_REG)) 8951 (clobber (match_scratch:SI 3 "=r"))] 8952 "TARGET_SH2" 8953 "#" 8954 "reload_completed" 8955 [(const_int 0)] 8956{ 8957 rtx lab = PATTERN (gen_call_site ()); 8958 8959 if (SYMBOL_REF_LOCAL_P (operands[1])) 8960 emit_insn (gen_sym_label2reg (operands[3], operands[1], lab)); 8961 else 8962 emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab)); 8963 emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3], 8964 operands[2], copy_rtx (lab))); 8965 DONE; 8966} 8967 [(set_attr "type" "call") 8968 (set (attr "fp_mode") 8969 (if_then_else (eq_attr "fpu_single" "yes") 8970 (const_string "single") (const_string "double"))) 8971 (set_attr "needs_delay_slot" "yes") 8972 (set_attr "fp_set" "unknown")]) 8973 8974(define_insn "call_value_compact" 8975 [(set (match_operand 0 "" "=rf") 8976 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) 8977 (match_operand 2 "" ""))) 8978 (match_operand 3 "immediate_operand" "n") 8979 (use (reg:SI R0_REG)) 8980 (use (reg:SI R1_REG)) 8981 (use (reg:PSI FPSCR_REG)) 8982 (clobber (reg:SI PR_REG))] 8983 "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))" 8984 "jsr @%1%#" 8985 [(set_attr "type" "call") 8986 (set (attr "fp_mode") 8987 (if_then_else (eq_attr "fpu_single" "yes") 8988 (const_string "single") (const_string "double"))) 8989 (set_attr "needs_delay_slot" "yes")]) 8990 8991(define_insn "call_value_compact_rettramp" 8992 [(set (match_operand 0 "" "=rf") 8993 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) 8994 (match_operand 2 "" ""))) 8995 (match_operand 3 "immediate_operand" "n") 8996 (use (reg:SI R0_REG)) 8997 (use (reg:SI R1_REG)) 8998 (use (reg:PSI FPSCR_REG)) 8999 (clobber (reg:SI R10_REG)) 9000 (clobber (reg:SI PR_REG))] 9001 "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))" 9002 "jsr @%1%#" 9003 [(set_attr "type" "call") 9004 (set (attr "fp_mode") 9005 (if_then_else (eq_attr "fpu_single" "yes") 9006 (const_string "single") (const_string "double"))) 9007 (set_attr "needs_delay_slot" "yes")]) 9008 9009(define_insn "call_value_media" 9010 [(set (match_operand 0 "" "=rf") 9011 (call (mem:DI (match_operand 1 "target_reg_operand" "b")) 9012 (match_operand 2 "" ""))) 9013 (clobber (reg:DI PR_MEDIA_REG))] 9014 "TARGET_SHMEDIA" 9015 "blink %1, r18" 9016 [(set_attr "type" "jump_media")]) 9017 9018(define_expand "call" 9019 [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" "")) 9020 (match_operand 1 "" "")) 9021 (match_operand 2 "" "") 9022 (use (reg:PSI FPSCR_REG)) 9023 (clobber (reg:SI PR_REG))])] 9024 "" 9025{ 9026 if (TARGET_SHMEDIA) 9027 { 9028 operands[0] = shmedia_prepare_call_address (operands[0], 0); 9029 emit_call_insn (gen_call_media (operands[0], operands[1])); 9030 DONE; 9031 } 9032 else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2])) 9033 { 9034 rtx cookie_rtx = operands[2]; 9035 long cookie = INTVAL (cookie_rtx); 9036 rtx func = XEXP (operands[0], 0); 9037 rtx r0, r1; 9038 9039 if (flag_pic) 9040 { 9041 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func)) 9042 { 9043 rtx reg = gen_reg_rtx (Pmode); 9044 9045 emit_insn (gen_symGOTPLT2reg (reg, func)); 9046 func = reg; 9047 } 9048 else 9049 func = legitimize_pic_address (func, Pmode, 0); 9050 } 9051 9052 r0 = gen_rtx_REG (SImode, R0_REG); 9053 r1 = gen_rtx_REG (SImode, R1_REG); 9054 9055 /* Since such a call function may use all call-clobbered 9056 registers, we force a mode switch earlier, so that we don't 9057 run out of registers when adjusting fpscr for the call. */ 9058 emit_insn (gen_force_mode_for_call ()); 9059 9060 operands[0] 9061 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT); 9062 operands[0] = force_reg (SImode, operands[0]); 9063 9064 emit_move_insn (r0, func); 9065 emit_move_insn (r1, cookie_rtx); 9066 9067 if (cookie & CALL_COOKIE_RET_TRAMP (1)) 9068 emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1], 9069 operands[2])); 9070 else 9071 emit_call_insn (gen_call_compact (operands[0], operands[1], 9072 operands[2])); 9073 9074 DONE; 9075 } 9076 else if (TARGET_SHCOMPACT && flag_pic 9077 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF 9078 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0))) 9079 { 9080 rtx reg = gen_reg_rtx (Pmode); 9081 9082 emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0))); 9083 XEXP (operands[0], 0) = reg; 9084 } 9085 if (!flag_pic && TARGET_SH2A 9086 && MEM_P (operands[0]) 9087 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF) 9088 { 9089 if (sh2a_is_function_vector_call (XEXP (operands[0], 0))) 9090 { 9091 emit_call_insn (gen_calli_tbr_rel (XEXP (operands[0], 0), 9092 operands[1])); 9093 DONE; 9094 } 9095 } 9096 if (flag_pic && TARGET_SH2 9097 && MEM_P (operands[0]) 9098 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF) 9099 { 9100 emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1])); 9101 DONE; 9102 } 9103 else 9104 { 9105 operands[0] = force_reg (SImode, XEXP (operands[0], 0)); 9106 operands[1] = operands[2]; 9107 } 9108 9109 emit_call_insn (gen_calli (operands[0], operands[1])); 9110 DONE; 9111}) 9112 9113(define_insn "call_pop_compact" 9114 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) 9115 (match_operand 1 "" "")) 9116 (match_operand 2 "immediate_operand" "n") 9117 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) 9118 (match_operand 3 "immediate_operand" "n"))) 9119 (use (reg:SI R0_REG)) 9120 (use (reg:SI R1_REG)) 9121 (use (reg:PSI FPSCR_REG)) 9122 (clobber (reg:SI PR_REG))] 9123 "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))" 9124 "jsr @%0%#" 9125 [(set_attr "type" "call") 9126 (set (attr "fp_mode") 9127 (if_then_else (eq_attr "fpu_single" "yes") 9128 (const_string "single") (const_string "double"))) 9129 (set_attr "needs_delay_slot" "yes")]) 9130 9131(define_insn "call_pop_compact_rettramp" 9132 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) 9133 (match_operand 1 "" "")) 9134 (match_operand 2 "immediate_operand" "n") 9135 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) 9136 (match_operand 3 "immediate_operand" "n"))) 9137 (use (reg:SI R0_REG)) 9138 (use (reg:SI R1_REG)) 9139 (use (reg:PSI FPSCR_REG)) 9140 (clobber (reg:SI R10_REG)) 9141 (clobber (reg:SI PR_REG))] 9142 "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))" 9143 "jsr @%0%#" 9144 [(set_attr "type" "call") 9145 (set (attr "fp_mode") 9146 (if_then_else (eq_attr "fpu_single" "yes") 9147 (const_string "single") (const_string "double"))) 9148 (set_attr "needs_delay_slot" "yes")]) 9149 9150(define_expand "call_pop" 9151 [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" "")) 9152 (match_operand 1 "" "")) 9153 (match_operand 2 "" "") 9154 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) 9155 (match_operand 3 "" "")))])] 9156 "TARGET_SHCOMPACT" 9157{ 9158 rtx cookie_rtx; 9159 long cookie; 9160 rtx func; 9161 rtx r0, r1; 9162 9163 gcc_assert (operands[2] && INTVAL (operands[2])); 9164 cookie_rtx = operands[2]; 9165 cookie = INTVAL (cookie_rtx); 9166 func = XEXP (operands[0], 0); 9167 9168 if (flag_pic) 9169 { 9170 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func)) 9171 { 9172 rtx reg = gen_reg_rtx (Pmode); 9173 emit_insn (gen_symGOTPLT2reg (reg, func)); 9174 func = reg; 9175 } 9176 else 9177 func = legitimize_pic_address (func, Pmode, 0); 9178 } 9179 9180 r0 = gen_rtx_REG (SImode, R0_REG); 9181 r1 = gen_rtx_REG (SImode, R1_REG); 9182 9183 /* Since such a call function may use all call-clobbered 9184 registers, we force a mode switch earlier, so that we don't 9185 run out of registers when adjusting fpscr for the call. */ 9186 emit_insn (gen_force_mode_for_call ()); 9187 9188 operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline", 9189 SFUNC_GOT); 9190 operands[0] = force_reg (SImode, operands[0]); 9191 9192 emit_move_insn (r0, func); 9193 emit_move_insn (r1, cookie_rtx); 9194 9195 if (cookie & CALL_COOKIE_RET_TRAMP (1)) 9196 emit_call_insn (gen_call_pop_compact_rettramp 9197 (operands[0], operands[1], operands[2], operands[3])); 9198 else 9199 emit_call_insn (gen_call_pop_compact 9200 (operands[0], operands[1], operands[2], operands[3])); 9201 9202 DONE; 9203}) 9204 9205(define_expand "call_value" 9206 [(parallel [(set (match_operand 0 "arith_reg_operand" "") 9207 (call (mem:SI (match_operand 1 "arith_reg_operand" "")) 9208 (match_operand 2 "" ""))) 9209 (match_operand 3 "" "") 9210 (use (reg:PSI FPSCR_REG)) 9211 (clobber (reg:SI PR_REG))])] 9212 "" 9213{ 9214 if (TARGET_SHMEDIA) 9215 { 9216 operands[1] = shmedia_prepare_call_address (operands[1], 0); 9217 emit_call_insn (gen_call_value_media (operands[0], operands[1], 9218 operands[2])); 9219 DONE; 9220 } 9221 else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3])) 9222 { 9223 rtx cookie_rtx = operands[3]; 9224 long cookie = INTVAL (cookie_rtx); 9225 rtx func = XEXP (operands[1], 0); 9226 rtx r0, r1; 9227 9228 if (flag_pic) 9229 { 9230 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func)) 9231 { 9232 rtx reg = gen_reg_rtx (Pmode); 9233 9234 emit_insn (gen_symGOTPLT2reg (reg, func)); 9235 func = reg; 9236 } 9237 else 9238 func = legitimize_pic_address (func, Pmode, 0); 9239 } 9240 9241 r0 = gen_rtx_REG (SImode, R0_REG); 9242 r1 = gen_rtx_REG (SImode, R1_REG); 9243 9244 /* Since such a call function may use all call-clobbered 9245 registers, we force a mode switch earlier, so that we don't 9246 run out of registers when adjusting fpscr for the call. */ 9247 emit_insn (gen_force_mode_for_call ()); 9248 9249 operands[1] 9250 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT); 9251 operands[1] = force_reg (SImode, operands[1]); 9252 9253 emit_move_insn (r0, func); 9254 emit_move_insn (r1, cookie_rtx); 9255 9256 if (cookie & CALL_COOKIE_RET_TRAMP (1)) 9257 emit_call_insn (gen_call_value_compact_rettramp (operands[0], 9258 operands[1], 9259 operands[2], 9260 operands[3])); 9261 else 9262 emit_call_insn (gen_call_value_compact (operands[0], operands[1], 9263 operands[2], operands[3])); 9264 9265 DONE; 9266 } 9267 else if (TARGET_SHCOMPACT && flag_pic 9268 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF 9269 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0))) 9270 { 9271 rtx reg = gen_reg_rtx (Pmode); 9272 9273 emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0))); 9274 XEXP (operands[1], 0) = reg; 9275 } 9276 if (!flag_pic && TARGET_SH2A 9277 && MEM_P (operands[1]) 9278 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF) 9279 { 9280 if (sh2a_is_function_vector_call (XEXP (operands[1], 0))) 9281 { 9282 emit_call_insn (gen_call_valuei_tbr_rel (operands[0], 9283 XEXP (operands[1], 0), operands[2])); 9284 DONE; 9285 } 9286 } 9287 if (flag_pic && TARGET_SH2 9288 && MEM_P (operands[1]) 9289 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF) 9290 { 9291 emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0), 9292 operands[2])); 9293 DONE; 9294 } 9295 else 9296 operands[1] = force_reg (SImode, XEXP (operands[1], 0)); 9297 9298 emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2])); 9299 DONE; 9300}) 9301 9302(define_insn "sibcalli" 9303 [(call (mem:SI (match_operand:SI 0 "register_operand" "k")) 9304 (match_operand 1 "" "")) 9305 (use (reg:PSI FPSCR_REG)) 9306 (return)] 9307 "TARGET_SH1" 9308 "jmp @%0%#" 9309 [(set_attr "needs_delay_slot" "yes") 9310 (set (attr "fp_mode") 9311 (if_then_else (eq_attr "fpu_single" "yes") 9312 (const_string "single") (const_string "double"))) 9313 (set_attr "type" "jump_ind")]) 9314 9315(define_insn "sibcalli_pcrel" 9316 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k")) 9317 (match_operand 1 "" "")) 9318 (use (match_operand 2 "" "")) 9319 (use (reg:PSI FPSCR_REG)) 9320 (return)] 9321 "TARGET_SH2" 9322{ 9323 return "braf %0" "\n" 9324 "%O2:%#"; 9325} 9326 [(set_attr "needs_delay_slot" "yes") 9327 (set (attr "fp_mode") 9328 (if_then_else (eq_attr "fpu_single" "yes") 9329 (const_string "single") (const_string "double"))) 9330 (set_attr "type" "jump_ind")]) 9331 9332;; This uses an unspec to describe that the symbol_ref is very close. 9333(define_insn "sibcalli_thunk" 9334 [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")] 9335 UNSPEC_THUNK)) 9336 (match_operand 1 "" "")) 9337 (use (reg:PSI FPSCR_REG)) 9338 (return)] 9339 "TARGET_SH1" 9340 "bra %O0" 9341 [(set_attr "needs_delay_slot" "yes") 9342 (set (attr "fp_mode") 9343 (if_then_else (eq_attr "fpu_single" "yes") 9344 (const_string "single") (const_string "double"))) 9345 (set_attr "type" "jump") 9346 (set_attr "length" "2")]) 9347 9348(define_insn_and_split "sibcall_pcrel" 9349 [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "")) 9350 (match_operand 1 "" "")) 9351 (use (reg:PSI FPSCR_REG)) 9352 (clobber (match_scratch:SI 2 "=k")) 9353 (return)] 9354 "TARGET_SH2" 9355 "#" 9356 "reload_completed" 9357 [(const_int 0)] 9358{ 9359 rtx lab = PATTERN (gen_call_site ()); 9360 rtx call_insn; 9361 9362 emit_insn (gen_sym_label2reg (operands[2], operands[0], lab)); 9363 call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1], 9364 copy_rtx (lab))); 9365 SIBLING_CALL_P (call_insn) = 1; 9366 DONE; 9367} 9368 [(set_attr "needs_delay_slot" "yes") 9369 (set (attr "fp_mode") 9370 (if_then_else (eq_attr "fpu_single" "yes") 9371 (const_string "single") (const_string "double"))) 9372 (set_attr "type" "jump_ind")]) 9373 9374(define_insn "sibcall_compact" 9375 [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k")) 9376 (match_operand 1 "" "")) 9377 (return) 9378 (use (match_operand:SI 2 "register_operand" "z,x")) 9379 (use (reg:SI R1_REG)) 9380 (use (reg:PSI FPSCR_REG)) 9381 ;; We want to make sure the `x' above will only match MACH_REG 9382 ;; because sibcall_epilogue may clobber MACL_REG. 9383 (clobber (reg:SI MACL_REG))] 9384 "TARGET_SHCOMPACT" 9385{ 9386 static const char* alt[] = 9387 { 9388 "jmp @%0%#", 9389 9390 "jmp @%0" "\n" 9391 " sts %2,r0" 9392 }; 9393 return alt[which_alternative]; 9394} 9395 [(set_attr "needs_delay_slot" "yes,no") 9396 (set_attr "length" "2,4") 9397 (set (attr "fp_mode") (const_string "single")) 9398 (set_attr "type" "jump_ind")]) 9399 9400(define_insn "sibcall_media" 9401 [(call (mem:DI (match_operand 0 "target_reg_operand" "k")) 9402 (match_operand 1 "" "")) 9403 (use (reg:SI PR_MEDIA_REG)) 9404 (return)] 9405 "TARGET_SHMEDIA" 9406 "blink %0, r63" 9407 [(set_attr "type" "jump_media")]) 9408 9409(define_expand "sibcall" 9410 [(parallel 9411 [(call (mem:SI (match_operand 0 "arith_reg_operand" "")) 9412 (match_operand 1 "" "")) 9413 (match_operand 2 "" "") 9414 (use (reg:PSI FPSCR_REG)) 9415 (return)])] 9416 "" 9417{ 9418 if (TARGET_SHMEDIA) 9419 { 9420 operands[0] = shmedia_prepare_call_address (operands[0], 1); 9421 emit_call_insn (gen_sibcall_media (operands[0], operands[1])); 9422 DONE; 9423 } 9424 else if (TARGET_SHCOMPACT && operands[2] 9425 && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1))) 9426 { 9427 rtx cookie_rtx = operands[2]; 9428 long cookie = INTVAL (cookie_rtx); 9429 rtx func = XEXP (operands[0], 0); 9430 rtx mach, r1; 9431 9432 if (flag_pic) 9433 { 9434 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func)) 9435 { 9436 rtx reg = gen_reg_rtx (Pmode); 9437 9438 emit_insn (gen_symGOT2reg (reg, func)); 9439 func = reg; 9440 } 9441 else 9442 func = legitimize_pic_address (func, Pmode, 0); 9443 } 9444 9445 /* FIXME: if we could tell whether all argument registers are 9446 already taken, we could decide whether to force the use of 9447 MACH_REG or to stick to R0_REG. Unfortunately, there's no 9448 simple way to tell. We could use the CALL_COOKIE, but we 9449 can't currently tell a register used for regular argument 9450 passing from one that is unused. If we leave it up to reload 9451 to decide which register to use, it seems to always choose 9452 R0_REG, which leaves no available registers in SIBCALL_REGS 9453 to hold the address of the trampoline. */ 9454 mach = gen_rtx_REG (SImode, MACH_REG); 9455 r1 = gen_rtx_REG (SImode, R1_REG); 9456 9457 /* Since such a call function may use all call-clobbered 9458 registers, we force a mode switch earlier, so that we don't 9459 run out of registers when adjusting fpscr for the call. */ 9460 emit_insn (gen_force_mode_for_call ()); 9461 9462 operands[0] 9463 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT); 9464 operands[0] = force_reg (SImode, operands[0]); 9465 9466 /* We don't need a return trampoline, since the callee will 9467 return directly to the upper caller. */ 9468 if (cookie & CALL_COOKIE_RET_TRAMP (1)) 9469 { 9470 cookie &= ~ CALL_COOKIE_RET_TRAMP (1); 9471 cookie_rtx = GEN_INT (cookie); 9472 } 9473 9474 emit_move_insn (mach, func); 9475 emit_move_insn (r1, cookie_rtx); 9476 9477 emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach)); 9478 DONE; 9479 } 9480 else if (TARGET_SHCOMPACT && flag_pic 9481 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF 9482 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0))) 9483 { 9484 rtx reg = gen_reg_rtx (Pmode); 9485 9486 emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0))); 9487 XEXP (operands[0], 0) = reg; 9488 } 9489 if (flag_pic && TARGET_SH2 9490 && MEM_P (operands[0]) 9491 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF 9492 /* The PLT needs the PIC register, but the epilogue would have 9493 to restore it, so we can only use PC-relative PIC calls for 9494 static functions. */ 9495 && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0))) 9496 { 9497 emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1])); 9498 DONE; 9499 } 9500 else 9501 operands[0] = force_reg (SImode, XEXP (operands[0], 0)); 9502 9503 emit_call_insn (gen_sibcalli (operands[0], operands[1])); 9504 DONE; 9505}) 9506 9507(define_insn "sibcall_valuei" 9508 [(set (match_operand 0 "" "=rf") 9509 (call (mem:SI (match_operand:SI 1 "register_operand" "k")) 9510 (match_operand 2 "" ""))) 9511 (use (reg:PSI FPSCR_REG)) 9512 (return)] 9513 "TARGET_SH1" 9514 "jmp @%1%#" 9515 [(set_attr "needs_delay_slot" "yes") 9516 (set (attr "fp_mode") 9517 (if_then_else (eq_attr "fpu_single" "yes") 9518 (const_string "single") (const_string "double"))) 9519 (set_attr "type" "jump_ind")]) 9520 9521(define_insn "sibcall_valuei_pcrel" 9522 [(set (match_operand 0 "" "=rf") 9523 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k")) 9524 (match_operand 2 "" ""))) 9525 (use (match_operand 3 "" "")) 9526 (use (reg:PSI FPSCR_REG)) 9527 (return)] 9528 "TARGET_SH2" 9529{ 9530 return "braf %1" "\n" 9531 "%O3:%#"; 9532} 9533 [(set_attr "needs_delay_slot" "yes") 9534 (set (attr "fp_mode") 9535 (if_then_else (eq_attr "fpu_single" "yes") 9536 (const_string "single") (const_string "double"))) 9537 (set_attr "type" "jump_ind")]) 9538 9539(define_insn_and_split "sibcall_value_pcrel" 9540 [(set (match_operand 0 "" "=rf") 9541 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "")) 9542 (match_operand 2 "" ""))) 9543 (use (reg:PSI FPSCR_REG)) 9544 (clobber (match_scratch:SI 3 "=k")) 9545 (return)] 9546 "TARGET_SH2" 9547 "#" 9548 "reload_completed" 9549 [(const_int 0)] 9550{ 9551 rtx lab = PATTERN (gen_call_site ()); 9552 rtx call_insn; 9553 9554 emit_insn (gen_sym_label2reg (operands[3], operands[1], lab)); 9555 call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0], 9556 operands[3], 9557 operands[2], 9558 copy_rtx (lab))); 9559 SIBLING_CALL_P (call_insn) = 1; 9560 DONE; 9561} 9562 [(set_attr "needs_delay_slot" "yes") 9563 (set (attr "fp_mode") 9564 (if_then_else (eq_attr "fpu_single" "yes") 9565 (const_string "single") (const_string "double"))) 9566 (set_attr "type" "jump_ind")]) 9567 9568(define_insn "sibcall_value_compact" 9569 [(set (match_operand 0 "" "=rf,rf") 9570 (call (mem:SI (match_operand:SI 1 "register_operand" "k,k")) 9571 (match_operand 2 "" ""))) 9572 (return) 9573 (use (match_operand:SI 3 "register_operand" "z,x")) 9574 (use (reg:SI R1_REG)) 9575 (use (reg:PSI FPSCR_REG)) 9576 ;; We want to make sure the `x' above will only match MACH_REG 9577 ;; because sibcall_epilogue may clobber MACL_REG. 9578 (clobber (reg:SI MACL_REG))] 9579 "TARGET_SHCOMPACT" 9580{ 9581 static const char* alt[] = 9582 { 9583 "jmp @%1%#", 9584 9585 "jmp @%1" "\n" 9586 " sts %3,r0" 9587 }; 9588 return alt[which_alternative]; 9589} 9590 [(set_attr "needs_delay_slot" "yes,no") 9591 (set_attr "length" "2,4") 9592 (set (attr "fp_mode") (const_string "single")) 9593 (set_attr "type" "jump_ind")]) 9594 9595(define_insn "sibcall_value_media" 9596 [(set (match_operand 0 "" "=rf") 9597 (call (mem:DI (match_operand 1 "target_reg_operand" "k")) 9598 (match_operand 2 "" ""))) 9599 (use (reg:SI PR_MEDIA_REG)) 9600 (return)] 9601 "TARGET_SHMEDIA" 9602 "blink %1, r63" 9603 [(set_attr "type" "jump_media")]) 9604 9605(define_expand "sibcall_value" 9606 [(parallel 9607 [(set (match_operand 0 "arith_reg_operand" "") 9608 (call (mem:SI (match_operand 1 "arith_reg_operand" "")) 9609 (match_operand 2 "" ""))) 9610 (match_operand 3 "" "") 9611 (use (reg:PSI FPSCR_REG)) 9612 (return)])] 9613 "" 9614{ 9615 if (TARGET_SHMEDIA) 9616 { 9617 operands[1] = shmedia_prepare_call_address (operands[1], 1); 9618 emit_call_insn (gen_sibcall_value_media (operands[0], operands[1], 9619 operands[2])); 9620 DONE; 9621 } 9622 else if (TARGET_SHCOMPACT && operands[3] 9623 && (INTVAL (operands[3]) & ~ CALL_COOKIE_RET_TRAMP (1))) 9624 { 9625 rtx cookie_rtx = operands[3]; 9626 long cookie = INTVAL (cookie_rtx); 9627 rtx func = XEXP (operands[1], 0); 9628 rtx mach, r1; 9629 9630 if (flag_pic) 9631 { 9632 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func)) 9633 { 9634 rtx reg = gen_reg_rtx (Pmode); 9635 9636 emit_insn (gen_symGOT2reg (reg, func)); 9637 func = reg; 9638 } 9639 else 9640 func = legitimize_pic_address (func, Pmode, 0); 9641 } 9642 9643 /* FIXME: if we could tell whether all argument registers are 9644 already taken, we could decide whether to force the use of 9645 MACH_REG or to stick to R0_REG. Unfortunately, there's no 9646 simple way to tell. We could use the CALL_COOKIE, but we 9647 can't currently tell a register used for regular argument 9648 passing from one that is unused. If we leave it up to reload 9649 to decide which register to use, it seems to always choose 9650 R0_REG, which leaves no available registers in SIBCALL_REGS 9651 to hold the address of the trampoline. */ 9652 mach = gen_rtx_REG (SImode, MACH_REG); 9653 r1 = gen_rtx_REG (SImode, R1_REG); 9654 9655 /* Since such a call function may use all call-clobbered 9656 registers, we force a mode switch earlier, so that we don't 9657 run out of registers when adjusting fpscr for the call. */ 9658 emit_insn (gen_force_mode_for_call ()); 9659 9660 operands[1] 9661 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT); 9662 operands[1] = force_reg (SImode, operands[1]); 9663 9664 /* We don't need a return trampoline, since the callee will 9665 return directly to the upper caller. */ 9666 if (cookie & CALL_COOKIE_RET_TRAMP (1)) 9667 { 9668 cookie &= ~ CALL_COOKIE_RET_TRAMP (1); 9669 cookie_rtx = GEN_INT (cookie); 9670 } 9671 9672 emit_move_insn (mach, func); 9673 emit_move_insn (r1, cookie_rtx); 9674 9675 emit_call_insn (gen_sibcall_value_compact (operands[0], operands[1], 9676 operands[2], mach)); 9677 DONE; 9678 } 9679 else if (TARGET_SHCOMPACT && flag_pic 9680 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF 9681 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0))) 9682 { 9683 rtx reg = gen_reg_rtx (Pmode); 9684 9685 emit_insn (gen_symGOT2reg (reg, XEXP (operands[1], 0))); 9686 XEXP (operands[1], 0) = reg; 9687 } 9688 if (flag_pic && TARGET_SH2 9689 && MEM_P (operands[1]) 9690 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF 9691 /* The PLT needs the PIC register, but the epilogue would have 9692 to restore it, so we can only use PC-relative PIC calls for 9693 static functions. */ 9694 && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0))) 9695 { 9696 emit_call_insn (gen_sibcall_value_pcrel (operands[0], 9697 XEXP (operands[1], 0), 9698 operands[2])); 9699 DONE; 9700 } 9701 else 9702 operands[1] = force_reg (SImode, XEXP (operands[1], 0)); 9703 9704 emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2])); 9705 DONE; 9706}) 9707 9708(define_insn "call_value_pop_compact" 9709 [(set (match_operand 0 "" "=rf") 9710 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) 9711 (match_operand 2 "" ""))) 9712 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) 9713 (match_operand 4 "immediate_operand" "n"))) 9714 (match_operand 3 "immediate_operand" "n") 9715 (use (reg:SI R0_REG)) 9716 (use (reg:SI R1_REG)) 9717 (use (reg:PSI FPSCR_REG)) 9718 (clobber (reg:SI PR_REG))] 9719 "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))" 9720 "jsr @%1%#" 9721 [(set_attr "type" "call") 9722 (set (attr "fp_mode") 9723 (if_then_else (eq_attr "fpu_single" "yes") 9724 (const_string "single") (const_string "double"))) 9725 (set_attr "needs_delay_slot" "yes")]) 9726 9727(define_insn "call_value_pop_compact_rettramp" 9728 [(set (match_operand 0 "" "=rf") 9729 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) 9730 (match_operand 2 "" ""))) 9731 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) 9732 (match_operand 4 "immediate_operand" "n"))) 9733 (match_operand 3 "immediate_operand" "n") 9734 (use (reg:SI R0_REG)) 9735 (use (reg:SI R1_REG)) 9736 (use (reg:PSI FPSCR_REG)) 9737 (clobber (reg:SI R10_REG)) 9738 (clobber (reg:SI PR_REG))] 9739 "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))" 9740 "jsr @%1%#" 9741 [(set_attr "type" "call") 9742 (set (attr "fp_mode") 9743 (if_then_else (eq_attr "fpu_single" "yes") 9744 (const_string "single") (const_string "double"))) 9745 (set_attr "needs_delay_slot" "yes")]) 9746 9747(define_expand "call_value_pop" 9748 [(parallel [(set (match_operand 0 "arith_reg_operand" "") 9749 (call (mem:SI (match_operand 1 "arith_reg_operand" "")) 9750 (match_operand 2 "" ""))) 9751 (match_operand 3 "" "") 9752 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) 9753 (match_operand 4 "" "")))])] 9754 "TARGET_SHCOMPACT" 9755{ 9756 rtx cookie_rtx; 9757 long cookie; 9758 rtx func; 9759 rtx r0, r1; 9760 9761 gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3])); 9762 cookie_rtx = operands[3]; 9763 cookie = INTVAL (cookie_rtx); 9764 func = XEXP (operands[1], 0); 9765 9766 if (flag_pic) 9767 { 9768 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func)) 9769 { 9770 rtx reg = gen_reg_rtx (Pmode); 9771 9772 emit_insn (gen_symGOTPLT2reg (reg, func)); 9773 func = reg; 9774 } 9775 else 9776 func = legitimize_pic_address (func, Pmode, 0); 9777 } 9778 9779 r0 = gen_rtx_REG (SImode, R0_REG); 9780 r1 = gen_rtx_REG (SImode, R1_REG); 9781 9782 /* Since such a call function may use all call-clobbered 9783 registers, we force a mode switch earlier, so that we don't 9784 run out of registers when adjusting fpscr for the call. */ 9785 emit_insn (gen_force_mode_for_call ()); 9786 9787 operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline", 9788 SFUNC_GOT); 9789 operands[1] = force_reg (SImode, operands[1]); 9790 9791 emit_move_insn (r0, func); 9792 emit_move_insn (r1, cookie_rtx); 9793 9794 if (cookie & CALL_COOKIE_RET_TRAMP (1)) 9795 emit_call_insn (gen_call_value_pop_compact_rettramp 9796 (operands[0], operands[1], operands[2], 9797 operands[3], operands[4])); 9798 else 9799 emit_call_insn (gen_call_value_pop_compact 9800 (operands[0], operands[1], operands[2], 9801 operands[3], operands[4])); 9802 9803 DONE; 9804}) 9805 9806(define_expand "sibcall_epilogue" 9807 [(return)] 9808 "" 9809{ 9810 sh_expand_epilogue (true); 9811 if (TARGET_SHCOMPACT) 9812 { 9813 rtx insn, set; 9814 9815 /* If epilogue clobbers r0, preserve it in macl. */ 9816 for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) 9817 if ((set = single_set (insn)) 9818 && REG_P (SET_DEST (set)) 9819 && REGNO (SET_DEST (set)) == R0_REG) 9820 { 9821 rtx r0 = gen_rtx_REG (SImode, R0_REG); 9822 rtx tmp = gen_rtx_REG (SImode, MACL_REG); 9823 9824 /* We can't tell at this point whether the sibcall is a 9825 sibcall_compact and, if it is, whether it uses r0 or 9826 mach as operand 2, so let the instructions that 9827 preserve r0 be optimized away if r0 turns out to be 9828 dead. */ 9829 emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn); 9830 emit_move_insn (r0, tmp); 9831 break; 9832 } 9833 } 9834 DONE; 9835}) 9836 9837(define_insn "indirect_jump_compact" 9838 [(set (pc) 9839 (match_operand:SI 0 "arith_reg_operand" "r"))] 9840 "TARGET_SH1" 9841 "jmp @%0%#" 9842 [(set_attr "needs_delay_slot" "yes") 9843 (set_attr "type" "jump_ind")]) 9844 9845(define_expand "indirect_jump" 9846 [(set (pc) 9847 (match_operand 0 "register_operand" ""))] 9848 "" 9849{ 9850 if (GET_MODE (operands[0]) != Pmode) 9851 operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0); 9852}) 9853 9854;; The use of operand 1 / 2 helps us distinguish case table jumps 9855;; which can be present in structured code from indirect jumps which can not 9856;; be present in structured code. This allows -fprofile-arcs to work. 9857 9858;; For SH1 processors. 9859(define_insn "casesi_jump_1" 9860 [(set (pc) 9861 (match_operand:SI 0 "register_operand" "r")) 9862 (use (label_ref (match_operand 1 "" "")))] 9863 "TARGET_SH1" 9864 "jmp @%0%#" 9865 [(set_attr "needs_delay_slot" "yes") 9866 (set_attr "type" "jump_ind")]) 9867 9868;; For all later processors. 9869(define_insn "casesi_jump_2" 9870 [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r") 9871 (label_ref (match_operand 1 "" "")))) 9872 (use (label_ref (match_operand 2 "" "")))] 9873 "TARGET_SH2 9874 && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)" 9875 "braf %0%#" 9876 [(set_attr "needs_delay_slot" "yes") 9877 (set_attr "type" "jump_ind")]) 9878 9879(define_insn "casesi_jump_media" 9880 [(set (pc) (match_operand 0 "target_reg_operand" "b")) 9881 (use (label_ref (match_operand 1 "" "")))] 9882 "TARGET_SHMEDIA" 9883 "blink %0, r63" 9884 [(set_attr "type" "jump_media")]) 9885 9886;; Call subroutine returning any type. 9887;; ??? This probably doesn't work. 9888(define_expand "untyped_call" 9889 [(parallel [(call (match_operand 0 "" "") 9890 (const_int 0)) 9891 (match_operand 1 "" "") 9892 (match_operand 2 "" "")])] 9893 "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA" 9894{ 9895 emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx)); 9896 9897 for (int i = 0; i < XVECLEN (operands[2], 0); i++) 9898 { 9899 rtx set = XVECEXP (operands[2], 0, i); 9900 emit_move_insn (SET_DEST (set), SET_SRC (set)); 9901 } 9902 9903 /* The optimizer does not know that the call sets the function value 9904 registers we stored in the result block. We avoid problems by 9905 claiming that all hard registers are used and clobbered at this 9906 point. */ 9907 emit_insn (gen_blockage ()); 9908 9909 DONE; 9910}) 9911 9912;; ------------------------------------------------------------------------ 9913;; Misc insns 9914;; ------------------------------------------------------------------------ 9915 9916(define_insn "dect" 9917 [(set (reg:SI T_REG) 9918 (eq:SI (match_operand:SI 1 "arith_reg_dest" "0") (const_int 1))) 9919 (set (match_operand:SI 0 "arith_reg_dest" "=r") 9920 (plus:SI (match_dup 1) (const_int -1)))] 9921 "TARGET_SH2" 9922 "dt %0" 9923 [(set_attr "type" "arith")]) 9924 9925(define_insn "nop" 9926 [(const_int 0)] 9927 "" 9928 "nop") 9929 9930;; Load address of a label. This is only generated by the casesi expand, 9931;; and by machine_dependent_reorg (fixing up fp moves). 9932;; This must use unspec, because this only works for labels that are 9933;; within range. 9934(define_insn "mova" 9935 [(set (reg:SI R0_REG) 9936 (unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))] 9937 "TARGET_SH1" 9938 "mova %O0,r0" 9939 [(set_attr "in_delay_slot" "no") 9940 (set_attr "type" "arith")]) 9941 9942;; machine_dependent_reorg will make this a `mova'. 9943(define_insn "mova_const" 9944 [(set (reg:SI R0_REG) 9945 (unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))] 9946 "TARGET_SH1" 9947 "#" 9948 [(set_attr "in_delay_slot" "no") 9949 (set_attr "type" "arith")]) 9950 9951(define_expand "GOTaddr2picreg" 9952 [(set (reg:SI R0_REG) 9953 (unspec:SI [(const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))] 9954 UNSPEC_MOVA)) 9955 (set (match_dup 0) (const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))) 9956 (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))] 9957 "" 9958{ 9959 if (TARGET_VXWORKS_RTP) 9960 { 9961 rtx gott_base = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE); 9962 rtx gott_index = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX); 9963 emit_insn (gen_vxworks_picreg (gott_base, gott_index)); 9964 DONE; 9965 } 9966 9967 operands[0] = gen_rtx_REG (Pmode, PIC_REG); 9968 operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME); 9969 9970 if (TARGET_SHMEDIA) 9971 { 9972 rtx tr = gen_rtx_REG (Pmode, TR0_REG); 9973 rtx pic = operands[0]; 9974 rtx lab = PATTERN (gen_call_site ()); 9975 rtx insn, equiv; 9976 9977 equiv = operands[1]; 9978 operands[1] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1], lab), 9979 UNSPEC_PCREL_SYMOFF); 9980 operands[1] = gen_rtx_CONST (Pmode, operands[1]); 9981 9982 if (Pmode == SImode) 9983 { 9984 emit_insn (gen_movsi_const (pic, operands[1])); 9985 emit_insn (gen_ptrel_si (tr, pic, copy_rtx (lab))); 9986 } 9987 else 9988 { 9989 emit_insn (gen_movdi_const (pic, operands[1])); 9990 emit_insn (gen_ptrel_di (tr, pic, copy_rtx (lab))); 9991 } 9992 9993 insn = emit_move_insn (operands[0], tr); 9994 9995 set_unique_reg_note (insn, REG_EQUAL, equiv); 9996 9997 DONE; 9998 } 9999}) 10000 10001;; A helper for GOTaddr2picreg to finish up the initialization of the 10002;; PIC register. 10003(define_expand "vxworks_picreg" 10004 [(set (reg:SI PIC_REG) 10005 (const:SI (unspec:SI [(match_operand:SI 0 "" "")] UNSPEC_PIC))) 10006 (set (reg:SI R0_REG) 10007 (const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC))) 10008 (set (reg:SI PIC_REG) 10009 (mem:SI (reg:SI PIC_REG))) 10010 (set (reg:SI PIC_REG) 10011 (mem:SI (plus:SI (reg:SI PIC_REG) 10012 (reg:SI R0_REG))))] 10013 "TARGET_VXWORKS_RTP") 10014 10015(define_insn "*ptb" 10016 [(set (match_operand 0 "target_reg_operand" "=b") 10017 (const (unspec [(match_operand 1 "" "Csy")] 10018 UNSPEC_DATALABEL)))] 10019 "TARGET_SHMEDIA && flag_pic 10020 && satisfies_constraint_Csy (operands[1])" 10021 "ptb/u datalabel %1, %0" 10022 [(set_attr "type" "ptabs_media") 10023 (set_attr "length" "*")]) 10024 10025(define_insn "ptrel_si" 10026 [(set (match_operand:SI 0 "target_reg_operand" "=b") 10027 (plus:SI (match_operand:SI 1 "register_operand" "r") 10028 (pc))) 10029 (match_operand:SI 2 "" "")] 10030 "TARGET_SHMEDIA" 10031 "%O2: ptrel/u %1, %0" 10032 [(set_attr "type" "ptabs_media")]) 10033 10034(define_insn "ptrel_di" 10035 [(set (match_operand:DI 0 "target_reg_operand" "=b") 10036 (plus:DI (match_operand:DI 1 "register_operand" "r") 10037 (pc))) 10038 (match_operand:DI 2 "" "")] 10039 "TARGET_SHMEDIA" 10040 "%O2: ptrel/u %1, %0" 10041 [(set_attr "type" "ptabs_media")]) 10042 10043(define_expand "builtin_setjmp_receiver" 10044 [(match_operand 0 "" "")] 10045 "flag_pic" 10046{ 10047 emit_insn (gen_GOTaddr2picreg ()); 10048 DONE; 10049}) 10050 10051(define_expand "call_site" 10052 [(unspec [(match_dup 0)] UNSPEC_CALLER)] 10053 "TARGET_SH1" 10054{ 10055 static HOST_WIDE_INT i = 0; 10056 operands[0] = GEN_INT (i); 10057 i++; 10058}) 10059 10060;; op0 = op1 + r12 but hide it before reload completed. See the comment 10061;; in symGOT_load expand. 10062(define_insn_and_split "chk_guard_add" 10063 [(set (match_operand:SI 0 "register_operand" "=&r") 10064 (unspec:SI [(match_operand:SI 1 "register_operand" "r") 10065 (reg:SI PIC_REG)] 10066 UNSPEC_CHKADD))] 10067 "TARGET_SH1" 10068 "#" 10069 "TARGET_SH1 && reload_completed" 10070 [(set (match_dup 0) (reg:SI PIC_REG)) 10071 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))] 10072 "" 10073 [(set_attr "type" "arith")]) 10074 10075(define_expand "sym_label2reg" 10076 [(set (match_operand:SI 0 "" "") 10077 (const:SI (unspec:SI [(match_operand:SI 1 "" "") 10078 (const (plus:SI (match_operand:SI 2 "" "") 10079 (const_int 2)))] 10080 UNSPEC_SYMOFF)))] 10081 "TARGET_SH1" "") 10082 10083(define_expand "symGOT_load" 10084 [(set (match_dup 2) (match_operand 1 "" "")) 10085 (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG))) 10086 (set (match_operand 0 "" "") (mem (match_dup 3)))] 10087 "" 10088{ 10089 rtx mem; 10090 10091 operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode); 10092 operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode); 10093 10094 if (TARGET_SHMEDIA) 10095 { 10096 rtx reg = operands[2]; 10097 10098 if (Pmode == DImode) 10099 { 10100 if (flag_pic > 1) 10101 emit_insn (gen_movdi_const_32bit (reg, operands[1])); 10102 else 10103 emit_insn (gen_movdi_const_16bit (reg, operands[1])); 10104 } 10105 else 10106 { 10107 if (flag_pic > 1) 10108 emit_insn (gen_movsi_const (reg, operands[1])); 10109 else 10110 emit_insn (gen_movsi_const_16bit (reg, operands[1])); 10111 } 10112 } 10113 else 10114 emit_move_insn (operands[2], operands[1]); 10115 10116 /* When stack protector inserts codes after the result is set to 10117 R0, @(rX, r12) will cause a spill failure for R0. Use a unspec 10118 insn to avoid combining (set A (plus rX r12)) and (set op0 (mem A)) 10119 when rX is a GOT address for the guard symbol. Ugly but doesn't 10120 matter because this is a rare situation. */ 10121 if (!TARGET_SHMEDIA 10122 && flag_stack_protect 10123 && GET_CODE (operands[1]) == CONST 10124 && GET_CODE (XEXP (operands[1], 0)) == UNSPEC 10125 && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == SYMBOL_REF 10126 && strcmp (XSTR (XVECEXP (XEXP (operands[1], 0), 0, 0), 0), 10127 "__stack_chk_guard") == 0) 10128 emit_insn (gen_chk_guard_add (operands[3], operands[2])); 10129 else 10130 emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2], 10131 gen_rtx_REG (Pmode, PIC_REG))); 10132 10133 /* N.B. This is not constant for a GOTPLT relocation. */ 10134 mem = gen_rtx_MEM (Pmode, operands[3]); 10135 MEM_NOTRAP_P (mem) = 1; 10136 /* ??? Should we have a special alias set for the GOT? */ 10137 emit_move_insn (operands[0], mem); 10138 10139 DONE; 10140}) 10141 10142(define_expand "sym2GOT" 10143 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))] 10144 "" 10145 "") 10146 10147(define_expand "symGOT2reg" 10148 [(match_operand 0 "" "") (match_operand 1 "" "")] 10149 "" 10150{ 10151 rtx gotsym, insn; 10152 10153 gotsym = gen_sym2GOT (operands[1]); 10154 PUT_MODE (gotsym, Pmode); 10155 insn = emit_insn (gen_symGOT_load (operands[0], gotsym)); 10156 10157 MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1; 10158 10159 DONE; 10160}) 10161 10162(define_expand "symGOTPLT2reg" 10163 [(match_operand 0 "" "") (match_operand 1 "" "")] 10164 "" 10165{ 10166 rtx pltsym = gen_rtx_CONST (Pmode, 10167 gen_rtx_UNSPEC (Pmode, 10168 gen_rtvec (1, operands[1]), 10169 UNSPEC_GOTPLT)); 10170 emit_insn (gen_symGOT_load (operands[0], pltsym)); 10171 DONE; 10172}) 10173 10174(define_expand "sym2GOTOFF" 10175 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))] 10176 "" 10177 "") 10178 10179(define_expand "symGOTOFF2reg" 10180 [(match_operand 0 "" "") (match_operand 1 "" "")] 10181 "" 10182{ 10183 rtx gotoffsym, insn; 10184 rtx t = (!can_create_pseudo_p () 10185 ? operands[0] 10186 : gen_reg_rtx (GET_MODE (operands[0]))); 10187 10188 gotoffsym = gen_sym2GOTOFF (operands[1]); 10189 PUT_MODE (gotoffsym, Pmode); 10190 emit_move_insn (t, gotoffsym); 10191 insn = emit_move_insn (operands[0], 10192 gen_rtx_PLUS (Pmode, t, 10193 gen_rtx_REG (Pmode, PIC_REG))); 10194 10195 set_unique_reg_note (insn, REG_EQUAL, operands[1]); 10196 10197 DONE; 10198}) 10199 10200(define_expand "symPLT_label2reg" 10201 [(set (match_operand:SI 0 "" "") 10202 (const:SI 10203 (unspec:SI 10204 [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT)) 10205 (const:SI (plus:SI (match_operand:SI 2 "" "") 10206 (const_int 2)))] UNSPEC_PCREL_SYMOFF))) 10207 ;; Even though the PIC register is not really used by the call 10208 ;; sequence in which this is expanded, the PLT code assumes the PIC 10209 ;; register is set, so we must not skip its initialization. Since 10210 ;; we only use this expand as part of calling sequences, and never 10211 ;; to take the address of a function, this is the best point to 10212 ;; insert the (use). Using the PLT to take the address of a 10213 ;; function would be wrong, not only because the PLT entry could 10214 ;; then be called from a function that doesn't initialize the PIC 10215 ;; register to the proper GOT, but also because pointers to the 10216 ;; same function might not compare equal, should they be set by 10217 ;; different shared libraries. 10218 (use (reg:SI PIC_REG))] 10219 "TARGET_SH1" 10220 "") 10221 10222(define_expand "sym2PIC" 10223 [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))] 10224 "" 10225 "") 10226 10227;; ------------------------------------------------------------------------- 10228;; TLS code generation. 10229 10230;; FIXME: The multi-insn asm blocks should be converted to use 10231;; define_insn_and_split. 10232;; See the thread [PATCH/RFA] SH TLS support on gcc-patches 10233;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html> 10234;; for details. 10235 10236(define_insn "tls_global_dynamic" 10237 [(set (match_operand:SI 0 "register_operand" "=&z") 10238 (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")] 10239 UNSPEC_TLSGD)) 10240 (const_int 0))) 10241 (use (reg:PSI FPSCR_REG)) 10242 (use (reg:SI PIC_REG)) 10243 (clobber (reg:SI PR_REG)) 10244 (clobber (scratch:SI))] 10245 "TARGET_SH1" 10246{ 10247 return "mov.l 1f,r4" "\n" 10248 " mova 2f,r0" "\n" 10249 " mov.l 2f,r1" "\n" 10250 " add r0,r1" "\n" 10251 " jsr @r1" "\n" 10252 " add r12,r4" "\n" 10253 " bra 3f" "\n" 10254 " nop" "\n" 10255 " .align 2" "\n" 10256 "1: .long %a1@TLSGD" "\n" 10257 "2: .long __tls_get_addr@PLT" "\n" 10258 "3:"; 10259} 10260 [(set_attr "type" "tls_load") 10261 (set_attr "length" "26")]) 10262 10263(define_insn "tls_local_dynamic" 10264 [(set (match_operand:SI 0 "register_operand" "=&z") 10265 (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")] 10266 UNSPEC_TLSLDM)) 10267 (const_int 0))) 10268 (use (reg:PSI FPSCR_REG)) 10269 (use (reg:SI PIC_REG)) 10270 (clobber (reg:SI PR_REG)) 10271 (clobber (scratch:SI))] 10272 "TARGET_SH1" 10273{ 10274 return "mov.l 1f,r4" "\n" 10275 " mova 2f,r0" "\n" 10276 " mov.l 2f,r1" "\n" 10277 " add r0,r1" "\n" 10278 " jsr @r1" "\n" 10279 " add r12,r4" "\n" 10280 " bra 3f" "\n" 10281 " nop" "\n" 10282 " .align 2" "\n" 10283 "1: .long %a1@TLSLDM" "\n" 10284 "2: .long __tls_get_addr@PLT" "\n" 10285 "3:"; 10286} 10287 [(set_attr "type" "tls_load") 10288 (set_attr "length" "26")]) 10289 10290(define_expand "sym2DTPOFF" 10291 [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))] 10292 "" 10293 "") 10294 10295(define_expand "symDTPOFF2reg" 10296 [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")] 10297 "" 10298{ 10299 rtx dtpoffsym; 10300 rtx t = (!can_create_pseudo_p () 10301 ? operands[0] 10302 : gen_reg_rtx (GET_MODE (operands[0]))); 10303 10304 dtpoffsym = gen_sym2DTPOFF (operands[1]); 10305 PUT_MODE (dtpoffsym, Pmode); 10306 emit_move_insn (t, dtpoffsym); 10307 emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, operands[2])); 10308 DONE; 10309}) 10310 10311(define_expand "sym2GOTTPOFF" 10312 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))] 10313 "" 10314 "") 10315 10316(define_insn "tls_initial_exec" 10317 [(set (match_operand:SI 0 "register_operand" "=&r") 10318 (unspec:SI [(match_operand:SI 1 "" "")] 10319 UNSPEC_TLSIE)) 10320 (use (reg:SI GBR_REG)) 10321 (use (reg:SI PIC_REG)) 10322 (clobber (reg:SI R0_REG))] 10323 "" 10324{ 10325 return "mov.l 1f,r0" "\n" 10326 " stc gbr,%0" "\n" 10327 " mov.l @(r0,r12),r0" "\n" 10328 " bra 2f" "\n" 10329 " add r0,%0" "\n" 10330 " .align 2" "\n" 10331 "1: .long %a1" "\n" 10332 "2:"; 10333} 10334 [(set_attr "type" "tls_load") 10335 (set_attr "length" "16")]) 10336 10337(define_expand "sym2TPOFF" 10338 [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))] 10339 "" 10340 "") 10341 10342(define_expand "symTPOFF2reg" 10343 [(match_operand 0 "" "") (match_operand 1 "" "")] 10344 "" 10345{ 10346 rtx tpoffsym; 10347 10348 tpoffsym = gen_sym2TPOFF (operands[1]); 10349 PUT_MODE (tpoffsym, Pmode); 10350 emit_move_insn (operands[0], tpoffsym); 10351 DONE; 10352}) 10353 10354;;------------------------------------------------------------------------------ 10355;; Thread pointer getter and setter. 10356;; 10357;; On SH the thread pointer is kept in the GBR. 10358;; These patterns are usually expanded from the respective built-in functions. 10359(define_expand "get_thread_pointersi" 10360 [(set (match_operand:SI 0 "register_operand") (reg:SI GBR_REG))] 10361 "TARGET_SH1") 10362 10363;; The store_gbr insn can also be used on !TARGET_SH1 for doing TLS accesses. 10364(define_insn "store_gbr" 10365 [(set (match_operand:SI 0 "register_operand" "=r") (reg:SI GBR_REG))] 10366 "" 10367 "stc gbr,%0" 10368 [(set_attr "type" "tls_load")]) 10369 10370(define_expand "set_thread_pointersi" 10371 [(set (reg:SI GBR_REG) 10372 (unspec_volatile:SI [(match_operand:SI 0 "register_operand")] 10373 UNSPECV_GBR))] 10374 "TARGET_SH1") 10375 10376(define_insn "load_gbr" 10377 [(set (reg:SI GBR_REG) 10378 (unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] 10379 UNSPECV_GBR))] 10380 "TARGET_SH1" 10381 "ldc %0,gbr" 10382 [(set_attr "type" "move")]) 10383 10384;;------------------------------------------------------------------------------ 10385;; Thread pointer relative memory loads and stores. 10386;; 10387;; On SH there are GBR displacement address modes which can be utilized to 10388;; access memory behind the thread pointer. 10389;; Since we do not allow using GBR for general purpose memory accesses, these 10390;; GBR addressing modes are formed by the combine pass. 10391;; This could be done with fewer patterns than below by using a mem predicate 10392;; for the GBR mem, but then reload would try to reload addresses with a 10393;; zero displacement for some strange reason. 10394 10395(define_insn "*mov<mode>_gbr_load" 10396 [(set (match_operand:QIHISI 0 "register_operand" "=z") 10397 (mem:QIHISI (plus:SI (reg:SI GBR_REG) 10398 (match_operand:QIHISI 1 "gbr_displacement"))))] 10399 "TARGET_SH1" 10400 "mov.<bwl> @(%O1,gbr),%0" 10401 [(set_attr "type" "load")]) 10402 10403(define_insn "*mov<mode>_gbr_load" 10404 [(set (match_operand:QIHISI 0 "register_operand" "=z") 10405 (mem:QIHISI (reg:SI GBR_REG)))] 10406 "TARGET_SH1" 10407 "mov.<bwl> @(0,gbr),%0" 10408 [(set_attr "type" "load")]) 10409 10410(define_insn "*mov<mode>_gbr_load" 10411 [(set (match_operand:SI 0 "register_operand" "=z") 10412 (sign_extend:SI 10413 (mem:QIHI (plus:SI (reg:SI GBR_REG) 10414 (match_operand:QIHI 1 "gbr_displacement")))))] 10415 "TARGET_SH1" 10416 "mov.<bw> @(%O1,gbr),%0" 10417 [(set_attr "type" "load")]) 10418 10419(define_insn "*mov<mode>_gbr_load" 10420 [(set (match_operand:SI 0 "register_operand" "=z") 10421 (sign_extend:SI (mem:QIHI (reg:SI GBR_REG))))] 10422 "TARGET_SH1" 10423 "mov.<bw> @(0,gbr),%0" 10424 [(set_attr "type" "load")]) 10425 10426(define_insn "*mov<mode>_gbr_store" 10427 [(set (mem:QIHISI (plus:SI (reg:SI GBR_REG) 10428 (match_operand:QIHISI 0 "gbr_displacement"))) 10429 (match_operand:QIHISI 1 "register_operand" "z"))] 10430 "TARGET_SH1" 10431 "mov.<bwl> %1,@(%O0,gbr)" 10432 [(set_attr "type" "store")]) 10433 10434(define_insn "*mov<mode>_gbr_store" 10435 [(set (mem:QIHISI (reg:SI GBR_REG)) 10436 (match_operand:QIHISI 0 "register_operand" "z"))] 10437 "TARGET_SH1" 10438 "mov.<bwl> %0,@(0,gbr)" 10439 [(set_attr "type" "store")]) 10440 10441;; DImode memory accesses have to be split in two SImode accesses. 10442;; Split them before reload, so that it gets a better chance to figure out 10443;; how to deal with the R0 restriction for the individual SImode accesses. 10444;; Do not match this insn during or after reload because it can't be split 10445;; afterwards. 10446(define_insn_and_split "*movdi_gbr_load" 10447 [(set (match_operand:DI 0 "register_operand") 10448 (match_operand:DI 1 "gbr_address_mem"))] 10449 "TARGET_SH1 && can_create_pseudo_p ()" 10450 "#" 10451 "&& 1" 10452 [(set (match_dup 3) (match_dup 5)) 10453 (set (match_dup 4) (match_dup 6))] 10454{ 10455 /* Swap low/high part load order on little endian, so that the result reg 10456 of the second load can be used better. */ 10457 int off = TARGET_LITTLE_ENDIAN ? 1 : 0; 10458 operands[3 + off] = gen_lowpart (SImode, operands[0]); 10459 operands[5 + off] = gen_lowpart (SImode, operands[1]); 10460 operands[4 - off] = gen_highpart (SImode, operands[0]); 10461 operands[6 - off] = gen_highpart (SImode, operands[1]); 10462}) 10463 10464(define_insn_and_split "*movdi_gbr_store" 10465 [(set (match_operand:DI 0 "gbr_address_mem") 10466 (match_operand:DI 1 "register_operand"))] 10467 "TARGET_SH1 && can_create_pseudo_p ()" 10468 "#" 10469 "&& 1" 10470 [(set (match_dup 3) (match_dup 5)) 10471 (set (match_dup 4) (match_dup 6))] 10472{ 10473 /* Swap low/high part store order on big endian, so that stores of function 10474 call results can save a reg copy. */ 10475 int off = TARGET_LITTLE_ENDIAN ? 0 : 1; 10476 operands[3 + off] = gen_lowpart (SImode, operands[0]); 10477 operands[5 + off] = gen_lowpart (SImode, operands[1]); 10478 operands[4 - off] = gen_highpart (SImode, operands[0]); 10479 operands[6 - off] = gen_highpart (SImode, operands[1]); 10480}) 10481 10482;; Sometimes memory accesses do not get combined with the store_gbr insn, 10483;; in particular when the displacements are in the range of the regular move 10484;; insns. Thus, in the first split pass after the combine pass we search 10485;; for missed opportunities and try to fix them up ourselves. 10486;; If an equivalent GBR address can be determined the load / store is split 10487;; into one of the GBR load / store patterns. 10488;; All of that must happen before reload (GBR address modes use R0 as the 10489;; other operand) and there's no point of doing it if the GBR is not 10490;; referenced in a function at all. 10491(define_split 10492 [(set (match_operand:QIHISIDI 0 "register_operand") 10493 (match_operand:QIHISIDI 1 "memory_operand"))] 10494 "TARGET_SH1 && !reload_in_progress && !reload_completed 10495 && df_regs_ever_live_p (GBR_REG)" 10496 [(set (match_dup 0) (match_dup 1))] 10497{ 10498 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]); 10499 if (gbr_mem != NULL_RTX) 10500 operands[1] = replace_equiv_address (operands[1], gbr_mem); 10501 else 10502 FAIL; 10503}) 10504 10505(define_split 10506 [(set (match_operand:SI 0 "register_operand") 10507 (sign_extend:SI (match_operand:QIHI 1 "memory_operand")))] 10508 "TARGET_SH1 && !reload_in_progress && !reload_completed 10509 && df_regs_ever_live_p (GBR_REG)" 10510 [(set (match_dup 0) (sign_extend:SI (match_dup 1)))] 10511{ 10512 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]); 10513 if (gbr_mem != NULL_RTX) 10514 operands[1] = replace_equiv_address (operands[1], gbr_mem); 10515 else 10516 FAIL; 10517}) 10518 10519;; On SH2A we've got movu.b and movu.w for doing zero-extending mem loads. 10520;; Split those so that a GBR load can be used. 10521(define_split 10522 [(set (match_operand:SI 0 "register_operand") 10523 (zero_extend:SI (match_operand:QIHI 1 "memory_operand")))] 10524 "TARGET_SH2A && !reload_in_progress && !reload_completed 10525 && df_regs_ever_live_p (GBR_REG)" 10526 [(set (match_dup 2) (match_dup 1)) 10527 (set (match_dup 0) (zero_extend:SI (match_dup 2)))] 10528{ 10529 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]); 10530 if (gbr_mem != NULL_RTX) 10531 { 10532 operands[2] = gen_reg_rtx (GET_MODE (operands[1])); 10533 operands[1] = replace_equiv_address (operands[1], gbr_mem); 10534 } 10535 else 10536 FAIL; 10537}) 10538 10539(define_split 10540 [(set (match_operand:QIHISIDI 0 "memory_operand") 10541 (match_operand:QIHISIDI 1 "register_operand"))] 10542 "TARGET_SH1 && !reload_in_progress && !reload_completed 10543 && df_regs_ever_live_p (GBR_REG)" 10544 [(set (match_dup 0) (match_dup 1))] 10545{ 10546 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[0]); 10547 if (gbr_mem != NULL_RTX) 10548 operands[0] = replace_equiv_address (operands[0], gbr_mem); 10549 else 10550 FAIL; 10551}) 10552 10553;;------------------------------------------------------------------------------ 10554;; case instruction for switch statements. 10555 10556;; operand 0 is index 10557;; operand 1 is the minimum bound 10558;; operand 2 is the maximum bound - minimum bound + 1 10559;; operand 3 is CODE_LABEL for the table; 10560;; operand 4 is the CODE_LABEL to go to if index out of range. 10561(define_expand "casesi" 10562 [(match_operand:SI 0 "arith_reg_operand" "") 10563 (match_operand:SI 1 "arith_reg_operand" "") 10564 (match_operand:SI 2 "arith_reg_operand" "") 10565 (match_operand 3 "" "") (match_operand 4 "" "")] 10566 "" 10567{ 10568 rtx reg = gen_reg_rtx (SImode); 10569 rtx reg2 = gen_reg_rtx (SImode); 10570 if (TARGET_SHMEDIA) 10571 { 10572 rtx reg = gen_reg_rtx (DImode); 10573 rtx reg2 = gen_reg_rtx (DImode); 10574 rtx reg3 = gen_reg_rtx (Pmode); 10575 rtx reg4 = gen_reg_rtx (Pmode); 10576 rtx reg5 = gen_reg_rtx (Pmode); 10577 rtx load, test; 10578 10579 operands[0] = convert_modes (DImode, SImode, operands[0], 0); 10580 operands[1] = convert_modes (DImode, SImode, operands[1], 0); 10581 operands[2] = convert_modes (DImode, SImode, operands[2], 1); 10582 10583 test = gen_rtx_GT (VOIDmode, operands[1], operands[0]); 10584 emit_jump_insn (gen_cbranchdi4 (test, operands[1], operands[0], 10585 operands[4])); 10586 emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1])); 10587 test = gen_rtx_GTU (VOIDmode, reg, operands[2]); 10588 emit_jump_insn (gen_cbranchdi4 (test, reg, operands[2], operands[4])); 10589 emit_insn (gen_casesi_shift_media (reg2, reg, operands[3])); 10590 emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF 10591 (Pmode, operands[3]))); 10592 /* Messy: can we subreg to clean this up? */ 10593 if (Pmode == DImode) 10594 load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]); 10595 else 10596 load = gen_casesi_load_media (reg4, 10597 gen_rtx_SUBREG (DImode, reg3, 0), 10598 reg2, operands[3]); 10599 PUT_MODE (SET_SRC (load), Pmode); 10600 emit_insn (load); 10601 /* ??? The following add could be eliminated if we used ptrel. */ 10602 emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4)); 10603 emit_jump_insn (gen_casesi_jump_media (reg5, operands[3])); 10604 emit_barrier (); 10605 DONE; 10606 } 10607 operands[1] = copy_to_mode_reg (SImode, operands[1]); 10608 operands[2] = copy_to_mode_reg (SImode, operands[2]); 10609 /* If optimizing, casesi_worker depends on the mode of the instruction 10610 before label it 'uses' - operands[3]. */ 10611 emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4], 10612 reg)); 10613 emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3])); 10614 if (TARGET_SH2) 10615 emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3])); 10616 else 10617 emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3])); 10618 /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to 10619 operands[3], but to lab. We will fix this up in 10620 machine_dependent_reorg. */ 10621 emit_barrier (); 10622 DONE; 10623}) 10624 10625(define_expand "casesi_0" 10626 [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" "")) 10627 (set (match_dup 4) (minus:SI (match_dup 4) 10628 (match_operand:SI 1 "arith_operand" ""))) 10629 (set (reg:SI T_REG) 10630 (gtu:SI (match_dup 4) 10631 (match_operand:SI 2 "arith_reg_operand" ""))) 10632 (set (pc) 10633 (if_then_else (ne (reg:SI T_REG) 10634 (const_int 0)) 10635 (label_ref (match_operand 3 "" "")) 10636 (pc)))] 10637 "TARGET_SH1" 10638 "") 10639 10640;; ??? reload might clobber r0 if we use it explicitly in the RTL before 10641;; reload; using a R0_REGS pseudo reg is likely to give poor code. 10642;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload. 10643(define_insn "casesi_worker_0" 10644 [(set (match_operand:SI 0 "register_operand" "=r,r") 10645 (unspec:SI [(match_operand:SI 1 "register_operand" "0,r") 10646 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI)) 10647 (clobber (match_scratch:SI 3 "=X,1")) 10648 (clobber (match_scratch:SI 4 "=&z,z"))] 10649 "TARGET_SH1" 10650 "#") 10651 10652(define_split 10653 [(set (match_operand:SI 0 "register_operand" "") 10654 (unspec:SI [(match_operand:SI 1 "register_operand" "") 10655 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI)) 10656 (clobber (match_scratch:SI 3 "")) 10657 (clobber (match_scratch:SI 4 ""))] 10658 "TARGET_SH1 && ! TARGET_SH2 && reload_completed" 10659 [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA)) 10660 (parallel [(set (match_dup 0) 10661 (unspec:SI [(reg:SI R0_REG) (match_dup 1) 10662 (label_ref (match_dup 2))] UNSPEC_CASESI)) 10663 (clobber (match_dup 3))]) 10664 (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))] 10665{ 10666 if (GET_CODE (operands[2]) == CODE_LABEL) 10667 LABEL_NUSES (operands[2])++; 10668}) 10669 10670(define_split 10671 [(set (match_operand:SI 0 "register_operand" "") 10672 (unspec:SI [(match_operand:SI 1 "register_operand" "") 10673 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI)) 10674 (clobber (match_scratch:SI 3 "")) 10675 (clobber (match_scratch:SI 4 ""))] 10676 "TARGET_SH2 && reload_completed" 10677 [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA)) 10678 (parallel [(set (match_dup 0) 10679 (unspec:SI [(reg:SI R0_REG) (match_dup 1) 10680 (label_ref (match_dup 2))] UNSPEC_CASESI)) 10681 (clobber (match_dup 3))])] 10682{ 10683 if (GET_CODE (operands[2]) == CODE_LABEL) 10684 LABEL_NUSES (operands[2])++; 10685}) 10686 10687(define_insn "casesi_worker_1" 10688 [(set (match_operand:SI 0 "register_operand" "=r,r") 10689 (unspec:SI [(reg:SI R0_REG) 10690 (match_operand:SI 1 "register_operand" "0,r") 10691 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI)) 10692 (clobber (match_scratch:SI 3 "=X,1"))] 10693 "TARGET_SH1" 10694{ 10695 rtx diff_vec = PATTERN (next_real_insn (operands[2])); 10696 10697 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); 10698 10699 switch (GET_MODE (diff_vec)) 10700 { 10701 case SImode: 10702 return "shll2 %1" "\n" 10703 " mov.l @(r0,%1),%0"; 10704 case HImode: 10705 return "add %1,%1" "\n" 10706 " mov.w @(r0,%1),%0"; 10707 case QImode: 10708 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned) 10709 return "mov.b @(r0,%1),%0" "\n" 10710 " extu.b %0,%0"; 10711 else 10712 return "mov.b @(r0,%1),%0"; 10713 10714 default: 10715 gcc_unreachable (); 10716 } 10717} 10718 [(set_attr "length" "4")]) 10719 10720(define_insn "casesi_worker_2" 10721 [(set (match_operand:SI 0 "register_operand" "=r,r") 10722 (unspec:SI [(reg:SI R0_REG) 10723 (match_operand:SI 1 "register_operand" "0,r") 10724 (label_ref (match_operand 2 "" "")) 10725 (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI)) 10726 (clobber (match_operand:SI 4 "" "=X,1"))] 10727 "TARGET_SH2 && reload_completed && flag_pic" 10728{ 10729 rtx diff_vec = PATTERN (next_real_insn (operands[2])); 10730 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); 10731 10732 switch (GET_MODE (diff_vec)) 10733 { 10734 case SImode: 10735 return "shll2 %1" "\n" 10736 " add r0,%1" "\n" 10737 " mova %O3,r0" "\n" 10738 " mov.l @(r0,%1),%0"; 10739 case HImode: 10740 return "add %1,%1" "\n" 10741 " add r0,%1" "\n" 10742 " mova %O3,r0" "\n" 10743 " mov.w @(r0,%1),%0"; 10744 case QImode: 10745 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned) 10746 return "add r0,%1" "\n" 10747 " mova %O3,r0" "\n" 10748 " mov.b @(r0,%1),%0" "\n" 10749 " extu.b %0,%0"; 10750 else 10751 return "add r0,%1" "\n" 10752 " mova %O3,r0" "\n" 10753 " mov.b @(r0,%1),%0"; 10754 default: 10755 gcc_unreachable (); 10756 } 10757} 10758 [(set_attr "length" "8")]) 10759 10760(define_insn "casesi_shift_media" 10761 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 10762 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r") 10763 (unspec:DI [(label_ref:DI (match_operand 2 "" ""))] 10764 UNSPEC_CASESI)))] 10765 "TARGET_SHMEDIA" 10766{ 10767 rtx diff_vec = PATTERN (next_real_insn (operands[2])); 10768 10769 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); 10770 10771 switch (GET_MODE (diff_vec)) 10772 { 10773 case SImode: 10774 return "shlli %1, 2, %0"; 10775 case HImode: 10776 return "shlli %1, 1, %0"; 10777 case QImode: 10778 if (rtx_equal_p (operands[0], operands[1])) 10779 return ""; 10780 return "add %1, r63, %0"; 10781 default: 10782 gcc_unreachable (); 10783 } 10784} 10785 [(set_attr "type" "arith_media")]) 10786 10787(define_insn "casesi_load_media" 10788 [(set (match_operand 0 "any_arith_reg_dest" "=r") 10789 (mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r") 10790 (match_operand:DI 2 "arith_reg_operand" "r") 10791 (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))] 10792 "TARGET_SHMEDIA" 10793{ 10794 rtx diff_vec = PATTERN (next_real_insn (operands[3])); 10795 10796 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); 10797 10798 switch (GET_MODE (diff_vec)) 10799 { 10800 case SImode: 10801 return "ldx.l %1, %2, %0"; 10802 case HImode: 10803#if 0 10804 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned) 10805 return "ldx.uw %1, %2, %0"; 10806#endif 10807 return "ldx.w %1, %2, %0"; 10808 case QImode: 10809 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned) 10810 return "ldx.ub %1, %2, %0"; 10811 return "ldx.b %1, %2, %0"; 10812 default: 10813 gcc_unreachable (); 10814 } 10815} 10816 [(set_attr "type" "load_media")]) 10817 10818(define_expand "simple_return" 10819 [(simple_return)] 10820 "sh_can_use_simple_return_p ()") 10821 10822(define_expand "return" 10823 [(return)] 10824 "reload_completed && epilogue_completed" 10825{ 10826 if (TARGET_SHMEDIA) 10827 { 10828 emit_jump_insn (gen_return_media ()); 10829 DONE; 10830 } 10831 10832 if (TARGET_SHCOMPACT 10833 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))) 10834 { 10835 emit_jump_insn (gen_shcompact_return_tramp ()); 10836 DONE; 10837 } 10838}) 10839 10840(define_insn "*<code>_i" 10841 [(any_return)] 10842 "TARGET_SH1 && ! (TARGET_SHCOMPACT 10843 && (crtl->args.info.call_cookie 10844 & CALL_COOKIE_RET_TRAMP (1))) 10845 && reload_completed 10846 && ! sh_cfun_trap_exit_p ()" 10847{ 10848 if (TARGET_SH2A && (dbr_sequence_length () == 0) 10849 && !current_function_interrupt) 10850 return "rts/n"; 10851 else 10852 return "%@ %#"; 10853} 10854 [(set_attr "type" "return") 10855 (set_attr "needs_delay_slot" "yes")]) 10856 10857;; trapa has no delay slot. 10858(define_insn "*return_trapa" 10859 [(return)] 10860 "TARGET_SH1 && !TARGET_SHCOMPACT 10861 && reload_completed" 10862 "%@" 10863 [(set_attr "type" "return")]) 10864 10865(define_expand "shcompact_return_tramp" 10866 [(return)] 10867 "TARGET_SHCOMPACT 10868 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))" 10869{ 10870 rtx reg = gen_rtx_REG (Pmode, R0_REG); 10871 10872 function_symbol (reg, "__GCC_shcompact_return_trampoline", SFUNC_STATIC); 10873 emit_jump_insn (gen_shcompact_return_tramp_i ()); 10874 DONE; 10875}) 10876 10877(define_insn "shcompact_return_tramp_i" 10878 [(parallel [(return) (use (reg:SI R0_REG))])] 10879 "TARGET_SHCOMPACT 10880 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))" 10881 "jmp @r0%#" 10882 [(set_attr "type" "jump_ind") 10883 (set_attr "needs_delay_slot" "yes")]) 10884 10885(define_insn "return_media_i" 10886 [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])] 10887 "TARGET_SHMEDIA && reload_completed" 10888 "blink %0, r63" 10889 [(set_attr "type" "jump_media")]) 10890 10891(define_insn "return_media_rte" 10892 [(return)] 10893 "TARGET_SHMEDIA && reload_completed && current_function_interrupt" 10894 "rte" 10895 [(set_attr "type" "jump_media")]) 10896 10897(define_expand "return_media" 10898 [(return)] 10899 "TARGET_SHMEDIA && reload_completed" 10900{ 10901 int tr_regno = sh_media_register_for_return (); 10902 rtx tr; 10903 10904 if (current_function_interrupt) 10905 { 10906 emit_jump_insn (gen_return_media_rte ()); 10907 DONE; 10908 } 10909 if (tr_regno < 0) 10910 { 10911 rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG); 10912 10913 gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]); 10914 tr_regno = TR0_REG; 10915 tr = gen_rtx_REG (Pmode, tr_regno); 10916 emit_move_insn (tr, r18); 10917 } 10918 else 10919 tr = gen_rtx_REG (Pmode, tr_regno); 10920 10921 emit_jump_insn (gen_return_media_i (tr)); 10922 DONE; 10923}) 10924 10925(define_insn "shcompact_preserve_incoming_args" 10926 [(set (match_operand:SI 0 "register_operand" "+r") 10927 (unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))] 10928 "TARGET_SHCOMPACT" 10929 "" 10930 [(set_attr "length" "0")]) 10931 10932(define_insn "shcompact_incoming_args" 10933 [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS)) 10934 (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS)) 10935 (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS)) 10936 (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS)) 10937 (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS)) 10938 (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS)) 10939 (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS)) 10940 (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS)) 10941 (set (mem:BLK (reg:SI MACL_REG)) 10942 (unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS)) 10943 (use (reg:SI R0_REG)) 10944 (clobber (reg:SI R0_REG)) 10945 (clobber (reg:SI MACL_REG)) 10946 (clobber (reg:SI MACH_REG)) 10947 (clobber (reg:SI PR_REG))] 10948 "TARGET_SHCOMPACT" 10949 "jsr @r0%#" 10950 [(set_attr "needs_delay_slot" "yes")]) 10951 10952(define_insn "shmedia_save_restore_regs_compact" 10953 [(set (reg:SI SP_REG) 10954 (plus:SI (reg:SI SP_REG) 10955 (match_operand:SI 0 "immediate_operand" "i"))) 10956 (use (reg:SI R0_REG)) 10957 (clobber (reg:SI PR_REG))] 10958 "TARGET_SHCOMPACT 10959 && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST () 10960 || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())" 10961 "jsr @r0%#" 10962 [(set_attr "needs_delay_slot" "yes")]) 10963 10964(define_expand "prologue" 10965 [(const_int 0)] 10966 "" 10967{ 10968 sh_expand_prologue (); 10969 DONE; 10970}) 10971 10972(define_expand "epilogue" 10973 [(return)] 10974 "" 10975{ 10976 sh_expand_epilogue (false); 10977 if (TARGET_SHMEDIA 10978 || (TARGET_SHCOMPACT 10979 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))) 10980 { 10981 emit_jump_insn (gen_return ()); 10982 DONE; 10983 } 10984}) 10985 10986(define_expand "eh_return" 10987 [(use (match_operand 0 "register_operand" ""))] 10988 "" 10989{ 10990 rtx ra = operands[0]; 10991 10992 if (TARGET_SHMEDIA64) 10993 emit_insn (gen_eh_set_ra_di (ra)); 10994 else 10995 emit_insn (gen_eh_set_ra_si (ra)); 10996 10997 DONE; 10998}) 10999 11000;; Clobber the return address on the stack. We can't expand this 11001;; until we know where it will be put in the stack frame. 11002 11003(define_insn "eh_set_ra_si" 11004 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] 11005 UNSPECV_EH_RETURN) 11006 (clobber (match_scratch:SI 1 "=&r"))] 11007 "! TARGET_SHMEDIA64" 11008 "#") 11009 11010(define_insn "eh_set_ra_di" 11011 [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")] 11012 UNSPECV_EH_RETURN) 11013 (clobber (match_scratch:DI 1 "=&r"))] 11014 "TARGET_SHMEDIA64" 11015 "#") 11016 11017(define_split 11018 [(unspec_volatile [(match_operand 0 "register_operand" "")] 11019 UNSPECV_EH_RETURN) 11020 (clobber (match_scratch 1 ""))] 11021 "reload_completed" 11022 [(const_int 0)] 11023{ 11024 sh_set_return_address (operands[0], operands[1]); 11025 DONE; 11026}) 11027 11028(define_insn "blockage" 11029 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)] 11030 "" 11031 "" 11032 [(set_attr "length" "0")]) 11033 11034;; Define movml instructions for SH2A target. Currently they are 11035;; used to push and pop all banked registers only. 11036 11037(define_insn "movml_push_banked" 11038 [(set (match_operand:SI 0 "register_operand" "=r") 11039 (plus (match_dup 0) (const_int -32))) 11040 (set (mem:SI (plus:SI (match_dup 0) (const_int 28))) (reg:SI R7_REG)) 11041 (set (mem:SI (plus:SI (match_dup 0) (const_int 24))) (reg:SI R6_REG)) 11042 (set (mem:SI (plus:SI (match_dup 0) (const_int 20))) (reg:SI R5_REG)) 11043 (set (mem:SI (plus:SI (match_dup 0) (const_int 16))) (reg:SI R4_REG)) 11044 (set (mem:SI (plus:SI (match_dup 0) (const_int 12))) (reg:SI R3_REG)) 11045 (set (mem:SI (plus:SI (match_dup 0) (const_int 8))) (reg:SI R2_REG)) 11046 (set (mem:SI (plus:SI (match_dup 0) (const_int 4))) (reg:SI R1_REG)) 11047 (set (mem:SI (plus:SI (match_dup 0) (const_int 0))) (reg:SI R0_REG))] 11048 "TARGET_SH2A && REGNO (operands[0]) == 15" 11049 "movml.l r7,@-r15" 11050 [(set_attr "in_delay_slot" "no")]) 11051 11052(define_insn "movml_pop_banked" 11053 [(set (match_operand:SI 0 "register_operand" "=r") 11054 (plus (match_dup 0) (const_int 32))) 11055 (set (reg:SI R0_REG) (mem:SI (plus:SI (match_dup 0) (const_int -32)))) 11056 (set (reg:SI R1_REG) (mem:SI (plus:SI (match_dup 0) (const_int -28)))) 11057 (set (reg:SI R2_REG) (mem:SI (plus:SI (match_dup 0) (const_int -24)))) 11058 (set (reg:SI R3_REG) (mem:SI (plus:SI (match_dup 0) (const_int -20)))) 11059 (set (reg:SI R4_REG) (mem:SI (plus:SI (match_dup 0) (const_int -16)))) 11060 (set (reg:SI R5_REG) (mem:SI (plus:SI (match_dup 0) (const_int -12)))) 11061 (set (reg:SI R6_REG) (mem:SI (plus:SI (match_dup 0) (const_int -8)))) 11062 (set (reg:SI R7_REG) (mem:SI (plus:SI (match_dup 0) (const_int -4))))] 11063 "TARGET_SH2A && REGNO (operands[0]) == 15" 11064 "movml.l @r15+,r7" 11065 [(set_attr "in_delay_slot" "no")]) 11066 11067;; ------------------------------------------------------------------------ 11068;; Scc instructions 11069;; ------------------------------------------------------------------------ 11070 11071(define_insn "movt" 11072 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 11073 (match_operand:SI 1 "t_reg_operand"))] 11074 "TARGET_SH1" 11075 "movt %0" 11076 [(set_attr "type" "arith")]) 11077 11078(define_insn "movrt" 11079 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 11080 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))] 11081 "TARGET_SH2A" 11082 "movrt %0" 11083 [(set_attr "type" "arith")]) 11084 11085(define_expand "cstore4_media" 11086 [(set (match_operand:SI 0 "register_operand" "=r") 11087 (match_operator:SI 1 "sh_float_comparison_operator" 11088 [(match_operand 2 "logical_operand" "") 11089 (match_operand 3 "cmp_operand" "")]))] 11090 "TARGET_SHMEDIA" 11091{ 11092 enum machine_mode mode = GET_MODE (operands[2]); 11093 enum rtx_code code = GET_CODE (operands[1]); 11094 bool invert, swap; 11095 if (mode == VOIDmode) 11096 mode = GET_MODE (operands[3]); 11097 if (operands[2] == const0_rtx) 11098 { 11099 if (code == EQ || code == NE) 11100 operands[2] = operands[3], operands[3] = const0_rtx; 11101 } 11102 else 11103 operands[2] = force_reg (mode, operands[2]); 11104 if (operands[3] != const0_rtx) 11105 operands[3] = force_reg (mode, operands[3]); 11106 11107 switch (code) 11108 { 11109 case GEU: 11110 case GE: 11111 swap = invert = !FLOAT_MODE_P (mode); 11112 break; 11113 11114 case LEU: 11115 case LE: 11116 swap = FLOAT_MODE_P (mode), invert = !swap; 11117 break; 11118 11119 case LTU: 11120 case LT: 11121 swap = true, invert = false; 11122 break; 11123 11124 case GTU: 11125 case GT: 11126 case EQ: 11127 case UNORDERED: 11128 swap = invert = false; 11129 break; 11130 11131 case NE: 11132 swap = invert = true; 11133 break; 11134 11135 default: 11136 gcc_unreachable (); 11137 } 11138 11139 if (swap) 11140 { 11141 rtx tem = operands[2]; 11142 operands[2] = operands[3]; 11143 operands[3] = tem; 11144 code = swap_condition (code); 11145 } 11146 11147 if (invert) 11148 { 11149 rtx tem = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0]; 11150 code = reverse_condition (code); 11151 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]); 11152 emit_insn (gen_cstore4_media (tem, operands[1], 11153 operands[2], operands[3])); 11154 code = EQ; 11155 operands[2] = tem; 11156 operands[3] = const0_rtx; 11157 } 11158 11159 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]); 11160}) 11161 11162(define_expand "cstoresi4" 11163 [(set (match_operand:SI 0 "register_operand" "=r") 11164 (match_operator:SI 1 "comparison_operator" 11165 [(match_operand:SI 2 "cmpsi_operand" "") 11166 (match_operand:SI 3 "arith_operand" "")]))] 11167 "TARGET_SH1 || TARGET_SHMEDIA" 11168{ 11169 if (TARGET_SHMEDIA) 11170 { 11171 emit_insn (gen_cstore4_media (operands[0], operands[1], 11172 operands[2], operands[3])); 11173 DONE; 11174 } 11175 11176 if (sh_expand_t_scc (operands)) 11177 DONE; 11178 11179 if (! currently_expanding_to_rtl) 11180 FAIL; 11181 11182 sh_emit_compare_and_set (operands, SImode); 11183 DONE; 11184}) 11185 11186(define_expand "cstoredi4" 11187 [(set (match_operand:SI 0 "register_operand" "=r") 11188 (match_operator:SI 1 "comparison_operator" 11189 [(match_operand:DI 2 "arith_operand" "") 11190 (match_operand:DI 3 "arith_operand" "")]))] 11191 "TARGET_SH2 || TARGET_SHMEDIA" 11192{ 11193 if (TARGET_SHMEDIA) 11194 { 11195 emit_insn (gen_cstore4_media (operands[0], operands[1], 11196 operands[2], operands[3])); 11197 DONE; 11198 } 11199 11200 if (sh_expand_t_scc (operands)) 11201 DONE; 11202 11203 if (! currently_expanding_to_rtl) 11204 FAIL; 11205 11206 sh_emit_compare_and_set (operands, DImode); 11207 DONE; 11208}) 11209 11210;; Move the complement of the T reg to a reg. 11211;; On SH2A the movrt insn can be used. 11212;; On anything else than SH2A this has to be done with multiple instructions. 11213;; One obvious way would be: 11214;; cmp/eq ... 11215;; movt r0 11216;; xor #1,r0 11217;; 11218;; However, this puts pressure on r0 in most cases and thus the following is 11219;; more appealing: 11220;; cmp/eq ... 11221;; mov #-1,temp 11222;; negc temp,dest 11223;; 11224;; If the constant -1 can be CSE-ed or lifted out of a loop it effectively 11225;; becomes a one instruction operation. Moreover, care must be taken that 11226;; the insn can still be combined with inverted compare and branch code 11227;; around it. On the other hand, if a function returns the complement of 11228;; a previous comparison result in the T bit, the xor #1,r0 approach might 11229;; lead to better code. 11230(define_expand "movnegt" 11231 [(set (match_operand:SI 0 "arith_reg_dest" "") 11232 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))] 11233 "TARGET_SH1" 11234{ 11235 if (TARGET_SH2A) 11236 emit_insn (gen_movrt (operands[0], operands[1])); 11237 else 11238 { 11239 rtx val = force_reg (SImode, gen_int_mode (-1, SImode)); 11240 emit_insn (gen_movrt_negc (operands[0], operands[1], val)); 11241 } 11242 DONE; 11243}) 11244 11245(define_insn "movrt_negc" 11246 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 11247 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1))) 11248 (set (reg:SI T_REG) (const_int 1)) 11249 (use (match_operand:SI 2 "arith_reg_operand" "r"))] 11250 "TARGET_SH1" 11251 "negc %2,%0" 11252 [(set_attr "type" "arith")]) 11253 11254;; The -1 constant will not be CSE-ed for the *movrt_negc pattern, but the 11255;; pattern can be used by the combine pass. Using a scratch reg for the 11256;; -1 constant results in slightly better register allocations compared to 11257;; generating a pseudo reg before reload. 11258(define_insn_and_split "*movrt_negc" 11259 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 11260 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1))) 11261 (clobber (match_scratch:SI 2 "=r")) 11262 (clobber (reg:SI T_REG))] 11263 "TARGET_SH1 && ! TARGET_SH2A" 11264 "#" 11265 "&& reload_completed" 11266 [(set (match_dup 2) (const_int -1)) 11267 (parallel 11268 [(set (match_dup 0) (xor:SI (match_dup 1) (const_int 1))) 11269 (set (reg:SI T_REG) (const_int 1)) 11270 (use (match_dup 2))])]) 11271 11272;; Store the negated T bit in a reg using r0 and xor. This one doesn't 11273;; clobber the T bit, which is useful when storing the T bit and the 11274;; negated T bit in parallel. On SH2A the movrt insn can be used for that. 11275;; Usually we don't want this insn to be matched, except for cases where the 11276;; T bit clobber is really not appreciated. Hence the extra use on T_REG. 11277(define_insn_and_split "movrt_xor" 11278 [(set (match_operand:SI 0 "arith_reg_dest" "=z") 11279 (xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1))) 11280 (use (reg:SI T_REG))] 11281 "TARGET_SH1 && !TARGET_SH2A" 11282 "#" 11283 "&& reload_completed" 11284 [(set (match_dup 0) (reg:SI T_REG)) 11285 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))]) 11286 11287;; Store the T bit and the negated T bit in two regs in parallel. There is 11288;; no real insn to do that, but specifying this pattern will give combine 11289;; some opportunities. 11290(define_insn_and_split "*movt_movrt" 11291 [(parallel [(set (match_operand:SI 0 "arith_reg_dest") 11292 (match_operand:SI 1 "negt_reg_operand")) 11293 (set (match_operand:SI 2 "arith_reg_dest") 11294 (match_operand:SI 3 "t_reg_operand"))])] 11295 "TARGET_SH1" 11296 "#" 11297 "&& 1" 11298 [(const_int 0)] 11299{ 11300 rtx i = TARGET_SH2A 11301 ? gen_movrt (operands[0], get_t_reg_rtx ()) 11302 : gen_movrt_xor (operands[0], get_t_reg_rtx ()); 11303 11304 emit_insn (i); 11305 emit_insn (gen_movt (operands[2], get_t_reg_rtx ())); 11306 DONE; 11307}) 11308 11309(define_insn_and_split "*movt_movrt" 11310 [(parallel [(set (match_operand:SI 0 "arith_reg_dest") 11311 (match_operand:SI 1 "t_reg_operand")) 11312 (set (match_operand:SI 2 "arith_reg_dest") 11313 (match_operand:SI 3 "negt_reg_operand"))])] 11314 "TARGET_SH1" 11315 "#" 11316 "&& 1" 11317 [(parallel [(set (match_dup 2) (match_dup 3)) 11318 (set (match_dup 0) (match_dup 1))])]) 11319 11320;; Use negc to store the T bit in a MSB of a reg in the following way: 11321;; T = 1: 0x80000000 -> reg 11322;; T = 0: 0x7FFFFFFF -> reg 11323;; This works because 0 - 0x80000000 = 0x80000000. 11324(define_insn_and_split "*mov_t_msb_neg" 11325 [(set (match_operand:SI 0 "arith_reg_dest") 11326 (minus:SI (const_int -2147483648) ;; 0x80000000 11327 (match_operand 1 "t_reg_operand"))) 11328 (clobber (reg:SI T_REG))] 11329 "TARGET_SH1" 11330 "#" 11331 "&& can_create_pseudo_p ()" 11332 [(set (match_dup 2) (const_int -2147483648)) 11333 (parallel [(set (match_dup 0) (minus:SI (neg:SI (match_dup 2)) 11334 (reg:SI T_REG))) 11335 (clobber (reg:SI T_REG))])] 11336{ 11337 operands[2] = gen_reg_rtx (SImode); 11338}) 11339 11340;; These are essentially the same as above, but with the inverted T bit. 11341;; Combine recognizes the split patterns, but does not take them sometimes 11342;; if the T_REG clobber is specified. Instead it tries to split out the 11343;; T bit negation. Since these splits are supposed to be taken only by 11344;; combine, it will see the T_REG clobber of the *mov_t_msb_neg insn, so this 11345;; should be fine. 11346(define_split 11347 [(set (match_operand:SI 0 "arith_reg_dest") 11348 (plus:SI (match_operand 1 "negt_reg_operand") 11349 (const_int 2147483647)))] ;; 0x7fffffff 11350 "TARGET_SH1 && can_create_pseudo_p ()" 11351 [(parallel [(set (match_dup 0) 11352 (minus:SI (const_int -2147483648) (reg:SI T_REG))) 11353 (clobber (reg:SI T_REG))])]) 11354 11355(define_split 11356 [(set (match_operand:SI 0 "arith_reg_dest") 11357 (if_then_else:SI (match_operand 1 "t_reg_operand") 11358 (const_int 2147483647) ;; 0x7fffffff 11359 (const_int -2147483648)))] ;; 0x80000000 11360 "TARGET_SH1 && can_create_pseudo_p ()" 11361 [(parallel [(set (match_dup 0) 11362 (minus:SI (const_int -2147483648) (reg:SI T_REG))) 11363 (clobber (reg:SI T_REG))])]) 11364 11365;; The *negnegt pattern helps the combine pass to figure out how to fold 11366;; an explicit double T bit negation. 11367(define_insn_and_split "*negnegt" 11368 [(set (reg:SI T_REG) 11369 (eq:SI (match_operand 0 "negt_reg_operand" "") (const_int 0)))] 11370 "TARGET_SH1" 11371 "#" 11372 "" 11373 [(const_int 0)]) 11374 11375;; Store T bit as all zeros or ones in a reg. 11376(define_insn "mov_neg_si_t" 11377 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 11378 (neg:SI (match_operand 1 "t_reg_operand" "")))] 11379 "TARGET_SH1" 11380 "subc %0,%0" 11381 [(set_attr "type" "arith")]) 11382 11383;; Store negated T bit as all zeros or ones in a reg. 11384;; Use the following sequence: 11385;; subc Rn,Rn ! Rn = Rn - Rn - T; T = T 11386;; not Rn,Rn ! Rn = 0 - Rn 11387(define_split 11388 [(set (match_operand:SI 0 "arith_reg_dest" "") 11389 (neg:SI (match_operand 1 "negt_reg_operand" "")))] 11390 "TARGET_SH1" 11391 [(set (match_dup 0) (neg:SI (reg:SI T_REG))) 11392 (set (match_dup 0) (not:SI (match_dup 0)))]) 11393 11394;; The *movtt pattern eliminates redundant T bit to T bit moves / tests. 11395(define_insn_and_split "*movtt" 11396 [(set (reg:SI T_REG) 11397 (eq:SI (match_operand 0 "t_reg_operand" "") (const_int 1)))] 11398 "TARGET_SH1" 11399 "#" 11400 "" 11401 [(const_int 0)]) 11402 11403;; Invert the T bit. 11404;; On SH2A we can use the nott insn. On anything else this must be done with 11405;; multiple insns like: 11406;; movt Rn 11407;; tst Rn,Rn 11408(define_insn_and_split "nott" 11409 [(set (reg:SI T_REG) 11410 (xor:SI (match_operand:SI 0 "t_reg_operand" "") (const_int 1)))] 11411 "TARGET_SH1" 11412{ 11413 gcc_assert (TARGET_SH2A); 11414 return "nott"; 11415} 11416 "! TARGET_SH2A && can_create_pseudo_p ()" 11417 [(set (match_dup 0) (reg:SI T_REG)) 11418 (set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))] 11419{ 11420 operands[0] = gen_reg_rtx (SImode); 11421}) 11422 11423;; Store T bit as MSB in a reg. 11424;; T = 0: 0x00000000 -> reg 11425;; T = 1: 0x80000000 -> reg 11426(define_insn_and_split "*movt_msb" 11427 [(set (match_operand:SI 0 "arith_reg_dest") 11428 (mult:SI (match_operand:SI 1 "t_reg_operand") 11429 (const_int -2147483648))) ;; 0xffffffff80000000 11430 (clobber (reg:SI T_REG))] 11431 "TARGET_SH1" 11432 "#" 11433 "&& 1" 11434 [(set (match_dup 0) (ashift:SI (reg:SI T_REG) (const_int 31)))]) 11435 11436;; Store inverted T bit as MSB in a reg. 11437;; T = 0: 0x80000000 -> reg 11438;; T = 1: 0x00000000 -> reg 11439;; On SH2A we can get away without clobbering the T_REG. 11440(define_insn_and_split "*negt_msb" 11441 [(set (match_operand:SI 0 "arith_reg_dest") 11442 (match_operand:SI 1 "negt_reg_shl31_operand"))] 11443 "TARGET_SH2A" 11444 "#" 11445 "&& can_create_pseudo_p ()" 11446 [(const_int 0)] 11447{ 11448 rtx tmp = gen_reg_rtx (SImode); 11449 emit_insn (gen_movrt (tmp, get_t_reg_rtx ())); 11450 emit_insn (gen_rotrsi3 (operands[0], tmp, const1_rtx)); 11451 DONE; 11452}) 11453 11454(define_insn_and_split "*negt_msb" 11455 [(set (match_operand:SI 0 "arith_reg_dest") 11456 (match_operand:SI 1 "negt_reg_shl31_operand")) 11457 (clobber (reg:SI T_REG))] 11458 "TARGET_SH1 && !TARGET_SH2A" 11459 "#" 11460 "&& can_create_pseudo_p ()" 11461 [(const_int 0)] 11462{ 11463 rtx tmp = gen_reg_rtx (SImode); 11464 emit_move_insn (tmp, get_t_reg_rtx ()); 11465 emit_insn (gen_cmpeqsi_t (tmp, const0_rtx)); 11466 emit_insn (gen_rotcr (operands[0], tmp, get_t_reg_rtx ())); 11467 DONE; 11468}) 11469 11470;; The *cset_zero patterns convert optimizations such as 11471;; "if (test) x = 0;" 11472;; to 11473;; "x &= -(test == 0);" 11474;; back to conditional branch sequences if zero-displacement branches 11475;; are enabled. 11476;; FIXME: These patterns can be removed when conditional execution patterns 11477;; are implemented, since ifcvt will not perform these optimizations if 11478;; conditional execution is supported. 11479(define_insn "*cset_zero" 11480 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 11481 (and:SI (plus:SI (match_operand:SI 1 "t_reg_operand") 11482 (const_int -1)) 11483 (match_operand:SI 2 "arith_reg_operand" "0")))] 11484 "TARGET_SH1 && TARGET_ZDCBRANCH" 11485{ 11486 return "bf 0f" "\n" 11487 " mov #0,%0" "\n" 11488 "0:"; 11489} 11490 [(set_attr "type" "arith") ;; poor approximation 11491 (set_attr "length" "4")]) 11492 11493(define_insn "*cset_zero" 11494 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 11495 (if_then_else:SI (match_operand:SI 1 "t_reg_operand") 11496 (match_operand:SI 2 "arith_reg_operand" "0") 11497 (const_int 0)))] 11498 "TARGET_SH1 && TARGET_ZDCBRANCH" 11499{ 11500 return "bt 0f" "\n" 11501 " mov #0,%0" "\n" 11502 "0:"; 11503} 11504 [(set_attr "type" "arith") ;; poor approximation 11505 (set_attr "length" "4")]) 11506 11507(define_expand "cstoresf4" 11508 [(set (match_operand:SI 0 "register_operand" "=r") 11509 (match_operator:SI 1 "sh_float_comparison_operator" 11510 [(match_operand:SF 2 "arith_operand" "") 11511 (match_operand:SF 3 "arith_operand" "")]))] 11512 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 11513{ 11514 if (TARGET_SHMEDIA) 11515 { 11516 emit_insn (gen_cstore4_media (operands[0], operands[1], 11517 operands[2], operands[3])); 11518 DONE; 11519 } 11520 11521 if (! currently_expanding_to_rtl) 11522 FAIL; 11523 11524 sh_emit_compare_and_set (operands, SFmode); 11525 DONE; 11526}) 11527 11528(define_expand "cstoredf4" 11529 [(set (match_operand:SI 0 "register_operand" "=r") 11530 (match_operator:SI 1 "sh_float_comparison_operator" 11531 [(match_operand:DF 2 "arith_operand" "") 11532 (match_operand:DF 3 "arith_operand" "")]))] 11533 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 11534{ 11535 if (TARGET_SHMEDIA) 11536 { 11537 emit_insn (gen_cstore4_media (operands[0], operands[1], 11538 operands[2], operands[3])); 11539 DONE; 11540 } 11541 11542 if (! currently_expanding_to_rtl) 11543 FAIL; 11544 11545 sh_emit_compare_and_set (operands, DFmode); 11546 DONE; 11547}) 11548 11549;; ------------------------------------------------------------------------- 11550;; Instructions to cope with inline literal tables 11551;; ------------------------------------------------------------------------- 11552 11553;; 2 byte integer in line 11554(define_insn "consttable_2" 11555 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g") 11556 (match_operand 1 "" "")] 11557 UNSPECV_CONST2)] 11558 "" 11559{ 11560 if (operands[1] != const0_rtx) 11561 assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1); 11562 return ""; 11563} 11564 [(set_attr "length" "2") 11565 (set_attr "in_delay_slot" "no")]) 11566 11567;; 4 byte integer in line 11568(define_insn "consttable_4" 11569 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g") 11570 (match_operand 1 "" "")] 11571 UNSPECV_CONST4)] 11572 "" 11573{ 11574 if (operands[1] != const0_rtx) 11575 { 11576 assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1); 11577 mark_symbol_refs_as_used (operands[0]); 11578 } 11579 return ""; 11580} 11581 [(set_attr "length" "4") 11582 (set_attr "in_delay_slot" "no")]) 11583 11584;; 8 byte integer in line 11585(define_insn "consttable_8" 11586 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g") 11587 (match_operand 1 "" "")] 11588 UNSPECV_CONST8)] 11589 "" 11590{ 11591 if (operands[1] != const0_rtx) 11592 assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1); 11593 return ""; 11594} 11595 [(set_attr "length" "8") 11596 (set_attr "in_delay_slot" "no")]) 11597 11598;; 4 byte floating point 11599(define_insn "consttable_sf" 11600 [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g") 11601 (match_operand 1 "" "")] 11602 UNSPECV_CONST4)] 11603 "" 11604{ 11605 if (operands[1] != const0_rtx) 11606 { 11607 REAL_VALUE_TYPE d; 11608 REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]); 11609 assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode)); 11610 } 11611 return ""; 11612} 11613 [(set_attr "length" "4") 11614 (set_attr "in_delay_slot" "no")]) 11615 11616;; 8 byte floating point 11617(define_insn "consttable_df" 11618 [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g") 11619 (match_operand 1 "" "")] 11620 UNSPECV_CONST8)] 11621 "" 11622{ 11623 if (operands[1] != const0_rtx) 11624 { 11625 REAL_VALUE_TYPE d; 11626 REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]); 11627 assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode)); 11628 } 11629 return ""; 11630} 11631 [(set_attr "length" "8") 11632 (set_attr "in_delay_slot" "no")]) 11633 11634;; Alignment is needed for some constant tables; it may also be added for 11635;; Instructions at the start of loops, or after unconditional branches. 11636;; ??? We would get more accurate lengths if we did instruction 11637;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used 11638;; here is too conservative. 11639 11640;; align to a two byte boundary 11641(define_expand "align_2" 11642 [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)] 11643 "" 11644 "") 11645 11646;; Align to a four byte boundary. 11647;; align_4 and align_log are instructions for the starts of loops, or 11648;; after unconditional branches, which may take up extra room. 11649(define_expand "align_4" 11650 [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)] 11651 "" 11652 "") 11653 11654;; Align to a cache line boundary. 11655(define_insn "align_log" 11656 [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)] 11657 "" 11658 "" 11659 [(set_attr "length" "0") 11660 (set_attr "in_delay_slot" "no")]) 11661 11662;; Emitted at the end of the literal table, used to emit the 11663;; 32bit branch labels if needed. 11664(define_insn "consttable_end" 11665 [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)] 11666 "" 11667{ 11668 return output_jump_label_table (); 11669} 11670 [(set_attr "in_delay_slot" "no")]) 11671 11672;; Emitted at the end of the window in the literal table. 11673(define_insn "consttable_window_end" 11674 [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)] 11675 "" 11676 "" 11677 [(set_attr "length" "0") 11678 (set_attr "in_delay_slot" "no")]) 11679 11680;; ------------------------------------------------------------------------- 11681;; Misc 11682;; ------------------------------------------------------------------------- 11683 11684;; String/block move insn. 11685 11686(define_expand "movmemsi" 11687 [(parallel [(set (mem:BLK (match_operand:BLK 0 "" "")) 11688 (mem:BLK (match_operand:BLK 1 "" ""))) 11689 (use (match_operand:SI 2 "nonmemory_operand" "")) 11690 (use (match_operand:SI 3 "immediate_operand" "")) 11691 (clobber (reg:SI PR_REG)) 11692 (clobber (reg:SI R4_REG)) 11693 (clobber (reg:SI R5_REG)) 11694 (clobber (reg:SI R0_REG))])] 11695 "TARGET_SH1 && ! TARGET_SH5" 11696{ 11697 if(expand_block_move (operands)) 11698 DONE; 11699 else FAIL; 11700}) 11701 11702(define_insn "block_move_real" 11703 [(parallel [(set (mem:BLK (reg:SI R4_REG)) 11704 (mem:BLK (reg:SI R5_REG))) 11705 (use (match_operand:SI 0 "arith_reg_operand" "r")) 11706 (clobber (reg:SI PR_REG)) 11707 (clobber (reg:SI R0_REG))])] 11708 "TARGET_SH1 && ! TARGET_HARD_SH4" 11709 "jsr @%0%#" 11710 [(set_attr "type" "sfunc") 11711 (set_attr "needs_delay_slot" "yes")]) 11712 11713(define_insn "block_lump_real" 11714 [(parallel [(set (mem:BLK (reg:SI R4_REG)) 11715 (mem:BLK (reg:SI R5_REG))) 11716 (use (match_operand:SI 0 "arith_reg_operand" "r")) 11717 (use (reg:SI R6_REG)) 11718 (clobber (reg:SI PR_REG)) 11719 (clobber (reg:SI T_REG)) 11720 (clobber (reg:SI R4_REG)) 11721 (clobber (reg:SI R5_REG)) 11722 (clobber (reg:SI R6_REG)) 11723 (clobber (reg:SI R0_REG))])] 11724 "TARGET_SH1 && ! TARGET_HARD_SH4" 11725 "jsr @%0%#" 11726 [(set_attr "type" "sfunc") 11727 (set_attr "needs_delay_slot" "yes")]) 11728 11729(define_insn "block_move_real_i4" 11730 [(parallel [(set (mem:BLK (reg:SI R4_REG)) 11731 (mem:BLK (reg:SI R5_REG))) 11732 (use (match_operand:SI 0 "arith_reg_operand" "r")) 11733 (clobber (reg:SI PR_REG)) 11734 (clobber (reg:SI R0_REG)) 11735 (clobber (reg:SI R1_REG)) 11736 (clobber (reg:SI R2_REG))])] 11737 "TARGET_HARD_SH4" 11738 "jsr @%0%#" 11739 [(set_attr "type" "sfunc") 11740 (set_attr "needs_delay_slot" "yes")]) 11741 11742(define_insn "block_lump_real_i4" 11743 [(parallel [(set (mem:BLK (reg:SI R4_REG)) 11744 (mem:BLK (reg:SI R5_REG))) 11745 (use (match_operand:SI 0 "arith_reg_operand" "r")) 11746 (use (reg:SI R6_REG)) 11747 (clobber (reg:SI PR_REG)) 11748 (clobber (reg:SI T_REG)) 11749 (clobber (reg:SI R4_REG)) 11750 (clobber (reg:SI R5_REG)) 11751 (clobber (reg:SI R6_REG)) 11752 (clobber (reg:SI R0_REG)) 11753 (clobber (reg:SI R1_REG)) 11754 (clobber (reg:SI R2_REG)) 11755 (clobber (reg:SI R3_REG))])] 11756 "TARGET_HARD_SH4" 11757 "jsr @%0%#" 11758 [(set_attr "type" "sfunc") 11759 (set_attr "needs_delay_slot" "yes")]) 11760 11761;; ------------------------------------------------------------------------- 11762;; Floating point instructions. 11763;; ------------------------------------------------------------------------- 11764 11765;; ??? All patterns should have a type attribute. 11766 11767(define_expand "movpsi" 11768 [(set (match_operand:PSI 0 "register_operand" "") 11769 (match_operand:PSI 1 "general_movsrc_operand" ""))] 11770 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 11771 "") 11772 11773;; The c / m alternative is a fake to guide reload to load directly into 11774;; fpscr, since reload doesn't know how to use post-increment. 11775;; TARGET_LEGITIMATE_ADDRESS_P guards about bogus addresses before reload, 11776;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's 11777;; predicate after reload. 11778;; The mac_gp type for r/!c might look a bit odd, but it actually schedules 11779;; like a mac -> gpr move. 11780(define_insn "fpu_switch" 11781 [(set (match_operand:PSI 0 "general_movdst_operand" "=c,c,r,c,c,r,m,r,<") 11782 (match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c,c"))] 11783 "TARGET_SH2E 11784 && (! reload_completed 11785 || true_regnum (operands[0]) != FPSCR_REG 11786 || !MEM_P (operands[1]) 11787 || GET_CODE (XEXP (operands[1], 0)) != PLUS)" 11788 "@ 11789 ! precision stays the same 11790 lds.l %1,fpscr 11791 mov.l %1,%0 11792 # 11793 lds %1,fpscr 11794 mov %1,%0 11795 mov.l %1,%0 11796 sts fpscr,%0 11797 sts.l fpscr,%0" 11798 [(set_attr "length" "0,2,2,4,2,2,2,2,2") 11799 (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store, 11800 mac_gp,fstore")]) 11801 11802(define_peephole2 11803 [(set (reg:PSI FPSCR_REG) 11804 (mem:PSI (match_operand:SI 0 "register_operand" "")))] 11805 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && peep2_reg_dead_p (1, operands[0])" 11806 [(const_int 0)] 11807{ 11808 rtx fpscr, mem, new_insn; 11809 11810 fpscr = SET_DEST (PATTERN (curr_insn)); 11811 mem = SET_SRC (PATTERN (curr_insn)); 11812 mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0])); 11813 11814 new_insn = emit_insn (gen_fpu_switch (fpscr, mem)); 11815 add_reg_note (new_insn, REG_INC, operands[0]); 11816 DONE; 11817}) 11818 11819(define_split 11820 [(set (reg:PSI FPSCR_REG) 11821 (mem:PSI (match_operand:SI 0 "register_operand" "")))] 11822 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) 11823 && (flag_peephole2 ? epilogue_completed : reload_completed)" 11824 [(const_int 0)] 11825{ 11826 rtx fpscr, mem, new_insn; 11827 11828 fpscr = SET_DEST (PATTERN (curr_insn)); 11829 mem = SET_SRC (PATTERN (curr_insn)); 11830 mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0])); 11831 11832 new_insn = emit_insn (gen_fpu_switch (fpscr, mem)); 11833 add_reg_note (new_insn, REG_INC, operands[0]); 11834 11835 if (!find_regno_note (curr_insn, REG_DEAD, true_regnum (operands[0]))) 11836 emit_insn (gen_addsi3 (operands[0], operands[0], GEN_INT (-4))); 11837 DONE; 11838}) 11839 11840;; ??? This uses the fp unit, but has no type indicating that. 11841;; If we did that, this would either give a bogus latency or introduce 11842;; a bogus FIFO constraint. 11843;; Since this insn is currently only used for prologues/epilogues, 11844;; it is probably best to claim no function unit, which matches the 11845;; current setting. 11846(define_insn "toggle_sz" 11847 [(set (reg:PSI FPSCR_REG) 11848 (xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))] 11849 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 11850 "fschg" 11851 [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")]) 11852 11853;; There's no way we can use it today, since optimize mode switching 11854;; doesn't enable us to know from which mode we're switching to the 11855;; mode it requests, to tell whether we can use a relative mode switch 11856;; (like toggle_pr) or an absolute switch (like loading fpscr from 11857;; memory). 11858(define_insn "toggle_pr" 11859 [(set (reg:PSI FPSCR_REG) 11860 (xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))] 11861 "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE" 11862 "fpchg" 11863 [(set_attr "type" "fpscr_toggle")]) 11864 11865(define_expand "addsf3" 11866 [(set (match_operand:SF 0 "arith_reg_operand" "") 11867 (plus:SF (match_operand:SF 1 "arith_reg_operand" "") 11868 (match_operand:SF 2 "arith_reg_operand" "")))] 11869 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 11870{ 11871 if (TARGET_SH2E) 11872 { 11873 expand_sf_binop (&gen_addsf3_i, operands); 11874 DONE; 11875 } 11876}) 11877 11878(define_insn "*addsf3_media" 11879 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 11880 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f") 11881 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 11882 "TARGET_SHMEDIA_FPU" 11883 "fadd.s %1, %2, %0" 11884 [(set_attr "type" "fparith_media")]) 11885 11886(define_insn_and_split "unary_sf_op" 11887 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f") 11888 (vec_select:V2SF 11889 (vec_concat:V2SF 11890 (vec_select:SF 11891 (match_dup 0) 11892 (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))])) 11893 (match_operator:SF 2 "unary_float_operator" 11894 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f") 11895 (parallel [(match_operand 4 11896 "const_int_operand" "n")]))])) 11897 (parallel [(not:BI (match_dup 3)) (match_dup 3)])))] 11898 "TARGET_SHMEDIA_FPU" 11899 "#" 11900 "TARGET_SHMEDIA_FPU && reload_completed" 11901 [(set (match_dup 5) (match_dup 6))] 11902{ 11903 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1; 11904 rtx op1 = gen_rtx_REG (SFmode, 11905 (true_regnum (operands[1]) 11906 + (INTVAL (operands[4]) ^ endian))); 11907 11908 operands[7] = gen_rtx_REG (SFmode, 11909 (true_regnum (operands[0]) 11910 + (INTVAL (operands[3]) ^ endian))); 11911 operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1); 11912} 11913 [(set_attr "type" "fparith_media")]) 11914 11915(define_insn_and_split "binary_sf_op0" 11916 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f") 11917 (vec_concat:V2SF 11918 (match_operator:SF 3 "binary_float_operator" 11919 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f") 11920 (parallel [(const_int 0)])) 11921 (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f") 11922 (parallel [(const_int 0)]))]) 11923 (vec_select:SF 11924 (match_dup 0) 11925 (parallel [(const_int 1)]))))] 11926 "TARGET_SHMEDIA_FPU" 11927 "#" 11928 "&& reload_completed" 11929 [(set (match_dup 4) (match_dup 5))] 11930{ 11931 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1; 11932 rtx op1 = gen_rtx_REG (SFmode, 11933 true_regnum (operands[1]) + endian); 11934 rtx op2 = gen_rtx_REG (SFmode, 11935 true_regnum (operands[2]) + endian); 11936 11937 operands[4] = gen_rtx_REG (SFmode, 11938 true_regnum (operands[0]) + endian); 11939 operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2); 11940} 11941 [(set_attr "type" "fparith_media")]) 11942 11943(define_insn_and_split "binary_sf_op1" 11944 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f") 11945 (vec_concat:V2SF 11946 (vec_select:SF 11947 (match_dup 0) 11948 (parallel [(const_int 0)])) 11949 (match_operator:SF 3 "binary_float_operator" 11950 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f") 11951 (parallel [(const_int 1)])) 11952 (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f") 11953 (parallel [(const_int 1)]))])))] 11954 "TARGET_SHMEDIA_FPU" 11955 "#" 11956 "&& reload_completed" 11957 [(set (match_dup 4) (match_dup 5))] 11958{ 11959 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1; 11960 rtx op1 = gen_rtx_REG (SFmode, true_regnum (operands[1]) + (1 ^ endian)); 11961 rtx op2 = gen_rtx_REG (SFmode, true_regnum (operands[2]) + (1 ^ endian)); 11962 11963 operands[4] = gen_rtx_REG (SFmode, true_regnum (operands[0]) + (1 ^ endian)); 11964 operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2); 11965} 11966 [(set_attr "type" "fparith_media")]) 11967 11968(define_insn "addsf3_i" 11969 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 11970 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0") 11971 (match_operand:SF 2 "fp_arith_reg_operand" "f"))) 11972 (use (match_operand:PSI 3 "fpscr_operand" "c"))] 11973 "TARGET_SH2E" 11974 "fadd %2,%0" 11975 [(set_attr "type" "fp") 11976 (set_attr "fp_mode" "single")]) 11977 11978(define_expand "subsf3" 11979 [(set (match_operand:SF 0 "fp_arith_reg_operand" "") 11980 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "") 11981 (match_operand:SF 2 "fp_arith_reg_operand" "")))] 11982 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 11983{ 11984 if (TARGET_SH2E) 11985 { 11986 expand_sf_binop (&gen_subsf3_i, operands); 11987 DONE; 11988 } 11989}) 11990 11991(define_insn "*subsf3_media" 11992 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 11993 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f") 11994 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 11995 "TARGET_SHMEDIA_FPU" 11996 "fsub.s %1, %2, %0" 11997 [(set_attr "type" "fparith_media")]) 11998 11999(define_insn "subsf3_i" 12000 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 12001 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0") 12002 (match_operand:SF 2 "fp_arith_reg_operand" "f"))) 12003 (use (match_operand:PSI 3 "fpscr_operand" "c"))] 12004 "TARGET_SH2E" 12005 "fsub %2,%0" 12006 [(set_attr "type" "fp") 12007 (set_attr "fp_mode" "single")]) 12008 12009(define_expand "mulsf3" 12010 [(set (match_operand:SF 0 "fp_arith_reg_operand" "") 12011 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "") 12012 (match_operand:SF 2 "fp_arith_reg_operand" "")))] 12013 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 12014{ 12015 if (TARGET_SH2E) 12016 { 12017 emit_insn (gen_mulsf3_i (operands[0], operands[1], operands[2], 12018 get_fpscr_rtx ())); 12019 DONE; 12020 } 12021}) 12022 12023(define_insn "*mulsf3_media" 12024 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 12025 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f") 12026 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 12027 "TARGET_SHMEDIA_FPU" 12028 "fmul.s %1, %2, %0" 12029 [(set_attr "type" "fparith_media")]) 12030 12031(define_insn "mulsf3_i" 12032 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 12033 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0") 12034 (match_operand:SF 2 "fp_arith_reg_operand" "f"))) 12035 (use (match_operand:PSI 3 "fpscr_operand" "c"))] 12036 "TARGET_SH2E" 12037 "fmul %2,%0" 12038 [(set_attr "type" "fp") 12039 (set_attr "fp_mode" "single")]) 12040 12041;; FMA (fused multiply-add) patterns 12042(define_expand "fmasf4" 12043 [(set (match_operand:SF 0 "fp_arith_reg_operand") 12044 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand") 12045 (match_operand:SF 2 "fp_arith_reg_operand") 12046 (match_operand:SF 3 "fp_arith_reg_operand")))] 12047 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 12048{ 12049 if (TARGET_SH2E) 12050 { 12051 emit_sf_insn (gen_fmasf4_i (operands[0], operands[1], operands[2], 12052 operands[3], get_fpscr_rtx ())); 12053 DONE; 12054 } 12055}) 12056 12057(define_insn "fmasf4_i" 12058 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 12059 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "w") 12060 (match_operand:SF 2 "fp_arith_reg_operand" "f") 12061 (match_operand:SF 3 "fp_arith_reg_operand" "0"))) 12062 (use (match_operand:PSI 4 "fpscr_operand" "c"))] 12063 "TARGET_SH2E" 12064 "fmac %1,%2,%0" 12065 [(set_attr "type" "fp") 12066 (set_attr "fp_mode" "single")]) 12067 12068(define_insn "fmasf4_media" 12069 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 12070 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "f") 12071 (match_operand:SF 2 "fp_arith_reg_operand" "f") 12072 (match_operand:SF 3 "fp_arith_reg_operand" "0")))] 12073 "TARGET_SHMEDIA_FPU" 12074 "fmac.s %1, %2, %0" 12075 [(set_attr "type" "fparith_media")]) 12076 12077;; For some cases such as 'a * b + a' the FMA pattern is not generated by 12078;; previous transformations. If FMA is generally allowed, let the combine 12079;; pass utilize it. 12080(define_insn_and_split "*fmasf4" 12081 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 12082 (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w") 12083 (match_operand:SF 2 "fp_arith_reg_operand" "f")) 12084 (match_operand:SF 3 "arith_reg_operand" "0"))) 12085 (use (match_operand:PSI 4 "fpscr_operand"))] 12086 "TARGET_SH2E && flag_fp_contract_mode != FP_CONTRACT_OFF" 12087 "fmac %1,%2,%0" 12088 "&& can_create_pseudo_p ()" 12089 [(parallel [(set (match_dup 0) 12090 (fma:SF (match_dup 1) (match_dup 2) (match_dup 3))) 12091 (use (match_dup 4))])] 12092{ 12093 /* Change 'b * a + a' into 'a * b + a'. 12094 This is better for register allocation. */ 12095 if (REGNO (operands[2]) == REGNO (operands[3])) 12096 { 12097 rtx tmp = operands[1]; 12098 operands[1] = operands[2]; 12099 operands[2] = tmp; 12100 } 12101} 12102 [(set_attr "type" "fp") 12103 (set_attr "fp_mode" "single")]) 12104 12105(define_insn "*fmasf4_media" 12106 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 12107 (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f") 12108 (match_operand:SF 2 "fp_arith_reg_operand" "f")) 12109 (match_operand:SF 3 "fp_arith_reg_operand" "0")))] 12110 "TARGET_SHMEDIA_FPU && flag_fp_contract_mode != FP_CONTRACT_OFF" 12111 "fmac.s %1, %2, %0" 12112 [(set_attr "type" "fparith_media")]) 12113 12114(define_expand "divsf3" 12115 [(set (match_operand:SF 0 "arith_reg_operand" "") 12116 (div:SF (match_operand:SF 1 "arith_reg_operand" "") 12117 (match_operand:SF 2 "arith_reg_operand" "")))] 12118 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 12119{ 12120 if (TARGET_SH2E) 12121 { 12122 expand_sf_binop (&gen_divsf3_i, operands); 12123 DONE; 12124 } 12125}) 12126 12127(define_insn "*divsf3_media" 12128 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 12129 (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f") 12130 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 12131 "TARGET_SHMEDIA_FPU" 12132 "fdiv.s %1, %2, %0" 12133 [(set_attr "type" "fdiv_media")]) 12134 12135(define_insn "divsf3_i" 12136 [(set (match_operand:SF 0 "arith_reg_dest" "=f") 12137 (div:SF (match_operand:SF 1 "arith_reg_operand" "0") 12138 (match_operand:SF 2 "arith_reg_operand" "f"))) 12139 (use (match_operand:PSI 3 "fpscr_operand" "c"))] 12140 "TARGET_SH2E" 12141 "fdiv %2,%0" 12142 [(set_attr "type" "fdiv") 12143 (set_attr "fp_mode" "single")]) 12144 12145(define_insn "floatdisf2" 12146 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 12147 (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))] 12148 "TARGET_SHMEDIA_FPU" 12149 "float.qs %1, %0" 12150 [(set_attr "type" "fpconv_media")]) 12151 12152(define_expand "floatsisf2" 12153 [(set (match_operand:SF 0 "fp_arith_reg_operand" "") 12154 (float:SF (match_operand:SI 1 "fpul_operand" "")))] 12155 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 12156{ 12157 if (TARGET_SH4 || TARGET_SH2A_SINGLE) 12158 { 12159 emit_sf_insn (gen_floatsisf2_i4 (operands[0], operands[1], 12160 get_fpscr_rtx ())); 12161 DONE; 12162 } 12163}) 12164 12165(define_insn "*floatsisf2_media" 12166 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 12167 (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))] 12168 "TARGET_SHMEDIA_FPU" 12169 "float.ls %1, %0" 12170 [(set_attr "type" "fpconv_media")]) 12171 12172(define_insn "floatsisf2_i4" 12173 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 12174 (float:SF (match_operand:SI 1 "fpul_operand" "y"))) 12175 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 12176 "(TARGET_SH4 || TARGET_SH2A_SINGLE)" 12177 "float %1,%0" 12178 [(set_attr "type" "fp") 12179 (set_attr "fp_mode" "single")]) 12180 12181(define_insn "*floatsisf2_ie" 12182 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 12183 (float:SF (match_operand:SI 1 "fpul_operand" "y")))] 12184 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)" 12185 "float %1,%0" 12186 [(set_attr "type" "fp")]) 12187 12188(define_insn "fix_truncsfdi2" 12189 [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f") 12190 (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 12191 "TARGET_SHMEDIA_FPU" 12192 "ftrc.sq %1, %0" 12193 [(set_attr "type" "fpconv_media")]) 12194 12195(define_expand "fix_truncsfsi2" 12196 [(set (match_operand:SI 0 "fpul_operand" "=y") 12197 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 12198 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 12199{ 12200 if (TARGET_SH4 || TARGET_SH2A_SINGLE) 12201 { 12202 emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1], 12203 get_fpscr_rtx ())); 12204 DONE; 12205 } 12206}) 12207 12208(define_insn "*fix_truncsfsi2_media" 12209 [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f") 12210 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 12211 "TARGET_SHMEDIA_FPU" 12212 "ftrc.sl %1, %0" 12213 [(set_attr "type" "fpconv_media")]) 12214 12215(define_insn "fix_truncsfsi2_i4" 12216 [(set (match_operand:SI 0 "fpul_operand" "=y") 12217 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f"))) 12218 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 12219 "(TARGET_SH4 || TARGET_SH2A_SINGLE)" 12220 "ftrc %1,%0" 12221 [(set_attr "type" "ftrc_s") 12222 (set_attr "fp_mode" "single")]) 12223 12224;; ??? This pattern is used nowhere. fix_truncsfsi2 always expands to 12225;; fix_truncsfsi2_i4. 12226;; (define_insn "fix_truncsfsi2_i4_2" 12227;; [(set (match_operand:SI 0 "arith_reg_operand" "=r") 12228;; (fix:SI (match_operand:SF 1 "arith_reg_operand" "f"))) 12229;; (use (reg:PSI FPSCR_REG)) 12230;; (clobber (reg:SI FPUL_REG))] 12231;; "TARGET_SH4" 12232;; "#" 12233;; [(set_attr "length" "4") 12234;; (set_attr "fp_mode" "single")]) 12235 12236;;(define_split 12237;; [(set (match_operand:SI 0 "arith_reg_operand" "=r") 12238;; (fix:SI (match_operand:SF 1 "arith_reg_operand" "f"))) 12239;; (use (match_operand:PSI 2 "fpscr_operand" "c")) 12240;; (clobber (reg:SI FPUL_REG))] 12241;; "TARGET_SH4" 12242;; [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1))) 12243;; (use (match_dup 2))]) 12244;; (set (match_dup 0) (reg:SI FPUL_REG))]) 12245 12246(define_insn "*fixsfsi" 12247 [(set (match_operand:SI 0 "fpul_operand" "=y") 12248 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 12249 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)" 12250 "ftrc %1,%0" 12251 [(set_attr "type" "fp")]) 12252 12253(define_insn "cmpgtsf_t" 12254 [(set (reg:SI T_REG) 12255 (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f") 12256 (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 12257 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)" 12258 "fcmp/gt %1,%0" 12259 [(set_attr "type" "fp_cmp") 12260 (set_attr "fp_mode" "single")]) 12261 12262(define_insn "cmpeqsf_t" 12263 [(set (reg:SI T_REG) 12264 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f") 12265 (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 12266 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)" 12267 "fcmp/eq %1,%0" 12268 [(set_attr "type" "fp_cmp") 12269 (set_attr "fp_mode" "single")]) 12270 12271(define_insn "ieee_ccmpeqsf_t" 12272 [(set (reg:SI T_REG) 12273 (ior:SI (reg:SI T_REG) 12274 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f") 12275 (match_operand:SF 1 "fp_arith_reg_operand" "f"))))] 12276 "TARGET_SH2E && TARGET_IEEE && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)" 12277{ 12278 return output_ieee_ccmpeq (insn, operands); 12279} 12280 [(set_attr "length" "4")]) 12281 12282 12283(define_insn "cmpgtsf_t_i4" 12284 [(set (reg:SI T_REG) 12285 (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f") 12286 (match_operand:SF 1 "fp_arith_reg_operand" "f"))) 12287 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 12288 "(TARGET_SH4 || TARGET_SH2A_SINGLE)" 12289 "fcmp/gt %1,%0" 12290 [(set_attr "type" "fp_cmp") 12291 (set_attr "fp_mode" "single")]) 12292 12293(define_insn "cmpeqsf_t_i4" 12294 [(set (reg:SI T_REG) 12295 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f") 12296 (match_operand:SF 1 "fp_arith_reg_operand" "f"))) 12297 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 12298 "(TARGET_SH4 || TARGET_SH2A_SINGLE)" 12299 "fcmp/eq %1,%0" 12300 [(set_attr "type" "fp_cmp") 12301 (set_attr "fp_mode" "single")]) 12302 12303(define_insn "*ieee_ccmpeqsf_t_4" 12304 [(set (reg:SI T_REG) 12305 (ior:SI (reg:SI T_REG) 12306 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f") 12307 (match_operand:SF 1 "fp_arith_reg_operand" "f")))) 12308 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 12309 "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_SINGLE)" 12310{ 12311 return output_ieee_ccmpeq (insn, operands); 12312} 12313 [(set_attr "length" "4") 12314 (set_attr "fp_mode" "single")]) 12315 12316(define_insn "cmpeqsf_media" 12317 [(set (match_operand:SI 0 "register_operand" "=r") 12318 (eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f") 12319 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 12320 "TARGET_SHMEDIA_FPU" 12321 "fcmpeq.s %1, %2, %0" 12322 [(set_attr "type" "fcmp_media")]) 12323 12324(define_insn "cmpgtsf_media" 12325 [(set (match_operand:SI 0 "register_operand" "=r") 12326 (gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f") 12327 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 12328 "TARGET_SHMEDIA_FPU" 12329 "fcmpgt.s %1, %2, %0" 12330 [(set_attr "type" "fcmp_media")]) 12331 12332(define_insn "cmpgesf_media" 12333 [(set (match_operand:SI 0 "register_operand" "=r") 12334 (ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f") 12335 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 12336 "TARGET_SHMEDIA_FPU" 12337 "fcmpge.s %1, %2, %0" 12338 [(set_attr "type" "fcmp_media")]) 12339 12340(define_insn "cmpunsf_media" 12341 [(set (match_operand:SI 0 "register_operand" "=r") 12342 (unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f") 12343 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 12344 "TARGET_SHMEDIA_FPU" 12345 "fcmpun.s %1, %2, %0" 12346 [(set_attr "type" "fcmp_media")]) 12347 12348(define_expand "cbranchsf4" 12349 [(set (pc) 12350 (if_then_else (match_operator 0 "sh_float_comparison_operator" 12351 [(match_operand:SF 1 "arith_operand" "") 12352 (match_operand:SF 2 "arith_operand" "")]) 12353 (match_operand 3 "" "") 12354 (pc)))] 12355 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 12356{ 12357 if (TARGET_SHMEDIA) 12358 emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2], 12359 operands[3])); 12360 else 12361 sh_emit_compare_and_branch (operands, SFmode); 12362 DONE; 12363}) 12364 12365(define_expand "negsf2" 12366 [(set (match_operand:SF 0 "fp_arith_reg_operand" "") 12367 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))] 12368 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 12369{ 12370 if (TARGET_SH2E) 12371 { 12372 expand_sf_unop (&gen_negsf2_i, operands); 12373 DONE; 12374 } 12375}) 12376 12377(define_insn "*negsf2_media" 12378 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 12379 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 12380 "TARGET_SHMEDIA_FPU" 12381 "fneg.s %1, %0" 12382 [(set_attr "type" "fmove_media")]) 12383 12384(define_insn "negsf2_i" 12385 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 12386 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0"))) 12387 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 12388 "TARGET_SH2E" 12389 "fneg %0" 12390 [(set_attr "type" "fmove") 12391 (set_attr "fp_mode" "single")]) 12392 12393(define_expand "sqrtsf2" 12394 [(set (match_operand:SF 0 "fp_arith_reg_operand" "") 12395 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))] 12396 "TARGET_SH3E || TARGET_SHMEDIA_FPU" 12397{ 12398 if (TARGET_SH3E) 12399 { 12400 expand_sf_unop (&gen_sqrtsf2_i, operands); 12401 DONE; 12402 } 12403}) 12404 12405(define_insn "*sqrtsf2_media" 12406 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 12407 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 12408 "TARGET_SHMEDIA_FPU" 12409 "fsqrt.s %1, %0" 12410 [(set_attr "type" "fdiv_media")]) 12411 12412(define_insn "sqrtsf2_i" 12413 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 12414 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0"))) 12415 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 12416 "TARGET_SH3E" 12417 "fsqrt %0" 12418 [(set_attr "type" "fdiv") 12419 (set_attr "fp_mode" "single")]) 12420 12421(define_insn "rsqrtsf2" 12422 [(set (match_operand:SF 0 "register_operand" "=f") 12423 (div:SF (match_operand:SF 1 "immediate_operand" "i") 12424 (sqrt:SF (match_operand:SF 2 "register_operand" "0")))) 12425 (use (match_operand:PSI 3 "fpscr_operand" "c"))] 12426 "TARGET_FPU_ANY && TARGET_FSRRA 12427 && operands[1] == CONST1_RTX (SFmode)" 12428 "fsrra %0" 12429 [(set_attr "type" "fsrra") 12430 (set_attr "fp_mode" "single")]) 12431 12432;; When the sincos pattern is defined, the builtin functions sin and cos 12433;; will be expanded to the sincos pattern and one of the output values will 12434;; remain unused. 12435(define_expand "sincossf3" 12436 [(set (match_operand:SF 0 "nonimmediate_operand") 12437 (unspec:SF [(match_operand:SF 2 "fp_arith_reg_operand")] UNSPEC_FCOSA)) 12438 (set (match_operand:SF 1 "nonimmediate_operand") 12439 (unspec:SF [(match_dup 2)] UNSPEC_FSINA))] 12440 "TARGET_FPU_ANY && TARGET_FSCA" 12441{ 12442 rtx scaled = gen_reg_rtx (SFmode); 12443 rtx truncated = gen_reg_rtx (SImode); 12444 rtx fsca = gen_reg_rtx (V2SFmode); 12445 rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ()); 12446 12447 emit_sf_insn (gen_mulsf3 (scaled, operands[2], scale_reg)); 12448 emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled)); 12449 emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (), 12450 get_fpscr_rtx ())); 12451 12452 emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4)); 12453 emit_move_insn (operands[1], gen_rtx_SUBREG (SFmode, fsca, 0)); 12454 DONE; 12455}) 12456 12457(define_insn_and_split "fsca" 12458 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f") 12459 (vec_concat:V2SF 12460 (unspec:SF [(mult:SF 12461 (float:SF (match_operand:SI 1 "fpul_fsca_operand" "y")) 12462 (match_operand:SF 2 "fsca_scale_factor" "i")) 12463 ] UNSPEC_FSINA) 12464 (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2)) 12465 ] UNSPEC_FCOSA))) 12466 (use (match_operand:PSI 3 "fpscr_operand" "c"))] 12467 "TARGET_FPU_ANY && TARGET_FSCA" 12468 "fsca fpul,%d0" 12469 "&& !fpul_operand (operands[1], SImode)" 12470 [(const_int 0)] 12471{ 12472 /* If operands[1] is something like (fix:SF (float:SF (reg:SI))) reduce it 12473 to a simple reg, otherwise reload will have trouble reloading the 12474 pseudo into fpul. */ 12475 rtx x = XEXP (operands[1], 0); 12476 while (x != NULL_RTX && !fpul_operand (x, SImode)) 12477 { 12478 gcc_assert (GET_CODE (x) == FIX || GET_CODE (x) == FLOAT); 12479 x = XEXP (x, 0); 12480 } 12481 12482 gcc_assert (x != NULL_RTX && fpul_operand (x, SImode)); 12483 emit_insn (gen_fsca (operands[0], x, operands[2], operands[3])); 12484 DONE; 12485} 12486 [(set_attr "type" "fsca") 12487 (set_attr "fp_mode" "single")]) 12488 12489(define_expand "abssf2" 12490 [(set (match_operand:SF 0 "fp_arith_reg_operand" "") 12491 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))] 12492 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 12493{ 12494 if (TARGET_SH2E) 12495 { 12496 expand_sf_unop (&gen_abssf2_i, operands); 12497 DONE; 12498 } 12499}) 12500 12501(define_insn "*abssf2_media" 12502 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 12503 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 12504 "TARGET_SHMEDIA_FPU" 12505 "fabs.s %1, %0" 12506 [(set_attr "type" "fmove_media")]) 12507 12508(define_insn "abssf2_i" 12509 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 12510 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0"))) 12511 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 12512 "TARGET_SH2E" 12513 "fabs %0" 12514 [(set_attr "type" "fmove") 12515 (set_attr "fp_mode" "single")]) 12516 12517(define_expand "adddf3" 12518 [(set (match_operand:DF 0 "fp_arith_reg_operand" "") 12519 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "") 12520 (match_operand:DF 2 "fp_arith_reg_operand" "")))] 12521 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 12522{ 12523 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 12524 { 12525 expand_df_binop (&gen_adddf3_i, operands); 12526 DONE; 12527 } 12528}) 12529 12530(define_insn "*adddf3_media" 12531 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 12532 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f") 12533 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 12534 "TARGET_SHMEDIA_FPU" 12535 "fadd.d %1, %2, %0" 12536 [(set_attr "type" "dfparith_media")]) 12537 12538(define_insn "adddf3_i" 12539 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 12540 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0") 12541 (match_operand:DF 2 "fp_arith_reg_operand" "f"))) 12542 (use (match_operand:PSI 3 "fpscr_operand" "c"))] 12543 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 12544 "fadd %2,%0" 12545 [(set_attr "type" "dfp_arith") 12546 (set_attr "fp_mode" "double")]) 12547 12548(define_expand "subdf3" 12549 [(set (match_operand:DF 0 "fp_arith_reg_operand" "") 12550 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "") 12551 (match_operand:DF 2 "fp_arith_reg_operand" "")))] 12552 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 12553{ 12554 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 12555 { 12556 expand_df_binop (&gen_subdf3_i, operands); 12557 DONE; 12558 } 12559}) 12560 12561(define_insn "*subdf3_media" 12562 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 12563 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f") 12564 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 12565 "TARGET_SHMEDIA_FPU" 12566 "fsub.d %1, %2, %0" 12567 [(set_attr "type" "dfparith_media")]) 12568 12569(define_insn "subdf3_i" 12570 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 12571 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0") 12572 (match_operand:DF 2 "fp_arith_reg_operand" "f"))) 12573 (use (match_operand:PSI 3 "fpscr_operand" "c"))] 12574 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 12575 "fsub %2,%0" 12576 [(set_attr "type" "dfp_arith") 12577 (set_attr "fp_mode" "double")]) 12578 12579(define_expand "muldf3" 12580 [(set (match_operand:DF 0 "fp_arith_reg_operand" "") 12581 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "") 12582 (match_operand:DF 2 "fp_arith_reg_operand" "")))] 12583 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 12584{ 12585 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 12586 { 12587 expand_df_binop (&gen_muldf3_i, operands); 12588 DONE; 12589 } 12590}) 12591 12592(define_insn "*muldf3_media" 12593 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 12594 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f") 12595 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 12596 "TARGET_SHMEDIA_FPU" 12597 "fmul.d %1, %2, %0" 12598 [(set_attr "type" "dfmul_media")]) 12599 12600(define_insn "muldf3_i" 12601 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 12602 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0") 12603 (match_operand:DF 2 "fp_arith_reg_operand" "f"))) 12604 (use (match_operand:PSI 3 "fpscr_operand" "c"))] 12605 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 12606 "fmul %2,%0" 12607 [(set_attr "type" "dfp_mul") 12608 (set_attr "fp_mode" "double")]) 12609 12610(define_expand "divdf3" 12611 [(set (match_operand:DF 0 "fp_arith_reg_operand" "") 12612 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "") 12613 (match_operand:DF 2 "fp_arith_reg_operand" "")))] 12614 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 12615{ 12616 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 12617 { 12618 expand_df_binop (&gen_divdf3_i, operands); 12619 DONE; 12620 } 12621}) 12622 12623(define_insn "*divdf3_media" 12624 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 12625 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f") 12626 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 12627 "TARGET_SHMEDIA_FPU" 12628 "fdiv.d %1, %2, %0" 12629 [(set_attr "type" "dfdiv_media")]) 12630 12631(define_insn "divdf3_i" 12632 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 12633 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0") 12634 (match_operand:DF 2 "fp_arith_reg_operand" "f"))) 12635 (use (match_operand:PSI 3 "fpscr_operand" "c"))] 12636 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 12637 "fdiv %2,%0" 12638 [(set_attr "type" "dfdiv") 12639 (set_attr "fp_mode" "double")]) 12640 12641(define_insn "floatdidf2" 12642 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 12643 (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))] 12644 "TARGET_SHMEDIA_FPU" 12645 "float.qd %1, %0" 12646 [(set_attr "type" "dfpconv_media")]) 12647 12648(define_expand "floatsidf2" 12649 [(set (match_operand:DF 0 "fp_arith_reg_operand" "") 12650 (float:DF (match_operand:SI 1 "fpul_operand" "")))] 12651 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 12652{ 12653 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 12654 { 12655 emit_df_insn (gen_floatsidf2_i (operands[0], operands[1], 12656 get_fpscr_rtx ())); 12657 DONE; 12658 } 12659}) 12660 12661(define_insn "*floatsidf2_media" 12662 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 12663 (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))] 12664 "TARGET_SHMEDIA_FPU" 12665 "float.ld %1, %0" 12666 [(set_attr "type" "dfpconv_media")]) 12667 12668(define_insn "floatsidf2_i" 12669 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 12670 (float:DF (match_operand:SI 1 "fpul_operand" "y"))) 12671 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 12672 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 12673 "float %1,%0" 12674 [(set_attr "type" "dfp_conv") 12675 (set_attr "fp_mode" "double")]) 12676 12677(define_insn "fix_truncdfdi2" 12678 [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f") 12679 (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))] 12680 "TARGET_SHMEDIA_FPU" 12681 "ftrc.dq %1, %0" 12682 [(set_attr "type" "dfpconv_media")]) 12683 12684(define_expand "fix_truncdfsi2" 12685 [(set (match_operand:SI 0 "fpul_operand" "") 12686 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))] 12687 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 12688{ 12689 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 12690 { 12691 emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1], 12692 get_fpscr_rtx ())); 12693 DONE; 12694 } 12695}) 12696 12697(define_insn "*fix_truncdfsi2_media" 12698 [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f") 12699 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))] 12700 "TARGET_SHMEDIA_FPU" 12701 "ftrc.dl %1, %0" 12702 [(set_attr "type" "dfpconv_media")]) 12703 12704(define_insn "fix_truncdfsi2_i" 12705 [(set (match_operand:SI 0 "fpul_operand" "=y") 12706 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f"))) 12707 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 12708 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 12709 "ftrc %1,%0" 12710 [(set_attr "type" "dfp_conv") 12711 (set_attr "dfp_comp" "no") 12712 (set_attr "fp_mode" "double")]) 12713 12714;; ??? This pattern is used nowhere. fix_truncdfsi2 always expands to 12715;; fix_truncdfsi2_i. 12716;; (define_insn "fix_truncdfsi2_i4" 12717;; [(set (match_operand:SI 0 "arith_reg_operand" "=r") 12718;; (fix:SI (match_operand:DF 1 "arith_reg_operand" "f"))) 12719;; (use (match_operand:PSI 2 "fpscr_operand" "c")) 12720;; (clobber (reg:SI FPUL_REG))] 12721;; "TARGET_SH4" 12722;; "#" 12723;; [(set_attr "length" "4") 12724;; (set_attr "fp_mode" "double")]) 12725;; 12726;; (define_split 12727;; [(set (match_operand:SI 0 "arith_reg_operand" "=r") 12728;; (fix:SI (match_operand:DF 1 "arith_reg_operand" "f"))) 12729;; (use (match_operand:PSI 2 "fpscr_operand" "c")) 12730;; (clobber (reg:SI FPUL_REG))] 12731;; "TARGET_SH4" 12732;; [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1))) 12733;; (use (match_dup 2))]) 12734;; (set (match_dup 0) (reg:SI FPUL_REG))]) 12735 12736(define_insn "cmpgtdf_t" 12737 [(set (reg:SI T_REG) 12738 (gt:SI (match_operand:DF 0 "arith_reg_operand" "f") 12739 (match_operand:DF 1 "arith_reg_operand" "f"))) 12740 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 12741 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 12742 "fcmp/gt %1,%0" 12743 [(set_attr "type" "dfp_cmp") 12744 (set_attr "fp_mode" "double")]) 12745 12746(define_insn "cmpeqdf_t" 12747 [(set (reg:SI T_REG) 12748 (eq:SI (match_operand:DF 0 "arith_reg_operand" "f") 12749 (match_operand:DF 1 "arith_reg_operand" "f"))) 12750 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 12751 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 12752 "fcmp/eq %1,%0" 12753 [(set_attr "type" "dfp_cmp") 12754 (set_attr "fp_mode" "double")]) 12755 12756(define_insn "*ieee_ccmpeqdf_t" 12757 [(set (reg:SI T_REG) 12758 (ior:SI (reg:SI T_REG) 12759 (eq:SI (match_operand:DF 0 "arith_reg_operand" "f") 12760 (match_operand:DF 1 "arith_reg_operand" "f")))) 12761 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 12762 "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)" 12763{ 12764 return output_ieee_ccmpeq (insn, operands); 12765} 12766 [(set_attr "length" "4") 12767 (set_attr "fp_mode" "double")]) 12768 12769(define_insn "cmpeqdf_media" 12770 [(set (match_operand:SI 0 "register_operand" "=r") 12771 (eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f") 12772 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 12773 "TARGET_SHMEDIA_FPU" 12774 "fcmpeq.d %1,%2,%0" 12775 [(set_attr "type" "fcmp_media")]) 12776 12777(define_insn "cmpgtdf_media" 12778 [(set (match_operand:SI 0 "register_operand" "=r") 12779 (gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f") 12780 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 12781 "TARGET_SHMEDIA_FPU" 12782 "fcmpgt.d %1,%2,%0" 12783 [(set_attr "type" "fcmp_media")]) 12784 12785(define_insn "cmpgedf_media" 12786 [(set (match_operand:SI 0 "register_operand" "=r") 12787 (ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f") 12788 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 12789 "TARGET_SHMEDIA_FPU" 12790 "fcmpge.d %1,%2,%0" 12791 [(set_attr "type" "fcmp_media")]) 12792 12793(define_insn "cmpundf_media" 12794 [(set (match_operand:SI 0 "register_operand" "=r") 12795 (unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f") 12796 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 12797 "TARGET_SHMEDIA_FPU" 12798 "fcmpun.d %1,%2,%0" 12799 [(set_attr "type" "fcmp_media")]) 12800 12801(define_expand "cbranchdf4" 12802 [(set (pc) 12803 (if_then_else (match_operator 0 "sh_float_comparison_operator" 12804 [(match_operand:DF 1 "arith_operand" "") 12805 (match_operand:DF 2 "arith_operand" "")]) 12806 (match_operand 3 "" "") 12807 (pc)))] 12808 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 12809{ 12810 if (TARGET_SHMEDIA) 12811 emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2], 12812 operands[3])); 12813 else 12814 sh_emit_compare_and_branch (operands, DFmode); 12815 DONE; 12816}) 12817 12818 12819(define_expand "negdf2" 12820 [(set (match_operand:DF 0 "arith_reg_operand" "") 12821 (neg:DF (match_operand:DF 1 "arith_reg_operand" "")))] 12822 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 12823{ 12824 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 12825 { 12826 expand_df_unop (&gen_negdf2_i, operands); 12827 DONE; 12828 } 12829}) 12830 12831(define_insn "*negdf2_media" 12832 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 12833 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))] 12834 "TARGET_SHMEDIA_FPU" 12835 "fneg.d %1, %0" 12836 [(set_attr "type" "fmove_media")]) 12837 12838(define_insn "negdf2_i" 12839 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 12840 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0"))) 12841 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 12842 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 12843 "fneg %0" 12844 [(set_attr "type" "fmove") 12845 (set_attr "fp_mode" "double")]) 12846 12847(define_expand "sqrtdf2" 12848 [(set (match_operand:DF 0 "arith_reg_operand" "") 12849 (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "")))] 12850 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 12851{ 12852 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 12853 { 12854 expand_df_unop (&gen_sqrtdf2_i, operands); 12855 DONE; 12856 } 12857}) 12858 12859(define_insn "*sqrtdf2_media" 12860 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 12861 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))] 12862 "TARGET_SHMEDIA_FPU" 12863 "fsqrt.d %1, %0" 12864 [(set_attr "type" "dfdiv_media")]) 12865 12866(define_insn "sqrtdf2_i" 12867 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 12868 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0"))) 12869 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 12870 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 12871 "fsqrt %0" 12872 [(set_attr "type" "dfdiv") 12873 (set_attr "fp_mode" "double")]) 12874 12875(define_expand "absdf2" 12876 [(set (match_operand:DF 0 "arith_reg_operand" "") 12877 (abs:DF (match_operand:DF 1 "arith_reg_operand" "")))] 12878 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 12879{ 12880 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 12881 { 12882 expand_df_unop (&gen_absdf2_i, operands); 12883 DONE; 12884 } 12885}) 12886 12887(define_insn "*absdf2_media" 12888 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 12889 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))] 12890 "TARGET_SHMEDIA_FPU" 12891 "fabs.d %1, %0" 12892 [(set_attr "type" "fmove_media")]) 12893 12894(define_insn "absdf2_i" 12895 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 12896 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0"))) 12897 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 12898 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 12899 "fabs %0" 12900 [(set_attr "type" "fmove") 12901 (set_attr "fp_mode" "double")]) 12902 12903(define_expand "extendsfdf2" 12904 [(set (match_operand:DF 0 "fp_arith_reg_operand" "") 12905 (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))] 12906 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 12907{ 12908 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 12909 { 12910 emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1], 12911 get_fpscr_rtx ())); 12912 DONE; 12913 } 12914}) 12915 12916(define_insn "*extendsfdf2_media" 12917 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 12918 (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 12919 "TARGET_SHMEDIA_FPU" 12920 "fcnv.sd %1, %0" 12921 [(set_attr "type" "dfpconv_media")]) 12922 12923(define_insn "extendsfdf2_i4" 12924 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 12925 (float_extend:DF (match_operand:SF 1 "fpul_operand" "y"))) 12926 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 12927 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 12928 "fcnvsd %1,%0" 12929 [(set_attr "type" "fp") 12930 (set_attr "fp_mode" "double")]) 12931 12932(define_expand "truncdfsf2" 12933 [(set (match_operand:SF 0 "fpul_operand" "") 12934 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))] 12935 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 12936{ 12937 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 12938 { 12939 emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1], 12940 get_fpscr_rtx ())); 12941 DONE; 12942 } 12943}) 12944 12945(define_insn "*truncdfsf2_media" 12946 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 12947 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))] 12948 "TARGET_SHMEDIA_FPU" 12949 "fcnv.ds %1, %0" 12950 [(set_attr "type" "dfpconv_media")]) 12951 12952(define_insn "truncdfsf2_i4" 12953 [(set (match_operand:SF 0 "fpul_operand" "=y") 12954 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f"))) 12955 (use (match_operand:PSI 2 "fpscr_operand" "c"))] 12956 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 12957 "fcnvds %1,%0" 12958 [(set_attr "type" "fp") 12959 (set_attr "fp_mode" "double")]) 12960 12961;; ------------------------------------------------------------------------- 12962;; Bit field extract patterns. 12963;; ------------------------------------------------------------------------- 12964 12965;; These give better code for packed bitfields, because they allow 12966;; auto-increment addresses to be generated. 12967 12968(define_expand "insv" 12969 [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "") 12970 (match_operand:SI 1 "immediate_operand" "") 12971 (match_operand:SI 2 "immediate_operand" "")) 12972 (match_operand:SI 3 "general_operand" ""))] 12973 "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN" 12974{ 12975 rtx addr_target, orig_address, shift_reg, qi_val; 12976 HOST_WIDE_INT bitsize, size, v = 0; 12977 rtx x = operands[3]; 12978 12979 if (TARGET_SH2A && TARGET_BITOPS 12980 && (satisfies_constraint_Sbw (operands[0]) 12981 || satisfies_constraint_Sbv (operands[0])) 12982 && satisfies_constraint_M (operands[1]) 12983 && satisfies_constraint_K03 (operands[2])) 12984 { 12985 if (satisfies_constraint_N (operands[3])) 12986 { 12987 emit_insn (gen_bclr_m2a (operands[0], operands[2])); 12988 DONE; 12989 } 12990 else if (satisfies_constraint_M (operands[3])) 12991 { 12992 emit_insn (gen_bset_m2a (operands[0], operands[2])); 12993 DONE; 12994 } 12995 else if ((REG_P (operands[3]) && REGNO (operands[3]) == T_REG) 12996 && satisfies_constraint_M (operands[1])) 12997 { 12998 emit_insn (gen_bst_m2a (operands[0], operands[2])); 12999 DONE; 13000 } 13001 else if (REG_P (operands[3]) 13002 && satisfies_constraint_M (operands[1])) 13003 { 13004 emit_insn (gen_bld_reg (operands[3], const0_rtx)); 13005 emit_insn (gen_bst_m2a (operands[0], operands[2])); 13006 DONE; 13007 } 13008 } 13009 /* ??? expmed doesn't care for non-register predicates. */ 13010 if (! memory_operand (operands[0], VOIDmode) 13011 || ! immediate_operand (operands[1], VOIDmode) 13012 || ! immediate_operand (operands[2], VOIDmode) 13013 || ! general_operand (x, VOIDmode)) 13014 FAIL; 13015 /* If this isn't a 16 / 24 / 32 bit field, or if 13016 it doesn't start on a byte boundary, then fail. */ 13017 bitsize = INTVAL (operands[1]); 13018 if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0 13019 || (INTVAL (operands[2]) % 8) != 0) 13020 FAIL; 13021 13022 size = bitsize / 8; 13023 orig_address = XEXP (operands[0], 0); 13024 shift_reg = gen_reg_rtx (SImode); 13025 if (CONST_INT_P (x)) 13026 { 13027 v = INTVAL (x); 13028 qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode))); 13029 } 13030 else 13031 { 13032 emit_insn (gen_movsi (shift_reg, operands[3])); 13033 qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3); 13034 } 13035 addr_target = copy_addr_to_reg (plus_constant (Pmode, 13036 orig_address, size - 1)); 13037 13038 operands[0] = replace_equiv_address (operands[0], addr_target); 13039 emit_insn (gen_movqi (operands[0], qi_val)); 13040 13041 while (size -= 1) 13042 { 13043 if (CONST_INT_P (x)) 13044 qi_val 13045 = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode))); 13046 else 13047 { 13048 emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8))); 13049 qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3); 13050 } 13051 emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx)); 13052 emit_insn (gen_movqi (operands[0], qi_val)); 13053 } 13054 13055 DONE; 13056}) 13057 13058(define_insn "movua" 13059 [(set (match_operand:SI 0 "register_operand" "=z") 13060 (unspec:SI [(match_operand:BLK 1 "unaligned_load_operand" "Sua>")] 13061 UNSPEC_MOVUA))] 13062 "TARGET_SH4A_ARCH" 13063 "movua.l %1,%0" 13064 [(set_attr "type" "movua")]) 13065 13066;; We shouldn't need this, but cse replaces increments with references 13067;; to other regs before flow has a chance to create post_inc 13068;; addressing modes, and only postreload's cse_move2add brings the 13069;; increments back to a usable form. 13070(define_peephole2 13071 [(set (match_operand:SI 0 "register_operand" "") 13072 (sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" "")) 13073 (const_int 32) (const_int 0))) 13074 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))] 13075 "TARGET_SH4A_ARCH && REGNO (operands[0]) != REGNO (operands[1])" 13076 [(set (match_operand:SI 0 "register_operand" "") 13077 (sign_extract:SI (mem:SI (post_inc:SI 13078 (match_operand:SI 1 "register_operand" ""))) 13079 (const_int 32) (const_int 0)))] 13080 "") 13081 13082(define_expand "extv" 13083 [(set (match_operand:SI 0 "register_operand" "") 13084 (sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "") 13085 (match_operand 2 "const_int_operand" "") 13086 (match_operand 3 "const_int_operand" "")))] 13087 "TARGET_SH4A_ARCH || TARGET_SH2A" 13088{ 13089 if (TARGET_SH2A && TARGET_BITOPS 13090 && (satisfies_constraint_Sbw (operands[1]) 13091 || satisfies_constraint_Sbv (operands[1])) 13092 && satisfies_constraint_M (operands[2]) 13093 && satisfies_constraint_K03 (operands[3])) 13094 { 13095 emit_insn (gen_bldsign_m2a (operands[1], operands[3])); 13096 if (REGNO (operands[0]) != T_REG) 13097 emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG))); 13098 DONE; 13099 } 13100 if (TARGET_SH4A_ARCH 13101 && INTVAL (operands[2]) == 32 13102 && INTVAL (operands[3]) == 0 13103 && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32) 13104 { 13105 rtx src = adjust_address (operands[1], BLKmode, 0); 13106 set_mem_size (src, 4); 13107 emit_insn (gen_movua (operands[0], src)); 13108 DONE; 13109 } 13110 13111 FAIL; 13112}) 13113 13114(define_expand "extzv" 13115 [(set (match_operand:SI 0 "register_operand" "") 13116 (zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "") 13117 (match_operand 2 "const_int_operand" "") 13118 (match_operand 3 "const_int_operand" "")))] 13119 "TARGET_SH4A_ARCH || TARGET_SH2A" 13120{ 13121 if (TARGET_SH2A && TARGET_BITOPS 13122 && (satisfies_constraint_Sbw (operands[1]) 13123 || satisfies_constraint_Sbv (operands[1])) 13124 && satisfies_constraint_M (operands[2]) 13125 && satisfies_constraint_K03 (operands[3])) 13126 { 13127 emit_insn (gen_bld_m2a (operands[1], operands[3])); 13128 if (REGNO (operands[0]) != T_REG) 13129 emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG))); 13130 DONE; 13131 } 13132 if (TARGET_SH4A_ARCH 13133 && INTVAL (operands[2]) == 32 13134 && INTVAL (operands[3]) == 0 13135 && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32) 13136 { 13137 rtx src = adjust_address (operands[1], BLKmode, 0); 13138 set_mem_size (src, 4); 13139 emit_insn (gen_movua (operands[0], src)); 13140 DONE; 13141 } 13142 13143 FAIL; 13144}) 13145 13146;; SH2A instructions for bitwise operations. 13147;; FIXME: Convert multiple instruction insns to insn_and_split. 13148;; FIXME: Use iterators to fold at least and,xor,or insn variations. 13149 13150;; Clear a bit in a memory location. 13151(define_insn "bclr_m2a" 13152 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv") 13153 (and:QI 13154 (not:QI (ashift:QI (const_int 1) 13155 (match_operand:QI 1 "const_int_operand" "K03,K03"))) 13156 (match_dup 0)))] 13157 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 13158 "@ 13159 bclr.b %1,%0 13160 bclr.b %1,@(0,%t0)" 13161[(set_attr "length" "4,4")]) 13162 13163(define_insn "bclrmem_m2a" 13164 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv") 13165 (and:QI (match_dup 0) 13166 (match_operand:QI 1 "const_int_operand" "Psz,Psz")))] 13167 "TARGET_SH2A && satisfies_constraint_Psz (operands[1]) && TARGET_BITOPS" 13168 "@ 13169 bclr.b %W1,%0 13170 bclr.b %W1,@(0,%t0)" 13171 [(set_attr "length" "4,4")]) 13172 13173;; Set a bit in a memory location. 13174(define_insn "bset_m2a" 13175 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv") 13176 (ior:QI 13177 (ashift:QI (const_int 1) 13178 (match_operand:QI 1 "const_int_operand" "K03,K03")) 13179 (match_dup 0)))] 13180 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 13181 "@ 13182 bset.b %1,%0 13183 bset.b %1,@(0,%t0)" 13184 [(set_attr "length" "4,4")]) 13185 13186(define_insn "bsetmem_m2a" 13187 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv") 13188 (ior:QI (match_dup 0) 13189 (match_operand:QI 1 "const_int_operand" "Pso,Pso")))] 13190 "TARGET_SH2A && satisfies_constraint_Pso (operands[1]) && TARGET_BITOPS" 13191 "@ 13192 bset.b %V1,%0 13193 bset.b %V1,@(0,%t0)" 13194 [(set_attr "length" "4,4")]) 13195 13196;;; Transfer the contents of the T bit to a specified bit of memory. 13197(define_insn "bst_m2a" 13198 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,m") 13199 (if_then_else (eq (reg:SI T_REG) (const_int 0)) 13200 (and:QI 13201 (not:QI (ashift:QI (const_int 1) 13202 (match_operand:QI 1 "const_int_operand" "K03,K03"))) 13203 (match_dup 0)) 13204 (ior:QI 13205 (ashift:QI (const_int 1) (match_dup 1)) 13206 (match_dup 0))))] 13207 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 13208 "@ 13209 bst.b %1,%0 13210 bst.b %1,@(0,%t0)" 13211 [(set_attr "length" "4")]) 13212 13213;; Store a specified bit of memory in the T bit. 13214(define_insn "bld_m2a" 13215 [(set (reg:SI T_REG) 13216 (zero_extract:SI 13217 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,Sbv") 13218 (const_int 1) 13219 (match_operand 1 "const_int_operand" "K03,K03")))] 13220 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 13221 "@ 13222 bld.b %1,%0 13223 bld.b %1,@(0,%t0)" 13224 [(set_attr "length" "4,4")]) 13225 13226;; Store a specified bit of memory in the T bit. 13227(define_insn "bldsign_m2a" 13228 [(set (reg:SI T_REG) 13229 (sign_extract:SI 13230 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m") 13231 (const_int 1) 13232 (match_operand 1 "const_int_operand" "K03,K03")))] 13233 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 13234 "@ 13235 bld.b %1,%0 13236 bld.b %1,@(0,%t0)" 13237 [(set_attr "length" "4,4")]) 13238 13239;; Store a specified bit of the LSB 8 bits of a register in the T bit. 13240(define_insn "bld_reg" 13241 [(set (reg:SI T_REG) 13242 (zero_extract:SI (match_operand:SI 0 "arith_reg_operand" "r") 13243 (const_int 1) 13244 (match_operand 1 "const_int_operand" "K03")))] 13245 "TARGET_SH2A && satisfies_constraint_K03 (operands[1])" 13246 "bld %1,%0") 13247 13248(define_insn "*bld_regqi" 13249 [(set (reg:SI T_REG) 13250 (zero_extract:SI (match_operand:QI 0 "arith_reg_operand" "r") 13251 (const_int 1) 13252 (match_operand 1 "const_int_operand" "K03")))] 13253 "TARGET_SH2A && satisfies_constraint_K03 (operands[1])" 13254 "bld %1,%0") 13255 13256;; Take logical and of a specified bit of memory with the T bit and 13257;; store its result in the T bit. 13258(define_insn "band_m2a" 13259 [(set (reg:SI T_REG) 13260 (and:SI (reg:SI T_REG) 13261 (zero_extract:SI 13262 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m") 13263 (const_int 1) 13264 (match_operand 1 "const_int_operand" "K03,K03"))))] 13265 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 13266 "@ 13267 band.b %1,%0 13268 band.b %1,@(0,%t0)" 13269 [(set_attr "length" "4,4")]) 13270 13271(define_insn "bandreg_m2a" 13272 [(set (match_operand:SI 0 "register_operand" "=r,r") 13273 (and:SI (zero_extract:SI 13274 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv") 13275 (const_int 1) 13276 (match_operand 2 "const_int_operand" "K03,K03")) 13277 (match_operand:SI 3 "register_operand" "r,r")))] 13278 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])" 13279{ 13280 static const char* alt[] = 13281 { 13282 "band.b %2,%1" "\n" 13283 " movt %0", 13284 13285 "band.b %2,@(0,%t1)" "\n" 13286 " movt %0" 13287 }; 13288 return alt[which_alternative]; 13289} 13290 [(set_attr "length" "6,6")]) 13291 13292;; Take logical or of a specified bit of memory with the T bit and 13293;; store its result in the T bit. 13294(define_insn "bor_m2a" 13295 [(set (reg:SI T_REG) 13296 (ior:SI (reg:SI T_REG) 13297 (zero_extract:SI 13298 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m") 13299 (const_int 1) 13300 (match_operand 1 "const_int_operand" "K03,K03"))))] 13301 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 13302 "@ 13303 bor.b %1,%0 13304 bor.b %1,@(0,%t0)" 13305 [(set_attr "length" "4,4")]) 13306 13307(define_insn "borreg_m2a" 13308 [(set (match_operand:SI 0 "register_operand" "=r,r") 13309 (ior:SI (zero_extract:SI 13310 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv") 13311 (const_int 1) 13312 (match_operand 2 "const_int_operand" "K03,K03")) 13313 (match_operand:SI 3 "register_operand" "=r,r")))] 13314 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])" 13315{ 13316 static const char* alt[] = 13317 { 13318 "bor.b %2,%1" "\n" 13319 " movt %0", 13320 13321 "bor.b %2,@(0,%t1)" "\n" 13322 " movt %0" 13323 }; 13324 return alt[which_alternative]; 13325} 13326 [(set_attr "length" "6,6")]) 13327 13328;; Take exclusive or of a specified bit of memory with the T bit and 13329;; store its result in the T bit. 13330(define_insn "bxor_m2a" 13331 [(set (reg:SI T_REG) 13332 (xor:SI (reg:SI T_REG) 13333 (zero_extract:SI 13334 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m") 13335 (const_int 1) 13336 (match_operand 1 "const_int_operand" "K03,K03"))))] 13337 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 13338 "@ 13339 bxor.b %1,%0 13340 bxor.b %1,@(0,%t0)" 13341 [(set_attr "length" "4,4")]) 13342 13343(define_insn "bxorreg_m2a" 13344 [(set (match_operand:SI 0 "register_operand" "=r,r") 13345 (xor:SI (zero_extract:SI 13346 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv") 13347 (const_int 1) 13348 (match_operand 2 "const_int_operand" "K03,K03")) 13349 (match_operand:SI 3 "register_operand" "=r,r")))] 13350 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])" 13351{ 13352 static const char* alt[] = 13353 { 13354 "bxor.b %2,%1" "\n" 13355 " movt %0", 13356 13357 "bxor.b %2,@(0,%t1)" "\n" 13358 " movt %0" 13359 }; 13360 return alt[which_alternative]; 13361} 13362 [(set_attr "length" "6,6")]) 13363 13364;; ------------------------------------------------------------------------- 13365;; Peepholes 13366;; ------------------------------------------------------------------------- 13367;; This matches cases where the bit in a memory location is set. 13368(define_peephole2 13369 [(set (match_operand:SI 0 "arith_reg_operand" "r,r") 13370 (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv"))) 13371 (set (match_dup 0) 13372 (ior:SI (match_dup 0) 13373 (match_operand:SI 2 "const_int_operand" "Pso,Pso"))) 13374 (set (match_dup 1) 13375 (match_operand 3 "arith_reg_operand" "r,r"))] 13376 "TARGET_SH2A && TARGET_BITOPS 13377 && satisfies_constraint_Pso (operands[2]) 13378 && REGNO (operands[0]) == REGNO (operands[3])" 13379 [(set (match_dup 1) 13380 (ior:QI (match_dup 1) (match_dup 2)))] 13381 "") 13382 13383;; This matches cases where the bit in a memory location is cleared. 13384(define_peephole2 13385 [(set (match_operand:SI 0 "arith_reg_operand" "r,r") 13386 (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv"))) 13387 (set (match_dup 0) 13388 (and:SI (match_dup 0) 13389 (match_operand:SI 2 "const_int_operand" "Psz,Psz"))) 13390 (set (match_dup 1) 13391 (match_operand 3 "arith_reg_operand" "r,r"))] 13392 "TARGET_SH2A && TARGET_BITOPS 13393 && satisfies_constraint_Psz (operands[2]) 13394 && REGNO (operands[0]) == REGNO (operands[3])" 13395 [(set (match_dup 1) 13396 (and:QI (match_dup 1) (match_dup 2)))] 13397 "") 13398 13399;; This matches cases where a stack pointer increment at the start of the 13400;; epilogue combines with a stack slot read loading the return value. 13401(define_peephole 13402 [(set (match_operand:SI 0 "arith_reg_operand" "") 13403 (mem:SI (match_operand:SI 1 "arith_reg_operand" ""))) 13404 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))] 13405 "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])" 13406 "mov.l @%1+,%0") 13407 13408;; See the comment on the dt combiner pattern above. 13409(define_peephole 13410 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 13411 (plus:SI (match_dup 0) 13412 (const_int -1))) 13413 (set (reg:SI T_REG) 13414 (eq:SI (match_dup 0) (const_int 0)))] 13415 "TARGET_SH2" 13416 "dt %0") 13417 13418;; The following peepholes fold load sequences for which reload was not 13419;; able to generate a displacement addressing move insn. 13420;; This can happen when reload has to transform a move insn 13421;; without displacement into one with displacement. Or when reload can't 13422;; fit a displacement into the insn's constraints. In the latter case, the 13423;; load destination reg remains at r0, which reload compensates by inserting 13424;; another mov insn. 13425 13426;; Fold sequence: 13427;; mov #54,r0 13428;; mov.{b,w} @(r0,r15),r0 13429;; mov r0,r3 13430;; into: 13431;; mov.{b,w} @(54,r15),r3 13432;; 13433(define_peephole2 13434 [(set (match_operand:SI 0 "arith_reg_dest" "") 13435 (match_operand:SI 1 "const_int_operand" "")) 13436 (set (match_operand:SI 2 "arith_reg_dest" "") 13437 (sign_extend:SI 13438 (mem:QI (plus:SI (match_dup 0) 13439 (match_operand:SI 3 "arith_reg_operand" ""))))) 13440 (set (match_operand:QI 4 "arith_reg_dest" "") 13441 (match_operand:QI 5 "arith_reg_operand" ""))] 13442 "TARGET_SH2A 13443 && sh_legitimate_index_p (QImode, operands[1], true, true) 13444 && REGNO (operands[2]) == REGNO (operands[5]) 13445 && peep2_reg_dead_p (3, operands[5])" 13446 [(set (match_dup 4) (mem:QI (plus:SI (match_dup 3) (match_dup 1))))] 13447 "") 13448 13449(define_peephole2 13450 [(set (match_operand:SI 0 "arith_reg_dest" "") 13451 (match_operand:SI 1 "const_int_operand" "")) 13452 (set (match_operand:SI 2 "arith_reg_dest" "") 13453 (sign_extend:SI 13454 (mem:HI (plus:SI (match_dup 0) 13455 (match_operand:SI 3 "arith_reg_operand" ""))))) 13456 (set (match_operand:HI 4 "arith_reg_dest" "") 13457 (match_operand:HI 5 "arith_reg_operand" ""))] 13458 "TARGET_SH2A 13459 && sh_legitimate_index_p (HImode, operands[1], true, true) 13460 && REGNO (operands[2]) == REGNO (operands[5]) 13461 && peep2_reg_dead_p (3, operands[5])" 13462 [(set (match_dup 4) (mem:HI (plus:SI (match_dup 3) (match_dup 1))))] 13463 "") 13464 13465;; Fold sequence: 13466;; mov #54,r0 13467;; mov.{b,w} @(r0,r15),r1 13468;; into: 13469;; mov.{b,w} @(54,r15),r1 13470;; 13471(define_peephole2 13472 [(set (match_operand:SI 0 "arith_reg_dest" "") 13473 (match_operand:SI 1 "const_int_operand" "")) 13474 (set (match_operand:SI 2 "arith_reg_dest" "") 13475 (sign_extend:SI 13476 (mem:QI (plus:SI (match_dup 0) 13477 (match_operand:SI 3 "arith_reg_operand" "")))))] 13478 "TARGET_SH2A 13479 && sh_legitimate_index_p (QImode, operands[1], true, true) 13480 && (peep2_reg_dead_p (2, operands[0]) 13481 || REGNO (operands[0]) == REGNO (operands[2]))" 13482 [(set (match_dup 2) 13483 (sign_extend:SI (mem:QI (plus:SI (match_dup 3) (match_dup 1)))))] 13484 "") 13485 13486(define_peephole2 13487 [(set (match_operand:SI 0 "arith_reg_dest" "") 13488 (match_operand:SI 1 "const_int_operand" "")) 13489 (set (match_operand:SI 2 "arith_reg_dest" "") 13490 (sign_extend:SI 13491 (mem:HI (plus:SI (match_dup 0) 13492 (match_operand:SI 3 "arith_reg_operand" "")))))] 13493 "TARGET_SH2A 13494 && sh_legitimate_index_p (HImode, operands[1], true, true) 13495 && (peep2_reg_dead_p (2, operands[0]) 13496 || REGNO (operands[0]) == REGNO (operands[2]))" 13497 [(set (match_dup 2) 13498 (sign_extend:SI (mem:HI (plus:SI (match_dup 3) (match_dup 1)))))] 13499 "") 13500 13501;; Fold sequence: 13502;; mov.{b,w} @(r0,r15),r0 13503;; mov r0,r3 13504;; into: 13505;; mov.{b,w} @(r0,r15),r3 13506;; 13507;; This can happen when initially a displacement address is picked, where 13508;; the destination reg is fixed to r0, and then the address is transformed 13509;; into 'r0 + reg'. 13510(define_peephole2 13511 [(set (match_operand:SI 0 "arith_reg_dest" "") 13512 (sign_extend:SI 13513 (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "") 13514 (match_operand:SI 2 "arith_reg_operand" ""))))) 13515 (set (match_operand:QI 3 "arith_reg_dest" "") 13516 (match_operand:QI 4 "arith_reg_operand" ""))] 13517 "TARGET_SH1 13518 && REGNO (operands[0]) == REGNO (operands[4]) 13519 && peep2_reg_dead_p (2, operands[0])" 13520 [(set (match_dup 3) 13521 (mem:QI (plus:SI (match_dup 1) (match_dup 2))))] 13522 "") 13523 13524(define_peephole2 13525 [(set (match_operand:SI 0 "arith_reg_dest" "") 13526 (sign_extend:SI 13527 (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "") 13528 (match_operand:SI 2 "arith_reg_operand" ""))))) 13529 (set (match_operand:HI 3 "arith_reg_dest" "") 13530 (match_operand:HI 4 "arith_reg_operand" ""))] 13531 "TARGET_SH1 13532 && REGNO (operands[0]) == REGNO (operands[4]) 13533 && peep2_reg_dead_p (2, operands[0])" 13534 [(set (match_dup 3) 13535 (mem:HI (plus:SI (match_dup 1) (match_dup 2))))] 13536 "") 13537 13538(define_peephole 13539 [(set (match_operand:SI 0 "register_operand" "=r") 13540 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) 13541 (set (mem:SF (match_dup 0)) 13542 (match_operand:SF 2 "general_movsrc_operand" ""))] 13543 "TARGET_SH1 && REGNO (operands[0]) == 0 13544 && ((REG_P (operands[2]) && REGNO (operands[2]) < 16) 13545 || (GET_CODE (operands[2]) == SUBREG 13546 && REGNO (SUBREG_REG (operands[2])) < 16)) 13547 && reg_unused_after (operands[0], insn)" 13548 "mov.l %2,@(%0,%1)") 13549 13550(define_peephole 13551 [(set (match_operand:SI 0 "register_operand" "=r") 13552 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) 13553 (set (match_operand:SF 2 "general_movdst_operand" "") 13554 13555 (mem:SF (match_dup 0)))] 13556 "TARGET_SH1 && REGNO (operands[0]) == 0 13557 && ((REG_P (operands[2]) && REGNO (operands[2]) < 16) 13558 || (GET_CODE (operands[2]) == SUBREG 13559 && REGNO (SUBREG_REG (operands[2])) < 16)) 13560 && reg_unused_after (operands[0], insn)" 13561 "mov.l @(%0,%1),%2") 13562 13563(define_peephole 13564 [(set (match_operand:SI 0 "register_operand" "=r") 13565 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) 13566 (set (mem:SF (match_dup 0)) 13567 (match_operand:SF 2 "general_movsrc_operand" ""))] 13568 "TARGET_SH2E && REGNO (operands[0]) == 0 13569 && ((REG_P (operands[2]) 13570 && FP_OR_XD_REGISTER_P (REGNO (operands[2]))) 13571 || (GET_CODE (operands[2]) == SUBREG 13572 && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2]))))) 13573 && reg_unused_after (operands[0], insn)" 13574 "fmov{.s|} %2,@(%0,%1)") 13575 13576(define_peephole 13577 [(set (match_operand:SI 0 "register_operand" "=r") 13578 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) 13579 (set (match_operand:SF 2 "general_movdst_operand" "") 13580 13581 (mem:SF (match_dup 0)))] 13582 "TARGET_SH2E && REGNO (operands[0]) == 0 13583 && ((REG_P (operands[2]) 13584 && FP_OR_XD_REGISTER_P (REGNO (operands[2]))) 13585 || (GET_CODE (operands[2]) == SUBREG 13586 && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2]))))) 13587 && reg_unused_after (operands[0], insn)" 13588 "fmov{.s|} @(%0,%1),%2") 13589 13590;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF). 13591(define_insn "sp_switch_1" 13592 [(set (reg:SI SP_REG) (unspec_volatile [(match_operand:SI 0 "" "")] 13593 UNSPECV_SP_SWITCH_B))] 13594 "TARGET_SH1" 13595{ 13596 return "mov.l r0,@-r15" "\n" 13597 " mov.l %0,r0" "\n" 13598 " mov.l @r0,r0" "\n" 13599 " mov.l r15,@-r0" "\n" 13600 " mov r0,r15"; 13601} 13602 [(set_attr "length" "10")]) 13603 13604;; Switch back to the original stack for interrupt functions with the 13605;; sp_switch attribute. 13606(define_insn "sp_switch_2" 13607 [(unspec_volatile [(const_int 0)] 13608 UNSPECV_SP_SWITCH_E)] 13609 "TARGET_SH1" 13610{ 13611 return "mov.l @r15,r15" "\n" 13612 " mov.l @r15+,r0"; 13613} 13614 [(set_attr "length" "4")]) 13615 13616;; ------------------------------------------------------------------------- 13617;; Integer vector moves 13618;; ------------------------------------------------------------------------- 13619 13620(define_expand "movv8qi" 13621 [(set (match_operand:V8QI 0 "general_movdst_operand" "") 13622 (match_operand:V8QI 1 "general_movsrc_operand" ""))] 13623 "TARGET_SHMEDIA" 13624{ 13625 prepare_move_operands (operands, V8QImode); 13626}) 13627 13628(define_insn "movv8qi_i" 13629 [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m") 13630 (match_operand:V8QI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))] 13631 "TARGET_SHMEDIA 13632 && (register_operand (operands[0], V8QImode) 13633 || sh_register_operand (operands[1], V8QImode))" 13634 "@ 13635 add %1, r63, %0 13636 movi %1, %0 13637 # 13638 ld%M1.q %m1, %0 13639 st%M0.q %m0, %N1" 13640 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media") 13641 (set_attr "length" "4,4,16,4,4")]) 13642 13643(define_split 13644 [(set (match_operand:V8QI 0 "arith_reg_dest" "") 13645 (subreg:V8QI (const_int 0) 0))] 13646 "TARGET_SHMEDIA" 13647 [(set (match_dup 0) 13648 (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0) 13649 (const_int 0) (const_int 0) (const_int 0) 13650 (const_int 0) (const_int 0)]))]) 13651 13652(define_split 13653 [(set (match_operand 0 "arith_reg_dest" "") 13654 (match_operand 1 "sh_rep_vec" ""))] 13655 "TARGET_SHMEDIA && reload_completed 13656 && GET_MODE (operands[0]) == GET_MODE (operands[1]) 13657 && sh_vector_mode_supported_p (GET_MODE (operands[0])) 13658 && GET_MODE_SIZE (GET_MODE (operands[0])) == 8 13659 && (XVECEXP (operands[1], 0, 0) != const0_rtx 13660 || XVECEXP (operands[1], 0, 1) != const0_rtx) 13661 && (XVECEXP (operands[1], 0, 0) != constm1_rtx 13662 || XVECEXP (operands[1], 0, 1) != constm1_rtx)" 13663 [(set (match_dup 0) (match_dup 1)) 13664 (match_dup 2)] 13665{ 13666 int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1])); 13667 rtx elt1 = XVECEXP (operands[1], 0, 1); 13668 13669 if (unit_size > 2) 13670 operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]); 13671 else 13672 { 13673 if (unit_size < 2) 13674 operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0])); 13675 operands[2] = gen_mperm_w0 (operands[0], operands[0]); 13676 } 13677 operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0])); 13678 operands[1] = XVECEXP (operands[1], 0, 0); 13679 if (unit_size < 2) 13680 { 13681 if (CONST_INT_P (operands[1]) && CONST_INT_P (elt1)) 13682 operands[1] 13683 = GEN_INT (TARGET_LITTLE_ENDIAN 13684 ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8) 13685 : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff)); 13686 else 13687 { 13688 operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0])); 13689 operands[1] 13690 = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1)); 13691 } 13692 } 13693}) 13694 13695(define_split 13696 [(set (match_operand 0 "arith_reg_dest" "") 13697 (match_operand 1 "sh_const_vec" ""))] 13698 "TARGET_SHMEDIA && reload_completed 13699 && GET_MODE (operands[0]) == GET_MODE (operands[1]) 13700 && sh_vector_mode_supported_p (GET_MODE (operands[0]))" 13701 [(set (match_dup 0) (match_dup 1))] 13702{ 13703 rtx v = operands[1]; 13704 enum machine_mode new_mode 13705 = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0); 13706 13707 operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0])); 13708 operands[1] 13709 = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0); 13710}) 13711 13712(define_expand "movv2hi" 13713 [(set (match_operand:V2HI 0 "general_movdst_operand" "") 13714 (match_operand:V2HI 1 "general_movsrc_operand" ""))] 13715 "TARGET_SHMEDIA" 13716{ 13717 prepare_move_operands (operands, V2HImode); 13718}) 13719 13720(define_insn "movv2hi_i" 13721 [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m") 13722 (match_operand:V2HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))] 13723 "TARGET_SHMEDIA 13724 && (register_operand (operands[0], V2HImode) 13725 || sh_register_operand (operands[1], V2HImode))" 13726 "@ 13727 add.l %1, r63, %0 13728 movi %1, %0 13729 # 13730 ld%M1.l %m1, %0 13731 st%M0.l %m0, %N1" 13732 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media") 13733 (set_attr "length" "4,4,16,4,4") 13734 (set (attr "highpart") 13735 (cond [(match_test "sh_contains_memref_p (insn)") 13736 (const_string "user")] 13737 (const_string "ignore")))]) 13738 13739(define_expand "movv4hi" 13740 [(set (match_operand:V4HI 0 "general_movdst_operand" "") 13741 (match_operand:V4HI 1 "general_movsrc_operand" ""))] 13742 "TARGET_SHMEDIA" 13743{ 13744 prepare_move_operands (operands, V4HImode); 13745}) 13746 13747(define_insn "movv4hi_i" 13748 [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m") 13749 (match_operand:V4HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))] 13750 "TARGET_SHMEDIA 13751 && (register_operand (operands[0], V4HImode) 13752 || sh_register_operand (operands[1], V4HImode))" 13753 "@ 13754 add %1, r63, %0 13755 movi %1, %0 13756 # 13757 ld%M1.q %m1, %0 13758 st%M0.q %m0, %N1" 13759 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media") 13760 (set_attr "length" "4,4,16,4,4") 13761 (set_attr "highpart" "depend")]) 13762 13763(define_expand "movv2si" 13764 [(set (match_operand:V2SI 0 "general_movdst_operand" "") 13765 (match_operand:V2SI 1 "general_movsrc_operand" ""))] 13766 "TARGET_SHMEDIA" 13767{ 13768 prepare_move_operands (operands, V2SImode); 13769}) 13770 13771(define_insn "movv2si_i" 13772 [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m") 13773 (match_operand:V2SI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))] 13774 "TARGET_SHMEDIA 13775 && (register_operand (operands[0], V2SImode) 13776 || sh_register_operand (operands[1], V2SImode))" 13777 "@ 13778 add %1, r63, %0 13779 # 13780 # 13781 ld%M1.q %m1, %0 13782 st%M0.q %m0, %N1" 13783 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media") 13784 (set_attr "length" "4,4,16,4,4") 13785 (set_attr "highpart" "depend")]) 13786 13787;; ------------------------------------------------------------------------- 13788;; Multimedia Intrinsics 13789;; ------------------------------------------------------------------------- 13790 13791(define_insn "absv2si2" 13792 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 13793 (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))] 13794 "TARGET_SHMEDIA" 13795 "mabs.l %1, %0" 13796 [(set_attr "type" "mcmp_media") 13797 (set_attr "highpart" "depend")]) 13798 13799(define_insn "absv4hi2" 13800 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 13801 (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))] 13802 "TARGET_SHMEDIA" 13803 "mabs.w %1, %0" 13804 [(set_attr "type" "mcmp_media") 13805 (set_attr "highpart" "depend")]) 13806 13807(define_insn "addv2si3" 13808 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 13809 (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r") 13810 (match_operand:V2SI 2 "arith_reg_operand" "r")))] 13811 "TARGET_SHMEDIA" 13812 "madd.l %1, %2, %0" 13813 [(set_attr "type" "arith_media") 13814 (set_attr "highpart" "depend")]) 13815 13816(define_insn "addv4hi3" 13817 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 13818 (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r") 13819 (match_operand:V4HI 2 "arith_reg_operand" "r")))] 13820 "TARGET_SHMEDIA" 13821 "madd.w %1, %2, %0" 13822 [(set_attr "type" "arith_media") 13823 (set_attr "highpart" "depend")]) 13824 13825(define_insn_and_split "addv2hi3" 13826 [(set (match_operand:V2HI 0 "arith_reg_dest" "=r") 13827 (plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r") 13828 (match_operand:V2HI 2 "extend_reg_operand" "r")))] 13829 "TARGET_SHMEDIA" 13830 "#" 13831 "TARGET_SHMEDIA" 13832 [(const_int 0)] 13833{ 13834 rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0); 13835 rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0); 13836 rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0); 13837 rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0); 13838 rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0); 13839 13840 emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1)); 13841 emit_insn (gen_truncdisi2 (si_dst, di_dst)); 13842 DONE; 13843} 13844 [(set_attr "highpart" "must_split")]) 13845 13846(define_insn "ssaddv2si3" 13847 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 13848 (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r") 13849 (match_operand:V2SI 2 "arith_reg_operand" "r")))] 13850 "TARGET_SHMEDIA" 13851 "madds.l %1, %2, %0" 13852 [(set_attr "type" "mcmp_media") 13853 (set_attr "highpart" "depend")]) 13854 13855(define_insn "usaddv8qi3" 13856 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") 13857 (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r") 13858 (match_operand:V8QI 2 "arith_reg_operand" "r")))] 13859 "TARGET_SHMEDIA" 13860 "madds.ub %1, %2, %0" 13861 [(set_attr "type" "mcmp_media") 13862 (set_attr "highpart" "depend")]) 13863 13864(define_insn "ssaddv4hi3" 13865 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 13866 (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r") 13867 (match_operand:V4HI 2 "arith_reg_operand" "r")))] 13868 "TARGET_SHMEDIA" 13869 "madds.w %1, %2, %0" 13870 [(set_attr "type" "mcmp_media") 13871 (set_attr "highpart" "depend")]) 13872 13873(define_insn "negcmpeqv8qi" 13874 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") 13875 (neg:V8QI (eq:V8QI 13876 (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ") 13877 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))] 13878 "TARGET_SHMEDIA" 13879 "mcmpeq.b %N1, %N2, %0" 13880 [(set_attr "type" "mcmp_media") 13881 (set_attr "highpart" "depend")]) 13882 13883(define_insn "negcmpeqv2si" 13884 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 13885 (neg:V2SI (eq:V2SI 13886 (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ") 13887 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))] 13888 "TARGET_SHMEDIA" 13889 "mcmpeq.l %N1, %N2, %0" 13890 [(set_attr "type" "mcmp_media") 13891 (set_attr "highpart" "depend")]) 13892 13893(define_insn "negcmpeqv4hi" 13894 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 13895 (neg:V4HI (eq:V4HI 13896 (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ") 13897 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))] 13898 "TARGET_SHMEDIA" 13899 "mcmpeq.w %N1, %N2, %0" 13900 [(set_attr "type" "mcmp_media") 13901 (set_attr "highpart" "depend")]) 13902 13903(define_insn "negcmpgtuv8qi" 13904 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") 13905 (neg:V8QI (gtu:V8QI 13906 (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ") 13907 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))] 13908 "TARGET_SHMEDIA" 13909 "mcmpgt.ub %N1, %N2, %0" 13910 [(set_attr "type" "mcmp_media") 13911 (set_attr "highpart" "depend")]) 13912 13913(define_insn "negcmpgtv2si" 13914 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 13915 (neg:V2SI (gt:V2SI 13916 (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ") 13917 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))] 13918 "TARGET_SHMEDIA" 13919 "mcmpgt.l %N1, %N2, %0" 13920 [(set_attr "type" "mcmp_media") 13921 (set_attr "highpart" "depend")]) 13922 13923(define_insn "negcmpgtv4hi" 13924 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 13925 (neg:V4HI (gt:V4HI 13926 (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ") 13927 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))] 13928 "TARGET_SHMEDIA" 13929 "mcmpgt.w %N1, %N2, %0" 13930 [(set_attr "type" "mcmp_media") 13931 (set_attr "highpart" "depend")]) 13932 13933(define_insn "mcmv" 13934 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 13935 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 13936 (match_operand:DI 2 "arith_reg_operand" "r")) 13937 (and:DI (match_operand:DI 3 "arith_reg_operand" "0") 13938 (not:DI (match_dup 2)))))] 13939 "TARGET_SHMEDIA" 13940 "mcmv %N1, %2, %0" 13941 [(set_attr "type" "arith_media") 13942 (set_attr "highpart" "depend")]) 13943 13944(define_insn "mcnvs_lw" 13945 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 13946 (vec_concat:V4HI 13947 (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")) 13948 (ss_truncate:V2HI 13949 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))] 13950 "TARGET_SHMEDIA" 13951 "mcnvs.lw %N1, %N2, %0" 13952 [(set_attr "type" "mcmp_media")]) 13953 13954(define_insn "mcnvs_wb" 13955 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") 13956 (vec_concat:V8QI 13957 (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")) 13958 (ss_truncate:V4QI 13959 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))] 13960 "TARGET_SHMEDIA" 13961 "mcnvs.wb %N1, %N2, %0" 13962 [(set_attr "type" "mcmp_media")]) 13963 13964(define_insn "mcnvs_wub" 13965 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") 13966 (vec_concat:V8QI 13967 (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")) 13968 (us_truncate:V4QI 13969 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))] 13970 "TARGET_SHMEDIA" 13971 "mcnvs.wub %N1, %N2, %0" 13972 [(set_attr "type" "mcmp_media")]) 13973 13974(define_insn "mextr_rl" 13975 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 13976 (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 13977 (match_operand:HI 3 "mextr_bit_offset" "i")) 13978 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ") 13979 (match_operand:HI 4 "mextr_bit_offset" "i"))))] 13980 "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64" 13981{ 13982 static char templ[21]; 13983 sprintf (templ, "mextr%d %%N1, %%N2, %%0", 13984 (int) INTVAL (operands[3]) >> 3); 13985 return templ; 13986} 13987 [(set_attr "type" "arith_media")]) 13988 13989(define_insn "*mextr_lr" 13990 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 13991 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 13992 (match_operand:HI 3 "mextr_bit_offset" "i")) 13993 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ") 13994 (match_operand:HI 4 "mextr_bit_offset" "i"))))] 13995 "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64" 13996{ 13997 static char templ[21]; 13998 sprintf (templ, "mextr%d %%N2, %%N1, %%0", 13999 (int) INTVAL (operands[4]) >> 3); 14000 return templ; 14001} 14002 [(set_attr "type" "arith_media")]) 14003 14004; mextrN can be modelled with vec_select / vec_concat, but the selection 14005; vector then varies depending on endianness. 14006(define_expand "mextr1" 14007 [(match_operand:DI 0 "arith_reg_dest" "") 14008 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 14009 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")] 14010 "TARGET_SHMEDIA" 14011{ 14012 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2], 14013 GEN_INT (1 * 8), GEN_INT (7 * 8))); 14014 DONE; 14015}) 14016 14017(define_expand "mextr2" 14018 [(match_operand:DI 0 "arith_reg_dest" "") 14019 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 14020 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")] 14021 "TARGET_SHMEDIA" 14022{ 14023 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2], 14024 GEN_INT (2 * 8), GEN_INT (6 * 8))); 14025 DONE; 14026}) 14027 14028(define_expand "mextr3" 14029 [(match_operand:DI 0 "arith_reg_dest" "") 14030 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 14031 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")] 14032 "TARGET_SHMEDIA" 14033{ 14034 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2], 14035 GEN_INT (3 * 8), GEN_INT (5 * 8))); 14036 DONE; 14037}) 14038 14039(define_expand "mextr4" 14040 [(match_operand:DI 0 "arith_reg_dest" "") 14041 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 14042 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")] 14043 "TARGET_SHMEDIA" 14044{ 14045 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2], 14046 GEN_INT (4 * 8), GEN_INT (4 * 8))); 14047 DONE; 14048}) 14049 14050(define_expand "mextr5" 14051 [(match_operand:DI 0 "arith_reg_dest" "") 14052 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 14053 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")] 14054 "TARGET_SHMEDIA" 14055{ 14056 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2], 14057 GEN_INT (5 * 8), GEN_INT (3 * 8))); 14058 DONE; 14059}) 14060 14061(define_expand "mextr6" 14062 [(match_operand:DI 0 "arith_reg_dest" "") 14063 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 14064 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")] 14065 "TARGET_SHMEDIA" 14066{ 14067 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2], 14068 GEN_INT (6 * 8), GEN_INT (2 * 8))); 14069 DONE; 14070}) 14071 14072(define_expand "mextr7" 14073 [(match_operand:DI 0 "arith_reg_dest" "") 14074 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 14075 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")] 14076 "TARGET_SHMEDIA" 14077{ 14078 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2], 14079 GEN_INT (7 * 8), GEN_INT (1 * 8))); 14080 DONE; 14081}) 14082 14083(define_expand "mmacfx_wl" 14084 [(match_operand:V2SI 0 "arith_reg_dest" "") 14085 (match_operand:V2HI 1 "extend_reg_operand" "") 14086 (match_operand:V2HI 2 "extend_reg_operand" "") 14087 (match_operand:V2SI 3 "arith_reg_operand" "")] 14088 "TARGET_SHMEDIA" 14089{ 14090 emit_insn (gen_mmacfx_wl_i (operands[0], operands[3], 14091 operands[1], operands[2])); 14092 DONE; 14093}) 14094 14095;; This could be highpart ignore if it only had inputs 2 or 3, but input 1 14096;; is depend 14097(define_insn "mmacfx_wl_i" 14098 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 14099 (ss_plus:V2SI 14100 (match_operand:V2SI 1 "arith_reg_operand" "0") 14101 (ss_truncate:V2SI 14102 (ashift:V2DI 14103 (sign_extend:V2DI 14104 (mult:V2SI 14105 (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r")) 14106 (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r")))) 14107 (const_int 1)))))] 14108 "TARGET_SHMEDIA" 14109 "mmacfx.wl %2, %3, %0" 14110 [(set_attr "type" "mac_media") 14111 (set_attr "highpart" "depend")]) 14112 14113(define_expand "mmacnfx_wl" 14114 [(match_operand:V2SI 0 "arith_reg_dest" "") 14115 (match_operand:V2HI 1 "extend_reg_operand" "") 14116 (match_operand:V2HI 2 "extend_reg_operand" "") 14117 (match_operand:V2SI 3 "arith_reg_operand" "")] 14118 "TARGET_SHMEDIA" 14119{ 14120 emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3], 14121 operands[1], operands[2])); 14122 DONE; 14123}) 14124 14125(define_insn "mmacnfx_wl_i" 14126 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 14127 (ss_minus:V2SI 14128 (match_operand:V2SI 1 "arith_reg_operand" "0") 14129 (ss_truncate:V2SI 14130 (ashift:V2DI 14131 (sign_extend:V2DI 14132 (mult:V2SI 14133 (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r")) 14134 (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r")))) 14135 (const_int 1)))))] 14136 "TARGET_SHMEDIA" 14137 "mmacnfx.wl %2, %3, %0" 14138 [(set_attr "type" "mac_media") 14139 (set_attr "highpart" "depend")]) 14140 14141(define_insn "mulv2si3" 14142 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 14143 (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r") 14144 (match_operand:V2SI 2 "arith_reg_operand" "r")))] 14145 "TARGET_SHMEDIA" 14146 "mmul.l %1, %2, %0" 14147 [(set_attr "type" "d2mpy_media") 14148 (set_attr "highpart" "depend")]) 14149 14150(define_insn "mulv4hi3" 14151 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 14152 (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r") 14153 (match_operand:V4HI 2 "arith_reg_operand" "r")))] 14154 "TARGET_SHMEDIA" 14155 "mmul.w %1, %2, %0" 14156 [(set_attr "type" "dmpy_media") 14157 (set_attr "highpart" "depend")]) 14158 14159(define_insn "mmulfx_l" 14160 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 14161 (ss_truncate:V2SI 14162 (ashiftrt:V2DI 14163 (mult:V2DI 14164 (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r")) 14165 (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r"))) 14166 (const_int 31))))] 14167 "TARGET_SHMEDIA" 14168 "mmulfx.l %1, %2, %0" 14169 [(set_attr "type" "d2mpy_media") 14170 (set_attr "highpart" "depend")]) 14171 14172(define_insn "mmulfx_w" 14173 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 14174 (ss_truncate:V4HI 14175 (ashiftrt:V4SI 14176 (mult:V4SI 14177 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r")) 14178 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r"))) 14179 (const_int 15))))] 14180 "TARGET_SHMEDIA" 14181 "mmulfx.w %1, %2, %0" 14182 [(set_attr "type" "dmpy_media") 14183 (set_attr "highpart" "depend")]) 14184 14185(define_insn "mmulfxrp_w" 14186 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 14187 (ss_truncate:V4HI 14188 (ashiftrt:V4SI 14189 (plus:V4SI 14190 (mult:V4SI 14191 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r")) 14192 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r"))) 14193 (const_int 16384)) 14194 (const_int 15))))] 14195 "TARGET_SHMEDIA" 14196 "mmulfxrp.w %1, %2, %0" 14197 [(set_attr "type" "dmpy_media") 14198 (set_attr "highpart" "depend")]) 14199 14200 14201(define_expand "mmulhi_wl" 14202 [(match_operand:V2SI 0 "arith_reg_dest" "") 14203 (match_operand:V4HI 1 "arith_reg_operand" "") 14204 (match_operand:V4HI 2 "arith_reg_operand" "")] 14205 "TARGET_SHMEDIA" 14206{ 14207 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl) 14208 (operands[0], operands[1], operands[2])); 14209 DONE; 14210}) 14211 14212(define_expand "mmullo_wl" 14213 [(match_operand:V2SI 0 "arith_reg_dest" "") 14214 (match_operand:V4HI 1 "arith_reg_operand" "") 14215 (match_operand:V4HI 2 "arith_reg_operand" "")] 14216 "TARGET_SHMEDIA" 14217{ 14218 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl) 14219 (operands[0], operands[1], operands[2])); 14220 DONE; 14221}) 14222 14223(define_insn "mmul23_wl" 14224 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 14225 (vec_select:V2SI 14226 (mult:V4SI 14227 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r")) 14228 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r"))) 14229 (parallel [(const_int 2) (const_int 3)])))] 14230 "TARGET_SHMEDIA" 14231{ 14232 return (TARGET_LITTLE_ENDIAN 14233 ? "mmulhi.wl %1, %2, %0" 14234 : "mmullo.wl %1, %2, %0"); 14235} 14236 [(set_attr "type" "dmpy_media") 14237 (set (attr "highpart") 14238 (cond [(eq_attr "endian" "big") (const_string "ignore")] 14239 (const_string "user")))]) 14240 14241(define_insn "mmul01_wl" 14242 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 14243 (vec_select:V2SI 14244 (mult:V4SI 14245 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r")) 14246 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r"))) 14247 (parallel [(const_int 0) (const_int 1)])))] 14248 "TARGET_SHMEDIA" 14249{ 14250 return (TARGET_LITTLE_ENDIAN 14251 ? "mmullo.wl %1, %2, %0" 14252 : "mmulhi.wl %1, %2, %0"); 14253} 14254 [(set_attr "type" "dmpy_media") 14255 (set (attr "highpart") 14256 (cond [(eq_attr "endian" "little") (const_string "ignore")] 14257 (const_string "user")))]) 14258 14259 14260(define_expand "mmulsum_wq" 14261 [(match_operand:DI 0 "arith_reg_dest" "") 14262 (match_operand:V4HI 1 "arith_reg_operand" "") 14263 (match_operand:V4HI 2 "arith_reg_operand" "") 14264 (match_operand:DI 3 "arith_reg_operand" "")] 14265 "TARGET_SHMEDIA" 14266{ 14267 emit_insn (gen_mmulsum_wq_i (operands[0], operands[3], 14268 operands[1], operands[2])); 14269 DONE; 14270}) 14271 14272(define_insn "mmulsum_wq_i" 14273 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 14274 (plus:DI (match_operand:DI 1 "arith_reg_operand" "0") 14275 (plus:DI 14276 (plus:DI 14277 (vec_select:DI 14278 (mult:V4DI 14279 (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r")) 14280 (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r"))) 14281 (parallel [(const_int 0)])) 14282 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2)) 14283 (sign_extend:V4DI (match_dup 3))) 14284 (parallel [(const_int 1)]))) 14285 (plus:DI 14286 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2)) 14287 (sign_extend:V4DI (match_dup 3))) 14288 (parallel [(const_int 2)])) 14289 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2)) 14290 (sign_extend:V4DI (match_dup 3))) 14291 (parallel [(const_int 3)]))))))] 14292 "TARGET_SHMEDIA" 14293 "mmulsum.wq %2, %3, %0" 14294 [(set_attr "type" "mac_media")]) 14295 14296(define_expand "mperm_w" 14297 [(match_operand:V4HI 0 "arith_reg_dest" "=r") 14298 (match_operand:V4HI 1 "arith_reg_operand" "r") 14299 (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")] 14300 "TARGET_SHMEDIA" 14301{ 14302 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big) 14303 (operands[0], operands[1], operands[2])); 14304 DONE; 14305}) 14306 14307; This use of vec_select isn't exactly correct according to rtl.texi 14308; (because not constant), but it seems a straightforward extension. 14309(define_insn "mperm_w_little" 14310 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 14311 (vec_select:V4HI 14312 (match_operand:V4HI 1 "arith_reg_operand" "r") 14313 (parallel 14314 [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ") 14315 (const_int 2) (const_int 0)) 14316 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2)) 14317 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4)) 14318 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))] 14319 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN" 14320 "mperm.w %1, %N2, %0" 14321 [(set_attr "type" "arith_media")]) 14322 14323(define_insn "mperm_w_big" 14324 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 14325 (vec_select:V4HI 14326 (match_operand:V4HI 1 "arith_reg_operand" "r") 14327 (parallel 14328 [(zero_extract:QI (not:QI (match_operand:QI 2 14329 "extend_reg_or_0_operand" "rZ")) 14330 (const_int 2) (const_int 0)) 14331 (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2)) 14332 (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4)) 14333 (zero_extract:QI (not:QI (match_dup 2)) 14334 (const_int 2) (const_int 6))])))] 14335 "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN" 14336 "mperm.w %1, %N2, %0" 14337 [(set_attr "type" "arith_media")]) 14338 14339(define_insn "mperm_w0" 14340 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 14341 (vec_duplicate:V4HI (truncate:HI (match_operand 1 14342 "trunc_hi_operand" "r"))))] 14343 "TARGET_SHMEDIA" 14344 "mperm.w %1, r63, %0" 14345 [(set_attr "type" "arith_media") 14346 (set_attr "highpart" "ignore")]) 14347 14348(define_expand "msad_ubq" 14349 [(match_operand:DI 0 "arith_reg_dest" "") 14350 (match_operand:V8QI 1 "arith_reg_or_0_operand" "") 14351 (match_operand:V8QI 2 "arith_reg_or_0_operand" "") 14352 (match_operand:DI 3 "arith_reg_operand" "")] 14353 "TARGET_SHMEDIA" 14354{ 14355 emit_insn (gen_msad_ubq_i (operands[0], operands[3], 14356 operands[1], operands[2])); 14357 DONE; 14358}) 14359 14360(define_insn "msad_ubq_i" 14361 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 14362 (plus:DI 14363 (plus:DI 14364 (plus:DI 14365 (plus:DI 14366 (match_operand:DI 1 "arith_reg_operand" "0") 14367 (abs:DI (vec_select:DI 14368 (minus:V8DI 14369 (zero_extend:V8DI 14370 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")) 14371 (zero_extend:V8DI 14372 (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ"))) 14373 (parallel [(const_int 0)])))) 14374 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) 14375 (zero_extend:V8DI (match_dup 3))) 14376 (parallel [(const_int 1)])))) 14377 (plus:DI 14378 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) 14379 (zero_extend:V8DI (match_dup 3))) 14380 (parallel [(const_int 2)]))) 14381 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) 14382 (zero_extend:V8DI (match_dup 3))) 14383 (parallel [(const_int 3)]))))) 14384 (plus:DI 14385 (plus:DI 14386 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) 14387 (zero_extend:V8DI (match_dup 3))) 14388 (parallel [(const_int 4)]))) 14389 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) 14390 (zero_extend:V8DI (match_dup 3))) 14391 (parallel [(const_int 5)])))) 14392 (plus:DI 14393 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) 14394 (zero_extend:V8DI (match_dup 3))) 14395 (parallel [(const_int 6)]))) 14396 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) 14397 (zero_extend:V8DI (match_dup 3))) 14398 (parallel [(const_int 7)])))))))] 14399 "TARGET_SHMEDIA" 14400 "msad.ubq %N2, %N3, %0" 14401 [(set_attr "type" "mac_media")]) 14402 14403(define_insn "mshalds_l" 14404 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 14405 (ss_truncate:V2SI 14406 (ashift:V2DI 14407 (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r")) 14408 (and:DI (match_operand:DI 2 "arith_reg_operand" "r") 14409 (const_int 31)))))] 14410 "TARGET_SHMEDIA" 14411 "mshalds.l %1, %2, %0" 14412 [(set_attr "type" "mcmp_media") 14413 (set_attr "highpart" "depend")]) 14414 14415(define_insn "mshalds_w" 14416 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 14417 (ss_truncate:V4HI 14418 (ashift:V4SI 14419 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r")) 14420 (and:DI (match_operand:DI 2 "arith_reg_operand" "r") 14421 (const_int 15)))))] 14422 "TARGET_SHMEDIA" 14423 "mshalds.w %1, %2, %0" 14424 [(set_attr "type" "mcmp_media") 14425 (set_attr "highpart" "depend")]) 14426 14427(define_insn "ashrv2si3" 14428 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 14429 (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r") 14430 (match_operand:DI 2 "arith_reg_operand" "r")))] 14431 "TARGET_SHMEDIA" 14432 "mshard.l %1, %2, %0" 14433 [(set_attr "type" "arith_media") 14434 (set_attr "highpart" "depend")]) 14435 14436(define_insn "ashrv4hi3" 14437 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 14438 (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r") 14439 (match_operand:DI 2 "arith_reg_operand" "r")))] 14440 "TARGET_SHMEDIA" 14441 "mshard.w %1, %2, %0" 14442 [(set_attr "type" "arith_media") 14443 (set_attr "highpart" "depend")]) 14444 14445(define_insn "mshards_q" 14446 [(set (match_operand:HI 0 "arith_reg_dest" "=r") 14447 (ss_truncate:HI 14448 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r") 14449 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))] 14450 "TARGET_SHMEDIA" 14451 "mshards.q %1, %N2, %0" 14452 [(set_attr "type" "mcmp_media")]) 14453 14454(define_expand "mshfhi_b" 14455 [(match_operand:V8QI 0 "arith_reg_dest" "") 14456 (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ") 14457 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")] 14458 "TARGET_SHMEDIA" 14459{ 14460 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b) 14461 (operands[0], operands[1], operands[2])); 14462 DONE; 14463}) 14464 14465(define_expand "mshflo_b" 14466 [(match_operand:V8QI 0 "arith_reg_dest" "") 14467 (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ") 14468 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")] 14469 "TARGET_SHMEDIA" 14470{ 14471 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b) 14472 (operands[0], operands[1], operands[2])); 14473 DONE; 14474}) 14475 14476(define_insn "mshf4_b" 14477 [(set 14478 (match_operand:V8QI 0 "arith_reg_dest" "=r") 14479 (vec_select:V8QI 14480 (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ") 14481 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")) 14482 (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13) 14483 (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))] 14484 "TARGET_SHMEDIA" 14485{ 14486 return (TARGET_LITTLE_ENDIAN 14487 ? "mshfhi.b %N1, %N2, %0" 14488 : "mshflo.b %N1, %N2, %0"); 14489} 14490 [(set_attr "type" "arith_media") 14491 (set (attr "highpart") 14492 (cond [(eq_attr "endian" "big") (const_string "ignore")] 14493 (const_string "user")))]) 14494 14495(define_insn "mshf0_b" 14496 [(set 14497 (match_operand:V8QI 0 "arith_reg_dest" "=r") 14498 (vec_select:V8QI 14499 (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ") 14500 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")) 14501 (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9) 14502 (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))] 14503 "TARGET_SHMEDIA" 14504{ 14505 return (TARGET_LITTLE_ENDIAN 14506 ? "mshflo.b %N1, %N2, %0" 14507 : "mshfhi.b %N1, %N2, %0"); 14508} 14509 [(set_attr "type" "arith_media") 14510 (set (attr "highpart") 14511 (cond [(eq_attr "endian" "little") (const_string "ignore")] 14512 (const_string "user")))]) 14513 14514(define_expand "mshfhi_l" 14515 [(match_operand:V2SI 0 "arith_reg_dest" "") 14516 (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ") 14517 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")] 14518 "TARGET_SHMEDIA" 14519{ 14520 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l) 14521 (operands[0], operands[1], operands[2])); 14522 DONE; 14523}) 14524 14525(define_expand "mshflo_l" 14526 [(match_operand:V2SI 0 "arith_reg_dest" "") 14527 (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ") 14528 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")] 14529 "TARGET_SHMEDIA" 14530{ 14531 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l) 14532 (operands[0], operands[1], operands[2])); 14533 DONE; 14534}) 14535 14536(define_insn "mshf4_l" 14537 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 14538 (vec_select:V2SI 14539 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ") 14540 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")) 14541 (parallel [(const_int 1) (const_int 3)])))] 14542 "TARGET_SHMEDIA" 14543{ 14544 return (TARGET_LITTLE_ENDIAN 14545 ? "mshfhi.l %N1, %N2, %0" 14546 : "mshflo.l %N1, %N2, %0"); 14547} 14548 [(set_attr "type" "arith_media") 14549 (set (attr "highpart") 14550 (cond [(eq_attr "endian" "big") (const_string "ignore")] 14551 (const_string "user")))]) 14552 14553(define_insn "mshf0_l" 14554 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 14555 (vec_select:V2SI 14556 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ") 14557 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")) 14558 (parallel [(const_int 0) (const_int 2)])))] 14559 "TARGET_SHMEDIA" 14560{ 14561 return (TARGET_LITTLE_ENDIAN 14562 ? "mshflo.l %N1, %N2, %0" 14563 : "mshfhi.l %N1, %N2, %0"); 14564} 14565 [(set_attr "type" "arith_media") 14566 (set (attr "highpart") 14567 (cond [(eq_attr "endian" "little") (const_string "ignore")] 14568 (const_string "user")))]) 14569 14570(define_expand "mshfhi_w" 14571 [(match_operand:V4HI 0 "arith_reg_dest" "") 14572 (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ") 14573 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")] 14574 "TARGET_SHMEDIA" 14575{ 14576 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w) 14577 (operands[0], operands[1], operands[2])); 14578 DONE; 14579}) 14580 14581(define_expand "mshflo_w" 14582 [(match_operand:V4HI 0 "arith_reg_dest" "") 14583 (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ") 14584 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")] 14585 "TARGET_SHMEDIA" 14586{ 14587 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w) 14588 (operands[0], operands[1], operands[2])); 14589 DONE; 14590}) 14591 14592(define_insn "mshf4_w" 14593 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 14594 (vec_select:V4HI 14595 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ") 14596 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")) 14597 (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))] 14598 "TARGET_SHMEDIA" 14599{ 14600 return (TARGET_LITTLE_ENDIAN 14601 ? "mshfhi.w %N1, %N2, %0" 14602 : "mshflo.w %N1, %N2, %0"); 14603} 14604 [(set_attr "type" "arith_media") 14605 (set (attr "highpart") 14606 (cond [(eq_attr "endian" "big") (const_string "ignore")] 14607 (const_string "user")))]) 14608 14609(define_insn "mshf0_w" 14610 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 14611 (vec_select:V4HI 14612 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ") 14613 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")) 14614 (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))] 14615 "TARGET_SHMEDIA" 14616{ 14617 return (TARGET_LITTLE_ENDIAN 14618 ? "mshflo.w %N1, %N2, %0" 14619 : "mshfhi.w %N1, %N2, %0"); 14620} 14621 [(set_attr "type" "arith_media") 14622 (set (attr "highpart") 14623 (cond [(eq_attr "endian" "little") (const_string "ignore")] 14624 (const_string "user")))]) 14625 14626(define_insn "mshflo_w_x" 14627 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 14628 (vec_select:V4HI 14629 (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ") 14630 (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ")) 14631 (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))] 14632 "TARGET_SHMEDIA" 14633 "mshflo.w %N1, %N2, %0" 14634 [(set_attr "type" "arith_media") 14635 (set_attr "highpart" "ignore")]) 14636 14637;; These are useful to expand ANDs and as combiner patterns. 14638(define_insn_and_split "mshfhi_l_di" 14639 [(set (match_operand:DI 0 "arith_reg_dest" "=r,f") 14640 (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f") 14641 (const_int 32)) 14642 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f") 14643 (const_int -4294967296))))] 14644 "TARGET_SHMEDIA" 14645 "@ 14646 mshfhi.l %N1, %N2, %0 14647 #" 14648 "TARGET_SHMEDIA && reload_completed 14649 && ! GENERAL_REGISTER_P (true_regnum (operands[0]))" 14650 [(set (match_dup 3) (match_dup 4)) 14651 (set (match_dup 5) (match_dup 6))] 14652{ 14653 operands[3] = gen_lowpart (SImode, operands[0]); 14654 operands[4] = gen_highpart (SImode, operands[1]); 14655 operands[5] = gen_highpart (SImode, operands[0]); 14656 operands[6] = gen_highpart (SImode, operands[2]); 14657} 14658 [(set_attr "type" "arith_media")]) 14659 14660(define_insn "*mshfhi_l_di_rev" 14661 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 14662 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 14663 (const_int -4294967296)) 14664 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ") 14665 (const_int 32))))] 14666 "TARGET_SHMEDIA" 14667 "mshfhi.l %N2, %N1, %0" 14668 [(set_attr "type" "arith_media")]) 14669 14670(define_split 14671 [(set (match_operand:DI 0 "arith_reg_dest" "") 14672 (ior:DI (zero_extend:DI (match_operand:SI 1 14673 "extend_reg_or_0_operand" "")) 14674 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "") 14675 (const_int -4294967296)))) 14676 (clobber (match_operand:DI 3 "arith_reg_dest" ""))] 14677 "TARGET_SHMEDIA" 14678 [(const_int 0)] 14679{ 14680 emit_insn (gen_ashldi3_media (operands[3], 14681 simplify_gen_subreg (DImode, operands[1], 14682 SImode, 0), 14683 GEN_INT (32))); 14684 emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2])); 14685 DONE; 14686}) 14687 14688(define_insn "mshflo_l_di" 14689 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 14690 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 14691 (const_int 4294967295)) 14692 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ") 14693 (const_int 32))))] 14694 14695 "TARGET_SHMEDIA" 14696 "mshflo.l %N1, %N2, %0" 14697 [(set_attr "type" "arith_media") 14698 (set_attr "highpart" "ignore")]) 14699 14700(define_insn "*mshflo_l_di_rev" 14701 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 14702 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 14703 (const_int 32)) 14704 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ") 14705 (const_int 4294967295))))] 14706 14707 "TARGET_SHMEDIA" 14708 "mshflo.l %N2, %N1, %0" 14709 [(set_attr "type" "arith_media") 14710 (set_attr "highpart" "ignore")]) 14711 14712;; Combiner pattern for trampoline initialization. 14713(define_insn_and_split "*double_shori" 14714 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 14715 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0") 14716 (const_int 32)) 14717 (match_operand:DI 2 "const_int_operand" "n")))] 14718 "TARGET_SHMEDIA 14719 && ! (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xffffffffUL)" 14720 "#" 14721 "rtx_equal_p (operands[0], operands[1])" 14722 [(const_int 0)] 14723{ 14724 HOST_WIDE_INT v = INTVAL (operands[2]); 14725 14726 emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v >> 16))); 14727 emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v & 65535))); 14728 DONE; 14729} 14730 [(set_attr "highpart" "ignore")]) 14731 14732(define_insn "*mshflo_l_di_x" 14733 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 14734 (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand" 14735 "rZ")) 14736 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ") 14737 (const_int 32))))] 14738 "TARGET_SHMEDIA" 14739 "mshflo.l %N1, %N2, %0" 14740 [(set_attr "type" "arith_media") 14741 (set_attr "highpart" "ignore")]) 14742 14743(define_insn_and_split "concat_v2sf" 14744 [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?") 14745;; (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f") 14746 (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f") 14747 (match_operand:SF 2 "register_operand" "rZ,f,f")))] 14748 "TARGET_SHMEDIA" 14749 "@ 14750 mshflo.l %N1, %N2, %0 14751 # 14752 #" 14753 "TARGET_SHMEDIA && reload_completed 14754 && ! GENERAL_REGISTER_P (true_regnum (operands[0]))" 14755 [(set (match_dup 3) (match_dup 1)) 14756 (set (match_dup 4) (match_dup 2))] 14757{ 14758 operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0); 14759 operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4); 14760} 14761 [(set_attr "type" "arith_media") 14762 (set_attr "highpart" "ignore")]) 14763 14764(define_insn "*mshflo_l_di_x_rev" 14765 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 14766 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 14767 (const_int 32)) 14768 (zero_extend:DI 14769 (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))] 14770 "TARGET_SHMEDIA" 14771 "mshflo.l %N2, %N1, %0" 14772 [(set_attr "type" "arith_media") 14773 (set_attr "highpart" "ignore")]) 14774 14775(define_insn "ashlv2si3" 14776 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 14777 (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r") 14778 (match_operand:DI 2 "shift_count_reg_operand" "r")))] 14779 "TARGET_SHMEDIA" 14780 "mshlld.l %1, %2, %0" 14781 [(set_attr "type" "arith_media") 14782 (set_attr "highpart" "depend")]) 14783 14784(define_split 14785 [(set (match_operand 0 "any_register_operand" "") 14786 (match_operator 3 "shift_operator" 14787 [(match_operand 1 "any_register_operand" "") 14788 (match_operand 2 "shift_count_reg_operand" "")]))] 14789 "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)" 14790 [(set (match_dup 0) (match_dup 3))] 14791{ 14792 rtx count = operands[2]; 14793 enum machine_mode outer_mode = GET_MODE (operands[2]), inner_mode; 14794 14795 while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND 14796 || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0) 14797 || GET_CODE (count) == TRUNCATE) 14798 count = XEXP (count, 0); 14799 inner_mode = GET_MODE (count); 14800 count = simplify_gen_subreg (outer_mode, count, inner_mode, 14801 subreg_lowpart_offset (outer_mode, inner_mode)); 14802 operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]), 14803 operands[1], count); 14804}) 14805 14806(define_insn "ashlv4hi3" 14807 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 14808 (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r") 14809 (match_operand:DI 2 "shift_count_reg_operand" "r")))] 14810 "TARGET_SHMEDIA" 14811 "mshlld.w %1, %2, %0" 14812 [(set_attr "type" "arith_media") 14813 (set_attr "highpart" "depend")]) 14814 14815(define_insn "lshrv2si3" 14816 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 14817 (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r") 14818 (match_operand:DI 2 "shift_count_reg_operand" "r")))] 14819 "TARGET_SHMEDIA" 14820 "mshlrd.l %1, %2, %0" 14821 [(set_attr "type" "arith_media") 14822 (set_attr "highpart" "depend")]) 14823 14824(define_insn "lshrv4hi3" 14825 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 14826 (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r") 14827 (match_operand:DI 2 "shift_count_reg_operand" "r")))] 14828 "TARGET_SHMEDIA" 14829 "mshlrd.w %1, %2, %0" 14830 [(set_attr "type" "arith_media") 14831 (set_attr "highpart" "depend")]) 14832 14833(define_insn "subv2si3" 14834 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 14835 (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ") 14836 (match_operand:V2SI 2 "arith_reg_operand" "r")))] 14837 "TARGET_SHMEDIA" 14838 "msub.l %N1, %2, %0" 14839 [(set_attr "type" "arith_media") 14840 (set_attr "highpart" "depend")]) 14841 14842(define_insn "subv4hi3" 14843 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 14844 (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ") 14845 (match_operand:V4HI 2 "arith_reg_operand" "r")))] 14846 "TARGET_SHMEDIA" 14847 "msub.w %N1, %2, %0" 14848 [(set_attr "type" "arith_media") 14849 (set_attr "highpart" "depend")]) 14850 14851(define_insn_and_split "subv2hi3" 14852 [(set (match_operand:V2HI 0 "arith_reg_dest" "=r") 14853 (minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ") 14854 (match_operand:V2HI 2 "arith_reg_operand" "r")))] 14855 "TARGET_SHMEDIA" 14856 "#" 14857 "TARGET_SHMEDIA" 14858 [(const_int 0)] 14859{ 14860 rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0); 14861 rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0); 14862 rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0); 14863 rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0); 14864 rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0); 14865 14866 emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1)); 14867 emit_insn (gen_truncdisi2 (si_dst, di_dst)); 14868 DONE; 14869} 14870 [(set_attr "highpart" "must_split")]) 14871 14872(define_insn "sssubv2si3" 14873 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 14874 (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ") 14875 (match_operand:V2SI 2 "arith_reg_operand" "r")))] 14876 "TARGET_SHMEDIA" 14877 "msubs.l %N1, %2, %0" 14878 [(set_attr "type" "mcmp_media") 14879 (set_attr "highpart" "depend")]) 14880 14881(define_insn "ussubv8qi3" 14882 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") 14883 (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ") 14884 (match_operand:V8QI 2 "arith_reg_operand" "r")))] 14885 "TARGET_SHMEDIA" 14886 "msubs.ub %N1, %2, %0" 14887 [(set_attr "type" "mcmp_media") 14888 (set_attr "highpart" "depend")]) 14889 14890(define_insn "sssubv4hi3" 14891 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 14892 (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ") 14893 (match_operand:V4HI 2 "arith_reg_operand" "r")))] 14894 "TARGET_SHMEDIA" 14895 "msubs.w %N1, %2, %0" 14896 [(set_attr "type" "mcmp_media") 14897 (set_attr "highpart" "depend")]) 14898 14899;; ------------------------------------------------------------------------- 14900;; Floating Point Intrinsics 14901;; ------------------------------------------------------------------------- 14902 14903(define_insn "fcosa_s" 14904 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 14905 (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")] 14906 UNSPEC_FCOSA))] 14907 "TARGET_SHMEDIA" 14908 "fcosa.s %1, %0" 14909 [(set_attr "type" "atrans_media")]) 14910 14911(define_insn "fsina_s" 14912 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 14913 (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")] 14914 UNSPEC_FSINA))] 14915 "TARGET_SHMEDIA" 14916 "fsina.s %1, %0" 14917 [(set_attr "type" "atrans_media")]) 14918 14919(define_insn "fipr" 14920 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 14921 (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1 14922 "fp_arith_reg_operand" "f") 14923 (match_operand:V4SF 2 14924 "fp_arith_reg_operand" "f")) 14925 (parallel [(const_int 0)])) 14926 (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2)) 14927 (parallel [(const_int 1)]))) 14928 (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2)) 14929 (parallel [(const_int 2)])) 14930 (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2)) 14931 (parallel [(const_int 3)])))))] 14932 "TARGET_SHMEDIA" 14933 "fipr.s %1, %2, %0" 14934 [(set_attr "type" "fparith_media")]) 14935 14936(define_insn "fsrra_s" 14937 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 14938 (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")] 14939 UNSPEC_FSRRA))] 14940 "TARGET_SHMEDIA" 14941 "fsrra.s %1, %0" 14942 [(set_attr "type" "atrans_media")]) 14943 14944(define_insn "ftrv" 14945 [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f") 14946 (plus:V4SF 14947 (plus:V4SF 14948 (mult:V4SF 14949 (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f") 14950 (parallel [(const_int 0) (const_int 5) 14951 (const_int 10) (const_int 15)])) 14952 (match_operand:V4SF 2 "fp_arith_reg_operand" "f")) 14953 (mult:V4SF 14954 (vec_select:V4SF (match_dup 1) 14955 (parallel [(const_int 4) (const_int 9) 14956 (const_int 14) (const_int 3)])) 14957 (vec_select:V4SF (match_dup 2) 14958 (parallel [(const_int 1) (const_int 2) 14959 (const_int 3) (const_int 0)])))) 14960 (plus:V4SF 14961 (mult:V4SF 14962 (vec_select:V4SF (match_dup 1) 14963 (parallel [(const_int 8) (const_int 13) 14964 (const_int 2) (const_int 7)])) 14965 (vec_select:V4SF (match_dup 2) 14966 (parallel [(const_int 2) (const_int 3) 14967 (const_int 0) (const_int 1)]))) 14968 (mult:V4SF 14969 (vec_select:V4SF (match_dup 1) 14970 (parallel [(const_int 12) (const_int 1) 14971 (const_int 6) (const_int 11)])) 14972 (vec_select:V4SF (match_dup 2) 14973 (parallel [(const_int 3) (const_int 0) 14974 (const_int 1) (const_int 2)]))))))] 14975 "TARGET_SHMEDIA" 14976 "ftrv.s %1, %2, %0" 14977 [(set_attr "type" "fparith_media")]) 14978 14979(define_insn "ldhi_l" 14980 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 14981 (zero_extract:SI 14982 (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p") 14983 (const_int 3)) 14984 (const_int -3))) 14985 (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1)) 14986 (const_int 0)))] 14987 "TARGET_SHMEDIA32" 14988 "ldhi.l %U1, %0" 14989 [(set_attr "type" "load_media")]) 14990 14991(define_insn "ldhi_q" 14992 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 14993 (zero_extract:DI 14994 (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p") 14995 (const_int 7)) 14996 (const_int -7))) 14997 (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1)) 14998 (const_int 0)))] 14999 "TARGET_SHMEDIA32" 15000 "ldhi.q %U1, %0" 15001 [(set_attr "type" "load_media")]) 15002 15003(define_insn_and_split "*ldhi_q_comb0" 15004 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 15005 (zero_extract:DI 15006 (mem:DI (plus:SI (ior:SI (plus:SI 15007 (match_operand:SI 1 "register_operand" "r") 15008 (match_operand:SI 2 "ua_offset" "I06")) 15009 (const_int 7)) 15010 (const_int -7))) 15011 (plus:SI (and:SI (match_dup 1) (const_int 7)) 15012 (const_int 1)) 15013 (const_int 0)))] 15014 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0" 15015 "#" 15016 "" 15017 [(pc)] 15018{ 15019 emit_insn (gen_ldhi_q (operands[0], 15020 gen_rtx_PLUS (SImode, operands[1], operands[2]))); 15021 DONE; 15022}) 15023 15024(define_insn_and_split "*ldhi_q_comb1" 15025 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 15026 (zero_extract:DI 15027 (mem:DI (plus:SI (ior:SI (plus:SI 15028 (match_operand:SI 1 "register_operand" "r") 15029 (match_operand:SI 2 "ua_offset" "I06")) 15030 (const_int 7)) 15031 (const_int -7))) 15032 (plus:SI (and:SI (plus:SI (match_dup 1) 15033 (match_operand:SI 3 "ua_offset" "I06")) 15034 (const_int 7)) 15035 (const_int 1)) 15036 (const_int 0)))] 15037 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8) 15038 && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])" 15039 "#" 15040 "" 15041 [(pc)] 15042{ 15043 emit_insn (gen_ldhi_q (operands[0], 15044 gen_rtx_PLUS (SImode, operands[1], operands[2]))); 15045 DONE; 15046}) 15047 15048(define_insn "ldlo_l" 15049 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 15050 (zero_extract:SI 15051 (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p") 15052 (const_int -4))) 15053 (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3))) 15054 (and:SI (match_dup 1) (const_int 3))))] 15055 "TARGET_SHMEDIA32" 15056 "ldlo.l %U1, %0" 15057 [(set_attr "type" "load_media")]) 15058 15059(define_insn "ldlo_q" 15060 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 15061 (zero_extract:DI 15062 (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p") 15063 (const_int -8))) 15064 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7))) 15065 (and:SI (match_dup 1) (const_int 7))))] 15066 "TARGET_SHMEDIA32" 15067 "ldlo.q %U1, %0" 15068 [(set_attr "type" "load_media")]) 15069 15070(define_insn_and_split "*ldlo_q_comb0" 15071 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 15072 (zero_extract:DI 15073 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r") 15074 (match_operand:SI 2 "ua_offset" "I06")) 15075 (const_int -8))) 15076 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7))) 15077 (and:SI (match_dup 1) (const_int 7))))] 15078 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0" 15079 "#" 15080 "" 15081 [(pc)] 15082{ 15083 emit_insn (gen_ldlo_q (operands[0], 15084 gen_rtx_PLUS (SImode, operands[1], operands[2]))); 15085 DONE; 15086}) 15087 15088(define_insn_and_split "*ldlo_q_comb1" 15089 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 15090 (zero_extract:DI 15091 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r") 15092 (match_operand:SI 2 "ua_offset" "I06")) 15093 (const_int -8))) 15094 (minus:SI (const_int 8) 15095 (and:SI (plus:SI (match_dup 1) 15096 (match_operand:SI 3 "ua_offset" "I06")) 15097 (const_int 7))) 15098 (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))] 15099 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8) 15100 && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])" 15101 "#" 15102 "" 15103 [(pc)] 15104{ 15105 emit_insn (gen_ldlo_q (operands[0], 15106 gen_rtx_PLUS (SImode, operands[1], operands[2]))); 15107 DONE; 15108}) 15109 15110(define_insn "sthi_l" 15111 [(set (zero_extract:SI 15112 (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p") 15113 (const_int 3)) 15114 (const_int -3))) 15115 (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1)) 15116 (const_int 0)) 15117 (match_operand:SI 1 "arith_reg_operand" "r"))] 15118 "TARGET_SHMEDIA32" 15119 "sthi.l %U0, %1" 15120 [(set_attr "type" "ustore_media")]) 15121 15122;; All unaligned stores are considered to be 'narrow' because they typically 15123;; operate on less that a quadword, and when they operate on a full quadword, 15124;; the vanilla store high / store low sequence will cause a stall if not 15125;; scheduled apart. 15126(define_insn "sthi_q" 15127 [(set (zero_extract:DI 15128 (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p") 15129 (const_int 7)) 15130 (const_int -7))) 15131 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1)) 15132 (const_int 0)) 15133 (match_operand:DI 1 "arith_reg_operand" "r"))] 15134 "TARGET_SHMEDIA32" 15135 "sthi.q %U0, %1" 15136 [(set_attr "type" "ustore_media")]) 15137 15138(define_insn_and_split "*sthi_q_comb0" 15139 [(set (zero_extract:DI 15140 (mem:DI (plus:SI (ior:SI (plus:SI 15141 (match_operand:SI 0 "register_operand" "r") 15142 (match_operand:SI 1 "ua_offset" "I06")) 15143 (const_int 7)) 15144 (const_int -7))) 15145 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1)) 15146 (const_int 0)) 15147 (match_operand:DI 2 "arith_reg_operand" "r"))] 15148 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0" 15149 "#" 15150 "" 15151 [(pc)] 15152{ 15153 emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]), 15154 operands[2])); 15155 DONE; 15156}) 15157 15158(define_insn_and_split "*sthi_q_comb1" 15159 [(set (zero_extract:DI 15160 (mem:DI (plus:SI (ior:SI (plus:SI 15161 (match_operand:SI 0 "register_operand" "r") 15162 (match_operand:SI 1 "ua_offset" "I06")) 15163 (const_int 7)) 15164 (const_int -7))) 15165 (plus:SI (and:SI (plus:SI (match_dup 0) 15166 (match_operand:SI 2 "ua_offset" "I06")) 15167 (const_int 7)) 15168 (const_int 1)) 15169 (const_int 0)) 15170 (match_operand:DI 3 "arith_reg_operand" "r"))] 15171 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8) 15172 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])" 15173 "#" 15174 "" 15175 [(pc)] 15176{ 15177 emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]), 15178 operands[3])); 15179 DONE; 15180}) 15181 15182;; This is highpart user because the address is used as full 64 bit. 15183(define_insn "stlo_l" 15184 [(set (zero_extract:SI 15185 (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p") 15186 (const_int -4))) 15187 (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3))) 15188 (and:SI (match_dup 0) (const_int 3))) 15189 (match_operand:SI 1 "arith_reg_operand" "r"))] 15190 "TARGET_SHMEDIA32" 15191 "stlo.l %U0, %1" 15192 [(set_attr "type" "ustore_media")]) 15193 15194(define_insn "stlo_q" 15195 [(set (zero_extract:DI 15196 (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p") 15197 (const_int -8))) 15198 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7))) 15199 (and:SI (match_dup 0) (const_int 7))) 15200 (match_operand:DI 1 "arith_reg_operand" "r"))] 15201 "TARGET_SHMEDIA32" 15202 "stlo.q %U0, %1" 15203 [(set_attr "type" "ustore_media")]) 15204 15205(define_insn_and_split "*stlo_q_comb0" 15206 [(set (zero_extract:DI 15207 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r") 15208 (match_operand:SI 1 "ua_offset" "I06")) 15209 (const_int -8))) 15210 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7))) 15211 (and:SI (match_dup 0) (const_int 7))) 15212 (match_operand:DI 2 "arith_reg_operand" "r"))] 15213 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0" 15214 "#" 15215 "" 15216 [(pc)] 15217{ 15218 emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]), 15219 operands[2])); 15220 DONE; 15221}) 15222 15223(define_insn_and_split "*stlo_q_comb1" 15224 [(set (zero_extract:DI 15225 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r") 15226 (match_operand:SI 1 "ua_offset" "I06")) 15227 (const_int -8))) 15228 (minus:SI (const_int 8) 15229 (and:SI (plus:SI (match_dup 0) 15230 (match_operand:SI 2 "ua_offset" "I06")) 15231 (const_int 7))) 15232 (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7))) 15233 (match_operand:DI 3 "arith_reg_operand" "r"))] 15234 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])" 15235 "#" 15236 "" 15237 [(pc)] 15238{ 15239 emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]), 15240 operands[3])); 15241 DONE; 15242}) 15243 15244(define_insn "ldhi_l64" 15245 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 15246 (zero_extract:SI 15247 (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p") 15248 (const_int 3)) 15249 (const_int -3))) 15250 (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1)) 15251 (const_int 0)))] 15252 "TARGET_SHMEDIA64" 15253 "ldhi.l %U1, %0" 15254 [(set_attr "type" "load_media")]) 15255 15256(define_insn "ldhi_q64" 15257 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 15258 (zero_extract:DI 15259 (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p") 15260 (const_int 7)) 15261 (const_int -7))) 15262 (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1)) 15263 (const_int 0)))] 15264 "TARGET_SHMEDIA64" 15265 "ldhi.q %U1, %0" 15266 [(set_attr "type" "load_media")]) 15267 15268(define_insn "ldlo_l64" 15269 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 15270 (zero_extract:SI 15271 (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p") 15272 (const_int -4))) 15273 (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3))) 15274 (and:DI (match_dup 1) (const_int 3))))] 15275 "TARGET_SHMEDIA64" 15276 "ldlo.l %U1, %0" 15277 [(set_attr "type" "load_media")]) 15278 15279(define_insn "ldlo_q64" 15280 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 15281 (zero_extract:DI 15282 (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p") 15283 (const_int -8))) 15284 (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7))) 15285 (and:DI (match_dup 1) (const_int 7))))] 15286 "TARGET_SHMEDIA64" 15287 "ldlo.q %U1, %0" 15288 [(set_attr "type" "load_media")]) 15289 15290(define_insn "sthi_l64" 15291 [(set (zero_extract:SI 15292 (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p") 15293 (const_int 3)) 15294 (const_int -3))) 15295 (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1)) 15296 (const_int 0)) 15297 (match_operand:SI 1 "arith_reg_operand" "r"))] 15298 "TARGET_SHMEDIA64" 15299 "sthi.l %U0, %1" 15300 [(set_attr "type" "ustore_media")]) 15301 15302(define_insn "sthi_q64" 15303 [(set (zero_extract:DI 15304 (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p") 15305 (const_int 7)) 15306 (const_int -7))) 15307 (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1)) 15308 (const_int 0)) 15309 (match_operand:DI 1 "arith_reg_operand" "r"))] 15310 "TARGET_SHMEDIA64" 15311 "sthi.q %U0, %1" 15312 [(set_attr "type" "ustore_media")]) 15313 15314(define_insn "stlo_l64" 15315 [(set (zero_extract:SI 15316 (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p") 15317 (const_int -4))) 15318 (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3))) 15319 (and:DI (match_dup 0) (const_int 3))) 15320 (match_operand:SI 1 "arith_reg_operand" "r"))] 15321 "TARGET_SHMEDIA64" 15322 "stlo.l %U0, %1" 15323 [(set_attr "type" "ustore_media")]) 15324 15325(define_insn "stlo_q64" 15326 [(set (zero_extract:DI 15327 (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p") 15328 (const_int -8))) 15329 (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7))) 15330 (and:DI (match_dup 0) (const_int 7))) 15331 (match_operand:DI 1 "arith_reg_operand" "r"))] 15332 "TARGET_SHMEDIA64" 15333 "stlo.q %U0, %1" 15334 [(set_attr "type" "ustore_media")]) 15335 15336(define_insn "nsb" 15337 [(set (match_operand:QI 0 "arith_reg_dest" "=r") 15338 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")] 15339 UNSPEC_NSB))] 15340 "TARGET_SHMEDIA" 15341 "nsb %1, %0" 15342 [(set_attr "type" "arith_media")]) 15343 15344(define_insn "nsbsi" 15345 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 15346 (zero_extend:SI 15347 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")] 15348 UNSPEC_NSB)))] 15349 "TARGET_SHMEDIA" 15350 "nsb %1, %0" 15351 [(set_attr "type" "arith_media")]) 15352 15353(define_insn "nsbdi" 15354 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 15355 (zero_extend:DI 15356 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")] 15357 UNSPEC_NSB)))] 15358 "TARGET_SHMEDIA" 15359 "nsb %1, %0" 15360 [(set_attr "type" "arith_media")]) 15361 15362(define_expand "ffsdi2" 15363 [(set (match_operand:DI 0 "arith_reg_dest" "") 15364 (ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))] 15365 "TARGET_SHMEDIA" 15366{ 15367 rtx scratch = gen_reg_rtx (DImode); 15368 rtx last; 15369 15370 emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx)); 15371 emit_insn (gen_xordi3 (scratch, operands[1], scratch)); 15372 emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx)); 15373 emit_insn (gen_nsbdi (scratch, scratch)); 15374 emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64))); 15375 emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch)); 15376 last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch)); 15377 set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (DImode, operands[0])); 15378 15379 DONE; 15380}) 15381 15382(define_expand "ffssi2" 15383 [(set (match_operand:SI 0 "arith_reg_dest" "") 15384 (ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))] 15385 "TARGET_SHMEDIA" 15386{ 15387 rtx scratch = gen_reg_rtx (SImode); 15388 rtx discratch = gen_reg_rtx (DImode); 15389 rtx last; 15390 15391 emit_insn (gen_adddi3 (discratch, 15392 simplify_gen_subreg (DImode, operands[1], SImode, 0), 15393 constm1_rtx)); 15394 emit_insn (gen_andcdi3 (discratch, 15395 simplify_gen_subreg (DImode, operands[1], SImode, 0), 15396 discratch)); 15397 emit_insn (gen_nsbsi (scratch, discratch)); 15398 last = emit_insn (gen_subsi3 (operands[0], 15399 force_reg (SImode, GEN_INT (63)), scratch)); 15400 set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (SImode, operands[0])); 15401 15402 DONE; 15403}) 15404 15405(define_insn "byterev" 15406 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") 15407 (vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r") 15408 (parallel [(const_int 7) (const_int 6) (const_int 5) 15409 (const_int 4) (const_int 3) (const_int 2) 15410 (const_int 1) (const_int 0)])))] 15411 "TARGET_SHMEDIA" 15412 "byterev %1, %0" 15413 [(set_attr "type" "arith_media")]) 15414 15415;; In user mode, the "pref" instruction will raise a RADDERR exception 15416;; for accesses to [0x80000000,0xffffffff]. This makes it an unsuitable 15417;; implementation of __builtin_prefetch for VxWorks RTPs. 15418(define_expand "prefetch" 15419 [(prefetch (match_operand 0 "address_operand" "") 15420 (match_operand:SI 1 "const_int_operand" "") 15421 (match_operand:SI 2 "const_int_operand" ""))] 15422 "(TARGET_SH2A || TARGET_SH3 || TARGET_SH5) 15423 && (TARGET_SHMEDIA || ! TARGET_VXWORKS_RTP)") 15424 15425(define_insn "*prefetch" 15426 [(prefetch (match_operand:SI 0 "register_operand" "r") 15427 (match_operand:SI 1 "const_int_operand" "n") 15428 (match_operand:SI 2 "const_int_operand" "n"))] 15429 "(TARGET_SH2A || TARGET_SH3 || TARGET_SHCOMPACT) && ! TARGET_VXWORKS_RTP" 15430 "pref @%0" 15431 [(set_attr "type" "other")]) 15432 15433(define_insn "*prefetch_media" 15434 [(prefetch (match_operand:QI 0 "address_operand" "p") 15435 (match_operand:SI 1 "const_int_operand" "n") 15436 (match_operand:SI 2 "const_int_operand" "n"))] 15437 "TARGET_SHMEDIA" 15438{ 15439 operands[0] = gen_rtx_MEM (QImode, operands[0]); 15440 output_asm_insn ("ld%M0.b %m0,r63", operands); 15441 return ""; 15442} 15443 [(set_attr "type" "other")]) 15444 15445(define_insn "alloco_i" 15446 [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p")) 15447 (unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))] 15448 "TARGET_SHMEDIA32" 15449{ 15450 rtx xops[2]; 15451 15452 if (GET_CODE (operands[0]) == PLUS) 15453 { 15454 xops[0] = XEXP (operands[0], 0); 15455 xops[1] = XEXP (operands[0], 1); 15456 } 15457 else 15458 { 15459 xops[0] = operands[0]; 15460 xops[1] = const0_rtx; 15461 } 15462 output_asm_insn ("alloco %0, %1", xops); 15463 return ""; 15464} 15465 [(set_attr "type" "other")]) 15466 15467(define_split 15468 [(set (match_operand 0 "any_register_operand" "") 15469 (match_operand 1 "" ""))] 15470 "TARGET_SHMEDIA && reload_completed" 15471 [(set (match_dup 0) (match_dup 1))] 15472{ 15473 int n_changes = 0; 15474 15475 for_each_rtx (&operands[1], shmedia_cleanup_truncate, &n_changes); 15476 if (!n_changes) 15477 FAIL; 15478}) 15479 15480;; ------------------------------------------------------------------------- 15481;; Stack Protector Patterns 15482;; ------------------------------------------------------------------------- 15483 15484(define_expand "stack_protect_set" 15485 [(set (match_operand 0 "memory_operand" "") 15486 (match_operand 1 "memory_operand" ""))] 15487 "" 15488{ 15489 if (TARGET_SHMEDIA) 15490 { 15491 if (TARGET_SHMEDIA64) 15492 emit_insn (gen_stack_protect_set_di_media (operands[0], operands[1])); 15493 else 15494 emit_insn (gen_stack_protect_set_si_media (operands[0], operands[1])); 15495 } 15496 else 15497 emit_insn (gen_stack_protect_set_si (operands[0], operands[1])); 15498 15499 DONE; 15500}) 15501 15502(define_insn "stack_protect_set_si" 15503 [(set (match_operand:SI 0 "memory_operand" "=m") 15504 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET)) 15505 (set (match_scratch:SI 2 "=&r") (const_int 0))] 15506 "!TARGET_SHMEDIA" 15507{ 15508 return "mov.l %1,%2" "\n" 15509 " mov.l %2,%0" "\n" 15510 " mov #0,%2"; 15511} 15512 [(set_attr "type" "other") 15513 (set_attr "length" "6")]) 15514 15515(define_insn "stack_protect_set_si_media" 15516 [(set (match_operand:SI 0 "memory_operand" "=m") 15517 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET)) 15518 (set (match_scratch:SI 2 "=&r") (const_int 0))] 15519 "TARGET_SHMEDIA" 15520{ 15521 return "ld%M1.l %m1,%2" "\n" 15522 " st%M0.l %m0,%2" "\n" 15523 " movi 0,%2"; 15524} 15525 [(set_attr "type" "other") 15526 (set_attr "length" "12")]) 15527 15528(define_insn "stack_protect_set_di_media" 15529 [(set (match_operand:DI 0 "memory_operand" "=m") 15530 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET)) 15531 (set (match_scratch:DI 2 "=&r") (const_int 0))] 15532 "TARGET_SHMEDIA64" 15533{ 15534 return "ld%M1.q %m1,%2" "\n" 15535 " st%M0.q %m0,%2" "\n" 15536 " movi 0,%2"; 15537} 15538 [(set_attr "type" "other") 15539 (set_attr "length" "12")]) 15540 15541(define_expand "stack_protect_test" 15542 [(match_operand 0 "memory_operand" "") 15543 (match_operand 1 "memory_operand" "") 15544 (match_operand 2 "" "")] 15545 "" 15546{ 15547 if (TARGET_SHMEDIA) 15548 { 15549 rtx tmp = gen_reg_rtx (GET_MODE (operands[0])); 15550 rtx test; 15551 15552 test = gen_rtx_NE (VOIDmode, tmp, const0_rtx); 15553 if (TARGET_SHMEDIA64) 15554 { 15555 emit_insn (gen_stack_protect_test_di_media (tmp, operands[0], 15556 operands[1])); 15557 emit_jump_insn (gen_cbranchdi4 (test, tmp, const0_rtx, operands[2])); 15558 } 15559 else 15560 { 15561 emit_insn (gen_stack_protect_test_si_media (tmp, operands[0], 15562 operands[1])); 15563 emit_jump_insn (gen_cbranchsi4 (test, tmp, const0_rtx, operands[2])); 15564 } 15565 } 15566 else 15567 { 15568 emit_insn (gen_stack_protect_test_si (operands[0], operands[1])); 15569 emit_jump_insn (gen_branch_true (operands[2])); 15570 } 15571 15572 DONE; 15573}) 15574 15575(define_insn "stack_protect_test_si" 15576 [(set (reg:SI T_REG) 15577 (unspec:SI [(match_operand:SI 0 "memory_operand" "m") 15578 (match_operand:SI 1 "memory_operand" "m")] 15579 UNSPEC_SP_TEST)) 15580 (set (match_scratch:SI 2 "=&r") (const_int 0)) 15581 (set (match_scratch:SI 3 "=&r") (const_int 0))] 15582 "!TARGET_SHMEDIA" 15583{ 15584 return "mov.l %0,%2" "\n" 15585 " mov.l %1,%3" "\n" 15586 " cmp/eq %2,%3" "\n" 15587 " mov #0,%2" "\n" 15588 " mov #0,%3"; 15589} 15590 [(set_attr "type" "other") 15591 (set_attr "length" "10")]) 15592 15593(define_insn "stack_protect_test_si_media" 15594 [(set (match_operand:SI 0 "register_operand" "=&r") 15595 (unspec:SI [(match_operand:SI 1 "memory_operand" "m") 15596 (match_operand:SI 2 "memory_operand" "m")] 15597 UNSPEC_SP_TEST)) 15598 (set (match_scratch:SI 3 "=&r") (const_int 0))] 15599 "TARGET_SHMEDIA" 15600{ 15601 return "ld%M1.l %m1,%0" "\n" 15602 " ld%M2.l %m2,%3" "\n" 15603 " cmpeq %0,%3,%0" "\n" 15604 " movi 0,%3"; 15605} 15606 [(set_attr "type" "other") 15607 (set_attr "length" "16")]) 15608 15609(define_insn "stack_protect_test_di_media" 15610 [(set (match_operand:DI 0 "register_operand" "=&r") 15611 (unspec:DI [(match_operand:DI 1 "memory_operand" "m") 15612 (match_operand:DI 2 "memory_operand" "m")] 15613 UNSPEC_SP_TEST)) 15614 (set (match_scratch:DI 3 "=&r") (const_int 0))] 15615 "TARGET_SHMEDIA64" 15616{ 15617 return "ld%M1.q %m1,%0" "\n" 15618 " ld%M2.q %m2,%3" "\n" 15619 " cmpeq %0,%3,%0" "\n" 15620 " movi 0,%3"; 15621} 15622 [(set_attr "type" "other") 15623 (set_attr "length" "16")]) 15624 15625;; ------------------------------------------------------------------------- 15626;; Atomic operations 15627;; ------------------------------------------------------------------------- 15628 15629(include "sync.md") 15630