* config/tc-mn10300.h (DIFF_EXPR_OK): Don't define this.

(tc_fix_adjustable): Don't adjust relocs against weak symbols or
        pc-relative relocs.
        * config/tc-mn10300.c (md_begin): Set linkrelax.
        (md_assemble): Create fixups as needed.
        (md_apply_fix3): Gut.  It shouldn't ever get called anymore.
First stab at fixups/relocs.
This commit is contained in:
Jeff Law 1996-11-21 18:58:26 +00:00
parent d3931e9311
commit d9a9c18fad
2 changed files with 121 additions and 84 deletions

View File

@ -1,3 +1,12 @@
Thu Nov 21 11:56:11 1996 Jeffrey A Law (law@cygnus.com)
* config/tc-mn10300.h (DIFF_EXPR_OK): Don't define this.
(tc_fix_adjustable): Don't adjust relocs against weak symbols or
pc-relative relocs.
* config/tc-mn10300.c (md_begin): Set linkrelax.
(md_assemble): Create fixups as needed.
(md_apply_fix3): Gut. It shouldn't ever get called anymore.
start-sanitize-d10v
Tue Nov 19 17:48:06 1996 Michael Meissner <meissner@tiktok.cygnus.com>

View File

@ -387,7 +387,7 @@ md_begin ()
on the operands. This hash table then provides a quick index to
the first opcode with a particular name in the opcode table. */
op = mn10300_opcodes;
op = mn10300_opcodes;
while (op->name)
{
if (strcmp (prev_name, op->name))
@ -397,6 +397,11 @@ md_begin ()
}
op++;
}
/* This is both a simplification (we don't have to write md_apply_fix)
and support for future optimizations (branch shortening and similar
stuff in the linker. */
linkrelax = 1;
}
void
@ -780,6 +785,110 @@ keep_going:
number_to_chars_bigendian (f, insn, size > 4 ? 4 : size);
if (size > 4)
number_to_chars_bigendian (f + 4, extension, size - 4);
/* Create any fixups. */
for (i = 0; i < fc; i++)
{
const struct mn10300_operand *operand;
operand = &mn10300_operands[fixups[i].opindex];
if (fixups[i].reloc != BFD_RELOC_UNUSED)
{
reloc_howto_type *reloc_howto;
int size;
int offset;
fixS *fixP;
reloc_howto = bfd_reloc_type_lookup (stdoutput, fixups[i].reloc);
if (!reloc_howto)
abort();
size = bfd_get_reloc_size (reloc_howto);
if (size < 1 || size > 4)
abort();
offset = 4 - size;
fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset, size,
&fixups[i].exp,
reloc_howto->pc_relative,
fixups[i].reloc);
}
else
{
int reloc, pcrel, reloc_size, offset;
/* How big is the reloc? Remember SPLIT relocs are
implicitly 32bits. */
if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
reloc_size = 32;
else
reloc_size = operand->bits;
/* Is the reloc pc-relative? */
pcrel = (operand->flags & MN10300_OPERAND_PCREL) != 0;
/* Gross. This disgusting hack is to make sure we
get the right offset for the 16/32 bit reloc in
"call" instructions. Basically they're a pain
because the reloc isn't at the end of the instruction. */
if ((size == 5 || size == 7)
&& (((insn >> 24) & 0xff) == 0xcd
|| ((insn >> 24) & 0xff) == 0xdd))
size -= 2;
/* Similarly for certain bit instructions which don't
hav their 32bit reloc at the tail of the instruction. */
if (size == 7
&& (((insn >> 16) & 0xffff) == 0xfe00
|| ((insn >> 16) & 0xffff) == 0xfe01
|| ((insn >> 16) & 0xffff) == 0xfe02))
size -= 1;
/* Determine offset from start of this insn to insert the
reloc. Except for a few exceptions we insert the reloc
at the tail of the instruction. */
offset = size - reloc_size / 8;
/* Choose a proper BFD relocation type. */
if (pcrel)
{
if (reloc_size == 32)
reloc = BFD_RELOC_32_PCREL;
else if (reloc_size == 16)
reloc = BFD_RELOC_16_PCREL;
else if (reloc_size == 8)
reloc = BFD_RELOC_8_PCREL;
else
abort ();
}
else
{
if (reloc_size == 32)
reloc = BFD_RELOC_32;
else if (reloc_size == 16)
reloc = BFD_RELOC_16;
else if (reloc_size == 8)
reloc = BFD_RELOC_8;
else
abort ();
}
/* Convert the size of the reloc into what fix_new_exp wants. */
reloc_size = reloc_size / 8;
if (reloc_size == 8)
reloc_size = 0;
else if (reloc_size == 16)
reloc_size = 1;
else if (reloc_size == 32)
reloc_size = 2;
fix_new_exp (frag_now, f - frag_now->fr_literal + offset, reloc_size,
&fixups[i].exp, pcrel,
((bfd_reloc_code_real_type) reloc));
}
}
}
@ -833,91 +942,10 @@ md_apply_fix3 (fixp, valuep, seg)
valueT *valuep;
segT seg;
{
valueT value;
char *where;
/* We shouldn't ever get here because linkrelax is nonzero. */
abort ();
fixp->fx_done = 1;
return 0;
if (fixp->fx_addsy == (symbolS *) NULL)
{
value = *valuep;
fixp->fx_done = 1;
}
else if (fixp->fx_pcrel)
value = *valuep;
else
{
value = fixp->fx_offset;
if (fixp->fx_subsy != (symbolS *) NULL)
{
if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
value -= S_GET_VALUE (fixp->fx_subsy);
else
{
/* We don't actually support subtracting a symbol. */
as_bad_where (fixp->fx_file, fixp->fx_line,
"expression too complex");
}
}
}
/* printf("md_apply_fix: value=0x%x type=%d\n", value, fixp->fx_r_type); */
if ((int) fixp->fx_r_type >= (int) BFD_RELOC_UNUSED)
{
int opindex;
const struct mn10300_operand *operand;
char *where;
unsigned long insn, extension;
opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
operand = &mn10300_operands[opindex];
/* Fetch the instruction, insert the fully resolved operand
value, and stuff the instruction back again.
Note the instruction has been stored in little endian
format! */
where = fixp->fx_frag->fr_literal + fixp->fx_where;
insn = bfd_getl32((unsigned char *) where);
extension = 0;
mn10300_insert_operand (&insn, &extension, operand,
(offsetT) value, fixp->fx_file,
fixp->fx_line, 0);
bfd_putl32((bfd_vma) insn, (unsigned char *) where);
if (fixp->fx_done)
{
/* Nothing else to do here. */
return 1;
}
/* Determine a BFD reloc value based on the operand information.
We are only prepared to turn a few of the operands into relocs. */
{
as_bad_where(fixp->fx_file, fixp->fx_line,
"unresolved expression that must be resolved");
fixp->fx_done = 1;
return 1;
}
}
else if (fixp->fx_done)
{
/* We still have to insert the value into memory! */
where = fixp->fx_frag->fr_literal + fixp->fx_where;
if (fixp->fx_size == 1)
*where = value & 0xff;
if (fixp->fx_size == 2)
bfd_putl16(value & 0xffff, (unsigned char *) where);
if (fixp->fx_size == 4)
bfd_putl32(value, (unsigned char *) where);
}
fixp->fx_addnumber = value;
return 1;
}
/* Insert an operand value into an instruction. */