* readelf.c (byte_get_little_endian): Comment typo fix.
[binutils.git] / bfd / elf32-m68hc12.c
blobea12e3b999e779c72957db0bc28c66a3fa6b83eb
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 *, Elf32_Internal_Rel *));
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 boolean elf32_m68hc11_gc_sweep_hook
47 PARAMS ((bfd *, struct bfd_link_info *, asection *,
48 const Elf_Internal_Rela *));
50 boolean _bfd_m68hc12_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *));
51 boolean _bfd_m68hc12_elf_set_private_flags PARAMS ((bfd *, flagword));
52 boolean _bfd_m68hc12_elf_print_private_bfd_data PARAMS ((bfd *, PTR));
56 /* Use REL instead of RELA to save space */
57 #define USE_REL 1
59 /* The Motorola 68HC11 microcontroler only addresses 64Kb.
60 We must handle 8 and 16-bit relocations. The 32-bit relocation
61 is defined but not used except by gas when -gstabs is used (which
62 is wrong).
64 The 68HC12 microcontroler has a memory bank switching system
65 with a 16Kb window in the 64Kb address space. The extended memory
66 is mapped in the 16Kb window (at 0x8000). The page register controls
67 which 16Kb bank is mapped. The call/rtc instructions take care of
68 bank switching in function calls/returns.
70 For GNU Binutils to work, we consider there is a physical memory
71 at 0..0x0ffff and a kind of virtual memory above that. Symbols
72 in virtual memory have their addresses treated in a special way
73 when disassembling and when linking.
75 For the linker to work properly, we must always relocate the virtual
76 memory as if it is mapped at 0x8000. When a 16-bit relocation is
77 made in the virtual memory, we check that it does not cross the
78 memory bank where it is used. This would involve a page change
79 which would be wrong. The 24-bit relocation is for that and it
80 treats the address as a physical address + page number.
83 Banked
84 Address Space
85 | | Page n
86 +---------------+ 0x1010000
87 | |
88 | jsr _foo |
89 | .. | Page 3
90 | _foo: |
91 +---------------+ 0x100C000
92 | |
93 | call _bar |
94 | .. | Page 2
95 | _bar: |
96 +---------------+ 0x1008000
97 /------>| |
98 | | call _foo | Page 1
99 | | |
100 | +---------------+ 0x1004000
101 Physical | | |
102 Address Space | | | Page 0
103 | | |
104 +-----------+ 0x00FFFF | +---------------+ 0x1000000
105 | | |
106 | call _foo | |
107 | | |
108 +-----------+ 0x00BFFF -+---/
109 | | |
110 | | |
111 | | 16K |
112 | | |
113 +-----------+ 0x008000 -+
119 +-----------+ 0000
122 The 'call _foo' must be relocated with page 3 and 16-bit address
123 mapped at 0x8000.
125 The 3-bit and 16-bit PC rel relocation is only used by 68HC12. */
126 static reloc_howto_type elf_m68hc11_howto_table[] = {
127 /* This reloc does nothing. */
128 HOWTO (R_M68HC11_NONE, /* type */
129 0, /* rightshift */
130 2, /* size (0 = byte, 1 = short, 2 = long) */
131 32, /* bitsize */
132 false, /* pc_relative */
133 0, /* bitpos */
134 complain_overflow_dont,/* complain_on_overflow */
135 bfd_elf_generic_reloc, /* special_function */
136 "R_M68HC12_NONE", /* name */
137 false, /* partial_inplace */
138 0, /* src_mask */
139 0, /* dst_mask */
140 false), /* pcrel_offset */
142 /* A 8 bit absolute relocation */
143 HOWTO (R_M68HC11_8, /* type */
144 0, /* rightshift */
145 0, /* size (0 = byte, 1 = short, 2 = long) */
146 8, /* bitsize */
147 false, /* pc_relative */
148 0, /* bitpos */
149 complain_overflow_bitfield, /* complain_on_overflow */
150 bfd_elf_generic_reloc, /* special_function */
151 "R_M68HC12_8", /* name */
152 false, /* partial_inplace */
153 0x00ff, /* src_mask */
154 0x00ff, /* dst_mask */
155 false), /* pcrel_offset */
157 /* A 8 bit absolute relocation (upper address) */
158 HOWTO (R_M68HC11_HI8, /* type */
159 8, /* rightshift */
160 0, /* size (0 = byte, 1 = short, 2 = long) */
161 8, /* bitsize */
162 false, /* pc_relative */
163 0, /* bitpos */
164 complain_overflow_bitfield, /* complain_on_overflow */
165 bfd_elf_generic_reloc, /* special_function */
166 "R_M68HC12_HI8", /* name */
167 false, /* partial_inplace */
168 0x00ff, /* src_mask */
169 0x00ff, /* dst_mask */
170 false), /* pcrel_offset */
172 /* A 8 bit absolute relocation (upper address) */
173 HOWTO (R_M68HC11_LO8, /* type */
174 0, /* rightshift */
175 0, /* size (0 = byte, 1 = short, 2 = long) */
176 8, /* bitsize */
177 false, /* pc_relative */
178 0, /* bitpos */
179 complain_overflow_dont, /* complain_on_overflow */
180 bfd_elf_generic_reloc, /* special_function */
181 "R_M68HC12_LO8", /* name */
182 false, /* partial_inplace */
183 0x00ff, /* src_mask */
184 0x00ff, /* dst_mask */
185 false), /* pcrel_offset */
187 /* A 8 bit PC-rel relocation */
188 HOWTO (R_M68HC11_PCREL_8, /* type */
189 0, /* rightshift */
190 0, /* size (0 = byte, 1 = short, 2 = long) */
191 8, /* bitsize */
192 true, /* pc_relative */
193 0, /* bitpos */
194 complain_overflow_bitfield, /* complain_on_overflow */
195 bfd_elf_generic_reloc, /* special_function */
196 "R_M68HC12_PCREL_8", /* name */
197 false, /* partial_inplace */
198 0x00ff, /* src_mask */
199 0x00ff, /* dst_mask */
200 false), /* pcrel_offset */
202 /* A 16 bit absolute relocation */
203 HOWTO (R_M68HC11_16, /* type */
204 0, /* rightshift */
205 1, /* size (0 = byte, 1 = short, 2 = long) */
206 16, /* bitsize */
207 false, /* pc_relative */
208 0, /* bitpos */
209 complain_overflow_dont /*bitfield */ , /* complain_on_overflow */
210 m68hc12_elf_special_reloc, /* special_function */
211 "R_M68HC12_16", /* name */
212 false, /* partial_inplace */
213 0xffff, /* src_mask */
214 0xffff, /* dst_mask */
215 false), /* pcrel_offset */
217 /* A 32 bit absolute relocation. This one is never used for the
218 code relocation. It's used by gas for -gstabs generation. */
219 HOWTO (R_M68HC11_32, /* type */
220 0, /* rightshift */
221 2, /* size (0 = byte, 1 = short, 2 = long) */
222 32, /* bitsize */
223 false, /* pc_relative */
224 0, /* bitpos */
225 complain_overflow_bitfield, /* complain_on_overflow */
226 bfd_elf_generic_reloc, /* special_function */
227 "R_M68HC12_32", /* name */
228 false, /* partial_inplace */
229 0xffffffff, /* src_mask */
230 0xffffffff, /* dst_mask */
231 false), /* pcrel_offset */
233 /* A 3 bit absolute relocation */
234 HOWTO (R_M68HC11_3B, /* type */
235 0, /* rightshift */
236 0, /* size (0 = byte, 1 = short, 2 = long) */
237 3, /* bitsize */
238 false, /* pc_relative */
239 0, /* bitpos */
240 complain_overflow_bitfield, /* complain_on_overflow */
241 bfd_elf_generic_reloc, /* special_function */
242 "R_M68HC12_4B", /* name */
243 false, /* partial_inplace */
244 0x003, /* src_mask */
245 0x003, /* dst_mask */
246 false), /* pcrel_offset */
248 /* A 16 bit PC-rel relocation */
249 HOWTO (R_M68HC11_PCREL_16, /* type */
250 0, /* rightshift */
251 1, /* size (0 = byte, 1 = short, 2 = long) */
252 16, /* bitsize */
253 true, /* pc_relative */
254 0, /* bitpos */
255 complain_overflow_dont, /* complain_on_overflow */
256 bfd_elf_generic_reloc, /* special_function */
257 "R_M68HC12_PCREL_16", /* name */
258 false, /* partial_inplace */
259 0xffff, /* src_mask */
260 0xffff, /* dst_mask */
261 false), /* pcrel_offset */
263 /* GNU extension to record C++ vtable hierarchy */
264 HOWTO (R_M68HC11_GNU_VTINHERIT, /* type */
265 0, /* rightshift */
266 1, /* size (0 = byte, 1 = short, 2 = long) */
267 0, /* bitsize */
268 false, /* pc_relative */
269 0, /* bitpos */
270 complain_overflow_dont, /* complain_on_overflow */
271 NULL, /* special_function */
272 "R_M68HC11_GNU_VTINHERIT", /* name */
273 false, /* partial_inplace */
274 0, /* src_mask */
275 0, /* dst_mask */
276 false), /* pcrel_offset */
278 /* GNU extension to record C++ vtable member usage */
279 HOWTO (R_M68HC11_GNU_VTENTRY, /* type */
280 0, /* rightshift */
281 1, /* size (0 = byte, 1 = short, 2 = long) */
282 0, /* bitsize */
283 false, /* pc_relative */
284 0, /* bitpos */
285 complain_overflow_dont, /* complain_on_overflow */
286 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
287 "R_M68HC11_GNU_VTENTRY", /* name */
288 false, /* partial_inplace */
289 0, /* src_mask */
290 0, /* dst_mask */
291 false), /* pcrel_offset */
293 /* A 24 bit relocation */
294 HOWTO (R_M68HC11_24, /* type */
295 0, /* rightshift */
296 1, /* size (0 = byte, 1 = short, 2 = long) */
297 24, /* bitsize */
298 false, /* pc_relative */
299 0, /* bitpos */
300 complain_overflow_dont, /* complain_on_overflow */
301 m68hc12_elf_special_reloc, /* special_function */
302 "R_M68HC12_24", /* name */
303 false, /* partial_inplace */
304 0xffff, /* src_mask */
305 0xffff, /* dst_mask */
306 false), /* pcrel_offset */
308 /* A 16-bit low relocation */
309 HOWTO (R_M68HC11_LO16, /* type */
310 0, /* rightshift */
311 1, /* size (0 = byte, 1 = short, 2 = long) */
312 16, /* bitsize */
313 false, /* pc_relative */
314 0, /* bitpos */
315 complain_overflow_dont, /* complain_on_overflow */
316 m68hc12_elf_special_reloc,/* special_function */
317 "R_M68HC12_LO16", /* name */
318 false, /* partial_inplace */
319 0xffff, /* src_mask */
320 0xffff, /* dst_mask */
321 false), /* pcrel_offset */
323 /* A page relocation */
324 HOWTO (R_M68HC11_PAGE, /* type */
325 0, /* rightshift */
326 0, /* size (0 = byte, 1 = short, 2 = long) */
327 8, /* bitsize */
328 false, /* pc_relative */
329 0, /* bitpos */
330 complain_overflow_dont, /* complain_on_overflow */
331 m68hc12_elf_special_reloc,/* special_function */
332 "R_M68HC12_PAGE", /* name */
333 false, /* partial_inplace */
334 0x00ff, /* src_mask */
335 0x00ff, /* dst_mask */
336 false), /* pcrel_offset */
338 EMPTY_HOWTO (14),
339 EMPTY_HOWTO (15),
340 EMPTY_HOWTO (16),
341 EMPTY_HOWTO (17),
342 EMPTY_HOWTO (18),
343 EMPTY_HOWTO (19),
345 /* Mark beginning of a jump instruction (any form). */
346 HOWTO (R_M68HC11_RL_JUMP, /* type */
347 0, /* rightshift */
348 1, /* size (0 = byte, 1 = short, 2 = long) */
349 0, /* bitsize */
350 false, /* pc_relative */
351 0, /* bitpos */
352 complain_overflow_dont, /* complain_on_overflow */
353 m68hc11_elf_ignore_reloc, /* special_function */
354 "R_M68HC12_RL_JUMP", /* name */
355 true, /* partial_inplace */
356 0, /* src_mask */
357 0, /* dst_mask */
358 true), /* pcrel_offset */
360 /* Mark beginning of Gcc relaxation group instruction. */
361 HOWTO (R_M68HC11_RL_GROUP, /* type */
362 0, /* rightshift */
363 1, /* size (0 = byte, 1 = short, 2 = long) */
364 0, /* bitsize */
365 false, /* pc_relative */
366 0, /* bitpos */
367 complain_overflow_dont, /* complain_on_overflow */
368 m68hc11_elf_ignore_reloc, /* special_function */
369 "R_M68HC12_RL_GROUP", /* name */
370 true, /* partial_inplace */
371 0, /* src_mask */
372 0, /* dst_mask */
373 true), /* pcrel_offset */
376 /* Map BFD reloc types to M68HC11 ELF reloc types. */
378 struct m68hc11_reloc_map
380 bfd_reloc_code_real_type bfd_reloc_val;
381 unsigned char elf_reloc_val;
384 static const struct m68hc11_reloc_map m68hc11_reloc_map[] = {
385 {BFD_RELOC_NONE, R_M68HC11_NONE,},
386 {BFD_RELOC_8, R_M68HC11_8},
387 {BFD_RELOC_M68HC11_HI8, R_M68HC11_HI8},
388 {BFD_RELOC_M68HC11_LO8, R_M68HC11_LO8},
389 {BFD_RELOC_8_PCREL, R_M68HC11_PCREL_8},
390 {BFD_RELOC_16_PCREL, R_M68HC11_PCREL_16},
391 {BFD_RELOC_16, R_M68HC11_16},
392 {BFD_RELOC_32, R_M68HC11_32},
393 {BFD_RELOC_M68HC11_3B, R_M68HC11_3B},
395 {BFD_RELOC_VTABLE_INHERIT, R_M68HC11_GNU_VTINHERIT},
396 {BFD_RELOC_VTABLE_ENTRY, R_M68HC11_GNU_VTENTRY},
398 {BFD_RELOC_M68HC11_LO16, R_M68HC11_LO16},
399 {BFD_RELOC_M68HC11_PAGE, R_M68HC11_PAGE},
400 {BFD_RELOC_M68HC11_24, R_M68HC11_24},
402 {BFD_RELOC_M68HC11_RL_JUMP, R_M68HC11_RL_JUMP},
403 {BFD_RELOC_M68HC11_RL_GROUP, R_M68HC11_RL_GROUP},
406 static reloc_howto_type *
407 bfd_elf32_bfd_reloc_type_lookup (abfd, code)
408 bfd *abfd ATTRIBUTE_UNUSED;
409 bfd_reloc_code_real_type code;
411 unsigned int i;
413 for (i = 0;
414 i < sizeof (m68hc11_reloc_map) / sizeof (struct m68hc11_reloc_map);
415 i++)
417 if (m68hc11_reloc_map[i].bfd_reloc_val == code)
418 return &elf_m68hc11_howto_table[m68hc11_reloc_map[i].elf_reloc_val];
421 return NULL;
424 /* This function is used for relocs which are only used for relaxing,
425 which the linker should otherwise ignore. */
427 static bfd_reloc_status_type
428 m68hc11_elf_ignore_reloc (abfd, reloc_entry, symbol, data, input_section,
429 output_bfd, error_message)
430 bfd *abfd ATTRIBUTE_UNUSED;
431 arelent *reloc_entry;
432 asymbol *symbol ATTRIBUTE_UNUSED;
433 PTR data ATTRIBUTE_UNUSED;
434 asection *input_section;
435 bfd *output_bfd;
436 char **error_message ATTRIBUTE_UNUSED;
438 if (output_bfd != NULL)
439 reloc_entry->address += input_section->output_offset;
440 return bfd_reloc_ok;
443 static int
444 m68hc12_addr_is_banked (addr)
445 bfd_vma addr;
447 return (addr >= M68HC12_BANK_VIRT) ? 1 : 0;
450 /* Return the physical address seen by the processor, taking
451 into account banked memory. */
452 static bfd_vma
453 m68hc12_phys_addr (addr)
454 bfd_vma addr;
456 if (addr < M68HC12_BANK_VIRT)
457 return addr;
459 /* Map the address to the memory bank. */
460 addr -= M68HC12_BANK_VIRT;
461 addr &= M68HC12_BANK_MASK;
462 addr += M68HC12_BANK_BASE;
463 return addr;
466 /* Return the page number corresponding to an address in banked memory. */
467 static bfd_vma
468 m68hc12_phys_page (addr)
469 bfd_vma addr;
471 if (addr < M68HC12_BANK_VIRT)
472 return 0;
474 /* Map the address to the memory bank. */
475 addr -= M68HC12_BANK_VIRT;
476 addr >>= M68HC12_BANK_SHIFT;
477 addr &= M68HC12_BANK_PAGE_MASK;
478 return addr;
481 static bfd_reloc_status_type
482 m68hc12_elf_special_reloc (abfd, reloc_entry, symbol, data, input_section,
483 output_bfd, error_message)
484 bfd *abfd;
485 arelent *reloc_entry;
486 asymbol *symbol;
487 PTR data;
488 asection *input_section;
489 bfd *output_bfd;
490 char **error_message ATTRIBUTE_UNUSED;
492 reloc_howto_type *howto;
493 bfd_vma relocation;
494 bfd_vma phys_addr;
495 bfd_vma phys_page;
496 bfd_vma insn_page;
497 bfd_vma insn_addr;
499 if (output_bfd != (bfd *) NULL
500 && (symbol->flags & BSF_SECTION_SYM) == 0
501 && (! reloc_entry->howto->partial_inplace
502 || reloc_entry->addend == 0))
504 reloc_entry->address += input_section->output_offset;
505 return bfd_reloc_ok;
508 if (output_bfd != NULL)
509 return bfd_reloc_continue;
511 if (reloc_entry->address > input_section->_cooked_size)
512 return bfd_reloc_outofrange;
514 /* Compute relocation. */
515 relocation = (symbol->value
516 + symbol->section->output_section->vma
517 + symbol->section->output_offset);
518 relocation += reloc_entry->addend;
519 relocation += bfd_get_16 (abfd, (bfd_byte*) data + reloc_entry->address);
521 /* Do the memory bank mapping. */
522 phys_addr = m68hc12_phys_addr (relocation);
523 phys_page = m68hc12_phys_page (relocation);
525 howto = reloc_entry->howto;
526 if (howto->complain_on_overflow != complain_overflow_dont
527 && (phys_addr & (((bfd_vma) -1) << 16)))
528 return bfd_reloc_overflow;
530 switch (howto->type)
532 case R_M68HC11_16:
533 /* Get virtual address of instruction having the relocation. */
534 insn_addr = input_section->output_section->vma
535 + input_section->output_offset
536 + reloc_entry->address;
538 insn_page = m68hc12_phys_page (insn_addr);
540 if (m68hc12_addr_is_banked (relocation)
541 && m68hc12_addr_is_banked (insn_addr)
542 && phys_page != insn_page)
544 *error_message = _("address is not in the same bank");
545 return bfd_reloc_dangerous;
547 if (m68hc12_addr_is_banked (relocation)
548 && !m68hc12_addr_is_banked (insn_addr))
550 *error_message = _("reference to a banked address in "
551 "the normal address space");
552 return bfd_reloc_dangerous;
555 case R_M68HC11_LO16:
556 bfd_put_16 (abfd, phys_addr, (bfd_byte*) data + reloc_entry->address);
557 break;
559 case R_M68HC11_24:
560 bfd_put_16 (abfd, phys_addr, (bfd_byte*) data + reloc_entry->address);
561 bfd_put_8 (abfd, phys_page, (bfd_byte*) data + reloc_entry->address + 2);
562 break;
564 case R_M68HC11_PAGE:
565 bfd_put_8 (abfd, phys_page, (bfd_byte*) data + reloc_entry->address);
566 break;
568 default:
569 abort ();
570 break;
573 return bfd_reloc_ok;
576 /* Set the howto pointer for an M68HC11 ELF reloc. */
578 static void
579 m68hc11_info_to_howto_rel (abfd, cache_ptr, dst)
580 bfd *abfd ATTRIBUTE_UNUSED;
581 arelent *cache_ptr;
582 Elf32_Internal_Rel *dst;
584 unsigned int r_type;
586 r_type = ELF32_R_TYPE (dst->r_info);
587 BFD_ASSERT (r_type < (unsigned int) R_M68HC11_max);
588 cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
591 static asection *
592 elf32_m68hc11_gc_mark_hook (sec, info, rel, h, sym)
593 asection *sec;
594 struct bfd_link_info *info ATTRIBUTE_UNUSED;
595 Elf_Internal_Rela *rel;
596 struct elf_link_hash_entry *h;
597 Elf_Internal_Sym *sym;
599 if (h != NULL)
601 switch (ELF32_R_TYPE (rel->r_info))
603 default:
604 switch (h->root.type)
606 case bfd_link_hash_defined:
607 case bfd_link_hash_defweak:
608 return h->root.u.def.section;
610 case bfd_link_hash_common:
611 return h->root.u.c.p->section;
613 default:
614 break;
618 else
619 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
621 return NULL;
624 static boolean
625 elf32_m68hc11_gc_sweep_hook (abfd, info, sec, relocs)
626 bfd *abfd ATTRIBUTE_UNUSED;
627 struct bfd_link_info *info ATTRIBUTE_UNUSED;
628 asection *sec ATTRIBUTE_UNUSED;
629 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
631 /* We don't use got and plt entries for 68hc11/68hc12. */
632 return true;
636 /* Set and control ELF flags in ELF header. */
638 boolean
639 _bfd_m68hc12_elf_set_private_flags (abfd, flags)
640 bfd *abfd;
641 flagword flags;
643 BFD_ASSERT (!elf_flags_init (abfd)
644 || elf_elfheader (abfd)->e_flags == flags);
646 elf_elfheader (abfd)->e_flags = flags;
647 elf_flags_init (abfd) = true;
648 return true;
651 /* Merge backend specific data from an object file to the output
652 object file when linking. */
654 boolean
655 _bfd_m68hc12_elf_merge_private_bfd_data (ibfd, obfd)
656 bfd *ibfd;
657 bfd *obfd;
659 flagword old_flags;
660 flagword new_flags;
661 boolean ok = true;
663 /* Check if we have the same endianess */
664 if (_bfd_generic_verify_endian_match (ibfd, obfd) == false)
665 return false;
667 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
668 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
669 return true;
671 new_flags = elf_elfheader (ibfd)->e_flags;
672 elf_elfheader (obfd)->e_flags |= new_flags & EF_M68HC11_ABI;
673 old_flags = elf_elfheader (obfd)->e_flags;
675 if (! elf_flags_init (obfd))
677 elf_flags_init (obfd) = true;
678 elf_elfheader (obfd)->e_flags = new_flags;
679 elf_elfheader (obfd)->e_ident[EI_CLASS]
680 = elf_elfheader (ibfd)->e_ident[EI_CLASS];
682 if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
683 && bfd_get_arch_info (obfd)->the_default)
685 if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
686 bfd_get_mach (ibfd)))
687 return false;
690 return true;
693 /* Check ABI compatibility. */
694 if ((new_flags & E_M68HC11_I32) != (old_flags & E_M68HC11_I32))
696 (*_bfd_error_handler)
697 (_("%s: linking files compiled for 16-bit integers (-mshort) "
698 "and others for 32-bit integers"),
699 bfd_archive_filename (ibfd));
700 ok = false;
702 if ((new_flags & E_M68HC11_F64) != (old_flags & E_M68HC11_F64))
704 (*_bfd_error_handler)
705 (_("%s: linking files compiled for 32-bit double (-fshort-double) "
706 "and others for 64-bit double"),
707 bfd_archive_filename (ibfd));
708 ok = false;
710 new_flags &= ~EF_M68HC11_ABI;
711 old_flags &= ~EF_M68HC11_ABI;
713 /* Warn about any other mismatches */
714 if (new_flags != old_flags)
716 (*_bfd_error_handler)
717 (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
718 bfd_archive_filename (ibfd), (unsigned long) new_flags,
719 (unsigned long) old_flags);
720 ok = false;
723 if (! ok)
725 bfd_set_error (bfd_error_bad_value);
726 return false;
729 return true;
732 boolean
733 _bfd_m68hc12_elf_print_private_bfd_data (abfd, ptr)
734 bfd *abfd;
735 PTR ptr;
737 FILE *file = (FILE *) ptr;
739 BFD_ASSERT (abfd != NULL && ptr != NULL);
741 /* Print normal ELF private data. */
742 _bfd_elf_print_private_bfd_data (abfd, ptr);
744 /* xgettext:c-format */
745 fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
747 if (elf_elfheader (abfd)->e_flags & E_M68HC11_I32)
748 fprintf (file, _("[abi=32-bit int,"));
749 else
750 fprintf (file, _("[abi=16-bit int,"));
752 if (elf_elfheader (abfd)->e_flags & E_M68HC11_F64)
753 fprintf (file, _(" 64-bit double]"));
754 else
755 fprintf (file, _(" 32-bit double]"));
757 fputc ('\n', file);
759 return true;
762 /* Below is the only difference between elf32-m68hc12.c and elf32-m68hc11.c.
763 The Motorola spec says to use a different Elf machine code. */
764 #define ELF_ARCH bfd_arch_m68hc12
765 #define ELF_MACHINE_CODE EM_68HC12
766 #define ELF_MAXPAGESIZE 0x1000
768 #define TARGET_BIG_SYM bfd_elf32_m68hc12_vec
769 #define TARGET_BIG_NAME "elf32-m68hc12"
771 #define elf_info_to_howto 0
772 #define elf_info_to_howto_rel m68hc11_info_to_howto_rel
773 #define elf_backend_gc_mark_hook elf32_m68hc11_gc_mark_hook
774 #define elf_backend_gc_sweep_hook elf32_m68hc11_gc_sweep_hook
775 #define elf_backend_object_p 0
776 #define elf_backend_final_write_processing 0
777 /* Disabled as this backend uses the generic linker. */
778 #define elf_backend_can_gc_sections 0
780 #define bfd_elf32_bfd_merge_private_bfd_data \
781 _bfd_m68hc12_elf_merge_private_bfd_data
782 #define bfd_elf32_bfd_set_private_flags _bfd_m68hc12_elf_set_private_flags
783 #define bfd_elf32_bfd_print_private_bfd_data \
784 _bfd_m68hc12_elf_print_private_bfd_data
786 #include "elf32-target.h"