Rename 'index' to 'offset'
[binutils.git] / bfd / elf32-m68hc12.c
blob219fd6b0da331a371d0f452fa0c5f13f746defee
1 /* Motorola 68HC12-specific support for 32-bit ELF
2 Copyright 1999, 2000, 2002 Free Software Foundation, Inc.
3 Contributed by Stephane Carrez (stcarrez@nerim.fr)
4 (Heavily copied from the D10V port by Martin Hunt (hunt@cygnus.com))
6 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22 #include "bfd.h"
23 #include "sysdep.h"
24 #include "libbfd.h"
25 #include "elf-bfd.h"
26 #include "elf/m68hc11.h"
27 #include "opcode/m68hc11.h"
29 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
30 PARAMS ((bfd *, bfd_reloc_code_real_type));
31 static void m68hc11_info_to_howto_rel
32 PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
34 static bfd_reloc_status_type m68hc11_elf_ignore_reloc
35 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
36 static bfd_reloc_status_type m68hc12_elf_special_reloc
37 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
38 static int m68hc12_addr_is_banked PARAMS ((bfd_vma));
39 static bfd_vma m68hc12_phys_addr PARAMS ((bfd_vma));
40 static bfd_vma m68hc12_phys_page PARAMS ((bfd_vma));
42 /* GC mark and sweep. */
43 static asection *elf32_m68hc11_gc_mark_hook
44 PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
45 struct elf_link_hash_entry *, Elf_Internal_Sym *));
46 static bfd_boolean elf32_m68hc11_gc_sweep_hook
47 PARAMS ((bfd *, struct bfd_link_info *, asection *,
48 const Elf_Internal_Rela *));
50 static bfd_boolean m68hc12_elf_set_mach_from_flags PARAMS ((bfd *));
52 bfd_boolean _bfd_m68hc12_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *));
53 bfd_boolean _bfd_m68hc12_elf_set_private_flags PARAMS ((bfd *, flagword));
54 bfd_boolean _bfd_m68hc12_elf_print_private_bfd_data PARAMS ((bfd *, PTR));
58 /* Use REL instead of RELA to save space */
59 #define USE_REL 1
61 /* The Motorola 68HC11 microcontroler only addresses 64Kb.
62 We must handle 8 and 16-bit relocations. The 32-bit relocation
63 is defined but not used except by gas when -gstabs is used (which
64 is wrong).
66 The 68HC12 microcontroler has a memory bank switching system
67 with a 16Kb window in the 64Kb address space. The extended memory
68 is mapped in the 16Kb window (at 0x8000). The page register controls
69 which 16Kb bank is mapped. The call/rtc instructions take care of
70 bank switching in function calls/returns.
72 For GNU Binutils to work, we consider there is a physical memory
73 at 0..0x0ffff and a kind of virtual memory above that. Symbols
74 in virtual memory have their addresses treated in a special way
75 when disassembling and when linking.
77 For the linker to work properly, we must always relocate the virtual
78 memory as if it is mapped at 0x8000. When a 16-bit relocation is
79 made in the virtual memory, we check that it does not cross the
80 memory bank where it is used. This would involve a page change
81 which would be wrong. The 24-bit relocation is for that and it
82 treats the address as a physical address + page number.
85 Banked
86 Address Space
87 | | Page n
88 +---------------+ 0x1010000
89 | |
90 | jsr _foo |
91 | .. | Page 3
92 | _foo: |
93 +---------------+ 0x100C000
94 | |
95 | call _bar |
96 | .. | Page 2
97 | _bar: |
98 +---------------+ 0x1008000
99 /------>| |
100 | | call _foo | Page 1
101 | | |
102 | +---------------+ 0x1004000
103 Physical | | |
104 Address Space | | | Page 0
105 | | |
106 +-----------+ 0x00FFFF | +---------------+ 0x1000000
107 | | |
108 | call _foo | |
109 | | |
110 +-----------+ 0x00BFFF -+---/
111 | | |
112 | | |
113 | | 16K |
114 | | |
115 +-----------+ 0x008000 -+
121 +-----------+ 0000
124 The 'call _foo' must be relocated with page 3 and 16-bit address
125 mapped at 0x8000.
127 The 3-bit and 16-bit PC rel relocation is only used by 68HC12. */
128 static reloc_howto_type elf_m68hc11_howto_table[] = {
129 /* This reloc does nothing. */
130 HOWTO (R_M68HC11_NONE, /* type */
131 0, /* rightshift */
132 2, /* size (0 = byte, 1 = short, 2 = long) */
133 32, /* bitsize */
134 FALSE, /* pc_relative */
135 0, /* bitpos */
136 complain_overflow_dont,/* complain_on_overflow */
137 bfd_elf_generic_reloc, /* special_function */
138 "R_M68HC12_NONE", /* name */
139 FALSE, /* partial_inplace */
140 0, /* src_mask */
141 0, /* dst_mask */
142 FALSE), /* pcrel_offset */
144 /* A 8 bit absolute relocation */
145 HOWTO (R_M68HC11_8, /* type */
146 0, /* rightshift */
147 0, /* size (0 = byte, 1 = short, 2 = long) */
148 8, /* bitsize */
149 FALSE, /* pc_relative */
150 0, /* bitpos */
151 complain_overflow_bitfield, /* complain_on_overflow */
152 bfd_elf_generic_reloc, /* special_function */
153 "R_M68HC12_8", /* name */
154 FALSE, /* partial_inplace */
155 0x00ff, /* src_mask */
156 0x00ff, /* dst_mask */
157 FALSE), /* pcrel_offset */
159 /* A 8 bit absolute relocation (upper address) */
160 HOWTO (R_M68HC11_HI8, /* type */
161 8, /* rightshift */
162 0, /* size (0 = byte, 1 = short, 2 = long) */
163 8, /* bitsize */
164 FALSE, /* pc_relative */
165 0, /* bitpos */
166 complain_overflow_bitfield, /* complain_on_overflow */
167 bfd_elf_generic_reloc, /* special_function */
168 "R_M68HC12_HI8", /* name */
169 FALSE, /* partial_inplace */
170 0x00ff, /* src_mask */
171 0x00ff, /* dst_mask */
172 FALSE), /* pcrel_offset */
174 /* A 8 bit absolute relocation (upper address) */
175 HOWTO (R_M68HC11_LO8, /* type */
176 0, /* rightshift */
177 0, /* size (0 = byte, 1 = short, 2 = long) */
178 8, /* bitsize */
179 FALSE, /* pc_relative */
180 0, /* bitpos */
181 complain_overflow_dont, /* complain_on_overflow */
182 bfd_elf_generic_reloc, /* special_function */
183 "R_M68HC12_LO8", /* name */
184 FALSE, /* partial_inplace */
185 0x00ff, /* src_mask */
186 0x00ff, /* dst_mask */
187 FALSE), /* pcrel_offset */
189 /* A 8 bit PC-rel relocation */
190 HOWTO (R_M68HC11_PCREL_8, /* type */
191 0, /* rightshift */
192 0, /* size (0 = byte, 1 = short, 2 = long) */
193 8, /* bitsize */
194 TRUE, /* pc_relative */
195 0, /* bitpos */
196 complain_overflow_bitfield, /* complain_on_overflow */
197 bfd_elf_generic_reloc, /* special_function */
198 "R_M68HC12_PCREL_8", /* name */
199 FALSE, /* partial_inplace */
200 0x00ff, /* src_mask */
201 0x00ff, /* dst_mask */
202 FALSE), /* pcrel_offset */
204 /* A 16 bit absolute relocation */
205 HOWTO (R_M68HC11_16, /* type */
206 0, /* rightshift */
207 1, /* size (0 = byte, 1 = short, 2 = long) */
208 16, /* bitsize */
209 FALSE, /* pc_relative */
210 0, /* bitpos */
211 complain_overflow_dont /*bitfield */ , /* complain_on_overflow */
212 m68hc12_elf_special_reloc, /* special_function */
213 "R_M68HC12_16", /* name */
214 FALSE, /* partial_inplace */
215 0xffff, /* src_mask */
216 0xffff, /* dst_mask */
217 FALSE), /* pcrel_offset */
219 /* A 32 bit absolute relocation. This one is never used for the
220 code relocation. It's used by gas for -gstabs generation. */
221 HOWTO (R_M68HC11_32, /* type */
222 0, /* rightshift */
223 2, /* size (0 = byte, 1 = short, 2 = long) */
224 32, /* bitsize */
225 FALSE, /* pc_relative */
226 0, /* bitpos */
227 complain_overflow_bitfield, /* complain_on_overflow */
228 bfd_elf_generic_reloc, /* special_function */
229 "R_M68HC12_32", /* name */
230 FALSE, /* partial_inplace */
231 0xffffffff, /* src_mask */
232 0xffffffff, /* dst_mask */
233 FALSE), /* pcrel_offset */
235 /* A 3 bit absolute relocation */
236 HOWTO (R_M68HC11_3B, /* type */
237 0, /* rightshift */
238 0, /* size (0 = byte, 1 = short, 2 = long) */
239 3, /* bitsize */
240 FALSE, /* pc_relative */
241 0, /* bitpos */
242 complain_overflow_bitfield, /* complain_on_overflow */
243 bfd_elf_generic_reloc, /* special_function */
244 "R_M68HC12_4B", /* name */
245 FALSE, /* partial_inplace */
246 0x003, /* src_mask */
247 0x003, /* dst_mask */
248 FALSE), /* pcrel_offset */
250 /* A 16 bit PC-rel relocation */
251 HOWTO (R_M68HC11_PCREL_16, /* type */
252 0, /* rightshift */
253 1, /* size (0 = byte, 1 = short, 2 = long) */
254 16, /* bitsize */
255 TRUE, /* pc_relative */
256 0, /* bitpos */
257 complain_overflow_dont, /* complain_on_overflow */
258 bfd_elf_generic_reloc, /* special_function */
259 "R_M68HC12_PCREL_16", /* name */
260 FALSE, /* partial_inplace */
261 0xffff, /* src_mask */
262 0xffff, /* dst_mask */
263 FALSE), /* pcrel_offset */
265 /* GNU extension to record C++ vtable hierarchy */
266 HOWTO (R_M68HC11_GNU_VTINHERIT, /* type */
267 0, /* rightshift */
268 1, /* size (0 = byte, 1 = short, 2 = long) */
269 0, /* bitsize */
270 FALSE, /* pc_relative */
271 0, /* bitpos */
272 complain_overflow_dont, /* complain_on_overflow */
273 NULL, /* special_function */
274 "R_M68HC11_GNU_VTINHERIT", /* name */
275 FALSE, /* partial_inplace */
276 0, /* src_mask */
277 0, /* dst_mask */
278 FALSE), /* pcrel_offset */
280 /* GNU extension to record C++ vtable member usage */
281 HOWTO (R_M68HC11_GNU_VTENTRY, /* type */
282 0, /* rightshift */
283 1, /* size (0 = byte, 1 = short, 2 = long) */
284 0, /* bitsize */
285 FALSE, /* pc_relative */
286 0, /* bitpos */
287 complain_overflow_dont, /* complain_on_overflow */
288 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
289 "R_M68HC11_GNU_VTENTRY", /* name */
290 FALSE, /* partial_inplace */
291 0, /* src_mask */
292 0, /* dst_mask */
293 FALSE), /* pcrel_offset */
295 /* A 24 bit relocation */
296 HOWTO (R_M68HC11_24, /* type */
297 0, /* rightshift */
298 1, /* size (0 = byte, 1 = short, 2 = long) */
299 24, /* bitsize */
300 FALSE, /* pc_relative */
301 0, /* bitpos */
302 complain_overflow_dont, /* complain_on_overflow */
303 m68hc12_elf_special_reloc, /* special_function */
304 "R_M68HC12_24", /* name */
305 FALSE, /* partial_inplace */
306 0xffff, /* src_mask */
307 0xffff, /* dst_mask */
308 FALSE), /* pcrel_offset */
310 /* A 16-bit low relocation */
311 HOWTO (R_M68HC11_LO16, /* type */
312 0, /* rightshift */
313 1, /* size (0 = byte, 1 = short, 2 = long) */
314 16, /* bitsize */
315 FALSE, /* pc_relative */
316 0, /* bitpos */
317 complain_overflow_dont, /* complain_on_overflow */
318 m68hc12_elf_special_reloc,/* special_function */
319 "R_M68HC12_LO16", /* name */
320 FALSE, /* partial_inplace */
321 0xffff, /* src_mask */
322 0xffff, /* dst_mask */
323 FALSE), /* pcrel_offset */
325 /* A page relocation */
326 HOWTO (R_M68HC11_PAGE, /* type */
327 0, /* rightshift */
328 0, /* size (0 = byte, 1 = short, 2 = long) */
329 8, /* bitsize */
330 FALSE, /* pc_relative */
331 0, /* bitpos */
332 complain_overflow_dont, /* complain_on_overflow */
333 m68hc12_elf_special_reloc,/* special_function */
334 "R_M68HC12_PAGE", /* name */
335 FALSE, /* partial_inplace */
336 0x00ff, /* src_mask */
337 0x00ff, /* dst_mask */
338 FALSE), /* pcrel_offset */
340 EMPTY_HOWTO (14),
341 EMPTY_HOWTO (15),
342 EMPTY_HOWTO (16),
343 EMPTY_HOWTO (17),
344 EMPTY_HOWTO (18),
345 EMPTY_HOWTO (19),
347 /* Mark beginning of a jump instruction (any form). */
348 HOWTO (R_M68HC11_RL_JUMP, /* type */
349 0, /* rightshift */
350 1, /* size (0 = byte, 1 = short, 2 = long) */
351 0, /* bitsize */
352 FALSE, /* pc_relative */
353 0, /* bitpos */
354 complain_overflow_dont, /* complain_on_overflow */
355 m68hc11_elf_ignore_reloc, /* special_function */
356 "R_M68HC12_RL_JUMP", /* name */
357 TRUE, /* partial_inplace */
358 0, /* src_mask */
359 0, /* dst_mask */
360 TRUE), /* pcrel_offset */
362 /* Mark beginning of Gcc relaxation group instruction. */
363 HOWTO (R_M68HC11_RL_GROUP, /* type */
364 0, /* rightshift */
365 1, /* size (0 = byte, 1 = short, 2 = long) */
366 0, /* bitsize */
367 FALSE, /* pc_relative */
368 0, /* bitpos */
369 complain_overflow_dont, /* complain_on_overflow */
370 m68hc11_elf_ignore_reloc, /* special_function */
371 "R_M68HC12_RL_GROUP", /* name */
372 TRUE, /* partial_inplace */
373 0, /* src_mask */
374 0, /* dst_mask */
375 TRUE), /* pcrel_offset */
378 /* Map BFD reloc types to M68HC11 ELF reloc types. */
380 struct m68hc11_reloc_map
382 bfd_reloc_code_real_type bfd_reloc_val;
383 unsigned char elf_reloc_val;
386 static const struct m68hc11_reloc_map m68hc11_reloc_map[] = {
387 {BFD_RELOC_NONE, R_M68HC11_NONE,},
388 {BFD_RELOC_8, R_M68HC11_8},
389 {BFD_RELOC_M68HC11_HI8, R_M68HC11_HI8},
390 {BFD_RELOC_M68HC11_LO8, R_M68HC11_LO8},
391 {BFD_RELOC_8_PCREL, R_M68HC11_PCREL_8},
392 {BFD_RELOC_16_PCREL, R_M68HC11_PCREL_16},
393 {BFD_RELOC_16, R_M68HC11_16},
394 {BFD_RELOC_32, R_M68HC11_32},
395 {BFD_RELOC_M68HC11_3B, R_M68HC11_3B},
397 {BFD_RELOC_VTABLE_INHERIT, R_M68HC11_GNU_VTINHERIT},
398 {BFD_RELOC_VTABLE_ENTRY, R_M68HC11_GNU_VTENTRY},
400 {BFD_RELOC_M68HC11_LO16, R_M68HC11_LO16},
401 {BFD_RELOC_M68HC11_PAGE, R_M68HC11_PAGE},
402 {BFD_RELOC_M68HC11_24, R_M68HC11_24},
404 {BFD_RELOC_M68HC11_RL_JUMP, R_M68HC11_RL_JUMP},
405 {BFD_RELOC_M68HC11_RL_GROUP, R_M68HC11_RL_GROUP},
408 static reloc_howto_type *
409 bfd_elf32_bfd_reloc_type_lookup (abfd, code)
410 bfd *abfd ATTRIBUTE_UNUSED;
411 bfd_reloc_code_real_type code;
413 unsigned int i;
415 for (i = 0;
416 i < sizeof (m68hc11_reloc_map) / sizeof (struct m68hc11_reloc_map);
417 i++)
419 if (m68hc11_reloc_map[i].bfd_reloc_val == code)
420 return &elf_m68hc11_howto_table[m68hc11_reloc_map[i].elf_reloc_val];
423 return NULL;
426 /* This function is used for relocs which are only used for relaxing,
427 which the linker should otherwise ignore. */
429 static bfd_reloc_status_type
430 m68hc11_elf_ignore_reloc (abfd, reloc_entry, symbol, data, input_section,
431 output_bfd, error_message)
432 bfd *abfd ATTRIBUTE_UNUSED;
433 arelent *reloc_entry;
434 asymbol *symbol ATTRIBUTE_UNUSED;
435 PTR data ATTRIBUTE_UNUSED;
436 asection *input_section;
437 bfd *output_bfd;
438 char **error_message ATTRIBUTE_UNUSED;
440 if (output_bfd != NULL)
441 reloc_entry->address += input_section->output_offset;
442 return bfd_reloc_ok;
445 static int
446 m68hc12_addr_is_banked (addr)
447 bfd_vma addr;
449 return (addr >= M68HC12_BANK_VIRT) ? 1 : 0;
452 /* Return the physical address seen by the processor, taking
453 into account banked memory. */
454 static bfd_vma
455 m68hc12_phys_addr (addr)
456 bfd_vma addr;
458 if (addr < M68HC12_BANK_VIRT)
459 return addr;
461 /* Map the address to the memory bank. */
462 addr -= M68HC12_BANK_VIRT;
463 addr &= M68HC12_BANK_MASK;
464 addr += M68HC12_BANK_BASE;
465 return addr;
468 /* Return the page number corresponding to an address in banked memory. */
469 static bfd_vma
470 m68hc12_phys_page (addr)
471 bfd_vma addr;
473 if (addr < M68HC12_BANK_VIRT)
474 return 0;
476 /* Map the address to the memory bank. */
477 addr -= M68HC12_BANK_VIRT;
478 addr >>= M68HC12_BANK_SHIFT;
479 addr &= M68HC12_BANK_PAGE_MASK;
480 return addr;
483 static bfd_reloc_status_type
484 m68hc12_elf_special_reloc (abfd, reloc_entry, symbol, data, input_section,
485 output_bfd, error_message)
486 bfd *abfd;
487 arelent *reloc_entry;
488 asymbol *symbol;
489 PTR data;
490 asection *input_section;
491 bfd *output_bfd;
492 char **error_message ATTRIBUTE_UNUSED;
494 reloc_howto_type *howto;
495 bfd_vma relocation;
496 bfd_vma phys_addr;
497 bfd_vma phys_page;
498 bfd_vma insn_page;
499 bfd_vma insn_addr;
501 if (output_bfd != (bfd *) NULL
502 && (symbol->flags & BSF_SECTION_SYM) == 0
503 && (! reloc_entry->howto->partial_inplace
504 || reloc_entry->addend == 0))
506 reloc_entry->address += input_section->output_offset;
507 return bfd_reloc_ok;
510 if (output_bfd != NULL)
511 return bfd_reloc_continue;
513 if (reloc_entry->address > input_section->_cooked_size)
514 return bfd_reloc_outofrange;
516 /* Compute relocation. */
517 relocation = (symbol->value
518 + symbol->section->output_section->vma
519 + symbol->section->output_offset);
520 relocation += reloc_entry->addend;
521 relocation += bfd_get_16 (abfd, (bfd_byte*) data + reloc_entry->address);
523 /* Do the memory bank mapping. */
524 phys_addr = m68hc12_phys_addr (relocation);
525 phys_page = m68hc12_phys_page (relocation);
527 howto = reloc_entry->howto;
528 if (howto->complain_on_overflow != complain_overflow_dont
529 && (phys_addr & (((bfd_vma) -1) << 16)))
530 return bfd_reloc_overflow;
532 switch (howto->type)
534 case R_M68HC11_16:
535 /* Get virtual address of instruction having the relocation. */
536 insn_addr = input_section->output_section->vma
537 + input_section->output_offset
538 + reloc_entry->address;
540 insn_page = m68hc12_phys_page (insn_addr);
542 if (m68hc12_addr_is_banked (relocation)
543 && m68hc12_addr_is_banked (insn_addr)
544 && phys_page != insn_page)
546 *error_message = _("address is not in the same bank");
547 return bfd_reloc_dangerous;
549 if (m68hc12_addr_is_banked (relocation)
550 && !m68hc12_addr_is_banked (insn_addr))
552 *error_message = _("reference to a banked address in "
553 "the normal address space");
554 return bfd_reloc_dangerous;
557 case R_M68HC11_LO16:
558 bfd_put_16 (abfd, phys_addr, (bfd_byte*) data + reloc_entry->address);
559 break;
561 case R_M68HC11_24:
562 bfd_put_16 (abfd, phys_addr, (bfd_byte*) data + reloc_entry->address);
563 bfd_put_8 (abfd, phys_page, (bfd_byte*) data + reloc_entry->address + 2);
564 break;
566 case R_M68HC11_PAGE:
567 bfd_put_8 (abfd, phys_page, (bfd_byte*) data + reloc_entry->address);
568 break;
570 default:
571 abort ();
572 break;
575 return bfd_reloc_ok;
578 /* Set the howto pointer for an M68HC11 ELF reloc. */
580 static void
581 m68hc11_info_to_howto_rel (abfd, cache_ptr, dst)
582 bfd *abfd ATTRIBUTE_UNUSED;
583 arelent *cache_ptr;
584 Elf_Internal_Rela *dst;
586 unsigned int r_type;
588 r_type = ELF32_R_TYPE (dst->r_info);
589 BFD_ASSERT (r_type < (unsigned int) R_M68HC11_max);
590 cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
593 static asection *
594 elf32_m68hc11_gc_mark_hook (sec, info, rel, h, sym)
595 asection *sec;
596 struct bfd_link_info *info ATTRIBUTE_UNUSED;
597 Elf_Internal_Rela *rel;
598 struct elf_link_hash_entry *h;
599 Elf_Internal_Sym *sym;
601 if (h != NULL)
603 switch (ELF32_R_TYPE (rel->r_info))
605 default:
606 switch (h->root.type)
608 case bfd_link_hash_defined:
609 case bfd_link_hash_defweak:
610 return h->root.u.def.section;
612 case bfd_link_hash_common:
613 return h->root.u.c.p->section;
615 default:
616 break;
620 else
621 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
623 return NULL;
626 static bfd_boolean
627 elf32_m68hc11_gc_sweep_hook (abfd, info, sec, relocs)
628 bfd *abfd ATTRIBUTE_UNUSED;
629 struct bfd_link_info *info ATTRIBUTE_UNUSED;
630 asection *sec ATTRIBUTE_UNUSED;
631 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
633 /* We don't use got and plt entries for 68hc11/68hc12. */
634 return TRUE;
638 static bfd_boolean
639 m68hc12_elf_set_mach_from_flags (abfd)
640 bfd *abfd;
642 flagword flags = elf_elfheader (abfd)->e_flags;
644 switch (flags & EF_M68HC11_MACH_MASK)
646 case EF_M68HC12_MACH:
647 bfd_default_set_arch_mach (abfd, bfd_arch_m68hc12, bfd_mach_m6812);
648 break;
649 case EF_M68HCS12_MACH:
650 bfd_default_set_arch_mach (abfd, bfd_arch_m68hc12, bfd_mach_m6812s);
651 break;
652 case EF_M68HC11_GENERIC:
653 bfd_default_set_arch_mach (abfd, bfd_arch_m68hc12,
654 bfd_mach_m6812_default);
655 break;
656 default:
657 return FALSE;
659 return TRUE;
662 /* Set and control ELF flags in ELF header. */
664 bfd_boolean
665 _bfd_m68hc12_elf_set_private_flags (abfd, flags)
666 bfd *abfd;
667 flagword flags;
669 BFD_ASSERT (!elf_flags_init (abfd)
670 || elf_elfheader (abfd)->e_flags == flags);
672 elf_elfheader (abfd)->e_flags = flags;
673 elf_flags_init (abfd) = TRUE;
674 return m68hc12_elf_set_mach_from_flags (abfd);
677 /* Merge backend specific data from an object file to the output
678 object file when linking. */
680 bfd_boolean
681 _bfd_m68hc12_elf_merge_private_bfd_data (ibfd, obfd)
682 bfd *ibfd;
683 bfd *obfd;
685 flagword old_flags;
686 flagword new_flags;
687 bfd_boolean ok = TRUE;
689 /* Check if we have the same endianess */
690 if (!_bfd_generic_verify_endian_match (ibfd, obfd))
691 return FALSE;
693 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
694 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
695 return TRUE;
697 new_flags = elf_elfheader (ibfd)->e_flags;
698 old_flags = elf_elfheader (obfd)->e_flags;
700 if (! elf_flags_init (obfd))
702 elf_flags_init (obfd) = TRUE;
703 elf_elfheader (obfd)->e_flags = new_flags;
704 elf_elfheader (obfd)->e_ident[EI_CLASS]
705 = elf_elfheader (ibfd)->e_ident[EI_CLASS];
707 if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
708 && bfd_get_arch_info (obfd)->the_default)
710 if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
711 bfd_get_mach (ibfd)))
712 return FALSE;
715 return TRUE;
718 /* Check ABI compatibility. */
719 if ((new_flags & E_M68HC11_I32) != (old_flags & E_M68HC11_I32))
721 (*_bfd_error_handler)
722 (_("%s: linking files compiled for 16-bit integers (-mshort) "
723 "and others for 32-bit integers"),
724 bfd_archive_filename (ibfd));
725 ok = FALSE;
727 if ((new_flags & E_M68HC11_F64) != (old_flags & E_M68HC11_F64))
729 (*_bfd_error_handler)
730 (_("%s: linking files compiled for 32-bit double (-fshort-double) "
731 "and others for 64-bit double"),
732 bfd_archive_filename (ibfd));
733 ok = FALSE;
736 /* Processor compatibility. */
737 if (!EF_M68HC11_CAN_MERGE_MACH (new_flags, old_flags))
739 (*_bfd_error_handler)
740 (_("%s: linking files compiled for HCS12 with "
741 "others compiled for HC12"),
742 bfd_archive_filename (ibfd));
743 ok = FALSE;
745 new_flags = ((new_flags & ~EF_M68HC11_MACH_MASK)
746 | (EF_M68HC11_MERGE_MACH (new_flags, old_flags)));
748 elf_elfheader (obfd)->e_flags = new_flags;
750 /* Warn about any other mismatches */
751 new_flags &= ~(EF_M68HC11_ABI | EF_M68HC11_MACH_MASK);
752 old_flags &= ~(EF_M68HC11_ABI | EF_M68HC11_MACH_MASK);
753 if (new_flags != old_flags)
755 (*_bfd_error_handler)
756 (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
757 bfd_archive_filename (ibfd), (unsigned long) new_flags,
758 (unsigned long) old_flags);
759 ok = FALSE;
762 if (! ok)
764 bfd_set_error (bfd_error_bad_value);
765 return FALSE;
768 return TRUE;
771 bfd_boolean
772 _bfd_m68hc12_elf_print_private_bfd_data (abfd, ptr)
773 bfd *abfd;
774 PTR ptr;
776 FILE *file = (FILE *) ptr;
778 BFD_ASSERT (abfd != NULL && ptr != NULL);
780 /* Print normal ELF private data. */
781 _bfd_elf_print_private_bfd_data (abfd, ptr);
783 /* xgettext:c-format */
784 fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
786 if (elf_elfheader (abfd)->e_flags & E_M68HC11_I32)
787 fprintf (file, _("[abi=32-bit int,"));
788 else
789 fprintf (file, _("[abi=16-bit int,"));
791 if (elf_elfheader (abfd)->e_flags & E_M68HC11_F64)
792 fprintf (file, _(" 64-bit double,"));
793 else
794 fprintf (file, _(" 32-bit double,"));
796 if (elf_elfheader (abfd)->e_flags & EF_M68HCS12_MACH)
797 fprintf (file, _(" cpu=HCS12]"));
798 else
799 fprintf (file, _(" cpu=HC12]"));
800 fputc ('\n', file);
802 return TRUE;
805 #define ELF_ARCH bfd_arch_m68hc12
806 #define ELF_MACHINE_CODE EM_68HC12
807 #define ELF_MAXPAGESIZE 0x1000
809 #define TARGET_BIG_SYM bfd_elf32_m68hc12_vec
810 #define TARGET_BIG_NAME "elf32-m68hc12"
812 #define elf_info_to_howto 0
813 #define elf_info_to_howto_rel m68hc11_info_to_howto_rel
814 #define elf_backend_gc_mark_hook elf32_m68hc11_gc_mark_hook
815 #define elf_backend_gc_sweep_hook elf32_m68hc11_gc_sweep_hook
816 #define elf_backend_object_p m68hc12_elf_set_mach_from_flags
817 #define elf_backend_final_write_processing 0
818 /* Disabled as this backend uses the generic linker. */
819 #define elf_backend_can_gc_sections 0
821 #define bfd_elf32_bfd_merge_private_bfd_data \
822 _bfd_m68hc12_elf_merge_private_bfd_data
823 #define bfd_elf32_bfd_set_private_flags _bfd_m68hc12_elf_set_private_flags
824 #define bfd_elf32_bfd_print_private_bfd_data \
825 _bfd_m68hc12_elf_print_private_bfd_data
827 #include "elf32-target.h"