mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-23 03:29:47 +08:00
* config/tc-mips.c (insn_label): Remove.
(struct insn_label_list): Define. (insn_labels, free_insn_labels): New static variables. (mips_clear_insn_labels): New static function. (append_insn): Mark all mips16 text labels, and make them odd. Handle all labels after emitting a nop, not just one. Call mips_clear_insn_labels rather than just clearing insn_label. (mips_emit_delays): Add insns parameter, and use it to decide whether to mark mips16 labels. Handle all labels, not just one. Force mips16 labels to be odd. Change all callers. (mips16_immed): Don't check for an odd branch target. (md_apply_fix): Don't check mips16 mode for a branch reloc. (mips16_extended_frag): Ignore the low bit in a branch target. (md_convert_frag): Likewise. (mips_no_prev_insn): Call mips_clear_insn_labels rather than just clearing insn_label. (mips_align, mips_flush_pending_output, s_cons): Likewise. (s_float_cons, s_gpword): Likewise. (s_align): Use insn_labels rather than insn_label. (s_cons, s_float_cons, s_gpword): Likewise. (mips_frob_file_after_relocs): New function. (mips_define_label): Rewrite to add to insn_labels list. * config/tc-mips.h (tc_frob_file_after_relocs): Define. * ecoff.c (ecoff_build_symbols): If the size of a function comes out odd, increment it.
This commit is contained in:
@ -1,5 +1,34 @@
|
|||||||
Tue Dec 17 10:59:32 1996 Ian Lance Taylor <ian@cygnus.com>
|
Tue Dec 17 10:59:32 1996 Ian Lance Taylor <ian@cygnus.com>
|
||||||
|
|
||||||
|
* config/tc-mips.c (insn_label): Remove.
|
||||||
|
(struct insn_label_list): Define.
|
||||||
|
(insn_labels, free_insn_labels): New static variables.
|
||||||
|
(mips_clear_insn_labels): New static function.
|
||||||
|
(append_insn): Mark all mips16 text labels, and make them odd.
|
||||||
|
Handle all labels after emitting a nop, not just one. Call
|
||||||
|
mips_clear_insn_labels rather than just clearing insn_label.
|
||||||
|
(mips_emit_delays): Add insns parameter, and use it to decide
|
||||||
|
whether to mark mips16 labels. Handle all labels, not just one.
|
||||||
|
Force mips16 labels to be odd. Change all callers.
|
||||||
|
(mips16_immed): Don't check for an odd branch target.
|
||||||
|
(md_apply_fix): Don't check mips16 mode for a branch reloc.
|
||||||
|
(mips16_extended_frag): Ignore the low bit in a branch target.
|
||||||
|
(md_convert_frag): Likewise.
|
||||||
|
(mips_no_prev_insn): Call mips_clear_insn_labels rather than just
|
||||||
|
clearing insn_label.
|
||||||
|
(mips_align, mips_flush_pending_output, s_cons): Likewise.
|
||||||
|
(s_float_cons, s_gpword): Likewise.
|
||||||
|
(s_align): Use insn_labels rather than insn_label.
|
||||||
|
(s_cons, s_float_cons, s_gpword): Likewise.
|
||||||
|
(mips_frob_file_after_relocs): New function.
|
||||||
|
(mips_define_label): Rewrite to add to insn_labels list.
|
||||||
|
* config/tc-mips.h (tc_frob_file_after_relocs): Define.
|
||||||
|
* ecoff.c (ecoff_build_symbols): If the size of a function comes
|
||||||
|
out odd, increment it.
|
||||||
|
|
||||||
|
* config/tc-mips.c (append_insn): Only update prev_insn when not
|
||||||
|
reordering if place is NULL.
|
||||||
|
|
||||||
* config/tc-mips.c (mips16_ip): Check for a missing expression
|
* config/tc-mips.c (mips16_ip): Check for a missing expression
|
||||||
when using the register indirect addressing mode.
|
when using the register indirect addressing mode.
|
||||||
|
|
||||||
|
@ -259,9 +259,6 @@ static int byte_order;
|
|||||||
|
|
||||||
static int auto_align = 1;
|
static int auto_align = 1;
|
||||||
|
|
||||||
/* Symbol labelling the current insn. */
|
|
||||||
static symbolS *insn_label;
|
|
||||||
|
|
||||||
/* When outputting SVR4 PIC code, the assembler needs to know the
|
/* When outputting SVR4 PIC code, the assembler needs to know the
|
||||||
offset in the stack frame from which to restore the $gp register.
|
offset in the stack frame from which to restore the $gp register.
|
||||||
This is set by the .cprestore pseudo-op, and saved in this
|
This is set by the .cprestore pseudo-op, and saved in this
|
||||||
@ -504,7 +501,7 @@ static void append_insn PARAMS ((char *place,
|
|||||||
bfd_reloc_code_real_type r,
|
bfd_reloc_code_real_type r,
|
||||||
boolean));
|
boolean));
|
||||||
static void mips_no_prev_insn PARAMS ((void));
|
static void mips_no_prev_insn PARAMS ((void));
|
||||||
static void mips_emit_delays PARAMS ((void));
|
static void mips_emit_delays PARAMS ((boolean));
|
||||||
#ifdef USE_STDARG
|
#ifdef USE_STDARG
|
||||||
static void macro_build PARAMS ((char *place, int *counter, expressionS * ep,
|
static void macro_build PARAMS ((char *place, int *counter, expressionS * ep,
|
||||||
const char *name, const char *fmt,
|
const char *name, const char *fmt,
|
||||||
@ -644,6 +641,30 @@ mips_pop_insert ()
|
|||||||
pop_insert (mips_nonecoff_pseudo_table);
|
pop_insert (mips_nonecoff_pseudo_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Symbols labelling the current insn. */
|
||||||
|
|
||||||
|
struct insn_label_list
|
||||||
|
{
|
||||||
|
struct insn_label_list *next;
|
||||||
|
symbolS *label;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct insn_label_list *insn_labels;
|
||||||
|
static struct insn_label_list *free_insn_labels;
|
||||||
|
|
||||||
|
static void mips_clear_insn_labels PARAMS ((void));
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
mips_clear_insn_labels ()
|
||||||
|
{
|
||||||
|
register struct insn_label_list **pl;
|
||||||
|
|
||||||
|
for (pl = &free_insn_labels; *pl != NULL; pl = &(*pl)->next)
|
||||||
|
;
|
||||||
|
*pl = insn_labels;
|
||||||
|
insn_labels = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static char *expr_end;
|
static char *expr_end;
|
||||||
|
|
||||||
/* Expressions which appear in instructions. These are set by
|
/* Expressions which appear in instructions. These are set by
|
||||||
@ -1172,6 +1193,27 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
|
|||||||
else
|
else
|
||||||
record_alignment (now_seg, 2);
|
record_alignment (now_seg, 2);
|
||||||
|
|
||||||
|
/* Mark instruction labels in mips16 mode. This permits the linker
|
||||||
|
to handle them specially, such as generating jalx instructions
|
||||||
|
when needed. We also make them odd for the duration of the
|
||||||
|
assembly, in order to generate the right sort of code. We will
|
||||||
|
make them even in the adjust_symtab routine, while leaving them
|
||||||
|
marked. This is convenient for the debugger and the
|
||||||
|
disassembler. The linker knows to make them odd again. */
|
||||||
|
if (mips16)
|
||||||
|
{
|
||||||
|
struct insn_label_list *l;
|
||||||
|
|
||||||
|
for (l = insn_labels; l != NULL; l = l->next)
|
||||||
|
{
|
||||||
|
#ifdef S_SET_OTHER
|
||||||
|
if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
|
||||||
|
S_SET_OTHER (l->label, STO_MIPS16);
|
||||||
|
#endif
|
||||||
|
++l->label->sy_value.X_add_number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
prev_pinfo = prev_insn.insn_mo->pinfo;
|
prev_pinfo = prev_insn.insn_mo->pinfo;
|
||||||
pinfo = ip->insn_mo->pinfo;
|
pinfo = ip->insn_mo->pinfo;
|
||||||
|
|
||||||
@ -1350,6 +1392,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
|
|||||||
fragS *old_frag;
|
fragS *old_frag;
|
||||||
unsigned long old_frag_offset;
|
unsigned long old_frag_offset;
|
||||||
int i;
|
int i;
|
||||||
|
struct insn_label_list *l;
|
||||||
|
|
||||||
old_frag = frag_now;
|
old_frag = frag_now;
|
||||||
old_frag_offset = frag_now_fix ();
|
old_frag_offset = frag_now_fix ();
|
||||||
@ -1371,11 +1414,14 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
|
|||||||
frag_grow (40);
|
frag_grow (40);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (insn_label != NULL)
|
for (l = insn_labels; l != NULL; l = l->next)
|
||||||
{
|
{
|
||||||
assert (S_GET_SEGMENT (insn_label) == now_seg);
|
assert (S_GET_SEGMENT (l->label) == now_seg);
|
||||||
insn_label->sy_frag = frag_now;
|
l->label->sy_frag = frag_now;
|
||||||
S_SET_VALUE (insn_label, (valueT) frag_now_fix ());
|
S_SET_VALUE (l->label, (valueT) frag_now_fix ());
|
||||||
|
/* mips16 text labels are stored as odd. */
|
||||||
|
if (mips16)
|
||||||
|
++l->label->sy_value.X_add_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_ECOFF_DEBUGGING
|
#ifndef NO_ECOFF_DEBUGGING
|
||||||
@ -1580,7 +1626,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
|
|||||||
whether there is a label on this instruction. If
|
whether there is a label on this instruction. If
|
||||||
there are any branches to anything other than a
|
there are any branches to anything other than a
|
||||||
label, users must use .set noreorder. */
|
label, users must use .set noreorder. */
|
||||||
|| insn_label != NULL
|
|| insn_labels != NULL
|
||||||
/* If the previous instruction is in a variant frag, we
|
/* If the previous instruction is in a variant frag, we
|
||||||
can not do the swap. This does not apply to the
|
can not do the swap. This does not apply to the
|
||||||
mips16, which uses variant frags for different
|
mips16, which uses variant frags for different
|
||||||
@ -1878,9 +1924,9 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
|
|||||||
prev_insn_where = f - frag_now->fr_literal;
|
prev_insn_where = f - frag_now->fr_literal;
|
||||||
prev_insn_valid = 1;
|
prev_insn_valid = 1;
|
||||||
}
|
}
|
||||||
else
|
else if (place == NULL)
|
||||||
{
|
{
|
||||||
/* We need to record a bit of uninformation even when we are not
|
/* We need to record a bit of information even when we are not
|
||||||
reordering, in order to determine the base address for mips16
|
reordering, in order to determine the base address for mips16
|
||||||
PC relative relocs. */
|
PC relative relocs. */
|
||||||
prev_insn = *ip;
|
prev_insn = *ip;
|
||||||
@ -1888,7 +1934,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* We just output an insn, so the next one doesn't have a label. */
|
/* We just output an insn, so the next one doesn't have a label. */
|
||||||
insn_label = NULL;
|
mips_clear_insn_labels ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function forgets that there was any previous instruction or
|
/* This function forgets that there was any previous instruction or
|
||||||
@ -1905,16 +1951,18 @@ mips_no_prev_insn ()
|
|||||||
prev_insn_extended = 0;
|
prev_insn_extended = 0;
|
||||||
prev_insn_reloc_type = BFD_RELOC_UNUSED;
|
prev_insn_reloc_type = BFD_RELOC_UNUSED;
|
||||||
prev_prev_insn_unreordered = 0;
|
prev_prev_insn_unreordered = 0;
|
||||||
insn_label = NULL;
|
mips_clear_insn_labels ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function must be called whenever we turn on noreorder or emit
|
/* This function must be called whenever we turn on noreorder or emit
|
||||||
something other than instructions. It inserts any NOPS which might
|
something other than instructions. It inserts any NOPS which might
|
||||||
be needed by the previous instruction, and clears the information
|
be needed by the previous instruction, and clears the information
|
||||||
kept for the previous instructions. */
|
kept for the previous instructions. The INSNS parameter is true if
|
||||||
|
instructions are to follow. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mips_emit_delays ()
|
mips_emit_delays (insns)
|
||||||
|
boolean insns;
|
||||||
{
|
{
|
||||||
if (! mips_noreorder)
|
if (! mips_noreorder)
|
||||||
{
|
{
|
||||||
@ -1958,16 +2006,43 @@ mips_emit_delays ()
|
|||||||
nop = 1;
|
nop = 1;
|
||||||
if (nop)
|
if (nop)
|
||||||
{
|
{
|
||||||
|
struct insn_label_list *l;
|
||||||
|
|
||||||
emit_nop ();
|
emit_nop ();
|
||||||
if (insn_label != NULL)
|
for (l = insn_labels; l != NULL; l = l->next)
|
||||||
{
|
{
|
||||||
assert (S_GET_SEGMENT (insn_label) == now_seg);
|
assert (S_GET_SEGMENT (l->label) == now_seg);
|
||||||
insn_label->sy_frag = frag_now;
|
l->label->sy_frag = frag_now;
|
||||||
S_SET_VALUE (insn_label, (valueT) frag_now_fix ());
|
S_SET_VALUE (l->label, (valueT) frag_now_fix ());
|
||||||
|
/* mips16 text labels are stored as odd. */
|
||||||
|
if (mips16)
|
||||||
|
++l->label->sy_value.X_add_number;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Mark instruction labels in mips16 mode. This permits the linker
|
||||||
|
to handle them specially, such as generating jalx instructions
|
||||||
|
when needed. We also make them odd for the duration of the
|
||||||
|
assembly, in order to generate the right sort of code. We will
|
||||||
|
make them even in the adjust_symtab routine, while leaving them
|
||||||
|
marked. This is convenient for the debugger and the
|
||||||
|
disassembler. The linker knows to make them odd again. */
|
||||||
|
if (mips16 && insns)
|
||||||
|
{
|
||||||
|
struct insn_label_list *l;
|
||||||
|
|
||||||
|
for (l = insn_labels; l != NULL; l = l->next)
|
||||||
|
{
|
||||||
|
#ifdef S_SET_OTHER
|
||||||
|
if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
|
||||||
|
S_SET_OTHER (l->label, STO_MIPS16);
|
||||||
|
#endif
|
||||||
|
if ((l->label->sy_value.X_add_number & 1) == 0)
|
||||||
|
++l->label->sy_value.X_add_number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mips_no_prev_insn ();
|
mips_no_prev_insn ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2914,7 +2989,7 @@ macro (ip)
|
|||||||
sub v0,$zero,$a0
|
sub v0,$zero,$a0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mips_emit_delays ();
|
mips_emit_delays (true);
|
||||||
++mips_noreorder;
|
++mips_noreorder;
|
||||||
mips_any_noreorder = 1;
|
mips_any_noreorder = 1;
|
||||||
|
|
||||||
@ -3372,7 +3447,7 @@ macro (ip)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mips_emit_delays ();
|
mips_emit_delays (true);
|
||||||
++mips_noreorder;
|
++mips_noreorder;
|
||||||
mips_any_noreorder = 1;
|
mips_any_noreorder = 1;
|
||||||
macro_build ((char *) NULL, &icnt, NULL,
|
macro_build ((char *) NULL, &icnt, NULL,
|
||||||
@ -3512,7 +3587,7 @@ macro (ip)
|
|||||||
s = "ddivu";
|
s = "ddivu";
|
||||||
s2 = "mfhi";
|
s2 = "mfhi";
|
||||||
do_divu3:
|
do_divu3:
|
||||||
mips_emit_delays ();
|
mips_emit_delays (true);
|
||||||
++mips_noreorder;
|
++mips_noreorder;
|
||||||
mips_any_noreorder = 1;
|
mips_any_noreorder = 1;
|
||||||
macro_build ((char *) NULL, &icnt, NULL, s, "z,s,t", sreg, treg);
|
macro_build ((char *) NULL, &icnt, NULL, s, "z,s,t", sreg, treg);
|
||||||
@ -5091,7 +5166,7 @@ macro2 (ip)
|
|||||||
case M_DMULO:
|
case M_DMULO:
|
||||||
dbl = 1;
|
dbl = 1;
|
||||||
case M_MULO:
|
case M_MULO:
|
||||||
mips_emit_delays ();
|
mips_emit_delays (true);
|
||||||
++mips_noreorder;
|
++mips_noreorder;
|
||||||
mips_any_noreorder = 1;
|
mips_any_noreorder = 1;
|
||||||
macro_build ((char *) NULL, &icnt, NULL,
|
macro_build ((char *) NULL, &icnt, NULL,
|
||||||
@ -5118,7 +5193,7 @@ macro2 (ip)
|
|||||||
case M_DMULOU:
|
case M_DMULOU:
|
||||||
dbl = 1;
|
dbl = 1;
|
||||||
case M_MULOU:
|
case M_MULOU:
|
||||||
mips_emit_delays ();
|
mips_emit_delays (true);
|
||||||
++mips_noreorder;
|
++mips_noreorder;
|
||||||
mips_any_noreorder = 1;
|
mips_any_noreorder = 1;
|
||||||
macro_build ((char *) NULL, &icnt, NULL,
|
macro_build ((char *) NULL, &icnt, NULL,
|
||||||
@ -5464,7 +5539,7 @@ macro2 (ip)
|
|||||||
* Is the double cfc1 instruction a bug in the mips assembler;
|
* Is the double cfc1 instruction a bug in the mips assembler;
|
||||||
* or is there a reason for it?
|
* or is there a reason for it?
|
||||||
*/
|
*/
|
||||||
mips_emit_delays ();
|
mips_emit_delays (true);
|
||||||
++mips_noreorder;
|
++mips_noreorder;
|
||||||
mips_any_noreorder = 1;
|
mips_any_noreorder = 1;
|
||||||
macro_build ((char *) NULL, &icnt, NULL, "cfc1", "t,G", treg, 31);
|
macro_build ((char *) NULL, &icnt, NULL, "cfc1", "t,G", treg, 31);
|
||||||
@ -5735,7 +5810,7 @@ mips16_macro (ip)
|
|||||||
case M_REM_3:
|
case M_REM_3:
|
||||||
s = "mfhi";
|
s = "mfhi";
|
||||||
do_div3:
|
do_div3:
|
||||||
mips_emit_delays ();
|
mips_emit_delays (true);
|
||||||
++mips_noreorder;
|
++mips_noreorder;
|
||||||
mips_any_noreorder = 1;
|
mips_any_noreorder = 1;
|
||||||
macro_build ((char *) NULL, &icnt, NULL,
|
macro_build ((char *) NULL, &icnt, NULL,
|
||||||
@ -5768,7 +5843,7 @@ mips16_macro (ip)
|
|||||||
s = "ddivu";
|
s = "ddivu";
|
||||||
s2 = "mfhi";
|
s2 = "mfhi";
|
||||||
do_divu3:
|
do_divu3:
|
||||||
mips_emit_delays ();
|
mips_emit_delays (true);
|
||||||
++mips_noreorder;
|
++mips_noreorder;
|
||||||
mips_any_noreorder = 1;
|
mips_any_noreorder = 1;
|
||||||
macro_build ((char *) NULL, &icnt, NULL, s, "0,x,y", xreg, yreg);
|
macro_build ((char *) NULL, &icnt, NULL, s, "0,x,y", xreg, yreg);
|
||||||
@ -7257,11 +7332,7 @@ mips16_immed (file, line, type, val, warn, small, ext, insn, use_extend,
|
|||||||
|
|
||||||
/* Branch offsets have an implicit 0 in the lowest bit. */
|
/* Branch offsets have an implicit 0 in the lowest bit. */
|
||||||
if (type == 'p' || type == 'q')
|
if (type == 'p' || type == 'q')
|
||||||
{
|
val /= 2;
|
||||||
if ((val & 1) != 0)
|
|
||||||
as_bad_where (file, line, "branch to odd address");
|
|
||||||
val /= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((val & ((1 << op->shift) - 1)) != 0
|
if ((val & ((1 << op->shift) - 1)) != 0
|
||||||
|| val < (mintiny << op->shift)
|
|| val < (mintiny << op->shift)
|
||||||
@ -8235,8 +8306,7 @@ md_apply_fix (fixP, valueP)
|
|||||||
* might be deleting the relocation entry (i.e., a branch within
|
* might be deleting the relocation entry (i.e., a branch within
|
||||||
* the current segment).
|
* the current segment).
|
||||||
*/
|
*/
|
||||||
/* TinyRISC can branch to odd addresses */
|
if ((value & 0x3) != 0)
|
||||||
if ((value & (mips16 ? 0x1 : 0x3)) != 0)
|
|
||||||
as_warn_where (fixP->fx_file, fixP->fx_line,
|
as_warn_where (fixP->fx_file, fixP->fx_line,
|
||||||
"Branch to odd address (%lx)", value);
|
"Branch to odd address (%lx)", value);
|
||||||
value >>= 2;
|
value >>= 2;
|
||||||
@ -8418,7 +8488,7 @@ mips_align (to, fill, label)
|
|||||||
int fill;
|
int fill;
|
||||||
symbolS *label;
|
symbolS *label;
|
||||||
{
|
{
|
||||||
mips_emit_delays ();
|
mips_emit_delays (false);
|
||||||
frag_align (to, fill);
|
frag_align (to, fill);
|
||||||
record_alignment (now_seg, to);
|
record_alignment (now_seg, to);
|
||||||
if (label != NULL)
|
if (label != NULL)
|
||||||
@ -8470,7 +8540,8 @@ s_align (x)
|
|||||||
if (temp)
|
if (temp)
|
||||||
{
|
{
|
||||||
auto_align = 1;
|
auto_align = 1;
|
||||||
mips_align (temp, (int) temp_fill, insn_label);
|
mips_align (temp, (int) temp_fill,
|
||||||
|
insn_labels != NULL ? insn_labels->label : NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -8483,8 +8554,8 @@ s_align (x)
|
|||||||
void
|
void
|
||||||
mips_flush_pending_output ()
|
mips_flush_pending_output ()
|
||||||
{
|
{
|
||||||
mips_emit_delays ();
|
mips_emit_delays (false);
|
||||||
insn_label = NULL;
|
mips_clear_insn_labels ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -8500,7 +8571,7 @@ s_change_sec (sec)
|
|||||||
&& (sec == 'd' || sec == 'r'))
|
&& (sec == 'd' || sec == 'r'))
|
||||||
sec = 's';
|
sec = 's';
|
||||||
|
|
||||||
mips_emit_delays ();
|
mips_emit_delays (false);
|
||||||
switch (sec)
|
switch (sec)
|
||||||
{
|
{
|
||||||
case 't':
|
case 't':
|
||||||
@ -8578,11 +8649,11 @@ s_cons (log_size)
|
|||||||
{
|
{
|
||||||
symbolS *label;
|
symbolS *label;
|
||||||
|
|
||||||
label = insn_label;
|
label = insn_labels != NULL ? insn_labels->label : NULL;
|
||||||
mips_emit_delays ();
|
mips_emit_delays (false);
|
||||||
if (log_size > 0 && auto_align)
|
if (log_size > 0 && auto_align)
|
||||||
mips_align (log_size, 0, label);
|
mips_align (log_size, 0, label);
|
||||||
insn_label = NULL;
|
mips_clear_insn_labels ();
|
||||||
cons (1 << log_size);
|
cons (1 << log_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8592,9 +8663,9 @@ s_float_cons (type)
|
|||||||
{
|
{
|
||||||
symbolS *label;
|
symbolS *label;
|
||||||
|
|
||||||
label = insn_label;
|
label = insn_labels != NULL ? insn_labels->label : NULL;
|
||||||
|
|
||||||
mips_emit_delays ();
|
mips_emit_delays (false);
|
||||||
|
|
||||||
if (auto_align)
|
if (auto_align)
|
||||||
if (type == 'd')
|
if (type == 'd')
|
||||||
@ -8602,7 +8673,7 @@ s_float_cons (type)
|
|||||||
else
|
else
|
||||||
mips_align (2, 0, label);
|
mips_align (2, 0, label);
|
||||||
|
|
||||||
insn_label = NULL;
|
mips_clear_insn_labels ();
|
||||||
|
|
||||||
float_cons (type);
|
float_cons (type);
|
||||||
}
|
}
|
||||||
@ -8717,7 +8788,7 @@ s_mipsset (x)
|
|||||||
}
|
}
|
||||||
else if (strcmp (name, "noreorder") == 0)
|
else if (strcmp (name, "noreorder") == 0)
|
||||||
{
|
{
|
||||||
mips_emit_delays ();
|
mips_emit_delays (true);
|
||||||
mips_noreorder = 1;
|
mips_noreorder = 1;
|
||||||
mips_any_noreorder = 1;
|
mips_any_noreorder = 1;
|
||||||
}
|
}
|
||||||
@ -8901,11 +8972,11 @@ s_gpword (ignore)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
label = insn_label;
|
label = insn_labels != NULL ? insn_labels->label : NULL;
|
||||||
mips_emit_delays ();
|
mips_emit_delays (true);
|
||||||
if (auto_align)
|
if (auto_align)
|
||||||
mips_align (2, 0, label);
|
mips_align (2, 0, label);
|
||||||
insn_label = NULL;
|
mips_clear_insn_labels ();
|
||||||
|
|
||||||
expression (&ex);
|
expression (&ex);
|
||||||
|
|
||||||
@ -9213,7 +9284,13 @@ mips16_extended_frag (fragp, sec, stretch)
|
|||||||
case it can not be extended) use the address of the
|
case it can not be extended) use the address of the
|
||||||
instruction whose delay slot it is in. */
|
instruction whose delay slot it is in. */
|
||||||
if (type == 'p' || type == 'q')
|
if (type == 'p' || type == 'q')
|
||||||
addr += 2;
|
{
|
||||||
|
addr += 2;
|
||||||
|
/* Ignore the low bit in the target, since it will be set
|
||||||
|
for a text label. */
|
||||||
|
if ((val & 1) != 0)
|
||||||
|
--val;
|
||||||
|
}
|
||||||
else if (RELAX_MIPS16_JAL_DSLOT (fragp->fr_subtype))
|
else if (RELAX_MIPS16_JAL_DSLOT (fragp->fr_subtype))
|
||||||
addr -= 4;
|
addr -= 4;
|
||||||
else if (RELAX_MIPS16_DSLOT (fragp->fr_subtype))
|
else if (RELAX_MIPS16_DSLOT (fragp->fr_subtype))
|
||||||
@ -9617,7 +9694,13 @@ md_convert_frag (abfd, asec, fragp)
|
|||||||
/* The rules for the base address of a PC relative reloc are
|
/* The rules for the base address of a PC relative reloc are
|
||||||
complicated; see mips16_extended_frag. */
|
complicated; see mips16_extended_frag. */
|
||||||
if (type == 'p' || type == 'q')
|
if (type == 'p' || type == 'q')
|
||||||
addr += 2;
|
{
|
||||||
|
addr += 2;
|
||||||
|
/* Ignore the low bit in the target, since it will be
|
||||||
|
set for a text label. */
|
||||||
|
if ((val & 1) != 0)
|
||||||
|
--val;
|
||||||
|
}
|
||||||
else if (RELAX_MIPS16_JAL_DSLOT (fragp->fr_subtype))
|
else if (RELAX_MIPS16_JAL_DSLOT (fragp->fr_subtype))
|
||||||
addr -= 4;
|
addr -= 4;
|
||||||
else if (RELAX_MIPS16_DSLOT (fragp->fr_subtype))
|
else if (RELAX_MIPS16_DSLOT (fragp->fr_subtype))
|
||||||
@ -9678,6 +9761,39 @@ md_convert_frag (abfd, asec, fragp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef OBJ_ELF
|
||||||
|
|
||||||
|
/* This function is called after the relocs have been generated.
|
||||||
|
We've been storing mips16 text labels as odd. Here we convert them
|
||||||
|
back to even for the convenience of the debugger. */
|
||||||
|
|
||||||
|
void
|
||||||
|
mips_frob_file_after_relocs ()
|
||||||
|
{
|
||||||
|
asymbol **syms;
|
||||||
|
unsigned int count, i;
|
||||||
|
|
||||||
|
if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
|
||||||
|
return;
|
||||||
|
|
||||||
|
syms = bfd_get_outsymbols (stdoutput);
|
||||||
|
count = bfd_get_symcount (stdoutput);
|
||||||
|
for (i = 0; i < count; i++, syms++)
|
||||||
|
{
|
||||||
|
if (elf_symbol (*syms)->internal_elf_sym.st_other == STO_MIPS16
|
||||||
|
&& ((*syms)->value & 1) != 0)
|
||||||
|
{
|
||||||
|
(*syms)->value &= ~1;
|
||||||
|
/* If the symbol has an odd size, it was probably computed
|
||||||
|
incorrectly, so adjust that as well. */
|
||||||
|
if ((elf_symbol (*syms)->internal_elf_sym.st_size & 1) != 0)
|
||||||
|
++elf_symbol (*syms)->internal_elf_sym.st_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* This function is called whenever a label is defined. It is used
|
/* This function is called whenever a label is defined. It is used
|
||||||
when handling branch delays; if a branch has a label, we assume we
|
when handling branch delays; if a branch has a label, we assume we
|
||||||
can not move it. */
|
can not move it. */
|
||||||
@ -9686,11 +9802,19 @@ void
|
|||||||
mips_define_label (sym)
|
mips_define_label (sym)
|
||||||
symbolS *sym;
|
symbolS *sym;
|
||||||
{
|
{
|
||||||
insn_label = sym;
|
struct insn_label_list *l;
|
||||||
#ifdef OBJ_ELF
|
|
||||||
if (mips16)
|
if (free_insn_labels == NULL)
|
||||||
S_SET_OTHER (insn_label, STO_MIPS16);
|
l = (struct insn_label_list *) xmalloc (sizeof *l);
|
||||||
#endif
|
else
|
||||||
|
{
|
||||||
|
l = free_insn_labels;
|
||||||
|
free_insn_labels = l->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
l->label = sym;
|
||||||
|
l->next = insn_labels;
|
||||||
|
insn_labels = l;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Decide whether a label is local. This is called by LOCAL_LABEL.
|
/* Decide whether a label is local. This is called by LOCAL_LABEL.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* tc-mips.c -- header file for tc-mips.c.
|
/* tc-mips.h -- header file for tc-mips.c.
|
||||||
Copyright (C) 1993 Free Software Foundation, Inc.
|
Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||||
Contributed by the OSF and Ralph Campbell.
|
Contributed by the OSF and Ralph Campbell.
|
||||||
Written by Keith Knowles and Ralph Campbell, working independently.
|
Written by Keith Knowles and Ralph Campbell, working independently.
|
||||||
Modified for ECOFF support by Ian Lance Taylor of Cygnus Support.
|
Modified for ECOFF support by Ian Lance Taylor of Cygnus Support.
|
||||||
@ -17,8 +17,9 @@
|
|||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with GAS; see the file COPYING. If not, write to
|
along with GAS; see the file COPYING. If not, write to the Free
|
||||||
the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
02111-1307, USA. */
|
||||||
|
|
||||||
#ifndef TC_MIPS
|
#ifndef TC_MIPS
|
||||||
|
|
||||||
@ -34,6 +35,11 @@
|
|||||||
#define MAX_RELOC_EXPANSION 3
|
#define MAX_RELOC_EXPANSION 3
|
||||||
#define LOCAL_LABELS_FB 1
|
#define LOCAL_LABELS_FB 1
|
||||||
|
|
||||||
|
/* We don't want to define LOCAL_LABELS_DOLLAR, because $0 is really a
|
||||||
|
reference to a register, not a label. */
|
||||||
|
#undef LOCAL_LABELS_DOLLAR
|
||||||
|
#define LOCAL_LABELS_DOLLAR 0
|
||||||
|
|
||||||
/* Maximum symbol offset that can be encoded in a BFD_RELOC_MIPS_GPREL
|
/* Maximum symbol offset that can be encoded in a BFD_RELOC_MIPS_GPREL
|
||||||
relocation: */
|
relocation: */
|
||||||
#define MAX_GPREL_OFFSET (0x7FF4)
|
#define MAX_GPREL_OFFSET (0x7FF4)
|
||||||
@ -41,7 +47,9 @@
|
|||||||
#define LOCAL_LABEL(name) mips_local_label (name)
|
#define LOCAL_LABEL(name) mips_local_label (name)
|
||||||
extern int mips_local_label PARAMS ((const char *));
|
extern int mips_local_label PARAMS ((const char *));
|
||||||
|
|
||||||
#define md_relax_frag(fragp, stretch) (0)
|
#define md_relax_frag(fragp, stretch) mips_relax_frag(fragp, stretch)
|
||||||
|
extern int mips_relax_frag PARAMS ((struct frag *, long));
|
||||||
|
|
||||||
#define md_undefined_symbol(name) (0)
|
#define md_undefined_symbol(name) (0)
|
||||||
#define md_operand(x)
|
#define md_operand(x)
|
||||||
|
|
||||||
@ -63,9 +71,13 @@ extern int mips_local_label PARAMS ((const char *));
|
|||||||
#define TARGET_FORMAT mips_target_format()
|
#define TARGET_FORMAT mips_target_format()
|
||||||
extern const char *mips_target_format ();
|
extern const char *mips_target_format ();
|
||||||
|
|
||||||
struct mips_cl_insn {
|
struct mips_cl_insn
|
||||||
unsigned long insn_opcode;
|
{
|
||||||
const struct mips_opcode *insn_mo;
|
unsigned long insn_opcode;
|
||||||
|
const struct mips_opcode *insn_mo;
|
||||||
|
/* The next two fields are used when generating mips16 code. */
|
||||||
|
boolean use_extend;
|
||||||
|
unsigned short extend;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int tc_get_register PARAMS ((int frame));
|
extern int tc_get_register PARAMS ((int frame));
|
||||||
@ -79,9 +91,18 @@ extern void mips_define_label PARAMS ((struct symbol *));
|
|||||||
#define tc_frob_file() mips_frob_file ()
|
#define tc_frob_file() mips_frob_file ()
|
||||||
extern void mips_frob_file PARAMS ((void));
|
extern void mips_frob_file PARAMS ((void));
|
||||||
|
|
||||||
|
#ifdef OBJ_ELF
|
||||||
|
#define tc_frob_file_after_relocs mips_frob_file_after_relocs
|
||||||
|
extern void mips_frob_file_after_relocs PARAMS ((void));
|
||||||
|
#endif
|
||||||
|
|
||||||
#define TC_CONS_FIX_NEW cons_fix_new_mips
|
#define TC_CONS_FIX_NEW cons_fix_new_mips
|
||||||
extern void cons_fix_new_mips ();
|
extern void cons_fix_new_mips ();
|
||||||
|
|
||||||
|
/* Don't adjust MIPS16 jump relocations to section addresses, so we
|
||||||
|
don't have to worry about the format of the offset in the .o file. */
|
||||||
|
#define tc_fix_adjustable(fixp) ((fixp)->fx_r_type != BFD_RELOC_MIPS16_JMP)
|
||||||
|
|
||||||
/* When generating embedded PIC code we must keep PC relative
|
/* When generating embedded PIC code we must keep PC relative
|
||||||
relocations. */
|
relocations. */
|
||||||
#define TC_FORCE_RELOCATION(fixp) mips_force_relocation (fixp)
|
#define TC_FORCE_RELOCATION(fixp) mips_force_relocation (fixp)
|
||||||
|
Reference in New Issue
Block a user