Support all of the V.4 relocations
This commit is contained in:
parent
e6cb7b411b
commit
65c91be516
3 changed files with 94 additions and 86 deletions
|
@ -1,3 +1,20 @@
|
||||||
|
Tue Sep 26 14:57:59 1995 Michael Meissner <meissner@tiktok.cygnus.com>
|
||||||
|
|
||||||
|
* config/tc-ppc.c (ppc_elf_suffix): Support all of the V.4
|
||||||
|
relocations.
|
||||||
|
(ppc_elf_cons): Remove restriction that @ suffixes must be done
|
||||||
|
with .long. Add error if relocation does not fit in the number of
|
||||||
|
bytes provided.
|
||||||
|
(md_assemble): For absolute branches, map PC relative relocations
|
||||||
|
back into an equivalent absolute relocation.
|
||||||
|
(md_pcrel_from): If TC_FORCE_RELOCATION is true, relocation offset
|
||||||
|
is 0, not segment start.
|
||||||
|
(md_apply_fix3): Don't bother writing addend into the instruction,
|
||||||
|
since it is ignored, given that we use RELA relocations for ELF.
|
||||||
|
|
||||||
|
* config/tc-ppc.h (TC_FORCE_RELOCATION): Define to force all
|
||||||
|
branch prediction relocations to always be emitted.
|
||||||
|
|
||||||
Mon Sep 25 16:08:43 1995 Michael Meissner <meissner@tiktok.cygnus.com>
|
Mon Sep 25 16:08:43 1995 Michael Meissner <meissner@tiktok.cygnus.com>
|
||||||
|
|
||||||
* config/tc-ppc.c (ppc_elf_suffix): Lower case reloc before
|
* config/tc-ppc.c (ppc_elf_suffix): Lower case reloc before
|
||||||
|
|
|
@ -567,23 +567,46 @@ ppc_elf_suffix (str_p)
|
||||||
int len;
|
int len;
|
||||||
struct map_bfd *ptr;
|
struct map_bfd *ptr;
|
||||||
|
|
||||||
|
#define MAP(str,reloc) { str, sizeof(str)-1, reloc }
|
||||||
|
|
||||||
static struct map_bfd mapping[] = {
|
static struct map_bfd mapping[] = {
|
||||||
{ "got", 3, BFD_RELOC_PPC_TOC16 },
|
MAP ("got", BFD_RELOC_PPC_TOC16),
|
||||||
{ "l", 1, BFD_RELOC_LO16 },
|
MAP ("l", BFD_RELOC_LO16),
|
||||||
{ "ha", 2, BFD_RELOC_HI16_S },
|
MAP ("h", BFD_RELOC_HI16),
|
||||||
{ "h", 1, BFD_RELOC_HI16 },
|
MAP ("ha", BFD_RELOC_HI16_S),
|
||||||
{ "sdarel", 6, BFD_RELOC_GPREL16 },
|
MAP ("brtaken", BFD_RELOC_PPC_B16_BRTAKEN),
|
||||||
{ "fixup", 5, BFD_RELOC_CTOR }, /* warnings with -mrelocatable */
|
MAP ("brntaken", BFD_RELOC_PPC_B16_BRNTAKEN),
|
||||||
{ "brtaken", 7, BFD_RELOC_PPC_B16_BRTAKEN },
|
MAP ("got@l", BFD_RELOC_LO16_GOTOFF),
|
||||||
{ "brntaken", 8, BFD_RELOC_PPC_B16_BRNTAKEN },
|
MAP ("got@h", BFD_RELOC_HI16_GOTOFF),
|
||||||
|
MAP ("got@ha", BFD_RELOC_HI16_S_GOTOFF),
|
||||||
|
MAP ("fixup", BFD_RELOC_CTOR), /* warnings with -mrelocatable */
|
||||||
|
MAP ("pltrel24", BFD_RELOC_24_PLT_PCREL),
|
||||||
|
MAP ("copy", BFD_RELOC_PPC_COPY),
|
||||||
|
MAP ("globdat", BFD_RELOC_PPC_GLOB_DAT),
|
||||||
|
MAP ("local24pc", BFD_RELOC_PPC_LOCAL24PC),
|
||||||
|
MAP ("plt", BFD_RELOC_32_PLTOFF),
|
||||||
|
MAP ("pltrel", BFD_RELOC_32_PLT_PCREL),
|
||||||
|
MAP ("plt@l", BFD_RELOC_LO16_PLTOFF),
|
||||||
|
MAP ("plt@h", BFD_RELOC_HI16_PLTOFF),
|
||||||
|
MAP ("plt@ha", BFD_RELOC_HI16_S_PLTOFF),
|
||||||
|
MAP ("sdarel", BFD_RELOC_GPREL16),
|
||||||
|
MAP ("sectoff", BFD_RELOC_32_BASEREL),
|
||||||
|
MAP ("sectoff@l", BFD_RELOC_LO16_BASEREL),
|
||||||
|
MAP ("sectoff@h", BFD_RELOC_HI16_BASEREL),
|
||||||
|
MAP ("sectoff@ha", BFD_RELOC_HI16_S_BASEREL),
|
||||||
|
|
||||||
{ (char *)0, 0, BFD_RELOC_UNUSED }
|
{ (char *)0, 0, BFD_RELOC_UNUSED }
|
||||||
};
|
};
|
||||||
|
|
||||||
if (*str++ != '@')
|
if (*str++ != '@')
|
||||||
return BFD_RELOC_UNUSED;
|
return BFD_RELOC_UNUSED;
|
||||||
|
|
||||||
for (ch = *str, str2 = ident; str2 < ident + sizeof(ident) - 1 && isalpha (ch); ch = *++str)
|
for (ch = *str, str2 = ident;
|
||||||
|
str2 < ident + sizeof(ident) - 1 && isalnum (ch) || ch == '@';
|
||||||
|
ch = *++str)
|
||||||
|
{
|
||||||
*str2++ = (islower (ch)) ? ch : tolower (ch);
|
*str2++ = (islower (ch)) ? ch : tolower (ch);
|
||||||
|
}
|
||||||
|
|
||||||
*str2 = '\0';
|
*str2 = '\0';
|
||||||
len = str2 - ident;
|
len = str2 - ident;
|
||||||
|
@ -618,19 +641,23 @@ ppc_elf_cons (nbytes)
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
expression (&exp);
|
expression (&exp);
|
||||||
if (nbytes == 4
|
if (exp.X_op == O_symbol
|
||||||
&& exp.X_op == O_symbol
|
|
||||||
&& *input_line_pointer == '@'
|
&& *input_line_pointer == '@'
|
||||||
&& (reloc = ppc_elf_suffix (&input_line_pointer)) != BFD_RELOC_UNUSED)
|
&& (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);
|
reloc_howto_type *reloc_howto = bfd_reloc_type_lookup (stdoutput, reloc);
|
||||||
int offset = (!reloc_howto) ? 0 : (nbytes - bfd_get_reloc_size (reloc_howto));
|
int size = bfd_get_reloc_size (reloc_howto);
|
||||||
|
|
||||||
if (offset < 0)
|
if (size > nbytes)
|
||||||
offset = 0;
|
as_bad ("%s relocations do not fit in %d bytes\n", reloc_howto->name, nbytes);
|
||||||
|
|
||||||
fix_new_exp (frag_now, p - frag_now->fr_literal + offset, (int) nbytes - offset, &exp, 0, reloc);
|
else
|
||||||
|
{
|
||||||
|
register char *p = frag_more ((int) nbytes);
|
||||||
|
int offset = nbytes - size;
|
||||||
|
|
||||||
|
fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size, &exp, 0, reloc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
emit_expr (&exp, (unsigned int) nbytes);
|
emit_expr (&exp, (unsigned int) nbytes);
|
||||||
|
@ -865,6 +892,17 @@ md_assemble (str)
|
||||||
#ifdef OBJ_ELF
|
#ifdef OBJ_ELF
|
||||||
else if ((reloc = ppc_elf_suffix (&str)) != BFD_RELOC_UNUSED)
|
else if ((reloc = ppc_elf_suffix (&str)) != BFD_RELOC_UNUSED)
|
||||||
{
|
{
|
||||||
|
/* For the absoulte forms of branchs, convert the PC relative form back into
|
||||||
|
the absolute. */
|
||||||
|
if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
|
||||||
|
switch (reloc)
|
||||||
|
{
|
||||||
|
case BFD_RELOC_PPC_B26: reloc = BFD_RELOC_PPC_BA26; break;
|
||||||
|
case BFD_RELOC_PPC_B16: reloc = BFD_RELOC_PPC_BA16; break;
|
||||||
|
case BFD_RELOC_PPC_B16_BRTAKEN: reloc = BFD_RELOC_PPC_BA16_BRTAKEN; break;
|
||||||
|
case BFD_RELOC_PPC_B16_BRNTAKEN: reloc = BFD_RELOC_PPC_BA16_BRNTAKEN; break;
|
||||||
|
}
|
||||||
|
|
||||||
/* We need to generate a fixup for this expression. */
|
/* We need to generate a fixup for this expression. */
|
||||||
if (fc >= MAX_INSN_FIXUPS)
|
if (fc >= MAX_INSN_FIXUPS)
|
||||||
as_fatal ("too many fixups");
|
as_fatal ("too many fixups");
|
||||||
|
@ -2518,7 +2556,8 @@ md_pcrel_from (fixp)
|
||||||
{
|
{
|
||||||
#ifdef OBJ_ELF
|
#ifdef OBJ_ELF
|
||||||
if (fixp->fx_addsy != (symbolS *) NULL
|
if (fixp->fx_addsy != (symbolS *) NULL
|
||||||
&& ! S_IS_DEFINED (fixp->fx_addsy))
|
&& (! S_IS_DEFINED (fixp->fx_addsy)
|
||||||
|
|| TC_FORCE_RELOCATION (fixp)))
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2651,7 +2690,6 @@ md_apply_fix3 (fixp, valuep, seg)
|
||||||
valueT value;
|
valueT value;
|
||||||
char *where;
|
char *where;
|
||||||
unsigned long insn;
|
unsigned long insn;
|
||||||
unsigned long mask;
|
|
||||||
|
|
||||||
/* FIXME FIXME FIXME: The value we are passed in *valuep includes
|
/* FIXME FIXME FIXME: The value we are passed in *valuep includes
|
||||||
the symbol values. Since we are using BFD_ASSEMBLER, if we are
|
the symbol values. Since we are using BFD_ASSEMBLER, if we are
|
||||||
|
@ -2758,7 +2796,7 @@ md_apply_fix3 (fixp, valuep, seg)
|
||||||
&& operand->shift == 0)
|
&& operand->shift == 0)
|
||||||
fixp->fx_r_type = BFD_RELOC_PPC_BA26;
|
fixp->fx_r_type = BFD_RELOC_PPC_BA26;
|
||||||
else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0
|
else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0
|
||||||
&& operand->bits == 26
|
&& operand->bits == 16
|
||||||
&& operand->shift == 0)
|
&& operand->shift == 0)
|
||||||
fixp->fx_r_type = BFD_RELOC_PPC_BA16;
|
fixp->fx_r_type = BFD_RELOC_PPC_BA16;
|
||||||
else if ((operand->flags & PPC_OPERAND_PARENS) != 0
|
else if ((operand->flags & PPC_OPERAND_PARENS) != 0
|
||||||
|
@ -2786,77 +2824,16 @@ md_apply_fix3 (fixp, valuep, seg)
|
||||||
#ifdef OBJ_ELF
|
#ifdef OBJ_ELF
|
||||||
ppc_elf_validate_fix (fixp, seg);
|
ppc_elf_validate_fix (fixp, seg);
|
||||||
#endif
|
#endif
|
||||||
mask = 0;
|
|
||||||
switch (fixp->fx_r_type)
|
switch (fixp->fx_r_type)
|
||||||
{
|
{
|
||||||
case BFD_RELOC_32:
|
case BFD_RELOC_32: /* fixup errant PC relative relocations */
|
||||||
case BFD_RELOC_CTOR:
|
case BFD_RELOC_CTOR:
|
||||||
if (fixp->fx_pcrel)
|
if (fixp->fx_pcrel)
|
||||||
{
|
{
|
||||||
fixp->fx_r_type = BFD_RELOC_32_PCREL;
|
fixp->fx_r_type = BFD_RELOC_32_PCREL;
|
||||||
value += fixp->fx_frag->fr_address + fixp->fx_where;
|
value += fixp->fx_frag->fr_address + fixp->fx_where;
|
||||||
} /* fall through */
|
|
||||||
|
|
||||||
case BFD_RELOC_32_PCREL:
|
|
||||||
md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
|
|
||||||
value, 4);
|
|
||||||
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_GPREL16:
|
|
||||||
if (fixp->fx_pcrel)
|
|
||||||
abort ();
|
|
||||||
|
|
||||||
mask = 0xffff;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BFD_RELOC_8:
|
|
||||||
if (fixp->fx_pcrel)
|
|
||||||
abort ();
|
|
||||||
|
|
||||||
mask = 0xff;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BFD_RELOC_PPC_B16:
|
|
||||||
case BFD_RELOC_PPC_B16_BRTAKEN:
|
|
||||||
case BFD_RELOC_PPC_B16_BRNTAKEN:
|
|
||||||
case BFD_RELOC_PPC_BA16:
|
|
||||||
case BFD_RELOC_PPC_BA16_BRTAKEN:
|
|
||||||
case BFD_RELOC_PPC_BA16_BRNTAKEN:
|
|
||||||
mask = 0xfffc;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BFD_RELOC_PPC_B26:
|
|
||||||
case BFD_RELOC_PPC_BA26:
|
|
||||||
mask = 0x3fffffc;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
abort ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fetch the instruction, insert the fully resolved operand
|
|
||||||
value, and stuff the instruction back again. */
|
|
||||||
if (mask != 0)
|
|
||||||
{
|
|
||||||
where = fixp->fx_frag->fr_literal + fixp->fx_where;
|
|
||||||
if (target_big_endian)
|
|
||||||
insn = bfd_getb32 ((unsigned char *) where);
|
|
||||||
else
|
|
||||||
insn = bfd_getl32 ((unsigned char *) where);
|
|
||||||
|
|
||||||
insn = (insn & ~mask) | (value & mask);
|
|
||||||
|
|
||||||
if (target_big_endian)
|
|
||||||
bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
|
|
||||||
else
|
|
||||||
bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef OBJ_ELF
|
#ifdef OBJ_ELF
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
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 Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
#define TC_PPC
|
#define TC_PPC
|
||||||
|
|
||||||
|
@ -28,12 +28,15 @@
|
||||||
#define TARGET_ARCH (ppc_arch ())
|
#define TARGET_ARCH (ppc_arch ())
|
||||||
extern enum bfd_architecture ppc_arch PARAMS ((void));
|
extern enum bfd_architecture ppc_arch PARAMS ((void));
|
||||||
|
|
||||||
|
/* Whether or not the target is big endian */
|
||||||
|
extern int target_big_endian;
|
||||||
|
|
||||||
/* The target BFD format. */
|
/* The target BFD format. */
|
||||||
#ifdef OBJ_COFF
|
#ifdef OBJ_COFF
|
||||||
#define TARGET_FORMAT "aixcoff-rs6000"
|
#define TARGET_FORMAT "aixcoff-rs6000"
|
||||||
#endif
|
#endif
|
||||||
#ifdef OBJ_ELF
|
#ifdef OBJ_ELF
|
||||||
#define TARGET_FORMAT "elf32-powerpc"
|
#define TARGET_FORMAT (target_big_endian) ? "elf32-powerpc" : "elf32-powerpcle"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Permit temporary numeric labels. */
|
/* Permit temporary numeric labels. */
|
||||||
|
@ -63,7 +66,7 @@ extern enum bfd_architecture ppc_arch PARAMS ((void));
|
||||||
/* Set the endianness we are using. Default to big endian. */
|
/* Set the endianness we are using. Default to big endian. */
|
||||||
#ifndef TARGET_BYTES_BIG_ENDIAN
|
#ifndef TARGET_BYTES_BIG_ENDIAN
|
||||||
#ifndef TARGET_BYTES_LITTLE_ENDIAN
|
#ifndef TARGET_BYTES_LITTLE_ENDIAN
|
||||||
#define TARGET_BYTES_BIG_ENDIAN
|
#define TARGET_BYTES_BIG_ENDIAN 1
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -145,6 +148,9 @@ extern void ppc_frob_section PARAMS ((asection *));
|
||||||
#define tc_frob_symbol(sym, punt) punt = ppc_frob_symbol (sym)
|
#define tc_frob_symbol(sym, punt) punt = ppc_frob_symbol (sym)
|
||||||
extern int ppc_frob_symbol PARAMS ((struct symbol *));
|
extern int ppc_frob_symbol PARAMS ((struct symbol *));
|
||||||
|
|
||||||
|
/* Niclas Andersson <nican@ida.liu.se> says this is needed. */
|
||||||
|
#define SUB_SEGMENT_ALIGN(SEG) 2
|
||||||
|
|
||||||
/* Finish up the file. */
|
/* Finish up the file. */
|
||||||
#define tc_frob_file() ppc_frob_file ()
|
#define tc_frob_file() ppc_frob_file ()
|
||||||
extern void ppc_frob_file PARAMS ((void));
|
extern void ppc_frob_file PARAMS ((void));
|
||||||
|
@ -157,6 +163,14 @@ extern void ppc_frob_file PARAMS ((void));
|
||||||
#ifndef GLOBAL_OFFSET_TABLE_NAME
|
#ifndef GLOBAL_OFFSET_TABLE_NAME
|
||||||
#define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_"
|
#define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Branch prediction relocations must force relocation */
|
||||||
|
#define TC_FORCE_RELOCATION(FIXP) \
|
||||||
|
((FIXP)->fx_r_type == BFD_RELOC_PPC_B16_BRTAKEN \
|
||||||
|
|| (FIXP)->fx_r_type == BFD_RELOC_PPC_B16_BRNTAKEN \
|
||||||
|
|| (FIXP)->fx_r_type == BFD_RELOC_PPC_BA16_BRTAKEN \
|
||||||
|
|| (FIXP)->fx_r_type == BFD_RELOC_PPC_BA16_BRNTAKEN)
|
||||||
|
|
||||||
#endif /* OBJ_ELF */
|
#endif /* OBJ_ELF */
|
||||||
|
|
||||||
/* call md_apply_fix3 with segment instead of md_apply_fix */
|
/* call md_apply_fix3 with segment instead of md_apply_fix */
|
||||||
|
|
Loading…
Add table
Reference in a new issue