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