📄 sh.md
字号:
(const_int 2) (eq_attr "med_cbranch_p" "yes") (const_int 6) (eq_attr "braf_cbranch_p" "yes") (const_int 12);; ??? using pc is not computed transitively. (ne (match_dup 0) (match_dup 0)) (const_int 14) (ne (symbol_ref ("flag_pic")) (const_int 0)) (const_int 24) ] (const_int 16)) (eq_attr "type" "jump") (cond [(eq_attr "med_branch_p" "yes") (const_int 2) (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))") (symbol_ref "INSN")) (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))") (symbol_ref "code_for_indirect_jump_scratch"))) (cond [(eq_attr "braf_branch_p" "yes") (const_int 6) (eq (symbol_ref "flag_pic") (const_int 0)) (const_int 10) (ne (symbol_ref "TARGET_SH2") (const_int 0)) (const_int 10)] (const_int 18)) (eq_attr "braf_branch_p" "yes") (const_int 10);; ??? using pc is not computed transitively. (ne (match_dup 0) (match_dup 0)) (const_int 12) (ne (symbol_ref ("flag_pic")) (const_int 0)) (const_int 22) ] (const_int 14)) (eq_attr "type" "pt_media") (if_then_else (ne (symbol_ref "TARGET_SHMEDIA64") (const_int 0)) (const_int 20) (const_int 12)) ] (if_then_else (ne (symbol_ref "TARGET_SHMEDIA") (const_int 0)) (const_int 4) (const_int 2))));; DFA descriptions for the pipelines(include "sh1.md")(include "shmedia.md")(include "sh4.md");; Definitions for filling delay slots(define_attr "needs_delay_slot" "yes,no" (const_string "no"));; ??? This should be (nil) instead of (const_int 0)(define_attr "hit_stack" "yes,no" (cond [(eq (symbol_ref "find_regno_note (insn, REG_INC, SP_REG)") (const_int 0)) (const_string "no")] (const_string "yes")))(define_attr "interrupt_function" "no,yes" (const (symbol_ref "current_function_interrupt")))(define_attr "in_delay_slot" "yes,no" (cond [(eq_attr "type" "cbranch") (const_string "no") (eq_attr "type" "pcload,pcload_si") (const_string "no") (eq_attr "needs_delay_slot" "yes") (const_string "no") (eq_attr "length" "2") (const_string "yes") ] (const_string "no")))(define_attr "cond_delay_slot" "yes,no" (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes") ] (const_string "no")))(define_attr "is_sfunc" "" (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))(define_attr "is_mac_media" "" (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0)))(define_attr "branch_zero" "yes,no" (cond [(eq_attr "type" "!cbranch") (const_string "no") (ne (symbol_ref "(next_active_insn (insn)\ == (prev_active_insn\ (XEXP (SET_SRC (PATTERN (insn)), 1))))\ && get_attr_length (next_active_insn (insn)) == 2") (const_int 0)) (const_string "yes")] (const_string "no")));; SH4 Double-precision computation with double-precision result -;; the two halves are ready at different times.(define_attr "dfp_comp" "yes,no" (cond [(eq_attr "type" "dfp_arith,dfp_conv,dfdiv") (const_string "yes")] (const_string "no")));; Insns for which the latency of a preceding fp insn is decreased by one.(define_attr "late_fp_use" "yes,no" (const_string "no"));; And feeding insns for which this relevant.(define_attr "any_fp_comp" "yes,no" (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_conv,dfdiv") (const_string "yes")] (const_string "no")))(define_attr "any_int_load" "yes,no" (cond [(eq_attr "type" "load,load_si,pcload,pcload_si") (const_string "yes")] (const_string "no")))(define_delay (eq_attr "needs_delay_slot" "yes") [(eq_attr "in_delay_slot" "yes") (nil) (nil)]);; On the SH and SH2, the rte instruction reads the return pc from the stack,;; and thus we can't put a pop instruction in its delay slot.;; ??? On the SH3, the rte instruction does not use the stack, so a pop;; instruction can go in the delay slot.;; Since a normal return (rts) implicitly uses the PR register,;; we can't allow PR register loads in an rts delay slot.(define_delay (eq_attr "type" "return") [(and (eq_attr "in_delay_slot" "yes") (ior (and (eq_attr "interrupt_function" "no") (eq_attr "type" "!pload,prset")) (and (eq_attr "interrupt_function" "yes") (ior (ne (symbol_ref "TARGET_SH3") (const_int 0)) (eq_attr "hit_stack" "no"))))) (nil) (nil)]);; Since a call implicitly uses the PR register, we can't allow;; a PR register store in a jsr delay slot.(define_delay (ior (eq_attr "type" "call") (eq_attr "type" "sfunc")) [(and (eq_attr "in_delay_slot" "yes") (eq_attr "type" "!pstore,prget")) (nil) (nil)]);; Say that we have annulled true branches, since this gives smaller and;; faster code when branches are predicted as not taken.;; ??? The non-annulled condition should really be "in_delay_slot",;; but insns that can be filled in non-annulled get priority over insns;; that can only be filled in anulled.(define_delay (and (eq_attr "type" "cbranch") (ne (symbol_ref "TARGET_SH2") (const_int 0))) ;; SH2e has a hardware bug that pretty much prohibits the use of ;; annuled delay slots. [(eq_attr "cond_delay_slot" "yes") (and (eq_attr "cond_delay_slot" "yes") (not (eq_attr "cpu" "sh2e"))) (nil)]);; -------------------------------------------------------------------------;; SImode signed integer comparisons;; -------------------------------------------------------------------------(define_insn "" [(set (reg:SI T_REG) (eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "z,r") (match_operand:SI 1 "arith_operand" "K08,r")) (const_int 0)))] "TARGET_SH1" "tst %1,%0" [(set_attr "type" "mt_group")]);; ??? Perhaps should only accept reg/constant if the register is reg 0.;; That would still allow reload to create cmpi instructions, but would;; perhaps allow forcing the constant into a register when that is better.;; Probably should use r0 for mem/imm compares, but force constant into a;; register for pseudo/imm compares.(define_insn "cmpeqsi_t" [(set (reg:SI T_REG) (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r") (match_operand:SI 1 "arith_operand" "N,rI08,r")))] "TARGET_SH1" "@ tst %0,%0 cmp/eq %1,%0 cmp/eq %1,%0" [(set_attr "type" "mt_group")])(define_insn "cmpgtsi_t" [(set (reg:SI T_REG) (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r") (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))] "TARGET_SH1" "@ cmp/gt %1,%0 cmp/pl %0" [(set_attr "type" "mt_group")])(define_insn "cmpgesi_t" [(set (reg:SI T_REG) (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r") (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))] "TARGET_SH1" "@ cmp/ge %1,%0 cmp/pz %0" [(set_attr "type" "mt_group")]);; -------------------------------------------------------------------------;; SImode unsigned integer comparisons;; -------------------------------------------------------------------------(define_insn "cmpgeusi_t" [(set (reg:SI T_REG) (geu:SI (match_operand:SI 0 "arith_reg_operand" "r") (match_operand:SI 1 "arith_reg_operand" "r")))] "TARGET_SH1" "cmp/hs %1,%0" [(set_attr "type" "mt_group")])(define_insn "cmpgtusi_t" [(set (reg:SI T_REG) (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r") (match_operand:SI 1 "arith_reg_operand" "r")))] "TARGET_SH1" "cmp/hi %1,%0" [(set_attr "type" "mt_group")]);; We save the compare operands in the cmpxx patterns and use them when;; we generate the branch.(define_expand "cmpsi" [(set (reg:SI T_REG) (compare (match_operand:SI 0 "cmpsi_operand" "") (match_operand:SI 1 "arith_operand" "")))] "TARGET_SH1" "{ if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == T_REG && GET_CODE (operands[1]) != CONST_INT) operands[0] = copy_to_mode_reg (SImode, operands[0]); sh_compare_op0 = operands[0]; sh_compare_op1 = operands[1]; DONE;}");; -------------------------------------------------------------------------;; DImode signed integer comparisons;; -------------------------------------------------------------------------;; ??? Could get better scheduling by splitting the initial test from the;; rest of the insn after reload. However, the gain would hardly justify;; the sh.md size increase necessary to do that.(define_insn "" [(set (reg:SI T_REG) (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r") (match_operand:DI 1 "arith_operand" "r")) (const_int 0)))] "TARGET_SH1" "* return output_branchy_insn (EQ, \"tst\\t%S1,%S0\;bf\\t%l9\;tst\\t%R1,%R0\", insn, operands);" [(set_attr "length" "6") (set_attr "type" "arith3b")])(define_insn "cmpeqdi_t" [(set (reg:SI T_REG) (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r") (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))] "TARGET_SH1" "@ tst %S0,%S0\;bf %,Ldi%=\;tst %R0,%R0\\n%,Ldi%=: cmp/eq %S1,%S0\;bf %,Ldi%=\;cmp/eq %R1,%R0\\n%,Ldi%=:" [(set_attr "length" "6") (set_attr "type" "arith3b")])(define_split [(set (reg:SI T_REG) (eq:SI (match_operand:DI 0 "arith_reg_operand" "") (match_operand:DI 1 "arith_reg_or_0_operand" "")))];; If we applied this split when not optimizing, it would only be;; applied during the machine-dependent reorg, when no new basic blocks;; may be created. "TARGET_SH1 && reload_completed && optimize" [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3))) (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0)) (label_ref (match_dup 6)) (pc))) (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5))) (match_dup 6)] "{ operands[2] = gen_rtx_REG (SImode, true_regnum (operands[0]) + (TARGET_LITTLE_ENDIAN ? 1 : 0)); operands[3] = (operands[1] == const0_rtx ? const0_rtx : gen_rtx_REG (SImode, true_regnum (operands[1]) + (TARGET_LITTLE_ENDIAN ? 1 : 0))); operands[4] = gen_lowpart (SImode, operands[0]); operands[5] = gen_lowpart (SImode, operands[1]); operands[6] = gen_label_rtx ();}")(define_insn "cmpgtdi_t" [(set (reg:SI T_REG) (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r") (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))] "TARGET_SH2" "@ cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/gt\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=: tst\\t%S0,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/pl\\t%S0\;cmp/hi\\t%S0,%R0\\n%,Ldi%=:" [(set_attr "length" "8") (set_attr "type" "arith3")])(define_insn "cmpgedi_t" [(set (reg:SI T_REG) (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r") (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))] "TARGET_SH2" "@ cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/ge\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=: cmp/pz\\t%S0" [(set_attr "length" "8,2") (set_attr "type" "arith3,mt_group")]);; -------------------------------------------------------------------------;; DImode unsigned integer comparisons;; -------------------------------------------------------------------------(define_insn "cmpgeudi_t" [(set (reg:SI T_REG) (geu:SI (match_operand:DI 0 "arith_reg_operand" "r") (match_operand:DI 1 "arith_reg_operand" "r")))] "TARGET_SH2" "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hs\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:" [(set_attr "length" "8") (set_attr "type" "arith3")])(define_insn "cmpgtudi_t" [(set (reg:SI T_REG) (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r") (match_operand:DI 1 "arith_reg_operand" "r")))] "TARGET_SH2" "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hi\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:" [(set_attr "length" "8") (set_attr "type" "arith3")])(define_insn "cmpeqdi_media" [(set (match_operand:DI 0 "register_operand" "=r") (eq:DI (match_operand:DI 1 "register_operand" "%r") (match_operand:DI 2 "arith_reg_or_0_operand" "Nr")))] "TARGET_SHMEDIA" "cmpeq %1, %N2, %0" [(set_attr "type" "cmp_media")])(define_insn "cmpgtdi_media" [(set (match_operand:DI 0 "register_operand" "=r") (gt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr") (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))] "TARGET_SHMEDIA" "cmpgt %N1, %N2, %0" [(set_attr "type" "cmp_media")])(define_insn "cmpgtudi_media" [(set (match_operand:DI 0 "register_operand" "=r") (gtu:DI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr") (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))] "TARGET_SHMEDIA" "cmpgtu %N1, %N2, %0" [(set_attr "type" "cmp_media")]);; We save the compare operands in the cmpxx patterns and use them when;; we generate the branch.(define_expand "cmpdi" [(set (reg:SI T_REG) (compare (match_operand:DI 0 "arith_operand" "") (match_operand:DI 1 "arith_operand" "")))] "TARGET_SH2 || TARGET_SHMEDIA" "{ sh_compare_op0 = operands[0]; sh_compare_op1 = operands[1]; DONE;}");; -------------------------------------------------------------------------;; Conditional move instructions;; -------------------------------------------------------------------------;; The insn names may seem reversed, but note that cmveq performs the move;; if op1 == 0, and cmvne does it if op1 != 0.(define_insn "movdicc_false" [(set (match_operand:DI 0 "arith_reg_dest" "=r") (if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r") (const_int 0))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -