📄 m68hc11.c
字号:
{ /* S_REGS class must not be used. The movhi template does not work to move a memory to a soft register. Restrict to a hard reg. */ switch (class) { default: case G_REGS: case D_OR_A_OR_S_REGS: class = A_OR_D_REGS; break; case A_OR_S_REGS: class = A_REGS; break; case D_OR_SP_OR_S_REGS: class = D_OR_SP_REGS; break; case D_OR_Y_OR_S_REGS: class = D_OR_Y_REGS; break; case D_OR_X_OR_S_REGS: class = D_OR_X_REGS; break; case SP_OR_S_REGS: class = SP_REGS; break; case Y_OR_S_REGS: class = Y_REGS; break; case X_OR_S_REGS: class = X_REGS; break; case D_OR_S_REGS: class = D_REGS; } } else if (class == Y_REGS && GET_CODE (operand) == MEM) { class = Y_REGS; } else if (class == A_OR_D_REGS && GET_MODE_SIZE (mode) == 4) { class = D_OR_X_REGS; } else if (class >= S_REGS && S_REG_P (operand)) { switch (class) { default: case G_REGS: case D_OR_A_OR_S_REGS: class = A_OR_D_REGS; break; case A_OR_S_REGS: class = A_REGS; break; case D_OR_SP_OR_S_REGS: class = D_OR_SP_REGS; break; case D_OR_Y_OR_S_REGS: class = D_OR_Y_REGS; break; case D_OR_X_OR_S_REGS: class = D_OR_X_REGS; break; case SP_OR_S_REGS: class = SP_REGS; break; case Y_OR_S_REGS: class = Y_REGS; break; case X_OR_S_REGS: class = X_REGS; break; case D_OR_S_REGS: class = D_REGS; } } else if (class >= S_REGS) { if (debug_m6811) { printf ("Class = %s for: ", reg_class_names[class]); fflush (stdout); debug_rtx (operand); } } if (debug_m6811) { printf (" => class=%s\n", reg_class_names[class]); fflush (stdout); debug_rtx (operand); } return class;}/* Return 1 if the operand is a valid indexed addressing mode. For 68hc11: n,r with n in [0..255] and r in A_REGS class For 68hc12: n,r no constraint on the constant, r in A_REGS class. */static intregister_indirect_p (rtx operand, enum machine_mode mode, int addr_mode){ rtx base, offset; switch (GET_CODE (operand)) { case MEM: if ((addr_mode & ADDR_INDIRECT) && GET_MODE_SIZE (mode) <= 2) return register_indirect_p (XEXP (operand, 0), mode, addr_mode & (ADDR_STRICT | ADDR_OFFSET)); return 0; case POST_INC: case PRE_INC: case POST_DEC: case PRE_DEC: if (addr_mode & ADDR_INCDEC) return register_indirect_p (XEXP (operand, 0), mode, addr_mode & ADDR_STRICT); return 0; case PLUS: base = XEXP (operand, 0); if (GET_CODE (base) == MEM) return 0; offset = XEXP (operand, 1); if (GET_CODE (offset) == MEM) return 0; /* Indexed addressing mode with 2 registers. */ if (GET_CODE (base) == REG && GET_CODE (offset) == REG) { if (!(addr_mode & ADDR_INDEXED)) return 0; addr_mode &= ADDR_STRICT; if (REGNO_OK_FOR_BASE_P2 (REGNO (base), addr_mode) && REGNO_OK_FOR_INDEX_P2 (REGNO (offset), addr_mode)) return 1; if (REGNO_OK_FOR_BASE_P2 (REGNO (offset), addr_mode) && REGNO_OK_FOR_INDEX_P2 (REGNO (base), addr_mode)) return 1; return 0; } if (!(addr_mode & ADDR_OFFSET)) return 0; if (GET_CODE (base) == REG) { if (!VALID_CONSTANT_OFFSET_P (offset, mode)) return 0; if (!(addr_mode & ADDR_STRICT)) return 1; return REGNO_OK_FOR_BASE_P2 (REGNO (base), 1); } if (GET_CODE (offset) == REG) { if (!VALID_CONSTANT_OFFSET_P (base, mode)) return 0; if (!(addr_mode & ADDR_STRICT)) return 1; return REGNO_OK_FOR_BASE_P2 (REGNO (offset), 1); } return 0; case REG: return REGNO_OK_FOR_BASE_P2 (REGNO (operand), addr_mode & ADDR_STRICT); case CONST_INT: if (addr_mode & ADDR_CONST) return VALID_CONSTANT_OFFSET_P (operand, mode); return 0; default: return 0; }}/* Returns 1 if the operand fits in a 68HC11 indirect mode or in a 68HC12 1-byte index addressing mode. */intm68hc11_small_indexed_indirect_p (rtx operand, enum machine_mode mode){ rtx base, offset; int addr_mode; if (GET_CODE (operand) == REG && reload_in_progress && REGNO (operand) >= FIRST_PSEUDO_REGISTER && reg_equiv_memory_loc[REGNO (operand)]) { operand = reg_equiv_memory_loc[REGNO (operand)]; operand = eliminate_regs (operand, 0, NULL_RTX); } if (GET_CODE (operand) != MEM) return 0; operand = XEXP (operand, 0); if (CONSTANT_ADDRESS_P (operand)) return 1; if (PUSH_POP_ADDRESS_P (operand)) return 1; addr_mode = m68hc11_mov_addr_mode | (reload_completed ? ADDR_STRICT : 0); if (!register_indirect_p (operand, mode, addr_mode)) return 0; if (TARGET_M6812 && GET_CODE (operand) == PLUS && (reload_completed | reload_in_progress)) { base = XEXP (operand, 0); offset = XEXP (operand, 1); /* The offset can be a symbol address and this is too big for the operand constraint. */ if (GET_CODE (base) != CONST_INT && GET_CODE (offset) != CONST_INT) return 0; if (GET_CODE (base) == CONST_INT) offset = base; switch (GET_MODE_SIZE (mode)) { case 8: if (INTVAL (offset) < -16 + 6 || INTVAL (offset) > 15 - 6) return 0; break; case 4: if (INTVAL (offset) < -16 + 2 || INTVAL (offset) > 15 - 2) return 0; break; default: if (INTVAL (offset) < -16 || INTVAL (offset) > 15) return 0; break; } } return 1;}intm68hc11_register_indirect_p (rtx operand, enum machine_mode mode){ int addr_mode; if (GET_CODE (operand) == REG && reload_in_progress && REGNO (operand) >= FIRST_PSEUDO_REGISTER && reg_equiv_memory_loc[REGNO (operand)]) { operand = reg_equiv_memory_loc[REGNO (operand)]; operand = eliminate_regs (operand, 0, NULL_RTX); } if (GET_CODE (operand) != MEM) return 0; operand = XEXP (operand, 0); addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0); return register_indirect_p (operand, mode, addr_mode);}static intgo_if_legitimate_address_internal (rtx operand, enum machine_mode mode, int strict){ int addr_mode; if (CONSTANT_ADDRESS_P (operand) && TARGET_M6812) { /* Reject the global variables if they are too wide. This forces a load of their address in a register and generates smaller code. */ if (GET_MODE_SIZE (mode) == 8) return 0; return 1; } addr_mode = m68hc11_addr_mode | (strict ? ADDR_STRICT : 0); if (register_indirect_p (operand, mode, addr_mode)) { return 1; } if (PUSH_POP_ADDRESS_P (operand)) { return 1; } if (symbolic_memory_operand (operand, mode)) { return 1; } return 0;}intm68hc11_go_if_legitimate_address (rtx operand, enum machine_mode mode, int strict){ int result; if (debug_m6811) { printf ("Checking: "); fflush (stdout); debug_rtx (operand); } result = go_if_legitimate_address_internal (operand, mode, strict); if (debug_m6811) { printf (" -> %s\n", result == 0 ? "NO" : "YES"); } if (result == 0) { if (debug_m6811) { printf ("go_if_legitimate%s, ret 0: %d:", (strict ? "_strict" : ""), mode); fflush (stdout); debug_rtx (operand); } } return result;}intm68hc11_legitimize_address (rtx *operand ATTRIBUTE_UNUSED, rtx old_operand ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED){ return 0;}intm68hc11_reload_operands (rtx operands[]){ enum machine_mode mode; if (regs_inited == 0) create_regs_rtx (); mode = GET_MODE (operands[1]); /* Input reload of indirect addressing (MEM (PLUS (REG) (CONST))). */ if (A_REG_P (operands[0]) && memory_reload_operand (operands[1], mode)) { rtx big_offset = XEXP (XEXP (operands[1], 0), 1); rtx base = XEXP (XEXP (operands[1], 0), 0); if (GET_CODE (base) != REG) { rtx tmp = base; base = big_offset; big_offset = tmp; } /* If the offset is out of range, we have to compute the address with a separate add instruction. We try to do with with an 8-bit add on the A register. This is possible only if the lowest part of the offset (i.e., big_offset % 256) is a valid constant offset with respect to the mode. If it's not, we have to generate a 16-bit add on the D register. From: (SET (REG X (MEM (PLUS (REG X) (CONST_INT 1000))))) we generate: [(SET (REG D) (REG X)) (SET (REG X) (REG D))] (SET (REG A) (PLUS (REG A) (CONST_INT 1000 / 256))) [(SET (REG D) (REG X)) (SET (REG X) (REG D))] (SET (REG X) (MEM (PLUS (REG X) (CONST_INT 1000 % 256))) (SET (REG X) (PLUS (REG X) (CONST_INT 1000 / 256 * 256))) (SET (REG X) (MEM (PLUS (REG X) (CONST_INT 1000 % 256)))) */ if (!VALID_CONSTANT_OFFSET_P (big_offset, mode)) { int vh, vl; rtx reg = operands[0]; rtx offset; int val = INTVAL (big_offset); /* We use the 'operands[0]' as a scratch register to compute the address. Make sure 'base' is in that register. */ if (!rtx_equal_p (base, operands[0])) { emit_move_insn (reg, base); } if (val > 0) { vh = val >> 8; vl = val & 0x0FF; } else { vh = (val >> 8) & 0x0FF; vl = val & 0x0FF; } /* Create the lowest part offset that still remains to be added. If it's not a valid offset, do a 16-bit add. */ offset = GEN_INT (vl); if (!VALID_CONSTANT_OFFSET_P (offset, mode)) { emit_insn (gen_rtx_SET (VOIDmode, reg, gen_rtx_PLUS (HImode, reg, big_offset))); offset = const0_rtx; } else { emit_insn (gen_rtx_SET (VOIDmode, reg, gen_rtx_PLUS (HImode, reg, GEN_INT (vh << 8)))); } emit_move_insn (operands[0], gen_rtx_MEM (GET_MODE (operands[1]), gen_rtx_PLUS (Pmode, reg, offset))); return 1; } } /* Use the normal gen_movhi pattern. */ return 0;}voidm68hc11_emit_libcall (const char *name, enum rtx_code code, enum machine_mode dmode, enum machine_mode smode, int noperands, rtx *operands){ rtx ret; rtx insns; rtx libcall; rtx equiv; start_sequence (); libcall = gen_rtx_SYMBOL_REF (Pmode, name); switch (noperands) { case 2: ret = emit_library_call_value (libcall, NULL_RTX, LCT_CONST, dmode, 1, operands[1], smode); equiv = gen_rtx_fmt_e (code, dmode, operands[1]); break; case 3: ret = emit_library_call_value (libcall, NULL_RTX, LCT_CONST, dmode, 2, operands[1], smode, operands[2], smode); equiv = gen_rtx_fmt_ee (code, dmode, operands[1], operands[2]); break; default: abort (); } insns = get_insns (); end_sequence (); emit_libcall_block (insns, operands[0], ret, equiv);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -