xref: /netbsd-src/external/gpl3/binutils.old/dist/bfd/elf32-z80.c (revision d16b7486a53dcb8072b60ec6fcb4373a2d0c27b7)
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.  */
34 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
35   (bfd *, bfd_reloc_code_real_type);
36 static bfd_boolean z80_info_to_howto_rel
37   (bfd *, arelent *, Elf_Internal_Rela *);
38 
39 typedef 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 
47 static const
48 bfd_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 
258 static reloc_howto_type *
259 bfd_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 
279 static reloc_howto_type *
280 bfd_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 
300 static bfd_boolean
301 z80_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 
326 static bfd_boolean
327 z80_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 
359 static int
360 z80_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"
381