2005-02-15  Nigel Stephens  <nigel@mips.com>
            Maciej W. Rozycki  <macro@mips.com>

	* elf32-mips.c (elf_mips16_howto_table_rel): New array for MIPS16
	reloc howtos.  Add R_MIPS16_HI16 and R_MIPS16_LO16 relocs and
	R_MIPS16_GOT16 and R_MIPS16_CALL16 placeholders.
	(elf_mips16_jump_howto): Move into elf_mips16_howto_table_rel.
	(elf_mips16_gprel_howto): Likewise.  Redefine src_mask and
	dst_mask.
	(mips16_gprel_reloc): Remove bit shuffling; call
	_bfd_mips16_elf_reloc_unshuffle(), _bfd_mips_elf_gprel16_with_gp()
	and _bfd_mips16_elf_reloc_shuffle() instead.
	(mips16_reloc_map): New reloc map for MIPS16 relocs.
	(bfd_elf32_bfd_reloc_type_lookup): Use mips16_reloc_map for MIPS16
	relocs.
	(mips_elf32_rtype_to_howto): Fetch MIPS16 howtos from
	elf_mips16_howto_table_rel.
	* elf64-mips.c (mips16_elf64_howto_table_rel): New array for
	MIPS16 REL reloc howtos.  Add R_MIPS16_HI16 and R_MIPS16_LO16
	relocs and R_MIPS16_GOT16 and R_MIPS16_CALL16 placeholders.
	(elf_mips16_jump_howto): Move into mips16_elf64_howto_table_rel.
	(elf_mips16_gprel_howto): Likewise.  Redefine src_mask and
	dst_mask.
	(mips16_elf64_howto_table_rela): New array for MIPS16 RELA
	reloc howtos.  Add R_MIPS16_26, R_MIPS16_GPREL, R_MIPS16_HI16 and
	R_MIPS16_LO16 relocs and R_MIPS16_GOT16 and R_MIPS16_CALL16
	placeholders.
	(mips16_gprel_reloc): Remove bit shuffling; call
	_bfd_mips16_elf_reloc_unshuffle(), _bfd_mips_elf_gprel16_with_gp()
	and _bfd_mips16_elf_reloc_shuffle() instead.
	(mips16_reloc_map): New reloc map for MIPS16 relocs.
	(bfd_elf64_bfd_reloc_type_lookup): Use mips16_reloc_map for MIPS16
	relocs.
	(mips_elf64_rtype_to_howto): Fetch MIPS16 howtos from
	mips16_elf64_howto_table_rela or mips16_elf64_howto_table_rel.
	* elfn32-mips.c (elf_mips16_howto_table_rel): New array for MIPS16
	REL reloc howtos.  Add R_MIPS16_HI16 and R_MIPS16_LO16 relocs and
	R_MIPS16_GOT16 and R_MIPS16_CALL16 placeholders.
	(elf_mips16_jump_howto): Move into elf_mips16_howto_table_rel.
	(elf_mips16_gprel_howto): Likewise.  Redefine src_mask and
	dst_mask.
	(mips16_gprel_reloc): Remove bit shuffling; call
	_bfd_mips16_elf_reloc_unshuffle(), _bfd_mips_elf_gprel16_with_gp()
	and _bfd_mips16_elf_reloc_shuffle() instead.
	(mips16_reloc_map): New reloc map for MIPS16 relocs.
	(bfd_elf32_bfd_reloc_type_lookup): Use mips16_reloc_map for MIPS16
	relocs.
	(mips_elf_n32_rtype_to_howto): Fetch MIPS16 howtos from
	elf_mips16_howto_table_rela or elf_mips16_howto_table_rel.
	* elfxx-mips.c (_bfd_mips16_elf_reloc_unshuffle): New function to
	handle bit shuffling for MIPS16 relocs.
	(_bfd_mips16_elf_reloc_shuffle): Likewise.
	(_bfd_mips_elf_lo16_reloc): Use _bfd_mips16_elf_reloc_unshuffle()
	and _bfd_mips16_elf_reloc_shuffle().
	(_bfd_mips_elf_generic_reloc): Likewise.
	(mips_elf_calculate_relocation): Likewise.  Handle R_MIPS16_HI16
	and R_MIPS16_LO16.
	(mips_elf_obtain_contents): Remove bit shuffling.
	(mips_elf_perform_relocation): Likewise; call
	_bfd_mips16_elf_reloc_unshuffle() and _bfd_mips16_elf_reloc_shuffle()
	instead.
	(_bfd_mips_elf_relocate_section): Likewise.  Handle R_MIPS16_HI16
	and R_MIPS16_LO16.
	* elfxx-mips.h (_bfd_mips16_elf_reloc_unshuffle): Declare.
	(_bfd_mips16_elf_reloc_shuffle): Likewise.
	* reloc.c (BFD_RELOC_MIPS16_HI16): New reloc.
	(BFD_RELOC_MIPS16_HI16_S): Likewise.
	(BFD_RELOC_MIPS16_LO16): Likewise.
	* bfd-in2.h: Regenerate.
	* libbfd.h: Regenerate.

