1 /* Motorola 68HC12-specific support for 32-bit ELF
2    Copyright 1999, 2000 Free Software Foundation, Inc.
3    Contributed by Stephane Carrez (stcarrez@worldnet.fr)
4    (Heavily copied from the D10V port by Martin Hunt (hunt@cygnus.com))
5 
6 This file is part of BFD, the Binary File Descriptor library.
7 
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21 
22 #include "bfd.h"
23 #include "sysdep.h"
24 #include "libbfd.h"
25 #include "elf-bfd.h"
26 #include "elf/m68hc11.h"
27 
28 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
29 PARAMS ((bfd * abfd, bfd_reloc_code_real_type code));
30 static void m68hc11_info_to_howto_rel
31 PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
32 
33 /* Use REL instead of RELA to save space */
34 #define USE_REL
35 
36 /* The Motorola 68HC11 microcontroler only addresses 64Kb.
37    We must handle 8 and 16-bit relocations.  The 32-bit relocation
38    is defined but not used except by gas when -gstabs is used (which
39    is wrong).
40    The 3-bit and 16-bit PC rel relocation is only used by 68HC12.  */
41 static reloc_howto_type elf_m68hc11_howto_table[] = {
42   /* This reloc does nothing.  */
43   HOWTO (R_M68HC11_NONE,	/* type */
44 	 0,			/* rightshift */
45 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
46 	 32,			/* bitsize */
47 	 false,			/* pc_relative */
48 	 0,			/* bitpos */
49 	 complain_overflow_bitfield,	/* complain_on_overflow */
50 	 bfd_elf_generic_reloc,	/* special_function */
51 	 "R_M68HC11_NONE",	/* name */
52 	 false,			/* partial_inplace */
53 	 0,			/* src_mask */
54 	 0,			/* dst_mask */
55 	 false),		/* pcrel_offset */
56 
57   /* A 8 bit absolute relocation */
58   HOWTO (R_M68HC11_8,		/* type */
59 	 0,			/* rightshift */
60 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
61 	 8,			/* bitsize */
62 	 false,			/* pc_relative */
63 	 0,			/* bitpos */
64 	 complain_overflow_bitfield,	/* complain_on_overflow */
65 	 bfd_elf_generic_reloc,	/* special_function */
66 	 "R_M68HC11_8",		/* name */
67 	 false,			/* partial_inplace */
68 	 0x00ff,		/* src_mask */
69 	 0x00ff,		/* dst_mask */
70 	 false),		/* pcrel_offset */
71 
72   /* A 8 bit absolute relocation (upper address) */
73   HOWTO (R_M68HC11_HI8,		/* type */
74 	 8,			/* rightshift */
75 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
76 	 8,			/* bitsize */
77 	 false,			/* pc_relative */
78 	 0,			/* bitpos */
79 	 complain_overflow_bitfield,	/* complain_on_overflow */
80 	 bfd_elf_generic_reloc,	/* special_function */
81 	 "R_M68HC11_HI8",	/* name */
82 	 false,			/* partial_inplace */
83 	 0x00ff,		/* src_mask */
84 	 0x00ff,		/* dst_mask */
85 	 false),		/* pcrel_offset */
86 
87   /* A 8 bit absolute relocation (upper address) */
88   HOWTO (R_M68HC11_LO8,		/* type */
89 	 0,			/* rightshift */
90 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
91 	 8,			/* bitsize */
92 	 false,			/* pc_relative */
93 	 0,			/* bitpos */
94 	 complain_overflow_dont,	/* complain_on_overflow */
95 	 bfd_elf_generic_reloc,	/* special_function */
96 	 "R_M68HC11_LO8",	/* name */
97 	 false,			/* partial_inplace */
98 	 0x00ff,		/* src_mask */
99 	 0x00ff,		/* dst_mask */
100 	 false),		/* pcrel_offset */
101 
102   /* A 8 bit PC-rel relocation */
103   HOWTO (R_M68HC11_PCREL_8,	/* type */
104 	 0,			/* rightshift */
105 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
106 	 8,			/* bitsize */
107 	 true,			/* pc_relative */
108 	 0,			/* bitpos */
109 	 complain_overflow_bitfield,	/* complain_on_overflow */
110 	 bfd_elf_generic_reloc,	/* special_function */
111 	 "R_M68HC11_PCREL_8",	/* name */
112 	 false,			/* partial_inplace */
113 	 0x0,			/* src_mask */
114 	 0x00ff,		/* dst_mask */
115 	 false),		/* pcrel_offset */
116 
117   /* A 16 bit absolute relocation */
118   HOWTO (R_M68HC11_16,		/* type */
119 	 0,			/* rightshift */
120 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
121 	 16,			/* bitsize */
122 	 false,			/* pc_relative */
123 	 0,			/* bitpos */
124 	 complain_overflow_dont /*bitfield */ ,	/* complain_on_overflow */
125 	 bfd_elf_generic_reloc,	/* special_function */
126 	 "R_M68HC11_16",	/* name */
127 	 false,			/* partial_inplace */
128 	 0xffff,		/* src_mask */
129 	 0xffff,		/* dst_mask */
130 	 false),		/* pcrel_offset */
131 
132   /* A 32 bit absolute relocation.  This one is never used for the
133      code relocation.  It's used by gas for -gstabs generation.  */
134   HOWTO (R_M68HC11_32,		/* type */
135 	 0,			/* rightshift */
136 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
137 	 32,			/* bitsize */
138 	 false,			/* pc_relative */
139 	 0,			/* bitpos */
140 	 complain_overflow_bitfield,	/* complain_on_overflow */
141 	 bfd_elf_generic_reloc,	/* special_function */
142 	 "R_M68HC11_32",	/* name */
143 	 false,			/* partial_inplace */
144 	 0xffffffff,		/* src_mask */
145 	 0xffffffff,		/* dst_mask */
146 	 false),		/* pcrel_offset */
147 
148   /* A 3 bit absolute relocation */
149   HOWTO (R_M68HC11_3B,		/* type */
150 	 0,			/* rightshift */
151 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
152 	 3,			/* bitsize */
153 	 false,			/* pc_relative */
154 	 0,			/* bitpos */
155 	 complain_overflow_bitfield,	/* complain_on_overflow */
156 	 bfd_elf_generic_reloc,	/* special_function */
157 	 "R_M68HC11_4B",	/* name */
158 	 false,			/* partial_inplace */
159 	 0x003,			/* src_mask */
160 	 0x003,			/* dst_mask */
161 	 false),		/* pcrel_offset */
162 
163   /* A 16 bit PC-rel relocation */
164   HOWTO (R_M68HC11_PCREL_16,	/* type */
165 	 0,			/* rightshift */
166 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
167 	 16,			/* bitsize */
168 	 true,			/* pc_relative */
169 	 0,			/* bitpos */
170 	 complain_overflow_dont,	/* complain_on_overflow */
171 	 bfd_elf_generic_reloc,	/* special_function */
172 	 "R_M68HC11_PCREL_16",	/* name */
173 	 false,			/* partial_inplace */
174 	 0x0,			/* src_mask */
175 	 0xffff,		/* dst_mask */
176 	 false),		/* pcrel_offset */
177 
178   /* GNU extension to record C++ vtable hierarchy */
179   HOWTO (R_M68HC11_GNU_VTINHERIT,	/* type */
180 	 0,			/* rightshift */
181 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
182 	 0,			/* bitsize */
183 	 false,			/* pc_relative */
184 	 0,			/* bitpos */
185 	 complain_overflow_dont,	/* complain_on_overflow */
186 	 NULL,			/* special_function */
187 	 "R_M68HC11_GNU_VTINHERIT",	/* name */
188 	 false,			/* partial_inplace */
189 	 0,			/* src_mask */
190 	 0,			/* dst_mask */
191 	 false),		/* pcrel_offset */
192 
193   /* GNU extension to record C++ vtable member usage */
194   HOWTO (R_M68HC11_GNU_VTENTRY,	/* type */
195 	 0,			/* rightshift */
196 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
197 	 0,			/* bitsize */
198 	 false,			/* pc_relative */
199 	 0,			/* bitpos */
200 	 complain_overflow_dont,	/* complain_on_overflow */
201 	 _bfd_elf_rel_vtable_reloc_fn,	/* special_function */
202 	 "R_M68HC11_GNU_VTENTRY",	/* name */
203 	 false,			/* partial_inplace */
204 	 0,			/* src_mask */
205 	 0,			/* dst_mask */
206 	 false),		/* pcrel_offset */
207 };
208 
209 /* Map BFD reloc types to M68HC11 ELF reloc types.  */
210 
211 struct m68hc11_reloc_map
212 {
213   bfd_reloc_code_real_type bfd_reloc_val;
214   unsigned char elf_reloc_val;
215 };
216 
217 static const struct m68hc11_reloc_map m68hc11_reloc_map[] = {
218   {BFD_RELOC_NONE, R_M68HC11_NONE,},
219   {BFD_RELOC_8, R_M68HC11_8},
220   {BFD_RELOC_M68HC11_HI8, R_M68HC11_HI8},
221   {BFD_RELOC_M68HC11_LO8, R_M68HC11_LO8},
222   {BFD_RELOC_8_PCREL, R_M68HC11_PCREL_8},
223   {BFD_RELOC_16_PCREL, R_M68HC11_PCREL_16},
224   {BFD_RELOC_16, R_M68HC11_16},
225   {BFD_RELOC_32, R_M68HC11_32},
226   {BFD_RELOC_M68HC11_3B, R_M68HC11_3B},
227 
228   /* The following relocs are defined but they probably don't work yet.  */
229   {BFD_RELOC_VTABLE_INHERIT, R_M68HC11_GNU_VTINHERIT},
230   {BFD_RELOC_VTABLE_ENTRY, R_M68HC11_GNU_VTENTRY},
231 };
232 
233 static reloc_howto_type *
234 bfd_elf32_bfd_reloc_type_lookup (abfd, code)
235      bfd *abfd ATTRIBUTE_UNUSED;
236      bfd_reloc_code_real_type code;
237 {
238   unsigned int i;
239 
240   for (i = 0;
241        i < sizeof (m68hc11_reloc_map) / sizeof (struct m68hc11_reloc_map);
242        i++)
243     {
244       if (m68hc11_reloc_map[i].bfd_reloc_val == code)
245 	return &elf_m68hc11_howto_table[m68hc11_reloc_map[i].elf_reloc_val];
246     }
247 
248   return NULL;
249 }
250 
251 /* Set the howto pointer for an M68HC11 ELF reloc.  */
252 
253 static void
254 m68hc11_info_to_howto_rel (abfd, cache_ptr, dst)
255      bfd *abfd ATTRIBUTE_UNUSED;
256      arelent *cache_ptr;
257      Elf32_Internal_Rel *dst;
258 {
259   unsigned int r_type;
260 
261   r_type = ELF32_R_TYPE (dst->r_info);
262   BFD_ASSERT (r_type < (unsigned int) R_M68HC11_max);
263   cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
264 }
265 
266 /* Below is the only difference between elf32-m68hc12.c and elf32-m68hc11.c.
267    The Motorola spec says to use a different Elf machine code.  */
268 #define ELF_ARCH		bfd_arch_m68hc12
269 #define ELF_MACHINE_CODE	EM_68HC12
270 #define ELF_MAXPAGESIZE		0x1000
271 
272 #define TARGET_BIG_SYM          bfd_elf32_m68hc12_vec
273 #define TARGET_BIG_NAME		"elf32-m68hc12"
274 
275 #define elf_info_to_howto	0
276 #define elf_info_to_howto_rel	m68hc11_info_to_howto_rel
277 #define elf_backend_object_p	0
278 #define elf_backend_final_write_processing	0
279 
280 #include "elf32-target.h"
281