* elf32-m68hc11.c (elf_m68hc11_howto_table): Add the new relocs;

fix masks for PC-rel relocs.
	(m68hc11_elf_ignore_reloc): New function.

	* elf32-m68hc12.c (m68hc12_elf_special_reloc): New to handle specific
	68HC12 banked addressing relocs.
	(m68hc12_phys_addr): New to compute physical address of banked memory.
	(m68hc12_phys_page): Likewise for page.
	(m68hc12_addr_is_banked): New to see if address is in banked area.
	(elf_m68hc12_howto_table): Add new relocs and rename to xx12.
This commit is contained in:
Stephane Carrez
2002-08-13 20:43:01 +00:00
parent 3dbfec8644
commit dae78fb09d
3 changed files with 413 additions and 21 deletions

View File

@ -1,3 +1,16 @@
2002-08-13 Stephane Carrez <stcarrez@nerim.fr>
* elf32-m68hc11.c (elf_m68hc11_howto_table): Add the new relocs;
fix masks for PC-rel relocs.
(m68hc11_elf_ignore_reloc): New function.
* elf32-m68hc12.c (m68hc12_elf_special_reloc): New to handle specific
68HC12 banked addressing relocs.
(m68hc12_phys_addr): New to compute physical address of banked memory.
(m68hc12_phys_page): Likewise for page.
(m68hc12_addr_is_banked): New to see if address is in banked area.
(elf_m68hc12_howto_table): Add new relocs and rename to xx12.
2002-08-13 Stephane Carrez <stcarrez@nerim.fr>
* reloc.c (BFD_RELOC_M68HC11_RL_JUMP, BFD_RELOC_M68HC11_RL_GROUP,

View File

@ -1,6 +1,6 @@
/* Motorola 68HC11-specific support for 32-bit ELF
Copyright 1999, 2000 Free Software Foundation, Inc.
Contributed by Stephane Carrez (stcarrez@worldnet.fr)
Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Stephane Carrez (stcarrez@nerim.fr)
(Heavily copied from the D10V port by Martin Hunt (hunt@cygnus.com))
This file is part of BFD, the Binary File Descriptor library.
@ -30,6 +30,11 @@ PARAMS ((bfd * abfd, bfd_reloc_code_real_type code));
static void m68hc11_info_to_howto_rel
PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
static bfd_reloc_status_type m68hc11_elf_ignore_reloc
PARAMS ((bfd *abfd, arelent *reloc_entry,
asymbol *symbol, PTR data, asection *input_section,
bfd *output_bfd, char **error_message));
/* Use REL instead of RELA to save space */
#define USE_REL
@ -110,7 +115,7 @@ static reloc_howto_type elf_m68hc11_howto_table[] = {
bfd_elf_generic_reloc, /* special_function */
"R_M68HC11_PCREL_8", /* name */
false, /* partial_inplace */
0x0, /* src_mask */
0x00ff, /* src_mask */
0x00ff, /* dst_mask */
false), /* pcrel_offset */
@ -171,7 +176,7 @@ static reloc_howto_type elf_m68hc11_howto_table[] = {
bfd_elf_generic_reloc, /* special_function */
"R_M68HC11_PCREL_16", /* name */
false, /* partial_inplace */
0x0, /* src_mask */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
@ -204,6 +209,46 @@ static reloc_howto_type elf_m68hc11_howto_table[] = {
0, /* src_mask */
0, /* dst_mask */
false), /* pcrel_offset */
EMPTY_HOWTO (11),
EMPTY_HOWTO (12),
EMPTY_HOWTO (13),
EMPTY_HOWTO (14),
EMPTY_HOWTO (15),
EMPTY_HOWTO (16),
EMPTY_HOWTO (17),
EMPTY_HOWTO (18),
EMPTY_HOWTO (19),
/* Mark beginning of a jump instruction (any form). */
HOWTO (R_M68HC11_RL_JUMP, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
m68hc11_elf_ignore_reloc, /* special_function */
"R_M68HC11_RL_JUMP", /* name */
true, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
true), /* pcrel_offset */
/* Mark beginning of Gcc relaxation group instruction. */
HOWTO (R_M68HC11_RL_GROUP, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
m68hc11_elf_ignore_reloc, /* special_function */
"R_M68HC11_RL_GROUP", /* name */
true, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
true), /* pcrel_offset */
};
/* Map BFD reloc types to M68HC11 ELF reloc types. */
@ -225,9 +270,11 @@ static const struct m68hc11_reloc_map m68hc11_reloc_map[] = {
{BFD_RELOC_32, R_M68HC11_32},
{BFD_RELOC_M68HC11_3B, R_M68HC11_3B},
/* The following relocs are defined but they probably don't work yet. */
{BFD_RELOC_VTABLE_INHERIT, R_M68HC11_GNU_VTINHERIT},
{BFD_RELOC_VTABLE_ENTRY, R_M68HC11_GNU_VTENTRY},
{BFD_RELOC_M68HC11_RL_JUMP, R_M68HC11_RL_JUMP},
{BFD_RELOC_M68HC11_RL_GROUP, R_M68HC11_RL_GROUP},
};
static reloc_howto_type *
@ -248,6 +295,25 @@ bfd_elf32_bfd_reloc_type_lookup (abfd, code)
return NULL;
}
/* This function is used for relocs which are only used for relaxing,
which the linker should otherwise ignore. */
static bfd_reloc_status_type
m68hc11_elf_ignore_reloc (abfd, reloc_entry, symbol, data, input_section,
output_bfd, error_message)
bfd *abfd ATTRIBUTE_UNUSED;
arelent *reloc_entry;
asymbol *symbol ATTRIBUTE_UNUSED;
PTR data ATTRIBUTE_UNUSED;
asection *input_section;
bfd *output_bfd;
char **error_message ATTRIBUTE_UNUSED;
{
if (output_bfd != NULL)
reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
}
/* Set the howto pointer for an M68HC11 ELF reloc. */
static void

