📄 m32r.c
字号:
REAL_VALUE_FROM_CONST_DOUBLE (r, op); REAL_VALUE_TO_TARGET_DOUBLE (r, l); if (l[0] == 0 && l[1] == 0) return 1; if ((l[0] & 0xffff) == 0 && l[1] == 0) return 1; return 0;}/* Return 1 if OP is an EQ or NE comparison operator. */inteqne_comparison_operator (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ enum rtx_code code = GET_CODE (op); if (GET_RTX_CLASS (code) != '<') return 0; return (code == EQ || code == NE);}/* Return 1 if OP is a signed comparison operator. */intsigned_comparison_operator (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ enum rtx_code code = GET_CODE (op); if (GET_RTX_CLASS (code) != '<') return 0; return (code == EQ || code == NE || code == LT || code == LE || code == GT || code == GE);}/* Return 1 if OP is (mem (reg ...)). This is used in insn length calcs. */intmemreg_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ return GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == REG;}/* Return true if OP is an acceptable input argument for a zero/sign extend operation. */intextend_operand (op, mode) rtx op; enum machine_mode mode;{ rtx addr; switch (GET_CODE (op)) { case REG : case SUBREG : return register_operand (op, mode); case MEM : addr = XEXP (op, 0); if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC) return 0; /* loads can't do pre inc/pre dec */ return address_operand (addr, mode); default : return 0; }}/* Return nonzero if the operand is an insn that is a small insn. Allow const_int 0 as well, which is a placeholder for NOP slots. */intsmall_insn_p (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ if (GET_CODE (op) == CONST_INT && INTVAL (op) == 0) return 1; if (! INSN_P (op)) return 0; return get_attr_length (op) == 2;}/* Return nonzero if the operand is an insn that is a large insn. */intlarge_insn_p (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ if (! INSN_P (op)) return 0; return get_attr_length (op) != 2;}/* Comparisons. *//* X and Y are two things to compare using CODE. Emit the compare insn and return the rtx for compare [arg0 of the if_then_else]. If need_compare is true then the comparison insn must be generated, rather than being susummed into the following branch instruction. */rtxgen_compare (code, x, y, need_compare) enum rtx_code code; rtx x, y; int need_compare;{ enum rtx_code compare_code, branch_code; rtx cc_reg = gen_rtx_REG (CCmode, CARRY_REGNUM); int must_swap = 0; switch (code) { case EQ: compare_code = EQ; branch_code = NE; break; case NE: compare_code = EQ; branch_code = EQ; break; case LT: compare_code = LT; branch_code = NE; break; case LE: compare_code = LT; branch_code = EQ; must_swap = 1; break; case GT: compare_code = LT; branch_code = NE; must_swap = 1; break; case GE: compare_code = LT; branch_code = EQ; break; case LTU: compare_code = LTU; branch_code = NE; break; case LEU: compare_code = LTU; branch_code = EQ; must_swap = 1; break; case GTU: compare_code = LTU; branch_code = NE; must_swap = 1; break; case GEU: compare_code = LTU; branch_code = EQ; break; default: abort (); } if (need_compare) { switch (compare_code) { case EQ: if (GET_CODE (y) == CONST_INT && CMP_INT16_P (INTVAL (y)) /* reg equal to small const. */ && y != const0_rtx) { rtx tmp = gen_reg_rtx (SImode); emit_insn (gen_cmp_ne_small_const_insn (tmp, x, y)); x = tmp; y = const0_rtx; } else if (CONSTANT_P (y)) /* reg equal to const. */ { rtx tmp = force_reg (GET_MODE (x), y); y = tmp; } if (register_operand (y, SImode) /* reg equal to reg. */ || y == const0_rtx) /* req equal to zero. */ { emit_insn (gen_cmp_eqsi_insn (x, y)); return gen_rtx (code, CCmode, cc_reg, const0_rtx); } break; case LT: if (register_operand (y, SImode) || (GET_CODE (y) == CONST_INT && CMP_INT16_P (INTVAL (y)))) { rtx tmp = gen_reg_rtx (SImode); /* reg compared to reg. */ switch (code) { case LT: emit_insn (gen_cmp_ltsi_insn (x, y)); code = EQ; break; case LE: if (y == const0_rtx) tmp = const1_rtx; else emit_insn (gen_cmp_ne_small_const_insn (tmp, y, const1_rtx)); emit_insn (gen_cmp_ltsi_insn (x, tmp)); code = EQ; break; case GT: if (GET_CODE (y) == CONST_INT) tmp = gen_rtx (PLUS, SImode, y, const1_rtx); else emit_insn (gen_cmp_ne_small_const_insn (tmp, y, const1_rtx)); emit_insn (gen_cmp_ltsi_insn (x, tmp)); code = NE; break; case GE: emit_insn (gen_cmp_ltsi_insn (x, y)); code = NE; break; default: abort (); } return gen_rtx (code, CCmode, cc_reg, const0_rtx); } break; case LTU: if (register_operand (y, SImode) || (GET_CODE (y) == CONST_INT && CMP_INT16_P (INTVAL (y)))) { rtx tmp = gen_reg_rtx (SImode); /* reg (unsigned) compared to reg. */ switch (code) { case LTU: emit_insn (gen_cmp_ltusi_insn (x, y)); code = EQ; break; case LEU: if (y == const0_rtx) tmp = const1_rtx; else emit_insn (gen_cmp_ne_small_const_insn (tmp, y, const1_rtx)); emit_insn (gen_cmp_ltusi_insn (x, tmp)); code = EQ; break; case GTU: if (GET_CODE (y) == CONST_INT) tmp = gen_rtx (PLUS, SImode, y, const1_rtx); else emit_insn (gen_cmp_ne_small_const_insn (tmp, y, const1_rtx)); emit_insn (gen_cmp_ltusi_insn (x, tmp)); code = NE; break; case GEU: emit_insn (gen_cmp_ltusi_insn (x, y)); code = NE; break; default: abort(); } return gen_rtx (code, CCmode, cc_reg, const0_rtx); } break; default: abort(); } } else { /* reg/reg equal comparison */ if (compare_code == EQ && register_operand (y, SImode)) return gen_rtx (code, CCmode, x, y); /* reg/zero signed comparison */ if ((compare_code == EQ || compare_code == LT) && y == const0_rtx) return gen_rtx (code, CCmode, x, y); /* reg/smallconst equal comparison */ if (compare_code == EQ && GET_CODE (y) == CONST_INT && CMP_INT16_P (INTVAL (y))) { rtx tmp = gen_reg_rtx (SImode); emit_insn (gen_cmp_ne_small_const_insn (tmp, x, y)); return gen_rtx (code, CCmode, tmp, const0_rtx); } /* reg/const equal comparison */ if (compare_code == EQ && CONSTANT_P (y)) { rtx tmp = force_reg (GET_MODE (x), y); return gen_rtx (code, CCmode, x, tmp); } } if (CONSTANT_P (y)) { if (must_swap) y = force_reg (GET_MODE (x), y); else { int ok_const = (code == LTU || code == LEU || code == GTU || code == GEU) ? uint16_operand (y, GET_MODE (y)) : reg_or_cmp_int16_operand (y, GET_MODE (y)); if (! ok_const) y = force_reg (GET_MODE (x), y); } } switch (compare_code) { case EQ : emit_insn (gen_cmp_eqsi_insn (must_swap ? y : x, must_swap ? x : y)); break; case LT : emit_insn (gen_cmp_ltsi_insn (must_swap ? y : x, must_swap ? x : y)); break; case LTU : emit_insn (gen_cmp_ltusi_insn (must_swap ? y : x, must_swap ? x : y)); break; default: abort (); } return gen_rtx (branch_code, VOIDmode, cc_reg, CONST0_RTX (CCmode));}/* Split a 2 word move (DI or DF) into component parts. */rtxgen_split_move_double (operands) rtx operands[];{ enum machine_mode mode = GET_MODE (operands[0]); rtx dest = operands[0]; rtx src = operands[1]; rtx val; /* We might have (SUBREG (MEM)) here, so just get rid of the subregs to make this code simpler. It is safe to call alter_subreg any time after reload. */ if (GET_CODE (dest) == SUBREG) alter_subreg (&dest); if (GET_CODE (src) == SUBREG) alter_subreg (&src); start_sequence (); if (GET_CODE (dest) == REG) { int dregno = REGNO (dest); /* reg = reg */ if (GET_CODE (src) == REG) { int sregno = REGNO (src); int reverse = (dregno == sregno + 1); /* We normally copy the low-numbered register first. However, if the first register operand 0 is the same as the second register of operand 1, we must copy in the opposite order. */ emit_insn (gen_rtx_SET (VOIDmode, operand_subword (dest, reverse, TRUE, mode), operand_subword (src, reverse, TRUE, mode))); emit_insn (gen_rtx_SET (VOIDmode, operand_subword (dest, !reverse, TRUE, mode), operand_subword (src, !reverse, TRUE, mode))); } /* reg = constant */ else if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE) { rtx words[2]; split_double (src, &words[0], &words[1]); emit_insn (gen_rtx_SET (VOIDmode, operand_subword (dest, 0, TRUE, mode), words[0])); emit_insn (gen_rtx_SET (VOIDmode, operand_subword (dest, 1, TRUE, mode), words[1])); } /* reg = mem */ else if (GET_CODE (src) == MEM) { /* If the high-address word is used in the address, we must load it last. Otherwise, load it first. */ int reverse = (refers_to_regno_p (dregno, dregno + 1, XEXP (src, 0), 0) != 0); /* We used to optimize loads from single registers as ld r1,r3+; ld r2,r3 if r3 were not used subsequently. However, the REG_NOTES aren't propigated correctly by the reload phase, and it can cause bad code to be generated. We could still try: ld r1,r3+; ld r2,r3; addi r3,-4 which saves 2 bytes and doesn't force longword alignment. */ emit_insn (gen_rtx_SET (VOIDmode, operand_subword (dest, reverse, TRUE, mode), adjust_address (src, SImode, reverse * UNITS_PER_WORD))); emit_insn (gen_rtx_SET (VOIDmode, operand_subword (dest, !reverse, TRUE, mode), adjust_address (src, SImode, !reverse * UNITS_PER_WORD))); } else abort (); } /* mem = reg */ /* We used to optimize loads from single registers as st r1,r3; st r2,+r3 if r3 were not used subsequently. However, the REG_NOTES aren't propigated correctly by the reload phase, and it can cause bad code to be generated. We could still try: st r1,r3; st r2,+r3; addi r3,-4 which saves 2 bytes and doesn't force longword alignment. */ else if (GET_CODE (dest) == MEM && GET_CODE (src) == REG) { emit_insn (gen_rtx_SET (VOIDmode, adjust_address (dest, SImode, 0), operand_subword (src, 0, TRUE, mode))); emit_insn (gen_rtx_SET (VOIDmode, adjust_address (dest, SImode, UNITS_PER_WORD), operand_subword (src, 1, TRUE, mode))); } else abort (); val = get_insns (); end_sequence (); return val;}/* Implements the FUNCTION_ARG_PARTIAL_NREGS macro. */intfunction_arg_partial_nregs (cum, mode, type, named) CUMULATIVE_ARGS *cum; enum machine_mode mode; tree type; int named ATTRIBUTE_UNUSED;{ int ret; unsigned int size = (((mode == BLKmode && type) ? (unsigned int) int_size_in_bytes (type) : GET_MODE_SIZE (mode)) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; if (*cum >= M32R_MAX_PARM_REGS) ret = 0; else if (*cum + size > M32R_MAX_PARM_REGS) ret = (*cum + size) - M32R_MAX_PARM_REGS; else ret = 0; return ret;}/* Do any needed setup for a variadic function. For the M32R, we must create a register parameter block, and then copy any anonymous arguments in registers to memory. CUM has not been updated for the last named argument which has type TYPE and mode MODE, and we rely on this fact. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -