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