📄 sparc.md
字号:
if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) { cc_status.flags |= CC_KNOW_HI_G1; cc_status.mdep = XEXP (operands[1], 0); return \"sethi %%hi(%m1),%%g1\;ldub [%%g1+%%lo(%m1)],%0\"; } return \"ldub %1,%0\";}");;- arithmetic shift instructions(define_insn "ashlsi3" [(set (match_operand:SI 0 "register_operand" "=r") (ashift:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "arith32_operand" "rn")))] "" "*{ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32) operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 31); return \"sll %1,%2,%0\";}")(define_insn "ashrsi3" [(set (match_operand:SI 0 "register_operand" "=r") (ashiftrt:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "arith32_operand" "rn")))] "" "*{ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32) operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 31); return \"sra %1,%2,%0\";}")(define_insn "lshrsi3" [(set (match_operand:SI 0 "register_operand" "=r") (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "arith32_operand" "rn")))] "" "*{ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32) operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 31); return \"srl %1,%2,%0\";}");; Unconditional and other jump instructions;; Note that for the Sparc, by setting the annul bit on an unconditional;; branch, the following insn is never executed. This saves us a nop,;; but requires a debugger which can handle annuled branches.(define_insn "jump" [(set (pc) (label_ref (match_operand 0 "" "")))] "" "*{ extern int optimize; extern int flag_no_peephole; if (optimize && !flag_no_peephole) return \"b,a %l0\"; return \"b %l0\;nop\";}");; Peephole optimizers recognize a few simple cases when delay insns are safe.;; Complex ones are up front. Simple ones after.;; This pattern is just like the following one, but matches when there;; is a jump insn after the "delay" insn. Without this pattern, we;; de-optimize that case.(define_peephole [(set (pc) (match_operand 0 "" "")) (set (match_operand:SI 1 "" "") (match_operand:SI 2 "" "")) (set (pc) (label_ref (match_operand 3 "" "")))] "TARGET_EAGER && operands_satisfy_eager_branch_peephole (operands, 2)" "*{ rtx xoperands[2]; rtx pat = gen_rtx (SET, VOIDmode, operands[1], operands[2]); rtx delay_insn = gen_rtx (INSN, VOIDmode, 0, 0, 0, pat, -1, 0, 0); rtx label, head; int parity; if (GET_CODE (XEXP (operands[0], 1)) == PC) { parity = 1; label = XEXP (XEXP (operands[0], 2), 0); } else { parity = 0; label = XEXP (XEXP (operands[0], 1), 0); } xoperands[0] = XEXP (operands[0], 0); xoperands[1] = label; head = next_real_insn_no_labels (label); /* If at the target of this label we set the condition codes, and the condition codes are already set for that value, advance, if we can, to the following insn. */ if (GET_CODE (PATTERN (head)) == SET && GET_CODE (SET_DEST (PATTERN (head))) == CC0 && cc_status.value2 == SET_SRC (PATTERN (head))) { rtx nhead = next_real_insn_no_labels (head); if (nhead && GET_CODE (nhead) == INSN && GET_CODE (PATTERN (nhead)) == SET && strict_single_insn_op_p (SET_SRC (PATTERN (nhead)), GET_MODE (SET_DEST (PATTERN (nhead)))) && strict_single_insn_op_p (SET_DEST (PATTERN (nhead)), VOIDmode) /* Moves between FP regs and CPU regs are two insns. */ && !(GET_CODE (SET_SRC (PATTERN (nhead))) == REG && GET_CODE (SET_DEST (PATTERN (nhead))) == REG && (FP_REG_P (SET_SRC (PATTERN (nhead))) != FP_REG_P (SET_DEST (PATTERN (nhead)))))) { head = nhead; } } /* Output the branch instruction first. */ if (cc_prev_status.flags & CC_IN_FCCR) { if (parity) output_asm_insn (\"fb%F0,a %l1 ! eager\", xoperands); else output_asm_insn (\"fb%C0,a %l1 ! eager\", xoperands); } else if (cc_prev_status.flags & CC_NO_OVERFLOW) { if (parity) output_asm_insn (\"b%U0,a %l1 ! eager\", xoperands); else output_asm_insn (\"b%I0,a %l1 ! eager\", xoperands); } else { if (parity) output_asm_insn (\"b%N0,a %l1 ! eager\", xoperands); else output_asm_insn (\"b%C0,a %l1 ! eager\", xoperands); } /* Now steal the first insn of the target. */ output_eager_then_insn (head, operands); XVECEXP (PATTERN (insn), 0, 0) = XVECEXP (PATTERN (insn), 0, 1); XVECEXP (PATTERN (insn), 0, 1) = XVECEXP (PATTERN (insn), 0, 2); return output_delayed_branch (\"b %l3 ! eager2\", operands, insn);}");; Here is a peephole which recognizes where delay insns can be made safe:;; (1) following a conditional branch, if the target of the conditional branch;; has only one user (this insn), move the first insn into our delay slot;; and emit an annulled branch.;; (2) following a conditional branch, if we can execute the fall-through;; insn without risking any evil effects, then do that instead of a nop.(define_peephole [(set (pc) (match_operand 0 "" "")) (set (match_operand:SI 1 "" "") (match_operand:SI 2 "" ""))] "TARGET_EAGER && operands_satisfy_eager_branch_peephole (operands, 1)" "*{ rtx xoperands[2]; rtx pat = gen_rtx (SET, VOIDmode, operands[1], operands[2]); rtx delay_insn = gen_rtx (INSN, VOIDmode, 0, 0, 0, pat, -1, 0, 0); rtx label, head, prev = (rtx)1; int parity; if (GET_CODE (XEXP (operands[0], 1)) == PC) { parity = 1; label = XEXP (XEXP (operands[0], 2), 0); } else { parity = 0; label = XEXP (XEXP (operands[0], 1), 0); } xoperands[0] = XEXP (operands[0], 0); xoperands[1] = label; if (LABEL_NUSES (label) == 1) { prev = PREV_INSN (label); while (prev && (GET_CODE (prev) == NOTE || (GET_CODE (prev) == INSN && (GET_CODE (PATTERN (prev)) == CLOBBER || GET_CODE (PATTERN (prev)) == USE)))) prev = PREV_INSN (prev); if (prev == 0 || GET_CODE (prev) == BARRIER) { prev = 0; head = next_real_insn_no_labels (label); } } if (prev == 0 && head != 0 && ! INSN_DELETED_P (head) && GET_CODE (head) == INSN && GET_CODE (PATTERN (head)) == SET && strict_single_insn_op_p (SET_SRC (PATTERN (head)), GET_MODE (SET_DEST (PATTERN (head)))) && strict_single_insn_op_p (SET_DEST (PATTERN (head)), VOIDmode) /* Moves between FP regs and CPU regs are two insns. */ && !(GET_CODE (SET_SRC (PATTERN (head))) == REG && GET_CODE (SET_DEST (PATTERN (head))) == REG && (FP_REG_P (SET_SRC (PATTERN (head))) != FP_REG_P (SET_DEST (PATTERN (head)))))) { /* If at the target of this label we set the condition codes, and the condition codes are already set for that value, advance, if we can, to the following insn. */ if (GET_CODE (PATTERN (head)) == SET && GET_CODE (SET_DEST (PATTERN (head))) == CC0 && cc_status.value2 == SET_SRC (PATTERN (head))) { rtx nhead = next_real_insn_no_labels (head); if (nhead && GET_CODE (nhead) == INSN && GET_CODE (PATTERN (nhead)) == SET && strict_single_insn_op_p (SET_SRC (PATTERN (nhead)), GET_MODE (SET_DEST (nhead))) && strict_single_insn_op_p (SET_DEST (PATTERN (nhead)), VOIDmode) /* Moves between FP regs and CPU regs are two insns. */ && !(GET_CODE (SET_SRC (PATTERN (nhead))) == REG && GET_CODE (SET_DEST (PATTERN (nhead))) == REG && (FP_REG_P (SET_SRC (PATTERN (nhead))) != FP_REG_P (SET_DEST (PATTERN (nhead)))))) head = nhead; } /* Output the branch instruction first. */ if (cc_prev_status.flags & CC_IN_FCCR) { if (parity) output_asm_insn (\"fb%F0,a %l1 ! eager\", xoperands); else output_asm_insn (\"fb%C0,a %l1 ! eager\", xoperands); } else if (cc_prev_status.flags & CC_NO_OVERFLOW) { if (parity) output_asm_insn (\"b%U0,a %l1 ! eager\", xoperands); else output_asm_insn (\"b%I0,a %l1 ! eager\", xoperands); } else { if (parity) output_asm_insn (\"b%N0,a %l1 ! eager\", xoperands); else output_asm_insn (\"b%C0,a %l1 ! eager\", xoperands); } /* Now steal the first insn of the target. */ output_eager_then_insn (head, operands); } else { /* Output the branch instruction first. */ if (cc_prev_status.flags & CC_IN_FCCR) { if (parity) output_asm_insn (\"fb%F0 %l1 ! eager\", xoperands); else output_asm_insn (\"fb%C0 %l1 ! eager\", xoperands); } else if (cc_prev_status.flags & CC_NO_OVERFLOW) { if (parity) output_asm_insn (\"b%U0,a %l1 ! eager\", xoperands); else output_asm_insn (\"b%I0,a %l1 ! eager\", xoperands); } else { if (parity) output_asm_insn (\"b%N0 %l1 ! eager\", xoperands); else output_asm_insn (\"b%C0 %l1 ! eager\", xoperands); } } return output_delay_insn (delay_insn);}");; Here are two simple peepholes which fill the delay slot of;; an unconditional branch.(define_peephole [(set (match_operand:SI 0 "register_operand" "=r") (match_operand:SI 1 "single_insn_src_p" "p")) (set (pc) (label_ref (match_operand 2 "" "")))] "single_insn_extra_test (operands[0], operands[1])" "* return output_delayed_branch (\"b %l2\", operands, insn);")(define_peephole [(set (match_operand:SI 0 "memory_operand" "=m") (match_operand:SI 1 "reg_or_0_operand" "rJ")) (set (pc) (label_ref (match_operand 2 "" "")))] "" "* return output_delayed_branch (\"b %l2\", operands, insn);")(define_insn "tablejump" [(set (pc) (match_operand:SI 0 "register_operand" "r")) (use (label_ref (match_operand 1 "" "")))] "" "jmp %0\;nop")(define_peephole [(set (match_operand:SI 0 "register_operand" "=r") (match_operand:SI 1 "single_insn_src_p" "p")) (parallel [(set (pc) (match_operand:SI 2 "register_operand" "r")) (use (label_ref (match_operand 3 "" "")))])] "REGNO (operands[0]) != REGNO (operands[2]) && single_insn_extra_test (operands[0], operands[1])" "* return output_delayed_branch (\"jmp %2\", operands, insn);")(define_peephole [(set (match_operand:SI 0 "memory_operand" "=m") (match_operand:SI 1 "reg_or_0_operand" "rJ")) (parallel [(set (pc) (match_operand:SI 2 "register_operand" "r")) (use (label_ref (match_operand 3 "" "")))])] "" "* return output_delayed_branch (\"jmp %2\", operands, insn);");;- jump to subroutine(define_expand "call" [(call (match_operand:SI 0 "memory_operand" "m") (match_operand 1 "" "i"))] ;; operand[2] is next_arg_register "" "{ rtx fn_rtx, nregs_rtx; if (TARGET_SUN_ASM && GET_CODE (XEXP (operands[0], 0)) == REG) { rtx g1_rtx = gen_rtx (REG, SImode, 1); emit_move_insn (g1_rtx, XEXP (operands[0], 0)); fn_rtx = gen_rtx (MEM, SImode, g1_rtx); } else fn_rtx = operands[0]; /* Count the number of parameter registers being used by this call. if that argument is NULL, it means we are using them all, which means 6 on the sparc. */#if 0 if (operands[2]) nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[2]) - 8); else nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6);#else nregs_rtx = const0_rtx;#endif emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2, gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx), gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, 31))))); DONE;}")(define_insn "" [(call (match_operand:SI 0 "memory_operand" "m") (match_operand 1 "" "i")) (use (reg:SI 31))] ;;- Don't use operand 1 for most machines. "CONSTANT_P (XEXP (operands[0], 0)) || GET_CODE (XEXP (operands[0], 0)) == REG" "*{ /* strip the MEM. */ operands[0] = XEXP (operands[0], 0); CC_STATUS_INIT; if (TARGET_SUN_ASM && GET_CODE (operands[0]) == REG) return \"jmpl %a0,%%o7\;nop\"; return \"call %a0,%1\;nop\";}")(define_peephole [(set (match_operand:SI 0 "register_operand" "=r") (match_operand:SI 1 "single_insn_src_p" "p")) (parallel [(call (match_operand:SI 2 "memory_operand" "m") (match_operand 3 "" "i")) (use (reg:SI 31))])] ;;- Don't use operand 1 for most machines. "! reg_mentioned_p (operands[0], operands[2]) && single_insn_extra_test (operands[0], operands[1])" "*{ /* strip the MEM. */ operands[2] = XEXP (operands[2], 0); if (TARGET_SUN_ASM && GET_CODE (operands[2]) == REG) return output_delayed_branch (\"jmpl %a2,%%o7\", operands, insn); return output_delayed_branch (\"call %a2,%3\", operands, insn);}")(define_peephole [(set (match_operand:SI 0 "memory_operand" "=m") (match_operand:SI 1 "reg_or_0_operand" "rJ")) (parallel [(call (match_operand:SI 2 "memory_operand" "m") (match_operand 3 "" "i")) (use (reg:SI 31))])] ;;- Don't use operand 1 for most machines. "" "*{ /* strip the MEM. */ operands[2] = XEXP (operands[2], 0); if (TARGET_SUN_ASM && GET_CODE (operands[2]) == REG) return output_delayed_branch (\"jmpl %a2,%%o7\", operands, insn); return output_delayed_branch (\"call %a2,%3\", operands, insn);}")(define_expand "call_value" [(set (match_operand 0 "register_operand" "=rf") (call (match_operand:SI 1 "memory_operand" "m") (match_operand 2 "" "i")))] ;; operand 3 is next_arg_register "" "{ rtx fn_rtx, nregs_rtx; rtvec vec; if (TARGET_SUN_ASM && GET_CODE (XEXP (operands[1], 0)) == REG) { rtx g1_rtx = gen_rtx (REG, SImode, 1); emit_move_insn (g1_rtx, XEXP (operands[1], 0)); fn_rtx = gen_rtx (MEM, SImode, g1_rtx); } else fn_rtx = operands[1];#if 0 if (operands[3]) nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[3]) - 8); else nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6);#
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -