de747b331020e714d97d630c77692218e985174d
[external/binutils.git] / bfd / elf32-m68hc11.c
1 /* Motorola 68HC11-specific support for 32-bit ELF
2    Copyright 1999, 2000, 2001, 2002 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 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 static bfd_reloc_status_type m68hc11_elf_ignore_reloc
34 PARAMS ((bfd *abfd, arelent *reloc_entry,
35          asymbol *symbol, PTR data, asection *input_section,
36          bfd *output_bfd, char **error_message));
37
38 /* Use REL instead of RELA to save space */
39 #define USE_REL
40
41 /* The Motorola 68HC11 microcontroler only addresses 64Kb.
42    We must handle 8 and 16-bit relocations.  The 32-bit relocation
43    is defined but not used except by gas when -gstabs is used (which
44    is wrong).
45    The 3-bit and 16-bit PC rel relocation is only used by 68HC12.  */
46 static reloc_howto_type elf_m68hc11_howto_table[] = {
47   /* This reloc does nothing.  */
48   HOWTO (R_M68HC11_NONE,        /* type */
49          0,                     /* rightshift */
50          2,                     /* size (0 = byte, 1 = short, 2 = long) */
51          32,                    /* bitsize */
52          false,                 /* pc_relative */
53          0,                     /* bitpos */
54          complain_overflow_bitfield,    /* complain_on_overflow */
55          bfd_elf_generic_reloc, /* special_function */
56          "R_M68HC11_NONE",      /* name */
57          false,                 /* partial_inplace */
58          0,                     /* src_mask */
59          0,                     /* dst_mask */
60          false),                /* pcrel_offset */
61
62   /* A 8 bit absolute relocation */
63   HOWTO (R_M68HC11_8,           /* type */
64          0,                     /* rightshift */
65          0,                     /* size (0 = byte, 1 = short, 2 = long) */
66          8,                     /* bitsize */
67          false,                 /* pc_relative */
68          0,                     /* bitpos */
69          complain_overflow_bitfield,    /* complain_on_overflow */
70          bfd_elf_generic_reloc, /* special_function */
71          "R_M68HC11_8",         /* name */
72          false,                 /* partial_inplace */
73          0x00ff,                /* src_mask */
74          0x00ff,                /* dst_mask */
75          false),                /* pcrel_offset */
76
77   /* A 8 bit absolute relocation (upper address) */
78   HOWTO (R_M68HC11_HI8,         /* type */
79          8,                     /* rightshift */
80          0,                     /* size (0 = byte, 1 = short, 2 = long) */
81          8,                     /* bitsize */
82          false,                 /* pc_relative */
83          0,                     /* bitpos */
84          complain_overflow_bitfield,    /* complain_on_overflow */
85          bfd_elf_generic_reloc, /* special_function */
86          "R_M68HC11_HI8",       /* name */
87          false,                 /* partial_inplace */
88          0x00ff,                /* src_mask */
89          0x00ff,                /* dst_mask */
90          false),                /* pcrel_offset */
91
92   /* A 8 bit absolute relocation (upper address) */
93   HOWTO (R_M68HC11_LO8,         /* type */
94          0,                     /* rightshift */
95          0,                     /* size (0 = byte, 1 = short, 2 = long) */
96          8,                     /* bitsize */
97          false,                 /* pc_relative */
98          0,                     /* bitpos */
99          complain_overflow_dont,        /* complain_on_overflow */
100          bfd_elf_generic_reloc, /* special_function */
101          "R_M68HC11_LO8",       /* name */
102          false,                 /* partial_inplace */
103          0x00ff,                /* src_mask */
104          0x00ff,                /* dst_mask */
105          false),                /* pcrel_offset */
106
107   /* A 8 bit PC-rel relocation */
108   HOWTO (R_M68HC11_PCREL_8,     /* type */
109          0,                     /* rightshift */
110          0,                     /* size (0 = byte, 1 = short, 2 = long) */
111          8,                     /* bitsize */
112          true,                  /* pc_relative */
113          0,                     /* bitpos */
114          complain_overflow_bitfield,    /* complain_on_overflow */
115          bfd_elf_generic_reloc, /* special_function */
116          "R_M68HC11_PCREL_8",   /* name */
117          false,                 /* partial_inplace */
118          0x00ff,                /* src_mask */
119          0x00ff,                /* dst_mask */
120          false),                /* pcrel_offset */
121
122   /* A 16 bit absolute relocation */
123   HOWTO (R_M68HC11_16,          /* type */
124          0,                     /* rightshift */
125          1,                     /* size (0 = byte, 1 = short, 2 = long) */
126          16,                    /* bitsize */
127          false,                 /* pc_relative */
128          0,                     /* bitpos */
129          complain_overflow_dont /*bitfield */ , /* complain_on_overflow */
130          bfd_elf_generic_reloc, /* special_function */
131          "R_M68HC11_16",        /* name */
132          false,                 /* partial_inplace */
133          0xffff,                /* src_mask */
134          0xffff,                /* dst_mask */
135          false),                /* pcrel_offset */
136
137   /* A 32 bit absolute relocation.  This one is never used for the
138      code relocation.  It's used by gas for -gstabs generation.  */
139   HOWTO (R_M68HC11_32,          /* type */
140          0,                     /* rightshift */
141          2,                     /* size (0 = byte, 1 = short, 2 = long) */
142          32,                    /* bitsize */
143          false,                 /* pc_relative */
144          0,                     /* bitpos */
145          complain_overflow_bitfield,    /* complain_on_overflow */
146          bfd_elf_generic_reloc, /* special_function */
147          "R_M68HC11_32",        /* name */
148          false,                 /* partial_inplace */
149          0xffffffff,            /* src_mask */
150          0xffffffff,            /* dst_mask */
151          false),                /* pcrel_offset */
152
153   /* A 3 bit absolute relocation */
154   HOWTO (R_M68HC11_3B,          /* type */
155          0,                     /* rightshift */
156          0,                     /* size (0 = byte, 1 = short, 2 = long) */
157          3,                     /* bitsize */
158          false,                 /* pc_relative */
159          0,                     /* bitpos */
160          complain_overflow_bitfield,    /* complain_on_overflow */
161          bfd_elf_generic_reloc, /* special_function */
162          "R_M68HC11_4B",        /* name */
163          false,                 /* partial_inplace */
164          0x003,                 /* src_mask */
165          0x003,                 /* dst_mask */
166          false),                /* pcrel_offset */
167
168   /* A 16 bit PC-rel relocation */
169   HOWTO (R_M68HC11_PCREL_16,    /* type */
170          0,                     /* rightshift */
171          1,                     /* size (0 = byte, 1 = short, 2 = long) */
172          16,                    /* bitsize */
173          true,                  /* pc_relative */
174          0,                     /* bitpos */
175          complain_overflow_dont,        /* complain_on_overflow */
176          bfd_elf_generic_reloc, /* special_function */
177          "R_M68HC11_PCREL_16",  /* name */
178          false,                 /* partial_inplace */
179          0xffff,                /* src_mask */
180          0xffff,                /* dst_mask */
181          false),                /* pcrel_offset */
182
183   /* GNU extension to record C++ vtable hierarchy */
184   HOWTO (R_M68HC11_GNU_VTINHERIT,       /* type */
185          0,                     /* rightshift */
186          1,                     /* size (0 = byte, 1 = short, 2 = long) */
187          0,                     /* bitsize */
188          false,                 /* pc_relative */
189          0,                     /* bitpos */
190          complain_overflow_dont,        /* complain_on_overflow */
191          NULL,                  /* special_function */
192          "R_M68HC11_GNU_VTINHERIT",     /* name */
193          false,                 /* partial_inplace */
194          0,                     /* src_mask */
195          0,                     /* dst_mask */
196          false),                /* pcrel_offset */
197
198   /* GNU extension to record C++ vtable member usage */
199   HOWTO (R_M68HC11_GNU_VTENTRY, /* type */
200          0,                     /* rightshift */
201          1,                     /* size (0 = byte, 1 = short, 2 = long) */
202          0,                     /* bitsize */
203          false,                 /* pc_relative */
204          0,                     /* bitpos */
205          complain_overflow_dont,        /* complain_on_overflow */
206          _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
207          "R_M68HC11_GNU_VTENTRY",       /* name */
208          false,                 /* partial_inplace */
209          0,                     /* src_mask */
210          0,                     /* dst_mask */
211          false),                /* pcrel_offset */
212
213   EMPTY_HOWTO (11),
214   EMPTY_HOWTO (12),
215   EMPTY_HOWTO (13),
216   EMPTY_HOWTO (14),
217   EMPTY_HOWTO (15),
218   EMPTY_HOWTO (16),
219   EMPTY_HOWTO (17),
220   EMPTY_HOWTO (18),
221   EMPTY_HOWTO (19),
222   
223   /* Mark beginning of a jump instruction (any form).  */
224   HOWTO (R_M68HC11_RL_JUMP,     /* type */
225          0,                     /* rightshift */
226          1,                     /* size (0 = byte, 1 = short, 2 = long) */
227          0,                     /* bitsize */
228          false,                 /* pc_relative */
229          0,                     /* bitpos */
230          complain_overflow_dont,        /* complain_on_overflow */
231          m68hc11_elf_ignore_reloc,      /* special_function */
232          "R_M68HC11_RL_JUMP",   /* name */
233          true,                  /* partial_inplace */
234          0,                     /* src_mask */
235          0,                     /* dst_mask */
236          true),                 /* pcrel_offset */
237
238   /* Mark beginning of Gcc relaxation group instruction.  */
239   HOWTO (R_M68HC11_RL_GROUP,    /* type */
240          0,                     /* rightshift */
241          1,                     /* size (0 = byte, 1 = short, 2 = long) */
242          0,                     /* bitsize */
243          false,                 /* pc_relative */
244          0,                     /* bitpos */
245          complain_overflow_dont,        /* complain_on_overflow */
246          m68hc11_elf_ignore_reloc,      /* special_function */
247          "R_M68HC11_RL_GROUP",  /* name */
248          true,                  /* partial_inplace */
249          0,                     /* src_mask */
250          0,                     /* dst_mask */
251          true),                 /* pcrel_offset */
252 };
253
254 /* Map BFD reloc types to M68HC11 ELF reloc types.  */
255
256 struct m68hc11_reloc_map
257 {
258   bfd_reloc_code_real_type bfd_reloc_val;
259   unsigned char elf_reloc_val;
260 };
261
262 static const struct m68hc11_reloc_map m68hc11_reloc_map[] = {
263   {BFD_RELOC_NONE, R_M68HC11_NONE,},
264   {BFD_RELOC_8, R_M68HC11_8},
265   {BFD_RELOC_M68HC11_HI8, R_M68HC11_HI8},
266   {BFD_RELOC_M68HC11_LO8, R_M68HC11_LO8},
267   {BFD_RELOC_8_PCREL, R_M68HC11_PCREL_8},
268   {BFD_RELOC_16_PCREL, R_M68HC11_PCREL_16},
269   {BFD_RELOC_16, R_M68HC11_16},
270   {BFD_RELOC_32, R_M68HC11_32},
271   {BFD_RELOC_M68HC11_3B, R_M68HC11_3B},
272
273   {BFD_RELOC_VTABLE_INHERIT, R_M68HC11_GNU_VTINHERIT},
274   {BFD_RELOC_VTABLE_ENTRY, R_M68HC11_GNU_VTENTRY},
275
276   {BFD_RELOC_M68HC11_RL_JUMP, R_M68HC11_RL_JUMP},
277   {BFD_RELOC_M68HC11_RL_GROUP, R_M68HC11_RL_GROUP},
278 };
279
280 static reloc_howto_type *
281 bfd_elf32_bfd_reloc_type_lookup (abfd, code)
282      bfd *abfd ATTRIBUTE_UNUSED;
283      bfd_reloc_code_real_type code;
284 {
285   unsigned int i;
286
287   for (i = 0;
288        i < sizeof (m68hc11_reloc_map) / sizeof (struct m68hc11_reloc_map);
289        i++)
290     {
291       if (m68hc11_reloc_map[i].bfd_reloc_val == code)
292         return &elf_m68hc11_howto_table[m68hc11_reloc_map[i].elf_reloc_val];
293     }
294
295   return NULL;
296 }
297
298 /* This function is used for relocs which are only used for relaxing,
299    which the linker should otherwise ignore.  */
300
301 static bfd_reloc_status_type
302 m68hc11_elf_ignore_reloc (abfd, reloc_entry, symbol, data, input_section,
303                           output_bfd, error_message)
304      bfd *abfd ATTRIBUTE_UNUSED;
305      arelent *reloc_entry;
306      asymbol *symbol ATTRIBUTE_UNUSED;
307      PTR data ATTRIBUTE_UNUSED;
308      asection *input_section;
309      bfd *output_bfd;
310      char **error_message ATTRIBUTE_UNUSED;
311 {
312   if (output_bfd != NULL)
313     reloc_entry->address += input_section->output_offset;
314   return bfd_reloc_ok;
315 }
316
317 /* Set the howto pointer for an M68HC11 ELF reloc.  */
318
319 static void
320 m68hc11_info_to_howto_rel (abfd, cache_ptr, dst)
321      bfd *abfd ATTRIBUTE_UNUSED;
322      arelent *cache_ptr;
323      Elf32_Internal_Rel *dst;
324 {
325   unsigned int r_type;
326
327   r_type = ELF32_R_TYPE (dst->r_info);
328   BFD_ASSERT (r_type < (unsigned int) R_M68HC11_max);
329   cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
330 }
331
332 /* Below is the only difference between elf32-m68hc12.c and elf32-m68hc11.c.
333    The Motorola spec says to use a different Elf machine code.  */
334 #define ELF_ARCH                bfd_arch_m68hc11
335 #define ELF_MACHINE_CODE        EM_68HC11
336 #define ELF_MAXPAGESIZE         0x1000
337
338 #define TARGET_BIG_SYM          bfd_elf32_m68hc11_vec
339 #define TARGET_BIG_NAME         "elf32-m68hc11"
340
341 #define elf_info_to_howto       0
342 #define elf_info_to_howto_rel   m68hc11_info_to_howto_rel
343 #define elf_backend_object_p    0
344 #define elf_backend_final_write_processing      0
345
346 #include "elf32-target.h"