sh.md revision 1.5
1;;- Machine description for Renesas / SuperH SH. 2;; Copyright (C) 1993-2015 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_ICACHE 139 UNSPEC_INIT_TRAMP 140 UNSPEC_FCOSA 141 UNSPEC_FSRRA 142 UNSPEC_FSINA 143 UNSPEC_NSB 144 UNSPEC_ALLOCO 145 UNSPEC_TLSGD 146 UNSPEC_TLSLDM 147 UNSPEC_TLSIE 148 UNSPEC_DTPOFF 149 UNSPEC_GOTTPOFF 150 UNSPEC_TPOFF 151 UNSPEC_RA 152 UNSPEC_DIV_INV_M0 153 UNSPEC_DIV_INV_M1 154 UNSPEC_DIV_INV_M2 155 UNSPEC_DIV_INV_M3 156 UNSPEC_DIV_INV20 157 UNSPEC_DIV_INV_TABLE 158 UNSPEC_ASHIFTRT 159 UNSPEC_THUNK 160 UNSPEC_CHKADD 161 UNSPEC_SP_SET 162 UNSPEC_SP_TEST 163 UNSPEC_MOVUA 164 ;; (unspec [VAL SHIFT] UNSPEC_EXTRACT_S16) computes (short) (VAL >> SHIFT). 165 ;; UNSPEC_EXTRACT_U16 is the unsigned equivalent. 166 UNSPEC_EXTRACT_S16 167 UNSPEC_EXTRACT_U16 168 ;; (unspec [TARGET ANCHOR] UNSPEC_SYMOFF) == TARGET - ANCHOR. 169 UNSPEC_SYMOFF 170 ;; (unspec [OFFSET ANCHOR] UNSPEC_PCREL_SYMOFF) == OFFSET - (ANCHOR - .). 171 UNSPEC_PCREL_SYMOFF 172 ;; Misc builtins 173 UNSPEC_BUILTIN_STRLEN 174]) 175 176(define_c_enum "unspecv" [ 177 ;; These are used with unspec_volatile. 178 UNSPECV_BLOCKAGE 179 UNSPECV_ALIGN 180 UNSPECV_CONST2 181 UNSPECV_CONST4 182 UNSPECV_CONST8 183 UNSPECV_WINDOW_END 184 UNSPECV_CONST_END 185 UNSPECV_EH_RETURN 186 UNSPECV_GBR 187 UNSPECV_SP_SWITCH_B 188 UNSPECV_SP_SWITCH_E 189 190 UNSPECV_FPSCR_MODES 191 UNSPECV_FPSCR_STAT 192]) 193 194;; ------------------------------------------------------------------------- 195;; Attributes 196;; ------------------------------------------------------------------------- 197 198;; Target CPU. 199 200(define_attr "cpu" 201 "sh1,sh2,sh2e,sh2a,sh3,sh3e,sh4,sh4a,sh5" 202 (const (symbol_ref "sh_cpu_attr"))) 203 204(define_attr "endian" "big,little" 205 (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN") 206 (const_string "little") (const_string "big")))) 207 208;; Indicate if the default fpu mode is single precision. 209(define_attr "fpu_single" "yes,no" 210 (const (if_then_else (symbol_ref "TARGET_FPU_SINGLE") 211 (const_string "yes") (const_string "no")))) 212 213(define_attr "fmovd" "yes,no" 214 (const (if_then_else (symbol_ref "TARGET_FMOVD") 215 (const_string "yes") (const_string "no")))) 216;; pipeline model 217(define_attr "pipe_model" "sh1,sh4,sh5media" 218 (const 219 (cond [(symbol_ref "TARGET_SHMEDIA") (const_string "sh5media") 220 (symbol_ref "TARGET_SUPERSCALAR") (const_string "sh4")] 221 (const_string "sh1")))) 222 223;; cbranch conditional branch instructions 224;; jump unconditional jumps 225;; arith ordinary arithmetic 226;; arith3 a compound insn that behaves similarly to a sequence of 227;; three insns of type arith 228;; arith3b like above, but might end with a redirected branch 229;; load from memory 230;; load_si Likewise, SImode variant for general register. 231;; fload Likewise, but load to fp register. 232;; store to memory 233;; fstore floating point register to memory 234;; move general purpose register to register 235;; movi8 8-bit immediate to general purpose register 236;; mt_group other sh4 mt instructions 237;; fmove register to register, floating point 238;; smpy word precision integer multiply 239;; dmpy longword or doublelongword precision integer multiply 240;; return rts 241;; pload load of pr reg, which can't be put into delay slot of rts 242;; prset copy register to pr reg, ditto 243;; pstore store of pr reg, which can't be put into delay slot of jsr 244;; prget copy pr to register, ditto 245;; pcload pc relative load of constant value 246;; pcfload Likewise, but load to fp register. 247;; pcload_si Likewise, SImode variant for general register. 248;; rte return from exception 249;; sfunc special function call with known used registers 250;; call function call 251;; fp floating point 252;; fpscr_toggle toggle a bit in the fpscr 253;; fdiv floating point divide (or square root) 254;; gp_fpul move from general purpose register to fpul 255;; fpul_gp move from fpul to general purpose register 256;; mac_gp move from mac[lh] to general purpose register 257;; gp_mac move from general purpose register to mac[lh] 258;; mac_mem move from mac[lh] to memory 259;; mem_mac move from memory to mac[lh] 260;; dfp_arith,dfp_mul, fp_cmp,dfp_cmp,dfp_conv 261;; ftrc_s fix_truncsfsi2_i4 262;; dfdiv double precision floating point divide (or square root) 263;; cwb ic_invalidate_line_i 264;; movua SH4a unaligned load 265;; fsrra square root reciprocal approximate 266;; fsca sine and cosine approximate 267;; tls_load load TLS related address 268;; arith_media SHmedia arithmetic, logical, and shift instructions 269;; cbranch_media SHmedia conditional branch instructions 270;; cmp_media SHmedia compare instructions 271;; dfdiv_media SHmedia double precision divide and square root 272;; dfmul_media SHmedia double precision multiply instruction 273;; dfparith_media SHmedia double precision floating point arithmetic 274;; dfpconv_media SHmedia double precision floating point conversions 275;; dmpy_media SHmedia longword multiply 276;; fcmp_media SHmedia floating point compare instructions 277;; fdiv_media SHmedia single precision divide and square root 278;; fload_media SHmedia floating point register load instructions 279;; fmove_media SHmedia floating point register moves (inc. fabs and fneg) 280;; fparith_media SHmedia single precision floating point arithmetic 281;; fpconv_media SHmedia single precision floating point conversions 282;; fstore_media SHmedia floating point register store instructions 283;; gettr_media SHmedia gettr instruction 284;; invalidate_line_media SHmedia invalidate_line sequence 285;; jump_media SHmedia unconditional branch instructions 286;; load_media SHmedia general register load instructions 287;; pt_media SHmedia pt instruction (expanded by assembler) 288;; ptabs_media SHmedia ptabs instruction 289;; store_media SHmedia general register store instructions 290;; mcmp_media SHmedia multimedia compare, absolute, saturating ops 291;; mac_media SHmedia mac-style fixed point operations 292;; d2mpy_media SHmedia: two 32-bit integer multiplies 293;; atrans_media SHmedia approximate transcendental functions 294;; ustore_media SHmedia unaligned stores 295;; nil no-op move, will be deleted. 296 297(define_attr "type" 298 "mt_group,cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,load,load_si, 299 fload,store,fstore,move,movi8,fmove,smpy,dmpy,return,pload,prset,pstore, 300 prget,pcload,pcload_si,pcfload,rte,sfunc,call,fp,fpscr_toggle,fdiv,ftrc_s, 301 dfp_arith,dfp_mul,fp_cmp,dfp_cmp,dfp_conv,dfdiv,gp_fpul,fpul_gp,mac_gp, 302 gp_mac,mac_mem,mem_mac,mem_fpscr,gp_fpscr,cwb,movua,fsrra,fsca,tls_load, 303 arith_media,cbranch_media,cmp_media,dfdiv_media,dfmul_media,dfparith_media, 304 dfpconv_media,dmpy_media,fcmp_media,fdiv_media,fload_media,fmove_media, 305 fparith_media,fpconv_media,fstore_media,gettr_media,invalidate_line_media, 306 jump_media,load_media,pt_media,ptabs_media,store_media,mcmp_media,mac_media, 307 d2mpy_media,atrans_media,ustore_media,nil,other" 308 (const_string "other")) 309 310;; We define a new attribute namely "insn_class".We use 311;; this for the DFA based pipeline description. 312;; 313;; mt_group SH4 "mt" group instructions. 314;; 315;; ex_group SH4 "ex" group instructions. 316;; 317;; ls_group SH4 "ls" group instructions. 318;; 319(define_attr "insn_class" 320 "mt_group,ex_group,ls_group,br_group,fe_group,co_group,none" 321 (cond [(eq_attr "type" "move,mt_group") (const_string "mt_group") 322 (eq_attr "type" "movi8,arith,dyn_shift") (const_string "ex_group") 323 (eq_attr "type" "fmove,load,pcload,load_si,pcload_si,fload,pcfload, 324 store,fstore,gp_fpul,fpul_gp") (const_string "ls_group") 325 (eq_attr "type" "cbranch,jump") (const_string "br_group") 326 (eq_attr "type" "fp,fp_cmp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv") 327 (const_string "fe_group") 328 (eq_attr "type" "jump_ind,smpy,dmpy,mac_gp,return,pload,prset,pstore, 329 prget,rte,sfunc,call,dfp_cmp,mem_fpscr,gp_fpscr,cwb, 330 gp_mac,mac_mem,mem_mac") (const_string "co_group")] 331 (const_string "none"))) 332 333;; nil are zero instructions, and arith3 / arith3b are multiple instructions, 334;; so these do not belong in an insn group, although they are modeled 335;; with their own define_insn_reservations. 336 337;; Indicate what precision must be selected in fpscr for this insn, if any. 338(define_attr "fp_mode" "single,double,none" (const_string "none")) 339 340;; Indicate if the fpu mode is set by this instruction 341;; "unknown" must have the value as "none" in fp_mode, and means 342;; that the instruction/abi has left the processor in an unknown 343;; state. 344;; "none" means that nothing has changed and no mode is set. 345;; This attribute is only used for the Renesas ABI. 346(define_attr "fp_set" "single,double,unknown,none" (const_string "none")) 347 348; If a conditional branch destination is within -252..258 bytes away 349; from the instruction it can be 2 bytes long. Something in the 350; range -4090..4100 bytes can be 6 bytes long. All other conditional 351; branches are initially assumed to be 16 bytes long. 352; In machine_dependent_reorg, we split all branches that are longer than 353; 2 bytes. 354 355;; The maximum range used for SImode constant pool entries is 1018. A final 356;; instruction can add 8 bytes while only being 4 bytes in size, thus we 357;; can have a total of 1022 bytes in the pool. Add 4 bytes for a branch 358;; instruction around the pool table, 2 bytes of alignment before the table, 359;; and 30 bytes of alignment after the table. That gives a maximum total 360;; pool size of 1058 bytes. 361;; Worst case code/pool content size ratio is 1:2 (using asms). 362;; Thus, in the worst case, there is one instruction in front of a maximum 363;; sized pool, and then there are 1052 bytes of pool for every 508 bytes of 364;; code. For the last n bytes of code, there are 2n + 36 bytes of pool. 365;; If we have a forward branch, the initial table will be put after the 366;; unconditional branch. 367;; 368;; ??? We could do much better by keeping track of the actual pcloads within 369;; the branch range and in the pcload range in front of the branch range. 370 371;; ??? This looks ugly because genattrtab won't allow if_then_else or cond 372;; inside an le. 373(define_attr "short_cbranch_p" "no,yes" 374 (cond [(match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD") 375 (const_string "no") 376 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506)) 377 (const_string "yes") 378 (match_test "NEXT_INSN (PREV_INSN (insn)) != insn") 379 (const_string "no") 380 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508)) 381 (const_string "yes") 382 ] (const_string "no"))) 383 384(define_attr "med_branch_p" "no,yes" 385 (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990)) 386 (const_int 1988)) 387 (const_string "yes") 388 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD") 389 (const_string "no") 390 (leu (plus (minus (match_dup 0) (pc)) (const_int 4092)) 391 (const_int 8186)) 392 (const_string "yes") 393 ] (const_string "no"))) 394 395(define_attr "med_cbranch_p" "no,yes" 396 (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988)) 397 (const_int 1986)) 398 (const_string "yes") 399 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD") 400 (const_string "no") 401 (leu (plus (minus (match_dup 0) (pc)) (const_int 4090)) 402 (const_int 8184)) 403 (const_string "yes") 404 ] (const_string "no"))) 405 406(define_attr "braf_branch_p" "no,yes" 407 (cond [(match_test "! TARGET_SH2") 408 (const_string "no") 409 (leu (plus (minus (match_dup 0) (pc)) (const_int 10330)) 410 (const_int 20660)) 411 (const_string "yes") 412 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD") 413 (const_string "no") 414 (leu (plus (minus (match_dup 0) (pc)) (const_int 32764)) 415 (const_int 65530)) 416 (const_string "yes") 417 ] (const_string "no"))) 418 419(define_attr "braf_cbranch_p" "no,yes" 420 (cond [(match_test "! TARGET_SH2") 421 (const_string "no") 422 (leu (plus (minus (match_dup 0) (pc)) (const_int 10328)) 423 (const_int 20658)) 424 (const_string "yes") 425 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD") 426 (const_string "no") 427 (leu (plus (minus (match_dup 0) (pc)) (const_int 32762)) 428 (const_int 65528)) 429 (const_string "yes") 430 ] (const_string "no"))) 431 432;; An unconditional jump in the range -4092..4098 can be 2 bytes long. 433;; For wider ranges, we need a combination of a code and a data part. 434;; If we can get a scratch register for a long range jump, the code 435;; part can be 4 bytes long; otherwise, it must be 8 bytes long. 436;; If the jump is in the range -32764..32770, the data part can be 2 bytes 437;; long; otherwise, it must be 6 bytes long. 438 439;; All other instructions are two bytes long by default. 440 441;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)), 442;; but getattrtab doesn't understand this. 443(define_attr "length" "" 444 (cond [(eq_attr "type" "cbranch") 445 (cond [(eq_attr "short_cbranch_p" "yes") 446 (const_int 2) 447 (eq_attr "med_cbranch_p" "yes") 448 (const_int 6) 449 (eq_attr "braf_cbranch_p" "yes") 450 (const_int 12) 451;; ??? using pc is not computed transitively. 452 (ne (match_dup 0) (match_dup 0)) 453 (const_int 14) 454 (match_test "flag_pic") 455 (const_int 24) 456 ] (const_int 16)) 457 (eq_attr "type" "jump") 458 (cond [(eq_attr "med_branch_p" "yes") 459 (const_int 2) 460 (and (match_test "prev_nonnote_insn (insn)") 461 (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))") 462 (symbol_ref "INSN")) 463 (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))") 464 (symbol_ref "code_for_indirect_jump_scratch")))) 465 (cond [(eq_attr "braf_branch_p" "yes") 466 (const_int 6) 467 (not (match_test "flag_pic")) 468 (const_int 10) 469 (match_test "TARGET_SH2") 470 (const_int 10)] (const_int 18)) 471 (eq_attr "braf_branch_p" "yes") 472 (const_int 10) 473;; ??? using pc is not computed transitively. 474 (ne (match_dup 0) (match_dup 0)) 475 (const_int 12) 476 (match_test "flag_pic") 477 (const_int 22) 478 ] (const_int 14)) 479 (eq_attr "type" "pt_media") 480 (if_then_else (match_test "TARGET_SHMEDIA64") 481 (const_int 20) (const_int 12)) 482 (and (eq_attr "type" "jump_media") 483 (match_test "TARGET_SH5_CUT2_WORKAROUND")) 484 (const_int 8) 485 ] (if_then_else (match_test "TARGET_SHMEDIA") 486 (const_int 4) 487 (const_int 2)))) 488 489;; DFA descriptions for the pipelines 490 491(include "sh1.md") 492(include "shmedia.md") 493(include "sh4.md") 494 495(include "iterators.md") 496(include "predicates.md") 497(include "constraints.md") 498 499;; Definitions for filling delay slots 500 501(define_attr "needs_delay_slot" "yes,no" (const_string "no")) 502 503(define_attr "banked" "yes,no" 504 (cond [(match_test "sh_loads_bankedreg_p (insn)") 505 (const_string "yes")] 506 (const_string "no"))) 507 508;; ??? This should be (nil) instead of (const_int 0) 509(define_attr "hit_stack" "yes,no" 510 (cond [(not (match_test "find_regno_note (insn, REG_INC, SP_REG)")) 511 (const_string "no")] 512 (const_string "yes"))) 513 514(define_attr "interrupt_function" "no,yes" 515 (const (symbol_ref "current_function_interrupt"))) 516 517(define_attr "in_delay_slot" "yes,no" 518 (cond [(eq_attr "type" "cbranch") (const_string "no") 519 (eq_attr "type" "pcload,pcload_si") (const_string "no") 520 (eq_attr "type" "fpscr_toggle") (const_string "no") 521 (eq_attr "needs_delay_slot" "yes") (const_string "no") 522 (eq_attr "length" "2") (const_string "yes") 523 ] (const_string "no"))) 524 525(define_attr "cond_delay_slot" "yes,no" 526 (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes") 527 ] (const_string "no"))) 528 529(define_attr "is_sfunc" "" 530 (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0))) 531 532(define_attr "is_mac_media" "" 533 (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0))) 534 535(define_attr "branch_zero" "yes,no" 536 (cond [(eq_attr "type" "!cbranch") (const_string "no") 537 (ne (symbol_ref "(next_active_insn (insn)\ 538 == (prev_active_insn\ 539 (XEXP (SET_SRC (PATTERN (insn)), 1))))\ 540 && get_attr_length (next_active_insn (insn)) == 2") 541 (const_int 0)) 542 (const_string "yes")] 543 (const_string "no"))) 544 545;; SH4 Double-precision computation with double-precision result - 546;; the two halves are ready at different times. 547(define_attr "dfp_comp" "yes,no" 548 (cond [(eq_attr "type" "dfp_arith,dfp_mul,dfp_conv,dfdiv") (const_string "yes")] 549 (const_string "no"))) 550 551;; Insns for which the latency of a preceding fp insn is decreased by one. 552(define_attr "late_fp_use" "yes,no" (const_string "no")) 553;; And feeding insns for which this relevant. 554(define_attr "any_fp_comp" "yes,no" 555 (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv") 556 (const_string "yes")] 557 (const_string "no"))) 558 559(define_attr "any_int_load" "yes,no" 560 (cond [(eq_attr "type" "load,load_si,pcload,pcload_si") 561 (const_string "yes")] 562 (const_string "no"))) 563 564(define_attr "highpart" "user, ignore, extend, depend, must_split" 565 (const_string "user")) 566 567(define_delay 568 (eq_attr "needs_delay_slot" "yes") 569 [(eq_attr "in_delay_slot" "yes") (nil) (nil)]) 570 571;; Since a normal return (rts) implicitly uses the PR register, 572;; we can't allow PR register loads in an rts delay slot. 573;; On the SH1* and SH2*, the rte instruction reads the return pc from the 574;; stack, and thus we can't put a pop instruction in its delay slot. 575;; On the SH3* and SH4*, the rte instruction does not use the stack, so a 576;; pop instruction can go in the delay slot, unless it references a banked 577;; register (the register bank is switched by rte). 578(define_delay 579 (eq_attr "type" "return") 580 [(and (eq_attr "in_delay_slot" "yes") 581 (ior (and (eq_attr "interrupt_function" "no") 582 (eq_attr "type" "!pload,prset")) 583 (and (eq_attr "interrupt_function" "yes") 584 (ior (match_test "TARGET_SH3") (eq_attr "hit_stack" "no")) 585 (eq_attr "banked" "no")))) 586 (nil) (nil)]) 587 588;; Since a call implicitly uses the PR register, we can't allow 589;; a PR register store in a jsr delay slot. 590 591(define_delay 592 (ior (eq_attr "type" "call") (eq_attr "type" "sfunc")) 593 [(and (eq_attr "in_delay_slot" "yes") 594 (eq_attr "type" "!pstore,prget")) (nil) (nil)]) 595 596;; Conditional branches with delay slots are available starting with SH2. 597(define_delay 598 (and (eq_attr "type" "cbranch") (match_test "TARGET_SH2")) 599 [(eq_attr "cond_delay_slot" "yes") (nil) (nil)]) 600 601;; ------------------------------------------------------------------------- 602;; SImode signed integer comparisons 603;; ------------------------------------------------------------------------- 604 605;; Patterns to generate the tst instruction which are usually formed by 606;; the combine pass. 607;; The canonical form here being used is (eq (and (op) (op)) 0). 608;; For some bit patterns, such as contiguous bits, we also must accept 609;; zero_extract forms. Single bit tests are also handled via zero_extract 610;; patterns in the 'bit field extract patterns' section. All variants 611;; are eventually converted to the 'tstsi_t' insn. 612;; As long as pseudos can be created (before RA), 'tstsi_t' will also accept 613;; constants that won't fit into 8 bits. After having captured the constant 614;; we can decide better whether/how to load it into a register and do other 615;; post-combine optimizations such as bypassing sign/zero extensions. 616(define_insn_and_split "tstsi_t" 617 [(set (reg:SI T_REG) 618 (eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "%z,r") 619 (match_operand:SI 1 "arith_or_int_operand" "K08,r")) 620 (const_int 0)))] 621 "TARGET_SH1 622 && (can_create_pseudo_p () || arith_reg_operand (operands[1], SImode) 623 || satisfies_constraint_K08 (operands[1]))" 624 "tst %1,%0" 625 "TARGET_SH1 && can_create_pseudo_p () && CONST_INT_P (operands[1]) 626 && !sh_in_recog_treg_set_expr ()" 627 [(const_int 0)] 628{ 629 gcc_assert (CONST_INT_P (operands[1])); 630 631 HOST_WIDE_INT op1val = INTVAL (operands[1]); 632 bool op0_dead_after_this = 633 sh_reg_dead_or_unused_after_insn (curr_insn, REGNO (operands[0])); 634 635 if (optimize) 636 { 637 if (dump_file) 638 fprintf (dump_file, 639 "tstsi_t: trying to optimize const_int 0x%08x\n", 640 (uint32_t)op1val); 641 642 /* See if we can convert a test with a reg and a constant into 643 something simpler, if the reg is known to be zero or sign 644 extended. */ 645 sh_extending_set_of_reg eop0 = sh_find_extending_set_of_reg (operands[0], 646 curr_insn); 647 if (eop0.ext_code != UNKNOWN) 648 { 649 /* Adjust the constant, trying to eliminate bits that are not 650 contributing to the result. */ 651 if (eop0.from_mode == QImode) 652 op1val = (op1val 653 | (eop0.ext_code == SIGN_EXTEND && (op1val & 0xFFFFFF80) 654 ? 0x80 : 0)) & 0xFF; 655 else if (eop0.from_mode == HImode) 656 op1val = (op1val 657 | (eop0.ext_code == SIGN_EXTEND && (op1val & 0xFFFF8000) 658 ? 0x8000 : 0)) & 0xFFFF; 659 660 if (dump_file) 661 fprintf (dump_file, "tstsi_t: using effective const_int: 0x%08x\n", 662 (uint32_t)op1val); 663 664 /* Try to bypass the sign/zero extension first if op0 dies after 665 this insn. */ 666 if (op0_dead_after_this && eop0.can_use_as_unextended_reg ()) 667 { 668 if (dump_file) 669 fprintf (dump_file, "tstsi_t: bypassing sign/zero extension\n"); 670 671 operands[0] = eop0.use_as_unextended_reg (curr_insn); 672 } 673 else if ((eop0.from_mode == QImode && op1val == 0xFF) 674 || (eop0.from_mode == HImode && op1val == 0xFFFF)) 675 { 676 if (dump_file) 677 fprintf (dump_file, "tstsi_t: converting to cmpeqsi_t\n"); 678 emit_insn (gen_cmpeqsi_t (eop0.use_as_extended_reg (curr_insn), 679 const0_rtx)); 680 DONE; 681 } 682 else if (eop0.ext_code == SIGN_EXTEND 683 && ((eop0.from_mode == QImode && op1val == 0x80) 684 || (eop0.from_mode == HImode && op1val == 0x8000))) 685 { 686 if (dump_file) 687 fprintf (dump_file, "tstsi_t: converting to cmpgesi_t\n"); 688 emit_insn (gen_cmpgesi_t (eop0.use_as_extended_reg (curr_insn), 689 const0_rtx)); 690 DONE; 691 } 692 else if (!CONST_OK_FOR_K08 (op1val)) 693 { 694 if (dump_file) 695 fprintf (dump_file, "tstsi_t: converting const_int to signed " 696 "value\n"); 697 698 /* If here we haven't done anything yet. Convert the constant 699 to a signed value to reduce the constant pool size. */ 700 operands[0] = eop0.use_as_extended_reg (curr_insn); 701 702 if (eop0.from_mode == QImode) 703 op1val |= (op1val & 0x80) ? 0xFFFFFFFFFFFFFF00LL : 0; 704 else if (eop0.from_mode == HImode) 705 op1val |= (op1val & 0x8000) ? 0xFFFFFFFFFFFF0000LL : 0; 706 } 707 else 708 operands[0] = eop0.use_as_extended_reg (curr_insn); 709 } 710 } 711 712 if (dump_file) 713 fprintf (dump_file, "tstsi_t: using const_int 0x%08x\n", 714 (uint32_t)op1val); 715 716 /* Try to fit the constant into 8 bits by shuffling the value in the 717 register operand. 718 Doing that usually results in smaller code as the constants in the 719 pools are avoided (32 bit constant = load + constant = 6 bytes). 720 However, if the constant load (LS insn) can be hoisted insn dependencies 721 can be avoided and chances for parallel execution increase. The common 722 usage pattern is: 723 - load reg from mem 724 - test bits 725 - conditional branch 726 727 FIXME: For now we do that only when optimizing for size until there is 728 a better heuristic. 729 730 FIXME: If there are multiple tst insns in the block with the same 731 constant, avoid the #imm variant to avoid R0 loads. Use the 'tst Rn,Rm' 732 variant instead and load the constant into a reg. For that we'd need 733 to do some analysis. */ 734 735 if (CONST_OK_FOR_K08 (op1val)) 736 { 737 /* Do nothing. */ 738 } 739 else if ((op1val & 0xFFFF) == 0 740 && CONST_OK_FOR_K08 (op1val >> 16) && optimize_size) 741 { 742 /* Use a swap.w insn to do a shift + reg copy (to R0) in one insn. */ 743 op1val = op1val >> 16; 744 rtx r = gen_reg_rtx (SImode); 745 emit_insn (gen_rotlsi3_16 (r, operands[0])); 746 operands[0] = r; 747 } 748 else if ((op1val & 0xFF) == 0 749 && CONST_OK_FOR_K08 (op1val >> 8) && optimize_size) 750 { 751 /* Use a swap.b insn to do a shift + reg copy (to R0) in one insn. */ 752 op1val = op1val >> 8; 753 rtx r = gen_reg_rtx (SImode); 754 emit_insn (gen_swapbsi2 (r, operands[0])); 755 operands[0] = r; 756 } 757 else if ((op1val & 3) == 0 758 && CONST_OK_FOR_K08 (op1val >> 2) && optimize_size) 759 { 760 op1val = op1val >> 2; 761 rtx r = gen_reg_rtx (SImode); 762 emit_insn (gen_lshrsi3_k (r, operands[0], GEN_INT (2))); 763 operands[0] = r; 764 } 765 else if ((op1val & 1) == 0 766 && CONST_OK_FOR_K08 (op1val >> 1) && optimize_size) 767 { 768 op1val = op1val >> 1; 769 rtx r = gen_reg_rtx (SImode); 770 emit_insn (gen_shlr (r, operands[0])); 771 operands[0] = r; 772 } 773 774 operands[1] = GEN_INT (op1val); 775 776 if (!satisfies_constraint_K08 (operands[1])) 777 operands[1] = force_reg (SImode, operands[1]); 778 779 emit_insn (gen_tstsi_t (operands[0], operands[1])); 780 DONE; 781} 782 [(set_attr "type" "mt_group")]) 783 784;; This pattern is used by combine when testing QI/HImode subregs with a 785;; negative constant. Ignore high bits by masking them out in the constant. 786(define_insn_and_split "*tst<mode>_t" 787 [(set (reg:SI T_REG) 788 (eq:SI (subreg:SI 789 (and:QIHI (match_operand:QIHI 0 "arith_reg_operand") 790 (match_operand 1 "const_int_operand")) 0) 791 (const_int 0)))] 792 "TARGET_SH1 && can_create_pseudo_p ()" 793 "#" 794 "&& 1" 795 [(set (reg:SI T_REG) 796 (eq:SI (and:SI (match_dup 0) (match_dup 1)) (const_int 0)))] 797{ 798 operands[0] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0); 799 operands[1] = GEN_INT (INTVAL (operands[1]) 800 & (<MODE>mode == HImode ? 0xFFFF : 0xFF)); 801}) 802 803;; This pattern might be risky because it also tests the upper bits and not 804;; only the subreg. We have to check whether the operands have been sign 805;; or zero extended. In the worst case, a zero extension has to be inserted 806;; to mask out the unwanted bits. 807(define_insn_and_split "*tst<mode>_t_subregs" 808 [(set (reg:SI T_REG) 809 (eq:SI 810 (subreg:QIHI 811 (and:SI (match_operand:SI 0 "arith_reg_operand") 812 (match_operand:SI 1 "arith_reg_operand")) <lowpart_le>) 813 (const_int 0)))] 814 "TARGET_SH1 && TARGET_LITTLE_ENDIAN && can_create_pseudo_p ()" 815 "#" 816 "&& !sh_in_recog_treg_set_expr ()" 817 [(const_int 0)] 818{ 819 sh_split_tst_subregs (curr_insn, <MODE>mode, <lowpart_le>, operands); 820 DONE; 821}) 822 823(define_insn_and_split "*tst<mode>_t_subregs" 824 [(set (reg:SI T_REG) 825 (eq:SI 826 (subreg:QIHI 827 (and:SI (match_operand:SI 0 "arith_reg_operand") 828 (match_operand:SI 1 "arith_reg_operand")) <lowpart_be>) 829 (const_int 0)))] 830 "TARGET_SH1 && TARGET_BIG_ENDIAN && can_create_pseudo_p ()" 831 "#" 832 "&& !sh_in_recog_treg_set_expr ()" 833 [(const_int 0)] 834{ 835 sh_split_tst_subregs (curr_insn, <MODE>mode, <lowpart_be>, operands); 836 DONE; 837}) 838 839;; Extract contiguous bits and compare them against zero. 840;; Notice that this will not be used for single bits. Special single bit 841;; extraction patterns are in the 'bit field extract patterns' section. 842(define_insn_and_split "*tst<mode>_t_zero_extract" 843 [(set (reg:SI T_REG) 844 (eq:SI (zero_extract:SI (match_operand:QIHISI 0 "arith_reg_operand") 845 (match_operand 1 "const_int_operand") 846 (match_operand 2 "const_int_operand")) 847 (const_int 0)))] 848 "TARGET_SH1 && can_create_pseudo_p ()" 849 "#" 850 "&& 1" 851 [(set (reg:SI T_REG) 852 (eq:SI (and:SI (match_dup 0) (match_dup 1)) (const_int 0)))] 853{ 854 operands[1] = GEN_INT (ZERO_EXTRACT_ANDMASK (operands[1], operands[2])); 855 if (GET_MODE (operands[0]) != SImode) 856 operands[0] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0); 857}) 858 859;; Convert '(reg << shift) & mask' into 'reg & (mask >> shift)'. 860;; The shifted-out bits in the mask will always be zero, since the 861;; shifted-in bits in the reg will also be always zero. 862(define_insn_and_split "*tstsi_t_shift_mask" 863 [(set (reg:SI T_REG) 864 (eq:SI (and:SI (ashift:SI (match_operand:SI 0 "arith_reg_operand") 865 (match_operand 1 "const_int_operand")) 866 (match_operand 2 "const_int_operand")) 867 (const_int 0)))] 868 "TARGET_SH1 && can_create_pseudo_p ()" 869 "#" 870 "&& 1" 871 [(set (reg:SI T_REG) 872 (eq:SI (and:SI (match_dup 0) (match_dup 2)) (const_int 0)))] 873{ 874 operands[2] = GEN_INT (INTVAL (operands[2]) >> INTVAL (operands[1])); 875}) 876 877(define_insn "cmpeqsi_t" 878 [(set (reg:SI T_REG) 879 (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r") 880 (match_operand:SI 1 "arith_operand" "N,rI08,r")))] 881 "TARGET_SH1" 882 "@ 883 tst %0,%0 884 cmp/eq %1,%0 885 cmp/eq %1,%0" 886 [(set_attr "type" "mt_group")]) 887 888;; Sometimes combine fails to form the (eq (and (op) (op)) 0) tst insn. 889;; Try to fix that in the split1 pass by looking for the previous set 890;; of the tested op. Also see if there is a preceeding sign/zero 891;; extension that can be avoided. 892(define_split 893 [(set (reg:SI T_REG) 894 (eq:SI (match_operand:SI 0 "arith_reg_operand") (const_int 0)))] 895 "TARGET_SH1 && can_create_pseudo_p () && optimize 896 && !sh_in_recog_treg_set_expr ()" 897 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))] 898{ 899 if (dump_file) 900 fprintf (dump_file, "cmpeqsi_t: trying to optimize const_int 0\n"); 901 902 /* If the tested reg is not dead after this insn, it's probably used by 903 something else after the comparison. It's probably better to leave 904 it as it is. */ 905 if (find_regno_note (curr_insn, REG_DEAD, REGNO (operands[0])) == NULL_RTX) 906 FAIL; 907 908 /* FIXME: Maybe also search the predecessor basic blocks to catch 909 more cases. */ 910 set_of_reg op = sh_find_set_of_reg (operands[0], curr_insn, 911 prev_nonnote_insn_bb); 912 913 if (op.set_src != NULL && GET_CODE (op.set_src) == AND 914 && !sh_insn_operands_modified_between_p (op.insn, op.insn, curr_insn)) 915 { 916 if (dump_file) 917 fprintf (dump_file, "cmpeqsi_t: found preceeding and in insn %d\n", 918 INSN_UID (op.insn)); 919 920 if (!(arith_reg_operand (XEXP (op.set_src, 0), SImode) 921 && (arith_reg_operand (XEXP (op.set_src, 1), SImode) 922 || CONST_INT_P (XEXP (op.set_src, 1))))) 923 FAIL; 924 925 /* Assume that the operands of the andsi insn are compatible with the 926 operands of the tstsi_t insn, which is generally the case. */ 927 if (dump_file) 928 fprintf (dump_file, "cmpeqsi_t: replacing with tstsi_t\n"); 929 emit_insn (gen_tstsi_t (XEXP (op.set_src, 0), XEXP (op.set_src, 1))); 930 DONE; 931 } 932 933 /* Converting HImode into tests against 0xFFFF tends to increase the code 934 size, as it will create constant pool entries. Disable it for now. */ 935 const bool enable_himode = false; 936 937 /* FIXME: try to keep the (eq (reg) (const_int 0)). Even if the zero 938 extended reg is used after this insn, if we know that _before_ the zero 939 extension the value was loaded via sign extending mem load, we can just 940 use the value of the mem load directly. */ 941 sh_extending_set_of_reg eop = sh_find_extending_set_of_reg (operands[0], 942 curr_insn); 943 944 if (eop.ext_code != UNKNOWN 945 && (eop.from_mode == QImode || (eop.from_mode == HImode && enable_himode)) 946 && eop.can_use_as_unextended_reg () 947 && !reg_used_between_p (operands[0], eop.insn, curr_insn)) 948 { 949 /* Bypass the sign/zero extension and test against the bit mask, but 950 only if it's the only use of the sign/zero extracted value. 951 Otherwise we'd be introducing new constants in the pool. */ 952 if (dump_file) 953 fprintf (dump_file, "cmpeqsi_t: bypassing sign/zero extension in " 954 "insn %d and using tstsi_t\n", INSN_UID (op.insn)); 955 956 emit_insn (gen_tstsi_t ( 957 eop.use_as_unextended_reg (curr_insn), 958 GEN_INT (eop.from_mode == QImode ? 0xFF : 0xFFFF))); 959 DONE; 960 } 961 962 if (dump_file) 963 fprintf (dump_file, "cmpeqsi_t: nothing optimized\n"); 964 FAIL; 965}) 966 967;; FIXME: For some reason, on SH4A and SH2A combine fails to simplify this 968;; pattern by itself. What this actually does is: 969;; x == 0: (1 >> 0-0) & 1 = 1 970;; x != 0: (1 >> 0-x) & 1 = 0 971;; Without this the test pr51244-8.c fails on SH2A and SH4A. 972(define_insn_and_split "*cmpeqsi_t" 973 [(set (reg:SI T_REG) 974 (and:SI (lshiftrt:SI 975 (const_int 1) 976 (neg:SI (match_operand:SI 0 "arith_reg_operand" "r"))) 977 (const_int 1)))] 978 "TARGET_SH1" 979 "#" 980 "&& 1" 981 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))]) 982 983(define_insn "cmpgtsi_t" 984 [(set (reg:SI T_REG) 985 (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r") 986 (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))] 987 "TARGET_SH1" 988 "@ 989 cmp/pl %0 990 cmp/gt %1,%0" 991 [(set_attr "type" "mt_group")]) 992 993(define_insn "cmpgesi_t" 994 [(set (reg:SI T_REG) 995 (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r") 996 (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))] 997 "TARGET_SH1" 998 "@ 999 cmp/pz %0 1000 cmp/ge %1,%0" 1001 [(set_attr "type" "mt_group")]) 1002 1003;; Recombine a cmp/pz followed by a nott into a shll. 1004;; On non-SH2A recombine a cmp/pz followed by a movrt into shll-movt. 1005;; On SH2A cmp/pz-movrt is slightly better, as it does not mutate the input. 1006(define_split 1007 [(set (reg:SI T_REG) 1008 (ge:SI (match_operand:SI 0 "arith_reg_operand") (const_int 0)))] 1009 1010 "TARGET_SH1 && can_create_pseudo_p () && optimize 1011 && !sh_in_recog_treg_set_expr ()" 1012 [(const_int 0)] 1013{ 1014 if (dump_file) 1015 fprintf (dump_file, "cmpgesi_t: trying to optimize for const_int 0\n"); 1016 1017 rtx_insn* i = next_nonnote_insn_bb (curr_insn); 1018 1019 if (dump_file) 1020 { 1021 fprintf (dump_file, "cmpgesi_t: following insn is \n"); 1022 print_rtl_single (dump_file, i); 1023 fprintf (dump_file, "\n"); 1024 } 1025 1026 if (sh_is_nott_insn (i)) 1027 { 1028 if (dump_file) 1029 fprintf (dump_file, 1030 "cmpgesi_t: replacing (cmp/pz, nott) with (shll)\n"); 1031 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[0])); 1032 set_insn_deleted (i); 1033 DONE; 1034 } 1035 1036 /* On non-SH2A negc is used as movrt replacement, which sets T = 1. 1037 Thus we can remove it only if T is marked as dead afterwards. */ 1038 if (rtx dest_reg = !TARGET_SH2A 1039 && sh_reg_dead_or_unused_after_insn (i, T_REG) 1040 ? sh_movrt_set_dest (i) : NULL) 1041 { 1042 if (dump_file) 1043 fprintf (dump_file, 1044 "cmpgesi_t: replacing (cmp/pz, movrt) with (shll, movt)\n"); 1045 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[0])); 1046 add_reg_note (emit_insn (gen_movt (dest_reg, get_t_reg_rtx ())), 1047 REG_DEAD, get_t_reg_rtx ()); 1048 set_insn_deleted (i); 1049 DONE; 1050 } 1051 1052 if (dump_file) 1053 fprintf (dump_file, "cmpgesi_t: nothing optimized\n"); 1054 1055 FAIL; 1056}) 1057 1058;; FIXME: This is actually wrong. There is no way to literally move a 1059;; general reg to t reg. Luckily, it seems that this pattern will be only 1060;; used when the general reg is known be either '0' or '1' during combine. 1061;; What we actually need is reg != 0 -> T, but we have only reg == 0 -> T. 1062;; Due to interactions with other patterns, combine fails to pick the latter 1063;; and invert the dependent logic. 1064(define_insn "*negtstsi" 1065 [(set (reg:SI T_REG) (match_operand:SI 0 "arith_reg_operand" "r"))] 1066 "TARGET_SH1 && !sh_in_recog_treg_set_expr ()" 1067 "cmp/pl %0" 1068 [(set_attr "type" "mt_group")]) 1069 1070;; Some integer sign comparison patterns can be realized with the div0s insn. 1071;; div0s Rm,Rn T = (Rm >> 31) ^ (Rn >> 31) 1072;; 1073;; The 'cmp_div0s' pattern is our canonical form, into which all the other 1074;; variations are converted. The negative forms will split into a trailing 1075;; nott sequence, which will be eliminated either by the 1076;; 'any_treg_expr_to_reg' pattern, or by the 'sh_treg_combine' pass. 1077(define_insn "cmp_div0s" 1078 [(set (reg:SI T_REG) 1079 (lshiftrt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "%r") 1080 (match_operand:SI 1 "arith_reg_operand" "r")) 1081 (const_int 31)))] 1082 "TARGET_SH1" 1083 "div0s %0,%1" 1084 [(set_attr "type" "arith")]) 1085 1086(define_insn_and_split "*cmp_div0s_1" 1087 [(set (reg:SI T_REG) 1088 (xor:SI (ge:SI (match_operand:SI 0 "arith_reg_operand") 1089 (const_int 0)) 1090 (ge:SI (match_operand:SI 1 "arith_reg_operand") 1091 (const_int 0))))] 1092 "TARGET_SH1 && can_create_pseudo_p ()" 1093 "#" 1094 "&& 1" 1095 [(set (reg:SI T_REG) 1096 (lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31)))]) 1097 1098(define_insn_and_split "*cmp_div0s_2" 1099 [(set (reg:SI T_REG) 1100 (eq:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand") 1101 (const_int 31)) 1102 (ge:SI (match_operand:SI 1 "arith_reg_operand") 1103 (const_int 0))))] 1104 "TARGET_SH1 && can_create_pseudo_p ()" 1105 "#" 1106 "&& 1" 1107 [(set (reg:SI T_REG) 1108 (lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31)))]) 1109 1110(define_insn_and_split "*cmp_div0s_3" 1111 [(set (reg:SI T_REG) 1112 (eq:SI (ge:SI (match_operand:SI 0 "arith_reg_operand") 1113 (const_int 0)) 1114 (ge:SI (match_operand:SI 1 "arith_reg_operand") 1115 (const_int 0))))] 1116 "TARGET_SH1 && can_create_pseudo_p ()" 1117 "#" 1118 "&& 1" 1119 [(set (reg:SI T_REG) 1120 (lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31))) 1121 (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))]) 1122 1123(define_insn_and_split "*cmp_div0s_4" 1124 [(set (reg:SI T_REG) 1125 (ge:SI (xor:SI (match_operand:SI 0 "arith_reg_operand") 1126 (match_operand:SI 1 "arith_reg_operand")) 1127 (const_int 0)))] 1128 "TARGET_SH1 && can_create_pseudo_p ()" 1129 "#" 1130 "&& 1" 1131 [(set (reg:SI T_REG) 1132 (lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31))) 1133 (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))]) 1134 1135(define_insn_and_split "*cmp_div0s_5" 1136 [(set (reg:SI T_REG) 1137 (xor:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand") 1138 (const_int 31)) 1139 (ge:SI (match_operand:SI 1 "arith_reg_operand") 1140 (const_int 0))))] 1141 "TARGET_SH1 && can_create_pseudo_p ()" 1142 "#" 1143 "&& 1" 1144 [(set (reg:SI T_REG) 1145 (lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31))) 1146 (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))]) 1147 1148(define_insn_and_split "*cmp_div0s_6" 1149 [(set (reg:SI T_REG) 1150 (eq:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand") 1151 (const_int 31)) 1152 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand") 1153 (const_int 31))))] 1154 "TARGET_SH1 && can_create_pseudo_p ()" 1155 "#" 1156 "&& 1" 1157 [(set (reg:SI T_REG) 1158 (lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31))) 1159 (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))]) 1160 1161;; ------------------------------------------------------------------------- 1162;; SImode compare and branch 1163;; ------------------------------------------------------------------------- 1164 1165(define_expand "cbranchsi4" 1166 [(set (pc) 1167 (if_then_else (match_operator 0 "comparison_operator" 1168 [(match_operand:SI 1 "arith_operand" "") 1169 (match_operand:SI 2 "arith_operand" "")]) 1170 (label_ref (match_operand 3 "" "")) 1171 (pc))) 1172 (clobber (reg:SI T_REG))] 1173 "" 1174{ 1175 if (TARGET_SHMEDIA) 1176 emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1], 1177 operands[2], operands[3])); 1178 else 1179 expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1); 1180 1181 DONE; 1182}) 1183 1184;; Combine patterns to invert compare and branch operations for which we 1185;; don't have actual comparison insns. These patterns are used in cases 1186;; which appear after the initial cbranchsi expansion, which also does 1187;; some condition inversion. 1188(define_split 1189 [(set (pc) 1190 (if_then_else (ne (match_operand:SI 0 "arith_reg_operand" "") 1191 (match_operand:SI 1 "arith_reg_or_0_operand" "")) 1192 (label_ref (match_operand 2)) 1193 (pc))) 1194 (clobber (reg:SI T_REG))] 1195 "TARGET_SH1" 1196 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (match_dup 1))) 1197 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 1198 (label_ref (match_dup 2)) 1199 (pc)))]) 1200 1201;; FIXME: Similar to the *cmpeqsi_t pattern above, for some reason, on SH4A 1202;; and SH2A combine fails to simplify this pattern by itself. 1203;; What this actually does is: 1204;; x == 0: (1 >> 0-0) & 1 = 1 1205;; x != 0: (1 >> 0-x) & 1 = 0 1206;; Without this the test pr51244-8.c fails on SH2A and SH4A. 1207(define_split 1208 [(set (pc) 1209 (if_then_else 1210 (eq (and:SI (lshiftrt:SI 1211 (const_int 1) 1212 (neg:SI (match_operand:SI 0 "arith_reg_operand" ""))) 1213 (const_int 1)) 1214 (const_int 0)) 1215 (label_ref (match_operand 2)) 1216 (pc))) 1217 (clobber (reg:SI T_REG))] 1218 "TARGET_SH1" 1219 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0))) 1220 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 1221 (label_ref (match_dup 2)) 1222 (pc)))]) 1223 1224;; FIXME: These could probably use code iterators for the compare op. 1225(define_split 1226 [(set (pc) 1227 (if_then_else (le (match_operand:SI 0 "arith_reg_operand" "") 1228 (match_operand:SI 1 "arith_reg_or_0_operand" "")) 1229 (label_ref (match_operand 2)) 1230 (pc))) 1231 (clobber (reg:SI T_REG))] 1232 "TARGET_SH1" 1233 [(set (reg:SI T_REG) (gt:SI (match_dup 0) (match_dup 1))) 1234 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 1235 (label_ref (match_dup 2)) 1236 (pc)))]) 1237 1238(define_split 1239 [(set (pc) 1240 (if_then_else (lt (match_operand:SI 0 "arith_reg_operand" "") 1241 (match_operand:SI 1 "arith_reg_or_0_operand" "")) 1242 (label_ref (match_operand 2)) 1243 (pc))) 1244 (clobber (reg:SI T_REG))] 1245 "TARGET_SH1" 1246 [(set (reg:SI T_REG) (ge:SI (match_dup 0) (match_dup 1))) 1247 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 1248 (label_ref (match_dup 2)) 1249 (pc)))]) 1250 1251(define_split 1252 [(set (pc) 1253 (if_then_else (leu (match_operand:SI 0 "arith_reg_operand" "") 1254 (match_operand:SI 1 "arith_reg_operand" "")) 1255 (label_ref (match_operand 2)) 1256 (pc))) 1257 (clobber (reg:SI T_REG))] 1258 "TARGET_SH1" 1259 [(set (reg:SI T_REG) (gtu:SI (match_dup 0) (match_dup 1))) 1260 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 1261 (label_ref (match_dup 2)) 1262 (pc)))]) 1263 1264(define_split 1265 [(set (pc) 1266 (if_then_else (ltu (match_operand:SI 0 "arith_reg_operand" "") 1267 (match_operand:SI 1 "arith_reg_operand" "")) 1268 (label_ref (match_operand 2)) 1269 (pc))) 1270 (clobber (reg:SI T_REG))] 1271 "TARGET_SH1" 1272 [(set (reg:SI T_REG) (geu:SI (match_dup 0) (match_dup 1))) 1273 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 1274 (label_ref (match_dup 2)) 1275 (pc)))]) 1276 1277;; ------------------------------------------------------------------------- 1278;; SImode unsigned integer comparisons 1279;; ------------------------------------------------------------------------- 1280 1281;; Usually comparisons of 'unsigned int >= 0' are optimized away completely. 1282;; However, especially when optimizations are off (e.g. -O0) such comparisons 1283;; might remain and we have to handle them. If the '>= 0' case wasn't 1284;; handled here, something else would just load a '0' into the second operand 1285;; and do the comparison. We can do slightly better by just setting the 1286;; T bit to '1'. 1287(define_insn_and_split "cmpgeusi_t" 1288 [(set (reg:SI T_REG) 1289 (geu:SI (match_operand:SI 0 "arith_reg_operand" "r") 1290 (match_operand:SI 1 "arith_reg_or_0_operand" "r")))] 1291 "TARGET_SH1" 1292 "cmp/hs %1,%0" 1293 "&& satisfies_constraint_Z (operands[1])" 1294 [(set (reg:SI T_REG) (const_int 1))] 1295 "" 1296 [(set_attr "type" "mt_group")]) 1297 1298(define_insn "cmpgtusi_t" 1299 [(set (reg:SI T_REG) 1300 (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r") 1301 (match_operand:SI 1 "arith_reg_operand" "r")))] 1302 "TARGET_SH1" 1303 "cmp/hi %1,%0" 1304 [(set_attr "type" "mt_group")]) 1305 1306;; ------------------------------------------------------------------------- 1307;; DImode compare and branch 1308;; ------------------------------------------------------------------------- 1309 1310;; arith3 patterns don't work well with the sh4-300 branch prediction mechanism. 1311;; Therefore, we aim to have a set of three branches that go straight to the 1312;; destination, i.e. only one of them is taken at any one time. 1313;; This mechanism should also be slightly better for the sh4-200. 1314 1315(define_expand "cbranchdi4" 1316 [(set (pc) 1317 (if_then_else (match_operator 0 "comparison_operator" 1318 [(match_operand:DI 1 "arith_operand" "") 1319 (match_operand:DI 2 "arith_operand" "")]) 1320 (label_ref (match_operand 3 "" "")) 1321 (pc))) 1322 (clobber (match_dup 4)) 1323 (clobber (reg:SI T_REG))] 1324 "TARGET_CBRANCHDI4 || TARGET_SH2 || TARGET_SHMEDIA" 1325{ 1326 enum rtx_code comparison; 1327 1328 if (TARGET_SHMEDIA) 1329 { 1330 emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1], 1331 operands[2], operands[3])); 1332 DONE; 1333 } 1334 else if (!TARGET_CBRANCHDI4) 1335 { 1336 sh_emit_compare_and_branch (operands, DImode); 1337 DONE; 1338 } 1339 else 1340 { 1341 if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE)) 1342 DONE; 1343 1344 comparison = prepare_cbranch_operands (operands, DImode, 1345 LAST_AND_UNUSED_RTX_CODE); 1346 if (comparison != GET_CODE (operands[0])) 1347 operands[0] 1348 = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]); 1349 operands[4] = gen_rtx_SCRATCH (SImode); 1350 } 1351}) 1352 1353(define_insn_and_split "cbranchdi4_i" 1354 [(set (pc) 1355 (if_then_else (match_operator 0 "comparison_operator" 1356 [(match_operand:DI 1 "arith_operand" "r,r") 1357 (match_operand:DI 2 "arith_operand" "rN,I08")]) 1358 (label_ref (match_operand 3 "" "")) 1359 (pc))) 1360 (clobber (match_scratch:SI 4 "=X,&r")) 1361 (clobber (reg:SI T_REG))] 1362 "TARGET_CBRANCHDI4" 1363 "#" 1364 "&& reload_completed" 1365 [(pc)] 1366{ 1367 if (!expand_cbranchdi4 (operands, GET_CODE (operands[0]))) 1368 FAIL; 1369 DONE; 1370}) 1371 1372;; ------------------------------------------------------------------------- 1373;; DImode signed integer comparisons 1374;; ------------------------------------------------------------------------- 1375 1376(define_insn "" 1377 [(set (reg:SI T_REG) 1378 (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r") 1379 (match_operand:DI 1 "arith_operand" "r")) 1380 (const_int 0)))] 1381 "TARGET_SH1" 1382{ 1383 return output_branchy_insn (EQ, "tst\t%S1,%S0;bf\t%l9;tst\t%R1,%R0", 1384 insn, operands); 1385} 1386 [(set_attr "length" "6") 1387 (set_attr "type" "arith3b")]) 1388 1389(define_insn "cmpeqdi_t" 1390 [(set (reg:SI T_REG) 1391 (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r") 1392 (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))] 1393 "TARGET_SH1" 1394{ 1395 static const char* alt[] = 1396 { 1397 "tst %S0,%S0" "\n" 1398 " bf 0f" "\n" 1399 " tst %R0,%R0" "\n" 1400 "0:", 1401 1402 "cmp/eq %S1,%S0" "\n" 1403 " bf 0f" "\n" 1404 " cmp/eq %R1,%R0" "\n" 1405 "0:" 1406 }; 1407 return alt[which_alternative]; 1408} 1409 [(set_attr "length" "6") 1410 (set_attr "type" "arith3b")]) 1411 1412(define_split 1413 [(set (reg:SI T_REG) 1414 (eq:SI (match_operand:DI 0 "arith_reg_operand" "") 1415 (match_operand:DI 1 "arith_reg_or_0_operand" "")))] 1416;; If we applied this split when not optimizing, it would only be 1417;; applied during the machine-dependent reorg, when no new basic blocks 1418;; may be created. 1419 "TARGET_SH1 && reload_completed && optimize" 1420 [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3))) 1421 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 1422 (label_ref (match_dup 6)) 1423 (pc))) 1424 (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5))) 1425 (match_dup 6)] 1426{ 1427 operands[2] = gen_highpart (SImode, operands[0]); 1428 operands[3] = operands[1] == const0_rtx 1429 ? const0_rtx 1430 : gen_highpart (SImode, operands[1]); 1431 operands[4] = gen_lowpart (SImode, operands[0]); 1432 operands[5] = gen_lowpart (SImode, operands[1]); 1433 operands[6] = gen_label_rtx (); 1434}) 1435 1436(define_insn "cmpgtdi_t" 1437 [(set (reg:SI T_REG) 1438 (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r") 1439 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))] 1440 "TARGET_SH2" 1441{ 1442 static const char* alt[] = 1443 { 1444 "cmp/eq %S1,%S0" "\n" 1445 " bf{.|/}s 0f" "\n" 1446 " cmp/gt %S1,%S0" "\n" 1447 " cmp/hi %R1,%R0" "\n" 1448 "0:", 1449 1450 "tst %S0,%S0" "\n" 1451 " bf{.|/}s 0f" "\n" 1452 " cmp/pl %S0" "\n" 1453 " cmp/hi %S0,%R0" "\n" 1454 "0:" 1455 }; 1456 return alt[which_alternative]; 1457} 1458 [(set_attr "length" "8") 1459 (set_attr "type" "arith3")]) 1460 1461(define_insn "cmpgedi_t" 1462 [(set (reg:SI T_REG) 1463 (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r") 1464 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))] 1465 "TARGET_SH2" 1466{ 1467 static const char* alt[] = 1468 { 1469 "cmp/eq %S1,%S0" "\n" 1470 " bf{.|/}s 0f" "\n" 1471 " cmp/ge %S1,%S0" "\n" 1472 " cmp/hs %R1,%R0" "\n" 1473 "0:", 1474 1475 "cmp/pz %S0" 1476 }; 1477 return alt[which_alternative]; 1478} 1479 [(set_attr "length" "8,2") 1480 (set_attr "type" "arith3,mt_group")]) 1481 1482;; ------------------------------------------------------------------------- 1483;; DImode unsigned integer comparisons 1484;; ------------------------------------------------------------------------- 1485 1486(define_insn "cmpgeudi_t" 1487 [(set (reg:SI T_REG) 1488 (geu:SI (match_operand:DI 0 "arith_reg_operand" "r") 1489 (match_operand:DI 1 "arith_reg_operand" "r")))] 1490 "TARGET_SH2" 1491{ 1492 return "cmp/eq %S1,%S0" "\n" 1493 " bf{.|/}s 0f" "\n" 1494 " cmp/hs %S1,%S0" "\n" 1495 " cmp/hs %R1,%R0" "\n" 1496 "0:"; 1497} 1498 [(set_attr "length" "8") 1499 (set_attr "type" "arith3")]) 1500 1501(define_insn "cmpgtudi_t" 1502 [(set (reg:SI T_REG) 1503 (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r") 1504 (match_operand:DI 1 "arith_reg_operand" "r")))] 1505 "TARGET_SH2" 1506{ 1507 return "cmp/eq %S1,%S0" "\n" 1508 " bf{.|/}s 0f" "\n" 1509 " cmp/hi %S1,%S0" "\n" 1510 " cmp/hi %R1,%R0" "\n" 1511 "0:"; 1512} 1513 [(set_attr "length" "8") 1514 (set_attr "type" "arith3")]) 1515 1516(define_insn "cmpeqsi_media" 1517 [(set (match_operand:SI 0 "register_operand" "=r") 1518 (eq:SI (match_operand:SI 1 "logical_operand" "%r") 1519 (match_operand:SI 2 "cmp_operand" "Nr")))] 1520 "TARGET_SHMEDIA" 1521 "cmpeq %1, %N2, %0" 1522 [(set_attr "type" "cmp_media")]) 1523 1524(define_insn "cmpeqdi_media" 1525 [(set (match_operand:SI 0 "register_operand" "=r") 1526 (eq:SI (match_operand:DI 1 "register_operand" "%r") 1527 (match_operand:DI 2 "cmp_operand" "Nr")))] 1528 "TARGET_SHMEDIA" 1529 "cmpeq %1, %N2, %0" 1530 [(set_attr "type" "cmp_media")]) 1531 1532(define_insn "cmpgtsi_media" 1533 [(set (match_operand:SI 0 "register_operand" "=r") 1534 (gt:SI (match_operand:SI 1 "cmp_operand" "Nr") 1535 (match_operand:SI 2 "cmp_operand" "rN")))] 1536 "TARGET_SHMEDIA" 1537 "cmpgt %N1, %N2, %0" 1538 [(set_attr "type" "cmp_media")]) 1539 1540(define_insn "cmpgtdi_media" 1541 [(set (match_operand:SI 0 "register_operand" "=r") 1542 (gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr") 1543 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))] 1544 "TARGET_SHMEDIA" 1545 "cmpgt %N1, %N2, %0" 1546 [(set_attr "type" "cmp_media")]) 1547 1548(define_insn "cmpgtusi_media" 1549 [(set (match_operand:SI 0 "register_operand" "=r") 1550 (gtu:SI (match_operand:SI 1 "cmp_operand" "Nr") 1551 (match_operand:SI 2 "cmp_operand" "rN")))] 1552 "TARGET_SHMEDIA" 1553 "cmpgtu %N1, %N2, %0" 1554 [(set_attr "type" "cmp_media")]) 1555 1556(define_insn "cmpgtudi_media" 1557 [(set (match_operand:SI 0 "register_operand" "=r") 1558 (gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr") 1559 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))] 1560 "TARGET_SHMEDIA" 1561 "cmpgtu %N1, %N2, %0" 1562 [(set_attr "type" "cmp_media")]) 1563 1564; This pattern is for combine. 1565(define_insn "*cmpne0sisi_media" 1566 [(set (match_operand:SI 0 "register_operand" "=r") 1567 (ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))] 1568 "TARGET_SHMEDIA" 1569 "cmpgtu %1,r63,%0" 1570 [(set_attr "type" "cmp_media")]) 1571 1572;; ------------------------------------------------------------------------- 1573;; Conditional move instructions 1574;; ------------------------------------------------------------------------- 1575 1576;; The insn names may seem reversed, but note that cmveq performs the move 1577;; if op1 == 0, and cmvne does it if op1 != 0. 1578 1579(define_insn "movdicc_false" 1580 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 1581 (if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r") 1582 (const_int 0)) 1583 (match_operand:DI 2 "arith_reg_or_0_operand" "rN") 1584 (match_operand:DI 3 "arith_reg_operand" "0")))] 1585 "TARGET_SHMEDIA" 1586 "cmveq %1, %N2, %0" 1587 [(set_attr "type" "arith_media")]) 1588 1589(define_insn "movdicc_true" 1590 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 1591 (if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r") 1592 (const_int 0)) 1593 (match_operand:DI 2 "arith_reg_or_0_operand" "rN") 1594 (match_operand:DI 3 "arith_reg_operand" "0")))] 1595 "TARGET_SHMEDIA" 1596 "cmvne %1, %N2, %0" 1597 [(set_attr "type" "arith_media")]) 1598 1599(define_peephole2 1600 [(set (match_operand:DI 0 "arith_reg_dest" "") 1601 (if_then_else:DI (match_operator 3 "equality_comparison_operator" 1602 [(match_operand:DI 1 "arith_reg_operand" "") 1603 (const_int 0)]) 1604 (match_operand:DI 2 "arith_reg_dest" "") 1605 (match_dup 0))) 1606 (set (match_dup 2) (match_dup 0))] 1607 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])" 1608 [(set (match_dup 2) 1609 (if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))] 1610{ 1611 operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])), 1612 VOIDmode, operands[1], CONST0_RTX (DImode)); 1613}) 1614 1615(define_peephole2 1616 [(set (match_operand:DI 0 "general_movdst_operand" "") 1617 (match_operand:DI 1 "arith_reg_or_0_operand" "")) 1618 (set (match_operand:DI 2 "arith_reg_dest" "") 1619 (if_then_else:DI (match_operator 4 "equality_comparison_operator" 1620 [(match_operand:DI 3 "arith_reg_operand" "") 1621 (const_int 0)]) 1622 (match_dup 0) 1623 (match_dup 2)))] 1624 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])" 1625 [(set (match_dup 2) 1626 (if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))] 1627 "") 1628 1629(define_expand "movdicc" 1630 [(set (match_operand:DI 0 "register_operand" "") 1631 (if_then_else:DI (match_operand 1 "comparison_operator" "") 1632 (match_operand:DI 2 "register_operand" "") 1633 (match_operand:DI 3 "register_operand" "")))] 1634 "TARGET_SHMEDIA" 1635{ 1636 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE) 1637 && GET_MODE (XEXP (operands[1], 0)) == DImode 1638 && XEXP (operands[1], 1) == const0_rtx) 1639 ; 1640 else 1641 { 1642 if (!can_create_pseudo_p ()) 1643 FAIL; 1644 1645 operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]), 1646 GET_CODE (operands[1]), 1647 XEXP (operands[1], 0), 1648 XEXP (operands[1], 1)); 1649 if (!operands[1]) 1650 FAIL; 1651 } 1652}) 1653 1654;; Add SImode variants for cmveq / cmvne to compensate for not promoting 1655;; SImode to DImode. 1656(define_insn "movsicc_false" 1657 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 1658 (if_then_else:SI (eq (match_operand:SI 1 "arith_reg_operand" "r") 1659 (const_int 0)) 1660 (match_operand:SI 2 "arith_reg_or_0_operand" "rN") 1661 (match_operand:SI 3 "arith_reg_operand" "0")))] 1662 "TARGET_SHMEDIA" 1663 "cmveq %1, %N2, %0" 1664 [(set_attr "type" "arith_media")]) 1665 1666(define_insn "movsicc_true" 1667 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 1668 (if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r") 1669 (const_int 0)) 1670 (match_operand:SI 2 "arith_reg_or_0_operand" "rN") 1671 (match_operand:SI 3 "arith_reg_operand" "0")))] 1672 "TARGET_SHMEDIA" 1673 "cmvne %1, %N2, %0" 1674 [(set_attr "type" "arith_media")]) 1675 1676(define_peephole2 1677 [(set (match_operand:SI 0 "arith_reg_dest" "") 1678 (if_then_else:SI (match_operator 3 "equality_comparison_operator" 1679 [(match_operand:SI 1 "arith_reg_operand" "") 1680 (const_int 0)]) 1681 (match_operand:SI 2 "arith_reg_dest" "") 1682 (match_dup 0))) 1683 (set (match_dup 2) (match_dup 0))] 1684 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])" 1685 [(set (match_dup 2) 1686 (if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))] 1687{ 1688 operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])), 1689 VOIDmode, operands[1], CONST0_RTX (SImode)); 1690}) 1691 1692(define_peephole2 1693 [(set (match_operand:SI 0 "general_movdst_operand" "") 1694 (match_operand:SI 1 "arith_reg_or_0_operand" "")) 1695 (set (match_operand:SI 2 "arith_reg_dest" "") 1696 (if_then_else:SI (match_operator 4 "equality_comparison_operator" 1697 [(match_operand:SI 3 "arith_reg_operand" "") 1698 (const_int 0)]) 1699 (match_dup 0) 1700 (match_dup 2)))] 1701 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0]) 1702 && (!REG_P (operands[1]) || GENERAL_REGISTER_P (REGNO (operands[1])))" 1703 [(set (match_dup 2) 1704 (if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))] 1705{ 1706 replace_rtx (operands[4], operands[0], operands[1]); 1707}) 1708 1709;; The register allocator is rather clumsy in handling multi-way conditional 1710;; moves, so allow the combiner to make them, and we split them up after 1711;; reload. */ 1712(define_insn_and_split "*movsicc_umin" 1713 [(set (match_operand:SI 0 "arith_reg_dest" "=&r") 1714 (umin:SI (if_then_else:SI 1715 (eq (match_operand:SI 1 "arith_reg_operand" "r") 1716 (const_int 0)) 1717 (match_operand:SI 2 "arith_reg_or_0_operand" "rN") 1718 (match_operand:SI 3 "register_operand" "0")) 1719 (match_operand:SI 4 "arith_reg_or_0_operand" "r"))) 1720 (clobber (match_scratch:SI 5 "=&r"))] 1721 "TARGET_SHMEDIA && !can_create_pseudo_p ()" 1722 "#" 1723 "TARGET_SHMEDIA && reload_completed" 1724 [(pc)] 1725{ 1726 emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2], 1727 operands[3])); 1728 emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0])); 1729 emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4], 1730 operands[0])); 1731 DONE; 1732}) 1733 1734(define_insn "*movsicc_t_false" 1735 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 1736 (if_then_else (eq (reg:SI T_REG) (const_int 0)) 1737 (match_operand:SI 1 "general_movsrc_operand" "r,I08") 1738 (match_operand:SI 2 "arith_reg_operand" "0,0")))] 1739 "TARGET_PRETEND_CMOVE 1740 && (arith_reg_operand (operands[1], SImode) 1741 || (immediate_operand (operands[1], SImode) 1742 && satisfies_constraint_I08 (operands[1])))" 1743{ 1744 return "bt 0f" "\n" 1745 " mov %1,%0" "\n" 1746 "0:"; 1747} 1748 [(set_attr "type" "mt_group,arith") ;; poor approximation 1749 (set_attr "length" "4")]) 1750 1751(define_insn "*movsicc_t_true" 1752 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 1753 (if_then_else (ne (reg:SI T_REG) (const_int 0)) 1754 (match_operand:SI 1 "general_movsrc_operand" "r,I08") 1755 (match_operand:SI 2 "arith_reg_operand" "0,0")))] 1756 "TARGET_PRETEND_CMOVE 1757 && (arith_reg_operand (operands[1], SImode) 1758 || (immediate_operand (operands[1], SImode) 1759 && satisfies_constraint_I08 (operands[1])))" 1760{ 1761 return "bf 0f" "\n" 1762 " mov %1,%0" "\n" 1763 "0:"; 1764} 1765 [(set_attr "type" "mt_group,arith") ;; poor approximation 1766 (set_attr "length" "4")]) 1767 1768(define_expand "movsicc" 1769 [(set (match_operand:SI 0 "arith_reg_dest" "") 1770 (if_then_else:SI (match_operand 1 "comparison_operator" "") 1771 (match_operand:SI 2 "arith_reg_or_0_operand" "") 1772 (match_operand:SI 3 "arith_reg_operand" "")))] 1773 "TARGET_SHMEDIA || TARGET_PRETEND_CMOVE" 1774{ 1775 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE) 1776 && GET_MODE (XEXP (operands[1], 0)) == SImode 1777 && (TARGET_SHMEDIA 1778 || (REG_P (XEXP (operands[1], 0)) 1779 && REGNO (XEXP (operands[1], 0)) == T_REG)) 1780 && XEXP (operands[1], 1) == const0_rtx) 1781 ; 1782 1783 else if (TARGET_PRETEND_CMOVE) 1784 { 1785 enum rtx_code code = GET_CODE (operands[1]); 1786 enum rtx_code new_code = code; 1787 rtx op0 = XEXP (operands[1], 0); 1788 rtx op1 = XEXP (operands[1], 1); 1789 1790 if (! currently_expanding_to_rtl) 1791 FAIL; 1792 switch (code) 1793 { 1794 case LT: case LE: case LEU: case LTU: 1795 if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_INT) 1796 break; 1797 case NE: 1798 new_code = reverse_condition (code); 1799 break; 1800 case EQ: case GT: case GE: case GEU: case GTU: 1801 break; 1802 default: 1803 FAIL; 1804 } 1805 sh_emit_scc_to_t (new_code, op0, op1); 1806 operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode, 1807 gen_rtx_REG (SImode, T_REG), const0_rtx); 1808 } 1809 else 1810 { 1811 if (!can_create_pseudo_p ()) 1812 FAIL; 1813 1814 operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]), 1815 GET_CODE (operands[1]), 1816 XEXP (operands[1], 0), 1817 XEXP (operands[1], 1)); 1818 if (!operands[1]) 1819 FAIL; 1820 } 1821}) 1822 1823(define_expand "movqicc" 1824 [(set (match_operand:QI 0 "register_operand" "") 1825 (if_then_else:QI (match_operand 1 "comparison_operator" "") 1826 (match_operand:QI 2 "register_operand" "") 1827 (match_operand:QI 3 "register_operand" "")))] 1828 "TARGET_SHMEDIA" 1829{ 1830 operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0); 1831 operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0); 1832 operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0); 1833 emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3])); 1834 DONE; 1835}) 1836 1837;; ------------------------------------------------------------------------- 1838;; Addition instructions 1839;; ------------------------------------------------------------------------- 1840 1841(define_expand "adddi3" 1842 [(set (match_operand:DI 0 "arith_reg_operand") 1843 (plus:DI (match_operand:DI 1 "arith_reg_operand") 1844 (match_operand:DI 2 "arith_operand")))] 1845 "" 1846{ 1847 if (TARGET_SH1) 1848 { 1849 operands[2] = force_reg (DImode, operands[2]); 1850 emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2])); 1851 DONE; 1852 } 1853}) 1854 1855(define_insn "*adddi3_media" 1856 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") 1857 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r") 1858 (match_operand:DI 2 "arith_operand" "r,I10")))] 1859 "TARGET_SHMEDIA" 1860 "@ 1861 add %1, %2, %0 1862 addi %1, %2, %0" 1863 [(set_attr "type" "arith_media")]) 1864 1865(define_insn "*adddisi3_media" 1866 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0) 1867 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r") 1868 (match_operand:DI 2 "arith_operand" "r,I10")))] 1869 "TARGET_SHMEDIA" 1870 "@ 1871 add.l %1, %2, %0 1872 addi.l %1, %2, %0" 1873 [(set_attr "type" "arith_media") 1874 (set_attr "highpart" "ignore")]) 1875 1876(define_insn "adddi3z_media" 1877 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 1878 (zero_extend:DI 1879 (plus:SI (match_operand:SI 1 "extend_reg_operand" "r") 1880 (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))] 1881 "TARGET_SHMEDIA" 1882 "addz.l %1, %N2, %0" 1883 [(set_attr "type" "arith_media") 1884 (set_attr "highpart" "ignore")]) 1885 1886(define_insn_and_split "adddi3_compact" 1887 [(set (match_operand:DI 0 "arith_reg_dest") 1888 (plus:DI (match_operand:DI 1 "arith_reg_operand") 1889 (match_operand:DI 2 "arith_reg_operand"))) 1890 (clobber (reg:SI T_REG))] 1891 "TARGET_SH1" 1892 "#" 1893 "&& can_create_pseudo_p ()" 1894 [(const_int 0)] 1895{ 1896 emit_insn (gen_clrt ()); 1897 emit_insn (gen_addc (gen_lowpart (SImode, operands[0]), 1898 gen_lowpart (SImode, operands[1]), 1899 gen_lowpart (SImode, operands[2]))); 1900 emit_insn (gen_addc (gen_highpart (SImode, operands[0]), 1901 gen_highpart (SImode, operands[1]), 1902 gen_highpart (SImode, operands[2]))); 1903 DONE; 1904}) 1905 1906(define_insn "addc" 1907 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 1908 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0") 1909 (match_operand:SI 2 "arith_reg_operand" "r")) 1910 (reg:SI T_REG))) 1911 (set (reg:SI T_REG) 1912 (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))] 1913 "TARGET_SH1" 1914 "addc %2,%0" 1915 [(set_attr "type" "arith")]) 1916 1917;; A simplified version of the addc insn, where the exact value of the 1918;; T bit doesn't matter. This is easier for combine to pick up. 1919;; We allow a reg or 0 for one of the operands in order to be able to 1920;; do 'reg + T' sequences. 1921(define_insn_and_split "*addc" 1922 [(set (match_operand:SI 0 "arith_reg_dest") 1923 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand") 1924 (match_operand:SI 2 "arith_reg_or_0_operand")) 1925 (match_operand 3 "treg_set_expr"))) 1926 (clobber (reg:SI T_REG))] 1927 "TARGET_SH1 && can_create_pseudo_p ()" 1928 "#" 1929 "&& 1" 1930 [(const_int 0)] 1931{ 1932 sh_treg_insns ti = sh_split_treg_set_expr (operands[3], curr_insn); 1933 if (ti.has_trailing_nott ()) 1934 { 1935 if (operands[2] == const0_rtx) 1936 { 1937 /* op1 + 0 + (1 - T) = op1 + 1 - T = op1 - (-1) - T */ 1938 remove_insn (ti.trailing_nott ()); 1939 emit_insn (gen_subc (operands[0], operands[1], 1940 force_reg (SImode, GEN_INT (-1)))); 1941 DONE; 1942 } 1943 else if (!TARGET_SH2A) 1944 { 1945 /* op1 + op2 + (1 - T) = op1 - (0 - op2 - 1) - T = op1 - ~op2 - T 1946 On SH2A keep the nott insn, because nott-addc sequence doesn't 1947 mutate the inputs. */ 1948 remove_insn (ti.trailing_nott ()); 1949 rtx tmp = gen_reg_rtx (SImode); 1950 emit_insn (gen_one_cmplsi2 (tmp, operands[2])); 1951 emit_insn (gen_subc (operands[0], operands[1], tmp)); 1952 DONE; 1953 } 1954 } 1955 1956 emit_insn (gen_addc (operands[0], operands[1], 1957 force_reg (SImode, operands[2]))); 1958 DONE; 1959}) 1960 1961(define_insn_and_split "*addc" 1962 [(set (match_operand:SI 0 "arith_reg_dest") 1963 (plus:SI (plus:SI (match_operand 1 "treg_set_expr") 1964 (match_operand:SI 2 "arith_reg_operand")) 1965 (match_operand:SI 3 "arith_reg_operand"))) 1966 (clobber (reg:SI T_REG))] 1967 "TARGET_SH1 && can_create_pseudo_p ()" 1968 "#" 1969 "&& 1" 1970 [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3)) 1971 (match_dup 1))) 1972 (clobber (reg:SI T_REG))])]) 1973 1974(define_insn_and_split "*addc" 1975 [(set (match_operand:SI 0 "arith_reg_dest") 1976 (plus:SI (match_operand 1 "treg_set_expr") 1977 (plus:SI (match_operand:SI 2 "arith_reg_operand") 1978 (match_operand:SI 3 "arith_reg_operand")))) 1979 (clobber (reg:SI T_REG))] 1980 "TARGET_SH1 && can_create_pseudo_p ()" 1981 "#" 1982 "&& 1" 1983 [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3)) 1984 (match_dup 1))) 1985 (clobber (reg:SI T_REG))])]) 1986 1987;; Sometimes combine will try to do 'reg + (0-reg) + 1' if the *addc pattern 1988;; matched. Split this up into a simple sub add sequence, as this will save 1989;; us one sett insn. 1990(define_insn_and_split "*minus_plus_one" 1991 [(set (match_operand:SI 0 "arith_reg_dest" "") 1992 (plus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "") 1993 (match_operand:SI 2 "arith_reg_operand" "")) 1994 (const_int 1)))] 1995 "TARGET_SH1" 1996 "#" 1997 "&& 1" 1998 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2))) 1999 (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))]) 2000 2001;; Split 'reg + T' into 'reg + 0 + T' to utilize the addc insn. 2002;; If the 0 constant can be CSE-ed, this becomes a one instruction 2003;; operation, as opposed to sequences such as 2004;; movt r2 2005;; add r2,r3 2006;; 2007;; Even if the constant is not CSE-ed, a sequence such as 2008;; mov #0,r2 2009;; addc r2,r3 2010;; can be scheduled much better since the load of the constant can be 2011;; done earlier, before any comparison insns that store the result in 2012;; the T bit. 2013;; However, avoid things like 'reg + 1', which would expand into a 2014;; 3 insn sequence, instead of add #imm8. 2015(define_insn_and_split "*addc_t_r" 2016 [(set (match_operand:SI 0 "arith_reg_dest") 2017 (plus:SI (match_operand 1 "treg_set_expr_not_const01") 2018 (match_operand:SI 2 "arith_reg_operand"))) 2019 (clobber (reg:SI T_REG))] 2020 "TARGET_SH1 && can_create_pseudo_p ()" 2021 "#" 2022 "&& 1" 2023 [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (const_int 0)) 2024 (match_dup 1))) 2025 (clobber (reg:SI T_REG))])]) 2026 2027(define_insn_and_split "*addc_r_t" 2028 [(set (match_operand:SI 0 "arith_reg_dest") 2029 (plus:SI (match_operand:SI 1 "arith_reg_operand") 2030 (match_operand 2 "treg_set_expr_not_const01"))) 2031 (clobber (reg:SI T_REG))] 2032 "TARGET_SH1 && can_create_pseudo_p ()" 2033 "#" 2034 "&& 1" 2035 [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (const_int 0)) 2036 (match_dup 2))) 2037 (clobber (reg:SI T_REG))])]) 2038 2039;; Convert '2 * reg + T' into 'reg + reg + T'. 2040(define_insn_and_split "*addc_2r_t" 2041 [(set (match_operand:SI 0 "arith_reg_dest") 2042 (plus:SI (match_operand 1 "treg_set_expr") 2043 (mult:SI (match_operand:SI 2 "arith_reg_operand") 2044 (const_int 2)))) 2045 (clobber (reg:SI T_REG))] 2046 "TARGET_SH1 && can_create_pseudo_p ()" 2047 "#" 2048 "&& 1" 2049 [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 2)) 2050 (match_dup 1))) 2051 (clobber (reg:SI T_REG))])]) 2052 2053(define_insn_and_split "*addc_2r_t" 2054 [(set (match_operand:SI 0 "arith_reg_dest") 2055 (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand") 2056 (const_int 2)) 2057 (match_operand 2 "treg_set_expr"))) 2058 (clobber (reg:SI T_REG))] 2059 "TARGET_SH1 && can_create_pseudo_p ()" 2060 "#" 2061 "&& 1" 2062 [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (match_dup 1)) 2063 (match_dup 2))) 2064 (clobber (reg:SI T_REG))])]) 2065 2066;; Convert '(op2 + T) - op3' into 'op2 + (-op3) + T' 2067(define_insn_and_split "*addc_negreg_t" 2068 [(set (match_operand:SI 0 "arith_reg_dest") 2069 (minus:SI (plus:SI (match_operand 1 "treg_set_expr") 2070 (match_operand:SI 2 "arith_reg_operand")) 2071 (match_operand:SI 3 "arith_reg_operand"))) 2072 (clobber (reg:SI T_REG))] 2073 "TARGET_SH1 && can_create_pseudo_p ()" 2074 "#" 2075 "&& 1" 2076 [(set (match_dup 4) (neg:SI (match_dup 3))) 2077 (parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 4)) 2078 (match_dup 1))) 2079 (clobber (reg:SI T_REG))])] 2080{ 2081 operands[4] = gen_reg_rtx (SImode); 2082}) 2083 2084(define_expand "addsi3" 2085 [(set (match_operand:SI 0 "arith_reg_dest") 2086 (plus:SI (match_operand:SI 1 "arith_reg_operand") 2087 (match_operand:SI 2 "arith_or_int_operand")))] 2088 "" 2089{ 2090 if (TARGET_SH1 && !arith_operand (operands[2], SImode)) 2091 { 2092 if (!sh_lra_p () || reg_overlap_mentioned_p (operands[0], operands[1])) 2093 { 2094 emit_insn (gen_addsi3_scr (operands[0], operands[1], operands[2])); 2095 DONE; 2096 } 2097 } 2098}) 2099 2100(define_insn "addsi3_media" 2101 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 2102 (plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r") 2103 (match_operand:SI 2 "arith_operand" "r,I10")))] 2104 "TARGET_SHMEDIA" 2105 "@ 2106 add.l %1, %2, %0 2107 addi.l %1, %2, %0" 2108 [(set_attr "type" "arith_media") 2109 (set_attr "highpart" "ignore")]) 2110 2111(define_insn "addsidi3_media" 2112 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") 2113 (sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand" 2114 "%r,r") 2115 (match_operand:SI 2 "arith_operand" 2116 "r,I10"))))] 2117 "TARGET_SHMEDIA" 2118 "@ 2119 add.l %1, %2, %0 2120 addi.l %1, %2, %0" 2121 [(set_attr "type" "arith_media") 2122 (set_attr "highpart" "ignore")]) 2123 2124;; The *addsi3_compact is made an insn_and_split and accepts actually 2125;; impossible constraints to make LRA's register elimination work well on SH. 2126;; The problem is that LRA expects something like 2127;; (set rA (plus rB (const_int N))) 2128;; to work. We can do that, but we have to split out an additional reg-reg 2129;; copy or constant load before the actual add insn. 2130;; Use u constraint for that case to avoid the invalid value in the stack 2131;; pointer. 2132;; This also results in better code when LRA is not used. However, we have 2133;; to use different sets of patterns and the order of these patterns is 2134;; important. 2135;; In some cases the constant zero might end up in operands[2] of the 2136;; patterns. We have to accept that and convert it into a reg-reg move. 2137(define_insn_and_split "*addsi3_compact_lra" 2138 [(set (match_operand:SI 0 "arith_reg_dest" "=r,&u") 2139 (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0,r") 2140 (match_operand:SI 2 "arith_or_int_operand" "rI08,rn")))] 2141 "TARGET_SH1 && sh_lra_p () 2142 && (! reg_overlap_mentioned_p (operands[0], operands[1]) 2143 || arith_operand (operands[2], SImode))" 2144 "@ 2145 add %2,%0 2146 #" 2147 "&& reload_completed 2148 && ! reg_overlap_mentioned_p (operands[0], operands[1])" 2149 [(set (match_dup 0) (match_dup 2)) 2150 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))] 2151{ 2152 /* Prefer 'mov r0,r1; add #imm8,r1' over 'mov #imm8,r1; add r0,r1' */ 2153 if (satisfies_constraint_I08 (operands[2])) 2154 std::swap (operands[1], operands[2]); 2155} 2156 [(set_attr "type" "arith")]) 2157 2158(define_insn_and_split "addsi3_scr" 2159 [(set (match_operand:SI 0 "arith_reg_dest" "=r,&u,&u") 2160 (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0,r,r") 2161 (match_operand:SI 2 "arith_or_int_operand" "rI08,r,n"))) 2162 (clobber (match_scratch:SI 3 "=X,X,&u"))] 2163 "TARGET_SH1" 2164 "@ 2165 add %2,%0 2166 # 2167 #" 2168 "&& reload_completed" 2169 [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))] 2170{ 2171 if (operands[2] == const0_rtx) 2172 { 2173 emit_move_insn (operands[0], operands[1]); 2174 DONE; 2175 } 2176 2177 if (CONST_INT_P (operands[2]) && !satisfies_constraint_I08 (operands[2])) 2178 { 2179 if (reg_overlap_mentioned_p (operands[0], operands[1])) 2180 { 2181 emit_move_insn (operands[3], operands[2]); 2182 emit_move_insn (operands[0], operands[1]); 2183 operands[2] = operands[3]; 2184 } 2185 else 2186 { 2187 emit_move_insn (operands[0], operands[2]); 2188 operands[2] = operands[1]; 2189 } 2190 } 2191 else if (!reg_overlap_mentioned_p (operands[0], operands[1])) 2192 { 2193 if (!reg_overlap_mentioned_p (operands[0], operands[2])) 2194 emit_move_insn (operands[0], operands[1]); 2195 else 2196 operands[2] = operands[1]; 2197 } 2198} 2199 [(set_attr "type" "arith")]) 2200 2201;; Old reload might generate add insns directly (not through the expander) for 2202;; address register calculations when reloading, in which case it won't try 2203;; the addsi_scr pattern. Because reload will sometimes try to validate 2204;; the generated insns and their constraints, this pattern must be 2205;; recognizable during and after reload. However, when reload generates 2206;; address register calculations for the stack pointer, we don't allow this 2207;; pattern. This will make reload prefer using indexed @(reg + reg) address 2208;; modes when the displacement of a @(disp + reg) doesn't fit. 2209(define_insn_and_split "*addsi3" 2210 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 2211 (plus:SI (match_operand:SI 1 "arith_reg_operand" "r") 2212 (match_operand:SI 2 "arith_or_int_operand" "rn")))] 2213 "TARGET_SH1 && !sh_lra_p () 2214 && (reload_completed || reload_in_progress) 2215 && !reg_overlap_mentioned_p (operands[0], operands[1]) 2216 && (!reload_in_progress 2217 || ((!REG_P (operands[1]) || REGNO (operands[1]) != SP_REG) 2218 && (!REG_P (operands[2]) || REGNO (operands[2]) != SP_REG)))" 2219 "#" 2220 "&& 1" 2221 [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))] 2222{ 2223 if (operands[2] == const0_rtx) 2224 { 2225 emit_move_insn (operands[0], operands[1]); 2226 DONE; 2227 } 2228 2229 if (CONST_INT_P (operands[2])) 2230 { 2231 if (satisfies_constraint_I08 (operands[2])) 2232 emit_move_insn (operands[0], operands[1]); 2233 else 2234 { 2235 emit_move_insn (operands[0], operands[2]); 2236 operands[2] = operands[1]; 2237 } 2238 } 2239 else if (!reg_overlap_mentioned_p (operands[0], operands[2])) 2240 emit_move_insn (operands[0], operands[1]); 2241 else 2242 operands[2] = operands[1]; 2243}) 2244 2245(define_insn_and_split "*addsi3" 2246 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 2247 (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0,r") 2248 (match_operand:SI 2 "arith_operand" "rI08,Z")))] 2249 "TARGET_SH1 && !sh_lra_p ()" 2250 "@ 2251 add %2,%0 2252 #" 2253 "&& operands[2] == const0_rtx" 2254 [(set (match_dup 0) (match_dup 1))] 2255{ 2256} 2257 [(set_attr "type" "arith")]) 2258 2259;; ------------------------------------------------------------------------- 2260;; Subtraction instructions 2261;; ------------------------------------------------------------------------- 2262 2263(define_expand "subdi3" 2264 [(set (match_operand:DI 0 "arith_reg_operand" "") 2265 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "") 2266 (match_operand:DI 2 "arith_reg_operand" "")))] 2267 "" 2268{ 2269 if (TARGET_SH1) 2270 { 2271 operands[1] = force_reg (DImode, operands[1]); 2272 emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2])); 2273 DONE; 2274 } 2275}) 2276 2277(define_insn "*subdi3_media" 2278 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 2279 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN") 2280 (match_operand:DI 2 "arith_reg_operand" "r")))] 2281 "TARGET_SHMEDIA" 2282 "sub %N1, %2, %0" 2283 [(set_attr "type" "arith_media")]) 2284 2285(define_insn "subdisi3_media" 2286 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0) 2287 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN") 2288 (match_operand:DI 2 "arith_reg_operand" "r")))] 2289 "TARGET_SHMEDIA" 2290 "sub.l %N1, %2, %0" 2291 [(set_attr "type" "arith_media") 2292 (set_attr "highpart" "ignore")]) 2293 2294(define_insn_and_split "subdi3_compact" 2295 [(set (match_operand:DI 0 "arith_reg_dest") 2296 (minus:DI (match_operand:DI 1 "arith_reg_operand") 2297 (match_operand:DI 2 "arith_reg_operand"))) 2298 (clobber (reg:SI T_REG))] 2299 "TARGET_SH1" 2300 "#" 2301 "&& can_create_pseudo_p ()" 2302 [(const_int 0)] 2303{ 2304 emit_insn (gen_clrt ()); 2305 emit_insn (gen_subc (gen_lowpart (SImode, operands[0]), 2306 gen_lowpart (SImode, operands[1]), 2307 gen_lowpart (SImode, operands[2]))); 2308 emit_insn (gen_subc (gen_highpart (SImode, operands[0]), 2309 gen_highpart (SImode, operands[1]), 2310 gen_highpart (SImode, operands[2]))); 2311 DONE; 2312}) 2313 2314(define_insn "subc" 2315 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 2316 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0") 2317 (match_operand:SI 2 "arith_reg_operand" "r")) 2318 (reg:SI T_REG))) 2319 (set (reg:SI T_REG) 2320 (gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2)) 2321 (reg:SI T_REG)) 2322 (match_dup 1)))] 2323 "TARGET_SH1" 2324 "subc %2,%0" 2325 [(set_attr "type" "arith")]) 2326 2327;; A simplified version of the subc insn, where the exact value of the 2328;; T bit doesn't matter. This is easier for combine to pick up. 2329;; We allow a reg or 0 for one of the operands in order to be able to 2330;; do 'reg - T' sequences. Reload will load the constant 0 into the reg 2331;; as needed. 2332(define_insn_and_split "*subc" 2333 [(set (match_operand:SI 0 "arith_reg_dest") 2334 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand") 2335 (match_operand:SI 2 "arith_reg_or_0_operand")) 2336 (match_operand 3 "treg_set_expr"))) 2337 (clobber (reg:SI T_REG))] 2338 "TARGET_SH1 && can_create_pseudo_p ()" 2339 "#" 2340 "&& 1" 2341 [(const_int 0)] 2342{ 2343 sh_treg_insns ti = sh_split_treg_set_expr (operands[3], curr_insn); 2344 if (ti.has_trailing_nott ()) 2345 { 2346 if (operands[2] == const0_rtx) 2347 { 2348 /* op1 - (1 - T) = op1 - 1 + T = op1 + (-1) + T */ 2349 remove_insn (ti.trailing_nott ()); 2350 emit_insn (gen_addc (operands[0], operands[1], 2351 force_reg (SImode, GEN_INT (-1)))); 2352 DONE; 2353 } 2354 else if (!TARGET_SH2A) 2355 { 2356 /* op1 - op2 - (1 - T) = op1 + (0 - op2 - 1) + T = op1 + ~op2 + T 2357 On SH2A keep the nott insn, because nott-subc sequence doesn't 2358 mutate the inputs. */ 2359 remove_insn (ti.trailing_nott ()); 2360 rtx tmp = gen_reg_rtx (SImode); 2361 emit_insn (gen_one_cmplsi2 (tmp, operands[2])); 2362 emit_insn (gen_addc (operands[0], operands[1], tmp)); 2363 DONE; 2364 } 2365 } 2366 2367 emit_insn (gen_subc (operands[0], operands[1], 2368 force_reg (SImode, operands[2]))); 2369 DONE; 2370}) 2371 2372;; Convert reg - T - reg = reg - reg - T 2373(define_insn_and_split "*subc" 2374 [(set (match_operand:SI 0 "arith_reg_dest") 2375 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand") 2376 (match_operand 2 "treg_set_expr")) 2377 (match_operand:SI 3 "arith_reg_operand"))) 2378 (clobber (reg:SI T_REG))] 2379 "TARGET_SH1 && can_create_pseudo_p ()" 2380 "#" 2381 "&& 1" 2382 [(parallel [(set (match_dup 0) 2383 (minus:SI (minus:SI (match_dup 1) (match_dup 3)) 2384 (match_dup 2))) 2385 (clobber (reg:SI T_REG))])]) 2386 2387;; Split reg - reg - 1 into a sett subc sequence, as it can be scheduled 2388;; better, if the sett insn can be done early. 2389;; Notice that combine turns 'a - b - 1' into 'a + (~b)'. 2390(define_insn_and_split "*subc" 2391 [(set (match_operand:SI 0 "arith_reg_dest" "") 2392 (plus:SI (not:SI (match_operand:SI 1 "arith_reg_operand" "")) 2393 (match_operand:SI 2 "arith_reg_operand" ""))) 2394 (clobber (reg:SI T_REG))] 2395 "TARGET_SH1 && can_create_pseudo_p ()" 2396 "#" 2397 "&& 1" 2398 [(parallel [(set (match_dup 0) 2399 (minus:SI (minus:SI (match_dup 2) (match_dup 1)) 2400 (const_int 1))) 2401 (clobber (reg:SI T_REG))])]) 2402 2403;; Split 'reg - T' into 'reg - 0 - T' to utilize the subc insn. 2404;; If the 0 constant can be CSE-ed, this becomes a one instruction 2405;; operation, as opposed to sequences such as 2406;; movt r2 2407;; sub r2,r3 2408;; 2409;; Even if the constant is not CSE-ed, a sequence such as 2410;; mov #0,r2 2411;; subc r2,r3 2412;; can be scheduled much better since the load of the constant can be 2413;; done earlier, before any comparison insns that store the result in 2414;; the T bit. 2415;; However, avoid things like 'reg - 1', which would expand into a 2416;; 3 insn sequence, instead of add #imm8. 2417(define_insn_and_split "*subc" 2418 [(set (match_operand:SI 0 "arith_reg_dest" "") 2419 (minus:SI (match_operand:SI 1 "arith_reg_operand" "") 2420 (match_operand 2 "treg_set_expr_not_const01"))) 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) (const_int 0)) 2427 (match_dup 2))) 2428 (clobber (reg:SI T_REG))])]) 2429 2430;; Convert 2431;; (1 - T) - op2 = 1 - op2 - T 2432(define_insn_and_split "*subc_negt_reg" 2433 [(set (match_operand:SI 0 "arith_reg_dest") 2434 (minus:SI (match_operand 1 "treg_set_expr_not_const01") 2435 (match_operand:SI 2 "arith_reg_operand"))) 2436 (clobber (reg:SI T_REG))] 2437 "TARGET_SH1 && can_create_pseudo_p ()" 2438 "#" 2439 "&& 1" 2440 [(const_int 0)] 2441{ 2442 sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn); 2443 if (ti.remove_trailing_nott ()) 2444 { 2445 /* (1 - T) - op2 = 1 - op2 - T */ 2446 emit_insn (gen_subc (operands[0], 2447 force_reg (SImode, GEN_INT (1)), operands[2])); 2448 } 2449 else 2450 { 2451 /* T - op2: use movt,sub sequence. */ 2452 rtx tmp = gen_reg_rtx (SImode); 2453 emit_insn (gen_movt (tmp, get_t_reg_rtx ())); 2454 emit_insn (gen_subsi3 (operands[0], tmp, operands[2])); 2455 } 2456 DONE; 2457}) 2458 2459;; Convert 2460;; op1 - (1 - T) + op3 = op1 - 1 + T + op3 2461;; (op1 - T) + op3 = op1 - (-op3) - T 2462(define_insn_and_split "*subc_negreg_t" 2463 [(set (match_operand:SI 0 "arith_reg_dest") 2464 (plus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand") 2465 (match_operand 2 "treg_set_expr")) 2466 (match_operand:SI 3 "arith_reg_operand"))) 2467 (clobber (reg:SI T_REG))] 2468 "TARGET_SH1 && can_create_pseudo_p ()" 2469 "#" 2470 "&& 1" 2471 [(const_int 0)] 2472{ 2473 sh_treg_insns ti = sh_split_treg_set_expr (operands[2], curr_insn); 2474 if (ti.remove_trailing_nott ()) 2475 { 2476 /* op1 - (1 - T) + op3 = (op1 - 1) + op3 + T */ 2477 rtx tmp = gen_reg_rtx (SImode); 2478 emit_insn (gen_addsi3 (tmp, operands[1], GEN_INT (-1))); 2479 emit_insn (gen_addc (operands[0], tmp, operands[3])); 2480 } 2481 else 2482 { 2483 /* (op1 - T) + op3' = 'op1 - (-op3) - T */ 2484 rtx tmp = gen_reg_rtx (SImode); 2485 emit_insn (gen_negsi2 (tmp, operands[3])); 2486 emit_insn (gen_subc (operands[0], operands[1], tmp)); 2487 } 2488 DONE; 2489}) 2490 2491(define_insn "*subsi3_internal" 2492 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 2493 (minus:SI (match_operand:SI 1 "arith_reg_operand" "0") 2494 (match_operand:SI 2 "arith_reg_operand" "r")))] 2495 "TARGET_SH1" 2496 "sub %2,%0" 2497 [(set_attr "type" "arith")]) 2498 2499(define_insn_and_split "*subsi3_media" 2500 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 2501 (minus:SI (match_operand:SI 1 "minuend_operand" "rN") 2502 (match_operand:SI 2 "extend_reg_operand" "r")))] 2503 "TARGET_SHMEDIA 2504 && (operands[1] != constm1_rtx 2505 || (GET_CODE (operands[2]) != TRUNCATE 2506 && GET_CODE (operands[2]) != SUBREG))" 2507 "sub.l %N1, %2, %0" 2508 "operands[1] == constm1_rtx" 2509 [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))] 2510 "" 2511 [(set_attr "type" "arith_media") 2512 (set_attr "highpart" "ignore")]) 2513 2514(define_split 2515 [(set (match_operand:SI 0 "arith_reg_dest" "") 2516 (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1 2517 "general_extend_operand" 2518 "") 0)) 0)))] 2519 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN" 2520 [(set (match_dup 0) (zero_extend:SI (match_dup 1))) 2521 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))] 2522 "") 2523 2524(define_split 2525 [(set (match_operand:SI 0 "arith_reg_dest" "") 2526 (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1 2527 "general_extend_operand" 2528 "") 0)) 3)))] 2529 "TARGET_SHMEDIA && TARGET_BIG_ENDIAN" 2530 [(set (match_dup 0) (zero_extend:SI (match_dup 1))) 2531 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))] 2532 "") 2533 2534;; Convert 2535;; constant - reg 2536;; to 2537;; neg reg 2538;; add reg, #const 2539;; since this will sometimes save one instruction. 2540;; Otherwise we might get a sequence like 2541;; mov #const, rY 2542;; sub rY, rX 2543;; mov rX, rY 2544;; if the source and dest regs are the same. 2545(define_expand "subsi3" 2546 [(set (match_operand:SI 0 "arith_reg_operand" "") 2547 (minus:SI (match_operand:SI 1 "arith_operand" "") 2548 (match_operand:SI 2 "arith_reg_operand" "")))] 2549 "" 2550{ 2551 if (TARGET_SH1 && CONST_INT_P (operands[1])) 2552 { 2553 emit_insn (gen_negsi2 (operands[0], operands[2])); 2554 emit_insn (gen_addsi3 (operands[0], operands[0], operands[1])); 2555 DONE; 2556 } 2557 if (TARGET_SHMEDIA) 2558 { 2559 if (!can_create_pseudo_p () 2560 && ! arith_reg_or_0_operand (operands[1], SImode)) 2561 FAIL; 2562 if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG) 2563 operands[1] = force_reg (SImode, operands[1]); 2564 } 2565}) 2566 2567;; ------------------------------------------------------------------------- 2568;; Division instructions 2569;; ------------------------------------------------------------------------- 2570 2571;; We take advantage of the library routines which don't clobber as many 2572;; registers as a normal function call would. 2573 2574;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it 2575;; also has an effect on the register that holds the address of the sfunc. 2576;; To make this work, we have an extra dummy insn that shows the use 2577;; of this register for reorg. 2578 2579(define_insn "use_sfunc_addr" 2580 [(set (reg:SI PR_REG) 2581 (unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))] 2582 "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])" 2583 "" 2584 [(set_attr "length" "0")]) 2585 2586(define_insn "udivsi3_sh2a" 2587 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 2588 (udiv:SI (match_operand:SI 1 "arith_reg_operand" "0") 2589 (match_operand:SI 2 "arith_reg_operand" "z")))] 2590 "TARGET_SH2A" 2591 "divu %2,%1" 2592 [(set_attr "type" "arith") 2593 (set_attr "in_delay_slot" "no")]) 2594 2595;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than 2596;; hard register 0. If we used hard register 0, then the next instruction 2597;; would be a move from hard register 0 to a pseudo-reg. If the pseudo-reg 2598;; gets allocated to a stack slot that needs its address reloaded, then 2599;; there is nothing to prevent reload from using r0 to reload the address. 2600;; This reload would clobber the value in r0 we are trying to store. 2601;; If we let reload allocate r0, then this problem can never happen. 2602(define_insn "udivsi3_i1" 2603 [(set (match_operand:SI 0 "register_operand" "=z") 2604 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2605 (clobber (reg:SI T_REG)) 2606 (clobber (reg:SI PR_REG)) 2607 (clobber (reg:SI R1_REG)) 2608 (clobber (reg:SI R4_REG)) 2609 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 2610 "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1" 2611 "jsr @%1%#" 2612 [(set_attr "type" "sfunc") 2613 (set_attr "needs_delay_slot" "yes")]) 2614 2615; Since shmedia-nofpu code could be linked against shcompact code, and 2616; the udivsi3 libcall has the same name, we must consider all registers 2617; clobbered that are in the union of the registers clobbered by the 2618; shmedia and the shcompact implementation. Note, if the shcompact 2619; implementation actually used shcompact code, we'd need to clobber 2620; also r23 and fr23. 2621(define_insn "udivsi3_i1_media" 2622 [(set (match_operand:SI 0 "register_operand" "=z") 2623 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2624 (clobber (reg:SI T_MEDIA_REG)) 2625 (clobber (reg:SI PR_MEDIA_REG)) 2626 (clobber (reg:SI R20_REG)) 2627 (clobber (reg:SI R21_REG)) 2628 (clobber (reg:SI R22_REG)) 2629 (clobber (reg:DI TR0_REG)) 2630 (clobber (reg:DI TR1_REG)) 2631 (clobber (reg:DI TR2_REG)) 2632 (use (match_operand 1 "target_reg_operand" "b"))] 2633 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)" 2634 "blink %1, r18" 2635 [(set_attr "type" "sfunc") 2636 (set_attr "needs_delay_slot" "yes")]) 2637 2638(define_expand "udivsi3_i4_media" 2639 [(set (match_dup 3) 2640 (zero_extend:DI (match_operand:SI 1 "register_operand" ""))) 2641 (set (match_dup 4) 2642 (zero_extend:DI (match_operand:SI 2 "register_operand" ""))) 2643 (set (match_dup 5) (float:DF (match_dup 3))) 2644 (set (match_dup 6) (float:DF (match_dup 4))) 2645 (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6))) 2646 (set (match_dup 8) (fix:DI (match_dup 7))) 2647 (set (match_operand:SI 0 "register_operand" "") 2648 (truncate:SI (match_dup 8)))] 2649 "TARGET_SHMEDIA_FPU" 2650{ 2651 operands[3] = gen_reg_rtx (DImode); 2652 operands[4] = gen_reg_rtx (DImode); 2653 operands[5] = gen_reg_rtx (DFmode); 2654 operands[6] = gen_reg_rtx (DFmode); 2655 operands[7] = gen_reg_rtx (DFmode); 2656 operands[8] = gen_reg_rtx (DImode); 2657}) 2658 2659(define_insn "udivsi3_i4" 2660 [(set (match_operand:SI 0 "register_operand" "=y") 2661 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2662 (clobber (reg:SI T_REG)) 2663 (clobber (reg:SI PR_REG)) 2664 (clobber (reg:DF DR0_REG)) 2665 (clobber (reg:DF DR2_REG)) 2666 (clobber (reg:DF DR4_REG)) 2667 (clobber (reg:SI R0_REG)) 2668 (clobber (reg:SI R1_REG)) 2669 (clobber (reg:SI R4_REG)) 2670 (clobber (reg:SI R5_REG)) 2671 (clobber (reg:SI FPSCR_STAT_REG)) 2672 (use (match_operand:SI 1 "arith_reg_operand" "r")) 2673 (use (reg:SI FPSCR_MODES_REG))] 2674 "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE" 2675 "jsr @%1%#" 2676 [(set_attr "type" "sfunc") 2677 (set_attr "fp_mode" "double") 2678 (set_attr "needs_delay_slot" "yes")]) 2679 2680(define_insn "udivsi3_i4_single" 2681 [(set (match_operand:SI 0 "register_operand" "=y") 2682 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2683 (clobber (reg:SI T_REG)) 2684 (clobber (reg:SI PR_REG)) 2685 (clobber (reg:DF DR0_REG)) 2686 (clobber (reg:DF DR2_REG)) 2687 (clobber (reg:DF DR4_REG)) 2688 (clobber (reg:SI R0_REG)) 2689 (clobber (reg:SI R1_REG)) 2690 (clobber (reg:SI R4_REG)) 2691 (clobber (reg:SI R5_REG)) 2692 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 2693 "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT) 2694 && TARGET_FPU_SINGLE" 2695 "jsr @%1%#" 2696 [(set_attr "type" "sfunc") 2697 (set_attr "needs_delay_slot" "yes")]) 2698 2699(define_insn "udivsi3_i4_int" 2700 [(set (match_operand:SI 0 "register_operand" "=z") 2701 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2702 (clobber (reg:SI T_REG)) 2703 (clobber (reg:SI R1_REG)) 2704 (clobber (reg:SI PR_REG)) 2705 (clobber (reg:SI MACH_REG)) 2706 (clobber (reg:SI MACL_REG)) 2707 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 2708 "TARGET_SH1" 2709 "jsr @%1%#" 2710 [(set_attr "type" "sfunc") 2711 (set_attr "needs_delay_slot" "yes")]) 2712 2713 2714(define_expand "udivsi3" 2715 [(set (match_dup 3) (symbol_ref:SI "__udivsi3")) 2716 (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" "")) 2717 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" "")) 2718 (parallel [(set (match_operand:SI 0 "register_operand" "") 2719 (udiv:SI (reg:SI R4_REG) 2720 (reg:SI R5_REG))) 2721 (clobber (reg:SI T_REG)) 2722 (clobber (reg:SI PR_REG)) 2723 (clobber (reg:SI R4_REG)) 2724 (use (match_dup 3))])] 2725 "" 2726{ 2727 rtx last; 2728 2729 operands[3] = gen_reg_rtx (Pmode); 2730 /* Emit the move of the address to a pseudo outside of the libcall. */ 2731 if (TARGET_DIVIDE_CALL_TABLE) 2732 { 2733 /* libgcc2:__udivmoddi4 is not supposed to use an actual division, since 2734 that causes problems when the divide code is supposed to come from a 2735 separate library. Division by zero is undefined, so dividing 1 can be 2736 implemented by comparing with the divisor. */ 2737 if (operands[1] == const1_rtx && currently_expanding_to_rtl) 2738 { 2739 rtx test = gen_rtx_GEU (VOIDmode, operands[1], operands[2]); 2740 emit_insn (gen_cstoresi4 (operands[0], test, 2741 operands[1], operands[2])); 2742 DONE; 2743 } 2744 else if (operands[2] == const0_rtx) 2745 { 2746 emit_move_insn (operands[0], operands[2]); 2747 DONE; 2748 } 2749 function_symbol (operands[3], "__udivsi3_i4i", SFUNC_GOT); 2750 last = gen_udivsi3_i4_int (operands[0], operands[3]); 2751 } 2752 else if (TARGET_DIVIDE_CALL_FP) 2753 { 2754 function_symbol (operands[3], "__udivsi3_i4", SFUNC_STATIC); 2755 if (TARGET_FPU_SINGLE) 2756 last = gen_udivsi3_i4_single (operands[0], operands[3]); 2757 else 2758 last = gen_udivsi3_i4 (operands[0], operands[3]); 2759 } 2760 else if (TARGET_SHMEDIA_FPU) 2761 { 2762 operands[1] = force_reg (SImode, operands[1]); 2763 operands[2] = force_reg (SImode, operands[2]); 2764 emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2])); 2765 DONE; 2766 } 2767 else if (TARGET_SH2A) 2768 { 2769 operands[1] = force_reg (SImode, operands[1]); 2770 operands[2] = force_reg (SImode, operands[2]); 2771 emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2])); 2772 DONE; 2773 } 2774 else if (TARGET_SH5) 2775 { 2776 function_symbol (operands[3], 2777 TARGET_FPU_ANY ? "__udivsi3_i4" : "__udivsi3", 2778 SFUNC_STATIC); 2779 2780 if (TARGET_SHMEDIA) 2781 last = gen_udivsi3_i1_media (operands[0], operands[3]); 2782 else if (TARGET_FPU_ANY) 2783 last = gen_udivsi3_i4_single (operands[0], operands[3]); 2784 else 2785 last = gen_udivsi3_i1 (operands[0], operands[3]); 2786 } 2787 else 2788 { 2789 function_symbol (operands[3], "__udivsi3", SFUNC_STATIC); 2790 last = gen_udivsi3_i1 (operands[0], operands[3]); 2791 } 2792 emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]); 2793 emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]); 2794 emit_insn (last); 2795 DONE; 2796}) 2797 2798(define_insn "divsi3_sh2a" 2799 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 2800 (div:SI (match_operand:SI 1 "arith_reg_operand" "0") 2801 (match_operand:SI 2 "arith_reg_operand" "z")))] 2802 "TARGET_SH2A" 2803 "divs %2,%1" 2804 [(set_attr "type" "arith") 2805 (set_attr "in_delay_slot" "no")]) 2806 2807(define_insn "divsi3_i1" 2808 [(set (match_operand:SI 0 "register_operand" "=z") 2809 (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2810 (clobber (reg:SI T_REG)) 2811 (clobber (reg:SI PR_REG)) 2812 (clobber (reg:SI R1_REG)) 2813 (clobber (reg:SI R2_REG)) 2814 (clobber (reg:SI R3_REG)) 2815 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 2816 "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1" 2817 "jsr @%1%#" 2818 [(set_attr "type" "sfunc") 2819 (set_attr "needs_delay_slot" "yes")]) 2820 2821(define_insn "divsi3_i1_media" 2822 [(set (match_operand:SI 0 "register_operand" "=z") 2823 (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2824 (clobber (reg:SI T_MEDIA_REG)) 2825 (clobber (reg:SI PR_MEDIA_REG)) 2826 (clobber (reg:SI R1_REG)) 2827 (clobber (reg:SI R20_REG)) 2828 (clobber (reg:SI R21_REG)) 2829 (clobber (reg:SI TR0_REG)) 2830 (use (match_operand 1 "target_reg_operand" "b"))] 2831 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)" 2832 "blink %1, r18" 2833 [(set_attr "type" "sfunc")]) 2834 2835(define_insn "divsi3_media_2" 2836 [(set (match_operand:SI 0 "register_operand" "=z") 2837 (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2838 (clobber (reg:SI T_MEDIA_REG)) 2839 (clobber (reg:SI PR_MEDIA_REG)) 2840 (clobber (reg:SI R1_REG)) 2841 (clobber (reg:SI R21_REG)) 2842 (clobber (reg:SI TR0_REG)) 2843 (use (reg:SI R20_REG)) 2844 (use (match_operand 1 "target_reg_operand" "b"))] 2845 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)" 2846 "blink %1, r18" 2847 [(set_attr "type" "sfunc")]) 2848 2849;; This pattern acts as a placeholder for -mdiv=inv:call to carry 2850;; hard reg clobbers and data dependencies that we need when we want 2851;; to rematerialize the division into a call. 2852(define_insn_and_split "divsi_inv_call" 2853 [(set (match_operand:SI 0 "register_operand" "=r") 2854 (div:SI (match_operand:SI 1 "register_operand" "r") 2855 (match_operand:SI 2 "register_operand" "r"))) 2856 (clobber (reg:SI R4_REG)) 2857 (clobber (reg:SI R5_REG)) 2858 (clobber (reg:SI T_MEDIA_REG)) 2859 (clobber (reg:SI PR_MEDIA_REG)) 2860 (clobber (reg:SI R1_REG)) 2861 (clobber (reg:SI R21_REG)) 2862 (clobber (reg:SI TR0_REG)) 2863 (clobber (reg:SI R20_REG)) 2864 (use (match_operand:SI 3 "register_operand" "r"))] 2865 "TARGET_SHMEDIA" 2866 "#" 2867 "&& (reload_in_progress || reload_completed)" 2868 [(set (match_dup 0) (match_dup 3))] 2869 "" 2870 [(set_attr "highpart" "must_split")]) 2871 2872;; This is the combiner pattern for -mdiv=inv:call . 2873(define_insn_and_split "*divsi_inv_call_combine" 2874 [(set (match_operand:SI 0 "register_operand" "=z") 2875 (div:SI (match_operand:SI 1 "register_operand" "r") 2876 (match_operand:SI 2 "register_operand" "r"))) 2877 (clobber (reg:SI R4_REG)) 2878 (clobber (reg:SI R5_REG)) 2879 (clobber (reg:SI T_MEDIA_REG)) 2880 (clobber (reg:SI PR_MEDIA_REG)) 2881 (clobber (reg:SI R1_REG)) 2882 (clobber (reg:SI R21_REG)) 2883 (clobber (reg:SI TR0_REG)) 2884 (clobber (reg:SI R20_REG)) 2885 (use (unspec:SI [(match_dup 1) 2886 (match_operand:SI 3 "" "") 2887 (unspec:SI [(match_operand:SI 4 "" "") 2888 (match_dup 3) 2889 (match_operand:DI 5 "" "")] 2890 UNSPEC_DIV_INV_M2) 2891 (match_operand:DI 6 "" "") 2892 (const_int 0) 2893 (const_int 0)] 2894 UNSPEC_DIV_INV_M3))] 2895 "TARGET_SHMEDIA" 2896 "#" 2897 "&& (reload_in_progress || reload_completed)" 2898 [(pc)] 2899{ 2900 const char *name = sh_divsi3_libfunc; 2901 enum sh_function_kind kind = SFUNC_GOT; 2902 rtx sym; 2903 2904 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]); 2905 emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]); 2906 while (TARGET_DIVIDE_INV_CALL2) 2907 { 2908 rtx x = operands[3]; 2909 2910 if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1) 2911 break; 2912 x = XVECEXP (x, 0, 0); 2913 name = "__sdivsi3_2"; 2914 kind = SFUNC_STATIC; 2915 emit_move_insn (gen_rtx_REG (DImode, R20_REG), x); 2916 break; 2917 } 2918 sym = function_symbol (NULL, name, kind); 2919 emit_insn (gen_divsi3_media_2 (operands[0], sym)); 2920 DONE; 2921} 2922 [(set_attr "highpart" "must_split")]) 2923 2924(define_expand "divsi3_i4_media" 2925 [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r"))) 2926 (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r"))) 2927 (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4))) 2928 (set (match_operand:SI 0 "register_operand" "=r") 2929 (fix:SI (match_dup 5)))] 2930 "TARGET_SHMEDIA_FPU" 2931{ 2932 operands[3] = gen_reg_rtx (DFmode); 2933 operands[4] = gen_reg_rtx (DFmode); 2934 operands[5] = gen_reg_rtx (DFmode); 2935}) 2936 2937(define_insn "divsi3_i4" 2938 [(set (match_operand:SI 0 "register_operand" "=y") 2939 (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2940 (clobber (reg:SI PR_REG)) 2941 (clobber (reg:DF DR0_REG)) 2942 (clobber (reg:DF DR2_REG)) 2943 (clobber (reg:SI FPSCR_STAT_REG)) 2944 (use (match_operand:SI 1 "arith_reg_operand" "r")) 2945 (use (reg:SI FPSCR_MODES_REG))] 2946 "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE" 2947 "jsr @%1%#" 2948 [(set_attr "type" "sfunc") 2949 (set_attr "fp_mode" "double") 2950 (set_attr "needs_delay_slot" "yes")]) 2951 2952(define_insn "divsi3_i4_single" 2953 [(set (match_operand:SI 0 "register_operand" "=y") 2954 (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2955 (clobber (reg:SI PR_REG)) 2956 (clobber (reg:DF DR0_REG)) 2957 (clobber (reg:DF DR2_REG)) 2958 (clobber (reg:SI R2_REG)) 2959 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 2960 "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT) 2961 && TARGET_FPU_SINGLE" 2962 "jsr @%1%#" 2963 [(set_attr "type" "sfunc") 2964 (set_attr "needs_delay_slot" "yes")]) 2965 2966(define_insn "divsi3_i4_int" 2967 [(set (match_operand:SI 0 "register_operand" "=z") 2968 (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) 2969 (clobber (reg:SI T_REG)) 2970 (clobber (reg:SI PR_REG)) 2971 (clobber (reg:SI R1_REG)) 2972 (clobber (reg:SI MACH_REG)) 2973 (clobber (reg:SI MACL_REG)) 2974 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 2975 "TARGET_SH1" 2976 "jsr @%1%#" 2977 [(set_attr "type" "sfunc") 2978 (set_attr "needs_delay_slot" "yes")]) 2979 2980(define_expand "divsi3" 2981 [(set (match_dup 3) (symbol_ref:SI "__sdivsi3")) 2982 (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" "")) 2983 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" "")) 2984 (parallel [(set (match_operand:SI 0 "register_operand" "") 2985 (div:SI (reg:SI R4_REG) 2986 (reg:SI R5_REG))) 2987 (clobber (reg:SI T_REG)) 2988 (clobber (reg:SI PR_REG)) 2989 (clobber (reg:SI R1_REG)) 2990 (clobber (reg:SI R2_REG)) 2991 (clobber (reg:SI R3_REG)) 2992 (use (match_dup 3))])] 2993 "" 2994{ 2995 rtx last; 2996 2997 operands[3] = gen_reg_rtx (Pmode); 2998 /* Emit the move of the address to a pseudo outside of the libcall. */ 2999 if (TARGET_DIVIDE_CALL_TABLE) 3000 { 3001 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT); 3002 last = gen_divsi3_i4_int (operands[0], operands[3]); 3003 } 3004 else if (TARGET_DIVIDE_CALL_FP) 3005 { 3006 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC); 3007 if (TARGET_FPU_SINGLE) 3008 last = gen_divsi3_i4_single (operands[0], operands[3]); 3009 else 3010 last = gen_divsi3_i4 (operands[0], operands[3]); 3011 } 3012 else if (TARGET_SH2A) 3013 { 3014 operands[1] = force_reg (SImode, operands[1]); 3015 operands[2] = force_reg (SImode, operands[2]); 3016 emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2])); 3017 DONE; 3018 } 3019 else if (TARGET_DIVIDE_INV) 3020 { 3021 rtx dividend = operands[1]; 3022 rtx divisor = operands[2]; 3023 rtx tab_base; 3024 rtx nsb_res = gen_reg_rtx (DImode); 3025 rtx norm64 = gen_reg_rtx (DImode); 3026 rtx tab_ix = gen_reg_rtx (DImode); 3027 rtx norm32 = gen_reg_rtx (SImode); 3028 rtx i92 = force_reg (DImode, GEN_INT (92)); 3029 rtx scratch0a = gen_reg_rtx (DImode); 3030 rtx scratch0b = gen_reg_rtx (DImode); 3031 rtx inv0 = gen_reg_rtx (SImode); 3032 rtx scratch1a = gen_reg_rtx (DImode); 3033 rtx scratch1b = gen_reg_rtx (DImode); 3034 rtx shift = gen_reg_rtx (DImode); 3035 rtx i2p27, i43; 3036 rtx inv1 = gen_reg_rtx (SImode); 3037 rtx scratch2a = gen_reg_rtx (DImode); 3038 rtx scratch2b = gen_reg_rtx (SImode); 3039 rtx inv2 = gen_reg_rtx (SImode); 3040 rtx scratch3a = gen_reg_rtx (DImode); 3041 rtx scratch3b = gen_reg_rtx (DImode); 3042 rtx scratch3c = gen_reg_rtx (DImode); 3043 rtx scratch3d = gen_reg_rtx (SImode); 3044 rtx scratch3e = gen_reg_rtx (DImode); 3045 rtx result = gen_reg_rtx (SImode); 3046 3047 if (! arith_reg_or_0_operand (dividend, SImode)) 3048 dividend = force_reg (SImode, dividend); 3049 if (! arith_reg_operand (divisor, SImode)) 3050 divisor = force_reg (SImode, divisor); 3051 if (flag_pic && Pmode != DImode) 3052 { 3053 tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table"); 3054 tab_base = gen_datalabel_ref (tab_base); 3055 tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base)); 3056 } 3057 else 3058 { 3059 tab_base = gen_rtx_SYMBOL_REF (DImode, "__div_table"); 3060 tab_base = gen_datalabel_ref (tab_base); 3061 tab_base = force_reg (DImode, tab_base); 3062 } 3063 if (TARGET_DIVIDE_INV20U) 3064 i2p27 = force_reg (DImode, GEN_INT (-2 << 27)); 3065 else 3066 i2p27 = GEN_INT (0); 3067 if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L) 3068 i43 = force_reg (DImode, GEN_INT (43)); 3069 else 3070 i43 = GEN_INT (0); 3071 emit_insn (gen_nsbdi (nsb_res, 3072 simplify_gen_subreg (DImode, divisor, SImode, 0))); 3073 emit_insn (gen_ashldi3_media (norm64, 3074 gen_rtx_SUBREG (DImode, divisor, 0), 3075 nsb_res)); 3076 emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58))); 3077 emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32))); 3078 emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32, 3079 inv0, scratch0a, scratch0b, 3080 scratch1a, scratch1b)); 3081 emit_insn (gen_subdi3 (shift, i92, nsb_res)); 3082 emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92, 3083 scratch2a)); 3084 emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift, 3085 i2p27, i43, 3086 scratch3a, scratch3b, scratch3c, 3087 scratch2a, scratch2b, scratch3d, scratch3e)); 3088 if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2) 3089 emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result)); 3090 else if (TARGET_DIVIDE_INV_FP) 3091 emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result, 3092 gen_reg_rtx (SImode), gen_reg_rtx (SImode), 3093 gen_reg_rtx (DFmode), gen_reg_rtx (DFmode), 3094 gen_reg_rtx (DFmode))); 3095 else 3096 emit_move_insn (operands[0], result); 3097 DONE; 3098 } 3099 else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP) 3100 { 3101 operands[1] = force_reg (SImode, operands[1]); 3102 operands[2] = force_reg (SImode, operands[2]); 3103 emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2])); 3104 DONE; 3105 } 3106 else if (TARGET_SH5) 3107 { 3108 if (TARGET_DIVIDE_CALL2) 3109 { 3110 rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table"); 3111 tab_base = gen_datalabel_ref (tab_base); 3112 emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base); 3113 } 3114 if (TARGET_FPU_ANY && TARGET_SH1) 3115 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC); 3116 else if (TARGET_DIVIDE_CALL2) 3117 function_symbol (operands[3], "__sdivsi3_2", SFUNC_STATIC); 3118 else 3119 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT); 3120 3121 if (TARGET_SHMEDIA) 3122 last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media) 3123 (operands[0], operands[3])); 3124 else if (TARGET_FPU_ANY) 3125 last = gen_divsi3_i4_single (operands[0], operands[3]); 3126 else 3127 last = gen_divsi3_i1 (operands[0], operands[3]); 3128 } 3129 else 3130 { 3131 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT); 3132 last = gen_divsi3_i1 (operands[0], operands[3]); 3133 } 3134 emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]); 3135 emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]); 3136 emit_insn (last); 3137 DONE; 3138}) 3139 3140;; operands: scratch, tab_base, tab_ix 3141;; These are unspecs because we could generate an indexed addressing mode 3142;; even if -m5-32media, where INDEX_REG_CLASS == NO_REGS, and this would 3143;; confuse reload. See PR27117. 3144(define_insn "divsi_inv_qitable" 3145 [(set (match_operand:DI 0 "register_operand" "=r") 3146 (zero_extend:DI (unspec:QI [(match_operand:DI 1 "register_operand" "r") 3147 (match_operand:DI 2 "register_operand" "r")] 3148 UNSPEC_DIV_INV_TABLE)))] 3149 "TARGET_SHMEDIA" 3150 "ldx.ub %1, %2, %0" 3151 [(set_attr "type" "load_media") 3152 (set_attr "highpart" "user")]) 3153 3154;; operands: scratch, tab_base, tab_ix 3155(define_insn "divsi_inv_hitable" 3156 [(set (match_operand:DI 0 "register_operand" "=r") 3157 (sign_extend:DI (unspec:HI [(match_operand:DI 1 "register_operand" "r") 3158 (match_operand:DI 2 "register_operand" "r")] 3159 UNSPEC_DIV_INV_TABLE)))] 3160 "TARGET_SHMEDIA" 3161 "ldx.w %1, %2, %0" 3162 [(set_attr "type" "load_media") 3163 (set_attr "highpart" "user")]) 3164 3165;; operands: inv0, tab_base, tab_ix, norm32 3166;; scratch equiv in sdivsi3_2: r19, r21 3167(define_expand "divsi_inv_m0" 3168 [(set (match_operand:SI 0 "register_operand" "=r") 3169 (unspec:SI [(match_operand:DI 1 "register_operand" "r") 3170 (match_operand:DI 2 "register_operand" "r") 3171 (match_operand:SI 3 "register_operand" "r")] 3172 UNSPEC_DIV_INV_M0)) 3173 (clobber (match_operand:DI 4 "register_operand" "=r")) 3174 (clobber (match_operand:DI 5 "register_operand" "=r"))] 3175 "TARGET_SHMEDIA" 3176{ 3177/* 3178tab_base: r20 3179tab_ix: r21 3180norm32: r25 3181 ldx.ub r20, r21, r19 // u0.8 3182 shlli r21, 1, r21 3183 muls.l r25, r19, r19 // s2.38 3184 ldx.w r20, r21, r21 // s2.14 3185 shari r19, 24, r19 // truncate to s2.14 3186 sub r21, r19, r19 // some 11 bit inverse in s1.14 3187*/ 3188 3189 rtx inv0 = operands[0]; 3190 rtx tab_base = operands[1]; 3191 rtx tab_ix = operands[2]; 3192 rtx norm32 = operands[3]; 3193 rtx scratch0 = operands[4]; 3194 rtx scratch0_si = gen_lowpart (SImode, scratch0); 3195 rtx scratch1 = operands[5]; 3196 3197 emit_insn (gen_divsi_inv_qitable (scratch0, tab_base, tab_ix)); 3198 emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1))); 3199 emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si)); 3200 emit_insn (gen_divsi_inv_hitable (scratch1, tab_base, scratch1)); 3201 emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24))); 3202 emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0)); 3203 DONE; 3204}) 3205 3206;; operands: inv1, tab_base, tab_ix, norm32 3207(define_insn_and_split "divsi_inv_m1" 3208 [(set (match_operand:SI 0 "register_operand" "=r") 3209 (unspec:SI [(match_operand:DI 1 "register_operand" "r") 3210 (match_operand:DI 2 "register_operand" "r") 3211 (match_operand:SI 3 "register_operand" "r")] 3212 UNSPEC_DIV_INV_M1)) 3213 (clobber (match_operand:SI 4 "register_operand" "=r")) 3214 (clobber (match_operand:DI 5 "register_operand" "=r")) 3215 (clobber (match_operand:DI 6 "register_operand" "=r")) 3216 (clobber (match_operand:DI 7 "register_operand" "=r")) 3217 (clobber (match_operand:DI 8 "register_operand" "=r"))] 3218 "TARGET_SHMEDIA" 3219 "#" 3220 "&& !can_create_pseudo_p ()" 3221 [(pc)] 3222{ 3223/* inv0: r19 3224 muls.l r19, r19, r18 // u0.28 3225 muls.l r25, r18, r18 // s2.58 3226 shlli r19, 45, r0 // multiply by two and convert to s2.58 3227 sub r0, r18, r18 3228 shari r18, 28, r18 // some 18 bit inverse in s1.30 3229*/ 3230 3231 rtx inv1 = operands[0]; 3232 rtx tab_base = operands[1]; 3233 rtx tab_ix = operands[2]; 3234 rtx norm32 = operands[3]; 3235 rtx inv0 = operands[4]; 3236 rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0); 3237 rtx scratch0a = operands[5]; 3238 rtx scratch0b = operands[6]; 3239 rtx scratch0 = operands[7]; 3240 rtx scratch1 = operands[8]; 3241 rtx scratch1_si = gen_lowpart (SImode, scratch1); 3242 3243 emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32, 3244 scratch0a, scratch0b)); 3245 emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0)); 3246 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si)); 3247 emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45))); 3248 emit_insn (gen_subdi3 (scratch1, scratch0, scratch1)); 3249 emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28))); 3250 DONE; 3251}) 3252 3253;; operands: inv2, norm32, inv1, i92 3254(define_insn_and_split "divsi_inv_m2" 3255 [(set (match_operand:SI 0 "register_operand" "=r") 3256 (unspec:SI [(match_operand:SI 1 "register_operand" "r") 3257 (match_operand:SI 2 "register_operand" "r") 3258 (match_operand:DI 3 "register_operand" "r")] 3259 UNSPEC_DIV_INV_M2)) 3260 (clobber (match_operand:DI 4 "register_operand" "=r"))] 3261 "TARGET_SHMEDIA" 3262 "#" 3263 "&& !can_create_pseudo_p ()" 3264 [(pc)] 3265{ 3266/* 3267 muls.l r18, r25, r0 // s2.60 3268 shari r0, 16, r0 // s-16.44 3269 sub 3270 muls.l r0, r18, r19 // s-16.74 3271 shari r19, 30, r19 // s-16.44 3272*/ 3273 rtx inv2 = operands[0]; 3274 rtx norm32 = operands[1]; 3275 rtx inv1 = operands[2]; 3276 rtx i92 = operands[3]; 3277 rtx scratch0 = operands[4]; 3278 rtx scratch0_si = gen_lowpart (SImode, scratch0); 3279 3280 emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32)); 3281 emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16))); 3282 emit_insn (gen_subdi3 (scratch0, i92, scratch0)); 3283 emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1)); 3284 emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30))); 3285 DONE; 3286}) 3287 3288(define_insn_and_split "divsi_inv_m3" 3289 [(set (match_operand:SI 0 "register_operand" "=r") 3290 (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN") 3291 (match_operand:SI 2 "register_operand" "r") 3292 (match_operand:SI 3 "register_operand" "r") 3293 (match_operand:DI 4 "register_operand" "r") 3294 (match_operand:DI 5 "arith_reg_or_0_operand" "rN") 3295 (match_operand:DI 6 "arith_reg_or_0_operand" "rN")] 3296 UNSPEC_DIV_INV_M3)) 3297 (clobber (match_operand:DI 7 "register_operand" "=r")) 3298 (clobber (match_operand:DI 8 "register_operand" "=r")) 3299 (clobber (match_operand:DI 9 "register_operand" "=r")) 3300 (clobber (match_operand:DI 10 "register_operand" "=r")) 3301 (clobber (match_operand:SI 11 "register_operand" "=r")) 3302 (clobber (match_operand:SI 12 "register_operand" "=r")) 3303 (clobber (match_operand:DI 13 "register_operand" "=r"))] 3304 "TARGET_SHMEDIA" 3305 "#" 3306 "&& !can_create_pseudo_p ()" 3307 [(pc)] 3308{ 3309/* 3310 r0: result r1: shift r4: dividend r18: inv1 r19: inv2 3311 r0: scratch0 r19: scratch1 r21: scratch2 3312 3313 muls.l r18, r4, r25 // s32.30 3314 muls.l r19, r4, r19 // s15.30 3315 shari r25, 63, r21 3316 shari r19, 14, r19 // s18.-14 3317 sub r25, r19, r0 3318 shard r0, r1, r0 3319 sub r0, r21, r0 3320*/ 3321 3322 rtx result = operands[0]; 3323 rtx dividend = operands[1]; 3324 rtx inv1 = operands[2]; 3325 rtx inv2 = operands[3]; 3326 rtx shift = operands[4]; 3327 rtx scratch0 = operands[7]; 3328 rtx scratch1 = operands[8]; 3329 rtx scratch2 = operands[9]; 3330 3331 if (satisfies_constraint_N (dividend)) 3332 { 3333 emit_move_insn (result, dividend); 3334 DONE; 3335 } 3336 3337 emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend)); 3338 emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend)); 3339 emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63))); 3340 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14))); 3341 emit_insn (gen_adddi3 (scratch0, scratch0, scratch1)); 3342 emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift)); 3343 emit_insn (gen_subdisi3_media (result, scratch0, scratch2)); 3344 DONE; 3345}) 3346 3347;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43 3348;; inv1: tab_base, tab_ix, norm32 3349;; inv2: norm32, inv1, i92 3350(define_insn_and_split "divsi_inv_m1_3" 3351 [(set (match_operand:SI 0 "register_operand" "=r") 3352 (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN") 3353 (unspec:SI [(match_operand:DI 2 "register_operand" "r") 3354 (match_operand:DI 3 "register_operand" "r") 3355 (match_operand:SI 4 "register_operand" "r")] 3356 UNSPEC_DIV_INV_M1) 3357 (unspec:SI [(match_dup 4) 3358 (unspec:SI [(match_dup 2) 3359 (match_dup 3) 3360 (match_dup 4)] UNSPEC_DIV_INV_M1) 3361 (match_operand:SI 5 "" "")] 3362 UNSPEC_DIV_INV_M2) 3363 (match_operand:DI 6 "register_operand" "r") 3364 (match_operand:DI 7 "arith_reg_or_0_operand" "rN") 3365 (match_operand:DI 8 "arith_reg_or_0_operand" "rN")] 3366 UNSPEC_DIV_INV_M3)) 3367 (clobber (match_operand:DI 9 "register_operand" "=r")) 3368 (clobber (match_operand:DI 10 "register_operand" "=r")) 3369 (clobber (match_operand:DI 11 "register_operand" "=r")) 3370 (clobber (match_operand:DI 12 "register_operand" "=r")) 3371 (clobber (match_operand:SI 13 "register_operand" "=r")) 3372 (clobber (match_operand:SI 14 "register_operand" "=r")) 3373 (clobber (match_operand:DI 15 "register_operand" "=r"))] 3374 "TARGET_SHMEDIA 3375 && (TARGET_DIVIDE_INV_MINLAT 3376 || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)" 3377 "#" 3378 "&& !can_create_pseudo_p ()" 3379 [(pc)] 3380{ 3381 rtx result = operands[0]; 3382 rtx dividend = operands[1]; 3383 rtx tab_base = operands[2]; 3384 rtx tab_ix = operands[3]; 3385 rtx norm32 = operands[4]; 3386 /* rtx i92 = operands[5]; */ 3387 rtx shift = operands[6]; 3388 rtx i2p27 = operands[7]; 3389 rtx i43 = operands[8]; 3390 rtx scratch0 = operands[9]; 3391 rtx scratch0_si = gen_lowpart (SImode, scratch0); 3392 rtx scratch1 = operands[10]; 3393 rtx scratch1_si = gen_lowpart (SImode, scratch1); 3394 rtx scratch2 = operands[11]; 3395 rtx scratch3 = operands[12]; 3396 rtx scratch4 = operands[13]; 3397 rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0); 3398 rtx scratch5 = operands[14]; 3399 rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0); 3400 rtx scratch6 = operands[15]; 3401 3402 emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32, 3403 scratch0, scratch1)); 3404 /* inv0 == scratch4 */ 3405 if (! TARGET_DIVIDE_INV20U) 3406 { 3407 emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4)); 3408 i2p27 = scratch0; 3409 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si)); 3410 } 3411 else 3412 { 3413 emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4)); 3414 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si)); 3415 } 3416 emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45))); 3417 emit_insn (gen_subdi3 (scratch1, scratch2, scratch1)); 3418 emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28))); 3419 /* inv1 == scratch4 */ 3420 3421 if (TARGET_DIVIDE_INV_MINLAT) 3422 { 3423 emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32)); 3424 emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4)); 3425 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16))); 3426 emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4)); 3427 emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63))); 3428 emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14))); 3429 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30))); 3430 emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5)); 3431 emit_insn (gen_xordi3 (scratch0, scratch3, i2p27)); 3432 emit_insn (gen_adddi3 (scratch2, scratch2, scratch0)); 3433 emit_insn (gen_subdi3 (scratch2, scratch2, scratch1)); 3434 } 3435 else 3436 { 3437 rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ()); 3438 /* Use separate scratch regs for nsb and sign to allow scheduling. */ 3439 emit_insn (gen_nsbdi (scratch6, 3440 simplify_gen_subreg (DImode, dividend, SImode, 0))); 3441 emit_insn (gen_xorsi3 (scratch5, dividend, norm32)); 3442 emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63))); 3443 emit_insn (gen_divsi_inv20 (scratch2, 3444 norm32, scratch4, dividend, 3445 scratch6, scratch3, i43, 3446 /* scratch0 may be shared with i2p27. */ 3447 scratch0, scratch1, scratch5, 3448 label, label, i2p27)); 3449 } 3450 emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift)); 3451 emit_insn (gen_subdisi3_media (result, scratch2, scratch3)); 3452 DONE; 3453}) 3454 3455(define_insn "divsi_inv20" 3456 [(set (match_operand:DI 0 "register_operand" "=&r") 3457 (unspec:DI [(match_operand:SI 1 "register_operand" "r") 3458 (match_operand:SI 2 "register_operand" "r") 3459 (match_operand:SI 3 "register_operand" "r") 3460 (match_operand:DI 4 "register_operand" "r") 3461 (match_operand:DI 5 "register_operand" "r") 3462 (match_operand:DI 6 "register_operand" "r") 3463 (match_operand:DI 12 "register_operand" "r") 3464 (match_operand 10 "target_operand" "b") 3465 (match_operand 11 "immediate_operand" "i")] 3466 UNSPEC_DIV_INV20)) 3467 (clobber (match_operand:DI 7 "register_operand" "=&r")) 3468 (clobber (match_operand:DI 8 "register_operand" "=&r")) 3469 (clobber (match_operand:SI 9 "register_operand" "=r"))] 3470 "TARGET_SHMEDIA 3471 && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)" 3472{ 3473/* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend, 3474 %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27, 3475 %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si) 3476 %10 label (tr), %11 label (imm) 3477 3478 muls.l inv1, norm32, scratch0 // s2.60 3479 muls.l inv1, dividend, result // s32.30 3480 xor i2p27, result_sign, round_scratch 3481 bge/u dividend_nsb, i43, tr.. (label) 3482 shari scratch0, 16, scratch0 // s-16.44 3483 muls.l sratch0_si, inv1, scratch0 // s-16.74 3484 sub result, round_scratch, result 3485 shari dividend, 14, scratch1 // s19.-14 3486 shari scratch0, 30, scratch0 // s-16.44 3487 muls.l scratch0, scratch1, round_scratch // s15.30 3488label: 3489 sub result, round_scratch, result */ 3490 3491 const bool likely = TARGET_DIVIDE_INV20L; 3492 if (likely) 3493 return 3494 "muls.l %2, %3, %0" "\n" 3495 " xor %12, %5, %7" "\n" 3496 " bge/l %4, %6, %10" "\n" 3497 " muls.l %2, %1, %8" "\n" 3498 " shari %8, 16, %8" "\n" 3499 " muls.l %8, %2, %8" "\n" 3500 " shari %3, 14, %9" "\n" 3501 " shari %8, 30, %8" "\n" 3502 " muls.l %8, %9, %8" "\n" 3503 " sub %0, %8, %0" "\n" 3504 "%11: add %0, %7, %0"; 3505 else 3506 return 3507 "muls.l %2, %1, %8" "\n" 3508 " muls.l %2, %3, %0" "\n" 3509 " xor %12, %5, %7" "\n" 3510 " bge/u %4, %6, %10" "\n" 3511 " shari %8, 16, %8" "\n" 3512 " muls.l %8, %2, %8" "\n" 3513 " sub %0, %7, %0" "\n" 3514 " shari %3, 14, %9" "\n" 3515 " shari %8, 30, %8" "\n" 3516 " muls.l %8, %9, %7" "\n" 3517 "%11: sub %0, %7, %0"; 3518}) 3519 3520(define_insn_and_split "divsi_inv_fp" 3521 [(set (match_operand:SI 0 "general_movdst_operand" "=rf") 3522 (div:SI (match_operand:SI 1 "general_movsrc_operand" "rf") 3523 (match_operand:SI 2 "register_operand" "rf"))) 3524 (use (match_operand:SI 3 "general_movsrc_operand" "r")) 3525 (clobber (match_operand:SI 4 "register_operand" "=r")) 3526 (clobber (match_operand:SI 5 "register_operand" "=r")) 3527 (clobber (match_operand:DF 6 "register_operand" "=r")) 3528 (clobber (match_operand:DF 7 "register_operand" "=r")) 3529 (clobber (match_operand:DF 8 "register_operand" "=r"))] 3530 "TARGET_SHMEDIA_FPU" 3531 "#" 3532 "&& (reload_in_progress || reload_completed)" 3533 [(set (match_dup 0) (match_dup 3))] 3534 "" 3535 [(set_attr "highpart" "must_split")]) 3536 3537;; If a matching group of divide-by-inverse instructions is in the same 3538;; basic block after gcse & loop optimizations, we want to transform them 3539;; to a straight division using floating point for TARGET_DIVIDE_INV_FP. 3540(define_insn_and_split "*divsi_inv_fp_combine" 3541 [(set (match_operand:SI 0 "register_operand" "=f") 3542 (div:SI (match_operand:SI 1 "register_operand" "f") 3543 (match_operand:SI 2 "register_operand" "f"))) 3544 (use (unspec:SI [(match_dup 1) 3545 (match_operand:SI 3 "" "") 3546 (unspec:SI [(match_operand:SI 4 "" "") 3547 (match_dup 3) 3548 (match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2) 3549 (match_operand:DI 6 "" "") 3550 (const_int 0) 3551 (const_int 0)] UNSPEC_DIV_INV_M3)) 3552 (clobber (match_operand:SI 7 "fp_arith_reg_operand" "")) 3553 (clobber (match_operand:SI 8 "fp_arith_reg_operand" "")) 3554 (clobber (match_operand:DF 9 "fp_arith_reg_operand" "")) 3555 (clobber (match_operand:DF 10 "fp_arith_reg_operand" "")) 3556 (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))] 3557 "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && !can_create_pseudo_p ()" 3558 "#" 3559 "&& 1" 3560 [(set (match_dup 9) (float:DF (match_dup 1))) 3561 (set (match_dup 10) (float:DF (match_dup 2))) 3562 (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10))) 3563 (set (match_dup 8) 3564 (fix:SI (match_dup 11))) 3565 (set (match_dup 0) (match_dup 8))] 3566{ 3567 if (! fp_arith_reg_operand (operands[1], SImode)) 3568 { 3569 emit_move_insn (operands[7], operands[1]); 3570 operands[1] = operands[7]; 3571 } 3572 if (! fp_arith_reg_operand (operands[2], SImode)) 3573 { 3574 emit_move_insn (operands[8], operands[2]); 3575 operands[2] = operands[8]; 3576 } 3577} 3578 [(set_attr "highpart" "must_split")]) 3579 3580;; ------------------------------------------------------------------------- 3581;; Multiplication instructions 3582;; ------------------------------------------------------------------------- 3583 3584(define_insn "umulhisi3_i" 3585 [(set (reg:SI MACL_REG) 3586 (mult:SI (zero_extend:SI 3587 (match_operand:HI 0 "arith_reg_operand" "r")) 3588 (zero_extend:SI 3589 (match_operand:HI 1 "arith_reg_operand" "r"))))] 3590 "TARGET_SH1" 3591 "mulu.w %1,%0" 3592 [(set_attr "type" "smpy")]) 3593 3594(define_insn "mulhisi3_i" 3595 [(set (reg:SI MACL_REG) 3596 (mult:SI (sign_extend:SI 3597 (match_operand:HI 0 "arith_reg_operand" "r")) 3598 (sign_extend:SI 3599 (match_operand:HI 1 "arith_reg_operand" "r"))))] 3600 "TARGET_SH1" 3601 "muls.w %1,%0" 3602 [(set_attr "type" "smpy")]) 3603 3604(define_expand "mulhisi3" 3605 [(set (reg:SI MACL_REG) 3606 (mult:SI (sign_extend:SI 3607 (match_operand:HI 1 "arith_reg_operand" "")) 3608 (sign_extend:SI 3609 (match_operand:HI 2 "arith_reg_operand" "")))) 3610 (set (match_operand:SI 0 "arith_reg_operand" "") 3611 (reg:SI MACL_REG))] 3612 "TARGET_SH1" 3613{ 3614 rtx_insn *insn; 3615 rtx macl; 3616 3617 macl = gen_rtx_REG (SImode, MACL_REG); 3618 start_sequence (); 3619 emit_insn (gen_mulhisi3_i (operands[1], operands[2])); 3620 insn = get_insns (); 3621 end_sequence (); 3622 /* expand_binop can't find a suitable code in umul_widen_optab to 3623 make a REG_EQUAL note from, so make one here. 3624 See also smulsi3_highpart. 3625 ??? Alternatively, we could put this at the calling site of expand_binop, 3626 i.e. expand_expr. */ 3627 /* Use emit_libcall_block for loop invariant code motion and to make 3628 a REG_EQUAL note. */ 3629 emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn))); 3630 3631 DONE; 3632}) 3633 3634(define_expand "umulhisi3" 3635 [(set (reg:SI MACL_REG) 3636 (mult:SI (zero_extend:SI 3637 (match_operand:HI 1 "arith_reg_operand" "")) 3638 (zero_extend:SI 3639 (match_operand:HI 2 "arith_reg_operand" "")))) 3640 (set (match_operand:SI 0 "arith_reg_operand" "") 3641 (reg:SI MACL_REG))] 3642 "TARGET_SH1" 3643{ 3644 rtx_insn *insn; 3645 rtx macl; 3646 3647 macl = gen_rtx_REG (SImode, MACL_REG); 3648 start_sequence (); 3649 emit_insn (gen_umulhisi3_i (operands[1], operands[2])); 3650 insn = get_insns (); 3651 end_sequence (); 3652 /* expand_binop can't find a suitable code in umul_widen_optab to 3653 make a REG_EQUAL note from, so make one here. 3654 See also smulsi3_highpart. 3655 ??? Alternatively, we could put this at the calling site of expand_binop, 3656 i.e. expand_expr. */ 3657 /* Use emit_libcall_block for loop invariant code motion and to make 3658 a REG_EQUAL note. */ 3659 emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn))); 3660 3661 DONE; 3662}) 3663 3664;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate 3665;; a call to a routine which clobbers known registers. 3666(define_insn "" 3667 [(set (match_operand:SI 1 "register_operand" "=z") 3668 (mult:SI (reg:SI R4_REG) (reg:SI R5_REG))) 3669 (clobber (reg:SI MACL_REG)) 3670 (clobber (reg:SI T_REG)) 3671 (clobber (reg:SI PR_REG)) 3672 (clobber (reg:SI R3_REG)) 3673 (clobber (reg:SI R2_REG)) 3674 (clobber (reg:SI R1_REG)) 3675 (use (match_operand:SI 0 "arith_reg_operand" "r"))] 3676 "TARGET_SH1" 3677 "jsr @%0%#" 3678 [(set_attr "type" "sfunc") 3679 (set_attr "needs_delay_slot" "yes")]) 3680 3681(define_expand "mulsi3_call" 3682 [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" "")) 3683 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" "")) 3684 (parallel[(set (match_operand:SI 0 "register_operand" "") 3685 (mult:SI (reg:SI R4_REG) 3686 (reg:SI R5_REG))) 3687 (clobber (reg:SI MACL_REG)) 3688 (clobber (reg:SI T_REG)) 3689 (clobber (reg:SI PR_REG)) 3690 (clobber (reg:SI R3_REG)) 3691 (clobber (reg:SI R2_REG)) 3692 (clobber (reg:SI R1_REG)) 3693 (use (match_operand:SI 3 "register_operand" ""))])] 3694 "TARGET_SH1" 3695 "") 3696 3697(define_insn "mul_r" 3698 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 3699 (mult:SI (match_operand:SI 1 "arith_reg_operand" "0") 3700 (match_operand:SI 2 "arith_reg_operand" "z")))] 3701 "TARGET_SH2A" 3702 "mulr %2,%0" 3703 [(set_attr "type" "dmpy")]) 3704 3705(define_insn "mul_l" 3706 [(set (reg:SI MACL_REG) 3707 (mult:SI (match_operand:SI 0 "arith_reg_operand" "r") 3708 (match_operand:SI 1 "arith_reg_operand" "r")))] 3709 "TARGET_SH2" 3710 "mul.l %1,%0" 3711 [(set_attr "type" "dmpy")]) 3712 3713(define_expand "mulsi3" 3714 [(set (reg:SI MACL_REG) 3715 (mult:SI (match_operand:SI 1 "arith_reg_operand" "") 3716 (match_operand:SI 2 "arith_reg_operand" ""))) 3717 (set (match_operand:SI 0 "arith_reg_operand" "") 3718 (reg:SI MACL_REG))] 3719 "TARGET_SH1" 3720{ 3721 if (!TARGET_SH2) 3722 { 3723 /* The address must be set outside the libcall, 3724 since it goes into a pseudo. */ 3725 rtx sym = function_symbol (NULL, "__mulsi3", SFUNC_STATIC); 3726 rtx addr = force_reg (SImode, sym); 3727 rtx insns = gen_mulsi3_call (operands[0], operands[1], 3728 operands[2], addr); 3729 emit_insn (insns); 3730 } 3731 else 3732 { 3733 rtx macl = gen_rtx_REG (SImode, MACL_REG); 3734 3735 emit_insn (gen_mul_l (operands[1], operands[2])); 3736 /* consec_sets_giv can only recognize the first insn that sets a 3737 giv as the giv insn. So we must tag this also with a REG_EQUAL 3738 note. */ 3739 emit_insn (gen_movsi_i ((operands[0]), macl)); 3740 } 3741 DONE; 3742}) 3743 3744(define_insn "mulsidi3_i" 3745 [(set (reg:SI MACH_REG) 3746 (truncate:SI 3747 (lshiftrt:DI 3748 (mult:DI 3749 (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) 3750 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))) 3751 (const_int 32)))) 3752 (set (reg:SI MACL_REG) 3753 (mult:SI (match_dup 0) 3754 (match_dup 1)))] 3755 "TARGET_SH2" 3756 "dmuls.l %1,%0" 3757 [(set_attr "type" "dmpy")]) 3758 3759(define_expand "mulsidi3" 3760 [(set (match_operand:DI 0 "arith_reg_dest" "") 3761 (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) 3762 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))] 3763 "TARGET_SH2 || TARGET_SHMEDIA" 3764{ 3765 if (TARGET_SH2) 3766 { 3767 emit_insn (gen_mulsidi3_compact (operands[0], operands[1], operands[2])); 3768 DONE; 3769 } 3770}) 3771 3772(define_insn "mulsidi3_media" 3773 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 3774 (mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r")) 3775 (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))] 3776 "TARGET_SHMEDIA" 3777 "muls.l %1, %2, %0" 3778 [(set_attr "type" "dmpy_media") 3779 (set_attr "highpart" "ignore")]) 3780 3781(define_insn_and_split "mulsidi3_compact" 3782 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 3783 (mult:DI 3784 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")) 3785 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r")))) 3786 (clobber (reg:SI MACH_REG)) 3787 (clobber (reg:SI MACL_REG))] 3788 "TARGET_SH2" 3789 "#" 3790 "&& 1" 3791 [(const_int 0)] 3792{ 3793 rtx low_dst = gen_lowpart (SImode, operands[0]); 3794 rtx high_dst = gen_highpart (SImode, operands[0]); 3795 3796 emit_insn (gen_mulsidi3_i (operands[1], operands[2])); 3797 3798 emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG)); 3799 emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG)); 3800 /* We need something to tag the possible REG_EQUAL notes on to. */ 3801 emit_move_insn (operands[0], operands[0]); 3802 DONE; 3803}) 3804 3805(define_insn "umulsidi3_i" 3806 [(set (reg:SI MACH_REG) 3807 (truncate:SI 3808 (lshiftrt:DI 3809 (mult:DI 3810 (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) 3811 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))) 3812 (const_int 32)))) 3813 (set (reg:SI MACL_REG) 3814 (mult:SI (match_dup 0) 3815 (match_dup 1)))] 3816 "TARGET_SH2" 3817 "dmulu.l %1,%0" 3818 [(set_attr "type" "dmpy")]) 3819 3820(define_expand "umulsidi3" 3821 [(set (match_operand:DI 0 "arith_reg_dest" "") 3822 (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) 3823 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))] 3824 "TARGET_SH2 || TARGET_SHMEDIA" 3825{ 3826 if (TARGET_SH2) 3827 { 3828 emit_insn (gen_umulsidi3_compact (operands[0], operands[1], operands[2])); 3829 DONE; 3830 } 3831}) 3832 3833(define_insn "umulsidi3_media" 3834 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 3835 (mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r")) 3836 (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))] 3837 "TARGET_SHMEDIA" 3838 "mulu.l %1, %2, %0" 3839 [(set_attr "type" "dmpy_media") 3840 (set_attr "highpart" "ignore")]) 3841 3842(define_insn_and_split "umulsidi3_compact" 3843 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 3844 (mult:DI 3845 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")) 3846 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r")))) 3847 (clobber (reg:SI MACH_REG)) 3848 (clobber (reg:SI MACL_REG))] 3849 "TARGET_SH2" 3850 "#" 3851 "&& 1" 3852 [(const_int 0)] 3853{ 3854 rtx low_dst = gen_lowpart (SImode, operands[0]); 3855 rtx high_dst = gen_highpart (SImode, operands[0]); 3856 3857 emit_insn (gen_umulsidi3_i (operands[1], operands[2])); 3858 3859 emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG)); 3860 emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG)); 3861 /* We need something to tag the possible REG_EQUAL notes on to. */ 3862 emit_move_insn (operands[0], operands[0]); 3863 DONE; 3864}) 3865 3866(define_insn "smulsi3_highpart_i" 3867 [(set (reg:SI MACH_REG) 3868 (truncate:SI 3869 (lshiftrt:DI 3870 (mult:DI 3871 (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) 3872 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))) 3873 (const_int 32)))) 3874 (clobber (reg:SI MACL_REG))] 3875 "TARGET_SH2" 3876 "dmuls.l %1,%0" 3877 [(set_attr "type" "dmpy")]) 3878 3879(define_expand "smulsi3_highpart" 3880 [(parallel 3881 [(set (reg:SI MACH_REG) 3882 (truncate:SI 3883 (lshiftrt:DI 3884 (mult:DI 3885 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) 3886 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))) 3887 (const_int 32)))) 3888 (clobber (reg:SI MACL_REG))]) 3889 (set (match_operand:SI 0 "arith_reg_operand" "") 3890 (reg:SI MACH_REG))] 3891 "TARGET_SH2" 3892{ 3893 rtx_insn *insn; 3894 rtx mach; 3895 3896 mach = gen_rtx_REG (SImode, MACH_REG); 3897 start_sequence (); 3898 emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2])); 3899 insn = get_insns (); 3900 end_sequence (); 3901 /* expand_binop can't find a suitable code in mul_highpart_optab to 3902 make a REG_EQUAL note from, so make one here. 3903 See also {,u}mulhisi. 3904 ??? Alternatively, we could put this at the calling site of expand_binop, 3905 i.e. expand_mult_highpart. */ 3906 /* Use emit_libcall_block for loop invariant code motion and to make 3907 a REG_EQUAL note. */ 3908 emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn))); 3909 3910 DONE; 3911}) 3912 3913(define_insn "umulsi3_highpart_i" 3914 [(set (reg:SI MACH_REG) 3915 (truncate:SI 3916 (lshiftrt:DI 3917 (mult:DI 3918 (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) 3919 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))) 3920 (const_int 32)))) 3921 (clobber (reg:SI MACL_REG))] 3922 "TARGET_SH2" 3923 "dmulu.l %1,%0" 3924 [(set_attr "type" "dmpy")]) 3925 3926(define_expand "umulsi3_highpart" 3927 [(parallel 3928 [(set (reg:SI MACH_REG) 3929 (truncate:SI 3930 (lshiftrt:DI 3931 (mult:DI 3932 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) 3933 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))) 3934 (const_int 32)))) 3935 (clobber (reg:SI MACL_REG))]) 3936 (set (match_operand:SI 0 "arith_reg_operand" "") 3937 (reg:SI MACH_REG))] 3938 "TARGET_SH2" 3939{ 3940 rtx_insn *insn; 3941 rtx mach; 3942 3943 mach = gen_rtx_REG (SImode, MACH_REG); 3944 start_sequence (); 3945 emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2])); 3946 insn = get_insns (); 3947 end_sequence (); 3948 /* Use emit_libcall_block for loop invariant code motion and to make 3949 a REG_EQUAL note. */ 3950 emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn))); 3951 3952 DONE; 3953}) 3954 3955(define_insn_and_split "muldi3" 3956 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 3957 (mult:DI (match_operand:DI 1 "arith_reg_operand" "r") 3958 (match_operand:DI 2 "arith_reg_operand" "r"))) 3959 (clobber (match_scratch:DI 3 "=&r")) 3960 (clobber (match_scratch:DI 4 "=r"))] 3961 "TARGET_SHMEDIA" 3962 "#" 3963 "reload_completed" 3964 [(const_int 0)] 3965{ 3966 rtx op3_v2si, op2_v2si; 3967 3968 op3_v2si = operands[3]; 3969 if (GET_CODE (op3_v2si) == SIGN_EXTEND) 3970 { 3971 op3_v2si = XEXP (op3_v2si, 0); 3972 op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0); 3973 } 3974 op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0); 3975 op2_v2si = operands[2]; 3976 if (GET_CODE (op2_v2si) == SIGN_EXTEND) 3977 { 3978 op2_v2si = XEXP (op2_v2si, 0); 3979 op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0); 3980 } 3981 op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0); 3982 emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32))); 3983 emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si)); 3984 emit_insn (gen_umulsidi3_media (operands[4], 3985 sh_gen_truncate (SImode, operands[1], 0), 3986 sh_gen_truncate (SImode, operands[2], 0))); 3987 emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL))); 3988 emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32))); 3989 emit_insn (gen_adddi3 (operands[0], operands[3], operands[0])); 3990 emit_insn (gen_adddi3 (operands[0], operands[4], operands[0])); 3991 DONE; 3992}) 3993 3994;; ------------------------------------------------------------------------- 3995;; Logical operations 3996;; ------------------------------------------------------------------------- 3997 3998(define_expand "andsi3" 3999 [(set (match_operand:SI 0 "arith_reg_operand" "") 4000 (and:SI (match_operand:SI 1 "logical_reg_operand" "") 4001 (match_operand:SI 2 "logical_and_operand" "")))] 4002 "" 4003{ 4004 /* If it is possible to turn the and insn into a zero extension 4005 already, redundant zero extensions will be folded, which results 4006 in better code. 4007 Ideally the splitter of *andsi_compact would be enough, if redundant 4008 zero extensions were detected after the combine pass, which does not 4009 happen at the moment. */ 4010 if (TARGET_SH1) 4011 { 4012 if (satisfies_constraint_Jmb (operands[2])) 4013 { 4014 emit_insn (gen_zero_extendqisi2 (operands[0], 4015 gen_lowpart (QImode, operands[1]))); 4016 DONE; 4017 } 4018 else if (satisfies_constraint_Jmw (operands[2])) 4019 { 4020 emit_insn (gen_zero_extendhisi2 (operands[0], 4021 gen_lowpart (HImode, operands[1]))); 4022 DONE; 4023 } 4024 } 4025}) 4026 4027(define_insn_and_split "*andsi_compact" 4028 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,z,r") 4029 (and:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,0,0") 4030 (match_operand:SI 2 "logical_and_operand" "Jmb,Jmw,K08,r")))] 4031 "TARGET_SH1" 4032 "@ 4033 extu.b %1,%0 4034 extu.w %1,%0 4035 and %2,%0 4036 and %2,%0" 4037 "&& 1" 4038 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))] 4039{ 4040 if (satisfies_constraint_Jmb (operands[2])) 4041 operands[1] = gen_lowpart (QImode, operands[1]); 4042 else if (satisfies_constraint_Jmw (operands[2])) 4043 operands[1] = gen_lowpart (HImode, operands[1]); 4044 else 4045 FAIL; 4046} 4047 [(set_attr "type" "arith")]) 4048 4049(define_insn "*andsi3_media" 4050 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 4051 (and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r") 4052 (match_operand:SI 2 "logical_operand" "r,I10")))] 4053 "TARGET_SHMEDIA" 4054 "@ 4055 and %1, %2, %0 4056 andi %1, %2, %0" 4057 [(set_attr "type" "arith_media")]) 4058 4059(define_insn "*andsi3_bclr" 4060 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4061 (and:SI (match_operand:SI 1 "arith_reg_operand" "%0") 4062 (match_operand:SI 2 "const_int_operand" "Psz")))] 4063 "TARGET_SH2A && satisfies_constraint_Psz (operands[2])" 4064 "bclr %W2,%0" 4065 [(set_attr "type" "arith")]) 4066 4067(define_insn_and_split "anddi3" 4068 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r") 4069 (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r") 4070 (match_operand:DI 2 "and_operand" "r,I10,J16")))] 4071 "TARGET_SHMEDIA" 4072 "@ 4073 and %1, %2, %0 4074 andi %1, %2, %0 4075 #" 4076 "reload_completed 4077 && ! logical_operand (operands[2], DImode)" 4078 [(const_int 0)] 4079{ 4080 if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff) 4081 emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode))); 4082 else 4083 emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1])); 4084 DONE; 4085} 4086 [(set_attr "type" "arith_media")]) 4087 4088(define_insn "andcsi3" 4089 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4090 (and:SI (match_operand:SI 1 "arith_reg_operand" "r") 4091 (not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))] 4092 "TARGET_SHMEDIA" 4093 "andc %1,%2,%0" 4094 [(set_attr "type" "arith_media")]) 4095 4096(define_insn "andcdi3" 4097 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 4098 (and:DI (match_operand:DI 1 "arith_reg_operand" "r") 4099 (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))] 4100 "TARGET_SHMEDIA" 4101 "andc %1,%2,%0" 4102 [(set_attr "type" "arith_media")]) 4103 4104(define_expand "iorsi3" 4105 [(set (match_operand:SI 0 "arith_reg_operand" "") 4106 (ior:SI (match_operand:SI 1 "logical_reg_operand" "") 4107 (match_operand:SI 2 "logical_operand" "")))] 4108 "" 4109 "") 4110 4111(define_insn "*iorsi3_compact" 4112 [(set (match_operand:SI 0 "arith_reg_dest" "=r,z") 4113 (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") 4114 (match_operand:SI 2 "logical_operand" "r,K08")))] 4115 "TARGET_SH1 4116 && !(TARGET_SH2A && satisfies_constraint_Pso (operands[2]))" 4117 "or %2,%0" 4118 [(set_attr "type" "arith")]) 4119 4120(define_insn "*iorsi3_media" 4121 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 4122 (ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r") 4123 (match_operand:SI 2 "logical_operand" "r,I10")))] 4124 "TARGET_SHMEDIA" 4125 "@ 4126 or %1, %2, %0 4127 ori %1, %2, %0" 4128 [(set_attr "type" "arith_media")]) 4129 4130(define_insn "*iorsi3_bset" 4131 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4132 (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0") 4133 (match_operand:SI 2 "const_int_operand" "Pso")))] 4134 "TARGET_SH2A && satisfies_constraint_Pso (operands[2])" 4135 "bset %V2,%0" 4136 [(set_attr "type" "arith")]) 4137 4138(define_insn "iordi3" 4139 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") 4140 (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r") 4141 (match_operand:DI 2 "logical_operand" "r,I10")))] 4142 "TARGET_SHMEDIA" 4143 "@ 4144 or %1, %2, %0 4145 ori %1, %2, %0" 4146 [(set_attr "type" "arith_media")]) 4147 4148(define_insn_and_split "*logical_sidi3" 4149 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") 4150 (sign_extend:DI (match_operator:SI 3 "logical_operator" 4151 [(match_operand:SI 1 "arith_reg_operand" "%r,r") 4152 (match_operand:SI 2 "logical_operand" "r,I10")])))] 4153 "TARGET_SHMEDIA" 4154 "#" 4155 "&& reload_completed" 4156 [(set (match_dup 0) (match_dup 3))] 4157{ 4158 operands[3] 4159 = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode, 4160 simplify_gen_subreg (DImode, operands[1], SImode, 0), 4161 simplify_gen_subreg (DImode, operands[2], SImode, 0)); 4162}) 4163 4164(define_insn_and_split "*logical_sidisi3" 4165 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 4166 (truncate:SI (sign_extend:DI 4167 (match_operator:SI 3 "logical_operator" 4168 [(match_operand:SI 1 "arith_reg_operand" "%r,r") 4169 (match_operand:SI 2 "logical_operand" "r,I10")]))))] 4170 "TARGET_SHMEDIA" 4171 "#" 4172 "&& 1" 4173 [(set (match_dup 0) (match_dup 3))]) 4174 4175(define_insn_and_split "*logical_sidi3_2" 4176 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") 4177 (sign_extend:DI (truncate:SI (sign_extend:DI 4178 (match_operator:SI 3 "logical_operator" 4179 [(match_operand:SI 1 "arith_reg_operand" "%r,r") 4180 (match_operand:SI 2 "logical_operand" "r,I10")])))))] 4181 "TARGET_SHMEDIA" 4182 "#" 4183 "&& 1" 4184 [(set (match_dup 0) (sign_extend:DI (match_dup 3)))]) 4185 4186(define_expand "xorsi3" 4187 [(set (match_operand:SI 0 "arith_reg_operand" "") 4188 (xor:SI (match_operand:SI 1 "logical_reg_operand" "") 4189 (match_operand:SI 2 "xor_operand" "")))] 4190 "" 4191 "") 4192 4193(define_insn "*xorsi3_compact" 4194 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r") 4195 (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") 4196 (match_operand:SI 2 "logical_operand" "K08,r")))] 4197 "TARGET_SH1" 4198 "xor %2,%0" 4199 [(set_attr "type" "arith")]) 4200 4201;; The *logical_op_t pattern helps combine eliminating sign/zero extensions 4202;; of results where one of the inputs is a T bit store. Notice that this 4203;; pattern must not match during reload. If reload picks this pattern it 4204;; will be impossible to split it afterwards. 4205(define_insn_and_split "*logical_op_t" 4206 [(set (match_operand:SI 0 "arith_reg_dest") 4207 (match_operator:SI 3 "logical_operator" 4208 [(match_operand:SI 1 "arith_reg_operand") 4209 (match_operand:SI 2 "t_reg_operand")]))] 4210 "TARGET_SH1 && can_create_pseudo_p ()" 4211 "#" 4212 "&& 1" 4213 [(set (match_dup 4) (reg:SI T_REG)) 4214 (set (match_dup 0) (match_dup 3))] 4215{ 4216 operands[4] = gen_reg_rtx (SImode); 4217 operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode, 4218 operands[1], operands[4]); 4219}) 4220 4221(define_insn "*xorsi3_media" 4222 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 4223 (xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r") 4224 (match_operand:SI 2 "xor_operand" "r,I06")))] 4225 "TARGET_SHMEDIA" 4226 "@ 4227 xor %1, %2, %0 4228 xori %1, %2, %0" 4229 [(set_attr "type" "arith_media")]) 4230 4231(define_insn "xordi3" 4232 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") 4233 (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r") 4234 (match_operand:DI 2 "xor_operand" "r,I06")))] 4235 "TARGET_SHMEDIA" 4236 "@ 4237 xor %1, %2, %0 4238 xori %1, %2, %0" 4239 [(set_attr "type" "arith_media")]) 4240 4241;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate. 4242;; converts 2 * sign extend -> logical op into logical op -> sign extend 4243(define_split 4244 [(set (match_operand:DI 0 "arith_reg_dest" "") 4245 (sign_extend:DI (match_operator 4 "binary_logical_operator" 4246 [(match_operand 1 "any_register_operand" "") 4247 (match_operand 2 "any_register_operand" "")])))] 4248 "TARGET_SHMEDIA" 4249 [(set (match_dup 5) (match_dup 4)) 4250 (set (match_dup 0) (sign_extend:DI (match_dup 5)))] 4251{ 4252 machine_mode inmode = GET_MODE (operands[1]); 4253 int offset = 0; 4254 4255 if (GET_CODE (operands[0]) == SUBREG) 4256 { 4257 offset = SUBREG_BYTE (operands[0]); 4258 operands[0] = SUBREG_REG (operands[0]); 4259 } 4260 gcc_assert (REG_P (operands[0])); 4261 if (TARGET_BIG_ENDIAN) 4262 offset += 8 - GET_MODE_SIZE (inmode); 4263 operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset); 4264}) 4265 4266;; ------------------------------------------------------------------------- 4267;; Shifts and rotates 4268;; ------------------------------------------------------------------------- 4269 4270;; Let combine see that we can get the MSB and LSB into the T bit 4271;; via shll and shlr. This allows it to plug it into insns that can have 4272;; the T bit as an input (e.g. addc). 4273;; FIXME: On SH2A use bld #0,Rn instead of shlr to avoid mutating the input. 4274(define_insn_and_split "*reg_lsb_t" 4275 [(set (reg:SI T_REG) 4276 (and:SI (match_operand:SI 0 "arith_reg_operand") 4277 (const_int 1)))] 4278 "TARGET_SH1 && can_create_pseudo_p ()" 4279 "#" 4280 "&& 1" 4281 [(const_int 0)] 4282{ 4283 emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[0])); 4284}) 4285 4286(define_insn_and_split "*reg_msb_t" 4287 [(set (reg:SI T_REG) 4288 (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand") 4289 (const_int 31)))] 4290 "TARGET_SH1 && can_create_pseudo_p ()" 4291 "#" 4292 "&& 1" 4293 [(const_int 0)] 4294{ 4295 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[0])); 4296}) 4297 4298(define_expand "rotldi3" 4299 [(set (match_operand:DI 0 "arith_reg_dest" "") 4300 (rotate:DI (match_operand:DI 1 "arith_reg_operand" "") 4301 (match_operand:HI 2 "mextr_bit_offset" "")))] 4302 "TARGET_SHMEDIA" 4303{ 4304 if (! mextr_bit_offset (operands[2], HImode)) 4305 FAIL; 4306}) 4307 4308(define_insn "rotldi3_mextr" 4309 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 4310 (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r") 4311 (match_operand:HI 2 "mextr_bit_offset" "i")))] 4312 "TARGET_SHMEDIA" 4313{ 4314 static char templ[16]; 4315 sprintf (templ, "mextr%d %%1,%%1,%%0", 4316 8 - (int) (INTVAL (operands[2]) >> 3)); 4317 return templ; 4318} 4319 [(set_attr "type" "arith_media")]) 4320 4321(define_expand "rotrdi3" 4322 [(set (match_operand:DI 0 "arith_reg_dest" "") 4323 (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "") 4324 (match_operand:HI 2 "mextr_bit_offset" "")))] 4325 "TARGET_SHMEDIA" 4326{ 4327 if (! mextr_bit_offset (operands[2], HImode)) 4328 FAIL; 4329}) 4330 4331(define_insn "rotrdi3_mextr" 4332 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 4333 (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r") 4334 (match_operand:HI 2 "mextr_bit_offset" "i")))] 4335 "TARGET_SHMEDIA" 4336{ 4337 static char templ[16]; 4338 sprintf (templ, "mextr%d %%1,%%1,%%0", (int) INTVAL (operands[2]) >> 3); 4339 return templ; 4340} 4341 [(set_attr "type" "arith_media")]) 4342 4343(define_split 4344 [(set (match_operand:DI 0 "arith_reg_dest" "") 4345 (ior:DI (zero_extend:DI (mem:QI (match_operand 1 4346 "ua_address_operand" ""))) 4347 (ashift:DI (match_operand:DI 2 "arith_reg_operand" "") 4348 (const_int 8)))) 4349 (clobber (match_operand:DI 3 "register_operand" ""))] 4350 "TARGET_SHMEDIA" 4351 [(match_dup 4) (match_dup 5)] 4352{ 4353 operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q) 4354 (operands[3], operands[1])); 4355 operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2], 4356 GEN_INT (56), GEN_INT (8)); 4357}) 4358 4359(define_expand "rotrsi3" 4360 [(set (match_operand:SI 0 "arith_reg_dest") 4361 (rotatert:SI (match_operand:SI 1 "arith_reg_operand") 4362 (match_operand:SI 2 "const_int_operand")))] 4363 "TARGET_SH1" 4364{ 4365 HOST_WIDE_INT ival = INTVAL (operands[2]); 4366 if (ival == 1) 4367 { 4368 emit_insn (gen_rotrsi3_1 (operands[0], operands[1])); 4369 DONE; 4370 } 4371 4372 FAIL; 4373}) 4374 4375(define_insn "rotrsi3_1" 4376 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4377 (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0") 4378 (const_int 1))) 4379 (set (reg:SI T_REG) 4380 (and:SI (match_dup 1) (const_int 1)))] 4381 "TARGET_SH1" 4382 "rotr %0" 4383 [(set_attr "type" "arith")]) 4384 4385;; A slimplified version of rotr for combine. 4386(define_insn "*rotrsi3_1" 4387 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4388 (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0") 4389 (const_int 1))) 4390 (clobber (reg:SI T_REG))] 4391 "TARGET_SH1" 4392 "rotr %0" 4393 [(set_attr "type" "arith")]) 4394 4395(define_insn "rotlsi3_1" 4396 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4397 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0") 4398 (const_int 1))) 4399 (set (reg:SI T_REG) 4400 (lshiftrt:SI (match_dup 1) (const_int 31)))] 4401 "TARGET_SH1" 4402 "rotl %0" 4403 [(set_attr "type" "arith")]) 4404 4405;; A simplified version of rotl for combine. 4406(define_insn "*rotlsi3_1" 4407 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4408 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0") 4409 (const_int 1))) 4410 (clobber (reg:SI T_REG))] 4411 "TARGET_SH1" 4412 "rotl %0" 4413 [(set_attr "type" "arith")]) 4414 4415(define_insn "rotlsi3_31" 4416 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4417 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0") 4418 (const_int 31))) 4419 (clobber (reg:SI T_REG))] 4420 "TARGET_SH1" 4421 "rotr %0" 4422 [(set_attr "type" "arith")]) 4423 4424(define_insn "rotlsi3_16" 4425 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4426 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r") 4427 (const_int 16)))] 4428 "TARGET_SH1" 4429 "swap.w %1,%0" 4430 [(set_attr "type" "arith")]) 4431 4432(define_expand "rotlsi3" 4433 [(set (match_operand:SI 0 "arith_reg_dest") 4434 (rotate:SI (match_operand:SI 1 "arith_reg_operand") 4435 (match_operand:SI 2 "const_int_operand")))] 4436 "TARGET_SH1" 4437{ 4438 static const char rot_tab[] = { 4439 000, 000, 000, 000, 000, 000, 010, 001, 4440 001, 001, 011, 013, 003, 003, 003, 003, 4441 003, 003, 003, 003, 003, 013, 012, 002, 4442 002, 002, 010, 000, 000, 000, 000, 000, 4443 }; 4444 4445 int count = INTVAL (operands[2]); 4446 int choice = rot_tab[count]; 4447 if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1) 4448 FAIL; 4449 choice &= 7; 4450 switch (choice) 4451 { 4452 case 0: 4453 emit_move_insn (operands[0], operands[1]); 4454 count -= (count & 16) * 2; 4455 break; 4456 case 3: 4457 emit_insn (gen_rotlsi3_16 (operands[0], operands[1])); 4458 count -= 16; 4459 break; 4460 case 1: 4461 case 2: 4462 { 4463 rtx parts[2]; 4464 parts[0] = gen_reg_rtx (SImode); 4465 parts[1] = gen_reg_rtx (SImode); 4466 emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1])); 4467 emit_move_insn (parts[choice-1], operands[1]); 4468 emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8))); 4469 emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8))); 4470 emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1])); 4471 count = (count & ~16) - 8; 4472 } 4473 } 4474 4475 for (; count > 0; count--) 4476 emit_insn (gen_rotlsi3_1 (operands[0], operands[0])); 4477 for (; count < 0; count++) 4478 emit_insn (gen_rotlsi3_31 (operands[0], operands[0])); 4479 4480 DONE; 4481}) 4482 4483(define_insn "rotlhi3_8" 4484 [(set (match_operand:HI 0 "arith_reg_dest" "=r") 4485 (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r") 4486 (const_int 8)))] 4487 "TARGET_SH1" 4488 "swap.b %1,%0" 4489 [(set_attr "type" "arith")]) 4490 4491(define_expand "rotlhi3" 4492 [(set (match_operand:HI 0 "arith_reg_operand") 4493 (rotate:HI (match_operand:HI 1 "arith_reg_operand") 4494 (match_operand:HI 2 "const_int_operand")))] 4495 "TARGET_SH1" 4496{ 4497 if (INTVAL (operands[2]) != 8) 4498 FAIL; 4499}) 4500 4501;; The rotcr and rotcl insns are used primarily in DImode shifts by one. 4502;; They can also be used to implement things like 4503;; bool t = a == b; 4504;; int x0 = (y >> 1) | (t << 31); // rotcr 4505;; int x1 = (y << 1) | t; // rotcl 4506(define_insn "rotcr" 4507 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4508 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 4509 (const_int 1)) 4510 (ashift:SI (match_operand:SI 2 "t_reg_operand") 4511 (const_int 31)))) 4512 (set (reg:SI T_REG) 4513 (and:SI (match_dup 1) (const_int 1)))] 4514 "TARGET_SH1" 4515 "rotcr %0" 4516 [(set_attr "type" "arith")]) 4517 4518(define_insn "rotcl" 4519 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 4520 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") 4521 (const_int 1)) 4522 (match_operand:SI 2 "t_reg_operand"))) 4523 (set (reg:SI T_REG) 4524 (lshiftrt:SI (match_dup 1) (const_int 31)))] 4525 "TARGET_SH1" 4526 "rotcl %0" 4527 [(set_attr "type" "arith")]) 4528 4529;; Simplified rotcr version for combine, which allows arbitrary shift 4530;; amounts for the reg. If the shift amount is '1' rotcr can be used 4531;; directly. Otherwise we have to insert a shift in between. 4532(define_insn_and_split "*rotcr" 4533 [(set (match_operand:SI 0 "arith_reg_dest") 4534 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_or_0_operand") 4535 (match_operand:SI 2 "const_int_operand")) 4536 (ashift:SI (match_operand 3 "arith_reg_or_treg_set_expr") 4537 (const_int 31)))) 4538 (clobber (reg:SI T_REG))] 4539 "TARGET_SH1 && can_create_pseudo_p ()" 4540 "#" 4541 "&& 1" 4542 [(const_int 0)] 4543{ 4544 rtx prev_set_t_insn = NULL_RTX; 4545 4546 if (!arith_reg_operand (operands[3], SImode)) 4547 { 4548 sh_treg_insns ti = sh_split_treg_set_expr (operands[3], curr_insn); 4549 if (!ti.was_treg_operand ()) 4550 prev_set_t_insn = ti.first_insn (); 4551 4552 operands[3] = get_t_reg_rtx (); 4553 4554 if (TARGET_SH2A && ti.has_trailing_nott () && operands[1] == const0_rtx) 4555 { 4556 /* Convert to a movrt, rotr sequence. */ 4557 remove_insn (ti.trailing_nott ()); 4558 rtx tmp = gen_reg_rtx (SImode); 4559 emit_insn (gen_movnegt (tmp, get_t_reg_rtx ())); 4560 emit_insn (gen_rotrsi3_1 (operands[0], tmp)); 4561 DONE; 4562 } 4563 } 4564 4565 if (operands[1] == const0_rtx) 4566 { 4567 operands[1] = gen_reg_rtx (SImode); 4568 emit_insn (gen_movt (operands[1], get_t_reg_rtx ())); 4569 } 4570 4571 if (INTVAL (operands[2]) > 1) 4572 { 4573 const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1); 4574 rtx tmp_t_reg = NULL_RTX; 4575 4576 /* If we're going to emit a shift sequence that clobbers the T_REG, 4577 try to find the previous insn that sets the T_REG and emit the 4578 shift insn before that insn, to remove the T_REG dependency. 4579 If the insn that sets the T_REG cannot be found, store the T_REG 4580 in a temporary reg and restore it after the shift. */ 4581 if (sh_lshrsi_clobbers_t_reg_p (shift_count) 4582 && ! sh_dynamicalize_shift_p (shift_count)) 4583 { 4584 if (prev_set_t_insn == NULL) 4585 prev_set_t_insn = prev_nonnote_insn_bb (curr_insn); 4586 4587 /* Skip the nott insn, which was probably inserted by the splitter 4588 of *rotcr_neg_t. Don't use one of the recog functions 4589 here during insn splitting, since that causes problems in later 4590 passes. */ 4591 if (prev_set_t_insn != NULL_RTX) 4592 { 4593 rtx pat = PATTERN (prev_set_t_insn); 4594 if (GET_CODE (pat) == SET 4595 && t_reg_operand (XEXP (pat, 0), SImode) 4596 && negt_reg_operand (XEXP (pat, 1), SImode)) 4597 prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn); 4598 } 4599 4600 if (! (prev_set_t_insn != NULL_RTX 4601 && reg_set_p (get_t_reg_rtx (), prev_set_t_insn) 4602 && ! reg_referenced_p (get_t_reg_rtx (), 4603 PATTERN (prev_set_t_insn)))) 4604 { 4605 prev_set_t_insn = NULL_RTX; 4606 tmp_t_reg = gen_reg_rtx (SImode); 4607 emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ())); 4608 } 4609 } 4610 4611 rtx shift_result = gen_reg_rtx (SImode); 4612 rtx shift_insn = gen_lshrsi3 (shift_result, operands[1], shift_count); 4613 operands[1] = shift_result; 4614 4615 /* Emit the shift insn before the insn that sets T_REG, if possible. */ 4616 if (prev_set_t_insn != NULL_RTX) 4617 emit_insn_before (shift_insn, prev_set_t_insn); 4618 else 4619 emit_insn (shift_insn); 4620 4621 /* Restore T_REG if it has been saved before. */ 4622 if (tmp_t_reg != NULL_RTX) 4623 emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx)); 4624 } 4625 4626 /* For the rotcr insn to work, operands[3] must be in T_REG. 4627 If it is not we can get it there by shifting it right one bit. 4628 In this case T_REG is not an input for this insn, thus we don't have to 4629 pay attention as of where to insert the shlr insn. */ 4630 if (! t_reg_operand (operands[3], SImode)) 4631 { 4632 /* We don't care about the shifted result here, only the T_REG. */ 4633 emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3])); 4634 operands[3] = get_t_reg_rtx (); 4635 } 4636 4637 emit_insn (gen_rotcr (operands[0], operands[1], operands[3])); 4638 DONE; 4639}) 4640 4641;; If combine tries the same as above but with swapped operands, split 4642;; it so that it will try the pattern above. 4643(define_split 4644 [(set (match_operand:SI 0 "arith_reg_dest") 4645 (ior:SI (ashift:SI (match_operand 1 "arith_reg_or_treg_set_expr") 4646 (const_int 31)) 4647 (lshiftrt:SI (match_operand:SI 2 "arith_reg_or_0_operand") 4648 (match_operand:SI 3 "const_int_operand"))))] 4649 "TARGET_SH1 && can_create_pseudo_p ()" 4650 [(parallel [(set (match_dup 0) 4651 (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3)) 4652 (ashift:SI (match_dup 1) (const_int 31)))) 4653 (clobber (reg:SI T_REG))])]) 4654 4655;; Basically the same as the rotcr pattern above, but for rotcl. 4656;; FIXME: Fold copy pasted split code for rotcr and rotcl. 4657(define_insn_and_split "*rotcl" 4658 [(set (match_operand:SI 0 "arith_reg_dest") 4659 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand") 4660 (match_operand:SI 2 "const_int_operand")) 4661 (and:SI (match_operand:SI 3 "arith_reg_or_t_reg_operand") 4662 (const_int 1)))) 4663 (clobber (reg:SI T_REG))] 4664 "TARGET_SH1" 4665 "#" 4666 "&& can_create_pseudo_p ()" 4667 [(const_int 0)] 4668{ 4669 gcc_assert (INTVAL (operands[2]) > 0); 4670 4671 if (INTVAL (operands[2]) > 1) 4672 { 4673 const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1); 4674 rtx prev_set_t_insn = NULL_RTX; 4675 rtx tmp_t_reg = NULL_RTX; 4676 4677 /* If we're going to emit a shift sequence that clobbers the T_REG, 4678 try to find the previous insn that sets the T_REG and emit the 4679 shift insn before that insn, to remove the T_REG dependency. 4680 If the insn that sets the T_REG cannot be found, store the T_REG 4681 in a temporary reg and restore it after the shift. */ 4682 if (sh_ashlsi_clobbers_t_reg_p (shift_count) 4683 && ! sh_dynamicalize_shift_p (shift_count)) 4684 { 4685 prev_set_t_insn = prev_nonnote_insn_bb (curr_insn); 4686 4687 /* Skip the nott insn, which was probably inserted by the splitter 4688 of *rotcl_neg_t. Don't use one of the recog functions 4689 here during insn splitting, since that causes problems in later 4690 passes. */ 4691 if (prev_set_t_insn != NULL_RTX) 4692 { 4693 rtx pat = PATTERN (prev_set_t_insn); 4694 if (GET_CODE (pat) == SET 4695 && t_reg_operand (XEXP (pat, 0), SImode) 4696 && negt_reg_operand (XEXP (pat, 1), SImode)) 4697 prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn); 4698 } 4699 4700 if (! (prev_set_t_insn != NULL_RTX 4701 && reg_set_p (get_t_reg_rtx (), prev_set_t_insn) 4702 && ! reg_referenced_p (get_t_reg_rtx (), 4703 PATTERN (prev_set_t_insn)))) 4704 { 4705 prev_set_t_insn = NULL_RTX; 4706 tmp_t_reg = gen_reg_rtx (SImode); 4707 emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ())); 4708 } 4709 } 4710 4711 rtx shift_result = gen_reg_rtx (SImode); 4712 rtx shift_insn = gen_ashlsi3 (shift_result, operands[1], shift_count); 4713 operands[1] = shift_result; 4714 4715 /* Emit the shift insn before the insn that sets T_REG, if possible. */ 4716 if (prev_set_t_insn != NULL_RTX) 4717 emit_insn_before (shift_insn, prev_set_t_insn); 4718 else 4719 emit_insn (shift_insn); 4720 4721 /* Restore T_REG if it has been saved before. */ 4722 if (tmp_t_reg != NULL_RTX) 4723 emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx)); 4724 } 4725 4726 /* For the rotcl insn to work, operands[3] must be in T_REG. 4727 If it is not we can get it there by shifting it right one bit. 4728 In this case T_REG is not an input for this insn, thus we don't have to 4729 pay attention as of where to insert the shlr insn. */ 4730 if (! t_reg_operand (operands[3], SImode)) 4731 { 4732 /* We don't care about the shifted result here, only the T_REG. */ 4733 emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3])); 4734 operands[3] = get_t_reg_rtx (); 4735 } 4736 4737 emit_insn (gen_rotcl (operands[0], operands[1], operands[3])); 4738 DONE; 4739}) 4740 4741;; rotcl combine pattern variations 4742(define_insn_and_split "*rotcl" 4743 [(set (match_operand:SI 0 "arith_reg_dest") 4744 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand") 4745 (match_operand:SI 2 "const_int_operand")) 4746 (match_operand 3 "treg_set_expr"))) 4747 (clobber (reg:SI T_REG))] 4748 "TARGET_SH1" 4749 "#" 4750 "&& can_create_pseudo_p ()" 4751 [(parallel [(set (match_dup 0) 4752 (ior:SI (ashift:SI (match_dup 1) (match_dup 2)) 4753 (and:SI (match_dup 3) (const_int 1)))) 4754 (clobber (reg:SI T_REG))])] 4755{ 4756 sh_split_treg_set_expr (operands[3], curr_insn); 4757 operands[3] = get_t_reg_rtx (); 4758}) 4759 4760(define_insn_and_split "*rotcl" 4761 [(set (match_operand:SI 0 "arith_reg_dest") 4762 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_or_t_reg_operand") 4763 (const_int 1)) 4764 (ashift:SI (match_operand:SI 2 "arith_reg_operand") 4765 (match_operand:SI 3 "const_int_operand")))) 4766 (clobber (reg:SI T_REG))] 4767 "TARGET_SH1" 4768 "#" 4769 "&& can_create_pseudo_p ()" 4770 [(parallel [(set (match_dup 0) 4771 (ior:SI (ashift:SI (match_dup 2) (match_dup 3)) 4772 (and:SI (match_dup 1) (const_int 1)))) 4773 (clobber (reg:SI T_REG))])]) 4774 4775(define_insn_and_split "*rotcl" 4776 [(set (match_operand:SI 0 "arith_reg_dest") 4777 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand") 4778 (match_operand:SI 2 "const_int_operand")) 4779 (lshiftrt:SI (match_operand:SI 3 "arith_reg_operand") 4780 (const_int 31)))) 4781 (clobber (reg:SI T_REG))] 4782 "TARGET_SH1" 4783 "#" 4784 "&& can_create_pseudo_p ()" 4785 [(parallel [(set (match_dup 0) 4786 (ior:SI (ashift:SI (match_dup 1) (match_dup 2)) 4787 (and:SI (reg:SI T_REG) (const_int 1)))) 4788 (clobber (reg:SI T_REG))])] 4789{ 4790 /* We don't care about the result of the left shift, only the T_REG. */ 4791 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3])); 4792}) 4793 4794(define_insn_and_split "*rotcl" 4795 [(set (match_operand:SI 0 "arith_reg_dest") 4796 (ior:SI (lshiftrt:SI (match_operand:SI 3 "arith_reg_operand") 4797 (const_int 31)) 4798 (ashift:SI (match_operand:SI 1 "arith_reg_operand") 4799 (match_operand:SI 2 "const_int_operand")))) 4800 (clobber (reg:SI T_REG))] 4801 "TARGET_SH1" 4802 "#" 4803 "&& can_create_pseudo_p ()" 4804 [(parallel [(set (match_dup 0) 4805 (ior:SI (ashift:SI (match_dup 1) (match_dup 2)) 4806 (and:SI (reg:SI T_REG) (const_int 1)))) 4807 (clobber (reg:SI T_REG))])] 4808{ 4809 /* We don't care about the result of the left shift, only the T_REG. */ 4810 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3])); 4811}) 4812 4813(define_insn_and_split "*rotcl" 4814 [(set (match_operand:SI 0 "arith_reg_dest") 4815 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand") 4816 (match_operand 2 "const_int_operand")) 4817 (zero_extract:SI (match_operand:SI 3 "arith_reg_operand") 4818 (const_int 1) 4819 (match_operand 4 "const_int_operand")))) 4820 (clobber (reg:SI T_REG))] 4821 "TARGET_SH1" 4822 "#" 4823 "&& can_create_pseudo_p ()" 4824 [(parallel [(set (match_dup 0) 4825 (ior:SI (ashift:SI (match_dup 1) (match_dup 2)) 4826 (and:SI (match_dup 5) (const_int 1)))) 4827 (clobber (reg:SI T_REG))])] 4828{ 4829 if (TARGET_SH2A && satisfies_constraint_K03 (operands[4])) 4830 { 4831 /* On SH2A we can use the bld insn to zero extract a single bit 4832 into the T bit. */ 4833 operands[5] = get_t_reg_rtx (); 4834 emit_insn (gen_bldsi_reg (operands[3], operands[4])); 4835 } 4836 else 4837 { 4838 /* If we can't use the bld insn we have to emit a tst + nott sequence 4839 to get the extracted bit into the T bit. 4840 This will probably be worse than pre-shifting the operand. */ 4841 operands[5] = gen_reg_rtx (SImode); 4842 emit_insn (gen_lshrsi3 (operands[5], operands[3], operands[4])); 4843 } 4844}) 4845 4846;; rotcr combine bridge pattern which will make combine try out more 4847;; complex patterns. 4848(define_insn_and_split "*rotcr" 4849 [(set (match_operand:SI 0 "arith_reg_dest") 4850 (ashift:SI (match_operand 1 "treg_set_expr") (const_int 31)))] 4851 "TARGET_SH1 && can_create_pseudo_p ()" 4852 "#" 4853 "&& 1" 4854 [(parallel [(set (match_dup 0) 4855 (ior:SI (lshiftrt:SI (const_int 0) (const_int 1)) 4856 (ashift:SI (match_dup 1) (const_int 31)))) 4857 (clobber (reg:SI T_REG))])]) 4858 4859(define_insn_and_split "*rotcr" 4860 [(set (match_operand:SI 0 "arith_reg_dest") 4861 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand") 4862 (const_int -2147483648)) ;; 0xffffffff80000000 4863 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand") 4864 (const_int 1)))) 4865 (clobber (reg:SI T_REG))] 4866 "TARGET_SH1" 4867 "#" 4868 "&& can_create_pseudo_p ()" 4869 [(const_int 0)] 4870{ 4871 rtx tmp = gen_reg_rtx (SImode); 4872 emit_insn (gen_shll (tmp, operands[1])); 4873 emit_insn (gen_rotcr (operands[0], operands[2], get_t_reg_rtx ())); 4874 DONE; 4875}) 4876 4877;; rotcr combine patterns for rotating in the negated T_REG value. 4878(define_insn_and_split "*rotcr_neg_t" 4879 [(set (match_operand:SI 0 "arith_reg_dest") 4880 (ior:SI (match_operand:SI 1 "negt_reg_shl31_operand") 4881 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand") 4882 (match_operand:SI 3 "const_int_operand")))) 4883 (clobber (reg:SI T_REG))] 4884 "TARGET_SH1" 4885 "#" 4886 "&& can_create_pseudo_p ()" 4887 [(parallel [(set (match_dup 0) 4888 (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3)) 4889 (ashift:SI (reg:SI T_REG) (const_int 31)))) 4890 (clobber (reg:SI T_REG))])] 4891{ 4892 emit_insn (gen_nott (get_t_reg_rtx ())); 4893}) 4894 4895(define_insn_and_split "*rotcr_neg_t" 4896 [(set (match_operand:SI 0 "arith_reg_dest") 4897 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand") 4898 (match_operand:SI 2 "const_int_operand")) 4899 (match_operand:SI 3 "negt_reg_shl31_operand"))) 4900 (clobber (reg:SI T_REG))] 4901 "TARGET_SH1" 4902 "#" 4903 "&& can_create_pseudo_p ()" 4904 [(parallel [(set (match_dup 0) 4905 (ior:SI (lshiftrt:SI (match_dup 1) (match_dup 2)) 4906 (ashift:SI (reg:SI T_REG) (const_int 31)))) 4907 (clobber (reg:SI T_REG))])] 4908{ 4909 emit_insn (gen_nott (get_t_reg_rtx ())); 4910}) 4911 4912;; rotcl combine patterns for rotating in the negated T_REG value. 4913;; For some strange reason these have to be specified as splits which combine 4914;; will pick up. If they are specified as insn_and_split like the 4915;; *rotcr_neg_t patterns above, combine would recognize them successfully 4916;; but not emit them on non-SH2A targets. 4917(define_split 4918 [(set (match_operand:SI 0 "arith_reg_dest") 4919 (ior:SI (match_operand:SI 1 "negt_reg_operand") 4920 (ashift:SI (match_operand:SI 2 "arith_reg_operand") 4921 (match_operand:SI 3 "const_int_operand"))))] 4922 "TARGET_SH1" 4923 [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1))) 4924 (parallel [(set (match_dup 0) 4925 (ior:SI (ashift:SI (match_dup 2) (match_dup 3)) 4926 (and:SI (reg:SI T_REG) (const_int 1)))) 4927 (clobber (reg:SI T_REG))])]) 4928 4929(define_split 4930 [(set (match_operand:SI 0 "arith_reg_dest") 4931 (ior:SI (ashift:SI (match_operand:SI 2 "arith_reg_operand") 4932 (match_operand:SI 3 "const_int_operand")) 4933 (match_operand:SI 1 "negt_reg_operand")))] 4934 "TARGET_SH1" 4935 [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1))) 4936 (parallel [(set (match_dup 0) 4937 (ior:SI (ashift:SI (match_dup 2) (match_dup 3)) 4938 (and:SI (reg:SI T_REG) (const_int 1)))) 4939 (clobber (reg:SI T_REG))])]) 4940 4941;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4942;; SImode shift left 4943 4944(define_expand "ashlsi3" 4945 [(set (match_operand:SI 0 "arith_reg_operand" "") 4946 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "") 4947 (match_operand:SI 2 "shift_count_operand" "")))] 4948 "" 4949{ 4950 if (TARGET_SHMEDIA) 4951 { 4952 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) 4953 { 4954 operands[2] = GEN_INT (-INTVAL (operands[2])); 4955 emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2])); 4956 DONE; 4957 } 4958 emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2])); 4959 DONE; 4960 } 4961 if (TARGET_DYNSHIFT 4962 && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2])) 4963 operands[2] = force_reg (SImode, operands[2]); 4964 4965 /* If the ashlsi3_* insn is going to clobber the T_REG it must be 4966 expanded here. */ 4967 if (CONST_INT_P (operands[2]) 4968 && sh_ashlsi_clobbers_t_reg_p (operands[2]) 4969 && ! sh_dynamicalize_shift_p (operands[2])) 4970 { 4971 emit_insn (gen_ashlsi3_n_clobbers_t (operands[0], operands[1], 4972 operands[2])); 4973 DONE; 4974 } 4975 4976 /* Expand a library call for the dynamic shift. */ 4977 if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT) 4978 { 4979 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]); 4980 rtx funcaddr = gen_reg_rtx (Pmode); 4981 function_symbol (funcaddr, "__ashlsi3_r0", SFUNC_STATIC); 4982 emit_insn (gen_ashlsi3_d_call (operands[0], operands[2], funcaddr)); 4983 4984 DONE; 4985 } 4986}) 4987 4988(define_insn "ashlsi3_k" 4989 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 4990 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0") 4991 (match_operand:SI 2 "p27_shift_count_operand" "M,P27")))] 4992 "TARGET_SH1" 4993 "@ 4994 add %0,%0 4995 shll%O2 %0" 4996 [(set_attr "type" "arith")]) 4997 4998(define_insn_and_split "ashlsi3_d" 4999 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5000 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") 5001 (match_operand:SI 2 "shift_count_operand" "r")))] 5002 "TARGET_DYNSHIFT" 5003 "shld %2,%0" 5004 "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2]) 5005 && ! sh_ashlsi_clobbers_t_reg_p (operands[2])" 5006 [(const_int 0)] 5007{ 5008 if (satisfies_constraint_P27 (operands[2])) 5009 { 5010 emit_insn (gen_ashlsi3_k (operands[0], operands[1], operands[2])); 5011 DONE; 5012 } 5013 else if (! satisfies_constraint_P27 (operands[2])) 5014 { 5015 /* This must happen before reload, otherwise the constant will be moved 5016 into a register due to the "r" constraint, after which this split 5017 cannot be done anymore. 5018 Unfortunately the move insn will not always be eliminated. 5019 Also, here we must not create a shift sequence that clobbers the 5020 T_REG. */ 5021 emit_move_insn (operands[0], operands[1]); 5022 gen_shifty_op (ASHIFT, operands); 5023 DONE; 5024 } 5025 5026 FAIL; 5027} 5028 [(set_attr "type" "dyn_shift")]) 5029 5030;; If dynamic shifts are not available use a library function. 5031;; By specifying the pattern we reduce the number of call clobbered regs. 5032;; In order to make combine understand the truncation of the shift amount 5033;; operand we have to allow it to use pseudo regs for the shift operands. 5034(define_insn "ashlsi3_d_call" 5035 [(set (match_operand:SI 0 "arith_reg_dest" "=z") 5036 (ashift:SI (reg:SI R4_REG) 5037 (and:SI (match_operand:SI 1 "arith_reg_operand" "z") 5038 (const_int 31)))) 5039 (use (match_operand:SI 2 "arith_reg_operand" "r")) 5040 (clobber (reg:SI T_REG)) 5041 (clobber (reg:SI PR_REG))] 5042 "TARGET_SH1 && !TARGET_DYNSHIFT" 5043 "jsr @%2%#" 5044 [(set_attr "type" "sfunc") 5045 (set_attr "needs_delay_slot" "yes")]) 5046 5047(define_insn_and_split "ashlsi3_n" 5048 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5049 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") 5050 (match_operand:SI 2 "not_p27_shift_count_operand" "")))] 5051 "TARGET_SH1 && ! sh_ashlsi_clobbers_t_reg_p (operands[2])" 5052 "#" 5053 "&& (reload_completed 5054 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))" 5055 [(const_int 0)] 5056{ 5057 if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()) 5058 { 5059 /* If this pattern was picked and dynamic shifts are supported, switch 5060 to dynamic shift pattern before reload. */ 5061 operands[2] = force_reg (SImode, operands[2]); 5062 emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2])); 5063 } 5064 else 5065 gen_shifty_op (ASHIFT, operands); 5066 5067 DONE; 5068}) 5069 5070(define_insn_and_split "ashlsi3_n_clobbers_t" 5071 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5072 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") 5073 (match_operand:SI 2 "not_p27_shift_count_operand" ""))) 5074 (clobber (reg:SI T_REG))] 5075 "TARGET_SH1 && sh_ashlsi_clobbers_t_reg_p (operands[2])" 5076 "#" 5077 "&& (reload_completed || INTVAL (operands[2]) == 31 5078 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))" 5079 [(const_int 0)] 5080{ 5081 if (INTVAL (operands[2]) == 31) 5082 { 5083 /* If the shift amount is 31 we split into a different sequence before 5084 reload so that it gets a chance to allocate R0 for the sequence. 5085 If it fails to do so (due to pressure on R0), it will take one insn 5086 more for the and. */ 5087 emit_insn (gen_andsi3 (operands[0], operands[1], const1_rtx)); 5088 emit_insn (gen_rotlsi3_31 (operands[0], operands[0])); 5089 } 5090 else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()) 5091 { 5092 /* If this pattern was picked and dynamic shifts are supported, switch 5093 to dynamic shift pattern before reload. */ 5094 operands[2] = force_reg (SImode, operands[2]); 5095 emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2])); 5096 } 5097 else 5098 gen_shifty_op (ASHIFT, operands); 5099 5100 DONE; 5101}) 5102 5103(define_insn "shll" 5104 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5105 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1))) 5106 (set (reg:SI T_REG) 5107 (lt:SI (match_dup 1) (const_int 0)))] 5108 "TARGET_SH1" 5109 "shll %0" 5110 [(set_attr "type" "arith")]) 5111 5112(define_insn "*ashlsi_c_void" 5113 [(set (reg:SI T_REG) 5114 (lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0))) 5115 (clobber (match_scratch:SI 1 "=0"))] 5116 "TARGET_SH1 && cse_not_expected" 5117 "shll %0" 5118 [(set_attr "type" "arith")]) 5119 5120(define_peephole2 5121 [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0)) 5122 (set (reg:SI T_REG) 5123 (gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))] 5124 "TARGET_SH1 5125 && peep2_reg_dead_p (2, operands[0]) 5126 && peep2_reg_dead_p (2, operands[1])" 5127 [(const_int 0)] 5128{ 5129 emit_insn (gen_shll (operands[1], operands[1])); 5130 DONE; 5131}) 5132 5133(define_insn "ashlsi3_media" 5134 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 5135 (ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r") 5136 (match_operand:SI 2 "shift_count_operand" "r,n")))] 5137 "TARGET_SHMEDIA" 5138 "@ 5139 shlld.l %1, %2, %0 5140 shlli.l %1, %2, %0" 5141 [(set_attr "type" "arith_media") 5142 (set_attr "highpart" "ignore")]) 5143 5144;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5145;; HImode shift left 5146 5147(define_expand "ashlhi3" 5148 [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "") 5149 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "") 5150 (match_operand:SI 2 "nonmemory_operand" ""))) 5151 (clobber (reg:SI T_REG))])] 5152 "TARGET_SH1" 5153{ 5154 if (!CONST_INT_P (operands[2])) 5155 FAIL; 5156 /* It may be possible to call gen_ashlhi3 directly with more generic 5157 operands. Make sure operands[1] is a HImode register here. */ 5158 if (!arith_reg_operand (operands[1], HImode)) 5159 operands[1] = copy_to_mode_reg (HImode, operands[1]); 5160}) 5161 5162(define_insn "ashlhi3_k" 5163 [(set (match_operand:HI 0 "arith_reg_dest" "=r,r") 5164 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0") 5165 (match_operand:HI 2 "const_int_operand" "M,P27")))] 5166 "TARGET_SH1 && satisfies_constraint_P27 (operands[2])" 5167 "@ 5168 add %0,%0 5169 shll%O2 %0" 5170 [(set_attr "type" "arith")]) 5171 5172(define_insn_and_split "*ashlhi3_n" 5173 [(set (match_operand:HI 0 "arith_reg_dest" "=r") 5174 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0") 5175 (match_operand:HI 2 "const_int_operand" "n"))) 5176 (clobber (reg:SI T_REG))] 5177 "TARGET_SH1" 5178 "#" 5179 "&& reload_completed" 5180 [(use (reg:SI R0_REG))] 5181{ 5182 gen_shifty_hi_op (ASHIFT, operands); 5183 DONE; 5184}) 5185 5186;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5187;; DImode shift left 5188 5189(define_expand "ashldi3" 5190 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "") 5191 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "") 5192 (match_operand:DI 2 "immediate_operand" ""))) 5193 (clobber (reg:SI T_REG))])] 5194 "" 5195{ 5196 if (TARGET_SHMEDIA) 5197 { 5198 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) 5199 { 5200 operands[2] = GEN_INT (-INTVAL (operands[2])); 5201 emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2])); 5202 DONE; 5203 } 5204 emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2])); 5205 DONE; 5206 } 5207 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1) 5208 { 5209 emit_insn (gen_ashldi3_k (operands[0], operands[1])); 5210 DONE; 5211 } 5212 else if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 32) 5213 { 5214 emit_insn (gen_ashldi3_std (operands[0], operands[1], operands[2])); 5215 DONE; 5216 } 5217 else 5218 FAIL; 5219}) 5220 5221;; Expander for DImode shift left with SImode operations. 5222(define_expand "ashldi3_std" 5223 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 5224 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r") 5225 (match_operand:DI 2 "const_int_operand" "n")))] 5226 "TARGET_SH1 && INTVAL (operands[2]) < 32" 5227{ 5228 rtx low_src = gen_lowpart (SImode, operands[1]); 5229 rtx high_src = gen_highpart (SImode, operands[1]); 5230 rtx dst = gen_reg_rtx (DImode); 5231 rtx low_dst = gen_lowpart (SImode, dst); 5232 rtx high_dst = gen_highpart (SImode, dst); 5233 rtx tmp0 = gen_reg_rtx (SImode); 5234 rtx tmp1 = gen_reg_rtx (SImode); 5235 5236 emit_insn (gen_lshrsi3 (tmp0, low_src, GEN_INT (32 - INTVAL (operands[2])))); 5237 emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2])); 5238 emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2])); 5239 emit_insn (gen_iorsi3 (high_dst, tmp0, tmp1)); 5240 emit_move_insn (operands[0], dst); 5241 DONE; 5242}) 5243 5244(define_insn_and_split "ashldi3_k" 5245 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 5246 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0") 5247 (const_int 1))) 5248 (clobber (reg:SI T_REG))] 5249 "TARGET_SH1" 5250 "#" 5251 "&& reload_completed" 5252 [(const_int 0)] 5253{ 5254 rtx high = gen_highpart (SImode, operands[0]); 5255 rtx low = gen_lowpart (SImode, operands[0]); 5256 emit_insn (gen_shll (low, low)); 5257 emit_insn (gen_rotcl (high, high, get_t_reg_rtx ())); 5258 DONE; 5259}) 5260 5261(define_insn "ashldi3_media" 5262 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") 5263 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r") 5264 (match_operand:DI 2 "shift_count_operand" "r,n")))] 5265 "TARGET_SHMEDIA" 5266 "@ 5267 shlld %1, %2, %0 5268 shlli %1, %2, %0" 5269 [(set_attr "type" "arith_media")]) 5270 5271(define_insn "*ashldisi3_media" 5272 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0) 5273 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r") 5274 (match_operand:DI 2 "const_int_operand" "n")))] 5275 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32" 5276 "shlli.l %1, %2, %0" 5277 [(set_attr "type" "arith_media") 5278 (set_attr "highpart" "ignore")]) 5279 5280;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5281;; SImode arithmetic shift right 5282;; 5283;; We can't do HImode right shifts correctly unless we start out with an 5284;; explicit zero / sign extension; doing that would result in worse overall 5285;; code, so just let the machine independent code widen the mode. 5286;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 . 5287 5288(define_expand "ashrsi3" 5289 [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "") 5290 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "") 5291 (match_operand:SI 2 "nonmemory_operand" ""))) 5292 (clobber (reg:SI T_REG))])] 5293 "" 5294{ 5295 if (TARGET_SHMEDIA) 5296 { 5297 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) 5298 { 5299 operands[2] = GEN_INT (-INTVAL (operands[2])); 5300 emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2])); 5301 DONE; 5302 } 5303 emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2])); 5304 DONE; 5305 } 5306 if (expand_ashiftrt (operands)) 5307 DONE; 5308 else 5309 FAIL; 5310}) 5311 5312(define_insn "shar" 5313 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5314 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 5315 (const_int 1))) 5316 (set (reg:SI T_REG) 5317 (and:SI (match_dup 1) (const_int 1)))] 5318 "TARGET_SH1" 5319 "shar %0" 5320 [(set_attr "type" "arith")]) 5321 5322(define_insn "ashrsi3_k" 5323 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5324 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 5325 (match_operand:SI 2 "const_int_operand" "M"))) 5326 (clobber (reg:SI T_REG))] 5327 "TARGET_SH1 && INTVAL (operands[2]) == 1" 5328 "shar %0" 5329 [(set_attr "type" "arith")]) 5330 5331(define_insn_and_split "ashrsi2_16" 5332 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5333 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r") 5334 (const_int 16)))] 5335 "TARGET_SH1" 5336 "#" 5337 "&& 1" 5338 [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16))) 5339 (set (match_dup 0) (sign_extend:SI (match_dup 2)))] 5340{ 5341 operands[2] = gen_lowpart (HImode, operands[0]); 5342}) 5343 5344(define_insn_and_split "ashrsi2_31" 5345 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5346 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 5347 (const_int 31))) 5348 (clobber (reg:SI T_REG))] 5349 "TARGET_SH1" 5350 "#" 5351 "&& 1" 5352 [(const_int 0)] 5353{ 5354 emit_insn (gen_shll (operands[0], operands[1])); 5355 emit_insn (gen_mov_neg_si_t (operands[0], get_t_reg_rtx ())); 5356 DONE; 5357}) 5358 5359;; If the shift amount is changed by combine it will try to plug the 5360;; use on the symbol of the library function and the PR clobber. 5361(define_insn_and_split "*ashrsi2_31" 5362 [(set (match_operand:SI 0 "arith_reg_dest") 5363 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand") 5364 (const_int 31))) 5365 (clobber (reg:SI T_REG)) 5366 (clobber (reg:SI PR_REG)) 5367 (use (match_operand:SI 2 "symbol_ref_operand"))] 5368 "TARGET_SH1" 5369 "#" 5370 "&& 1" 5371 [(parallel [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31))) 5372 (clobber (reg:SI T_REG))])]) 5373 5374(define_insn "ashrsi3_d" 5375 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5376 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 5377 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))] 5378 "TARGET_DYNSHIFT" 5379 "shad %2,%0" 5380 [(set_attr "type" "dyn_shift")]) 5381 5382(define_insn "ashrsi3_n" 5383 [(set (reg:SI R4_REG) 5384 (ashiftrt:SI (reg:SI R4_REG) 5385 (match_operand:SI 0 "const_int_operand" "i"))) 5386 (clobber (reg:SI T_REG)) 5387 (clobber (reg:SI PR_REG)) 5388 (use (match_operand:SI 1 "arith_reg_operand" "r"))] 5389 "TARGET_SH1" 5390 "jsr @%1%#" 5391 [(set_attr "type" "sfunc") 5392 (set_attr "needs_delay_slot" "yes")]) 5393 5394(define_insn "ashrsi3_media" 5395 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 5396 (ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r") 5397 (match_operand:SI 2 "shift_count_operand" "r,n")))] 5398 "TARGET_SHMEDIA" 5399 "@ 5400 shard.l %1, %2, %0 5401 shari.l %1, %2, %0" 5402 [(set_attr "type" "arith_media") 5403 (set_attr "highpart" "ignore")]) 5404 5405;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5406;; DImode arithmetic shift right 5407 5408(define_expand "ashrdi3" 5409 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "") 5410 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "") 5411 (match_operand:DI 2 "immediate_operand" ""))) 5412 (clobber (reg:SI T_REG))])] 5413 "" 5414{ 5415 if (TARGET_SHMEDIA) 5416 { 5417 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) 5418 { 5419 operands[2] = GEN_INT (-INTVAL (operands[2])); 5420 emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2])); 5421 DONE; 5422 } 5423 emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2])); 5424 DONE; 5425 } 5426 if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1) 5427 FAIL; 5428}) 5429 5430(define_insn_and_split "ashrdi3_k" 5431 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 5432 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0") 5433 (const_int 1))) 5434 (clobber (reg:SI T_REG))] 5435 "TARGET_SH1" 5436 "#" 5437 "&& reload_completed" 5438 [(const_int 0)] 5439{ 5440 rtx high = gen_highpart (SImode, operands[0]); 5441 rtx low = gen_lowpart (SImode, operands[0]); 5442 emit_insn (gen_shar (high, high)); 5443 emit_insn (gen_rotcr (low, low, get_t_reg_rtx ())); 5444 DONE; 5445}) 5446 5447(define_insn "ashrdi3_media" 5448 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r") 5449 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r") 5450 (match_operand:DI 2 "shift_count_operand" "r,n")))] 5451 "TARGET_SHMEDIA 5452 && (arith_reg_dest (operands[0], DImode) 5453 || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) >= 32))" 5454 "@ 5455 shard %1, %2, %0 5456 shari %1, %2, %0" 5457 [(set_attr "type" "arith_media")]) 5458 5459(define_insn "*ashrdisi3_media" 5460 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0) 5461 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r") 5462 (match_operand:DI 2 "const_int_operand" "n")))] 5463 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32" 5464 "shari.l %1, %2, %0" 5465 [(set_attr "type" "arith_media") 5466 (set_attr "highpart" "ignore")]) 5467 5468(define_insn "ashrdisi3_media_high" 5469 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5470 (truncate:SI 5471 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r") 5472 (match_operand:DI 2 "const_int_operand" "n"))))] 5473 "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32" 5474 "shari %1, %2, %0" 5475 [(set_attr "type" "arith_media")]) 5476 5477(define_insn "ashrdisi3_media_opaque" 5478 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5479 (unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r") 5480 (match_operand:DI 2 "const_int_operand" "n")] 5481 UNSPEC_ASHIFTRT))] 5482 "TARGET_SHMEDIA" 5483 "shari %1, %2, %0" 5484 [(set_attr "type" "arith_media")]) 5485 5486;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5487;; SImode logical shift right 5488 5489(define_expand "lshrsi3" 5490 [(set (match_operand:SI 0 "arith_reg_dest" "") 5491 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "") 5492 (match_operand:SI 2 "shift_count_operand" "")))] 5493 "" 5494{ 5495 if (TARGET_SHMEDIA) 5496 { 5497 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) 5498 { 5499 operands[2] = GEN_INT (-INTVAL (operands[2])); 5500 emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2])); 5501 DONE; 5502 } 5503 emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2])); 5504 DONE; 5505 } 5506 5507 /* If a dynamic shift is supposed to be used, expand the lshrsi3_d insn 5508 here, otherwise the pattern will never match due to the shift amount reg 5509 negation. */ 5510 if (TARGET_DYNSHIFT 5511 && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2])) 5512 { 5513 rtx neg_count = force_reg (SImode, 5514 gen_int_mode (- INTVAL (operands[2]), SImode)); 5515 emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count)); 5516 DONE; 5517 } 5518 5519 if (TARGET_DYNSHIFT && ! CONST_INT_P (operands[2])) 5520 { 5521 rtx neg_count = gen_reg_rtx (SImode); 5522 emit_insn (gen_negsi2 (neg_count, operands[2])); 5523 emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count)); 5524 DONE; 5525 } 5526 5527 /* If the lshrsi3_* insn is going to clobber the T_REG it must be 5528 expanded here. */ 5529 if (CONST_INT_P (operands[2]) 5530 && sh_lshrsi_clobbers_t_reg_p (operands[2]) 5531 && ! sh_dynamicalize_shift_p (operands[2])) 5532 { 5533 emit_insn (gen_lshrsi3_n_clobbers_t (operands[0], operands[1], 5534 operands[2])); 5535 DONE; 5536 } 5537 5538 /* Expand a library call for the dynamic shift. */ 5539 if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT) 5540 { 5541 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]); 5542 rtx funcaddr = gen_reg_rtx (Pmode); 5543 function_symbol (funcaddr, "__lshrsi3_r0", SFUNC_STATIC); 5544 emit_insn (gen_lshrsi3_d_call (operands[0], operands[2], funcaddr)); 5545 DONE; 5546 } 5547}) 5548 5549(define_insn "lshrsi3_k" 5550 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5551 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 5552 (match_operand:SI 2 "p27_rshift_count_operand" "P27")))] 5553 "TARGET_SH1" 5554 "shlr%O2 %0" 5555 [(set_attr "type" "arith")]) 5556 5557(define_insn_and_split "lshrsi3_d" 5558 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5559 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 5560 (neg:SI (match_operand:SI 2 "shift_count_operand" "r"))))] 5561 "TARGET_DYNSHIFT" 5562 "shld %2,%0" 5563 "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2]) 5564 && ! sh_lshrsi_clobbers_t_reg_p (operands[2])" 5565 [(const_int 0)] 5566{ 5567 if (satisfies_constraint_P27 (operands[2])) 5568 { 5569 /* This will not be done for a shift amount of 1, because it would 5570 clobber the T_REG. */ 5571 emit_insn (gen_lshrsi3_k (operands[0], operands[1], operands[2])); 5572 DONE; 5573 } 5574 else if (! satisfies_constraint_P27 (operands[2])) 5575 { 5576 /* This must happen before reload, otherwise the constant will be moved 5577 into a register due to the "r" constraint, after which this split 5578 cannot be done anymore. 5579 Unfortunately the move insn will not always be eliminated. 5580 Also, here we must not create a shift sequence that clobbers the 5581 T_REG. */ 5582 emit_move_insn (operands[0], operands[1]); 5583 gen_shifty_op (LSHIFTRT, operands); 5584 DONE; 5585 } 5586 5587 FAIL; 5588} 5589 [(set_attr "type" "dyn_shift")]) 5590 5591;; If dynamic shifts are not available use a library function. 5592;; By specifying the pattern we reduce the number of call clobbered regs. 5593;; In order to make combine understand the truncation of the shift amount 5594;; operand we have to allow it to use pseudo regs for the shift operands. 5595(define_insn "lshrsi3_d_call" 5596 [(set (match_operand:SI 0 "arith_reg_dest" "=z") 5597 (lshiftrt:SI (reg:SI R4_REG) 5598 (and:SI (match_operand:SI 1 "arith_reg_operand" "z") 5599 (const_int 31)))) 5600 (use (match_operand:SI 2 "arith_reg_operand" "r")) 5601 (clobber (reg:SI T_REG)) 5602 (clobber (reg:SI PR_REG))] 5603 "TARGET_SH1 && !TARGET_DYNSHIFT" 5604 "jsr @%2%#" 5605 [(set_attr "type" "sfunc") 5606 (set_attr "needs_delay_slot" "yes")]) 5607 5608(define_insn_and_split "lshrsi3_n" 5609 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5610 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 5611 (match_operand:SI 2 "not_p27_rshift_count_operand")))] 5612 "TARGET_SH1 && ! sh_lshrsi_clobbers_t_reg_p (operands[2])" 5613 "#" 5614 "&& (reload_completed 5615 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))" 5616 [(const_int 0)] 5617{ 5618 if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()) 5619 { 5620 /* If this pattern was picked and dynamic shifts are supported, switch 5621 to dynamic shift pattern before reload. */ 5622 operands[2] = force_reg (SImode, 5623 gen_int_mode (- INTVAL (operands[2]), SImode)); 5624 emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2])); 5625 } 5626 else 5627 gen_shifty_op (LSHIFTRT, operands); 5628 5629 DONE; 5630}) 5631 5632;; The lshrsi3_n_clobbers_t pattern also works as a simplified version of 5633;; the shlr pattern. 5634(define_insn_and_split "lshrsi3_n_clobbers_t" 5635 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5636 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 5637 (match_operand:SI 2 "not_p27_rshift_count_operand"))) 5638 (clobber (reg:SI T_REG))] 5639 "TARGET_SH1 && sh_lshrsi_clobbers_t_reg_p (operands[2])" 5640 "#" 5641 "&& (reload_completed || INTVAL (operands[2]) == 31 5642 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))" 5643 [(const_int 0)] 5644{ 5645 if (INTVAL (operands[2]) == 31) 5646 { 5647 emit_insn (gen_shll (operands[0], operands[1])); 5648 emit_insn (gen_movt (operands[0], get_t_reg_rtx ())); 5649 } 5650 else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()) 5651 { 5652 /* If this pattern was picked and dynamic shifts are supported, switch 5653 to dynamic shift pattern before reload. */ 5654 operands[2] = force_reg (SImode, 5655 gen_int_mode (- INTVAL (operands[2]), SImode)); 5656 emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2])); 5657 } 5658 else 5659 gen_shifty_op (LSHIFTRT, operands); 5660 5661 DONE; 5662}) 5663 5664(define_insn "shlr" 5665 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5666 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 5667 (const_int 1))) 5668 (set (reg:SI T_REG) 5669 (and:SI (match_dup 1) (const_int 1)))] 5670 "TARGET_SH1" 5671 "shlr %0" 5672 [(set_attr "type" "arith")]) 5673 5674(define_insn "lshrsi3_media" 5675 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 5676 (lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r") 5677 (match_operand:SI 2 "shift_count_operand" "r,n")))] 5678 "TARGET_SHMEDIA" 5679 "@ 5680 shlrd.l %1, %2, %0 5681 shlri.l %1, %2, %0" 5682 [(set_attr "type" "arith_media") 5683 (set_attr "highpart" "ignore")]) 5684 5685;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5686;; DImode logical shift right 5687 5688(define_expand "lshrdi3" 5689 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "") 5690 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "") 5691 (match_operand:DI 2 "immediate_operand" ""))) 5692 (clobber (reg:SI T_REG))])] 5693 "" 5694{ 5695 if (TARGET_SHMEDIA) 5696 { 5697 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) 5698 { 5699 operands[2] = GEN_INT (-INTVAL (operands[2])); 5700 emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2])); 5701 DONE; 5702 } 5703 emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2])); 5704 DONE; 5705 } 5706 if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1) 5707 FAIL; 5708}) 5709 5710(define_insn_and_split "lshrdi3_k" 5711 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 5712 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0") 5713 (const_int 1))) 5714 (clobber (reg:SI T_REG))] 5715 "TARGET_SH1" 5716 "#" 5717 "&& reload_completed" 5718 [(const_int 0)] 5719{ 5720 rtx high = gen_highpart (SImode, operands[0]); 5721 rtx low = gen_lowpart (SImode, operands[0]); 5722 emit_insn (gen_shlr (high, high)); 5723 emit_insn (gen_rotcr (low, low, get_t_reg_rtx ())); 5724 DONE; 5725}) 5726 5727(define_insn "lshrdi3_media" 5728 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r") 5729 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r") 5730 (match_operand:DI 2 "shift_count_operand" "r,n")))] 5731 "TARGET_SHMEDIA 5732 && (arith_reg_dest (operands[0], DImode) 5733 || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) > 32))" 5734 "@ 5735 shlrd %1, %2, %0 5736 shlri %1, %2, %0" 5737 [(set_attr "type" "arith_media")]) 5738 5739(define_insn "*lshrdisi3_media" 5740 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0) 5741 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r") 5742 (match_operand:DI 2 "const_int_operand" "n")))] 5743 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32" 5744 "shlri.l %1, %2, %0" 5745 [(set_attr "type" "arith_media") 5746 (set_attr "highpart" "ignore")]) 5747 5748;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5749;; Combined left/right shifts 5750 5751(define_split 5752 [(set (match_operand:SI 0 "register_operand" "") 5753 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "") 5754 (match_operand:SI 2 "const_int_operand" "")) 5755 (match_operand:SI 3 "const_int_operand" "")))] 5756 "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32" 5757 [(use (reg:SI R0_REG))] 5758{ 5759 if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) 5760 FAIL; 5761 DONE; 5762}) 5763 5764(define_split 5765 [(set (match_operand:SI 0 "register_operand" "") 5766 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "") 5767 (match_operand:SI 2 "const_int_operand" "")) 5768 (match_operand:SI 3 "const_int_operand" ""))) 5769 (clobber (reg:SI T_REG))] 5770 "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32" 5771 [(use (reg:SI R0_REG))] 5772{ 5773 if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) 5774 FAIL; 5775 DONE; 5776}) 5777 5778(define_insn "" 5779 [(set (match_operand:SI 0 "register_operand" "=r") 5780 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0") 5781 (match_operand:SI 2 "const_int_operand" "n")) 5782 (match_operand:SI 3 "const_int_operand" "n"))) 5783 (clobber (reg:SI T_REG))] 5784 "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1" 5785 "#" 5786 [(set (attr "length") 5787 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2)) 5788 (const_string "4") 5789 (eq (symbol_ref "shl_and_length (insn)") (const_int 3)) 5790 (const_string "6") 5791 (eq (symbol_ref "shl_and_length (insn)") (const_int 4)) 5792 (const_string "8") 5793 (eq (symbol_ref "shl_and_length (insn)") (const_int 5)) 5794 (const_string "10") 5795 (eq (symbol_ref "shl_and_length (insn)") (const_int 6)) 5796 (const_string "12") 5797 (eq (symbol_ref "shl_and_length (insn)") (const_int 7)) 5798 (const_string "14") 5799 (eq (symbol_ref "shl_and_length (insn)") (const_int 8)) 5800 (const_string "16")] 5801 (const_string "18"))) 5802 (set_attr "type" "arith")]) 5803 5804(define_insn "" 5805 [(set (match_operand:SI 0 "register_operand" "=z") 5806 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0") 5807 (match_operand:SI 2 "const_int_operand" "n")) 5808 (match_operand:SI 3 "const_int_operand" "n"))) 5809 (clobber (reg:SI T_REG))] 5810 "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2" 5811 "#" 5812 [(set (attr "length") 5813 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2)) 5814 (const_string "4") 5815 (eq (symbol_ref "shl_and_length (insn)") (const_int 3)) 5816 (const_string "6") 5817 (eq (symbol_ref "shl_and_length (insn)") (const_int 4)) 5818 (const_string "8")] 5819 (const_string "10"))) 5820 (set_attr "type" "arith")]) 5821 5822;; shift left / and combination with a scratch register: The combine pass 5823;; does not accept the individual instructions, even though they are 5824;; cheap. But it needs a precise description so that it is usable after 5825;; reload. 5826(define_insn "and_shl_scratch" 5827 [(set (match_operand:SI 0 "register_operand" "=r,&r") 5828 (lshiftrt:SI 5829 (ashift:SI 5830 (and:SI 5831 (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0") 5832 (match_operand:SI 2 "const_int_operand" "N,n")) 5833 (match_operand:SI 3 "" "0,r")) 5834 (match_operand:SI 4 "const_int_operand" "n,n")) 5835 (match_operand:SI 5 "const_int_operand" "n,n"))) 5836 (clobber (reg:SI T_REG))] 5837 "TARGET_SH1" 5838 "#" 5839 [(set (attr "length") 5840 (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2)) 5841 (const_string "4") 5842 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3)) 5843 (const_string "6") 5844 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4)) 5845 (const_string "8") 5846 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5)) 5847 (const_string "10")] 5848 (const_string "12"))) 5849 (set_attr "type" "arith")]) 5850 5851(define_split 5852 [(set (match_operand:SI 0 "register_operand" "") 5853 (lshiftrt:SI 5854 (ashift:SI 5855 (and:SI 5856 (lshiftrt:SI (match_operand:SI 1 "register_operand" "") 5857 (match_operand:SI 2 "const_int_operand" "")) 5858 (match_operand:SI 3 "register_operand" "")) 5859 (match_operand:SI 4 "const_int_operand" "")) 5860 (match_operand:SI 5 "const_int_operand" ""))) 5861 (clobber (reg:SI T_REG))] 5862 "TARGET_SH1" 5863 [(use (reg:SI R0_REG))] 5864{ 5865 rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1]; 5866 5867 if (INTVAL (operands[2])) 5868 { 5869 gen_shifty_op (LSHIFTRT, operands); 5870 } 5871 emit_insn (gen_andsi3 (operands[0], operands[0], and_source)); 5872 operands[2] = operands[4]; 5873 gen_shifty_op (ASHIFT, operands); 5874 if (INTVAL (operands[5])) 5875 { 5876 operands[2] = operands[5]; 5877 gen_shifty_op (LSHIFTRT, operands); 5878 } 5879 DONE; 5880}) 5881 5882;; signed left/right shift combination. 5883(define_split 5884 [(set (match_operand:SI 0 "register_operand" "") 5885 (sign_extract:SI 5886 (ashift:SI (match_operand:SI 1 "register_operand" "") 5887 (match_operand:SI 2 "const_int_operand" "")) 5888 (match_operand:SI 3 "const_int_operand" "") 5889 (const_int 0))) 5890 (clobber (reg:SI T_REG))] 5891 "TARGET_SH1" 5892 [(use (reg:SI R0_REG))] 5893{ 5894 if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1])) 5895 FAIL; 5896 DONE; 5897}) 5898 5899(define_insn "shl_sext_ext" 5900 [(set (match_operand:SI 0 "register_operand" "=r") 5901 (sign_extract:SI 5902 (ashift:SI (match_operand:SI 1 "register_operand" "0") 5903 (match_operand:SI 2 "const_int_operand" "n")) 5904 (match_operand:SI 3 "const_int_operand" "n") 5905 (const_int 0))) 5906 (clobber (reg:SI T_REG))] 5907 "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5" 5908 "#" 5909 [(set (attr "length") 5910 (cond [(match_test "shl_sext_length (insn)") 5911 (const_string "2") 5912 (eq (symbol_ref "shl_sext_length (insn)") (const_int 2)) 5913 (const_string "4") 5914 (eq (symbol_ref "shl_sext_length (insn)") (const_int 3)) 5915 (const_string "6") 5916 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4)) 5917 (const_string "8") 5918 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5)) 5919 (const_string "10") 5920 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6)) 5921 (const_string "12") 5922 (eq (symbol_ref "shl_sext_length (insn)") (const_int 7)) 5923 (const_string "14") 5924 (eq (symbol_ref "shl_sext_length (insn)") (const_int 8)) 5925 (const_string "16")] 5926 (const_string "18"))) 5927 (set_attr "type" "arith")]) 5928 5929(define_insn "shl_sext_sub" 5930 [(set (match_operand:SI 0 "register_operand" "=z") 5931 (sign_extract:SI 5932 (ashift:SI (match_operand:SI 1 "register_operand" "0") 5933 (match_operand:SI 2 "const_int_operand" "n")) 5934 (match_operand:SI 3 "const_int_operand" "n") 5935 (const_int 0))) 5936 (clobber (reg:SI T_REG))] 5937 "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6" 5938 "#" 5939 [(set (attr "length") 5940 (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3)) 5941 (const_string "6") 5942 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4)) 5943 (const_string "8") 5944 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5)) 5945 (const_string "10") 5946 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6)) 5947 (const_string "12")] 5948 (const_string "14"))) 5949 (set_attr "type" "arith")]) 5950 5951;; The xtrct_left and xtrct_right patterns are used in expansions of DImode 5952;; shifts by 16, and allow the xtrct instruction to be generated from C 5953;; source. 5954(define_insn "xtrct_left" 5955 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5956 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r") 5957 (const_int 16)) 5958 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0") 5959 (const_int 16))))] 5960 "TARGET_SH1" 5961 "xtrct %1,%0" 5962 [(set_attr "type" "arith")]) 5963 5964(define_insn "xtrct_right" 5965 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5966 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") 5967 (const_int 16)) 5968 (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r") 5969 (const_int 16))))] 5970 "TARGET_SH1" 5971 "xtrct %2,%0" 5972 [(set_attr "type" "arith")]) 5973 5974;; ------------------------------------------------------------------------- 5975;; Unary arithmetic 5976;; ------------------------------------------------------------------------- 5977 5978(define_insn "negc" 5979 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5980 (neg:SI (plus:SI (reg:SI T_REG) 5981 (match_operand:SI 1 "arith_reg_operand" "r")))) 5982 (set (reg:SI T_REG) 5983 (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1)) 5984 (const_int 0)))] 5985 "TARGET_SH1" 5986 "negc %1,%0" 5987 [(set_attr "type" "arith")]) 5988 5989;; A simplified version of the negc insn, where the exact value of the 5990;; T bit doesn't matter. This is easier for combine to pick up. 5991;; Notice that '0 - x - 1' is the same as '~x', thus we don't specify 5992;; extra patterns for this case. 5993(define_insn_and_split "*negc" 5994 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 5995 (minus:SI (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")) 5996 (match_operand 2 "treg_set_expr"))) 5997 (clobber (reg:SI T_REG))] 5998 "TARGET_SH1 && can_create_pseudo_p ()" 5999 "#" 6000 "&& 1" 6001 [(const_int 0)] 6002{ 6003 sh_split_treg_set_expr (operands[2], curr_insn); 6004 emit_insn (gen_negc (operands[0], operands[1])); 6005 DONE; 6006}); 6007 6008(define_insn "*negdi_media" 6009 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 6010 (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))] 6011 "TARGET_SHMEDIA" 6012 "sub r63, %1, %0" 6013 [(set_attr "type" "arith_media")]) 6014 6015;; Don't split into individual negc insns immediately so that neg:DI (abs:DI) 6016;; can be combined. 6017(define_expand "negdi2" 6018 [(parallel [(set (match_operand:DI 0 "arith_reg_dest") 6019 (neg:DI (match_operand:DI 1 "arith_reg_operand"))) 6020 (clobber (reg:SI T_REG))])] 6021 "TARGET_SH1") 6022 6023(define_insn_and_split "*negdi2" 6024 [(set (match_operand:DI 0 "arith_reg_dest") 6025 (neg:DI (match_operand:DI 1 "arith_reg_operand"))) 6026 (clobber (reg:SI T_REG))] 6027 "TARGET_SH1" 6028 "#" 6029 "&& can_create_pseudo_p ()" 6030 [(const_int 0)] 6031{ 6032 emit_insn (gen_clrt ()); 6033 emit_insn (gen_negc (gen_lowpart (SImode, operands[0]), 6034 gen_lowpart (SImode, operands[1]))); 6035 emit_insn (gen_negc (gen_highpart (SImode, operands[0]), 6036 gen_highpart (SImode, operands[1]))); 6037 DONE; 6038}) 6039 6040(define_insn "negsi2" 6041 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6042 (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))] 6043 "TARGET_SH1" 6044 "neg %1,%0" 6045 [(set_attr "type" "arith")]) 6046 6047(define_insn_and_split "one_cmplsi2" 6048 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6049 (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))] 6050 "TARGET_SH1" 6051 "not %1,%0" 6052 "&& can_create_pseudo_p ()" 6053 [(set (reg:SI T_REG) (ge:SI (match_dup 1) (const_int 0))) 6054 (set (match_dup 0) (reg:SI T_REG))] 6055{ 6056/* PR 54685 6057 If the result of 'unsigned int <= 0x7FFFFFFF' ends up as the following 6058 sequence: 6059 6060 (set (reg0) (not:SI (reg0) (reg1))) 6061 (parallel [(set (reg2) (lshiftrt:SI (reg0) (const_int 31))) 6062 (clobber (reg:SI T_REG))]) 6063 6064 ... match and combine the sequence manually in the split pass after the 6065 combine pass. Notice that combine does try the target pattern of this 6066 split, but if the pattern is added it interferes with other patterns, in 6067 particular with the div0s comparisons. 6068 This could also be done with a peephole but doing it here before register 6069 allocation can save one temporary. 6070 When we're here, the not:SI pattern obviously has been matched already 6071 and we only have to see whether the following insn is the left shift. */ 6072 6073 rtx i = next_nonnote_insn_bb (curr_insn); 6074 if (i == NULL_RTX || !NONJUMP_INSN_P (i)) 6075 FAIL; 6076 6077 rtx p = PATTERN (i); 6078 if (GET_CODE (p) != PARALLEL || XVECLEN (p, 0) != 2) 6079 FAIL; 6080 6081 rtx p0 = XVECEXP (p, 0, 0); 6082 rtx p1 = XVECEXP (p, 0, 1); 6083 6084 if (/* (set (reg2) (lshiftrt:SI (reg0) (const_int 31))) */ 6085 GET_CODE (p0) == SET 6086 && GET_CODE (XEXP (p0, 1)) == LSHIFTRT 6087 && REG_P (XEXP (XEXP (p0, 1), 0)) 6088 && REGNO (XEXP (XEXP (p0, 1), 0)) == REGNO (operands[0]) 6089 && CONST_INT_P (XEXP (XEXP (p0, 1), 1)) 6090 && INTVAL (XEXP (XEXP (p0, 1), 1)) == 31 6091 6092 /* (clobber (reg:SI T_REG)) */ 6093 && GET_CODE (p1) == CLOBBER && REG_P (XEXP (p1, 0)) 6094 && REGNO (XEXP (p1, 0)) == T_REG) 6095 { 6096 operands[0] = XEXP (p0, 0); 6097 set_insn_deleted (i); 6098 } 6099 else 6100 FAIL; 6101} 6102 [(set_attr "type" "arith")]) 6103 6104(define_expand "one_cmpldi2" 6105 [(set (match_operand:DI 0 "arith_reg_dest" "") 6106 (xor:DI (match_operand:DI 1 "arith_reg_operand" "") 6107 (const_int -1)))] 6108 "TARGET_SHMEDIA" "") 6109 6110(define_expand "abs<mode>2" 6111 [(parallel [(set (match_operand:SIDI 0 "arith_reg_dest") 6112 (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand"))) 6113 (clobber (reg:SI T_REG))])] 6114 "TARGET_SH1") 6115 6116(define_insn_and_split "*abs<mode>2" 6117 [(set (match_operand:SIDI 0 "arith_reg_dest") 6118 (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand"))) 6119 (clobber (reg:SI T_REG))] 6120 "TARGET_SH1" 6121 "#" 6122 "&& can_create_pseudo_p ()" 6123 [(const_int 0)] 6124{ 6125 if (<MODE>mode == SImode) 6126 emit_insn (gen_cmpgesi_t (operands[1], const0_rtx)); 6127 else 6128 { 6129 rtx high_src = gen_highpart (SImode, operands[1]); 6130 emit_insn (gen_cmpgesi_t (high_src, const0_rtx)); 6131 } 6132 6133 emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1], 6134 const1_rtx)); 6135 DONE; 6136}) 6137 6138(define_insn_and_split "*negabs<mode>2" 6139 [(set (match_operand:SIDI 0 "arith_reg_dest") 6140 (neg:SIDI (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand")))) 6141 (clobber (reg:SI T_REG))] 6142 "TARGET_SH1" 6143 "#" 6144 "&& can_create_pseudo_p ()" 6145 [(const_int 0)] 6146{ 6147 if (<MODE>mode == SImode) 6148 emit_insn (gen_cmpgesi_t (operands[1], const0_rtx)); 6149 else 6150 { 6151 rtx high_src = gen_highpart (SImode, operands[1]); 6152 emit_insn (gen_cmpgesi_t (high_src, const0_rtx)); 6153 } 6154 6155 emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1], 6156 const0_rtx)); 6157 DONE; 6158}) 6159 6160;; The SH4 202 can do zero-offset branches without pipeline stalls. 6161;; This can be used as some kind of conditional execution, which is useful 6162;; for abs. 6163;; Actually the instruction scheduling should decide whether to use a 6164;; zero-offset branch or not for any generic case involving a single 6165;; instruction on SH4 202. 6166(define_insn_and_split "negsi_cond" 6167 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 6168 (if_then_else 6169 (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand" "M,N")) 6170 (match_operand:SI 1 "arith_reg_operand" "0,0") 6171 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r,r"))))] 6172 "TARGET_SH1 && TARGET_ZDCBRANCH" 6173{ 6174 static const char* alt[] = 6175 { 6176 "bt 0f" "\n" 6177 " neg %2,%0" "\n" 6178 "0:", 6179 6180 "bf 0f" "\n" 6181 " neg %2,%0" "\n" 6182 "0:" 6183 }; 6184 return alt[which_alternative]; 6185} 6186 "TARGET_SH1 && ! TARGET_ZDCBRANCH" 6187 [(const_int 0)] 6188{ 6189 rtx skip_neg_label = gen_label_rtx (); 6190 6191 emit_move_insn (operands[0], operands[1]); 6192 6193 emit_jump_insn (INTVAL (operands[3]) 6194 ? gen_branch_true (skip_neg_label) 6195 : gen_branch_false (skip_neg_label)); 6196 6197 emit_label_after (skip_neg_label, 6198 emit_insn (gen_negsi2 (operands[0], operands[1]))); 6199 DONE; 6200} 6201 [(set_attr "type" "arith") ;; poor approximation 6202 (set_attr "length" "4")]) 6203 6204(define_insn_and_split "negdi_cond" 6205 [(set (match_operand:DI 0 "arith_reg_dest") 6206 (if_then_else 6207 (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand")) 6208 (match_operand:DI 1 "arith_reg_operand") 6209 (neg:DI (match_operand:DI 2 "arith_reg_operand")))) 6210 (clobber (reg:SI T_REG))] 6211 "TARGET_SH1" 6212 "#" 6213 "&& can_create_pseudo_p ()" 6214 [(const_int 0)] 6215{ 6216 rtx skip_neg_label = gen_label_rtx (); 6217 6218 emit_move_insn (operands[0], operands[1]); 6219 6220 emit_jump_insn (INTVAL (operands[3]) 6221 ? gen_branch_true (skip_neg_label) 6222 : gen_branch_false (skip_neg_label)); 6223 6224 if (!INTVAL (operands[3])) 6225 emit_insn (gen_clrt ()); 6226 6227 emit_insn (gen_negc (gen_lowpart (SImode, operands[0]), 6228 gen_lowpart (SImode, operands[1]))); 6229 emit_label_after (skip_neg_label, 6230 emit_insn (gen_negc (gen_highpart (SImode, operands[0]), 6231 gen_highpart (SImode, operands[1])))); 6232 DONE; 6233}) 6234 6235(define_expand "bswapsi2" 6236 [(set (match_operand:SI 0 "arith_reg_dest" "") 6237 (bswap:SI (match_operand:SI 1 "arith_reg_operand" "")))] 6238 "TARGET_SH1" 6239{ 6240 if (! can_create_pseudo_p ()) 6241 FAIL; 6242 else 6243 { 6244 rtx tmp0 = gen_reg_rtx (SImode); 6245 rtx tmp1 = gen_reg_rtx (SImode); 6246 6247 emit_insn (gen_swapbsi2 (tmp0, operands[1])); 6248 emit_insn (gen_rotlsi3_16 (tmp1, tmp0)); 6249 emit_insn (gen_swapbsi2 (operands[0], tmp1)); 6250 DONE; 6251 } 6252}) 6253 6254(define_insn "swapbsi2" 6255 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6256 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "r") 6257 (const_int -65536)) ;; 0xFFFF0000 6258 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8)) 6259 (const_int 65280)) 6260 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8)) 6261 (const_int 255)))))] 6262 "TARGET_SH1" 6263 "swap.b %1,%0" 6264 [(set_attr "type" "arith")]) 6265 6266;; The *swapbisi2_and_shl8 pattern helps the combine pass simplifying 6267;; partial byte swap expressions such as... 6268;; ((x & 0xFF) << 8) | ((x >> 8) & 0xFF). 6269;; ...which are currently not handled by the tree optimizers. 6270;; The combine pass will not initially try to combine the full expression, 6271;; but only some sub-expressions. In such a case the *swapbisi2_and_shl8 6272;; pattern acts as an intermediate pattern that will eventually lead combine 6273;; to the swapbsi2 pattern above. 6274;; As a side effect this also improves code that does (x & 0xFF) << 8 6275;; or (x << 8) & 0xFF00. 6276(define_insn_and_split "*swapbisi2_and_shl8" 6277 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6278 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r") 6279 (const_int 8)) 6280 (const_int 65280)) 6281 (match_operand:SI 2 "arith_reg_operand" "r")))] 6282 "TARGET_SH1 && ! reload_in_progress && ! reload_completed" 6283 "#" 6284 "&& can_create_pseudo_p ()" 6285 [(const_int 0)] 6286{ 6287 rtx tmp0 = gen_reg_rtx (SImode); 6288 rtx tmp1 = gen_reg_rtx (SImode); 6289 6290 emit_insn (gen_zero_extendqisi2 (tmp0, gen_lowpart (QImode, operands[1]))); 6291 emit_insn (gen_swapbsi2 (tmp1, tmp0)); 6292 emit_insn (gen_iorsi3 (operands[0], tmp1, operands[2])); 6293 DONE; 6294}) 6295 6296;; The *swapbhisi2 pattern is, like the *swapbisi2_and_shl8 pattern, another 6297;; intermediate pattern that will help the combine pass arriving at swapbsi2. 6298(define_insn_and_split "*swapbhisi2" 6299 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6300 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r") 6301 (const_int 8)) 6302 (const_int 65280)) 6303 (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))))] 6304 "TARGET_SH1 && ! reload_in_progress && ! reload_completed" 6305 "#" 6306 "&& can_create_pseudo_p ()" 6307 [(const_int 0)] 6308{ 6309 rtx tmp = gen_reg_rtx (SImode); 6310 6311 emit_insn (gen_zero_extendhisi2 (tmp, gen_lowpart (HImode, operands[1]))); 6312 emit_insn (gen_swapbsi2 (operands[0], tmp)); 6313 DONE; 6314}) 6315 6316;; In some cases the swapbsi2 pattern might leave a sequence such as... 6317;; swap.b r4,r4 6318;; mov r4,r0 6319;; 6320;; which can be simplified to... 6321;; swap.b r4,r0 6322(define_peephole2 6323 [(set (match_operand:SI 0 "arith_reg_dest" "") 6324 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "") 6325 (const_int -65536)) ;; 0xFFFF0000 6326 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8)) 6327 (const_int 65280)) 6328 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8)) 6329 (const_int 255))))) 6330 (set (match_operand:SI 2 "arith_reg_dest" "") 6331 (match_dup 0))] 6332 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])" 6333 [(set (match_dup 2) 6334 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "") 6335 (const_int -65536)) ;; 0xFFFF0000 6336 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8)) 6337 (const_int 65280)) 6338 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8)) 6339 (const_int 255)))))]) 6340 6341;; ------------------------------------------------------------------------- 6342;; Zero extension instructions 6343;; ------------------------------------------------------------------------- 6344 6345(define_insn "zero_extendsidi2" 6346 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 6347 (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))] 6348 "TARGET_SHMEDIA" 6349 "addz.l %1, r63, %0" 6350 [(set_attr "type" "arith_media") 6351 (set_attr "highpart" "extend")]) 6352 6353(define_insn "zero_extendhidi2" 6354 [(set (match_operand:DI 0 "register_operand" "=r,r") 6355 (zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))] 6356 "TARGET_SHMEDIA" 6357 "@ 6358 # 6359 ld%M1.uw %m1, %0" 6360 [(set_attr "type" "*,load_media") 6361 (set (attr "highpart") 6362 (cond [(match_test "sh_contains_memref_p (insn)") 6363 (const_string "user")] 6364 (const_string "ignore")))]) 6365 6366(define_split 6367 [(set (match_operand:DI 0 "register_operand" "") 6368 (zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))] 6369 "TARGET_SHMEDIA && reload_completed" 6370 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48))) 6371 (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))] 6372{ 6373 if (GET_CODE (operands[1]) == TRUNCATE) 6374 operands[1] = XEXP (operands[1], 0); 6375}) 6376 6377;; ??? when a truncated input to a zero_extend is reloaded, reload will 6378;; reload the entire truncate expression. 6379(define_insn_and_split "*loaddi_trunc" 6380 [(set (match_operand 0 "any_register_operand" "=r") 6381 (truncate (match_operand:DI 1 "memory_operand" "m")))] 6382 "TARGET_SHMEDIA && reload_completed" 6383 "#" 6384 "TARGET_SHMEDIA && reload_completed" 6385 [(set (match_dup 0) (match_dup 1))] 6386{ 6387 operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0])); 6388}) 6389 6390(define_insn "zero_extendqidi2" 6391 [(set (match_operand:DI 0 "register_operand" "=r,r") 6392 (zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))] 6393 "TARGET_SHMEDIA" 6394 "@ 6395 andi %1, 255, %0 6396 ld%M1.ub %m1, %0" 6397 [(set_attr "type" "arith_media,load_media") 6398 (set (attr "highpart") 6399 (cond [(match_test "sh_contains_memref_p (insn)") 6400 (const_string "user")] 6401 (const_string "ignore")))]) 6402 6403(define_expand "zero_extend<mode>si2" 6404 [(set (match_operand:SI 0 "arith_reg_dest") 6405 (zero_extend:SI (match_operand:QIHI 1 "zero_extend_operand")))]) 6406 6407(define_insn_and_split "*zero_extend<mode>si2_compact" 6408 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6409 (zero_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))] 6410 "TARGET_SH1" 6411 "extu.<bw> %1,%0" 6412 "&& can_create_pseudo_p ()" 6413 [(set (match_dup 0) (match_dup 2))] 6414{ 6415 /* Sometimes combine fails to combine a T bit or negated T bit store to a 6416 reg with a following zero extension. In the split pass after combine, 6417 try to figure out how the extended reg was set. If it originated from 6418 the T bit we can replace the zero extension with a reg move, which will 6419 be eliminated. Notice that this also helps the *cbranch_t splitter when 6420 it tries to post-combine tests and conditional branches, as it does not 6421 check for zero extensions. */ 6422 operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn); 6423 if (operands[2] == NULL_RTX) 6424 FAIL; 6425} 6426 [(set_attr "type" "arith")]) 6427 6428(define_insn "*zero_extendhisi2_media" 6429 [(set (match_operand:SI 0 "register_operand" "=r,r") 6430 (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))] 6431 "TARGET_SHMEDIA" 6432 "@ 6433 # 6434 ld%M1.uw %m1, %0" 6435 [(set_attr "type" "arith_media,load_media") 6436 (set (attr "highpart") 6437 (cond [(match_test "sh_contains_memref_p (insn)") 6438 (const_string "user")] 6439 (const_string "ignore")))]) 6440 6441(define_split 6442 [(set (match_operand:SI 0 "register_operand" "") 6443 (zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))] 6444 "TARGET_SHMEDIA && reload_completed" 6445 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16))) 6446 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))] 6447{ 6448 rtx op1 = operands[1]; 6449 6450 if (GET_CODE (op1) == TRUNCATE) 6451 op1 = XEXP (op1, 0); 6452 operands[2] 6453 = simplify_gen_subreg (SImode, op1, GET_MODE (op1), 6454 subreg_lowpart_offset (SImode, GET_MODE (op1))); 6455}) 6456 6457(define_insn "*zero_extendqisi2_media" 6458 [(set (match_operand:SI 0 "register_operand" "=r,r") 6459 (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))] 6460 "TARGET_SHMEDIA" 6461 "@ 6462 andi %1, 255, %0 6463 ld%M1.ub %m1, %0" 6464 [(set_attr "type" "arith_media,load_media") 6465 (set (attr "highpart") 6466 (cond [(match_test "sh_contains_memref_p (insn)") 6467 (const_string "user")] 6468 (const_string "ignore")))]) 6469 6470(define_insn "zero_extendqihi2" 6471 [(set (match_operand:HI 0 "arith_reg_dest" "=r") 6472 (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))] 6473 "TARGET_SH1" 6474 "extu.b %1,%0" 6475 [(set_attr "type" "arith")]) 6476 6477;; SH2A supports two zero extending load instructions: movu.b and movu.w. 6478;; They could also be used for simple memory addresses like @Rn by setting 6479;; the displacement value to zero. However, doing so too early results in 6480;; missed opportunities for other optimizations such as post-inc or index 6481;; addressing loads. 6482;; We don't allow the zero extending loads to match during RTL expansion 6483;; (see zero_extend_operand predicate), as this would pessimize other 6484;; optimization opportunities such as bit extractions of unsigned mems, 6485;; where the zero extraction is irrelevant. If the zero extracting mem 6486;; loads are emitted early it will be more difficult to change them back 6487;; to sign extending loads (which are preferred). 6488;; The combine pass will also try to combine mem loads and zero extends, 6489;; which is prevented by 'sh_legitimate_combined_insn'. 6490(define_insn "*zero_extend<mode>si2_disp_mem" 6491 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") 6492 (zero_extend:SI 6493 (match_operand:QIHI 1 "zero_extend_movu_operand" "Sdd,Sra")))] 6494 "TARGET_SH2A" 6495 "@ 6496 movu.<bw> %1,%0 6497 movu.<bw> @(0,%t1),%0" 6498 [(set_attr "type" "load") 6499 (set_attr "length" "4")]) 6500 6501;; Convert the zero extending loads in sequences such as: 6502;; movu.b @(1,r5),r0 movu.w @(2,r5),r0 6503;; mov.b r0,@(1,r4) mov.b r0,@(1,r4) 6504;; 6505;; back to sign extending loads like: 6506;; mov.b @(1,r5),r0 mov.w @(2,r5),r0 6507;; mov.b r0,@(1,r4) mov.b r0,@(1,r4) 6508;; 6509;; if the extension type is irrelevant. The sign extending mov.{b|w} insn 6510;; is only 2 bytes in size if the displacement is {K04|K05}. 6511;; If the displacement is greater it doesn't matter, so we convert anyways. 6512(define_peephole2 6513 [(set (match_operand:SI 0 "arith_reg_dest" "") 6514 (zero_extend:SI (match_operand 1 "displacement_mem_operand" ""))) 6515 (set (match_operand 2 "nonimmediate_operand" "") 6516 (match_operand 3 "arith_reg_operand" ""))] 6517 "TARGET_SH2A 6518 && REGNO (operands[0]) == REGNO (operands[3]) 6519 && peep2_reg_dead_p (2, operands[0]) 6520 && GET_MODE_SIZE (GET_MODE (operands[2])) 6521 <= GET_MODE_SIZE (GET_MODE (operands[1]))" 6522 [(set (match_dup 0) (sign_extend:SI (match_dup 1))) 6523 (set (match_dup 2) (match_dup 3))]) 6524 6525;; Fold sequences such as 6526;; mov.b @r3,r7 6527;; extu.b r7,r7 6528;; into 6529;; movu.b @(0,r3),r7 6530;; This does not reduce the code size but the number of instructions is 6531;; halved, which results in faster code. 6532(define_peephole2 6533 [(set (match_operand:SI 0 "arith_reg_dest" "") 6534 (sign_extend:SI (match_operand 1 "simple_mem_operand" ""))) 6535 (set (match_operand:SI 2 "arith_reg_dest" "") 6536 (zero_extend:SI (match_operand 3 "arith_reg_operand" "")))] 6537 "TARGET_SH2A 6538 && GET_MODE (operands[1]) == GET_MODE (operands[3]) 6539 && (GET_MODE (operands[1]) == QImode || GET_MODE (operands[1]) == HImode) 6540 && REGNO (operands[0]) == REGNO (operands[3]) 6541 && (REGNO (operands[2]) == REGNO (operands[0]) 6542 || peep2_reg_dead_p (2, operands[0]))" 6543 [(set (match_dup 2) (zero_extend:SI (match_dup 4)))] 6544{ 6545 operands[4] 6546 = replace_equiv_address (operands[1], 6547 gen_rtx_PLUS (SImode, XEXP (operands[1], 0), 6548 const0_rtx)); 6549}) 6550 6551;; ------------------------------------------------------------------------- 6552;; Sign extension instructions 6553;; ------------------------------------------------------------------------- 6554 6555;; ??? This should be a define expand. 6556;; ??? Or perhaps it should be dropped? 6557 6558;; convert_move generates good code for SH[1-4]. 6559(define_insn "extendsidi2" 6560 [(set (match_operand:DI 0 "register_operand" "=r,r,r") 6561 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))] 6562 "TARGET_SHMEDIA" 6563 "@ 6564 add.l %1, r63, %0 6565 ld%M1.l %m1, %0 6566 fmov.sl %1, %0" 6567 [(set_attr "type" "arith_media,load_media,fpconv_media") 6568 (set (attr "highpart") 6569 (cond [(match_test "sh_contains_memref_p (insn)") 6570 (const_string "user")] 6571 (const_string "extend")))]) 6572 6573(define_insn "extendhidi2" 6574 [(set (match_operand:DI 0 "register_operand" "=r,r") 6575 (sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))] 6576 "TARGET_SHMEDIA" 6577 "@ 6578 # 6579 ld%M1.w %m1, %0" 6580 [(set_attr "type" "*,load_media") 6581 (set (attr "highpart") 6582 (cond [(match_test "sh_contains_memref_p (insn)") 6583 (const_string "user")] 6584 (const_string "ignore")))]) 6585 6586(define_split 6587 [(set (match_operand:DI 0 "register_operand" "") 6588 (sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))] 6589 "TARGET_SHMEDIA && reload_completed" 6590 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48))) 6591 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))] 6592{ 6593 if (GET_CODE (operands[1]) == TRUNCATE) 6594 operands[1] = XEXP (operands[1], 0); 6595}) 6596 6597(define_insn "extendqidi2" 6598 [(set (match_operand:DI 0 "register_operand" "=r,r") 6599 (sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))] 6600 "TARGET_SHMEDIA" 6601 "@ 6602 # 6603 ld%M1.b %m1, %0" 6604 [(set_attr "type" "*,load_media") 6605 (set (attr "highpart") 6606 (cond [(match_test "sh_contains_memref_p (insn)") 6607 (const_string "user")] 6608 (const_string "ignore")))]) 6609 6610(define_split 6611 [(set (match_operand:DI 0 "register_operand" "") 6612 (sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))] 6613 "TARGET_SHMEDIA && reload_completed" 6614 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56))) 6615 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))] 6616{ 6617 if (GET_CODE (operands[1]) == TRUNCATE) 6618 operands[1] = XEXP (operands[1], 0); 6619}) 6620 6621(define_expand "extend<mode>si2" 6622 [(set (match_operand:SI 0 "arith_reg_dest") 6623 (sign_extend:SI (match_operand:QIHI 1 "general_extend_operand")))]) 6624 6625(define_insn "*extendhisi2_media" 6626 [(set (match_operand:SI 0 "register_operand" "=r,r") 6627 (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))] 6628 "TARGET_SHMEDIA" 6629 "@ 6630 # 6631 ld%M1.w %m1, %0" 6632 [(set_attr "type" "arith_media,load_media") 6633 (set (attr "highpart") 6634 (cond [(match_test "sh_contains_memref_p (insn)") 6635 (const_string "user")] 6636 (const_string "ignore")))]) 6637 6638(define_split 6639 [(set (match_operand:SI 0 "register_operand" "") 6640 (sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))] 6641 "TARGET_SHMEDIA && reload_completed" 6642 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16))) 6643 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))] 6644{ 6645 rtx op1 = operands[1]; 6646 if (GET_CODE (op1) == TRUNCATE) 6647 op1 = XEXP (op1, 0); 6648 operands[2] 6649 = simplify_gen_subreg (SImode, op1, GET_MODE (op1), 6650 subreg_lowpart_offset (SImode, GET_MODE (op1))); 6651}) 6652 6653(define_insn_and_split "*extend<mode>si2_compact_reg" 6654 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6655 (sign_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))] 6656 "TARGET_SH1" 6657 "exts.<bw> %1,%0" 6658 "&& can_create_pseudo_p ()" 6659 [(set (match_dup 0) (match_dup 2))] 6660{ 6661 /* Sometimes combine fails to combine a T bit or negated T bit store to a 6662 reg with a following sign extension. In the split pass after combine, 6663 try to figure the extended reg was set. If it originated from the T 6664 bit we can replace the sign extension with a reg move, which will be 6665 eliminated. */ 6666 operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn); 6667 if (operands[2] == NULL_RTX) 6668 FAIL; 6669} 6670 [(set_attr "type" "arith")]) 6671 6672;; FIXME: Fold non-SH2A and SH2A alternatives with "enabled" attribute. 6673;; See movqi insns. 6674(define_insn "*extend<mode>si2_compact_mem_disp" 6675 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r") 6676 (sign_extend:SI 6677 (mem:QIHI 6678 (plus:SI 6679 (match_operand:SI 1 "arith_reg_operand" "%r,r") 6680 (match_operand:SI 2 "const_int_operand" "<disp04>,N")))))] 6681 "TARGET_SH1 && ! TARGET_SH2A 6682 && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)" 6683 "@ 6684 mov.<bw> @(%O2,%1),%0 6685 mov.<bw> @%1,%0" 6686 [(set_attr "type" "load")]) 6687 6688(define_insn "*extend<mode>si2_compact_mem_disp" 6689 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r,r") 6690 (sign_extend:SI 6691 (mem:QIHI 6692 (plus:SI 6693 (match_operand:SI 1 "arith_reg_operand" "%r,r,r") 6694 (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>")))))] 6695 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)" 6696 "@ 6697 mov.<bw> @(%O2,%1),%0 6698 mov.<bw> @%1,%0 6699 mov.<bw> @(%O2,%1),%0" 6700 [(set_attr "type" "load") 6701 (set_attr "length" "2,2,4")]) 6702 6703;; The *_snd patterns will take care of other QImode/HImode addressing 6704;; modes than displacement addressing. They must be defined _after_ the 6705;; displacement addressing patterns. Otherwise the displacement addressing 6706;; patterns will not be picked. 6707(define_insn "*extend<mode>si2_compact_snd" 6708 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6709 (sign_extend:SI 6710 (match_operand:QIHI 1 "movsrc_no_disp_mem_operand" "Snd")))] 6711 "TARGET_SH1" 6712 "mov.<bw> %1,%0" 6713 [(set_attr "type" "load")]) 6714 6715(define_insn "*extendqisi2_media" 6716 [(set (match_operand:SI 0 "register_operand" "=r,r") 6717 (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))] 6718 "TARGET_SHMEDIA" 6719 "@ 6720 # 6721 ld%M1.b %m1, %0" 6722 [(set_attr "type" "arith_media,load_media") 6723 (set (attr "highpart") 6724 (cond [(match_test "sh_contains_memref_p (insn)") 6725 (const_string "user")] 6726 (const_string "ignore")))]) 6727 6728(define_split 6729 [(set (match_operand:SI 0 "register_operand" "") 6730 (sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))] 6731 "TARGET_SHMEDIA && reload_completed" 6732 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24))) 6733 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))] 6734{ 6735 rtx op1 = operands[1]; 6736 if (GET_CODE (op1) == TRUNCATE) 6737 op1 = XEXP (op1, 0); 6738 operands[2] 6739 = simplify_gen_subreg (SImode, op1, GET_MODE (op1), 6740 subreg_lowpart_offset (SImode, GET_MODE (op1))); 6741}) 6742 6743(define_expand "extendqihi2" 6744 [(set (match_operand:HI 0 "arith_reg_dest") 6745 (sign_extend:HI (match_operand:QI 1 "arith_reg_operand")))] 6746 "TARGET_SH1") 6747 6748(define_insn "*extendqihi2_compact_reg" 6749 [(set (match_operand:HI 0 "arith_reg_dest" "=r") 6750 (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))] 6751 "TARGET_SH1" 6752 "exts.b %1,%0" 6753 [(set_attr "type" "arith")]) 6754 6755;; It would seem useful to combine the truncXi patterns into the movXi 6756;; patterns, but unary operators are ignored when matching constraints, 6757;; so we need separate patterns. 6758(define_insn "truncdisi2" 6759 [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f") 6760 (truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))] 6761 "TARGET_SHMEDIA" 6762 "@ 6763 add.l %1, r63, %0 6764 st%M0.l %m0, %1 6765 fst%M0.s %m0, %T1 6766 fmov.ls %1, %0 6767 fmov.sl %T1, %0 6768 fmov.s %T1, %0" 6769 [(set_attr "type" "arith_media,store_media,fstore_media,fload_media, 6770 fpconv_media,fmove_media") 6771 (set (attr "highpart") 6772 (cond [(match_test "sh_contains_memref_p (insn)") 6773 (const_string "user")] 6774 (const_string "extend")))]) 6775 6776(define_insn "truncdihi2" 6777 [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m") 6778 (truncate:HI (match_operand:DI 1 "register_operand" "r,r")))] 6779 "TARGET_SHMEDIA" 6780{ 6781 static const char* alt[] = 6782 { 6783 "shlli %1,48,%0" "\n" 6784 " shlri %0,48,%0", 6785 6786 "st%M0.w %m0, %1" 6787 }; 6788 return alt[which_alternative]; 6789} 6790 [(set_attr "type" "arith_media,store_media") 6791 (set_attr "length" "8,4") 6792 (set (attr "highpart") 6793 (cond [(match_test "sh_contains_memref_p (insn)") 6794 (const_string "user")] 6795 (const_string "extend")))]) 6796 6797; N.B. This should agree with LOAD_EXTEND_OP and movqi. 6798; Because we use zero extension, we can't provide signed QImode compares 6799; using a simple compare or conditional branch insn. 6800(define_insn "truncdiqi2" 6801 [(set (match_operand:QI 0 "general_movdst_operand" "=r,m") 6802 (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))] 6803 "TARGET_SHMEDIA" 6804 "@ 6805 andi %1, 255, %0 6806 st%M0.b %m0, %1" 6807 [(set_attr "type" "arith_media,store") 6808 (set (attr "highpart") 6809 (cond [(match_test "sh_contains_memref_p (insn)") 6810 (const_string "user")] 6811 (const_string "extend")))]) 6812 6813;; ------------------------------------------------------------------------- 6814;; Move instructions 6815;; ------------------------------------------------------------------------- 6816 6817;; define push and pop so it is easy for sh.c 6818;; We can't use push and pop on SHcompact because the stack must always 6819;; be 8-byte aligned. 6820(define_expand "push" 6821 [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) 6822 (match_operand:SI 0 "register_operand" "r,l,x"))] 6823 "TARGET_SH1 && ! TARGET_SH5" 6824 "") 6825 6826(define_expand "pop" 6827 [(set (match_operand:SI 0 "register_operand" "=r,l,x") 6828 (mem:SI (post_inc:SI (reg:SI SP_REG))))] 6829 "TARGET_SH1 && ! TARGET_SH5" 6830 "") 6831 6832(define_expand "push_e" 6833 [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) 6834 (match_operand:SF 0 "" "")) 6835 (use (reg:SI FPSCR_MODES_REG)) 6836 (clobber (scratch:SI))])] 6837 "TARGET_SH1 && ! TARGET_SH5" 6838 "") 6839 6840(define_insn "push_fpul" 6841 [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))] 6842 "TARGET_SH2E && ! TARGET_SH5" 6843 "sts.l fpul,@-r15" 6844 [(set_attr "type" "fstore") 6845 (set_attr "late_fp_use" "yes") 6846 (set_attr "hit_stack" "yes")]) 6847 6848;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4, 6849;; so use that. 6850(define_expand "push_4" 6851 [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG))) 6852 (match_operand:DF 0 "" "")) 6853 (use (reg:SI FPSCR_MODES_REG)) 6854 (clobber (scratch:SI))])] 6855 "TARGET_SH1 && ! TARGET_SH5" 6856 "") 6857 6858(define_expand "pop_e" 6859 [(parallel [(set (match_operand:SF 0 "" "") 6860 (mem:SF (post_inc:SI (reg:SI SP_REG)))) 6861 (use (reg:SI FPSCR_MODES_REG)) 6862 (clobber (scratch:SI))])] 6863 "TARGET_SH1 && ! TARGET_SH5" 6864 "") 6865 6866(define_insn "pop_fpul" 6867 [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))] 6868 "TARGET_SH2E && ! TARGET_SH5" 6869 "lds.l @r15+,fpul" 6870 [(set_attr "type" "load") 6871 (set_attr "hit_stack" "yes")]) 6872 6873(define_expand "pop_4" 6874 [(parallel [(set (match_operand:DF 0 "" "") 6875 (mem:DF (post_inc:SI (reg:SI SP_REG)))) 6876 (use (reg:SI FPSCR_MODES_REG)) 6877 (clobber (scratch:SI))])] 6878 "TARGET_SH1 && ! TARGET_SH5" 6879 "") 6880 6881(define_expand "push_fpscr" 6882 [(const_int 0)] 6883 "TARGET_SH2E" 6884{ 6885 add_reg_note ( 6886 emit_insn ( 6887 gen_sts_fpscr ( 6888 gen_frame_mem (SImode, gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx)))), 6889 REG_INC, stack_pointer_rtx); 6890 DONE; 6891}) 6892 6893(define_expand "pop_fpscr" 6894 [(const_int 0)] 6895 "TARGET_SH2E" 6896{ 6897 add_reg_note ( 6898 emit_insn ( 6899 gen_lds_fpscr ( 6900 gen_frame_mem (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx)))), 6901 REG_INC, stack_pointer_rtx); 6902 DONE; 6903}) 6904 6905;; The clrt and sett patterns can happen as the result of optimization and 6906;; insn expansion. 6907;; Comparisons might get simplified to a move of zero or 1 into the T reg. 6908;; In this case they might not disappear completely, because the T reg is 6909;; a fixed hard reg. 6910;; When DImode operations that use the T reg as carry/borrow are split into 6911;; individual SImode operations, the T reg is usually cleared before the 6912;; first SImode insn. 6913(define_insn "clrt" 6914 [(set (reg:SI T_REG) (const_int 0))] 6915 "TARGET_SH1" 6916 "clrt" 6917 [(set_attr "type" "mt_group")]) 6918 6919(define_insn "sett" 6920 [(set (reg:SI T_REG) (const_int 1))] 6921 "TARGET_SH1" 6922 "sett" 6923 [(set_attr "type" "mt_group")]) 6924 6925;; Use the combine pass to transform sequences such as 6926;; mov r5,r0 6927;; add #1,r0 6928;; shll2 r0 6929;; mov.l @(r0,r4),r0 6930;; into 6931;; shll2 r5 6932;; add r4,r5 6933;; mov.l @(4,r5),r0 6934;; 6935;; See also PR 39423. 6936;; Notice that these patterns have a T_REG clobber, because the shift 6937;; sequence that will be split out might clobber the T_REG. Ideally, the 6938;; clobber would be added conditionally, depending on the result of 6939;; sh_ashlsi_clobbers_t_reg_p. When splitting out the shifts we must go 6940;; through the ashlsi3 expander in order to get the right shift insn -- 6941;; a T_REG clobbering or non-clobbering shift sequence or dynamic shift. 6942;; FIXME: Combine never tries this kind of patterns for DImode. 6943(define_insn_and_split "*movsi_index_disp_load" 6944 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 6945 (match_operand:SI 1 "mem_index_disp_operand" "m")) 6946 (clobber (reg:SI T_REG))] 6947 "TARGET_SH1" 6948 "#" 6949 "&& can_create_pseudo_p ()" 6950 [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3))) 6951 (set (match_dup 0) (match_dup 7))] 6952{ 6953 rtx mem = operands[1]; 6954 rtx plus0_rtx = XEXP (mem, 0); 6955 rtx plus1_rtx = XEXP (plus0_rtx, 0); 6956 rtx mult_rtx = XEXP (plus1_rtx, 0); 6957 6958 operands[1] = XEXP (mult_rtx, 0); 6959 operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1)))); 6960 operands[3] = XEXP (plus1_rtx, 1); 6961 operands[4] = XEXP (plus0_rtx, 1); 6962 operands[5] = gen_reg_rtx (SImode); 6963 operands[6] = gen_reg_rtx (SImode); 6964 operands[7] = 6965 replace_equiv_address (mem, 6966 gen_rtx_PLUS (SImode, operands[6], operands[4])); 6967 6968 emit_insn (gen_ashlsi3 (operands[5], operands[1], operands[2])); 6969}) 6970 6971(define_insn_and_split "*movhi_index_disp_load" 6972 [(set (match_operand:SI 0 "arith_reg_dest") 6973 (SZ_EXTEND:SI (match_operand:HI 1 "mem_index_disp_operand"))) 6974 (clobber (reg:SI T_REG))] 6975 "TARGET_SH1" 6976 "#" 6977 "&& can_create_pseudo_p ()" 6978 [(const_int 0)] 6979{ 6980 rtx mem = operands[1]; 6981 rtx plus0_rtx = XEXP (mem, 0); 6982 rtx plus1_rtx = XEXP (plus0_rtx, 0); 6983 rtx mult_rtx = XEXP (plus1_rtx, 0); 6984 6985 rtx op_1 = XEXP (mult_rtx, 0); 6986 rtx op_2 = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1)))); 6987 rtx op_3 = XEXP (plus1_rtx, 1); 6988 rtx op_4 = XEXP (plus0_rtx, 1); 6989 rtx op_5 = gen_reg_rtx (SImode); 6990 rtx op_6 = gen_reg_rtx (SImode); 6991 rtx op_7 = replace_equiv_address (mem, gen_rtx_PLUS (SImode, op_6, op_4)); 6992 6993 emit_insn (gen_ashlsi3 (op_5, op_1, op_2)); 6994 emit_insn (gen_addsi3 (op_6, op_5, op_3)); 6995 6996 if (<CODE> == SIGN_EXTEND) 6997 { 6998 emit_insn (gen_extendhisi2 (operands[0], op_7)); 6999 DONE; 7000 } 7001 else if (<CODE> == ZERO_EXTEND) 7002 { 7003 /* On SH2A the movu.w insn can be used for zero extending loads. */ 7004 if (TARGET_SH2A) 7005 emit_insn (gen_zero_extendhisi2 (operands[0], op_7)); 7006 else 7007 { 7008 emit_insn (gen_extendhisi2 (operands[0], op_7)); 7009 emit_insn (gen_zero_extendhisi2 (operands[0], 7010 gen_lowpart (HImode, operands[0]))); 7011 } 7012 DONE; 7013 } 7014 else 7015 FAIL; 7016}) 7017 7018(define_insn_and_split "*mov<mode>_index_disp_store" 7019 [(set (match_operand:HISI 0 "mem_index_disp_operand" "=m") 7020 (match_operand:HISI 1 "arith_reg_operand" "r")) 7021 (clobber (reg:SI T_REG))] 7022 "TARGET_SH1" 7023 "#" 7024 "&& can_create_pseudo_p ()" 7025 [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3))) 7026 (set (match_dup 7) (match_dup 1))] 7027{ 7028 rtx mem = operands[0]; 7029 rtx plus0_rtx = XEXP (mem, 0); 7030 rtx plus1_rtx = XEXP (plus0_rtx, 0); 7031 rtx mult_rtx = XEXP (plus1_rtx, 0); 7032 7033 operands[0] = XEXP (mult_rtx, 0); 7034 operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1)))); 7035 operands[3] = XEXP (plus1_rtx, 1); 7036 operands[4] = XEXP (plus0_rtx, 1); 7037 operands[5] = gen_reg_rtx (SImode); 7038 operands[6] = gen_reg_rtx (SImode); 7039 operands[7] = 7040 replace_equiv_address (mem, 7041 gen_rtx_PLUS (SImode, operands[6], operands[4])); 7042 7043 emit_insn (gen_ashlsi3 (operands[5], operands[0], operands[2])); 7044}) 7045 7046;; t/r must come after r/r, lest reload will try to reload stuff like 7047;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0) 7048;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T. 7049(define_insn "movsi_i" 7050 [(set (match_operand:SI 0 "general_movdst_operand" 7051 "=r,r,r,r,r,r,m,<,<,x,l,x,l,r") 7052 (match_operand:SI 1 "general_movsrc_operand" 7053 "Q,r,I08,mr,x,l,r,x,l,r,r,>,>,i"))] 7054 "TARGET_SH1 7055 && ! TARGET_SH2E 7056 && ! TARGET_SH2A 7057 && (register_operand (operands[0], SImode) 7058 || register_operand (operands[1], SImode))" 7059 "@ 7060 mov.l %1,%0 7061 mov %1,%0 7062 mov %1,%0 7063 mov.l %1,%0 7064 sts %1,%0 7065 sts %1,%0 7066 mov.l %1,%0 7067 sts.l %1,%0 7068 sts.l %1,%0 7069 lds %1,%0 7070 lds %1,%0 7071 lds.l %1,%0 7072 lds.l %1,%0 7073 fake %1,%0" 7074 [(set_attr "type" "pcload_si,move,movi8,load_si,mac_gp,prget,store,mac_mem, 7075 pstore,gp_mac,prset,mem_mac,pload,pcload_si") 7076 (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*")]) 7077 7078;; t/r must come after r/r, lest reload will try to reload stuff like 7079;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2) 7080;; ??? This allows moves from macl to fpul to be recognized, but these moves 7081;; will require a reload. 7082;; ??? We can't include f/f because we need the proper FPSCR setting when 7083;; TARGET_FMOVD is in effect, and mode switching is done before reload. 7084(define_insn "movsi_ie" 7085 [(set (match_operand:SI 0 "general_movdst_operand" 7086 "=r,r,r,r,r,r,r,r,mr,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y") 7087 (match_operand:SI 1 "general_movsrc_operand" 7088 "Q,r,I08,I20,I28,mr,x,l,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))] 7089 "(TARGET_SH2E || TARGET_SH2A) 7090 && ((register_operand (operands[0], SImode) 7091 && !fpscr_operand (operands[0], SImode)) 7092 || (register_operand (operands[1], SImode) 7093 && !fpscr_operand (operands[1], SImode)))" 7094 "@ 7095 mov.l %1,%0 7096 mov %1,%0 7097 mov %1,%0 7098 movi20 %1,%0 7099 movi20s %1,%0 7100 mov.l %1,%0 7101 sts %1,%0 7102 sts %1,%0 7103 mov.l %1,%0 7104 sts.l %1,%0 7105 sts.l %1,%0 7106 lds %1,%0 7107 lds %1,%0 7108 lds.l %1,%0 7109 lds.l %1,%0 7110 lds.l %1,%0 7111 sts.l %1,%0 7112 fake %1,%0 7113 lds %1,%0 7114 sts %1,%0 7115 fsts fpul,%0 7116 flds %1,fpul 7117 fmov %1,%0 7118 ! move optimized away" 7119 [(set_attr "type" "pcload_si,move,movi8,move,move,load_si,mac_gp,prget,store, 7120 mac_mem,pstore,gp_mac,prset,mem_mac,pload,load,fstore, 7121 pcload_si,gp_fpul,fpul_gp,fmove,fmove,fmove,nil") 7122 (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*") 7123 (set_attr_alternative "length" 7124 [(const_int 2) 7125 (const_int 2) 7126 (const_int 2) 7127 (const_int 4) 7128 (const_int 4) 7129 (if_then_else 7130 (match_test "TARGET_SH2A") 7131 (const_int 4) (const_int 2)) 7132 (const_int 2) 7133 (const_int 2) 7134 (if_then_else 7135 (match_test "TARGET_SH2A") 7136 (const_int 4) (const_int 2)) 7137 (const_int 2) 7138 (const_int 2) 7139 (const_int 2) 7140 (const_int 2) 7141 (const_int 2) 7142 (const_int 2) 7143 (const_int 2) 7144 (const_int 2) 7145 (const_int 2) 7146 (const_int 2) 7147 (const_int 2) 7148 (const_int 2) 7149 (const_int 2) 7150 (const_int 2) 7151 (const_int 0)])]) 7152 7153(define_insn "movsi_i_lowpart" 7154 [(set (strict_low_part 7155 (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r")) 7156 (match_operand:SI 1 "general_movsrc_operand" "Q,r,I08,mr,x,l,r,i"))] 7157 "TARGET_SH1 7158 && (register_operand (operands[0], SImode) 7159 || register_operand (operands[1], SImode))" 7160 "@ 7161 mov.l %1,%0 7162 mov %1,%0 7163 mov %1,%0 7164 mov.l %1,%0 7165 sts %1,%0 7166 sts %1,%0 7167 mov.l %1,%0 7168 fake %1,%0" 7169 [(set_attr "type" "pcload,move,arith,load,mac_gp,prget,store,pcload")]) 7170 7171(define_insn_and_split "load_ra" 7172 [(set (match_operand:SI 0 "general_movdst_operand" "") 7173 (unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))] 7174 "TARGET_SH1" 7175 "#" 7176 "&& ! currently_expanding_to_rtl" 7177 [(set (match_dup 0) (match_dup 1))] 7178{ 7179 if (TARGET_SHCOMPACT && crtl->saves_all_registers) 7180 operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx); 7181}) 7182 7183;; The '?'s in the following constraints may not reflect the time taken 7184;; to perform the move. They are there to discourage the use of floating- 7185;; point registers for storing integer values. 7186(define_insn "*movsi_media" 7187 [(set (match_operand:SI 0 "general_movdst_operand" 7188 "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b") 7189 (match_operand:SI 1 "general_movsrc_operand" 7190 "r,I16Css,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))] 7191 "TARGET_SHMEDIA_FPU 7192 && (register_operand (operands[0], SImode) 7193 || sh_register_operand (operands[1], SImode) 7194 || GET_CODE (operands[1]) == TRUNCATE)" 7195 "@ 7196 add.l %1, r63, %0 7197 movi %1, %0 7198 # 7199 ld%M1.l %m1, %0 7200 st%M0.l %m0, %N1 7201 fld%M1.s %m1, %0 7202 fst%M0.s %m0, %1 7203 fmov.ls %N1, %0 7204 fmov.sl %1, %0 7205 fmov.s %1, %0 7206 ptabs %1, %0 7207 gettr %1, %0 7208 pt %1, %0" 7209 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media, 7210 fload_media,fstore_media,fload_media,fpconv_media, 7211 fmove_media,ptabs_media,gettr_media,pt_media") 7212 (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12") 7213 (set (attr "highpart") 7214 (cond [(match_test "sh_contains_memref_p (insn)") 7215 (const_string "user")] 7216 (const_string "ignore")))]) 7217 7218(define_insn "*movsi_media_nofpu" 7219 [(set (match_operand:SI 0 "general_movdst_operand" 7220 "=r,r,r,r,m,*b,r,*b") 7221 (match_operand:SI 1 "general_movsrc_operand" 7222 "r,I16Css,nCpg,m,rZ,r,*b,Csy"))] 7223 "TARGET_SHMEDIA 7224 && (register_operand (operands[0], SImode) 7225 || sh_register_operand (operands[1], SImode) 7226 || GET_CODE (operands[1]) == TRUNCATE)" 7227 "@ 7228 add.l %1, r63, %0 7229 movi %1, %0 7230 # 7231 ld%M1.l %m1, %0 7232 st%M0.l %m0, %N1 7233 ptabs %1, %0 7234 gettr %1, %0 7235 pt %1, %0" 7236 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media, 7237 ptabs_media,gettr_media,pt_media") 7238 (set_attr "length" "4,4,8,4,4,4,4,12") 7239 (set (attr "highpart") 7240 (cond [(match_test "sh_contains_memref_p (insn)") 7241 (const_string "user")] 7242 (const_string "ignore")))]) 7243 7244(define_expand "movsi_const" 7245 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 7246 (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s") 7247 (const_int 16)] UNSPEC_EXTRACT_S16))) 7248 (set (match_dup 0) 7249 (ior:SI (ashift:SI (match_dup 0) (const_int 16)) 7250 (const:SI (unspec:SI [(match_dup 1) 7251 (const_int 0)] UNSPEC_EXTRACT_U16))))] 7252 "TARGET_SHMEDIA && reload_completed 7253 && MOVI_SHORI_BASE_OPERAND_P (operands[1])" 7254{ 7255 if (GET_CODE (operands[1]) == LABEL_REF 7256 && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL) 7257 LABEL_NUSES (XEXP (operands[1], 0)) += 2; 7258 else if (GOTOFF_P (operands[1])) 7259 { 7260 rtx unspec = XEXP (operands[1], 0); 7261 7262 if (! UNSPEC_GOTOFF_P (unspec)) 7263 { 7264 unspec = XEXP (unspec, 0); 7265 if (! UNSPEC_GOTOFF_P (unspec)) 7266 abort (); 7267 } 7268 if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF 7269 && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL)) 7270 LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2; 7271 } 7272}) 7273 7274(define_expand "movsi_const_16bit" 7275 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 7276 (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s") 7277 (const_int 0)] UNSPEC_EXTRACT_S16)))] 7278 "TARGET_SHMEDIA && flag_pic && reload_completed 7279 && GET_CODE (operands[1]) == SYMBOL_REF" 7280 "") 7281 7282(define_split 7283 [(set (match_operand:SI 0 "arith_reg_dest" "") 7284 (match_operand:SI 1 "immediate_operand" ""))] 7285 "TARGET_SHMEDIA && reload_completed 7286 && MOVI_SHORI_BASE_OPERAND_P (operands[1])" 7287 [(const_int 0)] 7288{ 7289 rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1])); 7290 7291 set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1])); 7292 7293 DONE; 7294}) 7295 7296(define_split 7297 [(set (match_operand:SI 0 "register_operand" "") 7298 (match_operand:SI 1 "immediate_operand" ""))] 7299 "TARGET_SHMEDIA && reload_completed 7300 && ((CONST_INT_P (operands[1]) 7301 && ! satisfies_constraint_I16 (operands[1])) 7302 || GET_CODE (operands[1]) == CONST_DOUBLE)" 7303 [(set (subreg:DI (match_dup 0) 0) (match_dup 1))]) 7304 7305(define_expand "movsi" 7306 [(set (match_operand:SI 0 "general_movdst_operand" "") 7307 (match_operand:SI 1 "general_movsrc_operand" ""))] 7308 "" 7309{ 7310 prepare_move_operands (operands, SImode); 7311}) 7312 7313(define_expand "ic_invalidate_line" 7314 [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r") 7315 (match_dup 1)] UNSPEC_ICACHE) 7316 (clobber (scratch:SI))])] 7317 "TARGET_HARD_SH4 || TARGET_SH5" 7318{ 7319 if (TARGET_SHMEDIA) 7320 { 7321 emit_insn (gen_ic_invalidate_line_media (operands[0])); 7322 DONE; 7323 } 7324 else if (TARGET_SHCOMPACT) 7325 { 7326 operands[1] = function_symbol (NULL, "__ic_invalidate", SFUNC_STATIC); 7327 operands[1] = force_reg (Pmode, operands[1]); 7328 emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1])); 7329 DONE; 7330 } 7331 else if (TARGET_SH4A || TARGET_SH4_300) 7332 { 7333 emit_insn (gen_ic_invalidate_line_sh4a (operands[0])); 7334 DONE; 7335 } 7336 operands[0] = force_reg (Pmode, operands[0]); 7337 operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008, 7338 Pmode))); 7339}) 7340 7341;; The address %0 is assumed to be 4-aligned at least. Thus, by ORing 7342;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits 7343;; the requirement *1*00 for associative address writes. The alignment of 7344;; %0 implies that its least significant bit is cleared, 7345;; thus we clear the V bit of a matching entry if there is one. 7346(define_insn "ic_invalidate_line_i" 7347 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r") 7348 (match_operand:SI 1 "register_operand" "r")] 7349 UNSPEC_ICACHE) 7350 (clobber (match_scratch:SI 2 "=&r"))] 7351 "TARGET_HARD_SH4" 7352{ 7353 return "ocbwb @%0" "\n" 7354 " extu.w %0,%2" "\n" 7355 " or %1,%2" "\n" 7356 " mov.l %0,@%2"; 7357} 7358 [(set_attr "length" "8") 7359 (set_attr "type" "cwb")]) 7360 7361(define_insn "ic_invalidate_line_sh4a" 7362 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] 7363 UNSPEC_ICACHE)] 7364 "TARGET_SH4A || TARGET_SH4_300" 7365{ 7366 return "ocbwb @%0" "\n" 7367 " synco" "\n" 7368 " icbi @%0"; 7369} 7370 [(set_attr "length" "16") ;; FIXME: Why 16 and not 6? Looks like typo. 7371 (set_attr "type" "cwb")]) 7372 7373;; ??? could make arg 0 an offsettable memory operand to allow to save 7374;; an add in the code that calculates the address. 7375(define_insn "ic_invalidate_line_media" 7376 [(unspec_volatile [(match_operand 0 "any_register_operand" "r")] 7377 UNSPEC_ICACHE)] 7378 "TARGET_SHMEDIA" 7379{ 7380 return "ocbwb %0,0" "\n" 7381 " synco" "\n" 7382 " icbi %0,0" "\n" 7383 " synci"; 7384} 7385 [(set_attr "length" "16") 7386 (set_attr "type" "invalidate_line_media")]) 7387 7388(define_insn "ic_invalidate_line_compact" 7389 [(unspec_volatile [(match_operand:SI 0 "register_operand" "z") 7390 (match_operand:SI 1 "register_operand" "r")] 7391 UNSPEC_ICACHE) 7392 (clobber (reg:SI PR_REG))] 7393 "TARGET_SHCOMPACT" 7394 "jsr @%1%#" 7395 [(set_attr "type" "sfunc") 7396 (set_attr "needs_delay_slot" "yes")]) 7397 7398(define_expand "initialize_trampoline" 7399 [(match_operand:SI 0 "" "") 7400 (match_operand:SI 1 "" "") 7401 (match_operand:SI 2 "" "")] 7402 "TARGET_SHCOMPACT" 7403{ 7404 rtx sfun, tramp; 7405 7406 tramp = force_reg (Pmode, operands[0]); 7407 sfun = force_reg (Pmode, function_symbol (NULL, "__init_trampoline", 7408 SFUNC_STATIC)); 7409 emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]); 7410 emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]); 7411 7412 emit_insn (gen_initialize_trampoline_compact (tramp, sfun)); 7413 DONE; 7414}) 7415 7416(define_insn "initialize_trampoline_compact" 7417 [(unspec_volatile [(match_operand:SI 0 "register_operand" "z") 7418 (match_operand:SI 1 "register_operand" "r") 7419 (reg:SI R2_REG) (reg:SI R3_REG)] 7420 UNSPEC_INIT_TRAMP) 7421 7422 (clobber (reg:SI PR_REG))] 7423 "TARGET_SHCOMPACT" 7424 "jsr @%1%#" 7425 [(set_attr "type" "sfunc") 7426 (set_attr "needs_delay_slot" "yes")]) 7427 7428(define_expand "mov<mode>" 7429 [(set (match_operand:QIHI 0 "general_movdst_operand") 7430 (match_operand:QIHI 1 "general_movsrc_operand"))] 7431 "" 7432{ 7433 if (can_create_pseudo_p () && CONST_INT_P (operands[1]) 7434 && REG_P (operands[0]) && REGNO (operands[0]) != R0_REG) 7435 { 7436 rtx reg = gen_reg_rtx(SImode); 7437 emit_move_insn (reg, operands[1]); 7438 operands[1] = gen_lowpart (<MODE>mode, reg); 7439 } 7440 7441 prepare_move_operands (operands, <MODE>mode); 7442}) 7443 7444;; Specifying the displacement addressing load / store patterns separately 7445;; before the generic movqi / movhi pattern allows controlling the order 7446;; in which load / store insns are selected in a more fine grained way. 7447;; FIXME: The non-SH2A and SH2A variants should be combined by adding 7448;; "enabled" attribute as it is done in other targets. 7449(define_insn "*mov<mode>_store_mem_disp04" 7450 [(set (mem:QIHI 7451 (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r,r") 7452 (match_operand:SI 1 "const_int_operand" "<disp04>,N"))) 7453 (match_operand:QIHI 2 "arith_reg_operand" "z,r"))] 7454 "TARGET_SH1 && sh_legitimate_index_p (<MODE>mode, operands[1], false, true)" 7455 "@ 7456 mov.<bw> %2,@(%O1,%0) 7457 mov.<bw> %2,@%0" 7458 [(set_attr "type" "store")]) 7459 7460(define_insn "*mov<mode>_store_mem_disp12" 7461 [(set (mem:QIHI 7462 (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r") 7463 (match_operand:SI 1 "const_int_operand" "<disp12>"))) 7464 (match_operand:QIHI 2 "arith_reg_operand" "r"))] 7465 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[1], true, true)" 7466 "mov.<bw> %2,@(%O1,%0)" 7467 [(set_attr "type" "store") 7468 (set_attr "length" "4")]) 7469 7470(define_insn "*mov<mode>_load_mem_disp04" 7471 [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r") 7472 (mem:QIHI 7473 (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r") 7474 (match_operand:SI 2 "const_int_operand" "<disp04>,N"))))] 7475 "TARGET_SH1 && ! TARGET_SH2A 7476 && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)" 7477 "@ 7478 mov.<bw> @(%O2,%1),%0 7479 mov.<bw> @%1,%0" 7480 [(set_attr "type" "load")]) 7481 7482(define_insn "*mov<mode>_load_mem_disp12" 7483 [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r,r") 7484 (mem:QIHI 7485 (plus:SI 7486 (match_operand:SI 1 "arith_reg_operand" "%r,r,r") 7487 (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>"))))] 7488 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)" 7489 "@ 7490 mov.<bw> @(%O2,%1),%0 7491 mov.<bw> @%1,%0 7492 mov.<bw> @(%O2,%1),%0" 7493 [(set_attr "type" "load") 7494 (set_attr "length" "2,2,4")]) 7495 7496;; The order of the constraint alternatives is important here. 7497;; Q/r has to come first, otherwise PC relative loads might wrongly get 7498;; placed into delay slots. Since there is no QImode PC relative load, the 7499;; Q constraint and general_movsrc_operand will reject it for QImode. 7500;; The Snd alternatives should come before Sdd in order to avoid a preference 7501;; of using r0 als the register operand for addressing modes other than 7502;; displacement addressing. 7503;; The Sdd alternatives allow only r0 as register operand, even though on 7504;; SH2A any register could be allowed by switching to a 32 bit insn. 7505;; Generally sticking to the r0 is preferrable, since it generates smaller 7506;; code. Obvious r0 reloads can then be eliminated with a peephole on SH2A. 7507(define_insn "*mov<mode>" 7508 [(set (match_operand:QIHI 0 "general_movdst_operand" 7509 "=r,r,r,Snd,r, Sdd,z, r,l") 7510 (match_operand:QIHI 1 "general_movsrc_operand" 7511 "Q,r,i,r, Snd,z, Sdd,l,r"))] 7512 "TARGET_SH1 7513 && (arith_reg_operand (operands[0], <MODE>mode) 7514 || arith_reg_operand (operands[1], <MODE>mode))" 7515 "@ 7516 mov.<bw> %1,%0 7517 mov %1,%0 7518 mov %1,%0 7519 mov.<bw> %1,%0 7520 mov.<bw> %1,%0 7521 mov.<bw> %1,%0 7522 mov.<bw> %1,%0 7523 sts %1,%0 7524 lds %1,%0" 7525 [(set_attr "type" "pcload,move,movi8,store,load,store,load,prget,prset") 7526 (set (attr "length") 7527 (cond [(and (match_operand 0 "displacement_mem_operand") 7528 (not (match_operand 0 "short_displacement_mem_operand"))) 7529 (const_int 4) 7530 (and (match_operand 1 "displacement_mem_operand") 7531 (not (match_operand 1 "short_displacement_mem_operand"))) 7532 (const_int 4)] 7533 (const_int 2)))]) 7534 7535(define_insn "*movqi_media" 7536 [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m") 7537 (match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))] 7538 "TARGET_SHMEDIA 7539 && (arith_reg_operand (operands[0], QImode) 7540 || extend_reg_or_0_operand (operands[1], QImode))" 7541 "@ 7542 add.l %1, r63, %0 7543 movi %1, %0 7544 ld%M1.ub %m1, %0 7545 st%M0.b %m0, %N1" 7546 [(set_attr "type" "arith_media,arith_media,load_media,store_media") 7547 (set (attr "highpart") 7548 (cond [(match_test "sh_contains_memref_p (insn)") 7549 (const_string "user")] 7550 (const_string "ignore")))]) 7551 7552(define_expand "reload_inqi" 7553 [(set (match_operand:SI 2 "" "=&r") 7554 (match_operand:QI 1 "inqhi_operand" "")) 7555 (set (match_operand:QI 0 "arith_reg_operand" "=r") 7556 (truncate:QI (match_dup 3)))] 7557 "TARGET_SHMEDIA" 7558{ 7559 rtx inner = XEXP (operands[1], 0); 7560 int regno = REGNO (inner); 7561 7562 regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1; 7563 operands[1] = gen_rtx_REG (SImode, regno); 7564 operands[3] = gen_rtx_REG (DImode, REGNO (operands[2])); 7565}) 7566 7567(define_insn "*movhi_media" 7568 [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m") 7569 (match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))] 7570 "TARGET_SHMEDIA 7571 && (arith_reg_operand (operands[0], HImode) 7572 || arith_reg_or_0_operand (operands[1], HImode))" 7573 "@ 7574 add.l %1, r63, %0 7575 movi %1, %0 7576 # 7577 ld%M1.w %m1, %0 7578 st%M0.w %m0, %N1" 7579 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media") 7580 (set (attr "highpart") 7581 (cond [(match_test "sh_contains_memref_p (insn)") 7582 (const_string "user")] 7583 (const_string "ignore")))]) 7584 7585(define_split 7586 [(set (match_operand:HI 0 "register_operand" "") 7587 (match_operand:HI 1 "immediate_operand" ""))] 7588 "TARGET_SHMEDIA && reload_completed 7589 && ! satisfies_constraint_I16 (operands[1])" 7590 [(set (subreg:DI (match_dup 0) 0) (match_dup 1))]) 7591 7592(define_expand "reload_inhi" 7593 [(set (match_operand:SI 2 "" "=&r") 7594 (match_operand:HI 1 "inqhi_operand" "")) 7595 (set (match_operand:HI 0 "arith_reg_operand" "=r") 7596 (truncate:HI (match_dup 3)))] 7597 "TARGET_SHMEDIA" 7598{ 7599 rtx inner = XEXP (operands[1], 0); 7600 int regno = REGNO (inner); 7601 7602 regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1; 7603 operands[1] = gen_rtx_REG (SImode, regno); 7604 operands[3] = gen_rtx_REG (DImode, REGNO (operands[2])); 7605}) 7606 7607;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c 7608;; compiled with -m2 -ml -O3 -funroll-loops 7609(define_insn "*movdi_i" 7610 [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x") 7611 (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))] 7612 "TARGET_SH1 7613 && (arith_reg_operand (operands[0], DImode) 7614 || arith_reg_operand (operands[1], DImode))" 7615{ 7616 return output_movedouble (insn, operands, DImode); 7617} 7618 [(set_attr "length" "4") 7619 (set_attr "type" "pcload,move,load,store,move,pcload,move,move")]) 7620 7621;; If the output is a register and the input is memory or a register, we have 7622;; to be careful and see which word needs to be loaded first. 7623(define_split 7624 [(set (match_operand:DI 0 "general_movdst_operand" "") 7625 (match_operand:DI 1 "general_movsrc_operand" ""))] 7626 "TARGET_SH1 && reload_completed" 7627 [(set (match_dup 2) (match_dup 3)) 7628 (set (match_dup 4) (match_dup 5))] 7629{ 7630 int regno; 7631 7632 if ((MEM_P (operands[0]) 7633 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) 7634 || (MEM_P (operands[1]) 7635 && GET_CODE (XEXP (operands[1], 0)) == POST_INC)) 7636 FAIL; 7637 7638 switch (GET_CODE (operands[0])) 7639 { 7640 case REG: 7641 regno = REGNO (operands[0]); 7642 break; 7643 case SUBREG: 7644 regno = subreg_regno (operands[0]); 7645 break; 7646 case MEM: 7647 regno = -1; 7648 break; 7649 default: 7650 gcc_unreachable (); 7651 } 7652 7653 if (regno == -1 || ! refers_to_regno_p (regno, operands[1])) 7654 { 7655 operands[2] = operand_subword (operands[0], 0, 0, DImode); 7656 operands[3] = operand_subword (operands[1], 0, 0, DImode); 7657 operands[4] = operand_subword (operands[0], 1, 0, DImode); 7658 operands[5] = operand_subword (operands[1], 1, 0, DImode); 7659 } 7660 else 7661 { 7662 operands[2] = operand_subword (operands[0], 1, 0, DImode); 7663 operands[3] = operand_subword (operands[1], 1, 0, DImode); 7664 operands[4] = operand_subword (operands[0], 0, 0, DImode); 7665 operands[5] = operand_subword (operands[1], 0, 0, DImode); 7666 } 7667 7668 if (operands[2] == 0 || operands[3] == 0 7669 || operands[4] == 0 || operands[5] == 0) 7670 FAIL; 7671}) 7672 7673;; The '?'s in the following constraints may not reflect the time taken 7674;; to perform the move. They are there to discourage the use of floating- 7675;; point registers for storing integer values. 7676(define_insn "*movdi_media" 7677 [(set (match_operand:DI 0 "general_movdst_operand" 7678 "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b") 7679 (match_operand:DI 1 "general_movsrc_operand" 7680 "r,I16Css,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))] 7681 "TARGET_SHMEDIA_FPU 7682 && (register_operand (operands[0], DImode) 7683 || sh_register_operand (operands[1], DImode))" 7684 "@ 7685 add %1, r63, %0 7686 movi %1, %0 7687 # 7688 ld%M1.q %m1, %0 7689 st%M0.q %m0, %N1 7690 fld%M1.d %m1, %0 7691 fst%M0.d %m0, %1 7692 fmov.qd %N1, %0 7693 fmov.dq %1, %0 7694 fmov.d %1, %0 7695 ptabs %1, %0 7696 gettr %1, %0 7697 pt %1, %0" 7698 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media, 7699 fload_media,fstore_media,fload_media,dfpconv_media, 7700 fmove_media,ptabs_media,gettr_media,pt_media") 7701 (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")]) 7702 7703(define_insn "*movdi_media_nofpu" 7704 [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b"); 7705 (match_operand:DI 1 "general_movsrc_operand" "r,I16Css,nCpgF,m,rlZ,r,*b,Csy"))] 7706 "TARGET_SHMEDIA 7707 && (register_operand (operands[0], DImode) 7708 || sh_register_operand (operands[1], DImode))" 7709 "@ 7710 add %1, r63, %0 7711 movi %1, %0 7712 # 7713 ld%M1.q %m1, %0 7714 st%M0.q %m0, %N1 7715 ptabs %1, %0 7716 gettr %1, %0 7717 pt %1, %0" 7718 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media, 7719 ptabs_media,gettr_media,pt_media") 7720 (set_attr "length" "4,4,16,4,4,4,4,*")]) 7721 7722(define_insn "*movdi_media_I16" 7723 [(set (match_operand:DI 0 "ext_dest_operand" "=r") 7724 (match_operand:DI 1 "const_int_operand" "I16"))] 7725 "TARGET_SHMEDIA && reload_completed" 7726 "movi %1, %0" 7727 [(set_attr "type" "arith_media") 7728 (set_attr "length" "4")]) 7729 7730(define_split 7731 [(set (match_operand:DI 0 "arith_reg_dest" "") 7732 (match_operand:DI 1 "immediate_operand" ""))] 7733 "TARGET_SHMEDIA && reload_completed 7734 && MOVI_SHORI_BASE_OPERAND_P (operands[1])" 7735 [(set (match_dup 0) (match_dup 1))] 7736{ 7737 rtx insn; 7738 7739 if (TARGET_SHMEDIA64) 7740 insn = emit_insn (gen_movdi_const (operands[0], operands[1])); 7741 else 7742 insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1])); 7743 7744 set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1])); 7745 7746 DONE; 7747}) 7748 7749(define_expand "movdi_const" 7750 [(set (match_operand:DI 0 "arith_reg_operand" "=r") 7751 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s") 7752 (const_int 48)] UNSPEC_EXTRACT_S16))) 7753 (set (match_dup 0) 7754 (ior:DI (ashift:DI (match_dup 0) (const_int 16)) 7755 (const:DI (unspec:DI [(match_dup 1) 7756 (const_int 32)] UNSPEC_EXTRACT_U16)))) 7757 (set (match_dup 0) 7758 (ior:DI (ashift:DI (match_dup 0) (const_int 16)) 7759 (const:DI (unspec:DI [(match_dup 1) 7760 (const_int 16)] UNSPEC_EXTRACT_U16)))) 7761 (set (match_dup 0) 7762 (ior:DI (ashift:DI (match_dup 0) (const_int 16)) 7763 (const:DI (unspec:DI [(match_dup 1) 7764 (const_int 0)] UNSPEC_EXTRACT_U16))))] 7765 "TARGET_SHMEDIA64 && reload_completed 7766 && MOVI_SHORI_BASE_OPERAND_P (operands[1])" 7767{ 7768 sh_mark_label (operands[1], 4); 7769}) 7770 7771(define_expand "movdi_const_32bit" 7772 [(set (match_operand:DI 0 "arith_reg_operand" "=r") 7773 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s") 7774 (const_int 16)] UNSPEC_EXTRACT_S16))) 7775 (set (match_dup 0) 7776 (ior:DI (ashift:DI (match_dup 0) (const_int 16)) 7777 (const:DI (unspec:DI [(match_dup 1) 7778 (const_int 0)] UNSPEC_EXTRACT_U16))))] 7779 "TARGET_SHMEDIA32 && reload_completed 7780 && MOVI_SHORI_BASE_OPERAND_P (operands[1])" 7781{ 7782 sh_mark_label (operands[1], 2); 7783}) 7784 7785(define_expand "movdi_const_16bit" 7786 [(set (match_operand:DI 0 "arith_reg_operand" "=r") 7787 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s") 7788 (const_int 0)] UNSPEC_EXTRACT_S16)))] 7789 "TARGET_SHMEDIA && flag_pic && reload_completed 7790 && GET_CODE (operands[1]) == SYMBOL_REF" 7791 "") 7792 7793(define_split 7794 [(set (match_operand:DI 0 "ext_dest_operand" "") 7795 (match_operand:DI 1 "immediate_operand" ""))] 7796 "TARGET_SHMEDIA && reload_completed 7797 && CONST_INT_P (operands[1]) 7798 && ! satisfies_constraint_I16 (operands[1])" 7799 [(set (match_dup 0) (match_dup 2)) 7800 (match_dup 1)] 7801{ 7802 unsigned HOST_WIDE_INT val = INTVAL (operands[1]); 7803 unsigned HOST_WIDE_INT low = val; 7804 unsigned HOST_WIDE_INT high = val; 7805 unsigned HOST_WIDE_INT sign; 7806 unsigned HOST_WIDE_INT val2 = val ^ (val-1); 7807 7808 /* Zero-extend the 16 least-significant bits. */ 7809 low &= 0xffff; 7810 7811 /* Arithmetic shift right the word by 16 bits. */ 7812 high >>= 16; 7813 if (GET_CODE (operands[0]) == SUBREG 7814 && GET_MODE (SUBREG_REG (operands[0])) == SImode) 7815 { 7816 high &= 0xffff; 7817 high ^= 0x8000; 7818 high -= 0x8000; 7819 } 7820 else 7821 { 7822 sign = 1; 7823 sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1); 7824 high ^= sign; 7825 high -= sign; 7826 } 7827 do 7828 { 7829 /* If we can't generate the constant with a two-insn movi / shori 7830 sequence, try some other strategies. */ 7831 if (! CONST_OK_FOR_I16 (high)) 7832 { 7833 /* Try constant load / left shift. We know VAL != 0. */ 7834 val2 = val ^ (val-1); 7835 if (val2 > 0x1ffff) 7836 { 7837 int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15; 7838 7839 if (CONST_OK_FOR_I16 (val >> trailing_zeroes) 7840 || (! CONST_OK_FOR_I16 (high >> 16) 7841 && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16)))) 7842 { 7843 val2 = (HOST_WIDE_INT) val >> trailing_zeroes; 7844 operands[1] = gen_ashldi3_media (operands[0], operands[0], 7845 GEN_INT (trailing_zeroes)); 7846 break; 7847 } 7848 } 7849 /* Try constant load / right shift. */ 7850 val2 = (val >> 15) + 1; 7851 if (val2 == (val2 & -val2)) 7852 { 7853 int shift = 49 - exact_log2 (val2); 7854 7855 val2 = trunc_int_for_mode (val << shift, DImode); 7856 if (CONST_OK_FOR_I16 (val2)) 7857 { 7858 operands[1] = gen_lshrdi3_media (operands[0], operands[0], 7859 GEN_INT (shift)); 7860 break; 7861 } 7862 } 7863 /* Try mperm.w . */ 7864 val2 = val & 0xffff; 7865 if ((val >> 16 & 0xffff) == val2 7866 && (val >> 32 & 0xffff) == val2 7867 && (val >> 48 & 0xffff) == val2) 7868 { 7869 val2 = (HOST_WIDE_INT) val >> 48; 7870 operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0])); 7871 operands[1] = gen_mperm_w0 (operands[1], operands[1]); 7872 break; 7873 } 7874 /* Try movi / mshflo.l */ 7875 val2 = (HOST_WIDE_INT) val >> 32; 7876 if (val2 == ((unsigned HOST_WIDE_INT) 7877 trunc_int_for_mode (val, SImode))) 7878 { 7879 operands[1] = gen_mshflo_l_di (operands[0], operands[0], 7880 operands[0]); 7881 break; 7882 } 7883 /* Try movi / mshflo.l w/ r63. */ 7884 val2 = val + ((HOST_WIDE_INT) -1 << 32); 7885 if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2)) 7886 { 7887 operands[1] = gen_mshflo_l_di (operands[0], operands[0], 7888 const0_rtx); 7889 break; 7890 } 7891 } 7892 val2 = high; 7893 operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low)); 7894 } 7895 while (0); 7896 operands[2] = GEN_INT (val2); 7897}) 7898 7899(define_split 7900 [(set (match_operand:DI 0 "ext_dest_operand" "") 7901 (match_operand:DI 1 "immediate_operand" ""))] 7902 "TARGET_SHMEDIA && reload_completed 7903 && GET_CODE (operands[1]) == CONST_DOUBLE" 7904 [(set (match_dup 0) (match_dup 2)) 7905 (set (match_dup 0) 7906 (ior:DI (ashift:DI (match_dup 0) (const_int 16)) (match_dup 1)))] 7907{ 7908 unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]); 7909 unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]); 7910 unsigned HOST_WIDE_INT val = low; 7911 unsigned HOST_WIDE_INT sign; 7912 7913 /* Zero-extend the 16 least-significant bits. */ 7914 val &= 0xffff; 7915 operands[1] = GEN_INT (val); 7916 7917 /* Arithmetic shift right the double-word by 16 bits. */ 7918 low >>= 16; 7919 low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16); 7920 high >>= 16; 7921 sign = 1; 7922 sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1); 7923 high ^= sign; 7924 high -= sign; 7925 7926 /* This will only be true if high is a sign-extension of low, i.e., 7927 it must be either 0 or (unsigned)-1, and be zero iff the 7928 most-significant bit of low is set. */ 7929 if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0) 7930 operands[2] = GEN_INT (low); 7931 else 7932 operands[2] = immed_double_const (low, high, DImode); 7933}) 7934 7935(define_insn "shori_media" 7936 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r") 7937 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0") 7938 (const_int 16)) 7939 (match_operand:DI 2 "immediate_operand" "K16Csu,nF")))] 7940 "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))" 7941 "@ 7942 shori %u2, %0 7943 #" 7944 [(set_attr "type" "arith_media,*")]) 7945 7946(define_insn "*shori_media_si" 7947 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 7948 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") 7949 (const_int 16)) 7950 (match_operand:SI 2 "immediate_operand" "K16Csu")))] 7951 "TARGET_SHMEDIA" 7952 "shori %u2, %0") 7953 7954(define_expand "movdi" 7955 [(set (match_operand:DI 0 "general_movdst_operand" "") 7956 (match_operand:DI 1 "general_movsrc_operand" ""))] 7957 "" 7958{ 7959 prepare_move_operands (operands, DImode); 7960 if (TARGET_SH1) 7961 { 7962 /* When the dest operand is (R0, R1) register pair, split it to 7963 two movsi of which dest is R1 and R0 so as to lower R0-register 7964 pressure on the first movsi. Apply only for simple source not 7965 to make complex rtl here. */ 7966 if (REG_P (operands[0]) 7967 && REGNO (operands[0]) == R0_REG 7968 && REG_P (operands[1]) 7969 && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER) 7970 { 7971 emit_insn (gen_movsi (gen_rtx_REG (SImode, R1_REG), 7972 gen_rtx_SUBREG (SImode, operands[1], 4))); 7973 emit_insn (gen_movsi (gen_rtx_REG (SImode, R0_REG), 7974 gen_rtx_SUBREG (SImode, operands[1], 0))); 7975 DONE; 7976 } 7977 } 7978}) 7979 7980(define_insn "movdf_media" 7981 [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m") 7982 (match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))] 7983 "TARGET_SHMEDIA_FPU 7984 && (register_operand (operands[0], DFmode) 7985 || sh_register_operand (operands[1], DFmode))" 7986 "@ 7987 fmov.d %1, %0 7988 fmov.qd %N1, %0 7989 fmov.dq %1, %0 7990 add %1, r63, %0 7991 # 7992 fld%M1.d %m1, %0 7993 fst%M0.d %m0, %1 7994 ld%M1.q %m1, %0 7995 st%M0.q %m0, %N1" 7996 [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*, 7997 fload_media,fstore_media,load_media,store_media")]) 7998 7999(define_insn "movdf_media_nofpu" 8000 [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m") 8001 (match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))] 8002 "TARGET_SHMEDIA 8003 && (register_operand (operands[0], DFmode) 8004 || sh_register_operand (operands[1], DFmode))" 8005 "@ 8006 add %1, r63, %0 8007 # 8008 ld%M1.q %m1, %0 8009 st%M0.q %m0, %N1" 8010 [(set_attr "type" "arith_media,*,load_media,store_media")]) 8011 8012(define_split 8013 [(set (match_operand:DF 0 "arith_reg_dest" "") 8014 (match_operand:DF 1 "immediate_operand" ""))] 8015 "TARGET_SHMEDIA && reload_completed" 8016 [(set (match_dup 3) (match_dup 2))] 8017{ 8018 int endian = WORDS_BIG_ENDIAN ? 1 : 0; 8019 long values[2]; 8020 REAL_VALUE_TYPE value; 8021 8022 REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]); 8023 REAL_VALUE_TO_TARGET_DOUBLE (value, values); 8024 8025 if (HOST_BITS_PER_WIDE_INT >= 64) 8026 operands[2] = immed_double_const ((unsigned long) values[endian] 8027 | ((HOST_WIDE_INT) values[1 - endian] 8028 << 32), 0, DImode); 8029 else 8030 { 8031 gcc_assert (HOST_BITS_PER_WIDE_INT == 32); 8032 operands[2] = immed_double_const (values[endian], values[1 - endian], 8033 DImode); 8034 } 8035 8036 operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0])); 8037}) 8038 8039;; FIXME: This should be a define_insn_and_split. 8040(define_insn "movdf_k" 8041 [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m") 8042 (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))] 8043 "TARGET_SH1 8044 && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed 8045 /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */ 8046 || (REG_P (operands[0]) && REGNO (operands[0]) == 3) 8047 || (REG_P (operands[1]) && REGNO (operands[1]) == 3)) 8048 && (arith_reg_operand (operands[0], DFmode) 8049 || arith_reg_operand (operands[1], DFmode))" 8050{ 8051 return output_movedouble (insn, operands, DFmode); 8052} 8053 [(set_attr "length" "4") 8054 (set_attr "type" "move,pcload,load,store")]) 8055 8056;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD. 8057;; However, the d/F/c/z alternative cannot be split directly; it is converted 8058;; with special code in machine_dependent_reorg into a load of the R0_REG and 8059;; the d/m/c/X alternative, which is split later into single-precision 8060;; instructions. And when not optimizing, no splits are done before fixing 8061;; up pcloads, so we need usable length information for that. 8062(define_insn "movdf_i4" 8063 [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d") 8064 (match_operand:DF 1 "general_movsrc_operand" "d,r,F,m,d,FQ,m,r,d,r")) 8065 (use (reg:SI FPSCR_MODES_REG)) 8066 (clobber (match_scratch:SI 2 "=X,X,&z,X,X,X,X,X,X,X"))] 8067 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) 8068 && (arith_reg_operand (operands[0], DFmode) 8069 || arith_reg_operand (operands[1], DFmode))" 8070 { 8071 switch (which_alternative) 8072 { 8073 case 0: 8074 if (TARGET_FMOVD) 8075 return "fmov %1,%0"; 8076 else if (REGNO (operands[0]) != REGNO (operands[1]) + 1) 8077 return "fmov %R1,%R0" "\n" 8078 " fmov %S1,%S0"; 8079 else 8080 return "fmov %S1,%S0" "\n" 8081 " fmov %R1,%R0"; 8082 case 3: 8083 case 4: 8084 return "fmov.d %1,%0"; 8085 default: 8086 return "#"; 8087 } 8088 } 8089 [(set_attr_alternative "length" 8090 [(if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 8)) 8091 (const_int 4) 8092 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6)) 8093 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6)) 8094 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6)) 8095 (const_int 4) 8096 (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn) 8097 ;; We can't use 4-byte push/pop on SHcompact, so we have to 8098 ;; increment or decrement r15 explicitly. 8099 (if_then_else 8100 (match_test "TARGET_SHCOMPACT") 8101 (const_int 10) (const_int 8)) 8102 (if_then_else 8103 (match_test "TARGET_SHCOMPACT") 8104 (const_int 10) (const_int 8))]) 8105 (set_attr "type" "fmove,move,pcfload,fload,fstore,pcload,load,store,load,fload") 8106 (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*") 8107 (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes") 8108 (const_string "double") 8109 (const_string "none")))]) 8110 8111;; Moving DFmode between fp/general registers through memory 8112;; (the top of the stack) is faster than moving through fpul even for 8113;; little endian. Because the type of an instruction is important for its 8114;; scheduling, it is beneficial to split these operations, rather than 8115;; emitting them in one single chunk, even if this will expose a stack 8116;; use that will prevent scheduling of other stack accesses beyond this 8117;; instruction. 8118(define_split 8119 [(set (match_operand:DF 0 "register_operand") 8120 (match_operand:DF 1 "register_operand")) 8121 (use (reg:SI FPSCR_MODES_REG)) 8122 (clobber (match_scratch:SI 2))] 8123 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed 8124 && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)" 8125 [(const_int 0)] 8126{ 8127 rtx insn, tos; 8128 8129 if (TARGET_SH5 && true_regnum (operands[1]) < 16) 8130 { 8131 emit_move_insn (stack_pointer_rtx, 8132 plus_constant (Pmode, stack_pointer_rtx, -8)); 8133 tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx); 8134 } 8135 else 8136 tos = gen_tmp_stack_mem (DFmode, 8137 gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx)); 8138 insn = emit_insn (gen_movdf_i4 (tos, operands[1])); 8139 if (! (TARGET_SH5 && true_regnum (operands[1]) < 16)) 8140 add_reg_note (insn, REG_INC, stack_pointer_rtx); 8141 if (TARGET_SH5 && true_regnum (operands[0]) < 16) 8142 tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx); 8143 else 8144 tos = gen_tmp_stack_mem (DFmode, 8145 gen_rtx_POST_INC (Pmode, stack_pointer_rtx)); 8146 insn = emit_insn (gen_movdf_i4 (operands[0], tos)); 8147 if (TARGET_SH5 && true_regnum (operands[0]) < 16) 8148 emit_move_insn (stack_pointer_rtx, 8149 plus_constant (Pmode, stack_pointer_rtx, 8)); 8150 else 8151 add_reg_note (insn, REG_INC, stack_pointer_rtx); 8152 DONE; 8153}) 8154 8155;; local-alloc sometimes allocates scratch registers even when not required, 8156;; so we must be prepared to handle these. 8157 8158;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k. 8159(define_split 8160 [(set (match_operand:DF 0 "general_movdst_operand" "") 8161 (match_operand:DF 1 "general_movsrc_operand" "")) 8162 (use (reg:SI FPSCR_MODES_REG)) 8163 (clobber (match_scratch:SI 2))] 8164 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) 8165 && reload_completed 8166 && true_regnum (operands[0]) < 16 8167 && true_regnum (operands[1]) < 16" 8168 [(set (match_dup 0) (match_dup 1))] 8169{ 8170 /* If this was a reg <-> mem operation with base + index reg addressing, 8171 we have to handle this in a special way. */ 8172 rtx mem = operands[0]; 8173 int store_p = 1; 8174 if (! memory_operand (mem, DFmode)) 8175 { 8176 mem = operands[1]; 8177 store_p = 0; 8178 } 8179 if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0) 8180 mem = SUBREG_REG (mem); 8181 if (MEM_P (mem)) 8182 { 8183 rtx addr = XEXP (mem, 0); 8184 if (GET_CODE (addr) == PLUS 8185 && REG_P (XEXP (addr, 0)) 8186 && REG_P (XEXP (addr, 1))) 8187 { 8188 int offset; 8189 rtx reg0 = gen_rtx_REG (Pmode, 0); 8190 rtx regop = operands[store_p], word0 ,word1; 8191 8192 if (GET_CODE (regop) == SUBREG) 8193 alter_subreg (®op, true); 8194 if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1))) 8195 offset = 2; 8196 else 8197 offset = 4; 8198 mem = copy_rtx (mem); 8199 PUT_MODE (mem, SImode); 8200 word0 = gen_rtx_SUBREG (SImode, regop, 0); 8201 alter_subreg (&word0, true); 8202 word1 = gen_rtx_SUBREG (SImode, regop, 4); 8203 alter_subreg (&word1, true); 8204 if (store_p || ! refers_to_regno_p (REGNO (word0), addr)) 8205 { 8206 emit_insn (store_p 8207 ? gen_movsi_ie (mem, word0) 8208 : gen_movsi_ie (word0, mem)); 8209 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset))); 8210 mem = copy_rtx (mem); 8211 emit_insn (store_p 8212 ? gen_movsi_ie (mem, word1) 8213 : gen_movsi_ie (word1, mem)); 8214 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset))); 8215 } 8216 else 8217 { 8218 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset))); 8219 emit_insn (gen_movsi_ie (word1, mem)); 8220 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset))); 8221 mem = copy_rtx (mem); 8222 emit_insn (gen_movsi_ie (word0, mem)); 8223 } 8224 DONE; 8225 } 8226 } 8227}) 8228 8229;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads. 8230(define_split 8231 [(set (match_operand:DF 0 "register_operand" "") 8232 (match_operand:DF 1 "memory_operand" "")) 8233 (use (reg:SI FPSCR_MODES_REG)) 8234 (clobber (reg:SI R0_REG))] 8235 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed" 8236 [(parallel [(set (match_dup 0) (match_dup 1)) 8237 (use (reg:SI FPSCR_MODES_REG)) 8238 (clobber (scratch:SI))])] 8239 "") 8240 8241(define_expand "reload_indf__frn" 8242 [(parallel [(set (match_operand:DF 0 "register_operand" "=a") 8243 (match_operand:DF 1 "immediate_operand" "FQ")) 8244 (use (reg:SI FPSCR_MODES_REG)) 8245 (clobber (match_operand:SI 2 "register_operand" "=&z"))])] 8246 "TARGET_SH1" 8247 "") 8248 8249(define_expand "reload_outdf__RnFRm" 8250 [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f") 8251 (match_operand:DF 1 "register_operand" "af,r")) 8252 (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])] 8253 "TARGET_SH1" 8254 "") 8255 8256;; Simplify no-op moves. 8257(define_split 8258 [(set (match_operand:SF 0 "register_operand" "") 8259 (match_operand:SF 1 "register_operand" "")) 8260 (use (reg:SI FPSCR_MODES_REG)) 8261 (clobber (match_scratch:SI 2))] 8262 "TARGET_SH2E && reload_completed 8263 && true_regnum (operands[0]) == true_regnum (operands[1])" 8264 [(set (match_dup 0) (match_dup 0))] 8265 "") 8266 8267;; fmovd substitute post-reload splits 8268(define_split 8269 [(set (match_operand:DF 0 "register_operand" "") 8270 (match_operand:DF 1 "register_operand" "")) 8271 (use (reg:SI FPSCR_MODES_REG)) 8272 (clobber (match_scratch:SI 2))] 8273 "TARGET_SH4 && ! TARGET_FMOVD && reload_completed 8274 && FP_OR_XD_REGISTER_P (true_regnum (operands[0])) 8275 && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))" 8276 [(const_int 0)] 8277{ 8278 int dst = true_regnum (operands[0]), src = true_regnum (operands[1]); 8279 emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst), 8280 gen_rtx_REG (SFmode, src))); 8281 emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1), 8282 gen_rtx_REG (SFmode, src + 1))); 8283 DONE; 8284}) 8285 8286(define_split 8287 [(set (match_operand:DF 0 "register_operand" "") 8288 (mem:DF (match_operand:SI 1 "register_operand" ""))) 8289 (use (reg:SI FPSCR_MODES_REG)) 8290 (clobber (match_scratch:SI 2))] 8291 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed 8292 && FP_OR_XD_REGISTER_P (true_regnum (operands[0])) 8293 && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))" 8294 [(const_int 0)] 8295{ 8296 int regno = true_regnum (operands[0]); 8297 rtx insn; 8298 rtx mem = SET_SRC (XVECEXP (PATTERN (curr_insn), 0, 0)); 8299 rtx mem2 8300 = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1])); 8301 insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, 8302 regno + SH_REG_MSW_OFFSET), 8303 mem2)); 8304 add_reg_note (insn, REG_INC, operands[1]); 8305 insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, 8306 regno + SH_REG_LSW_OFFSET), 8307 change_address (mem, SFmode, NULL_RTX))); 8308 DONE; 8309}) 8310 8311(define_split 8312 [(set (match_operand:DF 0 "register_operand" "") 8313 (match_operand:DF 1 "memory_operand" "")) 8314 (use (reg:SI FPSCR_MODES_REG)) 8315 (clobber (match_scratch:SI 2))] 8316 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed 8317 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))" 8318 [(const_int 0)] 8319{ 8320 int regno = true_regnum (operands[0]); 8321 rtx addr, insn; 8322 rtx mem2 = change_address (operands[1], SFmode, NULL_RTX); 8323 rtx reg0 = gen_rtx_REG (SFmode, regno + SH_REG_MSW_OFFSET); 8324 rtx reg1 = gen_rtx_REG (SFmode, regno + SH_REG_LSW_OFFSET); 8325 8326 operands[1] = copy_rtx (mem2); 8327 addr = XEXP (mem2, 0); 8328 8329 switch (GET_CODE (addr)) 8330 { 8331 case REG: 8332 /* This is complicated. If the register is an arithmetic register 8333 we can just fall through to the REG+DISP case below. Otherwise 8334 we have to use a combination of POST_INC and REG addressing... */ 8335 if (! arith_reg_operand (operands[1], SFmode)) 8336 { 8337 XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr); 8338 insn = emit_insn (gen_movsf_ie (reg0, mem2)); 8339 add_reg_note (insn, REG_INC, XEXP (addr, 0)); 8340 8341 emit_insn (gen_movsf_ie (reg1, operands[1])); 8342 8343 /* If we have modified the stack pointer, the value that we have 8344 read with post-increment might be modified by an interrupt, 8345 so write it back. */ 8346 if (REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM) 8347 emit_insn (gen_push_e (reg0)); 8348 else 8349 emit_insn (gen_addsi3 (XEXP (operands[1], 0), XEXP (operands[1], 0), 8350 GEN_INT (-4))); 8351 break; 8352 } 8353 /* Fall through. */ 8354 8355 case PLUS: 8356 emit_insn (gen_movsf_ie (reg0, operands[1])); 8357 operands[1] = copy_rtx (operands[1]); 8358 XEXP (operands[1], 0) = plus_constant (Pmode, addr, 4); 8359 emit_insn (gen_movsf_ie (reg1, operands[1])); 8360 break; 8361 8362 case POST_INC: 8363 insn = emit_insn (gen_movsf_ie (reg0, operands[1])); 8364 add_reg_note (insn, REG_INC, XEXP (addr, 0)); 8365 8366 insn = emit_insn (gen_movsf_ie (reg1, operands[1])); 8367 add_reg_note (insn, REG_INC, XEXP (addr, 0)); 8368 break; 8369 8370 default: 8371 debug_rtx (addr); 8372 gcc_unreachable (); 8373 } 8374 8375 DONE; 8376}) 8377 8378(define_split 8379 [(set (match_operand:DF 0 "memory_operand" "") 8380 (match_operand:DF 1 "register_operand" "")) 8381 (use (reg:SI FPSCR_MODES_REG)) 8382 (clobber (match_scratch:SI 2))] 8383 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed 8384 && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))" 8385 [(const_int 0)] 8386{ 8387 int regno = true_regnum (operands[1]); 8388 rtx insn, addr; 8389 rtx reg0 = gen_rtx_REG (SFmode, regno + SH_REG_MSW_OFFSET); 8390 rtx reg1 = gen_rtx_REG (SFmode, regno + SH_REG_LSW_OFFSET); 8391 8392 operands[0] = copy_rtx (operands[0]); 8393 PUT_MODE (operands[0], SFmode); 8394 addr = XEXP (operands[0], 0); 8395 8396 switch (GET_CODE (addr)) 8397 { 8398 case REG: 8399 /* This is complicated. If the register is an arithmetic register 8400 we can just fall through to the REG+DISP case below. Otherwise 8401 we have to use a combination of REG and PRE_DEC addressing... */ 8402 if (! arith_reg_operand (operands[0], SFmode)) 8403 { 8404 emit_insn (gen_addsi3 (addr, addr, GEN_INT (4))); 8405 emit_insn (gen_movsf_ie (operands[0], reg1)); 8406 8407 operands[0] = copy_rtx (operands[0]); 8408 XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr); 8409 8410 insn = emit_insn (gen_movsf_ie (operands[0], reg0)); 8411 add_reg_note (insn, REG_INC, XEXP (addr, 0)); 8412 break; 8413 } 8414 /* Fall through. */ 8415 8416 case PLUS: 8417 /* Since REG+DISP addressing has already been decided upon by gcc 8418 we can rely upon it having chosen an arithmetic register as the 8419 register component of the address. Just emit the lower numbered 8420 register first, to the lower address, then the higher numbered 8421 register to the higher address. */ 8422 emit_insn (gen_movsf_ie (operands[0], reg0)); 8423 8424 operands[0] = copy_rtx (operands[0]); 8425 XEXP (operands[0], 0) = plus_constant (Pmode, addr, 4); 8426 8427 emit_insn (gen_movsf_ie (operands[0], reg1)); 8428 break; 8429 8430 case PRE_DEC: 8431 /* This is easy. Output the word to go to the higher address 8432 first (ie the word in the higher numbered register) then the 8433 word to go to the lower address. */ 8434 8435 insn = emit_insn (gen_movsf_ie (operands[0], reg1)); 8436 add_reg_note (insn, REG_INC, XEXP (addr, 0)); 8437 8438 insn = emit_insn (gen_movsf_ie (operands[0], reg0)); 8439 add_reg_note (insn, REG_INC, XEXP (addr, 0)); 8440 break; 8441 8442 default: 8443 /* FAIL; */ 8444 debug_rtx (addr); 8445 gcc_unreachable (); 8446 } 8447 8448 DONE; 8449}) 8450 8451;; If the output is a register and the input is memory or a register, we have 8452;; to be careful and see which word needs to be loaded first. 8453(define_split 8454 [(set (match_operand:DF 0 "general_movdst_operand" "") 8455 (match_operand:DF 1 "general_movsrc_operand" ""))] 8456 "TARGET_SH1 && reload_completed" 8457 [(set (match_dup 2) (match_dup 3)) 8458 (set (match_dup 4) (match_dup 5))] 8459{ 8460 int regno; 8461 8462 if ((MEM_P (operands[0]) 8463 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) 8464 || (MEM_P (operands[1]) 8465 && GET_CODE (XEXP (operands[1], 0)) == POST_INC)) 8466 FAIL; 8467 8468 switch (GET_CODE (operands[0])) 8469 { 8470 case REG: 8471 regno = REGNO (operands[0]); 8472 break; 8473 case SUBREG: 8474 regno = subreg_regno (operands[0]); 8475 break; 8476 case MEM: 8477 regno = -1; 8478 break; 8479 default: 8480 gcc_unreachable (); 8481 } 8482 8483 if (regno == -1 || ! refers_to_regno_p (regno, operands[1])) 8484 { 8485 operands[2] = operand_subword (operands[0], 0, 0, DFmode); 8486 operands[3] = operand_subword (operands[1], 0, 0, DFmode); 8487 operands[4] = operand_subword (operands[0], 1, 0, DFmode); 8488 operands[5] = operand_subword (operands[1], 1, 0, DFmode); 8489 } 8490 else 8491 { 8492 operands[2] = operand_subword (operands[0], 1, 0, DFmode); 8493 operands[3] = operand_subword (operands[1], 1, 0, DFmode); 8494 operands[4] = operand_subword (operands[0], 0, 0, DFmode); 8495 operands[5] = operand_subword (operands[1], 0, 0, DFmode); 8496 } 8497 8498 if (operands[2] == 0 || operands[3] == 0 8499 || operands[4] == 0 || operands[5] == 0) 8500 FAIL; 8501}) 8502 8503(define_expand "movdf" 8504 [(set (match_operand:DF 0 "general_movdst_operand" "") 8505 (match_operand:DF 1 "general_movsrc_operand" ""))] 8506 "" 8507{ 8508 prepare_move_operands (operands, DFmode); 8509 if (TARGET_SHMEDIA) 8510 { 8511 if (TARGET_SHMEDIA_FPU) 8512 emit_insn (gen_movdf_media (operands[0], operands[1])); 8513 else 8514 emit_insn (gen_movdf_media_nofpu (operands[0], operands[1])); 8515 DONE; 8516 } 8517 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 8518 { 8519 emit_insn (gen_movdf_i4 (operands[0], operands[1])); 8520 DONE; 8521 } 8522}) 8523 8524;;This is incompatible with the way gcc uses subregs. 8525;;(define_insn "movv2sf_i" 8526;; [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m") 8527;; (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))] 8528;; "TARGET_SHMEDIA_FPU 8529;; && (fp_arith_reg_operand (operands[0], V2SFmode) 8530;; || fp_arith_reg_operand (operands[1], V2SFmode))" 8531;; "@ 8532;; # 8533;; fld%M1.p %m1, %0 8534;; fst%M0.p %m0, %1" 8535;; [(set_attr "type" "*,fload_media,fstore_media")]) 8536(define_insn_and_split "movv2sf_i" 8537 [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf") 8538 (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))] 8539 "TARGET_SHMEDIA_FPU" 8540 "#" 8541 "TARGET_SHMEDIA_FPU && reload_completed" 8542 [(set (match_dup 0) (match_dup 1))] 8543{ 8544 operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0); 8545 operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0); 8546}) 8547 8548(define_expand "movv2sf" 8549 [(set (match_operand:V2SF 0 "general_movdst_operand" "") 8550 (match_operand:V2SF 1 "nonimmediate_operand" ""))] 8551 "TARGET_SHMEDIA_FPU" 8552{ 8553 prepare_move_operands (operands, V2SFmode); 8554}) 8555 8556(define_expand "addv2sf3" 8557 [(match_operand:V2SF 0 "fp_arith_reg_operand" "") 8558 (match_operand:V2SF 1 "fp_arith_reg_operand" "") 8559 (match_operand:V2SF 2 "fp_arith_reg_operand" "")] 8560 "TARGET_SHMEDIA_FPU" 8561{ 8562 sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]); 8563 DONE; 8564}) 8565 8566(define_expand "subv2sf3" 8567 [(match_operand:V2SF 0 "fp_arith_reg_operand" "") 8568 (match_operand:V2SF 1 "fp_arith_reg_operand" "") 8569 (match_operand:V2SF 2 "fp_arith_reg_operand" "")] 8570 "TARGET_SHMEDIA_FPU" 8571{ 8572 sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]); 8573 DONE; 8574}) 8575 8576(define_expand "mulv2sf3" 8577 [(match_operand:V2SF 0 "fp_arith_reg_operand" "") 8578 (match_operand:V2SF 1 "fp_arith_reg_operand" "") 8579 (match_operand:V2SF 2 "fp_arith_reg_operand" "")] 8580 "TARGET_SHMEDIA_FPU" 8581{ 8582 sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]); 8583 DONE; 8584}) 8585 8586(define_expand "divv2sf3" 8587 [(match_operand:V2SF 0 "fp_arith_reg_operand" "") 8588 (match_operand:V2SF 1 "fp_arith_reg_operand" "") 8589 (match_operand:V2SF 2 "fp_arith_reg_operand" "")] 8590 "TARGET_SHMEDIA_FPU" 8591{ 8592 sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]); 8593 DONE; 8594}) 8595 8596(define_insn_and_split "*movv4sf_i" 8597 [(set (match_operand:V4SF 0 "general_movdst_operand" "=f,rf,r,m,mf") 8598 (match_operand:V4SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))] 8599 "TARGET_SHMEDIA_FPU" 8600 "#" 8601 "&& reload_completed" 8602 [(const_int 0)] 8603{ 8604 for (int i = 0; i < 4/2; i++) 8605 { 8606 rtx x, y; 8607 8608 if (MEM_P (operands[0])) 8609 x = adjust_address (operands[0], V2SFmode, 8610 i * GET_MODE_SIZE (V2SFmode)); 8611 else 8612 x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8); 8613 8614 if (MEM_P (operands[1])) 8615 y = adjust_address (operands[1], V2SFmode, 8616 i * GET_MODE_SIZE (V2SFmode)); 8617 else 8618 y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8); 8619 8620 emit_insn (gen_movv2sf_i (x, y)); 8621 } 8622 8623 DONE; 8624} 8625 [(set_attr "length" "8")]) 8626 8627(define_expand "movv4sf" 8628 [(set (match_operand:V4SF 0 "nonimmediate_operand" "") 8629 (match_operand:V4SF 1 "general_operand" ""))] 8630 "TARGET_SHMEDIA_FPU" 8631{ 8632 prepare_move_operands (operands, V4SFmode); 8633}) 8634 8635(define_insn_and_split "*movv16sf_i" 8636 [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m") 8637 (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))] 8638 "TARGET_SHMEDIA_FPU" 8639 "#" 8640 "&& reload_completed" 8641 [(const_int 0)] 8642{ 8643 for (int i = 0; i < 16/2; i++) 8644 { 8645 rtx x, y; 8646 8647 if (MEM_P (operands[0])) 8648 x = adjust_address (operands[0], V2SFmode, 8649 i * GET_MODE_SIZE (V2SFmode)); 8650 else 8651 { 8652 x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8); 8653 alter_subreg (&x, true); 8654 } 8655 8656 if (MEM_P (operands[1])) 8657 y = adjust_address (operands[1], V2SFmode, 8658 i * GET_MODE_SIZE (V2SFmode)); 8659 else 8660 { 8661 y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8); 8662 alter_subreg (&y, true); 8663 } 8664 8665 emit_insn (gen_movv2sf_i (x, y)); 8666 } 8667 8668 DONE; 8669} 8670 [(set_attr "length" "32")]) 8671 8672(define_expand "movv16sf" 8673 [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m") 8674 (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))] 8675 "TARGET_SHMEDIA_FPU" 8676{ 8677 prepare_move_operands (operands, V16SFmode); 8678}) 8679 8680(define_insn "movsf_media" 8681 [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m") 8682 (match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))] 8683 "TARGET_SHMEDIA_FPU 8684 && (register_operand (operands[0], SFmode) 8685 || sh_register_operand (operands[1], SFmode))" 8686 "@ 8687 fmov.s %1, %0 8688 fmov.ls %N1, %0 8689 fmov.sl %1, %0 8690 add.l %1, r63, %0 8691 # 8692 fld%M1.s %m1, %0 8693 fst%M0.s %m0, %1 8694 ld%M1.l %m1, %0 8695 st%M0.l %m0, %N1" 8696 [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media") 8697 (set (attr "highpart") 8698 (cond [(match_test "sh_contains_memref_p (insn)") 8699 (const_string "user")] 8700 (const_string "ignore")))]) 8701 8702(define_insn "movsf_media_nofpu" 8703 [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m") 8704 (match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))] 8705 "TARGET_SHMEDIA 8706 && (register_operand (operands[0], SFmode) 8707 || sh_register_operand (operands[1], SFmode))" 8708 "@ 8709 add.l %1, r63, %0 8710 # 8711 ld%M1.l %m1, %0 8712 st%M0.l %m0, %N1" 8713 [(set_attr "type" "arith_media,*,load_media,store_media") 8714 (set (attr "highpart") 8715 (cond [(match_test "sh_contains_memref_p (insn)") 8716 (const_string "user")] 8717 (const_string "ignore")))]) 8718 8719(define_split 8720 [(set (match_operand:SF 0 "arith_reg_dest" "") 8721 (match_operand:SF 1 "immediate_operand" ""))] 8722 "TARGET_SHMEDIA && reload_completed 8723 && ! FP_REGISTER_P (true_regnum (operands[0]))" 8724 [(set (match_dup 3) (match_dup 2))] 8725{ 8726 long values; 8727 REAL_VALUE_TYPE value; 8728 8729 REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]); 8730 REAL_VALUE_TO_TARGET_SINGLE (value, values); 8731 operands[2] = GEN_INT (values); 8732 8733 operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0])); 8734}) 8735 8736(define_insn "movsf_i" 8737 [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r") 8738 (match_operand:SF 1 "general_movsrc_operand" "r,G,FQ,mr,r,r,l"))] 8739 "TARGET_SH1 8740 && (! TARGET_SH2E 8741 /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */ 8742 || (REG_P (operands[0]) && REGNO (operands[0]) == 3) 8743 || (REG_P (operands[1]) && REGNO (operands[1]) == 3)) 8744 && (arith_reg_operand (operands[0], SFmode) 8745 || arith_reg_operand (operands[1], SFmode))" 8746 "@ 8747 mov %1,%0 8748 mov #0,%0 8749 mov.l %1,%0 8750 mov.l %1,%0 8751 mov.l %1,%0 8752 lds %1,%0 8753 sts %1,%0" 8754 [(set_attr "type" "move,move,pcload,load,store,move,move")]) 8755 8756;; We may not split the ry/yr/XX alternatives to movsi_ie, since 8757;; update_flow_info would not know where to put REG_EQUAL notes 8758;; when the destination changes mode. 8759(define_insn "movsf_ie" 8760 [(set (match_operand:SF 0 "general_movdst_operand" 8761 "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y") 8762 (match_operand:SF 1 "general_movsrc_operand" 8763 "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y")) 8764 (use (reg:SI FPSCR_MODES_REG)) 8765 (clobber (match_scratch:SI 2 "=X,X,X,X,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))] 8766 "TARGET_SH2E 8767 && (arith_reg_operand (operands[0], SFmode) || fpul_operand (operands[0], SFmode) 8768 || arith_reg_operand (operands[1], SFmode) || fpul_operand (operands[1], SFmode) 8769 || arith_reg_operand (operands[2], SImode))" 8770 "@ 8771 fmov %1,%0 8772 mov %1,%0 8773 fldi0 %0 8774 fldi1 %0 8775 # 8776 fmov.s %1,%0 8777 fmov.s %1,%0 8778 mov.l %1,%0 8779 mov.l %1,%0 8780 mov.l %1,%0 8781 fsts fpul,%0 8782 flds %1,fpul 8783 lds.l %1,%0 8784 # 8785 sts %1,%0 8786 lds %1,%0 8787 sts.l %1,%0 8788 lds.l %1,%0 8789 ! move optimized away" 8790 [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load, 8791 store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil") 8792 (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*") 8793 (set_attr_alternative "length" 8794 [(const_int 2) 8795 (const_int 2) 8796 (const_int 2) 8797 (const_int 2) 8798 (const_int 4) 8799 (if_then_else 8800 (match_test "TARGET_SH2A") 8801 (const_int 4) (const_int 2)) 8802 (if_then_else 8803 (match_test "TARGET_SH2A") 8804 (const_int 4) (const_int 2)) 8805 (const_int 2) 8806 (if_then_else 8807 (match_test "TARGET_SH2A") 8808 (const_int 4) (const_int 2)) 8809 (if_then_else 8810 (match_test "TARGET_SH2A") 8811 (const_int 4) (const_int 2)) 8812 (const_int 2) 8813 (const_int 2) 8814 (const_int 2) 8815 (const_int 4) 8816 (const_int 2) 8817 (const_int 2) 8818 (const_int 2) 8819 (const_int 2) 8820 (const_int 0)]) 8821 (set_attr_alternative "fp_mode" 8822 [(if_then_else (eq_attr "fmovd" "yes") 8823 (const_string "single") (const_string "none")) 8824 (const_string "none") 8825 (const_string "single") 8826 (const_string "single") 8827 (const_string "none") 8828 (if_then_else (eq_attr "fmovd" "yes") 8829 (const_string "single") (const_string "none")) 8830 (if_then_else (eq_attr "fmovd" "yes") 8831 (const_string "single") (const_string "none")) 8832 (const_string "none") 8833 (const_string "none") 8834 (const_string "none") 8835 (const_string "none") 8836 (const_string "none") 8837 (const_string "none") 8838 (const_string "none") 8839 (const_string "none") 8840 (const_string "none") 8841 (const_string "none") 8842 (const_string "none") 8843 (const_string "none")])]) 8844 8845(define_insn_and_split "movsf_ie_ra" 8846 [(set (match_operand:SF 0 "general_movdst_operand" 8847 "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y") 8848 (match_operand:SF 1 "general_movsrc_operand" 8849 "f,r,G,H,FQ,m,f,FQ,m,r,y,f,>,fr,y,r,y,>,y")) 8850 (use (reg:SI FPSCR_MODES_REG)) 8851 (clobber (match_scratch:SF 2 "=r,r,X,X,&z,r,r,X,r,r,r,r,r,y,r,r,r,r,r")) 8852 (const_int 0)] 8853 "TARGET_SH2E 8854 && (arith_reg_operand (operands[0], SFmode) 8855 || fpul_operand (operands[0], SFmode) 8856 || arith_reg_operand (operands[1], SFmode) 8857 || fpul_operand (operands[1], SFmode))" 8858 "@ 8859 fmov %1,%0 8860 mov %1,%0 8861 fldi0 %0 8862 fldi1 %0 8863 # 8864 fmov.s %1,%0 8865 fmov.s %1,%0 8866 mov.l %1,%0 8867 mov.l %1,%0 8868 mov.l %1,%0 8869 fsts fpul,%0 8870 flds %1,fpul 8871 lds.l %1,%0 8872 # 8873 sts %1,%0 8874 lds %1,%0 8875 sts.l %1,%0 8876 lds.l %1,%0 8877 ! move optimized away" 8878 "reload_completed 8879 && sh_movsf_ie_ra_split_p (operands[0], operands[1], operands[2])" 8880 [(const_int 0)] 8881{ 8882 if (! rtx_equal_p (operands[0], operands[1])) 8883 { 8884 emit_insn (gen_movsf_ie (operands[2], operands[1])); 8885 emit_insn (gen_movsf_ie (operands[0], operands[2])); 8886 } 8887} 8888 [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load, 8889 store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil") 8890 (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*") 8891 (set_attr_alternative "length" 8892 [(const_int 2) 8893 (const_int 2) 8894 (const_int 2) 8895 (const_int 2) 8896 (const_int 4) 8897 (if_then_else 8898 (match_test "TARGET_SH2A") 8899 (const_int 4) (const_int 2)) 8900 (if_then_else 8901 (match_test "TARGET_SH2A") 8902 (const_int 4) (const_int 2)) 8903 (const_int 2) 8904 (if_then_else 8905 (match_test "TARGET_SH2A") 8906 (const_int 4) (const_int 2)) 8907 (if_then_else 8908 (match_test "TARGET_SH2A") 8909 (const_int 4) (const_int 2)) 8910 (const_int 2) 8911 (const_int 2) 8912 (const_int 2) 8913 (const_int 4) 8914 (const_int 2) 8915 (const_int 2) 8916 (const_int 2) 8917 (const_int 2) 8918 (const_int 0)]) 8919 (set_attr_alternative "fp_mode" 8920 [(if_then_else (eq_attr "fmovd" "yes") 8921 (const_string "single") (const_string "none")) 8922 (const_string "none") 8923 (const_string "single") 8924 (const_string "single") 8925 (const_string "none") 8926 (if_then_else (eq_attr "fmovd" "yes") 8927 (const_string "single") (const_string "none")) 8928 (if_then_else (eq_attr "fmovd" "yes") 8929 (const_string "single") (const_string "none")) 8930 (const_string "none") 8931 (const_string "none") 8932 (const_string "none") 8933 (const_string "none") 8934 (const_string "none") 8935 (const_string "none") 8936 (const_string "none") 8937 (const_string "none") 8938 (const_string "none") 8939 (const_string "none") 8940 (const_string "none") 8941 (const_string "none")])]) 8942 8943(define_split 8944 [(set (match_operand:SF 0 "register_operand" "") 8945 (match_operand:SF 1 "register_operand" "")) 8946 (use (reg:SI FPSCR_MODES_REG)) 8947 (clobber (reg:SI FPUL_REG))] 8948 "TARGET_SH1" 8949 [(parallel [(set (reg:SF FPUL_REG) (match_dup 1)) 8950 (use (reg:SI FPSCR_MODES_REG)) 8951 (clobber (scratch:SI))]) 8952 (parallel [(set (match_dup 0) (reg:SF FPUL_REG)) 8953 (use (reg:SI FPSCR_MODES_REG)) 8954 (clobber (scratch:SI))])] 8955 "") 8956 8957(define_expand "movsf" 8958 [(set (match_operand:SF 0 "general_movdst_operand" "") 8959 (match_operand:SF 1 "general_movsrc_operand" ""))] 8960 "" 8961{ 8962 prepare_move_operands (operands, SFmode); 8963 if (TARGET_SHMEDIA) 8964 { 8965 if (TARGET_SHMEDIA_FPU) 8966 emit_insn (gen_movsf_media (operands[0], operands[1])); 8967 else 8968 emit_insn (gen_movsf_media_nofpu (operands[0], operands[1])); 8969 DONE; 8970 } 8971 if (TARGET_SH2E) 8972 { 8973 if (lra_in_progress) 8974 { 8975 if (GET_CODE (operands[0]) == SCRATCH) 8976 DONE; 8977 emit_insn (gen_movsf_ie_ra (operands[0], operands[1])); 8978 DONE; 8979 } 8980 8981 emit_insn (gen_movsf_ie (operands[0], operands[1])); 8982 DONE; 8983 } 8984}) 8985 8986(define_insn "mov_nop" 8987 [(set (match_operand 0 "any_register_operand" "") (match_dup 0))] 8988 "TARGET_SH2E" 8989 "" 8990 [(set_attr "length" "0") 8991 (set_attr "type" "nil")]) 8992 8993(define_expand "reload_insf__frn" 8994 [(parallel [(set (match_operand:SF 0 "register_operand" "=a") 8995 (match_operand:SF 1 "immediate_operand" "FQ")) 8996 (use (reg:SI FPSCR_MODES_REG)) 8997 (clobber (match_operand:SI 2 "register_operand" "=&z"))])] 8998 "TARGET_SH1" 8999 "") 9000 9001(define_expand "reload_insi__i_fpul" 9002 [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y") 9003 (match_operand:SI 1 "immediate_operand" "i")) 9004 (clobber (match_operand:SI 2 "register_operand" "=&z"))])] 9005 "TARGET_SH1" 9006 "") 9007 9008(define_expand "ptabs" 9009 [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))] 9010 "TARGET_SHMEDIA" 9011{ 9012 if (!TARGET_PT_FIXED) 9013 { 9014 rtx eq = operands[1]; 9015 9016 /* ??? For canonical RTL we really should remove any CONST from EQ 9017 before wrapping it in the AND, and finally wrap the EQ into a 9018 const if is constant. However, for reload we must expose the 9019 input register or symbolic constant, and we can't have 9020 different insn structures outside of the operands for different 9021 alternatives of the same pattern. */ 9022 eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)), 9023 GEN_INT (3)); 9024 operands[1] 9025 = (gen_rtx_IF_THEN_ELSE 9026 (PDImode, 9027 eq, 9028 gen_rtx_MEM (PDImode, operands[1]), 9029 gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE, 9030 PDImode, operands[1]))); 9031 } 9032}) 9033 9034;; expanded by ptabs expander. 9035(define_insn "*extendsipdi_media" 9036 [(set (match_operand:PDI 0 "target_reg_operand" "=b,b"); 9037 (if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand" 9038 "r,Csy") 9039 (const_int 3)) 9040 (const_int 3)) 9041 (mem:PDI (match_dup 1)) 9042 (sign_extend:PDI (match_dup 1))))] 9043 "TARGET_SHMEDIA && !TARGET_PT_FIXED" 9044 "@ 9045 ptabs %1, %0 9046 pt %1, %0" 9047 [(set_attr "type" "ptabs_media,pt_media") 9048 (set_attr "length" "4,*")]) 9049 9050(define_insn "*truncdipdi_media" 9051 [(set (match_operand:PDI 0 "target_reg_operand" "=b,b"); 9052 (if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand" 9053 "r,Csy") 9054 (const_int 3)) 9055 (const_int 3)) 9056 (mem:PDI (match_dup 1)) 9057 (truncate:PDI (match_dup 1))))] 9058 "TARGET_SHMEDIA && !TARGET_PT_FIXED" 9059 "@ 9060 ptabs %1, %0 9061 pt %1, %0" 9062 [(set_attr "type" "ptabs_media,pt_media") 9063 (set_attr "length" "4,*")]) 9064 9065(define_insn "*movsi_y" 9066 [(set (match_operand:SI 0 "register_operand" "=y,y") 9067 (match_operand:SI 1 "immediate_operand" "Qi,I08")) 9068 (clobber (match_scratch:SI 2 "=&z,r"))] 9069 "TARGET_SH2E 9070 && (reload_in_progress || reload_completed)" 9071 "#" 9072 [(set_attr "length" "4") 9073 (set_attr "type" "pcload,move")]) 9074 9075(define_split 9076 [(set (match_operand:SI 0 "register_operand" "") 9077 (match_operand:SI 1 "immediate_operand" "")) 9078 (clobber (match_operand:SI 2 "register_operand" ""))] 9079 "TARGET_SH1" 9080 [(set (match_dup 2) (match_dup 1)) 9081 (set (match_dup 0) (match_dup 2))] 9082 "") 9083 9084;; ------------------------------------------------------------------------ 9085;; Define the real conditional branch instructions. 9086;; ------------------------------------------------------------------------ 9087 9088(define_expand "branch_true" 9089 [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0)) 9090 (label_ref (match_operand 0)) 9091 (pc)))] 9092 "TARGET_SH1") 9093 9094(define_expand "branch_false" 9095 [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 9096 (label_ref (match_operand 0)) 9097 (pc)))] 9098 "TARGET_SH1") 9099 9100(define_insn_and_split "*cbranch_t" 9101 [(set (pc) (if_then_else (match_operand 1 "cbranch_treg_value") 9102 (label_ref (match_operand 0)) 9103 (pc)))] 9104 "TARGET_SH1" 9105{ 9106 return output_branch (sh_eval_treg_value (operands[1]), insn, operands); 9107} 9108 "&& 1" 9109 [(const_int 0)] 9110{ 9111 /* Try to canonicalize the branch condition if it is not one of: 9112 (ne (reg:SI T_REG) (const_int 0)) 9113 (eq (reg:SI T_REG) (const_int 0)) 9114 9115 Instead of splitting out a new insn, we modify the current insn's 9116 operands as needed. This preserves things such as REG_DEAD notes. */ 9117 9118 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE) 9119 && REG_P (XEXP (operands[1], 0)) && REGNO (XEXP (operands[1], 0)) == T_REG 9120 && XEXP (operands[1], 1) == const0_rtx) 9121 DONE; 9122 9123 int branch_cond = sh_eval_treg_value (operands[1]); 9124 rtx new_cond_rtx = NULL_RTX; 9125 9126 if (branch_cond == 0) 9127 new_cond_rtx = gen_rtx_EQ (VOIDmode, get_t_reg_rtx (), const0_rtx); 9128 else if (branch_cond == 1) 9129 new_cond_rtx = gen_rtx_NE (VOIDmode, get_t_reg_rtx (), const0_rtx); 9130 9131 if (new_cond_rtx != NULL_RTX) 9132 validate_change (curr_insn, &XEXP (XEXP (PATTERN (curr_insn), 1), 0), 9133 new_cond_rtx, false); 9134 DONE; 9135} 9136 [(set_attr "type" "cbranch")]) 9137 9138;; Patterns to prevent reorg from re-combining a condbranch with a branch 9139;; which destination is too far away. 9140;; The const_int_operand is distinct for each branch target; it avoids 9141;; unwanted matches with redundant_insn. 9142(define_insn "block_branch_redirect" 9143 [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))] 9144 "TARGET_SH1" 9145 "" 9146 [(set_attr "length" "0")]) 9147 9148;; This one has the additional purpose to record a possible scratch register 9149;; for the following branch. 9150;; ??? Unfortunately, just setting the scratch register is not good enough, 9151;; because the insn then might be deemed dead and deleted. And we can't 9152;; make the use in the jump insn explicit because that would disable 9153;; delay slot scheduling from the target. 9154(define_insn "indirect_jump_scratch" 9155 [(set (match_operand:SI 0 "register_operand" "=r") 9156 (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR)) 9157 (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))] 9158 "TARGET_SH1" 9159 "" 9160 [(set_attr "length" "0")]) 9161 9162;; This one is used to preemt an insn from beyond the bra / braf / jmp 9163;; being pulled into the delay slot of a condbranch that has been made to 9164;; jump around the unconditional jump because it was out of range. 9165(define_insn "stuff_delay_slot" 9166 [(set (pc) 9167 (unspec [(match_operand:SI 0 "const_int_operand" "") (pc) 9168 (match_operand:SI 1 "const_int_operand" "")] UNSPEC_BBR))] 9169 "TARGET_SH1" 9170 "" 9171 [(set_attr "length" "0") 9172 (set_attr "cond_delay_slot" "yes")]) 9173 9174;; Conditional branch insns 9175 9176(define_expand "cbranchint4_media" 9177 [(set (pc) 9178 (if_then_else (match_operator 0 "shmedia_cbranch_comparison_operator" 9179 [(match_operand 1 "" "") 9180 (match_operand 2 "" "")]) 9181 (match_operand 3 "" "") 9182 (pc)))] 9183 "TARGET_SHMEDIA" 9184{ 9185 machine_mode mode = GET_MODE (operands[1]); 9186 if (mode == VOIDmode) 9187 mode = GET_MODE (operands[2]); 9188 if (GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE) 9189 { 9190 operands[1] = force_reg (mode, operands[1]); 9191 if (CONSTANT_P (operands[2]) 9192 && (! satisfies_constraint_I06 (operands[2]))) 9193 operands[2] = force_reg (mode, operands[2]); 9194 } 9195 else 9196 { 9197 if (operands[1] != const0_rtx) 9198 operands[1] = force_reg (mode, operands[1]); 9199 if (operands[2] != const0_rtx) 9200 operands[2] = force_reg (mode, operands[2]); 9201 } 9202 switch (GET_CODE (operands[0])) 9203 { 9204 case LEU: 9205 case LE: 9206 case LTU: 9207 case LT: 9208 operands[0] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[0])), 9209 VOIDmode, operands[2], operands[1]); 9210 operands[1] = XEXP (operands[0], 0); 9211 operands[2] = XEXP (operands[0], 1); 9212 break; 9213 default: 9214 operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]), 9215 VOIDmode, operands[1], operands[2]); 9216 break; 9217 } 9218 operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]); 9219}) 9220 9221(define_expand "cbranchfp4_media" 9222 [(set (pc) 9223 (if_then_else (match_operator 0 "sh_float_comparison_operator" 9224 [(match_operand 1 "" "") 9225 (match_operand 2 "" "")]) 9226 (match_operand 3 "" "") 9227 (pc)))] 9228 "TARGET_SHMEDIA" 9229{ 9230 rtx tmp = gen_reg_rtx (SImode); 9231 rtx cmp; 9232 if (GET_CODE (operands[0]) == NE) 9233 cmp = gen_rtx_EQ (SImode, operands[1], operands[2]); 9234 else 9235 cmp = gen_rtx_fmt_ee (GET_CODE (operands[0]), SImode, 9236 operands[1], operands[2]); 9237 9238 emit_insn (gen_cstore4_media (tmp, cmp, operands[1], operands[2])); 9239 9240 if (GET_CODE (cmp) == GET_CODE (operands[0])) 9241 operands[0] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); 9242 else 9243 operands[0] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); 9244 operands[1] = tmp; 9245 operands[2] = const0_rtx; 9246 operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]); 9247}) 9248 9249(define_insn "*beq_media_i" 9250 [(set (pc) 9251 (if_then_else (match_operator 3 "equality_comparison_operator" 9252 [(match_operand:DI 1 "arith_reg_operand" "r,r") 9253 (match_operand:DI 2 "arith_operand" "r,I06")]) 9254 (match_operand 0 "target_operand" "b,b") 9255 (pc)))] 9256 "TARGET_SHMEDIA" 9257 "@ 9258 b%o3%' %1, %2, %0%> 9259 b%o3i%' %1, %2, %0%>" 9260 [(set_attr "type" "cbranch_media")]) 9261 9262(define_insn "*beq_media_i32" 9263 [(set (pc) 9264 (if_then_else (match_operator 3 "equality_comparison_operator" 9265 [(match_operand:SI 1 "arith_reg_operand" "r,r") 9266 (match_operand:SI 2 "arith_operand" "r,I06")]) 9267 (match_operand 0 "target_operand" "b,b") 9268 (pc)))] 9269 "TARGET_SHMEDIA" 9270 "@ 9271 b%o3%' %1, %2, %0%> 9272 b%o3i%' %1, %2, %0%>" 9273 [(set_attr "type" "cbranch_media")]) 9274 9275(define_insn "*bgt_media_i" 9276 [(set (pc) 9277 (if_then_else (match_operator 3 "greater_comparison_operator" 9278 [(match_operand:DI 1 "arith_reg_or_0_operand" "rN") 9279 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")]) 9280 (match_operand 0 "target_operand" "b") 9281 (pc)))] 9282 "TARGET_SHMEDIA" 9283 "b%o3%' %N1, %N2, %0%>" 9284 [(set_attr "type" "cbranch_media")]) 9285 9286(define_insn "*bgt_media_i32" 9287 [(set (pc) 9288 (if_then_else (match_operator 3 "greater_comparison_operator" 9289 [(match_operand:SI 1 "arith_reg_or_0_operand" "rN") 9290 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")]) 9291 (match_operand 0 "target_operand" "b") 9292 (pc)))] 9293 "TARGET_SHMEDIA" 9294 "b%o3%' %N1, %N2, %0%>" 9295 [(set_attr "type" "cbranch_media")]) 9296 9297;; These are only needed to make invert_jump() happy - otherwise, jump 9298;; optimization will be silently disabled. 9299(define_insn "*blt_media_i" 9300 [(set (pc) 9301 (if_then_else (match_operator 3 "less_comparison_operator" 9302 [(match_operand:DI 1 "arith_reg_or_0_operand" "rN") 9303 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")]) 9304 (match_operand 0 "target_operand" "b") 9305 (pc)))] 9306 "TARGET_SHMEDIA" 9307 "b%o3%' %N2, %N1, %0%>" 9308 [(set_attr "type" "cbranch_media")]) 9309 9310(define_insn "*blt_media_i32" 9311 [(set (pc) 9312 (if_then_else (match_operator 3 "less_comparison_operator" 9313 [(match_operand:SI 1 "arith_reg_or_0_operand" "rN") 9314 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")]) 9315 (match_operand 0 "target_operand" "b") 9316 (pc)))] 9317 "TARGET_SHMEDIA" 9318 "b%o3%' %N2, %N1, %0%>" 9319 [(set_attr "type" "cbranch_media")]) 9320 9321;; combiner splitter for test-and-branch on single bit in register. This 9322;; is endian dependent because the non-paradoxical subreg looks different 9323;; on big endian. 9324(define_split 9325 [(set (pc) 9326 (if_then_else 9327 (match_operator 3 "equality_comparison_operator" 9328 [(subreg:SI 9329 (zero_extract:DI 9330 (subreg:DI (match_operand:SI 1 "extend_reg_operand" "") 0) 9331 (const_int 1) 9332 (match_operand 2 "const_int_operand" "")) 0) 9333 (const_int 0)]) 9334 (match_operand 0 "target_operand" "") 9335 (pc))) 9336 (clobber (match_operand:SI 4 "arith_reg_dest" ""))] 9337 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN" 9338 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5))) 9339 (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))] 9340{ 9341 operands[5] = GEN_INT (31 - INTVAL (operands[2])); 9342 operands[6] = (GET_CODE (operands[3]) == EQ 9343 ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx) 9344 : gen_rtx_GT (VOIDmode, const0_rtx, operands[4])); 9345}) 9346 9347; operand 0 is the loop count pseudo register 9348; operand 1 is the label to jump to at the top of the loop 9349(define_expand "doloop_end" 9350 [(parallel [(set (pc) 9351 (if_then_else (ne:SI (match_operand:SI 0 "" "") 9352 (const_int 1)) 9353 (label_ref (match_operand 1 "" "")) 9354 (pc))) 9355 (set (match_dup 0) 9356 (plus:SI (match_dup 0) (const_int -1))) 9357 (clobber (reg:SI T_REG))])] 9358 "TARGET_SH2" 9359{ 9360 if (GET_MODE (operands[0]) != SImode) 9361 FAIL; 9362 emit_jump_insn (gen_doloop_end_split (operands[0], operands[1], operands[0])); 9363 DONE; 9364}) 9365 9366(define_insn_and_split "doloop_end_split" 9367 [(set (pc) 9368 (if_then_else (ne:SI (match_operand:SI 2 "arith_reg_dest" "0") 9369 (const_int 1)) 9370 (label_ref (match_operand 1 "" "")) 9371 (pc))) 9372 (set (match_operand:SI 0 "arith_reg_dest" "=r") 9373 (plus:SI (match_dup 2) (const_int -1))) 9374 (clobber (reg:SI T_REG))] 9375 "TARGET_SH2" 9376 "#" 9377 "" 9378 [(parallel [(set (reg:SI T_REG) 9379 (eq:SI (match_dup 2) (const_int 1))) 9380 (set (match_dup 0) (plus:SI (match_dup 2) (const_int -1)))]) 9381 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) 9382 (label_ref (match_dup 1)) 9383 (pc)))] 9384 "" 9385 [(set_attr "type" "cbranch")]) 9386 9387;; ------------------------------------------------------------------------ 9388;; Jump and linkage insns 9389;; ------------------------------------------------------------------------ 9390 9391(define_insn "jump_compact" 9392 [(set (pc) 9393 (label_ref (match_operand 0 "" "")))] 9394 "TARGET_SH1 && !CROSSING_JUMP_P (insn)" 9395{ 9396 /* The length is 16 if the delay slot is unfilled. */ 9397 if (get_attr_length(insn) > 4) 9398 return output_far_jump(insn, operands[0]); 9399 else 9400 return "bra %l0%#"; 9401} 9402 [(set_attr "type" "jump") 9403 (set_attr "needs_delay_slot" "yes")]) 9404 9405(define_insn "*jump_compact_crossing" 9406 [(set (pc) 9407 (label_ref (match_operand 0 "" "")))] 9408 "TARGET_SH1 9409 && flag_reorder_blocks_and_partition 9410 && CROSSING_JUMP_P (insn)" 9411{ 9412 /* The length is 16 if the delay slot is unfilled. */ 9413 return output_far_jump(insn, operands[0]); 9414} 9415 [(set_attr "type" "jump") 9416 (set_attr "length" "16")]) 9417 9418;; ??? It would be much saner to explicitly use the scratch register 9419;; in the jump insn, and have indirect_jump_scratch only set it, 9420;; but fill_simple_delay_slots would refuse to do delay slot filling 9421;; from the target then, as it uses simplejump_p. 9422;;(define_insn "jump_compact_far" 9423;; [(set (pc) 9424;; (label_ref (match_operand 0 "" ""))) 9425;; (use (match_operand 1 "register_operand" "r")] 9426;; "TARGET_SH1" 9427;; "* return output_far_jump(insn, operands[0], operands[1]);" 9428;; [(set_attr "type" "jump") 9429;; (set_attr "needs_delay_slot" "yes")]) 9430 9431(define_insn "jump_media" 9432 [(set (pc) 9433 (match_operand 0 "target_operand" "b"))] 9434 "TARGET_SHMEDIA" 9435 "blink %0, r63%>" 9436 [(set_attr "type" "jump_media")]) 9437 9438(define_expand "jump" 9439 [(set (pc) 9440 (label_ref (match_operand 0 "" "")))] 9441 "" 9442{ 9443 if (TARGET_SH1) 9444 emit_jump_insn (gen_jump_compact (operands[0])); 9445 else if (TARGET_SHMEDIA) 9446 { 9447 if (reload_in_progress || reload_completed) 9448 FAIL; 9449 emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode, operands[0]))); 9450 } 9451 DONE; 9452}) 9453 9454(define_insn "force_mode_for_call" 9455 [(use (reg:SI FPSCR_MODES_REG))] 9456 "TARGET_SHCOMPACT" 9457 "" 9458 [(set_attr "length" "0") 9459 (set (attr "fp_mode") 9460 (if_then_else (eq_attr "fpu_single" "yes") 9461 (const_string "single") (const_string "double")))]) 9462 9463(define_insn "calli" 9464 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) 9465 (match_operand 1 "" "")) 9466 (use (reg:SI FPSCR_MODES_REG)) 9467 (clobber (reg:SI PR_REG))] 9468 "TARGET_SH1" 9469{ 9470 if (TARGET_SH2A && (dbr_sequence_length () == 0)) 9471 return "jsr/n @%0"; 9472 else 9473 return "jsr @%0%#"; 9474} 9475 [(set_attr "type" "call") 9476 (set (attr "fp_mode") 9477 (if_then_else (eq_attr "fpu_single" "yes") 9478 (const_string "single") (const_string "double"))) 9479 (set_attr "needs_delay_slot" "yes") 9480 (set_attr "fp_set" "unknown")]) 9481 9482;; This is TBR relative jump instruction for SH2A architecture. 9483;; Its use is enabled by assigning an attribute "function_vector" 9484;; and the vector number to a function during its declaration. 9485(define_insn "calli_tbr_rel" 9486 [(call (mem (match_operand:SI 0 "symbol_ref_operand" "")) 9487 (match_operand 1 "" "")) 9488 (use (reg:SI FPSCR_MODES_REG)) 9489 (clobber (reg:SI PR_REG))] 9490 "TARGET_SH2A && sh2a_is_function_vector_call (operands[0])" 9491{ 9492 unsigned HOST_WIDE_INT vect_num; 9493 vect_num = sh2a_get_function_vector_number (operands[0]); 9494 operands[2] = GEN_INT (vect_num * 4); 9495 9496 return "jsr/n @@(%O2,tbr)"; 9497} 9498 [(set_attr "type" "call") 9499 (set (attr "fp_mode") 9500 (if_then_else (eq_attr "fpu_single" "yes") 9501 (const_string "single") (const_string "double"))) 9502 (set_attr "needs_delay_slot" "no") 9503 (set_attr "fp_set" "unknown")]) 9504 9505;; This is a pc-rel call, using bsrf, for use with PIC. 9506(define_insn "calli_pcrel" 9507 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) 9508 (match_operand 1 "" "")) 9509 (use (reg:SI FPSCR_MODES_REG)) 9510 (use (reg:SI PIC_REG)) 9511 (use (match_operand 2 "" "")) 9512 (clobber (reg:SI PR_REG))] 9513 "TARGET_SH2" 9514{ 9515 return "bsrf %0" "\n" 9516 "%O2:%#"; 9517} 9518 [(set_attr "type" "call") 9519 (set (attr "fp_mode") 9520 (if_then_else (eq_attr "fpu_single" "yes") 9521 (const_string "single") (const_string "double"))) 9522 (set_attr "needs_delay_slot" "yes") 9523 (set_attr "fp_set" "unknown")]) 9524 9525(define_insn_and_split "call_pcrel" 9526 [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "")) 9527 (match_operand 1 "" "")) 9528 (use (reg:SI FPSCR_MODES_REG)) 9529 (use (reg:SI PIC_REG)) 9530 (clobber (reg:SI PR_REG)) 9531 (clobber (match_scratch:SI 2 "=&r"))] 9532 "TARGET_SH2" 9533 "#" 9534 "reload_completed" 9535 [(const_int 0)] 9536{ 9537 rtx lab = PATTERN (gen_call_site ()); 9538 9539 if (SYMBOL_REF_LOCAL_P (operands[0])) 9540 emit_insn (gen_sym_label2reg (operands[2], operands[0], lab)); 9541 else 9542 emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab)); 9543 emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab))); 9544 DONE; 9545} 9546 [(set_attr "type" "call") 9547 (set (attr "fp_mode") 9548 (if_then_else (eq_attr "fpu_single" "yes") 9549 (const_string "single") (const_string "double"))) 9550 (set_attr "needs_delay_slot" "yes") 9551 (set_attr "fp_set" "unknown")]) 9552 9553(define_insn "call_compact" 9554 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) 9555 (match_operand 1 "" "")) 9556 (match_operand 2 "immediate_operand" "n") 9557 (use (reg:SI R0_REG)) 9558 (use (reg:SI R1_REG)) 9559 (use (reg:SI FPSCR_MODES_REG)) 9560 (clobber (reg:SI PR_REG))] 9561 "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))" 9562 "jsr @%0%#" 9563 [(set_attr "type" "call") 9564 (set (attr "fp_mode") 9565 (if_then_else (eq_attr "fpu_single" "yes") 9566 (const_string "single") (const_string "double"))) 9567 (set_attr "needs_delay_slot" "yes")]) 9568 9569(define_insn "call_compact_rettramp" 9570 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) 9571 (match_operand 1 "" "")) 9572 (match_operand 2 "immediate_operand" "n") 9573 (use (reg:SI R0_REG)) 9574 (use (reg:SI R1_REG)) 9575 (use (reg:SI FPSCR_MODES_REG)) 9576 (clobber (reg:SI R10_REG)) 9577 (clobber (reg:SI PR_REG))] 9578 "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))" 9579 "jsr @%0%#" 9580 [(set_attr "type" "call") 9581 (set (attr "fp_mode") 9582 (if_then_else (eq_attr "fpu_single" "yes") 9583 (const_string "single") (const_string "double"))) 9584 (set_attr "needs_delay_slot" "yes")]) 9585 9586(define_insn "call_media" 9587 [(call (mem:DI (match_operand 0 "target_reg_operand" "b")) 9588 (match_operand 1 "" "")) 9589 (clobber (reg:DI PR_MEDIA_REG))] 9590 "TARGET_SHMEDIA" 9591 "blink %0, r18" 9592 [(set_attr "type" "jump_media")]) 9593 9594(define_insn "call_valuei" 9595 [(set (match_operand 0 "" "=rf") 9596 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) 9597 (match_operand 2 "" ""))) 9598 (use (reg:SI FPSCR_MODES_REG)) 9599 (clobber (reg:SI PR_REG))] 9600 "TARGET_SH1" 9601{ 9602 if (TARGET_SH2A && (dbr_sequence_length () == 0)) 9603 return "jsr/n @%1"; 9604 else 9605 return "jsr @%1%#"; 9606} 9607 [(set_attr "type" "call") 9608 (set (attr "fp_mode") 9609 (if_then_else (eq_attr "fpu_single" "yes") 9610 (const_string "single") (const_string "double"))) 9611 (set_attr "needs_delay_slot" "yes") 9612 (set_attr "fp_set" "unknown")]) 9613 9614;; This is TBR relative jump instruction for SH2A architecture. 9615;; Its use is enabled by assigning an attribute "function_vector" 9616;; and the vector number to a function during its declaration. 9617(define_insn "call_valuei_tbr_rel" 9618 [(set (match_operand 0 "" "=rf") 9619 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "")) 9620 (match_operand 2 "" ""))) 9621 (use (reg:SI FPSCR_MODES_REG)) 9622 (clobber (reg:SI PR_REG))] 9623 "TARGET_SH2A && sh2a_is_function_vector_call (operands[1])" 9624{ 9625 unsigned HOST_WIDE_INT vect_num; 9626 vect_num = sh2a_get_function_vector_number (operands[1]); 9627 operands[3] = GEN_INT (vect_num * 4); 9628 9629 return "jsr/n @@(%O3,tbr)"; 9630} 9631 [(set_attr "type" "call") 9632 (set (attr "fp_mode") 9633 (if_then_else (eq_attr "fpu_single" "yes") 9634 (const_string "single") (const_string "double"))) 9635 (set_attr "needs_delay_slot" "no") 9636 (set_attr "fp_set" "unknown")]) 9637 9638(define_insn "call_valuei_pcrel" 9639 [(set (match_operand 0 "" "=rf") 9640 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) 9641 (match_operand 2 "" ""))) 9642 (use (reg:SI FPSCR_MODES_REG)) 9643 (use (reg:SI PIC_REG)) 9644 (use (match_operand 3 "" "")) 9645 (clobber (reg:SI PR_REG))] 9646 "TARGET_SH2" 9647{ 9648 return "bsrf %1" "\n" 9649 "%O3:%#"; 9650} 9651 [(set_attr "type" "call") 9652 (set (attr "fp_mode") 9653 (if_then_else (eq_attr "fpu_single" "yes") 9654 (const_string "single") (const_string "double"))) 9655 (set_attr "needs_delay_slot" "yes") 9656 (set_attr "fp_set" "unknown")]) 9657 9658(define_insn_and_split "call_value_pcrel" 9659 [(set (match_operand 0 "" "=rf") 9660 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "")) 9661 (match_operand 2 "" ""))) 9662 (use (reg:SI FPSCR_MODES_REG)) 9663 (use (reg:SI PIC_REG)) 9664 (clobber (reg:SI PR_REG)) 9665 (clobber (match_scratch:SI 3 "=&r"))] 9666 "TARGET_SH2" 9667 "#" 9668 "reload_completed" 9669 [(const_int 0)] 9670{ 9671 rtx lab = PATTERN (gen_call_site ()); 9672 9673 if (SYMBOL_REF_LOCAL_P (operands[1])) 9674 emit_insn (gen_sym_label2reg (operands[3], operands[1], lab)); 9675 else 9676 emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab)); 9677 emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3], 9678 operands[2], copy_rtx (lab))); 9679 DONE; 9680} 9681 [(set_attr "type" "call") 9682 (set (attr "fp_mode") 9683 (if_then_else (eq_attr "fpu_single" "yes") 9684 (const_string "single") (const_string "double"))) 9685 (set_attr "needs_delay_slot" "yes") 9686 (set_attr "fp_set" "unknown")]) 9687 9688(define_insn "call_value_compact" 9689 [(set (match_operand 0 "" "=rf") 9690 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) 9691 (match_operand 2 "" ""))) 9692 (match_operand 3 "immediate_operand" "n") 9693 (use (reg:SI R0_REG)) 9694 (use (reg:SI R1_REG)) 9695 (use (reg:SI FPSCR_MODES_REG)) 9696 (clobber (reg:SI PR_REG))] 9697 "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))" 9698 "jsr @%1%#" 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 9705(define_insn "call_value_compact_rettramp" 9706 [(set (match_operand 0 "" "=rf") 9707 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) 9708 (match_operand 2 "" ""))) 9709 (match_operand 3 "immediate_operand" "n") 9710 (use (reg:SI R0_REG)) 9711 (use (reg:SI R1_REG)) 9712 (use (reg:SI FPSCR_MODES_REG)) 9713 (clobber (reg:SI R10_REG)) 9714 (clobber (reg:SI PR_REG))] 9715 "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))" 9716 "jsr @%1%#" 9717 [(set_attr "type" "call") 9718 (set (attr "fp_mode") 9719 (if_then_else (eq_attr "fpu_single" "yes") 9720 (const_string "single") (const_string "double"))) 9721 (set_attr "needs_delay_slot" "yes")]) 9722 9723(define_insn "call_value_media" 9724 [(set (match_operand 0 "" "=rf") 9725 (call (mem:DI (match_operand 1 "target_reg_operand" "b")) 9726 (match_operand 2 "" ""))) 9727 (clobber (reg:DI PR_MEDIA_REG))] 9728 "TARGET_SHMEDIA" 9729 "blink %1, r18" 9730 [(set_attr "type" "jump_media")]) 9731 9732(define_expand "call" 9733 [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" "")) 9734 (match_operand 1 "" "")) 9735 (match_operand 2 "" "") 9736 (use (reg:SI FPSCR_MODES_REG)) 9737 (clobber (reg:SI PR_REG))])] 9738 "" 9739{ 9740 if (TARGET_SHMEDIA) 9741 { 9742 operands[0] = shmedia_prepare_call_address (operands[0], 0); 9743 emit_call_insn (gen_call_media (operands[0], operands[1])); 9744 DONE; 9745 } 9746 else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2])) 9747 { 9748 rtx cookie_rtx = operands[2]; 9749 long cookie = INTVAL (cookie_rtx); 9750 rtx func = XEXP (operands[0], 0); 9751 rtx r0, r1; 9752 9753 if (flag_pic) 9754 { 9755 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func)) 9756 { 9757 rtx reg = gen_reg_rtx (Pmode); 9758 9759 emit_insn (gen_symGOTPLT2reg (reg, func)); 9760 func = reg; 9761 } 9762 else 9763 func = legitimize_pic_address (func, Pmode, 0); 9764 } 9765 9766 r0 = gen_rtx_REG (SImode, R0_REG); 9767 r1 = gen_rtx_REG (SImode, R1_REG); 9768 9769 /* Since such a call function may use all call-clobbered 9770 registers, we force a mode switch earlier, so that we don't 9771 run out of registers when adjusting fpscr for the call. */ 9772 emit_insn (gen_force_mode_for_call ()); 9773 9774 operands[0] 9775 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT); 9776 operands[0] = force_reg (SImode, operands[0]); 9777 9778 emit_move_insn (r0, func); 9779 emit_move_insn (r1, cookie_rtx); 9780 9781 if (cookie & CALL_COOKIE_RET_TRAMP (1)) 9782 emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1], 9783 operands[2])); 9784 else 9785 emit_call_insn (gen_call_compact (operands[0], operands[1], 9786 operands[2])); 9787 9788 DONE; 9789 } 9790 else if (TARGET_SHCOMPACT && flag_pic 9791 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF 9792 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0))) 9793 { 9794 rtx reg = gen_reg_rtx (Pmode); 9795 9796 emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0))); 9797 XEXP (operands[0], 0) = reg; 9798 } 9799 if (!flag_pic && TARGET_SH2A 9800 && MEM_P (operands[0]) 9801 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF) 9802 { 9803 if (sh2a_is_function_vector_call (XEXP (operands[0], 0))) 9804 { 9805 emit_call_insn (gen_calli_tbr_rel (XEXP (operands[0], 0), 9806 operands[1])); 9807 DONE; 9808 } 9809 } 9810 if (flag_pic && TARGET_SH2 9811 && MEM_P (operands[0]) 9812 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF) 9813 { 9814 emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1])); 9815 DONE; 9816 } 9817 else 9818 { 9819 operands[0] = force_reg (SImode, XEXP (operands[0], 0)); 9820 operands[1] = operands[2]; 9821 } 9822 9823 emit_call_insn (gen_calli (operands[0], operands[1])); 9824 DONE; 9825}) 9826 9827(define_insn "call_pop_compact" 9828 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) 9829 (match_operand 1 "" "")) 9830 (match_operand 2 "immediate_operand" "n") 9831 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) 9832 (match_operand 3 "immediate_operand" "n"))) 9833 (use (reg:SI R0_REG)) 9834 (use (reg:SI R1_REG)) 9835 (use (reg:SI FPSCR_MODES_REG)) 9836 (clobber (reg:SI PR_REG))] 9837 "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))" 9838 "jsr @%0%#" 9839 [(set_attr "type" "call") 9840 (set (attr "fp_mode") 9841 (if_then_else (eq_attr "fpu_single" "yes") 9842 (const_string "single") (const_string "double"))) 9843 (set_attr "needs_delay_slot" "yes")]) 9844 9845(define_insn "call_pop_compact_rettramp" 9846 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) 9847 (match_operand 1 "" "")) 9848 (match_operand 2 "immediate_operand" "n") 9849 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) 9850 (match_operand 3 "immediate_operand" "n"))) 9851 (use (reg:SI R0_REG)) 9852 (use (reg:SI R1_REG)) 9853 (use (reg:SI FPSCR_MODES_REG)) 9854 (clobber (reg:SI R10_REG)) 9855 (clobber (reg:SI PR_REG))] 9856 "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))" 9857 "jsr @%0%#" 9858 [(set_attr "type" "call") 9859 (set (attr "fp_mode") 9860 (if_then_else (eq_attr "fpu_single" "yes") 9861 (const_string "single") (const_string "double"))) 9862 (set_attr "needs_delay_slot" "yes")]) 9863 9864(define_expand "call_pop" 9865 [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" "")) 9866 (match_operand 1 "" "")) 9867 (match_operand 2 "" "") 9868 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) 9869 (match_operand 3 "" "")))])] 9870 "TARGET_SHCOMPACT" 9871{ 9872 rtx cookie_rtx; 9873 long cookie; 9874 rtx func; 9875 rtx r0, r1; 9876 9877 gcc_assert (operands[2] && INTVAL (operands[2])); 9878 cookie_rtx = operands[2]; 9879 cookie = INTVAL (cookie_rtx); 9880 func = XEXP (operands[0], 0); 9881 9882 if (flag_pic) 9883 { 9884 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func)) 9885 { 9886 rtx reg = gen_reg_rtx (Pmode); 9887 emit_insn (gen_symGOTPLT2reg (reg, func)); 9888 func = reg; 9889 } 9890 else 9891 func = legitimize_pic_address (func, Pmode, 0); 9892 } 9893 9894 r0 = gen_rtx_REG (SImode, R0_REG); 9895 r1 = gen_rtx_REG (SImode, R1_REG); 9896 9897 /* Since such a call function may use all call-clobbered 9898 registers, we force a mode switch earlier, so that we don't 9899 run out of registers when adjusting fpscr for the call. */ 9900 emit_insn (gen_force_mode_for_call ()); 9901 9902 operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline", 9903 SFUNC_GOT); 9904 operands[0] = force_reg (SImode, operands[0]); 9905 9906 emit_move_insn (r0, func); 9907 emit_move_insn (r1, cookie_rtx); 9908 9909 if (cookie & CALL_COOKIE_RET_TRAMP (1)) 9910 emit_call_insn (gen_call_pop_compact_rettramp 9911 (operands[0], operands[1], operands[2], operands[3])); 9912 else 9913 emit_call_insn (gen_call_pop_compact 9914 (operands[0], operands[1], operands[2], operands[3])); 9915 9916 DONE; 9917}) 9918 9919(define_expand "call_value" 9920 [(parallel [(set (match_operand 0 "arith_reg_operand" "") 9921 (call (mem:SI (match_operand 1 "arith_reg_operand" "")) 9922 (match_operand 2 "" ""))) 9923 (match_operand 3 "" "") 9924 (use (reg:SI FPSCR_MODES_REG)) 9925 (clobber (reg:SI PR_REG))])] 9926 "" 9927{ 9928 if (TARGET_SHMEDIA) 9929 { 9930 operands[1] = shmedia_prepare_call_address (operands[1], 0); 9931 emit_call_insn (gen_call_value_media (operands[0], operands[1], 9932 operands[2])); 9933 DONE; 9934 } 9935 else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3])) 9936 { 9937 rtx cookie_rtx = operands[3]; 9938 long cookie = INTVAL (cookie_rtx); 9939 rtx func = XEXP (operands[1], 0); 9940 rtx r0, r1; 9941 9942 if (flag_pic) 9943 { 9944 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func)) 9945 { 9946 rtx reg = gen_reg_rtx (Pmode); 9947 9948 emit_insn (gen_symGOTPLT2reg (reg, func)); 9949 func = reg; 9950 } 9951 else 9952 func = legitimize_pic_address (func, Pmode, 0); 9953 } 9954 9955 r0 = gen_rtx_REG (SImode, R0_REG); 9956 r1 = gen_rtx_REG (SImode, R1_REG); 9957 9958 /* Since such a call function may use all call-clobbered 9959 registers, we force a mode switch earlier, so that we don't 9960 run out of registers when adjusting fpscr for the call. */ 9961 emit_insn (gen_force_mode_for_call ()); 9962 9963 operands[1] 9964 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT); 9965 operands[1] = force_reg (SImode, operands[1]); 9966 9967 emit_move_insn (r0, func); 9968 emit_move_insn (r1, cookie_rtx); 9969 9970 if (cookie & CALL_COOKIE_RET_TRAMP (1)) 9971 emit_call_insn (gen_call_value_compact_rettramp (operands[0], 9972 operands[1], 9973 operands[2], 9974 operands[3])); 9975 else 9976 emit_call_insn (gen_call_value_compact (operands[0], operands[1], 9977 operands[2], operands[3])); 9978 9979 DONE; 9980 } 9981 else if (TARGET_SHCOMPACT && flag_pic 9982 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF 9983 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0))) 9984 { 9985 rtx reg = gen_reg_rtx (Pmode); 9986 9987 emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0))); 9988 XEXP (operands[1], 0) = reg; 9989 } 9990 if (!flag_pic && TARGET_SH2A 9991 && MEM_P (operands[1]) 9992 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF) 9993 { 9994 if (sh2a_is_function_vector_call (XEXP (operands[1], 0))) 9995 { 9996 emit_call_insn (gen_call_valuei_tbr_rel (operands[0], 9997 XEXP (operands[1], 0), operands[2])); 9998 DONE; 9999 } 10000 } 10001 if (flag_pic && TARGET_SH2 10002 && MEM_P (operands[1]) 10003 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF) 10004 { 10005 emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0), 10006 operands[2])); 10007 DONE; 10008 } 10009 else 10010 operands[1] = force_reg (SImode, XEXP (operands[1], 0)); 10011 10012 emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2])); 10013 DONE; 10014}) 10015 10016(define_insn "sibcalli" 10017 [(call (mem:SI (match_operand:SI 0 "register_operand" "k")) 10018 (match_operand 1 "" "")) 10019 (use (reg:SI FPSCR_MODES_REG)) 10020 (return)] 10021 "TARGET_SH1" 10022 "jmp @%0%#" 10023 [(set_attr "needs_delay_slot" "yes") 10024 (set (attr "fp_mode") 10025 (if_then_else (eq_attr "fpu_single" "yes") 10026 (const_string "single") (const_string "double"))) 10027 (set_attr "type" "jump_ind")]) 10028 10029(define_insn "sibcalli_pcrel" 10030 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k")) 10031 (match_operand 1 "" "")) 10032 (use (match_operand 2 "" "")) 10033 (use (reg:SI FPSCR_MODES_REG)) 10034 (return)] 10035 "TARGET_SH2" 10036{ 10037 return "braf %0" "\n" 10038 "%O2:%#"; 10039} 10040 [(set_attr "needs_delay_slot" "yes") 10041 (set (attr "fp_mode") 10042 (if_then_else (eq_attr "fpu_single" "yes") 10043 (const_string "single") (const_string "double"))) 10044 (set_attr "type" "jump_ind")]) 10045 10046;; This uses an unspec to describe that the symbol_ref is very close. 10047(define_insn "sibcalli_thunk" 10048 [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")] 10049 UNSPEC_THUNK)) 10050 (match_operand 1 "" "")) 10051 (use (reg:SI FPSCR_MODES_REG)) 10052 (return)] 10053 "TARGET_SH1" 10054 "bra %O0" 10055 [(set_attr "needs_delay_slot" "yes") 10056 (set (attr "fp_mode") 10057 (if_then_else (eq_attr "fpu_single" "yes") 10058 (const_string "single") (const_string "double"))) 10059 (set_attr "type" "jump") 10060 (set_attr "length" "2")]) 10061 10062(define_insn_and_split "sibcall_pcrel" 10063 [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "")) 10064 (match_operand 1 "" "")) 10065 (use (reg:SI FPSCR_MODES_REG)) 10066 (clobber (match_scratch:SI 2 "=&k")) 10067 (return)] 10068 "TARGET_SH2" 10069 "#" 10070 "reload_completed" 10071 [(const_int 0)] 10072{ 10073 rtx lab = PATTERN (gen_call_site ()); 10074 rtx call_insn; 10075 10076 emit_insn (gen_sym_label2reg (operands[2], operands[0], lab)); 10077 call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1], 10078 copy_rtx (lab))); 10079 SIBLING_CALL_P (call_insn) = 1; 10080 DONE; 10081} 10082 [(set_attr "needs_delay_slot" "yes") 10083 (set (attr "fp_mode") 10084 (if_then_else (eq_attr "fpu_single" "yes") 10085 (const_string "single") (const_string "double"))) 10086 (set_attr "type" "jump_ind")]) 10087 10088(define_insn "sibcall_compact" 10089 [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k")) 10090 (match_operand 1 "" "")) 10091 (return) 10092 (use (match_operand:SI 2 "register_operand" "z,x")) 10093 (use (reg:SI R1_REG)) 10094 (use (reg:SI FPSCR_MODES_REG)) 10095 ;; We want to make sure the `x' above will only match MACH_REG 10096 ;; because sibcall_epilogue may clobber MACL_REG. 10097 (clobber (reg:SI MACL_REG))] 10098 "TARGET_SHCOMPACT" 10099{ 10100 static const char* alt[] = 10101 { 10102 "jmp @%0%#", 10103 10104 "jmp @%0" "\n" 10105 " sts %2,r0" 10106 }; 10107 return alt[which_alternative]; 10108} 10109 [(set_attr "needs_delay_slot" "yes,no") 10110 (set_attr "length" "2,4") 10111 (set (attr "fp_mode") (const_string "single")) 10112 (set_attr "type" "jump_ind")]) 10113 10114(define_insn "sibcall_media" 10115 [(call (mem:DI (match_operand 0 "target_reg_operand" "k")) 10116 (match_operand 1 "" "")) 10117 (use (reg:SI PR_MEDIA_REG)) 10118 (return)] 10119 "TARGET_SHMEDIA" 10120 "blink %0, r63" 10121 [(set_attr "type" "jump_media")]) 10122 10123(define_expand "sibcall" 10124 [(parallel 10125 [(call (mem:SI (match_operand 0 "arith_reg_operand" "")) 10126 (match_operand 1 "" "")) 10127 (match_operand 2 "" "") 10128 (use (reg:SI FPSCR_MODES_REG)) 10129 (return)])] 10130 "" 10131{ 10132 if (TARGET_SHMEDIA) 10133 { 10134 operands[0] = shmedia_prepare_call_address (operands[0], 1); 10135 emit_call_insn (gen_sibcall_media (operands[0], operands[1])); 10136 DONE; 10137 } 10138 else if (TARGET_SHCOMPACT && operands[2] 10139 && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1))) 10140 { 10141 rtx cookie_rtx = operands[2]; 10142 long cookie = INTVAL (cookie_rtx); 10143 rtx func = XEXP (operands[0], 0); 10144 rtx mach, r1; 10145 10146 if (flag_pic) 10147 { 10148 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func)) 10149 { 10150 rtx reg = gen_reg_rtx (Pmode); 10151 10152 emit_insn (gen_symGOT2reg (reg, func)); 10153 func = reg; 10154 } 10155 else 10156 func = legitimize_pic_address (func, Pmode, 0); 10157 } 10158 10159 /* FIXME: if we could tell whether all argument registers are 10160 already taken, we could decide whether to force the use of 10161 MACH_REG or to stick to R0_REG. Unfortunately, there's no 10162 simple way to tell. We could use the CALL_COOKIE, but we 10163 can't currently tell a register used for regular argument 10164 passing from one that is unused. If we leave it up to reload 10165 to decide which register to use, it seems to always choose 10166 R0_REG, which leaves no available registers in SIBCALL_REGS 10167 to hold the address of the trampoline. */ 10168 mach = gen_rtx_REG (SImode, MACH_REG); 10169 r1 = gen_rtx_REG (SImode, R1_REG); 10170 10171 /* Since such a call function may use all call-clobbered 10172 registers, we force a mode switch earlier, so that we don't 10173 run out of registers when adjusting fpscr for the call. */ 10174 emit_insn (gen_force_mode_for_call ()); 10175 10176 operands[0] 10177 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT); 10178 operands[0] = force_reg (SImode, operands[0]); 10179 10180 /* We don't need a return trampoline, since the callee will 10181 return directly to the upper caller. */ 10182 if (cookie & CALL_COOKIE_RET_TRAMP (1)) 10183 { 10184 cookie &= ~ CALL_COOKIE_RET_TRAMP (1); 10185 cookie_rtx = GEN_INT (cookie); 10186 } 10187 10188 emit_move_insn (mach, func); 10189 emit_move_insn (r1, cookie_rtx); 10190 10191 emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach)); 10192 DONE; 10193 } 10194 else if (TARGET_SHCOMPACT && flag_pic 10195 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF 10196 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0))) 10197 { 10198 rtx reg = gen_reg_rtx (Pmode); 10199 10200 emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0))); 10201 XEXP (operands[0], 0) = reg; 10202 } 10203 if (flag_pic && TARGET_SH2 10204 && MEM_P (operands[0]) 10205 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF 10206 /* The PLT needs the PIC register, but the epilogue would have 10207 to restore it, so we can only use PC-relative PIC calls for 10208 static functions. */ 10209 && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0))) 10210 { 10211 emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1])); 10212 DONE; 10213 } 10214 else 10215 operands[0] = force_reg (SImode, XEXP (operands[0], 0)); 10216 10217 emit_call_insn (gen_sibcalli (operands[0], operands[1])); 10218 DONE; 10219}) 10220 10221(define_insn "sibcall_valuei" 10222 [(set (match_operand 0 "" "=rf") 10223 (call (mem:SI (match_operand:SI 1 "register_operand" "k")) 10224 (match_operand 2 "" ""))) 10225 (use (reg:SI FPSCR_MODES_REG)) 10226 (return)] 10227 "TARGET_SH1" 10228 "jmp @%1%#" 10229 [(set_attr "needs_delay_slot" "yes") 10230 (set (attr "fp_mode") 10231 (if_then_else (eq_attr "fpu_single" "yes") 10232 (const_string "single") (const_string "double"))) 10233 (set_attr "type" "jump_ind")]) 10234 10235(define_insn "sibcall_valuei_pcrel" 10236 [(set (match_operand 0 "" "=rf") 10237 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k")) 10238 (match_operand 2 "" ""))) 10239 (use (match_operand 3 "" "")) 10240 (use (reg:SI FPSCR_MODES_REG)) 10241 (return)] 10242 "TARGET_SH2" 10243{ 10244 return "braf %1" "\n" 10245 "%O3:%#"; 10246} 10247 [(set_attr "needs_delay_slot" "yes") 10248 (set (attr "fp_mode") 10249 (if_then_else (eq_attr "fpu_single" "yes") 10250 (const_string "single") (const_string "double"))) 10251 (set_attr "type" "jump_ind")]) 10252 10253;; sibcall_value_pcrel used to have a =&k clobber for the scratch register 10254;; that it needs for the branch address. This causes troubles when there 10255;; is a big overlap of argument and return value registers. Hence, use a 10256;; fixed call clobbered register for the address. See also PR 67260. 10257(define_insn_and_split "sibcall_value_pcrel" 10258 [(set (match_operand 0 "" "=rf") 10259 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "")) 10260 (match_operand 2 "" ""))) 10261 (use (reg:SI FPSCR_MODES_REG)) 10262 (clobber (reg:SI R1_REG)) 10263 (return)] 10264 "TARGET_SH2" 10265 "#" 10266 "reload_completed" 10267 [(const_int 0)] 10268{ 10269 rtx lab = PATTERN (gen_call_site ()); 10270 rtx call_insn; 10271 10272 operands[3] = gen_rtx_REG (SImode, R1_REG); 10273 10274 emit_insn (gen_sym_label2reg (operands[3], operands[1], lab)); 10275 call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0], 10276 operands[3], 10277 operands[2], 10278 copy_rtx (lab))); 10279 SIBLING_CALL_P (call_insn) = 1; 10280 DONE; 10281} 10282 [(set_attr "needs_delay_slot" "yes") 10283 (set (attr "fp_mode") 10284 (if_then_else (eq_attr "fpu_single" "yes") 10285 (const_string "single") (const_string "double"))) 10286 (set_attr "type" "jump_ind")]) 10287 10288(define_insn "sibcall_value_compact" 10289 [(set (match_operand 0 "" "=rf,rf") 10290 (call (mem:SI (match_operand:SI 1 "register_operand" "k,k")) 10291 (match_operand 2 "" ""))) 10292 (return) 10293 (use (match_operand:SI 3 "register_operand" "z,x")) 10294 (use (reg:SI R1_REG)) 10295 (use (reg:SI FPSCR_MODES_REG)) 10296 ;; We want to make sure the `x' above will only match MACH_REG 10297 ;; because sibcall_epilogue may clobber MACL_REG. 10298 (clobber (reg:SI MACL_REG))] 10299 "TARGET_SHCOMPACT" 10300{ 10301 static const char* alt[] = 10302 { 10303 "jmp @%1%#", 10304 10305 "jmp @%1" "\n" 10306 " sts %3,r0" 10307 }; 10308 return alt[which_alternative]; 10309} 10310 [(set_attr "needs_delay_slot" "yes,no") 10311 (set_attr "length" "2,4") 10312 (set (attr "fp_mode") (const_string "single")) 10313 (set_attr "type" "jump_ind")]) 10314 10315(define_insn "sibcall_value_media" 10316 [(set (match_operand 0 "" "=rf") 10317 (call (mem:DI (match_operand 1 "target_reg_operand" "k")) 10318 (match_operand 2 "" ""))) 10319 (use (reg:SI PR_MEDIA_REG)) 10320 (return)] 10321 "TARGET_SHMEDIA" 10322 "blink %1, r63" 10323 [(set_attr "type" "jump_media")]) 10324 10325(define_expand "sibcall_value" 10326 [(parallel 10327 [(set (match_operand 0 "arith_reg_operand" "") 10328 (call (mem:SI (match_operand 1 "arith_reg_operand" "")) 10329 (match_operand 2 "" ""))) 10330 (match_operand 3 "" "") 10331 (use (reg:SI FPSCR_MODES_REG)) 10332 (return)])] 10333 "" 10334{ 10335 if (TARGET_SHMEDIA) 10336 { 10337 operands[1] = shmedia_prepare_call_address (operands[1], 1); 10338 emit_call_insn (gen_sibcall_value_media (operands[0], operands[1], 10339 operands[2])); 10340 DONE; 10341 } 10342 else if (TARGET_SHCOMPACT && operands[3] 10343 && (INTVAL (operands[3]) & ~ CALL_COOKIE_RET_TRAMP (1))) 10344 { 10345 rtx cookie_rtx = operands[3]; 10346 long cookie = INTVAL (cookie_rtx); 10347 rtx func = XEXP (operands[1], 0); 10348 rtx mach, r1; 10349 10350 if (flag_pic) 10351 { 10352 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func)) 10353 { 10354 rtx reg = gen_reg_rtx (Pmode); 10355 10356 emit_insn (gen_symGOT2reg (reg, func)); 10357 func = reg; 10358 } 10359 else 10360 func = legitimize_pic_address (func, Pmode, 0); 10361 } 10362 10363 /* FIXME: if we could tell whether all argument registers are 10364 already taken, we could decide whether to force the use of 10365 MACH_REG or to stick to R0_REG. Unfortunately, there's no 10366 simple way to tell. We could use the CALL_COOKIE, but we 10367 can't currently tell a register used for regular argument 10368 passing from one that is unused. If we leave it up to reload 10369 to decide which register to use, it seems to always choose 10370 R0_REG, which leaves no available registers in SIBCALL_REGS 10371 to hold the address of the trampoline. */ 10372 mach = gen_rtx_REG (SImode, MACH_REG); 10373 r1 = gen_rtx_REG (SImode, R1_REG); 10374 10375 /* Since such a call function may use all call-clobbered 10376 registers, we force a mode switch earlier, so that we don't 10377 run out of registers when adjusting fpscr for the call. */ 10378 emit_insn (gen_force_mode_for_call ()); 10379 10380 operands[1] 10381 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT); 10382 operands[1] = force_reg (SImode, operands[1]); 10383 10384 /* We don't need a return trampoline, since the callee will 10385 return directly to the upper caller. */ 10386 if (cookie & CALL_COOKIE_RET_TRAMP (1)) 10387 { 10388 cookie &= ~ CALL_COOKIE_RET_TRAMP (1); 10389 cookie_rtx = GEN_INT (cookie); 10390 } 10391 10392 emit_move_insn (mach, func); 10393 emit_move_insn (r1, cookie_rtx); 10394 10395 emit_call_insn (gen_sibcall_value_compact (operands[0], operands[1], 10396 operands[2], mach)); 10397 DONE; 10398 } 10399 else if (TARGET_SHCOMPACT && flag_pic 10400 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF 10401 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0))) 10402 { 10403 rtx reg = gen_reg_rtx (Pmode); 10404 10405 emit_insn (gen_symGOT2reg (reg, XEXP (operands[1], 0))); 10406 XEXP (operands[1], 0) = reg; 10407 } 10408 if (flag_pic && TARGET_SH2 10409 && MEM_P (operands[1]) 10410 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF 10411 /* The PLT needs the PIC register, but the epilogue would have 10412 to restore it, so we can only use PC-relative PIC calls for 10413 static functions. */ 10414 && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0))) 10415 { 10416 emit_call_insn (gen_sibcall_value_pcrel (operands[0], 10417 XEXP (operands[1], 0), 10418 operands[2])); 10419 DONE; 10420 } 10421 else 10422 operands[1] = force_reg (SImode, XEXP (operands[1], 0)); 10423 10424 emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2])); 10425 DONE; 10426}) 10427 10428(define_insn "call_value_pop_compact" 10429 [(set (match_operand 0 "" "=rf") 10430 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) 10431 (match_operand 2 "" ""))) 10432 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) 10433 (match_operand 4 "immediate_operand" "n"))) 10434 (match_operand 3 "immediate_operand" "n") 10435 (use (reg:SI R0_REG)) 10436 (use (reg:SI R1_REG)) 10437 (use (reg:SI FPSCR_MODES_REG)) 10438 (clobber (reg:SI PR_REG))] 10439 "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))" 10440 "jsr @%1%#" 10441 [(set_attr "type" "call") 10442 (set (attr "fp_mode") 10443 (if_then_else (eq_attr "fpu_single" "yes") 10444 (const_string "single") (const_string "double"))) 10445 (set_attr "needs_delay_slot" "yes")]) 10446 10447(define_insn "call_value_pop_compact_rettramp" 10448 [(set (match_operand 0 "" "=rf") 10449 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) 10450 (match_operand 2 "" ""))) 10451 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) 10452 (match_operand 4 "immediate_operand" "n"))) 10453 (match_operand 3 "immediate_operand" "n") 10454 (use (reg:SI R0_REG)) 10455 (use (reg:SI R1_REG)) 10456 (use (reg:SI FPSCR_MODES_REG)) 10457 (clobber (reg:SI R10_REG)) 10458 (clobber (reg:SI PR_REG))] 10459 "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))" 10460 "jsr @%1%#" 10461 [(set_attr "type" "call") 10462 (set (attr "fp_mode") 10463 (if_then_else (eq_attr "fpu_single" "yes") 10464 (const_string "single") (const_string "double"))) 10465 (set_attr "needs_delay_slot" "yes")]) 10466 10467(define_expand "call_value_pop" 10468 [(parallel [(set (match_operand 0 "arith_reg_operand" "") 10469 (call (mem:SI (match_operand 1 "arith_reg_operand" "")) 10470 (match_operand 2 "" ""))) 10471 (match_operand 3 "" "") 10472 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) 10473 (match_operand 4 "" "")))])] 10474 "TARGET_SHCOMPACT" 10475{ 10476 rtx cookie_rtx; 10477 long cookie; 10478 rtx func; 10479 rtx r0, r1; 10480 10481 gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3])); 10482 cookie_rtx = operands[3]; 10483 cookie = INTVAL (cookie_rtx); 10484 func = XEXP (operands[1], 0); 10485 10486 if (flag_pic) 10487 { 10488 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func)) 10489 { 10490 rtx reg = gen_reg_rtx (Pmode); 10491 10492 emit_insn (gen_symGOTPLT2reg (reg, func)); 10493 func = reg; 10494 } 10495 else 10496 func = legitimize_pic_address (func, Pmode, 0); 10497 } 10498 10499 r0 = gen_rtx_REG (SImode, R0_REG); 10500 r1 = gen_rtx_REG (SImode, R1_REG); 10501 10502 /* Since such a call function may use all call-clobbered 10503 registers, we force a mode switch earlier, so that we don't 10504 run out of registers when adjusting fpscr for the call. */ 10505 emit_insn (gen_force_mode_for_call ()); 10506 10507 operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline", 10508 SFUNC_GOT); 10509 operands[1] = force_reg (SImode, operands[1]); 10510 10511 emit_move_insn (r0, func); 10512 emit_move_insn (r1, cookie_rtx); 10513 10514 if (cookie & CALL_COOKIE_RET_TRAMP (1)) 10515 emit_call_insn (gen_call_value_pop_compact_rettramp 10516 (operands[0], operands[1], operands[2], 10517 operands[3], operands[4])); 10518 else 10519 emit_call_insn (gen_call_value_pop_compact 10520 (operands[0], operands[1], operands[2], 10521 operands[3], operands[4])); 10522 10523 DONE; 10524}) 10525 10526(define_expand "sibcall_epilogue" 10527 [(return)] 10528 "" 10529{ 10530 sh_expand_epilogue (true); 10531 if (TARGET_SHCOMPACT) 10532 { 10533 rtx_insn *insn; 10534 rtx set; 10535 10536 /* If epilogue clobbers r0, preserve it in macl. */ 10537 for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) 10538 if ((set = single_set (insn)) 10539 && REG_P (SET_DEST (set)) 10540 && REGNO (SET_DEST (set)) == R0_REG) 10541 { 10542 rtx r0 = gen_rtx_REG (SImode, R0_REG); 10543 rtx tmp = gen_rtx_REG (SImode, MACL_REG); 10544 10545 /* We can't tell at this point whether the sibcall is a 10546 sibcall_compact and, if it is, whether it uses r0 or 10547 mach as operand 2, so let the instructions that 10548 preserve r0 be optimized away if r0 turns out to be 10549 dead. */ 10550 emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn); 10551 emit_move_insn (r0, tmp); 10552 break; 10553 } 10554 } 10555 DONE; 10556}) 10557 10558(define_insn "indirect_jump_compact" 10559 [(set (pc) 10560 (match_operand:SI 0 "arith_reg_operand" "r"))] 10561 "TARGET_SH1" 10562 "jmp @%0%#" 10563 [(set_attr "needs_delay_slot" "yes") 10564 (set_attr "type" "jump_ind")]) 10565 10566(define_expand "indirect_jump" 10567 [(set (pc) 10568 (match_operand 0 "register_operand" ""))] 10569 "" 10570{ 10571 if (GET_MODE (operands[0]) != Pmode) 10572 operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0); 10573}) 10574 10575;; The use of operand 1 / 2 helps us distinguish case table jumps 10576;; which can be present in structured code from indirect jumps which can not 10577;; be present in structured code. This allows -fprofile-arcs to work. 10578 10579;; For SH1 processors. 10580(define_insn "casesi_jump_1" 10581 [(set (pc) 10582 (match_operand:SI 0 "register_operand" "r")) 10583 (use (label_ref (match_operand 1 "" "")))] 10584 "TARGET_SH1" 10585 "jmp @%0%#" 10586 [(set_attr "needs_delay_slot" "yes") 10587 (set_attr "type" "jump_ind")]) 10588 10589;; For all later processors. 10590(define_insn "casesi_jump_2" 10591 [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r") 10592 (label_ref (match_operand 1 "" "")))) 10593 (use (label_ref (match_operand 2 "" "")))] 10594 "TARGET_SH2 10595 && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)" 10596 "braf %0%#" 10597 [(set_attr "needs_delay_slot" "yes") 10598 (set_attr "type" "jump_ind")]) 10599 10600(define_insn "casesi_jump_media" 10601 [(set (pc) (match_operand 0 "target_reg_operand" "b")) 10602 (use (label_ref (match_operand 1 "" "")))] 10603 "TARGET_SHMEDIA" 10604 "blink %0, r63" 10605 [(set_attr "type" "jump_media")]) 10606 10607;; Call subroutine returning any type. 10608;; ??? This probably doesn't work. 10609(define_expand "untyped_call" 10610 [(parallel [(call (match_operand 0 "" "") 10611 (const_int 0)) 10612 (match_operand 1 "" "") 10613 (match_operand 2 "" "")])] 10614 "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA" 10615{ 10616 if (! TARGET_SHMEDIA) 10617 { 10618 /* RA does not know that the call sets the function value registers. 10619 We avoid problems by claiming that those registers are clobbered 10620 at this point. */ 10621 for (int i = 0; i < XVECLEN (operands[2], 0); i++) 10622 { 10623 rtx set = XVECEXP (operands[2], 0, i); 10624 emit_clobber (SET_SRC (set)); 10625 } 10626 } 10627 10628 emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx)); 10629 10630 for (int i = 0; i < XVECLEN (operands[2], 0); i++) 10631 { 10632 rtx set = XVECEXP (operands[2], 0, i); 10633 emit_move_insn (SET_DEST (set), SET_SRC (set)); 10634 } 10635 10636 /* The optimizer does not know that the call sets the function value 10637 registers we stored in the result block. We avoid problems by 10638 claiming that all hard registers are used and clobbered at this 10639 point. */ 10640 emit_insn (gen_blockage ()); 10641 10642 DONE; 10643}) 10644 10645;; ------------------------------------------------------------------------ 10646;; Misc insns 10647;; ------------------------------------------------------------------------ 10648 10649(define_insn "dect" 10650 [(set (reg:SI T_REG) 10651 (eq:SI (match_operand:SI 1 "arith_reg_dest" "0") (const_int 1))) 10652 (set (match_operand:SI 0 "arith_reg_dest" "=r") 10653 (plus:SI (match_dup 1) (const_int -1)))] 10654 "TARGET_SH2" 10655 "dt %0" 10656 [(set_attr "type" "arith")]) 10657 10658(define_insn "nop" 10659 [(const_int 0)] 10660 "" 10661 "nop") 10662 10663;; Load address of a label. This is only generated by the casesi expand, 10664;; and by machine_dependent_reorg (fixing up fp moves). 10665;; This must use unspec, because this only works for labels that are 10666;; within range. 10667(define_insn "mova" 10668 [(set (reg:SI R0_REG) 10669 (unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))] 10670 "TARGET_SH1" 10671 "mova %O0,r0" 10672 [(set_attr "in_delay_slot" "no") 10673 (set_attr "type" "arith")]) 10674 10675;; machine_dependent_reorg will make this a `mova'. 10676(define_insn "mova_const" 10677 [(set (reg:SI R0_REG) 10678 (unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))] 10679 "TARGET_SH1" 10680 "#" 10681 [(set_attr "in_delay_slot" "no") 10682 (set_attr "type" "arith")]) 10683 10684;; Loads of the GOTPC relocation values must not be optimized away 10685;; by e.g. any kind of CSE and must stay as they are. Although there 10686;; are other various ways to ensure this, we use an artificial counter 10687;; operand to generate unique symbols. 10688(define_expand "GOTaddr2picreg" 10689 [(set (reg:SI R0_REG) 10690 (unspec:SI [(const:SI (unspec:SI [(match_dup 2) 10691 (match_operand:SI 0 "" "")] 10692 UNSPEC_PIC))] UNSPEC_MOVA)) 10693 (set (match_dup 1) 10694 (const:SI (unspec:SI [(match_dup 2) (match_dup 0)] UNSPEC_PIC))) 10695 (set (match_dup 1) (plus:SI (match_dup 1) (reg:SI R0_REG)))] 10696 "" 10697{ 10698 if (TARGET_VXWORKS_RTP) 10699 { 10700 rtx gott_base = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE); 10701 rtx gott_index = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX); 10702 emit_insn (gen_vxworks_picreg (gott_base, gott_index)); 10703 DONE; 10704 } 10705 10706 operands[1] = gen_rtx_REG (Pmode, PIC_REG); 10707 operands[2] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME); 10708 10709 if (TARGET_SHMEDIA) 10710 { 10711 rtx tr = gen_rtx_REG (Pmode, TR0_REG); 10712 rtx pic = operands[1]; 10713 rtx lab = PATTERN (gen_call_site ()); 10714 rtx insn, equiv; 10715 10716 equiv = operands[2]; 10717 operands[2] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[2], lab), 10718 UNSPEC_PCREL_SYMOFF); 10719 operands[2] = gen_rtx_CONST (Pmode, operands[2]); 10720 10721 if (Pmode == SImode) 10722 { 10723 emit_insn (gen_movsi_const (pic, operands[2])); 10724 emit_insn (gen_ptrel_si (tr, pic, copy_rtx (lab))); 10725 } 10726 else 10727 { 10728 emit_insn (gen_movdi_const (pic, operands[2])); 10729 emit_insn (gen_ptrel_di (tr, pic, copy_rtx (lab))); 10730 } 10731 10732 insn = emit_move_insn (operands[1], tr); 10733 10734 set_unique_reg_note (insn, REG_EQUAL, equiv); 10735 10736 DONE; 10737 } 10738}) 10739 10740;; A helper for GOTaddr2picreg to finish up the initialization of the 10741;; PIC register. 10742(define_expand "vxworks_picreg" 10743 [(set (reg:SI PIC_REG) 10744 (const:SI (unspec:SI [(match_operand:SI 0 "" "")] UNSPEC_PIC))) 10745 (set (reg:SI R0_REG) 10746 (const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC))) 10747 (set (reg:SI PIC_REG) 10748 (mem:SI (reg:SI PIC_REG))) 10749 (set (reg:SI PIC_REG) 10750 (mem:SI (plus:SI (reg:SI PIC_REG) 10751 (reg:SI R0_REG))))] 10752 "TARGET_VXWORKS_RTP") 10753 10754(define_insn "*ptb" 10755 [(set (match_operand 0 "target_reg_operand" "=b") 10756 (const (unspec [(match_operand 1 "" "Csy")] 10757 UNSPEC_DATALABEL)))] 10758 "TARGET_SHMEDIA && flag_pic 10759 && satisfies_constraint_Csy (operands[1])" 10760 "ptb/u datalabel %1, %0" 10761 [(set_attr "type" "ptabs_media") 10762 (set_attr "length" "*")]) 10763 10764(define_insn "ptrel_si" 10765 [(set (match_operand:SI 0 "target_reg_operand" "=b") 10766 (plus:SI (match_operand:SI 1 "register_operand" "r") 10767 (pc))) 10768 (match_operand:SI 2 "" "")] 10769 "TARGET_SHMEDIA" 10770 "%O2: ptrel/u %1, %0" 10771 [(set_attr "type" "ptabs_media")]) 10772 10773(define_insn "ptrel_di" 10774 [(set (match_operand:DI 0 "target_reg_operand" "=b") 10775 (plus:DI (match_operand:DI 1 "register_operand" "r") 10776 (pc))) 10777 (match_operand:DI 2 "" "")] 10778 "TARGET_SHMEDIA" 10779 "%O2: ptrel/u %1, %0" 10780 [(set_attr "type" "ptabs_media")]) 10781 10782(define_expand "builtin_setjmp_receiver" 10783 [(match_operand 0 "" "")] 10784 "flag_pic" 10785{ 10786 emit_insn (gen_GOTaddr2picreg (const0_rtx)); 10787 DONE; 10788}) 10789 10790(define_expand "call_site" 10791 [(unspec [(match_dup 0)] UNSPEC_CALLER)] 10792 "TARGET_SH1" 10793{ 10794 static HOST_WIDE_INT i = 0; 10795 operands[0] = GEN_INT (i); 10796 i++; 10797}) 10798 10799;; op0 = op1 + r12 but hide it before reload completed. See the comment 10800;; in symGOT_load expand. 10801(define_insn_and_split "chk_guard_add" 10802 [(set (match_operand:SI 0 "register_operand" "=&r") 10803 (unspec:SI [(match_operand:SI 1 "register_operand" "r") 10804 (reg:SI PIC_REG)] 10805 UNSPEC_CHKADD))] 10806 "TARGET_SH1" 10807 "#" 10808 "TARGET_SH1 && reload_completed" 10809 [(set (match_dup 0) (reg:SI PIC_REG)) 10810 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))] 10811 "" 10812 [(set_attr "type" "arith")]) 10813 10814(define_expand "sym_label2reg" 10815 [(set (match_operand:SI 0 "" "") 10816 (const:SI (unspec:SI [(match_operand:SI 1 "" "") 10817 (const (plus:SI (match_operand:SI 2 "" "") 10818 (const_int 2)))] 10819 UNSPEC_SYMOFF)))] 10820 "TARGET_SH1" "") 10821 10822(define_expand "symGOT_load" 10823 [(set (match_dup 2) (match_operand 1 "" "")) 10824 (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG))) 10825 (set (match_operand 0 "" "") (mem (match_dup 3)))] 10826 "" 10827{ 10828 rtx mem; 10829 bool stack_chk_guard_p = false; 10830 10831 operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode); 10832 operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode); 10833 10834 if (!TARGET_SHMEDIA 10835 && flag_stack_protect 10836 && GET_CODE (operands[1]) == CONST 10837 && GET_CODE (XEXP (operands[1], 0)) == UNSPEC 10838 && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == SYMBOL_REF 10839 && strcmp (XSTR (XVECEXP (XEXP (operands[1], 0), 0, 0), 0), 10840 "__stack_chk_guard") == 0) 10841 stack_chk_guard_p = true; 10842 10843 if (TARGET_SHMEDIA) 10844 { 10845 rtx reg = operands[2]; 10846 10847 if (Pmode == DImode) 10848 { 10849 if (flag_pic > 1) 10850 emit_insn (gen_movdi_const_32bit (reg, operands[1])); 10851 else 10852 emit_insn (gen_movdi_const_16bit (reg, operands[1])); 10853 } 10854 else 10855 { 10856 if (flag_pic > 1) 10857 emit_insn (gen_movsi_const (reg, operands[1])); 10858 else 10859 emit_insn (gen_movsi_const_16bit (reg, operands[1])); 10860 } 10861 } 10862 else 10863 emit_move_insn (operands[2], operands[1]); 10864 10865 /* When stack protector inserts codes after the result is set to 10866 R0, @(rX, r12) will cause a spill failure for R0. Use a unspec 10867 insn to avoid combining (set A (plus rX r12)) and (set op0 (mem A)) 10868 when rX is a GOT address for the guard symbol. Ugly but doesn't 10869 matter because this is a rare situation. */ 10870 if (stack_chk_guard_p) 10871 emit_insn (gen_chk_guard_add (operands[3], operands[2])); 10872 else 10873 emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2], 10874 gen_rtx_REG (Pmode, PIC_REG))); 10875 10876 /* N.B. This is not constant for a GOTPLT relocation. */ 10877 mem = gen_rtx_MEM (Pmode, operands[3]); 10878 MEM_NOTRAP_P (mem) = 1; 10879 /* ??? Should we have a special alias set for the GOT? */ 10880 emit_move_insn (operands[0], mem); 10881 10882 DONE; 10883}) 10884 10885(define_expand "sym2GOT" 10886 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))] 10887 "" 10888 "") 10889 10890(define_expand "symGOT2reg" 10891 [(match_operand 0 "" "") (match_operand 1 "" "")] 10892 "" 10893{ 10894 rtx gotsym, insn; 10895 10896 gotsym = gen_sym2GOT (operands[1]); 10897 PUT_MODE (gotsym, Pmode); 10898 insn = emit_insn (gen_symGOT_load (operands[0], gotsym)); 10899 10900 MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1; 10901 10902 DONE; 10903}) 10904 10905(define_expand "symGOTPLT2reg" 10906 [(match_operand 0 "" "") (match_operand 1 "" "")] 10907 "" 10908{ 10909 rtx pltsym = gen_rtx_CONST (Pmode, 10910 gen_rtx_UNSPEC (Pmode, 10911 gen_rtvec (1, operands[1]), 10912 UNSPEC_GOTPLT)); 10913 emit_insn (gen_symGOT_load (operands[0], pltsym)); 10914 DONE; 10915}) 10916 10917(define_expand "sym2GOTOFF" 10918 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))] 10919 "" 10920 "") 10921 10922(define_expand "symGOTOFF2reg" 10923 [(match_operand 0 "" "") (match_operand 1 "" "")] 10924 "" 10925{ 10926 rtx gotoffsym, insn; 10927 rtx t = (!can_create_pseudo_p () 10928 ? operands[0] 10929 : gen_reg_rtx (GET_MODE (operands[0]))); 10930 10931 gotoffsym = gen_sym2GOTOFF (operands[1]); 10932 PUT_MODE (gotoffsym, Pmode); 10933 emit_move_insn (t, gotoffsym); 10934 insn = emit_move_insn (operands[0], 10935 gen_rtx_PLUS (Pmode, t, 10936 gen_rtx_REG (Pmode, PIC_REG))); 10937 10938 set_unique_reg_note (insn, REG_EQUAL, operands[1]); 10939 10940 DONE; 10941}) 10942 10943(define_expand "symPLT_label2reg" 10944 [(set (match_operand:SI 0 "" "") 10945 (const:SI 10946 (unspec:SI 10947 [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT)) 10948 (const:SI (plus:SI (match_operand:SI 2 "" "") 10949 (const_int 2)))] UNSPEC_PCREL_SYMOFF))) 10950 ;; Even though the PIC register is not really used by the call 10951 ;; sequence in which this is expanded, the PLT code assumes the PIC 10952 ;; register is set, so we must not skip its initialization. Since 10953 ;; we only use this expand as part of calling sequences, and never 10954 ;; to take the address of a function, this is the best point to 10955 ;; insert the (use). Using the PLT to take the address of a 10956 ;; function would be wrong, not only because the PLT entry could 10957 ;; then be called from a function that doesn't initialize the PIC 10958 ;; register to the proper GOT, but also because pointers to the 10959 ;; same function might not compare equal, should they be set by 10960 ;; different shared libraries. 10961 (use (reg:SI PIC_REG))] 10962 "TARGET_SH1" 10963 "") 10964 10965(define_expand "sym2PIC" 10966 [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))] 10967 "" 10968 "") 10969 10970;; ------------------------------------------------------------------------- 10971;; TLS code generation. 10972 10973;; FIXME: The multi-insn asm blocks should be converted to use 10974;; define_insn_and_split. 10975;; See the thread [PATCH/RFA] SH TLS support on gcc-patches 10976;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html> 10977;; for details. 10978 10979(define_insn "tls_global_dynamic" 10980 [(set (match_operand:SI 0 "register_operand" "=&z") 10981 (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")] 10982 UNSPEC_TLSGD)) 10983 (const_int 0))) 10984 (use (reg:SI FPSCR_MODES_REG)) 10985 (use (reg:SI PIC_REG)) 10986 (clobber (reg:SI PR_REG)) 10987 (clobber (scratch:SI))] 10988 "TARGET_SH1" 10989{ 10990 return "mov.l 1f,r4" "\n" 10991 " mova 2f,r0" "\n" 10992 " mov.l 2f,r1" "\n" 10993 " add r0,r1" "\n" 10994 " jsr @r1" "\n" 10995 " add r12,r4" "\n" 10996 " bra 3f" "\n" 10997 " nop" "\n" 10998 " .align 2" "\n" 10999 "1: .long %a1@TLSGD" "\n" 11000 "2: .long __tls_get_addr@PLT" "\n" 11001 "3:"; 11002} 11003 [(set_attr "type" "tls_load") 11004 (set_attr "length" "26")]) 11005 11006(define_insn "tls_local_dynamic" 11007 [(set (match_operand:SI 0 "register_operand" "=&z") 11008 (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")] 11009 UNSPEC_TLSLDM)) 11010 (const_int 0))) 11011 (use (reg:SI FPSCR_MODES_REG)) 11012 (use (reg:SI PIC_REG)) 11013 (clobber (reg:SI PR_REG)) 11014 (clobber (scratch:SI))] 11015 "TARGET_SH1" 11016{ 11017 return "mov.l 1f,r4" "\n" 11018 " mova 2f,r0" "\n" 11019 " mov.l 2f,r1" "\n" 11020 " add r0,r1" "\n" 11021 " jsr @r1" "\n" 11022 " add r12,r4" "\n" 11023 " bra 3f" "\n" 11024 " nop" "\n" 11025 " .align 2" "\n" 11026 "1: .long %a1@TLSLDM" "\n" 11027 "2: .long __tls_get_addr@PLT" "\n" 11028 "3:"; 11029} 11030 [(set_attr "type" "tls_load") 11031 (set_attr "length" "26")]) 11032 11033(define_expand "sym2DTPOFF" 11034 [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))] 11035 "" 11036 "") 11037 11038(define_expand "symDTPOFF2reg" 11039 [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")] 11040 "" 11041{ 11042 rtx dtpoffsym; 11043 rtx t = (!can_create_pseudo_p () 11044 ? operands[0] 11045 : gen_reg_rtx (GET_MODE (operands[0]))); 11046 11047 dtpoffsym = gen_sym2DTPOFF (operands[1]); 11048 PUT_MODE (dtpoffsym, Pmode); 11049 emit_move_insn (t, dtpoffsym); 11050 emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, operands[2])); 11051 DONE; 11052}) 11053 11054(define_expand "sym2GOTTPOFF" 11055 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))] 11056 "" 11057 "") 11058 11059(define_insn "tls_initial_exec" 11060 [(set (match_operand:SI 0 "register_operand" "=&r") 11061 (unspec:SI [(match_operand:SI 1 "" "")] 11062 UNSPEC_TLSIE)) 11063 (use (reg:SI GBR_REG)) 11064 (use (reg:SI PIC_REG)) 11065 (clobber (reg:SI R0_REG))] 11066 "" 11067{ 11068 return "mov.l 1f,r0" "\n" 11069 " stc gbr,%0" "\n" 11070 " mov.l @(r0,r12),r0" "\n" 11071 " bra 2f" "\n" 11072 " add r0,%0" "\n" 11073 " .align 2" "\n" 11074 "1: .long %a1" "\n" 11075 "2:"; 11076} 11077 [(set_attr "type" "tls_load") 11078 (set_attr "length" "16")]) 11079 11080(define_expand "sym2TPOFF" 11081 [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))] 11082 "" 11083 "") 11084 11085(define_expand "symTPOFF2reg" 11086 [(match_operand 0 "" "") (match_operand 1 "" "")] 11087 "" 11088{ 11089 rtx tpoffsym; 11090 11091 tpoffsym = gen_sym2TPOFF (operands[1]); 11092 PUT_MODE (tpoffsym, Pmode); 11093 emit_move_insn (operands[0], tpoffsym); 11094 DONE; 11095}) 11096 11097;;------------------------------------------------------------------------------ 11098;; Thread pointer getter and setter. 11099;; 11100;; On SH the thread pointer is kept in the GBR. 11101;; These patterns are usually expanded from the respective built-in functions. 11102(define_expand "get_thread_pointersi" 11103 [(set (match_operand:SI 0 "arith_reg_dest") (reg:SI GBR_REG))] 11104 "TARGET_SH1") 11105 11106;; The store_gbr insn can also be used on !TARGET_SH1 for doing TLS accesses. 11107(define_insn "store_gbr" 11108 [(set (match_operand:SI 0 "arith_reg_dest" "=r") (reg:SI GBR_REG))] 11109 "" 11110 "stc gbr,%0" 11111 [(set_attr "type" "tls_load")]) 11112 11113(define_expand "set_thread_pointersi" 11114 [(set (reg:SI GBR_REG) 11115 (unspec_volatile:SI [(match_operand:SI 0 "arith_reg_operand")] 11116 UNSPECV_GBR))] 11117 "TARGET_SH1") 11118 11119(define_insn "load_gbr" 11120 [(set (reg:SI GBR_REG) 11121 (unspec_volatile:SI [(match_operand:SI 0 "arith_reg_operand" "r")] 11122 UNSPECV_GBR))] 11123 "TARGET_SH1" 11124 "ldc %0,gbr" 11125 [(set_attr "type" "move")]) 11126 11127;;------------------------------------------------------------------------------ 11128;; Thread pointer relative memory loads and stores. 11129;; 11130;; On SH there are GBR displacement address modes which can be utilized to 11131;; access memory behind the thread pointer. 11132;; Since we do not allow using GBR for general purpose memory accesses, these 11133;; GBR addressing modes are formed by the combine pass. 11134;; This could be done with fewer patterns than below by using a mem predicate 11135;; for the GBR mem, but then reload would try to reload addresses with a 11136;; zero displacement for some strange reason. 11137 11138(define_insn "*mov<mode>_gbr_load" 11139 [(set (match_operand:QIHISI 0 "arith_reg_dest" "=z") 11140 (mem:QIHISI (plus:SI (reg:SI GBR_REG) 11141 (match_operand:QIHISI 1 "gbr_displacement"))))] 11142 "TARGET_SH1" 11143 "mov.<bwl> @(%O1,gbr),%0" 11144 [(set_attr "type" "load")]) 11145 11146(define_insn "*mov<mode>_gbr_load" 11147 [(set (match_operand:QIHISI 0 "arith_reg_dest" "=z") 11148 (mem:QIHISI (reg:SI GBR_REG)))] 11149 "TARGET_SH1" 11150 "mov.<bwl> @(0,gbr),%0" 11151 [(set_attr "type" "load")]) 11152 11153(define_insn "*mov<mode>_gbr_load" 11154 [(set (match_operand:SI 0 "arith_reg_dest" "=z") 11155 (sign_extend:SI 11156 (mem:QIHI (plus:SI (reg:SI GBR_REG) 11157 (match_operand:QIHI 1 "gbr_displacement")))))] 11158 "TARGET_SH1" 11159 "mov.<bw> @(%O1,gbr),%0" 11160 [(set_attr "type" "load")]) 11161 11162(define_insn "*mov<mode>_gbr_load" 11163 [(set (match_operand:SI 0 "arith_reg_dest" "=z") 11164 (sign_extend:SI (mem:QIHI (reg:SI GBR_REG))))] 11165 "TARGET_SH1" 11166 "mov.<bw> @(0,gbr),%0" 11167 [(set_attr "type" "load")]) 11168 11169(define_insn "*mov<mode>_gbr_store" 11170 [(set (mem:QIHISI (plus:SI (reg:SI GBR_REG) 11171 (match_operand:QIHISI 0 "gbr_displacement"))) 11172 (match_operand:QIHISI 1 "register_operand" "z"))] 11173 "TARGET_SH1" 11174 "mov.<bwl> %1,@(%O0,gbr)" 11175 [(set_attr "type" "store")]) 11176 11177(define_insn "*mov<mode>_gbr_store" 11178 [(set (mem:QIHISI (reg:SI GBR_REG)) 11179 (match_operand:QIHISI 0 "register_operand" "z"))] 11180 "TARGET_SH1" 11181 "mov.<bwl> %0,@(0,gbr)" 11182 [(set_attr "type" "store")]) 11183 11184;; DImode memory accesses have to be split in two SImode accesses. 11185;; Split them before reload, so that it gets a better chance to figure out 11186;; how to deal with the R0 restriction for the individual SImode accesses. 11187;; Do not match this insn during or after reload because it can't be split 11188;; afterwards. 11189(define_insn_and_split "*movdi_gbr_load" 11190 [(set (match_operand:DI 0 "arith_reg_dest") 11191 (match_operand:DI 1 "gbr_address_mem"))] 11192 "TARGET_SH1 && can_create_pseudo_p ()" 11193 "#" 11194 "&& 1" 11195 [(set (match_dup 3) (match_dup 5)) 11196 (set (match_dup 4) (match_dup 6))] 11197{ 11198 /* Swap low/high part load order on little endian, so that the result reg 11199 of the second load can be used better. */ 11200 int off = TARGET_LITTLE_ENDIAN ? 1 : 0; 11201 operands[3 + off] = gen_lowpart (SImode, operands[0]); 11202 operands[5 + off] = gen_lowpart (SImode, operands[1]); 11203 operands[4 - off] = gen_highpart (SImode, operands[0]); 11204 operands[6 - off] = gen_highpart (SImode, operands[1]); 11205}) 11206 11207(define_insn_and_split "*movdi_gbr_store" 11208 [(set (match_operand:DI 0 "gbr_address_mem") 11209 (match_operand:DI 1 "register_operand"))] 11210 "TARGET_SH1 && can_create_pseudo_p ()" 11211 "#" 11212 "&& 1" 11213 [(set (match_dup 3) (match_dup 5)) 11214 (set (match_dup 4) (match_dup 6))] 11215{ 11216 /* Swap low/high part store order on big endian, so that stores of function 11217 call results can save a reg copy. */ 11218 int off = TARGET_LITTLE_ENDIAN ? 0 : 1; 11219 operands[3 + off] = gen_lowpart (SImode, operands[0]); 11220 operands[5 + off] = gen_lowpart (SImode, operands[1]); 11221 operands[4 - off] = gen_highpart (SImode, operands[0]); 11222 operands[6 - off] = gen_highpart (SImode, operands[1]); 11223}) 11224 11225;; Sometimes memory accesses do not get combined with the store_gbr insn, 11226;; in particular when the displacements are in the range of the regular move 11227;; insns. Thus, in the first split pass after the combine pass we search 11228;; for missed opportunities and try to fix them up ourselves. 11229;; If an equivalent GBR address can be determined the load / store is split 11230;; into one of the GBR load / store patterns. 11231;; All of that must happen before reload (GBR address modes use R0 as the 11232;; other operand) and there's no point of doing it if the GBR is not 11233;; referenced in a function at all. 11234(define_split 11235 [(set (match_operand:QIHISIDI 0 "register_operand") 11236 (match_operand:QIHISIDI 1 "memory_operand"))] 11237 "TARGET_SH1 && !reload_in_progress && !reload_completed 11238 && df_regs_ever_live_p (GBR_REG)" 11239 [(set (match_dup 0) (match_dup 1))] 11240{ 11241 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]); 11242 if (gbr_mem != NULL_RTX) 11243 operands[1] = replace_equiv_address (operands[1], gbr_mem); 11244 else 11245 FAIL; 11246}) 11247 11248(define_split 11249 [(set (match_operand:SI 0 "register_operand") 11250 (sign_extend:SI (match_operand:QIHI 1 "memory_operand")))] 11251 "TARGET_SH1 && !reload_in_progress && !reload_completed 11252 && df_regs_ever_live_p (GBR_REG)" 11253 [(set (match_dup 0) (sign_extend:SI (match_dup 1)))] 11254{ 11255 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]); 11256 if (gbr_mem != NULL_RTX) 11257 operands[1] = replace_equiv_address (operands[1], gbr_mem); 11258 else 11259 FAIL; 11260}) 11261 11262;; On SH2A we've got movu.b and movu.w for doing zero-extending mem loads. 11263;; Split those so that a GBR load can be used. 11264(define_split 11265 [(set (match_operand:SI 0 "register_operand") 11266 (zero_extend:SI (match_operand:QIHI 1 "memory_operand")))] 11267 "TARGET_SH2A && !reload_in_progress && !reload_completed 11268 && df_regs_ever_live_p (GBR_REG)" 11269 [(set (match_dup 2) (match_dup 1)) 11270 (set (match_dup 0) (zero_extend:SI (match_dup 2)))] 11271{ 11272 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]); 11273 if (gbr_mem != NULL_RTX) 11274 { 11275 operands[2] = gen_reg_rtx (GET_MODE (operands[1])); 11276 operands[1] = replace_equiv_address (operands[1], gbr_mem); 11277 } 11278 else 11279 FAIL; 11280}) 11281 11282(define_split 11283 [(set (match_operand:QIHISIDI 0 "memory_operand") 11284 (match_operand:QIHISIDI 1 "register_operand"))] 11285 "TARGET_SH1 && !reload_in_progress && !reload_completed 11286 && df_regs_ever_live_p (GBR_REG)" 11287 [(set (match_dup 0) (match_dup 1))] 11288{ 11289 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[0]); 11290 if (gbr_mem != NULL_RTX) 11291 operands[0] = replace_equiv_address (operands[0], gbr_mem); 11292 else 11293 FAIL; 11294}) 11295 11296;;------------------------------------------------------------------------------ 11297;; case instruction for switch statements. 11298 11299;; operand 0 is index 11300;; operand 1 is the minimum bound 11301;; operand 2 is the maximum bound - minimum bound + 1 11302;; operand 3 is CODE_LABEL for the table; 11303;; operand 4 is the CODE_LABEL to go to if index out of range. 11304(define_expand "casesi" 11305 [(match_operand:SI 0 "arith_reg_operand" "") 11306 (match_operand:SI 1 "arith_reg_operand" "") 11307 (match_operand:SI 2 "arith_reg_operand" "") 11308 (match_operand 3 "" "") (match_operand 4 "" "")] 11309 "" 11310{ 11311 rtx reg = gen_reg_rtx (SImode); 11312 rtx reg2 = gen_reg_rtx (SImode); 11313 if (TARGET_SHMEDIA) 11314 { 11315 rtx reg = gen_reg_rtx (DImode); 11316 rtx reg2 = gen_reg_rtx (DImode); 11317 rtx reg3 = gen_reg_rtx (Pmode); 11318 rtx reg4 = gen_reg_rtx (Pmode); 11319 rtx reg5 = gen_reg_rtx (Pmode); 11320 rtx load, test; 11321 11322 operands[0] = convert_modes (DImode, SImode, operands[0], 0); 11323 operands[1] = convert_modes (DImode, SImode, operands[1], 0); 11324 operands[2] = convert_modes (DImode, SImode, operands[2], 1); 11325 11326 test = gen_rtx_GT (VOIDmode, operands[1], operands[0]); 11327 emit_jump_insn (gen_cbranchdi4 (test, operands[1], operands[0], 11328 operands[4])); 11329 emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1])); 11330 test = gen_rtx_GTU (VOIDmode, reg, operands[2]); 11331 emit_jump_insn (gen_cbranchdi4 (test, reg, operands[2], operands[4])); 11332 emit_insn (gen_casesi_shift_media (reg2, reg, operands[3])); 11333 emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF 11334 (Pmode, operands[3]))); 11335 /* Messy: can we subreg to clean this up? */ 11336 if (Pmode == DImode) 11337 load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]); 11338 else 11339 load = gen_casesi_load_media (reg4, 11340 gen_rtx_SUBREG (DImode, reg3, 0), 11341 reg2, operands[3]); 11342 PUT_MODE (SET_SRC (load), Pmode); 11343 emit_insn (load); 11344 /* ??? The following add could be eliminated if we used ptrel. */ 11345 emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4)); 11346 emit_jump_insn (gen_casesi_jump_media (reg5, operands[3])); 11347 emit_barrier (); 11348 DONE; 11349 } 11350 operands[1] = copy_to_mode_reg (SImode, operands[1]); 11351 operands[2] = copy_to_mode_reg (SImode, operands[2]); 11352 /* If optimizing, casesi_worker depends on the mode of the instruction 11353 before label it 'uses' - operands[3]. */ 11354 emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4], 11355 reg)); 11356 emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3])); 11357 if (TARGET_SH2) 11358 emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3])); 11359 else 11360 emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3])); 11361 /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to 11362 operands[3], but to lab. We will fix this up in 11363 machine_dependent_reorg. */ 11364 emit_barrier (); 11365 DONE; 11366}) 11367 11368(define_expand "casesi_0" 11369 [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" "")) 11370 (set (match_dup 4) (minus:SI (match_dup 4) 11371 (match_operand:SI 1 "arith_operand" ""))) 11372 (set (reg:SI T_REG) 11373 (gtu:SI (match_dup 4) 11374 (match_operand:SI 2 "arith_reg_operand" ""))) 11375 (set (pc) 11376 (if_then_else (ne (reg:SI T_REG) 11377 (const_int 0)) 11378 (label_ref (match_operand 3 "" "")) 11379 (pc)))] 11380 "TARGET_SH1" 11381 "") 11382 11383;; ??? reload might clobber r0 if we use it explicitly in the RTL before 11384;; reload; using a R0_REGS pseudo reg is likely to give poor code. 11385;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload. 11386;; 11387;; The use on the T_REG in the casesi_worker* patterns links the bounds 11388;; checking insns and the table memory access. See also PR 69713. 11389(define_insn "casesi_worker_0" 11390 [(set (match_operand:SI 0 "register_operand" "=r,r") 11391 (unspec:SI [(match_operand:SI 1 "register_operand" "0,r") 11392 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI)) 11393 (clobber (match_scratch:SI 3 "=X,1")) 11394 (clobber (match_scratch:SI 4 "=&z,z")) 11395 (use (reg:SI T_REG))] 11396 "TARGET_SH1" 11397 "#") 11398 11399(define_split 11400 [(set (match_operand:SI 0 "register_operand" "") 11401 (unspec:SI [(match_operand:SI 1 "register_operand" "") 11402 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI)) 11403 (clobber (match_scratch:SI 3 "")) 11404 (clobber (match_scratch:SI 4)) 11405 (use (reg:SI T_REG))] 11406 "TARGET_SH1 && ! TARGET_SH2 && reload_completed" 11407 [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA)) 11408 (parallel [(set (match_dup 0) 11409 (unspec:SI [(reg:SI R0_REG) (match_dup 1) 11410 (label_ref (match_dup 2))] UNSPEC_CASESI)) 11411 (clobber (match_dup 3))]) 11412 (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))] 11413{ 11414 if (GET_CODE (operands[2]) == CODE_LABEL) 11415 LABEL_NUSES (operands[2])++; 11416}) 11417 11418(define_split 11419 [(set (match_operand:SI 0 "register_operand" "") 11420 (unspec:SI [(match_operand:SI 1 "register_operand" "") 11421 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI)) 11422 (clobber (match_scratch:SI 3 "")) 11423 (clobber (match_scratch:SI 4)) 11424 (use (reg:SI T_REG))] 11425 "TARGET_SH2 && reload_completed" 11426 [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA)) 11427 (parallel [(set (match_dup 0) 11428 (unspec:SI [(reg:SI R0_REG) (match_dup 1) 11429 (label_ref (match_dup 2))] UNSPEC_CASESI)) 11430 (clobber (match_dup 3))])] 11431{ 11432 if (GET_CODE (operands[2]) == CODE_LABEL) 11433 LABEL_NUSES (operands[2])++; 11434}) 11435 11436;; This may be replaced with casesi_worker_2 in sh_reorg for PIC. 11437;; The insn length is set to 8 for that case. 11438(define_insn "casesi_worker_1" 11439 [(set (match_operand:SI 0 "register_operand" "=r,r") 11440 (unspec:SI [(reg:SI R0_REG) 11441 (match_operand:SI 1 "register_operand" "0,r") 11442 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI)) 11443 (clobber (match_scratch:SI 3 "=X,1"))] 11444 "TARGET_SH1" 11445{ 11446 rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[2]))); 11447 11448 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); 11449 11450 switch (GET_MODE (diff_vec)) 11451 { 11452 case SImode: 11453 return "shll2 %1" "\n" 11454 " mov.l @(r0,%1),%0"; 11455 case HImode: 11456 return "add %1,%1" "\n" 11457 " mov.w @(r0,%1),%0"; 11458 case QImode: 11459 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned) 11460 return "mov.b @(r0,%1),%0" "\n" 11461 " extu.b %0,%0"; 11462 else 11463 return "mov.b @(r0,%1),%0"; 11464 11465 default: 11466 gcc_unreachable (); 11467 } 11468} 11469 [(set_attr_alternative "length" 11470 [(if_then_else (match_test "flag_pic") (const_int 8) (const_int 4)) 11471 (if_then_else (match_test "flag_pic") (const_int 8) (const_int 4))])]) 11472 11473(define_insn "casesi_worker_2" 11474 [(set (match_operand:SI 0 "register_operand" "=r,r") 11475 (unspec:SI [(reg:SI R0_REG) 11476 (match_operand:SI 1 "register_operand" "0,r") 11477 (label_ref (match_operand 2 "" "")) 11478 (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI)) 11479 (clobber (match_operand:SI 4 "" "=X,1"))] 11480 "TARGET_SH2 && reload_completed && flag_pic" 11481{ 11482 rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[2]))); 11483 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); 11484 11485 switch (GET_MODE (diff_vec)) 11486 { 11487 case SImode: 11488 return "shll2 %1" "\n" 11489 " add r0,%1" "\n" 11490 " mova %O3,r0" "\n" 11491 " mov.l @(r0,%1),%0"; 11492 case HImode: 11493 return "add %1,%1" "\n" 11494 " add r0,%1" "\n" 11495 " mova %O3,r0" "\n" 11496 " mov.w @(r0,%1),%0"; 11497 case QImode: 11498 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned) 11499 return "add r0,%1" "\n" 11500 " mova %O3,r0" "\n" 11501 " mov.b @(r0,%1),%0" "\n" 11502 " extu.b %0,%0"; 11503 else 11504 return "add r0,%1" "\n" 11505 " mova %O3,r0" "\n" 11506 " mov.b @(r0,%1),%0"; 11507 default: 11508 gcc_unreachable (); 11509 } 11510} 11511 [(set_attr "length" "8")]) 11512 11513(define_insn "casesi_shift_media" 11514 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 11515 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r") 11516 (unspec:DI [(label_ref:DI (match_operand 2 "" ""))] 11517 UNSPEC_CASESI)))] 11518 "TARGET_SHMEDIA" 11519{ 11520 rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[2]))); 11521 11522 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); 11523 11524 switch (GET_MODE (diff_vec)) 11525 { 11526 case SImode: 11527 return "shlli %1, 2, %0"; 11528 case HImode: 11529 return "shlli %1, 1, %0"; 11530 case QImode: 11531 if (rtx_equal_p (operands[0], operands[1])) 11532 return ""; 11533 return "add %1, r63, %0"; 11534 default: 11535 gcc_unreachable (); 11536 } 11537} 11538 [(set_attr "type" "arith_media")]) 11539 11540(define_insn "casesi_load_media" 11541 [(set (match_operand 0 "any_arith_reg_dest" "=r") 11542 (mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r") 11543 (match_operand:DI 2 "arith_reg_operand" "r") 11544 (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))] 11545 "TARGET_SHMEDIA" 11546{ 11547 rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[3]))); 11548 11549 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); 11550 11551 switch (GET_MODE (diff_vec)) 11552 { 11553 case SImode: 11554 return "ldx.l %1, %2, %0"; 11555 case HImode: 11556#if 0 11557 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned) 11558 return "ldx.uw %1, %2, %0"; 11559#endif 11560 return "ldx.w %1, %2, %0"; 11561 case QImode: 11562 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned) 11563 return "ldx.ub %1, %2, %0"; 11564 return "ldx.b %1, %2, %0"; 11565 default: 11566 gcc_unreachable (); 11567 } 11568} 11569 [(set_attr "type" "load_media")]) 11570 11571(define_expand "simple_return" 11572 [(simple_return)] 11573 "sh_can_use_simple_return_p ()") 11574 11575(define_expand "return" 11576 [(return)] 11577 "reload_completed && epilogue_completed" 11578{ 11579 if (TARGET_SHMEDIA) 11580 { 11581 emit_jump_insn (gen_return_media ()); 11582 DONE; 11583 } 11584 11585 if (TARGET_SHCOMPACT 11586 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))) 11587 { 11588 emit_jump_insn (gen_shcompact_return_tramp ()); 11589 DONE; 11590 } 11591}) 11592 11593(define_insn "*<code>_i" 11594 [(any_return)] 11595 "TARGET_SH1 && ! (TARGET_SHCOMPACT 11596 && (crtl->args.info.call_cookie 11597 & CALL_COOKIE_RET_TRAMP (1))) 11598 && reload_completed 11599 && ! sh_cfun_trap_exit_p ()" 11600{ 11601 if (TARGET_SH2A && (dbr_sequence_length () == 0) 11602 && !current_function_interrupt) 11603 return "rts/n"; 11604 else 11605 return "%@ %#"; 11606} 11607 [(set_attr "type" "return") 11608 (set_attr "needs_delay_slot" "yes")]) 11609 11610;; trapa has no delay slot. 11611(define_insn "*return_trapa" 11612 [(return)] 11613 "TARGET_SH1 && !TARGET_SHCOMPACT 11614 && reload_completed" 11615 "%@" 11616 [(set_attr "type" "return")]) 11617 11618(define_expand "shcompact_return_tramp" 11619 [(return)] 11620 "TARGET_SHCOMPACT 11621 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))" 11622{ 11623 rtx reg = gen_rtx_REG (Pmode, R0_REG); 11624 11625 function_symbol (reg, "__GCC_shcompact_return_trampoline", SFUNC_STATIC); 11626 emit_jump_insn (gen_shcompact_return_tramp_i ()); 11627 DONE; 11628}) 11629 11630(define_insn "shcompact_return_tramp_i" 11631 [(parallel [(return) (use (reg:SI R0_REG))])] 11632 "TARGET_SHCOMPACT 11633 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))" 11634 "jmp @r0%#" 11635 [(set_attr "type" "jump_ind") 11636 (set_attr "needs_delay_slot" "yes")]) 11637 11638(define_insn "return_media_i" 11639 [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])] 11640 "TARGET_SHMEDIA && reload_completed" 11641 "blink %0, r63" 11642 [(set_attr "type" "jump_media")]) 11643 11644(define_insn "return_media_rte" 11645 [(return)] 11646 "TARGET_SHMEDIA && reload_completed && current_function_interrupt" 11647 "rte" 11648 [(set_attr "type" "jump_media")]) 11649 11650(define_expand "return_media" 11651 [(return)] 11652 "TARGET_SHMEDIA && reload_completed" 11653{ 11654 int tr_regno = sh_media_register_for_return (); 11655 rtx tr; 11656 11657 if (current_function_interrupt) 11658 { 11659 emit_jump_insn (gen_return_media_rte ()); 11660 DONE; 11661 } 11662 if (tr_regno < 0) 11663 { 11664 rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG); 11665 11666 gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]); 11667 tr_regno = TR0_REG; 11668 tr = gen_rtx_REG (Pmode, tr_regno); 11669 emit_move_insn (tr, r18); 11670 } 11671 else 11672 tr = gen_rtx_REG (Pmode, tr_regno); 11673 11674 emit_jump_insn (gen_return_media_i (tr)); 11675 DONE; 11676}) 11677 11678(define_insn "shcompact_preserve_incoming_args" 11679 [(set (match_operand:SI 0 "register_operand" "+r") 11680 (unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))] 11681 "TARGET_SHCOMPACT" 11682 "" 11683 [(set_attr "length" "0")]) 11684 11685(define_insn "shcompact_incoming_args" 11686 [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS)) 11687 (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS)) 11688 (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS)) 11689 (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS)) 11690 (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS)) 11691 (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS)) 11692 (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS)) 11693 (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS)) 11694 (set (mem:BLK (reg:SI MACL_REG)) 11695 (unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS)) 11696 (use (reg:SI R0_REG)) 11697 (clobber (reg:SI R0_REG)) 11698 (clobber (reg:SI MACL_REG)) 11699 (clobber (reg:SI MACH_REG)) 11700 (clobber (reg:SI PR_REG))] 11701 "TARGET_SHCOMPACT" 11702 "jsr @r0%#" 11703 [(set_attr "needs_delay_slot" "yes")]) 11704 11705(define_insn "shmedia_save_restore_regs_compact" 11706 [(set (reg:SI SP_REG) 11707 (plus:SI (reg:SI SP_REG) 11708 (match_operand:SI 0 "immediate_operand" "i"))) 11709 (use (reg:SI R0_REG)) 11710 (clobber (reg:SI PR_REG))] 11711 "TARGET_SHCOMPACT 11712 && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST () 11713 || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())" 11714 "jsr @r0%#" 11715 [(set_attr "needs_delay_slot" "yes")]) 11716 11717(define_expand "prologue" 11718 [(const_int 0)] 11719 "" 11720{ 11721 sh_expand_prologue (); 11722 DONE; 11723}) 11724 11725(define_expand "epilogue" 11726 [(return)] 11727 "" 11728{ 11729 sh_expand_epilogue (false); 11730 if (TARGET_SHMEDIA 11731 || (TARGET_SHCOMPACT 11732 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))) 11733 { 11734 emit_jump_insn (gen_return ()); 11735 DONE; 11736 } 11737}) 11738 11739(define_expand "eh_return" 11740 [(use (match_operand 0 "register_operand" ""))] 11741 "" 11742{ 11743 rtx ra = operands[0]; 11744 11745 if (TARGET_SHMEDIA64) 11746 emit_insn (gen_eh_set_ra_di (ra)); 11747 else 11748 emit_insn (gen_eh_set_ra_si (ra)); 11749 11750 DONE; 11751}) 11752 11753;; Clobber the return address on the stack. We can't expand this 11754;; until we know where it will be put in the stack frame. 11755 11756(define_insn "eh_set_ra_si" 11757 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] 11758 UNSPECV_EH_RETURN) 11759 (clobber (match_scratch:SI 1 "=&r"))] 11760 "! TARGET_SHMEDIA64" 11761 "#") 11762 11763(define_insn "eh_set_ra_di" 11764 [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")] 11765 UNSPECV_EH_RETURN) 11766 (clobber (match_scratch:DI 1 "=&r"))] 11767 "TARGET_SHMEDIA64" 11768 "#") 11769 11770(define_split 11771 [(unspec_volatile [(match_operand 0 "register_operand" "")] 11772 UNSPECV_EH_RETURN) 11773 (clobber (match_scratch 1 ""))] 11774 "reload_completed" 11775 [(const_int 0)] 11776{ 11777 sh_set_return_address (operands[0], operands[1]); 11778 DONE; 11779}) 11780 11781(define_insn "blockage" 11782 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)] 11783 "" 11784 "" 11785 [(set_attr "length" "0")]) 11786 11787;; Define movml instructions for SH2A target. Currently they are 11788;; used to push and pop all banked registers only. 11789 11790(define_insn "movml_push_banked" 11791 [(set (match_operand:SI 0 "register_operand" "=r") 11792 (plus (match_dup 0) (const_int -32))) 11793 (set (mem:SI (plus:SI (match_dup 0) (const_int 28))) (reg:SI R7_REG)) 11794 (set (mem:SI (plus:SI (match_dup 0) (const_int 24))) (reg:SI R6_REG)) 11795 (set (mem:SI (plus:SI (match_dup 0) (const_int 20))) (reg:SI R5_REG)) 11796 (set (mem:SI (plus:SI (match_dup 0) (const_int 16))) (reg:SI R4_REG)) 11797 (set (mem:SI (plus:SI (match_dup 0) (const_int 12))) (reg:SI R3_REG)) 11798 (set (mem:SI (plus:SI (match_dup 0) (const_int 8))) (reg:SI R2_REG)) 11799 (set (mem:SI (plus:SI (match_dup 0) (const_int 4))) (reg:SI R1_REG)) 11800 (set (mem:SI (plus:SI (match_dup 0) (const_int 0))) (reg:SI R0_REG))] 11801 "TARGET_SH2A && REGNO (operands[0]) == 15" 11802 "movml.l r7,@-r15" 11803 [(set_attr "in_delay_slot" "no")]) 11804 11805(define_insn "movml_pop_banked" 11806 [(set (match_operand:SI 0 "register_operand" "=r") 11807 (plus (match_dup 0) (const_int 32))) 11808 (set (reg:SI R0_REG) (mem:SI (plus:SI (match_dup 0) (const_int -32)))) 11809 (set (reg:SI R1_REG) (mem:SI (plus:SI (match_dup 0) (const_int -28)))) 11810 (set (reg:SI R2_REG) (mem:SI (plus:SI (match_dup 0) (const_int -24)))) 11811 (set (reg:SI R3_REG) (mem:SI (plus:SI (match_dup 0) (const_int -20)))) 11812 (set (reg:SI R4_REG) (mem:SI (plus:SI (match_dup 0) (const_int -16)))) 11813 (set (reg:SI R5_REG) (mem:SI (plus:SI (match_dup 0) (const_int -12)))) 11814 (set (reg:SI R6_REG) (mem:SI (plus:SI (match_dup 0) (const_int -8)))) 11815 (set (reg:SI R7_REG) (mem:SI (plus:SI (match_dup 0) (const_int -4))))] 11816 "TARGET_SH2A && REGNO (operands[0]) == 15" 11817 "movml.l @r15+,r7" 11818 [(set_attr "in_delay_slot" "no")]) 11819 11820;; ------------------------------------------------------------------------ 11821;; Scc instructions 11822;; ------------------------------------------------------------------------ 11823 11824(define_insn "movt" 11825 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 11826 (match_operand:SI 1 "t_reg_operand"))] 11827 "TARGET_SH1" 11828 "movt %0" 11829 [(set_attr "type" "arith")]) 11830 11831(define_insn "movrt" 11832 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 11833 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))] 11834 "TARGET_SH2A" 11835 "movrt %0" 11836 [(set_attr "type" "arith")]) 11837 11838(define_expand "cstore4_media" 11839 [(set (match_operand:SI 0 "register_operand" "=r") 11840 (match_operator:SI 1 "sh_float_comparison_operator" 11841 [(match_operand 2 "logical_operand" "") 11842 (match_operand 3 "cmp_operand" "")]))] 11843 "TARGET_SHMEDIA" 11844{ 11845 machine_mode mode = GET_MODE (operands[2]); 11846 enum rtx_code code = GET_CODE (operands[1]); 11847 bool invert, swap; 11848 if (mode == VOIDmode) 11849 mode = GET_MODE (operands[3]); 11850 if (operands[2] == const0_rtx) 11851 { 11852 if (code == EQ || code == NE) 11853 operands[2] = operands[3], operands[3] = const0_rtx; 11854 } 11855 else 11856 operands[2] = force_reg (mode, operands[2]); 11857 if (operands[3] != const0_rtx) 11858 operands[3] = force_reg (mode, operands[3]); 11859 11860 switch (code) 11861 { 11862 case GEU: 11863 case GE: 11864 swap = invert = !FLOAT_MODE_P (mode); 11865 break; 11866 11867 case LEU: 11868 case LE: 11869 swap = FLOAT_MODE_P (mode), invert = !swap; 11870 break; 11871 11872 case LTU: 11873 case LT: 11874 swap = true, invert = false; 11875 break; 11876 11877 case GTU: 11878 case GT: 11879 case EQ: 11880 case UNORDERED: 11881 swap = invert = false; 11882 break; 11883 11884 case NE: 11885 swap = invert = true; 11886 break; 11887 11888 default: 11889 gcc_unreachable (); 11890 } 11891 11892 if (swap) 11893 { 11894 std::swap (operands[2], operands[3]); 11895 code = swap_condition (code); 11896 } 11897 11898 if (invert) 11899 { 11900 rtx tem = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0]; 11901 code = reverse_condition (code); 11902 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]); 11903 emit_insn (gen_cstore4_media (tem, operands[1], 11904 operands[2], operands[3])); 11905 code = EQ; 11906 operands[2] = tem; 11907 operands[3] = const0_rtx; 11908 } 11909 11910 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]); 11911}) 11912 11913(define_expand "cstoresi4" 11914 [(set (match_operand:SI 0 "register_operand" "=r") 11915 (match_operator:SI 1 "comparison_operator" 11916 [(match_operand:SI 2 "cmpsi_operand" "") 11917 (match_operand:SI 3 "arith_operand" "")]))] 11918 "TARGET_SH1 || TARGET_SHMEDIA" 11919{ 11920 if (TARGET_SHMEDIA) 11921 { 11922 emit_insn (gen_cstore4_media (operands[0], operands[1], 11923 operands[2], operands[3])); 11924 DONE; 11925 } 11926 11927 if (sh_expand_t_scc (operands)) 11928 DONE; 11929 11930 if (! currently_expanding_to_rtl) 11931 FAIL; 11932 11933 sh_emit_compare_and_set (operands, SImode); 11934 DONE; 11935}) 11936 11937(define_expand "cstoredi4" 11938 [(set (match_operand:SI 0 "register_operand" "=r") 11939 (match_operator:SI 1 "comparison_operator" 11940 [(match_operand:DI 2 "arith_operand" "") 11941 (match_operand:DI 3 "arith_operand" "")]))] 11942 "TARGET_SH2 || TARGET_SHMEDIA" 11943{ 11944 if (TARGET_SHMEDIA) 11945 { 11946 emit_insn (gen_cstore4_media (operands[0], operands[1], 11947 operands[2], operands[3])); 11948 DONE; 11949 } 11950 11951 if (sh_expand_t_scc (operands)) 11952 DONE; 11953 11954 if (! currently_expanding_to_rtl) 11955 FAIL; 11956 11957 sh_emit_compare_and_set (operands, DImode); 11958 DONE; 11959}) 11960 11961;; Move the complement of the T reg to a reg. 11962;; On SH2A the movrt insn can be used. 11963;; On anything else than SH2A this has to be done with multiple instructions. 11964;; One obvious way would be: 11965;; cmp/eq ... 11966;; movt r0 11967;; xor #1,r0 11968;; 11969;; However, this puts pressure on r0 in most cases and thus the following is 11970;; more appealing: 11971;; cmp/eq ... 11972;; mov #-1,temp 11973;; negc temp,dest 11974;; 11975;; If the constant -1 can be CSE-ed or lifted out of a loop it effectively 11976;; becomes a one instruction operation. Moreover, care must be taken that 11977;; the insn can still be combined with inverted compare and branch code 11978;; around it. On the other hand, if a function returns the complement of 11979;; a previous comparison result in the T bit, the xor #1,r0 approach might 11980;; lead to better code. 11981(define_expand "movnegt" 11982 [(set (match_operand:SI 0 "arith_reg_dest" "") 11983 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))] 11984 "TARGET_SH1" 11985{ 11986 if (TARGET_SH2A) 11987 emit_insn (gen_movrt (operands[0], operands[1])); 11988 else 11989 { 11990 rtx val = force_reg (SImode, gen_int_mode (-1, SImode)); 11991 emit_insn (gen_movrt_negc (operands[0], operands[1], val)); 11992 } 11993 DONE; 11994}) 11995 11996(define_insn_and_split "movrt_negc" 11997 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 11998 (xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1))) 11999 (set (reg:SI T_REG) (const_int 1)) 12000 (use (match_operand:SI 2 "arith_reg_operand" "r"))] 12001 "TARGET_SH1" 12002 "negc %2,%0" 12003 "&& !sh_in_recog_treg_set_expr ()" 12004 [(const_int 0)] 12005{ 12006 if (sh_split_movrt_negc_to_movt_xor (curr_insn, operands)) 12007 DONE; 12008 else 12009 FAIL; 12010} 12011 [(set_attr "type" "arith")]) 12012 12013;; The -1 constant will not be CSE-ed for the *movrt_negc pattern, but the 12014;; pattern can be used by the combine pass. Using a scratch reg for the 12015;; -1 constant results in slightly better register allocations compared to 12016;; generating a pseudo reg before reload. 12017(define_insn_and_split "*movrt_negc" 12018 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 12019 (xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1))) 12020 (clobber (match_scratch:SI 2 "=r")) 12021 (clobber (reg:SI T_REG))] 12022 "TARGET_SH1 && ! TARGET_SH2A" 12023 "#" 12024 "&& !sh_in_recog_treg_set_expr ()" 12025 [(const_int 0)] 12026{ 12027 if (sh_split_movrt_negc_to_movt_xor (curr_insn, operands)) 12028 DONE; 12029 else if (reload_completed) 12030 { 12031 emit_move_insn (operands[2], gen_int_mode (-1, SImode)); 12032 emit_insn (gen_movrt_negc (operands[0], operands[1], operands[2])); 12033 DONE; 12034 } 12035 else 12036 FAIL; 12037}) 12038 12039;; Store the negated T bit in a reg using r0 and xor. This one doesn't 12040;; clobber the T bit, which is useful when storing the T bit and the 12041;; negated T bit in parallel. On SH2A the movrt insn can be used for that. 12042;; Usually we don't want this insn to be matched, except for cases where the 12043;; T bit clobber is really not appreciated. Hence the extra use on T_REG. 12044(define_insn_and_split "movrt_xor" 12045 [(set (match_operand:SI 0 "arith_reg_dest" "=z") 12046 (xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1))) 12047 (use (reg:SI T_REG))] 12048 "TARGET_SH1" 12049 "#" 12050 "&& reload_completed" 12051 [(set (match_dup 0) (reg:SI T_REG)) 12052 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))]) 12053 12054;; Use negc to store the T bit in a MSB of a reg in the following way: 12055;; T = 0: 0x80000000 -> reg 12056;; T = 1: 0x7FFFFFFF -> reg 12057;; This works because 0 - 0x80000000 = 0x80000000. 12058(define_insn_and_split "*mov_t_msb_neg" 12059 [(set (match_operand:SI 0 "arith_reg_dest") 12060 (minus:SI (const_int -2147483648) ;; 0x80000000 12061 (match_operand 1 "treg_set_expr"))) 12062 (clobber (reg:SI T_REG))] 12063 "TARGET_SH1 && can_create_pseudo_p ()" 12064 "#" 12065 "&& 1" 12066 [(const_int 0)] 12067{ 12068 if (negt_reg_operand (operands[1], VOIDmode)) 12069 { 12070 emit_insn (gen_addc (operands[0], 12071 force_reg (SImode, const0_rtx), 12072 force_reg (SImode, GEN_INT (2147483647)))); 12073 DONE; 12074 } 12075 12076 sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn); 12077 if (ti.remove_trailing_nott ()) 12078 emit_insn (gen_addc (operands[0], 12079 force_reg (SImode, const0_rtx), 12080 force_reg (SImode, GEN_INT (2147483647)))); 12081 else 12082 emit_insn (gen_negc (operands[0], 12083 force_reg (SImode, GEN_INT (-2147483648LL)))); 12084 DONE; 12085}) 12086 12087;; 0x7fffffff + T 12088;; 0x7fffffff + (1-T) = 0 - 0x80000000 - T 12089(define_insn_and_split "*mov_t_msb_neg" 12090 [(set (match_operand:SI 0 "arith_reg_dest") 12091 (plus:SI (match_operand 1 "treg_set_expr") 12092 (const_int 2147483647))) ;; 0x7fffffff 12093 (clobber (reg:SI T_REG))] 12094 "TARGET_SH1" 12095 "#" 12096 "&& can_create_pseudo_p ()" 12097 [(const_int 0)] 12098{ 12099 if (negt_reg_operand (operands[1], VOIDmode)) 12100 { 12101 emit_insn (gen_negc (operands[0], 12102 force_reg (SImode, GEN_INT (-2147483648LL)))); 12103 DONE; 12104 } 12105 12106 sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn); 12107 if (ti.remove_trailing_nott ()) 12108 emit_insn (gen_negc (operands[0], 12109 force_reg (SImode, GEN_INT (-2147483648LL)))); 12110 else 12111 emit_insn (gen_addc (operands[0], 12112 force_reg (SImode, const0_rtx), 12113 force_reg (SImode, GEN_INT (2147483647)))); 12114 DONE; 12115}) 12116 12117(define_insn_and_split "*mov_t_msb_neg" 12118 [(set (match_operand:SI 0 "arith_reg_dest") 12119 (if_then_else:SI (match_operand 1 "treg_set_expr") 12120 (match_operand 2 "const_int_operand") 12121 (match_operand 3 "const_int_operand"))) 12122 (clobber (reg:SI T_REG))] 12123 "TARGET_SH1 && can_create_pseudo_p () 12124 && ((INTVAL (operands[2]) == -2147483648LL 12125 && INTVAL (operands[3]) == 2147483647LL) 12126 || (INTVAL (operands[2]) == 2147483647LL 12127 && INTVAL (operands[3]) == -2147483648LL))" 12128 "#" 12129 "&& 1" 12130 [(const_int 0)] 12131{ 12132 sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn); 12133 12134 if (INTVAL (operands[2]) == -2147483648LL) 12135 { 12136 if (ti.remove_trailing_nott ()) 12137 emit_insn (gen_negc (operands[0], 12138 force_reg (SImode, GEN_INT (-2147483648LL)))); 12139 else 12140 emit_insn (gen_addc (operands[0], 12141 force_reg (SImode, const0_rtx), 12142 force_reg (SImode, operands[3]))); 12143 DONE; 12144 } 12145 else if (INTVAL (operands[2]) == 2147483647LL) 12146 { 12147 if (ti.remove_trailing_nott ()) 12148 emit_insn (gen_addc (operands[0], 12149 force_reg (SImode, const0_rtx), 12150 force_reg (SImode, GEN_INT (2147483647LL)))); 12151 else 12152 emit_insn (gen_negc (operands[0], 12153 force_reg (SImode, GEN_INT (-2147483648LL)))); 12154 DONE; 12155 } 12156 else 12157 gcc_unreachable (); 12158}) 12159 12160;; The *negnegt pattern helps the combine pass to figure out how to fold 12161;; an explicit double T bit negation. 12162(define_insn_and_split "*negnegt" 12163 [(set (reg:SI T_REG) 12164 (eq:SI (match_operand 0 "negt_reg_operand" "") (const_int 0)))] 12165 "TARGET_SH1" 12166 "#" 12167 "" 12168 [(const_int 0)]) 12169 12170;; Store (negated) T bit as all zeros or ones in a reg. 12171;; subc Rn,Rn ! Rn = Rn - Rn - T; T = T 12172;; not Rn,Rn ! Rn = 0 - Rn 12173(define_insn_and_split "mov_neg_si_t" 12174 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 12175 (neg:SI (match_operand 1 "treg_set_expr")))] 12176 "TARGET_SH1" 12177{ 12178 gcc_assert (t_reg_operand (operands[1], VOIDmode)); 12179 return "subc %0,%0"; 12180} 12181 "&& can_create_pseudo_p () && !t_reg_operand (operands[1], VOIDmode)" 12182 [(const_int 0)] 12183{ 12184 sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn); 12185 emit_insn (gen_mov_neg_si_t (operands[0], get_t_reg_rtx ())); 12186 12187 if (ti.remove_trailing_nott ()) 12188 emit_insn (gen_one_cmplsi2 (operands[0], operands[0])); 12189 12190 DONE; 12191} 12192 [(set_attr "type" "arith")]) 12193 12194;; The *movtt pattern eliminates redundant T bit to T bit moves / tests. 12195(define_insn_and_split "*movtt" 12196 [(set (reg:SI T_REG) 12197 (eq:SI (match_operand 0 "t_reg_operand" "") (const_int 1)))] 12198 "TARGET_SH1" 12199 "#" 12200 "" 12201 [(const_int 0)]) 12202 12203;; Invert the T bit. 12204;; On SH2A we can use the nott insn. On anything else this must be done with 12205;; multiple insns like: 12206;; movt Rn 12207;; tst Rn,Rn 12208;; This requires an additional pseudo. The SH specific sh_treg_combine RTL 12209;; pass will look for this insn. Disallow using it if pseudos can't be 12210;; created. 12211;; Don't split the nott inside the splitting of a treg_set_expr, or else 12212;; surrounding insns might not see and recombine it. Defer the splitting 12213;; of the nott until after the whole insn containing the treg_set_expr 12214;; has been split. 12215(define_insn_and_split "nott" 12216 [(set (reg:SI T_REG) 12217 (xor:SI (match_operand:SI 0 "t_reg_operand") (const_int 1)))] 12218 "TARGET_SH2A || (TARGET_SH1 && can_create_pseudo_p ())" 12219{ 12220 gcc_assert (TARGET_SH2A); 12221 return "nott"; 12222} 12223 "!TARGET_SH2A && can_create_pseudo_p () && !sh_in_recog_treg_set_expr ()" 12224 [(set (match_dup 0) (reg:SI T_REG)) 12225 (set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))] 12226{ 12227 operands[0] = gen_reg_rtx (SImode); 12228}) 12229 12230;; Store T bit as MSB in a reg. 12231;; T = 0: 0x00000000 -> reg 12232;; T = 1: 0x80000000 -> reg 12233(define_insn_and_split "*movt_msb" 12234 [(set (match_operand:SI 0 "arith_reg_dest") 12235 (mult:SI (match_operand:SI 1 "t_reg_operand") 12236 (const_int -2147483648))) ;; 0xffffffff80000000 12237 (clobber (reg:SI T_REG))] 12238 "TARGET_SH1" 12239 "#" 12240 "&& 1" 12241 [(set (match_dup 0) (ashift:SI (reg:SI T_REG) (const_int 31)))]) 12242 12243;; Store inverted T bit as MSB in a reg. 12244;; T = 0: 0x80000000 -> reg 12245;; T = 1: 0x00000000 -> reg 12246;; On SH2A we can get away without clobbering the T_REG using the movrt insn. 12247;; On non SH2A we resort to the following sequence: 12248;; movt Rn 12249;; tst Rn,Rn 12250;; rotcr Rn 12251;; The T bit value will be modified during the sequence, but the rotcr insn 12252;; will restore its original value. 12253(define_insn_and_split "*negt_msb" 12254 [(set (match_operand:SI 0 "arith_reg_dest") 12255 (match_operand:SI 1 "negt_reg_shl31_operand"))] 12256 "TARGET_SH1" 12257 "#" 12258 "&& can_create_pseudo_p ()" 12259 [(const_int 0)] 12260{ 12261 rtx tmp = gen_reg_rtx (SImode); 12262 12263 if (TARGET_SH2A) 12264 { 12265 emit_insn (gen_movrt (tmp, get_t_reg_rtx ())); 12266 emit_insn (gen_rotrsi3 (operands[0], tmp, const1_rtx)); 12267 } 12268 else 12269 { 12270 emit_move_insn (tmp, get_t_reg_rtx ()); 12271 emit_insn (gen_cmpeqsi_t (tmp, const0_rtx)); 12272 emit_insn (gen_rotcr (operands[0], tmp, get_t_reg_rtx ())); 12273 } 12274 DONE; 12275}) 12276 12277;; The *cset_zero patterns convert optimizations such as 12278;; "if (test) x = 0;" 12279;; to 12280;; "x &= -(test == 0);" 12281;; back to conditional branch sequences if zero-displacement branches 12282;; are enabled. 12283;; FIXME: These patterns can be removed when conditional execution patterns 12284;; are implemented, since ifcvt will not perform these optimizations if 12285;; conditional execution is supported. 12286(define_insn "*cset_zero" 12287 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 12288 (and:SI (plus:SI (match_operand:SI 1 "t_reg_operand") 12289 (const_int -1)) 12290 (match_operand:SI 2 "arith_reg_operand" "0")))] 12291 "TARGET_SH1 && TARGET_ZDCBRANCH" 12292{ 12293 return "bf 0f" "\n" 12294 " mov #0,%0" "\n" 12295 "0:"; 12296} 12297 [(set_attr "type" "arith") ;; poor approximation 12298 (set_attr "length" "4")]) 12299 12300(define_insn "*cset_zero" 12301 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 12302 (if_then_else:SI (match_operand:SI 1 "cbranch_treg_value") 12303 (match_operand:SI 2 "arith_reg_operand" "0") 12304 (const_int 0)))] 12305 "TARGET_SH1 && TARGET_ZDCBRANCH" 12306{ 12307 int tval = sh_eval_treg_value (operands[1]); 12308 if (tval == true) 12309 return "bt 0f" "\n" 12310 " mov #0,%0" "\n" 12311 "0:"; 12312 else if (tval == false) 12313 return "bf 0f" "\n" 12314 " mov #0,%0" "\n" 12315 "0:"; 12316 else 12317 gcc_unreachable (); 12318} 12319 [(set_attr "type" "arith") ;; poor approximation 12320 (set_attr "length" "4")]) 12321 12322(define_expand "cstoresf4" 12323 [(set (match_operand:SI 0 "register_operand" "=r") 12324 (match_operator:SI 1 "sh_float_comparison_operator" 12325 [(match_operand:SF 2 "arith_operand" "") 12326 (match_operand:SF 3 "arith_operand" "")]))] 12327 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 12328{ 12329 if (TARGET_SHMEDIA) 12330 { 12331 emit_insn (gen_cstore4_media (operands[0], operands[1], 12332 operands[2], operands[3])); 12333 DONE; 12334 } 12335 12336 if (! currently_expanding_to_rtl) 12337 FAIL; 12338 12339 sh_emit_compare_and_set (operands, SFmode); 12340 DONE; 12341}) 12342 12343(define_expand "cstoredf4" 12344 [(set (match_operand:SI 0 "register_operand" "=r") 12345 (match_operator:SI 1 "sh_float_comparison_operator" 12346 [(match_operand:DF 2 "arith_operand" "") 12347 (match_operand:DF 3 "arith_operand" "")]))] 12348 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 12349{ 12350 if (TARGET_SHMEDIA) 12351 { 12352 emit_insn (gen_cstore4_media (operands[0], operands[1], 12353 operands[2], operands[3])); 12354 DONE; 12355 } 12356 12357 if (! currently_expanding_to_rtl) 12358 FAIL; 12359 12360 sh_emit_compare_and_set (operands, DFmode); 12361 DONE; 12362}) 12363 12364;; Sometimes the T bit result of insns is needed in normal registers. 12365;; Instead of open coding all the pattern variations, use the treg_set_expr 12366;; predicate to match any T bit output insn and split it out after. 12367;; This pattern should be below all other related patterns so that it is 12368;; considered as a last resort option during matching. This allows 12369;; overriding it with special case patterns. 12370(define_insn_and_split "any_treg_expr_to_reg" 12371 [(set (match_operand:SI 0 "arith_reg_dest") 12372 (match_operand 1 "treg_set_expr")) 12373 (clobber (reg:SI T_REG))] 12374 "TARGET_SH1 && can_create_pseudo_p ()" 12375 "#" 12376 "&& !sh_in_recog_treg_set_expr ()" 12377 [(const_int 0)] 12378{ 12379 if (dump_file) 12380 fprintf (dump_file, "splitting any_treg_expr_to_reg\n"); 12381 12382 if (t_reg_operand (operands[1], VOIDmode)) 12383 { 12384 if (dump_file) 12385 fprintf (dump_file, "t_reg_operand: emitting movt\n"); 12386 emit_insn (gen_movt (operands[0], get_t_reg_rtx ())); 12387 DONE; 12388 } 12389 if (negt_reg_operand (operands[1], VOIDmode)) 12390 { 12391 if (dump_file) 12392 fprintf (dump_file, "negt_reg_operand: emitting movrt\n"); 12393 emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ())); 12394 DONE; 12395 } 12396 12397 /* If the split out insns ended with a nott, emit a movrt sequence, 12398 otherwise a normal movt. */ 12399 sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn); 12400 rtx_insn* i = NULL; 12401 if (ti.remove_trailing_nott ()) 12402 { 12403 /* Emit this same insn_and_split again. However, the next time it 12404 is split, it will emit the actual negc/movrt insn. This gives 12405 other surrounding insns the chance to see the trailing movrt. */ 12406 if (dump_file) 12407 fprintf (dump_file, 12408 "any_treg_expr_to_reg: replacing trailing nott with movrt\n"); 12409 i = emit_insn (gen_any_treg_expr_to_reg ( 12410 operands[0], gen_rtx_XOR (SImode, get_t_reg_rtx (), 12411 const1_rtx))); 12412 } 12413 else 12414 { 12415 i = emit_insn (gen_movt (operands[0], get_t_reg_rtx ())); 12416 if (dump_file) 12417 fprintf (dump_file, "any_treg_expr_to_reg: appending movt\n"); 12418 } 12419 12420 add_reg_note (i, REG_UNUSED, get_t_reg_rtx ()); 12421 DONE; 12422}) 12423 12424;; ------------------------------------------------------------------------- 12425;; Instructions to cope with inline literal tables 12426;; ------------------------------------------------------------------------- 12427 12428;; 2 byte integer in line 12429(define_insn "consttable_2" 12430 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g") 12431 (match_operand 1 "" "")] 12432 UNSPECV_CONST2)] 12433 "" 12434{ 12435 if (operands[1] != const0_rtx) 12436 assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1); 12437 return ""; 12438} 12439 [(set_attr "length" "2") 12440 (set_attr "in_delay_slot" "no")]) 12441 12442;; 4 byte integer in line 12443(define_insn "consttable_4" 12444 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g") 12445 (match_operand 1 "" "")] 12446 UNSPECV_CONST4)] 12447 "" 12448{ 12449 if (operands[1] != const0_rtx) 12450 { 12451 assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1); 12452 mark_symbol_refs_as_used (operands[0]); 12453 } 12454 return ""; 12455} 12456 [(set_attr "length" "4") 12457 (set_attr "in_delay_slot" "no")]) 12458 12459;; 8 byte integer in line 12460(define_insn "consttable_8" 12461 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g") 12462 (match_operand 1 "" "")] 12463 UNSPECV_CONST8)] 12464 "" 12465{ 12466 if (operands[1] != const0_rtx) 12467 assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1); 12468 return ""; 12469} 12470 [(set_attr "length" "8") 12471 (set_attr "in_delay_slot" "no")]) 12472 12473;; 4 byte floating point 12474(define_insn "consttable_sf" 12475 [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g") 12476 (match_operand 1 "" "")] 12477 UNSPECV_CONST4)] 12478 "" 12479{ 12480 if (operands[1] != const0_rtx) 12481 { 12482 REAL_VALUE_TYPE d; 12483 REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]); 12484 assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode)); 12485 } 12486 return ""; 12487} 12488 [(set_attr "length" "4") 12489 (set_attr "in_delay_slot" "no")]) 12490 12491;; 8 byte floating point 12492(define_insn "consttable_df" 12493 [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g") 12494 (match_operand 1 "" "")] 12495 UNSPECV_CONST8)] 12496 "" 12497{ 12498 if (operands[1] != const0_rtx) 12499 { 12500 REAL_VALUE_TYPE d; 12501 REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]); 12502 assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode)); 12503 } 12504 return ""; 12505} 12506 [(set_attr "length" "8") 12507 (set_attr "in_delay_slot" "no")]) 12508 12509;; Alignment is needed for some constant tables; it may also be added for 12510;; Instructions at the start of loops, or after unconditional branches. 12511;; ??? We would get more accurate lengths if we did instruction 12512;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used 12513;; here is too conservative. 12514 12515;; align to a two byte boundary 12516(define_expand "align_2" 12517 [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)] 12518 "" 12519 "") 12520 12521;; Align to a four byte boundary. 12522;; align_4 and align_log are instructions for the starts of loops, or 12523;; after unconditional branches, which may take up extra room. 12524(define_expand "align_4" 12525 [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)] 12526 "" 12527 "") 12528 12529;; Align to a cache line boundary. 12530(define_insn "align_log" 12531 [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)] 12532 "" 12533 "" 12534 [(set_attr "length" "0") 12535 (set_attr "in_delay_slot" "no")]) 12536 12537;; Emitted at the end of the literal table, used to emit the 12538;; 32bit branch labels if needed. 12539(define_insn "consttable_end" 12540 [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)] 12541 "" 12542{ 12543 return output_jump_label_table (); 12544} 12545 [(set_attr "in_delay_slot" "no")]) 12546 12547;; Emitted at the end of the window in the literal table. 12548(define_insn "consttable_window_end" 12549 [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)] 12550 "" 12551 "" 12552 [(set_attr "length" "0") 12553 (set_attr "in_delay_slot" "no")]) 12554 12555;; ------------------------------------------------------------------------- 12556;; Minimum / maximum operations. 12557;; ------------------------------------------------------------------------- 12558 12559;; The SH2A clips.b and clips.w insns do a signed min-max function. If smin 12560;; and smax standard name patterns are defined, they will be used during 12561;; initial expansion and combine will then be able to form the actual min-max 12562;; pattern. 12563;; The clips.b and clips.w set the SR.CS bit if the value in the register is 12564;; clipped, but there is currently no way of making use of this information. 12565;; The only way to read or reset the SR.CS bit is by accessing the SR. 12566(define_expand "<code>si3" 12567 [(parallel [(set (match_operand:SI 0 "arith_reg_dest") 12568 (SMIN_SMAX:SI (match_operand:SI 1 "arith_reg_operand") 12569 (match_operand 2 "const_int_operand"))) 12570 (clobber (reg:SI T_REG))])] 12571 "TARGET_SH2A" 12572{ 12573 /* Force the comparison value into a register, because greater-than 12574 comparisons can work only on registers. Combine will be able to pick up 12575 the constant value from the REG_EQUAL note when trying to form a min-max 12576 pattern. */ 12577 operands[2] = force_reg (SImode, operands[2]); 12578}) 12579 12580;; Convert 12581;; smax (smin (...)) 12582;; to 12583;; smin (smax (...)) 12584(define_insn_and_split "*clips" 12585 [(set (match_operand:SI 0 "arith_reg_dest") 12586 (smax:SI (smin:SI (match_operand:SI 1 "arith_reg_operand") 12587 (match_operand 2 "clips_max_const_int")) 12588 (match_operand 3 "clips_min_const_int")))] 12589 "TARGET_SH2A" 12590 "#" 12591 "&& 1" 12592 [(set (match_dup 0) 12593 (smin:SI (smax:SI (match_dup 1) (match_dup 3)) (match_dup 2)))]) 12594 12595(define_insn "*clips" 12596 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 12597 (smin:SI (smax:SI (match_operand:SI 1 "arith_reg_operand" "0") 12598 (match_operand 2 "clips_min_const_int")) 12599 (match_operand 3 "clips_max_const_int")))] 12600 "TARGET_SH2A" 12601{ 12602 if (INTVAL (operands[3]) == 127) 12603 return "clips.b %0"; 12604 else if (INTVAL (operands[3]) == 32767) 12605 return "clips.w %0"; 12606 else 12607 gcc_unreachable (); 12608} 12609 [(set_attr "type" "arith")]) 12610 12611;; If the expanded smin or smax patterns were not combined, split them into 12612;; a compare and branch sequence, because there are no real smin or smax 12613;; insns. 12614(define_insn_and_split "*<code>si3" 12615 [(set (match_operand:SI 0 "arith_reg_dest") 12616 (SMIN_SMAX:SI (match_operand:SI 1 "arith_reg_operand") 12617 (match_operand:SI 2 "arith_reg_or_0_or_1_operand"))) 12618 (clobber (reg:SI T_REG))] 12619 "TARGET_SH2A && can_create_pseudo_p ()" 12620 "#" 12621 "&& 1" 12622 [(const_int 0)] 12623{ 12624 rtx skip_label = gen_label_rtx (); 12625 emit_move_insn (operands[0], operands[1]); 12626 12627 rtx cmp_val = operands[2]; 12628 if (satisfies_constraint_M (cmp_val)) 12629 cmp_val = const0_rtx; 12630 12631 emit_insn (gen_cmpgtsi_t (operands[0], cmp_val)); 12632 emit_jump_insn (<CODE> == SMIN 12633 ? gen_branch_false (skip_label) 12634 : gen_branch_true (skip_label)); 12635 12636 emit_label_after (skip_label, emit_move_insn (operands[0], operands[2])); 12637 DONE; 12638}) 12639 12640;; The SH2A clipu.b and clipu.w insns can be used to implement a min function 12641;; with a register and a constant. 12642;; The clipu.b and clipu.w set the SR.CS bit if the value in the register is 12643;; clipped, but there is currently no way of making use of this information. 12644;; The only way to read or reset the SR.CS bit is by accessing the SR. 12645(define_expand "uminsi3" 12646 [(set (match_operand:SI 0 "arith_reg_dest") 12647 (umin:SI (match_operand:SI 1 "arith_reg_operand") 12648 (match_operand 2 "const_int_operand")))] 12649 "TARGET_SH2A" 12650{ 12651 if (INTVAL (operands[2]) == 1) 12652 { 12653 emit_insn (gen_clipu_one (operands[0], operands[1])); 12654 DONE; 12655 } 12656 else if (! clipu_max_const_int (operands[2], VOIDmode)) 12657 FAIL; 12658}) 12659 12660(define_insn "*clipu" 12661 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 12662 (umin:SI (match_operand:SI 1 "arith_reg_operand" "0") 12663 (match_operand 2 "clipu_max_const_int")))] 12664 "TARGET_SH2A" 12665{ 12666 if (INTVAL (operands[2]) == 255) 12667 return "clipu.b %0"; 12668 else if (INTVAL (operands[2]) == 65535) 12669 return "clipu.w %0"; 12670 else 12671 gcc_unreachable (); 12672} 12673 [(set_attr "type" "arith")]) 12674 12675(define_insn_and_split "clipu_one" 12676 [(set (match_operand:SI 0 "arith_reg_dest") 12677 (umin:SI (match_operand:SI 1 "arith_reg_operand") (const_int 1))) 12678 (clobber (reg:SI T_REG))] 12679 "TARGET_SH2A" 12680 "#" 12681 "&& can_create_pseudo_p ()" 12682 [(const_int 0)] 12683{ 12684 emit_insn (gen_cmpeqsi_t (operands[1], const0_rtx)); 12685 emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ())); 12686 DONE; 12687}) 12688 12689;; ------------------------------------------------------------------------- 12690;; Misc 12691;; ------------------------------------------------------------------------- 12692 12693;; String/block move insn. 12694 12695(define_expand "movmemsi" 12696 [(parallel [(set (mem:BLK (match_operand:BLK 0)) 12697 (mem:BLK (match_operand:BLK 1))) 12698 (use (match_operand:SI 2 "nonmemory_operand")) 12699 (use (match_operand:SI 3 "immediate_operand")) 12700 (clobber (reg:SI PR_REG)) 12701 (clobber (reg:SI R4_REG)) 12702 (clobber (reg:SI R5_REG)) 12703 (clobber (reg:SI R0_REG))])] 12704 "TARGET_SH1 && ! TARGET_SH5" 12705{ 12706 if (expand_block_move (operands)) 12707 DONE; 12708 else 12709 FAIL; 12710}) 12711 12712(define_insn "block_move_real" 12713 [(parallel [(set (mem:BLK (reg:SI R4_REG)) 12714 (mem:BLK (reg:SI R5_REG))) 12715 (use (match_operand:SI 0 "arith_reg_operand" "r")) 12716 (clobber (reg:SI PR_REG)) 12717 (clobber (reg:SI R0_REG))])] 12718 "TARGET_SH1 && ! TARGET_HARD_SH4" 12719 "jsr @%0%#" 12720 [(set_attr "type" "sfunc") 12721 (set_attr "needs_delay_slot" "yes")]) 12722 12723(define_insn "block_lump_real" 12724 [(parallel [(set (mem:BLK (reg:SI R4_REG)) 12725 (mem:BLK (reg:SI R5_REG))) 12726 (use (match_operand:SI 0 "arith_reg_operand" "r")) 12727 (use (reg:SI R6_REG)) 12728 (clobber (reg:SI PR_REG)) 12729 (clobber (reg:SI T_REG)) 12730 (clobber (reg:SI R4_REG)) 12731 (clobber (reg:SI R5_REG)) 12732 (clobber (reg:SI R6_REG)) 12733 (clobber (reg:SI R0_REG))])] 12734 "TARGET_SH1 && ! TARGET_HARD_SH4" 12735 "jsr @%0%#" 12736 [(set_attr "type" "sfunc") 12737 (set_attr "needs_delay_slot" "yes")]) 12738 12739(define_insn "block_move_real_i4" 12740 [(parallel [(set (mem:BLK (reg:SI R4_REG)) 12741 (mem:BLK (reg:SI R5_REG))) 12742 (use (match_operand:SI 0 "arith_reg_operand" "r")) 12743 (clobber (reg:SI PR_REG)) 12744 (clobber (reg:SI R0_REG)) 12745 (clobber (reg:SI R1_REG)) 12746 (clobber (reg:SI R2_REG))])] 12747 "TARGET_HARD_SH4" 12748 "jsr @%0%#" 12749 [(set_attr "type" "sfunc") 12750 (set_attr "needs_delay_slot" "yes")]) 12751 12752(define_insn "block_lump_real_i4" 12753 [(parallel [(set (mem:BLK (reg:SI R4_REG)) 12754 (mem:BLK (reg:SI R5_REG))) 12755 (use (match_operand:SI 0 "arith_reg_operand" "r")) 12756 (use (reg:SI R6_REG)) 12757 (clobber (reg:SI PR_REG)) 12758 (clobber (reg:SI T_REG)) 12759 (clobber (reg:SI R4_REG)) 12760 (clobber (reg:SI R5_REG)) 12761 (clobber (reg:SI R6_REG)) 12762 (clobber (reg:SI R0_REG)) 12763 (clobber (reg:SI R1_REG)) 12764 (clobber (reg:SI R2_REG)) 12765 (clobber (reg:SI R3_REG))])] 12766 "TARGET_HARD_SH4" 12767 "jsr @%0%#" 12768 [(set_attr "type" "sfunc") 12769 (set_attr "needs_delay_slot" "yes")]) 12770 12771;; byte compare pattern 12772;; temp = a ^ b; 12773;; !((temp & 0xF000) && (temp & 0x0F00) && (temp & 0x00F0) && (temp & 0x000F)) 12774(define_insn "cmpstr_t" 12775 [(set (reg:SI T_REG) 12776 (eq:SI (and:SI 12777 (and:SI 12778 (and:SI 12779 (zero_extract:SI 12780 (xor:SI (match_operand:SI 0 "arith_reg_operand" "r") 12781 (match_operand:SI 1 "arith_reg_operand" "r")) 12782 (const_int 8) (const_int 0)) 12783 (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1)) 12784 (const_int 8) (const_int 8))) 12785 (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1)) 12786 (const_int 8) (const_int 16))) 12787 (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1)) 12788 (const_int 8) (const_int 24))) 12789 (const_int 0)))] 12790 "TARGET_SH1" 12791 "cmp/str %0,%1" 12792 [(set_attr "type" "mt_group")]) 12793 12794(define_expand "cmpstrsi" 12795 [(set (match_operand:SI 0 "register_operand") 12796 (compare:SI (match_operand:BLK 1 "memory_operand") 12797 (match_operand:BLK 2 "memory_operand"))) 12798 (use (match_operand 3 "immediate_operand"))] 12799 "TARGET_SH1 && optimize" 12800{ 12801 if (! optimize_insn_for_size_p () && sh_expand_cmpstr (operands)) 12802 DONE; 12803 else 12804 FAIL; 12805}) 12806 12807(define_expand "cmpstrnsi" 12808 [(set (match_operand:SI 0 "register_operand") 12809 (compare:SI (match_operand:BLK 1 "memory_operand") 12810 (match_operand:BLK 2 "memory_operand"))) 12811 (use (match_operand:SI 3 "immediate_operand")) 12812 (use (match_operand:SI 4 "immediate_operand"))] 12813 "TARGET_SH1 && optimize" 12814{ 12815 if (! optimize_insn_for_size_p () && sh_expand_cmpnstr (operands)) 12816 DONE; 12817 else 12818 FAIL; 12819}) 12820 12821(define_expand "strlensi" 12822 [(set (match_operand:SI 0 "register_operand") 12823 (unspec:SI [(match_operand:BLK 1 "memory_operand") 12824 (match_operand:SI 2 "immediate_operand") 12825 (match_operand:SI 3 "immediate_operand")] 12826 UNSPEC_BUILTIN_STRLEN))] 12827 "TARGET_SH1 && optimize" 12828{ 12829 if (! optimize_insn_for_size_p () && sh_expand_strlen (operands)) 12830 DONE; 12831 else 12832 FAIL; 12833}) 12834 12835(define_expand "setmemqi" 12836 [(parallel [(set (match_operand:BLK 0 "memory_operand") 12837 (match_operand 2 "const_int_operand")) 12838 (use (match_operand:QI 1 "const_int_operand")) 12839 (use (match_operand:QI 3 "const_int_operand"))])] 12840 "TARGET_SH1 && optimize" 12841 { 12842 if (optimize_insn_for_size_p ()) 12843 FAIL; 12844 12845 sh_expand_setmem (operands); 12846 DONE; 12847 }) 12848 12849 12850;; ------------------------------------------------------------------------- 12851;; Floating point instructions. 12852;; ------------------------------------------------------------------------- 12853 12854;; FIXME: For now we disallow any memory operands for fpscr loads/stores, 12855;; except for post-inc loads and pre-dec stores for push/pop purposes. 12856;; This avoids problems with reload. As a consequence, user initiated fpscr 12857;; stores to memory will always be ferried through a general register. 12858;; User initiated fpscr loads always have to undergo bit masking to preserve 12859;; the current fpu mode settings for the compiler generated code. Thus such 12860;; fpscr loads will always have to go through general registers anyways. 12861(define_insn "lds_fpscr" 12862 [(set (reg:SI FPSCR_REG) 12863 (match_operand:SI 0 "fpscr_movsrc_operand" "r,>")) 12864 (set (reg:SI FPSCR_STAT_REG) 12865 (unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_STAT)) 12866 (set (reg:SI FPSCR_MODES_REG) 12867 (unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))] 12868 "TARGET_FPU_ANY" 12869 "@ 12870 lds %0,fpscr 12871 lds.l %0,fpscr" 12872 [(set_attr "type" "gp_fpscr,mem_fpscr")]) 12873 12874;; A move fpscr -> reg schedules like a move mac -> reg. Thus we use mac_gp 12875;; type for it. 12876(define_insn "sts_fpscr" 12877 [(set (match_operand:SI 0 "fpscr_movdst_operand" "=r,<") 12878 (reg:SI FPSCR_REG)) 12879 (use (reg:SI FPSCR_STAT_REG)) 12880 (use (reg:SI FPSCR_MODES_REG))] 12881 "TARGET_FPU_ANY" 12882 "@ 12883 sts fpscr,%0 12884 sts.l fpscr,%0" 12885 [(set_attr "type" "mac_gp,fstore")]) 12886 12887(define_expand "set_fpscr" 12888 [(parallel [(set (reg:SI FPSCR_REG) 12889 (match_operand:SI 0 "general_operand")) 12890 (set (reg:SI FPSCR_STAT_REG) 12891 (unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))])] 12892 "TARGET_FPU_ANY" 12893{ 12894 /* We have to mask out the FR, SZ and PR bits. To do that, we need to 12895 get the current FPSCR value first. 12896 (a & ~mask) | (b & mask) = a ^ ((a ^ b) & mask) */ 12897 12898 rtx mask = force_reg (SImode, GEN_INT (FPSCR_FR | FPSCR_SZ | FPSCR_PR)); 12899 12900 rtx a = force_reg (SImode, operands[0]); 12901 12902 rtx b = gen_reg_rtx (SImode); 12903 emit_insn (gen_sts_fpscr (b)); 12904 12905 rtx a_xor_b = gen_reg_rtx (SImode); 12906 emit_insn (gen_xorsi3 (a_xor_b, a, b)); 12907 12908 rtx a_xor_b_and_mask = gen_reg_rtx (SImode); 12909 emit_insn (gen_andsi3 (a_xor_b_and_mask, a_xor_b, mask)); 12910 12911 rtx r = gen_reg_rtx (SImode); 12912 emit_insn (gen_xorsi3 (r, a_xor_b_and_mask, a)); 12913 emit_insn (gen_lds_fpscr (r)); 12914 12915 DONE; 12916}) 12917 12918;; ??? This uses the fp unit, but has no type indicating that. 12919;; If we did that, this would either give a bogus latency or introduce 12920;; a bogus FIFO constraint. 12921;; Since this insn is currently only used for prologues/epilogues, 12922;; it is probably best to claim no function unit, which matches the 12923;; current setting. 12924(define_insn "toggle_sz" 12925 [(set (reg:SI FPSCR_REG) 12926 (xor:SI (reg:SI FPSCR_REG) (const_int FPSCR_SZ))) 12927 (set (reg:SI FPSCR_MODES_REG) 12928 (unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))] 12929 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 12930 "fschg" 12931 [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")]) 12932 12933;; Toggle FPU precision PR mode. 12934 12935(define_insn "toggle_pr" 12936 [(set (reg:SI FPSCR_REG) 12937 (xor:SI (reg:SI FPSCR_REG) (const_int FPSCR_PR))) 12938 (set (reg:SI FPSCR_MODES_REG) 12939 (unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))] 12940 "TARGET_SH4A_FP" 12941 "fpchg" 12942 [(set_attr "type" "fpscr_toggle")]) 12943 12944(define_expand "addsf3" 12945 [(set (match_operand:SF 0 "fp_arith_reg_operand") 12946 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand") 12947 (match_operand:SF 2 "fp_arith_reg_operand")))] 12948 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 12949{ 12950 if (TARGET_SH2E) 12951 { 12952 emit_insn (gen_addsf3_i (operands[0], operands[1], operands[2])); 12953 DONE; 12954 } 12955}) 12956 12957(define_insn "*addsf3_media" 12958 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 12959 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f") 12960 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 12961 "TARGET_SHMEDIA_FPU" 12962 "fadd.s %1, %2, %0" 12963 [(set_attr "type" "fparith_media")]) 12964 12965(define_insn_and_split "unary_sf_op" 12966 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f") 12967 (vec_select:V2SF 12968 (vec_concat:V2SF 12969 (vec_select:SF 12970 (match_dup 0) 12971 (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))])) 12972 (match_operator:SF 2 "unary_float_operator" 12973 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f") 12974 (parallel [(match_operand 4 12975 "const_int_operand" "n")]))])) 12976 (parallel [(not:BI (match_dup 3)) (match_dup 3)])))] 12977 "TARGET_SHMEDIA_FPU" 12978 "#" 12979 "TARGET_SHMEDIA_FPU && reload_completed" 12980 [(set (match_dup 5) (match_dup 6))] 12981{ 12982 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1; 12983 rtx op1 = gen_rtx_REG (SFmode, 12984 (true_regnum (operands[1]) 12985 + (INTVAL (operands[4]) ^ endian))); 12986 12987 operands[7] = gen_rtx_REG (SFmode, 12988 (true_regnum (operands[0]) 12989 + (INTVAL (operands[3]) ^ endian))); 12990 operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1); 12991} 12992 [(set_attr "type" "fparith_media")]) 12993 12994(define_insn_and_split "binary_sf_op0" 12995 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f") 12996 (vec_concat:V2SF 12997 (match_operator:SF 3 "binary_float_operator" 12998 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f") 12999 (parallel [(const_int 0)])) 13000 (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f") 13001 (parallel [(const_int 0)]))]) 13002 (vec_select:SF 13003 (match_dup 0) 13004 (parallel [(const_int 1)]))))] 13005 "TARGET_SHMEDIA_FPU" 13006 "#" 13007 "&& reload_completed" 13008 [(set (match_dup 4) (match_dup 5))] 13009{ 13010 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1; 13011 rtx op1 = gen_rtx_REG (SFmode, 13012 true_regnum (operands[1]) + endian); 13013 rtx op2 = gen_rtx_REG (SFmode, 13014 true_regnum (operands[2]) + endian); 13015 13016 operands[4] = gen_rtx_REG (SFmode, 13017 true_regnum (operands[0]) + endian); 13018 operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2); 13019} 13020 [(set_attr "type" "fparith_media")]) 13021 13022(define_insn_and_split "binary_sf_op1" 13023 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f") 13024 (vec_concat:V2SF 13025 (vec_select:SF 13026 (match_dup 0) 13027 (parallel [(const_int 0)])) 13028 (match_operator:SF 3 "binary_float_operator" 13029 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f") 13030 (parallel [(const_int 1)])) 13031 (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f") 13032 (parallel [(const_int 1)]))])))] 13033 "TARGET_SHMEDIA_FPU" 13034 "#" 13035 "&& reload_completed" 13036 [(set (match_dup 4) (match_dup 5))] 13037{ 13038 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1; 13039 rtx op1 = gen_rtx_REG (SFmode, true_regnum (operands[1]) + (1 ^ endian)); 13040 rtx op2 = gen_rtx_REG (SFmode, true_regnum (operands[2]) + (1 ^ endian)); 13041 13042 operands[4] = gen_rtx_REG (SFmode, true_regnum (operands[0]) + (1 ^ endian)); 13043 operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2); 13044} 13045 [(set_attr "type" "fparith_media")]) 13046 13047(define_insn "addsf3_i" 13048 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13049 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0") 13050 (match_operand:SF 2 "fp_arith_reg_operand" "f"))) 13051 (clobber (reg:SI FPSCR_STAT_REG)) 13052 (use (reg:SI FPSCR_MODES_REG))] 13053 "TARGET_SH2E" 13054 "fadd %2,%0" 13055 [(set_attr "type" "fp") 13056 (set_attr "fp_mode" "single")]) 13057 13058(define_expand "subsf3" 13059 [(set (match_operand:SF 0 "fp_arith_reg_operand" "") 13060 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "") 13061 (match_operand:SF 2 "fp_arith_reg_operand" "")))] 13062 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 13063{ 13064 if (TARGET_SH2E) 13065 { 13066 emit_insn (gen_subsf3_i (operands[0], operands[1], operands[2])); 13067 DONE; 13068 } 13069}) 13070 13071(define_insn "*subsf3_media" 13072 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13073 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f") 13074 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 13075 "TARGET_SHMEDIA_FPU" 13076 "fsub.s %1, %2, %0" 13077 [(set_attr "type" "fparith_media")]) 13078 13079(define_insn "subsf3_i" 13080 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13081 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0") 13082 (match_operand:SF 2 "fp_arith_reg_operand" "f"))) 13083 (clobber (reg:SI FPSCR_STAT_REG)) 13084 (use (reg:SI FPSCR_MODES_REG))] 13085 "TARGET_SH2E" 13086 "fsub %2,%0" 13087 [(set_attr "type" "fp") 13088 (set_attr "fp_mode" "single")]) 13089 13090(define_expand "mulsf3" 13091 [(set (match_operand:SF 0 "fp_arith_reg_operand" "") 13092 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "") 13093 (match_operand:SF 2 "fp_arith_reg_operand" "")))] 13094 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 13095{ 13096 if (TARGET_SH2E) 13097 { 13098 emit_insn (gen_mulsf3_i (operands[0], operands[1], operands[2])); 13099 DONE; 13100 } 13101}) 13102 13103(define_insn "*mulsf3_media" 13104 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13105 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f") 13106 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 13107 "TARGET_SHMEDIA_FPU" 13108 "fmul.s %1, %2, %0" 13109 [(set_attr "type" "fparith_media")]) 13110 13111(define_insn "mulsf3_i" 13112 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13113 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0") 13114 (match_operand:SF 2 "fp_arith_reg_operand" "f"))) 13115 (clobber (reg:SI FPSCR_STAT_REG)) 13116 (use (reg:SI FPSCR_MODES_REG))] 13117 "TARGET_SH2E" 13118 "fmul %2,%0" 13119 [(set_attr "type" "fp") 13120 (set_attr "fp_mode" "single")]) 13121 13122;; FMA (fused multiply-add) patterns 13123(define_expand "fmasf4" 13124 [(set (match_operand:SF 0 "fp_arith_reg_operand") 13125 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand") 13126 (match_operand:SF 2 "fp_arith_reg_operand") 13127 (match_operand:SF 3 "fp_arith_reg_operand")))] 13128 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 13129{ 13130 if (TARGET_SH2E) 13131 { 13132 emit_insn (gen_fmasf4_i (operands[0], operands[1], operands[2], 13133 operands[3])); 13134 DONE; 13135 } 13136}) 13137 13138(define_insn "fmasf4_i" 13139 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13140 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "w") 13141 (match_operand:SF 2 "fp_arith_reg_operand" "f") 13142 (match_operand:SF 3 "fp_arith_reg_operand" "0"))) 13143 (clobber (reg:SI FPSCR_STAT_REG)) 13144 (use (reg:SI FPSCR_MODES_REG))] 13145 "TARGET_SH2E" 13146 "fmac %1,%2,%0" 13147 [(set_attr "type" "fp") 13148 (set_attr "fp_mode" "single")]) 13149 13150(define_insn "fmasf4_media" 13151 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13152 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "f") 13153 (match_operand:SF 2 "fp_arith_reg_operand" "f") 13154 (match_operand:SF 3 "fp_arith_reg_operand" "0")))] 13155 "TARGET_SHMEDIA_FPU" 13156 "fmac.s %1, %2, %0" 13157 [(set_attr "type" "fparith_media")]) 13158 13159;; For some cases such as 'a * b + a' the FMA pattern is not generated by 13160;; previous transformations. If FMA is generally allowed, let the combine 13161;; pass utilize it. 13162(define_insn_and_split "*fmasf4" 13163 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13164 (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w") 13165 (match_operand:SF 2 "fp_arith_reg_operand" "f")) 13166 (match_operand:SF 3 "arith_reg_operand" "0"))) 13167 (clobber (reg:SI FPSCR_STAT_REG)) 13168 (use (reg:SI FPSCR_MODES_REG))] 13169 "TARGET_SH2E && flag_fp_contract_mode != FP_CONTRACT_OFF" 13170 "fmac %1,%2,%0" 13171 "&& can_create_pseudo_p ()" 13172 [(parallel [(set (match_dup 0) 13173 (fma:SF (match_dup 1) (match_dup 2) (match_dup 3))) 13174 (clobber (reg:SI FPSCR_STAT_REG)) 13175 (use (reg:SI FPSCR_MODES_REG))])] 13176{ 13177 /* Change 'b * a + a' into 'a * b + a'. 13178 This is better for register allocation. */ 13179 if (REGNO (operands[2]) == REGNO (operands[3])) 13180 std::swap (operands[1], operands[2]); 13181} 13182 [(set_attr "type" "fp") 13183 (set_attr "fp_mode" "single")]) 13184 13185(define_insn "*fmasf4_media" 13186 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13187 (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f") 13188 (match_operand:SF 2 "fp_arith_reg_operand" "f")) 13189 (match_operand:SF 3 "fp_arith_reg_operand" "0")))] 13190 "TARGET_SHMEDIA_FPU && flag_fp_contract_mode != FP_CONTRACT_OFF" 13191 "fmac.s %1, %2, %0" 13192 [(set_attr "type" "fparith_media")]) 13193 13194(define_expand "divsf3" 13195 [(set (match_operand:SF 0 "fp_arith_reg_operand") 13196 (div:SF (match_operand:SF 1 "fp_arith_reg_operand") 13197 (match_operand:SF 2 "fp_arith_reg_operand")))] 13198 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 13199{ 13200 if (TARGET_SH2E) 13201 { 13202 emit_insn (gen_divsf3_i (operands[0], operands[1], operands[2])); 13203 DONE; 13204 } 13205}) 13206 13207(define_insn "*divsf3_media" 13208 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13209 (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f") 13210 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 13211 "TARGET_SHMEDIA_FPU" 13212 "fdiv.s %1, %2, %0" 13213 [(set_attr "type" "fdiv_media")]) 13214 13215(define_insn "divsf3_i" 13216 [(set (match_operand:SF 0 "fp_arith_reg_dest" "=f") 13217 (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "0") 13218 (match_operand:SF 2 "fp_arith_reg_operand" "f"))) 13219 (clobber (reg:SI FPSCR_STAT_REG)) 13220 (use (reg:SI FPSCR_MODES_REG))] 13221 "TARGET_SH2E" 13222 "fdiv %2,%0" 13223 [(set_attr "type" "fdiv") 13224 (set_attr "fp_mode" "single")]) 13225 13226(define_insn "floatdisf2" 13227 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13228 (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))] 13229 "TARGET_SHMEDIA_FPU" 13230 "float.qs %1, %0" 13231 [(set_attr "type" "fpconv_media")]) 13232 13233(define_expand "floatsisf2" 13234 [(set (match_operand:SF 0 "fp_arith_reg_operand" "") 13235 (float:SF (match_operand:SI 1 "fpul_operand" "")))] 13236 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 13237{ 13238 if (!TARGET_SHMEDIA_FPU) 13239 { 13240 emit_insn (gen_floatsisf2_i4 (operands[0], operands[1])); 13241 DONE; 13242 } 13243}) 13244 13245(define_insn "*floatsisf2_media" 13246 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13247 (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))] 13248 "TARGET_SHMEDIA_FPU" 13249 "float.ls %1, %0" 13250 [(set_attr "type" "fpconv_media")]) 13251 13252(define_insn "floatsisf2_i4" 13253 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13254 (float:SF (match_operand:SI 1 "fpul_operand" "y"))) 13255 (clobber (reg:SI FPSCR_STAT_REG)) 13256 (use (reg:SI FPSCR_MODES_REG))] 13257 "TARGET_SH2E" 13258 "float %1,%0" 13259 [(set_attr "type" "fp") 13260 (set_attr "fp_mode" "single")]) 13261 13262(define_insn "fix_truncsfdi2" 13263 [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f") 13264 (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 13265 "TARGET_SHMEDIA_FPU" 13266 "ftrc.sq %1, %0" 13267 [(set_attr "type" "fpconv_media")]) 13268 13269(define_expand "fix_truncsfsi2" 13270 [(set (match_operand:SI 0 "fpul_operand" "=y") 13271 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 13272 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 13273{ 13274 if (!TARGET_SHMEDIA_FPU) 13275 { 13276 emit_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1])); 13277 DONE; 13278 } 13279}) 13280 13281(define_insn "*fix_truncsfsi2_media" 13282 [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f") 13283 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 13284 "TARGET_SHMEDIA_FPU" 13285 "ftrc.sl %1, %0" 13286 [(set_attr "type" "fpconv_media")]) 13287 13288(define_insn "fix_truncsfsi2_i4" 13289 [(set (match_operand:SI 0 "fpul_operand" "=y") 13290 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f"))) 13291 (clobber (reg:SI FPSCR_STAT_REG)) 13292 (use (reg:SI FPSCR_MODES_REG))] 13293 "TARGET_SH2E" 13294 "ftrc %1,%0" 13295 [(set_attr "type" "ftrc_s") 13296 (set_attr "fp_mode" "single")]) 13297 13298(define_insn "cmpgtsf_t" 13299 [(set (reg:SI T_REG) 13300 (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f") 13301 (match_operand:SF 1 "fp_arith_reg_operand" "f"))) 13302 (clobber (reg:SI FPSCR_STAT_REG)) 13303 (use (reg:SI FPSCR_MODES_REG))] 13304 "TARGET_SH2E || TARGET_SH4 || TARGET_SH2A_SINGLE" 13305 "fcmp/gt %1,%0" 13306 [(set_attr "type" "fp_cmp") 13307 (set_attr "fp_mode" "single")]) 13308 13309(define_insn "cmpeqsf_t" 13310 [(set (reg:SI T_REG) 13311 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f") 13312 (match_operand:SF 1 "fp_arith_reg_operand" "f"))) 13313 (clobber (reg:SI FPSCR_STAT_REG)) 13314 (use (reg:SI FPSCR_MODES_REG))] 13315 "TARGET_SH2E || TARGET_SH4 || TARGET_SH2A_SINGLE" 13316 "fcmp/eq %1,%0" 13317 [(set_attr "type" "fp_cmp") 13318 (set_attr "fp_mode" "single")]) 13319 13320(define_insn "ieee_ccmpeqsf_t" 13321 [(set (reg:SI T_REG) 13322 (ior:SI (reg:SI T_REG) 13323 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f") 13324 (match_operand:SF 1 "fp_arith_reg_operand" "f")))) 13325 (clobber (reg:SI FPSCR_STAT_REG)) 13326 (use (reg:SI FPSCR_MODES_REG))] 13327 "TARGET_IEEE && TARGET_SH2E" 13328{ 13329 return output_ieee_ccmpeq (insn, operands); 13330} 13331 [(set_attr "length" "4") 13332 (set_attr "fp_mode" "single")]) 13333 13334(define_insn "cmpeqsf_media" 13335 [(set (match_operand:SI 0 "register_operand" "=r") 13336 (eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f") 13337 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 13338 "TARGET_SHMEDIA_FPU" 13339 "fcmpeq.s %1, %2, %0" 13340 [(set_attr "type" "fcmp_media")]) 13341 13342(define_insn "cmpgtsf_media" 13343 [(set (match_operand:SI 0 "register_operand" "=r") 13344 (gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f") 13345 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 13346 "TARGET_SHMEDIA_FPU" 13347 "fcmpgt.s %1, %2, %0" 13348 [(set_attr "type" "fcmp_media")]) 13349 13350(define_insn "cmpgesf_media" 13351 [(set (match_operand:SI 0 "register_operand" "=r") 13352 (ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f") 13353 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 13354 "TARGET_SHMEDIA_FPU" 13355 "fcmpge.s %1, %2, %0" 13356 [(set_attr "type" "fcmp_media")]) 13357 13358(define_insn "cmpunsf_media" 13359 [(set (match_operand:SI 0 "register_operand" "=r") 13360 (unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f") 13361 (match_operand:SF 2 "fp_arith_reg_operand" "f")))] 13362 "TARGET_SHMEDIA_FPU" 13363 "fcmpun.s %1, %2, %0" 13364 [(set_attr "type" "fcmp_media")]) 13365 13366(define_expand "cbranchsf4" 13367 [(set (pc) 13368 (if_then_else (match_operator 0 "sh_float_comparison_operator" 13369 [(match_operand:SF 1 "arith_operand" "") 13370 (match_operand:SF 2 "arith_operand" "")]) 13371 (match_operand 3 "" "") 13372 (pc)))] 13373 "TARGET_SH2E || TARGET_SHMEDIA_FPU" 13374{ 13375 if (TARGET_SHMEDIA) 13376 emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2], 13377 operands[3])); 13378 else 13379 sh_emit_compare_and_branch (operands, SFmode); 13380 DONE; 13381}) 13382 13383(define_expand "negsf2" 13384 [(set (match_operand:SF 0 "fp_arith_reg_operand") 13385 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand")))] 13386 "TARGET_SH2E || TARGET_SHMEDIA_FPU") 13387 13388(define_insn "*negsf2_media" 13389 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13390 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 13391 "TARGET_SHMEDIA_FPU" 13392 "fneg.s %1, %0" 13393 [(set_attr "type" "fmove_media")]) 13394 13395(define_insn "*negsf2_i" 13396 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13397 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))] 13398 "TARGET_SH2E" 13399 "fneg %0" 13400 [(set_attr "type" "fmove")]) 13401 13402(define_expand "sqrtsf2" 13403 [(set (match_operand:SF 0 "fp_arith_reg_operand" "") 13404 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))] 13405 "TARGET_SH3E || TARGET_SHMEDIA_FPU" 13406{ 13407 if (TARGET_SH3E) 13408 { 13409 emit_insn (gen_sqrtsf2_i (operands[0], operands[1])); 13410 DONE; 13411 } 13412}) 13413 13414(define_insn "*sqrtsf2_media" 13415 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13416 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 13417 "TARGET_SHMEDIA_FPU" 13418 "fsqrt.s %1, %0" 13419 [(set_attr "type" "fdiv_media")]) 13420 13421(define_insn "sqrtsf2_i" 13422 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13423 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0"))) 13424 (clobber (reg:SI FPSCR_STAT_REG)) 13425 (use (reg:SI FPSCR_MODES_REG))] 13426 "TARGET_SH3E" 13427 "fsqrt %0" 13428 [(set_attr "type" "fdiv") 13429 (set_attr "fp_mode" "single")]) 13430 13431(define_insn "rsqrtsf2" 13432 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13433 (div:SF (match_operand:SF 1 "immediate_operand" "i") 13434 (sqrt:SF (match_operand:SF 2 "fp_arith_reg_operand" "0")))) 13435 (clobber (reg:SI FPSCR_STAT_REG)) 13436 (use (reg:SI FPSCR_MODES_REG))] 13437 "TARGET_FPU_ANY && TARGET_FSRRA 13438 && operands[1] == CONST1_RTX (SFmode)" 13439 "fsrra %0" 13440 [(set_attr "type" "fsrra") 13441 (set_attr "fp_mode" "single")]) 13442 13443;; When the sincos pattern is defined, the builtin functions sin and cos 13444;; will be expanded to the sincos pattern and one of the output values will 13445;; remain unused. 13446(define_expand "sincossf3" 13447 [(set (match_operand:SF 0 "nonimmediate_operand") 13448 (unspec:SF [(match_operand:SF 2 "fp_arith_reg_operand")] UNSPEC_FCOSA)) 13449 (set (match_operand:SF 1 "nonimmediate_operand") 13450 (unspec:SF [(match_dup 2)] UNSPEC_FSINA))] 13451 "TARGET_FPU_ANY && TARGET_FSCA" 13452{ 13453 rtx scaled = gen_reg_rtx (SFmode); 13454 rtx truncated = gen_reg_rtx (SImode); 13455 rtx fsca = gen_reg_rtx (V2SFmode); 13456 rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ()); 13457 13458 emit_insn (gen_mulsf3 (scaled, operands[2], scale_reg)); 13459 emit_insn (gen_fix_truncsfsi2 (truncated, scaled)); 13460 emit_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf ())); 13461 13462 emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4)); 13463 emit_move_insn (operands[1], gen_rtx_SUBREG (SFmode, fsca, 0)); 13464 DONE; 13465}) 13466 13467(define_insn_and_split "fsca" 13468 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f") 13469 (vec_concat:V2SF 13470 (unspec:SF [(mult:SF 13471 (float:SF (match_operand:SI 1 "fpul_fsca_operand" "y")) 13472 (match_operand:SF 2 "fsca_scale_factor" "i")) 13473 ] UNSPEC_FSINA) 13474 (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2)) 13475 ] UNSPEC_FCOSA))) 13476 (clobber (reg:SI FPSCR_STAT_REG)) 13477 (use (reg:SI FPSCR_MODES_REG))] 13478 "TARGET_FPU_ANY && TARGET_FSCA" 13479 "fsca fpul,%d0" 13480 "&& !fpul_operand (operands[1], SImode)" 13481 [(const_int 0)] 13482{ 13483 /* If operands[1] is something like (fix:SF (float:SF (reg:SI))) reduce it 13484 to a simple reg, otherwise reload will have trouble reloading the 13485 pseudo into fpul. */ 13486 rtx x = XEXP (operands[1], 0); 13487 while (x != NULL_RTX && !fpul_operand (x, SImode)) 13488 { 13489 gcc_assert (GET_CODE (x) == FIX || GET_CODE (x) == FLOAT); 13490 x = XEXP (x, 0); 13491 } 13492 gcc_assert (x != NULL_RTX && fpul_operand (x, SImode)); 13493 emit_insn (gen_fsca (operands[0], x, operands[2])); 13494 DONE; 13495} 13496 [(set_attr "type" "fsca") 13497 (set_attr "fp_mode" "single")]) 13498 13499(define_expand "abssf2" 13500 [(set (match_operand:SF 0 "fp_arith_reg_operand") 13501 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand")))] 13502 "TARGET_SH2E || TARGET_SHMEDIA_FPU") 13503 13504(define_insn "*abssf2_media" 13505 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13506 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 13507 "TARGET_SHMEDIA_FPU" 13508 "fabs.s %1, %0" 13509 [(set_attr "type" "fmove_media")]) 13510 13511(define_insn "*abssf2_i" 13512 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13513 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))] 13514 "TARGET_SH2E" 13515 "fabs %0" 13516 [(set_attr "type" "fmove")]) 13517 13518(define_expand "adddf3" 13519 [(set (match_operand:DF 0 "fp_arith_reg_operand" "") 13520 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "") 13521 (match_operand:DF 2 "fp_arith_reg_operand" "")))] 13522 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 13523{ 13524 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 13525 { 13526 emit_insn (gen_adddf3_i (operands[0], operands[1], operands[2])); 13527 DONE; 13528 } 13529}) 13530 13531(define_insn "*adddf3_media" 13532 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13533 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f") 13534 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 13535 "TARGET_SHMEDIA_FPU" 13536 "fadd.d %1, %2, %0" 13537 [(set_attr "type" "dfparith_media")]) 13538 13539(define_insn "adddf3_i" 13540 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13541 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0") 13542 (match_operand:DF 2 "fp_arith_reg_operand" "f"))) 13543 (clobber (reg:SI FPSCR_STAT_REG)) 13544 (use (reg:SI FPSCR_MODES_REG))] 13545 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 13546 "fadd %2,%0" 13547 [(set_attr "type" "dfp_arith") 13548 (set_attr "fp_mode" "double")]) 13549 13550(define_expand "subdf3" 13551 [(set (match_operand:DF 0 "fp_arith_reg_operand" "") 13552 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "") 13553 (match_operand:DF 2 "fp_arith_reg_operand" "")))] 13554 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 13555{ 13556 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 13557 { 13558 emit_insn (gen_subdf3_i (operands[0], operands[1], operands[2])); 13559 DONE; 13560 } 13561}) 13562 13563(define_insn "*subdf3_media" 13564 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13565 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f") 13566 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 13567 "TARGET_SHMEDIA_FPU" 13568 "fsub.d %1, %2, %0" 13569 [(set_attr "type" "dfparith_media")]) 13570 13571(define_insn "subdf3_i" 13572 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13573 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0") 13574 (match_operand:DF 2 "fp_arith_reg_operand" "f"))) 13575 (clobber (reg:SI FPSCR_STAT_REG)) 13576 (use (reg:SI FPSCR_MODES_REG))] 13577 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 13578 "fsub %2,%0" 13579 [(set_attr "type" "dfp_arith") 13580 (set_attr "fp_mode" "double")]) 13581 13582(define_expand "muldf3" 13583 [(set (match_operand:DF 0 "fp_arith_reg_operand" "") 13584 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "") 13585 (match_operand:DF 2 "fp_arith_reg_operand" "")))] 13586 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 13587{ 13588 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 13589 { 13590 emit_insn (gen_muldf3_i (operands[0], operands[1], operands[2])); 13591 DONE; 13592 } 13593}) 13594 13595(define_insn "*muldf3_media" 13596 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13597 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f") 13598 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 13599 "TARGET_SHMEDIA_FPU" 13600 "fmul.d %1, %2, %0" 13601 [(set_attr "type" "dfmul_media")]) 13602 13603(define_insn "muldf3_i" 13604 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13605 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0") 13606 (match_operand:DF 2 "fp_arith_reg_operand" "f"))) 13607 (clobber (reg:SI FPSCR_STAT_REG)) 13608 (use (reg:SI FPSCR_MODES_REG))] 13609 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 13610 "fmul %2,%0" 13611 [(set_attr "type" "dfp_mul") 13612 (set_attr "fp_mode" "double")]) 13613 13614(define_expand "divdf3" 13615 [(set (match_operand:DF 0 "fp_arith_reg_operand" "") 13616 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "") 13617 (match_operand:DF 2 "fp_arith_reg_operand" "")))] 13618 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 13619{ 13620 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 13621 { 13622 emit_insn (gen_divdf3_i (operands[0], operands[1], operands[2])); 13623 DONE; 13624 } 13625}) 13626 13627(define_insn "*divdf3_media" 13628 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13629 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f") 13630 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 13631 "TARGET_SHMEDIA_FPU" 13632 "fdiv.d %1, %2, %0" 13633 [(set_attr "type" "dfdiv_media")]) 13634 13635(define_insn "divdf3_i" 13636 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13637 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0") 13638 (match_operand:DF 2 "fp_arith_reg_operand" "f"))) 13639 (clobber (reg:SI FPSCR_STAT_REG)) 13640 (use (reg:SI FPSCR_MODES_REG))] 13641 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 13642 "fdiv %2,%0" 13643 [(set_attr "type" "dfdiv") 13644 (set_attr "fp_mode" "double")]) 13645 13646(define_insn "floatdidf2" 13647 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13648 (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))] 13649 "TARGET_SHMEDIA_FPU" 13650 "float.qd %1, %0" 13651 [(set_attr "type" "dfpconv_media")]) 13652 13653(define_expand "floatsidf2" 13654 [(set (match_operand:DF 0 "fp_arith_reg_operand" "") 13655 (float:DF (match_operand:SI 1 "fpul_operand" "")))] 13656 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 13657{ 13658 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 13659 { 13660 emit_insn (gen_floatsidf2_i (operands[0], operands[1])); 13661 DONE; 13662 } 13663}) 13664 13665(define_insn "*floatsidf2_media" 13666 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13667 (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))] 13668 "TARGET_SHMEDIA_FPU" 13669 "float.ld %1, %0" 13670 [(set_attr "type" "dfpconv_media")]) 13671 13672(define_insn "floatsidf2_i" 13673 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13674 (float:DF (match_operand:SI 1 "fpul_operand" "y"))) 13675 (clobber (reg:SI FPSCR_STAT_REG)) 13676 (use (reg:SI FPSCR_MODES_REG))] 13677 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 13678 "float %1,%0" 13679 [(set_attr "type" "dfp_conv") 13680 (set_attr "fp_mode" "double")]) 13681 13682(define_insn "fix_truncdfdi2" 13683 [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f") 13684 (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))] 13685 "TARGET_SHMEDIA_FPU" 13686 "ftrc.dq %1, %0" 13687 [(set_attr "type" "dfpconv_media")]) 13688 13689(define_expand "fix_truncdfsi2" 13690 [(set (match_operand:SI 0 "fpul_operand" "") 13691 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))] 13692 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 13693{ 13694 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 13695 { 13696 emit_insn (gen_fix_truncdfsi2_i (operands[0], operands[1])); 13697 DONE; 13698 } 13699}) 13700 13701(define_insn "*fix_truncdfsi2_media" 13702 [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f") 13703 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))] 13704 "TARGET_SHMEDIA_FPU" 13705 "ftrc.dl %1, %0" 13706 [(set_attr "type" "dfpconv_media")]) 13707 13708(define_insn "fix_truncdfsi2_i" 13709 [(set (match_operand:SI 0 "fpul_operand" "=y") 13710 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f"))) 13711 (clobber (reg:SI FPSCR_STAT_REG)) 13712 (use (reg:SI FPSCR_MODES_REG))] 13713 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 13714 "ftrc %1,%0" 13715 [(set_attr "type" "dfp_conv") 13716 (set_attr "dfp_comp" "no") 13717 (set_attr "fp_mode" "double")]) 13718 13719(define_insn "cmpgtdf_t" 13720 [(set (reg:SI T_REG) 13721 (gt:SI (match_operand:DF 0 "fp_arith_reg_operand" "f") 13722 (match_operand:DF 1 "fp_arith_reg_operand" "f"))) 13723 (clobber (reg:SI FPSCR_STAT_REG)) 13724 (use (reg:SI FPSCR_MODES_REG))] 13725 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 13726 "fcmp/gt %1,%0" 13727 [(set_attr "type" "dfp_cmp") 13728 (set_attr "fp_mode" "double")]) 13729 13730(define_insn "cmpeqdf_t" 13731 [(set (reg:SI T_REG) 13732 (eq:SI (match_operand:DF 0 "fp_arith_reg_operand" "f") 13733 (match_operand:DF 1 "fp_arith_reg_operand" "f"))) 13734 (clobber (reg:SI FPSCR_STAT_REG)) 13735 (use (reg:SI FPSCR_MODES_REG))] 13736 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 13737 "fcmp/eq %1,%0" 13738 [(set_attr "type" "dfp_cmp") 13739 (set_attr "fp_mode" "double")]) 13740 13741(define_insn "*ieee_ccmpeqdf_t" 13742 [(set (reg:SI T_REG) 13743 (ior:SI (reg:SI T_REG) 13744 (eq:SI (match_operand:DF 0 "fp_arith_reg_operand" "f") 13745 (match_operand:DF 1 "fp_arith_reg_operand" "f")))) 13746 (clobber (reg:SI FPSCR_STAT_REG)) 13747 (use (reg:SI FPSCR_MODES_REG))] 13748 "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)" 13749{ 13750 return output_ieee_ccmpeq (insn, operands); 13751} 13752 [(set_attr "length" "4") 13753 (set_attr "fp_mode" "double")]) 13754 13755(define_insn "cmpeqdf_media" 13756 [(set (match_operand:SI 0 "register_operand" "=r") 13757 (eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f") 13758 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 13759 "TARGET_SHMEDIA_FPU" 13760 "fcmpeq.d %1,%2,%0" 13761 [(set_attr "type" "fcmp_media")]) 13762 13763(define_insn "cmpgtdf_media" 13764 [(set (match_operand:SI 0 "register_operand" "=r") 13765 (gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f") 13766 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 13767 "TARGET_SHMEDIA_FPU" 13768 "fcmpgt.d %1,%2,%0" 13769 [(set_attr "type" "fcmp_media")]) 13770 13771(define_insn "cmpgedf_media" 13772 [(set (match_operand:SI 0 "register_operand" "=r") 13773 (ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f") 13774 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 13775 "TARGET_SHMEDIA_FPU" 13776 "fcmpge.d %1,%2,%0" 13777 [(set_attr "type" "fcmp_media")]) 13778 13779(define_insn "cmpundf_media" 13780 [(set (match_operand:SI 0 "register_operand" "=r") 13781 (unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f") 13782 (match_operand:DF 2 "fp_arith_reg_operand" "f")))] 13783 "TARGET_SHMEDIA_FPU" 13784 "fcmpun.d %1,%2,%0" 13785 [(set_attr "type" "fcmp_media")]) 13786 13787(define_expand "cbranchdf4" 13788 [(set (pc) 13789 (if_then_else (match_operator 0 "sh_float_comparison_operator" 13790 [(match_operand:DF 1 "arith_operand" "") 13791 (match_operand:DF 2 "arith_operand" "")]) 13792 (match_operand 3 "" "") 13793 (pc)))] 13794 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 13795{ 13796 if (TARGET_SHMEDIA) 13797 emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2], 13798 operands[3])); 13799 else 13800 sh_emit_compare_and_branch (operands, DFmode); 13801 DONE; 13802}) 13803 13804(define_expand "negdf2" 13805 [(set (match_operand:DF 0 "fp_arith_reg_operand") 13806 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand")))] 13807 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU") 13808 13809(define_insn "*negdf2_media" 13810 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13811 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))] 13812 "TARGET_SHMEDIA_FPU" 13813 "fneg.d %1, %0" 13814 [(set_attr "type" "fmove_media")]) 13815 13816(define_insn "*negdf2_i" 13817 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13818 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))] 13819 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 13820 "fneg %0" 13821 [(set_attr "type" "fmove")]) 13822 13823(define_expand "sqrtdf2" 13824 [(set (match_operand:DF 0 "fp_arith_reg_operand") 13825 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand")))] 13826 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 13827{ 13828 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 13829 { 13830 emit_insn (gen_sqrtdf2_i (operands[0], operands[1])); 13831 DONE; 13832 } 13833}) 13834 13835(define_insn "*sqrtdf2_media" 13836 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13837 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))] 13838 "TARGET_SHMEDIA_FPU" 13839 "fsqrt.d %1, %0" 13840 [(set_attr "type" "dfdiv_media")]) 13841 13842(define_insn "sqrtdf2_i" 13843 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13844 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0"))) 13845 (clobber (reg:SI FPSCR_STAT_REG)) 13846 (use (reg:SI FPSCR_MODES_REG))] 13847 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 13848 "fsqrt %0" 13849 [(set_attr "type" "dfdiv") 13850 (set_attr "fp_mode" "double")]) 13851 13852(define_expand "absdf2" 13853 [(set (match_operand:DF 0 "fp_arith_reg_operand") 13854 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand")))] 13855 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU") 13856 13857(define_insn "*absdf2_media" 13858 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13859 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))] 13860 "TARGET_SHMEDIA_FPU" 13861 "fabs.d %1, %0" 13862 [(set_attr "type" "fmove_media")]) 13863 13864(define_insn "*absdf2_i" 13865 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13866 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))] 13867 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 13868 "fabs %0" 13869 [(set_attr "type" "fmove")]) 13870 13871(define_expand "extendsfdf2" 13872 [(set (match_operand:DF 0 "fp_arith_reg_operand" "") 13873 (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))] 13874 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 13875{ 13876 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 13877 { 13878 emit_insn (gen_extendsfdf2_i4 (operands[0], operands[1])); 13879 DONE; 13880 } 13881}) 13882 13883(define_insn "*extendsfdf2_media" 13884 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13885 (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))] 13886 "TARGET_SHMEDIA_FPU" 13887 "fcnv.sd %1, %0" 13888 [(set_attr "type" "dfpconv_media")]) 13889 13890(define_insn "extendsfdf2_i4" 13891 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") 13892 (float_extend:DF (match_operand:SF 1 "fpul_operand" "y"))) 13893 (clobber (reg:SI FPSCR_STAT_REG)) 13894 (use (reg:SI FPSCR_MODES_REG))] 13895 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 13896 "fcnvsd %1,%0" 13897 [(set_attr "type" "fp") 13898 (set_attr "fp_mode" "double")]) 13899 13900(define_expand "truncdfsf2" 13901 [(set (match_operand:SF 0 "fpul_operand" "") 13902 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))] 13903 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" 13904{ 13905 if (TARGET_SH4 || TARGET_SH2A_DOUBLE) 13906 { 13907 emit_insn (gen_truncdfsf2_i4 (operands[0], operands[1])); 13908 DONE; 13909 } 13910}) 13911 13912(define_insn "*truncdfsf2_media" 13913 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 13914 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))] 13915 "TARGET_SHMEDIA_FPU" 13916 "fcnv.ds %1, %0" 13917 [(set_attr "type" "dfpconv_media")]) 13918 13919(define_insn "truncdfsf2_i4" 13920 [(set (match_operand:SF 0 "fpul_operand" "=y") 13921 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f"))) 13922 (clobber (reg:SI FPSCR_STAT_REG)) 13923 (use (reg:SI FPSCR_MODES_REG))] 13924 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" 13925 "fcnvds %1,%0" 13926 [(set_attr "type" "fp") 13927 (set_attr "fp_mode" "double")]) 13928 13929;; ------------------------------------------------------------------------- 13930;; Bit field extract patterns. 13931;; ------------------------------------------------------------------------- 13932 13933;; These give better code for packed bitfields, because they allow 13934;; auto-increment addresses to be generated. 13935 13936(define_expand "insv" 13937 [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "") 13938 (match_operand:SI 1 "immediate_operand" "") 13939 (match_operand:SI 2 "immediate_operand" "")) 13940 (match_operand:SI 3 "general_operand" ""))] 13941 "TARGET_SH1 && TARGET_BIG_ENDIAN" 13942{ 13943 rtx addr_target, orig_address, shift_reg, qi_val; 13944 HOST_WIDE_INT bitsize, size, v = 0; 13945 rtx x = operands[3]; 13946 13947 if (TARGET_SH2A && TARGET_BITOPS 13948 && (satisfies_constraint_Sbw (operands[0]) 13949 || satisfies_constraint_Sbv (operands[0])) 13950 && satisfies_constraint_M (operands[1]) 13951 && satisfies_constraint_K03 (operands[2])) 13952 { 13953 if (satisfies_constraint_N (operands[3])) 13954 { 13955 emit_insn (gen_bclr_m2a (operands[0], operands[2])); 13956 DONE; 13957 } 13958 else if (satisfies_constraint_M (operands[3])) 13959 { 13960 emit_insn (gen_bset_m2a (operands[0], operands[2])); 13961 DONE; 13962 } 13963 else if ((REG_P (operands[3]) && REGNO (operands[3]) == T_REG) 13964 && satisfies_constraint_M (operands[1])) 13965 { 13966 emit_insn (gen_bst_m2a (operands[0], operands[2])); 13967 DONE; 13968 } 13969 else if (REG_P (operands[3]) 13970 && satisfies_constraint_M (operands[1])) 13971 { 13972 emit_insn (gen_bldsi_reg (operands[3], const0_rtx)); 13973 emit_insn (gen_bst_m2a (operands[0], operands[2])); 13974 DONE; 13975 } 13976 } 13977 /* ??? expmed doesn't care for non-register predicates. */ 13978 if (! memory_operand (operands[0], VOIDmode) 13979 || ! immediate_operand (operands[1], VOIDmode) 13980 || ! immediate_operand (operands[2], VOIDmode) 13981 || ! general_operand (x, VOIDmode)) 13982 FAIL; 13983 /* If this isn't a 16 / 24 / 32 bit field, or if 13984 it doesn't start on a byte boundary, then fail. */ 13985 bitsize = INTVAL (operands[1]); 13986 if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0 13987 || (INTVAL (operands[2]) % 8) != 0) 13988 FAIL; 13989 13990 size = bitsize / 8; 13991 orig_address = XEXP (operands[0], 0); 13992 shift_reg = gen_reg_rtx (SImode); 13993 if (CONST_INT_P (x)) 13994 { 13995 v = INTVAL (x); 13996 qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode))); 13997 } 13998 else 13999 { 14000 emit_insn (gen_movsi (shift_reg, operands[3])); 14001 qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3); 14002 } 14003 addr_target = copy_addr_to_reg (plus_constant (Pmode, 14004 orig_address, size - 1)); 14005 14006 operands[0] = replace_equiv_address (operands[0], addr_target); 14007 emit_insn (gen_movqi (operands[0], qi_val)); 14008 14009 while (size -= 1) 14010 { 14011 if (CONST_INT_P (x)) 14012 qi_val 14013 = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode))); 14014 else 14015 { 14016 emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8))); 14017 qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3); 14018 } 14019 emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx)); 14020 emit_insn (gen_movqi (operands[0], qi_val)); 14021 } 14022 14023 DONE; 14024}) 14025 14026(define_insn "movua" 14027 [(set (match_operand:SI 0 "register_operand" "=z") 14028 (unspec:SI [(match_operand:BLK 1 "unaligned_load_operand" "Sua>")] 14029 UNSPEC_MOVUA))] 14030 "TARGET_SH4A" 14031 "movua.l %1,%0" 14032 [(set_attr "type" "movua")]) 14033 14034;; We shouldn't need this, but cse replaces increments with references 14035;; to other regs before flow has a chance to create post_inc 14036;; addressing modes, and only postreload's cse_move2add brings the 14037;; increments back to a usable form. 14038(define_peephole2 14039 [(set (match_operand:SI 0 "register_operand" "") 14040 (sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" "")) 14041 (const_int 32) (const_int 0))) 14042 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))] 14043 "TARGET_SH4A && REGNO (operands[0]) != REGNO (operands[1])" 14044 [(set (match_operand:SI 0 "register_operand" "") 14045 (sign_extract:SI (mem:SI (post_inc:SI 14046 (match_operand:SI 1 "register_operand" ""))) 14047 (const_int 32) (const_int 0)))] 14048 "") 14049 14050(define_expand "extv" 14051 [(set (match_operand:SI 0 "register_operand" "") 14052 (sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "") 14053 (match_operand 2 "const_int_operand" "") 14054 (match_operand 3 "const_int_operand" "")))] 14055 "TARGET_SH4A || TARGET_SH2A" 14056{ 14057 if (TARGET_SH2A && TARGET_BITOPS 14058 && (satisfies_constraint_Sbw (operands[1]) 14059 || satisfies_constraint_Sbv (operands[1])) 14060 && satisfies_constraint_M (operands[2]) 14061 && satisfies_constraint_K03 (operands[3])) 14062 { 14063 emit_insn (gen_bldsign_m2a (operands[1], operands[3])); 14064 if (REGNO (operands[0]) != T_REG) 14065 emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG))); 14066 DONE; 14067 } 14068 if (TARGET_SH4A 14069 && INTVAL (operands[2]) == 32 14070 && INTVAL (operands[3]) == 0 14071 && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32) 14072 { 14073 rtx src = adjust_address (operands[1], BLKmode, 0); 14074 set_mem_size (src, 4); 14075 emit_insn (gen_movua (operands[0], src)); 14076 DONE; 14077 } 14078 14079 FAIL; 14080}) 14081 14082(define_expand "extzv" 14083 [(set (match_operand:SI 0 "register_operand" "") 14084 (zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "") 14085 (match_operand 2 "const_int_operand" "") 14086 (match_operand 3 "const_int_operand" "")))] 14087 "TARGET_SH4A || TARGET_SH2A" 14088{ 14089 if (TARGET_SH2A && TARGET_BITOPS 14090 && (satisfies_constraint_Sbw (operands[1]) 14091 || satisfies_constraint_Sbv (operands[1])) 14092 && satisfies_constraint_M (operands[2]) 14093 && satisfies_constraint_K03 (operands[3])) 14094 { 14095 emit_insn (gen_bld_m2a (operands[1], operands[3])); 14096 if (REGNO (operands[0]) != T_REG) 14097 emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG))); 14098 DONE; 14099 } 14100 if (TARGET_SH4A 14101 && INTVAL (operands[2]) == 32 14102 && INTVAL (operands[3]) == 0 14103 && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32) 14104 { 14105 rtx src = adjust_address (operands[1], BLKmode, 0); 14106 set_mem_size (src, 4); 14107 emit_insn (gen_movua (operands[0], src)); 14108 DONE; 14109 } 14110 14111 FAIL; 14112}) 14113 14114;; ------------------------------------------------------------------------- 14115;; Extract negated single bit and zero extend it. 14116;; Generally we don't care about the exact xor const_int value, as long 14117;; as it contains the extracted bit. For simplicity, the pattern variations 14118;; that convert everything into the primary '*neg_zero_extract_0' pattern use 14119;; a xor const_int -1 value. 14120 14121(define_insn_and_split "*neg_zero_extract_0" 14122 [(set (reg:SI T_REG) 14123 (zero_extract:SI (xor:QIHISI (match_operand:QIHISI 0 "arith_reg_operand") 14124 (match_operand 1 "const_int_operand")) 14125 (const_int 1) 14126 (match_operand 2 "const_int_operand")))] 14127 "TARGET_SH1 && can_create_pseudo_p () 14128 && INTVAL (operands[1]) & (1LL << INTVAL (operands[2]))" 14129 "#" 14130 "&& 1" 14131 [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 2)) 14132 (const_int 0)))] 14133{ 14134 if (INTVAL (operands[2]) == 31 && <MODE>mode == SImode) 14135 { 14136 /* Use cmp/pz to extract bit 31 into the T bit. */ 14137 emit_insn (gen_cmpgesi_t (operands[0], const0_rtx)); 14138 DONE; 14139 } 14140 14141 operands[2] = GEN_INT ((1 << INTVAL (operands[2]))); 14142 if (GET_MODE (operands[0]) != SImode) 14143 operands[0] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0); 14144}) 14145 14146(define_insn_and_split "*neg_zero_extract_1" 14147 [(set (reg:SI T_REG) 14148 (and:SI (not:SI (match_operand:SI 0 "arith_reg_operand")) 14149 (const_int 1)))] 14150 "TARGET_SH1" 14151 "#" 14152 "&& 1" 14153 [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1)) 14154 (const_int 1) (const_int 0)))]) 14155 14156;; x & (1 << n) == 0: 0x00000000 + 1 = 1 14157;; x & (1 << n) != 0: 0xFFFFFFFF + 1 = 0 14158(define_insn_and_split "*neg_zero_extract_2" 14159 [(set (reg:SI T_REG) 14160 (plus:SI (sign_extract:SI (match_operand:QIHISI 0 "arith_reg_operand") 14161 (const_int 1) 14162 (match_operand 1 "const_int_operand")) 14163 (const_int 1)))] 14164 "TARGET_SH1 && can_create_pseudo_p ()" 14165 "#" 14166 "&& 1" 14167 [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1)) 14168 (const_int 1) (match_dup 1)))]) 14169 14170;; (signed)x >> 31 + 1 = (x >= 0) ^ 1 14171(define_insn_and_split "*neg_zero_extract_3" 14172 [(set (reg:SI T_REG) 14173 (plus:SI (ashiftrt:SI (match_operand:SI 0 "arith_reg_operand") 14174 (const_int 31)) 14175 (const_int 1)))] 14176 "TARGET_SH1 && can_create_pseudo_p ()" 14177 "#" 14178 "&& 1" 14179 [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1)) 14180 (const_int 1) (const_int 31)))]) 14181 14182;; This is required for some bit patterns of DImode subregs. 14183;; It looks like combine gets confused by the DImode right shift and fails 14184;; to simplify things. 14185(define_insn_and_split "*neg_zero_extract_4" 14186 [(set (reg:SI T_REG) 14187 (and:SI (and:SI 14188 (lshiftrt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand") 14189 (match_operand 1 "const_int_operand")) 14190 (match_operand 2 "const_int_operand")) 14191 (not:SI (ashift:SI (match_operand:SI 3 "arith_reg_operand") 14192 (match_operand 4 "const_int_operand")))) 14193 (const_int 1)))] 14194 "TARGET_SH1 && can_create_pseudo_p () 14195 && INTVAL (operands[4]) > 0 14196 && INTVAL (operands[1]) & (1LL << INTVAL (operands[2]))" 14197 "#" 14198 "&& 1" 14199 [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1)) 14200 (const_int 1) (match_dup 2)))]) 14201 14202(define_insn_and_split "*neg_zero_extract_5" 14203 [(set (reg:SI T_REG) 14204 (and:SI (not:SI (subreg:SI 14205 (lshiftrt:DI (match_operand:DI 0 "arith_reg_operand") 14206 (match_operand 1 "const_int_operand")) 14207 0)) 14208 (const_int 1)))] 14209 "TARGET_SH1 && TARGET_LITTLE_ENDIAN && can_create_pseudo_p () 14210 && INTVAL (operands[1]) < 32" 14211 "#" 14212 "&& 1" 14213 [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1)) 14214 (const_int 1) (match_dup 1)))] 14215{ 14216 operands[0] = gen_lowpart (SImode, operands[0]); 14217}) 14218 14219(define_insn_and_split "*neg_zero_extract_6" 14220 [(set (reg:SI T_REG) 14221 (and:SI (not:SI (subreg:SI 14222 (lshiftrt:DI (match_operand:DI 0 "arith_reg_operand") 14223 (match_operand 1 "const_int_operand")) 14224 4)) 14225 (const_int 1)))] 14226 "TARGET_SH1 && TARGET_BIG_ENDIAN && can_create_pseudo_p () 14227 && INTVAL (operands[1]) < 32" 14228 "#" 14229 "&& 1" 14230 [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1)) 14231 (const_int 1) (match_dup 1)))] 14232{ 14233 operands[0] = gen_lowpart (SImode, operands[0]); 14234}) 14235 14236;; ------------------------------------------------------------------------- 14237;; Extract single bit and zero extend it. 14238;; All patterns store the result bit in the T bit, although that is not 14239;; always possible to do with a single insn and a nott must be appended. 14240;; The trailing nott will be optimized away in most cases. E.g. if the 14241;; extracted bit is fed into a branch condition, the condition can be 14242;; inverted and the nott will be eliminated. 14243;; FIXME: In cases where the trailing nott can't be eliminated, try to 14244;; convert it into a (not, tst) sequence, which could be better on non-SH2A. 14245 14246;; On SH2A the 'bld<mode>_reg' insn will be used if the bit position fits. 14247(define_insn_and_split "*zero_extract_0" 14248 [(set (reg:SI T_REG) 14249 (zero_extract:SI (match_operand:QIHISI 0 "arith_reg_operand") 14250 (const_int 1) 14251 (match_operand 1 "const_int_operand")))] 14252 "TARGET_SH1 && can_create_pseudo_p () 14253 && !(TARGET_SH2A && satisfies_constraint_K03 (operands[1]))" 14254 "#" 14255 "&& 1" 14256 [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 1)) 14257 (const_int 0))) 14258 (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))] 14259{ 14260 if (INTVAL (operands[1]) == 31 && <MODE>mode == SImode) 14261 { 14262 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[0])); 14263 DONE; 14264 } 14265 14266 operands[1] = GEN_INT (1 << INTVAL (operands[1])); 14267 if (GET_MODE (operands[0]) != SImode) 14268 operands[0] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0); 14269}) 14270 14271;; This is required for some bit patterns of DImode subregs. 14272;; It looks like combine gets confused by the DImode right shift and fails 14273;; to simplify things. 14274(define_insn_and_split "*zero_extract_1" 14275 [(set (reg:SI T_REG) 14276 (subreg:SI (zero_extract:DI (match_operand:SI 0 "arith_reg_operand") 14277 (const_int 1) 14278 (match_operand 1 "const_int_operand")) 14279 0))] 14280 "TARGET_SH1 && TARGET_LITTLE_ENDIAN && can_create_pseudo_p () 14281 && INTVAL (operands[1]) < 32" 14282 "#" 14283 "&& 1" 14284 [(set (reg:SI T_REG) 14285 (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)))]) 14286 14287(define_insn_and_split "*zero_extract_2" 14288 [(set (reg:SI T_REG) 14289 (subreg:SI (zero_extract:DI (match_operand:SI 0 "arith_reg_operand") 14290 (const_int 1) 14291 (match_operand 1 "const_int_operand")) 14292 4))] 14293 "TARGET_SH1 && TARGET_BIG_ENDIAN && can_create_pseudo_p () 14294 && INTVAL (operands[1]) < 32" 14295 "#" 14296 "&& 1" 14297 [(set (reg:SI T_REG) 14298 (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)))]) 14299 14300;; ------------------------------------------------------------------------- 14301;; SH2A instructions for bitwise operations. 14302;; FIXME: Convert multiple instruction insns to insn_and_split. 14303;; FIXME: Use iterators to fold at least and,xor,or insn variations. 14304 14305;; Clear a bit in a memory location. 14306(define_insn "bclr_m2a" 14307 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv") 14308 (and:QI 14309 (not:QI (ashift:QI (const_int 1) 14310 (match_operand:QI 1 "const_int_operand" "K03,K03"))) 14311 (match_dup 0)))] 14312 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 14313 "@ 14314 bclr.b %1,%0 14315 bclr.b %1,@(0,%t0)" 14316[(set_attr "length" "4,4")]) 14317 14318(define_insn "bclrmem_m2a" 14319 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv") 14320 (and:QI (match_dup 0) 14321 (match_operand:QI 1 "const_int_operand" "Psz,Psz")))] 14322 "TARGET_SH2A && satisfies_constraint_Psz (operands[1]) && TARGET_BITOPS" 14323 "@ 14324 bclr.b %W1,%0 14325 bclr.b %W1,@(0,%t0)" 14326 [(set_attr "length" "4,4")]) 14327 14328;; Set a bit in a memory location. 14329(define_insn "bset_m2a" 14330 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv") 14331 (ior:QI 14332 (ashift:QI (const_int 1) 14333 (match_operand:QI 1 "const_int_operand" "K03,K03")) 14334 (match_dup 0)))] 14335 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 14336 "@ 14337 bset.b %1,%0 14338 bset.b %1,@(0,%t0)" 14339 [(set_attr "length" "4,4")]) 14340 14341(define_insn "bsetmem_m2a" 14342 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv") 14343 (ior:QI (match_dup 0) 14344 (match_operand:QI 1 "const_int_operand" "Pso,Pso")))] 14345 "TARGET_SH2A && satisfies_constraint_Pso (operands[1]) && TARGET_BITOPS" 14346 "@ 14347 bset.b %V1,%0 14348 bset.b %V1,@(0,%t0)" 14349 [(set_attr "length" "4,4")]) 14350 14351;;; Transfer the contents of the T bit to a specified bit of memory. 14352(define_insn "bst_m2a" 14353 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,m") 14354 (if_then_else (eq (reg:SI T_REG) (const_int 0)) 14355 (and:QI 14356 (not:QI (ashift:QI (const_int 1) 14357 (match_operand:QI 1 "const_int_operand" "K03,K03"))) 14358 (match_dup 0)) 14359 (ior:QI 14360 (ashift:QI (const_int 1) (match_dup 1)) 14361 (match_dup 0))))] 14362 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 14363 "@ 14364 bst.b %1,%0 14365 bst.b %1,@(0,%t0)" 14366 [(set_attr "length" "4")]) 14367 14368;; Store a specified bit of memory in the T bit. 14369(define_insn "bld_m2a" 14370 [(set (reg:SI T_REG) 14371 (zero_extract:SI 14372 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,Sbv") 14373 (const_int 1) 14374 (match_operand 1 "const_int_operand" "K03,K03")))] 14375 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 14376 "@ 14377 bld.b %1,%0 14378 bld.b %1,@(0,%t0)" 14379 [(set_attr "length" "4,4")]) 14380 14381;; Store a specified bit of memory in the T bit. 14382(define_insn "bldsign_m2a" 14383 [(set (reg:SI T_REG) 14384 (sign_extract:SI 14385 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m") 14386 (const_int 1) 14387 (match_operand 1 "const_int_operand" "K03,K03")))] 14388 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 14389 "@ 14390 bld.b %1,%0 14391 bld.b %1,@(0,%t0)" 14392 [(set_attr "length" "4,4")]) 14393 14394;; Store a specified bit of the LSB 8 bits of a register in the T bit. 14395(define_insn "bld<mode>_reg" 14396 [(set (reg:SI T_REG) 14397 (zero_extract:SI (match_operand:QIHISI 0 "arith_reg_operand" "r") 14398 (const_int 1) 14399 (match_operand 1 "const_int_operand" "K03")))] 14400 "TARGET_SH2A && satisfies_constraint_K03 (operands[1])" 14401 "bld %1,%0") 14402 14403;; Take logical and of a specified bit of memory with the T bit and 14404;; store its result in the T bit. 14405(define_insn "band_m2a" 14406 [(set (reg:SI T_REG) 14407 (and:SI (reg:SI T_REG) 14408 (zero_extract:SI 14409 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m") 14410 (const_int 1) 14411 (match_operand 1 "const_int_operand" "K03,K03"))))] 14412 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 14413 "@ 14414 band.b %1,%0 14415 band.b %1,@(0,%t0)" 14416 [(set_attr "length" "4,4")]) 14417 14418(define_insn "bandreg_m2a" 14419 [(set (match_operand:SI 0 "register_operand" "=r,r") 14420 (and:SI (zero_extract:SI 14421 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv") 14422 (const_int 1) 14423 (match_operand 2 "const_int_operand" "K03,K03")) 14424 (match_operand:SI 3 "register_operand" "r,r")))] 14425 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])" 14426{ 14427 static const char* alt[] = 14428 { 14429 "band.b %2,%1" "\n" 14430 " movt %0", 14431 14432 "band.b %2,@(0,%t1)" "\n" 14433 " movt %0" 14434 }; 14435 return alt[which_alternative]; 14436} 14437 [(set_attr "length" "6,6")]) 14438 14439;; Take logical or of a specified bit of memory with the T bit and 14440;; store its result in the T bit. 14441(define_insn "bor_m2a" 14442 [(set (reg:SI T_REG) 14443 (ior:SI (reg:SI T_REG) 14444 (zero_extract:SI 14445 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m") 14446 (const_int 1) 14447 (match_operand 1 "const_int_operand" "K03,K03"))))] 14448 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 14449 "@ 14450 bor.b %1,%0 14451 bor.b %1,@(0,%t0)" 14452 [(set_attr "length" "4,4")]) 14453 14454(define_insn "borreg_m2a" 14455 [(set (match_operand:SI 0 "register_operand" "=r,r") 14456 (ior:SI (zero_extract:SI 14457 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv") 14458 (const_int 1) 14459 (match_operand 2 "const_int_operand" "K03,K03")) 14460 (match_operand:SI 3 "register_operand" "=r,r")))] 14461 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])" 14462{ 14463 static const char* alt[] = 14464 { 14465 "bor.b %2,%1" "\n" 14466 " movt %0", 14467 14468 "bor.b %2,@(0,%t1)" "\n" 14469 " movt %0" 14470 }; 14471 return alt[which_alternative]; 14472} 14473 [(set_attr "length" "6,6")]) 14474 14475;; Take exclusive or of a specified bit of memory with the T bit and 14476;; store its result in the T bit. 14477(define_insn "bxor_m2a" 14478 [(set (reg:SI T_REG) 14479 (xor:SI (reg:SI T_REG) 14480 (zero_extract:SI 14481 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m") 14482 (const_int 1) 14483 (match_operand 1 "const_int_operand" "K03,K03"))))] 14484 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])" 14485 "@ 14486 bxor.b %1,%0 14487 bxor.b %1,@(0,%t0)" 14488 [(set_attr "length" "4,4")]) 14489 14490(define_insn "bxorreg_m2a" 14491 [(set (match_operand:SI 0 "register_operand" "=r,r") 14492 (xor:SI (zero_extract:SI 14493 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv") 14494 (const_int 1) 14495 (match_operand 2 "const_int_operand" "K03,K03")) 14496 (match_operand:SI 3 "register_operand" "=r,r")))] 14497 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])" 14498{ 14499 static const char* alt[] = 14500 { 14501 "bxor.b %2,%1" "\n" 14502 " movt %0", 14503 14504 "bxor.b %2,@(0,%t1)" "\n" 14505 " movt %0" 14506 }; 14507 return alt[which_alternative]; 14508} 14509 [(set_attr "length" "6,6")]) 14510 14511;; ------------------------------------------------------------------------- 14512;; Peepholes 14513;; ------------------------------------------------------------------------- 14514;; This matches cases where the bit in a memory location is set. 14515(define_peephole2 14516 [(set (match_operand:SI 0 "register_operand") 14517 (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand"))) 14518 (set (match_dup 0) 14519 (ior:SI (match_dup 0) 14520 (match_operand:SI 2 "const_int_operand"))) 14521 (set (match_dup 1) 14522 (match_operand 3 "arith_reg_operand"))] 14523 "TARGET_SH2A && TARGET_BITOPS 14524 && satisfies_constraint_Pso (operands[2]) 14525 && REGNO (operands[0]) == REGNO (operands[3])" 14526 [(set (match_dup 1) 14527 (ior:QI (match_dup 1) (match_dup 2)))] 14528 "") 14529 14530;; This matches cases where the bit in a memory location is cleared. 14531(define_peephole2 14532 [(set (match_operand:SI 0 "register_operand") 14533 (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand"))) 14534 (set (match_dup 0) 14535 (and:SI (match_dup 0) 14536 (match_operand:SI 2 "const_int_operand"))) 14537 (set (match_dup 1) 14538 (match_operand 3 "arith_reg_operand"))] 14539 "TARGET_SH2A && TARGET_BITOPS 14540 && satisfies_constraint_Psz (operands[2]) 14541 && REGNO (operands[0]) == REGNO (operands[3])" 14542 [(set (match_dup 1) 14543 (and:QI (match_dup 1) (match_dup 2)))] 14544 "") 14545 14546;; This matches cases where a stack pointer increment at the start of the 14547;; epilogue combines with a stack slot read loading the return value. 14548(define_peephole 14549 [(set (match_operand:SI 0 "arith_reg_operand" "") 14550 (mem:SI (match_operand:SI 1 "arith_reg_operand" ""))) 14551 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))] 14552 "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])" 14553 "mov.l @%1+,%0") 14554 14555;; See the comment on the dt combiner pattern above. 14556(define_peephole 14557 [(set (match_operand:SI 0 "arith_reg_operand" "=r") 14558 (plus:SI (match_dup 0) 14559 (const_int -1))) 14560 (set (reg:SI T_REG) 14561 (eq:SI (match_dup 0) (const_int 0)))] 14562 "TARGET_SH2" 14563 "dt %0") 14564 14565;; The following peepholes fold load sequences for which reload was not 14566;; able to generate a displacement addressing move insn. 14567;; This can happen when reload has to transform a move insn 14568;; without displacement into one with displacement. Or when reload can't 14569;; fit a displacement into the insn's constraints. In the latter case, the 14570;; load destination reg remains at r0, which reload compensates by inserting 14571;; another mov insn. 14572 14573;; Fold sequence: 14574;; mov #54,r0 14575;; mov.{b,w} @(r0,r15),r0 14576;; mov r0,r3 14577;; into: 14578;; mov.{b,w} @(54,r15),r3 14579;; 14580(define_peephole2 14581 [(set (match_operand:SI 0 "arith_reg_dest" "") 14582 (match_operand:SI 1 "const_int_operand" "")) 14583 (set (match_operand:SI 2 "arith_reg_dest" "") 14584 (sign_extend:SI 14585 (mem:QI (plus:SI (match_dup 0) 14586 (match_operand:SI 3 "arith_reg_operand" ""))))) 14587 (set (match_operand:QI 4 "arith_reg_dest" "") 14588 (match_operand:QI 5 "arith_reg_operand" ""))] 14589 "TARGET_SH2A 14590 && sh_legitimate_index_p (QImode, operands[1], true, true) 14591 && REGNO (operands[2]) == REGNO (operands[5]) 14592 && peep2_reg_dead_p (3, operands[5])" 14593 [(set (match_dup 4) (mem:QI (plus:SI (match_dup 3) (match_dup 1))))] 14594 "") 14595 14596(define_peephole2 14597 [(set (match_operand:SI 0 "arith_reg_dest" "") 14598 (match_operand:SI 1 "const_int_operand" "")) 14599 (set (match_operand:SI 2 "arith_reg_dest" "") 14600 (sign_extend:SI 14601 (mem:HI (plus:SI (match_dup 0) 14602 (match_operand:SI 3 "arith_reg_operand" ""))))) 14603 (set (match_operand:HI 4 "arith_reg_dest" "") 14604 (match_operand:HI 5 "arith_reg_operand" ""))] 14605 "TARGET_SH2A 14606 && sh_legitimate_index_p (HImode, operands[1], true, true) 14607 && REGNO (operands[2]) == REGNO (operands[5]) 14608 && peep2_reg_dead_p (3, operands[5])" 14609 [(set (match_dup 4) (mem:HI (plus:SI (match_dup 3) (match_dup 1))))] 14610 "") 14611 14612;; Fold sequence: 14613;; mov #54,r0 14614;; mov.{b,w} @(r0,r15),r1 14615;; into: 14616;; mov.{b,w} @(54,r15),r1 14617;; 14618(define_peephole2 14619 [(set (match_operand:SI 0 "arith_reg_dest" "") 14620 (match_operand:SI 1 "const_int_operand" "")) 14621 (set (match_operand:SI 2 "arith_reg_dest" "") 14622 (sign_extend:SI 14623 (mem:QI (plus:SI (match_dup 0) 14624 (match_operand:SI 3 "arith_reg_operand" "")))))] 14625 "TARGET_SH2A 14626 && sh_legitimate_index_p (QImode, operands[1], true, true) 14627 && (peep2_reg_dead_p (2, operands[0]) 14628 || REGNO (operands[0]) == REGNO (operands[2]))" 14629 [(set (match_dup 2) 14630 (sign_extend:SI (mem:QI (plus:SI (match_dup 3) (match_dup 1)))))] 14631 "") 14632 14633(define_peephole2 14634 [(set (match_operand:SI 0 "arith_reg_dest" "") 14635 (match_operand:SI 1 "const_int_operand" "")) 14636 (set (match_operand:SI 2 "arith_reg_dest" "") 14637 (sign_extend:SI 14638 (mem:HI (plus:SI (match_dup 0) 14639 (match_operand:SI 3 "arith_reg_operand" "")))))] 14640 "TARGET_SH2A 14641 && sh_legitimate_index_p (HImode, operands[1], true, true) 14642 && (peep2_reg_dead_p (2, operands[0]) 14643 || REGNO (operands[0]) == REGNO (operands[2]))" 14644 [(set (match_dup 2) 14645 (sign_extend:SI (mem:HI (plus:SI (match_dup 3) (match_dup 1)))))] 14646 "") 14647 14648;; Fold sequence: 14649;; mov.{b,w} @(r0,r15),r0 14650;; mov r0,r3 14651;; into: 14652;; mov.{b,w} @(r0,r15),r3 14653;; 14654;; This can happen when initially a displacement address is picked, where 14655;; the destination reg is fixed to r0, and then the address is transformed 14656;; into 'r0 + reg'. 14657(define_peephole2 14658 [(set (match_operand:SI 0 "arith_reg_dest" "") 14659 (sign_extend:SI 14660 (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "") 14661 (match_operand:SI 2 "arith_reg_operand" ""))))) 14662 (set (match_operand:QI 3 "arith_reg_dest" "") 14663 (match_operand:QI 4 "arith_reg_operand" ""))] 14664 "TARGET_SH1 14665 && REGNO (operands[0]) == REGNO (operands[4]) 14666 && peep2_reg_dead_p (2, operands[0])" 14667 [(set (match_dup 3) 14668 (mem:QI (plus:SI (match_dup 1) (match_dup 2))))] 14669 "") 14670 14671(define_peephole2 14672 [(set (match_operand:SI 0 "arith_reg_dest" "") 14673 (sign_extend:SI 14674 (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "") 14675 (match_operand:SI 2 "arith_reg_operand" ""))))) 14676 (set (match_operand:HI 3 "arith_reg_dest" "") 14677 (match_operand:HI 4 "arith_reg_operand" ""))] 14678 "TARGET_SH1 14679 && REGNO (operands[0]) == REGNO (operands[4]) 14680 && peep2_reg_dead_p (2, operands[0])" 14681 [(set (match_dup 3) 14682 (mem:HI (plus:SI (match_dup 1) (match_dup 2))))] 14683 "") 14684 14685;; extu.bw a,b 14686;; mov b,c -> extu.bw a,c 14687(define_peephole2 14688 [(set (match_operand:SI 0 "arith_reg_dest") 14689 (zero_extend:SI (match_operand:QIHI 1 "arith_reg_operand"))) 14690 (set (match_operand:SI 2 "arith_reg_dest") 14691 (match_dup 0))] 14692 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])" 14693 [(set (match_dup 2) (zero_extend:SI (match_dup 1)))]) 14694 14695;; mov r0,r1 14696;; extu.bw r1,r1 -> extu.bw r0,r1 14697(define_peephole2 14698 [(set (match_operand 0 "arith_reg_dest") 14699 (match_operand 1 "arith_reg_operand")) 14700 (set (match_operand:SI 2 "arith_reg_dest") 14701 (zero_extend:SI (match_operand:QIHI 3 "arith_reg_operand")))] 14702 "TARGET_SH1 14703 && REGNO (operands[0]) == REGNO (operands[3]) 14704 && (REGNO (operands[0]) == REGNO (operands[2]) 14705 || peep2_reg_dead_p (2, operands[0]))" 14706 [(set (match_dup 2) (zero_extend:SI (match_dup 1)))] 14707{ 14708 operands[1] = gen_rtx_REG (<MODE>mode, REGNO (operands[1])); 14709}) 14710 14711;; mov a,b 14712;; mov b,a -> < nop > 14713(define_peephole2 14714 [(set (match_operand 0 "register_operand") 14715 (match_operand 1 "register_operand")) 14716 (set (match_operand 2 "register_operand") 14717 (match_operand 3 "register_operand"))] 14718 "TARGET_SH1 14719 && REGNO (operands[0]) == REGNO (operands[3]) 14720 && REGNO (operands[1]) == REGNO (operands[2]) 14721 && peep2_reg_dead_p (2, operands[3])" 14722 [(const_int 0)]) 14723 14724;; mov #3,r4 14725;; and r4,r1 -> mov r1,r0 14726;; mov r1,r0 and #3,r0 14727(define_code_iterator ANDIORXOR [and ior xor]) 14728(define_peephole2 14729 [(set (match_operand:SI 0 "register_operand") 14730 (match_operand:SI 1 "const_logical_operand")) 14731 (set (match_operand:SI 2) (ANDIORXOR:SI (match_dup 2) (match_dup 0))) 14732 (set (reg:SI R0_REG) (match_dup 2))] 14733 "TARGET_SH1 14734 && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[2])" 14735 [(set (reg:SI R0_REG) (match_dup 2)) 14736 (set (reg:SI R0_REG) (ANDIORXOR:SI (reg:SI R0_REG) (match_dup 1)))]) 14737 14738;; ... r2,r0 ... r2,r0 14739;; or r1,r0 -> or r0,r1 14740;; mov r0,r1 14741;; (r0 dead) 14742(define_code_iterator ANDIORXORPLUS [and ior xor plus]) 14743(define_peephole2 14744 [(set (match_operand:SI 0 "arith_reg_dest") 14745 (ANDIORXORPLUS:SI (match_dup 0) (match_operand:SI 1 "arith_reg_dest"))) 14746 (set (match_dup 1) (match_dup 0))] 14747 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])" 14748 [(set (match_dup 1) (ANDIORXORPLUS:SI (match_dup 1) (match_dup 0)))]) 14749 14750;; mov r12,r0 14751;; add #-48,r0 -> add #-48,r12 14752;; mov.l r0,@(4,r10) mov.l r12,@(4,r10) 14753;; (r12 dead) 14754(define_peephole2 14755 [(set (match_operand:SI 0 "arith_reg_dest") 14756 (match_operand:SI 1 "arith_reg_dest")) 14757 (set (match_dup 0) (plus:SI (match_dup 0) 14758 (match_operand:SI 2 "const_int_operand"))) 14759 (set (match_operand:SI 3 "general_movdst_operand") (match_dup 0))] 14760 "TARGET_SH1 14761 && peep2_reg_dead_p (2, operands[1]) && peep2_reg_dead_p (3, operands[0])" 14762 [(const_int 0)] 14763{ 14764 emit_insn (gen_addsi3 (operands[1], operands[1], operands[2])); 14765 sh_peephole_emit_move_insn (operands[3], operands[1]); 14766}) 14767 14768;; mov.l @(r0,r9),r1 14769;; mov r1,r0 -> mov @(r0,r9),r0 14770(define_peephole2 14771 [(set (match_operand:SI 0 "arith_reg_dest") 14772 (match_operand:SI 1 "general_movsrc_operand")) 14773 (set (match_operand:SI 2 "arith_reg_dest") 14774 (match_dup 0))] 14775 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])" 14776 [(const_int 0)] 14777{ 14778 sh_peephole_emit_move_insn (operands[2], operands[1]); 14779}) 14780 14781(define_peephole2 14782 [(set (match_operand:QIHI 0 "register_operand") 14783 (match_operand:QIHI 1 "movsrc_no_disp_mem_operand")) 14784 (set (match_operand:QIHI 2 "register_operand") 14785 (match_dup 0))] 14786 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])" 14787 [(const_int 0)] 14788{ 14789 sh_peephole_emit_move_insn (operands[2], operands[1]); 14790}) 14791 14792(define_peephole2 14793 [(set (match_operand:SI 0 "arith_reg_dest") 14794 (sign_extend:SI (match_operand:QIHI 1 "movsrc_no_disp_mem_operand"))) 14795 (set (match_operand:SI 2 "arith_reg_dest") 14796 (match_dup 0))] 14797 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])" 14798 [(const_int 0)] 14799{ 14800 sh_check_add_incdec_notes (emit_insn (gen_extend<mode>si2 (operands[2], 14801 sh_remove_overlapping_post_inc (operands[2], operands[1])))); 14802}) 14803 14804;; mov.w @(18,r1),r0 (r0 = HImode) 14805;; mov r0,r1 (r0 = r1 = HImode) mov.w @(18,r1),r0 14806;; ... ..,r13 (r13 = SImode) -> ... ..,r13 14807;; tst r1,r13 tst r0,r13 14808(define_peephole2 14809 [(set (match_operand 0 "arith_reg_dest") 14810 (match_operand 1 "arith_reg_dest")) 14811 (set (match_operand:SI 2 "arith_reg_dest") 14812 (match_operand:SI 3)) 14813 (set (reg:SI T_REG) 14814 (eq:SI (and:SI (match_operand:SI 4 "arith_reg_operand") 14815 (match_operand:SI 5 "arith_reg_operand")) 14816 (const_int 0)))] 14817 "TARGET_SH1 14818 && peep2_reg_dead_p (3, operands[0]) 14819 && !reg_overlap_mentioned_p (operands[0], operands[3]) 14820 && (REGNO (operands[0]) == REGNO (operands[4]) 14821 || REGNO (operands[0]) == REGNO (operands[5])) 14822 && (REGNO (operands[2]) == REGNO (operands[4]) 14823 || REGNO (operands[2]) == REGNO (operands[5]))" 14824 [(const_int 0)] 14825{ 14826 if (REGNO (operands[1]) == REGNO (operands[2])) 14827 operands[2] = gen_rtx_REG (SImode, REGNO (operands[0])); 14828 14829 // We don't know what the new set insn will be in detail. Just make sure 14830 // that it still can be recognized and the constraints are satisfied. 14831 rtx_insn* i = emit_insn (gen_rtx_SET (VOIDmode, operands[2], 14832 sh_remove_overlapping_post_inc (operands[2], operands[3]))); 14833 14834 recog_data_d prev_recog_data = recog_data; 14835 bool i_invalid = insn_invalid_p (i, false); 14836 recog_data = prev_recog_data; 14837 14838 if (i_invalid) 14839 FAIL; 14840 14841 sh_check_add_incdec_notes (i); 14842 14843 emit_insn (gen_tstsi_t (operands[2], 14844 gen_rtx_REG (SImode, (REGNO (operands[1]))))); 14845}) 14846 14847;; mov.w @(18,r1),r0 (r0 = HImode) 14848;; ... ..,r13 (r13 = SImode) mov.w @(18,r1),r0 14849;; mov r0,r1 (r0 = r1 = HImode) -> ... ..,r13 14850;; tst r1,r13 tst r0,r13 14851(define_peephole2 14852 [(set (match_operand:SI 2 "arith_reg_dest") 14853 (match_operand:SI 3)) 14854 (set (match_operand 0 "arith_reg_dest") 14855 (match_operand 1 "arith_reg_operand")) 14856 (set (reg:SI T_REG) 14857 (eq:SI (and:SI (match_operand:SI 4 "arith_reg_operand") 14858 (match_operand:SI 5 "arith_reg_operand")) 14859 (const_int 0)))] 14860 "TARGET_SH1 14861 && peep2_reg_dead_p (3, operands[0]) 14862 && !reg_overlap_mentioned_p (operands[0], operands[3]) 14863 && (REGNO (operands[0]) == REGNO (operands[4]) 14864 || REGNO (operands[0]) == REGNO (operands[5])) 14865 && (REGNO (operands[2]) == REGNO (operands[4]) 14866 || REGNO (operands[2]) == REGNO (operands[5]))" 14867 [(const_int 0)] 14868{ 14869 // We don't know what the new set insn will be in detail. Just make sure 14870 // that it still can be recognized and the constraints are satisfied. 14871 rtx_insn* i = emit_insn (gen_rtx_SET (VOIDmode, operands[2], 14872 sh_remove_overlapping_post_inc (operands[2], operands[3]))); 14873 14874 recog_data_d prev_recog_data = recog_data; 14875 bool i_invalid = insn_invalid_p (i, false); 14876 recog_data = prev_recog_data; 14877 14878 if (i_invalid) 14879 FAIL; 14880 14881 sh_check_add_incdec_notes (i); 14882 14883 emit_insn (gen_tstsi_t (operands[2], 14884 gen_rtx_REG (SImode, (REGNO (operands[1]))))); 14885}) 14886 14887(define_peephole 14888 [(set (match_operand:SI 0 "register_operand" "=r") 14889 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) 14890 (set (mem:SF (match_dup 0)) 14891 (match_operand:SF 2 "general_movsrc_operand" ""))] 14892 "TARGET_SH1 && REGNO (operands[0]) == 0 14893 && ((REG_P (operands[2]) && REGNO (operands[2]) < 16) 14894 || (GET_CODE (operands[2]) == SUBREG 14895 && REGNO (SUBREG_REG (operands[2])) < 16)) 14896 && reg_unused_after (operands[0], insn)" 14897 "mov.l %2,@(%0,%1)") 14898 14899(define_peephole 14900 [(set (match_operand:SI 0 "register_operand" "=r") 14901 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) 14902 (set (match_operand:SF 2 "general_movdst_operand" "") 14903 14904 (mem:SF (match_dup 0)))] 14905 "TARGET_SH1 && REGNO (operands[0]) == 0 14906 && ((REG_P (operands[2]) && REGNO (operands[2]) < 16) 14907 || (GET_CODE (operands[2]) == SUBREG 14908 && REGNO (SUBREG_REG (operands[2])) < 16)) 14909 && reg_unused_after (operands[0], insn)" 14910 "mov.l @(%0,%1),%2") 14911 14912(define_peephole 14913 [(set (match_operand:SI 0 "register_operand" "=r") 14914 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) 14915 (set (mem:SF (match_dup 0)) 14916 (match_operand:SF 2 "general_movsrc_operand" ""))] 14917 "TARGET_SH2E && REGNO (operands[0]) == 0 14918 && ((REG_P (operands[2]) 14919 && FP_OR_XD_REGISTER_P (REGNO (operands[2]))) 14920 || (GET_CODE (operands[2]) == SUBREG 14921 && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2]))))) 14922 && reg_unused_after (operands[0], insn)" 14923 "fmov{.s|} %2,@(%0,%1)") 14924 14925(define_peephole 14926 [(set (match_operand:SI 0 "register_operand" "=r") 14927 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) 14928 (set (match_operand:SF 2 "general_movdst_operand" "") 14929 14930 (mem:SF (match_dup 0)))] 14931 "TARGET_SH2E && REGNO (operands[0]) == 0 14932 && ((REG_P (operands[2]) 14933 && FP_OR_XD_REGISTER_P (REGNO (operands[2]))) 14934 || (GET_CODE (operands[2]) == SUBREG 14935 && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2]))))) 14936 && reg_unused_after (operands[0], insn)" 14937 "fmov{.s|} @(%0,%1),%2") 14938 14939;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF). 14940(define_insn "sp_switch_1" 14941 [(set (reg:SI SP_REG) (unspec_volatile [(match_operand:SI 0 "" "")] 14942 UNSPECV_SP_SWITCH_B))] 14943 "TARGET_SH1" 14944{ 14945 return "mov.l r0,@-r15" "\n" 14946 " mov.l %0,r0" "\n" 14947 " mov.l @r0,r0" "\n" 14948 " mov.l r15,@-r0" "\n" 14949 " mov r0,r15"; 14950} 14951 [(set_attr "length" "10")]) 14952 14953;; Switch back to the original stack for interrupt functions with the 14954;; sp_switch attribute. 14955(define_insn "sp_switch_2" 14956 [(unspec_volatile [(const_int 0)] 14957 UNSPECV_SP_SWITCH_E)] 14958 "TARGET_SH1" 14959{ 14960 return "mov.l @r15,r15" "\n" 14961 " mov.l @r15+,r0"; 14962} 14963 [(set_attr "length" "4")]) 14964 14965;; ------------------------------------------------------------------------- 14966;; Integer vector moves 14967;; ------------------------------------------------------------------------- 14968 14969(define_expand "movv8qi" 14970 [(set (match_operand:V8QI 0 "general_movdst_operand" "") 14971 (match_operand:V8QI 1 "general_movsrc_operand" ""))] 14972 "TARGET_SHMEDIA" 14973{ 14974 prepare_move_operands (operands, V8QImode); 14975}) 14976 14977(define_insn "movv8qi_i" 14978 [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m") 14979 (match_operand:V8QI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))] 14980 "TARGET_SHMEDIA 14981 && (register_operand (operands[0], V8QImode) 14982 || sh_register_operand (operands[1], V8QImode))" 14983 "@ 14984 add %1, r63, %0 14985 movi %1, %0 14986 # 14987 ld%M1.q %m1, %0 14988 st%M0.q %m0, %N1" 14989 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media") 14990 (set_attr "length" "4,4,16,4,4")]) 14991 14992(define_split 14993 [(set (match_operand:V8QI 0 "arith_reg_dest" "") 14994 (subreg:V8QI (const_int 0) 0))] 14995 "TARGET_SHMEDIA" 14996 [(set (match_dup 0) 14997 (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0) 14998 (const_int 0) (const_int 0) (const_int 0) 14999 (const_int 0) (const_int 0)]))]) 15000 15001(define_split 15002 [(set (match_operand 0 "arith_reg_dest" "") 15003 (match_operand 1 "sh_rep_vec" ""))] 15004 "TARGET_SHMEDIA && reload_completed 15005 && GET_MODE (operands[0]) == GET_MODE (operands[1]) 15006 && sh_vector_mode_supported_p (GET_MODE (operands[0])) 15007 && GET_MODE_SIZE (GET_MODE (operands[0])) == 8 15008 && (XVECEXP (operands[1], 0, 0) != const0_rtx 15009 || XVECEXP (operands[1], 0, 1) != const0_rtx) 15010 && (XVECEXP (operands[1], 0, 0) != constm1_rtx 15011 || XVECEXP (operands[1], 0, 1) != constm1_rtx)" 15012 [(set (match_dup 0) (match_dup 1)) 15013 (match_dup 2)] 15014{ 15015 int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1])); 15016 rtx elt1 = XVECEXP (operands[1], 0, 1); 15017 15018 if (unit_size > 2) 15019 operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]); 15020 else 15021 { 15022 if (unit_size < 2) 15023 operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0])); 15024 operands[2] = gen_mperm_w0 (operands[0], operands[0]); 15025 } 15026 operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0])); 15027 operands[1] = XVECEXP (operands[1], 0, 0); 15028 if (unit_size < 2) 15029 { 15030 if (CONST_INT_P (operands[1]) && CONST_INT_P (elt1)) 15031 operands[1] 15032 = GEN_INT (TARGET_LITTLE_ENDIAN 15033 ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8) 15034 : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff)); 15035 else 15036 { 15037 operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0])); 15038 operands[1] 15039 = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1)); 15040 } 15041 } 15042}) 15043 15044(define_split 15045 [(set (match_operand 0 "arith_reg_dest" "") 15046 (match_operand 1 "sh_const_vec" ""))] 15047 "TARGET_SHMEDIA && reload_completed 15048 && GET_MODE (operands[0]) == GET_MODE (operands[1]) 15049 && sh_vector_mode_supported_p (GET_MODE (operands[0]))" 15050 [(set (match_dup 0) (match_dup 1))] 15051{ 15052 rtx v = operands[1]; 15053 machine_mode new_mode 15054 = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0); 15055 15056 operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0])); 15057 operands[1] 15058 = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0); 15059}) 15060 15061(define_expand "movv2hi" 15062 [(set (match_operand:V2HI 0 "general_movdst_operand" "") 15063 (match_operand:V2HI 1 "general_movsrc_operand" ""))] 15064 "TARGET_SHMEDIA" 15065{ 15066 prepare_move_operands (operands, V2HImode); 15067}) 15068 15069(define_insn "movv2hi_i" 15070 [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m") 15071 (match_operand:V2HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))] 15072 "TARGET_SHMEDIA 15073 && (register_operand (operands[0], V2HImode) 15074 || sh_register_operand (operands[1], V2HImode))" 15075 "@ 15076 add.l %1, r63, %0 15077 movi %1, %0 15078 # 15079 ld%M1.l %m1, %0 15080 st%M0.l %m0, %N1" 15081 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media") 15082 (set_attr "length" "4,4,16,4,4") 15083 (set (attr "highpart") 15084 (cond [(match_test "sh_contains_memref_p (insn)") 15085 (const_string "user")] 15086 (const_string "ignore")))]) 15087 15088(define_expand "movv4hi" 15089 [(set (match_operand:V4HI 0 "general_movdst_operand" "") 15090 (match_operand:V4HI 1 "general_movsrc_operand" ""))] 15091 "TARGET_SHMEDIA" 15092{ 15093 prepare_move_operands (operands, V4HImode); 15094}) 15095 15096(define_insn "movv4hi_i" 15097 [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m") 15098 (match_operand:V4HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))] 15099 "TARGET_SHMEDIA 15100 && (register_operand (operands[0], V4HImode) 15101 || sh_register_operand (operands[1], V4HImode))" 15102 "@ 15103 add %1, r63, %0 15104 movi %1, %0 15105 # 15106 ld%M1.q %m1, %0 15107 st%M0.q %m0, %N1" 15108 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media") 15109 (set_attr "length" "4,4,16,4,4") 15110 (set_attr "highpart" "depend")]) 15111 15112(define_expand "movv2si" 15113 [(set (match_operand:V2SI 0 "general_movdst_operand" "") 15114 (match_operand:V2SI 1 "general_movsrc_operand" ""))] 15115 "TARGET_SHMEDIA" 15116{ 15117 prepare_move_operands (operands, V2SImode); 15118}) 15119 15120(define_insn "movv2si_i" 15121 [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m") 15122 (match_operand:V2SI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))] 15123 "TARGET_SHMEDIA 15124 && (register_operand (operands[0], V2SImode) 15125 || sh_register_operand (operands[1], V2SImode))" 15126 "@ 15127 add %1, r63, %0 15128 # 15129 # 15130 ld%M1.q %m1, %0 15131 st%M0.q %m0, %N1" 15132 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media") 15133 (set_attr "length" "4,4,16,4,4") 15134 (set_attr "highpart" "depend")]) 15135 15136;; ------------------------------------------------------------------------- 15137;; Multimedia Intrinsics 15138;; ------------------------------------------------------------------------- 15139 15140(define_insn "absv2si2" 15141 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15142 (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))] 15143 "TARGET_SHMEDIA" 15144 "mabs.l %1, %0" 15145 [(set_attr "type" "mcmp_media") 15146 (set_attr "highpart" "depend")]) 15147 15148(define_insn "absv4hi2" 15149 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15150 (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))] 15151 "TARGET_SHMEDIA" 15152 "mabs.w %1, %0" 15153 [(set_attr "type" "mcmp_media") 15154 (set_attr "highpart" "depend")]) 15155 15156(define_insn "addv2si3" 15157 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15158 (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r") 15159 (match_operand:V2SI 2 "arith_reg_operand" "r")))] 15160 "TARGET_SHMEDIA" 15161 "madd.l %1, %2, %0" 15162 [(set_attr "type" "arith_media") 15163 (set_attr "highpart" "depend")]) 15164 15165(define_insn "addv4hi3" 15166 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15167 (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r") 15168 (match_operand:V4HI 2 "arith_reg_operand" "r")))] 15169 "TARGET_SHMEDIA" 15170 "madd.w %1, %2, %0" 15171 [(set_attr "type" "arith_media") 15172 (set_attr "highpart" "depend")]) 15173 15174(define_insn_and_split "addv2hi3" 15175 [(set (match_operand:V2HI 0 "arith_reg_dest" "=r") 15176 (plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r") 15177 (match_operand:V2HI 2 "extend_reg_operand" "r")))] 15178 "TARGET_SHMEDIA" 15179 "#" 15180 "TARGET_SHMEDIA" 15181 [(const_int 0)] 15182{ 15183 rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0); 15184 rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0); 15185 rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0); 15186 rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0); 15187 rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0); 15188 15189 emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1)); 15190 emit_insn (gen_truncdisi2 (si_dst, di_dst)); 15191 DONE; 15192} 15193 [(set_attr "highpart" "must_split")]) 15194 15195(define_insn "ssaddv2si3" 15196 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15197 (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r") 15198 (match_operand:V2SI 2 "arith_reg_operand" "r")))] 15199 "TARGET_SHMEDIA" 15200 "madds.l %1, %2, %0" 15201 [(set_attr "type" "mcmp_media") 15202 (set_attr "highpart" "depend")]) 15203 15204(define_insn "usaddv8qi3" 15205 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") 15206 (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r") 15207 (match_operand:V8QI 2 "arith_reg_operand" "r")))] 15208 "TARGET_SHMEDIA" 15209 "madds.ub %1, %2, %0" 15210 [(set_attr "type" "mcmp_media") 15211 (set_attr "highpart" "depend")]) 15212 15213(define_insn "ssaddv4hi3" 15214 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15215 (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r") 15216 (match_operand:V4HI 2 "arith_reg_operand" "r")))] 15217 "TARGET_SHMEDIA" 15218 "madds.w %1, %2, %0" 15219 [(set_attr "type" "mcmp_media") 15220 (set_attr "highpart" "depend")]) 15221 15222(define_insn "negcmpeqv8qi" 15223 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") 15224 (neg:V8QI (eq:V8QI 15225 (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ") 15226 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))] 15227 "TARGET_SHMEDIA" 15228 "mcmpeq.b %N1, %N2, %0" 15229 [(set_attr "type" "mcmp_media") 15230 (set_attr "highpart" "depend")]) 15231 15232(define_insn "negcmpeqv2si" 15233 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15234 (neg:V2SI (eq:V2SI 15235 (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ") 15236 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))] 15237 "TARGET_SHMEDIA" 15238 "mcmpeq.l %N1, %N2, %0" 15239 [(set_attr "type" "mcmp_media") 15240 (set_attr "highpart" "depend")]) 15241 15242(define_insn "negcmpeqv4hi" 15243 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15244 (neg:V4HI (eq:V4HI 15245 (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ") 15246 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))] 15247 "TARGET_SHMEDIA" 15248 "mcmpeq.w %N1, %N2, %0" 15249 [(set_attr "type" "mcmp_media") 15250 (set_attr "highpart" "depend")]) 15251 15252(define_insn "negcmpgtuv8qi" 15253 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") 15254 (neg:V8QI (gtu:V8QI 15255 (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ") 15256 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))] 15257 "TARGET_SHMEDIA" 15258 "mcmpgt.ub %N1, %N2, %0" 15259 [(set_attr "type" "mcmp_media") 15260 (set_attr "highpart" "depend")]) 15261 15262(define_insn "negcmpgtv2si" 15263 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15264 (neg:V2SI (gt:V2SI 15265 (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ") 15266 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))] 15267 "TARGET_SHMEDIA" 15268 "mcmpgt.l %N1, %N2, %0" 15269 [(set_attr "type" "mcmp_media") 15270 (set_attr "highpart" "depend")]) 15271 15272(define_insn "negcmpgtv4hi" 15273 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15274 (neg:V4HI (gt:V4HI 15275 (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ") 15276 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))] 15277 "TARGET_SHMEDIA" 15278 "mcmpgt.w %N1, %N2, %0" 15279 [(set_attr "type" "mcmp_media") 15280 (set_attr "highpart" "depend")]) 15281 15282(define_insn "mcmv" 15283 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 15284 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 15285 (match_operand:DI 2 "arith_reg_operand" "r")) 15286 (and:DI (match_operand:DI 3 "arith_reg_operand" "0") 15287 (not:DI (match_dup 2)))))] 15288 "TARGET_SHMEDIA" 15289 "mcmv %N1, %2, %0" 15290 [(set_attr "type" "arith_media") 15291 (set_attr "highpart" "depend")]) 15292 15293(define_insn "mcnvs_lw" 15294 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15295 (vec_concat:V4HI 15296 (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")) 15297 (ss_truncate:V2HI 15298 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))] 15299 "TARGET_SHMEDIA" 15300 "mcnvs.lw %N1, %N2, %0" 15301 [(set_attr "type" "mcmp_media")]) 15302 15303(define_insn "mcnvs_wb" 15304 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") 15305 (vec_concat:V8QI 15306 (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")) 15307 (ss_truncate:V4QI 15308 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))] 15309 "TARGET_SHMEDIA" 15310 "mcnvs.wb %N1, %N2, %0" 15311 [(set_attr "type" "mcmp_media")]) 15312 15313(define_insn "mcnvs_wub" 15314 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") 15315 (vec_concat:V8QI 15316 (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")) 15317 (us_truncate:V4QI 15318 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))] 15319 "TARGET_SHMEDIA" 15320 "mcnvs.wub %N1, %N2, %0" 15321 [(set_attr "type" "mcmp_media")]) 15322 15323(define_insn "mextr_rl" 15324 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 15325 (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 15326 (match_operand:HI 3 "mextr_bit_offset" "i")) 15327 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ") 15328 (match_operand:HI 4 "mextr_bit_offset" "i"))))] 15329 "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64" 15330{ 15331 static char templ[21]; 15332 sprintf (templ, "mextr%d %%N1, %%N2, %%0", 15333 (int) INTVAL (operands[3]) >> 3); 15334 return templ; 15335} 15336 [(set_attr "type" "arith_media")]) 15337 15338(define_insn "*mextr_lr" 15339 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 15340 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 15341 (match_operand:HI 3 "mextr_bit_offset" "i")) 15342 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ") 15343 (match_operand:HI 4 "mextr_bit_offset" "i"))))] 15344 "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64" 15345{ 15346 static char templ[21]; 15347 sprintf (templ, "mextr%d %%N2, %%N1, %%0", 15348 (int) INTVAL (operands[4]) >> 3); 15349 return templ; 15350} 15351 [(set_attr "type" "arith_media")]) 15352 15353; mextrN can be modelled with vec_select / vec_concat, but the selection 15354; vector then varies depending on endianness. 15355(define_expand "mextr1" 15356 [(match_operand:DI 0 "arith_reg_dest" "") 15357 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 15358 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")] 15359 "TARGET_SHMEDIA" 15360{ 15361 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2], 15362 GEN_INT (1 * 8), GEN_INT (7 * 8))); 15363 DONE; 15364}) 15365 15366(define_expand "mextr2" 15367 [(match_operand:DI 0 "arith_reg_dest" "") 15368 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 15369 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")] 15370 "TARGET_SHMEDIA" 15371{ 15372 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2], 15373 GEN_INT (2 * 8), GEN_INT (6 * 8))); 15374 DONE; 15375}) 15376 15377(define_expand "mextr3" 15378 [(match_operand:DI 0 "arith_reg_dest" "") 15379 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 15380 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")] 15381 "TARGET_SHMEDIA" 15382{ 15383 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2], 15384 GEN_INT (3 * 8), GEN_INT (5 * 8))); 15385 DONE; 15386}) 15387 15388(define_expand "mextr4" 15389 [(match_operand:DI 0 "arith_reg_dest" "") 15390 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 15391 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")] 15392 "TARGET_SHMEDIA" 15393{ 15394 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2], 15395 GEN_INT (4 * 8), GEN_INT (4 * 8))); 15396 DONE; 15397}) 15398 15399(define_expand "mextr5" 15400 [(match_operand:DI 0 "arith_reg_dest" "") 15401 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 15402 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")] 15403 "TARGET_SHMEDIA" 15404{ 15405 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2], 15406 GEN_INT (5 * 8), GEN_INT (3 * 8))); 15407 DONE; 15408}) 15409 15410(define_expand "mextr6" 15411 [(match_operand:DI 0 "arith_reg_dest" "") 15412 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 15413 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")] 15414 "TARGET_SHMEDIA" 15415{ 15416 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2], 15417 GEN_INT (6 * 8), GEN_INT (2 * 8))); 15418 DONE; 15419}) 15420 15421(define_expand "mextr7" 15422 [(match_operand:DI 0 "arith_reg_dest" "") 15423 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 15424 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")] 15425 "TARGET_SHMEDIA" 15426{ 15427 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2], 15428 GEN_INT (7 * 8), GEN_INT (1 * 8))); 15429 DONE; 15430}) 15431 15432(define_expand "mmacfx_wl" 15433 [(match_operand:V2SI 0 "arith_reg_dest" "") 15434 (match_operand:V2HI 1 "extend_reg_operand" "") 15435 (match_operand:V2HI 2 "extend_reg_operand" "") 15436 (match_operand:V2SI 3 "arith_reg_operand" "")] 15437 "TARGET_SHMEDIA" 15438{ 15439 emit_insn (gen_mmacfx_wl_i (operands[0], operands[3], 15440 operands[1], operands[2])); 15441 DONE; 15442}) 15443 15444;; This could be highpart ignore if it only had inputs 2 or 3, but input 1 15445;; is depend 15446(define_insn "mmacfx_wl_i" 15447 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15448 (ss_plus:V2SI 15449 (match_operand:V2SI 1 "arith_reg_operand" "0") 15450 (ss_truncate:V2SI 15451 (ashift:V2DI 15452 (sign_extend:V2DI 15453 (mult:V2SI 15454 (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r")) 15455 (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r")))) 15456 (const_int 1)))))] 15457 "TARGET_SHMEDIA" 15458 "mmacfx.wl %2, %3, %0" 15459 [(set_attr "type" "mac_media") 15460 (set_attr "highpart" "depend")]) 15461 15462(define_expand "mmacnfx_wl" 15463 [(match_operand:V2SI 0 "arith_reg_dest" "") 15464 (match_operand:V2HI 1 "extend_reg_operand" "") 15465 (match_operand:V2HI 2 "extend_reg_operand" "") 15466 (match_operand:V2SI 3 "arith_reg_operand" "")] 15467 "TARGET_SHMEDIA" 15468{ 15469 emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3], 15470 operands[1], operands[2])); 15471 DONE; 15472}) 15473 15474(define_insn "mmacnfx_wl_i" 15475 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15476 (ss_minus:V2SI 15477 (match_operand:V2SI 1 "arith_reg_operand" "0") 15478 (ss_truncate:V2SI 15479 (ashift:V2DI 15480 (sign_extend:V2DI 15481 (mult:V2SI 15482 (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r")) 15483 (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r")))) 15484 (const_int 1)))))] 15485 "TARGET_SHMEDIA" 15486 "mmacnfx.wl %2, %3, %0" 15487 [(set_attr "type" "mac_media") 15488 (set_attr "highpart" "depend")]) 15489 15490(define_insn "mulv2si3" 15491 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15492 (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r") 15493 (match_operand:V2SI 2 "arith_reg_operand" "r")))] 15494 "TARGET_SHMEDIA" 15495 "mmul.l %1, %2, %0" 15496 [(set_attr "type" "d2mpy_media") 15497 (set_attr "highpart" "depend")]) 15498 15499(define_insn "mulv4hi3" 15500 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15501 (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r") 15502 (match_operand:V4HI 2 "arith_reg_operand" "r")))] 15503 "TARGET_SHMEDIA" 15504 "mmul.w %1, %2, %0" 15505 [(set_attr "type" "dmpy_media") 15506 (set_attr "highpart" "depend")]) 15507 15508(define_insn "mmulfx_l" 15509 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15510 (ss_truncate:V2SI 15511 (ashiftrt:V2DI 15512 (mult:V2DI 15513 (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r")) 15514 (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r"))) 15515 (const_int 31))))] 15516 "TARGET_SHMEDIA" 15517 "mmulfx.l %1, %2, %0" 15518 [(set_attr "type" "d2mpy_media") 15519 (set_attr "highpart" "depend")]) 15520 15521(define_insn "mmulfx_w" 15522 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15523 (ss_truncate:V4HI 15524 (ashiftrt:V4SI 15525 (mult:V4SI 15526 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r")) 15527 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r"))) 15528 (const_int 15))))] 15529 "TARGET_SHMEDIA" 15530 "mmulfx.w %1, %2, %0" 15531 [(set_attr "type" "dmpy_media") 15532 (set_attr "highpart" "depend")]) 15533 15534(define_insn "mmulfxrp_w" 15535 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15536 (ss_truncate:V4HI 15537 (ashiftrt:V4SI 15538 (plus:V4SI 15539 (mult:V4SI 15540 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r")) 15541 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r"))) 15542 (const_int 16384)) 15543 (const_int 15))))] 15544 "TARGET_SHMEDIA" 15545 "mmulfxrp.w %1, %2, %0" 15546 [(set_attr "type" "dmpy_media") 15547 (set_attr "highpart" "depend")]) 15548 15549 15550(define_expand "mmulhi_wl" 15551 [(match_operand:V2SI 0 "arith_reg_dest" "") 15552 (match_operand:V4HI 1 "arith_reg_operand" "") 15553 (match_operand:V4HI 2 "arith_reg_operand" "")] 15554 "TARGET_SHMEDIA" 15555{ 15556 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl) 15557 (operands[0], operands[1], operands[2])); 15558 DONE; 15559}) 15560 15561(define_expand "mmullo_wl" 15562 [(match_operand:V2SI 0 "arith_reg_dest" "") 15563 (match_operand:V4HI 1 "arith_reg_operand" "") 15564 (match_operand:V4HI 2 "arith_reg_operand" "")] 15565 "TARGET_SHMEDIA" 15566{ 15567 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl) 15568 (operands[0], operands[1], operands[2])); 15569 DONE; 15570}) 15571 15572(define_insn "mmul23_wl" 15573 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15574 (vec_select:V2SI 15575 (mult:V4SI 15576 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r")) 15577 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r"))) 15578 (parallel [(const_int 2) (const_int 3)])))] 15579 "TARGET_SHMEDIA" 15580{ 15581 return (TARGET_LITTLE_ENDIAN 15582 ? "mmulhi.wl %1, %2, %0" 15583 : "mmullo.wl %1, %2, %0"); 15584} 15585 [(set_attr "type" "dmpy_media") 15586 (set (attr "highpart") 15587 (cond [(eq_attr "endian" "big") (const_string "ignore")] 15588 (const_string "user")))]) 15589 15590(define_insn "mmul01_wl" 15591 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15592 (vec_select:V2SI 15593 (mult:V4SI 15594 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r")) 15595 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r"))) 15596 (parallel [(const_int 0) (const_int 1)])))] 15597 "TARGET_SHMEDIA" 15598{ 15599 return (TARGET_LITTLE_ENDIAN 15600 ? "mmullo.wl %1, %2, %0" 15601 : "mmulhi.wl %1, %2, %0"); 15602} 15603 [(set_attr "type" "dmpy_media") 15604 (set (attr "highpart") 15605 (cond [(eq_attr "endian" "little") (const_string "ignore")] 15606 (const_string "user")))]) 15607 15608 15609(define_expand "mmulsum_wq" 15610 [(match_operand:DI 0 "arith_reg_dest" "") 15611 (match_operand:V4HI 1 "arith_reg_operand" "") 15612 (match_operand:V4HI 2 "arith_reg_operand" "") 15613 (match_operand:DI 3 "arith_reg_operand" "")] 15614 "TARGET_SHMEDIA" 15615{ 15616 emit_insn (gen_mmulsum_wq_i (operands[0], operands[3], 15617 operands[1], operands[2])); 15618 DONE; 15619}) 15620 15621(define_insn "mmulsum_wq_i" 15622 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 15623 (plus:DI (match_operand:DI 1 "arith_reg_operand" "0") 15624 (plus:DI 15625 (plus:DI 15626 (vec_select:DI 15627 (mult:V4DI 15628 (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r")) 15629 (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r"))) 15630 (parallel [(const_int 0)])) 15631 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2)) 15632 (sign_extend:V4DI (match_dup 3))) 15633 (parallel [(const_int 1)]))) 15634 (plus:DI 15635 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2)) 15636 (sign_extend:V4DI (match_dup 3))) 15637 (parallel [(const_int 2)])) 15638 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2)) 15639 (sign_extend:V4DI (match_dup 3))) 15640 (parallel [(const_int 3)]))))))] 15641 "TARGET_SHMEDIA" 15642 "mmulsum.wq %2, %3, %0" 15643 [(set_attr "type" "mac_media")]) 15644 15645(define_expand "mperm_w" 15646 [(match_operand:V4HI 0 "arith_reg_dest" "=r") 15647 (match_operand:V4HI 1 "arith_reg_operand" "r") 15648 (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")] 15649 "TARGET_SHMEDIA" 15650{ 15651 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big) 15652 (operands[0], operands[1], operands[2])); 15653 DONE; 15654}) 15655 15656; This use of vec_select isn't exactly correct according to rtl.texi 15657; (because not constant), but it seems a straightforward extension. 15658(define_insn "mperm_w_little" 15659 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15660 (vec_select:V4HI 15661 (match_operand:V4HI 1 "arith_reg_operand" "r") 15662 (parallel 15663 [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ") 15664 (const_int 2) (const_int 0)) 15665 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2)) 15666 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4)) 15667 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))] 15668 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN" 15669 "mperm.w %1, %N2, %0" 15670 [(set_attr "type" "arith_media")]) 15671 15672(define_insn "mperm_w_big" 15673 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15674 (vec_select:V4HI 15675 (match_operand:V4HI 1 "arith_reg_operand" "r") 15676 (parallel 15677 [(zero_extract:QI (not:QI (match_operand:QI 2 15678 "extend_reg_or_0_operand" "rZ")) 15679 (const_int 2) (const_int 0)) 15680 (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2)) 15681 (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4)) 15682 (zero_extract:QI (not:QI (match_dup 2)) 15683 (const_int 2) (const_int 6))])))] 15684 "TARGET_SHMEDIA && TARGET_BIG_ENDIAN" 15685 "mperm.w %1, %N2, %0" 15686 [(set_attr "type" "arith_media")]) 15687 15688(define_insn "mperm_w0" 15689 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15690 (vec_duplicate:V4HI (truncate:HI (match_operand 1 15691 "trunc_hi_operand" "r"))))] 15692 "TARGET_SHMEDIA" 15693 "mperm.w %1, r63, %0" 15694 [(set_attr "type" "arith_media") 15695 (set_attr "highpart" "ignore")]) 15696 15697(define_expand "msad_ubq" 15698 [(match_operand:DI 0 "arith_reg_dest" "") 15699 (match_operand:V8QI 1 "arith_reg_or_0_operand" "") 15700 (match_operand:V8QI 2 "arith_reg_or_0_operand" "") 15701 (match_operand:DI 3 "arith_reg_operand" "")] 15702 "TARGET_SHMEDIA" 15703{ 15704 emit_insn (gen_msad_ubq_i (operands[0], operands[3], 15705 operands[1], operands[2])); 15706 DONE; 15707}) 15708 15709(define_insn "msad_ubq_i" 15710 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 15711 (plus:DI 15712 (plus:DI 15713 (plus:DI 15714 (plus:DI 15715 (match_operand:DI 1 "arith_reg_operand" "0") 15716 (abs:DI (vec_select:DI 15717 (minus:V8DI 15718 (zero_extend:V8DI 15719 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")) 15720 (zero_extend:V8DI 15721 (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ"))) 15722 (parallel [(const_int 0)])))) 15723 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) 15724 (zero_extend:V8DI (match_dup 3))) 15725 (parallel [(const_int 1)])))) 15726 (plus:DI 15727 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) 15728 (zero_extend:V8DI (match_dup 3))) 15729 (parallel [(const_int 2)]))) 15730 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) 15731 (zero_extend:V8DI (match_dup 3))) 15732 (parallel [(const_int 3)]))))) 15733 (plus:DI 15734 (plus:DI 15735 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) 15736 (zero_extend:V8DI (match_dup 3))) 15737 (parallel [(const_int 4)]))) 15738 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) 15739 (zero_extend:V8DI (match_dup 3))) 15740 (parallel [(const_int 5)])))) 15741 (plus:DI 15742 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) 15743 (zero_extend:V8DI (match_dup 3))) 15744 (parallel [(const_int 6)]))) 15745 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) 15746 (zero_extend:V8DI (match_dup 3))) 15747 (parallel [(const_int 7)])))))))] 15748 "TARGET_SHMEDIA" 15749 "msad.ubq %N2, %N3, %0" 15750 [(set_attr "type" "mac_media")]) 15751 15752(define_insn "mshalds_l" 15753 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15754 (ss_truncate:V2SI 15755 (ashift:V2DI 15756 (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r")) 15757 (and:DI (match_operand:DI 2 "arith_reg_operand" "r") 15758 (const_int 31)))))] 15759 "TARGET_SHMEDIA" 15760 "mshalds.l %1, %2, %0" 15761 [(set_attr "type" "mcmp_media") 15762 (set_attr "highpart" "depend")]) 15763 15764(define_insn "mshalds_w" 15765 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15766 (ss_truncate:V4HI 15767 (ashift:V4SI 15768 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r")) 15769 (and:DI (match_operand:DI 2 "arith_reg_operand" "r") 15770 (const_int 15)))))] 15771 "TARGET_SHMEDIA" 15772 "mshalds.w %1, %2, %0" 15773 [(set_attr "type" "mcmp_media") 15774 (set_attr "highpart" "depend")]) 15775 15776(define_insn "ashrv2si3" 15777 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15778 (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r") 15779 (match_operand:DI 2 "arith_reg_operand" "r")))] 15780 "TARGET_SHMEDIA" 15781 "mshard.l %1, %2, %0" 15782 [(set_attr "type" "arith_media") 15783 (set_attr "highpart" "depend")]) 15784 15785(define_insn "ashrv4hi3" 15786 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15787 (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r") 15788 (match_operand:DI 2 "arith_reg_operand" "r")))] 15789 "TARGET_SHMEDIA" 15790 "mshard.w %1, %2, %0" 15791 [(set_attr "type" "arith_media") 15792 (set_attr "highpart" "depend")]) 15793 15794(define_insn "mshards_q" 15795 [(set (match_operand:HI 0 "arith_reg_dest" "=r") 15796 (ss_truncate:HI 15797 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r") 15798 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))] 15799 "TARGET_SHMEDIA" 15800 "mshards.q %1, %N2, %0" 15801 [(set_attr "type" "mcmp_media")]) 15802 15803(define_expand "mshfhi_b" 15804 [(match_operand:V8QI 0 "arith_reg_dest" "") 15805 (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ") 15806 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")] 15807 "TARGET_SHMEDIA" 15808{ 15809 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b) 15810 (operands[0], operands[1], operands[2])); 15811 DONE; 15812}) 15813 15814(define_expand "mshflo_b" 15815 [(match_operand:V8QI 0 "arith_reg_dest" "") 15816 (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ") 15817 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")] 15818 "TARGET_SHMEDIA" 15819{ 15820 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b) 15821 (operands[0], operands[1], operands[2])); 15822 DONE; 15823}) 15824 15825(define_insn "mshf4_b" 15826 [(set 15827 (match_operand:V8QI 0 "arith_reg_dest" "=r") 15828 (vec_select:V8QI 15829 (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ") 15830 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")) 15831 (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13) 15832 (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))] 15833 "TARGET_SHMEDIA" 15834{ 15835 return (TARGET_LITTLE_ENDIAN 15836 ? "mshfhi.b %N1, %N2, %0" 15837 : "mshflo.b %N1, %N2, %0"); 15838} 15839 [(set_attr "type" "arith_media") 15840 (set (attr "highpart") 15841 (cond [(eq_attr "endian" "big") (const_string "ignore")] 15842 (const_string "user")))]) 15843 15844(define_insn "mshf0_b" 15845 [(set 15846 (match_operand:V8QI 0 "arith_reg_dest" "=r") 15847 (vec_select:V8QI 15848 (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ") 15849 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")) 15850 (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9) 15851 (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))] 15852 "TARGET_SHMEDIA" 15853{ 15854 return (TARGET_LITTLE_ENDIAN 15855 ? "mshflo.b %N1, %N2, %0" 15856 : "mshfhi.b %N1, %N2, %0"); 15857} 15858 [(set_attr "type" "arith_media") 15859 (set (attr "highpart") 15860 (cond [(eq_attr "endian" "little") (const_string "ignore")] 15861 (const_string "user")))]) 15862 15863(define_expand "mshfhi_l" 15864 [(match_operand:V2SI 0 "arith_reg_dest" "") 15865 (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ") 15866 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")] 15867 "TARGET_SHMEDIA" 15868{ 15869 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l) 15870 (operands[0], operands[1], operands[2])); 15871 DONE; 15872}) 15873 15874(define_expand "mshflo_l" 15875 [(match_operand:V2SI 0 "arith_reg_dest" "") 15876 (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ") 15877 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")] 15878 "TARGET_SHMEDIA" 15879{ 15880 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l) 15881 (operands[0], operands[1], operands[2])); 15882 DONE; 15883}) 15884 15885(define_insn "mshf4_l" 15886 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15887 (vec_select:V2SI 15888 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ") 15889 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")) 15890 (parallel [(const_int 1) (const_int 3)])))] 15891 "TARGET_SHMEDIA" 15892{ 15893 return (TARGET_LITTLE_ENDIAN 15894 ? "mshfhi.l %N1, %N2, %0" 15895 : "mshflo.l %N1, %N2, %0"); 15896} 15897 [(set_attr "type" "arith_media") 15898 (set (attr "highpart") 15899 (cond [(eq_attr "endian" "big") (const_string "ignore")] 15900 (const_string "user")))]) 15901 15902(define_insn "mshf0_l" 15903 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 15904 (vec_select:V2SI 15905 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ") 15906 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")) 15907 (parallel [(const_int 0) (const_int 2)])))] 15908 "TARGET_SHMEDIA" 15909{ 15910 return (TARGET_LITTLE_ENDIAN 15911 ? "mshflo.l %N1, %N2, %0" 15912 : "mshfhi.l %N1, %N2, %0"); 15913} 15914 [(set_attr "type" "arith_media") 15915 (set (attr "highpart") 15916 (cond [(eq_attr "endian" "little") (const_string "ignore")] 15917 (const_string "user")))]) 15918 15919(define_expand "mshfhi_w" 15920 [(match_operand:V4HI 0 "arith_reg_dest" "") 15921 (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ") 15922 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")] 15923 "TARGET_SHMEDIA" 15924{ 15925 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w) 15926 (operands[0], operands[1], operands[2])); 15927 DONE; 15928}) 15929 15930(define_expand "mshflo_w" 15931 [(match_operand:V4HI 0 "arith_reg_dest" "") 15932 (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ") 15933 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")] 15934 "TARGET_SHMEDIA" 15935{ 15936 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w) 15937 (operands[0], operands[1], operands[2])); 15938 DONE; 15939}) 15940 15941(define_insn "mshf4_w" 15942 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15943 (vec_select:V4HI 15944 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ") 15945 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")) 15946 (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))] 15947 "TARGET_SHMEDIA" 15948{ 15949 return (TARGET_LITTLE_ENDIAN 15950 ? "mshfhi.w %N1, %N2, %0" 15951 : "mshflo.w %N1, %N2, %0"); 15952} 15953 [(set_attr "type" "arith_media") 15954 (set (attr "highpart") 15955 (cond [(eq_attr "endian" "big") (const_string "ignore")] 15956 (const_string "user")))]) 15957 15958(define_insn "mshf0_w" 15959 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15960 (vec_select:V4HI 15961 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ") 15962 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")) 15963 (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))] 15964 "TARGET_SHMEDIA" 15965{ 15966 return (TARGET_LITTLE_ENDIAN 15967 ? "mshflo.w %N1, %N2, %0" 15968 : "mshfhi.w %N1, %N2, %0"); 15969} 15970 [(set_attr "type" "arith_media") 15971 (set (attr "highpart") 15972 (cond [(eq_attr "endian" "little") (const_string "ignore")] 15973 (const_string "user")))]) 15974 15975(define_insn "mshflo_w_x" 15976 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 15977 (vec_select:V4HI 15978 (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ") 15979 (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ")) 15980 (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))] 15981 "TARGET_SHMEDIA" 15982 "mshflo.w %N1, %N2, %0" 15983 [(set_attr "type" "arith_media") 15984 (set_attr "highpart" "ignore")]) 15985 15986;; These are useful to expand ANDs and as combiner patterns. 15987(define_insn_and_split "mshfhi_l_di" 15988 [(set (match_operand:DI 0 "arith_reg_dest" "=r,f") 15989 (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f") 15990 (const_int 32)) 15991 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f") 15992 (const_int -4294967296))))] 15993 "TARGET_SHMEDIA" 15994 "@ 15995 mshfhi.l %N1, %N2, %0 15996 #" 15997 "TARGET_SHMEDIA && reload_completed 15998 && ! GENERAL_REGISTER_P (true_regnum (operands[0]))" 15999 [(set (match_dup 3) (match_dup 4)) 16000 (set (match_dup 5) (match_dup 6))] 16001{ 16002 operands[3] = gen_lowpart (SImode, operands[0]); 16003 operands[4] = gen_highpart (SImode, operands[1]); 16004 operands[5] = gen_highpart (SImode, operands[0]); 16005 operands[6] = gen_highpart (SImode, operands[2]); 16006} 16007 [(set_attr "type" "arith_media")]) 16008 16009(define_insn "*mshfhi_l_di_rev" 16010 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16011 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 16012 (const_int -4294967296)) 16013 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ") 16014 (const_int 32))))] 16015 "TARGET_SHMEDIA" 16016 "mshfhi.l %N2, %N1, %0" 16017 [(set_attr "type" "arith_media")]) 16018 16019(define_split 16020 [(set (match_operand:DI 0 "arith_reg_dest" "") 16021 (ior:DI (zero_extend:DI (match_operand:SI 1 16022 "extend_reg_or_0_operand" "")) 16023 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "") 16024 (const_int -4294967296)))) 16025 (clobber (match_operand:DI 3 "arith_reg_dest" ""))] 16026 "TARGET_SHMEDIA" 16027 [(const_int 0)] 16028{ 16029 emit_insn (gen_ashldi3_media (operands[3], 16030 simplify_gen_subreg (DImode, operands[1], 16031 SImode, 0), 16032 GEN_INT (32))); 16033 emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2])); 16034 DONE; 16035}) 16036 16037(define_insn "mshflo_l_di" 16038 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16039 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 16040 (const_int 4294967295)) 16041 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ") 16042 (const_int 32))))] 16043 16044 "TARGET_SHMEDIA" 16045 "mshflo.l %N1, %N2, %0" 16046 [(set_attr "type" "arith_media") 16047 (set_attr "highpart" "ignore")]) 16048 16049(define_insn "*mshflo_l_di_rev" 16050 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16051 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 16052 (const_int 32)) 16053 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ") 16054 (const_int 4294967295))))] 16055 16056 "TARGET_SHMEDIA" 16057 "mshflo.l %N2, %N1, %0" 16058 [(set_attr "type" "arith_media") 16059 (set_attr "highpart" "ignore")]) 16060 16061;; Combiner pattern for trampoline initialization. 16062(define_insn_and_split "*double_shori" 16063 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16064 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0") 16065 (const_int 32)) 16066 (match_operand:DI 2 "const_int_operand" "n")))] 16067 "TARGET_SHMEDIA 16068 && ! (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xffffffffUL)" 16069 "#" 16070 "rtx_equal_p (operands[0], operands[1])" 16071 [(const_int 0)] 16072{ 16073 HOST_WIDE_INT v = INTVAL (operands[2]); 16074 16075 emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v >> 16))); 16076 emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v & 65535))); 16077 DONE; 16078} 16079 [(set_attr "highpart" "ignore")]) 16080 16081(define_insn "*mshflo_l_di_x" 16082 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16083 (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand" 16084 "rZ")) 16085 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ") 16086 (const_int 32))))] 16087 "TARGET_SHMEDIA" 16088 "mshflo.l %N1, %N2, %0" 16089 [(set_attr "type" "arith_media") 16090 (set_attr "highpart" "ignore")]) 16091 16092(define_insn_and_split "concat_v2sf" 16093 [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?") 16094;; (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f") 16095 (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f") 16096 (match_operand:SF 2 "register_operand" "rZ,f,f")))] 16097 "TARGET_SHMEDIA" 16098 "@ 16099 mshflo.l %N1, %N2, %0 16100 # 16101 #" 16102 "TARGET_SHMEDIA && reload_completed 16103 && ! GENERAL_REGISTER_P (true_regnum (operands[0]))" 16104 [(set (match_dup 3) (match_dup 1)) 16105 (set (match_dup 4) (match_dup 2))] 16106{ 16107 operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0); 16108 operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4); 16109} 16110 [(set_attr "type" "arith_media") 16111 (set_attr "highpart" "ignore")]) 16112 16113(define_insn "*mshflo_l_di_x_rev" 16114 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16115 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ") 16116 (const_int 32)) 16117 (zero_extend:DI 16118 (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))] 16119 "TARGET_SHMEDIA" 16120 "mshflo.l %N2, %N1, %0" 16121 [(set_attr "type" "arith_media") 16122 (set_attr "highpart" "ignore")]) 16123 16124(define_insn "ashlv2si3" 16125 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 16126 (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r") 16127 (match_operand:DI 2 "shift_count_reg_operand" "r")))] 16128 "TARGET_SHMEDIA" 16129 "mshlld.l %1, %2, %0" 16130 [(set_attr "type" "arith_media") 16131 (set_attr "highpart" "depend")]) 16132 16133(define_split 16134 [(set (match_operand 0 "any_register_operand" "") 16135 (match_operator 3 "shift_operator" 16136 [(match_operand 1 "any_register_operand" "") 16137 (match_operand 2 "shift_count_reg_operand" "")]))] 16138 "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)" 16139 [(set (match_dup 0) (match_dup 3))] 16140{ 16141 rtx count = operands[2]; 16142 machine_mode outer_mode = GET_MODE (operands[2]), inner_mode; 16143 16144 while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND 16145 || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0) 16146 || GET_CODE (count) == TRUNCATE) 16147 count = XEXP (count, 0); 16148 inner_mode = GET_MODE (count); 16149 count = simplify_gen_subreg (outer_mode, count, inner_mode, 16150 subreg_lowpart_offset (outer_mode, inner_mode)); 16151 operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]), 16152 operands[1], count); 16153}) 16154 16155(define_insn "ashlv4hi3" 16156 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 16157 (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r") 16158 (match_operand:DI 2 "shift_count_reg_operand" "r")))] 16159 "TARGET_SHMEDIA" 16160 "mshlld.w %1, %2, %0" 16161 [(set_attr "type" "arith_media") 16162 (set_attr "highpart" "depend")]) 16163 16164(define_insn "lshrv2si3" 16165 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 16166 (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r") 16167 (match_operand:DI 2 "shift_count_reg_operand" "r")))] 16168 "TARGET_SHMEDIA" 16169 "mshlrd.l %1, %2, %0" 16170 [(set_attr "type" "arith_media") 16171 (set_attr "highpart" "depend")]) 16172 16173(define_insn "lshrv4hi3" 16174 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 16175 (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r") 16176 (match_operand:DI 2 "shift_count_reg_operand" "r")))] 16177 "TARGET_SHMEDIA" 16178 "mshlrd.w %1, %2, %0" 16179 [(set_attr "type" "arith_media") 16180 (set_attr "highpart" "depend")]) 16181 16182(define_insn "subv2si3" 16183 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 16184 (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ") 16185 (match_operand:V2SI 2 "arith_reg_operand" "r")))] 16186 "TARGET_SHMEDIA" 16187 "msub.l %N1, %2, %0" 16188 [(set_attr "type" "arith_media") 16189 (set_attr "highpart" "depend")]) 16190 16191(define_insn "subv4hi3" 16192 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 16193 (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ") 16194 (match_operand:V4HI 2 "arith_reg_operand" "r")))] 16195 "TARGET_SHMEDIA" 16196 "msub.w %N1, %2, %0" 16197 [(set_attr "type" "arith_media") 16198 (set_attr "highpart" "depend")]) 16199 16200(define_insn_and_split "subv2hi3" 16201 [(set (match_operand:V2HI 0 "arith_reg_dest" "=r") 16202 (minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ") 16203 (match_operand:V2HI 2 "arith_reg_operand" "r")))] 16204 "TARGET_SHMEDIA" 16205 "#" 16206 "TARGET_SHMEDIA" 16207 [(const_int 0)] 16208{ 16209 rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0); 16210 rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0); 16211 rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0); 16212 rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0); 16213 rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0); 16214 16215 emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1)); 16216 emit_insn (gen_truncdisi2 (si_dst, di_dst)); 16217 DONE; 16218} 16219 [(set_attr "highpart" "must_split")]) 16220 16221(define_insn "sssubv2si3" 16222 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") 16223 (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ") 16224 (match_operand:V2SI 2 "arith_reg_operand" "r")))] 16225 "TARGET_SHMEDIA" 16226 "msubs.l %N1, %2, %0" 16227 [(set_attr "type" "mcmp_media") 16228 (set_attr "highpart" "depend")]) 16229 16230(define_insn "ussubv8qi3" 16231 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") 16232 (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ") 16233 (match_operand:V8QI 2 "arith_reg_operand" "r")))] 16234 "TARGET_SHMEDIA" 16235 "msubs.ub %N1, %2, %0" 16236 [(set_attr "type" "mcmp_media") 16237 (set_attr "highpart" "depend")]) 16238 16239(define_insn "sssubv4hi3" 16240 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") 16241 (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ") 16242 (match_operand:V4HI 2 "arith_reg_operand" "r")))] 16243 "TARGET_SHMEDIA" 16244 "msubs.w %N1, %2, %0" 16245 [(set_attr "type" "mcmp_media") 16246 (set_attr "highpart" "depend")]) 16247 16248;; ------------------------------------------------------------------------- 16249;; Floating Point Intrinsics 16250;; ------------------------------------------------------------------------- 16251 16252(define_insn "fcosa_s" 16253 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 16254 (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")] 16255 UNSPEC_FCOSA))] 16256 "TARGET_SHMEDIA" 16257 "fcosa.s %1, %0" 16258 [(set_attr "type" "atrans_media")]) 16259 16260(define_insn "fsina_s" 16261 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 16262 (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")] 16263 UNSPEC_FSINA))] 16264 "TARGET_SHMEDIA" 16265 "fsina.s %1, %0" 16266 [(set_attr "type" "atrans_media")]) 16267 16268(define_insn "fipr" 16269 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 16270 (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1 16271 "fp_arith_reg_operand" "f") 16272 (match_operand:V4SF 2 16273 "fp_arith_reg_operand" "f")) 16274 (parallel [(const_int 0)])) 16275 (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2)) 16276 (parallel [(const_int 1)]))) 16277 (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2)) 16278 (parallel [(const_int 2)])) 16279 (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2)) 16280 (parallel [(const_int 3)])))))] 16281 "TARGET_SHMEDIA" 16282 "fipr.s %1, %2, %0" 16283 [(set_attr "type" "fparith_media")]) 16284 16285(define_insn "fsrra_s" 16286 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") 16287 (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")] 16288 UNSPEC_FSRRA))] 16289 "TARGET_SHMEDIA" 16290 "fsrra.s %1, %0" 16291 [(set_attr "type" "atrans_media")]) 16292 16293(define_insn "ftrv" 16294 [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f") 16295 (plus:V4SF 16296 (plus:V4SF 16297 (mult:V4SF 16298 (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f") 16299 (parallel [(const_int 0) (const_int 5) 16300 (const_int 10) (const_int 15)])) 16301 (match_operand:V4SF 2 "fp_arith_reg_operand" "f")) 16302 (mult:V4SF 16303 (vec_select:V4SF (match_dup 1) 16304 (parallel [(const_int 4) (const_int 9) 16305 (const_int 14) (const_int 3)])) 16306 (vec_select:V4SF (match_dup 2) 16307 (parallel [(const_int 1) (const_int 2) 16308 (const_int 3) (const_int 0)])))) 16309 (plus:V4SF 16310 (mult:V4SF 16311 (vec_select:V4SF (match_dup 1) 16312 (parallel [(const_int 8) (const_int 13) 16313 (const_int 2) (const_int 7)])) 16314 (vec_select:V4SF (match_dup 2) 16315 (parallel [(const_int 2) (const_int 3) 16316 (const_int 0) (const_int 1)]))) 16317 (mult:V4SF 16318 (vec_select:V4SF (match_dup 1) 16319 (parallel [(const_int 12) (const_int 1) 16320 (const_int 6) (const_int 11)])) 16321 (vec_select:V4SF (match_dup 2) 16322 (parallel [(const_int 3) (const_int 0) 16323 (const_int 1) (const_int 2)]))))))] 16324 "TARGET_SHMEDIA" 16325 "ftrv.s %1, %2, %0" 16326 [(set_attr "type" "fparith_media")]) 16327 16328(define_insn "ldhi_l" 16329 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 16330 (zero_extract:SI 16331 (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p") 16332 (const_int 3)) 16333 (const_int -3))) 16334 (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1)) 16335 (const_int 0)))] 16336 "TARGET_SHMEDIA32" 16337 "ldhi.l %U1, %0" 16338 [(set_attr "type" "load_media")]) 16339 16340(define_insn "ldhi_q" 16341 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16342 (zero_extract:DI 16343 (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p") 16344 (const_int 7)) 16345 (const_int -7))) 16346 (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1)) 16347 (const_int 0)))] 16348 "TARGET_SHMEDIA32" 16349 "ldhi.q %U1, %0" 16350 [(set_attr "type" "load_media")]) 16351 16352(define_insn_and_split "*ldhi_q_comb0" 16353 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16354 (zero_extract:DI 16355 (mem:DI (plus:SI (ior:SI (plus:SI 16356 (match_operand:SI 1 "register_operand" "r") 16357 (match_operand:SI 2 "ua_offset" "I06")) 16358 (const_int 7)) 16359 (const_int -7))) 16360 (plus:SI (and:SI (match_dup 1) (const_int 7)) 16361 (const_int 1)) 16362 (const_int 0)))] 16363 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0" 16364 "#" 16365 "" 16366 [(pc)] 16367{ 16368 emit_insn (gen_ldhi_q (operands[0], 16369 gen_rtx_PLUS (SImode, operands[1], operands[2]))); 16370 DONE; 16371}) 16372 16373(define_insn_and_split "*ldhi_q_comb1" 16374 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16375 (zero_extract:DI 16376 (mem:DI (plus:SI (ior:SI (plus:SI 16377 (match_operand:SI 1 "register_operand" "r") 16378 (match_operand:SI 2 "ua_offset" "I06")) 16379 (const_int 7)) 16380 (const_int -7))) 16381 (plus:SI (and:SI (plus:SI (match_dup 1) 16382 (match_operand:SI 3 "ua_offset" "I06")) 16383 (const_int 7)) 16384 (const_int 1)) 16385 (const_int 0)))] 16386 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8) 16387 && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])" 16388 "#" 16389 "" 16390 [(pc)] 16391{ 16392 emit_insn (gen_ldhi_q (operands[0], 16393 gen_rtx_PLUS (SImode, operands[1], operands[2]))); 16394 DONE; 16395}) 16396 16397(define_insn "ldlo_l" 16398 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 16399 (zero_extract:SI 16400 (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p") 16401 (const_int -4))) 16402 (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3))) 16403 (and:SI (match_dup 1) (const_int 3))))] 16404 "TARGET_SHMEDIA32" 16405 "ldlo.l %U1, %0" 16406 [(set_attr "type" "load_media")]) 16407 16408(define_insn "ldlo_q" 16409 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16410 (zero_extract:DI 16411 (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p") 16412 (const_int -8))) 16413 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7))) 16414 (and:SI (match_dup 1) (const_int 7))))] 16415 "TARGET_SHMEDIA32" 16416 "ldlo.q %U1, %0" 16417 [(set_attr "type" "load_media")]) 16418 16419(define_insn_and_split "*ldlo_q_comb0" 16420 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16421 (zero_extract:DI 16422 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r") 16423 (match_operand:SI 2 "ua_offset" "I06")) 16424 (const_int -8))) 16425 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7))) 16426 (and:SI (match_dup 1) (const_int 7))))] 16427 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0" 16428 "#" 16429 "" 16430 [(pc)] 16431{ 16432 emit_insn (gen_ldlo_q (operands[0], 16433 gen_rtx_PLUS (SImode, operands[1], operands[2]))); 16434 DONE; 16435}) 16436 16437(define_insn_and_split "*ldlo_q_comb1" 16438 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16439 (zero_extract:DI 16440 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r") 16441 (match_operand:SI 2 "ua_offset" "I06")) 16442 (const_int -8))) 16443 (minus:SI (const_int 8) 16444 (and:SI (plus:SI (match_dup 1) 16445 (match_operand:SI 3 "ua_offset" "I06")) 16446 (const_int 7))) 16447 (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))] 16448 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8) 16449 && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])" 16450 "#" 16451 "" 16452 [(pc)] 16453{ 16454 emit_insn (gen_ldlo_q (operands[0], 16455 gen_rtx_PLUS (SImode, operands[1], operands[2]))); 16456 DONE; 16457}) 16458 16459(define_insn "sthi_l" 16460 [(set (zero_extract:SI 16461 (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p") 16462 (const_int 3)) 16463 (const_int -3))) 16464 (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1)) 16465 (const_int 0)) 16466 (match_operand:SI 1 "arith_reg_operand" "r"))] 16467 "TARGET_SHMEDIA32" 16468 "sthi.l %U0, %1" 16469 [(set_attr "type" "ustore_media")]) 16470 16471;; All unaligned stores are considered to be 'narrow' because they typically 16472;; operate on less that a quadword, and when they operate on a full quadword, 16473;; the vanilla store high / store low sequence will cause a stall if not 16474;; scheduled apart. 16475(define_insn "sthi_q" 16476 [(set (zero_extract:DI 16477 (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p") 16478 (const_int 7)) 16479 (const_int -7))) 16480 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1)) 16481 (const_int 0)) 16482 (match_operand:DI 1 "arith_reg_operand" "r"))] 16483 "TARGET_SHMEDIA32" 16484 "sthi.q %U0, %1" 16485 [(set_attr "type" "ustore_media")]) 16486 16487(define_insn_and_split "*sthi_q_comb0" 16488 [(set (zero_extract:DI 16489 (mem:DI (plus:SI (ior:SI (plus:SI 16490 (match_operand:SI 0 "register_operand" "r") 16491 (match_operand:SI 1 "ua_offset" "I06")) 16492 (const_int 7)) 16493 (const_int -7))) 16494 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1)) 16495 (const_int 0)) 16496 (match_operand:DI 2 "arith_reg_operand" "r"))] 16497 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0" 16498 "#" 16499 "" 16500 [(pc)] 16501{ 16502 emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]), 16503 operands[2])); 16504 DONE; 16505}) 16506 16507(define_insn_and_split "*sthi_q_comb1" 16508 [(set (zero_extract:DI 16509 (mem:DI (plus:SI (ior:SI (plus:SI 16510 (match_operand:SI 0 "register_operand" "r") 16511 (match_operand:SI 1 "ua_offset" "I06")) 16512 (const_int 7)) 16513 (const_int -7))) 16514 (plus:SI (and:SI (plus:SI (match_dup 0) 16515 (match_operand:SI 2 "ua_offset" "I06")) 16516 (const_int 7)) 16517 (const_int 1)) 16518 (const_int 0)) 16519 (match_operand:DI 3 "arith_reg_operand" "r"))] 16520 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8) 16521 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])" 16522 "#" 16523 "" 16524 [(pc)] 16525{ 16526 emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]), 16527 operands[3])); 16528 DONE; 16529}) 16530 16531;; This is highpart user because the address is used as full 64 bit. 16532(define_insn "stlo_l" 16533 [(set (zero_extract:SI 16534 (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p") 16535 (const_int -4))) 16536 (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3))) 16537 (and:SI (match_dup 0) (const_int 3))) 16538 (match_operand:SI 1 "arith_reg_operand" "r"))] 16539 "TARGET_SHMEDIA32" 16540 "stlo.l %U0, %1" 16541 [(set_attr "type" "ustore_media")]) 16542 16543(define_insn "stlo_q" 16544 [(set (zero_extract:DI 16545 (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p") 16546 (const_int -8))) 16547 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7))) 16548 (and:SI (match_dup 0) (const_int 7))) 16549 (match_operand:DI 1 "arith_reg_operand" "r"))] 16550 "TARGET_SHMEDIA32" 16551 "stlo.q %U0, %1" 16552 [(set_attr "type" "ustore_media")]) 16553 16554(define_insn_and_split "*stlo_q_comb0" 16555 [(set (zero_extract:DI 16556 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r") 16557 (match_operand:SI 1 "ua_offset" "I06")) 16558 (const_int -8))) 16559 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7))) 16560 (and:SI (match_dup 0) (const_int 7))) 16561 (match_operand:DI 2 "arith_reg_operand" "r"))] 16562 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0" 16563 "#" 16564 "" 16565 [(pc)] 16566{ 16567 emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]), 16568 operands[2])); 16569 DONE; 16570}) 16571 16572(define_insn_and_split "*stlo_q_comb1" 16573 [(set (zero_extract:DI 16574 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r") 16575 (match_operand:SI 1 "ua_offset" "I06")) 16576 (const_int -8))) 16577 (minus:SI (const_int 8) 16578 (and:SI (plus:SI (match_dup 0) 16579 (match_operand:SI 2 "ua_offset" "I06")) 16580 (const_int 7))) 16581 (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7))) 16582 (match_operand:DI 3 "arith_reg_operand" "r"))] 16583 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])" 16584 "#" 16585 "" 16586 [(pc)] 16587{ 16588 emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]), 16589 operands[3])); 16590 DONE; 16591}) 16592 16593(define_insn "ldhi_l64" 16594 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 16595 (zero_extract:SI 16596 (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p") 16597 (const_int 3)) 16598 (const_int -3))) 16599 (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1)) 16600 (const_int 0)))] 16601 "TARGET_SHMEDIA64" 16602 "ldhi.l %U1, %0" 16603 [(set_attr "type" "load_media")]) 16604 16605(define_insn "ldhi_q64" 16606 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16607 (zero_extract:DI 16608 (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p") 16609 (const_int 7)) 16610 (const_int -7))) 16611 (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1)) 16612 (const_int 0)))] 16613 "TARGET_SHMEDIA64" 16614 "ldhi.q %U1, %0" 16615 [(set_attr "type" "load_media")]) 16616 16617(define_insn "ldlo_l64" 16618 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 16619 (zero_extract:SI 16620 (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p") 16621 (const_int -4))) 16622 (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3))) 16623 (and:DI (match_dup 1) (const_int 3))))] 16624 "TARGET_SHMEDIA64" 16625 "ldlo.l %U1, %0" 16626 [(set_attr "type" "load_media")]) 16627 16628(define_insn "ldlo_q64" 16629 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16630 (zero_extract:DI 16631 (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p") 16632 (const_int -8))) 16633 (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7))) 16634 (and:DI (match_dup 1) (const_int 7))))] 16635 "TARGET_SHMEDIA64" 16636 "ldlo.q %U1, %0" 16637 [(set_attr "type" "load_media")]) 16638 16639(define_insn "sthi_l64" 16640 [(set (zero_extract:SI 16641 (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p") 16642 (const_int 3)) 16643 (const_int -3))) 16644 (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1)) 16645 (const_int 0)) 16646 (match_operand:SI 1 "arith_reg_operand" "r"))] 16647 "TARGET_SHMEDIA64" 16648 "sthi.l %U0, %1" 16649 [(set_attr "type" "ustore_media")]) 16650 16651(define_insn "sthi_q64" 16652 [(set (zero_extract:DI 16653 (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p") 16654 (const_int 7)) 16655 (const_int -7))) 16656 (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1)) 16657 (const_int 0)) 16658 (match_operand:DI 1 "arith_reg_operand" "r"))] 16659 "TARGET_SHMEDIA64" 16660 "sthi.q %U0, %1" 16661 [(set_attr "type" "ustore_media")]) 16662 16663(define_insn "stlo_l64" 16664 [(set (zero_extract:SI 16665 (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p") 16666 (const_int -4))) 16667 (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3))) 16668 (and:DI (match_dup 0) (const_int 3))) 16669 (match_operand:SI 1 "arith_reg_operand" "r"))] 16670 "TARGET_SHMEDIA64" 16671 "stlo.l %U0, %1" 16672 [(set_attr "type" "ustore_media")]) 16673 16674(define_insn "stlo_q64" 16675 [(set (zero_extract:DI 16676 (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p") 16677 (const_int -8))) 16678 (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7))) 16679 (and:DI (match_dup 0) (const_int 7))) 16680 (match_operand:DI 1 "arith_reg_operand" "r"))] 16681 "TARGET_SHMEDIA64" 16682 "stlo.q %U0, %1" 16683 [(set_attr "type" "ustore_media")]) 16684 16685(define_insn "nsb" 16686 [(set (match_operand:QI 0 "arith_reg_dest" "=r") 16687 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")] 16688 UNSPEC_NSB))] 16689 "TARGET_SHMEDIA" 16690 "nsb %1, %0" 16691 [(set_attr "type" "arith_media")]) 16692 16693(define_insn "nsbsi" 16694 [(set (match_operand:SI 0 "arith_reg_dest" "=r") 16695 (zero_extend:SI 16696 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")] 16697 UNSPEC_NSB)))] 16698 "TARGET_SHMEDIA" 16699 "nsb %1, %0" 16700 [(set_attr "type" "arith_media")]) 16701 16702(define_insn "nsbdi" 16703 [(set (match_operand:DI 0 "arith_reg_dest" "=r") 16704 (zero_extend:DI 16705 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")] 16706 UNSPEC_NSB)))] 16707 "TARGET_SHMEDIA" 16708 "nsb %1, %0" 16709 [(set_attr "type" "arith_media")]) 16710 16711(define_expand "ffsdi2" 16712 [(set (match_operand:DI 0 "arith_reg_dest" "") 16713 (ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))] 16714 "TARGET_SHMEDIA" 16715{ 16716 rtx scratch = gen_reg_rtx (DImode); 16717 rtx last; 16718 16719 emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx)); 16720 emit_insn (gen_xordi3 (scratch, operands[1], scratch)); 16721 emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx)); 16722 emit_insn (gen_nsbdi (scratch, scratch)); 16723 emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64))); 16724 emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch)); 16725 last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch)); 16726 set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (DImode, operands[0])); 16727 16728 DONE; 16729}) 16730 16731(define_expand "ffssi2" 16732 [(set (match_operand:SI 0 "arith_reg_dest" "") 16733 (ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))] 16734 "TARGET_SHMEDIA" 16735{ 16736 rtx scratch = gen_reg_rtx (SImode); 16737 rtx discratch = gen_reg_rtx (DImode); 16738 rtx last; 16739 16740 emit_insn (gen_adddi3 (discratch, 16741 simplify_gen_subreg (DImode, operands[1], SImode, 0), 16742 constm1_rtx)); 16743 emit_insn (gen_andcdi3 (discratch, 16744 simplify_gen_subreg (DImode, operands[1], SImode, 0), 16745 discratch)); 16746 emit_insn (gen_nsbsi (scratch, discratch)); 16747 last = emit_insn (gen_subsi3 (operands[0], 16748 force_reg (SImode, GEN_INT (63)), scratch)); 16749 set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (SImode, operands[0])); 16750 16751 DONE; 16752}) 16753 16754(define_insn "byterev" 16755 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") 16756 (vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r") 16757 (parallel [(const_int 7) (const_int 6) (const_int 5) 16758 (const_int 4) (const_int 3) (const_int 2) 16759 (const_int 1) (const_int 0)])))] 16760 "TARGET_SHMEDIA" 16761 "byterev %1, %0" 16762 [(set_attr "type" "arith_media")]) 16763 16764;; In user mode, the "pref" instruction will raise a RADDERR exception 16765;; for accesses to [0x80000000,0xffffffff]. This makes it an unsuitable 16766;; implementation of __builtin_prefetch for VxWorks RTPs. 16767(define_expand "prefetch" 16768 [(prefetch (match_operand 0 "address_operand" "") 16769 (match_operand:SI 1 "const_int_operand" "") 16770 (match_operand:SI 2 "const_int_operand" ""))] 16771 "(TARGET_SH2A || TARGET_SH3 || TARGET_SH5) 16772 && (TARGET_SHMEDIA || ! TARGET_VXWORKS_RTP)") 16773 16774(define_insn "*prefetch" 16775 [(prefetch (match_operand:SI 0 "register_operand" "r") 16776 (match_operand:SI 1 "const_int_operand" "n") 16777 (match_operand:SI 2 "const_int_operand" "n"))] 16778 "(TARGET_SH2A || TARGET_SH3 || TARGET_SHCOMPACT) && ! TARGET_VXWORKS_RTP" 16779 "pref @%0" 16780 [(set_attr "type" "other")]) 16781 16782(define_insn "*prefetch_media" 16783 [(prefetch (match_operand:QI 0 "address_operand" "p") 16784 (match_operand:SI 1 "const_int_operand" "n") 16785 (match_operand:SI 2 "const_int_operand" "n"))] 16786 "TARGET_SHMEDIA" 16787{ 16788 operands[0] = gen_rtx_MEM (QImode, operands[0]); 16789 output_asm_insn ("ld%M0.b %m0,r63", operands); 16790 return ""; 16791} 16792 [(set_attr "type" "other")]) 16793 16794(define_insn "alloco_i" 16795 [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p")) 16796 (unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))] 16797 "TARGET_SHMEDIA32" 16798{ 16799 rtx xops[2]; 16800 16801 if (GET_CODE (operands[0]) == PLUS) 16802 { 16803 xops[0] = XEXP (operands[0], 0); 16804 xops[1] = XEXP (operands[0], 1); 16805 } 16806 else 16807 { 16808 xops[0] = operands[0]; 16809 xops[1] = const0_rtx; 16810 } 16811 output_asm_insn ("alloco %0, %1", xops); 16812 return ""; 16813} 16814 [(set_attr "type" "other")]) 16815 16816(define_split 16817 [(set (match_operand 0 "any_register_operand" "") 16818 (match_operand 1 "" ""))] 16819 "TARGET_SHMEDIA && reload_completed" 16820 [(set (match_dup 0) (match_dup 1))] 16821{ 16822 if (!shmedia_cleanup_truncate (operands[1])) 16823 FAIL; 16824}) 16825 16826;; ------------------------------------------------------------------------- 16827;; Stack Protector Patterns 16828;; ------------------------------------------------------------------------- 16829 16830(define_expand "stack_protect_set" 16831 [(set (match_operand 0 "memory_operand" "") 16832 (match_operand 1 "memory_operand" ""))] 16833 "" 16834{ 16835 if (TARGET_SHMEDIA) 16836 { 16837 if (TARGET_SHMEDIA64) 16838 emit_insn (gen_stack_protect_set_di_media (operands[0], operands[1])); 16839 else 16840 emit_insn (gen_stack_protect_set_si_media (operands[0], operands[1])); 16841 } 16842 else 16843 emit_insn (gen_stack_protect_set_si (operands[0], operands[1])); 16844 16845 DONE; 16846}) 16847 16848(define_insn "stack_protect_set_si" 16849 [(set (match_operand:SI 0 "memory_operand" "=m") 16850 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET)) 16851 (set (match_scratch:SI 2 "=&r") (const_int 0))] 16852 "!TARGET_SHMEDIA" 16853{ 16854 return "mov.l %1,%2" "\n" 16855 " mov.l %2,%0" "\n" 16856 " mov #0,%2"; 16857} 16858 [(set_attr "type" "other") 16859 (set_attr "length" "6")]) 16860 16861(define_insn "stack_protect_set_si_media" 16862 [(set (match_operand:SI 0 "memory_operand" "=m") 16863 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET)) 16864 (set (match_scratch:SI 2 "=&r") (const_int 0))] 16865 "TARGET_SHMEDIA" 16866{ 16867 return "ld%M1.l %m1,%2" "\n" 16868 " st%M0.l %m0,%2" "\n" 16869 " movi 0,%2"; 16870} 16871 [(set_attr "type" "other") 16872 (set_attr "length" "12")]) 16873 16874(define_insn "stack_protect_set_di_media" 16875 [(set (match_operand:DI 0 "memory_operand" "=m") 16876 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET)) 16877 (set (match_scratch:DI 2 "=&r") (const_int 0))] 16878 "TARGET_SHMEDIA64" 16879{ 16880 return "ld%M1.q %m1,%2" "\n" 16881 " st%M0.q %m0,%2" "\n" 16882 " movi 0,%2"; 16883} 16884 [(set_attr "type" "other") 16885 (set_attr "length" "12")]) 16886 16887(define_expand "stack_protect_test" 16888 [(match_operand 0 "memory_operand" "") 16889 (match_operand 1 "memory_operand" "") 16890 (match_operand 2 "" "")] 16891 "" 16892{ 16893 if (TARGET_SHMEDIA) 16894 { 16895 rtx tmp = gen_reg_rtx (GET_MODE (operands[0])); 16896 rtx test; 16897 16898 test = gen_rtx_NE (VOIDmode, tmp, const0_rtx); 16899 if (TARGET_SHMEDIA64) 16900 { 16901 emit_insn (gen_stack_protect_test_di_media (tmp, operands[0], 16902 operands[1])); 16903 emit_jump_insn (gen_cbranchdi4 (test, tmp, const0_rtx, operands[2])); 16904 } 16905 else 16906 { 16907 emit_insn (gen_stack_protect_test_si_media (tmp, operands[0], 16908 operands[1])); 16909 emit_jump_insn (gen_cbranchsi4 (test, tmp, const0_rtx, operands[2])); 16910 } 16911 } 16912 else 16913 { 16914 emit_insn (gen_stack_protect_test_si (operands[0], operands[1])); 16915 emit_jump_insn (gen_branch_true (operands[2])); 16916 } 16917 16918 DONE; 16919}) 16920 16921(define_insn "stack_protect_test_si" 16922 [(set (reg:SI T_REG) 16923 (unspec:SI [(match_operand:SI 0 "memory_operand" "m") 16924 (match_operand:SI 1 "memory_operand" "m")] 16925 UNSPEC_SP_TEST)) 16926 (set (match_scratch:SI 2 "=&r") (const_int 0)) 16927 (set (match_scratch:SI 3 "=&r") (const_int 0))] 16928 "!TARGET_SHMEDIA" 16929{ 16930 return "mov.l %0,%2" "\n" 16931 " mov.l %1,%3" "\n" 16932 " cmp/eq %2,%3" "\n" 16933 " mov #0,%2" "\n" 16934 " mov #0,%3"; 16935} 16936 [(set_attr "type" "other") 16937 (set_attr "length" "10")]) 16938 16939(define_insn "stack_protect_test_si_media" 16940 [(set (match_operand:SI 0 "register_operand" "=&r") 16941 (unspec:SI [(match_operand:SI 1 "memory_operand" "m") 16942 (match_operand:SI 2 "memory_operand" "m")] 16943 UNSPEC_SP_TEST)) 16944 (set (match_scratch:SI 3 "=&r") (const_int 0))] 16945 "TARGET_SHMEDIA" 16946{ 16947 return "ld%M1.l %m1,%0" "\n" 16948 " ld%M2.l %m2,%3" "\n" 16949 " cmpeq %0,%3,%0" "\n" 16950 " movi 0,%3"; 16951} 16952 [(set_attr "type" "other") 16953 (set_attr "length" "16")]) 16954 16955(define_insn "stack_protect_test_di_media" 16956 [(set (match_operand:DI 0 "register_operand" "=&r") 16957 (unspec:DI [(match_operand:DI 1 "memory_operand" "m") 16958 (match_operand:DI 2 "memory_operand" "m")] 16959 UNSPEC_SP_TEST)) 16960 (set (match_scratch:DI 3 "=&r") (const_int 0))] 16961 "TARGET_SHMEDIA64" 16962{ 16963 return "ld%M1.q %m1,%0" "\n" 16964 " ld%M2.q %m2,%3" "\n" 16965 " cmpeq %0,%3,%0" "\n" 16966 " movi 0,%3"; 16967} 16968 [(set_attr "type" "other") 16969 (set_attr "length" "16")]) 16970 16971;; ------------------------------------------------------------------------- 16972;; Atomic operations 16973;; ------------------------------------------------------------------------- 16974 16975(include "sync.md") 16976