* 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.
This commit is contained in:
Ian Lance Taylor
1994-12-19 22:02:01 +00:00
parent 60937ce7c2
commit 847a01cd4c
2 changed files with 96 additions and 53 deletions

View File

@ -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) 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 * Reduce useless symbols for ELF in an attempt to make smaller

View File

@ -1423,7 +1423,6 @@ macro_build (place, counter, ep, name, fmt, va_alist)
|| r == BFD_RELOC_MIPS_CALL16 || r == BFD_RELOC_MIPS_CALL16
|| (ep->X_op == O_subtract || (ep->X_op == O_subtract
&& now_seg == text_section && now_seg == text_section
&& S_GET_SEGMENT (ep->X_op_symbol) == text_section
&& r == BFD_RELOC_PCREL_LO16)); && r == BFD_RELOC_PCREL_LO16));
continue; continue;
@ -1436,7 +1435,6 @@ macro_build (place, counter, ep, name, fmt, va_alist)
|| r == BFD_RELOC_HI16)) || r == BFD_RELOC_HI16))
|| (ep->X_op == O_subtract || (ep->X_op == O_subtract
&& now_seg == text_section && now_seg == text_section
&& S_GET_SEGMENT (ep->X_op_symbol) == text_section
&& r == BFD_RELOC_PCREL_HI16_S))); && r == BFD_RELOC_PCREL_HI16_S)));
if (ep->X_op == O_constant) if (ep->X_op == O_constant)
{ {
@ -1592,47 +1590,78 @@ load_register (counter, reg, ep)
int reg; int reg;
expressionS *ep; expressionS *ep;
{ {
int shift;
expressionS hi32, lo32;
if (ep->X_op != O_big)
{
assert (ep->X_op == O_constant); assert (ep->X_op == O_constant);
if (ep->X_add_number >= -0x8000 && ep->X_add_number < 0x8000) if (ep->X_add_number >= -0x8000 && ep->X_add_number < 0x8000)
{ {
/* No need to ever use daddiu here, since we are adding in /* We can handle 16 bit signed values with an addiu to
register $zero. */ $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, macro_build ((char *) NULL, counter, ep, "addiu", "t,r,j", reg, 0,
(int) BFD_RELOC_LO16); (int) BFD_RELOC_LO16);
return;
} }
else if (ep->X_add_number >= 0 && ep->X_add_number < 0x10000) 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, macro_build ((char *) NULL, counter, ep, "ori", "t,r,i", reg, 0,
(int) BFD_RELOC_LO16); (int) BFD_RELOC_LO16);
return;
}
else if ((ep->X_add_number &~ (offsetT) 0x7fffffff) == 0 else if ((ep->X_add_number &~ (offsetT) 0x7fffffff) == 0
|| ((ep->X_add_number &~ (offsetT) 0x7fffffff) || ((ep->X_add_number &~ (offsetT) 0x7fffffff)
== ~ (offsetT) 0x7fffffff)) == ~ (offsetT) 0x7fffffff))
{ {
/* 32 bit values require an lui. */
macro_build ((char *) NULL, counter, ep, "lui", "t,u", reg, macro_build ((char *) NULL, counter, ep, "lui", "t,u", reg,
(int) BFD_RELOC_HI16); (int) BFD_RELOC_HI16);
if ((ep->X_add_number & 0xffff) != 0) if ((ep->X_add_number & 0xffff) != 0)
macro_build ((char *) NULL, counter, ep, "ori", "t,r,i", reg, reg, macro_build ((char *) NULL, counter, ep, "ori", "t,r,i", reg, reg,
(int) BFD_RELOC_LO16); (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"); as_bad ("Number larger than 32 bits");
macro_build ((char *) NULL, counter, ep, "addiu", "t,r,j", reg, 0, macro_build ((char *) NULL, counter, ep, "addiu", "t,r,j", reg, 0,
(int) BFD_RELOC_LO16); (int) BFD_RELOC_LO16);
return;
} }
else
{
int shift;
expressionS hi32, lo32;
if (ep->X_op != O_big)
{
hi32 = *ep; hi32 = *ep;
shift = 32; shift = 32;
hi32.X_add_number >>= shift; hi32.X_add_number >>= shift;
hi32.X_add_number &= 0xffffffff; hi32.X_add_number &= 0xffffffff;
if ((hi32.X_add_number & 0x80000000) != 0) if ((hi32.X_add_number & 0x80000000) != 0)
hi32.X_add_number |= ~ (offsetT) 0xffffffff; hi32.X_add_number |= ~ (offsetT) 0xffffffff;
load_register (counter, reg, &hi32);
lo32 = *ep; lo32 = *ep;
lo32.X_add_number &= 0xffffffff; lo32.X_add_number &= 0xffffffff;
}
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);
}
load_register (counter, reg, &hi32);
if ((lo32.X_add_number & 0xffff0000) == 0) if ((lo32.X_add_number & 0xffff0000) == 0)
macro_build ((char *) NULL, counter, NULL, "dsll32", "d,w,<", reg, macro_build ((char *) NULL, counter, NULL, "dsll32", "d,w,<", reg,
reg, 0); reg, 0);
@ -1652,7 +1681,6 @@ load_register (counter, reg, ep)
if ((lo32.X_add_number & 0xffff) != 0) if ((lo32.X_add_number & 0xffff) != 0)
macro_build ((char *) NULL, counter, &lo32, "ori", "t,r,i", reg, reg, macro_build ((char *) NULL, counter, &lo32, "ori", "t,r,i", reg, reg,
(int) BFD_RELOC_LO16); (int) BFD_RELOC_LO16);
}
} }
/* Load an address into a register. */ /* Load an address into a register. */
@ -1695,7 +1723,7 @@ load_address (counter, reg, ep)
mips_isa < 3 ? "addiu" : "daddiu", mips_isa < 3 ? "addiu" : "daddiu",
"t,r,j", reg, GP, (int) BFD_RELOC_MIPS_GPREL); "t,r,j", reg, GP, (int) BFD_RELOC_MIPS_GPREL);
p = frag_var (rs_machine_dependent, 8, 0, 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); ep->X_add_symbol, (long) 0, (char *) NULL);
} }
macro_build_lui (p, counter, ep, reg); macro_build_lui (p, counter, ep, reg);
@ -2441,7 +2469,12 @@ macro (ip)
if (mips_pic == EMBEDDED_PIC if (mips_pic == EMBEDDED_PIC
&& offset_expr.X_op == O_subtract && offset_expr.X_op == O_subtract
&& now_seg == text_section && 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 && breg == 0
&& offset_expr.X_add_number == 0) && offset_expr.X_add_number == 0)
{ {
@ -4494,6 +4527,7 @@ mips_ip (str, ip)
case 'I': case 'I':
my_getExpression (&imm_expr, s); my_getExpression (&imm_expr, s);
if (imm_expr.X_op != O_big)
check_absolute_expr (ip, &imm_expr); check_absolute_expr (ip, &imm_expr);
s = expr_end; s = expr_end;
continue; continue;
@ -4657,11 +4691,12 @@ mips_ip (str, ip)
imm_reloc = BFD_RELOC_HI16; imm_reloc = BFD_RELOC_HI16;
} }
} }
else else if (imm_expr.X_op != O_big)
check_absolute_expr (ip, &imm_expr); check_absolute_expr (ip, &imm_expr);
if (*args == 'i') 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) || imm_expr.X_add_number >= 0x10000)
{ {
if (insn + 1 < &mips_opcodes[NUMOPCODES] && if (insn + 1 < &mips_opcodes[NUMOPCODES] &&
@ -4690,8 +4725,9 @@ mips_ip (str, ip)
max = 0x8000; max = 0x8000;
else else
max = 0x10000; max = 0x10000;
if (imm_expr.X_add_number < -0x8000 || if (imm_expr.X_op == O_big
imm_expr.X_add_number >= max) || imm_expr.X_add_number < -0x8000
|| imm_expr.X_add_number >= max)
{ {
if (more) if (more)
break; break;