elf32-m68hc12.c revision 1.1 1 1.1 christos /* Motorola 68HC12-specific support for 32-bit ELF
2 1.1 christos Copyright 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2010, 2012
3 1.1 christos Free Software Foundation, Inc.
4 1.1 christos Contributed by Stephane Carrez (stcarrez (at) nerim.fr)
5 1.1 christos (Heavily copied from the D10V port by Martin Hunt (hunt (at) cygnus.com))
6 1.1 christos
7 1.1 christos This file is part of BFD, the Binary File Descriptor library.
8 1.1 christos
9 1.1 christos This program is free software; you can redistribute it and/or modify
10 1.1 christos it under the terms of the GNU General Public License as published by
11 1.1 christos the Free Software Foundation; either version 3 of the License, or
12 1.1 christos (at your option) any later version.
13 1.1 christos
14 1.1 christos This program is distributed in the hope that it will be useful,
15 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
16 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 1.1 christos GNU General Public License for more details.
18 1.1 christos
19 1.1 christos You should have received a copy of the GNU General Public License
20 1.1 christos along with this program; if not, write to the Free Software
21 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22 1.1 christos MA 02110-1301, USA. */
23 1.1 christos
24 1.1 christos #include "sysdep.h"
25 1.1 christos #include "bfd.h"
26 1.1 christos #include "bfdlink.h"
27 1.1 christos #include "libbfd.h"
28 1.1 christos #include "elf-bfd.h"
29 1.1 christos #include "elf32-m68hc1x.h"
30 1.1 christos #include "elf/m68hc11.h"
31 1.1 christos #include "opcode/m68hc11.h"
32 1.1 christos
33 1.1 christos /* Relocation functions. */
34 1.1 christos static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
35 1.1 christos (bfd *, bfd_reloc_code_real_type);
36 1.1 christos static void m68hc11_info_to_howto_rel
37 1.1 christos (bfd *, arelent *, Elf_Internal_Rela *);
38 1.1 christos
39 1.1 christos /* Trampoline generation. */
40 1.1 christos
41 1.1 christos
42 1.1 christos /* Use REL instead of RELA to save space */
43 1.1 christos #define USE_REL 1
44 1.1 christos
45 1.1 christos /* The 68HC12 microcontroler has a memory bank switching system
46 1.1 christos with a 16Kb window in the 64Kb address space. The extended memory
47 1.1 christos is mapped in the 16Kb window (at 0x8000). The page register controls
48 1.1 christos which 16Kb bank is mapped. The call/rtc instructions take care of
49 1.1 christos bank switching in function calls/returns.
50 1.1 christos
51 1.1 christos For GNU Binutils to work, we consider there is a physical memory
52 1.1 christos at 0..0x0ffff and a kind of virtual memory above that. Symbols
53 1.1 christos in virtual memory have their addresses treated in a special way
54 1.1 christos when disassembling and when linking.
55 1.1 christos
56 1.1 christos For the linker to work properly, we must always relocate the virtual
57 1.1 christos memory as if it is mapped at 0x8000. When a 16-bit relocation is
58 1.1 christos made in the virtual memory, we check that it does not cross the
59 1.1 christos memory bank where it is used. This would involve a page change
60 1.1 christos which would be wrong. The 24-bit relocation is for that and it
61 1.1 christos treats the address as a physical address + page number.
62 1.1 christos
63 1.1 christos
64 1.1 christos Banked
65 1.1 christos Address Space
66 1.1 christos | | Page n
67 1.1 christos +---------------+ 0x1010000
68 1.1 christos | |
69 1.1 christos | jsr _foo |
70 1.1 christos | .. | Page 3
71 1.1 christos | _foo: |
72 1.1 christos +---------------+ 0x100C000
73 1.1 christos | |
74 1.1 christos | call _bar |
75 1.1 christos | .. | Page 2
76 1.1 christos | _bar: |
77 1.1 christos +---------------+ 0x1008000
78 1.1 christos /------>| |
79 1.1 christos | | call _foo | Page 1
80 1.1 christos | | |
81 1.1 christos | +---------------+ 0x1004000
82 1.1 christos Physical | | |
83 1.1 christos Address Space | | | Page 0
84 1.1 christos | | |
85 1.1 christos +-----------+ 0x00FFFF | +---------------+ 0x1000000
86 1.1 christos | | |
87 1.1 christos | call _foo | |
88 1.1 christos | | |
89 1.1 christos +-----------+ 0x00BFFF -+---/
90 1.1 christos | | |
91 1.1 christos | | |
92 1.1 christos | | 16K |
93 1.1 christos | | |
94 1.1 christos +-----------+ 0x008000 -+
95 1.1 christos | |
96 1.1 christos | |
97 1.1 christos = =
98 1.1 christos | |
99 1.1 christos | |
100 1.1 christos +-----------+ 0000
101 1.1 christos
102 1.1 christos
103 1.1 christos The 'call _foo' must be relocated with page 3 and 16-bit address
104 1.1 christos mapped at 0x8000.
105 1.1 christos
106 1.1 christos The 3-bit and 16-bit PC rel relocation is only used by 68HC12. */
107 1.1 christos static reloc_howto_type elf_m68hc11_howto_table[] = {
108 1.1 christos /* This reloc does nothing. */
109 1.1 christos HOWTO (R_M68HC11_NONE, /* type */
110 1.1 christos 0, /* rightshift */
111 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
112 1.1 christos 32, /* bitsize */
113 1.1 christos FALSE, /* pc_relative */
114 1.1 christos 0, /* bitpos */
115 1.1 christos complain_overflow_dont,/* complain_on_overflow */
116 1.1 christos bfd_elf_generic_reloc, /* special_function */
117 1.1 christos "R_M68HC12_NONE", /* name */
118 1.1 christos FALSE, /* partial_inplace */
119 1.1 christos 0, /* src_mask */
120 1.1 christos 0, /* dst_mask */
121 1.1 christos FALSE), /* pcrel_offset */
122 1.1 christos
123 1.1 christos /* A 8 bit absolute relocation */
124 1.1 christos HOWTO (R_M68HC11_8, /* type */
125 1.1 christos 0, /* rightshift */
126 1.1 christos 0, /* size (0 = byte, 1 = short, 2 = long) */
127 1.1 christos 8, /* bitsize */
128 1.1 christos FALSE, /* pc_relative */
129 1.1 christos 0, /* bitpos */
130 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
131 1.1 christos bfd_elf_generic_reloc, /* special_function */
132 1.1 christos "R_M68HC12_8", /* name */
133 1.1 christos FALSE, /* partial_inplace */
134 1.1 christos 0x00ff, /* src_mask */
135 1.1 christos 0x00ff, /* dst_mask */
136 1.1 christos FALSE), /* pcrel_offset */
137 1.1 christos
138 1.1 christos /* A 8 bit absolute relocation (upper address) */
139 1.1 christos HOWTO (R_M68HC11_HI8, /* type */
140 1.1 christos 8, /* rightshift */
141 1.1 christos 0, /* size (0 = byte, 1 = short, 2 = long) */
142 1.1 christos 8, /* bitsize */
143 1.1 christos FALSE, /* pc_relative */
144 1.1 christos 0, /* bitpos */
145 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
146 1.1 christos bfd_elf_generic_reloc, /* special_function */
147 1.1 christos "R_M68HC12_HI8", /* name */
148 1.1 christos FALSE, /* partial_inplace */
149 1.1 christos 0x00ff, /* src_mask */
150 1.1 christos 0x00ff, /* dst_mask */
151 1.1 christos FALSE), /* pcrel_offset */
152 1.1 christos
153 1.1 christos /* A 8 bit absolute relocation (upper address) */
154 1.1 christos HOWTO (R_M68HC11_LO8, /* type */
155 1.1 christos 0, /* rightshift */
156 1.1 christos 0, /* size (0 = byte, 1 = short, 2 = long) */
157 1.1 christos 8, /* bitsize */
158 1.1 christos FALSE, /* pc_relative */
159 1.1 christos 0, /* bitpos */
160 1.1 christos complain_overflow_dont, /* complain_on_overflow */
161 1.1 christos bfd_elf_generic_reloc, /* special_function */
162 1.1 christos "R_M68HC12_LO8", /* name */
163 1.1 christos FALSE, /* partial_inplace */
164 1.1 christos 0x00ff, /* src_mask */
165 1.1 christos 0x00ff, /* dst_mask */
166 1.1 christos FALSE), /* pcrel_offset */
167 1.1 christos
168 1.1 christos /* A 8 bit PC-rel relocation */
169 1.1 christos HOWTO (R_M68HC11_PCREL_8, /* type */
170 1.1 christos 0, /* rightshift */
171 1.1 christos 0, /* size (0 = byte, 1 = short, 2 = long) */
172 1.1 christos 8, /* bitsize */
173 1.1 christos TRUE, /* pc_relative */
174 1.1 christos 0, /* bitpos */
175 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
176 1.1 christos bfd_elf_generic_reloc, /* special_function */
177 1.1 christos "R_M68HC12_PCREL_8", /* name */
178 1.1 christos FALSE, /* partial_inplace */
179 1.1 christos 0x00ff, /* src_mask */
180 1.1 christos 0x00ff, /* dst_mask */
181 1.1 christos TRUE), /* pcrel_offset */
182 1.1 christos
183 1.1 christos /* A 16 bit absolute relocation */
184 1.1 christos HOWTO (R_M68HC11_16, /* type */
185 1.1 christos 0, /* rightshift */
186 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
187 1.1 christos 16, /* bitsize */
188 1.1 christos FALSE, /* pc_relative */
189 1.1 christos 0, /* bitpos */
190 1.1 christos complain_overflow_dont /*bitfield */ , /* complain_on_overflow */
191 1.1 christos bfd_elf_generic_reloc, /* special_function */
192 1.1 christos "R_M68HC12_16", /* name */
193 1.1 christos FALSE, /* partial_inplace */
194 1.1 christos 0xffff, /* src_mask */
195 1.1 christos 0xffff, /* dst_mask */
196 1.1 christos FALSE), /* pcrel_offset */
197 1.1 christos
198 1.1 christos /* A 32 bit absolute relocation. This one is never used for the
199 1.1 christos code relocation. It's used by gas for -gstabs generation. */
200 1.1 christos HOWTO (R_M68HC11_32, /* type */
201 1.1 christos 0, /* rightshift */
202 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
203 1.1 christos 32, /* bitsize */
204 1.1 christos FALSE, /* pc_relative */
205 1.1 christos 0, /* bitpos */
206 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
207 1.1 christos bfd_elf_generic_reloc, /* special_function */
208 1.1 christos "R_M68HC12_32", /* name */
209 1.1 christos FALSE, /* partial_inplace */
210 1.1 christos 0xffffffff, /* src_mask */
211 1.1 christos 0xffffffff, /* dst_mask */
212 1.1 christos FALSE), /* pcrel_offset */
213 1.1 christos
214 1.1 christos /* A 3 bit absolute relocation */
215 1.1 christos HOWTO (R_M68HC11_3B, /* type */
216 1.1 christos 0, /* rightshift */
217 1.1 christos 0, /* size (0 = byte, 1 = short, 2 = long) */
218 1.1 christos 3, /* bitsize */
219 1.1 christos FALSE, /* pc_relative */
220 1.1 christos 0, /* bitpos */
221 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
222 1.1 christos bfd_elf_generic_reloc, /* special_function */
223 1.1 christos "R_M68HC12_4B", /* name */
224 1.1 christos FALSE, /* partial_inplace */
225 1.1 christos 0x003, /* src_mask */
226 1.1 christos 0x003, /* dst_mask */
227 1.1 christos FALSE), /* pcrel_offset */
228 1.1 christos
229 1.1 christos /* A 16 bit PC-rel relocation */
230 1.1 christos HOWTO (R_M68HC11_PCREL_16, /* type */
231 1.1 christos 0, /* rightshift */
232 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
233 1.1 christos 16, /* bitsize */
234 1.1 christos TRUE, /* pc_relative */
235 1.1 christos 0, /* bitpos */
236 1.1 christos complain_overflow_dont, /* complain_on_overflow */
237 1.1 christos bfd_elf_generic_reloc, /* special_function */
238 1.1 christos "R_M68HC12_PCREL_16", /* name */
239 1.1 christos FALSE, /* partial_inplace */
240 1.1 christos 0xffff, /* src_mask */
241 1.1 christos 0xffff, /* dst_mask */
242 1.1 christos TRUE), /* pcrel_offset */
243 1.1 christos
244 1.1 christos /* GNU extension to record C++ vtable hierarchy */
245 1.1 christos HOWTO (R_M68HC11_GNU_VTINHERIT, /* type */
246 1.1 christos 0, /* rightshift */
247 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
248 1.1 christos 0, /* bitsize */
249 1.1 christos FALSE, /* pc_relative */
250 1.1 christos 0, /* bitpos */
251 1.1 christos complain_overflow_dont, /* complain_on_overflow */
252 1.1 christos NULL, /* special_function */
253 1.1 christos "R_M68HC11_GNU_VTINHERIT", /* name */
254 1.1 christos FALSE, /* partial_inplace */
255 1.1 christos 0, /* src_mask */
256 1.1 christos 0, /* dst_mask */
257 1.1 christos FALSE), /* pcrel_offset */
258 1.1 christos
259 1.1 christos /* GNU extension to record C++ vtable member usage */
260 1.1 christos HOWTO (R_M68HC11_GNU_VTENTRY, /* type */
261 1.1 christos 0, /* rightshift */
262 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
263 1.1 christos 0, /* bitsize */
264 1.1 christos FALSE, /* pc_relative */
265 1.1 christos 0, /* bitpos */
266 1.1 christos complain_overflow_dont, /* complain_on_overflow */
267 1.1 christos _bfd_elf_rel_vtable_reloc_fn, /* special_function */
268 1.1 christos "R_M68HC11_GNU_VTENTRY", /* name */
269 1.1 christos FALSE, /* partial_inplace */
270 1.1 christos 0, /* src_mask */
271 1.1 christos 0, /* dst_mask */
272 1.1 christos FALSE), /* pcrel_offset */
273 1.1 christos
274 1.1 christos /* A 24 bit relocation */
275 1.1 christos HOWTO (R_M68HC11_24, /* type */
276 1.1 christos 0, /* rightshift */
277 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
278 1.1 christos 24, /* bitsize */
279 1.1 christos FALSE, /* pc_relative */
280 1.1 christos 0, /* bitpos */
281 1.1 christos complain_overflow_dont, /* complain_on_overflow */
282 1.1 christos m68hc11_elf_special_reloc, /* special_function */
283 1.1 christos "R_M68HC12_24", /* name */
284 1.1 christos FALSE, /* partial_inplace */
285 1.1 christos 0xffffff, /* src_mask */
286 1.1 christos 0xffffff, /* dst_mask */
287 1.1 christos FALSE), /* pcrel_offset */
288 1.1 christos
289 1.1 christos /* A 16-bit low relocation */
290 1.1 christos HOWTO (R_M68HC11_LO16, /* type */
291 1.1 christos 0, /* rightshift */
292 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
293 1.1 christos 16, /* bitsize */
294 1.1 christos FALSE, /* pc_relative */
295 1.1 christos 0, /* bitpos */
296 1.1 christos complain_overflow_dont, /* complain_on_overflow */
297 1.1 christos m68hc11_elf_special_reloc,/* special_function */
298 1.1 christos "R_M68HC12_LO16", /* name */
299 1.1 christos FALSE, /* partial_inplace */
300 1.1 christos 0xffff, /* src_mask */
301 1.1 christos 0xffff, /* dst_mask */
302 1.1 christos FALSE), /* pcrel_offset */
303 1.1 christos
304 1.1 christos /* A page relocation */
305 1.1 christos HOWTO (R_M68HC11_PAGE, /* type */
306 1.1 christos 0, /* rightshift */
307 1.1 christos 0, /* size (0 = byte, 1 = short, 2 = long) */
308 1.1 christos 8, /* bitsize */
309 1.1 christos FALSE, /* pc_relative */
310 1.1 christos 0, /* bitpos */
311 1.1 christos complain_overflow_dont, /* complain_on_overflow */
312 1.1 christos m68hc11_elf_special_reloc,/* special_function */
313 1.1 christos "R_M68HC12_PAGE", /* name */
314 1.1 christos FALSE, /* partial_inplace */
315 1.1 christos 0x00ff, /* src_mask */
316 1.1 christos 0x00ff, /* dst_mask */
317 1.1 christos FALSE), /* pcrel_offset */
318 1.1 christos
319 1.1 christos EMPTY_HOWTO (14),
320 1.1 christos
321 1.1 christos /* A 16 bit absolute relocation. */
322 1.1 christos HOWTO (R_M68HC12_16B, /* type */
323 1.1 christos 0, /* rightshift */
324 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
325 1.1 christos 16, /* bitsize */
326 1.1 christos FALSE, /* pc_relative */
327 1.1 christos 0, /* bitpos */
328 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
329 1.1 christos bfd_elf_generic_reloc, /* special_function */
330 1.1 christos "R_M68HC12_16B", /* name */
331 1.1 christos FALSE, /* partial_inplace */
332 1.1 christos 0xffff, /* src_mask */
333 1.1 christos 0xffff, /* dst_mask */
334 1.1 christos FALSE), /* pcrel_offset */
335 1.1 christos
336 1.1 christos /* A 9 bit PC-rel relocation. */
337 1.1 christos HOWTO (R_M68HC12_PCREL_9, /* type */
338 1.1 christos 1, /* rightshift */
339 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
340 1.1 christos 10, /* bitsize (result is >>1) */
341 1.1 christos TRUE, /* pc_relative */
342 1.1 christos 0, /* bitpos */
343 1.1 christos complain_overflow_dont, /* complain_on_overflow */
344 1.1 christos bfd_elf_generic_reloc, /* special_function */
345 1.1 christos "R_M68HC12_PCREL_9", /* name */
346 1.1 christos TRUE, /* partial_inplace */
347 1.1 christos 0xfe00, /* src_mask */
348 1.1 christos 0x01ff, /* dst_mask */
349 1.1 christos TRUE), /* pcrel_offset */
350 1.1 christos
351 1.1 christos /* A 10 bit PC-rel relocation. */
352 1.1 christos HOWTO (R_M68HC12_PCREL_10, /* type */
353 1.1 christos 1, /* rightshift */
354 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
355 1.1 christos 11, /* bitsize (result is >>1) */
356 1.1 christos TRUE, /* pc_relative */
357 1.1 christos 0, /* bitpos */
358 1.1 christos complain_overflow_dont, /* complain_on_overflow */
359 1.1 christos bfd_elf_generic_reloc, /* special_function */
360 1.1 christos "R_M68HC12_PCREL_10", /* name */
361 1.1 christos TRUE, /* partial_inplace */
362 1.1 christos 0xfc00, /* src_mask */
363 1.1 christos 0x03ff, /* dst_mask */
364 1.1 christos TRUE), /* pcrel_offset */
365 1.1 christos
366 1.1 christos /* A 8 bit absolute relocation (upper address). */
367 1.1 christos HOWTO (R_M68HC12_HI8XG, /* type */
368 1.1 christos 8, /* rightshift */
369 1.1 christos 0, /* size (0 = byte, 1 = short, 2 = long) */
370 1.1 christos 8, /* bitsize */
371 1.1 christos FALSE, /* pc_relative */
372 1.1 christos 0, /* bitpos */
373 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
374 1.1 christos bfd_elf_generic_reloc, /* special_function */
375 1.1 christos "R_M68HC12_HI8XG", /* name */
376 1.1 christos FALSE, /* partial_inplace */
377 1.1 christos 0x00ff, /* src_mask */
378 1.1 christos 0x00ff, /* dst_mask */
379 1.1 christos FALSE), /* pcrel_offset */
380 1.1 christos
381 1.1 christos /* A 8 bit absolute relocation (lower address). */
382 1.1 christos HOWTO (R_M68HC12_LO8XG, /* type */
383 1.1 christos 8, /* rightshift */
384 1.1 christos 0, /* size (0 = byte, 1 = short, 2 = long) */
385 1.1 christos 8, /* bitsize */
386 1.1 christos FALSE, /* pc_relative */
387 1.1 christos 0, /* bitpos */
388 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
389 1.1 christos bfd_elf_generic_reloc, /* special_function */
390 1.1 christos "R_M68HC12_LO8XG", /* name */
391 1.1 christos FALSE, /* partial_inplace */
392 1.1 christos 0x00ff, /* src_mask */
393 1.1 christos 0x00ff, /* dst_mask */
394 1.1 christos FALSE), /* pcrel_offset */
395 1.1 christos
396 1.1 christos /* Mark beginning of a jump instruction (any form). */
397 1.1 christos HOWTO (R_M68HC11_RL_JUMP, /* type */
398 1.1 christos 0, /* rightshift */
399 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
400 1.1 christos 0, /* bitsize */
401 1.1 christos FALSE, /* pc_relative */
402 1.1 christos 0, /* bitpos */
403 1.1 christos complain_overflow_dont, /* complain_on_overflow */
404 1.1 christos m68hc11_elf_ignore_reloc, /* special_function */
405 1.1 christos "R_M68HC12_RL_JUMP", /* name */
406 1.1 christos TRUE, /* partial_inplace */
407 1.1 christos 0, /* src_mask */
408 1.1 christos 0, /* dst_mask */
409 1.1 christos TRUE), /* pcrel_offset */
410 1.1 christos
411 1.1 christos /* Mark beginning of Gcc relaxation group instruction. */
412 1.1 christos HOWTO (R_M68HC11_RL_GROUP, /* type */
413 1.1 christos 0, /* rightshift */
414 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
415 1.1 christos 0, /* bitsize */
416 1.1 christos FALSE, /* pc_relative */
417 1.1 christos 0, /* bitpos */
418 1.1 christos complain_overflow_dont, /* complain_on_overflow */
419 1.1 christos m68hc11_elf_ignore_reloc, /* special_function */
420 1.1 christos "R_M68HC12_RL_GROUP", /* name */
421 1.1 christos TRUE, /* partial_inplace */
422 1.1 christos 0, /* src_mask */
423 1.1 christos 0, /* dst_mask */
424 1.1 christos TRUE), /* pcrel_offset */
425 1.1 christos };
426 1.1 christos
427 1.1 christos /* Map BFD reloc types to M68HC11 ELF reloc types. */
428 1.1 christos
429 1.1 christos struct m68hc11_reloc_map
430 1.1 christos {
431 1.1 christos bfd_reloc_code_real_type bfd_reloc_val;
432 1.1 christos unsigned char elf_reloc_val;
433 1.1 christos };
434 1.1 christos
435 1.1 christos static const struct m68hc11_reloc_map m68hc11_reloc_map[] =
436 1.1 christos {
437 1.1 christos {BFD_RELOC_NONE, R_M68HC11_NONE,},
438 1.1 christos {BFD_RELOC_8, R_M68HC11_8},
439 1.1 christos {BFD_RELOC_M68HC11_HI8, R_M68HC11_HI8},
440 1.1 christos {BFD_RELOC_M68HC11_LO8, R_M68HC11_LO8},
441 1.1 christos {BFD_RELOC_8_PCREL, R_M68HC11_PCREL_8},
442 1.1 christos {BFD_RELOC_16_PCREL, R_M68HC11_PCREL_16},
443 1.1 christos {BFD_RELOC_16, R_M68HC11_16},
444 1.1 christos {BFD_RELOC_32, R_M68HC11_32},
445 1.1 christos {BFD_RELOC_M68HC11_3B, R_M68HC11_3B},
446 1.1 christos
447 1.1 christos {BFD_RELOC_VTABLE_INHERIT, R_M68HC11_GNU_VTINHERIT},
448 1.1 christos {BFD_RELOC_VTABLE_ENTRY, R_M68HC11_GNU_VTENTRY},
449 1.1 christos
450 1.1 christos {BFD_RELOC_M68HC11_LO16, R_M68HC11_LO16},
451 1.1 christos {BFD_RELOC_M68HC11_PAGE, R_M68HC11_PAGE},
452 1.1 christos {BFD_RELOC_M68HC11_24, R_M68HC11_24},
453 1.1 christos
454 1.1 christos {BFD_RELOC_M68HC11_RL_JUMP, R_M68HC11_RL_JUMP},
455 1.1 christos {BFD_RELOC_M68HC11_RL_GROUP, R_M68HC11_RL_GROUP},
456 1.1 christos
457 1.1 christos {BFD_RELOC_M68HC12_16B, R_M68HC12_16B},
458 1.1 christos
459 1.1 christos {BFD_RELOC_M68HC12_9_PCREL, R_M68HC12_PCREL_9},
460 1.1 christos {BFD_RELOC_M68HC12_10_PCREL, R_M68HC12_PCREL_10},
461 1.1 christos {BFD_RELOC_M68HC12_HI8XG, R_M68HC12_HI8XG},
462 1.1 christos {BFD_RELOC_M68HC12_LO8XG, R_M68HC12_LO8XG},
463 1.1 christos };
464 1.1 christos
465 1.1 christos static reloc_howto_type *
466 1.1 christos bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
467 1.1 christos bfd_reloc_code_real_type code)
468 1.1 christos {
469 1.1 christos unsigned int i;
470 1.1 christos
471 1.1 christos for (i = 0;
472 1.1 christos i < sizeof (m68hc11_reloc_map) / sizeof (struct m68hc11_reloc_map);
473 1.1 christos i++)
474 1.1 christos {
475 1.1 christos if (m68hc11_reloc_map[i].bfd_reloc_val == code)
476 1.1 christos return &elf_m68hc11_howto_table[m68hc11_reloc_map[i].elf_reloc_val];
477 1.1 christos }
478 1.1 christos
479 1.1 christos return NULL;
480 1.1 christos }
481 1.1 christos
482 1.1 christos static reloc_howto_type *
483 1.1 christos bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
484 1.1 christos const char *r_name)
485 1.1 christos {
486 1.1 christos unsigned int i;
487 1.1 christos
488 1.1 christos for (i = 0;
489 1.1 christos i < (sizeof (elf_m68hc11_howto_table)
490 1.1 christos / sizeof (elf_m68hc11_howto_table[0]));
491 1.1 christos i++)
492 1.1 christos if (elf_m68hc11_howto_table[i].name != NULL
493 1.1 christos && strcasecmp (elf_m68hc11_howto_table[i].name, r_name) == 0)
494 1.1 christos return &elf_m68hc11_howto_table[i];
495 1.1 christos
496 1.1 christos return NULL;
497 1.1 christos }
498 1.1 christos
499 1.1 christos /* Set the howto pointer for an M68HC11 ELF reloc. */
500 1.1 christos
501 1.1 christos static void
502 1.1 christos m68hc11_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
503 1.1 christos arelent *cache_ptr, Elf_Internal_Rela *dst)
504 1.1 christos {
505 1.1 christos unsigned int r_type;
506 1.1 christos
507 1.1 christos r_type = ELF32_R_TYPE (dst->r_info);
508 1.1 christos BFD_ASSERT (r_type < (unsigned int) R_M68HC11_max);
509 1.1 christos cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
510 1.1 christos }
511 1.1 christos
512 1.1 christos
513 1.1 christos /* Far trampoline generation. */
515 1.1 christos
516 1.1 christos /* Build a 68HC12 trampoline stub. */
517 1.1 christos static bfd_boolean
518 1.1 christos m68hc12_elf_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
519 1.1 christos {
520 1.1 christos struct elf32_m68hc11_stub_hash_entry *stub_entry;
521 1.1 christos struct bfd_link_info *info;
522 1.1 christos struct m68hc11_elf_link_hash_table *htab;
523 1.1 christos asection *stub_sec;
524 1.1 christos bfd *stub_bfd;
525 1.1 christos bfd_byte *loc;
526 1.1 christos bfd_vma sym_value, phys_page, phys_addr;
527 1.1 christos
528 1.1 christos /* Massage our args to the form they really have. */
529 1.1 christos stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
530 1.1 christos info = (struct bfd_link_info *) in_arg;
531 1.1 christos
532 1.1 christos htab = m68hc11_elf_hash_table (info);
533 1.1 christos
534 1.1 christos stub_sec = stub_entry->stub_sec;
535 1.1 christos
536 1.1 christos /* Make a note of the offset within the stubs for this entry. */
537 1.1 christos stub_entry->stub_offset = stub_sec->size;
538 1.1 christos stub_sec->size += 7;
539 1.1 christos loc = stub_sec->contents + stub_entry->stub_offset;
540 1.1 christos
541 1.1 christos stub_bfd = stub_sec->owner;
542 1.1 christos
543 1.1 christos /* Create the trampoline call stub:
544 1.1 christos
545 1.1 christos ldy #%addr(symbol)
546 1.1 christos call %page(symbol), __trampoline
547 1.1 christos
548 1.1 christos */
549 1.1 christos sym_value = (stub_entry->target_value
550 1.1 christos + stub_entry->target_section->output_offset
551 1.1 christos + stub_entry->target_section->output_section->vma);
552 1.1 christos phys_addr = m68hc11_phys_addr (&htab->pinfo, sym_value);
553 1.1 christos phys_page = m68hc11_phys_page (&htab->pinfo, sym_value);
554 1.1 christos
555 1.1 christos /* ldy #%page(sym) */
556 1.1 christos bfd_put_8 (stub_bfd, 0xCD, loc);
557 1.1 christos bfd_put_16 (stub_bfd, phys_addr, loc + 1);
558 1.1 christos loc += 3;
559 1.1 christos
560 1.1 christos /* call %page(sym), __trampoline */
561 1.1 christos bfd_put_8 (stub_bfd, 0x4a, loc);
562 1.1 christos bfd_put_16 (stub_bfd, htab->pinfo.trampoline_addr, loc + 1);
563 1.1 christos bfd_put_8 (stub_bfd, phys_page, loc + 3);
564 1.1 christos
565 1.1 christos return TRUE;
566 1.1 christos }
567 1.1 christos
568 1.1 christos /* As above, but don't actually build the stub. Just bump offset so
569 1.1 christos we know stub section sizes. */
570 1.1 christos
571 1.1 christos static bfd_boolean
572 1.1 christos m68hc12_elf_size_one_stub (struct bfd_hash_entry *gen_entry,
573 1.1 christos void *in_arg ATTRIBUTE_UNUSED)
574 1.1 christos {
575 1.1 christos struct elf32_m68hc11_stub_hash_entry *stub_entry;
576 1.1 christos
577 1.1 christos /* Massage our args to the form they really have. */
578 1.1 christos stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
579 1.1 christos
580 1.1 christos stub_entry->stub_sec->size += 7;
581 1.1 christos return TRUE;
582 1.1 christos }
583 1.1 christos
584 1.1 christos /* Create a 68HC12 ELF linker hash table. */
585 1.1 christos
586 1.1 christos static struct bfd_link_hash_table *
587 1.1 christos m68hc12_elf_bfd_link_hash_table_create (bfd *abfd)
588 1.1 christos {
589 1.1 christos struct m68hc11_elf_link_hash_table *ret;
590 1.1 christos
591 1.1 christos ret = m68hc11_elf_hash_table_create (abfd);
592 1.1 christos if (ret == (struct m68hc11_elf_link_hash_table *) NULL)
593 1.1 christos return NULL;
594 1.1 christos
595 1.1 christos ret->size_one_stub = m68hc12_elf_size_one_stub;
596 1.1 christos ret->build_one_stub = m68hc12_elf_build_one_stub;
597 1.1 christos
598 1.1 christos return &ret->root.root;
599 1.1 christos }
600 1.1 christos
601 1.1 christos static bfd_boolean
603 1.1 christos m68hc12_elf_set_mach_from_flags (bfd *abfd)
604 1.1 christos {
605 1.1 christos flagword flags = elf_elfheader (abfd)->e_flags;
606 1.1 christos
607 1.1 christos switch (flags & EF_M68HC11_MACH_MASK)
608 1.1 christos {
609 1.1 christos case EF_M68HC12_MACH:
610 1.1 christos bfd_default_set_arch_mach (abfd, bfd_arch_m68hc12, bfd_mach_m6812);
611 1.1 christos break;
612 1.1 christos case EF_M68HCS12_MACH:
613 1.1 christos bfd_default_set_arch_mach (abfd, bfd_arch_m68hc12, bfd_mach_m6812s);
614 1.1 christos break;
615 1.1 christos case EF_M68HC11_GENERIC:
616 1.1 christos bfd_default_set_arch_mach (abfd, bfd_arch_m68hc12,
617 1.1 christos bfd_mach_m6812_default);
618 1.1 christos break;
619 1.1 christos default:
620 1.1 christos return FALSE;
621 1.1 christos }
622 1.1 christos return TRUE;
623 1.1 christos }
624 1.1 christos
625 1.1 christos /* Specific sections:
626 1.1 christos - The .page0 is a data section that is mapped in [0x0000..0x00FF].
627 1.1 christos Page0 accesses are faster on the M68HC12.
628 1.1 christos - The .vectors is the section that represents the interrupt
629 1.1 christos vectors. */
630 1.1 christos static const struct bfd_elf_special_section elf32_m68hc12_special_sections[] =
631 1.1 christos {
632 1.1 christos { STRING_COMMA_LEN (".eeprom"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
633 1.1 christos { STRING_COMMA_LEN (".page0"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
634 1.1 christos { STRING_COMMA_LEN (".softregs"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
635 1.1 christos { STRING_COMMA_LEN (".vectors"), 0, SHT_PROGBITS, SHF_ALLOC },
636 1.1 christos { NULL, 0, 0, 0, 0 }
637 1.1 christos };
638 1.1 christos
639 1.1 christos #define ELF_ARCH bfd_arch_m68hc12
641 1.1 christos #define ELF_TARGET_ID M68HC11_ELF_DATA
642 1.1 christos #define ELF_MACHINE_CODE EM_68HC12
643 1.1 christos #define ELF_MAXPAGESIZE 0x1000
644 1.1 christos
645 1.1 christos #define TARGET_BIG_SYM bfd_elf32_m68hc12_vec
646 1.1 christos #define TARGET_BIG_NAME "elf32-m68hc12"
647 1.1 christos
648 1.1 christos #define elf_info_to_howto 0
649 1.1 christos #define elf_info_to_howto_rel m68hc11_info_to_howto_rel
650 1.1 christos #define elf_backend_check_relocs elf32_m68hc11_check_relocs
651 1.1 christos #define elf_backend_relocate_section elf32_m68hc11_relocate_section
652 1.1 christos #define elf_backend_object_p m68hc12_elf_set_mach_from_flags
653 1.1 christos #define elf_backend_final_write_processing 0
654 1.1 christos #define elf_backend_can_gc_sections 1
655 1.1 christos #define elf_backend_special_sections elf32_m68hc12_special_sections
656 1.1 christos #define elf_backend_post_process_headers elf32_m68hc11_post_process_headers
657 1.1 christos #define elf_backend_add_symbol_hook elf32_m68hc11_add_symbol_hook
658 1.1 christos #define elf_backend_merge_symbol_attribute elf32_m68hc11_merge_symbol_attribute
659 1.1 christos
660 1.1 christos #define bfd_elf32_bfd_link_hash_table_create \
661 1.1 christos m68hc12_elf_bfd_link_hash_table_create
662 1.1 christos #define bfd_elf32_bfd_link_hash_table_free \
663 1.1 christos m68hc11_elf_bfd_link_hash_table_free
664 1.1 christos #define bfd_elf32_bfd_merge_private_bfd_data \
665 1.1 christos _bfd_m68hc11_elf_merge_private_bfd_data
666 1.1 christos #define bfd_elf32_bfd_set_private_flags _bfd_m68hc11_elf_set_private_flags
667 1.1 christos #define bfd_elf32_bfd_print_private_bfd_data \
668 _bfd_m68hc11_elf_print_private_bfd_data
669
670 #include "elf32-target.h"
671