1c074d1c9Sdrahn /* BFD back-end for Renesas Super-H COFF binaries.
2c074d1c9Sdrahn Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
3b55d4692Sfgsch Free Software Foundation, Inc.
42159047fSniklas Contributed by Cygnus Support.
52159047fSniklas Written by Steve Chamberlain, <sac@cygnus.com>.
6c88b1d6cSniklas Relaxing code written by Ian Lance Taylor, <ian@cygnus.com>.
72159047fSniklas
82159047fSniklas This file is part of BFD, the Binary File Descriptor library.
92159047fSniklas
102159047fSniklas This program is free software; you can redistribute it and/or modify
112159047fSniklas it under the terms of the GNU General Public License as published by
122159047fSniklas the Free Software Foundation; either version 2 of the License, or
132159047fSniklas (at your option) any later version.
142159047fSniklas
152159047fSniklas This program is distributed in the hope that it will be useful,
162159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
172159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
182159047fSniklas GNU General Public License for more details.
192159047fSniklas
202159047fSniklas You should have received a copy of the GNU General Public License
212159047fSniklas along with this program; if not, write to the Free Software
222159047fSniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
232159047fSniklas
242159047fSniklas #include "bfd.h"
252159047fSniklas #include "sysdep.h"
26c074d1c9Sdrahn #include "libiberty.h"
272159047fSniklas #include "libbfd.h"
282159047fSniklas #include "bfdlink.h"
292159047fSniklas #include "coff/sh.h"
302159047fSniklas #include "coff/internal.h"
31b305b0f1Sespie
32b305b0f1Sespie #ifdef COFF_WITH_PE
33b305b0f1Sespie #include "coff/pe.h"
34b305b0f1Sespie
35b305b0f1Sespie #ifndef COFF_IMAGE_WITH_PE
36c074d1c9Sdrahn static bfd_boolean sh_align_load_span
37b305b0f1Sespie PARAMS ((bfd *, asection *, bfd_byte *,
38c074d1c9Sdrahn bfd_boolean (*) (bfd *, asection *, PTR, bfd_byte *, bfd_vma),
39c074d1c9Sdrahn PTR, bfd_vma **, bfd_vma *, bfd_vma, bfd_vma, bfd_boolean *));
40b305b0f1Sespie
41b305b0f1Sespie #define _bfd_sh_align_load_span sh_align_load_span
42b305b0f1Sespie #endif
43b305b0f1Sespie #endif
44b305b0f1Sespie
452159047fSniklas #include "libcoff.h"
462159047fSniklas
472159047fSniklas /* Internal functions. */
482159047fSniklas static bfd_reloc_status_type sh_reloc
492159047fSniklas PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
502159047fSniklas static long get_symbol_value PARAMS ((asymbol *));
51c074d1c9Sdrahn static bfd_boolean sh_relax_section
52c074d1c9Sdrahn PARAMS ((bfd *, asection *, struct bfd_link_info *, bfd_boolean *));
53c074d1c9Sdrahn static bfd_boolean sh_relax_delete_bytes
542159047fSniklas PARAMS ((bfd *, asection *, bfd_vma, int));
55b305b0f1Sespie #ifndef COFF_IMAGE_WITH_PE
56c88b1d6cSniklas static const struct sh_opcode *sh_insn_info PARAMS ((unsigned int));
57b305b0f1Sespie #endif
58c074d1c9Sdrahn static bfd_boolean sh_align_loads
59c074d1c9Sdrahn PARAMS ((bfd *, asection *, struct internal_reloc *, bfd_byte *,
60c074d1c9Sdrahn bfd_boolean *));
61c074d1c9Sdrahn static bfd_boolean sh_swap_insns
620c6d0228Sniklas PARAMS ((bfd *, asection *, PTR, bfd_byte *, bfd_vma));
63c074d1c9Sdrahn static bfd_boolean sh_relocate_section
642159047fSniklas PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
652159047fSniklas struct internal_reloc *, struct internal_syment *, asection **));
662159047fSniklas static bfd_byte *sh_coff_get_relocated_section_contents
672159047fSniklas PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
68c074d1c9Sdrahn bfd_byte *, bfd_boolean, asymbol **));
69c074d1c9Sdrahn static reloc_howto_type * sh_coff_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type));
702159047fSniklas
71b305b0f1Sespie #ifdef COFF_WITH_PE
72b305b0f1Sespie /* Can't build import tables with 2**4 alignment. */
73b305b0f1Sespie #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 2
74b305b0f1Sespie #else
75c88b1d6cSniklas /* Default section alignment to 2**4. */
76b305b0f1Sespie #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 4
77b305b0f1Sespie #endif
78b305b0f1Sespie
79b305b0f1Sespie #ifdef COFF_IMAGE_WITH_PE
80b305b0f1Sespie /* Align PE executables. */
81b305b0f1Sespie #define COFF_PAGE_SIZE 0x1000
82b305b0f1Sespie #endif
832159047fSniklas
842159047fSniklas /* Generate long file names. */
852159047fSniklas #define COFF_LONG_FILENAMES
862159047fSniklas
87b305b0f1Sespie #ifdef COFF_WITH_PE
88c074d1c9Sdrahn static bfd_boolean in_reloc_p PARAMS ((bfd *, reloc_howto_type *));
89c074d1c9Sdrahn /* Return TRUE if this relocation should
90b305b0f1Sespie appear in the output .reloc section. */
in_reloc_p(abfd,howto)91c074d1c9Sdrahn static bfd_boolean in_reloc_p (abfd, howto)
92b305b0f1Sespie bfd * abfd ATTRIBUTE_UNUSED;
93b305b0f1Sespie reloc_howto_type * howto;
94b305b0f1Sespie {
95b305b0f1Sespie return ! howto->pc_relative && howto->type != R_SH_IMAGEBASE;
96b305b0f1Sespie }
97b305b0f1Sespie #endif
98b305b0f1Sespie
992159047fSniklas /* The supported relocations. There are a lot of relocations defined
1002159047fSniklas in coff/internal.h which we do not expect to ever see. */
1012159047fSniklas static reloc_howto_type sh_coff_howtos[] =
1022159047fSniklas {
103b305b0f1Sespie EMPTY_HOWTO (0),
104b305b0f1Sespie EMPTY_HOWTO (1),
105b305b0f1Sespie #ifdef COFF_WITH_PE
106b305b0f1Sespie /* Windows CE */
107b305b0f1Sespie HOWTO (R_SH_IMM32CE, /* type */
108b305b0f1Sespie 0, /* rightshift */
109b305b0f1Sespie 2, /* size (0 = byte, 1 = short, 2 = long) */
110b305b0f1Sespie 32, /* bitsize */
111c074d1c9Sdrahn FALSE, /* pc_relative */
112b305b0f1Sespie 0, /* bitpos */
113b305b0f1Sespie complain_overflow_bitfield, /* complain_on_overflow */
114b305b0f1Sespie sh_reloc, /* special_function */
115b305b0f1Sespie "r_imm32ce", /* name */
116c074d1c9Sdrahn TRUE, /* partial_inplace */
117b305b0f1Sespie 0xffffffff, /* src_mask */
118b305b0f1Sespie 0xffffffff, /* dst_mask */
119c074d1c9Sdrahn FALSE), /* pcrel_offset */
120b305b0f1Sespie #else
121b305b0f1Sespie EMPTY_HOWTO (2),
122b305b0f1Sespie #endif
123b305b0f1Sespie EMPTY_HOWTO (3), /* R_SH_PCREL8 */
124b305b0f1Sespie EMPTY_HOWTO (4), /* R_SH_PCREL16 */
125b305b0f1Sespie EMPTY_HOWTO (5), /* R_SH_HIGH8 */
126b305b0f1Sespie EMPTY_HOWTO (6), /* R_SH_IMM24 */
127b305b0f1Sespie EMPTY_HOWTO (7), /* R_SH_LOW16 */
128b305b0f1Sespie EMPTY_HOWTO (8),
129b305b0f1Sespie EMPTY_HOWTO (9), /* R_SH_PCDISP8BY4 */
1302159047fSniklas
1312159047fSniklas HOWTO (R_SH_PCDISP8BY2, /* type */
1322159047fSniklas 1, /* rightshift */
1332159047fSniklas 1, /* size (0 = byte, 1 = short, 2 = long) */
1342159047fSniklas 8, /* bitsize */
135c074d1c9Sdrahn TRUE, /* pc_relative */
1362159047fSniklas 0, /* bitpos */
1372159047fSniklas complain_overflow_signed, /* complain_on_overflow */
1382159047fSniklas sh_reloc, /* special_function */
1392159047fSniklas "r_pcdisp8by2", /* name */
140c074d1c9Sdrahn TRUE, /* partial_inplace */
1412159047fSniklas 0xff, /* src_mask */
1422159047fSniklas 0xff, /* dst_mask */
143c074d1c9Sdrahn TRUE), /* pcrel_offset */
1442159047fSniklas
145b305b0f1Sespie EMPTY_HOWTO (11), /* R_SH_PCDISP8 */
1462159047fSniklas
1472159047fSniklas HOWTO (R_SH_PCDISP, /* type */
1482159047fSniklas 1, /* rightshift */
1492159047fSniklas 1, /* size (0 = byte, 1 = short, 2 = long) */
1502159047fSniklas 12, /* bitsize */
151c074d1c9Sdrahn TRUE, /* pc_relative */
1522159047fSniklas 0, /* bitpos */
1532159047fSniklas complain_overflow_signed, /* complain_on_overflow */
1542159047fSniklas sh_reloc, /* special_function */
1552159047fSniklas "r_pcdisp12by2", /* name */
156c074d1c9Sdrahn TRUE, /* partial_inplace */
1572159047fSniklas 0xfff, /* src_mask */
1582159047fSniklas 0xfff, /* dst_mask */
159c074d1c9Sdrahn TRUE), /* pcrel_offset */
1602159047fSniklas
161b305b0f1Sespie EMPTY_HOWTO (13),
1622159047fSniklas
1632159047fSniklas HOWTO (R_SH_IMM32, /* type */
1642159047fSniklas 0, /* rightshift */
1652159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
1662159047fSniklas 32, /* bitsize */
167c074d1c9Sdrahn FALSE, /* pc_relative */
1682159047fSniklas 0, /* bitpos */
1692159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
1702159047fSniklas sh_reloc, /* special_function */
1712159047fSniklas "r_imm32", /* name */
172c074d1c9Sdrahn TRUE, /* partial_inplace */
1732159047fSniklas 0xffffffff, /* src_mask */
1742159047fSniklas 0xffffffff, /* dst_mask */
175c074d1c9Sdrahn FALSE), /* pcrel_offset */
1762159047fSniklas
177b305b0f1Sespie EMPTY_HOWTO (15),
178b305b0f1Sespie #ifdef COFF_WITH_PE
179b305b0f1Sespie HOWTO (R_SH_IMAGEBASE, /* type */
180b305b0f1Sespie 0, /* rightshift */
181b305b0f1Sespie 2, /* size (0 = byte, 1 = short, 2 = long) */
182b305b0f1Sespie 32, /* bitsize */
183c074d1c9Sdrahn FALSE, /* pc_relative */
184b305b0f1Sespie 0, /* bitpos */
185b305b0f1Sespie complain_overflow_bitfield, /* complain_on_overflow */
186b305b0f1Sespie sh_reloc, /* special_function */
187b305b0f1Sespie "rva32", /* name */
188c074d1c9Sdrahn TRUE, /* partial_inplace */
189b305b0f1Sespie 0xffffffff, /* src_mask */
190b305b0f1Sespie 0xffffffff, /* dst_mask */
191c074d1c9Sdrahn FALSE), /* pcrel_offset */
192b305b0f1Sespie #else
193b305b0f1Sespie EMPTY_HOWTO (16), /* R_SH_IMM8 */
194b305b0f1Sespie #endif
195b305b0f1Sespie EMPTY_HOWTO (17), /* R_SH_IMM8BY2 */
196b305b0f1Sespie EMPTY_HOWTO (18), /* R_SH_IMM8BY4 */
197b305b0f1Sespie EMPTY_HOWTO (19), /* R_SH_IMM4 */
198b305b0f1Sespie EMPTY_HOWTO (20), /* R_SH_IMM4BY2 */
199b305b0f1Sespie EMPTY_HOWTO (21), /* R_SH_IMM4BY4 */
2002159047fSniklas
2012159047fSniklas HOWTO (R_SH_PCRELIMM8BY2, /* type */
2022159047fSniklas 1, /* rightshift */
2032159047fSniklas 1, /* size (0 = byte, 1 = short, 2 = long) */
2042159047fSniklas 8, /* bitsize */
205c074d1c9Sdrahn TRUE, /* pc_relative */
2062159047fSniklas 0, /* bitpos */
2072159047fSniklas complain_overflow_unsigned, /* complain_on_overflow */
2082159047fSniklas sh_reloc, /* special_function */
2092159047fSniklas "r_pcrelimm8by2", /* name */
210c074d1c9Sdrahn TRUE, /* partial_inplace */
2112159047fSniklas 0xff, /* src_mask */
2122159047fSniklas 0xff, /* dst_mask */
213c074d1c9Sdrahn TRUE), /* pcrel_offset */
2142159047fSniklas
2152159047fSniklas HOWTO (R_SH_PCRELIMM8BY4, /* type */
2162159047fSniklas 2, /* rightshift */
2172159047fSniklas 1, /* size (0 = byte, 1 = short, 2 = long) */
2182159047fSniklas 8, /* bitsize */
219c074d1c9Sdrahn TRUE, /* pc_relative */
2202159047fSniklas 0, /* bitpos */
2212159047fSniklas complain_overflow_unsigned, /* complain_on_overflow */
2222159047fSniklas sh_reloc, /* special_function */
2232159047fSniklas "r_pcrelimm8by4", /* name */
224c074d1c9Sdrahn TRUE, /* partial_inplace */
2252159047fSniklas 0xff, /* src_mask */
2262159047fSniklas 0xff, /* dst_mask */
227c074d1c9Sdrahn TRUE), /* pcrel_offset */
2282159047fSniklas
2292159047fSniklas HOWTO (R_SH_IMM16, /* type */
2302159047fSniklas 0, /* rightshift */
2312159047fSniklas 1, /* size (0 = byte, 1 = short, 2 = long) */
2322159047fSniklas 16, /* bitsize */
233c074d1c9Sdrahn FALSE, /* pc_relative */
2342159047fSniklas 0, /* bitpos */
2352159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
2362159047fSniklas sh_reloc, /* special_function */
2372159047fSniklas "r_imm16", /* name */
238c074d1c9Sdrahn TRUE, /* partial_inplace */
2392159047fSniklas 0xffff, /* src_mask */
2402159047fSniklas 0xffff, /* dst_mask */
241c074d1c9Sdrahn FALSE), /* pcrel_offset */
2422159047fSniklas
2432159047fSniklas HOWTO (R_SH_SWITCH16, /* type */
2442159047fSniklas 0, /* rightshift */
2452159047fSniklas 1, /* size (0 = byte, 1 = short, 2 = long) */
2462159047fSniklas 16, /* bitsize */
247c074d1c9Sdrahn FALSE, /* pc_relative */
2482159047fSniklas 0, /* bitpos */
2492159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
2502159047fSniklas sh_reloc, /* special_function */
2512159047fSniklas "r_switch16", /* name */
252c074d1c9Sdrahn TRUE, /* partial_inplace */
2532159047fSniklas 0xffff, /* src_mask */
2542159047fSniklas 0xffff, /* dst_mask */
255c074d1c9Sdrahn FALSE), /* pcrel_offset */
2562159047fSniklas
2572159047fSniklas HOWTO (R_SH_SWITCH32, /* type */
2582159047fSniklas 0, /* rightshift */
2592159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
2602159047fSniklas 32, /* bitsize */
261c074d1c9Sdrahn FALSE, /* pc_relative */
2622159047fSniklas 0, /* bitpos */
2632159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
2642159047fSniklas sh_reloc, /* special_function */
2652159047fSniklas "r_switch32", /* name */
266c074d1c9Sdrahn TRUE, /* partial_inplace */
2672159047fSniklas 0xffffffff, /* src_mask */
2682159047fSniklas 0xffffffff, /* dst_mask */
269c074d1c9Sdrahn FALSE), /* pcrel_offset */
2702159047fSniklas
2712159047fSniklas HOWTO (R_SH_USES, /* type */
2722159047fSniklas 0, /* rightshift */
2732159047fSniklas 1, /* size (0 = byte, 1 = short, 2 = long) */
2742159047fSniklas 16, /* bitsize */
275c074d1c9Sdrahn FALSE, /* pc_relative */
2762159047fSniklas 0, /* bitpos */
2772159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
2782159047fSniklas sh_reloc, /* special_function */
2792159047fSniklas "r_uses", /* name */
280c074d1c9Sdrahn TRUE, /* partial_inplace */
2812159047fSniklas 0xffff, /* src_mask */
2822159047fSniklas 0xffff, /* dst_mask */
283c074d1c9Sdrahn FALSE), /* pcrel_offset */
2842159047fSniklas
2852159047fSniklas HOWTO (R_SH_COUNT, /* type */
2862159047fSniklas 0, /* rightshift */
2872159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
2882159047fSniklas 32, /* bitsize */
289c074d1c9Sdrahn FALSE, /* pc_relative */
2902159047fSniklas 0, /* bitpos */
2912159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
2922159047fSniklas sh_reloc, /* special_function */
2932159047fSniklas "r_count", /* name */
294c074d1c9Sdrahn TRUE, /* partial_inplace */
2952159047fSniklas 0xffffffff, /* src_mask */
2962159047fSniklas 0xffffffff, /* dst_mask */
297c074d1c9Sdrahn FALSE), /* pcrel_offset */
2982159047fSniklas
2992159047fSniklas HOWTO (R_SH_ALIGN, /* type */
3002159047fSniklas 0, /* rightshift */
3012159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
3022159047fSniklas 32, /* bitsize */
303c074d1c9Sdrahn FALSE, /* pc_relative */
3042159047fSniklas 0, /* bitpos */
3052159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
3062159047fSniklas sh_reloc, /* special_function */
3072159047fSniklas "r_align", /* name */
308c074d1c9Sdrahn TRUE, /* partial_inplace */
3092159047fSniklas 0xffffffff, /* src_mask */
3102159047fSniklas 0xffffffff, /* dst_mask */
311c074d1c9Sdrahn FALSE), /* pcrel_offset */
312c88b1d6cSniklas
313c88b1d6cSniklas HOWTO (R_SH_CODE, /* type */
314c88b1d6cSniklas 0, /* rightshift */
315c88b1d6cSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
316c88b1d6cSniklas 32, /* bitsize */
317c074d1c9Sdrahn FALSE, /* pc_relative */
318c88b1d6cSniklas 0, /* bitpos */
319c88b1d6cSniklas complain_overflow_bitfield, /* complain_on_overflow */
320c88b1d6cSniklas sh_reloc, /* special_function */
321c88b1d6cSniklas "r_code", /* name */
322c074d1c9Sdrahn TRUE, /* partial_inplace */
323c88b1d6cSniklas 0xffffffff, /* src_mask */
324c88b1d6cSniklas 0xffffffff, /* dst_mask */
325c074d1c9Sdrahn FALSE), /* pcrel_offset */
326c88b1d6cSniklas
327c88b1d6cSniklas HOWTO (R_SH_DATA, /* type */
328c88b1d6cSniklas 0, /* rightshift */
329c88b1d6cSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
330c88b1d6cSniklas 32, /* bitsize */
331c074d1c9Sdrahn FALSE, /* pc_relative */
332c88b1d6cSniklas 0, /* bitpos */
333c88b1d6cSniklas complain_overflow_bitfield, /* complain_on_overflow */
334c88b1d6cSniklas sh_reloc, /* special_function */
335c88b1d6cSniklas "r_data", /* name */
336c074d1c9Sdrahn TRUE, /* partial_inplace */
337c88b1d6cSniklas 0xffffffff, /* src_mask */
338c88b1d6cSniklas 0xffffffff, /* dst_mask */
339c074d1c9Sdrahn FALSE), /* pcrel_offset */
340c88b1d6cSniklas
341c88b1d6cSniklas HOWTO (R_SH_LABEL, /* type */
342c88b1d6cSniklas 0, /* rightshift */
343c88b1d6cSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
344c88b1d6cSniklas 32, /* bitsize */
345c074d1c9Sdrahn FALSE, /* pc_relative */
346c88b1d6cSniklas 0, /* bitpos */
347c88b1d6cSniklas complain_overflow_bitfield, /* complain_on_overflow */
348c88b1d6cSniklas sh_reloc, /* special_function */
349c88b1d6cSniklas "r_label", /* name */
350c074d1c9Sdrahn TRUE, /* partial_inplace */
351c88b1d6cSniklas 0xffffffff, /* src_mask */
352c88b1d6cSniklas 0xffffffff, /* dst_mask */
353c074d1c9Sdrahn FALSE), /* pcrel_offset */
354b305b0f1Sespie
355b305b0f1Sespie HOWTO (R_SH_SWITCH8, /* type */
356b305b0f1Sespie 0, /* rightshift */
357b305b0f1Sespie 0, /* size (0 = byte, 1 = short, 2 = long) */
358b305b0f1Sespie 8, /* bitsize */
359c074d1c9Sdrahn FALSE, /* pc_relative */
360b305b0f1Sespie 0, /* bitpos */
361b305b0f1Sespie complain_overflow_bitfield, /* complain_on_overflow */
362b305b0f1Sespie sh_reloc, /* special_function */
363b305b0f1Sespie "r_switch8", /* name */
364c074d1c9Sdrahn TRUE, /* partial_inplace */
365b305b0f1Sespie 0xff, /* src_mask */
366b305b0f1Sespie 0xff, /* dst_mask */
367c074d1c9Sdrahn FALSE) /* pcrel_offset */
3682159047fSniklas };
3692159047fSniklas
3702159047fSniklas #define SH_COFF_HOWTO_COUNT (sizeof sh_coff_howtos / sizeof sh_coff_howtos[0])
3712159047fSniklas
3722159047fSniklas /* Check for a bad magic number. */
3732159047fSniklas #define BADMAG(x) SHBADMAG(x)
3742159047fSniklas
3752159047fSniklas /* Customize coffcode.h (this is not currently used). */
3762159047fSniklas #define SH 1
3772159047fSniklas
3782159047fSniklas /* FIXME: This should not be set here. */
3792159047fSniklas #define __A_MAGIC_SET__
3802159047fSniklas
381b305b0f1Sespie #ifndef COFF_WITH_PE
3822159047fSniklas /* Swap the r_offset field in and out. */
383c074d1c9Sdrahn #define SWAP_IN_RELOC_OFFSET H_GET_32
384c074d1c9Sdrahn #define SWAP_OUT_RELOC_OFFSET H_PUT_32
3852159047fSniklas
3862159047fSniklas /* Swap out extra information in the reloc structure. */
3872159047fSniklas #define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
3882159047fSniklas do \
3892159047fSniklas { \
3902159047fSniklas dst->r_stuff[0] = 'S'; \
3912159047fSniklas dst->r_stuff[1] = 'C'; \
3922159047fSniklas } \
3932159047fSniklas while (0)
394b305b0f1Sespie #endif
3952159047fSniklas
3962159047fSniklas /* Get the value of a symbol, when performing a relocation. */
3972159047fSniklas
3982159047fSniklas static long
get_symbol_value(symbol)3992159047fSniklas get_symbol_value (symbol)
4002159047fSniklas asymbol *symbol;
4012159047fSniklas {
4022159047fSniklas bfd_vma relocation;
4032159047fSniklas
4042159047fSniklas if (bfd_is_com_section (symbol->section))
4052159047fSniklas relocation = 0;
4062159047fSniklas else
4072159047fSniklas relocation = (symbol->value +
4082159047fSniklas symbol->section->output_section->vma +
4092159047fSniklas symbol->section->output_offset);
4102159047fSniklas
4112159047fSniklas return relocation;
4122159047fSniklas }
4132159047fSniklas
414b305b0f1Sespie #ifdef COFF_WITH_PE
415b305b0f1Sespie /* Convert an rtype to howto for the COFF backend linker.
416b305b0f1Sespie Copied from coff-i386. */
417b305b0f1Sespie #define coff_rtype_to_howto coff_sh_rtype_to_howto
418c074d1c9Sdrahn 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 *));
419b305b0f1Sespie
420b305b0f1Sespie static reloc_howto_type *
coff_sh_rtype_to_howto(abfd,sec,rel,h,sym,addendp)421b305b0f1Sespie coff_sh_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
422b305b0f1Sespie bfd * abfd ATTRIBUTE_UNUSED;
423b305b0f1Sespie asection * sec;
424b305b0f1Sespie struct internal_reloc * rel;
425b305b0f1Sespie struct coff_link_hash_entry * h;
426b305b0f1Sespie struct internal_syment * sym;
427b305b0f1Sespie bfd_vma * addendp;
428b305b0f1Sespie {
429b305b0f1Sespie reloc_howto_type * howto;
430b305b0f1Sespie
431b305b0f1Sespie howto = sh_coff_howtos + rel->r_type;
432b305b0f1Sespie
433b305b0f1Sespie *addendp = 0;
434b305b0f1Sespie
435b305b0f1Sespie if (howto->pc_relative)
436b305b0f1Sespie *addendp += sec->vma;
437b305b0f1Sespie
438b305b0f1Sespie if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
439b305b0f1Sespie {
440b305b0f1Sespie /* This is a common symbol. The section contents include the
441b305b0f1Sespie size (sym->n_value) as an addend. The relocate_section
442b305b0f1Sespie function will be adding in the final value of the symbol. We
443b305b0f1Sespie need to subtract out the current size in order to get the
444b305b0f1Sespie correct result. */
445b305b0f1Sespie BFD_ASSERT (h != NULL);
446b305b0f1Sespie }
447b305b0f1Sespie
448b305b0f1Sespie if (howto->pc_relative)
449b305b0f1Sespie {
450b305b0f1Sespie *addendp -= 4;
451b305b0f1Sespie
452b305b0f1Sespie /* If the symbol is defined, then the generic code is going to
453b305b0f1Sespie add back the symbol value in order to cancel out an
454b305b0f1Sespie adjustment it made to the addend. However, we set the addend
455b305b0f1Sespie to 0 at the start of this function. We need to adjust here,
456b305b0f1Sespie to avoid the adjustment the generic code will make. FIXME:
457b305b0f1Sespie This is getting a bit hackish. */
458b305b0f1Sespie if (sym != NULL && sym->n_scnum != 0)
459b305b0f1Sespie *addendp -= sym->n_value;
460b305b0f1Sespie }
461b305b0f1Sespie
462b305b0f1Sespie if (rel->r_type == R_SH_IMAGEBASE)
463b305b0f1Sespie *addendp -= pe_data (sec->output_section->owner)->pe_opthdr.ImageBase;
464b305b0f1Sespie
465b305b0f1Sespie return howto;
466b305b0f1Sespie }
467b305b0f1Sespie
468c074d1c9Sdrahn #endif /* COFF_WITH_PE */
469c074d1c9Sdrahn
470b305b0f1Sespie /* This structure is used to map BFD reloc codes to SH PE relocs. */
471b305b0f1Sespie struct shcoff_reloc_map
472b305b0f1Sespie {
473c074d1c9Sdrahn bfd_reloc_code_real_type bfd_reloc_val;
474b305b0f1Sespie unsigned char shcoff_reloc_val;
475b305b0f1Sespie };
476b305b0f1Sespie
477c074d1c9Sdrahn #ifdef COFF_WITH_PE
478b305b0f1Sespie /* An array mapping BFD reloc codes to SH PE relocs. */
479b305b0f1Sespie static const struct shcoff_reloc_map sh_reloc_map[] =
480b305b0f1Sespie {
481b305b0f1Sespie { BFD_RELOC_32, R_SH_IMM32CE },
482b305b0f1Sespie { BFD_RELOC_RVA, R_SH_IMAGEBASE },
483b305b0f1Sespie { BFD_RELOC_CTOR, R_SH_IMM32CE },
484b305b0f1Sespie };
485c074d1c9Sdrahn #else
486c074d1c9Sdrahn /* An array mapping BFD reloc codes to SH PE relocs. */
487c074d1c9Sdrahn static const struct shcoff_reloc_map sh_reloc_map[] =
488c074d1c9Sdrahn {
489c074d1c9Sdrahn { BFD_RELOC_32, R_SH_IMM32 },
490c074d1c9Sdrahn { BFD_RELOC_CTOR, R_SH_IMM32 },
491c074d1c9Sdrahn };
492c074d1c9Sdrahn #endif
493b305b0f1Sespie
494b305b0f1Sespie /* Given a BFD reloc code, return the howto structure for the
495b305b0f1Sespie corresponding SH PE reloc. */
496b305b0f1Sespie #define coff_bfd_reloc_type_lookup sh_coff_reloc_type_lookup
497b305b0f1Sespie
498b305b0f1Sespie static reloc_howto_type *
sh_coff_reloc_type_lookup(abfd,code)499b305b0f1Sespie sh_coff_reloc_type_lookup (abfd, code)
500b305b0f1Sespie bfd * abfd ATTRIBUTE_UNUSED;
501b305b0f1Sespie bfd_reloc_code_real_type code;
502b305b0f1Sespie {
503b305b0f1Sespie unsigned int i;
504b305b0f1Sespie
505c074d1c9Sdrahn for (i = ARRAY_SIZE (sh_reloc_map); i--;)
506b305b0f1Sespie if (sh_reloc_map[i].bfd_reloc_val == code)
507b305b0f1Sespie return &sh_coff_howtos[(int) sh_reloc_map[i].shcoff_reloc_val];
508b305b0f1Sespie
509b305b0f1Sespie fprintf (stderr, "SH Error: unknown reloc type %d\n", code);
510b305b0f1Sespie return NULL;
511b305b0f1Sespie }
512b305b0f1Sespie
5132159047fSniklas /* This macro is used in coffcode.h to get the howto corresponding to
5142159047fSniklas an internal reloc. */
5152159047fSniklas
5162159047fSniklas #define RTYPE2HOWTO(relent, internal) \
5172159047fSniklas ((relent)->howto = \
5182159047fSniklas ((internal)->r_type < SH_COFF_HOWTO_COUNT \
5192159047fSniklas ? &sh_coff_howtos[(internal)->r_type] \
5202159047fSniklas : (reloc_howto_type *) NULL))
5212159047fSniklas
5222159047fSniklas /* This is the same as the macro in coffcode.h, except that it copies
5232159047fSniklas r_offset into reloc_entry->addend for some relocs. */
5242159047fSniklas #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
5252159047fSniklas { \
5262159047fSniklas coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
5272159047fSniklas if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
5282159047fSniklas coffsym = (obj_symbols (abfd) \
5292159047fSniklas + (cache_ptr->sym_ptr_ptr - symbols)); \
5302159047fSniklas else if (ptr) \
5312159047fSniklas coffsym = coff_symbol_from (abfd, ptr); \
5322159047fSniklas if (coffsym != (coff_symbol_type *) NULL \
5332159047fSniklas && coffsym->native->u.syment.n_scnum == 0) \
5342159047fSniklas cache_ptr->addend = 0; \
5352159047fSniklas else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
5362159047fSniklas && ptr->section != (asection *) NULL) \
5372159047fSniklas cache_ptr->addend = - (ptr->section->vma + ptr->value); \
5382159047fSniklas else \
5392159047fSniklas cache_ptr->addend = 0; \
540b305b0f1Sespie if ((reloc).r_type == R_SH_SWITCH8 \
541b305b0f1Sespie || (reloc).r_type == R_SH_SWITCH16 \
5422159047fSniklas || (reloc).r_type == R_SH_SWITCH32 \
5432159047fSniklas || (reloc).r_type == R_SH_USES \
5442159047fSniklas || (reloc).r_type == R_SH_COUNT \
5452159047fSniklas || (reloc).r_type == R_SH_ALIGN) \
5462159047fSniklas cache_ptr->addend = (reloc).r_offset; \
5472159047fSniklas }
5482159047fSniklas
5492159047fSniklas /* This is the howto function for the SH relocations. */
5502159047fSniklas
5512159047fSniklas static bfd_reloc_status_type
sh_reloc(abfd,reloc_entry,symbol_in,data,input_section,output_bfd,error_message)5522159047fSniklas sh_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
5532159047fSniklas error_message)
5542159047fSniklas bfd *abfd;
5552159047fSniklas arelent *reloc_entry;
5562159047fSniklas asymbol *symbol_in;
5572159047fSniklas PTR data;
5582159047fSniklas asection *input_section;
5592159047fSniklas bfd *output_bfd;
560b305b0f1Sespie char **error_message ATTRIBUTE_UNUSED;
5612159047fSniklas {
5622159047fSniklas unsigned long insn;
5632159047fSniklas bfd_vma sym_value;
5642159047fSniklas unsigned short r_type;
5652159047fSniklas bfd_vma addr = reloc_entry->address;
5662159047fSniklas bfd_byte *hit_data = addr + (bfd_byte *) data;
5672159047fSniklas
5682159047fSniklas r_type = reloc_entry->howto->type;
5692159047fSniklas
5702159047fSniklas if (output_bfd != NULL)
5712159047fSniklas {
5722159047fSniklas /* Partial linking--do nothing. */
5732159047fSniklas reloc_entry->address += input_section->output_offset;
5742159047fSniklas return bfd_reloc_ok;
5752159047fSniklas }
5762159047fSniklas
5772159047fSniklas /* Almost all relocs have to do with relaxing. If any work must be
5782159047fSniklas done for them, it has been done in sh_relax_section. */
5792159047fSniklas if (r_type != R_SH_IMM32
580b305b0f1Sespie #ifdef COFF_WITH_PE
581b305b0f1Sespie && r_type != R_SH_IMM32CE
582b305b0f1Sespie && r_type != R_SH_IMAGEBASE
583b305b0f1Sespie #endif
5842159047fSniklas && (r_type != R_SH_PCDISP
5852159047fSniklas || (symbol_in->flags & BSF_LOCAL) != 0))
5862159047fSniklas return bfd_reloc_ok;
5872159047fSniklas
5882159047fSniklas if (symbol_in != NULL
5892159047fSniklas && bfd_is_und_section (symbol_in->section))
5902159047fSniklas return bfd_reloc_undefined;
5912159047fSniklas
5922159047fSniklas sym_value = get_symbol_value (symbol_in);
5932159047fSniklas
5942159047fSniklas switch (r_type)
5952159047fSniklas {
5962159047fSniklas case R_SH_IMM32:
597b305b0f1Sespie #ifdef COFF_WITH_PE
598b305b0f1Sespie case R_SH_IMM32CE:
599b305b0f1Sespie #endif
6002159047fSniklas insn = bfd_get_32 (abfd, hit_data);
6012159047fSniklas insn += sym_value + reloc_entry->addend;
602c074d1c9Sdrahn bfd_put_32 (abfd, (bfd_vma) insn, hit_data);
6032159047fSniklas break;
604b305b0f1Sespie #ifdef COFF_WITH_PE
605b305b0f1Sespie case R_SH_IMAGEBASE:
606b305b0f1Sespie insn = bfd_get_32 (abfd, hit_data);
607c074d1c9Sdrahn insn += sym_value + reloc_entry->addend;
608c074d1c9Sdrahn insn -= pe_data (input_section->output_section->owner)->pe_opthdr.ImageBase;
609c074d1c9Sdrahn bfd_put_32 (abfd, (bfd_vma) insn, hit_data);
610b305b0f1Sespie break;
611b305b0f1Sespie #endif
6122159047fSniklas case R_SH_PCDISP:
6132159047fSniklas insn = bfd_get_16 (abfd, hit_data);
6142159047fSniklas sym_value += reloc_entry->addend;
6152159047fSniklas sym_value -= (input_section->output_section->vma
6162159047fSniklas + input_section->output_offset
6172159047fSniklas + addr
6182159047fSniklas + 4);
6192159047fSniklas sym_value += (insn & 0xfff) << 1;
6202159047fSniklas if (insn & 0x800)
6212159047fSniklas sym_value -= 0x1000;
6222159047fSniklas insn = (insn & 0xf000) | (sym_value & 0xfff);
623c074d1c9Sdrahn bfd_put_16 (abfd, (bfd_vma) insn, hit_data);
6242159047fSniklas if (sym_value < (bfd_vma) -0x1000 || sym_value >= 0x1000)
6252159047fSniklas return bfd_reloc_overflow;
6262159047fSniklas break;
6272159047fSniklas default:
6282159047fSniklas abort ();
6292159047fSniklas break;
6302159047fSniklas }
6312159047fSniklas
6322159047fSniklas return bfd_reloc_ok;
6332159047fSniklas }
6342159047fSniklas
635b305b0f1Sespie #define coff_bfd_merge_private_bfd_data _bfd_generic_verify_endian_match
636b305b0f1Sespie
6372159047fSniklas /* We can do relaxing. */
6382159047fSniklas #define coff_bfd_relax_section sh_relax_section
6392159047fSniklas
6402159047fSniklas /* We use the special COFF backend linker. */
6412159047fSniklas #define coff_relocate_section sh_relocate_section
6422159047fSniklas
6432159047fSniklas /* When relaxing, we need to use special code to get the relocated
6442159047fSniklas section contents. */
6452159047fSniklas #define coff_bfd_get_relocated_section_contents \
6462159047fSniklas sh_coff_get_relocated_section_contents
6472159047fSniklas
6482159047fSniklas #include "coffcode.h"
649c88b1d6cSniklas
6502159047fSniklas /* This function handles relaxing on the SH.
6512159047fSniklas
6522159047fSniklas Function calls on the SH look like this:
6532159047fSniklas
6542159047fSniklas movl L1,r0
6552159047fSniklas ...
6562159047fSniklas jsr @r0
6572159047fSniklas ...
6582159047fSniklas L1:
6592159047fSniklas .long function
6602159047fSniklas
6612159047fSniklas The compiler and assembler will cooperate to create R_SH_USES
6622159047fSniklas relocs on the jsr instructions. The r_offset field of the
6632159047fSniklas R_SH_USES reloc is the PC relative offset to the instruction which
6642159047fSniklas loads the register (the r_offset field is computed as though it
6652159047fSniklas were a jump instruction, so the offset value is actually from four
6662159047fSniklas bytes past the instruction). The linker can use this reloc to
6672159047fSniklas determine just which function is being called, and thus decide
6682159047fSniklas whether it is possible to replace the jsr with a bsr.
6692159047fSniklas
6702159047fSniklas If multiple function calls are all based on a single register load
6712159047fSniklas (i.e., the same function is called multiple times), the compiler
6722159047fSniklas guarantees that each function call will have an R_SH_USES reloc.
6732159047fSniklas Therefore, if the linker is able to convert each R_SH_USES reloc
6742159047fSniklas which refers to that address, it can safely eliminate the register
6752159047fSniklas load.
6762159047fSniklas
6772159047fSniklas When the assembler creates an R_SH_USES reloc, it examines it to
6782159047fSniklas determine which address is being loaded (L1 in the above example).
6792159047fSniklas It then counts the number of references to that address, and
6802159047fSniklas creates an R_SH_COUNT reloc at that address. The r_offset field of
6812159047fSniklas the R_SH_COUNT reloc will be the number of references. If the
6822159047fSniklas linker is able to eliminate a register load, it can use the
6832159047fSniklas R_SH_COUNT reloc to see whether it can also eliminate the function
684c88b1d6cSniklas address.
685c88b1d6cSniklas
686c88b1d6cSniklas SH relaxing also handles another, unrelated, matter. On the SH, if
687c88b1d6cSniklas a load or store instruction is not aligned on a four byte boundary,
688c88b1d6cSniklas the memory cycle interferes with the 32 bit instruction fetch,
689c88b1d6cSniklas causing a one cycle bubble in the pipeline. Therefore, we try to
690c88b1d6cSniklas align load and store instructions on four byte boundaries if we
691c88b1d6cSniklas can, by swapping them with one of the adjacent instructions. */
6922159047fSniklas
693c074d1c9Sdrahn static bfd_boolean
sh_relax_section(abfd,sec,link_info,again)6942159047fSniklas sh_relax_section (abfd, sec, link_info, again)
6952159047fSniklas bfd *abfd;
6962159047fSniklas asection *sec;
6972159047fSniklas struct bfd_link_info *link_info;
698c074d1c9Sdrahn bfd_boolean *again;
6992159047fSniklas {
7002159047fSniklas struct internal_reloc *internal_relocs;
7012159047fSniklas struct internal_reloc *free_relocs = NULL;
702c074d1c9Sdrahn bfd_boolean have_code;
7032159047fSniklas struct internal_reloc *irel, *irelend;
7042159047fSniklas bfd_byte *contents = NULL;
7052159047fSniklas bfd_byte *free_contents = NULL;
7062159047fSniklas
707c074d1c9Sdrahn *again = FALSE;
7082159047fSniklas
709*007c2a45Smiod if (link_info->relocatable
7102159047fSniklas || (sec->flags & SEC_RELOC) == 0
7112159047fSniklas || sec->reloc_count == 0)
712c074d1c9Sdrahn return TRUE;
7132159047fSniklas
7142159047fSniklas /* If this is the first time we have been called for this section,
7152159047fSniklas initialize the cooked size. */
7162159047fSniklas if (sec->_cooked_size == 0)
7172159047fSniklas sec->_cooked_size = sec->_raw_size;
7182159047fSniklas
7192159047fSniklas internal_relocs = (_bfd_coff_read_internal_relocs
7202159047fSniklas (abfd, sec, link_info->keep_memory,
721c074d1c9Sdrahn (bfd_byte *) NULL, FALSE,
7222159047fSniklas (struct internal_reloc *) NULL));
7232159047fSniklas if (internal_relocs == NULL)
7242159047fSniklas goto error_return;
7252159047fSniklas if (! link_info->keep_memory)
7262159047fSniklas free_relocs = internal_relocs;
7272159047fSniklas
728c074d1c9Sdrahn have_code = FALSE;
729c88b1d6cSniklas
7302159047fSniklas irelend = internal_relocs + sec->reloc_count;
7312159047fSniklas for (irel = internal_relocs; irel < irelend; irel++)
7322159047fSniklas {
7332159047fSniklas bfd_vma laddr, paddr, symval;
7342159047fSniklas unsigned short insn;
7352159047fSniklas struct internal_reloc *irelfn, *irelscan, *irelcount;
7362159047fSniklas struct internal_syment sym;
7372159047fSniklas bfd_signed_vma foff;
7382159047fSniklas
739c88b1d6cSniklas if (irel->r_type == R_SH_CODE)
740c074d1c9Sdrahn have_code = TRUE;
741c88b1d6cSniklas
7422159047fSniklas if (irel->r_type != R_SH_USES)
7432159047fSniklas continue;
7442159047fSniklas
7452159047fSniklas /* Get the section contents. */
7462159047fSniklas if (contents == NULL)
7472159047fSniklas {
7482159047fSniklas if (coff_section_data (abfd, sec) != NULL
7492159047fSniklas && coff_section_data (abfd, sec)->contents != NULL)
7502159047fSniklas contents = coff_section_data (abfd, sec)->contents;
7512159047fSniklas else
7522159047fSniklas {
753c88b1d6cSniklas contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
7542159047fSniklas if (contents == NULL)
7552159047fSniklas goto error_return;
7562159047fSniklas free_contents = contents;
7572159047fSniklas
7582159047fSniklas if (! bfd_get_section_contents (abfd, sec, contents,
7592159047fSniklas (file_ptr) 0, sec->_raw_size))
7602159047fSniklas goto error_return;
7612159047fSniklas }
7622159047fSniklas }
7632159047fSniklas
7642159047fSniklas /* The r_offset field of the R_SH_USES reloc will point us to
7652159047fSniklas the register load. The 4 is because the r_offset field is
7662159047fSniklas computed as though it were a jump offset, which are based
7672159047fSniklas from 4 bytes after the jump instruction. */
768b305b0f1Sespie laddr = irel->r_vaddr - sec->vma + 4;
769b305b0f1Sespie /* Careful to sign extend the 32-bit offset. */
770b305b0f1Sespie laddr += ((irel->r_offset & 0xffffffff) ^ 0x80000000) - 0x80000000;
7712159047fSniklas if (laddr >= sec->_raw_size)
7722159047fSniklas {
7732159047fSniklas (*_bfd_error_handler) ("%s: 0x%lx: warning: bad R_SH_USES offset",
774c074d1c9Sdrahn bfd_archive_filename (abfd),
7752159047fSniklas (unsigned long) irel->r_vaddr);
7762159047fSniklas continue;
7772159047fSniklas }
7782159047fSniklas insn = bfd_get_16 (abfd, contents + laddr);
7792159047fSniklas
780b305b0f1Sespie /* If the instruction is not mov.l NN,rN, we don't know what to do. */
7812159047fSniklas if ((insn & 0xf000) != 0xd000)
7822159047fSniklas {
7832159047fSniklas ((*_bfd_error_handler)
7842159047fSniklas ("%s: 0x%lx: warning: R_SH_USES points to unrecognized insn 0x%x",
785c074d1c9Sdrahn bfd_archive_filename (abfd), (unsigned long) irel->r_vaddr, insn));
7862159047fSniklas continue;
7872159047fSniklas }
7882159047fSniklas
7892159047fSniklas /* Get the address from which the register is being loaded. The
7902159047fSniklas displacement in the mov.l instruction is quadrupled. It is a
7912159047fSniklas displacement from four bytes after the movl instruction, but,
7922159047fSniklas before adding in the PC address, two least significant bits
7932159047fSniklas of the PC are cleared. We assume that the section is aligned
7942159047fSniklas on a four byte boundary. */
7952159047fSniklas paddr = insn & 0xff;
7962159047fSniklas paddr *= 4;
797c074d1c9Sdrahn paddr += (laddr + 4) &~ (bfd_vma) 3;
7982159047fSniklas if (paddr >= sec->_raw_size)
7992159047fSniklas {
8002159047fSniklas ((*_bfd_error_handler)
8012159047fSniklas ("%s: 0x%lx: warning: bad R_SH_USES load offset",
802c074d1c9Sdrahn bfd_archive_filename (abfd), (unsigned long) irel->r_vaddr));
8032159047fSniklas continue;
8042159047fSniklas }
8052159047fSniklas
8062159047fSniklas /* Get the reloc for the address from which the register is
8072159047fSniklas being loaded. This reloc will tell us which function is
8082159047fSniklas actually being called. */
8092159047fSniklas paddr += sec->vma;
8102159047fSniklas for (irelfn = internal_relocs; irelfn < irelend; irelfn++)
8112159047fSniklas if (irelfn->r_vaddr == paddr
812b305b0f1Sespie #ifdef COFF_WITH_PE
813b305b0f1Sespie && (irelfn->r_type == R_SH_IMM32
814b305b0f1Sespie || irelfn->r_type == R_SH_IMM32CE
815b305b0f1Sespie || irelfn->r_type == R_SH_IMAGEBASE))
816b305b0f1Sespie
817b305b0f1Sespie #else
8182159047fSniklas && irelfn->r_type == R_SH_IMM32)
819b305b0f1Sespie #endif
8202159047fSniklas break;
8212159047fSniklas if (irelfn >= irelend)
8222159047fSniklas {
8232159047fSniklas ((*_bfd_error_handler)
8242159047fSniklas ("%s: 0x%lx: warning: could not find expected reloc",
825c074d1c9Sdrahn bfd_archive_filename (abfd), (unsigned long) paddr));
8262159047fSniklas continue;
8272159047fSniklas }
8282159047fSniklas
8292159047fSniklas /* Get the value of the symbol referred to by the reloc. */
8302159047fSniklas if (! _bfd_coff_get_external_symbols (abfd))
8312159047fSniklas goto error_return;
8322159047fSniklas bfd_coff_swap_sym_in (abfd,
8332159047fSniklas ((bfd_byte *) obj_coff_external_syms (abfd)
8342159047fSniklas + (irelfn->r_symndx
8352159047fSniklas * bfd_coff_symesz (abfd))),
8362159047fSniklas &sym);
8372159047fSniklas if (sym.n_scnum != 0 && sym.n_scnum != sec->target_index)
8382159047fSniklas {
8392159047fSniklas ((*_bfd_error_handler)
8402159047fSniklas ("%s: 0x%lx: warning: symbol in unexpected section",
841c074d1c9Sdrahn bfd_archive_filename (abfd), (unsigned long) paddr));
8422159047fSniklas continue;
8432159047fSniklas }
8442159047fSniklas
8452159047fSniklas if (sym.n_sclass != C_EXT)
8462159047fSniklas {
8472159047fSniklas symval = (sym.n_value
8482159047fSniklas - sec->vma
8492159047fSniklas + sec->output_section->vma
8502159047fSniklas + sec->output_offset);
8512159047fSniklas }
8522159047fSniklas else
8532159047fSniklas {
8542159047fSniklas struct coff_link_hash_entry *h;
8552159047fSniklas
8562159047fSniklas h = obj_coff_sym_hashes (abfd)[irelfn->r_symndx];
8572159047fSniklas BFD_ASSERT (h != NULL);
8582159047fSniklas if (h->root.type != bfd_link_hash_defined
8592159047fSniklas && h->root.type != bfd_link_hash_defweak)
8602159047fSniklas {
8612159047fSniklas /* This appears to be a reference to an undefined
8622159047fSniklas symbol. Just ignore it--it will be caught by the
8632159047fSniklas regular reloc processing. */
8642159047fSniklas continue;
8652159047fSniklas }
8662159047fSniklas
8672159047fSniklas symval = (h->root.u.def.value
8682159047fSniklas + h->root.u.def.section->output_section->vma
8692159047fSniklas + h->root.u.def.section->output_offset);
8702159047fSniklas }
8712159047fSniklas
8722159047fSniklas symval += bfd_get_32 (abfd, contents + paddr - sec->vma);
8732159047fSniklas
8742159047fSniklas /* See if this function call can be shortened. */
8752159047fSniklas foff = (symval
8762159047fSniklas - (irel->r_vaddr
8772159047fSniklas - sec->vma
8782159047fSniklas + sec->output_section->vma
8792159047fSniklas + sec->output_offset
8802159047fSniklas + 4));
8812159047fSniklas if (foff < -0x1000 || foff >= 0x1000)
8822159047fSniklas {
8832159047fSniklas /* After all that work, we can't shorten this function call. */
8842159047fSniklas continue;
8852159047fSniklas }
8862159047fSniklas
8872159047fSniklas /* Shorten the function call. */
8882159047fSniklas
8892159047fSniklas /* For simplicity of coding, we are going to modify the section
8902159047fSniklas contents, the section relocs, and the BFD symbol table. We
8912159047fSniklas must tell the rest of the code not to free up this
8922159047fSniklas information. It would be possible to instead create a table
8932159047fSniklas of changes which have to be made, as is done in coff-mips.c;
8942159047fSniklas that would be more work, but would require less memory when
8952159047fSniklas the linker is run. */
8962159047fSniklas
8972159047fSniklas if (coff_section_data (abfd, sec) == NULL)
8982159047fSniklas {
899c074d1c9Sdrahn bfd_size_type amt = sizeof (struct coff_section_tdata);
900c074d1c9Sdrahn sec->used_by_bfd = (PTR) bfd_zalloc (abfd, amt);
9012159047fSniklas if (sec->used_by_bfd == NULL)
9022159047fSniklas goto error_return;
9032159047fSniklas }
9042159047fSniklas
9052159047fSniklas coff_section_data (abfd, sec)->relocs = internal_relocs;
906c074d1c9Sdrahn coff_section_data (abfd, sec)->keep_relocs = TRUE;
9072159047fSniklas free_relocs = NULL;
9082159047fSniklas
9092159047fSniklas coff_section_data (abfd, sec)->contents = contents;
910c074d1c9Sdrahn coff_section_data (abfd, sec)->keep_contents = TRUE;
9112159047fSniklas free_contents = NULL;
9122159047fSniklas
913c074d1c9Sdrahn obj_coff_keep_syms (abfd) = TRUE;
9142159047fSniklas
9152159047fSniklas /* Replace the jsr with a bsr. */
9162159047fSniklas
9172159047fSniklas /* Change the R_SH_USES reloc into an R_SH_PCDISP reloc, and
9182159047fSniklas replace the jsr with a bsr. */
9192159047fSniklas irel->r_type = R_SH_PCDISP;
9202159047fSniklas irel->r_symndx = irelfn->r_symndx;
9212159047fSniklas if (sym.n_sclass != C_EXT)
9222159047fSniklas {
9232159047fSniklas /* If this needs to be changed because of future relaxing,
9242159047fSniklas it will be handled here like other internal PCDISP
9252159047fSniklas relocs. */
9262159047fSniklas bfd_put_16 (abfd,
927c074d1c9Sdrahn (bfd_vma) 0xb000 | ((foff >> 1) & 0xfff),
9282159047fSniklas contents + irel->r_vaddr - sec->vma);
9292159047fSniklas }
9302159047fSniklas else
9312159047fSniklas {
9322159047fSniklas /* We can't fully resolve this yet, because the external
9332159047fSniklas symbol value may be changed by future relaxing. We let
9342159047fSniklas the final link phase handle it. */
935c074d1c9Sdrahn bfd_put_16 (abfd, (bfd_vma) 0xb000,
936c074d1c9Sdrahn contents + irel->r_vaddr - sec->vma);
9372159047fSniklas }
9382159047fSniklas
9392159047fSniklas /* See if there is another R_SH_USES reloc referring to the same
9402159047fSniklas register load. */
9412159047fSniklas for (irelscan = internal_relocs; irelscan < irelend; irelscan++)
9422159047fSniklas if (irelscan->r_type == R_SH_USES
9432159047fSniklas && laddr == irelscan->r_vaddr - sec->vma + 4 + irelscan->r_offset)
9442159047fSniklas break;
9452159047fSniklas if (irelscan < irelend)
9462159047fSniklas {
9472159047fSniklas /* Some other function call depends upon this register load,
9482159047fSniklas and we have not yet converted that function call.
9492159047fSniklas Indeed, we may never be able to convert it. There is
9502159047fSniklas nothing else we can do at this point. */
9512159047fSniklas continue;
9522159047fSniklas }
9532159047fSniklas
9542159047fSniklas /* Look for a R_SH_COUNT reloc on the location where the
9552159047fSniklas function address is stored. Do this before deleting any
9562159047fSniklas bytes, to avoid confusion about the address. */
9572159047fSniklas for (irelcount = internal_relocs; irelcount < irelend; irelcount++)
9582159047fSniklas if (irelcount->r_vaddr == paddr
9592159047fSniklas && irelcount->r_type == R_SH_COUNT)
9602159047fSniklas break;
9612159047fSniklas
9622159047fSniklas /* Delete the register load. */
9632159047fSniklas if (! sh_relax_delete_bytes (abfd, sec, laddr, 2))
9642159047fSniklas goto error_return;
9652159047fSniklas
9662159047fSniklas /* That will change things, so, just in case it permits some
9672159047fSniklas other function call to come within range, we should relax
9682159047fSniklas again. Note that this is not required, and it may be slow. */
969c074d1c9Sdrahn *again = TRUE;
9702159047fSniklas
9712159047fSniklas /* Now check whether we got a COUNT reloc. */
9722159047fSniklas if (irelcount >= irelend)
9732159047fSniklas {
9742159047fSniklas ((*_bfd_error_handler)
9752159047fSniklas ("%s: 0x%lx: warning: could not find expected COUNT reloc",
976c074d1c9Sdrahn bfd_archive_filename (abfd), (unsigned long) paddr));
9772159047fSniklas continue;
9782159047fSniklas }
9792159047fSniklas
9802159047fSniklas /* The number of uses is stored in the r_offset field. We've
9812159047fSniklas just deleted one. */
9822159047fSniklas if (irelcount->r_offset == 0)
9832159047fSniklas {
9842159047fSniklas ((*_bfd_error_handler) ("%s: 0x%lx: warning: bad count",
985c074d1c9Sdrahn bfd_archive_filename (abfd),
9862159047fSniklas (unsigned long) paddr));
9872159047fSniklas continue;
9882159047fSniklas }
9892159047fSniklas
9902159047fSniklas --irelcount->r_offset;
9912159047fSniklas
9922159047fSniklas /* If there are no more uses, we can delete the address. Reload
9932159047fSniklas the address from irelfn, in case it was changed by the
9942159047fSniklas previous call to sh_relax_delete_bytes. */
9952159047fSniklas if (irelcount->r_offset == 0)
9962159047fSniklas {
9972159047fSniklas if (! sh_relax_delete_bytes (abfd, sec,
9982159047fSniklas irelfn->r_vaddr - sec->vma, 4))
9992159047fSniklas goto error_return;
10002159047fSniklas }
10012159047fSniklas
10022159047fSniklas /* We've done all we can with that function call. */
10032159047fSniklas }
10042159047fSniklas
1005c88b1d6cSniklas /* Look for load and store instructions that we can align on four
1006c88b1d6cSniklas byte boundaries. */
1007c88b1d6cSniklas if (have_code)
1008c88b1d6cSniklas {
1009c074d1c9Sdrahn bfd_boolean swapped;
1010c88b1d6cSniklas
1011c88b1d6cSniklas /* Get the section contents. */
1012c88b1d6cSniklas if (contents == NULL)
1013c88b1d6cSniklas {
1014c88b1d6cSniklas if (coff_section_data (abfd, sec) != NULL
1015c88b1d6cSniklas && coff_section_data (abfd, sec)->contents != NULL)
1016c88b1d6cSniklas contents = coff_section_data (abfd, sec)->contents;
1017c88b1d6cSniklas else
1018c88b1d6cSniklas {
1019c88b1d6cSniklas contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
1020c88b1d6cSniklas if (contents == NULL)
1021c88b1d6cSniklas goto error_return;
1022c88b1d6cSniklas free_contents = contents;
1023c88b1d6cSniklas
1024c88b1d6cSniklas if (! bfd_get_section_contents (abfd, sec, contents,
1025c88b1d6cSniklas (file_ptr) 0, sec->_raw_size))
1026c88b1d6cSniklas goto error_return;
1027c88b1d6cSniklas }
1028c88b1d6cSniklas }
1029c88b1d6cSniklas
1030c88b1d6cSniklas if (! sh_align_loads (abfd, sec, internal_relocs, contents, &swapped))
1031c88b1d6cSniklas goto error_return;
1032c88b1d6cSniklas
1033c88b1d6cSniklas if (swapped)
1034c88b1d6cSniklas {
1035c88b1d6cSniklas if (coff_section_data (abfd, sec) == NULL)
1036c88b1d6cSniklas {
1037c074d1c9Sdrahn bfd_size_type amt = sizeof (struct coff_section_tdata);
1038c074d1c9Sdrahn sec->used_by_bfd = (PTR) bfd_zalloc (abfd, amt);
1039c88b1d6cSniklas if (sec->used_by_bfd == NULL)
1040c88b1d6cSniklas goto error_return;
1041c88b1d6cSniklas }
1042c88b1d6cSniklas
1043c88b1d6cSniklas coff_section_data (abfd, sec)->relocs = internal_relocs;
1044c074d1c9Sdrahn coff_section_data (abfd, sec)->keep_relocs = TRUE;
1045c88b1d6cSniklas free_relocs = NULL;
1046c88b1d6cSniklas
1047c88b1d6cSniklas coff_section_data (abfd, sec)->contents = contents;
1048c074d1c9Sdrahn coff_section_data (abfd, sec)->keep_contents = TRUE;
1049c88b1d6cSniklas free_contents = NULL;
1050c88b1d6cSniklas
1051c074d1c9Sdrahn obj_coff_keep_syms (abfd) = TRUE;
1052c88b1d6cSniklas }
1053c88b1d6cSniklas }
1054c88b1d6cSniklas
10552159047fSniklas if (free_relocs != NULL)
10562159047fSniklas {
10572159047fSniklas free (free_relocs);
10582159047fSniklas free_relocs = NULL;
10592159047fSniklas }
10602159047fSniklas
10612159047fSniklas if (free_contents != NULL)
10622159047fSniklas {
10632159047fSniklas if (! link_info->keep_memory)
10642159047fSniklas free (free_contents);
10652159047fSniklas else
10662159047fSniklas {
10672159047fSniklas /* Cache the section contents for coff_link_input_bfd. */
10682159047fSniklas if (coff_section_data (abfd, sec) == NULL)
10692159047fSniklas {
1070c074d1c9Sdrahn bfd_size_type amt = sizeof (struct coff_section_tdata);
1071c074d1c9Sdrahn sec->used_by_bfd = (PTR) bfd_zalloc (abfd, amt);
10722159047fSniklas if (sec->used_by_bfd == NULL)
10732159047fSniklas goto error_return;
10742159047fSniklas coff_section_data (abfd, sec)->relocs = NULL;
10752159047fSniklas }
10762159047fSniklas coff_section_data (abfd, sec)->contents = contents;
10772159047fSniklas }
10782159047fSniklas }
10792159047fSniklas
1080c074d1c9Sdrahn return TRUE;
10812159047fSniklas
10822159047fSniklas error_return:
10832159047fSniklas if (free_relocs != NULL)
10842159047fSniklas free (free_relocs);
10852159047fSniklas if (free_contents != NULL)
10862159047fSniklas free (free_contents);
1087c074d1c9Sdrahn return FALSE;
10882159047fSniklas }
10892159047fSniklas
10902159047fSniklas /* Delete some bytes from a section while relaxing. */
10912159047fSniklas
1092c074d1c9Sdrahn static bfd_boolean
sh_relax_delete_bytes(abfd,sec,addr,count)10932159047fSniklas sh_relax_delete_bytes (abfd, sec, addr, count)
10942159047fSniklas bfd *abfd;
10952159047fSniklas asection *sec;
10962159047fSniklas bfd_vma addr;
10972159047fSniklas int count;
10982159047fSniklas {
10992159047fSniklas bfd_byte *contents;
11002159047fSniklas struct internal_reloc *irel, *irelend;
11012159047fSniklas struct internal_reloc *irelalign;
11022159047fSniklas bfd_vma toaddr;
11032159047fSniklas bfd_byte *esym, *esymend;
11042159047fSniklas bfd_size_type symesz;
11052159047fSniklas struct coff_link_hash_entry **sym_hash;
11062159047fSniklas asection *o;
11072159047fSniklas
11082159047fSniklas contents = coff_section_data (abfd, sec)->contents;
11092159047fSniklas
11102159047fSniklas /* The deletion must stop at the next ALIGN reloc for an aligment
11112159047fSniklas power larger than the number of bytes we are deleting. */
11122159047fSniklas
11132159047fSniklas irelalign = NULL;
11142159047fSniklas toaddr = sec->_cooked_size;
11152159047fSniklas
11162159047fSniklas irel = coff_section_data (abfd, sec)->relocs;
11172159047fSniklas irelend = irel + sec->reloc_count;
11182159047fSniklas for (; irel < irelend; irel++)
11192159047fSniklas {
11202159047fSniklas if (irel->r_type == R_SH_ALIGN
11212159047fSniklas && irel->r_vaddr - sec->vma > addr
11222159047fSniklas && count < (1 << irel->r_offset))
11232159047fSniklas {
11242159047fSniklas irelalign = irel;
11252159047fSniklas toaddr = irel->r_vaddr - sec->vma;
11262159047fSniklas break;
11272159047fSniklas }
11282159047fSniklas }
11292159047fSniklas
11302159047fSniklas /* Actually delete the bytes. */
1131c074d1c9Sdrahn memmove (contents + addr, contents + addr + count,
1132c074d1c9Sdrahn (size_t) (toaddr - addr - count));
11332159047fSniklas if (irelalign == NULL)
11342159047fSniklas sec->_cooked_size -= count;
11352159047fSniklas else
1136c88b1d6cSniklas {
1137c88b1d6cSniklas int i;
1138c88b1d6cSniklas
1139c88b1d6cSniklas #define NOP_OPCODE (0x0009)
1140c88b1d6cSniklas
1141c88b1d6cSniklas BFD_ASSERT ((count & 1) == 0);
1142c88b1d6cSniklas for (i = 0; i < count; i += 2)
1143c074d1c9Sdrahn bfd_put_16 (abfd, (bfd_vma) NOP_OPCODE, contents + toaddr - count + i);
1144c88b1d6cSniklas }
11452159047fSniklas
11462159047fSniklas /* Adjust all the relocs. */
11472159047fSniklas for (irel = coff_section_data (abfd, sec)->relocs; irel < irelend; irel++)
11482159047fSniklas {
1149b305b0f1Sespie bfd_vma nraddr, stop;
1150b305b0f1Sespie bfd_vma start = 0;
11512159047fSniklas int insn = 0;
11522159047fSniklas struct internal_syment sym;
11532159047fSniklas int off, adjust, oinsn;
1154b305b0f1Sespie bfd_signed_vma voff = 0;
1155c074d1c9Sdrahn bfd_boolean overflow;
11562159047fSniklas
11572159047fSniklas /* Get the new reloc address. */
11582159047fSniklas nraddr = irel->r_vaddr - sec->vma;
11592159047fSniklas if ((irel->r_vaddr - sec->vma > addr
11602159047fSniklas && irel->r_vaddr - sec->vma < toaddr)
11612159047fSniklas || (irel->r_type == R_SH_ALIGN
11622159047fSniklas && irel->r_vaddr - sec->vma == toaddr))
11632159047fSniklas nraddr -= count;
11642159047fSniklas
11652159047fSniklas /* See if this reloc was for the bytes we have deleted, in which
1166c88b1d6cSniklas case we no longer care about it. Don't delete relocs which
1167c88b1d6cSniklas represent addresses, though. */
11682159047fSniklas if (irel->r_vaddr - sec->vma >= addr
11692159047fSniklas && irel->r_vaddr - sec->vma < addr + count
1170c88b1d6cSniklas && irel->r_type != R_SH_ALIGN
1171c88b1d6cSniklas && irel->r_type != R_SH_CODE
1172b305b0f1Sespie && irel->r_type != R_SH_DATA
1173b305b0f1Sespie && irel->r_type != R_SH_LABEL)
11742159047fSniklas irel->r_type = R_SH_UNUSED;
11752159047fSniklas
11762159047fSniklas /* If this is a PC relative reloc, see if the range it covers
11772159047fSniklas includes the bytes we have deleted. */
11782159047fSniklas switch (irel->r_type)
11792159047fSniklas {
11802159047fSniklas default:
11812159047fSniklas break;
11822159047fSniklas
11832159047fSniklas case R_SH_PCDISP8BY2:
11842159047fSniklas case R_SH_PCDISP:
11852159047fSniklas case R_SH_PCRELIMM8BY2:
11862159047fSniklas case R_SH_PCRELIMM8BY4:
11872159047fSniklas start = irel->r_vaddr - sec->vma;
11882159047fSniklas insn = bfd_get_16 (abfd, contents + nraddr);
11892159047fSniklas break;
11902159047fSniklas }
11912159047fSniklas
11922159047fSniklas switch (irel->r_type)
11932159047fSniklas {
11942159047fSniklas default:
11952159047fSniklas start = stop = addr;
11962159047fSniklas break;
11972159047fSniklas
11982159047fSniklas case R_SH_IMM32:
1199b305b0f1Sespie #ifdef COFF_WITH_PE
1200b305b0f1Sespie case R_SH_IMM32CE:
1201b305b0f1Sespie case R_SH_IMAGEBASE:
1202b305b0f1Sespie #endif
12032159047fSniklas /* If this reloc is against a symbol defined in this
12042159047fSniklas section, and the symbol will not be adjusted below, we
12052159047fSniklas must check the addend to see it will put the value in
12062159047fSniklas range to be adjusted, and hence must be changed. */
12072159047fSniklas bfd_coff_swap_sym_in (abfd,
12082159047fSniklas ((bfd_byte *) obj_coff_external_syms (abfd)
12092159047fSniklas + (irel->r_symndx
12102159047fSniklas * bfd_coff_symesz (abfd))),
12112159047fSniklas &sym);
12122159047fSniklas if (sym.n_sclass != C_EXT
12132159047fSniklas && sym.n_scnum == sec->target_index
12142159047fSniklas && ((bfd_vma) sym.n_value <= addr
12152159047fSniklas || (bfd_vma) sym.n_value >= toaddr))
12162159047fSniklas {
12172159047fSniklas bfd_vma val;
12182159047fSniklas
12192159047fSniklas val = bfd_get_32 (abfd, contents + nraddr);
12202159047fSniklas val += sym.n_value;
1221b305b0f1Sespie if (val > addr && val < toaddr)
12222159047fSniklas bfd_put_32 (abfd, val - count, contents + nraddr);
12232159047fSniklas }
12242159047fSniklas start = stop = addr;
12252159047fSniklas break;
12262159047fSniklas
12272159047fSniklas case R_SH_PCDISP8BY2:
12282159047fSniklas off = insn & 0xff;
12292159047fSniklas if (off & 0x80)
12302159047fSniklas off -= 0x100;
12312159047fSniklas stop = (bfd_vma) ((bfd_signed_vma) start + 4 + off * 2);
12322159047fSniklas break;
12332159047fSniklas
12342159047fSniklas case R_SH_PCDISP:
12352159047fSniklas bfd_coff_swap_sym_in (abfd,
12362159047fSniklas ((bfd_byte *) obj_coff_external_syms (abfd)
12372159047fSniklas + (irel->r_symndx
12382159047fSniklas * bfd_coff_symesz (abfd))),
12392159047fSniklas &sym);
12402159047fSniklas if (sym.n_sclass == C_EXT)
12412159047fSniklas start = stop = addr;
12422159047fSniklas else
12432159047fSniklas {
12442159047fSniklas off = insn & 0xfff;
12452159047fSniklas if (off & 0x800)
12462159047fSniklas off -= 0x1000;
12472159047fSniklas stop = (bfd_vma) ((bfd_signed_vma) start + 4 + off * 2);
12482159047fSniklas }
12492159047fSniklas break;
12502159047fSniklas
12512159047fSniklas case R_SH_PCRELIMM8BY2:
12522159047fSniklas off = insn & 0xff;
12532159047fSniklas stop = start + 4 + off * 2;
12542159047fSniklas break;
12552159047fSniklas
12562159047fSniklas case R_SH_PCRELIMM8BY4:
12572159047fSniklas off = insn & 0xff;
12582159047fSniklas stop = (start &~ (bfd_vma) 3) + 4 + off * 4;
12592159047fSniklas break;
12602159047fSniklas
1261b305b0f1Sespie case R_SH_SWITCH8:
12622159047fSniklas case R_SH_SWITCH16:
12632159047fSniklas case R_SH_SWITCH32:
12642159047fSniklas /* These relocs types represent
12652159047fSniklas .word L2-L1
12662159047fSniklas The r_offset field holds the difference between the reloc
12672159047fSniklas address and L1. That is the start of the reloc, and
12682159047fSniklas adding in the contents gives us the top. We must adjust
12692159047fSniklas both the r_offset field and the section contents. */
12702159047fSniklas
12712159047fSniklas start = irel->r_vaddr - sec->vma;
12722159047fSniklas stop = (bfd_vma) ((bfd_signed_vma) start - (long) irel->r_offset);
12732159047fSniklas
12742159047fSniklas if (start > addr
12752159047fSniklas && start < toaddr
12762159047fSniklas && (stop <= addr || stop >= toaddr))
12772159047fSniklas irel->r_offset += count;
12782159047fSniklas else if (stop > addr
12792159047fSniklas && stop < toaddr
12802159047fSniklas && (start <= addr || start >= toaddr))
12812159047fSniklas irel->r_offset -= count;
12822159047fSniklas
12832159047fSniklas start = stop;
12842159047fSniklas
12852159047fSniklas if (irel->r_type == R_SH_SWITCH16)
12862159047fSniklas voff = bfd_get_signed_16 (abfd, contents + nraddr);
1287b305b0f1Sespie else if (irel->r_type == R_SH_SWITCH8)
1288b305b0f1Sespie voff = bfd_get_8 (abfd, contents + nraddr);
12892159047fSniklas else
12902159047fSniklas voff = bfd_get_signed_32 (abfd, contents + nraddr);
12912159047fSniklas stop = (bfd_vma) ((bfd_signed_vma) start + voff);
12922159047fSniklas
12932159047fSniklas break;
12942159047fSniklas
12952159047fSniklas case R_SH_USES:
12962159047fSniklas start = irel->r_vaddr - sec->vma;
1297c88b1d6cSniklas stop = (bfd_vma) ((bfd_signed_vma) start
1298c88b1d6cSniklas + (long) irel->r_offset
1299c88b1d6cSniklas + 4);
13002159047fSniklas break;
13012159047fSniklas }
13022159047fSniklas
13032159047fSniklas if (start > addr
13042159047fSniklas && start < toaddr
13052159047fSniklas && (stop <= addr || stop >= toaddr))
13062159047fSniklas adjust = count;
13072159047fSniklas else if (stop > addr
13082159047fSniklas && stop < toaddr
13092159047fSniklas && (start <= addr || start >= toaddr))
13102159047fSniklas adjust = - count;
13112159047fSniklas else
13122159047fSniklas adjust = 0;
13132159047fSniklas
13142159047fSniklas if (adjust != 0)
13152159047fSniklas {
13162159047fSniklas oinsn = insn;
1317c074d1c9Sdrahn overflow = FALSE;
13182159047fSniklas switch (irel->r_type)
13192159047fSniklas {
13202159047fSniklas default:
13212159047fSniklas abort ();
13222159047fSniklas break;
13232159047fSniklas
13242159047fSniklas case R_SH_PCDISP8BY2:
13252159047fSniklas case R_SH_PCRELIMM8BY2:
13262159047fSniklas insn += adjust / 2;
13272159047fSniklas if ((oinsn & 0xff00) != (insn & 0xff00))
1328c074d1c9Sdrahn overflow = TRUE;
1329c074d1c9Sdrahn bfd_put_16 (abfd, (bfd_vma) insn, contents + nraddr);
13302159047fSniklas break;
13312159047fSniklas
13322159047fSniklas case R_SH_PCDISP:
13332159047fSniklas insn += adjust / 2;
13342159047fSniklas if ((oinsn & 0xf000) != (insn & 0xf000))
1335c074d1c9Sdrahn overflow = TRUE;
1336c074d1c9Sdrahn bfd_put_16 (abfd, (bfd_vma) insn, contents + nraddr);
13372159047fSniklas break;
13382159047fSniklas
13392159047fSniklas case R_SH_PCRELIMM8BY4:
13402159047fSniklas BFD_ASSERT (adjust == count || count >= 4);
13412159047fSniklas if (count >= 4)
13422159047fSniklas insn += adjust / 4;
13432159047fSniklas else
13442159047fSniklas {
13452159047fSniklas if ((irel->r_vaddr & 3) == 0)
13462159047fSniklas ++insn;
13472159047fSniklas }
13482159047fSniklas if ((oinsn & 0xff00) != (insn & 0xff00))
1349c074d1c9Sdrahn overflow = TRUE;
1350c074d1c9Sdrahn bfd_put_16 (abfd, (bfd_vma) insn, contents + nraddr);
13512159047fSniklas break;
13522159047fSniklas
1353b305b0f1Sespie case R_SH_SWITCH8:
1354b305b0f1Sespie voff += adjust;
1355b305b0f1Sespie if (voff < 0 || voff >= 0xff)
1356c074d1c9Sdrahn overflow = TRUE;
1357c074d1c9Sdrahn bfd_put_8 (abfd, (bfd_vma) voff, contents + nraddr);
1358b305b0f1Sespie break;
1359b305b0f1Sespie
13602159047fSniklas case R_SH_SWITCH16:
13612159047fSniklas voff += adjust;
13622159047fSniklas if (voff < - 0x8000 || voff >= 0x8000)
1363c074d1c9Sdrahn overflow = TRUE;
1364c074d1c9Sdrahn bfd_put_signed_16 (abfd, (bfd_vma) voff, contents + nraddr);
13652159047fSniklas break;
13662159047fSniklas
13672159047fSniklas case R_SH_SWITCH32:
13682159047fSniklas voff += adjust;
1369c074d1c9Sdrahn bfd_put_signed_32 (abfd, (bfd_vma) voff, contents + nraddr);
13702159047fSniklas break;
13712159047fSniklas
13722159047fSniklas case R_SH_USES:
13732159047fSniklas irel->r_offset += adjust;
13742159047fSniklas break;
13752159047fSniklas }
13762159047fSniklas
13772159047fSniklas if (overflow)
13782159047fSniklas {
13792159047fSniklas ((*_bfd_error_handler)
13802159047fSniklas ("%s: 0x%lx: fatal: reloc overflow while relaxing",
1381c074d1c9Sdrahn bfd_archive_filename (abfd), (unsigned long) irel->r_vaddr));
13822159047fSniklas bfd_set_error (bfd_error_bad_value);
1383c074d1c9Sdrahn return FALSE;
13842159047fSniklas }
13852159047fSniklas }
13862159047fSniklas
13872159047fSniklas irel->r_vaddr = nraddr + sec->vma;
13882159047fSniklas }
13892159047fSniklas
13902159047fSniklas /* Look through all the other sections. If there contain any IMM32
13912159047fSniklas relocs against internal symbols which we are not going to adjust
13922159047fSniklas below, we may need to adjust the addends. */
13932159047fSniklas for (o = abfd->sections; o != NULL; o = o->next)
13942159047fSniklas {
13952159047fSniklas struct internal_reloc *internal_relocs;
13962159047fSniklas struct internal_reloc *irelscan, *irelscanend;
13972159047fSniklas bfd_byte *ocontents;
13982159047fSniklas
13992159047fSniklas if (o == sec
14002159047fSniklas || (o->flags & SEC_RELOC) == 0
14012159047fSniklas || o->reloc_count == 0)
14022159047fSniklas continue;
14032159047fSniklas
14042159047fSniklas /* We always cache the relocs. Perhaps, if info->keep_memory is
1405c074d1c9Sdrahn FALSE, we should free them, if we are permitted to, when we
14062159047fSniklas leave sh_coff_relax_section. */
14072159047fSniklas internal_relocs = (_bfd_coff_read_internal_relocs
1408c074d1c9Sdrahn (abfd, o, TRUE, (bfd_byte *) NULL, FALSE,
14092159047fSniklas (struct internal_reloc *) NULL));
14102159047fSniklas if (internal_relocs == NULL)
1411c074d1c9Sdrahn return FALSE;
14122159047fSniklas
14132159047fSniklas ocontents = NULL;
14142159047fSniklas irelscanend = internal_relocs + o->reloc_count;
14152159047fSniklas for (irelscan = internal_relocs; irelscan < irelscanend; irelscan++)
14162159047fSniklas {
14172159047fSniklas struct internal_syment sym;
14182159047fSniklas
1419b305b0f1Sespie #ifdef COFF_WITH_PE
1420b305b0f1Sespie if (irelscan->r_type != R_SH_IMM32
1421b305b0f1Sespie && irelscan->r_type != R_SH_IMAGEBASE
1422b305b0f1Sespie && irelscan->r_type != R_SH_IMM32CE)
1423b305b0f1Sespie #else
14242159047fSniklas if (irelscan->r_type != R_SH_IMM32)
1425b305b0f1Sespie #endif
14262159047fSniklas continue;
14272159047fSniklas
14282159047fSniklas bfd_coff_swap_sym_in (abfd,
14292159047fSniklas ((bfd_byte *) obj_coff_external_syms (abfd)
14302159047fSniklas + (irelscan->r_symndx
14312159047fSniklas * bfd_coff_symesz (abfd))),
14322159047fSniklas &sym);
14332159047fSniklas if (sym.n_sclass != C_EXT
14342159047fSniklas && sym.n_scnum == sec->target_index
14352159047fSniklas && ((bfd_vma) sym.n_value <= addr
14362159047fSniklas || (bfd_vma) sym.n_value >= toaddr))
14372159047fSniklas {
14382159047fSniklas bfd_vma val;
14392159047fSniklas
14402159047fSniklas if (ocontents == NULL)
14412159047fSniklas {
14422159047fSniklas if (coff_section_data (abfd, o)->contents != NULL)
14432159047fSniklas ocontents = coff_section_data (abfd, o)->contents;
14442159047fSniklas else
14452159047fSniklas {
14462159047fSniklas /* We always cache the section contents.
1447c074d1c9Sdrahn Perhaps, if info->keep_memory is FALSE, we
14482159047fSniklas should free them, if we are permitted to,
14492159047fSniklas when we leave sh_coff_relax_section. */
1450c88b1d6cSniklas ocontents = (bfd_byte *) bfd_malloc (o->_raw_size);
14512159047fSniklas if (ocontents == NULL)
1452c074d1c9Sdrahn return FALSE;
14532159047fSniklas if (! bfd_get_section_contents (abfd, o, ocontents,
14542159047fSniklas (file_ptr) 0,
14552159047fSniklas o->_raw_size))
1456c074d1c9Sdrahn return FALSE;
14572159047fSniklas coff_section_data (abfd, o)->contents = ocontents;
14582159047fSniklas }
14592159047fSniklas }
14602159047fSniklas
14612159047fSniklas val = bfd_get_32 (abfd, ocontents + irelscan->r_vaddr - o->vma);
14622159047fSniklas val += sym.n_value;
1463b305b0f1Sespie if (val > addr && val < toaddr)
14642159047fSniklas bfd_put_32 (abfd, val - count,
14652159047fSniklas ocontents + irelscan->r_vaddr - o->vma);
14662159047fSniklas
1467c074d1c9Sdrahn coff_section_data (abfd, o)->keep_contents = TRUE;
14682159047fSniklas }
14692159047fSniklas }
14702159047fSniklas }
14712159047fSniklas
14722159047fSniklas /* Adjusting the internal symbols will not work if something has
14732159047fSniklas already retrieved the generic symbols. It would be possible to
14742159047fSniklas make this work by adjusting the generic symbols at the same time.
14752159047fSniklas However, this case should not arise in normal usage. */
14762159047fSniklas if (obj_symbols (abfd) != NULL
14772159047fSniklas || obj_raw_syments (abfd) != NULL)
14782159047fSniklas {
14792159047fSniklas ((*_bfd_error_handler)
14802159047fSniklas ("%s: fatal: generic symbols retrieved before relaxing",
1481c074d1c9Sdrahn bfd_archive_filename (abfd)));
14822159047fSniklas bfd_set_error (bfd_error_invalid_operation);
1483c074d1c9Sdrahn return FALSE;
14842159047fSniklas }
14852159047fSniklas
14862159047fSniklas /* Adjust all the symbols. */
14872159047fSniklas sym_hash = obj_coff_sym_hashes (abfd);
14882159047fSniklas symesz = bfd_coff_symesz (abfd);
14892159047fSniklas esym = (bfd_byte *) obj_coff_external_syms (abfd);
14902159047fSniklas esymend = esym + obj_raw_syment_count (abfd) * symesz;
14912159047fSniklas while (esym < esymend)
14922159047fSniklas {
14932159047fSniklas struct internal_syment isym;
14942159047fSniklas
14952159047fSniklas bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &isym);
14962159047fSniklas
14972159047fSniklas if (isym.n_scnum == sec->target_index
14982159047fSniklas && (bfd_vma) isym.n_value > addr
14992159047fSniklas && (bfd_vma) isym.n_value < toaddr)
15002159047fSniklas {
15012159047fSniklas isym.n_value -= count;
15022159047fSniklas
15032159047fSniklas bfd_coff_swap_sym_out (abfd, (PTR) &isym, (PTR) esym);
15042159047fSniklas
15052159047fSniklas if (*sym_hash != NULL)
15062159047fSniklas {
15072159047fSniklas BFD_ASSERT ((*sym_hash)->root.type == bfd_link_hash_defined
15082159047fSniklas || (*sym_hash)->root.type == bfd_link_hash_defweak);
15092159047fSniklas BFD_ASSERT ((*sym_hash)->root.u.def.value >= addr
15102159047fSniklas && (*sym_hash)->root.u.def.value < toaddr);
15112159047fSniklas (*sym_hash)->root.u.def.value -= count;
15122159047fSniklas }
15132159047fSniklas }
15142159047fSniklas
15152159047fSniklas esym += (isym.n_numaux + 1) * symesz;
15162159047fSniklas sym_hash += isym.n_numaux + 1;
15172159047fSniklas }
15182159047fSniklas
15192159047fSniklas /* See if we can move the ALIGN reloc forward. We have adjusted
15202159047fSniklas r_vaddr for it already. */
15212159047fSniklas if (irelalign != NULL)
15222159047fSniklas {
1523c88b1d6cSniklas bfd_vma alignto, alignaddr;
15242159047fSniklas
1525c88b1d6cSniklas alignto = BFD_ALIGN (toaddr, 1 << irelalign->r_offset);
15262159047fSniklas alignaddr = BFD_ALIGN (irelalign->r_vaddr - sec->vma,
15272159047fSniklas 1 << irelalign->r_offset);
1528c88b1d6cSniklas if (alignto != alignaddr)
15292159047fSniklas {
15302159047fSniklas /* Tail recursion. */
1531c88b1d6cSniklas return sh_relax_delete_bytes (abfd, sec, alignaddr,
1532c074d1c9Sdrahn (int) (alignto - alignaddr));
15332159047fSniklas }
15342159047fSniklas }
15352159047fSniklas
1536c074d1c9Sdrahn return TRUE;
15372159047fSniklas }
1538c88b1d6cSniklas
1539c88b1d6cSniklas /* This is yet another version of the SH opcode table, used to rapidly
1540c88b1d6cSniklas get information about a particular instruction. */
15412159047fSniklas
1542c88b1d6cSniklas /* The opcode map is represented by an array of these structures. The
1543c88b1d6cSniklas array is indexed by the high order four bits in the instruction. */
1544c88b1d6cSniklas
1545c88b1d6cSniklas struct sh_major_opcode
1546c88b1d6cSniklas {
1547c88b1d6cSniklas /* A pointer to the instruction list. This is an array which
1548c88b1d6cSniklas contains all the instructions with this major opcode. */
1549c88b1d6cSniklas const struct sh_minor_opcode *minor_opcodes;
1550c88b1d6cSniklas /* The number of elements in minor_opcodes. */
1551c88b1d6cSniklas unsigned short count;
1552c88b1d6cSniklas };
1553c88b1d6cSniklas
1554c88b1d6cSniklas /* This structure holds information for a set of SH opcodes. The
1555c88b1d6cSniklas instruction code is anded with the mask value, and the resulting
1556c88b1d6cSniklas value is used to search the order opcode list. */
1557c88b1d6cSniklas
1558c88b1d6cSniklas struct sh_minor_opcode
1559c88b1d6cSniklas {
1560c88b1d6cSniklas /* The sorted opcode list. */
1561c88b1d6cSniklas const struct sh_opcode *opcodes;
1562c88b1d6cSniklas /* The number of elements in opcodes. */
1563c88b1d6cSniklas unsigned short count;
1564c88b1d6cSniklas /* The mask value to use when searching the opcode list. */
1565c88b1d6cSniklas unsigned short mask;
1566c88b1d6cSniklas };
1567c88b1d6cSniklas
1568c88b1d6cSniklas /* This structure holds information for an SH instruction. An array
1569c88b1d6cSniklas of these structures is sorted in order by opcode. */
1570c88b1d6cSniklas
1571c88b1d6cSniklas struct sh_opcode
1572c88b1d6cSniklas {
1573c88b1d6cSniklas /* The code for this instruction, after it has been anded with the
1574c88b1d6cSniklas mask value in the sh_major_opcode structure. */
1575c88b1d6cSniklas unsigned short opcode;
1576c88b1d6cSniklas /* Flags for this instruction. */
1577b305b0f1Sespie unsigned long flags;
1578c88b1d6cSniklas };
1579c88b1d6cSniklas
1580c88b1d6cSniklas /* Flag which appear in the sh_opcode structure. */
1581c88b1d6cSniklas
1582c88b1d6cSniklas /* This instruction loads a value from memory. */
1583c88b1d6cSniklas #define LOAD (0x1)
1584c88b1d6cSniklas
1585c88b1d6cSniklas /* This instruction stores a value to memory. */
1586c88b1d6cSniklas #define STORE (0x2)
1587c88b1d6cSniklas
1588c88b1d6cSniklas /* This instruction is a branch. */
1589c88b1d6cSniklas #define BRANCH (0x4)
1590c88b1d6cSniklas
1591c88b1d6cSniklas /* This instruction has a delay slot. */
1592c88b1d6cSniklas #define DELAY (0x8)
1593c88b1d6cSniklas
1594c88b1d6cSniklas /* This instruction uses the value in the register in the field at
1595c88b1d6cSniklas mask 0x0f00 of the instruction. */
1596c88b1d6cSniklas #define USES1 (0x10)
1597b305b0f1Sespie #define USES1_REG(x) ((x & 0x0f00) >> 8)
1598c88b1d6cSniklas
1599c88b1d6cSniklas /* This instruction uses the value in the register in the field at
1600c88b1d6cSniklas mask 0x00f0 of the instruction. */
1601c88b1d6cSniklas #define USES2 (0x20)
1602b305b0f1Sespie #define USES2_REG(x) ((x & 0x00f0) >> 4)
1603c88b1d6cSniklas
1604c88b1d6cSniklas /* This instruction uses the value in register 0. */
1605c88b1d6cSniklas #define USESR0 (0x40)
1606c88b1d6cSniklas
1607c88b1d6cSniklas /* This instruction sets the value in the register in the field at
1608c88b1d6cSniklas mask 0x0f00 of the instruction. */
1609c88b1d6cSniklas #define SETS1 (0x80)
1610b305b0f1Sespie #define SETS1_REG(x) ((x & 0x0f00) >> 8)
1611c88b1d6cSniklas
1612c88b1d6cSniklas /* This instruction sets the value in the register in the field at
1613c88b1d6cSniklas mask 0x00f0 of the instruction. */
1614c88b1d6cSniklas #define SETS2 (0x100)
1615b305b0f1Sespie #define SETS2_REG(x) ((x & 0x00f0) >> 4)
1616c88b1d6cSniklas
1617c88b1d6cSniklas /* This instruction sets register 0. */
1618c88b1d6cSniklas #define SETSR0 (0x200)
1619c88b1d6cSniklas
1620c88b1d6cSniklas /* This instruction sets a special register. */
1621c88b1d6cSniklas #define SETSSP (0x400)
1622c88b1d6cSniklas
1623c88b1d6cSniklas /* This instruction uses a special register. */
1624c88b1d6cSniklas #define USESSP (0x800)
1625c88b1d6cSniklas
1626c88b1d6cSniklas /* This instruction uses the floating point register in the field at
1627c88b1d6cSniklas mask 0x0f00 of the instruction. */
1628c88b1d6cSniklas #define USESF1 (0x1000)
1629b305b0f1Sespie #define USESF1_REG(x) ((x & 0x0f00) >> 8)
1630c88b1d6cSniklas
1631c88b1d6cSniklas /* This instruction uses the floating point register in the field at
1632c88b1d6cSniklas mask 0x00f0 of the instruction. */
1633c88b1d6cSniklas #define USESF2 (0x2000)
1634b305b0f1Sespie #define USESF2_REG(x) ((x & 0x00f0) >> 4)
1635c88b1d6cSniklas
1636c88b1d6cSniklas /* This instruction uses floating point register 0. */
1637c88b1d6cSniklas #define USESF0 (0x4000)
1638c88b1d6cSniklas
1639c88b1d6cSniklas /* This instruction sets the floating point register in the field at
1640c88b1d6cSniklas mask 0x0f00 of the instruction. */
1641c88b1d6cSniklas #define SETSF1 (0x8000)
1642b305b0f1Sespie #define SETSF1_REG(x) ((x & 0x0f00) >> 8)
1643c88b1d6cSniklas
1644b305b0f1Sespie #define USESAS (0x10000)
1645b305b0f1Sespie #define USESAS_REG(x) (((((x) >> 8) - 2) & 3) + 2)
1646b305b0f1Sespie #define USESR8 (0x20000)
1647b305b0f1Sespie #define SETSAS (0x40000)
1648b305b0f1Sespie #define SETSAS_REG(x) USESAS_REG (x)
1649b305b0f1Sespie
1650*007c2a45Smiod #define MAP(a) a, sizeof a / sizeof a[0]
1651*007c2a45Smiod
1652b305b0f1Sespie #ifndef COFF_IMAGE_WITH_PE
1653c074d1c9Sdrahn static bfd_boolean sh_insn_uses_reg
1654c88b1d6cSniklas PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
1655c074d1c9Sdrahn static bfd_boolean sh_insn_sets_reg
1656b305b0f1Sespie PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
1657c074d1c9Sdrahn static bfd_boolean sh_insn_uses_or_sets_reg
1658b305b0f1Sespie PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
1659c074d1c9Sdrahn static bfd_boolean sh_insn_uses_freg
1660c88b1d6cSniklas PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
1661c074d1c9Sdrahn static bfd_boolean sh_insn_sets_freg
1662b305b0f1Sespie PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
1663c074d1c9Sdrahn static bfd_boolean sh_insn_uses_or_sets_freg
1664b305b0f1Sespie PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
1665c074d1c9Sdrahn static bfd_boolean sh_insns_conflict
1666c88b1d6cSniklas PARAMS ((unsigned int, const struct sh_opcode *, unsigned int,
1667c88b1d6cSniklas const struct sh_opcode *));
1668c074d1c9Sdrahn static bfd_boolean sh_load_use
1669c88b1d6cSniklas PARAMS ((unsigned int, const struct sh_opcode *, unsigned int,
1670c88b1d6cSniklas const struct sh_opcode *));
1671c88b1d6cSniklas
1672*007c2a45Smiod /* The opcode maps. */
1673c88b1d6cSniklas
1674c88b1d6cSniklas static const struct sh_opcode sh_opcode00[] =
1675c88b1d6cSniklas {
1676c88b1d6cSniklas { 0x0008, SETSSP }, /* clrt */
1677c88b1d6cSniklas { 0x0009, 0 }, /* nop */
1678c88b1d6cSniklas { 0x000b, BRANCH | DELAY | USESSP }, /* rts */
1679c88b1d6cSniklas { 0x0018, SETSSP }, /* sett */
1680c88b1d6cSniklas { 0x0019, SETSSP }, /* div0u */
1681c88b1d6cSniklas { 0x001b, 0 }, /* sleep */
1682c88b1d6cSniklas { 0x0028, SETSSP }, /* clrmac */
1683c88b1d6cSniklas { 0x002b, BRANCH | DELAY | SETSSP }, /* rte */
1684c88b1d6cSniklas { 0x0038, USESSP | SETSSP }, /* ldtlb */
1685c88b1d6cSniklas { 0x0048, SETSSP }, /* clrs */
1686c88b1d6cSniklas { 0x0058, SETSSP } /* sets */
1687c88b1d6cSniklas };
1688c88b1d6cSniklas
1689c88b1d6cSniklas static const struct sh_opcode sh_opcode01[] =
1690c88b1d6cSniklas {
1691c88b1d6cSniklas { 0x0003, BRANCH | DELAY | USES1 | SETSSP }, /* bsrf rn */
1692c88b1d6cSniklas { 0x000a, SETS1 | USESSP }, /* sts mach,rn */
1693c88b1d6cSniklas { 0x001a, SETS1 | USESSP }, /* sts macl,rn */
1694c88b1d6cSniklas { 0x0023, BRANCH | DELAY | USES1 }, /* braf rn */
1695c88b1d6cSniklas { 0x0029, SETS1 | USESSP }, /* movt rn */
1696c88b1d6cSniklas { 0x002a, SETS1 | USESSP }, /* sts pr,rn */
1697b305b0f1Sespie { 0x005a, SETS1 | USESSP }, /* sts fpul,rn */
1698b305b0f1Sespie { 0x006a, SETS1 | USESSP }, /* sts fpscr,rn / sts dsr,rn */
1699b305b0f1Sespie { 0x0083, LOAD | USES1 }, /* pref @rn */
1700b305b0f1Sespie { 0x007a, SETS1 | USESSP }, /* sts a0,rn */
1701b305b0f1Sespie { 0x008a, SETS1 | USESSP }, /* sts x0,rn */
1702b305b0f1Sespie { 0x009a, SETS1 | USESSP }, /* sts x1,rn */
1703b305b0f1Sespie { 0x00aa, SETS1 | USESSP }, /* sts y0,rn */
1704b305b0f1Sespie { 0x00ba, SETS1 | USESSP } /* sts y1,rn */
1705b305b0f1Sespie };
1706b305b0f1Sespie
1707b305b0f1Sespie /* These sixteen instructions can be handled with one table entry below. */
1708b305b0f1Sespie #if 0
1709b305b0f1Sespie { 0x0002, SETS1 | USESSP }, /* stc sr,rn */
1710b305b0f1Sespie { 0x0012, SETS1 | USESSP }, /* stc gbr,rn */
1711b305b0f1Sespie { 0x0022, SETS1 | USESSP }, /* stc vbr,rn */
1712c88b1d6cSniklas { 0x0032, SETS1 | USESSP }, /* stc ssr,rn */
1713c88b1d6cSniklas { 0x0042, SETS1 | USESSP }, /* stc spc,rn */
1714b305b0f1Sespie { 0x0052, SETS1 | USESSP }, /* stc mod,rn */
1715b305b0f1Sespie { 0x0062, SETS1 | USESSP }, /* stc rs,rn */
1716b305b0f1Sespie { 0x0072, SETS1 | USESSP }, /* stc re,rn */
1717c88b1d6cSniklas { 0x0082, SETS1 | USESSP }, /* stc r0_bank,rn */
1718c88b1d6cSniklas { 0x0092, SETS1 | USESSP }, /* stc r1_bank,rn */
1719c88b1d6cSniklas { 0x00a2, SETS1 | USESSP }, /* stc r2_bank,rn */
1720c88b1d6cSniklas { 0x00b2, SETS1 | USESSP }, /* stc r3_bank,rn */
1721c88b1d6cSniklas { 0x00c2, SETS1 | USESSP }, /* stc r4_bank,rn */
1722c88b1d6cSniklas { 0x00d2, SETS1 | USESSP }, /* stc r5_bank,rn */
1723c88b1d6cSniklas { 0x00e2, SETS1 | USESSP }, /* stc r6_bank,rn */
1724c88b1d6cSniklas { 0x00f2, SETS1 | USESSP } /* stc r7_bank,rn */
1725b305b0f1Sespie #endif
1726c88b1d6cSniklas
1727c88b1d6cSniklas static const struct sh_opcode sh_opcode02[] =
1728c88b1d6cSniklas {
1729b305b0f1Sespie { 0x0002, SETS1 | USESSP }, /* stc <special_reg>,rn */
1730c88b1d6cSniklas { 0x0004, STORE | USES1 | USES2 | USESR0 }, /* mov.b rm,@(r0,rn) */
1731c88b1d6cSniklas { 0x0005, STORE | USES1 | USES2 | USESR0 }, /* mov.w rm,@(r0,rn) */
1732c88b1d6cSniklas { 0x0006, STORE | USES1 | USES2 | USESR0 }, /* mov.l rm,@(r0,rn) */
1733c88b1d6cSniklas { 0x0007, SETSSP | USES1 | USES2 }, /* mul.l rm,rn */
1734c88b1d6cSniklas { 0x000c, LOAD | SETS1 | USES2 | USESR0 }, /* mov.b @(r0,rm),rn */
1735c88b1d6cSniklas { 0x000d, LOAD | SETS1 | USES2 | USESR0 }, /* mov.w @(r0,rm),rn */
1736c88b1d6cSniklas { 0x000e, LOAD | SETS1 | USES2 | USESR0 }, /* mov.l @(r0,rm),rn */
1737c88b1d6cSniklas { 0x000f, LOAD|SETS1|SETS2|SETSSP|USES1|USES2|USESSP }, /* mac.l @rm+,@rn+ */
1738c88b1d6cSniklas };
1739c88b1d6cSniklas
1740c88b1d6cSniklas static const struct sh_minor_opcode sh_opcode0[] =
1741c88b1d6cSniklas {
1742c88b1d6cSniklas { MAP (sh_opcode00), 0xffff },
1743c88b1d6cSniklas { MAP (sh_opcode01), 0xf0ff },
1744c88b1d6cSniklas { MAP (sh_opcode02), 0xf00f }
1745c88b1d6cSniklas };
1746c88b1d6cSniklas
1747c88b1d6cSniklas static const struct sh_opcode sh_opcode10[] =
1748c88b1d6cSniklas {
1749c88b1d6cSniklas { 0x1000, STORE | USES1 | USES2 } /* mov.l rm,@(disp,rn) */
1750c88b1d6cSniklas };
1751c88b1d6cSniklas
1752c88b1d6cSniklas static const struct sh_minor_opcode sh_opcode1[] =
1753c88b1d6cSniklas {
1754c88b1d6cSniklas { MAP (sh_opcode10), 0xf000 }
1755c88b1d6cSniklas };
1756c88b1d6cSniklas
1757c88b1d6cSniklas static const struct sh_opcode sh_opcode20[] =
1758c88b1d6cSniklas {
1759c88b1d6cSniklas { 0x2000, STORE | USES1 | USES2 }, /* mov.b rm,@rn */
1760c88b1d6cSniklas { 0x2001, STORE | USES1 | USES2 }, /* mov.w rm,@rn */
1761c88b1d6cSniklas { 0x2002, STORE | USES1 | USES2 }, /* mov.l rm,@rn */
1762c88b1d6cSniklas { 0x2004, STORE | SETS1 | USES1 | USES2 }, /* mov.b rm,@-rn */
1763c88b1d6cSniklas { 0x2005, STORE | SETS1 | USES1 | USES2 }, /* mov.w rm,@-rn */
1764c88b1d6cSniklas { 0x2006, STORE | SETS1 | USES1 | USES2 }, /* mov.l rm,@-rn */
1765c88b1d6cSniklas { 0x2007, SETSSP | USES1 | USES2 | USESSP }, /* div0s */
1766c88b1d6cSniklas { 0x2008, SETSSP | USES1 | USES2 }, /* tst rm,rn */
1767c88b1d6cSniklas { 0x2009, SETS1 | USES1 | USES2 }, /* and rm,rn */
1768c88b1d6cSniklas { 0x200a, SETS1 | USES1 | USES2 }, /* xor rm,rn */
1769c88b1d6cSniklas { 0x200b, SETS1 | USES1 | USES2 }, /* or rm,rn */
1770c88b1d6cSniklas { 0x200c, SETSSP | USES1 | USES2 }, /* cmp/str rm,rn */
1771c88b1d6cSniklas { 0x200d, SETS1 | USES1 | USES2 }, /* xtrct rm,rn */
1772c88b1d6cSniklas { 0x200e, SETSSP | USES1 | USES2 }, /* mulu.w rm,rn */
1773c88b1d6cSniklas { 0x200f, SETSSP | USES1 | USES2 } /* muls.w rm,rn */
1774c88b1d6cSniklas };
1775c88b1d6cSniklas
1776c88b1d6cSniklas static const struct sh_minor_opcode sh_opcode2[] =
1777c88b1d6cSniklas {
1778c88b1d6cSniklas { MAP (sh_opcode20), 0xf00f }
1779c88b1d6cSniklas };
1780c88b1d6cSniklas
1781c88b1d6cSniklas static const struct sh_opcode sh_opcode30[] =
1782c88b1d6cSniklas {
1783c88b1d6cSniklas { 0x3000, SETSSP | USES1 | USES2 }, /* cmp/eq rm,rn */
1784c88b1d6cSniklas { 0x3002, SETSSP | USES1 | USES2 }, /* cmp/hs rm,rn */
1785c88b1d6cSniklas { 0x3003, SETSSP | USES1 | USES2 }, /* cmp/ge rm,rn */
1786c88b1d6cSniklas { 0x3004, SETSSP | USESSP | USES1 | USES2 }, /* div1 rm,rn */
1787c88b1d6cSniklas { 0x3005, SETSSP | USES1 | USES2 }, /* dmulu.l rm,rn */
1788c88b1d6cSniklas { 0x3006, SETSSP | USES1 | USES2 }, /* cmp/hi rm,rn */
1789c88b1d6cSniklas { 0x3007, SETSSP | USES1 | USES2 }, /* cmp/gt rm,rn */
1790c88b1d6cSniklas { 0x3008, SETS1 | USES1 | USES2 }, /* sub rm,rn */
1791c88b1d6cSniklas { 0x300a, SETS1 | SETSSP | USES1 | USES2 | USESSP }, /* subc rm,rn */
1792c88b1d6cSniklas { 0x300b, SETS1 | SETSSP | USES1 | USES2 }, /* subv rm,rn */
1793c88b1d6cSniklas { 0x300c, SETS1 | USES1 | USES2 }, /* add rm,rn */
1794c88b1d6cSniklas { 0x300d, SETSSP | USES1 | USES2 }, /* dmuls.l rm,rn */
1795c88b1d6cSniklas { 0x300e, SETS1 | SETSSP | USES1 | USES2 | USESSP }, /* addc rm,rn */
1796c88b1d6cSniklas { 0x300f, SETS1 | SETSSP | USES1 | USES2 } /* addv rm,rn */
1797c88b1d6cSniklas };
1798c88b1d6cSniklas
1799c88b1d6cSniklas static const struct sh_minor_opcode sh_opcode3[] =
1800c88b1d6cSniklas {
1801c88b1d6cSniklas { MAP (sh_opcode30), 0xf00f }
1802c88b1d6cSniklas };
1803c88b1d6cSniklas
1804c88b1d6cSniklas static const struct sh_opcode sh_opcode40[] =
1805c88b1d6cSniklas {
1806c88b1d6cSniklas { 0x4000, SETS1 | SETSSP | USES1 }, /* shll rn */
1807c88b1d6cSniklas { 0x4001, SETS1 | SETSSP | USES1 }, /* shlr rn */
1808c88b1d6cSniklas { 0x4002, STORE | SETS1 | USES1 | USESSP }, /* sts.l mach,@-rn */
1809c88b1d6cSniklas { 0x4004, SETS1 | SETSSP | USES1 }, /* rotl rn */
1810c88b1d6cSniklas { 0x4005, SETS1 | SETSSP | USES1 }, /* rotr rn */
1811c88b1d6cSniklas { 0x4006, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,mach */
1812c88b1d6cSniklas { 0x4008, SETS1 | USES1 }, /* shll2 rn */
1813c88b1d6cSniklas { 0x4009, SETS1 | USES1 }, /* shlr2 rn */
1814c88b1d6cSniklas { 0x400a, SETSSP | USES1 }, /* lds rm,mach */
1815c88b1d6cSniklas { 0x400b, BRANCH | DELAY | USES1 }, /* jsr @rn */
1816c88b1d6cSniklas { 0x4010, SETS1 | SETSSP | USES1 }, /* dt rn */
1817c88b1d6cSniklas { 0x4011, SETSSP | USES1 }, /* cmp/pz rn */
1818c88b1d6cSniklas { 0x4012, STORE | SETS1 | USES1 | USESSP }, /* sts.l macl,@-rn */
1819b305b0f1Sespie { 0x4014, SETSSP | USES1 }, /* setrc rm */
1820c88b1d6cSniklas { 0x4015, SETSSP | USES1 }, /* cmp/pl rn */
1821c88b1d6cSniklas { 0x4016, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,macl */
1822c88b1d6cSniklas { 0x4018, SETS1 | USES1 }, /* shll8 rn */
1823c88b1d6cSniklas { 0x4019, SETS1 | USES1 }, /* shlr8 rn */
1824c88b1d6cSniklas { 0x401a, SETSSP | USES1 }, /* lds rm,macl */
1825c88b1d6cSniklas { 0x401b, LOAD | SETSSP | USES1 }, /* tas.b @rn */
1826c88b1d6cSniklas { 0x4020, SETS1 | SETSSP | USES1 }, /* shal rn */
1827c88b1d6cSniklas { 0x4021, SETS1 | SETSSP | USES1 }, /* shar rn */
1828c88b1d6cSniklas { 0x4022, STORE | SETS1 | USES1 | USESSP }, /* sts.l pr,@-rn */
1829c88b1d6cSniklas { 0x4024, SETS1 | SETSSP | USES1 | USESSP }, /* rotcl rn */
1830c88b1d6cSniklas { 0x4025, SETS1 | SETSSP | USES1 | USESSP }, /* rotcr rn */
1831c88b1d6cSniklas { 0x4026, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,pr */
1832c88b1d6cSniklas { 0x4028, SETS1 | USES1 }, /* shll16 rn */
1833c88b1d6cSniklas { 0x4029, SETS1 | USES1 }, /* shlr16 rn */
1834c88b1d6cSniklas { 0x402a, SETSSP | USES1 }, /* lds rm,pr */
1835c88b1d6cSniklas { 0x402b, BRANCH | DELAY | USES1 }, /* jmp @rn */
1836c88b1d6cSniklas { 0x4052, STORE | SETS1 | USES1 | USESSP }, /* sts.l fpul,@-rn */
1837c88b1d6cSniklas { 0x4056, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,fpul */
1838c88b1d6cSniklas { 0x405a, SETSSP | USES1 }, /* lds.l rm,fpul */
1839b305b0f1Sespie { 0x4062, STORE | SETS1 | USES1 | USESSP }, /* sts.l fpscr / dsr,@-rn */
1840b305b0f1Sespie { 0x4066, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,fpscr / dsr */
1841b305b0f1Sespie { 0x406a, SETSSP | USES1 }, /* lds rm,fpscr / lds rm,dsr */
1842b305b0f1Sespie { 0x4072, STORE | SETS1 | USES1 | USESSP }, /* sts.l a0,@-rn */
1843b305b0f1Sespie { 0x4076, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,a0 */
1844b305b0f1Sespie { 0x407a, SETSSP | USES1 }, /* lds.l rm,a0 */
1845b305b0f1Sespie { 0x4082, STORE | SETS1 | USES1 | USESSP }, /* sts.l x0,@-rn */
1846b305b0f1Sespie { 0x4086, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,x0 */
1847b305b0f1Sespie { 0x408a, SETSSP | USES1 }, /* lds.l rm,x0 */
1848b305b0f1Sespie { 0x4092, STORE | SETS1 | USES1 | USESSP }, /* sts.l x1,@-rn */
1849b305b0f1Sespie { 0x4096, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,x1 */
1850b305b0f1Sespie { 0x409a, SETSSP | USES1 }, /* lds.l rm,x1 */
1851b305b0f1Sespie { 0x40a2, STORE | SETS1 | USES1 | USESSP }, /* sts.l y0,@-rn */
1852b305b0f1Sespie { 0x40a6, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,y0 */
1853b305b0f1Sespie { 0x40aa, SETSSP | USES1 }, /* lds.l rm,y0 */
1854b305b0f1Sespie { 0x40b2, STORE | SETS1 | USES1 | USESSP }, /* sts.l y1,@-rn */
1855b305b0f1Sespie { 0x40b6, LOAD | SETS1 | SETSSP | USES1 }, /* lds.l @rm+,y1 */
1856b305b0f1Sespie { 0x40ba, SETSSP | USES1 } /* lds.l rm,y1 */
1857b305b0f1Sespie #if 0 /* These groups sixteen insns can be
1858b305b0f1Sespie handled with one table entry each below. */
1859b305b0f1Sespie { 0x4003, STORE | SETS1 | USES1 | USESSP }, /* stc.l sr,@-rn */
1860b305b0f1Sespie { 0x4013, STORE | SETS1 | USES1 | USESSP }, /* stc.l gbr,@-rn */
1861b305b0f1Sespie { 0x4023, STORE | SETS1 | USES1 | USESSP }, /* stc.l vbr,@-rn */
1862b305b0f1Sespie { 0x4033, STORE | SETS1 | USES1 | USESSP }, /* stc.l ssr,@-rn */
1863b305b0f1Sespie { 0x4043, STORE | SETS1 | USES1 | USESSP }, /* stc.l spc,@-rn */
1864b305b0f1Sespie { 0x4053, STORE | SETS1 | USES1 | USESSP }, /* stc.l mod,@-rn */
1865b305b0f1Sespie { 0x4063, STORE | SETS1 | USES1 | USESSP }, /* stc.l rs,@-rn */
1866b305b0f1Sespie { 0x4073, STORE | SETS1 | USES1 | USESSP }, /* stc.l re,@-rn */
1867b305b0f1Sespie { 0x4083, STORE | SETS1 | USES1 | USESSP }, /* stc.l r0_bank,@-rn */
1868b305b0f1Sespie ..
1869b305b0f1Sespie { 0x40f3, STORE | SETS1 | USES1 | USESSP }, /* stc.l r7_bank,@-rn */
1870b305b0f1Sespie
1871b305b0f1Sespie { 0x4007, LOAD | SETS1 | SETSSP | USES1 }, /* ldc.l @rm+,sr */
1872b305b0f1Sespie { 0x4017, LOAD | SETS1 | SETSSP | USES1 }, /* ldc.l @rm+,gbr */
1873b305b0f1Sespie { 0x4027, LOAD | SETS1 | SETSSP | USES1 }, /* ldc.l @rm+,vbr */
1874b305b0f1Sespie { 0x4037, LOAD | SETS1 | SETSSP | USES1 }, /* ldc.l @rm+,ssr */
1875b305b0f1Sespie { 0x4047, LOAD | SETS1 | SETSSP | USES1 }, /* ldc.l @rm+,spc */
1876b305b0f1Sespie { 0x4057, LOAD | SETS1 | SETSSP | USES1 }, /* ldc.l @rm+,mod */
1877b305b0f1Sespie { 0x4067, LOAD | SETS1 | SETSSP | USES1 }, /* ldc.l @rm+,rs */
1878b305b0f1Sespie { 0x4077, LOAD | SETS1 | SETSSP | USES1 }, /* ldc.l @rm+,re */
1879b305b0f1Sespie { 0x4087, LOAD | SETS1 | SETSSP | USES1 }, /* ldc.l @rm+,r0_bank */
1880b305b0f1Sespie ..
1881b305b0f1Sespie { 0x40f7, LOAD | SETS1 | SETSSP | USES1 }, /* ldc.l @rm+,r7_bank */
1882b305b0f1Sespie
1883b305b0f1Sespie { 0x400e, SETSSP | USES1 }, /* ldc rm,sr */
1884b305b0f1Sespie { 0x401e, SETSSP | USES1 }, /* ldc rm,gbr */
1885b305b0f1Sespie { 0x402e, SETSSP | USES1 }, /* ldc rm,vbr */
1886b305b0f1Sespie { 0x403e, SETSSP | USES1 }, /* ldc rm,ssr */
1887b305b0f1Sespie { 0x404e, SETSSP | USES1 }, /* ldc rm,spc */
1888b305b0f1Sespie { 0x405e, SETSSP | USES1 }, /* ldc rm,mod */
1889b305b0f1Sespie { 0x406e, SETSSP | USES1 }, /* ldc rm,rs */
1890b305b0f1Sespie { 0x407e, SETSSP | USES1 } /* ldc rm,re */
1891b305b0f1Sespie { 0x408e, SETSSP | USES1 } /* ldc rm,r0_bank */
1892b305b0f1Sespie ..
1893b305b0f1Sespie { 0x40fe, SETSSP | USES1 } /* ldc rm,r7_bank */
1894b305b0f1Sespie #endif
1895c88b1d6cSniklas };
1896c88b1d6cSniklas
1897c88b1d6cSniklas static const struct sh_opcode sh_opcode41[] =
1898c88b1d6cSniklas {
1899b305b0f1Sespie { 0x4003, STORE | SETS1 | USES1 | USESSP }, /* stc.l <special_reg>,@-rn */
1900b305b0f1Sespie { 0x4007, LOAD | SETS1 | SETSSP | USES1 }, /* ldc.l @rm+,<special_reg> */
1901c88b1d6cSniklas { 0x400c, SETS1 | USES1 | USES2 }, /* shad rm,rn */
1902c88b1d6cSniklas { 0x400d, SETS1 | USES1 | USES2 }, /* shld rm,rn */
1903b305b0f1Sespie { 0x400e, SETSSP | USES1 }, /* ldc rm,<special_reg> */
1904c88b1d6cSniklas { 0x400f, LOAD|SETS1|SETS2|SETSSP|USES1|USES2|USESSP }, /* mac.w @rm+,@rn+ */
1905c88b1d6cSniklas };
1906c88b1d6cSniklas
1907c88b1d6cSniklas static const struct sh_minor_opcode sh_opcode4[] =
1908c88b1d6cSniklas {
1909c88b1d6cSniklas { MAP (sh_opcode40), 0xf0ff },
1910b305b0f1Sespie { MAP (sh_opcode41), 0xf00f }
1911c88b1d6cSniklas };
1912c88b1d6cSniklas
1913c88b1d6cSniklas static const struct sh_opcode sh_opcode50[] =
1914c88b1d6cSniklas {
1915c88b1d6cSniklas { 0x5000, LOAD | SETS1 | USES2 } /* mov.l @(disp,rm),rn */
1916c88b1d6cSniklas };
1917c88b1d6cSniklas
1918c88b1d6cSniklas static const struct sh_minor_opcode sh_opcode5[] =
1919c88b1d6cSniklas {
1920c88b1d6cSniklas { MAP (sh_opcode50), 0xf000 }
1921c88b1d6cSniklas };
1922c88b1d6cSniklas
1923c88b1d6cSniklas static const struct sh_opcode sh_opcode60[] =
1924c88b1d6cSniklas {
1925c88b1d6cSniklas { 0x6000, LOAD | SETS1 | USES2 }, /* mov.b @rm,rn */
1926c88b1d6cSniklas { 0x6001, LOAD | SETS1 | USES2 }, /* mov.w @rm,rn */
1927c88b1d6cSniklas { 0x6002, LOAD | SETS1 | USES2 }, /* mov.l @rm,rn */
1928c88b1d6cSniklas { 0x6003, SETS1 | USES2 }, /* mov rm,rn */
1929c88b1d6cSniklas { 0x6004, LOAD | SETS1 | SETS2 | USES2 }, /* mov.b @rm+,rn */
1930c88b1d6cSniklas { 0x6005, LOAD | SETS1 | SETS2 | USES2 }, /* mov.w @rm+,rn */
1931c88b1d6cSniklas { 0x6006, LOAD | SETS1 | SETS2 | USES2 }, /* mov.l @rm+,rn */
1932c88b1d6cSniklas { 0x6007, SETS1 | USES2 }, /* not rm,rn */
1933c88b1d6cSniklas { 0x6008, SETS1 | USES2 }, /* swap.b rm,rn */
1934c88b1d6cSniklas { 0x6009, SETS1 | USES2 }, /* swap.w rm,rn */
1935c88b1d6cSniklas { 0x600a, SETS1 | SETSSP | USES2 | USESSP }, /* negc rm,rn */
1936c88b1d6cSniklas { 0x600b, SETS1 | USES2 }, /* neg rm,rn */
1937c88b1d6cSniklas { 0x600c, SETS1 | USES2 }, /* extu.b rm,rn */
1938c88b1d6cSniklas { 0x600d, SETS1 | USES2 }, /* extu.w rm,rn */
1939c88b1d6cSniklas { 0x600e, SETS1 | USES2 }, /* exts.b rm,rn */
1940c88b1d6cSniklas { 0x600f, SETS1 | USES2 } /* exts.w rm,rn */
1941c88b1d6cSniklas };
1942c88b1d6cSniklas
1943c88b1d6cSniklas static const struct sh_minor_opcode sh_opcode6[] =
1944c88b1d6cSniklas {
1945c88b1d6cSniklas { MAP (sh_opcode60), 0xf00f }
1946c88b1d6cSniklas };
1947c88b1d6cSniklas
1948c88b1d6cSniklas static const struct sh_opcode sh_opcode70[] =
1949c88b1d6cSniklas {
1950c88b1d6cSniklas { 0x7000, SETS1 | USES1 } /* add #imm,rn */
1951c88b1d6cSniklas };
1952c88b1d6cSniklas
1953c88b1d6cSniklas static const struct sh_minor_opcode sh_opcode7[] =
1954c88b1d6cSniklas {
1955c88b1d6cSniklas { MAP (sh_opcode70), 0xf000 }
1956c88b1d6cSniklas };
1957c88b1d6cSniklas
1958c88b1d6cSniklas static const struct sh_opcode sh_opcode80[] =
1959c88b1d6cSniklas {
1960c88b1d6cSniklas { 0x8000, STORE | USES2 | USESR0 }, /* mov.b r0,@(disp,rn) */
1961c88b1d6cSniklas { 0x8100, STORE | USES2 | USESR0 }, /* mov.w r0,@(disp,rn) */
1962b305b0f1Sespie { 0x8200, SETSSP }, /* setrc #imm */
1963c88b1d6cSniklas { 0x8400, LOAD | SETSR0 | USES2 }, /* mov.b @(disp,rm),r0 */
1964c88b1d6cSniklas { 0x8500, LOAD | SETSR0 | USES2 }, /* mov.w @(disp,rn),r0 */
1965c88b1d6cSniklas { 0x8800, SETSSP | USESR0 }, /* cmp/eq #imm,r0 */
1966c88b1d6cSniklas { 0x8900, BRANCH | USESSP }, /* bt label */
1967c88b1d6cSniklas { 0x8b00, BRANCH | USESSP }, /* bf label */
1968b305b0f1Sespie { 0x8c00, SETSSP }, /* ldrs @(disp,pc) */
1969c88b1d6cSniklas { 0x8d00, BRANCH | DELAY | USESSP }, /* bt/s label */
1970b305b0f1Sespie { 0x8e00, SETSSP }, /* ldre @(disp,pc) */
1971c88b1d6cSniklas { 0x8f00, BRANCH | DELAY | USESSP } /* bf/s label */
1972c88b1d6cSniklas };
1973c88b1d6cSniklas
1974c88b1d6cSniklas static const struct sh_minor_opcode sh_opcode8[] =
1975c88b1d6cSniklas {
1976c88b1d6cSniklas { MAP (sh_opcode80), 0xff00 }
1977c88b1d6cSniklas };
1978c88b1d6cSniklas
1979c88b1d6cSniklas static const struct sh_opcode sh_opcode90[] =
1980c88b1d6cSniklas {
1981c88b1d6cSniklas { 0x9000, LOAD | SETS1 } /* mov.w @(disp,pc),rn */
1982c88b1d6cSniklas };
1983c88b1d6cSniklas
1984c88b1d6cSniklas static const struct sh_minor_opcode sh_opcode9[] =
1985c88b1d6cSniklas {
1986c88b1d6cSniklas { MAP (sh_opcode90), 0xf000 }
1987c88b1d6cSniklas };
1988c88b1d6cSniklas
1989c88b1d6cSniklas static const struct sh_opcode sh_opcodea0[] =
1990c88b1d6cSniklas {
1991c88b1d6cSniklas { 0xa000, BRANCH | DELAY } /* bra label */
1992c88b1d6cSniklas };
1993c88b1d6cSniklas
1994c88b1d6cSniklas static const struct sh_minor_opcode sh_opcodea[] =
1995c88b1d6cSniklas {
1996c88b1d6cSniklas { MAP (sh_opcodea0), 0xf000 }
1997c88b1d6cSniklas };
1998c88b1d6cSniklas
1999c88b1d6cSniklas static const struct sh_opcode sh_opcodeb0[] =
2000c88b1d6cSniklas {
2001c88b1d6cSniklas { 0xb000, BRANCH | DELAY } /* bsr label */
2002c88b1d6cSniklas };
2003c88b1d6cSniklas
2004c88b1d6cSniklas static const struct sh_minor_opcode sh_opcodeb[] =
2005c88b1d6cSniklas {
2006c88b1d6cSniklas { MAP (sh_opcodeb0), 0xf000 }
2007c88b1d6cSniklas };
2008c88b1d6cSniklas
2009c88b1d6cSniklas static const struct sh_opcode sh_opcodec0[] =
2010c88b1d6cSniklas {
2011c88b1d6cSniklas { 0xc000, STORE | USESR0 | USESSP }, /* mov.b r0,@(disp,gbr) */
2012c88b1d6cSniklas { 0xc100, STORE | USESR0 | USESSP }, /* mov.w r0,@(disp,gbr) */
2013c88b1d6cSniklas { 0xc200, STORE | USESR0 | USESSP }, /* mov.l r0,@(disp,gbr) */
2014c88b1d6cSniklas { 0xc300, BRANCH | USESSP }, /* trapa #imm */
2015c88b1d6cSniklas { 0xc400, LOAD | SETSR0 | USESSP }, /* mov.b @(disp,gbr),r0 */
2016c88b1d6cSniklas { 0xc500, LOAD | SETSR0 | USESSP }, /* mov.w @(disp,gbr),r0 */
2017c88b1d6cSniklas { 0xc600, LOAD | SETSR0 | USESSP }, /* mov.l @(disp,gbr),r0 */
2018c88b1d6cSniklas { 0xc700, SETSR0 }, /* mova @(disp,pc),r0 */
2019c88b1d6cSniklas { 0xc800, SETSSP | USESR0 }, /* tst #imm,r0 */
2020c88b1d6cSniklas { 0xc900, SETSR0 | USESR0 }, /* and #imm,r0 */
2021c88b1d6cSniklas { 0xca00, SETSR0 | USESR0 }, /* xor #imm,r0 */
2022c88b1d6cSniklas { 0xcb00, SETSR0 | USESR0 }, /* or #imm,r0 */
2023c88b1d6cSniklas { 0xcc00, LOAD | SETSSP | USESR0 | USESSP }, /* tst.b #imm,@(r0,gbr) */
2024c88b1d6cSniklas { 0xcd00, LOAD | STORE | USESR0 | USESSP }, /* and.b #imm,@(r0,gbr) */
2025c88b1d6cSniklas { 0xce00, LOAD | STORE | USESR0 | USESSP }, /* xor.b #imm,@(r0,gbr) */
2026c88b1d6cSniklas { 0xcf00, LOAD | STORE | USESR0 | USESSP } /* or.b #imm,@(r0,gbr) */
2027c88b1d6cSniklas };
2028c88b1d6cSniklas
2029c88b1d6cSniklas static const struct sh_minor_opcode sh_opcodec[] =
2030c88b1d6cSniklas {
2031c88b1d6cSniklas { MAP (sh_opcodec0), 0xff00 }
2032c88b1d6cSniklas };
2033c88b1d6cSniklas
2034c88b1d6cSniklas static const struct sh_opcode sh_opcoded0[] =
2035c88b1d6cSniklas {
2036c88b1d6cSniklas { 0xd000, LOAD | SETS1 } /* mov.l @(disp,pc),rn */
2037c88b1d6cSniklas };
2038c88b1d6cSniklas
2039c88b1d6cSniklas static const struct sh_minor_opcode sh_opcoded[] =
2040c88b1d6cSniklas {
2041c88b1d6cSniklas { MAP (sh_opcoded0), 0xf000 }
2042c88b1d6cSniklas };
2043c88b1d6cSniklas
2044c88b1d6cSniklas static const struct sh_opcode sh_opcodee0[] =
2045c88b1d6cSniklas {
2046c88b1d6cSniklas { 0xe000, SETS1 } /* mov #imm,rn */
2047c88b1d6cSniklas };
2048c88b1d6cSniklas
2049c88b1d6cSniklas static const struct sh_minor_opcode sh_opcodee[] =
2050c88b1d6cSniklas {
2051c88b1d6cSniklas { MAP (sh_opcodee0), 0xf000 }
2052c88b1d6cSniklas };
2053c88b1d6cSniklas
2054c88b1d6cSniklas static const struct sh_opcode sh_opcodef0[] =
2055c88b1d6cSniklas {
2056c88b1d6cSniklas { 0xf000, SETSF1 | USESF1 | USESF2 }, /* fadd fm,fn */
2057c88b1d6cSniklas { 0xf001, SETSF1 | USESF1 | USESF2 }, /* fsub fm,fn */
2058c88b1d6cSniklas { 0xf002, SETSF1 | USESF1 | USESF2 }, /* fmul fm,fn */
2059c88b1d6cSniklas { 0xf003, SETSF1 | USESF1 | USESF2 }, /* fdiv fm,fn */
2060c88b1d6cSniklas { 0xf004, SETSSP | USESF1 | USESF2 }, /* fcmp/eq fm,fn */
2061c88b1d6cSniklas { 0xf005, SETSSP | USESF1 | USESF2 }, /* fcmp/gt fm,fn */
2062c88b1d6cSniklas { 0xf006, LOAD | SETSF1 | USES2 | USESR0 }, /* fmov.s @(r0,rm),fn */
2063c88b1d6cSniklas { 0xf007, STORE | USES1 | USESF2 | USESR0 }, /* fmov.s fm,@(r0,rn) */
2064c88b1d6cSniklas { 0xf008, LOAD | SETSF1 | USES2 }, /* fmov.s @rm,fn */
2065c88b1d6cSniklas { 0xf009, LOAD | SETS2 | SETSF1 | USES2 }, /* fmov.s @rm+,fn */
2066c88b1d6cSniklas { 0xf00a, STORE | USES1 | USESF2 }, /* fmov.s fm,@rn */
2067c88b1d6cSniklas { 0xf00b, STORE | SETS1 | USES1 | USESF2 }, /* fmov.s fm,@-rn */
2068c88b1d6cSniklas { 0xf00c, SETSF1 | USESF2 }, /* fmov fm,fn */
2069c88b1d6cSniklas { 0xf00e, SETSF1 | USESF1 | USESF2 | USESF0 } /* fmac f0,fm,fn */
2070c88b1d6cSniklas };
2071c88b1d6cSniklas
2072c88b1d6cSniklas static const struct sh_opcode sh_opcodef1[] =
2073c88b1d6cSniklas {
2074c88b1d6cSniklas { 0xf00d, SETSF1 | USESSP }, /* fsts fpul,fn */
2075c88b1d6cSniklas { 0xf01d, SETSSP | USESF1 }, /* flds fn,fpul */
2076c88b1d6cSniklas { 0xf02d, SETSF1 | USESSP }, /* float fpul,fn */
2077c88b1d6cSniklas { 0xf03d, SETSSP | USESF1 }, /* ftrc fn,fpul */
2078c88b1d6cSniklas { 0xf04d, SETSF1 | USESF1 }, /* fneg fn */
2079c88b1d6cSniklas { 0xf05d, SETSF1 | USESF1 }, /* fabs fn */
2080c88b1d6cSniklas { 0xf06d, SETSF1 | USESF1 }, /* fsqrt fn */
2081c88b1d6cSniklas { 0xf07d, SETSSP | USESF1 }, /* ftst/nan fn */
2082c88b1d6cSniklas { 0xf08d, SETSF1 }, /* fldi0 fn */
2083c88b1d6cSniklas { 0xf09d, SETSF1 } /* fldi1 fn */
2084c88b1d6cSniklas };
2085c88b1d6cSniklas
2086c88b1d6cSniklas static const struct sh_minor_opcode sh_opcodef[] =
2087c88b1d6cSniklas {
2088c88b1d6cSniklas { MAP (sh_opcodef0), 0xf00f },
2089c88b1d6cSniklas { MAP (sh_opcodef1), 0xf0ff }
2090c88b1d6cSniklas };
2091c88b1d6cSniklas
2092b305b0f1Sespie static struct sh_major_opcode sh_opcodes[] =
2093c88b1d6cSniklas {
2094c88b1d6cSniklas { MAP (sh_opcode0) },
2095c88b1d6cSniklas { MAP (sh_opcode1) },
2096c88b1d6cSniklas { MAP (sh_opcode2) },
2097c88b1d6cSniklas { MAP (sh_opcode3) },
2098c88b1d6cSniklas { MAP (sh_opcode4) },
2099c88b1d6cSniklas { MAP (sh_opcode5) },
2100c88b1d6cSniklas { MAP (sh_opcode6) },
2101c88b1d6cSniklas { MAP (sh_opcode7) },
2102c88b1d6cSniklas { MAP (sh_opcode8) },
2103c88b1d6cSniklas { MAP (sh_opcode9) },
2104c88b1d6cSniklas { MAP (sh_opcodea) },
2105c88b1d6cSniklas { MAP (sh_opcodeb) },
2106c88b1d6cSniklas { MAP (sh_opcodec) },
2107c88b1d6cSniklas { MAP (sh_opcoded) },
2108c88b1d6cSniklas { MAP (sh_opcodee) },
2109c88b1d6cSniklas { MAP (sh_opcodef) }
2110c88b1d6cSniklas };
2111c88b1d6cSniklas
2112b305b0f1Sespie /* The double data transfer / parallel processing insns are not
2113b305b0f1Sespie described here. This will cause sh_align_load_span to leave them alone. */
2114b305b0f1Sespie
2115b305b0f1Sespie static const struct sh_opcode sh_dsp_opcodef0[] =
2116b305b0f1Sespie {
2117b305b0f1Sespie { 0xf400, USESAS | SETSAS | LOAD | SETSSP }, /* movs.x @-as,ds */
2118b305b0f1Sespie { 0xf401, USESAS | SETSAS | STORE | USESSP }, /* movs.x ds,@-as */
2119b305b0f1Sespie { 0xf404, USESAS | LOAD | SETSSP }, /* movs.x @as,ds */
2120b305b0f1Sespie { 0xf405, USESAS | STORE | USESSP }, /* movs.x ds,@as */
2121b305b0f1Sespie { 0xf408, USESAS | SETSAS | LOAD | SETSSP }, /* movs.x @as+,ds */
2122b305b0f1Sespie { 0xf409, USESAS | SETSAS | STORE | USESSP }, /* movs.x ds,@as+ */
2123b305b0f1Sespie { 0xf40c, USESAS | SETSAS | LOAD | SETSSP | USESR8 }, /* movs.x @as+r8,ds */
2124b305b0f1Sespie { 0xf40d, USESAS | SETSAS | STORE | USESSP | USESR8 } /* movs.x ds,@as+r8 */
2125b305b0f1Sespie };
2126b305b0f1Sespie
2127b305b0f1Sespie static const struct sh_minor_opcode sh_dsp_opcodef[] =
2128b305b0f1Sespie {
2129b305b0f1Sespie { MAP (sh_dsp_opcodef0), 0xfc0d }
2130b305b0f1Sespie };
2131b305b0f1Sespie
2132c88b1d6cSniklas /* Given an instruction, return a pointer to the corresponding
2133c88b1d6cSniklas sh_opcode structure. Return NULL if the instruction is not
2134c88b1d6cSniklas recognized. */
2135c88b1d6cSniklas
2136c88b1d6cSniklas static const struct sh_opcode *
sh_insn_info(insn)2137c88b1d6cSniklas sh_insn_info (insn)
2138c88b1d6cSniklas unsigned int insn;
2139c88b1d6cSniklas {
2140c88b1d6cSniklas const struct sh_major_opcode *maj;
2141c88b1d6cSniklas const struct sh_minor_opcode *min, *minend;
2142c88b1d6cSniklas
2143c88b1d6cSniklas maj = &sh_opcodes[(insn & 0xf000) >> 12];
2144c88b1d6cSniklas min = maj->minor_opcodes;
2145c88b1d6cSniklas minend = min + maj->count;
2146c88b1d6cSniklas for (; min < minend; min++)
2147c88b1d6cSniklas {
2148c88b1d6cSniklas unsigned int l;
2149c88b1d6cSniklas const struct sh_opcode *op, *opend;
2150c88b1d6cSniklas
2151c88b1d6cSniklas l = insn & min->mask;
2152c88b1d6cSniklas op = min->opcodes;
2153c88b1d6cSniklas opend = op + min->count;
2154c88b1d6cSniklas
2155c88b1d6cSniklas /* Since the opcodes tables are sorted, we could use a binary
2156c88b1d6cSniklas search here if the count were above some cutoff value. */
2157c88b1d6cSniklas for (; op < opend; op++)
2158c88b1d6cSniklas if (op->opcode == l)
2159c88b1d6cSniklas return op;
2160c88b1d6cSniklas }
2161c88b1d6cSniklas
2162c88b1d6cSniklas return NULL;
2163c88b1d6cSniklas }
2164c88b1d6cSniklas
2165b305b0f1Sespie /* See whether an instruction uses or sets a general purpose register */
2166b305b0f1Sespie
2167c074d1c9Sdrahn static bfd_boolean
sh_insn_uses_or_sets_reg(insn,op,reg)2168b305b0f1Sespie sh_insn_uses_or_sets_reg (insn, op, reg)
2169b305b0f1Sespie unsigned int insn;
2170b305b0f1Sespie const struct sh_opcode *op;
2171b305b0f1Sespie unsigned int reg;
2172b305b0f1Sespie {
2173b305b0f1Sespie if (sh_insn_uses_reg (insn, op, reg))
2174c074d1c9Sdrahn return TRUE;
2175b305b0f1Sespie
2176b305b0f1Sespie return sh_insn_sets_reg (insn, op, reg);
2177b305b0f1Sespie }
2178b305b0f1Sespie
2179c88b1d6cSniklas /* See whether an instruction uses a general purpose register. */
2180c88b1d6cSniklas
2181c074d1c9Sdrahn static bfd_boolean
sh_insn_uses_reg(insn,op,reg)2182c88b1d6cSniklas sh_insn_uses_reg (insn, op, reg)
2183c88b1d6cSniklas unsigned int insn;
2184c88b1d6cSniklas const struct sh_opcode *op;
2185c88b1d6cSniklas unsigned int reg;
2186c88b1d6cSniklas {
2187c88b1d6cSniklas unsigned int f;
2188c88b1d6cSniklas
2189c88b1d6cSniklas f = op->flags;
2190c88b1d6cSniklas
2191c88b1d6cSniklas if ((f & USES1) != 0
2192b305b0f1Sespie && USES1_REG (insn) == reg)
2193c074d1c9Sdrahn return TRUE;
2194c88b1d6cSniklas if ((f & USES2) != 0
2195b305b0f1Sespie && USES2_REG (insn) == reg)
2196c074d1c9Sdrahn return TRUE;
2197c88b1d6cSniklas if ((f & USESR0) != 0
2198c88b1d6cSniklas && reg == 0)
2199c074d1c9Sdrahn return TRUE;
2200b305b0f1Sespie if ((f & USESAS) && reg == USESAS_REG (insn))
2201c074d1c9Sdrahn return TRUE;
2202b305b0f1Sespie if ((f & USESR8) && reg == 8)
2203c074d1c9Sdrahn return TRUE;
2204c88b1d6cSniklas
2205c074d1c9Sdrahn return FALSE;
2206c88b1d6cSniklas }
2207c88b1d6cSniklas
2208b305b0f1Sespie /* See whether an instruction sets a general purpose register. */
2209b305b0f1Sespie
2210c074d1c9Sdrahn static bfd_boolean
sh_insn_sets_reg(insn,op,reg)2211b305b0f1Sespie sh_insn_sets_reg (insn, op, reg)
2212b305b0f1Sespie unsigned int insn;
2213b305b0f1Sespie const struct sh_opcode *op;
2214b305b0f1Sespie unsigned int reg;
2215b305b0f1Sespie {
2216b305b0f1Sespie unsigned int f;
2217b305b0f1Sespie
2218b305b0f1Sespie f = op->flags;
2219b305b0f1Sespie
2220b305b0f1Sespie if ((f & SETS1) != 0
2221b305b0f1Sespie && SETS1_REG (insn) == reg)
2222c074d1c9Sdrahn return TRUE;
2223b305b0f1Sespie if ((f & SETS2) != 0
2224b305b0f1Sespie && SETS2_REG (insn) == reg)
2225c074d1c9Sdrahn return TRUE;
2226b305b0f1Sespie if ((f & SETSR0) != 0
2227b305b0f1Sespie && reg == 0)
2228c074d1c9Sdrahn return TRUE;
2229b305b0f1Sespie if ((f & SETSAS) && reg == SETSAS_REG (insn))
2230c074d1c9Sdrahn return TRUE;
2231b305b0f1Sespie
2232c074d1c9Sdrahn return FALSE;
2233b305b0f1Sespie }
2234b305b0f1Sespie
2235b305b0f1Sespie /* See whether an instruction uses or sets a floating point register */
2236b305b0f1Sespie
2237c074d1c9Sdrahn static bfd_boolean
sh_insn_uses_or_sets_freg(insn,op,reg)2238b305b0f1Sespie sh_insn_uses_or_sets_freg (insn, op, reg)
2239b305b0f1Sespie unsigned int insn;
2240b305b0f1Sespie const struct sh_opcode *op;
2241b305b0f1Sespie unsigned int reg;
2242b305b0f1Sespie {
2243b305b0f1Sespie if (sh_insn_uses_freg (insn, op, reg))
2244c074d1c9Sdrahn return TRUE;
2245b305b0f1Sespie
2246b305b0f1Sespie return sh_insn_sets_freg (insn, op, reg);
2247b305b0f1Sespie }
2248b305b0f1Sespie
2249c88b1d6cSniklas /* See whether an instruction uses a floating point register. */
2250c88b1d6cSniklas
2251c074d1c9Sdrahn static bfd_boolean
sh_insn_uses_freg(insn,op,freg)2252c88b1d6cSniklas sh_insn_uses_freg (insn, op, freg)
2253c88b1d6cSniklas unsigned int insn;
2254c88b1d6cSniklas const struct sh_opcode *op;
2255c88b1d6cSniklas unsigned int freg;
2256c88b1d6cSniklas {
2257c88b1d6cSniklas unsigned int f;
2258c88b1d6cSniklas
2259c88b1d6cSniklas f = op->flags;
2260c88b1d6cSniklas
2261b305b0f1Sespie /* We can't tell if this is a double-precision insn, so just play safe
2262b305b0f1Sespie and assume that it might be. So not only have we test FREG against
2263b305b0f1Sespie itself, but also even FREG against FREG+1 - if the using insn uses
2264b305b0f1Sespie just the low part of a double precision value - but also an odd
2265b305b0f1Sespie FREG against FREG-1 - if the setting insn sets just the low part
2266b305b0f1Sespie of a double precision value.
2267b305b0f1Sespie So what this all boils down to is that we have to ignore the lowest
2268b305b0f1Sespie bit of the register number. */
2269b305b0f1Sespie
2270c88b1d6cSniklas if ((f & USESF1) != 0
2271b305b0f1Sespie && (USESF1_REG (insn) & 0xe) == (freg & 0xe))
2272c074d1c9Sdrahn return TRUE;
2273c88b1d6cSniklas if ((f & USESF2) != 0
2274b305b0f1Sespie && (USESF2_REG (insn) & 0xe) == (freg & 0xe))
2275c074d1c9Sdrahn return TRUE;
2276c88b1d6cSniklas if ((f & USESF0) != 0
2277c88b1d6cSniklas && freg == 0)
2278c074d1c9Sdrahn return TRUE;
2279c88b1d6cSniklas
2280c074d1c9Sdrahn return FALSE;
2281c88b1d6cSniklas }
2282c88b1d6cSniklas
2283b305b0f1Sespie /* See whether an instruction sets a floating point register. */
2284b305b0f1Sespie
2285c074d1c9Sdrahn static bfd_boolean
sh_insn_sets_freg(insn,op,freg)2286b305b0f1Sespie sh_insn_sets_freg (insn, op, freg)
2287b305b0f1Sespie unsigned int insn;
2288b305b0f1Sespie const struct sh_opcode *op;
2289b305b0f1Sespie unsigned int freg;
2290b305b0f1Sespie {
2291b305b0f1Sespie unsigned int f;
2292b305b0f1Sespie
2293b305b0f1Sespie f = op->flags;
2294b305b0f1Sespie
2295b305b0f1Sespie /* We can't tell if this is a double-precision insn, so just play safe
2296b305b0f1Sespie and assume that it might be. So not only have we test FREG against
2297b305b0f1Sespie itself, but also even FREG against FREG+1 - if the using insn uses
2298b305b0f1Sespie just the low part of a double precision value - but also an odd
2299b305b0f1Sespie FREG against FREG-1 - if the setting insn sets just the low part
2300b305b0f1Sespie of a double precision value.
2301b305b0f1Sespie So what this all boils down to is that we have to ignore the lowest
2302b305b0f1Sespie bit of the register number. */
2303b305b0f1Sespie
2304b305b0f1Sespie if ((f & SETSF1) != 0
2305b305b0f1Sespie && (SETSF1_REG (insn) & 0xe) == (freg & 0xe))
2306c074d1c9Sdrahn return TRUE;
2307b305b0f1Sespie
2308c074d1c9Sdrahn return FALSE;
2309b305b0f1Sespie }
2310b305b0f1Sespie
2311c88b1d6cSniklas /* See whether instructions I1 and I2 conflict, assuming I1 comes
2312c88b1d6cSniklas before I2. OP1 and OP2 are the corresponding sh_opcode structures.
2313c074d1c9Sdrahn This should return TRUE if there is a conflict, or FALSE if the
23140c6d0228Sniklas instructions can be swapped safely. */
2315c88b1d6cSniklas
2316c074d1c9Sdrahn static bfd_boolean
sh_insns_conflict(i1,op1,i2,op2)2317c88b1d6cSniklas sh_insns_conflict (i1, op1, i2, op2)
2318c88b1d6cSniklas unsigned int i1;
2319c88b1d6cSniklas const struct sh_opcode *op1;
2320c88b1d6cSniklas unsigned int i2;
2321c88b1d6cSniklas const struct sh_opcode *op2;
2322c88b1d6cSniklas {
2323c88b1d6cSniklas unsigned int f1, f2;
2324c88b1d6cSniklas
2325c88b1d6cSniklas f1 = op1->flags;
2326c88b1d6cSniklas f2 = op2->flags;
2327c88b1d6cSniklas
2328b305b0f1Sespie /* Load of fpscr conflicts with floating point operations.
2329b305b0f1Sespie FIXME: shouldn't test raw opcodes here. */
2330b305b0f1Sespie if (((i1 & 0xf0ff) == 0x4066 && (i2 & 0xf000) == 0xf000)
2331b305b0f1Sespie || ((i2 & 0xf0ff) == 0x4066 && (i1 & 0xf000) == 0xf000))
2332c074d1c9Sdrahn return TRUE;
2333b305b0f1Sespie
2334c88b1d6cSniklas if ((f1 & (BRANCH | DELAY)) != 0
2335c88b1d6cSniklas || (f2 & (BRANCH | DELAY)) != 0)
2336c074d1c9Sdrahn return TRUE;
2337c88b1d6cSniklas
2338b305b0f1Sespie if (((f1 | f2) & SETSSP)
2339b305b0f1Sespie && (f1 & (SETSSP | USESSP))
2340b305b0f1Sespie && (f2 & (SETSSP | USESSP)))
2341c074d1c9Sdrahn return TRUE;
2342c88b1d6cSniklas
2343c88b1d6cSniklas if ((f1 & SETS1) != 0
2344b305b0f1Sespie && sh_insn_uses_or_sets_reg (i2, op2, SETS1_REG (i1)))
2345c074d1c9Sdrahn return TRUE;
2346c88b1d6cSniklas if ((f1 & SETS2) != 0
2347b305b0f1Sespie && sh_insn_uses_or_sets_reg (i2, op2, SETS2_REG (i1)))
2348c074d1c9Sdrahn return TRUE;
2349c88b1d6cSniklas if ((f1 & SETSR0) != 0
2350b305b0f1Sespie && sh_insn_uses_or_sets_reg (i2, op2, 0))
2351c074d1c9Sdrahn return TRUE;
2352b305b0f1Sespie if ((f1 & SETSAS)
2353b305b0f1Sespie && sh_insn_uses_or_sets_reg (i2, op2, SETSAS_REG (i1)))
2354c074d1c9Sdrahn return TRUE;
2355c88b1d6cSniklas if ((f1 & SETSF1) != 0
2356b305b0f1Sespie && sh_insn_uses_or_sets_freg (i2, op2, SETSF1_REG (i1)))
2357c074d1c9Sdrahn return TRUE;
2358c88b1d6cSniklas
2359c88b1d6cSniklas if ((f2 & SETS1) != 0
2360b305b0f1Sespie && sh_insn_uses_or_sets_reg (i1, op1, SETS1_REG (i2)))
2361c074d1c9Sdrahn return TRUE;
2362c88b1d6cSniklas if ((f2 & SETS2) != 0
2363b305b0f1Sespie && sh_insn_uses_or_sets_reg (i1, op1, SETS2_REG (i2)))
2364c074d1c9Sdrahn return TRUE;
2365c88b1d6cSniklas if ((f2 & SETSR0) != 0
2366b305b0f1Sespie && sh_insn_uses_or_sets_reg (i1, op1, 0))
2367c074d1c9Sdrahn return TRUE;
2368b305b0f1Sespie if ((f2 & SETSAS)
2369b305b0f1Sespie && sh_insn_uses_or_sets_reg (i1, op1, SETSAS_REG (i2)))
2370c074d1c9Sdrahn return TRUE;
2371c88b1d6cSniklas if ((f2 & SETSF1) != 0
2372b305b0f1Sespie && sh_insn_uses_or_sets_freg (i1, op1, SETSF1_REG (i2)))
2373c074d1c9Sdrahn return TRUE;
2374c88b1d6cSniklas
2375c88b1d6cSniklas /* The instructions do not conflict. */
2376c074d1c9Sdrahn return FALSE;
2377c88b1d6cSniklas }
2378c88b1d6cSniklas
2379c88b1d6cSniklas /* I1 is a load instruction, and I2 is some other instruction. Return
2380c074d1c9Sdrahn TRUE if I1 loads a register which I2 uses. */
2381c88b1d6cSniklas
2382c074d1c9Sdrahn static bfd_boolean
sh_load_use(i1,op1,i2,op2)2383c88b1d6cSniklas sh_load_use (i1, op1, i2, op2)
2384c88b1d6cSniklas unsigned int i1;
2385c88b1d6cSniklas const struct sh_opcode *op1;
2386c88b1d6cSniklas unsigned int i2;
2387c88b1d6cSniklas const struct sh_opcode *op2;
2388c88b1d6cSniklas {
2389c88b1d6cSniklas unsigned int f1;
2390c88b1d6cSniklas
2391c88b1d6cSniklas f1 = op1->flags;
2392c88b1d6cSniklas
2393c88b1d6cSniklas if ((f1 & LOAD) == 0)
2394c074d1c9Sdrahn return FALSE;
2395c88b1d6cSniklas
2396c88b1d6cSniklas /* If both SETS1 and SETSSP are set, that means a load to a special
2397c88b1d6cSniklas register using postincrement addressing mode, which we don't care
2398c88b1d6cSniklas about here. */
2399c88b1d6cSniklas if ((f1 & SETS1) != 0
2400c88b1d6cSniklas && (f1 & SETSSP) == 0
2401c88b1d6cSniklas && sh_insn_uses_reg (i2, op2, (i1 & 0x0f00) >> 8))
2402c074d1c9Sdrahn return TRUE;
2403c88b1d6cSniklas
2404c88b1d6cSniklas if ((f1 & SETSR0) != 0
2405c88b1d6cSniklas && sh_insn_uses_reg (i2, op2, 0))
2406c074d1c9Sdrahn return TRUE;
2407c88b1d6cSniklas
2408c88b1d6cSniklas if ((f1 & SETSF1) != 0
2409c88b1d6cSniklas && sh_insn_uses_freg (i2, op2, (i1 & 0x0f00) >> 8))
2410c074d1c9Sdrahn return TRUE;
2411c88b1d6cSniklas
2412c074d1c9Sdrahn return FALSE;
2413c88b1d6cSniklas }
2414c88b1d6cSniklas
24150c6d0228Sniklas /* Try to align loads and stores within a span of memory. This is
24160c6d0228Sniklas called by both the ELF and the COFF sh targets. ABFD and SEC are
24170c6d0228Sniklas the BFD and section we are examining. CONTENTS is the contents of
24180c6d0228Sniklas the section. SWAP is the routine to call to swap two instructions.
24190c6d0228Sniklas RELOCS is a pointer to the internal relocation information, to be
24200c6d0228Sniklas passed to SWAP. PLABEL is a pointer to the current label in a
24210c6d0228Sniklas sorted list of labels; LABEL_END is the end of the list. START and
24220c6d0228Sniklas STOP are the range of memory to examine. If a swap is made,
2423c074d1c9Sdrahn *PSWAPPED is set to TRUE. */
2424c88b1d6cSniklas
2425b305b0f1Sespie #ifdef COFF_WITH_PE
2426b305b0f1Sespie static
2427b305b0f1Sespie #endif
2428c074d1c9Sdrahn bfd_boolean
_bfd_sh_align_load_span(abfd,sec,contents,swap,relocs,plabel,label_end,start,stop,pswapped)24290c6d0228Sniklas _bfd_sh_align_load_span (abfd, sec, contents, swap, relocs,
24300c6d0228Sniklas plabel, label_end, start, stop, pswapped)
2431c88b1d6cSniklas bfd *abfd;
2432c88b1d6cSniklas asection *sec;
2433c88b1d6cSniklas bfd_byte *contents;
2434c074d1c9Sdrahn bfd_boolean (*swap) PARAMS ((bfd *, asection *, PTR, bfd_byte *, bfd_vma));
24350c6d0228Sniklas PTR relocs;
24360c6d0228Sniklas bfd_vma **plabel;
24370c6d0228Sniklas bfd_vma *label_end;
24380c6d0228Sniklas bfd_vma start;
24390c6d0228Sniklas bfd_vma stop;
2440c074d1c9Sdrahn bfd_boolean *pswapped;
2441c88b1d6cSniklas {
2442b305b0f1Sespie int dsp = (abfd->arch_info->mach == bfd_mach_sh_dsp
2443b305b0f1Sespie || abfd->arch_info->mach == bfd_mach_sh3_dsp);
24440c6d0228Sniklas bfd_vma i;
2445c88b1d6cSniklas
2446b305b0f1Sespie /* The SH4 has a Harvard architecture, hence aligning loads is not
2447b305b0f1Sespie desirable. In fact, it is counter-productive, since it interferes
2448b305b0f1Sespie with the schedules generated by the compiler. */
2449b305b0f1Sespie if (abfd->arch_info->mach == bfd_mach_sh4)
2450c074d1c9Sdrahn return TRUE;
2451b305b0f1Sespie
2452b305b0f1Sespie /* If we are linking sh[3]-dsp code, swap the FPU instructions for DSP
2453b305b0f1Sespie instructions. */
2454b305b0f1Sespie if (dsp)
2455b305b0f1Sespie {
2456b305b0f1Sespie sh_opcodes[0xf].minor_opcodes = sh_dsp_opcodef;
2457b305b0f1Sespie sh_opcodes[0xf].count = sizeof sh_dsp_opcodef / sizeof sh_dsp_opcodef;
2458b305b0f1Sespie }
2459b305b0f1Sespie
2460c88b1d6cSniklas /* Instructions should be aligned on 2 byte boundaries. */
2461c88b1d6cSniklas if ((start & 1) == 1)
2462c88b1d6cSniklas ++start;
2463c88b1d6cSniklas
2464c88b1d6cSniklas /* Now look through the unaligned addresses. */
2465c88b1d6cSniklas i = start;
2466c88b1d6cSniklas if ((i & 2) == 0)
2467c88b1d6cSniklas i += 2;
2468c88b1d6cSniklas for (; i < stop; i += 4)
2469c88b1d6cSniklas {
2470c88b1d6cSniklas unsigned int insn;
2471c88b1d6cSniklas const struct sh_opcode *op;
2472c88b1d6cSniklas unsigned int prev_insn = 0;
2473c88b1d6cSniklas const struct sh_opcode *prev_op = NULL;
2474c88b1d6cSniklas
2475c88b1d6cSniklas insn = bfd_get_16 (abfd, contents + i);
2476c88b1d6cSniklas op = sh_insn_info (insn);
2477c88b1d6cSniklas if (op == NULL
2478c88b1d6cSniklas || (op->flags & (LOAD | STORE)) == 0)
2479c88b1d6cSniklas continue;
2480c88b1d6cSniklas
24810c6d0228Sniklas /* This is a load or store which is not on a four byte boundary. */
2482c88b1d6cSniklas
24830c6d0228Sniklas while (*plabel < label_end && **plabel < i)
24840c6d0228Sniklas ++*plabel;
2485c88b1d6cSniklas
2486c88b1d6cSniklas if (i > start)
2487c88b1d6cSniklas {
2488c88b1d6cSniklas prev_insn = bfd_get_16 (abfd, contents + i - 2);
2489b305b0f1Sespie /* If INSN is the field b of a parallel processing insn, it is not
2490b305b0f1Sespie a load / store after all. Note that the test here might mistake
2491b305b0f1Sespie the field_b of a pcopy insn for the starting code of a parallel
2492b305b0f1Sespie processing insn; this might miss a swapping opportunity, but at
2493b305b0f1Sespie least we're on the safe side. */
2494b305b0f1Sespie if (dsp && (prev_insn & 0xfc00) == 0xf800)
2495b305b0f1Sespie continue;
2496b305b0f1Sespie
2497b305b0f1Sespie /* Check if prev_insn is actually the field b of a parallel
2498b305b0f1Sespie processing insn. Again, this can give a spurious match
2499b305b0f1Sespie after a pcopy. */
2500b305b0f1Sespie if (dsp && i - 2 > start)
2501b305b0f1Sespie {
2502b305b0f1Sespie unsigned pprev_insn = bfd_get_16 (abfd, contents + i - 4);
2503b305b0f1Sespie
2504b305b0f1Sespie if ((pprev_insn & 0xfc00) == 0xf800)
2505b305b0f1Sespie prev_op = NULL;
2506b305b0f1Sespie else
2507b305b0f1Sespie prev_op = sh_insn_info (prev_insn);
2508b305b0f1Sespie }
2509b305b0f1Sespie else
2510c88b1d6cSniklas prev_op = sh_insn_info (prev_insn);
2511c88b1d6cSniklas
2512c88b1d6cSniklas /* If the load/store instruction is in a delay slot, we
2513c88b1d6cSniklas can't swap. */
2514c88b1d6cSniklas if (prev_op == NULL
2515c88b1d6cSniklas || (prev_op->flags & DELAY) != 0)
2516c88b1d6cSniklas continue;
2517c88b1d6cSniklas }
2518c88b1d6cSniklas if (i > start
25190c6d0228Sniklas && (*plabel >= label_end || **plabel != i)
2520c88b1d6cSniklas && prev_op != NULL
2521c88b1d6cSniklas && (prev_op->flags & (LOAD | STORE)) == 0
2522c88b1d6cSniklas && ! sh_insns_conflict (prev_insn, prev_op, insn, op))
2523c88b1d6cSniklas {
2524c074d1c9Sdrahn bfd_boolean ok;
2525c88b1d6cSniklas
2526c88b1d6cSniklas /* The load/store instruction does not have a label, and
2527c88b1d6cSniklas there is a previous instruction; PREV_INSN is not
2528c88b1d6cSniklas itself a load/store instruction, and PREV_INSN and
2529c88b1d6cSniklas INSN do not conflict. */
2530c88b1d6cSniklas
2531c074d1c9Sdrahn ok = TRUE;
2532c88b1d6cSniklas
2533c88b1d6cSniklas if (i >= start + 4)
2534c88b1d6cSniklas {
2535c88b1d6cSniklas unsigned int prev2_insn;
2536c88b1d6cSniklas const struct sh_opcode *prev2_op;
2537c88b1d6cSniklas
2538c88b1d6cSniklas prev2_insn = bfd_get_16 (abfd, contents + i - 4);
2539c88b1d6cSniklas prev2_op = sh_insn_info (prev2_insn);
2540c88b1d6cSniklas
2541c88b1d6cSniklas /* If the instruction before PREV_INSN has a delay
2542c88b1d6cSniklas slot--that is, PREV_INSN is in a delay slot--we
2543c88b1d6cSniklas can not swap. */
2544c88b1d6cSniklas if (prev2_op == NULL
2545c88b1d6cSniklas || (prev2_op->flags & DELAY) != 0)
2546c074d1c9Sdrahn ok = FALSE;
2547c88b1d6cSniklas
2548c88b1d6cSniklas /* If the instruction before PREV_INSN is a load,
2549c88b1d6cSniklas and it sets a register which INSN uses, then
2550c88b1d6cSniklas putting INSN immediately after PREV_INSN will
2551c88b1d6cSniklas cause a pipeline bubble, so there is no point to
2552c88b1d6cSniklas making the swap. */
2553c88b1d6cSniklas if (ok
2554c88b1d6cSniklas && (prev2_op->flags & LOAD) != 0
2555c88b1d6cSniklas && sh_load_use (prev2_insn, prev2_op, insn, op))
2556c074d1c9Sdrahn ok = FALSE;
2557c88b1d6cSniklas }
2558c88b1d6cSniklas
2559c88b1d6cSniklas if (ok)
2560c88b1d6cSniklas {
25610c6d0228Sniklas if (! (*swap) (abfd, sec, relocs, contents, i - 2))
2562c074d1c9Sdrahn return FALSE;
2563c074d1c9Sdrahn *pswapped = TRUE;
2564c88b1d6cSniklas continue;
2565c88b1d6cSniklas }
2566c88b1d6cSniklas }
2567c88b1d6cSniklas
25680c6d0228Sniklas while (*plabel < label_end && **plabel < i + 2)
25690c6d0228Sniklas ++*plabel;
2570c88b1d6cSniklas
2571c88b1d6cSniklas if (i + 2 < stop
25720c6d0228Sniklas && (*plabel >= label_end || **plabel != i + 2))
2573c88b1d6cSniklas {
2574c88b1d6cSniklas unsigned int next_insn;
2575c88b1d6cSniklas const struct sh_opcode *next_op;
2576c88b1d6cSniklas
2577c88b1d6cSniklas /* There is an instruction after the load/store
2578c88b1d6cSniklas instruction, and it does not have a label. */
2579c88b1d6cSniklas next_insn = bfd_get_16 (abfd, contents + i + 2);
2580c88b1d6cSniklas next_op = sh_insn_info (next_insn);
2581c88b1d6cSniklas if (next_op != NULL
2582c88b1d6cSniklas && (next_op->flags & (LOAD | STORE)) == 0
2583c88b1d6cSniklas && ! sh_insns_conflict (insn, op, next_insn, next_op))
2584c88b1d6cSniklas {
2585c074d1c9Sdrahn bfd_boolean ok;
2586c88b1d6cSniklas
2587c88b1d6cSniklas /* NEXT_INSN is not itself a load/store instruction,
2588c88b1d6cSniklas and it does not conflict with INSN. */
2589c88b1d6cSniklas
2590c074d1c9Sdrahn ok = TRUE;
2591c88b1d6cSniklas
2592c88b1d6cSniklas /* If PREV_INSN is a load, and it sets a register
2593c88b1d6cSniklas which NEXT_INSN uses, then putting NEXT_INSN
2594c88b1d6cSniklas immediately after PREV_INSN will cause a pipeline
2595c88b1d6cSniklas bubble, so there is no reason to make this swap. */
2596c88b1d6cSniklas if (prev_op != NULL
2597c88b1d6cSniklas && (prev_op->flags & LOAD) != 0
2598c88b1d6cSniklas && sh_load_use (prev_insn, prev_op, next_insn, next_op))
2599c074d1c9Sdrahn ok = FALSE;
2600c88b1d6cSniklas
2601c88b1d6cSniklas /* If INSN is a load, and it sets a register which
2602c88b1d6cSniklas the insn after NEXT_INSN uses, then doing the
2603c88b1d6cSniklas swap will cause a pipeline bubble, so there is no
2604c88b1d6cSniklas reason to make the swap. However, if the insn
2605c88b1d6cSniklas after NEXT_INSN is itself a load or store
2606c88b1d6cSniklas instruction, then it is misaligned, so
2607c88b1d6cSniklas optimistically hope that it will be swapped
2608c88b1d6cSniklas itself, and just live with the pipeline bubble if
2609c88b1d6cSniklas it isn't. */
2610c88b1d6cSniklas if (ok
2611c88b1d6cSniklas && i + 4 < stop
2612c88b1d6cSniklas && (op->flags & LOAD) != 0)
2613c88b1d6cSniklas {
2614c88b1d6cSniklas unsigned int next2_insn;
2615c88b1d6cSniklas const struct sh_opcode *next2_op;
2616c88b1d6cSniklas
2617c88b1d6cSniklas next2_insn = bfd_get_16 (abfd, contents + i + 4);
2618c88b1d6cSniklas next2_op = sh_insn_info (next2_insn);
2619c88b1d6cSniklas if ((next2_op->flags & (LOAD | STORE)) == 0
2620c88b1d6cSniklas && sh_load_use (insn, op, next2_insn, next2_op))
2621c074d1c9Sdrahn ok = FALSE;
2622c88b1d6cSniklas }
2623c88b1d6cSniklas
2624c88b1d6cSniklas if (ok)
2625c88b1d6cSniklas {
26260c6d0228Sniklas if (! (*swap) (abfd, sec, relocs, contents, i))
2627c074d1c9Sdrahn return FALSE;
2628c074d1c9Sdrahn *pswapped = TRUE;
2629c88b1d6cSniklas continue;
2630c88b1d6cSniklas }
2631c88b1d6cSniklas }
2632c88b1d6cSniklas }
2633c88b1d6cSniklas }
26340c6d0228Sniklas
2635c074d1c9Sdrahn return TRUE;
26360c6d0228Sniklas }
2637b305b0f1Sespie #endif /* not COFF_IMAGE_WITH_PE */
26380c6d0228Sniklas
26390c6d0228Sniklas /* Look for loads and stores which we can align to four byte
26400c6d0228Sniklas boundaries. See the longer comment above sh_relax_section for why
26410c6d0228Sniklas this is desirable. This sets *PSWAPPED if some instruction was
26420c6d0228Sniklas swapped. */
26430c6d0228Sniklas
2644c074d1c9Sdrahn static bfd_boolean
sh_align_loads(abfd,sec,internal_relocs,contents,pswapped)26450c6d0228Sniklas sh_align_loads (abfd, sec, internal_relocs, contents, pswapped)
26460c6d0228Sniklas bfd *abfd;
26470c6d0228Sniklas asection *sec;
26480c6d0228Sniklas struct internal_reloc *internal_relocs;
26490c6d0228Sniklas bfd_byte *contents;
2650c074d1c9Sdrahn bfd_boolean *pswapped;
26510c6d0228Sniklas {
26520c6d0228Sniklas struct internal_reloc *irel, *irelend;
26530c6d0228Sniklas bfd_vma *labels = NULL;
26540c6d0228Sniklas bfd_vma *label, *label_end;
2655c074d1c9Sdrahn bfd_size_type amt;
26560c6d0228Sniklas
2657c074d1c9Sdrahn *pswapped = FALSE;
26580c6d0228Sniklas
26590c6d0228Sniklas irelend = internal_relocs + sec->reloc_count;
26600c6d0228Sniklas
26610c6d0228Sniklas /* Get all the addresses with labels on them. */
2662c074d1c9Sdrahn amt = (bfd_size_type) sec->reloc_count * sizeof (bfd_vma);
2663c074d1c9Sdrahn labels = (bfd_vma *) bfd_malloc (amt);
26640c6d0228Sniklas if (labels == NULL)
26650c6d0228Sniklas goto error_return;
26660c6d0228Sniklas label_end = labels;
26670c6d0228Sniklas for (irel = internal_relocs; irel < irelend; irel++)
26680c6d0228Sniklas {
26690c6d0228Sniklas if (irel->r_type == R_SH_LABEL)
26700c6d0228Sniklas {
26710c6d0228Sniklas *label_end = irel->r_vaddr - sec->vma;
26720c6d0228Sniklas ++label_end;
26730c6d0228Sniklas }
26740c6d0228Sniklas }
26750c6d0228Sniklas
26760c6d0228Sniklas /* Note that the assembler currently always outputs relocs in
26770c6d0228Sniklas address order. If that ever changes, this code will need to sort
26780c6d0228Sniklas the label values and the relocs. */
26790c6d0228Sniklas
26800c6d0228Sniklas label = labels;
26810c6d0228Sniklas
26820c6d0228Sniklas for (irel = internal_relocs; irel < irelend; irel++)
26830c6d0228Sniklas {
26840c6d0228Sniklas bfd_vma start, stop;
26850c6d0228Sniklas
26860c6d0228Sniklas if (irel->r_type != R_SH_CODE)
26870c6d0228Sniklas continue;
26880c6d0228Sniklas
26890c6d0228Sniklas start = irel->r_vaddr - sec->vma;
26900c6d0228Sniklas
26910c6d0228Sniklas for (irel++; irel < irelend; irel++)
26920c6d0228Sniklas if (irel->r_type == R_SH_DATA)
26930c6d0228Sniklas break;
26940c6d0228Sniklas if (irel < irelend)
26950c6d0228Sniklas stop = irel->r_vaddr - sec->vma;
26960c6d0228Sniklas else
26970c6d0228Sniklas stop = sec->_cooked_size;
26980c6d0228Sniklas
26990c6d0228Sniklas if (! _bfd_sh_align_load_span (abfd, sec, contents, sh_swap_insns,
27000c6d0228Sniklas (PTR) internal_relocs, &label,
27010c6d0228Sniklas label_end, start, stop, pswapped))
27020c6d0228Sniklas goto error_return;
2703c88b1d6cSniklas }
2704c88b1d6cSniklas
2705c88b1d6cSniklas free (labels);
2706c88b1d6cSniklas
2707c074d1c9Sdrahn return TRUE;
2708c88b1d6cSniklas
2709c88b1d6cSniklas error_return:
2710c88b1d6cSniklas if (labels != NULL)
2711c88b1d6cSniklas free (labels);
2712c074d1c9Sdrahn return FALSE;
2713c88b1d6cSniklas }
2714c88b1d6cSniklas
2715c88b1d6cSniklas /* Swap two SH instructions. */
2716c88b1d6cSniklas
2717c074d1c9Sdrahn static bfd_boolean
sh_swap_insns(abfd,sec,relocs,contents,addr)27180c6d0228Sniklas sh_swap_insns (abfd, sec, relocs, contents, addr)
2719c88b1d6cSniklas bfd *abfd;
2720c88b1d6cSniklas asection *sec;
27210c6d0228Sniklas PTR relocs;
2722c88b1d6cSniklas bfd_byte *contents;
2723c88b1d6cSniklas bfd_vma addr;
2724c88b1d6cSniklas {
27250c6d0228Sniklas struct internal_reloc *internal_relocs = (struct internal_reloc *) relocs;
2726c88b1d6cSniklas unsigned short i1, i2;
2727c88b1d6cSniklas struct internal_reloc *irel, *irelend;
2728c88b1d6cSniklas
2729c88b1d6cSniklas /* Swap the instructions themselves. */
2730c88b1d6cSniklas i1 = bfd_get_16 (abfd, contents + addr);
2731c88b1d6cSniklas i2 = bfd_get_16 (abfd, contents + addr + 2);
2732c074d1c9Sdrahn bfd_put_16 (abfd, (bfd_vma) i2, contents + addr);
2733c074d1c9Sdrahn bfd_put_16 (abfd, (bfd_vma) i1, contents + addr + 2);
2734c88b1d6cSniklas
2735c88b1d6cSniklas /* Adjust all reloc addresses. */
2736c88b1d6cSniklas irelend = internal_relocs + sec->reloc_count;
2737c88b1d6cSniklas for (irel = internal_relocs; irel < irelend; irel++)
2738c88b1d6cSniklas {
2739c88b1d6cSniklas int type, add;
2740c88b1d6cSniklas
2741c88b1d6cSniklas /* There are a few special types of relocs that we don't want to
2742c88b1d6cSniklas adjust. These relocs do not apply to the instruction itself,
2743c88b1d6cSniklas but are only associated with the address. */
2744c88b1d6cSniklas type = irel->r_type;
2745c88b1d6cSniklas if (type == R_SH_ALIGN
2746c88b1d6cSniklas || type == R_SH_CODE
2747c88b1d6cSniklas || type == R_SH_DATA
2748c88b1d6cSniklas || type == R_SH_LABEL)
2749c88b1d6cSniklas continue;
2750c88b1d6cSniklas
2751c88b1d6cSniklas /* If an R_SH_USES reloc points to one of the addresses being
2752c88b1d6cSniklas swapped, we must adjust it. It would be incorrect to do this
2753c88b1d6cSniklas for a jump, though, since we want to execute both
2754c88b1d6cSniklas instructions after the jump. (We have avoided swapping
2755c88b1d6cSniklas around a label, so the jump will not wind up executing an
2756c88b1d6cSniklas instruction it shouldn't). */
2757c88b1d6cSniklas if (type == R_SH_USES)
2758c88b1d6cSniklas {
2759c88b1d6cSniklas bfd_vma off;
2760c88b1d6cSniklas
2761c88b1d6cSniklas off = irel->r_vaddr - sec->vma + 4 + irel->r_offset;
2762c88b1d6cSniklas if (off == addr)
2763c88b1d6cSniklas irel->r_offset += 2;
2764c88b1d6cSniklas else if (off == addr + 2)
2765c88b1d6cSniklas irel->r_offset -= 2;
2766c88b1d6cSniklas }
2767c88b1d6cSniklas
2768c88b1d6cSniklas if (irel->r_vaddr - sec->vma == addr)
2769c88b1d6cSniklas {
2770c88b1d6cSniklas irel->r_vaddr += 2;
2771c88b1d6cSniklas add = -2;
2772c88b1d6cSniklas }
2773c88b1d6cSniklas else if (irel->r_vaddr - sec->vma == addr + 2)
2774c88b1d6cSniklas {
2775c88b1d6cSniklas irel->r_vaddr -= 2;
2776c88b1d6cSniklas add = 2;
2777c88b1d6cSniklas }
2778c88b1d6cSniklas else
2779c88b1d6cSniklas add = 0;
2780c88b1d6cSniklas
2781c88b1d6cSniklas if (add != 0)
2782c88b1d6cSniklas {
2783c88b1d6cSniklas bfd_byte *loc;
2784c88b1d6cSniklas unsigned short insn, oinsn;
2785c074d1c9Sdrahn bfd_boolean overflow;
2786c88b1d6cSniklas
2787c88b1d6cSniklas loc = contents + irel->r_vaddr - sec->vma;
2788c074d1c9Sdrahn overflow = FALSE;
2789c88b1d6cSniklas switch (type)
2790c88b1d6cSniklas {
2791c88b1d6cSniklas default:
2792c88b1d6cSniklas break;
2793c88b1d6cSniklas
2794c88b1d6cSniklas case R_SH_PCDISP8BY2:
2795c88b1d6cSniklas case R_SH_PCRELIMM8BY2:
2796c88b1d6cSniklas insn = bfd_get_16 (abfd, loc);
2797c88b1d6cSniklas oinsn = insn;
2798c88b1d6cSniklas insn += add / 2;
2799c88b1d6cSniklas if ((oinsn & 0xff00) != (insn & 0xff00))
2800c074d1c9Sdrahn overflow = TRUE;
2801c074d1c9Sdrahn bfd_put_16 (abfd, (bfd_vma) insn, loc);
2802c88b1d6cSniklas break;
2803c88b1d6cSniklas
2804c88b1d6cSniklas case R_SH_PCDISP:
2805c88b1d6cSniklas insn = bfd_get_16 (abfd, loc);
2806c88b1d6cSniklas oinsn = insn;
2807c88b1d6cSniklas insn += add / 2;
2808c88b1d6cSniklas if ((oinsn & 0xf000) != (insn & 0xf000))
2809c074d1c9Sdrahn overflow = TRUE;
2810c074d1c9Sdrahn bfd_put_16 (abfd, (bfd_vma) insn, loc);
2811c88b1d6cSniklas break;
2812c88b1d6cSniklas
2813c88b1d6cSniklas case R_SH_PCRELIMM8BY4:
2814c88b1d6cSniklas /* This reloc ignores the least significant 3 bits of
2815c88b1d6cSniklas the program counter before adding in the offset.
2816c88b1d6cSniklas This means that if ADDR is at an even address, the
2817c88b1d6cSniklas swap will not affect the offset. If ADDR is an at an
2818c88b1d6cSniklas odd address, then the instruction will be crossing a
2819c88b1d6cSniklas four byte boundary, and must be adjusted. */
2820c88b1d6cSniklas if ((addr & 3) != 0)
2821c88b1d6cSniklas {
2822c88b1d6cSniklas insn = bfd_get_16 (abfd, loc);
2823c88b1d6cSniklas oinsn = insn;
2824c88b1d6cSniklas insn += add / 2;
2825c88b1d6cSniklas if ((oinsn & 0xff00) != (insn & 0xff00))
2826c074d1c9Sdrahn overflow = TRUE;
2827c074d1c9Sdrahn bfd_put_16 (abfd, (bfd_vma) insn, loc);
2828c88b1d6cSniklas }
2829c88b1d6cSniklas
2830c88b1d6cSniklas break;
2831c88b1d6cSniklas }
2832c88b1d6cSniklas
2833c88b1d6cSniklas if (overflow)
2834c88b1d6cSniklas {
2835c88b1d6cSniklas ((*_bfd_error_handler)
2836c88b1d6cSniklas ("%s: 0x%lx: fatal: reloc overflow while relaxing",
2837c074d1c9Sdrahn bfd_archive_filename (abfd), (unsigned long) irel->r_vaddr));
2838c88b1d6cSniklas bfd_set_error (bfd_error_bad_value);
2839c074d1c9Sdrahn return FALSE;
2840c88b1d6cSniklas }
2841c88b1d6cSniklas }
2842c88b1d6cSniklas }
2843c88b1d6cSniklas
2844c074d1c9Sdrahn return TRUE;
2845c88b1d6cSniklas }
2846c88b1d6cSniklas
28472159047fSniklas /* This is a modification of _bfd_coff_generic_relocate_section, which
28482159047fSniklas will handle SH relaxing. */
28492159047fSniklas
2850c074d1c9Sdrahn static bfd_boolean
sh_relocate_section(output_bfd,info,input_bfd,input_section,contents,relocs,syms,sections)28512159047fSniklas sh_relocate_section (output_bfd, info, input_bfd, input_section, contents,
28522159047fSniklas relocs, syms, sections)
2853b305b0f1Sespie bfd *output_bfd ATTRIBUTE_UNUSED;
28542159047fSniklas struct bfd_link_info *info;
28552159047fSniklas bfd *input_bfd;
28562159047fSniklas asection *input_section;
28572159047fSniklas bfd_byte *contents;
28582159047fSniklas struct internal_reloc *relocs;
28592159047fSniklas struct internal_syment *syms;
28602159047fSniklas asection **sections;
28612159047fSniklas {
28622159047fSniklas struct internal_reloc *rel;
28632159047fSniklas struct internal_reloc *relend;
28642159047fSniklas
28652159047fSniklas rel = relocs;
28662159047fSniklas relend = rel + input_section->reloc_count;
28672159047fSniklas for (; rel < relend; rel++)
28682159047fSniklas {
28692159047fSniklas long symndx;
28702159047fSniklas struct coff_link_hash_entry *h;
28712159047fSniklas struct internal_syment *sym;
28722159047fSniklas bfd_vma addend;
28732159047fSniklas bfd_vma val;
28742159047fSniklas reloc_howto_type *howto;
28752159047fSniklas bfd_reloc_status_type rstat;
28762159047fSniklas
28772159047fSniklas /* Almost all relocs have to do with relaxing. If any work must
28782159047fSniklas be done for them, it has been done in sh_relax_section. */
28792159047fSniklas if (rel->r_type != R_SH_IMM32
2880b305b0f1Sespie #ifdef COFF_WITH_PE
2881b305b0f1Sespie && rel->r_type != R_SH_IMM32CE
2882b305b0f1Sespie && rel->r_type != R_SH_IMAGEBASE
2883b305b0f1Sespie #endif
28842159047fSniklas && rel->r_type != R_SH_PCDISP)
28852159047fSniklas continue;
28862159047fSniklas
28872159047fSniklas symndx = rel->r_symndx;
28882159047fSniklas
28892159047fSniklas if (symndx == -1)
28902159047fSniklas {
28912159047fSniklas h = NULL;
28922159047fSniklas sym = NULL;
28932159047fSniklas }
28942159047fSniklas else
28952159047fSniklas {
2896b305b0f1Sespie if (symndx < 0
2897b305b0f1Sespie || (unsigned long) symndx >= obj_raw_syment_count (input_bfd))
2898e93f7393Sniklas {
2899e93f7393Sniklas (*_bfd_error_handler)
2900e93f7393Sniklas ("%s: illegal symbol index %ld in relocs",
2901c074d1c9Sdrahn bfd_archive_filename (input_bfd), symndx);
2902e93f7393Sniklas bfd_set_error (bfd_error_bad_value);
2903c074d1c9Sdrahn return FALSE;
2904e93f7393Sniklas }
29052159047fSniklas h = obj_coff_sym_hashes (input_bfd)[symndx];
29062159047fSniklas sym = syms + symndx;
29072159047fSniklas }
29082159047fSniklas
29092159047fSniklas if (sym != NULL && sym->n_scnum != 0)
29102159047fSniklas addend = - sym->n_value;
29112159047fSniklas else
29122159047fSniklas addend = 0;
29132159047fSniklas
29142159047fSniklas if (rel->r_type == R_SH_PCDISP)
29152159047fSniklas addend -= 4;
29162159047fSniklas
29172159047fSniklas if (rel->r_type >= SH_COFF_HOWTO_COUNT)
29182159047fSniklas howto = NULL;
29192159047fSniklas else
29202159047fSniklas howto = &sh_coff_howtos[rel->r_type];
29212159047fSniklas
29222159047fSniklas if (howto == NULL)
29232159047fSniklas {
29242159047fSniklas bfd_set_error (bfd_error_bad_value);
2925c074d1c9Sdrahn return FALSE;
29262159047fSniklas }
29272159047fSniklas
2928b305b0f1Sespie #ifdef COFF_WITH_PE
2929b305b0f1Sespie if (rel->r_type == R_SH_IMAGEBASE)
2930b305b0f1Sespie addend -= pe_data (input_section->output_section->owner)->pe_opthdr.ImageBase;
2931b305b0f1Sespie #endif
2932b305b0f1Sespie
29332159047fSniklas val = 0;
29342159047fSniklas
29352159047fSniklas if (h == NULL)
29362159047fSniklas {
29372159047fSniklas asection *sec;
29382159047fSniklas
29392159047fSniklas /* There is nothing to do for an internal PCDISP reloc. */
29402159047fSniklas if (rel->r_type == R_SH_PCDISP)
29412159047fSniklas continue;
29422159047fSniklas
29432159047fSniklas if (symndx == -1)
29442159047fSniklas {
29452159047fSniklas sec = bfd_abs_section_ptr;
29462159047fSniklas val = 0;
29472159047fSniklas }
29482159047fSniklas else
29492159047fSniklas {
29502159047fSniklas sec = sections[symndx];
29512159047fSniklas val = (sec->output_section->vma
29522159047fSniklas + sec->output_offset
29532159047fSniklas + sym->n_value
29542159047fSniklas - sec->vma);
29552159047fSniklas }
29562159047fSniklas }
29572159047fSniklas else
29582159047fSniklas {
29592159047fSniklas if (h->root.type == bfd_link_hash_defined
29602159047fSniklas || h->root.type == bfd_link_hash_defweak)
29612159047fSniklas {
29622159047fSniklas asection *sec;
29632159047fSniklas
29642159047fSniklas sec = h->root.u.def.section;
29652159047fSniklas val = (h->root.u.def.value
29662159047fSniklas + sec->output_section->vma
29672159047fSniklas + sec->output_offset);
29682159047fSniklas }
2969*007c2a45Smiod else if (! info->relocatable)
29702159047fSniklas {
29712159047fSniklas if (! ((*info->callbacks->undefined_symbol)
29722159047fSniklas (info, h->root.root.string, input_bfd, input_section,
2973c074d1c9Sdrahn rel->r_vaddr - input_section->vma, TRUE)))
2974c074d1c9Sdrahn return FALSE;
29752159047fSniklas }
29762159047fSniklas }
29772159047fSniklas
29782159047fSniklas rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
29792159047fSniklas contents,
29802159047fSniklas rel->r_vaddr - input_section->vma,
29812159047fSniklas val, addend);
29822159047fSniklas
29832159047fSniklas switch (rstat)
29842159047fSniklas {
29852159047fSniklas default:
29862159047fSniklas abort ();
29872159047fSniklas case bfd_reloc_ok:
29882159047fSniklas break;
29892159047fSniklas case bfd_reloc_overflow:
29902159047fSniklas {
29912159047fSniklas const char *name;
29922159047fSniklas char buf[SYMNMLEN + 1];
29932159047fSniklas
29942159047fSniklas if (symndx == -1)
29952159047fSniklas name = "*ABS*";
29962159047fSniklas else if (h != NULL)
29972159047fSniklas name = h->root.root.string;
29982159047fSniklas else if (sym->_n._n_n._n_zeroes == 0
29992159047fSniklas && sym->_n._n_n._n_offset != 0)
30002159047fSniklas name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset;
30012159047fSniklas else
30022159047fSniklas {
30032159047fSniklas strncpy (buf, sym->_n._n_name, SYMNMLEN);
30042159047fSniklas buf[SYMNMLEN] = '\0';
30052159047fSniklas name = buf;
30062159047fSniklas }
30072159047fSniklas
30082159047fSniklas if (! ((*info->callbacks->reloc_overflow)
30092159047fSniklas (info, name, howto->name, (bfd_vma) 0, input_bfd,
30102159047fSniklas input_section, rel->r_vaddr - input_section->vma)))
3011c074d1c9Sdrahn return FALSE;
30122159047fSniklas }
30132159047fSniklas }
30142159047fSniklas }
30152159047fSniklas
3016c074d1c9Sdrahn return TRUE;
30172159047fSniklas }
30182159047fSniklas
30192159047fSniklas /* This is a version of bfd_generic_get_relocated_section_contents
30202159047fSniklas which uses sh_relocate_section. */
30212159047fSniklas
30222159047fSniklas static bfd_byte *
sh_coff_get_relocated_section_contents(output_bfd,link_info,link_order,data,relocatable,symbols)30232159047fSniklas sh_coff_get_relocated_section_contents (output_bfd, link_info, link_order,
3024*007c2a45Smiod data, relocatable, symbols)
30252159047fSniklas bfd *output_bfd;
30262159047fSniklas struct bfd_link_info *link_info;
30272159047fSniklas struct bfd_link_order *link_order;
30282159047fSniklas bfd_byte *data;
3029*007c2a45Smiod bfd_boolean relocatable;
30302159047fSniklas asymbol **symbols;
30312159047fSniklas {
30322159047fSniklas asection *input_section = link_order->u.indirect.section;
30332159047fSniklas bfd *input_bfd = input_section->owner;
30342159047fSniklas asection **sections = NULL;
30352159047fSniklas struct internal_reloc *internal_relocs = NULL;
30362159047fSniklas struct internal_syment *internal_syms = NULL;
30372159047fSniklas
30382159047fSniklas /* We only need to handle the case of relaxing, or of having a
30392159047fSniklas particular set of section contents, specially. */
3040*007c2a45Smiod if (relocatable
30412159047fSniklas || coff_section_data (input_bfd, input_section) == NULL
30422159047fSniklas || coff_section_data (input_bfd, input_section)->contents == NULL)
30432159047fSniklas return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
30442159047fSniklas link_order, data,
3045*007c2a45Smiod relocatable,
30462159047fSniklas symbols);
30472159047fSniklas
30482159047fSniklas memcpy (data, coff_section_data (input_bfd, input_section)->contents,
3049c074d1c9Sdrahn (size_t) input_section->_raw_size);
30502159047fSniklas
30512159047fSniklas if ((input_section->flags & SEC_RELOC) != 0
30522159047fSniklas && input_section->reloc_count > 0)
30532159047fSniklas {
30542159047fSniklas bfd_size_type symesz = bfd_coff_symesz (input_bfd);
30552159047fSniklas bfd_byte *esym, *esymend;
30562159047fSniklas struct internal_syment *isymp;
30572159047fSniklas asection **secpp;
3058c074d1c9Sdrahn bfd_size_type amt;
30592159047fSniklas
30602159047fSniklas if (! _bfd_coff_get_external_symbols (input_bfd))
30612159047fSniklas goto error_return;
30622159047fSniklas
30632159047fSniklas internal_relocs = (_bfd_coff_read_internal_relocs
3064c074d1c9Sdrahn (input_bfd, input_section, FALSE, (bfd_byte *) NULL,
3065c074d1c9Sdrahn FALSE, (struct internal_reloc *) NULL));
30662159047fSniklas if (internal_relocs == NULL)
30672159047fSniklas goto error_return;
30682159047fSniklas
3069c074d1c9Sdrahn amt = obj_raw_syment_count (input_bfd);
3070c074d1c9Sdrahn amt *= sizeof (struct internal_syment);
3071c074d1c9Sdrahn internal_syms = (struct internal_syment *) bfd_malloc (amt);
30722159047fSniklas if (internal_syms == NULL)
30732159047fSniklas goto error_return;
30742159047fSniklas
3075c074d1c9Sdrahn amt = obj_raw_syment_count (input_bfd);
3076c074d1c9Sdrahn amt *= sizeof (asection *);
3077c074d1c9Sdrahn sections = (asection **) bfd_malloc (amt);
30782159047fSniklas if (sections == NULL)
30792159047fSniklas goto error_return;
30802159047fSniklas
30812159047fSniklas isymp = internal_syms;
30822159047fSniklas secpp = sections;
30832159047fSniklas esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
30842159047fSniklas esymend = esym + obj_raw_syment_count (input_bfd) * symesz;
30852159047fSniklas while (esym < esymend)
30862159047fSniklas {
30872159047fSniklas bfd_coff_swap_sym_in (input_bfd, (PTR) esym, (PTR) isymp);
30882159047fSniklas
30892159047fSniklas if (isymp->n_scnum != 0)
30902159047fSniklas *secpp = coff_section_from_bfd_index (input_bfd, isymp->n_scnum);
30912159047fSniklas else
30922159047fSniklas {
30932159047fSniklas if (isymp->n_value == 0)
30942159047fSniklas *secpp = bfd_und_section_ptr;
30952159047fSniklas else
30962159047fSniklas *secpp = bfd_com_section_ptr;
30972159047fSniklas }
30982159047fSniklas
30992159047fSniklas esym += (isymp->n_numaux + 1) * symesz;
31002159047fSniklas secpp += isymp->n_numaux + 1;
31012159047fSniklas isymp += isymp->n_numaux + 1;
31022159047fSniklas }
31032159047fSniklas
31042159047fSniklas if (! sh_relocate_section (output_bfd, link_info, input_bfd,
31052159047fSniklas input_section, data, internal_relocs,
31062159047fSniklas internal_syms, sections))
31072159047fSniklas goto error_return;
31082159047fSniklas
31092159047fSniklas free (sections);
31102159047fSniklas sections = NULL;
31112159047fSniklas free (internal_syms);
31122159047fSniklas internal_syms = NULL;
31132159047fSniklas free (internal_relocs);
31142159047fSniklas internal_relocs = NULL;
31152159047fSniklas }
31162159047fSniklas
31172159047fSniklas return data;
31182159047fSniklas
31192159047fSniklas error_return:
31202159047fSniklas if (internal_relocs != NULL)
31212159047fSniklas free (internal_relocs);
31222159047fSniklas if (internal_syms != NULL)
31232159047fSniklas free (internal_syms);
31242159047fSniklas if (sections != NULL)
31252159047fSniklas free (sections);
31262159047fSniklas return NULL;
31272159047fSniklas }
31282159047fSniklas
31292159047fSniklas /* The target vectors. */
31302159047fSniklas
3131b305b0f1Sespie #ifndef TARGET_SHL_SYM
3132*007c2a45Smiod CREATE_BIG_COFF_TARGET_VEC (shcoff_vec, "coff-sh", BFD_IS_RELAXABLE, 0, '_', NULL, COFF_SWAP_TABLE)
3133b305b0f1Sespie #endif
3134b305b0f1Sespie
3135b305b0f1Sespie #ifdef TARGET_SHL_SYM
3136b305b0f1Sespie #define TARGET_SYM TARGET_SHL_SYM
3137b305b0f1Sespie #else
3138b305b0f1Sespie #define TARGET_SYM shlcoff_vec
3139b305b0f1Sespie #endif
3140b305b0f1Sespie
3141b305b0f1Sespie #ifndef TARGET_SHL_NAME
3142b305b0f1Sespie #define TARGET_SHL_NAME "coff-shl"
3143b305b0f1Sespie #endif
3144b305b0f1Sespie
3145b305b0f1Sespie #ifdef COFF_WITH_PE
3146b305b0f1Sespie CREATE_LITTLE_COFF_TARGET_VEC (TARGET_SYM, TARGET_SHL_NAME, BFD_IS_RELAXABLE,
3147*007c2a45Smiod SEC_CODE | SEC_DATA, '_', NULL, COFF_SWAP_TABLE);
3148b305b0f1Sespie #else
3149b305b0f1Sespie CREATE_LITTLE_COFF_TARGET_VEC (TARGET_SYM, TARGET_SHL_NAME, BFD_IS_RELAXABLE,
3150*007c2a45Smiod 0, '_', NULL, COFF_SWAP_TABLE)
3151b305b0f1Sespie #endif
3152b305b0f1Sespie
3153b305b0f1Sespie #ifndef TARGET_SHL_SYM
3154c074d1c9Sdrahn static const bfd_target * coff_small_object_p PARAMS ((bfd *));
3155c074d1c9Sdrahn static bfd_boolean coff_small_new_section_hook PARAMS ((bfd *, asection *));
3156b305b0f1Sespie /* Some people want versions of the SH COFF target which do not align
3157b305b0f1Sespie to 16 byte boundaries. We implement that by adding a couple of new
3158b305b0f1Sespie target vectors. These are just like the ones above, but they
3159b305b0f1Sespie change the default section alignment. To generate them in the
3160b305b0f1Sespie assembler, use -small. To use them in the linker, use -b
3161b305b0f1Sespie coff-sh{l}-small and -oformat coff-sh{l}-small.
3162b305b0f1Sespie
3163b305b0f1Sespie Yes, this is a horrible hack. A general solution for setting
3164b305b0f1Sespie section alignment in COFF is rather complex. ELF handles this
3165b305b0f1Sespie correctly. */
3166b305b0f1Sespie
3167b305b0f1Sespie /* Only recognize the small versions if the target was not defaulted.
3168b305b0f1Sespie Otherwise we won't recognize the non default endianness. */
3169b305b0f1Sespie
3170b305b0f1Sespie static const bfd_target *
coff_small_object_p(abfd)3171b305b0f1Sespie coff_small_object_p (abfd)
3172b305b0f1Sespie bfd *abfd;
31732159047fSniklas {
3174b305b0f1Sespie if (abfd->target_defaulted)
3175b305b0f1Sespie {
3176b305b0f1Sespie bfd_set_error (bfd_error_wrong_format);
3177b305b0f1Sespie return NULL;
3178b305b0f1Sespie }
3179b305b0f1Sespie return coff_object_p (abfd);
3180b305b0f1Sespie }
3181b305b0f1Sespie
3182b305b0f1Sespie /* Set the section alignment for the small versions. */
3183b305b0f1Sespie
3184c074d1c9Sdrahn static bfd_boolean
coff_small_new_section_hook(abfd,section)3185b305b0f1Sespie coff_small_new_section_hook (abfd, section)
3186b305b0f1Sespie bfd *abfd;
3187b305b0f1Sespie asection *section;
3188b305b0f1Sespie {
3189b305b0f1Sespie if (! coff_new_section_hook (abfd, section))
3190c074d1c9Sdrahn return FALSE;
3191b305b0f1Sespie
3192b305b0f1Sespie /* We must align to at least a four byte boundary, because longword
3193b305b0f1Sespie accesses must be on a four byte boundary. */
3194b305b0f1Sespie if (section->alignment_power == COFF_DEFAULT_SECTION_ALIGNMENT_POWER)
3195b305b0f1Sespie section->alignment_power = 2;
3196b305b0f1Sespie
3197c074d1c9Sdrahn return TRUE;
3198b305b0f1Sespie }
3199b305b0f1Sespie
3200b305b0f1Sespie /* This is copied from bfd_coff_std_swap_table so that we can change
3201b305b0f1Sespie the default section alignment power. */
3202b305b0f1Sespie
3203b305b0f1Sespie static const bfd_coff_backend_data bfd_coff_small_swap_table =
3204b305b0f1Sespie {
3205b305b0f1Sespie coff_swap_aux_in, coff_swap_sym_in, coff_swap_lineno_in,
3206b305b0f1Sespie coff_swap_aux_out, coff_swap_sym_out,
3207b305b0f1Sespie coff_swap_lineno_out, coff_swap_reloc_out,
3208b305b0f1Sespie coff_swap_filehdr_out, coff_swap_aouthdr_out,
3209b305b0f1Sespie coff_swap_scnhdr_out,
3210b305b0f1Sespie FILHSZ, AOUTSZ, SCNHSZ, SYMESZ, AUXESZ, RELSZ, LINESZ, FILNMLEN,
3211b305b0f1Sespie #ifdef COFF_LONG_FILENAMES
3212c074d1c9Sdrahn TRUE,
3213b305b0f1Sespie #else
3214c074d1c9Sdrahn FALSE,
3215b305b0f1Sespie #endif
3216b305b0f1Sespie #ifdef COFF_LONG_SECTION_NAMES
3217c074d1c9Sdrahn TRUE,
3218b305b0f1Sespie #else
3219c074d1c9Sdrahn FALSE,
3220b305b0f1Sespie #endif
3221b305b0f1Sespie 2,
3222b55d4692Sfgsch #ifdef COFF_FORCE_SYMBOLS_IN_STRINGS
3223c074d1c9Sdrahn TRUE,
3224b55d4692Sfgsch #else
3225c074d1c9Sdrahn FALSE,
3226b55d4692Sfgsch #endif
3227b55d4692Sfgsch #ifdef COFF_DEBUG_STRING_WIDE_PREFIX
3228b55d4692Sfgsch 4,
3229b55d4692Sfgsch #else
3230b55d4692Sfgsch 2,
3231b55d4692Sfgsch #endif
3232b305b0f1Sespie coff_swap_filehdr_in, coff_swap_aouthdr_in, coff_swap_scnhdr_in,
3233b305b0f1Sespie coff_swap_reloc_in, coff_bad_format_hook, coff_set_arch_mach_hook,
3234b305b0f1Sespie coff_mkobject_hook, styp_to_sec_flags, coff_set_alignment_hook,
3235b305b0f1Sespie coff_slurp_symbol_table, symname_in_debug_hook, coff_pointerize_aux_hook,
3236b305b0f1Sespie coff_print_aux, coff_reloc16_extra_cases, coff_reloc16_estimate,
3237b305b0f1Sespie coff_classify_symbol, coff_compute_section_file_positions,
3238b305b0f1Sespie coff_start_final_link, coff_relocate_section, coff_rtype_to_howto,
3239b305b0f1Sespie coff_adjust_symndx, coff_link_add_one_symbol,
3240b305b0f1Sespie coff_link_output_has_begun, coff_final_link_postscript
3241b305b0f1Sespie };
3242b305b0f1Sespie
3243b305b0f1Sespie #define coff_small_close_and_cleanup \
3244b305b0f1Sespie coff_close_and_cleanup
3245b305b0f1Sespie #define coff_small_bfd_free_cached_info \
3246b305b0f1Sespie coff_bfd_free_cached_info
3247b305b0f1Sespie #define coff_small_get_section_contents \
3248b305b0f1Sespie coff_get_section_contents
3249b305b0f1Sespie #define coff_small_get_section_contents_in_window \
3250b305b0f1Sespie coff_get_section_contents_in_window
3251b305b0f1Sespie
3252b305b0f1Sespie extern const bfd_target shlcoff_small_vec;
3253b305b0f1Sespie
3254b305b0f1Sespie const bfd_target shcoff_small_vec =
3255b305b0f1Sespie {
3256b305b0f1Sespie "coff-sh-small", /* name */
32572159047fSniklas bfd_target_coff_flavour,
3258c88b1d6cSniklas BFD_ENDIAN_BIG, /* data byte order is big */
3259c88b1d6cSniklas BFD_ENDIAN_BIG, /* header byte order is big */
32602159047fSniklas
32612159047fSniklas (HAS_RELOC | EXEC_P | /* object flags */
32622159047fSniklas HAS_LINENO | HAS_DEBUG |
32632159047fSniklas HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE),
32642159047fSniklas
32652159047fSniklas (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC),
32662159047fSniklas '_', /* leading symbol underscore */
32672159047fSniklas '/', /* ar_pad_char */
32682159047fSniklas 15, /* ar_max_namelen */
32692159047fSniklas bfd_getb64, bfd_getb_signed_64, bfd_putb64,
32702159047fSniklas bfd_getb32, bfd_getb_signed_32, bfd_putb32,
32712159047fSniklas bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
32722159047fSniklas bfd_getb64, bfd_getb_signed_64, bfd_putb64,
32732159047fSniklas bfd_getb32, bfd_getb_signed_32, bfd_putb32,
32742159047fSniklas bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
32752159047fSniklas
3276b305b0f1Sespie {_bfd_dummy_target, coff_small_object_p, /* bfd_check_format */
32772159047fSniklas bfd_generic_archive_p, _bfd_dummy_target},
32782159047fSniklas {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
32792159047fSniklas bfd_false},
32802159047fSniklas {bfd_false, coff_write_object_contents, /* bfd_write_contents */
32812159047fSniklas _bfd_write_archive_contents, bfd_false},
32822159047fSniklas
3283b305b0f1Sespie BFD_JUMP_TABLE_GENERIC (coff_small),
32842159047fSniklas BFD_JUMP_TABLE_COPY (coff),
32852159047fSniklas BFD_JUMP_TABLE_CORE (_bfd_nocore),
32862159047fSniklas BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
32872159047fSniklas BFD_JUMP_TABLE_SYMBOLS (coff),
32882159047fSniklas BFD_JUMP_TABLE_RELOCS (coff),
32892159047fSniklas BFD_JUMP_TABLE_WRITE (coff),
32902159047fSniklas BFD_JUMP_TABLE_LINK (coff),
32912159047fSniklas BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
32922159047fSniklas
3293b305b0f1Sespie & shlcoff_small_vec,
3294b305b0f1Sespie
3295b305b0f1Sespie (PTR) &bfd_coff_small_swap_table
32962159047fSniklas };
32972159047fSniklas
3298b305b0f1Sespie const bfd_target shlcoff_small_vec =
32992159047fSniklas {
3300b305b0f1Sespie "coff-shl-small", /* name */
33012159047fSniklas bfd_target_coff_flavour,
3302c88b1d6cSniklas BFD_ENDIAN_LITTLE, /* data byte order is little */
3303c88b1d6cSniklas BFD_ENDIAN_LITTLE, /* header byte order is little endian too*/
33042159047fSniklas
33052159047fSniklas (HAS_RELOC | EXEC_P | /* object flags */
33062159047fSniklas HAS_LINENO | HAS_DEBUG |
33072159047fSniklas HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE),
33082159047fSniklas
33092159047fSniklas (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC),
33102159047fSniklas '_', /* leading symbol underscore */
33112159047fSniklas '/', /* ar_pad_char */
33122159047fSniklas 15, /* ar_max_namelen */
33132159047fSniklas bfd_getl64, bfd_getl_signed_64, bfd_putl64,
33142159047fSniklas bfd_getl32, bfd_getl_signed_32, bfd_putl32,
33152159047fSniklas bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
33162159047fSniklas bfd_getl64, bfd_getl_signed_64, bfd_putl64,
33172159047fSniklas bfd_getl32, bfd_getl_signed_32, bfd_putl32,
33182159047fSniklas bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
33192159047fSniklas
3320b305b0f1Sespie {_bfd_dummy_target, coff_small_object_p, /* bfd_check_format */
33212159047fSniklas bfd_generic_archive_p, _bfd_dummy_target},
33222159047fSniklas {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
33232159047fSniklas bfd_false},
33242159047fSniklas {bfd_false, coff_write_object_contents, /* bfd_write_contents */
33252159047fSniklas _bfd_write_archive_contents, bfd_false},
33262159047fSniklas
3327b305b0f1Sespie BFD_JUMP_TABLE_GENERIC (coff_small),
33282159047fSniklas BFD_JUMP_TABLE_COPY (coff),
33292159047fSniklas BFD_JUMP_TABLE_CORE (_bfd_nocore),
33302159047fSniklas BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
33312159047fSniklas BFD_JUMP_TABLE_SYMBOLS (coff),
33322159047fSniklas BFD_JUMP_TABLE_RELOCS (coff),
33332159047fSniklas BFD_JUMP_TABLE_WRITE (coff),
33342159047fSniklas BFD_JUMP_TABLE_LINK (coff),
33352159047fSniklas BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
33362159047fSniklas
3337b305b0f1Sespie & shcoff_small_vec,
3338b305b0f1Sespie
3339b305b0f1Sespie (PTR) &bfd_coff_small_swap_table
33402159047fSniklas };
3341b305b0f1Sespie #endif
3342