diff options
author | Alan Modra <amodra@gmail.com> | 2018-04-16 15:29:39 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2018-04-16 15:29:39 +0930 |
commit | 211dc24b8744ed14ee5c293e7ac164d02e1fa1fe (patch) | |
tree | fcddbd29b4505638de6f018301a674816da8e025 /gas/config | |
parent | 4db9937a27496d2f62ac1dde76565809acd4ecde (diff) | |
download | gdb-211dc24b8744ed14ee5c293e7ac164d02e1fa1fe.zip gdb-211dc24b8744ed14ee5c293e7ac164d02e1fa1fe.tar.gz gdb-211dc24b8744ed14ee5c293e7ac164d02e1fa1fe.tar.bz2 |
Remove sh5 and sh64 support
include/
* dis-asm.h: Remove sh5 and sh64 support.
bfd/
* Makefile.am: Remove sh5 and sh64 support.
* archures.c: Likewise.
* config.bfd: Likewise.
* configure.ac: Likewise.
* cpu-sh.c: Likewise.
* elf32-sh-relocs.h: Likewise.
* elf32-sh.c: Likewise.
* targets.c: Likewise.
* elf32-sh64-com.c: Delete.
* elf32-sh64.c: Delete.
* elf32-sh64.h: Delete.
* elf64-sh64.c: Delete.
* Makefile.in: Regenerate.
* bfd-in2.h: Regenerate.
* configure: Regenerate.
* po/SRC-POTFILES.in: Regenerate.
opcodes/
* Makefile.am: Remove sh5 and sh64 support.
* configure.ac: Likewise.
* disassemble.c: Likewise.
* disassemble.h: Likewise.
* sh-dis.c: Likewise.
* sh64-dis.c: Delete.
* sh64-opc.c: Delete.
* sh64-opc.h: Delete.
* Makefile.in: Regenerate.
* configure: Regenerate.
* po/POTFILES.in: Regenerate.
bintuils/
* testsuite/binutils-all/objcopy.exp: Remove sh5 and sh64 support.
gas/
* Makefile.am: Remove sh5 and sh64 support.
* config/tc-sh.c: Likewise.
* configure.tgt: Likewise.
* doc/Makefile.am: Likewise.
* doc/as.texinfo: Likewise.
* testsuite/gas/cfi/cfi.exp: Likewise.
* testsuite/gas/sh/basic.exp: Likewise.
* config/tc-sh64.c: Delete.
* config/tc-sh64.h: Delete.
* doc/c-sh64.texi: Delete.
* testsuite/gas/sh/sh64/abi-32.d: Delete.
* testsuite/gas/sh/sh64/abi-32.s: Delete.
* testsuite/gas/sh/sh64/abi-64.d: Delete.
* testsuite/gas/sh/sh64/abi-64.s: Delete.
* testsuite/gas/sh/sh64/basic-1.d: Delete.
* testsuite/gas/sh/sh64/basic-1.s: Delete.
* testsuite/gas/sh/sh64/case-1.d: Delete.
* testsuite/gas/sh/sh64/case-1.s: Delete.
* testsuite/gas/sh/sh64/case-noexp-1.d: Delete.
* testsuite/gas/sh/sh64/crange1-1.d: Delete.
* testsuite/gas/sh/sh64/crange1-2.d: Delete.
* testsuite/gas/sh/sh64/crange1.s: Delete.
* testsuite/gas/sh/sh64/crange2-1.d: Delete.
* testsuite/gas/sh/sh64/crange2-2.d: Delete.
* testsuite/gas/sh/sh64/crange2-noexp-1.d: Delete.
* testsuite/gas/sh/sh64/crange2.s: Delete.
* testsuite/gas/sh/sh64/crange3-1.d: Delete.
* testsuite/gas/sh/sh64/crange3.s: Delete.
* testsuite/gas/sh/sh64/crange4-1.d: Delete.
* testsuite/gas/sh/sh64/crange4.s: Delete.
* testsuite/gas/sh/sh64/crange5-1.d: Delete.
* testsuite/gas/sh/sh64/crange5.s: Delete.
* testsuite/gas/sh/sh64/creg-1.d: Delete.
* testsuite/gas/sh/sh64/creg-1.s: Delete.
* testsuite/gas/sh/sh64/creg-2.d: Delete.
* testsuite/gas/sh/sh64/creg-2.s: Delete.
* testsuite/gas/sh/sh64/datal-1.s: Delete.
* testsuite/gas/sh/sh64/datal-2.d: Delete.
* testsuite/gas/sh/sh64/datal-2.s: Delete.
* testsuite/gas/sh/sh64/datal-3.s: Delete.
* testsuite/gas/sh/sh64/datal32-1.d: Delete.
* testsuite/gas/sh/sh64/datal32-3.d: Delete.
* testsuite/gas/sh/sh64/datal64-1.d: Delete.
* testsuite/gas/sh/sh64/datal64-3.d: Delete.
* testsuite/gas/sh/sh64/eh-1.d: Delete.
* testsuite/gas/sh/sh64/eh-1.s: Delete.
* testsuite/gas/sh/sh64/endian-1.d: Delete.
* testsuite/gas/sh/sh64/endian-1.s: Delete.
* testsuite/gas/sh/sh64/endian-2.d: Delete.
* testsuite/gas/sh/sh64/endian-2.s: Delete.
* testsuite/gas/sh/sh64/err-1.s: Delete.
* testsuite/gas/sh/sh64/err-2.s: Delete.
* testsuite/gas/sh/sh64/err-3.s: Delete.
* testsuite/gas/sh/sh64/err-4.s: Delete.
* testsuite/gas/sh/sh64/err-abi-32.s: Delete.
* testsuite/gas/sh/sh64/err-abi-64.s: Delete.
* testsuite/gas/sh/sh64/err-dsp.s: Delete.
* testsuite/gas/sh/sh64/err-movi-noexp-1.s: Delete.
* testsuite/gas/sh/sh64/err-noexp-cmd1.s: Delete.
* testsuite/gas/sh/sh64/err-pt-1.s: Delete.
* testsuite/gas/sh/sh64/err-pt32-cmd1.s: Delete.
* testsuite/gas/sh/sh64/err-pt32-cmd2.s: Delete.
* testsuite/gas/sh/sh64/err-pt32-cmd3.s: Delete.
* testsuite/gas/sh/sh64/err-ptb-1.s: Delete.
* testsuite/gas/sh/sh64/err-ptb-2.s: Delete.
* testsuite/gas/sh/sh64/err.exp: Delete.
* testsuite/gas/sh/sh64/immexpr1.s: Delete.
* testsuite/gas/sh/sh64/immexpr2.s: Delete.
* testsuite/gas/sh/sh64/immexpr32-1.d: Delete.
* testsuite/gas/sh/sh64/immexpr32-2.d: Delete.
* testsuite/gas/sh/sh64/immexpr64-1.d: Delete.
* testsuite/gas/sh/sh64/immexpr64-2.d: Delete.
* testsuite/gas/sh/sh64/lineno.d: Delete.
* testsuite/gas/sh/sh64/lineno.s: Delete.
* testsuite/gas/sh/sh64/localcom-1.d: Delete.
* testsuite/gas/sh/sh64/localcom-1.s: Delete.
* testsuite/gas/sh/sh64/mix-1.d: Delete.
* testsuite/gas/sh/sh64/mix-1.s: Delete.
* testsuite/gas/sh/sh64/mix-noexp-1.d: Delete.
* testsuite/gas/sh/sh64/movi-1.s: Delete.
* testsuite/gas/sh/sh64/movi-2.s: Delete.
* testsuite/gas/sh/sh64/movi-3.d: Delete.
* testsuite/gas/sh/sh64/movi-3.s: Delete.
* testsuite/gas/sh/sh64/movi32-1.d: Delete.
* testsuite/gas/sh/sh64/movi32-2.d: Delete.
* testsuite/gas/sh/sh64/movi32-noexp-2.d: Delete.
* testsuite/gas/sh/sh64/movi64-1.d: Delete.
* testsuite/gas/sh/sh64/movi64-2.d: Delete.
* testsuite/gas/sh/sh64/movi64-2.s: Delete.
* testsuite/gas/sh/sh64/movi64-3.d: Delete.
* testsuite/gas/sh/sh64/movi64-noexp-2.d: Delete.
* testsuite/gas/sh/sh64/pt-1.d: Delete.
* testsuite/gas/sh/sh64/pt-1.s: Delete.
* testsuite/gas/sh/sh64/pt-2.s: Delete.
* testsuite/gas/sh/sh64/pt-noexp-1.d: Delete.
* testsuite/gas/sh/sh64/pt32-1.d: Delete.
* testsuite/gas/sh/sh64/pt32-noexp-2.d: Delete.
* testsuite/gas/sh/sh64/pt64-1.d: Delete.
* testsuite/gas/sh/sh64/pt64-32-1.d: Delete.
* testsuite/gas/sh/sh64/pt64-32-2.d: Delete.
* testsuite/gas/sh/sh64/pt64-noexp-2.d: Delete.
* testsuite/gas/sh/sh64/ptc-1.s: Delete.
* testsuite/gas/sh/sh64/ptc32-1.d: Delete.
* testsuite/gas/sh/sh64/ptc32-noexp-1.d: Delete.
* testsuite/gas/sh/sh64/ptc64-1.d: Delete.
* testsuite/gas/sh/sh64/ptc64-32-1.d: Delete.
* testsuite/gas/sh/sh64/ptc64-noexp-1.d: Delete.
* testsuite/gas/sh/sh64/ptext-1.s: Delete.
* testsuite/gas/sh/sh64/ptext32-1.d: Delete.
* testsuite/gas/sh/sh64/ptext32-noexp-1.d: Delete.
* testsuite/gas/sh/sh64/ptext64-1.d: Delete.
* testsuite/gas/sh/sh64/ptext64-32-1.d: Delete.
* testsuite/gas/sh/sh64/ptext64-noexp-1.d: Delete.
* testsuite/gas/sh/sh64/rel-1.s: Delete.
* testsuite/gas/sh/sh64/rel-2.s: Delete.
* testsuite/gas/sh/sh64/rel-3.s: Delete.
* testsuite/gas/sh/sh64/rel-4.s: Delete.
* testsuite/gas/sh/sh64/rel-5.s: Delete.
* testsuite/gas/sh/sh64/rel32-1.d: Delete.
* testsuite/gas/sh/sh64/rel32-2.d: Delete.
* testsuite/gas/sh/sh64/rel32-3.d: Delete.
* testsuite/gas/sh/sh64/rel32-4.d: Delete.
* testsuite/gas/sh/sh64/rel32-5.d: Delete.
* testsuite/gas/sh/sh64/rel64-1.d: Delete.
* testsuite/gas/sh/sh64/rel64-2.d: Delete.
* testsuite/gas/sh/sh64/rel64-3.d: Delete.
* testsuite/gas/sh/sh64/rel64-4.d: Delete.
* testsuite/gas/sh/sh64/rel64-5.d: Delete.
* testsuite/gas/sh/sh64/relax-1.d: Delete.
* testsuite/gas/sh/sh64/relax-1.s: Delete.
* testsuite/gas/sh/sh64/relax-2.d: Delete.
* testsuite/gas/sh/sh64/relax-2.s: Delete.
* testsuite/gas/sh/sh64/relax-3.d: Delete.
* testsuite/gas/sh/sh64/relax-3.s: Delete.
* testsuite/gas/sh/sh64/sh64.exp: Delete.
* testsuite/gas/sh/sh64/shift-1.s: Delete.
* testsuite/gas/sh/sh64/shift-2.s: Delete.
* testsuite/gas/sh/sh64/shift-3.s: Delete.
* testsuite/gas/sh/sh64/shift32-1.d: Delete.
* testsuite/gas/sh/sh64/shift32-3.d: Delete.
* testsuite/gas/sh/sh64/shift32-noexp-3.d: Delete.
* testsuite/gas/sh/sh64/shift64-1.d: Delete.
* testsuite/gas/sh/sh64/shift64-2.d: Delete.
* testsuite/gas/sh/sh64/shift64-3.d: Delete.
* testsuite/gas/sh/sh64/shift64-noexp-3.d: Delete.
* testsuite/gas/sh/sh64/syntax-1.d: Delete.
* testsuite/gas/sh/sh64/syntax-1.s: Delete.
* testsuite/gas/sh/sh64/syntax-2.d: Delete.
* testsuite/gas/sh/sh64/syntax-2.s: Delete.
* testsuite/gas/sh/sh64/ua-1.s: Delete.
* testsuite/gas/sh/sh64/ua32-1.d: Delete.
* testsuite/gas/sh/sh64/ua64-1.d: Delete.
* Makefile.in: Regenerate.
* doc/Makefile.in: Regenerate.
* po/POTFILES.in: Regenerate.
ld/
* Makefile.am: Remove sh5 and sh64 support.
* configure.tgt: Likewise.
* ldlang.c: Likewise.
* testsuite/ld-elfcomm/elfcomm.exp: Likewise.
* testsuite/ld-gc/gc.exp: Likewise.
* testsuite/ld-gc/pr13683.d: Likewise.
* testsuite/ld-scripts/crossref.exp: Likewise.
* testsuite/ld-selective/selective.exp: Likewise.
* testsuite/ld-sh/ld-r-1.d: Likewise.
* testsuite/ld-sh/rd-sh.exp: Likewise.
* testsuite/ld-sh/sh.exp: Likewise.
* testsuite/ld-srec/srec.exp: Likewise.
* testsuite/ld-undefined/undefined.exp: Likewise.
* emulparams/shelf32.sh: Delete.
* emulparams/shelf32_linux.sh: Delete.
* emulparams/shelf32_nbsd.sh: Delete.
* emulparams/shelf64.sh: Delete.
* emulparams/shelf64_nbsd.sh: Delete.
* emulparams/shlelf32.sh: Delete.
* emulparams/shlelf32_linux.sh: Delete.
* emulparams/shlelf32_nbsd.sh: Delete.
* emulparams/shlelf64.sh: Delete.
* emulparams/shlelf64_nbsd.sh: Delete.
* emultempl/sh64elf.em: Delete.
* testsuite/ld-sh/sh64/abi32.sd: Delete.
* testsuite/ld-sh/sh64/abi32.xd: Delete.
* testsuite/ld-sh/sh64/abi64.sd: Delete.
* testsuite/ld-sh/sh64/abi64.xd: Delete.
* testsuite/ld-sh/sh64/abixx-noexp.sd: Delete.
* testsuite/ld-sh/sh64/cmpct1.sd: Delete.
* testsuite/ld-sh/sh64/cmpct1.xd: Delete.
* testsuite/ld-sh/sh64/crange-1.s: Delete.
* testsuite/ld-sh/sh64/crange-2a.s: Delete.
* testsuite/ld-sh/sh64/crange-2b.s: Delete.
* testsuite/ld-sh/sh64/crange-2c.s: Delete.
* testsuite/ld-sh/sh64/crange-2d.s: Delete.
* testsuite/ld-sh/sh64/crange-2e.s: Delete.
* testsuite/ld-sh/sh64/crange-2f.s: Delete.
* testsuite/ld-sh/sh64/crange-2g.s: Delete.
* testsuite/ld-sh/sh64/crange-2h.s: Delete.
* testsuite/ld-sh/sh64/crange-2i.s: Delete.
* testsuite/ld-sh/sh64/crange1.rd: Delete.
* testsuite/ld-sh/sh64/crange2.rd: Delete.
* testsuite/ld-sh/sh64/crange3-cmpct.rd: Delete.
* testsuite/ld-sh/sh64/crange3-media.rd: Delete.
* testsuite/ld-sh/sh64/crange3.dd: Delete.
* testsuite/ld-sh/sh64/crange3.rd: Delete.
* testsuite/ld-sh/sh64/crangerel1.rd: Delete.
* testsuite/ld-sh/sh64/crangerel2.rd: Delete.
* testsuite/ld-sh/sh64/dlsection-1.s: Delete.
* testsuite/ld-sh/sh64/dlsection.sd: Delete.
* testsuite/ld-sh/sh64/endian.dbd: Delete.
* testsuite/ld-sh/sh64/endian.dld: Delete.
* testsuite/ld-sh/sh64/endian.ld: Delete.
* testsuite/ld-sh/sh64/endian.s: Delete.
* testsuite/ld-sh/sh64/endian.sbd: Delete.
* testsuite/ld-sh/sh64/endian.sld: Delete.
* testsuite/ld-sh/sh64/gotplt.d: Delete.
* testsuite/ld-sh/sh64/gotplt.map: Delete.
* testsuite/ld-sh/sh64/gotplt.s: Delete.
* testsuite/ld-sh/sh64/init-cmpct.d: Delete.
* testsuite/ld-sh/sh64/init-media.d: Delete.
* testsuite/ld-sh/sh64/init.s: Delete.
* testsuite/ld-sh/sh64/init64.d: Delete.
* testsuite/ld-sh/sh64/mix1-noexp.sd: Delete.
* testsuite/ld-sh/sh64/mix1.sd: Delete.
* testsuite/ld-sh/sh64/mix1.xd: Delete.
* testsuite/ld-sh/sh64/mix2-noexp.sd: Delete.
* testsuite/ld-sh/sh64/mix2.sd: Delete.
* testsuite/ld-sh/sh64/mix2.xd: Delete.
* testsuite/ld-sh/sh64/rd-sh64.exp: Delete.
* testsuite/ld-sh/sh64/rel-1.s: Delete.
* testsuite/ld-sh/sh64/rel-2.s: Delete.
* testsuite/ld-sh/sh64/rel32.xd: Delete.
* testsuite/ld-sh/sh64/rel64.xd: Delete.
* testsuite/ld-sh/sh64/relax.exp: Delete.
* testsuite/ld-sh/sh64/relax1.s: Delete.
* testsuite/ld-sh/sh64/relax2.s: Delete.
* testsuite/ld-sh/sh64/relax3.s: Delete.
* testsuite/ld-sh/sh64/relax4.s: Delete.
* testsuite/ld-sh/sh64/reldl-1.s: Delete.
* testsuite/ld-sh/sh64/reldl-2.s: Delete.
* testsuite/ld-sh/sh64/reldl32.rd: Delete.
* testsuite/ld-sh/sh64/reldl64.rd: Delete.
* testsuite/ld-sh/sh64/relfail.exp: Delete.
* testsuite/ld-sh/sh64/relfail.s: Delete.
* testsuite/ld-sh/sh64/sh64-1.s: Delete.
* testsuite/ld-sh/sh64/sh64-2.s: Delete.
* testsuite/ld-sh/sh64/sh64.exp: Delete.
* testsuite/ld-sh/sh64/shcmp-1.s: Delete.
* testsuite/ld-sh/sh64/shdl-1.s: Delete.
* testsuite/ld-sh/sh64/shdl-2.s: Delete.
* testsuite/ld-sh/sh64/shdl32.xd: Delete.
* testsuite/ld-sh/sh64/shdl64.sd: Delete.
* testsuite/ld-sh/sh64/shdl64.xd: Delete.
* testsuite/ld-sh/sh64/shmix-1.s: Delete.
* testsuite/ld-sh/sh64/shmix-2.s: Delete.
* testsuite/ld-sh/sh64/shmix-3.s: Delete.
* testsuite/ld-sh/sh64/stobin-0-dso.d: Delete.
* testsuite/ld-sh/sh64/stobin-1.d: Delete.
* testsuite/ld-sh/sh64/stobin.s: Delete.
* testsuite/ld-sh/sh64/stolib.s: Delete.
* Makefile.in: Regenerate.
* po/BLD-POTFILES.in: Regenerate.
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-sh.c | 562 | ||||
-rw-r--r-- | gas/config/tc-sh64.c | 3526 | ||||
-rw-r--r-- | gas/config/tc-sh64.h | 226 |
3 files changed, 5 insertions, 4309 deletions
diff --git a/gas/config/tc-sh.c b/gas/config/tc-sh.c index 2704457..9b58db3 100644 --- a/gas/config/tc-sh.c +++ b/gas/config/tc-sh.c @@ -106,18 +106,6 @@ const pseudo_typeS md_pseudo_table[] = {"2byte", s_uacons, 2}, {"4byte", s_uacons, 4}, {"8byte", s_uacons, 8}, -#ifdef HAVE_SH64 - {"mode", s_sh64_mode, 0 }, - - /* Have the old name too. */ - {"isa", s_sh64_mode, 0 }, - - /* Assert that the right ABI is used. */ - {"abi", s_sh64_abi, 0 }, - - { "vtable_inherit", sh64_vtable_inherit, 0 }, - { "vtable_entry", sh64_vtable_entry, 0 }, -#endif /* HAVE_SH64 */ {0, 0, 0} }; @@ -167,31 +155,8 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP"; #define COND_JUMP_DELAY 2 #define UNCOND_JUMP 3 -#ifdef HAVE_SH64 - -/* A 16-bit (times four) pc-relative operand, at most expanded to 32 bits. */ -#define SH64PCREL16_32 4 -/* A 16-bit (times four) pc-relative operand, at most expanded to 64 bits. */ -#define SH64PCREL16_64 5 - -/* Variants of the above for adjusting the insn to PTA or PTB according to - the label. */ -#define SH64PCREL16PT_32 6 -#define SH64PCREL16PT_64 7 - -/* A MOVI expansion, expanding to at most 32 or 64 bits. */ -#define MOVI_IMM_32 8 -#define MOVI_IMM_32_PCREL 9 -#define MOVI_IMM_64 10 -#define MOVI_IMM_64_PCREL 11 -#define END 12 - -#else /* HAVE_SH64 */ - #define END 4 -#endif /* HAVE_SH64 */ - #define UNDEF_DISP 0 #define COND8 1 #define COND12 2 @@ -201,24 +166,6 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP"; #define UNCOND12 1 #define UNCOND32 2 -#ifdef HAVE_SH64 -#define UNDEF_SH64PCREL 0 -#define SH64PCREL16 1 -#define SH64PCREL32 2 -#define SH64PCREL48 3 -#define SH64PCREL64 4 -#define SH64PCRELPLT 5 - -#define UNDEF_MOVI 0 -#define MOVI_16 1 -#define MOVI_32 2 -#define MOVI_48 3 -#define MOVI_64 4 -#define MOVI_PLT 5 -#define MOVI_GOTOFF 6 -#define MOVI_GOTPC 7 -#endif /* HAVE_SH64 */ - /* Branch displacements are from the address of the branch plus four, thus all minimum and maximum values have 4 added to them. */ #define COND8_F 258 @@ -249,85 +196,6 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP"; #define UNCOND32_M -(1<<30) #define UNCOND32_LENGTH 14 -#ifdef HAVE_SH64 -/* The trivial expansion of a SH64PCREL16 relaxation is just a "PT label, - TRd" as is the current insn, so no extra length. Note that the "reach" - is calculated from the address *after* that insn, but the offset in the - insn is calculated from the beginning of the insn. We also need to - take into account the implicit 1 coded as the "A" in PTA when counting - forward. If PTB reaches an odd address, we trap that as an error - elsewhere, so we don't have to have different relaxation entries. We - don't add a one to the negative range, since PTB would then have the - farthest backward-reaching value skipped, not generated at relaxation. */ -#define SH64PCREL16_F (32767 * 4 - 4 + 1) -#define SH64PCREL16_M (-32768 * 4 - 4) -#define SH64PCREL16_LENGTH 0 - -/* The next step is to change that PT insn into - MOVI ((label - datalabel Ln) >> 16) & 65535, R25 - SHORI (label - datalabel Ln) & 65535, R25 - Ln: - PTREL R25,TRd - which means two extra insns, 8 extra bytes. This is the limit for the - 32-bit ABI. - - The expressions look a bit bad since we have to adjust this to avoid overflow on a - 32-bit host. */ -#define SH64PCREL32_F ((((long) 1 << 30) - 1) * 2 + 1 - 4) -#define SH64PCREL32_LENGTH (2 * 4) - -/* Similarly, we just change the MOVI and add a SHORI for the 48-bit - expansion. */ -#if BFD_HOST_64BIT_LONG -/* The "reach" type is long, so we can only do this for a 64-bit-long - host. */ -#define SH64PCREL32_M ((-((long) 1 << 30)) * 2 - 4) -#define SH64PCREL48_F ((((long) 1 << 47) - 1) - 4) -#define SH64PCREL48_M ((-((long) 1 << 47)) - 4) -#define SH64PCREL48_LENGTH (3 * 4) -#else -/* If the host does not have 64-bit longs, just make this state identical - in reach to the 32-bit state. Note that we have a slightly incorrect - reach, but the correct one above will overflow a 32-bit number. */ -#define SH64PCREL32_M ((-((long) 1 << 30)) * 2) -#define SH64PCREL48_F SH64PCREL32_F -#define SH64PCREL48_M SH64PCREL32_M -#define SH64PCREL48_LENGTH (3 * 4) -#endif /* BFD_HOST_64BIT_LONG */ - -/* And similarly for the 64-bit expansion; a MOVI + SHORI + SHORI + SHORI - + PTREL sequence. */ -#define SH64PCREL64_LENGTH (4 * 4) - -/* For MOVI, we make the MOVI + SHORI... expansion you can see in the - SH64PCREL expansions. The PCREL one is similar, but the other has no - pc-relative reach; it must be fully expanded in - shmedia_md_estimate_size_before_relax. */ -#define MOVI_16_LENGTH 0 -#define MOVI_16_F (32767 - 4) -#define MOVI_16_M (-32768 - 4) -#define MOVI_32_LENGTH 4 -#define MOVI_32_F ((((long) 1 << 30) - 1) * 2 + 1 - 4) -#define MOVI_48_LENGTH 8 - -#if BFD_HOST_64BIT_LONG -/* The "reach" type is long, so we can only do this for a 64-bit-long - host. */ -#define MOVI_32_M ((-((long) 1 << 30)) * 2 - 4) -#define MOVI_48_F ((((long) 1 << 47) - 1) - 4) -#define MOVI_48_M ((-((long) 1 << 47)) - 4) -#else -/* If the host does not have 64-bit longs, just make this state identical - in reach to the 32-bit state. Note that we have a slightly incorrect - reach, but the correct one above will overflow a 32-bit number. */ -#define MOVI_32_M ((-((long) 1 << 30)) * 2) -#define MOVI_48_F MOVI_32_F -#define MOVI_48_M MOVI_32_M -#endif /* BFD_HOST_64BIT_LONG */ - -#define MOVI_64_LENGTH 12 -#endif /* HAVE_SH64 */ - #define EMPTY { 0, 0, 0, 0 } const relax_typeS md_relax_table[C (END, 0)] = { @@ -369,117 +237,6 @@ const relax_typeS md_relax_table[C (END, 0)] = { EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, -#ifdef HAVE_SH64 - /* C (SH64PCREL16_32, SH64PCREL16) */ - EMPTY, - { SH64PCREL16_F, SH64PCREL16_M, SH64PCREL16_LENGTH, C (SH64PCREL16_32, SH64PCREL32) }, - /* C (SH64PCREL16_32, SH64PCREL32) */ - { 0, 0, SH64PCREL32_LENGTH, 0 }, - EMPTY, EMPTY, - /* C (SH64PCREL16_32, SH64PCRELPLT) */ - { 0, 0, SH64PCREL32_LENGTH, 0 }, - EMPTY, EMPTY, - EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, - - /* C (SH64PCREL16_64, SH64PCREL16) */ - EMPTY, - { SH64PCREL16_F, SH64PCREL16_M, SH64PCREL16_LENGTH, C (SH64PCREL16_64, SH64PCREL32) }, - /* C (SH64PCREL16_64, SH64PCREL32) */ - { SH64PCREL32_F, SH64PCREL32_M, SH64PCREL32_LENGTH, C (SH64PCREL16_64, SH64PCREL48) }, - /* C (SH64PCREL16_64, SH64PCREL48) */ - { SH64PCREL48_F, SH64PCREL48_M, SH64PCREL48_LENGTH, C (SH64PCREL16_64, SH64PCREL64) }, - /* C (SH64PCREL16_64, SH64PCREL64) */ - { 0, 0, SH64PCREL64_LENGTH, 0 }, - /* C (SH64PCREL16_64, SH64PCRELPLT) */ - { 0, 0, SH64PCREL64_LENGTH, 0 }, - EMPTY, EMPTY, - EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, - - /* C (SH64PCREL16PT_32, SH64PCREL16) */ - EMPTY, - { SH64PCREL16_F, SH64PCREL16_M, SH64PCREL16_LENGTH, C (SH64PCREL16PT_32, SH64PCREL32) }, - /* C (SH64PCREL16PT_32, SH64PCREL32) */ - { 0, 0, SH64PCREL32_LENGTH, 0 }, - EMPTY, EMPTY, - /* C (SH64PCREL16PT_32, SH64PCRELPLT) */ - { 0, 0, SH64PCREL32_LENGTH, 0 }, - EMPTY, EMPTY, - EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, - - /* C (SH64PCREL16PT_64, SH64PCREL16) */ - EMPTY, - { SH64PCREL16_F, SH64PCREL16_M, SH64PCREL16_LENGTH, C (SH64PCREL16PT_64, SH64PCREL32) }, - /* C (SH64PCREL16PT_64, SH64PCREL32) */ - { SH64PCREL32_F, - SH64PCREL32_M, - SH64PCREL32_LENGTH, - C (SH64PCREL16PT_64, SH64PCREL48) }, - /* C (SH64PCREL16PT_64, SH64PCREL48) */ - { SH64PCREL48_F, SH64PCREL48_M, SH64PCREL48_LENGTH, C (SH64PCREL16PT_64, SH64PCREL64) }, - /* C (SH64PCREL16PT_64, SH64PCREL64) */ - { 0, 0, SH64PCREL64_LENGTH, 0 }, - /* C (SH64PCREL16PT_64, SH64PCRELPLT) */ - { 0, 0, SH64PCREL64_LENGTH, 0}, - EMPTY, EMPTY, - EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, - - /* C (MOVI_IMM_32, UNDEF_MOVI) */ - { 0, 0, MOVI_32_LENGTH, 0 }, - /* C (MOVI_IMM_32, MOVI_16) */ - { MOVI_16_F, MOVI_16_M, MOVI_16_LENGTH, C (MOVI_IMM_32, MOVI_32) }, - /* C (MOVI_IMM_32, MOVI_32) */ - { MOVI_32_F, MOVI_32_M, MOVI_32_LENGTH, 0 }, - EMPTY, EMPTY, EMPTY, - /* C (MOVI_IMM_32, MOVI_GOTOFF) */ - { 0, 0, MOVI_32_LENGTH, 0 }, - EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, - - /* C (MOVI_IMM_32_PCREL, MOVI_16) */ - EMPTY, - { MOVI_16_F, MOVI_16_M, MOVI_16_LENGTH, C (MOVI_IMM_32_PCREL, MOVI_32) }, - /* C (MOVI_IMM_32_PCREL, MOVI_32) */ - { 0, 0, MOVI_32_LENGTH, 0 }, - EMPTY, EMPTY, - /* C (MOVI_IMM_32_PCREL, MOVI_PLT) */ - { 0, 0, MOVI_32_LENGTH, 0 }, - EMPTY, - /* C (MOVI_IMM_32_PCREL, MOVI_GOTPC) */ - { 0, 0, MOVI_32_LENGTH, 0 }, - EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, - - /* C (MOVI_IMM_64, UNDEF_MOVI) */ - { 0, 0, MOVI_64_LENGTH, 0 }, - /* C (MOVI_IMM_64, MOVI_16) */ - { MOVI_16_F, MOVI_16_M, MOVI_16_LENGTH, C (MOVI_IMM_64, MOVI_32) }, - /* C (MOVI_IMM_64, MOVI_32) */ - { MOVI_32_F, MOVI_32_M, MOVI_32_LENGTH, C (MOVI_IMM_64, MOVI_48) }, - /* C (MOVI_IMM_64, MOVI_48) */ - { MOVI_48_F, MOVI_48_M, MOVI_48_LENGTH, C (MOVI_IMM_64, MOVI_64) }, - /* C (MOVI_IMM_64, MOVI_64) */ - { 0, 0, MOVI_64_LENGTH, 0 }, - EMPTY, - /* C (MOVI_IMM_64, MOVI_GOTOFF) */ - { 0, 0, MOVI_64_LENGTH, 0 }, - EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, - - /* C (MOVI_IMM_64_PCREL, MOVI_16) */ - EMPTY, - { MOVI_16_F, MOVI_16_M, MOVI_16_LENGTH, C (MOVI_IMM_64_PCREL, MOVI_32) }, - /* C (MOVI_IMM_64_PCREL, MOVI_32) */ - { MOVI_32_F, MOVI_32_M, MOVI_32_LENGTH, C (MOVI_IMM_64_PCREL, MOVI_48) }, - /* C (MOVI_IMM_64_PCREL, MOVI_48) */ - { MOVI_48_F, MOVI_48_M, MOVI_48_LENGTH, C (MOVI_IMM_64_PCREL, MOVI_64) }, - /* C (MOVI_IMM_64_PCREL, MOVI_64) */ - { 0, 0, MOVI_64_LENGTH, 0 }, - /* C (MOVI_IMM_64_PCREL, MOVI_PLT) */ - { 0, 0, MOVI_64_LENGTH, 0 }, - EMPTY, - /* C (MOVI_IMM_64_PCREL, MOVI_GOTPC) */ - { 0, 0, MOVI_64_LENGTH, 0 }, - EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, - -#endif /* HAVE_SH64 */ - }; #undef EMPTY @@ -501,11 +258,6 @@ sh_PIC_related_p (symbolS *sym) if (sym == GOT_symbol) return 1; -#ifdef HAVE_SH64 - if (sh_PIC_related_p (*symbol_get_tc (sym))) - return 1; -#endif - exp = symbol_get_value_expression (sym); return (exp->X_op == O_PIC_reloc @@ -567,47 +319,11 @@ sh_check_fixup (expressionS *main_exp, bfd_reloc_code_real_type *r_type_p) if (exp->X_op == O_symbol || exp->X_op == O_add || exp->X_op == O_subtract) { -#ifdef HAVE_SH64 - if (exp->X_add_symbol - && (exp->X_add_symbol == GOT_symbol - || (GOT_symbol - && *symbol_get_tc (exp->X_add_symbol) == GOT_symbol))) - { - switch (*r_type_p) - { - case BFD_RELOC_SH_IMM_LOW16: - *r_type_p = BFD_RELOC_SH_GOTPC_LOW16; - break; - - case BFD_RELOC_SH_IMM_MEDLOW16: - *r_type_p = BFD_RELOC_SH_GOTPC_MEDLOW16; - break; - - case BFD_RELOC_SH_IMM_MEDHI16: - *r_type_p = BFD_RELOC_SH_GOTPC_MEDHI16; - break; - - case BFD_RELOC_SH_IMM_HI16: - *r_type_p = BFD_RELOC_SH_GOTPC_HI16; - break; - - case BFD_RELOC_NONE: - case BFD_RELOC_UNUSED: - *r_type_p = BFD_RELOC_SH_GOTPC; - break; - - default: - abort (); - } - return 0; - } -#else if (exp->X_add_symbol && exp->X_add_symbol == GOT_symbol) { *r_type_p = BFD_RELOC_SH_GOTPC; return 0; } -#endif exp = symbol_get_value_expression (exp->X_add_symbol); if (! exp) return 0; @@ -646,104 +362,6 @@ sh_check_fixup (expressionS *main_exp, bfd_reloc_code_real_type *r_type_p) } break; -#ifdef HAVE_SH64 - case BFD_RELOC_SH_IMM_LOW16: - switch (exp->X_md) - { - case BFD_RELOC_32_GOTOFF: - *r_type_p = BFD_RELOC_SH_GOTOFF_LOW16; - break; - - case BFD_RELOC_SH_GOTPLT32: - *r_type_p = BFD_RELOC_SH_GOTPLT_LOW16; - break; - - case BFD_RELOC_32_GOT_PCREL: - *r_type_p = BFD_RELOC_SH_GOT_LOW16; - break; - - case BFD_RELOC_32_PLT_PCREL: - *r_type_p = BFD_RELOC_SH_PLT_LOW16; - break; - - default: - abort (); - } - break; - - case BFD_RELOC_SH_IMM_MEDLOW16: - switch (exp->X_md) - { - case BFD_RELOC_32_GOTOFF: - *r_type_p = BFD_RELOC_SH_GOTOFF_MEDLOW16; - break; - - case BFD_RELOC_SH_GOTPLT32: - *r_type_p = BFD_RELOC_SH_GOTPLT_MEDLOW16; - break; - - case BFD_RELOC_32_GOT_PCREL: - *r_type_p = BFD_RELOC_SH_GOT_MEDLOW16; - break; - - case BFD_RELOC_32_PLT_PCREL: - *r_type_p = BFD_RELOC_SH_PLT_MEDLOW16; - break; - - default: - abort (); - } - break; - - case BFD_RELOC_SH_IMM_MEDHI16: - switch (exp->X_md) - { - case BFD_RELOC_32_GOTOFF: - *r_type_p = BFD_RELOC_SH_GOTOFF_MEDHI16; - break; - - case BFD_RELOC_SH_GOTPLT32: - *r_type_p = BFD_RELOC_SH_GOTPLT_MEDHI16; - break; - - case BFD_RELOC_32_GOT_PCREL: - *r_type_p = BFD_RELOC_SH_GOT_MEDHI16; - break; - - case BFD_RELOC_32_PLT_PCREL: - *r_type_p = BFD_RELOC_SH_PLT_MEDHI16; - break; - - default: - abort (); - } - break; - - case BFD_RELOC_SH_IMM_HI16: - switch (exp->X_md) - { - case BFD_RELOC_32_GOTOFF: - *r_type_p = BFD_RELOC_SH_GOTOFF_HI16; - break; - - case BFD_RELOC_SH_GOTPLT32: - *r_type_p = BFD_RELOC_SH_GOTPLT_HI16; - break; - - case BFD_RELOC_32_GOT_PCREL: - *r_type_p = BFD_RELOC_SH_GOT_HI16; - break; - - case BFD_RELOC_32_PLT_PCREL: - *r_type_p = BFD_RELOC_SH_PLT_HI16; - break; - - default: - abort (); - } - break; -#endif - default: abort (); } @@ -815,16 +433,6 @@ sh_elf_cons (int nbytes) { expressionS exp; -#ifdef HAVE_SH64 - - /* Update existing range to include a previous insn, if there was one. */ - sh64_update_contents_mark (TRUE); - - /* We need to make sure the contents type is set to data. */ - sh64_flag_output (); - -#endif /* HAVE_SH64 */ - if (is_it_end_of_statement ()) { demand_empty_rest_of_line (); @@ -957,10 +565,6 @@ md_begin (void) = preset_target_arch ? preset_target_arch : arch_sh_up & ~arch_sh_has_dsp; valid_arch = target_arch; -#ifdef HAVE_SH64 - shmedia_md_begin (); -#endif - opcode_hash_control = hash_new (); /* Insert unique names into hash table. */ @@ -2906,26 +2510,6 @@ md_assemble (char *str) unsigned int size = 0; char *initial_str = str; -#ifdef HAVE_SH64 - if (sh64_isa_mode == sh64_isa_shmedia) - { - shmedia_md_assemble (str); - return; - } - else - { - /* If we've seen pseudo-directives, make sure any emitted data or - frags are marked as data. */ - if (!seen_insn) - { - sh64_update_contents_mark (TRUE); - sh64_set_contents_type (CRT_SH5_ISA16); - } - - seen_insn = TRUE; - } -#endif /* HAVE_SH64 */ - opcode = find_cooked_opcode (&str); op_end = str; @@ -3136,13 +2720,6 @@ enum options OPTION_ISA, OPTION_RENESAS, OPTION_ALLOW_REG_PREFIX, -#ifdef HAVE_SH64 - OPTION_ABI, - OPTION_NO_MIX, - OPTION_SHCOMPACT_CONST_CRANGE, - OPTION_NO_EXPAND, - OPTION_PT32, -#endif OPTION_H_TICK_HEX, #ifdef OBJ_ELF OPTION_FDPIC, @@ -3166,13 +2743,6 @@ struct option md_longopts[] = {"renesas", no_argument, NULL, OPTION_RENESAS}, {"allow-reg-prefix", no_argument, NULL, OPTION_ALLOW_REG_PREFIX}, -#ifdef HAVE_SH64 - {"abi", required_argument, NULL, OPTION_ABI}, - {"no-mix", no_argument, NULL, OPTION_NO_MIX}, - {"shcompact-const-crange", no_argument, NULL, OPTION_SHCOMPACT_CONST_CRANGE}, - {"no-expand", no_argument, NULL, OPTION_NO_EXPAND}, - {"expand-pt32", no_argument, NULL, OPTION_PT32}, -#endif /* HAVE_SH64 */ { "h-tick-hex", no_argument, NULL, OPTION_H_TICK_HEX }, #ifdef OBJ_ELF @@ -3223,22 +2793,6 @@ md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED) preset_target_arch = arch_sh_up & ~arch_sh_has_dsp; else if (strcasecmp (arg, "any") == 0) preset_target_arch = arch_sh_up; -#ifdef HAVE_SH64 - else if (strcasecmp (arg, "shmedia") == 0) - { - if (sh64_isa_mode == sh64_isa_shcompact) - as_bad (_("Invalid combination: --isa=SHcompact with --isa=SHmedia")); - sh64_isa_mode = sh64_isa_shmedia; - } - else if (strcasecmp (arg, "shcompact") == 0) - { - if (sh64_isa_mode == sh64_isa_shmedia) - as_bad (_("Invalid combination: --isa=SHmedia with --isa=SHcompact")); - if (sh64_abi == sh64_abi_64) - as_bad (_("Invalid combination: --abi=64 with --isa=SHcompact")); - sh64_isa_mode = sh64_isa_shcompact; - } -#endif /* HAVE_SH64 */ else { extern const bfd_arch_info_type bfd_sh_arch; @@ -3249,9 +2803,6 @@ md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED) { int len = strlen(bfd_arch->printable_name); - if (bfd_arch->mach == bfd_mach_sh5) - continue; - if (strncasecmp (bfd_arch->printable_name, arg, len) != 0) continue; @@ -3271,43 +2822,6 @@ md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED) } break; -#ifdef HAVE_SH64 - case OPTION_ABI: - if (strcmp (arg, "32") == 0) - { - if (sh64_abi == sh64_abi_64) - as_bad (_("Invalid combination: --abi=32 with --abi=64")); - sh64_abi = sh64_abi_32; - } - else if (strcmp (arg, "64") == 0) - { - if (sh64_abi == sh64_abi_32) - as_bad (_("Invalid combination: --abi=64 with --abi=32")); - if (sh64_isa_mode == sh64_isa_shcompact) - as_bad (_("Invalid combination: --isa=SHcompact with --abi=64")); - sh64_abi = sh64_abi_64; - } - else - as_bad (_("Invalid argument to --abi option: %s"), arg); - break; - - case OPTION_NO_MIX: - sh64_mix = FALSE; - break; - - case OPTION_SHCOMPACT_CONST_CRANGE: - sh64_shcompact_const_crange = TRUE; - break; - - case OPTION_NO_EXPAND: - sh64_expand = FALSE; - break; - - case OPTION_PT32: - sh64_pt32 = TRUE; - break; -#endif /* HAVE_SH64 */ - case OPTION_H_TICK_HEX: enable_h_tick_hex = 1; break; @@ -3346,30 +2860,12 @@ SH options:\n\ bfd_arch_info_type const *bfd_arch = &bfd_sh_arch; for (; bfd_arch; bfd_arch=bfd_arch->next) - if (bfd_arch->mach != bfd_mach_sh5) - { - fprintf (stream, "\n | %s", bfd_arch->printable_name); - fprintf (stream, "\n | %s-up", bfd_arch->printable_name); - } + { + fprintf (stream, "\n | %s", bfd_arch->printable_name); + fprintf (stream, "\n | %s-up", bfd_arch->printable_name); + } } fprintf (stream, "]\n"); -#ifdef HAVE_SH64 - fprintf (stream, _("\ ---isa=[shmedia set as the default instruction set for SH64\n\ - | SHmedia\n\ - | shcompact\n\ - | SHcompact]\n")); - fprintf (stream, _("\ ---abi=[32|64] set size of expanded SHmedia operands and object\n\ - file type\n\ ---shcompact-const-crange emit code-range descriptors for constants in\n\ - SHcompact code sections\n\ ---no-mix disallow SHmedia code in the same section as\n\ - constants and SHcompact code\n\ ---no-expand do not expand MOVI, PT, PTA or PTB instructions\n\ ---expand-pt32 with -abi=64, expand PT, PTA and PTB instructions\n\ - to 32 bits only\n")); -#endif /* HAVE_SH64 */ #ifdef OBJ_ELF fprintf (stream, _("\ --fdpic generate an FDPIC object file\n")); @@ -3537,10 +3033,6 @@ sh_frob_section (bfd *abfd ATTRIBUTE_UNUSED, segT sec, void sh_frob_file (void) { -#ifdef HAVE_SH64 - shmedia_frob_file_before_adjust (); -#endif - if (! sh_relax) return; @@ -3673,11 +3165,7 @@ md_convert_frag (bfd *headers ATTRIBUTE_UNUSED, segT seg, fragS *fragP) break; default: -#ifdef HAVE_SH64 - shmedia_md_convert_frag (headers, seg, fragP, TRUE); -#else abort (); -#endif } if (donerelax && !sh_relax) @@ -3854,9 +3342,6 @@ sh_force_relocation (fixS *fix) || fix->fx_r_type == BFD_RELOC_SH_ALIGN || fix->fx_r_type == BFD_RELOC_SH_CODE || fix->fx_r_type == BFD_RELOC_SH_DATA -#ifdef HAVE_SH64 - || fix->fx_r_type == BFD_RELOC_SH_SHMEDIA_CODE -#endif || fix->fx_r_type == BFD_RELOC_SH_LABEL); } @@ -3892,14 +3377,7 @@ sh_elf_final_processing (void) /* Set file-specific flags to indicate if this code needs a processor with the sh-dsp / sh2e ISA to execute. */ -#ifdef HAVE_SH64 - /* SH5 and above don't know about the valid_arch arch_sh* bits defined - in sh-opc.h, so check SH64 mode before checking valid_arch. */ - if (sh64_isa_mode != sh64_isa_unspecified) - val = EF_SH5; - else -#endif /* HAVE_SH64 */ - val = sh_find_elf_flags (valid_arch); + val = sh_find_elf_flags (valid_arch); elf_elfheader (stdoutput)->e_flags &= ~EF_SH_MACH_MASK; elf_elfheader (stdoutput)->e_flags |= val; @@ -3961,11 +3439,6 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) the other symbol. We have to adjust the relocation type here. */ if (fixP->fx_pcrel) { -#ifndef HAVE_SH64 - /* Safeguard; this must not occur for non-sh64 configurations. */ - gas_assert (fixP->fx_r_type != BFD_RELOC_64); -#endif - switch (fixP->fx_r_type) { default: @@ -4164,12 +3637,6 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) buf[highbyte] |= (val >> 8) & 0xf; break; -#ifndef HAVE_SH64 - case BFD_RELOC_64: - apply_full_field_fix (fixP, buf, *valP, 8); - break; -#endif - case BFD_RELOC_32: case BFD_RELOC_32_PCREL: apply_full_field_fix (fixP, buf, val, 4); @@ -4260,12 +3727,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) #endif default: -#ifdef HAVE_SH64 - shmedia_md_apply_fix (fixP, valP); - return; -#else abort (); -#endif } if (shift != 0) @@ -4304,12 +3766,7 @@ md_estimate_size_before_relax (fragS *fragP, segT segment_type) switch (fragP->fr_subtype) { default: -#ifdef HAVE_SH64 - return shmedia_md_estimate_size_before_relax (fragP, segment_type); -#else abort (); -#endif - case C (UNCOND_JUMP, UNDEF_DISP): /* Used to be a branch to somewhere which was unknown. */ @@ -4375,11 +3832,6 @@ md_estimate_size_before_relax (fragS *fragP, segT segment_type) void md_number_to_chars (char *ptr, valueT use, int nbytes) { -#ifdef HAVE_SH64 - /* We might need to set the contents type to data. */ - sh64_flag_output (); -#endif - if (! target_big_endian) number_to_chars_littleendian (ptr, use, nbytes); else @@ -4457,10 +3909,6 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) rel->addend = 0; rel->address = rel->addend = fixp->fx_offset; } -#ifdef HAVE_SH64 - else if (shmedia_init_reloc (rel, fixp)) - ; -#endif else rel->addend = fixp->fx_addnumber; diff --git a/gas/config/tc-sh64.c b/gas/config/tc-sh64.c deleted file mode 100644 index 001fa2a..0000000 --- a/gas/config/tc-sh64.c +++ /dev/null @@ -1,3526 +0,0 @@ -/* tc-sh64.c -- Assemble code for the SuperH SH SHcompact and SHmedia. - Copyright (C) 2000-2018 Free Software Foundation, Inc. - - This file is part of GAS, the GNU Assembler. - - GAS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - GAS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GAS; see the file COPYING. If not, write to - the Free Software Foundation, 51 Franklin Street - Fifth Floor, - Boston, MA 02110-1301, USA. */ - -/* This file defines SHmedia ISA-specific functions and includes tc-sh.c. - The SHcompact ISA is in all useful aspects the "old" sh4 as implemented - in tc-sh.c. Not making this file part of tc-sh.c makes it easier to - keep a leaner sh[1-4]-only implementation. */ - -#define HAVE_SH64 - -#include "as.h" -#include "safe-ctype.h" -#include "opcodes/sh64-opc.h" - -#ifndef OBJ_ELF -#error This file assumes object output is in the ELF format -#endif - -/* Suffix used when we make "datalabel" symbol copies. It must not - collide with anything that can normally appear in a symbol, "faked - symbol" or local symbol. */ -#define DATALABEL_SUFFIX " DL" - -/* See shmedia_md_apply_fix and shmedia_md_pcrel_from_section for usage. */ -#define SHMEDIA_MD_PCREL_FROM_FIX(FIXP) \ - ((FIXP)->fx_size + (FIXP)->fx_where + (FIXP)->fx_frag->fr_address - 4) - -/* We use this internally to see which one is PT and which is a PTA/PTB - that should be error-checked. We give it a better name here (but not - one that looks official). Adding it to reloc.c would make it look too - much of a real reloc; it is just used temporarily as a fixup-type. */ -#define SHMEDIA_BFD_RELOC_PT BFD_RELOC_12_PCREL - -typedef struct - { - shmedia_arg_type type; - - /* These could go into a union, but that would uglify the code. */ - int reg; - expressionS immediate; - - /* If IMMEDIATE was a shift-expression, like "(S >> N) & 65535", where - N = 0, 16, 32, 48, used to extract a certain 16-bit-field to make up - a MOVI or SHORI relocation for a symbol, then we put the - corresponding reloc-type here and modify the "immediate" expression - to S. Otherwise, this is just BFD_RELOC_NONE. */ - bfd_reloc_code_real_type reloctype; - } shmedia_operand_info; - -/* Frag containing last base instruction. This is put in the TC field in - a frag, so we can emit fixups for fr_opcode without needing to make - sure that the opcode is in the same frag as any variant operand. */ -fragS *sh64_last_insn_frag = NULL; - -typedef struct - { - shmedia_operand_info operands[3]; - unsigned long ops_val; - } shmedia_operands_info; - -enum sh64_abi_values - { sh64_abi_unspecified, sh64_abi_32, sh64_abi_64 }; - -/* What ISA are we assembling code for? */ -enum sh64_isa_values sh64_isa_mode = sh64_isa_unspecified; - -/* What ABI was specified, if any (implicitly or explicitly)? */ -static enum sh64_abi_values sh64_abi = sh64_abi_unspecified; - -/* A note that says if we're in a sequence of insns without label - settings, segment or ISA mode changes or emitted data. */ -static bfd_boolean seen_insn = FALSE; - -/* This is set to TRUE in shmedia_md_end, so that we don't emit any - .cranges entries when the assembler calls output functions while - grinding along after all input is seen. */ -static bfd_boolean sh64_end_of_assembly = FALSE; - -/* Controlled by the option -no-mix, this invalidates mixing SHcompact and - SHmedia code in the same section, and also invalidates mixing data and - SHmedia code in the same section. No .cranges will therefore be - emitted, unless -shcompact-const-crange is specified and there is a - constant pool in SHcompact code. */ -static bfd_boolean sh64_mix = TRUE; - -static bfd_boolean sh64_shcompact_const_crange = FALSE; - -/* Controlled by the option -no-expand, this says whether or not we expand - MOVI and PT/PTA/PTB. When we do not expand these insns to fit an - operand, we will emit errors for operands out of range and generate the - basic instruction and reloc for an external symbol. */ -static bfd_boolean sh64_expand = TRUE; - -/* Controlled by the option -expand-pt32, this says whether we expand - PT/PTA/PTB of an external symbol to (only) 32 or (the full) 64 bits - when -abi=64 is in effect. */ -static bfd_boolean sh64_pt32 = FALSE; - -/* When emitting a .cranges descriptor, we want to avoid getting recursive - calls through emit_expr. */ -static bfd_boolean emitting_crange = FALSE; - -/* SHmedia mnemonics. */ -static struct hash_control *shmedia_opcode_hash_control = NULL; - -static const unsigned char shmedia_big_nop_pattern[4] = - { - (SHMEDIA_NOP_OPC >> 24) & 255, (SHMEDIA_NOP_OPC >> 16) & 255, - (SHMEDIA_NOP_OPC >> 8) & 255, SHMEDIA_NOP_OPC & 255 - }; - -static const unsigned char shmedia_little_nop_pattern[4] = - { - SHMEDIA_NOP_OPC & 255, (SHMEDIA_NOP_OPC >> 8) & 255, - (SHMEDIA_NOP_OPC >> 16) & 255, (SHMEDIA_NOP_OPC >> 24) & 255 - }; - -static void shmedia_md_begin (void); -static int shmedia_parse_reg (char *, shmedia_arg_type *, int *, - shmedia_arg_type); -static void shmedia_md_assemble (char *); -static void shmedia_md_apply_fix (fixS *, valueT *); -static int shmedia_md_estimate_size_before_relax (fragS *, segT); -static int shmedia_init_reloc (arelent *, fixS *); -static char *shmedia_get_operands (shmedia_opcode_info *, char *, - shmedia_operands_info *); -static void s_sh64_mode (int); -static void s_sh64_abi (int); -static void shmedia_md_convert_frag (bfd *, segT, fragS *, bfd_boolean); -static void shmedia_check_limits (offsetT *, bfd_reloc_code_real_type, - fixS *); -static void sh64_set_contents_type (enum sh64_elf_cr_type); -static void shmedia_get_operand (char **, shmedia_operand_info *, - shmedia_arg_type); -static unsigned long shmedia_immediate_op (char *, shmedia_operand_info *, - int, bfd_reloc_code_real_type); -static char *shmedia_parse_exp (char *, shmedia_operand_info *); -static void shmedia_frob_file_before_adjust (void); -static void sh64_emit_crange (symbolS *, symbolS *, enum sh64_elf_cr_type); -static void sh64_flush_last_crange (bfd *, asection *, void *); -static void sh64_flag_output (void); -static void sh64_update_contents_mark (bfd_boolean); -static void sh64_vtable_entry (int); -static void sh64_vtable_inherit (int); -static char *strip_datalabels (void); -static int shmedia_build_Mytes (shmedia_opcode_info *, - shmedia_operands_info *); -static shmedia_opcode_info *shmedia_find_cooked_opcode (char **); -static unsigned long shmedia_mask_number (unsigned long, - bfd_reloc_code_real_type); - -#include "tc-sh.c" - -void -shmedia_md_end (void) -{ - symbolS *symp; - - /* First, update the last range to include whatever data was last - emitted. */ - sh64_update_contents_mark (TRUE); - - /* Make sure frags generated after this point are not marked with the - wrong ISA; make them easily spottable. We still want to distinguish - it from sh64_isa_unspecified when we compile for SHcompact or - SHmedia. */ - if (sh64_isa_mode != sh64_isa_unspecified) - sh64_isa_mode = sh64_isa_sh5_guard; - - sh64_end_of_assembly = TRUE; - - bfd_map_over_sections (stdoutput, sh64_flush_last_crange, NULL); - - /* Iterate over segments and emit the last .cranges descriptor. */ - for (symp = symbol_rootP; symp != NULL; symp = symp->sy_next) - { - symbolS *mainsym = *symbol_get_tc (symp); - - /* Is this a datalabel symbol; does it have a pointer to the main - symbol? */ - if (mainsym != NULL) - { - /* If the datalabel symbol is undefined, check if the main - symbol has changed in that respect. */ - if (S_GET_SEGMENT (symp) == undefined_section) - { - segT symseg; - - symseg = S_GET_SEGMENT (mainsym); - - /* If the symbol is now defined to something that is not - global and without STO_SH5_ISA32, we just equate the - datalabel symbol to the main symbol, and the lack of - STO_SH5_ISA32 will handle the datalabelness. */ - if (symseg != undefined_section) - { - if (S_GET_OTHER (mainsym) != STO_SH5_ISA32) - { - symp->sy_value.X_op = O_symbol; - symp->sy_value.X_add_symbol = mainsym; - symp->sy_value.X_op_symbol = NULL; - symp->sy_value.X_add_number = 0; - S_SET_SEGMENT (symp, S_GET_SEGMENT (mainsym)); - symbol_set_frag (symp, &zero_address_frag); - copy_symbol_attributes (symp, mainsym); - } - else - { - /* An undefined symbol has since we saw it at - "datalabel", been defined to a BranchTarget - symbol. What we need to do here is very similar - to when we find the "datalabel" for a defined - symbol. FIXME: Break out to common function. */ - symbol_set_value_expression (symp, - symbol_get_value_expression - (mainsym)); - S_SET_SEGMENT (symp, symseg); - symbol_set_frag (symp, symbol_get_frag (mainsym)); - copy_symbol_attributes (symp, mainsym); - - /* Unset the BranchTarget mark that can be set at - attribute-copying. */ - S_SET_OTHER (symp, - S_GET_OTHER (symp) & ~STO_SH5_ISA32); - - /* The GLOBAL and WEAK attributes are not copied - over by copy_symbol_attributes. Do it here. */ - if (S_IS_WEAK (mainsym)) - S_SET_WEAK (symp); - else if (S_IS_EXTERNAL (mainsym)) - S_SET_EXTERNAL (symp); - } - } - else - { - /* A symbol that was defined at the time we saw - "datalabel" can since have been attributed with being - weak or global. */ - if (S_IS_WEAK (mainsym)) - S_SET_WEAK (symp); - else if (S_IS_EXTERNAL (mainsym)) - S_SET_EXTERNAL (symp); - } - } - } - } - - for (symp = symbol_rootP; symp != NULL; symp = symp->sy_next) - if (S_GET_OTHER (symp) & STO_SH5_ISA32) - symp->sy_value.X_add_number++; -} - -/* When resolving symbols, the main assembler has done us a misfavour. It - has removed the equation to the main symbol for a datalabel reference - that should be equal to the main symbol, e.g. when it's a global or - weak symbol and is a non-BranchTarget symbol anyway. We change that - back, so that relocs are against the main symbol, not the local "section - + offset" value. */ - -static void -shmedia_frob_file_before_adjust (void) -{ - symbolS *symp; - for (symp = symbol_rootP; symp != NULL; symp = symp->sy_next) - { - symbolS *mainsym = *symbol_get_tc (symp); - - if (mainsym != NULL - && S_GET_OTHER (mainsym) != STO_SH5_ISA32 - && (S_IS_EXTERNAL (mainsym) || S_IS_WEAK (mainsym))) - { - symp->sy_value.X_op = O_symbol; - symp->sy_value.X_add_symbol = mainsym; - symp->sy_value.X_op_symbol = NULL; - symp->sy_value.X_add_number = 0; - - /* For the "equation trick" to work, we have to set the section - to undefined. */ - S_SET_SEGMENT (symp, undefined_section); - symbol_set_frag (symp, &zero_address_frag); - copy_symbol_attributes (symp, mainsym); - - /* Don't forget to remove the STO_SH5_ISA32 attribute after - copying the other attributes. */ - S_SET_OTHER (symp, S_GET_OTHER (symp) & ~STO_SH5_ISA32); - } - } -} - -/* We need to mark the current location after the alignment. This is - copied code the caller, do_align. We mark the frag location before and - after as we need and arrange to skip the same code in do_align. - - An alternative to code duplication is to call the do_align recursively, - arranging to fall through into do_align if we're already here. That - would require do_align as an incoming function parameter, since it's - static in read.c. That solution was discarded a too kludgy. */ - -void -sh64_do_align (int n, const char *fill, int len, int max) -{ - /* Update region, or put a data region in front. */ - sh64_update_contents_mark (TRUE); - - /* Only make a frag if we HAVE to... */ - if (n != 0 && !need_pass_2) - { - if (fill == NULL) - { - if (subseg_text_p (now_seg)) - frag_align_code (n, max); - else - frag_align (n, 0, max); - } - else if (len <= 1) - frag_align (n, *fill, max); - else - frag_align_pattern (n, fill, len, max); - } - - /* Update mark for current region with current type. */ - sh64_update_contents_mark (FALSE); -} - -/* The MAX_MEM_FOR_RS_ALIGN_CODE worker. We have to find out the ISA of - the current segment at this position. We can't look just at - sh64_isa_shmedia, and we can't look at frag_now. This is brittle: - callers are currently frag_align_code from subsegs_finish in write.c - (end of assembly) and frag_align_code from do_align in read.c (during - assembly). */ - -int -sh64_max_mem_for_rs_align_code (void) -{ - segment_info_type *seginfo; - fragS *mode_start_frag; - seginfo = seg_info (now_seg); - - /* We don't use the contents type we find at the tc_segment_info_data, - since that does not give us absolute information about the ISA; the - contents type can presumably be CRT_DATA and we'd be none the wiser. - Instead we use the information stored at the frag of the symbol at - the start of this range. If any information is missing or NULL, - assume SHcompact. */ - return - /* If the current ISA mode is SHmedia, that's the mode that we're - going to assign to the new frag, so request enough memory for - it, even if we switch modes afterwards, otherwise we may - allocate too little memory and end up overflowing our buffer. */ - (sh64_isa_mode == sh64_isa_shmedia - || (sh64_isa_mode != sh64_isa_unspecified - && seginfo != NULL - && seginfo->tc_segment_info_data.mode_start_symbol != NULL - && ((mode_start_frag - = (symbol_get_frag - (seginfo->tc_segment_info_data.mode_start_symbol))) - != NULL) - && mode_start_frag->tc_frag_data.isa == sh64_isa_shmedia)) - ? (3 + 4) : (2 + 1); -} - -/* Put in SHmedia NOP:s if the alignment was created when in SHmedia mode. */ - -void -sh64_handle_align (fragS * frag) -{ - int bytes = frag->fr_next->fr_address - frag->fr_address - frag->fr_fix; - char * p = frag->fr_literal + frag->fr_fix; - - if (frag->tc_frag_data.isa == sh64_isa_shmedia - && frag->fr_type == rs_align_code) - { - while (bytes & 3) - { - *p++ = 0; - bytes--; - frag->fr_fix += 1; - } - - if (target_big_endian) - { - memcpy (p, shmedia_big_nop_pattern, - sizeof shmedia_big_nop_pattern); - frag->fr_var = sizeof shmedia_big_nop_pattern; - } - else - { - memcpy (p, shmedia_little_nop_pattern, - sizeof shmedia_little_nop_pattern); - frag->fr_var = sizeof shmedia_little_nop_pattern; - } - } - else - /* Punt to SHcompact function. */ - sh_handle_align (frag); -} - -/* Set SEC_SH64_ISA32 for SHmedia sections. */ - -void -shmedia_frob_section_type (asection *sec) -{ - segment_info_type *seginfo; - seginfo = seg_info (sec); - - /* This and elf32-sh64.c:sh64_elf_fake_sections are the only places - where we use anything else than ELF header flags to communicate the - section as containing SHmedia or other contents. BFD SEC_* section - flags are running out and should not be overloaded with - target-specific semantics. This target is ELF only (semantics not - defined for other formats), so we use the target-specific pointer - field of the ELF section data. */ - if (seginfo && sh64_abi == sh64_abi_32) - { - struct sh64_section_data *sec_elf_data; - flagword sec_type = 0; - - if (seginfo->tc_segment_info_data.emitted_ranges != 0) - sec_type = SHF_SH5_ISA32_MIXED; - else if (seginfo->tc_segment_info_data.contents_type == CRT_SH5_ISA32) - sec_type = SHF_SH5_ISA32; - - sec_elf_data = sh64_elf_section_data (sec)->sh64_info; - if (sec_elf_data == NULL) - { - sec_elf_data = XCNEW (struct sh64_section_data); - sh64_elf_section_data (sec)->sh64_info = sec_elf_data; - } - - sec_elf_data->contents_flags = sec_type; - } -} - -/* This function is called by write_object_file right before the symbol - table is written. We subtract 1 from all symbols marked STO_SH5_ISA32, - as their values are temporarily incremented in shmedia_md_end, before - symbols values are used by relocs and fixups. - - To increment all symbols and then decrement here is admittedly a - hackish solution. The alternative is to add infrastructure and hooks - to symbol evaluation that evaluates symbols differently internally to - the value output into the object file, but at the moment that just - seems too much for little benefit. */ - -void -sh64_adjust_symtab (void) -{ - symbolS *symp; - - for (symp = symbol_rootP; symp; symp = symbol_next (symp)) - { - symbolS *main_symbol = *symbol_get_tc (symp); - - if (main_symbol) - { - char *sym_name = (char *) S_GET_NAME (symp); - - /* All datalabels not used in relocs should be gone by now. - - We change those remaining to have the name of the main - symbol, and we set the ELF type of the symbol of the reloc to - STT_DATALABEL. */ - sym_name[strlen (sym_name) - strlen (DATALABEL_SUFFIX)] = 0; - elf_symbol (symbol_get_bfdsym (symp))->internal_elf_sym.st_info - = STT_DATALABEL; - - /* Also set this symbol to "undefined", so we'll have only one - definition. */ - S_SET_SEGMENT (symp, undefined_section); - } - else if (S_GET_OTHER (symp) & STO_SH5_ISA32) - { - /* It's important to change the BFD symbol value, since it is now - set to the GAS symbolS value. */ - symp->bsym->value--; - - /* Note that we do *not* adjust symp->sy_value.X_add_number. If - you do this, the test case in sh/sh64/immexpr2.s will fail. - This is because *after* symbols have been output but before - relocs are output, fixups are inspected one more time, and - some leftover expressions are resolved. To resolve to the - same values, those expressions must have the same GAS symbol - values before as after symbols have been output. We could - "symp->sy_value.X_add_number++" on the STO_SH5_ISA32 symbols - through tc_frob_file after symbols have been output, but that - would be too gross. */ - } - } -} - -/* Fill-in an allocated arelent. */ - -static int -shmedia_init_reloc (arelent *rel, fixS *fixP) -{ - /* Adjust parts of *relp according to *fixp, and tell that it has been - done, so default initializations will not happen. */ - switch (fixP->fx_r_type) - { - case BFD_RELOC_64: - case BFD_RELOC_64_PCREL: - case BFD_RELOC_SH_IMM_LOW16: - case BFD_RELOC_SH_IMM_MEDLOW16: - case BFD_RELOC_SH_IMM_MEDHI16: - case BFD_RELOC_SH_IMM_HI16: - case BFD_RELOC_SH_IMM_LOW16_PCREL: - case BFD_RELOC_SH_IMM_MEDLOW16_PCREL: - case BFD_RELOC_SH_IMM_MEDHI16_PCREL: - case BFD_RELOC_SH_IMM_HI16_PCREL: - case BFD_RELOC_SH_IMMU5: - case BFD_RELOC_SH_IMMU6: - case BFD_RELOC_SH_IMMS6: - case BFD_RELOC_SH_IMMS10: - case BFD_RELOC_SH_IMMS10BY2: - case BFD_RELOC_SH_IMMS10BY4: - case BFD_RELOC_SH_IMMS10BY8: - case BFD_RELOC_SH_IMMS16: - case BFD_RELOC_SH_IMMU16: - case BFD_RELOC_SH_PT_16: - case BFD_RELOC_SH_GOT_LOW16: - case BFD_RELOC_SH_GOT_MEDLOW16: - case BFD_RELOC_SH_GOT_MEDHI16: - case BFD_RELOC_SH_GOT_HI16: - case BFD_RELOC_SH_GOT10BY4: - case BFD_RELOC_SH_GOT10BY8: - case BFD_RELOC_SH_GOTPLT_LOW16: - case BFD_RELOC_SH_GOTPLT_MEDLOW16: - case BFD_RELOC_SH_GOTPLT_MEDHI16: - case BFD_RELOC_SH_GOTPLT_HI16: - case BFD_RELOC_SH_GOTPLT10BY4: - case BFD_RELOC_SH_GOTPLT10BY8: - case BFD_RELOC_SH_GOTOFF_LOW16: - case BFD_RELOC_SH_GOTOFF_MEDLOW16: - case BFD_RELOC_SH_GOTOFF_MEDHI16: - case BFD_RELOC_SH_GOTOFF_HI16: - case BFD_RELOC_SH_GOTPC_LOW16: - case BFD_RELOC_SH_GOTPC_MEDLOW16: - case BFD_RELOC_SH_GOTPC_MEDHI16: - case BFD_RELOC_SH_GOTPC_HI16: - case BFD_RELOC_SH_PLT_LOW16: - case BFD_RELOC_SH_PLT_MEDLOW16: - case BFD_RELOC_SH_PLT_MEDHI16: - case BFD_RELOC_SH_PLT_HI16: - rel->addend = fixP->fx_addnumber + fixP->fx_offset; - return 1; - - case BFD_RELOC_SH_IMMS6BY32: - /* This must be resolved in assembly; we do not support it as a - reloc in an object file. */ - as_bad_where (fixP->fx_file, fixP->fx_line, - _("This operand must be constant at assembly time")); - break; - - /* There are valid cases where we get here for other than SHmedia - relocs, so don't make a BAD_CASE out of this. */ - default: - ; - } - - return 0; -} - -/* Hook called from md_apply_fix in tc-sh.c. */ - -static void -shmedia_md_apply_fix (fixS *fixP, valueT *valp) -{ - offsetT val = *valp; - char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; - unsigned long insn - = target_big_endian ? bfd_getb32 (buf) : bfd_getl32 (buf); - bfd_reloc_code_real_type orig_fx_r_type = fixP->fx_r_type; - - /* Change a 64-bit pc-relative reloc into the correct type, just like - tc-sh.c:md_apply_fix. */ - if (fixP->fx_pcrel) - { - switch (orig_fx_r_type) - { - case BFD_RELOC_64: - case BFD_RELOC_SH_IMM_LOW16: - case BFD_RELOC_SH_IMM_MEDLOW16: - case BFD_RELOC_SH_IMM_MEDHI16: - case BFD_RELOC_SH_IMM_HI16: - /* Because write.c calls MD_PCREL_FROM_SECTION twice, we need to - undo one of the adjustments, if the relocation is not - actually for a symbol within the same segment (which we - cannot check, because we're not called from md_apply_fix, so - we have to keep the reloc). FIXME: This is a bug in - write.c:fixup_segment affecting most targets that change - ordinary relocs to pcrel relocs in md_apply_fix. */ - fixP->fx_offset - = *valp + SHMEDIA_MD_PCREL_FROM_FIX (fixP); - break; - - case BFD_RELOC_SH_PLT_LOW16: - case BFD_RELOC_SH_PLT_MEDLOW16: - case BFD_RELOC_SH_PLT_MEDHI16: - case BFD_RELOC_SH_PLT_HI16: - case BFD_RELOC_SH_GOTPC_LOW16: - case BFD_RELOC_SH_GOTPC_MEDLOW16: - case BFD_RELOC_SH_GOTPC_MEDHI16: - case BFD_RELOC_SH_GOTPC_HI16: - *valp = 0; - return; - - default: - ; - } - - /* We might need to change some relocs into the corresponding - PC-relative one. */ - switch (orig_fx_r_type) - { - case BFD_RELOC_64: - fixP->fx_r_type = BFD_RELOC_64_PCREL; - break; - - case BFD_RELOC_SH_IMM_LOW16: - fixP->fx_r_type = BFD_RELOC_SH_IMM_LOW16_PCREL; - break; - - case BFD_RELOC_SH_IMM_MEDLOW16: - fixP->fx_r_type = BFD_RELOC_SH_IMM_MEDLOW16_PCREL; - break; - - case BFD_RELOC_SH_IMM_MEDHI16: - fixP->fx_r_type = BFD_RELOC_SH_IMM_MEDHI16_PCREL; - break; - - case BFD_RELOC_SH_IMM_HI16: - fixP->fx_r_type = BFD_RELOC_SH_IMM_HI16_PCREL; - break; - - case SHMEDIA_BFD_RELOC_PT: - /* This is how we see a difference between PT and PTA when not - expanding (in which case we handle it in - shmedia_md_convert_frag). Note that we don't see a - difference after the reloc is emitted. */ - fixP->fx_r_type = BFD_RELOC_SH_PT_16; - break; - - case BFD_RELOC_SH_PT_16: - /* This tells us there was a PTA or PTB insn explicitly - expressed as such (not as PT). We "or" in a 1 into the - lowest bit in the (unused) destination field to tell the - linker that it should check the right ISA type of the - destination and not just change a PTA to PTB (if necessary). */ - md_number_to_chars (buf, insn | (1 << 10), 4); - break; - - case BFD_RELOC_64_PCREL: - case BFD_RELOC_SH_IMM_LOW16_PCREL: - case BFD_RELOC_SH_IMM_MEDLOW16_PCREL: - case BFD_RELOC_SH_IMM_MEDHI16_PCREL: - case BFD_RELOC_SH_IMM_HI16_PCREL: - /* Already handled. */ - break; - - default: - /* Everything else that changes into a pc-relative relocation is - an error. */ - as_bad_where (fixP->fx_file, fixP->fx_line, - _("Invalid operand expression")); - break; - } - - return; - } - - /* If an expression looked like it was PC-relative, but was completely - resolvable, we end up here with the result only in *VALP, and no - relocation will be emitted. */ - if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0) - { - /* Emit error for an out-of-range value. */ - shmedia_check_limits ((offsetT *) valp, fixP->fx_r_type, fixP); - - switch (fixP->fx_r_type) - { - case BFD_RELOC_SH_IMM_LOW16: - md_number_to_chars (buf, insn | ((val & 65535) << 10), 4); - break; - - case BFD_RELOC_SH_IMM_MEDLOW16: - md_number_to_chars (buf, - insn - | ((valueT) (val & ((valueT) 65535 << 16)) - >> (16 - 10)), 4); - break; - - case BFD_RELOC_SH_IMM_MEDHI16: - md_number_to_chars (buf, - insn - | ((valueT) (val & ((valueT) 65535 << 32)) - >> (32 - 10)), 4); - break; - - case BFD_RELOC_SH_IMM_HI16: - md_number_to_chars (buf, - insn - | ((valueT) (val & ((valueT) 65535 << 48)) - >> (48 - 10)), 4); - break; - - case BFD_RELOC_SH_IMMS16: - case BFD_RELOC_SH_IMMU16: - md_number_to_chars (buf, insn | ((val & 65535) << 10), 4); - break; - - case BFD_RELOC_SH_IMMS10: - md_number_to_chars (buf, insn | ((val & 0x3ff) << 10), 4); - break; - - case BFD_RELOC_SH_IMMS10BY2: - md_number_to_chars (buf, - insn | ((val & (0x3ff << 1)) << (10 - 1)), 4); - break; - - case BFD_RELOC_SH_IMMS10BY4: - md_number_to_chars (buf, - insn | ((val & (0x3ff << 2)) << (10 - 2)), 4); - break; - - case BFD_RELOC_SH_IMMS10BY8: - md_number_to_chars (buf, - insn | ((val & (0x3ff << 3)) << (10 - 3)), 4); - break; - - case BFD_RELOC_SH_SHMEDIA_CODE: - /* We just ignore and remove this one for the moment. FIXME: - Use it when implementing relaxing. */ - break; - - case BFD_RELOC_64: - md_number_to_chars (buf, val, 8); - break; - - case SHMEDIA_BFD_RELOC_PT: - /* Change a PT to PTB if the operand turned out to be SHcompact. - The basic opcode specified with PT is equivalent to PTA. */ - if ((val & 1) == 0) - insn |= SHMEDIA_PTB_BIT; - /* Fall through. */ - - case BFD_RELOC_SH_PT_16: - if (! sh64_expand || sh_relax) - { - /* Check if the operand of a PTA or PTB was for the "wrong" - ISA. A PT had an incoming fixup of SHMEDIA_BFD_RELOC_PT, - which we have changed to the right type above. */ - if (orig_fx_r_type != SHMEDIA_BFD_RELOC_PT) - { - if ((insn & SHMEDIA_PTB_BIT) != 0 && (val & 1) != 0) - as_bad_where (fixP->fx_file, fixP->fx_line, - _("PTB operand is a SHmedia symbol")); - else if ((insn & SHMEDIA_PTB_BIT) == 0 && (val & 1) == 0) - as_bad_where (fixP->fx_file, fixP->fx_line, - _("PTA operand is a SHcompact symbol")); - } - - md_number_to_chars (buf, - insn | ((val & (0xffff << 2)) - << (10 - 2)), - 4); - break; - } - /* Fall through. */ - - default: - /* This isn't a BAD_CASE, because presumably we can get here - from unexpected operands. Since we don't handle them, make - them syntax errors. */ - as_bad_where (fixP->fx_file, fixP->fx_line, - _("invalid expression in operand")); - } - fixP->fx_done = 1; - } -} - -/* Hook called from md_convert_frag in tc-sh.c. */ - -static void -shmedia_md_convert_frag (bfd *output_bfd ATTRIBUTE_UNUSED, - segT seg ATTRIBUTE_UNUSED, fragS *fragP, - bfd_boolean final) -{ - /* Pointer to first byte in variable-sized part of the frag. */ - char *var_partp; - - /* Pointer to first opcode byte in frag. */ - char *opcodep; - - /* Pointer to frag of opcode. */ - fragS *opc_fragP = fragP->tc_frag_data.opc_frag; - - /* Size in bytes of variable-sized part of frag. */ - int var_part_size = 0; - - /* This is part of *fragP. It contains all information about addresses - and offsets to varying parts. */ - symbolS *symbolP = fragP->fr_symbol; - - bfd_boolean reloc_needed - = (! final - || sh_relax - || symbolP == NULL - || ! S_IS_DEFINED (symbolP) - || S_IS_EXTERNAL (symbolP) - || S_IS_WEAK (symbolP) - || (S_GET_SEGMENT (fragP->fr_symbol) != absolute_section - && S_GET_SEGMENT (fragP->fr_symbol) != seg)); - - bfd_reloc_code_real_type reloctype = BFD_RELOC_NONE; - - unsigned long var_part_offset; - - /* Where, in file space, does addr point? */ - bfd_vma target_address; - bfd_vma opcode_address; - - /* What was the insn? */ - unsigned long insn; - know (fragP->fr_type == rs_machine_dependent); - - var_part_offset = fragP->fr_fix; - var_partp = fragP->fr_literal + var_part_offset; - opcodep = fragP->fr_opcode; - - insn = target_big_endian ? bfd_getb32 (opcodep) : bfd_getl32 (opcodep); - - target_address - = ((symbolP && final && ! sh_relax ? S_GET_VALUE (symbolP) : 0) - + fragP->fr_offset); - - /* The opcode that would be extended is the last four "fixed" bytes. */ - opcode_address = fragP->fr_address + fragP->fr_fix - 4; - - switch (fragP->fr_subtype) - { - case C (SH64PCREL16PT_64, SH64PCREL16): - case C (SH64PCREL16PT_32, SH64PCREL16): - /* We can get a PT to a relaxed SHcompact address if it is in the - same section; a mixed-ISA section. Change the opcode to PTB if - so. */ - if ((target_address & 1) == 0) - insn |= SHMEDIA_PTB_BIT; - /* Fall through. */ - - case C (SH64PCREL16_32, SH64PCREL16): - case C (SH64PCREL16_64, SH64PCREL16): - /* Check that a PTA or PTB points to the right type of target. We - can get here for a SHcompact target if we are in a mixed-ISA - section. */ - if (((target_address & 1) == 0) && ((insn & SHMEDIA_PTB_BIT) == 0)) - as_bad_where (fragP->fr_file, fragP->fr_line, - _("PTA operand is a SHcompact symbol")); - if (((target_address & 1) != 0) && ((insn & SHMEDIA_PTB_BIT) != 0)) - as_bad_where (fragP->fr_file, fragP->fr_line, - _("PTB operand is a SHmedia symbol")); - - /* When relaxing, we do not output the address in the insn, but - instead a 1 into the low bit. This matches what the linker - expects to find for a BFD_RELOC_SH_PT_16 reloc, when it checks - correctness for PTA/PTB insn; used when the target address is - unknown (which is not the case here). */ - md_number_to_chars (opcodep, - insn - | (((sh_relax - ? 1 : ((target_address - opcode_address) / 4)) - & ((1 << 16) - 1)) << 10), - 4); - - /* Note that we do not emit info that this was originally a PT since - we have resolved to which one of PTA or PTB it will be. */ - if (sh_relax) - fix_new (opc_fragP, opcodep - opc_fragP->fr_literal, 4, - fragP->fr_symbol, fragP->fr_offset, 1, BFD_RELOC_SH_PT_16); - var_part_size = 0; - break; - - case C (SH64PCREL16_32, SH64PCRELPLT): - case C (SH64PCREL16PT_32, SH64PCRELPLT): - reloctype = BFD_RELOC_32_PLT_PCREL; - reloc_needed = 1; - /* Fall through */ - - case C (SH64PCREL16_32, SH64PCREL32): - case C (SH64PCREL16_64, SH64PCREL32): - case C (SH64PCREL16PT_32, SH64PCREL32): - case C (SH64PCREL16PT_64, SH64PCREL32): - /* In the fixed bit, put in a MOVI. */ - md_number_to_chars (opcodep, - SHMEDIA_MOVI_OPC - | (SHMEDIA_TEMP_REG << 4) - | ((((reloc_needed - ? 0 : (target_address - (opcode_address + 8)) - ) >> 16) & 65535) << 10), - 4); - - /* Fill in a SHORI for the low part. */ - md_number_to_chars (var_partp, - SHMEDIA_SHORI_OPC - | (SHMEDIA_TEMP_REG << 4) - | (((reloc_needed - ? 0 : (target_address - (opcode_address + 8))) - & 65535) << 10), - 4); - - /* End with a "PTREL R25,TRd". */ - md_number_to_chars (var_partp + 4, - SHMEDIA_PTREL_OPC | (insn & SHMEDIA_LIKELY_BIT) - | (SHMEDIA_TEMP_REG << 10) - | (insn & (7 << 4)), - 4); - - /* We need relocs only if the target symbol was undefined or if - we're relaxing. */ - if (reloc_needed) - { - fix_new (opc_fragP, opcodep - opc_fragP->fr_literal, 4, - fragP->fr_symbol, fragP->fr_offset - 8, 1, - reloctype == BFD_RELOC_32_PLT_PCREL - ? BFD_RELOC_SH_PLT_MEDLOW16 - : BFD_RELOC_SH_IMM_MEDLOW16_PCREL); - fix_new (fragP, var_partp - fragP->fr_literal, 4, fragP->fr_symbol, - fragP->fr_offset - 4, 1, - reloctype == BFD_RELOC_32_PLT_PCREL - ? BFD_RELOC_SH_PLT_LOW16 - : BFD_RELOC_SH_IMM_LOW16_PCREL); - } - - var_part_size = 8; - break; - - case C (SH64PCREL16_64, SH64PCREL48): - case C (SH64PCREL16PT_64, SH64PCREL48): - /* In the fixed bit, put in a MOVI. */ - md_number_to_chars (opcodep, - SHMEDIA_MOVI_OPC - | (SHMEDIA_TEMP_REG << 4) - | ((((reloc_needed - ? 0 : (target_address - (opcode_address + 12)) - ) >> 32) & 65535) << 10), - 4); - - /* The first SHORI, for the medium part. */ - md_number_to_chars (var_partp, - SHMEDIA_SHORI_OPC - | (SHMEDIA_TEMP_REG << 4) - | ((((reloc_needed - ? 0 : (target_address - (opcode_address + 12)) - ) >> 16) & 65535) << 10), - 4); - - /* Fill in a SHORI for the low part. */ - md_number_to_chars (var_partp + 4, - SHMEDIA_SHORI_OPC - | (SHMEDIA_TEMP_REG << 4) - | (((reloc_needed - ? 0 : (target_address - (opcode_address + 12))) - & 65535) << 10), - 4); - - /* End with a "PTREL R25,TRd". */ - md_number_to_chars (var_partp + 8, - SHMEDIA_PTREL_OPC | (insn & SHMEDIA_LIKELY_BIT) - | (SHMEDIA_TEMP_REG << 10) - | (insn & (7 << 4)), - 4); - - /* We need relocs only if the target symbol was undefined or if - we're relaxing. */ - if (reloc_needed) - { - fix_new (opc_fragP, opcodep - opc_fragP->fr_literal, 4, - fragP->fr_symbol, fragP->fr_offset - 12, 1, - reloctype == BFD_RELOC_32_PLT_PCREL - ? BFD_RELOC_SH_PLT_MEDHI16 - : BFD_RELOC_SH_IMM_MEDHI16_PCREL); - fix_new (fragP, var_partp - fragP->fr_literal, 4, fragP->fr_symbol, - fragP->fr_offset - 8, 1, - reloctype == BFD_RELOC_32_PLT_PCREL - ? BFD_RELOC_SH_PLT_MEDLOW16 - : BFD_RELOC_SH_IMM_MEDLOW16_PCREL); - fix_new (fragP, var_partp - fragP->fr_literal + 4, 4, fragP->fr_symbol, - fragP->fr_offset - 4, 1, - reloctype == BFD_RELOC_32_PLT_PCREL - ? BFD_RELOC_SH_PLT_LOW16 - : BFD_RELOC_SH_IMM_LOW16_PCREL); - } - - var_part_size = 12; - break; - - case C (SH64PCREL16_64, SH64PCRELPLT): - case C (SH64PCREL16PT_64, SH64PCRELPLT): - reloctype = BFD_RELOC_32_PLT_PCREL; - reloc_needed = 1; - /* Fall through */ - - case C (SH64PCREL16_64, SH64PCREL64): - case C (SH64PCREL16PT_64, SH64PCREL64): - /* In the fixed bit, put in a MOVI. */ - md_number_to_chars (opcodep, - SHMEDIA_MOVI_OPC - | (SHMEDIA_TEMP_REG << 4) - | ((((reloc_needed - ? 0 : (target_address - (opcode_address + 16)) - ) >> 48) & 65535) << 10), - 4); - - /* The first SHORI, for the medium-high part. */ - md_number_to_chars (var_partp, - SHMEDIA_SHORI_OPC - | (SHMEDIA_TEMP_REG << 4) - | ((((reloc_needed - ? 0 : (target_address - (opcode_address + 16)) - ) >> 32) & 65535) << 10), - 4); - - /* A SHORI, for the medium-low part. */ - md_number_to_chars (var_partp + 4, - SHMEDIA_SHORI_OPC - | (SHMEDIA_TEMP_REG << 4) - | ((((reloc_needed - ? 0 : (target_address - (opcode_address + 16)) - ) >> 16) & 65535) << 10), - 4); - - /* Fill in a SHORI for the low part. */ - md_number_to_chars (var_partp + 8, - SHMEDIA_SHORI_OPC - | (SHMEDIA_TEMP_REG << 4) - | (((reloc_needed - ? 0 : (target_address - (opcode_address + 16))) - & 65535) << 10), - 4); - - /* End with a "PTREL R25,TRd". */ - md_number_to_chars (var_partp + 12, - SHMEDIA_PTREL_OPC | (insn & SHMEDIA_LIKELY_BIT) - | (SHMEDIA_TEMP_REG << 10) - | (insn & (7 << 4)), - 4); - - /* We need relocs only if the target symbol was undefined or if - we're relaxing. */ - if (reloc_needed) - { - fix_new (opc_fragP, opcodep - opc_fragP->fr_literal, 4, - fragP->fr_symbol, fragP->fr_offset - 16, 1, - reloctype == BFD_RELOC_32_PLT_PCREL - ? BFD_RELOC_SH_PLT_HI16 - : BFD_RELOC_SH_IMM_HI16_PCREL); - fix_new (fragP, var_partp - fragP->fr_literal, 4, fragP->fr_symbol, - fragP->fr_offset - 12, 1, - reloctype == BFD_RELOC_32_PLT_PCREL - ? BFD_RELOC_SH_PLT_MEDHI16 - : BFD_RELOC_SH_IMM_MEDHI16_PCREL); - fix_new (fragP, var_partp - fragP->fr_literal + 4, 4, fragP->fr_symbol, - fragP->fr_offset - 8, 1, - reloctype == BFD_RELOC_32_PLT_PCREL - ? BFD_RELOC_SH_PLT_MEDLOW16 - : BFD_RELOC_SH_IMM_MEDLOW16_PCREL); - fix_new (fragP, var_partp - fragP->fr_literal + 8, 4, fragP->fr_symbol, - fragP->fr_offset - 4, 1, - reloctype == BFD_RELOC_32_PLT_PCREL - ? BFD_RELOC_SH_PLT_LOW16 - : BFD_RELOC_SH_IMM_LOW16_PCREL); - } - - var_part_size = 16; - break; - - case C (MOVI_IMM_64, MOVI_GOTOFF): - reloctype = BFD_RELOC_32_GOTOFF; - reloc_needed = 1; - /* Fall through. */ - - case C (MOVI_IMM_64, UNDEF_MOVI): - case C (MOVI_IMM_64, MOVI_64): - { - /* We only get here for undefined symbols, so we can simplify - handling compared to those above; we have 0 in the parts that - will be filled with the symbol parts. */ - - int reg = (insn >> 4) & 0x3f; - - /* In the fixed bit, put in a MOVI. */ - md_number_to_chars (opcodep, SHMEDIA_MOVI_OPC | (reg << 4), 4); - fix_new (opc_fragP, opcodep - opc_fragP->fr_literal, 4, - fragP->fr_symbol, fragP->fr_offset, 0, - reloctype == BFD_RELOC_NONE - ? BFD_RELOC_SH_IMM_HI16 - : reloctype == BFD_RELOC_32_GOTOFF - ? BFD_RELOC_SH_GOTOFF_HI16 - : (abort (), BFD_RELOC_SH_IMM_HI16)); - - /* The first SHORI, for the medium-high part. */ - md_number_to_chars (var_partp, SHMEDIA_SHORI_OPC | (reg << 4), 4); - fix_new (fragP, var_partp - fragP->fr_literal, 4, fragP->fr_symbol, - fragP->fr_offset, 0, - reloctype == BFD_RELOC_NONE - ? BFD_RELOC_SH_IMM_MEDHI16 - : reloctype == BFD_RELOC_32_GOTOFF - ? BFD_RELOC_SH_GOTOFF_MEDHI16 - : (abort (), BFD_RELOC_SH_IMM_MEDHI16)); - - /* A SHORI, for the medium-low part. */ - md_number_to_chars (var_partp + 4, - SHMEDIA_SHORI_OPC | (reg << 4), 4); - fix_new (fragP, var_partp - fragP->fr_literal + 4, 4, fragP->fr_symbol, - fragP->fr_offset, 0, - reloctype == BFD_RELOC_NONE - ? BFD_RELOC_SH_IMM_MEDLOW16 - : reloctype == BFD_RELOC_32_GOTOFF - ? BFD_RELOC_SH_GOTOFF_MEDLOW16 - : (abort (), BFD_RELOC_SH_IMM_MEDLOW16)); - - /* Fill in a SHORI for the low part. */ - md_number_to_chars (var_partp + 8, - SHMEDIA_SHORI_OPC | (reg << 4), 4); - fix_new (fragP, var_partp - fragP->fr_literal + 8, 4, fragP->fr_symbol, - fragP->fr_offset, 0, - reloctype == BFD_RELOC_NONE - ? BFD_RELOC_SH_IMM_LOW16 - : reloctype == BFD_RELOC_32_GOTOFF - ? BFD_RELOC_SH_GOTOFF_LOW16 - : (abort (), BFD_RELOC_SH_IMM_LOW16)); - - var_part_size = 12; - break; - } - - case C (MOVI_IMM_32, MOVI_GOTOFF): - reloctype = BFD_RELOC_32_GOTOFF; - reloc_needed = 1; - /* Fall through. */ - - case C (MOVI_IMM_32, UNDEF_MOVI): - case C (MOVI_IMM_32, MOVI_32): - { - /* Note that we only get here for undefined symbols. */ - - int reg = (insn >> 4) & 0x3f; - - /* A MOVI, for the high part. */ - md_number_to_chars (opcodep, SHMEDIA_MOVI_OPC | (reg << 4), 4); - fix_new (opc_fragP, opcodep - opc_fragP->fr_literal, 4, - fragP->fr_symbol, fragP->fr_offset, 0, - reloctype == BFD_RELOC_NONE - ? BFD_RELOC_SH_IMM_MEDLOW16 - : reloctype == BFD_RELOC_32_GOTOFF - ? BFD_RELOC_SH_GOTOFF_MEDLOW16 - : reloctype == BFD_RELOC_SH_GOTPC - ? BFD_RELOC_SH_GOTPC_MEDLOW16 - : reloctype == BFD_RELOC_32_PLT_PCREL - ? BFD_RELOC_SH_PLT_MEDLOW16 - : (abort (), BFD_RELOC_SH_IMM_MEDLOW16)); - - /* Fill in a SHORI for the low part. */ - md_number_to_chars (var_partp, - SHMEDIA_SHORI_OPC | (reg << 4), 4); - fix_new (fragP, var_partp - fragP->fr_literal, 4, fragP->fr_symbol, - fragP->fr_offset, 0, - reloctype == BFD_RELOC_NONE - ? BFD_RELOC_SH_IMM_LOW16 - : reloctype == BFD_RELOC_32_GOTOFF - ? BFD_RELOC_SH_GOTOFF_LOW16 - : reloctype == BFD_RELOC_SH_GOTPC - ? BFD_RELOC_SH_GOTPC_LOW16 - : reloctype == BFD_RELOC_32_PLT_PCREL - ? BFD_RELOC_SH_PLT_LOW16 - : (abort (), BFD_RELOC_SH_IMM_LOW16)); - - var_part_size = 4; - break; - } - - case C (MOVI_IMM_32_PCREL, MOVI_16): - case C (MOVI_IMM_64_PCREL, MOVI_16): - md_number_to_chars (opcodep, - insn - | (((reloc_needed - ? 0 : (target_address - opcode_address)) - & 65535) << 10), - 4); - if (reloc_needed) - fix_new (opc_fragP, opcodep - opc_fragP->fr_literal, 4, - fragP->fr_symbol, fragP->fr_offset, 1, - BFD_RELOC_SH_IMM_LOW16_PCREL); - var_part_size = 0; - break; - - case C (MOVI_IMM_32, MOVI_16): - case C (MOVI_IMM_64, MOVI_16): - md_number_to_chars (opcodep, - insn - | (((reloc_needed ? 0 : target_address) - & 65535) << 10), - 4); - if (reloc_needed) - abort (); - var_part_size = 0; - break; - - case C (MOVI_IMM_32_PCREL, MOVI_PLT): - reloctype = BFD_RELOC_32_PLT_PCREL; - goto movi_imm_32_pcrel_reloc_needed; - - case C (MOVI_IMM_32_PCREL, MOVI_GOTPC): - reloctype = BFD_RELOC_SH_GOTPC; - /* Fall through. */ - - movi_imm_32_pcrel_reloc_needed: - reloc_needed = 1; - /* Fall through. */ - - case C (MOVI_IMM_32_PCREL, MOVI_32): - case C (MOVI_IMM_64_PCREL, MOVI_32): - { - int reg = (insn >> 4) & 0x3f; - - md_number_to_chars (opcodep, - insn - | (((((reloc_needed - ? 0 : (target_address - opcode_address))) - >> 16) & 65535) << 10), 4); - - /* A SHORI, for the low part. */ - md_number_to_chars (var_partp, - SHMEDIA_SHORI_OPC - | (reg << 4) - | (((reloc_needed - ? 0 : (target_address - opcode_address)) - & 65535) << 10), 4); - if (reloc_needed) - { - fix_new (opc_fragP, opcodep - opc_fragP->fr_literal, 4, - fragP->fr_symbol, fragP->fr_offset, 1, - reloctype == BFD_RELOC_NONE - ? BFD_RELOC_SH_IMM_MEDLOW16_PCREL - : reloctype == BFD_RELOC_SH_GOTPC - ? BFD_RELOC_SH_GOTPC_MEDLOW16 - : reloctype == BFD_RELOC_32_PLT_PCREL - ? BFD_RELOC_SH_PLT_MEDLOW16 - : (abort (), BFD_RELOC_SH_IMM_MEDLOW16_PCREL)); - fix_new (fragP, var_partp - fragP->fr_literal, 4, fragP->fr_symbol, - fragP->fr_offset + 4, 1, - reloctype == BFD_RELOC_NONE - ? BFD_RELOC_SH_IMM_LOW16_PCREL - : reloctype == BFD_RELOC_SH_GOTPC - ? BFD_RELOC_SH_GOTPC_LOW16 - : reloctype == BFD_RELOC_32_PLT_PCREL - ? BFD_RELOC_SH_PLT_LOW16 - : (abort (), BFD_RELOC_SH_IMM_LOW16_PCREL)); - } - var_part_size = 4; - } - break; - - case C (MOVI_IMM_32_PCREL, MOVI_48): - case C (MOVI_IMM_64_PCREL, MOVI_48): - { - int reg = (insn >> 4) & 0x3f; - - md_number_to_chars (opcodep, - insn - | (((((reloc_needed - ? 0 : (target_address - opcode_address))) - >> 32) & 65535) << 10), 4); - - /* A SHORI, for the medium part. */ - md_number_to_chars (var_partp, - SHMEDIA_SHORI_OPC - | (reg << 4) - | ((((reloc_needed - ? 0 : (target_address - opcode_address)) - >> 16) & 65535) << 10), 4); - - /* A SHORI, for the low part. */ - md_number_to_chars (var_partp + 4, - SHMEDIA_SHORI_OPC - | (reg << 4) - | (((reloc_needed - ? 0 : (target_address - opcode_address)) - & 65535) << 10), 4); - if (reloc_needed) - { - fix_new (opc_fragP, opcodep - opc_fragP->fr_literal, 4, - fragP->fr_symbol, fragP->fr_offset, 1, - BFD_RELOC_SH_IMM_MEDHI16_PCREL); - fix_new (fragP, var_partp - fragP->fr_literal, 4, fragP->fr_symbol, - fragP->fr_offset + 4, 1, BFD_RELOC_SH_IMM_MEDLOW16_PCREL); - fix_new (fragP, var_partp - fragP->fr_literal + 4, 4, fragP->fr_symbol, - fragP->fr_offset + 8, 1, BFD_RELOC_SH_IMM_LOW16_PCREL); - } - var_part_size = 8; - } - break; - - case C (MOVI_IMM_64_PCREL, MOVI_PLT): - reloctype = BFD_RELOC_32_PLT_PCREL; - goto movi_imm_64_pcrel_reloc_needed; - - case C (MOVI_IMM_64_PCREL, MOVI_GOTPC): - reloctype = BFD_RELOC_SH_GOTPC; - /* Fall through. */ - - movi_imm_64_pcrel_reloc_needed: - reloc_needed = 1; - /* Fall through. */ - - case C (MOVI_IMM_32_PCREL, MOVI_64): - case C (MOVI_IMM_64_PCREL, MOVI_64): - { - int reg = (insn >> 4) & 0x3f; - - md_number_to_chars (opcodep, - insn - | (((((reloc_needed - ? 0 : (target_address - opcode_address))) - >> 48) & 65535) << 10), 4); - - /* A SHORI, for the medium-high part. */ - md_number_to_chars (var_partp, - SHMEDIA_SHORI_OPC - | (reg << 4) - | ((((reloc_needed - ? 0 : (target_address - opcode_address)) - >> 32) & 65535) << 10), 4); - - /* A SHORI, for the medium-low part. */ - md_number_to_chars (var_partp + 4, - SHMEDIA_SHORI_OPC - | (reg << 4) - | ((((reloc_needed - ? 0 : (target_address - opcode_address)) - >> 16) & 65535) << 10), 4); - - /* A SHORI, for the low part. */ - md_number_to_chars (var_partp + 8, - SHMEDIA_SHORI_OPC - | (reg << 4) - | (((reloc_needed - ? 0 : (target_address - opcode_address)) - & 65535) << 10), 4); - if (reloc_needed) - { - fix_new (opc_fragP, opcodep - opc_fragP->fr_literal, 4, - fragP->fr_symbol, fragP->fr_offset, 1, - reloctype == BFD_RELOC_NONE - ? BFD_RELOC_SH_IMM_HI16_PCREL - : reloctype == BFD_RELOC_SH_GOTPC - ? BFD_RELOC_SH_GOTPC_HI16 - : reloctype == BFD_RELOC_32_PLT_PCREL - ? BFD_RELOC_SH_PLT_HI16 - : (abort (), BFD_RELOC_SH_IMM_HI16_PCREL)); - fix_new (fragP, var_partp - fragP->fr_literal, 4, fragP->fr_symbol, - fragP->fr_offset + 4, 1, - reloctype == BFD_RELOC_NONE - ? BFD_RELOC_SH_IMM_MEDHI16_PCREL - : reloctype == BFD_RELOC_SH_GOTPC - ? BFD_RELOC_SH_GOTPC_MEDHI16 - : reloctype == BFD_RELOC_32_PLT_PCREL - ? BFD_RELOC_SH_PLT_MEDHI16 - : (abort (), BFD_RELOC_SH_IMM_MEDHI16_PCREL)); - fix_new (fragP, var_partp - fragP->fr_literal + 4, 4, - fragP->fr_symbol, - fragP->fr_offset + 8, 1, - reloctype == BFD_RELOC_NONE - ? BFD_RELOC_SH_IMM_MEDLOW16_PCREL - : reloctype == BFD_RELOC_SH_GOTPC - ? BFD_RELOC_SH_GOTPC_MEDLOW16 - : reloctype == BFD_RELOC_32_PLT_PCREL - ? BFD_RELOC_SH_PLT_MEDLOW16 - : (abort (), BFD_RELOC_SH_IMM_MEDLOW16_PCREL)); - fix_new (fragP, var_partp - fragP->fr_literal + 8, 4, - fragP->fr_symbol, - fragP->fr_offset + 12, 1, - reloctype == BFD_RELOC_NONE - ? BFD_RELOC_SH_IMM_LOW16_PCREL - : reloctype == BFD_RELOC_SH_GOTPC - ? BFD_RELOC_SH_GOTPC_LOW16 - : reloctype == BFD_RELOC_32_PLT_PCREL - ? BFD_RELOC_SH_PLT_LOW16 - : (abort (), BFD_RELOC_SH_IMM_LOW16_PCREL)); - } - var_part_size = 12; - } - break; - - default: - BAD_CASE (fragP->fr_subtype); - } - - fragP->fr_fix += var_part_size; - fragP->fr_var = 0; -} - -/* Mask NUMBER (originating from a signed number) corresponding to the HOW - reloc. */ - -static unsigned long -shmedia_mask_number (unsigned long number, bfd_reloc_code_real_type how) -{ - switch (how) - { - case BFD_RELOC_SH_IMMU5: - number &= (1 << 5) - 1; - break; - - case BFD_RELOC_SH_IMMS6: - case BFD_RELOC_SH_IMMU6: - number &= (1 << 6) - 1; - break; - - case BFD_RELOC_SH_IMMS6BY32: - number = (number & ((1 << (6 + 5)) - 1)) >> 5; - break; - - case BFD_RELOC_SH_IMMS10: - number &= (1 << 10) - 1; - break; - - case BFD_RELOC_SH_IMMS10BY2: - number = (number & ((1 << (10 + 1)) - 1)) >> 1; - break; - - case BFD_RELOC_SH_IMMS10BY4: - number = (number & ((1 << (10 + 2)) - 1)) >> 2; - break; - - case BFD_RELOC_SH_IMMS10BY8: - number = (number & ((1 << (10 + 3)) - 1)) >> 3; - break; - - case BFD_RELOC_SH_IMMS16: - case BFD_RELOC_SH_IMMU16: - number &= (1 << 16) - 1; - break; - - default: - BAD_CASE (how); - } - - return number; -} - -/* Emit errors for values out-of-range, using as_bad_where if FRAGP is - non-NULL, as_bad otherwise. */ - -static void -shmedia_check_limits (offsetT *valp, bfd_reloc_code_real_type reloc, - fixS *fixp) -{ - offsetT val = *valp; - - const char *msg = NULL; - - switch (reloc) - { - case BFD_RELOC_SH_IMMU5: - if (val < 0 || val > (1 << 5) - 1) - msg = _("invalid operand, not a 5-bit unsigned value: %d"); - break; - - case BFD_RELOC_SH_IMMS6: - if (val < -(1 << 5) || val > (1 << 5) - 1) - msg = _("invalid operand, not a 6-bit signed value: %d"); - break; - - case BFD_RELOC_SH_IMMU6: - if (val < 0 || val > (1 << 6) - 1) - msg = _("invalid operand, not a 6-bit unsigned value: %d"); - break; - - case BFD_RELOC_SH_IMMS6BY32: - if (val < -(1 << 10) || val > (1 << 10) - 1) - msg = _("invalid operand, not a 11-bit signed value: %d"); - else if (val & 31) - msg = _("invalid operand, not a multiple of 32: %d"); - break; - - case BFD_RELOC_SH_IMMS10: - if (val < -(1 << 9) || val > (1 << 9) - 1) - msg = _("invalid operand, not a 10-bit signed value: %d"); - break; - - case BFD_RELOC_SH_IMMS10BY2: - if (val < -(1 << 10) || val > (1 << 10) - 1) - msg = _("invalid operand, not a 11-bit signed value: %d"); - else if (val & 1) - msg = _("invalid operand, not an even value: %d"); - break; - - case BFD_RELOC_SH_IMMS10BY4: - if (val < -(1 << 11) || val > (1 << 11) - 1) - msg = _("invalid operand, not a 12-bit signed value: %d"); - else if (val & 3) - msg = _("invalid operand, not a multiple of 4: %d"); - break; - - case BFD_RELOC_SH_IMMS10BY8: - if (val < -(1 << 12) || val > (1 << 12) - 1) - msg = _("invalid operand, not a 13-bit signed value: %d"); - else if (val & 7) - msg = _("invalid operand, not a multiple of 8: %d"); - break; - - case BFD_RELOC_SH_IMMS16: - if (val < -(1 << 15) || val > (1 << 15) - 1) - msg = _("invalid operand, not a 16-bit signed value: %d"); - break; - - case BFD_RELOC_SH_IMMU16: - if (val < 0 || val > (1 << 16) - 1) - msg = _("invalid operand, not a 16-bit unsigned value: %d"); - break; - - case BFD_RELOC_SH_PT_16: - case SHMEDIA_BFD_RELOC_PT: - if (val < -(1 << 15) * 4 || val > ((1 << 15) - 1) * 4 + 1) - msg = _("operand out of range for PT, PTA and PTB"); - else if ((val % 4) != 0 && ((val - 1) % 4) != 0) - msg = _("operand not a multiple of 4 for PT, PTA or PTB: %d"); - break; - - /* These have no limits; they take a 16-bit slice of a 32- or 64-bit - number. */ - case BFD_RELOC_SH_IMM_HI16: - case BFD_RELOC_SH_IMM_MEDHI16: - case BFD_RELOC_SH_IMM_MEDLOW16: - case BFD_RELOC_SH_IMM_LOW16: - case BFD_RELOC_SH_IMM_HI16_PCREL: - case BFD_RELOC_SH_IMM_MEDHI16_PCREL: - case BFD_RELOC_SH_IMM_MEDLOW16_PCREL: - case BFD_RELOC_SH_IMM_LOW16_PCREL: - - case BFD_RELOC_SH_SHMEDIA_CODE: - break; - - /* This one has limits out of our reach. */ - case BFD_RELOC_64: - break; - - default: - BAD_CASE (reloc); - } - - if (msg) - { - if (fixp) - as_bad_where (fixp->fx_file, fixp->fx_line, msg, val); - else - as_bad (msg, val); - } -} - -/* Handle an immediate operand by checking limits and noting it for later - evaluation if not computable yet, and return a bitfield suitable to - "or" into the opcode (non-zero if the value was a constant number). */ - -static unsigned long -shmedia_immediate_op (char *where, shmedia_operand_info *op, int pcrel, - bfd_reloc_code_real_type how) -{ - unsigned long retval = 0; - - /* If this is not an absolute number, make it a fixup. A constant in - place of a pc-relative operand also needs a fixup. */ - if (op->immediate.X_op != O_constant || pcrel) - fix_new_exp (frag_now, - where - frag_now->fr_literal, - 4, - &op->immediate, - pcrel, - how); - else - { - /* Check that the number is within limits as represented by the - reloc, and return the number. */ - shmedia_check_limits (&op->immediate.X_add_number, how, NULL); - - retval - = shmedia_mask_number ((unsigned long) op->immediate.X_add_number, - how); - } - - return retval << 10; -} - -/* Try and parse a register name case-insensitively, return the number of - chars consumed. */ - -static int -shmedia_parse_reg (char *src, shmedia_arg_type *mode, int *reg, - shmedia_arg_type argtype) -{ - int l0 = TOLOWER (src[0]); - int l1 = l0 ? TOLOWER (src[1]) : 0; - - if (l0 == 'r') - { - if (src[1] >= '1' && src[1] <= '5') - { - if (src[2] >= '0' && src[2] <= '9' - && ! IDENT_CHAR ((unsigned char) src[3])) - { - *mode = A_GREG_M; - *reg = 10 * (src[1] - '0') + src[2] - '0'; - return 3; - } - } - - if (src[1] == '6') - { - if (src[2] >= '0' && src[2] <= '3' - && ! IDENT_CHAR ((unsigned char) src[3])) - { - *mode = A_GREG_M; - *reg = 60 + src[2] - '0'; - return 3; - } - } - - if (src[1] >= '0' && src[1] <= '9' - && ! IDENT_CHAR ((unsigned char) src[2])) - { - *mode = A_GREG_M; - *reg = (src[1] - '0'); - return 2; - } - } - - if (l0 == 't' && l1 == 'r') - { - if (src[2] >= '0' && src[2] <= '7' - && ! IDENT_CHAR ((unsigned char) src[3])) - { - *mode = A_TREG_B; - *reg = (src[2] - '0'); - return 3; - } - } - - if (l0 == 'f' && l1 == 'r') - { - if (src[2] >= '1' && src[2] <= '5') - { - if (src[3] >= '0' && src[3] <= '9' - && ! IDENT_CHAR ((unsigned char) src[4])) - { - *mode = A_FREG_G; - *reg = 10 * (src[2] - '0') + src[3] - '0'; - return 4; - } - } - if (src[2] == '6') - { - if (src[3] >= '0' && src[3] <= '3' - && ! IDENT_CHAR ((unsigned char) src[4])) - { - *mode = A_FREG_G; - *reg = 60 + src[3] - '0'; - return 4; - } - } - if (src[2] >= '0' && src[2] <= '9' - && ! IDENT_CHAR ((unsigned char) src[3])) - { - *mode = A_FREG_G; - *reg = (src[2] - '0'); - return 3; - } - } - - if (l0 == 'f' && l1 == 'v') - { - if (src[2] >= '1' && src[2] <= '5') - { - if (src[3] >= '0' && src[3] <= '9' - && ((10 * (src[2] - '0') + src[3] - '0') % 4) == 0 - && ! IDENT_CHAR ((unsigned char) src[4])) - { - *mode = A_FVREG_G; - *reg = 10 * (src[2] - '0') + src[3] - '0'; - return 4; - } - } - if (src[2] == '6') - { - if (src[3] == '0' - && ! IDENT_CHAR ((unsigned char) src[4])) - { - *mode = A_FVREG_G; - *reg = 60 + src[3] - '0'; - return 4; - } - } - if (src[2] >= '0' && src[2] <= '9' - && ((src[2] - '0') % 4) == 0 - && ! IDENT_CHAR ((unsigned char) src[3])) - { - *mode = A_FVREG_G; - *reg = (src[2] - '0'); - return 3; - } - } - - if (l0 == 'd' && l1 == 'r') - { - if (src[2] >= '1' && src[2] <= '5') - { - if (src[3] >= '0' && src[3] <= '9' - && ((src[3] - '0') % 2) == 0 - && ! IDENT_CHAR ((unsigned char) src[4])) - { - *mode = A_DREG_G; - *reg = 10 * (src[2] - '0') + src[3] - '0'; - return 4; - } - } - - if (src[2] == '6') - { - if ((src[3] == '0' || src[3] == '2') - && ! IDENT_CHAR ((unsigned char) src[4])) - { - *mode = A_DREG_G; - *reg = 60 + src[3] - '0'; - return 4; - } - } - - if (src[2] >= '0' && src[2] <= '9' - && ((src[2] - '0') % 2) == 0 - && ! IDENT_CHAR ((unsigned char) src[3])) - { - *mode = A_DREG_G; - *reg = (src[2] - '0'); - return 3; - } - } - - if (l0 == 'f' && l1 == 'p') - { - if (src[2] >= '1' && src[2] <= '5') - { - if (src[3] >= '0' && src[3] <= '9' - && ((src[3] - '0') % 2) == 0 - && ! IDENT_CHAR ((unsigned char) src[4])) - { - *mode = A_FPREG_G; - *reg = 10 * (src[2] - '0') + src[3] - '0'; - return 4; - } - } - - if (src[2] == '6') - { - if ((src[3] == '0' || src[3] == '2') - && ! IDENT_CHAR ((unsigned char) src[4])) - { - *mode = A_FPREG_G; - *reg = 60 + src[3] - '0'; - return 4; - } - } - - if (src[2] >= '0' && src[2] <= '9' - && ((src[2] - '0') % 2) == 0 - && ! IDENT_CHAR ((unsigned char) src[3])) - { - *mode = A_FPREG_G; - *reg = (src[2] - '0'); - return 3; - } - } - - if (l0 == 'm' && strncasecmp (src, "mtrx", 4) == 0) - { - if (src[4] == '0' && ! IDENT_CHAR ((unsigned char) src[5])) - { - *mode = A_FMREG_G; - *reg = 0; - return 5; - } - - if (src[4] == '1' && src[5] == '6' - && ! IDENT_CHAR ((unsigned char) src[6])) - { - *mode = A_FMREG_G; - *reg = 16; - return 6; - } - - if (src[4] == '3' && src[5] == '2' - && ! IDENT_CHAR ((unsigned char) src[6])) - { - *mode = A_FMREG_G; - *reg = 32; - return 6; - } - - if (src[4] == '4' && src[5] == '8' - && ! IDENT_CHAR ((unsigned char) src[6])) - { - *mode = A_FMREG_G; - *reg = 48; - return 6; - } - } - - if (l0 == 'c' && l1 == 'r') - { - if (src[2] >= '1' && src[2] <= '5') - { - if (src[3] >= '0' && src[3] <= '9' - && ! IDENT_CHAR ((unsigned char) src[4])) - { - *mode = A_CREG_K; - *reg = 10 * (src[2] - '0') + src[3] - '0'; - return 4; - } - } - if (src[2] == '6') - { - if (src[3] >= '0' && src[3] <= '3' - && ! IDENT_CHAR ((unsigned char) src[4])) - { - *mode = A_CREG_K; - *reg = 60 + src[3] - '0'; - return 4; - } - } - if (src[2] >= '0' && src[2] <= '9' - && ! IDENT_CHAR ((unsigned char) src[3])) - { - *mode = A_CREG_K; - *reg = (src[2] - '0'); - return 3; - } - } - - /* We either have an error, a symbol or a control register by predefined - name. To keep things simple but still fast for normal cases, we do - linear search in the (not to big) table of predefined control - registers. We only do this when we *expect* a control register. - Those instructions should be rare enough that linear searching is ok. - Or just read them into a hash-table in shmedia_md_begin. Since they - cannot be specified in the same place of symbol operands, don't add - them there to the *main* symbol table as being in "reg_section". */ - if (argtype == A_CREG_J || argtype == A_CREG_K) - { - const shmedia_creg_info *cregp; - int len = 0; - - for (cregp = shmedia_creg_table; cregp->name != NULL; cregp++) - { - len = strlen (cregp->name); - if (strncasecmp (cregp->name, src, len) == 0 - && ! IDENT_CHAR (src[len])) - break; - } - - if (cregp->name != NULL) - { - *mode = A_CREG_K; - *reg = cregp->cregno; - return len; - } - } - - return 0; -} - -/* Called from md_estimate_size_before_relax in tc-sh.c */ - -static int -shmedia_md_estimate_size_before_relax (fragS *fragP, - segT segment_type ATTRIBUTE_UNUSED) -{ - int old_fr_fix; - expressionS *exp; - - /* For ELF, we can't relax externally visible symbols; see tc-i386.c. */ - bfd_boolean sym_relaxable - = (fragP->fr_symbol - && S_GET_SEGMENT (fragP->fr_symbol) == segment_type - && ! S_IS_EXTERNAL (fragP->fr_symbol) - && ! S_IS_WEAK (fragP->fr_symbol)); - - old_fr_fix = fragP->fr_fix; - - switch (fragP->fr_subtype) - { - case C (SH64PCREL16_32, UNDEF_SH64PCREL): - case C (SH64PCREL16PT_32, UNDEF_SH64PCREL): - /* Used to be to somewhere which was unknown. */ - if (sym_relaxable) - { - int what = GET_WHAT (fragP->fr_subtype); - - /* In this segment, so head for shortest. */ - fragP->fr_subtype = C (what, SH64PCREL16); - } - else - { - int what = GET_WHAT (fragP->fr_subtype); - /* We know the abs value, but we don't know where we will be - linked, so we must make it the longest. Presumably we could - switch to a non-pcrel representation, but having absolute - values in PT operands should be rare enough not to be worth - adding that code. */ - fragP->fr_subtype = C (what, SH64PCREL32); - } - fragP->fr_var = md_relax_table[fragP->fr_subtype].rlx_length; - break; - - case C (SH64PCREL16_64, UNDEF_SH64PCREL): - case C (SH64PCREL16PT_64, UNDEF_SH64PCREL): - /* Used to be to somewhere which was unknown. */ - if (sym_relaxable) - { - int what = GET_WHAT (fragP->fr_subtype); - - /* In this segment, so head for shortest. */ - fragP->fr_subtype = C (what, SH64PCREL16); - } - else - { - int what = GET_WHAT (fragP->fr_subtype); - /* We know the abs value, but we don't know where we will be - linked, so we must make it the longest. Presumably we could - switch to a non-pcrel representation, but having absolute - values in PT operands should be rare enough not to be worth - adding that code. */ - fragP->fr_subtype = C (what, SH64PCREL64); - } - fragP->fr_var = md_relax_table[fragP->fr_subtype].rlx_length; - break; - - case C (MOVI_IMM_64, UNDEF_MOVI): - case C (MOVI_IMM_32, UNDEF_MOVI): - exp = NULL; - - /* Look inside the "symbol". If we find a PC-relative expression, - change this to a PC-relative, relaxable expression. */ - if (fragP->fr_symbol != NULL - && (exp = symbol_get_value_expression (fragP->fr_symbol)) != NULL - && exp->X_op == O_subtract - && exp->X_op_symbol != NULL - && S_GET_SEGMENT (exp->X_op_symbol) == segment_type) - { - int what = GET_WHAT (fragP->fr_subtype); - int what_high = what == MOVI_IMM_32 ? MOVI_32 : MOVI_64; - expressionS *opexp - = symbol_get_value_expression (exp->X_op_symbol); - expressionS *addexp - = symbol_get_value_expression (exp->X_add_symbol); - - /* Change the MOVI expression to the "X" in "X - Y" and subtract - Y:s offset to this location from X. Note that we can only - allow an Y which is offset from this frag. */ - if (opexp != NULL - && addexp != NULL - && opexp->X_op == O_constant - && fragP == symbol_get_frag (exp->X_op_symbol)) - { - /* At this point, before relaxing, the add-number of opexp - is the offset from the fr_fix part. */ - fragP->fr_offset - = (exp->X_add_number - - (opexp->X_add_number - (fragP->fr_fix - 4))); - fragP->fr_symbol = exp->X_add_symbol; - - what = what == MOVI_IMM_32 - ? MOVI_IMM_32_PCREL : MOVI_IMM_64_PCREL; - - /* Check the "X" symbol to estimate the size of this - PC-relative expression. */ - if (S_GET_SEGMENT (exp->X_add_symbol) == segment_type - && ! S_IS_EXTERNAL (exp->X_add_symbol) - && ! S_IS_WEAK (exp->X_add_symbol)) - fragP->fr_subtype = C (what, MOVI_16); - else - fragP->fr_subtype = C (what, what_high); - - /* This is now a PC-relative expression, fit to be relaxed. */ - } - else - fragP->fr_subtype = C (what, what_high); - } - else if (fragP->fr_symbol == NULL - || (S_GET_SEGMENT (fragP->fr_symbol) == absolute_section - && exp->X_op == O_constant)) - { - unsigned long insn - = (target_big_endian - ? bfd_getb32 (fragP->fr_opcode) - : bfd_getl32 (fragP->fr_opcode)); - offsetT one = (offsetT) 1; - offsetT value = fragP->fr_offset - + (fragP->fr_symbol == NULL ? 0 : S_GET_VALUE (fragP->fr_symbol)); - - if (value >= (-((offsetT) 1 << 15)) && value < ((offsetT) 1 << 15)) - { - /* Fits in 16-bit signed number. */ - int what = GET_WHAT (fragP->fr_subtype); - fragP->fr_subtype = C (what, MOVI_16); - - /* Just "or" in the value. */ - md_number_to_chars (fragP->fr_opcode, - insn | ((value & ((1 << 16) - 1)) << 10), - 4); - } - else if (value >= -(one << 31) - && (value < (one << 31) - || (sh64_abi == sh64_abi_32 && value < (one << 32)))) - { - /* The value fits in a 32-bit signed number. */ - int reg = (insn >> 4) & 0x3f; - - /* Just "or" in the high bits of the value, making the first - MOVI. */ - md_number_to_chars (fragP->fr_opcode, - insn - | (((value >> 16) & ((1 << 16) - 1)) << 10), - 4); - - /* Add a SHORI with the low bits. Note that this insn lives - in the variable fragment part. */ - md_number_to_chars (fragP->fr_literal + old_fr_fix, - SHMEDIA_SHORI_OPC - | (reg << 4) - | ((value & ((1 << 16) - 1)) << 10), - 4); - - /* We took a piece of the variable part. */ - fragP->fr_fix += 4; - } - else if (GET_WHAT (fragP->fr_subtype) == MOVI_IMM_32) - { - /* Value out of range. */ - as_bad_where (fragP->fr_file, fragP->fr_line, - _("MOVI operand is not a 32-bit signed value: 0x%8x%08x"), - ((unsigned int) (value >> 32) - & (unsigned int) 0xffffffff), - (unsigned int) value & (unsigned int) 0xffffffff); - - /* Must advance size, or we will get internal inconsistency - and fall into an assert. */ - fragP->fr_fix += 4; - } - /* Now we know we are allowed to expand to 48- and 64-bit values. */ - else if (value >= -(one << 47) && value < (one << 47)) - { - /* The value fits in a 48-bit signed number. */ - int reg = (insn >> 4) & 0x3f; - - /* Just "or" in the high bits of the value, making the first - MOVI. */ - md_number_to_chars (fragP->fr_opcode, - insn - | (((value >> 32) & ((1 << 16) - 1)) << 10), - 4); - - /* Add a SHORI with the middle bits. Note that this insn lives - in the variable fragment part. */ - md_number_to_chars (fragP->fr_literal + old_fr_fix, - SHMEDIA_SHORI_OPC - | (reg << 4) - | (((value >> 16) & ((1 << 16) - 1)) << 10), - 4); - - /* Add a SHORI with the low bits. */ - md_number_to_chars (fragP->fr_literal + old_fr_fix + 4, - SHMEDIA_SHORI_OPC - | (reg << 4) - | ((value & ((1 << 16) - 1)) << 10), - 4); - - /* We took a piece of the variable part. */ - fragP->fr_fix += 8; - } - else - { - /* A 64-bit number. */ - int reg = (insn >> 4) & 0x3f; - - /* Just "or" in the high bits of the value, making the first - MOVI. */ - md_number_to_chars (fragP->fr_opcode, - insn - | (((value >> 48) & ((1 << 16) - 1)) << 10), - 4); - - /* Add a SHORI with the midhigh bits. Note that this insn lives - in the variable fragment part. */ - md_number_to_chars (fragP->fr_literal + old_fr_fix, - SHMEDIA_SHORI_OPC - | (reg << 4) - | (((value >> 32) & ((1 << 16) - 1)) << 10), - 4); - - /* Add a SHORI with the midlow bits. */ - md_number_to_chars (fragP->fr_literal + old_fr_fix + 4, - SHMEDIA_SHORI_OPC - | (reg << 4) - | (((value >> 16) & ((1 << 16) - 1)) << 10), - 4); - - /* Add a SHORI with the low bits. */ - md_number_to_chars (fragP->fr_literal + old_fr_fix + 8, - SHMEDIA_SHORI_OPC - | (reg << 4) - | ((value & ((1 << 16) - 1)) << 10), 4); - /* We took all of the variable part. */ - fragP->fr_fix += 12; - } - - /* MOVI expansions that get here have not been converted to - PC-relative frags, but instead expanded by - md_number_to_chars or by calling shmedia_md_convert_frag - with final == FALSE. We must not have them around as - frags anymore; symbols would be prematurely evaluated - when relaxing. We will not need to have md_convert_frag - called again with them; any further handling is through - the already emitted fixups. */ - frag_wane (fragP); - break; - } - fragP->fr_var = md_relax_table[fragP->fr_subtype].rlx_length; - break; - - /* For relaxation states that remain unchanged, report the - estimated length. */ - case C (SH64PCREL16_32, SH64PCREL16): - case C (SH64PCREL16PT_32, SH64PCREL16): - case C (SH64PCREL16_32, SH64PCREL32): - case C (SH64PCREL16PT_32, SH64PCREL32): - case C (SH64PCREL16_32, SH64PCRELPLT): - case C (SH64PCREL16PT_32, SH64PCRELPLT): - case C (SH64PCREL16_64, SH64PCREL16): - case C (SH64PCREL16PT_64, SH64PCREL16): - case C (SH64PCREL16_64, SH64PCREL32): - case C (SH64PCREL16PT_64, SH64PCREL32): - case C (SH64PCREL16_64, SH64PCREL48): - case C (SH64PCREL16PT_64, SH64PCREL48): - case C (SH64PCREL16_64, SH64PCREL64): - case C (SH64PCREL16PT_64, SH64PCREL64): - case C (SH64PCREL16_64, SH64PCRELPLT): - case C (SH64PCREL16PT_64, SH64PCRELPLT): - case C (MOVI_IMM_32, MOVI_16): - case C (MOVI_IMM_32, MOVI_32): - case C (MOVI_IMM_32, MOVI_GOTOFF): - case C (MOVI_IMM_32_PCREL, MOVI_16): - case C (MOVI_IMM_32_PCREL, MOVI_32): - case C (MOVI_IMM_32_PCREL, MOVI_PLT): - case C (MOVI_IMM_32_PCREL, MOVI_GOTPC): - case C (MOVI_IMM_64, MOVI_16): - case C (MOVI_IMM_64, MOVI_32): - case C (MOVI_IMM_64, MOVI_48): - case C (MOVI_IMM_64, MOVI_64): - case C (MOVI_IMM_64, MOVI_GOTOFF): - case C (MOVI_IMM_64_PCREL, MOVI_16): - case C (MOVI_IMM_64_PCREL, MOVI_32): - case C (MOVI_IMM_64_PCREL, MOVI_48): - case C (MOVI_IMM_64_PCREL, MOVI_64): - case C (MOVI_IMM_64_PCREL, MOVI_PLT): - case C (MOVI_IMM_64_PCREL, MOVI_GOTPC): - fragP->fr_var = md_relax_table[fragP->fr_subtype].rlx_length; - break; - - default: - abort (); - } - - return fragP->fr_var + (fragP->fr_fix - old_fr_fix); -} - -/* Parse an expression, SH64-style. Copied from tc-sh.c, but with - datatypes adjusted. */ - -static char * -shmedia_parse_exp (char *s, shmedia_operand_info *op) -{ - char *save; - char *new_pointer; - - save = input_line_pointer; - input_line_pointer = s; - expression (&op->immediate); - if (op->immediate.X_op == O_absent) - as_bad (_("missing operand")); - new_pointer = input_line_pointer; - input_line_pointer = save; - return new_pointer; -} - -/* Parse an operand. Store pointer to next character in *PTR. */ - -static void -shmedia_get_operand (char **ptr, shmedia_operand_info *op, - shmedia_arg_type argtype) -{ - char *src = *ptr; - shmedia_arg_type mode = (shmedia_arg_type) -1; - unsigned int len; - - len = shmedia_parse_reg (src, &mode, &(op->reg), argtype); - if (len) - { - *ptr = src + len; - op->type = mode; - } - else - { - /* Not a reg, so it must be a displacement. */ - *ptr = shmedia_parse_exp (src, op); - op->type = A_IMMM; - - /* This is just an initialization; shmedia_get_operands will change - as needed. */ - op->reloctype = BFD_RELOC_NONE; - } -} - -/* Parse the operands for this insn; return NULL if invalid, else return - how much text was consumed. */ - -static char * -shmedia_get_operands (shmedia_opcode_info *info, char *args, - shmedia_operands_info *operands) -{ - char *ptr = args; - int i; - - if (*ptr == ' ') - ptr++; - - for (i = 0; info->arg[i] != 0; i++) - { - memset (operands->operands + i, 0, sizeof (operands->operands[0])); - - /* No operand to get for these fields. */ - if (info->arg[i] == A_REUSE_PREV) - continue; - - shmedia_get_operand (&ptr, &operands->operands[i], info->arg[i]); - - /* Check operands type match. */ - switch (info->arg[i]) - { - case A_GREG_M: - case A_GREG_N: - case A_GREG_D: - if (operands->operands[i].type != A_GREG_M) - return NULL; - break; - - case A_FREG_G: - case A_FREG_H: - case A_FREG_F: - if (operands->operands[i].type != A_FREG_G) - return NULL; - break; - - case A_FVREG_G: - case A_FVREG_H: - case A_FVREG_F: - if (operands->operands[i].type != A_FVREG_G) - return NULL; - break; - - case A_FMREG_G: - case A_FMREG_H: - case A_FMREG_F: - if (operands->operands[i].type != A_FMREG_G) - return NULL; - break; - - case A_FPREG_G: - case A_FPREG_H: - case A_FPREG_F: - if (operands->operands[i].type != A_FPREG_G) - return NULL; - break; - - case A_DREG_G: - case A_DREG_H: - case A_DREG_F: - if (operands->operands[i].type != A_DREG_G) - return NULL; - break; - - case A_TREG_A: - case A_TREG_B: - if (operands->operands[i].type != A_TREG_B) - return NULL; - break; - - case A_CREG_J: - case A_CREG_K: - if (operands->operands[i].type != A_CREG_K) - return NULL; - break; - - case A_IMMS16: - case A_IMMU16: - /* Check for an expression that looks like S & 65535 or - (S >> N) & 65535, where N = 0, 16, 32, 48. - - Get the S and put at operands->operands[i].immediate, and - adjust operands->operands[i].reloctype. */ - { - expressionS *imm_expr = &operands->operands[i].immediate; - expressionS *right_expr; - - if (operands->operands[i].type == A_IMMM - && imm_expr->X_op == O_bit_and - && imm_expr->X_op_symbol != NULL - && ((right_expr - = symbol_get_value_expression (imm_expr->X_op_symbol)) - ->X_op == O_constant) - && right_expr->X_add_number == 0xffff) - { - symbolS *inner = imm_expr->X_add_symbol; - bfd_reloc_code_real_type reloctype = BFD_RELOC_SH_IMM_LOW16; - expressionS *inner_expr - = symbol_get_value_expression (inner); - - if (inner_expr->X_op == O_right_shift) - { - expressionS *inner_right; - - if (inner_expr->X_op_symbol != NULL - && ((inner_right - = symbol_get_value_expression (inner_expr - ->X_op_symbol)) - ->X_op == O_constant)) - { - offsetT addnum - = inner_right->X_add_number; - - if (addnum == 0 || addnum == 16 || addnum == 32 - || addnum == 48) - { - reloctype - = (addnum == 0 - ? BFD_RELOC_SH_IMM_LOW16 - : (addnum == 16 - ? BFD_RELOC_SH_IMM_MEDLOW16 - : (addnum == 32 - ? BFD_RELOC_SH_IMM_MEDHI16 - : BFD_RELOC_SH_IMM_HI16))); - - inner = inner_expr->X_add_symbol; - inner_expr = symbol_get_value_expression (inner); - } - } - } - - /* I'm not sure I understand the logic, but evidently the - inner expression of a lone symbol is O_constant, with - the actual symbol in expr_section. For a constant, the - section would be absolute_section. For sym+offset, - it's O_symbol as always. See expr.c:make_expr_symbol, - first statements. */ - - if (inner_expr->X_op == O_constant - && S_GET_SEGMENT (inner) != absolute_section) - { - operands->operands[i].immediate.X_op = O_symbol; - operands->operands[i].immediate.X_add_symbol = inner; - operands->operands[i].immediate.X_add_number = 0; - } - else - operands->operands[i].immediate - = *symbol_get_value_expression (inner); - - operands->operands[i].reloctype = reloctype; - } - } - /* Fall through. */ - case A_IMMS6: - case A_IMMS6BY32: - case A_IMMS10: - case A_IMMS10BY1: - case A_IMMS10BY2: - case A_IMMS10BY4: - case A_IMMS10BY8: - case A_PCIMMS16BY4: - case A_PCIMMS16BY4_PT: - case A_IMMU5: - case A_IMMU6: - if (operands->operands[i].type != A_IMMM) - return NULL; - - if (sh_check_fixup (&operands->operands[i].immediate, - &operands->operands[i].reloctype)) - { - as_bad (_("invalid PIC reference")); - return NULL; - } - - break; - - default: - BAD_CASE (info->arg[i]); - } - - if (*ptr == ',' && info->arg[i + 1]) - ptr++; - } - return ptr; -} - - -/* Find an opcode at the start of *STR_P in the hash table, and set - *STR_P to the first character after the last one read. */ - -static shmedia_opcode_info * -shmedia_find_cooked_opcode (char **str_p) -{ - char *str = *str_p; - char *op_start; - char *op_end; - char name[20]; - unsigned int nlen = 0; - - /* Drop leading whitespace. */ - while (*str == ' ') - str++; - - /* Find the op code end. */ - for (op_start = op_end = str; - *op_end - && nlen < sizeof (name) - 1 - && ! is_end_of_line[(unsigned char) *op_end] - && ! ISSPACE ((unsigned char) *op_end); - op_end++) - { - unsigned char c = op_start[nlen]; - - /* The machine independent code will convert CMP/EQ into cmp/EQ - because it thinks the '/' is the end of the symbol. Moreover, - all but the first sub-insn is a parallel processing insn won't - be capitalized. Instead of hacking up the machine independent - code, we just deal with it here. */ - c = TOLOWER (c); - name[nlen] = c; - nlen++; - } - - name[nlen] = 0; - *str_p = op_end; - - if (nlen == 0) - as_bad (_("can't find opcode")); - - return - (shmedia_opcode_info *) hash_find (shmedia_opcode_hash_control, name); -} - -/* Build up an instruction, including allocating the frag. */ - -static int -shmedia_build_Mytes (shmedia_opcode_info *opcode, - shmedia_operands_info *operands) -{ - unsigned long insn = opcode->opcode_base; - int i, j; - char *insn_loc = frag_more (4); - - /* The parameter to dwarf2_emit_insn is actually the offset to the start - of the insn from the fix piece of instruction that was emitted. - Since we want .debug_line addresses to record (address | 1) for - SHmedia insns, we get the wanted effect by taking one off the size, - knowing it's a multiple of 4. We count from the first fix piece of - the insn. There must be no frags changes (frag_more or frag_var) - calls in-between the frag_more call we account for, and this - dwarf2_emit_insn call. */ - dwarf2_emit_insn (3); - - /* This is stored into any frag_var operand. */ - sh64_last_insn_frag = frag_now; - - /* Loop over opcode info, emit an instruction. */ - for (i = 0, j = 0; opcode->arg[i]; i++) - { - shmedia_arg_type argtype = opcode->arg[i]; - shmedia_operand_info *opjp = &operands->operands[j]; - switch (argtype) - { - case A_TREG_A: - case A_TREG_B: - case A_GREG_M: - case A_GREG_N: - case A_GREG_D: - case A_FREG_G: - case A_FREG_H: - case A_FREG_F: - case A_FVREG_G: - case A_FVREG_H: - case A_FVREG_F: - case A_FMREG_G: - case A_FMREG_H: - case A_FMREG_F: - case A_FPREG_G: - case A_FPREG_H: - case A_FPREG_F: - case A_DREG_G: - case A_DREG_H: - case A_DREG_F: - case A_CREG_J: - case A_CREG_K: - /* Six-bit register fields. They just get filled with the - parsed register number. */ - insn |= (opjp->reg << opcode->nibbles[i]); - j++; - break; - - case A_REUSE_PREV: - /* Copy the register for the previous operand to this position. */ - insn |= (operands->operands[j - 1].reg << opcode->nibbles[i]); - j++; - break; - - case A_IMMS6: - insn |= shmedia_immediate_op (insn_loc, opjp, 0, - BFD_RELOC_SH_IMMS6); - j++; - break; - - case A_IMMS6BY32: - insn |= shmedia_immediate_op (insn_loc, opjp, 0, - BFD_RELOC_SH_IMMS6BY32); - j++; - break; - - case A_IMMS10BY1: - case A_IMMS10: - insn |= shmedia_immediate_op (insn_loc, opjp, 0, - BFD_RELOC_SH_IMMS10); - j++; - break; - - case A_IMMS10BY2: - insn |= shmedia_immediate_op (insn_loc, opjp, 0, - BFD_RELOC_SH_IMMS10BY2); - j++; - break; - - case A_IMMS10BY4: - if (opjp->reloctype == BFD_RELOC_NONE) - insn |= shmedia_immediate_op (insn_loc, opjp, 0, - BFD_RELOC_SH_IMMS10BY4); - else if (opjp->reloctype == BFD_RELOC_SH_GOTPLT32) - insn |= shmedia_immediate_op (insn_loc, opjp, 0, - BFD_RELOC_SH_GOTPLT10BY4); - else if (opjp->reloctype == BFD_RELOC_32_GOT_PCREL) - insn |= shmedia_immediate_op (insn_loc, opjp, 0, - BFD_RELOC_SH_GOT10BY4); - else - as_bad (_("invalid PIC reference")); - j++; - break; - - case A_IMMS10BY8: - if (opjp->reloctype == BFD_RELOC_NONE) - insn |= shmedia_immediate_op (insn_loc, opjp, 0, - BFD_RELOC_SH_IMMS10BY8); - else if (opjp->reloctype == BFD_RELOC_SH_GOTPLT32) - insn |= shmedia_immediate_op (insn_loc, opjp, 0, - BFD_RELOC_SH_GOTPLT10BY8); - else if (opjp->reloctype == BFD_RELOC_32_GOT_PCREL) - insn |= shmedia_immediate_op (insn_loc, opjp, 0, - BFD_RELOC_SH_GOT10BY8); - else - as_bad (_("invalid PIC reference")); - j++; - break; - - case A_IMMS16: - /* Sneak a peek if this is the MOVI insn. If so, check if we - should expand it. */ - if (opjp->reloctype == BFD_RELOC_32_GOT_PCREL) - opjp->reloctype = BFD_RELOC_SH_GOT_LOW16; - else if (opjp->reloctype == BFD_RELOC_SH_GOTPLT32) - opjp->reloctype = BFD_RELOC_SH_GOTPLT_LOW16; - - if ((opjp->reloctype == BFD_RELOC_NONE - || opjp->reloctype == BFD_RELOC_32_GOTOFF - || opjp->reloctype == BFD_RELOC_32_PLT_PCREL - || opjp->reloctype == BFD_RELOC_SH_GOTPC) - && opcode->opcode_base == SHMEDIA_MOVI_OPC - && (opjp->immediate.X_op != O_constant - || opjp->immediate.X_add_number < -32768 - || opjp->immediate.X_add_number > 32767) - && (sh64_expand - || opjp->reloctype == BFD_RELOC_32_GOTOFF - || opjp->reloctype == BFD_RELOC_32_PLT_PCREL - || opjp->reloctype == BFD_RELOC_SH_GOTPC)) - { - int what = sh64_abi == sh64_abi_64 ? MOVI_IMM_64 : MOVI_IMM_32; - offsetT max = sh64_abi == sh64_abi_64 ? MOVI_64 : MOVI_32; - offsetT min = MOVI_16; - offsetT init = UNDEF_MOVI; - valueT addvalue - = opjp->immediate.X_op_symbol != NULL - ? 0 : opjp->immediate.X_add_number; - symbolS *sym - = opjp->immediate.X_op_symbol != NULL - ? make_expr_symbol (&opjp->immediate) - : opjp->immediate.X_add_symbol; - - if (opjp->reloctype == BFD_RELOC_32_GOTOFF) - init = max = min = MOVI_GOTOFF; - else if (opjp->reloctype == BFD_RELOC_32_PLT_PCREL) - { - init = max = min = MOVI_PLT; - what = (sh64_abi == sh64_abi_64 - ? MOVI_IMM_64_PCREL - : MOVI_IMM_32_PCREL); - } - else if (opjp->reloctype == BFD_RELOC_SH_GOTPC) - { - init = max = min = MOVI_GOTPC; - what = (sh64_abi == sh64_abi_64 - ? MOVI_IMM_64_PCREL - : MOVI_IMM_32_PCREL); - } - - frag_var (rs_machine_dependent, - md_relax_table[C (what, max)].rlx_length, - md_relax_table[C (what, min)].rlx_length, - C (what, init), sym, addvalue, insn_loc); - } - else - insn |= shmedia_immediate_op (insn_loc, opjp, 0, - (opjp->reloctype - == BFD_RELOC_NONE) - ? BFD_RELOC_SH_IMMS16 - : opjp->reloctype); - j++; - break; - - case A_PCIMMS16BY4: - { - int what - = ((sh64_abi == sh64_abi_64 && ! sh64_pt32) - ? SH64PCREL16_64 : SH64PCREL16_32); - offsetT max - = ((sh64_abi == sh64_abi_64 && ! sh64_pt32) - ? SH64PCREL64 : SH64PCREL32); - offsetT min = SH64PCREL16; - offsetT init = UNDEF_SH64PCREL; - - /* Don't allow complex expressions here. */ - if (opjp->immediate.X_op_symbol != NULL) - { - as_bad (_("invalid operand: expression in PT target")); - return 0; - } - - if (opjp->reloctype == BFD_RELOC_32_PLT_PCREL) - init = max = min = SH64PCRELPLT; - - /* If we're not expanding, then just emit a fixup. */ - if (sh64_expand || opjp->reloctype != BFD_RELOC_NONE) - frag_var (rs_machine_dependent, - md_relax_table[C (what, max)].rlx_length, - md_relax_table[C (what, min)].rlx_length, - C (what, init), - opjp->immediate.X_add_symbol, - opjp->immediate.X_add_number, - insn_loc); - else - insn |= shmedia_immediate_op (insn_loc, opjp, 1, - opjp->reloctype == BFD_RELOC_NONE - ? BFD_RELOC_SH_PT_16 - : opjp->reloctype); - - j++; - break; - } - - case A_PCIMMS16BY4_PT: - { - int what - = ((sh64_abi == sh64_abi_64 && ! sh64_pt32) - ? SH64PCREL16PT_64 : SH64PCREL16PT_32); - offsetT max - = ((sh64_abi == sh64_abi_64 && ! sh64_pt32) - ? SH64PCREL64 : SH64PCREL32); - offsetT min = SH64PCREL16; - offsetT init = UNDEF_SH64PCREL; - - /* Don't allow complex expressions here. */ - if (opjp->immediate.X_op_symbol != NULL) - { - as_bad (_("invalid operand: expression in PT target")); - return 0; - } - - if (opjp->reloctype == BFD_RELOC_32_PLT_PCREL) - init = max = min = SH64PCRELPLT; - - /* If we're not expanding, then just emit a fixup. */ - if (sh64_expand || opjp->reloctype != BFD_RELOC_NONE) - frag_var (rs_machine_dependent, - md_relax_table[C (what, max)].rlx_length, - md_relax_table[C (what, min)].rlx_length, - C (what, init), - opjp->immediate.X_add_symbol, - opjp->immediate.X_add_number, - insn_loc); - else - /* This reloc-type is just temporary, so we can distinguish - PTA from PT. It is changed in shmedia_md_apply_fix to - BFD_RELOC_SH_PT_16. */ - insn |= shmedia_immediate_op (insn_loc, opjp, 1, - opjp->reloctype == BFD_RELOC_NONE - ? SHMEDIA_BFD_RELOC_PT - : opjp->reloctype); - - j++; - break; - } - - case A_IMMU5: - insn |= shmedia_immediate_op (insn_loc, opjp, 0, - BFD_RELOC_SH_IMMU5); - j++; - break; - - case A_IMMU6: - insn |= shmedia_immediate_op (insn_loc, opjp, 0, - BFD_RELOC_SH_IMMU6); - j++; - break; - - case A_IMMU16: - insn |= shmedia_immediate_op (insn_loc, opjp, 0, - (opjp->reloctype - == BFD_RELOC_NONE) - ? BFD_RELOC_SH_IMMU16 - : opjp->reloctype); - j++; - break; - - default: - BAD_CASE (argtype); - } - } - - md_number_to_chars (insn_loc, insn, 4); - return 4; -} - -/* Assemble a SHmedia instruction. */ - -static void -shmedia_md_assemble (char *str) -{ - char *op_end; - shmedia_opcode_info *opcode; - shmedia_operands_info operands; - int size; - - opcode = shmedia_find_cooked_opcode (&str); - op_end = str; - - if (opcode == NULL) - { - as_bad (_("unknown opcode")); - return; - } - - /* Start a SHmedia code region, if there has been pseudoinsns or similar - seen since the last one. */ - if (!seen_insn) - { - sh64_update_contents_mark (TRUE); - sh64_set_contents_type (CRT_SH5_ISA32); - seen_insn = TRUE; - } - - op_end = shmedia_get_operands (opcode, op_end, &operands); - - if (op_end == NULL) - { - as_bad (_("invalid operands to %s"), opcode->name); - return; - } - - if (*op_end) - { - as_bad (_("excess operands to %s"), opcode->name); - return; - } - - size = shmedia_build_Mytes (opcode, &operands); - if (size == 0) - return; -} - -/* Hook called from md_begin in tc-sh.c. */ - -void -shmedia_md_begin (void) -{ - const shmedia_opcode_info *shmedia_opcode; - shmedia_opcode_hash_control = hash_new (); - - /* Create opcode table for SHmedia mnemonics. */ - for (shmedia_opcode = shmedia_table; - shmedia_opcode->name; - shmedia_opcode++) - hash_insert (shmedia_opcode_hash_control, shmedia_opcode->name, - (char *) shmedia_opcode); -} - -/* Switch instruction set. Only valid if one of the --isa or --abi - options was specified. */ - -static void -s_sh64_mode (int ignore ATTRIBUTE_UNUSED) -{ - char *name = input_line_pointer, ch; - - /* Make sure data up to this location is handled according to the - previous ISA. */ - sh64_update_contents_mark (TRUE); - - while (!is_end_of_line[(unsigned char) *input_line_pointer]) - input_line_pointer++; - ch = *input_line_pointer; - *input_line_pointer = '\0'; - - /* If the mode was not set before, explicitly or implicitly, then we're - not emitting SH64 code, so this pseudo is invalid. */ - if (sh64_isa_mode == sh64_isa_unspecified) - as_bad (_("The `.mode %s' directive is not valid with this architecture"), - name); - - if (strcasecmp (name, "shcompact") == 0) - sh64_isa_mode = sh64_isa_shcompact; - else if (strcasecmp (name, "shmedia") == 0) - sh64_isa_mode = sh64_isa_shmedia; - else - as_bad (_("Invalid argument to .mode: %s"), name); - - /* Make a new frag, marking it with the supposedly-changed ISA. */ - frag_wane (frag_now); - frag_new (0); - - /* Contents type up to this new point is the same as before; don't add a - data region just because the new frag we created. */ - sh64_update_contents_mark (FALSE); - - *input_line_pointer = ch; - demand_empty_rest_of_line (); -} - -/* Check that the right ABI is used. Only valid if one of the --isa or - --abi options was specified. */ - -static void -s_sh64_abi (int ignore ATTRIBUTE_UNUSED) -{ - char *name = input_line_pointer, ch; - - while (!is_end_of_line[(unsigned char) *input_line_pointer]) - input_line_pointer++; - ch = *input_line_pointer; - *input_line_pointer = '\0'; - - /* If the mode was not set before, explicitly or implicitly, then we're - not emitting SH64 code, so this pseudo is invalid. */ - if (sh64_abi == sh64_abi_unspecified) - as_bad (_("The `.abi %s' directive is not valid with this architecture"), - name); - - if (strcmp (name, "64") == 0) - { - if (sh64_abi != sh64_abi_64) - as_bad (_("`.abi 64' but command-line options do not specify 64-bit ABI")); - } - else if (strcmp (name, "32") == 0) - { - if (sh64_abi != sh64_abi_32) - as_bad (_("`.abi 32' but command-line options do not specify 32-bit ABI")); - } - else - as_bad (_("Invalid argument to .abi: %s"), name); - - *input_line_pointer = ch; - demand_empty_rest_of_line (); -} - -/* This function is the first target-specific function called after - parsing command-line options. Therefore we set default values from - command-line options here and do some sanity checking we couldn't do - when options were being parsed. */ - -const char * -sh64_target_format (void) -{ -#ifdef TE_NetBSD - /* For NetBSD, if the ISA is unspecified, always use SHmedia. */ - if (preset_target_arch == 0 && sh64_isa_mode == sh64_isa_unspecified) - sh64_isa_mode = sh64_isa_shmedia; - - /* If the ABI is unspecified, select a default: based on how - we were configured: sh64 == sh64_abi_64, else sh64_abi_32. */ - if (sh64_abi == sh64_abi_unspecified) - { - if (preset_target_arch != 0 || sh64_isa_mode == sh64_isa_shcompact) - sh64_abi = sh64_abi_32; - else if (strncmp (TARGET_CPU, "sh64", 4) == 0) - sh64_abi = sh64_abi_64; - else - sh64_abi = sh64_abi_32; - } -#endif - -#ifdef TE_LINUX - if (preset_target_arch == 0 && sh64_isa_mode == sh64_isa_unspecified) - sh64_isa_mode = sh64_isa_shmedia; - - if (sh64_abi == sh64_abi_unspecified) - sh64_abi = sh64_abi_32; -#endif - - if (sh64_abi == sh64_abi_64 && sh64_isa_mode == sh64_isa_unspecified) - sh64_isa_mode = sh64_isa_shmedia; - - if (sh64_abi == sh64_abi_32 && sh64_isa_mode == sh64_isa_unspecified) - sh64_isa_mode = sh64_isa_shcompact; - - if (sh64_isa_mode == sh64_isa_shcompact - && sh64_abi == sh64_abi_unspecified) - sh64_abi = sh64_abi_32; - - if (sh64_isa_mode == sh64_isa_shmedia - && sh64_abi == sh64_abi_unspecified) - sh64_abi = sh64_abi_64; - - if (sh64_isa_mode == sh64_isa_unspecified && ! sh64_mix) - as_bad (_("-no-mix is invalid without specifying SHcompact or SHmedia")); - - if ((sh64_isa_mode == sh64_isa_unspecified - || sh64_isa_mode == sh64_isa_shmedia) - && sh64_shcompact_const_crange) - as_bad (_("-shcompact-const-crange is invalid without SHcompact")); - - if (sh64_pt32 && sh64_abi != sh64_abi_64) - as_bad (_("-expand-pt32 only valid with -abi=64")); - - if (! sh64_expand && sh64_isa_mode == sh64_isa_unspecified) - as_bad (_("-no-expand only valid with SHcompact or SHmedia")); - - if (sh64_pt32 && ! sh64_expand) - as_bad (_("-expand-pt32 invalid together with -no-expand")); - -#ifdef TE_NetBSD - if (sh64_abi == sh64_abi_64) - return (target_big_endian ? "elf64-sh64-nbsd" : "elf64-sh64l-nbsd"); - else - return (target_big_endian ? "elf32-sh64-nbsd" : "elf32-sh64l-nbsd"); -#elif defined (TE_LINUX) - if (sh64_abi == sh64_abi_64) - return (target_big_endian ? "elf64-sh64big-linux" : "elf64-sh64-linux"); - else - return (target_big_endian ? "elf32-sh64big-linux" : "elf32-sh64-linux"); -#else - /* When the ISA is not one of SHmedia or SHcompact, use the old SH - object format. */ - if (sh64_isa_mode == sh64_isa_unspecified) - return (target_big_endian ? "elf32-sh" : "elf32-shl"); - else if (sh64_abi == sh64_abi_64) - return (target_big_endian ? "elf64-sh64" : "elf64-sh64l"); - else - return (target_big_endian ? "elf32-sh64" : "elf32-sh64l"); -#endif -} - -/* The worker function of TARGET_MACH. */ - -int -sh64_target_mach (void) -{ - /* We need to explicitly set bfd_mach_sh5 instead of the default 0. But - we only do this for the 64-bit ABI: if we do it for the 32-bit ABI, - the SH5 info in the bfd_arch_info structure will be selected. - However correct, as the machine has 64-bit addresses, functions - expected to emit 32-bit data for addresses will start failing. For - example, the dwarf2dbg.c functions will emit 64-bit debugging format, - and we don't want that in the 32-bit ABI. - - We could have two bfd_arch_info structures for SH64; one for the - 32-bit ABI and one for the rest (64-bit ABI). But that would be a - bigger kludge: it's a flaw in the BFD design, and we need to just - work around it by having the default machine set here in the - assembler. For everything else but the assembler, the various bfd - functions will set the machine type right to bfd_mach_sh5 from object - file header flags regardless of the 0 here. */ - - return (sh64_abi == sh64_abi_64) ? bfd_mach_sh5 : 0; -} - -/* This is MD_PCREL_FROM_SECTION, we define so it is called instead of - md_pcrel_from (in tc-sh.c). */ - -valueT -shmedia_md_pcrel_from_section (struct fix *fixP, segT sec ATTRIBUTE_UNUSED) -{ - /* Use the ISA for the instruction to decide which offset to use. We - can glean it from the fixup type. */ - switch (fixP->fx_r_type) - { - case BFD_RELOC_SH_IMM_LOW16: - case BFD_RELOC_SH_IMM_MEDLOW16: - case BFD_RELOC_SH_IMM_MEDHI16: - case BFD_RELOC_SH_IMM_HI16: - case BFD_RELOC_SH_IMM_LOW16_PCREL: - case BFD_RELOC_SH_IMM_MEDLOW16_PCREL: - case BFD_RELOC_SH_IMM_MEDHI16_PCREL: - case BFD_RELOC_SH_IMM_HI16_PCREL: - case BFD_RELOC_SH_IMMU5: - case BFD_RELOC_SH_IMMU6: - case BFD_RELOC_SH_IMMS6: - case BFD_RELOC_SH_IMMS10: - case BFD_RELOC_SH_IMMS10BY2: - case BFD_RELOC_SH_IMMS10BY4: - case BFD_RELOC_SH_IMMS10BY8: - case BFD_RELOC_SH_IMMS16: - case BFD_RELOC_SH_IMMU16: - case BFD_RELOC_SH_PT_16: - case SHMEDIA_BFD_RELOC_PT: - /* PC-relative relocs are relative to the address of the last generated - instruction, i.e. fx_size - 4. */ - return SHMEDIA_MD_PCREL_FROM_FIX (fixP); - - case BFD_RELOC_64: - case BFD_RELOC_64_PCREL: - /* Fall through. */ - - default: - /* If section was SHcompact, use its function. */ - return (valueT) md_pcrel_from_section (fixP, sec); - } - - know (0 /* Shouldn't get here. */); - return 0; -} - -/* Create one .cranges descriptor from two symbols, STARTSYM marking begin - and ENDSYM marking end, and CR_TYPE specifying the type. */ - -static void -sh64_emit_crange (symbolS *startsym, symbolS *endsym, - enum sh64_elf_cr_type cr_type) -{ - expressionS exp; - segT current_seg = now_seg; - subsegT current_subseg = now_subseg; - - asection *cranges - = bfd_make_section_old_way (stdoutput, - SH64_CRANGES_SECTION_NAME); - - /* Temporarily change to the .cranges section. */ - subseg_set (cranges, 0); - - /* Emit the cr_addr part. */ - exp.X_op = O_symbol; - exp.X_add_number = 0; - exp.X_op_symbol = NULL; - exp.X_add_symbol = startsym; - emit_expr (&exp, 4); - - /* Emit the cr_size part. */ - exp.X_op = O_subtract; - exp.X_add_number = 0; - exp.X_add_symbol = endsym; - exp.X_op_symbol = startsym; - emit_expr (&exp, 4); - - /* Emit the cr_size part. */ - exp.X_op = O_constant; - exp.X_add_number = cr_type; - exp.X_add_symbol = NULL; - exp.X_op_symbol = NULL; - emit_expr (&exp, 2); - - /* Now back to our regular program. */ - subseg_set (current_seg, current_subseg); -} - -/* Called when the assembler is about to emit contents of some type into - SEG, so it is *known* that the type of that new contents is in - NEW_CONTENTS_TYPE. If just switching back and forth between different - contents types (for example, with consecutive .mode pseudos), then this - function isn't called. */ - -static void -sh64_set_contents_type (enum sh64_elf_cr_type new_contents_type) -{ - segment_info_type *seginfo; - - /* We will not be called when emitting .cranges output, since callers - stop that. Validize that assumption. */ - know (!emitting_crange); - - seginfo = seg_info (now_seg); - - if (seginfo) - { - symbolS *symp = seginfo->tc_segment_info_data.last_contents_mark; - - enum sh64_elf_cr_type contents_type - = seginfo->tc_segment_info_data.contents_type; - - /* If it was just SHcompact switching between code and constant - pool, don't change contents type. Just make sure we don't set - the contents type to data, as that would join with a data-region - in SHmedia mode. */ - if (sh64_isa_mode == sh64_isa_shcompact - && ! sh64_shcompact_const_crange) - new_contents_type = CRT_SH5_ISA16; - - /* If nothing changed, stop here. */ - if (contents_type == new_contents_type) - return; - - /* If we're in 64-bit ABI mode, we do not emit .cranges, as it is - only specified for 32-bit addresses. It could presumably be - extended, but in 64-bit ABI mode we don't have SHcompact code, so - we would only use it to mark code and data. */ - if (sh64_abi == sh64_abi_64) - { - /* Make the code type "sticky". We don't want to set the - sections contents type to data if there's any code in it as - we don't have .cranges in 64-bit mode to notice the - difference. */ - seginfo->tc_segment_info_data.contents_type - = (new_contents_type == CRT_SH5_ISA32 - || contents_type == CRT_SH5_ISA32) - ? CRT_SH5_ISA32 : new_contents_type; - return; - } - - /* If none was marked, create a start symbol for this range and - perhaps as a closing symbol for the old one. */ - if (symp == NULL) - symp = symbol_new (FAKE_LABEL_NAME, now_seg, (valueT) frag_now_fix (), - frag_now); - - /* We will use this symbol, so don't leave a pointer behind. */ - seginfo->tc_segment_info_data.last_contents_mark = NULL; - - /* We'll be making only datalabel references to it, if we emit a - .cranges descriptor, so remove any code flag. */ - S_SET_OTHER (symp, S_GET_OTHER (symp) & ~STO_SH5_ISA32); - - /* If we have already marked the start of a range, we need to close - and emit it before marking a new one, so emit a new .cranges - descriptor into the .cranges section. */ - if (seginfo->tc_segment_info_data.mode_start_symbol) - { - /* If we're not supposed to emit mixed-mode sections, make it an - error, but continue processing. */ - if (! sh64_mix - && (new_contents_type == CRT_SH5_ISA32 - || contents_type == CRT_SH5_ISA32)) - as_bad ( -_("SHmedia code not allowed in same section as constants and SHcompact code")); - - emitting_crange = TRUE; - sh64_emit_crange (seginfo->tc_segment_info_data.mode_start_symbol, - symp, contents_type); - emitting_crange = FALSE; - seginfo->tc_segment_info_data.emitted_ranges++; - } - - seginfo->tc_segment_info_data.mode_start_symbol = symp; - seginfo->tc_segment_info_data.mode_start_subseg = now_subseg; - seginfo->tc_segment_info_data.contents_type = new_contents_type; - - /* Always reset this, so the SHcompact code will emit a reloc when - it prepares to relax. */ - seginfo->tc_segment_info_data.in_code = 0; - } - else - as_bad (_("No segment info for current section")); -} - -/* Hook when defining symbols and labels. We set the ST_OTHER field if - the symbol is "shmedia" (with "bitor 1" automatically applied). Simple - semantics for a label being "shmedia" : It was defined when .mode - SHmedia was in effect, and it was defined in a code section. It - doesn't matter whether or not an assembled opcode is nearby. */ - -void -sh64_frob_label (symbolS *symp) -{ - segT seg = S_GET_SEGMENT (symp); - static const symbolS *null = NULL; - - /* Reset the tc marker for all newly created symbols. */ - symbol_set_tc (symp, (symbolS **) &null); - - if (seg != NULL && sh64_isa_mode == sh64_isa_shmedia && subseg_text_p (seg)) - S_SET_OTHER (symp, S_GET_OTHER (symp) | STO_SH5_ISA32); -} - -/* Handle the "datalabel" qualifier. We need to call "operand", but it's - static, so a function pointer is passed here instead. FIXME: A target - hook for qualifiers is needed; we currently use the md_parse_name - symbol hook. */ - -int -sh64_consume_datalabel (const char *name, expressionS *exp, - enum expr_mode mode, char *cp, - segT (*operandf) (expressionS *, enum expr_mode)) -{ - static int parsing_datalabel = 0; - - if (strcasecmp (name, "datalabel") == 0) - { - int save_parsing_datalabel = parsing_datalabel; - - if (parsing_datalabel) - as_bad (_("duplicate datalabel operator ignored")); - - *input_line_pointer = *cp; - parsing_datalabel = 1; - (*operandf) (exp, expr_normal); - parsing_datalabel = save_parsing_datalabel; - - if (exp->X_op == O_symbol || exp->X_op == O_PIC_reloc) - { - symbolS *symp = exp->X_add_symbol; - segT symseg = S_GET_SEGMENT (symp); - - /* If the symbol is defined to something that is already a - datalabel, we don't need to bother with any special handling. */ - if (symseg != undefined_section - && S_GET_OTHER (symp) != STO_SH5_ISA32) - /* Do nothing. */ - ; - else - { - symbolS *dl_symp; - const char * sname = S_GET_NAME (symp); - char *dl_name = concat (sname, DATALABEL_SUFFIX, (char *) NULL); - - /* Now we copy the datalabel-qualified symbol into a symbol - with the same name, but with " DL" appended. We mark the - symbol using the TC_SYMFIELD_TYPE field with a pointer to - the main symbol, so we don't have to inspect all symbol - names. Note that use of "datalabel" is not expected to - be a common case. */ - - /* A FAKE_LABEL_NAME marks "$" or ".". There can be any - number of them and all have the same (faked) name; we - must make a new one each time. */ - if (strcmp (sname, FAKE_LABEL_NAME) == 0) - dl_symp = symbol_make (dl_name); - else - dl_symp = symbol_find_or_make (dl_name); - - free (dl_name); - symbol_set_value_expression (dl_symp, - symbol_get_value_expression (symp)); - S_SET_SEGMENT (dl_symp, symseg); - symbol_set_frag (dl_symp, symbol_get_frag (symp)); - symbol_set_tc (dl_symp, &symp); - copy_symbol_attributes (dl_symp, symp); - exp->X_add_symbol = dl_symp; - - /* Unset the BranchTarget mark that can be set at symbol - creation or attributes copying. */ - S_SET_OTHER (dl_symp, S_GET_OTHER (dl_symp) & ~STO_SH5_ISA32); - - /* The GLOBAL and WEAK attributes are not copied over by - copy_symbol_attributes. Do it here. */ - if (S_IS_WEAK (symp)) - S_SET_WEAK (dl_symp); - else if (S_IS_EXTERNAL (symp)) - S_SET_EXTERNAL (dl_symp); - } - } - /* Complain about other types of operands than symbol, unless they - have already been complained about. A constant is always a - datalabel. Removing the low bit would therefore be wrong. - Complaining about it would also be wrong. */ - else if (exp->X_op != O_illegal - && exp->X_op != O_absent - && exp->X_op != O_constant) - as_bad (_("Invalid DataLabel expression")); - - *cp = *input_line_pointer; - - return 1; - } - - return sh_parse_name (name, exp, mode, cp); -} - -/* This function is called just before symbols are being output. It - returns zero when a symbol must be output, non-zero otherwise. - Datalabel references that were fully resolved to local symbols are not - necessary to output. We also do not want to output undefined symbols - that are not used in relocs. For symbols that are used in a reloc, it - does not matter what we set here. If it is *not* used in a reloc, then - it was probably the datalabel counterpart that was used in a reloc; - then we need not output the main symbol. */ - -int -sh64_exclude_symbol (symbolS *symp) -{ - symbolS *main_symbol = *symbol_get_tc (symp); - - return main_symbol != NULL || ! S_IS_DEFINED (symp); -} - -/* If we haven't seen an insn since the last update, and location - indicators have moved (a new frag, new location within frag) we have - emitted data, so change contents type to data. Forget that we have - seen a sequence of insns and store the current location so we can mark - a new region if needed. */ - -static void -sh64_update_contents_mark (bfd_boolean update_type) -{ - segment_info_type *seginfo; - seginfo = seg_info (now_seg); - - if (seginfo != NULL) - { - symbolS *symp = seginfo->tc_segment_info_data.last_contents_mark; - - if (symp == NULL) - { - symp = symbol_new (FAKE_LABEL_NAME, now_seg, - (valueT) frag_now_fix (), frag_now); - seginfo->tc_segment_info_data.last_contents_mark = symp; - } - else - { - /* If we have moved location since last flush, we need to emit a - data range. The previous contents type ended at the location - of the last update. */ - if ((S_GET_VALUE (symp) != frag_now_fix () - || symbol_get_frag (symp) != frag_now)) - { - enum sh64_elf_cr_type contents_type - = seginfo->tc_segment_info_data.contents_type; - - if (update_type - && contents_type != CRT_DATA - && contents_type != CRT_NONE - && ! seen_insn) - { - sh64_set_contents_type (CRT_DATA); - symp = seginfo->tc_segment_info_data.last_contents_mark; - } - - /* If the symbol wasn't used up to make up a new range - descriptor, update it to this new location. */ - if (symp) - { - S_SET_VALUE (symp, (valueT) frag_now_fix ()); - symbol_set_frag (symp, frag_now); - } - } - } - } - - seen_insn = FALSE; -} - -/* Called when the assembler is about to output some data, or maybe it's - just switching segments. */ - -void -sh64_flush_pending_output (void) -{ - sh64_update_contents_mark (TRUE); - sh_flush_pending_output (); -} - -/* Flush out the last crange descriptor after all insns have been emitted. */ - -static void -sh64_flush_last_crange (bfd *abfd ATTRIBUTE_UNUSED, asection *seg, - void *countparg ATTRIBUTE_UNUSED) -{ - segment_info_type *seginfo; - - seginfo = seg_info (seg); - - if (seginfo - /* Only emit .cranges descriptors if we would make it more than one. */ - && seginfo->tc_segment_info_data.emitted_ranges != 0) - { - symbolS *symp; - - /* We need a closing symbol, so switch to the indicated section and - emit it. */ - - /* Change to the section we're about to handle. */ - subseg_set (seg, seginfo->tc_segment_info_data.mode_start_subseg); - - symp = symbol_new (FAKE_LABEL_NAME, now_seg, (valueT) frag_now_fix (), - frag_now); - - /* We'll be making a datalabel reference to it, so remove any code - flag. */ - S_SET_OTHER (symp, S_GET_OTHER (symp) & ~STO_SH5_ISA32); - - sh64_emit_crange (seginfo->tc_segment_info_data.mode_start_symbol, - symp, - seginfo->tc_segment_info_data.contents_type); - } -} - -/* If and only if we see a call to md_number_to_chars without flagging the - start of an insn, we set the contents type to CRT_DATA, and only when - in SHmedia mode. Note that by default we don't bother changing when - going from SHcompact to data, as the constant pools in GCC-generated - SHcompact code would create an inordinate amount of .cranges - descriptors. */ - -static void -sh64_flag_output (void) -{ - if (sh64_isa_mode != sh64_isa_unspecified - && !seen_insn - && !sh64_end_of_assembly - && !emitting_crange) - { - md_flush_pending_output (); - sh64_set_contents_type (CRT_DATA); - } -} - -/* Vtables don't need "datalabel" but we allow it by simply deleting - any we find. */ - -static char * -strip_datalabels (void) -{ - char *src, *dest, *start=input_line_pointer; - - for (src=input_line_pointer, dest=input_line_pointer; *src != '\n'; ) - { - if (strncasecmp (src, "datalabel", 9) == 0 - && ISSPACE (src[9]) - && (src == start || !(ISALNUM (src[-1])) || src[-1] == '_')) - src += 10; - else - *dest++ = *src++; - } - - if (dest < src) - *dest = '\n'; - return src + 1; -} - -static void -sh64_vtable_entry (int ignore ATTRIBUTE_UNUSED) -{ - char *eol = strip_datalabels (); - - obj_elf_vtable_entry (0); - input_line_pointer = eol; -} - -static void -sh64_vtable_inherit (int ignore ATTRIBUTE_UNUSED) -{ - char *eol = strip_datalabels (); - - obj_elf_vtable_inherit (0); - input_line_pointer = eol; -} - -int -sh64_fake_label (const char *name) -{ - size_t len; - - if (strcmp (name, FAKE_LABEL_NAME) == 0) - return 1; - - len = strlen (name); - if (len >= (sizeof (DATALABEL_SUFFIX) - 1)) - return strcmp (&name [len - sizeof (DATALABEL_SUFFIX) + 1], - DATALABEL_SUFFIX) == 0; - - return 0; -} diff --git a/gas/config/tc-sh64.h b/gas/config/tc-sh64.h deleted file mode 100644 index 66b86f1..0000000 --- a/gas/config/tc-sh64.h +++ /dev/null @@ -1,226 +0,0 @@ -/* This file is tc-sh64.h - Copyright (C) 2000-2018 Free Software Foundation, Inc. - - This file is part of GAS, the GNU Assembler. - - GAS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - GAS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GAS; see the file COPYING. If not, write to - the Free Software Foundation, 51 Franklin Street - Fifth Floor, - Boston, MA 02110-1301, USA. */ - -#define TC_SH64 -#include "config/tc-sh.h" -#include "elf/sh.h" -#include "elf32-sh64.h" - -/* We need to override the tc-sh.h settings of HANDLE_ALIGN and - MAX_MEM_FOR_RS_ALIGN_CODE; we might need to put in SHmedia NOP:s, not - SHcompact NOP:s. */ -#undef HANDLE_ALIGN -#define HANDLE_ALIGN(frag) sh64_handle_align (frag) -extern void sh64_handle_align (fragS *); - -#undef MAX_MEM_FOR_RS_ALIGN_CODE -#define MAX_MEM_FOR_RS_ALIGN_CODE sh64_max_mem_for_rs_align_code () -extern int sh64_max_mem_for_rs_align_code (void); - -#undef LISTING_HEADER -#define LISTING_HEADER \ - (target_big_endian ? \ - "SuperH SHcompact/SHmedia Big Endian GAS" \ - : "SuperH SHcompact/SHmedia Little Endian GAS") - -/* We need to record the new frag position after an .align. */ -extern void sh64_do_align (int, const char *, int, int); -#define md_do_align(n, fill, len, max, l) \ - do { sh64_do_align (n, fill, len, max); goto l; } while (0) - -struct sh64_segment_info_type -{ - /* The type of the section is initialized when the range_start_symbol - member is non-NULL. */ - symbolS *mode_start_symbol; - subsegT mode_start_subseg; - - /* A stored symbol indicating location of last call of - "md_flush_pending_output". It is NULLed when we actually use it; - otherwise the contents is just filled in with segment, frag and - offset within frag. */ - symbolS *last_contents_mark; - - unsigned int emitted_ranges; - enum sh64_elf_cr_type contents_type; - - /* This is used by the SH1-4 parts; we set it to 0 for SHmedia code and - data. */ - unsigned int in_code : 1; -}; - -#undef TC_SEGMENT_INFO_TYPE -#define TC_SEGMENT_INFO_TYPE struct sh64_segment_info_type - -#undef TARGET_FORMAT -#define TARGET_FORMAT sh64_target_format () -extern const char *sh64_target_format (void); - -#define TARGET_MACH sh64_target_mach () -extern int sh64_target_mach (void); - -#undef TC_FORCE_RELOCATION_LOCAL -#define TC_FORCE_RELOCATION_LOCAL(FIX) \ - (GENERIC_FORCE_RELOCATION_LOCAL (FIX) \ - || (FIX)->fx_r_type == BFD_RELOC_32_PLT_PCREL \ - || (FIX)->fx_r_type == BFD_RELOC_SH_PLT_LOW16 \ - || (FIX)->fx_r_type == BFD_RELOC_SH_PLT_MEDLOW16 \ - || (FIX)->fx_r_type == BFD_RELOC_SH_PLT_MEDHI16 \ - || (FIX)->fx_r_type == BFD_RELOC_SH_PLT_HI16 \ - || (FIX)->fx_r_type == BFD_RELOC_32_GOT_PCREL \ - || (FIX)->fx_r_type == BFD_RELOC_SH_GOT_LOW16 \ - || (FIX)->fx_r_type == BFD_RELOC_SH_GOT_MEDLOW16 \ - || (FIX)->fx_r_type == BFD_RELOC_SH_GOT_MEDHI16 \ - || (FIX)->fx_r_type == BFD_RELOC_SH_GOT_HI16 \ - || (FIX)->fx_r_type == BFD_RELOC_SH_GOT10BY4 \ - || (FIX)->fx_r_type == BFD_RELOC_SH_GOT10BY8 \ - || (FIX)->fx_r_type == BFD_RELOC_SH_GOTPLT32 \ - || (FIX)->fx_r_type == BFD_RELOC_SH_GOTPLT_LOW16 \ - || (FIX)->fx_r_type == BFD_RELOC_SH_GOTPLT_MEDLOW16 \ - || (FIX)->fx_r_type == BFD_RELOC_SH_GOTPLT_MEDHI16 \ - || (FIX)->fx_r_type == BFD_RELOC_SH_GOTPLT_HI16 \ - || (FIX)->fx_r_type == BFD_RELOC_SH_GOTPLT10BY4 \ - || (FIX)->fx_r_type == BFD_RELOC_SH_GOTPLT10BY8 \ - || (FIX)->fx_r_type == BFD_RELOC_SH_GOTPC \ - || (FIX)->fx_r_type == BFD_RELOC_SH_GOTPC_LOW16 \ - || (FIX)->fx_r_type == BFD_RELOC_SH_GOTPC_MEDLOW16 \ - || (FIX)->fx_r_type == BFD_RELOC_SH_GOTPC_MEDHI16 \ - || (FIX)->fx_r_type == BFD_RELOC_SH_GOTPC_HI16) - -#undef TC_FORCE_RELOCATION_SUB_SAME -#define TC_FORCE_RELOCATION_SUB_SAME(FIX, SEC) \ - (GENERIC_FORCE_RELOCATION_SUB_SAME (FIX, SEC) \ - || TC_FORCE_RELOCATION (FIX) \ - || (sh_relax && SWITCH_TABLE (FIX)) \ - || *symbol_get_tc ((FIX)->fx_addsy) != NULL) - -/* Don't complain when we leave fx_subsy around. */ -#undef TC_VALIDATE_FIX_SUB -#define TC_VALIDATE_FIX_SUB(FIX, SEG) \ - ((md_register_arithmetic || (SEG) != reg_section) \ - && ((FIX)->fx_r_type == BFD_RELOC_32_PLT_PCREL \ - || (sh_relax && SWITCH_TABLE (FIX)) \ - || *symbol_get_tc ((FIX)->fx_addsy) != NULL)) - -/* Note the kludge: we want to put back C, and we also want to consume the - expression, since we have handled it ourselves. FIXME: What we really - need is a new GAS infrastructure feature: md_qualifier. */ -#undef md_parse_name -#define md_parse_name(NAME, EXP, MODE, CP) \ - sh64_consume_datalabel (NAME, EXP, MODE, CP, operand) -extern int sh64_consume_datalabel (const char *, expressionS *, - enum expr_mode, char *, - segT (*) (expressionS *, enum expr_mode)); - -/* Saying "$" is the same as saying ".". */ -#define DOLLAR_DOT - -#undef MD_PCREL_FROM_SECTION -#define MD_PCREL_FROM_SECTION(FIX, SEC) \ - shmedia_md_pcrel_from_section (FIX, SEC) - -extern valueT shmedia_md_pcrel_from_section (struct fix *, segT); - -/* We need to mark this symbol as a BranchTarget; setting st_other for it - and adding 1 to its value (temporarily). */ -extern void sh64_frob_label (symbolS *); - -#undef tc_frob_label -#define tc_frob_label(sym) \ - do { sh_frob_label (sym); sh64_frob_label (sym); } while (0) - -#define tc_symbol_new_hook(s) sh64_frob_label (s) - -/* We use this to mark our "datalabel" symbol copies. The "mark" is NULL - for an ordinary symbol, and the pointer to the "ordinary" symbol for a - datalabel symbol. */ -#define TC_SYMFIELD_TYPE symbolS * - -#define tc_frob_symbol(symp, punt) \ - do \ - { \ - punt = sh64_exclude_symbol (symp); \ - } \ - while (0) - -extern int sh64_exclude_symbol (symbolS *); - -extern void sh64_adjust_symtab (void); -#define tc_adjust_symtab sh64_adjust_symtab - -#undef md_flush_pending_output -#define md_flush_pending_output() sh64_flush_pending_output () -extern void sh64_flush_pending_output (void); - -/* Note that tc-sh.c has a sh_frob_section, but it's called from - tc_frob_file_before_adjust. */ -#define tc_frob_section(sec) shmedia_frob_section_type (sec) -extern void shmedia_frob_section_type (asection *); - -/* We need to emit fixups relative to the frag in which the instruction - resides. Safest way without calculating max fragment growth or making - it a fixed number is to provide a pointer to the opcode frag. - - We also need to emit the right NOP pattern in .align frags. This is - done after the text-to-bits assembly pass, so we need to mark it with - the ISA setting at the time the .align was assembled. */ -#define TC_FRAG_TYPE struct sh64_tc_frag_data - -enum sh64_isa_values - { - sh64_isa_unspecified, - sh64_isa_shcompact, - sh64_isa_shmedia, - - /* Special guard value used in contexts when we don't know which ISA it - is, just that it's specified (not sh64_isa_unspecified). */ - sh64_isa_sh5_guard - }; - -struct sh64_tc_frag_data -{ - fragS *opc_frag; - enum sh64_isa_values isa; -}; - -extern enum sh64_isa_values sh64_isa_mode; - -#define TC_FRAG_INIT(FRAGP) \ - do \ - { \ - (FRAGP)->tc_frag_data.opc_frag = sh64_last_insn_frag; \ - (FRAGP)->tc_frag_data.isa = sh64_isa_mode; \ - } \ - while (0) - -/* This variable is set whenever we generate (or grow) a new opcode frag - in shmedia_build_Mytes. */ -extern fragS *sh64_last_insn_frag; - -#define md_end() shmedia_md_end () -void shmedia_md_end (void); - -/* Because we make .debug_line hold the SHmedia instruction address | 1, - we have to say we only have minimum byte-size insns. */ -#undef DWARF2_LINE_MIN_INSN_LENGTH -#define DWARF2_LINE_MIN_INSN_LENGTH 1 - -#define TC_FAKE_LABEL(NAME) sh64_fake_label(NAME) -extern int sh64_fake_label (const char *); |