gas/:
2005-02-15  Nigel Stephens  <nigel@mips.com>
            Maciej W. Rozycki  <macro@mips.com>

	* config/tc-mips.c (reloc_needs_lo_p): Handle
	BFD_RELOC_MIPS16_HI16_S.
	(fixup_has_matching_lo_p): Handle BFD_RELOC_MIPS16_LO16.
	(append_insn): Add BFD_RELOC_MIPS16_GPREL, BFD_RELOC_MIPS16_HI16_S
	and BFD_RELOC_MIPS16_LO16 to relocs to suppress overflow
	complaints on.
	(mips16_ip): Resolve BFD_RELOC_MIPS16_HI16_S,
	BFD_RELOC_MIPS16_HI16 and BFD_RELOC_MIPS16_LO16 for constants.
	Call my_getSmallExpression() to parse percent operators.
	(percent_op_match, mips_percent_op): Separate definitions.
	(mips16_percent_op): Define percent operators for the MIPS16 mode.
	(parse_relocation): Handle the MIPS16 mode using
	mips16_percent_op.
	(md_apply_fix3): Handle BFD_RELOC_MIPS16_HI16,
	BFD_RELOC_MIPS16_HI16_S and BFD_RELOC_MIPS16_LO16.

gas/testsuite/:
2005-02-15  Nigel Stephens  <nigel@mips.com>
            Maciej W. Rozycki  <macro@mips.com>

	* gas/mips/mips16-hilo.d: New test for the R_MIPS16_HI16 and
	R_MIPS16_LO16 relocs.
	* gas/mips/mips16-hilo-n32.d: Likewise, for the n32 ABI.
	* gas/mips/mips16-hilo.s: Source for the new tests.
	* gas/mips/mips.exp: Run the new tests.

include/:
2005-02-15  Nigel Stephens  <nigel@mips.com>
            Maciej W. Rozycki  <macro@mips.com>

	* elf/mips.h (R_MIPS16_GOT16): New reloc code.
	(R_MIPS16_CALL16): Likewise.
	(R_MIPS16_HI16): Likewise.
	(R_MIPS16_LO16): Likewise.
	(R_MIPS16_min): New fake reloc code.
	(R_MIPS16_max): Likewise.

ld/testsuite/:
2005-02-15  Nigel Stephens  <nigel@mips.com>
            Maciej W. Rozycki  <macro@mips.com>

	* ld-mips-elf/mips16-hilo.d: New test for the R_MIPS16_HI16 and
	R_MIPS16_LO16 relocs.
	* ld-mips-elf/mips16-hilo-n32.d: Likewise, for the n32 ABI.
	* ld-mips-elf/mips16-hilo.s: Auxiliary source for the new tests.
	* ld-mips-elf/mips-elf.exp: Run the new tests.
This commit is contained in:
Maciej W. Rozycki
2005-02-15 19:57:54 +00:00
parent 77ef991de1
commit d6f1659387
24 changed files with 2943 additions and 363 deletions

