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