1*3d8817e4Smiod /* BFD back-end for Renesas Super-H COFF binaries.
2*3d8817e4Smiod Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
3*3d8817e4Smiod 2003, 2004, 2005 Free Software Foundation, Inc.
4*3d8817e4Smiod Contributed by Cygnus Support.
5*3d8817e4Smiod Written by Steve Chamberlain, <sac@cygnus.com>.
6*3d8817e4Smiod Relaxing code written by Ian Lance Taylor, <ian@cygnus.com>.
7*3d8817e4Smiod
8*3d8817e4Smiod This file is part of BFD, the Binary File Descriptor library.
9*3d8817e4Smiod
10*3d8817e4Smiod This program is free software; you can redistribute it and/or modify
11*3d8817e4Smiod it under the terms of the GNU General Public License as published by
12*3d8817e4Smiod the Free Software Foundation; either version 2 of the License, or
13*3d8817e4Smiod (at your option) any later version.
14*3d8817e4Smiod
15*3d8817e4Smiod This program is distributed in the hope that it will be useful,
16*3d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
17*3d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18*3d8817e4Smiod GNU General Public License for more details.
19*3d8817e4Smiod
20*3d8817e4Smiod You should have received a copy of the GNU General Public License
21*3d8817e4Smiod along with this program; if not, write to the Free Software
22*3d8817e4Smiod Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
23*3d8817e4Smiod
24*3d8817e4Smiod #include "bfd.h"
25*3d8817e4Smiod #include "sysdep.h"
26*3d8817e4Smiod #include "libiberty.h"
27*3d8817e4Smiod #include "libbfd.h"
28*3d8817e4Smiod #include "bfdlink.h"
29*3d8817e4Smiod #include "coff/sh.h"
30*3d8817e4Smiod #include "coff/internal.h"
31*3d8817e4Smiod
32*3d8817e4Smiod #ifdef COFF_WITH_PE
33*3d8817e4Smiod #include "coff/pe.h"
34*3d8817e4Smiod
35*3d8817e4Smiod #ifndef COFF_IMAGE_WITH_PE
36*3d8817e4Smiod static bfd_boolean sh_align_load_span
37*3d8817e4Smiod PARAMS ((bfd *, asection *, bfd_byte *,
38*3d8817e4Smiod bfd_boolean (*) (bfd *, asection *, PTR, bfd_byte *, bfd_vma),
39*3d8817e4Smiod PTR, bfd_vma **, bfd_vma *, bfd_vma, bfd_vma, bfd_boolean *));
40*3d8817e4Smiod
41*3d8817e4Smiod #define _bfd_sh_align_load_span sh_align_load_span
42*3d8817e4Smiod #endif
43*3d8817e4Smiod #endif
44*3d8817e4Smiod
45*3d8817e4Smiod #include "libcoff.h"
46*3d8817e4Smiod
47*3d8817e4Smiod /* Internal functions. */
48*3d8817e4Smiod static bfd_reloc_status_type sh_reloc
49*3d8817e4Smiod PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
50*3d8817e4Smiod static long get_symbol_value PARAMS ((asymbol *));
51*3d8817e4Smiod static bfd_boolean sh_relax_section
52*3d8817e4Smiod PARAMS ((bfd *, asection *, struct bfd_link_info *, bfd_boolean *));
53*3d8817e4Smiod static bfd_boolean sh_relax_delete_bytes
54*3d8817e4Smiod PARAMS ((bfd *, asection *, bfd_vma, int));
55*3d8817e4Smiod #ifndef COFF_IMAGE_WITH_PE
56*3d8817e4Smiod static const struct sh_opcode *sh_insn_info PARAMS ((unsigned int));
57*3d8817e4Smiod #endif
58*3d8817e4Smiod static bfd_boolean sh_align_loads
59*3d8817e4Smiod PARAMS ((bfd *, asection *, struct internal_reloc *, bfd_byte *,
60*3d8817e4Smiod bfd_boolean *));
61*3d8817e4Smiod static bfd_boolean sh_swap_insns
62*3d8817e4Smiod PARAMS ((bfd *, asection *, PTR, bfd_byte *, bfd_vma));
63*3d8817e4Smiod static bfd_boolean sh_relocate_section
64*3d8817e4Smiod PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
65*3d8817e4Smiod struct internal_reloc *, struct internal_syment *, asection **));
66*3d8817e4Smiod static bfd_byte *sh_coff_get_relocated_section_contents
67*3d8817e4Smiod PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
68*3d8817e4Smiod bfd_byte *, bfd_boolean, asymbol **));
69*3d8817e4Smiod static reloc_howto_type * sh_coff_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type));
70*3d8817e4Smiod
71*3d8817e4Smiod #ifdef COFF_WITH_PE
72*3d8817e4Smiod /* Can't build import tables with 2**4 alignment. */
73*3d8817e4Smiod #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 2
74*3d8817e4Smiod #else
75*3d8817e4Smiod /* Default section alignment to 2**4. */
76*3d8817e4Smiod #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 4
77*3d8817e4Smiod #endif
78*3d8817e4Smiod
79*3d8817e4Smiod #ifdef COFF_IMAGE_WITH_PE
80*3d8817e4Smiod /* Align PE executables. */
81*3d8817e4Smiod #define COFF_PAGE_SIZE 0x1000
82*3d8817e4Smiod #endif
83*3d8817e4Smiod
84*3d8817e4Smiod /* Generate long file names. */
85*3d8817e4Smiod #define COFF_LONG_FILENAMES
86*3d8817e4Smiod
87*3d8817e4Smiod #ifdef COFF_WITH_PE
88*3d8817e4Smiod static bfd_boolean in_reloc_p PARAMS ((bfd *, reloc_howto_type *));
89*3d8817e4Smiod /* Return TRUE if this relocation should
90*3d8817e4Smiod appear in the output .reloc section. */
in_reloc_p(abfd,howto)91*3d8817e4Smiod static bfd_boolean in_reloc_p (abfd, howto)
92*3d8817e4Smiod bfd * abfd ATTRIBUTE_UNUSED;
93*3d8817e4Smiod reloc_howto_type * howto;
94*3d8817e4Smiod {
95*3d8817e4Smiod return ! howto->pc_relative && howto->type != R_SH_IMAGEBASE;
96*3d8817e4Smiod }
97*3d8817e4Smiod #endif
98*3d8817e4Smiod
99*3d8817e4Smiod /* The supported relocations. There are a lot of relocations defined
100*3d8817e4Smiod in coff/internal.h which we do not expect to ever see. */
101*3d8817e4Smiod static reloc_howto_type sh_coff_howtos[] =
102*3d8817e4Smiod {
103*3d8817e4Smiod EMPTY_HOWTO (0),
104*3d8817e4Smiod EMPTY_HOWTO (1),
105*3d8817e4Smiod #ifdef COFF_WITH_PE
106*3d8817e4Smiod /* Windows CE */
107*3d8817e4Smiod HOWTO (R_SH_IMM32CE, /* type */
108*3d8817e4Smiod 0, /* rightshift */
109*3d8817e4Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
110*3d8817e4Smiod 32, /* bitsize */
111*3d8817e4Smiod FALSE, /* pc_relative */
112*3d8817e4Smiod 0, /* bitpos */
113*3d8817e4Smiod complain_overflow_bitfield, /* complain_on_overflow */
114*3d8817e4Smiod sh_reloc, /* special_function */
115*3d8817e4Smiod "r_imm32ce", /* name */
116*3d8817e4Smiod TRUE, /* partial_inplace */
117*3d8817e4Smiod 0xffffffff, /* src_mask */
118*3d8817e4Smiod 0xffffffff, /* dst_mask */
119*3d8817e4Smiod FALSE), /* pcrel_offset */
120*3d8817e4Smiod #else
121*3d8817e4Smiod EMPTY_HOWTO (2),
122*3d8817e4Smiod #endif
123*3d8817e4Smiod EMPTY_HOWTO (3), /* R_SH_PCREL8 */
124*3d8817e4Smiod EMPTY_HOWTO (4), /* R_SH_PCREL16 */
125*3d8817e4Smiod EMPTY_HOWTO (5), /* R_SH_HIGH8 */
126*3d8817e4Smiod EMPTY_HOWTO (6), /* R_SH_IMM24 */
127*3d8817e4Smiod EMPTY_HOWTO (7), /* R_SH_LOW16 */
128*3d8817e4Smiod EMPTY_HOWTO (8),
129*3d8817e4Smiod EMPTY_HOWTO (9), /* R_SH_PCDISP8BY4 */
130*3d8817e4Smiod
131*3d8817e4Smiod HOWTO (R_SH_PCDISP8BY2, /* type */
132*3d8817e4Smiod 1, /* rightshift */
133*3d8817e4Smiod 1, /* size (0 = byte, 1 = short, 2 = long) */
134*3d8817e4Smiod 8, /* bitsize */
135*3d8817e4Smiod TRUE, /* pc_relative */
136*3d8817e4Smiod 0, /* bitpos */
137*3d8817e4Smiod complain_overflow_signed, /* complain_on_overflow */
138*3d8817e4Smiod sh_reloc, /* special_function */
139*3d8817e4Smiod "r_pcdisp8by2", /* name */
140*3d8817e4Smiod TRUE, /* partial_inplace */
141*3d8817e4Smiod 0xff, /* src_mask */
142*3d8817e4Smiod 0xff, /* dst_mask */
143*3d8817e4Smiod TRUE), /* pcrel_offset */
144*3d8817e4Smiod
145*3d8817e4Smiod EMPTY_HOWTO (11), /* R_SH_PCDISP8 */
146*3d8817e4Smiod
147*3d8817e4Smiod HOWTO (R_SH_PCDISP, /* type */
148*3d8817e4Smiod 1, /* rightshift */
149*3d8817e4Smiod 1, /* size (0 = byte, 1 = short, 2 = long) */
150*3d8817e4Smiod 12, /* bitsize */
151*3d8817e4Smiod TRUE, /* pc_relative */
152*3d8817e4Smiod 0, /* bitpos */
153*3d8817e4Smiod complain_overflow_signed, /* complain_on_overflow */
154*3d8817e4Smiod sh_reloc, /* special_function */
155*3d8817e4Smiod "r_pcdisp12by2", /* name */
156*3d8817e4Smiod TRUE, /* partial_inplace */
157*3d8817e4Smiod 0xfff, /* src_mask */
158*3d8817e4Smiod 0xfff, /* dst_mask */
159*3d8817e4Smiod TRUE), /* pcrel_offset */
160*3d8817e4Smiod
161*3d8817e4Smiod EMPTY_HOWTO (13),
162*3d8817e4Smiod
163*3d8817e4Smiod HOWTO (R_SH_IMM32, /* type */
164*3d8817e4Smiod 0, /* rightshift */
165*3d8817e4Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
166*3d8817e4Smiod 32, /* bitsize */
167*3d8817e4Smiod FALSE, /* pc_relative */
168*3d8817e4Smiod 0, /* bitpos */
169*3d8817e4Smiod complain_overflow_bitfield, /* complain_on_overflow */
170*3d8817e4Smiod sh_reloc, /* special_function */
171*3d8817e4Smiod "r_imm32", /* name */
172*3d8817e4Smiod TRUE, /* partial_inplace */
173*3d8817e4Smiod 0xffffffff, /* src_mask */
174*3d8817e4Smiod 0xffffffff, /* dst_mask */
175*3d8817e4Smiod FALSE), /* pcrel_offset */
176*3d8817e4Smiod
177*3d8817e4Smiod EMPTY_HOWTO (15),
178*3d8817e4Smiod #ifdef COFF_WITH_PE
179*3d8817e4Smiod HOWTO (R_SH_IMAGEBASE, /* type */
180*3d8817e4Smiod 0, /* rightshift */
181*3d8817e4Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
182*3d8817e4Smiod 32, /* bitsize */
183*3d8817e4Smiod FALSE, /* pc_relative */
184*3d8817e4Smiod 0, /* bitpos */
185*3d8817e4Smiod complain_overflow_bitfield, /* complain_on_overflow */
186*3d8817e4Smiod sh_reloc, /* special_function */
187*3d8817e4Smiod "rva32", /* name */
188*3d8817e4Smiod TRUE, /* partial_inplace */
189*3d8817e4Smiod 0xffffffff, /* src_mask */
190*3d8817e4Smiod 0xffffffff, /* dst_mask */
191*3d8817e4Smiod FALSE), /* pcrel_offset */
192*3d8817e4Smiod #else
193*3d8817e4Smiod EMPTY_HOWTO (16), /* R_SH_IMM8 */
194*3d8817e4Smiod #endif
195*3d8817e4Smiod EMPTY_HOWTO (17), /* R_SH_IMM8BY2 */
196*3d8817e4Smiod EMPTY_HOWTO (18), /* R_SH_IMM8BY4 */
197*3d8817e4Smiod EMPTY_HOWTO (19), /* R_SH_IMM4 */
198*3d8817e4Smiod EMPTY_HOWTO (20), /* R_SH_IMM4BY2 */
199*3d8817e4Smiod EMPTY_HOWTO (21), /* R_SH_IMM4BY4 */
200*3d8817e4Smiod
201*3d8817e4Smiod HOWTO (R_SH_PCRELIMM8BY2, /* type */
202*3d8817e4Smiod 1, /* rightshift */
203*3d8817e4Smiod 1, /* size (0 = byte, 1 = short, 2 = long) */
204*3d8817e4Smiod 8, /* bitsize */
205*3d8817e4Smiod TRUE, /* pc_relative */
206*3d8817e4Smiod 0, /* bitpos */
207*3d8817e4Smiod complain_overflow_unsigned, /* complain_on_overflow */
208*3d8817e4Smiod sh_reloc, /* special_function */
209*3d8817e4Smiod "r_pcrelimm8by2", /* name */
210*3d8817e4Smiod TRUE, /* partial_inplace */
211*3d8817e4Smiod 0xff, /* src_mask */
212*3d8817e4Smiod 0xff, /* dst_mask */
213*3d8817e4Smiod TRUE), /* pcrel_offset */
214*3d8817e4Smiod
215*3d8817e4Smiod HOWTO (R_SH_PCRELIMM8BY4, /* type */
216*3d8817e4Smiod 2, /* rightshift */
217*3d8817e4Smiod 1, /* size (0 = byte, 1 = short, 2 = long) */
218*3d8817e4Smiod 8, /* bitsize */
219*3d8817e4Smiod TRUE, /* pc_relative */
220*3d8817e4Smiod 0, /* bitpos */
221*3d8817e4Smiod complain_overflow_unsigned, /* complain_on_overflow */
222*3d8817e4Smiod sh_reloc, /* special_function */
223*3d8817e4Smiod "r_pcrelimm8by4", /* name */
224*3d8817e4Smiod TRUE, /* partial_inplace */
225*3d8817e4Smiod 0xff, /* src_mask */
226*3d8817e4Smiod 0xff, /* dst_mask */
227*3d8817e4Smiod TRUE), /* pcrel_offset */
228*3d8817e4Smiod
229*3d8817e4Smiod HOWTO (R_SH_IMM16, /* type */
230*3d8817e4Smiod 0, /* rightshift */
231*3d8817e4Smiod 1, /* size (0 = byte, 1 = short, 2 = long) */
232*3d8817e4Smiod 16, /* bitsize */
233*3d8817e4Smiod FALSE, /* pc_relative */
234*3d8817e4Smiod 0, /* bitpos */
235*3d8817e4Smiod complain_overflow_bitfield, /* complain_on_overflow */
236*3d8817e4Smiod sh_reloc, /* special_function */
237*3d8817e4Smiod "r_imm16", /* name */
238*3d8817e4Smiod TRUE, /* partial_inplace */
239*3d8817e4Smiod 0xffff, /* src_mask */
240*3d8817e4Smiod 0xffff, /* dst_mask */
241*3d8817e4Smiod FALSE), /* pcrel_offset */
242*3d8817e4Smiod
243*3d8817e4Smiod HOWTO (R_SH_SWITCH16, /* type */
244*3d8817e4Smiod 0, /* rightshift */
245*3d8817e4Smiod 1, /* size (0 = byte, 1 = short, 2 = long) */
246*3d8817e4Smiod 16, /* bitsize */
247*3d8817e4Smiod FALSE, /* pc_relative */
248*3d8817e4Smiod 0, /* bitpos */
249*3d8817e4Smiod complain_overflow_bitfield, /* complain_on_overflow */
250*3d8817e4Smiod sh_reloc, /* special_function */
251*3d8817e4Smiod "r_switch16", /* name */
252*3d8817e4Smiod TRUE, /* partial_inplace */
253*3d8817e4Smiod 0xffff, /* src_mask */
254*3d8817e4Smiod 0xffff, /* dst_mask */
255*3d8817e4Smiod FALSE), /* pcrel_offset */
256*3d8817e4Smiod
257*3d8817e4Smiod HOWTO (R_SH_SWITCH32, /* type */
258*3d8817e4Smiod 0, /* rightshift */
259*3d8817e4Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
260*3d8817e4Smiod 32, /* bitsize */
261*3d8817e4Smiod FALSE, /* pc_relative */
262*3d8817e4Smiod 0, /* bitpos */
263*3d8817e4Smiod complain_overflow_bitfield, /* complain_on_overflow */
264*3d8817e4Smiod sh_reloc, /* special_function */
265*3d8817e4Smiod "r_switch32", /* name */
266*3d8817e4Smiod TRUE, /* partial_inplace */
267*3d8817e4Smiod 0xffffffff, /* src_mask */
268*3d8817e4Smiod 0xffffffff, /* dst_mask */
269*3d8817e4Smiod FALSE), /* pcrel_offset */
270*3d8817e4Smiod
271*3d8817e4Smiod HOWTO (R_SH_USES, /* type */
272*3d8817e4Smiod 0, /* rightshift */
273*3d8817e4Smiod 1, /* size (0 = byte, 1 = short, 2 = long) */
274*3d8817e4Smiod 16, /* bitsize */
275*3d8817e4Smiod FALSE, /* pc_relative */
276*3d8817e4Smiod 0, /* bitpos */
277*3d8817e4Smiod complain_overflow_bitfield, /* complain_on_overflow */
278*3d8817e4Smiod sh_reloc, /* special_function */
279*3d8817e4Smiod "r_uses", /* name */
280*3d8817e4Smiod TRUE, /* partial_inplace */
281*3d8817e4Smiod 0xffff, /* src_mask */
282*3d8817e4Smiod 0xffff, /* dst_mask */
283*3d8817e4Smiod FALSE), /* pcrel_offset */
284*3d8817e4Smiod
285*3d8817e4Smiod HOWTO (R_SH_COUNT, /* type */
286*3d8817e4Smiod 0, /* rightshift */
287*3d8817e4Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
288*3d8817e4Smiod 32, /* bitsize */
289*3d8817e4Smiod FALSE, /* pc_relative */
290*3d8817e4Smiod 0, /* bitpos */
291*3d8817e4Smiod complain_overflow_bitfield, /* complain_on_overflow */
292*3d8817e4Smiod sh_reloc, /* special_function */
293*3d8817e4Smiod "r_count", /* name */
294*3d8817e4Smiod TRUE, /* partial_inplace */
295*3d8817e4Smiod 0xffffffff, /* src_mask */
296*3d8817e4Smiod 0xffffffff, /* dst_mask */
297*3d8817e4Smiod FALSE), /* pcrel_offset */
298*3d8817e4Smiod
299*3d8817e4Smiod HOWTO (R_SH_ALIGN, /* type */
300*3d8817e4Smiod 0, /* rightshift */
301*3d8817e4Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
302*3d8817e4Smiod 32, /* bitsize */
303*3d8817e4Smiod FALSE, /* pc_relative */
304*3d8817e4Smiod 0, /* bitpos */
305*3d8817e4Smiod complain_overflow_bitfield, /* complain_on_overflow */
306*3d8817e4Smiod sh_reloc, /* special_function */
307*3d8817e4Smiod "r_align", /* name */
308*3d8817e4Smiod TRUE, /* partial_inplace */
309*3d8817e4Smiod 0xffffffff, /* src_mask */
310*3d8817e4Smiod 0xffffffff, /* dst_mask */
311*3d8817e4Smiod FALSE), /* pcrel_offset */
312*3d8817e4Smiod
313*3d8817e4Smiod HOWTO (R_SH_CODE, /* type */
314*3d8817e4Smiod 0, /* rightshift */
315*3d8817e4Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
316*3d8817e4Smiod 32, /* bitsize */
317*3d8817e4Smiod FALSE, /* pc_relative */
318*3d8817e4Smiod 0, /* bitpos */
319*3d8817e4Smiod complain_overflow_bitfield, /* complain_on_overflow */
320*3d8817e4Smiod sh_reloc, /* special_function */
321*3d8817e4Smiod "r_code", /* name */
322*3d8817e4Smiod TRUE, /* partial_inplace */
323*3d8817e4Smiod 0xffffffff, /* src_mask */
324*3d8817e4Smiod 0xffffffff, /* dst_mask */
325*3d8817e4Smiod FALSE), /* pcrel_offset */
326*3d8817e4Smiod
327*3d8817e4Smiod HOWTO (R_SH_DATA, /* type */
328*3d8817e4Smiod 0, /* rightshift */
329*3d8817e4Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
330*3d8817e4Smiod 32, /* bitsize */
331*3d8817e4Smiod FALSE, /* pc_relative */
332*3d8817e4Smiod 0, /* bitpos */
333*3d8817e4Smiod complain_overflow_bitfield, /* complain_on_overflow */
334*3d8817e4Smiod sh_reloc, /* special_function */
335*3d8817e4Smiod "r_data", /* name */
336*3d8817e4Smiod TRUE, /* partial_inplace */
337*3d8817e4Smiod 0xffffffff, /* src_mask */
338*3d8817e4Smiod 0xffffffff, /* dst_mask */
339*3d8817e4Smiod FALSE), /* pcrel_offset */
340*3d8817e4Smiod
341*3d8817e4Smiod HOWTO (R_SH_LABEL, /* type */
342*3d8817e4Smiod 0, /* rightshift */
343*3d8817e4Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
344*3d8817e4Smiod 32, /* bitsize */
345*3d8817e4Smiod FALSE, /* pc_relative */
346*3d8817e4Smiod 0, /* bitpos */
347*3d8817e4Smiod complain_overflow_bitfield, /* complain_on_overflow */
348*3d8817e4Smiod sh_reloc, /* special_function */
349*3d8817e4Smiod "r_label", /* name */
350*3d8817e4Smiod TRUE, /* partial_inplace */
351*3d8817e4Smiod 0xffffffff, /* src_mask */
352*3d8817e4Smiod 0xffffffff, /* dst_mask */
353*3d8817e4Smiod FALSE), /* pcrel_offset */
354*3d8817e4Smiod
355*3d8817e4Smiod HOWTO (R_SH_SWITCH8, /* type */
356*3d8817e4Smiod 0, /* rightshift */
357*3d8817e4Smiod 0, /* size (0 = byte, 1 = short, 2 = long) */
358*3d8817e4Smiod 8, /* bitsize */
359*3d8817e4Smiod FALSE, /* pc_relative */
360*3d8817e4Smiod 0, /* bitpos */
361*3d8817e4Smiod complain_overflow_bitfield, /* complain_on_overflow */
362*3d8817e4Smiod sh_reloc, /* special_function */
363*3d8817e4Smiod "r_switch8", /* name */
364*3d8817e4Smiod TRUE, /* partial_inplace */
365*3d8817e4Smiod 0xff, /* src_mask */
366*3d8817e4Smiod 0xff, /* dst_mask */
367*3d8817e4Smiod FALSE) /* pcrel_offset */
368*3d8817e4Smiod };
369*3d8817e4Smiod
370*3d8817e4Smiod #define SH_COFF_HOWTO_COUNT (sizeof sh_coff_howtos / sizeof sh_coff_howtos[0])
371*3d8817e4Smiod
372*3d8817e4Smiod /* Check for a bad magic number. */
373*3d8817e4Smiod #define BADMAG(x) SHBADMAG(x)
374*3d8817e4Smiod
375*3d8817e4Smiod /* Customize coffcode.h (this is not currently used). */
376*3d8817e4Smiod #define SH 1
377*3d8817e4Smiod
378*3d8817e4Smiod /* FIXME: This should not be set here. */
379*3d8817e4Smiod #define __A_MAGIC_SET__
380*3d8817e4Smiod
381*3d8817e4Smiod #ifndef COFF_WITH_PE
382*3d8817e4Smiod /* Swap the r_offset field in and out. */
383*3d8817e4Smiod #define SWAP_IN_RELOC_OFFSET H_GET_32
384*3d8817e4Smiod #define SWAP_OUT_RELOC_OFFSET H_PUT_32
385*3d8817e4Smiod
386*3d8817e4Smiod /* Swap out extra information in the reloc structure. */
387*3d8817e4Smiod #define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
388*3d8817e4Smiod do \
389*3d8817e4Smiod { \
390*3d8817e4Smiod dst->r_stuff[0] = 'S'; \
391*3d8817e4Smiod dst->r_stuff[1] = 'C'; \
392*3d8817e4Smiod } \
393*3d8817e4Smiod while (0)
394*3d8817e4Smiod #endif
395*3d8817e4Smiod
396*3d8817e4Smiod /* Get the value of a symbol, when performing a relocation. */
397*3d8817e4Smiod
398*3d8817e4Smiod static long
get_symbol_value(symbol)399*3d8817e4Smiod get_symbol_value (symbol)
400*3d8817e4Smiod asymbol *symbol;
401*3d8817e4Smiod {
402*3d8817e4Smiod bfd_vma relocation;
403*3d8817e4Smiod
404*3d8817e4Smiod if (bfd_is_com_section (symbol->section))
405*3d8817e4Smiod relocation = 0;
406*3d8817e4Smiod else
407*3d8817e4Smiod relocation = (symbol->value +
408*3d8817e4Smiod symbol->section->output_section->vma +
409*3d8817e4Smiod symbol->section->output_offset);
410*3d8817e4Smiod
411*3d8817e4Smiod return relocation;
412*3d8817e4Smiod }
413*3d8817e4Smiod
414*3d8817e4Smiod #ifdef COFF_WITH_PE
415*3d8817e4Smiod /* Convert an rtype to howto for the COFF backend linker.
416*3d8817e4Smiod Copied from coff-i386. */
417*3d8817e4Smiod #define coff_rtype_to_howto coff_sh_rtype_to_howto
418*3d8817e4Smiod static reloc_howto_type * coff_sh_rtype_to_howto PARAMS ((bfd *, asection *, struct internal_reloc *, struct coff_link_hash_entry *, struct internal_syment *, bfd_vma *));
419*3d8817e4Smiod
420*3d8817e4Smiod static reloc_howto_type *
coff_sh_rtype_to_howto(abfd,sec,rel,h,sym,addendp)421*3d8817e4Smiod coff_sh_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
422*3d8817e4Smiod bfd * abfd ATTRIBUTE_UNUSED;
423*3d8817e4Smiod asection * sec;
424*3d8817e4Smiod struct internal_reloc * rel;
425*3d8817e4Smiod struct coff_link_hash_entry * h;
426*3d8817e4Smiod struct internal_syment * sym;
427*3d8817e4Smiod bfd_vma * addendp;
428*3d8817e4Smiod {
429*3d8817e4Smiod reloc_howto_type * howto;
430*3d8817e4Smiod
431*3d8817e4Smiod howto = sh_coff_howtos + rel->r_type;
432*3d8817e4Smiod
433*3d8817e4Smiod *addendp = 0;
434*3d8817e4Smiod
435*3d8817e4Smiod if (howto->pc_relative)
436*3d8817e4Smiod *addendp += sec->vma;
437*3d8817e4Smiod
438*3d8817e4Smiod if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
439*3d8817e4Smiod {
440*3d8817e4Smiod /* This is a common symbol. The section contents include the
441*3d8817e4Smiod size (sym->n_value) as an addend. The relocate_section
442*3d8817e4Smiod function will be adding in the final value of the symbol. We
443*3d8817e4Smiod need to subtract out the current size in order to get the
444*3d8817e4Smiod correct result. */
445*3d8817e4Smiod BFD_ASSERT (h != NULL);
446*3d8817e4Smiod }
447*3d8817e4Smiod
448*3d8817e4Smiod if (howto->pc_relative)
449*3d8817e4Smiod {
450*3d8817e4Smiod *addendp -= 4;
451*3d8817e4Smiod
452*3d8817e4Smiod /* If the symbol is defined, then the generic code is going to
453*3d8817e4Smiod add back the symbol value in order to cancel out an
454*3d8817e4Smiod adjustment it made to the addend. However, we set the addend
455*3d8817e4Smiod to 0 at the start of this function. We need to adjust here,
456*3d8817e4Smiod to avoid the adjustment the generic code will make. FIXME:
457*3d8817e4Smiod This is getting a bit hackish. */
458*3d8817e4Smiod if (sym != NULL && sym->n_scnum != 0)
459*3d8817e4Smiod *addendp -= sym->n_value;
460*3d8817e4Smiod }
461*3d8817e4Smiod
462*3d8817e4Smiod if (rel->r_type == R_SH_IMAGEBASE)
463*3d8817e4Smiod *addendp -= pe_data (sec->output_section->owner)->pe_opthdr.ImageBase;
464*3d8817e4Smiod
465*3d8817e4Smiod return howto;
466*3d8817e4Smiod }
467*3d8817e4Smiod
468*3d8817e4Smiod #endif /* COFF_WITH_PE */
469*3d8817e4Smiod
470*3d8817e4Smiod /* This structure is used to map BFD reloc codes to SH PE relocs. */
471*3d8817e4Smiod struct shcoff_reloc_map
472*3d8817e4Smiod {
473*3d8817e4Smiod bfd_reloc_code_real_type bfd_reloc_val;
474*3d8817e4Smiod unsigned char shcoff_reloc_val;
475*3d8817e4Smiod };
476*3d8817e4Smiod
477*3d8817e4Smiod #ifdef COFF_WITH_PE
478*3d8817e4Smiod /* An array mapping BFD reloc codes to SH PE relocs. */
479*3d8817e4Smiod static const struct shcoff_reloc_map sh_reloc_map[] =
480*3d8817e4Smiod {
481*3d8817e4Smiod { BFD_RELOC_32, R_SH_IMM32CE },
482*3d8817e4Smiod { BFD_RELOC_RVA, R_SH_IMAGEBASE },
483*3d8817e4Smiod { BFD_RELOC_CTOR, R_SH_IMM32CE },
484*3d8817e4Smiod };
485*3d8817e4Smiod #else
486*3d8817e4Smiod /* An array mapping BFD reloc codes to SH PE relocs. */
487*3d8817e4Smiod static const struct shcoff_reloc_map sh_reloc_map[] =
488*3d8817e4Smiod {
489*3d8817e4Smiod { BFD_RELOC_32, R_SH_IMM32 },
490*3d8817e4Smiod { BFD_RELOC_CTOR, R_SH_IMM32 },
491*3d8817e4Smiod };
492*3d8817e4Smiod #endif
493*3d8817e4Smiod
494*3d8817e4Smiod /* Given a BFD reloc code, return the howto structure for the
495*3d8817e4Smiod corresponding SH PE reloc. */
496*3d8817e4Smiod #define coff_bfd_reloc_type_lookup sh_coff_reloc_type_lookup
497*3d8817e4Smiod
498*3d8817e4Smiod static reloc_howto_type *
sh_coff_reloc_type_lookup(abfd,code)499*3d8817e4Smiod sh_coff_reloc_type_lookup (abfd, code)
500*3d8817e4Smiod bfd * abfd ATTRIBUTE_UNUSED;
501*3d8817e4Smiod bfd_reloc_code_real_type code;
502*3d8817e4Smiod {
503*3d8817e4Smiod unsigned int i;
504*3d8817e4Smiod
505*3d8817e4Smiod for (i = ARRAY_SIZE (sh_reloc_map); i--;)
506*3d8817e4Smiod if (sh_reloc_map[i].bfd_reloc_val == code)
507*3d8817e4Smiod return &sh_coff_howtos[(int) sh_reloc_map[i].shcoff_reloc_val];
508*3d8817e4Smiod
509*3d8817e4Smiod fprintf (stderr, "SH Error: unknown reloc type %d\n", code);
510*3d8817e4Smiod return NULL;
511*3d8817e4Smiod }
512*3d8817e4Smiod
513*3d8817e4Smiod /* This macro is used in coffcode.h to get the howto corresponding to
514*3d8817e4Smiod an internal reloc. */
515*3d8817e4Smiod
516*3d8817e4Smiod #define RTYPE2HOWTO(relent, internal) \
517*3d8817e4Smiod ((relent)->howto = \
518*3d8817e4Smiod ((internal)->r_type < SH_COFF_HOWTO_COUNT \
519*3d8817e4Smiod ? &sh_coff_howtos[(internal)->r_type] \
520*3d8817e4Smiod : (reloc_howto_type *) NULL))
521*3d8817e4Smiod
522*3d8817e4Smiod /* This is the same as the macro in coffcode.h, except that it copies
523*3d8817e4Smiod r_offset into reloc_entry->addend for some relocs. */
524*3d8817e4Smiod #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
525*3d8817e4Smiod { \
526*3d8817e4Smiod coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
527*3d8817e4Smiod if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
528*3d8817e4Smiod coffsym = (obj_symbols (abfd) \
529*3d8817e4Smiod + (cache_ptr->sym_ptr_ptr - symbols)); \
530*3d8817e4Smiod else if (ptr) \
531*3d8817e4Smiod coffsym = coff_symbol_from (abfd, ptr); \
532*3d8817e4Smiod if (coffsym != (coff_symbol_type *) NULL \
533*3d8817e4Smiod && coffsym->native->u.syment.n_scnum == 0) \
534*3d8817e4Smiod cache_ptr->addend = 0; \
535*3d8817e4Smiod else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
536*3d8817e4Smiod && ptr->section != (asection *) NULL) \
537*3d8817e4Smiod cache_ptr->addend = - (ptr->section->vma + ptr->value); \
538*3d8817e4Smiod else \
539*3d8817e4Smiod cache_ptr->addend = 0; \
540*3d8817e4Smiod if ((reloc).r_type == R_SH_SWITCH8 \
541*3d8817e4Smiod || (reloc).r_type == R_SH_SWITCH16 \
542*3d8817e4Smiod || (reloc).r_type == R_SH_SWITCH32 \
543*3d8817e4Smiod || (reloc).r_type == R_SH_USES \
544*3d8817e4Smiod || (reloc).r_type == R_SH_COUNT \
545*3d8817e4Smiod || (reloc).r_type == R_SH_ALIGN) \
546*3d8817e4Smiod cache_ptr->addend = (reloc).r_offset; \
547*3d8817e4Smiod }
548*3d8817e4Smiod
549*3d8817e4Smiod /* This is the howto function for the SH relocations. */
550*3d8817e4Smiod
551*3d8817e4Smiod static bfd_reloc_status_type
sh_reloc(abfd,reloc_entry,symbol_in,data,input_section,output_bfd,error_message)552*3d8817e4Smiod sh_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
553*3d8817e4Smiod error_message)
554*3d8817e4Smiod bfd *abfd;
555*3d8817e4Smiod arelent *reloc_entry;
556*3d8817e4Smiod asymbol *symbol_in;
557*3d8817e4Smiod PTR data;
558*3d8817e4Smiod asection *input_section;
559*3d8817e4Smiod bfd *output_bfd;
560*3d8817e4Smiod char **error_message ATTRIBUTE_UNUSED;
561*3d8817e4Smiod {
562*3d8817e4Smiod unsigned long insn;
563*3d8817e4Smiod bfd_vma sym_value;
564*3d8817e4Smiod unsigned short r_type;
565*3d8817e4Smiod bfd_vma addr = reloc_entry->address;
566*3d8817e4Smiod bfd_byte *hit_data = addr + (bfd_byte *) data;
567*3d8817e4Smiod
568*3d8817e4Smiod r_type = reloc_entry->howto->type;
569*3d8817e4Smiod
570*3d8817e4Smiod if (output_bfd != NULL)
571*3d8817e4Smiod {
572*3d8817e4Smiod /* Partial linking--do nothing. */
573*3d8817e4Smiod reloc_entry->address += input_section->output_offset;
574*3d8817e4Smiod return bfd_reloc_ok;
575*3d8817e4Smiod }
576*3d8817e4Smiod
577*3d8817e4Smiod /* Almost all relocs have to do with relaxing. If any work must be
578*3d8817e4Smiod done for them, it has been done in sh_relax_section. */
579*3d8817e4Smiod if (r_type != R_SH_IMM32
580*3d8817e4Smiod #ifdef COFF_WITH_PE
581*3d8817e4Smiod && r_type != R_SH_IMM32CE
582*3d8817e4Smiod && r_type != R_SH_IMAGEBASE
583*3d8817e4Smiod #endif
584*3d8817e4Smiod && (r_type != R_SH_PCDISP
585*3d8817e4Smiod || (symbol_in->flags & BSF_LOCAL) != 0))
586*3d8817e4Smiod return bfd_reloc_ok;
587*3d8817e4Smiod
588*3d8817e4Smiod if (symbol_in != NULL
589*3d8817e4Smiod && bfd_is_und_section (symbol_in->section))
590*3d8817e4Smiod return bfd_reloc_undefined;
591*3d8817e4Smiod
592*3d8817e4Smiod sym_value = get_symbol_value (symbol_in);
593*3d8817e4Smiod
594*3d8817e4Smiod switch (r_type)
595*3d8817e4Smiod {
596*3d8817e4Smiod case R_SH_IMM32:
597*3d8817e4Smiod #ifdef COFF_WITH_PE
598*3d8817e4Smiod case R_SH_IMM32CE:
599*3d8817e4Smiod #endif
600*3d8817e4Smiod insn = bfd_get_32 (abfd, hit_data);
601*3d8817e4Smiod insn += sym_value + reloc_entry->addend;
602*3d8817e4Smiod bfd_put_32 (abfd, (bfd_vma) insn, hit_data);
603*3d8817e4Smiod break;
604*3d8817e4Smiod #ifdef COFF_WITH_PE
605*3d8817e4Smiod case R_SH_IMAGEBASE:
606*3d8817e4Smiod insn = bfd_get_32 (abfd, hit_data);
607*3d8817e4Smiod insn += sym_value + reloc_entry->addend;
608*3d8817e4Smiod insn -= pe_data (input_section->output_section->owner)->pe_opthdr.ImageBase;
609*3d8817e4Smiod bfd_put_32 (abfd, (bfd_vma) insn, hit_data);
610*3d8817e4Smiod break;
611*3d8817e4Smiod #endif
612*3d8817e4Smiod case R_SH_PCDISP:
613*3d8817e4Smiod insn = bfd_get_16 (abfd, hit_data);
614*3d8817e4Smiod sym_value += reloc_entry->addend;
615*3d8817e4Smiod sym_value -= (input_section->output_section->vma
616*3d8817e4Smiod + input_section->output_offset
617*3d8817e4Smiod + addr
618*3d8817e4Smiod + 4);
619*3d8817e4Smiod sym_value += (insn & 0xfff) << 1;
620*3d8817e4Smiod if (insn & 0x800)
621*3d8817e4Smiod sym_value -= 0x1000;
622*3d8817e4Smiod insn = (insn & 0xf000) | (sym_value & 0xfff);
623*3d8817e4Smiod bfd_put_16 (abfd, (bfd_vma) insn, hit_data);
624*3d8817e4Smiod if (sym_value < (bfd_vma) -0x1000 || sym_value >= 0x1000)
625*3d8817e4Smiod return bfd_reloc_overflow;
626*3d8817e4Smiod break;
627*3d8817e4Smiod default:
628*3d8817e4Smiod abort ();
629*3d8817e4Smiod break;
630*3d8817e4Smiod }
631*3d8817e4Smiod
632*3d8817e4Smiod return bfd_reloc_ok;
633*3d8817e4Smiod }
634*3d8817e4Smiod
635*3d8817e4Smiod #define coff_bfd_merge_private_bfd_data _bfd_generic_verify_endian_match
636*3d8817e4Smiod
637*3d8817e4Smiod /* We can do relaxing. */
638*3d8817e4Smiod #define coff_bfd_relax_section sh_relax_section
639*3d8817e4Smiod
640*3d8817e4Smiod /* We use the special COFF backend linker. */
641*3d8817e4Smiod #define coff_relocate_section sh_relocate_section
642*3d8817e4Smiod
643*3d8817e4Smiod /* When relaxing, we need to use special code to get the relocated
644*3d8817e4Smiod section contents. */
645*3d8817e4Smiod #define coff_bfd_get_relocated_section_contents \
646*3d8817e4Smiod sh_coff_get_relocated_section_contents
647*3d8817e4Smiod
648*3d8817e4Smiod #include "coffcode.h"
649*3d8817e4Smiod
650*3d8817e4Smiod /* This function handles relaxing on the SH.
651*3d8817e4Smiod
652*3d8817e4Smiod Function calls on the SH look like this:
653*3d8817e4Smiod
654*3d8817e4Smiod movl L1,r0
655*3d8817e4Smiod ...
656*3d8817e4Smiod jsr @r0
657*3d8817e4Smiod ...
658*3d8817e4Smiod L1:
659*3d8817e4Smiod .long function
660*3d8817e4Smiod
661*3d8817e4Smiod The compiler and assembler will cooperate to create R_SH_USES
662*3d8817e4Smiod relocs on the jsr instructions. The r_offset field of the
663*3d8817e4Smiod R_SH_USES reloc is the PC relative offset to the instruction which
664*3d8817e4Smiod loads the register (the r_offset field is computed as though it
665*3d8817e4Smiod were a jump instruction, so the offset value is actually from four
666*3d8817e4Smiod bytes past the instruction). The linker can use this reloc to
667*3d8817e4Smiod determine just which function is being called, and thus decide
668*3d8817e4Smiod whether it is possible to replace the jsr with a bsr.
669*3d8817e4Smiod
670*3d8817e4Smiod If multiple function calls are all based on a single register load
671*3d8817e4Smiod (i.e., the same function is called multiple times), the compiler
672*3d8817e4Smiod guarantees that each function call will have an R_SH_USES reloc.
673*3d8817e4Smiod Therefore, if the linker is able to convert each R_SH_USES reloc
674*3d8817e4Smiod which refers to that address, it can safely eliminate the register
675*3d8817e4Smiod load.
676*3d8817e4Smiod
677*3d8817e4Smiod When the assembler creates an R_SH_USES reloc, it examines it to
678*3d8817e4Smiod determine which address is being loaded (L1 in the above example).
679*3d8817e4Smiod It then counts the number of references to that address, and
680*3d8817e4Smiod creates an R_SH_COUNT reloc at that address. The r_offset field of
681*3d8817e4Smiod the R_SH_COUNT reloc will be the number of references. If the
682*3d8817e4Smiod linker is able to eliminate a register load, it can use the
683*3d8817e4Smiod R_SH_COUNT reloc to see whether it can also eliminate the function
684*3d8817e4Smiod address.
685*3d8817e4Smiod
686*3d8817e4Smiod SH relaxing also handles another, unrelated, matter. On the SH, if
687*3d8817e4Smiod a load or store instruction is not aligned on a four byte boundary,
688*3d8817e4Smiod the memory cycle interferes with the 32 bit instruction fetch,
689*3d8817e4Smiod causing a one cycle bubble in the pipeline. Therefore, we try to
690*3d8817e4Smiod align load and store instructions on four byte boundaries if we
691*3d8817e4Smiod can, by swapping them with one of the adjacent instructions. */
692*3d8817e4Smiod
693*3d8817e4Smiod static bfd_boolean
sh_relax_section(abfd,sec,link_info,again)694*3d8817e4Smiod sh_relax_section (abfd, sec, link_info, again)
695*3d8817e4Smiod bfd *abfd;
696*3d8817e4Smiod asection *sec;
697*3d8817e4Smiod struct bfd_link_info *link_info;
698*3d8817e4Smiod bfd_boolean *again;
699*3d8817e4Smiod {
700*3d8817e4Smiod struct internal_reloc *internal_relocs;
701*3d8817e4Smiod bfd_boolean have_code;
702*3d8817e4Smiod struct internal_reloc *irel, *irelend;
703*3d8817e4Smiod bfd_byte *contents = NULL;
704*3d8817e4Smiod
705*3d8817e4Smiod *again = FALSE;
706*3d8817e4Smiod
707*3d8817e4Smiod if (link_info->relocatable
708*3d8817e4Smiod || (sec->flags & SEC_RELOC) == 0
709*3d8817e4Smiod || sec->reloc_count == 0)
710*3d8817e4Smiod return TRUE;
711*3d8817e4Smiod
712*3d8817e4Smiod if (coff_section_data (abfd, sec) == NULL)
713*3d8817e4Smiod {
714*3d8817e4Smiod bfd_size_type amt = sizeof (struct coff_section_tdata);
715*3d8817e4Smiod sec->used_by_bfd = (PTR) bfd_zalloc (abfd, amt);
716*3d8817e4Smiod if (sec->used_by_bfd == NULL)
717*3d8817e4Smiod return FALSE;
718*3d8817e4Smiod }
719*3d8817e4Smiod
720*3d8817e4Smiod internal_relocs = (_bfd_coff_read_internal_relocs
721*3d8817e4Smiod (abfd, sec, link_info->keep_memory,
722*3d8817e4Smiod (bfd_byte *) NULL, FALSE,
723*3d8817e4Smiod (struct internal_reloc *) NULL));
724*3d8817e4Smiod if (internal_relocs == NULL)
725*3d8817e4Smiod goto error_return;
726*3d8817e4Smiod
727*3d8817e4Smiod have_code = FALSE;
728*3d8817e4Smiod
729*3d8817e4Smiod irelend = internal_relocs + sec->reloc_count;
730*3d8817e4Smiod for (irel = internal_relocs; irel < irelend; irel++)
731*3d8817e4Smiod {
732*3d8817e4Smiod bfd_vma laddr, paddr, symval;
733*3d8817e4Smiod unsigned short insn;
734*3d8817e4Smiod struct internal_reloc *irelfn, *irelscan, *irelcount;
735*3d8817e4Smiod struct internal_syment sym;
736*3d8817e4Smiod bfd_signed_vma foff;
737*3d8817e4Smiod
738*3d8817e4Smiod if (irel->r_type == R_SH_CODE)
739*3d8817e4Smiod have_code = TRUE;
740*3d8817e4Smiod
741*3d8817e4Smiod if (irel->r_type != R_SH_USES)
742*3d8817e4Smiod continue;
743*3d8817e4Smiod
744*3d8817e4Smiod /* Get the section contents. */
745*3d8817e4Smiod if (contents == NULL)
746*3d8817e4Smiod {
747*3d8817e4Smiod if (coff_section_data (abfd, sec)->contents != NULL)
748*3d8817e4Smiod contents = coff_section_data (abfd, sec)->contents;
749*3d8817e4Smiod else
750*3d8817e4Smiod {
751*3d8817e4Smiod if (!bfd_malloc_and_get_section (abfd, sec, &contents))
752*3d8817e4Smiod goto error_return;
753*3d8817e4Smiod }
754*3d8817e4Smiod }
755*3d8817e4Smiod
756*3d8817e4Smiod /* The r_offset field of the R_SH_USES reloc will point us to
757*3d8817e4Smiod the register load. The 4 is because the r_offset field is
758*3d8817e4Smiod computed as though it were a jump offset, which are based
759*3d8817e4Smiod from 4 bytes after the jump instruction. */
760*3d8817e4Smiod laddr = irel->r_vaddr - sec->vma + 4;
761*3d8817e4Smiod /* Careful to sign extend the 32-bit offset. */
762*3d8817e4Smiod laddr += ((irel->r_offset & 0xffffffff) ^ 0x80000000) - 0x80000000;
763*3d8817e4Smiod if (laddr >= sec->size)
764*3d8817e4Smiod {
765*3d8817e4Smiod (*_bfd_error_handler) ("%B: 0x%lx: warning: bad R_SH_USES offset",
766*3d8817e4Smiod abfd, (unsigned long) irel->r_vaddr);
767*3d8817e4Smiod continue;
768*3d8817e4Smiod }
769*3d8817e4Smiod insn = bfd_get_16 (abfd, contents + laddr);
770*3d8817e4Smiod
771*3d8817e4Smiod /* If the instruction is not mov.l NN,rN, we don't know what to do. */
772*3d8817e4Smiod if ((insn & 0xf000) != 0xd000)
773*3d8817e4Smiod {
774*3d8817e4Smiod ((*_bfd_error_handler)
775*3d8817e4Smiod ("%B: 0x%lx: warning: R_SH_USES points to unrecognized insn 0x%x",
776*3d8817e4Smiod abfd, (unsigned long) irel->r_vaddr, insn));
777*3d8817e4Smiod continue;
778*3d8817e4Smiod }
779*3d8817e4Smiod
780*3d8817e4Smiod /* Get the address from which the register is being loaded. The
781*3d8817e4Smiod displacement in the mov.l instruction is quadrupled. It is a
782*3d8817e4Smiod displacement from four bytes after the movl instruction, but,
783*3d8817e4Smiod before adding in the PC address, two least significant bits
784*3d8817e4Smiod of the PC are cleared. We assume that the section is aligned
785*3d8817e4Smiod on a four byte boundary. */
786*3d8817e4Smiod paddr = insn & 0xff;
787*3d8817e4Smiod paddr *= 4;
788*3d8817e4Smiod paddr += (laddr + 4) &~ (bfd_vma) 3;
789*3d8817e4Smiod if (paddr >= sec->size)
790*3d8817e4Smiod {
791*3d8817e4Smiod ((*_bfd_error_handler)
792*3d8817e4Smiod ("%B: 0x%lx: warning: bad R_SH_USES load offset",
793*3d8817e4Smiod abfd, (unsigned long) irel->r_vaddr));
794*3d8817e4Smiod continue;
795*3d8817e4Smiod }
796*3d8817e4Smiod
797*3d8817e4Smiod /* Get the reloc for the address from which the register is
798*3d8817e4Smiod being loaded. This reloc will tell us which function is
799*3d8817e4Smiod actually being called. */
800*3d8817e4Smiod paddr += sec->vma;
801*3d8817e4Smiod for (irelfn = internal_relocs; irelfn < irelend; irelfn++)
802*3d8817e4Smiod if (irelfn->r_vaddr == paddr
803*3d8817e4Smiod #ifdef COFF_WITH_PE
804*3d8817e4Smiod && (irelfn->r_type == R_SH_IMM32
805*3d8817e4Smiod || irelfn->r_type == R_SH_IMM32CE
806*3d8817e4Smiod || irelfn->r_type == R_SH_IMAGEBASE)
807*3d8817e4Smiod
808*3d8817e4Smiod #else
809*3d8817e4Smiod && irelfn->r_type == R_SH_IMM32
810*3d8817e4Smiod #endif
811*3d8817e4Smiod )
812*3d8817e4Smiod break;
813*3d8817e4Smiod if (irelfn >= irelend)
814*3d8817e4Smiod {
815*3d8817e4Smiod ((*_bfd_error_handler)
816*3d8817e4Smiod ("%B: 0x%lx: warning: could not find expected reloc",
817*3d8817e4Smiod abfd, (unsigned long) paddr));
818*3d8817e4Smiod continue;
819*3d8817e4Smiod }
820*3d8817e4Smiod
821*3d8817e4Smiod /* Get the value of the symbol referred to by the reloc. */
822*3d8817e4Smiod if (! _bfd_coff_get_external_symbols (abfd))
823*3d8817e4Smiod goto error_return;
824*3d8817e4Smiod bfd_coff_swap_sym_in (abfd,
825*3d8817e4Smiod ((bfd_byte *) obj_coff_external_syms (abfd)
826*3d8817e4Smiod + (irelfn->r_symndx
827*3d8817e4Smiod * bfd_coff_symesz (abfd))),
828*3d8817e4Smiod &sym);
829*3d8817e4Smiod if (sym.n_scnum != 0 && sym.n_scnum != sec->target_index)
830*3d8817e4Smiod {
831*3d8817e4Smiod ((*_bfd_error_handler)
832*3d8817e4Smiod ("%B: 0x%lx: warning: symbol in unexpected section",
833*3d8817e4Smiod abfd, (unsigned long) paddr));
834*3d8817e4Smiod continue;
835*3d8817e4Smiod }
836*3d8817e4Smiod
837*3d8817e4Smiod if (sym.n_sclass != C_EXT)
838*3d8817e4Smiod {
839*3d8817e4Smiod symval = (sym.n_value
840*3d8817e4Smiod - sec->vma
841*3d8817e4Smiod + sec->output_section->vma
842*3d8817e4Smiod + sec->output_offset);
843*3d8817e4Smiod }
844*3d8817e4Smiod else
845*3d8817e4Smiod {
846*3d8817e4Smiod struct coff_link_hash_entry *h;
847*3d8817e4Smiod
848*3d8817e4Smiod h = obj_coff_sym_hashes (abfd)[irelfn->r_symndx];
849*3d8817e4Smiod BFD_ASSERT (h != NULL);
850*3d8817e4Smiod if (h->root.type != bfd_link_hash_defined
851*3d8817e4Smiod && h->root.type != bfd_link_hash_defweak)
852*3d8817e4Smiod {
853*3d8817e4Smiod /* This appears to be a reference to an undefined
854*3d8817e4Smiod symbol. Just ignore it--it will be caught by the
855*3d8817e4Smiod regular reloc processing. */
856*3d8817e4Smiod continue;
857*3d8817e4Smiod }
858*3d8817e4Smiod
859*3d8817e4Smiod symval = (h->root.u.def.value
860*3d8817e4Smiod + h->root.u.def.section->output_section->vma
861*3d8817e4Smiod + h->root.u.def.section->output_offset);
862*3d8817e4Smiod }
863*3d8817e4Smiod
864*3d8817e4Smiod symval += bfd_get_32 (abfd, contents + paddr - sec->vma);
865*3d8817e4Smiod
866*3d8817e4Smiod /* See if this function call can be shortened. */
867*3d8817e4Smiod foff = (symval
868*3d8817e4Smiod - (irel->r_vaddr
869*3d8817e4Smiod - sec->vma
870*3d8817e4Smiod + sec->output_section->vma
871*3d8817e4Smiod + sec->output_offset
872*3d8817e4Smiod + 4));
873*3d8817e4Smiod if (foff < -0x1000 || foff >= 0x1000)
874*3d8817e4Smiod {
875*3d8817e4Smiod /* After all that work, we can't shorten this function call. */
876*3d8817e4Smiod continue;
877*3d8817e4Smiod }
878*3d8817e4Smiod
879*3d8817e4Smiod /* Shorten the function call. */
880*3d8817e4Smiod
881*3d8817e4Smiod /* For simplicity of coding, we are going to modify the section
882*3d8817e4Smiod contents, the section relocs, and the BFD symbol table. We
883*3d8817e4Smiod must tell the rest of the code not to free up this
884*3d8817e4Smiod information. It would be possible to instead create a table
885*3d8817e4Smiod of changes which have to be made, as is done in coff-mips.c;
886*3d8817e4Smiod that would be more work, but would require less memory when
887*3d8817e4Smiod the linker is run. */
888*3d8817e4Smiod
889*3d8817e4Smiod coff_section_data (abfd, sec)->relocs = internal_relocs;
890*3d8817e4Smiod coff_section_data (abfd, sec)->keep_relocs = TRUE;
891*3d8817e4Smiod
892*3d8817e4Smiod coff_section_data (abfd, sec)->contents = contents;
893*3d8817e4Smiod coff_section_data (abfd, sec)->keep_contents = TRUE;
894*3d8817e4Smiod
895*3d8817e4Smiod obj_coff_keep_syms (abfd) = TRUE;
896*3d8817e4Smiod
897*3d8817e4Smiod /* Replace the jsr with a bsr. */
898*3d8817e4Smiod
899*3d8817e4Smiod /* Change the R_SH_USES reloc into an R_SH_PCDISP reloc, and
900*3d8817e4Smiod replace the jsr with a bsr. */
901*3d8817e4Smiod irel->r_type = R_SH_PCDISP;
902*3d8817e4Smiod irel->r_symndx = irelfn->r_symndx;
903*3d8817e4Smiod if (sym.n_sclass != C_EXT)
904*3d8817e4Smiod {
905*3d8817e4Smiod /* If this needs to be changed because of future relaxing,
906*3d8817e4Smiod it will be handled here like other internal PCDISP
907*3d8817e4Smiod relocs. */
908*3d8817e4Smiod bfd_put_16 (abfd,
909*3d8817e4Smiod (bfd_vma) 0xb000 | ((foff >> 1) & 0xfff),
910*3d8817e4Smiod contents + irel->r_vaddr - sec->vma);
911*3d8817e4Smiod }
912*3d8817e4Smiod else
913*3d8817e4Smiod {
914*3d8817e4Smiod /* We can't fully resolve this yet, because the external
915*3d8817e4Smiod symbol value may be changed by future relaxing. We let
916*3d8817e4Smiod the final link phase handle it. */
917*3d8817e4Smiod bfd_put_16 (abfd, (bfd_vma) 0xb000,
918*3d8817e4Smiod contents + irel->r_vaddr - sec->vma);
919*3d8817e4Smiod }
920*3d8817e4Smiod
921*3d8817e4Smiod /* See if there is another R_SH_USES reloc referring to the same
922*3d8817e4Smiod register load. */
923*3d8817e4Smiod for (irelscan = internal_relocs; irelscan < irelend; irelscan++)
924*3d8817e4Smiod if (irelscan->r_type == R_SH_USES
925*3d8817e4Smiod && laddr == irelscan->r_vaddr - sec->vma + 4 + irelscan->r_offset)
926*3d8817e4Smiod break;
927*3d8817e4Smiod if (irelscan < irelend)
928*3d8817e4Smiod {
929*3d8817e4Smiod /* Some other function call depends upon this register load,
930*3d8817e4Smiod and we have not yet converted that function call.
931*3d8817e4Smiod Indeed, we may never be able to convert it. There is
932*3d8817e4Smiod nothing else we can do at this point. */
933*3d8817e4Smiod continue;
934*3d8817e4Smiod }
935*3d8817e4Smiod
936*3d8817e4Smiod /* Look for a R_SH_COUNT reloc on the location where the
937*3d8817e4Smiod function address is stored. Do this before deleting any
938*3d8817e4Smiod bytes, to avoid confusion about the address. */
939*3d8817e4Smiod for (irelcount = internal_relocs; irelcount < irelend; irelcount++)
940*3d8817e4Smiod if (irelcount->r_vaddr == paddr
941*3d8817e4Smiod && irelcount->r_type == R_SH_COUNT)
942*3d8817e4Smiod break;
943*3d8817e4Smiod
944*3d8817e4Smiod /* Delete the register load. */
945*3d8817e4Smiod if (! sh_relax_delete_bytes (abfd, sec, laddr, 2))
946*3d8817e4Smiod goto error_return;
947*3d8817e4Smiod
948*3d8817e4Smiod /* That will change things, so, just in case it permits some
949*3d8817e4Smiod other function call to come within range, we should relax
950*3d8817e4Smiod again. Note that this is not required, and it may be slow. */
951*3d8817e4Smiod *again = TRUE;
952*3d8817e4Smiod
953*3d8817e4Smiod /* Now check whether we got a COUNT reloc. */
954*3d8817e4Smiod if (irelcount >= irelend)
955*3d8817e4Smiod {
956*3d8817e4Smiod ((*_bfd_error_handler)
957*3d8817e4Smiod ("%B: 0x%lx: warning: could not find expected COUNT reloc",
958*3d8817e4Smiod abfd, (unsigned long) paddr));
959*3d8817e4Smiod continue;
960*3d8817e4Smiod }
961*3d8817e4Smiod
962*3d8817e4Smiod /* The number of uses is stored in the r_offset field. We've
963*3d8817e4Smiod just deleted one. */
964*3d8817e4Smiod if (irelcount->r_offset == 0)
965*3d8817e4Smiod {
966*3d8817e4Smiod ((*_bfd_error_handler) ("%B: 0x%lx: warning: bad count",
967*3d8817e4Smiod abfd, (unsigned long) paddr));
968*3d8817e4Smiod continue;
969*3d8817e4Smiod }
970*3d8817e4Smiod
971*3d8817e4Smiod --irelcount->r_offset;
972*3d8817e4Smiod
973*3d8817e4Smiod /* If there are no more uses, we can delete the address. Reload
974*3d8817e4Smiod the address from irelfn, in case it was changed by the
975*3d8817e4Smiod previous call to sh_relax_delete_bytes. */
976*3d8817e4Smiod if (irelcount->r_offset == 0)
977*3d8817e4Smiod {
978*3d8817e4Smiod if (! sh_relax_delete_bytes (abfd, sec,
979*3d8817e4Smiod irelfn->r_vaddr - sec->vma, 4))
980*3d8817e4Smiod goto error_return;
981*3d8817e4Smiod }
982*3d8817e4Smiod
983*3d8817e4Smiod /* We've done all we can with that function call. */
984*3d8817e4Smiod }
985*3d8817e4Smiod
986*3d8817e4Smiod /* Look for load and store instructions that we can align on four
987*3d8817e4Smiod byte boundaries. */
988*3d8817e4Smiod if (have_code)
989*3d8817e4Smiod {
990*3d8817e4Smiod bfd_boolean swapped;
991*3d8817e4Smiod
992*3d8817e4Smiod /* Get the section contents. */
993*3d8817e4Smiod if (contents == NULL)
994*3d8817e4Smiod {
995*3d8817e4Smiod if (coff_section_data (abfd, sec)->contents != NULL)
996*3d8817e4Smiod contents = coff_section_data (abfd, sec)->contents;
997*3d8817e4Smiod else
998*3d8817e4Smiod {
999*3d8817e4Smiod if (!bfd_malloc_and_get_section (abfd, sec, &contents))
1000*3d8817e4Smiod goto error_return;
1001*3d8817e4Smiod }
1002*3d8817e4Smiod }
1003*3d8817e4Smiod
1004*3d8817e4Smiod if (! sh_align_loads (abfd, sec, internal_relocs, contents, &swapped))
1005*3d8817e4Smiod goto error_return;
1006*3d8817e4Smiod
1007*3d8817e4Smiod if (swapped)
1008*3d8817e4Smiod {
1009*3d8817e4Smiod coff_section_data (abfd, sec)->relocs = internal_relocs;
1010*3d8817e4Smiod coff_section_data (abfd, sec)->keep_relocs = TRUE;
1011*3d8817e4Smiod
1012*3d8817e4Smiod coff_section_data (abfd, sec)->contents = contents;
1013*3d8817e4Smiod coff_section_data (abfd, sec)->keep_contents = TRUE;
1014*3d8817e4Smiod
1015*3d8817e4Smiod obj_coff_keep_syms (abfd) = TRUE;
1016*3d8817e4Smiod }
1017*3d8817e4Smiod }
1018*3d8817e4Smiod
1019*3d8817e4Smiod if (internal_relocs != NULL
1020*3d8817e4Smiod && internal_relocs != coff_section_data (abfd, sec)->relocs)
1021*3d8817e4Smiod {
1022*3d8817e4Smiod if (! link_info->keep_memory)
1023*3d8817e4Smiod free (internal_relocs);
1024*3d8817e4Smiod else
1025*3d8817e4Smiod coff_section_data (abfd, sec)->relocs = internal_relocs;
1026*3d8817e4Smiod }
1027*3d8817e4Smiod
1028*3d8817e4Smiod if (contents != NULL && contents != coff_section_data (abfd, sec)->contents)
1029*3d8817e4Smiod {
1030*3d8817e4Smiod if (! link_info->keep_memory)
1031*3d8817e4Smiod free (contents);
1032*3d8817e4Smiod else
1033*3d8817e4Smiod /* Cache the section contents for coff_link_input_bfd. */
1034*3d8817e4Smiod coff_section_data (abfd, sec)->contents = contents;
1035*3d8817e4Smiod }
1036*3d8817e4Smiod
1037*3d8817e4Smiod return TRUE;
1038*3d8817e4Smiod
1039*3d8817e4Smiod error_return:
1040*3d8817e4Smiod if (internal_relocs != NULL
1041*3d8817e4Smiod && internal_relocs != coff_section_data (abfd, sec)->relocs)
1042*3d8817e4Smiod free (internal_relocs);
1043*3d8817e4Smiod if (contents != NULL && contents != coff_section_data (abfd, sec)->contents)
1044*3d8817e4Smiod free (contents);
1045*3d8817e4Smiod return FALSE;
1046*3d8817e4Smiod }
1047*3d8817e4Smiod
1048*3d8817e4Smiod /* Delete some bytes from a section while relaxing. */
1049*3d8817e4Smiod
1050*3d8817e4Smiod static bfd_boolean
sh_relax_delete_bytes(abfd,sec,addr,count)1051*3d8817e4Smiod sh_relax_delete_bytes (abfd, sec, addr, count)
1052*3d8817e4Smiod bfd *abfd;
1053*3d8817e4Smiod asection *sec;
1054*3d8817e4Smiod bfd_vma addr;
1055*3d8817e4Smiod int count;
1056*3d8817e4Smiod {
1057*3d8817e4Smiod bfd_byte *contents;
1058*3d8817e4Smiod struct internal_reloc *irel, *irelend;
1059*3d8817e4Smiod struct internal_reloc *irelalign;
1060*3d8817e4Smiod bfd_vma toaddr;
1061*3d8817e4Smiod bfd_byte *esym, *esymend;
1062*3d8817e4Smiod bfd_size_type symesz;
1063*3d8817e4Smiod struct coff_link_hash_entry **sym_hash;
1064*3d8817e4Smiod asection *o;
1065*3d8817e4Smiod
1066*3d8817e4Smiod contents = coff_section_data (abfd, sec)->contents;
1067*3d8817e4Smiod
1068*3d8817e4Smiod /* The deletion must stop at the next ALIGN reloc for an aligment
1069*3d8817e4Smiod power larger than the number of bytes we are deleting. */
1070*3d8817e4Smiod
1071*3d8817e4Smiod irelalign = NULL;
1072*3d8817e4Smiod toaddr = sec->size;
1073*3d8817e4Smiod
1074*3d8817e4Smiod irel = coff_section_data (abfd, sec)->relocs;
1075*3d8817e4Smiod irelend = irel + sec->reloc_count;
1076*3d8817e4Smiod for (; irel < irelend; irel++)
1077*3d8817e4Smiod {
1078*3d8817e4Smiod if (irel->r_type == R_SH_ALIGN
1079*3d8817e4Smiod && irel->r_vaddr - sec->vma > addr
1080*3d8817e4Smiod && count < (1 << irel->r_offset))
1081*3d8817e4Smiod {
1082*3d8817e4Smiod irelalign = irel;
1083*3d8817e4Smiod toaddr = irel->r_vaddr - sec->vma;
1084*3d8817e4Smiod break;
1085*3d8817e4Smiod }
1086*3d8817e4Smiod }
1087*3d8817e4Smiod
1088*3d8817e4Smiod /* Actually delete the bytes. */
1089*3d8817e4Smiod memmove (contents + addr, contents + addr + count,
1090*3d8817e4Smiod (size_t) (toaddr - addr - count));
1091*3d8817e4Smiod if (irelalign == NULL)
1092*3d8817e4Smiod sec->size -= count;
1093*3d8817e4Smiod else
1094*3d8817e4Smiod {
1095*3d8817e4Smiod int i;
1096*3d8817e4Smiod
1097*3d8817e4Smiod #define NOP_OPCODE (0x0009)
1098*3d8817e4Smiod
1099*3d8817e4Smiod BFD_ASSERT ((count & 1) == 0);
1100*3d8817e4Smiod for (i = 0; i < count; i += 2)
1101*3d8817e4Smiod bfd_put_16 (abfd, (bfd_vma) NOP_OPCODE, contents + toaddr - count + i);
1102*3d8817e4Smiod }
1103*3d8817e4Smiod
1104*3d8817e4Smiod /* Adjust all the relocs. */
1105*3d8817e4Smiod for (irel = coff_section_data (abfd, sec)->relocs; irel < irelend; irel++)
1106*3d8817e4Smiod {
1107*3d8817e4Smiod bfd_vma nraddr, stop;
1108*3d8817e4Smiod bfd_vma start = 0;
1109*3d8817e4Smiod int insn = 0;
1110*3d8817e4Smiod struct internal_syment sym;
1111*3d8817e4Smiod int off, adjust, oinsn;
1112*3d8817e4Smiod bfd_signed_vma voff = 0;
1113*3d8817e4Smiod bfd_boolean overflow;
1114*3d8817e4Smiod
1115*3d8817e4Smiod /* Get the new reloc address. */
1116*3d8817e4Smiod nraddr = irel->r_vaddr - sec->vma;
1117*3d8817e4Smiod if ((irel->r_vaddr - sec->vma > addr
1118*3d8817e4Smiod && irel->r_vaddr - sec->vma < toaddr)
1119*3d8817e4Smiod || (irel->r_type == R_SH_ALIGN
1120*3d8817e4Smiod && irel->r_vaddr - sec->vma == toaddr))
1121*3d8817e4Smiod nraddr -= count;
1122*3d8817e4Smiod
1123*3d8817e4Smiod /* See if this reloc was for the bytes we have deleted, in which
1124*3d8817e4Smiod case we no longer care about it. Don't delete relocs which
1125*3d8817e4Smiod represent addresses, though. */
1126*3d8817e4Smiod if (irel->r_vaddr - sec->vma >= addr
1127*3d8817e4Smiod && irel->r_vaddr - sec->vma < addr + count
1128*3d8817e4Smiod && irel->r_type != R_SH_ALIGN
1129*3d8817e4Smiod && irel->r_type != R_SH_CODE
1130*3d8817e4Smiod && irel->r_type != R_SH_DATA
1131*3d8817e4Smiod && irel->r_type != R_SH_LABEL)
1132*3d8817e4Smiod irel->r_type = R_SH_UNUSED;
1133*3d8817e4Smiod
1134*3d8817e4Smiod /* If this is a PC relative reloc, see if the range it covers
1135*3d8817e4Smiod includes the bytes we have deleted. */
1136*3d8817e4Smiod switch (irel->r_type)
1137*3d8817e4Smiod {
1138*3d8817e4Smiod default:
1139*3d8817e4Smiod break;
1140*3d8817e4Smiod
1141*3d8817e4Smiod case R_SH_PCDISP8BY2:
1142*3d8817e4Smiod case R_SH_PCDISP:
1143*3d8817e4Smiod case R_SH_PCRELIMM8BY2:
1144*3d8817e4Smiod case R_SH_PCRELIMM8BY4:
1145*3d8817e4Smiod start = irel->r_vaddr - sec->vma;
1146*3d8817e4Smiod insn = bfd_get_16 (abfd, contents + nraddr);
1147*3d8817e4Smiod break;
1148*3d8817e4Smiod }
1149*3d8817e4Smiod
1150*3d8817e4Smiod switch (irel->r_type)
1151*3d8817e4Smiod {
1152*3d8817e4Smiod default:
1153*3d8817e4Smiod start = stop = addr;
1154*3d8817e4Smiod break;
1155*3d8817e4Smiod
1156*3d8817e4Smiod case R_SH_IMM32:
1157*3d8817e4Smiod #ifdef COFF_WITH_PE
1158*3d8817e4Smiod case R_SH_IMM32CE:
1159*3d8817e4Smiod case R_SH_IMAGEBASE:
1160*3d8817e4Smiod #endif
1161*3d8817e4Smiod /* If this reloc is against a symbol defined in this
1162*3d8817e4Smiod section, and the symbol will not be adjusted below, we
1163*3d8817e4Smiod must check the addend to see it will put the value in
1164*3d8817e4Smiod range to be adjusted, and hence must be changed. */
1165*3d8817e4Smiod bfd_coff_swap_sym_in (abfd,
1166*3d8817e4Smiod ((bfd_byte *) obj_coff_external_syms (abfd)
1167*3d8817e4Smiod + (irel->r_symndx
1168*3d8817e4Smiod * bfd_coff_symesz (abfd))),
1169*3d8817e4Smiod &sym);
1170*3d8817e4Smiod if (sym.n_sclass != C_EXT
1171*3d8817e4Smiod && sym.n_scnum == sec->target_index
1172*3d8817e4Smiod && ((bfd_vma) sym.n_value <= addr
1173*3d8817e4Smiod || (bfd_vma) sym.n_value >= toaddr))
1174*3d8817e4Smiod {
1175*3d8817e4Smiod bfd_vma val;
1176*3d8817e4Smiod
1177*3d8817e4Smiod val = bfd_get_32 (abfd, contents + nraddr);
1178*3d8817e4Smiod val += sym.n_value;
1179*3d8817e4Smiod if (val > addr && val < toaddr)
1180*3d8817e4Smiod bfd_put_32 (abfd, val - count, contents + nraddr);
1181*3d8817e4Smiod }
1182*3d8817e4Smiod start = stop = addr;
1183*3d8817e4Smiod break;
1184*3d8817e4Smiod
1185*3d8817e4Smiod case R_SH_PCDISP8BY2:
1186*3d8817e4Smiod off = insn & 0xff;
1187*3d8817e4Smiod if (off & 0x80)
1188*3d8817e4Smiod off -= 0x100;
1189*3d8817e4Smiod stop = (bfd_vma) ((bfd_signed_vma) start + 4 + off * 2);
1190*3d8817e4Smiod break;
1191*3d8817e4Smiod
1192*3d8817e4Smiod case R_SH_PCDISP:
1193*3d8817e4Smiod bfd_coff_swap_sym_in (abfd,
1194*3d8817e4Smiod ((bfd_byte *) obj_coff_external_syms (abfd)
1195*3d8817e4Smiod + (irel->r_symndx
1196*3d8817e4Smiod * bfd_coff_symesz (abfd))),
1197*3d8817e4Smiod &sym);
1198*3d8817e4Smiod if (sym.n_sclass == C_EXT)
1199*3d8817e4Smiod start = stop = addr;
1200*3d8817e4Smiod else
1201*3d8817e4Smiod {
1202*3d8817e4Smiod off = insn & 0xfff;
1203*3d8817e4Smiod if (off & 0x800)
1204*3d8817e4Smiod off -= 0x1000;
1205*3d8817e4Smiod stop = (bfd_vma) ((bfd_signed_vma) start + 4 + off * 2);
1206*3d8817e4Smiod }
1207*3d8817e4Smiod break;
1208*3d8817e4Smiod
1209*3d8817e4Smiod case R_SH_PCRELIMM8BY2:
1210*3d8817e4Smiod off = insn & 0xff;
1211*3d8817e4Smiod stop = start + 4 + off * 2;
1212*3d8817e4Smiod break;
1213*3d8817e4Smiod
1214*3d8817e4Smiod case R_SH_PCRELIMM8BY4:
1215*3d8817e4Smiod off = insn & 0xff;
1216*3d8817e4Smiod stop = (start &~ (bfd_vma) 3) + 4 + off * 4;
1217*3d8817e4Smiod break;
1218*3d8817e4Smiod
1219*3d8817e4Smiod case R_SH_SWITCH8:
1220*3d8817e4Smiod case R_SH_SWITCH16:
1221*3d8817e4Smiod case R_SH_SWITCH32:
1222*3d8817e4Smiod /* These relocs types represent
1223*3d8817e4Smiod .word L2-L1
1224*3d8817e4Smiod The r_offset field holds the difference between the reloc
1225*3d8817e4Smiod address and L1. That is the start of the reloc, and
1226*3d8817e4Smiod adding in the contents gives us the top. We must adjust
1227*3d8817e4Smiod both the r_offset field and the section contents. */
1228*3d8817e4Smiod
1229*3d8817e4Smiod start = irel->r_vaddr - sec->vma;
1230*3d8817e4Smiod stop = (bfd_vma) ((bfd_signed_vma) start - (long) irel->r_offset);
1231*3d8817e4Smiod
1232*3d8817e4Smiod if (start > addr
1233*3d8817e4Smiod && start < toaddr
1234*3d8817e4Smiod && (stop <= addr || stop >= toaddr))
1235*3d8817e4Smiod irel->r_offset += count;
1236*3d8817e4Smiod else if (stop > addr
1237*3d8817e4Smiod && stop < toaddr
1238*3d8817e4Smiod && (start <= addr || start >= toaddr))
1239*3d8817e4Smiod irel->r_offset -= count;
1240*3d8817e4Smiod
1241*3d8817e4Smiod start = stop;
1242*3d8817e4Smiod
1243*3d8817e4Smiod if (irel->r_type == R_SH_SWITCH16)
1244*3d8817e4Smiod voff = bfd_get_signed_16 (abfd, contents + nraddr);
1245*3d8817e4Smiod else if (irel->r_type == R_SH_SWITCH8)
1246*3d8817e4Smiod voff = bfd_get_8 (abfd, contents + nraddr);
1247*3d8817e4Smiod else
1248*3d8817e4Smiod voff = bfd_get_signed_32 (abfd, contents + nraddr);
1249*3d8817e4Smiod stop = (bfd_vma) ((bfd_signed_vma) start + voff);
1250*3d8817e4Smiod
1251*3d8817e4Smiod break;
1252*3d8817e4Smiod
1253*3d8817e4Smiod case R_SH_USES:
1254*3d8817e4Smiod start = irel->r_vaddr - sec->vma;
1255*3d8817e4Smiod stop = (bfd_vma) ((bfd_signed_vma) start
1256*3d8817e4Smiod + (long) irel->r_offset
1257*3d8817e4Smiod + 4);
1258*3d8817e4Smiod break;
1259*3d8817e4Smiod }
1260*3d8817e4Smiod
1261*3d8817e4Smiod if (start > addr
1262*3d8817e4Smiod && start < toaddr
1263*3d8817e4Smiod && (stop <= addr || stop >= toaddr))
1264*3d8817e4Smiod adjust = count;
1265*3d8817e4Smiod else if (stop > addr
1266*3d8817e4Smiod && stop < toaddr
1267*3d8817e4Smiod && (start <= addr || start >= toaddr))
1268*3d8817e4Smiod adjust = - count;
1269*3d8817e4Smiod else
1270*3d8817e4Smiod adjust = 0;
1271*3d8817e4Smiod
1272*3d8817e4Smiod if (adjust != 0)
1273*3d8817e4Smiod {
1274*3d8817e4Smiod oinsn = insn;
1275*3d8817e4Smiod overflow = FALSE;
1276*3d8817e4Smiod switch (irel->r_type)
1277*3d8817e4Smiod {
1278*3d8817e4Smiod default:
1279*3d8817e4Smiod abort ();
1280*3d8817e4Smiod break;
1281*3d8817e4Smiod
1282*3d8817e4Smiod case R_SH_PCDISP8BY2:
1283*3d8817e4Smiod case R_SH_PCRELIMM8BY2:
1284*3d8817e4Smiod insn += adjust / 2;
1285*3d8817e4Smiod if ((oinsn & 0xff00) != (insn & 0xff00))
1286*3d8817e4Smiod overflow = TRUE;
1287*3d8817e4Smiod bfd_put_16 (abfd, (bfd_vma) insn, contents + nraddr);
1288*3d8817e4Smiod break;
1289*3d8817e4Smiod
1290*3d8817e4Smiod case R_SH_PCDISP:
1291*3d8817e4Smiod insn += adjust / 2;
1292*3d8817e4Smiod if ((oinsn & 0xf000) != (insn & 0xf000))
1293*3d8817e4Smiod overflow = TRUE;
1294*3d8817e4Smiod bfd_put_16 (abfd, (bfd_vma) insn, contents + nraddr);
1295*3d8817e4Smiod break;
1296*3d8817e4Smiod
1297*3d8817e4Smiod case R_SH_PCRELIMM8BY4:
1298*3d8817e4Smiod BFD_ASSERT (adjust == count || count >= 4);
1299*3d8817e4Smiod if (count >= 4)
1300*3d8817e4Smiod insn += adjust / 4;
1301*3d8817e4Smiod else
1302*3d8817e4Smiod {
1303*3d8817e4Smiod if ((irel->r_vaddr & 3) == 0)
1304*3d8817e4Smiod ++insn;
1305*3d8817e4Smiod }
1306*3d8817e4Smiod if ((oinsn & 0xff00) != (insn & 0xff00))
1307*3d8817e4Smiod overflow = TRUE;
1308*3d8817e4Smiod bfd_put_16 (abfd, (bfd_vma) insn, contents + nraddr);
1309*3d8817e4Smiod break;
1310*3d8817e4Smiod
1311*3d8817e4Smiod case R_SH_SWITCH8:
1312*3d8817e4Smiod voff += adjust;
1313*3d8817e4Smiod if (voff < 0 || voff >= 0xff)
1314*3d8817e4Smiod overflow = TRUE;
1315*3d8817e4Smiod bfd_put_8 (abfd, (bfd_vma) voff, contents + nraddr);
1316*3d8817e4Smiod break;
1317*3d8817e4Smiod
1318*3d8817e4Smiod case R_SH_SWITCH16:
1319*3d8817e4Smiod voff += adjust;
1320*3d8817e4Smiod if (voff < - 0x8000 || voff >= 0x8000)
1321*3d8817e4Smiod overflow = TRUE;
1322*3d8817e4Smiod bfd_put_signed_16 (abfd, (bfd_vma) voff, contents + nraddr);
1323*3d8817e4Smiod break;
1324*3d8817e4Smiod
1325*3d8817e4Smiod case R_SH_SWITCH32:
1326*3d8817e4Smiod voff += adjust;
1327*3d8817e4Smiod bfd_put_signed_32 (abfd, (bfd_vma) voff, contents + nraddr);
1328*3d8817e4Smiod break;
1329*3d8817e4Smiod
1330*3d8817e4Smiod case R_SH_USES:
1331*3d8817e4Smiod irel->r_offset += adjust;
1332*3d8817e4Smiod break;
1333*3d8817e4Smiod }
1334*3d8817e4Smiod
1335*3d8817e4Smiod if (overflow)
1336*3d8817e4Smiod {
1337*3d8817e4Smiod ((*_bfd_error_handler)
1338*3d8817e4Smiod ("%B: 0x%lx: fatal: reloc overflow while relaxing",
1339*3d8817e4Smiod abfd, (unsigned long) irel->r_vaddr));
1340*3d8817e4Smiod bfd_set_error (bfd_error_bad_value);
1341*3d8817e4Smiod return FALSE;
1342*3d8817e4Smiod }
1343*3d8817e4Smiod }
1344*3d8817e4Smiod
1345*3d8817e4Smiod irel->r_vaddr = nraddr + sec->vma;
1346*3d8817e4Smiod }
1347*3d8817e4Smiod
1348*3d8817e4Smiod /* Look through all the other sections. If there contain any IMM32
1349*3d8817e4Smiod relocs against internal symbols which we are not going to adjust
1350*3d8817e4Smiod below, we may need to adjust the addends. */
1351*3d8817e4Smiod for (o = abfd->sections; o != NULL; o = o->next)
1352*3d8817e4Smiod {
1353*3d8817e4Smiod struct internal_reloc *internal_relocs;
1354*3d8817e4Smiod struct internal_reloc *irelscan, *irelscanend;
1355*3d8817e4Smiod bfd_byte *ocontents;
1356*3d8817e4Smiod
1357*3d8817e4Smiod if (o == sec
1358*3d8817e4Smiod || (o->flags & SEC_RELOC) == 0
1359*3d8817e4Smiod || o->reloc_count == 0)
1360*3d8817e4Smiod continue;
1361*3d8817e4Smiod
1362*3d8817e4Smiod /* We always cache the relocs. Perhaps, if info->keep_memory is
1363*3d8817e4Smiod FALSE, we should free them, if we are permitted to, when we
1364*3d8817e4Smiod leave sh_coff_relax_section. */
1365*3d8817e4Smiod internal_relocs = (_bfd_coff_read_internal_relocs
1366*3d8817e4Smiod (abfd, o, TRUE, (bfd_byte *) NULL, FALSE,
1367*3d8817e4Smiod (struct internal_reloc *) NULL));
1368*3d8817e4Smiod if (internal_relocs == NULL)
1369*3d8817e4Smiod return FALSE;
1370*3d8817e4Smiod
1371*3d8817e4Smiod ocontents = NULL;
1372*3d8817e4Smiod irelscanend = internal_relocs + o->reloc_count;
1373*3d8817e4Smiod for (irelscan = internal_relocs; irelscan < irelscanend; irelscan++)
1374*3d8817e4Smiod {
1375*3d8817e4Smiod struct internal_syment sym;
1376*3d8817e4Smiod
1377*3d8817e4Smiod #ifdef COFF_WITH_PE
1378*3d8817e4Smiod if (irelscan->r_type != R_SH_IMM32
1379*3d8817e4Smiod && irelscan->r_type != R_SH_IMAGEBASE
1380*3d8817e4Smiod && irelscan->r_type != R_SH_IMM32CE)
1381*3d8817e4Smiod #else
1382*3d8817e4Smiod if (irelscan->r_type != R_SH_IMM32)
1383*3d8817e4Smiod #endif
1384*3d8817e4Smiod continue;
1385*3d8817e4Smiod
1386*3d8817e4Smiod bfd_coff_swap_sym_in (abfd,
1387*3d8817e4Smiod ((bfd_byte *) obj_coff_external_syms (abfd)
1388*3d8817e4Smiod + (irelscan->r_symndx
1389*3d8817e4Smiod * bfd_coff_symesz (abfd))),
1390*3d8817e4Smiod &sym);
1391*3d8817e4Smiod if (sym.n_sclass != C_EXT
1392*3d8817e4Smiod && sym.n_scnum == sec->target_index
1393*3d8817e4Smiod && ((bfd_vma) sym.n_value <= addr
1394*3d8817e4Smiod || (bfd_vma) sym.n_value >= toaddr))
1395*3d8817e4Smiod {
1396*3d8817e4Smiod bfd_vma val;
1397*3d8817e4Smiod
1398*3d8817e4Smiod if (ocontents == NULL)
1399*3d8817e4Smiod {
1400*3d8817e4Smiod if (coff_section_data (abfd, o)->contents != NULL)
1401*3d8817e4Smiod ocontents = coff_section_data (abfd, o)->contents;
1402*3d8817e4Smiod else
1403*3d8817e4Smiod {
1404*3d8817e4Smiod if (!bfd_malloc_and_get_section (abfd, o, &ocontents))
1405*3d8817e4Smiod return FALSE;
1406*3d8817e4Smiod /* We always cache the section contents.
1407*3d8817e4Smiod Perhaps, if info->keep_memory is FALSE, we
1408*3d8817e4Smiod should free them, if we are permitted to,
1409*3d8817e4Smiod when we leave sh_coff_relax_section. */
1410*3d8817e4Smiod coff_section_data (abfd, o)->contents = ocontents;
1411*3d8817e4Smiod }
1412*3d8817e4Smiod }
1413*3d8817e4Smiod
1414*3d8817e4Smiod val = bfd_get_32 (abfd, ocontents + irelscan->r_vaddr - o->vma);
1415*3d8817e4Smiod val += sym.n_value;
1416*3d8817e4Smiod if (val > addr && val < toaddr)
1417*3d8817e4Smiod bfd_put_32 (abfd, val - count,
1418*3d8817e4Smiod ocontents + irelscan->r_vaddr - o->vma);
1419*3d8817e4Smiod
1420*3d8817e4Smiod coff_section_data (abfd, o)->keep_contents = TRUE;
1421*3d8817e4Smiod }
1422*3d8817e4Smiod }
1423*3d8817e4Smiod }
1424*3d8817e4Smiod
1425*3d8817e4Smiod /* Adjusting the internal symbols will not work if something has
1426*3d8817e4Smiod already retrieved the generic symbols. It would be possible to
1427*3d8817e4Smiod make this work by adjusting the generic symbols at the same time.
1428*3d8817e4Smiod However, this case should not arise in normal usage. */
1429*3d8817e4Smiod if (obj_symbols (abfd) != NULL
1430*3d8817e4Smiod || obj_raw_syments (abfd) != NULL)
1431*3d8817e4Smiod {
1432*3d8817e4Smiod ((*_bfd_error_handler)
1433*3d8817e4Smiod ("%B: fatal: generic symbols retrieved before relaxing", abfd));
1434*3d8817e4Smiod bfd_set_error (bfd_error_invalid_operation);
1435*3d8817e4Smiod return FALSE;
1436*3d8817e4Smiod }
1437*3d8817e4Smiod
1438*3d8817e4Smiod /* Adjust all the symbols. */
1439*3d8817e4Smiod sym_hash = obj_coff_sym_hashes (abfd);
1440*3d8817e4Smiod symesz = bfd_coff_symesz (abfd);
1441*3d8817e4Smiod esym = (bfd_byte *) obj_coff_external_syms (abfd);
1442*3d8817e4Smiod esymend = esym + obj_raw_syment_count (abfd) * symesz;
1443*3d8817e4Smiod while (esym < esymend)
1444*3d8817e4Smiod {
1445*3d8817e4Smiod struct internal_syment isym;
1446*3d8817e4Smiod
1447*3d8817e4Smiod bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &isym);
1448*3d8817e4Smiod
1449*3d8817e4Smiod if (isym.n_scnum == sec->target_index
1450*3d8817e4Smiod && (bfd_vma) isym.n_value > addr
1451*3d8817e4Smiod && (bfd_vma) isym.n_value < toaddr)
1452*3d8817e4Smiod {
1453*3d8817e4Smiod isym.n_value -= count;
1454*3d8817e4Smiod
1455*3d8817e4Smiod bfd_coff_swap_sym_out (abfd, (PTR) &isym, (PTR) esym);
1456*3d8817e4Smiod
1457*3d8817e4Smiod if (*sym_hash != NULL)
1458*3d8817e4Smiod {
1459*3d8817e4Smiod BFD_ASSERT ((*sym_hash)->root.type == bfd_link_hash_defined
1460*3d8817e4Smiod || (*sym_hash)->root.type == bfd_link_hash_defweak);
1461*3d8817e4Smiod BFD_ASSERT ((*sym_hash)->root.u.def.value >= addr
1462*3d8817e4Smiod && (*sym_hash)->root.u.def.value < toaddr);
1463*3d8817e4Smiod (*sym_hash)->root.u.def.value -= count;
1464*3d8817e4Smiod }
1465*3d8817e4Smiod }
1466*3d8817e4Smiod
1467*3d8817e4Smiod esym += (isym.n_numaux + 1) * symesz;
1468*3d8817e4Smiod sym_hash += isym.n_numaux + 1;
1469*3d8817e4Smiod }
1470*3d8817e4Smiod
1471*3d8817e4Smiod /* See if we can move the ALIGN reloc forward. We have adjusted
1472*3d8817e4Smiod r_vaddr for it already. */
1473*3d8817e4Smiod if (irelalign != NULL)
1474*3d8817e4Smiod {
1475*3d8817e4Smiod bfd_vma alignto, alignaddr;
1476*3d8817e4Smiod
1477*3d8817e4Smiod alignto = BFD_ALIGN (toaddr, 1 << irelalign->r_offset);
1478*3d8817e4Smiod alignaddr = BFD_ALIGN (irelalign->r_vaddr - sec->vma,
1479*3d8817e4Smiod 1 << irelalign->r_offset);
1480*3d8817e4Smiod if (alignto != alignaddr)
1481*3d8817e4Smiod {
1482*3d8817e4Smiod /* Tail recursion. */
1483*3d8817e4Smiod return sh_relax_delete_bytes (abfd, sec, alignaddr,
1484*3d8817e4Smiod (int) (alignto - alignaddr));
1485*3d8817e4Smiod }
1486*3d8817e4Smiod }
1487*3d8817e4Smiod
1488*3d8817e4Smiod return TRUE;
1489*3d8817e4Smiod }
1490*3d8817e4Smiod
1491*3d8817e4Smiod /* This is yet another version of the SH opcode table, used to rapidly
1492*3d8817e4Smiod get information about a particular instruction. */
1493*3d8817e4Smiod
1494*3d8817e4Smiod /* The opcode map is represented by an array of these structures. The
1495*3d8817e4Smiod array is indexed by the high order four bits in the instruction. */
1496*3d8817e4Smiod
1497*3d8817e4Smiod struct sh_major_opcode
1498*3d8817e4Smiod {
1499*3d8817e4Smiod /* A pointer to the instruction list. This is an array which
1500*3d8817e4Smiod contains all the instructions with this major opcode. */
1501*3d8817e4Smiod const struct sh_minor_opcode *minor_opcodes;
1502*3d8817e4Smiod /* The number of elements in minor_opcodes. */
1503*3d8817e4Smiod unsigned short count;
1504*3d8817e4Smiod };
1505*3d8817e4Smiod
1506*3d8817e4Smiod /* This structure holds information for a set of SH opcodes. The
1507*3d8817e4Smiod instruction code is anded with the mask value, and the resulting
1508*3d8817e4Smiod value is used to search the order opcode list. */
1509*3d8817e4Smiod
1510*3d8817e4Smiod struct sh_minor_opcode
1511*3d8817e4Smiod {
1512*3d8817e4Smiod /* The sorted opcode list. */
1513*3d8817e4Smiod const struct sh_opcode *opcodes;
1514*3d8817e4Smiod /* The number of elements in opcodes. */
1515*3d8817e4Smiod unsigned short count;
1516*3d8817e4Smiod /* The mask value to use when searching the opcode list. */
1517*3d8817e4Smiod unsigned short mask;
1518*3d8817e4Smiod };
1519*3d8817e4Smiod
1520*3d8817e4Smiod /* This structure holds information for an SH instruction. An array
1521*3d8817e4Smiod of these structures is sorted in order by opcode. */
1522*3d8817e4Smiod
1523*3d8817e4Smiod struct sh_opcode
1524*3d8817e4Smiod {
1525*3d8817e4Smiod /* The code for this instruction, after it has been anded with the
1526*3d8817e4Smiod mask value in the sh_major_opcode structure. */
1527*3d8817e4Smiod unsigned short opcode;
1528*3d8817e4Smiod /* Flags for this instruction. */
1529*3d8817e4Smiod unsigned long flags;
1530*3d8817e4Smiod };
1531*3d8817e4Smiod
1532*3d8817e4Smiod /* Flag which appear in the sh_opcode structure. */
1533*3d8817e4Smiod
1534*3d8817e4Smiod /* This instruction loads a value from memory. */
1535*3d8817e4Smiod #define LOAD (0x1)
1536*3d8817e4Smiod
1537*3d8817e4Smiod /* This instruction stores a value to memory. */
1538*3d8817e4Smiod #define STORE (0x2)
1539*3d8817e4Smiod
1540*3d8817e4Smiod /* This instruction is a branch. */
1541*3d8817e4Smiod #define BRANCH (0x4)
1542*3d8817e4Smiod
1543*3d8817e4Smiod /* This instruction has a delay slot. */
1544*3d8817e4Smiod #define DELAY (0x8)
1545*3d8817e4Smiod
1546*3d8817e4Smiod /* This instruction uses the value in the register in the field at
1547*3d8817e4Smiod mask 0x0f00 of the instruction. */
1548*3d8817e4Smiod #define USES1 (0x10)
1549*3d8817e4Smiod #define USES1_REG(x) ((x & 0x0f00) >> 8)
1550*3d8817e4Smiod
1551*3d8817e4Smiod /* This instruction uses the value in the register in the field at
1552*3d8817e4Smiod mask 0x00f0 of the instruction. */
1553*3d8817e4Smiod #define USES2 (0x20)
1554*3d8817e4Smiod #define USES2_REG(x) ((x & 0x00f0) >> 4)
1555*3d8817e4Smiod
1556*3d8817e4Smiod /* This instruction uses the value in register 0. */
1557*3d8817e4Smiod #define USESR0 (0x40)
1558*3d8817e4Smiod
1559*3d8817e4Smiod /* This instruction sets the value in the register in the field at
1560*3d8817e4Smiod mask 0x0f00 of the instruction. */
1561*3d8817e4Smiod #define SETS1 (0x80)
1562*3d8817e4Smiod #define SETS1_REG(x) ((x & 0x0f00) >> 8)
1563*3d8817e4Smiod
1564*3d8817e4Smiod /* This instruction sets the value in the register in the field at
1565*3d8817e4Smiod mask 0x00f0 of the instruction. */
1566*3d8817e4Smiod #define SETS2 (0x100)
1567*3d8817e4Smiod #define SETS2_REG(x) ((x & 0x00f0) >> 4)
1568*3d8817e4Smiod
1569*3d8817e4Smiod /* This instruction sets register 0. */
1570*3d8817e4Smiod #define SETSR0 (0x200)
1571*3d8817e4Smiod
1572*3d8817e4Smiod /* This instruction sets a special register. */
1573*3d8817e4Smiod #define SETSSP (0x400)
1574*3d8817e4Smiod
1575*3d8817e4Smiod /* This instruction uses a special register. */
1576*3d8817e4Smiod #define USESSP (0x800)
1577*3d8817e4Smiod
1578*3d8817e4Smiod /* This instruction uses the floating point register in the field at
1579*3d8817e4Smiod mask 0x0f00 of the instruction. */
1580*3d8817e4Smiod #define USESF1 (0x1000)
1581*3d8817e4Smiod #define USESF1_REG(x) ((x & 0x0f00) >> 8)
1582*3d8817e4Smiod
1583*3d8817e4Smiod /* This instruction uses the floating point register in the field at
1584*3d8817e4Smiod mask 0x00f0 of the instruction. */
1585*3d8817e4Smiod #define USESF2 (0x2000)
1586*3d8817e4Smiod #define USESF2_REG(x) ((x & 0x00f0) >> 4)
1587*3d8817e4Smiod
1588*3d8817e4Smiod /* This instruction uses floating point register 0. */
1589*3d8817e4Smiod #define USESF0 (0x4000)
1590*3d8817e4Smiod
1591*3d8817e4Smiod /* This instruction sets the floating point register in the field at
1592*3d8817e4Smiod mask 0x0f00 of the instruction. */
1593*3d8817e4Smiod #define SETSF1 (0x8000)
1594*3d8817e4Smiod #define SETSF1_REG(x) ((x & 0x0f00) >> 8)
1595*3d8817e4Smiod
1596*3d8817e4Smiod #define USESAS (0x10000)
1597*3d8817e4Smiod #define USESAS_REG(x) (((((x) >> 8) - 2) & 3) + 2)
1598*3d8817e4Smiod #define USESR8 (0x20000)
1599*3d8817e4Smiod #define SETSAS (0x40000)
1600*3d8817e4Smiod #define SETSAS_REG(x) USESAS_REG (x)
1601*3d8817e4Smiod
1602*3d8817e4Smiod #define MAP(a) a, sizeof a / sizeof a[0]
1603*3d8817e4Smiod
1604*3d8817e4Smiod #ifndef COFF_IMAGE_WITH_PE
1605*3d8817e4Smiod static bfd_boolean sh_insn_uses_reg
1606*3d8817e4Smiod PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
1607*3d8817e4Smiod static bfd_boolean sh_insn_sets_reg
1608*3d8817e4Smiod PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
1609*3d8817e4Smiod static bfd_boolean sh_insn_uses_or_sets_reg
1610*3d8817e4Smiod PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
1611*3d8817e4Smiod static bfd_boolean sh_insn_uses_freg
1612*3d8817e4Smiod PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
1613*3d8817e4Smiod static bfd_boolean sh_insn_sets_freg
1614*3d8817e4Smiod PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
1615*3d8817e4Smiod static bfd_boolean sh_insn_uses_or_sets_freg
1616*3d8817e4Smiod PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
1617*3d8817e4Smiod static bfd_boolean sh_insns_conflict
1618*3d8817e4Smiod PARAMS ((unsigned int, const struct sh_opcode *, unsigned int,
1619*3d8817e4Smiod const struct sh_opcode *));
1620*3d8817e4Smiod static bfd_boolean sh_load_use
1621*3d8817e4Smiod PARAMS ((unsigned int, const struct sh_opcode *, unsigned int,
1622*3d8817e4Smiod const struct sh_opcode *));
1623*3d8817e4Smiod
1624*3d8817e4Smiod /* The opcode maps. */
1625*3d8817e4Smiod
1626*3d8817e4Smiod static const struct sh_opcode sh_opcode00[] =
1627*3d8817e4Smiod {
1628*3d8817e4Smiod { 0x0008, SETSSP }, /* clrt */
1629*3d8817e4Smiod { 0x0009, 0 }, /* nop */
1630*3d8817e4Smiod { 0x000b, BRANCH | DELAY | USESSP }, /* rts */
1631*3d8817e4Smiod { 0x0018, SETSSP }, /* sett */
1632*3d8817e4Smiod { 0x0019, SETSSP }, /* div0u */
1633*3d8817e4Smiod { 0x001b, 0 }, /* sleep */
1634*3d8817e4Smiod { 0x0028, SETSSP }, /* clrmac */
1635*3d8817e4Smiod { 0x002b, BRANCH | DELAY | SETSSP }, /* rte */
1636*3d8817e4Smiod { 0x0038, USESSP | SETSSP }, /* ldtlb */
1637*3d8817e4Smiod { 0x0048, SETSSP }, /* clrs */
1638*3d8817e4Smiod { 0x0058, SETSSP } /* sets */
1639*3d8817e4Smiod };
1640*3d8817e4Smiod
1641*3d8817e4Smiod static const struct sh_opcode sh_opcode01[] =
1642*3d8817e4Smiod {
1643*3d8817e4Smiod { 0x0003, BRANCH | DELAY | USES1 | SETSSP }, /* bsrf rn */
1644*3d8817e4Smiod { 0x000a, SETS1 | USESSP }, /* sts mach,rn */
1645*3d8817e4Smiod { 0x001a, SETS1 | USESSP }, /* sts macl,rn */
1646*3d8817e4Smiod { 0x0023, BRANCH | DELAY | USES1 }, /* braf rn */
1647*3d8817e4Smiod { 0x0029, SETS1 | USESSP }, /* movt rn */
1648*3d8817e4Smiod { 0x002a, SETS1 | USESSP }, /* sts pr,rn */
1649*3d8817e4Smiod { 0x005a, SETS1 | USESSP }, /* sts fpul,rn */
1650*3d8817e4Smiod { 0x006a, SETS1 | USESSP }, /* sts fpscr,rn / sts dsr,rn */
1651*3d8817e4Smiod { 0x0083, LOAD | USES1 }, /* pref @rn */
1652*3d8817e4Smiod { 0x007a, SETS1 | USESSP }, /* sts a0,rn */
1653*3d8817e4Smiod { 0x008a, SETS1 | USESSP }, /* sts x0,rn */
1654*3d8817e4Smiod { 0x009a, SETS1 | USESSP }, /* sts x1,rn */
1655*3d8817e4Smiod { 0x00aa, SETS1 | USESSP }, /* sts y0,rn */
1656*3d8817e4Smiod { 0x00ba, SETS1 | USESSP } /* sts y1,rn */
1657*3d8817e4Smiod };
1658*3d8817e4Smiod
1659*3d8817e4Smiod static const struct sh_opcode sh_opcode02[] =
1660*3d8817e4Smiod {
1661*3d8817e4Smiod { 0x0002, SETS1 | USESSP }, /* stc <special_reg>,rn */
1662*3d8817e4Smiod { 0x0004, STORE | USES1 | USES2 | USESR0 }, /* mov.b rm,@(r0,rn) */
1663*3d8817e4Smiod { 0x0005, STORE | USES1 | USES2 | USESR0 }, /* mov.w rm,@(r0,rn) */
1664*3d8817e4Smiod { 0x0006, STORE | USES1 | USES2 | USESR0 }, /* mov.l rm,@(r0,rn) */
1665*3d8817e4Smiod { 0x0007, SETSSP | USES1 | USES2 }, /* mul.l rm,rn */
1666*3d8817e4Smiod { 0x000c, LOAD | SETS1 | USES2 | USESR0 }, /* mov.b @(r0,rm),rn */
1667*3d8817e4Smiod { 0x000d, LOAD | SETS1 | USES2 | USESR0 }, /* mov.w @(r0,rm),rn */
1668*3d8817e4Smiod { 0x000e, LOAD | SETS1 | USES2 | USESR0 }, /* mov.l @(r0,rm),rn */
1669*3d8817e4Smiod { 0x000f, LOAD|SETS1|SETS2|SETSSP|USES1|USES2|USESSP }, /* mac.l @rm+,@rn+ */
1670*3d8817e4Smiod };
1671*3d8817e4Smiod
1672*3d8817e4Smiod static const struct sh_minor_opcode sh_opcode0[] =
1673*3d8817e4Smiod {
1674*3d8817e4Smiod { MAP (sh_opcode00), 0xffff },
1675*3d8817e4Smiod { MAP (sh_opcode01), 0xf0ff },
1676*3d8817e4Smiod { MAP (sh_opcode02), 0xf00f }
1677*3d8817e4Smiod };
1678*3d8817e4Smiod
1679*3d8817e4Smiod static const struct sh_opcode sh_opcode10[] =
1680*3d8817e4Smiod {
1681*3d8817e4Smiod { 0x1000, STORE | USES1 | USES2 } /* mov.l rm,@(disp,rn) */
1682*3d8817e4Smiod };
1683*3d8817e4Smiod
1684*3d8817e4Smiod static const struct sh_minor_opcode sh_opcode1[] =
1685*3d8817e4Smiod {
1686*3d8817e4Smiod { MAP (sh_opcode10), 0xf000 }
1687*3d8817e4Smiod };
1688*3d8817e4Smiod
1689*3d8817e4Smiod static const struct sh_opcode sh_opcode20[] =
1690*3d8817e4Smiod {
1691*3d8817e4Smiod { 0x2000, STORE | USES1 | USES2 }, /* mov.b rm,@rn */
1692*3d8817e4Smiod { 0x2001, STORE | USES1 | USES2 }, /* mov.w rm,@rn */
1693*3d8817e4Smiod { 0x2002, STORE | USES1 | USES2 }, /* mov.l rm,@rn */
1694*3d8817e4Smiod { 0x2004, STORE | SETS1 | USES1 | USES2 }, /* mov.b rm,@-rn */
1695*3d8817e4Smiod { 0x2005, STORE | SETS1 | USES1 | USES2 }, /* mov.w rm,@-rn */
1696*3d8817e4Smiod { 0x2006, STORE | SETS1 | USES1 | USES2 }, /* mov.l rm,@-rn */
1697*3d8817e4Smiod { 0x2007, SETSSP | USES1 | USES2 | USESSP }, /* div0s */
1698*3d8817e4Smiod { 0x2008, SETSSP | USES1 | USES2 }, /* tst rm,rn */
1699*3d8817e4Smiod { 0x2009, SETS1 | USES1 | USES2 }, /* and rm,rn */
1700*3d8817e4Smiod { 0x200a, SETS1 | USES1 | USES2 }, /* xor rm,rn */
1701*3d8817e4Smiod { 0x200b, SETS1 | USES1 | USES2 }, /* or rm,rn */
1702*3d8817e4Smiod { 0x200c, SETSSP | USES1 | USES2 }, /* cmp/str rm,rn */
1703*3d8817e4Smiod { 0x200d, SETS1 | USES1 | USES2 }, /* xtrct rm,rn */
1704*3d8817e4Smiod { 0x200e, SETSSP | USES1 | USES2 }, /* mulu.w rm,rn */
1705*3d8817e4Smiod { 0x200f, SETSSP | USES1 | USES2 } /* muls.w rm,rn */
1706*3d8817e4Smiod };
1707*3d8817e4Smiod
1708*3d8817e4Smiod static const struct sh_minor_opcode sh_opcode2[] =
1709*3d8817e4Smiod {
1710*3d8817e4Smiod { MAP (sh_opcode20), 0xf00f }
1711*3d8817e4Smiod };
1712*3d8817e4Smiod
1713*3d8817e4Smiod static const struct sh_opcode sh_opcode30[] =
1714*3d8817e4Smiod {
1715*3d8817e4Smiod { 0x3000, SETSSP | USES1 | USES2 }, /* cmp/eq rm,rn */
1716*3d8817e4Smiod { 0x3002, SETSSP | USES1 | USES2 }, /* cmp/hs rm,rn */
1717*3d8817e4Smiod { 0x3003, SETSSP | USES1 | USES2 }, /* cmp/ge rm,rn */
1718*3d8817e4Smiod { 0x3004, SETSSP | USESSP | USES1 | USES2 }, /* div1 rm,rn */
1719*3d8817e4Smiod { 0x3005, SETSSP | USES1 | USES2 }, /* dmulu.l rm,rn */
1720*3d8817e4Smiod { 0x3006, SETSSP | USES1 | USES2 }, /* cmp/hi rm,rn */
1721*3d8817e4Smiod { 0x3007, SETSSP | USES1 | USES2 }, /* cmp/gt rm,rn */
1722*3d8817e4Smiod { 0x3008, SETS1 | USES1 | USES2 }, /* sub rm,rn */
1723*3d8817e4Smiod { 0x300a, SETS1 | SETSSP | USES1 | USES2 | USESSP }, /* subc rm,rn */
1724*3d8817e4Smiod { 0x300b, SETS1 | SETSSP | USES1 | USES2 }, /* subv rm,rn */
1725*3d8817e4Smiod { 0x300c, SETS1 | USES1 | USES2 }, /* add rm,rn */
1726*3d8817e4Smiod { 0x300d, SETSSP | USES1 | USES2 }, /* dmuls.l rm,rn */
1727*3d8817e4Smiod { 0x300e, SETS1 | SETSSP | USES1 | USES2 | USESSP }, /* addc rm,rn */
1728*3d8817e4Smiod { 0x300f, SETS1 | SETSSP | USES1 | USES2 } /* addv rm,rn */
1729*3d8817e4Smiod };
1730*3d8817e4Smiod
1731*3d8817e4Smiod static const struct sh_minor_opcode sh_opcode3[] =
1732*3d8817e4Smiod {
1733*3d8817e4Smiod { MAP (sh_opcode30), 0xf00f }
1734*3d8817e4Smiod };
1735*3d8817e4Smiod
1736*3d8817e4Smiod static const struct sh_opcode sh_opcode40[] =
1737*3d8817e4Smiod {
1738*3d8817e4Smiod { 0x4000, SETS1 | SETSSP | USES1 }, /* shll rn */
1739*3d8817e4Smiod { 0x4001, SETS1 | SETSSP | USES1 }, /* shlr rn */
1740*3d8817e4Smiod { 0x4002, STORE | SETS1 | USES1 | USESSP }, /* sts.l mach,@-rn */
1741*3d8817e4Smiod { 0x4004, SETS1 | SETSSP | USES1 }, /* rotl rn */
1742*3d8817e4Smiod { 0x4005, SETS1 | SETSSP | USES1 }, /* rotr rn */
1743*3d8817e4Smiod { 0x4006, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,mach */
1744*3d8817e4Smiod { 0x4008, SETS1 | USES1 }, /* shll2 rn */
1745*3d8817e4Smiod { 0x4009, SETS1 | USES1 }, /* shlr2 rn */
1746*3d8817e4Smiod { 0x400a, SETSSP | USES1 }, /* lds rm,mach */
1747*3d8817e4Smiod { 0x400b, BRANCH | DELAY | USES1 }, /* jsr @rn */
1748*3d8817e4Smiod { 0x4010, SETS1 | SETSSP | USES1 }, /* dt rn */
1749*3d8817e4Smiod { 0x4011, SETSSP | USES1 }, /* cmp/pz rn */
1750*3d8817e4Smiod { 0x4012, STORE | SETS1 | USES1 | USESSP }, /* sts.l macl,@-rn */
1751*3d8817e4Smiod { 0x4014, SETSSP | USES1 }, /* setrc rm */
1752*3d8817e4Smiod { 0x4015, SETSSP | USES1 }, /* cmp/pl rn */
1753*3d8817e4Smiod { 0x4016, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,macl */
1754*3d8817e4Smiod { 0x4018, SETS1 | USES1 }, /* shll8 rn */
1755*3d8817e4Smiod { 0x4019, SETS1 | USES1 }, /* shlr8 rn */
1756*3d8817e4Smiod { 0x401a, SETSSP | USES1 }, /* lds rm,macl */
1757*3d8817e4Smiod { 0x401b, LOAD | SETSSP | USES1 }, /* tas.b @rn */
1758*3d8817e4Smiod { 0x4020, SETS1 | SETSSP | USES1 }, /* shal rn */
1759*3d8817e4Smiod { 0x4021, SETS1 | SETSSP | USES1 }, /* shar rn */
1760*3d8817e4Smiod { 0x4022, STORE | SETS1 | USES1 | USESSP }, /* sts.l pr,@-rn */
1761*3d8817e4Smiod { 0x4024, SETS1 | SETSSP | USES1 | USESSP }, /* rotcl rn */
1762*3d8817e4Smiod { 0x4025, SETS1 | SETSSP | USES1 | USESSP }, /* rotcr rn */
1763*3d8817e4Smiod { 0x4026, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,pr */
1764*3d8817e4Smiod { 0x4028, SETS1 | USES1 }, /* shll16 rn */
1765*3d8817e4Smiod { 0x4029, SETS1 | USES1 }, /* shlr16 rn */
1766*3d8817e4Smiod { 0x402a, SETSSP | USES1 }, /* lds rm,pr */
1767*3d8817e4Smiod { 0x402b, BRANCH | DELAY | USES1 }, /* jmp @rn */
1768*3d8817e4Smiod { 0x4052, STORE | SETS1 | USES1 | USESSP }, /* sts.l fpul,@-rn */
1769*3d8817e4Smiod { 0x4056, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,fpul */
1770*3d8817e4Smiod { 0x405a, SETSSP | USES1 }, /* lds.l rm,fpul */
1771*3d8817e4Smiod { 0x4062, STORE | SETS1 | USES1 | USESSP }, /* sts.l fpscr / dsr,@-rn */
1772*3d8817e4Smiod { 0x4066, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,fpscr / dsr */
1773*3d8817e4Smiod { 0x406a, SETSSP | USES1 }, /* lds rm,fpscr / lds rm,dsr */
1774*3d8817e4Smiod { 0x4072, STORE | SETS1 | USES1 | USESSP }, /* sts.l a0,@-rn */
1775*3d8817e4Smiod { 0x4076, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,a0 */
1776*3d8817e4Smiod { 0x407a, SETSSP | USES1 }, /* lds.l rm,a0 */
1777*3d8817e4Smiod { 0x4082, STORE | SETS1 | USES1 | USESSP }, /* sts.l x0,@-rn */
1778*3d8817e4Smiod { 0x4086, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,x0 */
1779*3d8817e4Smiod { 0x408a, SETSSP | USES1 }, /* lds.l rm,x0 */
1780*3d8817e4Smiod { 0x4092, STORE | SETS1 | USES1 | USESSP }, /* sts.l x1,@-rn */
1781*3d8817e4Smiod { 0x4096, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,x1 */
1782*3d8817e4Smiod { 0x409a, SETSSP | USES1 }, /* lds.l rm,x1 */
1783*3d8817e4Smiod { 0x40a2, STORE | SETS1 | USES1 | USESSP }, /* sts.l y0,@-rn */
1784*3d8817e4Smiod { 0x40a6, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,y0 */
1785*3d8817e4Smiod { 0x40aa, SETSSP | USES1 }, /* lds.l rm,y0 */
1786*3d8817e4Smiod { 0x40b2, STORE | SETS1 | USES1 | USESSP }, /* sts.l y1,@-rn */
1787*3d8817e4Smiod { 0x40b6, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,y1 */
1788*3d8817e4Smiod { 0x40ba, SETSSP | USES1 } /* lds.l rm,y1 */
1789*3d8817e4Smiod };
1790*3d8817e4Smiod
1791*3d8817e4Smiod static const struct sh_opcode sh_opcode41[] =
1792*3d8817e4Smiod {
1793*3d8817e4Smiod { 0x4003, STORE | SETS1 | USES1 | USESSP }, /* stc.l <special_reg>,@-rn */
1794*3d8817e4Smiod { 0x4007, LOAD | SETS1 | SETSSP | USES1 }, /* ldc.l @rm+,<special_reg> */
1795*3d8817e4Smiod { 0x400c, SETS1 | USES1 | USES2 }, /* shad rm,rn */
1796*3d8817e4Smiod { 0x400d, SETS1 | USES1 | USES2 }, /* shld rm,rn */
1797*3d8817e4Smiod { 0x400e, SETSSP | USES1 }, /* ldc rm,<special_reg> */
1798*3d8817e4Smiod { 0x400f, LOAD|SETS1|SETS2|SETSSP|USES1|USES2|USESSP }, /* mac.w @rm+,@rn+ */
1799*3d8817e4Smiod };
1800*3d8817e4Smiod
1801*3d8817e4Smiod static const struct sh_minor_opcode sh_opcode4[] =
1802*3d8817e4Smiod {
1803*3d8817e4Smiod { MAP (sh_opcode40), 0xf0ff },
1804*3d8817e4Smiod { MAP (sh_opcode41), 0xf00f }
1805*3d8817e4Smiod };
1806*3d8817e4Smiod
1807*3d8817e4Smiod static const struct sh_opcode sh_opcode50[] =
1808*3d8817e4Smiod {
1809*3d8817e4Smiod { 0x5000, LOAD | SETS1 | USES2 } /* mov.l @(disp,rm),rn */
1810*3d8817e4Smiod };
1811*3d8817e4Smiod
1812*3d8817e4Smiod static const struct sh_minor_opcode sh_opcode5[] =
1813*3d8817e4Smiod {
1814*3d8817e4Smiod { MAP (sh_opcode50), 0xf000 }
1815*3d8817e4Smiod };
1816*3d8817e4Smiod
1817*3d8817e4Smiod static const struct sh_opcode sh_opcode60[] =
1818*3d8817e4Smiod {
1819*3d8817e4Smiod { 0x6000, LOAD | SETS1 | USES2 }, /* mov.b @rm,rn */
1820*3d8817e4Smiod { 0x6001, LOAD | SETS1 | USES2 }, /* mov.w @rm,rn */
1821*3d8817e4Smiod { 0x6002, LOAD | SETS1 | USES2 }, /* mov.l @rm,rn */
1822*3d8817e4Smiod { 0x6003, SETS1 | USES2 }, /* mov rm,rn */
1823*3d8817e4Smiod { 0x6004, LOAD | SETS1 | SETS2 | USES2 }, /* mov.b @rm+,rn */
1824*3d8817e4Smiod { 0x6005, LOAD | SETS1 | SETS2 | USES2 }, /* mov.w @rm+,rn */
1825*3d8817e4Smiod { 0x6006, LOAD | SETS1 | SETS2 | USES2 }, /* mov.l @rm+,rn */
1826*3d8817e4Smiod { 0x6007, SETS1 | USES2 }, /* not rm,rn */
1827*3d8817e4Smiod { 0x6008, SETS1 | USES2 }, /* swap.b rm,rn */
1828*3d8817e4Smiod { 0x6009, SETS1 | USES2 }, /* swap.w rm,rn */
1829*3d8817e4Smiod { 0x600a, SETS1 | SETSSP | USES2 | USESSP }, /* negc rm,rn */
1830*3d8817e4Smiod { 0x600b, SETS1 | USES2 }, /* neg rm,rn */
1831*3d8817e4Smiod { 0x600c, SETS1 | USES2 }, /* extu.b rm,rn */
1832*3d8817e4Smiod { 0x600d, SETS1 | USES2 }, /* extu.w rm,rn */
1833*3d8817e4Smiod { 0x600e, SETS1 | USES2 }, /* exts.b rm,rn */
1834*3d8817e4Smiod { 0x600f, SETS1 | USES2 } /* exts.w rm,rn */
1835*3d8817e4Smiod };
1836*3d8817e4Smiod
1837*3d8817e4Smiod static const struct sh_minor_opcode sh_opcode6[] =
1838*3d8817e4Smiod {
1839*3d8817e4Smiod { MAP (sh_opcode60), 0xf00f }
1840*3d8817e4Smiod };
1841*3d8817e4Smiod
1842*3d8817e4Smiod static const struct sh_opcode sh_opcode70[] =
1843*3d8817e4Smiod {
1844*3d8817e4Smiod { 0x7000, SETS1 | USES1 } /* add #imm,rn */
1845*3d8817e4Smiod };
1846*3d8817e4Smiod
1847*3d8817e4Smiod static const struct sh_minor_opcode sh_opcode7[] =
1848*3d8817e4Smiod {
1849*3d8817e4Smiod { MAP (sh_opcode70), 0xf000 }
1850*3d8817e4Smiod };
1851*3d8817e4Smiod
1852*3d8817e4Smiod static const struct sh_opcode sh_opcode80[] =
1853*3d8817e4Smiod {
1854*3d8817e4Smiod { 0x8000, STORE | USES2 | USESR0 }, /* mov.b r0,@(disp,rn) */
1855*3d8817e4Smiod { 0x8100, STORE | USES2 | USESR0 }, /* mov.w r0,@(disp,rn) */
1856*3d8817e4Smiod { 0x8200, SETSSP }, /* setrc #imm */
1857*3d8817e4Smiod { 0x8400, LOAD | SETSR0 | USES2 }, /* mov.b @(disp,rm),r0 */
1858*3d8817e4Smiod { 0x8500, LOAD | SETSR0 | USES2 }, /* mov.w @(disp,rn),r0 */
1859*3d8817e4Smiod { 0x8800, SETSSP | USESR0 }, /* cmp/eq #imm,r0 */
1860*3d8817e4Smiod { 0x8900, BRANCH | USESSP }, /* bt label */
1861*3d8817e4Smiod { 0x8b00, BRANCH | USESSP }, /* bf label */
1862*3d8817e4Smiod { 0x8c00, SETSSP }, /* ldrs @(disp,pc) */
1863*3d8817e4Smiod { 0x8d00, BRANCH | DELAY | USESSP }, /* bt/s label */
1864*3d8817e4Smiod { 0x8e00, SETSSP }, /* ldre @(disp,pc) */
1865*3d8817e4Smiod { 0x8f00, BRANCH | DELAY | USESSP } /* bf/s label */
1866*3d8817e4Smiod };
1867*3d8817e4Smiod
1868*3d8817e4Smiod static const struct sh_minor_opcode sh_opcode8[] =
1869*3d8817e4Smiod {
1870*3d8817e4Smiod { MAP (sh_opcode80), 0xff00 }
1871*3d8817e4Smiod };
1872*3d8817e4Smiod
1873*3d8817e4Smiod static const struct sh_opcode sh_opcode90[] =
1874*3d8817e4Smiod {
1875*3d8817e4Smiod { 0x9000, LOAD | SETS1 } /* mov.w @(disp,pc),rn */
1876*3d8817e4Smiod };
1877*3d8817e4Smiod
1878*3d8817e4Smiod static const struct sh_minor_opcode sh_opcode9[] =
1879*3d8817e4Smiod {
1880*3d8817e4Smiod { MAP (sh_opcode90), 0xf000 }
1881*3d8817e4Smiod };
1882*3d8817e4Smiod
1883*3d8817e4Smiod static const struct sh_opcode sh_opcodea0[] =
1884*3d8817e4Smiod {
1885*3d8817e4Smiod { 0xa000, BRANCH | DELAY } /* bra label */
1886*3d8817e4Smiod };
1887*3d8817e4Smiod
1888*3d8817e4Smiod static const struct sh_minor_opcode sh_opcodea[] =
1889*3d8817e4Smiod {
1890*3d8817e4Smiod { MAP (sh_opcodea0), 0xf000 }
1891*3d8817e4Smiod };
1892*3d8817e4Smiod
1893*3d8817e4Smiod static const struct sh_opcode sh_opcodeb0[] =
1894*3d8817e4Smiod {
1895*3d8817e4Smiod { 0xb000, BRANCH | DELAY } /* bsr label */
1896*3d8817e4Smiod };
1897*3d8817e4Smiod
1898*3d8817e4Smiod static const struct sh_minor_opcode sh_opcodeb[] =
1899*3d8817e4Smiod {
1900*3d8817e4Smiod { MAP (sh_opcodeb0), 0xf000 }
1901*3d8817e4Smiod };
1902*3d8817e4Smiod
1903*3d8817e4Smiod static const struct sh_opcode sh_opcodec0[] =
1904*3d8817e4Smiod {
1905*3d8817e4Smiod { 0xc000, STORE | USESR0 | USESSP }, /* mov.b r0,@(disp,gbr) */
1906*3d8817e4Smiod { 0xc100, STORE | USESR0 | USESSP }, /* mov.w r0,@(disp,gbr) */
1907*3d8817e4Smiod { 0xc200, STORE | USESR0 | USESSP }, /* mov.l r0,@(disp,gbr) */
1908*3d8817e4Smiod { 0xc300, BRANCH | USESSP }, /* trapa #imm */
1909*3d8817e4Smiod { 0xc400, LOAD | SETSR0 | USESSP }, /* mov.b @(disp,gbr),r0 */
1910*3d8817e4Smiod { 0xc500, LOAD | SETSR0 | USESSP }, /* mov.w @(disp,gbr),r0 */
1911*3d8817e4Smiod { 0xc600, LOAD | SETSR0 | USESSP }, /* mov.l @(disp,gbr),r0 */
1912*3d8817e4Smiod { 0xc700, SETSR0 }, /* mova @(disp,pc),r0 */
1913*3d8817e4Smiod { 0xc800, SETSSP | USESR0 }, /* tst #imm,r0 */
1914*3d8817e4Smiod { 0xc900, SETSR0 | USESR0 }, /* and #imm,r0 */
1915*3d8817e4Smiod { 0xca00, SETSR0 | USESR0 }, /* xor #imm,r0 */
1916*3d8817e4Smiod { 0xcb00, SETSR0 | USESR0 }, /* or #imm,r0 */
1917*3d8817e4Smiod { 0xcc00, LOAD | SETSSP | USESR0 | USESSP }, /* tst.b #imm,@(r0,gbr) */
1918*3d8817e4Smiod { 0xcd00, LOAD | STORE | USESR0 | USESSP }, /* and.b #imm,@(r0,gbr) */
1919*3d8817e4Smiod { 0xce00, LOAD | STORE | USESR0 | USESSP }, /* xor.b #imm,@(r0,gbr) */
1920*3d8817e4Smiod { 0xcf00, LOAD | STORE | USESR0 | USESSP } /* or.b #imm,@(r0,gbr) */
1921*3d8817e4Smiod };
1922*3d8817e4Smiod
1923*3d8817e4Smiod static const struct sh_minor_opcode sh_opcodec[] =
1924*3d8817e4Smiod {
1925*3d8817e4Smiod { MAP (sh_opcodec0), 0xff00 }
1926*3d8817e4Smiod };
1927*3d8817e4Smiod
1928*3d8817e4Smiod static const struct sh_opcode sh_opcoded0[] =
1929*3d8817e4Smiod {
1930*3d8817e4Smiod { 0xd000, LOAD | SETS1 } /* mov.l @(disp,pc),rn */
1931*3d8817e4Smiod };
1932*3d8817e4Smiod
1933*3d8817e4Smiod static const struct sh_minor_opcode sh_opcoded[] =
1934*3d8817e4Smiod {
1935*3d8817e4Smiod { MAP (sh_opcoded0), 0xf000 }
1936*3d8817e4Smiod };
1937*3d8817e4Smiod
1938*3d8817e4Smiod static const struct sh_opcode sh_opcodee0[] =
1939*3d8817e4Smiod {
1940*3d8817e4Smiod { 0xe000, SETS1 } /* mov #imm,rn */
1941*3d8817e4Smiod };
1942*3d8817e4Smiod
1943*3d8817e4Smiod static const struct sh_minor_opcode sh_opcodee[] =
1944*3d8817e4Smiod {
1945*3d8817e4Smiod { MAP (sh_opcodee0), 0xf000 }
1946*3d8817e4Smiod };
1947*3d8817e4Smiod
1948*3d8817e4Smiod static const struct sh_opcode sh_opcodef0[] =
1949*3d8817e4Smiod {
1950*3d8817e4Smiod { 0xf000, SETSF1 | USESF1 | USESF2 }, /* fadd fm,fn */
1951*3d8817e4Smiod { 0xf001, SETSF1 | USESF1 | USESF2 }, /* fsub fm,fn */
1952*3d8817e4Smiod { 0xf002, SETSF1 | USESF1 | USESF2 }, /* fmul fm,fn */
1953*3d8817e4Smiod { 0xf003, SETSF1 | USESF1 | USESF2 }, /* fdiv fm,fn */
1954*3d8817e4Smiod { 0xf004, SETSSP | USESF1 | USESF2 }, /* fcmp/eq fm,fn */
1955*3d8817e4Smiod { 0xf005, SETSSP | USESF1 | USESF2 }, /* fcmp/gt fm,fn */
1956*3d8817e4Smiod { 0xf006, LOAD | SETSF1 | USES2 | USESR0 }, /* fmov.s @(r0,rm),fn */
1957*3d8817e4Smiod { 0xf007, STORE | USES1 | USESF2 | USESR0 }, /* fmov.s fm,@(r0,rn) */
1958*3d8817e4Smiod { 0xf008, LOAD | SETSF1 | USES2 }, /* fmov.s @rm,fn */
1959*3d8817e4Smiod { 0xf009, LOAD | SETS2 | SETSF1 | USES2 }, /* fmov.s @rm+,fn */
1960*3d8817e4Smiod { 0xf00a, STORE | USES1 | USESF2 }, /* fmov.s fm,@rn */
1961*3d8817e4Smiod { 0xf00b, STORE | SETS1 | USES1 | USESF2 }, /* fmov.s fm,@-rn */
1962*3d8817e4Smiod { 0xf00c, SETSF1 | USESF2 }, /* fmov fm,fn */
1963*3d8817e4Smiod { 0xf00e, SETSF1 | USESF1 | USESF2 | USESF0 } /* fmac f0,fm,fn */
1964*3d8817e4Smiod };
1965*3d8817e4Smiod
1966*3d8817e4Smiod static const struct sh_opcode sh_opcodef1[] =
1967*3d8817e4Smiod {
1968*3d8817e4Smiod { 0xf00d, SETSF1 | USESSP }, /* fsts fpul,fn */
1969*3d8817e4Smiod { 0xf01d, SETSSP | USESF1 }, /* flds fn,fpul */
1970*3d8817e4Smiod { 0xf02d, SETSF1 | USESSP }, /* float fpul,fn */
1971*3d8817e4Smiod { 0xf03d, SETSSP | USESF1 }, /* ftrc fn,fpul */
1972*3d8817e4Smiod { 0xf04d, SETSF1 | USESF1 }, /* fneg fn */
1973*3d8817e4Smiod { 0xf05d, SETSF1 | USESF1 }, /* fabs fn */
1974*3d8817e4Smiod { 0xf06d, SETSF1 | USESF1 }, /* fsqrt fn */
1975*3d8817e4Smiod { 0xf07d, SETSSP | USESF1 }, /* ftst/nan fn */
1976*3d8817e4Smiod { 0xf08d, SETSF1 }, /* fldi0 fn */
1977*3d8817e4Smiod { 0xf09d, SETSF1 } /* fldi1 fn */
1978*3d8817e4Smiod };
1979*3d8817e4Smiod
1980*3d8817e4Smiod static const struct sh_minor_opcode sh_opcodef[] =
1981*3d8817e4Smiod {
1982*3d8817e4Smiod { MAP (sh_opcodef0), 0xf00f },
1983*3d8817e4Smiod { MAP (sh_opcodef1), 0xf0ff }
1984*3d8817e4Smiod };
1985*3d8817e4Smiod
1986*3d8817e4Smiod static struct sh_major_opcode sh_opcodes[] =
1987*3d8817e4Smiod {
1988*3d8817e4Smiod { MAP (sh_opcode0) },
1989*3d8817e4Smiod { MAP (sh_opcode1) },
1990*3d8817e4Smiod { MAP (sh_opcode2) },
1991*3d8817e4Smiod { MAP (sh_opcode3) },
1992*3d8817e4Smiod { MAP (sh_opcode4) },
1993*3d8817e4Smiod { MAP (sh_opcode5) },
1994*3d8817e4Smiod { MAP (sh_opcode6) },
1995*3d8817e4Smiod { MAP (sh_opcode7) },
1996*3d8817e4Smiod { MAP (sh_opcode8) },
1997*3d8817e4Smiod { MAP (sh_opcode9) },
1998*3d8817e4Smiod { MAP (sh_opcodea) },
1999*3d8817e4Smiod { MAP (sh_opcodeb) },
2000*3d8817e4Smiod { MAP (sh_opcodec) },
2001*3d8817e4Smiod { MAP (sh_opcoded) },
2002*3d8817e4Smiod { MAP (sh_opcodee) },
2003*3d8817e4Smiod { MAP (sh_opcodef) }
2004*3d8817e4Smiod };
2005*3d8817e4Smiod
2006*3d8817e4Smiod /* The double data transfer / parallel processing insns are not
2007*3d8817e4Smiod described here. This will cause sh_align_load_span to leave them alone. */
2008*3d8817e4Smiod
2009*3d8817e4Smiod static const struct sh_opcode sh_dsp_opcodef0[] =
2010*3d8817e4Smiod {
2011*3d8817e4Smiod { 0xf400, USESAS | SETSAS | LOAD | SETSSP }, /* movs.x @-as,ds */
2012*3d8817e4Smiod { 0xf401, USESAS | SETSAS | STORE | USESSP }, /* movs.x ds,@-as */
2013*3d8817e4Smiod { 0xf404, USESAS | LOAD | SETSSP }, /* movs.x @as,ds */
2014*3d8817e4Smiod { 0xf405, USESAS | STORE | USESSP }, /* movs.x ds,@as */
2015*3d8817e4Smiod { 0xf408, USESAS | SETSAS | LOAD | SETSSP }, /* movs.x @as+,ds */
2016*3d8817e4Smiod { 0xf409, USESAS | SETSAS | STORE | USESSP }, /* movs.x ds,@as+ */
2017*3d8817e4Smiod { 0xf40c, USESAS | SETSAS | LOAD | SETSSP | USESR8 }, /* movs.x @as+r8,ds */
2018*3d8817e4Smiod { 0xf40d, USESAS | SETSAS | STORE | USESSP | USESR8 } /* movs.x ds,@as+r8 */
2019*3d8817e4Smiod };
2020*3d8817e4Smiod
2021*3d8817e4Smiod static const struct sh_minor_opcode sh_dsp_opcodef[] =
2022*3d8817e4Smiod {
2023*3d8817e4Smiod { MAP (sh_dsp_opcodef0), 0xfc0d }
2024*3d8817e4Smiod };
2025*3d8817e4Smiod
2026*3d8817e4Smiod /* Given an instruction, return a pointer to the corresponding
2027*3d8817e4Smiod sh_opcode structure. Return NULL if the instruction is not
2028*3d8817e4Smiod recognized. */
2029*3d8817e4Smiod
2030*3d8817e4Smiod static const struct sh_opcode *
sh_insn_info(insn)2031*3d8817e4Smiod sh_insn_info (insn)
2032*3d8817e4Smiod unsigned int insn;
2033*3d8817e4Smiod {
2034*3d8817e4Smiod const struct sh_major_opcode *maj;
2035*3d8817e4Smiod const struct sh_minor_opcode *min, *minend;
2036*3d8817e4Smiod
2037*3d8817e4Smiod maj = &sh_opcodes[(insn & 0xf000) >> 12];
2038*3d8817e4Smiod min = maj->minor_opcodes;
2039*3d8817e4Smiod minend = min + maj->count;
2040*3d8817e4Smiod for (; min < minend; min++)
2041*3d8817e4Smiod {
2042*3d8817e4Smiod unsigned int l;
2043*3d8817e4Smiod const struct sh_opcode *op, *opend;
2044*3d8817e4Smiod
2045*3d8817e4Smiod l = insn & min->mask;
2046*3d8817e4Smiod op = min->opcodes;
2047*3d8817e4Smiod opend = op + min->count;
2048*3d8817e4Smiod
2049*3d8817e4Smiod /* Since the opcodes tables are sorted, we could use a binary
2050*3d8817e4Smiod search here if the count were above some cutoff value. */
2051*3d8817e4Smiod for (; op < opend; op++)
2052*3d8817e4Smiod if (op->opcode == l)
2053*3d8817e4Smiod return op;
2054*3d8817e4Smiod }
2055*3d8817e4Smiod
2056*3d8817e4Smiod return NULL;
2057*3d8817e4Smiod }
2058*3d8817e4Smiod
2059*3d8817e4Smiod /* See whether an instruction uses or sets a general purpose register */
2060*3d8817e4Smiod
2061*3d8817e4Smiod static bfd_boolean
sh_insn_uses_or_sets_reg(insn,op,reg)2062*3d8817e4Smiod sh_insn_uses_or_sets_reg (insn, op, reg)
2063*3d8817e4Smiod unsigned int insn;
2064*3d8817e4Smiod const struct sh_opcode *op;
2065*3d8817e4Smiod unsigned int reg;
2066*3d8817e4Smiod {
2067*3d8817e4Smiod if (sh_insn_uses_reg (insn, op, reg))
2068*3d8817e4Smiod return TRUE;
2069*3d8817e4Smiod
2070*3d8817e4Smiod return sh_insn_sets_reg (insn, op, reg);
2071*3d8817e4Smiod }
2072*3d8817e4Smiod
2073*3d8817e4Smiod /* See whether an instruction uses a general purpose register. */
2074*3d8817e4Smiod
2075*3d8817e4Smiod static bfd_boolean
sh_insn_uses_reg(insn,op,reg)2076*3d8817e4Smiod sh_insn_uses_reg (insn, op, reg)
2077*3d8817e4Smiod unsigned int insn;
2078*3d8817e4Smiod const struct sh_opcode *op;
2079*3d8817e4Smiod unsigned int reg;
2080*3d8817e4Smiod {
2081*3d8817e4Smiod unsigned int f;
2082*3d8817e4Smiod
2083*3d8817e4Smiod f = op->flags;
2084*3d8817e4Smiod
2085*3d8817e4Smiod if ((f & USES1) != 0
2086*3d8817e4Smiod && USES1_REG (insn) == reg)
2087*3d8817e4Smiod return TRUE;
2088*3d8817e4Smiod if ((f & USES2) != 0
2089*3d8817e4Smiod && USES2_REG (insn) == reg)
2090*3d8817e4Smiod return TRUE;
2091*3d8817e4Smiod if ((f & USESR0) != 0
2092*3d8817e4Smiod && reg == 0)
2093*3d8817e4Smiod return TRUE;
2094*3d8817e4Smiod if ((f & USESAS) && reg == USESAS_REG (insn))
2095*3d8817e4Smiod return TRUE;
2096*3d8817e4Smiod if ((f & USESR8) && reg == 8)
2097*3d8817e4Smiod return TRUE;
2098*3d8817e4Smiod
2099*3d8817e4Smiod return FALSE;
2100*3d8817e4Smiod }
2101*3d8817e4Smiod
2102*3d8817e4Smiod /* See whether an instruction sets a general purpose register. */
2103*3d8817e4Smiod
2104*3d8817e4Smiod static bfd_boolean
sh_insn_sets_reg(insn,op,reg)2105*3d8817e4Smiod sh_insn_sets_reg (insn, op, reg)
2106*3d8817e4Smiod unsigned int insn;
2107*3d8817e4Smiod const struct sh_opcode *op;
2108*3d8817e4Smiod unsigned int reg;
2109*3d8817e4Smiod {
2110*3d8817e4Smiod unsigned int f;
2111*3d8817e4Smiod
2112*3d8817e4Smiod f = op->flags;
2113*3d8817e4Smiod
2114*3d8817e4Smiod if ((f & SETS1) != 0
2115*3d8817e4Smiod && SETS1_REG (insn) == reg)
2116*3d8817e4Smiod return TRUE;
2117*3d8817e4Smiod if ((f & SETS2) != 0
2118*3d8817e4Smiod && SETS2_REG (insn) == reg)
2119*3d8817e4Smiod return TRUE;
2120*3d8817e4Smiod if ((f & SETSR0) != 0
2121*3d8817e4Smiod && reg == 0)
2122*3d8817e4Smiod return TRUE;
2123*3d8817e4Smiod if ((f & SETSAS) && reg == SETSAS_REG (insn))
2124*3d8817e4Smiod return TRUE;
2125*3d8817e4Smiod
2126*3d8817e4Smiod return FALSE;
2127*3d8817e4Smiod }
2128*3d8817e4Smiod
2129*3d8817e4Smiod /* See whether an instruction uses or sets a floating point register */
2130*3d8817e4Smiod
2131*3d8817e4Smiod static bfd_boolean
sh_insn_uses_or_sets_freg(insn,op,reg)2132*3d8817e4Smiod sh_insn_uses_or_sets_freg (insn, op, reg)
2133*3d8817e4Smiod unsigned int insn;
2134*3d8817e4Smiod const struct sh_opcode *op;
2135*3d8817e4Smiod unsigned int reg;
2136*3d8817e4Smiod {
2137*3d8817e4Smiod if (sh_insn_uses_freg (insn, op, reg))
2138*3d8817e4Smiod return TRUE;
2139*3d8817e4Smiod
2140*3d8817e4Smiod return sh_insn_sets_freg (insn, op, reg);
2141*3d8817e4Smiod }
2142*3d8817e4Smiod
2143*3d8817e4Smiod /* See whether an instruction uses a floating point register. */
2144*3d8817e4Smiod
2145*3d8817e4Smiod static bfd_boolean
sh_insn_uses_freg(insn,op,freg)2146*3d8817e4Smiod sh_insn_uses_freg (insn, op, freg)
2147*3d8817e4Smiod unsigned int insn;
2148*3d8817e4Smiod const struct sh_opcode *op;
2149*3d8817e4Smiod unsigned int freg;
2150*3d8817e4Smiod {
2151*3d8817e4Smiod unsigned int f;
2152*3d8817e4Smiod
2153*3d8817e4Smiod f = op->flags;
2154*3d8817e4Smiod
2155*3d8817e4Smiod /* We can't tell if this is a double-precision insn, so just play safe
2156*3d8817e4Smiod and assume that it might be. So not only have we test FREG against
2157*3d8817e4Smiod itself, but also even FREG against FREG+1 - if the using insn uses
2158*3d8817e4Smiod just the low part of a double precision value - but also an odd
2159*3d8817e4Smiod FREG against FREG-1 - if the setting insn sets just the low part
2160*3d8817e4Smiod of a double precision value.
2161*3d8817e4Smiod So what this all boils down to is that we have to ignore the lowest
2162*3d8817e4Smiod bit of the register number. */
2163*3d8817e4Smiod
2164*3d8817e4Smiod if ((f & USESF1) != 0
2165*3d8817e4Smiod && (USESF1_REG (insn) & 0xe) == (freg & 0xe))
2166*3d8817e4Smiod return TRUE;
2167*3d8817e4Smiod if ((f & USESF2) != 0
2168*3d8817e4Smiod && (USESF2_REG (insn) & 0xe) == (freg & 0xe))
2169*3d8817e4Smiod return TRUE;
2170*3d8817e4Smiod if ((f & USESF0) != 0
2171*3d8817e4Smiod && freg == 0)
2172*3d8817e4Smiod return TRUE;
2173*3d8817e4Smiod
2174*3d8817e4Smiod return FALSE;
2175*3d8817e4Smiod }
2176*3d8817e4Smiod
2177*3d8817e4Smiod /* See whether an instruction sets a floating point register. */
2178*3d8817e4Smiod
2179*3d8817e4Smiod static bfd_boolean
sh_insn_sets_freg(insn,op,freg)2180*3d8817e4Smiod sh_insn_sets_freg (insn, op, freg)
2181*3d8817e4Smiod unsigned int insn;
2182*3d8817e4Smiod const struct sh_opcode *op;
2183*3d8817e4Smiod unsigned int freg;
2184*3d8817e4Smiod {
2185*3d8817e4Smiod unsigned int f;
2186*3d8817e4Smiod
2187*3d8817e4Smiod f = op->flags;
2188*3d8817e4Smiod
2189*3d8817e4Smiod /* We can't tell if this is a double-precision insn, so just play safe
2190*3d8817e4Smiod and assume that it might be. So not only have we test FREG against
2191*3d8817e4Smiod itself, but also even FREG against FREG+1 - if the using insn uses
2192*3d8817e4Smiod just the low part of a double precision value - but also an odd
2193*3d8817e4Smiod FREG against FREG-1 - if the setting insn sets just the low part
2194*3d8817e4Smiod of a double precision value.
2195*3d8817e4Smiod So what this all boils down to is that we have to ignore the lowest
2196*3d8817e4Smiod bit of the register number. */
2197*3d8817e4Smiod
2198*3d8817e4Smiod if ((f & SETSF1) != 0
2199*3d8817e4Smiod && (SETSF1_REG (insn) & 0xe) == (freg & 0xe))
2200*3d8817e4Smiod return TRUE;
2201*3d8817e4Smiod
2202*3d8817e4Smiod return FALSE;
2203*3d8817e4Smiod }
2204*3d8817e4Smiod
2205*3d8817e4Smiod /* See whether instructions I1 and I2 conflict, assuming I1 comes
2206*3d8817e4Smiod before I2. OP1 and OP2 are the corresponding sh_opcode structures.
2207*3d8817e4Smiod This should return TRUE if there is a conflict, or FALSE if the
2208*3d8817e4Smiod instructions can be swapped safely. */
2209*3d8817e4Smiod
2210*3d8817e4Smiod static bfd_boolean
sh_insns_conflict(i1,op1,i2,op2)2211*3d8817e4Smiod sh_insns_conflict (i1, op1, i2, op2)
2212*3d8817e4Smiod unsigned int i1;
2213*3d8817e4Smiod const struct sh_opcode *op1;
2214*3d8817e4Smiod unsigned int i2;
2215*3d8817e4Smiod const struct sh_opcode *op2;
2216*3d8817e4Smiod {
2217*3d8817e4Smiod unsigned int f1, f2;
2218*3d8817e4Smiod
2219*3d8817e4Smiod f1 = op1->flags;
2220*3d8817e4Smiod f2 = op2->flags;
2221*3d8817e4Smiod
2222*3d8817e4Smiod /* Load of fpscr conflicts with floating point operations.
2223*3d8817e4Smiod FIXME: shouldn't test raw opcodes here. */
2224*3d8817e4Smiod if (((i1 & 0xf0ff) == 0x4066 && (i2 & 0xf000) == 0xf000)
2225*3d8817e4Smiod || ((i2 & 0xf0ff) == 0x4066 && (i1 & 0xf000) == 0xf000))
2226*3d8817e4Smiod return TRUE;
2227*3d8817e4Smiod
2228*3d8817e4Smiod if ((f1 & (BRANCH | DELAY)) != 0
2229*3d8817e4Smiod || (f2 & (BRANCH | DELAY)) != 0)
2230*3d8817e4Smiod return TRUE;
2231*3d8817e4Smiod
2232*3d8817e4Smiod if (((f1 | f2) & SETSSP)
2233*3d8817e4Smiod && (f1 & (SETSSP | USESSP))
2234*3d8817e4Smiod && (f2 & (SETSSP | USESSP)))
2235*3d8817e4Smiod return TRUE;
2236*3d8817e4Smiod
2237*3d8817e4Smiod if ((f1 & SETS1) != 0
2238*3d8817e4Smiod && sh_insn_uses_or_sets_reg (i2, op2, SETS1_REG (i1)))
2239*3d8817e4Smiod return TRUE;
2240*3d8817e4Smiod if ((f1 & SETS2) != 0
2241*3d8817e4Smiod && sh_insn_uses_or_sets_reg (i2, op2, SETS2_REG (i1)))
2242*3d8817e4Smiod return TRUE;
2243*3d8817e4Smiod if ((f1 & SETSR0) != 0
2244*3d8817e4Smiod && sh_insn_uses_or_sets_reg (i2, op2, 0))
2245*3d8817e4Smiod return TRUE;
2246*3d8817e4Smiod if ((f1 & SETSAS)
2247*3d8817e4Smiod && sh_insn_uses_or_sets_reg (i2, op2, SETSAS_REG (i1)))
2248*3d8817e4Smiod return TRUE;
2249*3d8817e4Smiod if ((f1 & SETSF1) != 0
2250*3d8817e4Smiod && sh_insn_uses_or_sets_freg (i2, op2, SETSF1_REG (i1)))
2251*3d8817e4Smiod return TRUE;
2252*3d8817e4Smiod
2253*3d8817e4Smiod if ((f2 & SETS1) != 0
2254*3d8817e4Smiod && sh_insn_uses_or_sets_reg (i1, op1, SETS1_REG (i2)))
2255*3d8817e4Smiod return TRUE;
2256*3d8817e4Smiod if ((f2 & SETS2) != 0
2257*3d8817e4Smiod && sh_insn_uses_or_sets_reg (i1, op1, SETS2_REG (i2)))
2258*3d8817e4Smiod return TRUE;
2259*3d8817e4Smiod if ((f2 & SETSR0) != 0
2260*3d8817e4Smiod && sh_insn_uses_or_sets_reg (i1, op1, 0))
2261*3d8817e4Smiod return TRUE;
2262*3d8817e4Smiod if ((f2 & SETSAS)
2263*3d8817e4Smiod && sh_insn_uses_or_sets_reg (i1, op1, SETSAS_REG (i2)))
2264*3d8817e4Smiod return TRUE;
2265*3d8817e4Smiod if ((f2 & SETSF1) != 0
2266*3d8817e4Smiod && sh_insn_uses_or_sets_freg (i1, op1, SETSF1_REG (i2)))
2267*3d8817e4Smiod return TRUE;
2268*3d8817e4Smiod
2269*3d8817e4Smiod /* The instructions do not conflict. */
2270*3d8817e4Smiod return FALSE;
2271*3d8817e4Smiod }
2272*3d8817e4Smiod
2273*3d8817e4Smiod /* I1 is a load instruction, and I2 is some other instruction. Return
2274*3d8817e4Smiod TRUE if I1 loads a register which I2 uses. */
2275*3d8817e4Smiod
2276*3d8817e4Smiod static bfd_boolean
sh_load_use(i1,op1,i2,op2)2277*3d8817e4Smiod sh_load_use (i1, op1, i2, op2)
2278*3d8817e4Smiod unsigned int i1;
2279*3d8817e4Smiod const struct sh_opcode *op1;
2280*3d8817e4Smiod unsigned int i2;
2281*3d8817e4Smiod const struct sh_opcode *op2;
2282*3d8817e4Smiod {
2283*3d8817e4Smiod unsigned int f1;
2284*3d8817e4Smiod
2285*3d8817e4Smiod f1 = op1->flags;
2286*3d8817e4Smiod
2287*3d8817e4Smiod if ((f1 & LOAD) == 0)
2288*3d8817e4Smiod return FALSE;
2289*3d8817e4Smiod
2290*3d8817e4Smiod /* If both SETS1 and SETSSP are set, that means a load to a special
2291*3d8817e4Smiod register using postincrement addressing mode, which we don't care
2292*3d8817e4Smiod about here. */
2293*3d8817e4Smiod if ((f1 & SETS1) != 0
2294*3d8817e4Smiod && (f1 & SETSSP) == 0
2295*3d8817e4Smiod && sh_insn_uses_reg (i2, op2, (i1 & 0x0f00) >> 8))
2296*3d8817e4Smiod return TRUE;
2297*3d8817e4Smiod
2298*3d8817e4Smiod if ((f1 & SETSR0) != 0
2299*3d8817e4Smiod && sh_insn_uses_reg (i2, op2, 0))
2300*3d8817e4Smiod return TRUE;
2301*3d8817e4Smiod
2302*3d8817e4Smiod if ((f1 & SETSF1) != 0
2303*3d8817e4Smiod && sh_insn_uses_freg (i2, op2, (i1 & 0x0f00) >> 8))
2304*3d8817e4Smiod return TRUE;
2305*3d8817e4Smiod
2306*3d8817e4Smiod return FALSE;
2307*3d8817e4Smiod }
2308*3d8817e4Smiod
2309*3d8817e4Smiod /* Try to align loads and stores within a span of memory. This is
2310*3d8817e4Smiod called by both the ELF and the COFF sh targets. ABFD and SEC are
2311*3d8817e4Smiod the BFD and section we are examining. CONTENTS is the contents of
2312*3d8817e4Smiod the section. SWAP is the routine to call to swap two instructions.
2313*3d8817e4Smiod RELOCS is a pointer to the internal relocation information, to be
2314*3d8817e4Smiod passed to SWAP. PLABEL is a pointer to the current label in a
2315*3d8817e4Smiod sorted list of labels; LABEL_END is the end of the list. START and
2316*3d8817e4Smiod STOP are the range of memory to examine. If a swap is made,
2317*3d8817e4Smiod *PSWAPPED is set to TRUE. */
2318*3d8817e4Smiod
2319*3d8817e4Smiod #ifdef COFF_WITH_PE
2320*3d8817e4Smiod static
2321*3d8817e4Smiod #endif
2322*3d8817e4Smiod bfd_boolean
_bfd_sh_align_load_span(abfd,sec,contents,swap,relocs,plabel,label_end,start,stop,pswapped)2323*3d8817e4Smiod _bfd_sh_align_load_span (abfd, sec, contents, swap, relocs,
2324*3d8817e4Smiod plabel, label_end, start, stop, pswapped)
2325*3d8817e4Smiod bfd *abfd;
2326*3d8817e4Smiod asection *sec;
2327*3d8817e4Smiod bfd_byte *contents;
2328*3d8817e4Smiod bfd_boolean (*swap) PARAMS ((bfd *, asection *, PTR, bfd_byte *, bfd_vma));
2329*3d8817e4Smiod PTR relocs;
2330*3d8817e4Smiod bfd_vma **plabel;
2331*3d8817e4Smiod bfd_vma *label_end;
2332*3d8817e4Smiod bfd_vma start;
2333*3d8817e4Smiod bfd_vma stop;
2334*3d8817e4Smiod bfd_boolean *pswapped;
2335*3d8817e4Smiod {
2336*3d8817e4Smiod int dsp = (abfd->arch_info->mach == bfd_mach_sh_dsp
2337*3d8817e4Smiod || abfd->arch_info->mach == bfd_mach_sh3_dsp);
2338*3d8817e4Smiod bfd_vma i;
2339*3d8817e4Smiod
2340*3d8817e4Smiod /* The SH4 has a Harvard architecture, hence aligning loads is not
2341*3d8817e4Smiod desirable. In fact, it is counter-productive, since it interferes
2342*3d8817e4Smiod with the schedules generated by the compiler. */
2343*3d8817e4Smiod if (abfd->arch_info->mach == bfd_mach_sh4)
2344*3d8817e4Smiod return TRUE;
2345*3d8817e4Smiod
2346*3d8817e4Smiod /* If we are linking sh[3]-dsp code, swap the FPU instructions for DSP
2347*3d8817e4Smiod instructions. */
2348*3d8817e4Smiod if (dsp)
2349*3d8817e4Smiod {
2350*3d8817e4Smiod sh_opcodes[0xf].minor_opcodes = sh_dsp_opcodef;
2351*3d8817e4Smiod sh_opcodes[0xf].count = sizeof sh_dsp_opcodef / sizeof sh_dsp_opcodef;
2352*3d8817e4Smiod }
2353*3d8817e4Smiod
2354*3d8817e4Smiod /* Instructions should be aligned on 2 byte boundaries. */
2355*3d8817e4Smiod if ((start & 1) == 1)
2356*3d8817e4Smiod ++start;
2357*3d8817e4Smiod
2358*3d8817e4Smiod /* Now look through the unaligned addresses. */
2359*3d8817e4Smiod i = start;
2360*3d8817e4Smiod if ((i & 2) == 0)
2361*3d8817e4Smiod i += 2;
2362*3d8817e4Smiod for (; i < stop; i += 4)
2363*3d8817e4Smiod {
2364*3d8817e4Smiod unsigned int insn;
2365*3d8817e4Smiod const struct sh_opcode *op;
2366*3d8817e4Smiod unsigned int prev_insn = 0;
2367*3d8817e4Smiod const struct sh_opcode *prev_op = NULL;
2368*3d8817e4Smiod
2369*3d8817e4Smiod insn = bfd_get_16 (abfd, contents + i);
2370*3d8817e4Smiod op = sh_insn_info (insn);
2371*3d8817e4Smiod if (op == NULL
2372*3d8817e4Smiod || (op->flags & (LOAD | STORE)) == 0)
2373*3d8817e4Smiod continue;
2374*3d8817e4Smiod
2375*3d8817e4Smiod /* This is a load or store which is not on a four byte boundary. */
2376*3d8817e4Smiod
2377*3d8817e4Smiod while (*plabel < label_end && **plabel < i)
2378*3d8817e4Smiod ++*plabel;
2379*3d8817e4Smiod
2380*3d8817e4Smiod if (i > start)
2381*3d8817e4Smiod {
2382*3d8817e4Smiod prev_insn = bfd_get_16 (abfd, contents + i - 2);
2383*3d8817e4Smiod /* If INSN is the field b of a parallel processing insn, it is not
2384*3d8817e4Smiod a load / store after all. Note that the test here might mistake
2385*3d8817e4Smiod the field_b of a pcopy insn for the starting code of a parallel
2386*3d8817e4Smiod processing insn; this might miss a swapping opportunity, but at
2387*3d8817e4Smiod least we're on the safe side. */
2388*3d8817e4Smiod if (dsp && (prev_insn & 0xfc00) == 0xf800)
2389*3d8817e4Smiod continue;
2390*3d8817e4Smiod
2391*3d8817e4Smiod /* Check if prev_insn is actually the field b of a parallel
2392*3d8817e4Smiod processing insn. Again, this can give a spurious match
2393*3d8817e4Smiod after a pcopy. */
2394*3d8817e4Smiod if (dsp && i - 2 > start)
2395*3d8817e4Smiod {
2396*3d8817e4Smiod unsigned pprev_insn = bfd_get_16 (abfd, contents + i - 4);
2397*3d8817e4Smiod
2398*3d8817e4Smiod if ((pprev_insn & 0xfc00) == 0xf800)
2399*3d8817e4Smiod prev_op = NULL;
2400*3d8817e4Smiod else
2401*3d8817e4Smiod prev_op = sh_insn_info (prev_insn);
2402*3d8817e4Smiod }
2403*3d8817e4Smiod else
2404*3d8817e4Smiod prev_op = sh_insn_info (prev_insn);
2405*3d8817e4Smiod
2406*3d8817e4Smiod /* If the load/store instruction is in a delay slot, we
2407*3d8817e4Smiod can't swap. */
2408*3d8817e4Smiod if (prev_op == NULL
2409*3d8817e4Smiod || (prev_op->flags & DELAY) != 0)
2410*3d8817e4Smiod continue;
2411*3d8817e4Smiod }
2412*3d8817e4Smiod if (i > start
2413*3d8817e4Smiod && (*plabel >= label_end || **plabel != i)
2414*3d8817e4Smiod && prev_op != NULL
2415*3d8817e4Smiod && (prev_op->flags & (LOAD | STORE)) == 0
2416*3d8817e4Smiod && ! sh_insns_conflict (prev_insn, prev_op, insn, op))
2417*3d8817e4Smiod {
2418*3d8817e4Smiod bfd_boolean ok;
2419*3d8817e4Smiod
2420*3d8817e4Smiod /* The load/store instruction does not have a label, and
2421*3d8817e4Smiod there is a previous instruction; PREV_INSN is not
2422*3d8817e4Smiod itself a load/store instruction, and PREV_INSN and
2423*3d8817e4Smiod INSN do not conflict. */
2424*3d8817e4Smiod
2425*3d8817e4Smiod ok = TRUE;
2426*3d8817e4Smiod
2427*3d8817e4Smiod if (i >= start + 4)
2428*3d8817e4Smiod {
2429*3d8817e4Smiod unsigned int prev2_insn;
2430*3d8817e4Smiod const struct sh_opcode *prev2_op;
2431*3d8817e4Smiod
2432*3d8817e4Smiod prev2_insn = bfd_get_16 (abfd, contents + i - 4);
2433*3d8817e4Smiod prev2_op = sh_insn_info (prev2_insn);
2434*3d8817e4Smiod
2435*3d8817e4Smiod /* If the instruction before PREV_INSN has a delay
2436*3d8817e4Smiod slot--that is, PREV_INSN is in a delay slot--we
2437*3d8817e4Smiod can not swap. */
2438*3d8817e4Smiod if (prev2_op == NULL
2439*3d8817e4Smiod || (prev2_op->flags & DELAY) != 0)
2440*3d8817e4Smiod ok = FALSE;
2441*3d8817e4Smiod
2442*3d8817e4Smiod /* If the instruction before PREV_INSN is a load,
2443*3d8817e4Smiod and it sets a register which INSN uses, then
2444*3d8817e4Smiod putting INSN immediately after PREV_INSN will
2445*3d8817e4Smiod cause a pipeline bubble, so there is no point to
2446*3d8817e4Smiod making the swap. */
2447*3d8817e4Smiod if (ok
2448*3d8817e4Smiod && (prev2_op->flags & LOAD) != 0
2449*3d8817e4Smiod && sh_load_use (prev2_insn, prev2_op, insn, op))
2450*3d8817e4Smiod ok = FALSE;
2451*3d8817e4Smiod }
2452*3d8817e4Smiod
2453*3d8817e4Smiod if (ok)
2454*3d8817e4Smiod {
2455*3d8817e4Smiod if (! (*swap) (abfd, sec, relocs, contents, i - 2))
2456*3d8817e4Smiod return FALSE;
2457*3d8817e4Smiod *pswapped = TRUE;
2458*3d8817e4Smiod continue;
2459*3d8817e4Smiod }
2460*3d8817e4Smiod }
2461*3d8817e4Smiod
2462*3d8817e4Smiod while (*plabel < label_end && **plabel < i + 2)
2463*3d8817e4Smiod ++*plabel;
2464*3d8817e4Smiod
2465*3d8817e4Smiod if (i + 2 < stop
2466*3d8817e4Smiod && (*plabel >= label_end || **plabel != i + 2))
2467*3d8817e4Smiod {
2468*3d8817e4Smiod unsigned int next_insn;
2469*3d8817e4Smiod const struct sh_opcode *next_op;
2470*3d8817e4Smiod
2471*3d8817e4Smiod /* There is an instruction after the load/store
2472*3d8817e4Smiod instruction, and it does not have a label. */
2473*3d8817e4Smiod next_insn = bfd_get_16 (abfd, contents + i + 2);
2474*3d8817e4Smiod next_op = sh_insn_info (next_insn);
2475*3d8817e4Smiod if (next_op != NULL
2476*3d8817e4Smiod && (next_op->flags & (LOAD | STORE)) == 0
2477*3d8817e4Smiod && ! sh_insns_conflict (insn, op, next_insn, next_op))
2478*3d8817e4Smiod {
2479*3d8817e4Smiod bfd_boolean ok;
2480*3d8817e4Smiod
2481*3d8817e4Smiod /* NEXT_INSN is not itself a load/store instruction,
2482*3d8817e4Smiod and it does not conflict with INSN. */
2483*3d8817e4Smiod
2484*3d8817e4Smiod ok = TRUE;
2485*3d8817e4Smiod
2486*3d8817e4Smiod /* If PREV_INSN is a load, and it sets a register
2487*3d8817e4Smiod which NEXT_INSN uses, then putting NEXT_INSN
2488*3d8817e4Smiod immediately after PREV_INSN will cause a pipeline
2489*3d8817e4Smiod bubble, so there is no reason to make this swap. */
2490*3d8817e4Smiod if (prev_op != NULL
2491*3d8817e4Smiod && (prev_op->flags & LOAD) != 0
2492*3d8817e4Smiod && sh_load_use (prev_insn, prev_op, next_insn, next_op))
2493*3d8817e4Smiod ok = FALSE;
2494*3d8817e4Smiod
2495*3d8817e4Smiod /* If INSN is a load, and it sets a register which
2496*3d8817e4Smiod the insn after NEXT_INSN uses, then doing the
2497*3d8817e4Smiod swap will cause a pipeline bubble, so there is no
2498*3d8817e4Smiod reason to make the swap. However, if the insn
2499*3d8817e4Smiod after NEXT_INSN is itself a load or store
2500*3d8817e4Smiod instruction, then it is misaligned, so
2501*3d8817e4Smiod optimistically hope that it will be swapped
2502*3d8817e4Smiod itself, and just live with the pipeline bubble if
2503*3d8817e4Smiod it isn't. */
2504*3d8817e4Smiod if (ok
2505*3d8817e4Smiod && i + 4 < stop
2506*3d8817e4Smiod && (op->flags & LOAD) != 0)
2507*3d8817e4Smiod {
2508*3d8817e4Smiod unsigned int next2_insn;
2509*3d8817e4Smiod const struct sh_opcode *next2_op;
2510*3d8817e4Smiod
2511*3d8817e4Smiod next2_insn = bfd_get_16 (abfd, contents + i + 4);
2512*3d8817e4Smiod next2_op = sh_insn_info (next2_insn);
2513*3d8817e4Smiod if ((next2_op->flags & (LOAD | STORE)) == 0
2514*3d8817e4Smiod && sh_load_use (insn, op, next2_insn, next2_op))
2515*3d8817e4Smiod ok = FALSE;
2516*3d8817e4Smiod }
2517*3d8817e4Smiod
2518*3d8817e4Smiod if (ok)
2519*3d8817e4Smiod {
2520*3d8817e4Smiod if (! (*swap) (abfd, sec, relocs, contents, i))
2521*3d8817e4Smiod return FALSE;
2522*3d8817e4Smiod *pswapped = TRUE;
2523*3d8817e4Smiod continue;
2524*3d8817e4Smiod }
2525*3d8817e4Smiod }
2526*3d8817e4Smiod }
2527*3d8817e4Smiod }
2528*3d8817e4Smiod
2529*3d8817e4Smiod return TRUE;
2530*3d8817e4Smiod }
2531*3d8817e4Smiod #endif /* not COFF_IMAGE_WITH_PE */
2532*3d8817e4Smiod
2533*3d8817e4Smiod /* Look for loads and stores which we can align to four byte
2534*3d8817e4Smiod boundaries. See the longer comment above sh_relax_section for why
2535*3d8817e4Smiod this is desirable. This sets *PSWAPPED if some instruction was
2536*3d8817e4Smiod swapped. */
2537*3d8817e4Smiod
2538*3d8817e4Smiod static bfd_boolean
sh_align_loads(abfd,sec,internal_relocs,contents,pswapped)2539*3d8817e4Smiod sh_align_loads (abfd, sec, internal_relocs, contents, pswapped)
2540*3d8817e4Smiod bfd *abfd;
2541*3d8817e4Smiod asection *sec;
2542*3d8817e4Smiod struct internal_reloc *internal_relocs;
2543*3d8817e4Smiod bfd_byte *contents;
2544*3d8817e4Smiod bfd_boolean *pswapped;
2545*3d8817e4Smiod {
2546*3d8817e4Smiod struct internal_reloc *irel, *irelend;
2547*3d8817e4Smiod bfd_vma *labels = NULL;
2548*3d8817e4Smiod bfd_vma *label, *label_end;
2549*3d8817e4Smiod bfd_size_type amt;
2550*3d8817e4Smiod
2551*3d8817e4Smiod *pswapped = FALSE;
2552*3d8817e4Smiod
2553*3d8817e4Smiod irelend = internal_relocs + sec->reloc_count;
2554*3d8817e4Smiod
2555*3d8817e4Smiod /* Get all the addresses with labels on them. */
2556*3d8817e4Smiod amt = (bfd_size_type) sec->reloc_count * sizeof (bfd_vma);
2557*3d8817e4Smiod labels = (bfd_vma *) bfd_malloc (amt);
2558*3d8817e4Smiod if (labels == NULL)
2559*3d8817e4Smiod goto error_return;
2560*3d8817e4Smiod label_end = labels;
2561*3d8817e4Smiod for (irel = internal_relocs; irel < irelend; irel++)
2562*3d8817e4Smiod {
2563*3d8817e4Smiod if (irel->r_type == R_SH_LABEL)
2564*3d8817e4Smiod {
2565*3d8817e4Smiod *label_end = irel->r_vaddr - sec->vma;
2566*3d8817e4Smiod ++label_end;
2567*3d8817e4Smiod }
2568*3d8817e4Smiod }
2569*3d8817e4Smiod
2570*3d8817e4Smiod /* Note that the assembler currently always outputs relocs in
2571*3d8817e4Smiod address order. If that ever changes, this code will need to sort
2572*3d8817e4Smiod the label values and the relocs. */
2573*3d8817e4Smiod
2574*3d8817e4Smiod label = labels;
2575*3d8817e4Smiod
2576*3d8817e4Smiod for (irel = internal_relocs; irel < irelend; irel++)
2577*3d8817e4Smiod {
2578*3d8817e4Smiod bfd_vma start, stop;
2579*3d8817e4Smiod
2580*3d8817e4Smiod if (irel->r_type != R_SH_CODE)
2581*3d8817e4Smiod continue;
2582*3d8817e4Smiod
2583*3d8817e4Smiod start = irel->r_vaddr - sec->vma;
2584*3d8817e4Smiod
2585*3d8817e4Smiod for (irel++; irel < irelend; irel++)
2586*3d8817e4Smiod if (irel->r_type == R_SH_DATA)
2587*3d8817e4Smiod break;
2588*3d8817e4Smiod if (irel < irelend)
2589*3d8817e4Smiod stop = irel->r_vaddr - sec->vma;
2590*3d8817e4Smiod else
2591*3d8817e4Smiod stop = sec->size;
2592*3d8817e4Smiod
2593*3d8817e4Smiod if (! _bfd_sh_align_load_span (abfd, sec, contents, sh_swap_insns,
2594*3d8817e4Smiod (PTR) internal_relocs, &label,
2595*3d8817e4Smiod label_end, start, stop, pswapped))
2596*3d8817e4Smiod goto error_return;
2597*3d8817e4Smiod }
2598*3d8817e4Smiod
2599*3d8817e4Smiod free (labels);
2600*3d8817e4Smiod
2601*3d8817e4Smiod return TRUE;
2602*3d8817e4Smiod
2603*3d8817e4Smiod error_return:
2604*3d8817e4Smiod if (labels != NULL)
2605*3d8817e4Smiod free (labels);
2606*3d8817e4Smiod return FALSE;
2607*3d8817e4Smiod }
2608*3d8817e4Smiod
2609*3d8817e4Smiod /* Swap two SH instructions. */
2610*3d8817e4Smiod
2611*3d8817e4Smiod static bfd_boolean
sh_swap_insns(abfd,sec,relocs,contents,addr)2612*3d8817e4Smiod sh_swap_insns (abfd, sec, relocs, contents, addr)
2613*3d8817e4Smiod bfd *abfd;
2614*3d8817e4Smiod asection *sec;
2615*3d8817e4Smiod PTR relocs;
2616*3d8817e4Smiod bfd_byte *contents;
2617*3d8817e4Smiod bfd_vma addr;
2618*3d8817e4Smiod {
2619*3d8817e4Smiod struct internal_reloc *internal_relocs = (struct internal_reloc *) relocs;
2620*3d8817e4Smiod unsigned short i1, i2;
2621*3d8817e4Smiod struct internal_reloc *irel, *irelend;
2622*3d8817e4Smiod
2623*3d8817e4Smiod /* Swap the instructions themselves. */
2624*3d8817e4Smiod i1 = bfd_get_16 (abfd, contents + addr);
2625*3d8817e4Smiod i2 = bfd_get_16 (abfd, contents + addr + 2);
2626*3d8817e4Smiod bfd_put_16 (abfd, (bfd_vma) i2, contents + addr);
2627*3d8817e4Smiod bfd_put_16 (abfd, (bfd_vma) i1, contents + addr + 2);
2628*3d8817e4Smiod
2629*3d8817e4Smiod /* Adjust all reloc addresses. */
2630*3d8817e4Smiod irelend = internal_relocs + sec->reloc_count;
2631*3d8817e4Smiod for (irel = internal_relocs; irel < irelend; irel++)
2632*3d8817e4Smiod {
2633*3d8817e4Smiod int type, add;
2634*3d8817e4Smiod
2635*3d8817e4Smiod /* There are a few special types of relocs that we don't want to
2636*3d8817e4Smiod adjust. These relocs do not apply to the instruction itself,
2637*3d8817e4Smiod but are only associated with the address. */
2638*3d8817e4Smiod type = irel->r_type;
2639*3d8817e4Smiod if (type == R_SH_ALIGN
2640*3d8817e4Smiod || type == R_SH_CODE
2641*3d8817e4Smiod || type == R_SH_DATA
2642*3d8817e4Smiod || type == R_SH_LABEL)
2643*3d8817e4Smiod continue;
2644*3d8817e4Smiod
2645*3d8817e4Smiod /* If an R_SH_USES reloc points to one of the addresses being
2646*3d8817e4Smiod swapped, we must adjust it. It would be incorrect to do this
2647*3d8817e4Smiod for a jump, though, since we want to execute both
2648*3d8817e4Smiod instructions after the jump. (We have avoided swapping
2649*3d8817e4Smiod around a label, so the jump will not wind up executing an
2650*3d8817e4Smiod instruction it shouldn't). */
2651*3d8817e4Smiod if (type == R_SH_USES)
2652*3d8817e4Smiod {
2653*3d8817e4Smiod bfd_vma off;
2654*3d8817e4Smiod
2655*3d8817e4Smiod off = irel->r_vaddr - sec->vma + 4 + irel->r_offset;
2656*3d8817e4Smiod if (off == addr)
2657*3d8817e4Smiod irel->r_offset += 2;
2658*3d8817e4Smiod else if (off == addr + 2)
2659*3d8817e4Smiod irel->r_offset -= 2;
2660*3d8817e4Smiod }
2661*3d8817e4Smiod
2662*3d8817e4Smiod if (irel->r_vaddr - sec->vma == addr)
2663*3d8817e4Smiod {
2664*3d8817e4Smiod irel->r_vaddr += 2;
2665*3d8817e4Smiod add = -2;
2666*3d8817e4Smiod }
2667*3d8817e4Smiod else if (irel->r_vaddr - sec->vma == addr + 2)
2668*3d8817e4Smiod {
2669*3d8817e4Smiod irel->r_vaddr -= 2;
2670*3d8817e4Smiod add = 2;
2671*3d8817e4Smiod }
2672*3d8817e4Smiod else
2673*3d8817e4Smiod add = 0;
2674*3d8817e4Smiod
2675*3d8817e4Smiod if (add != 0)
2676*3d8817e4Smiod {
2677*3d8817e4Smiod bfd_byte *loc;
2678*3d8817e4Smiod unsigned short insn, oinsn;
2679*3d8817e4Smiod bfd_boolean overflow;
2680*3d8817e4Smiod
2681*3d8817e4Smiod loc = contents + irel->r_vaddr - sec->vma;
2682*3d8817e4Smiod overflow = FALSE;
2683*3d8817e4Smiod switch (type)
2684*3d8817e4Smiod {
2685*3d8817e4Smiod default:
2686*3d8817e4Smiod break;
2687*3d8817e4Smiod
2688*3d8817e4Smiod case R_SH_PCDISP8BY2:
2689*3d8817e4Smiod case R_SH_PCRELIMM8BY2:
2690*3d8817e4Smiod insn = bfd_get_16 (abfd, loc);
2691*3d8817e4Smiod oinsn = insn;
2692*3d8817e4Smiod insn += add / 2;
2693*3d8817e4Smiod if ((oinsn & 0xff00) != (insn & 0xff00))
2694*3d8817e4Smiod overflow = TRUE;
2695*3d8817e4Smiod bfd_put_16 (abfd, (bfd_vma) insn, loc);
2696*3d8817e4Smiod break;
2697*3d8817e4Smiod
2698*3d8817e4Smiod case R_SH_PCDISP:
2699*3d8817e4Smiod insn = bfd_get_16 (abfd, loc);
2700*3d8817e4Smiod oinsn = insn;
2701*3d8817e4Smiod insn += add / 2;
2702*3d8817e4Smiod if ((oinsn & 0xf000) != (insn & 0xf000))
2703*3d8817e4Smiod overflow = TRUE;
2704*3d8817e4Smiod bfd_put_16 (abfd, (bfd_vma) insn, loc);
2705*3d8817e4Smiod break;
2706*3d8817e4Smiod
2707*3d8817e4Smiod case R_SH_PCRELIMM8BY4:
2708*3d8817e4Smiod /* This reloc ignores the least significant 3 bits of
2709*3d8817e4Smiod the program counter before adding in the offset.
2710*3d8817e4Smiod This means that if ADDR is at an even address, the
2711*3d8817e4Smiod swap will not affect the offset. If ADDR is an at an
2712*3d8817e4Smiod odd address, then the instruction will be crossing a
2713*3d8817e4Smiod four byte boundary, and must be adjusted. */
2714*3d8817e4Smiod if ((addr & 3) != 0)
2715*3d8817e4Smiod {
2716*3d8817e4Smiod insn = bfd_get_16 (abfd, loc);
2717*3d8817e4Smiod oinsn = insn;
2718*3d8817e4Smiod insn += add / 2;
2719*3d8817e4Smiod if ((oinsn & 0xff00) != (insn & 0xff00))
2720*3d8817e4Smiod overflow = TRUE;
2721*3d8817e4Smiod bfd_put_16 (abfd, (bfd_vma) insn, loc);
2722*3d8817e4Smiod }
2723*3d8817e4Smiod
2724*3d8817e4Smiod break;
2725*3d8817e4Smiod }
2726*3d8817e4Smiod
2727*3d8817e4Smiod if (overflow)
2728*3d8817e4Smiod {
2729*3d8817e4Smiod ((*_bfd_error_handler)
2730*3d8817e4Smiod ("%B: 0x%lx: fatal: reloc overflow while relaxing",
2731*3d8817e4Smiod abfd, (unsigned long) irel->r_vaddr));
2732*3d8817e4Smiod bfd_set_error (bfd_error_bad_value);
2733*3d8817e4Smiod return FALSE;
2734*3d8817e4Smiod }
2735*3d8817e4Smiod }
2736*3d8817e4Smiod }
2737*3d8817e4Smiod
2738*3d8817e4Smiod return TRUE;
2739*3d8817e4Smiod }
2740*3d8817e4Smiod
2741*3d8817e4Smiod /* This is a modification of _bfd_coff_generic_relocate_section, which
2742*3d8817e4Smiod will handle SH relaxing. */
2743*3d8817e4Smiod
2744*3d8817e4Smiod static bfd_boolean
sh_relocate_section(output_bfd,info,input_bfd,input_section,contents,relocs,syms,sections)2745*3d8817e4Smiod sh_relocate_section (output_bfd, info, input_bfd, input_section, contents,
2746*3d8817e4Smiod relocs, syms, sections)
2747*3d8817e4Smiod bfd *output_bfd ATTRIBUTE_UNUSED;
2748*3d8817e4Smiod struct bfd_link_info *info;
2749*3d8817e4Smiod bfd *input_bfd;
2750*3d8817e4Smiod asection *input_section;
2751*3d8817e4Smiod bfd_byte *contents;
2752*3d8817e4Smiod struct internal_reloc *relocs;
2753*3d8817e4Smiod struct internal_syment *syms;
2754*3d8817e4Smiod asection **sections;
2755*3d8817e4Smiod {
2756*3d8817e4Smiod struct internal_reloc *rel;
2757*3d8817e4Smiod struct internal_reloc *relend;
2758*3d8817e4Smiod
2759*3d8817e4Smiod rel = relocs;
2760*3d8817e4Smiod relend = rel + input_section->reloc_count;
2761*3d8817e4Smiod for (; rel < relend; rel++)
2762*3d8817e4Smiod {
2763*3d8817e4Smiod long symndx;
2764*3d8817e4Smiod struct coff_link_hash_entry *h;
2765*3d8817e4Smiod struct internal_syment *sym;
2766*3d8817e4Smiod bfd_vma addend;
2767*3d8817e4Smiod bfd_vma val;
2768*3d8817e4Smiod reloc_howto_type *howto;
2769*3d8817e4Smiod bfd_reloc_status_type rstat;
2770*3d8817e4Smiod
2771*3d8817e4Smiod /* Almost all relocs have to do with relaxing. If any work must
2772*3d8817e4Smiod be done for them, it has been done in sh_relax_section. */
2773*3d8817e4Smiod if (rel->r_type != R_SH_IMM32
2774*3d8817e4Smiod #ifdef COFF_WITH_PE
2775*3d8817e4Smiod && rel->r_type != R_SH_IMM32CE
2776*3d8817e4Smiod && rel->r_type != R_SH_IMAGEBASE
2777*3d8817e4Smiod #endif
2778*3d8817e4Smiod && rel->r_type != R_SH_PCDISP)
2779*3d8817e4Smiod continue;
2780*3d8817e4Smiod
2781*3d8817e4Smiod symndx = rel->r_symndx;
2782*3d8817e4Smiod
2783*3d8817e4Smiod if (symndx == -1)
2784*3d8817e4Smiod {
2785*3d8817e4Smiod h = NULL;
2786*3d8817e4Smiod sym = NULL;
2787*3d8817e4Smiod }
2788*3d8817e4Smiod else
2789*3d8817e4Smiod {
2790*3d8817e4Smiod if (symndx < 0
2791*3d8817e4Smiod || (unsigned long) symndx >= obj_raw_syment_count (input_bfd))
2792*3d8817e4Smiod {
2793*3d8817e4Smiod (*_bfd_error_handler)
2794*3d8817e4Smiod ("%B: illegal symbol index %ld in relocs",
2795*3d8817e4Smiod input_bfd, symndx);
2796*3d8817e4Smiod bfd_set_error (bfd_error_bad_value);
2797*3d8817e4Smiod return FALSE;
2798*3d8817e4Smiod }
2799*3d8817e4Smiod h = obj_coff_sym_hashes (input_bfd)[symndx];
2800*3d8817e4Smiod sym = syms + symndx;
2801*3d8817e4Smiod }
2802*3d8817e4Smiod
2803*3d8817e4Smiod if (sym != NULL && sym->n_scnum != 0)
2804*3d8817e4Smiod addend = - sym->n_value;
2805*3d8817e4Smiod else
2806*3d8817e4Smiod addend = 0;
2807*3d8817e4Smiod
2808*3d8817e4Smiod if (rel->r_type == R_SH_PCDISP)
2809*3d8817e4Smiod addend -= 4;
2810*3d8817e4Smiod
2811*3d8817e4Smiod if (rel->r_type >= SH_COFF_HOWTO_COUNT)
2812*3d8817e4Smiod howto = NULL;
2813*3d8817e4Smiod else
2814*3d8817e4Smiod howto = &sh_coff_howtos[rel->r_type];
2815*3d8817e4Smiod
2816*3d8817e4Smiod if (howto == NULL)
2817*3d8817e4Smiod {
2818*3d8817e4Smiod bfd_set_error (bfd_error_bad_value);
2819*3d8817e4Smiod return FALSE;
2820*3d8817e4Smiod }
2821*3d8817e4Smiod
2822*3d8817e4Smiod #ifdef COFF_WITH_PE
2823*3d8817e4Smiod if (rel->r_type == R_SH_IMAGEBASE)
2824*3d8817e4Smiod addend -= pe_data (input_section->output_section->owner)->pe_opthdr.ImageBase;
2825*3d8817e4Smiod #endif
2826*3d8817e4Smiod
2827*3d8817e4Smiod val = 0;
2828*3d8817e4Smiod
2829*3d8817e4Smiod if (h == NULL)
2830*3d8817e4Smiod {
2831*3d8817e4Smiod asection *sec;
2832*3d8817e4Smiod
2833*3d8817e4Smiod /* There is nothing to do for an internal PCDISP reloc. */
2834*3d8817e4Smiod if (rel->r_type == R_SH_PCDISP)
2835*3d8817e4Smiod continue;
2836*3d8817e4Smiod
2837*3d8817e4Smiod if (symndx == -1)
2838*3d8817e4Smiod {
2839*3d8817e4Smiod sec = bfd_abs_section_ptr;
2840*3d8817e4Smiod val = 0;
2841*3d8817e4Smiod }
2842*3d8817e4Smiod else
2843*3d8817e4Smiod {
2844*3d8817e4Smiod sec = sections[symndx];
2845*3d8817e4Smiod val = (sec->output_section->vma
2846*3d8817e4Smiod + sec->output_offset
2847*3d8817e4Smiod + sym->n_value
2848*3d8817e4Smiod - sec->vma);
2849*3d8817e4Smiod }
2850*3d8817e4Smiod }
2851*3d8817e4Smiod else
2852*3d8817e4Smiod {
2853*3d8817e4Smiod if (h->root.type == bfd_link_hash_defined
2854*3d8817e4Smiod || h->root.type == bfd_link_hash_defweak)
2855*3d8817e4Smiod {
2856*3d8817e4Smiod asection *sec;
2857*3d8817e4Smiod
2858*3d8817e4Smiod sec = h->root.u.def.section;
2859*3d8817e4Smiod val = (h->root.u.def.value
2860*3d8817e4Smiod + sec->output_section->vma
2861*3d8817e4Smiod + sec->output_offset);
2862*3d8817e4Smiod }
2863*3d8817e4Smiod else if (! info->relocatable)
2864*3d8817e4Smiod {
2865*3d8817e4Smiod if (! ((*info->callbacks->undefined_symbol)
2866*3d8817e4Smiod (info, h->root.root.string, input_bfd, input_section,
2867*3d8817e4Smiod rel->r_vaddr - input_section->vma, TRUE)))
2868*3d8817e4Smiod return FALSE;
2869*3d8817e4Smiod }
2870*3d8817e4Smiod }
2871*3d8817e4Smiod
2872*3d8817e4Smiod rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
2873*3d8817e4Smiod contents,
2874*3d8817e4Smiod rel->r_vaddr - input_section->vma,
2875*3d8817e4Smiod val, addend);
2876*3d8817e4Smiod
2877*3d8817e4Smiod switch (rstat)
2878*3d8817e4Smiod {
2879*3d8817e4Smiod default:
2880*3d8817e4Smiod abort ();
2881*3d8817e4Smiod case bfd_reloc_ok:
2882*3d8817e4Smiod break;
2883*3d8817e4Smiod case bfd_reloc_overflow:
2884*3d8817e4Smiod {
2885*3d8817e4Smiod const char *name;
2886*3d8817e4Smiod char buf[SYMNMLEN + 1];
2887*3d8817e4Smiod
2888*3d8817e4Smiod if (symndx == -1)
2889*3d8817e4Smiod name = "*ABS*";
2890*3d8817e4Smiod else if (h != NULL)
2891*3d8817e4Smiod name = NULL;
2892*3d8817e4Smiod else if (sym->_n._n_n._n_zeroes == 0
2893*3d8817e4Smiod && sym->_n._n_n._n_offset != 0)
2894*3d8817e4Smiod name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset;
2895*3d8817e4Smiod else
2896*3d8817e4Smiod {
2897*3d8817e4Smiod strncpy (buf, sym->_n._n_name, SYMNMLEN);
2898*3d8817e4Smiod buf[SYMNMLEN] = '\0';
2899*3d8817e4Smiod name = buf;
2900*3d8817e4Smiod }
2901*3d8817e4Smiod
2902*3d8817e4Smiod if (! ((*info->callbacks->reloc_overflow)
2903*3d8817e4Smiod (info, (h ? &h->root : NULL), name, howto->name,
2904*3d8817e4Smiod (bfd_vma) 0, input_bfd, input_section,
2905*3d8817e4Smiod rel->r_vaddr - input_section->vma)))
2906*3d8817e4Smiod return FALSE;
2907*3d8817e4Smiod }
2908*3d8817e4Smiod }
2909*3d8817e4Smiod }
2910*3d8817e4Smiod
2911*3d8817e4Smiod return TRUE;
2912*3d8817e4Smiod }
2913*3d8817e4Smiod
2914*3d8817e4Smiod /* This is a version of bfd_generic_get_relocated_section_contents
2915*3d8817e4Smiod which uses sh_relocate_section. */
2916*3d8817e4Smiod
2917*3d8817e4Smiod static bfd_byte *
sh_coff_get_relocated_section_contents(output_bfd,link_info,link_order,data,relocatable,symbols)2918*3d8817e4Smiod sh_coff_get_relocated_section_contents (output_bfd, link_info, link_order,
2919*3d8817e4Smiod data, relocatable, symbols)
2920*3d8817e4Smiod bfd *output_bfd;
2921*3d8817e4Smiod struct bfd_link_info *link_info;
2922*3d8817e4Smiod struct bfd_link_order *link_order;
2923*3d8817e4Smiod bfd_byte *data;
2924*3d8817e4Smiod bfd_boolean relocatable;
2925*3d8817e4Smiod asymbol **symbols;
2926*3d8817e4Smiod {
2927*3d8817e4Smiod asection *input_section = link_order->u.indirect.section;
2928*3d8817e4Smiod bfd *input_bfd = input_section->owner;
2929*3d8817e4Smiod asection **sections = NULL;
2930*3d8817e4Smiod struct internal_reloc *internal_relocs = NULL;
2931*3d8817e4Smiod struct internal_syment *internal_syms = NULL;
2932*3d8817e4Smiod
2933*3d8817e4Smiod /* We only need to handle the case of relaxing, or of having a
2934*3d8817e4Smiod particular set of section contents, specially. */
2935*3d8817e4Smiod if (relocatable
2936*3d8817e4Smiod || coff_section_data (input_bfd, input_section) == NULL
2937*3d8817e4Smiod || coff_section_data (input_bfd, input_section)->contents == NULL)
2938*3d8817e4Smiod return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
2939*3d8817e4Smiod link_order, data,
2940*3d8817e4Smiod relocatable,
2941*3d8817e4Smiod symbols);
2942*3d8817e4Smiod
2943*3d8817e4Smiod memcpy (data, coff_section_data (input_bfd, input_section)->contents,
2944*3d8817e4Smiod (size_t) input_section->size);
2945*3d8817e4Smiod
2946*3d8817e4Smiod if ((input_section->flags & SEC_RELOC) != 0
2947*3d8817e4Smiod && input_section->reloc_count > 0)
2948*3d8817e4Smiod {
2949*3d8817e4Smiod bfd_size_type symesz = bfd_coff_symesz (input_bfd);
2950*3d8817e4Smiod bfd_byte *esym, *esymend;
2951*3d8817e4Smiod struct internal_syment *isymp;
2952*3d8817e4Smiod asection **secpp;
2953*3d8817e4Smiod bfd_size_type amt;
2954*3d8817e4Smiod
2955*3d8817e4Smiod if (! _bfd_coff_get_external_symbols (input_bfd))
2956*3d8817e4Smiod goto error_return;
2957*3d8817e4Smiod
2958*3d8817e4Smiod internal_relocs = (_bfd_coff_read_internal_relocs
2959*3d8817e4Smiod (input_bfd, input_section, FALSE, (bfd_byte *) NULL,
2960*3d8817e4Smiod FALSE, (struct internal_reloc *) NULL));
2961*3d8817e4Smiod if (internal_relocs == NULL)
2962*3d8817e4Smiod goto error_return;
2963*3d8817e4Smiod
2964*3d8817e4Smiod amt = obj_raw_syment_count (input_bfd);
2965*3d8817e4Smiod amt *= sizeof (struct internal_syment);
2966*3d8817e4Smiod internal_syms = (struct internal_syment *) bfd_malloc (amt);
2967*3d8817e4Smiod if (internal_syms == NULL)
2968*3d8817e4Smiod goto error_return;
2969*3d8817e4Smiod
2970*3d8817e4Smiod amt = obj_raw_syment_count (input_bfd);
2971*3d8817e4Smiod amt *= sizeof (asection *);
2972*3d8817e4Smiod sections = (asection **) bfd_malloc (amt);
2973*3d8817e4Smiod if (sections == NULL)
2974*3d8817e4Smiod goto error_return;
2975*3d8817e4Smiod
2976*3d8817e4Smiod isymp = internal_syms;
2977*3d8817e4Smiod secpp = sections;
2978*3d8817e4Smiod esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
2979*3d8817e4Smiod esymend = esym + obj_raw_syment_count (input_bfd) * symesz;
2980*3d8817e4Smiod while (esym < esymend)
2981*3d8817e4Smiod {
2982*3d8817e4Smiod bfd_coff_swap_sym_in (input_bfd, (PTR) esym, (PTR) isymp);
2983*3d8817e4Smiod
2984*3d8817e4Smiod if (isymp->n_scnum != 0)
2985*3d8817e4Smiod *secpp = coff_section_from_bfd_index (input_bfd, isymp->n_scnum);
2986*3d8817e4Smiod else
2987*3d8817e4Smiod {
2988*3d8817e4Smiod if (isymp->n_value == 0)
2989*3d8817e4Smiod *secpp = bfd_und_section_ptr;
2990*3d8817e4Smiod else
2991*3d8817e4Smiod *secpp = bfd_com_section_ptr;
2992*3d8817e4Smiod }
2993*3d8817e4Smiod
2994*3d8817e4Smiod esym += (isymp->n_numaux + 1) * symesz;
2995*3d8817e4Smiod secpp += isymp->n_numaux + 1;
2996*3d8817e4Smiod isymp += isymp->n_numaux + 1;
2997*3d8817e4Smiod }
2998*3d8817e4Smiod
2999*3d8817e4Smiod if (! sh_relocate_section (output_bfd, link_info, input_bfd,
3000*3d8817e4Smiod input_section, data, internal_relocs,
3001*3d8817e4Smiod internal_syms, sections))
3002*3d8817e4Smiod goto error_return;
3003*3d8817e4Smiod
3004*3d8817e4Smiod free (sections);
3005*3d8817e4Smiod sections = NULL;
3006*3d8817e4Smiod free (internal_syms);
3007*3d8817e4Smiod internal_syms = NULL;
3008*3d8817e4Smiod free (internal_relocs);
3009*3d8817e4Smiod internal_relocs = NULL;
3010*3d8817e4Smiod }
3011*3d8817e4Smiod
3012*3d8817e4Smiod return data;
3013*3d8817e4Smiod
3014*3d8817e4Smiod error_return:
3015*3d8817e4Smiod if (internal_relocs != NULL)
3016*3d8817e4Smiod free (internal_relocs);
3017*3d8817e4Smiod if (internal_syms != NULL)
3018*3d8817e4Smiod free (internal_syms);
3019*3d8817e4Smiod if (sections != NULL)
3020*3d8817e4Smiod free (sections);
3021*3d8817e4Smiod return NULL;
3022*3d8817e4Smiod }
3023*3d8817e4Smiod
3024*3d8817e4Smiod /* The target vectors. */
3025*3d8817e4Smiod
3026*3d8817e4Smiod #ifndef TARGET_SHL_SYM
3027*3d8817e4Smiod CREATE_BIG_COFF_TARGET_VEC (shcoff_vec, "coff-sh", BFD_IS_RELAXABLE, 0, '_', NULL, COFF_SWAP_TABLE)
3028*3d8817e4Smiod #endif
3029*3d8817e4Smiod
3030*3d8817e4Smiod #ifdef TARGET_SHL_SYM
3031*3d8817e4Smiod #define TARGET_SYM TARGET_SHL_SYM
3032*3d8817e4Smiod #else
3033*3d8817e4Smiod #define TARGET_SYM shlcoff_vec
3034*3d8817e4Smiod #endif
3035*3d8817e4Smiod
3036*3d8817e4Smiod #ifndef TARGET_SHL_NAME
3037*3d8817e4Smiod #define TARGET_SHL_NAME "coff-shl"
3038*3d8817e4Smiod #endif
3039*3d8817e4Smiod
3040*3d8817e4Smiod #ifdef COFF_WITH_PE
3041*3d8817e4Smiod CREATE_LITTLE_COFF_TARGET_VEC (TARGET_SYM, TARGET_SHL_NAME, BFD_IS_RELAXABLE,
3042*3d8817e4Smiod SEC_CODE | SEC_DATA, '_', NULL, COFF_SWAP_TABLE);
3043*3d8817e4Smiod #else
3044*3d8817e4Smiod CREATE_LITTLE_COFF_TARGET_VEC (TARGET_SYM, TARGET_SHL_NAME, BFD_IS_RELAXABLE,
3045*3d8817e4Smiod 0, '_', NULL, COFF_SWAP_TABLE)
3046*3d8817e4Smiod #endif
3047*3d8817e4Smiod
3048*3d8817e4Smiod #ifndef TARGET_SHL_SYM
3049*3d8817e4Smiod static const bfd_target * coff_small_object_p PARAMS ((bfd *));
3050*3d8817e4Smiod static bfd_boolean coff_small_new_section_hook PARAMS ((bfd *, asection *));
3051*3d8817e4Smiod /* Some people want versions of the SH COFF target which do not align
3052*3d8817e4Smiod to 16 byte boundaries. We implement that by adding a couple of new
3053*3d8817e4Smiod target vectors. These are just like the ones above, but they
3054*3d8817e4Smiod change the default section alignment. To generate them in the
3055*3d8817e4Smiod assembler, use -small. To use them in the linker, use -b
3056*3d8817e4Smiod coff-sh{l}-small and -oformat coff-sh{l}-small.
3057*3d8817e4Smiod
3058*3d8817e4Smiod Yes, this is a horrible hack. A general solution for setting
3059*3d8817e4Smiod section alignment in COFF is rather complex. ELF handles this
3060*3d8817e4Smiod correctly. */
3061*3d8817e4Smiod
3062*3d8817e4Smiod /* Only recognize the small versions if the target was not defaulted.
3063*3d8817e4Smiod Otherwise we won't recognize the non default endianness. */
3064*3d8817e4Smiod
3065*3d8817e4Smiod static const bfd_target *
coff_small_object_p(abfd)3066*3d8817e4Smiod coff_small_object_p (abfd)
3067*3d8817e4Smiod bfd *abfd;
3068*3d8817e4Smiod {
3069*3d8817e4Smiod if (abfd->target_defaulted)
3070*3d8817e4Smiod {
3071*3d8817e4Smiod bfd_set_error (bfd_error_wrong_format);
3072*3d8817e4Smiod return NULL;
3073*3d8817e4Smiod }
3074*3d8817e4Smiod return coff_object_p (abfd);
3075*3d8817e4Smiod }
3076*3d8817e4Smiod
3077*3d8817e4Smiod /* Set the section alignment for the small versions. */
3078*3d8817e4Smiod
3079*3d8817e4Smiod static bfd_boolean
coff_small_new_section_hook(abfd,section)3080*3d8817e4Smiod coff_small_new_section_hook (abfd, section)
3081*3d8817e4Smiod bfd *abfd;
3082*3d8817e4Smiod asection *section;
3083*3d8817e4Smiod {
3084*3d8817e4Smiod if (! coff_new_section_hook (abfd, section))
3085*3d8817e4Smiod return FALSE;
3086*3d8817e4Smiod
3087*3d8817e4Smiod /* We must align to at least a four byte boundary, because longword
3088*3d8817e4Smiod accesses must be on a four byte boundary. */
3089*3d8817e4Smiod if (section->alignment_power == COFF_DEFAULT_SECTION_ALIGNMENT_POWER)
3090*3d8817e4Smiod section->alignment_power = 2;
3091*3d8817e4Smiod
3092*3d8817e4Smiod return TRUE;
3093*3d8817e4Smiod }
3094*3d8817e4Smiod
3095*3d8817e4Smiod /* This is copied from bfd_coff_std_swap_table so that we can change
3096*3d8817e4Smiod the default section alignment power. */
3097*3d8817e4Smiod
3098*3d8817e4Smiod static const bfd_coff_backend_data bfd_coff_small_swap_table =
3099*3d8817e4Smiod {
3100*3d8817e4Smiod coff_swap_aux_in, coff_swap_sym_in, coff_swap_lineno_in,
3101*3d8817e4Smiod coff_swap_aux_out, coff_swap_sym_out,
3102*3d8817e4Smiod coff_swap_lineno_out, coff_swap_reloc_out,
3103*3d8817e4Smiod coff_swap_filehdr_out, coff_swap_aouthdr_out,
3104*3d8817e4Smiod coff_swap_scnhdr_out,
3105*3d8817e4Smiod FILHSZ, AOUTSZ, SCNHSZ, SYMESZ, AUXESZ, RELSZ, LINESZ, FILNMLEN,
3106*3d8817e4Smiod #ifdef COFF_LONG_FILENAMES
3107*3d8817e4Smiod TRUE,
3108*3d8817e4Smiod #else
3109*3d8817e4Smiod FALSE,
3110*3d8817e4Smiod #endif
3111*3d8817e4Smiod #ifdef COFF_LONG_SECTION_NAMES
3112*3d8817e4Smiod TRUE,
3113*3d8817e4Smiod #else
3114*3d8817e4Smiod FALSE,
3115*3d8817e4Smiod #endif
3116*3d8817e4Smiod 2,
3117*3d8817e4Smiod #ifdef COFF_FORCE_SYMBOLS_IN_STRINGS
3118*3d8817e4Smiod TRUE,
3119*3d8817e4Smiod #else
3120*3d8817e4Smiod FALSE,
3121*3d8817e4Smiod #endif
3122*3d8817e4Smiod #ifdef COFF_DEBUG_STRING_WIDE_PREFIX
3123*3d8817e4Smiod 4,
3124*3d8817e4Smiod #else
3125*3d8817e4Smiod 2,
3126*3d8817e4Smiod #endif
3127*3d8817e4Smiod coff_swap_filehdr_in, coff_swap_aouthdr_in, coff_swap_scnhdr_in,
3128*3d8817e4Smiod coff_swap_reloc_in, coff_bad_format_hook, coff_set_arch_mach_hook,
3129*3d8817e4Smiod coff_mkobject_hook, styp_to_sec_flags, coff_set_alignment_hook,
3130*3d8817e4Smiod coff_slurp_symbol_table, symname_in_debug_hook, coff_pointerize_aux_hook,
3131*3d8817e4Smiod coff_print_aux, coff_reloc16_extra_cases, coff_reloc16_estimate,
3132*3d8817e4Smiod coff_classify_symbol, coff_compute_section_file_positions,
3133*3d8817e4Smiod coff_start_final_link, coff_relocate_section, coff_rtype_to_howto,
3134*3d8817e4Smiod coff_adjust_symndx, coff_link_add_one_symbol,
3135*3d8817e4Smiod coff_link_output_has_begun, coff_final_link_postscript
3136*3d8817e4Smiod };
3137*3d8817e4Smiod
3138*3d8817e4Smiod #define coff_small_close_and_cleanup \
3139*3d8817e4Smiod coff_close_and_cleanup
3140*3d8817e4Smiod #define coff_small_bfd_free_cached_info \
3141*3d8817e4Smiod coff_bfd_free_cached_info
3142*3d8817e4Smiod #define coff_small_get_section_contents \
3143*3d8817e4Smiod coff_get_section_contents
3144*3d8817e4Smiod #define coff_small_get_section_contents_in_window \
3145*3d8817e4Smiod coff_get_section_contents_in_window
3146*3d8817e4Smiod
3147*3d8817e4Smiod extern const bfd_target shlcoff_small_vec;
3148*3d8817e4Smiod
3149*3d8817e4Smiod const bfd_target shcoff_small_vec =
3150*3d8817e4Smiod {
3151*3d8817e4Smiod "coff-sh-small", /* name */
3152*3d8817e4Smiod bfd_target_coff_flavour,
3153*3d8817e4Smiod BFD_ENDIAN_BIG, /* data byte order is big */
3154*3d8817e4Smiod BFD_ENDIAN_BIG, /* header byte order is big */
3155*3d8817e4Smiod
3156*3d8817e4Smiod (HAS_RELOC | EXEC_P | /* object flags */
3157*3d8817e4Smiod HAS_LINENO | HAS_DEBUG |
3158*3d8817e4Smiod HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE),
3159*3d8817e4Smiod
3160*3d8817e4Smiod (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC),
3161*3d8817e4Smiod '_', /* leading symbol underscore */
3162*3d8817e4Smiod '/', /* ar_pad_char */
3163*3d8817e4Smiod 15, /* ar_max_namelen */
3164*3d8817e4Smiod bfd_getb64, bfd_getb_signed_64, bfd_putb64,
3165*3d8817e4Smiod bfd_getb32, bfd_getb_signed_32, bfd_putb32,
3166*3d8817e4Smiod bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
3167*3d8817e4Smiod bfd_getb64, bfd_getb_signed_64, bfd_putb64,
3168*3d8817e4Smiod bfd_getb32, bfd_getb_signed_32, bfd_putb32,
3169*3d8817e4Smiod bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
3170*3d8817e4Smiod
3171*3d8817e4Smiod {_bfd_dummy_target, coff_small_object_p, /* bfd_check_format */
3172*3d8817e4Smiod bfd_generic_archive_p, _bfd_dummy_target},
3173*3d8817e4Smiod {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
3174*3d8817e4Smiod bfd_false},
3175*3d8817e4Smiod {bfd_false, coff_write_object_contents, /* bfd_write_contents */
3176*3d8817e4Smiod _bfd_write_archive_contents, bfd_false},
3177*3d8817e4Smiod
3178*3d8817e4Smiod BFD_JUMP_TABLE_GENERIC (coff_small),
3179*3d8817e4Smiod BFD_JUMP_TABLE_COPY (coff),
3180*3d8817e4Smiod BFD_JUMP_TABLE_CORE (_bfd_nocore),
3181*3d8817e4Smiod BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
3182*3d8817e4Smiod BFD_JUMP_TABLE_SYMBOLS (coff),
3183*3d8817e4Smiod BFD_JUMP_TABLE_RELOCS (coff),
3184*3d8817e4Smiod BFD_JUMP_TABLE_WRITE (coff),
3185*3d8817e4Smiod BFD_JUMP_TABLE_LINK (coff),
3186*3d8817e4Smiod BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
3187*3d8817e4Smiod
3188*3d8817e4Smiod & shlcoff_small_vec,
3189*3d8817e4Smiod
3190*3d8817e4Smiod (PTR) &bfd_coff_small_swap_table
3191*3d8817e4Smiod };
3192*3d8817e4Smiod
3193*3d8817e4Smiod const bfd_target shlcoff_small_vec =
3194*3d8817e4Smiod {
3195*3d8817e4Smiod "coff-shl-small", /* name */
3196*3d8817e4Smiod bfd_target_coff_flavour,
3197*3d8817e4Smiod BFD_ENDIAN_LITTLE, /* data byte order is little */
3198*3d8817e4Smiod BFD_ENDIAN_LITTLE, /* header byte order is little endian too*/
3199*3d8817e4Smiod
3200*3d8817e4Smiod (HAS_RELOC | EXEC_P | /* object flags */
3201*3d8817e4Smiod HAS_LINENO | HAS_DEBUG |
3202*3d8817e4Smiod HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE),
3203*3d8817e4Smiod
3204*3d8817e4Smiod (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC),
3205*3d8817e4Smiod '_', /* leading symbol underscore */
3206*3d8817e4Smiod '/', /* ar_pad_char */
3207*3d8817e4Smiod 15, /* ar_max_namelen */
3208*3d8817e4Smiod bfd_getl64, bfd_getl_signed_64, bfd_putl64,
3209*3d8817e4Smiod bfd_getl32, bfd_getl_signed_32, bfd_putl32,
3210*3d8817e4Smiod bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
3211*3d8817e4Smiod bfd_getl64, bfd_getl_signed_64, bfd_putl64,
3212*3d8817e4Smiod bfd_getl32, bfd_getl_signed_32, bfd_putl32,
3213*3d8817e4Smiod bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
3214*3d8817e4Smiod
3215*3d8817e4Smiod {_bfd_dummy_target, coff_small_object_p, /* bfd_check_format */
3216*3d8817e4Smiod bfd_generic_archive_p, _bfd_dummy_target},
3217*3d8817e4Smiod {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
3218*3d8817e4Smiod bfd_false},
3219*3d8817e4Smiod {bfd_false, coff_write_object_contents, /* bfd_write_contents */
3220*3d8817e4Smiod _bfd_write_archive_contents, bfd_false},
3221*3d8817e4Smiod
3222*3d8817e4Smiod BFD_JUMP_TABLE_GENERIC (coff_small),
3223*3d8817e4Smiod BFD_JUMP_TABLE_COPY (coff),
3224*3d8817e4Smiod BFD_JUMP_TABLE_CORE (_bfd_nocore),
3225*3d8817e4Smiod BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
3226*3d8817e4Smiod BFD_JUMP_TABLE_SYMBOLS (coff),
3227*3d8817e4Smiod BFD_JUMP_TABLE_RELOCS (coff),
3228*3d8817e4Smiod BFD_JUMP_TABLE_WRITE (coff),
3229*3d8817e4Smiod BFD_JUMP_TABLE_LINK (coff),
3230*3d8817e4Smiod BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
3231*3d8817e4Smiod
3232*3d8817e4Smiod & shcoff_small_vec,
3233*3d8817e4Smiod
3234*3d8817e4Smiod (PTR) &bfd_coff_small_swap_table
3235*3d8817e4Smiod };
3236*3d8817e4Smiod #endif
3237