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