* config/tc-alpha.h (alpha_do_align): Don't declare.
(md_do_align): Don't define. (tc_frob_label): Define. (alpha_define_label): Declare. (md_flush_pending_output): Define. (alpha_flush_pending_output): Declare. * config/tc-alpha.c (insn_label): New static variable. (auto_align): New static variable. (md_pseudo_table): Add cases for .text, .data, .align, .byte, .hword, .int, .long, .octa, .quad, .short, .word, .double, .float, and .single. Change .t_floating, .s_floating, .f_floating, .g_floating, and .d_floating to use s_alpha_float_cons rather than float_cons. (s_alpha_text, s_alpha_data): New static functions. (s_rdata, s_sdata): Clear insn_label and set auto_align. (s_gprel32): If auto_align, align. Clear insn_label. (emit_insn): Clear insn_label. (s_alpha_align): New static function. (alpha_align): Make static. Take label argument. (alpha_flush_pending_output): New static function. (s_alpha_cons, s_alpha_float_cons): New static functions. (alpha_define_label): New function. PR 7148.
This commit is contained in:
parent
5cb0993caf
commit
265d172efb
3 changed files with 248 additions and 36 deletions
|
@ -1,3 +1,28 @@
|
|||
Thu Jul 6 12:54:27 1995 Ian Lance Taylor <ian@cygnus.com>
|
||||
|
||||
* config/tc-alpha.h (alpha_do_align): Don't declare.
|
||||
(md_do_align): Don't define.
|
||||
(tc_frob_label): Define.
|
||||
(alpha_define_label): Declare.
|
||||
(md_flush_pending_output): Define.
|
||||
(alpha_flush_pending_output): Declare.
|
||||
* config/tc-alpha.c (insn_label): New static variable.
|
||||
(auto_align): New static variable.
|
||||
(md_pseudo_table): Add cases for .text, .data, .align, .byte,
|
||||
.hword, .int, .long, .octa, .quad, .short, .word, .double, .float,
|
||||
and .single. Change .t_floating, .s_floating, .f_floating,
|
||||
.g_floating, and .d_floating to use s_alpha_float_cons rather than
|
||||
float_cons.
|
||||
(s_alpha_text, s_alpha_data): New static functions.
|
||||
(s_rdata, s_sdata): Clear insn_label and set auto_align.
|
||||
(s_gprel32): If auto_align, align. Clear insn_label.
|
||||
(emit_insn): Clear insn_label.
|
||||
(s_alpha_align): New static function.
|
||||
(alpha_align): Make static. Take label argument.
|
||||
(alpha_flush_pending_output): New static function.
|
||||
(s_alpha_cons, s_alpha_float_cons): New static functions.
|
||||
(alpha_define_label): New function.
|
||||
|
||||
Wed Jul 5 22:49:31 1995 Ken Raeburn <raeburn@cygnus.com>
|
||||
|
||||
* conf.in: Regenerate with autoreconf.
|
||||
|
|
|
@ -65,7 +65,6 @@
|
|||
|
||||
/* These are exported to relaxing code, even though we don't do any
|
||||
relaxing on this processor currently. */
|
||||
const relax_typeS md_relax_table[1];
|
||||
int md_short_jump_size = 4;
|
||||
int md_long_jump_size = 4;
|
||||
|
||||
|
@ -85,7 +84,7 @@ static symbolS *gp;
|
|||
|
||||
/* We'll probably be using this relocation frequently, and we
|
||||
will want to compare for it. */
|
||||
static const reloc_howto_type *gpdisp_hi16_howto;
|
||||
static reloc_howto_type *gpdisp_hi16_howto;
|
||||
|
||||
/* These are exported to ECOFF code. */
|
||||
unsigned long alpha_gprmask, alpha_fprmask;
|
||||
|
@ -99,6 +98,17 @@ static expressionS lituse_basereg, lituse_byteoff, lituse_jsr;
|
|||
Some other systems may want this option too. */
|
||||
static int addr32;
|
||||
|
||||
/* Symbol labelling the current insn. When the Alpha gas sees
|
||||
foo:
|
||||
.quad 0
|
||||
and the section happens to not be on an eight byte boundary, it
|
||||
will align both the symbol and the .quad to an eight byte boundary. */
|
||||
static symbolS *insn_label;
|
||||
|
||||
/* Whether we should automatically align data generation pseudo-ops.
|
||||
.align 0 will turn this off. */
|
||||
static int auto_align = 1;
|
||||
|
||||
/* Imported functions -- they should be defined in header files somewhere. */
|
||||
extern segT subseg_get ();
|
||||
extern PTR bfd_alloc_by_size_t ();
|
||||
|
@ -108,6 +118,11 @@ extern void s_globl (), s_long (), s_short (), s_space (), cons (), s_text (),
|
|||
/* Static functions, needing forward declarations. */
|
||||
static void s_base (), s_proc (), s_alpha_set ();
|
||||
static void s_gprel32 (), s_rdata (), s_sdata (), s_alpha_comm ();
|
||||
static void s_alpha_text PARAMS ((int));
|
||||
static void s_alpha_data PARAMS ((int));
|
||||
static void s_alpha_align PARAMS ((int));
|
||||
static void s_alpha_cons PARAMS ((int));
|
||||
static void s_alpha_float_cons PARAMS ((int));
|
||||
static int alpha_ip ();
|
||||
|
||||
static void emit_unaligned_io PARAMS ((char *, int, valueT, int));
|
||||
|
@ -127,19 +142,22 @@ 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_signed PARAMS ((bfd_vma, int));
|
||||
static void alpha_align PARAMS ((int, int, symbolS *));
|
||||
|
||||
const pseudo_typeS md_pseudo_table[] =
|
||||
{
|
||||
{"common", s_comm, 0}, /* is this used? */
|
||||
{"comm", s_alpha_comm, 0}, /* osf1 compiler does this */
|
||||
{"text", s_alpha_text, 0},
|
||||
{"data", s_alpha_data, 0},
|
||||
{"rdata", s_rdata, 0},
|
||||
{"sdata", s_sdata, 0},
|
||||
{"gprel32", s_gprel32, 0},
|
||||
{"t_floating", float_cons, 'd'},
|
||||
{"s_floating", float_cons, 'f'},
|
||||
{"f_floating", float_cons, 'F'},
|
||||
{"g_floating", float_cons, 'G'},
|
||||
{"d_floating", float_cons, 'D'},
|
||||
{"t_floating", s_alpha_float_cons, 'd'},
|
||||
{"s_floating", s_alpha_float_cons, 'f'},
|
||||
{"f_floating", s_alpha_float_cons, 'F'},
|
||||
{"g_floating", s_alpha_float_cons, 'G'},
|
||||
{"d_floating", s_alpha_float_cons, 'D'},
|
||||
|
||||
{"proc", s_proc, 0},
|
||||
{"aproc", s_proc, 1},
|
||||
|
@ -153,6 +171,19 @@ const pseudo_typeS md_pseudo_table[] =
|
|||
{"aent", s_ignore, 0},
|
||||
{"ugen", s_ignore, 0},
|
||||
|
||||
{"align", s_alpha_align, 0},
|
||||
{"byte", s_alpha_cons, 0},
|
||||
{"hword", s_alpha_cons, 1},
|
||||
{"int", s_alpha_cons, 2},
|
||||
{"long", s_alpha_cons, 2},
|
||||
{"octa", s_alpha_cons, 4},
|
||||
{"quad", s_alpha_cons, 3},
|
||||
{"short", s_alpha_cons, 1},
|
||||
{"word", s_alpha_cons, 1},
|
||||
{"double", s_alpha_float_cons, 'd'},
|
||||
{"float", s_alpha_float_cons, 'f'},
|
||||
{"single", s_alpha_float_cons, 'f'},
|
||||
|
||||
/* We don't do any optimizing, so we can safely ignore these. */
|
||||
{"noalias", s_ignore, 0},
|
||||
{"alias", s_ignore, 0},
|
||||
|
@ -265,6 +296,30 @@ tc_get_register (frame)
|
|||
return framereg;
|
||||
}
|
||||
|
||||
/* Handle the .text pseudo-op. This is like the usual one, but it
|
||||
clears insn_label and restores auto alignment. */
|
||||
|
||||
static void
|
||||
s_alpha_text (i)
|
||||
int i;
|
||||
{
|
||||
s_text (i);
|
||||
insn_label = NULL;
|
||||
auto_align = 1;
|
||||
}
|
||||
|
||||
/* Handle the .data pseudo-op. This is like the usual one, but it
|
||||
clears insn_label and restores auto alignment. */
|
||||
|
||||
static void
|
||||
s_alpha_data (i)
|
||||
int i;
|
||||
{
|
||||
s_data (i);
|
||||
insn_label = NULL;
|
||||
auto_align = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
s_rdata (ignore)
|
||||
int ignore;
|
||||
|
@ -280,6 +335,8 @@ s_rdata (ignore)
|
|||
rdata = subseg_new (".rdata", 0);
|
||||
#endif
|
||||
demand_empty_rest_of_line ();
|
||||
insn_label = NULL;
|
||||
auto_align = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -297,6 +354,8 @@ s_sdata (ignore)
|
|||
sdata = subseg_new (".sdata", 0);
|
||||
#endif
|
||||
demand_empty_rest_of_line ();
|
||||
insn_label = NULL;
|
||||
auto_align = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -439,7 +498,7 @@ static int in_range_signed (val, nbits)
|
|||
|
||||
mask = (one << nbits) - 1;
|
||||
stored_value = val & mask;
|
||||
top_bit = stored_value & (one << nbits - 1);
|
||||
top_bit = stored_value & (one << (nbits - 1));
|
||||
missing_bits = val & ~mask;
|
||||
/* will sign-extend */
|
||||
if (top_bit)
|
||||
|
@ -495,10 +554,13 @@ s_gprel32 ()
|
|||
default:
|
||||
abort ();
|
||||
}
|
||||
if (auto_align)
|
||||
alpha_align (2, 0, insn_label);
|
||||
p = frag_more (4);
|
||||
memset (p, 0, 4);
|
||||
fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &e, 0,
|
||||
BFD_RELOC_GPREL32);
|
||||
insn_label = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -592,7 +654,7 @@ md_begin ()
|
|||
char *q2 = p;
|
||||
|
||||
for (; *q; q++)
|
||||
if (*q /= '/')
|
||||
if (*q != '/')
|
||||
*q2++ = *q;
|
||||
|
||||
*q2++ = 0;
|
||||
|
@ -658,14 +720,16 @@ emit_insn (insn)
|
|||
}
|
||||
f = fix_new_exp (frag_now, (toP - frag_now->fr_literal), 4,
|
||||
&r->exp, r->pcrel, r->code);
|
||||
}
|
||||
if (r->code == BFD_RELOC_ALPHA_GPDISP_LO16)
|
||||
{
|
||||
static bit_fixS cookie;
|
||||
/* @@ This'll make the range checking in write.c shut up. */
|
||||
f->fx_bit_fixP = &cookie;
|
||||
if (r->code == BFD_RELOC_ALPHA_GPDISP_LO16)
|
||||
{
|
||||
static bit_fixS cookie;
|
||||
/* @@ This'll make the range checking in write.c shut up. */
|
||||
f->fx_bit_fixP = &cookie;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
insn_label = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1185,11 +1249,11 @@ alpha_ip (str, insns)
|
|||
struct alpha_opcode *pattern;
|
||||
char *argsStart;
|
||||
unsigned int opcode;
|
||||
unsigned int mask;
|
||||
unsigned int mask = 0;
|
||||
int match = 0, num_gen = 1;
|
||||
int comma = 0;
|
||||
int do_add64, add64_in, add64_out;
|
||||
bfd_vma add64_addend;
|
||||
int do_add64, add64_in = 0, add64_out = 0;
|
||||
bfd_vma add64_addend = 0;
|
||||
|
||||
for (s = str;
|
||||
islower (*s) || *s == '_' || *s == '/' || *s == '4' || *s == '8';
|
||||
|
@ -1644,7 +1708,7 @@ alpha_ip (str, insns)
|
|||
else if (insns[0].reloc[0].exp.X_op == O_symbol)
|
||||
{
|
||||
unsigned long old_opcode = opcode;
|
||||
int tmp_reg;
|
||||
int tmp_reg = -1;
|
||||
|
||||
if (!macro_ok)
|
||||
as_bad ("insn requires expansion but `nomacro' specified");
|
||||
|
@ -1816,10 +1880,10 @@ alpha_ip (str, insns)
|
|||
manipulation, with t9 and t10 as temporaries. */
|
||||
{
|
||||
/* Characteristics of access. */
|
||||
int is_load, is_unsigned = 0, is_unaligned = 0;
|
||||
int is_load = 99, is_unsigned = 0, is_unaligned = 0;
|
||||
int mode_size, mode;
|
||||
/* Register operand. */
|
||||
int reg;
|
||||
int reg = -1;
|
||||
/* Addend for loads and stores. */
|
||||
valueT addend;
|
||||
/* Which register do we use for the address? */
|
||||
|
@ -1937,7 +2001,7 @@ alpha_ip (str, insns)
|
|||
|
||||
if (is_load)
|
||||
{
|
||||
int reg2, reg3;
|
||||
int reg2, reg3 = -1;
|
||||
|
||||
if (is_unaligned)
|
||||
reg2 = T9, reg3 = T10;
|
||||
|
@ -2328,21 +2392,143 @@ md_pcrel_from (fixP)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
alpha_do_align (n, fill)
|
||||
int n;
|
||||
const char *fill;
|
||||
/* Handle the .align pseudo-op. This aligns to a power of two. It
|
||||
also adjusts any current instruction label. We treat this the same
|
||||
way the MIPS port does: .align 0 turns off auto alignment. */
|
||||
|
||||
static void
|
||||
s_alpha_align (ignore)
|
||||
int ignore;
|
||||
{
|
||||
if (!fill
|
||||
register int temp;
|
||||
register long temp_fill;
|
||||
long max_alignment = 15;
|
||||
|
||||
temp = get_absolute_expression ();
|
||||
if (temp > max_alignment)
|
||||
as_bad ("Alignment too large: %d. assumed.", temp = max_alignment);
|
||||
else if (temp < 0)
|
||||
{
|
||||
as_warn ("Alignment negative: 0 assumed.");
|
||||
temp = 0;
|
||||
}
|
||||
if (*input_line_pointer == ',')
|
||||
{
|
||||
input_line_pointer++;
|
||||
temp_fill = get_absolute_expression ();
|
||||
}
|
||||
else
|
||||
temp_fill = 0;
|
||||
if (temp)
|
||||
{
|
||||
auto_align = 1;
|
||||
alpha_align (temp, (int) temp_fill, insn_label);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto_align = 0;
|
||||
}
|
||||
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
static void
|
||||
alpha_align (n, fill, label)
|
||||
int n;
|
||||
int fill;
|
||||
symbolS *label;
|
||||
{
|
||||
if (fill == 0
|
||||
&& (now_seg == text_section
|
||||
|| !strcmp (now_seg->name, ".init")
|
||||
|| !strcmp (now_seg->name, ".fini")))
|
||||
{
|
||||
static const unsigned char nop_pattern[] = { 0x1f, 0x04, 0xff, 0x47 };
|
||||
frag_align_pattern (n, nop_pattern, sizeof (nop_pattern));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
else
|
||||
frag_align (n, fill);
|
||||
|
||||
if (label != NULL)
|
||||
{
|
||||
assert (S_GET_SEGMENT (label) == now_seg);
|
||||
label->sy_frag = frag_now;
|
||||
S_SET_VALUE (label, (valueT) frag_now_fix ());
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is called just before the generic pseudo-ops output
|
||||
something. It just clears insn_label. */
|
||||
|
||||
void
|
||||
alpha_flush_pending_output ()
|
||||
{
|
||||
insn_label = NULL;
|
||||
}
|
||||
|
||||
/* Handle data allocation pseudo-ops. This is like the generic
|
||||
version, but it makes sure the current label, if any, is correctly
|
||||
aligned. */
|
||||
|
||||
static void
|
||||
s_alpha_cons (log_size)
|
||||
int log_size;
|
||||
{
|
||||
if (log_size > 0 && auto_align)
|
||||
alpha_align (log_size, 0, insn_label);
|
||||
insn_label = NULL;
|
||||
cons (1 << log_size);
|
||||
}
|
||||
|
||||
/* Handle floating point allocation pseudo-ops. This is like the
|
||||
generic vresion, but it makes sure the current label, if any, is
|
||||
correctly aligned. */
|
||||
|
||||
static void
|
||||
s_alpha_float_cons (type)
|
||||
int type;
|
||||
{
|
||||
if (auto_align)
|
||||
{
|
||||
int log_size;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
default:
|
||||
case 'f':
|
||||
case 'F':
|
||||
log_size = 2;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'D':
|
||||
case 'G':
|
||||
log_size = 3;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
case 'X':
|
||||
case 'p':
|
||||
case 'P':
|
||||
log_size = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
alpha_align (log_size, 0, insn_label);
|
||||
}
|
||||
|
||||
insn_label = NULL;
|
||||
float_cons (type);
|
||||
}
|
||||
|
||||
/* This function is called whenever a label is defined. It is used to
|
||||
adjust the label when an automatic alignment occurs. */
|
||||
|
||||
void
|
||||
alpha_define_label (sym)
|
||||
symbolS *sym;
|
||||
{
|
||||
insn_label = sym;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -47,9 +47,7 @@ extern valueT alpha_gp_value;
|
|||
#define md_create_short_jump(p,f,t,fr,s) as_fatal("alpha_create_short_jump")
|
||||
#define md_estimate_size_before_relax(f,s) \
|
||||
(as_fatal("estimate_size_before_relax called"),1)
|
||||
#define md_operand(x) 0
|
||||
|
||||
extern unsigned long md_section_align PARAMS ((segT, unsigned long));
|
||||
#define md_operand(x) ((void) (0))
|
||||
|
||||
#define md_undefined_symbol(name) (0)
|
||||
|
||||
|
@ -57,8 +55,11 @@ extern unsigned long md_section_align PARAMS ((segT, unsigned long));
|
|||
|
||||
#define md_number_to_chars number_to_chars_littleendian
|
||||
|
||||
extern int alpha_do_align ();
|
||||
#define md_do_align(n,fill,l) if (alpha_do_align(n,fill)) goto l
|
||||
extern int tc_get_register PARAMS ((int frame));
|
||||
extern void alpha_frob_ecoff_data PARAMS ((void));
|
||||
|
||||
extern void alpha_frob_file ();
|
||||
#define tc_frob_file alpha_frob_file
|
||||
#define tc_frob_label(sym) alpha_define_label (sym)
|
||||
extern void alpha_define_label PARAMS ((struct symbol *));
|
||||
|
||||
#define md_flush_pending_output alpha_flush_pending_output
|
||||
extern void alpha_flush_pending_output PARAMS ((void));
|
||||
|
|
Loading…
Reference in a new issue