📄 out-pyr.c
字号:
{ if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1))) <= UNITS_PER_WORD) return 0; regno_off1 = SUBREG_WORD (op1); op1 = SUBREG_REG (op1); code1 = REG; } if (code0 != code1) return 0; switch (code0) { case CONST_INT: /* Cannot permit any symbolic constants, even if the consecutive operand is 0, since a movl really performs sign extension. */ if (code1 != CONST_INT) return 0; if ((INTVAL (op0) == 0 && INTVAL (op1) == 0) || (INTVAL (op0) == -1 && INTVAL (op1) == -1)) return 3; if ((INTVAL (op0) == 0 && INTVAL (op1) > 0) || (INTVAL (op0) == -1 && INTVAL (op1) < 0)) return 2; if ((INTVAL (op1) == 0 && INTVAL (op0) > 0) || (INTVAL (op1) == -1 && INTVAL (op0) < 0)) return 1; break; case REG: regno_off0 = REGNO (op0) + regno_off0; regno_off1 = REGNO (op1) + regno_off1; cnst_diff = regno_off0 - regno_off1; if (cnst_diff == 1) { /* movl with the highest numbered parameter (local) register as source or destination, doesn't wrap to the lowest numbered local (temporary) register. */ if (regno_off0 % 16 != 0) return 1; else return 0; } else if (cnst_diff == -1) { if (regno_off1 % 16 != 0) return 2; else return 0; } break; case MEM: op0 = XEXP (op0, 0); op1 = XEXP (op1, 0); if (GET_CODE (op0) == CONST) op0 = XEXP (op0, 0); if (GET_CODE (op1) == CONST) op1 = XEXP (op1, 0); cnst_diff = constant_diff (op0, op1); if (cnst_diff) { if (cnst_diff == 4) return 1; else if (cnst_diff == -4) return 2; } break; } return 0;}/* Return the constant difference of the rtx expressions OP0 and OP1, or 0 if they don't have a constant difference. This function is used to determine if addresses are consecutive, and therefore possible to combine to fewer instructions. */intconstant_diff (op0, op1) rtx op0, op1;{ RTX_CODE code0, code1; int cnst_diff; code0 = GET_CODE (op0); code1 = GET_CODE (op1); if (code0 != code1) { if (code0 == PLUS) { if (GET_CODE (XEXP (op0, 1)) == CONST_INT && rtx_equal_p (op1, XEXP (op0, 0))) return INTVAL (XEXP (op0, 1)); } else if (code1 == PLUS) { if (GET_CODE (XEXP (op1, 1)) == CONST_INT && rtx_equal_p (op0, XEXP (op1, 0))) return -INTVAL (XEXP (op1, 1)); } return 0; } if (code0 == CONST_INT) return INTVAL (op0) - INTVAL (op1); if (code0 == PLUS) { cnst_diff = constant_diff (XEXP (op0, 0), XEXP (op1, 0)); if (cnst_diff) return (rtx_equal_p (XEXP (op0, 1), XEXP (op1, 1))) ? cnst_diff : 0; cnst_diff = constant_diff (XEXP (op0, 1), XEXP (op1, 1)); if (cnst_diff) return (rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0))) ? cnst_diff : 0; } return 0;}intalready_sign_extended (insn, from_mode, op) rtx insn; enum machine_mode from_mode; rtx op;{ rtx xinsn, xdest, xsrc; for (;;) { insn = PREV_INSN (insn); if (insn == 0) return 0; if (GET_CODE (insn) == NOTE || GET_CODE (insn) == JUMP_INSN) continue; if (GET_CODE (insn) == CALL_INSN && ! call_used_regs[REGNO (op)]) continue; if (GET_CODE (insn) != INSN) return 0; xinsn = PATTERN (insn); if (GET_CODE (xinsn) != SET) return 0; xdest = SET_DEST (xinsn); xsrc = SET_SRC (xinsn); if (GET_CODE (xdest) == SUBREG) abort (); if ( ! REG_P (xdest)) continue; if (REGNO (op) == REGNO (xdest) && ((GET_CODE (xsrc) == SIGN_EXTEND && GET_MODE (XEXP (xsrc, 0)) == from_mode) || (GET_CODE (xsrc) == MEM && GET_MODE (xsrc) == from_mode))) return 1; /* The register is modified by another operation. */ if (reg_overlap_mentioned_p (xdest, op)) return 0; }}char *output_move_double (operands) rtx *operands;{ if (GET_CODE (operands[1]) == CONST_DOUBLE) { if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT) { /* In an integer, the low-order word is in CONST_DOUBLE_LOW. */ rtx const_op = operands[1]; if ((CONST_DOUBLE_HIGH (const_op) == 0 && CONST_DOUBLE_LOW (const_op) >= 0) || (CONST_DOUBLE_HIGH (const_op) == -1 && CONST_DOUBLE_LOW (const_op) < 0)) { operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (const_op)); return "movl %1,%0"; } operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (const_op)); output_asm_insn ("movw %1,%0", operands); operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (const_op)); return "movw %1,%0"; } else { /* In a real, the low-address word is in CONST_DOUBLE_LOW. */ rtx const_op = operands[1]; if ((CONST_DOUBLE_LOW (const_op) == 0 && CONST_DOUBLE_HIGH (const_op) >= 0) || (CONST_DOUBLE_LOW (const_op) == -1 && CONST_DOUBLE_HIGH (const_op) < 0)) { operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (const_op)); return "movl %1,%0"; } operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (const_op)); output_asm_insn ("movw %1,%0", operands); operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (const_op)); return "movw %1,%0"; } } return "movl %1,%0";}/* Output a shift insns, after having reduced integer arguments to avoid as warnings. */char *output_shift (pattern, op2, mod) char *pattern; rtx op2; int mod;{ if (GET_CODE (op2) == CONST_INT) { int cnt = INTVAL (op2) % mod; if (cnt == 0) { cc_status = cc_prev_status; return ""; } op2 = gen_rtx (CONST_INT, VOIDmode, cnt); } return pattern;}/* Return non-zero if the code of this rtx pattern is a relop. */intrelop (op, mode) rtx op; enum machine_mode mode;{ switch (GET_CODE (op)) { case EQ: case NE: case LT: case LE: case GE: case GT: case LTU: case LEU: case GEU: case GTU: return 1; } return 0;}voidnotice_update_cc (EXP, INSN) rtx EXP, INSN;{ switch (GET_CODE (EXP)) { case SET: switch (GET_CODE (SET_DEST (EXP))) { case CC0: cc_status.mdep = 0; cc_status.flags = 0; cc_status.value1 = 0; cc_status.value2 = SET_SRC (EXP); break; case PC: break; case REG: switch (GET_CODE (SET_SRC (EXP))) { case CALL: goto call; case MEM: if (GET_MODE (SET_SRC (EXP)) == QImode || GET_MODE (SET_SRC (EXP)) == HImode) { cc_status.mdep = 0; cc_status.flags = CC_NO_OVERFLOW; cc_status.value1 = SET_DEST (EXP); cc_status.value2 = SET_SRC (EXP); break; } /* else: Fall through. */ case CONST_INT: case SYMBOL_REF: case LABEL_REF: case CONST: case CONST_DOUBLE: case REG: if (cc_status.value1 && reg_overlap_mentioned_p (SET_DEST (EXP), cc_status.value1)) cc_status.value1 = 0; if (cc_status.value2 && reg_overlap_mentioned_p (SET_DEST (EXP), cc_status.value2)) cc_status.value2 = 0; break; case UDIV: case UMOD: cc_status.mdep = CC_VALID_FOR_UNSIGNED; cc_status.flags = CC_NO_OVERFLOW; cc_status.value1 = SET_DEST (EXP); cc_status.value2 = SET_SRC (EXP); break; default: cc_status.mdep = 0; cc_status.flags = CC_NO_OVERFLOW; cc_status.value1 = SET_DEST (EXP); cc_status.value2 = SET_SRC (EXP); break; } break; case MEM: switch (GET_CODE (SET_SRC (EXP))) { case REG: if (GET_MODE (SET_SRC (EXP)) == QImode || GET_MODE (SET_SRC (EXP)) == HImode) { cc_status.flags = CC_NO_OVERFLOW; cc_status.value1 = SET_DEST (EXP); cc_status.value2 = SET_SRC (EXP); cc_status.mdep = 0; break; } /* else: Fall through. */ case CONST_INT: case SYMBOL_REF: case LABEL_REF: case CONST: case CONST_DOUBLE: case MEM: /* Need to forget cc_status about memory positions each time a memory store is made, even if the memory store insns in question doesn't modify the condition codes. */ if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM) cc_status.value1 = 0; if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM) cc_status.value2 = 0; break; case SIGN_EXTEND: case FLOAT_EXTEND: case FLOAT_TRUNCATE: case FLOAT: case FIX: cc_status.flags = CC_NO_OVERFLOW; cc_status.value1 = SET_DEST (EXP); cc_status.value2 = SET_SRC (EXP); cc_status.mdep = 0; break; default: abort (); } break; default: abort (); } break; case CALL: call: CC_STATUS_INIT; break; /* Do calls preserve the condition codes? (At least forget cc_status expressions if they refer to registers not preserved across calls. Also forget expressions about memory contents.) */ if (cc_status.value1 && (refers_to_regno_p (PYR_TREG (0), PYR_TREG (15), cc_status.value1, 0) || GET_CODE (cc_status.value1) == MEM)) cc_status.value1 = 0; if (cc_status.value2 && (refers_to_regno_p (PYR_TREG (0), PYR_TREG (15), cc_status.value2, 0) || GET_CODE (cc_status.value2) == MEM)) cc_status.value2 = 0; break; default: CC_STATUS_INIT; }}voidforget_cc_if_dependent (op) rtx op;{ cc_status = cc_prev_status; if (cc_status.value1 && reg_overlap_mentioned_p (op, cc_status.value1)) cc_status.value1 = 0; if (cc_status.value2 && reg_overlap_mentioned_p (op, cc_status.value2)) cc_status.value2 = 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -