sh.md revision 1.6
1;;- Machine description for Renesas / SuperH SH. 2;; Copyright (C) 1993-2016 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;; BSR is not generated by the compiler proper, but when relaxing, it 35;; generates .uses pseudo-ops that allow linker relaxation to create 36;; BSR. This is actually implemented in bfd/{coff,elf32}-sh.c 37 38;; Special constraints for SH machine description: 39;; 40;; t -- T 41;; x -- mac 42;; l -- pr 43;; z -- r0 44;; 45;; Special formats used for outputting SH instructions: 46;; 47;; %. -- print a .s if insn needs delay slot 48;; %@ -- print rte/rts if is/isn't an interrupt function 49;; %# -- output a nop if there is nothing to put in the delay slot 50;; %O -- print a constant without the # 51;; %R -- print the lsw reg of a double 52;; %S -- print the msw reg of a double 53;; %T -- print next word of a double REG or MEM 54;; 55;; Special predicates: 56;; 57;; arith_operand -- operand is valid source for arithmetic op 58;; arith_reg_operand -- operand is valid register for arithmetic op 59;; general_movdst_operand -- operand is valid move destination 60;; general_movsrc_operand -- operand is valid move source 61;; logical_operand -- operand is valid source for logical op 62 63;; ------------------------------------------------------------------------- 64;; Constants 65;; ------------------------------------------------------------------------- 66 67(define_constants [ 68 (AP_REG 145) 69 (PR_REG 146) 70 (T_REG 147) 71 (GBR_REG 144) 72 (MACH_REG 148) 73 (MACL_REG 149) 74 (FPUL_REG 150) 75 (RAP_REG 152) 76 77 (FPSCR_REG 151) 78 79 ;; Virtual FPSCR - bits that are used by FP ops. 80 (FPSCR_MODES_REG 154) 81 82 ;; Virtual FPSCR - bits that are updated by FP ops. 83 (FPSCR_STAT_REG 155) 84 85 (PIC_REG 12) 86 (FP_REG 14) 87 (SP_REG 15) 88 89 (PR_MEDIA_REG 18) 90 (T_MEDIA_REG 19) 91 92 (R0_REG 0) 93 (R1_REG 1) 94 (R2_REG 2) 95 (R3_REG 3) 96 (R4_REG 4) 97 (R5_REG 5) 98 (R6_REG 6) 99 (R7_REG 7) 100 (R8_REG 8) 101 (R9_REG 9) 102 (R10_REG 10) 103 (R20_REG 20) 104 (R21_REG 21) 105 (R22_REG 22) 106 (R23_REG 23) 107 108 (DR0_REG 64) 109 (DR2_REG 66) 110 (DR4_REG 68) 111 (FR23_REG 87) 112 113 (TR0_REG 128) 114 (TR1_REG 129) 115 (TR2_REG 130) 116 117 (XD0_REG 136) 118 119 (FPSCR_PR 524288) ;; 1 << 19 120 (FPSCR_SZ 1048576) ;; 1 << 20 121 (FPSCR_FR 2097152) ;; 1 << 21 122]) 123 124(define_c_enum "unspec" [ 125 ;; These are used with unspec. 126 UNSPEC_COMPACT_ARGS 127 UNSPEC_MOVA 128 UNSPEC_CASESI 129 UNSPEC_DATALABEL 130 UNSPEC_BBR 131 UNSPEC_SFUNC 132 UNSPEC_PIC 133 UNSPEC_GOT 134 UNSPEC_GOTOFF 135 UNSPEC_PLT 136 UNSPEC_CALLER 137 UNSPEC_GOTPLT 138 UNSPEC_PCREL 139 UNSPEC_ICACHE 140 UNSPEC_INIT_TRAMP 141 UNSPEC_FCOSA 142 UNSPEC_FSRRA 143 UNSPEC_FSINA 144 UNSPEC_NSB 145 UNSPEC_ALLOCO 146 UNSPEC_TLSGD 147 UNSPEC_TLSLDM 148 UNSPEC_TLSIE 149 UNSPEC_DTPOFF 150 UNSPEC_GOTTPOFF 151 UNSPEC_TPOFF 152 UNSPEC_RA 153 UNSPEC_DIV_INV_M0 154 UNSPEC_DIV_INV_M1 155 UNSPEC_DIV_INV_M2 156 UNSPEC_DIV_INV_M3 157 UNSPEC_DIV_INV20 158 UNSPEC_DIV_INV_TABLE 159 UNSPEC_ASHIFTRT 160 UNSPEC_THUNK 161 UNSPEC_CHKADD 162 UNSPEC_SP_SET 163 UNSPEC_SP_TEST 164 UNSPEC_MOVUA 165 ;; (unspec [VAL SHIFT] UNSPEC_EXTRACT_S16) computes (short) (VAL >> SHIFT). 166 ;; UNSPEC_EXTRACT_U16 is the unsigned equivalent. 167 UNSPEC_EXTRACT_S16 168 UNSPEC_EXTRACT_U16 169 ;; (unspec [TARGET ANCHOR] UNSPEC_SYMOFF) == TARGET - ANCHOR. 170 UNSPEC_SYMOFF 171 ;; (unspec [OFFSET ANCHOR] UNSPEC_PCREL_SYMOFF) == OFFSET - (ANCHOR - .). 172 UNSPEC_PCREL_SYMOFF 173 ;; For FDPIC 174 UNSPEC_GOTFUNCDESC 175 UNSPEC_GOTOFFFUNCDESC 176 ;; Misc builtins 177 UNSPEC_BUILTIN_STRLEN 178]) 179 180(define_c_enum "unspecv" [ 181 ;; These are used with unspec_volatile. 182 UNSPECV_BLOCKAGE 183 UNSPECV_ALIGN 184 UNSPECV_CONST2 185 UNSPECV_CONST4 186 UNSPECV_CONST8 187 UNSPECV_WINDOW_END 188 UNSPECV_CONST_END 189 UNSPECV_EH_RETURN 190 UNSPECV_GBR 191 UNSPECV_SP_SWITCH_B 192 UNSPECV_SP_SWITCH_E 193 194 UNSPECV_FPSCR_MODES 195 UNSPECV_FPSCR_STAT 196]) 197 198;; ------------------------------------------------------------------------- 199;; Attributes 200;; ------------------------------------------------------------------------- 201 202;; Target CPU. 203 204(define_attr "cpu" 205 "sh1,sh2,sh2e,sh2a,sh3,sh3e,sh4,sh4a,sh5" 206 (const (symbol_ref "sh_cpu_attr"))) 207 208(define_attr "endian" "big,little" 209 (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN") 210 (const_string "little") (const_string "big")))) 211 212;; Indicate if the default fpu mode is single precision. 213(define_attr "fpu_single" "yes,no" 214 (const (if_then_else (symbol_ref "TARGET_FPU_SINGLE") 215 (const_string "yes") (const_string "no")))) 216 217(define_attr "fmovd" "yes,no" 218 (const (if_then_else (symbol_ref "TARGET_FMOVD") 219 (const_string "yes") (const_string "no")))) 220;; pipeline model 221(define_attr "pipe_model" "sh1,sh4,sh5media" 222 (const 223 (cond [(symbol_ref "TARGET_SHMEDIA") (const_string "sh5media") 224 (symbol_ref "TARGET_SUPERSCALAR") (const_string "sh4")] 225 (const_string "sh1")))) 226 227;; cbranch conditional branch instructions 228;; jump unconditional jumps 229;; arith ordinary arithmetic 230;; arith3 a compound insn that behaves similarly to a sequence of 231;; three insns of type arith 232;; arith3b like above, but might end with a redirected branch 233;; load from memory 234;; load_si Likewise, SImode variant for general register. 235;; fload Likewise, but load to fp register. 236;; store to memory 237;; fstore floating point register to memory 238;; move general purpose register to register 239;; movi8 8-bit immediate to general purpose register 240;; mt_group other sh4 mt instructions 241;; fmove register to register, floating point 242;; smpy word precision integer multiply 243;; dmpy longword or doublelongword precision integer multiply 244;; return rts 245;; pload load of pr reg, which can't be put into delay slot of rts 246;; prset copy register to pr reg, ditto 247;; pstore store of pr reg, which can't be put into delay slot of jsr 248;; prget copy pr to register, ditto 249;; pcload pc relative load of constant value 250;; pcfload Likewise, but load to fp register. 251;; pcload_si Likewise, SImode variant for general register. 252;; rte return from exception 253;; sfunc special function call with known used registers 254;; call function call 255;; fp floating point 256;; fpscr_toggle toggle a bit in the fpscr 257;; fdiv floating point divide (or square root) 258;; gp_fpul move from general purpose register to fpul 259;; fpul_gp move from fpul to general purpose register 260;; mac_gp move from mac[lh] to general purpose register 261;; gp_mac move from general purpose register to mac[lh] 262;; mac_mem move from mac[lh] to memory 263;; mem_mac move from memory to mac[lh] 264;; dfp_arith,dfp_mul, fp_cmp,dfp_cmp,dfp_conv 265;; ftrc_s fix_truncsfsi2_i4 266;; dfdiv double precision floating point divide (or square root) 267;; cwb ic_invalidate_line_i 268;; movua SH4a unaligned load 269;; fsrra square root reciprocal approximate 270;; fsca sine and cosine approximate 271;; tls_load load TLS related address 272;; arith_media SHmedia arithmetic, logical, and shift instructions 273;; cbranch_media SHmedia conditional branch instructions 274;; cmp_media SHmedia compare instructions 275;; dfdiv_media SHmedia double precision divide and square root 276;; dfmul_media SHmedia double precision multiply instruction 277;; dfparith_media SHmedia double precision floating point arithmetic 278;; dfpconv_media SHmedia double precision floating point conversions 279;; dmpy_media SHmedia longword multiply 280;; fcmp_media SHmedia floating point compare instructions 281;; fdiv_media SHmedia single precision divide and square root 282;; fload_media SHmedia floating point register load instructions 283;; fmove_media SHmedia floating point register moves (inc. fabs and fneg) 284;; fparith_media SHmedia single precision floating point arithmetic 285;; fpconv_media SHmedia single precision floating point conversions 286;; fstore_media SHmedia floating point register store instructions 287;; gettr_media SHmedia gettr instruction 288;; invalidate_line_media SHmedia invalidate_line sequence 289;; jump_media SHmedia unconditional branch instructions 290;; load_media SHmedia general register load instructions 291;; pt_media SHmedia pt instruction (expanded by assembler) 292;; ptabs_media SHmedia ptabs instruction 293;; store_media SHmedia general register store instructions 294;; mcmp_media SHmedia multimedia compare, absolute, saturating ops 295;; mac_media SHmedia mac-style fixed point operations 296;; d2mpy_media SHmedia: two 32-bit integer multiplies 297;; atrans_media SHmedia approximate transcendental functions 298;; ustore_media SHmedia unaligned stores 299;; nil no-op move, will be deleted. 300 301(define_attr "type" 302 "mt_group,cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,load,load_si, 303 fload,store,fstore,move,movi8,fmove,smpy,dmpy,return,pload,prset,pstore, 304 prget,pcload,pcload_si,pcfload,rte,sfunc,call,fp,fpscr_toggle,fdiv,ftrc_s, 305 dfp_arith,dfp_mul,fp_cmp,dfp_cmp,dfp_conv,dfdiv,gp_fpul,fpul_gp,mac_gp, 306 gp_mac,mac_mem,mem_mac,mem_fpscr,gp_fpscr,cwb,movua,fsrra,fsca,tls_load, 307 arith_media,cbranch_media,cmp_media,dfdiv_media,dfmul_media,dfparith_media, 308 dfpconv_media,dmpy_media,fcmp_media,fdiv_media,fload_media,fmove_media, 309 fparith_media,fpconv_media,fstore_media,gettr_media,invalidate_line_media, 310 jump_media,load_media,pt_media,ptabs_media,store_media,mcmp_media,mac_media, 311 d2mpy_media,atrans_media,ustore_media,nil,other" 312 (const_string "other")) 313 314;; We define a new attribute namely "insn_class".We use 315;; this for the DFA based pipeline description. 316;; 317;; mt_group SH4 "mt" group instructions. 318;; 319;; ex_group SH4 "ex" group instructions. 320;; 321;; ls_group SH4 "ls" group instructions. 322;; 323(define_attr "insn_class" 324 "mt_group,ex_group,ls_group,br_group,fe_group,co_group,none" 325 (cond [(eq_attr "type" "move,mt_group") (const_string "mt_group") 326 (eq_attr "type" "movi8,arith,dyn_shift") (const_string "ex_group") 327 (eq_attr "type" "fmove,load,pcload,load_si,pcload_si,fload,pcfload, 328 store,fstore,gp_fpul,fpul_gp") (const_string "ls_group") 329 (eq_attr "type" "cbranch,jump") (const_string "br_group") 330 (eq_attr "type" "fp,fp_cmp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv") 331 (const_string "fe_group") 332 (eq_attr "type" "jump_ind,smpy,dmpy,mac_gp,return,pload,prset,pstore, 333 prget,rte,sfunc,call,dfp_cmp,mem_fpscr,gp_fpscr,cwb, 334 gp_mac,mac_mem,mem_mac") (const_string "co_group")] 335 (const_string "none"))) 336 337;; nil are zero instructions, and arith3 / arith3b are multiple instructions, 338;; so these do not belong in an insn group, although they are modeled 339;; with their own define_insn_reservations. 340 341;; Indicate what precision must be selected in fpscr for this insn, if any. 342(define_attr "fp_mode" "single,double,none" (const_string "none")) 343 344;; Indicate if the fpu mode is set by this instruction 345;; "unknown" must have the value as "none" in fp_mode, and means 346;; that the instruction/abi has left the processor in an unknown 347;; state. 348;; "none" means that nothing has changed and no mode is set. 349;; This attribute is only used for the Renesas ABI. 350(define_attr "fp_set" "single,double,unknown,none" (const_string "none")) 351 352; If a conditional branch destination is within -252..258 bytes away 353; from the instruction it can be 2 bytes long. Something in the 354; range -4090..4100 bytes can be 6 bytes long. All other conditional 355; branches are initially assumed to be 16 bytes long. 356; In machine_dependent_reorg, we split all branches that are longer than 357; 2 bytes. 358 359;; The maximum range used for SImode constant pool entries is 1018. A final 360;; instruction can add 8 bytes while only being 4 bytes in size, thus we 361;; can have a total of 1022 bytes in the pool. Add 4 bytes for a branch 362;; instruction around the pool table, 2 bytes of alignment before the table, 363;; and 30 bytes of alignment after the table. That gives a maximum total 364;; pool size of 1058 bytes. 365;; Worst case code/pool content size ratio is 1:2 (using asms). 366;; Thus, in the worst case, there is one instruction in front of a maximum 367;; sized pool, and then there are 1052 bytes of pool for every 508 bytes of 368;; code. For the last n bytes of code, there are 2n + 36 bytes of pool. 369;; If we have a forward branch, the initial table will be put after the 370;; unconditional branch. 371;; 372;; ??? We could do much better by keeping track of the actual pcloads within 373;; the branch range and in the pcload range in front of the branch range. 374 375;; ??? This looks ugly because genattrtab won't allow if_then_else or cond 376;; inside an le. 377(define_attr "short_cbranch_p" "no,yes" 378 (cond [(match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD") 379 (const_string "no") 380 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506)) 381 (const_string "yes") 382 (match_test "NEXT_INSN (PREV_INSN (insn)) != insn") 383 (const_string "no") 384 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508)) 385 (const_string "yes") 386 ] (const_string "no"))) 387 388(define_attr "med_branch_p" "no,yes" 389 (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990)) 390 (const_int 1988)) 391 (const_string "yes") 392 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD") 393 (const_string "no") 394 (leu (plus (minus (match_dup 0) (pc)) (const_int 4092)) 395 (const_int 8186)) 396 (const_string "yes") 397 ] (const_string "no"))) 398 399(define_attr "med_cbranch_p" "no,yes" 400 (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988)) 401 (const_int 1986)) 402 (const_string "yes") 403 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD") 404 (const_string "no") 405 (leu (plus (minus (match_dup 0) (pc)) (const_int 4090)) 406 (const_int 8184)) 407 (const_string "yes") 408 ] (const_string "no"))) 409 410(define_attr "braf_branch_p" "no,yes" 411 (cond [(match_test "! TARGET_SH2") 412 (const_string "no") 413 (leu (plus (minus (match_dup 0) (pc)) (const_int 10330)) 414 (const_int 20660)) 415 (const_string "yes") 416 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD") 417 (const_string "no") 418 (leu (plus (minus (match_dup 0) (pc)) (const_int 32764)) 419 (const_int 65530)) 420 (const_string "yes") 421 ] (const_string "no"))) 422 423(define_attr "braf_cbranch_p" "no,yes" 424 (cond [(match_test "! TARGET_SH2") 425 (const_string "no") 426 (leu (plus (minus (match_dup 0) (pc)) (const_int 10328)) 427 (const_int 20658)) 428 (const_string "yes") 429 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD") 430 (const_string "no") 431 (leu (plus (minus (match_dup 0) (pc)) (const_int 32762)) 432 (const_int 65528)) 433 (const_string "yes") 434 ] (const_string "no"))) 435 436;; An unconditional jump in the range -4092..4098 can be 2 bytes long. 437;; For wider ranges, we need a combination of a code and a data part. 438;; If we can get a scratch register for a long range jump, the code 439;; part can be 4 bytes long; otherwise, it must be 8 bytes long. 440;; If the jump is in the range -32764..32770, the data part can be 2 bytes 441;; long; otherwise, it must be 6 bytes long. 442 443;; All other instructions are two bytes long by default. 444 445;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)), 446;; but getattrtab doesn't understand this. 447(define_attr "length" "" 448 (cond [(eq_attr "type" "cbranch") 449 (cond [(eq_attr "short_cbranch_p" "yes") 450 (const_int 2) 451 (eq_attr "med_cbranch_p" "yes") 452 (const_int 6) 453 (eq_attr "braf_cbranch_p" "yes") 454 (const_int 12) 455;; ??? using pc is not computed transitively. 456 (ne (match_dup 0) (match_dup 0)) 457 (const_int 14) 458 (match_test "flag_pic") 459 (const_int 24) 460 ] (const_int 16)) 461 (eq_attr "type" "jump") 462 (cond [(eq_attr "med_branch_p" "yes") 463 (const_int 2) 464 (and (match_test "prev_nonnote_insn (insn)") 465 (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))") 466 (symbol_ref "INSN")) 467 (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))") 468 (symbol_ref "code_for_indirect_jump_scratch")))) 469 (cond [(eq_attr "braf_branch_p" "yes") 470 (const_int 6) 471 (not (match_test "flag_pic")) 472 (const_int 10) 473 (match_test "TARGET_SH2") 474 (const_int 10)] (const_int 18)) 475 (eq_attr "braf_branch_p" "yes") 476 (const_int 10) 477;; ??? using pc is not computed transitively. 478 (ne (match_dup 0) (match_dup 0)) 479 (const_int 12) 480 (match_test "flag_pic") 481 (const_int 22) 482 ] (const_int 14)) 483 (eq_attr "type" "pt_media") 484 (if_then_else (match_test "TARGET_SHMEDIA64") 485 (const_int 20) (const_int 12)) 486 (and (eq_attr "type" "jump_media") 487 (match_test "TARGET_SH5_CUT2_WORKAROUND")) 488 (const_int 8) 489 ] (if_then_else (match_test "TARGET_SHMEDIA") 490 (const_int 4) 491 (const_int 2)))) 492 493;; DFA descriptions for the pipelines 494 495(include "sh1.md") 496(include "shmedia.md") 497(include "sh4.md") 498 499(include "iterators.md") 500(include "predicates.md") 501(include "constraints.md") 502 503;; Definitions for filling delay slots 504 505(define_attr "needs_delay_slot" "yes,no" (const_string "no")) 506 507(define_attr "banked" "yes,no" 508 (cond [(match_test "sh_loads_bankedreg_p (insn)") 509 (const_string "yes")] 510 (const_string "no"))) 511 512;; ??? This should be (nil) instead of (const_int 0) 513(define_attr "hit_stack" "yes,no" 514 (cond [(not (match_test "find_regno_note (insn, REG_INC, SP_REG)")) 515 (const_string "no")] 516 (const_string "yes"))) 517 518(define_attr "interrupt_function" "no,yes" 519 (const (symbol_ref "current_function_interrupt"))) 520 521(define_attr "in_delay_slot" "yes,no" 522 (cond [(eq_attr "type" "cbranch") (const_string "no") 523 (eq_attr "type" "pcload,pcload_si") (const_string "no") 524 (eq_attr "type" "fpscr_toggle") (const_string "no") 525 (eq_attr "needs_delay_slot" "yes") (const_string "no") 526 (eq_attr "length" "2") (const_string "yes") 527 ] (const_string "no"))) 528 529(define_attr "cond_delay_slot" "yes,no" 530 (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes") 531 ] (const_string "no"))) 532 533(define_attr "is_sfunc" "" 534 (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0))) 535 536(define_attr "is_mac_media" "" 537 (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0))) 538 539(define_attr "branch_zero" "yes,no" 540 (cond [(eq_attr "type" "!cbranch") (const_string "no") 541 (ne (symbol_ref "(next_active_insn (insn)\ 542 == (prev_active_insn\ 543 (XEXP (SET_SRC (PATTERN (insn)), 1))))\ 544 && get_attr_length (next_active_insn (insn)) == 2") 545 (const_int 0)) 546 (const_string "yes")] 547 (const_string "no"))) 548 549;; SH4 Double-precision computation with double-precision result - 550;; the two halves are ready at different times. 551(define_attr "dfp_comp" "yes,no" 552 (cond [(eq_attr "type" "dfp_arith,dfp_mul,dfp_conv,dfdiv") (const_string "yes")] 553 (const_string "no"))) 554 555;; Insns for which the latency of a preceding fp insn is decreased by one. 556(define_attr "late_fp_use" "yes,no" (const_string "no")) 557;; And feeding insns for which this relevant. 558(define_attr "any_fp_comp" "yes,no" 559 (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv") 560 (const_string "yes")] 561 (const_string "no"))) 562 563(define_attr "any_int_load" "yes,no" 564 (cond [(eq_attr "type" "load,load_si,pcload,pcload_si") 565 (const_string "yes")] 566 (const_string "no"))) 567 568(define_attr "highpart" "user, ignore, extend, depend, must_split" 569 (const_string "user")) 570 571(define_delay 572 (eq_attr "needs_delay_slot" "yes") 573 [(eq_attr "in_delay_slot" "yes") (nil) (nil)]) 574 575;; Since a normal return (rts) implicitly uses the PR register, 576;; we can't allow PR register loads in an rts delay slot. 577;; On the SH1* and SH2*, the rte instruction reads the return pc from the 578;; stack, and thus we can't put a pop instruction in its delay slot. 579;; On the SH3* and SH4*, the rte instruction does not use the stack, so a 580;; pop instruction can go in the delay slot, unless it references a banked 581;; register (the register bank is switched by rte). 582(define_delay 583 (eq_attr "type" "return") 584 [(and (eq_attr "in_delay_slot" "yes") 585 (ior (and (eq_attr "interrupt_function" "no") 586 (eq_attr "type" "!pload,prset")) 587 (and (eq_attr "interrupt_function" "yes") 588 (ior (match_test "TARGET_SH3") (eq_attr "hit_stack" "no")) 589 (eq_attr "banked" "no")))) 590 (nil) (nil)]) 591 592;; Since a call implicitly uses the PR register, we can't allow 593;; a PR register store in a jsr delay slot. 594 595(define_delay 596 (ior (eq_attr "type" "call") (eq_attr "type" "sfunc")) 597 [(and (eq_attr "in_delay_slot" "yes") 598 (eq_attr "type" "!pstore,prget")) (nil) (nil)]) 599 600;; Conditional branches with delay slots are available starting with SH2. 601(define_delay 602 (and (eq_attr "type" "cbranch") (match_test "TARGET_SH2")) 603 [(eq_attr "cond_delay_slot" "yes") (nil) (nil)]) 604 605;; ------------------------------------------------------------------------- 606;; SImode signed integer comparisons 607;; ------------------------------------------------------------------------- 608 609;; Patterns to generate the tst instruction which are usually formed by 610;; the combine pass. 611;; The canonical form here being used is (eq (and (op) (op)) 0). 612;; For some bit patterns, such as contiguous bits, we also must accept 613;; zero_extract forms. Single bit tests are also handled via zero_extract 614;; patterns in the 'bit field extract patterns' section. All variants 615;; are eventually converted to the 'tstsi_t' insn. 616;; As long as pseudos can be created (before RA), 'tstsi_t' will also accept 617;; constants that won't fit into 8 bits. After having captured the constant 618;; we can decide better whether/how to load it into a register and do other 619;; post-combine optimizations such as bypassing sign/zero extensions. 620(define_insn_and_split "tstsi_t" 621 [(set (reg:SI T_REG) 622 (eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "%z,r") 623 (match_operand:SI 1 "arith_or_int_operand" "K08,?r")) 624 (const_int 0)))] 625 "TARGET_SH1 626 && (can_create_pseudo_p () || arith_reg_operand (operands[1], SImode) 627 || satisfies_constraint_K08 (operands[1]))" 628 "tst %1,%0" 629 "TARGET_SH1 && can_create_pseudo_p () && CONST_INT_P (operands[1]) 630 && !sh_in_recog_treg_set_expr ()" 631 [(const_int 0)] 632{ 633 gcc_assert (CONST_INT_P (operands[1])); 634 635 HOST_WIDE_INT op1val = INTVAL (operands[1]); 636 bool op0_dead_after_this = 637 sh_reg_dead_or_unused_after_insn (curr_insn, REGNO (operands[0])); 638 639 if (optimize) 640 { 641 if (dump_file) 642 fprintf (dump_file, 643 "tstsi_t: trying to optimize const_int 0x%08x\n", 644 (uint32_t)op1val); 645 646 /* See if we can convert a test with a reg and a constant into 647 something simpler, if the reg is known to be zero or sign 648 extended. */ 649 sh_extending_set_of_reg eop0 = sh_find_extending_set_of_reg (operands[0], 650 curr_insn); 651 if (eop0.ext_code != UNKNOWN) 652 { 653 /* Adjust the constant, trying to eliminate bits that are not 654 contributing to the result. */ 655 if (eop0.from_mode == QImode) 656 op1val = (op1val 657 | (eop0.ext_code == SIGN_EXTEND && (op1val & 0xFFFFFF80) 658 ? 0x80 : 0)) & 0xFF; 659 else if (eop0.from_mode == HImode) 660 op1val = (op1val 661 | (eop0.ext_code == SIGN_EXTEND && (op1val & 0xFFFF8000) 662 ? 0x8000 : 0)) & 0xFFFF; 663 664 if (dump_file) 665 fprintf (dump_file, "tstsi_t: using effective const_int: 0x%08x\n", 666 (uint32_t)op1val); 667 668 /* Try to bypass the sign/zero extension first if op0 dies after 669 this insn. */ 670 if (op0_dead_after_this && eop0.can_use_as_unextended_reg ()) 671 { 672 if (dump_file) 673 fprintf (dump_file, "tstsi_t: bypassing sign/zero extension\n"); 674 675 operands[0] = eop0.use_as_unextended_reg (curr_insn); 676 } 677 else if ((eop0.from_mode == QImode && op1val == 0xFF) 678 || (eop0.from_mode == HImode && op1val == 0xFFFF)) 679 { 680 if (dump_file) 681 fprintf (dump_file, "tstsi_t: converting to cmpeqsi_t\n"); 682 emit_insn (gen_cmpeqsi_t (eop0.use_as_extended_reg (curr_insn), 683 const0_rtx)); 684 DONE; 685 } 686 else if (eop0.ext_code == SIGN_EXTEND 687 && ((eop0.from_mode == QImode && op1val == 0x80) 688 || (eop0.from_mode == HImode && op1val == 0x8000))) 689 { 690 if (dump_file) 691 fprintf (dump_file, "tstsi_t: converting to cmpgesi_t\n"); 692 emit_insn (gen_cmpgesi_t (eop0.use_as_extended_reg (curr_insn), 693 const0_rtx)); 694 DONE; 695 } 696 else if (!CONST_OK_FOR_K08 (op1val)) 697 { 698 if (dump_file) 699 fprintf (dump_file, "tstsi_t: converting const_int to signed " 700 "value\n"); 701 702 /* If here we haven't done anything yet. Convert the constant 703 to a signed value to reduce the constant pool size. */ 704 operands[0] = eop0.use_as_extended_reg (curr_insn); 705 706 if (eop0.from_mode == QImode) 707 op1val |= (op1val & 0x80) ? 0xFFFFFFFFFFFFFF00LL : 0; 708 else if (eop0.from_mode == HImode) 709 op1val |= (op1val & 0x8000) ? 0xFFFFFFFFFFFF0000LL : 0; 710 } 711 else 712 operands[0] = eop0.use_as_extended_reg (curr_insn); 713 } 714 } 715 716 if (dump_file) 717 fprintf (dump_file, "tstsi_t: using const_int 0x%08x\n", 718 (uint32_t)op1val); 719 720 /* Try to fit the constant into 8 bits by shuffling the value in the 721 register operand. 722 Doing that usually results in smaller code as the constants in the 723 pools are avoided (32 bit constant = load + constant = 6 bytes). 724 However, if the constant load (LS insn) can be hoisted insn dependencies 725 can be avoided and chances for parallel execution increase. The common 726 usage pattern is: 727 - load reg from mem 728 - test bits 729 - conditional branch 730 731 FIXME: For now we do that only when optimizing for size until there is 732 a better heuristic. 733 734 FIXME: If there are multiple tst insns in the block with the same 735 constant, avoid the #imm variant to avoid R0 loads. Use the 'tst Rn,Rm' 736 variant instead and load the constant into a reg. For that we'd need 737 to do some analysis. */ 738 739 if (CONST_OK_FOR_K08 (op1val)) 740 { 741 /* Do nothing. */ 742 } 743 else if ((op1val & 0xFFFF) == 0 744 && CONST_OK_FOR_K08 (op1val >> 16) && optimize_size) 745 { 746 /* Use a swap.w insn to do a shift + reg copy (to R0) in one insn. */ 747 op1val = op1val >> 16; 748 rtx r = gen_reg_rtx (SImode); 749 emit_insn (gen_rotlsi3_16 (r, operands[0])); 750 operands[0] = r; 751 } 752 else if ((op1val & 0xFF) == 0 753 && CONST_OK_FOR_K08 (op1val >> 8) && optimize_size) 754 { 755 /* Use a swap.b insn to do a shift + reg copy (to R0) in one insn. */ 756 op1val = op1val >> 8; 757 rtx r = gen_reg_rtx (SImode); 758 emit_insn (gen_swapbsi2 (r, operands[0])); 759 operands[0] = r; 760 } 761 else if ((op1val & 3) == 0 762 && CONST_OK_FOR_K08 (op1val >> 2) && optimize_size) 763 { 764 op1val = op1val >> 2; 765 rtx r = gen_reg_rtx (SImode); 766 emit_insn (gen_lshrsi3_k (r, operands[0], GEN_INT (2))); 767 operands[0] = r; 768 } 769 else if ((op1val & 1) == 0 770 && CONST_OK_FOR_K08 (op1val >> 1) && optimize_size) 771 { 772 op1val = op1val >> 1; 773 rtx r = gen_reg_rtx (SImode); 774 emit_insn (gen_shlr (r, operands[0])); 775 operands[0] = r; 776 } 777 778 operands[1] = GEN_INT (op1val); 779 780 if (!satisfies_constraint_K08 (operands[1])) 781 operands[1] = force_reg (SImode, operands[1]); 782 783 emit_insn (gen_tstsi_t (operands[0], operands[1])); 784 DONE; 785} 786 [(set_attr "type" "mt_group")]) 787 788;; This pattern is used by combine when testing QI/HImode subregs with a 789;; negative constant. Ignore high bits by masking them out in the constant. 790(define_insn_and_split "*tst<mode>_t" 791 [(set (reg:SI T_REG) 792 (eq:SI (subreg:SI 793 (and:QIHI (match_operand:QIHI 0 "arith_reg_operand") 794 (match_operand 1 "const_int_operand")) 0) 795 (const_int 0)))] 796 "TARGET_SH1 && can_create_pseudo_p ()" 797 "#" 798 "&& 1" 799 [(set (reg:SI T_REG) 800 (eq:SI (and:SI (match_dup 0) (match_dup 1)) (const_int 0)))] 801{ 802 operands[0] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0); 803 operands[1] = GEN_INT (INTVAL (operands[1]) 804 & (<MODE>mode == HImode ? 0xFFFF : 0xFF)); 805}) 806 807;; This pattern might be risky because it also tests the upper bits and not 808;; only the subreg. We have to check whether the operands have been sign 809;; or zero extended. In the worst case, a zero extension has to be inserted 810;; to mask out the unwanted bits. 811(define_insn_and_split "*tst<mode>_t_subregs" 812 [(set (reg:SI T_REG) 813 (eq:SI 814 (subreg:QIHI 815 (and:SI (match_operand:SI 0 "arith_reg_operand") 816 (match_operand:SI 1 "arith_reg_operand")) <lowpart_le>) 817 (const_int 0)))] 818 "TARGET_SH1 && TARGET_LITTLE_ENDIAN && can_create_pseudo_p ()" 819 "#" 820 "&& !sh_in_recog_treg_set_expr ()" 821 [(const_int 0)] 822{ 823 sh_split_tst_subregs (curr_insn, <MODE>mode, <lowpart_le>, operands); 824 DONE; 825}) 826 827(define_insn_and_split "*tst<mode>_t_subregs" 828 [(set (reg:SI T_REG) 829 (eq:SI 830 (subreg:QIHI 831 (and:SI (match_operand:SI 0 "arith_reg_operand") 832 (match_operand:SI 1 "arith_reg_operand")) <lowpart_be>) 833 (const_int 0)))] 834 "TARGET_SH1 && TARGET_BIG_ENDIAN && can_create_pseudo_p ()" 835 "#" 836 "&& !sh_in_recog_treg_set_expr ()" 837 [(const_int 0)] 838{ 839 sh_split_tst_subregs (curr_insn, <MODE>mode, <lowpart_be>, operands); 840 DONE; 841}) 842 843;; Extract contiguous bits and compare them against zero. 844;; Notice that this will not be used for single bits. Special single bit 845;; extraction patterns are in the 'bit field extract patterns' section. 846(define_insn_and_split "*tst<mode>_t_zero_extract" 847 [(set (reg:SI T_REG) 848 (eq:SI (zero_extract:SI (match_operand:QIHISI 0 "arith_reg_operand") 849 (match_operand 1 "const_int_operand") 850 (match_operand 2 "const_int_operand")) 851 (const_int 0)))] 852 "TARGET_SH1 && can_create_pseudo_p ()" 853 "#" 854 "&& 1" 855 [(set (reg:SI T_REG) 856 (eq:SI (and:SI (match_dup 0) (match_dup 1)) (const_int 0)))] 857{ 858 operands[1] = GEN_INT (ZERO_EXTRACT_ANDMASK (operands[1], operands[2])); 859 if (GET_MODE (operands[0]) != SImode) 860 operands[0] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0); 861}) 862 863;; Convert '(reg << shift) & mask' into 'reg & (mask >> shift)'. 864;; The shifted-out bits in the mask will always be zero, since the 865;; shifted-in bits in the reg will also be always zero. 866(define_insn_and_split "*tstsi_t_shift_mask" 867 [(set (reg:SI T_REG) 868 (eq:SI (and:SI (ashift:SI (match_operand:SI 0 "arith_reg_operand") 869 (match_operand 1 "const_int_operand")) 870 (match_operand 2 "const_int_operand")) 871 (const_int 0)))] 872 "TARGET_SH1 && can_create_pseudo_p ()" 873 "#" 874 "&& 1" 875 [(set (reg:SI T_REG) 876 (eq:SI (and:SI (match_dup 0) (match_dup 2)) (const_int 0)))] 877{ 878 operands[2] = GEN_INT (INTVAL (operands[2]) >> INTVAL (operands[1])); 879}) 880 881(define_insn "cmpeqsi_t" 882 [(set (reg:SI T_REG) 883 (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r") 884 (match_operand:SI 1 "arith_operand" "N,rI08,r")))] 885 "TARGET_SH1" 886 "@ 887 tst %0,%0 888 cmp/eq %1,%0 889 cmp/eq %1,%0" 890 [(set_attr "type" "mt_group")]) 891 892;; Sometimes combine fails to form the (eq (and (op) (op)) 0) tst insn. 893;; Try to fix that in the split1 pass by looking for the previous set 894;; of the tested op. Also see if there is a preceeding sign/zero 895;; extension that can be avoided. 896(define_split 897 [(set (reg:SI T_REG) 898 (eq:SI (match_operand:SI 0 "arith_reg_operand") (const_int 0)))] 899 "TARGET_SH1 && can_create_pseudo_p () && optimize 900 && !sh_in_recog_treg_set_expr ()" 901 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))] 902{ 903 if (dump_file) 904 fprintf (dump_file, "cmpeqsi_t: trying to optimize const_int 0\n"); 905 906 /* If the tested reg is not dead after this insn, it's probably used by 907 something else after the comparison. It's probably better to leave 908 it as it is. */ 909 if (find_regno_note (curr_insn, REG_DEAD, REGNO (operands[0])) == NULL_RTX) 910 FAIL; 911 912 /* FIXME: Maybe also search the predecessor basic blocks to catch 913 more cases. */ 914 set_of_reg op = sh_find_set_of_reg (operands[0], curr_insn, 915 prev_nonnote_insn_bb); 916 917 if (op.set_src != NULL && GET_CODE (op.set_src) == AND 918 && !sh_insn_operands_modified_between_p (op.insn, op.insn, curr_insn)) 919 { 920 if (dump_file) 921 fprintf (dump_file, "cmpeqsi_t: found preceeding and in insn %d\n", 922 INSN_UID (op.insn)); 923 924 if (!(arith_reg_operand (XEXP (op.set_src, 0), SImode) 925 && (arith_reg_operand (XEXP (op.set_src, 1), SImode) 926 || CONST_INT_P (XEXP (op.set_src, 1))))) 927 FAIL; 928 929 /* Assume that the operands of the andsi insn are compatible with the 930 operands of the tstsi_t insn, which is generally the case. */ 931 if (dump_file) 932 fprintf (dump_file, "cmpeqsi_t: replacing with tstsi_t\n"); 933 emit_insn (gen_tstsi_t (XEXP (op.set_src, 0), XEXP (op.set_src, 1))); 934 DONE; 935 } 936 937 /* Converting HImode into tests against 0xFFFF tends to increase the code 938 size, as it will create constant pool entries. Disable it for now. */ 939 const bool enable_himode = false; 940 941 /* FIXME: try to keep the (eq (reg) (const_int 0)). Even if the zero 942 extended reg is used after this insn, if we know that _before_ the zero 943 extension the value was loaded via sign extending mem load, we can just 944 use the value of the mem load directly. */ 945 sh_extending_set_of_reg eop = sh_find_extending_set_of_reg (operands[0], 946 curr_insn); 947 948 if (eop.ext_code != UNKNOWN 949 && (eop.from_mode == QImode || (eop.from_mode == HImode && enable_himode)) 950 && eop.can_use_as_unextended_reg () 951 && !reg_used_between_p (operands[0], eop.insn, curr_insn)) 952 { 953 /* Bypass the sign/zero extension and test against the bit mask, but 954 only if it's the only use of the sign/zero extracted value. 955 Otherwise we'd be introducing new constants in the pool. */ 956 if (dump_file) 957 fprintf (dump_file, "cmpeqsi_t: bypassing sign/zero extension in " 958 "insn %d and using tstsi_t\n", INSN_UID (op.insn)); 959 960 emit_insn (gen_tstsi_t ( 961 eop.use_as_unextended_reg (curr_insn), 962 GEN_INT (eop.from_mode == QImode ? 0xFF : 0xFFFF))); 963 DONE; 964 } 965 966 if (dump_file) 967 fprintf (dump_file, "cmpeqsi_t: nothing optimized\n"); 968 FAIL; 969}) 970 971;; FIXME: For some reason, on SH4A and SH2A combine fails to simplify this 972;; pattern by itself. What this actually does is: 973;; x == 0: (1 >> 0-0) & 1 = 1 974;; x != 0: (1 >> 0-x) & 1 = 0 975;; Without this the test pr51244-8.c fails on SH2A and SH4A. 976(define_insn_and_split "*cmpeqsi_t" 977 [(set (reg:SI T_REG) 978 (and:SI (lshiftrt:SI 979 (const_int 1) 980 (neg:SI (match_operand:SI 0 "arith_reg_operand" "r"))) 981 (const_int 1)))] 982 "TARGET_SH1" 983 "#" 984 "&& 1" 985 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))]) 986 987(define_insn "cmpgtsi_t" 988 [(set (reg:SI T_REG) 989 (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r") 990 (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))] 991 "TARGET_SH1" 992 "@ 993 cmp/pl %0 994 cmp/gt %1,%0" 995 [(set_attr "type" "mt_group")]) 996 997(define_insn "cmpgesi_t" 998 [(set (reg:SI T_REG) 999 (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r") 1000 (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))] 1001 "TARGET_SH1" 1002 "@ 1003 cmp/pz %0 1004 cmp/ge %1,%0" 1005 [(set_attr "type" "mt_group")]) 1006 1007;; Recombine a cmp/pz followed by a nott into a shll. 1008;; On non-SH2A recombine a cmp/pz followed by a movrt into shll-movt. 1009;; On SH2A cmp/pz-movrt is slightly better, as it does not mutate the input. 1010(define_split 1011 [(set (reg:SI T_REG) 1012 (ge:SI (match_operand:SI 0 "arith_reg_operand") (const_int 0)))] 1013 1014 "TARGET_SH1 && can_create_pseudo_p () && optimize 1015 && !sh_in_recog_treg_set_expr ()" 1016 [(const_int 0)] 1017{ 1018 if (dump_file) 1019 fprintf (dump_file, "cmpgesi_t: trying to optimize for const_int 0\n"); 1020 1021 rtx_insn* i = next_nonnote_insn_bb (curr_insn); 1022 1023 if (dump_file) 1024 { 1025 fprintf (dump_file, "cmpgesi_t: following insn is \n"); 1026 print_rtl_single (dump_file, i); 1027 fprintf (dump_file, "\n"); 1028 } 1029 1030 if (sh_is_nott_insn (i)) 1031 { 1032 if (dump_file) 1033 fprintf (dump_file, 1034 "cmpgesi_t: replacing (cmp/pz, nott) with (shll)\n"); 1035 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[0])); 1036 set_insn_deleted (i); 1037 DONE; 1038 } 1039 1040 /* On non-SH2A negc is used as movrt replacement, which sets T = 1. 1041 Thus we can remove it only if T is marked as dead afterwards. */ 1042 if (rtx dest_reg = !TARGET_SH2A 1043 && sh_reg_dead_or_unused_after_insn (i, T_REG) 1044 ? sh_movrt_set_dest (i) : NULL) 1045 { 1046 if (dump_file) 1047 fprintf (dump_file, 1048 "cmpgesi_t: replacing (cmp/pz, movrt) with (shll, movt)\n"); 1049 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[0])); 1050 add_reg_note (emit_insn (gen_movt (dest_reg, get_t_reg_rtx ())), 1051 REG_DEAD, get_t_reg_rtx ()); 1052 set_insn_deleted (i); 1053 DONE; 1054 } 1055 1056 if (dump_file) 1057 fprintf (dump_file, "cmpgesi_t: nothing optimized\n"); 1058 1059 FAIL; 1060}) 1061 1062;; FIXME: This is actually wrong. There is no way to literally move a 1063;; general reg to t reg. Luckily, it seems that this pattern will be only 1064;; used when the general reg is known be either '0' or '1' during combine. 1065;; What we actually need is reg != 0 -> T, but we have only reg == 0 -> T. 1066;; Due to interactions with other patterns, combine fails to pick the latter 1067;; and invert the dependent logic. 1068(define_insn "*negtstsi" 1069 [(set (reg:SI T_REG) (match_operand:SI 0 "arith_reg_operand" "r"))] 1070 "TARGET_SH1 && !sh_in_recog_treg_set_expr ()" 1071 "cmp/pl %0" 1072 [(set_attr "type" "mt_group")]) 1073 1074;; Some integer sign comparison patterns can be realized with the div0s insn. 1075;; div0s Rm,Rn T = (Rm >> 31) ^ (Rn >> 31) 1076;; 1077;; The 'cmp_div0s' pattern is our canonical form, into which all the other 1078;; variations are converted. The negative forms will split into a trailing 1079;; nott sequence, which will be eliminated either by the 1080;; 'any_treg_expr_to_reg' pattern, or by the 'sh_treg_combine' pass. 1081(define_insn "cmp_div0s" 1082 [(set (reg:SI T_REG) 1083 (lshiftrt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "%r") 1084 (match_operand:SI 1 "arith_reg_operand" "r")) 1085 (const_int 31)))] 1086 "TARGET_SH1" 1087 "div0s %0,%1" 1088 [(set_attr "type" "arith")]) 1089 1090(define_insn_and_split "*cmp_div0s_1" 1091 [(set (reg:SI T_REG) 1092 (xor:SI (ge:SI (match_operand:SI 0 "arith_reg_operand") 1093 (const_int 0)) 1094 (ge:SI (match_operand:SI 1 "arith_reg_operand") 1095 (const_int 0))))] 1096 "TARGET_SH1 && can_create_pseudo_p ()" 1097 "#" 1098 "&& 1" 1099 [(set (reg:SI T_REG) 1100 (lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31)))]) 1101 1102(define_insn_and_split "*cmp_div0s_2" 1103 [(set (reg:SI T_REG) 1104 (eq:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand") 1105 (const_int 31)) 1106 (ge:SI (match_operand:SI 1 "arith_reg_operand") 1107 (const_int 0))))] 1108 "TARGET_SH1 && can_create_pseudo_p ()" 1109 "#" 1110 "&& 1" 1111 [(set (reg:SI T_REG) 1112 (lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31)))]) 1113 1114(define_insn_and_split "*cmp_div0s_3" 1115 [(set (reg:SI T_REG) 1116 (eq:SI (ge:SI (match_operand:SI 0 "arith_reg_operand") 1117 (const_int 0)) 1118 (ge:SI (match_operand:SI 1 "arith_reg_operand") 1119 (const_int 0))))] 1120 "TARGET_SH1 && can_create_pseudo_p ()" 1121 "#" 1122 "&& 1" 1123 [(set (reg:SI T_REG) 1124 (lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31))) 1125 (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))]) 1126 1127(define_insn_and_split "*cmp_div0s_4" 1128 [(set (reg:SI T_REG) 1129 (ge:SI (xor:SI (match_operand:SI 0 "arith_reg_operand") 1130 (match_operand:SI 1 "arith_reg_operand")) 1131 (const_int 0)))] 1132 "TARGET_SH1 && can_create_pseudo_p ()" 1133 "#" 1134 "&& 1" 1135 [(set (reg:SI T_REG) 1136 (lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31))) 1137 (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))]) 1138 1139(define_insn_and_split "*cmp_div0s_5" 1140 [(set (reg:SI T_REG) 1141 (xor:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand") 1142 (const_int 31)) 1143 (ge:SI (match_operand:SI 1 "arith_reg_operand") 1144 (const_int 0))))] 1145 "TARGET_SH1 && can_create_pseudo_p ()" 1146 "#" 1147 "&& 1" 1148 [(set (reg:SI T_REG) 1149 (lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31))) 1150 (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))]) 1151 1152(define_insn_and_split "*cmp_div0s_6" 1153 [(set (reg:SI T_REG) 1154 (eq:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand") 1155 (const_int 31)) 1156 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand") 1157 (const_int 31))))] 1158 "TARGET_SH1 && can_create_pseudo_p ()" 1159 "#" 1160 "&& 1" 1161 [(set (reg:SI T_REG) 1162 (lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31))) 1163 (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))]) 1164 1165;; ------------------------------------------------------------------------- 1166;; SImode compare and branch 1167;; ------------------------------------------------------------------------- 1168 1169(define_expand "cbranchsi4" 1170 [(set (pc) 1171 (if_then_else (match_operator 0 "comparison_operator" 1172 [(match_operand:SI 1 "arith_operand" "") 1173 (match_operand:SI 2 "arith_operand" "")]) 1174 (label_ref (match_operand 3 "" "")) 1175 (pc))) 1176 (clobber (reg:SI T_REG))] 1177 "" 1178{ 1179 if (TARGET_SHMEDIA) 1180 emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1], 1181 operands[2], operands[3])); 1182 else 1183 expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1); 1184 1185 DONE; 1186}) 1187 1188;; Combine patterns to invert compare and branch operations for which we 1189;; don't have actual comparison insns. These patterns are used in cases 1190;; which appear after the initial cbranchsi expansion, which also does 1191;; some condition inversion. 1192(define_split 1193 [(set (pc) 1194 (if_then_else (ne (match_operand:SI 0 "arith_reg_operand" "") 1195 (match_operand:SI 1 "arith_reg_or_0_operand" "")) 1196 (label_ref (match_operand 2)) 1197 (pc))) 1198 (clobber (reg:SI T_REG))] 1199 "TARGET_SH1" 1200 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (match_dup 1))) 1201 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 1202 (label_ref (match_dup 2)) 1203 (pc)))]) 1204 1205;; FIXME: Similar to the *cmpeqsi_t pattern above, for some reason, on SH4A 1206;; and SH2A combine fails to simplify this pattern by itself. 1207;; What this actually does is: 1208;; x == 0: (1 >> 0-0) & 1 = 1 1209;; x != 0: (1 >> 0-x) & 1 = 0 1210;; Without this the test pr51244-8.c fails on SH2A and SH4A. 1211(define_split 1212 [(set (pc) 1213 (if_then_else 1214 (eq (and:SI (lshiftrt:SI 1215 (const_int 1) 1216 (neg:SI (match_operand:SI 0 "arith_reg_operand" ""))) 1217 (const_int 1)) 1218 (const_int 0)) 1219 (label_ref (match_operand 2)) 1220 (pc))) 1221 (clobber (reg:SI T_REG))] 1222 "TARGET_SH1" 1223 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0))) 1224 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 1225 (label_ref (match_dup 2)) 1226 (pc)))]) 1227 1228;; FIXME: These could probably use code iterators for the compare op. 1229(define_split 1230 [(set (pc) 1231 (if_then_else (le (match_operand:SI 0 "arith_reg_operand" "") 1232 (match_operand:SI 1 "arith_reg_or_0_operand" "")) 1233 (label_ref (match_operand 2)) 1234 (pc))) 1235 (clobber (reg:SI T_REG))] 1236 "TARGET_SH1" 1237 [(set (reg:SI T_REG) (gt:SI (match_dup 0) (match_dup 1))) 1238 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 1239 (label_ref (match_dup 2)) 1240 (pc)))]) 1241 1242(define_split 1243 [(set (pc) 1244 (if_then_else (lt (match_operand:SI 0 "arith_reg_operand" "") 1245 (match_operand:SI 1 "arith_reg_or_0_operand" "")) 1246 (label_ref (match_operand 2)) 1247 (pc))) 1248 (clobber (reg:SI T_REG))] 1249 "TARGET_SH1" 1250 [(set (reg:SI T_REG) (ge:SI (match_dup 0) (match_dup 1))) 1251 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 1252 (label_ref (match_dup 2)) 1253 (pc)))]) 1254 1255(define_split 1256 [(set (pc) 1257 (if_then_else (leu (match_operand:SI 0 "arith_reg_operand" "") 1258 (match_operand:SI 1 "arith_reg_operand" "")) 1259 (label_ref (match_operand 2)) 1260 (pc))) 1261 (clobber (reg:SI T_REG))] 1262 "TARGET_SH1" 1263 [(set (reg:SI T_REG) (gtu:SI (match_dup 0) (match_dup 1))) 1264 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 1265 (label_ref (match_dup 2)) 1266 (pc)))]) 1267 1268(define_split 1269 [(set (pc) 1270 (if_then_else (ltu (match_operand:SI 0 "arith_reg_operand" "") 1271 (match_operand:SI 1 "arith_reg_operand" "")) 1272 (label_ref (match_operand 2)) 1273 (pc))) 1274 (clobber (reg:SI T_REG))] 1275 "TARGET_SH1" 1276 [(set (reg:SI T_REG) (geu:SI (match_dup 0) (match_dup 1))) 1277 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 1278 (label_ref (match_dup 2)) 1279 (pc)))]) 1280 1281;; ------------------------------------------------------------------------- 1282;; SImode unsigned integer comparisons 1283;; ------------------------------------------------------------------------- 1284 1285;; Usually comparisons of 'unsigned int >= 0' are optimized away completely. 1286;; However, especially when optimizations are off (e.g. -O0) such comparisons 1287;; might remain and we have to handle them. If the '>= 0' case wasn't 1288;; handled here, something else would just load a '0' into the second operand 1289;; and do the comparison. We can do slightly better by just setting the 1290;; T bit to '1'. 1291(define_insn_and_split "cmpgeusi_t" 1292 [(set (reg:SI T_REG) 1293 (geu:SI (match_operand:SI 0 "arith_reg_operand" "r") 1294 (match_operand:SI 1 "arith_reg_or_0_operand" "r")))] 1295 "TARGET_SH1" 1296 "cmp/hs %1,%0" 1297 "&& satisfies_constraint_Z (operands[1])" 1298 [(set (reg:SI T_REG) (const_int 1))] 1299 "" 1300 [(set_attr "type" "mt_group")]) 1301 1302(define_insn "cmpgtusi_t" 1303 [(set (reg:SI T_REG) 1304 (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r") 1305 (match_operand:SI 1 "arith_reg_operand" "r")))] 1306 "TARGET_SH1" 1307 "cmp/hi %1,%0" 1308 [(set_attr "type" "mt_group")]) 1309 1310;; ------------------------------------------------------------------------- 1311;; DImode compare and branch 1312;; ------------------------------------------------------------------------- 1313 1314;; arith3 patterns don't work well with the sh4-300 branch prediction mechanism. 1315;; Therefore, we aim to have a set of three branches that go straight to the 1316;; destination, i.e. only one of them is taken at any one time. 1317;; This mechanism should also be slightly better for the sh4-200. 1318 1319(define_expand "cbranchdi4" 1320 [(set (pc) 1321 (if_then_else (match_operator 0 "comparison_operator" 1322 [(match_operand:DI 1 "arith_operand" "") 1323 (match_operand:DI 2 "arith_operand" "")]) 1324 (label_ref (match_operand 3 "" "")) 1325 (pc))) 1326 (clobber (match_dup 4)) 1327 (clobber (reg:SI T_REG))] 1328 "TARGET_CBRANCHDI4 || TARGET_SH2 || TARGET_SHMEDIA" 1329{ 1330 enum rtx_code comparison; 1331 1332 if (TARGET_SHMEDIA) 1333 { 1334 emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1], 1335 operands[2], operands[3])); 1336 DONE; 1337 } 1338 else if (!TARGET_CBRANCHDI4) 1339 { 1340 sh_emit_compare_and_branch (operands, DImode); 1341 DONE; 1342 } 1343 else 1344 { 1345 if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE)) 1346 DONE; 1347 1348 comparison = prepare_cbranch_operands (operands, DImode, 1349 LAST_AND_UNUSED_RTX_CODE); 1350 if (comparison != GET_CODE (operands[0])) 1351 operands[0] 1352 = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]); 1353 operands[4] = gen_rtx_SCRATCH (SImode); 1354 } 1355}) 1356 1357(define_insn_and_split "cbranchdi4_i" 1358 [(set (pc) 1359 (if_then_else (match_operator 0 "comparison_operator" 1360 [(match_operand:DI 1 "arith_operand" "r,r") 1361 (match_operand:DI 2 "arith_operand" "rN,I08")]) 1362 (label_ref (match_operand 3 "" "")) 1363 (pc))) 1364 (clobber (match_scratch:SI 4 "=X,&r")) 1365 (clobber (reg:SI T_REG))] 1366 "TARGET_CBRANCHDI4" 1367 "#" 1368 "&& reload_completed" 1369 [(pc)] 1370{ 1371 if (!expand_cbranchdi4 (operands, GET_CODE (operands[0]))) 1372 FAIL; 1373 DONE; 1374}) 1375 1376;; ------------------------------------------------------------------------- 1377;; DImode signed integer comparisons 1378;; ------------------------------------------------------------------------- 1379 1380(define_insn "" 1381 [(set (reg:SI T_REG) 1382 (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r") 1383 (match_operand:DI 1 "arith_operand" "r")) 1384 (const_int 0)))] 1385 "TARGET_SH1" 1386{ 1387 return output_branchy_insn (EQ, "tst\t%S1,%S0;bf\t%l9;tst\t%R1,%R0", 1388 insn, operands); 1389} 1390 [(set_attr "length" "6") 1391 (set_attr "type" "arith3b")]) 1392 1393(define_insn "cmpeqdi_t" 1394 [(set (reg:SI T_REG) 1395 (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r") 1396 (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))] 1397 "TARGET_SH1" 1398{ 1399 static const char* alt[] = 1400 { 1401 "tst %S0,%S0" "\n" 1402 " bf 0f" "\n" 1403 " tst %R0,%R0" "\n" 1404 "0:", 1405 1406 "cmp/eq %S1,%S0" "\n" 1407 " bf 0f" "\n" 1408 " cmp/eq %R1,%R0" "\n" 1409 "0:" 1410 }; 1411 return alt[which_alternative]; 1412} 1413 [(set_attr "length" "6") 1414 (set_attr "type" "arith3b")]) 1415 1416(define_split 1417 [(set (reg:SI T_REG) 1418 (eq:SI (match_operand:DI 0 "arith_reg_operand" "") 1419 (match_operand:DI 1 "arith_reg_or_0_operand" "")))] 1420;; If we applied this split when not optimizing, it would only be 1421;; applied during the machine-dependent reorg, when no new basic blocks 1422;; may be created. 1423 "TARGET_SH1 && reload_completed && optimize" 1424 [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3))) 1425 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 1426 (label_ref (match_dup 6)) 1427 (pc))) 1428 (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5))) 1429 (match_dup 6)] 1430{ 1431 operands[2] = gen_highpart (SImode, operands[0]); 1432 operands[3] = operands[1] == const0_rtx 1433 ? const0_rtx 1434 : gen_highpart (SImode, operands[1]); 1435 operands[4] = gen_lowpart (SImode, operands[0]); 1436 operands[5] = gen_lowpart (SImode, operands[1]); 1437 operands[6] = gen_label_rtx (); 1438}) 1439 1440(define_insn "cmpgtdi_t" 1441 [(set (reg:SI T_REG) 1442 (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r") 1443 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))] 1444 "TARGET_SH2" 1445{ 1446 static const char* alt[] = 1447 { 1448 "cmp/eq %S1,%S0" "\n" 1449 " bf{.|/}s 0f" "\n" 1450 " cmp/gt %S1,%S0" "\n" 1451 " cmp/hi %R1,%R0" "\n" 1452 "0:", 1453 1454 "tst %S0,%S0" "\n" 1455 " bf{.|/}s 0f" "\n" 1456 " cmp/pl %S0" "\n" 1457 " cmp/hi %S0,%R0" "\n" 1458 "0:" 1459 }; 1460 return alt[which_alternative]; 1461} 1462 [(set_attr "length" "8") 1463 (set_attr "type" "arith3")]) 1464 1465(define_insn "cmpgedi_t" 1466 [(set (reg:SI T_REG) 1467 (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r") 1468 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))] 1469 "TARGET_SH2" 1470{ 1471 static const char* alt[] = 1472 { 1473 "cmp/eq %S1,%S0" "\n" 1474 " bf{.|/}s 0f" "\n" 1475 " cmp/ge %S1,%S0" "\n" 1476 " cmp/hs %R1,%R0" "\n" 1477 "0:", 1478 1479 "cmp/pz %S0" 1480 }; 1481 return alt[which_alternative]; 1482} 1483 [(set_attr "length" "8,2") 1484 (set_attr "type" "arith3,mt_group")]) 1485 1486;; ------------------------------------------------------------------------- 1487;; DImode unsigned integer comparisons 1488;; ------------------------------------------------------------------------- 1489 1490(define_insn "cmpgeudi_t" 1491 [(set (reg:SI T_REG) 1492 (geu:SI (match_operand:DI 0 "arith_reg_operand" "r") 1493 (match_operand:DI 1 "arith_reg_operand" "r")))] 1494 "TARGET_SH2" 1495{ 1496 return "cmp/eq %S1,%S0" "\n" 1497 " bf{.|/}s 0f" "\n" 1498 " cmp/hs %S1,%S0" "\n" 1499 " cmp/hs %R1,%R0" "\n" 1500 "0:"; 1501} 1502 [(set_attr "length" "8") 1503 (set_attr "type" "arith3")]) 1504 1505(define_insn "cmpgtudi_t" 1506 [(set (reg:SI T_REG) 1507 (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r") 1508 (match_operand:DI 1 "arith_reg_operand" "r")))] 1509 "TARGET_SH2" 1510{ 1511 return "cmp/eq %S1,%S0" "\n" 1512 " bf{.|/}s 0f" "\n" 1513 " cmp/hi %S1,%S0" "\n" 1514 " cmp/hi %R1,%R0" "\n" 1515 "0:"; 1516} 1517 [(set_attr "length" "8") 1518 (set_attr "type" "arith3")]) 1519 1520(define_insn "cmpeqsi_media" 1521 [(set (match_operand:SI 0 "register_operand" "=r") 1522 (eq:SI (match_operand:SI 1 "logical_operand" "%r") 1523 (match_operand:SI 2 "cmp_operand" "Nr")))] 1524 "TARGET_SHMEDIA" 1525 "cmpeq %1, %N2, %0" 1526 [(set_attr "type" "cmp_media")]) 1527 1528(define_insn "cmpeqdi_media" 1529 [(set (match_operand:SI 0 "register_operand" "=r") 1530 (eq:SI (match_operand:DI 1 "register_operand" "%r") 1531 (match_operand:DI 2 "cmp_operand" "Nr")))] 1532 "TARGET_SHMEDIA" 1533 "cmpeq %1, %N2, %0" 1534 [(set_attr "type" "cmp_media")]) 1535 1536(define_insn "cmpgtsi_media" 1537 [(set (match_operand:SI 0 "register_operand" "=r") 1538 (gt:SI (match_operand:SI 1 "cmp_operand" "Nr") 1539 (match_operand:SI 2 "cmp_operand" "rN")))] 1540 "TARGET_SHMEDIA" 1541 "cmpgt %N1, %N2, %0" 1542 [(set_attr "type" "cmp_media")]) 1543 1544(define_insn "cmpgtdi_media" 1545 [(set (match_operand:SI 0 "register_operand" "=r") 1546 (gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr") 1547 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))] 1548 "TARGET_SHMEDIA" 1549 "cmpgt %N1, %N2, %0" 1550 [(set_attr "type" "cmp_media")]) 1551 1552(define_insn "cmpgtusi_media" 1553 [(set (match_operand:SI 0 "register_operand" "=r") 1554 (gtu:SI (match_operand:SI 1 "cmp_operand" "Nr") 1555 (match_operand:SI 2 "cmp_operand" "rN")))] 1556 "TARGET_SHMEDIA" 1557 "cmpgtu %N1, %N2, %0" 1558 [(set_attr "type" "cmp_media")]) 1559 1560(define_insn "cmpgtudi_media" 1561 [(set (match_operand:SI 0 "register_operand" "=r") 1562 (gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr") 1563 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))] 1564 "TARGET_SHMEDIA" 1565 "cmpgtu %N1, %N2, %0" 1566 [(set_attr "type" "cmp_media")]) 1567 1568; This pattern is for combine. 1569(define_insn "*cmpne0sisi_media" 1570 [(set (match_operand:SI 0 "register_operand" "=r") 1571 (ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))] 1572 "TARGET_SHMEDIA" 1573 "cmpgtu %1,r63,%0" 1574 [(set_attr "type" "cmp_media")]) 1575 1576;; ------------------------------------------------------------------------- 1577;; Conditional move instructions 1578;; ------------------------------------------------------------------------- 1579 1580;; The insn names may seem reversed, but note that cmveq performs the move 1581;; if op1 == 0, and cmvne does it if op1 != 0. 1582 1583(define_insn "movdicc_false" 1584 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 1585 (if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r") 1586 (const_int 0)) 1587 (match_operand:DI 2 "arith_reg_or_0_operand" "rN") 1588 (match_operand:DI 3 "arith_reg_operand" "0")))] 1589 "TARGET_SHMEDIA" 1590 "cmveq %1, %N2, %0" 1591 [(set_attr "type" "arith_media")]) 1592 1593(define_insn "movdicc_true" 1594 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 1595 (if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r") 1596 (const_int 0)) 1597 (match_operand:DI 2 "arith_reg_or_0_operand" "rN") 1598 (match_operand:DI 3 "arith_reg_operand" "0")))] 1599 "TARGET_SHMEDIA" 1600 "cmvne %1, %N2, %0" 1601 [(set_attr "type" "arith_media")]) 1602 1603(define_peephole2 1604 [(set (match_operand:DI 0 "arith_reg_dest" "") 1605 (if_then_else:DI (match_operator 3 "equality_comparison_operator" 1606 [(match_operand:DI 1 "arith_reg_operand" "") 1607 (const_int 0)]) 1608 (match_operand:DI 2 "arith_reg_dest" "") 1609 (match_dup 0))) 1610 (set (match_dup 2) (match_dup 0))] 1611 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])" 1612 [(set (match_dup 2) 1613 (if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))] 1614{ 1615 operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])), 1616 VOIDmode, operands[1], CONST0_RTX (DImode)); 1617}) 1618 1619(define_peephole2 1620 [(set (match_operand:DI 0 "general_movdst_operand" "") 1621 (match_operand:DI 1 "arith_reg_or_0_operand" "")) 1622 (set (match_operand:DI 2 "arith_reg_dest" "") 1623 (if_then_else:DI (match_operator 4 "equality_comparison_operator" 1624 [(match_operand:DI 3 "arith_reg_operand" "") 1625 (const_int 0)]) 1626 (match_dup 0) 1627 (match_dup 2)))] 1628 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])" 1629 [(set (match_dup 2) 1630 (if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))] 1631 "") 1632 1633(define_expand "movdicc" 1634 [(set (match_operand:DI 0 "register_operand" "") 1635 (if_then_else:DI (match_operand 1 "comparison_operator" "") 1636 (match_operand:DI 2 "register_operand" "") 1637 (match_operand:DI 3 "register_operand" "")))] 1638 "TARGET_SHMEDIA" 1639{ 1640 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE) 1641 && GET_MODE (XEXP (operands[1], 0)) == DImode 1642 && XEXP (operands[1], 1) == const0_rtx) 1643 ; 1644 else 1645 { 1646 if (!can_create_pseudo_p ()) 1647 FAIL; 1648 1649 operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]), 1650 GET_CODE (operands[1]), 1651 XEXP (operands[1], 0), 1652 XEXP (operands[1], 1)); 1653 if (!operands[1]) 1654 FAIL; 1655 } 1656}) 1657 1658;; Add SImode variants for cmveq / cmvne to compensate for not promoting 1659;; SImode to DImode. 1660(define_insn "movsicc_false" 1661 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 1662 (if_then_else:SI (eq (match_operand:SI 1 "arith_reg_operand" "r") 1663 (const_int 0)) 1664 (match_operand:SI 2 "arith_reg_or_0_operand" "rN") 1665 (match_operand:SI 3 "arith_reg_operand" "0")))] 1666 "TARGET_SHMEDIA" 1667 "cmveq %1, %N2, %0" 1668 [(set_attr "type" "arith_media")]) 1669 1670(define_insn "movsicc_true" 1671 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 1672 (if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r") 1673 (const_int 0)) 1674 (match_operand:SI 2 "arith_reg_or_0_operand" "rN") 1675 (match_operand:SI 3 "arith_reg_operand" "0")))] 1676 "TARGET_SHMEDIA" 1677 "cmvne %1, %N2, %0" 1678 [(set_attr "type" "arith_media")]) 1679 1680(define_peephole2 1681 [(set (match_operand:SI 0 "arith_reg_dest" "") 1682 (if_then_else:SI (match_operator 3 "equality_comparison_operator" 1683 [(match_operand:SI 1 "arith_reg_operand" "") 1684 (const_int 0)]) 1685 (match_operand:SI 2 "arith_reg_dest" "") 1686 (match_dup 0))) 1687 (set (match_dup 2) (match_dup 0))] 1688 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])" 1689 [(set (match_dup 2) 1690 (if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))] 1691{ 1692 operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])), 1693 VOIDmode, operands[1], CONST0_RTX (SImode)); 1694}) 1695 1696(define_peephole2 1697 [(set (match_operand:SI 0 "general_movdst_operand" "") 1698 (match_operand:SI 1 "arith_reg_or_0_operand" "")) 1699 (set (match_operand:SI 2 "arith_reg_dest" "") 1700 (if_then_else:SI (match_operator 4 "equality_comparison_operator" 1701 [(match_operand:SI 3 "arith_reg_operand" "") 1702 (const_int 0)]) 1703 (match_dup 0) 1704 (match_dup 2)))] 1705 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0]) 1706 && (!REG_P (operands[1]) || GENERAL_REGISTER_P (REGNO (operands[1])))" 1707 [(set (match_dup 2) 1708 (if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))] 1709{ 1710 replace_rtx (operands[4], operands[0], operands[1]); 1711}) 1712 1713;; The register allocator is rather clumsy in handling multi-way conditional 1714;; moves, so allow the combiner to make them, and we split them up after 1715;; reload. */ 1716(define_insn_and_split "*movsicc_umin" 1717 [(set (match_operand:SI 0 "arith_reg_dest" "=&r") 1718 (umin:SI (if_then_else:SI 1719 (eq (match_operand:SI 1 "arith_reg_operand" "r") 1720 (const_int 0)) 1721 (match_operand:SI 2 "arith_reg_or_0_operand" "rN") 1722 (match_operand:SI 3 "register_operand" "0")) 1723 (match_operand:SI 4 "arith_reg_or_0_operand" "r"))) 1724 (clobber (match_scratch:SI 5 "=&r"))] 1725 "TARGET_SHMEDIA && !can_create_pseudo_p ()" 1726 "#" 1727 "TARGET_SHMEDIA && reload_completed" 1728 [(pc)] 1729{ 1730 emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2], 1731 operands[3])); 1732 emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0])); 1733 emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4], 1734 operands[0])); 1735 DONE; 1736}) 1737 1738(define_insn "*movsicc_t_false" 1739 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 1740 (if_then_else (eq (reg:SI T_REG) (const_int 0)) 1741 (match_operand:SI 1 "general_movsrc_operand" "r,I08") 1742 (match_operand:SI 2 "arith_reg_operand" "0,0")))] 1743 "TARGET_PRETEND_CMOVE 1744 && (arith_reg_operand (operands[1], SImode) 1745 || (immediate_operand (operands[1], SImode) 1746 && satisfies_constraint_I08 (operands[1])))" 1747{ 1748 return "bt 0f" "\n" 1749 " mov %1,%0" "\n" 1750 "0:"; 1751} 1752 [(set_attr "type" "mt_group,arith") ;; poor approximation 1753 (set_attr "length" "4")]) 1754 1755(define_insn "*movsicc_t_true" 1756 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 1757 (if_then_else (ne (reg:SI T_REG) (const_int 0)) 1758 (match_operand:SI 1 "general_movsrc_operand" "r,I08") 1759 (match_operand:SI 2 "arith_reg_operand" "0,0")))] 1760 "TARGET_PRETEND_CMOVE 1761 && (arith_reg_operand (operands[1], SImode) 1762 || (immediate_operand (operands[1], SImode) 1763 && satisfies_constraint_I08 (operands[1])))" 1764{ 1765 return "bf 0f" "\n" 1766 " mov %1,%0" "\n" 1767 "0:"; 1768} 1769 [(set_attr "type" "mt_group,arith") ;; poor approximation 1770 (set_attr "length" "4")]) 1771 1772(define_expand "movsicc" 1773 [(set (match_operand:SI 0 "arith_reg_dest" "") 1774 (if_then_else:SI (match_operand 1 "comparison_operator" "") 1775 (match_operand:SI 2 "arith_reg_or_0_operand" "") 1776 (match_operand:SI 3 "arith_reg_operand" "")))] 1777 "TARGET_SHMEDIA || TARGET_PRETEND_CMOVE" 1778{ 1779 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE) 1780 && GET_MODE (XEXP (operands[1], 0)) == SImode 1781 && (TARGET_SHMEDIA 1782 || (REG_P (XEXP (operands[1], 0)) 1783 && REGNO (XEXP (operands[1], 0)) == T_REG)) 1784 && XEXP (operands[1], 1) == const0_rtx) 1785 ; 1786 1787 else if (TARGET_PRETEND_CMOVE) 1788 { 1789 enum rtx_code code = GET_CODE (operands[1]); 1790 enum rtx_code new_code = code; 1791 rtx op0 = XEXP (operands[1], 0); 1792 rtx op1 = XEXP (operands[1], 1); 1793 1794 if (! currently_expanding_to_rtl) 1795 FAIL; 1796 switch (code) 1797 { 1798 case LT: case LE: case LEU: case LTU: 1799 if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_INT) 1800 break; 1801 case NE: 1802 new_code = reverse_condition (code); 1803 break; 1804 case EQ: case GT: case GE: case GEU: case GTU: 1805 break; 1806 default: 1807 FAIL; 1808 } 1809 sh_emit_scc_to_t (new_code, op0, op1); 1810 operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode, 1811 gen_rtx_REG (SImode, T_REG), const0_rtx); 1812 } 1813 else 1814 { 1815 if (!can_create_pseudo_p ()) 1816 FAIL; 1817 1818 operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]), 1819 GET_CODE (operands[1]), 1820 XEXP (operands[1], 0), 1821 XEXP (operands[1], 1)); 1822 if (!operands[1]) 1823 FAIL; 1824 } 1825}) 1826 1827(define_expand "movqicc" 1828 [(set (match_operand:QI 0 "register_operand" "") 1829 (if_then_else:QI (match_operand 1 "comparison_operator" "") 1830 (match_operand:QI 2 "register_operand" "") 1831 (match_operand:QI 3 "register_operand" "")))] 1832 "TARGET_SHMEDIA" 1833{ 1834 operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0); 1835 operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0); 1836 operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0); 1837 emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3])); 1838 DONE; 1839}) 1840 1841;; ------------------------------------------------------------------------- 1842;; Addition instructions 1843;; ------------------------------------------------------------------------- 1844 1845(define_expand "adddi3" 1846 [(set (match_operand:DI 0 "arith_reg_operand") 1847 (plus:DI (match_operand:DI 1 "arith_reg_operand") 1848 (match_operand:DI 2 "arith_operand")))] 1849 "" 1850{ 1851 if (TARGET_SH1) 1852 { 1853 operands[2] = force_reg (DImode, operands[2]); 1854 emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2])); 1855 DONE; 1856 } 1857}) 1858 1859(define_insn "*adddi3_media" 1860 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") 1861 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r") 1862 (match_operand:DI 2 "arith_operand" "r,I10")))] 1863 "TARGET_SHMEDIA" 1864 "@ 1865 add %1, %2, %0 1866 addi %1, %2, %0" 1867 [(set_attr "type" "arith_media")]) 1868 1869(define_insn "*adddisi3_media" 1870 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0) 1871 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r") 1872 (match_operand:DI 2 "arith_operand" "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 "adddi3z_media" 1881 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 1882 (zero_extend:DI 1883 (plus:SI (match_operand:SI 1 "extend_reg_operand" "r") 1884 (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))] 1885 "TARGET_SHMEDIA" 1886 "addz.l %1, %N2, %0" 1887 [(set_attr "type" "arith_media") 1888 (set_attr "highpart" "ignore")]) 1889 1890(define_insn_and_split "adddi3_compact" 1891 [(set (match_operand:DI 0 "arith_reg_dest") 1892 (plus:DI (match_operand:DI 1 "arith_reg_operand") 1893 (match_operand:DI 2 "arith_reg_operand"))) 1894 (clobber (reg:SI T_REG))] 1895 "TARGET_SH1" 1896 "#" 1897 "&& can_create_pseudo_p ()" 1898 [(const_int 0)] 1899{ 1900 emit_insn (gen_clrt ()); 1901 emit_insn (gen_addc (gen_lowpart (SImode, operands[0]), 1902 gen_lowpart (SImode, operands[1]), 1903 gen_lowpart (SImode, operands[2]))); 1904 emit_insn (gen_addc (gen_highpart (SImode, operands[0]), 1905 gen_highpart (SImode, operands[1]), 1906 gen_highpart (SImode, operands[2]))); 1907 DONE; 1908}) 1909 1910(define_insn "addc" 1911 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 1912 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0") 1913 (match_operand:SI 2 "arith_reg_operand" "r")) 1914 (reg:SI T_REG))) 1915 (set (reg:SI T_REG) 1916 (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))] 1917 "TARGET_SH1" 1918 "addc %2,%0" 1919 [(set_attr "type" "arith")]) 1920 1921;; A simplified version of the addc insn, where the exact value of the 1922;; T bit doesn't matter. This is easier for combine to pick up. 1923;; We allow a reg or 0 for one of the operands in order to be able to 1924;; do 'reg + T' sequences. 1925(define_insn_and_split "*addc" 1926 [(set (match_operand:SI 0 "arith_reg_dest") 1927 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand") 1928 (match_operand:SI 2 "arith_reg_or_0_operand")) 1929 (match_operand 3 "treg_set_expr"))) 1930 (clobber (reg:SI T_REG))] 1931 "TARGET_SH1 && can_create_pseudo_p ()" 1932 "#" 1933 "&& 1" 1934 [(const_int 0)] 1935{ 1936 sh_treg_insns ti = sh_split_treg_set_expr (operands[3], curr_insn); 1937 if (ti.has_trailing_nott ()) 1938 { 1939 if (operands[2] == const0_rtx) 1940 { 1941 /* op1 + 0 + (1 - T) = op1 + 1 - T = op1 - (-1) - T */ 1942 remove_insn (ti.trailing_nott ()); 1943 emit_insn (gen_subc (operands[0], operands[1], 1944 force_reg (SImode, GEN_INT (-1)))); 1945 DONE; 1946 } 1947 else if (!TARGET_SH2A) 1948 { 1949 /* op1 + op2 + (1 - T) = op1 - (0 - op2 - 1) - T = op1 - ~op2 - T 1950 On SH2A keep the nott insn, because nott-addc sequence doesn't 1951 mutate the inputs. */ 1952 remove_insn (ti.trailing_nott ()); 1953 rtx tmp = gen_reg_rtx (SImode); 1954 emit_insn (gen_one_cmplsi2 (tmp, operands[2])); 1955 emit_insn (gen_subc (operands[0], operands[1], tmp)); 1956 DONE; 1957 } 1958 } 1959 1960 emit_insn (gen_addc (operands[0], operands[1], 1961 force_reg (SImode, operands[2]))); 1962 DONE; 1963}) 1964 1965(define_insn_and_split "*addc" 1966 [(set (match_operand:SI 0 "arith_reg_dest") 1967 (plus:SI (plus:SI (match_operand 1 "treg_set_expr") 1968 (match_operand:SI 2 "arith_reg_operand")) 1969 (match_operand:SI 3 "arith_reg_operand"))) 1970 (clobber (reg:SI T_REG))] 1971 "TARGET_SH1 && can_create_pseudo_p ()" 1972 "#" 1973 "&& 1" 1974 [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3)) 1975 (match_dup 1))) 1976 (clobber (reg:SI T_REG))])]) 1977 1978(define_insn_and_split "*addc" 1979 [(set (match_operand:SI 0 "arith_reg_dest") 1980 (plus:SI (match_operand 1 "treg_set_expr") 1981 (plus:SI (match_operand:SI 2 "arith_reg_operand") 1982 (match_operand:SI 3 "arith_reg_operand")))) 1983 (clobber (reg:SI T_REG))] 1984 "TARGET_SH1 && can_create_pseudo_p ()" 1985 "#" 1986 "&& 1" 1987 [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3)) 1988 (match_dup 1))) 1989 (clobber (reg:SI T_REG))])]) 1990 1991;; Sometimes combine will try to do 'reg + (0-reg) + 1' if the *addc pattern 1992;; matched. Split this up into a simple sub add sequence, as this will save 1993;; us one sett insn. 1994(define_insn_and_split "*minus_plus_one" 1995 [(set (match_operand:SI 0 "arith_reg_dest" "") 1996 (plus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "") 1997 (match_operand:SI 2 "arith_reg_operand" "")) 1998 (const_int 1)))] 1999 "TARGET_SH1" 2000 "#" 2001 "&& 1" 2002 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2))) 2003 (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))]) 2004 2005 2006;; The tree optimiziers canonicalize 2007;; reg + (reg & 1) 2008;; into 2009;; (reg + 1) & -2 2010;; 2011;; On SH2A an add-bclr sequence will be used to handle this. 2012;; On non-SH2A re-emit the add-and sequence to improve register utilization. 2013(define_insn_and_split "*round_int_even" 2014 [(set (match_operand:SI 0 "arith_reg_dest") 2015 (and:SI (plus:SI (match_operand:SI 1 "arith_reg_operand") 2016 (const_int 1)) 2017 (const_int -2)))] 2018 "TARGET_SH1 && !TARGET_SH2A && can_create_pseudo_p () 2019 && !reg_overlap_mentioned_p (operands[0], operands[1])" 2020 "#" 2021 "&& 1" 2022 [(set (match_dup 0) (const_int -2)) 2023 (set (match_dup 2) (plus:SI (match_dup 1) (const_int 1))) 2024 (set (match_dup 0) (and:SI (match_dup 0) (match_dup 2)))] 2025{ 2026 operands[2] = gen_reg_rtx (SImode); 2027}) 2028 2029;; If the *round_int_even pattern is combined with another plus, 2030;; convert it into an addc pattern to emit an shlr-addc sequence. 2031;; This split is taken by combine on non-SH2A and SH2A. 2032(define_split 2033 [(set (match_operand:SI 0 "arith_reg_dest") 2034 (plus:SI (and:SI (plus:SI (match_operand:SI 1 "arith_reg_operand") 2035 (const_int 1)) 2036 (const_int -2)) 2037 (match_operand:SI 2 "arith_reg_operand")))] 2038 "TARGET_SH1 && can_create_pseudo_p ()" 2039 [(parallel [(set (match_dup 0) 2040 (plus:SI (plus:SI (match_dup 1) (match_dup 2)) 2041 (and:SI (match_dup 1) (const_int 1)))) 2042 (clobber (reg:SI T_REG))])]) 2043 2044;; Split 'reg + T' into 'reg + 0 + T' to utilize the addc insn. 2045;; If the 0 constant can be CSE-ed, this becomes a one instruction 2046;; operation, as opposed to sequences such as 2047;; movt r2 2048;; add r2,r3 2049;; 2050;; Even if the constant is not CSE-ed, a sequence such as 2051;; mov #0,r2 2052;; addc r2,r3 2053;; can be scheduled much better since the load of the constant can be 2054;; done earlier, before any comparison insns that store the result in 2055;; the T bit. 2056;; However, avoid things like 'reg + 1', which would expand into a 2057;; 3 insn sequence, instead of add #imm8. 2058(define_insn_and_split "*addc_t_r" 2059 [(set (match_operand:SI 0 "arith_reg_dest") 2060 (plus:SI (match_operand 1 "treg_set_expr_not_const01") 2061 (match_operand:SI 2 "arith_reg_operand"))) 2062 (clobber (reg:SI T_REG))] 2063 "TARGET_SH1 && can_create_pseudo_p ()" 2064 "#" 2065 "&& 1" 2066 [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (const_int 0)) 2067 (match_dup 1))) 2068 (clobber (reg:SI T_REG))])]) 2069 2070(define_insn_and_split "*addc_r_t" 2071 [(set (match_operand:SI 0 "arith_reg_dest") 2072 (plus:SI (match_operand:SI 1 "arith_reg_operand") 2073 (match_operand 2 "treg_set_expr_not_const01"))) 2074 (clobber (reg:SI T_REG))] 2075 "TARGET_SH1 && can_create_pseudo_p ()" 2076 "#" 2077 "&& 1" 2078 [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (const_int 0)) 2079 (match_dup 2))) 2080 (clobber (reg:SI T_REG))])]) 2081 2082;; Convert '2 * reg + T' into 'reg + reg + T'. 2083(define_insn_and_split "*addc_2r_t" 2084 [(set (match_operand:SI 0 "arith_reg_dest") 2085 (plus:SI (match_operand 1 "treg_set_expr") 2086 (ashift:SI (match_operand:SI 2 "arith_reg_operand") 2087 (const_int 1)))) 2088 (clobber (reg:SI T_REG))] 2089 "TARGET_SH1 && can_create_pseudo_p ()" 2090 "#" 2091 "&& 1" 2092 [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 2)) 2093 (match_dup 1))) 2094 (clobber (reg:SI T_REG))])]) 2095 2096(define_insn_and_split "*addc_2r_t" 2097 [(set (match_operand:SI 0 "arith_reg_dest") 2098 (plus:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand") 2099 (const_int 1)) 2100 (match_operand 2 "treg_set_expr"))) 2101 (clobber (reg:SI T_REG))] 2102 "TARGET_SH1 && can_create_pseudo_p ()" 2103 "#" 2104 "&& 1" 2105 [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (match_dup 1)) 2106 (match_dup 2))) 2107 (clobber (reg:SI T_REG))])]) 2108 2109;; Convert '(op2 + T) - op3' into 'op2 + (-op3) + T' 2110(define_insn_and_split "*addc_negreg_t" 2111 [(set (match_operand:SI 0 "arith_reg_dest") 2112 (minus:SI (plus:SI (match_operand 1 "treg_set_expr") 2113 (match_operand:SI 2 "arith_reg_operand")) 2114 (match_operand:SI 3 "arith_reg_operand"))) 2115 (clobber (reg:SI T_REG))] 2116 "TARGET_SH1 && can_create_pseudo_p ()" 2117 "#" 2118 "&& 1" 2119 [(set (match_dup 4) (neg:SI (match_dup 3))) 2120 (parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 4)) 2121 (match_dup 1))) 2122 (clobber (reg:SI T_REG))])] 2123{ 2124 operands[4] = gen_reg_rtx (SImode); 2125}) 2126 2127(define_expand "addsi3" 2128 [(set (match_operand:SI 0 "arith_reg_dest") 2129 (plus:SI (match_operand:SI 1 "arith_reg_operand") 2130 (match_operand:SI 2 "arith_or_int_operand")))] 2131 "" 2132{ 2133 if (TARGET_SH1 && !arith_operand (operands[2], SImode)) 2134 { 2135 if (!sh_lra_p () || reg_overlap_mentioned_p (operands[0], operands[1])) 2136 { 2137 emit_insn (gen_addsi3_scr (operands[0], operands[1], operands[2])); 2138 DONE; 2139 } 2140 } 2141}) 2142 2143(define_insn "addsi3_media" 2144 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 2145 (plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r") 2146 (match_operand:SI 2 "arith_operand" "r,I10")))] 2147 "TARGET_SHMEDIA" 2148 "@ 2149 add.l %1, %2, %0 2150 addi.l %1, %2, %0" 2151 [(set_attr "type" "arith_media") 2152 (set_attr "highpart" "ignore")]) 2153 2154(define_insn "addsidi3_media" 2155 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") 2156 (sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand" 2157 "%r,r") 2158 (match_operand:SI 2 "arith_operand" 2159 "r,I10"))))] 2160 "TARGET_SHMEDIA" 2161 "@ 2162 add.l %1, %2, %0 2163 addi.l %1, %2, %0" 2164 [(set_attr "type" "arith_media") 2165 (set_attr "highpart" "ignore")]) 2166 2167;; The *addsi3_compact is made an insn_and_split and accepts actually 2168;; impossible constraints to make LRA's register elimination work well on SH. 2169;; The problem is that LRA expects something like 2170;; (set rA (plus rB (const_int N))) 2171;; to work. We can do that, but we have to split out an additional reg-reg 2172;; copy or constant load before the actual add insn. 2173;; Use u constraint for that case to avoid the invalid value in the stack 2174;; pointer. 2175;; This also results in better code when LRA is not used. However, we have 2176;; to use different sets of patterns and the order of these patterns is 2177;; important. 2178;; In some cases the constant zero might end up in operands[2] of the 2179;; patterns. We have to accept that and convert it into a reg-reg move. 2180(define_insn_and_split "*addsi3_compact_lra" 2181 [(set (match_operand:SI 0 "arith_reg_dest" "=r,&u") 2182 (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0,r") 2183 (match_operand:SI 2 "arith_or_int_operand" "rI08,rn")))] 2184 "TARGET_SH1 && sh_lra_p () 2185 && (! reg_overlap_mentioned_p (operands[0], operands[1]) 2186 || arith_operand (operands[2], SImode))" 2187 "@ 2188 add %2,%0 2189 #" 2190 "&& reload_completed 2191 && ! reg_overlap_mentioned_p (operands[0], operands[1])" 2192 [(set (match_dup 0) (match_dup 2)) 2193 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))] 2194{ 2195 /* Prefer 'mov r0,r1; add #imm8,r1' over 'mov #imm8,r1; add r0,r1' */ 2196 if (satisfies_constraint_I08 (operands[2])) 2197 std::swap (operands[1], operands[2]); 2198} 2199 [(set_attr "type" "arith")]) 2200 2201(define_insn_and_split "addsi3_scr" 2202 [(set (match_operand:SI 0 "arith_reg_dest" "=r,&u,&u") 2203 (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0,r,r") 2204 (match_operand:SI 2 "arith_or_int_operand" "rI08,r,n"))) 2205 (clobber (match_scratch:SI 3 "=X,X,&u"))] 2206 "TARGET_SH1" 2207 "@ 2208 add %2,%0 2209 # 2210 #" 2211 "&& reload_completed" 2212 [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))] 2213{ 2214 if (operands[2] == const0_rtx) 2215 { 2216 emit_move_insn (operands[0], operands[1]); 2217 DONE; 2218 } 2219 2220 if (CONST_INT_P (operands[2]) && !satisfies_constraint_I08 (operands[2])) 2221 { 2222 if (reg_overlap_mentioned_p (operands[0], operands[1])) 2223 { 2224 emit_move_insn (operands[3], operands[2]); 2225 emit_move_insn (operands[0], operands[1]); 2226 operands[2] = operands[3]; 2227 } 2228 else 2229 { 2230 emit_move_insn (operands[0], operands[2]); 2231 operands[2] = operands[1]; 2232 } 2233 } 2234 else if (!reg_overlap_mentioned_p (operands[0], operands[1])) 2235 { 2236 if (!reg_overlap_mentioned_p (operands[0], operands[2])) 2237 emit_move_insn (operands[0], operands[1]); 2238 else 2239 operands[2] = operands[1]; 2240 } 2241} 2242 [(set_attr "type" "arith")]) 2243 2244;; Old reload might generate add insns directly (not through the expander) for 2245;; address register calculations when reloading, in which case it won't try 2246;; the addsi_scr pattern. Because reload will sometimes try to validate 2247;; the generated insns and their constraints, this pattern must be 2248;; recognizable during and after reload. However, when reload generates 2249;; address register calculations for the stack pointer, we don't allow this 2250;; pattern. This will make reload prefer using indexed @(reg + reg) address 2251;; modes when the displacement of a @(disp + reg) doesn't fit. 2252(define_insn_and_split "*addsi3" 2253 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 2254 (plus:SI (match_operand:SI 1 "arith_reg_operand" "r") 2255 (match_operand:SI 2 "arith_or_int_operand" "rn")))] 2256 "TARGET_SH1 && !sh_lra_p () 2257 && (reload_completed || reload_in_progress) 2258 && !reg_overlap_mentioned_p (operands[0], operands[1]) 2259 && (!reload_in_progress 2260 || ((!REG_P (operands[1]) || REGNO (operands[1]) != SP_REG) 2261 && (!REG_P (operands[2]) || REGNO (operands[2]) != SP_REG)))" 2262 "#" 2263 "&& 1" 2264 [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))] 2265{ 2266 if (operands[2] == const0_rtx) 2267 { 2268 emit_move_insn (operands[0], operands[1]); 2269 DONE; 2270 } 2271 2272 if (CONST_INT_P (operands[2])) 2273 { 2274 if (satisfies_constraint_I08 (operands[2])) 2275 emit_move_insn (operands[0], operands[1]); 2276 else 2277 { 2278 emit_move_insn (operands[0], operands[2]); 2279 operands[2] = operands[1]; 2280 } 2281 } 2282 else if (!reg_overlap_mentioned_p (operands[0], operands[2])) 2283 emit_move_insn (operands[0], operands[1]); 2284 else 2285 operands[2] = operands[1]; 2286}) 2287 2288(define_insn_and_split "*addsi3" 2289 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 2290 (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0,r") 2291 (match_operand:SI 2 "arith_operand" "rI08,Z")))] 2292 "TARGET_SH1 && !sh_lra_p ()" 2293 "@ 2294 add %2,%0 2295 #" 2296 "&& operands[2] == const0_rtx" 2297 [(set (match_dup 0) (match_dup 1))] 2298{ 2299} 2300 [(set_attr "type" "arith")]) 2301 2302;; ------------------------------------------------------------------------- 2303;; Subtraction instructions 2304;; ------------------------------------------------------------------------- 2305 2306(define_expand "subdi3" 2307 [(set (match_operand:DI 0 "arith_reg_operand" "") 2308 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "") 2309 (match_operand:DI 2 "arith_reg_operand" "")))] 2310 "" 2311{ 2312 if (TARGET_SH1) 2313 { 2314 operands[1] = force_reg (DImode, operands[1]); 2315 emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2])); 2316 DONE; 2317 } 2318}) 2319 2320(define_insn "*subdi3_media" 2321 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 2322 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN") 2323 (match_operand:DI 2 "arith_reg_operand" "r")))] 2324 "TARGET_SHMEDIA" 2325 "sub %N1, %2, %0" 2326 [(set_attr "type" "arith_media")]) 2327 2328(define_insn "subdisi3_media" 2329 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0) 2330 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN") 2331 (match_operand:DI 2 "arith_reg_operand" "r")))] 2332 "TARGET_SHMEDIA" 2333 "sub.l %N1, %2, %0" 2334 [(set_attr "type" "arith_media") 2335 (set_attr "highpart" "ignore")]) 2336 2337(define_insn_and_split "subdi3_compact" 2338 [(set (match_operand:DI 0 "arith_reg_dest") 2339 (minus:DI (match_operand:DI 1 "arith_reg_operand") 2340 (match_operand:DI 2 "arith_reg_operand"))) 2341 (clobber (reg:SI T_REG))] 2342 "TARGET_SH1" 2343 "#" 2344 "&& can_create_pseudo_p ()" 2345 [(const_int 0)] 2346{ 2347 emit_insn (gen_clrt ()); 2348 emit_insn (gen_subc (gen_lowpart (SImode, operands[0]), 2349 gen_lowpart (SImode, operands[1]), 2350 gen_lowpart (SImode, operands[2]))); 2351 emit_insn (gen_subc (gen_highpart (SImode, operands[0]), 2352 gen_highpart (SImode, operands[1]), 2353 gen_highpart (SImode, operands[2]))); 2354 DONE; 2355}) 2356 2357(define_insn "subc" 2358 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 2359 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0") 2360 (match_operand:SI 2 "arith_reg_operand" "r")) 2361 (reg:SI T_REG))) 2362 (set (reg:SI T_REG) 2363 (gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2)) 2364 (reg:SI T_REG)) 2365 (match_dup 1)))] 2366 "TARGET_SH1" 2367 "subc %2,%0" 2368 [(set_attr "type" "arith")]) 2369 2370;; A simplified version of the subc insn, where the exact value of the 2371;; T bit doesn't matter. This is easier for combine to pick up. 2372;; We allow a reg or 0 for one of the operands in order to be able to 2373;; do 'reg - T' sequences. Reload will load the constant 0 into the reg 2374;; as needed. 2375(define_insn_and_split "*subc" 2376 [(set (match_operand:SI 0 "arith_reg_dest") 2377 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand") 2378 (match_operand:SI 2 "arith_reg_or_0_operand")) 2379 (match_operand 3 "treg_set_expr"))) 2380 (clobber (reg:SI T_REG))] 2381 "TARGET_SH1 && can_create_pseudo_p ()" 2382 "#" 2383 "&& 1" 2384 [(const_int 0)] 2385{ 2386 sh_treg_insns ti = sh_split_treg_set_expr (operands[3], curr_insn); 2387 if (ti.has_trailing_nott ()) 2388 { 2389 if (operands[2] == const0_rtx) 2390 { 2391 /* op1 - (1 - T) = op1 - 1 + T = op1 + (-1) + T */ 2392 remove_insn (ti.trailing_nott ()); 2393 emit_insn (gen_addc (operands[0], operands[1], 2394 force_reg (SImode, GEN_INT (-1)))); 2395 DONE; 2396 } 2397 else if (!TARGET_SH2A) 2398 { 2399 /* op1 - op2 - (1 - T) = op1 + (0 - op2 - 1) + T = op1 + ~op2 + T 2400 On SH2A keep the nott insn, because nott-subc sequence doesn't 2401 mutate the inputs. */ 2402 remove_insn (ti.trailing_nott ()); 2403 rtx tmp = gen_reg_rtx (SImode); 2404 emit_insn (gen_one_cmplsi2 (tmp, operands[2])); 2405 emit_insn (gen_addc (operands[0], operands[1], tmp)); 2406 DONE; 2407 } 2408 } 2409 2410 emit_insn (gen_subc (operands[0], operands[1], 2411 force_reg (SImode, operands[2]))); 2412 DONE; 2413}) 2414 2415;; Convert reg - T - reg = reg - reg - T 2416(define_insn_and_split "*subc" 2417 [(set (match_operand:SI 0 "arith_reg_dest") 2418 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand") 2419 (match_operand 2 "treg_set_expr")) 2420 (match_operand:SI 3 "arith_reg_operand"))) 2421 (clobber (reg:SI T_REG))] 2422 "TARGET_SH1 && can_create_pseudo_p ()" 2423 "#" 2424 "&& 1" 2425 [(parallel [(set (match_dup 0) 2426 (minus:SI (minus:SI (match_dup 1) (match_dup 3)) 2427 (match_dup 2))) 2428 (clobber (reg:SI T_REG))])]) 2429 2430;; Split reg - reg - 1 into a sett subc sequence, as it can be scheduled 2431;; better, if the sett insn can be done early. 2432;; Notice that combine turns 'a - b - 1' into 'a + (~b)'. 2433(define_insn_and_split "*subc" 2434 [(set (match_operand:SI 0 "arith_reg_dest" "") 2435 (plus:SI (not:SI (match_operand:SI 1 "arith_reg_operand" "")) 2436 (match_operand:SI 2 "arith_reg_operand" ""))) 2437 (clobber (reg:SI T_REG))] 2438 "TARGET_SH1 && can_create_pseudo_p ()" 2439 "#" 2440 "&& 1" 2441 [(parallel [(set (match_dup 0) 2442 (minus:SI (minus:SI (match_dup 2) (match_dup 1)) 2443 (const_int 1))) 2444 (clobber (reg:SI T_REG))])]) 2445 2446;; Split 'reg - T' into 'reg - 0 - T' to utilize the subc insn. 2447;; If the 0 constant can be CSE-ed, this becomes a one instruction 2448;; operation, as opposed to sequences such as 2449;; movt r2 2450;; sub r2,r3 2451;; 2452;; Even if the constant is not CSE-ed, a sequence such as 2453;; mov #0,r2 2454;; subc r2,r3 2455;; can be scheduled much better since the load of the constant can be 2456;; done earlier, before any comparison insns that store the result in 2457;; the T bit. 2458;; However, avoid things like 'reg - 1', which would expand into a 2459;; 3 insn sequence, instead of add #imm8. 2460(define_insn_and_split "*subc" 2461 [(set (match_operand:SI 0 "arith_reg_dest" "") 2462 (minus:SI (match_operand:SI 1 "arith_reg_operand" "") 2463 (match_operand 2 "treg_set_expr_not_const01"))) 2464 (clobber (reg:SI T_REG))] 2465 "TARGET_SH1 && can_create_pseudo_p ()" 2466 "#" 2467 "&& 1" 2468 [(parallel [(set (match_dup 0) 2469 (minus:SI (minus:SI (match_dup 1) (const_int 0)) 2470 (match_dup 2))) 2471 (clobber (reg:SI T_REG))])]) 2472 2473;; Convert 2474;; (1 - T) - op2 = 1 - op2 - T 2475(define_insn_and_split "*subc_negt_reg" 2476 [(set (match_operand:SI 0 "arith_reg_dest") 2477 (minus:SI (match_operand 1 "treg_set_expr_not_const01") 2478 (match_operand:SI 2 "arith_reg_operand"))) 2479 (clobber (reg:SI T_REG))] 2480 "TARGET_SH1 && can_create_pseudo_p ()" 2481 "#" 2482 "&& 1" 2483 [(const_int 0)] 2484{ 2485 sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn); 2486 if (ti.remove_trailing_nott ()) 2487 { 2488 /* (1 - T) - op2 = 1 - op2 - T */ 2489 emit_insn (gen_subc (operands[0], 2490 force_reg (SImode, GEN_INT (1)), operands[2])); 2491 } 2492 else 2493 { 2494 /* T - op2: use movt,sub sequence. */ 2495 rtx tmp = gen_reg_rtx (SImode); 2496 emit_insn (gen_movt (tmp, get_t_reg_rtx ())); 2497 emit_insn (gen_subsi3 (operands[0], tmp, operands[2])); 2498 } 2499 DONE; 2500}) 2501 2502;; Convert 2503;; op1 - (1 - T) + op3 = op1 - 1 + T + op3 2504;; (op1 - T) + op3 = op1 - (-op3) - T 2505(define_insn_and_split "*subc_negreg_t" 2506 [(set (match_operand:SI 0 "arith_reg_dest") 2507 (plus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand") 2508 (match_operand 2 "treg_set_expr")) 2509 (match_operand:SI 3 "arith_reg_operand"))) 2510 (clobber (reg:SI T_REG))] 2511 "TARGET_SH1 && can_create_pseudo_p ()" 2512 "#" 2513 "&& 1" 2514 [(const_int 0)] 2515{ 2516 sh_treg_insns ti = sh_split_treg_set_expr (operands[2], curr_insn); 2517 if (ti.remove_trailing_nott ()) 2518 { 2519 /* op1 - (1 - T) + op3 = (op1 - 1) + op3 + T */ 2520 rtx tmp = gen_reg_rtx (SImode); 2521 emit_insn (gen_addsi3 (tmp, operands[1], GEN_INT (-1))); 2522 emit_insn (gen_addc (operands[0], tmp, operands[3])); 2523 } 2524 else 2525 { 2526 /* (op1 - T) + op3' = 'op1 - (-op3) - T */ 2527 rtx tmp = gen_reg_rtx (SImode); 2528 emit_insn (gen_negsi2 (tmp, operands[3])); 2529 emit_insn (gen_subc (operands[0], operands[1], tmp)); 2530 } 2531 DONE; 2532}) 2533 2534(define_insn "*subsi3_internal" 2535 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 2536 (minus:SI (match_operand:SI 1 "arith_reg_operand" "0") 2537 (match_operand:SI 2 "arith_reg_operand" "r")))] 2538 "TARGET_SH1" 2539 "sub %2,%0" 2540 [(set_attr "type" "arith")]) 2541 2542(define_insn_and_split "*subsi3_media" 2543 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 2544 (minus:SI (match_operand:SI 1 "minuend_operand" "rN") 2545 (match_operand:SI 2 "extend_reg_operand" "r")))] 2546 "TARGET_SHMEDIA 2547 && (operands[1] != constm1_rtx 2548 || (GET_CODE (operands[2]) != TRUNCATE 2549 && GET_CODE (operands[2]) != SUBREG))" 2550 "sub.l %N1, %2, %0" 2551 "operands[1] == constm1_rtx" 2552 [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))] 2553 "" 2554 [(set_attr "type" "arith_media") 2555 (set_attr "highpart" "ignore")]) 2556 2557(define_split 2558 [(set (match_operand:SI 0 "arith_reg_dest" "") 2559 (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1 2560 "general_extend_operand" 2561 "") 0)) 0)))] 2562 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN" 2563 [(set (match_dup 0) (zero_extend:SI (match_dup 1))) 2564 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))] 2565 "") 2566 2567(define_split 2568 [(set (match_operand:SI 0 "arith_reg_dest" "") 2569 (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1 2570 "general_extend_operand" 2571 "") 0)) 3)))] 2572 "TARGET_SHMEDIA && TARGET_BIG_ENDIAN" 2573 [(set (match_dup 0) (zero_extend:SI (match_dup 1))) 2574 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))] 2575 "") 2576 2577;; Convert 2578;; constant - reg 2579;; to 2580;; neg reg 2581;; add reg, #const 2582;; since this will sometimes save one instruction. 2583;; Otherwise we might get a sequence like 2584;; mov #const, rY 2585;; sub rY, rX 2586;; mov rX, rY 2587;; if the source and dest regs are the same. 2588(define_expand "subsi3" 2589 [(set (match_operand:SI 0 "arith_reg_operand" "") 2590 (minus:SI (match_operand:SI 1 "arith_operand" "") 2591 (match_operand:SI 2 "arith_reg_operand" "")))] 2592 "" 2593{ 2594 if (TARGET_SH1 && CONST_INT_P (operands[1])) 2595 { 2596 emit_insn (gen_negsi2 (operands[0], operands[2])); 2597 emit_insn (gen_addsi3 (operands[0], operands[0], operands[1])); 2598 DONE; 2599 } 2600 if (TARGET_SHMEDIA) 2601 { 2602 if (!can_create_pseudo_p () 2603 && ! arith_reg_or_0_operand (operands[1], SImode)) 2604 FAIL; 2605 if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG) 2606 operands[1] = force_reg (SImode, operands[1]); 2607 } 2608}) 2609 2610;; ------------------------------------------------------------------------- 2611;; Division instructions 2612;; ------------------------------------------------------------------------- 2613 2614;; We take advantage of the library routines which don't clobber as many 2615;; registers as a normal function call would. 2616 2617;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it 2618;; also has an effect on the register that holds the address of the sfunc. 2619;; To make this work, we have an extra dummy insn that shows the use 2620;; of this register for reorg. 2621 2622(define_insn "use_sfunc_addr" 2623 [(set (reg:SI PR_REG) 2624 (unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))] 2625 "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])" 2626 "" 2627 [(set_attr "length" "0")]) 2628 2629(define_insn "udivsi3_sh2a" 2630 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 2631 (udiv:SI (match_operand:SI 1 "arith_reg_operand" "0") 2632 (match_operand:SI 2 "arith_reg_operand" "z")))] 2633 "TARGET_SH2A" 2634 "divu %2,%1" 2635 [(set_attr "type" "arith") 2636 (set_attr "in_delay_slot" "no")]) 2637 2638;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than 2639;; hard register 0. If we used hard register 0, then the next instruction 2640;; would be a move from hard register 0 to a pseudo-reg. If the pseudo-reg 2641;; gets allocated to a stack slot that needs its address reloaded, then 2642;; there is nothing to prevent reload from using r0 to reload the address. 2643;; This reload would clobber the value in r0 we are trying to store. 2644;; If we let reload allocate r0, then this problem can never happen. 2645(define_insn "udivsi3_i1" 2646 [(set (match_operand:SI 0 "register_operand" "=z,z") 2647 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2648 (clobber (reg:SI T_REG)) 2649 (clobber (reg:SI PR_REG)) 2650 (clobber (reg:SI R1_REG)) 2651 (clobber (reg:SI R4_REG)) 2652 (use (match_operand:SI 1 "arith_reg_operand" "r,r")) 2653 (use (match_operand 2 "" "Z,Ccl"))] 2654 "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1" 2655 "@ 2656 jsr @%1%# 2657 bsrf %1\n%O2:%#" 2658 [(set_attr "type" "sfunc") 2659 (set_attr "needs_delay_slot" "yes")]) 2660 2661; Since shmedia-nofpu code could be linked against shcompact code, and 2662; the udivsi3 libcall has the same name, we must consider all registers 2663; clobbered that are in the union of the registers clobbered by the 2664; shmedia and the shcompact implementation. Note, if the shcompact 2665; implementation actually used shcompact code, we'd need to clobber 2666; also r23 and fr23. 2667(define_insn "udivsi3_i1_media" 2668 [(set (match_operand:SI 0 "register_operand" "=z") 2669 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2670 (clobber (reg:SI T_MEDIA_REG)) 2671 (clobber (reg:SI PR_MEDIA_REG)) 2672 (clobber (reg:SI R20_REG)) 2673 (clobber (reg:SI R21_REG)) 2674 (clobber (reg:SI R22_REG)) 2675 (clobber (reg:DI TR0_REG)) 2676 (clobber (reg:DI TR1_REG)) 2677 (clobber (reg:DI TR2_REG)) 2678 (use (match_operand 1 "target_reg_operand" "b"))] 2679 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)" 2680 "blink %1, r18" 2681 [(set_attr "type" "sfunc") 2682 (set_attr "needs_delay_slot" "yes")]) 2683 2684(define_expand "udivsi3_i4_media" 2685 [(set (match_dup 3) 2686 (zero_extend:DI (match_operand:SI 1 "register_operand" ""))) 2687 (set (match_dup 4) 2688 (zero_extend:DI (match_operand:SI 2 "register_operand" ""))) 2689 (set (match_dup 5) (float:DF (match_dup 3))) 2690 (set (match_dup 6) (float:DF (match_dup 4))) 2691 (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6))) 2692 (set (match_dup 8) (fix:DI (match_dup 7))) 2693 (set (match_operand:SI 0 "register_operand" "") 2694 (truncate:SI (match_dup 8)))] 2695 "TARGET_SHMEDIA_FPU" 2696{ 2697 operands[3] = gen_reg_rtx (DImode); 2698 operands[4] = gen_reg_rtx (DImode); 2699 operands[5] = gen_reg_rtx (DFmode); 2700 operands[6] = gen_reg_rtx (DFmode); 2701 operands[7] = gen_reg_rtx (DFmode); 2702 operands[8] = gen_reg_rtx (DImode); 2703}) 2704 2705(define_insn "udivsi3_i4" 2706 [(set (match_operand:SI 0 "register_operand" "=y,y") 2707 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2708 (clobber (reg:SI T_REG)) 2709 (clobber (reg:SI PR_REG)) 2710 (clobber (reg:DF DR0_REG)) 2711 (clobber (reg:DF DR2_REG)) 2712 (clobber (reg:DF DR4_REG)) 2713 (clobber (reg:SI R0_REG)) 2714 (clobber (reg:SI R1_REG)) 2715 (clobber (reg:SI R4_REG)) 2716 (clobber (reg:SI R5_REG)) 2717 (clobber (reg:SI FPSCR_STAT_REG)) 2718 (use (match_operand:SI 1 "arith_reg_operand" "r,r")) 2719 (use (match_operand 2 "" "Z,Ccl")) 2720 (use (reg:SI FPSCR_MODES_REG))] 2721 "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE" 2722 "@ 2723 jsr @%1%# 2724 bsrf %1\n%O2:%#" 2725 [(set_attr "type" "sfunc") 2726 (set_attr "fp_mode" "double") 2727 (set_attr "needs_delay_slot" "yes")]) 2728 2729(define_insn "udivsi3_i4_single" 2730 [(set (match_operand:SI 0 "register_operand" "=y,y") 2731 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2732 (clobber (reg:SI T_REG)) 2733 (clobber (reg:SI PR_REG)) 2734 (clobber (reg:DF DR0_REG)) 2735 (clobber (reg:DF DR2_REG)) 2736 (clobber (reg:DF DR4_REG)) 2737 (clobber (reg:SI R0_REG)) 2738 (clobber (reg:SI R1_REG)) 2739 (clobber (reg:SI R4_REG)) 2740 (clobber (reg:SI R5_REG)) 2741 (use (match_operand:SI 1 "arith_reg_operand" "r,r")) 2742 (use (match_operand 2 "" "Z,Ccl"))] 2743 "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT) 2744 && TARGET_FPU_SINGLE" 2745 "@ 2746 jsr @%1%# 2747 bsrf %1\n%O2:%#" 2748 [(set_attr "type" "sfunc") 2749 (set_attr "needs_delay_slot" "yes")]) 2750 2751(define_insn "udivsi3_i4_int" 2752 [(set (match_operand:SI 0 "register_operand" "=z") 2753 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2754 (clobber (reg:SI T_REG)) 2755 (clobber (reg:SI R1_REG)) 2756 (clobber (reg:SI PR_REG)) 2757 (clobber (reg:SI MACH_REG)) 2758 (clobber (reg:SI MACL_REG)) 2759 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 2760 "TARGET_SH1" 2761 "jsr @%1%#" 2762 [(set_attr "type" "sfunc") 2763 (set_attr "needs_delay_slot" "yes")]) 2764 2765 2766(define_expand "udivsi3" 2767 [(set (match_dup 3) (symbol_ref:SI "__udivsi3")) 2768 (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" "")) 2769 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" "")) 2770 (parallel [(set (match_operand:SI 0 "register_operand" "") 2771 (udiv:SI (reg:SI R4_REG) 2772 (reg:SI R5_REG))) 2773 (clobber (reg:SI T_REG)) 2774 (clobber (reg:SI PR_REG)) 2775 (clobber (reg:SI R4_REG)) 2776 (use (match_dup 3))])] 2777 "" 2778{ 2779 rtx last; 2780 2781 operands[3] = gen_reg_rtx (Pmode); 2782 /* Emit the move of the address to a pseudo outside of the libcall. */ 2783 if (TARGET_DIVIDE_CALL_TABLE) 2784 { 2785 /* libgcc2:__udivmoddi4 is not supposed to use an actual division, since 2786 that causes problems when the divide code is supposed to come from a 2787 separate library. Division by zero is undefined, so dividing 1 can be 2788 implemented by comparing with the divisor. */ 2789 if (operands[1] == const1_rtx && currently_expanding_to_rtl) 2790 { 2791 rtx test = gen_rtx_GEU (VOIDmode, operands[1], operands[2]); 2792 emit_insn (gen_cstoresi4 (operands[0], test, 2793 operands[1], operands[2])); 2794 DONE; 2795 } 2796 else if (operands[2] == const0_rtx) 2797 { 2798 emit_move_insn (operands[0], operands[2]); 2799 DONE; 2800 } 2801 function_symbol (operands[3], "__udivsi3_i4i", SFUNC_GOT); 2802 last = gen_udivsi3_i4_int (operands[0], operands[3]); 2803 } 2804 else if (TARGET_DIVIDE_CALL_FP) 2805 { 2806 rtx lab = function_symbol (operands[3], "__udivsi3_i4", SFUNC_STATIC).lab; 2807 if (TARGET_FPU_SINGLE) 2808 last = gen_udivsi3_i4_single (operands[0], operands[3], lab); 2809 else 2810 last = gen_udivsi3_i4 (operands[0], operands[3], lab); 2811 } 2812 else if (TARGET_SHMEDIA_FPU) 2813 { 2814 operands[1] = force_reg (SImode, operands[1]); 2815 operands[2] = force_reg (SImode, operands[2]); 2816 emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2])); 2817 DONE; 2818 } 2819 else if (TARGET_SH2A) 2820 { 2821 operands[1] = force_reg (SImode, operands[1]); 2822 operands[2] = force_reg (SImode, operands[2]); 2823 emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2])); 2824 DONE; 2825 } 2826 else if (TARGET_SH5) 2827 { 2828 function_symbol (operands[3], 2829 TARGET_FPU_ANY ? "__udivsi3_i4" : "__udivsi3", 2830 SFUNC_STATIC); 2831 2832 if (TARGET_SHMEDIA) 2833 last = gen_udivsi3_i1_media (operands[0], operands[3]); 2834 else if (TARGET_FPU_ANY) 2835 last = gen_udivsi3_i4_single (operands[0], operands[3], const0_rtx); 2836 else 2837 last = gen_udivsi3_i1 (operands[0], operands[3], const0_rtx); 2838 } 2839 else 2840 { 2841 rtx lab = function_symbol (operands[3], "__udivsi3", SFUNC_STATIC).lab; 2842 last = gen_udivsi3_i1 (operands[0], operands[3], lab); 2843 } 2844 emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]); 2845 emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]); 2846 emit_insn (last); 2847 DONE; 2848}) 2849 2850(define_insn "divsi3_sh2a" 2851 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 2852 (div:SI (match_operand:SI 1 "arith_reg_operand" "0") 2853 (match_operand:SI 2 "arith_reg_operand" "z")))] 2854 "TARGET_SH2A" 2855 "divs %2,%1" 2856 [(set_attr "type" "arith") 2857 (set_attr "in_delay_slot" "no")]) 2858 2859(define_insn "divsi3_i1" 2860 [(set (match_operand:SI 0 "register_operand" "=z") 2861 (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2862 (clobber (reg:SI T_REG)) 2863 (clobber (reg:SI PR_REG)) 2864 (clobber (reg:SI R1_REG)) 2865 (clobber (reg:SI R2_REG)) 2866 (clobber (reg:SI R3_REG)) 2867 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 2868 "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1" 2869 "jsr @%1%#" 2870 [(set_attr "type" "sfunc") 2871 (set_attr "needs_delay_slot" "yes")]) 2872 2873(define_insn "divsi3_i1_media" 2874 [(set (match_operand:SI 0 "register_operand" "=z") 2875 (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2876 (clobber (reg:SI T_MEDIA_REG)) 2877 (clobber (reg:SI PR_MEDIA_REG)) 2878 (clobber (reg:SI R1_REG)) 2879 (clobber (reg:SI R20_REG)) 2880 (clobber (reg:SI R21_REG)) 2881 (clobber (reg:SI TR0_REG)) 2882 (use (match_operand 1 "target_reg_operand" "b"))] 2883 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)" 2884 "blink %1, r18" 2885 [(set_attr "type" "sfunc")]) 2886 2887(define_insn "divsi3_media_2" 2888 [(set (match_operand:SI 0 "register_operand" "=z") 2889 (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2890 (clobber (reg:SI T_MEDIA_REG)) 2891 (clobber (reg:SI PR_MEDIA_REG)) 2892 (clobber (reg:SI R1_REG)) 2893 (clobber (reg:SI R21_REG)) 2894 (clobber (reg:SI TR0_REG)) 2895 (use (reg:SI R20_REG)) 2896 (use (match_operand 1 "target_reg_operand" "b"))] 2897 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)" 2898 "blink %1, r18" 2899 [(set_attr "type" "sfunc")]) 2900 2901;; This pattern acts as a placeholder for -mdiv=inv:call to carry 2902;; hard reg clobbers and data dependencies that we need when we want 2903;; to rematerialize the division into a call. 2904(define_insn_and_split "divsi_inv_call" 2905 [(set (match_operand:SI 0 "register_operand" "=r") 2906 (div:SI (match_operand:SI 1 "register_operand" "r") 2907 (match_operand:SI 2 "register_operand" "r"))) 2908 (clobber (reg:SI R4_REG)) 2909 (clobber (reg:SI R5_REG)) 2910 (clobber (reg:SI T_MEDIA_REG)) 2911 (clobber (reg:SI PR_MEDIA_REG)) 2912 (clobber (reg:SI R1_REG)) 2913 (clobber (reg:SI R21_REG)) 2914 (clobber (reg:SI TR0_REG)) 2915 (clobber (reg:SI R20_REG)) 2916 (use (match_operand:SI 3 "register_operand" "r"))] 2917 "TARGET_SHMEDIA" 2918 "#" 2919 "&& (reload_in_progress || reload_completed)" 2920 [(set (match_dup 0) (match_dup 3))] 2921 "" 2922 [(set_attr "highpart" "must_split")]) 2923 2924;; This is the combiner pattern for -mdiv=inv:call . 2925(define_insn_and_split "*divsi_inv_call_combine" 2926 [(set (match_operand:SI 0 "register_operand" "=z") 2927 (div:SI (match_operand:SI 1 "register_operand" "r") 2928 (match_operand:SI 2 "register_operand" "r"))) 2929 (clobber (reg:SI R4_REG)) 2930 (clobber (reg:SI R5_REG)) 2931 (clobber (reg:SI T_MEDIA_REG)) 2932 (clobber (reg:SI PR_MEDIA_REG)) 2933 (clobber (reg:SI R1_REG)) 2934 (clobber (reg:SI R21_REG)) 2935 (clobber (reg:SI TR0_REG)) 2936 (clobber (reg:SI R20_REG)) 2937 (use (unspec:SI [(match_dup 1) 2938 (match_operand:SI 3 "" "") 2939 (unspec:SI [(match_operand:SI 4 "" "") 2940 (match_dup 3) 2941 (match_operand:DI 5 "" "")] 2942 UNSPEC_DIV_INV_M2) 2943 (match_operand:DI 6 "" "") 2944 (const_int 0) 2945 (const_int 0)] 2946 UNSPEC_DIV_INV_M3))] 2947 "TARGET_SHMEDIA" 2948 "#" 2949 "&& (reload_in_progress || reload_completed)" 2950 [(pc)] 2951{ 2952 const char *name = sh_divsi3_libfunc; 2953 enum sh_function_kind kind = SFUNC_GOT; 2954 rtx sym; 2955 2956 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]); 2957 emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]); 2958 while (TARGET_DIVIDE_INV_CALL2) 2959 { 2960 rtx x = operands[3]; 2961 2962 if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1) 2963 break; 2964 x = XVECEXP (x, 0, 0); 2965 name = "__sdivsi3_2"; 2966 kind = SFUNC_STATIC; 2967 emit_move_insn (gen_rtx_REG (DImode, R20_REG), x); 2968 break; 2969 } 2970 sym = function_symbol (NULL, name, kind).sym; 2971 emit_insn (gen_divsi3_media_2 (operands[0], sym)); 2972 DONE; 2973} 2974 [(set_attr "highpart" "must_split")]) 2975 2976(define_expand "divsi3_i4_media" 2977 [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r"))) 2978 (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r"))) 2979 (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4))) 2980 (set (match_operand:SI 0 "register_operand" "=r") 2981 (fix:SI (match_dup 5)))] 2982 "TARGET_SHMEDIA_FPU" 2983{ 2984 operands[3] = gen_reg_rtx (DFmode); 2985 operands[4] = gen_reg_rtx (DFmode); 2986 operands[5] = gen_reg_rtx (DFmode); 2987}) 2988 2989(define_insn "divsi3_i4" 2990 [(set (match_operand:SI 0 "register_operand" "=y,y") 2991 (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2992 (clobber (reg:SI PR_REG)) 2993 (clobber (reg:DF DR0_REG)) 2994 (clobber (reg:DF DR2_REG)) 2995 (clobber (reg:SI FPSCR_STAT_REG)) 2996 (use (match_operand:SI 1 "arith_reg_operand" "r,r")) 2997 (use (match_operand 2 "" "Z,Ccl")) 2998 (use (reg:SI FPSCR_MODES_REG))] 2999 "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE" 3000 "@ 3001 jsr @%1%# 3002 bsrf %1\n%O2:%#" 3003 [(set_attr "type" "sfunc") 3004 (set_attr "fp_mode" "double") 3005 (set_attr "needs_delay_slot" "yes")]) 3006 3007(define_insn "divsi3_i4_single" 3008 [(set (match_operand:SI 0 "register_operand" "=y,y") 3009 (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) 3010 (clobber (reg:SI PR_REG)) 3011 (clobber (reg:DF DR0_REG)) 3012 (clobber (reg:DF DR2_REG)) 3013 (clobber (reg:SI R2_REG)) 3014 (use (match_operand:SI 1 "arith_reg_operand" "r,r")) 3015 (use (match_operand 2 "" "Z,Ccl"))] 3016 "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT) 3017 && TARGET_FPU_SINGLE" 3018 "@ 3019 jsr @%1%# 3020 bsrf %1\n%O2:%#" 3021 [(set_attr "type" "sfunc") 3022 (set_attr "needs_delay_slot" "yes")]) 3023 3024(define_insn "divsi3_i4_int" 3025 [(set (match_operand:SI 0 "register_operand" "=z") 3026 (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) 3027 (clobber (reg:SI T_REG)) 3028 (clobber (reg:SI PR_REG)) 3029 (clobber (reg:SI R1_REG)) 3030 (clobber (reg:SI MACH_REG)) 3031 (clobber (reg:SI MACL_REG)) 3032 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 3033 "TARGET_SH1" 3034 "jsr @%1%#" 3035 [(set_attr "type" "sfunc") 3036 (set_attr "needs_delay_slot" "yes")]) 3037 3038(define_expand "divsi3" 3039 [(set (match_dup 3) (symbol_ref:SI "__sdivsi3")) 3040 (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" "")) 3041 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" "")) 3042 (parallel [(set (match_operand:SI 0 "register_operand" "") 3043 (div:SI (reg:SI R4_REG) 3044 (reg:SI R5_REG))) 3045 (clobber (reg:SI T_REG)) 3046 (clobber (reg:SI PR_REG)) 3047 (clobber (reg:SI R1_REG)) 3048 (clobber (reg:SI R2_REG)) 3049 (clobber (reg:SI R3_REG)) 3050 (use (match_dup 3))])] 3051 "" 3052{ 3053 rtx last; 3054 3055 operands[3] = gen_reg_rtx (Pmode); 3056 /* Emit the move of the address to a pseudo outside of the libcall. */ 3057 if (TARGET_DIVIDE_CALL_TABLE) 3058 { 3059 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT); 3060 last = gen_divsi3_i4_int (operands[0], operands[3]); 3061 } 3062 else if (TARGET_DIVIDE_CALL_FP) 3063 { 3064 rtx lab = function_symbol (operands[3], sh_divsi3_libfunc, 3065 SFUNC_STATIC).lab; 3066 if (TARGET_FPU_SINGLE) 3067 last = gen_divsi3_i4_single (operands[0], operands[3], lab); 3068 else 3069 last = gen_divsi3_i4 (operands[0], operands[3], lab); 3070 } 3071 else if (TARGET_SH2A) 3072 { 3073 operands[1] = force_reg (SImode, operands[1]); 3074 operands[2] = force_reg (SImode, operands[2]); 3075 emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2])); 3076 DONE; 3077 } 3078 else if (TARGET_DIVIDE_INV) 3079 { 3080 rtx dividend = operands[1]; 3081 rtx divisor = operands[2]; 3082 rtx tab_base; 3083 rtx nsb_res = gen_reg_rtx (DImode); 3084 rtx norm64 = gen_reg_rtx (DImode); 3085 rtx tab_ix = gen_reg_rtx (DImode); 3086 rtx norm32 = gen_reg_rtx (SImode); 3087 rtx i92 = force_reg (DImode, GEN_INT (92)); 3088 rtx scratch0a = gen_reg_rtx (DImode); 3089 rtx scratch0b = gen_reg_rtx (DImode); 3090 rtx inv0 = gen_reg_rtx (SImode); 3091 rtx scratch1a = gen_reg_rtx (DImode); 3092 rtx scratch1b = gen_reg_rtx (DImode); 3093 rtx shift = gen_reg_rtx (DImode); 3094 rtx i2p27, i43; 3095 rtx inv1 = gen_reg_rtx (SImode); 3096 rtx scratch2a = gen_reg_rtx (DImode); 3097 rtx scratch2b = gen_reg_rtx (SImode); 3098 rtx inv2 = gen_reg_rtx (SImode); 3099 rtx scratch3a = gen_reg_rtx (DImode); 3100 rtx scratch3b = gen_reg_rtx (DImode); 3101 rtx scratch3c = gen_reg_rtx (DImode); 3102 rtx scratch3d = gen_reg_rtx (SImode); 3103 rtx scratch3e = gen_reg_rtx (DImode); 3104 rtx result = gen_reg_rtx (SImode); 3105 3106 if (! arith_reg_or_0_operand (dividend, SImode)) 3107 dividend = force_reg (SImode, dividend); 3108 if (! arith_reg_operand (divisor, SImode)) 3109 divisor = force_reg (SImode, divisor); 3110 if (flag_pic && Pmode != DImode) 3111 { 3112 tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table"); 3113 tab_base = gen_datalabel_ref (tab_base); 3114 tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base)); 3115 } 3116 else 3117 { 3118 tab_base = gen_rtx_SYMBOL_REF (DImode, "__div_table"); 3119 tab_base = gen_datalabel_ref (tab_base); 3120 tab_base = force_reg (DImode, tab_base); 3121 } 3122 if (TARGET_DIVIDE_INV20U) 3123 i2p27 = force_reg (DImode, GEN_INT ((unsigned HOST_WIDE_INT)-2 << 27)); 3124 else 3125 i2p27 = GEN_INT (0); 3126 if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L) 3127 i43 = force_reg (DImode, GEN_INT (43)); 3128 else 3129 i43 = GEN_INT (0); 3130 emit_insn (gen_nsbdi (nsb_res, 3131 simplify_gen_subreg (DImode, divisor, SImode, 0))); 3132 emit_insn (gen_ashldi3_media (norm64, 3133 gen_rtx_SUBREG (DImode, divisor, 0), 3134 nsb_res)); 3135 emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58))); 3136 emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32))); 3137 emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32, 3138 inv0, scratch0a, scratch0b, 3139 scratch1a, scratch1b)); 3140 emit_insn (gen_subdi3 (shift, i92, nsb_res)); 3141 emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92, 3142 scratch2a)); 3143 emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift, 3144 i2p27, i43, 3145 scratch3a, scratch3b, scratch3c, 3146 scratch2a, scratch2b, scratch3d, scratch3e)); 3147 if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2) 3148 emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result)); 3149 else if (TARGET_DIVIDE_INV_FP) 3150 emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result, 3151 gen_reg_rtx (SImode), gen_reg_rtx (SImode), 3152 gen_reg_rtx (DFmode), gen_reg_rtx (DFmode), 3153 gen_reg_rtx (DFmode))); 3154 else 3155 emit_move_insn (operands[0], result); 3156 DONE; 3157 } 3158 else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP) 3159 { 3160 operands[1] = force_reg (SImode, operands[1]); 3161 operands[2] = force_reg (SImode, operands[2]); 3162 emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2])); 3163 DONE; 3164 } 3165 else if (TARGET_SH5) 3166 { 3167 if (TARGET_DIVIDE_CALL2) 3168 { 3169 rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table"); 3170 tab_base = gen_datalabel_ref (tab_base); 3171 emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base); 3172 } 3173 if (TARGET_FPU_ANY && TARGET_SH1) 3174 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC); 3175 else if (TARGET_DIVIDE_CALL2) 3176 function_symbol (operands[3], "__sdivsi3_2", SFUNC_STATIC); 3177 else 3178 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT); 3179 3180 if (TARGET_SHMEDIA) 3181 last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media) 3182 (operands[0], operands[3])); 3183 else if (TARGET_FPU_ANY) 3184 last = gen_divsi3_i4_single (operands[0], operands[3], const0_rtx); 3185 else 3186 last = gen_divsi3_i1 (operands[0], operands[3]); 3187 } 3188 else 3189 { 3190 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT); 3191 last = gen_divsi3_i1 (operands[0], operands[3]); 3192 } 3193 emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]); 3194 emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]); 3195 emit_insn (last); 3196 DONE; 3197}) 3198 3199;; operands: scratch, tab_base, tab_ix 3200;; These are unspecs because we could generate an indexed addressing mode 3201;; even if -m5-32media, where INDEX_REG_CLASS == NO_REGS, and this would 3202;; confuse reload. See PR27117. 3203(define_insn "divsi_inv_qitable" 3204 [(set (match_operand:DI 0 "register_operand" "=r") 3205 (zero_extend:DI (unspec:QI [(match_operand:DI 1 "register_operand" "r") 3206 (match_operand:DI 2 "register_operand" "r")] 3207 UNSPEC_DIV_INV_TABLE)))] 3208 "TARGET_SHMEDIA" 3209 "ldx.ub %1, %2, %0" 3210 [(set_attr "type" "load_media") 3211 (set_attr "highpart" "user")]) 3212 3213;; operands: scratch, tab_base, tab_ix 3214(define_insn "divsi_inv_hitable" 3215 [(set (match_operand:DI 0 "register_operand" "=r") 3216 (sign_extend:DI (unspec:HI [(match_operand:DI 1 "register_operand" "r") 3217 (match_operand:DI 2 "register_operand" "r")] 3218 UNSPEC_DIV_INV_TABLE)))] 3219 "TARGET_SHMEDIA" 3220 "ldx.w %1, %2, %0" 3221 [(set_attr "type" "load_media") 3222 (set_attr "highpart" "user")]) 3223 3224;; operands: inv0, tab_base, tab_ix, norm32 3225;; scratch equiv in sdivsi3_2: r19, r21 3226(define_expand "divsi_inv_m0" 3227 [(set (match_operand:SI 0 "register_operand" "=r") 3228 (unspec:SI [(match_operand:DI 1 "register_operand" "r") 3229 (match_operand:DI 2 "register_operand" "r") 3230 (match_operand:SI 3 "register_operand" "r")] 3231 UNSPEC_DIV_INV_M0)) 3232 (clobber (match_operand:DI 4 "register_operand" "=r")) 3233 (clobber (match_operand:DI 5 "register_operand" "=r"))] 3234 "TARGET_SHMEDIA" 3235{ 3236/* 3237tab_base: r20 3238tab_ix: r21 3239norm32: r25 3240 ldx.ub r20, r21, r19 // u0.8 3241 shlli r21, 1, r21 3242 muls.l r25, r19, r19 // s2.38 3243 ldx.w r20, r21, r21 // s2.14 3244 shari r19, 24, r19 // truncate to s2.14 3245 sub r21, r19, r19 // some 11 bit inverse in s1.14 3246*/ 3247 3248 rtx inv0 = operands[0]; 3249 rtx tab_base = operands[1]; 3250 rtx tab_ix = operands[2]; 3251 rtx norm32 = operands[3]; 3252 rtx scratch0 = operands[4]; 3253 rtx scratch0_si = gen_lowpart (SImode, scratch0); 3254 rtx scratch1 = operands[5]; 3255 3256 emit_insn (gen_divsi_inv_qitable (scratch0, tab_base, tab_ix)); 3257 emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1))); 3258 emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si)); 3259 emit_insn (gen_divsi_inv_hitable (scratch1, tab_base, scratch1)); 3260 emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24))); 3261 emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0)); 3262 DONE; 3263}) 3264 3265;; operands: inv1, tab_base, tab_ix, norm32 3266(define_insn_and_split "divsi_inv_m1" 3267 [(set (match_operand:SI 0 "register_operand" "=r") 3268 (unspec:SI [(match_operand:DI 1 "register_operand" "r") 3269 (match_operand:DI 2 "register_operand" "r") 3270 (match_operand:SI 3 "register_operand" "r")] 3271 UNSPEC_DIV_INV_M1)) 3272 (clobber (match_operand:SI 4 "register_operand" "=r")) 3273 (clobber (match_operand:DI 5 "register_operand" "=r")) 3274 (clobber (match_operand:DI 6 "register_operand" "=r")) 3275 (clobber (match_operand:DI 7 "register_operand" "=r")) 3276 (clobber (match_operand:DI 8 "register_operand" "=r"))] 3277 "TARGET_SHMEDIA" 3278 "#" 3279 "&& !can_create_pseudo_p ()" 3280 [(pc)] 3281{ 3282/* inv0: r19 3283 muls.l r19, r19, r18 // u0.28 3284 muls.l r25, r18, r18 // s2.58 3285 shlli r19, 45, r0 // multiply by two and convert to s2.58 3286 sub r0, r18, r18 3287 shari r18, 28, r18 // some 18 bit inverse in s1.30 3288*/ 3289 3290 rtx inv1 = operands[0]; 3291 rtx tab_base = operands[1]; 3292 rtx tab_ix = operands[2]; 3293 rtx norm32 = operands[3]; 3294 rtx inv0 = operands[4]; 3295 rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0); 3296 rtx scratch0a = operands[5]; 3297 rtx scratch0b = operands[6]; 3298 rtx scratch0 = operands[7]; 3299 rtx scratch1 = operands[8]; 3300 rtx scratch1_si = gen_lowpart (SImode, scratch1); 3301 3302 emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32, 3303 scratch0a, scratch0b)); 3304 emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0)); 3305 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si)); 3306 emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45))); 3307 emit_insn (gen_subdi3 (scratch1, scratch0, scratch1)); 3308 emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28))); 3309 DONE; 3310}) 3311 3312;; operands: inv2, norm32, inv1, i92 3313(define_insn_and_split "divsi_inv_m2" 3314 [(set (match_operand:SI 0 "register_operand" "=r") 3315 (unspec:SI [(match_operand:SI 1 "register_operand" "r") 3316 (match_operand:SI 2 "register_operand" "r") 3317 (match_operand:DI 3 "register_operand" "r")] 3318 UNSPEC_DIV_INV_M2)) 3319 (clobber (match_operand:DI 4 "register_operand" "=r"))] 3320 "TARGET_SHMEDIA" 3321 "#" 3322 "&& !can_create_pseudo_p ()" 3323 [(pc)] 3324{ 3325/* 3326 muls.l r18, r25, r0 // s2.60 3327 shari r0, 16, r0 // s-16.44 3328 sub 3329 muls.l r0, r18, r19 // s-16.74 3330 shari r19, 30, r19 // s-16.44 3331*/ 3332 rtx inv2 = operands[0]; 3333 rtx norm32 = operands[1]; 3334 rtx inv1 = operands[2]; 3335 rtx i92 = operands[3]; 3336 rtx scratch0 = operands[4]; 3337 rtx scratch0_si = gen_lowpart (SImode, scratch0); 3338 3339 emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32)); 3340 emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16))); 3341 emit_insn (gen_subdi3 (scratch0, i92, scratch0)); 3342 emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1)); 3343 emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30))); 3344 DONE; 3345}) 3346 3347(define_insn_and_split "divsi_inv_m3" 3348 [(set (match_operand:SI 0 "register_operand" "=r") 3349 (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN") 3350 (match_operand:SI 2 "register_operand" "r") 3351 (match_operand:SI 3 "register_operand" "r") 3352 (match_operand:DI 4 "register_operand" "r") 3353 (match_operand:DI 5 "arith_reg_or_0_operand" "rN") 3354 (match_operand:DI 6 "arith_reg_or_0_operand" "rN")] 3355 UNSPEC_DIV_INV_M3)) 3356 (clobber (match_operand:DI 7 "register_operand" "=r")) 3357 (clobber (match_operand:DI 8 "register_operand" "=r")) 3358 (clobber (match_operand:DI 9 "register_operand" "=r")) 3359 (clobber (match_operand:DI 10 "register_operand" "=r")) 3360 (clobber (match_operand:SI 11 "register_operand" "=r")) 3361 (clobber (match_operand:SI 12 "register_operand" "=r")) 3362 (clobber (match_operand:DI 13 "register_operand" "=r"))] 3363 "TARGET_SHMEDIA" 3364 "#" 3365 "&& !can_create_pseudo_p ()" 3366 [(pc)] 3367{ 3368/* 3369 r0: result r1: shift r4: dividend r18: inv1 r19: inv2 3370 r0: scratch0 r19: scratch1 r21: scratch2 3371 3372 muls.l r18, r4, r25 // s32.30 3373 muls.l r19, r4, r19 // s15.30 3374 shari r25, 63, r21 3375 shari r19, 14, r19 // s18.-14 3376 sub r25, r19, r0 3377 shard r0, r1, r0 3378 sub r0, r21, r0 3379*/ 3380 3381 rtx result = operands[0]; 3382 rtx dividend = operands[1]; 3383 rtx inv1 = operands[2]; 3384 rtx inv2 = operands[3]; 3385 rtx shift = operands[4]; 3386 rtx scratch0 = operands[7]; 3387 rtx scratch1 = operands[8]; 3388 rtx scratch2 = operands[9]; 3389 3390 if (satisfies_constraint_N (dividend)) 3391 { 3392 emit_move_insn (result, dividend); 3393 DONE; 3394 } 3395 3396 emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend)); 3397 emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend)); 3398 emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63))); 3399 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14))); 3400 emit_insn (gen_adddi3 (scratch0, scratch0, scratch1)); 3401 emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift)); 3402 emit_insn (gen_subdisi3_media (result, scratch0, scratch2)); 3403 DONE; 3404}) 3405 3406;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43 3407;; inv1: tab_base, tab_ix, norm32 3408;; inv2: norm32, inv1, i92 3409(define_insn_and_split "divsi_inv_m1_3" 3410 [(set (match_operand:SI 0 "register_operand" "=r") 3411 (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN") 3412 (unspec:SI [(match_operand:DI 2 "register_operand" "r") 3413 (match_operand:DI 3 "register_operand" "r") 3414 (match_operand:SI 4 "register_operand" "r")] 3415 UNSPEC_DIV_INV_M1) 3416 (unspec:SI [(match_dup 4) 3417 (unspec:SI [(match_dup 2) 3418 (match_dup 3) 3419 (match_dup 4)] UNSPEC_DIV_INV_M1) 3420 (match_operand:SI 5 "" "")] 3421 UNSPEC_DIV_INV_M2) 3422 (match_operand:DI 6 "register_operand" "r") 3423 (match_operand:DI 7 "arith_reg_or_0_operand" "rN") 3424 (match_operand:DI 8 "arith_reg_or_0_operand" "rN")] 3425 UNSPEC_DIV_INV_M3)) 3426 (clobber (match_operand:DI 9 "register_operand" "=r")) 3427 (clobber (match_operand:DI 10 "register_operand" "=r")) 3428 (clobber (match_operand:DI 11 "register_operand" "=r")) 3429 (clobber (match_operand:DI 12 "register_operand" "=r")) 3430 (clobber (match_operand:SI 13 "register_operand" "=r")) 3431 (clobber (match_operand:SI 14 "register_operand" "=r")) 3432 (clobber (match_operand:DI 15 "register_operand" "=r"))] 3433 "TARGET_SHMEDIA 3434 && (TARGET_DIVIDE_INV_MINLAT 3435 || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)" 3436 "#" 3437 "&& !can_create_pseudo_p ()" 3438 [(pc)] 3439{ 3440 rtx result = operands[0]; 3441 rtx dividend = operands[1]; 3442 rtx tab_base = operands[2]; 3443 rtx tab_ix = operands[3]; 3444 rtx norm32 = operands[4]; 3445 /* rtx i92 = operands[5]; */ 3446 rtx shift = operands[6]; 3447 rtx i2p27 = operands[7]; 3448 rtx i43 = operands[8]; 3449 rtx scratch0 = operands[9]; 3450 rtx scratch0_si = gen_lowpart (SImode, scratch0); 3451 rtx scratch1 = operands[10]; 3452 rtx scratch1_si = gen_lowpart (SImode, scratch1); 3453 rtx scratch2 = operands[11]; 3454 rtx scratch3 = operands[12]; 3455 rtx scratch4 = operands[13]; 3456 rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0); 3457 rtx scratch5 = operands[14]; 3458 rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0); 3459 rtx scratch6 = operands[15]; 3460 3461 emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32, 3462 scratch0, scratch1)); 3463 /* inv0 == scratch4 */ 3464 if (! TARGET_DIVIDE_INV20U) 3465 { 3466 emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4)); 3467 i2p27 = scratch0; 3468 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si)); 3469 } 3470 else 3471 { 3472 emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4)); 3473 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si)); 3474 } 3475 emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45))); 3476 emit_insn (gen_subdi3 (scratch1, scratch2, scratch1)); 3477 emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28))); 3478 /* inv1 == scratch4 */ 3479 3480 if (TARGET_DIVIDE_INV_MINLAT) 3481 { 3482 emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32)); 3483 emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4)); 3484 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16))); 3485 emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4)); 3486 emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63))); 3487 emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14))); 3488 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30))); 3489 emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5)); 3490 emit_insn (gen_xordi3 (scratch0, scratch3, i2p27)); 3491 emit_insn (gen_adddi3 (scratch2, scratch2, scratch0)); 3492 emit_insn (gen_subdi3 (scratch2, scratch2, scratch1)); 3493 } 3494 else 3495 { 3496 rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ()); 3497 /* Use separate scratch regs for nsb and sign to allow scheduling. */ 3498 emit_insn (gen_nsbdi (scratch6, 3499 simplify_gen_subreg (DImode, dividend, SImode, 0))); 3500 emit_insn (gen_xorsi3 (scratch5, dividend, norm32)); 3501 emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63))); 3502 emit_insn (gen_divsi_inv20 (scratch2, 3503 norm32, scratch4, dividend, 3504 scratch6, scratch3, i43, 3505 /* scratch0 may be shared with i2p27. */ 3506 scratch0, scratch1, scratch5, 3507 label, label, i2p27)); 3508 } 3509 emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift)); 3510 emit_insn (gen_subdisi3_media (result, scratch2, scratch3)); 3511 DONE; 3512}) 3513 3514(define_insn "divsi_inv20" 3515 [(set (match_operand:DI 0 "register_operand" "=&r") 3516 (unspec:DI [(match_operand:SI 1 "register_operand" "r") 3517 (match_operand:SI 2 "register_operand" "r") 3518 (match_operand:SI 3 "register_operand" "r") 3519 (match_operand:DI 4 "register_operand" "r") 3520 (match_operand:DI 5 "register_operand" "r") 3521 (match_operand:DI 6 "register_operand" "r") 3522 (match_operand:DI 12 "register_operand" "r") 3523 (match_operand 10 "target_operand" "b") 3524 (match_operand 11 "immediate_operand" "i")] 3525 UNSPEC_DIV_INV20)) 3526 (clobber (match_operand:DI 7 "register_operand" "=&r")) 3527 (clobber (match_operand:DI 8 "register_operand" "=&r")) 3528 (clobber (match_operand:SI 9 "register_operand" "=r"))] 3529 "TARGET_SHMEDIA 3530 && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)" 3531{ 3532/* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend, 3533 %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27, 3534 %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si) 3535 %10 label (tr), %11 label (imm) 3536 3537 muls.l inv1, norm32, scratch0 // s2.60 3538 muls.l inv1, dividend, result // s32.30 3539 xor i2p27, result_sign, round_scratch 3540 bge/u dividend_nsb, i43, tr.. (label) 3541 shari scratch0, 16, scratch0 // s-16.44 3542 muls.l sratch0_si, inv1, scratch0 // s-16.74 3543 sub result, round_scratch, result 3544 shari dividend, 14, scratch1 // s19.-14 3545 shari scratch0, 30, scratch0 // s-16.44 3546 muls.l scratch0, scratch1, round_scratch // s15.30 3547label: 3548 sub result, round_scratch, result */ 3549 3550 const bool likely = TARGET_DIVIDE_INV20L; 3551 if (likely) 3552 return 3553 "muls.l %2, %3, %0" "\n" 3554 " xor %12, %5, %7" "\n" 3555 " bge/l %4, %6, %10" "\n" 3556 " muls.l %2, %1, %8" "\n" 3557 " shari %8, 16, %8" "\n" 3558 " muls.l %8, %2, %8" "\n" 3559 " shari %3, 14, %9" "\n" 3560 " shari %8, 30, %8" "\n" 3561 " muls.l %8, %9, %8" "\n" 3562 " sub %0, %8, %0" "\n" 3563 "%11: add %0, %7, %0"; 3564 else 3565 return 3566 "muls.l %2, %1, %8" "\n" 3567 " muls.l %2, %3, %0" "\n" 3568 " xor %12, %5, %7" "\n" 3569 " bge/u %4, %6, %10" "\n" 3570 " shari %8, 16, %8" "\n" 3571 " muls.l %8, %2, %8" "\n" 3572 " sub %0, %7, %0" "\n" 3573 " shari %3, 14, %9" "\n" 3574 " shari %8, 30, %8" "\n" 3575 " muls.l %8, %9, %7" "\n" 3576 "%11: sub %0, %7, %0"; 3577}) 3578 3579(define_insn_and_split "divsi_inv_fp" 3580 [(set (match_operand:SI 0 "general_movdst_operand" "=rf") 3581 (div:SI (match_operand:SI 1 "general_movsrc_operand" "rf") 3582 (match_operand:SI 2 "register_operand" "rf"))) 3583 (use (match_operand:SI 3 "general_movsrc_operand" "r")) 3584 (clobber (match_operand:SI 4 "register_operand" "=r")) 3585 (clobber (match_operand:SI 5 "register_operand" "=r")) 3586 (clobber (match_operand:DF 6 "register_operand" "=r")) 3587 (clobber (match_operand:DF 7 "register_operand" "=r")) 3588 (clobber (match_operand:DF 8 "register_operand" "=r"))] 3589 "TARGET_SHMEDIA_FPU" 3590 "#" 3591 "&& (reload_in_progress || reload_completed)" 3592 [(set (match_dup 0) (match_dup 3))] 3593 "" 3594 [(set_attr "highpart" "must_split")]) 3595 3596;; If a matching group of divide-by-inverse instructions is in the same 3597;; basic block after gcse & loop optimizations, we want to transform them 3598;; to a straight division using floating point for TARGET_DIVIDE_INV_FP. 3599(define_insn_and_split "*divsi_inv_fp_combine" 3600 [(set (match_operand:SI 0 "register_operand" "=f") 3601 (div:SI (match_operand:SI 1 "register_operand" "f") 3602 (match_operand:SI 2 "register_operand" "f"))) 3603 (use (unspec:SI [(match_dup 1) 3604 (match_operand:SI 3 "" "") 3605 (unspec:SI [(match_operand:SI 4 "" "") 3606 (match_dup 3) 3607 (match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2) 3608 (match_operand:DI 6 "" "") 3609 (const_int 0) 3610 (const_int 0)] UNSPEC_DIV_INV_M3)) 3611 (clobber (match_operand:SI 7 "fp_arith_reg_operand" "")) 3612 (clobber (match_operand:SI 8 "fp_arith_reg_operand" "")) 3613 (clobber (match_operand:DF 9 "fp_arith_reg_operand" "")) 3614 (clobber (match_operand:DF 10 "fp_arith_reg_operand" "")) 3615 (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))] 3616 "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && !can_create_pseudo_p ()" 3617 "#" 3618 "&& 1" 3619 [(set (match_dup 9) (float:DF (match_dup 1))) 3620 (set (match_dup 10) (float:DF (match_dup 2))) 3621 (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10))) 3622 (set (match_dup 8) 3623 (fix:SI (match_dup 11))) 3624 (set (match_dup 0) (match_dup 8))] 3625{ 3626 if (! fp_arith_reg_operand (operands[1], SImode)) 3627 { 3628 emit_move_insn (operands[7], operands[1]); 3629 operands[1] = operands[7]; 3630 } 3631 if (! fp_arith_reg_operand (operands[2], SImode)) 3632 { 3633 emit_move_insn (operands[8], operands[2]); 3634 operands[2] = operands[8]; 3635 } 3636} 3637 [(set_attr "highpart" "must_split")]) 3638 3639;; ------------------------------------------------------------------------- 3640;; Multiplication instructions 3641;; ------------------------------------------------------------------------- 3642 3643(define_insn "umulhisi3_i" 3644 [(set (reg:SI MACL_REG) 3645 (mult:SI (zero_extend:SI 3646 (match_operand:HI 0 "arith_reg_operand" "r")) 3647 (zero_extend:SI 3648 (match_operand:HI 1 "arith_reg_operand" "r"))))] 3649 "TARGET_SH1" 3650 "mulu.w %1,%0" 3651 [(set_attr "type" "smpy")]) 3652 3653(define_insn "mulhisi3_i" 3654 [(set (reg:SI MACL_REG) 3655 (mult:SI (sign_extend:SI 3656 (match_operand:HI 0 "arith_reg_operand" "r")) 3657 (sign_extend:SI 3658 (match_operand:HI 1 "arith_reg_operand" "r"))))] 3659 "TARGET_SH1" 3660 "muls.w %1,%0" 3661 [(set_attr "type" "smpy")]) 3662 3663(define_expand "mulhisi3" 3664 [(set (reg:SI MACL_REG) 3665 (mult:SI (sign_extend:SI 3666 (match_operand:HI 1 "arith_reg_operand" "")) 3667 (sign_extend:SI 3668 (match_operand:HI 2 "arith_reg_operand" "")))) 3669 (set (match_operand:SI 0 "arith_reg_operand" "") 3670 (reg:SI MACL_REG))] 3671 "TARGET_SH1" 3672{ 3673 rtx_insn *insn; 3674 rtx macl; 3675 3676 macl = gen_rtx_REG (SImode, MACL_REG); 3677 start_sequence (); 3678 emit_insn (gen_mulhisi3_i (operands[1], operands[2])); 3679 insn = get_insns (); 3680 end_sequence (); 3681 /* expand_binop can't find a suitable code in umul_widen_optab to 3682 make a REG_EQUAL note from, so make one here. 3683 See also smulsi3_highpart. 3684 ??? Alternatively, we could put this at the calling site of expand_binop, 3685 i.e. expand_expr. */ 3686 /* Use emit_libcall_block for loop invariant code motion and to make 3687 a REG_EQUAL note. */ 3688 emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn))); 3689 3690 DONE; 3691}) 3692 3693(define_expand "umulhisi3" 3694 [(set (reg:SI MACL_REG) 3695 (mult:SI (zero_extend:SI 3696 (match_operand:HI 1 "arith_reg_operand" "")) 3697 (zero_extend:SI 3698 (match_operand:HI 2 "arith_reg_operand" "")))) 3699 (set (match_operand:SI 0 "arith_reg_operand" "") 3700 (reg:SI MACL_REG))] 3701 "TARGET_SH1" 3702{ 3703 rtx_insn *insn; 3704 rtx macl; 3705 3706 macl = gen_rtx_REG (SImode, MACL_REG); 3707 start_sequence (); 3708 emit_insn (gen_umulhisi3_i (operands[1], operands[2])); 3709 insn = get_insns (); 3710 end_sequence (); 3711 /* expand_binop can't find a suitable code in umul_widen_optab to 3712 make a REG_EQUAL note from, so make one here. 3713 See also smulsi3_highpart. 3714 ??? Alternatively, we could put this at the calling site of expand_binop, 3715 i.e. expand_expr. */ 3716 /* Use emit_libcall_block for loop invariant code motion and to make 3717 a REG_EQUAL note. */ 3718 emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn))); 3719 3720 DONE; 3721}) 3722 3723;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate 3724;; a call to a routine which clobbers known registers. 3725(define_insn "" 3726 [(set (match_operand:SI 1 "register_operand" "=z") 3727 (mult:SI (reg:SI R4_REG) (reg:SI R5_REG))) 3728 (clobber (reg:SI MACL_REG)) 3729 (clobber (reg:SI T_REG)) 3730 (clobber (reg:SI PR_REG)) 3731 (clobber (reg:SI R3_REG)) 3732 (clobber (reg:SI R2_REG)) 3733 (clobber (reg:SI R1_REG)) 3734 (use (match_operand:SI 0 "arith_reg_operand" "r"))] 3735 "TARGET_SH1" 3736 "jsr @%0%#" 3737 [(set_attr "type" "sfunc") 3738 (set_attr "needs_delay_slot" "yes")]) 3739 3740(define_expand "mulsi3_call" 3741 [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" "")) 3742 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" "")) 3743 (parallel[(set (match_operand:SI 0 "register_operand" "") 3744 (mult:SI (reg:SI R4_REG) 3745 (reg:SI R5_REG))) 3746 (clobber (reg:SI MACL_REG)) 3747 (clobber (reg:SI T_REG)) 3748 (clobber (reg:SI PR_REG)) 3749 (clobber (reg:SI R3_REG)) 3750 (clobber (reg:SI R2_REG)) 3751 (clobber (reg:SI R1_REG)) 3752 (use (match_operand:SI 3 "register_operand" ""))])] 3753 "TARGET_SH1" 3754 "") 3755 3756(define_insn "mul_r" 3757 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 3758 (mult:SI (match_operand:SI 1 "arith_reg_operand" "0") 3759 (match_operand:SI 2 "arith_reg_operand" "z")))] 3760 "TARGET_SH2A" 3761 "mulr %2,%0" 3762 [(set_attr "type" "dmpy")]) 3763 3764(define_insn "mul_l" 3765 [(set (reg:SI MACL_REG) 3766 (mult:SI (match_operand:SI 0 "arith_reg_operand" "r") 3767 (match_operand:SI 1 "arith_reg_operand" "r")))] 3768 "TARGET_SH2" 3769 "mul.l %1,%0" 3770 [(set_attr "type" "dmpy")]) 3771 3772(define_expand "mulsi3" 3773 [(set (reg:SI MACL_REG) 3774 (mult:SI (match_operand:SI 1 "arith_reg_operand" "") 3775 (match_operand:SI 2 "arith_reg_operand" ""))) 3776 (set (match_operand:SI 0 "arith_reg_operand" "") 3777 (reg:SI MACL_REG))] 3778 "TARGET_SH1" 3779{ 3780 if (!TARGET_SH2) 3781 { 3782 /* The address must be set outside the libcall, 3783 since it goes into a pseudo. */ 3784 rtx sym = function_symbol (NULL, "__mulsi3", SFUNC_STATIC).sym; 3785 rtx addr = force_reg (SImode, sym); 3786 rtx insns = gen_mulsi3_call (operands[0], operands[1], 3787 operands[2], addr); 3788 emit_insn (insns); 3789 } 3790 else 3791 { 3792 rtx macl = gen_rtx_REG (SImode, MACL_REG); 3793 3794 emit_insn (gen_mul_l (operands[1], operands[2])); 3795 /* consec_sets_giv can only recognize the first insn that sets a 3796 giv as the giv insn. So we must tag this also with a REG_EQUAL 3797 note. */ 3798 emit_insn (gen_movsi_i ((operands[0]), macl)); 3799 } 3800 DONE; 3801}) 3802 3803(define_insn "mulsidi3_i" 3804 [(set (reg:SI MACH_REG) 3805 (truncate:SI 3806 (lshiftrt:DI 3807 (mult:DI 3808 (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) 3809 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))) 3810 (const_int 32)))) 3811 (set (reg:SI MACL_REG) 3812 (mult:SI (match_dup 0) 3813 (match_dup 1)))] 3814 "TARGET_SH2" 3815 "dmuls.l %1,%0" 3816 [(set_attr "type" "dmpy")]) 3817 3818(define_expand "mulsidi3" 3819 [(set (match_operand:DI 0 "arith_reg_dest" "") 3820 (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) 3821 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))] 3822 "TARGET_SH2 || TARGET_SHMEDIA" 3823{ 3824 if (TARGET_SH2) 3825 { 3826 emit_insn (gen_mulsidi3_compact (operands[0], operands[1], operands[2])); 3827 DONE; 3828 } 3829}) 3830 3831(define_insn "mulsidi3_media" 3832 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 3833 (mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r")) 3834 (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))] 3835 "TARGET_SHMEDIA" 3836 "muls.l %1, %2, %0" 3837 [(set_attr "type" "dmpy_media") 3838 (set_attr "highpart" "ignore")]) 3839 3840(define_insn_and_split "mulsidi3_compact" 3841 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 3842 (mult:DI 3843 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")) 3844 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r")))) 3845 (clobber (reg:SI MACH_REG)) 3846 (clobber (reg:SI MACL_REG))] 3847 "TARGET_SH2" 3848 "#" 3849 "&& 1" 3850 [(const_int 0)] 3851{ 3852 rtx low_dst = gen_lowpart (SImode, operands[0]); 3853 rtx high_dst = gen_highpart (SImode, operands[0]); 3854 3855 emit_insn (gen_mulsidi3_i (operands[1], operands[2])); 3856 3857 emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG)); 3858 emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG)); 3859 /* We need something to tag the possible REG_EQUAL notes on to. */ 3860 emit_move_insn (operands[0], operands[0]); 3861 DONE; 3862}) 3863 3864(define_insn "umulsidi3_i" 3865 [(set (reg:SI MACH_REG) 3866 (truncate:SI 3867 (lshiftrt:DI 3868 (mult:DI 3869 (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) 3870 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))) 3871 (const_int 32)))) 3872 (set (reg:SI MACL_REG) 3873 (mult:SI (match_dup 0) 3874 (match_dup 1)))] 3875 "TARGET_SH2" 3876 "dmulu.l %1,%0" 3877 [(set_attr "type" "dmpy")]) 3878 3879(define_expand "umulsidi3" 3880 [(set (match_operand:DI 0 "arith_reg_dest" "") 3881 (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) 3882 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))] 3883 "TARGET_SH2 || TARGET_SHMEDIA" 3884{ 3885 if (TARGET_SH2) 3886 { 3887 emit_insn (gen_umulsidi3_compact (operands[0], operands[1], operands[2])); 3888 DONE; 3889 } 3890}) 3891 3892(define_insn "umulsidi3_media" 3893 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 3894 (mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r")) 3895 (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))] 3896 "TARGET_SHMEDIA" 3897 "mulu.l %1, %2, %0" 3898 [(set_attr "type" "dmpy_media") 3899 (set_attr "highpart" "ignore")]) 3900 3901(define_insn_and_split "umulsidi3_compact" 3902 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 3903 (mult:DI 3904 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")) 3905 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r")))) 3906 (clobber (reg:SI MACH_REG)) 3907 (clobber (reg:SI MACL_REG))] 3908 "TARGET_SH2" 3909 "#" 3910 "&& 1" 3911 [(const_int 0)] 3912{ 3913 rtx low_dst = gen_lowpart (SImode, operands[0]); 3914 rtx high_dst = gen_highpart (SImode, operands[0]); 3915 3916 emit_insn (gen_umulsidi3_i (operands[1], operands[2])); 3917 3918 emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG)); 3919 emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG)); 3920 /* We need something to tag the possible REG_EQUAL notes on to. */ 3921 emit_move_insn (operands[0], operands[0]); 3922 DONE; 3923}) 3924 3925(define_insn "smulsi3_highpart_i" 3926 [(set (reg:SI MACH_REG) 3927 (truncate:SI 3928 (lshiftrt:DI 3929 (mult:DI 3930 (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) 3931 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))) 3932 (const_int 32)))) 3933 (clobber (reg:SI MACL_REG))] 3934 "TARGET_SH2" 3935 "dmuls.l %1,%0" 3936 [(set_attr "type" "dmpy")]) 3937 3938(define_expand "smulsi3_highpart" 3939 [(parallel 3940 [(set (reg:SI MACH_REG) 3941 (truncate:SI 3942 (lshiftrt:DI 3943 (mult:DI 3944 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) 3945 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))) 3946 (const_int 32)))) 3947 (clobber (reg:SI MACL_REG))]) 3948 (set (match_operand:SI 0 "arith_reg_operand" "") 3949 (reg:SI MACH_REG))] 3950 "TARGET_SH2" 3951{ 3952 rtx_insn *insn; 3953 rtx mach; 3954 3955 mach = gen_rtx_REG (SImode, MACH_REG); 3956 start_sequence (); 3957 emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2])); 3958 insn = get_insns (); 3959 end_sequence (); 3960 /* expand_binop can't find a suitable code in mul_highpart_optab to 3961 make a REG_EQUAL note from, so make one here. 3962 See also {,u}mulhisi. 3963 ??? Alternatively, we could put this at the calling site of expand_binop, 3964 i.e. expand_mult_highpart. */ 3965 /* Use emit_libcall_block for loop invariant code motion and to make 3966 a REG_EQUAL note. */ 3967 emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn))); 3968 3969 DONE; 3970}) 3971 3972(define_insn "umulsi3_highpart_i" 3973 [(set (reg:SI MACH_REG) 3974 (truncate:SI 3975 (lshiftrt:DI 3976 (mult:DI 3977 (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) 3978 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))) 3979 (const_int 32)))) 3980 (clobber (reg:SI MACL_REG))] 3981 "TARGET_SH2" 3982 "dmulu.l %1,%0" 3983 [(set_attr "type" "dmpy")]) 3984 3985(define_expand "umulsi3_highpart" 3986 [(parallel 3987 [(set (reg:SI MACH_REG) 3988 (truncate:SI 3989 (lshiftrt:DI 3990 (mult:DI 3991 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) 3992 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))) 3993 (const_int 32)))) 3994 (clobber (reg:SI MACL_REG))]) 3995 (set (match_operand:SI 0 "arith_reg_operand" "") 3996 (reg:SI MACH_REG))] 3997 "TARGET_SH2" 3998{ 3999 rtx_insn *insn; 4000 rtx mach; 4001 4002 mach = gen_rtx_REG (SImode, MACH_REG); 4003 start_sequence (); 4004 emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2])); 4005 insn = get_insns (); 4006 end_sequence (); 4007 /* Use emit_libcall_block for loop invariant code motion and to make 4008 a REG_EQUAL note. */ 4009 emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn))); 4010 4011 DONE; 4012}) 4013 4014(define_insn_and_split "muldi3" 4015 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 4016 (mult:DI (match_operand:DI 1 "arith_reg_operand" "r") 4017 (match_operand:DI 2 "arith_reg_operand" "r"))) 4018 (clobber (match_scratch:DI 3 "=&r")) 4019 (clobber (match_scratch:DI 4 "=r"))] 4020 "TARGET_SHMEDIA" 4021 "#" 4022 "reload_completed" 4023 [(const_int 0)] 4024{ 4025 rtx op3_v2si, op2_v2si; 4026 4027 op3_v2si = operands[3]; 4028 if (GET_CODE (op3_v2si) == SIGN_EXTEND) 4029 { 4030 op3_v2si = XEXP (op3_v2si, 0); 4031 op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0); 4032 } 4033 op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0); 4034 op2_v2si = operands[2]; 4035 if (GET_CODE (op2_v2si) == SIGN_EXTEND) 4036 { 4037 op2_v2si = XEXP (op2_v2si, 0); 4038 op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0); 4039 } 4040 op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0); 4041 emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32))); 4042 emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si)); 4043 emit_insn (gen_umulsidi3_media (operands[4], 4044 sh_gen_truncate (SImode, operands[1], 0), 4045 sh_gen_truncate (SImode, operands[2], 0))); 4046 emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL))); 4047 emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32))); 4048 emit_insn (gen_adddi3 (operands[0], operands[3], operands[0])); 4049 emit_insn (gen_adddi3 (operands[0], operands[4], operands[0])); 4050 DONE; 4051}) 4052 4053;; ------------------------------------------------------------------------- 4054;; Logical operations 4055;; ------------------------------------------------------------------------- 4056 4057(define_expand "andsi3" 4058 [(set (match_operand:SI 0 "arith_reg_operand" "") 4059 (and:SI (match_operand:SI 1 "logical_reg_operand" "") 4060 (match_operand:SI 2 "logical_and_operand" "")))] 4061 "" 4062{ 4063 /* If it is possible to turn the and insn into a zero extension 4064 already, redundant zero extensions will be folded, which results 4065 in better code. 4066 Ideally the splitter of *andsi_compact would be enough, if redundant 4067 zero extensions were detected after the combine pass, which does not 4068 happen at the moment. */ 4069 if (TARGET_SH1) 4070 { 4071 if (satisfies_constraint_Jmb (operands[2])) 4072 { 4073 emit_insn (gen_zero_extendqisi2 (operands[0], 4074 gen_lowpart (QImode, operands[1]))); 4075 DONE; 4076 } 4077 else if (satisfies_constraint_Jmw (operands[2])) 4078 { 4079 emit_insn (gen_zero_extendhisi2 (operands[0], 4080 gen_lowpart (HImode, operands[1]))); 4081 DONE; 4082 } 4083 } 4084}) 4085 4086(define_insn_and_split "*andsi_compact" 4087 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,z,r") 4088 (and:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,0,0") 4089 (match_operand:SI 2 "logical_and_operand" "Jmb,Jmw,K08,r")))] 4090 "TARGET_SH1" 4091 "@ 4092 extu.b %1,%0 4093 extu.w %1,%0 4094 and %2,%0 4095 and %2,%0" 4096 "&& 1" 4097 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))] 4098{ 4099 if (satisfies_constraint_Jmb (operands[2])) 4100 operands[1] = gen_lowpart (QImode, operands[1]); 4101 else if (satisfies_constraint_Jmw (operands[2])) 4102 operands[1] = gen_lowpart (HImode, operands[1]); 4103 else 4104 FAIL; 4105} 4106 [(set_attr "type" "arith")]) 4107 4108(define_insn "*andsi3_media" 4109 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 4110 (and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r") 4111 (match_operand:SI 2 "logical_operand" "r,I10")))] 4112 "TARGET_SHMEDIA" 4113 "@ 4114 and %1, %2, %0 4115 andi %1, %2, %0" 4116 [(set_attr "type" "arith_media")]) 4117 4118(define_insn "*andsi3_bclr" 4119 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4120 (and:SI (match_operand:SI 1 "arith_reg_operand" "%0") 4121 (match_operand:SI 2 "const_int_operand" "Psz")))] 4122 "TARGET_SH2A && satisfies_constraint_Psz (operands[2])" 4123 "bclr %W2,%0" 4124 [(set_attr "type" "arith")]) 4125 4126(define_insn_and_split "anddi3" 4127 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r") 4128 (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r") 4129 (match_operand:DI 2 "and_operand" "r,I10,J16")))] 4130 "TARGET_SHMEDIA" 4131 "@ 4132 and %1, %2, %0 4133 andi %1, %2, %0 4134 #" 4135 "reload_completed 4136 && ! logical_operand (operands[2], DImode)" 4137 [(const_int 0)] 4138{ 4139 if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff) 4140 emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode))); 4141 else 4142 emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1])); 4143 DONE; 4144} 4145 [(set_attr "type" "arith_media")]) 4146 4147(define_insn "andcsi3" 4148 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4149 (and:SI (match_operand:SI 1 "arith_reg_operand" "r") 4150 (not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))] 4151 "TARGET_SHMEDIA" 4152 "andc %1,%2,%0" 4153 [(set_attr "type" "arith_media")]) 4154 4155(define_insn "andcdi3" 4156 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 4157 (and:DI (match_operand:DI 1 "arith_reg_operand" "r") 4158 (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))] 4159 "TARGET_SHMEDIA" 4160 "andc %1,%2,%0" 4161 [(set_attr "type" "arith_media")]) 4162 4163(define_expand "iorsi3" 4164 [(set (match_operand:SI 0 "arith_reg_operand" "") 4165 (ior:SI (match_operand:SI 1 "logical_reg_operand" "") 4166 (match_operand:SI 2 "logical_operand" "")))] 4167 "" 4168 "") 4169 4170(define_insn "*iorsi3_compact" 4171 [(set (match_operand:SI 0 "arith_reg_dest" "=r,z") 4172 (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") 4173 (match_operand:SI 2 "logical_operand" "r,K08")))] 4174 "TARGET_SH1 4175 && !(TARGET_SH2A && satisfies_constraint_Pso (operands[2]))" 4176 "or %2,%0" 4177 [(set_attr "type" "arith")]) 4178 4179(define_insn "*iorsi3_media" 4180 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 4181 (ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r") 4182 (match_operand:SI 2 "logical_operand" "r,I10")))] 4183 "TARGET_SHMEDIA" 4184 "@ 4185 or %1, %2, %0 4186 ori %1, %2, %0" 4187 [(set_attr "type" "arith_media")]) 4188 4189(define_insn "*iorsi3_bset" 4190 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4191 (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0") 4192 (match_operand:SI 2 "const_int_operand" "Pso")))] 4193 "TARGET_SH2A && satisfies_constraint_Pso (operands[2])" 4194 "bset %V2,%0" 4195 [(set_attr "type" "arith")]) 4196 4197(define_insn "iordi3" 4198 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") 4199 (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r") 4200 (match_operand:DI 2 "logical_operand" "r,I10")))] 4201 "TARGET_SHMEDIA" 4202 "@ 4203 or %1, %2, %0 4204 ori %1, %2, %0" 4205 [(set_attr "type" "arith_media")]) 4206 4207(define_insn_and_split "*logical_sidi3" 4208 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") 4209 (sign_extend:DI (match_operator:SI 3 "logical_operator" 4210 [(match_operand:SI 1 "arith_reg_operand" "%r,r") 4211 (match_operand:SI 2 "logical_operand" "r,I10")])))] 4212 "TARGET_SHMEDIA" 4213 "#" 4214 "&& reload_completed" 4215 [(set (match_dup 0) (match_dup 3))] 4216{ 4217 operands[3] 4218 = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode, 4219 simplify_gen_subreg (DImode, operands[1], SImode, 0), 4220 simplify_gen_subreg (DImode, operands[2], SImode, 0)); 4221}) 4222 4223(define_insn_and_split "*logical_sidisi3" 4224 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 4225 (truncate:SI (sign_extend:DI 4226 (match_operator:SI 3 "logical_operator" 4227 [(match_operand:SI 1 "arith_reg_operand" "%r,r") 4228 (match_operand:SI 2 "logical_operand" "r,I10")]))))] 4229 "TARGET_SHMEDIA" 4230 "#" 4231 "&& 1" 4232 [(set (match_dup 0) (match_dup 3))]) 4233 4234(define_insn_and_split "*logical_sidi3_2" 4235 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") 4236 (sign_extend:DI (truncate:SI (sign_extend:DI 4237 (match_operator:SI 3 "logical_operator" 4238 [(match_operand:SI 1 "arith_reg_operand" "%r,r") 4239 (match_operand:SI 2 "logical_operand" "r,I10")])))))] 4240 "TARGET_SHMEDIA" 4241 "#" 4242 "&& 1" 4243 [(set (match_dup 0) (sign_extend:DI (match_dup 3)))]) 4244 4245(define_expand "xorsi3" 4246 [(set (match_operand:SI 0 "arith_reg_operand" "") 4247 (xor:SI (match_operand:SI 1 "logical_reg_operand" "") 4248 (match_operand:SI 2 "xor_operand" "")))] 4249 "" 4250 "") 4251 4252(define_insn "*xorsi3_compact" 4253 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r") 4254 (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") 4255 (match_operand:SI 2 "logical_operand" "K08,r")))] 4256 "TARGET_SH1" 4257 "xor %2,%0" 4258 [(set_attr "type" "arith")]) 4259 4260;; The *logical_op_t pattern helps combine eliminating sign/zero extensions 4261;; of results where one of the inputs is a T bit store. Notice that this 4262;; pattern must not match during reload. If reload picks this pattern it 4263;; will be impossible to split it afterwards. 4264(define_insn_and_split "*logical_op_t" 4265 [(set (match_operand:SI 0 "arith_reg_dest") 4266 (match_operator:SI 3 "logical_operator" 4267 [(match_operand:SI 1 "arith_reg_operand") 4268 (match_operand:SI 2 "t_reg_operand")]))] 4269 "TARGET_SH1 && can_create_pseudo_p ()" 4270 "#" 4271 "&& 1" 4272 [(set (match_dup 4) (reg:SI T_REG)) 4273 (set (match_dup 0) (match_dup 3))] 4274{ 4275 operands[4] = gen_reg_rtx (SImode); 4276 operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode, 4277 operands[1], operands[4]); 4278}) 4279 4280(define_insn "*xorsi3_media" 4281 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 4282 (xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r") 4283 (match_operand:SI 2 "xor_operand" "r,I06")))] 4284 "TARGET_SHMEDIA" 4285 "@ 4286 xor %1, %2, %0 4287 xori %1, %2, %0" 4288 [(set_attr "type" "arith_media")]) 4289 4290(define_insn "xordi3" 4291 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") 4292 (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r") 4293 (match_operand:DI 2 "xor_operand" "r,I06")))] 4294 "TARGET_SHMEDIA" 4295 "@ 4296 xor %1, %2, %0 4297 xori %1, %2, %0" 4298 [(set_attr "type" "arith_media")]) 4299 4300;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate. 4301;; converts 2 * sign extend -> logical op into logical op -> sign extend 4302(define_split 4303 [(set (match_operand:DI 0 "arith_reg_dest" "") 4304 (sign_extend:DI (match_operator 4 "binary_logical_operator" 4305 [(match_operand 1 "any_register_operand" "") 4306 (match_operand 2 "any_register_operand" "")])))] 4307 "TARGET_SHMEDIA" 4308 [(set (match_dup 5) (match_dup 4)) 4309 (set (match_dup 0) (sign_extend:DI (match_dup 5)))] 4310{ 4311 machine_mode inmode = GET_MODE (operands[1]); 4312 int offset = 0; 4313 4314 if (GET_CODE (operands[0]) == SUBREG) 4315 { 4316 offset = SUBREG_BYTE (operands[0]); 4317 operands[0] = SUBREG_REG (operands[0]); 4318 } 4319 gcc_assert (REG_P (operands[0])); 4320 if (TARGET_BIG_ENDIAN) 4321 offset += 8 - GET_MODE_SIZE (inmode); 4322 operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset); 4323}) 4324 4325;; ------------------------------------------------------------------------- 4326;; Shifts and rotates 4327;; ------------------------------------------------------------------------- 4328 4329;; Let combine see that we can get the MSB and LSB into the T bit 4330;; via shll and shlr. This allows it to plug it into insns that can have 4331;; the T bit as an input (e.g. addc). 4332;; On SH2A use bld #0,Rn instead of shlr to avoid mutating the input. 4333(define_insn_and_split "*reg_lsb_t" 4334 [(set (reg:SI T_REG) 4335 (and:SI (match_operand:SI 0 "arith_reg_operand") 4336 (const_int 1)))] 4337 "TARGET_SH1 && can_create_pseudo_p ()" 4338 "#" 4339 "&& 1" 4340 [(const_int 0)] 4341{ 4342 emit_insn (TARGET_SH2A ? gen_bldsi_reg (operands[0], const0_rtx) 4343 : gen_shlr (gen_reg_rtx (SImode), operands[0])); 4344}) 4345 4346(define_insn_and_split "*reg_msb_t" 4347 [(set (reg:SI T_REG) 4348 (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand") 4349 (const_int 31)))] 4350 "TARGET_SH1 && can_create_pseudo_p ()" 4351 "#" 4352 "&& 1" 4353 [(const_int 0)] 4354{ 4355 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[0])); 4356}) 4357 4358(define_expand "rotldi3" 4359 [(set (match_operand:DI 0 "arith_reg_dest" "") 4360 (rotate:DI (match_operand:DI 1 "arith_reg_operand" "") 4361 (match_operand:HI 2 "mextr_bit_offset" "")))] 4362 "TARGET_SHMEDIA" 4363{ 4364 if (! mextr_bit_offset (operands[2], HImode)) 4365 FAIL; 4366}) 4367 4368(define_insn "rotldi3_mextr" 4369 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 4370 (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r") 4371 (match_operand:HI 2 "mextr_bit_offset" "i")))] 4372 "TARGET_SHMEDIA" 4373{ 4374 static char templ[16]; 4375 sprintf (templ, "mextr%d %%1,%%1,%%0", 4376 8 - (int) (INTVAL (operands[2]) >> 3)); 4377 return templ; 4378} 4379 [(set_attr "type" "arith_media")]) 4380 4381(define_expand "rotrdi3" 4382 [(set (match_operand:DI 0 "arith_reg_dest" "") 4383 (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "") 4384 (match_operand:HI 2 "mextr_bit_offset" "")))] 4385 "TARGET_SHMEDIA" 4386{ 4387 if (! mextr_bit_offset (operands[2], HImode)) 4388 FAIL; 4389}) 4390 4391(define_insn "rotrdi3_mextr" 4392 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 4393 (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r") 4394 (match_operand:HI 2 "mextr_bit_offset" "i")))] 4395 "TARGET_SHMEDIA" 4396{ 4397 static char templ[16]; 4398 sprintf (templ, "mextr%d %%1,%%1,%%0", (int) INTVAL (operands[2]) >> 3); 4399 return templ; 4400} 4401 [(set_attr "type" "arith_media")]) 4402 4403(define_split 4404 [(set (match_operand:DI 0 "arith_reg_dest" "") 4405 (ior:DI (zero_extend:DI (mem:QI (match_operand 1 4406 "ua_address_operand" ""))) 4407 (ashift:DI (match_operand:DI 2 "arith_reg_operand" "") 4408 (const_int 8)))) 4409 (clobber (match_operand:DI 3 "register_operand" ""))] 4410 "TARGET_SHMEDIA" 4411 [(match_dup 4) (match_dup 5)] 4412{ 4413 operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q) 4414 (operands[3], operands[1])); 4415 operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2], 4416 GEN_INT (56), GEN_INT (8)); 4417}) 4418 4419(define_expand "rotrsi3" 4420 [(set (match_operand:SI 0 "arith_reg_dest") 4421 (rotatert:SI (match_operand:SI 1 "arith_reg_operand") 4422 (match_operand:SI 2 "const_int_operand")))] 4423 "TARGET_SH1" 4424{ 4425 HOST_WIDE_INT ival = INTVAL (operands[2]); 4426 if (ival == 1) 4427 { 4428 emit_insn (gen_rotrsi3_1 (operands[0], operands[1])); 4429 DONE; 4430 } 4431 4432 FAIL; 4433}) 4434 4435(define_insn "rotrsi3_1" 4436 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4437 (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0") 4438 (const_int 1))) 4439 (set (reg:SI T_REG) 4440 (and:SI (match_dup 1) (const_int 1)))] 4441 "TARGET_SH1" 4442 "rotr %0" 4443 [(set_attr "type" "arith")]) 4444 4445;; A slimplified version of rotr for combine. 4446(define_insn "*rotrsi3_1" 4447 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4448 (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0") 4449 (const_int 1))) 4450 (clobber (reg:SI T_REG))] 4451 "TARGET_SH1" 4452 "rotr %0" 4453 [(set_attr "type" "arith")]) 4454 4455(define_insn "rotlsi3_1" 4456 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4457 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0") 4458 (const_int 1))) 4459 (set (reg:SI T_REG) 4460 (lshiftrt:SI (match_dup 1) (const_int 31)))] 4461 "TARGET_SH1" 4462 "rotl %0" 4463 [(set_attr "type" "arith")]) 4464 4465;; A simplified version of rotl for combine. 4466(define_insn "*rotlsi3_1" 4467 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4468 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0") 4469 (const_int 1))) 4470 (clobber (reg:SI T_REG))] 4471 "TARGET_SH1" 4472 "rotl %0" 4473 [(set_attr "type" "arith")]) 4474 4475(define_insn "rotlsi3_31" 4476 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4477 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0") 4478 (const_int 31))) 4479 (clobber (reg:SI T_REG))] 4480 "TARGET_SH1" 4481 "rotr %0" 4482 [(set_attr "type" "arith")]) 4483 4484(define_insn "rotlsi3_16" 4485 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4486 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r") 4487 (const_int 16)))] 4488 "TARGET_SH1" 4489 "swap.w %1,%0" 4490 [(set_attr "type" "arith")]) 4491 4492(define_expand "rotlsi3" 4493 [(set (match_operand:SI 0 "arith_reg_dest") 4494 (rotate:SI (match_operand:SI 1 "arith_reg_operand") 4495 (match_operand:SI 2 "const_int_operand")))] 4496 "TARGET_SH1" 4497{ 4498 static const char rot_tab[] = { 4499 000, 000, 000, 000, 000, 000, 010, 001, 4500 001, 001, 011, 013, 003, 003, 003, 003, 4501 003, 003, 003, 003, 003, 013, 012, 002, 4502 002, 002, 010, 000, 000, 000, 000, 000, 4503 }; 4504 4505 int count = INTVAL (operands[2]); 4506 int choice = rot_tab[count]; 4507 if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1) 4508 FAIL; 4509 choice &= 7; 4510 switch (choice) 4511 { 4512 case 0: 4513 emit_move_insn (operands[0], operands[1]); 4514 count -= (count & 16) * 2; 4515 break; 4516 case 3: 4517 emit_insn (gen_rotlsi3_16 (operands[0], operands[1])); 4518 count -= 16; 4519 break; 4520 case 1: 4521 case 2: 4522 { 4523 rtx parts[2]; 4524 parts[0] = gen_reg_rtx (SImode); 4525 parts[1] = gen_reg_rtx (SImode); 4526 emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1])); 4527 emit_move_insn (parts[choice-1], operands[1]); 4528 emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8))); 4529 emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8))); 4530 emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1])); 4531 count = (count & ~16) - 8; 4532 } 4533 } 4534 4535 for (; count > 0; count--) 4536 emit_insn (gen_rotlsi3_1 (operands[0], operands[0])); 4537 for (; count < 0; count++) 4538 emit_insn (gen_rotlsi3_31 (operands[0], operands[0])); 4539 4540 DONE; 4541}) 4542 4543(define_insn "rotlhi3_8" 4544 [(set (match_operand:HI 0 "arith_reg_dest" "=r") 4545 (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r") 4546 (const_int 8)))] 4547 "TARGET_SH1" 4548 "swap.b %1,%0" 4549 [(set_attr "type" "arith")]) 4550 4551(define_expand "rotlhi3" 4552 [(set (match_operand:HI 0 "arith_reg_operand") 4553 (rotate:HI (match_operand:HI 1 "arith_reg_operand") 4554 (match_operand:HI 2 "const_int_operand")))] 4555 "TARGET_SH1" 4556{ 4557 if (INTVAL (operands[2]) != 8) 4558 FAIL; 4559}) 4560 4561;; The rotcr and rotcl insns are used primarily in DImode shifts by one. 4562;; They can also be used to implement things like 4563;; bool t = a == b; 4564;; int x0 = (y >> 1) | (t << 31); // rotcr 4565;; int x1 = (y << 1) | t; // rotcl 4566(define_insn "rotcr" 4567 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4568 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 4569 (const_int 1)) 4570 (ashift:SI (match_operand:SI 2 "t_reg_operand") 4571 (const_int 31)))) 4572 (set (reg:SI T_REG) 4573 (and:SI (match_dup 1) (const_int 1)))] 4574 "TARGET_SH1" 4575 "rotcr %0" 4576 [(set_attr "type" "arith")]) 4577 4578(define_insn "rotcl" 4579 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4580 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") 4581 (const_int 1)) 4582 (match_operand:SI 2 "t_reg_operand"))) 4583 (set (reg:SI T_REG) 4584 (lshiftrt:SI (match_dup 1) (const_int 31)))] 4585 "TARGET_SH1" 4586 "rotcl %0" 4587 [(set_attr "type" "arith")]) 4588 4589;; Simplified rotcr version for combine, which allows arbitrary shift 4590;; amounts for the reg. If the shift amount is '1' rotcr can be used 4591;; directly. Otherwise we have to insert a shift in between. 4592(define_insn_and_split "*rotcr" 4593 [(set (match_operand:SI 0 "arith_reg_dest") 4594 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_or_0_operand") 4595 (match_operand:SI 2 "const_int_operand")) 4596 (ashift:SI (match_operand 3 "arith_reg_or_treg_set_expr") 4597 (const_int 31)))) 4598 (clobber (reg:SI T_REG))] 4599 "TARGET_SH1 && can_create_pseudo_p ()" 4600 "#" 4601 "&& 1" 4602 [(const_int 0)] 4603{ 4604 rtx prev_set_t_insn = NULL_RTX; 4605 4606 if (!arith_reg_operand (operands[3], SImode)) 4607 { 4608 sh_treg_insns ti = sh_split_treg_set_expr (operands[3], curr_insn); 4609 if (!ti.was_treg_operand ()) 4610 prev_set_t_insn = ti.first_insn (); 4611 4612 operands[3] = get_t_reg_rtx (); 4613 4614 if (TARGET_SH2A && ti.has_trailing_nott () && operands[1] == const0_rtx) 4615 { 4616 /* Convert to a movrt, rotr sequence. */ 4617 remove_insn (ti.trailing_nott ()); 4618 rtx tmp = gen_reg_rtx (SImode); 4619 emit_insn (gen_movnegt (tmp, get_t_reg_rtx ())); 4620 emit_insn (gen_rotrsi3_1 (operands[0], tmp)); 4621 DONE; 4622 } 4623 } 4624 4625 if (operands[1] == const0_rtx) 4626 { 4627 operands[1] = gen_reg_rtx (SImode); 4628 emit_insn (gen_movt (operands[1], get_t_reg_rtx ())); 4629 } 4630 4631 if (INTVAL (operands[2]) > 1) 4632 { 4633 const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1); 4634 rtx tmp_t_reg = NULL_RTX; 4635 4636 /* If we're going to emit a shift sequence that clobbers the T_REG, 4637 try to find the previous insn that sets the T_REG and emit the 4638 shift insn before that insn, to remove the T_REG dependency. 4639 If the insn that sets the T_REG cannot be found, store the T_REG 4640 in a temporary reg and restore it after the shift. */ 4641 if (sh_lshrsi_clobbers_t_reg_p (shift_count) 4642 && ! sh_dynamicalize_shift_p (shift_count)) 4643 { 4644 if (prev_set_t_insn == NULL) 4645 prev_set_t_insn = prev_nonnote_insn_bb (curr_insn); 4646 4647 /* Skip the nott insn, which was probably inserted by the splitter 4648 of *rotcr_neg_t. Don't use one of the recog functions 4649 here during insn splitting, since that causes problems in later 4650 passes. */ 4651 if (prev_set_t_insn != NULL_RTX) 4652 { 4653 rtx pat = PATTERN (prev_set_t_insn); 4654 if (GET_CODE (pat) == SET 4655 && t_reg_operand (XEXP (pat, 0), SImode) 4656 && negt_reg_operand (XEXP (pat, 1), SImode)) 4657 prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn); 4658 } 4659 4660 if (! (prev_set_t_insn != NULL_RTX 4661 && reg_set_p (get_t_reg_rtx (), prev_set_t_insn) 4662 && ! reg_referenced_p (get_t_reg_rtx (), 4663 PATTERN (prev_set_t_insn)))) 4664 { 4665 prev_set_t_insn = NULL_RTX; 4666 tmp_t_reg = gen_reg_rtx (SImode); 4667 emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ())); 4668 } 4669 } 4670 4671 rtx shift_result = gen_reg_rtx (SImode); 4672 rtx shift_insn = gen_lshrsi3 (shift_result, operands[1], shift_count); 4673 operands[1] = shift_result; 4674 4675 /* Emit the shift insn before the insn that sets T_REG, if possible. */ 4676 if (prev_set_t_insn != NULL_RTX) 4677 emit_insn_before (shift_insn, prev_set_t_insn); 4678 else 4679 emit_insn (shift_insn); 4680 4681 /* Restore T_REG if it has been saved before. */ 4682 if (tmp_t_reg != NULL_RTX) 4683 emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx)); 4684 } 4685 4686 /* For the rotcr insn to work, operands[3] must be in T_REG. 4687 If it is not we can get it there by shifting it right one bit. 4688 In this case T_REG is not an input for this insn, thus we don't have to 4689 pay attention as of where to insert the shlr insn. */ 4690 if (! t_reg_operand (operands[3], SImode)) 4691 { 4692 /* We don't care about the shifted result here, only the T_REG. */ 4693 emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3])); 4694 operands[3] = get_t_reg_rtx (); 4695 } 4696 4697 emit_insn (gen_rotcr (operands[0], operands[1], operands[3])); 4698 DONE; 4699}) 4700 4701;; If combine tries the same as above but with swapped operands, split 4702;; it so that it will try the pattern above. 4703(define_split 4704 [(set (match_operand:SI 0 "arith_reg_dest") 4705 (ior:SI (ashift:SI (match_operand 1 "arith_reg_or_treg_set_expr") 4706 (const_int 31)) 4707 (lshiftrt:SI (match_operand:SI 2 "arith_reg_or_0_operand") 4708 (match_operand:SI 3 "const_int_operand"))))] 4709 "TARGET_SH1 && can_create_pseudo_p ()" 4710 [(parallel [(set (match_dup 0) 4711 (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3)) 4712 (ashift:SI (match_dup 1) (const_int 31)))) 4713 (clobber (reg:SI T_REG))])]) 4714 4715;; Basically the same as the rotcr pattern above, but for rotcl. 4716;; FIXME: Fold copy pasted split code for rotcr and rotcl. 4717(define_insn_and_split "*rotcl" 4718 [(set (match_operand:SI 0 "arith_reg_dest") 4719 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand") 4720 (match_operand:SI 2 "const_int_operand")) 4721 (and:SI (match_operand:SI 3 "arith_reg_or_t_reg_operand") 4722 (const_int 1)))) 4723 (clobber (reg:SI T_REG))] 4724 "TARGET_SH1" 4725 "#" 4726 "&& can_create_pseudo_p ()" 4727 [(const_int 0)] 4728{ 4729 gcc_assert (INTVAL (operands[2]) > 0); 4730 4731 if (INTVAL (operands[2]) > 1) 4732 { 4733 const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1); 4734 rtx prev_set_t_insn = NULL_RTX; 4735 rtx tmp_t_reg = NULL_RTX; 4736 4737 /* If we're going to emit a shift sequence that clobbers the T_REG, 4738 try to find the previous insn that sets the T_REG and emit the 4739 shift insn before that insn, to remove the T_REG dependency. 4740 If the insn that sets the T_REG cannot be found, store the T_REG 4741 in a temporary reg and restore it after the shift. */ 4742 if (sh_ashlsi_clobbers_t_reg_p (shift_count) 4743 && ! sh_dynamicalize_shift_p (shift_count)) 4744 { 4745 prev_set_t_insn = prev_nonnote_insn_bb (curr_insn); 4746 4747 /* Skip the nott insn, which was probably inserted by the splitter 4748 of *rotcl_neg_t. Don't use one of the recog functions 4749 here during insn splitting, since that causes problems in later 4750 passes. */ 4751 if (prev_set_t_insn != NULL_RTX) 4752 { 4753 rtx pat = PATTERN (prev_set_t_insn); 4754 if (GET_CODE (pat) == SET 4755 && t_reg_operand (XEXP (pat, 0), SImode) 4756 && negt_reg_operand (XEXP (pat, 1), SImode)) 4757 prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn); 4758 } 4759 4760 if (! (prev_set_t_insn != NULL_RTX 4761 && reg_set_p (get_t_reg_rtx (), prev_set_t_insn) 4762 && ! reg_referenced_p (get_t_reg_rtx (), 4763 PATTERN (prev_set_t_insn)))) 4764 { 4765 prev_set_t_insn = NULL_RTX; 4766 tmp_t_reg = gen_reg_rtx (SImode); 4767 emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ())); 4768 } 4769 } 4770 4771 rtx shift_result = gen_reg_rtx (SImode); 4772 rtx shift_insn = gen_ashlsi3 (shift_result, operands[1], shift_count); 4773 operands[1] = shift_result; 4774 4775 /* Emit the shift insn before the insn that sets T_REG, if possible. */ 4776 if (prev_set_t_insn != NULL_RTX) 4777 emit_insn_before (shift_insn, prev_set_t_insn); 4778 else 4779 emit_insn (shift_insn); 4780 4781 /* Restore T_REG if it has been saved before. */ 4782 if (tmp_t_reg != NULL_RTX) 4783 emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx)); 4784 } 4785 4786 /* For the rotcl insn to work, operands[3] must be in T_REG. 4787 If it is not we can get it there by shifting it right one bit. 4788 In this case T_REG is not an input for this insn, thus we don't have to 4789 pay attention as of where to insert the shlr insn. */ 4790 if (! t_reg_operand (operands[3], SImode)) 4791 { 4792 /* We don't care about the shifted result here, only the T_REG. */ 4793 emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3])); 4794 operands[3] = get_t_reg_rtx (); 4795 } 4796 4797 emit_insn (gen_rotcl (operands[0], operands[1], operands[3])); 4798 DONE; 4799}) 4800 4801;; rotcl combine pattern variations 4802(define_insn_and_split "*rotcl" 4803 [(set (match_operand:SI 0 "arith_reg_dest") 4804 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand") 4805 (match_operand:SI 2 "const_int_operand")) 4806 (match_operand 3 "treg_set_expr"))) 4807 (clobber (reg:SI T_REG))] 4808 "TARGET_SH1" 4809 "#" 4810 "&& can_create_pseudo_p ()" 4811 [(parallel [(set (match_dup 0) 4812 (ior:SI (ashift:SI (match_dup 1) (match_dup 2)) 4813 (and:SI (match_dup 3) (const_int 1)))) 4814 (clobber (reg:SI T_REG))])] 4815{ 4816 sh_split_treg_set_expr (operands[3], curr_insn); 4817 operands[3] = get_t_reg_rtx (); 4818}) 4819 4820(define_insn_and_split "*rotcl" 4821 [(set (match_operand:SI 0 "arith_reg_dest") 4822 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_or_t_reg_operand") 4823 (const_int 1)) 4824 (ashift:SI (match_operand:SI 2 "arith_reg_operand") 4825 (match_operand:SI 3 "const_int_operand")))) 4826 (clobber (reg:SI T_REG))] 4827 "TARGET_SH1" 4828 "#" 4829 "&& can_create_pseudo_p ()" 4830 [(parallel [(set (match_dup 0) 4831 (ior:SI (ashift:SI (match_dup 2) (match_dup 3)) 4832 (and:SI (match_dup 1) (const_int 1)))) 4833 (clobber (reg:SI T_REG))])]) 4834 4835(define_insn_and_split "*rotcl" 4836 [(set (match_operand:SI 0 "arith_reg_dest") 4837 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand") 4838 (match_operand:SI 2 "const_int_operand")) 4839 (lshiftrt:SI (match_operand:SI 3 "arith_reg_operand") 4840 (const_int 31)))) 4841 (clobber (reg:SI T_REG))] 4842 "TARGET_SH1" 4843 "#" 4844 "&& can_create_pseudo_p ()" 4845 [(parallel [(set (match_dup 0) 4846 (ior:SI (ashift:SI (match_dup 1) (match_dup 2)) 4847 (and:SI (reg:SI T_REG) (const_int 1)))) 4848 (clobber (reg:SI T_REG))])] 4849{ 4850 /* We don't care about the result of the left shift, only the T_REG. */ 4851 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3])); 4852}) 4853 4854(define_insn_and_split "*rotcl" 4855 [(set (match_operand:SI 0 "arith_reg_dest") 4856 (ior:SI (lshiftrt:SI (match_operand:SI 3 "arith_reg_operand") 4857 (const_int 31)) 4858 (ashift:SI (match_operand:SI 1 "arith_reg_operand") 4859 (match_operand:SI 2 "const_int_operand")))) 4860 (clobber (reg:SI T_REG))] 4861 "TARGET_SH1" 4862 "#" 4863 "&& can_create_pseudo_p ()" 4864 [(parallel [(set (match_dup 0) 4865 (ior:SI (ashift:SI (match_dup 1) (match_dup 2)) 4866 (and:SI (reg:SI T_REG) (const_int 1)))) 4867 (clobber (reg:SI T_REG))])] 4868{ 4869 /* We don't care about the result of the left shift, only the T_REG. */ 4870 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3])); 4871}) 4872 4873(define_insn_and_split "*rotcl" 4874 [(set (match_operand:SI 0 "arith_reg_dest") 4875 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand") 4876 (match_operand 2 "const_int_operand")) 4877 (zero_extract:SI (match_operand:SI 3 "arith_reg_operand") 4878 (const_int 1) 4879 (match_operand 4 "const_int_operand")))) 4880 (clobber (reg:SI T_REG))] 4881 "TARGET_SH1" 4882 "#" 4883 "&& can_create_pseudo_p ()" 4884 [(parallel [(set (match_dup 0) 4885 (ior:SI (ashift:SI (match_dup 1) (match_dup 2)) 4886 (and:SI (match_dup 5) (const_int 1)))) 4887 (clobber (reg:SI T_REG))])] 4888{ 4889 if (TARGET_SH2A && satisfies_constraint_K03 (operands[4])) 4890 { 4891 /* On SH2A we can use the bld insn to zero extract a single bit 4892 into the T bit. */ 4893 operands[5] = get_t_reg_rtx (); 4894 emit_insn (gen_bldsi_reg (operands[3], operands[4])); 4895 } 4896 else 4897 { 4898 /* If we can't use the bld insn we have to emit a tst + nott sequence 4899 to get the extracted bit into the T bit. 4900 This will probably be worse than pre-shifting the operand. */ 4901 operands[5] = gen_reg_rtx (SImode); 4902 emit_insn (gen_lshrsi3 (operands[5], operands[3], operands[4])); 4903 } 4904}) 4905 4906;; rotcr combine bridge pattern which will make combine try out more 4907;; complex patterns. 4908(define_insn_and_split "*rotcr" 4909 [(set (match_operand:SI 0 "arith_reg_dest") 4910 (ashift:SI (match_operand 1 "treg_set_expr") (const_int 31)))] 4911 "TARGET_SH1 && can_create_pseudo_p ()" 4912 "#" 4913 "&& 1" 4914 [(parallel [(set (match_dup 0) 4915 (ior:SI (lshiftrt:SI (const_int 0) (const_int 1)) 4916 (ashift:SI (match_dup 1) (const_int 31)))) 4917 (clobber (reg:SI T_REG))])]) 4918 4919(define_insn_and_split "*rotcr" 4920 [(set (match_operand:SI 0 "arith_reg_dest") 4921 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand") 4922 (const_int -2147483648)) ;; 0xffffffff80000000 4923 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand") 4924 (const_int 1)))) 4925 (clobber (reg:SI T_REG))] 4926 "TARGET_SH1" 4927 "#" 4928 "&& can_create_pseudo_p ()" 4929 [(const_int 0)] 4930{ 4931 rtx tmp = gen_reg_rtx (SImode); 4932 emit_insn (gen_shll (tmp, operands[1])); 4933 emit_insn (gen_rotcr (operands[0], operands[2], get_t_reg_rtx ())); 4934 DONE; 4935}) 4936 4937;; rotcr combine patterns for rotating in the negated T_REG value. 4938(define_insn_and_split "*rotcr_neg_t" 4939 [(set (match_operand:SI 0 "arith_reg_dest") 4940 (ior:SI (match_operand:SI 1 "negt_reg_shl31_operand") 4941 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand") 4942 (match_operand:SI 3 "const_int_operand")))) 4943 (clobber (reg:SI T_REG))] 4944 "TARGET_SH1" 4945 "#" 4946 "&& can_create_pseudo_p ()" 4947 [(parallel [(set (match_dup 0) 4948 (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3)) 4949 (ashift:SI (reg:SI T_REG) (const_int 31)))) 4950 (clobber (reg:SI T_REG))])] 4951{ 4952 emit_insn (gen_nott (get_t_reg_rtx ())); 4953}) 4954 4955(define_insn_and_split "*rotcr_neg_t" 4956 [(set (match_operand:SI 0 "arith_reg_dest") 4957 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand") 4958 (match_operand:SI 2 "const_int_operand")) 4959 (match_operand:SI 3 "negt_reg_shl31_operand"))) 4960 (clobber (reg:SI T_REG))] 4961 "TARGET_SH1" 4962 "#" 4963 "&& can_create_pseudo_p ()" 4964 [(parallel [(set (match_dup 0) 4965 (ior:SI (lshiftrt:SI (match_dup 1) (match_dup 2)) 4966 (ashift:SI (reg:SI T_REG) (const_int 31)))) 4967 (clobber (reg:SI T_REG))])] 4968{ 4969 emit_insn (gen_nott (get_t_reg_rtx ())); 4970}) 4971 4972;; rotcl combine patterns for rotating in the negated T_REG value. 4973;; For some strange reason these have to be specified as splits which combine 4974;; will pick up. If they are specified as insn_and_split like the 4975;; *rotcr_neg_t patterns above, combine would recognize them successfully 4976;; but not emit them on non-SH2A targets. 4977(define_split 4978 [(set (match_operand:SI 0 "arith_reg_dest") 4979 (ior:SI (match_operand:SI 1 "negt_reg_operand") 4980 (ashift:SI (match_operand:SI 2 "arith_reg_operand") 4981 (match_operand:SI 3 "const_int_operand"))))] 4982 "TARGET_SH1" 4983 [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1))) 4984 (parallel [(set (match_dup 0) 4985 (ior:SI (ashift:SI (match_dup 2) (match_dup 3)) 4986 (and:SI (reg:SI T_REG) (const_int 1)))) 4987 (clobber (reg:SI T_REG))])]) 4988 4989(define_split 4990 [(set (match_operand:SI 0 "arith_reg_dest") 4991 (ior:SI (ashift:SI (match_operand:SI 2 "arith_reg_operand") 4992 (match_operand:SI 3 "const_int_operand")) 4993 (match_operand:SI 1 "negt_reg_operand")))] 4994 "TARGET_SH1" 4995 [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1))) 4996 (parallel [(set (match_dup 0) 4997 (ior:SI (ashift:SI (match_dup 2) (match_dup 3)) 4998 (and:SI (reg:SI T_REG) (const_int 1)))) 4999 (clobber (reg:SI T_REG))])]) 5000 5001;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5002;; SImode shift left 5003 5004(define_expand "ashlsi3" 5005 [(set (match_operand:SI 0 "arith_reg_operand" "") 5006 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "") 5007 (match_operand:SI 2 "shift_count_operand" "")))] 5008 "" 5009{ 5010 if (TARGET_SHMEDIA) 5011 { 5012 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) 5013 { 5014 operands[2] = GEN_INT (-INTVAL (operands[2])); 5015 emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2])); 5016 DONE; 5017 } 5018 emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2])); 5019 DONE; 5020 } 5021 if (TARGET_DYNSHIFT 5022 && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2])) 5023 { 5024 /* Don't force the constant into a reg yet. Some other optimizations 5025 might not see through the reg that holds the shift count. */ 5026 } 5027 5028 /* If the ashlsi3_* insn is going to clobber the T_REG it must be 5029 expanded here. */ 5030 if (CONST_INT_P (operands[2]) 5031 && sh_ashlsi_clobbers_t_reg_p (operands[2]) 5032 && ! sh_dynamicalize_shift_p (operands[2])) 5033 { 5034 emit_insn (gen_ashlsi3_n_clobbers_t (operands[0], operands[1], 5035 operands[2])); 5036 DONE; 5037 } 5038 5039 /* Expand a library call for the dynamic shift. */ 5040 if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT) 5041 { 5042 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]); 5043 rtx funcaddr = gen_reg_rtx (Pmode); 5044 rtx lab = function_symbol (funcaddr, "__ashlsi3_r0", SFUNC_STATIC).lab; 5045 emit_insn (gen_ashlsi3_d_call (operands[0], operands[2], funcaddr, lab)); 5046 5047 DONE; 5048 } 5049}) 5050 5051(define_insn "ashlsi3_k" 5052 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 5053 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0") 5054 (match_operand:SI 2 "p27_shift_count_operand" "M,P27")))] 5055 "TARGET_SH1" 5056 "@ 5057 add %0,%0 5058 shll%O2 %0" 5059 [(set_attr "type" "arith")]) 5060 5061(define_insn_and_split "ashlsi3_d" 5062 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5063 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") 5064 (match_operand:SI 2 "shift_count_operand" "r")))] 5065 "TARGET_DYNSHIFT" 5066 "shld %2,%0" 5067 "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2]) 5068 && ! sh_ashlsi_clobbers_t_reg_p (operands[2])" 5069 [(const_int 0)] 5070{ 5071 if (satisfies_constraint_P27 (operands[2])) 5072 { 5073 emit_insn (gen_ashlsi3_k (operands[0], operands[1], operands[2])); 5074 DONE; 5075 } 5076 else if (! satisfies_constraint_P27 (operands[2])) 5077 { 5078 /* This must happen before reload, otherwise the constant will be moved 5079 into a register due to the "r" constraint, after which this split 5080 cannot be done anymore. 5081 Unfortunately the move insn will not always be eliminated. 5082 Also, here we must not create a shift sequence that clobbers the 5083 T_REG. */ 5084 emit_move_insn (operands[0], operands[1]); 5085 gen_shifty_op (ASHIFT, operands); 5086 DONE; 5087 } 5088 5089 FAIL; 5090} 5091 [(set_attr "type" "dyn_shift")]) 5092 5093;; If dynamic shifts are not available use a library function. 5094;; By specifying the pattern we reduce the number of call clobbered regs. 5095;; In order to make combine understand the truncation of the shift amount 5096;; operand we have to allow it to use pseudo regs for the shift operands. 5097(define_insn "ashlsi3_d_call" 5098 [(set (match_operand:SI 0 "arith_reg_dest" "=z,z") 5099 (ashift:SI (reg:SI R4_REG) 5100 (and:SI (match_operand:SI 1 "arith_reg_operand" "z,z") 5101 (const_int 31)))) 5102 (use (match_operand:SI 2 "arith_reg_operand" "r,r")) 5103 (use (match_operand 3 "" "Z,Ccl")) 5104 (clobber (reg:SI T_REG)) 5105 (clobber (reg:SI PR_REG))] 5106 "TARGET_SH1 && !TARGET_DYNSHIFT" 5107 "@ 5108 jsr @%2%# 5109 bsrf %2\n%O3:%#" 5110 [(set_attr "type" "sfunc") 5111 (set_attr "needs_delay_slot" "yes")]) 5112 5113(define_insn_and_split "ashlsi3_n" 5114 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5115 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") 5116 (match_operand:SI 2 "not_p27_shift_count_operand" "")))] 5117 "TARGET_SH1 && ! sh_ashlsi_clobbers_t_reg_p (operands[2])" 5118 "#" 5119 "&& (reload_completed 5120 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))" 5121 [(const_int 0)] 5122{ 5123 if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()) 5124 { 5125 /* If this pattern was picked and dynamic shifts are supported, switch 5126 to dynamic shift pattern before reload. */ 5127 operands[2] = force_reg (SImode, operands[2]); 5128 emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2])); 5129 } 5130 else 5131 gen_shifty_op (ASHIFT, operands); 5132 5133 DONE; 5134}) 5135 5136(define_insn_and_split "ashlsi3_n_clobbers_t" 5137 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5138 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") 5139 (match_operand:SI 2 "not_p27_shift_count_operand" ""))) 5140 (clobber (reg:SI T_REG))] 5141 "TARGET_SH1 && sh_ashlsi_clobbers_t_reg_p (operands[2])" 5142 "#" 5143 "&& (reload_completed || INTVAL (operands[2]) == 31 5144 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))" 5145 [(const_int 0)] 5146{ 5147 if (INTVAL (operands[2]) == 31) 5148 { 5149 /* If the shift amount is 31 we split into a different sequence before 5150 reload so that it gets a chance to allocate R0 for the sequence. 5151 If it fails to do so (due to pressure on R0), it will take one insn 5152 more for the and. */ 5153 emit_insn (gen_andsi3 (operands[0], operands[1], const1_rtx)); 5154 emit_insn (gen_rotlsi3_31 (operands[0], operands[0])); 5155 } 5156 else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()) 5157 { 5158 /* If this pattern was picked and dynamic shifts are supported, switch 5159 to dynamic shift pattern before reload. */ 5160 operands[2] = force_reg (SImode, operands[2]); 5161 emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2])); 5162 } 5163 else 5164 gen_shifty_op (ASHIFT, operands); 5165 5166 DONE; 5167}) 5168 5169(define_insn "shll" 5170 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5171 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1))) 5172 (set (reg:SI T_REG) 5173 (lt:SI (match_dup 1) (const_int 0)))] 5174 "TARGET_SH1" 5175 "shll %0" 5176 [(set_attr "type" "arith")]) 5177 5178(define_insn "*ashlsi_c_void" 5179 [(set (reg:SI T_REG) 5180 (lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0))) 5181 (clobber (match_scratch:SI 1 "=0"))] 5182 "TARGET_SH1 && cse_not_expected" 5183 "shll %0" 5184 [(set_attr "type" "arith")]) 5185 5186(define_peephole2 5187 [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0)) 5188 (set (reg:SI T_REG) 5189 (gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))] 5190 "TARGET_SH1 5191 && peep2_reg_dead_p (2, operands[0]) 5192 && peep2_reg_dead_p (2, operands[1])" 5193 [(const_int 0)] 5194{ 5195 emit_insn (gen_shll (operands[1], operands[1])); 5196 DONE; 5197}) 5198 5199(define_insn "ashlsi3_media" 5200 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 5201 (ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r") 5202 (match_operand:SI 2 "shift_count_operand" "r,n")))] 5203 "TARGET_SHMEDIA" 5204 "@ 5205 shlld.l %1, %2, %0 5206 shlli.l %1, %2, %0" 5207 [(set_attr "type" "arith_media") 5208 (set_attr "highpart" "ignore")]) 5209 5210;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5211;; HImode shift left 5212 5213(define_expand "ashlhi3" 5214 [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "") 5215 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "") 5216 (match_operand:SI 2 "nonmemory_operand" ""))) 5217 (clobber (reg:SI T_REG))])] 5218 "TARGET_SH1" 5219{ 5220 if (!CONST_INT_P (operands[2])) 5221 FAIL; 5222 /* It may be possible to call gen_ashlhi3 directly with more generic 5223 operands. Make sure operands[1] is a HImode register here. */ 5224 if (!arith_reg_operand (operands[1], HImode)) 5225 operands[1] = copy_to_mode_reg (HImode, operands[1]); 5226}) 5227 5228(define_insn "ashlhi3_k" 5229 [(set (match_operand:HI 0 "arith_reg_dest" "=r,r") 5230 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0") 5231 (match_operand:HI 2 "const_int_operand" "M,P27")))] 5232 "TARGET_SH1 && satisfies_constraint_P27 (operands[2])" 5233 "@ 5234 add %0,%0 5235 shll%O2 %0" 5236 [(set_attr "type" "arith")]) 5237 5238(define_insn_and_split "*ashlhi3_n" 5239 [(set (match_operand:HI 0 "arith_reg_dest" "=r") 5240 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0") 5241 (match_operand:HI 2 "const_int_operand" "n"))) 5242 (clobber (reg:SI T_REG))] 5243 "TARGET_SH1" 5244 "#" 5245 "&& reload_completed" 5246 [(use (reg:SI R0_REG))] 5247{ 5248 gen_shifty_hi_op (ASHIFT, operands); 5249 DONE; 5250}) 5251 5252;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5253;; DImode shift left 5254 5255(define_expand "ashldi3" 5256 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "") 5257 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "") 5258 (match_operand:DI 2 "immediate_operand" ""))) 5259 (clobber (reg:SI T_REG))])] 5260 "" 5261{ 5262 if (TARGET_SHMEDIA) 5263 { 5264 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) 5265 { 5266 operands[2] = GEN_INT (-INTVAL (operands[2])); 5267 emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2])); 5268 DONE; 5269 } 5270 emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2])); 5271 DONE; 5272 } 5273 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1) 5274 { 5275 emit_insn (gen_ashldi3_k (operands[0], operands[1])); 5276 DONE; 5277 } 5278 else if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 32) 5279 { 5280 emit_insn (gen_ashldi3_std (operands[0], operands[1], operands[2])); 5281 DONE; 5282 } 5283 else 5284 FAIL; 5285}) 5286 5287;; Expander for DImode shift left with SImode operations. 5288(define_expand "ashldi3_std" 5289 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 5290 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r") 5291 (match_operand:DI 2 "const_int_operand" "n")))] 5292 "TARGET_SH1 && INTVAL (operands[2]) < 32" 5293{ 5294 rtx low_src = gen_lowpart (SImode, operands[1]); 5295 rtx high_src = gen_highpart (SImode, operands[1]); 5296 rtx dst = gen_reg_rtx (DImode); 5297 rtx low_dst = gen_lowpart (SImode, dst); 5298 rtx high_dst = gen_highpart (SImode, dst); 5299 rtx tmp0 = gen_reg_rtx (SImode); 5300 rtx tmp1 = gen_reg_rtx (SImode); 5301 5302 emit_insn (gen_lshrsi3 (tmp0, low_src, GEN_INT (32 - INTVAL (operands[2])))); 5303 emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2])); 5304 emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2])); 5305 emit_insn (gen_iorsi3 (high_dst, tmp0, tmp1)); 5306 emit_move_insn (operands[0], dst); 5307 DONE; 5308}) 5309 5310(define_insn_and_split "ashldi3_k" 5311 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 5312 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0") 5313 (const_int 1))) 5314 (clobber (reg:SI T_REG))] 5315 "TARGET_SH1" 5316 "#" 5317 "&& reload_completed" 5318 [(const_int 0)] 5319{ 5320 rtx high = gen_highpart (SImode, operands[0]); 5321 rtx low = gen_lowpart (SImode, operands[0]); 5322 emit_insn (gen_shll (low, low)); 5323 emit_insn (gen_rotcl (high, high, get_t_reg_rtx ())); 5324 DONE; 5325}) 5326 5327(define_insn "ashldi3_media" 5328 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") 5329 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r") 5330 (match_operand:DI 2 "shift_count_operand" "r,n")))] 5331 "TARGET_SHMEDIA" 5332 "@ 5333 shlld %1, %2, %0 5334 shlli %1, %2, %0" 5335 [(set_attr "type" "arith_media")]) 5336 5337(define_insn "*ashldisi3_media" 5338 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0) 5339 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r") 5340 (match_operand:DI 2 "const_int_operand" "n")))] 5341 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32" 5342 "shlli.l %1, %2, %0" 5343 [(set_attr "type" "arith_media") 5344 (set_attr "highpart" "ignore")]) 5345 5346;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5347;; SImode arithmetic shift right 5348;; 5349;; We can't do HImode right shifts correctly unless we start out with an 5350;; explicit zero / sign extension; doing that would result in worse overall 5351;; code, so just let the machine independent code widen the mode. 5352;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 . 5353 5354(define_expand "ashrsi3" 5355 [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "") 5356 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "") 5357 (match_operand:SI 2 "nonmemory_operand" ""))) 5358 (clobber (reg:SI T_REG))])] 5359 "" 5360{ 5361 if (TARGET_SHMEDIA) 5362 { 5363 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) 5364 { 5365 operands[2] = GEN_INT (-INTVAL (operands[2])); 5366 emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2])); 5367 DONE; 5368 } 5369 emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2])); 5370 DONE; 5371 } 5372 if (expand_ashiftrt (operands)) 5373 DONE; 5374 else 5375 FAIL; 5376}) 5377 5378(define_insn "shar" 5379 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5380 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 5381 (const_int 1))) 5382 (set (reg:SI T_REG) 5383 (and:SI (match_dup 1) (const_int 1)))] 5384 "TARGET_SH1" 5385 "shar %0" 5386 [(set_attr "type" "arith")]) 5387 5388(define_insn "ashrsi3_k" 5389 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5390 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 5391 (match_operand:SI 2 "const_int_operand" "M"))) 5392 (clobber (reg:SI T_REG))] 5393 "TARGET_SH1 && INTVAL (operands[2]) == 1" 5394 "shar %0" 5395 [(set_attr "type" "arith")]) 5396 5397(define_insn_and_split "ashrsi2_16" 5398 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5399 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r") 5400 (const_int 16)))] 5401 "TARGET_SH1" 5402 "#" 5403 "&& 1" 5404 [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16))) 5405 (set (match_dup 0) (sign_extend:SI (match_dup 2)))] 5406{ 5407 operands[2] = gen_lowpart (HImode, operands[0]); 5408}) 5409 5410(define_insn_and_split "ashrsi2_31" 5411 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5412 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 5413 (const_int 31))) 5414 (clobber (reg:SI T_REG))] 5415 "TARGET_SH1" 5416 "#" 5417 "&& 1" 5418 [(const_int 0)] 5419{ 5420 emit_insn (gen_shll (operands[0], operands[1])); 5421 emit_insn (gen_mov_neg_si_t (operands[0], get_t_reg_rtx ())); 5422 DONE; 5423}) 5424 5425;; If the shift amount is changed by combine it will try to plug the 5426;; use on the symbol of the library function and the PR clobber. 5427(define_insn_and_split "*ashrsi2_31" 5428 [(set (match_operand:SI 0 "arith_reg_dest") 5429 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand") 5430 (const_int 31))) 5431 (clobber (reg:SI T_REG)) 5432 (clobber (reg:SI PR_REG)) 5433 (use (match_operand:SI 2 "symbol_ref_operand"))] 5434 "TARGET_SH1" 5435 "#" 5436 "&& 1" 5437 [(parallel [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31))) 5438 (clobber (reg:SI T_REG))])]) 5439 5440(define_insn "ashrsi3_d" 5441 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5442 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 5443 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))] 5444 "TARGET_DYNSHIFT" 5445 "shad %2,%0" 5446 [(set_attr "type" "dyn_shift")]) 5447 5448(define_insn "ashrsi3_n" 5449 [(set (reg:SI R4_REG) 5450 (ashiftrt:SI (reg:SI R4_REG) 5451 (match_operand:SI 0 "const_int_operand" "i,i"))) 5452 (clobber (reg:SI T_REG)) 5453 (clobber (reg:SI PR_REG)) 5454 (use (match_operand:SI 1 "arith_reg_operand" "r,r")) 5455 (use (match_operand 2 "" "Z,Ccl"))] 5456 "TARGET_SH1" 5457 "@ 5458 jsr @%1%# 5459 bsrf %1\n%O2:%#" 5460 [(set_attr "type" "sfunc") 5461 (set_attr "needs_delay_slot" "yes")]) 5462 5463(define_insn "ashrsi3_media" 5464 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 5465 (ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r") 5466 (match_operand:SI 2 "shift_count_operand" "r,n")))] 5467 "TARGET_SHMEDIA" 5468 "@ 5469 shard.l %1, %2, %0 5470 shari.l %1, %2, %0" 5471 [(set_attr "type" "arith_media") 5472 (set_attr "highpart" "ignore")]) 5473 5474;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5475;; DImode arithmetic shift right 5476 5477(define_expand "ashrdi3" 5478 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "") 5479 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "") 5480 (match_operand:DI 2 "immediate_operand" ""))) 5481 (clobber (reg:SI T_REG))])] 5482 "" 5483{ 5484 if (TARGET_SHMEDIA) 5485 { 5486 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) 5487 { 5488 operands[2] = GEN_INT (-INTVAL (operands[2])); 5489 emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2])); 5490 DONE; 5491 } 5492 emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2])); 5493 DONE; 5494 } 5495 if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1) 5496 FAIL; 5497}) 5498 5499(define_insn_and_split "ashrdi3_k" 5500 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 5501 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0") 5502 (const_int 1))) 5503 (clobber (reg:SI T_REG))] 5504 "TARGET_SH1" 5505 "#" 5506 "&& reload_completed" 5507 [(const_int 0)] 5508{ 5509 rtx high = gen_highpart (SImode, operands[0]); 5510 rtx low = gen_lowpart (SImode, operands[0]); 5511 emit_insn (gen_shar (high, high)); 5512 emit_insn (gen_rotcr (low, low, get_t_reg_rtx ())); 5513 DONE; 5514}) 5515 5516(define_insn "ashrdi3_media" 5517 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r") 5518 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r") 5519 (match_operand:DI 2 "shift_count_operand" "r,n")))] 5520 "TARGET_SHMEDIA 5521 && (arith_reg_dest (operands[0], DImode) 5522 || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) >= 32))" 5523 "@ 5524 shard %1, %2, %0 5525 shari %1, %2, %0" 5526 [(set_attr "type" "arith_media")]) 5527 5528(define_insn "*ashrdisi3_media" 5529 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0) 5530 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r") 5531 (match_operand:DI 2 "const_int_operand" "n")))] 5532 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32" 5533 "shari.l %1, %2, %0" 5534 [(set_attr "type" "arith_media") 5535 (set_attr "highpart" "ignore")]) 5536 5537(define_insn "ashrdisi3_media_high" 5538 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5539 (truncate:SI 5540 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r") 5541 (match_operand:DI 2 "const_int_operand" "n"))))] 5542 "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32" 5543 "shari %1, %2, %0" 5544 [(set_attr "type" "arith_media")]) 5545 5546(define_insn "ashrdisi3_media_opaque" 5547 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5548 (unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r") 5549 (match_operand:DI 2 "const_int_operand" "n")] 5550 UNSPEC_ASHIFTRT))] 5551 "TARGET_SHMEDIA" 5552 "shari %1, %2, %0" 5553 [(set_attr "type" "arith_media")]) 5554 5555;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5556;; SImode logical shift right 5557 5558(define_expand "lshrsi3" 5559 [(set (match_operand:SI 0 "arith_reg_dest" "") 5560 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "") 5561 (match_operand:SI 2 "shift_count_operand" "")))] 5562 "" 5563{ 5564 if (TARGET_SHMEDIA) 5565 { 5566 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) 5567 { 5568 operands[2] = GEN_INT (-INTVAL (operands[2])); 5569 emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2])); 5570 DONE; 5571 } 5572 emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2])); 5573 DONE; 5574 } 5575 5576 /* If a dynamic shift is supposed to be used, expand the lshrsi3_d insn 5577 here, otherwise the pattern will never match due to the shift amount reg 5578 negation. */ 5579 if (TARGET_DYNSHIFT 5580 && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2])) 5581 { 5582 /* Don't force the constant into a reg yet. Some other optimizations 5583 might not see through the reg that holds the shift count. */ 5584 if (sh_lshrsi_clobbers_t_reg_p (operands[2])) 5585 emit_insn (gen_lshrsi3_n_clobbers_t (operands[0], operands[1], operands[2])); 5586 else 5587 emit_insn (gen_lshrsi3_n (operands[0], operands[1], operands[2])); 5588 DONE; 5589 } 5590 5591 if (TARGET_DYNSHIFT && ! CONST_INT_P (operands[2])) 5592 { 5593 rtx neg_count = gen_reg_rtx (SImode); 5594 emit_insn (gen_negsi2 (neg_count, operands[2])); 5595 emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count)); 5596 DONE; 5597 } 5598 5599 /* If the lshrsi3_* insn is going to clobber the T_REG it must be 5600 expanded here. */ 5601 if (CONST_INT_P (operands[2]) 5602 && sh_lshrsi_clobbers_t_reg_p (operands[2]) 5603 && ! sh_dynamicalize_shift_p (operands[2])) 5604 { 5605 emit_insn (gen_lshrsi3_n_clobbers_t (operands[0], operands[1], 5606 operands[2])); 5607 DONE; 5608 } 5609 5610 /* Expand a library call for the dynamic shift. */ 5611 if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT) 5612 { 5613 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]); 5614 rtx funcaddr = gen_reg_rtx (Pmode); 5615 rtx lab = function_symbol (funcaddr, "__lshrsi3_r0", SFUNC_STATIC).lab; 5616 emit_insn (gen_lshrsi3_d_call (operands[0], operands[2], funcaddr, lab)); 5617 DONE; 5618 } 5619}) 5620 5621(define_insn "lshrsi3_k" 5622 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5623 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 5624 (match_operand:SI 2 "p27_rshift_count_operand" "P27")))] 5625 "TARGET_SH1" 5626 "shlr%O2 %0" 5627 [(set_attr "type" "arith")]) 5628 5629(define_insn_and_split "lshrsi3_d" 5630 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5631 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 5632 (neg:SI (match_operand:SI 2 "shift_count_operand" "r"))))] 5633 "TARGET_DYNSHIFT" 5634 "shld %2,%0" 5635 "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2]) 5636 && ! sh_lshrsi_clobbers_t_reg_p (operands[2])" 5637 [(const_int 0)] 5638{ 5639 /* The shift count const_int is a negative value for all dynamic 5640 right shift insns. */ 5641 operands[2] = GEN_INT (- INTVAL (operands[2])); 5642 5643 if (satisfies_constraint_P27 (operands[2])) 5644 { 5645 /* This will not be done for a shift amount of 1, because it would 5646 clobber the T_REG. */ 5647 emit_insn (gen_lshrsi3_k (operands[0], operands[1], operands[2])); 5648 DONE; 5649 } 5650 else if (! satisfies_constraint_P27 (operands[2])) 5651 { 5652 /* This must happen before reload, otherwise the constant will be moved 5653 into a register due to the "r" constraint, after which this split 5654 cannot be done anymore. 5655 Unfortunately the move insn will not always be eliminated. 5656 Also, here we must not create a shift sequence that clobbers the 5657 T_REG. */ 5658 emit_move_insn (operands[0], operands[1]); 5659 gen_shifty_op (LSHIFTRT, operands); 5660 DONE; 5661 } 5662 5663 FAIL; 5664} 5665 [(set_attr "type" "dyn_shift")]) 5666 5667;; If dynamic shifts are not available use a library function. 5668;; By specifying the pattern we reduce the number of call clobbered regs. 5669;; In order to make combine understand the truncation of the shift amount 5670;; operand we have to allow it to use pseudo regs for the shift operands. 5671(define_insn "lshrsi3_d_call" 5672 [(set (match_operand:SI 0 "arith_reg_dest" "=z,z") 5673 (lshiftrt:SI (reg:SI R4_REG) 5674 (and:SI (match_operand:SI 1 "arith_reg_operand" "z,z") 5675 (const_int 31)))) 5676 (use (match_operand:SI 2 "arith_reg_operand" "r,r")) 5677 (use (match_operand 3 "" "Z,Ccl")) 5678 (clobber (reg:SI T_REG)) 5679 (clobber (reg:SI PR_REG))] 5680 "TARGET_SH1 && !TARGET_DYNSHIFT" 5681 "@ 5682 jsr @%2%# 5683 bsrf %2\n%O3:%#" 5684 [(set_attr "type" "sfunc") 5685 (set_attr "needs_delay_slot" "yes")]) 5686 5687(define_insn_and_split "lshrsi3_n" 5688 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5689 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 5690 (match_operand:SI 2 "not_p27_rshift_count_operand")))] 5691 "TARGET_SH1 && ! sh_lshrsi_clobbers_t_reg_p (operands[2])" 5692 "#" 5693 "&& (reload_completed 5694 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))" 5695 [(const_int 0)] 5696{ 5697 if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()) 5698 { 5699 /* If this pattern was picked and dynamic shifts are supported, switch 5700 to dynamic shift pattern before reload. */ 5701 operands[2] = GEN_INT (- INTVAL (operands[2])); 5702 emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2])); 5703 } 5704 else 5705 gen_shifty_op (LSHIFTRT, operands); 5706 5707 DONE; 5708}) 5709 5710;; The lshrsi3_n_clobbers_t pattern also works as a simplified version of 5711;; the shlr pattern. 5712(define_insn_and_split "lshrsi3_n_clobbers_t" 5713 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5714 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 5715 (match_operand:SI 2 "not_p27_rshift_count_operand"))) 5716 (clobber (reg:SI T_REG))] 5717 "TARGET_SH1 && sh_lshrsi_clobbers_t_reg_p (operands[2])" 5718 "#" 5719 "&& (reload_completed || INTVAL (operands[2]) == 31 5720 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))" 5721 [(const_int 0)] 5722{ 5723 if (INTVAL (operands[2]) == 31) 5724 { 5725 emit_insn (gen_shll (operands[0], operands[1])); 5726 emit_insn (gen_movt (operands[0], get_t_reg_rtx ())); 5727 } 5728 else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()) 5729 { 5730 /* If this pattern was picked and dynamic shifts are supported, switch 5731 to dynamic shift pattern before reload. */ 5732 operands[2] = GEN_INT (- INTVAL (operands[2])); 5733 emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2])); 5734 } 5735 else 5736 gen_shifty_op (LSHIFTRT, operands); 5737 5738 DONE; 5739}) 5740 5741(define_insn "shlr" 5742 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5743 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 5744 (const_int 1))) 5745 (set (reg:SI T_REG) 5746 (and:SI (match_dup 1) (const_int 1)))] 5747 "TARGET_SH1" 5748 "shlr %0" 5749 [(set_attr "type" "arith")]) 5750 5751(define_insn "lshrsi3_media" 5752 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 5753 (lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r") 5754 (match_operand:SI 2 "shift_count_operand" "r,n")))] 5755 "TARGET_SHMEDIA" 5756 "@ 5757 shlrd.l %1, %2, %0 5758 shlri.l %1, %2, %0" 5759 [(set_attr "type" "arith_media") 5760 (set_attr "highpart" "ignore")]) 5761 5762;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5763;; DImode logical shift right 5764 5765(define_expand "lshrdi3" 5766 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "") 5767 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "") 5768 (match_operand:DI 2 "immediate_operand" ""))) 5769 (clobber (reg:SI T_REG))])] 5770 "" 5771{ 5772 if (TARGET_SHMEDIA) 5773 { 5774 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) 5775 { 5776 operands[2] = GEN_INT (-INTVAL (operands[2])); 5777 emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2])); 5778 DONE; 5779 } 5780 emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2])); 5781 DONE; 5782 } 5783 if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1) 5784 FAIL; 5785}) 5786 5787(define_insn_and_split "lshrdi3_k" 5788 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 5789 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0") 5790 (const_int 1))) 5791 (clobber (reg:SI T_REG))] 5792 "TARGET_SH1" 5793 "#" 5794 "&& reload_completed" 5795 [(const_int 0)] 5796{ 5797 rtx high = gen_highpart (SImode, operands[0]); 5798 rtx low = gen_lowpart (SImode, operands[0]); 5799 emit_insn (gen_shlr (high, high)); 5800 emit_insn (gen_rotcr (low, low, get_t_reg_rtx ())); 5801 DONE; 5802}) 5803 5804(define_insn "lshrdi3_media" 5805 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r") 5806 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r") 5807 (match_operand:DI 2 "shift_count_operand" "r,n")))] 5808 "TARGET_SHMEDIA 5809 && (arith_reg_dest (operands[0], DImode) 5810 || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) > 32))" 5811 "@ 5812 shlrd %1, %2, %0 5813 shlri %1, %2, %0" 5814 [(set_attr "type" "arith_media")]) 5815 5816(define_insn "*lshrdisi3_media" 5817 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0) 5818 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r") 5819 (match_operand:DI 2 "const_int_operand" "n")))] 5820 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32" 5821 "shlri.l %1, %2, %0" 5822 [(set_attr "type" "arith_media") 5823 (set_attr "highpart" "ignore")]) 5824 5825;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5826;; Combined left/right shifts 5827 5828(define_split 5829 [(set (match_operand:SI 0 "register_operand" "") 5830 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "") 5831 (match_operand:SI 2 "const_int_operand" "")) 5832 (match_operand:SI 3 "const_int_operand" "")))] 5833 "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32" 5834 [(use (reg:SI R0_REG))] 5835{ 5836 if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) 5837 FAIL; 5838 DONE; 5839}) 5840 5841(define_split 5842 [(set (match_operand:SI 0 "register_operand" "") 5843 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "") 5844 (match_operand:SI 2 "const_int_operand" "")) 5845 (match_operand:SI 3 "const_int_operand" ""))) 5846 (clobber (reg:SI T_REG))] 5847 "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32" 5848 [(use (reg:SI R0_REG))] 5849{ 5850 if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) 5851 FAIL; 5852 DONE; 5853}) 5854 5855(define_insn "" 5856 [(set (match_operand:SI 0 "register_operand" "=r") 5857 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0") 5858 (match_operand:SI 2 "const_int_operand" "n")) 5859 (match_operand:SI 3 "const_int_operand" "n"))) 5860 (clobber (reg:SI T_REG))] 5861 "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1" 5862 "#" 5863 [(set (attr "length") 5864 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2)) 5865 (const_string "4") 5866 (eq (symbol_ref "shl_and_length (insn)") (const_int 3)) 5867 (const_string "6") 5868 (eq (symbol_ref "shl_and_length (insn)") (const_int 4)) 5869 (const_string "8") 5870 (eq (symbol_ref "shl_and_length (insn)") (const_int 5)) 5871 (const_string "10") 5872 (eq (symbol_ref "shl_and_length (insn)") (const_int 6)) 5873 (const_string "12") 5874 (eq (symbol_ref "shl_and_length (insn)") (const_int 7)) 5875 (const_string "14") 5876 (eq (symbol_ref "shl_and_length (insn)") (const_int 8)) 5877 (const_string "16")] 5878 (const_string "18"))) 5879 (set_attr "type" "arith")]) 5880 5881(define_insn "" 5882 [(set (match_operand:SI 0 "register_operand" "=z") 5883 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0") 5884 (match_operand:SI 2 "const_int_operand" "n")) 5885 (match_operand:SI 3 "const_int_operand" "n"))) 5886 (clobber (reg:SI T_REG))] 5887 "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2" 5888 "#" 5889 [(set (attr "length") 5890 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2)) 5891 (const_string "4") 5892 (eq (symbol_ref "shl_and_length (insn)") (const_int 3)) 5893 (const_string "6") 5894 (eq (symbol_ref "shl_and_length (insn)") (const_int 4)) 5895 (const_string "8")] 5896 (const_string "10"))) 5897 (set_attr "type" "arith")]) 5898 5899;; shift left / and combination with a scratch register: The combine pass 5900;; does not accept the individual instructions, even though they are 5901;; cheap. But it needs a precise description so that it is usable after 5902;; reload. 5903(define_insn "and_shl_scratch" 5904 [(set (match_operand:SI 0 "register_operand" "=r,&r") 5905 (lshiftrt:SI 5906 (ashift:SI 5907 (and:SI 5908 (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0") 5909 (match_operand:SI 2 "const_int_operand" "N,n")) 5910 (match_operand:SI 3 "" "0,r")) 5911 (match_operand:SI 4 "const_int_operand" "n,n")) 5912 (match_operand:SI 5 "const_int_operand" "n,n"))) 5913 (clobber (reg:SI T_REG))] 5914 "TARGET_SH1" 5915 "#" 5916 [(set (attr "length") 5917 (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2)) 5918 (const_string "4") 5919 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3)) 5920 (const_string "6") 5921 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4)) 5922 (const_string "8") 5923 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5)) 5924 (const_string "10")] 5925 (const_string "12"))) 5926 (set_attr "type" "arith")]) 5927 5928(define_split 5929 [(set (match_operand:SI 0 "register_operand" "") 5930 (lshiftrt:SI 5931 (ashift:SI 5932 (and:SI 5933 (lshiftrt:SI (match_operand:SI 1 "register_operand" "") 5934 (match_operand:SI 2 "const_int_operand" "")) 5935 (match_operand:SI 3 "register_operand" "")) 5936 (match_operand:SI 4 "const_int_operand" "")) 5937 (match_operand:SI 5 "const_int_operand" ""))) 5938 (clobber (reg:SI T_REG))] 5939 "TARGET_SH1" 5940 [(use (reg:SI R0_REG))] 5941{ 5942 rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1]; 5943 5944 if (INTVAL (operands[2])) 5945 { 5946 gen_shifty_op (LSHIFTRT, operands); 5947 } 5948 emit_insn (gen_andsi3 (operands[0], operands[0], and_source)); 5949 operands[2] = operands[4]; 5950 gen_shifty_op (ASHIFT, operands); 5951 if (INTVAL (operands[5])) 5952 { 5953 operands[2] = operands[5]; 5954 gen_shifty_op (LSHIFTRT, operands); 5955 } 5956 DONE; 5957}) 5958 5959;; signed left/right shift combination. 5960(define_split 5961 [(set (match_operand:SI 0 "register_operand" "") 5962 (sign_extract:SI 5963 (ashift:SI (match_operand:SI 1 "register_operand" "") 5964 (match_operand:SI 2 "const_int_operand" "")) 5965 (match_operand:SI 3 "const_int_operand" "") 5966 (const_int 0))) 5967 (clobber (reg:SI T_REG))] 5968 "TARGET_SH1" 5969 [(use (reg:SI R0_REG))] 5970{ 5971 if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1])) 5972 FAIL; 5973 DONE; 5974}) 5975 5976(define_insn "shl_sext_ext" 5977 [(set (match_operand:SI 0 "register_operand" "=r") 5978 (sign_extract:SI 5979 (ashift:SI (match_operand:SI 1 "register_operand" "0") 5980 (match_operand:SI 2 "const_int_operand" "n")) 5981 (match_operand:SI 3 "const_int_operand" "n") 5982 (const_int 0))) 5983 (clobber (reg:SI T_REG))] 5984 "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5" 5985 "#" 5986 [(set (attr "length") 5987 (cond [(match_test "shl_sext_length (insn)") 5988 (const_string "2") 5989 (eq (symbol_ref "shl_sext_length (insn)") (const_int 2)) 5990 (const_string "4") 5991 (eq (symbol_ref "shl_sext_length (insn)") (const_int 3)) 5992 (const_string "6") 5993 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4)) 5994 (const_string "8") 5995 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5)) 5996 (const_string "10") 5997 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6)) 5998 (const_string "12") 5999 (eq (symbol_ref "shl_sext_length (insn)") (const_int 7)) 6000 (const_string "14") 6001 (eq (symbol_ref "shl_sext_length (insn)") (const_int 8)) 6002 (const_string "16")] 6003 (const_string "18"))) 6004 (set_attr "type" "arith")]) 6005 6006(define_insn "shl_sext_sub" 6007 [(set (match_operand:SI 0 "register_operand" "=z") 6008 (sign_extract:SI 6009 (ashift:SI (match_operand:SI 1 "register_operand" "0") 6010 (match_operand:SI 2 "const_int_operand" "n")) 6011 (match_operand:SI 3 "const_int_operand" "n") 6012 (const_int 0))) 6013 (clobber (reg:SI T_REG))] 6014 "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6" 6015 "#" 6016 [(set (attr "length") 6017 (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3)) 6018 (const_string "6") 6019 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4)) 6020 (const_string "8") 6021 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5)) 6022 (const_string "10") 6023 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6)) 6024 (const_string "12")] 6025 (const_string "14"))) 6026 (set_attr "type" "arith")]) 6027 6028;; The xtrct_left and xtrct_right patterns are used in expansions of DImode 6029;; shifts by 16, and allow the xtrct instruction to be generated from C 6030;; source. 6031(define_insn "xtrct_left" 6032 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6033 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r") 6034 (const_int 16)) 6035 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0") 6036 (const_int 16))))] 6037 "TARGET_SH1" 6038 "xtrct %1,%0" 6039 [(set_attr "type" "arith")]) 6040 6041(define_insn "xtrct_right" 6042 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6043 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 6044 (const_int 16)) 6045 (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r") 6046 (const_int 16))))] 6047 "TARGET_SH1" 6048 "xtrct %2,%0" 6049 [(set_attr "type" "arith")]) 6050 6051;; ------------------------------------------------------------------------- 6052;; Unary arithmetic 6053;; ------------------------------------------------------------------------- 6054 6055(define_insn "negc" 6056 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6057 (neg:SI (plus:SI (reg:SI T_REG) 6058 (match_operand:SI 1 "arith_reg_operand" "r")))) 6059 (set (reg:SI T_REG) 6060 (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1)) 6061 (const_int 0)))] 6062 "TARGET_SH1" 6063 "negc %1,%0" 6064 [(set_attr "type" "arith")]) 6065 6066;; A simplified version of the negc insn, where the exact value of the 6067;; T bit doesn't matter. This is easier for combine to pick up. 6068;; Notice that '0 - x - 1' is the same as '~x', thus we don't specify 6069;; extra patterns for this case. 6070(define_insn_and_split "*negc" 6071 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6072 (minus:SI (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")) 6073 (match_operand 2 "treg_set_expr"))) 6074 (clobber (reg:SI T_REG))] 6075 "TARGET_SH1 && can_create_pseudo_p ()" 6076 "#" 6077 "&& 1" 6078 [(const_int 0)] 6079{ 6080 sh_split_treg_set_expr (operands[2], curr_insn); 6081 emit_insn (gen_negc (operands[0], operands[1])); 6082 DONE; 6083}); 6084 6085(define_insn "*negdi_media" 6086 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 6087 (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))] 6088 "TARGET_SHMEDIA" 6089 "sub r63, %1, %0" 6090 [(set_attr "type" "arith_media")]) 6091 6092;; Don't split into individual negc insns immediately so that neg:DI (abs:DI) 6093;; can be combined. 6094(define_expand "negdi2" 6095 [(parallel [(set (match_operand:DI 0 "arith_reg_dest") 6096 (neg:DI (match_operand:DI 1 "arith_reg_operand"))) 6097 (clobber (reg:SI T_REG))])] 6098 "TARGET_SH1") 6099 6100(define_insn_and_split "*negdi2" 6101 [(set (match_operand:DI 0 "arith_reg_dest") 6102 (neg:DI (match_operand:DI 1 "arith_reg_operand"))) 6103 (clobber (reg:SI T_REG))] 6104 "TARGET_SH1" 6105 "#" 6106 "&& can_create_pseudo_p ()" 6107 [(const_int 0)] 6108{ 6109 emit_insn (gen_clrt ()); 6110 emit_insn (gen_negc (gen_lowpart (SImode, operands[0]), 6111 gen_lowpart (SImode, operands[1]))); 6112 emit_insn (gen_negc (gen_highpart (SImode, operands[0]), 6113 gen_highpart (SImode, operands[1]))); 6114 DONE; 6115}) 6116 6117(define_insn "negsi2" 6118 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6119 (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))] 6120 "TARGET_SH1" 6121 "neg %1,%0" 6122 [(set_attr "type" "arith")]) 6123 6124(define_insn_and_split "one_cmplsi2" 6125 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6126 (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))] 6127 "TARGET_SH1" 6128 "not %1,%0" 6129 "&& can_create_pseudo_p ()" 6130 [(set (reg:SI T_REG) (ge:SI (match_dup 1) (const_int 0))) 6131 (set (match_dup 0) (reg:SI T_REG))] 6132{ 6133/* PR 54685 6134 If the result of 'unsigned int <= 0x7FFFFFFF' ends up as the following 6135 sequence: 6136 6137 (set (reg0) (not:SI (reg0) (reg1))) 6138 (parallel [(set (reg2) (lshiftrt:SI (reg0) (const_int 31))) 6139 (clobber (reg:SI T_REG))]) 6140 6141 ... match and combine the sequence manually in the split pass after the 6142 combine pass. Notice that combine does try the target pattern of this 6143 split, but if the pattern is added it interferes with other patterns, in 6144 particular with the div0s comparisons. 6145 This could also be done with a peephole but doing it here before register 6146 allocation can save one temporary. 6147 When we're here, the not:SI pattern obviously has been matched already 6148 and we only have to see whether the following insn is the left shift. */ 6149 6150 rtx_insn *i = next_nonnote_insn_bb (curr_insn); 6151 if (i == NULL_RTX || !NONJUMP_INSN_P (i)) 6152 FAIL; 6153 6154 rtx p = PATTERN (i); 6155 if (GET_CODE (p) != PARALLEL || XVECLEN (p, 0) != 2) 6156 FAIL; 6157 6158 rtx p0 = XVECEXP (p, 0, 0); 6159 rtx p1 = XVECEXP (p, 0, 1); 6160 6161 if (/* (set (reg2) (lshiftrt:SI (reg0) (const_int 31))) */ 6162 GET_CODE (p0) == SET 6163 && GET_CODE (XEXP (p0, 1)) == LSHIFTRT 6164 && REG_P (XEXP (XEXP (p0, 1), 0)) 6165 && REGNO (XEXP (XEXP (p0, 1), 0)) == REGNO (operands[0]) 6166 && CONST_INT_P (XEXP (XEXP (p0, 1), 1)) 6167 && INTVAL (XEXP (XEXP (p0, 1), 1)) == 31 6168 6169 /* (clobber (reg:SI T_REG)) */ 6170 && GET_CODE (p1) == CLOBBER && REG_P (XEXP (p1, 0)) 6171 && REGNO (XEXP (p1, 0)) == T_REG) 6172 { 6173 operands[0] = XEXP (p0, 0); 6174 set_insn_deleted (i); 6175 } 6176 else 6177 FAIL; 6178} 6179 [(set_attr "type" "arith")]) 6180 6181(define_expand "one_cmpldi2" 6182 [(set (match_operand:DI 0 "arith_reg_dest" "") 6183 (xor:DI (match_operand:DI 1 "arith_reg_operand" "") 6184 (const_int -1)))] 6185 "TARGET_SHMEDIA" "") 6186 6187(define_expand "abs<mode>2" 6188 [(parallel [(set (match_operand:SIDI 0 "arith_reg_dest") 6189 (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand"))) 6190 (clobber (reg:SI T_REG))])] 6191 "TARGET_SH1") 6192 6193(define_insn_and_split "*abs<mode>2" 6194 [(set (match_operand:SIDI 0 "arith_reg_dest") 6195 (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand"))) 6196 (clobber (reg:SI T_REG))] 6197 "TARGET_SH1" 6198 "#" 6199 "&& can_create_pseudo_p ()" 6200 [(const_int 0)] 6201{ 6202 if (<MODE>mode == SImode) 6203 emit_insn (gen_cmpgesi_t (operands[1], const0_rtx)); 6204 else 6205 { 6206 rtx high_src = gen_highpart (SImode, operands[1]); 6207 emit_insn (gen_cmpgesi_t (high_src, const0_rtx)); 6208 } 6209 6210 emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1], 6211 const1_rtx)); 6212 DONE; 6213}) 6214 6215(define_insn_and_split "*negabs<mode>2" 6216 [(set (match_operand:SIDI 0 "arith_reg_dest") 6217 (neg:SIDI (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand")))) 6218 (clobber (reg:SI T_REG))] 6219 "TARGET_SH1" 6220 "#" 6221 "&& can_create_pseudo_p ()" 6222 [(const_int 0)] 6223{ 6224 if (<MODE>mode == SImode) 6225 emit_insn (gen_cmpgesi_t (operands[1], const0_rtx)); 6226 else 6227 { 6228 rtx high_src = gen_highpart (SImode, operands[1]); 6229 emit_insn (gen_cmpgesi_t (high_src, const0_rtx)); 6230 } 6231 6232 emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1], 6233 const0_rtx)); 6234 DONE; 6235}) 6236 6237;; The SH4 202 can do zero-offset branches without pipeline stalls. 6238;; This can be used as some kind of conditional execution, which is useful 6239;; for abs. 6240;; Actually the instruction scheduling should decide whether to use a 6241;; zero-offset branch or not for any generic case involving a single 6242;; instruction on SH4 202. 6243(define_insn_and_split "negsi_cond" 6244 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 6245 (if_then_else 6246 (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand" "M,N")) 6247 (match_operand:SI 1 "arith_reg_operand" "0,0") 6248 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r,r"))))] 6249 "TARGET_SH1 && TARGET_ZDCBRANCH" 6250{ 6251 static const char* alt[] = 6252 { 6253 "bt 0f" "\n" 6254 " neg %2,%0" "\n" 6255 "0:", 6256 6257 "bf 0f" "\n" 6258 " neg %2,%0" "\n" 6259 "0:" 6260 }; 6261 return alt[which_alternative]; 6262} 6263 "TARGET_SH1 && ! TARGET_ZDCBRANCH" 6264 [(const_int 0)] 6265{ 6266 rtx skip_neg_label = gen_label_rtx (); 6267 6268 emit_move_insn (operands[0], operands[1]); 6269 6270 emit_jump_insn (INTVAL (operands[3]) 6271 ? gen_branch_true (skip_neg_label) 6272 : gen_branch_false (skip_neg_label)); 6273 6274 emit_label_after (skip_neg_label, 6275 emit_insn (gen_negsi2 (operands[0], operands[1]))); 6276 DONE; 6277} 6278 [(set_attr "type" "arith") ;; poor approximation 6279 (set_attr "length" "4")]) 6280 6281(define_insn_and_split "negdi_cond" 6282 [(set (match_operand:DI 0 "arith_reg_dest") 6283 (if_then_else 6284 (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand")) 6285 (match_operand:DI 1 "arith_reg_operand") 6286 (neg:DI (match_operand:DI 2 "arith_reg_operand")))) 6287 (clobber (reg:SI T_REG))] 6288 "TARGET_SH1" 6289 "#" 6290 "&& can_create_pseudo_p ()" 6291 [(const_int 0)] 6292{ 6293 rtx skip_neg_label = gen_label_rtx (); 6294 6295 emit_move_insn (operands[0], operands[1]); 6296 6297 emit_jump_insn (INTVAL (operands[3]) 6298 ? gen_branch_true (skip_neg_label) 6299 : gen_branch_false (skip_neg_label)); 6300 6301 if (!INTVAL (operands[3])) 6302 emit_insn (gen_clrt ()); 6303 6304 emit_insn (gen_negc (gen_lowpart (SImode, operands[0]), 6305 gen_lowpart (SImode, operands[1]))); 6306 emit_label_after (skip_neg_label, 6307 emit_insn (gen_negc (gen_highpart (SImode, operands[0]), 6308 gen_highpart (SImode, operands[1])))); 6309 DONE; 6310}) 6311 6312(define_expand "bswapsi2" 6313 [(set (match_operand:SI 0 "arith_reg_dest" "") 6314 (bswap:SI (match_operand:SI 1 "arith_reg_operand" "")))] 6315 "TARGET_SH1" 6316{ 6317 if (! can_create_pseudo_p ()) 6318 FAIL; 6319 else 6320 { 6321 rtx tmp0 = gen_reg_rtx (SImode); 6322 rtx tmp1 = gen_reg_rtx (SImode); 6323 6324 emit_insn (gen_swapbsi2 (tmp0, operands[1])); 6325 emit_insn (gen_rotlsi3_16 (tmp1, tmp0)); 6326 emit_insn (gen_swapbsi2 (operands[0], tmp1)); 6327 DONE; 6328 } 6329}) 6330 6331(define_insn "swapbsi2" 6332 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6333 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "r") 6334 (const_int -65536)) ;; 0xFFFF0000 6335 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8)) 6336 (const_int 65280)) 6337 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8)) 6338 (const_int 255)))))] 6339 "TARGET_SH1" 6340 "swap.b %1,%0" 6341 [(set_attr "type" "arith")]) 6342 6343;; The *swapbisi2_and_shl8 pattern helps the combine pass simplifying 6344;; partial byte swap expressions such as... 6345;; ((x & 0xFF) << 8) | ((x >> 8) & 0xFF). 6346;; ...which are currently not handled by the tree optimizers. 6347;; The combine pass will not initially try to combine the full expression, 6348;; but only some sub-expressions. In such a case the *swapbisi2_and_shl8 6349;; pattern acts as an intermediate pattern that will eventually lead combine 6350;; to the swapbsi2 pattern above. 6351;; As a side effect this also improves code that does (x & 0xFF) << 8 6352;; or (x << 8) & 0xFF00. 6353(define_insn_and_split "*swapbisi2_and_shl8" 6354 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6355 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r") 6356 (const_int 8)) 6357 (const_int 65280)) 6358 (match_operand:SI 2 "arith_reg_operand" "r")))] 6359 "TARGET_SH1 && ! reload_in_progress && ! reload_completed" 6360 "#" 6361 "&& can_create_pseudo_p ()" 6362 [(const_int 0)] 6363{ 6364 rtx tmp0 = gen_reg_rtx (SImode); 6365 rtx tmp1 = gen_reg_rtx (SImode); 6366 6367 emit_insn (gen_zero_extendqisi2 (tmp0, gen_lowpart (QImode, operands[1]))); 6368 emit_insn (gen_swapbsi2 (tmp1, tmp0)); 6369 emit_insn (gen_iorsi3 (operands[0], tmp1, operands[2])); 6370 DONE; 6371}) 6372 6373;; The *swapbhisi2 pattern is, like the *swapbisi2_and_shl8 pattern, another 6374;; intermediate pattern that will help the combine pass arriving at swapbsi2. 6375(define_insn_and_split "*swapbhisi2" 6376 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6377 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r") 6378 (const_int 8)) 6379 (const_int 65280)) 6380 (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))))] 6381 "TARGET_SH1 && ! reload_in_progress && ! reload_completed" 6382 "#" 6383 "&& can_create_pseudo_p ()" 6384 [(const_int 0)] 6385{ 6386 rtx tmp = gen_reg_rtx (SImode); 6387 6388 emit_insn (gen_zero_extendhisi2 (tmp, gen_lowpart (HImode, operands[1]))); 6389 emit_insn (gen_swapbsi2 (operands[0], tmp)); 6390 DONE; 6391}) 6392 6393;; In some cases the swapbsi2 pattern might leave a sequence such as... 6394;; swap.b r4,r4 6395;; mov r4,r0 6396;; 6397;; which can be simplified to... 6398;; swap.b r4,r0 6399(define_peephole2 6400 [(set (match_operand:SI 0 "arith_reg_dest" "") 6401 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "") 6402 (const_int -65536)) ;; 0xFFFF0000 6403 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8)) 6404 (const_int 65280)) 6405 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8)) 6406 (const_int 255))))) 6407 (set (match_operand:SI 2 "arith_reg_dest" "") 6408 (match_dup 0))] 6409 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])" 6410 [(set (match_dup 2) 6411 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "") 6412 (const_int -65536)) ;; 0xFFFF0000 6413 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8)) 6414 (const_int 65280)) 6415 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8)) 6416 (const_int 255)))))]) 6417 6418;; ------------------------------------------------------------------------- 6419;; Zero extension instructions 6420;; ------------------------------------------------------------------------- 6421 6422(define_insn "zero_extendsidi2" 6423 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 6424 (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))] 6425 "TARGET_SHMEDIA" 6426 "addz.l %1, r63, %0" 6427 [(set_attr "type" "arith_media") 6428 (set_attr "highpart" "extend")]) 6429 6430(define_insn "zero_extendhidi2" 6431 [(set (match_operand:DI 0 "register_operand" "=r,r") 6432 (zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))] 6433 "TARGET_SHMEDIA" 6434 "@ 6435 # 6436 ld%M1.uw %m1, %0" 6437 [(set_attr "type" "*,load_media") 6438 (set (attr "highpart") 6439 (cond [(match_test "sh_contains_memref_p (insn)") 6440 (const_string "user")] 6441 (const_string "ignore")))]) 6442 6443(define_split 6444 [(set (match_operand:DI 0 "register_operand" "") 6445 (zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))] 6446 "TARGET_SHMEDIA && reload_completed" 6447 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48))) 6448 (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))] 6449{ 6450 if (GET_CODE (operands[1]) == TRUNCATE) 6451 operands[1] = XEXP (operands[1], 0); 6452}) 6453 6454;; ??? when a truncated input to a zero_extend is reloaded, reload will 6455;; reload the entire truncate expression. 6456(define_insn_and_split "*loaddi_trunc" 6457 [(set (match_operand 0 "any_register_operand" "=r") 6458 (truncate (match_operand:DI 1 "memory_operand" "m")))] 6459 "TARGET_SHMEDIA && reload_completed" 6460 "#" 6461 "TARGET_SHMEDIA && reload_completed" 6462 [(set (match_dup 0) (match_dup 1))] 6463{ 6464 operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0])); 6465}) 6466 6467(define_insn "zero_extendqidi2" 6468 [(set (match_operand:DI 0 "register_operand" "=r,r") 6469 (zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))] 6470 "TARGET_SHMEDIA" 6471 "@ 6472 andi %1, 255, %0 6473 ld%M1.ub %m1, %0" 6474 [(set_attr "type" "arith_media,load_media") 6475 (set (attr "highpart") 6476 (cond [(match_test "sh_contains_memref_p (insn)") 6477 (const_string "user")] 6478 (const_string "ignore")))]) 6479 6480(define_expand "zero_extend<mode>si2" 6481 [(set (match_operand:SI 0 "arith_reg_dest") 6482 (zero_extend:SI (match_operand:QIHI 1 "zero_extend_operand")))]) 6483 6484(define_insn_and_split "*zero_extend<mode>si2_compact" 6485 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6486 (zero_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))] 6487 "TARGET_SH1" 6488 "extu.<bw> %1,%0" 6489 "&& can_create_pseudo_p ()" 6490 [(set (match_dup 0) (match_dup 2))] 6491{ 6492 /* Sometimes combine fails to combine a T bit or negated T bit store to a 6493 reg with a following zero extension. In the split pass after combine, 6494 try to figure out how the extended reg was set. If it originated from 6495 the T bit we can replace the zero extension with a reg move, which will 6496 be eliminated. Notice that this also helps the *cbranch_t splitter when 6497 it tries to post-combine tests and conditional branches, as it does not 6498 check for zero extensions. */ 6499 operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn); 6500 if (operands[2] == NULL_RTX) 6501 FAIL; 6502} 6503 [(set_attr "type" "arith")]) 6504 6505(define_insn "*zero_extendhisi2_media" 6506 [(set (match_operand:SI 0 "register_operand" "=r,r") 6507 (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))] 6508 "TARGET_SHMEDIA" 6509 "@ 6510 # 6511 ld%M1.uw %m1, %0" 6512 [(set_attr "type" "arith_media,load_media") 6513 (set (attr "highpart") 6514 (cond [(match_test "sh_contains_memref_p (insn)") 6515 (const_string "user")] 6516 (const_string "ignore")))]) 6517 6518(define_split 6519 [(set (match_operand:SI 0 "register_operand" "") 6520 (zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))] 6521 "TARGET_SHMEDIA && reload_completed" 6522 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16))) 6523 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))] 6524{ 6525 rtx op1 = operands[1]; 6526 6527 if (GET_CODE (op1) == TRUNCATE) 6528 op1 = XEXP (op1, 0); 6529 operands[2] 6530 = simplify_gen_subreg (SImode, op1, GET_MODE (op1), 6531 subreg_lowpart_offset (SImode, GET_MODE (op1))); 6532}) 6533 6534(define_insn "*zero_extendqisi2_media" 6535 [(set (match_operand:SI 0 "register_operand" "=r,r") 6536 (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))] 6537 "TARGET_SHMEDIA" 6538 "@ 6539 andi %1, 255, %0 6540 ld%M1.ub %m1, %0" 6541 [(set_attr "type" "arith_media,load_media") 6542 (set (attr "highpart") 6543 (cond [(match_test "sh_contains_memref_p (insn)") 6544 (const_string "user")] 6545 (const_string "ignore")))]) 6546 6547(define_insn "zero_extendqihi2" 6548 [(set (match_operand:HI 0 "arith_reg_dest" "=r") 6549 (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))] 6550 "TARGET_SH1" 6551 "extu.b %1,%0" 6552 [(set_attr "type" "arith")]) 6553 6554;; SH2A supports two zero extending load instructions: movu.b and movu.w. 6555;; They could also be used for simple memory addresses like @Rn by setting 6556;; the displacement value to zero. However, doing so too early results in 6557;; missed opportunities for other optimizations such as post-inc or index 6558;; addressing loads. 6559;; We don't allow the zero extending loads to match during RTL expansion 6560;; (see zero_extend_operand predicate), as this would pessimize other 6561;; optimization opportunities such as bit extractions of unsigned mems, 6562;; where the zero extraction is irrelevant. If the zero extracting mem 6563;; loads are emitted early it will be more difficult to change them back 6564;; to sign extending loads (which are preferred). 6565;; The combine pass will also try to combine mem loads and zero extends, 6566;; which is prevented by 'sh_legitimate_combined_insn'. 6567(define_insn "*zero_extend<mode>si2_disp_mem" 6568 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 6569 (zero_extend:SI 6570 (match_operand:QIHI 1 "zero_extend_movu_operand" "Sdd,Sra")))] 6571 "TARGET_SH2A" 6572 "@ 6573 movu.<bw> %1,%0 6574 movu.<bw> @(0,%t1),%0" 6575 [(set_attr "type" "load") 6576 (set_attr "length" "4")]) 6577 6578;; Convert the zero extending loads in sequences such as: 6579;; movu.b @(1,r5),r0 movu.w @(2,r5),r0 6580;; mov.b r0,@(1,r4) mov.b r0,@(1,r4) 6581;; 6582;; back to sign extending loads like: 6583;; mov.b @(1,r5),r0 mov.w @(2,r5),r0 6584;; mov.b r0,@(1,r4) mov.b r0,@(1,r4) 6585;; 6586;; if the extension type is irrelevant. The sign extending mov.{b|w} insn 6587;; is only 2 bytes in size if the displacement is {K04|K05}. 6588;; If the displacement is greater it doesn't matter, so we convert anyways. 6589(define_peephole2 6590 [(set (match_operand:SI 0 "arith_reg_dest" "") 6591 (zero_extend:SI (match_operand 1 "displacement_mem_operand" ""))) 6592 (set (match_operand 2 "nonimmediate_operand" "") 6593 (match_operand 3 "arith_reg_operand" ""))] 6594 "TARGET_SH2A 6595 && REGNO (operands[0]) == REGNO (operands[3]) 6596 && peep2_reg_dead_p (2, operands[0]) 6597 && GET_MODE_SIZE (GET_MODE (operands[2])) 6598 <= GET_MODE_SIZE (GET_MODE (operands[1]))" 6599 [(set (match_dup 0) (sign_extend:SI (match_dup 1))) 6600 (set (match_dup 2) (match_dup 3))]) 6601 6602;; Fold sequences such as 6603;; mov.b @r3,r7 6604;; extu.b r7,r7 6605;; into 6606;; movu.b @(0,r3),r7 6607;; This does not reduce the code size but the number of instructions is 6608;; halved, which results in faster code. 6609(define_peephole2 6610 [(set (match_operand:SI 0 "arith_reg_dest" "") 6611 (sign_extend:SI (match_operand 1 "simple_mem_operand" ""))) 6612 (set (match_operand:SI 2 "arith_reg_dest" "") 6613 (zero_extend:SI (match_operand 3 "arith_reg_operand" "")))] 6614 "TARGET_SH2A 6615 && GET_MODE (operands[1]) == GET_MODE (operands[3]) 6616 && (GET_MODE (operands[1]) == QImode || GET_MODE (operands[1]) == HImode) 6617 && REGNO (operands[0]) == REGNO (operands[3]) 6618 && (REGNO (operands[2]) == REGNO (operands[0]) 6619 || peep2_reg_dead_p (2, operands[0]))" 6620 [(set (match_dup 2) (zero_extend:SI (match_dup 4)))] 6621{ 6622 operands[4] 6623 = replace_equiv_address (operands[1], 6624 gen_rtx_PLUS (SImode, XEXP (operands[1], 0), 6625 const0_rtx)); 6626}) 6627 6628;; ------------------------------------------------------------------------- 6629;; Sign extension instructions 6630;; ------------------------------------------------------------------------- 6631 6632;; ??? This should be a define expand. 6633;; ??? Or perhaps it should be dropped? 6634 6635;; convert_move generates good code for SH[1-4]. 6636(define_insn "extendsidi2" 6637 [(set (match_operand:DI 0 "register_operand" "=r,r,r") 6638 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))] 6639 "TARGET_SHMEDIA" 6640 "@ 6641 add.l %1, r63, %0 6642 ld%M1.l %m1, %0 6643 fmov.sl %1, %0" 6644 [(set_attr "type" "arith_media,load_media,fpconv_media") 6645 (set (attr "highpart") 6646 (cond [(match_test "sh_contains_memref_p (insn)") 6647 (const_string "user")] 6648 (const_string "extend")))]) 6649 6650(define_insn "extendhidi2" 6651 [(set (match_operand:DI 0 "register_operand" "=r,r") 6652 (sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))] 6653 "TARGET_SHMEDIA" 6654 "@ 6655 # 6656 ld%M1.w %m1, %0" 6657 [(set_attr "type" "*,load_media") 6658 (set (attr "highpart") 6659 (cond [(match_test "sh_contains_memref_p (insn)") 6660 (const_string "user")] 6661 (const_string "ignore")))]) 6662 6663(define_split 6664 [(set (match_operand:DI 0 "register_operand" "") 6665 (sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))] 6666 "TARGET_SHMEDIA && reload_completed" 6667 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48))) 6668 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))] 6669{ 6670 if (GET_CODE (operands[1]) == TRUNCATE) 6671 operands[1] = XEXP (operands[1], 0); 6672}) 6673 6674(define_insn "extendqidi2" 6675 [(set (match_operand:DI 0 "register_operand" "=r,r") 6676 (sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))] 6677 "TARGET_SHMEDIA" 6678 "@ 6679 # 6680 ld%M1.b %m1, %0" 6681 [(set_attr "type" "*,load_media") 6682 (set (attr "highpart") 6683 (cond [(match_test "sh_contains_memref_p (insn)") 6684 (const_string "user")] 6685 (const_string "ignore")))]) 6686 6687(define_split 6688 [(set (match_operand:DI 0 "register_operand" "") 6689 (sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))] 6690 "TARGET_SHMEDIA && reload_completed" 6691 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56))) 6692 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))] 6693{ 6694 if (GET_CODE (operands[1]) == TRUNCATE) 6695 operands[1] = XEXP (operands[1], 0); 6696}) 6697 6698(define_expand "extend<mode>si2" 6699 [(set (match_operand:SI 0 "arith_reg_dest") 6700 (sign_extend:SI (match_operand:QIHI 1 "general_extend_operand")))]) 6701 6702(define_insn "*extendhisi2_media" 6703 [(set (match_operand:SI 0 "register_operand" "=r,r") 6704 (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))] 6705 "TARGET_SHMEDIA" 6706 "@ 6707 # 6708 ld%M1.w %m1, %0" 6709 [(set_attr "type" "arith_media,load_media") 6710 (set (attr "highpart") 6711 (cond [(match_test "sh_contains_memref_p (insn)") 6712 (const_string "user")] 6713 (const_string "ignore")))]) 6714 6715(define_split 6716 [(set (match_operand:SI 0 "register_operand" "") 6717 (sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))] 6718 "TARGET_SHMEDIA && reload_completed" 6719 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16))) 6720 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))] 6721{ 6722 rtx op1 = operands[1]; 6723 if (GET_CODE (op1) == TRUNCATE) 6724 op1 = XEXP (op1, 0); 6725 operands[2] 6726 = simplify_gen_subreg (SImode, op1, GET_MODE (op1), 6727 subreg_lowpart_offset (SImode, GET_MODE (op1))); 6728}) 6729 6730(define_insn_and_split "*extend<mode>si2_compact_reg" 6731 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6732 (sign_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))] 6733 "TARGET_SH1" 6734 "exts.<bw> %1,%0" 6735 "&& can_create_pseudo_p ()" 6736 [(set (match_dup 0) (match_dup 2))] 6737{ 6738 /* Sometimes combine fails to combine a T bit or negated T bit store to a 6739 reg with a following sign extension. In the split pass after combine, 6740 try to figure the extended reg was set. If it originated from the T 6741 bit we can replace the sign extension with a reg move, which will be 6742 eliminated. */ 6743 operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn); 6744 if (operands[2] == NULL_RTX) 6745 FAIL; 6746} 6747 [(set_attr "type" "arith")]) 6748 6749;; FIXME: Fold non-SH2A and SH2A alternatives with "enabled" attribute. 6750;; See movqi insns. 6751(define_insn "*extend<mode>si2_compact_mem_disp" 6752 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r") 6753 (sign_extend:SI 6754 (mem:QIHI 6755 (plus:SI 6756 (match_operand:SI 1 "arith_reg_operand" "%r,r") 6757 (match_operand:SI 2 "const_int_operand" "<disp04>,N")))))] 6758 "TARGET_SH1 && ! TARGET_SH2A 6759 && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)" 6760 "@ 6761 mov.<bw> @(%O2,%1),%0 6762 mov.<bw> @%1,%0" 6763 [(set_attr "type" "load")]) 6764 6765(define_insn "*extend<mode>si2_compact_mem_disp" 6766 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r,r") 6767 (sign_extend:SI 6768 (mem:QIHI 6769 (plus:SI 6770 (match_operand:SI 1 "arith_reg_operand" "%r,r,r") 6771 (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>")))))] 6772 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)" 6773 "@ 6774 mov.<bw> @(%O2,%1),%0 6775 mov.<bw> @%1,%0 6776 mov.<bw> @(%O2,%1),%0" 6777 [(set_attr "type" "load") 6778 (set_attr "length" "2,2,4")]) 6779 6780;; The *_snd patterns will take care of other QImode/HImode addressing 6781;; modes than displacement addressing. They must be defined _after_ the 6782;; displacement addressing patterns. Otherwise the displacement addressing 6783;; patterns will not be picked. 6784(define_insn "*extend<mode>si2_compact_snd" 6785 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6786 (sign_extend:SI 6787 (match_operand:QIHI 1 "movsrc_no_disp_mem_operand" "Snd")))] 6788 "TARGET_SH1" 6789 "mov.<bw> %1,%0" 6790 [(set_attr "type" "load")]) 6791 6792(define_insn "*extendqisi2_media" 6793 [(set (match_operand:SI 0 "register_operand" "=r,r") 6794 (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))] 6795 "TARGET_SHMEDIA" 6796 "@ 6797 # 6798 ld%M1.b %m1, %0" 6799 [(set_attr "type" "arith_media,load_media") 6800 (set (attr "highpart") 6801 (cond [(match_test "sh_contains_memref_p (insn)") 6802 (const_string "user")] 6803 (const_string "ignore")))]) 6804 6805(define_split 6806 [(set (match_operand:SI 0 "register_operand" "") 6807 (sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))] 6808 "TARGET_SHMEDIA && reload_completed" 6809 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24))) 6810 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))] 6811{ 6812 rtx op1 = operands[1]; 6813 if (GET_CODE (op1) == TRUNCATE) 6814 op1 = XEXP (op1, 0); 6815 operands[2] 6816 = simplify_gen_subreg (SImode, op1, GET_MODE (op1), 6817 subreg_lowpart_offset (SImode, GET_MODE (op1))); 6818}) 6819 6820(define_expand "extendqihi2" 6821 [(set (match_operand:HI 0 "arith_reg_dest") 6822 (sign_extend:HI (match_operand:QI 1 "arith_reg_operand")))] 6823 "TARGET_SH1") 6824 6825(define_insn "*extendqihi2_compact_reg" 6826 [(set (match_operand:HI 0 "arith_reg_dest" "=r") 6827 (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))] 6828 "TARGET_SH1" 6829 "exts.b %1,%0" 6830 [(set_attr "type" "arith")]) 6831 6832;; It would seem useful to combine the truncXi patterns into the movXi 6833;; patterns, but unary operators are ignored when matching constraints, 6834;; so we need separate patterns. 6835(define_insn "truncdisi2" 6836 [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f") 6837 (truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))] 6838 "TARGET_SHMEDIA" 6839 "@ 6840 add.l %1, r63, %0 6841 st%M0.l %m0, %1 6842 fst%M0.s %m0, %T1 6843 fmov.ls %1, %0 6844 fmov.sl %T1, %0 6845 fmov.s %T1, %0" 6846 [(set_attr "type" "arith_media,store_media,fstore_media,fload_media, 6847 fpconv_media,fmove_media") 6848 (set (attr "highpart") 6849 (cond [(match_test "sh_contains_memref_p (insn)") 6850 (const_string "user")] 6851 (const_string "extend")))]) 6852 6853(define_insn "truncdihi2" 6854 [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m") 6855 (truncate:HI (match_operand:DI 1 "register_operand" "r,r")))] 6856 "TARGET_SHMEDIA" 6857{ 6858 static const char* alt[] = 6859 { 6860 "shlli %1,48,%0" "\n" 6861 " shlri %0,48,%0", 6862 6863 "st%M0.w %m0, %1" 6864 }; 6865 return alt[which_alternative]; 6866} 6867 [(set_attr "type" "arith_media,store_media") 6868 (set_attr "length" "8,4") 6869 (set (attr "highpart") 6870 (cond [(match_test "sh_contains_memref_p (insn)") 6871 (const_string "user")] 6872 (const_string "extend")))]) 6873 6874; N.B. This should agree with LOAD_EXTEND_OP and movqi. 6875; Because we use zero extension, we can't provide signed QImode compares 6876; using a simple compare or conditional branch insn. 6877(define_insn "truncdiqi2" 6878 [(set (match_operand:QI 0 "general_movdst_operand" "=r,m") 6879 (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))] 6880 "TARGET_SHMEDIA" 6881 "@ 6882 andi %1, 255, %0 6883 st%M0.b %m0, %1" 6884 [(set_attr "type" "arith_media,store") 6885 (set (attr "highpart") 6886 (cond [(match_test "sh_contains_memref_p (insn)") 6887 (const_string "user")] 6888 (const_string "extend")))]) 6889 6890;; ------------------------------------------------------------------------- 6891;; Move instructions 6892;; ------------------------------------------------------------------------- 6893 6894;; define push and pop so it is easy for sh.c 6895;; We can't use push and pop on SHcompact because the stack must always 6896;; be 8-byte aligned. 6897(define_expand "push" 6898 [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) 6899 (match_operand:SI 0 "register_operand" "r,l,x"))] 6900 "TARGET_SH1 && ! TARGET_SH5" 6901 "") 6902 6903(define_expand "pop" 6904 [(set (match_operand:SI 0 "register_operand" "=r,l,x") 6905 (mem:SI (post_inc:SI (reg:SI SP_REG))))] 6906 "TARGET_SH1 && ! TARGET_SH5" 6907 "") 6908 6909(define_expand "push_e" 6910 [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) 6911 (match_operand:SF 0 "" "")) 6912 (use (reg:SI FPSCR_MODES_REG)) 6913 (clobber (scratch:SI))])] 6914 "TARGET_SH1 && ! TARGET_SH5" 6915 "") 6916 6917(define_insn "push_fpul" 6918 [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))] 6919 "TARGET_SH2E && ! TARGET_SH5" 6920 "sts.l fpul,@-r15" 6921 [(set_attr "type" "fstore") 6922 (set_attr "late_fp_use" "yes") 6923 (set_attr "hit_stack" "yes")]) 6924 6925;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4, 6926;; so use that. 6927(define_expand "push_4" 6928 [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG))) 6929 (match_operand:DF 0 "" "")) 6930 (use (reg:SI FPSCR_MODES_REG)) 6931 (clobber (scratch:SI))])] 6932 "TARGET_SH1 && ! TARGET_SH5" 6933 "") 6934 6935(define_expand "pop_e" 6936 [(parallel [(set (match_operand:SF 0 "" "") 6937 (mem:SF (post_inc:SI (reg:SI SP_REG)))) 6938 (use (reg:SI FPSCR_MODES_REG)) 6939 (clobber (scratch:SI))])] 6940 "TARGET_SH1 && ! TARGET_SH5" 6941 "") 6942 6943(define_insn "pop_fpul" 6944 [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))] 6945 "TARGET_SH2E && ! TARGET_SH5" 6946 "lds.l @r15+,fpul" 6947 [(set_attr "type" "load") 6948 (set_attr "hit_stack" "yes")]) 6949 6950(define_expand "pop_4" 6951 [(parallel [(set (match_operand:DF 0 "" "") 6952 (mem:DF (post_inc:SI (reg:SI SP_REG)))) 6953 (use (reg:SI FPSCR_MODES_REG)) 6954 (clobber (scratch:SI))])] 6955 "TARGET_SH1 && ! TARGET_SH5" 6956 "") 6957 6958(define_expand "push_fpscr" 6959 [(const_int 0)] 6960 "TARGET_SH2E" 6961{ 6962 add_reg_note ( 6963 emit_insn ( 6964 gen_sts_fpscr ( 6965 gen_frame_mem (SImode, gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx)))), 6966 REG_INC, stack_pointer_rtx); 6967 DONE; 6968}) 6969 6970(define_expand "pop_fpscr" 6971 [(const_int 0)] 6972 "TARGET_SH2E" 6973{ 6974 add_reg_note ( 6975 emit_insn ( 6976 gen_lds_fpscr ( 6977 gen_frame_mem (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx)))), 6978 REG_INC, stack_pointer_rtx); 6979 DONE; 6980}) 6981 6982;; The clrt and sett patterns can happen as the result of optimization and 6983;; insn expansion. 6984;; Comparisons might get simplified to a move of zero or 1 into the T reg. 6985;; In this case they might not disappear completely, because the T reg is 6986;; a fixed hard reg. 6987;; When DImode operations that use the T reg as carry/borrow are split into 6988;; individual SImode operations, the T reg is usually cleared before the 6989;; first SImode insn. 6990(define_insn "clrt" 6991 [(set (reg:SI T_REG) (const_int 0))] 6992 "TARGET_SH1" 6993 "clrt" 6994 [(set_attr "type" "mt_group")]) 6995 6996(define_insn "sett" 6997 [(set (reg:SI T_REG) (const_int 1))] 6998 "TARGET_SH1" 6999 "sett" 7000 [(set_attr "type" "mt_group")]) 7001 7002;; Use the combine pass to transform sequences such as 7003;; mov r5,r0 7004;; add #1,r0 7005;; shll2 r0 7006;; mov.l @(r0,r4),r0 7007;; into 7008;; shll2 r5 7009;; add r4,r5 7010;; mov.l @(4,r5),r0 7011;; 7012;; See also PR 39423. 7013;; Notice that these patterns have a T_REG clobber, because the shift 7014;; sequence that will be split out might clobber the T_REG. Ideally, the 7015;; clobber would be added conditionally, depending on the result of 7016;; sh_ashlsi_clobbers_t_reg_p. When splitting out the shifts we must go 7017;; through the ashlsi3 expander in order to get the right shift insn -- 7018;; a T_REG clobbering or non-clobbering shift sequence or dynamic shift. 7019;; FIXME: Combine never tries this kind of patterns for DImode. 7020(define_insn_and_split "*movsi_index_disp_load" 7021 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 7022 (match_operand:SI 1 "mem_index_disp_operand" "m")) 7023 (clobber (reg:SI T_REG))] 7024 "TARGET_SH1" 7025 "#" 7026 "&& can_create_pseudo_p ()" 7027 [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3))) 7028 (set (match_dup 0) (match_dup 7))] 7029{ 7030 rtx mem = operands[1]; 7031 rtx plus0_rtx = XEXP (mem, 0); 7032 rtx plus1_rtx = XEXP (plus0_rtx, 0); 7033 rtx mult_rtx = XEXP (plus1_rtx, 0); 7034 7035 operands[1] = XEXP (mult_rtx, 0); 7036 operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1)))); 7037 operands[3] = XEXP (plus1_rtx, 1); 7038 operands[4] = XEXP (plus0_rtx, 1); 7039 operands[5] = gen_reg_rtx (SImode); 7040 operands[6] = gen_reg_rtx (SImode); 7041 operands[7] = 7042 replace_equiv_address (mem, 7043 gen_rtx_PLUS (SImode, operands[6], operands[4])); 7044 7045 emit_insn (gen_ashlsi3 (operands[5], operands[1], operands[2])); 7046}) 7047 7048(define_insn_and_split "*movhi_index_disp_load" 7049 [(set (match_operand:SI 0 "arith_reg_dest") 7050 (SZ_EXTEND:SI (match_operand:HI 1 "mem_index_disp_operand"))) 7051 (clobber (reg:SI T_REG))] 7052 "TARGET_SH1" 7053 "#" 7054 "&& can_create_pseudo_p ()" 7055 [(const_int 0)] 7056{ 7057 rtx mem = operands[1]; 7058 rtx plus0_rtx = XEXP (mem, 0); 7059 rtx plus1_rtx = XEXP (plus0_rtx, 0); 7060 rtx mult_rtx = XEXP (plus1_rtx, 0); 7061 7062 rtx op_1 = XEXP (mult_rtx, 0); 7063 rtx op_2 = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1)))); 7064 rtx op_3 = XEXP (plus1_rtx, 1); 7065 rtx op_4 = XEXP (plus0_rtx, 1); 7066 rtx op_5 = gen_reg_rtx (SImode); 7067 rtx op_6 = gen_reg_rtx (SImode); 7068 rtx op_7 = replace_equiv_address (mem, gen_rtx_PLUS (SImode, op_6, op_4)); 7069 7070 emit_insn (gen_ashlsi3 (op_5, op_1, op_2)); 7071 emit_insn (gen_addsi3 (op_6, op_5, op_3)); 7072 7073 if (<CODE> == SIGN_EXTEND) 7074 { 7075 emit_insn (gen_extendhisi2 (operands[0], op_7)); 7076 DONE; 7077 } 7078 else if (<CODE> == ZERO_EXTEND) 7079 { 7080 /* On SH2A the movu.w insn can be used for zero extending loads. */ 7081 if (TARGET_SH2A) 7082 emit_insn (gen_zero_extendhisi2 (operands[0], op_7)); 7083 else 7084 { 7085 emit_insn (gen_extendhisi2 (operands[0], op_7)); 7086 emit_insn (gen_zero_extendhisi2 (operands[0], 7087 gen_lowpart (HImode, operands[0]))); 7088 } 7089 DONE; 7090 } 7091 else 7092 FAIL; 7093}) 7094 7095(define_insn_and_split "*mov<mode>_index_disp_store" 7096 [(set (match_operand:HISI 0 "mem_index_disp_operand" "=m") 7097 (match_operand:HISI 1 "arith_reg_operand" "r")) 7098 (clobber (reg:SI T_REG))] 7099 "TARGET_SH1" 7100 "#" 7101 "&& can_create_pseudo_p ()" 7102 [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3))) 7103 (set (match_dup 7) (match_dup 1))] 7104{ 7105 rtx mem = operands[0]; 7106 rtx plus0_rtx = XEXP (mem, 0); 7107 rtx plus1_rtx = XEXP (plus0_rtx, 0); 7108 rtx mult_rtx = XEXP (plus1_rtx, 0); 7109 7110 operands[0] = XEXP (mult_rtx, 0); 7111 operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1)))); 7112 operands[3] = XEXP (plus1_rtx, 1); 7113 operands[4] = XEXP (plus0_rtx, 1); 7114 operands[5] = gen_reg_rtx (SImode); 7115 operands[6] = gen_reg_rtx (SImode); 7116 operands[7] = 7117 replace_equiv_address (mem, 7118 gen_rtx_PLUS (SImode, operands[6], operands[4])); 7119 7120 emit_insn (gen_ashlsi3 (operands[5], operands[0], operands[2])); 7121}) 7122 7123;; t/r must come after r/r, lest reload will try to reload stuff like 7124;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0) 7125;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T. 7126(define_insn "movsi_i" 7127 [(set (match_operand:SI 0 "general_movdst_operand" 7128 "=r,r,r,r,r,r,m,<,<,x,l,x,l,r") 7129 (match_operand:SI 1 "general_movsrc_operand" 7130 "Q,r,I08,mr,x,l,r,x,l,r,r,>,>,i"))] 7131 "TARGET_SH1 7132 && ! TARGET_SH2E 7133 && ! TARGET_SH2A 7134 && (register_operand (operands[0], SImode) 7135 || register_operand (operands[1], SImode))" 7136 "@ 7137 mov.l %1,%0 7138 mov %1,%0 7139 mov %1,%0 7140 mov.l %1,%0 7141 sts %1,%0 7142 sts %1,%0 7143 mov.l %1,%0 7144 sts.l %1,%0 7145 sts.l %1,%0 7146 lds %1,%0 7147 lds %1,%0 7148 lds.l %1,%0 7149 lds.l %1,%0 7150 fake %1,%0" 7151 [(set_attr "type" "pcload_si,move,movi8,load_si,mac_gp,prget,store,mac_mem, 7152 pstore,gp_mac,prset,mem_mac,pload,pcload_si") 7153 (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*")]) 7154 7155;; t/r must come after r/r, lest reload will try to reload stuff like 7156;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2) 7157;; ??? This allows moves from macl to fpul to be recognized, but these moves 7158;; will require a reload. 7159;; ??? We can't include f/f because we need the proper FPSCR setting when 7160;; TARGET_FMOVD is in effect, and mode switching is done before reload. 7161(define_insn "movsi_ie" 7162 [(set (match_operand:SI 0 "general_movdst_operand" 7163 "=r,r,r,r,r,r,r,r,mr,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y") 7164 (match_operand:SI 1 "general_movsrc_operand" 7165 "Q,r,I08,I20,I28,mr,x,l,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))] 7166 "(TARGET_SH2E || TARGET_SH2A) 7167 && ((register_operand (operands[0], SImode) 7168 && !fpscr_operand (operands[0], SImode)) 7169 || (register_operand (operands[1], SImode) 7170 && !fpscr_operand (operands[1], SImode)))" 7171 "@ 7172 mov.l %1,%0 7173 mov %1,%0 7174 mov %1,%0 7175 movi20 %1,%0 7176 movi20s %1,%0 7177 mov.l %1,%0 7178 sts %1,%0 7179 sts %1,%0 7180 mov.l %1,%0 7181 sts.l %1,%0 7182 sts.l %1,%0 7183 lds %1,%0 7184 lds %1,%0 7185 lds.l %1,%0 7186 lds.l %1,%0 7187 lds.l %1,%0 7188 sts.l %1,%0 7189 fake %1,%0 7190 lds %1,%0 7191 sts %1,%0 7192 fsts fpul,%0 7193 flds %1,fpul 7194 fmov %1,%0 7195 ! move optimized away" 7196 [(set_attr "type" "pcload_si,move,movi8,move,move,load_si,mac_gp,prget,store, 7197 mac_mem,pstore,gp_mac,prset,mem_mac,pload,load,fstore, 7198 pcload_si,gp_fpul,fpul_gp,fmove,fmove,fmove,nil") 7199 (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*") 7200 (set_attr_alternative "length" 7201 [(const_int 2) 7202 (const_int 2) 7203 (const_int 2) 7204 (const_int 4) 7205 (const_int 4) 7206 (if_then_else 7207 (match_test "TARGET_SH2A") 7208 (const_int 4) (const_int 2)) 7209 (const_int 2) 7210 (const_int 2) 7211 (if_then_else 7212 (match_test "TARGET_SH2A") 7213 (const_int 4) (const_int 2)) 7214 (const_int 2) 7215 (const_int 2) 7216 (const_int 2) 7217 (const_int 2) 7218 (const_int 2) 7219 (const_int 2) 7220 (const_int 2) 7221 (const_int 2) 7222 (const_int 2) 7223 (const_int 2) 7224 (const_int 2) 7225 (const_int 2) 7226 (const_int 2) 7227 (const_int 2) 7228 (const_int 0)])]) 7229 7230(define_insn "movsi_i_lowpart" 7231 [(set (strict_low_part 7232 (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r")) 7233 (match_operand:SI 1 "general_movsrc_operand" "Q,r,I08,mr,x,l,r,i"))] 7234 "TARGET_SH1 7235 && (register_operand (operands[0], SImode) 7236 || register_operand (operands[1], SImode))" 7237 "@ 7238 mov.l %1,%0 7239 mov %1,%0 7240 mov %1,%0 7241 mov.l %1,%0 7242 sts %1,%0 7243 sts %1,%0 7244 mov.l %1,%0 7245 fake %1,%0" 7246 [(set_attr "type" "pcload,move,arith,load,mac_gp,prget,store,pcload")]) 7247 7248(define_insn_and_split "load_ra" 7249 [(set (match_operand:SI 0 "general_movdst_operand" "") 7250 (unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))] 7251 "TARGET_SH1" 7252 "#" 7253 "&& ! currently_expanding_to_rtl" 7254 [(set (match_dup 0) (match_dup 1))] 7255{ 7256 if (TARGET_SHCOMPACT && crtl->saves_all_registers) 7257 operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx); 7258}) 7259 7260;; The '?'s in the following constraints may not reflect the time taken 7261;; to perform the move. They are there to discourage the use of floating- 7262;; point registers for storing integer values. 7263(define_insn "*movsi_media" 7264 [(set (match_operand:SI 0 "general_movdst_operand" 7265 "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b") 7266 (match_operand:SI 1 "general_movsrc_operand" 7267 "r,I16Css,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))] 7268 "TARGET_SHMEDIA_FPU 7269 && (register_operand (operands[0], SImode) 7270 || sh_register_operand (operands[1], SImode) 7271 || GET_CODE (operands[1]) == TRUNCATE)" 7272 "@ 7273 add.l %1, r63, %0 7274 movi %1, %0 7275 # 7276 ld%M1.l %m1, %0 7277 st%M0.l %m0, %N1 7278 fld%M1.s %m1, %0 7279 fst%M0.s %m0, %1 7280 fmov.ls %N1, %0 7281 fmov.sl %1, %0 7282 fmov.s %1, %0 7283 ptabs %1, %0 7284 gettr %1, %0 7285 pt %1, %0" 7286 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media, 7287 fload_media,fstore_media,fload_media,fpconv_media, 7288 fmove_media,ptabs_media,gettr_media,pt_media") 7289 (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12") 7290 (set (attr "highpart") 7291 (cond [(match_test "sh_contains_memref_p (insn)") 7292 (const_string "user")] 7293 (const_string "ignore")))]) 7294 7295(define_insn "*movsi_media_nofpu" 7296 [(set (match_operand:SI 0 "general_movdst_operand" 7297 "=r,r,r,r,m,*b,r,*b") 7298 (match_operand:SI 1 "general_movsrc_operand" 7299 "r,I16Css,nCpg,m,rZ,r,*b,Csy"))] 7300 "TARGET_SHMEDIA 7301 && (register_operand (operands[0], SImode) 7302 || sh_register_operand (operands[1], SImode) 7303 || GET_CODE (operands[1]) == TRUNCATE)" 7304 "@ 7305 add.l %1, r63, %0 7306 movi %1, %0 7307 # 7308 ld%M1.l %m1, %0 7309 st%M0.l %m0, %N1 7310 ptabs %1, %0 7311 gettr %1, %0 7312 pt %1, %0" 7313 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media, 7314 ptabs_media,gettr_media,pt_media") 7315 (set_attr "length" "4,4,8,4,4,4,4,12") 7316 (set (attr "highpart") 7317 (cond [(match_test "sh_contains_memref_p (insn)") 7318 (const_string "user")] 7319 (const_string "ignore")))]) 7320 7321(define_expand "movsi_const" 7322 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 7323 (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s") 7324 (const_int 16)] UNSPEC_EXTRACT_S16))) 7325 (set (match_dup 0) 7326 (ior:SI (ashift:SI (match_dup 0) (const_int 16)) 7327 (const:SI (unspec:SI [(match_dup 1) 7328 (const_int 0)] UNSPEC_EXTRACT_U16))))] 7329 "TARGET_SHMEDIA && reload_completed 7330 && MOVI_SHORI_BASE_OPERAND_P (operands[1])" 7331{ 7332 if (GET_CODE (operands[1]) == LABEL_REF 7333 && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL) 7334 LABEL_NUSES (XEXP (operands[1], 0)) += 2; 7335 else if (GOTOFF_P (operands[1])) 7336 { 7337 rtx unspec = XEXP (operands[1], 0); 7338 7339 if (! UNSPEC_GOTOFF_P (unspec)) 7340 { 7341 unspec = XEXP (unspec, 0); 7342 if (! UNSPEC_GOTOFF_P (unspec)) 7343 abort (); 7344 } 7345 if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF 7346 && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL)) 7347 LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2; 7348 } 7349}) 7350 7351(define_expand "movsi_const_16bit" 7352 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 7353 (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s") 7354 (const_int 0)] UNSPEC_EXTRACT_S16)))] 7355 "TARGET_SHMEDIA && flag_pic && reload_completed 7356 && GET_CODE (operands[1]) == SYMBOL_REF" 7357 "") 7358 7359(define_split 7360 [(set (match_operand:SI 0 "arith_reg_dest" "") 7361 (match_operand:SI 1 "immediate_operand" ""))] 7362 "TARGET_SHMEDIA && reload_completed 7363 && MOVI_SHORI_BASE_OPERAND_P (operands[1])" 7364 [(const_int 0)] 7365{ 7366 rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1])); 7367 7368 set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1])); 7369 7370 DONE; 7371}) 7372 7373(define_split 7374 [(set (match_operand:SI 0 "register_operand" "") 7375 (match_operand:SI 1 "immediate_operand" ""))] 7376 "TARGET_SHMEDIA && reload_completed 7377 && ((CONST_INT_P (operands[1]) 7378 && ! satisfies_constraint_I16 (operands[1])) 7379 || GET_CODE (operands[1]) == CONST_DOUBLE)" 7380 [(set (subreg:DI (match_dup 0) 0) (match_dup 1))]) 7381 7382(define_expand "movsi" 7383 [(set (match_operand:SI 0 "general_movdst_operand" "") 7384 (match_operand:SI 1 "general_movsrc_operand" ""))] 7385 "" 7386{ 7387 prepare_move_operands (operands, SImode); 7388}) 7389 7390(define_expand "ic_invalidate_line" 7391 [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r") 7392 (match_dup 1)] UNSPEC_ICACHE) 7393 (clobber (scratch:SI))])] 7394 "TARGET_HARD_SH4 || TARGET_SH5" 7395{ 7396 if (TARGET_SHMEDIA) 7397 { 7398 emit_insn (gen_ic_invalidate_line_media (operands[0])); 7399 DONE; 7400 } 7401 else if (TARGET_SHCOMPACT) 7402 { 7403 operands[1] = function_symbol (NULL, "__ic_invalidate", SFUNC_STATIC).sym; 7404 operands[1] = force_reg (Pmode, operands[1]); 7405 emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1])); 7406 DONE; 7407 } 7408 else if (TARGET_SH4A || TARGET_SH4_300) 7409 { 7410 emit_insn (gen_ic_invalidate_line_sh4a (operands[0])); 7411 DONE; 7412 } 7413 operands[0] = force_reg (Pmode, operands[0]); 7414 operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008, 7415 Pmode))); 7416}) 7417 7418;; The address %0 is assumed to be 4-aligned at least. Thus, by ORing 7419;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits 7420;; the requirement *1*00 for associative address writes. The alignment of 7421;; %0 implies that its least significant bit is cleared, 7422;; thus we clear the V bit of a matching entry if there is one. 7423(define_insn "ic_invalidate_line_i" 7424 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r") 7425 (match_operand:SI 1 "register_operand" "r")] 7426 UNSPEC_ICACHE) 7427 (clobber (match_scratch:SI 2 "=&r"))] 7428 "TARGET_HARD_SH4" 7429{ 7430 return "ocbwb @%0" "\n" 7431 " extu.w %0,%2" "\n" 7432 " or %1,%2" "\n" 7433 " mov.l %0,@%2"; 7434} 7435 [(set_attr "length" "8") 7436 (set_attr "type" "cwb")]) 7437 7438(define_insn "ic_invalidate_line_sh4a" 7439 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] 7440 UNSPEC_ICACHE)] 7441 "TARGET_SH4A || TARGET_SH4_300" 7442{ 7443 return "ocbwb @%0" "\n" 7444 " synco" "\n" 7445 " icbi @%0"; 7446} 7447 [(set_attr "length" "16") ;; FIXME: Why 16 and not 6? Looks like typo. 7448 (set_attr "type" "cwb")]) 7449 7450;; ??? could make arg 0 an offsettable memory operand to allow to save 7451;; an add in the code that calculates the address. 7452(define_insn "ic_invalidate_line_media" 7453 [(unspec_volatile [(match_operand 0 "any_register_operand" "r")] 7454 UNSPEC_ICACHE)] 7455 "TARGET_SHMEDIA" 7456{ 7457 return "ocbwb %0,0" "\n" 7458 " synco" "\n" 7459 " icbi %0,0" "\n" 7460 " synci"; 7461} 7462 [(set_attr "length" "16") 7463 (set_attr "type" "invalidate_line_media")]) 7464 7465(define_insn "ic_invalidate_line_compact" 7466 [(unspec_volatile [(match_operand:SI 0 "register_operand" "z") 7467 (match_operand:SI 1 "register_operand" "r")] 7468 UNSPEC_ICACHE) 7469 (clobber (reg:SI PR_REG))] 7470 "TARGET_SHCOMPACT" 7471 "jsr @%1%#" 7472 [(set_attr "type" "sfunc") 7473 (set_attr "needs_delay_slot" "yes")]) 7474 7475(define_expand "initialize_trampoline" 7476 [(match_operand:SI 0 "" "") 7477 (match_operand:SI 1 "" "") 7478 (match_operand:SI 2 "" "")] 7479 "TARGET_SHCOMPACT" 7480{ 7481 rtx sfun, tramp; 7482 7483 tramp = force_reg (Pmode, operands[0]); 7484 sfun = force_reg (Pmode, function_symbol (NULL, "__init_trampoline", 7485 SFUNC_STATIC).sym); 7486 emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]); 7487 emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]); 7488 7489 emit_insn (gen_initialize_trampoline_compact (tramp, sfun)); 7490 DONE; 7491}) 7492 7493(define_insn "initialize_trampoline_compact" 7494 [(unspec_volatile [(match_operand:SI 0 "register_operand" "z") 7495 (match_operand:SI 1 "register_operand" "r") 7496 (reg:SI R2_REG) (reg:SI R3_REG)] 7497 UNSPEC_INIT_TRAMP) 7498 7499 (clobber (reg:SI PR_REG))] 7500 "TARGET_SHCOMPACT" 7501 "jsr @%1%#" 7502 [(set_attr "type" "sfunc") 7503 (set_attr "needs_delay_slot" "yes")]) 7504 7505(define_expand "mov<mode>" 7506 [(set (match_operand:QIHI 0 "general_movdst_operand") 7507 (match_operand:QIHI 1 "general_movsrc_operand"))] 7508 "" 7509{ 7510 if (can_create_pseudo_p () && CONST_INT_P (operands[1]) 7511 && REG_P (operands[0]) && REGNO (operands[0]) != R0_REG) 7512 { 7513 rtx reg = gen_reg_rtx(SImode); 7514 emit_move_insn (reg, operands[1]); 7515 operands[1] = gen_lowpart (<MODE>mode, reg); 7516 } 7517 7518 prepare_move_operands (operands, <MODE>mode); 7519}) 7520 7521;; Specifying the displacement addressing load / store patterns separately 7522;; before the generic movqi / movhi pattern allows controlling the order 7523;; in which load / store insns are selected in a more fine grained way. 7524;; FIXME: The non-SH2A and SH2A variants should be combined by adding 7525;; "enabled" attribute as it is done in other targets. 7526(define_insn "*mov<mode>_store_mem_disp04" 7527 [(set (mem:QIHI 7528 (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r,r") 7529 (match_operand:SI 1 "const_int_operand" "<disp04>,N"))) 7530 (match_operand:QIHI 2 "arith_reg_operand" "z,r"))] 7531 "TARGET_SH1 && sh_legitimate_index_p (<MODE>mode, operands[1], false, true)" 7532 "@ 7533 mov.<bw> %2,@(%O1,%0) 7534 mov.<bw> %2,@%0" 7535 [(set_attr "type" "store")]) 7536 7537(define_insn "*mov<mode>_store_mem_disp12" 7538 [(set (mem:QIHI 7539 (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r") 7540 (match_operand:SI 1 "const_int_operand" "<disp12>"))) 7541 (match_operand:QIHI 2 "arith_reg_operand" "r"))] 7542 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[1], true, true)" 7543 "mov.<bw> %2,@(%O1,%0)" 7544 [(set_attr "type" "store") 7545 (set_attr "length" "4")]) 7546 7547(define_insn "*mov<mode>_load_mem_disp04" 7548 [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r") 7549 (mem:QIHI 7550 (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r") 7551 (match_operand:SI 2 "const_int_operand" "<disp04>,N"))))] 7552 "TARGET_SH1 && ! TARGET_SH2A 7553 && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)" 7554 "@ 7555 mov.<bw> @(%O2,%1),%0 7556 mov.<bw> @%1,%0" 7557 [(set_attr "type" "load")]) 7558 7559(define_insn "*mov<mode>_load_mem_disp12" 7560 [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r,r") 7561 (mem:QIHI 7562 (plus:SI 7563 (match_operand:SI 1 "arith_reg_operand" "%r,r,r") 7564 (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>"))))] 7565 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)" 7566 "@ 7567 mov.<bw> @(%O2,%1),%0 7568 mov.<bw> @%1,%0 7569 mov.<bw> @(%O2,%1),%0" 7570 [(set_attr "type" "load") 7571 (set_attr "length" "2,2,4")]) 7572 7573;; The order of the constraint alternatives is important here. 7574;; Q/r has to come first, otherwise PC relative loads might wrongly get 7575;; placed into delay slots. Since there is no QImode PC relative load, the 7576;; Q constraint and general_movsrc_operand will reject it for QImode. 7577;; The Sid/Ssd alternatives should come before Sdd in order to avoid 7578;; a preference of using r0 als the register operand for addressing modes 7579;; other than displacement addressing. 7580;; The Sdd alternatives allow only r0 as register operand, even though on 7581;; SH2A any register could be allowed by switching to a 32 bit insn. 7582;; Generally sticking to the r0 is preferrable, since it generates smaller 7583;; code. Obvious r0 reloads can then be eliminated with a peephole on SH2A. 7584(define_insn "*mov<mode>" 7585 [(set (match_operand:QIHI 0 "general_movdst_operand" 7586 "=r,r,r,Sid,^zr,Ssd,r, Sdd,z, r,l") 7587 (match_operand:QIHI 1 "general_movsrc_operand" 7588 "Q,r,i,^zr,Sid,r, Ssd,z, Sdd,l,r"))] 7589 "TARGET_SH1 7590 && (arith_reg_operand (operands[0], <MODE>mode) 7591 || arith_reg_operand (operands[1], <MODE>mode))" 7592 "@ 7593 mov.<bw> %1,%0 7594 mov %1,%0 7595 mov %1,%0 7596 mov.<bw> %1,%0 7597 mov.<bw> %1,%0 7598 mov.<bw> %1,%0 7599 mov.<bw> %1,%0 7600 mov.<bw> %1,%0 7601 mov.<bw> %1,%0 7602 sts %1,%0 7603 lds %1,%0" 7604 [(set_attr "type" "pcload,move,movi8,store,load,store,load,store,load,prget,prset") 7605 (set (attr "length") 7606 (cond [(and (match_operand 0 "displacement_mem_operand") 7607 (not (match_operand 0 "short_displacement_mem_operand"))) 7608 (const_int 4) 7609 (and (match_operand 1 "displacement_mem_operand") 7610 (not (match_operand 1 "short_displacement_mem_operand"))) 7611 (const_int 4)] 7612 (const_int 2)))]) 7613 7614(define_insn "*movqi_media" 7615 [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m") 7616 (match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))] 7617 "TARGET_SHMEDIA 7618 && (arith_reg_operand (operands[0], QImode) 7619 || extend_reg_or_0_operand (operands[1], QImode))" 7620 "@ 7621 add.l %1, r63, %0 7622 movi %1, %0 7623 ld%M1.ub %m1, %0 7624 st%M0.b %m0, %N1" 7625 [(set_attr "type" "arith_media,arith_media,load_media,store_media") 7626 (set (attr "highpart") 7627 (cond [(match_test "sh_contains_memref_p (insn)") 7628 (const_string "user")] 7629 (const_string "ignore")))]) 7630 7631(define_expand "reload_inqi" 7632 [(set (match_operand:SI 2 "" "=&r") 7633 (match_operand:QI 1 "inqhi_operand" "")) 7634 (set (match_operand:QI 0 "arith_reg_operand" "=r") 7635 (truncate:QI (match_dup 3)))] 7636 "TARGET_SHMEDIA" 7637{ 7638 rtx inner = XEXP (operands[1], 0); 7639 int regno = REGNO (inner); 7640 7641 regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1; 7642 operands[1] = gen_rtx_REG (SImode, regno); 7643 operands[3] = gen_rtx_REG (DImode, REGNO (operands[2])); 7644}) 7645 7646(define_insn "*movhi_media" 7647 [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m") 7648 (match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))] 7649 "TARGET_SHMEDIA 7650 && (arith_reg_operand (operands[0], HImode) 7651 || arith_reg_or_0_operand (operands[1], HImode))" 7652 "@ 7653 add.l %1, r63, %0 7654 movi %1, %0 7655 # 7656 ld%M1.w %m1, %0 7657 st%M0.w %m0, %N1" 7658 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media") 7659 (set (attr "highpart") 7660 (cond [(match_test "sh_contains_memref_p (insn)") 7661 (const_string "user")] 7662 (const_string "ignore")))]) 7663 7664(define_split 7665 [(set (match_operand:HI 0 "register_operand" "") 7666 (match_operand:HI 1 "immediate_operand" ""))] 7667 "TARGET_SHMEDIA && reload_completed 7668 && ! satisfies_constraint_I16 (operands[1])" 7669 [(set (subreg:DI (match_dup 0) 0) (match_dup 1))]) 7670 7671(define_expand "reload_inhi" 7672 [(set (match_operand:SI 2 "" "=&r") 7673 (match_operand:HI 1 "inqhi_operand" "")) 7674 (set (match_operand:HI 0 "arith_reg_operand" "=r") 7675 (truncate:HI (match_dup 3)))] 7676 "TARGET_SHMEDIA" 7677{ 7678 rtx inner = XEXP (operands[1], 0); 7679 int regno = REGNO (inner); 7680 7681 regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1; 7682 operands[1] = gen_rtx_REG (SImode, regno); 7683 operands[3] = gen_rtx_REG (DImode, REGNO (operands[2])); 7684}) 7685 7686;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c 7687;; compiled with -m2 -ml -O3 -funroll-loops 7688(define_insn "*movdi_i" 7689 [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x") 7690 (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))] 7691 "TARGET_SH1 7692 && (arith_reg_operand (operands[0], DImode) 7693 || arith_reg_operand (operands[1], DImode))" 7694{ 7695 return output_movedouble (insn, operands, DImode); 7696} 7697 [(set_attr "length" "4") 7698 (set_attr "type" "pcload,move,load,store,move,pcload,move,move")]) 7699 7700;; If the output is a register and the input is memory or a register, we have 7701;; to be careful and see which word needs to be loaded first. 7702(define_split 7703 [(set (match_operand:DI 0 "general_movdst_operand" "") 7704 (match_operand:DI 1 "general_movsrc_operand" ""))] 7705 "TARGET_SH1 && reload_completed" 7706 [(set (match_dup 2) (match_dup 3)) 7707 (set (match_dup 4) (match_dup 5))] 7708{ 7709 int regno; 7710 7711 if ((MEM_P (operands[0]) 7712 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) 7713 || (MEM_P (operands[1]) 7714 && GET_CODE (XEXP (operands[1], 0)) == POST_INC)) 7715 FAIL; 7716 7717 switch (GET_CODE (operands[0])) 7718 { 7719 case REG: 7720 regno = REGNO (operands[0]); 7721 break; 7722 case SUBREG: 7723 regno = subreg_regno (operands[0]); 7724 break; 7725 case MEM: 7726 regno = -1; 7727 break; 7728 default: 7729 gcc_unreachable (); 7730 } 7731 7732 if (regno == -1 || ! refers_to_regno_p (regno, operands[1])) 7733 { 7734 operands[2] = operand_subword (operands[0], 0, 0, DImode); 7735 operands[3] = operand_subword (operands[1], 0, 0, DImode); 7736 operands[4] = operand_subword (operands[0], 1, 0, DImode); 7737 operands[5] = operand_subword (operands[1], 1, 0, DImode); 7738 } 7739 else 7740 { 7741 operands[2] = operand_subword (operands[0], 1, 0, DImode); 7742 operands[3] = operand_subword (operands[1], 1, 0, DImode); 7743 operands[4] = operand_subword (operands[0], 0, 0, DImode); 7744 operands[5] = operand_subword (operands[1], 0, 0, DImode); 7745 } 7746 7747 if (operands[2] == 0 || operands[3] == 0 7748 || operands[4] == 0 || operands[5] == 0) 7749 FAIL; 7750}) 7751 7752;; The '?'s in the following constraints may not reflect the time taken 7753;; to perform the move. They are there to discourage the use of floating- 7754;; point registers for storing integer values. 7755(define_insn "*movdi_media" 7756 [(set (match_operand:DI 0 "general_movdst_operand" 7757 "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b") 7758 (match_operand:DI 1 "general_movsrc_operand" 7759 "r,I16Css,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))] 7760 "TARGET_SHMEDIA_FPU 7761 && (register_operand (operands[0], DImode) 7762 || sh_register_operand (operands[1], DImode))" 7763 "@ 7764 add %1, r63, %0 7765 movi %1, %0 7766 # 7767 ld%M1.q %m1, %0 7768 st%M0.q %m0, %N1 7769 fld%M1.d %m1, %0 7770 fst%M0.d %m0, %1 7771 fmov.qd %N1, %0 7772 fmov.dq %1, %0 7773 fmov.d %1, %0 7774 ptabs %1, %0 7775 gettr %1, %0 7776 pt %1, %0" 7777 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media, 7778 fload_media,fstore_media,fload_media,dfpconv_media, 7779 fmove_media,ptabs_media,gettr_media,pt_media") 7780 (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")]) 7781 7782(define_insn "*movdi_media_nofpu" 7783 [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b"); 7784 (match_operand:DI 1 "general_movsrc_operand" "r,I16Css,nCpgF,m,rlZ,r,*b,Csy"))] 7785 "TARGET_SHMEDIA 7786 && (register_operand (operands[0], DImode) 7787 || sh_register_operand (operands[1], DImode))" 7788 "@ 7789 add %1, r63, %0 7790 movi %1, %0 7791 # 7792 ld%M1.q %m1, %0 7793 st%M0.q %m0, %N1 7794 ptabs %1, %0 7795 gettr %1, %0 7796 pt %1, %0" 7797 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media, 7798 ptabs_media,gettr_media,pt_media") 7799 (set_attr "length" "4,4,16,4,4,4,4,*")]) 7800 7801(define_insn "*movdi_media_I16" 7802 [(set (match_operand:DI 0 "ext_dest_operand" "=r") 7803 (match_operand:DI 1 "const_int_operand" "I16"))] 7804 "TARGET_SHMEDIA && reload_completed" 7805 "movi %1, %0" 7806 [(set_attr "type" "arith_media") 7807 (set_attr "length" "4")]) 7808 7809(define_split 7810 [(set (match_operand:DI 0 "arith_reg_dest" "") 7811 (match_operand:DI 1 "immediate_operand" ""))] 7812 "TARGET_SHMEDIA && reload_completed 7813 && MOVI_SHORI_BASE_OPERAND_P (operands[1])" 7814 [(set (match_dup 0) (match_dup 1))] 7815{ 7816 rtx insn; 7817 7818 if (TARGET_SHMEDIA64) 7819 insn = emit_insn (gen_movdi_const (operands[0], operands[1])); 7820 else 7821 insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1])); 7822 7823 set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1])); 7824 7825 DONE; 7826}) 7827 7828(define_expand "movdi_const" 7829 [(set (match_operand:DI 0 "arith_reg_operand" "=r") 7830 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s") 7831 (const_int 48)] UNSPEC_EXTRACT_S16))) 7832 (set (match_dup 0) 7833 (ior:DI (ashift:DI (match_dup 0) (const_int 16)) 7834 (const:DI (unspec:DI [(match_dup 1) 7835 (const_int 32)] UNSPEC_EXTRACT_U16)))) 7836 (set (match_dup 0) 7837 (ior:DI (ashift:DI (match_dup 0) (const_int 16)) 7838 (const:DI (unspec:DI [(match_dup 1) 7839 (const_int 16)] UNSPEC_EXTRACT_U16)))) 7840 (set (match_dup 0) 7841 (ior:DI (ashift:DI (match_dup 0) (const_int 16)) 7842 (const:DI (unspec:DI [(match_dup 1) 7843 (const_int 0)] UNSPEC_EXTRACT_U16))))] 7844 "TARGET_SHMEDIA64 && reload_completed 7845 && MOVI_SHORI_BASE_OPERAND_P (operands[1])" 7846{ 7847 sh_mark_label (operands[1], 4); 7848}) 7849 7850(define_expand "movdi_const_32bit" 7851 [(set (match_operand:DI 0 "arith_reg_operand" "=r") 7852 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s") 7853 (const_int 16)] UNSPEC_EXTRACT_S16))) 7854 (set (match_dup 0) 7855 (ior:DI (ashift:DI (match_dup 0) (const_int 16)) 7856 (const:DI (unspec:DI [(match_dup 1) 7857 (const_int 0)] UNSPEC_EXTRACT_U16))))] 7858 "TARGET_SHMEDIA32 && reload_completed 7859 && MOVI_SHORI_BASE_OPERAND_P (operands[1])" 7860{ 7861 sh_mark_label (operands[1], 2); 7862}) 7863 7864(define_expand "movdi_const_16bit" 7865 [(set (match_operand:DI 0 "arith_reg_operand" "=r") 7866 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s") 7867 (const_int 0)] UNSPEC_EXTRACT_S16)))] 7868 "TARGET_SHMEDIA && flag_pic && reload_completed 7869 && GET_CODE (operands[1]) == SYMBOL_REF" 7870 "") 7871 7872(define_split 7873 [(set (match_operand:DI 0 "ext_dest_operand" "") 7874 (match_operand:DI 1 "immediate_operand" ""))] 7875 "TARGET_SHMEDIA && reload_completed 7876 && CONST_INT_P (operands[1]) 7877 && ! satisfies_constraint_I16 (operands[1])" 7878 [(set (match_dup 0) (match_dup 2)) 7879 (match_dup 1)] 7880{ 7881 unsigned HOST_WIDE_INT val = INTVAL (operands[1]); 7882 unsigned HOST_WIDE_INT low = val; 7883 unsigned HOST_WIDE_INT high = val; 7884 unsigned HOST_WIDE_INT sign; 7885 unsigned HOST_WIDE_INT val2 = val ^ (val-1); 7886 7887 /* Zero-extend the 16 least-significant bits. */ 7888 low &= 0xffff; 7889 7890 /* Arithmetic shift right the word by 16 bits. */ 7891 high >>= 16; 7892 if (GET_CODE (operands[0]) == SUBREG 7893 && GET_MODE (SUBREG_REG (operands[0])) == SImode) 7894 { 7895 high &= 0xffff; 7896 high ^= 0x8000; 7897 high -= 0x8000; 7898 } 7899 else 7900 { 7901 sign = 1; 7902 sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1); 7903 high ^= sign; 7904 high -= sign; 7905 } 7906 do 7907 { 7908 /* If we can't generate the constant with a two-insn movi / shori 7909 sequence, try some other strategies. */ 7910 if (! CONST_OK_FOR_I16 (high)) 7911 { 7912 /* Try constant load / left shift. We know VAL != 0. */ 7913 val2 = val ^ (val-1); 7914 if (val2 > 0x1ffff) 7915 { 7916 int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15; 7917 7918 if (CONST_OK_FOR_I16 (val >> trailing_zeroes) 7919 || (! CONST_OK_FOR_I16 (high >> 16) 7920 && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16)))) 7921 { 7922 val2 = (HOST_WIDE_INT) val >> trailing_zeroes; 7923 operands[1] = gen_ashldi3_media (operands[0], operands[0], 7924 GEN_INT (trailing_zeroes)); 7925 break; 7926 } 7927 } 7928 /* Try constant load / right shift. */ 7929 val2 = (val >> 15) + 1; 7930 if (val2 == (val2 & -val2)) 7931 { 7932 int shift = 49 - exact_log2 (val2); 7933 7934 val2 = trunc_int_for_mode (val << shift, DImode); 7935 if (CONST_OK_FOR_I16 (val2)) 7936 { 7937 operands[1] = gen_lshrdi3_media (operands[0], operands[0], 7938 GEN_INT (shift)); 7939 break; 7940 } 7941 } 7942 /* Try mperm.w . */ 7943 val2 = val & 0xffff; 7944 if ((val >> 16 & 0xffff) == val2 7945 && (val >> 32 & 0xffff) == val2 7946 && (val >> 48 & 0xffff) == val2) 7947 { 7948 val2 = (HOST_WIDE_INT) val >> 48; 7949 operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0])); 7950 operands[1] = gen_mperm_w0 (operands[1], operands[1]); 7951 break; 7952 } 7953 /* Try movi / mshflo.l */ 7954 val2 = (HOST_WIDE_INT) val >> 32; 7955 if (val2 == ((unsigned HOST_WIDE_INT) 7956 trunc_int_for_mode (val, SImode))) 7957 { 7958 operands[1] = gen_mshflo_l_di (operands[0], operands[0], 7959 operands[0]); 7960 break; 7961 } 7962 /* Try movi / mshflo.l w/ r63. */ 7963 val2 = val + ((HOST_WIDE_INT) (HOST_WIDE_INT_M1U << 32)); 7964 if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2)) 7965 { 7966 operands[1] = gen_mshflo_l_di (operands[0], operands[0], 7967 const0_rtx); 7968 break; 7969 } 7970 } 7971 val2 = high; 7972 operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low)); 7973 } 7974 while (0); 7975 operands[2] = GEN_INT (val2); 7976}) 7977 7978(define_split 7979 [(set (match_operand:DI 0 "ext_dest_operand" "") 7980 (match_operand:DI 1 "immediate_operand" ""))] 7981 "TARGET_SHMEDIA && reload_completed 7982 && GET_CODE (operands[1]) == CONST_DOUBLE" 7983 [(set (match_dup 0) (match_dup 2)) 7984 (set (match_dup 0) 7985 (ior:DI (ashift:DI (match_dup 0) (const_int 16)) (match_dup 1)))] 7986{ 7987 unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]); 7988 unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]); 7989 unsigned HOST_WIDE_INT val = low; 7990 unsigned HOST_WIDE_INT sign; 7991 7992 /* Zero-extend the 16 least-significant bits. */ 7993 val &= 0xffff; 7994 operands[1] = GEN_INT (val); 7995 7996 /* Arithmetic shift right the double-word by 16 bits. */ 7997 low >>= 16; 7998 low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16); 7999 high >>= 16; 8000 sign = 1; 8001 sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1); 8002 high ^= sign; 8003 high -= sign; 8004 8005 /* This will only be true if high is a sign-extension of low, i.e., 8006 it must be either 0 or (unsigned)-1, and be zero iff the 8007 most-significant bit of low is set. */ 8008 if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0) 8009 operands[2] = GEN_INT (low); 8010 else 8011 operands[2] = immed_double_const (low, high, DImode); 8012}) 8013 8014(define_insn "shori_media" 8015 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r") 8016 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0") 8017 (const_int 16)) 8018 (match_operand:DI 2 "immediate_operand" "K16Csu,nF")))] 8019 "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))" 8020 "@ 8021 shori %u2, %0 8022 #" 8023 [(set_attr "type" "arith_media,*")]) 8024 8025(define_insn "*shori_media_si" 8026 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 8027 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") 8028 (const_int 16)) 8029 (match_operand:SI 2 "immediate_operand" "K16Csu")))] 8030 "TARGET_SHMEDIA" 8031 "shori %u2, %0") 8032 8033(define_expand "movdi" 8034 [(set (match_operand:DI 0 "general_movdst_operand" "") 8035 (match_operand:DI 1 "general_movsrc_operand" ""))] 8036 "" 8037{ 8038 prepare_move_operands (operands, DImode); 8039 if (TARGET_SH1) 8040 { 8041 /* When the dest operand is (R0, R1) register pair, split it to 8042 two movsi of which dest is R1 and R0 so as to lower R0-register 8043 pressure on the first movsi. Apply only for simple source not 8044 to make complex rtl here. */ 8045 if (REG_P (operands[0]) 8046 && REGNO (operands[0]) == R0_REG 8047 && REG_P (operands[1]) 8048 && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER) 8049 { 8050 emit_insn (gen_movsi (gen_rtx_REG (SImode, R1_REG), 8051 gen_rtx_SUBREG (SImode, operands[1], 4))); 8052 emit_insn (gen_movsi (gen_rtx_REG (SImode, R0_REG), 8053 gen_rtx_SUBREG (SImode, operands[1], 0))); 8054 DONE; 8055 } 8056 } 8057}) 8058 8059(define_insn "movdf_media" 8060 [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m") 8061 (match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))] 8062 "TARGET_SHMEDIA_FPU 8063 && (register_operand (operands[0], DFmode) 8064 || sh_register_operand (operands[1], DFmode))" 8065 "@ 8066 fmov.d %1, %0 8067 fmov.qd %N1, %0 8068 fmov.dq %1, %0 8069 add %1, r63, %0 8070 # 8071 fld%M1.d %m1, %0 8072 fst%M0.d %m0, %1 8073 ld%M1.q %m1, %0 8074 st%M0.q %m0, %N1" 8075 [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*, 8076 fload_media,fstore_media,load_media,store_media")]) 8077 8078(define_insn "movdf_media_nofpu" 8079 [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m") 8080 (match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))] 8081 "TARGET_SHMEDIA 8082 && (register_operand (operands[0], DFmode) 8083 || sh_register_operand (operands[1], DFmode))" 8084 "@ 8085 add %1, r63, %0 8086 # 8087 ld%M1.q %m1, %0 8088 st%M0.q %m0, %N1" 8089 [(set_attr "type" "arith_media,*,load_media,store_media")]) 8090 8091(define_split 8092 [(set (match_operand:DF 0 "arith_reg_dest" "") 8093 (match_operand:DF 1 "immediate_operand" ""))] 8094 "TARGET_SHMEDIA && reload_completed" 8095 [(set (match_dup 3) (match_dup 2))] 8096{ 8097 int endian = WORDS_BIG_ENDIAN ? 1 : 0; 8098 long values[2]; 8099 8100 REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (operands[1]), values); 8101 8102 if (HOST_BITS_PER_WIDE_INT >= 64) 8103 operands[2] = immed_double_const ((unsigned long) values[endian] 8104 | ((HOST_WIDE_INT) values[1 - endian] 8105 << 32), 0, DImode); 8106 else 8107 { 8108 gcc_assert (HOST_BITS_PER_WIDE_INT == 32); 8109 operands[2] = immed_double_const (values[endian], values[1 - endian], 8110 DImode); 8111 } 8112 8113 operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0])); 8114}) 8115 8116;; FIXME: This should be a define_insn_and_split. 8117(define_insn "movdf_k" 8118 [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m") 8119 (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))] 8120 "TARGET_SH1 8121 && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed 8122 /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */ 8123 || (REG_P (operands[0]) && REGNO (operands[0]) == 3) 8124 || (REG_P (operands[1]) && REGNO (operands[1]) == 3)) 8125 && (arith_reg_operand (operands[0], DFmode) 8126 || arith_reg_operand (operands[1], DFmode))" 8127{ 8128 return output_movedouble (insn, operands, DFmode); 8129} 8130 [(set_attr "length" "4") 8131 (set_attr "type" "move,pcload,load,store")]) 8132 8133;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD. 8134;; However, the d/F/c/z alternative cannot be split directly; it is converted 8135;; with special code in machine_dependent_reorg into a load of the R0_REG and 8136;; the d/m/c/X alternative, which is split later into single-precision 8137;; instructions. And when not optimizing, no splits are done before fixing 8138;; up pcloads, so we need usable length information for that. 8139(define_insn "movdf_i4" 8140 [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d") 8141 (match_operand:DF 1 "general_movsrc_operand" "d,r,F,m,d,FQ,m,r,d,r")) 8142 (use (reg:SI FPSCR_MODES_REG)) 8143 (clobber (match_scratch:SI 2 "=X,X,&z,X,X,X,X,X,X,X"))] 8144 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) 8145 && (arith_reg_operand (operands[0], DFmode) 8146 || arith_reg_operand (operands[1], DFmode))" 8147 { 8148 switch (which_alternative) 8149 { 8150 case 0: 8151 if (TARGET_FMOVD) 8152 return "fmov %1,%0"; 8153 else if (REGNO (operands[0]) != REGNO (operands[1]) + 1) 8154 return "fmov %R1,%R0" "\n" 8155 " fmov %S1,%S0"; 8156 else 8157 return "fmov %S1,%S0" "\n" 8158 " fmov %R1,%R0"; 8159 case 3: 8160 case 4: 8161 return "fmov.d %1,%0"; 8162 default: 8163 return "#"; 8164 } 8165 } 8166 [(set_attr_alternative "length" 8167 [(if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 8)) 8168 (const_int 4) 8169 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6)) 8170 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6)) 8171 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6)) 8172 (const_int 4) 8173 (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn) 8174 ;; We can't use 4-byte push/pop on SHcompact, so we have to 8175 ;; increment or decrement r15 explicitly. 8176 (if_then_else 8177 (match_test "TARGET_SHCOMPACT") 8178 (const_int 10) (const_int 8)) 8179 (if_then_else 8180 (match_test "TARGET_SHCOMPACT") 8181 (const_int 10) (const_int 8))]) 8182 (set_attr "type" "fmove,move,pcfload,fload,fstore,pcload,load,store,load,fload") 8183 (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*") 8184 (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes") 8185 (const_string "double") 8186 (const_string "none")))]) 8187 8188;; Moving DFmode between fp/general registers through memory 8189;; (the top of the stack) is faster than moving through fpul even for 8190;; little endian. Because the type of an instruction is important for its 8191;; scheduling, it is beneficial to split these operations, rather than 8192;; emitting them in one single chunk, even if this will expose a stack 8193;; use that will prevent scheduling of other stack accesses beyond this 8194;; instruction. 8195(define_split 8196 [(set (match_operand:DF 0 "register_operand") 8197 (match_operand:DF 1 "register_operand")) 8198 (use (reg:SI FPSCR_MODES_REG)) 8199 (clobber (match_scratch:SI 2))] 8200 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed 8201 && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)" 8202 [(const_int 0)] 8203{ 8204 rtx insn, tos; 8205 8206 if (TARGET_SH5 && true_regnum (operands[1]) < 16) 8207 { 8208 emit_move_insn (stack_pointer_rtx, 8209 plus_constant (Pmode, stack_pointer_rtx, -8)); 8210 tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx); 8211 } 8212 else 8213 tos = gen_tmp_stack_mem (DFmode, 8214 gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx)); 8215 insn = emit_insn (gen_movdf_i4 (tos, operands[1])); 8216 if (! (TARGET_SH5 && true_regnum (operands[1]) < 16)) 8217 add_reg_note (insn, REG_INC, stack_pointer_rtx); 8218 if (TARGET_SH5 && true_regnum (operands[0]) < 16) 8219 tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx); 8220 else 8221 tos = gen_tmp_stack_mem (DFmode, 8222 gen_rtx_POST_INC (Pmode, stack_pointer_rtx)); 8223 insn = emit_insn (gen_movdf_i4 (operands[0], tos)); 8224 if (TARGET_SH5 && true_regnum (operands[0]) < 16) 8225 emit_move_insn (stack_pointer_rtx, 8226 plus_constant (Pmode, stack_pointer_rtx, 8)); 8227 else 8228 add_reg_note (insn, REG_INC, stack_pointer_rtx); 8229 DONE; 8230}) 8231 8232;; local-alloc sometimes allocates scratch registers even when not required, 8233;; so we must be prepared to handle these. 8234 8235;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k. 8236(define_split 8237 [(set (match_operand:DF 0 "general_movdst_operand" "") 8238 (match_operand:DF 1 "general_movsrc_operand" "")) 8239 (use (reg:SI FPSCR_MODES_REG)) 8240 (clobber (match_scratch:SI 2))] 8241 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) 8242 && reload_completed 8243 && true_regnum (operands[0]) < 16 8244 && true_regnum (operands[1]) < 16" 8245 [(set (match_dup 0) (match_dup 1))] 8246{ 8247 /* If this was a reg <-> mem operation with base + index reg addressing, 8248 we have to handle this in a special way. */ 8249 rtx mem = operands[0]; 8250 int store_p = 1; 8251 if (! memory_operand (mem, DFmode)) 8252 { 8253 mem = operands[1]; 8254 store_p = 0; 8255 } 8256 if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0) 8257 mem = SUBREG_REG (mem); 8258 if (MEM_P (mem)) 8259 { 8260 rtx addr = XEXP (mem, 0); 8261 if (GET_CODE (addr) == PLUS 8262 && REG_P (XEXP (addr, 0)) 8263 && REG_P (XEXP (addr, 1))) 8264 { 8265 int offset; 8266 rtx reg0 = gen_rtx_REG (Pmode, 0); 8267 rtx regop = operands[store_p], word0 ,word1; 8268 8269 if (GET_CODE (regop) == SUBREG) 8270 alter_subreg (®op, true); 8271 if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1))) 8272 offset = 2; 8273 else 8274 offset = 4; 8275 mem = copy_rtx (mem); 8276 PUT_MODE (mem, SImode); 8277 word0 = gen_rtx_SUBREG (SImode, regop, 0); 8278 alter_subreg (&word0, true); 8279 word1 = gen_rtx_SUBREG (SImode, regop, 4); 8280 alter_subreg (&word1, true); 8281 if (store_p || ! refers_to_regno_p (REGNO (word0), addr)) 8282 { 8283 emit_insn (store_p 8284 ? gen_movsi_ie (mem, word0) 8285 : gen_movsi_ie (word0, mem)); 8286 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset))); 8287 mem = copy_rtx (mem); 8288 emit_insn (store_p 8289 ? gen_movsi_ie (mem, word1) 8290 : gen_movsi_ie (word1, mem)); 8291 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset))); 8292 } 8293 else 8294 { 8295 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset))); 8296 emit_insn (gen_movsi_ie (word1, mem)); 8297 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset))); 8298 mem = copy_rtx (mem); 8299 emit_insn (gen_movsi_ie (word0, mem)); 8300 } 8301 DONE; 8302 } 8303 } 8304}) 8305 8306;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads. 8307(define_split 8308 [(set (match_operand:DF 0 "register_operand" "") 8309 (match_operand:DF 1 "memory_operand" "")) 8310 (use (reg:SI FPSCR_MODES_REG)) 8311 (clobber (reg:SI R0_REG))] 8312 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed" 8313 [(parallel [(set (match_dup 0) (match_dup 1)) 8314 (use (reg:SI FPSCR_MODES_REG)) 8315 (clobber (scratch:SI))])] 8316 "") 8317 8318(define_expand "reload_indf__frn" 8319 [(parallel [(set (match_operand:DF 0 "register_operand" "=a") 8320 (match_operand:DF 1 "immediate_operand" "FQ")) 8321 (use (reg:SI FPSCR_MODES_REG)) 8322 (clobber (match_operand:SI 2 "register_operand" "=&z"))])] 8323 "TARGET_SH1" 8324 "") 8325 8326(define_expand "reload_outdf__RnFRm" 8327 [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f") 8328 (match_operand:DF 1 "register_operand" "af,r")) 8329 (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])] 8330 "TARGET_SH1" 8331 "") 8332 8333;; Simplify no-op moves. 8334(define_split 8335 [(set (match_operand:SF 0 "register_operand" "") 8336 (match_operand:SF 1 "register_operand" "")) 8337 (use (reg:SI FPSCR_MODES_REG)) 8338 (clobber (match_scratch:SI 2))] 8339 "TARGET_SH2E && reload_completed 8340 && true_regnum (operands[0]) == true_regnum (operands[1])" 8341 [(set (match_dup 0) (match_dup 0))] 8342 "") 8343 8344;; fmovd substitute post-reload splits 8345(define_split 8346 [(set (match_operand:DF 0 "register_operand" "") 8347 (match_operand:DF 1 "register_operand" "")) 8348 (use (reg:SI FPSCR_MODES_REG)) 8349 (clobber (match_scratch:SI 2))] 8350 "TARGET_SH4 && ! TARGET_FMOVD && reload_completed 8351 && FP_OR_XD_REGISTER_P (true_regnum (operands[0])) 8352 && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))" 8353 [(const_int 0)] 8354{ 8355 int dst = true_regnum (operands[0]), src = true_regnum (operands[1]); 8356 emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst), 8357 gen_rtx_REG (SFmode, src))); 8358 emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1), 8359 gen_rtx_REG (SFmode, src + 1))); 8360 DONE; 8361}) 8362 8363(define_split 8364 [(set (match_operand:DF 0 "register_operand" "") 8365 (mem:DF (match_operand:SI 1 "register_operand" ""))) 8366 (use (reg:SI FPSCR_MODES_REG)) 8367 (clobber (match_scratch:SI 2))] 8368 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed 8369 && FP_OR_XD_REGISTER_P (true_regnum (operands[0])) 8370 && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))" 8371 [(const_int 0)] 8372{ 8373 int regno = true_regnum (operands[0]); 8374 rtx insn; 8375 rtx mem = SET_SRC (XVECEXP (PATTERN (curr_insn), 0, 0)); 8376 rtx mem2 8377 = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1])); 8378 insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, 8379 regno + SH_REG_MSW_OFFSET), 8380 mem2)); 8381 add_reg_note (insn, REG_INC, operands[1]); 8382 insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, 8383 regno + SH_REG_LSW_OFFSET), 8384 change_address (mem, SFmode, NULL_RTX))); 8385 DONE; 8386}) 8387 8388(define_split 8389 [(set (match_operand:DF 0 "register_operand" "") 8390 (match_operand:DF 1 "memory_operand" "")) 8391 (use (reg:SI FPSCR_MODES_REG)) 8392 (clobber (match_scratch:SI 2))] 8393 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed 8394 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))" 8395 [(const_int 0)] 8396{ 8397 int regno = true_regnum (operands[0]); 8398 rtx addr, insn; 8399 rtx mem2 = change_address (operands[1], SFmode, NULL_RTX); 8400 rtx reg0 = gen_rtx_REG (SFmode, regno + SH_REG_MSW_OFFSET); 8401 rtx reg1 = gen_rtx_REG (SFmode, regno + SH_REG_LSW_OFFSET); 8402 8403 operands[1] = copy_rtx (mem2); 8404 addr = XEXP (mem2, 0); 8405 8406 switch (GET_CODE (addr)) 8407 { 8408 case REG: 8409 /* This is complicated. If the register is an arithmetic register 8410 we can just fall through to the REG+DISP case below. Otherwise 8411 we have to use a combination of POST_INC and REG addressing... */ 8412 if (! arith_reg_operand (operands[1], SFmode)) 8413 { 8414 XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr); 8415 insn = emit_insn (gen_movsf_ie (reg0, mem2)); 8416 add_reg_note (insn, REG_INC, XEXP (addr, 0)); 8417 8418 emit_insn (gen_movsf_ie (reg1, operands[1])); 8419 8420 /* If we have modified the stack pointer, the value that we have 8421 read with post-increment might be modified by an interrupt, 8422 so write it back. */ 8423 if (REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM) 8424 emit_insn (gen_push_e (reg0)); 8425 else 8426 emit_insn (gen_addsi3 (XEXP (operands[1], 0), XEXP (operands[1], 0), 8427 GEN_INT (-4))); 8428 break; 8429 } 8430 /* Fall through. */ 8431 8432 case PLUS: 8433 emit_insn (gen_movsf_ie (reg0, operands[1])); 8434 operands[1] = copy_rtx (operands[1]); 8435 XEXP (operands[1], 0) = plus_constant (Pmode, addr, 4); 8436 emit_insn (gen_movsf_ie (reg1, operands[1])); 8437 break; 8438 8439 case POST_INC: 8440 insn = emit_insn (gen_movsf_ie (reg0, operands[1])); 8441 add_reg_note (insn, REG_INC, XEXP (addr, 0)); 8442 8443 insn = emit_insn (gen_movsf_ie (reg1, operands[1])); 8444 add_reg_note (insn, REG_INC, XEXP (addr, 0)); 8445 break; 8446 8447 default: 8448 debug_rtx (addr); 8449 gcc_unreachable (); 8450 } 8451 8452 DONE; 8453}) 8454 8455(define_split 8456 [(set (match_operand:DF 0 "memory_operand" "") 8457 (match_operand:DF 1 "register_operand" "")) 8458 (use (reg:SI FPSCR_MODES_REG)) 8459 (clobber (match_scratch:SI 2))] 8460 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed 8461 && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))" 8462 [(const_int 0)] 8463{ 8464 int regno = true_regnum (operands[1]); 8465 rtx insn, addr; 8466 rtx reg0 = gen_rtx_REG (SFmode, regno + SH_REG_MSW_OFFSET); 8467 rtx reg1 = gen_rtx_REG (SFmode, regno + SH_REG_LSW_OFFSET); 8468 8469 operands[0] = copy_rtx (operands[0]); 8470 PUT_MODE (operands[0], SFmode); 8471 addr = XEXP (operands[0], 0); 8472 8473 switch (GET_CODE (addr)) 8474 { 8475 case REG: 8476 /* This is complicated. If the register is an arithmetic register 8477 we can just fall through to the REG+DISP case below. Otherwise 8478 we have to use a combination of REG and PRE_DEC addressing... */ 8479 if (! arith_reg_operand (operands[0], SFmode)) 8480 { 8481 emit_insn (gen_addsi3 (addr, addr, GEN_INT (4))); 8482 emit_insn (gen_movsf_ie (operands[0], reg1)); 8483 8484 operands[0] = copy_rtx (operands[0]); 8485 XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr); 8486 8487 insn = emit_insn (gen_movsf_ie (operands[0], reg0)); 8488 add_reg_note (insn, REG_INC, XEXP (addr, 0)); 8489 break; 8490 } 8491 /* Fall through. */ 8492 8493 case PLUS: 8494 /* Since REG+DISP addressing has already been decided upon by gcc 8495 we can rely upon it having chosen an arithmetic register as the 8496 register component of the address. Just emit the lower numbered 8497 register first, to the lower address, then the higher numbered 8498 register to the higher address. */ 8499 emit_insn (gen_movsf_ie (operands[0], reg0)); 8500 8501 operands[0] = copy_rtx (operands[0]); 8502 XEXP (operands[0], 0) = plus_constant (Pmode, addr, 4); 8503 8504 emit_insn (gen_movsf_ie (operands[0], reg1)); 8505 break; 8506 8507 case PRE_DEC: 8508 /* This is easy. Output the word to go to the higher address 8509 first (ie the word in the higher numbered register) then the 8510 word to go to the lower address. */ 8511 8512 insn = emit_insn (gen_movsf_ie (operands[0], reg1)); 8513 add_reg_note (insn, REG_INC, XEXP (addr, 0)); 8514 8515 insn = emit_insn (gen_movsf_ie (operands[0], reg0)); 8516 add_reg_note (insn, REG_INC, XEXP (addr, 0)); 8517 break; 8518 8519 default: 8520 /* FAIL; */ 8521 debug_rtx (addr); 8522 gcc_unreachable (); 8523 } 8524 8525 DONE; 8526}) 8527 8528;; If the output is a register and the input is memory or a register, we have 8529;; to be careful and see which word needs to be loaded first. 8530(define_split 8531 [(set (match_operand:DF 0 "general_movdst_operand" "") 8532 (match_operand:DF 1 "general_movsrc_operand" ""))] 8533 "TARGET_SH1 && reload_completed" 8534 [(set (match_dup 2) (match_dup 3)) 8535 (set (match_dup 4) (match_dup 5))] 8536{ 8537 int regno; 8538 8539 if ((MEM_P (operands[0]) 8540 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) 8541 || (MEM_P (operands[1]) 8542 && GET_CODE (XEXP (operands[1], 0)) == POST_INC)) 8543 FAIL; 8544 8545 switch (GET_CODE (operands[0])) 8546 { 8547 case REG: 8548 regno = REGNO (operands[0]); 8549 break; 8550 case SUBREG: 8551 regno = subreg_regno (operands[0]); 8552 break; 8553 case MEM: 8554 regno = -1; 8555 break; 8556 default: 8557 gcc_unreachable (); 8558 } 8559 8560 if (regno == -1 || ! refers_to_regno_p (regno, operands[1])) 8561 { 8562 operands[2] = operand_subword (operands[0], 0, 0, DFmode); 8563 operands[3] = operand_subword (operands[1], 0, 0, DFmode); 8564 operands[4] = operand_subword (operands[0], 1, 0, DFmode); 8565 operands[5] = operand_subword (operands[1], 1, 0, DFmode); 8566 } 8567 else 8568 { 8569 operands[2] = operand_subword (operands[0], 1, 0, DFmode); 8570 operands[3] = operand_subword (operands[1], 1, 0, DFmode); 8571 operands[4] = operand_subword (operands[0], 0, 0, DFmode); 8572 operands[5] = operand_subword (operands[1], 0, 0, DFmode); 8573 } 8574 8575 if (operands[2] == 0 || operands[3] == 0 8576 || operands[4] == 0 || operands[5] == 0) 8577 FAIL; 8578}) 8579 8580(define_expand "movdf" 8581 [(set (match_operand:DF 0 "general_movdst_operand" "") 8582 (match_operand:DF 1 "general_movsrc_operand" ""))] 8583 "" 8584{ 8585 prepare_move_operands (operands, DFmode); 8586 if (TARGET_SHMEDIA) 8587 { 8588 if (TARGET_SHMEDIA_FPU) 8589 emit_insn (gen_movdf_media (operands[0], operands[1])); 8590 else 8591 emit_insn (gen_movdf_media_nofpu (operands[0], operands[1])); 8592 DONE; 8593 } 8594 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 8595 { 8596 emit_insn (gen_movdf_i4 (operands[0], operands[1])); 8597 DONE; 8598 } 8599}) 8600 8601;;This is incompatible with the way gcc uses subregs. 8602;;(define_insn "movv2sf_i" 8603;; [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m") 8604;; (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))] 8605;; "TARGET_SHMEDIA_FPU 8606;; && (fp_arith_reg_operand (operands[0], V2SFmode) 8607;; || fp_arith_reg_operand (operands[1], V2SFmode))" 8608;; "@ 8609;; # 8610;; fld%M1.p %m1, %0 8611;; fst%M0.p %m0, %1" 8612;; [(set_attr "type" "*,fload_media,fstore_media")]) 8613(define_insn_and_split "movv2sf_i" 8614 [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf") 8615 (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))] 8616 "TARGET_SHMEDIA_FPU" 8617 "#" 8618 "TARGET_SHMEDIA_FPU && reload_completed" 8619 [(set (match_dup 0) (match_dup 1))] 8620{ 8621 operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0); 8622 operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0); 8623}) 8624 8625(define_expand "movv2sf" 8626 [(set (match_operand:V2SF 0 "general_movdst_operand" "") 8627 (match_operand:V2SF 1 "nonimmediate_operand" ""))] 8628 "TARGET_SHMEDIA_FPU" 8629{ 8630 prepare_move_operands (operands, V2SFmode); 8631}) 8632 8633(define_expand "addv2sf3" 8634 [(match_operand:V2SF 0 "fp_arith_reg_operand" "") 8635 (match_operand:V2SF 1 "fp_arith_reg_operand" "") 8636 (match_operand:V2SF 2 "fp_arith_reg_operand" "")] 8637 "TARGET_SHMEDIA_FPU" 8638{ 8639 sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]); 8640 DONE; 8641}) 8642 8643(define_expand "subv2sf3" 8644 [(match_operand:V2SF 0 "fp_arith_reg_operand" "") 8645 (match_operand:V2SF 1 "fp_arith_reg_operand" "") 8646 (match_operand:V2SF 2 "fp_arith_reg_operand" "")] 8647 "TARGET_SHMEDIA_FPU" 8648{ 8649 sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]); 8650 DONE; 8651}) 8652 8653(define_expand "mulv2sf3" 8654 [(match_operand:V2SF 0 "fp_arith_reg_operand" "") 8655 (match_operand:V2SF 1 "fp_arith_reg_operand" "") 8656 (match_operand:V2SF 2 "fp_arith_reg_operand" "")] 8657 "TARGET_SHMEDIA_FPU" 8658{ 8659 sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]); 8660 DONE; 8661}) 8662 8663(define_expand "divv2sf3" 8664 [(match_operand:V2SF 0 "fp_arith_reg_operand" "") 8665 (match_operand:V2SF 1 "fp_arith_reg_operand" "") 8666 (match_operand:V2SF 2 "fp_arith_reg_operand" "")] 8667 "TARGET_SHMEDIA_FPU" 8668{ 8669 sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]); 8670 DONE; 8671}) 8672 8673(define_insn_and_split "*movv4sf_i" 8674 [(set (match_operand:V4SF 0 "general_movdst_operand" "=f,rf,r,m,mf") 8675 (match_operand:V4SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))] 8676 "TARGET_SHMEDIA_FPU" 8677 "#" 8678 "&& reload_completed" 8679 [(const_int 0)] 8680{ 8681 for (int i = 0; i < 4/2; i++) 8682 { 8683 rtx x, y; 8684 8685 if (MEM_P (operands[0])) 8686 x = adjust_address (operands[0], V2SFmode, 8687 i * GET_MODE_SIZE (V2SFmode)); 8688 else 8689 x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8); 8690 8691 if (MEM_P (operands[1])) 8692 y = adjust_address (operands[1], V2SFmode, 8693 i * GET_MODE_SIZE (V2SFmode)); 8694 else 8695 y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8); 8696 8697 emit_insn (gen_movv2sf_i (x, y)); 8698 } 8699 8700 DONE; 8701} 8702 [(set_attr "length" "8")]) 8703 8704(define_expand "movv4sf" 8705 [(set (match_operand:V4SF 0 "nonimmediate_operand" "") 8706 (match_operand:V4SF 1 "general_operand" ""))] 8707 "TARGET_SHMEDIA_FPU" 8708{ 8709 prepare_move_operands (operands, V4SFmode); 8710}) 8711 8712(define_insn_and_split "*movv16sf_i" 8713 [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m") 8714 (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))] 8715 "TARGET_SHMEDIA_FPU" 8716 "#" 8717 "&& reload_completed" 8718 [(const_int 0)] 8719{ 8720 for (int i = 0; i < 16/2; i++) 8721 { 8722 rtx x, y; 8723 8724 if (MEM_P (operands[0])) 8725 x = adjust_address (operands[0], V2SFmode, 8726 i * GET_MODE_SIZE (V2SFmode)); 8727 else 8728 { 8729 x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8); 8730 alter_subreg (&x, true); 8731 } 8732 8733 if (MEM_P (operands[1])) 8734 y = adjust_address (operands[1], V2SFmode, 8735 i * GET_MODE_SIZE (V2SFmode)); 8736 else 8737 { 8738 y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8); 8739 alter_subreg (&y, true); 8740 } 8741 8742 emit_insn (gen_movv2sf_i (x, y)); 8743 } 8744 8745 DONE; 8746} 8747 [(set_attr "length" "32")]) 8748 8749(define_expand "movv16sf" 8750 [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m") 8751 (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))] 8752 "TARGET_SHMEDIA_FPU" 8753{ 8754 prepare_move_operands (operands, V16SFmode); 8755}) 8756 8757(define_insn "movsf_media" 8758 [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m") 8759 (match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))] 8760 "TARGET_SHMEDIA_FPU 8761 && (register_operand (operands[0], SFmode) 8762 || sh_register_operand (operands[1], SFmode))" 8763 "@ 8764 fmov.s %1, %0 8765 fmov.ls %N1, %0 8766 fmov.sl %1, %0 8767 add.l %1, r63, %0 8768 # 8769 fld%M1.s %m1, %0 8770 fst%M0.s %m0, %1 8771 ld%M1.l %m1, %0 8772 st%M0.l %m0, %N1" 8773 [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media") 8774 (set (attr "highpart") 8775 (cond [(match_test "sh_contains_memref_p (insn)") 8776 (const_string "user")] 8777 (const_string "ignore")))]) 8778 8779(define_insn "movsf_media_nofpu" 8780 [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m") 8781 (match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))] 8782 "TARGET_SHMEDIA 8783 && (register_operand (operands[0], SFmode) 8784 || sh_register_operand (operands[1], SFmode))" 8785 "@ 8786 add.l %1, r63, %0 8787 # 8788 ld%M1.l %m1, %0 8789 st%M0.l %m0, %N1" 8790 [(set_attr "type" "arith_media,*,load_media,store_media") 8791 (set (attr "highpart") 8792 (cond [(match_test "sh_contains_memref_p (insn)") 8793 (const_string "user")] 8794 (const_string "ignore")))]) 8795 8796(define_split 8797 [(set (match_operand:SF 0 "arith_reg_dest" "") 8798 (match_operand:SF 1 "immediate_operand" ""))] 8799 "TARGET_SHMEDIA && reload_completed 8800 && ! FP_REGISTER_P (true_regnum (operands[0]))" 8801 [(set (match_dup 3) (match_dup 2))] 8802{ 8803 long values; 8804 8805 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (operands[1]), values); 8806 operands[2] = GEN_INT (values); 8807 8808 operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0])); 8809}) 8810 8811(define_insn "movsf_i" 8812 [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r") 8813 (match_operand:SF 1 "general_movsrc_operand" "r,G,FQ,mr,r,r,l"))] 8814 "TARGET_SH1 8815 && (! TARGET_SH2E 8816 /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */ 8817 || (REG_P (operands[0]) && REGNO (operands[0]) == 3) 8818 || (REG_P (operands[1]) && REGNO (operands[1]) == 3)) 8819 && (arith_reg_operand (operands[0], SFmode) 8820 || arith_reg_operand (operands[1], SFmode))" 8821 "@ 8822 mov %1,%0 8823 mov #0,%0 8824 mov.l %1,%0 8825 mov.l %1,%0 8826 mov.l %1,%0 8827 lds %1,%0 8828 sts %1,%0" 8829 [(set_attr "type" "move,move,pcload,load,store,move,move")]) 8830 8831;; We may not split the ry/yr/XX alternatives to movsi_ie, since 8832;; update_flow_info would not know where to put REG_EQUAL notes 8833;; when the destination changes mode. 8834(define_insn "movsf_ie" 8835 [(set (match_operand:SF 0 "general_movdst_operand" 8836 "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y") 8837 (match_operand:SF 1 "general_movsrc_operand" 8838 "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y")) 8839 (use (reg:SI FPSCR_MODES_REG)) 8840 (clobber (match_scratch:SI 2 "=X,X,X,X,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))] 8841 "TARGET_SH2E 8842 && (arith_reg_operand (operands[0], SFmode) || fpul_operand (operands[0], SFmode) 8843 || arith_reg_operand (operands[1], SFmode) || fpul_operand (operands[1], SFmode) 8844 || arith_reg_operand (operands[2], SImode))" 8845 "@ 8846 fmov %1,%0 8847 mov %1,%0 8848 fldi0 %0 8849 fldi1 %0 8850 # 8851 fmov.s %1,%0 8852 fmov.s %1,%0 8853 mov.l %1,%0 8854 mov.l %1,%0 8855 mov.l %1,%0 8856 fsts fpul,%0 8857 flds %1,fpul 8858 lds.l %1,%0 8859 # 8860 sts %1,%0 8861 lds %1,%0 8862 sts.l %1,%0 8863 lds.l %1,%0 8864 ! move optimized away" 8865 [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load, 8866 store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil") 8867 (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*") 8868 (set_attr_alternative "length" 8869 [(const_int 2) 8870 (const_int 2) 8871 (const_int 2) 8872 (const_int 2) 8873 (const_int 4) 8874 (if_then_else 8875 (match_test "TARGET_SH2A") 8876 (const_int 4) (const_int 2)) 8877 (if_then_else 8878 (match_test "TARGET_SH2A") 8879 (const_int 4) (const_int 2)) 8880 (const_int 2) 8881 (if_then_else 8882 (match_test "TARGET_SH2A") 8883 (const_int 4) (const_int 2)) 8884 (if_then_else 8885 (match_test "TARGET_SH2A") 8886 (const_int 4) (const_int 2)) 8887 (const_int 2) 8888 (const_int 2) 8889 (const_int 2) 8890 (const_int 4) 8891 (const_int 2) 8892 (const_int 2) 8893 (const_int 2) 8894 (const_int 2) 8895 (const_int 0)]) 8896 (set_attr_alternative "fp_mode" 8897 [(if_then_else (eq_attr "fmovd" "yes") 8898 (const_string "single") (const_string "none")) 8899 (const_string "none") 8900 (const_string "single") 8901 (const_string "single") 8902 (const_string "none") 8903 (if_then_else (eq_attr "fmovd" "yes") 8904 (const_string "single") (const_string "none")) 8905 (if_then_else (eq_attr "fmovd" "yes") 8906 (const_string "single") (const_string "none")) 8907 (const_string "none") 8908 (const_string "none") 8909 (const_string "none") 8910 (const_string "none") 8911 (const_string "none") 8912 (const_string "none") 8913 (const_string "none") 8914 (const_string "none") 8915 (const_string "none") 8916 (const_string "none") 8917 (const_string "none") 8918 (const_string "none")])]) 8919 8920(define_insn_and_split "movsf_ie_ra" 8921 [(set (match_operand:SF 0 "general_movdst_operand" 8922 "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y") 8923 (match_operand:SF 1 "general_movsrc_operand" 8924 "f,r,G,H,FQ,m,f,FQ,m,r,y,f,>,fr,y,r,y,>,y")) 8925 (use (reg:SI FPSCR_MODES_REG)) 8926 (clobber (match_scratch:SF 2 "=r,r,X,X,&z,r,r,X,r,r,r,r,r,y,r,r,r,r,r")) 8927 (const_int 0)] 8928 "TARGET_SH2E 8929 && (arith_reg_operand (operands[0], SFmode) 8930 || fpul_operand (operands[0], SFmode) 8931 || arith_reg_operand (operands[1], SFmode) 8932 || fpul_operand (operands[1], SFmode))" 8933 "@ 8934 fmov %1,%0 8935 mov %1,%0 8936 fldi0 %0 8937 fldi1 %0 8938 # 8939 fmov.s %1,%0 8940 fmov.s %1,%0 8941 mov.l %1,%0 8942 mov.l %1,%0 8943 mov.l %1,%0 8944 fsts fpul,%0 8945 flds %1,fpul 8946 lds.l %1,%0 8947 # 8948 sts %1,%0 8949 lds %1,%0 8950 sts.l %1,%0 8951 lds.l %1,%0 8952 ! move optimized away" 8953 "reload_completed 8954 && sh_movsf_ie_ra_split_p (operands[0], operands[1], operands[2])" 8955 [(const_int 0)] 8956{ 8957 if (! rtx_equal_p (operands[0], operands[1])) 8958 { 8959 emit_insn (gen_movsf_ie (operands[2], operands[1])); 8960 emit_insn (gen_movsf_ie (operands[0], operands[2])); 8961 } 8962} 8963 [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load, 8964 store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil") 8965 (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*") 8966 (set_attr_alternative "length" 8967 [(const_int 2) 8968 (const_int 2) 8969 (const_int 2) 8970 (const_int 2) 8971 (const_int 4) 8972 (if_then_else 8973 (match_test "TARGET_SH2A") 8974 (const_int 4) (const_int 2)) 8975 (if_then_else 8976 (match_test "TARGET_SH2A") 8977 (const_int 4) (const_int 2)) 8978 (const_int 2) 8979 (if_then_else 8980 (match_test "TARGET_SH2A") 8981 (const_int 4) (const_int 2)) 8982 (if_then_else 8983 (match_test "TARGET_SH2A") 8984 (const_int 4) (const_int 2)) 8985 (const_int 2) 8986 (const_int 2) 8987 (const_int 2) 8988 (const_int 4) 8989 (const_int 2) 8990 (const_int 2) 8991 (const_int 2) 8992 (const_int 2) 8993 (const_int 0)]) 8994 (set_attr_alternative "fp_mode" 8995 [(if_then_else (eq_attr "fmovd" "yes") 8996 (const_string "single") (const_string "none")) 8997 (const_string "none") 8998 (const_string "single") 8999 (const_string "single") 9000 (const_string "none") 9001 (if_then_else (eq_attr "fmovd" "yes") 9002 (const_string "single") (const_string "none")) 9003 (if_then_else (eq_attr "fmovd" "yes") 9004 (const_string "single") (const_string "none")) 9005 (const_string "none") 9006 (const_string "none") 9007 (const_string "none") 9008 (const_string "none") 9009 (const_string "none") 9010 (const_string "none") 9011 (const_string "none") 9012 (const_string "none") 9013 (const_string "none") 9014 (const_string "none") 9015 (const_string "none") 9016 (const_string "none")])]) 9017 9018(define_split 9019 [(set (match_operand:SF 0 "register_operand" "") 9020 (match_operand:SF 1 "register_operand" "")) 9021 (use (reg:SI FPSCR_MODES_REG)) 9022 (clobber (reg:SI FPUL_REG))] 9023 "TARGET_SH1" 9024 [(parallel [(set (reg:SF FPUL_REG) (match_dup 1)) 9025 (use (reg:SI FPSCR_MODES_REG)) 9026 (clobber (scratch:SI))]) 9027 (parallel [(set (match_dup 0) (reg:SF FPUL_REG)) 9028 (use (reg:SI FPSCR_MODES_REG)) 9029 (clobber (scratch:SI))])] 9030 "") 9031 9032(define_expand "movsf" 9033 [(set (match_operand:SF 0 "general_movdst_operand" "") 9034 (match_operand:SF 1 "general_movsrc_operand" ""))] 9035 "" 9036{ 9037 prepare_move_operands (operands, SFmode); 9038 if (TARGET_SHMEDIA) 9039 { 9040 if (TARGET_SHMEDIA_FPU) 9041 emit_insn (gen_movsf_media (operands[0], operands[1])); 9042 else 9043 emit_insn (gen_movsf_media_nofpu (operands[0], operands[1])); 9044 DONE; 9045 } 9046 if (TARGET_SH2E) 9047 { 9048 if (lra_in_progress) 9049 { 9050 if (GET_CODE (operands[0]) == SCRATCH) 9051 DONE; 9052 emit_insn (gen_movsf_ie_ra (operands[0], operands[1])); 9053 DONE; 9054 } 9055 9056 emit_insn (gen_movsf_ie (operands[0], operands[1])); 9057 DONE; 9058 } 9059}) 9060 9061(define_insn "mov_nop" 9062 [(set (match_operand 0 "any_register_operand" "") (match_dup 0))] 9063 "TARGET_SH2E" 9064 "" 9065 [(set_attr "length" "0") 9066 (set_attr "type" "nil")]) 9067 9068(define_expand "reload_insf__frn" 9069 [(parallel [(set (match_operand:SF 0 "register_operand" "=a") 9070 (match_operand:SF 1 "immediate_operand" "FQ")) 9071 (use (reg:SI FPSCR_MODES_REG)) 9072 (clobber (match_operand:SI 2 "register_operand" "=&z"))])] 9073 "TARGET_SH1" 9074 "") 9075 9076(define_expand "reload_insi__i_fpul" 9077 [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y") 9078 (match_operand:SI 1 "immediate_operand" "i")) 9079 (clobber (match_operand:SI 2 "register_operand" "=&z"))])] 9080 "TARGET_SH1" 9081 "") 9082 9083(define_expand "ptabs" 9084 [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))] 9085 "TARGET_SHMEDIA" 9086{ 9087 if (!TARGET_PT_FIXED) 9088 { 9089 rtx eq = operands[1]; 9090 9091 /* ??? For canonical RTL we really should remove any CONST from EQ 9092 before wrapping it in the AND, and finally wrap the EQ into a 9093 const if is constant. However, for reload we must expose the 9094 input register or symbolic constant, and we can't have 9095 different insn structures outside of the operands for different 9096 alternatives of the same pattern. */ 9097 eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)), 9098 GEN_INT (3)); 9099 operands[1] 9100 = (gen_rtx_IF_THEN_ELSE 9101 (PDImode, 9102 eq, 9103 gen_rtx_MEM (PDImode, operands[1]), 9104 gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE, 9105 PDImode, operands[1]))); 9106 } 9107}) 9108 9109;; expanded by ptabs expander. 9110(define_insn "*extendsipdi_media" 9111 [(set (match_operand:PDI 0 "target_reg_operand" "=b,b"); 9112 (if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand" 9113 "r,Csy") 9114 (const_int 3)) 9115 (const_int 3)) 9116 (mem:PDI (match_dup 1)) 9117 (sign_extend:PDI (match_dup 1))))] 9118 "TARGET_SHMEDIA && !TARGET_PT_FIXED" 9119 "@ 9120 ptabs %1, %0 9121 pt %1, %0" 9122 [(set_attr "type" "ptabs_media,pt_media") 9123 (set_attr "length" "4,*")]) 9124 9125(define_insn "*truncdipdi_media" 9126 [(set (match_operand:PDI 0 "target_reg_operand" "=b,b"); 9127 (if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand" 9128 "r,Csy") 9129 (const_int 3)) 9130 (const_int 3)) 9131 (mem:PDI (match_dup 1)) 9132 (truncate:PDI (match_dup 1))))] 9133 "TARGET_SHMEDIA && !TARGET_PT_FIXED" 9134 "@ 9135 ptabs %1, %0 9136 pt %1, %0" 9137 [(set_attr "type" "ptabs_media,pt_media") 9138 (set_attr "length" "4,*")]) 9139 9140(define_insn "*movsi_y" 9141 [(set (match_operand:SI 0 "register_operand" "=y,y") 9142 (match_operand:SI 1 "immediate_operand" "Qi,I08")) 9143 (clobber (match_scratch:SI 2 "=&z,r"))] 9144 "TARGET_SH2E 9145 && (reload_in_progress || reload_completed)" 9146 "#" 9147 [(set_attr "length" "4") 9148 (set_attr "type" "pcload,move")]) 9149 9150(define_split 9151 [(set (match_operand:SI 0 "register_operand" "") 9152 (match_operand:SI 1 "immediate_operand" "")) 9153 (clobber (match_operand:SI 2 "register_operand" ""))] 9154 "TARGET_SH1" 9155 [(set (match_dup 2) (match_dup 1)) 9156 (set (match_dup 0) (match_dup 2))] 9157 "") 9158 9159;; ------------------------------------------------------------------------ 9160;; Define the real conditional branch instructions. 9161;; ------------------------------------------------------------------------ 9162 9163(define_expand "branch_true" 9164 [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0)) 9165 (label_ref (match_operand 0)) 9166 (pc)))] 9167 "TARGET_SH1") 9168 9169(define_expand "branch_false" 9170 [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 9171 (label_ref (match_operand 0)) 9172 (pc)))] 9173 "TARGET_SH1") 9174 9175(define_insn_and_split "*cbranch_t" 9176 [(set (pc) (if_then_else (match_operand 1 "cbranch_treg_value") 9177 (label_ref (match_operand 0)) 9178 (pc)))] 9179 "TARGET_SH1" 9180{ 9181 return output_branch (sh_eval_treg_value (operands[1]), insn, operands); 9182} 9183 "&& 1" 9184 [(const_int 0)] 9185{ 9186 /* Try to canonicalize the branch condition if it is not one of: 9187 (ne (reg:SI T_REG) (const_int 0)) 9188 (eq (reg:SI T_REG) (const_int 0)) 9189 9190 Instead of splitting out a new insn, we modify the current insn's 9191 operands as needed. This preserves things such as REG_DEAD notes. */ 9192 9193 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE) 9194 && REG_P (XEXP (operands[1], 0)) && REGNO (XEXP (operands[1], 0)) == T_REG 9195 && XEXP (operands[1], 1) == const0_rtx) 9196 DONE; 9197 9198 int branch_cond = sh_eval_treg_value (operands[1]); 9199 rtx new_cond_rtx = NULL_RTX; 9200 9201 if (branch_cond == 0) 9202 new_cond_rtx = gen_rtx_EQ (VOIDmode, get_t_reg_rtx (), const0_rtx); 9203 else if (branch_cond == 1) 9204 new_cond_rtx = gen_rtx_NE (VOIDmode, get_t_reg_rtx (), const0_rtx); 9205 9206 if (new_cond_rtx != NULL_RTX) 9207 validate_change (curr_insn, &XEXP (XEXP (PATTERN (curr_insn), 1), 0), 9208 new_cond_rtx, false); 9209 DONE; 9210} 9211 [(set_attr "type" "cbranch")]) 9212 9213;; Patterns to prevent reorg from re-combining a condbranch with a branch 9214;; which destination is too far away. 9215;; The const_int_operand is distinct for each branch target; it avoids 9216;; unwanted matches with redundant_insn. 9217(define_insn "block_branch_redirect" 9218 [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))] 9219 "TARGET_SH1" 9220 "" 9221 [(set_attr "length" "0")]) 9222 9223;; This one has the additional purpose to record a possible scratch register 9224;; for the following branch. 9225;; ??? Unfortunately, just setting the scratch register is not good enough, 9226;; because the insn then might be deemed dead and deleted. And we can't 9227;; make the use in the jump insn explicit because that would disable 9228;; delay slot scheduling from the target. 9229(define_insn "indirect_jump_scratch" 9230 [(set (match_operand:SI 0 "register_operand" "=r") 9231 (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR)) 9232 (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))] 9233 "TARGET_SH1" 9234 "" 9235 [(set_attr "length" "0")]) 9236 9237;; This one is used to preemt an insn from beyond the bra / braf / jmp 9238;; being pulled into the delay slot of a condbranch that has been made to 9239;; jump around the unconditional jump because it was out of range. 9240(define_insn "stuff_delay_slot" 9241 [(set (pc) 9242 (unspec [(match_operand:SI 0 "const_int_operand" "") (pc) 9243 (match_operand:SI 1 "const_int_operand" "")] UNSPEC_BBR))] 9244 "TARGET_SH1" 9245 "" 9246 [(set_attr "length" "0") 9247 (set_attr "cond_delay_slot" "yes")]) 9248 9249;; Conditional branch insns 9250 9251(define_expand "cbranchint4_media" 9252 [(set (pc) 9253 (if_then_else (match_operator 0 "shmedia_cbranch_comparison_operator" 9254 [(match_operand 1 "" "") 9255 (match_operand 2 "" "")]) 9256 (match_operand 3 "" "") 9257 (pc)))] 9258 "TARGET_SHMEDIA" 9259{ 9260 machine_mode mode = GET_MODE (operands[1]); 9261 if (mode == VOIDmode) 9262 mode = GET_MODE (operands[2]); 9263 if (GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE) 9264 { 9265 operands[1] = force_reg (mode, operands[1]); 9266 if (CONSTANT_P (operands[2]) 9267 && (! satisfies_constraint_I06 (operands[2]))) 9268 operands[2] = force_reg (mode, operands[2]); 9269 } 9270 else 9271 { 9272 if (operands[1] != const0_rtx) 9273 operands[1] = force_reg (mode, operands[1]); 9274 if (operands[2] != const0_rtx) 9275 operands[2] = force_reg (mode, operands[2]); 9276 } 9277 switch (GET_CODE (operands[0])) 9278 { 9279 case LEU: 9280 case LE: 9281 case LTU: 9282 case LT: 9283 operands[0] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[0])), 9284 VOIDmode, operands[2], operands[1]); 9285 operands[1] = XEXP (operands[0], 0); 9286 operands[2] = XEXP (operands[0], 1); 9287 break; 9288 default: 9289 operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]), 9290 VOIDmode, operands[1], operands[2]); 9291 break; 9292 } 9293 operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]); 9294}) 9295 9296(define_expand "cbranchfp4_media" 9297 [(set (pc) 9298 (if_then_else (match_operator 0 "sh_float_comparison_operator" 9299 [(match_operand 1 "" "") 9300 (match_operand 2 "" "")]) 9301 (match_operand 3 "" "") 9302 (pc)))] 9303 "TARGET_SHMEDIA" 9304{ 9305 rtx tmp = gen_reg_rtx (SImode); 9306 rtx cmp; 9307 if (GET_CODE (operands[0]) == NE) 9308 cmp = gen_rtx_EQ (SImode, operands[1], operands[2]); 9309 else 9310 cmp = gen_rtx_fmt_ee (GET_CODE (operands[0]), SImode, 9311 operands[1], operands[2]); 9312 9313 emit_insn (gen_cstore4_media (tmp, cmp, operands[1], operands[2])); 9314 9315 if (GET_CODE (cmp) == GET_CODE (operands[0])) 9316 operands[0] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); 9317 else 9318 operands[0] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); 9319 operands[1] = tmp; 9320 operands[2] = const0_rtx; 9321 operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]); 9322}) 9323 9324(define_insn "*beq_media_i" 9325 [(set (pc) 9326 (if_then_else (match_operator 3 "equality_comparison_operator" 9327 [(match_operand:DI 1 "arith_reg_operand" "r,r") 9328 (match_operand:DI 2 "arith_operand" "r,I06")]) 9329 (match_operand 0 "target_operand" "b,b") 9330 (pc)))] 9331 "TARGET_SHMEDIA" 9332 "@ 9333 b%o3%' %1, %2, %0%> 9334 b%o3i%' %1, %2, %0%>" 9335 [(set_attr "type" "cbranch_media")]) 9336 9337(define_insn "*beq_media_i32" 9338 [(set (pc) 9339 (if_then_else (match_operator 3 "equality_comparison_operator" 9340 [(match_operand:SI 1 "arith_reg_operand" "r,r") 9341 (match_operand:SI 2 "arith_operand" "r,I06")]) 9342 (match_operand 0 "target_operand" "b,b") 9343 (pc)))] 9344 "TARGET_SHMEDIA" 9345 "@ 9346 b%o3%' %1, %2, %0%> 9347 b%o3i%' %1, %2, %0%>" 9348 [(set_attr "type" "cbranch_media")]) 9349 9350(define_insn "*bgt_media_i" 9351 [(set (pc) 9352 (if_then_else (match_operator 3 "greater_comparison_operator" 9353 [(match_operand:DI 1 "arith_reg_or_0_operand" "rN") 9354 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")]) 9355 (match_operand 0 "target_operand" "b") 9356 (pc)))] 9357 "TARGET_SHMEDIA" 9358 "b%o3%' %N1, %N2, %0%>" 9359 [(set_attr "type" "cbranch_media")]) 9360 9361(define_insn "*bgt_media_i32" 9362 [(set (pc) 9363 (if_then_else (match_operator 3 "greater_comparison_operator" 9364 [(match_operand:SI 1 "arith_reg_or_0_operand" "rN") 9365 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")]) 9366 (match_operand 0 "target_operand" "b") 9367 (pc)))] 9368 "TARGET_SHMEDIA" 9369 "b%o3%' %N1, %N2, %0%>" 9370 [(set_attr "type" "cbranch_media")]) 9371 9372;; These are only needed to make invert_jump() happy - otherwise, jump 9373;; optimization will be silently disabled. 9374(define_insn "*blt_media_i" 9375 [(set (pc) 9376 (if_then_else (match_operator 3 "less_comparison_operator" 9377 [(match_operand:DI 1 "arith_reg_or_0_operand" "rN") 9378 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")]) 9379 (match_operand 0 "target_operand" "b") 9380 (pc)))] 9381 "TARGET_SHMEDIA" 9382 "b%o3%' %N2, %N1, %0%>" 9383 [(set_attr "type" "cbranch_media")]) 9384 9385(define_insn "*blt_media_i32" 9386 [(set (pc) 9387 (if_then_else (match_operator 3 "less_comparison_operator" 9388 [(match_operand:SI 1 "arith_reg_or_0_operand" "rN") 9389 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")]) 9390 (match_operand 0 "target_operand" "b") 9391 (pc)))] 9392 "TARGET_SHMEDIA" 9393 "b%o3%' %N2, %N1, %0%>" 9394 [(set_attr "type" "cbranch_media")]) 9395 9396;; combiner splitter for test-and-branch on single bit in register. This 9397;; is endian dependent because the non-paradoxical subreg looks different 9398;; on big endian. 9399(define_split 9400 [(set (pc) 9401 (if_then_else 9402 (match_operator 3 "equality_comparison_operator" 9403 [(subreg:SI 9404 (zero_extract:DI 9405 (subreg:DI (match_operand:SI 1 "extend_reg_operand" "") 0) 9406 (const_int 1) 9407 (match_operand 2 "const_int_operand" "")) 0) 9408 (const_int 0)]) 9409 (match_operand 0 "target_operand" "") 9410 (pc))) 9411 (clobber (match_operand:SI 4 "arith_reg_dest" ""))] 9412 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN" 9413 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5))) 9414 (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))] 9415{ 9416 operands[5] = GEN_INT (31 - INTVAL (operands[2])); 9417 operands[6] = (GET_CODE (operands[3]) == EQ 9418 ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx) 9419 : gen_rtx_GT (VOIDmode, const0_rtx, operands[4])); 9420}) 9421 9422; operand 0 is the loop count pseudo register 9423; operand 1 is the label to jump to at the top of the loop 9424(define_expand "doloop_end" 9425 [(parallel [(set (pc) 9426 (if_then_else (ne:SI (match_operand:SI 0 "" "") 9427 (const_int 1)) 9428 (label_ref (match_operand 1 "" "")) 9429 (pc))) 9430 (set (match_dup 0) 9431 (plus:SI (match_dup 0) (const_int -1))) 9432 (clobber (reg:SI T_REG))])] 9433 "TARGET_SH2" 9434{ 9435 if (GET_MODE (operands[0]) != SImode) 9436 FAIL; 9437 emit_jump_insn (gen_doloop_end_split (operands[0], operands[1], operands[0])); 9438 DONE; 9439}) 9440 9441(define_insn_and_split "doloop_end_split" 9442 [(set (pc) 9443 (if_then_else (ne:SI (match_operand:SI 2 "arith_reg_dest" "0") 9444 (const_int 1)) 9445 (label_ref (match_operand 1 "" "")) 9446 (pc))) 9447 (set (match_operand:SI 0 "arith_reg_dest" "=r") 9448 (plus:SI (match_dup 2) (const_int -1))) 9449 (clobber (reg:SI T_REG))] 9450 "TARGET_SH2" 9451 "#" 9452 "" 9453 [(parallel [(set (reg:SI T_REG) 9454 (eq:SI (match_dup 2) (const_int 1))) 9455 (set (match_dup 0) (plus:SI (match_dup 2) (const_int -1)))]) 9456 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 9457 (label_ref (match_dup 1)) 9458 (pc)))] 9459 "" 9460 [(set_attr "type" "cbranch")]) 9461 9462;; ------------------------------------------------------------------------ 9463;; Jump and linkage insns 9464;; ------------------------------------------------------------------------ 9465 9466(define_insn "jump_compact" 9467 [(set (pc) 9468 (label_ref (match_operand 0 "" "")))] 9469 "TARGET_SH1 && !CROSSING_JUMP_P (insn)" 9470{ 9471 /* The length is 16 if the delay slot is unfilled. */ 9472 if (get_attr_length(insn) > 4) 9473 return output_far_jump(insn, operands[0]); 9474 else 9475 return "bra %l0%#"; 9476} 9477 [(set_attr "type" "jump") 9478 (set_attr "needs_delay_slot" "yes")]) 9479 9480(define_insn "*jump_compact_crossing" 9481 [(set (pc) 9482 (label_ref (match_operand 0 "" "")))] 9483 "TARGET_SH1 9484 && flag_reorder_blocks_and_partition 9485 && CROSSING_JUMP_P (insn)" 9486{ 9487 /* The length is 16 if the delay slot is unfilled. */ 9488 return output_far_jump(insn, operands[0]); 9489} 9490 [(set_attr "type" "jump") 9491 (set_attr "length" "16")]) 9492 9493;; ??? It would be much saner to explicitly use the scratch register 9494;; in the jump insn, and have indirect_jump_scratch only set it, 9495;; but fill_simple_delay_slots would refuse to do delay slot filling 9496;; from the target then, as it uses simplejump_p. 9497;;(define_insn "jump_compact_far" 9498;; [(set (pc) 9499;; (label_ref (match_operand 0 "" ""))) 9500;; (use (match_operand 1 "register_operand" "r")] 9501;; "TARGET_SH1" 9502;; "* return output_far_jump(insn, operands[0], operands[1]);" 9503;; [(set_attr "type" "jump") 9504;; (set_attr "needs_delay_slot" "yes")]) 9505 9506(define_insn "jump_media" 9507 [(set (pc) 9508 (match_operand 0 "target_operand" "b"))] 9509 "TARGET_SHMEDIA" 9510 "blink %0, r63%>" 9511 [(set_attr "type" "jump_media")]) 9512 9513(define_expand "jump" 9514 [(set (pc) 9515 (label_ref (match_operand 0 "" "")))] 9516 "" 9517{ 9518 if (TARGET_SH1) 9519 emit_jump_insn (gen_jump_compact (operands[0])); 9520 else if (TARGET_SHMEDIA) 9521 { 9522 if (reload_in_progress || reload_completed) 9523 FAIL; 9524 emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode, operands[0]))); 9525 } 9526 DONE; 9527}) 9528 9529(define_insn "force_mode_for_call" 9530 [(use (reg:SI FPSCR_MODES_REG))] 9531 "TARGET_SHCOMPACT" 9532 "" 9533 [(set_attr "length" "0") 9534 (set (attr "fp_mode") 9535 (if_then_else (eq_attr "fpu_single" "yes") 9536 (const_string "single") (const_string "double")))]) 9537 9538(define_insn "calli" 9539 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) 9540 (match_operand 1 "" "")) 9541 (use (reg:SI FPSCR_MODES_REG)) 9542 (clobber (reg:SI PR_REG))] 9543 "TARGET_SH1 && !TARGET_FDPIC" 9544{ 9545 if (TARGET_SH2A && dbr_sequence_length () == 0) 9546 return "jsr/n @%0"; 9547 else 9548 return "jsr @%0%#"; 9549} 9550 [(set_attr "type" "call") 9551 (set (attr "fp_mode") 9552 (if_then_else (eq_attr "fpu_single" "yes") 9553 (const_string "single") (const_string "double"))) 9554 (set_attr "needs_delay_slot" "yes") 9555 (set_attr "fp_set" "unknown")]) 9556 9557(define_insn "calli_fdpic" 9558 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) 9559 (match_operand 1)) 9560 (use (reg:SI FPSCR_MODES_REG)) 9561 (use (reg:SI PIC_REG)) 9562 (clobber (reg:SI PR_REG))] 9563 "TARGET_FDPIC" 9564{ 9565 if (TARGET_SH2A && dbr_sequence_length () == 0) 9566 return "jsr/n @%0"; 9567 else 9568 return "jsr @%0%#"; 9569} 9570 [(set_attr "type" "call") 9571 (set (attr "fp_mode") 9572 (if_then_else (eq_attr "fpu_single" "yes") 9573 (const_string "single") (const_string "double"))) 9574 (set_attr "needs_delay_slot" "yes") 9575 (set_attr "fp_set" "unknown")]) 9576 9577;; This is TBR relative jump instruction for SH2A architecture. 9578;; Its use is enabled by assigning an attribute "function_vector" 9579;; and the vector number to a function during its declaration. 9580(define_insn "calli_tbr_rel" 9581 [(call (mem (match_operand:SI 0 "symbol_ref_operand" "")) 9582 (match_operand 1 "" "")) 9583 (use (reg:SI FPSCR_MODES_REG)) 9584 (clobber (reg:SI PR_REG))] 9585 "TARGET_SH2A && sh2a_is_function_vector_call (operands[0])" 9586{ 9587 unsigned HOST_WIDE_INT vect_num; 9588 vect_num = sh2a_get_function_vector_number (operands[0]); 9589 operands[2] = GEN_INT (vect_num * 4); 9590 9591 return "jsr/n @@(%O2,tbr)"; 9592} 9593 [(set_attr "type" "call") 9594 (set (attr "fp_mode") 9595 (if_then_else (eq_attr "fpu_single" "yes") 9596 (const_string "single") (const_string "double"))) 9597 (set_attr "needs_delay_slot" "no") 9598 (set_attr "fp_set" "unknown")]) 9599 9600;; This is a pc-rel call, using bsrf, for use with PIC. 9601(define_insn "calli_pcrel" 9602 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) 9603 (match_operand 1 "" "")) 9604 (use (reg:SI FPSCR_MODES_REG)) 9605 (use (reg:SI PIC_REG)) 9606 (use (match_operand 2 "" "")) 9607 (clobber (reg:SI PR_REG))] 9608 "TARGET_SH2" 9609{ 9610 return "bsrf %0" "\n" 9611 "%O2:%#"; 9612} 9613 [(set_attr "type" "call") 9614 (set (attr "fp_mode") 9615 (if_then_else (eq_attr "fpu_single" "yes") 9616 (const_string "single") (const_string "double"))) 9617 (set_attr "needs_delay_slot" "yes") 9618 (set_attr "fp_set" "unknown")]) 9619 9620(define_insn_and_split "call_pcrel" 9621 [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "")) 9622 (match_operand 1 "" "")) 9623 (use (reg:SI FPSCR_MODES_REG)) 9624 (use (reg:SI PIC_REG)) 9625 (clobber (reg:SI PR_REG)) 9626 (clobber (match_scratch:SI 2 "=&r"))] 9627 "TARGET_SH2" 9628 "#" 9629 "reload_completed" 9630 [(const_int 0)] 9631{ 9632 rtx lab = PATTERN (gen_call_site ()); 9633 9634 sh_expand_sym_label2reg (operands[2], operands[0], lab, false); 9635 emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab))); 9636 DONE; 9637} 9638 [(set_attr "type" "call") 9639 (set (attr "fp_mode") 9640 (if_then_else (eq_attr "fpu_single" "yes") 9641 (const_string "single") (const_string "double"))) 9642 (set_attr "needs_delay_slot" "yes") 9643 (set_attr "fp_set" "unknown")]) 9644 9645(define_insn "call_compact" 9646 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) 9647 (match_operand 1 "" "")) 9648 (match_operand 2 "immediate_operand" "n") 9649 (use (reg:SI R0_REG)) 9650 (use (reg:SI R1_REG)) 9651 (use (reg:SI FPSCR_MODES_REG)) 9652 (clobber (reg:SI PR_REG))] 9653 "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))" 9654 "jsr @%0%#" 9655 [(set_attr "type" "call") 9656 (set (attr "fp_mode") 9657 (if_then_else (eq_attr "fpu_single" "yes") 9658 (const_string "single") (const_string "double"))) 9659 (set_attr "needs_delay_slot" "yes")]) 9660 9661(define_insn "call_compact_rettramp" 9662 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) 9663 (match_operand 1 "" "")) 9664 (match_operand 2 "immediate_operand" "n") 9665 (use (reg:SI R0_REG)) 9666 (use (reg:SI R1_REG)) 9667 (use (reg:SI FPSCR_MODES_REG)) 9668 (clobber (reg:SI R10_REG)) 9669 (clobber (reg:SI PR_REG))] 9670 "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))" 9671 "jsr @%0%#" 9672 [(set_attr "type" "call") 9673 (set (attr "fp_mode") 9674 (if_then_else (eq_attr "fpu_single" "yes") 9675 (const_string "single") (const_string "double"))) 9676 (set_attr "needs_delay_slot" "yes")]) 9677 9678(define_insn "call_media" 9679 [(call (mem:DI (match_operand 0 "target_reg_operand" "b")) 9680 (match_operand 1 "" "")) 9681 (clobber (reg:DI PR_MEDIA_REG))] 9682 "TARGET_SHMEDIA" 9683 "blink %0, r18" 9684 [(set_attr "type" "jump_media")]) 9685 9686(define_insn "call_valuei" 9687 [(set (match_operand 0 "" "=rf") 9688 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) 9689 (match_operand 2 "" ""))) 9690 (use (reg:SI FPSCR_MODES_REG)) 9691 (clobber (reg:SI PR_REG))] 9692 "TARGET_SH1 && !TARGET_FDPIC" 9693{ 9694 if (TARGET_SH2A && dbr_sequence_length () == 0) 9695 return "jsr/n @%1"; 9696 else 9697 return "jsr @%1%#"; 9698} 9699 [(set_attr "type" "call") 9700 (set (attr "fp_mode") 9701 (if_then_else (eq_attr "fpu_single" "yes") 9702 (const_string "single") (const_string "double"))) 9703 (set_attr "needs_delay_slot" "yes") 9704 (set_attr "fp_set" "unknown")]) 9705 9706(define_insn "call_valuei_fdpic" 9707 [(set (match_operand 0 "" "=rf") 9708 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) 9709 (match_operand 2))) 9710 (use (reg:SI FPSCR_REG)) 9711 (use (reg:SI PIC_REG)) 9712 (clobber (reg:SI PR_REG))] 9713 "TARGET_FDPIC" 9714{ 9715 if (TARGET_SH2A && dbr_sequence_length () == 0) 9716 return "jsr/n @%1"; 9717 else 9718 return "jsr @%1%#"; 9719} 9720 [(set_attr "type" "call") 9721 (set (attr "fp_mode") 9722 (if_then_else (eq_attr "fpu_single" "yes") 9723 (const_string "single") (const_string "double"))) 9724 (set_attr "needs_delay_slot" "yes") 9725 (set_attr "fp_set" "unknown")]) 9726 9727;; This is TBR relative jump instruction for SH2A architecture. 9728;; Its use is enabled by assigning an attribute "function_vector" 9729;; and the vector number to a function during its declaration. 9730(define_insn "call_valuei_tbr_rel" 9731 [(set (match_operand 0 "" "=rf") 9732 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "")) 9733 (match_operand 2 "" ""))) 9734 (use (reg:SI FPSCR_MODES_REG)) 9735 (clobber (reg:SI PR_REG))] 9736 "TARGET_SH2A && sh2a_is_function_vector_call (operands[1])" 9737{ 9738 unsigned HOST_WIDE_INT vect_num; 9739 vect_num = sh2a_get_function_vector_number (operands[1]); 9740 operands[3] = GEN_INT (vect_num * 4); 9741 9742 return "jsr/n @@(%O3,tbr)"; 9743} 9744 [(set_attr "type" "call") 9745 (set (attr "fp_mode") 9746 (if_then_else (eq_attr "fpu_single" "yes") 9747 (const_string "single") (const_string "double"))) 9748 (set_attr "needs_delay_slot" "no") 9749 (set_attr "fp_set" "unknown")]) 9750 9751(define_insn "call_valuei_pcrel" 9752 [(set (match_operand 0 "" "=rf") 9753 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) 9754 (match_operand 2 "" ""))) 9755 (use (reg:SI FPSCR_MODES_REG)) 9756 (use (reg:SI PIC_REG)) 9757 (use (match_operand 3 "" "")) 9758 (clobber (reg:SI PR_REG))] 9759 "TARGET_SH2" 9760{ 9761 return "bsrf %1" "\n" 9762 "%O3:%#"; 9763} 9764 [(set_attr "type" "call") 9765 (set (attr "fp_mode") 9766 (if_then_else (eq_attr "fpu_single" "yes") 9767 (const_string "single") (const_string "double"))) 9768 (set_attr "needs_delay_slot" "yes") 9769 (set_attr "fp_set" "unknown")]) 9770 9771(define_insn_and_split "call_value_pcrel" 9772 [(set (match_operand 0 "" "=rf") 9773 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "")) 9774 (match_operand 2 "" ""))) 9775 (use (reg:SI FPSCR_MODES_REG)) 9776 (use (reg:SI PIC_REG)) 9777 (clobber (reg:SI PR_REG)) 9778 (clobber (match_scratch:SI 3 "=&r"))] 9779 "TARGET_SH2" 9780 "#" 9781 "reload_completed" 9782 [(const_int 0)] 9783{ 9784 rtx lab = PATTERN (gen_call_site ()); 9785 9786 sh_expand_sym_label2reg (operands[3], operands[1], lab, false); 9787 emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3], 9788 operands[2], copy_rtx (lab))); 9789 DONE; 9790} 9791 [(set_attr "type" "call") 9792 (set (attr "fp_mode") 9793 (if_then_else (eq_attr "fpu_single" "yes") 9794 (const_string "single") (const_string "double"))) 9795 (set_attr "needs_delay_slot" "yes") 9796 (set_attr "fp_set" "unknown")]) 9797 9798(define_insn "call_value_compact" 9799 [(set (match_operand 0 "" "=rf") 9800 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) 9801 (match_operand 2 "" ""))) 9802 (match_operand 3 "immediate_operand" "n") 9803 (use (reg:SI R0_REG)) 9804 (use (reg:SI R1_REG)) 9805 (use (reg:SI FPSCR_MODES_REG)) 9806 (clobber (reg:SI PR_REG))] 9807 "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))" 9808 "jsr @%1%#" 9809 [(set_attr "type" "call") 9810 (set (attr "fp_mode") 9811 (if_then_else (eq_attr "fpu_single" "yes") 9812 (const_string "single") (const_string "double"))) 9813 (set_attr "needs_delay_slot" "yes")]) 9814 9815(define_insn "call_value_compact_rettramp" 9816 [(set (match_operand 0 "" "=rf") 9817 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) 9818 (match_operand 2 "" ""))) 9819 (match_operand 3 "immediate_operand" "n") 9820 (use (reg:SI R0_REG)) 9821 (use (reg:SI R1_REG)) 9822 (use (reg:SI FPSCR_MODES_REG)) 9823 (clobber (reg:SI R10_REG)) 9824 (clobber (reg:SI PR_REG))] 9825 "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))" 9826 "jsr @%1%#" 9827 [(set_attr "type" "call") 9828 (set (attr "fp_mode") 9829 (if_then_else (eq_attr "fpu_single" "yes") 9830 (const_string "single") (const_string "double"))) 9831 (set_attr "needs_delay_slot" "yes")]) 9832 9833(define_insn "call_value_media" 9834 [(set (match_operand 0 "" "=rf") 9835 (call (mem:DI (match_operand 1 "target_reg_operand" "b")) 9836 (match_operand 2 "" ""))) 9837 (clobber (reg:DI PR_MEDIA_REG))] 9838 "TARGET_SHMEDIA" 9839 "blink %1, r18" 9840 [(set_attr "type" "jump_media")]) 9841 9842(define_expand "call" 9843 [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" "")) 9844 (match_operand 1 "" "")) 9845 (match_operand 2 "" "") 9846 (use (reg:SI FPSCR_MODES_REG)) 9847 (clobber (reg:SI PR_REG))])] 9848 "" 9849{ 9850 if (TARGET_FDPIC) 9851 { 9852 rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG); 9853 emit_move_insn (pic_reg, sh_get_fdpic_reg_initial_val ()); 9854 } 9855 9856 if (TARGET_SHMEDIA) 9857 { 9858 operands[0] = shmedia_prepare_call_address (operands[0], 0); 9859 emit_call_insn (gen_call_media (operands[0], operands[1])); 9860 DONE; 9861 } 9862 else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2])) 9863 { 9864 rtx cookie_rtx = operands[2]; 9865 long cookie = INTVAL (cookie_rtx); 9866 rtx func = XEXP (operands[0], 0); 9867 rtx r0, r1; 9868 9869 if (flag_pic) 9870 { 9871 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func)) 9872 { 9873 rtx reg = gen_reg_rtx (Pmode); 9874 9875 emit_insn (gen_symGOTPLT2reg (reg, func)); 9876 func = reg; 9877 } 9878 else 9879 func = legitimize_pic_address (func, Pmode, 0); 9880 } 9881 9882 r0 = gen_rtx_REG (SImode, R0_REG); 9883 r1 = gen_rtx_REG (SImode, R1_REG); 9884 9885 /* Since such a call function may use all call-clobbered 9886 registers, we force a mode switch earlier, so that we don't 9887 run out of registers when adjusting fpscr for the call. */ 9888 emit_insn (gen_force_mode_for_call ()); 9889 9890 operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline", 9891 SFUNC_GOT).sym; 9892 operands[0] = force_reg (SImode, operands[0]); 9893 9894 emit_move_insn (r0, func); 9895 emit_move_insn (r1, cookie_rtx); 9896 9897 if (cookie & CALL_COOKIE_RET_TRAMP (1)) 9898 emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1], 9899 operands[2])); 9900 else 9901 emit_call_insn (gen_call_compact (operands[0], operands[1], 9902 operands[2])); 9903 9904 DONE; 9905 } 9906 else if (TARGET_SHCOMPACT && flag_pic 9907 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF 9908 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0))) 9909 { 9910 rtx reg = gen_reg_rtx (Pmode); 9911 9912 emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0))); 9913 XEXP (operands[0], 0) = reg; 9914 } 9915 if (!flag_pic && TARGET_SH2A 9916 && MEM_P (operands[0]) 9917 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF) 9918 { 9919 if (sh2a_is_function_vector_call (XEXP (operands[0], 0))) 9920 { 9921 emit_call_insn (gen_calli_tbr_rel (XEXP (operands[0], 0), 9922 operands[1])); 9923 DONE; 9924 } 9925 } 9926 if (flag_pic && TARGET_SH2 9927 && MEM_P (operands[0]) 9928 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF) 9929 { 9930 emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1])); 9931 DONE; 9932 } 9933 else 9934 { 9935 operands[0] = force_reg (SImode, XEXP (operands[0], 0)); 9936 operands[1] = operands[2]; 9937 } 9938 9939 if (TARGET_FDPIC) 9940 { 9941 operands[0] = sh_load_function_descriptor (operands[0]); 9942 emit_call_insn (gen_calli_fdpic (operands[0], operands[1])); 9943 } 9944 else 9945 emit_call_insn (gen_calli (operands[0], operands[1])); 9946 DONE; 9947}) 9948 9949(define_insn "call_pop_compact" 9950 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) 9951 (match_operand 1 "" "")) 9952 (match_operand 2 "immediate_operand" "n") 9953 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) 9954 (match_operand 3 "immediate_operand" "n"))) 9955 (use (reg:SI R0_REG)) 9956 (use (reg:SI R1_REG)) 9957 (use (reg:SI FPSCR_MODES_REG)) 9958 (clobber (reg:SI PR_REG))] 9959 "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))" 9960 "jsr @%0%#" 9961 [(set_attr "type" "call") 9962 (set (attr "fp_mode") 9963 (if_then_else (eq_attr "fpu_single" "yes") 9964 (const_string "single") (const_string "double"))) 9965 (set_attr "needs_delay_slot" "yes")]) 9966 9967(define_insn "call_pop_compact_rettramp" 9968 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) 9969 (match_operand 1 "" "")) 9970 (match_operand 2 "immediate_operand" "n") 9971 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) 9972 (match_operand 3 "immediate_operand" "n"))) 9973 (use (reg:SI R0_REG)) 9974 (use (reg:SI R1_REG)) 9975 (use (reg:SI FPSCR_MODES_REG)) 9976 (clobber (reg:SI R10_REG)) 9977 (clobber (reg:SI PR_REG))] 9978 "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))" 9979 "jsr @%0%#" 9980 [(set_attr "type" "call") 9981 (set (attr "fp_mode") 9982 (if_then_else (eq_attr "fpu_single" "yes") 9983 (const_string "single") (const_string "double"))) 9984 (set_attr "needs_delay_slot" "yes")]) 9985 9986(define_expand "call_pop" 9987 [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" "")) 9988 (match_operand 1 "" "")) 9989 (match_operand 2 "" "") 9990 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) 9991 (match_operand 3 "" "")))])] 9992 "TARGET_SHCOMPACT" 9993{ 9994 rtx cookie_rtx; 9995 long cookie; 9996 rtx func; 9997 rtx r0, r1; 9998 9999 gcc_assert (operands[2] && INTVAL (operands[2])); 10000 cookie_rtx = operands[2]; 10001 cookie = INTVAL (cookie_rtx); 10002 func = XEXP (operands[0], 0); 10003 10004 if (flag_pic) 10005 { 10006 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func)) 10007 { 10008 rtx reg = gen_reg_rtx (Pmode); 10009 emit_insn (gen_symGOTPLT2reg (reg, func)); 10010 func = reg; 10011 } 10012 else 10013 func = legitimize_pic_address (func, Pmode, 0); 10014 } 10015 10016 r0 = gen_rtx_REG (SImode, R0_REG); 10017 r1 = gen_rtx_REG (SImode, R1_REG); 10018 10019 /* Since such a call function may use all call-clobbered 10020 registers, we force a mode switch earlier, so that we don't 10021 run out of registers when adjusting fpscr for the call. */ 10022 emit_insn (gen_force_mode_for_call ()); 10023 10024 operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline", 10025 SFUNC_GOT).sym; 10026 operands[0] = force_reg (SImode, operands[0]); 10027 10028 emit_move_insn (r0, func); 10029 emit_move_insn (r1, cookie_rtx); 10030 10031 if (cookie & CALL_COOKIE_RET_TRAMP (1)) 10032 emit_call_insn (gen_call_pop_compact_rettramp 10033 (operands[0], operands[1], operands[2], operands[3])); 10034 else 10035 emit_call_insn (gen_call_pop_compact 10036 (operands[0], operands[1], operands[2], operands[3])); 10037 10038 DONE; 10039}) 10040 10041(define_expand "call_value" 10042 [(parallel [(set (match_operand 0 "arith_reg_operand" "") 10043 (call (mem:SI (match_operand 1 "arith_reg_operand" "")) 10044 (match_operand 2 "" ""))) 10045 (match_operand 3 "" "") 10046 (use (reg:SI FPSCR_MODES_REG)) 10047 (clobber (reg:SI PR_REG))])] 10048 "" 10049{ 10050 if (TARGET_FDPIC) 10051 { 10052 rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG); 10053 emit_move_insn (pic_reg, sh_get_fdpic_reg_initial_val ()); 10054 } 10055 10056 if (TARGET_SHMEDIA) 10057 { 10058 operands[1] = shmedia_prepare_call_address (operands[1], 0); 10059 emit_call_insn (gen_call_value_media (operands[0], operands[1], 10060 operands[2])); 10061 DONE; 10062 } 10063 else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3])) 10064 { 10065 rtx cookie_rtx = operands[3]; 10066 long cookie = INTVAL (cookie_rtx); 10067 rtx func = XEXP (operands[1], 0); 10068 rtx r0, r1; 10069 10070 if (flag_pic) 10071 { 10072 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func)) 10073 { 10074 rtx reg = gen_reg_rtx (Pmode); 10075 10076 emit_insn (gen_symGOTPLT2reg (reg, func)); 10077 func = reg; 10078 } 10079 else 10080 func = legitimize_pic_address (func, Pmode, 0); 10081 } 10082 10083 r0 = gen_rtx_REG (SImode, R0_REG); 10084 r1 = gen_rtx_REG (SImode, R1_REG); 10085 10086 /* Since such a call function may use all call-clobbered 10087 registers, we force a mode switch earlier, so that we don't 10088 run out of registers when adjusting fpscr for the call. */ 10089 emit_insn (gen_force_mode_for_call ()); 10090 10091 operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline", 10092 SFUNC_GOT).sym; 10093 operands[1] = force_reg (SImode, operands[1]); 10094 10095 emit_move_insn (r0, func); 10096 emit_move_insn (r1, cookie_rtx); 10097 10098 if (cookie & CALL_COOKIE_RET_TRAMP (1)) 10099 emit_call_insn (gen_call_value_compact_rettramp (operands[0], 10100 operands[1], 10101 operands[2], 10102 operands[3])); 10103 else 10104 emit_call_insn (gen_call_value_compact (operands[0], operands[1], 10105 operands[2], operands[3])); 10106 10107 DONE; 10108 } 10109 else if (TARGET_SHCOMPACT && flag_pic 10110 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF 10111 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0))) 10112 { 10113 rtx reg = gen_reg_rtx (Pmode); 10114 10115 emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0))); 10116 XEXP (operands[1], 0) = reg; 10117 } 10118 if (!flag_pic && TARGET_SH2A 10119 && MEM_P (operands[1]) 10120 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF) 10121 { 10122 if (sh2a_is_function_vector_call (XEXP (operands[1], 0))) 10123 { 10124 emit_call_insn (gen_call_valuei_tbr_rel (operands[0], 10125 XEXP (operands[1], 0), operands[2])); 10126 DONE; 10127 } 10128 } 10129 if (flag_pic && TARGET_SH2 10130 && MEM_P (operands[1]) 10131 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF) 10132 { 10133 emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0), 10134 operands[2])); 10135 DONE; 10136 } 10137 else 10138 operands[1] = force_reg (SImode, XEXP (operands[1], 0)); 10139 10140 if (TARGET_FDPIC) 10141 { 10142 operands[1] = sh_load_function_descriptor (operands[1]); 10143 emit_call_insn (gen_call_valuei_fdpic (operands[0], operands[1], 10144 operands[2])); 10145 } 10146 else 10147 emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2])); 10148 DONE; 10149}) 10150 10151(define_insn "sibcalli" 10152 [(call (mem:SI (match_operand:SI 0 "register_operand" "k")) 10153 (match_operand 1 "" "")) 10154 (use (reg:SI FPSCR_MODES_REG)) 10155 (return)] 10156 "TARGET_SH1 && !TARGET_FDPIC" 10157 "jmp @%0%#" 10158 [(set_attr "needs_delay_slot" "yes") 10159 (set (attr "fp_mode") 10160 (if_then_else (eq_attr "fpu_single" "yes") 10161 (const_string "single") (const_string "double"))) 10162 (set_attr "type" "jump_ind")]) 10163 10164(define_insn "sibcalli_fdpic" 10165 [(call (mem:SI (match_operand:SI 0 "register_operand" "k")) 10166 (match_operand 1)) 10167 (use (reg:SI FPSCR_MODES_REG)) 10168 (use (reg:SI PIC_REG)) 10169 (return)] 10170 "TARGET_FDPIC" 10171 "jmp @%0%#" 10172 [(set_attr "needs_delay_slot" "yes") 10173 (set (attr "fp_mode") 10174 (if_then_else (eq_attr "fpu_single" "yes") 10175 (const_string "single") (const_string "double"))) 10176 (set_attr "type" "jump_ind")]) 10177 10178(define_insn "sibcalli_pcrel" 10179 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k")) 10180 (match_operand 1 "" "")) 10181 (use (match_operand 2 "" "")) 10182 (use (reg:SI FPSCR_MODES_REG)) 10183 (return)] 10184 "TARGET_SH2 && !TARGET_FDPIC" 10185{ 10186 return "braf %0" "\n" 10187 "%O2:%#"; 10188} 10189 [(set_attr "needs_delay_slot" "yes") 10190 (set (attr "fp_mode") 10191 (if_then_else (eq_attr "fpu_single" "yes") 10192 (const_string "single") (const_string "double"))) 10193 (set_attr "type" "jump_ind")]) 10194 10195(define_insn "sibcalli_pcrel_fdpic" 10196 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k")) 10197 (match_operand 1)) 10198 (use (match_operand 2)) 10199 (use (reg:SI FPSCR_MODES_REG)) 10200 (use (reg:SI PIC_REG)) 10201 (return)] 10202 "TARGET_SH2 && TARGET_FDPIC" 10203{ 10204 return "braf %0" "\n" 10205 "%O2:%#"; 10206} 10207 [(set_attr "needs_delay_slot" "yes") 10208 (set (attr "fp_mode") 10209 (if_then_else (eq_attr "fpu_single" "yes") 10210 (const_string "single") (const_string "double"))) 10211 (set_attr "type" "jump_ind")]) 10212 10213;; This uses an unspec to describe that the symbol_ref is very close. 10214(define_insn "sibcalli_thunk" 10215 [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")] 10216 UNSPEC_THUNK)) 10217 (match_operand 1 "" "")) 10218 (use (reg:SI FPSCR_MODES_REG)) 10219 (return)] 10220 "TARGET_SH1" 10221 "bra %O0" 10222 [(set_attr "needs_delay_slot" "yes") 10223 (set (attr "fp_mode") 10224 (if_then_else (eq_attr "fpu_single" "yes") 10225 (const_string "single") (const_string "double"))) 10226 (set_attr "type" "jump") 10227 (set_attr "length" "2")]) 10228 10229(define_insn_and_split "sibcall_pcrel" 10230 [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "")) 10231 (match_operand 1 "" "")) 10232 (use (reg:SI FPSCR_MODES_REG)) 10233 (clobber (match_scratch:SI 2 "=&k")) 10234 (return)] 10235 "TARGET_SH2 && !TARGET_FDPIC" 10236 "#" 10237 "reload_completed" 10238 [(const_int 0)] 10239{ 10240 rtx lab = PATTERN (gen_call_site ()); 10241 rtx call_insn; 10242 10243 sh_expand_sym_label2reg (operands[2], operands[0], lab, true); 10244 call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1], 10245 copy_rtx (lab))); 10246 SIBLING_CALL_P (call_insn) = 1; 10247 DONE; 10248} 10249 [(set_attr "needs_delay_slot" "yes") 10250 (set (attr "fp_mode") 10251 (if_then_else (eq_attr "fpu_single" "yes") 10252 (const_string "single") (const_string "double"))) 10253 (set_attr "type" "jump_ind")]) 10254 10255(define_insn_and_split "sibcall_pcrel_fdpic" 10256 [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand")) 10257 (match_operand 1)) 10258 (use (reg:SI FPSCR_MODES_REG)) 10259 (use (reg:SI PIC_REG)) 10260 (clobber (match_scratch:SI 2 "=k")) 10261 (return)] 10262 "TARGET_SH2 && TARGET_FDPIC" 10263 "#" 10264 "&& reload_completed" 10265 [(const_int 0)] 10266{ 10267 rtx lab = PATTERN (gen_call_site ()); 10268 10269 sh_expand_sym_label2reg (operands[2], operands[0], lab, true); 10270 rtx i = emit_call_insn (gen_sibcalli_pcrel_fdpic (operands[2], operands[1], 10271 copy_rtx (lab))); 10272 SIBLING_CALL_P (i) = 1; 10273 DONE; 10274} 10275 [(set_attr "needs_delay_slot" "yes") 10276 (set (attr "fp_mode") 10277 (if_then_else (eq_attr "fpu_single" "yes") 10278 (const_string "single") (const_string "double"))) 10279 (set_attr "type" "jump_ind")]) 10280 10281(define_insn "sibcall_compact" 10282 [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k")) 10283 (match_operand 1 "" "")) 10284 (return) 10285 (use (match_operand:SI 2 "register_operand" "z,x")) 10286 (use (reg:SI R1_REG)) 10287 (use (reg:SI FPSCR_MODES_REG)) 10288 ;; We want to make sure the `x' above will only match MACH_REG 10289 ;; because sibcall_epilogue may clobber MACL_REG. 10290 (clobber (reg:SI MACL_REG))] 10291 "TARGET_SHCOMPACT" 10292{ 10293 static const char* alt[] = 10294 { 10295 "jmp @%0%#", 10296 10297 "jmp @%0" "\n" 10298 " sts %2,r0" 10299 }; 10300 return alt[which_alternative]; 10301} 10302 [(set_attr "needs_delay_slot" "yes,no") 10303 (set_attr "length" "2,4") 10304 (set (attr "fp_mode") (const_string "single")) 10305 (set_attr "type" "jump_ind")]) 10306 10307(define_insn "sibcall_media" 10308 [(call (mem:DI (match_operand 0 "target_reg_operand" "k")) 10309 (match_operand 1 "" "")) 10310 (use (reg:SI PR_MEDIA_REG)) 10311 (return)] 10312 "TARGET_SHMEDIA" 10313 "blink %0, r63" 10314 [(set_attr "type" "jump_media")]) 10315 10316(define_expand "sibcall" 10317 [(parallel 10318 [(call (mem:SI (match_operand 0 "arith_reg_operand" "")) 10319 (match_operand 1 "" "")) 10320 (match_operand 2 "" "") 10321 (use (reg:SI FPSCR_MODES_REG)) 10322 (return)])] 10323 "" 10324{ 10325 if (TARGET_FDPIC) 10326 { 10327 rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG); 10328 emit_move_insn (pic_reg, sh_get_fdpic_reg_initial_val ()); 10329 } 10330 10331 if (TARGET_SHMEDIA) 10332 { 10333 operands[0] = shmedia_prepare_call_address (operands[0], 1); 10334 emit_call_insn (gen_sibcall_media (operands[0], operands[1])); 10335 DONE; 10336 } 10337 else if (TARGET_SHCOMPACT && operands[2] 10338 && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1))) 10339 { 10340 rtx cookie_rtx = operands[2]; 10341 long cookie = INTVAL (cookie_rtx); 10342 rtx func = XEXP (operands[0], 0); 10343 rtx mach, r1; 10344 10345 if (flag_pic) 10346 { 10347 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func)) 10348 { 10349 rtx reg = gen_reg_rtx (Pmode); 10350 10351 emit_insn (gen_symGOT2reg (reg, func)); 10352 func = reg; 10353 } 10354 else 10355 func = legitimize_pic_address (func, Pmode, 0); 10356 } 10357 10358 /* FIXME: if we could tell whether all argument registers are 10359 already taken, we could decide whether to force the use of 10360 MACH_REG or to stick to R0_REG. Unfortunately, there's no 10361 simple way to tell. We could use the CALL_COOKIE, but we 10362 can't currently tell a register used for regular argument 10363 passing from one that is unused. If we leave it up to reload 10364 to decide which register to use, it seems to always choose 10365 R0_REG, which leaves no available registers in SIBCALL_REGS 10366 to hold the address of the trampoline. */ 10367 mach = gen_rtx_REG (SImode, MACH_REG); 10368 r1 = gen_rtx_REG (SImode, R1_REG); 10369 10370 /* Since such a call function may use all call-clobbered 10371 registers, we force a mode switch earlier, so that we don't 10372 run out of registers when adjusting fpscr for the call. */ 10373 emit_insn (gen_force_mode_for_call ()); 10374 10375 operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline", 10376 SFUNC_GOT).sym; 10377 operands[0] = force_reg (SImode, operands[0]); 10378 10379 /* We don't need a return trampoline, since the callee will 10380 return directly to the upper caller. */ 10381 if (cookie & CALL_COOKIE_RET_TRAMP (1)) 10382 { 10383 cookie &= ~ CALL_COOKIE_RET_TRAMP (1); 10384 cookie_rtx = GEN_INT (cookie); 10385 } 10386 10387 emit_move_insn (mach, func); 10388 emit_move_insn (r1, cookie_rtx); 10389 10390 emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach)); 10391 DONE; 10392 } 10393 else if (TARGET_SHCOMPACT && flag_pic 10394 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF 10395 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0))) 10396 { 10397 rtx reg = gen_reg_rtx (Pmode); 10398 10399 emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0))); 10400 XEXP (operands[0], 0) = reg; 10401 } 10402 if (flag_pic && TARGET_SH2 10403 && MEM_P (operands[0]) 10404 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF 10405 /* The PLT needs the PIC register, but the epilogue would have 10406 to restore it, so we can only use PC-relative PIC calls for 10407 static functions. */ 10408 && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0))) 10409 { 10410 if (TARGET_FDPIC) 10411 emit_call_insn (gen_sibcall_pcrel_fdpic (XEXP (operands[0], 0), 10412 operands[1])); 10413 else 10414 emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1])); 10415 DONE; 10416 } 10417 else 10418 operands[0] = force_reg (SImode, XEXP (operands[0], 0)); 10419 10420 if (TARGET_FDPIC) 10421 { 10422 operands[0] = sh_load_function_descriptor (operands[0]); 10423 emit_call_insn (gen_sibcalli_fdpic (operands[0], operands[1])); 10424 } 10425 else 10426 emit_call_insn (gen_sibcalli (operands[0], operands[1])); 10427 DONE; 10428}) 10429 10430(define_insn "sibcall_valuei" 10431 [(set (match_operand 0 "" "=rf") 10432 (call (mem:SI (match_operand:SI 1 "register_operand" "k")) 10433 (match_operand 2 "" ""))) 10434 (use (reg:SI FPSCR_MODES_REG)) 10435 (return)] 10436 "TARGET_SH1 && !TARGET_FDPIC" 10437 "jmp @%1%#" 10438 [(set_attr "needs_delay_slot" "yes") 10439 (set (attr "fp_mode") 10440 (if_then_else (eq_attr "fpu_single" "yes") 10441 (const_string "single") (const_string "double"))) 10442 (set_attr "type" "jump_ind")]) 10443 10444(define_insn "sibcall_valuei_fdpic" 10445 [(set (match_operand 0 "" "=rf") 10446 (call (mem:SI (match_operand:SI 1 "register_operand" "k")) 10447 (match_operand 2))) 10448 (use (reg:SI FPSCR_MODES_REG)) 10449 (use (reg:SI PIC_REG)) 10450 (return)] 10451 "TARGET_FDPIC" 10452 "jmp @%1%#" 10453 [(set_attr "needs_delay_slot" "yes") 10454 (set (attr "fp_mode") 10455 (if_then_else (eq_attr "fpu_single" "yes") 10456 (const_string "single") (const_string "double"))) 10457 (set_attr "type" "jump_ind")]) 10458 10459(define_insn "sibcall_valuei_pcrel" 10460 [(set (match_operand 0 "" "=rf") 10461 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k")) 10462 (match_operand 2 "" ""))) 10463 (use (match_operand 3 "" "")) 10464 (use (reg:SI FPSCR_MODES_REG)) 10465 (return)] 10466 "TARGET_SH2 && !TARGET_FDPIC" 10467{ 10468 return "braf %1" "\n" 10469 "%O3:%#"; 10470} 10471 [(set_attr "needs_delay_slot" "yes") 10472 (set (attr "fp_mode") 10473 (if_then_else (eq_attr "fpu_single" "yes") 10474 (const_string "single") (const_string "double"))) 10475 (set_attr "type" "jump_ind")]) 10476 10477(define_insn "sibcall_valuei_pcrel_fdpic" 10478 [(set (match_operand 0 "" "=rf") 10479 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k")) 10480 (match_operand 2))) 10481 (use (match_operand 3)) 10482 (use (reg:SI FPSCR_MODES_REG)) 10483 (use (reg:SI PIC_REG)) 10484 (return)] 10485 "TARGET_SH2 && TARGET_FDPIC" 10486{ 10487 return "braf %1" "\n" 10488 "%O3:%#"; 10489} 10490 [(set_attr "needs_delay_slot" "yes") 10491 (set (attr "fp_mode") 10492 (if_then_else (eq_attr "fpu_single" "yes") 10493 (const_string "single") (const_string "double"))) 10494 (set_attr "type" "jump_ind")]) 10495 10496;; sibcall_value_pcrel used to have a =&k clobber for the scratch register 10497;; that it needs for the branch address. This causes troubles when there 10498;; is a big overlap of argument and return value registers. Hence, use a 10499;; fixed call clobbered register for the address. See also PR 67260. 10500(define_insn_and_split "sibcall_value_pcrel" 10501 [(set (match_operand 0 "" "=rf") 10502 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "")) 10503 (match_operand 2 "" ""))) 10504 (use (reg:SI FPSCR_MODES_REG)) 10505 (clobber (reg:SI R1_REG)) 10506 (return)] 10507 "TARGET_SH2 && !TARGET_FDPIC" 10508 "#" 10509 "reload_completed" 10510 [(const_int 0)] 10511{ 10512 rtx lab = PATTERN (gen_call_site ()); 10513 rtx call_insn; 10514 10515 operands[3] = gen_rtx_REG (SImode, R1_REG); 10516 10517 sh_expand_sym_label2reg (operands[3], operands[1], lab, true); 10518 call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0], 10519 operands[3], 10520 operands[2], 10521 copy_rtx (lab))); 10522 SIBLING_CALL_P (call_insn) = 1; 10523 DONE; 10524} 10525 [(set_attr "needs_delay_slot" "yes") 10526 (set (attr "fp_mode") 10527 (if_then_else (eq_attr "fpu_single" "yes") 10528 (const_string "single") (const_string "double"))) 10529 (set_attr "type" "jump_ind")]) 10530 10531;; Like for sibcall_value_pcrel, use a fixed call clobbered register for 10532;; the branch address. 10533(define_insn_and_split "sibcall_value_pcrel_fdpic" 10534 [(set (match_operand 0 "" "=rf") 10535 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand")) 10536 (match_operand 2))) 10537 (use (reg:SI FPSCR_MODES_REG)) 10538 (use (reg:SI PIC_REG)) 10539 (clobber (reg:SI R1_REG)) 10540 (return)] 10541 "TARGET_SH2 && TARGET_FDPIC" 10542 "#" 10543 "&& reload_completed" 10544 [(const_int 0)] 10545{ 10546 rtx lab = PATTERN (gen_call_site ()); 10547 10548 operands[3] = gen_rtx_REG (SImode, R1_REG); 10549 10550 sh_expand_sym_label2reg (operands[3], operands[1], lab, true); 10551 rtx i = emit_call_insn (gen_sibcall_valuei_pcrel_fdpic (operands[0], 10552 operands[3], 10553 operands[2], 10554 copy_rtx (lab))); 10555 SIBLING_CALL_P (i) = 1; 10556 DONE; 10557} 10558 [(set_attr "needs_delay_slot" "yes") 10559 (set (attr "fp_mode") 10560 (if_then_else (eq_attr "fpu_single" "yes") 10561 (const_string "single") (const_string "double"))) 10562 (set_attr "type" "jump_ind")]) 10563 10564(define_insn "sibcall_value_compact" 10565 [(set (match_operand 0 "" "=rf,rf") 10566 (call (mem:SI (match_operand:SI 1 "register_operand" "k,k")) 10567 (match_operand 2 "" ""))) 10568 (return) 10569 (use (match_operand:SI 3 "register_operand" "z,x")) 10570 (use (reg:SI R1_REG)) 10571 (use (reg:SI FPSCR_MODES_REG)) 10572 ;; We want to make sure the `x' above will only match MACH_REG 10573 ;; because sibcall_epilogue may clobber MACL_REG. 10574 (clobber (reg:SI MACL_REG))] 10575 "TARGET_SHCOMPACT" 10576{ 10577 static const char* alt[] = 10578 { 10579 "jmp @%1%#", 10580 10581 "jmp @%1" "\n" 10582 " sts %3,r0" 10583 }; 10584 return alt[which_alternative]; 10585} 10586 [(set_attr "needs_delay_slot" "yes,no") 10587 (set_attr "length" "2,4") 10588 (set (attr "fp_mode") (const_string "single")) 10589 (set_attr "type" "jump_ind")]) 10590 10591(define_insn "sibcall_value_media" 10592 [(set (match_operand 0 "" "=rf") 10593 (call (mem:DI (match_operand 1 "target_reg_operand" "k")) 10594 (match_operand 2 "" ""))) 10595 (use (reg:SI PR_MEDIA_REG)) 10596 (return)] 10597 "TARGET_SHMEDIA" 10598 "blink %1, r63" 10599 [(set_attr "type" "jump_media")]) 10600 10601(define_expand "sibcall_value" 10602 [(parallel 10603 [(set (match_operand 0 "arith_reg_operand" "") 10604 (call (mem:SI (match_operand 1 "arith_reg_operand" "")) 10605 (match_operand 2 "" ""))) 10606 (match_operand 3 "" "") 10607 (use (reg:SI FPSCR_MODES_REG)) 10608 (return)])] 10609 "" 10610{ 10611 if (TARGET_FDPIC) 10612 { 10613 rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG); 10614 emit_move_insn (pic_reg, sh_get_fdpic_reg_initial_val ()); 10615 } 10616 10617 if (TARGET_SHMEDIA) 10618 { 10619 operands[1] = shmedia_prepare_call_address (operands[1], 1); 10620 emit_call_insn (gen_sibcall_value_media (operands[0], operands[1], 10621 operands[2])); 10622 DONE; 10623 } 10624 else if (TARGET_SHCOMPACT && operands[3] 10625 && (INTVAL (operands[3]) & ~ CALL_COOKIE_RET_TRAMP (1))) 10626 { 10627 rtx cookie_rtx = operands[3]; 10628 long cookie = INTVAL (cookie_rtx); 10629 rtx func = XEXP (operands[1], 0); 10630 rtx mach, r1; 10631 10632 if (flag_pic) 10633 { 10634 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func)) 10635 { 10636 rtx reg = gen_reg_rtx (Pmode); 10637 10638 emit_insn (gen_symGOT2reg (reg, func)); 10639 func = reg; 10640 } 10641 else 10642 func = legitimize_pic_address (func, Pmode, 0); 10643 } 10644 10645 /* FIXME: if we could tell whether all argument registers are 10646 already taken, we could decide whether to force the use of 10647 MACH_REG or to stick to R0_REG. Unfortunately, there's no 10648 simple way to tell. We could use the CALL_COOKIE, but we 10649 can't currently tell a register used for regular argument 10650 passing from one that is unused. If we leave it up to reload 10651 to decide which register to use, it seems to always choose 10652 R0_REG, which leaves no available registers in SIBCALL_REGS 10653 to hold the address of the trampoline. */ 10654 mach = gen_rtx_REG (SImode, MACH_REG); 10655 r1 = gen_rtx_REG (SImode, R1_REG); 10656 10657 /* Since such a call function may use all call-clobbered 10658 registers, we force a mode switch earlier, so that we don't 10659 run out of registers when adjusting fpscr for the call. */ 10660 emit_insn (gen_force_mode_for_call ()); 10661 10662 operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline", 10663 SFUNC_GOT).sym; 10664 operands[1] = force_reg (SImode, operands[1]); 10665 10666 /* We don't need a return trampoline, since the callee will 10667 return directly to the upper caller. */ 10668 if (cookie & CALL_COOKIE_RET_TRAMP (1)) 10669 { 10670 cookie &= ~ CALL_COOKIE_RET_TRAMP (1); 10671 cookie_rtx = GEN_INT (cookie); 10672 } 10673 10674 emit_move_insn (mach, func); 10675 emit_move_insn (r1, cookie_rtx); 10676 10677 emit_call_insn (gen_sibcall_value_compact (operands[0], operands[1], 10678 operands[2], mach)); 10679 DONE; 10680 } 10681 else if (TARGET_SHCOMPACT && flag_pic 10682 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF 10683 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0))) 10684 { 10685 rtx reg = gen_reg_rtx (Pmode); 10686 10687 emit_insn (gen_symGOT2reg (reg, XEXP (operands[1], 0))); 10688 XEXP (operands[1], 0) = reg; 10689 } 10690 if (flag_pic && TARGET_SH2 10691 && MEM_P (operands[1]) 10692 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF 10693 /* The PLT needs the PIC register, but the epilogue would have 10694 to restore it, so we can only use PC-relative PIC calls for 10695 static functions. */ 10696 && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0))) 10697 { 10698 if (TARGET_FDPIC) 10699 emit_call_insn (gen_sibcall_value_pcrel_fdpic (operands[0], 10700 XEXP (operands[1], 0), 10701 operands[2])); 10702 else 10703 emit_call_insn (gen_sibcall_value_pcrel (operands[0], 10704 XEXP (operands[1], 0), 10705 operands[2])); 10706 DONE; 10707 } 10708 else 10709 operands[1] = force_reg (SImode, XEXP (operands[1], 0)); 10710 10711 if (TARGET_FDPIC) 10712 { 10713 operands[1] = sh_load_function_descriptor (operands[1]); 10714 emit_call_insn (gen_sibcall_valuei_fdpic (operands[0], operands[1], 10715 operands[2])); 10716 } 10717 else 10718 emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2])); 10719 DONE; 10720}) 10721 10722(define_insn "call_value_pop_compact" 10723 [(set (match_operand 0 "" "=rf") 10724 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) 10725 (match_operand 2 "" ""))) 10726 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) 10727 (match_operand 4 "immediate_operand" "n"))) 10728 (match_operand 3 "immediate_operand" "n") 10729 (use (reg:SI R0_REG)) 10730 (use (reg:SI R1_REG)) 10731 (use (reg:SI FPSCR_MODES_REG)) 10732 (clobber (reg:SI PR_REG))] 10733 "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))" 10734 "jsr @%1%#" 10735 [(set_attr "type" "call") 10736 (set (attr "fp_mode") 10737 (if_then_else (eq_attr "fpu_single" "yes") 10738 (const_string "single") (const_string "double"))) 10739 (set_attr "needs_delay_slot" "yes")]) 10740 10741(define_insn "call_value_pop_compact_rettramp" 10742 [(set (match_operand 0 "" "=rf") 10743 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) 10744 (match_operand 2 "" ""))) 10745 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) 10746 (match_operand 4 "immediate_operand" "n"))) 10747 (match_operand 3 "immediate_operand" "n") 10748 (use (reg:SI R0_REG)) 10749 (use (reg:SI R1_REG)) 10750 (use (reg:SI FPSCR_MODES_REG)) 10751 (clobber (reg:SI R10_REG)) 10752 (clobber (reg:SI PR_REG))] 10753 "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))" 10754 "jsr @%1%#" 10755 [(set_attr "type" "call") 10756 (set (attr "fp_mode") 10757 (if_then_else (eq_attr "fpu_single" "yes") 10758 (const_string "single") (const_string "double"))) 10759 (set_attr "needs_delay_slot" "yes")]) 10760 10761(define_expand "call_value_pop" 10762 [(parallel [(set (match_operand 0 "arith_reg_operand" "") 10763 (call (mem:SI (match_operand 1 "arith_reg_operand" "")) 10764 (match_operand 2 "" ""))) 10765 (match_operand 3 "" "") 10766 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) 10767 (match_operand 4 "" "")))])] 10768 "TARGET_SHCOMPACT" 10769{ 10770 rtx cookie_rtx; 10771 long cookie; 10772 rtx func; 10773 rtx r0, r1; 10774 10775 gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3])); 10776 cookie_rtx = operands[3]; 10777 cookie = INTVAL (cookie_rtx); 10778 func = XEXP (operands[1], 0); 10779 10780 if (flag_pic) 10781 { 10782 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func)) 10783 { 10784 rtx reg = gen_reg_rtx (Pmode); 10785 10786 emit_insn (gen_symGOTPLT2reg (reg, func)); 10787 func = reg; 10788 } 10789 else 10790 func = legitimize_pic_address (func, Pmode, 0); 10791 } 10792 10793 r0 = gen_rtx_REG (SImode, R0_REG); 10794 r1 = gen_rtx_REG (SImode, R1_REG); 10795 10796 /* Since such a call function may use all call-clobbered 10797 registers, we force a mode switch earlier, so that we don't 10798 run out of registers when adjusting fpscr for the call. */ 10799 emit_insn (gen_force_mode_for_call ()); 10800 10801 operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline", 10802 SFUNC_GOT).sym; 10803 operands[1] = force_reg (SImode, operands[1]); 10804 10805 emit_move_insn (r0, func); 10806 emit_move_insn (r1, cookie_rtx); 10807 10808 if (cookie & CALL_COOKIE_RET_TRAMP (1)) 10809 emit_call_insn (gen_call_value_pop_compact_rettramp 10810 (operands[0], operands[1], operands[2], 10811 operands[3], operands[4])); 10812 else 10813 emit_call_insn (gen_call_value_pop_compact 10814 (operands[0], operands[1], operands[2], 10815 operands[3], operands[4])); 10816 10817 DONE; 10818}) 10819 10820(define_expand "sibcall_epilogue" 10821 [(return)] 10822 "" 10823{ 10824 sh_expand_epilogue (true); 10825 if (TARGET_SHCOMPACT) 10826 { 10827 rtx_insn *insn; 10828 rtx set; 10829 10830 /* If epilogue clobbers r0, preserve it in macl. */ 10831 for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) 10832 if ((set = single_set (insn)) 10833 && REG_P (SET_DEST (set)) 10834 && REGNO (SET_DEST (set)) == R0_REG) 10835 { 10836 rtx r0 = gen_rtx_REG (SImode, R0_REG); 10837 rtx tmp = gen_rtx_REG (SImode, MACL_REG); 10838 10839 /* We can't tell at this point whether the sibcall is a 10840 sibcall_compact and, if it is, whether it uses r0 or 10841 mach as operand 2, so let the instructions that 10842 preserve r0 be optimized away if r0 turns out to be 10843 dead. */ 10844 emit_insn_before (gen_rtx_SET (tmp, r0), insn); 10845 emit_move_insn (r0, tmp); 10846 break; 10847 } 10848 } 10849 DONE; 10850}) 10851 10852(define_insn "indirect_jump_compact" 10853 [(set (pc) 10854 (match_operand:SI 0 "arith_reg_operand" "r"))] 10855 "TARGET_SH1" 10856 "jmp @%0%#" 10857 [(set_attr "needs_delay_slot" "yes") 10858 (set_attr "type" "jump_ind")]) 10859 10860(define_expand "indirect_jump" 10861 [(set (pc) 10862 (match_operand 0 "register_operand" ""))] 10863 "" 10864{ 10865 if (GET_MODE (operands[0]) != Pmode) 10866 operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0); 10867}) 10868 10869;; The use of operand 1 / 2 helps us distinguish case table jumps 10870;; which can be present in structured code from indirect jumps which can not 10871;; be present in structured code. This allows -fprofile-arcs to work. 10872 10873;; For SH1 processors. 10874(define_insn "casesi_jump_1" 10875 [(set (pc) 10876 (match_operand:SI 0 "register_operand" "r")) 10877 (use (label_ref (match_operand 1 "" "")))] 10878 "TARGET_SH1" 10879 "jmp @%0%#" 10880 [(set_attr "needs_delay_slot" "yes") 10881 (set_attr "type" "jump_ind")]) 10882 10883;; For all later processors. 10884(define_insn "casesi_jump_2" 10885 [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r") 10886 (label_ref (match_operand 1 "" "")))) 10887 (use (label_ref (match_operand 2 "" "")))] 10888 "TARGET_SH2 10889 && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)" 10890 "braf %0%#" 10891 [(set_attr "needs_delay_slot" "yes") 10892 (set_attr "type" "jump_ind")]) 10893 10894(define_insn "casesi_jump_media" 10895 [(set (pc) (match_operand 0 "target_reg_operand" "b")) 10896 (use (label_ref (match_operand 1 "" "")))] 10897 "TARGET_SHMEDIA" 10898 "blink %0, r63" 10899 [(set_attr "type" "jump_media")]) 10900 10901;; Call subroutine returning any type. 10902;; ??? This probably doesn't work. 10903(define_expand "untyped_call" 10904 [(parallel [(call (match_operand 0 "" "") 10905 (const_int 0)) 10906 (match_operand 1 "" "") 10907 (match_operand 2 "" "")])] 10908 "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA" 10909{ 10910 if (! TARGET_SHMEDIA) 10911 { 10912 /* RA does not know that the call sets the function value registers. 10913 We avoid problems by claiming that those registers are clobbered 10914 at this point. */ 10915 for (int i = 0; i < XVECLEN (operands[2], 0); i++) 10916 { 10917 rtx set = XVECEXP (operands[2], 0, i); 10918 emit_clobber (SET_SRC (set)); 10919 } 10920 } 10921 10922 emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx)); 10923 10924 for (int i = 0; i < XVECLEN (operands[2], 0); i++) 10925 { 10926 rtx set = XVECEXP (operands[2], 0, i); 10927 emit_move_insn (SET_DEST (set), SET_SRC (set)); 10928 } 10929 10930 /* The optimizer does not know that the call sets the function value 10931 registers we stored in the result block. We avoid problems by 10932 claiming that all hard registers are used and clobbered at this 10933 point. */ 10934 emit_insn (gen_blockage ()); 10935 10936 DONE; 10937}) 10938 10939;; ------------------------------------------------------------------------ 10940;; Misc insns 10941;; ------------------------------------------------------------------------ 10942 10943(define_insn "dect" 10944 [(set (reg:SI T_REG) 10945 (eq:SI (match_operand:SI 1 "arith_reg_dest" "0") (const_int 1))) 10946 (set (match_operand:SI 0 "arith_reg_dest" "=r") 10947 (plus:SI (match_dup 1) (const_int -1)))] 10948 "TARGET_SH2" 10949 "dt %0" 10950 [(set_attr "type" "arith")]) 10951 10952(define_insn "nop" 10953 [(const_int 0)] 10954 "" 10955 "nop") 10956 10957;; Load address of a label. This is only generated by the casesi expand, 10958;; and by machine_dependent_reorg (fixing up fp moves). 10959;; This must use unspec, because this only works for labels that are 10960;; within range. 10961(define_insn "mova" 10962 [(set (reg:SI R0_REG) 10963 (unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))] 10964 "TARGET_SH1" 10965 "mova %O0,r0" 10966 [(set_attr "in_delay_slot" "no") 10967 (set_attr "type" "arith")]) 10968 10969;; machine_dependent_reorg will make this a `mova'. 10970(define_insn "mova_const" 10971 [(set (reg:SI R0_REG) 10972 (unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))] 10973 "TARGET_SH1" 10974 "#" 10975 [(set_attr "in_delay_slot" "no") 10976 (set_attr "type" "arith")]) 10977 10978;; Loads of the GOTPC relocation values must not be optimized away 10979;; by e.g. any kind of CSE and must stay as they are. Although there 10980;; are other various ways to ensure this, we use an artificial counter 10981;; operand to generate unique symbols. 10982(define_expand "GOTaddr2picreg" 10983 [(set (reg:SI R0_REG) 10984 (unspec:SI [(const:SI (unspec:SI [(match_dup 2) 10985 (match_operand:SI 0 "" "")] 10986 UNSPEC_PIC))] UNSPEC_MOVA)) 10987 (set (match_dup 1) 10988 (const:SI (unspec:SI [(match_dup 2) (match_dup 0)] UNSPEC_PIC))) 10989 (set (match_dup 1) (plus:SI (match_dup 1) (reg:SI R0_REG)))] 10990 "" 10991{ 10992 if (TARGET_VXWORKS_RTP) 10993 { 10994 rtx gott_base = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE); 10995 rtx gott_index = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX); 10996 emit_insn (gen_vxworks_picreg (gott_base, gott_index)); 10997 DONE; 10998 } 10999 11000 if (TARGET_FDPIC) 11001 { 11002 rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG); 11003 emit_move_insn (pic_reg, sh_get_fdpic_reg_initial_val ()); 11004 DONE; 11005 } 11006 11007 operands[1] = gen_rtx_REG (Pmode, PIC_REG); 11008 operands[2] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME); 11009 11010 if (TARGET_SHMEDIA) 11011 { 11012 rtx tr = gen_rtx_REG (Pmode, TR0_REG); 11013 rtx pic = operands[1]; 11014 rtx lab = PATTERN (gen_call_site ()); 11015 rtx insn, equiv; 11016 11017 equiv = operands[2]; 11018 operands[2] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[2], lab), 11019 UNSPEC_PCREL_SYMOFF); 11020 operands[2] = gen_rtx_CONST (Pmode, operands[2]); 11021 11022 if (Pmode == SImode) 11023 { 11024 emit_insn (gen_movsi_const (pic, operands[2])); 11025 emit_insn (gen_ptrel_si (tr, pic, copy_rtx (lab))); 11026 } 11027 else 11028 { 11029 emit_insn (gen_movdi_const (pic, operands[2])); 11030 emit_insn (gen_ptrel_di (tr, pic, copy_rtx (lab))); 11031 } 11032 11033 insn = emit_move_insn (operands[1], tr); 11034 11035 set_unique_reg_note (insn, REG_EQUAL, equiv); 11036 11037 DONE; 11038 } 11039}) 11040 11041;; A helper for GOTaddr2picreg to finish up the initialization of the 11042;; PIC register. 11043(define_expand "vxworks_picreg" 11044 [(set (reg:SI PIC_REG) 11045 (const:SI (unspec:SI [(match_operand:SI 0 "" "")] UNSPEC_PIC))) 11046 (set (reg:SI R0_REG) 11047 (const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC))) 11048 (set (reg:SI PIC_REG) 11049 (mem:SI (reg:SI PIC_REG))) 11050 (set (reg:SI PIC_REG) 11051 (mem:SI (plus:SI (reg:SI PIC_REG) 11052 (reg:SI R0_REG))))] 11053 "TARGET_VXWORKS_RTP") 11054 11055(define_insn "*ptb" 11056 [(set (match_operand 0 "target_reg_operand" "=b") 11057 (const (unspec [(match_operand 1 "" "Csy")] 11058 UNSPEC_DATALABEL)))] 11059 "TARGET_SHMEDIA && flag_pic 11060 && satisfies_constraint_Csy (operands[1])" 11061 "ptb/u datalabel %1, %0" 11062 [(set_attr "type" "ptabs_media") 11063 (set_attr "length" "*")]) 11064 11065(define_insn "ptrel_si" 11066 [(set (match_operand:SI 0 "target_reg_operand" "=b") 11067 (plus:SI (match_operand:SI 1 "register_operand" "r") 11068 (pc))) 11069 (match_operand:SI 2 "" "")] 11070 "TARGET_SHMEDIA" 11071 "%O2: ptrel/u %1, %0" 11072 [(set_attr "type" "ptabs_media")]) 11073 11074(define_insn "ptrel_di" 11075 [(set (match_operand:DI 0 "target_reg_operand" "=b") 11076 (plus:DI (match_operand:DI 1 "register_operand" "r") 11077 (pc))) 11078 (match_operand:DI 2 "" "")] 11079 "TARGET_SHMEDIA" 11080 "%O2: ptrel/u %1, %0" 11081 [(set_attr "type" "ptabs_media")]) 11082 11083(define_expand "builtin_setjmp_receiver" 11084 [(match_operand 0 "" "")] 11085 "flag_pic" 11086{ 11087 emit_insn (gen_GOTaddr2picreg (const0_rtx)); 11088 DONE; 11089}) 11090 11091(define_expand "call_site" 11092 [(unspec [(match_dup 0)] UNSPEC_CALLER)] 11093 "TARGET_SH1" 11094{ 11095 static HOST_WIDE_INT i = 0; 11096 operands[0] = GEN_INT (i); 11097 i++; 11098}) 11099 11100;; op0 = op1 + r12 but hide it before reload completed. See the comment 11101;; in symGOT_load expand. 11102(define_insn_and_split "chk_guard_add" 11103 [(set (match_operand:SI 0 "register_operand" "=&r") 11104 (unspec:SI [(match_operand:SI 1 "register_operand" "r") 11105 (reg:SI PIC_REG)] 11106 UNSPEC_CHKADD))] 11107 "TARGET_SH1" 11108 "#" 11109 "TARGET_SH1 && reload_completed" 11110 [(set (match_dup 0) (reg:SI PIC_REG)) 11111 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))] 11112 "" 11113 [(set_attr "type" "arith")]) 11114 11115(define_expand "sym_label2reg" 11116 [(set (match_operand:SI 0 "" "") 11117 (const:SI (unspec:SI [(match_operand:SI 1 "" "") 11118 (const (plus:SI (match_operand:SI 2 "" "") 11119 (const_int 2)))] 11120 UNSPEC_SYMOFF)))] 11121 "TARGET_SH1" "") 11122 11123(define_expand "symPCREL_label2reg" 11124 [(set (match_operand:SI 0 "" "") 11125 (const:SI 11126 (unspec:SI 11127 [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PCREL)) 11128 (const:SI (plus:SI (match_operand:SI 2 "" "") 11129 (const_int 2)))] UNSPEC_PCREL_SYMOFF)))] 11130 "TARGET_SH1" 11131 "") 11132 11133(define_expand "symGOT_load" 11134 [(set (match_dup 2) (match_operand 1 "" "")) 11135 (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG))) 11136 (set (match_operand 0 "" "") (mem (match_dup 3)))] 11137 "" 11138{ 11139 rtx mem; 11140 bool stack_chk_guard_p = false; 11141 11142 rtx picreg = TARGET_FDPIC ? sh_get_fdpic_reg_initial_val () 11143 : gen_rtx_REG (Pmode, PIC_REG); 11144 11145 operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode); 11146 operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode); 11147 11148 if (!TARGET_SHMEDIA && !TARGET_FDPIC 11149 && flag_stack_protect 11150 && GET_CODE (operands[1]) == CONST 11151 && GET_CODE (XEXP (operands[1], 0)) == UNSPEC 11152 && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == SYMBOL_REF 11153 && strcmp (XSTR (XVECEXP (XEXP (operands[1], 0), 0, 0), 0), 11154 "__stack_chk_guard") == 0) 11155 stack_chk_guard_p = true; 11156 11157 if (TARGET_SHMEDIA) 11158 { 11159 rtx reg = operands[2]; 11160 11161 if (Pmode == DImode) 11162 { 11163 if (flag_pic > 1) 11164 emit_insn (gen_movdi_const_32bit (reg, operands[1])); 11165 else 11166 emit_insn (gen_movdi_const_16bit (reg, operands[1])); 11167 } 11168 else 11169 { 11170 if (flag_pic > 1) 11171 emit_insn (gen_movsi_const (reg, operands[1])); 11172 else 11173 emit_insn (gen_movsi_const_16bit (reg, operands[1])); 11174 } 11175 } 11176 else 11177 emit_move_insn (operands[2], operands[1]); 11178 11179 /* When stack protector inserts codes after the result is set to 11180 R0, @(rX, r12) will cause a spill failure for R0. Use a unspec 11181 insn to avoid combining (set A (plus rX r12)) and (set op0 (mem A)) 11182 when rX is a GOT address for the guard symbol. Ugly but doesn't 11183 matter because this is a rare situation. */ 11184 if (stack_chk_guard_p) 11185 emit_insn (gen_chk_guard_add (operands[3], operands[2])); 11186 else 11187 emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2], picreg)); 11188 11189 /* N.B. This is not constant for a GOTPLT relocation. */ 11190 mem = gen_rtx_MEM (Pmode, operands[3]); 11191 MEM_NOTRAP_P (mem) = 1; 11192 /* ??? Should we have a special alias set for the GOT? */ 11193 emit_move_insn (operands[0], mem); 11194 11195 DONE; 11196}) 11197 11198(define_expand "sym2GOT" 11199 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))] 11200 "" 11201 "") 11202 11203(define_expand "symGOT2reg" 11204 [(match_operand 0 "" "") (match_operand 1 "" "")] 11205 "" 11206{ 11207 rtx gotsym, insn; 11208 11209 gotsym = gen_sym2GOT (operands[1]); 11210 PUT_MODE (gotsym, Pmode); 11211 insn = emit_insn (gen_symGOT_load (operands[0], gotsym)); 11212 11213 MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1; 11214 11215 DONE; 11216}) 11217 11218(define_expand "sym2GOTFUNCDESC" 11219 [(const (unspec [(match_operand 0)] UNSPEC_GOTFUNCDESC))] 11220 "TARGET_FDPIC") 11221 11222(define_expand "symGOTFUNCDESC2reg" 11223 [(match_operand 0) (match_operand 1)] 11224 "TARGET_FDPIC" 11225{ 11226 rtx gotsym = gen_sym2GOTFUNCDESC (operands[1]); 11227 PUT_MODE (gotsym, Pmode); 11228 rtx insn = emit_insn (gen_symGOT_load (operands[0], gotsym)); 11229 11230 MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1; 11231 11232 DONE; 11233}) 11234 11235(define_expand "symGOTPLT2reg" 11236 [(match_operand 0 "" "") (match_operand 1 "" "")] 11237 "" 11238{ 11239 rtx pltsym = gen_rtx_CONST (Pmode, 11240 gen_rtx_UNSPEC (Pmode, 11241 gen_rtvec (1, operands[1]), 11242 UNSPEC_GOTPLT)); 11243 emit_insn (gen_symGOT_load (operands[0], pltsym)); 11244 DONE; 11245}) 11246 11247(define_expand "sym2GOTOFF" 11248 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))] 11249 "" 11250 "") 11251 11252(define_expand "symGOTOFF2reg" 11253 [(match_operand 0 "" "") (match_operand 1 "" "")] 11254 "" 11255{ 11256 rtx gotoffsym, insn; 11257 rtx t = (!can_create_pseudo_p () 11258 ? operands[0] 11259 : gen_reg_rtx (GET_MODE (operands[0]))); 11260 11261 rtx picreg = TARGET_FDPIC ? sh_get_fdpic_reg_initial_val () 11262 : gen_rtx_REG (Pmode, PIC_REG); 11263 11264 gotoffsym = gen_sym2GOTOFF (operands[1]); 11265 PUT_MODE (gotoffsym, Pmode); 11266 emit_move_insn (t, gotoffsym); 11267 insn = emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, picreg)); 11268 11269 set_unique_reg_note (insn, REG_EQUAL, operands[1]); 11270 11271 DONE; 11272}) 11273 11274(define_expand "sym2GOTOFFFUNCDESC" 11275 [(const (unspec [(match_operand 0)] UNSPEC_GOTOFFFUNCDESC))] 11276 "TARGET_FDPIC") 11277 11278(define_expand "symGOTOFFFUNCDESC2reg" 11279 [(match_operand 0) (match_operand 1)] 11280 "TARGET_FDPIC" 11281{ 11282 rtx picreg = sh_get_fdpic_reg_initial_val (); 11283 rtx t = !can_create_pseudo_p () 11284 ? operands[0] 11285 : gen_reg_rtx (GET_MODE (operands[0])); 11286 11287 rtx gotoffsym = gen_sym2GOTOFFFUNCDESC (operands[1]); 11288 PUT_MODE (gotoffsym, Pmode); 11289 emit_move_insn (t, gotoffsym); 11290 emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, picreg)); 11291 DONE; 11292}) 11293 11294(define_expand "symPLT_label2reg" 11295 [(set (match_operand:SI 0 "" "") 11296 (const:SI 11297 (unspec:SI 11298 [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT)) 11299 (const:SI (plus:SI (match_operand:SI 2 "" "") 11300 (const_int 2)))] UNSPEC_PCREL_SYMOFF))) 11301 ;; Even though the PIC register is not really used by the call 11302 ;; sequence in which this is expanded, the PLT code assumes the PIC 11303 ;; register is set, so we must not skip its initialization. Since 11304 ;; we only use this expand as part of calling sequences, and never 11305 ;; to take the address of a function, this is the best point to 11306 ;; insert the (use). Using the PLT to take the address of a 11307 ;; function would be wrong, not only because the PLT entry could 11308 ;; then be called from a function that doesn't initialize the PIC 11309 ;; register to the proper GOT, but also because pointers to the 11310 ;; same function might not compare equal, should they be set by 11311 ;; different shared libraries. 11312 (use (reg:SI PIC_REG))] 11313 "TARGET_SH1" 11314 "") 11315 11316(define_expand "sym2PIC" 11317 [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))] 11318 "" 11319 "") 11320 11321;; ------------------------------------------------------------------------- 11322;; TLS code generation. 11323 11324;; FIXME: The multi-insn asm blocks should be converted to use 11325;; define_insn_and_split. 11326;; See the thread [PATCH/RFA] SH TLS support on gcc-patches 11327;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html> 11328;; for details. 11329 11330(define_insn "tls_global_dynamic" 11331 [(set (match_operand:SI 0 "register_operand" "=&z") 11332 (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")] 11333 UNSPEC_TLSGD)) 11334 (const_int 0))) 11335 (use (reg:SI FPSCR_MODES_REG)) 11336 (use (reg:SI PIC_REG)) 11337 (clobber (reg:SI PR_REG)) 11338 (clobber (scratch:SI))] 11339 "TARGET_SH1" 11340{ 11341 return "mov.l 1f,r4" "\n" 11342 " mova 2f,r0" "\n" 11343 " mov.l 2f,r1" "\n" 11344 " add r0,r1" "\n" 11345 " jsr @r1" "\n" 11346 " add r12,r4" "\n" 11347 " bra 3f" "\n" 11348 " nop" "\n" 11349 " .align 2" "\n" 11350 "1: .long %a1@TLSGD" "\n" 11351 "2: .long __tls_get_addr@PLT" "\n" 11352 "3:"; 11353} 11354 [(set_attr "type" "tls_load") 11355 (set_attr "length" "26")]) 11356 11357(define_insn "tls_local_dynamic" 11358 [(set (match_operand:SI 0 "register_operand" "=&z") 11359 (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")] 11360 UNSPEC_TLSLDM)) 11361 (const_int 0))) 11362 (use (reg:SI FPSCR_MODES_REG)) 11363 (use (reg:SI PIC_REG)) 11364 (clobber (reg:SI PR_REG)) 11365 (clobber (scratch:SI))] 11366 "TARGET_SH1" 11367{ 11368 return "mov.l 1f,r4" "\n" 11369 " mova 2f,r0" "\n" 11370 " mov.l 2f,r1" "\n" 11371 " add r0,r1" "\n" 11372 " jsr @r1" "\n" 11373 " add r12,r4" "\n" 11374 " bra 3f" "\n" 11375 " nop" "\n" 11376 " .align 2" "\n" 11377 "1: .long %a1@TLSLDM" "\n" 11378 "2: .long __tls_get_addr@PLT" "\n" 11379 "3:"; 11380} 11381 [(set_attr "type" "tls_load") 11382 (set_attr "length" "26")]) 11383 11384(define_expand "sym2DTPOFF" 11385 [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))] 11386 "" 11387 "") 11388 11389(define_expand "symDTPOFF2reg" 11390 [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")] 11391 "" 11392{ 11393 rtx dtpoffsym; 11394 rtx t = (!can_create_pseudo_p () 11395 ? operands[0] 11396 : gen_reg_rtx (GET_MODE (operands[0]))); 11397 11398 dtpoffsym = gen_sym2DTPOFF (operands[1]); 11399 PUT_MODE (dtpoffsym, Pmode); 11400 emit_move_insn (t, dtpoffsym); 11401 emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, operands[2])); 11402 DONE; 11403}) 11404 11405(define_expand "sym2GOTTPOFF" 11406 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))] 11407 "" 11408 "") 11409 11410(define_insn "tls_initial_exec" 11411 [(set (match_operand:SI 0 "register_operand" "=&r") 11412 (unspec:SI [(match_operand:SI 1 "" "")] 11413 UNSPEC_TLSIE)) 11414 (use (reg:SI GBR_REG)) 11415 (use (reg:SI PIC_REG)) 11416 (clobber (reg:SI R0_REG))] 11417 "" 11418{ 11419 return "mov.l 1f,r0" "\n" 11420 " stc gbr,%0" "\n" 11421 " mov.l @(r0,r12),r0" "\n" 11422 " bra 2f" "\n" 11423 " add r0,%0" "\n" 11424 " .align 2" "\n" 11425 "1: .long %a1" "\n" 11426 "2:"; 11427} 11428 [(set_attr "type" "tls_load") 11429 (set_attr "length" "16")]) 11430 11431(define_expand "sym2TPOFF" 11432 [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))] 11433 "" 11434 "") 11435 11436(define_expand "symTPOFF2reg" 11437 [(match_operand 0 "" "") (match_operand 1 "" "")] 11438 "" 11439{ 11440 rtx tpoffsym; 11441 11442 tpoffsym = gen_sym2TPOFF (operands[1]); 11443 PUT_MODE (tpoffsym, Pmode); 11444 emit_move_insn (operands[0], tpoffsym); 11445 DONE; 11446}) 11447 11448;;------------------------------------------------------------------------------ 11449;; Thread pointer getter and setter. 11450;; 11451;; On SH the thread pointer is kept in the GBR. 11452;; These patterns are usually expanded from the respective built-in functions. 11453(define_expand "get_thread_pointersi" 11454 [(set (match_operand:SI 0 "arith_reg_dest") (reg:SI GBR_REG))] 11455 "TARGET_SH1") 11456 11457;; The store_gbr insn can also be used on !TARGET_SH1 for doing TLS accesses. 11458(define_insn "store_gbr" 11459 [(set (match_operand:SI 0 "arith_reg_dest" "=r") (reg:SI GBR_REG))] 11460 "" 11461 "stc gbr,%0" 11462 [(set_attr "type" "tls_load")]) 11463 11464(define_expand "set_thread_pointersi" 11465 [(set (reg:SI GBR_REG) 11466 (unspec_volatile:SI [(match_operand:SI 0 "arith_reg_operand")] 11467 UNSPECV_GBR))] 11468 "TARGET_SH1") 11469 11470(define_insn "load_gbr" 11471 [(set (reg:SI GBR_REG) 11472 (unspec_volatile:SI [(match_operand:SI 0 "arith_reg_operand" "r")] 11473 UNSPECV_GBR))] 11474 "TARGET_SH1" 11475 "ldc %0,gbr" 11476 [(set_attr "type" "move")]) 11477 11478;;------------------------------------------------------------------------------ 11479;; Thread pointer relative memory loads and stores. 11480;; 11481;; On SH there are GBR displacement address modes which can be utilized to 11482;; access memory behind the thread pointer. 11483;; Since we do not allow using GBR for general purpose memory accesses, these 11484;; GBR addressing modes are formed by the combine pass. 11485;; This could be done with fewer patterns than below by using a mem predicate 11486;; for the GBR mem, but then reload would try to reload addresses with a 11487;; zero displacement for some strange reason. 11488 11489(define_insn "*mov<mode>_gbr_load" 11490 [(set (match_operand:QIHISI 0 "arith_reg_dest" "=z") 11491 (mem:QIHISI (plus:SI (reg:SI GBR_REG) 11492 (match_operand:QIHISI 1 "gbr_displacement"))))] 11493 "TARGET_SH1" 11494 "mov.<bwl> @(%O1,gbr),%0" 11495 [(set_attr "type" "load")]) 11496 11497(define_insn "*mov<mode>_gbr_load" 11498 [(set (match_operand:QIHISI 0 "arith_reg_dest" "=z") 11499 (mem:QIHISI (reg:SI GBR_REG)))] 11500 "TARGET_SH1" 11501 "mov.<bwl> @(0,gbr),%0" 11502 [(set_attr "type" "load")]) 11503 11504(define_insn "*mov<mode>_gbr_load" 11505 [(set (match_operand:SI 0 "arith_reg_dest" "=z") 11506 (sign_extend:SI 11507 (mem:QIHI (plus:SI (reg:SI GBR_REG) 11508 (match_operand:QIHI 1 "gbr_displacement")))))] 11509 "TARGET_SH1" 11510 "mov.<bw> @(%O1,gbr),%0" 11511 [(set_attr "type" "load")]) 11512 11513(define_insn "*mov<mode>_gbr_load" 11514 [(set (match_operand:SI 0 "arith_reg_dest" "=z") 11515 (sign_extend:SI (mem:QIHI (reg:SI GBR_REG))))] 11516 "TARGET_SH1" 11517 "mov.<bw> @(0,gbr),%0" 11518 [(set_attr "type" "load")]) 11519 11520(define_insn "*mov<mode>_gbr_store" 11521 [(set (mem:QIHISI (plus:SI (reg:SI GBR_REG) 11522 (match_operand:QIHISI 0 "gbr_displacement"))) 11523 (match_operand:QIHISI 1 "register_operand" "z"))] 11524 "TARGET_SH1" 11525 "mov.<bwl> %1,@(%O0,gbr)" 11526 [(set_attr "type" "store")]) 11527 11528(define_insn "*mov<mode>_gbr_store" 11529 [(set (mem:QIHISI (reg:SI GBR_REG)) 11530 (match_operand:QIHISI 0 "register_operand" "z"))] 11531 "TARGET_SH1" 11532 "mov.<bwl> %0,@(0,gbr)" 11533 [(set_attr "type" "store")]) 11534 11535;; DImode memory accesses have to be split in two SImode accesses. 11536;; Split them before reload, so that it gets a better chance to figure out 11537;; how to deal with the R0 restriction for the individual SImode accesses. 11538;; Do not match this insn during or after reload because it can't be split 11539;; afterwards. 11540(define_insn_and_split "*movdi_gbr_load" 11541 [(set (match_operand:DI 0 "arith_reg_dest") 11542 (match_operand:DI 1 "gbr_address_mem"))] 11543 "TARGET_SH1 && can_create_pseudo_p ()" 11544 "#" 11545 "&& 1" 11546 [(set (match_dup 3) (match_dup 5)) 11547 (set (match_dup 4) (match_dup 6))] 11548{ 11549 /* Swap low/high part load order on little endian, so that the result reg 11550 of the second load can be used better. */ 11551 int off = TARGET_LITTLE_ENDIAN ? 1 : 0; 11552 operands[3 + off] = gen_lowpart (SImode, operands[0]); 11553 operands[5 + off] = gen_lowpart (SImode, operands[1]); 11554 operands[4 - off] = gen_highpart (SImode, operands[0]); 11555 operands[6 - off] = gen_highpart (SImode, operands[1]); 11556}) 11557 11558(define_insn_and_split "*movdi_gbr_store" 11559 [(set (match_operand:DI 0 "gbr_address_mem") 11560 (match_operand:DI 1 "register_operand"))] 11561 "TARGET_SH1 && can_create_pseudo_p ()" 11562 "#" 11563 "&& 1" 11564 [(set (match_dup 3) (match_dup 5)) 11565 (set (match_dup 4) (match_dup 6))] 11566{ 11567 /* Swap low/high part store order on big endian, so that stores of function 11568 call results can save a reg copy. */ 11569 int off = TARGET_LITTLE_ENDIAN ? 0 : 1; 11570 operands[3 + off] = gen_lowpart (SImode, operands[0]); 11571 operands[5 + off] = gen_lowpart (SImode, operands[1]); 11572 operands[4 - off] = gen_highpart (SImode, operands[0]); 11573 operands[6 - off] = gen_highpart (SImode, operands[1]); 11574}) 11575 11576;; Sometimes memory accesses do not get combined with the store_gbr insn, 11577;; in particular when the displacements are in the range of the regular move 11578;; insns. Thus, in the first split pass after the combine pass we search 11579;; for missed opportunities and try to fix them up ourselves. 11580;; If an equivalent GBR address can be determined the load / store is split 11581;; into one of the GBR load / store patterns. 11582;; All of that must happen before reload (GBR address modes use R0 as the 11583;; other operand) and there's no point of doing it if the GBR is not 11584;; referenced in a function at all. 11585(define_split 11586 [(set (match_operand:QIHISIDI 0 "register_operand") 11587 (match_operand:QIHISIDI 1 "memory_operand"))] 11588 "TARGET_SH1 && !reload_in_progress && !reload_completed 11589 && df_regs_ever_live_p (GBR_REG)" 11590 [(set (match_dup 0) (match_dup 1))] 11591{ 11592 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]); 11593 if (gbr_mem != NULL_RTX) 11594 operands[1] = replace_equiv_address (operands[1], gbr_mem); 11595 else 11596 FAIL; 11597}) 11598 11599(define_split 11600 [(set (match_operand:SI 0 "register_operand") 11601 (sign_extend:SI (match_operand:QIHI 1 "memory_operand")))] 11602 "TARGET_SH1 && !reload_in_progress && !reload_completed 11603 && df_regs_ever_live_p (GBR_REG)" 11604 [(set (match_dup 0) (sign_extend:SI (match_dup 1)))] 11605{ 11606 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]); 11607 if (gbr_mem != NULL_RTX) 11608 operands[1] = replace_equiv_address (operands[1], gbr_mem); 11609 else 11610 FAIL; 11611}) 11612 11613;; On SH2A we've got movu.b and movu.w for doing zero-extending mem loads. 11614;; Split those so that a GBR load can be used. 11615(define_split 11616 [(set (match_operand:SI 0 "register_operand") 11617 (zero_extend:SI (match_operand:QIHI 1 "memory_operand")))] 11618 "TARGET_SH2A && !reload_in_progress && !reload_completed 11619 && df_regs_ever_live_p (GBR_REG)" 11620 [(set (match_dup 2) (match_dup 1)) 11621 (set (match_dup 0) (zero_extend:SI (match_dup 2)))] 11622{ 11623 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]); 11624 if (gbr_mem != NULL_RTX) 11625 { 11626 operands[2] = gen_reg_rtx (GET_MODE (operands[1])); 11627 operands[1] = replace_equiv_address (operands[1], gbr_mem); 11628 } 11629 else 11630 FAIL; 11631}) 11632 11633(define_split 11634 [(set (match_operand:QIHISIDI 0 "memory_operand") 11635 (match_operand:QIHISIDI 1 "register_operand"))] 11636 "TARGET_SH1 && !reload_in_progress && !reload_completed 11637 && df_regs_ever_live_p (GBR_REG)" 11638 [(set (match_dup 0) (match_dup 1))] 11639{ 11640 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[0]); 11641 if (gbr_mem != NULL_RTX) 11642 operands[0] = replace_equiv_address (operands[0], gbr_mem); 11643 else 11644 FAIL; 11645}) 11646 11647;;------------------------------------------------------------------------------ 11648;; case instruction for switch statements. 11649 11650;; operand 0 is index 11651;; operand 1 is the minimum bound 11652;; operand 2 is the maximum bound - minimum bound + 1 11653;; operand 3 is CODE_LABEL for the table; 11654;; operand 4 is the CODE_LABEL to go to if index out of range. 11655(define_expand "casesi" 11656 [(match_operand:SI 0 "arith_reg_operand" "") 11657 (match_operand:SI 1 "arith_reg_operand" "") 11658 (match_operand:SI 2 "arith_reg_operand" "") 11659 (match_operand 3 "" "") (match_operand 4 "" "")] 11660 "" 11661{ 11662 rtx reg = gen_reg_rtx (SImode); 11663 rtx reg2 = gen_reg_rtx (SImode); 11664 if (TARGET_SHMEDIA) 11665 { 11666 rtx reg = gen_reg_rtx (DImode); 11667 rtx reg2 = gen_reg_rtx (DImode); 11668 rtx reg3 = gen_reg_rtx (Pmode); 11669 rtx reg4 = gen_reg_rtx (Pmode); 11670 rtx reg5 = gen_reg_rtx (Pmode); 11671 rtx load, test; 11672 11673 operands[0] = convert_modes (DImode, SImode, operands[0], 0); 11674 operands[1] = convert_modes (DImode, SImode, operands[1], 0); 11675 operands[2] = convert_modes (DImode, SImode, operands[2], 1); 11676 11677 test = gen_rtx_GT (VOIDmode, operands[1], operands[0]); 11678 emit_jump_insn (gen_cbranchdi4 (test, operands[1], operands[0], 11679 operands[4])); 11680 emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1])); 11681 test = gen_rtx_GTU (VOIDmode, reg, operands[2]); 11682 emit_jump_insn (gen_cbranchdi4 (test, reg, operands[2], operands[4])); 11683 emit_insn (gen_casesi_shift_media (reg2, reg, operands[3])); 11684 emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF 11685 (Pmode, operands[3]))); 11686 /* Messy: can we subreg to clean this up? */ 11687 if (Pmode == DImode) 11688 load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]); 11689 else 11690 load = gen_casesi_load_media (reg4, 11691 gen_rtx_SUBREG (DImode, reg3, 0), 11692 reg2, operands[3]); 11693 PUT_MODE (SET_SRC (load), Pmode); 11694 emit_insn (load); 11695 /* ??? The following add could be eliminated if we used ptrel. */ 11696 emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4)); 11697 emit_jump_insn (gen_casesi_jump_media (reg5, operands[3])); 11698 emit_barrier (); 11699 DONE; 11700 } 11701 operands[1] = copy_to_mode_reg (SImode, operands[1]); 11702 operands[2] = copy_to_mode_reg (SImode, operands[2]); 11703 /* If optimizing, casesi_worker depends on the mode of the instruction 11704 before label it 'uses' - operands[3]. */ 11705 emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4], 11706 reg)); 11707 emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3])); 11708 if (TARGET_SH2) 11709 emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3])); 11710 else 11711 emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3])); 11712 /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to 11713 operands[3], but to lab. We will fix this up in 11714 machine_dependent_reorg. */ 11715 emit_barrier (); 11716 DONE; 11717}) 11718 11719(define_expand "casesi_0" 11720 [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" "")) 11721 (set (match_dup 4) (minus:SI (match_dup 4) 11722 (match_operand:SI 1 "arith_operand" ""))) 11723 (set (reg:SI T_REG) 11724 (gtu:SI (match_dup 4) 11725 (match_operand:SI 2 "arith_reg_operand" ""))) 11726 (set (pc) 11727 (if_then_else (ne (reg:SI T_REG) 11728 (const_int 0)) 11729 (label_ref (match_operand 3 "" "")) 11730 (pc)))] 11731 "TARGET_SH1" 11732 "") 11733 11734;; ??? reload might clobber r0 if we use it explicitly in the RTL before 11735;; reload; using a R0_REGS pseudo reg is likely to give poor code. 11736;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload. 11737;; 11738;; The use on the T_REG in the casesi_worker* patterns links the bounds 11739;; checking insns and the table memory access. See also PR 69713. 11740(define_insn "casesi_worker_0" 11741 [(set (match_operand:SI 0 "register_operand" "=r,r") 11742 (unspec:SI [(match_operand:SI 1 "register_operand" "0,r") 11743 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI)) 11744 (clobber (match_scratch:SI 3 "=X,1")) 11745 (clobber (match_scratch:SI 4 "=&z,z")) 11746 (use (reg:SI T_REG))] 11747 "TARGET_SH1" 11748 "#") 11749 11750(define_split 11751 [(set (match_operand:SI 0 "register_operand" "") 11752 (unspec:SI [(match_operand:SI 1 "register_operand" "") 11753 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI)) 11754 (clobber (match_scratch:SI 3 "")) 11755 (clobber (match_scratch:SI 4)) 11756 (use (reg:SI T_REG))] 11757 "TARGET_SH1 && ! TARGET_SH2 && reload_completed" 11758 [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA)) 11759 (parallel [(set (match_dup 0) 11760 (unspec:SI [(reg:SI R0_REG) (match_dup 1) 11761 (label_ref (match_dup 2))] UNSPEC_CASESI)) 11762 (clobber (match_dup 3))]) 11763 (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))] 11764{ 11765 if (GET_CODE (operands[2]) == CODE_LABEL) 11766 LABEL_NUSES (operands[2])++; 11767}) 11768 11769(define_split 11770 [(set (match_operand:SI 0 "register_operand" "") 11771 (unspec:SI [(match_operand:SI 1 "register_operand" "") 11772 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI)) 11773 (clobber (match_scratch:SI 3 "")) 11774 (clobber (match_scratch:SI 4)) 11775 (use (reg:SI T_REG))] 11776 "TARGET_SH2 && reload_completed" 11777 [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA)) 11778 (parallel [(set (match_dup 0) 11779 (unspec:SI [(reg:SI R0_REG) (match_dup 1) 11780 (label_ref (match_dup 2))] UNSPEC_CASESI)) 11781 (clobber (match_dup 3))])] 11782{ 11783 if (GET_CODE (operands[2]) == CODE_LABEL) 11784 LABEL_NUSES (operands[2])++; 11785}) 11786 11787;; This may be replaced with casesi_worker_2 in sh_reorg for PIC. 11788;; The insn length is set to 8 for that case. 11789(define_insn "casesi_worker_1" 11790 [(set (match_operand:SI 0 "register_operand" "=r,r") 11791 (unspec:SI [(reg:SI R0_REG) 11792 (match_operand:SI 1 "register_operand" "0,r") 11793 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI)) 11794 (clobber (match_scratch:SI 3 "=X,1"))] 11795 "TARGET_SH1" 11796{ 11797 rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[2]))); 11798 11799 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); 11800 11801 switch (GET_MODE (diff_vec)) 11802 { 11803 case SImode: 11804 return "shll2 %1" "\n" 11805 " mov.l @(r0,%1),%0"; 11806 case HImode: 11807 return "add %1,%1" "\n" 11808 " mov.w @(r0,%1),%0"; 11809 case QImode: 11810 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned) 11811 return "mov.b @(r0,%1),%0" "\n" 11812 " extu.b %0,%0"; 11813 else 11814 return "mov.b @(r0,%1),%0"; 11815 11816 default: 11817 gcc_unreachable (); 11818 } 11819} 11820 [(set_attr_alternative "length" 11821 [(if_then_else (match_test "flag_pic") (const_int 8) (const_int 4)) 11822 (if_then_else (match_test "flag_pic") (const_int 8) (const_int 4))])]) 11823 11824(define_insn "casesi_worker_2" 11825 [(set (match_operand:SI 0 "register_operand" "=r,r") 11826 (unspec:SI [(reg:SI R0_REG) 11827 (match_operand:SI 1 "register_operand" "0,r") 11828 (label_ref (match_operand 2 "" "")) 11829 (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI)) 11830 (clobber (match_operand:SI 4 "" "=X,1"))] 11831 "TARGET_SH2 && reload_completed && flag_pic" 11832{ 11833 rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[2]))); 11834 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); 11835 11836 switch (GET_MODE (diff_vec)) 11837 { 11838 case SImode: 11839 return "shll2 %1" "\n" 11840 " add r0,%1" "\n" 11841 " mova %O3,r0" "\n" 11842 " mov.l @(r0,%1),%0"; 11843 case HImode: 11844 return "add %1,%1" "\n" 11845 " add r0,%1" "\n" 11846 " mova %O3,r0" "\n" 11847 " mov.w @(r0,%1),%0"; 11848 case QImode: 11849 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned) 11850 return "add r0,%1" "\n" 11851 " mova %O3,r0" "\n" 11852 " mov.b @(r0,%1),%0" "\n" 11853 " extu.b %0,%0"; 11854 else 11855 return "add r0,%1" "\n" 11856 " mova %O3,r0" "\n" 11857 " mov.b @(r0,%1),%0"; 11858 default: 11859 gcc_unreachable (); 11860 } 11861} 11862 [(set_attr "length" "8")]) 11863 11864(define_insn "casesi_shift_media" 11865 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 11866 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r") 11867 (unspec:DI [(label_ref:DI (match_operand 2 "" ""))] 11868 UNSPEC_CASESI)))] 11869 "TARGET_SHMEDIA" 11870{ 11871 rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[2]))); 11872 11873 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); 11874 11875 switch (GET_MODE (diff_vec)) 11876 { 11877 case SImode: 11878 return "shlli %1, 2, %0"; 11879 case HImode: 11880 return "shlli %1, 1, %0"; 11881 case QImode: 11882 if (rtx_equal_p (operands[0], operands[1])) 11883 return ""; 11884 return "add %1, r63, %0"; 11885 default: 11886 gcc_unreachable (); 11887 } 11888} 11889 [(set_attr "type" "arith_media")]) 11890 11891(define_insn "casesi_load_media" 11892 [(set (match_operand 0 "any_arith_reg_dest" "=r") 11893 (mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r") 11894 (match_operand:DI 2 "arith_reg_operand" "r") 11895 (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))] 11896 "TARGET_SHMEDIA" 11897{ 11898 rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[3]))); 11899 11900 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); 11901 11902 switch (GET_MODE (diff_vec)) 11903 { 11904 case SImode: 11905 return "ldx.l %1, %2, %0"; 11906 case HImode: 11907#if 0 11908 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned) 11909 return "ldx.uw %1, %2, %0"; 11910#endif 11911 return "ldx.w %1, %2, %0"; 11912 case QImode: 11913 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned) 11914 return "ldx.ub %1, %2, %0"; 11915 return "ldx.b %1, %2, %0"; 11916 default: 11917 gcc_unreachable (); 11918 } 11919} 11920 [(set_attr "type" "load_media")]) 11921 11922(define_expand "simple_return" 11923 [(simple_return)] 11924 "sh_can_use_simple_return_p ()") 11925 11926(define_expand "return" 11927 [(return)] 11928 "reload_completed && epilogue_completed" 11929{ 11930 if (TARGET_SHMEDIA) 11931 { 11932 emit_jump_insn (gen_return_media ()); 11933 DONE; 11934 } 11935 11936 if (TARGET_SHCOMPACT 11937 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))) 11938 { 11939 emit_jump_insn (gen_shcompact_return_tramp ()); 11940 DONE; 11941 } 11942}) 11943 11944(define_insn "*<code>_i" 11945 [(any_return)] 11946 "TARGET_SH1 && ! (TARGET_SHCOMPACT 11947 && (crtl->args.info.call_cookie 11948 & CALL_COOKIE_RET_TRAMP (1))) 11949 && reload_completed 11950 && ! sh_cfun_trap_exit_p ()" 11951{ 11952 if (TARGET_SH2A && (dbr_sequence_length () == 0) 11953 && !current_function_interrupt) 11954 return "rts/n"; 11955 else 11956 return "%@ %#"; 11957} 11958 [(set_attr "type" "return") 11959 (set_attr "needs_delay_slot" "yes")]) 11960 11961;; trapa has no delay slot. 11962(define_insn "*return_trapa" 11963 [(return)] 11964 "TARGET_SH1 && !TARGET_SHCOMPACT 11965 && reload_completed" 11966 "%@" 11967 [(set_attr "type" "return")]) 11968 11969(define_expand "shcompact_return_tramp" 11970 [(return)] 11971 "TARGET_SHCOMPACT 11972 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))" 11973{ 11974 rtx reg = gen_rtx_REG (Pmode, R0_REG); 11975 11976 function_symbol (reg, "__GCC_shcompact_return_trampoline", SFUNC_STATIC); 11977 emit_jump_insn (gen_shcompact_return_tramp_i ()); 11978 DONE; 11979}) 11980 11981(define_insn "shcompact_return_tramp_i" 11982 [(parallel [(return) (use (reg:SI R0_REG))])] 11983 "TARGET_SHCOMPACT 11984 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))" 11985 "jmp @r0%#" 11986 [(set_attr "type" "jump_ind") 11987 (set_attr "needs_delay_slot" "yes")]) 11988 11989(define_insn "return_media_i" 11990 [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])] 11991 "TARGET_SHMEDIA && reload_completed" 11992 "blink %0, r63" 11993 [(set_attr "type" "jump_media")]) 11994 11995(define_insn "return_media_rte" 11996 [(return)] 11997 "TARGET_SHMEDIA && reload_completed && current_function_interrupt" 11998 "rte" 11999 [(set_attr "type" "jump_media")]) 12000 12001(define_expand "return_media" 12002 [(return)] 12003 "TARGET_SHMEDIA && reload_completed" 12004{ 12005 int tr_regno = sh_media_register_for_return (); 12006 rtx tr; 12007 12008 if (current_function_interrupt) 12009 { 12010 emit_jump_insn (gen_return_media_rte ()); 12011 DONE; 12012 } 12013 if (tr_regno < 0) 12014 { 12015 rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG); 12016 12017 gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]); 12018 tr_regno = TR0_REG; 12019 tr = gen_rtx_REG (Pmode, tr_regno); 12020 emit_move_insn (tr, r18); 12021 } 12022 else 12023 tr = gen_rtx_REG (Pmode, tr_regno); 12024 12025 emit_jump_insn (gen_return_media_i (tr)); 12026 DONE; 12027}) 12028 12029(define_insn "shcompact_preserve_incoming_args" 12030 [(set (match_operand:SI 0 "register_operand" "+r") 12031 (unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))] 12032 "TARGET_SHCOMPACT" 12033 "" 12034 [(set_attr "length" "0")]) 12035 12036(define_insn "shcompact_incoming_args" 12037 [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS)) 12038 (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS)) 12039 (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS)) 12040 (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS)) 12041 (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS)) 12042 (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS)) 12043 (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS)) 12044 (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS)) 12045 (set (mem:BLK (reg:SI MACL_REG)) 12046 (unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS)) 12047 (use (reg:SI R0_REG)) 12048 (clobber (reg:SI R0_REG)) 12049 (clobber (reg:SI MACL_REG)) 12050 (clobber (reg:SI MACH_REG)) 12051 (clobber (reg:SI PR_REG))] 12052 "TARGET_SHCOMPACT" 12053 "jsr @r0%#" 12054 [(set_attr "needs_delay_slot" "yes")]) 12055 12056(define_insn "shmedia_save_restore_regs_compact" 12057 [(set (reg:SI SP_REG) 12058 (plus:SI (reg:SI SP_REG) 12059 (match_operand:SI 0 "immediate_operand" "i"))) 12060 (use (reg:SI R0_REG)) 12061 (clobber (reg:SI PR_REG))] 12062 "TARGET_SHCOMPACT 12063 && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST () 12064 || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())" 12065 "jsr @r0%#" 12066 [(set_attr "needs_delay_slot" "yes")]) 12067 12068(define_expand "prologue" 12069 [(const_int 0)] 12070 "" 12071{ 12072 sh_expand_prologue (); 12073 DONE; 12074}) 12075 12076(define_expand "epilogue" 12077 [(return)] 12078 "" 12079{ 12080 sh_expand_epilogue (false); 12081 if (TARGET_SHMEDIA 12082 || (TARGET_SHCOMPACT 12083 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))) 12084 { 12085 emit_jump_insn (gen_return ()); 12086 DONE; 12087 } 12088}) 12089 12090(define_expand "eh_return" 12091 [(use (match_operand 0 "register_operand" ""))] 12092 "" 12093{ 12094 rtx ra = operands[0]; 12095 12096 if (TARGET_SHMEDIA64) 12097 emit_insn (gen_eh_set_ra_di (ra)); 12098 else 12099 emit_insn (gen_eh_set_ra_si (ra)); 12100 12101 DONE; 12102}) 12103 12104;; Clobber the return address on the stack. We can't expand this 12105;; until we know where it will be put in the stack frame. 12106 12107(define_insn "eh_set_ra_si" 12108 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] 12109 UNSPECV_EH_RETURN) 12110 (clobber (match_scratch:SI 1 "=&r"))] 12111 "! TARGET_SHMEDIA64" 12112 "#") 12113 12114(define_insn "eh_set_ra_di" 12115 [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")] 12116 UNSPECV_EH_RETURN) 12117 (clobber (match_scratch:DI 1 "=&r"))] 12118 "TARGET_SHMEDIA64" 12119 "#") 12120 12121(define_split 12122 [(unspec_volatile [(match_operand 0 "register_operand" "")] 12123 UNSPECV_EH_RETURN) 12124 (clobber (match_scratch 1 ""))] 12125 "reload_completed" 12126 [(const_int 0)] 12127{ 12128 sh_set_return_address (operands[0], operands[1]); 12129 DONE; 12130}) 12131 12132(define_insn "blockage" 12133 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)] 12134 "" 12135 "" 12136 [(set_attr "length" "0")]) 12137 12138;; Define movml instructions for SH2A target. Currently they are 12139;; used to push and pop all banked registers only. 12140 12141(define_insn "movml_push_banked" 12142 [(set (match_operand:SI 0 "register_operand" "=r") 12143 (plus (match_dup 0) (const_int -32))) 12144 (set (mem:SI (plus:SI (match_dup 0) (const_int 28))) (reg:SI R7_REG)) 12145 (set (mem:SI (plus:SI (match_dup 0) (const_int 24))) (reg:SI R6_REG)) 12146 (set (mem:SI (plus:SI (match_dup 0) (const_int 20))) (reg:SI R5_REG)) 12147 (set (mem:SI (plus:SI (match_dup 0) (const_int 16))) (reg:SI R4_REG)) 12148 (set (mem:SI (plus:SI (match_dup 0) (const_int 12))) (reg:SI R3_REG)) 12149 (set (mem:SI (plus:SI (match_dup 0) (const_int 8))) (reg:SI R2_REG)) 12150 (set (mem:SI (plus:SI (match_dup 0) (const_int 4))) (reg:SI R1_REG)) 12151 (set (mem:SI (plus:SI (match_dup 0) (const_int 0))) (reg:SI R0_REG))] 12152 "TARGET_SH2A && REGNO (operands[0]) == 15" 12153 "movml.l r7,@-r15" 12154 [(set_attr "in_delay_slot" "no")]) 12155 12156(define_insn "movml_pop_banked" 12157 [(set (match_operand:SI 0 "register_operand" "=r") 12158 (plus (match_dup 0) (const_int 32))) 12159 (set (reg:SI R0_REG) (mem:SI (plus:SI (match_dup 0) (const_int -32)))) 12160 (set (reg:SI R1_REG) (mem:SI (plus:SI (match_dup 0) (const_int -28)))) 12161 (set (reg:SI R2_REG) (mem:SI (plus:SI (match_dup 0) (const_int -24)))) 12162 (set (reg:SI R3_REG) (mem:SI (plus:SI (match_dup 0) (const_int -20)))) 12163 (set (reg:SI R4_REG) (mem:SI (plus:SI (match_dup 0) (const_int -16)))) 12164 (set (reg:SI R5_REG) (mem:SI (plus:SI (match_dup 0) (const_int -12)))) 12165 (set (reg:SI R6_REG) (mem:SI (plus:SI (match_dup 0) (const_int -8)))) 12166 (set (reg:SI R7_REG) (mem:SI (plus:SI (match_dup 0) (const_int -4))))] 12167 "TARGET_SH2A && REGNO (operands[0]) == 15" 12168 "movml.l @r15+,r7" 12169 [(set_attr "in_delay_slot" "no")]) 12170 12171;; ------------------------------------------------------------------------ 12172;; Scc instructions 12173;; ------------------------------------------------------------------------ 12174 12175(define_insn "movt" 12176 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 12177 (match_operand:SI 1 "t_reg_operand"))] 12178 "TARGET_SH1" 12179 "movt %0" 12180 [(set_attr "type" "arith")]) 12181 12182(define_insn "movrt" 12183 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 12184 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))] 12185 "TARGET_SH2A" 12186 "movrt %0" 12187 [(set_attr "type" "arith")]) 12188 12189(define_expand "cstore4_media" 12190 [(set (match_operand:SI 0 "register_operand" "=r") 12191 (match_operator:SI 1 "sh_float_comparison_operator" 12192 [(match_operand 2 "logical_operand" "") 12193 (match_operand 3 "cmp_operand" "")]))] 12194 "TARGET_SHMEDIA" 12195{ 12196 machine_mode mode = GET_MODE (operands[2]); 12197 enum rtx_code code = GET_CODE (operands[1]); 12198 bool invert, swap; 12199 if (mode == VOIDmode) 12200 mode = GET_MODE (operands[3]); 12201 if (operands[2] == const0_rtx) 12202 { 12203 if (code == EQ || code == NE) 12204 operands[2] = operands[3], operands[3] = const0_rtx; 12205 } 12206 else 12207 operands[2] = force_reg (mode, operands[2]); 12208 if (operands[3] != const0_rtx) 12209 operands[3] = force_reg (mode, operands[3]); 12210 12211 switch (code) 12212 { 12213 case GEU: 12214 case GE: 12215 swap = invert = !FLOAT_MODE_P (mode); 12216 break; 12217 12218 case LEU: 12219 case LE: 12220 swap = FLOAT_MODE_P (mode), invert = !swap; 12221 break; 12222 12223 case LTU: 12224 case LT: 12225 swap = true, invert = false; 12226 break; 12227 12228 case GTU: 12229 case GT: 12230 case EQ: 12231 case UNORDERED: 12232 swap = invert = false; 12233 break; 12234 12235 case NE: 12236 swap = invert = true; 12237 break; 12238 12239 default: 12240 gcc_unreachable (); 12241 } 12242 12243 if (swap) 12244 { 12245 std::swap (operands[2], operands[3]); 12246 code = swap_condition (code); 12247 } 12248 12249 if (invert) 12250 { 12251 rtx tem = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0]; 12252 code = reverse_condition (code); 12253 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]); 12254 emit_insn (gen_cstore4_media (tem, operands[1], 12255 operands[2], operands[3])); 12256 code = EQ; 12257 operands[2] = tem; 12258 operands[3] = const0_rtx; 12259 } 12260 12261 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]); 12262}) 12263 12264(define_expand "cstoresi4" 12265 [(set (match_operand:SI 0 "register_operand" "=r") 12266 (match_operator:SI 1 "comparison_operator" 12267 [(match_operand:SI 2 "cmpsi_operand" "") 12268 (match_operand:SI 3 "arith_operand" "")]))] 12269 "TARGET_SH1 || TARGET_SHMEDIA" 12270{ 12271 if (TARGET_SHMEDIA) 12272 { 12273 emit_insn (gen_cstore4_media (operands[0], operands[1], 12274 operands[2], operands[3])); 12275 DONE; 12276 } 12277 12278 if (sh_expand_t_scc (operands)) 12279 DONE; 12280 12281 if (! currently_expanding_to_rtl) 12282 FAIL; 12283 12284 sh_emit_compare_and_set (operands, SImode); 12285 DONE; 12286}) 12287 12288(define_expand "cstoredi4" 12289 [(set (match_operand:SI 0 "register_operand" "=r") 12290 (match_operator:SI 1 "comparison_operator" 12291 [(match_operand:DI 2 "arith_operand" "") 12292 (match_operand:DI 3 "arith_operand" "")]))] 12293 "TARGET_SH2 || TARGET_SHMEDIA" 12294{ 12295 if (TARGET_SHMEDIA) 12296 { 12297 emit_insn (gen_cstore4_media (operands[0], operands[1], 12298 operands[2], operands[3])); 12299 DONE; 12300 } 12301 12302 if (sh_expand_t_scc (operands)) 12303 DONE; 12304 12305 if (! currently_expanding_to_rtl) 12306 FAIL; 12307 12308 sh_emit_compare_and_set (operands, DImode); 12309 DONE; 12310}) 12311 12312;; Move the complement of the T reg to a reg. 12313;; On SH2A the movrt insn can be used. 12314;; On anything else than SH2A this has to be done with multiple instructions. 12315;; One obvious way would be: 12316;; cmp/eq ... 12317;; movt r0 12318;; xor #1,r0 12319;; 12320;; However, this puts pressure on r0 in most cases and thus the following is 12321;; more appealing: 12322;; cmp/eq ... 12323;; mov #-1,temp 12324;; negc temp,dest 12325;; 12326;; If the constant -1 can be CSE-ed or lifted out of a loop it effectively 12327;; becomes a one instruction operation. Moreover, care must be taken that 12328;; the insn can still be combined with inverted compare and branch code 12329;; around it. On the other hand, if a function returns the complement of 12330;; a previous comparison result in the T bit, the xor #1,r0 approach might 12331;; lead to better code. 12332(define_expand "movnegt" 12333 [(set (match_operand:SI 0 "arith_reg_dest" "") 12334 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))] 12335 "TARGET_SH1" 12336{ 12337 if (TARGET_SH2A) 12338 emit_insn (gen_movrt (operands[0], operands[1])); 12339 else 12340 { 12341 rtx val = force_reg (SImode, gen_int_mode (-1, SImode)); 12342 emit_insn (gen_movrt_negc (operands[0], operands[1], val)); 12343 } 12344 DONE; 12345}) 12346 12347(define_insn_and_split "movrt_negc" 12348 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 12349 (xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1))) 12350 (set (reg:SI T_REG) (const_int 1)) 12351 (use (match_operand:SI 2 "arith_reg_operand" "r"))] 12352 "TARGET_SH1" 12353 "negc %2,%0" 12354 "&& !sh_in_recog_treg_set_expr ()" 12355 [(const_int 0)] 12356{ 12357 if (sh_split_movrt_negc_to_movt_xor (curr_insn, operands)) 12358 DONE; 12359 else 12360 FAIL; 12361} 12362 [(set_attr "type" "arith")]) 12363 12364;; The -1 constant will not be CSE-ed for the *movrt_negc pattern, but the 12365;; pattern can be used by the combine pass. Using a scratch reg for the 12366;; -1 constant results in slightly better register allocations compared to 12367;; generating a pseudo reg before reload. 12368(define_insn_and_split "*movrt_negc" 12369 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 12370 (xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1))) 12371 (clobber (match_scratch:SI 2 "=r")) 12372 (clobber (reg:SI T_REG))] 12373 "TARGET_SH1 && ! TARGET_SH2A" 12374 "#" 12375 "&& !sh_in_recog_treg_set_expr ()" 12376 [(const_int 0)] 12377{ 12378 if (sh_split_movrt_negc_to_movt_xor (curr_insn, operands)) 12379 DONE; 12380 else if (reload_completed) 12381 { 12382 emit_move_insn (operands[2], gen_int_mode (-1, SImode)); 12383 emit_insn (gen_movrt_negc (operands[0], operands[1], operands[2])); 12384 DONE; 12385 } 12386 else 12387 FAIL; 12388}) 12389 12390;; Store the negated T bit in a reg using r0 and xor. This one doesn't 12391;; clobber the T bit, which is useful when storing the T bit and the 12392;; negated T bit in parallel. On SH2A the movrt insn can be used for that. 12393;; Usually we don't want this insn to be matched, except for cases where the 12394;; T bit clobber is really not appreciated. Hence the extra use on T_REG. 12395(define_insn_and_split "movrt_xor" 12396 [(set (match_operand:SI 0 "arith_reg_dest" "=z") 12397 (xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1))) 12398 (use (reg:SI T_REG))] 12399 "TARGET_SH1" 12400 "#" 12401 "&& reload_completed" 12402 [(set (match_dup 0) (reg:SI T_REG)) 12403 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))]) 12404 12405;; 0x7fffffff + T 12406;; 0x7fffffff + (1-T) = 0 - 0x80000000 - T 12407;; 12408;; Notice that 0 - 0x80000000 = 0x80000000. 12409 12410;; Single bit tests are usually done with zero_extract. On non-SH2A this 12411;; will use a tst-negc sequence. On SH2A it will use a bld-addc sequence. 12412;; The zeroth bit requires a special pattern, otherwise we get a shlr-addc. 12413;; This is a special case of the generic treg_set_expr pattern and thus has 12414;; to come first or it will never match. 12415(define_insn_and_split "*mov_t_msb_neg" 12416 [(set (match_operand:SI 0 "arith_reg_dest") 12417 (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand") 12418 (const_int 1)) 12419 (const_int 2147483647))) 12420 (clobber (reg:SI T_REG))] 12421 "TARGET_SH1" 12422 "#" 12423 "&& can_create_pseudo_p ()" 12424 [(parallel [(set (match_dup 0) 12425 (plus:SI (zero_extract:SI (match_dup 1) 12426 (const_int 1) (const_int 0)) 12427 (const_int 2147483647))) 12428 (clobber (reg:SI T_REG))])]) 12429 12430(define_insn_and_split "*mov_t_msb_neg" 12431 [(set (match_operand:SI 0 "arith_reg_dest") 12432 (plus:SI (match_operand 1 "treg_set_expr") 12433 (const_int 2147483647))) ;; 0x7fffffff 12434 (clobber (reg:SI T_REG))] 12435 "TARGET_SH1" 12436 "#" 12437 "&& can_create_pseudo_p ()" 12438 [(const_int 0)] 12439{ 12440 if (negt_reg_operand (operands[1], VOIDmode)) 12441 { 12442 emit_insn (gen_negc (operands[0], 12443 force_reg (SImode, GEN_INT (-2147483648LL)))); 12444 DONE; 12445 } 12446 12447 sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn); 12448 if (ti.remove_trailing_nott ()) 12449 emit_insn (gen_negc (operands[0], 12450 force_reg (SImode, GEN_INT (-2147483648LL)))); 12451 else 12452 emit_insn (gen_addc (operands[0], 12453 force_reg (SImode, const0_rtx), 12454 force_reg (SImode, GEN_INT (2147483647)))); 12455 DONE; 12456}) 12457 12458(define_insn_and_split "*mov_t_msb_neg" 12459 [(set (match_operand:SI 0 "arith_reg_dest") 12460 (if_then_else:SI (match_operand 1 "treg_set_expr") 12461 (match_operand 2 "const_int_operand") 12462 (match_operand 3 "const_int_operand"))) 12463 (clobber (reg:SI T_REG))] 12464 "TARGET_SH1 && can_create_pseudo_p () 12465 && ((INTVAL (operands[2]) == -2147483648LL 12466 && INTVAL (operands[3]) == 2147483647LL) 12467 || (INTVAL (operands[2]) == 2147483647LL 12468 && INTVAL (operands[3]) == -2147483648LL))" 12469 "#" 12470 "&& 1" 12471 [(const_int 0)] 12472{ 12473 sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn); 12474 12475 if (INTVAL (operands[2]) == -2147483648LL) 12476 { 12477 if (ti.remove_trailing_nott ()) 12478 emit_insn (gen_negc (operands[0], 12479 force_reg (SImode, GEN_INT (-2147483648LL)))); 12480 else 12481 emit_insn (gen_addc (operands[0], 12482 force_reg (SImode, const0_rtx), 12483 force_reg (SImode, operands[3]))); 12484 DONE; 12485 } 12486 else if (INTVAL (operands[2]) == 2147483647LL) 12487 { 12488 if (ti.remove_trailing_nott ()) 12489 emit_insn (gen_addc (operands[0], 12490 force_reg (SImode, const0_rtx), 12491 force_reg (SImode, GEN_INT (2147483647LL)))); 12492 else 12493 emit_insn (gen_negc (operands[0], 12494 force_reg (SImode, GEN_INT (-2147483648LL)))); 12495 DONE; 12496 } 12497 else 12498 gcc_unreachable (); 12499}) 12500 12501;; The *negnegt pattern helps the combine pass to figure out how to fold 12502;; an explicit double T bit negation. 12503(define_insn_and_split "*negnegt" 12504 [(set (reg:SI T_REG) 12505 (eq:SI (match_operand 0 "negt_reg_operand" "") (const_int 0)))] 12506 "TARGET_SH1" 12507 "#" 12508 "" 12509 [(const_int 0)]) 12510 12511;; Store (negated) T bit as all zeros or ones in a reg. 12512;; subc Rn,Rn ! Rn = Rn - Rn - T; T = T 12513;; not Rn,Rn ! Rn = 0 - Rn 12514(define_insn_and_split "mov_neg_si_t" 12515 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 12516 (neg:SI (match_operand 1 "treg_set_expr")))] 12517 "TARGET_SH1" 12518{ 12519 gcc_assert (t_reg_operand (operands[1], VOIDmode)); 12520 return "subc %0,%0"; 12521} 12522 "&& can_create_pseudo_p () && !t_reg_operand (operands[1], VOIDmode)" 12523 [(const_int 0)] 12524{ 12525 sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn); 12526 emit_insn (gen_mov_neg_si_t (operands[0], get_t_reg_rtx ())); 12527 12528 if (ti.remove_trailing_nott ()) 12529 emit_insn (gen_one_cmplsi2 (operands[0], operands[0])); 12530 12531 DONE; 12532} 12533 [(set_attr "type" "arith")]) 12534 12535;; The *movtt pattern eliminates redundant T bit to T bit moves / tests. 12536(define_insn_and_split "*movtt" 12537 [(set (reg:SI T_REG) 12538 (eq:SI (match_operand 0 "t_reg_operand" "") (const_int 1)))] 12539 "TARGET_SH1" 12540 "#" 12541 "" 12542 [(const_int 0)]) 12543 12544;; Invert the T bit. 12545;; On SH2A we can use the nott insn. On anything else this must be done with 12546;; multiple insns like: 12547;; movt Rn 12548;; tst Rn,Rn 12549;; This requires an additional pseudo. The SH specific sh_treg_combine RTL 12550;; pass will look for this insn. Disallow using it if pseudos can't be 12551;; created. 12552;; Don't split the nott inside the splitting of a treg_set_expr, or else 12553;; surrounding insns might not see and recombine it. Defer the splitting 12554;; of the nott until after the whole insn containing the treg_set_expr 12555;; has been split. 12556(define_insn_and_split "nott" 12557 [(set (reg:SI T_REG) 12558 (xor:SI (match_operand:SI 0 "t_reg_operand") (const_int 1)))] 12559 "TARGET_SH2A || (TARGET_SH1 && can_create_pseudo_p ())" 12560{ 12561 gcc_assert (TARGET_SH2A); 12562 return "nott"; 12563} 12564 "!TARGET_SH2A && can_create_pseudo_p () && !sh_in_recog_treg_set_expr ()" 12565 [(set (match_dup 0) (reg:SI T_REG)) 12566 (set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))] 12567{ 12568 operands[0] = gen_reg_rtx (SImode); 12569}) 12570 12571;; Store T bit as MSB in a reg. 12572;; T = 0: 0x00000000 -> reg 12573;; T = 1: 0x80000000 -> reg 12574(define_insn_and_split "*movt_msb" 12575 [(set (match_operand:SI 0 "arith_reg_dest") 12576 (mult:SI (match_operand:SI 1 "t_reg_operand") 12577 (const_int -2147483648))) ;; 0xffffffff80000000 12578 (clobber (reg:SI T_REG))] 12579 "TARGET_SH1" 12580 "#" 12581 "&& 1" 12582 [(set (match_dup 0) (ashift:SI (reg:SI T_REG) (const_int 31)))]) 12583 12584;; Store inverted T bit as MSB in a reg. 12585;; T = 0: 0x80000000 -> reg 12586;; T = 1: 0x00000000 -> reg 12587;; On SH2A we can get away without clobbering the T_REG using the movrt insn. 12588;; On non SH2A we resort to the following sequence: 12589;; movt Rn 12590;; tst Rn,Rn 12591;; rotcr Rn 12592;; The T bit value will be modified during the sequence, but the rotcr insn 12593;; will restore its original value. 12594(define_insn_and_split "*negt_msb" 12595 [(set (match_operand:SI 0 "arith_reg_dest") 12596 (match_operand:SI 1 "negt_reg_shl31_operand"))] 12597 "TARGET_SH1" 12598 "#" 12599 "&& can_create_pseudo_p ()" 12600 [(const_int 0)] 12601{ 12602 rtx tmp = gen_reg_rtx (SImode); 12603 12604 if (TARGET_SH2A) 12605 { 12606 emit_insn (gen_movrt (tmp, get_t_reg_rtx ())); 12607 emit_insn (gen_rotrsi3 (operands[0], tmp, const1_rtx)); 12608 } 12609 else 12610 { 12611 emit_move_insn (tmp, get_t_reg_rtx ()); 12612 emit_insn (gen_cmpeqsi_t (tmp, const0_rtx)); 12613 emit_insn (gen_rotcr (operands[0], tmp, get_t_reg_rtx ())); 12614 } 12615 DONE; 12616}) 12617 12618;; The *cset_zero patterns convert optimizations such as 12619;; "if (test) x = 0;" 12620;; to 12621;; "x &= -(test == 0);" 12622;; back to conditional branch sequences if zero-displacement branches 12623;; are enabled. 12624;; FIXME: These patterns can be removed when conditional execution patterns 12625;; are implemented, since ifcvt will not perform these optimizations if 12626;; conditional execution is supported. 12627(define_insn "*cset_zero" 12628 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 12629 (and:SI (plus:SI (match_operand:SI 1 "t_reg_operand") 12630 (const_int -1)) 12631 (match_operand:SI 2 "arith_reg_operand" "0")))] 12632 "TARGET_SH1 && TARGET_ZDCBRANCH" 12633{ 12634 return "bf 0f" "\n" 12635 " mov #0,%0" "\n" 12636 "0:"; 12637} 12638 [(set_attr "type" "arith") ;; poor approximation 12639 (set_attr "length" "4")]) 12640 12641(define_insn "*cset_zero" 12642 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 12643 (if_then_else:SI (match_operand:SI 1 "cbranch_treg_value") 12644 (match_operand:SI 2 "arith_reg_operand" "0") 12645 (const_int 0)))] 12646 "TARGET_SH1 && TARGET_ZDCBRANCH" 12647{ 12648 int tval = sh_eval_treg_value (operands[1]); 12649 if (tval == true) 12650 return "bt 0f" "\n" 12651 " mov #0,%0" "\n" 12652 "0:"; 12653 else if (tval == false) 12654 return "bf 0f" "\n" 12655 " mov #0,%0" "\n" 12656 "0:"; 12657 else 12658 gcc_unreachable (); 12659} 12660 [(set_attr "type" "arith") ;; poor approximation 12661 (set_attr "length" "4")]) 12662 12663(define_expand "cstoresf4" 12664 [(set (match_operand:SI 0 "register_operand" "=r") 12665 (match_operator:SI 1 "sh_float_comparison_operator" 12666 [(match_operand:SF 2 "arith_operand" "") 12667 (match_operand:SF 3 "arith_operand" "")]))] 12668 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 12669{ 12670 if (TARGET_SHMEDIA) 12671 { 12672 emit_insn (gen_cstore4_media (operands[0], operands[1], 12673 operands[2], operands[3])); 12674 DONE; 12675 } 12676 12677 if (! currently_expanding_to_rtl) 12678 FAIL; 12679 12680 sh_emit_compare_and_set (operands, SFmode); 12681 DONE; 12682}) 12683 12684(define_expand "cstoredf4" 12685 [(set (match_operand:SI 0 "register_operand" "=r") 12686 (match_operator:SI 1 "sh_float_comparison_operator" 12687 [(match_operand:DF 2 "arith_operand" "") 12688 (match_operand:DF 3 "arith_operand" "")]))] 12689 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 12690{ 12691 if (TARGET_SHMEDIA) 12692 { 12693 emit_insn (gen_cstore4_media (operands[0], operands[1], 12694 operands[2], operands[3])); 12695 DONE; 12696 } 12697 12698 if (! currently_expanding_to_rtl) 12699 FAIL; 12700 12701 sh_emit_compare_and_set (operands, DFmode); 12702 DONE; 12703}) 12704 12705;; Sometimes the T bit result of insns is needed in normal registers. 12706;; Instead of open coding all the pattern variations, use the treg_set_expr 12707;; predicate to match any T bit output insn and split it out after. 12708;; This pattern should be below all other related patterns so that it is 12709;; considered as a last resort option during matching. This allows 12710;; overriding it with special case patterns. 12711(define_insn_and_split "any_treg_expr_to_reg" 12712 [(set (match_operand:SI 0 "arith_reg_dest") 12713 (match_operand 1 "treg_set_expr")) 12714 (clobber (reg:SI T_REG))] 12715 "TARGET_SH1 && can_create_pseudo_p ()" 12716 "#" 12717 "&& !sh_in_recog_treg_set_expr ()" 12718 [(const_int 0)] 12719{ 12720 if (dump_file) 12721 fprintf (dump_file, "splitting any_treg_expr_to_reg\n"); 12722 12723 if (t_reg_operand (operands[1], VOIDmode)) 12724 { 12725 if (dump_file) 12726 fprintf (dump_file, "t_reg_operand: emitting movt\n"); 12727 emit_insn (gen_movt (operands[0], get_t_reg_rtx ())); 12728 DONE; 12729 } 12730 if (negt_reg_operand (operands[1], VOIDmode)) 12731 { 12732 if (dump_file) 12733 fprintf (dump_file, "negt_reg_operand: emitting movrt\n"); 12734 emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ())); 12735 DONE; 12736 } 12737 12738 /* If the split out insns ended with a nott, emit a movrt sequence, 12739 otherwise a normal movt. */ 12740 sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn); 12741 rtx_insn* i = NULL; 12742 if (ti.remove_trailing_nott ()) 12743 { 12744 /* Emit this same insn_and_split again. However, the next time it 12745 is split, it will emit the actual negc/movrt insn. This gives 12746 other surrounding insns the chance to see the trailing movrt. */ 12747 if (dump_file) 12748 fprintf (dump_file, 12749 "any_treg_expr_to_reg: replacing trailing nott with movrt\n"); 12750 i = emit_insn (gen_any_treg_expr_to_reg ( 12751 operands[0], gen_rtx_XOR (SImode, get_t_reg_rtx (), 12752 const1_rtx))); 12753 } 12754 else 12755 { 12756 i = emit_insn (gen_movt (operands[0], get_t_reg_rtx ())); 12757 if (dump_file) 12758 fprintf (dump_file, "any_treg_expr_to_reg: appending movt\n"); 12759 } 12760 12761 add_reg_note (i, REG_UNUSED, get_t_reg_rtx ()); 12762 DONE; 12763}) 12764 12765;; ------------------------------------------------------------------------- 12766;; Instructions to cope with inline literal tables 12767;; ------------------------------------------------------------------------- 12768 12769;; 2 byte integer in line 12770(define_insn "consttable_2" 12771 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g") 12772 (match_operand 1 "" "")] 12773 UNSPECV_CONST2)] 12774 "" 12775{ 12776 if (operands[1] != const0_rtx) 12777 assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1); 12778 return ""; 12779} 12780 [(set_attr "length" "2") 12781 (set_attr "in_delay_slot" "no")]) 12782 12783;; 4 byte integer in line 12784(define_insn "consttable_4" 12785 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g") 12786 (match_operand 1 "" "")] 12787 UNSPECV_CONST4)] 12788 "" 12789{ 12790 if (operands[1] != const0_rtx) 12791 { 12792 assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1); 12793 mark_symbol_refs_as_used (operands[0]); 12794 } 12795 return ""; 12796} 12797 [(set_attr "length" "4") 12798 (set_attr "in_delay_slot" "no")]) 12799 12800;; 8 byte integer in line 12801(define_insn "consttable_8" 12802 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g") 12803 (match_operand 1 "" "")] 12804 UNSPECV_CONST8)] 12805 "" 12806{ 12807 if (operands[1] != const0_rtx) 12808 assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1); 12809 return ""; 12810} 12811 [(set_attr "length" "8") 12812 (set_attr "in_delay_slot" "no")]) 12813 12814;; 4 byte floating point 12815(define_insn "consttable_sf" 12816 [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g") 12817 (match_operand 1 "" "")] 12818 UNSPECV_CONST4)] 12819 "" 12820{ 12821 if (operands[1] != const0_rtx) 12822 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]), 12823 SFmode, GET_MODE_ALIGNMENT (SFmode)); 12824 return ""; 12825} 12826 [(set_attr "length" "4") 12827 (set_attr "in_delay_slot" "no")]) 12828 12829;; 8 byte floating point 12830(define_insn "consttable_df" 12831 [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g") 12832 (match_operand 1 "" "")] 12833 UNSPECV_CONST8)] 12834 "" 12835{ 12836 if (operands[1] != const0_rtx) 12837 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]), 12838 DFmode, GET_MODE_ALIGNMENT (DFmode)); 12839 return ""; 12840} 12841 [(set_attr "length" "8") 12842 (set_attr "in_delay_slot" "no")]) 12843 12844;; Alignment is needed for some constant tables; it may also be added for 12845;; Instructions at the start of loops, or after unconditional branches. 12846;; ??? We would get more accurate lengths if we did instruction 12847;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used 12848;; here is too conservative. 12849 12850;; align to a two byte boundary 12851(define_expand "align_2" 12852 [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)] 12853 "" 12854 "") 12855 12856;; Align to a four byte boundary. 12857;; align_4 and align_log are instructions for the starts of loops, or 12858;; after unconditional branches, which may take up extra room. 12859(define_expand "align_4" 12860 [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)] 12861 "" 12862 "") 12863 12864;; Align to a cache line boundary. 12865(define_insn "align_log" 12866 [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)] 12867 "" 12868 "" 12869 [(set_attr "length" "0") 12870 (set_attr "in_delay_slot" "no")]) 12871 12872;; Emitted at the end of the literal table, used to emit the 12873;; 32bit branch labels if needed. 12874(define_insn "consttable_end" 12875 [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)] 12876 "" 12877{ 12878 return output_jump_label_table (); 12879} 12880 [(set_attr "in_delay_slot" "no")]) 12881 12882;; Emitted at the end of the window in the literal table. 12883(define_insn "consttable_window_end" 12884 [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)] 12885 "" 12886 "" 12887 [(set_attr "length" "0") 12888 (set_attr "in_delay_slot" "no")]) 12889 12890;; ------------------------------------------------------------------------- 12891;; Minimum / maximum operations. 12892;; ------------------------------------------------------------------------- 12893 12894;; The SH2A clips.b and clips.w insns do a signed min-max function. If smin 12895;; and smax standard name patterns are defined, they will be used during 12896;; initial expansion and combine will then be able to form the actual min-max 12897;; pattern. 12898;; The clips.b and clips.w set the SR.CS bit if the value in the register is 12899;; clipped, but there is currently no way of making use of this information. 12900;; The only way to read or reset the SR.CS bit is by accessing the SR. 12901(define_expand "<code>si3" 12902 [(parallel [(set (match_operand:SI 0 "arith_reg_dest") 12903 (SMIN_SMAX:SI (match_operand:SI 1 "arith_reg_operand") 12904 (match_operand 2 "const_int_operand"))) 12905 (clobber (reg:SI T_REG))])] 12906 "TARGET_SH2A" 12907{ 12908 /* Force the comparison value into a register, because greater-than 12909 comparisons can work only on registers. Combine will be able to pick up 12910 the constant value from the REG_EQUAL note when trying to form a min-max 12911 pattern. */ 12912 operands[2] = force_reg (SImode, operands[2]); 12913}) 12914 12915;; Convert 12916;; smax (smin (...)) 12917;; to 12918;; smin (smax (...)) 12919(define_insn_and_split "*clips" 12920 [(set (match_operand:SI 0 "arith_reg_dest") 12921 (smax:SI (smin:SI (match_operand:SI 1 "arith_reg_operand") 12922 (match_operand 2 "clips_max_const_int")) 12923 (match_operand 3 "clips_min_const_int")))] 12924 "TARGET_SH2A" 12925 "#" 12926 "&& 1" 12927 [(set (match_dup 0) 12928 (smin:SI (smax:SI (match_dup 1) (match_dup 3)) (match_dup 2)))]) 12929 12930(define_insn "*clips" 12931 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 12932 (smin:SI (smax:SI (match_operand:SI 1 "arith_reg_operand" "0") 12933 (match_operand 2 "clips_min_const_int")) 12934 (match_operand 3 "clips_max_const_int")))] 12935 "TARGET_SH2A" 12936{ 12937 if (INTVAL (operands[3]) == 127) 12938 return "clips.b %0"; 12939 else if (INTVAL (operands[3]) == 32767) 12940 return "clips.w %0"; 12941 else 12942 gcc_unreachable (); 12943} 12944 [(set_attr "type" "arith")]) 12945 12946;; If the expanded smin or smax patterns were not combined, split them into 12947;; a compare and branch sequence, because there are no real smin or smax 12948;; insns. 12949(define_insn_and_split "*<code>si3" 12950 [(set (match_operand:SI 0 "arith_reg_dest") 12951 (SMIN_SMAX:SI (match_operand:SI 1 "arith_reg_operand") 12952 (match_operand:SI 2 "arith_reg_or_0_or_1_operand"))) 12953 (clobber (reg:SI T_REG))] 12954 "TARGET_SH2A && can_create_pseudo_p ()" 12955 "#" 12956 "&& 1" 12957 [(const_int 0)] 12958{ 12959 rtx skip_label = gen_label_rtx (); 12960 emit_move_insn (operands[0], operands[1]); 12961 12962 rtx cmp_val = operands[2]; 12963 if (satisfies_constraint_M (cmp_val)) 12964 cmp_val = const0_rtx; 12965 12966 emit_insn (gen_cmpgtsi_t (operands[0], cmp_val)); 12967 emit_jump_insn (<CODE> == SMIN 12968 ? gen_branch_false (skip_label) 12969 : gen_branch_true (skip_label)); 12970 12971 emit_label_after (skip_label, emit_move_insn (operands[0], operands[2])); 12972 DONE; 12973}) 12974 12975;; The SH2A clipu.b and clipu.w insns can be used to implement a min function 12976;; with a register and a constant. 12977;; The clipu.b and clipu.w set the SR.CS bit if the value in the register is 12978;; clipped, but there is currently no way of making use of this information. 12979;; The only way to read or reset the SR.CS bit is by accessing the SR. 12980(define_expand "uminsi3" 12981 [(set (match_operand:SI 0 "arith_reg_dest") 12982 (umin:SI (match_operand:SI 1 "arith_reg_operand") 12983 (match_operand 2 "const_int_operand")))] 12984 "TARGET_SH2A" 12985{ 12986 if (INTVAL (operands[2]) == 1) 12987 { 12988 emit_insn (gen_clipu_one (operands[0], operands[1])); 12989 DONE; 12990 } 12991 else if (! clipu_max_const_int (operands[2], VOIDmode)) 12992 FAIL; 12993}) 12994 12995(define_insn "*clipu" 12996 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 12997 (umin:SI (match_operand:SI 1 "arith_reg_operand" "0") 12998 (match_operand 2 "clipu_max_const_int")))] 12999 "TARGET_SH2A" 13000{ 13001 if (INTVAL (operands[2]) == 255) 13002 return "clipu.b %0"; 13003 else if (INTVAL (operands[2]) == 65535) 13004 return "clipu.w %0"; 13005 else 13006 gcc_unreachable (); 13007} 13008 [(set_attr "type" "arith")]) 13009 13010(define_insn_and_split "clipu_one" 13011 [(set (match_operand:SI 0 "arith_reg_dest") 13012 (umin:SI (match_operand:SI 1 "arith_reg_operand") (const_int 1))) 13013 (clobber (reg:SI T_REG))] 13014 "TARGET_SH2A" 13015 "#" 13016 "&& can_create_pseudo_p ()" 13017 [(const_int 0)] 13018{ 13019 emit_insn (gen_cmpeqsi_t (operands[1], const0_rtx)); 13020 emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ())); 13021 DONE; 13022}) 13023 13024;; ------------------------------------------------------------------------- 13025;; Misc 13026;; ------------------------------------------------------------------------- 13027 13028;; String/block move insn. 13029 13030(define_expand "movmemsi" 13031 [(parallel [(set (mem:BLK (match_operand:BLK 0)) 13032 (mem:BLK (match_operand:BLK 1))) 13033 (use (match_operand:SI 2 "nonmemory_operand")) 13034 (use (match_operand:SI 3 "immediate_operand")) 13035 (clobber (reg:SI PR_REG)) 13036 (clobber (reg:SI R4_REG)) 13037 (clobber (reg:SI R5_REG)) 13038 (clobber (reg:SI R0_REG))])] 13039 "TARGET_SH1 && ! TARGET_SH5" 13040{ 13041 if (expand_block_move (operands)) 13042 DONE; 13043 else 13044 FAIL; 13045}) 13046 13047(define_insn "block_move_real" 13048 [(parallel [(set (mem:BLK (reg:SI R4_REG)) 13049 (mem:BLK (reg:SI R5_REG))) 13050 (use (match_operand:SI 0 "arith_reg_operand" "r,r")) 13051 (use (match_operand 1 "" "Z,Ccl")) 13052 (clobber (reg:SI PR_REG)) 13053 (clobber (reg:SI R0_REG))])] 13054 "TARGET_SH1 && ! TARGET_HARD_SH4" 13055 "@ 13056 jsr @%0%# 13057 bsrf %0\n%O1:%#" 13058 [(set_attr "type" "sfunc") 13059 (set_attr "needs_delay_slot" "yes")]) 13060 13061(define_insn "block_lump_real" 13062 [(parallel [(set (mem:BLK (reg:SI R4_REG)) 13063 (mem:BLK (reg:SI R5_REG))) 13064 (use (match_operand:SI 0 "arith_reg_operand" "r,r")) 13065 (use (match_operand 1 "" "Z,Ccl")) 13066 (use (reg:SI R6_REG)) 13067 (clobber (reg:SI PR_REG)) 13068 (clobber (reg:SI T_REG)) 13069 (clobber (reg:SI R4_REG)) 13070 (clobber (reg:SI R5_REG)) 13071 (clobber (reg:SI R6_REG)) 13072 (clobber (reg:SI R0_REG))])] 13073 "TARGET_SH1 && ! TARGET_HARD_SH4" 13074 "@ 13075 jsr @%0%# 13076 bsrf %0\n%O1:%#" 13077 [(set_attr "type" "sfunc") 13078 (set_attr "needs_delay_slot" "yes")]) 13079 13080(define_insn "block_move_real_i4" 13081 [(parallel [(set (mem:BLK (reg:SI R4_REG)) 13082 (mem:BLK (reg:SI R5_REG))) 13083 (use (match_operand:SI 0 "arith_reg_operand" "r,r")) 13084 (use (match_operand 1 "" "Z,Ccl")) 13085 (clobber (reg:SI PR_REG)) 13086 (clobber (reg:SI R0_REG)) 13087 (clobber (reg:SI R1_REG)) 13088 (clobber (reg:SI R2_REG))])] 13089 "TARGET_HARD_SH4" 13090 "@ 13091 jsr @%0%# 13092 bsrf %0\n%O1:%#" 13093 [(set_attr "type" "sfunc") 13094 (set_attr "needs_delay_slot" "yes")]) 13095 13096(define_insn "block_lump_real_i4" 13097 [(parallel [(set (mem:BLK (reg:SI R4_REG)) 13098 (mem:BLK (reg:SI R5_REG))) 13099 (use (match_operand:SI 0 "arith_reg_operand" "r,r")) 13100 (use (match_operand 1 "" "Z,Ccl")) 13101 (use (reg:SI R6_REG)) 13102 (clobber (reg:SI PR_REG)) 13103 (clobber (reg:SI T_REG)) 13104 (clobber (reg:SI R4_REG)) 13105 (clobber (reg:SI R5_REG)) 13106 (clobber (reg:SI R6_REG)) 13107 (clobber (reg:SI R0_REG)) 13108 (clobber (reg:SI R1_REG)) 13109 (clobber (reg:SI R2_REG)) 13110 (clobber (reg:SI R3_REG))])] 13111 "TARGET_HARD_SH4" 13112 "@ 13113 jsr @%0%# 13114 bsrf %0\n%O1:%#" 13115 [(set_attr "type" "sfunc") 13116 (set_attr "needs_delay_slot" "yes")]) 13117 13118;; byte compare pattern 13119;; temp = a ^ b; 13120;; !((temp & 0xF000) && (temp & 0x0F00) && (temp & 0x00F0) && (temp & 0x000F)) 13121(define_insn "cmpstr_t" 13122 [(set (reg:SI T_REG) 13123 (eq:SI (and:SI 13124 (and:SI 13125 (and:SI 13126 (zero_extract:SI 13127 (xor:SI (match_operand:SI 0 "arith_reg_operand" "r") 13128 (match_operand:SI 1 "arith_reg_operand" "r")) 13129 (const_int 8) (const_int 0)) 13130 (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1)) 13131 (const_int 8) (const_int 8))) 13132 (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1)) 13133 (const_int 8) (const_int 16))) 13134 (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1)) 13135 (const_int 8) (const_int 24))) 13136 (const_int 0)))] 13137 "TARGET_SH1" 13138 "cmp/str %0,%1" 13139 [(set_attr "type" "mt_group")]) 13140 13141(define_expand "cmpstrsi" 13142 [(set (match_operand:SI 0 "register_operand") 13143 (compare:SI (match_operand:BLK 1 "memory_operand") 13144 (match_operand:BLK 2 "memory_operand"))) 13145 (use (match_operand 3 "immediate_operand"))] 13146 "TARGET_SH1 && optimize" 13147{ 13148 if (! optimize_insn_for_size_p () && sh_expand_cmpstr (operands)) 13149 DONE; 13150 else 13151 FAIL; 13152}) 13153 13154(define_expand "cmpstrnsi" 13155 [(set (match_operand:SI 0 "register_operand") 13156 (compare:SI (match_operand:BLK 1 "memory_operand") 13157 (match_operand:BLK 2 "memory_operand"))) 13158 (use (match_operand:SI 3 "nonmemory_operand")) 13159 (use (match_operand:SI 4 "immediate_operand"))] 13160 "TARGET_SH1 && optimize" 13161{ 13162 if (! optimize_insn_for_size_p () && sh_expand_cmpnstr (operands)) 13163 DONE; 13164 else 13165 FAIL; 13166}) 13167 13168(define_expand "strlensi" 13169 [(set (match_operand:SI 0 "register_operand") 13170 (unspec:SI [(match_operand:BLK 1 "memory_operand") 13171 (match_operand:SI 2 "immediate_operand") 13172 (match_operand:SI 3 "immediate_operand")] 13173 UNSPEC_BUILTIN_STRLEN))] 13174 "TARGET_SH1 && optimize" 13175{ 13176 if (! optimize_insn_for_size_p () && sh_expand_strlen (operands)) 13177 DONE; 13178 else 13179 FAIL; 13180}) 13181 13182(define_expand "setmemqi" 13183 [(parallel [(set (match_operand:BLK 0 "memory_operand") 13184 (match_operand 2 "const_int_operand")) 13185 (use (match_operand:QI 1 "const_int_operand")) 13186 (use (match_operand:QI 3 "const_int_operand"))])] 13187 "TARGET_SH1 && optimize" 13188 { 13189 if (optimize_insn_for_size_p ()) 13190 FAIL; 13191 13192 sh_expand_setmem (operands); 13193 DONE; 13194 }) 13195 13196 13197;; ------------------------------------------------------------------------- 13198;; Floating point instructions. 13199;; ------------------------------------------------------------------------- 13200 13201;; FIXME: For now we disallow any memory operands for fpscr loads/stores, 13202;; except for post-inc loads and pre-dec stores for push/pop purposes. 13203;; This avoids problems with reload. As a consequence, user initiated fpscr 13204;; stores to memory will always be ferried through a general register. 13205;; User initiated fpscr loads always have to undergo bit masking to preserve 13206;; the current fpu mode settings for the compiler generated code. Thus such 13207;; fpscr loads will always have to go through general registers anyways. 13208(define_insn "lds_fpscr" 13209 [(set (reg:SI FPSCR_REG) 13210 (match_operand:SI 0 "fpscr_movsrc_operand" "r,>")) 13211 (set (reg:SI FPSCR_STAT_REG) 13212 (unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_STAT)) 13213 (set (reg:SI FPSCR_MODES_REG) 13214 (unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))] 13215 "TARGET_FPU_ANY" 13216 "@ 13217 lds %0,fpscr 13218 lds.l %0,fpscr" 13219 [(set_attr "type" "gp_fpscr,mem_fpscr")]) 13220 13221;; A move fpscr -> reg schedules like a move mac -> reg. Thus we use mac_gp 13222;; type for it. 13223(define_insn "sts_fpscr" 13224 [(set (match_operand:SI 0 "fpscr_movdst_operand" "=r,<") 13225 (reg:SI FPSCR_REG)) 13226 (use (reg:SI FPSCR_STAT_REG)) 13227 (use (reg:SI FPSCR_MODES_REG))] 13228 "TARGET_FPU_ANY" 13229 "@ 13230 sts fpscr,%0 13231 sts.l fpscr,%0" 13232 [(set_attr "type" "mac_gp,fstore")]) 13233 13234(define_expand "set_fpscr" 13235 [(parallel [(set (reg:SI FPSCR_REG) 13236 (match_operand:SI 0 "general_operand")) 13237 (set (reg:SI FPSCR_STAT_REG) 13238 (unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))])] 13239 "TARGET_FPU_ANY" 13240{ 13241 /* We have to mask out the FR, SZ and PR bits. To do that, we need to 13242 get the current FPSCR value first. 13243 (a & ~mask) | (b & mask) = a ^ ((a ^ b) & mask) */ 13244 13245 rtx mask = force_reg (SImode, GEN_INT (FPSCR_FR | FPSCR_SZ | FPSCR_PR)); 13246 13247 rtx a = force_reg (SImode, operands[0]); 13248 13249 rtx b = gen_reg_rtx (SImode); 13250 emit_insn (gen_sts_fpscr (b)); 13251 13252 rtx a_xor_b = gen_reg_rtx (SImode); 13253 emit_insn (gen_xorsi3 (a_xor_b, a, b)); 13254 13255 rtx a_xor_b_and_mask = gen_reg_rtx (SImode); 13256 emit_insn (gen_andsi3 (a_xor_b_and_mask, a_xor_b, mask)); 13257 13258 rtx r = gen_reg_rtx (SImode); 13259 emit_insn (gen_xorsi3 (r, a_xor_b_and_mask, a)); 13260 emit_insn (gen_lds_fpscr (r)); 13261 13262 DONE; 13263}) 13264 13265;; ??? This uses the fp unit, but has no type indicating that. 13266;; If we did that, this would either give a bogus latency or introduce 13267;; a bogus FIFO constraint. 13268;; Since this insn is currently only used for prologues/epilogues, 13269;; it is probably best to claim no function unit, which matches the 13270;; current setting. 13271(define_insn "toggle_sz" 13272 [(set (reg:SI FPSCR_REG) 13273 (xor:SI (reg:SI FPSCR_REG) (const_int FPSCR_SZ))) 13274 (set (reg:SI FPSCR_MODES_REG) 13275 (unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))] 13276 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 13277 "fschg" 13278 [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")]) 13279 13280;; Toggle FPU precision PR mode. 13281 13282(define_insn "toggle_pr" 13283 [(set (reg:SI FPSCR_REG) 13284 (xor:SI (reg:SI FPSCR_REG) (const_int FPSCR_PR))) 13285 (set (reg:SI FPSCR_MODES_REG) 13286 (unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))] 13287 "TARGET_SH4A_FP" 13288 "fpchg" 13289 [(set_attr "type" "fpscr_toggle")]) 13290 13291(define_expand "addsf3" 13292 [(set (match_operand:SF 0 "fp_arith_reg_operand") 13293 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand") 13294 (match_operand:SF 2 "fp_arith_reg_operand")))] 13295 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 13296{ 13297 if (TARGET_SH2E) 13298 { 13299 emit_insn (gen_addsf3_i (operands[0], operands[1], operands[2])); 13300 DONE; 13301 } 13302}) 13303 13304(define_insn "*addsf3_media" 13305 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13306 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f") 13307 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 13308 "TARGET_SHMEDIA_FPU" 13309 "fadd.s %1, %2, %0" 13310 [(set_attr "type" "fparith_media")]) 13311 13312(define_insn_and_split "unary_sf_op" 13313 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f") 13314 (vec_select:V2SF 13315 (vec_concat:V2SF 13316 (vec_select:SF 13317 (match_dup 0) 13318 (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))])) 13319 (match_operator:SF 2 "unary_float_operator" 13320 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f") 13321 (parallel [(match_operand 4 13322 "const_int_operand" "n")]))])) 13323 (parallel [(not:BI (match_dup 3)) (match_dup 3)])))] 13324 "TARGET_SHMEDIA_FPU" 13325 "#" 13326 "TARGET_SHMEDIA_FPU && reload_completed" 13327 [(set (match_dup 5) (match_dup 6))] 13328{ 13329 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1; 13330 rtx op1 = gen_rtx_REG (SFmode, 13331 (true_regnum (operands[1]) 13332 + (INTVAL (operands[4]) ^ endian))); 13333 13334 operands[7] = gen_rtx_REG (SFmode, 13335 (true_regnum (operands[0]) 13336 + (INTVAL (operands[3]) ^ endian))); 13337 operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1); 13338} 13339 [(set_attr "type" "fparith_media")]) 13340 13341(define_insn_and_split "binary_sf_op0" 13342 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f") 13343 (vec_concat:V2SF 13344 (match_operator:SF 3 "binary_float_operator" 13345 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f") 13346 (parallel [(const_int 0)])) 13347 (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f") 13348 (parallel [(const_int 0)]))]) 13349 (vec_select:SF 13350 (match_dup 0) 13351 (parallel [(const_int 1)]))))] 13352 "TARGET_SHMEDIA_FPU" 13353 "#" 13354 "&& reload_completed" 13355 [(set (match_dup 4) (match_dup 5))] 13356{ 13357 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1; 13358 rtx op1 = gen_rtx_REG (SFmode, 13359 true_regnum (operands[1]) + endian); 13360 rtx op2 = gen_rtx_REG (SFmode, 13361 true_regnum (operands[2]) + endian); 13362 13363 operands[4] = gen_rtx_REG (SFmode, 13364 true_regnum (operands[0]) + endian); 13365 operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2); 13366} 13367 [(set_attr "type" "fparith_media")]) 13368 13369(define_insn_and_split "binary_sf_op1" 13370 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f") 13371 (vec_concat:V2SF 13372 (vec_select:SF 13373 (match_dup 0) 13374 (parallel [(const_int 0)])) 13375 (match_operator:SF 3 "binary_float_operator" 13376 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f") 13377 (parallel [(const_int 1)])) 13378 (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f") 13379 (parallel [(const_int 1)]))])))] 13380 "TARGET_SHMEDIA_FPU" 13381 "#" 13382 "&& reload_completed" 13383 [(set (match_dup 4) (match_dup 5))] 13384{ 13385 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1; 13386 rtx op1 = gen_rtx_REG (SFmode, true_regnum (operands[1]) + (1 ^ endian)); 13387 rtx op2 = gen_rtx_REG (SFmode, true_regnum (operands[2]) + (1 ^ endian)); 13388 13389 operands[4] = gen_rtx_REG (SFmode, true_regnum (operands[0]) + (1 ^ endian)); 13390 operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2); 13391} 13392 [(set_attr "type" "fparith_media")]) 13393 13394(define_insn "addsf3_i" 13395 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13396 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0") 13397 (match_operand:SF 2 "fp_arith_reg_operand" "f"))) 13398 (clobber (reg:SI FPSCR_STAT_REG)) 13399 (use (reg:SI FPSCR_MODES_REG))] 13400 "TARGET_SH2E" 13401 "fadd %2,%0" 13402 [(set_attr "type" "fp") 13403 (set_attr "fp_mode" "single")]) 13404 13405(define_expand "subsf3" 13406 [(set (match_operand:SF 0 "fp_arith_reg_operand" "") 13407 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "") 13408 (match_operand:SF 2 "fp_arith_reg_operand" "")))] 13409 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 13410{ 13411 if (TARGET_SH2E) 13412 { 13413 emit_insn (gen_subsf3_i (operands[0], operands[1], operands[2])); 13414 DONE; 13415 } 13416}) 13417 13418(define_insn "*subsf3_media" 13419 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13420 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f") 13421 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 13422 "TARGET_SHMEDIA_FPU" 13423 "fsub.s %1, %2, %0" 13424 [(set_attr "type" "fparith_media")]) 13425 13426(define_insn "subsf3_i" 13427 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13428 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0") 13429 (match_operand:SF 2 "fp_arith_reg_operand" "f"))) 13430 (clobber (reg:SI FPSCR_STAT_REG)) 13431 (use (reg:SI FPSCR_MODES_REG))] 13432 "TARGET_SH2E" 13433 "fsub %2,%0" 13434 [(set_attr "type" "fp") 13435 (set_attr "fp_mode" "single")]) 13436 13437(define_expand "mulsf3" 13438 [(set (match_operand:SF 0 "fp_arith_reg_operand" "") 13439 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "") 13440 (match_operand:SF 2 "fp_arith_reg_operand" "")))] 13441 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 13442{ 13443 if (TARGET_SH2E) 13444 { 13445 emit_insn (gen_mulsf3_i (operands[0], operands[1], operands[2])); 13446 DONE; 13447 } 13448}) 13449 13450(define_insn "*mulsf3_media" 13451 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13452 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f") 13453 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 13454 "TARGET_SHMEDIA_FPU" 13455 "fmul.s %1, %2, %0" 13456 [(set_attr "type" "fparith_media")]) 13457 13458(define_insn "mulsf3_i" 13459 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13460 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0") 13461 (match_operand:SF 2 "fp_arith_reg_operand" "f"))) 13462 (clobber (reg:SI FPSCR_STAT_REG)) 13463 (use (reg:SI FPSCR_MODES_REG))] 13464 "TARGET_SH2E" 13465 "fmul %2,%0" 13466 [(set_attr "type" "fp") 13467 (set_attr "fp_mode" "single")]) 13468 13469;; FMA (fused multiply-add) patterns 13470(define_expand "fmasf4" 13471 [(set (match_operand:SF 0 "fp_arith_reg_operand") 13472 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand") 13473 (match_operand:SF 2 "fp_arith_reg_operand") 13474 (match_operand:SF 3 "fp_arith_reg_operand")))] 13475 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 13476{ 13477 if (TARGET_SH2E) 13478 { 13479 emit_insn (gen_fmasf4_i (operands[0], operands[1], operands[2], 13480 operands[3])); 13481 DONE; 13482 } 13483}) 13484 13485(define_insn "fmasf4_i" 13486 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13487 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "w") 13488 (match_operand:SF 2 "fp_arith_reg_operand" "f") 13489 (match_operand:SF 3 "fp_arith_reg_operand" "0"))) 13490 (clobber (reg:SI FPSCR_STAT_REG)) 13491 (use (reg:SI FPSCR_MODES_REG))] 13492 "TARGET_SH2E" 13493 "fmac %1,%2,%0" 13494 [(set_attr "type" "fp") 13495 (set_attr "fp_mode" "single")]) 13496 13497(define_insn "fmasf4_media" 13498 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13499 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "f") 13500 (match_operand:SF 2 "fp_arith_reg_operand" "f") 13501 (match_operand:SF 3 "fp_arith_reg_operand" "0")))] 13502 "TARGET_SHMEDIA_FPU" 13503 "fmac.s %1, %2, %0" 13504 [(set_attr "type" "fparith_media")]) 13505 13506;; For some cases such as 'a * b + a' the FMA pattern is not generated by 13507;; previous transformations. If FMA is generally allowed, let the combine 13508;; pass utilize it. 13509(define_insn_and_split "*fmasf4" 13510 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13511 (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w") 13512 (match_operand:SF 2 "fp_arith_reg_operand" "f")) 13513 (match_operand:SF 3 "arith_reg_operand" "0"))) 13514 (clobber (reg:SI FPSCR_STAT_REG)) 13515 (use (reg:SI FPSCR_MODES_REG))] 13516 "TARGET_SH2E && flag_fp_contract_mode != FP_CONTRACT_OFF" 13517 "fmac %1,%2,%0" 13518 "&& can_create_pseudo_p ()" 13519 [(parallel [(set (match_dup 0) 13520 (fma:SF (match_dup 1) (match_dup 2) (match_dup 3))) 13521 (clobber (reg:SI FPSCR_STAT_REG)) 13522 (use (reg:SI FPSCR_MODES_REG))])] 13523{ 13524 /* Change 'b * a + a' into 'a * b + a'. 13525 This is better for register allocation. */ 13526 if (REGNO (operands[2]) == REGNO (operands[3])) 13527 std::swap (operands[1], operands[2]); 13528} 13529 [(set_attr "type" "fp") 13530 (set_attr "fp_mode" "single")]) 13531 13532(define_insn "*fmasf4_media" 13533 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13534 (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f") 13535 (match_operand:SF 2 "fp_arith_reg_operand" "f")) 13536 (match_operand:SF 3 "fp_arith_reg_operand" "0")))] 13537 "TARGET_SHMEDIA_FPU && flag_fp_contract_mode != FP_CONTRACT_OFF" 13538 "fmac.s %1, %2, %0" 13539 [(set_attr "type" "fparith_media")]) 13540 13541(define_expand "divsf3" 13542 [(set (match_operand:SF 0 "fp_arith_reg_operand") 13543 (div:SF (match_operand:SF 1 "fp_arith_reg_operand") 13544 (match_operand:SF 2 "fp_arith_reg_operand")))] 13545 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 13546{ 13547 if (TARGET_SH2E) 13548 { 13549 emit_insn (gen_divsf3_i (operands[0], operands[1], operands[2])); 13550 DONE; 13551 } 13552}) 13553 13554(define_insn "*divsf3_media" 13555 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13556 (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f") 13557 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 13558 "TARGET_SHMEDIA_FPU" 13559 "fdiv.s %1, %2, %0" 13560 [(set_attr "type" "fdiv_media")]) 13561 13562(define_insn "divsf3_i" 13563 [(set (match_operand:SF 0 "fp_arith_reg_dest" "=f") 13564 (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "0") 13565 (match_operand:SF 2 "fp_arith_reg_operand" "f"))) 13566 (clobber (reg:SI FPSCR_STAT_REG)) 13567 (use (reg:SI FPSCR_MODES_REG))] 13568 "TARGET_SH2E" 13569 "fdiv %2,%0" 13570 [(set_attr "type" "fdiv") 13571 (set_attr "fp_mode" "single")]) 13572 13573(define_insn "floatdisf2" 13574 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13575 (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))] 13576 "TARGET_SHMEDIA_FPU" 13577 "float.qs %1, %0" 13578 [(set_attr "type" "fpconv_media")]) 13579 13580(define_expand "floatsisf2" 13581 [(set (match_operand:SF 0 "fp_arith_reg_operand" "") 13582 (float:SF (match_operand:SI 1 "fpul_operand" "")))] 13583 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 13584{ 13585 if (!TARGET_SHMEDIA_FPU) 13586 { 13587 emit_insn (gen_floatsisf2_i4 (operands[0], operands[1])); 13588 DONE; 13589 } 13590}) 13591 13592(define_insn "*floatsisf2_media" 13593 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13594 (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))] 13595 "TARGET_SHMEDIA_FPU" 13596 "float.ls %1, %0" 13597 [(set_attr "type" "fpconv_media")]) 13598 13599(define_insn "floatsisf2_i4" 13600 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13601 (float:SF (match_operand:SI 1 "fpul_operand" "y"))) 13602 (clobber (reg:SI FPSCR_STAT_REG)) 13603 (use (reg:SI FPSCR_MODES_REG))] 13604 "TARGET_SH2E" 13605 "float %1,%0" 13606 [(set_attr "type" "fp") 13607 (set_attr "fp_mode" "single")]) 13608 13609(define_insn "fix_truncsfdi2" 13610 [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f") 13611 (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 13612 "TARGET_SHMEDIA_FPU" 13613 "ftrc.sq %1, %0" 13614 [(set_attr "type" "fpconv_media")]) 13615 13616(define_expand "fix_truncsfsi2" 13617 [(set (match_operand:SI 0 "fpul_operand" "=y") 13618 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 13619 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 13620{ 13621 if (!TARGET_SHMEDIA_FPU) 13622 { 13623 emit_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1])); 13624 DONE; 13625 } 13626}) 13627 13628(define_insn "*fix_truncsfsi2_media" 13629 [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f") 13630 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 13631 "TARGET_SHMEDIA_FPU" 13632 "ftrc.sl %1, %0" 13633 [(set_attr "type" "fpconv_media")]) 13634 13635(define_insn "fix_truncsfsi2_i4" 13636 [(set (match_operand:SI 0 "fpul_operand" "=y") 13637 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f"))) 13638 (clobber (reg:SI FPSCR_STAT_REG)) 13639 (use (reg:SI FPSCR_MODES_REG))] 13640 "TARGET_SH2E" 13641 "ftrc %1,%0" 13642 [(set_attr "type" "ftrc_s") 13643 (set_attr "fp_mode" "single")]) 13644 13645(define_insn "cmpgtsf_t" 13646 [(set (reg:SI T_REG) 13647 (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f") 13648 (match_operand:SF 1 "fp_arith_reg_operand" "f"))) 13649 (clobber (reg:SI FPSCR_STAT_REG)) 13650 (use (reg:SI FPSCR_MODES_REG))] 13651 "TARGET_SH2E || TARGET_SH4 || TARGET_SH2A_SINGLE" 13652 "fcmp/gt %1,%0" 13653 [(set_attr "type" "fp_cmp") 13654 (set_attr "fp_mode" "single")]) 13655 13656(define_insn "cmpeqsf_t" 13657 [(set (reg:SI T_REG) 13658 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f") 13659 (match_operand:SF 1 "fp_arith_reg_operand" "f"))) 13660 (clobber (reg:SI FPSCR_STAT_REG)) 13661 (use (reg:SI FPSCR_MODES_REG))] 13662 "TARGET_SH2E || TARGET_SH4 || TARGET_SH2A_SINGLE" 13663 "fcmp/eq %1,%0" 13664 [(set_attr "type" "fp_cmp") 13665 (set_attr "fp_mode" "single")]) 13666 13667(define_insn "ieee_ccmpeqsf_t" 13668 [(set (reg:SI T_REG) 13669 (ior:SI (reg:SI T_REG) 13670 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f") 13671 (match_operand:SF 1 "fp_arith_reg_operand" "f")))) 13672 (clobber (reg:SI FPSCR_STAT_REG)) 13673 (use (reg:SI FPSCR_MODES_REG))] 13674 "TARGET_IEEE && TARGET_SH2E" 13675{ 13676 return output_ieee_ccmpeq (insn, operands); 13677} 13678 [(set_attr "length" "4") 13679 (set_attr "fp_mode" "single")]) 13680 13681(define_insn "cmpeqsf_media" 13682 [(set (match_operand:SI 0 "register_operand" "=r") 13683 (eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f") 13684 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 13685 "TARGET_SHMEDIA_FPU" 13686 "fcmpeq.s %1, %2, %0" 13687 [(set_attr "type" "fcmp_media")]) 13688 13689(define_insn "cmpgtsf_media" 13690 [(set (match_operand:SI 0 "register_operand" "=r") 13691 (gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f") 13692 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 13693 "TARGET_SHMEDIA_FPU" 13694 "fcmpgt.s %1, %2, %0" 13695 [(set_attr "type" "fcmp_media")]) 13696 13697(define_insn "cmpgesf_media" 13698 [(set (match_operand:SI 0 "register_operand" "=r") 13699 (ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f") 13700 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 13701 "TARGET_SHMEDIA_FPU" 13702 "fcmpge.s %1, %2, %0" 13703 [(set_attr "type" "fcmp_media")]) 13704 13705(define_insn "cmpunsf_media" 13706 [(set (match_operand:SI 0 "register_operand" "=r") 13707 (unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f") 13708 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 13709 "TARGET_SHMEDIA_FPU" 13710 "fcmpun.s %1, %2, %0" 13711 [(set_attr "type" "fcmp_media")]) 13712 13713(define_expand "cbranchsf4" 13714 [(set (pc) 13715 (if_then_else (match_operator 0 "sh_float_comparison_operator" 13716 [(match_operand:SF 1 "arith_operand" "") 13717 (match_operand:SF 2 "arith_operand" "")]) 13718 (match_operand 3 "" "") 13719 (pc)))] 13720 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 13721{ 13722 if (TARGET_SHMEDIA) 13723 emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2], 13724 operands[3])); 13725 else 13726 sh_emit_compare_and_branch (operands, SFmode); 13727 DONE; 13728}) 13729 13730(define_expand "negsf2" 13731 [(set (match_operand:SF 0 "fp_arith_reg_operand") 13732 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand")))] 13733 "TARGET_SH2E || TARGET_SHMEDIA_FPU") 13734 13735(define_insn "*negsf2_media" 13736 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13737 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 13738 "TARGET_SHMEDIA_FPU" 13739 "fneg.s %1, %0" 13740 [(set_attr "type" "fmove_media")]) 13741 13742(define_insn "*negsf2_i" 13743 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13744 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))] 13745 "TARGET_SH2E" 13746 "fneg %0" 13747 [(set_attr "type" "fmove")]) 13748 13749(define_expand "sqrtsf2" 13750 [(set (match_operand:SF 0 "fp_arith_reg_operand" "") 13751 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))] 13752 "TARGET_SH3E || TARGET_SHMEDIA_FPU" 13753{ 13754 if (TARGET_SH3E) 13755 { 13756 emit_insn (gen_sqrtsf2_i (operands[0], operands[1])); 13757 DONE; 13758 } 13759}) 13760 13761(define_insn "*sqrtsf2_media" 13762 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13763 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 13764 "TARGET_SHMEDIA_FPU" 13765 "fsqrt.s %1, %0" 13766 [(set_attr "type" "fdiv_media")]) 13767 13768(define_insn "sqrtsf2_i" 13769 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13770 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0"))) 13771 (clobber (reg:SI FPSCR_STAT_REG)) 13772 (use (reg:SI FPSCR_MODES_REG))] 13773 "TARGET_SH3E" 13774 "fsqrt %0" 13775 [(set_attr "type" "fdiv") 13776 (set_attr "fp_mode" "single")]) 13777 13778(define_insn "rsqrtsf2" 13779 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13780 (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "0")] 13781 UNSPEC_FSRRA)) 13782 (clobber (reg:SI FPSCR_STAT_REG)) 13783 (use (reg:SI FPSCR_MODES_REG))] 13784 "TARGET_FPU_ANY && TARGET_FSRRA" 13785 "fsrra %0" 13786 [(set_attr "type" "fsrra") 13787 (set_attr "fp_mode" "single")]) 13788 13789;; When the sincos pattern is defined, the builtin functions sin and cos 13790;; will be expanded to the sincos pattern and one of the output values will 13791;; remain unused. 13792(define_expand "sincossf3" 13793 [(set (match_operand:SF 0 "nonimmediate_operand") 13794 (unspec:SF [(match_operand:SF 2 "fp_arith_reg_operand")] UNSPEC_FCOSA)) 13795 (set (match_operand:SF 1 "nonimmediate_operand") 13796 (unspec:SF [(match_dup 2)] UNSPEC_FSINA))] 13797 "TARGET_FPU_ANY && TARGET_FSCA" 13798{ 13799 rtx scaled = gen_reg_rtx (SFmode); 13800 rtx truncated = gen_reg_rtx (SImode); 13801 rtx fsca = gen_reg_rtx (V2SFmode); 13802 rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ()); 13803 13804 emit_insn (gen_mulsf3 (scaled, operands[2], scale_reg)); 13805 emit_insn (gen_fix_truncsfsi2 (truncated, scaled)); 13806 emit_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf ())); 13807 13808 emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4)); 13809 emit_move_insn (operands[1], gen_rtx_SUBREG (SFmode, fsca, 0)); 13810 DONE; 13811}) 13812 13813(define_insn_and_split "fsca" 13814 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f") 13815 (vec_concat:V2SF 13816 (unspec:SF [(mult:SF 13817 (float:SF (match_operand:SI 1 "fpul_fsca_operand" "y")) 13818 (match_operand:SF 2 "fsca_scale_factor" "i")) 13819 ] UNSPEC_FSINA) 13820 (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2)) 13821 ] UNSPEC_FCOSA))) 13822 (clobber (reg:SI FPSCR_STAT_REG)) 13823 (use (reg:SI FPSCR_MODES_REG))] 13824 "TARGET_FPU_ANY && TARGET_FSCA" 13825 "fsca fpul,%d0" 13826 "&& !fpul_operand (operands[1], SImode)" 13827 [(const_int 0)] 13828{ 13829 /* If operands[1] is something like (fix:SF (float:SF (reg:SI))) reduce it 13830 to a simple reg, otherwise reload will have trouble reloading the 13831 pseudo into fpul. */ 13832 rtx x = XEXP (operands[1], 0); 13833 while (x != NULL_RTX && !fpul_operand (x, SImode)) 13834 { 13835 gcc_assert (GET_CODE (x) == FIX || GET_CODE (x) == FLOAT); 13836 x = XEXP (x, 0); 13837 } 13838 gcc_assert (x != NULL_RTX && fpul_operand (x, SImode)); 13839 emit_insn (gen_fsca (operands[0], x, operands[2])); 13840 DONE; 13841} 13842 [(set_attr "type" "fsca") 13843 (set_attr "fp_mode" "single")]) 13844 13845(define_expand "abssf2" 13846 [(set (match_operand:SF 0 "fp_arith_reg_operand") 13847 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand")))] 13848 "TARGET_SH2E || TARGET_SHMEDIA_FPU") 13849 13850(define_insn "*abssf2_media" 13851 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13852 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 13853 "TARGET_SHMEDIA_FPU" 13854 "fabs.s %1, %0" 13855 [(set_attr "type" "fmove_media")]) 13856 13857(define_insn "*abssf2_i" 13858 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13859 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))] 13860 "TARGET_SH2E" 13861 "fabs %0" 13862 [(set_attr "type" "fmove")]) 13863 13864(define_expand "adddf3" 13865 [(set (match_operand:DF 0 "fp_arith_reg_operand" "") 13866 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "") 13867 (match_operand:DF 2 "fp_arith_reg_operand" "")))] 13868 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 13869{ 13870 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 13871 { 13872 emit_insn (gen_adddf3_i (operands[0], operands[1], operands[2])); 13873 DONE; 13874 } 13875}) 13876 13877(define_insn "*adddf3_media" 13878 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13879 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f") 13880 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 13881 "TARGET_SHMEDIA_FPU" 13882 "fadd.d %1, %2, %0" 13883 [(set_attr "type" "dfparith_media")]) 13884 13885(define_insn "adddf3_i" 13886 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13887 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0") 13888 (match_operand:DF 2 "fp_arith_reg_operand" "f"))) 13889 (clobber (reg:SI FPSCR_STAT_REG)) 13890 (use (reg:SI FPSCR_MODES_REG))] 13891 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 13892 "fadd %2,%0" 13893 [(set_attr "type" "dfp_arith") 13894 (set_attr "fp_mode" "double")]) 13895 13896(define_expand "subdf3" 13897 [(set (match_operand:DF 0 "fp_arith_reg_operand" "") 13898 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "") 13899 (match_operand:DF 2 "fp_arith_reg_operand" "")))] 13900 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 13901{ 13902 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 13903 { 13904 emit_insn (gen_subdf3_i (operands[0], operands[1], operands[2])); 13905 DONE; 13906 } 13907}) 13908 13909(define_insn "*subdf3_media" 13910 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13911 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f") 13912 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 13913 "TARGET_SHMEDIA_FPU" 13914 "fsub.d %1, %2, %0" 13915 [(set_attr "type" "dfparith_media")]) 13916 13917(define_insn "subdf3_i" 13918 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13919 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0") 13920 (match_operand:DF 2 "fp_arith_reg_operand" "f"))) 13921 (clobber (reg:SI FPSCR_STAT_REG)) 13922 (use (reg:SI FPSCR_MODES_REG))] 13923 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 13924 "fsub %2,%0" 13925 [(set_attr "type" "dfp_arith") 13926 (set_attr "fp_mode" "double")]) 13927 13928(define_expand "muldf3" 13929 [(set (match_operand:DF 0 "fp_arith_reg_operand" "") 13930 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "") 13931 (match_operand:DF 2 "fp_arith_reg_operand" "")))] 13932 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 13933{ 13934 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 13935 { 13936 emit_insn (gen_muldf3_i (operands[0], operands[1], operands[2])); 13937 DONE; 13938 } 13939}) 13940 13941(define_insn "*muldf3_media" 13942 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13943 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f") 13944 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 13945 "TARGET_SHMEDIA_FPU" 13946 "fmul.d %1, %2, %0" 13947 [(set_attr "type" "dfmul_media")]) 13948 13949(define_insn "muldf3_i" 13950 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13951 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0") 13952 (match_operand:DF 2 "fp_arith_reg_operand" "f"))) 13953 (clobber (reg:SI FPSCR_STAT_REG)) 13954 (use (reg:SI FPSCR_MODES_REG))] 13955 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 13956 "fmul %2,%0" 13957 [(set_attr "type" "dfp_mul") 13958 (set_attr "fp_mode" "double")]) 13959 13960(define_expand "divdf3" 13961 [(set (match_operand:DF 0 "fp_arith_reg_operand" "") 13962 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "") 13963 (match_operand:DF 2 "fp_arith_reg_operand" "")))] 13964 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 13965{ 13966 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 13967 { 13968 emit_insn (gen_divdf3_i (operands[0], operands[1], operands[2])); 13969 DONE; 13970 } 13971}) 13972 13973(define_insn "*divdf3_media" 13974 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13975 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f") 13976 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 13977 "TARGET_SHMEDIA_FPU" 13978 "fdiv.d %1, %2, %0" 13979 [(set_attr "type" "dfdiv_media")]) 13980 13981(define_insn "divdf3_i" 13982 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13983 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0") 13984 (match_operand:DF 2 "fp_arith_reg_operand" "f"))) 13985 (clobber (reg:SI FPSCR_STAT_REG)) 13986 (use (reg:SI FPSCR_MODES_REG))] 13987 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 13988 "fdiv %2,%0" 13989 [(set_attr "type" "dfdiv") 13990 (set_attr "fp_mode" "double")]) 13991 13992(define_insn "floatdidf2" 13993 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13994 (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))] 13995 "TARGET_SHMEDIA_FPU" 13996 "float.qd %1, %0" 13997 [(set_attr "type" "dfpconv_media")]) 13998 13999(define_expand "floatsidf2" 14000 [(set (match_operand:DF 0 "fp_arith_reg_operand" "") 14001 (float:DF (match_operand:SI 1 "fpul_operand" "")))] 14002 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 14003{ 14004 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 14005 { 14006 emit_insn (gen_floatsidf2_i (operands[0], operands[1])); 14007 DONE; 14008 } 14009}) 14010 14011(define_insn "*floatsidf2_media" 14012 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 14013 (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))] 14014 "TARGET_SHMEDIA_FPU" 14015 "float.ld %1, %0" 14016 [(set_attr "type" "dfpconv_media")]) 14017 14018(define_insn "floatsidf2_i" 14019 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 14020 (float:DF (match_operand:SI 1 "fpul_operand" "y"))) 14021 (clobber (reg:SI FPSCR_STAT_REG)) 14022 (use (reg:SI FPSCR_MODES_REG))] 14023 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 14024 "float %1,%0" 14025 [(set_attr "type" "dfp_conv") 14026 (set_attr "fp_mode" "double")]) 14027 14028(define_insn "fix_truncdfdi2" 14029 [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f") 14030 (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))] 14031 "TARGET_SHMEDIA_FPU" 14032 "ftrc.dq %1, %0" 14033 [(set_attr "type" "dfpconv_media")]) 14034 14035(define_expand "fix_truncdfsi2" 14036 [(set (match_operand:SI 0 "fpul_operand" "") 14037 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))] 14038 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 14039{ 14040 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 14041 { 14042 emit_insn (gen_fix_truncdfsi2_i (operands[0], operands[1])); 14043 DONE; 14044 } 14045}) 14046 14047(define_insn "*fix_truncdfsi2_media" 14048 [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f") 14049 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))] 14050 "TARGET_SHMEDIA_FPU" 14051 "ftrc.dl %1, %0" 14052 [(set_attr "type" "dfpconv_media")]) 14053 14054(define_insn "fix_truncdfsi2_i" 14055 [(set (match_operand:SI 0 "fpul_operand" "=y") 14056 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f"))) 14057 (clobber (reg:SI FPSCR_STAT_REG)) 14058 (use (reg:SI FPSCR_MODES_REG))] 14059 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 14060 "ftrc %1,%0" 14061 [(set_attr "type" "dfp_conv") 14062 (set_attr "dfp_comp" "no") 14063 (set_attr "fp_mode" "double")]) 14064 14065(define_insn "cmpgtdf_t" 14066 [(set (reg:SI T_REG) 14067 (gt:SI (match_operand:DF 0 "fp_arith_reg_operand" "f") 14068 (match_operand:DF 1 "fp_arith_reg_operand" "f"))) 14069 (clobber (reg:SI FPSCR_STAT_REG)) 14070 (use (reg:SI FPSCR_MODES_REG))] 14071 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 14072 "fcmp/gt %1,%0" 14073 [(set_attr "type" "dfp_cmp") 14074 (set_attr "fp_mode" "double")]) 14075 14076(define_insn "cmpeqdf_t" 14077 [(set (reg:SI T_REG) 14078 (eq:SI (match_operand:DF 0 "fp_arith_reg_operand" "f") 14079 (match_operand:DF 1 "fp_arith_reg_operand" "f"))) 14080 (clobber (reg:SI FPSCR_STAT_REG)) 14081 (use (reg:SI FPSCR_MODES_REG))] 14082 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 14083 "fcmp/eq %1,%0" 14084 [(set_attr "type" "dfp_cmp") 14085 (set_attr "fp_mode" "double")]) 14086 14087(define_insn "*ieee_ccmpeqdf_t" 14088 [(set (reg:SI T_REG) 14089 (ior:SI (reg:SI T_REG) 14090 (eq:SI (match_operand:DF 0 "fp_arith_reg_operand" "f") 14091 (match_operand:DF 1 "fp_arith_reg_operand" "f")))) 14092 (clobber (reg:SI FPSCR_STAT_REG)) 14093 (use (reg:SI FPSCR_MODES_REG))] 14094 "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)" 14095{ 14096 return output_ieee_ccmpeq (insn, operands); 14097} 14098 [(set_attr "length" "4") 14099 (set_attr "fp_mode" "double")]) 14100 14101(define_insn "cmpeqdf_media" 14102 [(set (match_operand:SI 0 "register_operand" "=r") 14103 (eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f") 14104 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 14105 "TARGET_SHMEDIA_FPU" 14106 "fcmpeq.d %1,%2,%0" 14107 [(set_attr "type" "fcmp_media")]) 14108 14109(define_insn "cmpgtdf_media" 14110 [(set (match_operand:SI 0 "register_operand" "=r") 14111 (gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f") 14112 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 14113 "TARGET_SHMEDIA_FPU" 14114 "fcmpgt.d %1,%2,%0" 14115 [(set_attr "type" "fcmp_media")]) 14116 14117(define_insn "cmpgedf_media" 14118 [(set (match_operand:SI 0 "register_operand" "=r") 14119 (ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f") 14120 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 14121 "TARGET_SHMEDIA_FPU" 14122 "fcmpge.d %1,%2,%0" 14123 [(set_attr "type" "fcmp_media")]) 14124 14125(define_insn "cmpundf_media" 14126 [(set (match_operand:SI 0 "register_operand" "=r") 14127 (unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f") 14128 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 14129 "TARGET_SHMEDIA_FPU" 14130 "fcmpun.d %1,%2,%0" 14131 [(set_attr "type" "fcmp_media")]) 14132 14133(define_expand "cbranchdf4" 14134 [(set (pc) 14135 (if_then_else (match_operator 0 "sh_float_comparison_operator" 14136 [(match_operand:DF 1 "arith_operand" "") 14137 (match_operand:DF 2 "arith_operand" "")]) 14138 (match_operand 3 "" "") 14139 (pc)))] 14140 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 14141{ 14142 if (TARGET_SHMEDIA) 14143 emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2], 14144 operands[3])); 14145 else 14146 sh_emit_compare_and_branch (operands, DFmode); 14147 DONE; 14148}) 14149 14150(define_expand "negdf2" 14151 [(set (match_operand:DF 0 "fp_arith_reg_operand") 14152 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand")))] 14153 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU") 14154 14155(define_insn "*negdf2_media" 14156 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 14157 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))] 14158 "TARGET_SHMEDIA_FPU" 14159 "fneg.d %1, %0" 14160 [(set_attr "type" "fmove_media")]) 14161 14162(define_insn "*negdf2_i" 14163 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 14164 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))] 14165 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 14166 "fneg %0" 14167 [(set_attr "type" "fmove")]) 14168 14169(define_expand "sqrtdf2" 14170 [(set (match_operand:DF 0 "fp_arith_reg_operand") 14171 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand")))] 14172 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 14173{ 14174 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 14175 { 14176 emit_insn (gen_sqrtdf2_i (operands[0], operands[1])); 14177 DONE; 14178 } 14179}) 14180 14181(define_insn "*sqrtdf2_media" 14182 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 14183 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))] 14184 "TARGET_SHMEDIA_FPU" 14185 "fsqrt.d %1, %0" 14186 [(set_attr "type" "dfdiv_media")]) 14187 14188(define_insn "sqrtdf2_i" 14189 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 14190 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0"))) 14191 (clobber (reg:SI FPSCR_STAT_REG)) 14192 (use (reg:SI FPSCR_MODES_REG))] 14193 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 14194 "fsqrt %0" 14195 [(set_attr "type" "dfdiv") 14196 (set_attr "fp_mode" "double")]) 14197 14198(define_expand "absdf2" 14199 [(set (match_operand:DF 0 "fp_arith_reg_operand") 14200 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand")))] 14201 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU") 14202 14203(define_insn "*absdf2_media" 14204 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 14205 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))] 14206 "TARGET_SHMEDIA_FPU" 14207 "fabs.d %1, %0" 14208 [(set_attr "type" "fmove_media")]) 14209 14210(define_insn "*absdf2_i" 14211 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 14212 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))] 14213 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 14214 "fabs %0" 14215 [(set_attr "type" "fmove")]) 14216 14217(define_expand "extendsfdf2" 14218 [(set (match_operand:DF 0 "fp_arith_reg_operand" "") 14219 (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))] 14220 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 14221{ 14222 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 14223 { 14224 emit_insn (gen_extendsfdf2_i4 (operands[0], operands[1])); 14225 DONE; 14226 } 14227}) 14228 14229(define_insn "*extendsfdf2_media" 14230 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 14231 (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 14232 "TARGET_SHMEDIA_FPU" 14233 "fcnv.sd %1, %0" 14234 [(set_attr "type" "dfpconv_media")]) 14235 14236(define_insn "extendsfdf2_i4" 14237 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 14238 (float_extend:DF (match_operand:SF 1 "fpul_operand" "y"))) 14239 (clobber (reg:SI FPSCR_STAT_REG)) 14240 (use (reg:SI FPSCR_MODES_REG))] 14241 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 14242 "fcnvsd %1,%0" 14243 [(set_attr "type" "fp") 14244 (set_attr "fp_mode" "double")]) 14245 14246(define_expand "truncdfsf2" 14247 [(set (match_operand:SF 0 "fpul_operand" "") 14248 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))] 14249 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 14250{ 14251 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 14252 { 14253 emit_insn (gen_truncdfsf2_i4 (operands[0], operands[1])); 14254 DONE; 14255 } 14256}) 14257 14258(define_insn "*truncdfsf2_media" 14259 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 14260 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))] 14261 "TARGET_SHMEDIA_FPU" 14262 "fcnv.ds %1, %0" 14263 [(set_attr "type" "dfpconv_media")]) 14264 14265(define_insn "truncdfsf2_i4" 14266 [(set (match_operand:SF 0 "fpul_operand" "=y") 14267 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f"))) 14268 (clobber (reg:SI FPSCR_STAT_REG)) 14269 (use (reg:SI FPSCR_MODES_REG))] 14270 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 14271 "fcnvds %1,%0" 14272 [(set_attr "type" "fp") 14273 (set_attr "fp_mode" "double")]) 14274 14275;; ------------------------------------------------------------------------- 14276;; Bit field extract patterns. 14277;; ------------------------------------------------------------------------- 14278 14279;; These give better code for packed bitfields, because they allow 14280;; auto-increment addresses to be generated. 14281 14282(define_expand "insv" 14283 [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "") 14284 (match_operand:SI 1 "immediate_operand" "") 14285 (match_operand:SI 2 "immediate_operand" "")) 14286 (match_operand:SI 3 "general_operand" ""))] 14287 "TARGET_SH1 && TARGET_BIG_ENDIAN" 14288{ 14289 rtx addr_target, orig_address, shift_reg, qi_val; 14290 HOST_WIDE_INT bitsize, size, v = 0; 14291 rtx x = operands[3]; 14292 14293 if (TARGET_SH2A && TARGET_BITOPS 14294 && (satisfies_constraint_Sbw (operands[0]) 14295 || satisfies_constraint_Sbv (operands[0])) 14296 && satisfies_constraint_M (operands[1]) 14297 && satisfies_constraint_K03 (operands[2])) 14298 { 14299 if (satisfies_constraint_N (operands[3])) 14300 { 14301 emit_insn (gen_bclr_m2a (operands[0], operands[2])); 14302 DONE; 14303 } 14304 else if (satisfies_constraint_M (operands[3])) 14305 { 14306 emit_insn (gen_bset_m2a (operands[0], operands[2])); 14307 DONE; 14308 } 14309 else if ((REG_P (operands[3]) && REGNO (operands[3]) == T_REG) 14310 && satisfies_constraint_M (operands[1])) 14311 { 14312 emit_insn (gen_bst_m2a (operands[0], operands[2])); 14313 DONE; 14314 } 14315 else if (REG_P (operands[3]) 14316 && satisfies_constraint_M (operands[1])) 14317 { 14318 emit_insn (gen_bldsi_reg (operands[3], const0_rtx)); 14319 emit_insn (gen_bst_m2a (operands[0], operands[2])); 14320 DONE; 14321 } 14322 } 14323 /* ??? expmed doesn't care for non-register predicates. */ 14324 if (! memory_operand (operands[0], VOIDmode) 14325 || ! immediate_operand (operands[1], VOIDmode) 14326 || ! immediate_operand (operands[2], VOIDmode) 14327 || ! general_operand (x, VOIDmode)) 14328 FAIL; 14329 /* If this isn't a 16 / 24 / 32 bit field, or if 14330 it doesn't start on a byte boundary, then fail. */ 14331 bitsize = INTVAL (operands[1]); 14332 if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0 14333 || (INTVAL (operands[2]) % 8) != 0) 14334 FAIL; 14335 14336 size = bitsize / 8; 14337 orig_address = XEXP (operands[0], 0); 14338 shift_reg = gen_reg_rtx (SImode); 14339 if (CONST_INT_P (x)) 14340 { 14341 v = INTVAL (x); 14342 qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode))); 14343 } 14344 else 14345 { 14346 emit_insn (gen_movsi (shift_reg, operands[3])); 14347 qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3); 14348 } 14349 addr_target = copy_addr_to_reg (plus_constant (Pmode, 14350 orig_address, size - 1)); 14351 14352 operands[0] = replace_equiv_address (operands[0], addr_target); 14353 emit_insn (gen_movqi (operands[0], qi_val)); 14354 14355 while (size -= 1) 14356 { 14357 if (CONST_INT_P (x)) 14358 qi_val 14359 = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode))); 14360 else 14361 { 14362 emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8))); 14363 qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3); 14364 } 14365 emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx)); 14366 emit_insn (gen_movqi (operands[0], qi_val)); 14367 } 14368 14369 DONE; 14370}) 14371 14372(define_insn "movua" 14373 [(set (match_operand:SI 0 "register_operand" "=z") 14374 (unspec:SI [(match_operand:BLK 1 "unaligned_load_operand" "Sua>")] 14375 UNSPEC_MOVUA))] 14376 "TARGET_SH4A" 14377 "movua.l %1,%0" 14378 [(set_attr "type" "movua")]) 14379 14380;; We shouldn't need this, but cse replaces increments with references 14381;; to other regs before flow has a chance to create post_inc 14382;; addressing modes, and only postreload's cse_move2add brings the 14383;; increments back to a usable form. 14384(define_peephole2 14385 [(set (match_operand:SI 0 "register_operand" "") 14386 (sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" "")) 14387 (const_int 32) (const_int 0))) 14388 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))] 14389 "TARGET_SH4A && REGNO (operands[0]) != REGNO (operands[1])" 14390 [(set (match_operand:SI 0 "register_operand" "") 14391 (sign_extract:SI (mem:SI (post_inc:SI 14392 (match_operand:SI 1 "register_operand" ""))) 14393 (const_int 32) (const_int 0)))] 14394 "") 14395 14396(define_expand "extv" 14397 [(set (match_operand:SI 0 "register_operand" "") 14398 (sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "") 14399 (match_operand 2 "const_int_operand" "") 14400 (match_operand 3 "const_int_operand" "")))] 14401 "TARGET_SH4A || TARGET_SH2A" 14402{ 14403 if (TARGET_SH2A && TARGET_BITOPS 14404 && (satisfies_constraint_Sbw (operands[1]) 14405 || satisfies_constraint_Sbv (operands[1])) 14406 && satisfies_constraint_M (operands[2]) 14407 && satisfies_constraint_K03 (operands[3])) 14408 { 14409 emit_insn (gen_bldsign_m2a (operands[1], operands[3])); 14410 if (REGNO (operands[0]) != T_REG) 14411 emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG))); 14412 DONE; 14413 } 14414 if (TARGET_SH4A 14415 && INTVAL (operands[2]) == 32 14416 && INTVAL (operands[3]) == 0 14417 && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32) 14418 { 14419 rtx src = adjust_address (operands[1], BLKmode, 0); 14420 set_mem_size (src, 4); 14421 emit_insn (gen_movua (operands[0], src)); 14422 DONE; 14423 } 14424 14425 FAIL; 14426}) 14427 14428(define_expand "extzv" 14429 [(set (match_operand:SI 0 "register_operand" "") 14430 (zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "") 14431 (match_operand 2 "const_int_operand" "") 14432 (match_operand 3 "const_int_operand" "")))] 14433 "TARGET_SH4A || TARGET_SH2A" 14434{ 14435 if (TARGET_SH2A && TARGET_BITOPS 14436 && (satisfies_constraint_Sbw (operands[1]) 14437 || satisfies_constraint_Sbv (operands[1])) 14438 && satisfies_constraint_M (operands[2]) 14439 && satisfies_constraint_K03 (operands[3])) 14440 { 14441 emit_insn (gen_bld_m2a (operands[1], operands[3])); 14442 if (REGNO (operands[0]) != T_REG) 14443 emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG))); 14444 DONE; 14445 } 14446 if (TARGET_SH4A 14447 && INTVAL (operands[2]) == 32 14448 && INTVAL (operands[3]) == 0 14449 && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32) 14450 { 14451 rtx src = adjust_address (operands[1], BLKmode, 0); 14452 set_mem_size (src, 4); 14453 emit_insn (gen_movua (operands[0], src)); 14454 DONE; 14455 } 14456 14457 FAIL; 14458}) 14459 14460;; ------------------------------------------------------------------------- 14461;; Extract negated single bit and zero extend it. 14462;; Generally we don't care about the exact xor const_int value, as long 14463;; as it contains the extracted bit. For simplicity, the pattern variations 14464;; that convert everything into the primary '*neg_zero_extract_0' pattern use 14465;; a xor const_int -1 value. 14466 14467(define_insn_and_split "*neg_zero_extract_0" 14468 [(set (reg:SI T_REG) 14469 (zero_extract:SI (xor:QIHISI (match_operand:QIHISI 0 "arith_reg_operand") 14470 (match_operand 1 "const_int_operand")) 14471 (const_int 1) 14472 (match_operand 2 "const_int_operand")))] 14473 "TARGET_SH1 && can_create_pseudo_p () 14474 && INTVAL (operands[1]) & (1LL << INTVAL (operands[2]))" 14475 "#" 14476 "&& 1" 14477 [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 2)) 14478 (const_int 0)))] 14479{ 14480 if (INTVAL (operands[2]) == 31 && <MODE>mode == SImode) 14481 { 14482 /* Use cmp/pz to extract bit 31 into the T bit. */ 14483 emit_insn (gen_cmpgesi_t (operands[0], const0_rtx)); 14484 DONE; 14485 } 14486 14487 operands[2] = GEN_INT ((1 << INTVAL (operands[2]))); 14488 if (GET_MODE (operands[0]) != SImode) 14489 operands[0] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0); 14490}) 14491 14492(define_insn_and_split "*neg_zero_extract_1" 14493 [(set (reg:SI T_REG) 14494 (and:SI (not:SI (match_operand:SI 0 "arith_reg_operand")) 14495 (const_int 1)))] 14496 "TARGET_SH1" 14497 "#" 14498 "&& 1" 14499 [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1)) 14500 (const_int 1) (const_int 0)))]) 14501 14502;; x & (1 << n) == 0: 0x00000000 + 1 = 1 14503;; x & (1 << n) != 0: 0xFFFFFFFF + 1 = 0 14504(define_insn_and_split "*neg_zero_extract_2" 14505 [(set (reg:SI T_REG) 14506 (plus:SI (sign_extract:SI (match_operand:QIHISI 0 "arith_reg_operand") 14507 (const_int 1) 14508 (match_operand 1 "const_int_operand")) 14509 (const_int 1)))] 14510 "TARGET_SH1 && can_create_pseudo_p ()" 14511 "#" 14512 "&& 1" 14513 [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1)) 14514 (const_int 1) (match_dup 1)))]) 14515 14516;; (signed)x >> 31 + 1 = (x >= 0) ^ 1 14517(define_insn_and_split "*neg_zero_extract_3" 14518 [(set (reg:SI T_REG) 14519 (plus:SI (ashiftrt:SI (match_operand:SI 0 "arith_reg_operand") 14520 (const_int 31)) 14521 (const_int 1)))] 14522 "TARGET_SH1 && can_create_pseudo_p ()" 14523 "#" 14524 "&& 1" 14525 [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1)) 14526 (const_int 1) (const_int 31)))]) 14527 14528;; This is required for some bit patterns of DImode subregs. 14529;; It looks like combine gets confused by the DImode right shift and fails 14530;; to simplify things. 14531(define_insn_and_split "*neg_zero_extract_4" 14532 [(set (reg:SI T_REG) 14533 (and:SI (and:SI 14534 (lshiftrt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand") 14535 (match_operand 1 "const_int_operand")) 14536 (match_operand 2 "const_int_operand")) 14537 (not:SI (ashift:SI (match_operand:SI 3 "arith_reg_operand") 14538 (match_operand 4 "const_int_operand")))) 14539 (const_int 1)))] 14540 "TARGET_SH1 && can_create_pseudo_p () 14541 && INTVAL (operands[4]) > 0 14542 && INTVAL (operands[1]) & (1LL << INTVAL (operands[2]))" 14543 "#" 14544 "&& 1" 14545 [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1)) 14546 (const_int 1) (match_dup 2)))]) 14547 14548(define_insn_and_split "*neg_zero_extract_5" 14549 [(set (reg:SI T_REG) 14550 (and:SI (not:SI (subreg:SI 14551 (lshiftrt:DI (match_operand:DI 0 "arith_reg_operand") 14552 (match_operand 1 "const_int_operand")) 14553 0)) 14554 (const_int 1)))] 14555 "TARGET_SH1 && TARGET_LITTLE_ENDIAN && can_create_pseudo_p () 14556 && INTVAL (operands[1]) < 32" 14557 "#" 14558 "&& 1" 14559 [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1)) 14560 (const_int 1) (match_dup 1)))] 14561{ 14562 operands[0] = gen_lowpart (SImode, operands[0]); 14563}) 14564 14565(define_insn_and_split "*neg_zero_extract_6" 14566 [(set (reg:SI T_REG) 14567 (and:SI (not:SI (subreg:SI 14568 (lshiftrt:DI (match_operand:DI 0 "arith_reg_operand") 14569 (match_operand 1 "const_int_operand")) 14570 4)) 14571 (const_int 1)))] 14572 "TARGET_SH1 && TARGET_BIG_ENDIAN && can_create_pseudo_p () 14573 && INTVAL (operands[1]) < 32" 14574 "#" 14575 "&& 1" 14576 [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1)) 14577 (const_int 1) (match_dup 1)))] 14578{ 14579 operands[0] = gen_lowpart (SImode, operands[0]); 14580}) 14581 14582;; ------------------------------------------------------------------------- 14583;; Extract single bit and zero extend it. 14584;; All patterns store the result bit in the T bit, although that is not 14585;; always possible to do with a single insn and a nott must be appended. 14586;; The trailing nott will be optimized away in most cases. E.g. if the 14587;; extracted bit is fed into a branch condition, the condition can be 14588;; inverted and the nott will be eliminated. 14589;; FIXME: In cases where the trailing nott can't be eliminated, try to 14590;; convert it into a (not, tst) sequence, which could be better on non-SH2A. 14591 14592;; On SH2A the 'bld<mode>_reg' insn will be used if the bit position fits. 14593(define_insn_and_split "*zero_extract_0" 14594 [(set (reg:SI T_REG) 14595 (zero_extract:SI (match_operand:QIHISI 0 "arith_reg_operand") 14596 (const_int 1) 14597 (match_operand 1 "const_int_operand")))] 14598 "TARGET_SH1 && can_create_pseudo_p () 14599 && !(TARGET_SH2A && satisfies_constraint_K03 (operands[1]))" 14600 "#" 14601 "&& 1" 14602 [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 1)) 14603 (const_int 0))) 14604 (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))] 14605{ 14606 if (INTVAL (operands[1]) == 31 && <MODE>mode == SImode) 14607 { 14608 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[0])); 14609 DONE; 14610 } 14611 14612 operands[1] = GEN_INT (1 << INTVAL (operands[1])); 14613 if (GET_MODE (operands[0]) != SImode) 14614 operands[0] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0); 14615}) 14616 14617;; This is required for some bit patterns of DImode subregs. 14618;; It looks like combine gets confused by the DImode right shift and fails 14619;; to simplify things. 14620(define_insn_and_split "*zero_extract_1" 14621 [(set (reg:SI T_REG) 14622 (subreg:SI (zero_extract:DI (match_operand:SI 0 "arith_reg_operand") 14623 (const_int 1) 14624 (match_operand 1 "const_int_operand")) 14625 0))] 14626 "TARGET_SH1 && TARGET_LITTLE_ENDIAN && can_create_pseudo_p () 14627 && INTVAL (operands[1]) < 32" 14628 "#" 14629 "&& 1" 14630 [(set (reg:SI T_REG) 14631 (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)))]) 14632 14633(define_insn_and_split "*zero_extract_2" 14634 [(set (reg:SI T_REG) 14635 (subreg:SI (zero_extract:DI (match_operand:SI 0 "arith_reg_operand") 14636 (const_int 1) 14637 (match_operand 1 "const_int_operand")) 14638 4))] 14639 "TARGET_SH1 && TARGET_BIG_ENDIAN && can_create_pseudo_p () 14640 && INTVAL (operands[1]) < 32" 14641 "#" 14642 "&& 1" 14643 [(set (reg:SI T_REG) 14644 (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)))]) 14645 14646(define_insn_and_split "*zero_extract_3" 14647 [(set (match_operand:SI 0 "arith_reg_dest") 14648 (and:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand") 14649 (match_operand 2 "const_int_operand")) 14650 (match_operand 3 "const_int_operand"))) 14651 (clobber (reg:SI T_REG))] 14652 "TARGET_SH1 && can_create_pseudo_p () 14653 && exact_log2 (INTVAL (operands[3])) >= 0" 14654 "#" 14655 "&& 1" 14656 [(const_int 0)] 14657{ 14658 int rshift = INTVAL (operands[2]); 14659 int lshift = exact_log2 (INTVAL (operands[3])); 14660 14661 rtx tmp = gen_reg_rtx (SImode); 14662 emit_insn (gen_rtx_PARALLEL (VOIDmode, 14663 gen_rtvec (2, 14664 gen_rtx_SET (tmp, 14665 gen_rtx_ZERO_EXTRACT (SImode, operands[1], const1_rtx, 14666 GEN_INT (rshift + lshift))), 14667 gen_rtx_CLOBBER (VOIDmode, get_t_reg_rtx ())))); 14668 emit_insn (gen_ashlsi3 (operands[0], tmp, GEN_INT (lshift))); 14669}) 14670 14671;; ------------------------------------------------------------------------- 14672;; SH2A instructions for bitwise operations. 14673;; FIXME: Convert multiple instruction insns to insn_and_split. 14674;; FIXME: Use iterators to fold at least and,xor,or insn variations. 14675 14676;; Clear a bit in a memory location. 14677(define_insn "bclr_m2a" 14678 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv") 14679 (and:QI 14680 (not:QI (ashift:QI (const_int 1) 14681 (match_operand:QI 1 "const_int_operand" "K03,K03"))) 14682 (match_dup 0)))] 14683 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 14684 "@ 14685 bclr.b %1,%0 14686 bclr.b %1,@(0,%t0)" 14687[(set_attr "length" "4,4")]) 14688 14689(define_insn "bclrmem_m2a" 14690 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv") 14691 (and:QI (match_dup 0) 14692 (match_operand:QI 1 "const_int_operand" "Psz,Psz")))] 14693 "TARGET_SH2A && satisfies_constraint_Psz (operands[1]) && TARGET_BITOPS" 14694 "@ 14695 bclr.b %W1,%0 14696 bclr.b %W1,@(0,%t0)" 14697 [(set_attr "length" "4,4")]) 14698 14699;; Set a bit in a memory location. 14700(define_insn "bset_m2a" 14701 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv") 14702 (ior:QI 14703 (ashift:QI (const_int 1) 14704 (match_operand:QI 1 "const_int_operand" "K03,K03")) 14705 (match_dup 0)))] 14706 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 14707 "@ 14708 bset.b %1,%0 14709 bset.b %1,@(0,%t0)" 14710 [(set_attr "length" "4,4")]) 14711 14712(define_insn "bsetmem_m2a" 14713 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv") 14714 (ior:QI (match_dup 0) 14715 (match_operand:QI 1 "const_int_operand" "Pso,Pso")))] 14716 "TARGET_SH2A && satisfies_constraint_Pso (operands[1]) && TARGET_BITOPS" 14717 "@ 14718 bset.b %V1,%0 14719 bset.b %V1,@(0,%t0)" 14720 [(set_attr "length" "4,4")]) 14721 14722;;; Transfer the contents of the T bit to a specified bit of memory. 14723(define_insn "bst_m2a" 14724 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,m") 14725 (if_then_else (eq (reg:SI T_REG) (const_int 0)) 14726 (and:QI 14727 (not:QI (ashift:QI (const_int 1) 14728 (match_operand:QI 1 "const_int_operand" "K03,K03"))) 14729 (match_dup 0)) 14730 (ior:QI 14731 (ashift:QI (const_int 1) (match_dup 1)) 14732 (match_dup 0))))] 14733 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 14734 "@ 14735 bst.b %1,%0 14736 bst.b %1,@(0,%t0)" 14737 [(set_attr "length" "4")]) 14738 14739;; Store a specified bit of memory in the T bit. 14740(define_insn "bld_m2a" 14741 [(set (reg:SI T_REG) 14742 (zero_extract:SI 14743 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,Sbv") 14744 (const_int 1) 14745 (match_operand 1 "const_int_operand" "K03,K03")))] 14746 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 14747 "@ 14748 bld.b %1,%0 14749 bld.b %1,@(0,%t0)" 14750 [(set_attr "length" "4,4")]) 14751 14752;; Store a specified bit of memory in the T bit. 14753(define_insn "bldsign_m2a" 14754 [(set (reg:SI T_REG) 14755 (sign_extract:SI 14756 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m") 14757 (const_int 1) 14758 (match_operand 1 "const_int_operand" "K03,K03")))] 14759 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 14760 "@ 14761 bld.b %1,%0 14762 bld.b %1,@(0,%t0)" 14763 [(set_attr "length" "4,4")]) 14764 14765;; Store a specified bit of the LSB 8 bits of a register in the T bit. 14766(define_insn "bld<mode>_reg" 14767 [(set (reg:SI T_REG) 14768 (zero_extract:SI (match_operand:QIHISI 0 "arith_reg_operand" "r") 14769 (const_int 1) 14770 (match_operand 1 "const_int_operand" "K03")))] 14771 "TARGET_SH2A && satisfies_constraint_K03 (operands[1])" 14772 "bld %1,%0") 14773 14774;; Take logical and of a specified bit of memory with the T bit and 14775;; store its result in the T bit. 14776(define_insn "band_m2a" 14777 [(set (reg:SI T_REG) 14778 (and:SI (reg:SI T_REG) 14779 (zero_extract:SI 14780 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m") 14781 (const_int 1) 14782 (match_operand 1 "const_int_operand" "K03,K03"))))] 14783 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 14784 "@ 14785 band.b %1,%0 14786 band.b %1,@(0,%t0)" 14787 [(set_attr "length" "4,4")]) 14788 14789(define_insn "bandreg_m2a" 14790 [(set (match_operand:SI 0 "register_operand" "=r,r") 14791 (and:SI (zero_extract:SI 14792 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv") 14793 (const_int 1) 14794 (match_operand 2 "const_int_operand" "K03,K03")) 14795 (match_operand:SI 3 "register_operand" "r,r")))] 14796 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])" 14797{ 14798 static const char* alt[] = 14799 { 14800 "band.b %2,%1" "\n" 14801 " movt %0", 14802 14803 "band.b %2,@(0,%t1)" "\n" 14804 " movt %0" 14805 }; 14806 return alt[which_alternative]; 14807} 14808 [(set_attr "length" "6,6")]) 14809 14810;; Take logical or of a specified bit of memory with the T bit and 14811;; store its result in the T bit. 14812(define_insn "bor_m2a" 14813 [(set (reg:SI T_REG) 14814 (ior:SI (reg:SI T_REG) 14815 (zero_extract:SI 14816 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m") 14817 (const_int 1) 14818 (match_operand 1 "const_int_operand" "K03,K03"))))] 14819 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 14820 "@ 14821 bor.b %1,%0 14822 bor.b %1,@(0,%t0)" 14823 [(set_attr "length" "4,4")]) 14824 14825(define_insn "borreg_m2a" 14826 [(set (match_operand:SI 0 "register_operand" "=r,r") 14827 (ior:SI (zero_extract:SI 14828 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv") 14829 (const_int 1) 14830 (match_operand 2 "const_int_operand" "K03,K03")) 14831 (match_operand:SI 3 "register_operand" "=r,r")))] 14832 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])" 14833{ 14834 static const char* alt[] = 14835 { 14836 "bor.b %2,%1" "\n" 14837 " movt %0", 14838 14839 "bor.b %2,@(0,%t1)" "\n" 14840 " movt %0" 14841 }; 14842 return alt[which_alternative]; 14843} 14844 [(set_attr "length" "6,6")]) 14845 14846;; Take exclusive or of a specified bit of memory with the T bit and 14847;; store its result in the T bit. 14848(define_insn "bxor_m2a" 14849 [(set (reg:SI T_REG) 14850 (xor:SI (reg:SI T_REG) 14851 (zero_extract:SI 14852 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m") 14853 (const_int 1) 14854 (match_operand 1 "const_int_operand" "K03,K03"))))] 14855 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 14856 "@ 14857 bxor.b %1,%0 14858 bxor.b %1,@(0,%t0)" 14859 [(set_attr "length" "4,4")]) 14860 14861(define_insn "bxorreg_m2a" 14862 [(set (match_operand:SI 0 "register_operand" "=r,r") 14863 (xor:SI (zero_extract:SI 14864 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv") 14865 (const_int 1) 14866 (match_operand 2 "const_int_operand" "K03,K03")) 14867 (match_operand:SI 3 "register_operand" "=r,r")))] 14868 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])" 14869{ 14870 static const char* alt[] = 14871 { 14872 "bxor.b %2,%1" "\n" 14873 " movt %0", 14874 14875 "bxor.b %2,@(0,%t1)" "\n" 14876 " movt %0" 14877 }; 14878 return alt[which_alternative]; 14879} 14880 [(set_attr "length" "6,6")]) 14881 14882;; ------------------------------------------------------------------------- 14883;; Peepholes 14884;; ------------------------------------------------------------------------- 14885;; This matches cases where the bit in a memory location is set. 14886(define_peephole2 14887 [(set (match_operand:SI 0 "register_operand") 14888 (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand"))) 14889 (set (match_dup 0) 14890 (ior:SI (match_dup 0) 14891 (match_operand:SI 2 "const_int_operand"))) 14892 (set (match_dup 1) 14893 (match_operand 3 "arith_reg_operand"))] 14894 "TARGET_SH2A && TARGET_BITOPS 14895 && satisfies_constraint_Pso (operands[2]) 14896 && REGNO (operands[0]) == REGNO (operands[3])" 14897 [(set (match_dup 1) 14898 (ior:QI (match_dup 1) (match_dup 2)))] 14899 "") 14900 14901;; This matches cases where the bit in a memory location is cleared. 14902(define_peephole2 14903 [(set (match_operand:SI 0 "register_operand") 14904 (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand"))) 14905 (set (match_dup 0) 14906 (and:SI (match_dup 0) 14907 (match_operand:SI 2 "const_int_operand"))) 14908 (set (match_dup 1) 14909 (match_operand 3 "arith_reg_operand"))] 14910 "TARGET_SH2A && TARGET_BITOPS 14911 && satisfies_constraint_Psz (operands[2]) 14912 && REGNO (operands[0]) == REGNO (operands[3])" 14913 [(set (match_dup 1) 14914 (and:QI (match_dup 1) (match_dup 2)))] 14915 "") 14916 14917;; This matches cases where a stack pointer increment at the start of the 14918;; epilogue combines with a stack slot read loading the return value. 14919(define_peephole 14920 [(set (match_operand:SI 0 "arith_reg_operand" "") 14921 (mem:SI (match_operand:SI 1 "arith_reg_operand" ""))) 14922 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))] 14923 "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])" 14924 "mov.l @%1+,%0") 14925 14926;; See the comment on the dt combiner pattern above. 14927(define_peephole 14928 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 14929 (plus:SI (match_dup 0) 14930 (const_int -1))) 14931 (set (reg:SI T_REG) 14932 (eq:SI (match_dup 0) (const_int 0)))] 14933 "TARGET_SH2" 14934 "dt %0") 14935 14936;; The following peepholes fold load sequences for which reload was not 14937;; able to generate a displacement addressing move insn. 14938;; This can happen when reload has to transform a move insn 14939;; without displacement into one with displacement. Or when reload can't 14940;; fit a displacement into the insn's constraints. In the latter case, the 14941;; load destination reg remains at r0, which reload compensates by inserting 14942;; another mov insn. 14943 14944;; Fold sequence: 14945;; mov #54,r0 14946;; mov.{b,w} @(r0,r15),r0 14947;; mov r0,r3 14948;; into: 14949;; mov.{b,w} @(54,r15),r3 14950;; 14951(define_peephole2 14952 [(set (match_operand:SI 0 "arith_reg_dest" "") 14953 (match_operand:SI 1 "const_int_operand" "")) 14954 (set (match_operand:SI 2 "arith_reg_dest" "") 14955 (sign_extend:SI 14956 (mem:QI (plus:SI (match_dup 0) 14957 (match_operand:SI 3 "arith_reg_operand" ""))))) 14958 (set (match_operand:QI 4 "arith_reg_dest" "") 14959 (match_operand:QI 5 "arith_reg_operand" ""))] 14960 "TARGET_SH2A 14961 && sh_legitimate_index_p (QImode, operands[1], true, true) 14962 && REGNO (operands[2]) == REGNO (operands[5]) 14963 && peep2_reg_dead_p (3, operands[5])" 14964 [(set (match_dup 4) (mem:QI (plus:SI (match_dup 3) (match_dup 1))))] 14965 "") 14966 14967(define_peephole2 14968 [(set (match_operand:SI 0 "arith_reg_dest" "") 14969 (match_operand:SI 1 "const_int_operand" "")) 14970 (set (match_operand:SI 2 "arith_reg_dest" "") 14971 (sign_extend:SI 14972 (mem:HI (plus:SI (match_dup 0) 14973 (match_operand:SI 3 "arith_reg_operand" ""))))) 14974 (set (match_operand:HI 4 "arith_reg_dest" "") 14975 (match_operand:HI 5 "arith_reg_operand" ""))] 14976 "TARGET_SH2A 14977 && sh_legitimate_index_p (HImode, operands[1], true, true) 14978 && REGNO (operands[2]) == REGNO (operands[5]) 14979 && peep2_reg_dead_p (3, operands[5])" 14980 [(set (match_dup 4) (mem:HI (plus:SI (match_dup 3) (match_dup 1))))] 14981 "") 14982 14983;; Fold sequence: 14984;; mov #54,r0 14985;; mov.{b,w} @(r0,r15),r1 14986;; into: 14987;; mov.{b,w} @(54,r15),r1 14988;; 14989(define_peephole2 14990 [(set (match_operand:SI 0 "arith_reg_dest" "") 14991 (match_operand:SI 1 "const_int_operand" "")) 14992 (set (match_operand:SI 2 "arith_reg_dest" "") 14993 (sign_extend:SI 14994 (mem:QI (plus:SI (match_dup 0) 14995 (match_operand:SI 3 "arith_reg_operand" "")))))] 14996 "TARGET_SH2A 14997 && sh_legitimate_index_p (QImode, operands[1], true, true) 14998 && (peep2_reg_dead_p (2, operands[0]) 14999 || REGNO (operands[0]) == REGNO (operands[2]))" 15000 [(set (match_dup 2) 15001 (sign_extend:SI (mem:QI (plus:SI (match_dup 3) (match_dup 1)))))] 15002 "") 15003 15004(define_peephole2 15005 [(set (match_operand:SI 0 "arith_reg_dest" "") 15006 (match_operand:SI 1 "const_int_operand" "")) 15007 (set (match_operand:SI 2 "arith_reg_dest" "") 15008 (sign_extend:SI 15009 (mem:HI (plus:SI (match_dup 0) 15010 (match_operand:SI 3 "arith_reg_operand" "")))))] 15011 "TARGET_SH2A 15012 && sh_legitimate_index_p (HImode, operands[1], true, true) 15013 && (peep2_reg_dead_p (2, operands[0]) 15014 || REGNO (operands[0]) == REGNO (operands[2]))" 15015 [(set (match_dup 2) 15016 (sign_extend:SI (mem:HI (plus:SI (match_dup 3) (match_dup 1)))))] 15017 "") 15018 15019;; Fold sequence: 15020;; mov.{b,w} @(r0,r15),r0 15021;; mov r0,r3 15022;; into: 15023;; mov.{b,w} @(r0,r15),r3 15024;; 15025;; This can happen when initially a displacement address is picked, where 15026;; the destination reg is fixed to r0, and then the address is transformed 15027;; into 'r0 + reg'. 15028(define_peephole2 15029 [(set (match_operand:SI 0 "arith_reg_dest" "") 15030 (sign_extend:SI 15031 (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "") 15032 (match_operand:SI 2 "arith_reg_operand" ""))))) 15033 (set (match_operand:QI 3 "arith_reg_dest" "") 15034 (match_operand:QI 4 "arith_reg_operand" ""))] 15035 "TARGET_SH1 15036 && REGNO (operands[0]) == REGNO (operands[4]) 15037 && peep2_reg_dead_p (2, operands[0])" 15038 [(set (match_dup 3) 15039 (mem:QI (plus:SI (match_dup 1) (match_dup 2))))] 15040 "") 15041 15042(define_peephole2 15043 [(set (match_operand:SI 0 "arith_reg_dest" "") 15044 (sign_extend:SI 15045 (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "") 15046 (match_operand:SI 2 "arith_reg_operand" ""))))) 15047 (set (match_operand:HI 3 "arith_reg_dest" "") 15048 (match_operand:HI 4 "arith_reg_operand" ""))] 15049 "TARGET_SH1 15050 && REGNO (operands[0]) == REGNO (operands[4]) 15051 && peep2_reg_dead_p (2, operands[0])" 15052 [(set (match_dup 3) 15053 (mem:HI (plus:SI (match_dup 1) (match_dup 2))))] 15054 "") 15055 15056;; extu.bw a,b 15057;; mov b,c -> extu.bw a,c 15058(define_peephole2 15059 [(set (match_operand:SI 0 "arith_reg_dest") 15060 (zero_extend:SI (match_operand:QIHI 1 "arith_reg_operand"))) 15061 (set (match_operand:SI 2 "arith_reg_dest") 15062 (match_dup 0))] 15063 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])" 15064 [(set (match_dup 2) (zero_extend:SI (match_dup 1)))]) 15065 15066;; mov r0,r1 15067;; extu.bw r1,r1 -> extu.bw r0,r1 15068(define_peephole2 15069 [(set (match_operand 0 "arith_reg_dest") 15070 (match_operand 1 "arith_reg_operand")) 15071 (set (match_operand:SI 2 "arith_reg_dest") 15072 (zero_extend:SI (match_operand:QIHI 3 "arith_reg_operand")))] 15073 "TARGET_SH1 15074 && REGNO (operands[0]) == REGNO (operands[3]) 15075 && (REGNO (operands[0]) == REGNO (operands[2]) 15076 || peep2_reg_dead_p (2, operands[0]))" 15077 [(set (match_dup 2) (zero_extend:SI (match_dup 1)))] 15078{ 15079 operands[1] = gen_rtx_REG (<MODE>mode, REGNO (operands[1])); 15080}) 15081 15082;; mov a,b 15083;; mov b,a -> < nop > 15084(define_peephole2 15085 [(set (match_operand 0 "register_operand") 15086 (match_operand 1 "register_operand")) 15087 (set (match_operand 2 "register_operand") 15088 (match_operand 3 "register_operand"))] 15089 "TARGET_SH1 15090 && REGNO (operands[0]) == REGNO (operands[3]) 15091 && REGNO (operands[1]) == REGNO (operands[2]) 15092 && peep2_reg_dead_p (2, operands[3])" 15093 [(const_int 0)]) 15094 15095;; mov #3,r4 15096;; and r4,r1 -> mov r1,r0 15097;; mov r1,r0 and #3,r0 15098(define_code_iterator ANDIORXOR [and ior xor]) 15099(define_peephole2 15100 [(set (match_operand:SI 0 "register_operand") 15101 (match_operand:SI 1 "const_logical_operand")) 15102 (set (match_operand:SI 2) (ANDIORXOR:SI (match_dup 2) (match_dup 0))) 15103 (set (reg:SI R0_REG) (match_dup 2))] 15104 "TARGET_SH1 15105 && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[2])" 15106 [(set (reg:SI R0_REG) (match_dup 2)) 15107 (set (reg:SI R0_REG) (ANDIORXOR:SI (reg:SI R0_REG) (match_dup 1)))]) 15108 15109;; ... r2,r0 ... r2,r0 15110;; or r1,r0 -> or r0,r1 15111;; mov r0,r1 15112;; (r0 dead) 15113(define_code_iterator ANDIORXORPLUS [and ior xor plus]) 15114(define_peephole2 15115 [(set (match_operand:SI 0 "arith_reg_dest") 15116 (ANDIORXORPLUS:SI (match_dup 0) (match_operand:SI 1 "arith_reg_dest"))) 15117 (set (match_dup 1) (match_dup 0))] 15118 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])" 15119 [(set (match_dup 1) (ANDIORXORPLUS:SI (match_dup 1) (match_dup 0)))]) 15120 15121;; mov r12,r0 15122;; add #-48,r0 -> add #-48,r12 15123;; mov.l r0,@(4,r10) mov.l r12,@(4,r10) 15124;; (r12 dead) 15125(define_peephole2 15126 [(set (match_operand:SI 0 "arith_reg_dest") 15127 (match_operand:SI 1 "arith_reg_dest")) 15128 (set (match_dup 0) (plus:SI (match_dup 0) 15129 (match_operand:SI 2 "const_int_operand"))) 15130 (set (match_operand:SI 3 "general_movdst_operand") (match_dup 0))] 15131 "TARGET_SH1 15132 && peep2_reg_dead_p (2, operands[1]) && peep2_reg_dead_p (3, operands[0])" 15133 [(const_int 0)] 15134{ 15135 emit_insn (gen_addsi3 (operands[1], operands[1], operands[2])); 15136 sh_peephole_emit_move_insn (operands[3], operands[1]); 15137}) 15138 15139;; mov.l @(r0,r9),r1 15140;; mov r1,r0 -> mov @(r0,r9),r0 15141(define_peephole2 15142 [(set (match_operand:SI 0 "arith_reg_dest") 15143 (match_operand:SI 1 "general_movsrc_operand")) 15144 (set (match_operand:SI 2 "arith_reg_dest") 15145 (match_dup 0))] 15146 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])" 15147 [(const_int 0)] 15148{ 15149 sh_peephole_emit_move_insn (operands[2], operands[1]); 15150}) 15151 15152(define_peephole2 15153 [(set (match_operand:QIHI 0 "register_operand") 15154 (match_operand:QIHI 1 "movsrc_no_disp_mem_operand")) 15155 (set (match_operand:QIHI 2 "register_operand") 15156 (match_dup 0))] 15157 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])" 15158 [(const_int 0)] 15159{ 15160 sh_peephole_emit_move_insn (operands[2], operands[1]); 15161}) 15162 15163(define_peephole2 15164 [(set (match_operand:SI 0 "arith_reg_dest") 15165 (sign_extend:SI (match_operand:QIHI 1 "movsrc_no_disp_mem_operand"))) 15166 (set (match_operand:SI 2 "arith_reg_dest") 15167 (match_dup 0))] 15168 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])" 15169 [(const_int 0)] 15170{ 15171 sh_check_add_incdec_notes (emit_insn (gen_extend<mode>si2 (operands[2], 15172 sh_remove_overlapping_post_inc (operands[2], operands[1])))); 15173}) 15174 15175;; mov.w @(18,r1),r0 (r0 = HImode) 15176;; mov r0,r1 (r0 = r1 = HImode) mov.w @(18,r1),r0 15177;; ... ..,r13 (r13 = SImode) -> ... ..,r13 15178;; tst r1,r13 tst r0,r13 15179(define_peephole2 15180 [(set (match_operand 0 "arith_reg_dest") 15181 (match_operand 1 "arith_reg_dest")) 15182 (set (match_operand:SI 2 "arith_reg_dest") 15183 (match_operand:SI 3)) 15184 (set (reg:SI T_REG) 15185 (eq:SI (and:SI (match_operand:SI 4 "arith_reg_operand") 15186 (match_operand:SI 5 "arith_reg_operand")) 15187 (const_int 0)))] 15188 "TARGET_SH1 15189 && peep2_reg_dead_p (3, operands[0]) 15190 && !reg_overlap_mentioned_p (operands[0], operands[3]) 15191 && (REGNO (operands[0]) == REGNO (operands[4]) 15192 || REGNO (operands[0]) == REGNO (operands[5])) 15193 && (REGNO (operands[2]) == REGNO (operands[4]) 15194 || REGNO (operands[2]) == REGNO (operands[5]))" 15195 [(const_int 0)] 15196{ 15197 if (REGNO (operands[1]) == REGNO (operands[2])) 15198 operands[2] = gen_rtx_REG (SImode, REGNO (operands[0])); 15199 15200 // We don't know what the new set insn will be in detail. Just make sure 15201 // that it still can be recognized and the constraints are satisfied. 15202 rtx_insn* i = emit_insn (gen_rtx_SET (operands[2], 15203 sh_remove_overlapping_post_inc (operands[2], operands[3]))); 15204 15205 recog_data_d prev_recog_data = recog_data; 15206 bool i_invalid = insn_invalid_p (i, false); 15207 recog_data = prev_recog_data; 15208 15209 if (i_invalid) 15210 FAIL; 15211 15212 sh_check_add_incdec_notes (i); 15213 15214 emit_insn (gen_tstsi_t (operands[2], 15215 gen_rtx_REG (SImode, (REGNO (operands[1]))))); 15216}) 15217 15218;; mov.w @(18,r1),r0 (r0 = HImode) 15219;; ... ..,r13 (r13 = SImode) mov.w @(18,r1),r0 15220;; mov r0,r1 (r0 = r1 = HImode) -> ... ..,r13 15221;; tst r1,r13 tst r0,r13 15222(define_peephole2 15223 [(set (match_operand:SI 2 "arith_reg_dest") 15224 (match_operand:SI 3)) 15225 (set (match_operand 0 "arith_reg_dest") 15226 (match_operand 1 "arith_reg_operand")) 15227 (set (reg:SI T_REG) 15228 (eq:SI (and:SI (match_operand:SI 4 "arith_reg_operand") 15229 (match_operand:SI 5 "arith_reg_operand")) 15230 (const_int 0)))] 15231 "TARGET_SH1 15232 && peep2_reg_dead_p (3, operands[0]) 15233 && !reg_overlap_mentioned_p (operands[0], operands[3]) 15234 && (REGNO (operands[0]) == REGNO (operands[4]) 15235 || REGNO (operands[0]) == REGNO (operands[5])) 15236 && (REGNO (operands[2]) == REGNO (operands[4]) 15237 || REGNO (operands[2]) == REGNO (operands[5]))" 15238 [(const_int 0)] 15239{ 15240 // We don't know what the new set insn will be in detail. Just make sure 15241 // that it still can be recognized and the constraints are satisfied. 15242 rtx_insn* i = emit_insn (gen_rtx_SET (operands[2], 15243 sh_remove_overlapping_post_inc (operands[2], operands[3]))); 15244 15245 recog_data_d prev_recog_data = recog_data; 15246 bool i_invalid = insn_invalid_p (i, false); 15247 recog_data = prev_recog_data; 15248 15249 if (i_invalid) 15250 FAIL; 15251 15252 sh_check_add_incdec_notes (i); 15253 15254 emit_insn (gen_tstsi_t (operands[2], 15255 gen_rtx_REG (SImode, (REGNO (operands[1]))))); 15256}) 15257 15258;; This is not a peephole, but it's here because it's actually supposed 15259;; to be one. It tries to convert a sequence such as 15260;; movt r2 -> movt r2 15261;; movt r13 mov r2,r13 15262;; This gives the schduler a bit more freedom to hoist a following 15263;; comparison insn. Moreover, it the reg-reg mov insn is MT group which has 15264;; better chances for parallel execution. 15265;; We can do this with a peephole2 pattern, but then the cprop_hardreg 15266;; pass will revert the change. See also PR 64331. 15267;; Thus do it manually in one of the split passes after register allocation. 15268;; Sometimes the cprop_hardreg pass might also eliminate the reg-reg copy. 15269(define_split 15270 [(set (match_operand:SI 0 "arith_reg_dest") 15271 (match_operand:SI 1 "t_reg_operand"))] 15272 "TARGET_SH1 && reload_completed" 15273 [(set (match_dup 0) (match_dup 1))] 15274{ 15275 rtx t_reg = get_t_reg_rtx (); 15276 15277 for (rtx_insn* i = prev_nonnote_insn_bb (curr_insn); i != NULL; 15278 i = prev_nonnote_insn_bb (i)) 15279 { 15280 if (!INSN_P (i) || DEBUG_INSN_P (i)) 15281 continue; 15282 15283 if (modified_in_p (t_reg, i) || BARRIER_P (i)) 15284 FAIL; 15285 15286 if (sh_is_movt_insn (i)) 15287 { 15288 rtx r = sh_movt_set_dest (i); 15289 if (!modified_between_p (r, i, curr_insn)) 15290 { 15291 operands[1] = r; 15292 break; 15293 } 15294 } 15295 } 15296}) 15297 15298(define_peephole 15299 [(set (match_operand:SI 0 "register_operand" "=r") 15300 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) 15301 (set (mem:SF (match_dup 0)) 15302 (match_operand:SF 2 "general_movsrc_operand" ""))] 15303 "TARGET_SH1 && REGNO (operands[0]) == 0 15304 && ((REG_P (operands[2]) && REGNO (operands[2]) < 16) 15305 || (GET_CODE (operands[2]) == SUBREG 15306 && REGNO (SUBREG_REG (operands[2])) < 16)) 15307 && reg_unused_after (operands[0], insn)" 15308 "mov.l %2,@(%0,%1)") 15309 15310(define_peephole 15311 [(set (match_operand:SI 0 "register_operand" "=r") 15312 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) 15313 (set (match_operand:SF 2 "general_movdst_operand" "") 15314 15315 (mem:SF (match_dup 0)))] 15316 "TARGET_SH1 && REGNO (operands[0]) == 0 15317 && ((REG_P (operands[2]) && REGNO (operands[2]) < 16) 15318 || (GET_CODE (operands[2]) == SUBREG 15319 && REGNO (SUBREG_REG (operands[2])) < 16)) 15320 && reg_unused_after (operands[0], insn)" 15321 "mov.l @(%0,%1),%2") 15322 15323(define_peephole 15324 [(set (match_operand:SI 0 "register_operand" "=r") 15325 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) 15326 (set (mem:SF (match_dup 0)) 15327 (match_operand:SF 2 "general_movsrc_operand" ""))] 15328 "TARGET_SH2E && REGNO (operands[0]) == 0 15329 && ((REG_P (operands[2]) 15330 && FP_OR_XD_REGISTER_P (REGNO (operands[2]))) 15331 || (GET_CODE (operands[2]) == SUBREG 15332 && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2]))))) 15333 && reg_unused_after (operands[0], insn)" 15334 "fmov{.s|} %2,@(%0,%1)") 15335 15336(define_peephole 15337 [(set (match_operand:SI 0 "register_operand" "=r") 15338 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) 15339 (set (match_operand:SF 2 "general_movdst_operand" "") 15340 15341 (mem:SF (match_dup 0)))] 15342 "TARGET_SH2E && REGNO (operands[0]) == 0 15343 && ((REG_P (operands[2]) 15344 && FP_OR_XD_REGISTER_P (REGNO (operands[2]))) 15345 || (GET_CODE (operands[2]) == SUBREG 15346 && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2]))))) 15347 && reg_unused_after (operands[0], insn)" 15348 "fmov{.s|} @(%0,%1),%2") 15349 15350;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF). 15351(define_insn "sp_switch_1" 15352 [(set (reg:SI SP_REG) (unspec_volatile [(match_operand:SI 0 "" "")] 15353 UNSPECV_SP_SWITCH_B))] 15354 "TARGET_SH1" 15355{ 15356 return "mov.l r0,@-r15" "\n" 15357 " mov.l %0,r0" "\n" 15358 " mov.l @r0,r0" "\n" 15359 " mov.l r15,@-r0" "\n" 15360 " mov r0,r15"; 15361} 15362 [(set_attr "length" "10")]) 15363 15364;; Switch back to the original stack for interrupt functions with the 15365;; sp_switch attribute. 15366(define_insn "sp_switch_2" 15367 [(unspec_volatile [(const_int 0)] 15368 UNSPECV_SP_SWITCH_E)] 15369 "TARGET_SH1" 15370{ 15371 return "mov.l @r15,r15" "\n" 15372 " mov.l @r15+,r0"; 15373} 15374 [(set_attr "length" "4")]) 15375 15376;; ------------------------------------------------------------------------- 15377;; Integer vector moves 15378;; ------------------------------------------------------------------------- 15379 15380(define_expand "movv8qi" 15381 [(set (match_operand:V8QI 0 "general_movdst_operand" "") 15382 (match_operand:V8QI 1 "general_movsrc_operand" ""))] 15383 "TARGET_SHMEDIA" 15384{ 15385 prepare_move_operands (operands, V8QImode); 15386}) 15387 15388(define_insn "movv8qi_i" 15389 [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m") 15390 (match_operand:V8QI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))] 15391 "TARGET_SHMEDIA 15392 && (register_operand (operands[0], V8QImode) 15393 || sh_register_operand (operands[1], V8QImode))" 15394 "@ 15395 add %1, r63, %0 15396 movi %1, %0 15397 # 15398 ld%M1.q %m1, %0 15399 st%M0.q %m0, %N1" 15400 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media") 15401 (set_attr "length" "4,4,16,4,4")]) 15402 15403(define_split 15404 [(set (match_operand:V8QI 0 "arith_reg_dest" "") 15405 (subreg:V8QI (const_int 0) 0))] 15406 "TARGET_SHMEDIA" 15407 [(set (match_dup 0) 15408 (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0) 15409 (const_int 0) (const_int 0) (const_int 0) 15410 (const_int 0) (const_int 0)]))]) 15411 15412(define_split 15413 [(set (match_operand 0 "arith_reg_dest" "") 15414 (match_operand 1 "sh_rep_vec" ""))] 15415 "TARGET_SHMEDIA && reload_completed 15416 && GET_MODE (operands[0]) == GET_MODE (operands[1]) 15417 && sh_vector_mode_supported_p (GET_MODE (operands[0])) 15418 && GET_MODE_SIZE (GET_MODE (operands[0])) == 8 15419 && (XVECEXP (operands[1], 0, 0) != const0_rtx 15420 || XVECEXP (operands[1], 0, 1) != const0_rtx) 15421 && (XVECEXP (operands[1], 0, 0) != constm1_rtx 15422 || XVECEXP (operands[1], 0, 1) != constm1_rtx)" 15423 [(set (match_dup 0) (match_dup 1)) 15424 (match_dup 2)] 15425{ 15426 int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1])); 15427 rtx elt1 = XVECEXP (operands[1], 0, 1); 15428 15429 if (unit_size > 2) 15430 operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]); 15431 else 15432 { 15433 if (unit_size < 2) 15434 operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0])); 15435 operands[2] = gen_mperm_w0 (operands[0], operands[0]); 15436 } 15437 operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0])); 15438 operands[1] = XVECEXP (operands[1], 0, 0); 15439 if (unit_size < 2) 15440 { 15441 if (CONST_INT_P (operands[1]) && CONST_INT_P (elt1)) 15442 operands[1] 15443 = GEN_INT (TARGET_LITTLE_ENDIAN 15444 ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8) 15445 : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff)); 15446 else 15447 { 15448 operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0])); 15449 operands[1] 15450 = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1)); 15451 } 15452 } 15453}) 15454 15455(define_split 15456 [(set (match_operand 0 "arith_reg_dest" "") 15457 (match_operand 1 "sh_const_vec" ""))] 15458 "TARGET_SHMEDIA && reload_completed 15459 && GET_MODE (operands[0]) == GET_MODE (operands[1]) 15460 && sh_vector_mode_supported_p (GET_MODE (operands[0]))" 15461 [(set (match_dup 0) (match_dup 1))] 15462{ 15463 rtx v = operands[1]; 15464 machine_mode new_mode 15465 = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0); 15466 15467 operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0])); 15468 operands[1] 15469 = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0); 15470}) 15471 15472(define_expand "movv2hi" 15473 [(set (match_operand:V2HI 0 "general_movdst_operand" "") 15474 (match_operand:V2HI 1 "general_movsrc_operand" ""))] 15475 "TARGET_SHMEDIA" 15476{ 15477 prepare_move_operands (operands, V2HImode); 15478}) 15479 15480(define_insn "movv2hi_i" 15481 [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m") 15482 (match_operand:V2HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))] 15483 "TARGET_SHMEDIA 15484 && (register_operand (operands[0], V2HImode) 15485 || sh_register_operand (operands[1], V2HImode))" 15486 "@ 15487 add.l %1, r63, %0 15488 movi %1, %0 15489 # 15490 ld%M1.l %m1, %0 15491 st%M0.l %m0, %N1" 15492 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media") 15493 (set_attr "length" "4,4,16,4,4") 15494 (set (attr "highpart") 15495 (cond [(match_test "sh_contains_memref_p (insn)") 15496 (const_string "user")] 15497 (const_string "ignore")))]) 15498 15499(define_expand "movv4hi" 15500 [(set (match_operand:V4HI 0 "general_movdst_operand" "") 15501 (match_operand:V4HI 1 "general_movsrc_operand" ""))] 15502 "TARGET_SHMEDIA" 15503{ 15504 prepare_move_operands (operands, V4HImode); 15505}) 15506 15507(define_insn "movv4hi_i" 15508 [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m") 15509 (match_operand:V4HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))] 15510 "TARGET_SHMEDIA 15511 && (register_operand (operands[0], V4HImode) 15512 || sh_register_operand (operands[1], V4HImode))" 15513 "@ 15514 add %1, r63, %0 15515 movi %1, %0 15516 # 15517 ld%M1.q %m1, %0 15518 st%M0.q %m0, %N1" 15519 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media") 15520 (set_attr "length" "4,4,16,4,4") 15521 (set_attr "highpart" "depend")]) 15522 15523(define_expand "movv2si" 15524 [(set (match_operand:V2SI 0 "general_movdst_operand" "") 15525 (match_operand:V2SI 1 "general_movsrc_operand" ""))] 15526 "TARGET_SHMEDIA" 15527{ 15528 prepare_move_operands (operands, V2SImode); 15529}) 15530 15531(define_insn "movv2si_i" 15532 [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m") 15533 (match_operand:V2SI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))] 15534 "TARGET_SHMEDIA 15535 && (register_operand (operands[0], V2SImode) 15536 || sh_register_operand (operands[1], V2SImode))" 15537 "@ 15538 add %1, r63, %0 15539 # 15540 # 15541 ld%M1.q %m1, %0 15542 st%M0.q %m0, %N1" 15543 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media") 15544 (set_attr "length" "4,4,16,4,4") 15545 (set_attr "highpart" "depend")]) 15546 15547;; ------------------------------------------------------------------------- 15548;; Multimedia Intrinsics 15549;; ------------------------------------------------------------------------- 15550 15551(define_insn "absv2si2" 15552 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15553 (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))] 15554 "TARGET_SHMEDIA" 15555 "mabs.l %1, %0" 15556 [(set_attr "type" "mcmp_media") 15557 (set_attr "highpart" "depend")]) 15558 15559(define_insn "absv4hi2" 15560 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15561 (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))] 15562 "TARGET_SHMEDIA" 15563 "mabs.w %1, %0" 15564 [(set_attr "type" "mcmp_media") 15565 (set_attr "highpart" "depend")]) 15566 15567(define_insn "addv2si3" 15568 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15569 (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r") 15570 (match_operand:V2SI 2 "arith_reg_operand" "r")))] 15571 "TARGET_SHMEDIA" 15572 "madd.l %1, %2, %0" 15573 [(set_attr "type" "arith_media") 15574 (set_attr "highpart" "depend")]) 15575 15576(define_insn "addv4hi3" 15577 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15578 (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r") 15579 (match_operand:V4HI 2 "arith_reg_operand" "r")))] 15580 "TARGET_SHMEDIA" 15581 "madd.w %1, %2, %0" 15582 [(set_attr "type" "arith_media") 15583 (set_attr "highpart" "depend")]) 15584 15585(define_insn_and_split "addv2hi3" 15586 [(set (match_operand:V2HI 0 "arith_reg_dest" "=r") 15587 (plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r") 15588 (match_operand:V2HI 2 "extend_reg_operand" "r")))] 15589 "TARGET_SHMEDIA" 15590 "#" 15591 "TARGET_SHMEDIA" 15592 [(const_int 0)] 15593{ 15594 rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0); 15595 rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0); 15596 rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0); 15597 rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0); 15598 rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0); 15599 15600 emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1)); 15601 emit_insn (gen_truncdisi2 (si_dst, di_dst)); 15602 DONE; 15603} 15604 [(set_attr "highpart" "must_split")]) 15605 15606(define_insn "ssaddv2si3" 15607 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15608 (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r") 15609 (match_operand:V2SI 2 "arith_reg_operand" "r")))] 15610 "TARGET_SHMEDIA" 15611 "madds.l %1, %2, %0" 15612 [(set_attr "type" "mcmp_media") 15613 (set_attr "highpart" "depend")]) 15614 15615(define_insn "usaddv8qi3" 15616 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") 15617 (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r") 15618 (match_operand:V8QI 2 "arith_reg_operand" "r")))] 15619 "TARGET_SHMEDIA" 15620 "madds.ub %1, %2, %0" 15621 [(set_attr "type" "mcmp_media") 15622 (set_attr "highpart" "depend")]) 15623 15624(define_insn "ssaddv4hi3" 15625 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15626 (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r") 15627 (match_operand:V4HI 2 "arith_reg_operand" "r")))] 15628 "TARGET_SHMEDIA" 15629 "madds.w %1, %2, %0" 15630 [(set_attr "type" "mcmp_media") 15631 (set_attr "highpart" "depend")]) 15632 15633(define_insn "negcmpeqv8qi" 15634 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") 15635 (neg:V8QI (eq:V8QI 15636 (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ") 15637 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))] 15638 "TARGET_SHMEDIA" 15639 "mcmpeq.b %N1, %N2, %0" 15640 [(set_attr "type" "mcmp_media") 15641 (set_attr "highpart" "depend")]) 15642 15643(define_insn "negcmpeqv2si" 15644 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15645 (neg:V2SI (eq:V2SI 15646 (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ") 15647 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))] 15648 "TARGET_SHMEDIA" 15649 "mcmpeq.l %N1, %N2, %0" 15650 [(set_attr "type" "mcmp_media") 15651 (set_attr "highpart" "depend")]) 15652 15653(define_insn "negcmpeqv4hi" 15654 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15655 (neg:V4HI (eq:V4HI 15656 (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ") 15657 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))] 15658 "TARGET_SHMEDIA" 15659 "mcmpeq.w %N1, %N2, %0" 15660 [(set_attr "type" "mcmp_media") 15661 (set_attr "highpart" "depend")]) 15662 15663(define_insn "negcmpgtuv8qi" 15664 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") 15665 (neg:V8QI (gtu:V8QI 15666 (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ") 15667 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))] 15668 "TARGET_SHMEDIA" 15669 "mcmpgt.ub %N1, %N2, %0" 15670 [(set_attr "type" "mcmp_media") 15671 (set_attr "highpart" "depend")]) 15672 15673(define_insn "negcmpgtv2si" 15674 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15675 (neg:V2SI (gt:V2SI 15676 (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ") 15677 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))] 15678 "TARGET_SHMEDIA" 15679 "mcmpgt.l %N1, %N2, %0" 15680 [(set_attr "type" "mcmp_media") 15681 (set_attr "highpart" "depend")]) 15682 15683(define_insn "negcmpgtv4hi" 15684 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15685 (neg:V4HI (gt:V4HI 15686 (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ") 15687 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))] 15688 "TARGET_SHMEDIA" 15689 "mcmpgt.w %N1, %N2, %0" 15690 [(set_attr "type" "mcmp_media") 15691 (set_attr "highpart" "depend")]) 15692 15693(define_insn "mcmv" 15694 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 15695 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 15696 (match_operand:DI 2 "arith_reg_operand" "r")) 15697 (and:DI (match_operand:DI 3 "arith_reg_operand" "0") 15698 (not:DI (match_dup 2)))))] 15699 "TARGET_SHMEDIA" 15700 "mcmv %N1, %2, %0" 15701 [(set_attr "type" "arith_media") 15702 (set_attr "highpart" "depend")]) 15703 15704(define_insn "mcnvs_lw" 15705 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15706 (vec_concat:V4HI 15707 (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")) 15708 (ss_truncate:V2HI 15709 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))] 15710 "TARGET_SHMEDIA" 15711 "mcnvs.lw %N1, %N2, %0" 15712 [(set_attr "type" "mcmp_media")]) 15713 15714(define_insn "mcnvs_wb" 15715 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") 15716 (vec_concat:V8QI 15717 (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")) 15718 (ss_truncate:V4QI 15719 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))] 15720 "TARGET_SHMEDIA" 15721 "mcnvs.wb %N1, %N2, %0" 15722 [(set_attr "type" "mcmp_media")]) 15723 15724(define_insn "mcnvs_wub" 15725 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") 15726 (vec_concat:V8QI 15727 (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")) 15728 (us_truncate:V4QI 15729 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))] 15730 "TARGET_SHMEDIA" 15731 "mcnvs.wub %N1, %N2, %0" 15732 [(set_attr "type" "mcmp_media")]) 15733 15734(define_insn "mextr_rl" 15735 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 15736 (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 15737 (match_operand:HI 3 "mextr_bit_offset" "i")) 15738 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ") 15739 (match_operand:HI 4 "mextr_bit_offset" "i"))))] 15740 "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64" 15741{ 15742 static char templ[21]; 15743 sprintf (templ, "mextr%d %%N1, %%N2, %%0", 15744 (int) INTVAL (operands[3]) >> 3); 15745 return templ; 15746} 15747 [(set_attr "type" "arith_media")]) 15748 15749(define_insn "*mextr_lr" 15750 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 15751 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 15752 (match_operand:HI 3 "mextr_bit_offset" "i")) 15753 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ") 15754 (match_operand:HI 4 "mextr_bit_offset" "i"))))] 15755 "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64" 15756{ 15757 static char templ[21]; 15758 sprintf (templ, "mextr%d %%N2, %%N1, %%0", 15759 (int) INTVAL (operands[4]) >> 3); 15760 return templ; 15761} 15762 [(set_attr "type" "arith_media")]) 15763 15764; mextrN can be modelled with vec_select / vec_concat, but the selection 15765; vector then varies depending on endianness. 15766(define_expand "mextr1" 15767 [(match_operand:DI 0 "arith_reg_dest" "") 15768 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 15769 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")] 15770 "TARGET_SHMEDIA" 15771{ 15772 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2], 15773 GEN_INT (1 * 8), GEN_INT (7 * 8))); 15774 DONE; 15775}) 15776 15777(define_expand "mextr2" 15778 [(match_operand:DI 0 "arith_reg_dest" "") 15779 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 15780 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")] 15781 "TARGET_SHMEDIA" 15782{ 15783 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2], 15784 GEN_INT (2 * 8), GEN_INT (6 * 8))); 15785 DONE; 15786}) 15787 15788(define_expand "mextr3" 15789 [(match_operand:DI 0 "arith_reg_dest" "") 15790 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 15791 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")] 15792 "TARGET_SHMEDIA" 15793{ 15794 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2], 15795 GEN_INT (3 * 8), GEN_INT (5 * 8))); 15796 DONE; 15797}) 15798 15799(define_expand "mextr4" 15800 [(match_operand:DI 0 "arith_reg_dest" "") 15801 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 15802 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")] 15803 "TARGET_SHMEDIA" 15804{ 15805 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2], 15806 GEN_INT (4 * 8), GEN_INT (4 * 8))); 15807 DONE; 15808}) 15809 15810(define_expand "mextr5" 15811 [(match_operand:DI 0 "arith_reg_dest" "") 15812 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 15813 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")] 15814 "TARGET_SHMEDIA" 15815{ 15816 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2], 15817 GEN_INT (5 * 8), GEN_INT (3 * 8))); 15818 DONE; 15819}) 15820 15821(define_expand "mextr6" 15822 [(match_operand:DI 0 "arith_reg_dest" "") 15823 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 15824 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")] 15825 "TARGET_SHMEDIA" 15826{ 15827 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2], 15828 GEN_INT (6 * 8), GEN_INT (2 * 8))); 15829 DONE; 15830}) 15831 15832(define_expand "mextr7" 15833 [(match_operand:DI 0 "arith_reg_dest" "") 15834 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 15835 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")] 15836 "TARGET_SHMEDIA" 15837{ 15838 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2], 15839 GEN_INT (7 * 8), GEN_INT (1 * 8))); 15840 DONE; 15841}) 15842 15843(define_expand "mmacfx_wl" 15844 [(match_operand:V2SI 0 "arith_reg_dest" "") 15845 (match_operand:V2HI 1 "extend_reg_operand" "") 15846 (match_operand:V2HI 2 "extend_reg_operand" "") 15847 (match_operand:V2SI 3 "arith_reg_operand" "")] 15848 "TARGET_SHMEDIA" 15849{ 15850 emit_insn (gen_mmacfx_wl_i (operands[0], operands[3], 15851 operands[1], operands[2])); 15852 DONE; 15853}) 15854 15855;; This could be highpart ignore if it only had inputs 2 or 3, but input 1 15856;; is depend 15857(define_insn "mmacfx_wl_i" 15858 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15859 (ss_plus:V2SI 15860 (match_operand:V2SI 1 "arith_reg_operand" "0") 15861 (ss_truncate:V2SI 15862 (ashift:V2DI 15863 (sign_extend:V2DI 15864 (mult:V2SI 15865 (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r")) 15866 (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r")))) 15867 (const_int 1)))))] 15868 "TARGET_SHMEDIA" 15869 "mmacfx.wl %2, %3, %0" 15870 [(set_attr "type" "mac_media") 15871 (set_attr "highpart" "depend")]) 15872 15873(define_expand "mmacnfx_wl" 15874 [(match_operand:V2SI 0 "arith_reg_dest" "") 15875 (match_operand:V2HI 1 "extend_reg_operand" "") 15876 (match_operand:V2HI 2 "extend_reg_operand" "") 15877 (match_operand:V2SI 3 "arith_reg_operand" "")] 15878 "TARGET_SHMEDIA" 15879{ 15880 emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3], 15881 operands[1], operands[2])); 15882 DONE; 15883}) 15884 15885(define_insn "mmacnfx_wl_i" 15886 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15887 (ss_minus:V2SI 15888 (match_operand:V2SI 1 "arith_reg_operand" "0") 15889 (ss_truncate:V2SI 15890 (ashift:V2DI 15891 (sign_extend:V2DI 15892 (mult:V2SI 15893 (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r")) 15894 (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r")))) 15895 (const_int 1)))))] 15896 "TARGET_SHMEDIA" 15897 "mmacnfx.wl %2, %3, %0" 15898 [(set_attr "type" "mac_media") 15899 (set_attr "highpart" "depend")]) 15900 15901(define_insn "mulv2si3" 15902 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15903 (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r") 15904 (match_operand:V2SI 2 "arith_reg_operand" "r")))] 15905 "TARGET_SHMEDIA" 15906 "mmul.l %1, %2, %0" 15907 [(set_attr "type" "d2mpy_media") 15908 (set_attr "highpart" "depend")]) 15909 15910(define_insn "mulv4hi3" 15911 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15912 (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r") 15913 (match_operand:V4HI 2 "arith_reg_operand" "r")))] 15914 "TARGET_SHMEDIA" 15915 "mmul.w %1, %2, %0" 15916 [(set_attr "type" "dmpy_media") 15917 (set_attr "highpart" "depend")]) 15918 15919(define_insn "mmulfx_l" 15920 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15921 (ss_truncate:V2SI 15922 (ashiftrt:V2DI 15923 (mult:V2DI 15924 (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r")) 15925 (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r"))) 15926 (const_int 31))))] 15927 "TARGET_SHMEDIA" 15928 "mmulfx.l %1, %2, %0" 15929 [(set_attr "type" "d2mpy_media") 15930 (set_attr "highpart" "depend")]) 15931 15932(define_insn "mmulfx_w" 15933 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15934 (ss_truncate:V4HI 15935 (ashiftrt:V4SI 15936 (mult:V4SI 15937 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r")) 15938 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r"))) 15939 (const_int 15))))] 15940 "TARGET_SHMEDIA" 15941 "mmulfx.w %1, %2, %0" 15942 [(set_attr "type" "dmpy_media") 15943 (set_attr "highpart" "depend")]) 15944 15945(define_insn "mmulfxrp_w" 15946 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15947 (ss_truncate:V4HI 15948 (ashiftrt:V4SI 15949 (plus:V4SI 15950 (mult:V4SI 15951 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r")) 15952 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r"))) 15953 (const_int 16384)) 15954 (const_int 15))))] 15955 "TARGET_SHMEDIA" 15956 "mmulfxrp.w %1, %2, %0" 15957 [(set_attr "type" "dmpy_media") 15958 (set_attr "highpart" "depend")]) 15959 15960 15961(define_expand "mmulhi_wl" 15962 [(match_operand:V2SI 0 "arith_reg_dest" "") 15963 (match_operand:V4HI 1 "arith_reg_operand" "") 15964 (match_operand:V4HI 2 "arith_reg_operand" "")] 15965 "TARGET_SHMEDIA" 15966{ 15967 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl) 15968 (operands[0], operands[1], operands[2])); 15969 DONE; 15970}) 15971 15972(define_expand "mmullo_wl" 15973 [(match_operand:V2SI 0 "arith_reg_dest" "") 15974 (match_operand:V4HI 1 "arith_reg_operand" "") 15975 (match_operand:V4HI 2 "arith_reg_operand" "")] 15976 "TARGET_SHMEDIA" 15977{ 15978 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl) 15979 (operands[0], operands[1], operands[2])); 15980 DONE; 15981}) 15982 15983(define_insn "mmul23_wl" 15984 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15985 (vec_select:V2SI 15986 (mult:V4SI 15987 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r")) 15988 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r"))) 15989 (parallel [(const_int 2) (const_int 3)])))] 15990 "TARGET_SHMEDIA" 15991{ 15992 return (TARGET_LITTLE_ENDIAN 15993 ? "mmulhi.wl %1, %2, %0" 15994 : "mmullo.wl %1, %2, %0"); 15995} 15996 [(set_attr "type" "dmpy_media") 15997 (set (attr "highpart") 15998 (cond [(eq_attr "endian" "big") (const_string "ignore")] 15999 (const_string "user")))]) 16000 16001(define_insn "mmul01_wl" 16002 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 16003 (vec_select:V2SI 16004 (mult:V4SI 16005 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r")) 16006 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r"))) 16007 (parallel [(const_int 0) (const_int 1)])))] 16008 "TARGET_SHMEDIA" 16009{ 16010 return (TARGET_LITTLE_ENDIAN 16011 ? "mmullo.wl %1, %2, %0" 16012 : "mmulhi.wl %1, %2, %0"); 16013} 16014 [(set_attr "type" "dmpy_media") 16015 (set (attr "highpart") 16016 (cond [(eq_attr "endian" "little") (const_string "ignore")] 16017 (const_string "user")))]) 16018 16019 16020(define_expand "mmulsum_wq" 16021 [(match_operand:DI 0 "arith_reg_dest" "") 16022 (match_operand:V4HI 1 "arith_reg_operand" "") 16023 (match_operand:V4HI 2 "arith_reg_operand" "") 16024 (match_operand:DI 3 "arith_reg_operand" "")] 16025 "TARGET_SHMEDIA" 16026{ 16027 emit_insn (gen_mmulsum_wq_i (operands[0], operands[3], 16028 operands[1], operands[2])); 16029 DONE; 16030}) 16031 16032(define_insn "mmulsum_wq_i" 16033 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16034 (plus:DI (match_operand:DI 1 "arith_reg_operand" "0") 16035 (plus:DI 16036 (plus:DI 16037 (vec_select:DI 16038 (mult:V4DI 16039 (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r")) 16040 (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r"))) 16041 (parallel [(const_int 0)])) 16042 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2)) 16043 (sign_extend:V4DI (match_dup 3))) 16044 (parallel [(const_int 1)]))) 16045 (plus:DI 16046 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2)) 16047 (sign_extend:V4DI (match_dup 3))) 16048 (parallel [(const_int 2)])) 16049 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2)) 16050 (sign_extend:V4DI (match_dup 3))) 16051 (parallel [(const_int 3)]))))))] 16052 "TARGET_SHMEDIA" 16053 "mmulsum.wq %2, %3, %0" 16054 [(set_attr "type" "mac_media")]) 16055 16056(define_expand "mperm_w" 16057 [(match_operand:V4HI 0 "arith_reg_dest" "=r") 16058 (match_operand:V4HI 1 "arith_reg_operand" "r") 16059 (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")] 16060 "TARGET_SHMEDIA" 16061{ 16062 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big) 16063 (operands[0], operands[1], operands[2])); 16064 DONE; 16065}) 16066 16067; This use of vec_select isn't exactly correct according to rtl.texi 16068; (because not constant), but it seems a straightforward extension. 16069(define_insn "mperm_w_little" 16070 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 16071 (vec_select:V4HI 16072 (match_operand:V4HI 1 "arith_reg_operand" "r") 16073 (parallel 16074 [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ") 16075 (const_int 2) (const_int 0)) 16076 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2)) 16077 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4)) 16078 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))] 16079 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN" 16080 "mperm.w %1, %N2, %0" 16081 [(set_attr "type" "arith_media")]) 16082 16083(define_insn "mperm_w_big" 16084 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 16085 (vec_select:V4HI 16086 (match_operand:V4HI 1 "arith_reg_operand" "r") 16087 (parallel 16088 [(zero_extract:QI (not:QI (match_operand:QI 2 16089 "extend_reg_or_0_operand" "rZ")) 16090 (const_int 2) (const_int 0)) 16091 (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2)) 16092 (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4)) 16093 (zero_extract:QI (not:QI (match_dup 2)) 16094 (const_int 2) (const_int 6))])))] 16095 "TARGET_SHMEDIA && TARGET_BIG_ENDIAN" 16096 "mperm.w %1, %N2, %0" 16097 [(set_attr "type" "arith_media")]) 16098 16099(define_insn "mperm_w0" 16100 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 16101 (vec_duplicate:V4HI (truncate:HI (match_operand 1 16102 "trunc_hi_operand" "r"))))] 16103 "TARGET_SHMEDIA" 16104 "mperm.w %1, r63, %0" 16105 [(set_attr "type" "arith_media") 16106 (set_attr "highpart" "ignore")]) 16107 16108(define_expand "msad_ubq" 16109 [(match_operand:DI 0 "arith_reg_dest" "") 16110 (match_operand:V8QI 1 "arith_reg_or_0_operand" "") 16111 (match_operand:V8QI 2 "arith_reg_or_0_operand" "") 16112 (match_operand:DI 3 "arith_reg_operand" "")] 16113 "TARGET_SHMEDIA" 16114{ 16115 emit_insn (gen_msad_ubq_i (operands[0], operands[3], 16116 operands[1], operands[2])); 16117 DONE; 16118}) 16119 16120(define_insn "msad_ubq_i" 16121 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16122 (plus:DI 16123 (plus:DI 16124 (plus:DI 16125 (plus:DI 16126 (match_operand:DI 1 "arith_reg_operand" "0") 16127 (abs:DI (vec_select:DI 16128 (minus:V8DI 16129 (zero_extend:V8DI 16130 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")) 16131 (zero_extend:V8DI 16132 (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ"))) 16133 (parallel [(const_int 0)])))) 16134 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) 16135 (zero_extend:V8DI (match_dup 3))) 16136 (parallel [(const_int 1)])))) 16137 (plus:DI 16138 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) 16139 (zero_extend:V8DI (match_dup 3))) 16140 (parallel [(const_int 2)]))) 16141 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) 16142 (zero_extend:V8DI (match_dup 3))) 16143 (parallel [(const_int 3)]))))) 16144 (plus:DI 16145 (plus:DI 16146 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) 16147 (zero_extend:V8DI (match_dup 3))) 16148 (parallel [(const_int 4)]))) 16149 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) 16150 (zero_extend:V8DI (match_dup 3))) 16151 (parallel [(const_int 5)])))) 16152 (plus:DI 16153 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) 16154 (zero_extend:V8DI (match_dup 3))) 16155 (parallel [(const_int 6)]))) 16156 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) 16157 (zero_extend:V8DI (match_dup 3))) 16158 (parallel [(const_int 7)])))))))] 16159 "TARGET_SHMEDIA" 16160 "msad.ubq %N2, %N3, %0" 16161 [(set_attr "type" "mac_media")]) 16162 16163(define_insn "mshalds_l" 16164 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 16165 (ss_truncate:V2SI 16166 (ashift:V2DI 16167 (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r")) 16168 (and:DI (match_operand:DI 2 "arith_reg_operand" "r") 16169 (const_int 31)))))] 16170 "TARGET_SHMEDIA" 16171 "mshalds.l %1, %2, %0" 16172 [(set_attr "type" "mcmp_media") 16173 (set_attr "highpart" "depend")]) 16174 16175(define_insn "mshalds_w" 16176 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 16177 (ss_truncate:V4HI 16178 (ashift:V4SI 16179 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r")) 16180 (and:DI (match_operand:DI 2 "arith_reg_operand" "r") 16181 (const_int 15)))))] 16182 "TARGET_SHMEDIA" 16183 "mshalds.w %1, %2, %0" 16184 [(set_attr "type" "mcmp_media") 16185 (set_attr "highpart" "depend")]) 16186 16187(define_insn "ashrv2si3" 16188 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 16189 (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r") 16190 (match_operand:DI 2 "arith_reg_operand" "r")))] 16191 "TARGET_SHMEDIA" 16192 "mshard.l %1, %2, %0" 16193 [(set_attr "type" "arith_media") 16194 (set_attr "highpart" "depend")]) 16195 16196(define_insn "ashrv4hi3" 16197 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 16198 (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r") 16199 (match_operand:DI 2 "arith_reg_operand" "r")))] 16200 "TARGET_SHMEDIA" 16201 "mshard.w %1, %2, %0" 16202 [(set_attr "type" "arith_media") 16203 (set_attr "highpart" "depend")]) 16204 16205(define_insn "mshards_q" 16206 [(set (match_operand:HI 0 "arith_reg_dest" "=r") 16207 (ss_truncate:HI 16208 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r") 16209 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))] 16210 "TARGET_SHMEDIA" 16211 "mshards.q %1, %N2, %0" 16212 [(set_attr "type" "mcmp_media")]) 16213 16214(define_expand "mshfhi_b" 16215 [(match_operand:V8QI 0 "arith_reg_dest" "") 16216 (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ") 16217 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")] 16218 "TARGET_SHMEDIA" 16219{ 16220 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b) 16221 (operands[0], operands[1], operands[2])); 16222 DONE; 16223}) 16224 16225(define_expand "mshflo_b" 16226 [(match_operand:V8QI 0 "arith_reg_dest" "") 16227 (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ") 16228 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")] 16229 "TARGET_SHMEDIA" 16230{ 16231 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b) 16232 (operands[0], operands[1], operands[2])); 16233 DONE; 16234}) 16235 16236(define_insn "mshf4_b" 16237 [(set 16238 (match_operand:V8QI 0 "arith_reg_dest" "=r") 16239 (vec_select:V8QI 16240 (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ") 16241 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")) 16242 (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13) 16243 (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))] 16244 "TARGET_SHMEDIA" 16245{ 16246 return (TARGET_LITTLE_ENDIAN 16247 ? "mshfhi.b %N1, %N2, %0" 16248 : "mshflo.b %N1, %N2, %0"); 16249} 16250 [(set_attr "type" "arith_media") 16251 (set (attr "highpart") 16252 (cond [(eq_attr "endian" "big") (const_string "ignore")] 16253 (const_string "user")))]) 16254 16255(define_insn "mshf0_b" 16256 [(set 16257 (match_operand:V8QI 0 "arith_reg_dest" "=r") 16258 (vec_select:V8QI 16259 (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ") 16260 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")) 16261 (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9) 16262 (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))] 16263 "TARGET_SHMEDIA" 16264{ 16265 return (TARGET_LITTLE_ENDIAN 16266 ? "mshflo.b %N1, %N2, %0" 16267 : "mshfhi.b %N1, %N2, %0"); 16268} 16269 [(set_attr "type" "arith_media") 16270 (set (attr "highpart") 16271 (cond [(eq_attr "endian" "little") (const_string "ignore")] 16272 (const_string "user")))]) 16273 16274(define_expand "mshfhi_l" 16275 [(match_operand:V2SI 0 "arith_reg_dest" "") 16276 (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ") 16277 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")] 16278 "TARGET_SHMEDIA" 16279{ 16280 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l) 16281 (operands[0], operands[1], operands[2])); 16282 DONE; 16283}) 16284 16285(define_expand "mshflo_l" 16286 [(match_operand:V2SI 0 "arith_reg_dest" "") 16287 (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ") 16288 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")] 16289 "TARGET_SHMEDIA" 16290{ 16291 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l) 16292 (operands[0], operands[1], operands[2])); 16293 DONE; 16294}) 16295 16296(define_insn "mshf4_l" 16297 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 16298 (vec_select:V2SI 16299 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ") 16300 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")) 16301 (parallel [(const_int 1) (const_int 3)])))] 16302 "TARGET_SHMEDIA" 16303{ 16304 return (TARGET_LITTLE_ENDIAN 16305 ? "mshfhi.l %N1, %N2, %0" 16306 : "mshflo.l %N1, %N2, %0"); 16307} 16308 [(set_attr "type" "arith_media") 16309 (set (attr "highpart") 16310 (cond [(eq_attr "endian" "big") (const_string "ignore")] 16311 (const_string "user")))]) 16312 16313(define_insn "mshf0_l" 16314 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 16315 (vec_select:V2SI 16316 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ") 16317 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")) 16318 (parallel [(const_int 0) (const_int 2)])))] 16319 "TARGET_SHMEDIA" 16320{ 16321 return (TARGET_LITTLE_ENDIAN 16322 ? "mshflo.l %N1, %N2, %0" 16323 : "mshfhi.l %N1, %N2, %0"); 16324} 16325 [(set_attr "type" "arith_media") 16326 (set (attr "highpart") 16327 (cond [(eq_attr "endian" "little") (const_string "ignore")] 16328 (const_string "user")))]) 16329 16330(define_expand "mshfhi_w" 16331 [(match_operand:V4HI 0 "arith_reg_dest" "") 16332 (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ") 16333 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")] 16334 "TARGET_SHMEDIA" 16335{ 16336 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w) 16337 (operands[0], operands[1], operands[2])); 16338 DONE; 16339}) 16340 16341(define_expand "mshflo_w" 16342 [(match_operand:V4HI 0 "arith_reg_dest" "") 16343 (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ") 16344 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")] 16345 "TARGET_SHMEDIA" 16346{ 16347 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w) 16348 (operands[0], operands[1], operands[2])); 16349 DONE; 16350}) 16351 16352(define_insn "mshf4_w" 16353 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 16354 (vec_select:V4HI 16355 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ") 16356 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")) 16357 (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))] 16358 "TARGET_SHMEDIA" 16359{ 16360 return (TARGET_LITTLE_ENDIAN 16361 ? "mshfhi.w %N1, %N2, %0" 16362 : "mshflo.w %N1, %N2, %0"); 16363} 16364 [(set_attr "type" "arith_media") 16365 (set (attr "highpart") 16366 (cond [(eq_attr "endian" "big") (const_string "ignore")] 16367 (const_string "user")))]) 16368 16369(define_insn "mshf0_w" 16370 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 16371 (vec_select:V4HI 16372 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ") 16373 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")) 16374 (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))] 16375 "TARGET_SHMEDIA" 16376{ 16377 return (TARGET_LITTLE_ENDIAN 16378 ? "mshflo.w %N1, %N2, %0" 16379 : "mshfhi.w %N1, %N2, %0"); 16380} 16381 [(set_attr "type" "arith_media") 16382 (set (attr "highpart") 16383 (cond [(eq_attr "endian" "little") (const_string "ignore")] 16384 (const_string "user")))]) 16385 16386(define_insn "mshflo_w_x" 16387 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 16388 (vec_select:V4HI 16389 (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ") 16390 (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ")) 16391 (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))] 16392 "TARGET_SHMEDIA" 16393 "mshflo.w %N1, %N2, %0" 16394 [(set_attr "type" "arith_media") 16395 (set_attr "highpart" "ignore")]) 16396 16397;; These are useful to expand ANDs and as combiner patterns. 16398(define_insn_and_split "mshfhi_l_di" 16399 [(set (match_operand:DI 0 "arith_reg_dest" "=r,f") 16400 (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f") 16401 (const_int 32)) 16402 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f") 16403 (const_int -4294967296))))] 16404 "TARGET_SHMEDIA" 16405 "@ 16406 mshfhi.l %N1, %N2, %0 16407 #" 16408 "TARGET_SHMEDIA && reload_completed 16409 && ! GENERAL_REGISTER_P (true_regnum (operands[0]))" 16410 [(set (match_dup 3) (match_dup 4)) 16411 (set (match_dup 5) (match_dup 6))] 16412{ 16413 operands[3] = gen_lowpart (SImode, operands[0]); 16414 operands[4] = gen_highpart (SImode, operands[1]); 16415 operands[5] = gen_highpart (SImode, operands[0]); 16416 operands[6] = gen_highpart (SImode, operands[2]); 16417} 16418 [(set_attr "type" "arith_media")]) 16419 16420(define_insn "*mshfhi_l_di_rev" 16421 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16422 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 16423 (const_int -4294967296)) 16424 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ") 16425 (const_int 32))))] 16426 "TARGET_SHMEDIA" 16427 "mshfhi.l %N2, %N1, %0" 16428 [(set_attr "type" "arith_media")]) 16429 16430(define_split 16431 [(set (match_operand:DI 0 "arith_reg_dest" "") 16432 (ior:DI (zero_extend:DI (match_operand:SI 1 16433 "extend_reg_or_0_operand" "")) 16434 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "") 16435 (const_int -4294967296)))) 16436 (clobber (match_operand:DI 3 "arith_reg_dest" ""))] 16437 "TARGET_SHMEDIA" 16438 [(const_int 0)] 16439{ 16440 emit_insn (gen_ashldi3_media (operands[3], 16441 simplify_gen_subreg (DImode, operands[1], 16442 SImode, 0), 16443 GEN_INT (32))); 16444 emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2])); 16445 DONE; 16446}) 16447 16448(define_insn "mshflo_l_di" 16449 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16450 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 16451 (const_int 4294967295)) 16452 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ") 16453 (const_int 32))))] 16454 16455 "TARGET_SHMEDIA" 16456 "mshflo.l %N1, %N2, %0" 16457 [(set_attr "type" "arith_media") 16458 (set_attr "highpart" "ignore")]) 16459 16460(define_insn "*mshflo_l_di_rev" 16461 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16462 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 16463 (const_int 32)) 16464 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ") 16465 (const_int 4294967295))))] 16466 16467 "TARGET_SHMEDIA" 16468 "mshflo.l %N2, %N1, %0" 16469 [(set_attr "type" "arith_media") 16470 (set_attr "highpart" "ignore")]) 16471 16472;; Combiner pattern for trampoline initialization. 16473(define_insn_and_split "*double_shori" 16474 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16475 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0") 16476 (const_int 32)) 16477 (match_operand:DI 2 "const_int_operand" "n")))] 16478 "TARGET_SHMEDIA 16479 && ! (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xffffffffUL)" 16480 "#" 16481 "rtx_equal_p (operands[0], operands[1])" 16482 [(const_int 0)] 16483{ 16484 HOST_WIDE_INT v = INTVAL (operands[2]); 16485 16486 emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v >> 16))); 16487 emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v & 65535))); 16488 DONE; 16489} 16490 [(set_attr "highpart" "ignore")]) 16491 16492(define_insn "*mshflo_l_di_x" 16493 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16494 (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand" 16495 "rZ")) 16496 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ") 16497 (const_int 32))))] 16498 "TARGET_SHMEDIA" 16499 "mshflo.l %N1, %N2, %0" 16500 [(set_attr "type" "arith_media") 16501 (set_attr "highpart" "ignore")]) 16502 16503(define_insn_and_split "concat_v2sf" 16504 [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?") 16505;; (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f") 16506 (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f") 16507 (match_operand:SF 2 "register_operand" "rZ,f,f")))] 16508 "TARGET_SHMEDIA" 16509 "@ 16510 mshflo.l %N1, %N2, %0 16511 # 16512 #" 16513 "TARGET_SHMEDIA && reload_completed 16514 && ! GENERAL_REGISTER_P (true_regnum (operands[0]))" 16515 [(set (match_dup 3) (match_dup 1)) 16516 (set (match_dup 4) (match_dup 2))] 16517{ 16518 operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0); 16519 operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4); 16520} 16521 [(set_attr "type" "arith_media") 16522 (set_attr "highpart" "ignore")]) 16523 16524(define_insn "*mshflo_l_di_x_rev" 16525 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16526 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 16527 (const_int 32)) 16528 (zero_extend:DI 16529 (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))] 16530 "TARGET_SHMEDIA" 16531 "mshflo.l %N2, %N1, %0" 16532 [(set_attr "type" "arith_media") 16533 (set_attr "highpart" "ignore")]) 16534 16535(define_insn "ashlv2si3" 16536 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 16537 (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r") 16538 (match_operand:DI 2 "shift_count_reg_operand" "r")))] 16539 "TARGET_SHMEDIA" 16540 "mshlld.l %1, %2, %0" 16541 [(set_attr "type" "arith_media") 16542 (set_attr "highpart" "depend")]) 16543 16544(define_split 16545 [(set (match_operand 0 "any_register_operand" "") 16546 (match_operator 3 "shift_operator" 16547 [(match_operand 1 "any_register_operand" "") 16548 (match_operand 2 "shift_count_reg_operand" "")]))] 16549 "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)" 16550 [(set (match_dup 0) (match_dup 3))] 16551{ 16552 rtx count = operands[2]; 16553 machine_mode outer_mode = GET_MODE (operands[2]), inner_mode; 16554 16555 while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND 16556 || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0) 16557 || GET_CODE (count) == TRUNCATE) 16558 count = XEXP (count, 0); 16559 inner_mode = GET_MODE (count); 16560 count = simplify_gen_subreg (outer_mode, count, inner_mode, 16561 subreg_lowpart_offset (outer_mode, inner_mode)); 16562 operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]), 16563 operands[1], count); 16564}) 16565 16566(define_insn "ashlv4hi3" 16567 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 16568 (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r") 16569 (match_operand:DI 2 "shift_count_reg_operand" "r")))] 16570 "TARGET_SHMEDIA" 16571 "mshlld.w %1, %2, %0" 16572 [(set_attr "type" "arith_media") 16573 (set_attr "highpart" "depend")]) 16574 16575(define_insn "lshrv2si3" 16576 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 16577 (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r") 16578 (match_operand:DI 2 "shift_count_reg_operand" "r")))] 16579 "TARGET_SHMEDIA" 16580 "mshlrd.l %1, %2, %0" 16581 [(set_attr "type" "arith_media") 16582 (set_attr "highpart" "depend")]) 16583 16584(define_insn "lshrv4hi3" 16585 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 16586 (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r") 16587 (match_operand:DI 2 "shift_count_reg_operand" "r")))] 16588 "TARGET_SHMEDIA" 16589 "mshlrd.w %1, %2, %0" 16590 [(set_attr "type" "arith_media") 16591 (set_attr "highpart" "depend")]) 16592 16593(define_insn "subv2si3" 16594 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 16595 (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ") 16596 (match_operand:V2SI 2 "arith_reg_operand" "r")))] 16597 "TARGET_SHMEDIA" 16598 "msub.l %N1, %2, %0" 16599 [(set_attr "type" "arith_media") 16600 (set_attr "highpart" "depend")]) 16601 16602(define_insn "subv4hi3" 16603 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 16604 (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ") 16605 (match_operand:V4HI 2 "arith_reg_operand" "r")))] 16606 "TARGET_SHMEDIA" 16607 "msub.w %N1, %2, %0" 16608 [(set_attr "type" "arith_media") 16609 (set_attr "highpart" "depend")]) 16610 16611(define_insn_and_split "subv2hi3" 16612 [(set (match_operand:V2HI 0 "arith_reg_dest" "=r") 16613 (minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ") 16614 (match_operand:V2HI 2 "arith_reg_operand" "r")))] 16615 "TARGET_SHMEDIA" 16616 "#" 16617 "TARGET_SHMEDIA" 16618 [(const_int 0)] 16619{ 16620 rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0); 16621 rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0); 16622 rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0); 16623 rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0); 16624 rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0); 16625 16626 emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1)); 16627 emit_insn (gen_truncdisi2 (si_dst, di_dst)); 16628 DONE; 16629} 16630 [(set_attr "highpart" "must_split")]) 16631 16632(define_insn "sssubv2si3" 16633 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 16634 (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ") 16635 (match_operand:V2SI 2 "arith_reg_operand" "r")))] 16636 "TARGET_SHMEDIA" 16637 "msubs.l %N1, %2, %0" 16638 [(set_attr "type" "mcmp_media") 16639 (set_attr "highpart" "depend")]) 16640 16641(define_insn "ussubv8qi3" 16642 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") 16643 (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ") 16644 (match_operand:V8QI 2 "arith_reg_operand" "r")))] 16645 "TARGET_SHMEDIA" 16646 "msubs.ub %N1, %2, %0" 16647 [(set_attr "type" "mcmp_media") 16648 (set_attr "highpart" "depend")]) 16649 16650(define_insn "sssubv4hi3" 16651 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 16652 (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ") 16653 (match_operand:V4HI 2 "arith_reg_operand" "r")))] 16654 "TARGET_SHMEDIA" 16655 "msubs.w %N1, %2, %0" 16656 [(set_attr "type" "mcmp_media") 16657 (set_attr "highpart" "depend")]) 16658 16659;; ------------------------------------------------------------------------- 16660;; Floating Point Intrinsics 16661;; ------------------------------------------------------------------------- 16662 16663(define_insn "fcosa_s" 16664 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 16665 (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")] 16666 UNSPEC_FCOSA))] 16667 "TARGET_SHMEDIA" 16668 "fcosa.s %1, %0" 16669 [(set_attr "type" "atrans_media")]) 16670 16671(define_insn "fsina_s" 16672 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 16673 (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")] 16674 UNSPEC_FSINA))] 16675 "TARGET_SHMEDIA" 16676 "fsina.s %1, %0" 16677 [(set_attr "type" "atrans_media")]) 16678 16679(define_insn "fipr" 16680 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 16681 (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1 16682 "fp_arith_reg_operand" "f") 16683 (match_operand:V4SF 2 16684 "fp_arith_reg_operand" "f")) 16685 (parallel [(const_int 0)])) 16686 (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2)) 16687 (parallel [(const_int 1)]))) 16688 (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2)) 16689 (parallel [(const_int 2)])) 16690 (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2)) 16691 (parallel [(const_int 3)])))))] 16692 "TARGET_SHMEDIA" 16693 "fipr.s %1, %2, %0" 16694 [(set_attr "type" "fparith_media")]) 16695 16696(define_insn "fsrra_s" 16697 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 16698 (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")] 16699 UNSPEC_FSRRA))] 16700 "TARGET_SHMEDIA" 16701 "fsrra.s %1, %0" 16702 [(set_attr "type" "atrans_media")]) 16703 16704(define_insn "ftrv" 16705 [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f") 16706 (plus:V4SF 16707 (plus:V4SF 16708 (mult:V4SF 16709 (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f") 16710 (parallel [(const_int 0) (const_int 5) 16711 (const_int 10) (const_int 15)])) 16712 (match_operand:V4SF 2 "fp_arith_reg_operand" "f")) 16713 (mult:V4SF 16714 (vec_select:V4SF (match_dup 1) 16715 (parallel [(const_int 4) (const_int 9) 16716 (const_int 14) (const_int 3)])) 16717 (vec_select:V4SF (match_dup 2) 16718 (parallel [(const_int 1) (const_int 2) 16719 (const_int 3) (const_int 0)])))) 16720 (plus:V4SF 16721 (mult:V4SF 16722 (vec_select:V4SF (match_dup 1) 16723 (parallel [(const_int 8) (const_int 13) 16724 (const_int 2) (const_int 7)])) 16725 (vec_select:V4SF (match_dup 2) 16726 (parallel [(const_int 2) (const_int 3) 16727 (const_int 0) (const_int 1)]))) 16728 (mult:V4SF 16729 (vec_select:V4SF (match_dup 1) 16730 (parallel [(const_int 12) (const_int 1) 16731 (const_int 6) (const_int 11)])) 16732 (vec_select:V4SF (match_dup 2) 16733 (parallel [(const_int 3) (const_int 0) 16734 (const_int 1) (const_int 2)]))))))] 16735 "TARGET_SHMEDIA" 16736 "ftrv.s %1, %2, %0" 16737 [(set_attr "type" "fparith_media")]) 16738 16739(define_insn "ldhi_l" 16740 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 16741 (zero_extract:SI 16742 (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p") 16743 (const_int 3)) 16744 (const_int -3))) 16745 (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1)) 16746 (const_int 0)))] 16747 "TARGET_SHMEDIA32" 16748 "ldhi.l %U1, %0" 16749 [(set_attr "type" "load_media")]) 16750 16751(define_insn "ldhi_q" 16752 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16753 (zero_extract:DI 16754 (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p") 16755 (const_int 7)) 16756 (const_int -7))) 16757 (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1)) 16758 (const_int 0)))] 16759 "TARGET_SHMEDIA32" 16760 "ldhi.q %U1, %0" 16761 [(set_attr "type" "load_media")]) 16762 16763(define_insn_and_split "*ldhi_q_comb0" 16764 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16765 (zero_extract:DI 16766 (mem:DI (plus:SI (ior:SI (plus:SI 16767 (match_operand:SI 1 "register_operand" "r") 16768 (match_operand:SI 2 "ua_offset" "I06")) 16769 (const_int 7)) 16770 (const_int -7))) 16771 (plus:SI (and:SI (match_dup 1) (const_int 7)) 16772 (const_int 1)) 16773 (const_int 0)))] 16774 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0" 16775 "#" 16776 "" 16777 [(pc)] 16778{ 16779 emit_insn (gen_ldhi_q (operands[0], 16780 gen_rtx_PLUS (SImode, operands[1], operands[2]))); 16781 DONE; 16782}) 16783 16784(define_insn_and_split "*ldhi_q_comb1" 16785 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16786 (zero_extract:DI 16787 (mem:DI (plus:SI (ior:SI (plus:SI 16788 (match_operand:SI 1 "register_operand" "r") 16789 (match_operand:SI 2 "ua_offset" "I06")) 16790 (const_int 7)) 16791 (const_int -7))) 16792 (plus:SI (and:SI (plus:SI (match_dup 1) 16793 (match_operand:SI 3 "ua_offset" "I06")) 16794 (const_int 7)) 16795 (const_int 1)) 16796 (const_int 0)))] 16797 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8) 16798 && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])" 16799 "#" 16800 "" 16801 [(pc)] 16802{ 16803 emit_insn (gen_ldhi_q (operands[0], 16804 gen_rtx_PLUS (SImode, operands[1], operands[2]))); 16805 DONE; 16806}) 16807 16808(define_insn "ldlo_l" 16809 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 16810 (zero_extract:SI 16811 (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p") 16812 (const_int -4))) 16813 (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3))) 16814 (and:SI (match_dup 1) (const_int 3))))] 16815 "TARGET_SHMEDIA32" 16816 "ldlo.l %U1, %0" 16817 [(set_attr "type" "load_media")]) 16818 16819(define_insn "ldlo_q" 16820 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16821 (zero_extract:DI 16822 (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p") 16823 (const_int -8))) 16824 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7))) 16825 (and:SI (match_dup 1) (const_int 7))))] 16826 "TARGET_SHMEDIA32" 16827 "ldlo.q %U1, %0" 16828 [(set_attr "type" "load_media")]) 16829 16830(define_insn_and_split "*ldlo_q_comb0" 16831 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16832 (zero_extract:DI 16833 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r") 16834 (match_operand:SI 2 "ua_offset" "I06")) 16835 (const_int -8))) 16836 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7))) 16837 (and:SI (match_dup 1) (const_int 7))))] 16838 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0" 16839 "#" 16840 "" 16841 [(pc)] 16842{ 16843 emit_insn (gen_ldlo_q (operands[0], 16844 gen_rtx_PLUS (SImode, operands[1], operands[2]))); 16845 DONE; 16846}) 16847 16848(define_insn_and_split "*ldlo_q_comb1" 16849 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16850 (zero_extract:DI 16851 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r") 16852 (match_operand:SI 2 "ua_offset" "I06")) 16853 (const_int -8))) 16854 (minus:SI (const_int 8) 16855 (and:SI (plus:SI (match_dup 1) 16856 (match_operand:SI 3 "ua_offset" "I06")) 16857 (const_int 7))) 16858 (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))] 16859 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8) 16860 && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])" 16861 "#" 16862 "" 16863 [(pc)] 16864{ 16865 emit_insn (gen_ldlo_q (operands[0], 16866 gen_rtx_PLUS (SImode, operands[1], operands[2]))); 16867 DONE; 16868}) 16869 16870(define_insn "sthi_l" 16871 [(set (zero_extract:SI 16872 (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p") 16873 (const_int 3)) 16874 (const_int -3))) 16875 (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1)) 16876 (const_int 0)) 16877 (match_operand:SI 1 "arith_reg_operand" "r"))] 16878 "TARGET_SHMEDIA32" 16879 "sthi.l %U0, %1" 16880 [(set_attr "type" "ustore_media")]) 16881 16882;; All unaligned stores are considered to be 'narrow' because they typically 16883;; operate on less that a quadword, and when they operate on a full quadword, 16884;; the vanilla store high / store low sequence will cause a stall if not 16885;; scheduled apart. 16886(define_insn "sthi_q" 16887 [(set (zero_extract:DI 16888 (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p") 16889 (const_int 7)) 16890 (const_int -7))) 16891 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1)) 16892 (const_int 0)) 16893 (match_operand:DI 1 "arith_reg_operand" "r"))] 16894 "TARGET_SHMEDIA32" 16895 "sthi.q %U0, %1" 16896 [(set_attr "type" "ustore_media")]) 16897 16898(define_insn_and_split "*sthi_q_comb0" 16899 [(set (zero_extract:DI 16900 (mem:DI (plus:SI (ior:SI (plus:SI 16901 (match_operand:SI 0 "register_operand" "r") 16902 (match_operand:SI 1 "ua_offset" "I06")) 16903 (const_int 7)) 16904 (const_int -7))) 16905 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1)) 16906 (const_int 0)) 16907 (match_operand:DI 2 "arith_reg_operand" "r"))] 16908 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0" 16909 "#" 16910 "" 16911 [(pc)] 16912{ 16913 emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]), 16914 operands[2])); 16915 DONE; 16916}) 16917 16918(define_insn_and_split "*sthi_q_comb1" 16919 [(set (zero_extract:DI 16920 (mem:DI (plus:SI (ior:SI (plus:SI 16921 (match_operand:SI 0 "register_operand" "r") 16922 (match_operand:SI 1 "ua_offset" "I06")) 16923 (const_int 7)) 16924 (const_int -7))) 16925 (plus:SI (and:SI (plus:SI (match_dup 0) 16926 (match_operand:SI 2 "ua_offset" "I06")) 16927 (const_int 7)) 16928 (const_int 1)) 16929 (const_int 0)) 16930 (match_operand:DI 3 "arith_reg_operand" "r"))] 16931 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8) 16932 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])" 16933 "#" 16934 "" 16935 [(pc)] 16936{ 16937 emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]), 16938 operands[3])); 16939 DONE; 16940}) 16941 16942;; This is highpart user because the address is used as full 64 bit. 16943(define_insn "stlo_l" 16944 [(set (zero_extract:SI 16945 (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p") 16946 (const_int -4))) 16947 (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3))) 16948 (and:SI (match_dup 0) (const_int 3))) 16949 (match_operand:SI 1 "arith_reg_operand" "r"))] 16950 "TARGET_SHMEDIA32" 16951 "stlo.l %U0, %1" 16952 [(set_attr "type" "ustore_media")]) 16953 16954(define_insn "stlo_q" 16955 [(set (zero_extract:DI 16956 (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p") 16957 (const_int -8))) 16958 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7))) 16959 (and:SI (match_dup 0) (const_int 7))) 16960 (match_operand:DI 1 "arith_reg_operand" "r"))] 16961 "TARGET_SHMEDIA32" 16962 "stlo.q %U0, %1" 16963 [(set_attr "type" "ustore_media")]) 16964 16965(define_insn_and_split "*stlo_q_comb0" 16966 [(set (zero_extract:DI 16967 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r") 16968 (match_operand:SI 1 "ua_offset" "I06")) 16969 (const_int -8))) 16970 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7))) 16971 (and:SI (match_dup 0) (const_int 7))) 16972 (match_operand:DI 2 "arith_reg_operand" "r"))] 16973 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0" 16974 "#" 16975 "" 16976 [(pc)] 16977{ 16978 emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]), 16979 operands[2])); 16980 DONE; 16981}) 16982 16983(define_insn_and_split "*stlo_q_comb1" 16984 [(set (zero_extract:DI 16985 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r") 16986 (match_operand:SI 1 "ua_offset" "I06")) 16987 (const_int -8))) 16988 (minus:SI (const_int 8) 16989 (and:SI (plus:SI (match_dup 0) 16990 (match_operand:SI 2 "ua_offset" "I06")) 16991 (const_int 7))) 16992 (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7))) 16993 (match_operand:DI 3 "arith_reg_operand" "r"))] 16994 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])" 16995 "#" 16996 "" 16997 [(pc)] 16998{ 16999 emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]), 17000 operands[3])); 17001 DONE; 17002}) 17003 17004(define_insn "ldhi_l64" 17005 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 17006 (zero_extract:SI 17007 (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p") 17008 (const_int 3)) 17009 (const_int -3))) 17010 (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1)) 17011 (const_int 0)))] 17012 "TARGET_SHMEDIA64" 17013 "ldhi.l %U1, %0" 17014 [(set_attr "type" "load_media")]) 17015 17016(define_insn "ldhi_q64" 17017 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 17018 (zero_extract:DI 17019 (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p") 17020 (const_int 7)) 17021 (const_int -7))) 17022 (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1)) 17023 (const_int 0)))] 17024 "TARGET_SHMEDIA64" 17025 "ldhi.q %U1, %0" 17026 [(set_attr "type" "load_media")]) 17027 17028(define_insn "ldlo_l64" 17029 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 17030 (zero_extract:SI 17031 (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p") 17032 (const_int -4))) 17033 (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3))) 17034 (and:DI (match_dup 1) (const_int 3))))] 17035 "TARGET_SHMEDIA64" 17036 "ldlo.l %U1, %0" 17037 [(set_attr "type" "load_media")]) 17038 17039(define_insn "ldlo_q64" 17040 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 17041 (zero_extract:DI 17042 (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p") 17043 (const_int -8))) 17044 (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7))) 17045 (and:DI (match_dup 1) (const_int 7))))] 17046 "TARGET_SHMEDIA64" 17047 "ldlo.q %U1, %0" 17048 [(set_attr "type" "load_media")]) 17049 17050(define_insn "sthi_l64" 17051 [(set (zero_extract:SI 17052 (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p") 17053 (const_int 3)) 17054 (const_int -3))) 17055 (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1)) 17056 (const_int 0)) 17057 (match_operand:SI 1 "arith_reg_operand" "r"))] 17058 "TARGET_SHMEDIA64" 17059 "sthi.l %U0, %1" 17060 [(set_attr "type" "ustore_media")]) 17061 17062(define_insn "sthi_q64" 17063 [(set (zero_extract:DI 17064 (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p") 17065 (const_int 7)) 17066 (const_int -7))) 17067 (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1)) 17068 (const_int 0)) 17069 (match_operand:DI 1 "arith_reg_operand" "r"))] 17070 "TARGET_SHMEDIA64" 17071 "sthi.q %U0, %1" 17072 [(set_attr "type" "ustore_media")]) 17073 17074(define_insn "stlo_l64" 17075 [(set (zero_extract:SI 17076 (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p") 17077 (const_int -4))) 17078 (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3))) 17079 (and:DI (match_dup 0) (const_int 3))) 17080 (match_operand:SI 1 "arith_reg_operand" "r"))] 17081 "TARGET_SHMEDIA64" 17082 "stlo.l %U0, %1" 17083 [(set_attr "type" "ustore_media")]) 17084 17085(define_insn "stlo_q64" 17086 [(set (zero_extract:DI 17087 (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p") 17088 (const_int -8))) 17089 (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7))) 17090 (and:DI (match_dup 0) (const_int 7))) 17091 (match_operand:DI 1 "arith_reg_operand" "r"))] 17092 "TARGET_SHMEDIA64" 17093 "stlo.q %U0, %1" 17094 [(set_attr "type" "ustore_media")]) 17095 17096(define_insn "nsb" 17097 [(set (match_operand:QI 0 "arith_reg_dest" "=r") 17098 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")] 17099 UNSPEC_NSB))] 17100 "TARGET_SHMEDIA" 17101 "nsb %1, %0" 17102 [(set_attr "type" "arith_media")]) 17103 17104(define_insn "nsbsi" 17105 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 17106 (zero_extend:SI 17107 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")] 17108 UNSPEC_NSB)))] 17109 "TARGET_SHMEDIA" 17110 "nsb %1, %0" 17111 [(set_attr "type" "arith_media")]) 17112 17113(define_insn "nsbdi" 17114 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 17115 (zero_extend:DI 17116 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")] 17117 UNSPEC_NSB)))] 17118 "TARGET_SHMEDIA" 17119 "nsb %1, %0" 17120 [(set_attr "type" "arith_media")]) 17121 17122(define_expand "ffsdi2" 17123 [(set (match_operand:DI 0 "arith_reg_dest" "") 17124 (ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))] 17125 "TARGET_SHMEDIA" 17126{ 17127 rtx scratch = gen_reg_rtx (DImode); 17128 rtx last; 17129 17130 emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx)); 17131 emit_insn (gen_xordi3 (scratch, operands[1], scratch)); 17132 emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx)); 17133 emit_insn (gen_nsbdi (scratch, scratch)); 17134 emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64))); 17135 emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch)); 17136 last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch)); 17137 set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (DImode, operands[0])); 17138 17139 DONE; 17140}) 17141 17142(define_expand "ffssi2" 17143 [(set (match_operand:SI 0 "arith_reg_dest" "") 17144 (ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))] 17145 "TARGET_SHMEDIA" 17146{ 17147 rtx scratch = gen_reg_rtx (SImode); 17148 rtx discratch = gen_reg_rtx (DImode); 17149 rtx last; 17150 17151 emit_insn (gen_adddi3 (discratch, 17152 simplify_gen_subreg (DImode, operands[1], SImode, 0), 17153 constm1_rtx)); 17154 emit_insn (gen_andcdi3 (discratch, 17155 simplify_gen_subreg (DImode, operands[1], SImode, 0), 17156 discratch)); 17157 emit_insn (gen_nsbsi (scratch, discratch)); 17158 last = emit_insn (gen_subsi3 (operands[0], 17159 force_reg (SImode, GEN_INT (63)), scratch)); 17160 set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (SImode, operands[0])); 17161 17162 DONE; 17163}) 17164 17165(define_insn "byterev" 17166 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") 17167 (vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r") 17168 (parallel [(const_int 7) (const_int 6) (const_int 5) 17169 (const_int 4) (const_int 3) (const_int 2) 17170 (const_int 1) (const_int 0)])))] 17171 "TARGET_SHMEDIA" 17172 "byterev %1, %0" 17173 [(set_attr "type" "arith_media")]) 17174 17175;; In user mode, the "pref" instruction will raise a RADDERR exception 17176;; for accesses to [0x80000000,0xffffffff]. This makes it an unsuitable 17177;; implementation of __builtin_prefetch for VxWorks RTPs. 17178(define_expand "prefetch" 17179 [(prefetch (match_operand 0 "address_operand" "") 17180 (match_operand:SI 1 "const_int_operand" "") 17181 (match_operand:SI 2 "const_int_operand" ""))] 17182 "(TARGET_SH2A || TARGET_SH3 || TARGET_SH5) 17183 && (TARGET_SHMEDIA || ! TARGET_VXWORKS_RTP)") 17184 17185(define_insn "*prefetch" 17186 [(prefetch (match_operand:SI 0 "register_operand" "r") 17187 (match_operand:SI 1 "const_int_operand" "n") 17188 (match_operand:SI 2 "const_int_operand" "n"))] 17189 "(TARGET_SH2A || TARGET_SH3 || TARGET_SHCOMPACT) && ! TARGET_VXWORKS_RTP" 17190 "pref @%0" 17191 [(set_attr "type" "other")]) 17192 17193(define_insn "*prefetch_media" 17194 [(prefetch (match_operand:QI 0 "address_operand" "p") 17195 (match_operand:SI 1 "const_int_operand" "n") 17196 (match_operand:SI 2 "const_int_operand" "n"))] 17197 "TARGET_SHMEDIA" 17198{ 17199 operands[0] = gen_rtx_MEM (QImode, operands[0]); 17200 output_asm_insn ("ld%M0.b %m0,r63", operands); 17201 return ""; 17202} 17203 [(set_attr "type" "other")]) 17204 17205(define_insn "alloco_i" 17206 [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p")) 17207 (unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))] 17208 "TARGET_SHMEDIA32" 17209{ 17210 rtx xops[2]; 17211 17212 if (GET_CODE (operands[0]) == PLUS) 17213 { 17214 xops[0] = XEXP (operands[0], 0); 17215 xops[1] = XEXP (operands[0], 1); 17216 } 17217 else 17218 { 17219 xops[0] = operands[0]; 17220 xops[1] = const0_rtx; 17221 } 17222 output_asm_insn ("alloco %0, %1", xops); 17223 return ""; 17224} 17225 [(set_attr "type" "other")]) 17226 17227(define_split 17228 [(set (match_operand 0 "any_register_operand" "") 17229 (match_operand 1 "" ""))] 17230 "TARGET_SHMEDIA && reload_completed" 17231 [(set (match_dup 0) (match_dup 1))] 17232{ 17233 if (!shmedia_cleanup_truncate (operands[1])) 17234 FAIL; 17235}) 17236 17237;; ------------------------------------------------------------------------- 17238;; Stack Protector Patterns 17239;; ------------------------------------------------------------------------- 17240 17241(define_expand "stack_protect_set" 17242 [(set (match_operand 0 "memory_operand" "") 17243 (match_operand 1 "memory_operand" ""))] 17244 "" 17245{ 17246 if (TARGET_SHMEDIA) 17247 { 17248 if (TARGET_SHMEDIA64) 17249 emit_insn (gen_stack_protect_set_di_media (operands[0], operands[1])); 17250 else 17251 emit_insn (gen_stack_protect_set_si_media (operands[0], operands[1])); 17252 } 17253 else 17254 emit_insn (gen_stack_protect_set_si (operands[0], operands[1])); 17255 17256 DONE; 17257}) 17258 17259(define_insn "stack_protect_set_si" 17260 [(set (match_operand:SI 0 "memory_operand" "=m") 17261 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET)) 17262 (set (match_scratch:SI 2 "=&r") (const_int 0))] 17263 "!TARGET_SHMEDIA" 17264{ 17265 return "mov.l %1,%2" "\n" 17266 " mov.l %2,%0" "\n" 17267 " mov #0,%2"; 17268} 17269 [(set_attr "type" "other") 17270 (set_attr "length" "6")]) 17271 17272(define_insn "stack_protect_set_si_media" 17273 [(set (match_operand:SI 0 "memory_operand" "=m") 17274 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET)) 17275 (set (match_scratch:SI 2 "=&r") (const_int 0))] 17276 "TARGET_SHMEDIA" 17277{ 17278 return "ld%M1.l %m1,%2" "\n" 17279 " st%M0.l %m0,%2" "\n" 17280 " movi 0,%2"; 17281} 17282 [(set_attr "type" "other") 17283 (set_attr "length" "12")]) 17284 17285(define_insn "stack_protect_set_di_media" 17286 [(set (match_operand:DI 0 "memory_operand" "=m") 17287 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET)) 17288 (set (match_scratch:DI 2 "=&r") (const_int 0))] 17289 "TARGET_SHMEDIA64" 17290{ 17291 return "ld%M1.q %m1,%2" "\n" 17292 " st%M0.q %m0,%2" "\n" 17293 " movi 0,%2"; 17294} 17295 [(set_attr "type" "other") 17296 (set_attr "length" "12")]) 17297 17298(define_expand "stack_protect_test" 17299 [(match_operand 0 "memory_operand" "") 17300 (match_operand 1 "memory_operand" "") 17301 (match_operand 2 "" "")] 17302 "" 17303{ 17304 if (TARGET_SHMEDIA) 17305 { 17306 rtx tmp = gen_reg_rtx (GET_MODE (operands[0])); 17307 rtx test; 17308 17309 test = gen_rtx_NE (VOIDmode, tmp, const0_rtx); 17310 if (TARGET_SHMEDIA64) 17311 { 17312 emit_insn (gen_stack_protect_test_di_media (tmp, operands[0], 17313 operands[1])); 17314 emit_jump_insn (gen_cbranchdi4 (test, tmp, const0_rtx, operands[2])); 17315 } 17316 else 17317 { 17318 emit_insn (gen_stack_protect_test_si_media (tmp, operands[0], 17319 operands[1])); 17320 emit_jump_insn (gen_cbranchsi4 (test, tmp, const0_rtx, operands[2])); 17321 } 17322 } 17323 else 17324 { 17325 emit_insn (gen_stack_protect_test_si (operands[0], operands[1])); 17326 emit_jump_insn (gen_branch_true (operands[2])); 17327 } 17328 17329 DONE; 17330}) 17331 17332(define_insn "stack_protect_test_si" 17333 [(set (reg:SI T_REG) 17334 (unspec:SI [(match_operand:SI 0 "memory_operand" "m") 17335 (match_operand:SI 1 "memory_operand" "m")] 17336 UNSPEC_SP_TEST)) 17337 (set (match_scratch:SI 2 "=&r") (const_int 0)) 17338 (set (match_scratch:SI 3 "=&r") (const_int 0))] 17339 "!TARGET_SHMEDIA" 17340{ 17341 return "mov.l %0,%2" "\n" 17342 " mov.l %1,%3" "\n" 17343 " cmp/eq %2,%3" "\n" 17344 " mov #0,%2" "\n" 17345 " mov #0,%3"; 17346} 17347 [(set_attr "type" "other") 17348 (set_attr "length" "10")]) 17349 17350(define_insn "stack_protect_test_si_media" 17351 [(set (match_operand:SI 0 "register_operand" "=&r") 17352 (unspec:SI [(match_operand:SI 1 "memory_operand" "m") 17353 (match_operand:SI 2 "memory_operand" "m")] 17354 UNSPEC_SP_TEST)) 17355 (set (match_scratch:SI 3 "=&r") (const_int 0))] 17356 "TARGET_SHMEDIA" 17357{ 17358 return "ld%M1.l %m1,%0" "\n" 17359 " ld%M2.l %m2,%3" "\n" 17360 " cmpeq %0,%3,%0" "\n" 17361 " movi 0,%3"; 17362} 17363 [(set_attr "type" "other") 17364 (set_attr "length" "16")]) 17365 17366(define_insn "stack_protect_test_di_media" 17367 [(set (match_operand:DI 0 "register_operand" "=&r") 17368 (unspec:DI [(match_operand:DI 1 "memory_operand" "m") 17369 (match_operand:DI 2 "memory_operand" "m")] 17370 UNSPEC_SP_TEST)) 17371 (set (match_scratch:DI 3 "=&r") (const_int 0))] 17372 "TARGET_SHMEDIA64" 17373{ 17374 return "ld%M1.q %m1,%0" "\n" 17375 " ld%M2.q %m2,%3" "\n" 17376 " cmpeq %0,%3,%0" "\n" 17377 " movi 0,%3"; 17378} 17379 [(set_attr "type" "other") 17380 (set_attr "length" "16")]) 17381 17382;; ------------------------------------------------------------------------- 17383;; Atomic operations 17384;; ------------------------------------------------------------------------- 17385 17386(include "sync.md") 17387