All ELF relocs.

This commit is contained in:
Michael Meissner
1995-02-15 20:15:07 +00:00
parent bcbe2c719c
commit 4a6b2f8bbd
2 changed files with 187 additions and 8 deletions

View File

@ -1,3 +1,24 @@
Wed Feb 15 15:07:00 1995 Michael Meissner <meissner@tiktok.cygnus.com>
* config/tc-ppc.c (md_pseudo_table): If ELF, go to ppc_elf_cons
instead of cons.
(md_show_usage): Show all of the PowerPc options.
(ppc_elf_suffix): New function to recognize ELF suffixes that
specify a relocation, such as @GOT.
(ppc_elf_cons): Replacement for the standard cons function that
knows about the ELF suffixes.
(ppc_fixup): Add reloc field to hold non-standard relocation.
(md_assemble): Handle ELF suffixes like @GOT.
(md_create_short_jump): Dummy in case WORKING_DOT_WORD is not
defined.
(md_create_long_jump): Ditto.
(md_short_jump_size): Ditto.
(md_long_jump_size): Ditto.
(md_apply_fix): Handle BFD_RELOC_32_PCREL, BFD_RELOC_LO16,
BFD_RELOC_HI16, BFD_RELOC_HI16_S, BFD_RELOC_PPC_TOC16, and
BFD_RELOC_16 relocations. If relocation can not be found, print
the decimal value of the relocation.
Wed Feb 15 11:46:02 1995 Ian Lance Taylor <ian@cygnus.com> Wed Feb 15 11:46:02 1995 Ian Lance Taylor <ian@cygnus.com>
* config/tc-mips.c (macro): Don't use the target register as a * config/tc-mips.c (macro): Don't use the target register as a

View File

