aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1994-12-19 22:02:01 +0000
committerIan Lance Taylor <ian@airs.com>1994-12-19 22:02:01 +0000
commit847a01cd4cd73749699db2fc7b8f49d3bb619076 (patch)
tree1f0348ab1eb14c14010f4b5d1cfefacaf47d6313
parent60937ce7c2522765fc431338adf2d0aefb8e7eab (diff)
downloadgdb-847a01cd4cd73749699db2fc7b8f49d3bb619076.zip
gdb-847a01cd4cd73749699db2fc7b8f49d3bb619076.tar.gz
gdb-847a01cd4cd73749699db2fc7b8f49d3bb619076.tar.bz2
* config/tc-mips.c (load_register): Rewrite to handle O_big 64 bit
constants. (mips_ip): Accept O_big constants in case 'I'. Change case 'i'/'j' to treat an O_big constant as an out of range value.
-rw-r--r--gas/ChangeLog7
-rw-r--r--gas/config/tc-mips.c140
2 files changed, 95 insertions, 52 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index eedb5bb..7502cd6 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,10 @@
+Mon Dec 19 16:53:36 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * config/tc-mips.c (load_register): Rewrite to handle O_big 64 bit
+ constants.
+ (mips_ip): Accept O_big constants in case 'I'. Change case
+ 'i'/'j' to treat an O_big constant as an out of range value.
+
Mon Dec 19 14:15:07 1994 Jeff Law (law@snake.cs.utah.edu)
* Reduce useless symbols for ELF in an attempt to make smaller
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index c3a7565..ca7024b 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -1423,7 +1423,6 @@ macro_build (place, counter, ep, name, fmt, va_alist)
|| r == BFD_RELOC_MIPS_CALL16
|| (ep->X_op == O_subtract
&& now_seg == text_section
- && S_GET_SEGMENT (ep->X_op_symbol) == text_section
&& r == BFD_RELOC_PCREL_LO16));
continue;
@@ -1436,7 +1435,6 @@ macro_build (place, counter, ep, name, fmt, va_alist)
|| r == BFD_RELOC_HI16))
|| (ep->X_op == O_subtract
&& now_seg == text_section
- && S_GET_SEGMENT (ep->X_op_symbol) == text_section
&& r == BFD_RELOC_PCREL_HI16_S)));
if (ep->X_op == O_constant)
{
@@ -1592,67 +1590,97 @@ load_register (counter, reg, ep)
int reg;
expressionS *ep;
{
- assert (ep->X_op == O_constant);
- if (ep->X_add_number >= -0x8000 && ep->X_add_number < 0x8000)
- {
- /* No need to ever use daddiu here, since we are adding in
- register $zero. */
- macro_build ((char *) NULL, counter, ep, "addiu", "t,r,j", reg, 0,
- (int) BFD_RELOC_LO16);
- }
- else if (ep->X_add_number >= 0 && ep->X_add_number < 0x10000)
- macro_build ((char *) NULL, counter, ep, "ori", "t,r,i", reg, 0,
- (int) BFD_RELOC_LO16);
- else if ((ep->X_add_number &~ (offsetT) 0x7fffffff) == 0
- || ((ep->X_add_number &~ (offsetT) 0x7fffffff)
- == ~ (offsetT) 0x7fffffff))
+ int shift;
+ expressionS hi32, lo32;
+
+ if (ep->X_op != O_big)
{
- macro_build ((char *) NULL, counter, ep, "lui", "t,u", reg,
- (int) BFD_RELOC_HI16);
- if ((ep->X_add_number & 0xffff) != 0)
- macro_build ((char *) NULL, counter, ep, "ori", "t,r,i", reg, reg,
- (int) BFD_RELOC_LO16);
+ assert (ep->X_op == O_constant);
+ if (ep->X_add_number >= -0x8000 && ep->X_add_number < 0x8000)
+ {
+ /* We can handle 16 bit signed values with an addiu to
+ $zero. No need to ever use daddiu here, since $zero and
+ the result are always correct in 32 bit mode. */
+ macro_build ((char *) NULL, counter, ep, "addiu", "t,r,j", reg, 0,
+ (int) BFD_RELOC_LO16);
+ return;
+ }
+ else if (ep->X_add_number >= 0 && ep->X_add_number < 0x10000)
+ {
+ /* We can handle 16 bit unsigned values with an ori to
+ $zero. */
+ macro_build ((char *) NULL, counter, ep, "ori", "t,r,i", reg, 0,
+ (int) BFD_RELOC_LO16);
+ return;
+ }
+ else if ((ep->X_add_number &~ (offsetT) 0x7fffffff) == 0
+ || ((ep->X_add_number &~ (offsetT) 0x7fffffff)
+ == ~ (offsetT) 0x7fffffff))
+ {
+ /* 32 bit values require an lui. */
+ macro_build ((char *) NULL, counter, ep, "lui", "t,u", reg,
+ (int) BFD_RELOC_HI16);
+ if ((ep->X_add_number & 0xffff) != 0)
+ macro_build ((char *) NULL, counter, ep, "ori", "t,r,i", reg, reg,
+ (int) BFD_RELOC_LO16);
+ return;
+ }
}
- else if (mips_isa < 3)
+
+ /* The value is larger than 32 bits. */
+
+ if (mips_isa < 3)
{
as_bad ("Number larger than 32 bits");
macro_build ((char *) NULL, counter, ep, "addiu", "t,r,j", reg, 0,
(int) BFD_RELOC_LO16);
+ return;
}
- else
- {
- int shift;
- expressionS hi32, lo32;
+ if (ep->X_op != O_big)
+ {
hi32 = *ep;
shift = 32;
hi32.X_add_number >>= shift;
hi32.X_add_number &= 0xffffffff;
if ((hi32.X_add_number & 0x80000000) != 0)
hi32.X_add_number |= ~ (offsetT) 0xffffffff;
- load_register (counter, reg, &hi32);
lo32 = *ep;
lo32.X_add_number &= 0xffffffff;
- if ((lo32.X_add_number & 0xffff0000) == 0)
- macro_build ((char *) NULL, counter, NULL, "dsll32", "d,w,<", reg,
- reg, 0);
- else
- {
- expressionS mid16;
+ }
+ else
+ {
+ assert (ep->X_add_number > 2);
+ if (ep->X_add_number == 3)
+ generic_bignum[3] = 0;
+ else if (ep->X_add_number > 4)
+ as_bad ("Number larger than 64 bits");
+ lo32.X_op = O_constant;
+ lo32.X_add_number = generic_bignum[0] + (generic_bignum[1] << 16);
+ hi32.X_op = O_constant;
+ hi32.X_add_number = generic_bignum[2] + (generic_bignum[3] << 16);
+ }
- macro_build ((char *) NULL, counter, NULL, "dsll", "d,w,<", reg,
- reg, 16);
- mid16 = lo32;
- mid16.X_add_number >>= 16;
- macro_build ((char *) NULL, counter, &mid16, "ori", "t,r,i", reg,
- reg, (int) BFD_RELOC_LO16);
- macro_build ((char *) NULL, counter, NULL, "dsll", "d,w,<", reg,
- reg, 16);
- }
- if ((lo32.X_add_number & 0xffff) != 0)
- macro_build ((char *) NULL, counter, &lo32, "ori", "t,r,i", reg, reg,
- (int) BFD_RELOC_LO16);
+ load_register (counter, reg, &hi32);
+ if ((lo32.X_add_number & 0xffff0000) == 0)
+ macro_build ((char *) NULL, counter, NULL, "dsll32", "d,w,<", reg,
+ reg, 0);
+ else
+ {
+ expressionS mid16;
+
+ macro_build ((char *) NULL, counter, NULL, "dsll", "d,w,<", reg,
+ reg, 16);
+ mid16 = lo32;
+ mid16.X_add_number >>= 16;
+ macro_build ((char *) NULL, counter, &mid16, "ori", "t,r,i", reg,
+ reg, (int) BFD_RELOC_LO16);
+ macro_build ((char *) NULL, counter, NULL, "dsll", "d,w,<", reg,
+ reg, 16);
}
+ if ((lo32.X_add_number & 0xffff) != 0)
+ macro_build ((char *) NULL, counter, &lo32, "ori", "t,r,i", reg, reg,
+ (int) BFD_RELOC_LO16);
}
/* Load an address into a register. */
@@ -1695,7 +1723,7 @@ load_address (counter, reg, ep)
mips_isa < 3 ? "addiu" : "daddiu",
"t,r,j", reg, GP, (int) BFD_RELOC_MIPS_GPREL);
p = frag_var (rs_machine_dependent, 8, 0,
- RELAX_ENCODE (4, 8, -4, 0, 0, mips_warn_about_macros),
+ RELAX_ENCODE (4, 8, 0, 4, 0, mips_warn_about_macros),
ep->X_add_symbol, (long) 0, (char *) NULL);
}
macro_build_lui (p, counter, ep, reg);
@@ -2441,7 +2469,12 @@ macro (ip)
if (mips_pic == EMBEDDED_PIC
&& offset_expr.X_op == O_subtract
&& now_seg == text_section
- && S_GET_SEGMENT (offset_expr.X_op_symbol) == text_section
+ && (offset_expr.X_op_symbol->sy_value.X_op == O_constant
+ ? S_GET_SEGMENT (offset_expr.X_op_symbol) == text_section
+ : (offset_expr.X_op_symbol->sy_value.X_op == O_symbol
+ && (S_GET_SEGMENT (offset_expr.X_op_symbol
+ ->sy_value.X_add_symbol)
+ == text_section)))
&& breg == 0
&& offset_expr.X_add_number == 0)
{
@@ -4494,7 +4527,8 @@ mips_ip (str, ip)
case 'I':
my_getExpression (&imm_expr, s);
- check_absolute_expr (ip, &imm_expr);
+ if (imm_expr.X_op != O_big)
+ check_absolute_expr (ip, &imm_expr);
s = expr_end;
continue;
@@ -4657,11 +4691,12 @@ mips_ip (str, ip)
imm_reloc = BFD_RELOC_HI16;
}
}
- else
+ else if (imm_expr.X_op != O_big)
check_absolute_expr (ip, &imm_expr);
if (*args == 'i')
{
- if (imm_expr.X_add_number < 0
+ if (imm_expr.X_op == O_big
+ || imm_expr.X_add_number < 0
|| imm_expr.X_add_number >= 0x10000)
{
if (insn + 1 < &mips_opcodes[NUMOPCODES] &&
@@ -4690,8 +4725,9 @@ mips_ip (str, ip)
max = 0x8000;
else
max = 0x10000;
- if (imm_expr.X_add_number < -0x8000 ||
- imm_expr.X_add_number >= max)
+ if (imm_expr.X_op == O_big
+ || imm_expr.X_add_number < -0x8000
+ || imm_expr.X_add_number >= max)
{
if (more)
break;