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