2004-04-21 Andrew Cagney <cagney@redhat.com>
[binutils.git] / bfd / elf32-m68hc11.c
blob42010b01dd2b4e675093184e52f052faca1c0ac0
1 /* Motorola 68HC11-specific support for 32-bit ELF
2 Copyright 1999, 2000, 2001, 2002, 2003 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 "bfdlink.h"
25 #include "libbfd.h"
26 #include "elf-bfd.h"
27 #include "elf32-m68hc1x.h"
28 #include "elf/m68hc11.h"
29 #include "opcode/m68hc11.h"
31 /* Relocation functions. */
32 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
33 (bfd *, bfd_reloc_code_real_type);
34 static void m68hc11_info_to_howto_rel
35 (bfd *, arelent *, Elf_Internal_Rela *);
37 /* Trampoline generation. */
38 static bfd_boolean m68hc11_elf_size_one_stub
39 (struct bfd_hash_entry *gen_entry, void *in_arg);
40 static bfd_boolean m68hc11_elf_build_one_stub
41 (struct bfd_hash_entry *gen_entry, void *in_arg);
42 static struct bfd_link_hash_table* m68hc11_elf_bfd_link_hash_table_create
43 (bfd* abfd);
45 /* Linker relaxation. */
46 static bfd_boolean m68hc11_elf_relax_section
47 (bfd *, asection *, struct bfd_link_info *, bfd_boolean *);
48 static void m68hc11_elf_relax_delete_bytes
49 (bfd *, asection *, bfd_vma, int);
50 static void m68hc11_relax_group
51 (bfd *, asection *, bfd_byte *, unsigned, unsigned long, unsigned long);
52 static int compare_reloc (const void *, const void *);
54 /* Use REL instead of RELA to save space */
55 #define USE_REL 1
57 /* The Motorola 68HC11 microcontroller only addresses 64Kb but we also
58 support a memory bank switching mechanism similar to 68HC12.
59 We must handle 8 and 16-bit relocations. The 32-bit relocation
60 are used for debugging sections (DWARF2) to represent a virtual
61 address.
62 The 3-bit and 16-bit PC rel relocation is only used by 68HC12. */
63 static reloc_howto_type elf_m68hc11_howto_table[] = {
64 /* This reloc does nothing. */
65 HOWTO (R_M68HC11_NONE, /* type */
66 0, /* rightshift */
67 2, /* size (0 = byte, 1 = short, 2 = long) */
68 32, /* bitsize */
69 FALSE, /* pc_relative */
70 0, /* bitpos */
71 complain_overflow_dont,/* complain_on_overflow */
72 bfd_elf_generic_reloc, /* special_function */
73 "R_M68HC11_NONE", /* name */
74 FALSE, /* partial_inplace */
75 0, /* src_mask */
76 0, /* dst_mask */
77 FALSE), /* pcrel_offset */
79 /* A 8 bit absolute relocation */
80 HOWTO (R_M68HC11_8, /* type */
81 0, /* rightshift */
82 0, /* size (0 = byte, 1 = short, 2 = long) */
83 8, /* bitsize */
84 FALSE, /* pc_relative */
85 0, /* bitpos */
86 complain_overflow_bitfield, /* complain_on_overflow */
87 bfd_elf_generic_reloc, /* special_function */
88 "R_M68HC11_8", /* name */
89 FALSE, /* partial_inplace */
90 0x00ff, /* src_mask */
91 0x00ff, /* dst_mask */
92 FALSE), /* pcrel_offset */
94 /* A 8 bit absolute relocation (upper address) */
95 HOWTO (R_M68HC11_HI8, /* type */
96 8, /* rightshift */
97 0, /* size (0 = byte, 1 = short, 2 = long) */
98 8, /* bitsize */
99 FALSE, /* pc_relative */
100 0, /* bitpos */
101 complain_overflow_bitfield, /* complain_on_overflow */
102 bfd_elf_generic_reloc, /* special_function */
103 "R_M68HC11_HI8", /* name */
104 FALSE, /* partial_inplace */
105 0x00ff, /* src_mask */
106 0x00ff, /* dst_mask */
107 FALSE), /* pcrel_offset */
109 /* A 8 bit absolute relocation (upper address) */
110 HOWTO (R_M68HC11_LO8, /* type */
111 0, /* rightshift */
112 0, /* size (0 = byte, 1 = short, 2 = long) */
113 8, /* bitsize */
114 FALSE, /* pc_relative */
115 0, /* bitpos */
116 complain_overflow_dont, /* complain_on_overflow */
117 bfd_elf_generic_reloc, /* special_function */
118 "R_M68HC11_LO8", /* name */
119 FALSE, /* partial_inplace */
120 0x00ff, /* src_mask */
121 0x00ff, /* dst_mask */
122 FALSE), /* pcrel_offset */
124 /* A 8 bit PC-rel relocation */
125 HOWTO (R_M68HC11_PCREL_8, /* type */
126 0, /* rightshift */
127 0, /* size (0 = byte, 1 = short, 2 = long) */
128 8, /* bitsize */
129 TRUE, /* pc_relative */
130 0, /* bitpos */
131 complain_overflow_bitfield, /* complain_on_overflow */
132 bfd_elf_generic_reloc, /* special_function */
133 "R_M68HC11_PCREL_8", /* name */
134 FALSE, /* partial_inplace */
135 0x00ff, /* src_mask */
136 0x00ff, /* dst_mask */
137 TRUE), /* pcrel_offset */
139 /* A 16 bit absolute relocation */
140 HOWTO (R_M68HC11_16, /* type */
141 0, /* rightshift */
142 1, /* size (0 = byte, 1 = short, 2 = long) */
143 16, /* bitsize */
144 FALSE, /* pc_relative */
145 0, /* bitpos */
146 complain_overflow_dont /*bitfield */ , /* complain_on_overflow */
147 bfd_elf_generic_reloc, /* special_function */
148 "R_M68HC11_16", /* name */
149 FALSE, /* partial_inplace */
150 0xffff, /* src_mask */
151 0xffff, /* dst_mask */
152 FALSE), /* pcrel_offset */
154 /* A 32 bit absolute relocation. This one is never used for the
155 code relocation. It's used by gas for -gstabs generation. */
156 HOWTO (R_M68HC11_32, /* type */
157 0, /* rightshift */
158 2, /* size (0 = byte, 1 = short, 2 = long) */
159 32, /* bitsize */
160 FALSE, /* pc_relative */
161 0, /* bitpos */
162 complain_overflow_bitfield, /* complain_on_overflow */
163 bfd_elf_generic_reloc, /* special_function */
164 "R_M68HC11_32", /* name */
165 FALSE, /* partial_inplace */
166 0xffffffff, /* src_mask */
167 0xffffffff, /* dst_mask */
168 FALSE), /* pcrel_offset */
170 /* A 3 bit absolute relocation */
171 HOWTO (R_M68HC11_3B, /* type */
172 0, /* rightshift */
173 0, /* size (0 = byte, 1 = short, 2 = long) */
174 3, /* bitsize */
175 FALSE, /* pc_relative */
176 0, /* bitpos */
177 complain_overflow_bitfield, /* complain_on_overflow */
178 bfd_elf_generic_reloc, /* special_function */
179 "R_M68HC11_4B", /* name */
180 FALSE, /* partial_inplace */
181 0x003, /* src_mask */
182 0x003, /* dst_mask */
183 FALSE), /* pcrel_offset */
185 /* A 16 bit PC-rel relocation */
186 HOWTO (R_M68HC11_PCREL_16, /* type */
187 0, /* rightshift */
188 1, /* size (0 = byte, 1 = short, 2 = long) */
189 16, /* bitsize */
190 TRUE, /* pc_relative */
191 0, /* bitpos */
192 complain_overflow_dont, /* complain_on_overflow */
193 bfd_elf_generic_reloc, /* special_function */
194 "R_M68HC11_PCREL_16", /* name */
195 FALSE, /* partial_inplace */
196 0xffff, /* src_mask */
197 0xffff, /* dst_mask */
198 TRUE), /* pcrel_offset */
200 /* GNU extension to record C++ vtable hierarchy */
201 HOWTO (R_M68HC11_GNU_VTINHERIT, /* type */
202 0, /* rightshift */
203 1, /* size (0 = byte, 1 = short, 2 = long) */
204 0, /* bitsize */
205 FALSE, /* pc_relative */
206 0, /* bitpos */
207 complain_overflow_dont, /* complain_on_overflow */
208 NULL, /* special_function */
209 "R_M68HC11_GNU_VTINHERIT", /* name */
210 FALSE, /* partial_inplace */
211 0, /* src_mask */
212 0, /* dst_mask */
213 FALSE), /* pcrel_offset */
215 /* GNU extension to record C++ vtable member usage */
216 HOWTO (R_M68HC11_GNU_VTENTRY, /* type */
217 0, /* rightshift */
218 1, /* size (0 = byte, 1 = short, 2 = long) */
219 0, /* bitsize */
220 FALSE, /* pc_relative */
221 0, /* bitpos */
222 complain_overflow_dont, /* complain_on_overflow */
223 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
224 "R_M68HC11_GNU_VTENTRY", /* name */
225 FALSE, /* partial_inplace */
226 0, /* src_mask */
227 0, /* dst_mask */
228 FALSE), /* pcrel_offset */
230 /* A 24 bit relocation */
231 HOWTO (R_M68HC11_24, /* type */
232 0, /* rightshift */
233 1, /* size (0 = byte, 1 = short, 2 = long) */
234 24, /* bitsize */
235 FALSE, /* pc_relative */
236 0, /* bitpos */
237 complain_overflow_bitfield, /* complain_on_overflow */
238 bfd_elf_generic_reloc, /* special_function */
239 "R_M68HC11_24", /* name */
240 FALSE, /* partial_inplace */
241 0xffffff, /* src_mask */
242 0xffffff, /* dst_mask */
243 FALSE), /* pcrel_offset */
245 /* A 16-bit low relocation */
246 HOWTO (R_M68HC11_LO16, /* type */
247 0, /* rightshift */
248 1, /* size (0 = byte, 1 = short, 2 = long) */
249 16, /* bitsize */
250 FALSE, /* pc_relative */
251 0, /* bitpos */
252 complain_overflow_bitfield, /* complain_on_overflow */
253 bfd_elf_generic_reloc, /* special_function */
254 "R_M68HC11_LO16", /* name */
255 FALSE, /* partial_inplace */
256 0xffff, /* src_mask */
257 0xffff, /* dst_mask */
258 FALSE), /* pcrel_offset */
260 /* A page relocation */
261 HOWTO (R_M68HC11_PAGE, /* type */
262 0, /* rightshift */
263 0, /* size (0 = byte, 1 = short, 2 = long) */
264 8, /* bitsize */
265 FALSE, /* pc_relative */
266 0, /* bitpos */
267 complain_overflow_bitfield, /* complain_on_overflow */
268 bfd_elf_generic_reloc, /* special_function */
269 "R_M68HC11_PAGE", /* name */
270 FALSE, /* partial_inplace */
271 0x00ff, /* src_mask */
272 0x00ff, /* dst_mask */
273 FALSE), /* pcrel_offset */
275 EMPTY_HOWTO (14),
276 EMPTY_HOWTO (15),
277 EMPTY_HOWTO (16),
278 EMPTY_HOWTO (17),
279 EMPTY_HOWTO (18),
280 EMPTY_HOWTO (19),
282 /* Mark beginning of a jump instruction (any form). */
283 HOWTO (R_M68HC11_RL_JUMP, /* type */
284 0, /* rightshift */
285 1, /* size (0 = byte, 1 = short, 2 = long) */
286 0, /* bitsize */
287 FALSE, /* pc_relative */
288 0, /* bitpos */
289 complain_overflow_dont, /* complain_on_overflow */
290 m68hc11_elf_ignore_reloc, /* special_function */
291 "R_M68HC11_RL_JUMP", /* name */
292 TRUE, /* partial_inplace */
293 0, /* src_mask */
294 0, /* dst_mask */
295 TRUE), /* pcrel_offset */
297 /* Mark beginning of Gcc relaxation group instruction. */
298 HOWTO (R_M68HC11_RL_GROUP, /* type */
299 0, /* rightshift */
300 1, /* size (0 = byte, 1 = short, 2 = long) */
301 0, /* bitsize */
302 FALSE, /* pc_relative */
303 0, /* bitpos */
304 complain_overflow_dont, /* complain_on_overflow */
305 m68hc11_elf_ignore_reloc, /* special_function */
306 "R_M68HC11_RL_GROUP", /* name */
307 TRUE, /* partial_inplace */
308 0, /* src_mask */
309 0, /* dst_mask */
310 TRUE), /* pcrel_offset */
313 /* Map BFD reloc types to M68HC11 ELF reloc types. */
315 struct m68hc11_reloc_map
317 bfd_reloc_code_real_type bfd_reloc_val;
318 unsigned char elf_reloc_val;
321 static const struct m68hc11_reloc_map m68hc11_reloc_map[] = {
322 {BFD_RELOC_NONE, R_M68HC11_NONE,},
323 {BFD_RELOC_8, R_M68HC11_8},
324 {BFD_RELOC_M68HC11_HI8, R_M68HC11_HI8},
325 {BFD_RELOC_M68HC11_LO8, R_M68HC11_LO8},
326 {BFD_RELOC_8_PCREL, R_M68HC11_PCREL_8},
327 {BFD_RELOC_16_PCREL, R_M68HC11_PCREL_16},
328 {BFD_RELOC_16, R_M68HC11_16},
329 {BFD_RELOC_32, R_M68HC11_32},
330 {BFD_RELOC_M68HC11_3B, R_M68HC11_3B},
332 {BFD_RELOC_VTABLE_INHERIT, R_M68HC11_GNU_VTINHERIT},
333 {BFD_RELOC_VTABLE_ENTRY, R_M68HC11_GNU_VTENTRY},
335 {BFD_RELOC_M68HC11_LO16, R_M68HC11_LO16},
336 {BFD_RELOC_M68HC11_PAGE, R_M68HC11_PAGE},
337 {BFD_RELOC_M68HC11_24, R_M68HC11_24},
339 {BFD_RELOC_M68HC11_RL_JUMP, R_M68HC11_RL_JUMP},
340 {BFD_RELOC_M68HC11_RL_GROUP, R_M68HC11_RL_GROUP},
343 static reloc_howto_type *
344 bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
345 bfd_reloc_code_real_type code)
347 unsigned int i;
349 for (i = 0;
350 i < sizeof (m68hc11_reloc_map) / sizeof (struct m68hc11_reloc_map);
351 i++)
353 if (m68hc11_reloc_map[i].bfd_reloc_val == code)
354 return &elf_m68hc11_howto_table[m68hc11_reloc_map[i].elf_reloc_val];
357 return NULL;
360 /* Set the howto pointer for an M68HC11 ELF reloc. */
362 static void
363 m68hc11_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
364 arelent *cache_ptr, Elf_Internal_Rela *dst)
366 unsigned int r_type;
368 r_type = ELF32_R_TYPE (dst->r_info);
369 BFD_ASSERT (r_type < (unsigned int) R_M68HC11_max);
370 cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
374 /* Far trampoline generation. */
376 /* Build a 68HC11 trampoline stub. */
377 static bfd_boolean
378 m68hc11_elf_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
380 struct elf32_m68hc11_stub_hash_entry *stub_entry;
381 struct bfd_link_info *info;
382 struct m68hc11_elf_link_hash_table *htab;
383 asection *stub_sec;
384 bfd *stub_bfd;
385 bfd_byte *loc;
386 bfd_vma sym_value, phys_page, phys_addr;
388 /* Massage our args to the form they really have. */
389 stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
390 info = (struct bfd_link_info *) in_arg;
392 htab = m68hc11_elf_hash_table (info);
394 stub_sec = stub_entry->stub_sec;
396 /* Make a note of the offset within the stubs for this entry. */
397 stub_entry->stub_offset = stub_sec->_raw_size;
398 stub_sec->_raw_size += 10;
399 loc = stub_sec->contents + stub_entry->stub_offset;
401 stub_bfd = stub_sec->owner;
403 /* Create the trampoline call stub:
405 pshb
406 ldab #%page(symbol)
407 ldy #%addr(symbol)
408 jmp __trampoline
411 sym_value = (stub_entry->target_value
412 + stub_entry->target_section->output_offset
413 + stub_entry->target_section->output_section->vma);
414 phys_addr = m68hc11_phys_addr (&htab->pinfo, sym_value);
415 phys_page = m68hc11_phys_page (&htab->pinfo, sym_value);
417 /* pshb; ldab #%page(sym) */
418 bfd_put_8 (stub_bfd, 0x37, loc);
419 bfd_put_8 (stub_bfd, 0xC6, loc + 1);
420 bfd_put_8 (stub_bfd, phys_page, loc + 2);
421 loc += 3;
423 /* ldy #%addr(sym) */
424 bfd_put_8 (stub_bfd, 0x18, loc);
425 bfd_put_8 (stub_bfd, 0xCE, loc + 1);
426 bfd_put_16 (stub_bfd, phys_addr, loc + 2);
427 loc += 4;
429 /* jmp __trampoline */
430 bfd_put_8 (stub_bfd, 0x7E, loc);
431 bfd_put_16 (stub_bfd, htab->pinfo.trampoline_addr, loc + 1);
433 return TRUE;
436 /* As above, but don't actually build the stub. Just bump offset so
437 we know stub section sizes. */
439 static bfd_boolean
440 m68hc11_elf_size_one_stub (struct bfd_hash_entry *gen_entry,
441 void *in_arg ATTRIBUTE_UNUSED)
443 struct elf32_m68hc11_stub_hash_entry *stub_entry;
445 /* Massage our args to the form they really have. */
446 stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
448 stub_entry->stub_sec->_raw_size += 10;
449 return TRUE;
452 /* Create a 68HC11 ELF linker hash table. */
454 static struct bfd_link_hash_table *
455 m68hc11_elf_bfd_link_hash_table_create (bfd *abfd)
457 struct m68hc11_elf_link_hash_table *ret;
459 ret = m68hc11_elf_hash_table_create (abfd);
460 if (ret == (struct m68hc11_elf_link_hash_table *) NULL)
461 return NULL;
463 ret->size_one_stub = m68hc11_elf_size_one_stub;
464 ret->build_one_stub = m68hc11_elf_build_one_stub;
466 return &ret->root.root;
470 /* 68HC11 Linker Relaxation. */
472 struct m68hc11_direct_relax
474 const char *name;
475 unsigned char code;
476 unsigned char direct_code;
477 } m68hc11_direct_relax_table[] = {
478 { "adca", 0xB9, 0x99 },
479 { "adcb", 0xF9, 0xD9 },
480 { "adda", 0xBB, 0x9B },
481 { "addb", 0xFB, 0xDB },
482 { "addd", 0xF3, 0xD3 },
483 { "anda", 0xB4, 0x94 },
484 { "andb", 0xF4, 0xD4 },
485 { "cmpa", 0xB1, 0x91 },
486 { "cmpb", 0xF1, 0xD1 },
487 { "cpd", 0xB3, 0x93 },
488 { "cpxy", 0xBC, 0x9C },
489 /* { "cpy", 0xBC, 0x9C }, */
490 { "eora", 0xB8, 0x98 },
491 { "eorb", 0xF8, 0xD8 },
492 { "jsr", 0xBD, 0x9D },
493 { "ldaa", 0xB6, 0x96 },
494 { "ldab", 0xF6, 0xD6 },
495 { "ldd", 0xFC, 0xDC },
496 { "lds", 0xBE, 0x9E },
497 { "ldxy", 0xFE, 0xDE },
498 /* { "ldy", 0xFE, 0xDE },*/
499 { "oraa", 0xBA, 0x9A },
500 { "orab", 0xFA, 0xDA },
501 { "sbca", 0xB2, 0x92 },
502 { "sbcb", 0xF2, 0xD2 },
503 { "staa", 0xB7, 0x97 },
504 { "stab", 0xF7, 0xD7 },
505 { "std", 0xFD, 0xDD },
506 { "sts", 0xBF, 0x9F },
507 { "stxy", 0xFF, 0xDF },
508 /* { "sty", 0xFF, 0xDF },*/
509 { "suba", 0xB0, 0x90 },
510 { "subb", 0xF0, 0xD0 },
511 { "subd", 0xB3, 0x93 },
512 { 0, 0, 0 }
515 static struct m68hc11_direct_relax *
516 find_relaxable_insn (unsigned char code)
518 int i;
520 for (i = 0; m68hc11_direct_relax_table[i].name; i++)
521 if (m68hc11_direct_relax_table[i].code == code)
522 return &m68hc11_direct_relax_table[i];
524 return 0;
527 static int
528 compare_reloc (const void *e1, const void *e2)
530 const Elf_Internal_Rela *i1 = (const Elf_Internal_Rela *) e1;
531 const Elf_Internal_Rela *i2 = (const Elf_Internal_Rela *) e2;
533 if (i1->r_offset == i2->r_offset)
534 return 0;
535 else
536 return i1->r_offset < i2->r_offset ? -1 : 1;
539 #define M6811_OP_LDX_IMMEDIATE (0xCE)
541 static void
542 m68hc11_relax_group (bfd *abfd, asection *sec, bfd_byte *contents,
543 unsigned value, unsigned long offset,
544 unsigned long end_group)
546 unsigned char code;
547 unsigned long start_offset;
548 unsigned long ldx_offset = offset;
549 unsigned long ldx_size;
550 int can_delete_ldx;
551 int relax_ldy = 0;
553 /* First instruction of the relax group must be a
554 LDX #value or LDY #value. If this is not the case,
555 ignore the relax group. */
556 code = bfd_get_8 (abfd, contents + offset);
557 if (code == 0x18)
559 relax_ldy++;
560 offset++;
561 code = bfd_get_8 (abfd, contents + offset);
563 ldx_size = offset - ldx_offset + 3;
564 offset += 3;
565 if (code != M6811_OP_LDX_IMMEDIATE || offset >= end_group)
566 return;
569 /* We can remove the LDX/LDY only when all bset/brclr instructions
570 of the relax group have been converted to use direct addressing
571 mode. */
572 can_delete_ldx = 1;
573 while (offset < end_group)
575 unsigned isize;
576 unsigned new_value;
577 int bset_use_y;
579 bset_use_y = 0;
580 start_offset = offset;
581 code = bfd_get_8 (abfd, contents + offset);
582 if (code == 0x18)
584 bset_use_y++;
585 offset++;
586 code = bfd_get_8 (abfd, contents + offset);
589 /* Check the instruction and translate to use direct addressing mode. */
590 switch (code)
592 /* bset */
593 case 0x1C:
594 code = 0x14;
595 isize = 3;
596 break;
598 /* brclr */
599 case 0x1F:
600 code = 0x13;
601 isize = 4;
602 break;
604 /* brset */
605 case 0x1E:
606 code = 0x12;
607 isize = 4;
608 break;
610 /* bclr */
611 case 0x1D:
612 code = 0x15;
613 isize = 3;
614 break;
616 /* This instruction is not recognized and we are not
617 at end of the relax group. Ignore and don't remove
618 the first LDX (we don't know what it is used for...). */
619 default:
620 return;
622 new_value = (unsigned) bfd_get_8 (abfd, contents + offset + 1);
623 new_value += value;
624 if ((new_value & 0xff00) == 0 && bset_use_y == relax_ldy)
626 bfd_put_8 (abfd, code, contents + offset);
627 bfd_put_8 (abfd, new_value, contents + offset + 1);
628 if (start_offset != offset)
630 m68hc11_elf_relax_delete_bytes (abfd, sec, start_offset,
631 offset - start_offset);
632 end_group--;
635 else
637 can_delete_ldx = 0;
639 offset = start_offset + isize;
641 if (can_delete_ldx)
643 /* Remove the move instruction (3 or 4 bytes win). */
644 m68hc11_elf_relax_delete_bytes (abfd, sec, ldx_offset, ldx_size);
648 /* This function handles relaxing for the 68HC11.
651 and somewhat more difficult to support. */
653 static bfd_boolean
654 m68hc11_elf_relax_section (bfd *abfd, asection *sec,
655 struct bfd_link_info *link_info, bfd_boolean *again)
657 Elf_Internal_Shdr *symtab_hdr;
658 Elf_Internal_Shdr *shndx_hdr;
659 Elf_Internal_Rela *internal_relocs;
660 Elf_Internal_Rela *free_relocs = NULL;
661 Elf_Internal_Rela *irel, *irelend;
662 bfd_byte *contents = NULL;
663 bfd_byte *free_contents = NULL;
664 Elf32_External_Sym *free_extsyms = NULL;
665 Elf_Internal_Rela *prev_insn_branch = NULL;
666 Elf_Internal_Rela *prev_insn_group = NULL;
667 unsigned insn_group_value = 0;
668 Elf_Internal_Sym *isymbuf = NULL;
670 /* Assume nothing changes. */
671 *again = FALSE;
673 /* We don't have to do anything for a relocatable link, if
674 this section does not have relocs, or if this is not a
675 code section. */
676 if (link_info->relocatable
677 || (sec->flags & SEC_RELOC) == 0
678 || sec->reloc_count == 0
679 || (sec->flags & SEC_CODE) == 0)
680 return TRUE;
682 /* If this is the first time we have been called for this section,
683 initialize the cooked size. */
684 if (sec->_cooked_size == 0)
685 sec->_cooked_size = sec->_raw_size;
687 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
688 shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
690 /* Get a copy of the native relocations. */
691 internal_relocs = (_bfd_elf_link_read_relocs
692 (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
693 link_info->keep_memory));
694 if (internal_relocs == NULL)
695 goto error_return;
696 if (! link_info->keep_memory)
697 free_relocs = internal_relocs;
699 /* Checking for branch relaxation relies on the relocations to
700 be sorted on 'r_offset'. This is not guaranteed so we must sort. */
701 qsort (internal_relocs, sec->reloc_count, sizeof (Elf_Internal_Rela),
702 compare_reloc);
704 /* Walk through them looking for relaxing opportunities. */
705 irelend = internal_relocs + sec->reloc_count;
706 for (irel = internal_relocs; irel < irelend; irel++)
708 bfd_vma symval;
709 bfd_vma value;
710 Elf_Internal_Sym *isym;
711 asection *sym_sec;
712 int is_far = 0;
714 /* If this isn't something that can be relaxed, then ignore
715 this reloc. */
716 if (ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_16
717 && ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_RL_JUMP
718 && ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_RL_GROUP)
720 prev_insn_branch = 0;
721 prev_insn_group = 0;
722 continue;
725 /* Get the section contents if we haven't done so already. */
726 if (contents == NULL)
728 /* Get cached copy if it exists. */
729 if (elf_section_data (sec)->this_hdr.contents != NULL)
730 contents = elf_section_data (sec)->this_hdr.contents;
731 else
733 /* Go get them off disk. */
734 contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
735 if (contents == NULL)
736 goto error_return;
737 free_contents = contents;
739 if (! bfd_get_section_contents (abfd, sec, contents,
740 (file_ptr) 0, sec->_raw_size))
741 goto error_return;
745 /* Try to eliminate an unconditional 8 bit pc-relative branch
746 which immediately follows a conditional 8 bit pc-relative
747 branch around the unconditional branch.
749 original: new:
750 bCC lab1 bCC' lab2
751 bra lab2
752 lab1: lab1:
754 This happens when the bCC can't reach lab2 at assembly time,
755 but due to other relaxations it can reach at link time. */
756 if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_RL_JUMP)
758 Elf_Internal_Rela *nrel;
759 unsigned char code;
760 unsigned char roffset;
762 prev_insn_branch = 0;
763 prev_insn_group = 0;
765 /* Do nothing if this reloc is the last byte in the section. */
766 if (irel->r_offset + 2 >= sec->_cooked_size)
767 continue;
769 /* See if the next instruction is an unconditional pc-relative
770 branch, more often than not this test will fail, so we
771 test it first to speed things up. */
772 code = bfd_get_8 (abfd, contents + irel->r_offset + 2);
773 if (code != 0x7e)
774 continue;
776 /* Also make sure the next relocation applies to the next
777 instruction and that it's a pc-relative 8 bit branch. */
778 nrel = irel + 1;
779 if (nrel == irelend
780 || irel->r_offset + 3 != nrel->r_offset
781 || ELF32_R_TYPE (nrel->r_info) != (int) R_M68HC11_16)
782 continue;
784 /* Make sure our destination immediately follows the
785 unconditional branch. */
786 roffset = bfd_get_8 (abfd, contents + irel->r_offset + 1);
787 if (roffset != 3)
788 continue;
790 prev_insn_branch = irel;
791 prev_insn_group = 0;
792 continue;
795 /* Read this BFD's symbols if we haven't done so already. */
796 if (isymbuf == NULL && symtab_hdr->sh_info != 0)
798 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
799 if (isymbuf == NULL)
800 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
801 symtab_hdr->sh_info, 0,
802 NULL, NULL, NULL);
803 if (isymbuf == NULL)
804 goto error_return;
807 /* Get the value of the symbol referred to by the reloc. */
808 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
810 /* A local symbol. */
811 isym = isymbuf + ELF32_R_SYM (irel->r_info);
812 is_far = isym->st_other & STO_M68HC12_FAR;
813 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
814 symval = (isym->st_value
815 + sym_sec->output_section->vma
816 + sym_sec->output_offset);
818 else
820 unsigned long indx;
821 struct elf_link_hash_entry *h;
823 /* An external symbol. */
824 indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
825 h = elf_sym_hashes (abfd)[indx];
826 BFD_ASSERT (h != NULL);
827 if (h->root.type != bfd_link_hash_defined
828 && h->root.type != bfd_link_hash_defweak)
830 /* This appears to be a reference to an undefined
831 symbol. Just ignore it--it will be caught by the
832 regular reloc processing. */
833 prev_insn_branch = 0;
834 prev_insn_group = 0;
835 continue;
838 is_far = h->other & STO_M68HC12_FAR;
839 isym = 0;
840 sym_sec = h->root.u.def.section;
841 symval = (h->root.u.def.value
842 + sym_sec->output_section->vma
843 + sym_sec->output_offset);
846 if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_RL_GROUP)
848 prev_insn_branch = 0;
849 prev_insn_group = 0;
851 /* Do nothing if this reloc is the last byte in the section. */
852 if (irel->r_offset == sec->_cooked_size)
853 continue;
855 prev_insn_group = irel;
856 insn_group_value = isym->st_value;
857 continue;
860 /* When we relax some bytes, the size of our section changes.
861 This affects the layout of next input sections that go in our
862 output section. When the symbol is part of another section that
863 will go in the same output section as the current one, it's
864 final address may now be incorrect (too far). We must let the
865 linker re-compute all section offsets before processing this
866 reloc. Code example:
868 Initial Final
869 .sect .text section size = 6 section size = 4
870 jmp foo
871 jmp bar
872 .sect .text.foo_bar output_offset = 6 output_offset = 4
873 foo: rts
874 bar: rts
876 If we process the reloc now, the jmp bar is replaced by a
877 relative branch to the initial bar address (output_offset 6). */
878 if (*again && sym_sec != sec
879 && sym_sec->output_section == sec->output_section)
881 prev_insn_group = 0;
882 prev_insn_branch = 0;
883 continue;
886 value = symval;
887 /* Try to turn a far branch to a near branch. */
888 if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_16
889 && prev_insn_branch)
891 bfd_vma offset;
892 unsigned char code;
894 offset = value - (prev_insn_branch->r_offset
895 + sec->output_section->vma
896 + sec->output_offset + 2);
898 /* If the offset is still out of -128..+127 range,
899 leave that far branch unchanged. */
900 if ((offset & 0xff80) != 0 && (offset & 0xff80) != 0xff80)
902 prev_insn_branch = 0;
903 continue;
906 /* Shrink the branch. */
907 code = bfd_get_8 (abfd, contents + prev_insn_branch->r_offset);
908 if (code == 0x7e)
910 code = 0x20;
911 bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset);
912 bfd_put_8 (abfd, 0xff,
913 contents + prev_insn_branch->r_offset + 1);
914 irel->r_offset = prev_insn_branch->r_offset + 1;
915 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
916 R_M68HC11_PCREL_8);
917 m68hc11_elf_relax_delete_bytes (abfd, sec,
918 irel->r_offset + 1, 1);
920 else
922 code ^= 0x1;
923 bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset);
924 bfd_put_8 (abfd, 0xff,
925 contents + prev_insn_branch->r_offset + 1);
926 irel->r_offset = prev_insn_branch->r_offset + 1;
927 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
928 R_M68HC11_PCREL_8);
929 m68hc11_elf_relax_delete_bytes (abfd, sec,
930 irel->r_offset + 1, 3);
932 prev_insn_branch = 0;
933 *again = TRUE;
936 /* Try to turn a 16 bit address into a 8 bit page0 address. */
937 else if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_16
938 && (value & 0xff00) == 0)
940 unsigned char code;
941 unsigned short offset;
942 struct m68hc11_direct_relax *rinfo;
944 prev_insn_branch = 0;
945 offset = bfd_get_16 (abfd, contents + irel->r_offset);
946 offset += value;
947 if ((offset & 0xff00) != 0)
949 prev_insn_group = 0;
950 continue;
953 if (prev_insn_group)
955 unsigned long old_sec_size = sec->_cooked_size;
957 /* Note that we've changed the relocation contents, etc. */
958 elf_section_data (sec)->relocs = internal_relocs;
959 free_relocs = NULL;
961 elf_section_data (sec)->this_hdr.contents = contents;
962 free_contents = NULL;
964 symtab_hdr->contents = (bfd_byte *) isymbuf;
965 free_extsyms = NULL;
967 m68hc11_relax_group (abfd, sec, contents, offset,
968 prev_insn_group->r_offset,
969 insn_group_value);
970 irel = prev_insn_group;
971 prev_insn_group = 0;
972 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
973 R_M68HC11_NONE);
974 if (sec->_cooked_size != old_sec_size)
975 *again = TRUE;
976 continue;
979 /* Get the opcode. */
980 code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
981 rinfo = find_relaxable_insn (code);
982 if (rinfo == 0)
984 prev_insn_group = 0;
985 continue;
988 /* Note that we've changed the relocation contents, etc. */
989 elf_section_data (sec)->relocs = internal_relocs;
990 free_relocs = NULL;
992 elf_section_data (sec)->this_hdr.contents = contents;
993 free_contents = NULL;
995 symtab_hdr->contents = (bfd_byte *) isymbuf;
996 free_extsyms = NULL;
998 /* Fix the opcode. */
999 /* printf ("A relaxable case : 0x%02x (%s)\n",
1000 code, rinfo->name); */
1001 bfd_put_8 (abfd, rinfo->direct_code,
1002 contents + irel->r_offset - 1);
1004 /* Delete one byte of data (upper byte of address). */
1005 m68hc11_elf_relax_delete_bytes (abfd, sec, irel->r_offset, 1);
1007 /* Fix the relocation's type. */
1008 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1009 R_M68HC11_8);
1011 /* That will change things, so, we should relax again. */
1012 *again = TRUE;
1014 else if (ELF32_R_TYPE (irel->r_info) == R_M68HC11_16 && !is_far)
1016 unsigned char code;
1017 bfd_vma offset;
1019 prev_insn_branch = 0;
1020 code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
1021 if (code == 0x7e || code == 0xbd)
1023 offset = value - (irel->r_offset
1024 + sec->output_section->vma
1025 + sec->output_offset + 1);
1026 offset += bfd_get_16 (abfd, contents + irel->r_offset);
1028 /* If the offset is still out of -128..+127 range,
1029 leave that far branch unchanged. */
1030 if ((offset & 0xff80) == 0 || (offset & 0xff80) == 0xff80)
1033 /* Note that we've changed the relocation contents, etc. */
1034 elf_section_data (sec)->relocs = internal_relocs;
1035 free_relocs = NULL;
1037 elf_section_data (sec)->this_hdr.contents = contents;
1038 free_contents = NULL;
1040 symtab_hdr->contents = (bfd_byte *) isymbuf;
1041 free_extsyms = NULL;
1043 /* Shrink the branch. */
1044 code = (code == 0x7e) ? 0x20 : 0x8d;
1045 bfd_put_8 (abfd, code,
1046 contents + irel->r_offset - 1);
1047 bfd_put_8 (abfd, 0xff,
1048 contents + irel->r_offset);
1049 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1050 R_M68HC11_PCREL_8);
1051 m68hc11_elf_relax_delete_bytes (abfd, sec,
1052 irel->r_offset + 1, 1);
1053 /* That will change things, so, we should relax again. */
1054 *again = TRUE;
1058 prev_insn_branch = 0;
1059 prev_insn_group = 0;
1062 if (free_relocs != NULL)
1064 free (free_relocs);
1065 free_relocs = NULL;
1068 if (free_contents != NULL)
1070 if (! link_info->keep_memory)
1071 free (free_contents);
1072 else
1074 /* Cache the section contents for elf_link_input_bfd. */
1075 elf_section_data (sec)->this_hdr.contents = contents;
1077 free_contents = NULL;
1080 if (free_extsyms != NULL)
1082 if (! link_info->keep_memory)
1083 free (free_extsyms);
1084 else
1086 /* Cache the symbols for elf_link_input_bfd. */
1087 symtab_hdr->contents = (unsigned char *) isymbuf;
1089 free_extsyms = NULL;
1092 return TRUE;
1094 error_return:
1095 if (free_relocs != NULL)
1096 free (free_relocs);
1097 if (free_contents != NULL)
1098 free (free_contents);
1099 if (free_extsyms != NULL)
1100 free (free_extsyms);
1101 return FALSE;
1104 /* Delete some bytes from a section while relaxing. */
1106 static void
1107 m68hc11_elf_relax_delete_bytes (bfd *abfd, asection *sec,
1108 bfd_vma addr, int count)
1110 Elf_Internal_Shdr *symtab_hdr;
1111 unsigned int sec_shndx;
1112 bfd_byte *contents;
1113 Elf_Internal_Rela *irel, *irelend;
1114 bfd_vma toaddr;
1115 Elf_Internal_Sym *isymbuf, *isym, *isymend;
1116 struct elf_link_hash_entry **sym_hashes;
1117 struct elf_link_hash_entry **end_hashes;
1118 unsigned int symcount;
1120 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1121 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1123 sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
1125 contents = elf_section_data (sec)->this_hdr.contents;
1127 toaddr = sec->_cooked_size;
1129 irel = elf_section_data (sec)->relocs;
1130 irelend = irel + sec->reloc_count;
1132 /* Actually delete the bytes. */
1133 memmove (contents + addr, contents + addr + count,
1134 (size_t) (toaddr - addr - count));
1136 sec->_cooked_size -= count;
1138 /* Adjust all the relocs. */
1139 for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
1141 unsigned char code;
1142 unsigned char offset;
1143 unsigned short raddr;
1144 unsigned long old_offset;
1145 int branch_pos;
1147 old_offset = irel->r_offset;
1149 /* See if this reloc was for the bytes we have deleted, in which
1150 case we no longer care about it. Don't delete relocs which
1151 represent addresses, though. */
1152 if (ELF32_R_TYPE (irel->r_info) != R_M68HC11_RL_JUMP
1153 && irel->r_offset >= addr && irel->r_offset < addr + count)
1154 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1155 R_M68HC11_NONE);
1157 if (ELF32_R_TYPE (irel->r_info) == R_M68HC11_NONE)
1158 continue;
1160 /* Get the new reloc address. */
1161 if ((irel->r_offset > addr
1162 && irel->r_offset < toaddr))
1163 irel->r_offset -= count;
1165 /* If this is a PC relative reloc, see if the range it covers
1166 includes the bytes we have deleted. */
1167 switch (ELF32_R_TYPE (irel->r_info))
1169 default:
1170 break;
1172 case R_M68HC11_RL_JUMP:
1173 code = bfd_get_8 (abfd, contents + irel->r_offset);
1174 switch (code)
1176 /* jsr and jmp instruction are also marked with RL_JUMP
1177 relocs but no adjustment must be made. */
1178 case 0x7e:
1179 case 0x9d:
1180 case 0xbd:
1181 continue;
1183 case 0x12:
1184 case 0x13:
1185 branch_pos = 3;
1186 raddr = 4;
1188 /* Special case when we translate a brclr N,y into brclr *<addr>
1189 In this case, the 0x18 page2 prefix is removed.
1190 The reloc offset is not modified but the instruction
1191 size is reduced by 1. */
1192 if (old_offset == addr)
1193 raddr++;
1194 break;
1196 case 0x1e:
1197 case 0x1f:
1198 branch_pos = 3;
1199 raddr = 4;
1200 break;
1202 case 0x18:
1203 branch_pos = 4;
1204 raddr = 5;
1205 break;
1207 default:
1208 branch_pos = 1;
1209 raddr = 2;
1210 break;
1212 offset = bfd_get_8 (abfd, contents + irel->r_offset + branch_pos);
1213 raddr += old_offset;
1214 raddr += ((unsigned short) offset | ((offset & 0x80) ? 0xff00 : 0));
1215 if (irel->r_offset < addr && raddr > addr)
1217 offset -= count;
1218 bfd_put_8 (abfd, offset, contents + irel->r_offset + branch_pos);
1220 else if (irel->r_offset >= addr && raddr <= addr)
1222 offset += count;
1223 bfd_put_8 (abfd, offset, contents + irel->r_offset + branch_pos);
1225 else
1227 /*printf ("Not adjusted 0x%04x [0x%4x 0x%4x]\n", raddr,
1228 irel->r_offset, addr);*/
1231 break;
1235 /* Adjust the local symbols defined in this section. */
1236 isymend = isymbuf + symtab_hdr->sh_info;
1237 for (isym = isymbuf; isym < isymend; isym++)
1239 if (isym->st_shndx == sec_shndx
1240 && isym->st_value > addr
1241 && isym->st_value <= toaddr)
1242 isym->st_value -= count;
1245 /* Now adjust the global symbols defined in this section. */
1246 symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
1247 - symtab_hdr->sh_info);
1248 sym_hashes = elf_sym_hashes (abfd);
1249 end_hashes = sym_hashes + symcount;
1250 for (; sym_hashes < end_hashes; sym_hashes++)
1252 struct elf_link_hash_entry *sym_hash = *sym_hashes;
1253 if ((sym_hash->root.type == bfd_link_hash_defined
1254 || sym_hash->root.type == bfd_link_hash_defweak)
1255 && sym_hash->root.u.def.section == sec
1256 && sym_hash->root.u.def.value > addr
1257 && sym_hash->root.u.def.value <= toaddr)
1259 sym_hash->root.u.def.value -= count;
1264 /* Specific sections:
1265 - The .page0 is a data section that is mapped in [0x0000..0x00FF].
1266 Page0 accesses are faster on the M68HC11. Soft registers used by GCC-m6811
1267 are located in .page0.
1268 - The .vectors is the section that represents the interrupt
1269 vectors. */
1270 static struct bfd_elf_special_section const elf32_m68hc11_special_sections[]=
1272 { ".eeprom", 7, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
1273 { ".softregs", 9, 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
1274 { ".page0", 6, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
1275 { ".vectors", 8, 0, SHT_PROGBITS, SHF_ALLOC },
1276 { NULL, 0, 0, 0, 0 }
1279 #define ELF_ARCH bfd_arch_m68hc11
1280 #define ELF_MACHINE_CODE EM_68HC11
1281 #define ELF_MAXPAGESIZE 0x1000
1283 #define TARGET_BIG_SYM bfd_elf32_m68hc11_vec
1284 #define TARGET_BIG_NAME "elf32-m68hc11"
1286 #define elf_info_to_howto 0
1287 #define elf_info_to_howto_rel m68hc11_info_to_howto_rel
1288 #define bfd_elf32_bfd_relax_section m68hc11_elf_relax_section
1289 #define elf_backend_gc_mark_hook elf32_m68hc11_gc_mark_hook
1290 #define elf_backend_gc_sweep_hook elf32_m68hc11_gc_sweep_hook
1291 #define elf_backend_check_relocs elf32_m68hc11_check_relocs
1292 #define elf_backend_relocate_section elf32_m68hc11_relocate_section
1293 #define elf_backend_add_symbol_hook elf32_m68hc11_add_symbol_hook
1294 #define elf_backend_object_p 0
1295 #define elf_backend_final_write_processing 0
1296 #define elf_backend_can_gc_sections 1
1297 #define elf_backend_special_sections elf32_m68hc11_special_sections
1299 #define bfd_elf32_bfd_link_hash_table_create \
1300 m68hc11_elf_bfd_link_hash_table_create
1301 #define bfd_elf32_bfd_link_hash_table_free \
1302 m68hc11_elf_bfd_link_hash_table_free
1303 #define bfd_elf32_bfd_merge_private_bfd_data \
1304 _bfd_m68hc11_elf_merge_private_bfd_data
1305 #define bfd_elf32_bfd_set_private_flags _bfd_m68hc11_elf_set_private_flags
1306 #define bfd_elf32_bfd_print_private_bfd_data \
1307 _bfd_m68hc11_elf_print_private_bfd_data
1309 #include "elf32-target.h"