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