This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH]: Support new HC11/HC12 relocs in bfd


Hi!

This patch adds support for the new HC11/HC12 relocs.  The 68HC12 part supports
the 16K memory bank window of the chip.  A special reloc is necessary and
some address mapping is necessary since two symbols can be mapped at the same
address in the window but still have different values (very similar to an overlay
but it is not; the two symbols still exists in memory at the same time).

I've committed this patch on mainline.

	Stephane

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.
Index: elf32-m68hc11.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-m68hc11.c,v
retrieving revision 1.3
diff -u -p -r1.3 elf32-m68hc11.c
--- elf32-m68hc11.c	8 Mar 2001 21:03:59 -0000	1.3
+++ elf32-m68hc11.c	13 Aug 2002 20:41:37 -0000
@@ -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
 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_howt
 	 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_howt
 	 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_howt
 	 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 m6
   {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 *
@@ -246,6 +293,25 @@ bfd_elf32_bfd_reloc_type_lookup (abfd, c
     }
 
   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.  */
Index: elf32-m68hc12.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-m68hc12.c,v
retrieving revision 1.3
diff -u -p -r1.3 elf32-m68hc12.c
--- elf32-m68hc12.c	8 Mar 2001 21:03:59 -0000	1.3
+++ elf32-m68hc12.c	13 Aug 2002 20:41:37 -0000
@@ -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 - Suit
 #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_Interna
    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_howt
 	 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_howt
 	 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_howt
 	 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_howt
 	 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_howt
 	 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_howt
 	 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_howt
 	 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_howt
 	 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_howt
 	 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_howt
 	 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 m6
   {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 *
@@ -246,6 +407,158 @@ bfd_elf32_bfd_reloc_type_lookup (abfd, c
     }
 
   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.  */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]