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