Merge branch 'master' into merge-job
[deliverable/binutils-gdb.git] / bfd / elf32-z80.c
CommitLineData
6655dba2
SB
1/* Zilog (e)Z80-specific support for 32-bit ELF
2 Copyright (C) 1999-2019 Free Software Foundation, Inc.
3 (Heavily copied from the S12Z port by Sergey Belyashov (sergey.belyashov@gmail.com))
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
21
22#include "sysdep.h"
23#include "bfd.h"
24#include "bfdlink.h"
25#include "libbfd.h"
26#include "elf-bfd.h"
27
28#include "elf/z80.h"
29
30/* All users of this file have bfd_octets_per_byte (abfd, sec) == 1. */
31#define OCTETS_PER_BYTE(ABFD, SEC) 1
32
33/* Relocation functions. */
34static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
35 (bfd *, bfd_reloc_code_real_type);
36static bfd_boolean z80_info_to_howto_rel
37 (bfd *, arelent *, Elf_Internal_Rela *);
38
39typedef struct {
40 bfd_reloc_code_real_type r_type;
41 reloc_howto_type howto;
42} bfd_howto_type;
43
44#define BFD_EMPTY_HOWTO(rt,x) {rt, EMPTY_HOWTO(x)}
45#define BFD_HOWTO(rt,a,b,c,d,e,f,g,h,i,j,k,l,m) {rt, HOWTO(a,b,c,d,e,f,g,h,i,j,k,l,m)}
46
47static const
48bfd_howto_type elf_z80_howto_table[] =
49{
50 /* This reloc does nothing. */
51 BFD_HOWTO (BFD_RELOC_NONE,
52 R_Z80_NONE, /* type */
53 0, /* rightshift */
54 3, /* size (0 = byte, 1 = short, 2 = long) */
55 0, /* bitsize */
56 FALSE, /* pc_relative */
57 0, /* bitpos */
58 complain_overflow_dont,/* complain_on_overflow */
59 bfd_elf_generic_reloc, /* special_function */
60 "R_NONE", /* name */
61 FALSE, /* partial_inplace */
62 0, /* src_mask */
63 0, /* dst_mask */
64 FALSE), /* pcrel_offset */
65
66 /* A 8 bit relocation */
67 BFD_HOWTO (BFD_RELOC_8,
68 R_Z80_8, /* type */
69 0, /* rightshift */
70 0, /* size (0 = byte, 1 = short, 2 = long) */
71 8, /* bitsize */
72 FALSE, /* pc_relative */
73 0, /* bitpos */
74 complain_overflow_bitfield, /* complain_on_overflow */
75 bfd_elf_generic_reloc, /* special_function */
76 "r_imm8", /* name */
77 FALSE, /* partial_inplace */
78 0x00, /* src_mask */
79 0xff, /* dst_mask */
80 FALSE), /* pcrel_offset */
81
82 /* A 8 bit index register displacement relocation */
83 BFD_HOWTO (BFD_RELOC_Z80_DISP8,
84 R_Z80_8_DIS, /* type */
85 0, /* rightshift */
86 0, /* size (0 = byte, 1 = short, 2 = long) */
87 8, /* bitsize */
88 FALSE, /* pc_relative */
89 0, /* bitpos */
90 complain_overflow_signed, /* complain_on_overflow */
91 bfd_elf_generic_reloc, /* special_function */
92 "r_off", /* name */
93 FALSE, /* partial_inplace */
94 0x00, /* src_mask */
95 0xff, /* dst_mask */
96 FALSE), /* pcrel_offset */
97
98 /* A 8 bit PC-rel relocation */
99 BFD_HOWTO (BFD_RELOC_8_PCREL,
100 R_Z80_8_PCREL, /* type */
101 0, /* rightshift */
102 0, /* size (0 = byte, 1 = short, 2 = long) */
103 8, /* bitsize */
104 TRUE, /* pc_relative */
105 0, /* bitpos */
106 complain_overflow_signed, /* complain_on_overflow */
107 bfd_elf_generic_reloc, /* special_function */
108 "r_jr", /* name */
109 FALSE, /* partial_inplace */
110 0x00, /* src_mask */
111 0xff, /* dst_mask */
112 TRUE), /* pcrel_offset */
113
114 /* An 16 bit absolute relocation */
115 BFD_HOWTO (BFD_RELOC_16,
116 R_Z80_16, /* type */
117 0, /* rightshift */
118 1, /* size (0 = byte, 1 = short, 2 = long) */
119 16, /* bitsize */
120 FALSE, /* pc_relative */
121 0, /* bitpos */
122 complain_overflow_bitfield, /* complain_on_overflow */
123 bfd_elf_generic_reloc, /* special_function */
124 "r_imm16", /* name */
125 FALSE, /* partial_inplace */
126 0x00000000, /* src_mask */
127 0x0000ffff, /* dst_mask */
128 FALSE), /* pcrel_offset */
129
130 /* A 24 bit absolute relocation emitted by ADL mode operands */
131 BFD_HOWTO (BFD_RELOC_24,
132 R_Z80_24, /* type */
133 0, /* rightshift */
134 5, /* size (0 = byte, 1 = short, 2 = long) */
135 24, /* bitsize */
136 FALSE, /* pc_relative */
137 0, /* bitpos */
138 complain_overflow_bitfield, /* complain_on_overflow */
139 bfd_elf_generic_reloc, /* special_function */
140 "r_imm24", /* name */
141 FALSE, /* partial_inplace */
142 0x00000000, /* src_mask */
143 0x00ffffff, /* dst_mask */
144 FALSE), /* pcrel_offset */
145
146 BFD_HOWTO (BFD_RELOC_32,
147 R_Z80_32, /* type */
148 0, /* rightshift */
149 2, /* size (0 = byte, 1 = short, 2 = long) */
150 32, /* bitsize */
151 FALSE, /* pc_relative */
152 0, /* bitpos */
153 complain_overflow_dont,/* complain_on_overflow */
154 bfd_elf_generic_reloc, /* special_function */
155 "r_imm32", /* name */
156 FALSE, /* partial_inplace */
157 0x00000000, /* src_mask */
158 0xffffffff, /* dst_mask */
159 FALSE), /* pcrel_offset */
160
161 /* First (lowest) 8 bits of multibyte relocation */
162 BFD_HOWTO (BFD_RELOC_Z80_BYTE0,
163 R_Z80_BYTE0, /* type */
164 0, /* rightshift */
165 0, /* size (0 = byte, 1 = short, 2 = long) */
166 32, /* bitsize */
167 FALSE, /* pc_relative */
168 0, /* bitpos */
169 complain_overflow_dont,/* complain_on_overflow */
170 bfd_elf_generic_reloc, /* special_function */
171 "r_byte0", /* name */
172 FALSE, /* partial_inplace */
173 0, /* src_mask */
174 0xff, /* dst_mask */
175 FALSE), /* pcrel_offset */
176
177 /* Second 8 bits of multibyte relocation */
178 BFD_HOWTO (BFD_RELOC_Z80_BYTE1,
179 R_Z80_BYTE1, /* type */
180 8, /* rightshift */
181 0, /* size (0 = byte, 1 = short, 2 = long) */
182 32, /* bitsize */
183 FALSE, /* pc_relative */
184 0, /* bitpos */
185 complain_overflow_dont,/* complain_on_overflow */
186 bfd_elf_generic_reloc, /* special_function */
187 "r_byte1", /* name */
188 FALSE, /* partial_inplace */
189 0, /* src_mask */
190 0xff, /* dst_mask */
191 FALSE), /* pcrel_offset */
192
193 /* Third 8 bits of multibyte relocation */
194 BFD_HOWTO (BFD_RELOC_Z80_BYTE2,
195 R_Z80_BYTE2, /* type */
196 16, /* rightshift */
197 0, /* size (0 = byte, 1 = short, 2 = long) */
198 32, /* bitsize */
199 FALSE, /* pc_relative */
200 0, /* bitpos */
201 complain_overflow_dont,/* complain_on_overflow */
202 bfd_elf_generic_reloc, /* special_function */
203 "r_byte2", /* name */
204 FALSE, /* partial_inplace */
205 0, /* src_mask */
206 0xff, /* dst_mask */
207 FALSE), /* pcrel_offset */
208
209 /* Fourth (highest) 8 bits of multibyte relocation */
210 BFD_HOWTO (BFD_RELOC_Z80_BYTE3,
211 R_Z80_BYTE3, /* type */
212 24, /* rightshift */
213 0, /* size (0 = byte, 1 = short, 2 = long) */
214 32, /* bitsize */
215 FALSE, /* pc_relative */
216 0, /* bitpos */
217 complain_overflow_dont,/* complain_on_overflow */
218 bfd_elf_generic_reloc, /* special_function */
219 "r_byte3", /* name */
220 FALSE, /* partial_inplace */
221 0, /* src_mask */
222 0xff, /* dst_mask */
223 FALSE), /* pcrel_offset */
224
225 /* An 16 bit absolute relocation of lower word of multibyte value */
226 BFD_HOWTO (BFD_RELOC_Z80_WORD0,
227 R_Z80_WORD0, /* type */
228 0, /* rightshift */
229 1, /* size (0 = byte, 1 = short, 2 = long) */
230 32, /* bitsize */
231 FALSE, /* pc_relative */
232 0, /* bitpos */
233 complain_overflow_dont,/* complain_on_overflow */
234 bfd_elf_generic_reloc, /* special_function */
235 "r_word0", /* name */
236 FALSE, /* partial_inplace */
237 0, /* src_mask */
238 0xffff, /* dst_mask */
239 FALSE), /* pcrel_offset */
240
241 /* An 16 bit absolute relocation of higher word of multibyte value */
242 BFD_HOWTO (BFD_RELOC_Z80_WORD1,
243 R_Z80_WORD1, /* type */
244 16, /* rightshift */
245 1, /* size (0 = byte, 1 = short, 2 = long) */
246 32, /* bitsize */
247 FALSE, /* pc_relative */
248 0, /* bitpos */
249 complain_overflow_dont,/* complain_on_overflow */
250 bfd_elf_generic_reloc, /* special_function */
251 "r_word1", /* name */
252 FALSE, /* partial_inplace */
253 0, /* src_mask */
254 0xffff, /* dst_mask */
255 FALSE), /* pcrel_offset */
256};
257
258static reloc_howto_type *
259bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
260 bfd_reloc_code_real_type code)
261{
262 enum
263 {
264 table_size = sizeof (elf_z80_howto_table) / sizeof (elf_z80_howto_table[0])
265 };
266 unsigned int i;
267
268 for (i = 0; i < table_size; i++)
269 {
270 if (elf_z80_howto_table[i].r_type == code)
271 return &elf_z80_howto_table[i].howto;
272 }
273
274 printf ("%s:%d Not found type %d\n", __FILE__, __LINE__, code);
275
276 return NULL;
277}
278
279static reloc_howto_type *
280bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
281{
282 enum
283 {
284 table_size = sizeof (elf_z80_howto_table) / sizeof (elf_z80_howto_table[0])
285 };
286 unsigned int i;
287
288 for (i = 0; i < table_size; i++)
289 {
290 if (elf_z80_howto_table[i].howto.name != NULL
291 && strcasecmp (elf_z80_howto_table[i].howto.name, r_name) == 0)
292 return &elf_z80_howto_table[i].howto;
293 }
294
295 return NULL;
296}
297
298/* Set the howto pointer for an z80 ELF reloc. */
299
300static bfd_boolean
301z80_info_to_howto_rel (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst)
302{
303 enum
304 {
305 table_size = sizeof (elf_z80_howto_table) / sizeof (elf_z80_howto_table[0])
306 };
307 unsigned int i;
308 unsigned int r_type = ELF32_R_TYPE (dst->r_info);
309
310 for (i = 0; i < table_size; i++)
311 {
312 if (elf_z80_howto_table[i].howto.type == r_type)
313 {
314 cache_ptr->howto = &elf_z80_howto_table[i].howto;
315 return TRUE;
316 }
317 }
318
319 /* xgettext:c-format */
320 _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
321 abfd, r_type);
322 bfd_set_error (bfd_error_bad_value);
323 return FALSE;
324}
325
326static bfd_boolean
327z80_elf_set_mach_from_flags (bfd *abfd)
328{
329 int mach;
330 switch (elf_elfheader (abfd)->e_flags)
331 {
332 case EF_Z80_MACH_GBZ80:
333 mach = bfd_mach_gbz80;
334 break;
335 case EF_Z80_MACH_Z80:
336 mach = bfd_mach_z80;
337 break;
338 case EF_Z80_MACH_Z180:
339 mach = bfd_mach_z180;
340 break;
341 case EF_Z80_MACH_EZ80_Z80:
342 mach = bfd_mach_ez80_z80;
343 break;
344 case EF_Z80_MACH_EZ80_ADL:
345 mach = bfd_mach_ez80_adl;
346 break;
347 case EF_Z80_MACH_R800:
348 mach = bfd_mach_r800;
349 break;
350 default:
351 mach = bfd_mach_z80;
352 break;
353 }
354
355 bfd_default_set_arch_mach (abfd, bfd_arch_z80, mach);
356 return TRUE;
357}
358
359static int
360z80_is_local_label_name (bfd * abfd ATTRIBUTE_UNUSED,
361 const char * name)
362{
363 return (name[0] == '.' && name[1] == 'L') ||
364 _bfd_elf_is_local_label_name (abfd, name);
365}
366
367
368#define ELF_ARCH bfd_arch_z80
369#define ELF_MACHINE_CODE EM_Z80
370#define ELF_MAXPAGESIZE 0x10000
371
372#define TARGET_LITTLE_SYM z80_elf32_vec
373#define TARGET_LITTLE_NAME "elf32-z80"
374
375#define elf_info_to_howto NULL
376#define elf_info_to_howto_rel z80_info_to_howto_rel
377#define elf_backend_object_p z80_elf_set_mach_from_flags
378#define bfd_elf32_bfd_is_local_label_name z80_is_local_label_name
379
380#include "elf32-target.h"
This page took 0.036593 seconds and 4 git commands to generate.