diff options
-rw-r--r-- | gas/ChangeLog | 12 | ||||
-rw-r--r-- | gas/config/tc-mips.c | 67 |
2 files changed, 49 insertions, 30 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index e4183dd..328f139 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,15 @@ +2003-09-14 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de> + + * config/tc-mips.c (HAVE_64BIT_ADDRESS_CONSTANTS): Remove. + (macro_build_ldst_constoffset): Sign-extend 32-bit constants. Change + the function prototype. + (load_register): Likewise. Simplify the checks for sign-extended + constants. + (macro): Likewise. Fix code generation for 64-bit address constants + outside the 32-bit compatibility space. Adjust + macro_build_ldst_constoffset calls. + (s_cprestore): Adjust macro_build_ldst_constoffset call. + 2003-09-11 Bob Wilson <bob.wilson@acm.org> * config/tc-xtensa.c (insn_labels, free_insn_labels, saved_insn_labels, diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index e2e3f4a..8c7c69e 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -302,8 +302,6 @@ static int mips_32bitmode = 0; && mips_pic != EMBEDDED_PIC)) #define HAVE_64BIT_ADDRESSES (! HAVE_32BIT_ADDRESSES) -#define HAVE_64BIT_ADDRESS_CONSTANTS (HAVE_64BIT_ADDRESSES \ - || HAVE_64BIT_GPRS) /* Addresses are loaded in different ways, depending on the address size in use. The n32 ABI Documentation also mandates the use of additions @@ -3225,10 +3223,15 @@ macro_build_lui (char *place, int *counter, expressionS *ep, int regnum) using AT if necessary. */ static void macro_build_ldst_constoffset (char *place, int *counter, expressionS *ep, - const char *op, int treg, int breg) + const char *op, int treg, int breg, int dbl) { assert (ep->X_op == O_constant); + /* Sign-extending 32-bit constants makes their handling easier. */ + if (! dbl) + ep->X_add_number = (((ep->X_add_number & 0xffffffff) ^ 0x80000000) + - 0x80000000); + /* Right now, this routine can only handle signed 32-bit contants. */ if (! IS_SEXT_32BIT_NUM(ep->X_add_number)) as_warn (_("operand overflow")); @@ -3381,12 +3384,13 @@ load_register (int *counter, int reg, expressionS *ep, int dbl) if (ep->X_op != O_big) { assert (ep->X_op == O_constant); - if (ep->X_add_number < 0x8000 - && (ep->X_add_number >= 0 - || (ep->X_add_number >= -0x8000 - && (! dbl - || ! ep->X_unsigned - || sizeof (ep->X_add_number) > 4)))) + + /* Sign-extending 32-bit constants makes their handling easier. */ + if (! dbl) + ep->X_add_number = (((ep->X_add_number & 0xffffffff) ^ 0x80000000) + - 0x80000000); + + if (IS_SEXT_16BIT_NUM (ep->X_add_number)) { /* We can handle 16 bit signed values with an addiu to $zero. No need to ever use daddiu here, since $zero and @@ -3403,17 +3407,7 @@ load_register (int *counter, int reg, expressionS *ep, int dbl) BFD_RELOC_LO16); return; } - else if ((IS_SEXT_32BIT_NUM (ep->X_add_number) - && (! dbl - || ! ep->X_unsigned - || sizeof (ep->X_add_number) > 4 - || (ep->X_add_number & 0x80000000) == 0)) - || ((HAVE_32BIT_GPRS || ! dbl) - && (ep->X_add_number &~ (offsetT) 0xffffffff) == 0) - || (HAVE_32BIT_GPRS - && ! dbl - && ((ep->X_add_number &~ (offsetT) 0xffffffff) - == ~ (offsetT) 0xffffffff))) + else if ((IS_SEXT_32BIT_NUM (ep->X_add_number))) { /* 32 bit values require an lui. */ macro_build (NULL, counter, ep, "lui", "t,u", reg, BFD_RELOC_HI16); @@ -5450,7 +5444,8 @@ macro (struct mips_cl_insn *ip) macro_build_ldst_constoffset (NULL, &icnt, &expr1, ADDRESS_LOAD_INSN, mips_gp_register, - mips_frame_reg); + mips_frame_reg, + HAVE_64BIT_ADDRESSES); } } } @@ -5601,7 +5596,8 @@ macro (struct mips_cl_insn *ip) macro_build_ldst_constoffset (NULL, &icnt, &expr1, ADDRESS_LOAD_INSN, mips_gp_register, - mips_frame_reg); + mips_frame_reg, + HAVE_64BIT_ADDRESSES); } } } @@ -5791,6 +5787,15 @@ macro (struct mips_cl_insn *ip) else fmt = "t,o(b)"; + /* Sign-extending 32-bit constants makes their handling easier. + The HAVE_64BIT_GPRS... part is due to the linux kernel hack + described below. */ + if ((! HAVE_64BIT_ADDRESSES + && (! HAVE_64BIT_GPRS && offset_expr.X_op == O_constant)) + && (offset_expr.X_op == O_constant)) + offset_expr.X_add_number = (((offset_expr.X_add_number & 0xffffffff) + ^ 0x80000000) - 0x80000000); + /* For embedded PIC, we allow loads where the offset is calculated by subtracting a symbol in the current segment from an unknown symbol, relative to a base register, e.g.: @@ -5923,10 +5928,12 @@ macro (struct mips_cl_insn *ip) end up converting the binary to ELF32 for a number of platforms whose boot loaders don't support ELF64 binaries. */ - if ((offset_expr.X_op != O_constant && HAVE_64BIT_ADDRESSES) - || (offset_expr.X_op == O_constant - && !IS_SEXT_32BIT_NUM (offset_expr.X_add_number + 0x8000) - && HAVE_64BIT_ADDRESS_CONSTANTS)) + if ((HAVE_64BIT_ADDRESSES + && ! (offset_expr.X_op == O_constant + && IS_SEXT_32BIT_NUM (offset_expr.X_add_number + 0x8000))) + || (HAVE_64BIT_GPRS + && offset_expr.X_op == O_constant + && ! IS_SEXT_32BIT_NUM (offset_expr.X_add_number + 0x8000))) { p = NULL; @@ -5973,9 +5980,9 @@ macro (struct mips_cl_insn *ip) return; } - else if (offset_expr.X_op == O_constant - && !HAVE_64BIT_ADDRESS_CONSTANTS - && !IS_SEXT_32BIT_NUM (offset_expr.X_add_number)) + + if (offset_expr.X_op == O_constant + && ! IS_SEXT_32BIT_NUM (offset_expr.X_add_number)) as_bad (_("load/store address overflow (max 32 bits)")); if (breg == 0) @@ -12302,7 +12309,7 @@ s_cprestore (int ignore ATTRIBUTE_UNUSED) ex.X_add_number = mips_cprestore_offset; macro_build_ldst_constoffset (NULL, &icnt, &ex, ADDRESS_STORE_INSN, - mips_gp_register, SP); + mips_gp_register, SP, HAVE_64BIT_ADDRESSES); demand_empty_rest_of_line (); } |