📄 ip2k.c
字号:
if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM) return get_frame_size () + 1; if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM) return (CHAIN_FRAMES ? 2 : 0) + (no_saved_pc ? 0 : 2); /* Count all the registers we had to preserve. */ reglimit = CHAIN_FRAMES ? REG_FP : (REG_FP + 2); for (offset = 0,reg = 0; reg < reglimit; ++reg) { if ((regs_ever_live[reg] && ! call_used_regs[reg])) { ++offset; } } if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM) return -offset; if (from == HARD_FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM) /* Add in the stack-local variables. */ return offset + get_frame_size () + 1; if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM) /* Add stack-locals plus saved FP and PC. */ return offset + get_frame_size () + 1 + (CHAIN_FRAMES ? 2 : 0) + (no_saved_pc ? 0 : 2); abort (); /* Unanticipated elimination. */}/* Return nonzero if X (an RTX) is a legitimate memory address on the target machine for a memory operand of mode MODE. */intlegitimate_address_p (mode, x, strict) enum machine_mode mode; rtx x; int strict;{ int off; if (GET_CODE (x) == SUBREG) x = SUBREG_REG (x); switch (GET_CODE (x)) { case REG: /* IP allows indirection without offset - only okay if we don't require access to multiple bytes. */ if (REGNO (x) == REG_IP) return (GET_MODE_SIZE (mode) == 1) ? 'R' : 0; /* We can indirect thru DP or SP register. */ if (strict ? REG_OK_FOR_BASE_STRICT_P (x) : REG_OK_FOR_BASE_NOSTRICT_P (x)) return 'S'; break; case PLUS: /* Offsets from DP or SP are legal in the range 0..127 */ { rtx op1, op2; op1 = XEXP (x, 0); op2 = XEXP (x, 1); if (REG_P (op2) && ! REG_P (op1)) { rtx tmp = op1; op1 = op2; op2 = tmp; } /* Don't let anything but R+I thru.. */ if (! REG_P (op1) || REG_P (op2) || GET_CODE (op2) != CONST_INT) return 0; switch (REGNO (op1)) { case REG_DP: /* only 0..127 displacement */ case REG_SP: off = 2 * GET_MODE_SIZE (mode); if (! off) off = 1; if (INTVAL (op2) < 0 || INTVAL (op2) > (128 - off)) return 0; /* Positive must be small enough that after splitting all pieces are addressed. */ return 'S'; /* Safe displacement. */ case REG_IP: if (GET_MODE_SIZE (mode) <= 1 && INTVAL (op2) == 0) return (GET_MODE_SIZE (mode) == 1) ? 'R' : 0; return 0; case REG_AP: case REG_FP: case REG_VFP: default: if (strict || ! REG_OK_FOR_BASE_NOSTRICT_P (op1)) return 0; /* Allow until reload. */ return 'S'; } } break; case CONST: case SYMBOL_REF: /* We always allow references to things in code space. */ return is_regfile_address (x) ? 0 : 'C'; case LABEL_REF: return 'L'; default: return 0; } return 0;}/* Is ADDR mode dependent? */intip2k_mode_dependent_address (addr) rtx addr;{ switch (GET_CODE (addr)) { case POST_INC: case POST_DEC: case PRE_INC: case PRE_DEC: return 1; case REG: return (REGNO (addr) == REG_IP); /* Can't do IP displaced addresses. */ default: return 0; /* Assume no dependency. */ }}/* Attempts to replace X with a valid memory address for an operand of mode MODE. */rtxlegitimize_address (x, oldx, mode, scratch) rtx x; rtx oldx ATTRIBUTE_UNUSED; rtx scratch; enum machine_mode mode ATTRIBUTE_UNUSED;{ rtx reg; /* You might think that we could split up a symbolic address by adding the HIGH 8 bits and doing a displacement off the dp. But because we only have 7 bits of offset, that doesn't actually help. So only constant displacements are likely to obtain an advantage. */ if (GET_CODE (x) == PLUS && REG_P (XEXP (x, 0)) && GET_CODE (XEXP (x, 1)) == CONST_INT && ! CONST_OK_FOR_LETTER_P (INTVAL (XEXP (x, 1)), 'K')) { int offset = INTVAL (XEXP (x, 1)); reg = scratch ? scratch : gen_reg_rtx (Pmode); emit_insn (gen_rtx_SET (VOIDmode, reg, gen_rtx_PLUS (Pmode, XEXP (x, 0), GEN_INT (offset & 0xffc0)))); x = gen_rtx_PLUS (Pmode, reg, GEN_INT (offset & 0x3f)); } return x; /* We don't have any other tricks. */}/* Determine if X is a 'data' address or a code address. All static data and stack variables reside in data memory. Only code is believed to be in PRAM or FLASH. */intis_regfile_address (x) rtx x;{ while (1) switch (GET_CODE (x)) { case SYMBOL_REF: return ! SYMBOL_REF_FLAG (x); /* Declared as function. */ case CONST: case PLUS: x = XEXP (x, 0); break; case CONST_INT: case REG: case SUBREG: return 1; case LABEL_REF: return 0; default: return 0; } return 0;}/* Output ADDR to FILE as address. */voidprint_operand_address (file, addr) FILE *file; rtx addr;{ switch (GET_CODE (addr)) { case SUBREG: addr = alter_subreg (&addr); /* fall-thru */ case REG: fprintf (file, "(%s)", REGNO (addr) == REG_DP ? "DP" : REGNO (addr) == REG_SP ? "SP" : REGNO (addr) == REG_IP ? "IP" : REGNO (addr) == REG_VFP ? "VFP" /* Should never see this */ : REGNO (addr) == REG_AP ? "AP" /* or this, either. */ : reg_names[REGNO (addr)]); break; case PRE_DEC: case POST_INC: abort (); break; case CONST: addr = XEXP (addr, 0); print_operand_address (file, XEXP (addr, 0)); fprintf (file, "+"); print_operand_address (file, XEXP (addr, 1)); return; case LO_SUM: if (is_regfile_address (XEXP (addr, 1))) fprintf (file, "%%lo8data("); else fprintf (file, "%%lo8insn("); print_operand_address (file, XEXP (addr, 1)); fprintf (file, ")"); print_operand_address (file, XEXP (addr, 0)); break; case PLUS: /* Ought to be stack or dp references. */ if (XEXP (addr, 1) == const0_rtx && GET_CODE (XEXP (addr, 0)) == PLUS) { print_operand_address (file, XEXP (addr, 0)); return; } if (! REG_P (XEXP (addr, 0)) || REGNO (XEXP (addr, 0)) != REG_IP) print_operand_address (file, XEXP (addr, 1)); /* const */ print_operand_address (file, XEXP (addr, 0)); /* (reg) */ break; case HIGH: if (is_regfile_address (XEXP (addr, 0))) fprintf (file, "%%hi8data("); else fprintf (file, "%%hi8insn("); output_addr_const (file, XEXP (addr, 0)); fprintf (file, ")"); break; default: output_addr_const (file, addr); }}/* Output X as assembler operand to file FILE. */ voidprint_operand (file, x, code) FILE *file; rtx x; int code;{ int abcd = 0; unsigned long value; switch (code) { case '<': /* Push */ ip2k_stack_delta++; return; case '>': /* Pop */ ip2k_stack_delta--; return; case 'A': case 'B': case 'C': case 'D': abcd = code - 'A'; break; case 'H': abcd = 0; break; case 'L': abcd = 1; break; case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': abcd = code - 'S'; default: break; } if (ip2k_short_operand (x, GET_MODE (x)) && ip2k_address_uses_reg_p (x, REG_SP)) /* An SP-relative address needs to account for interior stack pushes that reload didn't know about when it calculated the stack offset. */ abcd += ip2k_stack_delta; switch (GET_CODE (x)) { case SUBREG: x = alter_subreg (&x); /* fall-thru */ case REG: fprintf (file, reg_names[true_regnum (x) + abcd]); break; case CONST_INT: switch (code) { case 'x': fprintf (file, "$%x", INTVAL (x) & 0xffff); break; case 'b': fprintf (file, "%d", INTVAL (x)); /* bit selector */ break; case 'e': /* "1 << n" - e.g. "exp" */ fprintf (file, "#%d", 1 << INTVAL (x)); break; case 'A': case 'B': case 'C': case 'D': value = INTVAL (x); value >>= 8 * (3 - abcd); value &= 0xff; fprintf (file, "#%ld", value); break; case 'H': fprintf (file, "#%d", (INTVAL (x) >> 8) & 0xff); break; case 'L': fprintf (file, "#%d", INTVAL (x) & 0xff); break; case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': value = ((unsigned long long)INTVAL (x)) >> (8 * (7 - abcd)) & 0xff; fprintf (file, "#%ld", value); break; default: fprintf (file, "#%d", INTVAL (x)); } break; case SYMBOL_REF: case LABEL_REF: case CODE_LABEL: case CONST: switch (code) { case 'A': case 'B': case 'C': case 'D': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': abort (); /* Probably an error. */ break; case 'H': fprintf (file, "#%s(", is_regfile_address (x) ? "%hi8data" : "%hi8insn"); print_operand_address (file, x); fputc (')', file); break; case 'L': fprintf (file, "#%s(", is_regfile_address (x) ? "%lo8data" : "%lo8insn"); print_operand_address (file, x); fputc (')', file); break; default: print_operand_address (file, x); } break; case MEM: { rtx addr = XEXP (x, 0); if (GET_CODE (addr) == SUBREG) addr = alter_subreg (&x); if (CONSTANT_P (addr) && abcd) { fputc ('(', file); print_operand_address (file, addr); fprintf (file, ")+%d", abcd); } else if (abcd) { switch (GET_CODE (addr)) { case PLUS: abcd += INTVAL (XEXP (addr, 1)); /* Worry about (plus (plus (reg DP) (const_int 10)) (const_int 0)) */ if (GET_CODE (XEXP (addr, 0)) == PLUS) { addr = XEXP (addr, 0); abcd += INTVAL (XEXP (addr, 1)); } fprintf (file, "%d", abcd); print_operand_address (file, XEXP (addr, 0)); break; case REG: default: fprintf (file, "%d", abcd); print_operand_address (file, addr); } } else if (GET_CODE (addr) == REG && (REGNO (addr) == REG_DP || REGNO (addr) == REG_SP)) { fprintf (file, "0"); print_operand_address (file, addr); } else print_operand_address (file, addr); } break; case CONST_DOUBLE: /* Is this an integer or a floating point value? */ if (GET_MODE (x) == VOIDmode) { switch (code) { case 'S': case 'T': case 'U': case 'V': value = CONST_DOUBLE_HIGH (x); value >>= 8 * (3 - abcd); value &= 0xff; fprintf (file, "#%ld", value); break; case 'W': case 'X': case 'Y': case 'Z': value = CONST_DOUBLE_LOW (x); value >>= 8 * (7 - abcd); value &= 0xff; fprintf (file, "#%ld", value); break; } } else { REAL_VALUE_TYPE rv; REAL_VALUE_FROM_CONST_DOUBLE (rv, x); REAL_VALUE_TO_TARGET_SINGLE (rv, value); fprintf (file, "0x%lx", value); } break; default: fatal_insn ("bad operand", x); }}/* Remember the operands for the compare. */const char *ip2k_set_compare (x, y) rtx x; rtx y;{ ip2k_compare_operands[0] = x; ip2k_compare_operands[1] = y; return "";}/* Emit the code for sCOND instructions. */const char *ip2k_gen_sCOND (insn, code, dest) rtx insn ATTRIBUTE_UNUSED;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -