* [PATCH 1/3] bfd: Add support for nanoMIPS architecture
[not found] <20220429155813.388328-1-aleksandar.rikalo@syrmia.com>
@ 2022-04-29 15:58 ` Aleksandar Rikalo
2022-05-01 22:56 ` Maciej W. Rozycki
2022-04-29 15:58 ` [PATCH 2/3] sim: Add nanoMIPS port Aleksandar Rikalo
2022-04-29 15:58 ` [PATCH 3/3] gdb: " Aleksandar Rikalo
2 siblings, 1 reply; 14+ messages in thread
From: Aleksandar Rikalo @ 2022-04-29 15:58 UTC (permalink / raw)
To: gdb-patches
Co-Authored-By: Jaydeep Patil <jaydeep.patil@imgtec.com>
Co-Authored-By: Matthew Fortune <matthew.fortune@imgtec.com>
Co-Authored-By: Maciej W. Rozycki <macro@mips.com>
Co-Authored-By: Stefan Markovic <stefan.markovic@mips.com>
Co-Authored-By: Sara Graovac <sara.graovac@syrmia.com>
Co-Authored-By: Dragan Mladjenovic <dragan.mladjenovic@syrmia.com>
---
bfd/Makefile.am | 19 +
bfd/Makefile.in | 22 +
bfd/archures.c | 5 +
bfd/bfd-in2.h | 74 ++
bfd/config.bfd | 6 +
bfd/configure | 4 +
bfd/configure.ac | 4 +
bfd/cpu-nanomips.c | 61 ++
bfd/elf-bfd.h | 1 +
bfd/elfnn-nanomips.c | 1558 ++++++++++++++++++++++++++++++++++++
bfd/elfxx-mips.h | 5 +
bfd/elfxx-nanomips.c | 825 +++++++++++++++++++
bfd/elfxx-nanomips.h | 54 ++
bfd/libbfd.h | 69 ++
bfd/reloc.c | 140 ++++
bfd/targets.c | 11 +
binutils/readelf.c | 523 ++++++++++++
include/dis-asm.h | 15 +
include/elf/common.h | 1 +
include/elf/mips-common.h | 41 +
include/elf/nanomips.h | 260 ++++++
include/opcode/nanomips.h | 1453 +++++++++++++++++++++++++++++++++
opcodes/ChangeLog | 17 +
opcodes/Makefile.am | 8 +
opcodes/Makefile.in | 10 +
opcodes/configure | 1 +
opcodes/configure.ac | 1 +
opcodes/dis-buf.c | 9 +
opcodes/dis-init.c | 1 +
opcodes/disassemble.c | 13 +
opcodes/nanomips-dis.c | 1505 ++++++++++++++++++++++++++++++++++
opcodes/nanomips-formats.h | 265 ++++++
opcodes/nanomips-opc.c | 1073 +++++++++++++++++++++++++
33 files changed, 8054 insertions(+)
create mode 100644 bfd/cpu-nanomips.c
create mode 100644 bfd/elfnn-nanomips.c
create mode 100644 bfd/elfxx-nanomips.c
create mode 100644 bfd/elfxx-nanomips.h
create mode 100644 include/elf/mips-common.h
create mode 100644 include/elf/nanomips.h
create mode 100644 include/opcode/nanomips.h
create mode 100644 opcodes/nanomips-dis.c
create mode 100644 opcodes/nanomips-formats.h
create mode 100644 opcodes/nanomips-opc.c
diff --git a/bfd/Makefile.am b/bfd/Makefile.am
index f2f70590e88..f2d951c2124 100644
--- a/bfd/Makefile.am
+++ b/bfd/Makefile.am
@@ -142,6 +142,7 @@ ALL_MACHINES = \
cpu-moxie.lo \
cpu-msp430.lo \
cpu-mt.lo \
+ cpu-nanomips.lo \
cpu-nds32.lo \
cpu-nfp.lo \
cpu-nios2.lo \
@@ -545,6 +546,7 @@ BFD64_BACKENDS = \
coff64-rs6000.lo \
elf32-ia64.lo \
elf32-mips.lo \
+ elf32-nanomips.lo \
elf32-score.lo \
elf32-score7.lo \
elf64-alpha.lo \
@@ -562,6 +564,8 @@ BFD64_BACKENDS = \
elfxx-mips.lo \
elf64-mmix.lo \
elf64-nfp.lo \
+ elf64-nanomips.lo \
+ elfxx-nanomips.lo \
elf64-ppc.lo \
elf32-riscv.lo \
elf64-riscv.lo \
@@ -602,6 +606,7 @@ BFD64_BACKENDS_CFILES = \
elf64-mips.c \
elf64-mmix.c \
elf64-nfp.c \
+ elf64-nanomips.c \
elf64-ppc.c \
elf64-s390.c \
elf64-sparc.c \
@@ -615,6 +620,7 @@ BFD64_BACKENDS_CFILES = \
elfxx-ia64.c \
elfxx-loongarch.c \
elfxx-mips.c \
+ elfxx-nanomips.c \
elfxx-riscv.c \
mach-o-aarch64.c \
mach-o-x86-64.c \
@@ -681,6 +687,7 @@ BUILD_CFILES = \
elf32-ia64.c elf64-ia64.c \
elf32-loongarch.c elf64-loongarch.c \
elf32-riscv.c elf64-riscv.c \
+ elf32-nanomips.c elf64-nanomips.c \
peigen.c pepigen.c pex64igen.c pe-aarch64igen.c
CFILES = $(SOURCE_CFILES) $(BUILD_CFILES)
@@ -898,6 +905,18 @@ pe-aarch64igen.c: peXXigen.c
$(AM_V_at)echo "#line 1 \"peXXigen.c\"" > $@
$(AM_V_GEN)$(SED) -e s/XX/peAArch64/g < $< >> $@
+elf32-nanomips.c : elfnn-nanomips.c
+ rm -f elf32-nanomips.c
+ echo "#line 1 \"$(srcdir)/elfnn-nanomips.c\"" > elf32-nanomips.new
+ sed -e s/NN/32/g < $(srcdir)/elfnn-nanomips.c >> elf32-nanomips.new
+ mv -f elf32-nanomips.new elf32-nanomips.c
+
+elf64-nanomips.c : elfnn-nanomips.c
+ rm -f elf64-nanomips.c
+ echo "#line 1 \"$(srcdir)/elfnn-nanomips.c\"" > elf64-nanomips.new
+ sed -e s/NN/64/g < $(srcdir)/elfnn-nanomips.c >> elf64-nanomips.new
+ mv -f elf64-nanomips.new elf64-nanomips.c
+
host-aout.lo: Makefile
# The following program can be used to generate a simple config file
diff --git a/bfd/Makefile.in b/bfd/Makefile.in
index 3068560c48b..2e30994c6f2 100644
--- a/bfd/Makefile.in
+++ b/bfd/Makefile.in
@@ -609,6 +609,7 @@ ALL_MACHINES = \
cpu-moxie.lo \
cpu-msp430.lo \
cpu-mt.lo \
+ cpu-nanomips.lo \
cpu-nds32.lo \
cpu-nfp.lo \
cpu-nios2.lo \
@@ -1014,6 +1015,7 @@ BFD64_BACKENDS = \
coff64-rs6000.lo \
elf32-ia64.lo \
elf32-mips.lo \
+ elf32-nanomips.lo \
elf32-score.lo \
elf32-score7.lo \
elf64-alpha.lo \
@@ -1031,6 +1033,8 @@ BFD64_BACKENDS = \
elfxx-mips.lo \
elf64-mmix.lo \
elf64-nfp.lo \
+ elf64-nanomips.lo \
+ elfxx-nanomips.lo \
elf64-ppc.lo \
elf32-riscv.lo \
elf64-riscv.lo \
@@ -1071,6 +1075,7 @@ BFD64_BACKENDS_CFILES = \
elf64-mips.c \
elf64-mmix.c \
elf64-nfp.c \
+ elf64-nanomips.c \
elf64-ppc.c \
elf64-s390.c \
elf64-sparc.c \
@@ -1084,6 +1089,7 @@ BFD64_BACKENDS_CFILES = \
elfxx-ia64.c \
elfxx-loongarch.c \
elfxx-mips.c \
+ elfxx-nanomips.c \
elfxx-riscv.c \
mach-o-aarch64.c \
mach-o-x86-64.c \
@@ -1149,6 +1155,7 @@ BUILD_CFILES = \
elf32-ia64.c elf64-ia64.c \
elf32-loongarch.c elf64-loongarch.c \
elf32-riscv.c elf64-riscv.c \
+ elf32-nanomips.c elf64-nanomips.c \
peigen.c pepigen.c pex64igen.c pe-aarch64igen.c
CFILES = $(SOURCE_CFILES) $(BUILD_CFILES)
@@ -1614,6 +1621,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-moxie.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-msp430.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-mt.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-nanomips.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-nds32.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-nios2.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-or1k.Plo@am__quote@
@@ -1655,6 +1663,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-mips.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-mmix.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-nfp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-nanomips.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-ppc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-riscv.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-s390.Plo@am__quote@
@@ -1668,6 +1677,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-ia64.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-loongarch.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-mips.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-nanomips.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-riscv.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-sparc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-tilegx.Plo@am__quote@
@@ -2413,6 +2423,18 @@ pe-aarch64igen.c: peXXigen.c
$(AM_V_at)echo "#line 1 \"peXXigen.c\"" > $@
$(AM_V_GEN)$(SED) -e s/XX/peAArch64/g < $< >> $@
+elf32-nanomips.c : elfnn-nanomips.c
+ rm -f elf32-nanomips.c
+ echo "#line 1 \"$(srcdir)/elfnn-nanomips.c\"" > elf32-nanomips.new
+ sed -e s/NN/32/g < $(srcdir)/elfnn-nanomips.c >> elf32-nanomips.new
+ mv -f elf32-nanomips.new elf32-nanomips.c
+
+elf64-nanomips.c : elfnn-nanomips.c
+ rm -f elf64-nanomips.c
+ echo "#line 1 \"$(srcdir)/elfnn-nanomips.c\"" > elf64-nanomips.new
+ sed -e s/NN/64/g < $(srcdir)/elfnn-nanomips.c >> elf64-nanomips.new
+ mv -f elf64-nanomips.new elf64-nanomips.c
+
host-aout.lo: Makefile
# The following program can be used to generate a simple config file
diff --git a/bfd/archures.c b/bfd/archures.c
index bcd2b1cf48b..fa806db0afd 100644
--- a/bfd/archures.c
+++ b/bfd/archures.c
@@ -566,6 +566,9 @@ DESCRIPTION
.#define bfd_mach_amdgcn_gfx1030 0x036
.#define bfd_mach_amdgcn_gfx1031 0x037
.#define bfd_mach_amdgcn_gfx1032 0x038
+. bfd_arch_nanomips, {* nanoMIPS. *}
+.#define bfd_mach_nanomipsisa32r6 32
+.#define bfd_mach_nanomipsisa64r6 64
. bfd_arch_last
. };
*/
@@ -666,6 +669,7 @@ extern const bfd_arch_info_type bfd_moxie_arch;
extern const bfd_arch_info_type bfd_ft32_arch;
extern const bfd_arch_info_type bfd_msp430_arch;
extern const bfd_arch_info_type bfd_mt_arch;
+extern const bfd_arch_info_type bfd_nanomips_arch;
extern const bfd_arch_info_type bfd_nds32_arch;
extern const bfd_arch_info_type bfd_nfp_arch;
extern const bfd_arch_info_type bfd_nios2_arch;
@@ -755,6 +759,7 @@ static const bfd_arch_info_type * const bfd_archures_list[] =
&bfd_ft32_arch,
&bfd_msp430_arch,
&bfd_mt_arch,
+ &bfd_nanomips_arch,
&bfd_nds32_arch,
&bfd_nfp_arch,
&bfd_nios2_arch,
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 50e26fc691d..eab3afdbde7 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1927,6 +1927,9 @@ enum bfd_architecture
#define bfd_mach_amdgcn_gfx1030 0x036
#define bfd_mach_amdgcn_gfx1031 0x037
#define bfd_mach_amdgcn_gfx1032 0x038
+ bfd_arch_nanomips, /* nanoMIPS. */
+#define bfd_mach_nanomipsisa32r6 32
+#define bfd_mach_nanomipsisa64r6 64
bfd_arch_last
};
@@ -2664,6 +2667,77 @@ to compensate for the borrow when the low bits are added. */
BFD_RELOC_MIPS_JUMP_SLOT,
+/* nanoMIPS relocations */
+ BFD_RELOC_NANOMIPS_HI20,
+ BFD_RELOC_NANOMIPS_LO12,
+ BFD_RELOC_NANOMIPS_LO4_S2,
+ BFD_RELOC_NANOMIPS_IMM16,
+ BFD_RELOC_NANOMIPS_NEG12,
+ BFD_RELOC_NANOMIPS_GPREL7_S2,
+ BFD_RELOC_NANOMIPS_GPREL18,
+ BFD_RELOC_NANOMIPS_GPREL19_S2,
+ BFD_RELOC_NANOMIPS_GPREL16_S2,
+ BFD_RELOC_NANOMIPS_GPREL18_S3,
+ BFD_RELOC_NANOMIPS_4_PCREL_S1,
+ BFD_RELOC_NANOMIPS_7_PCREL_S1,
+ BFD_RELOC_NANOMIPS_10_PCREL_S1,
+ BFD_RELOC_NANOMIPS_11_PCREL_S1,
+ BFD_RELOC_NANOMIPS_14_PCREL_S1,
+ BFD_RELOC_NANOMIPS_21_PCREL_S1,
+ BFD_RELOC_NANOMIPS_25_PCREL_S1,
+ BFD_RELOC_NANOMIPS_PCREL_HI20,
+ BFD_RELOC_NANOMIPS_GOT_CALL,
+ BFD_RELOC_NANOMIPS_GOTPC_HI20,
+ BFD_RELOC_NANOMIPS_GOTPC_I32,
+ BFD_RELOC_NANOMIPS_GOT_LO12,
+ BFD_RELOC_NANOMIPS_GOT_DISP,
+ BFD_RELOC_NANOMIPS_GOT_PAGE,
+ BFD_RELOC_NANOMIPS_GOT_OFST,
+ BFD_RELOC_NANOMIPS_I32,
+ BFD_RELOC_NANOMIPS_GPREL_HI20,
+ BFD_RELOC_NANOMIPS_GPREL_LO12,
+ BFD_RELOC_NANOMIPS_TLS_GD,
+ BFD_RELOC_NANOMIPS_TLS_GD_I32,
+ BFD_RELOC_NANOMIPS_TLS_LD,
+ BFD_RELOC_NANOMIPS_TLS_LD_I32,
+ BFD_RELOC_NANOMIPS_TLS_DTPREL12,
+ BFD_RELOC_NANOMIPS_TLS_DTPREL16,
+ BFD_RELOC_NANOMIPS_TLS_DTPREL_I32,
+ BFD_RELOC_NANOMIPS_TLS_GOTTPREL,
+ BFD_RELOC_NANOMIPS_TLS_GOTTPREL_PC_I32,
+ BFD_RELOC_NANOMIPS_TLS_TPREL12,
+ BFD_RELOC_NANOMIPS_TLS_TPREL16,
+ BFD_RELOC_NANOMIPS_TLS_TPREL_I32,
+ BFD_RELOC_NANOMIPS_TLS_DTPMOD,
+ BFD_RELOC_NANOMIPS_TLS_DTPREL,
+ BFD_RELOC_NANOMIPS_TLS_TPREL,
+ BFD_RELOC_NANOMIPS_PC_I32,
+ BFD_RELOC_NANOMIPS_GPREL_I32,
+ BFD_RELOC_NANOMIPS_GPREL17_S1,
+ BFD_RELOC_NANOMIPS_NEG,
+ BFD_RELOC_NANOMIPS_ASHIFTR_1,
+ BFD_RELOC_NANOMIPS_UNSIGNED_8,
+ BFD_RELOC_NANOMIPS_UNSIGNED_16,
+ BFD_RELOC_NANOMIPS_SIGNED_8,
+ BFD_RELOC_NANOMIPS_SIGNED_16,
+ BFD_RELOC_NANOMIPS_EH,
+ BFD_RELOC_NANOMIPS_JUMP_SLOT,
+ BFD_RELOC_NANOMIPS_ALIGN,
+ BFD_RELOC_NANOMIPS_FILL,
+ BFD_RELOC_NANOMIPS_MAX,
+ BFD_RELOC_NANOMIPS_INSN32,
+ BFD_RELOC_NANOMIPS_INSN16,
+ BFD_RELOC_NANOMIPS_FIXED,
+ BFD_RELOC_NANOMIPS_RELAX,
+ BFD_RELOC_NANOMIPS_NORELAX,
+ BFD_RELOC_NANOMIPS_SAVERESTORE,
+ BFD_RELOC_NANOMIPS_JALR16,
+ BFD_RELOC_NANOMIPS_JALR32,
+ BFD_RELOC_NANOMIPS_COPY,
+ BFD_RELOC_NANOMIPS_SIGNED_9,
+ BFD_RELOC_NANOMIPS_JUMPTABLE_LOAD,
+
+
/* Moxie ELF relocations. */
BFD_RELOC_MOXIE_10_PCREL,
diff --git a/bfd/config.bfd b/bfd/config.bfd
index 5a690742eb3..8b73021f90b 100644
--- a/bfd/config.bfd
+++ b/bfd/config.bfd
@@ -206,6 +206,7 @@ m68*) targ_archs=bfd_m68k_arch ;;
s12z*) targ_archs=bfd_s12z_arch ;;
microblaze*) targ_archs=bfd_microblaze_arch ;;
mips*) targ_archs=bfd_mips_arch ;;
+nanomips*) targ_archs=bfd_nanomips_arch ;;
nds32*) targ_archs=bfd_nds32_arch ;;
nfp) targ_archs=bfd_nfp_arch ;;
nios2*) targ_archs=bfd_nios2_arch ;;
@@ -1002,6 +1003,11 @@ case "${targ}" in
targ_selvecs=msp430_elf32_ti_vec
;;
+ nanomips*-*-elf*)
+ targ_defvec=nanomips_elf32_le_vec
+ targ_selvecs="nanomips_elf32_be_vec nanomips_elf64_be_vec nanomips_elf64_le_vec"
+ ;;
+
nds32*le-*-linux*)
targ_defvec=nds32_elf32_linux_le_vec
targ_selvecs=nds32_elf32_linux_be_vec
diff --git a/bfd/configure b/bfd/configure
index ee2bbe69c87..9bcac2eff58 100755
--- a/bfd/configure
+++ b/bfd/configure
@@ -13509,6 +13509,10 @@ do
msp430_elf32_vec) tb="$tb elf32-msp430.lo elf32.lo $elf" ;;
msp430_elf32_ti_vec) tb="$tb elf32-msp430.lo elf32.lo $elf" ;;
mt_elf32_vec) tb="$tb elf32-mt.lo elf32.lo $elf" ;;
+ nanomips_elf32_be_vec) tb="$tb elf32-nanomips.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo" ;;
+ nanomips_elf32_le_vec) tb="$tb elf32-nanomips.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo" ;;
+ nanomips_elf64_be_vec) tb="$tb elf64-nanomips.lo elf64.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
+ nanomips_elf64_le_vec) tb="$tb elf64-nanomips.lo elf64.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
nds32_elf32_be_vec) tb="$tb elf32-nds32.lo elf32.lo $elf" ;;
nds32_elf32_le_vec) tb="$tb elf32-nds32.lo elf32.lo $elf" ;;
nds32_elf32_linux_be_vec) tb="$tb elf32-nds32.lo elf32.lo $elf" ;;
diff --git a/bfd/configure.ac b/bfd/configure.ac
index 8004c3ef4bf..085054b262b 100644
--- a/bfd/configure.ac
+++ b/bfd/configure.ac
@@ -582,6 +582,10 @@ do
msp430_elf32_vec) tb="$tb elf32-msp430.lo elf32.lo $elf" ;;
msp430_elf32_ti_vec) tb="$tb elf32-msp430.lo elf32.lo $elf" ;;
mt_elf32_vec) tb="$tb elf32-mt.lo elf32.lo $elf" ;;
+ nanomips_elf32_be_vec) tb="$tb elf32-nanomips.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo" ;;
+ nanomips_elf32_le_vec) tb="$tb elf32-nanomips.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo" ;;
+ nanomips_elf64_be_vec) tb="$tb elf64-nanomips.lo elf64.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
+ nanomips_elf64_le_vec) tb="$tb elf64-nanomips.lo elf64.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
nds32_elf32_be_vec) tb="$tb elf32-nds32.lo elf32.lo $elf" ;;
nds32_elf32_le_vec) tb="$tb elf32-nds32.lo elf32.lo $elf" ;;
nds32_elf32_linux_be_vec) tb="$tb elf32-nds32.lo elf32.lo $elf" ;;
diff --git a/bfd/cpu-nanomips.c b/bfd/cpu-nanomips.c
new file mode 100644
index 00000000000..2ee15cf1f35
--- /dev/null
+++ b/bfd/cpu-nanomips.c
@@ -0,0 +1,61 @@
+/* bfd back-end for nanomips support
+ Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+ Written by Faraz Shahbazker <faraz.shahbazker@mips.com>
+
+ This file is part of BFD, the Binary File Descriptor library.
+
+ This program 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 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+
+#define N(BITS_WORD, BITS_ADDR, NUMBER, PRINT, DEFAULT, NEXT) \
+ { \
+ BITS_WORD, /* bits in a word */ \
+ BITS_ADDR, /* bits in an address */ \
+ 8, /* 8 bits in a byte */ \
+ bfd_arch_nanomips, \
+ NUMBER, \
+ "nanomips", \
+ PRINT, \
+ 3, \
+ DEFAULT, \
+ bfd_default_compatible, \
+ bfd_default_scan, \
+ bfd_arch_default_fill, \
+ NEXT, \
+ 0 /* Maximum offset of a reloc from the start of an insn. */ \
+ }
+
+enum
+{
+ I_nanomipsisa32r6,
+ I_nanomipsisa64r6,
+};
+
+#define NN(index) (&arch_info_struct[(index) + 1])
+
+static const bfd_arch_info_type arch_info_struct[] = {
+ N (32, 32, bfd_mach_nanomipsisa32r6, "nanomips:isa32r6", false,
+ NN (I_nanomipsisa32r6)),
+ N (64, 64, bfd_mach_nanomipsisa64r6, "nanomips:isa64r6", false,
+ 0),
+};
+
+const bfd_arch_info_type bfd_nanomips_arch =
+N (32, 32, 0, "nanomips", true, &arch_info_struct[0]);
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index c7c0a793b15..3b7101a41e4 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -520,6 +520,7 @@ enum elf_target_id
MICROBLAZE_ELF_DATA,
MIPS_ELF_DATA,
MN10300_ELF_DATA,
+ NANOMIPS_ELF_DATA,
NDS32_ELF_DATA,
NIOS2_ELF_DATA,
OR1K_ELF_DATA,
diff --git a/bfd/elfnn-nanomips.c b/bfd/elfnn-nanomips.c
new file mode 100644
index 00000000000..ac3d143b27e
--- /dev/null
+++ b/bfd/elfnn-nanomips.c
@@ -0,0 +1,1558 @@
+/* nanoMIPS-specific support for 32-bit ELF
+ Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+ Written by Faraz Shahbazker <faraz.shahbazker@mips.com>
+
+ This file is part of BFD, the Binary File Descriptor library.
+
+ This program 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 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+
+/* This file handles nanoMIPS ELF targets. */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+#include "elfxx-nanomips.h"
+#include "elf/nanomips.h"
+
+#define ARCH_SIZE NN
+
+#if ARCH_SIZE == 32
+/* Nonzero if ABFD is using the P32 ABI. */
+#define ABI_P32_P(abfd) \
+ ((elf_elfheader (abfd)->e_flags & EF_NANOMIPS_ABI) != E_NANOMIPS_ABI_P64)
+#else /* ARCH_SIZE != 32 */
+/* Nonzero if ABFD is using the P64 ABI. */
+#define ABI_P64_P(abfd) \
+ ((elf_elfheader (abfd)->e_flags & EF_NANOMIPS_ABI) != E_NANOMIPS_ABI_P32)
+#endif /* ARCH_SIZE == 32 */
+
+/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
+ from smaller values. Start with zero, widen, *then* decrement. */
+#define MINUS_ONE (((bfd_vma)0) - 1)
+
+/* The relocation table used for SHT_RELA sections. */
+
+static reloc_howto_type elfNN_nanomips_howto_table_rela[] = {
+ /* No relocation. */
+ HOWTO (R_NANOMIPS_NONE, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_NONE", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 32 bit relocation. */
+ HOWTO (R_NANOMIPS_32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_32", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 64 bit relocation. */
+ HOWTO (R_NANOMIPS_64, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_64", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ MINUS_ONE, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Symbol address negation, can be composed for label differences. */
+ HOWTO (R_NANOMIPS_NEG, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_nanomips_elf_negative_reloc, /* special_function */
+ "R_NANOMIPS_NEG", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A 5 bit shift field. */
+ HOWTO (R_NANOMIPS_ASHIFTR_1, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_ASHIFTR_1", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ HOWTO (R_NANOMIPS_UNSIGNED_8, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_UNSIGNED_8", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ HOWTO (R_NANOMIPS_SIGNED_8, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_SIGNED_8", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ HOWTO (R_NANOMIPS_UNSIGNED_16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_UNSIGNED_16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ HOWTO (R_NANOMIPS_SIGNED_16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_SIGNED_16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ EMPTY_HOWTO (R_NANOMIPS_RELATIVE),
+ EMPTY_HOWTO (R_NANOMIPS_GLOBAL),
+
+ /* Lazy resolver jump slot. */
+ HOWTO (R_NANOMIPS_JUMP_SLOT, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_JUMP_SLOT", /* name */
+ false, /* partial_inplace */
+ 0x0, /* src_mask */
+ 0x0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Reserved for IFUNC support. */
+ EMPTY_HOWTO (R_NANOMIPS_IRELATIVE),
+
+ HOWTO (R_NANOMIPS_PC25_S1, /* type */
+ 1, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 25, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_PC25_S1", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x01ffffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_NANOMIPS_PC21_S1, /* type */
+ 1, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 21, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_PC21_S1", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0001ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_NANOMIPS_PC14_S1, /* type */
+ 1, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 14, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_PC14_S1", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x00003fff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_NANOMIPS_PC11_S1, /* type */
+ 1, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 11, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_PC11_S1", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x000007ff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_NANOMIPS_PC10_S1, /* type */
+ 1, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 10, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_PC10_S1", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x000003ff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* This is for nanoMIPS branches. */
+ HOWTO (R_NANOMIPS_PC7_S1, /* type */
+ 1, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 7, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_PC7_S1", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000007f, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_NANOMIPS_PC4_S1, /* type */
+ 1, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 4, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_PC4_S1", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000000f, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* GP relative reference. */
+ HOWTO (R_NANOMIPS_GPREL19_S2, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 19, /* bitsize */
+ false, /* pc_relative */
+ 2, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_GPREL19_S2", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x001ffffc, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* GP relative reference. */
+ HOWTO (R_NANOMIPS_GPREL18_S3, /* type */
+ 3, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 18, /* bitsize */
+ false, /* pc_relative */
+ 3, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_GPREL18_S3", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x001ffff8, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* GP relative reference. */
+ HOWTO (R_NANOMIPS_GPREL18, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 18, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_GPREL18", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0003ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* GP relative reference. */
+ HOWTO (R_NANOMIPS_GPREL17_S1, /* type */
+ 1, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 17, /* bitsize */
+ false, /* pc_relative */
+ 1, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_GPREL17_S1", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0001fffe, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* GP relative reference. */
+ HOWTO (R_NANOMIPS_GPREL16_S2, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 2, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_GPREL16_S2", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0003fffc, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* GP- and PC-relative relocations. */
+ HOWTO (R_NANOMIPS_GPREL7_S2, /* type */
+ 2, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 7, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_GPREL7_S2", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000007f, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* High 20 bits of GP relative reference. */
+ HOWTO (R_NANOMIPS_GPREL_HI20, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 20, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_GPREL_HI20", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x001ffffd, /* dst_mask */
+ false), /* pcrel_offset */
+
+ HOWTO (R_NANOMIPS_PCHI20, /* type */
+ 12, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 20, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_PCHI20", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x001ffffd, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* High 20 bits of symbol value. */
+ HOWTO (R_NANOMIPS_HI20, /* type */
+ 12, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 20, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_HI20", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x001ffffd, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Low 12 bits of symbol value. */
+ HOWTO (R_NANOMIPS_LO12, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 12, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_LO12", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x00000fff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* High 32 bits of 64-bit address. */
+ HOWTO (R_NANOMIPS_GPREL_I32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_GPREL_I32", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* High 32 bits of 64-bit address. */
+ HOWTO (R_NANOMIPS_PC_I32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_PC_I32", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Refers to low 32-bits of 48-bit instruction. The 32-bit value
+ is encoded as nanoMIPS instruction stream - so it will be
+ half-word swapped on little endian targets. */
+ HOWTO (R_NANOMIPS_I32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_I32", /* name */
+ false, /* partial_inplace */
+ 0x0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Displacement in the global offset table. */
+ HOWTO (R_NANOMIPS_GOT_DISP, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 19, /* bitsize */
+ false, /* pc_relative */
+ 2, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_GOT_DISP", /* name */
+ false, /* partial_inplace */
+ 0x0, /* src_mask */
+ 0x001ffffc, /* dst_mask */
+ false), /* pcrel_offset */
+ /* High 32 bits of 64-bit address. */
+ HOWTO (R_NANOMIPS_GOTPC_I32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_GOTPC_I32", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* High 20 bits of PC-relative GOT offset. */
+ HOWTO (R_NANOMIPS_GOTPC_HI20, /* type */
+ 12, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 20, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_GOTPC_HI20", /* name */
+ false, /* partial_inplace */
+ 0x0, /* src_mask */
+ 0x001ffffd, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* Low 12 bits of displacement in global offset table. */
+ HOWTO (R_NANOMIPS_GOT_LO12, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 12, /* bitsize */
+ false, /* pc_relative */
+ 2, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_GOT_LO12", /* name */
+ false, /* partial_inplace */
+ 0x0, /* src_mask */
+ 0x00000fff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* 19 bit call through global offset table. */
+ HOWTO (R_NANOMIPS_GOT_CALL, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 19, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_GOT_CALL", /* name */
+ false, /* partial_inplace */
+ 0x0, /* src_mask */
+ 0x001ffffc, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Displacement to page pointer in the global offset table. */
+ HOWTO (R_NANOMIPS_GOT_PAGE, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 19, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_GOT_PAGE", /* name */
+ false, /* partial_inplace */
+ 0x0, /* src_mask */
+ 0x001ffffc, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Offset from page pointer in the global offset table. */
+ HOWTO (R_NANOMIPS_GOT_OFST, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 12, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_GOT_OFST", /* name */
+ false, /* partial_inplace */
+ 0x0, /* src_mask */
+ 0x00000fff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Low 4 bits of symbol value. */
+ HOWTO (R_NANOMIPS_LO4_S2, /* type */
+ 2, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 4, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_LO4_S2", /* name */
+ false, /* partial_inplace */
+ 0x0000000f, /* src_mask */
+ 0x0000000f, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Reserved for 64-bit ABI, HI32 relocation. */
+ EMPTY_HOWTO (R_NANOMIPS_RESERVED1),
+
+ /* Low 12 bits of GP-relative displacement. */
+ HOWTO (R_NANOMIPS_GPREL_LO12, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 12, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_GPREL_LO12", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x00000fff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Section displacement. */
+ HOWTO (R_NANOMIPS_SCN_DISP, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_SCN_DISP", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Copy relocation. */
+ HOWTO (R_NANOMIPS_COPY, /* type */
+ 0, /* rightshift */
+ 0, /* this one is variable size */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_COPY", /* name */
+ false, /* partial_inplace */
+ 0x0, /* src_mask */
+ 0x0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ EMPTY_HOWTO (45),
+ EMPTY_HOWTO (46),
+ EMPTY_HOWTO (47),
+ EMPTY_HOWTO (48),
+ EMPTY_HOWTO (49),
+ EMPTY_HOWTO (50),
+ EMPTY_HOWTO (51),
+ EMPTY_HOWTO (52),
+ EMPTY_HOWTO (53),
+ EMPTY_HOWTO (54),
+ EMPTY_HOWTO (55),
+ EMPTY_HOWTO (56),
+ EMPTY_HOWTO (57),
+ EMPTY_HOWTO (58),
+ EMPTY_HOWTO (59),
+ EMPTY_HOWTO (60),
+ EMPTY_HOWTO (61),
+ EMPTY_HOWTO (62),
+ EMPTY_HOWTO (63),
+
+ /* Place-holder for code alignment. */
+ HOWTO (R_NANOMIPS_ALIGN, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special handler. */
+ "R_NANOMIPS_ALIGN", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Fill value for code alignment. */
+ HOWTO (R_NANOMIPS_FILL, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special handler. */
+ "R_NANOMIPS_FILL", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Maximum padding bytes for code alignment. */
+ HOWTO (R_NANOMIPS_MAX, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special handler. */
+ "R_NANOMIPS_MAX", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Place-holder to enforce 32-bit instruction encoding. */
+ HOWTO (R_NANOMIPS_INSN32, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special handler. */
+ "R_NANOMIPS_INSN32", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Place-holder to inhibit relaxation on one instruction. */
+ HOWTO (R_NANOMIPS_FIXED, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special handler. */
+ "R_NANOMIPS_FIXED", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Marker to inhibit linker relaxation. */
+ HOWTO (R_NANOMIPS_NORELAX, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special handler. */
+ "R_NANOMIPS_NORELAX", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Marker to enable linker relaxation. */
+ HOWTO (R_NANOMIPS_RELAX, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special handler. */
+ "R_NANOMIPS_RELAX", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Place-holder for relaxation of save/restore instructions. */
+ HOWTO (R_NANOMIPS_SAVERESTORE, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special handler. */
+ "R_NANOMIPS_SAVERESTORE", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Place-holder to enforce 16-bit instruction encoding. */
+ HOWTO (R_NANOMIPS_INSN16, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special handler. */
+ "R_NANOMIPS_INSN16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Place-holder to enforce 32-bit JALR encoding. */
+ HOWTO (R_NANOMIPS_JALR32, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special handler. */
+ "R_NANOMIPS_JALR32", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Place-holder to enforce 16-bit JALR encoding. */
+ HOWTO (R_NANOMIPS_JALR16, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special handler. */
+ "R_NANOMIPS_JALR16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Place-holder for compressed jump-table load instructions. */
+ HOWTO (R_NANOMIPS_JUMPTABLE_LOAD, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special handler */
+ "R_NANOMIPS_JUMPTABLE_LOAD", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Place-holder for relaxing frame-register information. */
+ HOWTO (R_NANOMIPS_FRAME_REG, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special handler */
+ "R_NANOMIPS_FRAME_REG", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+
+ EMPTY_HOWTO (77),
+ EMPTY_HOWTO (78),
+ EMPTY_HOWTO (79),
+
+ /* TLS GD/LD dynamic relocations. */
+ HOWTO (R_NANOMIPS_TLS_DTPMOD, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_TLS_DTPMOD", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ HOWTO (R_NANOMIPS_TLS_DTPREL, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_TLS_DTPREL", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* TLS IE dynamic relocations. */
+ HOWTO (R_NANOMIPS_TLS_TPREL, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_TLS_TPREL", /* name */
+ false, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* TLS general dynamic variable reference. */
+ HOWTO (R_NANOMIPS_TLS_GD, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 19, /* bitsize */
+ false, /* pc_relative */
+ 2, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_TLS_GD", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x001ffffc, /* dst_mask */
+ false), /* pcrel_offset */
+
+ HOWTO (R_NANOMIPS_TLS_GD_I32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_TLS_GD_I32", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* TLS local dynamic variable reference. */
+ HOWTO (R_NANOMIPS_TLS_LD, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 19, /* bitsize */
+ false, /* pc_relative */
+ 2, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_TLS_LD", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x001ffffc, /* dst_mask */
+ false), /* pcrel_offset */
+
+ HOWTO (R_NANOMIPS_TLS_LD_I32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_TLS_LD_I32", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* TLS local dynamic 12-bit offset. */
+ HOWTO (R_NANOMIPS_TLS_DTPREL12, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 12, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_TLS_DTPREL12", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x00000fff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* TLS local dynamic 16-bit offset. */
+ HOWTO (R_NANOMIPS_TLS_DTPREL16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_TLS_DTPREL16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* TLS local dynamic 32-bit offset. */
+ HOWTO (R_NANOMIPS_TLS_DTPREL_I32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_TLS_DTPREL_I32", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* TLS thread pointer 21-bit GOT offset. */
+ HOWTO (R_NANOMIPS_TLS_GOTTPREL, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 19, /* bitsize */
+ false, /* pc_relative */
+ 2, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_TLS_GOTTPREL", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x001ffffc, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* TLS thread pointer 32-bit GOT offset. */
+ HOWTO (R_NANOMIPS_TLS_GOTTPREL_PC_I32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_TLS_GOTTPREL_PC_I32", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* TLS thread pointer 12-bit offset. */
+ HOWTO (R_NANOMIPS_TLS_TPREL12, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 12, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_TLS_TPREL12", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x00000fff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* TLS thread pointer 16-bit offset. */
+ HOWTO (R_NANOMIPS_TLS_TPREL16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_TLS_TPREL16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* TLS thread pointer 32-bit offset. */
+ HOWTO (R_NANOMIPS_TLS_TPREL_I32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_TLS_TPREL_I32", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+};
+
+/* GNU extension to record C++ vtable hierarchy */
+static reloc_howto_type elf_nanomips_gnu_vtinherit_howto =
+ HOWTO (R_NANOMIPS_GNU_VTINHERIT, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ NULL, /* special_function */
+ "R_NANOMIPS_GNU_VTINHERIT", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false); /* pcrel_offset */
+
+/* GNU extension to record C++ vtable member usage */
+static reloc_howto_type elf_nanomips_gnu_vtentry_howto =
+ HOWTO (R_NANOMIPS_GNU_VTENTRY, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_elf_rel_vtable_reloc_fn, /* special_function */
+ "R_NANOMIPS_GNU_VTENTRY", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false); /* pcrel_offset */
+
+/* 32 bit pc-relative. */
+static reloc_howto_type elf_nanomips_gnu_pcrel32 =
+ HOWTO (R_NANOMIPS_PC32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_PC32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ true); /* pcrel_offset */
+
+/* Used in EH tables. */
+static reloc_howto_type elf_nanomips_eh_howto =
+ HOWTO (R_NANOMIPS_EH, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_nanomips_elf_generic_reloc, /* special_function */
+ "R_NANOMIPS_EH", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false); /* pcrel_offset */
+
+/* A mapping from BFD reloc types to nanoMIPS ELF reloc types. */
+
+struct elf_reloc_map
+{
+ bfd_reloc_code_real_type bfd_val;
+ enum elf_nanomips_reloc_type elf_val;
+};
+
+static const struct elf_reloc_map nanomips_reloc_map[] = {
+ { BFD_RELOC_NONE, R_NANOMIPS_NONE },
+ { BFD_RELOC_32, R_NANOMIPS_32 },
+ { BFD_RELOC_64, R_NANOMIPS_64 },
+ { BFD_RELOC_NANOMIPS_NEG, R_NANOMIPS_NEG },
+ { BFD_RELOC_NANOMIPS_ASHIFTR_1, R_NANOMIPS_ASHIFTR_1 },
+ { BFD_RELOC_NANOMIPS_UNSIGNED_8, R_NANOMIPS_UNSIGNED_8 },
+ { BFD_RELOC_NANOMIPS_SIGNED_8, R_NANOMIPS_SIGNED_8 },
+ { BFD_RELOC_NANOMIPS_UNSIGNED_16, R_NANOMIPS_UNSIGNED_16 },
+ { BFD_RELOC_16, R_NANOMIPS_UNSIGNED_16 },
+ { BFD_RELOC_NANOMIPS_SIGNED_16, R_NANOMIPS_SIGNED_16 },
+ { BFD_RELOC_NANOMIPS_HI20, R_NANOMIPS_HI20 },
+ { BFD_RELOC_NANOMIPS_LO12, R_NANOMIPS_LO12 },
+ { BFD_RELOC_NANOMIPS_IMM16, R_NANOMIPS_LO12 },
+ { BFD_RELOC_NANOMIPS_25_PCREL_S1, R_NANOMIPS_PC25_S1 },
+ { BFD_RELOC_NANOMIPS_21_PCREL_S1, R_NANOMIPS_PC21_S1 },
+ { BFD_RELOC_NANOMIPS_14_PCREL_S1, R_NANOMIPS_PC14_S1 },
+ { BFD_RELOC_NANOMIPS_11_PCREL_S1, R_NANOMIPS_PC11_S1 },
+ { BFD_RELOC_NANOMIPS_10_PCREL_S1, R_NANOMIPS_PC10_S1 },
+ { BFD_RELOC_NANOMIPS_7_PCREL_S1, R_NANOMIPS_PC7_S1 },
+ { BFD_RELOC_NANOMIPS_GPREL7_S2, R_NANOMIPS_GPREL7_S2 },
+ { BFD_RELOC_NANOMIPS_GPREL18, R_NANOMIPS_GPREL18 },
+ { BFD_RELOC_NANOMIPS_GPREL19_S2, R_NANOMIPS_GPREL19_S2 },
+ { BFD_RELOC_NANOMIPS_4_PCREL_S1,R_NANOMIPS_PC4_S1 },
+ { BFD_RELOC_NANOMIPS_PCREL_HI20, R_NANOMIPS_PCHI20 },
+ { BFD_RELOC_NANOMIPS_GPREL16_S2, R_NANOMIPS_GPREL16_S2 },
+ { BFD_RELOC_NANOMIPS_GPREL18_S3, R_NANOMIPS_GPREL18_S3 },
+ { BFD_RELOC_NANOMIPS_GOT_CALL, R_NANOMIPS_GOT_CALL },
+ { BFD_RELOC_NANOMIPS_GOT_DISP, R_NANOMIPS_GOT_DISP },
+ { BFD_RELOC_NANOMIPS_GOT_PAGE, R_NANOMIPS_GOT_PAGE },
+ { BFD_RELOC_NANOMIPS_GOT_OFST, R_NANOMIPS_GOT_OFST },
+ { BFD_RELOC_NANOMIPS_GOTPC_HI20, R_NANOMIPS_GOTPC_HI20 },
+ { BFD_RELOC_NANOMIPS_GOT_LO12, R_NANOMIPS_GOT_LO12 },
+ { BFD_RELOC_NANOMIPS_GOTPC_I32, R_NANOMIPS_GOTPC_I32 },
+ { BFD_RELOC_NANOMIPS_I32, R_NANOMIPS_I32 },
+ { BFD_RELOC_NANOMIPS_GPREL_HI20, R_NANOMIPS_GPREL_HI20 },
+ { BFD_RELOC_NANOMIPS_PC_I32, R_NANOMIPS_PC_I32 },
+ { BFD_RELOC_NANOMIPS_GPREL_I32, R_NANOMIPS_GPREL_I32 },
+ { BFD_RELOC_NANOMIPS_GPREL17_S1, R_NANOMIPS_GPREL17_S1 },
+ { BFD_RELOC_NANOMIPS_GPREL_LO12, R_NANOMIPS_GPREL_LO12 },
+ { BFD_RELOC_NANOMIPS_LO4_S2, R_NANOMIPS_LO4_S2 },
+ { BFD_RELOC_NANOMIPS_COPY, R_NANOMIPS_COPY },
+
+ { BFD_RELOC_NANOMIPS_ALIGN, R_NANOMIPS_ALIGN },
+ { BFD_RELOC_NANOMIPS_FILL, R_NANOMIPS_FILL },
+ { BFD_RELOC_NANOMIPS_MAX, R_NANOMIPS_MAX },
+ { BFD_RELOC_NANOMIPS_INSN32, R_NANOMIPS_INSN32 },
+ { BFD_RELOC_NANOMIPS_INSN16, R_NANOMIPS_INSN16 },
+ { BFD_RELOC_NANOMIPS_FIXED, R_NANOMIPS_FIXED },
+ { BFD_RELOC_NANOMIPS_RELAX, R_NANOMIPS_RELAX },
+ { BFD_RELOC_NANOMIPS_NORELAX, R_NANOMIPS_NORELAX },
+ { BFD_RELOC_NANOMIPS_SAVERESTORE, R_NANOMIPS_SAVERESTORE },
+ { BFD_RELOC_NANOMIPS_JALR32, R_NANOMIPS_JALR32 },
+ { BFD_RELOC_NANOMIPS_JALR16, R_NANOMIPS_JALR16 },
+ { BFD_RELOC_NANOMIPS_JUMPTABLE_LOAD, R_NANOMIPS_JUMPTABLE_LOAD },
+
+ { BFD_RELOC_NANOMIPS_TLS_GD, R_NANOMIPS_TLS_GD },
+ { BFD_RELOC_NANOMIPS_TLS_GD_I32, R_NANOMIPS_TLS_GD_I32 },
+ { BFD_RELOC_NANOMIPS_TLS_LD, R_NANOMIPS_TLS_LD },
+ { BFD_RELOC_NANOMIPS_TLS_LD_I32, R_NANOMIPS_TLS_LD_I32 },
+ { BFD_RELOC_NANOMIPS_TLS_DTPREL12, R_NANOMIPS_TLS_DTPREL12 },
+ { BFD_RELOC_NANOMIPS_TLS_DTPREL16, R_NANOMIPS_TLS_DTPREL16 },
+ { BFD_RELOC_NANOMIPS_TLS_DTPREL_I32, R_NANOMIPS_TLS_DTPREL_I32 },
+ { BFD_RELOC_NANOMIPS_TLS_GOTTPREL, R_NANOMIPS_TLS_GOTTPREL },
+ { BFD_RELOC_NANOMIPS_TLS_GOTTPREL_PC_I32, R_NANOMIPS_TLS_GOTTPREL_PC_I32 },
+ { BFD_RELOC_NANOMIPS_TLS_TPREL12, R_NANOMIPS_TLS_TPREL12 },
+ { BFD_RELOC_NANOMIPS_TLS_TPREL16, R_NANOMIPS_TLS_TPREL16 },
+ { BFD_RELOC_NANOMIPS_TLS_TPREL_I32, R_NANOMIPS_TLS_TPREL_I32 },
+ { BFD_RELOC_NANOMIPS_TLS_DTPMOD, R_NANOMIPS_TLS_DTPMOD },
+ { BFD_RELOC_NANOMIPS_TLS_DTPREL, R_NANOMIPS_TLS_DTPREL },
+ { BFD_RELOC_NANOMIPS_TLS_TPREL, R_NANOMIPS_TLS_TPREL },
+};
+
+/* Given a BFD reloc type, return a howto structure. */
+
+static reloc_howto_type *
+bfd_elfNN_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ bfd_reloc_code_real_type code)
+{
+ unsigned int i;
+ reloc_howto_type *howto_nanomips_table;
+
+ howto_nanomips_table = elfNN_nanomips_howto_table_rela;
+
+ for (i = 0; i < sizeof (nanomips_reloc_map) / sizeof (struct elf_reloc_map);
+ i++)
+ {
+ if (nanomips_reloc_map[i].bfd_val == code)
+ return &howto_nanomips_table[(int) nanomips_reloc_map[i].elf_val];
+ }
+
+ switch (code)
+ {
+ default:
+ bfd_set_error (bfd_error_bad_value);
+ return NULL;
+
+ case BFD_RELOC_CTOR:
+ return &howto_nanomips_table[(int) R_NANOMIPS_32];
+
+ case BFD_RELOC_VTABLE_INHERIT:
+ return &elf_nanomips_gnu_vtinherit_howto;
+ case BFD_RELOC_VTABLE_ENTRY:
+ return &elf_nanomips_gnu_vtentry_howto;
+ case BFD_RELOC_NANOMIPS_EH:
+ return &elf_nanomips_eh_howto;
+ case BFD_RELOC_32_PCREL:
+ return &elf_nanomips_gnu_pcrel32;
+ }
+}
+
+/* Map a BFD relocation to its display name. */
+
+static reloc_howto_type *
+bfd_elfNN_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *r_name)
+{
+ unsigned int i;
+
+ for (i = 0;
+ i < (sizeof (elfNN_nanomips_howto_table_rela)
+ / sizeof (elfNN_nanomips_howto_table_rela[0])); i++)
+ if (elfNN_nanomips_howto_table_rela[i].name != NULL
+ && strcasecmp (elfNN_nanomips_howto_table_rela[i].name, r_name) == 0)
+ return &elfNN_nanomips_howto_table_rela[i];
+
+ if (strcasecmp (elf_nanomips_gnu_vtinherit_howto.name, r_name) == 0)
+ return &elf_nanomips_gnu_vtinherit_howto;
+ if (strcasecmp (elf_nanomips_gnu_vtentry_howto.name, r_name) == 0)
+ return &elf_nanomips_gnu_vtentry_howto;
+ if (strcasecmp (elf_nanomips_eh_howto.name, r_name) == 0)
+ return &elf_nanomips_eh_howto;
+
+ return NULL;
+}
+
+/* Given a nanoMIPS Elf_Internal_Rel, fill in an arelent structure. */
+
+static reloc_howto_type *
+nanomips_elfNN_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
+ unsigned int r_type,
+ bool rela_p ATTRIBUTE_UNUSED)
+{
+ switch (r_type)
+ {
+ case R_NANOMIPS_GNU_VTINHERIT:
+ return &elf_nanomips_gnu_vtinherit_howto;
+ case R_NANOMIPS_GNU_VTENTRY:
+ return &elf_nanomips_gnu_vtentry_howto;
+ case R_NANOMIPS_EH:
+ return &elf_nanomips_eh_howto;
+ case R_NANOMIPS_PC32:
+ return &elf_nanomips_gnu_pcrel32;
+ default:
+ return &elfNN_nanomips_howto_table_rela[r_type];
+ }
+}
+
+/* Given a nanoMIPS Elf_Internal_Rela, fill in an arelent structure. */
+
+static bool
+nanomips_info_to_howto_rela (bfd *abfd, arelent *cache_ptr,
+ Elf_Internal_Rela *dst)
+{
+ const struct elf_backend_data *bed;
+ unsigned int r_type;
+
+ r_type = ELFNN_R_TYPE (dst->r_info);
+ bed = get_elf_backend_data (abfd);
+ cache_ptr->howto = bed->elf_backend_mips_rtype_to_howto (abfd, r_type, true);
+ cache_ptr->addend = dst->r_addend;
+ return true;
+}
+\f
+/* nanoMIPS ELF local labels start with '$'. */
+
+static bool
+nanomips_elf_is_local_label_name (bfd *abfd, const char *name)
+{
+ if (name[0] == '$')
+ return true;
+
+ /* Fall back to the generic ELF local label syntax. */
+ return _bfd_elf_is_local_label_name (abfd, name);
+}
+\f
+/* Set the right machine number for a nanoMIPS ELF file. */
+
+static bool
+nanomips_elfNN_object_p (bfd *abfd)
+{
+ unsigned long mach;
+
+ if (!ABI_PNN_P (abfd))
+ return false;
+
+ mach = _bfd_elf_mips_mach (elf_elfheader (abfd)->e_flags);
+ bfd_default_set_arch_mach (abfd, bfd_arch_nanomips, mach);
+ return true;
+}
+\f
+#if ARCH_SIZE == 32
+# define PRSTATUS_SIZE 256
+# define PRSTATUS_OFFSET_PR_CURSIG 12
+# define PRSTATUS_OFFSET_PR_PID 24
+# define PRSTATUS_OFFSET_PR_REG 72
+# define ELF_GREGSET_T_SIZE 180
+# define PRPSINFO_SIZE 128
+# define PRPSINFO_OFFSET_PR_PID 16
+# define PRPSINFO_OFFSET_PR_FNAME 32
+# define PRPSINFO_OFFSET_PR_PSARGS 48
+#else
+# define PRSTATUS_SIZE 480
+# define PRSTATUS_OFFSET_PR_CURSIG 12
+# define PRSTATUS_OFFSET_PR_PID 32
+# define PRSTATUS_OFFSET_PR_REG 112
+# define ELF_GREGSET_T_SIZE 360
+# define PRPSINFO_SIZE 136
+# define PRPSINFO_OFFSET_PR_PID 24
+# define PRPSINFO_OFFSET_PR_FNAME 40
+# define PRPSINFO_OFFSET_PR_PSARGS 56
+#endif
+
+static bool
+nanomips_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
+{
+ size_t size;
+ int offset;
+
+ switch (note->descsz)
+ {
+ default:
+ return false;
+
+ case PRSTATUS_SIZE: /* sizeof(struct elf_prstatus) on Linux/nanoMIPS. */
+ /* pr_cursig */
+ elf_tdata (abfd)->core->signal
+ = bfd_get_16 (abfd, note->descdata + PRSTATUS_OFFSET_PR_CURSIG);
+
+ /* pr_pid */
+ elf_tdata (abfd)->core->lwpid
+ = bfd_get_32 (abfd, note->descdata + PRSTATUS_OFFSET_PR_PID);
+
+ /* pr_reg */
+ offset = PRSTATUS_OFFSET_PR_REG;
+ size = ELF_GREGSET_T_SIZE;
+ break;
+ }
+
+ /* Make a ".reg/999" section. */
+ return _bfd_elfcore_make_pseudosection (abfd, ".reg", size,
+ note->descpos + offset);
+}
+
+static bool
+nanomips_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
+{
+ switch (note->descsz)
+ {
+ default:
+ return false;
+
+ case PRPSINFO_SIZE: /* sizeof(struct elf_prpsinfo) on Linux/nanoMIPS. */
+ /* pr_pid */
+ elf_tdata (abfd)->core->pid
+ = bfd_get_32 (abfd, note->descdata + PRPSINFO_OFFSET_PR_PID);
+
+ /* pr_fname */
+ elf_tdata (abfd)->core->program = _bfd_elfcore_strndup
+ (abfd, note->descdata + PRPSINFO_OFFSET_PR_FNAME, 16);
+
+ /* pr_psargs */
+ elf_tdata (abfd)->core->command = _bfd_elfcore_strndup
+ (abfd, note->descdata + PRPSINFO_OFFSET_PR_PSARGS, 80);
+ break;
+ }
+
+ /* Note that for some reason, a spurious space is tacked
+ onto the end of the args in some (at least one anyway)
+ implementations, so strip it off if it exists. */
+
+ {
+ char *command = elf_tdata (abfd)->core->command;
+ int n = strlen (command);
+
+ if (0 < n && command[n - 1] == ' ')
+ command[n - 1] = '\0';
+ }
+
+ return true;
+}
+
+/* Write Linux core PRSTATUS note into core file. */
+
+static char *
+nanomips_elf_write_core_note (bfd *abfd, char *buf, int *bufsiz, int note_type,
+ ...)
+{
+ switch (note_type)
+ {
+ default:
+ return NULL;
+
+ case NT_PRPSINFO:
+ BFD_FAIL ();
+ return NULL;
+
+ case NT_PRSTATUS:
+ {
+ char data[PRSTATUS_SIZE];
+ va_list ap;
+ long pid;
+ int cursig;
+ const void *greg;
+
+ va_start (ap, note_type);
+ memset (data, 0, PRSTATUS_OFFSET_PR_REG);
+ pid = va_arg (ap, long);
+ bfd_put_32 (abfd, pid, data + PRSTATUS_OFFSET_PR_PID);
+ cursig = va_arg (ap, int);
+ bfd_put_16 (abfd, cursig, data + PRSTATUS_OFFSET_PR_CURSIG);
+ greg = va_arg (ap, const void *);
+ memcpy (data + PRSTATUS_OFFSET_PR_REG, greg, ELF_GREGSET_T_SIZE);
+ memset (data + PRSTATUS_OFFSET_PR_REG + ELF_GREGSET_T_SIZE, 0,
+ PRSTATUS_SIZE - (PRSTATUS_OFFSET_PR_REG + ELF_GREGSET_T_SIZE));
+ va_end (ap);
+ return elfcore_write_note (abfd, buf, bufsiz,
+ "CORE", note_type, data, sizeof (data));
+ }
+ }
+}
+\f
+
+#define ELF_ARCH bfd_arch_nanomips
+#define ELF_TARGET_ID NANOMIPS_ELF_DATA
+#define ELF_MACHINE_CODE EM_NANOMIPS
+
+#define elf_backend_collect true
+#define elf_backend_type_change_ok true
+#define elf_info_to_howto nanomips_info_to_howto_rela
+#define elf_backend_object_p nanomips_elfNN_object_p
+#define elf_backend_section_processing _bfd_nanomips_elf_section_processing
+#define elf_backend_section_from_shdr _bfd_nanomips_elf_section_from_shdr
+#define elf_backend_fake_sections _bfd_nanomips_elf_fake_sections
+#define elf_backend_final_write_processing \
+ _bfd_nanomips_elf_final_write_processing
+#define elf_backend_grok_prstatus nanomips_elf_grok_prstatus
+#define elf_backend_grok_psinfo nanomips_elf_grok_psinfo
+#define elf_backend_write_core_note nanomips_elf_write_core_note
+
+#define elf_backend_may_use_rela_p 1
+#define elf_backend_default_use_rela_p 1
+#define elf_backend_sign_extend_vma true
+#define elf_backend_plt_readonly 1
+
+#define bfd_elfNN_bfd_get_relocated_section_contents \
+ _bfd_elf_nanomips_get_relocated_section_contents
+#define elf_backend_mips_rtype_to_howto nanomips_elfNN_rtype_to_howto
+#define bfd_elfNN_bfd_print_private_bfd_data \
+ _bfd_nanomips_elf_print_private_bfd_data
+#define bfd_elfNN_mkobject _bfd_nanomips_elf_mkobject
+#define bfd_elfNN_bfd_is_local_label_name \
+ nanomips_elf_is_local_label_name
+
+#define ELF_MAXPAGESIZE 0x1000
+#define ELF_COMMONPAGESIZE 0x1000
+
+/* Support for nanomipsNN target. */
+
+#define TARGET_LITTLE_SYM nanomips_elfNN_le_vec
+#define TARGET_LITTLE_NAME "elfNN-littlenanomips"
+#define TARGET_BIG_SYM nanomips_elfNN_be_vec
+#define TARGET_BIG_NAME "elfNN-bignanomips"
+
+#define elfNN_bed elfNN_nanomips_bed
+
+/* Include the target file for this target. */
+#include "elfNN-target.h"
diff --git a/bfd/elfxx-mips.h b/bfd/elfxx-mips.h
index 3be69524c01..1799686c954 100644
--- a/bfd/elfxx-mips.h
+++ b/bfd/elfxx-mips.h
@@ -50,6 +50,8 @@ extern bool _bfd_mips_elf_create_dynamic_sections
(bfd *, struct bfd_link_info *);
extern bool _bfd_mips_elf_check_relocs
(bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *);
+extern bool _bfd_mips_relax_section
+ (bfd *, asection *, struct bfd_link_info *, bool *again);
extern bool _bfd_mips_elf_adjust_dynamic_symbol
(struct bfd_link_info *, struct elf_link_hash_entry *);
extern bool _bfd_mips_elf_always_size_sections
@@ -116,6 +118,8 @@ extern const char * _bfd_mips_fp_abi_string
(int);
extern bool _bfd_mips_elf_print_private_bfd_data
(bfd *, void *);
+extern bool _bfd_nanomips_elf_print_private_bfd_data
+ (bfd *, void *);
extern bool _bfd_mips_elf_discard_info
(bfd *, struct elf_reloc_cookie *, struct bfd_link_info *);
extern bool _bfd_mips_elf_write_section
@@ -146,6 +150,7 @@ extern bfd_vma _bfd_mips_elf_sign_extend
extern void _bfd_mips_elf_merge_symbol_attribute
(struct elf_link_hash_entry *, unsigned int, bool, bool);
extern char *_bfd_mips_elf_get_target_dtag (bfd_vma);
+extern char *_bfd_nanomips_elf_get_target_dtag (bfd_vma);
extern bool _bfd_mips_elf_ignore_undef_symbol
(struct elf_link_hash_entry *);
extern void _bfd_mips_elf_use_plts_and_copy_relocs
diff --git a/bfd/elfxx-nanomips.c b/bfd/elfxx-nanomips.c
new file mode 100644
index 00000000000..34ca23e32aa
--- /dev/null
+++ b/bfd/elfxx-nanomips.c
@@ -0,0 +1,825 @@
+/* nanoMIPS-specific support for ELF
+ Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+ Written by Faraz Shahbazker <faraz.shahbazker@mips.com>
+
+ This file is part of BFD, the Binary File Descriptor library.
+
+ This program 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 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+
+/* This file handles functionality common to nanoMIPS ABIs. */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+#include "elfxx-nanomips.h"
+#include "elf/nanomips.h"
+
+/* nanoMIPS ELF private object data. */
+
+struct nanomips_elf_obj_tdata
+{
+ /* Generic ELF private object data. */
+ struct elf_obj_tdata root;
+
+ /* Input BFD providing Tag_GNU_NANOMIPS_ABI_FP attribute for output. */
+ bfd *abi_fp_bfd;
+
+ /* Input BFD providing Tag_GNU_NANOMIPS_ABI_MSA attribute for output. */
+ bfd *abi_msa_bfd;
+
+ /* The abiflags for this object. */
+ Elf_Internal_ABIFlags_v0 abiflags;
+ bool abiflags_valid;
+
+ bfd_signed_vma sdata_section[1000];
+};
+
+/* Get nanoMIPS ELF private object data from BFD's tdata. */
+
+#define nanomips_elf_tdata(bfd) \
+ ((struct nanomips_elf_obj_tdata *) (bfd)->tdata.any)
+\f
+
+
+/* True if NAME is the recognized name of any SHT_NANOMIPS_ABIFLAGS section. */
+
+#define NANOMIPS_ELF_ABIFLAGS_SECTION_NAME_P(NAME) \
+ (strcmp (NAME, ".nanoMIPS.abiflags") == 0)
+\f
+
+/* Allocate nanoMIPS ELF private object data. */
+
+bool
+_bfd_nanomips_elf_mkobject (bfd *abfd)
+{
+ return bfd_elf_allocate_object (abfd,
+ sizeof (struct nanomips_elf_obj_tdata),
+ NANOMIPS_ELF_DATA);
+}
+\f
+
+
+/* A generic howto special_function. This calculates and installs the
+ relocation itself, thus avoiding the oft-discussed problems in
+ bfd_perform_relocation and bfd_install_relocation. */
+
+bfd_reloc_status_type
+_bfd_nanomips_elf_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED,
+ arelent *reloc_entry, asymbol *symbol,
+ void *data ATTRIBUTE_UNUSED,
+ asection *input_section, bfd *output_bfd,
+ char **error_message ATTRIBUTE_UNUSED)
+{
+ bfd_signed_vma val;
+ bfd_reloc_status_type status;
+ bool relocatable;
+
+ relocatable = (output_bfd != NULL);
+
+ if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+ return bfd_reloc_outofrange;
+
+ /* Build up the field adjustment in VAL. */
+ val = 0;
+ if (!relocatable || (symbol->flags & BSF_SECTION_SYM) != 0)
+ {
+ /* Either we're calculating the final field value or we have a
+ relocation against a section symbol. Add in the section's
+ offset or address. */
+ val += symbol->section->output_section->vma;
+ val += symbol->section->output_offset;
+ }
+
+ if (!relocatable)
+ {
+ /* We're calculating the final field value. Add in the symbol's value
+ and, if pc-relative, subtract the address of the field itself. */
+ val += symbol->value;
+ if (reloc_entry->howto->pc_relative)
+ {
+ val -= input_section->output_section->vma;
+ val -= input_section->output_offset;
+ val -= reloc_entry->address;
+ }
+ }
+
+ /* VAL is now the final adjustment. If we're keeping this relocation
+ in the output file, and if the relocation uses a separate addend,
+ we just need to add VAL to that addend. Otherwise we need to add
+ VAL to the relocation field itself. */
+ if (relocatable && !reloc_entry->howto->partial_inplace)
+ reloc_entry->addend += val;
+ else
+ {
+ bfd_byte *location = (bfd_byte *) data + reloc_entry->address;
+
+ /* Add in the separate addend, if any. */
+ val += reloc_entry->addend;
+
+ /* Add VAL to the relocation field. */
+ status = _bfd_relocate_contents (reloc_entry->howto, abfd, val,
+ location);
+ if (status != bfd_reloc_ok)
+ return status;
+ }
+
+ if (relocatable)
+ reloc_entry->address += input_section->output_offset;
+
+ return bfd_reloc_ok;
+}
+\f
+
+/* A negation howto special_function. */
+
+bfd_reloc_status_type
+_bfd_nanomips_elf_negative_reloc (bfd *abfd ATTRIBUTE_UNUSED,
+ arelent *reloc_entry, asymbol *symbol,
+ void *data ATTRIBUTE_UNUSED,
+ asection *input_section, bfd *output_bfd,
+ char **error_message ATTRIBUTE_UNUSED)
+{
+ bfd_signed_vma val;
+ bool relocatable;
+
+ relocatable = (output_bfd != NULL);
+
+ if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+ return bfd_reloc_outofrange;
+
+ /* Calculate the value of the symbol S. */
+ val = symbol->section->output_section->vma;
+ val += symbol->section->output_offset;
+ val += symbol->value;
+
+ /* Add negated value to addend: (-S + A). */
+ if (! relocatable )
+ reloc_entry->addend = -val + reloc_entry->addend;
+
+ if (relocatable)
+ reloc_entry->address += input_section->output_offset;
+
+ return bfd_reloc_ok;
+}
+
+/* Swap in an abiflags structure. */
+
+void
+bfd_nanomips_elf_swap_abiflags_v0_in (bfd *abfd,
+ const Elf_External_ABIFlags_v0 *ex,
+ Elf_Internal_ABIFlags_v0 *in)
+{
+ in->version = H_GET_16 (abfd, ex->version);
+ in->isa_level = H_GET_8 (abfd, ex->isa_level);
+ in->isa_rev = H_GET_8 (abfd, ex->isa_rev);
+ in->gpr_size = H_GET_8 (abfd, ex->gpr_size);
+ in->cpr1_size = H_GET_8 (abfd, ex->cpr1_size);
+ in->cpr2_size = H_GET_8 (abfd, ex->cpr2_size);
+ in->fp_abi = H_GET_8 (abfd, ex->fp_abi);
+ in->isa_ext = H_GET_32 (abfd, ex->isa_ext);
+ in->ases = H_GET_32 (abfd, ex->ases);
+ in->flags1 = H_GET_32 (abfd, ex->flags1);
+ in->flags2 = H_GET_32 (abfd, ex->flags2);
+}
+
+/* Swap out an abiflags structure. */
+
+void
+bfd_nanomips_elf_swap_abiflags_v0_out (bfd *abfd,
+ const Elf_Internal_ABIFlags_v0 *in,
+ Elf_External_ABIFlags_v0 *ex)
+{
+ H_PUT_16 (abfd, in->version, ex->version);
+ H_PUT_8 (abfd, in->isa_level, ex->isa_level);
+ H_PUT_8 (abfd, in->isa_rev, ex->isa_rev);
+ H_PUT_8 (abfd, in->gpr_size, ex->gpr_size);
+ H_PUT_8 (abfd, in->cpr1_size, ex->cpr1_size);
+ H_PUT_8 (abfd, in->cpr2_size, ex->cpr2_size);
+ H_PUT_8 (abfd, in->fp_abi, ex->fp_abi);
+ H_PUT_32 (abfd, in->isa_ext, ex->isa_ext);
+ H_PUT_32 (abfd, in->ases, ex->ases);
+ H_PUT_32 (abfd, in->flags1, ex->flags1);
+ H_PUT_32 (abfd, in->flags2, ex->flags2);
+}
+\f
+
+/* Map flag bits to BFD architecture. */
+
+unsigned long
+_bfd_elf_mips_mach (flagword flags)
+{
+ switch (flags & EF_NANOMIPS_ARCH)
+ {
+ default:
+ case E_NANOMIPS_ARCH_32R6:
+ return bfd_mach_nanomipsisa32r6;
+
+ case E_NANOMIPS_ARCH_64R6:
+ return bfd_mach_nanomipsisa64r6;
+ }
+
+ return 0;
+}
+
+/* Return printable name for ABI. */
+
+static inline char *
+elf_nanomips_abi_name (bfd *abfd)
+{
+ flagword flags;
+
+ flags = elf_elfheader (abfd)->e_flags;
+ switch (flags & EF_NANOMIPS_ABI)
+ {
+ case 0:
+ return "none";
+ case E_NANOMIPS_ABI_P32:
+ return "P32";
+ case E_NANOMIPS_ABI_P64:
+ return "P64";
+ default:
+ return "unknown abi";
+ }
+}
+\f
+
+/* Work over a section just before writing it out. This routine is
+ used by both the 32-bit and the 64-bit ABI. */
+
+bool
+_bfd_nanomips_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED,
+ Elf_Internal_Shdr *hdr)
+{
+ if (hdr->bfd_section != NULL)
+ {
+ const char *name = bfd_section_name (hdr->bfd_section);
+
+ /* .sbss is not handled specially here because the GNU/Linux
+ prelinker can convert .sbss from NOBITS to PROGBITS and
+ changing it back to NOBITS breaks the binary. The entry in
+ _bfd_nanomips_elf_special_sections will ensure the correct flags
+ are set on .sbss if BFD creates it without reading it from an
+ input file, and without special handling here the flags set
+ on it in an input file will be followed. */
+ if (strcmp (name, ".sdata") == 0
+ || strcmp (name, ".lit8") == 0
+ || strcmp (name, ".lit4") == 0
+ || strncmp (name, ".sdata_", 7) == 0)
+ {
+ hdr->sh_flags |= SHF_ALLOC | SHF_WRITE;
+ hdr->sh_type = SHT_PROGBITS;
+ }
+ else if (strcmp (name, ".srdata") == 0)
+ {
+ hdr->sh_flags |= SHF_ALLOC;
+ hdr->sh_type = SHT_PROGBITS;
+ }
+ else if (strcmp (name, ".compact_rel") == 0)
+ {
+ hdr->sh_flags = 0;
+ hdr->sh_type = SHT_PROGBITS;
+ }
+ else if (strcmp (name, ".rtproc") == 0)
+ {
+ if (hdr->sh_addralign != 0 && hdr->sh_entsize == 0)
+ {
+ unsigned int adjust;
+
+ adjust = hdr->sh_size % hdr->sh_addralign;
+ if (adjust != 0)
+ hdr->sh_size += hdr->sh_addralign - adjust;
+ }
+ }
+ }
+
+ return true;
+}
+
+/* Handle a nanoMIPS specific section when reading an object file.
+ This is called when elfcode.h finds a section with an unknown type.
+ This routine supports both the 32-bit and 64-bit ELF ABI. */
+
+bool
+_bfd_nanomips_elf_section_from_shdr (bfd *abfd, Elf_Internal_Shdr *hdr,
+ const char *name, int shindex)
+{
+ flagword flags = 0;
+
+ /* There ought to be a place to keep ELF backend specific flags, but
+ at the moment there isn't one. We just keep track of the
+ sections by their name, instead. */
+ switch (hdr->sh_type)
+ {
+ case SHT_NANOMIPS_ABIFLAGS:
+ if (!NANOMIPS_ELF_ABIFLAGS_SECTION_NAME_P (name))
+ return false;
+ flags = (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_SAME_SIZE);
+ break;
+ default:
+ break;
+ }
+
+ if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
+ return false;
+
+ if (flags)
+ {
+ if (!bfd_set_section_flags (hdr->bfd_section,
+ (bfd_section_flags (hdr->bfd_section)
+ | flags)))
+ return false;
+ }
+
+ if (hdr->sh_type == SHT_NANOMIPS_ABIFLAGS)
+ {
+ Elf_External_ABIFlags_v0 ext;
+
+ if (! bfd_get_section_contents (abfd, hdr->bfd_section, &ext,
+ 0, sizeof ext))
+ return false;
+ bfd_nanomips_elf_swap_abiflags_v0_in
+ (abfd, &ext, &nanomips_elf_tdata (abfd)->abiflags);
+ if (nanomips_elf_tdata (abfd)->abiflags.version != 0)
+ return false;
+ nanomips_elf_tdata (abfd)->abiflags_valid = true;
+ }
+
+ return true;
+}
+
+/* Set the correct type for a nanoMIPS ELF section. We do this by the
+ section name, which is a hack, but ought to work. This routine is
+ used by both the 32-bit and the 64-bit ABI. */
+
+bool
+_bfd_nanomips_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
+ Elf_Internal_Shdr *hdr,
+ asection *sec)
+{
+ const char *name = bfd_section_name (sec);
+
+ if (startswith (name, ".nanoMIPS.abiflags"))
+ {
+ hdr->sh_type = SHT_NANOMIPS_ABIFLAGS;
+ hdr->sh_entsize = sizeof (Elf_External_ABIFlags_v0);
+ }
+
+ /* The generic elf_fake_sections will set up REL_HDR using the default
+ kind of relocations. */
+ return true;
+}
+\f
+
+/* Functions for the dynamic linker. */
+
+/* Set ABFD's EF_NANOMIPS_ARCH and EF_NANOMIPS_MACH flags. */
+
+static void
+nanomips_set_isa_flags (bfd *abfd)
+{
+ flagword val = 0;
+
+ switch (bfd_get_mach (abfd))
+ {
+ case bfd_mach_nanomipsisa32r6:
+ val = E_NANOMIPS_ARCH_32R6;
+ break;
+
+ case bfd_mach_nanomipsisa64r6:
+ val = E_NANOMIPS_ARCH_64R6;
+ break;
+ default:
+ break;
+ }
+
+ elf_elfheader (abfd)->e_flags &= ~(EF_NANOMIPS_ARCH | EF_NANOMIPS_MACH);
+ elf_elfheader (abfd)->e_flags |= val;
+}
+
+/* The final processing done just before writing out a nanoMIPS ELF
+ object file. This gets the nanoMIPS architecture right based on the
+ machine number. This is used by both the 32-bit and the 64-bit ABI. */
+
+bool
+_bfd_nanomips_elf_final_write_processing (bfd *abfd)
+{
+ nanomips_set_isa_flags (abfd);
+ return _bfd_elf_final_write_processing (abfd);
+}
+\f
+
+/* Return the meaning of Tag_GNU_NANOMIPS_ABI_FP value FP, or null if
+ not known. */
+
+const char *
+_bfd_nanomips_fp_abi_string (int fp)
+{
+ switch (fp)
+ {
+ /* These strings aren't translated because they're simply
+ option lists. */
+ case Val_GNU_NANOMIPS_ABI_FP_DOUBLE:
+ return "-mdouble-float";
+
+ case Val_GNU_NANOMIPS_ABI_FP_SINGLE:
+ return "-msingle-float";
+
+ case Val_GNU_NANOMIPS_ABI_FP_SOFT:
+ return "-msoft-float";
+
+ default:
+ return 0;
+ }
+}
+
+/* Print the name of an ASE. */
+
+static void
+print_nanomips_ases (FILE *file, unsigned int mask)
+{
+ if (mask & NANOMIPS_ASE_DSPR3)
+ fputs ("\n\tDSP R3 ASE", file);
+ if (mask & NANOMIPS_ASE_EVA)
+ fputs ("\n\tEnhanced VA Scheme", file);
+ if (mask & NANOMIPS_ASE_MCU)
+ fputs ("\n\tMCU (MicroController) ASE", file);
+ if (mask & NANOMIPS_ASE_MT)
+ fputs ("\n\tMT ASE", file);
+ if (mask & NANOMIPS_ASE_VIRT)
+ fputs ("\n\tVZ ASE", file);
+ if (mask & NANOMIPS_ASE_MSA)
+ fputs ("\n\tMSA ASE", file);
+ if (mask & NANOMIPS_ASE_TLB)
+ fputs ("\n\tTLB ASE", file);
+ if (mask & NANOMIPS_ASE_CRC)
+ fputs ("\n\tCRC ASE", file);
+ if ((mask & NANOMIPS_ASE_xNMS) == 0)
+ fputs ("\n\tnanoMIPS subset", file);
+ else if (mask == 0)
+ fprintf (file, "\n\t%s", _("None"));
+ else if ((mask & ~NANOMIPS_ASE_MASK) != 0)
+ fprintf (stdout, "\n\t%s (%x)", _("Unknown"), mask & ~NANOMIPS_ASE_MASK);
+}
+
+/* Print the name of an ISA extension. None yet for nanoMIPS. */
+
+static void
+print_nanomips_isa_ext (FILE *file, unsigned int isa_ext)
+{
+ switch (isa_ext)
+ {
+ case 0:
+ fputs (_("None"), file);
+ break;
+ default:
+ fprintf (file, "%s (%d)", _("Unknown"), isa_ext);
+ break;
+ }
+}
+
+/* Decode and print the FP ABI mode. */
+
+static void
+print_nanomips_fp_abi_value (FILE *file, int val)
+{
+ switch (val)
+ {
+ case Val_GNU_NANOMIPS_ABI_FP_ANY:
+ fprintf (file, _("Hard or soft float\n"));
+ break;
+ case Val_GNU_NANOMIPS_ABI_FP_DOUBLE:
+ fprintf (file, _("Hard float (double precision)\n"));
+ break;
+ case Val_GNU_NANOMIPS_ABI_FP_SINGLE:
+ fprintf (file, _("Hard float (single precision)\n"));
+ break;
+ case Val_GNU_NANOMIPS_ABI_FP_SOFT:
+ fprintf (file, _("Soft float\n"));
+ break;
+ default:
+ fprintf (file, "??? (%d)\n", val);
+ break;
+ }
+}
+
+/* Map register type to size. */
+
+static int
+get_nanomips_reg_size (int reg_size)
+{
+ return ((reg_size == AFL_REG_NONE) ? 0
+ : (reg_size == AFL_REG_32) ? 32
+ : (reg_size == AFL_REG_64) ? 64
+ : (reg_size == AFL_REG_128) ? 128
+ : -1);
+}
+
+/* Print nanoMIPS-specific ELF data. */
+
+bool
+_bfd_nanomips_elf_print_private_bfd_data (bfd *abfd, void *ptr)
+{
+ FILE *file = ptr;
+
+ BFD_ASSERT (abfd != NULL && ptr != NULL);
+
+ /* Print normal ELF private data. */
+ _bfd_elf_print_private_bfd_data (abfd, ptr);
+
+ /* xgettext:c-format */
+ fprintf (file, _("private flags = %08lx:"), elf_elfheader (abfd)->e_flags);
+
+ if ((elf_elfheader (abfd)->e_flags & EF_NANOMIPS_ABI) == E_NANOMIPS_ABI_P32)
+ fprintf (file, _(" [abi=P32]"));
+ else if ((elf_elfheader (abfd)->e_flags & EF_NANOMIPS_ABI) ==
+ E_NANOMIPS_ABI_P64)
+ fprintf (file, _(" [abi=P64]"));
+ else
+ fprintf (file, _(" [no abi set]"));
+
+ if ((elf_elfheader (abfd)->e_flags & EF_NANOMIPS_ARCH)
+ == E_NANOMIPS_ARCH_32R6)
+ fprintf (file, " [nanomips32r6]");
+ else if ((elf_elfheader (abfd)->e_flags & EF_NANOMIPS_ARCH)
+ == E_NANOMIPS_ARCH_64R6)
+ fprintf (file, " [nanomips64r6]");
+ else
+ fprintf (file, _(" [unknown ISA]"));
+
+ if (elf_elfheader (abfd)->e_flags & EF_NANOMIPS_32BITMODE)
+ fprintf (file, " [32bitmode]");
+ else
+ fprintf (file, _(" [not 32bitmode]"));
+
+ if (elf_elfheader (abfd)->e_flags & EF_NANOMIPS_LINKRELAX)
+ fprintf (file, " [RELAXABLE]");
+
+ if (elf_elfheader (abfd)->e_flags & EF_NANOMIPS_PIC)
+ fprintf (file, " [PIC]");
+
+ if (elf_elfheader (abfd)->e_flags & EF_NANOMIPS_PID)
+ fprintf (file, " [PID]");
+
+ if (elf_elfheader (abfd)->e_flags & EF_NANOMIPS_PCREL)
+ fprintf (file, " [PCREL]");
+
+ fputc ('\n', file);
+
+ if (nanomips_elf_tdata (abfd)->abiflags_valid)
+ {
+ Elf_Internal_ABIFlags_v0 *abiflags =
+ &nanomips_elf_tdata (abfd)->abiflags;
+ fprintf (file, "\nnanoMIPS ABI Flags Version: %d\n", abiflags->version);
+ fprintf (file, "\nISA: nanoMIPS%d", abiflags->isa_level);
+ if (abiflags->isa_rev > 1)
+ fprintf (file, "r%d", abiflags->isa_rev);
+ fprintf (file, "\nGPR size: %d",
+ get_nanomips_reg_size (abiflags->gpr_size));
+ fprintf (file, "\nCPR1 size: %d",
+ get_nanomips_reg_size (abiflags->cpr1_size));
+ fprintf (file, "\nCPR2 size: %d",
+ get_nanomips_reg_size (abiflags->cpr2_size));
+ fputs ("\nFP ABI: ", file);
+ print_nanomips_fp_abi_value (file, abiflags->fp_abi);
+ fputs ("ISA Extension: ", file);
+ print_nanomips_isa_ext (file, abiflags->isa_ext);
+ fputs ("\nASEs:", file);
+ print_nanomips_ases (file, abiflags->ases);
+ fprintf (file, "\nFLAGS 1: %8.8lx", abiflags->flags1);
+ fprintf (file, "\nFLAGS 2: %8.8lx", abiflags->flags2);
+ fputc ('\n', file);
+ }
+
+ return true;
+}
+
+const struct bfd_elf_special_section _bfd_nanomips_elf_special_sections[] = {
+ { STRING_COMMA_LEN (".lit4"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE},
+ { STRING_COMMA_LEN (".lit8"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE},
+ { STRING_COMMA_LEN (".sbss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE},
+ { STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE},
+ { NULL, 0, 0, 0, 0 }
+};
+
+/* Merge non visibility st_other attributes. Ensure that the
+ STO_OPTIONAL flag is copied into h->other, even if this is not a
+ definiton of the symbol. */
+
+void
+_bfd_nanomips_elf_merge_symbol_attribute (struct elf_link_hash_entry *h,
+ unsigned int st_other,
+ bool definition,
+ bool dynamic
+ ATTRIBUTE_UNUSED)
+{
+ if ((st_other & ~ELF_ST_VISIBILITY (-1)) != 0)
+ {
+ unsigned char other;
+
+ other = (definition ? st_other : h->other);
+ other &= ~ELF_ST_VISIBILITY (-1);
+ h->other = other | ELF_ST_VISIBILITY (h->other);
+ }
+}
+
+/* Get ABI flags for a nanoMIPS BFD arch. */
+
+Elf_Internal_ABIFlags_v0 *
+bfd_nanomips_elf_get_abiflags (bfd *abfd)
+{
+ struct nanomips_elf_obj_tdata *tdata = nanomips_elf_tdata (abfd);
+
+ return tdata->abiflags_valid ? &tdata->abiflags : NULL;
+}
+
+/* Relocate a section. Tools like readelf/binutils needed to perform a static
+ relocation on objects to make sense debug information that contains label
+ difference relocations. The only difference between this and the generic
+ ELF version is that correct handling of composite relocations according to
+ gABI spec. */
+
+bfd_byte *
+_bfd_elf_nanomips_get_relocated_section_contents (bfd *abfd,
+ struct bfd_link_info *link_info,
+ struct bfd_link_order *link_order,
+ bfd_byte *data,
+ bool relocatable,
+ asymbol **symbols)
+{
+ bfd *input_bfd = link_order->u.indirect.section->owner;
+ asection *input_section = link_order->u.indirect.section;
+ long reloc_size;
+ arelent **reloc_vector;
+ long reloc_count;
+
+ reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
+ if (reloc_size < 0)
+ return NULL;
+
+ /* Read in the section. */
+ if (!bfd_get_full_section_contents (input_bfd, input_section, &data))
+ return NULL;
+
+ if (data == NULL)
+ return NULL;
+
+ if (reloc_size == 0)
+ return data;
+
+ reloc_vector = (arelent **) bfd_malloc (reloc_size);
+ if (reloc_vector == NULL)
+ return NULL;
+
+ reloc_count = bfd_canonicalize_reloc (input_bfd, input_section,
+ reloc_vector, symbols);
+
+ if (reloc_count < 0)
+ goto error_return;
+
+ if (reloc_count > 0)
+ {
+ arelent **parent;
+ /* offset in section of previous relocation */
+ bfd_size_type last_address = 0;
+ /* saved result of previous relocation. */
+ bfd_vma saved_addend = 0;
+
+ for (parent = reloc_vector; *parent != NULL; parent++)
+ {
+ char *error_message = NULL;
+ asymbol *symbol;
+ bfd_reloc_status_type r;
+
+ symbol = *(*parent)->sym_ptr_ptr;
+ /* PR ld/19628: A specially crafted input file
+ can result in a NULL symbol pointer here. */
+ if (symbol == NULL)
+ {
+ link_info->callbacks->einfo
+ /* xgettext:c-format */
+ (_("%X%P: %B(%A): error: relocation for offset %V has no value\n"),
+ abfd, input_section, (* parent)->address);
+ goto error_return;
+ }
+
+ if (symbol->section && discarded_section (symbol->section))
+ {
+ bfd_vma off;
+ static reloc_howto_type none_howto
+ = HOWTO (0, 0, 0, 0, false, 0, complain_overflow_dont, NULL,
+ "unused", false, 0, 0, false);
+
+ off = (*parent)->address * bfd_octets_per_byte (input_bfd, input_section);
+ _bfd_clear_contents ((*parent)->howto, input_bfd, input_section,
+ data, off);
+ (*parent)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+ (*parent)->addend = 0;
+ (*parent)->howto = &none_howto;
+ r = bfd_reloc_ok;
+ }
+ else
+ {
+ if (last_address != 0 && (*parent)->address == last_address)
+ (*parent)->addend = saved_addend;
+ else
+ saved_addend = 0;
+
+ r = bfd_perform_relocation (input_bfd,
+ *parent,
+ data,
+ input_section,
+ relocatable ? abfd : NULL,
+ &error_message);
+ saved_addend = (*parent)->addend;
+ }
+
+ if (relocatable)
+ {
+ asection *os = input_section->output_section;
+
+ /* A partial link, so keep the relocs. */
+ os->orelocation[os->reloc_count] = *parent;
+ os->reloc_count++;
+ }
+
+ if (r != bfd_reloc_ok)
+ {
+ switch (r)
+ {
+ case bfd_reloc_undefined:
+ (*link_info->callbacks->undefined_symbol)
+ (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr),
+ input_bfd, input_section, (*parent)->address, true);
+ break;
+ case bfd_reloc_dangerous:
+ BFD_ASSERT (error_message != NULL);
+ (*link_info->callbacks->reloc_dangerous)
+ (link_info, error_message,
+ input_bfd, input_section, (*parent)->address);
+ break;
+ case bfd_reloc_overflow:
+ (*link_info->callbacks->reloc_overflow)
+ (link_info, NULL,
+ bfd_asymbol_name (*(*parent)->sym_ptr_ptr),
+ (*parent)->howto->name, (*parent)->addend,
+ input_bfd, input_section, (*parent)->address);
+ break;
+ case bfd_reloc_outofrange:
+ /* PR ld/13730:
+ This error can result when processing some partially
+ complete binaries. Do not abort, but issue an error
+ message instead. */
+ link_info->callbacks->einfo
+ /* xgettext:c-format */
+ (_("%X%P: %B(%A): relocation \"%R\" goes out of range\n"),
+ abfd, input_section, *parent);
+ goto error_return;
+
+ case bfd_reloc_notsupported:
+ /* PR ld/17512
+ This error can result when processing a corrupt binary.
+ Do not abort. Issue an error message instead. */
+ link_info->callbacks->einfo
+ /* xgettext:c-format */
+ (_("%X%P: %B(%A): relocation \"%R\" is not supported\n"),
+ abfd, input_section, *parent);
+ goto error_return;
+
+ default:
+ /* PR 17512; file: 90c2a92e.
+ Report unexpected results, without aborting. */
+ link_info->callbacks->einfo
+ /* xgettext:c-format */
+ (_("%X%P: %B(%A): relocation \"%R\" returns an unrecognized value %x\n"),
+ abfd, input_section, *parent, r);
+ break;
+ }
+
+ }
+ last_address = (*parent)->address;
+ }
+ }
+
+ free (reloc_vector);
+ return data;
+
+error_return:
+ free (reloc_vector);
+ return NULL;
+}
diff --git a/bfd/elfxx-nanomips.h b/bfd/elfxx-nanomips.h
new file mode 100644
index 00000000000..6d441842d6f
--- /dev/null
+++ b/bfd/elfxx-nanomips.h
@@ -0,0 +1,54 @@
+/* nanoMIPS ELF specific backend routines.
+ Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+ Written by Faraz Shahbazker <faraz.shahbazker@mips.com>
+
+ This file is part of BFD, the Binary File Descriptor library.
+
+ This program 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 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "elf/nanomips.h"
+
+extern bool _bfd_nanomips_elf_mkobject (bfd *);
+extern bool _bfd_nanomips_elf_section_processing
+ (bfd *, Elf_Internal_Shdr *);
+extern bool _bfd_nanomips_elf_section_from_shdr
+ (bfd *, Elf_Internal_Shdr *, const char *, int);
+extern bool _bfd_nanomips_elf_fake_sections
+ (bfd *, Elf_Internal_Shdr *, asection *);
+extern bool _bfd_nanomips_elf_final_write_processing (bfd *);
+extern const char *_bfd_nanomips_fp_abi_string (int);
+extern bool _bfd_nanomips_elf_print_private_bfd_data (bfd *, void *);
+
+extern bfd_reloc_status_type _bfd_nanomips_elf_generic_reloc
+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
+extern bfd_reloc_status_type _bfd_nanomips_elf_negative_reloc
+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
+
+extern unsigned long _bfd_elf_mips_mach (flagword);
+extern void _bfd_nanomips_elf_merge_symbol_attribute
+ (struct elf_link_hash_entry *, unsigned int, bool, bool);
+
+extern const struct bfd_elf_special_section
+ _bfd_nanomips_elf_special_sections[];
+
+extern bfd_byte *_bfd_elf_nanomips_get_relocated_section_contents
+ (bfd *, struct bfd_link_info *, struct bfd_link_order *,
+ bfd_byte *, bool, asymbol **);
+
+#define elf_backend_special_sections _bfd_nanomips_elf_special_sections
+#define elf_backend_merge_symbol_attribute \
+ _bfd_nanomips_elf_merge_symbol_attribute
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 8c02e29eebd..201b18d5d4a 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1314,6 +1314,75 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_MIPS_COPY",
"BFD_RELOC_MIPS_JUMP_SLOT",
+ "BFD_RELOC_NANOMIPS_HI20",
+ "BFD_RELOC_NANOMIPS_LO12",
+ "BFD_RELOC_NANOMIPS_LO4_S2",
+ "BFD_RELOC_NANOMIPS_IMM16",
+ "BFD_RELOC_NANOMIPS_NEG12",
+ "BFD_RELOC_NANOMIPS_GPREL7_S2",
+ "BFD_RELOC_NANOMIPS_GPREL18",
+ "BFD_RELOC_NANOMIPS_GPREL19_S2",
+ "BFD_RELOC_NANOMIPS_GPREL16_S2",
+ "BFD_RELOC_NANOMIPS_GPREL18_S3",
+ "BFD_RELOC_NANOMIPS_4_PCREL_S1",
+ "BFD_RELOC_NANOMIPS_7_PCREL_S1",
+ "BFD_RELOC_NANOMIPS_10_PCREL_S1",
+ "BFD_RELOC_NANOMIPS_11_PCREL_S1",
+ "BFD_RELOC_NANOMIPS_14_PCREL_S1",
+ "BFD_RELOC_NANOMIPS_21_PCREL_S1",
+ "BFD_RELOC_NANOMIPS_25_PCREL_S1",
+ "BFD_RELOC_NANOMIPS_PCREL_HI20",
+ "BFD_RELOC_NANOMIPS_GOT_CALL",
+ "BFD_RELOC_NANOMIPS_GOTPC_HI20",
+ "BFD_RELOC_NANOMIPS_GOTPC_I32",
+ "BFD_RELOC_NANOMIPS_GOT_LO12",
+ "BFD_RELOC_NANOMIPS_GOT_DISP",
+ "BFD_RELOC_NANOMIPS_GOT_PAGE",
+ "BFD_RELOC_NANOMIPS_GOT_OFST",
+ "BFD_RELOC_NANOMIPS_I32",
+ "BFD_RELOC_NANOMIPS_GPREL_HI20",
+ "BFD_RELOC_NANOMIPS_GPREL_LO12",
+ "BFD_RELOC_NANOMIPS_TLS_GD",
+ "BFD_RELOC_NANOMIPS_TLS_GD_I32",
+ "BFD_RELOC_NANOMIPS_TLS_LD",
+ "BFD_RELOC_NANOMIPS_TLS_LD_I32",
+ "BFD_RELOC_NANOMIPS_TLS_DTPREL12",
+ "BFD_RELOC_NANOMIPS_TLS_DTPREL16",
+ "BFD_RELOC_NANOMIPS_TLS_DTPREL_I32",
+ "BFD_RELOC_NANOMIPS_TLS_GOTTPREL",
+ "BFD_RELOC_NANOMIPS_TLS_GOTTPREL_PC_I32",
+ "BFD_RELOC_NANOMIPS_TLS_TPREL12",
+ "BFD_RELOC_NANOMIPS_TLS_TPREL16",
+ "BFD_RELOC_NANOMIPS_TLS_TPREL_I32",
+ "BFD_RELOC_NANOMIPS_TLS_DTPMOD",
+ "BFD_RELOC_NANOMIPS_TLS_DTPREL",
+ "BFD_RELOC_NANOMIPS_TLS_TPREL",
+ "BFD_RELOC_NANOMIPS_PC_I32",
+ "BFD_RELOC_NANOMIPS_GPREL_I32",
+ "BFD_RELOC_NANOMIPS_GPREL17_S1",
+ "BFD_RELOC_NANOMIPS_NEG",
+ "BFD_RELOC_NANOMIPS_ASHIFTR_1",
+ "BFD_RELOC_NANOMIPS_UNSIGNED_8",
+ "BFD_RELOC_NANOMIPS_UNSIGNED_16",
+ "BFD_RELOC_NANOMIPS_SIGNED_8",
+ "BFD_RELOC_NANOMIPS_SIGNED_16",
+ "BFD_RELOC_NANOMIPS_EH",
+ "BFD_RELOC_NANOMIPS_JUMP_SLOT",
+ "BFD_RELOC_NANOMIPS_ALIGN",
+ "BFD_RELOC_NANOMIPS_FILL",
+ "BFD_RELOC_NANOMIPS_MAX",
+ "BFD_RELOC_NANOMIPS_INSN32",
+ "BFD_RELOC_NANOMIPS_INSN16",
+ "BFD_RELOC_NANOMIPS_FIXED",
+ "BFD_RELOC_NANOMIPS_RELAX",
+ "BFD_RELOC_NANOMIPS_NORELAX",
+ "BFD_RELOC_NANOMIPS_SAVERESTORE",
+ "BFD_RELOC_NANOMIPS_JALR16",
+ "BFD_RELOC_NANOMIPS_JALR32",
+ "BFD_RELOC_NANOMIPS_COPY",
+ "BFD_RELOC_NANOMIPS_SIGNED_9",
+ "BFD_RELOC_NANOMIPS_JUMPTABLE_LOAD",
+
"BFD_RELOC_MOXIE_10_PCREL",
"BFD_RELOC_FT32_10",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 5098e0ab09f..9f3e9f01dfe 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -2376,6 +2376,146 @@ ENUMDOC
MIPS ELF relocations (VxWorks and PLT extensions).
COMMENT
+ENUM
+ BFD_RELOC_NANOMIPS_HI20
+ENUMX
+ BFD_RELOC_NANOMIPS_LO12
+ENUMX
+ BFD_RELOC_NANOMIPS_LO4_S2
+ENUMX
+ BFD_RELOC_NANOMIPS_IMM16
+ENUMX
+ BFD_RELOC_NANOMIPS_NEG12
+ENUMX
+ BFD_RELOC_NANOMIPS_GPREL7_S2
+ENUMX
+ BFD_RELOC_NANOMIPS_GPREL18
+ENUMX
+ BFD_RELOC_NANOMIPS_GPREL19_S2
+ENUMX
+ BFD_RELOC_NANOMIPS_GPREL16_S2
+ENUMX
+ BFD_RELOC_NANOMIPS_GPREL18_S3
+ENUMX
+ BFD_RELOC_NANOMIPS_4_PCREL_S1
+ENUMX
+ BFD_RELOC_NANOMIPS_7_PCREL_S1
+ENUMX
+ BFD_RELOC_NANOMIPS_10_PCREL_S1
+ENUMX
+ BFD_RELOC_NANOMIPS_11_PCREL_S1
+ENUMX
+ BFD_RELOC_NANOMIPS_14_PCREL_S1
+ENUMX
+ BFD_RELOC_NANOMIPS_21_PCREL_S1
+ENUMX
+ BFD_RELOC_NANOMIPS_25_PCREL_S1
+ENUMX
+ BFD_RELOC_NANOMIPS_PCREL_HI20
+ENUMX
+ BFD_RELOC_NANOMIPS_GOT_CALL
+ENUMX
+ BFD_RELOC_NANOMIPS_GOTPC_HI20
+ENUMX
+ BFD_RELOC_NANOMIPS_GOTPC_I32
+ENUMX
+ BFD_RELOC_NANOMIPS_GOT_LO12
+ENUMX
+ BFD_RELOC_NANOMIPS_GOT_DISP
+ENUMX
+ BFD_RELOC_NANOMIPS_GOT_PAGE
+ENUMX
+ BFD_RELOC_NANOMIPS_GOT_OFST
+ENUMX
+ BFD_RELOC_NANOMIPS_I32
+ENUMX
+ BFD_RELOC_NANOMIPS_GPREL_HI20
+ENUMX
+ BFD_RELOC_NANOMIPS_GPREL_LO12
+ENUMX
+ BFD_RELOC_NANOMIPS_TLS_GD
+ENUMX
+ BFD_RELOC_NANOMIPS_TLS_GD_I32
+ENUMX
+ BFD_RELOC_NANOMIPS_TLS_LD
+ENUMX
+ BFD_RELOC_NANOMIPS_TLS_LD_I32
+ENUMX
+ BFD_RELOC_NANOMIPS_TLS_DTPREL12
+ENUMX
+ BFD_RELOC_NANOMIPS_TLS_DTPREL16
+ENUMX
+ BFD_RELOC_NANOMIPS_TLS_DTPREL_I32
+ENUMX
+ BFD_RELOC_NANOMIPS_TLS_GOTTPREL
+ENUMX
+ BFD_RELOC_NANOMIPS_TLS_GOTTPREL_PC_I32
+ENUMX
+ BFD_RELOC_NANOMIPS_TLS_TPREL12
+ENUMX
+ BFD_RELOC_NANOMIPS_TLS_TPREL16
+ENUMX
+ BFD_RELOC_NANOMIPS_TLS_TPREL_I32
+ENUMX
+ BFD_RELOC_NANOMIPS_TLS_DTPMOD
+ENUMX
+ BFD_RELOC_NANOMIPS_TLS_DTPREL
+ENUMX
+ BFD_RELOC_NANOMIPS_TLS_TPREL
+ENUMX
+ BFD_RELOC_NANOMIPS_PC_I32
+ENUMX
+ BFD_RELOC_NANOMIPS_GPREL_I32
+ENUMX
+ BFD_RELOC_NANOMIPS_GPREL17_S1
+ENUMX
+ BFD_RELOC_NANOMIPS_NEG
+ENUMX
+ BFD_RELOC_NANOMIPS_ASHIFTR_1
+ENUMX
+ BFD_RELOC_NANOMIPS_UNSIGNED_8
+ENUMX
+ BFD_RELOC_NANOMIPS_UNSIGNED_16
+ENUMX
+ BFD_RELOC_NANOMIPS_SIGNED_8
+ENUMX
+ BFD_RELOC_NANOMIPS_SIGNED_16
+ENUMX
+ BFD_RELOC_NANOMIPS_EH
+ENUMX
+ BFD_RELOC_NANOMIPS_JUMP_SLOT
+ENUMX
+ BFD_RELOC_NANOMIPS_ALIGN
+ENUMX
+ BFD_RELOC_NANOMIPS_FILL
+ENUMX
+ BFD_RELOC_NANOMIPS_MAX
+ENUMX
+ BFD_RELOC_NANOMIPS_INSN32
+ENUMX
+ BFD_RELOC_NANOMIPS_INSN16
+ENUMX
+ BFD_RELOC_NANOMIPS_FIXED
+ENUMX
+ BFD_RELOC_NANOMIPS_RELAX
+ENUMX
+ BFD_RELOC_NANOMIPS_NORELAX
+ENUMX
+ BFD_RELOC_NANOMIPS_SAVERESTORE
+ENUMX
+ BFD_RELOC_NANOMIPS_JALR16
+ENUMX
+ BFD_RELOC_NANOMIPS_JALR32
+ENUMX
+ BFD_RELOC_NANOMIPS_COPY
+ENUMX
+ BFD_RELOC_NANOMIPS_SIGNED_9
+ENUMX
+ BFD_RELOC_NANOMIPS_JUMPTABLE_LOAD
+ENUMDOC
+ nanoMIPS relocations
+COMMENT
+
ENUM
BFD_RELOC_MOXIE_10_PCREL
ENUMDOC
diff --git a/bfd/targets.c b/bfd/targets.c
index 05dd8236d91..6914d2d2be9 100644
--- a/bfd/targets.c
+++ b/bfd/targets.c
@@ -823,6 +823,10 @@ extern const bfd_target moxie_elf32_le_vec;
extern const bfd_target msp430_elf32_vec;
extern const bfd_target msp430_elf32_ti_vec;
extern const bfd_target mt_elf32_vec;
+extern const bfd_target nanomips_elf32_be_vec;
+extern const bfd_target nanomips_elf32_le_vec;
+extern const bfd_target nanomips_elf64_le_vec;
+extern const bfd_target nanomips_elf64_be_vec;
extern const bfd_target nds32_elf32_be_vec;
extern const bfd_target nds32_elf32_le_vec;
extern const bfd_target nds32_elf32_linux_be_vec;
@@ -1198,6 +1202,13 @@ static const bfd_target * const _bfd_target_vector[] =
&mt_elf32_vec,
+ &nanomips_elf32_be_vec,
+ &nanomips_elf32_le_vec,
+#ifdef BFD64
+ &nanomips_elf64_be_vec,
+ &nanomips_elf64_le_vec,
+#endif
+
&nds32_elf32_be_vec,
&nds32_elf32_le_vec,
&nds32_elf32_linux_be_vec,
diff --git a/binutils/readelf.c b/binutils/readelf.c
index d45e0920788..9ba45bb2803 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -139,6 +139,7 @@
#include "elf/moxie.h"
#include "elf/mt.h"
#include "elf/msp430.h"
+#include "elf/nanomips.h"
#include "elf/nds32.h"
#include "elf/nfp.h"
#include "elf/nios2.h"
@@ -1101,6 +1102,7 @@ guess_is_rela (unsigned int e_machine)
case EM_MSP430:
case EM_MSP430_OLD:
case EM_MT:
+ case EM_NANOMIPS:
case EM_NDS32:
case EM_NIOS32:
case EM_OR1K:
@@ -1911,6 +1913,10 @@ dump_relocations (Filedata * filedata,
rtype = elf_nios2_reloc_type (type);
break;
+ case EM_NANOMIPS:
+ rtype = elf_nanomips_reloc_type (type);
+ break;
+
case EM_TI_PRU:
rtype = elf_pru_reloc_type (type);
break;
@@ -2224,6 +2230,17 @@ get_mips_dynamic_type (unsigned long type)
}
}
+static const char *
+get_nanomips_dynamic_type (unsigned long type)
+{
+ switch (type)
+ {
+ case DT_NANOMIPS_GOTNO: return "NANOMIPS_GOTNO";
+ default:
+ return NULL;
+ }
+}
+
static const char *
get_sparc64_dynamic_type (unsigned long type)
{
@@ -2589,6 +2606,8 @@ get_dynamic_type (Filedata * filedata, unsigned long type)
break;
case EM_RISCV:
result = get_riscv_dynamic_type (type);
+ case EM_NANOMIPS:
+ result = get_nanomips_dynamic_type (type);
break;
default:
if (filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS)
@@ -2884,6 +2903,7 @@ get_machine_name (unsigned e_machine)
case EM_ALTERA_NIOS2: return "Altera Nios II";
case EM_CRX: return "National Semiconductor CRX microprocessor";
case EM_XGATE: return "Motorola XGATE embedded processor";
+ case EM_NANOMIPS: return "Mips nanoMIPS";
case EM_C166:
case EM_XC16X: return "Infineon Technologies xc16x";
case EM_M16C: return "Renesas M16C series microprocessors";
@@ -4409,6 +4429,38 @@ get_machine_flags (Filedata * filedata, unsigned e_flags, unsigned e_machine)
strcat (buf, ", DOUBLE-FLOAT");
break;
+ case EM_NANOMIPS:
+ if (e_flags & EF_NANOMIPS_PIC)
+ strcat (buf, ", pic");
+
+ if (e_flags & EF_NANOMIPS_32BITMODE)
+ strcat (buf, ", 32bitmode");
+
+ switch ((e_flags & EF_NANOMIPS_MACH))
+ {
+ default: strcat (buf, _(", unknown CPU")); break;
+ }
+
+ switch ((e_flags & EF_NANOMIPS_ABI))
+ {
+ case E_NANOMIPS_ABI_P32: strcat (buf, ", p32"); break;
+ case E_NANOMIPS_ABI_P64: strcat (buf, ", p64"); break;
+ case 0:
+ /* We simply ignore the field in this case to avoid confusion:
+ MIPS ELF does not specify EF_MIPS_ABI, it is a GNU extension.
+ This means it is likely to be an o32 file, but not for
+ sure. */
+ break;
+ default: strcat (buf, _(", unknown ABI")); break;
+ }
+
+ switch ((e_flags & EF_NANOMIPS_ARCH))
+ {
+ case E_NANOMIPS_ARCH_32R6: strcat (buf, ", nanomips32r6"); break;
+ case E_NANOMIPS_ARCH_64R6: strcat (buf, ", nanomips64r6"); break;
+ default: strcat (buf, _(", unknown ISA")); break;
+ }
+ break;
}
}
@@ -4536,6 +4588,20 @@ get_mips_segment_type (unsigned long type)
}
}
+static const char *
+get_nanomips_segment_type (unsigned long type)
+{
+ switch (type)
+ {
+ case PT_NANOMIPS_ABIFLAGS:
+ return "ABIFLAGS";
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
static const char *
get_parisc_segment_type (unsigned long type)
{
@@ -4687,6 +4753,8 @@ get_segment_type (Filedata * filedata, unsigned long p_type)
case EM_S390:
case EM_S390_OLD:
result = get_s390_segment_type (p_type);
+ case EM_NANOMIPS:
+ result = get_nanomips_segment_type (p_type);
break;
case EM_RISCV:
result = get_riscv_segment_type (p_type);
@@ -10646,6 +10714,21 @@ dynamic_section_mips_val (Filedata * filedata, Elf_Internal_Dyn * entry)
putchar ('\n');
}
+static void
+dynamic_section_nanomips_val (Elf_Internal_Dyn * entry)
+{
+ switch (entry->d_tag)
+ {
+ case DT_NANOMIPS_GOTNO:
+ print_vma (entry->d_un.d_ptr, DEC);
+ break;
+
+ default:
+ print_vma (entry->d_un.d_ptr, PREFIX_HEX);
+ }
+ putchar ('\n');
+}
+
static void
dynamic_section_parisc_val (Elf_Internal_Dyn * entry)
{
@@ -11989,6 +12072,9 @@ the .dynstr section doesn't match the DT_STRTAB and DT_STRSZ tags\n"));
case EM_IA_64:
dynamic_section_ia64_val (entry);
break;
+ case EM_NANOMIPS:
+ dynamic_section_nanomips_val (entry);
+ break;
default:
print_vma (entry->d_un.d_val, PREFIX_HEX);
putchar ('\n');
@@ -14271,6 +14357,8 @@ is_32bit_abs_reloc (Filedata * filedata, unsigned int reloc_type)
return reloc_type == 1; /* R_MSP430_32 or R_MSP320_ABS32. */
case EM_MT:
return reloc_type == 2; /* R_MT_32. */
+ case EM_NANOMIPS:
+ return reloc_type == 1; /* R_NANOMIPS_32. */
case EM_NDS32:
return reloc_type == 20; /* R_NDS32_32_RELA. */
case EM_ALTERA_NIOS2:
@@ -14476,6 +14564,8 @@ is_64bit_abs_reloc (Filedata * filedata, unsigned int reloc_type)
return reloc_type == 1; /* R_TILEGX_64. */
case EM_MIPS:
return reloc_type == 18; /* R_MIPS_64. */
+ case EM_NANOMIPS:
+ return reloc_type == 2; /* R_NANOMIPS_64. */
default:
return false;
}
@@ -14583,6 +14673,8 @@ is_16bit_abs_reloc (Filedata * filedata, unsigned int reloc_type)
/* Fall through. */
case EM_MSP430_OLD:
return reloc_type == 5; /* R_MSP430_16_BYTE. */
+ case EM_NANOMIPS:
+ return reloc_type == 7; /* R_NANOMIPS_UNSIGNED_16 */
case EM_NDS32:
return reloc_type == 19; /* R_NDS32_16_RELA. */
case EM_ALTERA_NIOS2:
@@ -14815,6 +14907,8 @@ is_none_reloc (Filedata * filedata, unsigned int reloc_type)
case EM_MOXIE: /* R_MOXIE_NONE. */
case EM_NIOS32: /* R_NIOS_NONE. */
case EM_OR1K: /* R_OR1K_NONE. */
+ case EM_NANOMIPS: /* R_NANOMIPS_NONE. */
+ return reloc_type == 0;
case EM_PARISC: /* R_PARISC_NONE. */
case EM_PPC64: /* R_PPC64_NONE. */
case EM_PPC: /* R_PPC_NONE. */
@@ -17311,6 +17405,75 @@ display_mips_gnu_attribute (unsigned char * p,
return display_tag_value (tag & 1, p, end);
}
+static void
+print_nanomips_fp_abi_value (int val)
+{
+ switch (val)
+ {
+ case Val_GNU_NANOMIPS_ABI_FP_ANY:
+ printf (_("Hard or soft float\n"));
+ break;
+ case Val_GNU_NANOMIPS_ABI_FP_DOUBLE:
+ printf (_("Hard float (double precision)\n"));
+ break;
+ case Val_GNU_NANOMIPS_ABI_FP_SINGLE:
+ printf (_("Hard float (single precision)\n"));
+ break;
+ case Val_GNU_NANOMIPS_ABI_FP_SOFT:
+ printf (_("Soft float\n"));
+ break;
+ default:
+ printf ("??? (%d)\n", val);
+ break;
+ }
+}
+
+static unsigned char *
+display_nanomips_gnu_attribute (unsigned char * p,
+ int tag,
+ const unsigned char * const end)
+{
+ if (tag == Tag_GNU_NANOMIPS_ABI_FP)
+ {
+ unsigned int len;
+ int val;
+
+ val = read_uleb128 (p, &len, end);
+ p += len;
+ printf (" Tag_GNU_NANOMIPS_ABI_FP: ");
+
+ print_nanomips_fp_abi_value (val);
+
+ return p;
+ }
+
+ if (tag == Tag_GNU_NANOMIPS_ABI_MSA)
+ {
+ unsigned int len;
+ int val;
+
+ val = read_uleb128 (p, &len, end);
+ p += len;
+ printf (" Tag_GNU_NANOMIPS_ABI_MSA: ");
+
+ switch (val)
+ {
+ case Val_GNU_NANOMIPS_ABI_MSA_ANY:
+ printf (_("Any MSA or not\n"));
+ break;
+ case Val_GNU_NANOMIPS_ABI_MSA_128:
+ printf (_("128-bit MSA\n"));
+ break;
+ default:
+ printf ("??? (%d)\n", val);
+ break;
+ }
+ return p;
+ }
+
+ return display_tag_value (tag & 1, p, end);
+}
+
static unsigned char *
display_tic6x_attribute (unsigned char * p,
const unsigned char * const end)
@@ -19147,6 +19310,364 @@ process_mips_specific (Filedata * filedata)
return res;
}
+static void
+print_nanomips_ases (unsigned int mask)
+{
+ if (mask & NANOMIPS_ASE_DSPR3)
+ fputs ("\n\tDSP R3 ASE", stdout);
+ if (mask & NANOMIPS_ASE_EVA)
+ fputs ("\n\tEnhanced VA Scheme", stdout);
+ if (mask & NANOMIPS_ASE_MCU)
+ fputs ("\n\tMCU (MicroController) ASE", stdout);
+ if (mask & NANOMIPS_ASE_MT)
+ fputs ("\n\tMT ASE", stdout);
+ if (mask & NANOMIPS_ASE_VIRT)
+ fputs ("\n\tVZ ASE", stdout);
+ if (mask & NANOMIPS_ASE_MSA)
+ fputs ("\n\tMSA ASE", stdout);
+ if (mask & NANOMIPS_ASE_XPA)
+ fputs ("\n\tXPA ASE", stdout);
+ if (mask & NANOMIPS_ASE_TLB)
+ fputs ("\n\tTLB ASE", stdout);
+ if (mask & NANOMIPS_ASE_GINV)
+ fputs ("\n\tGINV ASE", stdout);
+ if ((mask & NANOMIPS_ASE_xNMS) == 0)
+ fputs ("\n\tnanoMIPS subset", stdout);
+ else if (mask == 0)
+ fprintf (stdout, "\n\t%s", _("None"));
+ else if ((mask & ~NANOMIPS_ASE_MASK) != 0)
+ fprintf (stdout, "\n\t%s (%x)", _("Unknown"), mask & ~NANOMIPS_ASE_MASK);
+}
+
+static void
+print_nanomips_isa_ext (unsigned int isa_ext)
+{
+ switch (isa_ext)
+ {
+ case 0:
+ fputs (_("None"), stdout);
+ break;
+ default:
+ fprintf (stdout, "%s (%d)", _("Unknown"), isa_ext);
+ }
+}
+
+static int
+get_nanomips_reg_size (int reg_size)
+{
+ return (get_mips_reg_size (reg_size));
+}
+
+static int
+process_nanomips_specific (FILE * file)
+{
+ Elf_Internal_Dyn * entry;
+ Elf_Internal_Shdr *sect = NULL;
+ size_t options_offset = 0;
+ bfd_vma pltgot = 0;
+ bfd_vma gotsym = 0;
+ bfd_vma symtabno = 0;
+
+ process_attributes (file, NULL, SHT_GNU_ATTRIBUTES, NULL,
+ display_nanomips_gnu_attribute);
+
+ sect = find_section (".nanoMIPS.abiflags");
+
+ if (sect != NULL)
+ {
+ Elf_External_ABIFlags_v0 *abiflags_ext;
+ Elf_Internal_ABIFlags_v0 abiflags_in;
+
+ if (sizeof (Elf_External_ABIFlags_v0) != sect->sh_size)
+ fputs ("\nCorrupt ABI Flags section.\n", stdout);
+ else
+ {
+ abiflags_ext = get_data (NULL, file, sect->sh_offset, 1,
+ sect->sh_size, _("nanoMIPS ABI Flags section"));
+ if (abiflags_ext)
+ {
+ abiflags_in.version = BYTE_GET (abiflags_ext->version);
+ abiflags_in.isa_level = BYTE_GET (abiflags_ext->isa_level);
+ abiflags_in.isa_rev = BYTE_GET (abiflags_ext->isa_rev);
+ abiflags_in.gpr_size = BYTE_GET (abiflags_ext->gpr_size);
+ abiflags_in.cpr1_size = BYTE_GET (abiflags_ext->cpr1_size);
+ abiflags_in.cpr2_size = BYTE_GET (abiflags_ext->cpr2_size);
+ abiflags_in.fp_abi = BYTE_GET (abiflags_ext->fp_abi);
+ abiflags_in.isa_ext = BYTE_GET (abiflags_ext->isa_ext);
+ abiflags_in.ases = BYTE_GET (abiflags_ext->ases);
+ abiflags_in.flags1 = BYTE_GET (abiflags_ext->flags1);
+ abiflags_in.flags2 = BYTE_GET (abiflags_ext->flags2);
+
+ printf ("\nnanoMIPS ABI Flags Version: %d\n", abiflags_in.version);
+ printf ("\nISA: nanoMIPS%d", abiflags_in.isa_level);
+ if (abiflags_in.isa_rev > 1)
+ printf ("r%d", abiflags_in.isa_rev);
+ printf ("\nGPR size: %d",
+ get_nanomips_reg_size (abiflags_in.gpr_size));
+ printf ("\nCPR1 size: %d",
+ get_nanomips_reg_size (abiflags_in.cpr1_size));
+ printf ("\nCPR2 size: %d",
+ get_nanomips_reg_size (abiflags_in.cpr2_size));
+ fputs ("\nFP ABI: ", stdout);
+ print_nanomips_fp_abi_value (abiflags_in.fp_abi);
+ fputs ("ISA Extension: ", stdout);
+ print_nanomips_isa_ext (abiflags_in.isa_ext);
+ fputs ("\nASEs:", stdout);
+ print_nanomips_ases (abiflags_in.ases);
+ printf ("\nFLAGS 1: %8.8lx", abiflags_in.flags1);
+ printf ("\nFLAGS 2: %8.8lx", abiflags_in.flags2);
+ fputc ('\n', stdout);
+ free (abiflags_ext);
+ }
+ }
+ }
+
+ if (dynamic_section == NULL)
+ /* No information available. */
+ return 0;
+
+ for (entry = dynamic_section;
+ entry < dynamic_section + dynamic_nent && entry->d_tag != DT_NULL;
+ ++entry)
+ switch (entry->d_tag)
+ {
+ case DT_PLTGOT:
+ pltgot = entry->d_un.d_ptr;
+ break;
+ case DT_NANOMIPS_GOTNO:
+ symtabno = entry->d_un.d_val;
+ break;
+ default:
+ break;
+ }
+
+ if (options_offset != 0)
+ {
+ Elf_External_Options * eopt;
+ Elf_Internal_Options * iopt;
+ Elf_Internal_Options * option;
+ size_t offset;
+ int cnt;
+ sect = section_headers;
+
+ /* Find the section header so that we get the size. */
+ sect = find_section_by_type (SHT_MIPS_OPTIONS);
+ /* PR 17533 file: 012-277276-0.004. */
+ if (sect == NULL)
+ {
+ error (_("No MIPS_OPTIONS header found\n"));
+ return 0;
+ }
+
+ eopt = (Elf_External_Options *) get_data (NULL, file, options_offset, 1,
+ sect->sh_size, _("options"));
+ if (eopt)
+ {
+ iopt = (Elf_Internal_Options *)
+ cmalloc ((sect->sh_size / sizeof (eopt)), sizeof (* iopt));
+ if (iopt == NULL)
+ {
+ error (_("Out of memory allocatinf space for MIPS options\n"));
+ return 0;
+ }
+
+ offset = cnt = 0;
+ option = iopt;
+
+ while (offset < sect->sh_size)
+ {
+ Elf_External_Options * eoption;
+
+ eoption = (Elf_External_Options *) ((char *) eopt + offset);
+
+ option->kind = BYTE_GET (eoption->kind);
+ option->size = BYTE_GET (eoption->size);
+ option->section = BYTE_GET (eoption->section);
+ option->info = BYTE_GET (eoption->info);
+
+ offset += option->size;
+
+ ++option;
+ ++cnt;
+ }
+
+ printf (_("\nSection '%s' contains %d entries:\n"),
+ printable_section_name (sect), cnt);
+
+ option = iopt;
+
+ while (cnt-- > 0)
+ {
+ size_t len;
+
+ switch (option->kind)
+ {
+ case ODK_NULL:
+ /* This shouldn't happen. */
+ printf (" NULL %d %lx", option->section, option->info);
+ break;
+ case ODK_EXCEPTIONS:
+ fputs (" EXCEPTIONS fpe_min(", stdout);
+ process_mips_fpe_exception (option->info & OEX_FPU_MIN);
+ fputs (") fpe_max(", stdout);
+ process_mips_fpe_exception ((option->info & OEX_FPU_MAX) >> 8);
+ fputs (")", stdout);
+
+ if (option->info & OEX_PAGE0)
+ fputs (" PAGE0", stdout);
+ if (option->info & OEX_SMM)
+ fputs (" SMM", stdout);
+ if (option->info & OEX_FPDBUG)
+ fputs (" FPDBUG", stdout);
+ if (option->info & OEX_DISMISS)
+ fputs (" DISMISS", stdout);
+ break;
+ case ODK_PAD:
+ fputs (" PAD ", stdout);
+ if (option->info & OPAD_PREFIX)
+ fputs (" PREFIX", stdout);
+ if (option->info & OPAD_POSTFIX)
+ fputs (" POSTFIX", stdout);
+ if (option->info & OPAD_SYMBOL)
+ fputs (" SYMBOL", stdout);
+ break;
+ case ODK_HWPATCH:
+ fputs (" HWPATCH ", stdout);
+ if (option->info & OHW_R4KEOP)
+ fputs (" R4KEOP", stdout);
+ if (option->info & OHW_R8KPFETCH)
+ fputs (" R8KPFETCH", stdout);
+ if (option->info & OHW_R5KEOP)
+ fputs (" R5KEOP", stdout);
+ if (option->info & OHW_R5KCVTL)
+ fputs (" R5KCVTL", stdout);
+ break;
+ case ODK_FILL:
+ fputs (" FILL ", stdout);
+ /* XXX Print content of info word? */
+ break;
+ case ODK_TAGS:
+ fputs (" TAGS ", stdout);
+ /* XXX Print content of info word? */
+ break;
+ case ODK_HWAND:
+ fputs (" HWAND ", stdout);
+ if (option->info & OHWA0_R4KEOP_CHECKED)
+ fputs (" R4KEOP_CHECKED", stdout);
+ if (option->info & OHWA0_R4KEOP_CLEAN)
+ fputs (" R4KEOP_CLEAN", stdout);
+ break;
+ case ODK_HWOR:
+ fputs (" HWOR ", stdout);
+ if (option->info & OHWA0_R4KEOP_CHECKED)
+ fputs (" R4KEOP_CHECKED", stdout);
+ if (option->info & OHWA0_R4KEOP_CLEAN)
+ fputs (" R4KEOP_CLEAN", stdout);
+ break;
+ case ODK_GP_GROUP:
+ printf (" GP_GROUP %#06lx self-contained %#06lx",
+ option->info & OGP_GROUP,
+ (option->info & OGP_SELF) >> 16);
+ break;
+ case ODK_IDENT:
+ printf (" IDENT %#06lx self-contained %#06lx",
+ option->info & OGP_GROUP,
+ (option->info & OGP_SELF) >> 16);
+ break;
+ default:
+ /* This shouldn't happen. */
+ printf (" %3d ??? %d %lx",
+ option->kind, option->section, option->info);
+ break;
+ }
+
+ len = sizeof (* eopt);
+ while (len < option->size)
+ if (((char *) option)[len] >= ' '
+ && ((char *) option)[len] < 0x7f)
+ printf ("%c", ((char *) option)[len++]);
+ else
+ printf ("\\%03o", ((char *) option)[len++]);
+
+ fputs ("\n", stdout);
+ ++option;
+ }
+
+ free (eopt);
+ }
+ }
+
+ if (pltgot != 0)
+ {
+ bfd_vma ent, end;
+ size_t i, offset;
+ unsigned char * data;
+ int addr_size;
+
+ ent = pltgot;
+ addr_size = (is_32bit_elf ? 4 : 8);
+
+ if (symtabno < gotsym)
+ {
+ error (_("The GOT symbol offset (%lu) is greater than the symbol table size (%lu)\n"),
+ (long) gotsym, (long) symtabno);
+ return 0;
+ }
+
+ end = pltgot + (symtabno - gotsym) * addr_size;
+ offset = offset_from_vma (file, pltgot, end - pltgot);
+ data = (unsigned char *) get_data (NULL, file, offset,
+ end - pltgot, 1,
+ _("Global Offset Table data"));
+ if (data == NULL)
+ return 0;
+
+ printf (_(" Canonical gp value: "));
+ print_vma (pltgot + 0x7ff0, LONG_HEX);
+ printf ("\n\n");
+
+ printf (_(" Reserved entries:\n"));
+ printf (_(" %*s %10s %*s Purpose\n"),
+ addr_size * 2, _("Address"), _("Access"),
+ addr_size * 2, _("Initial"));
+ ent = print_mips_got_entry (data, pltgot, ent);
+ printf (_(" Lazy resolver\n"));
+ if (data
+ && (byte_get (data + ent - pltgot, addr_size)
+ >> (addr_size * 8 - 1)) != 0)
+ {
+ ent = print_mips_got_entry (data, pltgot, ent);
+ printf (_(" Module pointer (GNU extension)\n"));
+ }
+ printf ("\n");
+
+ printf ("\n");
+
+ printf (_(" Entries:\n"));
+ printf (" %*s %10s %*s %*s %-7s %3s %s\n",
+ addr_size * 2, _("Address"),
+ _("Access"),
+ addr_size * 2, _("Initial"),
+ addr_size * 2, _("Sym.Val."),
+ _("Type"),
+ /* Note for translators: "Ndx" = abbreviated form of "Index". */
+ _("Ndx"), _("Name"));
+
+ for (i = gotsym; i < symtabno; i++)
+ {
+ ent = print_mips_got_entry (data, pltgot, ent);
+ printf (" ");
+
+ printf ("\n");
+ }
+
+ if (data)
+ free (data);
+ }
+
+ return 1;
+}
+
static bool
process_nds32_specific (Filedata * filedata)
{
@@ -22027,6 +22548,8 @@ process_arch_specific (Filedata * filedata)
return process_attributes (filedata, "c6xabi", SHT_C6000_ATTRIBUTES,
display_tic6x_attribute,
display_generic_attribute);
+ case EM_NANOMIPS:
+ return process_nanomips_specific (file);
case EM_CSKY:
return process_attributes (filedata, "csky", SHT_CSKY_ATTRIBUTES,
diff --git a/include/dis-asm.h b/include/dis-asm.h
index 4f91df12498..17f0a644e84 100644
--- a/include/dis-asm.h
+++ b/include/dis-asm.h
@@ -300,6 +300,11 @@ typedef struct disassemble_info
/* Set to true if the disassembler applied styling to the output,
otherwise, set to false. */
bool created_styled_output;
+
+ /* Predict the size of an instruction. */
+ int (* predict_insn_length)
+ (bfd_vma, int, struct disassemble_info *);
+
} disassemble_info;
/* This struct is used to pass information about valid disassembler
@@ -358,6 +363,7 @@ typedef int (*disassembler_ftype) (bfd_vma, disassemble_info *);
extern int print_insn_m32c (bfd_vma, disassemble_info *);
extern int print_insn_mep (bfd_vma, disassemble_info *);
extern int print_insn_s12z (bfd_vma, disassemble_info *);
+extern int print_insn_nanomips (bfd_vma, disassemble_info *);
extern int print_insn_sh (bfd_vma, disassemble_info *);
extern int print_insn_sparc (bfd_vma, disassemble_info *);
extern int print_insn_rx (bfd_vma, disassemble_info *);
@@ -372,6 +378,7 @@ extern disassembler_ftype cris_get_disassembler (bfd *);
extern void print_aarch64_disassembler_options (FILE *);
extern void print_i386_disassembler_options (FILE *);
extern void print_mips_disassembler_options (FILE *);
+extern void print_nanomips_disassembler_options (FILE *);
extern void print_nfp_disassembler_options (FILE *);
extern void print_ppc_disassembler_options (FILE *);
extern void print_riscv_disassembler_options (FILE *);
@@ -467,6 +474,14 @@ extern asymbol *generic_symbol_at_address
extern bool generic_symbol_is_valid
(asymbol *, struct disassemble_info *);
+/* Generic insn length, returns 2nd argument. */
+extern int generic_predict_insn_length
+ (bfd_vma, int, struct disassemble_info *);
+
+extern int nanomips_predict_insn_length (bfd_vma memaddr_base,
+ int previous_octect ATTRIBUTE_UNUSED,
+ struct disassemble_info *info);
+
/* Method to initialize a disassemble_info struct. This should be
called by all applications creating such a struct. */
extern void init_disassemble_info (struct disassemble_info *dinfo, void *stream,
diff --git a/include/elf/common.h b/include/elf/common.h
index e4bc53e35b4..8a98dd81630 100644
--- a/include/elf/common.h
+++ b/include/elf/common.h
@@ -346,6 +346,7 @@
#define EM_CEVA_X2 246 /* CEVA X2 Processor Family */
#define EM_BPF 247 /* Linux BPF – in-kernel virtual machine. */
#define EM_GRAPHCORE_IPU 248 /* Graphcore Intelligent Processing Unit */
+#define EM_NANOMIPS 249 /* MIPS Tech nanoMIPS architecture. */
#define EM_IMG1 249 /* Imagination Technologies */
#define EM_NFP 250 /* Netronome Flow Processor. */
#define EM_VE 251 /* NEC Vector Engine */
diff --git a/include/elf/mips-common.h b/include/elf/mips-common.h
new file mode 100644
index 00000000000..1d941fa9f2d
--- /dev/null
+++ b/include/elf/mips-common.h
@@ -0,0 +1,41 @@
+/* MIPS ELF support for BFD.
+ Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+ This file is part of BFD, the Binary File Descriptor library.
+
+ This program 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 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* This file holds definitions common to the MIPS and nanoMIPS ELF ABIs. */
+
+#ifndef _ELF_MIPS_COMMON_H
+#define _ELF_MIPS_COMMON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Values for the xxx_size bytes of an ABI flags structure. */
+
+#define AFL_REG_NONE 0x00 /* No registers. */
+#define AFL_REG_32 0x01 /* 32-bit registers. */
+#define AFL_REG_64 0x02 /* 64-bit registers. */
+#define AFL_REG_128 0x03 /* 128-bit registers. */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ELF_MIPS_COMMON_H */
diff --git a/include/elf/nanomips.h b/include/elf/nanomips.h
new file mode 100644
index 00000000000..82d081c04f8
--- /dev/null
+++ b/include/elf/nanomips.h
@@ -0,0 +1,260 @@
+/* nanoMIPS ELF support for BFD.
+ Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+ Written by Faraz Shahbazker <faraz.shahbazker@mips.com>
+
+ This file is part of BFD, the Binary File Descriptor library.
+
+ This program 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 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* This file holds definitions specific to the nanoMIPS ELF ABI. */
+
+#ifndef _ELF_NANOMIPS_H
+#define _ELF_NANOMIPS_H
+
+#include "elf/reloc-macros.h"
+#include "elf/mips.h"
+#include "elf/mips-common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+START_RELOC_NUMBERS (elf_nanomips_reloc_type)
+ RELOC_NUMBER (R_NANOMIPS_NONE, 0)
+ RELOC_NUMBER (R_NANOMIPS_32, 1)
+ RELOC_NUMBER (R_NANOMIPS_64, 2)
+ RELOC_NUMBER (R_NANOMIPS_NEG, 3)
+ RELOC_NUMBER (R_NANOMIPS_ASHIFTR_1, 4)
+ RELOC_NUMBER (R_NANOMIPS_UNSIGNED_8, 5)
+ RELOC_NUMBER (R_NANOMIPS_SIGNED_8, 6)
+ RELOC_NUMBER (R_NANOMIPS_UNSIGNED_16, 7)
+ RELOC_NUMBER (R_NANOMIPS_SIGNED_16, 8)
+ RELOC_NUMBER (R_NANOMIPS_RELATIVE, 9)
+ RELOC_NUMBER (R_NANOMIPS_GLOBAL, 10)
+ RELOC_NUMBER (R_NANOMIPS_JUMP_SLOT, 11)
+ RELOC_NUMBER (R_NANOMIPS_IRELATIVE, 12)
+
+ RELOC_NUMBER (R_NANOMIPS_PC25_S1, 13)
+ RELOC_NUMBER (R_NANOMIPS_PC21_S1, 14)
+ RELOC_NUMBER (R_NANOMIPS_PC14_S1, 15)
+ RELOC_NUMBER (R_NANOMIPS_PC11_S1, 16)
+ RELOC_NUMBER (R_NANOMIPS_PC10_S1, 17)
+ RELOC_NUMBER (R_NANOMIPS_PC7_S1, 18)
+ RELOC_NUMBER (R_NANOMIPS_PC4_S1, 19)
+
+ RELOC_NUMBER (R_NANOMIPS_GPREL19_S2, 20)
+ RELOC_NUMBER (R_NANOMIPS_GPREL18_S3, 21)
+ RELOC_NUMBER (R_NANOMIPS_GPREL18, 22)
+ RELOC_NUMBER (R_NANOMIPS_GPREL17_S1, 23)
+ RELOC_NUMBER (R_NANOMIPS_GPREL16_S2, 24)
+ RELOC_NUMBER (R_NANOMIPS_GPREL7_S2, 25)
+ RELOC_NUMBER (R_NANOMIPS_GPREL_HI20, 26)
+ RELOC_NUMBER (R_NANOMIPS_PCHI20, 27)
+
+ RELOC_NUMBER (R_NANOMIPS_HI20, 28)
+ RELOC_NUMBER (R_NANOMIPS_LO12, 29)
+ RELOC_NUMBER (R_NANOMIPS_GPREL_I32, 30)
+ RELOC_NUMBER (R_NANOMIPS_PC_I32, 31)
+ RELOC_NUMBER (R_NANOMIPS_I32, 32)
+ RELOC_NUMBER (R_NANOMIPS_GOT_DISP, 33)
+ RELOC_NUMBER (R_NANOMIPS_GOTPC_I32, 34)
+ RELOC_NUMBER (R_NANOMIPS_GOTPC_HI20, 35)
+ RELOC_NUMBER (R_NANOMIPS_GOT_LO12, 36)
+ RELOC_NUMBER (R_NANOMIPS_GOT_CALL, 37)
+ RELOC_NUMBER (R_NANOMIPS_GOT_PAGE, 38)
+ RELOC_NUMBER (R_NANOMIPS_GOT_OFST, 39)
+ RELOC_NUMBER (R_NANOMIPS_LO4_S2, 40)
+ /* Reserved for 64-bit ABI. */
+ RELOC_NUMBER (R_NANOMIPS_RESERVED1, 41)
+ RELOC_NUMBER (R_NANOMIPS_GPREL_LO12, 42)
+ RELOC_NUMBER (R_NANOMIPS_SCN_DISP, 43)
+ RELOC_NUMBER (R_NANOMIPS_COPY, 44)
+
+ RELOC_NUMBER (R_NANOMIPS_ALIGN, 64)
+ RELOC_NUMBER (R_NANOMIPS_FILL, 65)
+ RELOC_NUMBER (R_NANOMIPS_MAX, 66)
+ RELOC_NUMBER (R_NANOMIPS_INSN32, 67)
+ RELOC_NUMBER (R_NANOMIPS_FIXED, 68)
+ RELOC_NUMBER (R_NANOMIPS_NORELAX, 69)
+ RELOC_NUMBER (R_NANOMIPS_RELAX, 70)
+ RELOC_NUMBER (R_NANOMIPS_SAVERESTORE, 71)
+ RELOC_NUMBER (R_NANOMIPS_INSN16, 72)
+ RELOC_NUMBER (R_NANOMIPS_JALR32, 73)
+ RELOC_NUMBER (R_NANOMIPS_JALR16, 74)
+ RELOC_NUMBER (R_NANOMIPS_JUMPTABLE_LOAD, 75)
+ RELOC_NUMBER (R_NANOMIPS_FRAME_REG, 76)
+
+ /* TLS relocations. */
+ RELOC_NUMBER (R_NANOMIPS_TLS_DTPMOD, 80)
+ RELOC_NUMBER (R_NANOMIPS_TLS_DTPREL, 81)
+ RELOC_NUMBER (R_NANOMIPS_TLS_TPREL, 82)
+ RELOC_NUMBER (R_NANOMIPS_TLS_GD, 83)
+ RELOC_NUMBER (R_NANOMIPS_TLS_GD_I32, 84)
+ RELOC_NUMBER (R_NANOMIPS_TLS_LD, 85)
+ RELOC_NUMBER (R_NANOMIPS_TLS_LD_I32, 86)
+ RELOC_NUMBER (R_NANOMIPS_TLS_DTPREL12, 87)
+ RELOC_NUMBER (R_NANOMIPS_TLS_DTPREL16, 88)
+ RELOC_NUMBER (R_NANOMIPS_TLS_DTPREL_I32, 89)
+ RELOC_NUMBER (R_NANOMIPS_TLS_GOTTPREL, 90)
+ RELOC_NUMBER (R_NANOMIPS_TLS_GOTTPREL_PC_I32, 91)
+ RELOC_NUMBER (R_NANOMIPS_TLS_TPREL12, 92)
+ RELOC_NUMBER (R_NANOMIPS_TLS_TPREL16, 93)
+ RELOC_NUMBER (R_NANOMIPS_TLS_TPREL_I32, 94)
+
+ FAKE_RELOC (R_NANOMIPS_max, 94)
+ /* May be used for compact unwind tables in the future. */
+ RELOC_NUMBER (R_NANOMIPS_PC32, 248)
+ RELOC_NUMBER (R_NANOMIPS_EH, 249)
+ /* These are GNU extensions to enable C++ vtable garbage collection. */
+ RELOC_NUMBER (R_NANOMIPS_GNU_VTINHERIT, 253)
+ RELOC_NUMBER (R_NANOMIPS_GNU_VTENTRY, 254)
+END_RELOC_NUMBERS (R_NANOMIPS_maxext)
+
+/* Processor specific flags for the ELF header e_flags field. */
+
+/* File may be relaxed by the linker. */
+#define EF_NANOMIPS_LINKRELAX 0x00000001
+
+/* File contains position independent code. */
+#define EF_NANOMIPS_PIC 0x00000002
+
+/* Indicates code compiled for a 64-bit machine in 32-bit mode
+ (regs are 32-bits wide). */
+#define EF_NANOMIPS_32BITMODE 0x00000004
+
+/* File contains position independent code. */
+#define EF_NANOMIPS_PID 0x00000008
+
+/* File contains pure PC-relative code. */
+#define EF_NANOMIPS_PCREL 0x00000010
+
+/* Four bit nanoMIPS architecture field. */
+#define EF_NANOMIPS_ARCH 0xf0000000
+
+/* -march=32r6[s] code. */
+#define E_NANOMIPS_ARCH_32R6 0x00000000
+
+/* -march=64r6 code. */
+#define E_NANOMIPS_ARCH_64R6 0x10000000
+
+/* The ABI of the file. */
+#define EF_NANOMIPS_ABI 0x0000F000
+
+/* nanoMIPS ABI in 32 bit mode. */
+#define E_NANOMIPS_ABI_P32 0x00001000
+
+/* nanoMIPS ABI in 64 bit mode. */
+#define E_NANOMIPS_ABI_P64 0x00002000
+
+/* Machine variant if we know it. This field was invented at Cygnus
+ for MIPS. It may be used similarly for nanoMIPS. */
+
+#define EF_NANOMIPS_MACH 0x00FF0000
+
+\f
+/* Processor specific section types. */
+
+/* ABI related flags section. */
+#define SHT_NANOMIPS_ABIFLAGS 0x70000000
+
+\f
+/* Processor specific program header types. */
+
+/* Records ABI related flags. */
+#define PT_NANOMIPS_ABIFLAGS 0x70000000
+
+\f
+
+/* Object attribute tags. */
+enum
+{
+ /* 0-3 are generic. */
+
+ /* Floating-point ABI used by this object file. */
+ Tag_GNU_NANOMIPS_ABI_FP = 4,
+
+ /* MSA ABI used by this object file. */
+ Tag_GNU_NANOMIPS_ABI_MSA = 8,
+};
+
+/* Object attribute values. */
+enum
+{
+ /* Values defined for Tag_GNU_NANOMIPS_ABI_FP. */
+
+ /* Not tagged or not using any ABIs affected by the differences. */
+ Val_GNU_NANOMIPS_ABI_FP_ANY = 0,
+
+ /* Using hard-float -mdouble-float. */
+ Val_GNU_NANOMIPS_ABI_FP_DOUBLE = 1,
+
+ /* Using hard-float -msingle-float. */
+ Val_GNU_NANOMIPS_ABI_FP_SINGLE = 2,
+
+ /* Using soft-float. */
+ Val_GNU_NANOMIPS_ABI_FP_SOFT = 3,
+
+ /* Not tagged or not using any ABIs affected by the differences. */
+ Val_GNU_NANOMIPS_ABI_MSA_ANY = 0,
+
+ /* Using 128-bit MSA. */
+ Val_GNU_NANOMIPS_ABI_MSA_128 = 1,
+};
+
+/* Masks for the ases word of an ABI flags structure.
+
+ Unfortunate decisions in early development transitioning from MIPS
+ to nanoMIPS, left this horifically fragmented. Bits marked as
+ UNUSED may be cannibalized for future ASEs; bits marked as RESERVED
+ are intended to remain blocked. If MIPS history is anything to go
+ by, nanoMIPS will eventually spawn enough ASEs to fill up the gaps!
+*/
+
+#define NANOMIPS_ASE_TLB 0x00000001 /* TLB control ASE. */
+#define NANOMIPS_ASE_UNUSED1 0x00000002 /* was DSP R2 ASE. */
+#define NANOMIPS_ASE_EVA 0x00000004 /* Enhanced VA Scheme. */
+#define NANOMIPS_ASE_MCU 0x00000008 /* MCU (MicroController) ASE. */
+#define NANOMIPS_ASE_UNUSED2 0x00000010 /* was MDMX ASE. */
+#define NANOMIPS_ASE_UNUSED3 0x00000020 /* was MIPS-3D ASE. */
+#define NANOMIPS_ASE_MT 0x00000040 /* MT ASE. */
+#define NANOMIPS_ASE_UNUSED4 0x00000080 /* was SmartMIPS ASE. */
+#define NANOMIPS_ASE_VIRT 0x00000100 /* VZ ASE. */
+#define NANOMIPS_ASE_MSA 0x00000200 /* MSA ASE. */
+#define NANOMIPS_ASE_RESERVED1 0x00000400 /* was MIPS16 ASE. */
+#define NANOMIPS_ASE_RESERVED2 0x00000800 /* was MICROMIPS ASE. */
+#define NANOMIPS_ASE_UNUSED6 0x00001000 /* was XPA. */
+#define NANOMIPS_ASE_DSPR3 0x00002000 /* DSP R3 ASE. */
+#define NANOMIPS_ASE_UNUSED5 0x00004000 /* was MIPS16 E2 Extension. */
+#define NANOMIPS_ASE_CRC 0x00008000 /* CRC extension. */
+#define NANOMIPS_ASE_CRYPTO 0x00010000 /* Cryptography extension. */
+#define NANOMIPS_ASE_GINV 0x00020000 /* GINV ASE. */
+#define NANOMIPS_ASE_xNMS 0x00040000 /* not nanoMIPS Subset. */
+#define NANOMIPS_ASE_MASK 0x0007af4d /* All valid ASEs. */
+
+/* nanoMIPS ELF flags routines. */
+extern Elf_Internal_ABIFlags_v0 * bfd_nanomips_elf_get_abiflags (bfd *);
+
+extern void bfd_nanomips_elf_swap_abiflags_v0_in
+ (bfd *, const Elf_External_ABIFlags_v0 *, Elf_Internal_ABIFlags_v0 *);
+extern void bfd_nanomips_elf_swap_abiflags_v0_out
+ (bfd *, const Elf_Internal_ABIFlags_v0 *, Elf_External_ABIFlags_v0 *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ELF_NANOMIPS_H */
diff --git a/include/opcode/nanomips.h b/include/opcode/nanomips.h
new file mode 100644
index 00000000000..d77120e244d
--- /dev/null
+++ b/include/opcode/nanomips.h
@@ -0,0 +1,1453 @@
+/* nanomips.h. nanoMIPS opcode list for GDB, the GNU debugger.
+ Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+ Written by Faraz Shahbazker <faraz.shahbazker@mips.com>
+
+ This file is part of GDB, GAS, and the GNU binutils.
+
+ GDB, GAS, and the GNU binutils are free software; you can redistribute
+ them and/or modify them 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.
+
+ GDB, GAS, and the GNU binutils are distributed in the hope that they
+ 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 this file; see the file COPYING3. If not, write to the Free
+ Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#ifndef _NANOMIPS_H_
+#define _NANOMIPS_H_
+
+#include "bfd.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Enumerates the various types of nanoMIPS operand. */
+enum nanomips_operand_type {
+ /* Described by nanomips_int_operand. */
+ OP_INT,
+
+ /* Described by nanomips_mapped_int_operand. */
+ OP_MAPPED_INT,
+
+ /* Described by nanomips_msb_operand. */
+ OP_MSB,
+
+ /* Described by nanomips_reg_operand. */
+ OP_REG,
+
+ /* Like OP_REG, but can be omitted if the register is the same as the
+ previous operand. */
+ OP_OPTIONAL_REG,
+
+ /* Described by nanomips_reg_pair_operand. */
+ OP_REG_PAIR,
+
+ /* Described by nanomips_pcrel_operand. */
+ OP_PCREL,
+
+ /* The register list and frame size for a MIPS16 SAVE or RESTORE
+ instruction. */
+ OP_SAVE_RESTORE_LIST,
+
+ /* A register operand that must match the destination register. */
+ OP_REPEAT_DEST_REG,
+
+ /* A register operand that must match the previous register. */
+ OP_REPEAT_PREV_REG,
+
+ /* Described by nanomips_prev_operand. */
+ OP_CHECK_PREV,
+
+ /* A register operand that must not be zero. */
+ OP_NON_ZERO_REG,
+
+ /* The floating-point register list for a nanoMIPS SAVE or RESTORE
+ instruction. */
+ OP_SAVE_RESTORE_FP_LIST,
+
+ /* Fractured upper immediate PC-offset for nanoMIPS */
+ OP_HI20_PCREL,
+
+ /* Fractured upper immediate 20-bit signed integer for nanoMIPS */
+ OP_HI20_INT,
+
+ /* Fractured upper immediate 20-bit scaled integer for nanoMIPS */
+ OP_HI20_SCALE,
+
+ /* A non-zero PC-relative offset. */
+ OP_NON_ZERO_PCREL_S1,
+
+ /* To check a mapped register against a previous operand. */
+ OP_MAPPED_CHECK_PREV,
+
+ /* Unsigned word operand. */
+ OP_UINT_WORD,
+
+ /* Signed word operand. */
+ OP_INT_WORD,
+
+ /* Immediate PC-relative word operand. */
+ OP_PC_WORD,
+
+ /* Immediate GP-relative word operand. */
+ OP_GPREL_WORD,
+
+ /* Don't care bits. */
+ OP_DONT_CARE,
+
+ /* Immediate unsigned word operand, to be negated. */
+ OP_NEG_INT,
+
+ /* Immediate (non-relocatable) integer operand. */
+ OP_IMM_INT,
+
+ /* Immediate (non-relocatable) word operand. */
+ OP_IMM_WORD,
+
+ /* Base register for limited types of offsets. */
+ OP_BASE_CHECK_OFFSET,
+
+ /* Copy over bits from another part of instruction. */
+ OP_COPY_BITS,
+
+ /* Select bits for a COP0 register. */
+ OP_CP0SEL,
+};
+
+/* Enumerates the types of nanoMIPS register. */
+enum nanomips_reg_operand_type {
+ /* General registers $0-$31. Software names like $at can also be used. */
+ OP_REG_GP,
+
+ /* Floating-point registers $f0-$f31. */
+ OP_REG_FP,
+
+ /* DSP accumulator registers $ac0-$ac3. */
+ OP_REG_ACC,
+
+ /* Coprocessor registers in numeric format, $0-$31. */
+ OP_REG_COPRO,
+
+ /* Hardware registers $0-$31. Mnemonic names like hwr_cpunum can
+ also be used in some contexts. */
+ OP_REG_HW,
+
+ /* MSA registers $w0-$w31. */
+ OP_REG_MSA,
+
+ /* MSA control registers $0-$31. */
+ OP_REG_MSA_CTRL,
+
+ /* Co-processor 0 named registers. */
+ OP_REG_CP0,
+
+ /* Co-processor 0 named registers with select. */
+ OP_REG_CP0SEL,
+
+ /* Co-processor 0 named registers with select. */
+ OP_REG_HWRSEL
+};
+
+/* Base class for all operands. */
+struct nanomips_operand
+{
+ /* The type of the operand. */
+ enum nanomips_operand_type type;
+
+ /* The operand occupies SIZE bits of the instruction, starting at LSB. */
+ unsigned short size;
+ unsigned short lsb;
+
+ /* These are used to split a value across two different
+ parts of the instruction encoding. */
+ unsigned int size_top;
+ unsigned int lsb_top;
+};
+
+/* Describes an integer operand with a regular encoding pattern. */
+struct nanomips_int_operand
+{
+ struct nanomips_operand root;
+
+ /* The low ROOT.SIZE bits of MAX_VAL encodes (MAX_VAL + BIAS) << SHIFT.
+ The cyclically previous field value encodes 1 << SHIFT less than that,
+ and so on. E.g.
+
+ - for { { T, 4, L }, 14, 0, 0 }, field values 0...14 encode themselves,
+ but 15 encodes -1.
+
+ - { { T, 8, L }, 127, 0, 2 } is a normal signed 8-bit operand that is
+ shifted left two places.
+
+ - { { T, 3, L }, 8, 0, 0 } is a normal unsigned 3-bit operand except
+ that 0 encodes 8.
+
+ - { { ... }, 0, 1, 3 } means that N encodes (N + 1) << 3. */
+ unsigned int max_val;
+ int bias;
+ unsigned int shift;
+
+ /* True if the operand should be printed as hex rather than decimal. */
+ bool print_hex;
+};
+
+/* Uses a lookup table to describe a small integer operand. */
+struct nanomips_mapped_int_operand
+{
+ struct nanomips_operand root;
+
+ /* Maps each encoding value to the integer that it represents. */
+ const int *int_map;
+
+ /* True if the operand should be printed as hex rather than decimal. */
+ bool print_hex;
+};
+
+/* An operand that encodes the most significant bit position of a bitfield.
+ Given a bitfield that spans bits [MSB, LSB], some operands of this type
+ encode MSB directly while others encode MSB - LSB. Each operand of this
+ type is preceded by an integer operand that specifies LSB.
+
+ The assembly form varies between instructions. For some instructions,
+ such as EXT, the operand is written as the bitfield size. For others,
+ such as EXTS, it is written in raw MSB - LSB form. */
+struct nanomips_msb_operand
+{
+ struct nanomips_operand root;
+
+ /* The assembly-level operand encoded by a field value of 0. */
+ int bias;
+
+ /* True if the operand encodes MSB directly, false if it encodes
+ MSB - LSB. */
+ bool add_lsb;
+
+ /* The maximum value of MSB + 1. */
+ unsigned int opsize;
+};
+
+/* Describes a single register operand. */
+struct nanomips_reg_operand
+{
+ struct nanomips_operand root;
+
+ /* The type of register. */
+ enum nanomips_reg_operand_type reg_type;
+
+ /* If nonnull, REG_MAP[N] gives the register associated with encoding N,
+ otherwise the encoding is the same as the register number. */
+ const unsigned char *reg_map;
+};
+
+/* Describes an operand that which must match a condition based on the
+ previous operand. */
+struct nanomips_check_prev_operand
+{
+ struct nanomips_operand root;
+
+ bool greater_than_ok;
+ bool less_than_ok;
+ bool equal_ok;
+ bool zero_ok;
+};
+
+/* Describes an operand that encodes a pair of registers. */
+struct nanomips_reg_pair_operand
+{
+ struct nanomips_operand root;
+
+ /* The type of register. */
+ enum nanomips_reg_operand_type reg_type;
+
+ /* Encoding N represents REG1_MAP[N], REG2_MAP[N]. */
+ unsigned char *reg1_map;
+ unsigned char *reg2_map;
+};
+
+/* Describes an operand that is calculated relative to a base PC.
+ The base PC is usually the address of the following instruction,
+ but the rules for MIPS16 instructions like ADDIUPC are more complicated. */
+struct nanomips_pcrel_operand
+{
+ /* Encodes the offset. */
+ struct nanomips_int_operand root;
+
+ /* The low ALIGN_LOG2 bits of the base PC are cleared to give PC',
+ which is then added to the offset encoded by ROOT. */
+ unsigned int align_log2 : 8;
+
+ /* If INCLUDE_ISA_BIT, the ISA bit of the original base PC is then
+ reinstated. This is true for jumps and branches and false for
+ PC-relative data instructions. */
+ unsigned int include_isa_bit : 1;
+
+ /* If FLIP_ISA_BIT, the ISA bit of the result is inverted.
+ This is true for JALX and false otherwise. */
+ unsigned int flip_isa_bit : 1;
+};
+
+/* This structure holds information for a particular instruction. */
+
+struct nanomips_opcode
+{
+ /* The name of the instruction. */
+ const char *name;
+ /* An optional suffix. */
+ const char *suffix;
+ /* A string describing the arguments for this instruction. */
+ const char *args;
+ /* The basic opcode for the instruction. When assembling, this
+ opcode is modified by the arguments to produce the actual opcode
+ that is used. If pinfo is INSN_MACRO, then this is 0. */
+ unsigned long match;
+ /* If pinfo is not INSN_MACRO, then this is a bit mask for the
+ relevant portions of the opcode when disassembling. If the
+ actual opcode anded with the match field equals the opcode field,
+ then we have found the correct instruction. If pinfo is
+ INSN_MACRO, then this field is the macro identifier. */
+ unsigned long mask;
+ /* For a macro, this is INSN_MACRO. Otherwise, it is a collection
+ of bits describing the instruction, notably any relevant hazard
+ information. */
+ unsigned long pinfo;
+ /* A collection of additional bits describing the instruction. */
+ unsigned long pinfo2;
+ /* A collection of bits describing the instruction sets of which this
+ instruction or macro is a member. */
+ unsigned long membership;
+ /* A collection of bits describing the ASE of which this instruction
+ or macro is a member. */
+ unsigned long ase;
+};
+
+/* Return true if the assembly syntax allows OPERAND to be omitted. */
+
+static inline bool
+nanomips_optional_operand_p (const struct nanomips_operand *operand)
+{
+ return (operand->type == OP_OPTIONAL_REG
+ || operand->type == OP_REPEAT_PREV_REG
+ || (operand->type != OP_INT
+ && operand->size == 0
+ && operand->lsb == 0));
+}
+
+/* Return a version of INSN in which the field specified by OPERAND
+ has value UVAL. */
+
+static inline unsigned int
+nanomips_insert_operand (const struct nanomips_operand *operand,
+ unsigned int insn, unsigned int uval)
+{
+ unsigned int mask;
+ unsigned int size_bottom = operand->size - operand->size_top;
+
+ mask = (1 << size_bottom) - 1;
+ insn &= ~(mask << operand->lsb);
+ insn |= (uval & mask) << operand->lsb;
+
+ mask = (1 << operand->size_top) - 1;
+ insn &= ~(mask << operand->lsb_top);
+ insn |= ((uval & (mask << size_bottom)) >> size_bottom) << operand->lsb_top;
+ return insn;
+}
+
+/* Extract OPERAND from instruction INSN. */
+
+static inline unsigned int
+nanomips_extract_operand (const struct nanomips_operand *operand,
+ unsigned int insn)
+{
+ unsigned int uval;
+ unsigned int size_bottom = operand->size - operand->size_top;
+
+ uval = (insn >> operand->lsb_top) & ((1 << operand->size_top) - 1);
+ uval <<= size_bottom;
+ uval |= (insn >> operand->lsb) & ((1 << size_bottom) - 1);
+ return uval;
+}
+
+/* UVAL is the value encoded by OPERAND. Return it in signed form. */
+
+static inline int
+nanomips_signed_operand (const struct nanomips_operand *operand,
+ unsigned int uval)
+{
+ unsigned int sign_bit, mask;
+
+ mask = (1 << operand->size) - 1;
+ sign_bit = 1 << (operand->size - 1);
+ return ((uval + sign_bit) & mask) - sign_bit;
+}
+
+/* Return the integer that OPERAND encodes as UVAL. */
+
+static inline int
+nanomips_decode_int_operand (const struct nanomips_int_operand *operand,
+ unsigned int uval)
+{
+ uval |= (operand->max_val - uval) & -(1 << operand->root.size);
+ uval += operand->bias;
+ uval <<= operand->shift;
+ return uval;
+}
+
+/* Return the maximum value that can be encoded by OPERAND. */
+
+static inline int
+nanomips_int_operand_max (const struct nanomips_int_operand *operand)
+{
+ return (operand->max_val + operand->bias) << operand->shift;
+}
+
+/* Return the minimum value that can be encoded by OPERAND. */
+
+static inline int
+nanomips_int_operand_min (const struct nanomips_int_operand *operand)
+{
+ unsigned int mask;
+
+ mask = (1 << operand->root.size) - 1;
+ return nanomips_int_operand_max (operand) - (mask << operand->shift);
+}
+
+/* Return the register that OPERAND encodes as UVAL. */
+
+static inline int
+nanomips_decode_reg_operand (const struct nanomips_reg_operand *operand,
+ unsigned int uval)
+{
+ if (operand->reg_map)
+ uval = operand->reg_map[uval];
+ return uval;
+}
+
+/* PC-relative operand OPERAND has value UVAL and is relative to BASE_PC.
+ Return the address that it encodes. */
+
+static inline bfd_vma
+nanomips_decode_pcrel_operand (const struct nanomips_pcrel_operand *operand,
+ bfd_vma base_pc, unsigned int uval)
+{
+ bfd_vma addr;
+
+ addr = base_pc & -(1 << operand->align_log2);
+ addr += nanomips_decode_int_operand (&operand->root, uval);
+ if (operand->include_isa_bit)
+ addr |= base_pc & 1;
+ if (operand->flip_isa_bit)
+ addr ^= 1;
+ return addr;
+}
+
+/* Describes an operand that encapsulates a mapped register with
+ a check against the previous operand. */
+struct nanomips_mapped_check_prev_operand
+{
+ struct nanomips_operand root;
+
+ enum nanomips_reg_operand_type reg_type;
+ const unsigned char *reg_map;
+
+ bool greater_than_ok;
+ bool less_than_ok;
+ bool equal_ok;
+ bool zero_ok;
+};
+
+/* Describes an operand that encapsulates a base register with
+ a check against the type of offset. */
+struct nanomips_base_check_offset_operand
+{
+ struct nanomips_operand root;
+
+ enum nanomips_reg_operand_type reg_type;
+
+ bool const_ok;
+ bool expr_ok;
+};
+
+/* Return true if MO is an instruction that requires 32-bit encoding. */
+
+static inline bool
+nanomips_opcode_32bit_p (const struct nanomips_opcode *mo)
+{
+ return mo->mask >> 16 != 0;
+}
+
+static inline int
+nanomips_operand_mask (const struct nanomips_operand *operand)
+{
+ unsigned int mask;
+
+ mask = ((1 << operand->size_top) - 1) << operand->lsb_top;
+ mask |= ((1 << (operand->size - operand->size_top)) - 1) << operand->lsb;
+ return mask;
+}
+
+/* Return the UVAL encoding of REGNO as OPERAND. */
+
+static inline unsigned int
+nanomips_encode_reg_operand (const struct nanomips_operand *operand,
+ int regno)
+{
+ unsigned int uval;
+ const unsigned int num_vals = 1 << operand->size;
+ const struct nanomips_reg_operand *reg_op
+ = (const struct nanomips_reg_operand *) operand;
+
+ for (uval = 0; uval < num_vals; uval++)
+ if (reg_op->reg_map[uval] == regno)
+ break;
+ return uval;
+}
+
+
+/* Re-organize HI20 bits of OPERAND encoded as UVAL. */
+
+#define SIGNEX_VALUE(OP) {OP_INT, (unsigned short)(OP->size - 1), 0, 0, 0}
+
+static inline int
+nanomips_decode_hi20_operand (const struct nanomips_operand *operand,
+ unsigned int uval)
+{
+ const struct nanomips_operand op_ext = SIGNEX_VALUE (operand);
+ const struct nanomips_operand op_shuffle = {OP_INT, 19, 10, 10, 0};
+ unsigned int low19 = nanomips_extract_operand (&op_shuffle, uval);
+ return nanomips_insert_operand (&op_ext, uval, low19);
+}
+
+/* Decode HI20 signed integer. */
+
+#define SIGNED_VALUE(OP) {OP_INT, OP->size, 0, 0, 0}
+
+static inline int
+nanomips_decode_hi20_int_operand (const struct nanomips_operand *operand,
+ unsigned int uval)
+{
+ const struct nanomips_operand op_enc = SIGNED_VALUE (operand);
+ uval = nanomips_decode_hi20_operand (operand, uval);
+ return (nanomips_signed_operand (&op_enc, uval));
+}
+
+/* Decode HI20 PCREL */
+
+#define PCREL_VALUE(OP) { { { OP_PCREL, OP->size, 0, 0, 0}, \
+ (unsigned int)((1 << (OP->size - 1)) - 1), 0, 0, false}, 12, 0, 0}
+
+static inline bfd_vma
+nanomips_decode_hi20_pcrel_operand (const struct nanomips_operand *operand,
+ bfd_vma base_pc, unsigned int uval)
+{
+ const struct nanomips_pcrel_operand pcrel_op = PCREL_VALUE (operand);
+ uval = nanomips_decode_hi20_operand (operand, uval);
+ return nanomips_decode_pcrel_operand (&pcrel_op, base_pc, uval << 12);
+}
+
+
+/* Return true if MO is an instruction that requires 48-bit encoding. */
+
+static inline bool
+opcode_48bit_p (const struct nanomips_opcode *mo)
+{
+ return ((mo->mask >> 16 == 0)
+ && ((mo->match >> 10) == 0x18));
+}
+
+/* These are the bits which may be set in the pinfo field of an
+ instructions, if it is not equal to INSN_MACRO. */
+
+/* Writes to operand number N. */
+#define INSN_WRITE_SHIFT 0
+#define INSN_WRITE_1 0x00000001
+#define INSN_WRITE_2 0x00000002
+#define INSN_WRITE_ALL 0x00000003
+/* Reads from operand number N. */
+#define INSN_READ_SHIFT 2
+#define INSN_READ_1 0x00000004
+#define INSN_READ_2 0x00000008
+#define INSN_READ_3 0x00000010
+#define INSN_READ_ALL 0x0000001c
+/* Modifies general purpose register 31. */
+#define INSN_WRITE_GPR_31 0x00000020
+/* Reads coprocessor register other than floating point register. */
+#define INSN_COP 0x00000040
+/* Instruction loads value from memory. */
+#define INSN_LOAD_MEMORY 0x00000080
+/* Reads the accumulator register. */
+#define INSN_READ_ACC 0x00000100
+/* Modifies the HI register. */
+#define INSN_WRITE_ACC 0x00000200
+/* Instruction stores value into memory. */
+#define INSN_STORE_MEMORY 0x00000400
+/* Instruction uses single precision floating point. */
+#define INSN_FP_S 0x00000800
+/* Instruction uses double precision floating point. */
+#define INSN_FP_D 0x00001000
+/* A user-defined instruction. */
+#define INSN_UDI 0x00002000
+/* Instruction is actually a macro. It should be ignored by the
+ disassembler, and requires special treatment by the assembler. */
+#define INSN_MACRO 0xffffffff
+
+/* These are the bits which may be set in the pinfo2 field of an
+ instruction. */
+
+/* Instruction is a simple alias (I.E. "move" for daddu/addu/or) */
+#define INSN2_ALIAS 0x00000001
+/* Macro uses single-precision floating-point instructions. This should
+ only be set for macros. For instructions, FP_S in pinfo carries the
+ same information. */
+#define INSN2_M_FP_S 0x00000002
+/* Macro uses double-precision floating-point instructions. This should
+ only be set for macros. For instructions, FP_D in pinfo carries the
+ same information. */
+#define INSN2_M_FP_D 0x00000004
+/* Is an unconditional branch insn. */
+#define INSN2_UNCOND_BRANCH 0x00000008
+/* Is a conditional branch insn. */
+#define INSN2_COND_BRANCH 0x00000010
+/* This indicates delayed branch converted to compact branch. */
+#define INSN2_CONVERTED_TO_COMPACT 0x00000020
+/* Marks the LI macro expansion as special, temporary. */
+#define INSN2_MACRO 0x00000040
+/* Marks the legacy/downgraded MTTGPR format, temporary. */
+#define INSN2_MTTGPR_RC1 0x00000080
+
+/* Masks used to mark instructions to indicate which MIPS ISA level
+ they were introduced in. INSN_ISA_MASK masks an enumeration that
+ specifies the base ISA level(s). The remainder of a 32-bit
+ word constructed using these macros is a bitmask of the remaining
+ INSN_* values below. */
+
+#define INSN_ISA_MASK 0x00000003ul
+
+/* We cannot start at zero due to ISA_UNKNOWN below. */
+#define INSN_ISAN32R6 1
+#define INSN_ISAN64R6 2
+
+#define ISA_UNKNOWN 0 /* Gas internal use. */
+
+#define ISA_NANOMIPS32R6 INSN_ISAN32R6
+#define ISA_NANOMIPS64R6 INSN_ISAN64R6
+
+/* CPU defines, use instead of hardcoding processor number. Keep this
+ in sync with bfd/archures.c in order for machine selection to work. */
+#define CPU_UNKNOWN 0 /* Gas internal use. */
+
+#define CPU_NANOMIPS32R6 32
+#define CPU_NANOMIPS64R6 64
+
+#define ISAF(X) (1 << (INSN_ISA##X - 1))
+
+/* The same information in table form: bit INSN_ISA<X> - 1 of index
+ INSN_UPTO<Y> - 1 is set if ISA Y includes ISA X. */
+static const unsigned int nanomips_isa_table[] = {
+ ISAF(N32R6),
+ ISAF(N32R6) | ISAF(N64R6)
+};
+#undef ISAF
+
+/* DSP ASE */
+#define ASE_DSP 0x00000001
+#define ASE_DSP64 0x00000002
+/* Enhanced VA Scheme */
+#define ASE_EVA 0x00000004
+/* MCU (MicroController) ASE */
+#define ASE_MCU 0x00000008
+/* MT ASE */
+#define ASE_MT 0x00000010
+/* Virtualization ASE */
+#define ASE_VIRT 0x00000020
+#define ASE_VIRT64 0x00000040
+/* MSA Extension */
+#define ASE_MSA 0x00000080
+#define ASE_MSA64 0x00000100
+/* Cyclic redundancy check (CRC) ASE */
+#define ASE_CRC 0x00000200
+#define ASE_CRC64 0x00000400
+/* Global INValidate Extension. */
+#define ASE_GINV 0x00000800
+/* The Virtualization ASE has Global INValidate extension instructions
+ which are only valid when both ASEs are enabled. */
+#define ASE_GINV_VIRT 0x00001000
+/* Excluded for low power instruction subset for nanoMIPS. */
+#define ASE_xNMS 0x00002000
+/* TLB control ASE. */
+#define ASE_TLB 0x00004000
+
+static inline bool
+nanomips_cpu_is_member (int cpu, unsigned int mask)
+{
+ switch (cpu)
+ {
+ case CPU_NANOMIPS32R6:
+ return (mask & INSN_ISA_MASK) == INSN_ISAN32R6;
+
+ case CPU_NANOMIPS64R6:
+ return ((mask & INSN_ISA_MASK) == INSN_ISAN32R6)
+ || ((mask & INSN_ISA_MASK) == INSN_ISAN64R6);
+
+ default:
+ return false;
+ }
+}
+
+/* Test for membership in an ISA including chip specific ISAs. INSN
+ is pointer to an element of the opcode table; ISA is the specified
+ ISA/ASE bitmask to test against; and CPU is the CPU specific ISA to
+ test, or zero if no CPU specific ISA test is desired. Return true
+ if instruction INSN is available to the given ISA and CPU. */
+static inline bool
+nanomips_opcode_is_member (const struct nanomips_opcode *insn,
+ int isa, int ase, int cpu)
+{
+ /* Test for ISA level compatibility. */
+ if ((isa & INSN_ISA_MASK) != 0
+ && (insn->membership & INSN_ISA_MASK) != 0
+ && ((nanomips_isa_table[(isa & INSN_ISA_MASK) - 1]
+ >> ((insn->membership & INSN_ISA_MASK) - 1)) & 1) != 0)
+ return true;
+
+ /* Test for ASE compatibility. */
+ if (insn->ase != 0 && (ase & insn->ase) == insn->ase)
+ return true;
+
+ /* Test for processor-specific extensions. */
+ if (nanomips_cpu_is_member (cpu, insn->membership))
+ return true;
+
+ return false;
+}
+
+/* This is a list of macro expanded instructions.
+
+ _I appended means immediate
+ _A appended means target address of a jump
+ _AB appended means address with (possibly zero) base register
+ _AC appended means either symbolic address with no base register
+ or constant offset with base register.
+ _D appended means 64 bit floating point constant
+ _S appended means 32 bit floating point constant. */
+
+enum
+{
+ M_ABS,
+ M_ACLR_AC,
+ M_ADD_I,
+ M_ADDU_I,
+ M_AND_I,
+ M_ASET_AC,
+ M_BEQ,
+ M_BEQ_I,
+ M_BGE,
+ M_BGE_I,
+ M_BGEU,
+ M_BGEU_I,
+ M_BGEZ,
+ M_BGT,
+ M_BGT_I,
+ M_BGTU,
+ M_BGTU_I,
+ M_BGTZ,
+ M_BLE,
+ M_BLE_I,
+ M_BLEU,
+ M_BLEU_I,
+ M_BLEZ,
+ M_BLT,
+ M_BLT_I,
+ M_BLTU,
+ M_BLTU_I,
+ M_BLTZ,
+ M_BNE,
+ M_BNE_I,
+ M_CACHE_AC,
+ M_CACHEE_AC,
+ M_DABS,
+ M_DADD_I,
+ M_DADDU_I,
+ M_DLA_AB,
+ M_DLI,
+ M_DMUL,
+ M_DMUL_I,
+ M_DSUB_I,
+ M_DSUBU_I,
+ M_J_A,
+ M_JAL_A,
+ M_JRADDIUSP,
+ M_LA_AB,
+ M_LB_AC,
+ M_LBE_AC,
+ M_LBU_AC,
+ M_LBUE_AC,
+ M_LBX_AB,
+ M_LBUX_AB,
+ M_LD_AC,
+ M_LDC1_AC,
+ M_LDC1X_AB,
+ M_LDC2_AC,
+ M_LDM_AC,
+ M_LDX_AB,
+ M_LH_AC,
+ M_LHE_AC,
+ M_LHU_AC,
+ M_LHUE_AC,
+ M_LHUX_AB,
+ M_LHX_AB,
+ M_LI,
+ M_LI_D,
+ M_LI_DD,
+ M_LI_S,
+ M_LI_SS,
+ M_LL_AC,
+ M_LLD_AC,
+ M_LLE_AC,
+ M_LLDP_AC,
+ M_LLWP_AC,
+ M_LW_AC,
+ M_LWC1_AC,
+ M_LWC1X_AB,
+ M_LWC2_AC,
+ M_LWE_AC,
+ M_LWM_AC,
+ M_LWU_AC,
+ M_LWUX_AB,
+ M_LWX_AB,
+ M_MUL,
+ M_MUL_I,
+ M_NOR_I,
+ M_OR_I,
+ M_PREF_AC,
+ M_PREFE_AC,
+ M_REM_3I,
+ M_DROL,
+ M_ROL,
+ M_DROL_I,
+ M_ROL_I,
+ M_ROR_I,
+ M_SC_AC,
+ M_SCD_AC,
+ M_SCE_AC,
+ M_SCDP_AC,
+ M_SCWP_AC,
+ M_SD_AC,
+ M_SDC1_AC,
+ M_SDC1X_AB,
+ M_SDC2_AC,
+ M_SDM_AC,
+ M_SDX_AB,
+ M_SEQ,
+ M_SEQ_I,
+ M_SGE,
+ M_SGE_I,
+ M_SGEU,
+ M_SGEU_I,
+ M_SGT,
+ M_SGT_I,
+ M_SGTU,
+ M_SGTU_I,
+ M_SLE,
+ M_SLE_I,
+ M_SLEU,
+ M_SLEU_I,
+ M_SLT_I,
+ M_SLTU_I,
+ M_SNE,
+ M_SNE_I,
+ M_SB_AC,
+ M_SBE_AC,
+ M_SBX_AB,
+ M_SH_AC,
+ M_SHE_AC,
+ M_SHX_AB,
+ M_SW_AC,
+ M_SWE_AC,
+ M_SWX_AB,
+ M_SWC1_AC,
+ M_SWC1X_AB,
+ M_SWC2_AC,
+ M_SWM_AC,
+ M_SUB_I,
+ M_SUBU_I,
+ M_TEQ_I,
+ M_TNE_I,
+ M_ULD_AC,
+ M_ULH_AC,
+ M_ULW_AC,
+ M_USH_AC,
+ M_USW_AC,
+ M_USD_AC,
+ M_XOR_I,
+ M_BGEZAL,
+ M_BLTZAL,
+ M_EXT,
+ M_INS,
+ M_MOD_I,
+ M_MODU_I,
+ M_DMOD_I,
+ M_DMODU_I,
+ M_DIV_I,
+ M_DIVU_I,
+ M_DDIV_I,
+ M_DDIVU_I,
+ M_NANOMIPS_NUM_MACROS
+};
+
+/* These are the bit masks and shift counts used for the different fields
+ in the nanoMIPS instruction formats. No masks are provided for the
+ fixed portions of an instruction, since they are not needed. */
+
+#define NANOMIPSOP_MASK_RS 0x1f
+#define NANOMIPSOP_SH_RS 16
+#define NANOMIPSOP_MASK_RT 0x1f
+#define NANOMIPSOP_SH_RT 21
+#define NANOMIPSOP_MASK_RD 0x1f
+#define NANOMIPSOP_SH_RD 11
+#define NANOMIPSOP_SH_ME 1
+#define NANOMIPSOP_SH_MC 4
+#define NANOMIPSOP_SH_MD 7
+#define NANOMIPSOP_SH_MP 5
+#define NANOMIPSOP_SH_MM 7
+
+#define NANOMIPSOP_SH_CP0SEL 5
+#define NANOMIPSOP_MASK_CP0SEL 0x1f
+#define NANOMIPSOP_SH_HWRSEL 5
+#define NANOMIPSOP_MASK_HWRSEL 0x1f
+
+/* Describes a COP0 named register with a fixed select. */
+struct nanomips_cp0_name
+{
+ const char *name;
+ unsigned int num;
+ unsigned int sel;
+};
+
+/* The reference list of COP0 named register with fixed selects. */
+static const struct nanomips_cp0_name nanomips_cp0_3264r6[] = {
+ {"$index", 0, 0},
+ {"$mvpcontrol", 0, 1},
+ {"$mvpconf0", 0, 2},
+ {"$mvpconf1", 0, 3},
+ {"$vpcontrol", 0, 4},
+ {"$random", 1, 0},
+ {"$vpecontrol", 1, 1},
+ {"$vpeconf0", 1, 2},
+ {"$vpeconf1", 1, 3},
+ {"$yqmask", 1, 4},
+ {"$vpeschedule", 1, 5},
+ {"$vpeschefback", 1, 6},
+ {"$vpeopt", 1, 7},
+ {"$entrylo0", 2, 0},
+ {"$tcstatus", 2, 1},
+ {"$tcbind", 2, 2},
+ {"$tcrestart", 2, 3},
+ {"$tchalt", 2, 4},
+ {"$tccontext", 2, 5},
+ {"$tcschedule", 2, 6},
+ {"$tcschefback", 2, 7},
+ {"$entrylo1", 3, 0},
+ {"$globalnumber", 3, 1},
+ {"$tcopt", 3, 7},
+ {"$context", 4, 0},
+ {"$contextconfig", 4, 1},
+ {"$userlocal", 4, 2},
+ {"$xcontextconfig", 4, 3},
+ {"$debugcontextid", 4, 4},
+ {"$memorymapid", 4, 5},
+ {"$pagemask", 5, 0},
+ {"$pagegrain", 5, 1},
+ {"$segctl0", 5, 2},
+ {"$segctl1", 5, 3},
+ {"$segctl2", 5, 4},
+ {"$pwbase", 5, 5},
+ {"$pwfield", 5, 6},
+ {"$pwsize", 5, 7},
+ {"$wired", 6, 0},
+ {"$srsconf0", 6, 1},
+ {"$srsconf1", 6, 2},
+ {"$srsconf2", 6, 3},
+ {"$srsconf3", 6, 4},
+ {"$srsconf4", 6, 5},
+ {"$pwctl", 6, 6},
+ {"$hwrena", 7, 0},
+ {"$badvaddr", 8, 0},
+ {"$badinst", 8, 1},
+ {"$badinstrp", 8, 2},
+ {"$badinstrx", 8, 3},
+ {"$count", 9, 0},
+ {"$entryhi", 10, 0},
+ {"$guestctl1", 10, 4},
+ {"$guestctl2", 10, 5},
+ {"$guestctl3", 10, 6},
+ {"$compare", 11, 0},
+ {"$guestctl0ext", 11, 4},
+ {"$status", 12, 0},
+ {"$intctl", 12, 1},
+ {"$srsctl", 12, 2},
+ {"$srsmap", 12, 3},
+ {"$view_ipl", 12, 4},
+ {"$srsmap2", 12, 5},
+ {"$guestctl0", 12, 6},
+ {"$gtoffset", 12, 7},
+ {"$cause", 13, 0},
+ {"$view_ripl", 13, 4},
+ {"$nestedexc", 13, 5},
+ {"$epc", 14, 0},
+ {"$nestedepc", 14, 2},
+ {"$prid", 15, 0},
+ {"$ebase", 15, 1},
+ {"$cdmmbase", 15, 2},
+ {"$cmgcrbase", 15, 3},
+ {"$bevva", 15, 4},
+ {"$config", 16, 0},
+ {"$config1", 16, 1},
+ {"$config2", 16, 2},
+ {"$config3", 16, 3},
+ {"$config4", 16, 4},
+ {"$config5", 16, 5},
+ {"$lladdr", 17, 0},
+ {"$maar", 17, 1},
+ {"$maari", 17, 2},
+ {"$watchlo0", 18, 0},
+ {"$watchlo1", 18, 1},
+ {"$watchlo2", 18, 2},
+ {"$watchlo3", 18, 3},
+ {"$watchlo4", 18, 4},
+ {"$watchlo5", 18, 5},
+ {"$watchlo6", 18, 6},
+ {"$watchlo7", 18, 7},
+ {"$watchlo8", 18, 8},
+ {"$watchlo9", 18, 9},
+ {"$watchlo10", 18, 10},
+ {"$watchlo11", 18, 11},
+ {"$watchlo12", 18, 12},
+ {"$watchlo13", 18, 13},
+ {"$watchlo14", 18, 14},
+ {"$watchlo15", 18, 15},
+ {"$watchhi0", 19, 0},
+ {"$watchhi1", 19, 1},
+ {"$watchhi2", 19, 2},
+ {"$watchhi3", 19, 3},
+ {"$watchhi4", 19, 4},
+ {"$watchhi5", 19, 5},
+ {"$watchhi6", 19, 6},
+ {"$watchhi7", 19, 7},
+ {"$watchhi8", 19, 8},
+ {"$watchhi9", 19, 9},
+ {"$watchhi10", 19, 10},
+ {"$watchhi11", 19, 11},
+ {"$watchhi12", 19, 12},
+ {"$watchhi13", 19, 13},
+ {"$watchhi14", 19, 14},
+ {"$watchhi15", 19, 15},
+ {"$xcontext", 20, 0},
+ {"$debug", 23, 0},
+ {"$tracecontrol", 23, 1},
+ {"$tracecontrol2", 23, 2},
+ {"$usertracedata1", 23, 3},
+ {"$traceibpc", 23, 4},
+ {"$tracedbpc", 23, 5},
+ {"$debug2", 23, 6},
+ {"$depc", 24, 0},
+ {"$tracecontrol3", 24, 2},
+ {"$usertracedata2", 24, 3},
+ {"$perfctl0", 25, 0},
+ {"$perfcnt0", 25, 1},
+ {"$perfctl1", 25, 2},
+ {"$perfcnt1", 25, 3},
+ {"$perfctl2", 25, 4},
+ {"$perfcnt2", 25, 5},
+ {"$perfctl3", 25, 6},
+ {"$perfcnt3", 25, 7},
+ {"$perfctl4", 25, 8},
+ {"$perfcnt4", 25, 9},
+ {"$perfctl5", 25, 10},
+ {"$perfcnt5", 25, 11},
+ {"$perfctl6", 25, 12},
+ {"$perfcnt6", 25, 13},
+ {"$perfctl7", 25, 14},
+ {"$perfcnt7", 25, 15},
+ {"$errctl", 26, 0},
+ {"$cacheerr", 27, 0},
+ {"$itaglo", 28, 0},
+ {"$idatalo", 28, 1},
+ {"$dtaglo", 28, 2},
+ {"$ddatalo", 28, 3},
+ {"$itaghi", 29, 0},
+ {"$idatahi", 29, 1},
+ {"$dtaghi", 29, 2},
+ {"$ddatahi", 29, 3},
+ {"$errorepc", 30, 0},
+ {"$desave", 31, 0},
+ {"$kscratch1", 31, 2},
+ {"$kscratch2", 31, 3},
+ {"$kscratch3", 31, 4},
+ {"$kscratch4", 31, 5},
+ {"$kscratch5", 31, 6},
+ {"$kscratch6", 31, 7},
+ {NULL, 0, 0}
+};
+
+/* Describes a CP0 named register which permits various select values. */
+ struct nanomips_cp0_select
+{
+ const char *name;
+ unsigned int num;
+ unsigned int selmask;
+};
+
+/* Currently recognized CP0 select patterns. */
+
+#define NANOMIPS_CP0SEL_MASK_EVEN 0x55555555
+#define NANOMIPS_CP0SEL_MASK_ODD 0xaaaaaaaa
+#define NANOMIPS_CP0SEL_MASK_ANY 0xffffffff
+#define NANOMIPS_CP0SEL_MASK_EVEN16 0x5555
+#define NANOMIPS_CP0SEL_MASK_ODD16 0xaaaa
+#define NANOMIPS_CP0SEL_MASK_ANY16 0xffff
+
+/* The reference list of CP0 named register with variable selects. */
+static const struct nanomips_cp0_select nanomips_cp0sel_3264r6[] = {
+ {"$watchlo", 18, NANOMIPS_CP0SEL_MASK_ANY16},
+ {"$watchhi", 19, NANOMIPS_CP0SEL_MASK_ANY16},
+ {"$perfctl", 25, NANOMIPS_CP0SEL_MASK_EVEN16},
+ {"$perfcnt", 25, NANOMIPS_CP0SEL_MASK_ANY16},
+ {"$taglo", 28, NANOMIPS_CP0SEL_MASK_EVEN},
+ {"$datalo", 28, NANOMIPS_CP0SEL_MASK_ODD},
+ {"$taghi", 29, NANOMIPS_CP0SEL_MASK_EVEN},
+ {"$datahi", 29, NANOMIPS_CP0SEL_MASK_ODD},
+ {NULL, 0, 0}
+};
+
+
+/* Describes a HWR named register with a fixed select. If the HWR name
+ is remapped from an existing CP0 register name, its cp0_num and cp0_sel
+ fields will provide the mapping, else they will both be invalid. */
+
+struct nanomips_hwr_name
+{
+ const char *name;
+ unsigned int num;
+ unsigned int sel;
+ unsigned int cp0_num;
+ unsigned int cp0_sel;
+};
+
+#define INV_RNUM 0xffffffff
+#define INV_SEL 0xffffffff
+
+ /* The reference list of named hardware register with fixed selects. */
+static const struct nanomips_hwr_name nanomips_hwr_names_3264r6[] = {
+ {"$cpunum", 0, 0, INV_RNUM, INV_SEL},
+ {"$synci_step", 1, 0, INV_RNUM, INV_SEL},
+ {"$cc", 2, 0, 9, 0},
+ {"$count", 2, 0, 9, 0},
+ {"$ccres", 3, 0, INV_RNUM, INV_SEL},
+ {"$perfctl0", 4, 0, 25, 0},
+ {"$perfcnt0", 4, 1, 25, 1},
+ {"$perfctl1", 4, 2, 25, 2},
+ {"$perfcnt1", 4, 3, 25, 3},
+ {"$perfctl2", 4, 4, 25, 4},
+ {"$perfcnt2", 4, 5, 25, 5},
+ {"$perfctl3", 4, 6, 25, 6},
+ {"$perfcnt3", 4, 7, 25, 7},
+ {"$perfctl4", 4, 8, 25, 8},
+ {"$perfcnt4", 4, 9, 25, 9},
+ {"$perfctl5", 4, 10, 25, 10},
+ {"$perfcnt5", 4, 11, 25, 11},
+ {"$perfctl6", 4, 12, 25, 12},
+ {"$perfcnt6", 4, 13, 25, 13},
+ {"$perfctl7", 4, 14, 25, 14},
+ {"$perfcnt7", 4, 15, 25, 15},
+ {"$perfctl", 4, 0, 25, 0},
+ {"$perfcnt", 4, 1, 25, 1},
+ {"$xnp", 5, 0, INV_RNUM, INV_SEL},
+ {"$userlocal", 29, 0, 4, 2},
+ {NULL, 0, 0, INV_RNUM, INV_SEL}
+};
+
+#define NANOMIPS_CP0SEL_PERFCNT 25
+#define NANOMIPS_HWRSEL_PERFCNT 4
+
+/* Don't care stubs in operand formats need special handling. */
+#define NANOMIPS_MIN_DONTCARE_FMT 'A'
+#define NANOMIPS_MAX_DONTCARE_FMT 'Q'
+
+#define IS_NANOMIPS_DONTCARE_FMT(x) ((x)[0] == '-' \
+ && (x)[1] >= NANOMIPS_MIN_DONTCARE_FMT \
+ && (x)[1] <= NANOMIPS_MAX_DONTCARE_FMT)
+
+/* These are the characters which may appears in the args field of a nanoMIPS
+ instruction. They appear in the order in which the fields appear when the
+ instruction is used. Commas and parentheses in the args string are ignored
+ when assembling, and written into the output when disassembling.
+
+ Operands for 16-bit nanoMIPS instructions.
+
+ "ma" must be $28
+ "mb" 5-bit non-zero GP register at bit 5
+ "mc" 3-bit nanoMIPS registers 4-7, 16-19 bit 4
+ The same register used as both source and target.
+ "md" 3-bit nanoMIPS registers 4-7, 16-19 at bit 7
+ "me" 3-bit nanoMIPS registers 4-7, 16-19 at bit 1
+ "mf" 3-bit nanoMIPS register 4-7, 16-19 at bit 7.
+ Must be larger than the last seen register.
+ "mg" 3-bit nanoMIPS register 4-7, 16-19 at bit 4.
+ Must be smaller than the last seen register.
+ "mh" 3-bit nanoMIPS register 4-7, 16-19 at bit 7.
+ Must be at least as large as the last seen register.
+ "mi" 3-bit nanoMIPS register 4-7, 16-19 at bit 4.
+ May be at most as large as the last seen register.
+
+ "mj" 5-bit nanoMIPS registers at bit 0
+ "mk" must be the same as the destination register
+ "ml" 3-bit nanoMIPS registers 4-7, 16-19 at bit 4
+ "mm" 3-bit nanoMIPS registers 0, 4-7, 17-19 at bit 7
+ "mn" 5-bit encoding of a save/restore register list
+ "mp" 5-bit nanoMIPS registers at bit 5
+ "mq" 2-bit pair at bits [8,3] maps to ($a0,$a1), ($a1,$a2), ($a2,$a3)
+ or ($a3,$a4)
+ "mr" 2-bit pair at bits [8,3] maps to ($a1,$a0), ($a2,$a1), ($a3,$a2)
+ or ($a4,$a3)
+ "ms" must be $29
+ "mt" must be the same as the previous register
+ "mu" 4-bit encoding of nanoMIPS destination register at bit 5
+ "mv" 4-bit encoding of nanoMIPS destination register at bit 0
+ "mw" 4-bit encoding of nanoMIPS source register at bit 5
+ "mx" 4-bit encoding of nanoMIPS source register at bit 0
+ "my" must be $31
+ "mz" must be literal 0
+
+ "mA" 7-bit relocatable GP offset (0 .. 127) << 2
+ "mB" 3-bit immediate at bit 0 (0, 4, 8, 12, 16, 20, 24, 28)
+ "mC" 4-bit immediate at bit 0 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 65535, 14, 15)
+ "mD" 10-bit signed branch address, split & scaled at bit 0 [S9:1,S10]
+ "mE" 7-bit signed branch address, split & scaled at bit 0 [S6:1,S7]
+ "mF" 4-bit unsigned branch address, scaled at bit 0 [U4:U1]
+ "mG" 4-bit scaled immediate at bit 4, (0 .. 15) << 4
+ "mH" 2-bit scaled immediate at bit 1, (0 .. 3) << 1
+ "mI" 7-bit immediate at bit 0, (-1 .. 126)
+ "mJ" 4-bit scaled immediate at bit 0, (0 .. 15) << 2
+ "mK" 3-bit BREAK/SDBBP code at bit 0
+ "mL" 2-bit immediate at bit 0, (0 .. 3)
+ "mM" 3-bit immediate at bit 0, (1 .. 8)
+ "mN" 2-bit split scaled immediate at bits 8 & 3 (0 .. 3) << 2
+ "mO" 7-bit immediate GP offset at bit 0, (0 .. 127) << 2
+ "mP" 2-bit SYSCALL/HYPCALL code at bit 0
+ "mQ" 4-bit immediate signed offset, (s3,s2:s0)
+ "mR" 5-bit immediate at bit 0, (0 .. 31) << 2
+ "mS" 6-bit immediate at bit 0, (0 .. 63) << 2
+ "mZ" must be zero
+
+ Operands for 32-bit nanoMIPS instructions.
+
+ "+1" 18-bit unsigned GP-relative offset, (u17:u0)
+ "+2" 18-bit scaled GP-relative offset, (u18:u2) << 2
+ "+3" 21-bit scaled GP-relative offset, (u18:u1) << 1
+ "+4" 18-bit GP-relative offset, (0 .. 2^18-1) << 3
+ "+5" 4-bit encoding of nanoMIPS source register at bit 21
+ "+6" 5-bit mask encoding, corresponding to (1 << X) - 1
+ "+7" 1-bit register at bit 24, (0,1) => ($a0,$a1)
+ "+8" 23-bit un-spec'ed value at bit 3 for UDIs.
+ "+9" 7-bit immediate at bit 11, (0 .. 127)
+
+ "+A" 5-bit INS/EXT/DINS/DEXT/DINSM/DEXTM position, which becomes
+ LSB.
+ "+B" 5-bit INS/DINS size, which becomes MSB
+ Requires that "+A" or "+E" occur first to set position.
+ Enforces: 0 < (pos+size) <= 32.
+ "+C" 5-bit EXT/DEXT size, which becomes MSBD.
+ Requires that "+A" or "+E" occur first to set position.
+ Enforces: 0 < (pos+size) <= 32.
+ "+D" 4-bit encoding of a floating point save/restore register list
+ "+E" 5-bit DINSU/DEXTU position, which becomes LSB-32.
+ "+F" 5-bit DINSM/DINSU size, which becomes MSB-32.
+ Requires that "+A" or "+E" occur first to set position.
+ Enforces: 32 < (pos+size) <= 64.
+ "+G" 5-bit DEXTM size, which becomes MSBD-32.
+ Requires that "+A" or "+E" occur first to set position.
+ Enforces: 32 < (pos+size) <= 64.
+ "+H" 5-bit DEXTU size, which becomes MSBD.
+ Requires that "+A" or "+E" occur first to set position.
+ Enforces: 32 < (pos+size) <= 64.
+ "+I" 5-bit EXTW/EXTD/PREPEND position, which becomes LSB.
+ "+J" 19-bit BREAK/SDBBP function code at bit 0
+ "+K" Tri-part upper 20-bits of immediate value.
+ "+L" 10-bit WAIT code at bit 16
+ "+M" 18-bit SYSCALL/HYPCALL code at bit 0
+ "+N" 9-bit immediate at bit 3, (0 .. 511) << 3
+
+ "+i" 5-bit SYNC code type at bit 16, (0..31)
+ "+j" 9-bit signed offset (s7:s0,s8), (-256 .. 255)
+ "+k" 5-bit nanoMIPS registers at bit 3
+ "+p" 9-bit scaled signed offset, (s7:s2) << 2 for LL/SC*
+ "+q" 9-bit scaled signed offset, (s7:s3) << 3 for LLD/SCD*
+ "+r" 21-bit PC-relative branch offset (s19:s1,s20) << 1
+ "+s" 21-bit immediate offset for PC-relative operation ((s19:s1,s20) + 2) << 1
+ "+t" 5-bit non-zero GP register at bit 21
+ "+u" 25-bit PC-relative branch offset (s24:s1,s25) << 1
+ "+v" 5-bit mapping of R6 ALIGN byte-wise shift to EXTW bit-wise shift.
+ "+w" 2-bit shift for scaled address calculation at bit 9, (0..3)
+ "+*" 4-bit ROTX shift at bit 7, (0 .. 15) << 1
+ "+|" 1-bit ROTX stripe at bit 6, (0 .. 1)
+
+ "." 21-bit scaled GP-relative offset, (u21:u2) << 2
+ "<" 5-bit immediate shift value for bit operations, (0..31)
+ "|" 3-bit Element count for load/store multiple, (1..8)
+ "~" 11-bit branch offset, (s9:s1,s10) << 1
+ "^" 5-bit trap code at bit 11, (0..31)
+ "b" 5-bit base register at bit 16 for label or symbolic offsets
+ "c" 5-bit base register at bit 16, either used with immediate offset
+ or skipped with symbolic offset.
+ "d" 5-bit destination register specifier at bit 11
+ "g" 12-bit unsigned immediate at bit 0, (0..4095)
+ "h" 12-bit negative immediate at bit 0, (-4095..0)
+ "i" 12-bit unsigned immediate at bit 0, (0..4095)
+ "j" 16-bit unsigned immediate at bit 0, (0..65535)
+ "k" 5-bit cache operation code at bit 21, (0..31)
+ "n" 11-bit encoding of save/restore register list
+ "o" 12-bit offset at bit 0, (0..4095)
+ "p" 14-bit PC-relative branch offset (s13:s1,s14) << 1
+ "r" 5-bit same register at bit 16, used as both source and target
+ "s" 5-bit source register specifier at bit 16
+ "t" 5-bit target register specifier at bit 21
+ "u" Tri-part upper 20 bits of address
+ "x" Tri-part upper 20 bits of address, scaled by 12 bits
+ "v" 5-bit same register used as both source and destination at bit 15
+ "w" 5-bit same register used as both target and destination at bit 21
+ "z" must be zero register
+
+ Used in special matching contexts:
+ "-A" 5 don't care bits at bit 16
+ "-B" 1 don't care bit at bit 10
+ "-C" 12 don't care bits at bit 0
+ "-D" 1 don't care bit at bit 17
+ "-E" 3 don't care bits at bit 13
+ "-F" 10 don't care bits at bit 16
+ "-G" 8 split don't care bits, 3 at bit 9 and 5 at bit 7
+ "-H" 9 don't care bits at bit 17
+ "-I" 5 don't care bits at bit 21
+ "-J" 3 don't care bits at bit 23
+ "-K" 2 split don't care bits, 1 at bit 2 and 1 at bit 15
+ "-L" 3 don't care bits at bit 6
+ "-M" 3 don't care bits at bit 9
+ "-N" 6 don't care bits at bit 10
+ "-O" 1 don't care bit at bit 12
+ "-P" 8 split don't care bits, 4 at bit 10 and 4 at bit 22
+ "-Q" 1 don't care bit at bit 11
+
+ "-i" Ignored register operand, internally used for macro expansions.
+ "-m" Place-holder to copy 5 bits from bit 11 to bit 21
+ "-n" Place-holder to copy 5 bits from bit 11 to bit 16
+
+ Exclusively for 48-bit nanoMIPS instructions:
+
+ "+O" Signed GP-relative 32-bit offset in instruction byte order
+ "+P" Immediate signed 32-bit value in instruction byte order
+ "+Q" Unsigned 32-bit value or address in instruction byte order
+ "+R" Signed 32-bit value in instruction byte order
+ "+S" Signed PC-relative 32-bit offset in instruction byte order
+
+ DSP instructions:
+ "0" 5-bit shift value for DSP accumulator at bit 16, (0..63)
+ "1" 5-bit position for DSP bit operations at bit 11
+ "2" 5-bit size for DSP bit operations at bit 16
+ "3" 3-bit byte vector shift at bit 13, (0..7)
+ "4" 4-bit hword vector shift at bit 12, (0..15)
+ "5" 8-bit unsigned immediate at bit 13, (0..255)
+ "7" 2-bit DSP accumulator register at bit 14, (0..3)
+ "8" 7-bit DSP control mask at bit 14, (0x3f)
+ "@" 10-bit signed immediate at bit 11, (0..1023)
+
+ Coprocessor instructions:
+ "E" 5-bit target register
+ "G" 5-bit source register
+ "H" 5-bit sel field for (D)MTC* and (D)MFC*
+ "J" 5-bit select code at bit 11 for named COP1 registers, (0..31)
+ "K" 10-bit register+select encoding at bit 11 for named h/w register
+ "O" 10-bit register+select encoding at bit 11 for named COP1 register
+ "P" 5-bit named COP1 register at bit 16
+ "Q" 5-bit select code at bit 11
+ "U" 5-bit named HW register at bit 16
+
+ MT instructions:
+ "!" 1-bit u-mode for move to/from thread registers at bit 10, (0,1)
+ "$" 1-bit high-mode for move to/from thread registers at bit 3, (0,1)
+ "*" 2-bit accumulator register at bit 18, (0..3)
+
+ GINV instructions
+ "+;" 2-bit global invalidate operation type at bit 21, (0..3)
+
+ Floating point instructions:
+ "D" 5-bit destination register
+ "R" 5-bit fr destination register
+ "S" 5-bit fs source 1 register
+ "T" 5-bit ft source 2 register
+ "V" 5-bit same register used as floating source and destination or target
+
+ Macro instructions:
+ "A" general 32 bit expression
+ "I" 32-bit immediate (value placed in imm_expr).
+ "F" 64-bit floating point constant in memory
+ "L" 64-bit floating point constant in memory
+ "f" 32-bit floating point constant in memory
+ "l" 32-bit floating point constant in memory
+
+ CP2 instructions:
+ "C" 23-bit coprocessor function code at bit 3
+
+ MCU instructions:
+ "\" 3-bit position for atomic set/clear operations, (0..7)
+
+
+ Other:
+ "()" parens surrounding optional value
+ "," separates operands
+ "+" start of extension sequence
+
+ Characters used so far, for quick reference when adding more:
+ "12345 78 0"
+ ".<\|~@^!$*"
+ "A CDEFGHIJKL OP RSTUV "
+ " bcde ghijk nop rstuvwx z"
+
+ Extension character sequences used so far ("+" followed by the
+ following), for quick reference when adding more:
+ "123456789
+ "*|;"
+ "ABCDEFGHIJKLMNOPQRS "
+ " ij pqrstuvw "
+
+ Extension character sequences used so far ("m" followed by the
+ following), for quick reference when adding more:
+ ""
+ ""
+ "ABCDEFGHIJKLMNOPQRS Z"
+ "abcdefghijklmn pqrstuvwxyz"
+
+ Extension character sequences used so far ("-" followed by the
+ following), for quick reference when adding more:
+ ""
+ ""
+ "ABCDEFGHIJKLMNOPQ "
+ " i mn "
+*/
+
+extern const struct nanomips_operand *decode_nanomips_operand (const char *);
+extern const struct nanomips_opcode nanomips_opcodes[];
+extern const int bfd_nanomips_num_opcodes;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NANOMIPS_H_ */
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index 3d9f4a14532..d28f3f37730 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -1,3 +1,20 @@
+2022-04-20 Jaydeep Patil <jaydeep.patil@imgtec.com>
+ Faraz Shahbazker <faraz.shahbazker@mips.com>
+ Maciej W. Rozycki <macro@mips.com>
+ Dragan Mladjenovic <dragan.mladjenovic@syrmia.com>
+ Aleksandar Rikalo <aleksandar.rikalo@syrmia.com>
+
+ * Makefile.am: Add nanoMIPS objects.
+ * Makefile.in: Regenerate.
+ * configure: Regenerate.
+ * configure.ac: Add nanoMIPS support.
+ * dis-buf.c (generic_predict_insn_length): New function.
+ * dis-init.c (init_disassemble_info): Use generic_predict_insn_length().
+ * disassemble.c (disassemble_init_for_target): Initialization for nanoMIPS.
+ * nanomips-dis.c: New file.
+ * nanomips-formats.h: New file.
+ * nanomips-opc.c: New file.
+
2022-04-07 Andreas Krebbel <krebbel@linux.ibm.com>
* s390-mkopc.c (main): Enable z16 as CPU string in the opcode
diff --git a/opcodes/Makefile.am b/opcodes/Makefile.am
index afd19fa7785..cf6a2994626 100644
--- a/opcodes/Makefile.am
+++ b/opcodes/Makefile.am
@@ -207,6 +207,12 @@ TARGET32_LIBOPCODES_CFILES = \
mep-opc.c \
metag-dis.c \
microblaze-dis.c \
+ micromips-opc.c \
+ mips-dis.c \
+ mips-opc.c \
+ mips16-opc.c \
+ mmix-dis.c \
+ mmix-opc.c \
moxie-dis.c \
moxie-opc.c \
msp430-decode.c \
@@ -216,6 +222,8 @@ TARGET32_LIBOPCODES_CFILES = \
mt-dis.c \
mt-ibld.c \
mt-opc.c \
+ nanomips-dis.c \
+ nanomips-opc.c \
nds32-asm.c \
nds32-dis.c \
nios2-dis.c \
diff --git a/opcodes/Makefile.in b/opcodes/Makefile.in
index 3ab8bfb0548..9eba41fae6c 100644
--- a/opcodes/Makefile.in
+++ b/opcodes/Makefile.in
@@ -599,6 +599,12 @@ TARGET32_LIBOPCODES_CFILES = \
mep-opc.c \
metag-dis.c \
microblaze-dis.c \
+ micromips-opc.c \
+ mips-dis.c \
+ mips-opc.c \
+ mips16-opc.c \
+ mmix-dis.c \
+ mmix-opc.c \
moxie-dis.c \
moxie-opc.c \
msp430-decode.c \
@@ -608,6 +614,8 @@ TARGET32_LIBOPCODES_CFILES = \
mt-dis.c \
mt-ibld.c \
mt-opc.c \
+ nanomips-dis.c \
+ nanomips-opc.c \
nds32-asm.c \
nds32-dis.c \
nios2-dis.c \
@@ -1020,6 +1028,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mt-dis.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mt-ibld.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mt-opc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nanomips-dis.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nanomips-opc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nds32-asm.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nds32-dis.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nfp-dis.Plo@am__quote@
diff --git a/opcodes/configure b/opcodes/configure
index 792c863b895..cbc80d60944 100755
--- a/opcodes/configure
+++ b/opcodes/configure
@@ -12540,6 +12540,7 @@ if test x${all_targets} = xfalse ; then
bfd_mn10300_arch) ta="$ta m10300-dis.lo m10300-opc.lo" ;;
bfd_mt_arch) ta="$ta mt-asm.lo mt-desc.lo mt-dis.lo mt-ibld.lo mt-opc.lo" using_cgen=yes ;;
bfd_msp430_arch) ta="$ta msp430-dis.lo msp430-decode.lo" ;;
+ bfd_nanomips_arch) ta="$ta nanomips-dis.lo nanomips-opc.lo" ;;
bfd_nds32_arch) ta="$ta nds32-asm.lo nds32-dis.lo" ;;
bfd_nfp_arch) ta="$ta nfp-dis.lo" ;;
bfd_nios2_arch) ta="$ta nios2-dis.lo nios2-opc.lo" ;;
diff --git a/opcodes/configure.ac b/opcodes/configure.ac
index 006a95d8704..657d1914229 100644
--- a/opcodes/configure.ac
+++ b/opcodes/configure.ac
@@ -306,6 +306,7 @@ if test x${all_targets} = xfalse ; then
bfd_mn10300_arch) ta="$ta m10300-dis.lo m10300-opc.lo" ;;
bfd_mt_arch) ta="$ta mt-asm.lo mt-desc.lo mt-dis.lo mt-ibld.lo mt-opc.lo" using_cgen=yes ;;
bfd_msp430_arch) ta="$ta msp430-dis.lo msp430-decode.lo" ;;
+ bfd_nanomips_arch) ta="$ta nanomips-dis.lo nanomips-opc.lo" ;;
bfd_nds32_arch) ta="$ta nds32-asm.lo nds32-dis.lo" ;;
bfd_nfp_arch) ta="$ta nfp-dis.lo" ;;
bfd_nios2_arch) ta="$ta nios2-dis.lo nios2-opc.lo" ;;
diff --git a/opcodes/dis-buf.c b/opcodes/dis-buf.c
index 3bd078f54dc..20e4917b6e5 100644
--- a/opcodes/dis-buf.c
+++ b/opcodes/dis-buf.c
@@ -104,3 +104,12 @@ generic_symbol_is_valid (asymbol * sym ATTRIBUTE_UNUSED,
{
return true;
}
+
+/* Just return size of previous instruction. */
+
+int
+generic_predict_insn_length (bfd_vma addr ATTRIBUTE_UNUSED, int previous,
+ struct disassemble_info *info ATTRIBUTE_UNUSED)
+{
+ return previous;
+}
diff --git a/opcodes/dis-init.c b/opcodes/dis-init.c
index 59039ef8b11..fc03a2ef99a 100644
--- a/opcodes/dis-init.c
+++ b/opcodes/dis-init.c
@@ -43,6 +43,7 @@ init_disassemble_info (struct disassemble_info *info, void *stream,
info->print_address_func = generic_print_address;
info->symbol_at_address_func = generic_symbol_at_address;
info->symbol_is_valid = generic_symbol_is_valid;
+ info->predict_insn_length = generic_predict_insn_length;
info->display_endian = BFD_ENDIAN_UNKNOWN;
info->created_styled_output = false;
}
diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c
index bd1b90b3956..3726a5b4fde 100644
--- a/opcodes/disassemble.c
+++ b/opcodes/disassemble.c
@@ -360,6 +360,11 @@ disassembler (enum bfd_architecture a,
disassemble = print_insn_mn10300;
break;
#endif
+#ifdef ARCH_nanomips
+ case bfd_arch_nanomips:
+ disassemble = print_insn_nanomips;
+ break;
+#endif
#ifdef ARCH_nios2
case bfd_arch_nios2:
if (big)
@@ -582,6 +587,9 @@ disassembler_usage (FILE *stream ATTRIBUTE_UNUSED)
#ifdef ARCH_nfp
print_nfp_disassembler_options (stream);
#endif
+#ifdef ARCH_nanomips
+ print_nanomips_disassembler_options (stream);
+#endif
#ifdef ARCH_powerpc
print_ppc_disassembler_options (stream);
#endif
@@ -729,6 +737,11 @@ disassemble_init_for_target (struct disassemble_info * info)
disassemble_init_nds32 (info);
break;
#endif
+#ifdef ARCH_nanomips
+ case bfd_arch_nanomips:
+ info->disassembler_needs_relocs = true;
+ break;
+#endif
default:
break;
}
diff --git a/opcodes/nanomips-dis.c b/opcodes/nanomips-dis.c
new file mode 100644
index 00000000000..3d17d813943
--- /dev/null
+++ b/opcodes/nanomips-dis.c
@@ -0,0 +1,1505 @@
+/* Print nanoMIPS instructions for GDB, the GNU debugger, or for objdump.
+ Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+ Written by Faraz Shahbazker <faraz.shahbazker@mips.com>
+
+ This file is part of the GNU opcodes library.
+
+ This library 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.
+
+ It 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 this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "sysdep.h"
+#include "dis-asm.h"
+#include "libiberty.h"
+#include "opcode/nanomips.h"
+#include "opintl.h"
+
+#if !defined(EMBEDDED_ENV)
+#include "elf-bfd.h"
+#include "elf/nanomips.h"
+#endif
+\f
+
+/* FIXME: These should be shared with gdb somehow. */
+
+static const char * const nanomips_gpr_names_numeric[32] = {
+ "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
+ "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
+ "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
+ "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
+};
+
+static const char * const nanomips_gpr_names_symbolic[32] = {
+ "zero", "at", "t4", "t5", "a0", "a1", "a2", "a3",
+ "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+ "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
+};
+
+static const char * const nanomips_fpr_names_numeric[32] = {
+ "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
+ "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
+ "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
+ "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31"
+};
+
+static const char * const nanomips_fpr_names_64[32] = {
+ "fv0", "ft12", "fv1", "ft13", "ft0", "ft1", "ft2", "ft3",
+ "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3",
+ "fa4", "fa5", "fa6", "fa7", "ft8", "ft9", "ft10", "ft11",
+ "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7"
+};
+
+static const char * const nanomips_cp1_names_numeric[32] = {
+ "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
+ "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
+ "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
+ "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
+};
+
+static const char * const nanomips_cp1_names_3264r6[32] = {
+ "c1_fir", "c1_ufr", "$2", "$3",
+ "c1_unfr", "$5", "$6", "$7",
+ "$8", "$9", "$10", "$11",
+ "$12", "$13", "$14", "$15",
+ "$16", "$17", "$18", "$19",
+ "$20", "$21", "$22", "$23",
+ "$24", "c1_fccr", "c1_fexr", "$27",
+ "c1_fenr", "$29", "$30", "c1_fcsr"
+};
+
+static const char * const msa_control_names[32] = {
+ "msa_ir", "msa_csr", "msa_access", "msa_save",
+ "msa_modify", "msa_request", "msa_map", "msa_unmap",
+ "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
+ "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
+ "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
+};
+
+/* The empty-list of CP0 registers serves as an indicator to fall-back to
+ numeric register names. */
+static const struct nanomips_cp0_name nanomips_cp0_numeric[] = {
+ {NULL, 0, 0}
+};
+static const struct nanomips_cp0_select nanomips_cp0sel_numeric[] = {
+ {NULL, 0, 0}
+};
+
+/* The empty-list of HWR registers serves as an indicator to fall-back to
+ numeric register names. */
+static const struct nanomips_hwr_name nanomips_hwr_names_numeric[] = {
+ {NULL, 0, 0, 0, 0}
+};
+
+struct nanomips_abi_choice
+{
+ const char *name;
+ const char *const *gpr_names;
+ const char *const *fpr_names;
+};
+
+struct nanomips_abi_choice nanomips_abi_choices[] = {
+ {"numeric", nanomips_gpr_names_numeric, nanomips_fpr_names_numeric},
+ {"p32", nanomips_gpr_names_symbolic, nanomips_fpr_names_64},
+ {"p64", nanomips_gpr_names_symbolic, nanomips_fpr_names_64},
+};
+
+struct nanomips_arch_choice
+{
+ const char *name;
+ int bfd_mach_valid;
+ unsigned long bfd_mach;
+ int processor;
+ int isa;
+ int ase;
+ const struct nanomips_cp0_name *cp0_names;
+ const struct nanomips_cp0_select *cp0sel_names;
+ const char *const *cp1_names;
+ const struct nanomips_hwr_name *hwr_names;
+};
+
+const struct nanomips_arch_choice nanomips_arch_choices[] = {
+ {"numeric", 0, 0, 0, 0, 0,
+ nanomips_cp0_numeric, nanomips_cp0sel_numeric, nanomips_cp1_names_numeric,
+ nanomips_hwr_names_numeric},
+
+ {"32r6", 1, bfd_mach_nanomipsisa32r6, CPU_NANOMIPS32R6, ISA_NANOMIPS32R6,
+ (ASE_EVA | ASE_MSA | ASE_VIRT | ASE_MCU | ASE_MT | ASE_DSP | ASE_xNMS
+ | ASE_TLB | ASE_GINV | ASE_CRC),
+ nanomips_cp0_3264r6, nanomips_cp0sel_3264r6, nanomips_cp1_names_3264r6,
+ nanomips_hwr_names_3264r6},
+
+ {"32r6s", 1, bfd_mach_nanomipsisa32r6, CPU_NANOMIPS32R6, ISA_NANOMIPS32R6,
+ (ASE_EVA | ASE_MSA | ASE_VIRT | ASE_MCU | ASE_MT | ASE_DSP | ASE_TLB
+ | ASE_GINV | ASE_CRC),
+ nanomips_cp0_3264r6, nanomips_cp0sel_3264r6, nanomips_cp1_names_3264r6,
+ nanomips_hwr_names_3264r6},
+
+ {"64r6", 1, bfd_mach_nanomipsisa64r6, CPU_NANOMIPS64R6, ISA_NANOMIPS64R6,
+ (ASE_EVA | ASE_MSA | ASE_MSA64 | ASE_VIRT | ASE_MCU | ASE_MT | ASE_DSP
+ | ASE_DSP64 | ASE_xNMS | ASE_TLB | ASE_GINV | ASE_CRC | ASE_CRC64),
+ nanomips_cp0_3264r6, nanomips_cp0sel_3264r6, nanomips_cp1_names_3264r6,
+ nanomips_hwr_names_3264r6},
+};
+
+/* ISA and processor type to disassemble for, and register names to use.
+ set_default_nanomips_dis_options and parse_nanomips_dis_options fill in
+ these values. */
+
+static int nanomips_processor;
+static int nanomips_ase;
+static int nanomips_isa;
+static const char *const *nanomips_gpr_names;
+static const char *const *nanomips_fpr_names;
+static const struct nanomips_cp0_name *nanomips_cp0_names;
+static const struct nanomips_cp0_select *nanomips_cp0sel_names;
+static const char *const *nanomips_cp1_names;
+static const struct nanomips_hwr_name *nanomips_hwr_names;
+
+/* Other options */
+static int no_aliases; /* If set, disassemble as most general inst. */
+static bool show_arch_insn; /* Mnemonics with suffix. */
+static bool show_mttgpr_rc1 = false; /* RC1 style MTTGPR format. */
+\f
+
+/* Map ABI name to nanomips_abi_choice descriptor. */
+
+static const struct nanomips_abi_choice *
+choose_abi_by_name (const char *name, unsigned int namelen)
+{
+ const struct nanomips_abi_choice *c;
+ unsigned int i;
+
+ for (i = 0, c = NULL; i < ARRAY_SIZE (nanomips_abi_choices) && c == NULL;
+ i++)
+ if (strncmp (nanomips_abi_choices[i].name, name, namelen) == 0
+ && strlen (nanomips_abi_choices[i].name) == namelen)
+ c = &nanomips_abi_choices[i];
+
+ return c;
+}
+
+/* Map architecture name to nanomips_arch_choice descriptor. */
+
+static const struct nanomips_arch_choice *
+choose_arch_by_name (const char *name, unsigned int namelen)
+{
+ const struct nanomips_arch_choice *c = NULL;
+ unsigned int i;
+
+ for (i = 0, c = NULL; i < ARRAY_SIZE (nanomips_arch_choices) && c == NULL;
+ i++)
+ if (strncmp (nanomips_arch_choices[i].name, name, namelen) == 0
+ && strlen (nanomips_arch_choices[i].name) == namelen)
+ c = &nanomips_arch_choices[i];
+
+ return c;
+}
+
+/* Map BFD architecture to nanomips_arch_choice descriptor. */
+
+static const struct nanomips_arch_choice *
+choose_arch_by_number (unsigned long mach)
+{
+ static unsigned long hint_bfd_mach;
+ static const struct nanomips_arch_choice *hint_arch_choice;
+ const struct nanomips_arch_choice *c;
+ unsigned int i;
+
+ /* We optimize this because even if the user specifies no
+ flags, this will be done for every instruction! */
+ if (hint_bfd_mach == mach
+ && hint_arch_choice != NULL
+ && hint_arch_choice->bfd_mach == hint_bfd_mach)
+ return hint_arch_choice;
+
+ for (i = 0, c = NULL; i < ARRAY_SIZE (nanomips_arch_choices) && c == NULL;
+ i++)
+ {
+ if (nanomips_arch_choices[i].bfd_mach_valid
+ && nanomips_arch_choices[i].bfd_mach == mach)
+ {
+ c = &nanomips_arch_choices[i];
+ hint_bfd_mach = mach;
+ hint_arch_choice = c;
+ }
+ }
+ return c;
+}
+
+/* Select default descriptors and initial mode for the default
+ architecture. */
+
+static void
+set_default_nanomips_dis_options (struct disassemble_info *info)
+{
+ const struct nanomips_arch_choice *chosen_arch;
+
+ nanomips_isa = ISA_NANOMIPS32R6;
+ nanomips_processor = CPU_NANOMIPS32R6;
+ nanomips_isa = true;
+ nanomips_ase = 0;
+ nanomips_fpr_names = nanomips_fpr_names_numeric;
+ nanomips_cp0_names = nanomips_cp0_numeric;
+ nanomips_cp0sel_names = nanomips_cp0sel_numeric;
+ nanomips_cp1_names = nanomips_cp1_names_numeric;
+ nanomips_hwr_names = nanomips_hwr_names_numeric;
+ no_aliases = 0;
+ show_arch_insn = false;
+
+ nanomips_gpr_names = nanomips_gpr_names_symbolic;
+
+ /* Set ISA, architecture, and cp0 register names as best we can. */
+ chosen_arch = choose_arch_by_number (info->mach);
+ if (chosen_arch != NULL)
+ {
+ nanomips_processor = chosen_arch->processor;
+ nanomips_isa = chosen_arch->isa;
+ nanomips_ase = chosen_arch->ase;
+ nanomips_cp0_names = chosen_arch->cp0_names;
+ nanomips_cp0sel_names = chosen_arch->cp0sel_names;
+ nanomips_cp1_names = chosen_arch->cp1_names;
+ nanomips_hwr_names = chosen_arch->hwr_names;
+ }
+}
+
+/* Parse and translate a command-line options to internal state. */
+
+static void
+parse_nanomips_dis_option (const char *option, unsigned int len)
+{
+ unsigned int i, optionlen, vallen;
+ const char *val;
+ const struct nanomips_abi_choice *chosen_abi;
+ const struct nanomips_arch_choice *chosen_arch;
+
+ /* Try to match options that are simple flags */
+ if (startswith (option, "show-arch-insn"))
+ {
+ show_arch_insn = true;
+ return;
+ }
+
+ if (startswith (option, "no-aliases"))
+ {
+ no_aliases = 1;
+ return;
+ }
+
+ if (startswith (option, "show-mttgpr-rc1"))
+ {
+ show_mttgpr_rc1 = true;
+ return;
+ }
+
+ if (startswith (option, "msa"))
+ {
+ nanomips_ase |= ASE_MSA;
+ if ((nanomips_isa & INSN_ISA_MASK) == ISA_NANOMIPS64R6)
+ nanomips_ase |= ASE_MSA64;
+ return;
+ }
+
+ if (startswith (option, "virt"))
+ {
+ nanomips_ase |= ASE_VIRT;
+
+ if (nanomips_isa & ISA_NANOMIPS64R6)
+ nanomips_ase |= ASE_VIRT64;
+
+ if (nanomips_ase & ASE_GINV)
+ nanomips_ase |= ASE_GINV_VIRT;
+ }
+
+ if (startswith (option, "ginv"))
+ {
+ nanomips_ase |= ASE_GINV;
+ if (nanomips_ase & ASE_VIRT)
+ nanomips_ase |= ASE_GINV_VIRT;
+ return;
+ }
+
+ /* Look for the = that delimits the end of the option name. */
+ for (i = 0; i < len; i++)
+ if (option[i] == '=')
+ break;
+
+ if (i == 0) /* Invalid option: no name before '='. */
+ return;
+ if (i == len) /* Invalid option: no '='. */
+ return;
+ if (i == (len - 1)) /* Invalid option: no value after '='. */
+ return;
+
+ optionlen = i;
+ val = option + (optionlen + 1);
+ vallen = len - (optionlen + 1);
+
+ if (strncmp ("gpr-names", option, optionlen) == 0
+ && strlen ("gpr-names") == optionlen)
+ {
+ chosen_abi = choose_abi_by_name (val, vallen);
+ if (chosen_abi != NULL)
+ nanomips_gpr_names = chosen_abi->gpr_names;
+ return;
+ }
+
+ if (strncmp ("fpr-names", option, optionlen) == 0
+ && strlen ("fpr-names") == optionlen)
+ {
+ chosen_abi = choose_abi_by_name (val, vallen);
+ if (chosen_abi != NULL)
+ nanomips_fpr_names = chosen_abi->fpr_names;
+ return;
+ }
+
+ if (strncmp ("cp0-names", option, optionlen) == 0
+ && strlen ("cp0-names") == optionlen)
+ {
+ chosen_arch = choose_arch_by_name (val, vallen);
+ if (chosen_arch != NULL)
+ {
+ nanomips_cp0_names = chosen_arch->cp0_names;
+ nanomips_cp0sel_names = chosen_arch->cp0sel_names;
+ }
+ return;
+ }
+
+ if (strncmp ("cp1-names", option, optionlen) == 0
+ && strlen ("cp1-names") == optionlen)
+ {
+ chosen_arch = choose_arch_by_name (val, vallen);
+ if (chosen_arch != NULL)
+ nanomips_cp1_names = chosen_arch->cp1_names;
+ return;
+ }
+
+ if (strncmp ("hwr-names", option, optionlen) == 0
+ && strlen ("hwr-names") == optionlen)
+ {
+ chosen_arch = choose_arch_by_name (val, vallen);
+ if (chosen_arch != NULL)
+ nanomips_hwr_names = chosen_arch->hwr_names;
+ return;
+ }
+
+ if (strncmp ("reg-names", option, optionlen) == 0
+ && strlen ("reg-names") == optionlen)
+ {
+ /* We check both ABI and ARCH here unconditionally, so
+ that "numeric" will do the desirable thing: select
+ numeric register names for all registers. Other than
+ that, a given name probably won't match both. */
+ chosen_abi = choose_abi_by_name (val, vallen);
+ if (chosen_abi != NULL)
+ {
+ nanomips_gpr_names = chosen_abi->gpr_names;
+ nanomips_fpr_names = chosen_abi->fpr_names;
+ }
+ chosen_arch = choose_arch_by_name (val, vallen);
+ if (chosen_arch != NULL)
+ {
+ nanomips_cp0_names = chosen_arch->cp0_names;
+ nanomips_cp0sel_names = chosen_arch->cp0sel_names;
+ nanomips_cp1_names = chosen_arch->cp1_names;
+ nanomips_hwr_names = chosen_arch->hwr_names;
+ }
+ return;
+ }
+
+ /* Invalid option. */
+}
+
+/* Loop to parse nanoMIPS-specific command-line options. */
+
+static void
+parse_nanomips_dis_options (const char *options)
+{
+ const char *option_end;
+
+ if (options == NULL)
+ return;
+
+ while (*options != '\0')
+ {
+ /* Skip empty options. */
+ if (*options == ',')
+ {
+ options++;
+ continue;
+ }
+
+ /* We know that *options is neither NUL or a comma. */
+ option_end = options + 1;
+ while (*option_end != ',' && *option_end != '\0')
+ option_end++;
+
+ parse_nanomips_dis_option (options, option_end - options);
+
+ /* Go on to the next one. If option_end points to a comma, it
+ will be skipped above. */
+ options = option_end;
+ }
+}
+
+/* Look-up and print the symbolic name of a named CP0 register with
+ a fixed select value. Fall-back to numeric format if no match is
+ found. */
+
+static void
+print_cp0_reg (struct disassemble_info *info, int regno)
+{
+ int i;
+ unsigned int selnum = regno & NANOMIPSOP_MASK_CP0SEL;
+ unsigned int cp0_regno = regno >> NANOMIPSOP_SH_CP0SEL;
+
+ if (nanomips_cp0_names != nanomips_cp0_numeric)
+ for (i = cp0_regno; nanomips_cp0_names[i].name; i++)
+ {
+ if (nanomips_cp0_names[i].num == cp0_regno
+ && nanomips_cp0_names[i].sel == selnum)
+ {
+ info->fprintf_func (info->stream, "%s",
+ nanomips_cp0_names[i].name + 1);
+ return;
+ }
+ }
+
+ /* A select value of 0 is deemed optional. */
+ if (selnum == 0)
+ info->fprintf_func (info->stream, "$%d", cp0_regno);
+ else
+ info->fprintf_func (info->stream, "$%d,%d", cp0_regno, selnum);
+}
+
+/* Look-up and print the symbolic name of a named CP0 register with
+ a variable select value. Fall-back to numeric format if no match is
+ found. */
+
+static void
+print_cp0sel_reg (struct disassemble_info *info, unsigned int regno,
+ unsigned int selnum)
+{
+ int i;
+
+ for (i = 0; nanomips_cp0sel_names[i].name; i++)
+ {
+ if (nanomips_cp0sel_names[i].num == regno
+ && ((1 << selnum) & nanomips_cp0sel_names[i].selmask) != 0)
+ {
+ info->fprintf_func (info->stream, "%s,%d",
+ nanomips_cp0sel_names[i].name + 1, selnum);
+ return;
+ }
+ }
+
+ /* A select value of 0 is deemed optional. */
+ if (selnum == 0)
+ info->fprintf_func (info->stream, "$%d", regno);
+ else
+ info->fprintf_func (info->stream, "$%d,%d", regno, selnum);
+}
+
+/* Look-up and print the symbolic name of a named CP0 register with
+ a fixed select value. Fall-back to numeric format if no match is
+ found. */
+
+static void
+print_hwr_reg (struct disassemble_info *info, int regno)
+{
+ int i;
+ unsigned int selnum = regno & NANOMIPSOP_MASK_CP0SEL;
+ unsigned int hwr_regno = regno >> NANOMIPSOP_SH_HWRSEL;
+
+ if (nanomips_hwr_names != nanomips_hwr_names_numeric)
+ for (i = 0; nanomips_hwr_names[i].name; i++)
+ {
+ if (nanomips_hwr_names[i].num == hwr_regno
+ && nanomips_hwr_names[i].sel == selnum)
+ {
+ info->fprintf_func (info->stream, "%s",
+ nanomips_hwr_names[i].name + 1);
+ return;
+ }
+ }
+
+ /* A select value of 0 is deemed optional. */
+ if (selnum == 0)
+ info->fprintf_func (info->stream, "$%d", hwr_regno);
+ else
+ info->fprintf_func (info->stream, "$%d,%d", hwr_regno, selnum);
+}
+
+/* Print register REGNO, of type TYPE, for instruction OPCODE. */
+
+static void
+print_reg (struct disassemble_info *info,
+ const struct nanomips_opcode *opcode,
+ enum nanomips_reg_operand_type type, int regno)
+{
+ switch (type)
+ {
+ case OP_REG_GP:
+ info->fprintf_func (info->stream, "%s", nanomips_gpr_names[regno]);
+ break;
+
+ case OP_REG_FP:
+ info->fprintf_func (info->stream, "%s", nanomips_fpr_names[regno]);
+ break;
+
+ case OP_REG_ACC:
+ info->fprintf_func (info->stream, "$ac%d", regno);
+ break;
+
+ case OP_REG_COPRO:
+ if (opcode->name[strlen (opcode->name) - 1] == '1')
+ info->fprintf_func (info->stream, "%s", nanomips_cp1_names[regno]);
+ else
+ info->fprintf_func (info->stream, "$%d", regno);
+ break;
+
+ case OP_REG_HW:
+ case OP_REG_HWRSEL:
+ print_hwr_reg (info, regno);
+ break;
+
+ case OP_REG_MSA:
+ info->fprintf_func (info->stream, "$w%d", regno);
+ break;
+
+ case OP_REG_MSA_CTRL:
+ info->fprintf_func (info->stream, "%s", msa_control_names[regno]);
+ break;
+
+ case OP_REG_CP0:
+ print_cp0_reg (info, regno);
+ break;
+
+ case OP_REG_CP0SEL:
+ /* Need to check select bits againt mask, defer output to next operand. */
+ break;
+ }
+}
+\f
+/* Used to track the state carried over from previous operands in
+ an instruction. */
+
+struct nanomips_print_arg_state
+{
+ /* The value of the last OP_INT seen. We only use this for OP_MSB,
+ where the value is known to be unsigned and small. */
+ unsigned int last_int;
+
+ /* The type and number of the last OP_REG seen. We only use this for
+ OP_REPEAT_DEST_REG and OP_REPEAT_PREV_REG. */
+ enum nanomips_reg_operand_type last_reg_type;
+ unsigned int last_regno;
+ unsigned int dest_regno;
+ unsigned int seen_dest;
+};
+
+/* Initialize STATE for the start of an instruction. */
+
+static inline void
+init_print_arg_state (struct nanomips_print_arg_state *state)
+{
+ memset (state, 0, sizeof (*state));
+}
+
+/* Record information about a register operand. */
+
+static void
+nanomips_seen_register (struct nanomips_print_arg_state *state,
+ unsigned int regno,
+ enum nanomips_reg_operand_type reg_type)
+{
+ state->last_reg_type = reg_type;
+ state->last_regno = regno;
+
+ if (!state->seen_dest)
+ {
+ state->seen_dest = 1;
+ state->dest_regno = regno;
+ }
+}
+
+/* Pretty-print a save/restore register list. */
+
+static void
+nanomips_print_save_restore (struct disassemble_info *info,
+ unsigned int uval, bool mode16)
+{
+ const fprintf_ftype infprintf = info->fprintf_func;
+ void *is = info->stream;
+ char *comma = ",";
+ unsigned int pending = 0;
+ unsigned int freg, fp, gp, ra;
+ int count;
+ fp = gp = ra = 0;
+
+ if (mode16)
+ {
+ freg = 30 | (uval >> 4);
+ count = uval & 0xf;
+ }
+ else
+ {
+ freg = (uval >> 6) & 0x1f;
+ count = (uval >> 1) & 0xf;
+ if (count > 0)
+ gp = uval & 1;
+ }
+
+ if (freg == 30 && count > 0)
+ fp = 1;
+ if ((freg == 31 && count > 0) || (freg == 30 && count > 1))
+ ra = 1;
+
+ if (freg + count == 45)
+ gp = 1;
+
+ count = count - gp;
+ if (fp && count > 0)
+ {
+ freg = (freg & 0x10) | ((freg + 1) % 32);
+ count--;
+ }
+
+ if (ra && count > 0)
+ {
+ freg = (freg & 0x10) | ((freg + 1) % 32);
+ count--;
+ }
+
+ if (fp)
+ {
+ infprintf (is, "%s", nanomips_gpr_names[30]);
+ pending = 1;
+ }
+
+ if (ra)
+ {
+ infprintf (is, "%s%s", (pending ? comma : ""), nanomips_gpr_names[31]);
+ pending = 1;
+ }
+
+ if (count > 0)
+ {
+ if (count > 1)
+ infprintf (is, "%s%s-%s", (pending ? comma : ""),
+ nanomips_gpr_names[freg],
+ nanomips_gpr_names[freg + count - 1]);
+ else
+ infprintf (is, "%s%s", (pending ? comma : ""),
+ nanomips_gpr_names[freg]);
+ pending = 1;
+ }
+
+ if (gp)
+ infprintf (is, "%s%s", (pending ? comma : ""), nanomips_gpr_names[28]);
+}
+
+/* Pretty-print save/restore floating-point register list. */
+
+static void
+nanomips_print_save_restore_fp (struct disassemble_info *info,
+ unsigned int count)
+{
+ const fprintf_ftype infprintf = info->fprintf_func;
+ void *is = info->stream;
+
+ if (count == 1)
+ infprintf (is, "%s", nanomips_fpr_names[0]);
+ else
+ infprintf (is, "%s-%s", nanomips_fpr_names[0],
+ nanomips_fpr_names[count - 1]);
+}
+
+/* Print operand OPERAND of OPCODE, using STATE to track inter-operand state.
+ UVAL is the encoding of the operand (shifted into bit 0) and BASE_PC is
+ the base address for OP_PCREL operands. */
+
+static void
+print_insn_arg (struct disassemble_info *info,
+ struct nanomips_print_arg_state *state,
+ const struct nanomips_opcode *opcode,
+ const struct nanomips_operand *operand,
+ bfd_vma base_pc, unsigned int uval)
+{
+ const fprintf_ftype infprintf = info->fprintf_func;
+ void *is = info->stream;
+
+ switch (operand->type)
+ {
+ case OP_INT:
+ case OP_IMM_INT:
+ {
+ const struct nanomips_int_operand *int_op;
+
+ int_op = (const struct nanomips_int_operand *) operand;
+ uval = nanomips_decode_int_operand (int_op, uval);
+ state->last_int = uval;
+ if (int_op->print_hex)
+ infprintf (is, "0x%x", uval);
+ else
+ infprintf (is, "%d", uval);
+ }
+ break;
+
+ case OP_MAPPED_INT:
+ {
+ const struct nanomips_mapped_int_operand *mint_op;
+
+ mint_op = (const struct nanomips_mapped_int_operand *) operand;
+ uval = mint_op->int_map[uval];
+ state->last_int = uval;
+ if (mint_op->print_hex)
+ infprintf (is, "0x%x", uval);
+ else
+ infprintf (is, "%d", uval);
+ }
+ break;
+
+ case OP_MSB:
+ {
+ const struct nanomips_msb_operand *msb_op;
+
+ msb_op = (const struct nanomips_msb_operand *) operand;
+ uval += msb_op->bias;
+ if (msb_op->add_lsb)
+ uval -= state->last_int;
+ infprintf (is, "%d", uval);
+ }
+ break;
+
+ case OP_REG:
+ case OP_OPTIONAL_REG:
+ case OP_MAPPED_CHECK_PREV:
+ case OP_BASE_CHECK_OFFSET:
+ {
+ const struct nanomips_reg_operand *reg_op;
+
+ reg_op = (const struct nanomips_reg_operand *) operand;
+ uval = nanomips_decode_reg_operand (reg_op, uval);
+ print_reg (info, opcode, reg_op->reg_type, uval);
+
+ nanomips_seen_register (state, uval, reg_op->reg_type);
+ }
+ break;
+
+ case OP_REG_PAIR:
+ {
+ const struct nanomips_reg_pair_operand *pair_op;
+
+ pair_op = (const struct nanomips_reg_pair_operand *) operand;
+ print_reg (info, opcode, pair_op->reg_type, pair_op->reg1_map[uval]);
+ infprintf (is, ",");
+ print_reg (info, opcode, pair_op->reg_type, pair_op->reg2_map[uval]);
+ }
+ break;
+
+ case OP_PCREL:
+ {
+ const struct nanomips_pcrel_operand *pcrel_op;
+
+ pcrel_op = (const struct nanomips_pcrel_operand *) operand;
+ info->target = nanomips_decode_pcrel_operand (pcrel_op, base_pc, uval);
+
+ /* Preserve the ISA bit for the GDB disassembler,
+ otherwise clear it. */
+ if (info->flavour != bfd_target_unknown_flavour)
+ info->target &= -2;
+
+ (*info->print_address_func) (info->target, info);
+ }
+ break;
+
+ case OP_NON_ZERO_PCREL_S1:
+ {
+ const struct nanomips_pcrel_operand pcrel_op = {
+ {{OP_PCREL, operand->size, operand->lsb, 0, 0},
+ (1 << operand->size) - 1, 0, 1, true}, 0, 0, 0
+ };
+
+ if ((info->flags & INSN_HAS_RELOC) == 0)
+ info->target = nanomips_decode_pcrel_operand (&pcrel_op, base_pc,
+ uval);
+ else
+ info->target = 0;
+ (*info->print_address_func) (info->target, info);
+ }
+ break;
+
+ case OP_CHECK_PREV:
+ case OP_NON_ZERO_REG:
+ {
+ print_reg (info, opcode, OP_REG_GP, uval & 31);
+ nanomips_seen_register (state, uval, OP_REG_GP);
+ }
+ break;
+
+ case OP_SAVE_RESTORE_LIST:
+ nanomips_print_save_restore (info, uval, opcode->mask >> 16 == 0);
+ break;
+
+ case OP_SAVE_RESTORE_FP_LIST:
+ nanomips_print_save_restore_fp (info, uval + 1);
+ break;
+
+ case OP_REPEAT_PREV_REG:
+ print_reg (info, opcode, state->last_reg_type, state->last_regno);
+ break;
+
+ case OP_REPEAT_DEST_REG:
+ print_reg (info, opcode, state->last_reg_type, state->dest_regno);
+ break;
+
+ case OP_HI20_PCREL:
+ {
+ if ((info->flags & INSN_HAS_RELOC) == 0)
+ {
+ uval = nanomips_decode_hi20_int_operand (operand, uval);
+ infprintf (is, "0x%x", uval & 0xfffff);
+ }
+ else
+ {
+ info->target = nanomips_decode_hi20_pcrel_operand (operand, base_pc,
+ uval);
+ infprintf (is, "%%pcrel_hi(");
+ (*info->print_address_func) (info->target, info);
+ infprintf (is, ")");
+ }
+ }
+ break;
+
+ case OP_HI20_SCALE:
+ {
+ uval = nanomips_decode_hi20_int_operand (operand, uval);
+ state->last_int = uval;
+ infprintf (is, "0x%x", uval & 0xfffff);
+ }
+ break;
+
+ case OP_HI20_INT:
+ {
+ uval = nanomips_decode_hi20_int_operand (operand, uval);
+ state->last_int = uval;
+ if ((info->flags & INSN_HAS_RELOC) != 0 || uval == 0)
+ infprintf (is, "0x%x", uval & 0xfffff);
+ else
+ infprintf (is, "%%hi(0x%x)", (uval & 0xfffff) << 12);
+ }
+ break;
+
+ case OP_IMM_WORD:
+ {
+ const struct nanomips_int_operand *int_op;
+ int_op = (const struct nanomips_int_operand *) operand;
+ state->last_int = ((uval >> 16) & 0xffff) | (uval << 16);
+ state->last_int += int_op->bias;
+ infprintf (is, "%d", state->last_int);
+ }
+ break;
+
+ case OP_INT_WORD:
+ case OP_GPREL_WORD:
+ {
+ state->last_int = ((uval >> 16) & 0xffff) | (uval << 16);
+ infprintf (is, "%d", state->last_int);
+ }
+ break;
+
+ case OP_UINT_WORD:
+ {
+ state->last_int = ((uval >> 16) & 0xffff) | (uval << 16);
+ infprintf (is, "0x%x", state->last_int);
+ }
+ break;
+
+ case OP_PC_WORD:
+ {
+ info->target = base_pc + (((uval >> 16) & 0xffff) | (uval << 16));
+ (*info->print_address_func) (info->target, info);
+ }
+ break;
+
+ case OP_NEG_INT:
+ infprintf (is, "-%d", uval);
+ break;
+
+ case OP_CP0SEL:
+ if (no_aliases)
+ infprintf (is, ",%d", uval);
+ else
+ print_cp0sel_reg (info, state->last_regno, uval);
+ break;
+
+ case OP_DONT_CARE:
+ case OP_COPY_BITS:
+ default:
+ break;
+ }
+}
+
+/* Check if register+select map to a valid CP0 select sequence. */
+
+static bool
+validate_cp0_reg_operand (unsigned int uval)
+{
+ int i;
+ unsigned int regno, selnum;
+ regno = uval >> NANOMIPSOP_SH_CP0SEL;
+ selnum = uval & NANOMIPSOP_MASK_CP0SEL;
+
+ for (i = 0; nanomips_cp0_3264r6[i].name; i++)
+ if (regno == nanomips_cp0_3264r6[i].num
+ && selnum == nanomips_cp0_3264r6[i].sel)
+ break;
+ else if (regno < nanomips_cp0_3264r6[i].num)
+ return false;
+
+ if (nanomips_cp0_3264r6[i].name == NULL)
+ return false;
+
+ return true;
+}
+
+/* Validate the arguments for INSN, which is described by OPCODE.
+ Use DECODE_OPERAND to get the encoding of each operand. */
+
+static bool
+validate_insn_args (const struct nanomips_opcode *opcode,
+ const struct nanomips_operand *(*decode_operand) (const char *),
+ unsigned int insn, struct disassemble_info *info)
+{
+ struct nanomips_print_arg_state state;
+ const struct nanomips_operand *operand;
+ const char *s;
+ unsigned int uval;
+
+ init_print_arg_state (&state);
+ for (s = opcode->args; *s; ++s)
+ {
+ switch (*s)
+ {
+ case ',':
+ case '(':
+ case ')':
+ break;
+
+ case '#':
+ ++s;
+ break;
+
+ default:
+ operand = decode_operand (s);
+
+ if (!operand)
+ continue;
+
+ uval = nanomips_extract_operand (operand, insn);
+ switch (operand->type)
+ {
+ case OP_REG:
+ case OP_OPTIONAL_REG:
+ case OP_BASE_CHECK_OFFSET:
+ {
+ const struct nanomips_reg_operand *reg_op;
+
+ reg_op = (const struct nanomips_reg_operand *) operand;
+
+ if (operand->type == OP_REG
+ && reg_op->reg_type == OP_REG_CP0
+ && !validate_cp0_reg_operand (uval))
+ return false;
+
+ uval = nanomips_decode_reg_operand (reg_op, uval);
+ nanomips_seen_register (&state, uval, reg_op->reg_type);
+ }
+ break;
+
+ case OP_CHECK_PREV:
+ {
+ const struct nanomips_check_prev_operand *prev_op
+ = (const struct nanomips_check_prev_operand *) operand;
+
+ if (!prev_op->zero_ok && uval == 0)
+ return false;
+
+ if (((prev_op->less_than_ok && uval < state.last_regno)
+ || (prev_op->greater_than_ok && uval > state.last_regno)
+ || (prev_op->equal_ok && uval == state.last_regno)))
+ break;
+
+ return false;
+ }
+
+ case OP_MAPPED_CHECK_PREV:
+ {
+ const struct nanomips_mapped_check_prev_operand *prev_op =
+ (const struct nanomips_mapped_check_prev_operand *) operand;
+ unsigned int last_uval =
+ nanomips_encode_reg_operand (operand, state.last_regno);
+
+ if (((prev_op->less_than_ok && uval < last_uval)
+ || (prev_op->greater_than_ok && uval > last_uval)
+ || (prev_op->equal_ok && uval == last_uval)))
+ break;
+
+ return false;
+ }
+
+ case OP_NON_ZERO_REG:
+ if (uval == 0)
+ return false;
+ break;
+
+ case OP_NON_ZERO_PCREL_S1:
+ if (uval == 0 && (info->flags & INSN_HAS_RELOC) == 0)
+ return false;
+ break;
+
+ case OP_SAVE_RESTORE_LIST:
+ {
+ /* The operand for SAVE/RESTORE is split into 3 pieces
+ rather than just 2 but we only support a 2-way split
+ decode the last bit of the instruction here. */
+ if (opcode->mask >> 16 != 0 && ((insn >> 20) & 0x1) != 0)
+ return false;
+ }
+ break;
+
+ case OP_IMM_INT:
+ case OP_IMM_WORD:
+ case OP_NEG_INT:
+ case OP_INT:
+ case OP_MAPPED_INT:
+ case OP_MSB:
+ case OP_REG_PAIR:
+ case OP_PCREL:
+ case OP_REPEAT_PREV_REG:
+ case OP_REPEAT_DEST_REG:
+ case OP_SAVE_RESTORE_FP_LIST:
+ case OP_HI20_INT:
+ case OP_HI20_PCREL:
+ case OP_INT_WORD:
+ case OP_UINT_WORD:
+ case OP_PC_WORD:
+ case OP_GPREL_WORD:
+ case OP_DONT_CARE:
+ case OP_HI20_SCALE:
+ case OP_COPY_BITS:
+ case OP_CP0SEL:
+ break;
+ }
+
+ if (*s == 'm' || *s == '+' || *s == '-' || *s == '`')
+ ++s;
+ }
+ }
+ return true;
+}
+
+/* Print the arguments for INSN, which is described by OPCODE.
+ Use DECODE_OPERAND to get the encoding of each operand. Use BASE_PC
+ as the base of OP_PCREL operands, adjusting by LENGTH if the OP_PCREL
+ operand is for a branch or jump. */
+
+static void
+print_insn_args (struct disassemble_info *info,
+ const struct nanomips_opcode *opcode,
+ const struct nanomips_operand *(*decode_operand) (const char *),
+ bfd_uint64_t insn, bfd_vma insn_pc, unsigned int length)
+{
+ const fprintf_ftype infprintf = info->fprintf_func;
+ void *is = info->stream;
+ struct nanomips_print_arg_state state;
+ const struct nanomips_operand *operand;
+ const char *s;
+ bool pending_sep = false;
+ bool pending_space = true;
+
+ init_print_arg_state (&state);
+ for (s = opcode->args; *s; ++s)
+ {
+ switch (*s)
+ {
+ case ',':
+ pending_sep = true;
+ break;
+ case '(':
+ if (pending_sep)
+ {
+ infprintf (is, ",");
+ pending_sep = false;
+ }
+ /* fall-through */
+ case ')':
+ infprintf (is, "%c", *s);
+ break;
+
+ case '#':
+ ++s;
+ infprintf (is, "%c%c", *s, *s);
+ break;
+
+ default:
+ operand = decode_operand (s);
+ if (!operand)
+ {
+ /* xgettext:c-format */
+ infprintf (is,
+ _("# internal error, undefined operand in `%s %s'"),
+ opcode->name, opcode->args);
+ return;
+ }
+
+ /* Defer printing the comma separator for CP0-select values since
+ the preceding register output is also defered. */
+ if (operand->type != OP_DONT_CARE
+ && operand->type != OP_CP0SEL
+ && pending_sep)
+ {
+ infprintf (is, ",");
+ pending_sep = false;
+ }
+
+ if (operand->type != OP_DONT_CARE && pending_space)
+ infprintf (is, "\t");
+ pending_space = false;
+
+ {
+ bfd_vma base_pc = 0;
+ bool have_reloc = ((info->flags & INSN_HAS_RELOC) != 0);
+
+ if (!have_reloc)
+ base_pc = insn_pc;
+
+ if ((operand->type == OP_PCREL
+ || operand->type == OP_HI20_PCREL
+ || operand->type == OP_NON_ZERO_PCREL_S1
+ || operand->type == OP_PC_WORD)
+ && !have_reloc)
+ base_pc += length;
+
+ if (operand->type == OP_INT_WORD
+ || operand->type == OP_UINT_WORD
+ || operand->type == OP_PC_WORD
+ || operand->type == OP_GPREL_WORD
+ || operand->type == OP_IMM_WORD)
+ print_insn_arg (info, &state, opcode, operand, base_pc,
+ insn >> 32);
+ else if (operand->type != OP_DONT_CARE)
+ print_insn_arg (info, &state, opcode, operand, base_pc,
+ nanomips_extract_operand (operand, insn));
+ }
+ if (*s == 'm' || *s == '+' || *s == '-' || *s == '`')
+ ++s;
+ break;
+ }
+ }
+}
+\f
+
+enum match_kind
+{
+ MATCH_NONE,
+ MATCH_FULL,
+ MATCH_SHORT
+};
+
+/* Disassemble nanoMIPS instructions. */
+
+static int
+_print_insn_nanomips (bfd_vma memaddr_base, struct disassemble_info *info)
+{
+ const fprintf_ftype infprintf = info->fprintf_func;
+ const struct nanomips_opcode *op, *opend;
+ void *is = info->stream;
+ bfd_byte buffer[2];
+ bfd_uint64_t higher = 0;
+ unsigned int length;
+ int status;
+ bfd_uint64_t insn;
+
+ bfd_vma memaddr = memaddr_base;
+
+ info->bytes_per_chunk = 2;
+ info->display_endian = info->endian;
+ info->insn_info_valid = 1;
+ info->branch_delay_insns = 0;
+ info->data_size = 0;
+ info->insn_type = dis_nonbranch;
+ info->target = 0;
+ info->target2 = 0;
+
+ status = (*info->read_memory_func) (memaddr, buffer, 2, info);
+ if (status != 0)
+ {
+ (*info->memory_error_func) (status, memaddr, info);
+ return -1;
+ }
+
+ length = 2;
+
+ if (info->endian == BFD_ENDIAN_BIG)
+ insn = bfd_getb16 (buffer);
+ else
+ insn = bfd_getl16 (buffer);
+
+ if ((insn & 0xfc00) == 0x6000)
+ {
+ unsigned imm;
+ /* This is a 48-bit nanoMIPS instruction. */
+ status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
+ if (status != 0)
+ {
+ infprintf (is, "0x%x (expected 48 bits, got only 16): ",
+ (unsigned) insn);
+ (*info->memory_error_func) (status, memaddr + 2, info);
+ return -1;
+ }
+ if (info->endian == BFD_ENDIAN_BIG)
+ imm = bfd_getb16 (buffer);
+ else
+ imm = bfd_getl16 (buffer);
+ higher = (imm << 16);
+
+ status = (*info->read_memory_func) (memaddr + 4, buffer, 2, info);
+ if (status != 0)
+ {
+ infprintf (is, "0x%x (expected 48 bits, got only 32): ",
+ (unsigned) insn);
+ (*info->memory_error_func) (status, memaddr + 4, info);
+ return -1;
+ }
+
+ if (info->endian == BFD_ENDIAN_BIG)
+ imm = bfd_getb16 (buffer);
+ else
+ imm = bfd_getl16 (buffer);
+ higher = higher | imm;
+
+ length += 4;
+ }
+ else if ((insn & 0x1000) == 0x0)
+ {
+ /* This is a 32-bit nanoMIPS instruction. */
+ higher = insn;
+
+ status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
+ if (status != 0)
+ {
+ infprintf (is, "0x%x (expected 32 bits, got only 16): ",
+ (unsigned) higher);
+ (*info->memory_error_func) (status, memaddr + 2, info);
+ return -1;
+ }
+
+ if (info->endian == BFD_ENDIAN_BIG)
+ insn = bfd_getb16 (buffer);
+ else
+ insn = bfd_getl16 (buffer);
+
+ insn = insn | (higher << 16);
+
+ length += 2;
+ }
+
+ /* FIXME: Should probably use a hash table on the major opcode here. */
+ const struct nanomips_opcode *opcodes;
+ int num_opcodes;
+ struct nanomips_operand const *(*decode) (const char *);
+
+ opcodes = nanomips_opcodes;
+ num_opcodes = bfd_nanomips_num_opcodes;
+ decode = decode_nanomips_operand;
+
+ opend = opcodes + num_opcodes;
+ for (op = opcodes; op < opend; op++)
+ {
+ if (op->pinfo != INSN_MACRO
+ && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
+ && (show_mttgpr_rc1 || (op->pinfo2 & INSN2_MTTGPR_RC1) == 0)
+ && (insn & op->mask) == op->match
+ && ((length == 2 && (op->mask & 0xffff0000) == 0)
+ || (length == 6
+ && (op->mask & 0xffff0000) == 0)
+ || (length == 4 && (op->mask & 0xffff0000) != 0)))
+ {
+ if (!nanomips_opcode_is_member (op, nanomips_isa, nanomips_ase,
+ nanomips_processor)
+ || (op->pinfo2 & INSN2_CONVERTED_TO_COMPACT))
+ continue;
+
+ if (!validate_insn_args (op, decode, insn, info))
+ continue;
+
+ infprintf (is, "%s%s", op->name,
+ (show_arch_insn ? op->suffix : ""));
+
+ if (length == 6)
+ insn |= (higher << 32);
+
+ if (op->args[0])
+ print_insn_args (info, op, decode, insn, memaddr, length);
+
+ /* Figure out instruction type and branch delay information. */
+ if ((op->pinfo2 & INSN2_UNCOND_BRANCH) != 0)
+ {
+ if ((op->pinfo & (INSN_WRITE_GPR_31 | INSN_WRITE_1)) != 0)
+ info->insn_type = dis_jsr;
+ else
+ info->insn_type = dis_branch;
+ }
+ else if ((op->pinfo2 & INSN2_COND_BRANCH) != 0)
+ {
+ if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
+ info->insn_type = dis_condjsr;
+ else
+ info->insn_type = dis_condbranch;
+ }
+ else if ((op->pinfo & (INSN_STORE_MEMORY | INSN_LOAD_MEMORY)) != 0)
+ info->insn_type = dis_dref;
+
+ return length;
+ }
+ }
+
+ infprintf (is, "0x%x", (unsigned) insn);
+ info->insn_type = dis_noninsn;
+
+ return length;
+}
+
+/* Set up the options and disassemble. */
+
+int
+print_insn_nanomips (bfd_vma memaddr, struct disassemble_info *info)
+{
+ set_default_nanomips_dis_options (info);
+ parse_nanomips_dis_options (info->disassembler_options);
+
+ return _print_insn_nanomips (memaddr, info);
+}
+\f
+/* Print description of nanoMIPS-specific command-line options. */
+
+void
+print_nanomips_disassembler_options (FILE *stream)
+{
+ unsigned int i;
+
+ fprintf (stream, _("\n\
+The following nanoMIPS specific disassembler options are supported for use\n\
+with the -M switch (multiple options should be separated by commas):\n"));
+
+ fprintf (stream, _("\n\
+ no-aliases Use canonical instruction forms.\n"));
+
+ fprintf (stream, _("\n\
+ show-arch-insn Print extended mnemonics in disassembly including\n\
+ suffix as in the architecture reference manual.\n"));
+
+ fprintf (stream, _("\n\
+ show-mttgpr-rc1 Disassemble MTTGPR as RC1 style (deprecated) format.\n"));
+
+ fprintf (stream, _("\n\
+ msa Recognize MSA instructions.\n"));
+
+ fprintf (stream, _("\n\
+ virt Recognize the virtualization ASE instructions.\n"));
+
+ fprintf (stream, _("\n\
+ mxu Recognize the MXU ASE instructions.\n"));
+
+ fprintf (stream, _("\n\
+ gpr-names=ABI Print GPR names according to specified ABI.\n\
+ Default: based on binary being disassembled.\n"));
+
+ fprintf (stream, _("\n\
+ fpr-names=ABI Print FPR names according to specified ABI.\n\
+ Default: numeric.\n"));
+
+ fprintf (stream, _("\n\
+ cp0-names=ARCH Print CP0 register names according to\n\
+ specified architecture.\n\
+ Default: based on binary being disassembled.\n"));
+
+ fprintf (stream, _("\n\
+ hwr-names=ARCH Print HWR names according to specified \n\
+ architecture.\n\
+ Default: based on binary being disassembled.\n"));
+
+ fprintf (stream, _("\n\
+ reg-names=ABI Print GPR and FPR names according to\n\
+ specified ABI.\n"));
+
+ fprintf (stream, _("\n\
+ reg-names=ARCH Print CP0 register and HWR names according to\n\
+ specified architecture.\n"));
+
+ fprintf (stream, _("\n\
+ For the options above, the following values are supported for \"ABI\":\n\
+ "));
+ for (i = 0; i < ARRAY_SIZE (nanomips_abi_choices); i++)
+ fprintf (stream, " %s", nanomips_abi_choices[i].name);
+ fprintf (stream, _("\n"));
+
+ fprintf (stream, _("\n\
+ For the options above, The following values are supported for \"ARCH\":\n\
+ "));
+ for (i = 0; i < ARRAY_SIZE (nanomips_arch_choices); i++)
+ if (*nanomips_arch_choices[i].name != '\0')
+ fprintf (stream, " %s", nanomips_arch_choices[i].name);
+ fprintf (stream, _("\n"));
+
+ fprintf (stream, _("\n"));
+}
+\f
+/* nanoMIPS hook to predict instruction length from opcode bits. */
+
+int
+nanomips_predict_insn_length (bfd_vma memaddr_base,
+ int previous_octect ATTRIBUTE_UNUSED,
+ struct disassemble_info *info)
+{
+ bfd_byte buffer[2];
+ unsigned int length;
+ bfd_uint64_t insn;
+ bfd_vma memaddr = memaddr_base;
+ int status;
+
+ status = (*info->read_memory_func) (memaddr, buffer, 2, info);
+ if (status != 0)
+ {
+ (*info->memory_error_func) (status, memaddr, info);
+ return -1;
+ }
+
+ length = 2;
+
+ if (info->endian == BFD_ENDIAN_BIG)
+ insn = bfd_getb16 (buffer);
+ else
+ insn = bfd_getl16 (buffer);
+
+ if ((insn & 0xfc00) == 0x6000)
+ length += 4;
+ else if ((insn & 0x1000) == 0x0)
+ length += 2;
+
+ return length;
+}
diff --git a/opcodes/nanomips-formats.h b/opcodes/nanomips-formats.h
new file mode 100644
index 00000000000..1144604abe6
--- /dev/null
+++ b/opcodes/nanomips-formats.h
@@ -0,0 +1,265 @@
+/* nanomips-formats.h
+ Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+ Written by Faraz Shahbazker <faraz.shahbazker@mips.com>
+
+ This library 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.
+
+ It 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 this program; see the file COPYING3. If not,
+ see <http://www.gnu.org/licenses/>. */
+
+#include "libiberty.h"
+
+#define INT_BIAS(SIZE, LSB, MAX_VAL, BIAS, SHIFT, PRINT_HEX) \
+ { \
+ static const struct nanomips_int_operand op = { \
+ { OP_INT, SIZE, LSB, 0, 0 }, MAX_VAL, BIAS, SHIFT, PRINT_HEX \
+ }; \
+ return &op.root; \
+ }
+
+#define INT_ADJ(SIZE, LSB, MAX_VAL, SHIFT, PRINT_HEX) \
+ INT_BIAS(SIZE, LSB, MAX_VAL, 0, SHIFT, PRINT_HEX)
+
+#define UINT(SIZE, LSB) \
+ INT_ADJ(SIZE, LSB, (1 << (SIZE)) - 1, 0, false)
+
+#define SINT(SIZE, LSB) \
+ INT_ADJ(SIZE, LSB, (1 << ((SIZE) - 1)) - 1, 0, false)
+
+#define HINT(SIZE, LSB) \
+ INT_ADJ(SIZE, LSB, (1 << (SIZE)) - 1, 0, true)
+
+#define BIT(SIZE, LSB, BIAS) \
+ { \
+ static const struct nanomips_int_operand op = { \
+ { OP_INT, SIZE, LSB, 0, 0 }, (1 << (SIZE)) - 1, BIAS, 0, false \
+ }; \
+ return &op.root; \
+ }
+
+#define MAPPED_INT(SIZE, LSB, MAP, PRINT_HEX) \
+ { \
+ typedef char ATTRIBUTE_UNUSED \
+ static_assert[(1 << (SIZE)) == ARRAY_SIZE (MAP)]; \
+ static const struct nanomips_mapped_int_operand op = { \
+ { OP_MAPPED_INT, SIZE, LSB, 0, 0 }, MAP, PRINT_HEX \
+ }; \
+ return &op.root; \
+ }
+
+#define MSB(SIZE, LSB, BIAS, ADD_LSB, OPSIZE) \
+ { \
+ static const struct nanomips_msb_operand op = { \
+ { OP_MSB, SIZE, LSB, 0, 0 }, BIAS, ADD_LSB, OPSIZE \
+ }; \
+ return &op.root; \
+ }
+
+#define REG(SIZE, LSB, BANK) \
+ { \
+ static const struct nanomips_reg_operand op = { \
+ { OP_REG, SIZE, LSB, 0, 0 }, OP_REG_##BANK, 0 \
+ }; \
+ return &op.root; \
+ }
+
+#define OPTIONAL_REG(SIZE, LSB, BANK) \
+ { \
+ static const struct nanomips_reg_operand op = { \
+ { OP_OPTIONAL_REG, SIZE, LSB, 0, 0 }, OP_REG_##BANK, 0 \
+ }; \
+ return &op.root; \
+ }
+
+#define MAPPED_REG(SIZE, LSB, BANK, MAP) \
+ { \
+ typedef char ATTRIBUTE_UNUSED \
+ static_assert[(1 << (SIZE)) == ARRAY_SIZE (MAP)]; \
+ static const struct nanomips_reg_operand op = { \
+ { OP_REG, SIZE, LSB, 0, 0 }, OP_REG_##BANK, MAP \
+ }; \
+ return &op.root; \
+ }
+
+#define SPLIT_MAPPED_REG(SIZE, LSB, SIZE_T, LSB_T, BANK, MAP) \
+ { \
+ typedef char ATTRIBUTE_UNUSED \
+ static_assert[(1 << (SIZE)) == ARRAY_SIZE (MAP)]; \
+ static const struct nanomips_reg_operand op = { \
+ { OP_REG, SIZE, LSB, SIZE_T, LSB_T }, OP_REG_##BANK, MAP \
+ }; \
+ return &op.root; \
+ }
+
+#define OPTIONAL_MAPPED_REG(SIZE, LSB, BANK, MAP) \
+ { \
+ typedef char ATTRIBUTE_UNUSED \
+ static_assert[(1 << (SIZE)) == ARRAY_SIZE (MAP)]; \
+ static const struct nanomips_reg_operand op = { \
+ { OP_OPTIONAL_REG, SIZE, LSB, 0, 0 }, OP_REG_##BANK, MAP \
+ }; \
+ return &op.root; \
+ }
+
+#define REG_PAIR(SIZE, LSB, BANK, MAP) \
+ { \
+ typedef char ATTRIBUTE_UNUSED \
+ static_assert1[(1 << (SIZE)) == ARRAY_SIZE (MAP##1)]; \
+ typedef char ATTRIBUTE_UNUSED \
+ static_assert2[(1 << (SIZE)) == ARRAY_SIZE (MAP##2)]; \
+ static const struct nanomips_reg_pair_operand op = { \
+ { OP_REG_PAIR, SIZE, LSB, 0, 0 }, OP_REG_##BANK, MAP##1, MAP##2 \
+ }; \
+ return &op.root; \
+ }
+
+#define PCREL(SIZE, LSB, IS_SIGNED, SHIFT, ALIGN_LOG2, INCLUDE_ISA_BIT, \
+ FLIP_ISA_BIT) \
+ { \
+ static const struct nanomips_pcrel_operand op = { \
+ { { OP_PCREL, SIZE, LSB, 0, 0 }, \
+ (1 << ((SIZE) - (IS_SIGNED))) - 1, 0, SHIFT, true }, \
+ ALIGN_LOG2, INCLUDE_ISA_BIT, FLIP_ISA_BIT \
+ }; \
+ return &op.root.root; \
+ }
+
+#define JUMP(SIZE, LSB, SHIFT) \
+ PCREL (SIZE, LSB, false, SHIFT, SIZE + SHIFT, true, false)
+
+#define JALX(SIZE, LSB, SHIFT) \
+ PCREL (SIZE, LSB, false, SHIFT, SIZE + SHIFT, true, true)
+
+#define BRANCH(SIZE, LSB, SHIFT) \
+ PCREL (SIZE, LSB, true, SHIFT, 0, true, false)
+
+#define SPECIAL(SIZE, LSB, TYPE) \
+ { \
+ static const struct nanomips_operand op = { OP_##TYPE, SIZE, LSB, 0, 0 }; \
+ return &op; \
+ }
+
+#define PREV_CHECK(SIZE, LSB, GT_OK, LT_OK, EQ_OK, ZERO_OK) \
+ { \
+ static const struct nanomips_check_prev_operand op = { \
+ { OP_CHECK_PREV, SIZE, LSB, 0, 0 }, GT_OK, LT_OK, EQ_OK, ZERO_OK \
+ }; \
+ return &op.root; \
+ }
+
+#define IMM_INT_BIAS(SIZE, LSB, MAX_VAL, BIAS, SHIFT, PRINT_HEX) \
+ { \
+ static const struct nanomips_int_operand op = { \
+ { OP_IMM_INT, SIZE, LSB, 0, 0 }, MAX_VAL, BIAS, SHIFT, PRINT_HEX \
+ }; \
+ return &op.root; \
+ }
+
+#define IMM_INT_ADJ(SIZE, LSB, MAX_VAL, SHIFT, PRINT_HEX) \
+ IMM_INT_BIAS(SIZE, LSB, MAX_VAL, 0, SHIFT, PRINT_HEX)
+
+#define UINT_SPLIT(SIZE, LSB, SHIFT, SIZE_TOP, LSB_TOP) \
+ { \
+ static const struct nanomips_int_operand op = { \
+ { OP_INT, SIZE, LSB, SIZE_TOP, LSB_TOP }, \
+ (1 << (SIZE)) - 1, 0, SHIFT, 0 \
+ }; \
+ return &op.root; \
+ }
+
+#define SINT_SPLIT(SIZE, LSB, SHIFT, SIZE_TOP, LSB_TOP, BIAS) \
+ { \
+ static const struct nanomips_int_operand op = { \
+ { OP_INT, SIZE, LSB, SIZE_TOP, LSB_TOP }, \
+ (1 << ((SIZE) -1)) - 1, BIAS, SHIFT, 0 \
+ }; \
+ return &op.root; \
+ }
+
+#define IMM_SINT_SPLIT(SIZE, LSB, SHIFT, SIZE_TOP, LSB_TOP, BIAS) \
+ { \
+ static const struct nanomips_int_operand op = { \
+ { OP_IMM_INT, SIZE, LSB, SIZE_TOP, LSB_TOP }, \
+ (1 << ((SIZE) -1)) - 1, BIAS, SHIFT, false \
+ }; \
+ return &op.root; \
+ }
+
+#define HINT_SPLIT(SIZE, LSB, SIZE_T, LSB_T) \
+ SINT_SPLIT(SIZE, LSB, 0, SIZE_T, LSB_T)
+
+#define SPLIT_MAPPED_REG_PAIR(SIZE, LSB, SIZE_T, LSB_T, BANK, MAP1, MAP2) \
+ { \
+ typedef char ATTRIBUTE_UNUSED \
+ static_assert1[(1 << (SIZE)) == ARRAY_SIZE (MAP1)]; \
+ typedef char ATTRIBUTE_UNUSED \
+ static_assert2[(1 << (SIZE)) == ARRAY_SIZE (MAP2)]; \
+ static const struct nanomips_reg_pair_operand op = { \
+ { OP_REG_PAIR, SIZE, LSB, SIZE_T, LSB_T }, OP_REG_##BANK, \
+ MAP1, MAP2 \
+ }; \
+ return &op.root; \
+ }
+
+#define BRANCH_UNORD_SPLIT(SIZE, SHIFT) \
+ { \
+ static const struct nanomips_pcrel_operand op = { \
+ { { OP_PCREL, SIZE, 1, 1, 0 }, \
+ (1 << ((SIZE) - 1)) - 1, 0, SHIFT, true }, \
+ 0, false, false \
+ }; \
+ return &op.root.root; \
+ }
+
+#define BRANCH_SPLIT(SIZE, LSB, SHIFT, SIZE_TOP, LSB_TOP) \
+ { \
+ static const struct nanomips_pcrel_operand op = { \
+ { { OP_PCREL, SIZE, 1, SIZE_TOP, LSB_TOP }, \
+ (1 << ((SIZE) - 1)) - 1, LSB, SHIFT, true }, \
+ 0, false, false \
+ }; \
+ return &op.root.root; \
+ }
+
+#define SPECIAL_SPLIT(SIZE, LSB, SIZE_T, LSB_T, TYPE) \
+ { \
+ static const struct nanomips_operand op = { OP_##TYPE, SIZE, LSB, SIZE_T, LSB_T }; \
+ return &op; \
+ }
+
+#define SPECIAL_WORD(BIAS, TYPE) \
+ { \
+ static const struct nanomips_int_operand op = { { OP_##TYPE, 0, 0, 0, 0 }, \
+ 0x7fffffff, BIAS, 0, false }; \
+ return &op.root; \
+ }
+
+#define MAPPED_PREV_CHECK(SIZE, LSB, BANK, MAP, GT_OK, LT_OK, EQ_OK, ZERO_OK) \
+ { \
+ typedef char ATTRIBUTE_UNUSED \
+ static_assert[(1 << (SIZE)) == ARRAY_SIZE (MAP)]; \
+ static const struct nanomips_mapped_check_prev_operand op = { \
+ { OP_MAPPED_CHECK_PREV, SIZE, LSB, 0, 0 }, OP_REG_##BANK, MAP, \
+ GT_OK, LT_OK, EQ_OK, ZERO_OK \
+ }; \
+ return &op.root; \
+ }
+
+#define BASE_OFFSET_CHECK(SIZE, LSB, CONST_OK, EXPR_OK) \
+ { \
+ static const struct nanomips_base_check_offset_operand op = { \
+ { OP_BASE_CHECK_OFFSET, SIZE, LSB, 0, 0 }, OP_REG_GP, \
+ CONST_OK, EXPR_OK \
+ }; \
+ return &op.root; \
+ }
diff --git a/opcodes/nanomips-opc.c b/opcodes/nanomips-opc.c
new file mode 100644
index 00000000000..aa82c5c021c
--- /dev/null
+++ b/opcodes/nanomips-opc.c
@@ -0,0 +1,1073 @@
+/* nanomips-opc.c. nanoMIPS opcode table.
+ Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+ Written by Faraz Shahbazker <faraz.shahbazker@mips.com>
+
+ This file is part of the GNU opcodes library.
+
+ This library 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.
+
+ It 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 this file; see the file COPYING. If not, write to the
+ Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "sysdep.h"
+#include "opcode/nanomips.h"
+#include "nanomips-formats.h"
+
+static unsigned char reg_0_map[] = { 0 };
+static unsigned char reg_28_map[] = { 28 };
+static unsigned char reg_29_map[] = { 29 };
+static unsigned char reg_31_map[] = { 31 };
+static unsigned char reg_m16_map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
+static unsigned char reg_q_map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
+
+static unsigned char reg_4to5_map[] = {
+ 8, 9, 10, 11, 4, 5, 6, 7,
+ 16, 17, 18, 19, 20, 21, 22, 23
+};
+
+static unsigned char reg_4to5_srcmap[] = {
+ 8, 9, 10, 0, 4, 5, 6, 7,
+ 16, 17, 18, 19, 20, 21, 22, 23
+};
+
+static unsigned char reg_4or5_map[] = { 4, 5 };
+
+static unsigned char reg_gpr2d_map1[] = { 4, 5, 6, 7 };
+static unsigned char reg_gpr2d_map2[] = { 5, 6, 7, 8 };
+
+static int int_b_map[] = {
+ 0, 4, 8, 12, 16, 20, 24, 28
+};
+
+static int int_c_map[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 255, 65535, 14, 15
+};
+
+static int word_byte_map[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0
+};
+
+static int int_mask_map[] = {
+ 0x1, 0x3, 0x7, 0xf,
+ 0x1f, 0x3f, 0x7f, 0xff,
+ 0x1ff, 0x3ff, 0x7ff, 0xfff,
+ 0x1fff, 0x3fff, 0x7fff, 0xffff,
+ 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff,
+ 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff,
+ 0x1ffffff,0x3ffffff,0x7ffffff,0xfffffff,
+ 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff
+};
+
+/* Return the nanomips_operand structure for the operand at the
+ beginning of P. */
+
+/* FIXME: Unused cases left commented in-place for quick reminder
+ of which character strings are unused. */
+const struct nanomips_operand *
+decode_nanomips_operand (const char *p)
+{
+ switch (p[0])
+ {
+ case 'm':
+ switch (p[1])
+ {
+ case 'a': MAPPED_REG (0, 0, GP, reg_28_map);
+ case 'b': SPECIAL (5, 5, NON_ZERO_REG);
+ case 'c': OPTIONAL_MAPPED_REG (3, 4, GP, reg_m16_map);
+ case 'd': MAPPED_REG (3, 7, GP, reg_m16_map);
+ case 'e': MAPPED_REG (3, 1, GP, reg_m16_map);
+ case 'f': MAPPED_PREV_CHECK (3, 7, GP, reg_m16_map, true, false, false, false);
+ case 'g': MAPPED_PREV_CHECK (3, 4, GP, reg_m16_map, false, true, false, false);
+ case 'h': MAPPED_PREV_CHECK (3, 7, GP, reg_m16_map, false, true, true, false);
+ case 'i': MAPPED_PREV_CHECK (3, 4, GP, reg_m16_map, true, false, true, false);
+ case 'j': REG (5, 0, GP);
+ case 'k': SPECIAL (0, 0, REPEAT_DEST_REG);
+ case 'l': MAPPED_REG (3, 4, GP, reg_m16_map);
+ case 'm': MAPPED_REG (3, 7, GP, reg_q_map);
+ case 'n': SPECIAL_SPLIT (5, 0, 1, 9, SAVE_RESTORE_LIST);
+ case 'p': REG (5, 5, GP);
+ case 'q': SPLIT_MAPPED_REG_PAIR (2, 8, 1, 3, GP, reg_gpr2d_map1,
+ reg_gpr2d_map2);
+ case 'r': SPLIT_MAPPED_REG_PAIR (2, 8, 1, 3, GP, reg_gpr2d_map2,
+ reg_gpr2d_map1);
+ case 's': MAPPED_REG (0, 0, GP, reg_29_map);
+ case 't': SPECIAL (0, 0, REPEAT_PREV_REG);
+ case 'u': SPLIT_MAPPED_REG (4, 5, 1, 9, GP, reg_4to5_map);
+ case 'v': SPLIT_MAPPED_REG (4, 0, 1, 4, GP, reg_4to5_map);
+ case 'w': SPLIT_MAPPED_REG (4, 5, 1, 9, GP, reg_4to5_srcmap);
+ case 'x': SPLIT_MAPPED_REG (4, 0, 1, 4, GP, reg_4to5_srcmap);
+ case 'y': MAPPED_REG (0, 0, GP, reg_31_map);
+ case 'z': UINT (0, 0); /* Literal 0 */
+ case 'A': INT_ADJ (7, 0, 127, 2, false); /* (0 .. 127) << 2 */
+ case 'B': MAPPED_INT (3, 0, int_b_map, false);
+ case 'C': MAPPED_INT (4, 0, int_c_map, true);
+ case 'D': BRANCH_UNORD_SPLIT (10, 1);
+ case 'E': BRANCH_UNORD_SPLIT (7, 1);
+ case 'F': SPECIAL (4, 0, NON_ZERO_PCREL_S1);
+ case 'G': INT_ADJ (4, 4, 15, 4, false);
+ case 'H': INT_ADJ (2, 1, 3, 1, false); /* (0 .. 3) << 1 */
+ case 'I': INT_ADJ (7, 0, 126, 0, false); /* (-1 .. 126) */
+ case 'J': INT_ADJ (4, 0, 15, 2, false); /* (0 .. 15) << 2 */
+ case 'K': HINT (3, 0);
+ case 'L': UINT (2, 0); /* (0 .. 3) */
+ case 'M': INT_ADJ (3, 0, 8, 0, false); /* (1 .. 8) */
+ case 'N': UINT_SPLIT (2, 8, 2, 1, 3); /* split encoded 2-bit offset << 2 */
+ case 'O': IMM_INT_ADJ (7, 0, 127, 2, false); /* (0 .. 127) << 2 */
+ case 'P': HINT (2, 0);
+ case 'Q': SINT_SPLIT (4, 0, 0, 1, 4, 0);
+ case 'R': INT_ADJ (5, 0, 31, 2, false); /* (0 .. 31) << 2 */
+ case 'S': INT_ADJ (6, 0, 63, 2, false); /* (0 .. 63) << 2 */
+ case 'Z': UINT (0, 0); /* 0 only */
+ }
+ break;
+
+ case '-':
+ switch (p[1])
+ {
+ case 'i': REG (0, 0, GP); /* Ignored register operand. */
+ case 'm': SPECIAL_SPLIT (5, 11, 5, 21, COPY_BITS);
+ case 'n': SPECIAL_SPLIT (5, 11, 5, 16, COPY_BITS);
+ case 'A': SPECIAL (5, 16, DONT_CARE);
+ case 'B': SPECIAL (1, 10, DONT_CARE);
+ case 'C': SPECIAL (12, 0, DONT_CARE);
+ case 'D': SPECIAL (1, 17, DONT_CARE);
+ case 'E': SPECIAL (3, 13, DONT_CARE);
+ case 'F': SPECIAL (10, 16, DONT_CARE);
+ case 'G': SPECIAL_SPLIT (8, 9, 5, 16, DONT_CARE);
+ case 'H': SPECIAL (9, 17, DONT_CARE);
+ case 'I': SPECIAL (5, 21, DONT_CARE);
+ case 'J': SPECIAL (3, 23, DONT_CARE);
+ case 'K': SPECIAL_SPLIT (2, 2, 1, 15, DONT_CARE);
+ case 'L': SPECIAL (3, 6, DONT_CARE);
+ case 'M': SPECIAL (3, 9, DONT_CARE);
+ case 'N': SPECIAL (6, 10, DONT_CARE);
+ case 'O': SPECIAL (1, 12, DONT_CARE);
+ case 'P': SPECIAL_SPLIT (8, 10, 4, 22, DONT_CARE);
+ case 'Q': SPECIAL (1, 11, DONT_CARE);
+ }
+ break;
+
+ case '+':
+ switch (p[1])
+ {
+ case 'A': BIT (5, 0, 0); /* (0 .. 31) */
+ case 'B': MSB (5, 6, 1, true, 32); /* (1 .. 32), 32-bit op */
+ case 'C': MSB (5, 6, 1, false, 32); /* (1 .. 32), 32-bit op */
+ case 'D': SPECIAL (4, 16, SAVE_RESTORE_FP_LIST);
+ case 'E': BIT (5, 0, 32); /* (32 .. 63) */
+ case 'F': MSB (5, 6, 33, true, 64); /* (33 .. 64), 64-bit op */
+ case 'G': MSB (5, 6, 33, false, 64); /* (33 .. 64), 64-bit op */
+ case 'H': MSB (5, 6, 1, false, 64); /* (1 .. 32), 64-bit op */
+ case 'I': BIT (5, 6, 0); /* (0 .. 31) */
+ case 'J': HINT (19, 0);
+ case 'K': SPECIAL_SPLIT (20, 2, 1, 0, HI20_PCREL); /* tri-part 20-bit */
+ case 'L': HINT (10, 16);
+ case 'M': HINT (18, 0);
+ case 'N': INT_ADJ (9, 3, 511, 3, false); /* 9-bit << 3 */
+ case 'O': SPECIAL_WORD (0, GPREL_WORD);
+ case 'P': SPECIAL_WORD (6, IMM_WORD);
+ case 'Q': SPECIAL_WORD (0, UINT_WORD);
+ case 'R': SPECIAL_WORD (0, INT_WORD);
+ case 'S': SPECIAL_WORD (0, PC_WORD);
+
+ case 'i': HINT (5, 16);
+ case 'j': SINT_SPLIT (9, 0, 0, 1, 15, 0);
+ case 'p': SINT_SPLIT (7, 2, 2, 1, 15, 0); /* split 7-bit signed << 2 */
+ case 'q': SINT_SPLIT (6, 3, 3, 1, 15, 0); /* split 6-bit signed << 3 */
+ case 'r': BRANCH_UNORD_SPLIT (21, 1); /* split 21-bit signed << 1 */
+ case 's': IMM_SINT_SPLIT (21, 1, 1, 1, 0, 2); /* split (21-bit signed + 2) << 1 */
+ case 't': SPECIAL (5, 21, NON_ZERO_REG);
+ case 'u': BRANCH_UNORD_SPLIT (25, 1);
+ case 'v': MAPPED_INT (5, 6, word_byte_map, false);
+ case 'w': BIT (2, 9, 0); /* (0 .. 3) */
+
+ case '*': INT_ADJ (4, 7, 15, 1, false); /* (0 .. 15) << 1 */
+ case '|': UINT (1, 6); /* 0/1 */
+ case ';': UINT (2, 21); /* (0 .. 3) */
+ case '1': UINT (18, 0);
+ case '2': INT_ADJ (16, 2, (1<<16) - 1, 2, false);
+ case '3': INT_ADJ (17, 1, (1<<17) - 1, 1, false);
+ case '4': INT_ADJ (18, 3, (1<<18)-1, 3, false); /* 18-bit << 3 */
+ case '5': SPLIT_MAPPED_REG (4, 21, 1, 25, GP, reg_4to5_srcmap);
+ case '6': MAPPED_INT (5, 6, int_mask_map, true);
+ case '7': MAPPED_REG (1, 24, GP, reg_4or5_map);
+ case '8': HINT (23, 3);
+ case '9': UINT (7, 11);
+ }
+ break;
+
+ case '.': INT_ADJ (19, 2, (1<<19) - 1, 2, false);
+ case '<': BIT (5, 0, 0); /* (0 .. 31) */
+/* case '>': BIT (5, 11, 32); /\* (32 .. 63) *\/ */
+ case '\\': BIT (3, 21, 0); /* (0 .. 7) */
+ case '|': INT_ADJ (3, 12, 8, 0, false); /* 1 .. 8 */
+ case '~': BRANCH_UNORD_SPLIT (11, 1); /* split 11-bit signed << 1 */
+ case '@': SINT (10, 11);
+ case '^': HINT (5, 11);
+ case '!': UINT (1, 10);
+ case '$': UINT (1, 3);
+ case '*': REG (2, 18, ACC);
+/* case '&': REG (2, 23, ACC); */
+
+ case '0': SINT (6, 16);
+ case '1': BIT (5, 11, 0); /* (0 .. 31) */
+ case '2': BIT (5, 16, 0); /* (0 .. 31) */
+ case '3': BIT (3, 13, 0);
+ case '4': BIT (4, 12, 0);
+ case '5': HINT (8, 13);
+ case '7': REG (2, 14, ACC);
+ case '8': HINT (7, 14);
+
+ case 'C': HINT (23, 3);
+ case 'D': REG (5, 11, FP);
+ case 'E': REG (5, 21, COPRO);
+ case 'G': REG (5, 16, COPRO);
+ case 'H': UINT (5, 11);
+ case 'J': SPECIAL (5, 11, CP0SEL);
+ case 'K': REG (10, 11, HW);
+/* case 'M': REG (3, 13, CCC); */
+/* case 'N': REG (3, 18, CCC); */
+ case 'O': REG (10, 11, CP0);
+ case 'P': REG (5, 16, CP0SEL);
+/* case 'Q': UINT (5, 11); */
+ case 'R': REG (5, 11, FP);
+ case 'S': REG (5, 16, FP);
+ case 'T': REG (5, 21, FP);
+ case 'U': REG (5, 16, HWRSEL);
+ case 'V': OPTIONAL_REG (5, 16, FP);
+
+/* case 'a': JUMP (26, 0, 1); */
+ case 'b': REG (5, 16, GP);
+ case 'c': BASE_OFFSET_CHECK (5, 16, true, false);
+ case 'd': REG (5, 11, GP);
+ case 'e': REG (5, 3, GP);
+ case 'g': HINT (12, 0);
+ case 'h': SPECIAL (12, 0, NEG_INT);
+ case 'i': UINT (12, 0);
+ case 'j': UINT (16, 0);
+ case 'k': HINT (5, 21);
+ case 'n': SPECIAL_SPLIT (11, 2, 10, 16, SAVE_RESTORE_LIST);
+ case 'o': UINT (12, 0);
+ case 'p': BRANCH_UNORD_SPLIT (14, 1);
+/* case 'q': BRANCH_UNORD_SPLIT (20, 1); - unused */
+ case 'r': OPTIONAL_REG (5, 16, GP);
+ case 's': REG (5, 16, GP);
+ case 't': REG (5, 21, GP);
+ case 'u': SPECIAL_SPLIT (20, 2, 1, 0, HI20_INT); /* tri-part 20-bit */
+ case 'v': OPTIONAL_REG (5, 16, GP);
+ case 'w': OPTIONAL_REG (5, 21, GP);
+ case 'x': SPECIAL_SPLIT (20, 2, 1, 0, HI20_SCALE); /* tri-part 20-bit */
+ case 'z': MAPPED_REG (0, 0, GP, reg_0_map);
+ }
+ return 0;
+}
+
+#define LM INSN_LOAD_MEMORY
+#define SM INSN_STORE_MEMORY
+
+#define WR_1 INSN_WRITE_1
+#define WR_2 INSN_WRITE_2
+#define RD_1 INSN_READ_1
+#define RD_2 INSN_READ_2
+#define RD_3 INSN_READ_3
+#define MOD_1 (WR_1|RD_1)
+#define MOD_2 (WR_2|RD_2)
+#define FP_S INSN_FP_S
+#define FP_D INSN_FP_D
+
+ /* Write dsp accumulators */
+#define WR_a INSN_WRITE_ACC
+ /* Read dsp accumulators */
+#define RD_a INSN_READ_ACC
+
+/* Flags used in pinfo2. */
+#define CTC INSN2_CONVERTED_TO_COMPACT
+#define UBR INSN2_UNCOND_BRANCH
+#define CBR INSN2_COND_BRANCH
+#define ALIAS INSN2_ALIAS
+
+/* For 32-bit nanoMIPS instructions. */
+#define WR_31 INSN_WRITE_GPR_31
+
+/* nanoMIPS DSP ASE support. */
+#define D32 ASE_DSP
+
+/* nanoMIPS MT ASE support. */
+#define MT32 ASE_MT
+
+/* nanoMIPS MCU (MicroController) ASE support. */
+#define MC ASE_MCU
+
+/* nanoMIPS Enhanced VA Scheme. */
+#define EVA ASE_EVA
+
+/* MSA support. */
+#define MSA ASE_MSA
+#define MSA64 ASE_MSA64
+
+/* eXtended Physical Address (XPA) support. */
+#define XPA ASE_XPA
+
+/* Global INValidate extension. */
+#define GINV ASE_GINV
+
+/* Cyclic redundancy check instruction (CRC) support. */
+#define CRC ASE_CRC
+
+/* nanoMIPS instruction subset. */
+#define xNMS ASE_xNMS
+/* TLB manipulations. */
+#define TLB ASE_TLB
+
+/* Base ISA for nanoMIPS. */
+#define I38 INSN_ISAN32R6
+#define I70 INSN_ISAN64R6
+
+const struct nanomips_opcode nanomips_opcodes[] = {
+/* These instructions appear first so that the disassembler will find
+ them first. The assemblers uses a hash table based on the
+ instruction name anyhow. */
+/* name, suffix, args, match, mask, pinfo pinfo2, membership, ase */
+/* Pure macros */
+{"la", "", "t,A(b)", 0, (int) M_LA_AB, INSN_MACRO, 0, I38, 0},
+{"dla", "", "t,A(b)", 0, (int) M_DLA_AB, INSN_MACRO, 0, I38, 0},
+/* Precedence=1 */
+{"aluipc", "", "t,+K", 0xe0000002, 0xfc000002, WR_1, 0, I38, 0}, /* ALUIPC */
+{"break", "[16]", "", 0x1010, 0xffff, 0, INSN2_ALIAS, I38, 0},
+{"break", "[16]", "mK", 0x1010, 0xfff8, 0, 0, I38, 0},
+{"break", "[32]", "", 0x00100000, 0xffffffff, 0, INSN2_ALIAS, I38, 0},
+{"break", "[32]", "+J", 0x00100000, 0xfff80000, 0, 0, I38, 0},
+{"dvp", "", "-A", 0x20000390, 0xffe0ffff, 0, INSN2_ALIAS, I38, 0}, /* DVP */
+{"dvp", "", "t,-A", 0x20000390, 0xfc00ffff, WR_1, 0, I38, 0},
+{"nop", "[16]", "", 0x9008, 0xffff, 0, 0, I38, 0}, /* NOP[16] */
+{"nop", "[32]", "", 0x8000c000, 0xffffffff, 0, 0, I38, 0}, /* NOP */
+{"sdbbp", "[16]", "", 0x1018, 0xffff, 0, INSN2_ALIAS, I38, 0},
+{"sdbbp", "[16]", "mK", 0x1018, 0xfff8, 0, 0, I38, 0},
+{"sdbbp", "[32]", "", 0x00180000, 0xffffffff, 0, INSN2_ALIAS, I38, 0},
+{"sdbbp", "[32]", "+J", 0x00180000, 0xfff80000, 0, 0, I38, 0},
+{"move", "", "mb,mj", 0x1000, 0xfc00, WR_1|RD_2, 0, I38, 0}, /* preceded by BREAK, SDBBP */
+{"move", "", "d,s", 0x20000290, 0xffe007ff, WR_1|RD_2, INSN2_ALIAS, I38, 0}, /* OR */
+{"move", "", "d,s", 0x20000150, 0xffe007ff, WR_1|RD_2, INSN2_ALIAS, I38, 0}, /* ADDU */
+{"sigrie", "", "+J", 0x00000000, 0xfff80000, 0, 0, I38, 0},
+{"synci", "[u12]", "o(b)", 0x87e03000, 0xffe0f000, RD_2, 0, I38, 0}, /* SYNCI[U12] */
+{"synci", "[s9]", "+j(b)", 0xa7e01800, 0xffe07f00, RD_2, 0, I38, 0}, /* SYNCI[S9] */
+{"syncie", "", "+j(b)", 0xa7e01a00, 0xffe07f00, RD_2, 0, 0, EVA},
+{"jrc", "[16]", "mp", 0xd800, 0xfc1f, RD_1, 0, I38, 0}, /* JRC[16] */
+{"jrc", "[32]", "s", 0x48000000, 0xffe0ffff, RD_1, INSN2_ALIAS, I38, 0}, /* JALRC */
+{"jalrc", "[16]", "mp", 0xd810, 0xfc1f, WR_31|RD_1, 0, I38, 0}, /* JALRC[16] */
+{"jalrc", "[16]", "my,mp", 0xd810, 0xfc1f, WR_31|RD_1, INSN2_ALIAS, I38, 0}, /* JALRC[16] */
+{"jalrc", "[32]", "s", 0x4be00000, 0xffe0ffff, RD_1, INSN2_ALIAS, I38, 0}, /* JALRC[32] */
+{"jalrc", "[32]", "t,s,-C", 0x48000000, 0xfc00f000, WR_1|RD_2, 0, I38, 0},
+{"jalrc", "", "mp,-i", 0xd810, 0xfc1f, WR_31|RD_1, INSN2_ALIAS, I38, 0}, /* JALRC[16] */
+{"jalrc", "", "s,-i", 0x4be00000, 0xffe0ffff, RD_1, INSN2_ALIAS, I38, 0}, /* JALRC[32] */
+{"jr", "", "mp", 0xd800, 0xfc1f, RD_1, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JRC */
+{"jr", "", "s", 0x48000000, 0xffe0ffff, RD_1, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC */
+{"jalr", "", "my,mp", 0xd810, 0xfc1f, WR_31|RD_1, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC[16] */
+{"jalr", "", "mp", 0xd810, 0xfc1f, WR_31|RD_1, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC[16] */
+{"jalr", "", "s", 0x4be00000, 0xffe0ffff, RD_1, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC */
+{"jalr", "", "t,s", 0x48000000, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC */
+{"lui", "", "t,u", 0xe0000000, 0xfc000002, WR_1, 0, I38, 0},
+{"li", "[16]", "md,mI", 0xd000, 0xfc00, WR_1, 0, I38, 0}, /* LI[16] */
+{"li", "", "mb,mZ", 0x1000, 0xfc1f, WR_1, INSN2_ALIAS, I38, 0}, /* MOVE[16] */
+{"li", "[32]", "+t,j", 0x00000000, 0xfc1f0000, WR_1, INSN2_ALIAS, I38, 0}, /* ADDIU[32] */
+{"li", "[neg]", "t,h", 0x80008000, 0xfc1ff000, WR_1, INSN2_ALIAS, I38, 0}, /* ADDIU[NEG] */
+{"li", "", "t,x", 0xe0000000, 0xfc000002, WR_1, INSN2_ALIAS, I38, 0}, /* LUI */
+{"li", "[48]", "mp,+Q", 0x6000, 0xfc1f, WR_1, 0, 0, xNMS}, /* LI[48] */
+{"li", "", "+t,A", 0, (int) M_LI, INSN_MACRO, INSN2_MACRO, I38, 0},
+{"ext", "", "t,r,+A,+C", 0x8000f000, 0xfc00f820, WR_1|RD_2, 0, 0, xNMS},
+{"ext", "", "t,r,+A,+C", 0, (int) M_EXT, INSN_MACRO, 0, I38, 0},
+
+/* Precedence=0 */
+{"abs", "", "d,v", 0, (int) M_ABS, INSN_MACRO, 0, I38, 0},
+{"absq_s.ph", "", "t,s", 0x2000113f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32},
+{"absq_s.qb", "", "t,s", 0x2000013f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32},
+{"absq_s.w", "", "t,s", 0x2000213f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32},
+{"add", "", "d,v,t,-B", 0x20000110, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, xNMS},
+{"add", "", "t,r,I", 0, (int) M_ADD_I, INSN_MACRO, 0, 0, xNMS},
+{"addi", "", "t,r,I", 0, (int) M_ADD_I, INSN_MACRO, 0, 0, xNMS},
+{"addiu", "[r1.sp]", "md,ms,mS", 0x7040, 0xfc40, WR_1|RD_2, 0, I38, 0}, /* ADDIU[R1.SP] */
+{"addiu", "[r2]", "md,mc,mB", 0x9000, 0xfc08, WR_1|RD_2, 0, I38, 0}, /* ADDIU[R2] */
+{"addiu", "[rs5]", "mp,mk,mQ", 0x9008, 0xfc08, MOD_1, INSN2_ALIAS, I38, 0}, /* ADDIU[RS5] */
+{"addiu", "[rs5]", "mp,mQ", 0x9008, 0xfc08, MOD_1, 0, I38, 0}, /* ADDIU[RS5], preceded by NOP[16] */
+{"addiu", "[gp.b]", "t,ma,+1", 0x440c0000, 0xfc1c0000, WR_1|RD_2, 0, I38, 0}, /* ADDIU[GP.B] */
+{"addiu", "[gp.w]", "t,ma,.", 0x40000000, 0xfc000003, WR_1|RD_2, 0, I38, 0}, /* ADDIU[GP.W] */
+{"addiu", "[32]", "+t,r,j", 0x00000000, 0xfc000000, WR_1|RD_2, 0, I38, 0}, /* preceded by SIGRIE */
+{"addiu", "[neg]", "t,r,h", 0x80008000, 0xfc00f000, WR_1|RD_2, 0, I38, 0}, /* ADDIU[NEG] */
+{"addiu", "[48]", "mp,mt,+R", 0x6001, 0xfc1f, MOD_1, 0, 0, xNMS}, /* ADDIU[48] */
+{"addiu", "[gp48]", "mp,ma,+O", 0x6002, 0xfc1f, WR_1|RD_2, 0, 0, xNMS}, /* ADDIU[GP48] */
+{"lapc", "[32]", "t,+r", 0x04000000, 0xfc000000, WR_1, INSN2_ALIAS, I38, 0}, /* ADDIUPC */
+{"lapc", "[48]", "mp,+S", 0x6003, 0xfc1f, WR_1, INSN2_ALIAS, 0, xNMS}, /* ADDIUPC[48] */
+{"lapc.h", "", "t,+r", 0x04000000, 0xfc000000, WR_1, INSN2_ALIAS, I38, 0}, /* ADDIUPC */
+{"lapc.b", "", "mp,+S", 0x6003, 0xfc1f, WR_1, INSN2_ALIAS, 0, xNMS}, /* ADDIUPC[48] */
+{"addiupc", "[32]", "t,+s", 0x04000000, 0xfc000000, WR_1, 0, I38, 0},
+{"addiupc", "[48]", "mp,+P", 0x6003, 0xfc1f, WR_1, 0, 0, xNMS}, /* ADDIUPC[48] */
+{"addiu.b", "", "t,ma,+1", 0x440c0000, 0xfc1c0000, WR_1|RD_2, INSN2_ALIAS, I38, 0}, /* ADDIU[GP.B] */
+{"addiu.w", "", "t,ma,.", 0x40000000, 0xfc000003, WR_1|RD_2, INSN2_ALIAS, I38, 0}, /* ADDIU[GP.W] */
+{"addiu.b32", "", "mp,ma,+O", 0x6002, 0xfc1f, WR_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* ADDIU[GP48] */
+{"addq.ph", "", "d,s,t", 0x2000000d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"addqh.ph", "", "d,s,t", 0x2000004d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"addqh.w", "", "d,s,t", 0x2000008d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"addqh_r.ph", "", "d,s,t", 0x2000044d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"addqh_r.w", "", "d,s,t", 0x2000048d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"addq_s.ph", "", "d,s,t", 0x2000040d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"addq_s.w", "", "d,s,t,-B", 0x20000305, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"addsc", "", "d,s,t,-B", 0x20000385, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"addu", "[16]", "me,mc,md", 0xb000, 0xfc01, WR_1|RD_2|RD_3, 0, I38, 0}, /* ADDU[16] */
+{"addu", "[4x4]", "mu,mt,mv", 0x3c00, 0xfd08, MOD_1|RD_3, 0, 0, xNMS}, /* ADDU[4X4] */
+{"addu", "[4x4]", "mu,mv,mk", 0x3c00, 0xfd08, MOD_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* ADDU[4X4] */
+{"addu", "[32]", "d,v,t,-B", 0x20000150, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"addu", "", "t,r,I", 0, (int) M_ADDU_I, INSN_MACRO, 0, I38, 0},
+{"addu.ph", "", "d,s,t", 0x2000010d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"addu.qb", "", "d,s,t", 0x200000cd, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"adduh.qb", "", "d,s,t", 0x2000014d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"adduh_r.qb", "", "d,s,t", 0x2000054d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"addu_s.ph", "", "d,s,t", 0x2000050d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"addu_s.qb", "", "d,s,t", 0x200004cd, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"addwc", "", "d,s,t,-B", 0x200003c5, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"extw", "", "d,s,t,+I", 0x2000001f, 0xfc00003f, WR_1|RD_2|RD_3, 0, I38, 0},
+{"align", "", "mb,-i,mj,mz", 0x1000, 0xfc00, WR_1|RD_3, INSN2_ALIAS, I38, 0}, /* MOVE[16] */
+{"align", "", "d,-i,s,mz", 0x20000290, 0xffe007ff, WR_1|RD_3, INSN2_ALIAS, I38, 0}, /* MOVE[32] */
+{"align", "", "d,s,t,+v", 0x2000001f, 0xfc00003f, WR_1|RD_2|RD_3, INSN2_ALIAS, I38, 0}, /* EXTW */
+{"and", "[16]", "md,mk,ml", 0x5008, 0xfc0f, MOD_1|RD_3, INSN2_ALIAS, I38, 0}, /* AND[16] */
+{"and", "[16]", "md,ml,mk", 0x5008, 0xfc0f, MOD_1|RD_2, INSN2_ALIAS, I38, 0}, /* AND[16] */
+{"and", "[16]", "md,ml", 0x5008, 0xfc0f, MOD_1|RD_2, 0, I38, 0}, /* AND[16] */
+{"and", "[32]", "d,v,t,-B", 0x20000250, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"and", "[32]", "t,r,I", 0, (int) M_AND_I, INSN_MACRO, 0, I38, 0},
+{"andi", "[16]", "md,mc,mC", 0xf000, 0xfc00, WR_1|RD_2, 0, I38, 0}, /* ANDI[16] */
+{"andi", "[32]", "t,r,g", 0x80002000, 0xfc00f000, WR_1|RD_2, 0, I38, 0},
+{"andi", "", "t,r,+6", 0x8000f000, 0xfc00f83f, WR_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* EXT */
+{"append", "", "t,s,1", 0x20000215, 0xfc0007ff, WR_1|RD_2, 0, 0, D32},
+{"balc", "[16]", "mD", 0x3800, 0xfc00, WR_31, 0, I38, 0}, /* BALC[16] */
+{"balc", "[32]", "+u", 0x2a000000, 0xfe000000, WR_31, 0, I38, 0},
+{"bal", "", "mD", 0x3800, 0xfc00, WR_31, INSN2_ALIAS|UBR|CTC, I38, 0}, /* BALC[16] */
+{"bal", "", "+u", 0x2a000000, 0xfe000000, WR_31, INSN2_ALIAS|UBR|CTC, I38, 0}, /* BALC */
+{"balign", "", "d,-m,s,+v", 0x2000001f, 0xfc00003f, WR_1|RD_3, INSN2_ALIAS, 0, D32}, /* EXTW */
+{"balrsc", "", "+t,s,-C", 0x48008000, 0xfc00f000, WR_1|RD_2, 0, I38, 0},
+{"balrsc", "", "s", 0x4be08000, 0xffe0ffff, RD_1|WR_31, INSN2_ALIAS, I38, 0}, /* BALRSC */
+{"bbeqzc", "", "t,1,~,-D", 0xc8040000, 0xfc1d0000, RD_1, 0, 0, xNMS},
+{"bbnezc", "", "t,1,~,-D", 0xc8140000, 0xfc1d0000, RD_1, 0, 0, xNMS},
+{"bc", "[16]", "mD", 0x1800, 0xfc00, 0, 0, I38, 0}, /* BC[16] */
+{"bc", "[32]", "+u", 0x28000000, 0xfe000000, 0, 0, I38, 0},
+{"b", "", "mD", 0x1800, 0xfc00, 0, INSN2_ALIAS|UBR|CTC, I38, 0}, /* BC[16] */
+{"b", "", "+u", 0x28000000, 0xfe000000, 0, INSN2_ALIAS|UBR|CTC, I38, 0}, /* BC */
+{"beqzc", "[16]", "md,mE", 0x9800, 0xfc00, RD_1, 0, I38, 0}, /* BEQZC[16] */
+{"beqzc", "[32]", "t,p", 0x88000000, 0xfc1fc000, RD_1, INSN2_ALIAS, I38, 0}, /* BEQC */
+{"beqzc", "[32]", "s,p", 0x88000000, 0xffe0c000, RD_1, INSN2_ALIAS, I38, 0}, /* BEQC */
+{"beqz", "", "md,mE", 0x9800, 0xfc00, RD_1, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BEQZC[16] */
+{"beqz", "", "t,p", 0x88000000, 0xfc1fc000, RD_1, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BEQC */
+{"beqz", "", "s,p", 0x88000000, 0xffe0c000, RD_1, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BEQC */
+{"beqc", "[16]", "md,z,mE", 0x9800, 0xfc00, RD_1, INSN2_ALIAS, I38, 0}, /* BEQZC[16] */
+{"beqc", "[16]", "z,md,mE", 0x9800, 0xfc00, RD_1, INSN2_ALIAS, I38, 0}, /* BEQZC[16] */
+{"beqc", "[16]", "ml,mf,mF", 0xd800, 0xfc00, RD_1|RD_2, 0, 0, xNMS}, /* BEQC[16], with rs3<rt3 && u[4:1]!=0 */
+{"beqc", "[16]", "md,mg,mF", 0xd800, 0xfc00, RD_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* BEQC[16], with operands commutated */
+{"beqc", "[32]", "s,t,p", 0x88000000, 0xfc00c000, RD_1|RD_2, 0, I38, 0},
+{"beq", "", "md,z,mE", 0x9800, 0xfc00, RD_1, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BEQZC[16] */
+{"beq", "", "z,md,mE", 0x9800, 0xfc00, RD_1, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BEQZC[16] */
+{"beq", "", "ml,mf,mF", 0xd800, 0xfc00, RD_1|RD_2, INSN2_ALIAS|CBR|CTC, 0, xNMS}, /* BEQC[16], with rs3<rt3 && u[4:1]!=0 */
+{"beq", "", "md,mg,mF", 0xd800, 0xfc00, RD_1|RD_2, INSN2_ALIAS|CBR|CTC, 0, xNMS}, /* BEQC[16], with operands commutated */
+{"beq", "", "s,t,p", 0x88000000, 0xfc00c000, RD_1|RD_2, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BEQC */
+{"beq", "", "s,I,p", 0, (int) M_BEQ_I, INSN_MACRO, 0, I38, 0},
+{"beqic", "", "t,+9,~", 0xc8000000, 0xfc1c0000, RD_1, 0, I38, 0},
+{"blezc", "", "t,p", 0x88008000, 0xfc1fc000, RD_1, INSN2_ALIAS, I38, 0}, /* BGEC $0, t */
+{"blez", "", "t,p", 0x88008000, 0xfc1fc000, RD_1, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BGEC $0, t */
+{"bgezc", "", "s,p", 0x88008000, 0xffe0c000, RD_1, INSN2_ALIAS, I38, 0}, /* BGEC s, $0 */
+{"bgez", "", "s,p", 0x88008000, 0xffe0c000, RD_1, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BGEC s, $0 */
+{"bgec", "", "s,t,p", 0x88008000, 0xfc00c000, RD_1|RD_2, 0, I38, 0},
+{"bge", "", "s,t,p", 0x88008000, 0xfc00c000, RD_1|RD_2, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BGEC */
+{"bge", "", "s,I,p", 0, (int) M_BGE_I, INSN_MACRO, 0, I38, 0},
+{"bgt", "", "s,t,p", 0, (int) M_BGT, INSN_MACRO, 0, I38, 0},
+{"bgt", "", "s,I,p", 0, (int) M_BGT_I, INSN_MACRO, 0, I38, 0},
+{"bgtu", "", "s,t,p", 0, (int) M_BGTU, INSN_MACRO, 0, I38, 0},
+{"bgtu", "", "s,I,p", 0, (int) M_BGTU_I, INSN_MACRO, 0, I38, 0},
+{"ble", "", "s,t,p", 0, (int) M_BLE, INSN_MACRO, 0, I38, 0},
+{"ble", "", "s,I,p", 0, (int) M_BLE_I, INSN_MACRO, 0, I38, 0},
+{"bleu", "", "s,t,p", 0, (int) M_BLEU, INSN_MACRO, 0, I38, 0},
+{"bleu", "", "s,I,p", 0, (int) M_BLEU_I, INSN_MACRO, 0, I38, 0},
+{"bgezal", "", "s,p", 0, (int) M_BGEZAL, INSN_MACRO, 0, I38, 0},
+{"bgeic", "", "t,+9,~", 0xc8080000, 0xfc1c0000, RD_1, 0, I38, 0},
+{"bgeuc", "", "s,t,p", 0x8800c000, 0xfc00c000, RD_1|RD_2, 0, I38, 0},
+{"bgeu", "", "s,t,p", 0x8800c000, 0xfc00c000, RD_1|RD_2, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BGEUC */
+{"bgeu", "", "s,I,p", 0, (int) M_BGEU_I, INSN_MACRO, 0, I38, 0},
+{"bgeiuc", "", "t,+9,~", 0xc80c0000, 0xfc1c0000, RD_1, 0, I38, 0},
+{"bitrev", "", "t,r", 0x2000313f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32}, /* ROTX t,s,7,8,1 */
+{"bitrevb", "", "t,r", 0x8000d247, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* ROTX t,s,7,8,1 */
+{"bitrevh", "", "t,r", 0x8000d40f, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* ROTX t,s,15,16 */
+{"bitrevw", "", "t,r", 0x8000d01f, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* ROTX t,s,31,0*/
+{"bitswap", "", "t,r", 0x8000d247, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* ROTX t,s,7,8,1*/
+{"bgtzc", "", "t,p", 0xa8008000, 0xfc1fc000, RD_1, INSN2_ALIAS, I38, 0}, /* BLTC $0, t */
+{"bgtz", "", "t,p", 0xa8008000, 0xfc1fc000, RD_1, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BLTC $0, t */
+{"bltzc", "", "s,p", 0xa8008000, 0xffe0c000, RD_1, INSN2_ALIAS, I38, 0}, /* BLTC s, $0 */
+{"bltz", "", "s,p", 0xa8008000, 0xffe0c000, RD_1, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BLTC s, $0 */
+{"bltc", "", "s,t,p", 0xa8008000, 0xfc00c000, RD_1|RD_2, 0, I38, 0},
+{"blt", "", "s,t,p", 0xa8008000, 0xfc00c000, RD_1|RD_2, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BLTC */
+{"blt", "", "s,I,p", 0, (int) M_BLT_I, INSN_MACRO, 0, I38, 0},
+{"bltzal", "", "s,p", 0, (int) M_BLTZAL, INSN_MACRO, 0, I38, 0},
+{"bltic", "", "t,+9,~", 0xc8180000, 0xfc1c0000, RD_1, 0, I38, 0},
+{"bltuc", "", "s,t,p", 0xa800c000, 0xfc00c000, RD_1|RD_2, 0, I38, 0},
+{"bltu", "", "s,t,p", 0xa800c000, 0xfc00c000, RD_1|RD_2, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BLTUC */
+{"bltu", "", "s,I,p", 0, (int) M_BLTU_I, INSN_MACRO, 0, I38, 0},
+{"bltiuc", "", "t,+9,~", 0xc81c0000, 0xfc1c0000, RD_1, 0, I38, 0},
+{"bnezc", "[16]", "md,mE", 0xb800, 0xfc00, RD_1, 0, I38, 0}, /* BNEZC[16] */
+{"bnezc", "[32]", "t,p", 0xa8000000, 0xfc1fc000, RD_1, INSN2_ALIAS, I38, 0}, /* BNEC */
+{"bnezc", "[32]", "s,p", 0xa8000000, 0xffe0c000, RD_1, INSN2_ALIAS, I38, 0}, /* BNEC */
+{"bnez", "", "md,mE", 0xb800, 0xfc00, RD_1, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BNEZC[16] */
+{"bnez", "", "t,p", 0xa8000000, 0xfc1fc000, RD_1, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BNEC */
+{"bnez", "", "s,p", 0xa8000000, 0xffe0c000, RD_1, INSN2_ALIAS, I38, 0}, /* BNEC */
+{"bnec", "[16]", "md,z,mE", 0xb800, 0xfc00, RD_1, INSN2_ALIAS, I38, 0}, /* BNEZC[16] */
+{"bnec", "[16]", "z,md,mE", 0xb800, 0xfc00, RD_2, INSN2_ALIAS, I38, 0}, /* BNEZC[16] */
+{"bnec", "[16]", "ml,mh,mF", 0xd800, 0xfc00, RD_1|RD_2, 0, 0, xNMS}, /* BNEC[16], with rs3>=rt3 && u[4:1]!=0 */
+{"bnec", "[16]", "md,mi,mF", 0xd800, 0xfc00, RD_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* BNEC[16], with operands commutated */
+{"bnec", "[32]", "s,t,p", 0xa8000000, 0xfc00c000, RD_1|RD_2, 0, I38, 0},
+{"bne", "", "md,z,mE", 0xb800, 0xfc00, RD_1, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BNEZC[16] */
+{"bne", "", "z,md,mE", 0xb800, 0xfc00, RD_2, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BNEZC[16] */
+{"bne", "", "ml,mh,mF", 0xd800, 0xfc00, RD_1|RD_2, INSN2_ALIAS|CBR|CTC, 0, xNMS}, /* BNEC[16], with rs3>=rt3 && u[4:1]!=0 */
+{"bne", "", "md,mi,mF", 0xd800, 0xfc00, RD_1|RD_2, INSN2_ALIAS|CBR|CTC, 0, xNMS}, /* BNEC[16], with operands commutated */
+{"bne", "", "s,t,p", 0xa8000000, 0xfc00c000, RD_1|RD_2, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BNEC */
+{"bne", "", "s,I,p", 0, (int) M_BNE_I, INSN_MACRO, 0, I38, 0},
+{"bneic", "", "t,+9,~", 0xc8100000, 0xfc1c0000, RD_1, 0, I38, 0},
+{"bposge32c", "", "p,-I", 0x88044000, 0xfc1fc000, 0, 0, 0, D32},
+{"bposge32", "", "p", 0x88044000, 0xffffc000, 0, INSN2_ALIAS|CBR|CTC, 0, D32}, /* BPOSGE32C */
+{"brsc", "", "s,-C", 0x48008000, 0xffe0f000, RD_1, 0, I38, 0},
+{"byterevh", "", "t,r", 0x8000d608, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* ROTX t,s,8,24 */
+{"byterevw", "", "t,r", 0x8000d218, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* ROTX t,s,24,8 */
+{"cache", "", "k,+j(b)", 0xa4003900, 0xfc007f00, RD_3, 0, I38, 0},
+{"cache", "", "k,A(c)", 0, (int) M_CACHE_AC, INSN_MACRO, 0, I38, 0},
+{"cachee", "", "k,+j(b)", 0xa4003a00, 0xfc007f00, RD_3, 0, 0, EVA},
+{"cachee", "", "k,A(c)", 0, (int) M_CACHEE_AC, INSN_MACRO, 0, 0, EVA},
+{"cfc1", "", "t,G", 0xa000103b, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS, I38, 0},
+{"cfc1", "", "t,S", 0xa000103b, 0xfc00ffff, WR_1|RD_2, 0, I38, 0},
+{"cftc1", "", "t,G", 0x20001e30, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS, 0, MT32}, /* MFTR */
+{"cftc1", "", "t,S", 0x20001e30, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS, 0, MT32}, /* MFTR */
+{"cftc2", "", "t,G", 0x20002e30, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS, 0, MT32}, /* MFTR */
+{"clo", "", "t,s", 0x20004b3f, 0xfc00ffff, WR_1|RD_2, 0, 0, xNMS},
+{"clz", "", "t,s", 0x20005b3f, 0xfc00ffff, WR_1|RD_2, 0, 0, xNMS},
+{"cmp.eq.ph", "", "s,t,-N", 0x20000005, 0xfc0003ff, WR_1|RD_2, 0, 0, D32},
+{"cmp.le.ph", "", "s,t,-N", 0x20000085, 0xfc0003ff, WR_1|RD_2, 0, 0, D32},
+{"cmp.lt.ph", "", "s,t,-N", 0x20000045, 0xfc0003ff, WR_1|RD_2, 0, 0, D32},
+{"cmpgdu.eq.qb", "", "d,s,t,-B", 0x20000185, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"cmpgdu.le.qb", "", "d,s,t,-B", 0x20000205, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"cmpgdu.lt.qb", "", "d,s,t,-B", 0x200001c5, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"cmpgu.eq.qb", "", "d,s,t,-B", 0x200000c5, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"cmpgu.le.qb", "", "d,s,t,-B", 0x20000145, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"cmpgu.lt.qb", "", "d,s,t,-B", 0x20000105, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"cmpu.eq.qb", "", "s,t,-N", 0x20000245, 0xfc0003ff, WR_1|RD_2, 0, 0, D32},
+{"cmpu.le.qb", "", "s,t,-N", 0x200002c5, 0xfc0003ff, WR_1|RD_2, 0, 0, D32},
+{"cmpu.lt.qb", "", "s,t,-N", 0x20000285, 0xfc0003ff, WR_1|RD_2, 0, 0, D32},
+{"cop2_1", "", "C", 0x20000002, 0xfc000007, 0, 0, I38, 0},
+{"crc32b", "", "t,r,-E", 0x200003e8, 0xfc001fff, WR_1|RD_2, 0, 0, CRC},
+{"crc32h", "", "t,r,-E", 0x200007e8, 0xfc001fff, WR_1|RD_2, 0, 0, CRC},
+{"crc32w", "", "t,r,-E", 0x20000be8, 0xfc001fff, WR_1|RD_2, 0, 0, CRC},
+{"crc32cb", "", "t,r,-E", 0x200013e8, 0xfc001fff, WR_1|RD_2, 0, 0, CRC},
+{"crc32ch", "", "t,r,-E", 0x200017e8, 0xfc001fff, WR_1|RD_2, 0, 0, CRC},
+{"crc32cw", "", "t,r,-E", 0x20001be8, 0xfc001fff, WR_1|RD_2, 0, 0, CRC},
+{"ctc1", "", "t,G", 0xa000183b, 0xfc00ffff, RD_1|WR_2, INSN2_ALIAS, I38, 0},
+{"ctc1", "", "t,S", 0xa000183b, 0xfc00ffff, RD_1|WR_2, 0, I38, 0},
+{"cttc1", "", "t,G", 0x20001e70, 0xfc00ffff, RD_1|WR_2, INSN2_ALIAS, 0, MT32}, /* MTTR */
+{"cttc1", "", "t,S", 0x20001e70, 0xfc00ffff, RD_1|WR_2, INSN2_ALIAS, 0, MT32}, /* MTTR */
+{"cttc2", "", "t,G", 0x20002e70, 0xfc00ffff, RD_1|WR_2, INSN2_ALIAS, 0, MT32}, /* MTTR */
+{"dabs", "", "d,v", 0, (int) M_DABS, INSN_MACRO, 0, I38, 0},
+{"daddiu", "[neg]", "t,r,h", 0x80008000, 0xfc00f000, WR_1|RD_2, 0, I38, 0}, /* DADDIU[NEG] */
+{"deret", "", "-F", 0x2000e37f, 0xfc00ffff, 0, 0, I38, 0},
+{"di", "", "", 0x2000477f, 0xffffffff, 0, INSN2_ALIAS, I38, 0},
+{"di", "", "w,-A", 0x2000477f, 0xfc00ffff, WR_1, 0, I38, 0},
+{"div", "", "d,v,t,-B", 0x20000118, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"div", "", "d,v,I", 0, (int) M_DIV_I, INSN_MACRO, 0, I38, 0},
+{"divu", "", "d,v,t,-B", 0x20000198, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"divu", "", "d,v,I", 0, (int) M_DIVU_I, INSN_MACRO, 0, I38, 0},
+{"dmt", "", "", 0x20010ab0, 0xffffffff, 0, INSN2_ALIAS, 0, MT32},
+{"dmt", "", "t", 0x20010ab0, 0xfc1fffff, WR_1, 0, 0, MT32},
+{"dpa.w.ph", "", "7,s,t", 0x200000bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32},
+{"dpaqx_s.w.ph", "", "7,s,t", 0x200022bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32},
+{"dpaqx_sa.w.ph","", "7,s,t", 0x200032bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32},
+{"dpaq_s.w.ph", "", "7,s,t", 0x200002bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32},
+{"dpaq_sa.l.w", "", "7,s,t", 0x200012bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32},
+{"dpau.h.qbl", "", "7,s,t", 0x200020bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32},
+{"dpau.h.qbr", "", "7,s,t", 0x200030bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32},
+{"dpax.w.ph", "", "7,s,t", 0x200010bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32},
+{"dps.w.ph", "", "7,s,t", 0x200004bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32},
+{"dpsqx_s.w.ph", "", "7,s,t", 0x200026bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32},
+{"dpsqx_sa.w.ph", "", "7,s,t", 0x200036bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32},
+{"dpsq_s.w.ph", "", "7,s,t", 0x200006bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32},
+{"dpsq_sa.l.w", "", "7,s,t", 0x200016bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32},
+{"dpsu.h.qbl", "", "7,s,t", 0x200024bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32},
+{"dpsu.h.qbr", "", "7,s,t", 0x200034bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32},
+{"dpsx.w.ph", "", "7,s,t", 0x200014bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32},
+{"dvpe", "", "", 0x20000ab0, 0xffffffff, 0, INSN2_ALIAS, 0, MT32}, /* DVPE */
+{"dvpe", "", "t", 0x20000ab0, 0xfc1fffff, WR_1, 0, 0, MT32},
+{"ehb", "", "-G", 0x8000c003, 0xffe0f1ff, 0, 0, I38, 0},
+{"ei", "", "", 0x2000577f, 0xffffffff, 0, INSN2_ALIAS, I38, 0},
+{"ei", "", "t,-A", 0x2000577f, 0xfc00ffff, WR_1, 0, I38, 0},
+{"emt", "", "", 0x20010eb0, 0xffffffff, 0, INSN2_ALIAS, 0, MT32},
+{"emt", "", "t", 0x20010eb0, 0xfc1fffff, WR_1, 0, 0, MT32},
+{"eret", "", "-H", 0x2000f37f, 0xfc01ffff, 0, 0, I38, 0},
+{"eretnc", "", "-H", 0x2001f37f, 0xfc01ffff, 0, 0, I38, 0},
+{"evpe", "", "", 0x20000eb0, 0xffffffff, 0, INSN2_ALIAS, 0, MT32}, /* EVPE */
+{"evpe", "", "t", 0x20000eb0, 0xfc1fffff, WR_1, 0, 0, MT32},
+{"evp", "", "-A", 0x20000790, 0xffe0ffff, 0, INSN2_ALIAS, I38, 0}, /* EVP */
+{"evp", "", "t,-A", 0x20000790, 0xfc00ffff, WR_1, 0, I38, 0},
+{"extp", "", "t,7,2", 0x2000267f, 0xfc003fff, WR_1|RD_2, 0, 0, D32},
+{"extpdp", "", "t,7,2", 0x2000367f, 0xfc003fff, WR_1|RD_2, 0, 0, D32},
+{"extpdpv", "", "t,7,s", 0x200038bf, 0xfc003fff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"extpv", "", "t,7,s", 0x200028bf, 0xfc003fff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"extr.w", "", "t,7,2", 0x20000e7f, 0xfc003fff, WR_1|RD_2, 0, 0, D32},
+{"extrv.w", "", "t,7,s", 0x20000ebf, 0xfc003fff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"extrv_r.w", "", "t,7,s", 0x20001ebf, 0xfc003fff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"extrv_rs.w", "", "t,7,s", 0x20002ebf, 0xfc003fff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"extrv_s.h", "", "t,7,s", 0x20003ebf, 0xfc003fff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"extr_r.w", "", "t,7,2", 0x20001e7f, 0xfc003fff, WR_1|RD_2, 0, 0, D32},
+{"extr_rs.w", "", "t,7,2", 0x20002e7f, 0xfc003fff, WR_1|RD_2, 0, 0, D32},
+{"extr_s.h", "", "t,7,2", 0x20003e7f, 0xfc003fff, WR_1|RD_2, 0, 0, D32},
+{"fork", "", "d,s,t,-B", 0x20000228, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, MT32},
+{"ginvi", "", "s,-I", 0x20001f7f, 0xfc00ffff, RD_1, 0, 0, GINV},
+{"ginvt", "", "s,+;,-J", 0x20000f7f, 0xfc00ffff, RD_1, 0, 0, GINV},
+{"ins", "", "t,r,+A,+B", 0x8000e000, 0xfc00f820, WR_1|RD_2, 0, 0, xNMS},
+{"ins", "", "t,r,+A,+B", 0, (int) M_INS, INSN_MACRO, 0, I38, 0},
+{"insv", "", "t,s", 0x2000413f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32},
+{"j", "", "mp", 0xd800, 0xfc1f, RD_1, INSN2_ALIAS|UBR|CTC, I38, 0},
+{"j", "", "+u", 0x28000000, 0xfe000000, 0, INSN2_ALIAS|UBR|CTC, I38, 0}, /* BC */
+{"j", "", "s", 0x48000000, 0xffe0ffff, RD_1, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC */
+{"jrc.hb", "", "s", 0x48001000, 0xffe0ffff, RD_1, INSN2_ALIAS, I38, 0}, /* JALRC.HB */
+{"jr.hb", "", "s", 0x48001000, 0xffe0ffff, RD_1, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC.HB */
+{"jalrc.hb", "", "s", 0x4be01000, 0xffe0ffff, RD_1, INSN2_ALIAS, I38, 0}, /* JALRC.HB */
+{"jalrc.hb", "", "t,s,-C", 0x48001000, 0xfc00f000, WR_1|RD_2, 0, I38, 0},
+{"jalr.hb", "", "s", 0x4be01000, 0xffe0ffff, RD_1, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC.HB */
+{"jalr.hb", "", "t,s", 0x48001000, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC.HB */
+/* SVR4 PIC code requires special handling for jal, so it must be a macro. */
+{"jal", "", "my,mp", 0xd810, 0xfc1f, WR_31|RD_1, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC[16] */
+{"jal", "", "mp", 0xd810, 0xfc1f, WR_31|RD_1, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC[16] */
+{"jal", "", "s", 0x4be00000, 0xffe0ffff, RD_1, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC */
+{"jal", "", "t,s", 0x48000000, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC */
+{"jal", "", "A", 0, (int) M_JAL_A, INSN_MACRO, 0, I38, 0},
+{"jal", "", "+u", 0x2a000000, 0xfe000000, WR_31, INSN2_ALIAS|UBR|CTC, I38, 0}, /* BALC */
+{"lb", "[16]", "md,mL(ml)", 0x5c00, 0xfc0c, WR_1|RD_3, 0, I38, 0}, /* LB[16] */
+{"lb", "[gp]", "t,+1(ma)", 0x44000000, 0xfc1c0000, WR_1|RD_3, 0, I38, 0}, /* LB[GP] */
+{"lb", "[u12]", "t,o(b)", 0x84000000, 0xfc00f000, WR_1|RD_3, 0, I38, 0}, /* LB[U12] */
+{"lb", "[s9]", "t,+j(b)", 0xa4000000, 0xfc007f00, WR_1|RD_3, 0, I38, 0}, /* LB[S9] */
+{"lb", "", "t,A(c)", 0, (int) M_LB_AC, INSN_MACRO, 0, I38, 0},
+{"lb", "", "t,A(b)", 0, (int) M_LBX_AB, INSN_MACRO, 0, I38, 0},
+{"lbe", "", "t,+j(b)", 0xa4000200, 0xfc007f00, WR_1|RD_3, 0, 0, EVA},
+{"lbe", "", "t,A(c)", 0, (int) M_LBE_AC, INSN_MACRO, 0, 0, EVA},
+{"lbu", "[16]", "md,mL(ml)", 0x5c08, 0xfc0c, WR_1|RD_3, 0, I38, 0}, /* LBU[16] */
+{"lbu", "[gp]", "t,+1(ma)", 0x44080000, 0xfc1c0000, WR_1|RD_3, 0, I38, 0}, /* LBU[GP] */
+{"lbu", "[u12]", "t,o(b)", 0x84002000, 0xfc00f000, WR_1|RD_3, 0, I38, 0}, /* LBU[U12] */
+{"lbu", "[s9]", "t,+j(b)", 0xa4001000, 0xfc007f00, WR_1|RD_3, 0, I38, 0}, /* LBU[S9] */
+{"lbu", "", "t,A(c)", 0, (int) M_LBU_AC, INSN_MACRO, 0, I38, 0},
+{"lbu", "", "t,A(b)", 0, (int) M_LBUX_AB, INSN_MACRO, 0, I38, 0},
+{"lbue", "", "t,+j(b)", 0xa4001200, 0xfc007f00, WR_1|RD_3, 0, 0, EVA},
+{"lbue", "", "t,A(c)", 0, (int) M_LBUE_AC, INSN_MACRO, 0, 0, EVA},
+{"lbux", "", "d,s(t)", 0x20000107, 0xfc0007ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"lbx", "", "d,s(t)", 0x20000007, 0xfc0007ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"ld", "", "t,A(c)", 0, (int) M_LD_AC, INSN_MACRO, 0, I38, 0},
+{"ld", "", "t,A(b)", 0, (int) M_LDX_AB, INSN_MACRO, 0, I38, 0},
+{"lh", "[16]", "md,mH(ml)", 0x7c00, 0xfc09, WR_1|RD_3, 0, I38, 0}, /* LH[16] */
+{"lh", "[gp]", "t,+3(ma)", 0x44100000, 0xfc1c0001, WR_1|RD_3, 0, I38, 0}, /* LH[GP] */
+{"lh", "[u12]", "t,o(b)", 0x84004000, 0xfc00f000, WR_1|RD_3, 0, I38, 0}, /* LH[U12] */
+{"lh", "[s9]", "t,+j(b)", 0xa4002000, 0xfc007f00, WR_1|RD_3, 0, I38, 0}, /* LH[S9] */
+{"lh", "", "t,A(c)", 0, (int) M_LH_AC, INSN_MACRO, 0, I38, 0},
+{"lh", "", "t,A(b)", 0, (int) M_LHX_AB, INSN_MACRO, 0, I38, 0},
+{"lhe", "", "t,+j(b)", 0xa4002200, 0xfc007f00, WR_1|RD_3, 0, 0, EVA},
+{"lhe", "", "t,A(c)", 0, (int) M_LHE_AC, INSN_MACRO, 0, 0, EVA},
+{"lhu", "[16]", "md,mH(ml)", 0x7c08, 0xfc09, WR_1|RD_3, 0, I38, 0}, /* LHU[16] */
+{"lhu", "[gp]", "t,+3(ma)", 0x44100001, 0xfc1c0001, WR_1|RD_3, 0, I38, 0}, /* LHU[GP] */
+{"lhu", "[u12]", "t,o(b)", 0x84006000, 0xfc00f000, WR_1|RD_3, 0, I38, 0}, /* LHU[U12] */
+{"lhu", "[s9]", "t,+j(b)", 0xa4003000, 0xfc007f00, WR_1|RD_3, 0, I38, 0}, /* LHU[S9] */
+{"lhu", "", "t,A(c)", 0, (int) M_LHU_AC, INSN_MACRO, 0, I38, 0},
+{"lhu", "", "t,A(b)", 0, (int) M_LHUX_AB, INSN_MACRO, 0, I38, 0},
+{"lhue", "", "t,+j(b)", 0xa4003200, 0xfc007f00, WR_1|RD_3, 0, 0, EVA},
+{"lhue", "", "t,A(c)", 0, (int) M_LHUE_AC, INSN_MACRO, 0, 0, EVA},
+{"lhux", "", "d,s(t)", 0x20000307, 0xfc0007ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"lhuxs", "", "d,s(t)", 0x20000347, 0xfc0007ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"lhx", "", "d,s(t)", 0x20000207, 0xfc0007ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"lhxs", "", "d,s(t)", 0x20000247, 0xfc0007ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"li.d", "", "t,F", 0, (int) M_LI_D, INSN_MACRO, 0, I38, 0},
+{"li.s", "", "t,f", 0, (int) M_LI_S, INSN_MACRO, 0, I38, 0},
+{"ll", "", "t,+p(b)", 0xa4005100, 0xfc007f03, WR_1|RD_3, 0, I38, 0},
+{"ll", "", "t,A(c)", 0, (int) M_LL_AC, INSN_MACRO, 0, I38, 0},
+{"lle", "", "t,+p(b)", 0xa4005200, 0xfc007f03, WR_1|RD_3, 0, 0, EVA},
+{"lle", "", "t,A(c)", 0, (int) M_LLE_AC, INSN_MACRO, 0, 0, EVA},
+{"llwp", "", "t,e,(b),-K", 0xa4005101, 0xfc007f03, WR_1|WR_2|RD_3, 0, 0, xNMS},
+{"llwp", "", "t,e,A(c)", 0, (int) M_LLWP_AC, INSN_MACRO, 0, 0, xNMS},
+{"llwpe", "", "t,e,(b),-K", 0xa4005201, 0xfc007f03, WR_1|WR_2|RD_3, 0, 0, EVA},
+{"llwpe", "", "t,e,A(c)", 0, (int) M_LLWP_AC, INSN_MACRO, 0, 0, EVA},
+{"lsa", "", "d,v,t,+w,-L", 0x2000000f, 0xfc00003f, WR_1|RD_2|RD_3, 0, I38, 0},
+{"lw", "[16]", "md,mJ(ml)", 0x1400, 0xfc00, WR_1|RD_3, 0, I38, 0}, /* LW[16] */
+{"lw", "[4x4]", "mu,mN(mv)", 0x7400, 0xfc00, WR_1|RD_3, 0, 0, xNMS}, /* LW[4X4] */
+{"lw", "[sp]", "mp,mR(ms)", 0x3400, 0xfc00, WR_1|RD_3, 0, I38, 0}, /* LW[SP] */
+{"lw", "[gp16]", "md,mO(ma)", 0x5400, 0xfc00, WR_1|RD_3, 0, I38, 0}, /* LW[GP16] */
+{"lw", "[gp]", "t,.(ma)", 0x40000002, 0xfc000003, WR_1|RD_3, 0, I38, 0}, /* LW[GP] */
+{"lw", "[gp16]", "md,mA(ma)", 0x5400, 0xfc00, WR_1|RD_3, 0, I38, 0}, /* LW[GP16] */
+{"lw", "[u12]", "t,o(b)", 0x84008000, 0xfc00f000, WR_1|RD_3, 0, I38, 0}, /* LW[U12] */
+{"lw", "[s9]", "t,+j(b)", 0xa4004000, 0xfc007f00, WR_1|RD_3, 0, I38, 0}, /* LW[S9] */
+{"lw", "", "t,A(c)", 0, (int) M_LW_AC, INSN_MACRO, 0, I38, 0},
+{"lw", "", "t,A(b)", 0, (int) M_LWX_AB, INSN_MACRO, 0, I38, 0},
+{"lwe", "", "t,+j(b)", 0xa4004200, 0xfc007f00, WR_1|RD_3, 0, 0, EVA},
+{"lwe", "", "t,A(c)", 0, (int) M_LWE_AC, INSN_MACRO, 0, 0, EVA},
+{"lwm", "", "t,+j(b),|", 0xa4000400, 0xfc000f00, WR_1|RD_3, 0, 0, xNMS}, /* LWM */
+{"lwpc", "[48]", "mp,+S", 0x600b, 0xfc1f, WR_1, 0, 0, xNMS}, /* LWPC[48] */
+{"lwx", "", "d,s(t)", 0x20000407, 0xfc0007ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"lwxs", "[16]", "me,ml(md)", 0x5001, 0xfc01, WR_1|RD_2|RD_3, 0, I38, 0}, /* LWXS[16] */
+{"lwxs", "[32]", "d,s(t)", 0x20000447, 0xfc0007ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"madd", "[dsp]", "7,s,t", 0x20000abf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, /* MADD[DSP] */
+{"maddu", "[dsp]", "7,s,t", 0x20001abf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, /* MADDU[DSP] */
+{"maq_s.w.phl", "", "7,s,t", 0x20001a7f, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32},
+{"maq_s.w.phr", "", "7,s,t", 0x20000a7f, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32},
+{"maq_sa.w.phl", "", "7,s,t", 0x20003a7f, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32},
+{"maq_sa.w.phr", "", "7,s,t", 0x20002a7f, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32},
+{"mfc0", "", "t,O", 0x20000030, 0xfc0007ff, WR_1, INSN2_ALIAS, I38, 0}, /* MFC0 with named register */
+{"mfc0", "", "t,P,J", 0x20000030, 0xfc0007ff, WR_1, INSN2_ALIAS, I38, 0}, /* MFC0 with named register & select */
+{"mfc0", "", "t,G,J,-B", 0x20000030, 0xfc0003ff, WR_1, 0, I38, 0},
+{"mfhc0", "", "t,O", 0x20000038, 0xfc0007ff, WR_1, INSN2_ALIAS, I38, 0}, /* MFHC0 with named register */
+{"mfhc0", "", "t,P,J", 0x20000038, 0xfc0007ff, WR_1, INSN2_ALIAS, I38, 0}, /* MFHC0 with named register & select*/
+{"mfhc0", "", "t,G,J,-B", 0x20000038, 0xfc0003ff, WR_1, 0, I38, 0},
+{"mfhi", "[dsp]", "t,7,-A", 0x2000007f, 0xfc003fff, WR_1|RD_2, 0, 0, D32}, /* MFHI[DSP] */
+{"mflo", "[dsp]", "t,7,-A", 0x2000107f, 0xfc003fff, WR_1|RD_2, 0, 0, D32}, /* MFLO[DSP] */
+{"mftc0", "", "t,O", 0x20000230, 0xfc0007ff, WR_1, INSN2_ALIAS, 0, MT32}, /* MFTR with named register */
+{"mftc0", "", "t,P,J", 0x20000230, 0xfc0007ff, WR_1, INSN2_ALIAS, 0, MT32}, /* MFTR with named register & select */
+{"mfthc0", "", "t,O", 0x20000238, 0xfc0007ff, WR_1, INSN2_ALIAS, 0, MT32}, /* MFTR with named register */
+{"mfthc0", "", "t,P,J", 0x20000238, 0xfc0007ff, WR_1, INSN2_ALIAS, 0, MT32}, /* MFTR with named register & select*/
+{"mftc1", "", "t,S", 0x20001630, 0xfc00ffff, WR_1|RD_2|FP_S, INSN2_ALIAS, 0, MT32}, /* MFTR */
+{"mftc1", "", "t,G", 0x20001630, 0xfc00ffff, WR_1|RD_2|FP_S, INSN2_ALIAS, 0, MT32}, /* MFTR */
+{"mftc2", "", "t,G", 0x20002630, 0xfc00ffff, WR_1, INSN2_ALIAS, 0, MT32}, /* MFTR */
+{"mftdsp", "", "t", 0x20100e30, 0xfc1fffff, WR_1, INSN2_ALIAS, 0, MT32}, /* MFTR */
+{"mftgpr", "", "t,s", 0x20000630, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS, 0, MT32}, /* MFTR */
+{"mfthc1", "", "t,S", 0x20001638, 0xfc00ffff, WR_1|RD_2|FP_D, INSN2_ALIAS, 0, MT32}, /* MFTR */
+{"mfthc1", "", "t,G", 0x20001638, 0xfc00ffff, WR_1|RD_2|FP_D, INSN2_ALIAS, 0, MT32}, /* MFTR */
+{"mfthc2", "", "t,G", 0x20002638, 0xfc00ffff, WR_1, INSN2_ALIAS, 0, MT32}, /* MFTR */
+{"mfthi", "", "t", 0x20010e30, 0xfc1fffff, WR_1|RD_a, INSN2_ALIAS, 0, MT32}, /* MFTR */
+{"mfthi", "", "t,*", 0x20010e30, 0xfc13ffff, WR_1|RD_a, INSN2_ALIAS, 0, MT32}, /* MFTR */
+{"mftlo", "", "t", 0x20000e30, 0xfc1fffff, WR_1|RD_a, INSN2_ALIAS, 0, MT32}, /* MFTR */
+{"mftlo", "", "t,*", 0x20000e30, 0xfc13ffff, WR_1|RD_a, INSN2_ALIAS, 0, MT32}, /* MFTR */
+{"mftr", "", "t,s,!,H,$", 0x20000230, 0xfc0003f7, WR_1, 0, 0, MT32},
+{"mod", "", "d,v,t,-B", 0x20000158, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"mod", "", "d,v,I", 0, (int) M_MOD_I, INSN_MACRO, 0, I38, 0},
+{"modsub", "", "d,s,t,-B", 0x20000295, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"modu", "", "d,v,t,-B", 0x200001d8, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"modu", "", "d,v,I", 0, (int) M_MODU_I, INSN_MACRO, 0, I38, 0},
+{"move.balc", "", "+7,+5,+r", 0x08000000, 0xfc000000, WR_1|RD_2, 0, 0, xNMS},
+{"move.bal", "", "+7,+5,+r", 0x08000000, 0xfc000000, WR_1|RD_2, INSN2_ALIAS|UBR|CTC, 0, xNMS}, /* MOVE.BALC */
+{"movep", "", "mq,mx,mw", 0xbc00, 0xfc00, WR_1|RD_2|RD_3, 0, 0, xNMS}, /* MOVEP */
+{"movep", "", "mr,mw,mx", 0xbc00, 0xfc00, WR_1|RD_2|RD_3, INSN2_ALIAS, 0, xNMS}, /* MOVEP */
+{"movep", "[rev]", "mv,mu,mq", 0xfc00, 0xfc00, WR_1|WR_2|RD_3, 0, 0, xNMS}, /* MOVEP[REV] */
+{"movep", "[rev]", "mu,mv,mr", 0xfc00, 0xfc00, WR_1|WR_2|RD_3, INSN2_ALIAS, 0, xNMS}, /* MOVEP[REV] */
+{"movn", "", "d,v,t", 0x20000610, 0xfc0007ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"movz", "", "d,v,t", 0x20000210, 0xfc0007ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"msub", "[dsp]", "7,s,t", 0x20002abf, 0xfc003fff,MOD_1|RD_2|RD_3, 0, 0, D32}, /* MSUB[DSP] */
+{"msubu", "[dsp]", "7,s,t", 0x20003abf, 0xfc003fff,MOD_1|RD_2|RD_3, 0, 0, D32}, /* MSUBU[DSP] */
+{"mtc0", "", "t,O", 0x20000070, 0xfc0007ff, RD_1, INSN2_ALIAS, I38, 0}, /* MTC0 with named register */
+{"mtc0", "", "t,P,J", 0x20000070, 0xfc0007ff, RD_1, INSN2_ALIAS, I38, 0}, /* MTCO with named register & select */
+{"mtc0", "", "t,G,J,-B", 0x20000070, 0xfc0003ff, RD_1, 0, I38, 0},
+{"mthc0", "", "t,O", 0x20000078, 0xfc0007ff, RD_1, INSN2_ALIAS, I38, 0}, /* MTHC0 with named register */
+{"mthc0", "", "t,P,J", 0x20000078, 0xfc0007ff, RD_1, INSN2_ALIAS, I38, 0}, /* MTHC0 with named register & select */
+{"mthc0", "", "t,G,J,-B", 0x20000078, 0xfc0003ff, RD_1, 0, I38, 0},
+{"mthi", "[dsp]", "s,7,-I", 0x2000207f, 0xfc003fff, WR_1|RD_2, 0, 0, D32}, /* MTHI[DSP] */
+{"mthlip", "", "s,7,-I", 0x2000027f, 0xfc003fff, WR_1|RD_2, 0, 0, D32},
+{"mtlo", "[dsp]", "s,7,-I", 0x2000307f, 0xfc003fff, WR_1|RD_2, 0, 0, D32}, /* MTLO[DSP] */
+{"mttc0", "", "t,O", 0x20000270, 0xfc0007ff, RD_1, INSN2_ALIAS, 0, MT32}, /* MTTR with named register */
+{"mttc0", "", "t,P,J", 0x20000270, 0xfc0007ff, RD_1, INSN2_ALIAS, 0, MT32}, /* MTTR with named register & select */
+{"mtthc0", "", "t,O", 0x20000278, 0xfc0007ff, RD_1, INSN2_ALIAS, 0, MT32}, /* MTTR with named register*/
+{"mtthc0", "", "t,P,J", 0x20000278, 0xfc0007ff, RD_1, INSN2_ALIAS, 0, MT32}, /* MTTR with named register & select */
+{"mttc1", "", "t,S", 0x20001670, 0xfc00ffff, RD_1|WR_2|FP_S, INSN2_ALIAS, 0, MT32}, /* MTTR */
+{"mttc1", "", "t,G", 0x20001670, 0xfc00ffff, RD_1|WR_2|FP_S, INSN2_ALIAS, 0, MT32}, /* MTTR */
+{"mttc2", "", "t,G", 0x20002670, 0xfc00ffff, RD_1, INSN2_ALIAS, 0, MT32}, /* MTTR */
+{"mttgpr", "", "s,t", 0x20000670, 0xfc00ffff, RD_1|WR_2, INSN2_ALIAS|INSN2_MTTGPR_RC1, 0, MT32}, /* MTTR */
+{"mttgpr", "", "t,s", 0x20000670, 0xfc00ffff, RD_1|WR_2, INSN2_ALIAS, 0, MT32}, /* MTTR */
+{"mtthc1", "", "t,S", 0x20001678, 0xfc00ffff, RD_1|WR_2|FP_D, INSN2_ALIAS, 0, MT32}, /* MTTR */
+{"mtthc1", "", "t,G", 0x20001678, 0xfc00ffff, RD_1|WR_2|FP_D, INSN2_ALIAS, 0, MT32}, /* MTTR */
+{"mtthc2", "", "t,G", 0x20002678, 0xfc00ffff, RD_1, INSN2_ALIAS, 0, MT32}, /* MTTR */
+{"mtthi", "", "t", 0x20010e70, 0xfc1fffff, RD_1|WR_a, INSN2_ALIAS, 0, MT32}, /* MTTR */
+{"mtthi", "", "t,*", 0x20010e70, 0xfc13ffff, RD_1|WR_a, INSN2_ALIAS, 0, MT32}, /* MTTR */
+{"mttlo", "", "t", 0x20000e70, 0xfc1fffff, RD_1|WR_a, INSN2_ALIAS, 0, MT32}, /* MTTR */
+{"mttlo", "", "t,*", 0x20000e70, 0xfc13ffff, RD_1|WR_a, INSN2_ALIAS, 0, MT32}, /* MTTR */
+{"mttdsp", "", "t", 0x20100e70, 0xfc1fffff, RD_1, INSN2_ALIAS, 0, MT32}, /* MTTR */
+{"mttr", "", "t,s,!,H,$", 0x20000270, 0xfc0003f7, RD_1, 0, 0, MT32},
+{"muh", "", "d,v,t,-B", 0x20000058, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"muhu", "", "d,v,t,-B", 0x200000d8, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"mul", "[4x4]", "mu,mt,mv", 0x3c08, 0xfd08, MOD_1|RD_3, 0, 0, xNMS}, /* MUL[4X4] */
+{"mul", "[4x4]", "mu,mv,mk", 0x3c08, 0xfd08, MOD_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* MUL[4X4] */
+{"mul", "[32]", "d,v,t,-B", 0x20000018, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"mul", "", "d,v,I", 0, (int) M_MUL_I, INSN_MACRO, 0, I38, 0},
+{"mul.ph", "", "d,s,t", 0x2000002d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"muleq_s.w.phl", "", "d,s,t,-B", 0x20000025, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"muleq_s.w.phr", "", "d,s,t,-B", 0x20000065, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"muleu_s.ph.qbl", "", "d,s,t,-B", 0x20000095, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"muleu_s.ph.qbr", "", "d,s,t,-B", 0x200000d5, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"mulq_rs.ph", "", "d,s,t,-B", 0x20000115, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"mulq_rs.w", "", "d,s,t,-B", 0x20000195, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"mulq_s.ph", "", "d,s,t,-B", 0x20000155, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"mulq_s.w", "", "d,s,t,-B", 0x200001d5, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"mulsa.w.ph", "", "7,s,t", 0x20002cbf, 0xfc003fff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"mulsaq_s.w.ph", "", "7,s,t", 0x20003cbf, 0xfc003fff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"mult", "[dsp]", "7,s,t", 0x20000cbf, 0xfc003fff, WR_1|RD_2|RD_3, 0, 0, D32}, /* MULT[DSP] */
+{"multu", "[dsp]", "7,s,t", 0x20001cbf, 0xfc003fff, WR_1|RD_2|RD_3, 0, 0, D32}, /* MULTU[DSP] */
+{"mulu", "", "d,v,t,-B", 0x20000098, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"mul_s.ph", "", "d,s,t", 0x2000042d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"neg", "", "d,w", 0x20000190, 0xfc1f07ff, WR_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* SUB */
+{"negu", "", "d,w", 0x200001d0, 0xfc1f07ff, WR_1|RD_2, INSN2_ALIAS, I38, 0}, /* SUBU */
+{"not", "[16]", "md,ml", 0x5000, 0xfc0f, WR_1|RD_2, 0, I38, 0}, /* NOT[16] */
+{"not", "[32]", "d,v", 0x200002d0, 0xffe007ff, WR_1|RD_2, INSN2_ALIAS, I38, 0}, /* NOR */
+{"nor", "", "d,v,t,-B", 0x200002d0, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"nor", "", "t,r,I", 0, (int) M_NOR_I, INSN_MACRO, 0, I38, 0},
+{"or", "[16]", "md,mk,ml", 0x500c, 0xfc0f, WR_1|RD_3, INSN2_ALIAS, I38, 0}, /* OR[16] */
+{"or", "[16]", "md,ml,mk", 0x500c, 0xfc0f, WR_1|RD_2, INSN2_ALIAS, I38, 0}, /* OR[16] */
+{"or", "[16]", "md,ml", 0x500c, 0xfc0f, WR_1|RD_2, 0, I38, 0}, /* OR[16] */
+{"or", "[32]", "d,v,t,-B", 0x20000290, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"or", "", "t,r,I", 0, (int) M_OR_I, INSN_MACRO, 0, I38, 0},
+{"ori", "", "t,r,g", 0x80000000, 0xfc00f000, WR_1|RD_2, 0, I38, 0},
+{"pause", "", "-M", 0x8000c005, 0xfffff1ff, 0, 0, I38, 0},
+{"packrl.ph", "", "d,s,t,-B", 0x200001ad, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"pick.ph", "", "d,s,t,-B", 0x2000022d, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"pick.qb", "", "d,s,t,-B", 0x200001ed, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"preceq.w.phl", "", "t,s", 0x2000513f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32},
+{"preceq.w.phr", "", "t,s", 0x2000613f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32},
+{"precequ.ph.qbl", "", "t,s", 0x2000713f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32},
+{"precequ.ph.qbla", "", "t,s", 0x2000733f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32},
+{"precequ.ph.qbr", "", "t,s", 0x2000913f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32},
+{"precequ.ph.qbra", "", "t,s", 0x2000933f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32},
+{"preceu.ph.qbl", "", "t,s", 0x2000b13f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32},
+{"preceu.ph.qbla", "", "t,s", 0x2000b33f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32},
+{"preceu.ph.qbr", "", "t,s", 0x2000d13f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32},
+{"preceu.ph.qbra", "", "t,s", 0x2000d33f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32},
+{"precr.qb.ph", "", "d,s,t,-B", 0x2000006d, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"precrq.ph.w", "", "d,s,t,-B", 0x200000ed, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"precrq.qb.ph", "", "d,s,t,-B", 0x200000ad, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"precrqu_s.qb.ph", "", "d,s,t,-B", 0x2000016d, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"precrq_rs.ph.w", "", "d,s,t,-B", 0x2000012d, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"precr_sra.ph.w", "", "t,s,1", 0x200003cd, 0xfc0007ff, WR_1|RD_2, 0, 0, D32},
+{"precr_sra_r.ph.w", "", "t,s,1", 0x200007cd, 0xfc0007ff, WR_1|RD_2, 0, 0, D32},
+{"pref", "[u12]", "k,o(b)", 0x84003000, 0xfc00f000, RD_3, 0, I38, 0}, /* PREF[U12] */
+{"pref", "[s9]", "k,+j(b)", 0xa4001800, 0xfc007f00, RD_3, 0, I38, 0}, /* PREF[S9], preceded by SYNCI[S9] */
+{"pref", "", "k,A(c)", 0, (int) M_PREF_AC, INSN_MACRO, 0, I38, 0},
+{"prefe", "", "k,+j(b)", 0xa4001a00, 0xfc007f00, RD_3, 0, 0, EVA}, /* preceded by SYNCIE */
+{"prefe", "", "k,A(c)", 0, (int) M_PREFE_AC, INSN_MACRO, 0, 0, EVA},
+{"prepend", "", "d,-n,t,+I", 0x2000001f, 0xfc00003f, WR_1|RD_3, INSN2_ALIAS, 0, D32}, /* EXTW */
+{"raddu.w.qb", "", "t,s", 0x2000f13f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32},
+{"rddsp", "", "t", 0x201fc67f, 0xfc1fffff, WR_1, INSN2_ALIAS, 0, D32},
+{"rddsp", "", "t,8", 0x2000067f, 0xfc003fff, WR_1, 0, 0, D32},
+{"rdhwr", "", "t,K", 0x200001c0, 0xfc0007ff, WR_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* RDHWR with sel=0 */
+{"rdhwr", "", "t,U,J", 0x200001c0, 0xfc0007ff, WR_1|RD_2, INSN2_ALIAS, 0, xNMS},
+{"rdhwr", "", "t,G,H,-B", 0x200001c0, 0xfc0003ff, WR_1|RD_2, 0, 0, xNMS}, /* RDWHR */
+{"rdpgpr", "", "t,s", 0x2000e17f, 0xfc00ffff, WR_1|RD_2, 0, I38, 0},
+{"rem", "", "d,v,t", 0x20000158, 0xfc0007ff, WR_1|RD_2|RD_3, INSN2_ALIAS, I38, 0}, /* MOD */
+{"rem", "", "d,v,I", 0, (int) M_REM_3I, INSN_MACRO, 0, I38, 0},
+{"remu", "", "d,v,t", 0x200001d8, 0xfc0007ff, WR_1|RD_2|RD_3, INSN2_ALIAS, I38, 0}, /* MODU */
+{"repl.ph", "", "t,@,-B", 0x2000003d, 0xfc0003ff, WR_1, 0, 0, D32},
+{"repl.qb", "", "t,5,-O", 0x200005ff, 0xfc000fff, WR_1, 0, 0, D32},
+{"replv.ph", "", "t,s", 0x2000033f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32},
+{"replv.qb", "", "t,s", 0x2000133f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32},
+{"restore", "[32]", "+N,n", 0x80003002, 0xfc00f003, 0, 0, I38, 0},
+{"restore.jrc", "[16]", "mG", 0x1d00, 0xff0f, 0, 0, I38, 0}, /* RESTORE.JRC[16] */
+{"restore.jrc", "[16]", "mG,mn", 0x1d00, 0xfd00, 0, 0, I38, 0}, /* RESTORE.JRC[16], preceded by RESTORE[16] */
+{"restore.jrc", "[32]", "+N", 0x80003003, 0xfffff007, 0, 0, I38, 0}, /* RESTORE.JRC[32] */
+{"restore.jrc", "[32]", "+N,n", 0x80003003, 0xfc00f003, 0, 0, I38, 0},
+{"jraddiusp", "", "mG", 0x1d00, 0xff0f, 0, INSN2_ALIAS, I38, 0}, /* RESTORE.JRC[16] */
+{"jraddiusp", "", "+N", 0x80003003, 0xfffff007, 0, INSN2_ALIAS, I38, 0}, /* RESTORE.JRC[32] */
+{"jraddiusp", "", "I", 0, (int) M_JRADDIUSP, INSN_MACRO, 0, I38, 0},
+{"rol", "", "d,v,t", 0, (int) M_ROL, INSN_MACRO, 0, I38, 0},
+{"rol", "", "d,v,I", 0, (int) M_ROL_I, INSN_MACRO, 0, I38, 0},
+{"rotrv", "", "d,s,t,-B", 0x200000d0, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"rotr", "", "t,r,<,-M", 0x8000c0c0, 0xfc00f1e0, WR_1|RD_2, 0, I38, 0},
+{"rotr", "", "d,v,t", 0x200000d0, 0xfc0007ff, WR_1|RD_2|RD_3, INSN2_ALIAS, I38, 0}, /* ROTRV */
+{"ror", "", "t,r,<", 0x8000c0c0, 0xfc00ffe0, WR_1|RD_2, INSN2_ALIAS, I38, 0}, /* ROTR */
+{"ror", "", "d,v,t", 0x200000d0, 0xfc0007ff, WR_1|RD_2|RD_3, INSN2_ALIAS, I38, 0}, /* ROTRV */
+{"ror", "", "d,v,I", 0, (int) M_ROR_I, INSN_MACRO, 0, I38, 0},
+{"rorv", "", "t,r,<", 0x8000c0c0, 0xfc00ffe0, WR_1|RD_2, INSN2_ALIAS, I38, 0}, /* ROTR */
+{"rorv", "", "d,v,t", 0x200000d0, 0xfc0007ff, WR_1|RD_2|RD_3, INSN2_ALIAS, I38, 0}, /* ROTRV */
+{"rotl", "", "d,v,t", 0, (int) M_ROL, INSN_MACRO, 0, I38, 0},
+{"rotl", "", "d,v,I", 0, (int) M_ROL_I, INSN_MACRO, 0, I38, 0},
+{"wsbh", "", "t,r", 0x8000d608, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* ROTX t,s,8,24*/
+{"rotx", "", "t,r,<,+*", 0x8000d000, 0xfc00f860, WR_1|RD_2, INSN2_ALIAS, 0, xNMS},
+{"rotx", "", "t,r,<,+*,+|", 0x8000d000, 0xfc00f820, WR_1|RD_2, 0, 0, xNMS},
+{"save", "[16]", "mG", 0x1c00, 0xff0f, 0, 0, I38, 0}, /* SAVE[16] */
+{"save", "[16]", "mG,mn", 0x1c00, 0xfd00, 0, 0, I38, 0}, /* SAVE[16] */
+{"save", "[32]", "+N,n", 0x80003000, 0xfc00f003, 0, 0, I38, 0},
+{"sb", "[16]", "mm,mL(ml)", 0x5c04, 0xfc0c, RD_1|RD_3, 0, I38, 0}, /* SB[16] */
+{"sb", "[gp]", "t,+1(ma)", 0x44040000, 0xfc1c0000, RD_1|RD_3, 0, I38, 0}, /* SB[GP] */
+{"sb", "[u12]", "t,o(b)", 0x84001000, 0xfc00f000, RD_1|RD_3, 0, I38, 0}, /* SB[U12] */
+{"sb", "[s9]", "t,+j(b)", 0xa4000800, 0xfc007f00, RD_1|RD_3, 0, I38, 0}, /* SB[S9] */
+{"sb", "", "t,A(c)", 0, (int) M_SB_AC, INSN_MACRO, 0, I38, 0},
+{"sb", "", "t,A(b)", 0, (int) M_SBX_AB, INSN_MACRO, 0, 0, xNMS},
+{"sbe", "", "t,+j(b)", 0xa4000a00, 0xfc007f00, RD_1|RD_3, 0, 0, EVA},
+{"sbe", "", "t,A(c)", 0, (int) M_SBE_AC, INSN_MACRO, 0, 0, EVA},
+{"sbx", "", "d,s(t)", 0x20000087, 0xfc0007ff, RD_1|RD_2|RD_3, 0, 0, xNMS},
+{"sc", "", "t,+p(b)", 0xa4005900, 0xfc007f03, MOD_1|RD_3, 0, I38, 0},
+{"sc", "", "t,A(c)", 0, (int) M_SC_AC, INSN_MACRO, 0, I38, 0},
+{"sce", "", "t,+p(b)", 0xa4005a00, 0xfc007f03, MOD_1|RD_3, 0, 0, EVA},
+{"sce", "", "t,A(c)", 0, (int) M_SCE_AC, INSN_MACRO, 0, 0, EVA},
+{"scwp", "", "t,e,(b),-K", 0xa4005901, 0xfc007f03, MOD_1|WR_2|RD_3, 0, 0, xNMS},
+{"scwp", "", "t,e,A(c)", 0, (int) M_SCWP_AC, INSN_MACRO, 0, 0, xNMS},
+{"scwpe", "", "t,e,(b),-K", 0xa4005a01, 0xfc007f03, MOD_1|WR_2|RD_3, 0, 0, EVA},
+{"scwpe", "", "t,e,A(c)", 0, (int) M_SCWP_AC, INSN_MACRO, 0, 0, EVA},
+{"sd", "", "t,A(c)", 0, (int) M_SD_AC, INSN_MACRO, 0, I38, 0},
+{"sd", "", "t,A(b)", 0, (int) M_SDX_AB, INSN_MACRO, 0, I38, 0},
+{"seb", "", "t,r,-N", 0x20000008, 0xfc0003ff, WR_1|RD_2, 0, 0, xNMS},
+{"seh", "", "t,r,-N", 0x20000048, 0xfc0003ff, WR_1|RD_2, 0, I38, 0},
+{"seqi", "", "t,r,i", 0x80006000, 0xfc00f000, WR_1|RD_2, 0, I38, 0},
+{"seq", "", "d,v,t", 0, (int) M_SEQ, INSN_MACRO, 0, I38, 0},
+{"seq", "", "d,v,I", 0, (int) M_SEQ_I, INSN_MACRO, 0, I38, 0},
+{"sge", "", "d,v,t", 0, (int) M_SGE, INSN_MACRO, 0, I38, 0},
+{"sge", "", "d,v,I", 0, (int) M_SGE_I, INSN_MACRO, 0, I38, 0},
+{"sgeu", "", "d,v,t", 0, (int) M_SGEU, INSN_MACRO, 0, I38, 0},
+{"sgeu", "", "d,v,I", 0, (int) M_SGEU_I, INSN_MACRO, 0, I38, 0},
+{"sgt", "", "d,v,t", 0, (int) M_SGT, INSN_MACRO, 0, I38, 0},
+{"sgt", "", "d,v,I", 0, (int) M_SGT_I, INSN_MACRO, 0, I38, 0},
+{"sgtu", "", "d,v,t", 0, (int) M_SGTU, INSN_MACRO, 0, I38, 0},
+{"sgtu", "", "d,v,I", 0, (int) M_SGTU_I, INSN_MACRO, 0, I38, 0},
+{"sh", "[16]", "mm,mH(ml)", 0x7c01, 0xfc09, RD_1|RD_3, 0, I38, 0}, /* SH[16] */
+{"sh", "[gp]", "t,+3(ma)", 0x44140000, 0xfc1c0001, RD_1|RD_3, 0, I38, 0}, /* SH[GP] */
+{"sh", "[u12]", "t,o(b)", 0x84005000, 0xfc00f000, RD_1|RD_3, 0, I38, 0}, /* SH[U12] */
+{"sh", "[s9]", "t,+j(b)", 0xa4002800, 0xfc007f00, RD_1|RD_3, 0, I38, 0}, /* SH[S9] */
+{"sh", "", "t,A(c)", 0, (int) M_SH_AC, INSN_MACRO, 0, I38, 0},
+{"sh", "", "t,A(b)", 0, (int) M_SHX_AB, INSN_MACRO, 0, 0, xNMS}, /* SHX */
+{"she", "", "t,+j(b)", 0xa4002a00, 0xfc007f00, RD_1|RD_3, 0, 0, EVA},
+{"she", "", "t,A(c)", 0, (int) M_SHE_AC, INSN_MACRO, 0, 0, EVA},
+{"shilo", "", "7,0,-P", 0x2000001d, 0xfc0003ff, MOD_1, 0, 0, D32},
+{"shilov", "", "7,s,-I", 0x2000127f, 0xfc003fff, MOD_1|RD_2, 0, 0, D32},
+{"shll.ph", "", "t,s,4", 0x200003b5, 0xfc000fff, WR_1|RD_2, 0, 0, D32},
+{"shll.qb", "", "t,s,3", 0x2000087f, 0xfc001fff, WR_1|RD_2, 0, 0, D32},
+{"shllv.ph", "", "d,t,s", 0x2000038d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"shllv.qb", "", "d,t,s,-B", 0x20000395, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"shllv_s.ph", "", "d,t,s", 0x2000078d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"shllv_s.w", "", "d,t,s,-B", 0x200003d5, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"shll_s.ph", "", "t,s,4", 0x20000bb5, 0xfc000fff, WR_1|RD_2, 0, 0, D32},
+{"shll_s.w", "", "t,s,1,-B", 0x200003f5, 0xfc0003ff, WR_1|RD_2, 0, 0, D32},
+{"shra.ph", "", "t,s,4", 0x20000335, 0xfc000fff, WR_1|RD_2, 0, 0, D32},
+{"shra.qb", "", "t,s,3", 0x200001ff, 0xfc001fff, WR_1|RD_2, 0, 0, D32},
+{"shrav.ph", "", "d,t,s", 0x2000018d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"shrav.qb", "", "d,t,s", 0x200001cd, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"shrav_r.ph", "", "d,t,s", 0x2000058d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"shrav_r.qb", "", "d,t,s", 0x200005cd, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"shrav_r.w", "", "d,t,s,-B", 0x200002d5, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"shra_r.ph", "", "t,s,4,-Q", 0x20000735, 0xfc0007ff, WR_1|RD_2, 0, 0, D32},
+{"shra_r.qb", "", "t,s,3", 0x200011ff, 0xfc001fff, WR_1|RD_2, 0, 0, D32},
+{"shra_r.w", "", "t,s,1,-B", 0x200002f5, 0xfc0003ff, WR_1|RD_2, 0, 0, D32},
+{"shrl.ph", "", "t,s,4", 0x200003ff, 0xfc000fff, WR_1|RD_2, 0, 0, D32},
+{"shrl.qb", "", "t,s,3", 0x2000187f, 0xfc001fff, WR_1|RD_2, 0, 0, D32},
+{"shrlv.ph", "", "d,t,s,-B", 0x20000315, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"shrlv.qb", "", "d,t,s,-B", 0x20000355, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"shx", "", "d,s(t)", 0x20000287, 0xfc0007ff, RD_1|RD_2|RD_3, 0, 0, xNMS},
+{"shxs", "", "d,s(t)", 0x200002c7, 0xfc0007ff, RD_1|RD_2|RD_3, 0, 0, xNMS},
+{"sync_wmb", "", "", 0x8004c006, 0xffffffff, 0, INSN2_ALIAS, I38, 0}, /* SYNC */
+{"sync_mb", "", "", 0x8010c006, 0xffffffff, 0, INSN2_ALIAS, I38, 0}, /* SYNC */
+{"sync_acquire", "", "", 0x8011c006, 0xffffffff, 0, INSN2_ALIAS, I38, 0}, /* SYNC */
+{"sync_release", "", "", 0x8012c006, 0xffffffff, 0, INSN2_ALIAS, I38, 0}, /* SYNC */
+{"sync_rmb", "", "", 0x8013c006, 0xffffffff, 0, INSN2_ALIAS, I38, 0}, /* SYNC */
+{"sync_ginv", "", "", 0x8014c006, 0xffffffff, 0, INSN2_ALIAS, 0, GINV}, /* SYNC */
+{"sync", "", "", 0x8000c006, 0xffffffff, 0, INSN2_ALIAS, I38, 0}, /* SYNC */
+{"sync", "", "+i,-M", 0x8000c006, 0xffe0f1ff, 0, 0, I38, 0},
+{"sle", "", "d,v,t", 0, (int) M_SLE, INSN_MACRO, 0, I38, 0},
+{"sle", "", "d,v,I", 0, (int) M_SLE_I, INSN_MACRO, 0, I38, 0},
+{"sleu", "", "d,v,t", 0, (int) M_SLEU, INSN_MACRO, 0, I38, 0},
+{"sleu", "", "d,v,I", 0, (int) M_SLEU_I, INSN_MACRO, 0, I38, 0},
+{"sllv", "", "d,s,t,-B", 0x20000010, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"sll", "[16]", "md,mc,mM", 0x3000, 0xfc08, WR_1|RD_2, 0, I38, 0}, /* SLL[16] */
+{"sll", "[32]", "t,r,<,-M", 0x8000c000, 0xfc00f1e0, WR_1|RD_2, 0, I38, 0}, /* preceded by EHB, PAUSE, SYNC */
+{"sll", "[32]", "d,v,t", 0x20000010, 0xfc0007ff, WR_1|RD_2|RD_3, INSN2_ALIAS, I38, 0}, /* SLLV */
+{"slt", "", "d,v,t,-B", 0x20000350, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"slt", "", "d,v,I", 0, (int) M_SLT_I, INSN_MACRO, 0, I38, 0},
+{"slti", "", "t,r,i", 0x80004000, 0xfc00f000, WR_1|RD_2, 0, I38, 0},
+{"sltiu", "", "t,r,i", 0x80005000, 0xfc00f000, WR_1|RD_2, 0, I38, 0},
+{"sltu", "", "d,v,t,-B", 0x20000390, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0}, /* preceded by DVP */
+{"sltu", "", "d,v,I", 0, (int) M_SLTU_I, INSN_MACRO, 0, I38, 0},
+{"sne", "", "d,v,t", 0, (int) M_SNE, INSN_MACRO, 0, I38, 0},
+{"sne", "", "d,v,I", 0, (int) M_SNE_I, INSN_MACRO, 0, I38, 0},
+{"sov", "", "d,v,t,-B", 0x200003d0, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"srav", "", "d,s,t,-B", 0x20000090, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"sra", "", "t,r,<,-M", 0x8000c080, 0xfc00f1e0, WR_1|RD_2, 0, I38, 0},
+{"sra", "", "d,v,t", 0x20000090, 0xfc0007ff, WR_1|RD_2|RD_3, INSN2_ALIAS, I38, 0}, /* SRAV */
+{"srlv", "", "d,s,t,-B", 0x20000050, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"srl", "[16]", "md,mc,mM", 0x3008, 0xfc08, WR_1|RD_2, 0, I38, 0}, /* SRL[16] */
+{"srl", "[32]", "t,r,<,-M", 0x8000c040, 0xfc00f1e0, WR_1|RD_2, 0, I38, 0},
+{"srl", "[32]", "d,v,t", 0x20000050, 0xfc0007ff, WR_1|RD_2|RD_3, INSN2_ALIAS, I38, 0}, /* SRLV */
+{"sub", "", "d,v,t,-B", 0x20000190, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, xNMS},
+{"sub", "", "t,r,I", 0, (int) M_SUB_I, INSN_MACRO, 0, 0, xNMS},
+{"subq.ph", "", "d,s,t", 0x2000020d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"subqh.ph", "", "d,s,t", 0x2000024d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"subqh.w", "", "d,s,t", 0x2000028d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"subqh_r.ph", "", "d,s,t", 0x2000064d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"subqh_r.w", "", "d,s,t", 0x2000068d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"subq_s.ph", "", "d,s,t", 0x2000060d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"subq_s.w", "", "d,s,t,-B", 0x20000345, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"subu", "[16]", "me,mc,md", 0xb001, 0xfc01, WR_1|RD_2|RD_3, 0, I38, 0}, /* SUBU[16] */
+{"subu", "[32]", "d,v,t,-B", 0x200001d0, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"subu", "", "d,v,I", 0, (int) M_SUBU_I, INSN_MACRO, 0, I38, 0},
+{"subu.ph", "", "d,s,t", 0x2000030d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"subu.qb", "", "d,s,t", 0x200002cd, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"subuh.qb", "", "d,s,t", 0x2000034d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"subuh_r.qb", "", "d,s,t", 0x2000074d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"subu_s.ph", "", "d,s,t", 0x2000070d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"subu_s.qb", "", "d,s,t", 0x200006cd, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32},
+{"sw", "[16]", "mm,mJ(ml)", 0x9400, 0xfc00, RD_1|RD_3, 0, I38, 0}, /* SW[16] */
+{"sw", "[sp]", "mp,mR(ms)", 0xb400, 0xfc00, RD_1|RD_3, 0, I38, 0}, /* SW[SP] */
+{"sw", "[4x4]", "mw,mN(mv)", 0xf400, 0xfc00, RD_1|RD_3, 0, 0, xNMS}, /* SW[4X4] */
+{"sw", "[gp16]", "mm,mO(ma)", 0xd400, 0xfc00, RD_1|RD_3, 0, I38, 0}, /* SW[GP16] */
+{"sw", "[gp]", "t,.(ma)", 0x40000003, 0xfc000003, RD_1|RD_3, 0, I38, 0}, /* SW[GP] */
+{"sw", "[gp16]", "mm,mA(ma)", 0xd400, 0xfc00, RD_1|RD_3, 0, I38, 0}, /* SW[GP16] */
+{"sw", "[u12]", "t,o(b)", 0x84009000, 0xfc00f000, RD_1|RD_3, 0, I38, 0}, /* SW[U12] */
+{"sw", "[s9]", "t,+j(b)", 0xa4004800, 0xfc007f00, RD_1|RD_3, 0, I38, 0}, /* SW[S9] */
+{"sw", "", "t,A(c)", 0, (int) M_SW_AC, INSN_MACRO, 0, I38, 0},
+{"sw", "", "t,A(b)", 0, (int) M_SWX_AB, INSN_MACRO, 0, 0, xNMS}, /* SWX */
+{"swe", "", "t,+j(b)", 0xa4004a00, 0xfc007f00, RD_1|RD_3, 0, 0, EVA},
+{"swe", "", "t,A(c)", 0, (int) M_SWE_AC, INSN_MACRO, 0, 0, EVA},
+{"swm", "", "t,+j(b),|", 0xa4000c00, 0xfc000f00, RD_1|RD_3, 0, 0, xNMS}, /* SWM */
+{"swpc", "[48]", "mp,+S", 0x600f, 0xfc1f, WR_1, 0, 0, xNMS}, /* SWPC[48] */
+{"swx", "", "d,s(t)", 0x20000487, 0xfc0007ff, RD_1|RD_2|RD_3, 0, 0, xNMS},
+{"swxs", "", "d,s(t)", 0x200004c7, 0xfc0007ff, RD_1|RD_2|RD_3, 0, 0, xNMS},
+{"syscall", "[16]", "", 0x1008, 0xffff, 0, INSN2_ALIAS, I38, 0}, /* SYSCALL[16] */
+{"syscall", "[16]", "mP", 0x1008, 0xfffc, 0, 0, I38, 0}, /* SYSCALL[16] */
+{"syscall", "[32]", "", 0x00080000, 0xffffffff, 0, INSN2_ALIAS, I38, 0},
+{"syscall", "[32]", "+M", 0x00080000, 0xfffc0000, 0, 0, I38, 0},
+{"teq", "", "s,t", 0x20000000, 0xfc00ffff, RD_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* TEQ */
+{"teq", "", "s,t,^", 0x20000000, 0xfc0007ff, RD_1|RD_2, 0, 0, xNMS}, /* TEQ */
+{"teq", "", "s,I", 0, (int) M_TEQ_I, INSN_MACRO, 0, 0, xNMS},
+{"tne", "", "s,t", 0x20000400, 0xfc00ffff, RD_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* TNE */
+{"tne", "", "s,t,^", 0x20000400, 0xfc0007ff, RD_1|RD_2, 0, 0, xNMS}, /* TNE */
+{"tne", "", "s,I", 0, (int) M_TNE_I, INSN_MACRO, 0, 0, xNMS},
+{"tlbinv", "", "-F", 0x2000077f, 0xfc00ffff, 0, 0, 0, TLB},
+{"tlbinvf", "", "-F", 0x2000177f, 0xfc00ffff, 0, 0, 0, TLB},
+{"tlbp", "", "-F", 0x2000037f, 0xfc00ffff, 0, 0, 0, TLB},
+{"tlbr", "", "-F", 0x2000137f, 0xfc00ffff, 0, 0, 0, TLB},
+{"tlbwi", "", "-F", 0x2000237f, 0xfc00ffff, 0, 0, 0, TLB},
+{"tlbwr", "", "-F", 0x2000337f, 0xfc00ffff, 0, 0, 0, TLB},
+{"ualh", "", "t,+j(b)", 0xa4002100, 0xfc007f00, WR_1|RD_3, 0, 0, xNMS},
+{"ualw", "", "t,+j(b)", 0xa4001500, 0xfc007f00, WR_1|RD_3, INSN2_ALIAS, 0, xNMS}, /* UALWM */
+{"ualwm", "", "t,+j(b),|", 0xa4000500, 0xfc000f00, WR_1|RD_3, 0, 0, xNMS}, /* UALWM */
+{"uash", "", "t,+j(b)", 0xa4002900, 0xfc007f00, RD_1|RD_3, 0, 0, xNMS},
+{"uasw", "", "t,+j(b)", 0xa4001d00, 0xfc007f00, RD_1|RD_3, INSN2_ALIAS, 0, xNMS}, /* UASWM */
+{"uaswm", "", "t,+j(b),|", 0xa4000d00, 0xfc000f00, RD_1|RD_3, 0, 0, xNMS}, /* UASWM */
+{"uld", "", "t,A(c)", 0, (int) M_ULD_AC, INSN_MACRO, 0, 0, xNMS},
+{"ulh", "", "t,A(c)", 0, (int) M_ULH_AC, INSN_MACRO, 0, 0, xNMS},
+{"ulw", "", "t,A(c)", 0, (int) M_ULW_AC, INSN_MACRO, 0, 0, xNMS},
+{"usd", "", "t,A(c)", 0, (int) M_USD_AC, INSN_MACRO, 0, 0, xNMS},
+{"ush", "", "t,A(c)", 0, (int) M_USH_AC, INSN_MACRO, 0, 0, xNMS},
+{"usw", "", "t,A(c)", 0, (int) M_USW_AC, INSN_MACRO, 0, 0, xNMS},
+{"wait", "", "", 0x2000c37f, 0xffffffff, 0, INSN2_ALIAS, I38, 0},
+{"wait", "", "+L", 0x2000c37f, 0xfc00ffff, 0, 0, I38, 0},
+{"wrdsp", "", "t", 0x201fd67f, 0xfc1fffff, RD_1, INSN2_ALIAS, 0, D32},
+{"wrdsp", "", "t,8", 0x2000167f, 0xfc003fff, RD_1, 0, 0, D32},
+{"wrpgpr", "", "t,r", 0x2000f17f, 0xfc00ffff, WR_1|RD_2, 0, I38, 0},
+{"xor", "[16]", "md,mk,ml", 0x5004, 0xfc0f, WR_1|RD_3, INSN2_ALIAS, I38, 0}, /* XOR[16] */
+{"xor", "[16]", "md,ml,mk", 0x5004, 0xfc0f, WR_1|RD_2, INSN2_ALIAS, I38, 0}, /* XOR[16] */
+{"xor", "[16]", "md,ml", 0x5004, 0xfc0f, WR_1|RD_2, 0, I38, 0}, /* XOR[16] */
+{"xor", "[32]", "d,v,t,-B", 0x20000310, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0},
+{"xor", "", "t,r,I", 0, (int) M_XOR_I, INSN_MACRO, 0, I38, 0},
+{"xori", "", "t,r,g", 0x80001000, 0xfc00f000, WR_1|RD_2, 0, I38, 0},
+{"yield", "", "s", 0x20000268, 0xffe0ffff, RD_1, INSN2_ALIAS, 0, MT32},
+{"yield", "", "t,s,-N", 0x20000268, 0xfc0003ff, WR_1|RD_2, 0, 0, MT32},
+};
+
+const int bfd_nanomips_num_opcodes =
+ ((sizeof nanomips_opcodes) / (sizeof (nanomips_opcodes[0])));
--
2.25.1
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 2/3] sim: Add nanoMIPS port
[not found] <20220429155813.388328-1-aleksandar.rikalo@syrmia.com>
2022-04-29 15:58 ` [PATCH 1/3] bfd: Add support for nanoMIPS architecture Aleksandar Rikalo
@ 2022-04-29 15:58 ` Aleksandar Rikalo
2022-05-04 12:45 ` Mike Frysinger
2022-11-21 11:06 ` [PATCH v3 1/2] " Aleksandar Rikalo
2022-04-29 15:58 ` [PATCH 3/3] gdb: " Aleksandar Rikalo
2 siblings, 2 replies; 14+ messages in thread
From: Aleksandar Rikalo @ 2022-04-29 15:58 UTC (permalink / raw)
To: gdb-patches
Co-Authored-By: Jaydeep Patil <jaydeep.patil@imgtec.com>
Co-Authored-By: Matthew Fortune <matthew.fortune@imgtec.com>
Co-Authored-By: Maciej W. Rozycki <macro@mips.com>
Co-Authored-By: Stefan Markovic <stefan.markovic@mips.com>
Co-Authored-By: Sara Graovac <sara.graovac@syrmia.com>
Co-Authored-By: Dragan Mladjenovic <dragan.mladjenovic@syrmia.com>
---
sim/common/sim-bits.h | 4 +
sim/configure | 8 +
sim/mips/Makefile.in | 42 +
sim/mips/configure | 71 +
sim/mips/configure.ac | 28 +
sim/mips/interp.c | 75 +-
sim/mips/micromips.igen | 22 +-
sim/mips/micromips16.dc | 3 +
sim/mips/mips.igen | 441 +++--
sim/mips/nanomipsdsp.igen | 1116 +++++++++++++
sim/mips/nanomipsr6.igen | 3283 +++++++++++++++++++++++++++++++++++++
sim/mips/nanomipsrun.c | 109 ++
sim/mips/nms.c | 44 +
sim/mips/sim-main.c | 87 +-
sim/mips/sim-main.h | 154 +-
15 files changed, 5321 insertions(+), 166 deletions(-)
create mode 100644 sim/mips/nanomipsdsp.igen
create mode 100644 sim/mips/nanomipsr6.igen
create mode 100644 sim/mips/nanomipsrun.c
create mode 100644 sim/mips/nms.c
diff --git a/sim/common/sim-bits.h b/sim/common/sim-bits.h
index fab1dab478c..8799916de26 100644
--- a/sim/common/sim-bits.h
+++ b/sim/common/sim-bits.h
@@ -499,15 +499,19 @@ INLINE_SIM_BITS(unsigned_word) MSINSERTED (unsigned_word val, int start, int sto
#define EXTEND4(X) (LSSEXT ((X), 3))
#define EXTEND5(X) (LSSEXT ((X), 4))
#define EXTEND6(X) (LSSEXT ((X), 5))
+#define EXTEND7(X) (LSSEXT ((X), 6))
#define EXTEND8(X) ((signed_word)(int8_t)(X))
#define EXTEND9(X) (LSSEXT ((X), 8))
+#define EXTEND10(X) (LSSEXT ((X), 9))
#define EXTEND11(X) (LSSEXT ((X), 10))
#define EXTEND12(X) (LSSEXT ((X), 11))
+#define EXTEND14(X) (LSSEXT ((X), 13))
#define EXTEND15(X) (LSSEXT ((X), 14))
#define EXTEND16(X) ((signed_word)(int16_t)(X))
#define EXTEND18(X) (LSSEXT ((X), 17))
#define EXTEND19(X) (LSSEXT ((X), 18))
#define EXTEND21(X) (LSSEXT ((X), 20))
+#define EXTEND22(X) (LSSEXT ((X), 21))
#define EXTEND24(X) (LSSEXT ((X), 23))
#define EXTEND25(X) (LSSEXT ((X), 24))
#define EXTEND26(X) (LSSEXT ((X), 25))
diff --git a/sim/configure b/sim/configure
index b31c2f5d8f3..cc2d957192f 100755
--- a/sim/configure
+++ b/sim/configure
@@ -15298,6 +15298,14 @@ fi
sim_enable_arch_mips=true
sim_igen=yes
;;
+ nanomips*-*-*)
+
+ sim_arch=mips
+ subdirs="$subdirs mips"
+
+ sim_igen=yes
+ ;;
+
esac
diff --git a/sim/mips/Makefile.in b/sim/mips/Makefile.in
index 75438be5a18..6bf2d14bdef 100644
--- a/sim/mips/Makefile.in
+++ b/sim/mips/Makefile.in
@@ -61,6 +61,7 @@ SIM_OBJS = \
cp1.o \
mdmx.o \
dsp.o \
+ nms.o \
sim-main.o \
sim-resume.o \
@@ -79,6 +80,20 @@ SIM_EXTRA_DEPS = itable.h
## COMMON_POST_CONFIG_FRAG
+interp.o: $(srcdir)/interp.c sim-main.h itable.h
+
+m16run.o: sim-main.h m16_idecode.h m32_idecode.h m16run.c $(SIM_EXTRA_DEPS)
+
+micromipsrun.o: sim-main.h micromips16_idecode.h micromips32_idecode.h \
+ micromips_m32_idecode.h micromipsrun.c $(SIM_EXTRA_DEPS)
+
+nms.o: $(srcdir)/nms.c $(srcdir)/sim-main.h
+
+multi-run.o: multi-include.h tmp-mach-multi
+
+../igen/igen:
+ cd ../igen && $(MAKE)
+
IGEN_TRACE= # -G omit-line-numbers # -G trace-rule-selection -G trace-rule-rejection -G trace-entries # -G trace-all
IGEN_INSN=$(srcdir)/mips.igen
IGEN_DC=$(srcdir)/mips.dc
@@ -99,6 +114,8 @@ IGEN_INCLUDE=\
$(srcdir)/dsp2.igen \
$(srcdir)/mips3264r2.igen \
$(srcdir)/mips3264r6.igen \
+ $(srcdir)/nanomipsdsp.igen \
+ $(srcdir)/nanomipsr6.igen
# NB: Since these can be built by a number of generators, care
# must be taken to ensure that they are only dependant on
@@ -463,8 +480,11 @@ tmp-mach-multi: $(IGEN_INSN) $(IGEN_DC) $(IGEN) $(IGEN_INCLUDE)
f=`echo $${t} | sed -e 's/.*://'` ; \
case $${p} in \
micromips16*) e="-B 16 -H 15 -o $(MICROMIPS16_DC) -F 16" ;; \
+ nanomips16*) e="-B 16 -H 15 -o $(MICROMIPS16_DC) -F 16" ;; \
micromips32* | micromips64*) \
e="-B 32 -H 31 -o $(MICROMIPS32_DC) -F $${f}" ;; \
+ nanomips32* | nanomips64*) \
+ e="-B 32 -H 31 -o $(MICROMIPS32_DC) -F $${f}" ;; \
micromips_m32*) \
e="-B 32 -H 31 -o $(IGEN_DC) -F $${f}"; \
m="mips32r2,mips3d,mdmx,dsp,dsp2,smartmips" ;; \
@@ -579,6 +599,28 @@ tmp-run-multi: $(srcdir)/m16run.c $(srcdir)/micromipsrun.c
$(SHELL) $(srcdir)/../../move-if-change tmp-run \
micromips$${m}_run.c ; \
;;\
+ nanomips32*) \
+ m=`echo $${t} | sed -e 's/^nanomips32//' -e 's/:.*//'`; \
+ sed < $(srcdir)/nanomipsrun.c > tmp-run \
+ -e "s/^sim_/nanomips32$${m}_/" \
+ -e "s/nanomips_instruction_decode/nanomips32$${m}_instruction_decode/g" \
+ -e "s/nanomips16_/nanomips16$${m}_/" \
+ -e "s/nanomips32_/nanomips32$${m}_/" \
+ -e "s/m32_/m32$${m}_/" ; \
+ $(SHELL) $(srcdir)/../../move-if-change tmp-run \
+ nanomips$${m}_run.c ; \
+ ;;\
+ nanomips64*) \
+ m=`echo $${t} | sed -e 's/^nanomips64//' -e 's/:.*//'`; \
+ sed < $(srcdir)/nanomipsrun.c > tmp-run \
+ -e "s/^sim_/nanomips64$${m}_/" \
+ -e "s/nanomips_instruction_decode/nanomips64$${m}_instruction_decode/g" \
+ -e "s/nanomips16_/nanomips16$${m}_/" \
+ -e "s/nanomips32_/nanomips64$${m}_/" \
+ -e "s/m32_/m64$${m}_/" ; \
+ $(SHELL) $(srcdir)/../../move-if-change tmp-run \
+ nanomips$${m}_run.c ; \
+ ;;\
esac \
done
$(SILENCE) touch $@
diff --git a/sim/mips/configure b/sim/mips/configure
index 2f635a50e10..1438951b5d1 100755
--- a/sim/mips/configure
+++ b/sim/mips/configure
@@ -1874,6 +1874,12 @@ case "${target}" in
mipsisa64r6:mips64r6:32,64,f:mipsisa32r6,mipsisa64r6"
sim_multi_default=mipsisa64r2
;;
+ nanomips*-elf*)
+ sim_gen=MULTI
+ sim_multi_configs="\
+ nanor6sim:nanomips64r6,nanomipsdsp:32,64,f:nanomipsisa64r6,nanomipsisa32r6"
+ sim_multi_default=nanomipsisa32r6
+ ;;
mips64*-*-*) sim_igen_filter="32,64,f"
sim_gen=IGEN
;;
@@ -2072,6 +2078,17 @@ __EOF__
sim_multi_obj="${sim_multi_obj} micromips${name}_run.o"
sim_multi_flags="${sim_multi_flags} -F 16,32"
;;
+ *:*nanomips32*)
+ # Run igen twice, once for nanomips32 and once for nanomips16.
+ ws="nanomips16 nanomips32"
+
+ # The top-level function for the micromips simulator is
+ # in a file micromips${name}_run.c, generated by the
+ # tmp-run-multi Makefile rule.
+ sim_multi_src="${sim_multi_src} nanomips${name}_run.c"
+ sim_multi_obj="${sim_multi_obj} nanomips${name}_run.o"
+ sim_multi_flags="${sim_multi_flags} -F 16,32"
+ ;;
*:*micromips64*:*)
# Run igen thrice, once for micromips64, once for micromips16,
# and once for m64.
@@ -2084,6 +2101,17 @@ __EOF__
sim_multi_obj="${sim_multi_obj} micromips${name}_run.o"
sim_multi_flags="${sim_multi_flags} -F 16,32,64"
;;
+ *:*nanomips64*)
+ # Run igen twice, once for nanomips64 and once for nanomips16.
+ ws="nanomips16 nanomips64"
+
+ # The top-level function for the micromips simulator is
+ # in a file micromips${name}_run.c, generated by the
+ # tmp-run-multi Makefile rule.
+ sim_multi_src="${sim_multi_src} nanomips${name}_run.c"
+ sim_multi_obj="${sim_multi_obj} nanomips${name}_run.o"
+ sim_multi_flags="${sim_multi_flags} -F 16,32,64"
+ ;;
*)
ws=m32
;;
@@ -2126,6 +2154,8 @@ __EOF__
}
}
+int
+mips_mach_multi (SIM_DESC sd);
int
mips_mach_multi (SIM_DESC sd)
{
@@ -2155,6 +2185,47 @@ __EOF__
return bfd_mach_${sim_multi_default};
}
}
+
+address_word
+micromips_instruction_decode_multi (SIM_DESC sd,
+ sim_cpu* cpu,
+ address_word cia,
+ int instruction_size)
+{
+ unsigned long bfdmach;
+ if (STATE_ARCHITECTURE(SD) == NULL)
+ bfdmach = bfd_mach_${sim_multi_default};
+ else
+ bfdmach = STATE_ARCHITECTURE(SD)->mach;
+
+ switch (bfdmach)
+ {
+__EOF__
+
+ # Add a case statement for each micromips-enabled engine
+ for fc in ${micromips_configs}; do
+ machine=`echo ${fc} | sed 's/.*:\(.*\):.*:.*:.*:.*/\1/'`
+ name=`echo ${fc} | sed 's/:.*//'`
+ bfdmachs=`echo ${fc} | sed 's/.*:.*:.*:.*:\(.*\):.*/\1/'`
+ case ${machine} in
+ micromips*)
+ for bfdmach in `echo ${bfdmachs} | sed 's/,/ /g'`; do
+ echo " case bfd_mach_${bfdmach}:" >> multi-run.c
+ done
+ echo " return ${name}_instruction_decode (sd, cpu, cia, instruction_size);" >> multi-run.c
+ ;;
+ *)
+ ;;
+ esac
+ done
+
+ cat << __EOF__ >> multi-run.c
+ default:
+ fprintf(stderr, "no valid micromips instruction decoder for this micromips engine\n");
+ abort();
+ break;
+ }
+}
__EOF__
SIM_SUBTARGET="$SIM_SUBTARGET -DMIPS_MACH_MULTI"
diff --git a/sim/mips/configure.ac b/sim/mips/configure.ac
index 96806424958..0d48b9630d9 100644
--- a/sim/mips/configure.ac
+++ b/sim/mips/configure.ac
@@ -106,6 +106,12 @@ case "${target}" in
mipsisa64r6:mips64r6:32,64,f:mipsisa32r6,mipsisa64r6"
sim_multi_default=mipsisa64r2
;;
+ nanomips*-*-elf*)
+ sim_gen=MULTI
+ sim_multi_configs="\
+ nanor6sim:nanomips64r6,nanomipsdsp:32,64,f:nanomipsisa64r6,nanomipsisa32r6"
+ sim_multi_default=nanomipsisa64r6
+ ;;
mips64*-*-*) sim_igen_filter="32,64,f"
sim_gen=IGEN
;;
@@ -304,6 +310,17 @@ __EOF__
sim_multi_obj="${sim_multi_obj} micromips${name}_run.o"
sim_multi_flags="${sim_multi_flags} -F 16,32"
;;
+ *:*nanomips32*)
+ # Run igen twice, once for nanomips32 and once for nanomips16.
+ ws="nanomips16 nanomips32"
+
+ # The top-level function for the micromips simulator is
+ # in a file micromips${name}_run.c, generated by the
+ # tmp-run-multi Makefile rule.
+ sim_multi_src="${sim_multi_src} nanomips${name}_run.c"
+ sim_multi_obj="${sim_multi_obj} nanomips${name}_run.o"
+ sim_multi_flags="${sim_multi_flags} -F 16,32"
+ ;;
*:*micromips64*:*)
# Run igen thrice, once for micromips64, once for micromips16,
# and once for m64.
@@ -316,6 +333,17 @@ __EOF__
sim_multi_obj="${sim_multi_obj} micromips${name}_run.o"
sim_multi_flags="${sim_multi_flags} -F 16,32,64"
;;
+ *:*nanomips64*)
+ # Run igen twice, once for nanomips64 and once for nanomips16.
+ ws="nanomips16 nanomips64"
+
+ # The top-level function for the micromips simulator is
+ # in a file micromips${name}_run.c, generated by the
+ # tmp-run-multi Makefile rule.
+ sim_multi_src="${sim_multi_src} nanomips${name}_run.c"
+ sim_multi_obj="${sim_multi_obj} nanomips${name}_run.o"
+ sim_multi_flags="${sim_multi_flags} -F 16,32,64"
+ ;;
*)
ws=m32
;;
diff --git a/sim/mips/interp.c b/sim/mips/interp.c
index c5d0901428b..eba56df0a3e 100644
--- a/sim/mips/interp.c
+++ b/sim/mips/interp.c
@@ -140,6 +140,7 @@ static SIM_ADDR lsipmon_monitor_base = 0xBFC00200;
static SIM_RC sim_firmware_command (SIM_DESC sd, char* arg);
+int is_nanomips = 0;
#define MEM_SIZE (8 << 20) /* 8 MBytes */
@@ -672,10 +673,13 @@ sim_open (SIM_OPEN_KIND kind, host_callback *cb,
cpu->register_widths[rn] = WITH_TARGET_FLOATING_POINT_BITSIZE;
else if ((rn >= 33) && (rn <= 37))
cpu->register_widths[rn] = WITH_TARGET_WORD_BITSIZE;
+ else if ((rn >= 70) && (rn <= 78))
+ cpu->register_widths[rn] = WITH_TARGET_WORD_BITSIZE;
else if ((rn == SRIDX)
|| (rn == FCR0IDX)
|| (rn == FCR31IDX)
- || ((rn >= 72) && (rn <= 89)))
+ || (rn == DSPCRIDX)
+ || ((rn >= 80) && (rn <= 89)))
cpu->register_widths[rn] = 32;
else
cpu->register_widths[rn] = 0;
@@ -1200,7 +1204,7 @@ sim_monitor (SIM_DESC sd,
case 6: /* int open(char *path,int flags) */
{
char *path = fetch_str (sd, A0);
- V0 = sim_io_open (sd, path, (int)A1);
+ SET_RV0 (sim_io_open (sd, path, (int)A1));
free (path);
break;
}
@@ -1210,7 +1214,7 @@ sim_monitor (SIM_DESC sd,
int fd = A0;
int nr = A2;
char *buf = zalloc (nr);
- V0 = sim_io_read (sd, fd, buf, nr);
+ SET_RV0 (sim_io_read (sd, fd, buf, nr));
sim_write (sd, A1, (unsigned char *)buf, nr);
free (buf);
}
@@ -1222,7 +1226,7 @@ sim_monitor (SIM_DESC sd,
int nr = A2;
char *buf = zalloc (nr);
sim_read (sd, A1, (unsigned char *)buf, nr);
- V0 = sim_io_write (sd, fd, buf, nr);
+ SET_RV0 (sim_io_write (sd, fd, buf, nr));
if (fd == 1)
sim_io_flush_stdout (sd);
else if (fd == 2)
@@ -1233,14 +1237,14 @@ sim_monitor (SIM_DESC sd,
case 10: /* int close(int file) */
{
- V0 = sim_io_close (sd, (int)A0);
+ SET_RV0 (sim_io_close (sd, (int)A0));
break;
}
case 2: /* Densan monitor: char inbyte(int waitflag) */
{
if (A0 == 0) /* waitflag == NOWAIT */
- V0 = (unsigned_word)-1;
+ SET_RV0 ((unsigned_word)-1);
}
/* Drop through to case 11 */
@@ -1252,10 +1256,10 @@ sim_monitor (SIM_DESC sd,
if (sim_io_read_stdin (sd, &tmp, sizeof(char)) != sizeof(char))
{
sim_io_error(sd,"Invalid return from character read");
- V0 = (unsigned_word)-1;
+ SET_RV0 ((unsigned_word)-1);
}
else
- V0 = (unsigned_word)tmp;
+ SET_RV0 ((unsigned_word)tmp);
break;
}
@@ -1531,21 +1535,26 @@ store_word (SIM_DESC sd,
uword64 vaddr,
signed_word val)
{
- address_word paddr = vaddr;
+ address_word paddr;
+ int uncached;
if ((vaddr & 3) != 0)
SignalExceptionAddressStore ();
else
{
- const uword64 mask = 7;
- uword64 memval;
- unsigned int byte;
-
- paddr = (paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2));
- byte = (vaddr & mask) ^ (BigEndianCPU << 2);
- memval = ((uword64) val) << (8 * byte);
- StoreMemory (AccessLength_WORD, memval, 0, paddr, vaddr,
- isREAL);
+ if (AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached,
+ isTARGET, isREAL))
+ {
+ const uword64 mask = 7;
+ uword64 memval;
+ unsigned int byte;
+
+ paddr = (paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2));
+ byte = (vaddr & mask) ^ (BigEndianCPU << 2);
+ memval = ((uword64) val) << (8 * byte);
+ StoreMemory (uncached, AccessLength_WORD, memval, 0, paddr, vaddr,
+ isREAL);
+ }
}
}
@@ -1567,18 +1576,24 @@ load_word (SIM_DESC sd,
}
else
{
- address_word paddr = vaddr;
- const uword64 mask = 0x7;
- const unsigned int reverse = ReverseEndian ? 1 : 0;
- const unsigned int bigend = BigEndianCPU ? 1 : 0;
- uword64 memval;
- unsigned int byte;
-
- paddr = (paddr & ~mask) | ((paddr & mask) ^ (reverse << 2));
- LoadMemory (&memval, NULL, AccessLength_WORD, paddr, vaddr, isDATA,
- isREAL);
- byte = (vaddr & mask) ^ (bigend << 2);
- return EXTEND32 (memval >> (8 * byte));
+ address_word paddr;
+ int uncached;
+
+ if (AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached,
+ isTARGET, isREAL))
+ {
+ const uword64 mask = 0x7;
+ const unsigned int reverse = ReverseEndian ? 1 : 0;
+ const unsigned int bigend = BigEndianCPU ? 1 : 0;
+ uword64 memval;
+ unsigned int byte;
+
+ paddr = (paddr & ~mask) | ((paddr & mask) ^ (reverse << 2));
+ LoadMemory (&memval,NULL,uncached, AccessLength_WORD, paddr, vaddr,
+ isDATA, isREAL);
+ byte = (vaddr & mask) ^ (bigend << 2);
+ return EXTEND32 (memval >> (8 * byte));
+ }
}
return 0;
diff --git a/sim/mips/micromips.igen b/sim/mips/micromips.igen
index bb61b3f26e6..55545403a4b 100644
--- a/sim/mips/micromips.igen
+++ b/sim/mips/micromips.igen
@@ -42,6 +42,7 @@
*micromips32:
*micromips64:
*micromipsdsp:
+*nanomipsdsp:
{
instruction_word delay_insn;
sim_events_slip (SD, 1);
@@ -49,7 +50,7 @@
CIA = nia;
STATE |= simDELAYSLOT;
ENGINE_ISSUE_PREFIX_HOOK();
- micromips_instruction_decode (SD, CPU, CIA, delayslot_instruction_size);
+ MICROMIPS_INSTRUCTION_DECODE (SD, CPU, CIA, delayslot_instruction_size);
STATE &= ~simDELAYSLOT;
return target;
}
@@ -128,6 +129,8 @@
:function:::FP_formats:convert_fmt_micromips:int fmt
*micromips32:
*micromips64:
+*nanomips32r6:
+*nanomips64r6:
{
switch (fmt)
{
@@ -141,6 +144,8 @@
:function:::FP_formats:convert_fmt_micromips_cvt_d:int fmt
*micromips32:
*micromips64:
+*nanomips32r6:
+*nanomips64r6:
{
switch (fmt)
{
@@ -155,6 +160,8 @@
:function:::FP_formats:convert_fmt_micromips_cvt_s:int fmt
*micromips32:
*micromips64:
+*nanomips32r6:
+*nanomips64r6:
{
switch (fmt)
{
@@ -865,8 +872,11 @@
address_word base = GPR[BASE];
address_word offset = EXTEND12 (IMMEDIATE);
address_word vaddr = loadstore_ea (SD_, base, offset);
- address_word paddr = vaddr;
- CacheOp (OP, vaddr, paddr, instruction_0);
+ address_word paddr;
+ int uncached;
+ if (AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached,
+ isTARGET, isREAL))
+ CacheOp (OP, vaddr, paddr, instruction_0);
}
@@ -2275,6 +2285,8 @@
:%s::::FMT_MICROMIPS:int fmt
*micromips32:
*micromips64:
+*nanomips32r6:
+*nanomips64r6:
{
switch (fmt)
{
@@ -2289,6 +2301,8 @@
:%s::::FMT_MICROMIPS_CVT_D:int fmt
*micromips32:
*micromips64:
+*nanomips32r6:
+*nanomips64r6:
{
switch (fmt)
{
@@ -2303,6 +2317,8 @@
:%s::::FMT_MICROMIPS_CVT_S:int fmt
*micromips32:
*micromips64:
+*nanomips32r6:
+*nanomips64r6:
{
switch (fmt)
{
diff --git a/sim/mips/micromips16.dc b/sim/mips/micromips16.dc
index a1cd9a0ea89..ace9bb94fad 100644
--- a/sim/mips/micromips16.dc
+++ b/sim/mips/micromips16.dc
@@ -8,4 +8,7 @@
switch,combine : 9 : 6 : : : : : :
switch,combine : 9 : 5 : : : : : :
+ switch,combine : 3 : 0 : : : : : :
+ switch,combine : 2 : 0 : : : : : :
+ switch,combine : 5 : 3 : : : : : :
switch,combine : 0 : 0 : : : : : :
diff --git a/sim/mips/mips.igen b/sim/mips/mips.igen
index dfad4227615..8f427ce258b 100644
--- a/sim/mips/mips.igen
+++ b/sim/mips/mips.igen
@@ -79,6 +79,9 @@
:model:::micromips32:micromips64: // micromips.igen
:model:::micromips64:micromips64: // micromips.igen
:model:::micromipsdsp:micromipsdsp: // micromipsdsp.igen
+:model:::nanomips32r6:nanomips32r6: // nanomipsr6.igen
+:model:::nanomips64r6:nanomips64r6: // nanomipsr6.igen
+:model:::nanomipsdsp:nanomipsdsp: // nanompsdsp.igen
// Vendor Extensions
//
@@ -98,6 +101,31 @@
// For grep - RSVD_INSTRUCTION, RSVD_INSTRUCTION_MASK
000000,5.*,5.*,5.*,5.OP,111001:SPECIAL:32::RSVD
"rsvd <OP>"
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips32:
+*mips32r2:
+*mips64:
+*mips64r2:
+*vr4100:
+*vr4120:
+*vr5000:
+*vr5400:
+*vr5500:
+*r3900:
+*mips16:
+*mips16e:
+*mips3d:
+*mdmx:
+*dsp:
+*dsp2:
+*smartmips:
+*micromips32:
+*micromips64:
+*micromipsdsp:
{
SignalException (ReservedInstruction, instruction_0);
}
@@ -192,6 +220,7 @@
*vr5000:
*r3900:
*micromips32:
+*nanomips32r6:
{
return base + offset;
}
@@ -201,6 +230,7 @@
*mips64r2:
*micromips64:
*mips64r6:
+*nanomips64r6:
{
#if 0 /* XXX FIXME: enable this only after some additional testing. */
/* If in user mode and UX is not set, use 32-bit compatibility effective
@@ -237,6 +267,8 @@
*micromips32:
*micromips64:
*mips64r6:
+*nanomips32r6:
+*nanomips64r6:
{
#if WITH_TARGET_WORD_BITSIZE == 64
return value != (((value & 0xffffffff) ^ 0x80000000) - 0x80000000);
@@ -274,6 +306,8 @@
*micromips32:
*micromips64:
*mips64r6:
+*nanomips32r6:
+*nanomips64r6:
{
unpredictable_action (CPU, CIA);
}
@@ -369,6 +403,7 @@
*r3900:
*micromips32:
*micromips64:
+*nanomipsdsp:
{
int64_t time = sim_events_time (SD);
history->mt.timestamp = time;
@@ -399,6 +434,7 @@
*r3900:
*micromips32:
*micromips64:
+*nanomipsdsp:
{
int64_t time = sim_events_time (SD);
int ok = 1;
@@ -473,6 +509,7 @@
*r3900:
*micromips32:
*micromips64:
+*nanomipsdsp:
{
/* FIXME: could record the fact that a stall occured if we want */
int64_t time = sim_events_time (SD);
@@ -570,6 +607,8 @@
*micromips64:
*micromips32:
*mips64r6:
+*nanomips32r6:
+*nanomips64r6:
{
#if 0 /* XXX FIXME: enable this only after some additional testing. */
if (UserMode && (SR & (status_UX|status_PX)) == 0)
@@ -781,12 +820,44 @@
}
:function:::void:do_lb:int rt, int offset, int base
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips32:
+*mips32r2:
+*mips32r6:
+*mips64:
+*mips64r2:
+*mips64r6:
+*vr4100:
+*vr5000:
+*r3900:
+*micromips32:
+*micromips64:
{
GPR[rt] = EXTEND8 (do_load (SD_, AccessLength_BYTE, GPR[base],
EXTEND16 (offset)));
}
:function:::void:do_lh:int rt, int offset, int base
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips32:
+*mips32r2:
+*mips32r6:
+*mips64:
+*mips64r2:
+*mips64r6:
+*vr4100:
+*vr5000:
+*r3900:
+*micromips32:
+*micromips64:
{
GPR[rt] = EXTEND16 (do_load (SD_, AccessLength_HALFWORD, GPR[base],
EXTEND16 (offset)));
@@ -811,6 +882,22 @@
}
:function:::void:do_lw:int rt, int offset, int base
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips32:
+*mips32r2:
+*mips32r6:
+*mips64:
+*mips64r2:
+*mips64r6:
+*vr4100:
+*vr5000:
+*r3900:
+*micromips32:
+*micromips64:
{
GPR[rt] = EXTEND32 (do_load (SD_, AccessLength_WORD, GPR[base],
EXTEND16 (offset)));
@@ -823,6 +910,22 @@
}
:function:::void:do_lhu:int rt, int offset, int base
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips32:
+*mips32r2:
+*mips32r6:
+*mips64:
+*mips64r2:
+*mips64r6:
+*vr4100:
+*vr5000:
+*r3900:
+*micromips32:
+*micromips64:
{
GPR[rt] = do_load (SD_, AccessLength_HALFWORD, GPR[base], EXTEND16 (offset));
}
@@ -844,7 +947,8 @@
address_word offset = EXTEND16 (insn_offset);
{
address_word vaddr = loadstore_ea (SD_, base, offset);
- address_word paddr = vaddr;
+ address_word paddr;
+ int uncached;
if ((vaddr & 3) != 0)
{
SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 4, vaddr, read_transfer,
@@ -852,19 +956,23 @@
}
else
{
- uint64_t memval = 0;
- uint64_t memval1 = 0;
- uint64_t mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3);
- unsigned int shift = 2;
- unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);
- unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);
- unsigned int byte;
- paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));
- LoadMemory (&memval, &memval1, AccessLength_WORD, paddr, vaddr,
- isDATA, isREAL);
- byte = ((vaddr & mask) ^ (bigend << shift));
- GPR[rt] = EXTEND32 (memval >> (8 * byte));
- LLBIT = 1;
+ if (AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached,
+ isTARGET, isREAL))
+ {
+ uint64_t memval = 0;
+ uint64_t memval1 = 0;
+ uint64_t mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3);
+ unsigned int shift = 2;
+ unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);
+ unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);
+ unsigned int byte;
+ paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));
+ LoadMemory (&memval, &memval1, uncached, AccessLength_WORD, paddr,
+ vaddr, isDATA, isREAL);
+ byte = ((vaddr & mask) ^ (bigend << shift));
+ GPR[rt] = EXTEND32 (memval >> (8 * byte));
+ LLBIT = 1;
+ }
}
}
}
@@ -875,8 +983,8 @@
address_word offset = EXTEND16 (roffset);
{
address_word vaddr = loadstore_ea (SD_, base, offset);
- address_word paddr = vaddr;
-
+ address_word paddr;
+ int uncached;
if ((vaddr & 7) != 0)
{
SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 8, vaddr, read_transfer,
@@ -884,12 +992,16 @@
}
else
{
- uint64_t memval = 0;
- uint64_t memval1 = 0;
- LoadMemory (&memval, &memval1, AccessLength_DOUBLEWORD, paddr, vaddr,
- isDATA, isREAL);
- GPR[rt] = memval;
- LLBIT = 1;
+ if (AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached,
+ isTARGET, isREAL))
+ {
+ uint64_t memval = 0;
+ uint64_t memval1 = 0;
+ LoadMemory (&memval, &memval1, uncached, AccessLength_DOUBLEWORD,
+ paddr, vaddr, isDATA, isREAL);
+ GPR[rt] = memval;
+ LLBIT = 1;
+ }
}
}
}
@@ -1137,8 +1249,13 @@
address_word offset = EXTEND16 (insn_offset);
{
address_word vaddr = loadstore_ea (SD_, base, offset);
- address_word paddr = vaddr;
- /* Prefetch (paddr, vaddr, isDATA, hint); */
+ address_word paddr;
+ int uncached;
+ {
+ if (AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached,
+ isTARGET, isREAL))
+ Prefetch (uncached, paddr, vaddr, isDATA, hint);
+ }
}
}
@@ -1149,8 +1266,8 @@
address_word offset = EXTEND16 (offsetarg);
{
address_word vaddr = loadstore_ea (SD_, base, offset);
- address_word paddr = vaddr;
-
+ address_word paddr;
+ int uncached;
if ((vaddr & 3) != 0)
{
SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 4, vaddr, write_transfer,
@@ -1158,23 +1275,27 @@
}
else
{
- uint64_t memval = 0;
- uint64_t memval1 = 0;
- uint64_t mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3);
- address_word reverseendian =
- (ReverseEndian ? (mask ^ AccessLength_WORD) : 0);
- address_word bigendiancpu =
- (BigEndianCPU ? (mask ^ AccessLength_WORD) : 0);
- unsigned int byte;
- paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
- byte = ((vaddr & mask) ^ bigendiancpu);
- memval = ((uint64_t) GPR[rt] << (8 * byte));
- if (LLBIT)
- StoreMemory (AccessLength_WORD, memval, memval1, paddr, vaddr,
- isREAL);
- if (store_ll_bit)
- GPR[rt] = LLBIT;
- }
+ if (AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached,
+ isTARGET, isREAL))
+ {
+ uint64_t memval = 0;
+ uint64_t memval1 = 0;
+ uint64_t mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3);
+ address_word reverseendian =
+ (ReverseEndian ? (mask ^ AccessLength_WORD) : 0);
+ address_word bigendiancpu =
+ (BigEndianCPU ? (mask ^ AccessLength_WORD) : 0);
+ unsigned int byte;
+ paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
+ byte = ((vaddr & mask) ^ bigendiancpu);
+ memval = ((uint64_t) GPR[rt] << (8 * byte));
+ if (LLBIT)
+ StoreMemory (uncached, AccessLength_WORD, memval, memval1, paddr, vaddr,
+ isREAL);
+ if (store_ll_bit)
+ GPR[rt] = LLBIT;
+ }
+ }
}
}
@@ -1184,8 +1305,8 @@
address_word offset = EXTEND16 (roffset);
{
address_word vaddr = loadstore_ea (SD_, base, offset);
- address_word paddr = vaddr;
-
+ address_word paddr;
+ int uncached;
if ((vaddr & 7) != 0)
{
SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 8, vaddr, write_transfer,
@@ -1193,15 +1314,19 @@
}
else
{
+ if (AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached,
+ isTARGET, isREAL))
+ {
uint64_t memval = 0;
uint64_t memval1 = 0;
memval = GPR[rt];
if (LLBIT)
- StoreMemory (AccessLength_DOUBLEWORD, memval, memval1, paddr, vaddr,
+ StoreMemory (uncached, AccessLength_DOUBLEWORD, memval, memval1, paddr, vaddr,
isREAL);
if (store_ll_bit)
GPR[rt] = LLBIT;
}
+ }
}
}
@@ -1688,8 +1813,11 @@
address_word index = GPR[rindex];
{
address_word vaddr = loadstore_ea (SD_, base, index);
- address_word paddr = vaddr;
- /* Prefetch (paddr, vaddr, isDATA, hint); */
+ address_word paddr;
+ int uncached;
+ if (AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached, isTARGET,
+ isREAL))
+ Prefetch (uncached, paddr, vaddr, isDATA, hint);
}
}
@@ -1753,8 +1881,8 @@
check_fpu (SD_);
{
address_word vaddr = loadstore_ea (SD_, base, offset);
- address_word paddr = vaddr;
-
+ address_word paddr;
+ int uncached;
if ((vaddr & 3) != 0)
{
SIM_CORE_SIGNAL (SD, CPU, cia, read_map, AccessLength_WORD+1, vaddr,
@@ -1762,18 +1890,23 @@
}
else
{
- uword64 memval = 0;
- uword64 memval1 = 0;
- uword64 mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3);
- address_word reverseendian =
- (ReverseEndian ? (mask ^ AccessLength_WORD) : 0);
- address_word bigendiancpu =
- (BigEndianCPU ? (mask ^ AccessLength_WORD) : 0);
- unsigned int byte;
- paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
- byte = ((vaddr & mask) ^ bigendiancpu);
- memval = (((uword64)COP_SW(1, ft)) << (8 * byte));
- StoreMemory (AccessLength_WORD, memval, memval1, paddr, vaddr, isREAL);
+ if (AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached,
+ isTARGET, isREAL))
+ {
+ uword64 memval = 0;
+ uword64 memval1 = 0;
+ uword64 mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3);
+ address_word reverseendian =
+ (ReverseEndian ?(mask ^ AccessLength_WORD): 0);
+ address_word bigendiancpu =
+ (BigEndianCPU ?(mask ^ AccessLength_WORD): 0);
+ unsigned int byte;
+ paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
+ byte = ((vaddr & mask) ^ bigendiancpu);
+ memval = (((uword64)COP_SW(1, ft)) << (8 * byte));
+ StoreMemory (uncached, AccessLength_WORD, memval, memval1, paddr,
+ vaddr, isREAL);
+ }
}
}
}
@@ -1786,8 +1919,8 @@
check_u64 (SD_, instruction_0);
{
address_word vaddr = loadstore_ea (SD_, base, index);
- address_word paddr = vaddr;
-
+ address_word paddr;
+ int uncached;
if ((vaddr & 3) != 0)
{
SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 4, vaddr, write_transfer,
@@ -1795,19 +1928,23 @@
}
else
{
- uint64_t memval = 0;
- uint64_t memval1 = 0;
- uint64_t mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3);
- address_word reverseendian =
- (ReverseEndian ? (mask ^ AccessLength_WORD) : 0);
- address_word bigendiancpu =
- (BigEndianCPU ? (mask ^ AccessLength_WORD) : 0);
- unsigned int byte;
- paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
- byte = ((vaddr & mask) ^ bigendiancpu);
- memval = (((uint64_t)COP_SW(1,fs)) << (8 * byte));
- StoreMemory (AccessLength_WORD, memval, memval1, paddr, vaddr,
- isREAL);
+ if (AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached,
+ isTARGET, isREAL))
+ {
+ uint64_t memval = 0;
+ uint64_t memval1 = 0;
+ uint64_t mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3);
+ address_word reverseendian =
+ (ReverseEndian ? (mask ^ AccessLength_WORD) : 0);
+ address_word bigendiancpu =
+ (BigEndianCPU ? (mask ^ AccessLength_WORD) : 0);
+ unsigned int byte;
+ paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
+ byte = ((vaddr & mask) ^ bigendiancpu);
+ memval = (((uint64_t)COP_SW(1,fs)) << (8 * byte));
+ StoreMemory (uncached, AccessLength_WORD, memval, memval1, paddr,
+ vaddr, isREAL);
+ }
}
}
}
@@ -1861,7 +1998,23 @@
-:function:::void:do_addiu:int rs, int rt, uint16_t immediate
+:function:::void:do_addiu:int rs, int rt, int immediate
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips32:
+*mips32r2:
+*mips32r6:
+*mips64:
+*mips64r2:
+*mips64r6:
+*vr4100:
+*vr5000:
+*r3900:
+*micromips32:
+*micromips64:
{
if (NotWordValue (GPR[rs]))
Unpredictable ();
@@ -2595,6 +2748,14 @@
:function:::void:do_ddiv:int rs, int rt
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips64:
+*mips64r2:
+*micromips64:
+*vr4100:
+*vr5000:
{
check_div_hilo (SD_, HIHISTORY, LOHISTORY);
TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
@@ -2641,6 +2802,14 @@
:function:::void:do_ddivu:int rs, int rt
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips64:
+*mips64r2:
+*micromips64:
+*vr4100:
+*vr5000:
{
check_div_hilo (SD_, HIHISTORY, LOHISTORY);
TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
@@ -2680,6 +2849,20 @@
}
:function:::void:do_div:int rs, int rt
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips32:
+*mips32r2:
+*micromips32:
+*mips64:
+*mips64r2:
+*micromips64:
+*vr4100:
+*vr5000:
+*r3900:
{
check_div_hilo (SD_, HIHISTORY, LOHISTORY);
TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
@@ -2726,6 +2909,20 @@
:function:::void:do_divu:int rs, int rt
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips32:
+*mips32r2:
+*micromips32:
+*mips64:
+*mips64r2:
+*micromips64:
+*vr4100:
+*vr5000:
+*r3900:
{
check_div_hilo (SD_, HIHISTORY, LOHISTORY);
TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
@@ -3277,16 +3474,18 @@
address_word bigendiancpu = (BigEndianCPU ? (mask ^ access) : 0);
unsigned int byte;
address_word paddr;
+ int uncached;
uint64_t memval;
address_word vaddr;
- paddr = vaddr = loadstore_ea (SD_, base, offset);
+ vaddr = loadstore_ea (SD_, base, offset);
if ((vaddr & access) != 0)
{
SIM_CORE_SIGNAL (SD, STATE_CPU (SD, 0), cia, read_map, access+1, vaddr, read_transfer, sim_core_unaligned_signal);
}
+ AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached, isTARGET, isREAL);
paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
- LoadMemory (&memval, NULL, access, paddr, vaddr, isDATA, isREAL);
+ LoadMemory (&memval, NULL, uncached, access, paddr, vaddr, isDATA, isREAL);
byte = ((vaddr & mask) ^ bigendiancpu);
return (memval >> (8 * byte));
}
@@ -3299,6 +3498,7 @@
unsigned int byte;
unsigned int word;
address_word paddr;
+ int uncached;
uint64_t memval;
address_word vaddr;
int nr_lhs_bits;
@@ -3306,7 +3506,8 @@
unsigned_word lhs_mask;
unsigned_word temp;
- paddr = vaddr = loadstore_ea (SD_, base, offset);
+ vaddr = loadstore_ea (SD_, base, offset);
+ AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached, isTARGET, isREAL);
paddr = (paddr ^ (reverseendian & mask));
if (BigEndianMem == 0)
paddr = paddr & ~access;
@@ -3323,7 +3524,7 @@
(long) ((uint64_t) paddr >> 32), (long) paddr,
word, byte, nr_lhs_bits, nr_rhs_bits); */
- LoadMemory (&memval, NULL, byte, paddr, vaddr, isDATA, isREAL);
+ LoadMemory (&memval, NULL, uncached, byte, paddr, vaddr, isDATA, isREAL);
if (word == 0)
{
/* GPR{31..32-NR_LHS_BITS} = memval{NR_LHS_BITS-1..0} */
@@ -3352,17 +3553,19 @@
address_word bigendiancpu = (BigEndianCPU ? -1 : 0);
unsigned int byte;
address_word paddr;
+ int uncached;
uint64_t memval;
address_word vaddr;
- paddr = vaddr = loadstore_ea (SD_, base, offset);
+ vaddr = loadstore_ea (SD_, base, offset);
+ AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached, isTARGET, isREAL);
/* NOTE: SPEC is wrong, has `BigEndianMem == 0' not `BigEndianMem != 0' */
paddr = (paddr ^ (reverseendian & mask));
if (BigEndianMem != 0)
paddr = paddr & ~access;
byte = ((vaddr & mask) ^ (bigendiancpu & mask));
/* NOTE: SPEC is wrong, had `byte' not `access - byte'. See SW. */
- LoadMemory (&memval, NULL, access - (access & byte), paddr, vaddr, isDATA, isREAL);
+ LoadMemory (&memval, NULL, uncached, access - (access & byte), paddr, vaddr, isDATA, isREAL);
/* printf ("lr: 0x%08lx %d@0x%08lx 0x%08lx\n",
(long) paddr, byte, (long) paddr, (long) memval); */
{
@@ -3714,6 +3917,23 @@
:function:::void:do_mfhi:int rd
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*vr4100:
+*vr5000:
+*r3900:
+*mips32:
+*mips64:
+*mips32r2:
+*mips64r2:
+*dsp:
+*micromips32:
+*micromips64:
+*micromipsdsp:
+*nanomipsdsp:
{
check_mf_hilo (SD_, HIHISTORY, LOHISTORY);
TRACE_ALU_INPUT1 (HI);
@@ -4175,18 +4395,20 @@
address_word bigendiancpu = (BigEndianCPU ? (mask ^ access) : 0);
unsigned int byte;
address_word paddr;
+ int uncached;
uint64_t memval;
address_word vaddr;
- paddr = vaddr = loadstore_ea (SD_, base, offset);
+ vaddr = loadstore_ea (SD_, base, offset);
if ((vaddr & access) != 0)
{
SIM_CORE_SIGNAL (SD, STATE_CPU(SD, 0), cia, read_map, access+1, vaddr, write_transfer, sim_core_unaligned_signal);
}
+ AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached, isTARGET, isREAL);
paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
byte = ((vaddr & mask) ^ bigendiancpu);
memval = (word << (8 * byte));
- StoreMemory (access, memval, 0, paddr, vaddr, isREAL);
+ StoreMemory (uncached, access, memval, 0, paddr, vaddr, isREAL);
}
:function:::void:do_store_left:unsigned access, address_word base, address_word offset, unsigned_word rt
@@ -4197,12 +4419,14 @@
unsigned int byte;
unsigned int word;
address_word paddr;
+ int uncached;
uint64_t memval;
address_word vaddr;
int nr_lhs_bits;
int nr_rhs_bits;
- paddr = vaddr = loadstore_ea (SD_, base, offset);
+ vaddr = loadstore_ea (SD_, base, offset);
+ AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached, isTARGET, isREAL);
paddr = (paddr ^ (reverseendian & mask));
if (BigEndianMem == 0)
paddr = paddr & ~access;
@@ -4229,7 +4453,7 @@
/* fprintf (stderr, "s[wd]l: 0x%08lx%08lx -> 0x%08lx%08lx\n",
(long) ((uint64_t) rt >> 32), (long) rt,
(long) ((uint64_t) memval >> 32), (long) memval); */
- StoreMemory (byte, memval, 0, paddr, vaddr, isREAL);
+ StoreMemory (uncached, byte, memval, 0, paddr, vaddr, isREAL);
}
:function:::void:do_store_right:unsigned access, address_word base, address_word offset, unsigned_word rt
@@ -4239,16 +4463,18 @@
address_word bigendiancpu = (BigEndianCPU ? -1 : 0);
unsigned int byte;
address_word paddr;
+ int uncached;
uint64_t memval;
address_word vaddr;
- paddr = vaddr = loadstore_ea (SD_, base, offset);
+ vaddr = loadstore_ea (SD_, base, offset);
+ AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached, isTARGET, isREAL);
paddr = (paddr ^ (reverseendian & mask));
if (BigEndianMem != 0)
paddr &= ~access;
byte = ((vaddr & mask) ^ (bigendiancpu & mask));
memval = (rt << (byte * 8));
- StoreMemory (access - (access & byte), memval, 0, paddr, vaddr, isREAL);
+ StoreMemory (uncached, access - (access & byte), memval, 0, paddr, vaddr, isREAL);
}
@@ -5225,6 +5451,8 @@
*vr4100:
*vr5000:
*r3900:
+*nanomips32r6:
+*nanomips64r6:
{
/* None of these ISAs support Paired Single, so just fall back to
the single/double check. */
@@ -5273,6 +5501,8 @@
*r3900:
*micromips32:
*micromips64:
+*nanomips32r6:
+*nanomips64r6:
{
if (! COP_Usable (1))
SignalExceptionCoProcessorUnusable (1);
@@ -5316,20 +5546,24 @@
int bigendian = (BigEndianCPU ? ! ReverseEndian : ReverseEndian);
address_word vaddr;
address_word paddr;
+ int uncached;
uint64_t memval;
uint64_t v;
- paddr = vaddr = loadstore_ea (SD_, base, offset);
+ vaddr = loadstore_ea (SD_, base, offset);
if ((vaddr & AccessLength_DOUBLEWORD) != 0)
{
SIM_CORE_SIGNAL (SD, STATE_CPU (SD, 0), cia, read_map,
AccessLength_DOUBLEWORD + 1, vaddr, read_transfer,
sim_core_unaligned_signal);
}
- LoadMemory (&memval, NULL, AccessLength_WORD, paddr, vaddr, isDATA, isREAL);
+ AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached, isTARGET,
+ isREAL);
+ LoadMemory (&memval, NULL, uncached, AccessLength_WORD, paddr, vaddr,
+ isDATA, isREAL);
v = (uint64_t)memval;
- LoadMemory (&memval, NULL, AccessLength_WORD, paddr + 4, vaddr + 4, isDATA,
- isREAL);
+ LoadMemory (&memval, NULL, uncached, AccessLength_WORD, paddr + 4, vaddr + 4,
+ isDATA, isREAL);
return (bigendian ? ((v << 32) | memval) : (v | (memval << 32)));
}
@@ -5351,19 +5585,24 @@
int bigendian = (BigEndianCPU ? ! ReverseEndian : ReverseEndian);
address_word vaddr;
address_word paddr;
+ int uncached;
uint64_t memval;
- paddr = vaddr = loadstore_ea (SD_, base, offset);
+ vaddr = loadstore_ea (SD_, base, offset);
if ((vaddr & AccessLength_DOUBLEWORD) != 0)
{
SIM_CORE_SIGNAL (SD, STATE_CPU(SD, 0), cia, read_map,
AccessLength_DOUBLEWORD + 1, vaddr, write_transfer,
sim_core_unaligned_signal);
}
+ AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached, isTARGET,
+ isREAL);
memval = (bigendian ? (v >> 32) : (v & 0xFFFFFFFF));
- StoreMemory (AccessLength_WORD, memval, 0, paddr, vaddr, isREAL);
+ StoreMemory (uncached, AccessLength_WORD, memval, 0, paddr, vaddr,
+ isREAL);
memval = (bigendian ? (v & 0xFFFFFFFF) : (v >> 32));
- StoreMemory (AccessLength_WORD, memval, 0, paddr + 4, vaddr + 4, isREAL);
+ StoreMemory (uncached, AccessLength_WORD, memval, 0, paddr + 4, vaddr + 4,
+ isREAL);
}
@@ -6628,7 +6867,10 @@
{
address_word vaddr = loadstore_ea (SD_, base, offset);
address_word paddr = vaddr;
- CacheOp(op, vaddr, paddr, instruction_0);
+
+ int uncached;
+ if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))
+ CacheOp(op, vaddr, paddr, instruction_0);
}
}
@@ -6867,4 +7109,5 @@
:include:::smartmips.igen
:include:::micromips.igen
:include:::micromipsdsp.igen
-
+:include:::nanomipsr6.igen
+:include:::nanomipsdsp.igen
diff --git a/sim/mips/nanomipsdsp.igen b/sim/mips/nanomipsdsp.igen
new file mode 100644
index 00000000000..65d0282f325
--- /dev/null
+++ b/sim/mips/nanomipsdsp.igen
@@ -0,0 +1,1116 @@
+// Simulator definition for the micromips ASE.
+// Copyright (C) 2018-2022 Free Software Foundation, Inc.
+// Contributed by Imagination Technologies, Ltd.
+// Written by Ali Lown <ali.lown@imgtec.com>
+//
+// This file is part of GDB, the GNU debugger.
+//
+// This program 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 of the License, or
+// (at your option) any later version.
+//
+// This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+
+001000,5.RT,5.RS,0001000100111111:POOL32A:32::ABSQ_S.PH
+"absq_s.ph r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_ph_s_absq (SD_, RT, RS);
+}
+
+001000,5.RT,5.RS,0000000100111111:POOL32A:32::ABSQ_S.QB
+"absq_s.qb r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_qb_s_absq (SD_, RT, RS);
+}
+
+001000,5.RT,5.RS,0010000100111111:POOL32A:32::ABSQ_S.W
+"absq_s.w r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_w_s_absq (SD_, RT, RS);
+}
+
+001000,5.RT,5.RS,5.RD,00000001101:POOL32A:32::ADDQ.PH
+"addq.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_op (SD_, RD, RS, RT, 0, 0);
+}
+
+001000,5.RT,5.RS,5.RD,10000001101:POOL32A:32::ADDQ_S.PH
+"addq_s.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_op (SD_, RD, RS, RT, 0, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1100000101:POOL32A:32::ADDQ_S.W
+"addq_s.w r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_w_op (SD_, RD, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,5.RD,00001001101:POOL32A:32::ADDQH.PH
+"addqh.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qh_ph_op (SD_, RD, RS, RT, 0, 0);
+}
+
+001000,5.RT,5.RS,5.RD,10001001101:POOL32A:32::ADDQH_R.PH
+"addqh_r.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qh_ph_op (SD_, RD, RS, RT, 0, 1);
+}
+
+001000,5.RT,5.RS,5.RD,00010001101:POOL32A:32::ADDQH.W
+"addqh.w r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qh_w_op (SD_, RD, RS, RT, 0, 0);
+}
+
+001000,5.RT,5.RS,5.RD,10010001101:POOL32A:32::ADDQH_R.W
+"addqh_r.w r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qh_w_op (SD_, RD, RS, RT, 0, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1110000101:POOL32A:32::ADDSC
+"addsc r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_addsc (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,5.RD,00100001101:POOL32A:32::ADDU.PH
+"addu.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_u_ph_op (SD_, RD, RS, RT, 0, 0);
+}
+
+001000,5.RT,5.RS,5.RD,10100001101:POOL32A:32::ADDU_S.PH
+"addu_s.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_u_ph_op (SD_, RD, RS, RT, 0, 1);
+}
+
+001000,5.RT,5.RS,5.RD,00011001101:POOL32A:32::ADDU.QB
+"addu.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qb_op (SD_, RD, RS, RT, 0, 0);
+}
+
+001000,5.RT,5.RS,5.RD,10011001101:POOL32A:32::ADDU_S.QB
+"addu_s.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qb_op (SD_, RD, RS, RT, 0, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1111000101:POOL32A:32::ADDWC
+"addwc r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_addwc (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,5.RD,00101001101:POOL32A:32::ADDUH.QB
+"adduh.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_uh_qb_op (SD_, RD, RS, RT, 0, 0);
+}
+
+001000,5.RT,5.RS,5.RD,10101001101:POOL32A:32::ADDUH_R.QB
+"adduh_r.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_uh_qb_op (SD_, RD, RS, RT, 0, 1);
+}
+
+001000,5.RT,5.RS,5.SA,1.X,1000010101:POOL32A:32::APPEND
+"append r<RT>, r<RS>, <SA>"
+*nanomipsdsp:
+{
+ do_append (SD_, RT, RS, SA);
+}
+
+001000,5.RT,5.RS,2.BP,00100010111111:POOL32A:32::BALIGN
+"balign r<RT>, r<RS>, <BP>"
+*nanomipsdsp:
+{
+ do_balign (SD_, RT, RS, BP);
+}
+
+001000,5.RT,5.RS,0011000100111111:POOL32A:32::BITREV
+"bitrev r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_bitrev (SD_, RT, RS);
+}
+
+100010,5.X,0010001,14.IMMEDIATE:POOL32I:32::BPOSGE32C
+"bposge32c <IMMEDIATE>"
+*nanomipsdsp:
+{
+ uint32_t pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK;
+ if (pos >= 32)
+ NIA = delayslot_micromips (SD_, NIA + (EXTEND12 (IMMEDIATE) << 1), NIA,
+ MICROMIPS_DELAYSLOT_SIZE_ANY);
+}
+
+001000,5.RT,5.RS,6.X,0000000101:POOL32A:32::CMP.EQ.PH
+"cmp.eq.ph r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_cmpu (SD_, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,0000000001,000101:POOL32A:32::CMP.LT.PH
+"cmp.lt.ph r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_cmpu (SD_, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,0000000010,000101:POOL32A:32::CMP.LE.PH
+"cmp.le.ph r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_cmpu (SD_, RS, RT, 2);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0110000101:POOL32A:32::CMPGDU.EQ.QB
+"cmpgdu.eq.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qb_cmpgdu (SD_, RD, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0111000101:POOL32A:32::CMPGDU.LT.QB
+"cmpgdu.lt.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qb_cmpgdu (SD_, RD, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1000000101:POOL32A:32::CMPGDU.LE.QB
+"cmpgdu.le.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qb_cmpgdu (SD_, RD, RS, RT, 2);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0011000101:POOL32A:32::CMPGU.EQ.QB
+"cmpgu.eq.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qb_cmpgu (SD_, RD, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0100000101:POOL32A:32::CMPGU.LT.QB
+"cmpgu.lt.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qb_cmpgu (SD_, RD, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0101000101:POOL32A:32::CMPGU.LE.QB
+"cmpgu.le.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qb_cmpgu (SD_, RD, RS, RT, 2);
+}
+
+001000,5.RT,5.RS,5.X1,1.X2,1001000101:POOL32A:32::CMPU.EQ.QB
+"cmpu.eq.qb r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qb_cmpu (SD_, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,5.X1,1.X2,1010000101:POOL32A:32::CMPU.LT.QB
+"cmpu.lt.qb r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qb_cmpu (SD_, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,5.X1,1.X2,1011000101:POOL32A:32::CMPU.LE.QB
+"cmpu.le.qb r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qb_cmpu (SD_, RS, RT, 2);
+}
+
+001000,5.RT,5.RS,2.AC,00000010111111:POOL32A:32::DPA.W.PH
+"dpa.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_w_ph_dot_product (SD_, AC, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,2.AC,00001010111111:POOL32A:32::DPAQ_S.W.PH
+"dpaq_s.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_dot_product (SD_, AC, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,2.AC,01001010111111:POOL32A:32::DPAQ_SA.L.W
+"dpaq_sa.l.w ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_w_dot_product (SD_, AC, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,2.AC,10001010111111:POOL32A:32::DPAQX_S.W.PH
+"dpaqx_s.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qx_w_ph_dot_product (SD_, AC, RS, RT, 0, 0);
+}
+
+001000,5.RT,5.RS,2.AC,11001010111111:POOL32A:32::DPAQX_SA.W.PH
+"dpaqx_sa.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qx_w_ph_dot_product (SD_, AC, RS, RT, 0, 1);
+}
+
+001000,5.RT,5.RS,2.AC,10000010111111:POOL32A:32::DPAU.H.QBL
+"dpau.h.qbl ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qb_dot_product (SD_, AC, RS, RT, 0, 0);
+}
+
+001000,5.RT,5.RS,2.AC,11000010111111:POOL32A:32::DPAU.H.QBR
+"dpau.h.qbr ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qb_dot_product (SD_, AC, RS, RT, 0, 1);
+}
+
+001000,5.RT,5.RS,2.AC,01000010111111:POOL32A:32::DPAX.W.PH
+"dpax.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_x_w_ph_dot_product (SD_, AC, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,2.AC,00010010111111:POOL32A:32::DPS.W.PH
+"dps.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_w_ph_dot_product (SD_, AC, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,2.AC,00011010111111:POOL32A:32::DPSQ_S.W.PH
+"dpsq_s.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_dot_product (SD_, AC, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,2.AC,01011010111111:POOL32A:32::DPSQ_SA.L.W
+"dpsq_sa.l.w ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_w_dot_product (SD_, AC, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,2.AC,10011010111111:POOL32A:32::DPSQX_S.W.PH
+"dpsqx_s.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qx_w_ph_dot_product (SD_, AC, RS, RT, 1, 0);
+}
+
+001000,5.RT,5.RS,2.AC,11011010111111:POOL32A:32::DPSQX_SA.W.PH
+"dpsqx_sa.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qx_w_ph_dot_product (SD_, AC, RS, RT, 1, 1);
+}
+
+001000,5.RT,5.RS,2.AC,10010010111111:POOL32A:32::DPSU.H.QBL
+"dpsu.h.qbl ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qb_dot_product (SD_, AC, RS, RT, 1, 0);
+}
+
+001000,5.RT,5.RS,2.AC,11010010111111:POOL32A:32::DPSU.H.QBR
+"dpsu.h.qbr ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qb_dot_product (SD_, AC, RS, RT, 1, 1);
+}
+
+001000,5.RT,5.RS,2.AC,01010010111111:POOL32A:32::DPSX.W.PH
+"dpsx.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_x_w_ph_dot_product (SD_, AC, RS, RT, 1);
+}
+
+001000,5.RT,5.SIZE,2.AC,10011001111111:POOL32A:32::EXTP
+"extp r<RT>, ac<AC>, <SIZE>"
+*nanomipsdsp:
+{
+ do_extp (SD_, RT, AC, SIZE, 0);
+}
+
+001000,5.RT,5.SIZE,2.AC,11011001111111:POOL32A:32::EXTPDP
+"extpdp r<RT>, ac<AC>, <SIZE>"
+*nanomipsdsp:
+{
+ do_extp (SD_, RT, AC, SIZE, 1);
+}
+
+001000,5.RT,5.RS,2.AC,11100010111111:POOL32A:32::EXTPDPV
+"extpdpv r<RT>, ac<AC>, r<RS>"
+*nanomipsdsp:
+{
+ do_extpv (SD_, RT, AC, RS, 1);
+}
+
+001000,5.RT,5.RS,2.AC,10100010111111:POOL32A:32::EXTPV
+"extpv r<RT>, ac<AC>, r<RS>"
+*nanomipsdsp:
+{
+ do_extpv (SD_, RT, AC, RS, 0);
+}
+
+001000,5.RT,5.SHIFT,2.AC,00111001111111:POOL32A:32::EXTR.W
+"extr.w r<RT>, ac<AC>, <SHIFT>"
+*nanomipsdsp:
+{
+ do_w_extr (SD_, RT, AC, SHIFT, 0);
+}
+
+001000,5.RT,5.SHIFT,2.AC,01111001111111:POOL32A:32::EXTR_R.W
+"extr_r.w r<RT>, ac<AC>, <SHIFT>"
+*nanomipsdsp:
+{
+ do_w_extr (SD_, RT, AC, SHIFT, 1);
+}
+
+001000,5.RT,5.SHIFT,2.AC,10111001111111:POOL32A:32::EXTR_RS.W
+"extr_rs.w r<RT>, ac<AC>, <SHIFT>"
+*nanomipsdsp:
+{
+ do_w_extr (SD_, RT, AC, SHIFT, 2);
+}
+
+001000,5.RT,5.SHIFT,2.AC,11111001111111:POOL32A:32::EXTR_S.H
+"extr_s.h r<RT>, ac<AC>, <SHIFT>"
+*nanomipsdsp:
+{
+ do_h_extr (SD_, RT, AC, SHIFT);
+}
+
+001000,5.RT,5.RS,2.AC,00111010111111:POOL32A:32::EXTRV.W
+"extrv.w r<RT>, ac<AC>, r<RS>"
+*nanomipsdsp:
+{
+ do_extrv (SD_, RT, AC, RS, 0);
+}
+
+001000,5.RT,5.RS,2.AC,01111010111111:POOL32A:32::EXTRV_R.W
+"extrv_r.w r<RT>, ac<AC>, r<RS>"
+*nanomipsdsp:
+{
+ do_extrv (SD_, RT, AC, RS, 1);
+}
+
+001000,5.RT,5.RS,2.AC,10111010111111:POOL32A:32::EXTRV_RS.W
+"extrv_rs.w r<RT>, ac<AC>, r<RS>"
+*nanomipsdsp:
+{
+ do_extrv (SD_, RT, AC, RS, 2);
+}
+
+001000,5.RT,5.RS,2.AC,11111010111111:POOL32A:32::EXTRV_S.H
+"extrv_s.h r<RT>, ac<AC>, r<RS>"
+*nanomipsdsp:
+{
+ do_extrv_s_h (SD_, RT, AC, RS);
+}
+
+001000,5.RT,5.RS,0100000100111111:POOL32A:32::INSV
+"insv r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_insv (SD_, RT, RS);
+}
+
+001000,5.RT,5.RS,2.AC,00101010111111:POOL32A:32::MADD_DSP
+"madd ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_dsp_madd (SD_, AC, RS, RT);
+}
+
+001000,5.RT,5.RS,2.AC,01101010111111:POOL32A:32::MADDU_DSP
+"maddu ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_dsp_maddu (SD_, AC, RS, RT);
+}
+
+001000,5.RT,5.RS,2.AC,01101001111111:POOL32A:32::MAQ_S.W.PHL
+"maq_s.w.phl ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_maq (SD_, AC, RS, RT, 0, 0);
+}
+
+001000,5.RT,5.RS,2.AC,11101001111111:POOL32A:32::MAQ_SA.W.PHL
+"maq_sa.w.phl ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_maq (SD_, AC, RS, RT, 1, 0);
+}
+
+001000,5.RT,5.RS,2.AC,00101001111111:POOL32A:32::MAQ_S.W.PHR
+"maq_s.w.phr ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_maq (SD_, AC, RS, RT, 0, 1);
+}
+
+001000,5.RT,5.RS,2.AC,10101001111111:POOL32A:32::MAQ_SA.W.PHR
+"maq_sa.w.phr ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_maq (SD_, AC, RS, RT, 1, 1);
+}
+
+001000,5.RS,5.X,2.AC,00000001111111:POOL32A:32::MFHI_DSP
+"mfhi r<RS>, ac<AC>"
+*nanomipsdsp:
+{
+ do_dsp_mfhi (SD_, AC, RS);
+}
+
+001000,5.RS,5.X,2.AC,01000001111111:POOL32A:32::MFLO_DSP
+"mflo r<RS>, ac<AC>"
+*nanomipsdsp:
+{
+ do_dsp_mflo (SD_, AC, RS);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1010010101:POOL32A:32::MODSUB
+"modsub r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_modsub (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,2.AC,10101010111111:POOL32A:32::MSUB_DSP
+"msub ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_dsp_msub (SD_, AC, RS, RT);
+}
+
+001000,5.RT,5.RS,2.AC,11101010111111:POOL32A:32::MSUBU_DSP
+"msubu ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_dsp_msubu (SD_, AC, RS, RT);
+}
+
+001000,00000,5.RS,2.AC,10000001111111:POOL32A:32::MTHI_DSP
+"mthi r<RS>, ac<AC>"
+*nanomipsdsp:
+{
+ do_dsp_mthi (SD_, AC, RS);
+}
+
+001000,00000,5.RS,2.AC,00001001111111:POOL32A:32::MTHLIP
+"mthlip r<RS>, ac<AC>"
+*nanomipsdsp:
+{
+ do_mthlip (SD_, RS, AC);
+}
+
+001000,00000,5.RS,2.AC,11000001111111:POOL32A:32::MTLO_DSP
+"mtlo r<RS>, ac<AC>"
+*nanomipsdsp:
+{
+ do_dsp_mtlo (SD_, AC, RS);
+}
+
+001000,5.RT,5.RS,5.RD,00000101101:POOL32A:32::MUL.PH
+"mul.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_op (SD_, RD, RS, RT, 2, 0);
+}
+
+001000,5.RT,5.RS,5.RD,10000101101:POOL32A:32::MUL_S.PH
+"mul_s.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_op (SD_, RD, RS, RT, 2, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0000100101:POOL32A:32::MULEQ_S.W.PHL
+"muleq_s.w.phl r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_muleq (SD_, RD, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0001100101:POOL32A:32::MULEQ_S.W.PHR
+"muleq_s.w.phr r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_muleq (SD_, RD, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0010010101:POOL32A:32::MULEU_S.PH.QBL
+"muleu_s.ph.qbl r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qb_muleu (SD_, RD, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0011010101:POOL32A:32::MULEU_S.PH.QBR
+"muleu_s.ph.qbr r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qb_muleu (SD_, RD, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0100010101:POOL32A:32::MULQ_RS.PH
+"mulq_rs.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_mulq (SD_, RD, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0110010101:POOL32A:32::MULQ_RS.W
+"mulq_rs.w r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_w_mulq (SD_, RD, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0101010101:POOL32A:32::MULQ_S.PH
+"mulq_s.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_mulq (SD_, RD, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0111010101:POOL32A:32::MULQ_S.W
+"mulq_s.w r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_w_mulq (SD_, RD, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,2.AC,10110010111111:POOL32A:32::MULSA.W.PH
+"mulsa.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_w_mulsa (SD_, AC, RS, RT);
+}
+
+001000,5.RT,5.RS,2.AC,11110010111111:POOL32A:32::MULSAQ_S.W.PH
+"mulsaq_s.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_mulsaq_s_w_ph (SD_, AC, RS, RT);
+}
+
+001000,5.RT,5.RS,2.AC,00110010111111:POOL32A:32::MULT_DSP
+"mult ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_dsp_mult (SD_, AC, RS, RT);
+}
+
+001000,5.RT,5.RS,2.AC,01110010111111:POOL32A:32::MULTU_DSP
+"multu ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_dsp_multu (SD_, AC, RS, RT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0110101101:POOL32A:32::PACKRL.PH
+"packrl.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_packrl (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1000101101:POOL32A:32::PICK.PH
+"pick.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_pick (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0111101101:POOL32A:32::PICK.QB
+"pick.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qb_pick (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,0101000100111111:POOL32A:32::PRECEQ.W.PHL
+"preceq.w.phl r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_w_preceq (SD_, RT, RS, 0);
+}
+
+001000,5.RT,5.RS,0110000100111111:POOL32A:32::PRECEQ.W.PHR
+"preceq.w.phr r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_w_preceq (SD_, RT, RS, 1);
+}
+
+001000,5.RT,5.RS,0111000100111111:POOL32A:32::PRECEQU.PH.QBL
+"precequ.ph.qbl r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_qb_ph_precequ (SD_, RT, RS, 2);
+}
+
+001000,5.RT,5.RS,0111001100111111:POOL32A:32::PRECEQU.PH.QBLA
+"precequ.ph.qbla r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_qb_ph_precequ (SD_, RT, RS, 3);
+}
+
+001000,5.RT,5.RS,1001000100111111:POOL32A:32::PRECEQU.PH.QBR
+"precequ.ph.qbr r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_qb_ph_precequ (SD_, RT, RS, 0);
+}
+
+001000,5.RT,5.RS,1001001100111111:POOL32A:32::PRECEQU.PH.QBRA
+"precequ.ph.qbra r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_qb_ph_precequ (SD_, RT, RS, 1);
+}
+
+001000,5.RT,5.RS,1011000100111111:POOL32A:32::PRECEU.PH.QBL
+"preceu.ph.qbl r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_qb_ph_preceu (SD_, RT, RS, 2);
+}
+
+001000,5.RT,5.RS,1011001100111111:POOL32A:32::PRECEU.PH.QBLA
+"preceu.ph.qbla r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_qb_ph_preceu (SD_, RT, RS, 3);
+}
+
+001000,5.RT,5.RS,1101000100111111:POOL32A:32::PRECEU.PH.QBR
+"preceu.ph.qbr r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_qb_ph_preceu (SD_, RT, RS, 0);
+}
+
+001000,5.RT,5.RS,1101001100111111:POOL32A:32::PRECEU.PH.QBRA
+"preceu.ph.qbra r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_qb_ph_preceu (SD_, RT, RS, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0001101101:POOL32A:32::PRECR.QB.PH
+"precr.qb.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_qb_precr (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,5.SA,01111001101:POOL32A:32::PRECR_SRA.PH.W
+"precr_sra.ph.w r<RT>, r<RS>, <SA>"
+*nanomipsdsp:
+{
+ do_precr_sra (SD_, RT, RS, SA, 0);
+}
+
+001000,5.RT,5.RS,5.SA,11111001101:POOL32A:32::PRECR_SRA_R.PH.W
+"precr_sra_r.ph.w r<RT>, r<RS>, <SA>"
+*nanomipsdsp:
+{
+ do_precr_sra (SD_, RT, RS, SA, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0011101101:POOL32A:32::PRECRQ.PH.W
+"precrq.ph.w r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_w_ph_precrq (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0010101101:POOL32A:32::PRECRQ.QB.PH
+"precrq.qb.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_qb_precrq (SD_, RD, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0101101101:POOL32A:32::PRECRQU_S.QB.PH
+"precrqu_s.qb.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_qb_precrq (SD_, RD, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0100101101:POOL32A:32::PRECRQ_RS.PH.W
+"precrq_rs.ph.w r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_w_ph_rs_precrq (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,5.SA,1.X,1001010101:POOL32A:32::PREPEND
+"prepend r<RT>, r<RS>, <SA>"
+*nanomipsdsp:
+{
+ do_prepend (SD_, RT, RS, SA);
+}
+
+001000,5.RT,5.RS,1111000100111111:POOL32A:32::RADDU.W.QB
+"raddu.w.qb r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_qb_w_raddu (SD_, RT, RS);
+}
+
+001000,5.RT,7.CONTROL_MASK,00011001111111:POOL32A:32::RDDSP
+"rddsp r<RT>":CONTROL_MASK == 1111111111
+"rddsp r<RT>, <CONTROL_MASK>"
+*nanomipsdsp:
+{
+ do_rddsp (SD_, RT, CONTROL_MASK);
+}
+
+001000,5.RT,10.IMMEDIATE,1.X,0000111101:POOL32A:32::REPL.PH
+"repl.ph r<RT>, <IMMEDIATE>"
+*nanomipsdsp:
+{
+ do_repl (SD_, RT, IMMEDIATE, 2);
+}
+
+001000,5.RT,8.IMMEDIATE,1.X,010111111111:POOL32A:32::REPL.QB
+"repl.qb r<RT>, <IMMEDIATE>"
+*nanomipsdsp:
+{
+ do_repl (SD_, RT, IMMEDIATE, 0);
+}
+
+001000,5.RT,5.RS,0000001100111111:POOL32A:32::REPLV.PH
+"replv.ph r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_repl (SD_, RT, RS, 3);
+}
+
+001000,5.RT,5.RS,0001001100111111:POOL32A:32::REPLV.QB
+"replv.qb r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_repl (SD_, RT, RS, 1);
+}
+
+001000,0000,6.IMMEDIATE,2.AC,00000000011101:POOL32A:32::SHILO
+"shilo ac<AC>, <IMMEDIATE>"
+*nanomipsdsp:
+{
+ do_shilo (SD_, AC, IMMEDIATE);
+}
+
+001000,00000,5.RS,2.AC,01001001111111:POOL32A:32::SHILOV
+"shilov ac<AC>, r<RS>"
+*nanomipsdsp:
+{
+ do_shilov (SD_, AC, RS);
+}
+
+001000,5.RT,5.RS,4.SHIFT,001110110101:POOL32A:32::SHLL.PH
+"shll.ph r<RT>, r<RS>, <SHIFT>"
+*nanomipsdsp:
+{
+ do_ph_shift (SD_, RT, RS, SHIFT, 0, 0);
+}
+
+001000,5.RT,5.RS,4.SHIFT,101110110101:POOL32A:32::SHLL_S.PH
+"shll_s.ph r<RT>, r<RS>, <SHIFT>"
+*nanomipsdsp:
+{
+ do_ph_shift (SD_, RT, RS, SHIFT, 0, 1);
+}
+
+001000,5.RT,5.RS,3.SHIFT,0100001111111:POOL32A:32::SHLL.QB
+"shll.qb r<RT>, r<RS>, <SHIFT>"
+*nanomipsdsp:
+{
+ do_qb_shift (SD_, RT, RS, SHIFT, 0);
+}
+
+001000,5.RT,5.RS,5.RD,01110001101:POOL32A:32::SHLLV.PH
+"shllv.ph r<RD>, r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_ph_shl (SD_, RD, RT, RS, 0, 0);
+}
+
+001000,5.RT,5.RS,5.RD,11110001101:POOL32A:32::SHLLV_S.PH
+"shllv_s.ph r<RD>, r<RD>, r<RS>"
+*nanomipsdsp:
+{
+ do_ph_shl (SD_, RD, RT, RS, 0, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1110010101:POOL32A:32::SHLLV.QB
+"shllv.qb r<RD>, r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_qb_shl (SD_, RD, RT, RS, 0);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1111010101:POOL32A:32::SHLLV_S.W
+"shllv_s.w r<RD>, r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_w_s_shllv (SD_, RD, RT, RS);
+}
+
+001000,5.RT,5.RS,5.SHIFT,1.X,1111110101:POOL32A:32::SHLL_S.W
+"shll_s.w r<RT>, r<RS>, <SHIFT>"
+*nanomipsdsp:
+{
+ do_w_shll (SD_, RT, RS, SHIFT);
+}
+
+001000,5.RT,5.RS,3.SHIFT,0000111111111:POOL32A:32::SHRA.QB
+"shra.qb r<RT>, r<RS>, <SHIFT>"
+*nanomipsdsp:
+{
+ do_qb_shra (SD_, RT, RS, SHIFT, 0);
+}
+
+001000,5.RT,5.RS,3.SHIFT,1000111111111:POOL32A:32::SHRA_R.QB
+"shra_r.qb r<RT>, r<RS>, <SHIFT>"
+*nanomipsdsp:
+{
+ do_qb_shra (SD_, RT, RS, SHIFT, 1);
+}
+
+001000,5.RT,5.RS,4.SHIFT,1.X,01100110101:POOL32A:32::SHRA.PH
+"shra.ph r<RT>, r<RS>, <SHIFT>"
+*nanomipsdsp:
+{
+ do_ph_shift (SD_, RT, RS, SHIFT, 1, 0);
+}
+
+001000,5.RT,5.RS,4.SHIFT,1.X,11100110101:POOL32A:32::SHRA_R.PH
+"shra_r.ph r<RT>, r<RS>, <SHIFT>"
+*nanomipsdsp:
+{
+ do_ph_shift (SD_, RT, RS, SHIFT, 1, 1);
+}
+
+001000,5.RT,5.RS,5.RD,00110001101:POOL32A:32::SHRAV.PH
+"shrav.ph r<RD>, r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_ph_shl (SD_, RD, RT, RS, 1, 0);
+}
+
+001000,5.RT,5.RS,5.RD,10110001101:POOL32A:32::SHRAV_R.PH
+"shrav_r.ph r<RD>, r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_ph_shl (SD_, RD, RT, RS, 1, 1);
+}
+
+001000,5.RT,5.RS,5.RD,00111001101:POOL32A:32::SHRAV.QB
+"shrav.qb r<RD>, r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_qb_shrav (SD_, RD, RT, RS, 0);
+}
+
+001000,5.RT,5.RS,5.RD,10111001101:POOL32A:32::SHRAV_R.QB
+"shrav_r.qb r<RD>, r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_qb_shrav (SD_, RD, RT, RS, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1011010101:POOL32A:32::SHRAV_R.W
+"shrav_r.w r<RD>, r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_w_r_shrav (SD_, RD, RT, RS);
+}
+
+001000,5.RT,5.RS,5.SHIFT,1.X,1011110101:POOL32A:32::SHRA_R.W
+"shra_r.w r<RT>, r<RS>, <SHIFT>"
+*nanomipsdsp:
+{
+ do_w_shra (SD_, RT, RS, SHIFT);
+}
+
+001000,5.RT,5.RS,4.SHIFT,001111111111:POOL32A:32::SHRL.PH
+"shrl.ph r<RT>, r<RS>, <SHIFT>"
+*nanomipsdsp:
+{
+ do_ph_shrl (SD_, RT, RS, SHIFT);
+}
+
+001000,5.RT,5.RS,3.SHIFT,1100001111111:POOL32A:32::SHRL.QB
+"shrl.qb r<RT>, r<RS>, <SHIFT>"
+*nanomipsdsp:
+{
+ do_qb_shift (SD_, RT, RS, SHIFT, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1100010101:POOL32A:32::SHRLV.PH
+"shrlv.ph r<RD>, r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_ph_shrlv (SD_, RD, RT, RS);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1101010101:POOL32A:32::SHRLV.QB
+"shrlv.qb r<RD>, r<RT>, r<RS>"
+*nanomipsdsp:
+{
+ do_qb_shl (SD_, RD, RT, RS, 1);
+}
+
+001000,5.RT,5.RS,5.RD,01000001101:POOL32A:32::SUBQ.PH
+"subq.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_op (SD_, RD, RS, RT, 1, 0);
+}
+
+001000,5.RT,5.RS,5.RD,11000001101:POOL32A:32::SUBQ_S.PH
+"subq_s.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_ph_op (SD_, RD, RS, RT, 1, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1101000101:POOL32A:32::SUBQ_S.W
+"subq_s.w r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_w_op (SD_, RD, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,5.RD,01001001101:POOL32A:32::SUBQH.PH
+"subqh.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qh_ph_op (SD_, RD, RS, RT, 1, 0);
+}
+
+001000,5.RT,5.RS,5.RD,11001001101:POOL32A:32::SUBQH_R.PH
+"subqh_r.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qh_ph_op (SD_, RD, RS, RT, 1, 1);
+}
+
+001000,5.RT,5.RS,5.RD,01010001101:POOL32A:32::SUBQH.W
+"subqh.w r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qh_w_op (SD_, RD, RS, RT, 1, 0);
+}
+
+001000,5.RT,5.RS,5.RD,11010001101:POOL32A:32::SUBQH_R.W
+"subqh_r.w r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qh_w_op (SD_, RD, RS, RT, 1, 1);
+}
+
+001000,5.RT,5.RS,5.RD,01100001101:POOL32A:32::SUBU.PH
+"subu.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_u_ph_op (SD_, RD, RS, RT, 1, 0);
+}
+
+001000,5.RT,5.RS,5.RD,11100001101:POOL32A:32::SUBU_S.PH
+"subu_s.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_u_ph_op (SD_, RD, RS, RT, 1, 1);
+}
+
+001000,5.RT,5.RS,5.RD,01011001101:POOL32A:32::SUBU.QB
+"subu.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qb_op (SD_, RD, RS, RT, 1, 0);
+}
+
+001000,5.RT,5.RS,5.RD,11011001101:POOL32A:32::SUBU_S.QB
+"subu_s.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_qb_op (SD_, RD, RS, RT, 1, 1);
+}
+
+001000,5.RT,5.RS,5.RD,01101001101:POOL32A:32::SUBUH.QB
+"subuh.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_uh_qb_op (SD_, RD, RS, RT, 1, 0);
+}
+
+001000,5.RT,5.RS,5.RD,11101001101:POOL32A:32::SUBUH_R.QB
+"subuh_r.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+ do_uh_qb_op (SD_, RD, RS, RT, 1, 1);
+}
+
+001000,5.RT,7.CONTROL_MASK,01011001111111:POOL32A:32::WRDSP
+"wrdsp r<RT>":CONTROL_MASK == 1111111111
+"wrdsp r<RT>, <CONTROL_MASK>"
+*nanomipsdsp:
+{
+ do_wrdsp (SD_, RT, CONTROL_MASK);
+}
diff --git a/sim/mips/nanomipsr6.igen b/sim/mips/nanomipsr6.igen
new file mode 100644
index 00000000000..109fa1510f9
--- /dev/null
+++ b/sim/mips/nanomipsr6.igen
@@ -0,0 +1,3283 @@
+// Simulator definition for the nanoMIPS.
+// Copyright (C) 2018-2022 Free Software Foundation, Inc.
+// Contributed by Imagination Technologies, Ltd.
+// Written by Ali Lown <ali.lown@imgtec.com>
+//
+// This file is part of GDB, the GNU debugger.
+//
+// This program 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 of the License, or
+// (at your option) any later version.
+//
+// This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+
+:compute:::int:U_SHIFT_1BIT:U:(U << 1)
+:compute:::int:U_SHIFT_2BIT:U:(U << 2)
+:compute:::int:U_SHIFT_3BIT:U:(U << 3)
+:compute:::int:U_SHIFT_4BIT:U:(U << 4)
+:compute:::int:EU_127:EU:((EU == 127) ? -1 \: EU)
+:compute:::int:U_LW4X4:U2,U3:((U3 << 3) | (U2 << 2))
+:compute:::int:AXUIPC_S_LO:S1,S2,S3:((EXTEND32((S3 << 31) | (S2 << 21) | (S1 << 12))) & 0x0000ffff)
+:compute:::int:AXUIPC_S_HI:S1,S2,S3:((EXTEND32((S3 << 31) | (S2 << 21) | (S1 << 12))) & 0xffff0000)
+:compute:::int:AXUIPC_S:S1,S2,S3:(EXTEND32((S3 << 31) | (S2 << 21) | (S1 << 12)))
+:compute:::int:TRD2:RD20,RD21:(compute_gpr2_dest1_reg (SD_, (RD21 << 1 | RD20)))
+:compute:::int:TRE2:RD20,RD21:(compute_gpr2_dest2_reg (SD_, (RD21 << 1 | RD20)))
+:compute:::int:TRS2:RS4,RS2_0:(compute_gpr4_zero (SD_, (RS4 << 3 | RS2_0)))
+:compute:::int:TRT2:RT4,RT2_0:(compute_gpr4_zero (SD_, (RT4 << 3 | RT2_0)))
+:compute:::int:TRD2_REV:RD4,RD2_0:(compute_gpr4 (SD_, (RD4 << 3) | RD2_0))
+:compute:::int:TRE2_REV:RE4,RE2_0:(compute_gpr4 (SD_, (RE4 << 3) | RE2_0))
+:compute:::int:TRS2_REV:RS20,RS21:(compute_gpr2_dest1_reg (SD_, (RS21 << 1 | RS20)))
+:compute:::int:TRT2_REV:RS20,RS21:(compute_gpr2_dest2_reg (SD_, (RS21 << 1 | RS20)))
+:compute:::address_word:ADDRESS8:S1,S2:(nia + EXTEND8((S2 << 7) | (S1 << 1)))
+:compute:::address_word:ADDRESS11:S1,S2:(nia + EXTEND11((S2 << 10) | (S1 << 1)))
+:compute:::address_word:ADDRESS15:S1,S2:(nia + EXTEND15((S2 << 14) | (S1 << 1)))
+:compute:::address_word:ADDRESS21:S1,S2:(nia + EXTEND21((S2 << 20) | (S1 << 1)))
+:compute:::address_word:ADDRESS22:S1,S2:(nia + EXTEND22((S2 << 21) | (S1 << 1)))
+:compute:::address_word:ADDRESS26:S1,S2:(nia + EXTEND26((S2 << 25) | (S1 << 1)))
+:compute:::int:INS_POS:LSB:(LSB)
+:compute:::int:INS_SIZE:LSB,MSBD:(1 + MSBD - LSB)
+:compute:::address_word:ADDRESS12:S1,S2:(nia + EXTEND12(S2 << 11 | S1 << 1))
+:compute:::int:S_14_BIT:S1,S2:(EXTEND14 ((S1 << 13) | S2))
+:compute:::int:S_4_BIT:S1,S2:(EXTEND4((S1 << 3) | S2))
+:compute:::int:S_9_BIT:S1,S2:(EXTEND9((S1 << 8) | S2))
+:compute:::int:S_9_BIT_LLSC:S1,S2:(EXTEND9((S1 << 8) | (S2 << 2)))
+:compute:::int:RD1:RD:(compute_gpr1_dest_reg (SD_, RD))
+:compute:::int:RT_5_BIT_NM_Z:RT1,RT2:(compute_gpr4_zero (SD_, (RT1 << 3) | RT2))
+:compute:::int:RT_5_BIT_NM:RT1,RT2:(compute_gpr4 (SD_, (RT1 << 3) | RT2))
+:compute:::int:RS_5_BIT_NM:RS1,RS2:(compute_gpr4 (SD_, (RS1 << 3) | RS2))
+:compute:::int:TRTZ:RTZ:((RTZ >= 1 && RTZ <= 3) ? (16 + RTZ) \: RTZ)
+:compute:::int:EU_12_13:EU:((EU == 12) ? 255 \: ((EU == 13) ? 65535 \: EU))
+:compute:::int:RS_MOVE:RS1,RS_CODE_1,RS_CODE_2:((RS1 << 3) | (RS_CODE_1 << 2) | RS_CODE_2)
+:compute:::int:CODE_BREAK:RS_CODE_1,RS_CODE_2:((RS_CODE_1 << 2) | RS_CODE_2)
+:compute:::int:TRD_NM:RD:((RD < 4) ? (16 + RD) \: RD)
+:compute:::int:TRS_NM:RS:((RS < 4) ? (16 + RS) \: RS)
+:compute:::int:TRT_NM:RT:((RT < 4) ? (16 + RT) \: RT)
+:compute:::int:COUNT:COUNT3:(COUNT3 == 0 ? 8 \: COUNT3)
+:compute:::int:SHIFTX_1BIT:SHIFTX:(SHIFTX << 1)
+
+:function:::void:do_msubf:int fd, int fs, int ft, int fmt, instruction_word instruction_0
+{
+ check_fpu (SD_);
+ check_u64 (SD_, instruction_0);
+ check_fmt_p (SD_, fmt, instruction_0);
+ TRACE_ALU_INPUT3 (FGR[fd], FGR[fs], FGR[ft]);
+ StoreFPR (fd, fmt, FusedMultiplySub (ValueFPR (fs, fmt),
+ ValueFPR (ft, fmt),
+ ValueFPR (fd, fmt), fmt));
+ TRACE_ALU_RESULT (FGR[fd]);
+}
+
+:function:::void:do_maddf:int fd, int fs, int ft, int fmt, instruction_word instruction_0
+{
+ check_fpu (SD_);
+ check_u64 (SD_, instruction_0);
+ check_fmt_p (SD_, fmt, instruction_0);
+ TRACE_ALU_INPUT3 (FGR[fd], FGR[fs], FGR[ft]);
+ StoreFPR (fd, fmt, FusedMultiplyAdd (ValueFPR (fs, fmt),
+ ValueFPR (ft, fmt),
+ ValueFPR (fd, fmt), fmt));
+ TRACE_ALU_RESULT (FGR[fd]);
+}
+
+:function:::void:do_rint:int fd, int fs, int fmt, instruction_word instruction_0
+{
+ uint64_t result = 0;
+ check_fpu (SD_);
+ check_u64 (SD_, instruction_0);
+ check_fmt_p (SD_, fmt, instruction_0);
+ TRACE_ALU_INPUT1 (FGR[fs]);
+ RoundToIntegralExact (ValueFPR (fs, fmt), &result, fmt);
+ StoreFPR (fd, fmt, result);
+ TRACE_ALU_RESULT (FGR[fd]);
+}
+
+:function:::void:do_class:int fd, int fs, int fmt, instruction_word instruction_0
+{
+ check_fpu (SD_);
+ check_u64 (SD_, instruction_0);
+ check_fmt_p (SD_, fmt, instruction_0);
+ StoreFPR (fd, fmt, Classify (ValueFPR (fs, fmt), fmt));
+}
+
+:function:::void:do_seleqzf:int fd, int fs, int ft, int fmt, instruction_word instruction_0
+{
+ check_fpu (SD_);
+ check_fmt_p (SD_, fmt, instruction_0);
+ TRACE_ALU_INPUT2 (ValueFPR(fs, fmt), FGR[ft]);
+ if ((FGR[ft] & 0x01) == 0)
+ StoreFPR (fd, fmt, ValueFPR (fs, fmt));
+ else
+ StoreFPR (fd, fmt, 0);
+ TRACE_ALU_RESULT (ValueFPR(fd, fmt));
+}
+
+:function:::void:do_selnezf:int fd, int fs, int ft, int fmt, instruction_word instruction_0
+{
+ check_fpu (SD_);
+ check_fmt_p (SD_, fmt, instruction_0);
+ TRACE_ALU_INPUT2 (ValueFPR(fs, fmt), FGR[ft]);
+ if ((FGR[ft] & 0x01) == 0x1)
+ StoreFPR (fd, fmt, ValueFPR (fs, fmt));
+ else
+ StoreFPR (fd, fmt, 0);
+ TRACE_ALU_RESULT (ValueFPR(fd, fmt));
+}
+
+:function:::void:do_self:int fd, int fs, int ft, int fmt, instruction_word instruction_0
+{
+ check_fpu (SD_);
+ check_fmt_p (SD_, fmt, instruction_0);
+ TRACE_ALU_INPUT3 (FGR[fd], ValueFPR(fs, fmt), ValueFPR(ft, fmt));
+ if ((FGR[fd] & 0x01) != 0)
+ StoreFPR (fd, fmt, ValueFPR (ft, fmt));
+ else
+ StoreFPR (fd, fmt, ValueFPR (fs, fmt));
+ TRACE_ALU_RESULT (ValueFPR(fd, fmt));
+}
+
+:function:::void:do_mina:int fd, int fs, int ft, int fmt, instruction_word instruction_0
+{
+ check_fpu (SD_);
+ check_u64 (SD_, instruction_0);
+ check_fmt_p (SD_, fmt, instruction_0);
+ TRACE_ALU_INPUT2 (FGR[fs], FGR[ft]);
+ StoreFPR (fd, fmt, MinA (ValueFPR (fs, fmt), ValueFPR (ft, fmt), fmt));
+ TRACE_ALU_RESULT (FGR[fd]);
+}
+
+:function:::void:do_maxa:int fd, int fs, int ft, int fmt, instruction_word instruction_0
+{
+ check_fpu (SD_);
+ check_u64 (SD_, instruction_0);
+ check_fmt_p (SD_, fmt, instruction_0);
+ TRACE_ALU_INPUT2 (FGR[fs], FGR[ft]);
+ StoreFPR (fd, fmt, MaxA (ValueFPR (fs, fmt), ValueFPR (ft, fmt), fmt));
+ TRACE_ALU_RESULT (FGR[fd]);
+}
+
+:function:::void:do_max:int fd, int fs, int ft, int fmt, instruction_word instruction_0
+{
+ check_fpu (SD_);
+ check_u64 (SD_, instruction_0);
+ check_fmt_p (SD_, fmt, instruction_0);
+ TRACE_ALU_INPUT2 (FGR[fs], FGR[ft]);
+ StoreFPR (fd, fmt, Max (ValueFPR (fs, fmt), ValueFPR (ft, fmt), fmt));
+ TRACE_ALU_RESULT (FGR[fd]);
+}
+
+:function:::void:do_min:int fd, int fs, int ft, int fmt, instruction_word instruction_0
+{
+ check_fpu (SD_);
+ check_u64 (SD_, instruction_0);
+ check_fmt_p (SD_, fmt, instruction_0);
+ TRACE_ALU_INPUT2 (FGR[fs], FGR[ft]);
+ StoreFPR (fd, fmt, Min (ValueFPR (fs, fmt), ValueFPR (ft, fmt), fmt));
+ TRACE_ALU_RESULT (FGR[fd]);
+}
+
+:function:::void:do_cmp:int fd, int fs, int ft, int fmt, int condition
+{
+ uint64_t result;
+ check_fpu (SD_);
+ TRACE_ALU_INPUT2 (ValueFPR (fs, fmt), ValueFPR (ft, fmt));
+ result = R6Compare (ValueFPR (fs, fmt), ValueFPR (ft, fmt), fmt, condition);
+ StoreFPR (fd, fmt, result);
+ TRACE_ALU_RESULT (result);
+}
+
+:function:::void:do_modu:int rd, int rs, int rt
+{
+ uint32_t n = GPR[rs];
+ uint32_t d = GPR[rt];
+ TRACE_ALU_INPUT2 (n,d);
+ if (d == 0)
+ GPR[rd] = EXTEND32 (0);
+ else
+ GPR[rd] = EXTEND32 (n % d);
+
+ TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_mod:int rd, int rs, int rt
+{
+ int32_t n = GPR[rs];
+ int32_t d = GPR[rt];
+ TRACE_ALU_INPUT2 (n,d);
+ if (d == 0 || (n == SIGNED32 (0x80000000) && d == -1))
+ GPR[rd] = EXTEND32 (0);
+ else
+ GPR[rd] = EXTEND32 (n % d);
+
+ TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_muhu:int rd, int rs, int rt
+{
+ uint64_t prod;
+ if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
+ prod = ((uint64_t)(uint32_t) GPR[rs])
+ * ((uint64_t)(uint32_t) GPR[rt]);
+ GPR[rd] = EXTEND32 (VH4_8 (prod));
+ TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_mulu:int rd, int rs, int rt
+{
+ uint64_t prod;
+ if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
+ prod = ((uint64_t)(uint32_t) GPR[rs])
+ * ((uint64_t)(uint32_t) GPR[rt]);
+ GPR[rd] = EXTEND32 (VL4_8 (prod));
+ TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_muh:int rd, int rs, int rt
+{
+ int64_t prod;
+ if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
+ prod = ((int64_t)(int32_t) GPR[rs])
+ * ((int64_t)(int32_t) GPR[rt]);
+ GPR[rd] = EXTEND32 (VH4_8 (prod));
+ TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_lsa:int rd, int rs, int rt, unsigned immediate
+{
+ uint32_t t = GPR[rs] << immediate;
+ GPR[rd] = EXTEND32(GPR[rt] + t);
+ TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_divu:int rd, int rs, int rt
+*nanomips32r6:
+*nanomips64r6:
+{
+ uint32_t n = GPR[rs];
+ uint32_t d = GPR[rt];
+ TRACE_ALU_INPUT2 (n,d);
+ if (d == 0)
+ GPR[rd] = EXTEND32 (0x80000000);
+ else
+ GPR[rd] = EXTEND32 (n / d);
+
+ TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_div:int rd, int rs, int rt
+*nanomips32r6:
+*nanomips64r6:
+{
+ int32_t n = GPR[rs];
+ int32_t d = GPR[rt];
+ TRACE_ALU_INPUT2 (n,d);
+ if (d == 0)
+ GPR[rd] = EXTEND32 (0x80000000);
+ else if (n == SIGNED32 (0x80000000) && d == -1)
+ GPR[rd] = EXTEND32 (0x80000000);
+ else
+ GPR[rd] = EXTEND32 (n / d);
+
+ TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_llwp:int rt, int ru, int roffset, int rbase
+{
+ address_word base = GPR[rbase];
+ address_word offset = EXTEND16 (roffset);
+ {
+ address_word vaddr = loadstore_ea (SD_, base, offset);
+ address_word paddr;
+ int uncached;
+ if ((vaddr & 7) != 0)
+ {
+ SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 8, vaddr, read_transfer,
+ sim_core_unaligned_signal);
+ }
+ else
+ {
+ if (AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached,
+ isTARGET, isREAL))
+ {
+ uint64_t memval = 0;
+ uint64_t memval1 = 0;
+ uint64_t data = memval;
+
+ LoadMemory (&memval, &memval1, uncached, AccessLength_DOUBLEWORD,
+ paddr, vaddr, isDATA, isREAL);
+
+ GPR[rt] = EXTEND32 (data & 0xFFFFFFFF);
+ GPR[ru] = EXTEND32 (data >> 32);
+
+ LLBIT = 1;
+ COP0_COUNT++;
+ }
+ }
+ }
+}
+
+:function:::void:do_rotx:int rt, int rs, int shift, int shiftx, int stripe
+{
+ int i;
+ uint64_t tmp0 = ((uint64_t)GPR[rs] << 32) | (GPR[rs] & 0xFFFFFFFF);
+ uint64_t tmp1, tmp2, tmp3, tmp4, tmp5;
+
+ tmp1 = tmp0;
+ for (i = 0; i <=46; i++) {
+ int s;
+
+ if (i & 0x8)
+ s = shift;
+ else
+ s = shiftx;
+
+ if (stripe != 0 && !(i & 0x4))
+ s = ~s;
+
+ if (s & 0x10) {
+ if (tmp0 & (1LL << (i + 16)))
+ tmp1 |= 1LL << i;
+ else
+ tmp1 &= ~(1LL << i);
+ }
+ }
+
+ tmp2 = tmp1;
+ for (i = 0; i <=38; i++) {
+ int s;
+
+ if (i & 0x4)
+ s = shift;
+ else
+ s = shiftx;
+
+ if (s & 0x8) {
+ if (tmp1 & (1LL << (i + 8)))
+ tmp2 |= 1LL << i;
+ else
+ tmp2 &= ~(1LL << i);
+ }
+ }
+
+ tmp3 = tmp2;
+ for (i = 0; i <=34; i++) {
+ int s;
+
+ if (i & 0x2)
+ s = shift;
+ else
+ s = shiftx;
+
+ if (s & 0x4) {
+ if (tmp2 & (1LL << (i + 4)))
+ tmp3 |= 1LL << i;
+ else
+ tmp3 &= ~(1LL << i);
+ }
+ }
+
+ tmp4 = tmp3;
+ for (i = 0; i <=32; i++) {
+ int s;
+
+ if (i & 0x1)
+ s = shift;
+ else
+ s = shiftx;
+
+ if (s & 0x2) {
+ if (tmp3 & (1LL << (i + 2)))
+ tmp4 |= 1LL << i;
+ else
+ tmp4 &= ~(1LL << i);
+ }
+ }
+
+ tmp5 = tmp4;
+ for (i = 0; i <=31; i++) {
+ int s;
+
+ s = shift;
+
+ if (s & 0x1) {
+ if (tmp4 & (1LL << (i + 1)))
+ tmp5 |= 1LL << i;
+ else
+ tmp5 &= ~(1LL << i);
+ }
+ }
+
+ GPR[rt] = EXTEND32 (tmp5);
+}
+
+:function:::void:do_lwc1xs:int ft, int rbase, int roffset
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_fpu (SD_);
+ COP_LW (1, ft, do_load (SD_, AccessLength_WORD, GPR[rbase] << 2,
+ GPR[roffset]));
+}
+
+:function:::void:do_lwpc_nanomips:int rt, uint32_t offset, address_word nia
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_fpu (SD_);
+ GPR[rt] = EXTEND32 (do_load (SD_, AccessLength_WORD, nia, offset));
+}
+
+:function:::void:check_nms_flag:
+*nanomips32r6:
+*nanomips64r6:
+{
+ if(nms_flag == 0)
+ sim_engine_abort (SD, CPU, CIA, "Error: NMS instruction generated\
+ (nanoMIPS Subset is disabled - use -march=32r6s option)\n");
+}
+
+:function:::void:do_swc1xs:int ft, int rbase, int roffset, address_word instruction_0
+*nanomips32r6:
+*nanomips64r6:
+{
+ address_word base = GPR[rbase] << 2;
+ address_word offset = GPR[roffset];
+ check_fpu (SD_);
+ {
+ address_word vaddr = loadstore_ea (SD_, base, offset);
+ address_word paddr;
+ int uncached;
+ if ((vaddr & 3) != 0)
+ {
+ SIM_CORE_SIGNAL (SD, CPU, cia, read_map, AccessLength_WORD+1, vaddr,
+ write_transfer, sim_core_unaligned_signal);
+ }
+ else
+ {
+ if (AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached,
+ isTARGET, isREAL))
+ {
+ uword64 memval = 0;
+ uword64 memval1 = 0;
+ uword64 mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3);
+ address_word reverseendian =
+ (ReverseEndian ?(mask ^ AccessLength_WORD): 0);
+ address_word bigendiancpu =
+ (BigEndianCPU ?(mask ^ AccessLength_WORD): 0);
+ unsigned int byte;
+ paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
+ byte = ((vaddr & mask) ^ bigendiancpu);
+ memval = (((uword64)COP_SW(1, ft)) << (8 * byte));
+ StoreMemory (uncached, AccessLength_WORD, memval, memval1, paddr,
+ vaddr, isREAL);
+ }
+ }
+ }
+}
+
+:function:::uint32_t:compute_gpr2_dest1_reg:int reg
+*nanomips32r6:
+*nanomips64r6:
+{
+ switch(reg)
+ {
+ case 0: return 4;
+ case 1: return 5;
+ case 2: return 6;
+ case 3: return 7;
+ default: return 4;
+ }
+}
+
+:function:::uint32_t:compute_gpr4_zero:int reg
+*nanomips32r6:
+*nanomips64r6:
+{
+ if (reg == 3) return 0;
+ else if (reg >=4 && reg <= 7) return reg;
+ else return reg + 8;
+}
+
+:function:::uint32_t:compute_gpr4:int reg
+*nanomips32r6:
+*nanomips64r6:
+{
+ if (reg >=4 && reg <= 7) return reg;
+ else return reg + 8;
+}
+
+:function:::uint32_t:compute_gpr2_dest2_reg:int reg
+*nanomips32r6:
+*nanomips64r6:
+{
+ switch(reg)
+ {
+ case 0: return 5;
+ case 1: return 6;
+ case 2: return 7;
+ case 3: return 8;
+ default: return 5;
+ }
+}
+
+:function:::uint32_t:compute_gpr1_dest_reg:int reg
+*nanomips32r6:
+*nanomips64r6:
+{
+ switch(reg)
+ {
+ case 0: return 4;
+ case 1: return 5;
+ default: return 4;
+ }
+}
+
+:function:::unsigned:zero_extend:signed_word value, uint32_t from_nbits
+{
+ uint32_t low_bits_mask = (1 << from_nbits) - 1;
+ return value & low_bits_mask;
+}
+
+:function:::void:do_save_gprs_to_stack_and_adjust_sp: int first_gpr, int count, int gp, int u
+*nanomips32r6:
+*nanomips64r6:
+{
+ int counter = 0;
+
+ while (counter != count) {
+ int gpr = (first_gpr & 0x10) | ((first_gpr + counter) & 0x1F);
+ int offset = - ( (counter + 1) << 2 );
+
+ if ( gp && (counter == count - 1))
+ gpr = 28;
+
+ do_store (SD_, AccessLength_WORD, GPR[SPIDX], offset, GPR[gpr]);
+
+ counter++;
+ COP0_COUNT++;
+ }
+
+ GPR[SPIDX] -= u;
+}
+
+:function:::void:do_restore_gprs_from_stack_and_adjust_sp: int first_gpr, int count, int gp, int u
+*nanomips32r6:
+*nanomips64r6:
+{
+ int counter = 0;
+
+ while (counter != count) {
+ int gpr = (first_gpr & 0x10) | ((first_gpr + counter) & 0x1F);
+ int offset;
+
+ if (gpr == 29)
+ Unpredictable();
+
+ offset = u - ((counter + 1) << 2);
+
+ if ( gp && (counter == count - 1))
+ gpr = 28;
+
+ GPR[gpr] = EXTEND32 (do_load(SD_, AccessLength_WORD, GPR[SPIDX], offset));
+
+ counter++;
+ COP0_COUNT++;
+ }
+
+ GPR[SPIDX] += u;
+}
+
+:function:::address_word:do_eret:int nc, address_word nia
+*nanomips32r6:
+*nanomips64r6:
+{
+ if (SR & status_ERL)
+ {
+ /* Oops, not yet available */
+ sim_io_printf (SD, "Warning: ERET when SR[ERL] set not supported");
+ nia = EPC;
+ SR &= ~status_ERL;
+ }
+ else
+ {
+ nia = EPC;
+ SR &= ~status_EXL;
+ //if ( SRSCtl.HSS > 0 && Status.BEV == 0)
+ // SRSCtl.CSS = SRSCtl.PSS
+ }
+
+ if (!nc)
+ LLBIT = 0;
+
+ //TODO: ClearHazards()
+ return nia;
+}
+
+:%s::::GPR_LIST_SAVE:int count
+*nanomips32r6:
+*nanomips64r6:
+{
+ int i;
+ static char gpr_list[100];
+
+ gpr_list[0] = '\0';
+
+ i = 0;
+
+ while (i<count)
+ {
+ char str1[32];
+ if (i == 0 || i==count-1) {
+ sprintf(str1, "%d", i);
+ strcat (gpr_list,"s");
+ strcat (gpr_list,str1);
+ if(i==0 && count > 1)
+ strcat (gpr_list,"-");
+ }
+ i++;
+ }
+ return (gpr_list);
+}
+
+:function:::void:do_break_nanomips:address_word instruction_0
+{
+ /* Check for some break instruction which are reserved for use by the
+ simulator. */
+ unsigned int break_code = instruction_0 & HALT_INSTRUCTION_MASK_NANOMIPS;
+ if (break_code == (HALT_INSTRUCTION_NANOMIPS & HALT_INSTRUCTION_MASK_NANOMIPS))
+ {
+ sim_engine_halt (SD, CPU, NULL, cia,
+ sim_exited, (unsigned int)(A0 & 0xFFFFFFFF));
+ }
+ else if (break_code == (BREAKPOINT_INSTRUCTION_NANOMIPS & HALT_INSTRUCTION_MASK_NANOMIPS))
+ {
+ PC = cia;
+ SignalException (BreakPoint, instruction_0);
+ }
+
+ else
+ {
+ /* If we get this far, we're not an instruction reserved by the sim. Raise
+ the exception. */
+ SignalException (BreakPoint, instruction_0);
+ }
+}
+
+:function:::FP_formats:convert_fmt_micromips_mul:int fmt
+*nanomips32r6:
+*nanomips64r6:
+{
+ switch (fmt)
+ {
+ case 1: return fmt_single;
+ case 3: return fmt_double;
+ default: return fmt_unknown;
+ }
+}
+
+:%s::::GP_SAVE:int gp
+*nanomips32r6:
+*nanomips64r6:
+{
+ return (gp > 0) ? "gp" : "";
+}
+
+:%s::::FP_SAVE:int fp
+*nanomips32r6:
+*nanomips64r6:
+{
+ return (fp > 0) ? "fp" : "";
+}
+
+11111111111111111111111111111111:R6DUMMY:32,f::DUMMY0.fmt
+"dummy 0"
+*nanomips32r6:
+*nanomips64r6:
+{
+ /* Just needed so GNUSIM builds */
+}
+
+011100,3.RT,1,6.U:R6P16A1:16::ADDIUR1SP
+"addiu r<TRT_NM>, SP, <U_SHIFT_2BIT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_addiu (SD_, SPIDX, TRT_NM, U_SHIFT_2BIT);
+}
+
+100100,3.RT,3.RS,0,3.U:R6P16A2:16::ADDIUR2
+"addiu r<TRT_NM>, r<TRS_NM>, <U_SHIFT_2BIT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_addiu (SD_, TRS_NM, TRT_NM, U_SHIFT_2BIT);
+}
+
+100100,5.RT,1.S1,1,3.S2:R6P16ADDIURS5:16::ADDIURS5
+"nop":RT==0
+"addiu r<RT>, <S_4_BIT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ if (RT != 0)
+ do_addiu (SD_, RT, RT, S_4_BIT);
+}
+
+000001,5.RT,20.S1,1.S2:R6P32:32::ADDIUPC
+"addiu r<RT>, <ADDRESS22>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ GPR[RT] = ADDRESS22;
+}
+
+011000,5.RT,00011,16.IMM48:R6POOL48I:32::ADDIUPC48
+"addiu r<RT>, <IMM48>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ uint16_t U2;
+ uint32_t total;
+ check_nms_flag (SD_);
+ U2 = do_load (SD_, AccessLength_HALFWORD, CIA + 4, 0);
+ total = U2 << 16 | IMM48;
+ TRACE_ALU_INPUT2(GPR[RT], total);
+ GPR[RT] = CIA + 6 + EXTEND32(total);
+ TRACE_ALU_RESULT(GPR[RT]);
+ NIA = CIA + 6;
+}
+
+101100,3.RT,3.RS,3.RD,0:R6P16ADDU:16::ADDU16
+"addu r<TRD_NM>, r<TRS_NM>, r<TRT_NM>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_addu (SD_, TRS_NM, TRT_NM, TRD_NM);
+}
+
+001111,1.RT1,0,3.RT2,1.RS1,0,3.RS2:R6P164X4:16::ADDU4X4
+"addu r<RT_5_BIT_NM>, r<RS_5_BIT_NM>, r<RT_5_BIT_NM>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+ do_addu (SD_, RS_5_BIT_NM, RT_5_BIT_NM, RT_5_BIT_NM);
+}
+
+010100,3.RT,3.RS,10,0,0:R6POOL16C00:16::AND16
+"and r<TRT_NM>, r<TRS_NM>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_and (SD_, TRS_NM, TRT_NM, TRT_NM);
+}
+
+111100,3.RT,3.RS,4.EU:R6P16:16::ANDI16
+"andi r<TRT_NM>, r<TRS_NM>, <EU_12_13>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_andi (SD_, TRS_NM, TRT_NM, EU_12_13);
+}
+
+001110,9.S1,1.S2:R6P16:16::BALC16
+"balc <ADDRESS11>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT1(RA);
+ RA = NIA;
+ NIA = ADDRESS11;
+ TRACE_ALU_RESULT(RA);
+
+ // For cycle counting
+ COP0_COUNT++;
+}
+
+000110,9.S1,1.S2:R6P16:16::BC16
+"bc <ADDRESS11>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ NIA = ADDRESS11;
+}
+
+110110,3.RT,3.RS,4.U!0:R6P16BR1:16::BxxC16
+"beqc r<TRS_NM>, r<TRT_NM>, <U_SHIFT_1BIT>":RS<RT
+"bnec r<TRS_NM>, r<TRT_NM>, <U_SHIFT_1BIT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+ TRACE_ALU_INPUT2(GPR[TRS_NM], GPR[TRT_NM]);
+ if (RS < RT && GPR[TRS_NM] == GPR[TRT_NM])
+ NIA = NIA + U_SHIFT_1BIT; //BEQC
+ else if (RS >= RT && GPR[TRS_NM] != GPR[TRT_NM])
+ NIA = NIA + U_SHIFT_1BIT; //BNEC
+}
+
+100110,3.RT,6.S1,1.S2:R6P16:16::BEQZC16
+"beqzc r<TRT_NM>, <ADDRESS8>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT1(GPR[TRT_NM]);
+ if(GPR[TRT_NM] == 0)
+ NIA = ADDRESS8;
+}
+
+101110,3.RT,6.S1,1.S2:R6P16:16::BNEZC16
+"bnezc r<TRT_NM>, <ADDRESS8>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT1(GPR[TRT_NM]);
+ if(GPR[TRT_NM] != 0)
+ NIA = ADDRESS8;
+}
+
+110110,5.RT,1,0000:R6P16JRC:16::JALRC16
+"jalrc r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(GPR[RT], RA);
+ RA = NIA;
+ NIA = GPR[RT];
+ TRACE_ALU_RESULT(RA);
+
+ // For cycle counting
+ COP0_COUNT++;
+}
+
+110110,5.RT,0,0000:R6P16JRC:16::JRC16
+"jrc r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT1(GPR[RT]);
+ NIA = GPR[RT];
+}
+
+010111,3.RT,3.RS,00,2.U:R6P16LB:16::LB16
+"lb r<TRT_NM>, <U>(r<TRS_NM>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lb (SD_, TRT_NM, U, TRS_NM);
+}
+
+010111,3.RT,3.RS,10,2.U:R6P16LB:16::LBU16
+"lbu r<TRT_NM>, <U>(r<TRS_NM>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2 (U, GPR[TRS_NM]);
+ do_lbu (SD_, TRT_NM, U, TRS_NM);
+ TRACE_ALU_RESULT (GPR[TRT_NM]);
+}
+
+011111,3.RT,3.RS,0,2.U,0:R6P16LH:16::LH16
+"lh r<TRT_NM>, <U_SHIFT_1BIT>(r<TRS_NM>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lh (SD_, TRT_NM, U_SHIFT_1BIT, TRS_NM);
+}
+
+011111,3.RT,3.RS,1,2.U,0:R6P16LH:16::LHU16
+"lhu r<TRT_NM>, <U_SHIFT_1BIT>(r<TRS_NM>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lhu (SD_, TRT_NM, U_SHIFT_1BIT, TRS_NM);
+}
+
+110100,3.RT,7.EU:R6P16:16::LI16
+"li r<TRT_NM>, <EU_127>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT1(GPR[TRT_NM]);
+ GPR[TRT_NM] = EU_127;
+ TRACE_ALU_RESULT(GPR[TRT_NM]);
+}
+
+011101,1.RT1,1.U2,3.RT2,1.RS1,1.U3,3.RS2:R6P16:16::LW4X4
+"lw r<RT_5_BIT_NM>, <U_LW4X4>(r<RS_5_BIT_NM>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+ do_lw (SD_, RT_5_BIT_NM, U_LW4X4, RS_5_BIT_NM);
+}
+
+000101,3.RT,3.RS,4.U:R6P16:16::LW16
+"lw r<TRT_NM>, <U_SHIFT_2BIT>(r<TRS_NM>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lw (SD_, TRT_NM, U_SHIFT_2BIT, TRS_NM);
+}
+
+010101,3.RT,7.U:R6P16:16::LWGP16
+"lw r<TRT_NM>, <U_SHIFT_2BIT>(gp)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lw (SD_, TRT_NM, U_SHIFT_2BIT, GPIDX);
+}
+
+001101,5.RT,5.U:R6P16:16::LWSP
+"lw r<RT>, <U_SHIFT_2BIT>(sp)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lw (SD_, RT, U_SHIFT_2BIT, SPIDX);
+}
+
+010100,3.RT,3.RS,3.RD,1:R6P16C:16::LWXS16
+"lwxs r<TRD_NM>, r<TRS_NM>(r<TRT_NM>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lw (SD_, TRD_NM, GPR[TRS_NM] << 2, TRT_NM);
+}
+
+// These four instructions are grouped together because of a bug in GNUSIM
+// pattern recognition
+000100,5.RT,2.RS1,1.RS_CODE_1,2.RS_CODE_2:R6P16MOVE:16::P16MOVE_P16RI
+"move r<RT>, r<RS_MOVE>": RT != 0
+"syscall <RS_CODE_2>": RS1 == 1
+"sdbbp <CODE_BREAK>": RS1 == 3
+"break <CODE_BREAK>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ if (RT == 0) {
+ if (RS1 == 1)
+ SignalException (SystemCall, instruction_0);
+ else if (RS1 == 3)
+ SignalException (DebugBreakPoint, instruction_0);
+ else
+ do_break_nanomips (SD_, instruction_0);
+ }
+ else {
+ TRACE_ALU_INPUT2 (GPR[RT], GPR[RS_MOVE]);
+ GPR[RT] = GPR[RS_MOVE];
+ TRACE_ALU_RESULT2 (GPR[RT], GPR[RS_MOVE]);
+ }
+}
+
+101111,1.RT4,1.RD20,3.RT2_0,1.RS4,1.RD21,3.RS2_0:R6P16:16::MOVEP
+"movep r<TRD2>, r<TRE2>, r<TRS2>, r<TRT2>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+ TRACE_ALU_INPUT4 (GPR[TRD2], GPR[TRE2], GPR[TRS2], GPR[TRT2]);
+ GPR[TRD2] = GPR[TRS2];
+ GPR[TRE2] = GPR[TRT2];
+ TRACE_ALU_RESULT2 (GPR[TRD2], GPR[TRE2]);
+
+ // For cycle counting
+ COP0_COUNT++;
+}
+
+111111,1.RE4,1.RS20,3.RE2_0,1.RD4,1.RS21,3.RD2_0:R6P16:16::MOVEPREV
+"movep r<TRD2_REV>, r<TRE2_REV>, r<TRS2_REV>, r<TRT2_REV>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+ TRACE_ALU_INPUT4 (GPR[TRD2_REV], GPR[TRE2_REV], GPR[TRS2_REV], GPR[TRT2_REV]);
+ GPR[TRD2_REV] = GPR[TRS2_REV];
+ GPR[TRE2_REV] = GPR[TRT2_REV];
+ TRACE_ALU_RESULT2 (GPR[TRD2_REV], GPR[TRE2_REV]);
+
+ // For cycle counting
+ COP0_COUNT++;
+}
+
+010100,3.RT,3.RS,00,0,0:R6POOL16C00:16::NOT16
+"not r<TRT_NM>, r<TRS_NM>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_nor (SD_, 0, TRS_NM, TRT_NM);
+}
+
+010100,3.RT,3.RS,11,0,0:R6POOL16C00:16::OR16
+"or r<TRT_NM>, r<TRS_NM>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_or (SD_, TRS_NM, TRT_NM, TRT_NM);
+}
+
+000111,1.RT1,1,4.U,4.GPR_LIST_SAVE:R6P16SR:16::RESTORE.JRC16
+"restore.jrc <U_SHIFT_4BIT>":GPR_LIST_SAVE==15
+"restore.jrc <U_SHIFT_4BIT>, ra, %s<GPR_LIST_SAVE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ if (RT1 == 0)
+ do_restore_gprs_from_stack_and_adjust_sp(SD_, 30, GPR_LIST_SAVE, 0,
+ U_SHIFT_4BIT);
+ else
+ do_restore_gprs_from_stack_and_adjust_sp(SD_, 31, GPR_LIST_SAVE, 0,
+ U_SHIFT_4BIT);
+ NIA = RA;
+}
+
+000111,1.RT1,0,4.U,4.GPR_LIST_SAVE:R6P16SR:16::SAVE16
+"save <U_SHIFT_4BIT>, ra": GPR_LIST_SAVE == 0
+"save <U_SHIFT_4BIT>, ra, %s<GPR_LIST_SAVE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ if (RT1 == 0)
+ do_save_gprs_to_stack_and_adjust_sp(SD_, 30, GPR_LIST_SAVE, 0, U_SHIFT_4BIT);
+ else
+ do_save_gprs_to_stack_and_adjust_sp(SD_, 31, GPR_LIST_SAVE, 0, U_SHIFT_4BIT);
+
+}
+
+010111,3.RTZ,3.RS,01,2.U:R6P16LB:16::SB16
+"sb r<TRTZ>, <U>(r<TRS_NM>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_store (SD_, AccessLength_BYTE, GPR[TRS_NM], U, GPR[TRTZ]);
+}
+
+011111,3.RTZ,3.RS,0,2.U,1:R6P16LH:16::SH16
+"sh r<TRTZ>, <U_SHIFT_1BIT>(r<TRS_NM>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_store (SD_, AccessLength_HALFWORD, GPR[TRS_NM], U_SHIFT_1BIT, GPR[TRTZ]);
+}
+
+001100,3.RT,3.RS,0,3.SHIFT:R6P16SHIFT:16::SLL16
+"sll r<TRT_NM>, r<TRS_NM>, <SHIFT_DEC>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_sll (SD_, TRS_NM, TRT_NM, SHIFT_DEC);
+}
+
+001100,3.RT,3.RS,1,3.SHIFT:R6P16SHIFT:16::SRL16
+"srl r<TRT_NM>, r<TRS_NM>, <SHIFT_DEC>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_srl (SD_, TRS_NM, TRT_NM, SHIFT_DEC);
+}
+
+101100,3.RT,3.RS,3.RD,1:R6P16ADDU:16::SUBU16
+"subu r<TRD_NM>, r<TRS_NM>, r<TRT_NM>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_subu (SD_, TRS_NM, TRT_NM, TRD_NM);
+}
+
+100101,3.RTZ,3.RS,4.U:R6P16:16::SW16
+"sw r<TRTZ>, <U_SHIFT_2BIT>(r<TRS_NM>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_store (SD_, AccessLength_WORD, GPR[TRS_NM], U_SHIFT_2BIT, GPR[TRTZ]);
+}
+
+101101,5.RT,5.U:R6P16:16::SWSP
+"sw r<RT>, <U_SHIFT_2BIT>(sp)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_store (SD_, AccessLength_WORD, SP, U_SHIFT_2BIT, GPR[RT]);
+}
+
+010100,3.RT,3.RS,01,0,0:R6POOL16C00:16::XOR16
+"xor r<TRT_NM>, r<TRS_NM>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_xor (SD_, TRT_NM, TRS_NM, TRT_NM);
+}
+
+// 32-bit instructions
+
+001000,5.RT,5.RS,5.RD,1.X,0100010,000:R6POOL32A0:32::ADD
+"add r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+ do_add (SD_, RS, RT, RD);
+}
+
+000000,5.RT!0,5.RS,16.U:R6PPADDIU:32::ADDIU
+"addiu r<RT>, r<RS>, <U>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_addiu (SD_, RS, RT, U);
+}
+
+010001,5.RT,011,18.U:R6PGPBH:32::ADDIUGPB
+"addiu r<RT>, GP, <U>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_addiu (SD_, GPIDX, RT, U);
+}
+
+010000,5.RT,19.U,00:R6PGPW:32::ADDIUGPW
+"addiu r<RT>, GP, <U_SHIFT_2BIT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_addiu (SD_, GPIDX, RT, U_SHIFT_2BIT);
+}
+
+111000,5.RT,9.S1,10.S2,1,1.S3:R6PLUI:32::ALUIPC
+"aluipc r<RT>, <AXUIPC_S_HI>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ address_word address = NIA + AXUIPC_S;
+
+ TRACE_ALU_INPUT2(GPR[RT], address);
+ GPR[RT] = address & ~0xfff;
+ TRACE_ALU_RESULT(GPR[RT]);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0101010,000:R6POOL32A0:32::ADDU
+"addu r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_addu (SD_, RS, RT, RD);
+}
+
+001000,5.RT,5.RS,5.RD,5.IMMEDIATE,011,111:R6POOL32A0:32::EXTW
+"prepend r<RT>, r<RS>, <IMMEDIATE>": RD == RS
+"align r<RD>, r<RS>, r<RT>, <IMMEDIATE>": IMMEDIATE != 0
+"extw r<RD>, r<RS>, r<RT>, <IMMEDIATE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ if (IMMEDIATE != 0) {
+ uint64_t tmp = ((uint64_t)GPR[RT] << 32) | (0xffffffff & GPR[RS]);
+ TRACE_ALU_INPUT4 (GPR[RD], GPR[RS], GPR[RT], tmp);
+ GPR[RD] = EXTEND32 (tmp >> IMMEDIATE);
+ TRACE_ALU_RESULT (GPR[RD]);
+ } else {
+ TRACE_ALU_INPUT2 (GPR[RD], GPR[RT]);
+ GPR[RD] = GPR[RT];
+ TRACE_ALU_RESULT (GPR[RD]);
+ }
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1001010,000:R6POOL32A0:32::AND
+"and r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_and (SD_, RS, RT, RD);
+}
+
+100000,5.RT,5.RS,0010,12.U:R6PU12:32::ANDI
+"andi r<RT>, r<RS>, <U>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_andi (SD_, RS, RT, U);
+}
+
+001010,1,24.S1,1.S2:R6PBAL:32::BALC
+"balc <ADDRESS26>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT1(RA);
+ RA = NIA;
+ NIA = ADDRESS26;
+ TRACE_ALU_RESULT(RA);
+
+ // For cycle counting
+ COP0_COUNT++;
+}
+
+001010,0,24.S1,1.S2:R6PBAL:32::BC
+"bc <ADDRESS26>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ NIA = ADDRESS26;
+}
+
+100010,5.RT,5.RS,00,13.S1,1.S2:R6PBR1:32::BEQC
+"beqc r<RS>, r<RT>, <ADDRESS15>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(GPR[RS], GPR[RT]);
+ if (GPR[RS] == GPR[RT])
+ NIA = ADDRESS15;
+}
+
+110010,5.RT,000,7.U,10.S1,1.S2:P7PBRI:32::BEQIC
+"beqic r<RT>, <U>, <ADDRESS12>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(GPR[RT], U);
+ if (GPR[RT] == U) {
+ NIA = ADDRESS12;
+ }
+}
+
+100010,5.RT,5.RS,10,13.S1,1.S2:P7PBR1:32::BGEC
+"bgec r<RS>, r<RT>, <ADDRESS15>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(GPR[RS], GPR[RT]);
+ if ((signed_word) GPR[RS] >= (signed_word) GPR[RT])
+ NIA = ADDRESS15;
+}
+
+110010,5.RT,010,7.U,10.S1,1.S2:P7PBRI:32::BGEIC
+"bgeic r<RT>, <U>, <ADDRESS12>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(GPR[RT], U);
+ if ((signed_word) GPR[RT] >= U) {
+ NIA = ADDRESS12;
+ }
+}
+
+100010,5.RT,5.RS,11,13.S1,1.S2:P7PBR2:32::BGEUC
+"bgeuc r<RS>, r<RT>, <ADDRESS15>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(GPR[RS], GPR[RT]);
+ if ((unsigned_word) (GPR[RS]) >= (unsigned_word)(GPR[RT])) {
+ NIA = ADDRESS15;
+ }
+}
+
+110010,5.RT,011,7.U,10.S1,1.S2:P7PBRI:32::BGEUIC
+"bgeuic r<RT>, <U>, <ADDRESS12>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(GPR[RT], U);
+ if ((unsigned_word) GPR[RT] >= U) {
+ NIA = ADDRESS12;
+ }
+}
+
+101010,5.RT,5.RS,10,13.S1,1.S2:P7PBR2:32::BLTC
+"bltc r<RS>, r<RT>, <ADDRESS15>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(GPR[RS], GPR[RT]);
+ if ((signed_word) GPR[RS] < (signed_word) GPR[RT])
+ NIA = ADDRESS15;
+}
+
+110010,5.RT,110,7.U,10.S1,1.S2:P7PBRI:32::BLTIC
+"bltic r<RT>, <U>, <ADDRESS12>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(GPR[RT], U);
+ if ((signed_word) GPR[RT] < U) {
+ NIA = ADDRESS12;
+ }
+}
+
+101010,5.RT,5.RS,11,13.S1,1.S2:P7PBR2:32::BLTUC
+"bltuc r<RS>, r<RT>, <ADDRESS15>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(GPR[RS], GPR[RT]);
+ if ((unsigned_word) GPR[RS] < (unsigned_word) GPR[RT]) {
+ NIA = ADDRESS15;
+ }
+}
+
+110010,5.RT,111,7.U,10.S1,1.S2:P7PBRI:32::BLTIUC
+"bltiuc <RT>, <U>, <ADDRESS12>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(GPR[RT], U);
+ if ((unsigned_word) GPR[RT] < U) {
+ NIA = ADDRESS12;
+ }
+}
+
+101010,5.RT,5.RS,00,13.S1,1.S2:R6PBR2:32::BNEC
+"bnec r<RS>, r<RT>, <ADDRESS15>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(GPR[RS], GPR[RT]);
+ if (GPR[RS] != GPR[RT])
+ NIA = ADDRESS15;
+}
+
+110010,5.RT,100,7.U,10.S1,1.S2:R6PBRI:32::BNEIC
+"bneic r<RT>, <U>, <ADDRESS12>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(GPR[RT], U);
+ if (GPR[RT] != U) {
+ NIA = ADDRESS12;
+ }
+}
+
+000000,00000,10,19.CODE:R6PRI:32::BREAK
+"break %#lx<CODE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_break_nanomips (SD_, instruction_0);
+}
+
+101001,5.OP,5.RS,1.S1,0111,0,01,8.S2:R6PLSS1:32::CACHE
+"cache <OP>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_cache (SD_, OP, RS, S_9_BIT, instruction_0);
+}
+
+001000,5.RT,5.RS,0100101,100,111,111:R6POOL32AXF4:32::CLO
+"clo r<RT>, r<RS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+ do_clo (SD_, RT, RS);
+}
+
+001000,5.RT,5.RS,0101101,100,111,111:R6POOL32AXF4:32::CLZ
+"clz r<RT>, r<RS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+ do_clz (SD_, RT, RS);
+}
+
+001000,5.RT,5.X,01,00011,101,111,111:R6POOL32AXF5GROUP1:32::DI
+"di":RT == 0
+"di r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_di (SD_, RT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0100011,000:R6POOL32A0:32::DIV
+"div r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_div (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0110011,000:R6POOL32A0:32::DIVU
+"divu r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_divu (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.X,01,01011,101,111,111:R6POOL32AXF5GROUP1:32::EI
+"ei":RT == 0
+"ei r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_ei (SD_, RT);
+}
+
+001000,9.X,0,11,11001,101,111,111:R6ERETX:32::ERET
+"eret"
+*nanomips32r6:
+*nanomips64r6:
+{
+ NIA = do_eret(SD_, 0, NIA);
+}
+
+001000,9.X,1,11,11001,101,111,111:R6ERETX:32::ERETNC
+"eretnc"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+ SignalException (ReservedInstruction, instruction_0);
+ NIA = do_eret(SD_, 1, NIA);
+}
+
+100000,5.RT,5.RS,1111,0,5.MSBD,0,5.LSB:R6PEXT:32::EXT
+"ext r<RT>, r<RS>, <LSB>, <MSBD+1>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+ if (LSB + MSBD + 1 > 32)
+ Unpredictable ();
+
+ do_ext (SD_, RT, RS, LSB, MSBD);
+}
+
+100000,5.RT,5.RS,1110,0,5.MSBD,0,5.LSB:R6PINS:32::INS
+"ins r<RT>, r<RS>, <INS_POS>, <INS_SIZE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+ if ((1 + MSBD - LSB) < 1)
+ Unpredictable ();
+ do_ins (SD_, RT, RS, LSB, MSBD);
+}
+
+100000,5.RT,5.RS,1101,0,4.SHIFTX,1.STRIPE,0,5.SHIFT:R6PROTX:32::ROTX
+"bitrev r<RT>, r<RS>": SHIFT == 31 && SHIFTX_1BIT == 0
+"bitswap r<RT>, r<RS>": SHIFT == 7 && SHIFTX_1BIT == 8 && STRIPE == 1
+"bitswap.h r<RT>, r<RS>": SHIFT == 15 && SHIFTX_1BIT == 16
+"byteswap r<RT>, r<RS>": SHIFT == 24 && SHIFTX_1BIT == 8
+"wsbh r<RT>, r<RS>": SHIFT == 8 && SHIFTX_1BIT == 24
+"rotx r<RT>, r<RS>, <SHIFT>, <SHIFTX_1BIT>": STRIPE == 0
+"rotx r<RT>, r<RS>, <SHIFT>, <SHIFTX_1BIT>, <STRIPE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+
+ TRACE_ALU_INPUT4 (GPR[RT], GPR[RS], SHIFT, SHIFTX_1BIT);
+ do_rotx (SD_, RT, RS, SHIFT, SHIFTX_1BIT, STRIPE);
+ TRACE_ALU_RESULT (GPR[RT]);
+}
+
+010010,5.RT,5.RS,0000,12.X:R6PJ:32::JALRC
+"jalrc r<RT>, r<RS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ unsigned_word address;
+ TRACE_ALU_INPUT3(GPR[RT], GPR[RS], RA);
+ GPR[RT] = NIA;
+ address = GPR[RS];
+ NIA = address;
+
+ // For cycle counting
+ COP0_COUNT++;
+ TRACE_ALU_RESULT(NIA);
+
+}
+
+010010,5.RT,5.RS,0001,12.X:R6PJ:32::JALRC.HB
+"jalrc.hb r<RT>, r<RS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ unsigned_word address;
+ GPR[RT] = NIA;
+ address = GPR[RS];
+ NIA = address;
+
+ // For cycle counting
+ COP0_COUNT++;
+}
+
+100001,5.RT,5.RS,0000,12.U:R6PLSU12:32::LB
+"lb r<RT>, <U>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lb (SD_, RT, U, RS);
+}
+
+010001,5.RT,000,18.U:R6PLSGP:32::LBGP
+"lb r<RT>, <U>(GP)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lb (SD_, RT, U, GPIDX);
+}
+
+101001,5.RT,5.RS,1.S1,0000,0,00,8.S2:R6PLSS0:32::LBS9
+"lb r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lb (SD_, RT, S_9_BIT, RS);
+}
+
+100001,5.RT,5.RS,0010,12.U:R6PLSU12:32::LBU
+"lbu r<RT>, <U>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lbu (SD_, RT, U, RS);
+}
+
+010001,5.RT,010,18.U:R6GPBH:32::LBUGP
+"lbu r<RT>, <U>(GP)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2 (U, GP);
+ do_lbu (SD_, RT, U, GPIDX);
+ TRACE_ALU_RESULT (GPR[RT]);
+}
+
+101001,5.RT,5.RS,1.S1,0010,0,00,8.S2:R6PLSS0:32::LBUS9
+"lbu r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lbu (SD_, RT, S_9_BIT, RS);
+}
+
+001000,5.RT,5.RS,5.RD,0010,0,000,111:R6PPLSX:32::LBUX
+"lbux r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lbu (SD_, RD, GPR[RS], RT);
+}
+
+001000,5.RT,5.RS,5.RD,0000,0,000,111:R6PPLSX:32::LBX
+"lbx r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lb (SD_, RD, GPR[RS], RT);
+}
+
+100001,5.RT,5.RS,0100,12.U:R6PLSU12:32::LH
+"lh r<RT>, <U>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lh (SD_, RT, U, RS);
+}
+
+010001,5.RT,100,17.U,0:R6PGPLH:32::LHGP
+"lh r<RT>, <U_SHIFT_1BIT>(GP)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lh (SD_, RT, U_SHIFT_1BIT, GPIDX);
+}
+
+101001,5.RT,5.RS,1.S1,0100,0,00,8.S2:R6PLSS0:32::LHS9
+"lh r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lh (SD_, RT, S_9_BIT, RS);
+}
+
+100001,5.RT,5.RS,0110,12.U:R6PLSU12:32::LHU
+"lhu r<RT>, <U>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lhu (SD_, RT, U, RS);
+}
+
+010001,5.RT,100,17.U,1:R6PLSGP:32::LHUGP
+"lhu r<RT>, <U_SHIFT_1BIT>(gp)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lhu (SD_, RT, U_SHIFT_1BIT, GPIDX);
+}
+
+101001,5.RT,5.RS,1.S1,0110,0,00,8.S2:R6PLSS0:32::LHUS9
+"lhu r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lhu (SD_, RT, S_9_BIT, RS);
+}
+
+001000,5.RT,5.RS,5.RD,0110,0,000,111:R6PPLSX:32::LHUX
+"lhux r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lhu (SD_, RD, GPR[RS], RT);
+}
+
+001000,5.RT,5.RS,5.RD,0110,1,000,111:R6PPLSXS:32::LHUXS
+"lhux r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lhu (SD_, RD, GPR[RS] << 1, RT);
+}
+
+001000,5.RT,5.RS,5.RD,0100,0,000,111:R6PPLSX:32::LHX
+"lhx r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lh (SD_, RD, GPR[RS], RT);
+}
+
+001000,5.RT,5.RS,5.RD,0100,1,000,111:R6PPLSXS:32::LHXS
+"lhxs r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lh (SD_, RD, GPR[RS] << 1, RT);
+}
+
+101001,5.RT,5.RS,1.S1,1010,0,01,6.S2,00:R6PLL:32::LL
+"ll r<RT>, <S_9_BIT_LLSC>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT3(GPR[RT], S_9_BIT_LLSC, GPR[RS]);
+ do_ll (SD_, RT, S_9_BIT_LLSC, RS);
+ TRACE_ALU_RESULT(GPR[RT]);
+}
+
+101001,5.RT,5.RS,1.X1,1010,0,01,5.RU,1.X2,01:R6PLL:32::LLWP
+"llwp r<RT>, r<RU>, (r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_llwp (SD_, RT, RU, 0, RS);
+}
+
+001000,5.RT,5.RS,5.RD,2.U,3.X,001,111:R6POOL32A7:32::LSA
+"lsa r<RD>, r<RS>, r<RT>, <U>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lsa (SD_, RD, RS, RT, U);
+}
+
+111000,5.RT,9.S1,10.S2,0,1.S3:R6PLUI:32::LUI
+"lui r<RT>, <AXUIPC_S_HI>, <AXUIPC_S_LO>":AXUIPC_S_LO != 0
+"lui r<RT>, <AXUIPC_S_HI>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2 (GPR[RT], AXUIPC_S);
+ GPR[RT] = AXUIPC_S;
+ TRACE_ALU_RESULT (GPR[RT]);
+}
+
+100001,5.RT,5.RS,1000,12.U:R6PLSU12:32::LW
+"lw r<RT>, <U>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT3 (GPR[RT], U, GPR[RS]);
+ do_lw (SD_, RT, U, RS);
+ TRACE_ALU_RESULT (GPR[RT]);
+}
+
+101001,5.RT,5.RS,1.S1,1000000,8.S2:R6PLSS0:32::LWS9
+"lw r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lw (SD_, RT, S_9_BIT, RS);
+}
+
+101001,5.RT,5.RS,1.S1,3.COUNT3,0,1,00,8.S2:R6PLSWM:32::LWM
+"lwm r<RT>, <S_9_BIT>(r<RS>), <COUNT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ int counter = 0;
+ int dest;
+ int this_offset;
+
+ check_nms_flag (SD_);
+
+ while (counter != COUNT)
+ {
+ dest = (RT & 0x10) | ((RT + counter) & 0x1F);
+
+ if ((dest == RS) && (counter != (COUNT - 1)))
+ Unpredictable ();
+
+ this_offset = S_9_BIT + (counter << 2);
+
+ do_lw (SD_, dest, this_offset, RS);
+
+ counter++;
+ if (counter != 0)
+ COP0_COUNT++;
+ }
+}
+
+010000,5.RT,19.U,10:R6PGPW:32::LWGP
+"lw r<RT>, <U_SHIFT_2BIT>(GP)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(GPR[RT], GPR[RT]);
+ do_lw (SD_, RT, U_SHIFT_2BIT, GPIDX);
+ TRACE_ALU_RESULT(GPR[RT]);
+}
+
+011000,5.RT,01011,16.IMM48:R6POOL48I:32::LWPC48
+"lwpc r<RT>, <IMM48>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ uint16_t S2;
+ uint32_t total;
+ check_nms_flag (SD_);
+ S2 = do_load(SD_, AccessLength_HALFWORD, CIA + 4, 0);
+ total = S2 << 16 | IMM48;
+
+ do_lwpc_nanomips (SD_, RT, total, CIA + 6);
+ NIA = CIA + 6;
+}
+
+001000,5.RT,5.RS,5.RD,1000,0,000,111:R6PPLSX:32::LWX
+"lwx r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lw (SD_, RD, GPR[RS], RT);
+}
+
+001000,5.RT,5.RS,5.RD,1000,1,000,111:R6PPLSXS:32::LWXS
+"lwxs r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lw (SD_, RD, GPR[RS] << 2, RT);
+}
+
+001000,5.RT,5.C0S,5.SEL,1.X,0000110,000:R6POOL32A0:32::MFC0
+"mfc0 r<RT>, r<C0S>, <SEL>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ DecodeCoproc (instruction_0, 0, cp0_mfc0, RT, C0S, SEL);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0101011,000:R6POOL32A0:32::MOD
+"mod r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_mod (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0111011,000:R6POOL32A0:32::MODU
+"modu r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_modu (SD_, RD, RS, RT);
+}
+
+000010,1.RT1,1.RD,3.RT2,20.S1,1.S2:R6MOVEBALC:32::MOVE.BALC
+"move.balc r<RD1>, r<RT_5_BIT_NM_Z>, <ADDRESS22>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+ TRACE_ALU_INPUT2(GPR[RD1], GPR[RT_5_BIT_NM_Z]);
+ GPR[RD1] = GPR[RT_5_BIT_NM_Z];
+ RA = NIA;
+ NIA = ADDRESS22;
+ TRACE_ALU_RESULT(GPR[RD1]);
+
+ // For cycle counting
+ COP0_COUNT += 2;
+}
+
+001000,5.RT,5.RS,5.RD,1,1000010,000:R6PCMOVE:32::MOVN
+"movn r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(GPR[RS], GPR[RT]);
+ do_movn (SD_, RD, RS, RT);
+ TRACE_ALU_RESULT(GPR[RD]);
+}
+
+001000,5.RT,5.RS,5.RD,0,1000010,000:R6PCMOVE:32::MOVZ
+"movz r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_movz (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.C0S,5.SEL,1.X,0001110,000:R6POOL32A0:32::MTC0
+"mtc0 r<RT>, r<C0S>, <SEL>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ DecodeCoproc (instruction_0, 0, cp0_mtc0, RT, C0S, SEL);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0001011,000:R6POOL32A0:32::MUH
+"muh r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_muh (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0011011,000:R6POOL32A0:32::MUHU
+"muhu r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_muhu (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0000011,000:R6POOL32A0:32::MUL32
+"mul r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_mul (SD_, RD, RS, RT);
+}
+
+001111,1.RT1,0,3.RT2,1.RS1,1,3.RS2:R6P164X4:16::MUL4X4
+"mul r<RT_5_BIT_NM>, r<RS_5_BIT_NM>, r<RT_5_BIT_NM>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+ do_mul (SD_, RT_5_BIT_NM, RS_5_BIT_NM, RT_5_BIT_NM);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0010011,000:R6POOL32A0:32::MULU
+"mulu r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_mulu (SD_, RD, RS, RT);
+}
+
+100000,00000,5.X1,1100,3.X2,0000,00000:R6PSLL:32::NOP32
+"nop"
+*nanomips32r6:
+*nanomips64r6:
+{
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1011010,000:R6POOL32A0:32::NOR
+"nor r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_nor (SD_, RS, RT, RD);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1010010,000:R6POOL32A0:32::OR32
+"or r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_or (SD_, RS, RT, RD);
+}
+
+100000,5.RT,5.RS,0000,12.U:R6PU12:32::ORI
+"ori r<RT>, r<RS>, <U>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_ori (SD_, RS, RT, U);
+}
+
+100000,00000,5.X1,1100,3.X2,0000,00101:R6PSLL:32::PAUSE
+"pause"
+*nanomips32r6:
+*nanomips64r6:
+{
+ sim_io_printf (SD, "Not implemented");
+}
+
+101001,5.HINT!31,5.RS,1.S1,0011,0,00,8.S2:R6PPREFS9:32::PREFS9
+"pref <HINT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_pref (SD_, HINT, S_9_BIT, RS);
+}
+
+100001,5.HINT,5.RS,0011,12.U:R6PLSU12:32::PREFU12
+"pref <HINT>, <U>(r<RS>)": HINT != 31
+"synci <U>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ if (HINT != 31)
+ do_pref (SD_, HINT, U, RS);
+ else
+ {
+ // synci - nothing to do currently
+ sim_io_printf (SD, "Not implemented");
+ }
+}
+
+100000,5.RT,0,4.GPR_LIST_SAVE,0011,9.U,1.GP_SAVE,10:R6PPSR:32::RESTORE
+"restore <U_SHIFT_3BIT>, r<RT>": GPR_LIST_SAVE == 0
+"restore <U_SHIFT_3BIT>, r<RT>, %s<GPR_LIST_SAVE>": !GP_SAVE && GPR_LIST_SAVE != 0
+"restore <U_SHIFT_3BIT>, r<RT>": !GP_SAVE && GPR_LIST_SAVE < 2
+"restore <U_SHIFT_3BIT>, r<RT>, %s<GPR_LIST_SAVE>" : !GP_SAVE && GPR_LIST_SAVE >=2
+"restore <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>": GP_SAVE && GPR_LIST_SAVE < 2
+"restore <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>, %s<GPR_LIST_SAVE>" : GP_SAVE && GPR_LIST_SAVE >=2
+"restore <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>": GP_SAVE && GPR_LIST_SAVE < 3
+"restore <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>, %s<GPR_LIST_SAVE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_restore_gprs_from_stack_and_adjust_sp(SD_, RT, GPR_LIST_SAVE,
+ GP_SAVE, U_SHIFT_3BIT);
+}
+
+100000,5.RT,0,4.GPR_LIST_SAVE,0011,9.U,1.GP_SAVE,11:R6PPSR:32::RESTORE.JRC
+"restore.jrc <U_SHIFT_3BIT>, r<RT>": GPR_LIST_SAVE == 0
+"restore.jrc <U_SHIFT_3BIT>, r<RT>, %s<GPR_LIST_SAVE>": !GP_SAVE && GPR_LIST_SAVE != 0
+"restore.jrc <U_SHIFT_3BIT>, r<RT>": !GP_SAVE && GPR_LIST_SAVE < 2
+"restore.jrc <U_SHIFT_3BIT>, r<RT>, %s<GPR_LIST_SAVE>" : !GP_SAVE && GPR_LIST_SAVE >=2
+"restore.jrc <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>": GP_SAVE && GPR_LIST_SAVE < 2
+"restore.jrc <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>, %s<GPR_LIST_SAVE>" : GP_SAVE && GPR_LIST_SAVE >=2
+"restore.jrc <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>": GP_SAVE && GPR_LIST_SAVE < 3
+"restore.jrc <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>, %s<GPR_LIST_SAVE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_restore_gprs_from_stack_and_adjust_sp(SD_, RT, GPR_LIST_SAVE,
+ GP_SAVE, U_SHIFT_3BIT);
+
+ NIA = GPR[RAIDX];
+}
+
+100000,5.RT,5.RS,1100,3.X,0110,5.SHIFT:R6PSHIFT:32::ROTR
+"rotr r<RT>, r<RS>, <SHIFT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ GPR[RT] = do_ror (SD_, GPR[RS], SHIFT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0011010,000:R6POOL32A0:32::ROTRV
+"rotrv r<RD>, r<RT>, r<RS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ uint32_t shift = GPR[RT] & 0x1f;
+ GPR[RD] = do_ror (SD_, GPR[RS], shift);
+}
+
+001000,5.RT,5.RS,5.RD,0,1100010,000:R6POOL32A0:32::XOR
+"xor r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_xor (SD_, RS, RT, RD);
+}
+
+100000,5.RT,5.RS,0001,12.U:R6PU12:32::XORI
+"xori r<RT>, r<RS>, <U>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_xori (SD_, RS, RT, U);
+}
+
+100000,5.RT,0,4.GPR_LIST_SAVE,0011,9.U,1.GP_SAVE,00:R6PPSR:32::SAVE
+"save <U_SHIFT_3BIT>, r<RT>": GPR_LIST_SAVE == 0
+"save <U_SHIFT_3BIT>, r<RT>, %s<GPR_LIST_SAVE>": !GP_SAVE && GPR_LIST_SAVE != 0
+"save <U_SHIFT_3BIT>, r<RT>": !GP_SAVE && GPR_LIST_SAVE < 2
+"save <U_SHIFT_3BIT>, r<RT> %s<GPR_LIST_SAVE>" : !GP_SAVE && GPR_LIST_SAVE >=2
+"save <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>": GP_SAVE && GPR_LIST_SAVE < 2
+"save <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>, %s<GPR_LIST_SAVE>" : GP_SAVE && GPR_LIST_SAVE >=2
+"save <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>": GP_SAVE && GPR_LIST_SAVE < 3
+"save <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>, %s<GPR_LIST_SAVE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_save_gprs_to_stack_and_adjust_sp(SD_, RT, GPR_LIST_SAVE,
+ GP_SAVE, U_SHIFT_3BIT);
+}
+
+100001,5.RT,5.RS,0001,12.U:R6PLSU12:32::SBU12
+"sb r<RT>, <U>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_store (SD_, AccessLength_BYTE, GPR[RS], U, GPR[RT]);
+}
+
+010001,5.RT,001,18.U:R6PGPBH:32::SBGP
+"sb r<RT>, <U>(gp)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_store (SD_, AccessLength_BYTE, GP, U, GPR[RT]);
+}
+
+101001,5.RT,5.RS,1.S1,0001,0,00,8.S2:R6PLSS0:32::SBS9
+"sb r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_store (SD_, AccessLength_BYTE, GPR[RS], S_9_BIT, GPR[RT]);
+}
+
+001000,5.RT,5.RS,5.RD,0001,0,000,111:R6PPLSX:32::SBX
+"sbx r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+ do_store (SD_, AccessLength_BYTE, GPR[RT], GPR[RS], GPR[RD]);
+}
+
+101001,5.RT,5.RS,1.S1,1011,0,01,6.S2,00:R6PSC:32::SC
+"sc r<RT>, <S_9_BIT_LLSC>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_sc (SD_, RT, S_9_BIT_LLSC, RS, instruction_0, 1);
+}
+
+101001,5.RT,5.RS,1.X1,1011,0,01,5.RU,1.X,01:R6PSC:32::SCWP
+"scwp r<RT>, r<RU>, (r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ int offset = BigEndianCPU ? 0 : 4;
+
+ do_sc (SD_, RU, offset, RS, instruction_0, 0);
+ do_sc (SD_, RT, offset ^ 4, RS, instruction_0, 1);
+}
+
+001000,5.RT,5.RS,6.X,0000001,000:R6POOL32A0:32::SEB
+"seb r<RT>, r<RS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+ do_seb (SD_, RT, RS);
+}
+
+001000,5.RT,5.RS,6.X,0001001,000:R6POOL32A0:32::SEH
+"seh r<RT>, r<RS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_seh (SD_, RT, RS);
+}
+
+100000,5.RT,5.RS,0110,12.IMMEDIATE:R6PU12:32::SEQI
+"seqi r<RT>, r<RS>, <IMMEDIATE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT3(GPR[RT], GPR[RS], IMMEDIATE);
+ GPR[RT] = (GPR[RS] == IMMEDIATE) ? 1 : 0;
+ TRACE_ALU_RESULT(GPR[RT]);
+}
+
+100001,5.RT,5.RS,0101,12.U:R6PLSU12:32::SHU12
+"sh r<RT>, <U>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_store (SD_, AccessLength_HALFWORD, GPR[RS], U, GPR[RT]);
+}
+
+010001,5.RT,101,17.U,0:R6PGPSH:32::SHGP
+"sh r<RT>, <U_SHIFT_1BIT>(GP)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_store (SD_, AccessLength_HALFWORD, GP, U_SHIFT_1BIT, GPR[RT]);
+}
+
+101001,5.RT,5.RS,1.S1,0101,0,00,8.S2:R6PLSS0:32::SHS9
+"sh r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_store (SD_, AccessLength_HALFWORD, GPR[RS], S_9_BIT, GPR[RT]);
+}
+
+001000,5.RT,5.RS,5.RD,0101,0,000,111:R6PPLSX:32::SHX
+"shx r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+ do_store (SD_, AccessLength_HALFWORD, GPR[RT], GPR[RS], GPR[RD]);
+}
+
+001000,5.RT,5.RS,5.RD,0101,1,000,111:R6PPLSXS:32::SHXS
+"shxs r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+ do_store (SD_, AccessLength_HALFWORD, GPR[RT], GPR[RS] << 1, GPR[RD]);
+}
+
+000000,00000,00,19.CODE:R6PRI:32::SIGRIE
+"sigrie %#lx<CODE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ SignalException (ReservedInstruction, instruction_0);
+}
+
+100000,5.RT!0,5.RS,1100,3.X,0000,5.SHIFT:R6PSLL:32::SLL32
+"sll r<RT>, r<RS>, <SHIFT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_sll (SD_, RS, RT, SHIFT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0000010,000:R6POOL32A0:32::SLLV
+"sllv r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_sllv (SD_, RT, RS, RD);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1101010,000:R6POOL32A0:32::SLT
+"slt r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_slt (SD_, RS, RT, RD);
+}
+
+100000,5.RT,5.RS,0100,12.IMMEDIATE:R6PU12:32::SLTI
+"slti r<RT>, r<RS>, <IMMEDIATE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_slti (SD_, RS, RT, EXTEND12(IMMEDIATE));
+}
+
+100000,5.RT,5.RS,0101,12.U:R6PU12:32::SLTIU
+"sltiu r<RT>, r<RS>, <U>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_sltiu (SD_, RS, RT, EXTEND12(U));
+}
+
+001000,5.RT,5.RS,5.RD!0,1.X,1110010,000:R6PSLTU:32::SLTU
+"sltu r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_sltu (SD_, RS, RT, RD);
+}
+
+100000,5.RT,5.RS,1100,3.X,0100,5.SHIFT:R6PSHIFT:32::SRA
+"sra r<RT>, r<RS>, <SHIFT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_sra (SD_, RS, RT, SHIFT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0010010,000:R6POOL32A0:32::SRAV
+"srav r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_srav (SD_, RT, RS, RD);
+}
+
+100000,5.RT,5.RS,1100,3.X,0010,5.SHIFT:R6PSHIFT:32::SRL32
+"srl r<RT>, r<RS>, <SHIFT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_srl (SD_, RS, RT, SHIFT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0001010,000:R6POOL32A0:32::SRLV
+"srlv r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_srlv (SD_, RT, RS, RD);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0110010,000:R6POOL32A0:32::SUB
+"sub r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+ do_sub (SD_, RS, RT, RD);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0111010,000:R6POOL32A0:32::SUBU32
+"subu r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_subu (SD_, RS, RT, RD);
+}
+
+100001,5.RT,5.RS,1001,12.U:R6PLSU12:32::SWU12
+"sw r<RT>, <U>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_store (SD_, AccessLength_WORD, GPR[RS], U, GPR[RT]);
+}
+
+101001,5.RT,5.RS,1.S1,1001,0,00,8.S2:R6PLS0:32::SWS9
+"sw r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_store (SD_, AccessLength_WORD, GPR[RS], S_9_BIT, GPR[RT]);
+}
+
+010000,5.RT,19.U,11:R6PGPW:32::SWGP
+"sw r<RT>, <U_SHIFT_2BIT>(GP)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_store (SD_, AccessLength_WORD, GP, U_SHIFT_2BIT, GPR[RT]);
+}
+
+011000,5.RT,01111,16.IMM48:R6POOL48I:32::SWPC48
+"swpc r<RT>, <IMM48>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ uint16_t U2;
+ uint32_t total;
+ check_nms_flag (SD_);
+ U2 = do_load (SD_, AccessLength_HALFWORD, CIA + 4, 0);
+ total = U2 << 16 | IMM48;
+ TRACE_ALU_INPUT2(GPR[RT], total);
+ do_store(SD_, AccessLength_WORD, CIA + 6, total, GPR[RT]);
+ TRACE_ALU_RESULT(GPR[RT]);
+ NIA = CIA + 6;
+}
+
+
+110101,3.RTZ,7.U:R6P16:16::SWGP16
+"sw r<TRTZ>, <U_SHIFT_2BIT>(GP)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_store (SD_, AccessLength_WORD, GP, U_SHIFT_2BIT, GPR[TRTZ]);
+}
+
+001000,5.RT,5.RS,5.RD,1001,0,000,111:R6PPLSX:32::SWX
+"swx r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+ do_store (SD_, AccessLength_WORD, GPR[RT], GPR[RS], GPR[RD]);
+}
+
+001000,5.RT,5.RS,5.RD,1001,1,000,111:R6PPLSXS:32::SWXS
+"swxs r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+ do_store (SD_, AccessLength_WORD, GPR[RT], GPR[RS] << 2, GPR[RD]);
+}
+
+111101,1.RT1,1.U2,3.RT2,1.RS1,1.U3,3.RS2:R6P16:16::SW4X4
+"sw r<RT_5_BIT_NM_Z>, <U_LW4X4>(r<RS_5_BIT_NM>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+ do_store (SD_, AccessLength_WORD, GPR[RS_5_BIT_NM], U_LW4X4, GPR[RT_5_BIT_NM_Z]);
+}
+
+101001,5.RT,5.RS,1.S1,3.COUNT3,1,1,00,8.S2:R6PLSWM:32::SWM
+"swm r<RT>, <S_9_BIT>(r<RS>), <COUNT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ int counter = 0;
+ int source;
+ int offsetm;
+
+ check_nms_flag (SD_);
+
+ while (counter != COUNT)
+ {
+ if (RT == 0)
+ source = 0;
+ else
+ source = (RT & 0x10) | ((RT + counter) & 0x1F);
+
+ offsetm = S_9_BIT + (counter << 2);
+
+ do_sw (SD_, source, offsetm, RS);
+
+ counter++;
+
+ if (counter != 0)
+ COP0_COUNT++;
+ }
+}
+
+100000,00000,5.STYPE,1100,3.X,0000,00110:R6PHB:32::SYNC
+"sync":STYPE==0
+"sync <STYPE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ SyncOperation (STYPE);
+}
+
+101001,11111,5.RS,1.S1,0011,0,00,8.S2:R6PPREFS:32::SYNCI
+"synci <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ // sync i-cache - nothing to do currently
+ sim_io_printf (SD, "Not implemented");
+}
+
+000000,00000,11,19.CODE:R6PRI:32::SDBBP32
+"sdbbp %#lx<CODE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ SignalException (DebugBreakPoint, instruction_0);
+}
+
+001000,10.X,00,00001,101,111,111:R6POOL32AXF5GROUP0:32::TLBP
+"tlbp"
+*nanomips32r6:
+*nanomips64r6:
+{
+ // nothing to do currently
+ sim_io_printf (SD, "Not implemented");
+}
+
+001000,10.X,00,10001,101,111,111:R6POOL32AXF5GROUP0:32::TLBWI
+"tlbwi"
+*nanomips32r6:
+*nanomips64r6:
+{
+ // nothing to do currently
+ sim_io_printf (SD, "Not implemented");
+}
+
+001000,10.X,00,11001,101,111,111:R6POOL32AXF5GROUP0:32::TLBWR
+"tlbwr"
+*nanomips32r6:
+*nanomips64r6:
+{
+ // nothing to do currently
+ sim_io_printf (SD, "Not implemented");
+}
+
+
+001000,0000000000,01,00001,101,111,111:R6POOL32AXF5GROUP1:32::TLBINV
+"tlbinv"
+*nanomips32r6:
+*nanomips64r6:
+{
+ // invalidate a set of TLB entries based on ASID and Index match - nothing to do currently
+ sim_io_printf (SD, "Not implemented");
+}
+
+001000,0000000000,01,01001,101,111,111:R6POOL32AXF5GROUP1:32::TLBINVF
+"tlbinvf"
+*nanomips32r6:
+*nanomips64r6:
+{
+ // invalidate a set of TLB entries based on Index match - nothing to do currently
+ sim_io_printf (SD, "Not implemented");
+}
+
+001000,10.CODE,10,00101,101,111,111:R6PSYSCALL:32::SYSCALL
+"syscall %#lx<CODE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ SignalException (SystemCall, instruction_0);
+}
+
+100000,00000,5.X1,1100,3.X2,0000,00011:R6PHB:32::EHB
+"ehb"
+*nanomips32r6:
+*nanomips64r6:
+{
+ // Do nothing, there are no hazards to clear
+}
+
+001000,5.RT,5.RS,5.X,0,0000000,000:R6PTRAP:32::TEQ
+"teq r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+
+ if (GPR[RS] == GPR[RT])
+ SignalException(Trap, instruction_0);
+}
+
+001000,5.RT,5.RS,5.X,1,0000000,000:R6PTRAP:32::TNE
+"tne r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+
+ if (GPR[RS] != GPR[RT])
+ SignalException(Trap, instruction_0);
+}
+
+101001,5.RT,5.RS,1.S1,0100,0,01,8.S2:R6PLSS1:32::UALH
+"ualh r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+
+ TRACE_ALU_INPUT3(GPR[RT], S_9_BIT, GPR[RS]);
+ do_lh (SD_, RT, S_9_BIT, RS);
+ TRACE_ALU_RESULT(GPR[RT]);
+}
+
+101001,5.RT,5.RS,1.S1,3.COUNT3,0,1,01,8.S2:R6PLSUAWM:32::UALWM
+"ualwm r<RT>, <S_9_BIT>(r<RS>), <COUNT>":COUNT != 1
+"ualw r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ int i;
+ int dest;
+ int this_offset;
+
+ address_word base = GPR[RS];
+ for(i = 0; i< COUNT; i++)
+ {
+ dest = (RT & 0x10) | ((RT + i) & 0x1F);
+
+ if (dest == RS && i != COUNT - 1)
+ Unpredictable ();
+
+ this_offset = S_9_BIT + (i << 2);
+
+ if(BigEndianCPU) {
+ GPR[dest] = EXTEND32 (do_load_left (SD_, AccessLength_WORD, base,
+ EXTEND16 (this_offset), GPR[dest]));
+ GPR[dest] = EXTEND32 (do_load_right (SD_, AccessLength_WORD, base,
+ EXTEND16 (this_offset + AccessLength_WORD), GPR[dest]));
+ } else {
+ GPR[dest] = EXTEND32 (do_load_right (SD_, AccessLength_WORD, base,
+ EXTEND16 (this_offset), GPR[dest]));
+ GPR[dest] = EXTEND32 (do_load_left (SD_, AccessLength_WORD, base,
+ EXTEND16 (this_offset + AccessLength_WORD), GPR[dest]));
+ }
+
+ if (i != 0)
+ COP0_COUNT++;
+ }
+}
+
+101001,5.RT,5.RS,1.S1,0101,0,01,8.S2:R6PLSS1:32::UASH
+"uash r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+
+ do_store (SD_, AccessLength_HALFWORD, GPR[RS], S_9_BIT, GPR[RT]);
+}
+
+101001,5.RT,5.RS,1.S1,3.COUNT3,1,1,01,8.S2:R6PLSUAWM:32::UASWM
+"uaswm r<RT>, <S_9_BIT>(r<RS>), <COUNT>":COUNT != 1
+"uasw r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+
+ int i;
+ int source;
+ int offsetm;
+
+ for(i = 0; i< COUNT; i++)
+ {
+ if (RT == 0)
+ source = 0;
+ else
+ source = (RT & 0x10) | ((RT + i) & 0x1F);
+
+ offsetm = S_9_BIT + (i << 2);
+
+ if(BigEndianCPU) {
+ do_store_left (SD_, AccessLength_WORD, GPR[RS], EXTEND16 (offsetm), GPR[source]);
+ do_store_right (SD_, AccessLength_WORD, GPR[RS],
+ EXTEND16 (offsetm + AccessLength_WORD), GPR[source]);
+ } else {
+ do_store_right (SD_, AccessLength_WORD, GPR[RS], EXTEND16 (offsetm), GPR[source]);
+ do_store_left (SD_, AccessLength_WORD, GPR[RS],
+ EXTEND16 (offsetm + AccessLength_WORD), GPR[source]);
+ }
+
+ if (i != 0)
+ COP0_COUNT++;
+ }
+}
+
+001000,5.RT,5.X,00000,0,1110010,000:R6PDVP:32::DVP
+"dvp r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ // nothing to do currently
+ sim_io_printf (SD, "Not implemented");
+}
+
+
+001000,5.RT,5.HS,2.X1,3.SEL,1.X2,0111000,000:R6POOL32A0:32::RDHWR
+"rdhwr r<HS>, r<RT>, <SEL>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_nms_flag (SD_);
+ do_rdhwr (SD_, RT, HS);
+}
+
+001000,5.RT,5.RS,11,10000,101,111,111:R6POOL32AXF5GROUP3:32::RDPGPR
+"rdpgpr r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ // nothing to do currently
+ sim_io_printf (SD, "Not implemented");
+}
+
+001000,5.RT,5.RS,11,11000,101,111,111:R6POOL32AXF5GROUP3:32::WRPGPR
+"wrpgpr r<RT>, r<RS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ // TODO: implement as given in the specification
+ sim_io_printf (SD, "Not implemented");
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1111010,000:R6POOL32A0:32::SOV
+"SOV r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
+ {
+ ALU32_BEGIN (GPR[RS]);
+ ALU32_ADD (GPR[RT]);
+ if (ALU32_HAD_OVERFLOW)
+ GPR[RD] = 1;
+ else
+ GPR[RD] = 0;
+ }
+ TRACE_ALU_RESULT (GPR[RD]);
+}
+
+001000,10.X,11,10001,101,111,111:R6POOL32A0:32::DERET
+"deret"
+*nanomips32r6:
+*nanomips64r6:
+{
+ // nothing to do currently
+ sim_io_printf (SD, "Not implemented");
+}
+
+001000,5.RT,5.X,00000,1,1110010,000:R6PDVP:32::EVP
+"evp r<RT>" : RT!=0
+"evp"
+*nanomips32r6:
+*nanomips64r6:
+{
+ // nothing to do currently
+ sim_io_printf (SD, "Not implemented");
+}
+
+001000,10.CODE,110000110,1111111:R6POOL32AXF5GROUP2:32::WAIT
+"wait"
+*nanomips32r6:
+*nanomips64r6:
+{
+ // nothing to do currently
+ sim_io_printf (SD, "Not implemented");
+}
+
+011000,5.RT,00000,16.IMM48:R6POOL48I:32::LI48
+"li r<RT>, <IMM48>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ uint16_t U2;
+ uint32_t total;
+ check_nms_flag (SD_);
+ U2 = do_load (SD_, AccessLength_HALFWORD, CIA + 4, 0);
+ total = U2 << 16 | IMM48;
+ TRACE_ALU_INPUT2(GPR[RT], total);
+ GPR[RT] = EXTEND32(total);
+ TRACE_ALU_RESULT(GPR[RT]);
+ NIA = CIA + 6;
+}
+
+011000,5.RT,00001,16.IMM48:R6POOL48I:32::ADDIU48
+"addiu r<RT>, <IMM48>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ uint16_t S2;
+ uint32_t total;
+ check_nms_flag (SD_);
+ S2 = do_load(SD_, AccessLength_HALFWORD, CIA + 4, 0);
+ total = S2 << 16 | IMM48;
+ do_addiu(SD_, RT, RT, total);
+ NIA = CIA + 6;
+}
+
+100000,5.RT,5.RS,1000,12.U:R6PU12:32::ADDIUNEG
+"addiu r<RT>, r<RS>, -<U>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_addiu (SD_, RS, RT, -U);
+}
+
+011000,5.RT,00010,16.IMM48:R6POOL48I:32::ADDIUGP48
+"addiu r<RT>, GP, <IMM48>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ uint16_t S2;
+ uint32_t total;
+ check_nms_flag (SD_);
+ S2 = do_load(SD_, AccessLength_HALFWORD, CIA + 4, 0);
+ total = S2 << 16 | IMM48;
+ do_addiu (SD_, GPIDX, RT, total);
+ NIA = CIA + 6;
+}
+
+010010,00000,5.RS,1000,12.X:R6BALRSC:32::BRSC
+"brsc r<RS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ unsigned_word address = NIA + (GPR[RS] << 1);
+ NIA = address;
+}
+
+010010,5.RT!0,5.RS,1000,12.X:R6PBALRSC:32::BALRSC
+"balrsc r<RT>, r<RS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ unsigned_word address = NIA + (GPR[RS] << 1);
+
+ GPR[RT] = NIA;
+ NIA = address;
+
+ // For cycle counting
+ COP0_COUNT++;
+}
+
+110010,5.RT,001,1.X,6.BIT,10.S1,1.S2:R6PBRI:32::BBEQZC
+"bbeqzc r<RT>, <BIT>, <ADDRESS12>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ int testbit = (GPR[RT] >> BIT) & 1;
+
+ check_nms_flag (SD_);
+
+ if (testbit == 0)
+ NIA = ADDRESS12;
+}
+
+110010,5.RT,101,1.X,6.BIT,10.S1,1.S2:R6PBRI:32::BBNEZC
+"bbnezc r<RT>, <BIT>, <ADDRESS12>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ int testbit = (GPR[RT] >> BIT) & 1;
+
+ check_nms_flag (SD_);
+
+ if (testbit == 1)
+ NIA = ADDRESS12;
+}
+
+//////////////////////////////////////////////////////////////////////
+// Not yet in the specification.
+//////////////////////////////////////////////////////////////////////
+
+100001,5.FT,5.RS,1111,12.U:R6PLSU12:32::SDC1
+"sdc1 f<FT>, <U>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_fpu (SD_);
+ TRACE_ALU_INPUT3(FGR[FT], U, GPR[RS]);
+ do_store (SD_, AccessLength_DOUBLEWORD, GPR[RS], EXTEND16 (U), COP_SD (1, FT));
+}
+
+100001,5.FT,5.RS,1110,12.OFFSET:R6PLSU12:32::LDC1
+"ldc1 f<FT>, <OFFSET>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_fpu (SD_);
+ TRACE_ALU_INPUT3(FGR[FT], OFFSET, GPR[RS]);
+ COP_LD (1, FT, do_load (SD_, AccessLength_DOUBLEWORD, GPR[RS], EXTEND16 (OFFSET)));
+ TRACE_ALU_RESULT(FGR[FT]);
+}
+
+100001,5.FT,5.BASE,1010,12.OFFSET:R6PLSU12:32::LWC1
+"lwc1 f<FT>, <OFFSET>(r<BASE>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lwc1 (SD_, FT, OFFSET, BASE);
+}
+
+100001,5.FT,5.BASE,1011,12.OFFSET:R6PLSU12:32::SWC1
+"swc1 f<FT>, <OFFSET>(fp)": BASE == 30
+"swc1 f<FT>, <OFFSET>(r<BASE>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ if(BASE == 30)
+ do_swc1 (SD_, FT, OFFSET, 30, instruction_0);
+ else
+ do_swc1 (SD_, FT, OFFSET, BASE, instruction_0);
+}
+
+001000,10.X,00,01001,101,111,111:R6POOL32AXF5GROUP0:32::TLBR
+"tlbr"
+*nanomips32r6:
+*nanomips64r6:
+{
+ // nothing to do currently
+ sim_io_printf (SD, "Not implemented");
+}
+
+101000,5.RT,5.FS,2.X,101000,00,111,011:R6POOL32FXF0:32,f::MTC1
+"mtc1 r<RT>, f<FS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(GPR[RT], FGR[FS]);
+ do_mtc1b (SD_, RT, FS);
+ TRACE_ALU_RESULT(FGR[FS]);
+}
+
+101000,5.RT,5.FS,2.X,111000,00,111,011:R6POOL32FXF0:32,f::MTHC1
+"mthc1 r<RT>, f<FS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+TRACE_ALU_INPUT2(GPR[RT],FGR[FS]);
+ do_mthc1 (SD_, RT, FS);
+ TRACE_ALU_RESULT(FGR[FS]);
+}
+
+101000,5.FT,5.FS,5.FD,1.X,0,1.FMT_MICROMIPS,00110,000:R6POOLADDFMT1:32,f::ADD.fmt1
+"add.%s<FMT_MICROMIPS> f<FD>, f<FS>, f<FT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(FGR[FT], FGR[FS]);
+ do_add_fmt (SD_, convert_fmt_micromips (SD_, FMT_MICROMIPS), FD, FS, FT,
+ instruction_0);
+ TRACE_ALU_RESULT(FGR[FD]);
+}
+
+101000,5.FT,5.FS,5.FD,5.R6COND,0,1.FMT,0101:R6POOL32F5:32,f::CMP.cond.fmt
+"cmp.%s<R6COND>.%s<FMT> f<FD>, f<FS>, f<FT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_cmp (SD_, FD, FS, FT, FMT, R6COND);
+}
+
+101000,5.FT,5.FS,1.X,0,1.FMT_MICROMIPS,00000,01,111,011:R6POOLMOVFMT:32,f::MOV.fmt
+"mov.%s<FMT_MICROMIPS> f<FT>, f<FS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(FGR[FT], FGR[FS]);
+ do_mov_fmt (SD_, convert_fmt_micromips (SD_, FMT_MICROMIPS), FT, FS,
+ instruction_0);
+ TRACE_ALU_RESULT(FGR[FT]);
+}
+
+010001,5.FT,110,16.U,00:R6PLSGPCP1:32::LWC1GP
+"lwc1 f<FT>, <U_SHIFT_2BIT>(GP)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_lwc1 (SD_, FT, U_SHIFT_2BIT, GPIDX);
+}
+
+010001,5.FT,110,16.U,01:R6PLSGPCP1:32::SWC1GP
+"swc1 f<FT>, <U_SHIFT_2BIT>(GP)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_swc1 (SD_, FT, U_SHIFT_2BIT, GPIDX, instruction_0);
+}
+
+101001,5.FT,5.RS,1.S1,1011000,8.S2:R6PLSGPCP1:32::SWC1S9
+"swc1 f<FT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_swc1 (SD_, FT, S_9_BIT, RS, instruction_0);
+}
+
+010001,5.FT,110,16.U,10:R6PLSGPCP1:32::LDC1GP
+"ldc1 f<FT>, <U_SHIFT_2BIT>(GP)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT3(FGR[FT], U_SHIFT_2BIT, GP);
+ COP_LD (1, FT, do_load (SD_, AccessLength_DOUBLEWORD, GP, U_SHIFT_2BIT));
+ TRACE_ALU_RESULT(FGR[FT]);
+}
+
+100010,5.FT,00001,01,13.S2,1.S1:R6POOLPBR3A:32,f::BC1NEZC
+"bc1nezc f<FT>, <S_14_BIT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_fpu (SD_);
+ TRACE_ALU_INPUT2(NIA, S_14_BIT);
+ if ((FGR[FT] & 0x01) != 0)
+ NIA = NIA + (S_14_BIT << 1);
+ TRACE_ALU_RESULT(NIA);
+}
+
+100010,5.FT,00000,01,13.S2,1.S1:R6POOLPBR3A:32,f::BC1EQZC
+"bc1eqzc f<FT>, <S_14_BIT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_fpu (SD_);
+ TRACE_ALU_INPUT2(NIA, S_14_BIT);
+ if ((FGR[FT] & 0x01) == 0)
+ NIA = NIA + (S_14_BIT << 1);
+ TRACE_ALU_RESULT(NIA);
+}
+
+101000,5.RT,5.FS,2.X,100000,00,111,011:R6POOL32FXF0:32,f::MFC1
+"mfc1 r<RT>, f<FS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(GPR[RT], FGR[FS]);
+ do_mfc1b (SD_, RT, FS);
+ TRACE_ALU_RESULT(GPR[RT]);
+}
+
+101000,5.RT,5.FS,2.X,110000,00,111,011:R6POOL32FXF0:32,f::MFHC1
+"mfhc1 r<RT>, f<FS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(GPR[RT], FGR[FS]);
+ do_mfhc1 (SD_, RT, FS);
+ TRACE_ALU_RESULT(GPR[RT]);
+}
+
+101000,5.FT,5.FS,1.X,2.FMT_MICROMIPS_CVT_D!3,10011,01,111,011:R6CVTDFMT:32,f::CVT.D.fmt
+"cvt.d.%s<FMT_MICROMIPS_CVT_D> f<FT>, f<FS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_cvt_d_fmt (SD_, convert_fmt_micromips_cvt_d (SD_, FMT_MICROMIPS_CVT_D),
+ FT, FS, instruction_0);
+}
+
+:%s::::FMT_MICROMIPS_MUL:int fmt
+{
+ switch (fmt)
+ {
+ case 1: return "s";
+ case 3: return "d";
+ default: return "?";
+ }
+}
+
+101000,5.FT,5.FS,5.FD,1.X,0,2.FMT_MICROMIPS_MUL!2!0,0110,000:R6MULFMT1:32,f::MUL.fmt
+"mul.%s<FMT_MICROMIPS_MUL> f<FD>, f<FS>, f<FT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(FGR[FS], FGR[FT]);
+ do_mul_fmt (SD_, convert_fmt_micromips_mul (SD_, FMT_MICROMIPS_MUL), FD, FS, FT,
+ instruction_0);
+ TRACE_ALU_RESULT(FGR[FD]);
+}
+
+
+101000,5.FT,5.FS,5.FD,1.X,0,2.FMT_MICROMIPS_MUL!2!0,1110,000:R6DIVFMT1:32,f::DIV.fmt
+"div.%s<FMT_MICROMIPS_MUL> f<FD>, f<FS>, f<FT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(FGR[FS], FGR[FT]);
+ if (FMT_MICROMIPS_MUL == 1)
+ do_div_fmt (SD_, 0, FD, FS, FT, instruction_0);
+ else
+ do_div_fmt (SD_, 1, FD, FS, FT, instruction_0);
+ TRACE_ALU_RESULT(FGR[FD]);
+}
+
+101000,5.FT,5.FS,1.X,1.FMT_MICROMIPS,101011,00,111,011:R6POOL32FXF0:32,f::TRUNC.W.fmt
+"trunc.w.%s<FMT_MICROMIPS> f<FT>, f<FS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_trunc_fmt (SD_, fmt_word, FMT_MICROMIPS, FT, FS);
+}
+
+101000,5.FT,5.FS,1.X,2.FMT_MICROMIPS_CVT_S!3,11011,01,111,011:R6CVTSFMT:32,f::CVT.S.dsw
+"cvt.s.%s<FMT_MICROMIPS_CVT_S> f<FT>, f<FS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_cvt_s_fmt (SD_, convert_fmt_micromips_cvt_s (SD_, FMT_MICROMIPS_CVT_S),
+ FT, FS, instruction_0);
+}
+
+010001,5.FT,110,16.U,11:R6PLSU12:32::SDC1GP
+"sdc1 f<FT>, <U_SHIFT_2BIT>(GP)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT3(FGR[FT], U_SHIFT_2BIT, GP);
+ do_store (SD_, AccessLength_DOUBLEWORD, GP, U_SHIFT_2BIT, COP_SD (1, FT));
+}
+
+101000,5.FT,5.FS,5.FD,1.X,0,1.FMT_MICROMIPS,01110,000:R6SUBFMT1:32,f::SUB.fmt
+"sub.%s<FMT_MICROMIPS> f<FD>, f<FS>, f<FT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(FGR[FS], FGR[FT]);
+ do_sub_fmt (SD_, convert_fmt_micromips (SD_, FMT_MICROMIPS), FD, FS, FT,
+ instruction_0);
+ TRACE_ALU_RESULT(FGR[FD]);
+}
+
+101000,5.FT,5.FS,1.X,2.FMT_MICROMIPS!3!2,00011,01,111,011:R6POOL32FXF1:32,f::::ABS.fmt
+"abs.%s<FMT_MICROMIPS> f<FT>, f<FS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_abs_fmt (SD_, convert_fmt_micromips (SD_, FMT_MICROMIPS), FT, FS,
+ instruction_0);
+}
+
+101000,5.FT,5.FS,5.FD,1.X,1.FMT_MICROMIPS,110111,000:R6POOL32F0:32,f::MADDF.fmt
+"maddf.%s<FMT_MICROMIPS> f<FD>, f<FS>, f<FT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT2(FGR[FS], FGR[FT]);
+ do_maddf (SD_, FD, FS, FT, convert_fmt_micromips (SD_, FMT_MICROMIPS), instruction_0);
+ TRACE_ALU_RESULT(FGR[FD]);
+}
+
+101000,5.FT,5.FS,1.X,2.FMT_MICROMIPS!3!2,01011,01,111,011:R6POOL32FXF1:32,f::NEG.fmt
+"neg.%s<FMT_MICROMIPS> f<FT>, f<FS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_neg_fmt (SD_, convert_fmt_micromips (SD_, FMT_MICROMIPS), FT, FS,
+ instruction_0);
+}
+
+101000,5.FT,5.FS,1.X,1.FMT_MICROMIPS,100011,00,111,011:R6POOL32FXF0:32,f::TRUNC.L.fmt
+"trunc.l.%s<FMT_MICROMIPS> f<FT>, f<FS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_trunc_fmt (SD_, fmt_long, FMT_MICROMIPS, FT, FS);
+}
+
+001000,5.RT,5.RS,5.FT,1011,1,000,111:R6POOLPPLSXS:32,f::SWC1XS
+"swc1xs f<FT>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_swc1xs(SD_, FT, RS, RT, instruction_0);
+}
+
+001000,5.RT,5.RS,5.FT,1111,0,000,111:R6POOLPPLSX:32,f::SDC1X
+"sdc1x f<FT>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_fpu (SD_);
+ TRACE_ALU_INPUT3(FGR[FT], GPR[RS], GPR[RT]);
+ do_store (SD_, AccessLength_DOUBLEWORD, GPR[RS], GPR[RT], COP_SD (1, FT));
+}
+
+001000,5.RT,5.RS,5.FT,1111,1,000,111:R6POOLPPLSXS:32,f::SDC1XS
+"sdc1xs f<FT>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ check_fpu (SD_);
+ TRACE_ALU_INPUT3(FGR[FT], GPR[RS], GPR[RT]);
+ do_store (SD_, AccessLength_DOUBLEWORD, GPR[RS] << 3, GPR[RT], COP_SD (1, FT));
+}
+
+001000,5.RT,5.RS,5.FT,1110,0,000,111:R6POOLPPLSXS:32::LDC1X
+"ldc1x f<FT>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT3(FGR[FT], GPR[RS], GPR[RT]);
+ COP_LD (1, FT, do_load (SD_, AccessLength_DOUBLEWORD, GPR[RS], GPR[RT]));
+ TRACE_ALU_RESULT(FGR[FT]);
+}
+
+001000,5.RT,5.RS,5.FT,1110,1,000,111:R6POOLPPLSXS:32::LDC1XS
+"ldc1xs f<FT>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT3(FGR[FT], GPR[RS], GPR[RT]);
+ COP_LD (1, FT, do_load (SD_, AccessLength_DOUBLEWORD, GPR[RS] << 3, GPR[RT]));
+ TRACE_ALU_RESULT(FGR[FT]);
+}
+
+001000,5.RT,5.RS,5.FT,1010,1,000,111:R6POOLPPLSXS:32::LWC1XS
+"lwc1xs f<FT>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT3(FGR[FT], GPR[RS], GPR[RT]);
+ do_lwc1xs (SD_, FT, RS, RT);
+ TRACE_ALU_RESULT(FGR[FT]);
+}
+
+001000,5.RT,5.RS,5.FT,1010,0,000,111:R6PPLSX:32,f::LWC1X
+"lwc1x f<FT>, r<RT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT3(FGR[FT], GPR[RS], GPR[RT]);
+ do_lwxc1 (SD_, FT, RT, RS, instruction_0);
+ TRACE_ALU_RESULT(FGR[FT]);
+}
+
+001000,5.RT,5.RS,5.FT,1011,0,000,111:R6PPLSX:32,f::SWC1X
+"swc1x f<FT>, r<RT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_swxc1 (SD_, FT, RT, RS, instruction_0);
+}
+
+101001,5.FT,5.RS,1.S1,1110,0,00,8.S2:R6PLSS0:32,f::LDC1S9
+"ldc1 r<FT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT3(GPR[FT], S_9_BIT, GPR[RS]);
+ COP_LD (1, FT, do_load (SD_, AccessLength_DOUBLEWORD, GPR[RS], S_9_BIT));
+ TRACE_ALU_RESULT(GPR[FT]);
+}
+
+101001,5.FT,5.RS,1.S1,1111,0,00,8.S2:R6PLSS0:32,f::SDC1S9
+"sdc1 r<FT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT3(GPR[FT], S_9_BIT, GPR[RS]);
+ do_store (SD_, AccessLength_DOUBLEWORD, GPR[RS], S_9_BIT, COP_SD (1, FT));
+}
+
+101001,5.FT,5.RS,1.S1,1010,0,00,8.S2:R6PLSS0:32::LWC1S9
+"lwc1 f<FT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+ TRACE_ALU_INPUT3(GPR[FT], S_9_BIT, GPR[RS]);
+ do_lwc1 (SD_, FT, S_9_BIT, RS);
+ TRACE_ALU_RESULT(GPR[FT]);
+}
+
+101000,5.FT,5.FS,5.FD,2.FMT,000000011:R6POOL32F3:32,f::MIN.fmt
+"min.%s<FMT> f<FD>, f<FS>, f<FT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_min (SD_, FD, FS, FT, FMT, instruction_0);
+}
+
+101000,5.FT,5.FS,5.FD,2.FMT,000001,011:R6POOL32F3:32,f::MAX.fmt
+"max.%s<FMT> f<FD>, f<FS>, f<FT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_max (SD_, FD, FS, FT, FMT, instruction_0);
+}
+
+101000,5.FT,5.FS,5.FD,2.FMT,000100,011:R6POOL32F3:32,f::MINA.fmt
+"mina.%s<FMT> f<FD>, f<FS>, f<FT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_mina (SD_, FD, FS, FT, FMT, instruction_0);
+}
+
+101000,5.FT,5.FS,5.FD,2.FMT,000101,011:R6POOL32F3:32,f::MAXA.fmt
+"maxa.%s<FMT> f<FD>, f<FS>, f<FT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_maxa (SD_, FD, FS, FT, FMT, instruction_0);
+}
+
+101000,5.FT,5.FS,5.FD,2.FMT,111111,000:R6POOL32F0:32,f::MSUBF.fmt
+"msubf.%s<FMT> f<FD>, f<FS>, f<FT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_msubf (SD_, FD, FS, FT, FMT, instruction_0);
+}
+
+101000,5.FS,5.FD,00000,2.FMT,000100,000:R6POOL32F0:32,f::RINT.fmt
+"rint.%s<FMT> f<FD>, f<FS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_rint (SD_, FD, FS, FMT, instruction_0);
+}
+
+101000,5.FS,5.FD,00000,2.FMT,001100,000:R6POOL32F0:32,f::CLASS.fmt
+"class.%s<FMT> f<FD>, f<FS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_class (SD_, FD, FS, FMT, instruction_0);
+}
+
+101000,5.FT,5.FS,5.FD,2.FMT,010111,000:R6POOL32F0:32,f::SEL.fmt
+"sel.%s<FMT> f<FD>, f<FS>, f<FT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_self (SD_, FD, FS, FT, FMT, instruction_0);
+}
+
+101000,5.FT,5.FS,5.FD,2.FMT,000111,000:R6POOL32F0:32,f::SELEQZ.fmt
+"seleqz.%s<FMT> f<FD>, f<FS>, f<FT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_seleqzf (SD_, FD, FS, FT, FMT, instruction_0);
+}
+
+101000,5.FT,5.FS,5.FD,2.FMT,001111,000:R6POOL32F0:32,f::SELNEZ.fmt
+"selnez.%s<FMT> f<FD>, f<FS>, f<FT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+ do_selnezf (SD_, FD, FS, FT, FMT, instruction_0);
+}
+
+:function:::void:do_lb:int rt, int offset, int base
+*nanomips32r6:
+*nanomips64r6:
+{
+ GPR[rt] = EXTEND8 (do_load (SD_, AccessLength_BYTE, GPR[base], offset));
+}
+
+:function:::void:do_lh:int rt, int offset, int base
+*nanomips32r6:
+*nanomips64r6:
+{
+ GPR[rt] = EXTEND16 (do_load (SD_, AccessLength_HALFWORD, GPR[base], offset));
+}
+
+:function:::void:do_lw:int rt, int offset, int base
+*nanomips32r6:
+*nanomips64r6:
+{
+ GPR[rt] = EXTEND32 (do_load (SD_, AccessLength_WORD, GPR[base], offset));
+}
+
+:function:::void:do_lhu:int rt, int offset, int base
+*nanomips32r6:
+*nanomips64r6:
+{
+ GPR[rt] = do_load (SD_, AccessLength_HALFWORD, GPR[base], offset);
+}
+
+:function:::void:do_addiu:int rs, int rt, int immediate
+*nanomips32r6:
+*nanomips64r6:
+{
+ if (NotWordValue (GPR[rs]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[rs], immediate);
+ GPR[rt] = EXTEND32 (GPR[rs] + immediate);
+ TRACE_ALU_RESULT (GPR[rt]);
+}
diff --git a/sim/mips/nanomipsrun.c b/sim/mips/nanomipsrun.c
new file mode 100644
index 00000000000..6321fd441ec
--- /dev/null
+++ b/sim/mips/nanomipsrun.c
@@ -0,0 +1,109 @@
+/* Run function for the nanomips simulator
+
+ Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+ Written by Andrew Bennett <andrew.bennett@imgtec.com>.
+
+ This file is part of GDB, the GNU debugger.
+
+ This program 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 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "sim-main.h"
+#include "nanomips16_idecode.h"
+#include "nanomips32_idecode.h"
+#include "bfd.h"
+
+
+#define SD sd
+#define CPU cpu
+#define SIM_MONITOR_ADDRESS 0xBFC00000
+
+void
+sim_engine_run (SIM_DESC sd, int next_cpu_nr, int nr_cpus, int signal);
+
+address_word
+nanomips_instruction_decode (SIM_DESC sd, sim_cpu * cpu,
+ address_word cia,
+ int instruction_size);
+
+address_word
+nanomips_instruction_decode (SIM_DESC sd, sim_cpu * cpu,
+ address_word cia,
+ int instruction_size)
+{
+
+ nanomips16_instruction_word instruction_0 = IMEM16_NANOMIPS (cia);
+
+ if((cia & 0xFFF00000) == SIM_MONITOR_ADDRESS) {
+ nanomips32_instruction_word instruction_0 = IMEM32 (cia);
+ return nanomips32_idecode_issue (sd, instruction_0, cia);
+ } else if ((STATE_ARCHITECTURE (sd)->mach == bfd_mach_nanomipsisa32r6
+ || STATE_ARCHITECTURE (sd)->mach == bfd_mach_nanomipsisa64r6)
+ && (NANOMIPS_MAJOR_OPCODE_3_5 (instruction_0) & 0x4) == 4)
+ return nanomips16_idecode_issue (sd, instruction_0, cia);
+ else
+ {
+ nanomips32_instruction_word instruction_0 = IMEM32_NANOMIPS (cia);
+ return nanomips32_idecode_issue (sd, instruction_0, cia);
+ }
+}
+
+void
+sim_engine_run (SIM_DESC sd, int next_cpu_nr, int nr_cpus,
+ int signal)
+{
+ nanomips32_instruction_word instruction_0;
+ sim_cpu *cpu = STATE_CPU (sd, next_cpu_nr);
+ nanomips32_instruction_address cia = CIA_GET (cpu);
+ unsigned long bfdmach;
+ is_nanomips = 1;
+
+ bfdmach = STATE_ARCHITECTURE(SD)->mach;
+
+ if (is_nms_flag_set == 0 && (bfdmach == bfd_mach_nanomipsisa64r6
+ || bfdmach == bfd_mach_nanomipsisa32r6))
+ set_nms_flag (sd);
+
+ while (1)
+ {
+ nanomips32_instruction_address nia;
+
+ cia = cia & ~0x1;
+
+#if defined (ENGINE_ISSUE_PREFIX_HOOK)
+ ENGINE_ISSUE_PREFIX_HOOK ();
+#endif
+
+ nia =
+ nanomips_instruction_decode (sd, cpu, cia,
+ MICROMIPS_DELAYSLOT_SIZE_ANY);
+
+#if defined (ENGINE_ISSUE_POSTFIX_HOOK)
+ ENGINE_ISSUE_POSTFIX_HOOK ();
+#endif
+ // Cycle counting
+ COP0_COUNT++;
+
+ /* Update the instruction address */
+ cia = nia;
+
+ /* process any events */
+ if (sim_events_tick (sd))
+ {
+ CIA_SET (CPU, cia);
+ sim_events_process (sd);
+ cia = CIA_GET (CPU);
+ }
+ }
+}
diff --git a/sim/mips/nms.c b/sim/mips/nms.c
new file mode 100644
index 00000000000..fd957d69e8b
--- /dev/null
+++ b/sim/mips/nms.c
@@ -0,0 +1,44 @@
+/* Run function for the nanomips simulator
+
+ Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+ Written by Andrew Bennett <andrew.bennett@imgtec.com>.
+
+ This file is part of GDB, the GNU debugger.
+
+ This program 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 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "sim-main.h"
+#include "elf/mips-common.h"
+#include "elf/nanomips.h"
+
+/* NMS Flag */
+int nms_flag = -1;
+
+int is_nms_flag_set = 0;
+
+void
+set_nms_flag (SIM_DESC sd)
+{
+ Elf_Internal_ABIFlags_v0 *abiflags;
+ abiflags = bfd_nanomips_elf_get_abiflags (STATE_PROG_BFD(sd));
+
+ nms_flag = 0;
+
+ if (abiflags != NULL
+ && ((abiflags->ases & NANOMIPS_ASE_xNMS) != 0))
+ nms_flag = 1;
+
+ is_nms_flag_set = 1;
+}
diff --git a/sim/mips/sim-main.c b/sim/mips/sim-main.c
index 250310eceb3..183082ab7c7 100644
--- a/sim/mips/sim-main.c
+++ b/sim/mips/sim-main.c
@@ -32,6 +32,81 @@
/*---------------------------------------------------------------------------*/
+/* Description from page A-22 of the "MIPS IV Instruction Set" manual
+ (revision 3.1) */
+/* Translate a virtual address to a physical address and cache
+ coherence algorithm describing the mechanism used to resolve the
+ memory reference. Given the virtual address vAddr, and whether the
+ reference is to Instructions ot Data (IorD), find the corresponding
+ physical address (pAddr) and the cache coherence algorithm (CCA)
+ used to resolve the reference. If the virtual address is in one of
+ the unmapped address spaces the physical address and the CCA are
+ determined directly by the virtual address. If the virtual address
+ is in one of the mapped address spaces then the TLB is used to
+ determine the physical address and access type; if the required
+ translation is not present in the TLB or the desired access is not
+ permitted the function fails and an exception is taken.
+
+ NOTE: Normally (RAW == 0), when address translation fails, this
+ function raises an exception and does not return. */
+
+INLINE_SIM_MAIN
+(int)
+address_translation (SIM_DESC sd,
+ sim_cpu * cpu,
+ address_word cia,
+ address_word vAddr,
+ int IorD,
+ int LorS,
+ address_word * pAddr,
+ int *CCA,
+ int raw)
+{
+ int res = -1; /* TRUE : Assume good return */
+
+#ifdef DEBUG
+ sim_io_printf (sd, "AddressTranslation(0x%s,%s,%s,...);\n", pr_addr (vAddr), (IorD ? "isDATA" : "isINSTRUCTION"), (LorS ? "iSTORE" : "isLOAD"));
+#endif
+
+ /* Check that the address is valid for this memory model */
+
+ /* For a simple (flat) memory model, we simply pass virtual
+ addressess through (mostly) unchanged. */
+ vAddr &= 0xFFFFFFFF;
+
+ *pAddr = vAddr; /* default for isTARGET */
+ *CCA = Uncached; /* not used for isHOST */
+
+ return (res);
+}
+
+
+
+/* Description from page A-23 of the "MIPS IV Instruction Set" manual
+ (revision 3.1) */
+/* Prefetch data from memory. Prefetch is an advisory instruction for
+ which an implementation specific action is taken. The action taken
+ may increase performance, but must not change the meaning of the
+ program, or alter architecturally-visible state. */
+
+INLINE_SIM_MAIN (void)
+prefetch (SIM_DESC sd,
+ sim_cpu *cpu,
+ address_word cia,
+ int CCA,
+ address_word pAddr,
+ address_word vAddr,
+ int DATA,
+ int hint)
+{
+#ifdef DEBUG
+ sim_io_printf(sd,"Prefetch(%d,0x%s,0x%s,%d,%d);\n",CCA,pr_addr(pAddr),pr_addr(vAddr),DATA,hint);
+#endif /* DEBUG */
+
+ /* For our simple memory model we do nothing */
+ return;
+}
+
/* Description from page A-22 of the "MIPS IV Instruction Set" manual
(revision 3.1) */
/* Load a value from memory. Use the cache and main memory as
@@ -266,13 +341,15 @@ ifetch32 (SIM_DESC SD,
address_word reverseendian = (ReverseEndian ? (mask ^ access) : 0);
address_word bigendiancpu = (BigEndianCPU ? (mask ^ access) : 0);
unsigned int byte;
- address_word paddr = vaddr;
+ address_word paddr;
+ int uncached;
uint64_t memval;
if ((vaddr & access) != 0)
SignalExceptionInstructionFetch ();
+ AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL);
paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
- LoadMemory (&memval, NULL, access, paddr, vaddr, isINSTRUCTION, isREAL);
+ LoadMemory (&memval, NULL, uncached, access, paddr, vaddr, isINSTRUCTION, isREAL);
byte = ((vaddr & mask) ^ bigendiancpu);
return (memval >> (8 * byte));
}
@@ -290,13 +367,15 @@ ifetch16 (SIM_DESC SD,
address_word reverseendian = (ReverseEndian ? (mask ^ access) : 0);
address_word bigendiancpu = (BigEndianCPU ? (mask ^ access) : 0);
unsigned int byte;
- address_word paddr = vaddr;
+ address_word paddr;
+ int uncached;
uint64_t memval;
if ((vaddr & access) != 0)
SignalExceptionInstructionFetch ();
+ AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL);
paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
- LoadMemory (&memval, NULL, access, paddr, vaddr, isINSTRUCTION, isREAL);
+ LoadMemory (&memval, NULL, uncached, access, paddr, vaddr, isINSTRUCTION, isREAL);
byte = ((vaddr & mask) ^ bigendiancpu);
return (memval >> (8 * byte));
}
diff --git a/sim/mips/sim-main.h b/sim/mips/sim-main.h
index 418c6599118..1397202c787 100644
--- a/sim/mips/sim-main.h
+++ b/sim/mips/sim-main.h
@@ -262,6 +262,8 @@ struct _sim_cpu {
/* The following are internal simulator state variables: */
+#define CIA_GET(CPU) ((CPU)->registers[PCIDX] + 0)
+#define CIA_SET(CPU,CIA) ((CPU)->registers[PCIDX] = (CIA))
address_word dspc; /* delay-slot PC */
#define DSPC ((CPU)->dspc)
@@ -318,9 +320,9 @@ struct _sim_cpu {
#define LAST_EMBED_REGNUM (96)
#define NUM_REGS (LAST_EMBED_REGNUM + 1)
-#define FP0_REGNUM 38 /* Floating point register 0 (single float) */
-#define FCRCS_REGNUM 70 /* FP control/status */
-#define FCRIR_REGNUM 71 /* FP implementation/revision */
+#define FP0_REGNUM 36 /* Floating point register 0 (single float) */
+#define FCRCS_REGNUM 68 /* FP control/status */
+#define FCRIR_REGNUM 69 /* FP implementation/revision */
#endif
@@ -336,16 +338,16 @@ struct _sim_cpu {
#define GPR (®ISTERS[0])
#define GPR_SET(N,VAL) (REGISTERS[(N)] = (VAL))
-#define LO (REGISTERS[33])
-#define HI (REGISTERS[34])
-#define PCIDX 37
+#define HI (REGISTERS[70])
+#define LO (REGISTERS[71])
+#define PCIDX (is_nanomips?32:35)
#define PC (REGISTERS[PCIDX])
-#define CAUSE (REGISTERS[36])
+#define CAUSE (REGISTERS[34])
#define SRIDX (32)
#define SR (REGISTERS[SRIDX]) /* CPU status register */
-#define FCR0IDX (71)
+#define FCR0IDX (69)
#define FCR0 (REGISTERS[FCR0IDX]) /* really a 32bit register */
-#define FCR31IDX (70)
+#define FCR31IDX (68)
#define FCR31 (REGISTERS[FCR31IDX]) /* really a 32bit register */
#define FCSR (FCR31)
#define Debug (REGISTERS[86])
@@ -353,19 +355,19 @@ struct _sim_cpu {
#define EPC (REGISTERS[88])
#define ACX (REGISTERS[89])
-#define AC0LOIDX (33) /* Must be the same register as LO */
-#define AC0HIIDX (34) /* Must be the same register as HI */
-#define AC1LOIDX (90)
-#define AC1HIIDX (91)
-#define AC2LOIDX (92)
-#define AC2HIIDX (93)
-#define AC3LOIDX (94)
-#define AC3HIIDX (95)
+#define AC0HIIDX (70) /* Must be the same register as HI */
+#define AC0LOIDX (71) /* Must be the same register as LO */
+#define AC1HIIDX (72)
+#define AC1LOIDX (73)
+#define AC2HIIDX (74)
+#define AC2LOIDX (75)
+#define AC3HIIDX (76)
+#define AC3LOIDX (77)
#define DSPLO(N) (REGISTERS[DSPLO_REGNUM[N]])
#define DSPHI(N) (REGISTERS[DSPHI_REGNUM[N]])
-#define DSPCRIDX (96) /* DSP control register */
+#define DSPCRIDX (79) /* DSP control register */
#define DSPCR (REGISTERS[DSPCRIDX])
#define DSPCR_POS_SHIFT (0)
@@ -420,6 +422,8 @@ struct _sim_cpu {
#define A3 (REGISTERS[7])
#define T8IDX 24
#define T8 (REGISTERS[T8IDX])
+#define GPIDX 28
+#define GP (REGISTERS[GPIDX])
#define SPIDX 29
#define SP (REGISTERS[SPIDX])
#define RAIDX 31
@@ -433,6 +437,7 @@ struct _sim_cpu {
unsigned_word cop0_gpr[NR_COP0_GPR];
#define COP0_GPR ((CPU)->cop0_gpr)
#define COP0_BADVADDR (COP0_GPR[8])
+#define COP0_COUNT (COP0_GPR[9])
/* While space is allocated for the floating point registers in the
main registers array, they are stored separatly. This is because
@@ -476,6 +481,17 @@ struct _sim_cpu {
sim_cpu_base base;
};
+extern int is_nanomips;
+
+#define SET_RV0(VAL) \
+ do { \
+ if (is_nanomips) \
+ A0 = VAL; \
+ else \
+ V0 = VAL; \
+ } while (0)
+
+
extern void mips_sim_close (SIM_DESC sd, int quitting);
#define SIM_CLOSE_HOOK(...) mips_sim_close (__VA_ARGS__)
@@ -643,13 +659,16 @@ enum ExceptionCause {
is used by gdb for break-points. NOTE: Care must be taken, since
this value may be used in later revisions of the MIPS ISA. */
#define HALT_INSTRUCTION_MASK (0x03FFFFC0)
+#define HALT_INSTRUCTION_MASK_NANOMIPS (0x0007FFFF)
#define HALT_INSTRUCTION (0x03ff000d)
#define HALT_INSTRUCTION2 (0x0000ffcd)
+#define HALT_INSTRUCTION_NANOMIPS (0x001003FF)
#define BREAKPOINT_INSTRUCTION (0x0005000d)
#define BREAKPOINT_INSTRUCTION2 (0x0000014d)
+#define BREAKPOINT_INSTRUCTION_NANOMIPS (0x00101400)
@@ -728,6 +747,44 @@ void store_fcr (SIM_STATE, int fcr, unsigned_word value);
void test_fcsr (SIM_STATE);
#define TestFCSR() test_fcsr (SIM_ARGS)
+/* FPU operations. */
+/* Non-signalling */
+#define FP_R6CMP_AF 0x0
+#define FP_R6CMP_EQ 0x2
+#define FP_R6CMP_LE 0x6
+#define FP_R6CMP_LT 0x4
+#define FP_R6CMP_NE 0x13
+#define FP_R6CMP_OR 0x11
+#define FP_R6CMP_UEQ 0x3
+#define FP_R6CMP_ULE 0x7
+#define FP_R6CMP_ULT 0x5
+#define FP_R6CMP_UN 0x1
+#define FP_R6CMP_UNE 0x12
+
+/* Signalling */
+#define FP_R6CMP_SAF 0x8
+#define FP_R6CMP_SEQ 0xa
+#define FP_R6CMP_SLE 0xe
+#define FP_R6CMP_SLT 0xc
+#define FP_R6CMP_SNE 0x1b
+#define FP_R6CMP_SOR 0x19
+#define FP_R6CMP_SUEQ 0xb
+#define FP_R6CMP_SULE 0xf
+#define FP_R6CMP_SULT 0xd
+#define FP_R6CMP_SUN 0x9
+#define FP_R6CMP_SUNE 0x1a
+
+/* FPU Class */
+#define FP_R6CLASS_SNAN (1<<0)
+#define FP_R6CLASS_QNAN (1<<1)
+#define FP_R6CLASS_NEGINF (1<<2)
+#define FP_R6CLASS_NEGNORM (1<<3)
+#define FP_R6CLASS_NEGSUB (1<<4)
+#define FP_R6CLASS_NEGZERO (1<<5)
+#define FP_R6CLASS_POSINF (1<<6)
+#define FP_R6CLASS_POSNORM (1<<7)
+#define FP_R6CLASS_POSSUB (1<<8)
+#define FP_R6CLASS_POSZERO (1<<9)
/* FPU operations. */
/* Non-signalling */
@@ -812,21 +869,21 @@ uint64_t fp_fmadd (SIM_STATE, uint64_t op1, uint64_t op2,
uint64_t op3, FP_formats fmt);
#define FusedMultiplySub(op1,op2,op3,fmt) fp_fmsub(SIM_ARGS, op1, op2, op3, fmt)
uint64_t fp_fmsub (SIM_STATE, uint64_t op1, uint64_t op2,
- uint64_t op3, FP_formats fmt);
+ uint64_t op3, FP_formats fmt);
#define MultiplyAdd(op1,op2,op3,fmt) fp_madd(SIM_ARGS, op1, op2, op3, fmt)
uint64_t fp_msub (SIM_STATE, uint64_t op1, uint64_t op2,
- uint64_t op3, FP_formats fmt);
+ uint64_t op3, FP_formats fmt);
#define MultiplySub(op1,op2,op3,fmt) fp_msub(SIM_ARGS, op1, op2, op3, fmt)
uint64_t fp_nmadd (SIM_STATE, uint64_t op1, uint64_t op2,
- uint64_t op3, FP_formats fmt);
+ uint64_t op3, FP_formats fmt);
#define NegMultiplyAdd(op1,op2,op3,fmt) fp_nmadd(SIM_ARGS, op1, op2, op3, fmt)
uint64_t fp_nmsub (SIM_STATE, uint64_t op1, uint64_t op2,
- uint64_t op3, FP_formats fmt);
+ uint64_t op3, FP_formats fmt);
#define NegMultiplySub(op1,op2,op3,fmt) fp_nmsub(SIM_ARGS, op1, op2, op3, fmt)
uint64_t convert (SIM_STATE, int rm, uint64_t op, FP_formats from, FP_formats to);
#define Convert(rm,op,from,to) convert (SIM_ARGS, rm, op, from, to)
uint64_t convert_ps (SIM_STATE, int rm, uint64_t op, FP_formats from,
- FP_formats to);
+ FP_formats to);
#define ConvertPS(rm,op,from,to) convert_ps (SIM_ARGS, rm, op, from, to)
@@ -959,6 +1016,12 @@ uint64_t mdmx_shuffle (SIM_STATE, int, uint64_t, uint64_t);
/* The following are generic to all versions of the MIPS architecture
to date: */
+/* Memory Access Types (for CCA): */
+#define Uncached (0)
+#define CachedNoncoherent (1)
+#define CachedCoherent (2)
+#define Cached (3)
+
#define isINSTRUCTION (1 == 0) /* FALSE */
#define isDATA (1 == 1) /* TRUE */
#define isLOAD (1 == 0) /* FALSE */
@@ -985,13 +1048,17 @@ uint64_t mdmx_shuffle (SIM_STATE, int, uint64_t, uint64_t);
? AccessLength_DOUBLEWORD /*7*/ \
: AccessLength_WORD /*3*/)
+INLINE_SIM_MAIN (int) address_translation (SIM_DESC sd, sim_cpu *, address_word cia, address_word vAddr, int IorD, int LorS, address_word *pAddr, int *CCA, int raw);
+#define AddressTranslation(vAddr,IorD,LorS,pAddr,CCA,host,raw) \
+address_translation (SD, CPU, cia, vAddr, IorD, LorS, pAddr, CCA, raw)
+
INLINE_SIM_MAIN (void) load_memory (SIM_DESC sd, sim_cpu *cpu, address_word cia, uword64* memvalp, uword64* memval1p, int CCA, unsigned int AccessLength, address_word pAddr, address_word vAddr, int IorD);
-#define LoadMemory(memvalp,memval1p,AccessLength,pAddr,vAddr,IorD,raw) \
-load_memory (SD, CPU, cia, memvalp, memval1p, 0, AccessLength, pAddr, vAddr, IorD)
+#define LoadMemory(memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD,raw) \
+load_memory (SD, CPU, cia, memvalp, memval1p, CCA, AccessLength, pAddr, vAddr, IorD)
INLINE_SIM_MAIN (void) store_memory (SIM_DESC sd, sim_cpu *cpu, address_word cia, int CCA, unsigned int AccessLength, uword64 MemElem, uword64 MemElem1, address_word pAddr, address_word vAddr);
-#define StoreMemory(AccessLength,MemElem,MemElem1,pAddr,vAddr,raw) \
-store_memory (SD, CPU, cia, 0, AccessLength, MemElem, MemElem1, pAddr, vAddr)
+#define StoreMemory(CCA,AccessLength,MemElem,MemElem1,pAddr,vAddr,raw) \
+store_memory (SD, CPU, cia, CCA, AccessLength, MemElem, MemElem1, pAddr, vAddr)
INLINE_SIM_MAIN (void) cache_op (SIM_DESC sd, sim_cpu *cpu, address_word cia, int op, address_word pAddr, address_word vAddr, unsigned int instruction);
#define CacheOp(op,pAddr,vAddr,instruction) \
@@ -1001,6 +1068,10 @@ INLINE_SIM_MAIN (void) sync_operation (SIM_DESC sd, sim_cpu *cpu, address_word c
#define SyncOperation(stype) \
sync_operation (SD, CPU, cia, (stype))
+INLINE_SIM_MAIN (void) prefetch (SIM_DESC sd, sim_cpu *cpu, address_word cia, int CCA, address_word pAddr, address_word vAddr, int DATA, int hint);
+#define Prefetch(CCA,pAddr,vAddr,DATA,hint) \
+prefetch (SD, CPU, cia, CCA, pAddr, vAddr, DATA, hint)
+
void unpredictable_action (sim_cpu *cpu, address_word cia);
#define NotWordValue(val) not_word_value (SD_, (val))
#define Unpredictable() unpredictable (SD_)
@@ -1022,6 +1093,16 @@ INLINE_SIM_MAIN (uint16_t) ifetch16 (SIM_DESC sd, sim_cpu *cpu, address_word cia
#define MICROMIPS_DELAYSLOT_SIZE_16 2
#define MICROMIPS_DELAYSLOT_SIZE_32 4
+#define IMEM32_NANOMIPS(CIA) \
+ (ifetch16 (SD, CPU, (CIA), (CIA)) << 16 | ifetch16 (SD, CPU, (CIA + 2), \
+ (CIA + 2)))
+#define IMEM16_NANOMIPS(CIA) ifetch16 (SD, CPU, (CIA), ((CIA)))
+
+
+#define NANOMIPS_MAJOR_OPCODE_3_5(INSN) ((INSN & 0x1c00) >> 10)
+
+#define NANOMIPS_DELAYSLOT_SIZE_ANY 0
+
extern int isa_mode;
#define ISA_MODE_MIPS32 0
@@ -1041,6 +1122,13 @@ extern FILE *tracefh;
extern int DSPLO_REGNUM[4];
extern int DSPHI_REGNUM[4];
+/* NMS Flag */
+extern int nms_flag;
+extern int is_nms_flag_set;
+
+void
+set_nms_flag (SIM_DESC sd);
+
INLINE_SIM_MAIN (void) pending_tick (SIM_DESC sd, sim_cpu *cpu, address_word cia);
extern SIM_CORE_SIGNAL_FN mips_core_signal;
@@ -1055,10 +1143,16 @@ void mips_cpu_exception_suspend(SIM_DESC sd, sim_cpu* cpu, int exception);
void mips_cpu_exception_resume(SIM_DESC sd, sim_cpu* cpu, int exception);
#ifdef MIPS_MACH_MULTI
-extern int mips_mach_multi(SIM_DESC sd);
-#define MIPS_MACH(SD) mips_mach_multi(SD)
+extern address_word micromips_instruction_decode_multi(SIM_DESC sd,
+ sim_cpu* cpu,
+ address_word cia,
+ int instruction_size);
+#define MICROMIPS_INSTRUCTION_DECODE(SD, cpu, cia, size) \
+ micromips_instruction_decode_multi (SD, cpu, cia, size);
#else
-#define MIPS_MACH(SD) MIPS_MACH_DEFAULT
+#define MIPS_MACH(SD) MIPS_MACH_DEFAULT
+#define MICROMIPS_INSTRUCTION_DECODE(SD, cpu, cia, size) \
+ micromips_instruction_decode (SD, cpu, cia, size);
#endif
/* Macros for determining whether a MIPS IV or MIPS V part is subject
--
2.25.1
^ permalink raw reply [flat|nested] 14+ messages in thread