* 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:
Ken Raeburn
1995-01-06 22:02:27 +00:00
parent 2a6978af8d
commit 71f9b3c097
2 changed files with 77 additions and 55 deletions

View File

@ -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. * 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> Fri Dec 30 18:21:41 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
* listing.c (list_symbol_table): Build a format string based on * listing.c (list_symbol_table): Build a format string based on

View File

@ -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_addq_r PARAMS ((int, int, int));
static void emit_lda_n PARAMS ((int, bfd_vma, int)); static void emit_lda_n PARAMS ((int, bfd_vma, int));
static void emit_add64 PARAMS ((int, int, bfd_vma)); 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[] = const pseudo_typeS md_pseudo_table[] =
{ {
@ -430,9 +430,9 @@ s_base ()
demand_empty_rest_of_line (); demand_empty_rest_of_line ();
} }
static int in_range (val, nbits, unsignedness) static int in_range_signed (val, nbits)
bfd_vma val; bfd_vma val;
int nbits, unsignedness; int nbits;
{ {
/* Look at top bit of value that would be stored, figure out how it /* 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 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; stored_value = val & mask;
top_bit = stored_value & (one << nbits - 1); top_bit = stored_value & (one << nbits - 1);
missing_bits = val & ~mask; 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 else
{ {
/* will sign-extend */ /* all other bits should be zero */
if (top_bit) return missing_bits == 0;
{
/* 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;
}
} }
} }
#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 static void
s_gprel32 () s_gprel32 ()
{ {
@ -509,8 +522,6 @@ create_literal_section (secp, name)
| SEC_DATA); | SEC_DATA);
} }
#define create_lita_section() create_literal_section (&lita_sec, ".lita")
static valueT static valueT
get_lit8_offset (val) get_lit8_offset (val)
bfd_vma val; bfd_vma val;
@ -648,7 +659,7 @@ md_begin ()
/* So .sbss will get used for tiny objects. */ /* So .sbss will get used for tiny objects. */
bfd_set_gp_size (stdoutput, 8); 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 /* For handling the GP, create a symbol that won't be output in the
symbol table. We'll edit it out of relocs later. */ symbol table. We'll edit it out of relocs later. */
gp = symbol_create ("<GP value>", lita_sec, 0x8000, &zero_address_frag); 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; bfd_signed_vma snum = num;
if (in_range (num, 16, 0)) if (in_range_signed (num, 16))
{ {
emit_lda_n (out, num, in); emit_lda_n (out, num, in);
return; return;
} }
if ((num & 0xffff) == 0 if ((num & 0xffff) == 0
&& in == ZERO && in == ZERO
&& in_range (snum >> 16, 16, 0)) && in_range_signed (snum >> 16, 16))
{ {
emit_ldah_num (out, snum >> 16, in); emit_ldah_num (out, snum >> 16, in);
return; return;
@ -1151,21 +1162,21 @@ emit_add64 (in, out, num)
/* I'm not sure this one is getting invoked when it could. */ /* I'm not sure this one is getting invoked when it could. */
if ((num & 1) == 0 && in == ZERO) 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_lda_n (out, snum >> 1, in);
emit_addq_r (out, out, out); emit_addq_r (out, out, out);
return; return;
} }
else if (num & 0x1fffe == 0 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_ldah_num (out, snum >> 17, in);
emit_addq_r (out, out, out); emit_addq_r (out, out, out);
return; return;
} }
} }
if (in_range (num, 32, 0)) if (in_range_signed (num, 32))
{ {
bfd_vma lo = num & 0xffff; bfd_vma lo = num & 0xffff;
if (lo & 0x8000) 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 static int
alpha_ip (str, insns) alpha_ip (str, insns)
char *str; char *str;
@ -1223,6 +1228,8 @@ alpha_ip (str, insns)
unsigned int mask; unsigned int mask;
int match = 0, num_gen = 1; int match = 0, num_gen = 1;
int comma = 0; int comma = 0;
int do_add64, add64_in, add64_out;
bfd_vma add64_addend;
for (s = str; for (s = str;
islower (*s) || *s == '_' || *s == '/' || *s == '4' || *s == '8'; 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) 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; return -1;
} }
if (comma) if (comma)
@ -1257,6 +1264,7 @@ alpha_ip (str, insns)
argsStart = s; argsStart = s;
for (;;) for (;;)
{ {
do_add64 = 0;
opcode = pattern->match; opcode = pattern->match;
num_gen = 1; num_gen = 1;
for (i = 0; i < MAX_INSNS; i++) for (i = 0; i < MAX_INSNS; i++)
@ -1465,24 +1473,14 @@ alpha_ip (str, insns)
insns[0].reloc[0].code = BFD_RELOC_26; insns[0].reloc[0].code = BFD_RELOC_26;
goto immediate; goto immediate;
#if 0 case 't': /* 12 bit displacement, for PALcode */
case 't': /* 12 bit 0...11 */ insns[0].reloc[0].code = BFD_RELOC_12_PCREL;
insns[0].reloc = RELOC_0_12;
goto immediate; goto immediate;
case '8': /* 8 bit 0...7 */ case '8': /* 8 bit 0...7 */
insns[0].reloc = RELOC_0_8; insns[0].reloc[0].code = BFD_RELOC_8;
goto immediate; goto immediate;
case 'I': /* 26 bit immediate */
insns[0].reloc = RELOC_0_25;
#else
case 't':
case '8':
abort ();
#endif
/*FALLTHROUGH*/
immediate: immediate:
if (*s == ' ') if (*s == ' ')
s++; s++;
@ -1523,8 +1521,10 @@ alpha_ip (str, insns)
else if (at_ok && macro_ok) else if (at_ok && macro_ok)
{ {
/* Constant value supplied, but it's too large. */ /* Constant value supplied, but it's too large. */
emit_add64 (ZERO, AT, do_add64 = 1;
insns[0].reloc[0].exp.X_add_number); add64_in = ZERO;
add64_out = AT;
add64_addend = insns[0].reloc[0].exp.X_add_number;
opcode &= ~ 0x1000; opcode &= ~ 0x1000;
opcode |= (AT << SB); opcode |= (AT << SB);
insns[0].reloc[0].code = BFD_RELOC_NONE; 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 else if (insns[0].reloc[0].code == BFD_RELOC_16
&& insns[0].reloc[0].exp.X_op == O_constant && insns[0].reloc[0].exp.X_op == O_constant
&& !in_range (insns[0].reloc[0].exp.X_add_number, && !in_range_signed (insns[0].reloc[0].exp.X_add_number,
16, 0)) 16))
{ {
bfd_vma val = insns[0].reloc[0].exp.X_add_number; bfd_vma val = insns[0].reloc[0].exp.X_add_number;
if (OPCODE (opcode) == 0x08) if (OPCODE (opcode) == 0x08)
{ {
emit_add64 (ZERO, AT, val); do_add64 = 1;
add64_in = ZERO;
add64_out = AT;
add64_addend = val;
opcode &= ~0x1000; opcode &= ~0x1000;
opcode |= (AT << SB); opcode |= (AT << SB);
insns[0].reloc[0].code = BFD_RELOC_NONE; insns[0].reloc[0].code = BFD_RELOC_NONE;
} }
else if (OPCODE (opcode) == 0x09 else if (OPCODE (opcode) == 0x09
&& in_range (val >> 16, 16, 0)) && in_range_signed (val >> 16, 16))
{ {
/* ldah with high operand - convert to low */ /* ldah with high operand - convert to low */
insns[0].reloc[0].exp.X_add_number >>= 16; insns[0].reloc[0].exp.X_add_number >>= 16;
@ -1667,7 +1670,10 @@ alpha_ip (str, insns)
top = val - low; top = val - low;
if (top) if (top)
{ {
emit_add64 (ZERO, AT, top); do_add64 = 1;
add64_in = ZERO;
add64_out = AT;
add64_addend = top;
opcode |= AT << SB; opcode |= AT << SB;
} }
else else
@ -1821,7 +1827,7 @@ alpha_ip (str, insns)
note_gpreg (PV); note_gpreg (PV);
jsr = &insns[num_gen++]; jsr = &insns[num_gen++];
jsr->opcode = (0x68004000 /* jsr */ jsr->opcode = (pattern->match
| (mask << SA) | (mask << SA)
| (PV << SB) | (PV << SB)
| 0); | 0);
@ -2136,6 +2142,11 @@ alpha_ip (str, insns)
break; break;
} }
if (do_add64)
{
emit_add64 (add64_in, add64_out, add64_addend);
}
insns[0].opcode = opcode; insns[0].opcode = opcode;
return num_gen; return num_gen;
} }
@ -2361,7 +2372,7 @@ s_alpha_set (x)
else if (!strcmp ("volatile", s)) else if (!strcmp ("volatile", s))
/* ignore */ ; /* ignore */ ;
else else
as_warn ("Tried to set unrecognized symbol: %s", name); as_warn ("Tried to .set unrecognized mode `%s'", name);
*input_line_pointer = ch; *input_line_pointer = ch;
demand_empty_rest_of_line (); demand_empty_rest_of_line ();
} }
@ -2531,6 +2542,13 @@ md_apply_fix (fixP, valueP)
*p |= (value & 0x1f); *p |= (value & 0x1f);
goto done; 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_LITERAL:
case BFD_RELOC_ALPHA_LITUSE: case BFD_RELOC_ALPHA_LITUSE:
return 2; return 2;
@ -2551,7 +2569,8 @@ md_apply_fix (fixP, valueP)
return 2; return 2;
default: 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; return 9;
} }