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