View File

@ -1,6 +1,6 @@
/* Motorola 68HC12-specific support for 32-bit ELF
Copyright 1999, 2000 Free Software Foundation, Inc.
Contributed by Stephane Carrez (stcarrez@worldnet.fr)
Copyright 1999, 2000, 2002 Free Software Foundation, Inc.
Contributed by Stephane Carrez (stcarrez@nerim.fr)
(Heavily copied from the D10V port by Martin Hunt (hunt@cygnus.com))
This file is part of BFD, the Binary File Descriptor library.
@ -24,12 +24,23 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf/m68hc11.h"
#include "opcode/m68hc11.h"
static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
PARAMS ((bfd * abfd, bfd_reloc_code_real_type code));
static void m68hc11_info_to_howto_rel
PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
static bfd_reloc_status_type m68hc11_elf_ignore_reloc
PARAMS ((bfd *abfd, arelent *reloc_entry,
asymbol *symbol, PTR data, asection *input_section,
bfd *output_bfd, char **error_message));
static bfd_reloc_status_type m68hc12_elf_special_reloc
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
static int m68hc12_addr_is_banked PARAMS ((bfd_vma));
static bfd_vma m68hc12_phys_addr PARAMS ((bfd_vma));
static bfd_vma m68hc12_phys_page PARAMS ((bfd_vma));
/* Use REL instead of RELA to save space */
#define USE_REL
@ -37,6 +48,68 @@ PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
We must handle 8 and 16-bit relocations. The 32-bit relocation
is defined but not used except by gas when -gstabs is used (which
is wrong).
The 68HC12 microcontroler has a memory bank switching system
with a 16Kb window in the 64Kb address space. The extended memory
is mapped in the 16Kb window (at 0x8000). The page register controls
which 16Kb bank is mapped. The call/rtc instructions take care of
bank switching in function calls/returns.
For GNU Binutils to work, we consider there is a physical memory
at 0..0x0ffff and a kind of virtual memory above that. Symbols
in virtual memory have their addresses treated in a special way
when disassembling and when linking.
For the linker to work properly, we must always relocate the virtual
memory as if it is mapped at 0x8000. When a 16-bit relocation is
made in the virtual memory, we check that it does not cross the
memory bank where it is used. This would involve a page change
which would be wrong. The 24-bit relocation is for that and it
treats the address as a physical address + page number.
Banked
Address Space
| | Page n
+---------------+ 0x1010000
| |
| jsr _foo |
| .. | Page 3
| _foo: |
+---------------+ 0x100C000
| |
| call _bar |
| .. | Page 2
| _bar: |
+---------------+ 0x1008000
/------>| |
| | call _foo | Page 1
| | |
| +---------------+ 0x1004000
Physical | | |
Address Space | | | Page 0
| | |
+-----------+ 0x00FFFF | +---------------+ 0x1000000
| | |
| call _foo | |
| | |
+-----------+ 0x00BFFF -+---/
| | |
| | |
| | 16K |
| | |
+-----------+ 0x008000 -+
| |
| |
= =
| |
| |
+-----------+ 0000
The 'call _foo' must be relocated with page 3 and 16-bit address
mapped at 0x8000.
The 3-bit and 16-bit PC rel relocation is only used by 68HC12. */
static reloc_howto_type elf_m68hc11_howto_table[] = {
/* This reloc does nothing. */
@ -46,9 +119,9 @@ static reloc_howto_type elf_m68hc11_howto_table[] = {
32, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_M68HC11_NONE", /* name */
"R_M68HC12_NONE", /* name */
false, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
@ -63,7 +136,7 @@ static reloc_howto_type elf_m68hc11_howto_table[] = {
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_M68HC11_8", /* name */
"R_M68HC12_8", /* name */
false, /* partial_inplace */
0x00ff, /* src_mask */
0x00ff, /* dst_mask */
@ -78,7 +151,7 @@ static reloc_howto_type elf_m68hc11_howto_table[] = {
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_M68HC11_HI8", /* name */
"R_M68HC12_HI8", /* name */
false, /* partial_inplace */
0x00ff, /* src_mask */
0x00ff, /* dst_mask */
@ -93,7 +166,7 @@ static reloc_howto_type elf_m68hc11_howto_table[] = {
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_M68HC11_LO8", /* name */
"R_M68HC12_LO8", /* name */
false, /* partial_inplace */
0x00ff, /* src_mask */
0x00ff, /* dst_mask */
@ -108,9 +181,9 @@ static reloc_howto_type elf_m68hc11_howto_table[] = {
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_M68HC11_PCREL_8", /* name */
"R_M68HC12_PCREL_8", /* name */
false, /* partial_inplace */
0x0, /* src_mask */
0x00ff, /* src_mask */
0x00ff, /* dst_mask */
false), /* pcrel_offset */
@ -122,8 +195,8 @@ static reloc_howto_type elf_m68hc11_howto_table[] = {
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont /*bitfield */ , /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_M68HC11_16", /* name */
m68hc12_elf_special_reloc, /* special_function */
"R_M68HC12_16", /* name */
false, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
@ -139,7 +212,7 @@ static reloc_howto_type elf_m68hc11_howto_table[] = {
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_M68HC11_32", /* name */
"R_M68HC12_32", /* name */
false, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
@ -154,7 +227,7 @@ static reloc_howto_type elf_m68hc11_howto_table[] = {
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_M68HC11_4B", /* name */
"R_M68HC12_4B", /* name */
false, /* partial_inplace */
0x003, /* src_mask */
0x003, /* dst_mask */
@ -169,9 +242,9 @@ static reloc_howto_type elf_m68hc11_howto_table[] = {
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_M68HC11_PCREL_16", /* name */
"R_M68HC12_PCREL_16", /* name */
false, /* partial_inplace */
0x0, /* src_mask */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
@ -204,6 +277,88 @@ static reloc_howto_type elf_m68hc11_howto_table[] = {
0, /* src_mask */
0, /* dst_mask */
false), /* pcrel_offset */
/* A 24 bit relocation */
HOWTO (R_M68HC11_24, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
24, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
m68hc12_elf_special_reloc, /* special_function */
"R_M68HC12_24", /* name */
false, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
/* A 16-bit low relocation */
HOWTO (R_M68HC11_LO16, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
m68hc12_elf_special_reloc,/* special_function */
"R_M68HC12_LO16", /* name */
false, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
/* A page relocation */
HOWTO (R_M68HC11_PAGE, /* type */
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
8, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
m68hc12_elf_special_reloc,/* special_function */
"R_M68HC12_PAGE", /* name */
false, /* partial_inplace */
0x00ff, /* src_mask */
0x00ff, /* dst_mask */
false), /* pcrel_offset */
EMPTY_HOWTO (14),
EMPTY_HOWTO (15),
EMPTY_HOWTO (16),
EMPTY_HOWTO (17),
EMPTY_HOWTO (18),
EMPTY_HOWTO (19),
/* Mark beginning of a jump instruction (any form). */
HOWTO (R_M68HC11_RL_JUMP, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
m68hc11_elf_ignore_reloc, /* special_function */
"R_M68HC12_RL_JUMP", /* name */
true, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
true), /* pcrel_offset */
/* Mark beginning of Gcc relaxation group instruction. */
HOWTO (R_M68HC11_RL_GROUP, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
m68hc11_elf_ignore_reloc, /* special_function */
"R_M68HC12_RL_GROUP", /* name */
true, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
true), /* pcrel_offset */
};
/* Map BFD reloc types to M68HC11 ELF reloc types. */
@ -225,9 +380,15 @@ static const struct m68hc11_reloc_map m68hc11_reloc_map[] = {
{BFD_RELOC_32, R_M68HC11_32},
{BFD_RELOC_M68HC11_3B, R_M68HC11_3B},
/* The following relocs are defined but they probably don't work yet. */
{BFD_RELOC_VTABLE_INHERIT, R_M68HC11_GNU_VTINHERIT},
{BFD_RELOC_VTABLE_ENTRY, R_M68HC11_GNU_VTENTRY},
{BFD_RELOC_M68HC11_LO16, R_M68HC11_LO16},
{BFD_RELOC_M68HC11_PAGE, R_M68HC11_PAGE},
{BFD_RELOC_M68HC11_24, R_M68HC11_24},
{BFD_RELOC_M68HC11_RL_JUMP, R_M68HC11_RL_JUMP},
{BFD_RELOC_M68HC11_RL_GROUP, R_M68HC11_RL_GROUP},
};
static reloc_howto_type *
@ -248,6 +409,158 @@ bfd_elf32_bfd_reloc_type_lookup (abfd, code)
return NULL;
}
/* This function is used for relocs which are only used for relaxing,
which the linker should otherwise ignore. */
static bfd_reloc_status_type
m68hc11_elf_ignore_reloc (abfd, reloc_entry, symbol, data, input_section,
output_bfd, error_message)
bfd *abfd ATTRIBUTE_UNUSED;
arelent *reloc_entry;
asymbol *symbol ATTRIBUTE_UNUSED;
PTR data ATTRIBUTE_UNUSED;
asection *input_section;
bfd *output_bfd;
char **error_message ATTRIBUTE_UNUSED;
{
if (output_bfd != NULL)
reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
}
static int
m68hc12_addr_is_banked (addr)
bfd_vma addr;
{
return (addr >= M68HC12_BANK_VIRT) ? 1 : 0;
}
/* Return the physical address seen by the processor, taking
into account banked memory. */
static bfd_vma
m68hc12_phys_addr (addr)
bfd_vma addr;
{
if (addr < M68HC12_BANK_VIRT)
return addr;
/* Map the address to the memory bank. */
addr -= M68HC12_BANK_VIRT;
addr &= M68HC12_BANK_MASK;
addr += M68HC12_BANK_BASE;
return addr;
}
/* Return the page number corresponding to an address in banked memory. */
static bfd_vma
m68hc12_phys_page (addr)
bfd_vma addr;
{
if (addr < M68HC12_BANK_VIRT)
return 0;
/* Map the address to the memory bank. */
addr -= M68HC12_BANK_VIRT;
addr >>= M68HC12_BANK_SHIFT;
addr &= M68HC12_BANK_PAGE_MASK;
return addr;
}
static bfd_reloc_status_type
m68hc12_elf_special_reloc (abfd, reloc_entry, symbol, data, input_section,
output_bfd, error_message)
bfd *abfd;
arelent *reloc_entry;
asymbol *symbol;
PTR data;
asection *input_section;
bfd *output_bfd;
char **error_message ATTRIBUTE_UNUSED;
{
reloc_howto_type *howto;
bfd_vma relocation;
bfd_vma phys_addr;
bfd_vma phys_page;
bfd_vma insn_page;
bfd_vma insn_addr;
if (output_bfd != (bfd *) NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& (! reloc_entry->howto->partial_inplace
|| reloc_entry->addend == 0))
{
reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
}
if (output_bfd != NULL)
return bfd_reloc_continue;
if (reloc_entry->address > input_section->_cooked_size)
return bfd_reloc_outofrange;
/* Compute relocation. */
relocation = (symbol->value
+ symbol->section->output_section->vma
+ symbol->section->output_offset);
relocation += reloc_entry->addend;
relocation += bfd_get_16 (abfd, (bfd_byte*) data + reloc_entry->address);
/* Do the memory bank mapping. */
phys_addr = m68hc12_phys_addr (relocation);
phys_page = m68hc12_phys_page (relocation);
howto = reloc_entry->howto;
if (howto->complain_on_overflow != complain_overflow_dont
&& (phys_addr & (((bfd_vma) -1) << 16)))
return bfd_reloc_overflow;
switch (howto->type)
{
case R_M68HC11_16:
/* Get virtual address of instruction having the relocation. */
insn_addr = input_section->output_section->vma
+ input_section->output_offset
+ reloc_entry->address;
insn_page = m68hc12_phys_page (insn_addr);
if (m68hc12_addr_is_banked (relocation)
&& m68hc12_addr_is_banked (insn_addr)
&& phys_page != insn_page)
{
*error_message = _("address is not in the same bank");
return bfd_reloc_dangerous;
}
if (m68hc12_addr_is_banked (relocation)
&& !m68hc12_addr_is_banked (insn_addr))
{
*error_message = _("reference to a banked address in "
"the normal address space");
return bfd_reloc_dangerous;
}
case R_M68HC11_LO16:
bfd_put_16 (abfd, phys_addr, (bfd_byte*) data + reloc_entry->address);
break;
case R_M68HC11_24:
bfd_put_16 (abfd, phys_addr, (bfd_byte*) data + reloc_entry->address);
bfd_put_8 (abfd, phys_page, (bfd_byte*) data + reloc_entry->address + 2);
break;
case R_M68HC11_PAGE:
bfd_put_8 (abfd, phys_page, (bfd_byte*) data + reloc_entry->address);
break;
default:
abort ();
break;
}
return bfd_reloc_ok;
}
/* Set the howto pointer for an M68HC11 ELF reloc. */
static void