View File

@ -564,8 +564,9 @@ static reloc_howto_type elf_mips_ctor64_howto =
0xffffffff, /* dst_mask */
FALSE); /* pcrel_offset */
/* The reloc used for the mips16 jump instruction. */
static reloc_howto_type elf_mips16_jump_howto =
static reloc_howto_type elf_mips16_howto_table_rel[] =
{
/* The reloc used for the mips16 jump instruction. */
HOWTO (R_MIPS16_26, /* type */
2, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
@ -581,10 +582,9 @@ static reloc_howto_type elf_mips16_jump_howto =
TRUE, /* partial_inplace */
0x3ffffff, /* src_mask */
0x3ffffff, /* dst_mask */
FALSE); /* pcrel_offset */
FALSE), /* pcrel_offset */
/* The reloc used for the mips16 gprel instruction. */
static reloc_howto_type elf_mips16_gprel_howto =
/* The reloc used for the mips16 gprel instruction. */
HOWTO (R_MIPS16_GPREL, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
@ -595,9 +595,46 @@ static reloc_howto_type elf_mips16_gprel_howto =
mips16_gprel_reloc, /* special_function */
"R_MIPS16_GPREL", /* name */
TRUE, /* partial_inplace */
0x07ff001f, /* src_mask */
0x07ff001f, /* dst_mask */
FALSE); /* pcrel_offset */
0x0000ffff, /* src_mask */
0x0000ffff, /* dst_mask */
FALSE), /* pcrel_offset */
/* A placeholder for MIPS16 reference to global offset table. */
EMPTY_HOWTO (R_MIPS16_GOT16),
/* A placeholder for MIPS16 16 bit call through global offset table. */
EMPTY_HOWTO (R_MIPS16_CALL16),
/* MIPS16 high 16 bits of symbol value. */
HOWTO (R_MIPS16_HI16, /* type */
16, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
_bfd_mips_elf_hi16_reloc, /* special_function */
"R_MIPS16_HI16", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
0x0000ffff, /* dst_mask */
FALSE), /* pcrel_offset */
/* MIPS16 low 16 bits of symbol value. */
HOWTO (R_MIPS16_LO16, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
_bfd_mips_elf_lo16_reloc, /* special_function */
"R_MIPS16_LO16", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
0x0000ffff, /* dst_mask */
FALSE), /* pcrel_offset */
};
/* 16 bit offset for pc-relative branches. */
static reloc_howto_type elf_mips_gnu_rel16_s2 =
@ -957,11 +994,8 @@ mips16_gprel_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
{
bfd_boolean relocatable;
bfd_reloc_status_type ret;
bfd_byte *location;
bfd_vma gp;
unsigned short extend = 0;
unsigned short insn = 0;
bfd_signed_vma val;
bfd_vma relocation;
/* If we're relocating, and this is an external symbol, we don't want
to change anything. */
@ -986,55 +1020,16 @@ mips16_gprel_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
if (ret != bfd_reloc_ok)
return ret;
if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
return bfd_reloc_outofrange;
location = (bfd_byte *) data + reloc_entry->address;
_bfd_mips16_elf_reloc_unshuffle (abfd, reloc_entry->howto->type, FALSE,
location);
ret = _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
input_section, relocatable,
data, gp);
_bfd_mips16_elf_reloc_shuffle (abfd, reloc_entry->howto->type, !relocatable,
location);
if (bfd_is_com_section (symbol->section))
relocation = 0;
else
relocation = symbol->value;
relocation += symbol->section->output_section->vma;
relocation += symbol->section->output_offset;
/* Set val to the offset into the section or symbol. */
val = reloc_entry->addend;
if (reloc_entry->howto->partial_inplace)
{
/* Pick up the mips16 extend instruction and the real instruction. */
extend = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address);
insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address + 2);
val += ((extend & 0x1f) << 11) | (extend & 0x7e0) | (insn & 0x1f);
}
_bfd_mips_elf_sign_extend(val, 16);
/* Adjust val for the final section location and GP value. If we
are producing relocatable output, we don't want to do this for
an external symbol. */
if (! relocatable
|| (symbol->flags & BSF_SECTION_SYM) != 0)
val += relocation - gp;
if (reloc_entry->howto->partial_inplace)
{
bfd_put_16 (abfd,
(extend & 0xf800) | ((val >> 11) & 0x1f) | (val & 0x7e0),
(bfd_byte *) data + reloc_entry->address);
bfd_put_16 (abfd,
(insn & 0xffe0) | (val & 0x1f),
(bfd_byte *) data + reloc_entry->address + 2);
}
else
reloc_entry->addend = val;
if (relocatable)
reloc_entry->address += input_section->output_offset;
else if (((val & ~0xffff) != ~0xffff) && ((val & ~0xffff) != 0))
return bfd_reloc_overflow;
return bfd_reloc_ok;
return ret;
}
/* A mapping from BFD reloc types to MIPS ELF reloc types. */
@ -1070,6 +1065,14 @@ static const struct elf_reloc_map mips_reloc_map[] =
{ BFD_RELOC_MIPS_GOT_DISP, R_MIPS_GOT_DISP }
};
static const struct elf_reloc_map mips16_reloc_map[] =
{
{ BFD_RELOC_MIPS16_JMP, R_MIPS16_26 - R_MIPS16_min },
{ BFD_RELOC_MIPS16_GPREL, R_MIPS16_GPREL - R_MIPS16_min },
{ BFD_RELOC_MIPS16_HI16_S, R_MIPS16_HI16 - R_MIPS16_min },
{ BFD_RELOC_MIPS16_LO16, R_MIPS16_LO16 - R_MIPS16_min },
};
/* Given a BFD reloc type, return a howto structure. */
static reloc_howto_type *
@ -1077,6 +1080,7 @@ bfd_elf32_bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code)
{
unsigned int i;
reloc_howto_type *howto_table = elf_mips_howto_table_rel;
reloc_howto_type *howto16_table = elf_mips16_howto_table_rel;
for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map);
i++)
@ -1085,6 +1089,13 @@ bfd_elf32_bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code)
return &howto_table[(int) mips_reloc_map[i].elf_val];
}
for (i = 0; i < sizeof (mips16_reloc_map) / sizeof (struct elf_reloc_map);
i++)
{
if (mips16_reloc_map[i].bfd_val == code)
return &howto16_table[(int) mips16_reloc_map[i].elf_val];
}
switch (code)
{
default:
@ -1101,10 +1112,6 @@ bfd_elf32_bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code)
else
return &howto_table[(int) R_MIPS_32];
case BFD_RELOC_MIPS16_JMP:
return &elf_mips16_jump_howto;
case BFD_RELOC_MIPS16_GPREL:
return &elf_mips16_gprel_howto;
case BFD_RELOC_VTABLE_INHERIT:
return &elf_mips_gnu_vtinherit_howto;
case BFD_RELOC_VTABLE_ENTRY:
@ -1124,10 +1131,6 @@ mips_elf32_rtype_to_howto (unsigned int r_type,
{
switch (r_type)
{
case R_MIPS16_26:
return &elf_mips16_jump_howto;
case R_MIPS16_GPREL:
return &elf_mips16_gprel_howto;
case R_MIPS_GNU_VTINHERIT:
return &elf_mips_gnu_vtinherit_howto;
case R_MIPS_GNU_VTENTRY:
@ -1137,6 +1140,8 @@ mips_elf32_rtype_to_howto (unsigned int r_type,
case R_MIPS_PC32:
return &elf_mips_gnu_pcrel32;
default:
if (r_type >= R_MIPS16_min && r_type < R_MIPS16_max)
return &elf_mips16_howto_table_rel[r_type - R_MIPS16_min];
BFD_ASSERT (r_type < (unsigned int) R_MIPS_max);
return &elf_mips_howto_table_rel[r_type];
}