📄 sh.md
字号:
{ rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]); high0 = gen_rtx (REG, SImode, true_regnum (operands[0]) + (TARGET_LITTLE_ENDIAN ? 1 : 0)); high2 = gen_rtx (REG, SImode, true_regnum (operands[2]) + (TARGET_LITTLE_ENDIAN ? 1 : 0)); emit_insn (gen_clrt ()); emit_insn (gen_subc (low0, low0, gen_lowpart (SImode, operands[2]))); emit_insn (gen_subc1 (high0, high0, high2)); DONE;}")(define_insn "subc" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0") (match_operand:SI 2 "arith_reg_operand" "r")) (reg:SI 18))) (set (reg:SI 18) (gtu:SI (minus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))] "" "subc %2,%0" [(set_attr "type" "arith")])(define_insn "subc1" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0") (match_operand:SI 2 "arith_reg_operand" "r")) (reg:SI 18))) (clobber (reg:SI 18))] "" "subc %2,%0" [(set_attr "type" "arith")])(define_insn "*subsi3_internal" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (minus:SI (match_operand:SI 1 "arith_reg_operand" "0") (match_operand:SI 2 "arith_reg_operand" "r")))] "" "sub %2,%0" [(set_attr "type" "arith")]);; Convert `constant - reg' to `neg rX; add rX, #const' since this;; will sometimes save one instruction. Otherwise we might get;; `mov #const, rY; sub rY,rX; mov rX, rY' if the source and dest regs;; are the same.(define_expand "subsi3" [(set (match_operand:SI 0 "arith_reg_operand" "") (minus:SI (match_operand:SI 1 "arith_operand" "") (match_operand:SI 2 "arith_reg_operand" "")))] "" "{ if (GET_CODE (operands[1]) == CONST_INT) { emit_insn (gen_negsi2 (operands[0], operands[2])); emit_insn (gen_addsi3 (operands[0], operands[0], operands[1])); DONE; }}");; -------------------------------------------------------------------------;; Division instructions;; -------------------------------------------------------------------------;; We take advantage of the library routines which don't clobber as many;; registers as a normal function call would.;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it;; also has an effect on the register that holds the address of the sfunc.;; To make this work, we have an extra dummy insns that shows the use;; of this register for reorg.(define_insn "use_sfunc_addr" [(set (reg:SI 17) (unspec [(match_operand:SI 0 "register_operand" "r")] 5))] "" "" [(set_attr "length" "0")]);; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than;; hard register 0. If we used hard register 0, then the next instruction;; would be a move from hard register 0 to a pseudo-reg. If the pseudo-reg;; gets allocated to a stack slot that needs its address reloaded, then;; there is nothing to prevent reload from using r0 to reload the address.;; This reload would clobber the value in r0 we are trying to store.;; If we let reload allocate r0, then this problem can never happen.(define_insn "" [(set (match_operand:SI 0 "register_operand" "=z") (udiv:SI (reg:SI 4) (reg:SI 5))) (clobber (reg:SI 18)) (clobber (reg:SI 17)) (clobber (reg:SI 4)) (use (match_operand:SI 1 "arith_reg_operand" "r"))] "! TARGET_SH4" "jsr @%1%#" [(set_attr "type" "sfunc") (set_attr "needs_delay_slot" "yes")])(define_insn "udivsi3_i4" [(set (match_operand:SI 0 "register_operand" "=y") (udiv:SI (reg:SI 4) (reg:SI 5))) (clobber (reg:SI 17)) (clobber (reg:DF 24)) (clobber (reg:DF 26)) (clobber (reg:DF 28)) (clobber (reg:SI 0)) (clobber (reg:SI 1)) (clobber (reg:SI 4)) (clobber (reg:SI 5)) (use (reg:PSI 48)) (use (match_operand:SI 1 "arith_reg_operand" "r"))] "TARGET_SH4 && ! TARGET_FPU_SINGLE" "jsr @%1%#" [(set_attr "type" "sfunc") (set_attr "needs_delay_slot" "yes")])(define_insn "udivsi3_i4_single" [(set (match_operand:SI 0 "register_operand" "=y") (udiv:SI (reg:SI 4) (reg:SI 5))) (clobber (reg:SI 17)) (clobber (reg:DF 24)) (clobber (reg:DF 26)) (clobber (reg:DF 28)) (clobber (reg:SI 0)) (clobber (reg:SI 1)) (clobber (reg:SI 4)) (clobber (reg:SI 5)) (use (match_operand:SI 1 "arith_reg_operand" "r"))] "TARGET_HARD_SH4 && TARGET_FPU_SINGLE" "jsr @%1%#" [(set_attr "type" "sfunc") (set_attr "needs_delay_slot" "yes")])(define_expand "udivsi3" [(set (reg:SI 4) (match_operand:SI 1 "general_operand" "")) (set (reg:SI 5) (match_operand:SI 2 "general_operand" "")) (set (match_dup 3) (symbol_ref:SI "__udivsi3")) (parallel [(set (match_operand:SI 0 "register_operand" "") (udiv:SI (reg:SI 4) (reg:SI 5))) (clobber (reg:SI 18)) (clobber (reg:SI 17)) (clobber (reg:SI 4)) (use (match_dup 3))])] "" "{ operands[3] = gen_reg_rtx(SImode); if (TARGET_HARD_SH4) { emit_move_insn (gen_rtx (REG, SImode, 4), operands[1]); emit_move_insn (gen_rtx (REG, SImode, 5), operands[2]); emit_move_insn (operands[3], gen_rtx_SYMBOL_REF (SImode, \"__udivsi3_i4\")); if (TARGET_FPU_SINGLE) emit_insn (gen_udivsi3_i4_single (operands[0], operands[3])); else emit_insn (gen_udivsi3_i4 (operands[0], operands[3])); DONE; }}")(define_insn "" [(set (match_operand:SI 0 "register_operand" "=z") (div:SI (reg:SI 4) (reg:SI 5))) (clobber (reg:SI 18)) (clobber (reg:SI 17)) (clobber (reg:SI 1)) (clobber (reg:SI 2)) (clobber (reg:SI 3)) (use (match_operand:SI 1 "arith_reg_operand" "r"))] "! TARGET_SH4" "jsr @%1%#" [(set_attr "type" "sfunc") (set_attr "needs_delay_slot" "yes")])(define_insn "divsi3_i4" [(set (match_operand:SI 0 "register_operand" "=y") (div:SI (reg:SI 4) (reg:SI 5))) (clobber (reg:SI 17)) (clobber (reg:DF 24)) (clobber (reg:DF 26)) (use (reg:PSI 48)) (use (match_operand:SI 1 "arith_reg_operand" "r"))] "TARGET_SH4 && ! TARGET_FPU_SINGLE" "jsr @%1%#" [(set_attr "type" "sfunc") (set_attr "needs_delay_slot" "yes")])(define_insn "divsi3_i4_single" [(set (match_operand:SI 0 "register_operand" "=y") (div:SI (reg:SI 4) (reg:SI 5))) (clobber (reg:SI 17)) (clobber (reg:DF 24)) (clobber (reg:DF 26)) (clobber (reg:SI 2)) (use (match_operand:SI 1 "arith_reg_operand" "r"))] "TARGET_HARD_SH4 && TARGET_FPU_SINGLE" "jsr @%1%#" [(set_attr "type" "sfunc") (set_attr "needs_delay_slot" "yes")])(define_expand "divsi3" [(set (reg:SI 4) (match_operand:SI 1 "general_operand" "")) (set (reg:SI 5) (match_operand:SI 2 "general_operand" "")) (set (match_dup 3) (symbol_ref:SI "__sdivsi3")) (parallel [(set (match_operand:SI 0 "register_operand" "") (div:SI (reg:SI 4) (reg:SI 5))) (clobber (reg:SI 18)) (clobber (reg:SI 17)) (clobber (reg:SI 1)) (clobber (reg:SI 2)) (clobber (reg:SI 3)) (use (match_dup 3))])] "" "{ operands[3] = gen_reg_rtx(SImode); if (TARGET_HARD_SH4) { emit_move_insn (gen_rtx (REG, SImode, 4), operands[1]); emit_move_insn (gen_rtx (REG, SImode, 5), operands[2]); emit_move_insn (operands[3], gen_rtx_SYMBOL_REF (SImode, \"__sdivsi3_i4\")); if (TARGET_FPU_SINGLE) emit_insn (gen_divsi3_i4_single (operands[0], operands[3])); else emit_insn (gen_divsi3_i4 (operands[0], operands[3])); DONE; }}");; -------------------------------------------------------------------------;; Multiplication instructions;; -------------------------------------------------------------------------(define_insn "" [(set (reg:SI 21) (mult:SI (zero_extend:SI (match_operand:HI 0 "arith_reg_operand" "r")) (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r"))))] "" "mulu %1,%0" [(set_attr "type" "smpy")])(define_insn "" [(set (reg:SI 21) (mult:SI (sign_extend:SI (match_operand:HI 0 "arith_reg_operand" "r")) (sign_extend:SI (match_operand:HI 1 "arith_reg_operand" "r"))))] "" "muls %1,%0" [(set_attr "type" "smpy")])(define_expand "mulhisi3" [(set (reg:SI 21) (mult:SI (sign_extend:SI (match_operand:HI 1 "arith_reg_operand" "")) (sign_extend:SI (match_operand:HI 2 "arith_reg_operand" "")))) (set (match_operand:SI 0 "arith_reg_operand" "") (reg:SI 21))] "" "")(define_expand "umulhisi3" [(set (reg:SI 21) (mult:SI (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "")) (zero_extend:SI (match_operand:HI 2 "arith_reg_operand" "")))) (set (match_operand:SI 0 "arith_reg_operand" "") (reg:SI 21))] "" "");; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate;; a call to a routine which clobbers known registers.(define_insn "" [(set (match_operand:SI 1 "register_operand" "=z") (mult:SI (reg:SI 4) (reg:SI 5))) (clobber (reg:SI 21)) (clobber (reg:SI 18)) (clobber (reg:SI 17)) (clobber (reg:SI 3)) (clobber (reg:SI 2)) (clobber (reg:SI 1)) (use (match_operand:SI 0 "arith_reg_operand" "r"))] "" "jsr @%0%#" [(set_attr "type" "sfunc") (set_attr "needs_delay_slot" "yes")])(define_expand "mulsi3_call" [(set (reg:SI 4) (match_operand:SI 1 "general_operand" "")) (set (reg:SI 5) (match_operand:SI 2 "general_operand" "")) (parallel[(set (match_operand:SI 0 "register_operand" "") (mult:SI (reg:SI 4) (reg:SI 5))) (clobber (reg:SI 21)) (clobber (reg:SI 18)) (clobber (reg:SI 17)) (clobber (reg:SI 3)) (clobber (reg:SI 2)) (clobber (reg:SI 1)) (use (match_operand:SI 3 "register_operand" ""))])] "" "")(define_insn "mul_l" [(set (reg:SI 21) (mult:SI (match_operand:SI 0 "arith_reg_operand" "r") (match_operand:SI 1 "arith_reg_operand" "r")))] "TARGET_SH2" "mul.l %1,%0" [(set_attr "type" "dmpy")])(define_expand "mulsi3" [(set (reg:SI 21) (mult:SI (match_operand:SI 1 "arith_reg_operand" "") (match_operand:SI 2 "arith_reg_operand" ""))) (set (match_operand:SI 0 "arith_reg_operand" "") (reg:SI 21))] "" "{ rtx first, last; if (!TARGET_SH2) { /* The address must be set outside the libcall, since it goes into a pseudo. */ rtx addr = force_reg (SImode, gen_rtx_SYMBOL_REF (SImode, \"__mulsi3\")); rtx insns = gen_mulsi3_call (operands[0], operands[1], operands[2], addr); first = XVECEXP (insns, 0, 0); last = XVECEXP (insns, 0, XVECLEN (insns, 0) - 1); emit_insn (insns); } else { rtx macl = gen_rtx_REG (SImode, MACL_REG); rtx giv_insn; first = emit_insn (gen_mul_l (operands[1], operands[2])); /* consec_sets_giv can only recognize the first insn that sets a giv as the giv insn. So we must tag this also with a REG_EQUAL note. */ giv_insn = emit_insn (gen_movsi_i ((operands[0]), macl)); REG_NOTES (giv_insn) = gen_rtx_EXPR_LIST (REG_EQUAL, gen_rtx_MULT (SImode, operands[1], operands[2]), REG_NOTES (giv_insn)); /* The sequence must end in a no-op move, lest cse puts macl in its tables and does invalid substitutions. */ last = emit_insn (gen_movsi_i ((operands[0]), operands[0])); } /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop invariant code motion can move it. */ REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first)); REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last)); DONE;}")(define_insn "mulsidi3_i" [(set (reg:DI 20) (mult:DI (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))))] "TARGET_SH2" "dmuls.l %1,%0" [(set_attr "type" "dmpy")])(define_expand "mulsidi3" [(set (reg:DI 20) (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))) (set (match_operand:DI 0 "arith_reg_operand" "") (reg:DI 20))] "TARGET_SH2" "{ /* We must swap the two words when copying them from MACH/MACL to the output register. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -