1ed0d50c3Schristos /* Freescale XGATE-specific support for 32-bit ELF
2*b88e3e88Schristos Copyright (C) 2010-2020 Free Software Foundation, Inc.
3ed0d50c3Schristos Contributed by Sean Keys(skeys@ipdatasys.com)
4ed0d50c3Schristos
5ed0d50c3Schristos This file is part of BFD, the Binary File Descriptor library.
6ed0d50c3Schristos
7ed0d50c3Schristos This program is free software; you can redistribute it and/or modify
8ed0d50c3Schristos it under the terms of the GNU General Public License as published by
9ed0d50c3Schristos the Free Software Foundation; either version 3 of the License, or
10ed0d50c3Schristos (at your option) any later version.
11ed0d50c3Schristos
12ed0d50c3Schristos This program is distributed in the hope that it will be useful,
13ed0d50c3Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
14ed0d50c3Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15ed0d50c3Schristos GNU General Public License for more details.
16ed0d50c3Schristos
17ed0d50c3Schristos You should have received a copy of the GNU General Public License
18ed0d50c3Schristos along with this program; if not, write to the Free Software
19ed0d50c3Schristos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20ed0d50c3Schristos MA 02110-1301, USA. */
21ed0d50c3Schristos
22ed0d50c3Schristos #include "sysdep.h"
23ed0d50c3Schristos #include "bfd.h"
24ed0d50c3Schristos #include "bfdlink.h"
25ed0d50c3Schristos #include "libbfd.h"
26ed0d50c3Schristos #include "elf-bfd.h"
27ed0d50c3Schristos #include "elf/xgate.h"
28ed0d50c3Schristos #include "opcode/xgate.h"
29ed0d50c3Schristos #include "libiberty.h"
30ed0d50c3Schristos
31*b88e3e88Schristos /* Forward declarations. */
32*b88e3e88Schristos static bfd_reloc_status_type xgate_elf_ignore_reloc
33*b88e3e88Schristos (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
34*b88e3e88Schristos static bfd_reloc_status_type xgate_elf_special_reloc
35*b88e3e88Schristos (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
36ed0d50c3Schristos
37ed0d50c3Schristos /* Use REL instead of RELA to save space */
38ed0d50c3Schristos #define USE_REL 1
39ed0d50c3Schristos
40ed0d50c3Schristos static reloc_howto_type elf_xgate_howto_table[] =
41ed0d50c3Schristos {
42ed0d50c3Schristos /* This reloc does nothing. */
43ed0d50c3Schristos HOWTO (R_XGATE_NONE, /* type */
44ed0d50c3Schristos 0, /* rightshift */
45ed0d50c3Schristos 3, /* size (0 = byte, 1 = short, 2 = long) */
46ed0d50c3Schristos 0, /* bitsize */
47ed0d50c3Schristos FALSE, /* pc_relative */
48ed0d50c3Schristos 0, /* bitpos */
49ed0d50c3Schristos complain_overflow_dont,/* complain_on_overflow */
50ed0d50c3Schristos bfd_elf_generic_reloc, /* special_function */
51ed0d50c3Schristos "R_XGATE_NONE", /* name */
52ed0d50c3Schristos FALSE, /* partial_inplace */
53ed0d50c3Schristos 0, /* src_mask */
54ed0d50c3Schristos 0, /* dst_mask */
55ed0d50c3Schristos FALSE), /* pcrel_offset */
56ed0d50c3Schristos
57ed0d50c3Schristos /* A 8 bit absolute relocation. */
58ed0d50c3Schristos HOWTO (R_XGATE_8, /* type */
59ed0d50c3Schristos 0, /* rightshift */
60ed0d50c3Schristos 0, /* size (0 = byte, 1 = short, 2 = long) */
61ed0d50c3Schristos 8, /* bitsize */
62ed0d50c3Schristos FALSE, /* pc_relative */
63ed0d50c3Schristos 0, /* bitpos */
64ed0d50c3Schristos complain_overflow_bitfield, /* complain_on_overflow */
65ed0d50c3Schristos bfd_elf_generic_reloc, /* special_function */
66ed0d50c3Schristos "R_XGATE_8", /* name */
67ed0d50c3Schristos FALSE, /* partial_inplace */
68ed0d50c3Schristos 0x00ff, /* src_mask */
69ed0d50c3Schristos 0x00ff, /* dst_mask */
70ed0d50c3Schristos FALSE), /* pcrel_offset */
71ed0d50c3Schristos
72ed0d50c3Schristos /* A 8 bit PC-rel relocation. */
73ed0d50c3Schristos HOWTO (R_XGATE_PCREL_8, /* type */
74ed0d50c3Schristos 0, /* rightshift */
75ed0d50c3Schristos 0, /* size (0 = byte, 1 = short, 2 = long) */
76ed0d50c3Schristos 8, /* bitsize */
77ed0d50c3Schristos TRUE, /* pc_relative */
78ed0d50c3Schristos 0, /* bitpos */
79ed0d50c3Schristos complain_overflow_bitfield, /* complain_on_overflow */
80ed0d50c3Schristos bfd_elf_generic_reloc, /* special_function */
81ed0d50c3Schristos "R_XGATE_PCREL_8", /* name */
82ed0d50c3Schristos FALSE, /* partial_inplace */
83ed0d50c3Schristos 0x00ff, /* src_mask */
84ed0d50c3Schristos 0x00ff, /* dst_mask */
85ed0d50c3Schristos TRUE), /* pcrel_offset */
86ed0d50c3Schristos
87ed0d50c3Schristos /* A 16 bit absolute relocation. */
88ed0d50c3Schristos HOWTO (R_XGATE_16, /* type */
89ed0d50c3Schristos 0, /* rightshift */
90ed0d50c3Schristos 1, /* size (0 = byte, 1 = short, 2 = long) */
91ed0d50c3Schristos 16, /* bitsize */
92ed0d50c3Schristos FALSE, /* pc_relative */
93ed0d50c3Schristos 0, /* bitpos */
94ed0d50c3Schristos complain_overflow_dont /*bitfield */, /* complain_on_overflow */
95ed0d50c3Schristos bfd_elf_generic_reloc, /* special_function */
96ed0d50c3Schristos "R_XGATE_16", /* name */
97ed0d50c3Schristos FALSE, /* partial_inplace */
98ed0d50c3Schristos 0xffff, /* src_mask */
99ed0d50c3Schristos 0xffff, /* dst_mask */
100ed0d50c3Schristos FALSE), /* pcrel_offset */
101ed0d50c3Schristos
102ed0d50c3Schristos /* A 32 bit absolute relocation. This one is never used for the
103ed0d50c3Schristos code relocation. It's used by gas for -gstabs generation. */
104ed0d50c3Schristos HOWTO (R_XGATE_32, /* type */
105ed0d50c3Schristos 0, /* rightshift */
106ed0d50c3Schristos 2, /* size (0 = byte, 1 = short, 2 = long) */
107ed0d50c3Schristos 32, /* bitsize */
108ed0d50c3Schristos FALSE, /* pc_relative */
109ed0d50c3Schristos 0, /* bitpos */
110ed0d50c3Schristos complain_overflow_bitfield, /* complain_on_overflow */
111ed0d50c3Schristos bfd_elf_generic_reloc, /* special_function */
112ed0d50c3Schristos "R_XGATE_32", /* name */
113ed0d50c3Schristos FALSE, /* partial_inplace */
114ed0d50c3Schristos 0xffffffff, /* src_mask */
115ed0d50c3Schristos 0xffffffff, /* dst_mask */
116ed0d50c3Schristos FALSE), /* pcrel_offset */
117ed0d50c3Schristos
118ed0d50c3Schristos /* A 16 bit PC-rel relocation. */
119ed0d50c3Schristos HOWTO (R_XGATE_PCREL_16, /* type */
120ed0d50c3Schristos 0, /* rightshift */
121ed0d50c3Schristos 1, /* size (0 = byte, 1 = short, 2 = long) */
122ed0d50c3Schristos 16, /* bitsize */
123ed0d50c3Schristos TRUE, /* pc_relative */
124ed0d50c3Schristos 0, /* bitpos */
125ed0d50c3Schristos complain_overflow_dont, /* complain_on_overflow */
126ed0d50c3Schristos bfd_elf_generic_reloc, /* special_function */
127ed0d50c3Schristos "R_XGATE_PCREL_16", /* name */
128ed0d50c3Schristos FALSE, /* partial_inplace */
129ed0d50c3Schristos 0xffff, /* src_mask */
130ed0d50c3Schristos 0xffff, /* dst_mask */
131ed0d50c3Schristos TRUE), /* pcrel_offset */
132ed0d50c3Schristos
133ed0d50c3Schristos /* GNU extension to record C++ vtable hierarchy. */
134ed0d50c3Schristos HOWTO (R_XGATE_GNU_VTINHERIT, /* type */
135ed0d50c3Schristos 0, /* rightshift */
136ed0d50c3Schristos 1, /* size (0 = byte, 1 = short, 2 = long) */
137ed0d50c3Schristos 0, /* bitsize */
138ed0d50c3Schristos FALSE, /* pc_relative */
139ed0d50c3Schristos 0, /* bitpos */
140ed0d50c3Schristos complain_overflow_dont, /* complain_on_overflow */
141ed0d50c3Schristos NULL, /* special_function */
142ed0d50c3Schristos "R_XGATE_GNU_VTINHERIT", /* name */
143ed0d50c3Schristos FALSE, /* partial_inplace */
144ed0d50c3Schristos 0, /* src_mask */
145ed0d50c3Schristos 0, /* dst_mask */
146ed0d50c3Schristos FALSE), /* pcrel_offset */
147ed0d50c3Schristos
148ed0d50c3Schristos /* GNU extension to record C++ vtable member usage. */
149ed0d50c3Schristos HOWTO (R_XGATE_GNU_VTENTRY, /* type */
150ed0d50c3Schristos 0, /* rightshift */
151ed0d50c3Schristos 1, /* size (0 = byte, 1 = short, 2 = long) */
152ed0d50c3Schristos 0, /* bitsize */
153ed0d50c3Schristos FALSE, /* pc_relative */
154ed0d50c3Schristos 0, /* bitpos */
155ed0d50c3Schristos complain_overflow_dont, /* complain_on_overflow */
156ed0d50c3Schristos _bfd_elf_rel_vtable_reloc_fn, /* special_function */
157ed0d50c3Schristos "R_XGATE_GNU_VTENTRY", /* name */
158ed0d50c3Schristos FALSE, /* partial_inplace */
159ed0d50c3Schristos 0, /* src_mask */
160ed0d50c3Schristos 0, /* dst_mask */
161ed0d50c3Schristos FALSE), /* pcrel_offset */
162ed0d50c3Schristos
163ed0d50c3Schristos /* A 24 bit relocation. */
164ed0d50c3Schristos HOWTO (R_XGATE_24, /* type */
165ed0d50c3Schristos 0, /* rightshift */
166ed0d50c3Schristos 1, /* size (0 = byte, 1 = short, 2 = long) */
167ed0d50c3Schristos 16, /* bitsize */
168ed0d50c3Schristos FALSE, /* pc_relative */
169ed0d50c3Schristos 0, /* bitpos */
170ed0d50c3Schristos complain_overflow_dont, /* complain_on_overflow */
171ed0d50c3Schristos bfd_elf_generic_reloc, /* special_function */
172ed0d50c3Schristos "R_XGATE_IMM8_LO", /* name */
173ed0d50c3Schristos FALSE, /* partial_inplace */
174ed0d50c3Schristos 0x00ff, /* src_mask */
175ed0d50c3Schristos 0x00ff, /* dst_mask */
176ed0d50c3Schristos FALSE), /* pcrel_offset */
177ed0d50c3Schristos
178ed0d50c3Schristos /* A 16-bit low relocation. */
179ed0d50c3Schristos HOWTO (R_XGATE_LO16, /* type */
180ed0d50c3Schristos 8, /* rightshift */
181ed0d50c3Schristos 1, /* size (0 = byte, 1 = short, 2 = long) */
182ed0d50c3Schristos 16, /* bitsize */
183ed0d50c3Schristos FALSE, /* pc_relative */
184ed0d50c3Schristos 0, /* bitpos */
185ed0d50c3Schristos complain_overflow_dont, /* complain_on_overflow */
186ed0d50c3Schristos bfd_elf_generic_reloc, /* special_function */
187ed0d50c3Schristos "R_XGATE_IMM8_HI", /* name */
188ed0d50c3Schristos FALSE, /* partial_inplace */
189ed0d50c3Schristos 0x00ff, /* src_mask */
190ed0d50c3Schristos 0x00ff, /* dst_mask */
191ed0d50c3Schristos FALSE), /* pcrel_offset */
192ed0d50c3Schristos
193ed0d50c3Schristos /* A page relocation. */
194ed0d50c3Schristos HOWTO (R_XGATE_GPAGE, /* type */
195ed0d50c3Schristos 0, /* rightshift */
196ed0d50c3Schristos 0, /* size (0 = byte, 1 = short, 2 = long) */
197ed0d50c3Schristos 8, /* bitsize */
198ed0d50c3Schristos FALSE, /* pc_relative */
199ed0d50c3Schristos 0, /* bitpos */
200ed0d50c3Schristos complain_overflow_dont, /* complain_on_overflow */
201ed0d50c3Schristos xgate_elf_special_reloc,/* special_function */
202ed0d50c3Schristos "R_XGATE_GPAGE", /* name */
203ed0d50c3Schristos FALSE, /* partial_inplace */
204ed0d50c3Schristos 0x00ff, /* src_mask */
205ed0d50c3Schristos 0x00ff, /* dst_mask */
206ed0d50c3Schristos FALSE), /* pcrel_offset */
207ed0d50c3Schristos
208ed0d50c3Schristos /* A 9 bit absolute relocation. */
209ed0d50c3Schristos HOWTO (R_XGATE_PCREL_9, /* type */
210ed0d50c3Schristos 0, /* rightshift */
211ed0d50c3Schristos 1, /* size (0 = byte, 1 = short, 2 = long) */
212ed0d50c3Schristos 9, /* bitsize */
213ed0d50c3Schristos TRUE, /* pc_relative */
214ed0d50c3Schristos 0, /* bitpos */
215ed0d50c3Schristos complain_overflow_bitfield, /* complain_on_overflow */
216ed0d50c3Schristos bfd_elf_generic_reloc, /* special_function */
217ed0d50c3Schristos "R_XGATE_PCREL_9", /* name */
218ed0d50c3Schristos FALSE, /* partial_inplace */
219ed0d50c3Schristos 0xffff, /* src_mask */
220ed0d50c3Schristos 0xffff, /* dst_mask */
221ed0d50c3Schristos TRUE), /* pcrel_offset */
222ed0d50c3Schristos
223ed0d50c3Schristos /* A 8 bit absolute relocation (upper address). */
224ed0d50c3Schristos HOWTO (R_XGATE_PCREL_10, /* type */
225ed0d50c3Schristos 8, /* rightshift */
226ed0d50c3Schristos 0, /* size (0 = byte, 1 = short, 2 = long) */
227ed0d50c3Schristos 10, /* bitsize */
228ed0d50c3Schristos TRUE, /* pc_relative */
229ed0d50c3Schristos 0, /* bitpos */
230ed0d50c3Schristos complain_overflow_dont, /* complain_on_overflow */
231ed0d50c3Schristos bfd_elf_generic_reloc, /* special_function */
232ed0d50c3Schristos "R_XGATE_PCREL_10", /* name */
233ed0d50c3Schristos FALSE, /* partial_inplace */
234ed0d50c3Schristos 0x00ff, /* src_mask */
235ed0d50c3Schristos 0x00ff, /* dst_mask */
236ed0d50c3Schristos TRUE), /* pcrel_offset */
237ed0d50c3Schristos
238ed0d50c3Schristos /* A 8 bit absolute relocation. */
239ed0d50c3Schristos HOWTO (R_XGATE_IMM8_LO, /* type */
240ed0d50c3Schristos 0, /* rightshift */
241ed0d50c3Schristos 1, /* size (0 = byte, 1 = short, 2 = long) */
242ed0d50c3Schristos 16, /* bitsize */
243ed0d50c3Schristos FALSE, /* pc_relative */
244ed0d50c3Schristos 0, /* bitpos */
245ed0d50c3Schristos complain_overflow_dont, /* complain_on_overflow */
246ed0d50c3Schristos bfd_elf_generic_reloc, /* special_function */
247ed0d50c3Schristos "R_XGATE_IMM8_LO", /* name */
248ed0d50c3Schristos FALSE, /* partial_inplace */
249ed0d50c3Schristos 0xffff, /* src_mask */
250ed0d50c3Schristos 0xffff, /* dst_mask */
251ed0d50c3Schristos FALSE), /* pcrel_offset */
252ed0d50c3Schristos
253ed0d50c3Schristos /* A 16 bit absolute relocation (upper address). */
254ed0d50c3Schristos HOWTO (R_XGATE_IMM8_HI, /* type */
255ed0d50c3Schristos 8, /* rightshift */
256ed0d50c3Schristos 1, /* size (0 = byte, 1 = short, 2 = long) */
257ed0d50c3Schristos 16, /* bitsize */
258ed0d50c3Schristos FALSE, /* pc_relative */
259ed0d50c3Schristos 0, /* bitpos */
260ed0d50c3Schristos complain_overflow_dont, /* complain_on_overflow */
261ed0d50c3Schristos bfd_elf_generic_reloc, /* special_function */
262ed0d50c3Schristos "R_XGATE_IMM8_HI", /* name */
263ed0d50c3Schristos FALSE, /* partial_inplace */
264ed0d50c3Schristos 0x00ff, /* src_mask */
265ed0d50c3Schristos 0x00ff, /* dst_mask */
266ed0d50c3Schristos FALSE), /* pcrel_offset */
267ed0d50c3Schristos
268ed0d50c3Schristos /* A 3 bit absolute relocation. */
269ed0d50c3Schristos HOWTO (R_XGATE_IMM3, /* type */
270ed0d50c3Schristos 8, /* rightshift */
271ed0d50c3Schristos 1, /* size (0 = byte, 1 = short, 2 = long) */
272ed0d50c3Schristos 16, /* bitsize */
273ed0d50c3Schristos FALSE, /* pc_relative */
274ed0d50c3Schristos 0, /* bitpos */
275ed0d50c3Schristos complain_overflow_dont, /* complain_on_overflow */
276ed0d50c3Schristos bfd_elf_generic_reloc, /* special_function */
277ed0d50c3Schristos "R_XGATE_IMM3", /* name */
278ed0d50c3Schristos FALSE, /* partial_inplace */
279ed0d50c3Schristos 0x00ff, /* src_mask */
280ed0d50c3Schristos 0x00ff, /* dst_mask */
281ed0d50c3Schristos FALSE), /* pcrel_offset */
282ed0d50c3Schristos
283ed0d50c3Schristos /* A 4 bit absolute relocation. */
284ed0d50c3Schristos HOWTO (R_XGATE_IMM4, /* type */
285ed0d50c3Schristos 8, /* rightshift */
286ed0d50c3Schristos 1, /* size (0 = byte, 1 = short, 2 = long) */
287ed0d50c3Schristos 16, /* bitsize */
288ed0d50c3Schristos FALSE, /* pc_relative */
289ed0d50c3Schristos 0, /* bitpos */
290ed0d50c3Schristos complain_overflow_dont, /* complain_on_overflow */
291ed0d50c3Schristos bfd_elf_generic_reloc, /* special_function */
292ed0d50c3Schristos "R_XGATE_IMM4", /* name */
293ed0d50c3Schristos FALSE, /* partial_inplace */
294ed0d50c3Schristos 0x00ff, /* src_mask */
295ed0d50c3Schristos 0x00ff, /* dst_mask */
296ed0d50c3Schristos FALSE), /* pcrel_offset */
297ed0d50c3Schristos
298ed0d50c3Schristos /* A 5 bit absolute relocation. */
299ed0d50c3Schristos HOWTO (R_XGATE_IMM5, /* type */
300ed0d50c3Schristos 8, /* rightshift */
301ed0d50c3Schristos 1, /* size (0 = byte, 1 = short, 2 = long) */
302ed0d50c3Schristos 16, /* bitsize */
303ed0d50c3Schristos FALSE, /* pc_relative */
304ed0d50c3Schristos 0, /* bitpos */
305ed0d50c3Schristos complain_overflow_dont, /* complain_on_overflow */
306ed0d50c3Schristos bfd_elf_generic_reloc, /* special_function */
307ed0d50c3Schristos "R_XGATE_IMM5", /* name */
308ed0d50c3Schristos FALSE, /* partial_inplace */
309ed0d50c3Schristos 0x00ff, /* src_mask */
310ed0d50c3Schristos 0x00ff, /* dst_mask */
311ed0d50c3Schristos FALSE), /* pcrel_offset */
312ed0d50c3Schristos
313ed0d50c3Schristos /* Mark beginning of a jump instruction (any form). */
314ed0d50c3Schristos HOWTO (R_XGATE_RL_JUMP, /* type */
315ed0d50c3Schristos 0, /* rightshift */
316ed0d50c3Schristos 1, /* size (0 = byte, 1 = short, 2 = long) */
317ed0d50c3Schristos 0, /* bitsize */
318ed0d50c3Schristos FALSE, /* pc_relative */
319ed0d50c3Schristos 0, /* bitpos */
320ed0d50c3Schristos complain_overflow_dont, /* complain_on_overflow */
321ed0d50c3Schristos xgate_elf_ignore_reloc, /* special_function */
322ed0d50c3Schristos "R_XGATE_RL_JUMP", /* name */
323ed0d50c3Schristos TRUE, /* partial_inplace */
324ed0d50c3Schristos 0, /* src_mask */
325ed0d50c3Schristos 0, /* dst_mask */
326ed0d50c3Schristos TRUE), /* pcrel_offset */
327ed0d50c3Schristos
328ed0d50c3Schristos /* Mark beginning of Gcc relaxation group instruction. */
329ed0d50c3Schristos HOWTO (R_XGATE_RL_GROUP, /* type */
330ed0d50c3Schristos 0, /* rightshift */
331ed0d50c3Schristos 1, /* size (0 = byte, 1 = short, 2 = long) */
332ed0d50c3Schristos 0, /* bitsize */
333ed0d50c3Schristos FALSE, /* pc_relative */
334ed0d50c3Schristos 0, /* bitpos */
335ed0d50c3Schristos complain_overflow_dont, /* complain_on_overflow */
336ed0d50c3Schristos xgate_elf_ignore_reloc, /* special_function */
337ed0d50c3Schristos "R_XGATE_RL_GROUP", /* name */
338ed0d50c3Schristos TRUE, /* partial_inplace */
339ed0d50c3Schristos 0, /* src_mask */
340ed0d50c3Schristos 0, /* dst_mask */
341ed0d50c3Schristos TRUE), /* pcrel_offset */
342ed0d50c3Schristos };
343ed0d50c3Schristos
344ed0d50c3Schristos /* Map BFD reloc types to XGATE ELF reloc types. */
345ed0d50c3Schristos
346ed0d50c3Schristos struct xgate_reloc_map
347ed0d50c3Schristos {
348ed0d50c3Schristos bfd_reloc_code_real_type bfd_reloc_val;
349ed0d50c3Schristos unsigned char elf_reloc_val;
350ed0d50c3Schristos };
351ed0d50c3Schristos
352ed0d50c3Schristos static const struct xgate_reloc_map xgate_reloc_map[] =
353ed0d50c3Schristos {
354ed0d50c3Schristos {BFD_RELOC_NONE, R_XGATE_NONE},
355ed0d50c3Schristos {BFD_RELOC_8, R_XGATE_8},
356ed0d50c3Schristos {BFD_RELOC_8_PCREL, R_XGATE_PCREL_8},
357ed0d50c3Schristos {BFD_RELOC_16_PCREL, R_XGATE_PCREL_16},
358ed0d50c3Schristos {BFD_RELOC_16, R_XGATE_16},
359ed0d50c3Schristos {BFD_RELOC_32, R_XGATE_32},
360ed0d50c3Schristos
361ed0d50c3Schristos {BFD_RELOC_VTABLE_INHERIT, R_XGATE_GNU_VTINHERIT},
362ed0d50c3Schristos {BFD_RELOC_VTABLE_ENTRY, R_XGATE_GNU_VTENTRY},
363ed0d50c3Schristos
364ed0d50c3Schristos {BFD_RELOC_XGATE_LO16, R_XGATE_LO16},
365ed0d50c3Schristos {BFD_RELOC_XGATE_GPAGE, R_XGATE_GPAGE},
366ed0d50c3Schristos {BFD_RELOC_XGATE_24, R_XGATE_24},
367ed0d50c3Schristos {BFD_RELOC_XGATE_PCREL_9, R_XGATE_PCREL_9},
368ed0d50c3Schristos {BFD_RELOC_XGATE_PCREL_10, R_XGATE_PCREL_10},
369ed0d50c3Schristos {BFD_RELOC_XGATE_IMM8_LO, R_XGATE_IMM8_LO},
370ed0d50c3Schristos {BFD_RELOC_XGATE_IMM8_HI, R_XGATE_IMM8_HI},
371ed0d50c3Schristos {BFD_RELOC_XGATE_IMM3, R_XGATE_IMM3},
372ed0d50c3Schristos {BFD_RELOC_XGATE_IMM4, R_XGATE_IMM4},
373ed0d50c3Schristos {BFD_RELOC_XGATE_IMM5, R_XGATE_IMM5},
374ed0d50c3Schristos
375ed0d50c3Schristos {BFD_RELOC_XGATE_RL_JUMP, R_XGATE_RL_JUMP},
376ed0d50c3Schristos {BFD_RELOC_XGATE_RL_GROUP, R_XGATE_RL_GROUP},
377ed0d50c3Schristos };
378ed0d50c3Schristos
379ed0d50c3Schristos static reloc_howto_type *
bfd_elf32_bfd_reloc_type_lookup(bfd * abfd ATTRIBUTE_UNUSED,bfd_reloc_code_real_type code)380ed0d50c3Schristos bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
381ed0d50c3Schristos bfd_reloc_code_real_type code)
382ed0d50c3Schristos {
383ed0d50c3Schristos unsigned int i;
384ed0d50c3Schristos
385ed0d50c3Schristos for (i = 0; i < ARRAY_SIZE (xgate_reloc_map); i++)
386ed0d50c3Schristos if (xgate_reloc_map[i].bfd_reloc_val == code)
387ed0d50c3Schristos return &elf_xgate_howto_table[xgate_reloc_map[i].elf_reloc_val];
388ed0d50c3Schristos
389ed0d50c3Schristos return NULL;
390ed0d50c3Schristos }
391ed0d50c3Schristos
392ed0d50c3Schristos static reloc_howto_type *
bfd_elf32_bfd_reloc_name_lookup(bfd * abfd ATTRIBUTE_UNUSED,const char * r_name)393ed0d50c3Schristos bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
394ed0d50c3Schristos {
395ed0d50c3Schristos unsigned int i;
396ed0d50c3Schristos
397ed0d50c3Schristos for (i = 0; i < ARRAY_SIZE (elf_xgate_howto_table); i++)
398ed0d50c3Schristos if (elf_xgate_howto_table[i].name != NULL
399ed0d50c3Schristos && strcasecmp (elf_xgate_howto_table[i].name, r_name) == 0)
400ed0d50c3Schristos return &elf_xgate_howto_table[i];
401ed0d50c3Schristos
402ed0d50c3Schristos return NULL;
403ed0d50c3Schristos }
404ed0d50c3Schristos
405ed0d50c3Schristos /* Set the howto pointer for an XGATE ELF reloc. */
406ed0d50c3Schristos
40706324dcfSchristos static bfd_boolean
xgate_info_to_howto_rel(bfd * abfd,arelent * cache_ptr,Elf_Internal_Rela * dst)40806324dcfSchristos xgate_info_to_howto_rel (bfd *abfd,
409ed0d50c3Schristos arelent *cache_ptr,
410ed0d50c3Schristos Elf_Internal_Rela *dst)
411ed0d50c3Schristos {
412ed0d50c3Schristos unsigned int r_type;
413ed0d50c3Schristos
414ed0d50c3Schristos r_type = ELF32_R_TYPE (dst->r_info);
415ed0d50c3Schristos if (r_type >= (unsigned int) R_XGATE_max)
416ed0d50c3Schristos {
41706324dcfSchristos /* xgettext:c-format */
41806324dcfSchristos _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
41906324dcfSchristos abfd, r_type);
42006324dcfSchristos bfd_set_error (bfd_error_bad_value);
42106324dcfSchristos return FALSE;
422ed0d50c3Schristos }
423ed0d50c3Schristos cache_ptr->howto = &elf_xgate_howto_table[r_type];
42406324dcfSchristos return TRUE;
425ed0d50c3Schristos }
426ed0d50c3Schristos
427ed0d50c3Schristos /* Specific sections:
428ed0d50c3Schristos - The .page0 is a data section that is mapped in [0x0000..0x00FF].
429ed0d50c3Schristos Page0 accesses are faster on the M68HC12.
430ed0d50c3Schristos - The .vectors is the section that represents the interrupt
431ed0d50c3Schristos vectors.
432ed0d50c3Schristos - The .xgate section is starts in 0xE08800 or as xgate sees it 0x0800. */
433ed0d50c3Schristos static const struct bfd_elf_special_section elf32_xgate_special_sections[] =
434ed0d50c3Schristos {
435ed0d50c3Schristos { STRING_COMMA_LEN (".eeprom"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
436ed0d50c3Schristos { STRING_COMMA_LEN (".page0"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
437ed0d50c3Schristos { STRING_COMMA_LEN (".softregs"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
438ed0d50c3Schristos { STRING_COMMA_LEN (".vectors"), 0, SHT_PROGBITS, SHF_ALLOC },
439ed0d50c3Schristos /*{ STRING_COMMA_LEN (".xgate"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
440ed0d50c3Schristos TODO finish this implementation */
441ed0d50c3Schristos { NULL, 0, 0, 0, 0 }
442ed0d50c3Schristos };
443ed0d50c3Schristos
444*b88e3e88Schristos /* Hook called when reading symbols. */
445*b88e3e88Schristos
446*b88e3e88Schristos static void
elf32_xgate_backend_symbol_processing(bfd * abfd ATTRIBUTE_UNUSED,asymbol * sym)447*b88e3e88Schristos elf32_xgate_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
448*b88e3e88Schristos asymbol *sym)
449ed0d50c3Schristos {
450*b88e3e88Schristos /* Mark xgate symbols. */
451*b88e3e88Schristos ((elf_symbol_type *) sym)->internal_elf_sym.st_target_internal = 1;
452ed0d50c3Schristos }
453ed0d50c3Schristos
454ed0d50c3Schristos /* This function is used for relocs which are only used for relaxing,
455ed0d50c3Schristos which the linker should otherwise ignore. */
456ed0d50c3Schristos
457*b88e3e88Schristos static bfd_reloc_status_type
xgate_elf_ignore_reloc(bfd * abfd ATTRIBUTE_UNUSED,arelent * reloc_entry,asymbol * symbol ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED,asection * input_section,bfd * output_bfd,char ** error_message ATTRIBUTE_UNUSED)458ed0d50c3Schristos xgate_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED,
459ed0d50c3Schristos arelent *reloc_entry,
460ed0d50c3Schristos asymbol *symbol ATTRIBUTE_UNUSED,
461ed0d50c3Schristos void *data ATTRIBUTE_UNUSED,
462ed0d50c3Schristos asection *input_section,
463ed0d50c3Schristos bfd *output_bfd,
464ed0d50c3Schristos char **error_message ATTRIBUTE_UNUSED)
465ed0d50c3Schristos {
466ed0d50c3Schristos if (output_bfd != NULL)
467ed0d50c3Schristos reloc_entry->address += input_section->output_offset;
468ed0d50c3Schristos return bfd_reloc_ok;
469ed0d50c3Schristos }
470ed0d50c3Schristos
471*b88e3e88Schristos static bfd_reloc_status_type
xgate_elf_special_reloc(bfd * abfd ATTRIBUTE_UNUSED,arelent * reloc_entry ATTRIBUTE_UNUSED,asymbol * symbol ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED,asection * input_section ATTRIBUTE_UNUSED,bfd * output_bfd ATTRIBUTE_UNUSED,char ** error_message ATTRIBUTE_UNUSED)472ed0d50c3Schristos xgate_elf_special_reloc (bfd *abfd ATTRIBUTE_UNUSED,
473ed0d50c3Schristos arelent *reloc_entry ATTRIBUTE_UNUSED,
474ed0d50c3Schristos asymbol *symbol ATTRIBUTE_UNUSED,
475ed0d50c3Schristos void *data ATTRIBUTE_UNUSED,
476ed0d50c3Schristos asection *input_section ATTRIBUTE_UNUSED,
477ed0d50c3Schristos bfd *output_bfd ATTRIBUTE_UNUSED,
478ed0d50c3Schristos char **error_message ATTRIBUTE_UNUSED)
479ed0d50c3Schristos {
480ed0d50c3Schristos abort ();
481ed0d50c3Schristos }
482ed0d50c3Schristos
483*b88e3e88Schristos static bfd_boolean
_bfd_xgate_elf_print_private_bfd_data(bfd * abfd,void * ptr)484ed0d50c3Schristos _bfd_xgate_elf_print_private_bfd_data (bfd *abfd, void *ptr)
485ed0d50c3Schristos {
486ed0d50c3Schristos FILE *file = (FILE *) ptr;
487ed0d50c3Schristos
488ed0d50c3Schristos BFD_ASSERT (abfd != NULL && ptr != NULL);
489ed0d50c3Schristos
490ed0d50c3Schristos /* Print normal ELF private data. */
491ed0d50c3Schristos _bfd_elf_print_private_bfd_data (abfd, ptr);
492ed0d50c3Schristos
493ed0d50c3Schristos /* xgettext:c-format */
494ed0d50c3Schristos fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
495ed0d50c3Schristos
496ed0d50c3Schristos if (elf_elfheader (abfd)->e_flags & E_XGATE_I32)
497ed0d50c3Schristos fprintf (file, _("[abi=32-bit int, "));
498ed0d50c3Schristos else
499ed0d50c3Schristos fprintf (file, _("[abi=16-bit int, "));
500ed0d50c3Schristos
501ed0d50c3Schristos if (elf_elfheader (abfd)->e_flags & E_XGATE_F64)
502ed0d50c3Schristos fprintf (file, _("64-bit double, "));
503ed0d50c3Schristos else
504ed0d50c3Schristos fprintf (file, _("32-bit double, "));
505ed0d50c3Schristos if (elf_elfheader (abfd)->e_flags & EF_XGATE_MACH)
506ed0d50c3Schristos fprintf (file, _("cpu=XGATE]"));
507ed0d50c3Schristos else
508ed0d50c3Schristos fprintf (file, _("error reading cpu type from elf private data"));
509ed0d50c3Schristos fputc ('\n', file);
510ed0d50c3Schristos
511ed0d50c3Schristos return TRUE;
512ed0d50c3Schristos }
513ed0d50c3Schristos
514ed0d50c3Schristos #define ELF_ARCH bfd_arch_xgate
515ed0d50c3Schristos #define ELF_MACHINE_CODE EM_XGATE
516ed0d50c3Schristos
517ed0d50c3Schristos #define ELF_MAXPAGESIZE 0x1000
518ed0d50c3Schristos
519ed0d50c3Schristos #define TARGET_BIG_SYM xgate_elf32_vec
520ed0d50c3Schristos #define TARGET_BIG_NAME "elf32-xgate"
521ed0d50c3Schristos
522ed0d50c3Schristos #define elf_info_to_howto_rel xgate_info_to_howto_rel
523ed0d50c3Schristos #define elf_backend_special_sections elf32_xgate_special_sections
524*b88e3e88Schristos #define elf_backend_symbol_processing elf32_xgate_backend_symbol_processing
525ed0d50c3Schristos #define bfd_elf32_bfd_print_private_bfd_data _bfd_xgate_elf_print_private_bfd_data
526ed0d50c3Schristos
527ed0d50c3Schristos #include "elf32-target.h"
528