@ -55,6 +55,10 @@ static void ppc_stabx PARAMS ((int));
static void ppc_rename PARAMS ((int)); static void ppc_rename PARAMS ((int));
static void ppc_toc PARAMS ((int)); static void ppc_toc PARAMS ((int));
#endif #endif
#ifdef OBJ_ELF
static bfd_reloc_code_real_type ppc_elf_suffix PARAMS ((char **));
static void ppc_elf_cons PARAMS ((int));
#endif
/* Generic assembler global variables which must be defined by all /* Generic assembler global variables which must be defined by all
targets. */ targets. */
@ -107,6 +111,12 @@ const pseudo_typeS md_pseudo_table[] =
{ "stabx", ppc_stabx, 0 }, { "stabx", ppc_stabx, 0 },
{ "toc", ppc_toc, 0 }, { "toc", ppc_toc, 0 },
#endif #endif
#ifdef OBJ_ELF
{ "long", ppc_elf_cons, 4 },
{ "word", ppc_elf_cons, 2 },
{ "short", ppc_elf_cons, 2 },
{ "byte", ppc_elf_cons, 1 },
#endif
/* This pseudo-op is used even when not generating XCOFF output. */ /* This pseudo-op is used even when not generating XCOFF output. */
{ "tc", ppc_tc, 0 }, { "tc", ppc_tc, 0 },
@ -187,6 +197,10 @@ static bfd_size_type ppc_debug_name_section_size;
symbolS *GOT_symbol; /* Pre-defined "_GLOBAL_OFFSET_TABLE" */ symbolS *GOT_symbol; /* Pre-defined "_GLOBAL_OFFSET_TABLE" */
#endif /* OBJ_ELF */ #endif /* OBJ_ELF */
#ifndef WORKING_DOT_WORD
const int md_short_jump_size = 4;
const int md_long_jump_size = 4;
#endif
#ifdef OBJ_ELF #ifdef OBJ_ELF
CONST char *md_shortopts = "um:VQ:"; CONST char *md_shortopts = "um:VQ:";
@ -277,7 +291,8 @@ PowerPC options:\n\
-mpwrx generate code for IBM POWER/2 (RIOS2)\n\ -mpwrx generate code for IBM POWER/2 (RIOS2)\n\
-mpwr generate code for IBM POWER (RIOS1)\n\ -mpwr generate code for IBM POWER (RIOS1)\n\
-m601 generate code for Motorola PowerPC 601\n\ -m601 generate code for Motorola PowerPC 601\n\
-mppc generate code for Motorola PowerPC 603/604\n\ -mppc, -mppc32, -m603, -m604\n\
generate code for Motorola PowerPC 603/604\n\
-many generate code for any architecture (PWR/PWRX/PPC)\n"); -many generate code for any architecture (PWR/PWRX/PPC)\n");
#ifdef OBJ_ELF #ifdef OBJ_ELF
fprintf(stream, "\ fprintf(stream, "\
@ -469,6 +484,91 @@ ppc_insert_operand (insn, operand, val, file, line)
return insn; return insn;
} }
#ifdef OBJ_ELF
/* Parse @got, etc. and return the desired relocation. */
static bfd_reloc_code_real_type
ppc_elf_suffix (str_p)
char **str_p;
{
char *str = *str_p;
if (*str != '@')
return BFD_RELOC_UNUSED;
if (strncmp (str, "@GOT", 4) == 0 || strncmp (str, "@got", 4) == 0)
{
*str_p += 4;
return BFD_RELOC_PPC_TOC16;
}
else if (strncmp (str, "@L", 2) == 0 || strncmp (str, "@l", 2) == 0)
{
*str_p += 2;
return BFD_RELOC_LO16;
}
else if (strncmp (str, "@HA", 3) == 0 || strncmp (str, "@ha", 3) == 0)
{
*str_p += 3;
return BFD_RELOC_HI16_S;
}
else if (strncmp (str, "@H", 2) == 0 || strncmp (str, "@h", 2) == 0)
{
*str_p += 2;
return BFD_RELOC_HI16;
}
else if (strncmp (str, "@PCREL", 6) == 0 || strncmp (str, "@pcrel", 6) == 0)
{ /* this is a hack */
*str_p += 6;
return BFD_RELOC_32_PCREL;
}
return BFD_RELOC_UNUSED;
}
/* Like normal .long, except support @got, etc. */
/* worker to do .byte etc statements */
/* clobbers input_line_pointer, checks */
/* end-of-line. */
static void
ppc_elf_cons (nbytes)
register int nbytes; /* 1=.byte, 2=.word, 4=.long */
{
expressionS exp;
bfd_reloc_code_real_type reloc;
if (is_it_end_of_statement ())
{
demand_empty_rest_of_line ();
return;
}
do
{
expression (&exp);
if (nbytes == 4
&& exp.X_op == O_symbol
&& *input_line_pointer == '@'
&& (reloc = ppc_elf_suffix (&input_line_pointer)) != BFD_RELOC_UNUSED)
{
register char *p = frag_more ((int) nbytes);
reloc_howto_type *reloc_howto = bfd_reloc_type_lookup (stdoutput, reloc);
int offset = (!reloc_howto) ? 0 : (nbytes - bfd_get_reloc_size (reloc_howto));
if (offset < 0)
offset = 0;
fix_new_exp (frag_now, p - frag_now->fr_literal + offset, (int) nbytes - offset, &exp, 0, reloc);
}
else
emit_expr (&exp, (unsigned int) nbytes);
}
while (*input_line_pointer++ == ',');
input_line_pointer--; /* Put terminator back into stream. */
demand_empty_rest_of_line ();
}
#endif /* OBJ_ELF */
/* We need to keep a list of fixups. We can't simply generate them as /* We need to keep a list of fixups. We can't simply generate them as
we go, because that would require us to first create the frag, and we go, because that would require us to first create the frag, and
that would screw up references to ``.''. */ that would screw up references to ``.''. */
@ -477,6 +577,7 @@ struct ppc_fixup
{ {
expressionS exp; expressionS exp;
int opindex; int opindex;
bfd_reloc_code_real_type reloc;
}; };
#define MAX_INSN_FIXUPS (5) #define MAX_INSN_FIXUPS (5)
@ -498,6 +599,7 @@ md_assemble (str)
int fc; int fc;
char *f; char *f;
int i; int i;
bfd_reloc_code_real_type reloc;
/* Get the opcode. */ /* Get the opcode. */
for (s = str; *s != '\0' && ! isspace (*s); s++) for (s = str; *s != '\0' && ! isspace (*s); s++)
@ -632,6 +734,20 @@ md_assemble (str)
else if (ex.X_op == O_constant) else if (ex.X_op == O_constant)
insn = ppc_insert_operand (insn, operand, ex.X_add_number, insn = ppc_insert_operand (insn, operand, ex.X_add_number,
(char *) NULL, 0); (char *) NULL, 0);
#ifdef OBJ_ELF
else if ((reloc = ppc_elf_suffix (&str)) != BFD_RELOC_UNUSED)
{
/* We need to generate a fixup for this expression. */
if (fc >= MAX_INSN_FIXUPS)
as_fatal ("too many fixups");
fixups[fc].exp = ex;
fixups[fc].opindex = 0;
fixups[fc].reloc = reloc;
++fc;
}
#endif /* OBJ_ELF */
else else
{ {
/* We need to generate a fixup for this expression. */ /* We need to generate a fixup for this expression. */
@ -639,6 +755,7 @@ md_assemble (str)
as_fatal ("too many fixups"); as_fatal ("too many fixups");
fixups[fc].exp = ex; fixups[fc].exp = ex;
fixups[fc].opindex = *opindex_ptr; fixups[fc].opindex = *opindex_ptr;
fixups[fc].reloc = BFD_RELOC_UNUSED;
++fc; ++fc;
} }
@ -688,6 +805,19 @@ md_assemble (str)
const struct powerpc_operand *operand; const struct powerpc_operand *operand;
operand = &powerpc_operands[fixups[i].opindex]; operand = &powerpc_operands[fixups[i].opindex];
if (fixups[i].reloc != BFD_RELOC_UNUSED)
{
reloc_howto_type *reloc_howto = bfd_reloc_type_lookup (stdoutput, fixups[i].reloc);
int offset = (!reloc_howto) ? 0 : (4 - bfd_get_reloc_size (reloc_howto));
if (offset < 0)
offset = 0;
fix_new_exp (frag_now, f - frag_now->fr_literal + offset, 4 - offset,
&fixups[i].exp, (reloc_howto && reloc_howto->pc_relative),
fixups[i].reloc);
}
else
fix_new_exp (frag_now, f - frag_now->fr_literal, 4, fix_new_exp (frag_now, f - frag_now->fr_literal, 4,
&fixups[i].exp, &fixups[i].exp,
(operand->flags & PPC_OPERAND_RELATIVE) != 0, (operand->flags & PPC_OPERAND_RELATIVE) != 0,
@ -696,6 +826,29 @@ md_assemble (str)
} }
} }
#ifndef WORKING_DOT_WORD
/* Handle long and short jumps */
void
md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
char *ptr;
addressT from_addr, to_addr;
fragS *frag;
symbolS *to_symbol;
{
abort ();
}
void
md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
char *ptr;
addressT from_addr, to_addr;
fragS *frag;
symbolS *to_symbol;
{
abort ();
}
#endif
/* Handle a macro. Gather all the operands, transform them as /* Handle a macro. Gather all the operands, transform them as
described by the macro, and call md_assemble recursively. All the described by the macro, and call md_assemble recursively. All the
operands are separated by commas; we don't accept parentheses operands are separated by commas; we don't accept parentheses
@ -1789,7 +1942,7 @@ ppc_symbol_new_hook (sym)
sym->sy_tc.class = XMC_TI; sym->sy_tc.class = XMC_TI;
else if (strcmp (s, "TB]") == 0) else if (strcmp (s, "TB]") == 0)
sym->sy_tc.class = XMC_TB; sym->sy_tc.class = XMC_TB;
else if (strcmp (s, "TC0]") == 0 || strcm (s, "T0]") == 0) else if (strcmp (s, "TC0]") == 0 || strcmp (s, "T0]") == 0)
sym->sy_tc.class = XMC_TC0; sym->sy_tc.class = XMC_TC0;
break; break;
case 'U': case 'U':
@ -2492,9 +2645,14 @@ md_apply_fix (fixp, valuep)
switch (fixp->fx_r_type) switch (fixp->fx_r_type)
{ {
case BFD_RELOC_32: case BFD_RELOC_32:
case BFD_RELOC_32_PCREL:
md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where, md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
value, 4); value, 4);
break; break;
case BFD_RELOC_LO16:
case BFD_RELOC_HI16:
case BFD_RELOC_HI16_S:
case BFD_RELOC_PPC_TOC16:
case BFD_RELOC_16: case BFD_RELOC_16:
md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where, md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
value, 2); value, 2);
@ -2542,7 +2700,7 @@ tc_gen_reloc (seg, fixp)
if (reloc->howto == (reloc_howto_type *) NULL) if (reloc->howto == (reloc_howto_type *) NULL)
{ {
as_bad_where (fixp->fx_file, fixp->fx_line, as_bad_where (fixp->fx_file, fixp->fx_line,
"reloc not supported by object file format"); "reloc %d not supported by object file format", (int)fixp->fx_r_type);
return NULL; return NULL;
} }
reloc->addend = fixp->fx_addnumber; reloc->addend = fixp->fx_addnumber;