📄 m88k.c
字号:
FILE *stream;{ char name[256], high[256], low[256]; for (; sb_name && sb_high && sb_low; sb_name = XEXP (sb_name, 1), sb_high = XEXP (sb_high, 1), sb_low = XEXP (sb_low, 1)) { ASM_GENERATE_INTERNAL_LABEL (name, "L", CODE_LABEL_NUMBER (XEXP (sb_name, 0))); ASM_GENERATE_INTERNAL_LABEL (high, "L", CODE_LABEL_NUMBER (XEXP (sb_high, 0))); ASM_GENERATE_INTERNAL_LABEL (low, "L", CODE_LABEL_NUMBER (XEXP (sb_low, 0))); /* This will change as the assembler requirements become known. */ fprintf (stream, "\t%s\t %s,%s-%s\n", SET_ASM_OP, &name[1], &high[1], &low[1]); } if (sb_name || sb_high || sb_low) abort ();}/* Return truth value of the statement that this conditional branch is likely to fall through. CONDITION, is the condition that JUMP_INSN is testing. */intmostly_false_jump (jump_insn, condition) rtx jump_insn, condition;{ rtx target_label = JUMP_LABEL (jump_insn); rtx insnt, insnj; /* Much of this isn't computed unless we're optimizing. */ if (optimize == 0) return 0; /* Determine if one path or the other leads to a return. */ for (insnt = NEXT_INSN (target_label); insnt; insnt = NEXT_INSN (insnt)) { if (GET_CODE (insnt) == JUMP_INSN) break; else if (GET_CODE (insnt) == INSN && GET_CODE (PATTERN (insnt)) == SEQUENCE && GET_CODE (XVECEXP (PATTERN (insnt), 0, 0)) == JUMP_INSN) { insnt = XVECEXP (PATTERN (insnt), 0, 0); break; } } if (insnt && (GET_CODE (PATTERN (insnt)) == RETURN || (GET_CODE (PATTERN (insnt)) == SET && GET_CODE (SET_SRC (PATTERN (insnt))) == REG && REGNO (SET_SRC (PATTERN (insnt))) == 1))) insnt = 0; for (insnj = NEXT_INSN (jump_insn); insnj; insnj = NEXT_INSN (insnj)) { if (GET_CODE (insnj) == JUMP_INSN) break; else if (GET_CODE (insnj) == INSN && GET_CODE (PATTERN (insnj)) == SEQUENCE && GET_CODE (XVECEXP (PATTERN (insnj), 0, 0)) == JUMP_INSN) { insnj = XVECEXP (PATTERN (insnj), 0, 0); break; } } if (insnj && (GET_CODE (PATTERN (insnj)) == RETURN || (GET_CODE (PATTERN (insnj)) == SET && GET_CODE (SET_SRC (PATTERN (insnj))) == REG && REGNO (SET_SRC (PATTERN (insnj))) == 1))) insnj = 0; /* Predict to not return. */ if ((insnt == 0) != (insnj == 0)) return (insnt == 0); /* Predict loops to loop. */ for (insnt = PREV_INSN (target_label); insnt && GET_CODE (insnt) == NOTE; insnt = PREV_INSN (insnt)) if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_END) return 1; else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_BEG) return 0; else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_CONT) return 0; /* Predict backward branches usually take. */ if (final_sequence) insnj = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0))); else insnj = jump_insn; if (insn_addresses[INSN_UID (insnj)] > insn_addresses[INSN_UID (target_label)]) return 0; /* EQ tests are usually false and NE tests are usually true. Also, most quantities are positive, so we can make the appropriate guesses about signed comparisons against zero. Consider unsigned comparisons to be a range check and assume quantities to be in range. */ switch (GET_CODE (condition)) { case CONST_INT: /* Unconditional branch. */ return 0; case EQ: return 1; case NE: return 0; case LE: case LT: case GEU: case GTU: /* Must get casesi right at least. */ if (XEXP (condition, 1) == const0_rtx) return 1; break; case GE: case GT: case LEU: case LTU: if (XEXP (condition, 1) == const0_rtx) return 0; break; } return 0;}/* Return true if the operand is a power of two and is a floating point type (to optimize division by power of two into multiplication). */intreal_power_of_2_operand (op, mode) rtx op; enum machine_mode mode;{ union { REAL_VALUE_TYPE d; int i[sizeof (REAL_VALUE_TYPE) / sizeof (int)]; struct { /* IEEE double precision format */ unsigned sign : 1; unsigned exponent : 11; unsigned mantissa1 : 20; unsigned mantissa2; } s; struct { /* IEEE double format to quick check */ unsigned sign : 1; /* if it fits in a float */ unsigned exponent1 : 4; unsigned exponent2 : 7; unsigned mantissa1 : 20; unsigned mantissa2; } s2; } u; if (GET_MODE (op) != DFmode && GET_MODE (op) != SFmode) return 0; if (GET_CODE (op) != CONST_DOUBLE) return 0; u.i[0] = CONST_DOUBLE_LOW (op); u.i[1] = CONST_DOUBLE_HIGH (op); if (u.s.mantissa1 != 0 || u.s.mantissa2 != 0 /* not a power of two */ || u.s.exponent == 0 /* constant 0.0 */ || u.s.exponent == 0x7ff /* NAN */ || (u.s2.exponent1 != 0x8 && u.s2.exponent1 != 0x7)) return 0; /* const won't fit in float */ return 1;}/* Make OP legitimate for mode MODE. Currently this only deals with DFmode operands, putting them in registers and making CONST_DOUBLE values SFmode where possible. */struct rtx_def *legitimize_operand (op, mode) rtx op; enum machine_mode mode;{ rtx temp; union { union real_extract r; struct { /* IEEE double precision format */ unsigned sign : 1; unsigned exponent : 11; unsigned mantissa1 : 20; unsigned mantissa2; } d; struct { /* IEEE double format to quick check */ unsigned sign : 1; /* if it fits in a float */ unsigned exponent1 : 4; unsigned exponent2 : 7; unsigned mantissa1 : 20; unsigned mantissa2; } s; } u; if (GET_CODE (op) == REG || mode != DFmode) return op; if (GET_CODE (op) == CONST_DOUBLE) { bcopy (&CONST_DOUBLE_LOW (op), &u.r, sizeof u); if (u.d.exponent != 0x7ff /* NaN */ && u.d.mantissa2 == 0 /* Mantissa fits */ && (u.s.exponent1 == 0x8 || u.s.exponent1 == 0x7) /* Exponent fits */ && (temp = simplify_unary_operation (FLOAT_TRUNCATE, SFmode, op, mode)) != 0) return gen_rtx (FLOAT_EXTEND, mode, force_reg (SFmode, temp)); } else if (register_operand (op, mode)) return op; return force_reg (mode, op);}/* Return true if OP is a suitable input for a move insn. */intmove_operand (op, mode) rtx op; enum machine_mode mode;{ if (register_operand (op, mode)) return 1; if (GET_CODE (op) == CONST_INT) return (classify_integer (mode, INTVAL (op)) < m88k_oru_hi16); if (GET_MODE (op) != mode) return 0; if (GET_CODE (op) == SUBREG) op = SUBREG_REG (op); if (GET_CODE (op) != MEM) return 0; op = XEXP (op, 0); if (GET_CODE (op) == LO_SUM) return (REG_P (XEXP (op, 0)) && symbolic_address_p (XEXP (op, 1))); return memory_address_p (mode, op);}/* Return true if OP is suitable for a call insn. */intcall_address_operand (op, mode) rtx op; enum machine_mode mode;{ return (REG_P (op) || symbolic_address_p (op));}/* Returns true if OP is either a symbol reference or a sum of a symbol reference and a constant. */intsymbolic_address_p (op) register rtx op;{ switch (GET_CODE (op)) { case SYMBOL_REF: case LABEL_REF: return 1; case CONST: op = XEXP (op, 0); return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF || GET_CODE (XEXP (op, 0)) == LABEL_REF) && GET_CODE (XEXP (op, 1)) == CONST_INT); default: return 0; }}/* Return true if OP is a register or const0_rtx. */intreg_or_0_operand (op, mode) rtx op; enum machine_mode mode;{ return (op == const0_rtx || register_operand (op, mode));}/* Nonzero if OP is a valid second operand for an arithmetic insn. */intarith_operand (op, mode) rtx op; enum machine_mode mode;{ return (register_operand (op, mode) || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));}/* Return true if OP is a register or 5 bit integer. */intarith5_operand (op, mode) rtx op; enum machine_mode mode;{ return (register_operand (op, mode) || (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32));}intarith32_operand (op, mode) rtx op; enum machine_mode mode;{ return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);}intarith64_operand (op, mode) rtx op; enum machine_mode mode;{ return (register_operand (op, mode) || GET_CODE (op) == CONST_INT || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode));}intint5_operand (op, mode) rtx op; enum machine_mode mode;{ return (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32);}intint32_operand (op, mode) rtx op; enum machine_mode mode;{ return (GET_CODE (op) == CONST_INT);}/* Return true if OP is a register or a valid immediate operand for addu or subu. */intadd_operand (op, mode) rtx op; enum machine_mode mode;{ return (register_operand (op, mode) || (GET_CODE (op) == CONST_INT && ADD_INT (op)));}/* Nonzero if this is a bitmask filling the bottom bits, for optimizing and + shift left combinations into a single mak instruction. */intmak_mask_p (value) int value;{ return (value && POWER_OF_2_or_0 (value + 1));}intreg_or_bbx_mask_operand (op, mode) rtx op; enum machine_mode mode;{ int value; if (register_operand (op, mode)) return 1; if (GET_CODE (op) != CONST_INT) return 0; value = INTVAL (op); if (POWER_OF_2 (value)) return 1; return 0;}/* Return true if OP is valid to use in the context of a floating point operation. Special case 0.0, since we can use r0. */intreal_or_0_operand (op, mode) rtx op; enum machine_mode mode;{ if (mode != SFmode && mode != DFmode) return 0; return (register_operand (op, mode) || (GET_CODE (op) == CONST_DOUBLE && op == CONST0_RTX (mode)));}/* Return true if OP is valid to use in the context of logic arithmetic on condition codes. */intpartial_ccmode_register_operand (op, mode) rtx op; enum machine_mode mode;{ return register_operand (op, CCmode) || register_operand (op, CCEVENmode);}/* Return true if OP is a relational operator. */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; default: return 0; }}inteven_relop (op, mode) rtx op; enum machine_mode mode;{ switch (GET_CODE (op)) { case EQ: case LT: case GT: case LTU: case GTU: return 1; default: return 0; }}intodd_relop (op, mode) rtx op; enum machine_mode mode;{ switch (GET_CODE (op)) { case NE: case LE: case GE: case LEU: case GEU:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -