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