* config/tc-alpha.c (alpha_ip): Delay calls to emit_add64 until after any
remaining operands are also known to match.
This commit is contained in:
parent
2a6978af8d
commit
71f9b3c097
2 changed files with 77 additions and 55 deletions
|
@ -2,6 +2,9 @@ Fri Jan 6 16:59:41 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
|
|||
|
||||
* gasp.c: Include string.h. Put config.h before other includes.
|
||||
|
||||
* config/tc-alpha.c (alpha_ip): Delay calls to emit_add64 until
|
||||
after any remaining operands are also known to match.
|
||||
|
||||
Fri Dec 30 18:21:41 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
|
||||
|
||||
* listing.c (list_symbol_table): Build a format string based on
|
||||
|
|
|
@ -130,7 +130,7 @@ static void emit_ldah_num PARAMS ((int, bfd_vma, int));
|
|||
static void emit_addq_r PARAMS ((int, int, int));
|
||||
static void emit_lda_n PARAMS ((int, bfd_vma, int));
|
||||
static void emit_add64 PARAMS ((int, int, bfd_vma));
|
||||
static int in_range PARAMS ((bfd_vma, int, int));
|
||||
static int in_range_signed PARAMS ((bfd_vma, int));
|
||||
|
||||
const pseudo_typeS md_pseudo_table[] =
|
||||
{
|
||||
|
@ -430,9 +430,9 @@ s_base ()
|
|||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
static int in_range (val, nbits, unsignedness)
|
||||
static int in_range_signed (val, nbits)
|
||||
bfd_vma val;
|
||||
int nbits, unsignedness;
|
||||
int nbits;
|
||||
{
|
||||
/* Look at top bit of value that would be stored, figure out how it
|
||||
would be extended by the hardware, and see if that matches the
|
||||
|
@ -445,27 +445,40 @@ static int in_range (val, nbits, unsignedness)
|
|||
stored_value = val & mask;
|
||||
top_bit = stored_value & (one << nbits - 1);
|
||||
missing_bits = val & ~mask;
|
||||
if (unsignedness)
|
||||
/* will sign-extend */
|
||||
if (top_bit)
|
||||
{
|
||||
return missing_bits == 0;
|
||||
/* all remaining bits beyond mask should be one */
|
||||
missing_bits |= mask;
|
||||
return missing_bits + 1 == 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* will sign-extend */
|
||||
if (top_bit)
|
||||
{
|
||||
/* all remaining bits beyond mask should be one */
|
||||
missing_bits |= mask;
|
||||
return missing_bits + 1 == 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* all other bits should be zero */
|
||||
return missing_bits == 0;
|
||||
}
|
||||
/* all other bits should be zero */
|
||||
return missing_bits == 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int in_range_unsigned (val, nbits)
|
||||
bfd_vma val;
|
||||
int nbits;
|
||||
{
|
||||
/* Look at top bit of value that would be stored, figure out how it
|
||||
would be extended by the hardware, and see if that matches the
|
||||
original supplied value. */
|
||||
bfd_vma mask;
|
||||
bfd_vma one = 1;
|
||||
bfd_vma top_bit, stored_value, missing_bits;
|
||||
|
||||
mask = (one << nbits) - 1;
|
||||
stored_value = val & mask;
|
||||
top_bit = stored_value & (one << nbits - 1);
|
||||
missing_bits = val & ~mask;
|
||||
return missing_bits == 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
s_gprel32 ()
|
||||
{
|
||||
|
@ -509,8 +522,6 @@ create_literal_section (secp, name)
|
|||
| SEC_DATA);
|
||||
}
|
||||
|
||||
#define create_lita_section() create_literal_section (&lita_sec, ".lita")
|
||||
|
||||
static valueT
|
||||
get_lit8_offset (val)
|
||||
bfd_vma val;
|
||||
|
@ -648,7 +659,7 @@ md_begin ()
|
|||
|
||||
/* So .sbss will get used for tiny objects. */
|
||||
bfd_set_gp_size (stdoutput, 8);
|
||||
create_lita_section ();
|
||||
create_literal_section (&lita_sec, ".lita");
|
||||
/* For handling the GP, create a symbol that won't be output in the
|
||||
symbol table. We'll edit it out of relocs later. */
|
||||
gp = symbol_create ("<GP value>", lita_sec, 0x8000, &zero_address_frag);
|
||||
|
@ -1136,14 +1147,14 @@ emit_add64 (in, out, num)
|
|||
{
|
||||
bfd_signed_vma snum = num;
|
||||
|
||||
if (in_range (num, 16, 0))
|
||||
if (in_range_signed (num, 16))
|
||||
{
|
||||
emit_lda_n (out, num, in);
|
||||
return;
|
||||
}
|
||||
if ((num & 0xffff) == 0
|
||||
&& in == ZERO
|
||||
&& in_range (snum >> 16, 16, 0))
|
||||
&& in_range_signed (snum >> 16, 16))
|
||||
{
|
||||
emit_ldah_num (out, snum >> 16, in);
|
||||
return;
|
||||
|
@ -1151,21 +1162,21 @@ emit_add64 (in, out, num)
|
|||
/* I'm not sure this one is getting invoked when it could. */
|
||||
if ((num & 1) == 0 && in == ZERO)
|
||||
{
|
||||
if (in_range (snum >> 1, 16, 0))
|
||||
if (in_range_signed (snum >> 1, 16))
|
||||
{
|
||||
emit_lda_n (out, snum >> 1, in);
|
||||
emit_addq_r (out, out, out);
|
||||
return;
|
||||
}
|
||||
else if (num & 0x1fffe == 0
|
||||
&& in_range (snum >> 17, 16, 0))
|
||||
&& in_range_signed (snum >> 17, 16))
|
||||
{
|
||||
emit_ldah_num (out, snum >> 17, in);
|
||||
emit_addq_r (out, out, out);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (in_range (num, 32, 0))
|
||||
if (in_range_signed (num, 32))
|
||||
{
|
||||
bfd_vma lo = num & 0xffff;
|
||||
if (lo & 0x8000)
|
||||
|
@ -1202,12 +1213,6 @@ emit_add64 (in, out, num)
|
|||
}
|
||||
}
|
||||
|
||||
/* Note that for now, this function is called recursively (by way of
|
||||
calling md_assemble again). Some of the macros defined as part of
|
||||
the assembly language are currently rewritten as sequences of
|
||||
strings to be assembled. See, for example, the handling of "divq".
|
||||
|
||||
For efficiency, this should be fixed someday. */
|
||||
static int
|
||||
alpha_ip (str, insns)
|
||||
char *str;
|
||||
|
@ -1223,6 +1228,8 @@ alpha_ip (str, insns)
|
|||
unsigned int mask;
|
||||
int match = 0, num_gen = 1;
|
||||
int comma = 0;
|
||||
int do_add64, add64_in, add64_out;
|
||||
bfd_vma add64_addend;
|
||||
|
||||
for (s = str;
|
||||
islower (*s) || *s == '_' || *s == '/' || *s == '4' || *s == '8';
|
||||
|
@ -1248,7 +1255,7 @@ alpha_ip (str, insns)
|
|||
}
|
||||
if ((pattern = (struct alpha_opcode *) hash_find (op_hash, str)) == NULL)
|
||||
{
|
||||
as_warn ("Unknown opcode: `%s'", str);
|
||||
as_bad ("Unknown opcode: `%s'", str);
|
||||
return -1;
|
||||
}
|
||||
if (comma)
|
||||
|
@ -1257,6 +1264,7 @@ alpha_ip (str, insns)
|
|||
argsStart = s;
|
||||
for (;;)
|
||||
{
|
||||
do_add64 = 0;
|
||||
opcode = pattern->match;
|
||||
num_gen = 1;
|
||||
for (i = 0; i < MAX_INSNS; i++)
|
||||
|
@ -1465,24 +1473,14 @@ alpha_ip (str, insns)
|
|||
insns[0].reloc[0].code = BFD_RELOC_26;
|
||||
goto immediate;
|
||||
|
||||
#if 0
|
||||
case 't': /* 12 bit 0...11 */
|
||||
insns[0].reloc = RELOC_0_12;
|
||||
case 't': /* 12 bit displacement, for PALcode */
|
||||
insns[0].reloc[0].code = BFD_RELOC_12_PCREL;
|
||||
goto immediate;
|
||||
|
||||
case '8': /* 8 bit 0...7 */
|
||||
insns[0].reloc = RELOC_0_8;
|
||||
insns[0].reloc[0].code = BFD_RELOC_8;
|
||||
goto immediate;
|
||||
|
||||
case 'I': /* 26 bit immediate */
|
||||
insns[0].reloc = RELOC_0_25;
|
||||
#else
|
||||
case 't':
|
||||
case '8':
|
||||
abort ();
|
||||
#endif
|
||||
/*FALLTHROUGH*/
|
||||
|
||||
immediate:
|
||||
if (*s == ' ')
|
||||
s++;
|
||||
|
@ -1523,8 +1521,10 @@ alpha_ip (str, insns)
|
|||
else if (at_ok && macro_ok)
|
||||
{
|
||||
/* Constant value supplied, but it's too large. */
|
||||
emit_add64 (ZERO, AT,
|
||||
insns[0].reloc[0].exp.X_add_number);
|
||||
do_add64 = 1;
|
||||
add64_in = ZERO;
|
||||
add64_out = AT;
|
||||
add64_addend = insns[0].reloc[0].exp.X_add_number;
|
||||
opcode &= ~ 0x1000;
|
||||
opcode |= (AT << SB);
|
||||
insns[0].reloc[0].code = BFD_RELOC_NONE;
|
||||
|
@ -1534,19 +1534,22 @@ alpha_ip (str, insns)
|
|||
}
|
||||
else if (insns[0].reloc[0].code == BFD_RELOC_16
|
||||
&& insns[0].reloc[0].exp.X_op == O_constant
|
||||
&& !in_range (insns[0].reloc[0].exp.X_add_number,
|
||||
16, 0))
|
||||
&& !in_range_signed (insns[0].reloc[0].exp.X_add_number,
|
||||
16))
|
||||
{
|
||||
bfd_vma val = insns[0].reloc[0].exp.X_add_number;
|
||||
if (OPCODE (opcode) == 0x08)
|
||||
{
|
||||
emit_add64 (ZERO, AT, val);
|
||||
do_add64 = 1;
|
||||
add64_in = ZERO;
|
||||
add64_out = AT;
|
||||
add64_addend = val;
|
||||
opcode &= ~0x1000;
|
||||
opcode |= (AT << SB);
|
||||
insns[0].reloc[0].code = BFD_RELOC_NONE;
|
||||
}
|
||||
else if (OPCODE (opcode) == 0x09
|
||||
&& in_range (val >> 16, 16, 0))
|
||||
&& in_range_signed (val >> 16, 16))
|
||||
{
|
||||
/* ldah with high operand - convert to low */
|
||||
insns[0].reloc[0].exp.X_add_number >>= 16;
|
||||
|
@ -1667,7 +1670,10 @@ alpha_ip (str, insns)
|
|||
top = val - low;
|
||||
if (top)
|
||||
{
|
||||
emit_add64 (ZERO, AT, top);
|
||||
do_add64 = 1;
|
||||
add64_in = ZERO;
|
||||
add64_out = AT;
|
||||
add64_addend = top;
|
||||
opcode |= AT << SB;
|
||||
}
|
||||
else
|
||||
|
@ -1821,7 +1827,7 @@ alpha_ip (str, insns)
|
|||
note_gpreg (PV);
|
||||
|
||||
jsr = &insns[num_gen++];
|
||||
jsr->opcode = (0x68004000 /* jsr */
|
||||
jsr->opcode = (pattern->match
|
||||
| (mask << SA)
|
||||
| (PV << SB)
|
||||
| 0);
|
||||
|
@ -2136,6 +2142,11 @@ alpha_ip (str, insns)
|
|||
break;
|
||||
}
|
||||
|
||||
if (do_add64)
|
||||
{
|
||||
emit_add64 (add64_in, add64_out, add64_addend);
|
||||
}
|
||||
|
||||
insns[0].opcode = opcode;
|
||||
return num_gen;
|
||||
}
|
||||
|
@ -2361,7 +2372,7 @@ s_alpha_set (x)
|
|||
else if (!strcmp ("volatile", s))
|
||||
/* ignore */ ;
|
||||
else
|
||||
as_warn ("Tried to set unrecognized symbol: %s", name);
|
||||
as_warn ("Tried to .set unrecognized mode `%s'", name);
|
||||
*input_line_pointer = ch;
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
@ -2531,6 +2542,13 @@ md_apply_fix (fixP, valueP)
|
|||
*p |= (value & 0x1f);
|
||||
goto done;
|
||||
|
||||
case BFD_RELOC_12_PCREL:
|
||||
*p++ = value & 0xff;
|
||||
value >>= 8;
|
||||
*p &= 0xf0;
|
||||
*p |= (value & 0x0f);
|
||||
goto done;
|
||||
|
||||
case BFD_RELOC_ALPHA_LITERAL:
|
||||
case BFD_RELOC_ALPHA_LITUSE:
|
||||
return 2;
|
||||
|
@ -2551,7 +2569,8 @@ md_apply_fix (fixP, valueP)
|
|||
return 2;
|
||||
|
||||
default:
|
||||
as_fatal ("unknown relocation type %d?", fixP->fx_r_type);
|
||||
as_fatal ("unhandled relocation type %s",
|
||||
bfd_get_reloc_code_name (fixP->fx_r_type));
|
||||
return 9;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue