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