b4db9bc58e1a6fb8cf0c6d405399f6c2a76f2473
[external/binutils.git] / bfd / elf32-m68hc12.c
1 /* Motorola 68HC12-specific support for 32-bit ELF
2    Copyright (C) 1999, 2000 Free Software Foundation, Inc.
3    Contributed by Stephane Carrez (stcarrez@worldnet.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 2 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., 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"
27
28 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
29 PARAMS ((bfd * abfd, bfd_reloc_code_real_type code));
30 static void m68hc11_info_to_howto_rel
31 PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
32
33
34 /* Use REL instead of RELA to save space */
35 #define USE_REL
36
37 /* The Motorola 68HC11 microcontroler only addresses 64Kb.
38    We must handle 8 and 16-bit relocations.  The 32-bit relocation
39    is defined but not used except by gas when -gstabs is used (which
40    is wrong).
41    The 3-bit and 16-bit PC rel relocation is only used by 68HC12.  */
42 static reloc_howto_type elf_m68hc11_howto_table[] = {
43   /* This reloc does nothing.  */
44   HOWTO (R_M68HC11_NONE,        /* type */
45          0,                     /* rightshift */
46          2,                     /* size (0 = byte, 1 = short, 2 = long) */
47          32,                    /* bitsize */
48          false,                 /* pc_relative */
49          0,                     /* bitpos */
50          complain_overflow_bitfield,    /* complain_on_overflow */
51          bfd_elf_generic_reloc, /* special_function */
52          "R_M68HC11_NONE",      /* name */
53          false,                 /* partial_inplace */
54          0,                     /* src_mask */
55          0,                     /* dst_mask */
56          false),                /* pcrel_offset */
57
58   /* A 8 bit absolute relocation */
59   HOWTO (R_M68HC11_8,           /* type */
60          0,                     /* rightshift */
61          0,                     /* size (0 = byte, 1 = short, 2 = long) */
62          8,                     /* bitsize */
63          false,                 /* pc_relative */
64          0,                     /* bitpos */
65          complain_overflow_bitfield,    /* complain_on_overflow */
66          bfd_elf_generic_reloc, /* special_function */
67          "R_M68HC11_8",         /* name */
68          false,                 /* partial_inplace */
69          0x00ff,                /* src_mask */
70          0x00ff,                /* dst_mask */
71          false),                /* pcrel_offset */
72
73   /* A 8 bit absolute relocation (upper address) */
74   HOWTO (R_M68HC11_HI8,         /* type */
75          8,                     /* rightshift */
76          0,                     /* size (0 = byte, 1 = short, 2 = long) */
77          8,                     /* bitsize */
78          false,                 /* pc_relative */
79          0,                     /* bitpos */
80          complain_overflow_bitfield,    /* complain_on_overflow */
81          bfd_elf_generic_reloc, /* special_function */
82          "R_M68HC11_HI8",       /* name */
83          false,                 /* partial_inplace */
84          0x00ff,                /* src_mask */
85          0x00ff,                /* dst_mask */
86          false),                /* pcrel_offset */
87
88   /* A 8 bit absolute relocation (upper address) */
89   HOWTO (R_M68HC11_LO8,         /* type */
90          0,                     /* rightshift */
91          0,                     /* size (0 = byte, 1 = short, 2 = long) */
92          8,                     /* bitsize */
93          false,                 /* pc_relative */
94          0,                     /* bitpos */
95          complain_overflow_dont,        /* complain_on_overflow */
96          bfd_elf_generic_reloc, /* special_function */
97          "R_M68HC11_LO8",       /* name */
98          false,                 /* partial_inplace */
99          0x00ff,                /* src_mask */
100          0x00ff,                /* dst_mask */
101          false),                /* pcrel_offset */
102
103   /* A 8 bit PC-rel relocation */
104   HOWTO (R_M68HC11_PCREL_8,     /* type */
105          0,                     /* rightshift */
106          0,                     /* size (0 = byte, 1 = short, 2 = long) */
107          8,                     /* bitsize */
108          true,                  /* pc_relative */
109          0,                     /* bitpos */
110          complain_overflow_bitfield,    /* complain_on_overflow */
111          bfd_elf_generic_reloc, /* special_function */
112          "R_M68HC11_PCREL_8",   /* name */
113          false,                 /* partial_inplace */
114          0x0,                   /* src_mask */
115          0x00ff,                /* dst_mask */
116          false),                /* pcrel_offset */
117
118   /* A 16 bit absolute relocation */
119   HOWTO (R_M68HC11_16,          /* type */
120          0,                     /* rightshift */
121          1,                     /* size (0 = byte, 1 = short, 2 = long) */
122          16,                    /* bitsize */
123          false,                 /* pc_relative */
124          0,                     /* bitpos */
125          complain_overflow_dont /*bitfield */ , /* complain_on_overflow */
126          bfd_elf_generic_reloc, /* special_function */
127          "R_M68HC11_16",        /* name */
128          false,                 /* partial_inplace */
129          0xffff,                /* src_mask */
130          0xffff,                /* dst_mask */
131          false),                /* pcrel_offset */
132
133   /* A 32 bit absolute relocation.  This one is never used for the
134      code relocation.  It's used by gas for -gstabs generation.  */
135   HOWTO (R_M68HC11_32,          /* type */
136          0,                     /* rightshift */
137          2,                     /* size (0 = byte, 1 = short, 2 = long) */
138          32,                    /* bitsize */
139          false,                 /* pc_relative */
140          0,                     /* bitpos */
141          complain_overflow_bitfield,    /* complain_on_overflow */
142          bfd_elf_generic_reloc, /* special_function */
143          "R_M68HC11_32",        /* name */
144          false,                 /* partial_inplace */
145          0xffffffff,            /* src_mask */
146          0xffffffff,            /* dst_mask */
147          false),                /* pcrel_offset */
148
149   /* A 3 bit absolute relocation */
150   HOWTO (R_M68HC11_3B,          /* type */
151          0,                     /* rightshift */
152          0,                     /* size (0 = byte, 1 = short, 2 = long) */
153          3,                     /* bitsize */
154          false,                 /* pc_relative */
155          0,                     /* bitpos */
156          complain_overflow_bitfield,    /* complain_on_overflow */
157          bfd_elf_generic_reloc, /* special_function */
158          "R_M68HC11_4B",        /* name */
159          false,                 /* partial_inplace */
160          0x003,                 /* src_mask */
161          0x003,                 /* dst_mask */
162          false),                /* pcrel_offset */
163
164   /* A 16 bit PC-rel relocation */
165   HOWTO (R_M68HC11_PCREL_16,    /* type */
166          0,                     /* rightshift */
167          1,                     /* size (0 = byte, 1 = short, 2 = long) */
168          16,                    /* bitsize */
169          true,                  /* pc_relative */
170          0,                     /* bitpos */
171          complain_overflow_dont,        /* complain_on_overflow */
172          bfd_elf_generic_reloc, /* special_function */
173          "R_M68HC11_PCREL_16",  /* name */
174          false,                 /* partial_inplace */
175          0x0,                   /* src_mask */
176          0xffff,                /* dst_mask */
177          false),                /* pcrel_offset */
178
179   /* GNU extension to record C++ vtable hierarchy */
180   HOWTO (R_M68HC11_GNU_VTINHERIT,       /* type */
181          0,                     /* rightshift */
182          1,                     /* size (0 = byte, 1 = short, 2 = long) */
183          0,                     /* bitsize */
184          false,                 /* pc_relative */
185          0,                     /* bitpos */
186          complain_overflow_dont,        /* complain_on_overflow */
187          NULL,                  /* special_function */
188          "R_M68HC11_GNU_VTINHERIT",     /* name */
189          false,                 /* partial_inplace */
190          0,                     /* src_mask */
191          0,                     /* dst_mask */
192          false),                /* pcrel_offset */
193
194   /* GNU extension to record C++ vtable member usage */
195   HOWTO (R_M68HC11_GNU_VTENTRY, /* type */
196          0,                     /* rightshift */
197          1,                     /* size (0 = byte, 1 = short, 2 = long) */
198          0,                     /* bitsize */
199          false,                 /* pc_relative */
200          0,                     /* bitpos */
201          complain_overflow_dont,        /* complain_on_overflow */
202          _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
203          "R_M68HC11_GNU_VTENTRY",       /* name */
204          false,                 /* partial_inplace */
205          0,                     /* src_mask */
206          0,                     /* dst_mask */
207          false),                /* pcrel_offset */
208 };
209
210 /* Map BFD reloc types to M68HC11 ELF reloc types.  */
211
212 struct m68hc11_reloc_map
213 {
214   bfd_reloc_code_real_type bfd_reloc_val;
215   unsigned char elf_reloc_val;
216 };
217
218 static const struct m68hc11_reloc_map m68hc11_reloc_map[] = {
219   {BFD_RELOC_NONE, R_M68HC11_NONE,},
220   {BFD_RELOC_8, R_M68HC11_8},
221   {BFD_RELOC_M68HC11_HI8, R_M68HC11_HI8},
222   {BFD_RELOC_M68HC11_LO8, R_M68HC11_LO8},
223   {BFD_RELOC_8_PCREL, R_M68HC11_PCREL_8},
224   {BFD_RELOC_16_PCREL, R_M68HC11_PCREL_16},
225   {BFD_RELOC_16, R_M68HC11_16},
226   {BFD_RELOC_32, R_M68HC11_32},
227   {BFD_RELOC_M68HC11_3B, R_M68HC11_3B},
228
229   /* The following relocs are defined but they probably don't work yet.  */
230   {BFD_RELOC_VTABLE_INHERIT, R_M68HC11_GNU_VTINHERIT},
231   {BFD_RELOC_VTABLE_ENTRY, R_M68HC11_GNU_VTENTRY},
232 };
233
234 static reloc_howto_type *
235 bfd_elf32_bfd_reloc_type_lookup (abfd, code)
236      bfd *abfd ATTRIBUTE_UNUSED;
237      bfd_reloc_code_real_type code;
238 {
239   unsigned int i;
240
241   for (i = 0;
242        i < sizeof (m68hc11_reloc_map) / sizeof (struct m68hc11_reloc_map);
243        i++)
244     {
245       if (m68hc11_reloc_map[i].bfd_reloc_val == code)
246         return &elf_m68hc11_howto_table[m68hc11_reloc_map[i].elf_reloc_val];
247     }
248
249   return NULL;
250 }
251
252 /* Set the howto pointer for an M68HC11 ELF reloc.  */
253
254 static void
255 m68hc11_info_to_howto_rel (abfd, cache_ptr, dst)
256      bfd *abfd ATTRIBUTE_UNUSED;
257      arelent *cache_ptr;
258      Elf32_Internal_Rel *dst;
259 {
260   unsigned int r_type;
261
262   r_type = ELF32_R_TYPE (dst->r_info);
263   BFD_ASSERT (r_type < (unsigned int) R_M68HC11_max);
264   cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
265 }
266
267 /* Below is the only difference between elf32-m68hc12.c and elf32-m68hc11.c.
268    The Motorola spec says to use a different Elf machine code.  */
269 #define ELF_ARCH                bfd_arch_m68hc12
270 #define ELF_MACHINE_CODE        EM_68HC12
271 #define ELF_MAXPAGESIZE         0x1000
272
273 #define TARGET_BIG_SYM          bfd_elf32_m68hc12_vec
274 #define TARGET_BIG_NAME         "elf32-m68hc12"
275
276 #define elf_info_to_howto       0
277 #define elf_info_to_howto_rel   m68hc11_info_to_howto_rel
278 #define elf_backend_object_p    0
279 #define elf_backend_final_write_processing      0
280
281 #include "elf32-target.h"