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