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