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