📄 m32c.c
字号:
if (TARGET_A24) { call_used_regs[R1_REGNO] = 0; call_used_regs[R2_REGNO] = 0; call_used_regs[R3_REGNO] = 0; call_used_regs[A0_REGNO] = 0; call_used_regs[A1_REGNO] = 0; }}/* How Values Fit in Registers *//* Implements HARD_REGNO_NREGS. This is complicated by the fact that different registers are different sizes from each other, *and* may be different sizes in different chip families. */intm32c_hard_regno_nregs (int regno, enum machine_mode mode){ if (regno == FLG_REGNO && mode == CCmode) return 1; if (regno >= FIRST_PSEUDO_REGISTER) return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD); if (regno >= MEM0_REGNO && regno <= MEM7_REGNO) return (GET_MODE_SIZE (mode) + 1) / 2; if (GET_MODE_SIZE (mode) <= 1) return nregs_table[regno].qi_regs; if (GET_MODE_SIZE (mode) <= 2) return nregs_table[regno].hi_regs; if (regno == A0_REGNO && mode == PSImode && TARGET_A16) return 2; if ((GET_MODE_SIZE (mode) <= 3 || mode == PSImode) && TARGET_A24) return nregs_table[regno].pi_regs; if (GET_MODE_SIZE (mode) <= 4) return nregs_table[regno].si_regs; if (GET_MODE_SIZE (mode) <= 8) return nregs_table[regno].di_regs; return 0;}/* Implements HARD_REGNO_MODE_OK. The above function does the work already; just test its return value. */intm32c_hard_regno_ok (int regno, enum machine_mode mode){ return m32c_hard_regno_nregs (regno, mode) != 0;}/* Implements MODES_TIEABLE_P. In general, modes aren't tieable since registers are all different sizes. However, since most modes are bigger than our registers anyway, it's easier to implement this function that way, leaving QImode as the only unique case. */intm32c_modes_tieable_p (enum machine_mode m1, enum machine_mode m2){ if (GET_MODE_SIZE (m1) == GET_MODE_SIZE (m2)) return 1; if (m1 == QImode || m2 == QImode) return 0; return 1;}/* Register Classes *//* Implements REGNO_REG_CLASS. */enum machine_modem32c_regno_reg_class (int regno){ switch (regno) { case R0_REGNO: return R0_REGS; case R1_REGNO: return R1_REGS; case R2_REGNO: return R2_REGS; case R3_REGNO: return R3_REGS; case A0_REGNO: case A1_REGNO: return A_REGS; case SB_REGNO: return SB_REGS; case FB_REGNO: return FB_REGS; case SP_REGNO: return SP_REGS; case FLG_REGNO: return FLG_REGS; default: if (IS_MEM_REGNO (regno)) return MEM_REGS; return ALL_REGS; }}/* Implements REG_CLASS_FROM_CONSTRAINT. Note that some constraints only match for certain chip families. */intm32c_reg_class_from_constraint (char c ATTRIBUTE_UNUSED, const char *s){ if (memcmp (s, "Rsp", 3) == 0) return SP_REGS; if (memcmp (s, "Rfb", 3) == 0) return FB_REGS; if (memcmp (s, "Rsb", 3) == 0) return SB_REGS; if (memcmp (s, "Rcr", 3) == 0 && TARGET_A16) return CR_REGS; if (memcmp (s, "Rcl", 3) == 0 && TARGET_A24) return CR_REGS; if (memcmp (s, "R0w", 3) == 0) return R0_REGS; if (memcmp (s, "R1w", 3) == 0) return R1_REGS; if (memcmp (s, "R2w", 3) == 0) return R2_REGS; if (memcmp (s, "R3w", 3) == 0) return R3_REGS; if (memcmp (s, "R02", 3) == 0) return R02_REGS; if (memcmp (s, "R03", 3) == 0) return R03_REGS; if (memcmp (s, "Rdi", 3) == 0) return DI_REGS; if (memcmp (s, "Rhl", 3) == 0) return HL_REGS; if (memcmp (s, "R23", 3) == 0) return R23_REGS; if (memcmp (s, "Raa", 3) == 0) return A_REGS; if (memcmp (s, "Raw", 3) == 0 && TARGET_A16) return A_REGS; if (memcmp (s, "Ral", 3) == 0 && TARGET_A24) return A_REGS; if (memcmp (s, "Rqi", 3) == 0) return QI_REGS; if (memcmp (s, "Rad", 3) == 0) return AD_REGS; if (memcmp (s, "Rsi", 3) == 0) return SI_REGS; if (memcmp (s, "Rhi", 3) == 0) return HI_REGS; if (memcmp (s, "Rhc", 3) == 0) return HC_REGS; if (memcmp (s, "Rra", 3) == 0) return RA_REGS; if (memcmp (s, "Rfl", 3) == 0) return FLG_REGS; if (memcmp (s, "Rmm", 3) == 0) { if (fixed_regs[MEM0_REGNO]) return NO_REGS; return MEM_REGS; } /* PSImode registers - i.e. whatever can hold a pointer. */ if (memcmp (s, "Rpi", 3) == 0) { if (TARGET_A16) return HI_REGS; else return RA_REGS; /* r2r0 and r3r1 can hold pointers. */ } /* We handle this one as an EXTRA_CONSTRAINT. */ if (memcmp (s, "Rpa", 3) == 0) return NO_REGS; return NO_REGS;}/* Implements REGNO_OK_FOR_BASE_P. */intm32c_regno_ok_for_base_p (int regno){ if (regno == A0_REGNO || regno == A1_REGNO || regno >= FIRST_PSEUDO_REGISTER) return 1; return 0;}#define DEBUG_RELOAD 0/* Implements PREFERRED_RELOAD_CLASS. In general, prefer general registers of the appropriate size. */intm32c_preferred_reload_class (rtx x, int rclass){ int newclass = rclass;#if DEBUG_RELOAD fprintf (stderr, "\npreferred_reload_class for %s is ", class_names[rclass]);#endif if (rclass == NO_REGS) rclass = GET_MODE (x) == QImode ? HL_REGS : R03_REGS; if (classes_intersect (rclass, CR_REGS)) { switch (GET_MODE (x)) { case QImode: newclass = HL_REGS; break; default: /* newclass = HI_REGS; */ break; } } else if (newclass == QI_REGS && GET_MODE_SIZE (GET_MODE (x)) > 2) newclass = SI_REGS; else if (GET_MODE_SIZE (GET_MODE (x)) > 4 && ~class_contents[rclass][0] & 0x000f) newclass = DI_REGS; rclass = reduce_class (rclass, newclass, rclass); if (GET_MODE (x) == QImode) rclass = reduce_class (rclass, HL_REGS, rclass);#if DEBUG_RELOAD fprintf (stderr, "%s\n", class_names[rclass]); debug_rtx (x); if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == PLUS && GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS) fprintf (stderr, "Glorm!\n");#endif return rclass;}/* Implements PREFERRED_OUTPUT_RELOAD_CLASS. */intm32c_preferred_output_reload_class (rtx x, int rclass){ return m32c_preferred_reload_class (x, rclass);}/* Implements LIMIT_RELOAD_CLASS. We basically want to avoid using address registers for reloads since they're needed for address reloads. */intm32c_limit_reload_class (enum machine_mode mode, int rclass){#if DEBUG_RELOAD fprintf (stderr, "limit_reload_class for %s: %s ->", mode_name[mode], class_names[rclass]);#endif if (mode == QImode) rclass = reduce_class (rclass, HL_REGS, rclass); else if (mode == HImode) rclass = reduce_class (rclass, HI_REGS, rclass); else if (mode == SImode) rclass = reduce_class (rclass, SI_REGS, rclass); if (rclass != A_REGS) rclass = reduce_class (rclass, DI_REGS, rclass);#if DEBUG_RELOAD fprintf (stderr, " %s\n", class_names[rclass]);#endif return rclass;}/* Implements SECONDARY_RELOAD_CLASS. QImode have to be reloaded in r0 or r1, as those are the only real QImode registers. CR regs get reloaded through appropriately sized general or address registers. */intm32c_secondary_reload_class (int rclass, enum machine_mode mode, rtx x){ int cc = class_contents[rclass][0];#if DEBUG0 fprintf (stderr, "\nsecondary reload class %s %s\n", class_names[rclass], mode_name[mode]); debug_rtx (x);#endif if (mode == QImode && GET_CODE (x) == MEM && (cc & ~class_contents[R23_REGS][0]) == 0) return QI_REGS; if (classes_intersect (rclass, CR_REGS) && GET_CODE (x) == REG && REGNO (x) >= SB_REGNO && REGNO (x) <= SP_REGNO) return TARGET_A16 ? HI_REGS : A_REGS; return NO_REGS;}/* Implements CLASS_LIKELY_SPILLED_P. A_REGS is needed for address reloads. */intm32c_class_likely_spilled_p (int regclass){ if (regclass == A_REGS) return 1; return reg_class_size[regclass] == 1;}/* Implements CLASS_MAX_NREGS. We calculate this according to its documented meaning, to avoid potential inconsistencies with actual class definitions. */intm32c_class_max_nregs (int regclass, enum machine_mode mode){ int rn, max = 0; for (rn = 0; rn < FIRST_PSEUDO_REGISTER; rn++) if (class_contents[regclass][0] & (1 << rn)) { int n = m32c_hard_regno_nregs (rn, mode); if (max < n) max = n; } return max;}/* Implements CANNOT_CHANGE_MODE_CLASS. Only r0 and r1 can change to QI (r0l, r1l) because the chip doesn't support QI ops on other registers (well, it does on a0/a1 but if we let gcc do that, reload suffers). Otherwise, we allow changes to larger modes. */intm32c_cannot_change_mode_class (enum machine_mode from, enum machine_mode to, int rclass){#if DEBUG0 fprintf (stderr, "cannot change from %s to %s in %s\n", mode_name[from], mode_name[to], class_names[rclass]);#endif if (to == QImode) return (class_contents[rclass][0] & 0x1ffa); if (class_contents[rclass][0] & 0x0005 /* r0, r1 */ && GET_MODE_SIZE (from) > 1) return 0; if (GET_MODE_SIZE (from) > 2) /* all other regs */ return 0; return 1;}/* Helpers for the rest of the file. *//* TRUE if the rtx is a REG rtx for the given register. */#define IS_REG(rtx,regno) (GET_CODE (rtx) == REG \ && REGNO (rtx) == regno)/* TRUE if the rtx is a pseudo - specifically, one we can use as a base register in address calculations (hence the "strict" argument). */#define IS_PSEUDO(rtx,strict) (!strict && GET_CODE (rtx) == REG \ && (REGNO (rtx) == AP_REGNO \ || REGNO (rtx) >= FIRST_PSEUDO_REGISTER))/* Implements CONST_OK_FOR_CONSTRAINT_P. Currently, all constant constraints start with 'I', with the next two characters indicating the type and size of the range allowed. */intm32c_const_ok_for_constraint_p (HOST_WIDE_INT value, char c ATTRIBUTE_UNUSED, const char *str){ /* s=signed u=unsigned n=nonzero m=minus l=log2able, [sun] bits [SUN] bytes, p=pointer size I[-0-9][0-9] matches that number */ if (memcmp (str, "Is3", 3) == 0) { return (-8 <= value && value <= 7); } if (memcmp (str, "IS1", 3) == 0) { return (-128 <= value && value <= 127); } if (memcmp (str, "IS2", 3) == 0) { return (-32768 <= value && value <= 32767); } if (memcmp (str, "IU2", 3) == 0) { return (0 <= value && value <= 65535); } if (memcmp (str, "IU3", 3) == 0) { return (0 <= value && value <= 0x00ffffff); } if (memcmp (str, "In4", 3) == 0) { return (-8 <= value && value && value <= 8); } if (memcmp (str, "In5", 3) == 0) { return (-16 <= value && value && value <= 16); } if (memcmp (str, "IM2", 3) == 0) { return (-65536 <= value && value && value <= -1); } if (memcmp (str, "Ilb", 3) == 0) { int b = exact_log2 (value); return (b >= 1 && b <= 8); } if (memcmp (str, "Ilw", 3) == 0) { int b = exact_log2 (value); return (b >= 1 && b <= 16); } return 0;}/* Implements EXTRA_CONSTRAINT_STR (see next function too). 'S' is for memory constraints, plus "Rpa" for PARALLEL rtx's we use for call return values. */intm32c_extra_constraint_p2 (rtx value, char c ATTRIBUTE_UNUSED, const char *str){ encode_pattern (value); if (memcmp (str, "Sd", 2) == 0) { /* This is the common "src/dest" address */ rtx r; if (GET_CODE (value) == MEM && CONSTANT_P (XEXP (value, 0))) return 1; if (RTX_IS ("ms") || RTX_IS ("m+si")) return 1; if (RTX_IS ("mr")) r = patternr[1]; else if (RTX_IS ("m+ri") || RTX_IS ("m+rs") || RTX_IS ("m+r+si")) r = patternr[2]; else return 0; if (REGNO (r) == SP_REGNO) return 0; return m32c_legitimate_address_p (GET_MODE (value), XEXP (value, 0), 1); } else if (memcmp (str, "Sa", 2) == 0) { rtx r; if (RTX_IS ("mr")) r = patternr[1]; else if (RTX_IS ("m+ri")) r = patternr[2]; else return 0; return (IS_REG (r, A0_REGNO) || IS_REG (r, A1_REGNO)); } else if (memcmp (str, "Si", 2) == 0) { return (RTX_IS ("mi") || RTX_IS ("ms") || RTX_IS ("m+si")); } else if (memcmp (str, "Ss", 2) == 0) { return ((RTX_IS ("mr") && (IS_REG (patternr[1], SP_REGNO))) || (RTX_IS ("m+ri") && (IS_REG (patternr[2], SP_REGNO)))); } else if (memcmp (str, "Sf", 2) == 0) { return ((RTX_IS ("mr") && (IS_REG (patternr[1], FB_REGNO))) || (RTX_IS ("m+ri") && (IS_REG (patternr[2], FB_REGNO)))); } else if (memcmp (str, "Sb", 2) == 0) { return ((RTX_IS ("mr") && (IS_REG (patternr[1], SB_REGNO))) || (RTX_IS ("m+ri") && (IS_REG (patternr[2], SB_REGNO)))); } else if (memcmp (str, "S1", 2) == 0) { return r1h_operand (value, QImode); } gcc_assert (str[0] != 'S'); if (memcmp (str, "Rpa", 2) == 0) return GET_CODE (value) == PARALLEL; return 0;}/* This is for when we're debugging the above. */intm32c_extra_constraint_p (rtx value, char c, const char *str){ int rv = m32c_extra_constraint_p2 (value, c, str);#if DEBUG0 fprintf (stderr, "\nconstraint %.*s: %d\n", CONSTRAINT_LEN (c, str), str, rv); debug_rtx (value);#endif return rv;}/* Implements EXTRA_MEMORY_CONSTRAINT. Currently, we only use strings starting with 'S'. */intm32c_extra_memory_constraint (char c, const char *str ATTRIBUTE_UNUSED){ return c == 'S';}/* Implements EXTRA_ADDRESS_CONSTRAINT. We reserve 'A' strings for these, but don't currently define any. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -