Annotation of src/external/gpl3/binutils.old/dist/bfd/elf32-m68hc12.c, Revision 1.6
1.1 christos 1: /* Motorola 68HC12-specific support for 32-bit ELF
1.6 ! christos 2: Copyright (C) 1999-2018 Free Software Foundation, Inc.
1.1 christos 3: Contributed by Stephane Carrez (stcarrez@nerim.fr)
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 3 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
20: Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21: MA 02110-1301, USA. */
22:
23: #include "sysdep.h"
24: #include "bfd.h"
25: #include "bfdlink.h"
26: #include "libbfd.h"
27: #include "elf-bfd.h"
28: #include "elf32-m68hc1x.h"
29: #include "elf/m68hc11.h"
30: #include "opcode/m68hc11.h"
31:
32: /* Relocation functions. */
33: static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
34: (bfd *, bfd_reloc_code_real_type);
1.6 ! christos 35: static bfd_boolean m68hc11_info_to_howto_rel
1.1 christos 36: (bfd *, arelent *, Elf_Internal_Rela *);
37:
38: /* Trampoline generation. */
39:
40:
41: /* Use REL instead of RELA to save space */
42: #define USE_REL 1
43:
44: /* The 68HC12 microcontroler has a memory bank switching system
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
1.6 ! christos 65: | | Page n
1.1 christos 66: +---------------+ 0x1010000
1.6 ! christos 67: | |
! 68: | jsr _foo |
! 69: | .. | Page 3
! 70: | _foo: |
1.1 christos 71: +---------------+ 0x100C000
1.6 ! christos 72: | |
! 73: | call _bar |
! 74: | .. | Page 2
! 75: | _bar: |
1.1 christos 76: +---------------+ 0x1008000
1.6 ! christos 77: /------>| |
! 78: | | call _foo | Page 1
! 79: | | |
1.1 christos 80: | +---------------+ 0x1004000
1.6 ! christos 81: Physical | | |
! 82: Address Space | | | Page 0
! 83: | | |
1.1 christos 84: +-----------+ 0x00FFFF | +---------------+ 0x1000000
85: | | |
86: | call _foo | |
87: | | |
88: +-----------+ 0x00BFFF -+---/
1.6 ! christos 89: | | |
1.1 christos 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
103: mapped at 0x8000.
104:
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 */
1.3 christos 110: 3, /* size (0 = byte, 1 = short, 2 = long) */
111: 0, /* bitsize */
1.1 christos 112: FALSE, /* pc_relative */
113: 0, /* bitpos */
114: complain_overflow_dont,/* complain_on_overflow */
115: bfd_elf_generic_reloc, /* special_function */
116: "R_M68HC12_NONE", /* name */
117: FALSE, /* partial_inplace */
118: 0, /* src_mask */
119: 0, /* dst_mask */
120: FALSE), /* pcrel_offset */
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 */
127: FALSE, /* pc_relative */
128: 0, /* bitpos */
129: complain_overflow_bitfield, /* complain_on_overflow */
130: bfd_elf_generic_reloc, /* special_function */
131: "R_M68HC12_8", /* name */
132: FALSE, /* partial_inplace */
133: 0x00ff, /* src_mask */
134: 0x00ff, /* dst_mask */
135: FALSE), /* pcrel_offset */
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 */
142: FALSE, /* pc_relative */
143: 0, /* bitpos */
144: complain_overflow_bitfield, /* complain_on_overflow */
145: bfd_elf_generic_reloc, /* special_function */
146: "R_M68HC12_HI8", /* name */
147: FALSE, /* partial_inplace */
148: 0x00ff, /* src_mask */
149: 0x00ff, /* dst_mask */
150: FALSE), /* pcrel_offset */
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 */
157: FALSE, /* pc_relative */
158: 0, /* bitpos */
159: complain_overflow_dont, /* complain_on_overflow */
160: bfd_elf_generic_reloc, /* special_function */
161: "R_M68HC12_LO8", /* name */
162: FALSE, /* partial_inplace */
163: 0x00ff, /* src_mask */
164: 0x00ff, /* dst_mask */
165: FALSE), /* pcrel_offset */
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 */
172: TRUE, /* pc_relative */
173: 0, /* bitpos */
174: complain_overflow_bitfield, /* complain_on_overflow */
175: bfd_elf_generic_reloc, /* special_function */
176: "R_M68HC12_PCREL_8", /* name */
177: FALSE, /* partial_inplace */
178: 0x00ff, /* src_mask */
179: 0x00ff, /* dst_mask */
1.6 ! christos 180: TRUE), /* pcrel_offset */
1.1 christos 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 */
187: FALSE, /* pc_relative */
188: 0, /* bitpos */
189: complain_overflow_dont /*bitfield */ , /* complain_on_overflow */
190: bfd_elf_generic_reloc, /* special_function */
191: "R_M68HC12_16", /* name */
192: FALSE, /* partial_inplace */
193: 0xffff, /* src_mask */
194: 0xffff, /* dst_mask */
195: FALSE), /* pcrel_offset */
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 */
203: FALSE, /* pc_relative */
204: 0, /* bitpos */
205: complain_overflow_bitfield, /* complain_on_overflow */
206: bfd_elf_generic_reloc, /* special_function */
207: "R_M68HC12_32", /* name */
208: FALSE, /* partial_inplace */
209: 0xffffffff, /* src_mask */
210: 0xffffffff, /* dst_mask */
211: FALSE), /* pcrel_offset */
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 */
218: FALSE, /* pc_relative */
219: 0, /* bitpos */
220: complain_overflow_bitfield, /* complain_on_overflow */
221: bfd_elf_generic_reloc, /* special_function */
222: "R_M68HC12_4B", /* name */
223: FALSE, /* partial_inplace */
224: 0x003, /* src_mask */
225: 0x003, /* dst_mask */
226: FALSE), /* pcrel_offset */
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 */
233: TRUE, /* pc_relative */
234: 0, /* bitpos */
235: complain_overflow_dont, /* complain_on_overflow */
236: bfd_elf_generic_reloc, /* special_function */
237: "R_M68HC12_PCREL_16", /* name */
238: FALSE, /* partial_inplace */
239: 0xffff, /* src_mask */
240: 0xffff, /* dst_mask */
1.6 ! christos 241: TRUE), /* pcrel_offset */
1.1 christos 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 */
248: FALSE, /* pc_relative */
249: 0, /* bitpos */
250: complain_overflow_dont, /* complain_on_overflow */
251: NULL, /* special_function */
252: "R_M68HC11_GNU_VTINHERIT", /* name */
253: FALSE, /* partial_inplace */
254: 0, /* src_mask */
255: 0, /* dst_mask */
256: FALSE), /* pcrel_offset */
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 */
263: FALSE, /* pc_relative */
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 */
268: FALSE, /* partial_inplace */
269: 0, /* src_mask */
270: 0, /* dst_mask */
271: FALSE), /* pcrel_offset */
272:
273: /* A 24 bit relocation */
1.6 ! christos 274: HOWTO (R_M68HC11_24, /* type */
1.1 christos 275: 0, /* rightshift */
276: 2, /* size (0 = byte, 1 = short, 2 = long) */
277: 24, /* bitsize */
278: FALSE, /* pc_relative */
279: 0, /* bitpos */
280: complain_overflow_dont, /* complain_on_overflow */
281: m68hc11_elf_special_reloc, /* special_function */
282: "R_M68HC12_24", /* name */
283: FALSE, /* partial_inplace */
284: 0xffffff, /* src_mask */
285: 0xffffff, /* dst_mask */
286: FALSE), /* pcrel_offset */
287:
288: /* A 16-bit low relocation */
1.6 ! christos 289: HOWTO (R_M68HC11_LO16, /* type */
1.1 christos 290: 0, /* rightshift */
291: 1, /* size (0 = byte, 1 = short, 2 = long) */
292: 16, /* bitsize */
293: FALSE, /* pc_relative */
294: 0, /* bitpos */
295: complain_overflow_dont, /* complain_on_overflow */
296: m68hc11_elf_special_reloc,/* special_function */
297: "R_M68HC12_LO16", /* name */
298: FALSE, /* partial_inplace */
299: 0xffff, /* src_mask */
300: 0xffff, /* dst_mask */
301: FALSE), /* pcrel_offset */
302:
303: /* A page relocation */
1.6 ! christos 304: HOWTO (R_M68HC11_PAGE, /* type */
1.1 christos 305: 0, /* rightshift */
306: 0, /* size (0 = byte, 1 = short, 2 = long) */
307: 8, /* bitsize */
308: FALSE, /* pc_relative */
309: 0, /* bitpos */
310: complain_overflow_dont, /* complain_on_overflow */
311: m68hc11_elf_special_reloc,/* special_function */
312: "R_M68HC12_PAGE", /* name */
313: FALSE, /* partial_inplace */
314: 0x00ff, /* src_mask */
315: 0x00ff, /* dst_mask */
316: FALSE), /* pcrel_offset */
317:
318: EMPTY_HOWTO (14),
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 */
1.6 ! christos 331: 0xffff, /* src_mask */
! 332: 0xffff, /* dst_mask */
1.1 christos 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 */
1.6 ! christos 348: TRUE), /* pcrel_offset */
1.1 christos 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 */
1.6 ! christos 363: TRUE), /* pcrel_offset */
1.1 christos 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 */
394:
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 */
400: FALSE, /* pc_relative */
401: 0, /* bitpos */
402: complain_overflow_dont, /* complain_on_overflow */
403: m68hc11_elf_ignore_reloc, /* special_function */
404: "R_M68HC12_RL_JUMP", /* name */
405: TRUE, /* partial_inplace */
406: 0, /* src_mask */
407: 0, /* dst_mask */
1.6 ! christos 408: TRUE), /* pcrel_offset */
1.1 christos 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 */
415: FALSE, /* pc_relative */
416: 0, /* bitpos */
417: complain_overflow_dont, /* complain_on_overflow */
418: m68hc11_elf_ignore_reloc, /* special_function */
419: "R_M68HC12_RL_GROUP", /* name */
420: TRUE, /* partial_inplace */
421: 0, /* src_mask */
422: 0, /* dst_mask */
1.6 ! christos 423: TRUE), /* pcrel_offset */
1.1 christos 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:
434: static const struct m68hc11_reloc_map m68hc11_reloc_map[] =
435: {
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:
446: {BFD_RELOC_VTABLE_INHERIT, R_M68HC11_GNU_VTINHERIT},
447: {BFD_RELOC_VTABLE_ENTRY, R_M68HC11_GNU_VTENTRY},
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},
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},
462: };
463:
464: static reloc_howto_type *
465: bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
1.6 ! christos 466: bfd_reloc_code_real_type code)
1.1 christos 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:
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:
498: /* Set the howto pointer for an M68HC11 ELF reloc. */
499:
1.6 ! christos 500: static bfd_boolean
! 501: m68hc11_info_to_howto_rel (bfd *abfd,
! 502: arelent *cache_ptr, Elf_Internal_Rela *dst)
1.1 christos 503: {
504: unsigned int r_type;
505:
506: r_type = ELF32_R_TYPE (dst->r_info);
1.3 christos 507: if (r_type >= (unsigned int) R_M68HC11_max)
508: {
1.6 ! christos 509: /* xgettext:c-format */
! 510: _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
! 511: abfd, r_type);
! 512: bfd_set_error (bfd_error_bad_value);
! 513: return FALSE;
1.3 christos 514: }
1.1 christos 515: cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
1.6 ! christos 516: return TRUE;
1.1 christos 517: }
518:
519:
520: /* Far trampoline generation. */
521:
522: /* Build a 68HC12 trampoline stub. */
523: static bfd_boolean
524: m68hc12_elf_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
525: {
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;
533:
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;
537:
538: htab = m68hc11_elf_hash_table (info);
539:
540: stub_sec = stub_entry->stub_sec;
541:
542: /* Make a note of the offset within the stubs for this entry. */
543: stub_entry->stub_offset = stub_sec->size;
544: stub_sec->size += 7;
545: loc = stub_sec->contents + stub_entry->stub_offset;
546:
547: stub_bfd = stub_sec->owner;
548:
549: /* Create the trampoline call stub:
550:
551: ldy #%addr(symbol)
552: call %page(symbol), __trampoline
553:
554: */
555: sym_value = (stub_entry->target_value
1.6 ! christos 556: + stub_entry->target_section->output_offset
! 557: + stub_entry->target_section->output_section->vma);
1.1 christos 558: phys_addr = m68hc11_phys_addr (&htab->pinfo, sym_value);
559: phys_page = m68hc11_phys_page (&htab->pinfo, sym_value);
560:
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;
565:
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);
570:
571: return TRUE;
572: }
573:
574: /* As above, but don't actually build the stub. Just bump offset so
575: we know stub section sizes. */
576:
577: static bfd_boolean
578: m68hc12_elf_size_one_stub (struct bfd_hash_entry *gen_entry,
1.6 ! christos 579: void *in_arg ATTRIBUTE_UNUSED)
1.1 christos 580: {
581: struct elf32_m68hc11_stub_hash_entry *stub_entry;
582:
583: /* Massage our args to the form they really have. */
584: stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
585:
586: stub_entry->stub_sec->size += 7;
587: return TRUE;
588: }
589:
590: /* Create a 68HC12 ELF linker hash table. */
591:
592: static struct bfd_link_hash_table *
593: m68hc12_elf_bfd_link_hash_table_create (bfd *abfd)
594: {
595: struct m68hc11_elf_link_hash_table *ret;
596:
597: ret = m68hc11_elf_hash_table_create (abfd);
598: if (ret == (struct m68hc11_elf_link_hash_table *) NULL)
599: return NULL;
600:
601: ret->size_one_stub = m68hc12_elf_size_one_stub;
602: ret->build_one_stub = m68hc12_elf_build_one_stub;
603:
604: return &ret->root.root;
605: }
606:
607: static bfd_boolean
608: m68hc12_elf_set_mach_from_flags (bfd *abfd)
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,
1.6 ! christos 622: bfd_mach_m6812_default);
1.1 christos 623: break;
624: default:
625: return FALSE;
626: }
627: return TRUE;
628: }
629:
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. */
635: static const struct bfd_elf_special_section elf32_m68hc12_special_sections[] =
636: {
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 },
1.6 ! christos 641: { NULL, 0, 0, 0, 0 }
1.1 christos 642: };
643:
644: #define ELF_ARCH bfd_arch_m68hc12
645: #define ELF_TARGET_ID M68HC11_ELF_DATA
646: #define ELF_MACHINE_CODE EM_68HC12
647: #define ELF_MAXPAGESIZE 0x1000
648:
1.6 ! christos 649: #define TARGET_BIG_SYM m68hc12_elf32_vec
1.1 christos 650: #define TARGET_BIG_NAME "elf32-m68hc12"
651:
1.6 ! christos 652: #define elf_info_to_howto NULL
1.1 christos 653: #define elf_info_to_howto_rel m68hc11_info_to_howto_rel
654: #define elf_backend_check_relocs elf32_m68hc11_check_relocs
655: #define elf_backend_relocate_section elf32_m68hc11_relocate_section
656: #define elf_backend_object_p m68hc12_elf_set_mach_from_flags
657: #define elf_backend_final_write_processing 0
658: #define elf_backend_can_gc_sections 1
659: #define elf_backend_special_sections elf32_m68hc12_special_sections
660: #define elf_backend_post_process_headers elf32_m68hc11_post_process_headers
661: #define elf_backend_add_symbol_hook elf32_m68hc11_add_symbol_hook
662: #define elf_backend_merge_symbol_attribute elf32_m68hc11_merge_symbol_attribute
663:
664: #define bfd_elf32_bfd_link_hash_table_create \
1.6 ! christos 665: m68hc12_elf_bfd_link_hash_table_create
1.1 christos 666: #define bfd_elf32_bfd_merge_private_bfd_data \
667: _bfd_m68hc11_elf_merge_private_bfd_data
668: #define bfd_elf32_bfd_set_private_flags _bfd_m68hc11_elf_set_private_flags
669: #define bfd_elf32_bfd_print_private_bfd_data \
670: _bfd_m68hc11_elf_print_private_bfd_data
671:
672: #include "elf32-target.h"
CVSweb <webmaster@jp.NetBSD.org>