mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-28 23:39:35 +08:00
* config/tc-d30v.c (cur_mul32_p, prev_mul32_p): Make static.
(d30v_current_align, d30v_current_align_seg): New variables. (d30v_last_label): New variable. (d30v_align, s_d30v_align, s_d30v_text): New functions. (s_d30v_data, s_d30v_section): Likewise. (md_pseudo_table): Call them. (md_begin): Initialize d30v_current_align_seg. (md_assemble): Call d30v_align when needed by known current alignment. (d30v_frob_label, d30v_cons_align): New functions. * config/tc-d30v.h (md_do_align): Remove. (tc_frob_label): Call d30v_frob_label. (md_cons_align): New. PR 15642
This commit is contained in:
@ -1,3 +1,18 @@
|
|||||||
|
Tue May 12 12:03:44 1998 Richard Henderson <rth@cygnus.com>
|
||||||
|
|
||||||
|
* config/tc-d30v.c (cur_mul32_p, prev_mul32_p): Make static.
|
||||||
|
(d30v_current_align, d30v_current_align_seg): New variables.
|
||||||
|
(d30v_last_label): New variable.
|
||||||
|
(d30v_align, s_d30v_align, s_d30v_text): New functions.
|
||||||
|
(s_d30v_data, s_d30v_section): Likewise.
|
||||||
|
(md_pseudo_table): Call them.
|
||||||
|
(md_begin): Initialize d30v_current_align_seg.
|
||||||
|
(md_assemble): Call d30v_align when needed by known current alignment.
|
||||||
|
(d30v_frob_label, d30v_cons_align): New functions.
|
||||||
|
* config/tc-d30v.h (md_do_align): Remove.
|
||||||
|
(tc_frob_label): Call d30v_frob_label.
|
||||||
|
(md_cons_align): New.
|
||||||
|
|
||||||
start-sanitize-sky
|
start-sanitize-sky
|
||||||
Mon May 11 12:48:33 1998 Doug Evans <devans@canuck.cygnus.com>
|
Mon May 11 12:48:33 1998 Doug Evans <devans@canuck.cygnus.com>
|
||||||
|
|
||||||
|
@ -71,8 +71,8 @@ static Fixups FixUps[2];
|
|||||||
static Fixups *fixups;
|
static Fixups *fixups;
|
||||||
|
|
||||||
/* Whether current and previous instruction is a word multiply. */
|
/* Whether current and previous instruction is a word multiply. */
|
||||||
int cur_mul32_p = 0;
|
static int cur_mul32_p = 0;
|
||||||
int prev_mul32_p = 0;
|
static int prev_mul32_p = 0;
|
||||||
|
|
||||||
/* The flag_explicitly_parallel is true iff the instruction being assembled
|
/* The flag_explicitly_parallel is true iff the instruction being assembled
|
||||||
has been explicitly written as a parallel short-instruction pair by the
|
has been explicitly written as a parallel short-instruction pair by the
|
||||||
@ -83,6 +83,14 @@ int prev_mul32_p = 0;
|
|||||||
static int flag_explicitly_parallel = 0;
|
static int flag_explicitly_parallel = 0;
|
||||||
static int flag_xp_state = 0;
|
static int flag_xp_state = 0;
|
||||||
|
|
||||||
|
/* The known current alignment of the current section. */
|
||||||
|
static int d30v_current_align;
|
||||||
|
static segT d30v_current_align_seg;
|
||||||
|
|
||||||
|
/* The last seen label in the current section. This is used to auto-align
|
||||||
|
labels preceeding instructions. */
|
||||||
|
static symbolS *d30v_last_label;
|
||||||
|
|
||||||
/* Two nops */
|
/* Two nops */
|
||||||
#define NOP_LEFT ((long long)NOP << 32)
|
#define NOP_LEFT ((long long)NOP << 32)
|
||||||
#define NOP_RIGHT ((long long)NOP)
|
#define NOP_RIGHT ((long long)NOP)
|
||||||
@ -109,6 +117,11 @@ static int parallel_ok PARAMS ((struct d30v_insn *opcode1, unsigned long insn1,
|
|||||||
exec_type_enum exec_type));
|
exec_type_enum exec_type));
|
||||||
static void d30v_number_to_chars PARAMS ((char *buf, long long value, int nbytes));
|
static void d30v_number_to_chars PARAMS ((char *buf, long long value, int nbytes));
|
||||||
static void check_size PARAMS ((long value, int bits, char *file, int line));
|
static void check_size PARAMS ((long value, int bits, char *file, int line));
|
||||||
|
static void d30v_align PARAMS ((int, char *, symbolS *));
|
||||||
|
static void s_d30v_align PARAMS ((int));
|
||||||
|
static void s_d30v_text PARAMS ((int));
|
||||||
|
static void s_d30v_data PARAMS ((int));
|
||||||
|
static void s_d30v_section PARAMS ((int));
|
||||||
|
|
||||||
struct option md_longopts[] = {
|
struct option md_longopts[] = {
|
||||||
{NULL, no_argument, NULL, 0}
|
{NULL, no_argument, NULL, 0}
|
||||||
@ -121,6 +134,13 @@ const pseudo_typeS md_pseudo_table[] =
|
|||||||
{
|
{
|
||||||
{ "word", cons, 4 },
|
{ "word", cons, 4 },
|
||||||
{ "hword", cons, 2 },
|
{ "hword", cons, 2 },
|
||||||
|
{ "align", s_d30v_align, 0 },
|
||||||
|
{ "text", s_d30v_text, 0 },
|
||||||
|
{ "data", s_d30v_data, 0 },
|
||||||
|
{ "section", s_d30v_section, 0 },
|
||||||
|
{ "section.s", s_d30v_section, 0 },
|
||||||
|
{ "sect", s_d30v_section, 0 },
|
||||||
|
{ "sect.s", s_d30v_section, 0 },
|
||||||
{ NULL, NULL, 0 }
|
{ NULL, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -225,10 +245,10 @@ void
|
|||||||
md_show_usage (stream)
|
md_show_usage (stream)
|
||||||
FILE *stream;
|
FILE *stream;
|
||||||
{
|
{
|
||||||
fprintf(stream, (_("\nD30V options:\n\
|
fprintf(stream, _("\nD30V options:\n\
|
||||||
-O Make adjacent short instructions parallel if possible.\n\
|
-O Make adjacent short instructions parallel if possible.\n\
|
||||||
-n Warn about all NOPs inserted by the assembler.\n\
|
-n Warn about all NOPs inserted by the assembler.\n\
|
||||||
-N Warn about NOPs inserted after word multiplies.\n")));
|
-N Warn about NOPs inserted after word multiplies.\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -341,6 +361,8 @@ md_begin ()
|
|||||||
fixups = &FixUps[0];
|
fixups = &FixUps[0];
|
||||||
FixUps[0].next = &FixUps[1];
|
FixUps[0].next = &FixUps[1];
|
||||||
FixUps[1].next = &FixUps[0];
|
FixUps[1].next = &FixUps[0];
|
||||||
|
|
||||||
|
d30v_current_align_seg = now_seg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1054,9 +1076,16 @@ md_assemble (str)
|
|||||||
static exec_type_enum etype = EXEC_UNKNOWN; /* saved extype. used for multiline instructions */
|
static exec_type_enum etype = EXEC_UNKNOWN; /* saved extype. used for multiline instructions */
|
||||||
char *str2;
|
char *str2;
|
||||||
|
|
||||||
if ( (prev_insn != -1) && prev_seg && ((prev_seg != now_seg) || (prev_subseg != now_subseg)))
|
if ((prev_insn != -1) && prev_seg
|
||||||
|
&& ((prev_seg != now_seg) || (prev_subseg != now_subseg)))
|
||||||
d30v_cleanup();
|
d30v_cleanup();
|
||||||
|
|
||||||
|
if (d30v_current_align < 3)
|
||||||
|
d30v_align (3, NULL, d30v_last_label);
|
||||||
|
else if (d30v_current_align > 3)
|
||||||
|
d30v_current_align = 3;
|
||||||
|
d30v_last_label = NULL;
|
||||||
|
|
||||||
flag_explicitly_parallel = 0;
|
flag_explicitly_parallel = 0;
|
||||||
flag_xp_state = 0;
|
flag_xp_state = 0;
|
||||||
if (etype == EXEC_UNKNOWN)
|
if (etype == EXEC_UNKNOWN)
|
||||||
@ -1092,7 +1121,7 @@ md_assemble (str)
|
|||||||
/* assemble first instruction and save it */
|
/* assemble first instruction and save it */
|
||||||
prev_insn = do_assemble (str, &prev_opcode, 1);
|
prev_insn = do_assemble (str, &prev_opcode, 1);
|
||||||
if (prev_insn == -1)
|
if (prev_insn == -1)
|
||||||
as_fatal (_("cannot assemble instruction "));
|
as_fatal (_("Cannot assemble instruction"));
|
||||||
if (prev_opcode.form->form >= LONG)
|
if (prev_opcode.form->form >= LONG)
|
||||||
as_fatal (_("First opcode is long. Unable to mix instructions as specified."));
|
as_fatal (_("First opcode is long. Unable to mix instructions as specified."));
|
||||||
fixups = fixups->next;
|
fixups = fixups->next;
|
||||||
@ -1109,7 +1138,7 @@ md_assemble (str)
|
|||||||
etype = extype;
|
etype = extype;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
as_fatal (_("cannot assemble instruction "));
|
as_fatal (_("Cannot assemble instruction"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (etype != EXEC_UNKNOWN)
|
if (etype != EXEC_UNKNOWN)
|
||||||
@ -1149,7 +1178,7 @@ md_assemble (str)
|
|||||||
d30v_number_to_chars (f, NOP2, 8);
|
d30v_number_to_chars (f, NOP2, 8);
|
||||||
if (warn_nops == NOP_ALL || warn_nops == NOP_MULTIPLY)
|
if (warn_nops == NOP_ALL || warn_nops == NOP_MULTIPLY)
|
||||||
{
|
{
|
||||||
if ((opcode.op->flags_used & FLAG_MEM))
|
if (opcode.op->flags_used & FLAG_MEM)
|
||||||
as_warn (_("word of NOPs added between word multiply and load"));
|
as_warn (_("word of NOPs added between word multiply and load"));
|
||||||
else
|
else
|
||||||
as_warn (_("word of NOPs added between word multiply and 16-bit multiply"));
|
as_warn (_("word of NOPs added between word multiply and 16-bit multiply"));
|
||||||
@ -1312,7 +1341,7 @@ do_assemble (str, opcode, shortp)
|
|||||||
{
|
{
|
||||||
opcode->op++;
|
opcode->op++;
|
||||||
if (strcmp(opcode->op->name,name))
|
if (strcmp(opcode->op->name,name))
|
||||||
return -1;
|
as_fatal (_("operands for opcode `%s' do not match any valid format"), name);
|
||||||
}
|
}
|
||||||
input_line_pointer = save;
|
input_line_pointer = save;
|
||||||
|
|
||||||
@ -1329,9 +1358,9 @@ do_assemble (str, opcode, shortp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* find_format() gets a pointer to an entry in the format table. */
|
/* find_format() gets a pointer to an entry in the format table.
|
||||||
/* It must look at all formats for an opcode and use the operands */
|
It must look at all formats for an opcode and use the operands
|
||||||
/* to choose the correct one. Returns NULL on error. */
|
to choose the correct one. Returns NULL on error. */
|
||||||
|
|
||||||
static struct d30v_format *
|
static struct d30v_format *
|
||||||
find_format (opcode, myops, fsize, cmp_hack)
|
find_format (opcode, myops, fsize, cmp_hack)
|
||||||
@ -1343,15 +1372,15 @@ find_format (opcode, myops, fsize, cmp_hack)
|
|||||||
int numops, match, index, i=0, j, k;
|
int numops, match, index, i=0, j, k;
|
||||||
struct d30v_format *fm;
|
struct d30v_format *fm;
|
||||||
|
|
||||||
/* get all the operands and save them as expressions */
|
/* Get all the operands and save them as expressions. */
|
||||||
numops = get_operands (myops, cmp_hack);
|
numops = get_operands (myops, cmp_hack);
|
||||||
|
|
||||||
while ((index = opcode->format[i++]) != 0)
|
while ((index = opcode->format[i++]) != 0)
|
||||||
{
|
{
|
||||||
if ((fsize == FORCE_SHORT) && (index >= LONG))
|
if (fsize == FORCE_SHORT && index >= LONG)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ((fsize == FORCE_LONG) && (index < LONG))
|
if (fsize == FORCE_LONG && index < LONG)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
fm = (struct d30v_format *)&d30v_format_table[index];
|
fm = (struct d30v_format *)&d30v_format_table[index];
|
||||||
@ -1359,20 +1388,21 @@ find_format (opcode, myops, fsize, cmp_hack)
|
|||||||
while (fm->form == index)
|
while (fm->form == index)
|
||||||
{
|
{
|
||||||
match = 1;
|
match = 1;
|
||||||
/* now check the operands for compatibility */
|
/* Now check the operands for compatibility. */
|
||||||
for (j = 0; match && fm->operands[j]; j++)
|
for (j = 0; match && fm->operands[j]; j++)
|
||||||
{
|
{
|
||||||
int flags = d30v_operand_table[fm->operands[j]].flags;
|
int flags = d30v_operand_table[fm->operands[j]].flags;
|
||||||
|
int bits = d30v_operand_table[fm->operands[j]].bits;
|
||||||
int X_op = myops[j].X_op;
|
int X_op = myops[j].X_op;
|
||||||
int num = myops[j].X_add_number;
|
int num = myops[j].X_add_number;
|
||||||
|
|
||||||
if (flags & OPERAND_SPECIAL)
|
if (flags & OPERAND_SPECIAL)
|
||||||
break;
|
break;
|
||||||
else if (X_op == 0)
|
else if (X_op == O_illegal)
|
||||||
match = 0;
|
match = 0;
|
||||||
else if (flags & OPERAND_REG)
|
else if (flags & OPERAND_REG)
|
||||||
{
|
{
|
||||||
if ((X_op != O_register)
|
if (X_op != O_register
|
||||||
|| ((flags & OPERAND_ACC) && !(num & OPERAND_ACC))
|
|| ((flags & OPERAND_ACC) && !(num & OPERAND_ACC))
|
||||||
|| ((flags & OPERAND_FLAG) && !(num & OPERAND_FLAG))
|
|| ((flags & OPERAND_FLAG) && !(num & OPERAND_FLAG))
|
||||||
|| ((flags & OPERAND_CONTROL)
|
|| ((flags & OPERAND_CONTROL)
|
||||||
@ -1381,49 +1411,70 @@ find_format (opcode, myops, fsize, cmp_hack)
|
|||||||
match = 0;
|
match = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (((flags & OPERAND_MINUS)
|
||||||
if (((flags & OPERAND_MINUS) && ((X_op != O_absent) || (num != OPERAND_MINUS)))
|
&& (X_op != O_absent || num != OPERAND_MINUS))
|
||||||
|| ((flags & OPERAND_PLUS) && ((X_op != O_absent) || (num != OPERAND_PLUS)))
|
|| ((flags & OPERAND_PLUS)
|
||||||
|| ((flags & OPERAND_ATMINUS) && ((X_op != O_absent) || (num != OPERAND_ATMINUS)))
|
&& (X_op != O_absent || num != OPERAND_PLUS))
|
||||||
|| ((flags & OPERAND_ATPAR) && ((X_op != O_absent) || (num != OPERAND_ATPAR)))
|
|| ((flags & OPERAND_ATMINUS)
|
||||||
|| ((flags & OPERAND_ATSIGN) && ((X_op != O_absent) || (num != OPERAND_ATSIGN))))
|
&& (X_op != O_absent || num != OPERAND_ATMINUS))
|
||||||
|
|| ((flags & OPERAND_ATPAR)
|
||||||
|
&& (X_op != O_absent || num != OPERAND_ATPAR))
|
||||||
|
|| ((flags & OPERAND_ATSIGN)
|
||||||
|
&& (X_op != O_absent || num != OPERAND_ATSIGN)))
|
||||||
{
|
{
|
||||||
match=0;
|
match=0;
|
||||||
}
|
}
|
||||||
else if (flags & OPERAND_NUM)
|
else if (flags & OPERAND_NUM)
|
||||||
{
|
{
|
||||||
/* a number can be a constant or symbol expression */
|
/* A number can be a constant or symbol expression. */
|
||||||
|
|
||||||
|
/* Turn an expression into a symbol for later resolution. */
|
||||||
|
if (X_op != O_absent && X_op != O_constant
|
||||||
|
&& X_op != O_symbol && X_op != O_register
|
||||||
|
&& X_op != O_big)
|
||||||
|
{
|
||||||
|
symbolS *sym = make_expr_symbol (&myops[j]);
|
||||||
|
myops[j].X_op = X_op = O_symbol;
|
||||||
|
myops[j].X_add_symbol = sym;
|
||||||
|
myops[j].X_add_number = num = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (fm->form >= LONG)
|
if (fm->form >= LONG)
|
||||||
{
|
{
|
||||||
/* If we're testing for a LONG format, either fits */
|
/* If we're testing for a LONG format, either fits. */
|
||||||
if (X_op != O_constant && X_op != O_symbol)
|
if (X_op != O_constant && X_op != O_symbol)
|
||||||
match = 0;
|
match = 0;
|
||||||
}
|
}
|
||||||
else if ((fm->form < LONG) && (((fsize == FORCE_SHORT) && (X_op == O_symbol)) ||
|
else if (fm->form < LONG
|
||||||
(fm->form == SHORT_D2 && j == 0)))
|
&& ((fsize == FORCE_SHORT && X_op == O_symbol)
|
||||||
|
|| (fm->form == SHORT_D2 && j == 0)))
|
||||||
match = 1;
|
match = 1;
|
||||||
/* This is the tricky part. Will the constant or symbol */
|
/* This is the tricky part. Will the constant or symbol
|
||||||
/* fit into the space in the current format? */
|
fit into the space in the current format? */
|
||||||
else if (X_op == O_constant)
|
else if (X_op == O_constant)
|
||||||
{
|
{
|
||||||
if (check_range (num, d30v_operand_table[fm->operands[j]].bits, flags))
|
if (check_range (num, bits, flags))
|
||||||
match = 0;
|
match = 0;
|
||||||
}
|
}
|
||||||
else if (X_op == O_symbol && S_IS_DEFINED(myops[j].X_add_symbol) &&
|
else if (X_op == O_symbol
|
||||||
(S_GET_SEGMENT(myops[j].X_add_symbol) == now_seg) &&
|
&& S_IS_DEFINED(myops[j].X_add_symbol)
|
||||||
opcode->reloc_flag == RELOC_PCREL)
|
&& S_GET_SEGMENT(myops[j].X_add_symbol) == now_seg
|
||||||
|
&& opcode->reloc_flag == RELOC_PCREL)
|
||||||
{
|
{
|
||||||
/* if the symbol is defined, see if the value will fit */
|
/* If the symbol is defined, see if the value will fit
|
||||||
/* into the form we're considering */
|
into the form we're considering. */
|
||||||
fragS *f;
|
fragS *f;
|
||||||
long value;
|
long value;
|
||||||
/* calculate the current address by running through the previous frags */
|
|
||||||
/* and adding our current offset */
|
/* Calculate the current address by running through the
|
||||||
for (value = 0, f = frchain_now->frch_root; f; f = f->fr_next)
|
previous frags and adding our current offset. */
|
||||||
|
value = 0;
|
||||||
|
for (f = frchain_now->frch_root; f; f = f->fr_next)
|
||||||
value += f->fr_fix + f->fr_offset;
|
value += f->fr_fix + f->fr_offset;
|
||||||
value = S_GET_VALUE(myops[j].X_add_symbol) - value -
|
value = (S_GET_VALUE(myops[j].X_add_symbol) - value
|
||||||
(obstack_next_free(&frchain_now->frch_obstack) - frag_now->fr_literal);
|
- (obstack_next_free(&frchain_now->frch_obstack)
|
||||||
if (check_range (value, d30v_operand_table[fm->operands[j]].bits, flags))
|
- frag_now->fr_literal));
|
||||||
|
if (check_range (value, bits, flags))
|
||||||
match = 0;
|
match = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1431,11 +1482,10 @@ find_format (opcode, myops, fsize, cmp_hack)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* printf("through the loop: match=%d\n",match); */
|
/* printf("through the loop: match=%d\n",match); */
|
||||||
/* we're only done if the operands matched so far AND there
|
/* We're only done if the operands matched so far AND there
|
||||||
are no more to check */
|
are no more to check. */
|
||||||
if (match && myops[j].X_op == 0)
|
if (match && myops[j].X_op == 0)
|
||||||
return fm;
|
return fm;
|
||||||
match = 0;
|
|
||||||
fm = (struct d30v_format *)&d30v_format_table[++k];
|
fm = (struct d30v_format *)&d30v_format_table[++k];
|
||||||
}
|
}
|
||||||
/* printf("trying another format: i=%d\n",i); */
|
/* printf("trying another format: i=%d\n",i); */
|
||||||
@ -1636,7 +1686,6 @@ d30v_cleanup ()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
d30v_number_to_chars (buf, value, n)
|
d30v_number_to_chars (buf, value, n)
|
||||||
char *buf; /* Return 'nbytes' of chars here. */
|
char *buf; /* Return 'nbytes' of chars here. */
|
||||||
@ -1685,7 +1734,172 @@ check_size (value, bits, file, line)
|
|||||||
max = (1 << (bits - 1)) - 1;
|
max = (1 << (bits - 1)) - 1;
|
||||||
|
|
||||||
if (tmp > max)
|
if (tmp > max)
|
||||||
as_bad_where (file, line,"value too large to fit in %d bits",bits);
|
as_bad_where (file, line, _("value too large to fit in %d bits"), bits);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* d30v_frob_label() is called when after a label is recognized. */
|
||||||
|
|
||||||
|
void
|
||||||
|
d30v_frob_label (lab)
|
||||||
|
symbolS *lab;
|
||||||
|
{
|
||||||
|
/* Emit any pending instructions. */
|
||||||
|
d30v_cleanup();
|
||||||
|
|
||||||
|
/* Update the label's address with the current output pointer. */
|
||||||
|
lab->sy_frag = frag_now;
|
||||||
|
S_SET_VALUE (lab, (valueT) frag_now_fix ());
|
||||||
|
|
||||||
|
/* Record this label for future adjustment after we find out what
|
||||||
|
kind of data it references, and the required alignment therewith. */
|
||||||
|
d30v_last_label = lab;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hook into cons for capturing alignment changes. */
|
||||||
|
|
||||||
|
void
|
||||||
|
d30v_cons_align (size)
|
||||||
|
int size;
|
||||||
|
{
|
||||||
|
int log_size;
|
||||||
|
|
||||||
|
log_size = 0;
|
||||||
|
while ((size >>= 1) != 0)
|
||||||
|
++log_size;
|
||||||
|
|
||||||
|
if (d30v_current_align < log_size)
|
||||||
|
d30v_align (log_size, (char *) NULL, NULL);
|
||||||
|
else if (d30v_current_align > log_size)
|
||||||
|
d30v_current_align = log_size;
|
||||||
|
d30v_last_label = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called internally to handle all alignment needs. This takes care
|
||||||
|
of eliding calls to frag_align if'n the cached current alignment
|
||||||
|
says we've already got it, as well as taking care of the auto-aligning
|
||||||
|
labels wrt code. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
d30v_align (n, pfill, label)
|
||||||
|
int n;
|
||||||
|
char *pfill;
|
||||||
|
symbolS *label;
|
||||||
|
{
|
||||||
|
/* The front end is prone to changing segments out from under us
|
||||||
|
temporarily when -g is in effect. */
|
||||||
|
int switched_seg_p = (d30v_current_align_seg != now_seg);
|
||||||
|
|
||||||
|
if (d30v_current_align >= n && !switched_seg_p)
|
||||||
|
return;
|
||||||
|
|
||||||
|
d30v_cleanup();
|
||||||
|
|
||||||
|
if (pfill == NULL)
|
||||||
|
{
|
||||||
|
if (n > 2
|
||||||
|
&& (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
|
||||||
|
{
|
||||||
|
static char const nop[4] = { 0x00, 0xf0, 0x00, 0x00 };
|
||||||
|
|
||||||
|
/* First, make sure we're on a four-byte boundary, in case
|
||||||
|
someone has been putting .byte values the text section. */
|
||||||
|
if (d30v_current_align < 2 || switched_seg_p)
|
||||||
|
frag_align (2, 0, 0);
|
||||||
|
frag_align_pattern (n, nop, sizeof nop, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
frag_align (n, 0, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
frag_align (n, *pfill, 0);
|
||||||
|
|
||||||
|
if (!switched_seg_p)
|
||||||
|
d30v_current_align = n;
|
||||||
|
|
||||||
|
if (label != NULL)
|
||||||
|
{
|
||||||
|
assert (S_GET_SEGMENT (label) == now_seg);
|
||||||
|
label->sy_frag = frag_now;
|
||||||
|
S_SET_VALUE (label, (valueT) frag_now_fix ());
|
||||||
|
}
|
||||||
|
|
||||||
|
record_alignment(now_seg, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle the .align pseudo-op. This aligns to a power of two. We
|
||||||
|
hook here to latch the current alignment. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
s_d30v_align (ignore)
|
||||||
|
int ignore;
|
||||||
|
{
|
||||||
|
int align;
|
||||||
|
char fill, *pfill = NULL;
|
||||||
|
long max_alignment = 15;
|
||||||
|
|
||||||
|
align = get_absolute_expression ();
|
||||||
|
if (align > max_alignment)
|
||||||
|
{
|
||||||
|
align = max_alignment;
|
||||||
|
as_warn (_("Alignment too large: %d assumed"), align);
|
||||||
|
}
|
||||||
|
else if (align < 0)
|
||||||
|
{
|
||||||
|
as_warn (_("Alignment negative: 0 assumed"));
|
||||||
|
align = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*input_line_pointer == ',')
|
||||||
|
{
|
||||||
|
input_line_pointer++;
|
||||||
|
fill = get_absolute_expression ();
|
||||||
|
pfill = &fill;
|
||||||
|
}
|
||||||
|
|
||||||
|
d30v_last_label = NULL;
|
||||||
|
d30v_align (align, pfill, NULL);
|
||||||
|
|
||||||
|
demand_empty_rest_of_line ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle the .text pseudo-op. This is like the usual one, but it
|
||||||
|
clears the saved last label and resets known alignment. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
s_d30v_text (i)
|
||||||
|
int i;
|
||||||
|
|
||||||
|
{
|
||||||
|
s_text (i);
|
||||||
|
d30v_last_label = NULL;
|
||||||
|
d30v_current_align = 0;
|
||||||
|
d30v_current_align_seg = now_seg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle the .data pseudo-op. This is like the usual one, but it
|
||||||
|
clears the saved last label and resets known alignment. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
s_d30v_data (i)
|
||||||
|
int i;
|
||||||
|
{
|
||||||
|
s_data (i);
|
||||||
|
d30v_last_label = NULL;
|
||||||
|
d30v_current_align = 0;
|
||||||
|
d30v_current_align_seg = now_seg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle the .section pseudo-op. This is like the usual one, but it
|
||||||
|
clears the saved last label and resets known alignment. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
s_d30v_section (ignore)
|
||||||
|
int ignore;
|
||||||
|
{
|
||||||
|
obj_elf_section (ignore);
|
||||||
|
d30v_last_label = NULL;
|
||||||
|
d30v_current_align = 0;
|
||||||
|
d30v_current_align_seg = now_seg;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user