aboutsummaryrefslogtreecommitdiff
path: root/sim/mips
diff options
context:
space:
mode:
authorFaraz Shahbazker <fshahbazker@wavecomp.com>2022-02-02 11:17:25 +0100
committerMike Frysinger <vapier@gentoo.org>2022-02-04 19:37:26 -0500
commit06c441cceffb1437a3af51bfad43dce5fd200d9e (patch)
treee9622ab76b867b2461991d00658703d630018703 /sim/mips
parentfc3c199facd60cc2facbfeee3e541e6aa6410f52 (diff)
downloadgdb-06c441cceffb1437a3af51bfad43dce5fd200d9e.zip
gdb-06c441cceffb1437a3af51bfad43dce5fd200d9e.tar.gz
gdb-06c441cceffb1437a3af51bfad43dce5fd200d9e.tar.bz2
sim: mips: Add simulator support for mips32r6/mips64r6
2022-02-01 Ali Lown <ali.lown@imgtec.com> Andrew Bennett <andrew.bennett@imgtec.com> Dragan Mladjenovic <dragan.mladjenovic@rt-rk.com> Faraz Shahbazker <fshahbazker@wavecomp.com> sim/common/ChangeLog: * sim-bits.h (EXTEND9, EXTEND18 ,EXTEND19, EXTEND21, EXTEND26): New macros. sim/mips/ChangeLog: * Makefile.in (IGEN_INCLUDE): Add mips3264r6.igen. * configure: Regenerate. * configure.ac: Support mipsisa32r6 and mipsisa64r6. (sim_engine_run): Pick simulator model from processor specified in e_flags. * cp1.c (value_fpr): Handle fmt_dc32. (fp_unary, fp_binary): Zero initialize locals. (update_fcsr, fp_classify, fp_rint, fp_r6_cmp, inner_fmac, fp_fmac, fp_min, fp_max, fp_mina, fp_maxa, fp_fmadd, fp_fmsub): New functions. (sim_fpu_class_mips_mapping): New. * cp1.h (fcsr_ABS2008_mask, fcsr_ABS2008_shift): New define. * interp.c (MIPSR6_P): New. (load_word): Allow unaligned memory access for MIPSR6. * micromips.igen (sc, scd): Adapt to new do_sc* helper signature. * mips.igen: Add *r6 models. (signal_if_cti, forbiddenslot32): New helpers. (delayslot32): Use signal_if_cti. (do_sc, do_scd); Add store_ll_bit parameter. (sc, scd): Adapt to previous change. (nal, beq, bal): New definitions for *r6. (sll): Split nop and ssnop cases into ... (nop, ssnop): New definitions. (loadstore_ea): Use the 32-bit compatibility adressing. (cache): Split logic into ... (do_cache): New helper. (check_fpu): Select IEEE 754-2008 mode for R6. (not_word_value, unpredictable, check_mt_hilo, check_mf_hilo, check_multi_hilo, check_div_hilo, check_u64, do_dmfc1b, add, li, addu, and, andi, bgez, bgtz, blez, bltz, bne, break, dadd, daddiu, daddu, dror, dror32, drorv, dsll, dsll32, dsllv, dsra, dsra32, dsrav, dsrl, dsrl32, dsub, dsubu, j, jal, jalr, jalr.hb, lb, lbu, ld, lh, lhu, lui, lw, lwu, nor, or, ori, ror, rorv, sb, sd, sh, sll, sllv, slt, slti, sltiu, sltu, sra, srav, srl, srlv, sub, subu, sw, sync, syscall, teq, tge, tgeu, tlt, tltu, tne, xor, xori, check_fmt_p, do_load_double, do_store_double, abs.FMT, add.FMT, ceil.l.FMT, ceil.w.FMT, cfc1, ctc1, cvt.d.FMT, cvt.l.FMT, cvt.w.FMT, div.FMT, dfmc1, dmtc1, floor.l.FMT, floor.w.FMT, ldc1, lwc1, mfc1, mov.FMT, mtc1, mul.FMT, recip.FMT, round.l.FMT, round.w.FMT, rsqrt.FMT, sdc1, sqrt.FMT, sub.FMT, swc1, trunc.l.FMT, trunc.w.FMT, bc0f, bc0fl, bc0t, bc0tl, dmfc0, dmtc0, eret, mfc0, mtc0, cop, tlbp, tlbr, tlbwi, tlbwr): Enable on *r6 models. * mips3264r2.igen (dext, dextm, dextu, di, dins, dinsm, dinsu, dsbh, dshd, ei, ext, mfhc1, mthc1, ins, seb, seh, synci, rdhwr, wsbh): Likewise. * mips3264r6.igen: New file. * sim-main.h (FP_formats): Add fmt_dc32. (FORBIDDEN_SLOT): New macros. (simFORBIDDENSLOT, FP_R6CMP_*, FP_R6CLASS_*): New defines. (fp_r6_cmp, fp_classify, fp_rint, fp_min, fp_max, fp_mina, fp_maxa, fp_fmadd, fp_fmsub): New declarations. (R6Compare, Classify, RoundToIntegralExact, Min, Max, MinA, MaxA, FusedMultiplyAdd, FusedMultiplySub): New macros. Wrapping previous declarations. sim/testsuite/mips/ChangeLog: * basic.exp: Add r6-*.s tests. (run_r6_removed_test): New function. (run_endian_tests): New function. * hilo-hazard-3.s: Skip for mips*r6. * r2-fpu.s: New test. * r6-64.s: New test. * r6-branch.s: New test. * r6-forbidden.s: New test. * r6-fpu.s: New test. * r6-llsc-dp.s: New test. * r6-llsc-wp.s: New test. * r6-removed.csv: New test. * r6-removed.s: New test. * r6.s: New test. * utils-r6.inc: New inc.
Diffstat (limited to 'sim/mips')
-rw-r--r--sim/mips/Makefile.in1
-rwxr-xr-xsim/mips/configure22
-rw-r--r--sim/mips/configure.ac20
-rw-r--r--sim/mips/cp1.c432
-rw-r--r--sim/mips/cp1.h2
-rw-r--r--sim/mips/interp.c6
-rw-r--r--sim/mips/micromips.igen4
-rw-r--r--sim/mips/mips.igen380
-rw-r--r--sim/mips/mips3264r2.igen30
-rw-r--r--sim/mips/mips3264r6.igen1226
-rw-r--r--sim/mips/sim-main.h94
11 files changed, 2147 insertions, 70 deletions
diff --git a/sim/mips/Makefile.in b/sim/mips/Makefile.in
index 5c66927..75438be 100644
--- a/sim/mips/Makefile.in
+++ b/sim/mips/Makefile.in
@@ -98,6 +98,7 @@ IGEN_INCLUDE=\
$(srcdir)/dsp.igen \
$(srcdir)/dsp2.igen \
$(srcdir)/mips3264r2.igen \
+ $(srcdir)/mips3264r6.igen \
# NB: Since these can be built by a number of generators, care
# must be taken to ensure that they are only dependant on
diff --git a/sim/mips/configure b/sim/mips/configure
index 2521ce8..956b967 100755
--- a/sim/mips/configure
+++ b/sim/mips/configure
@@ -1871,7 +1871,8 @@ case "${target}" in
sim_gen=MULTI
sim_multi_configs="\
micromips:micromips64,micromipsdsp:32,64,f:mips_micromips\
- mips64r2:mips64r2,mips3d,mips16,mips16e,mdmx,dsp,dsp2,smartmips:32,64,f:mipsisa64r2"
+ mipsisa64r2:mips64r2,mips16,mips16e,mdmx,dsp,dsp2,mips3d,smartmips:32,64,f:mipsisa32r2,mipsisa64r2,mipsisa32r5,mipsisa64r5\
+ mipsisa64r6:mips64r6:32,64,f:mipsisa32r6,mipsisa64r6"
sim_multi_default=mipsisa64r2
;;
mips64*-*-*) sim_igen_filter="32,64,f"
@@ -1887,6 +1888,11 @@ case "${target}" in
mips32r2:mips32r2,mips3d,mips16,mips16e,mdmx,dsp,dsp2,smartmips:32,f:mipsisa32r2"
sim_multi_default=mipsisa32r2
;;
+ mipsisa32r6*-*-*) sim_gen=IGEN
+ sim_igen_machine="-M mips32r6"
+ sim_igen_filter="32,f"
+ sim_mach_default="mipsisa32r6"
+ ;;
mipsisa32*-*-*) sim_gen=M16
sim_igen_machine="-M mips32,mips16,mips16e,smartmips"
sim_m16_machine="-M mips16,mips16e,mips32"
@@ -1899,6 +1905,11 @@ case "${target}" in
sim_igen_filter="32,64,f"
sim_mach_default="mipsisa64r2"
;;
+ mipsisa64r6*-*-*) sim_gen=IGEN
+ sim_igen_machine="-M mips64r6"
+ sim_igen_filter="32,64,f"
+ sim_mach_default="mipsisa64r6"
+ ;;
mipsisa64sb1*-*-*) sim_gen=IGEN
sim_igen_machine="-M mips64,mips3d,sb1"
sim_igen_filter="32,64,f"
@@ -1963,7 +1974,7 @@ if test ${sim_gen} = MULTI; then
cat << __EOF__ > multi-run.c
/* Main entry point for MULTI simulators.
- Copyright (C) 2003-2021 Free Software Foundation, Inc.
+ Copyright (C) 2003-2022 Free Software Foundation, Inc.
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
@@ -1985,6 +1996,7 @@ if test ${sim_gen} = MULTI; then
#include "sim-main.h"
#include "multi-include.h"
#include "elf-bfd.h"
+#include "elfxx-mips.h"
#include "elf/mips.h"
#define SD sd
@@ -2004,7 +2016,11 @@ sim_engine_run (SIM_DESC sd,
& EF_MIPS_ARCH_ASE_MICROMIPS)
mach = bfd_mach_mips_micromips;
else
- mach = STATE_ARCHITECTURE (SD)->mach;
+ {
+ mach = _bfd_elf_mips_mach (elf_elfheader (STATE_PROG_BFD (sd))->e_flags);
+ if (!mach)
+ mach = STATE_ARCHITECTURE (SD)->mach;
+ }
switch (mach)
{
diff --git a/sim/mips/configure.ac b/sim/mips/configure.ac
index 2ec9f0f..9680642 100644
--- a/sim/mips/configure.ac
+++ b/sim/mips/configure.ac
@@ -102,7 +102,8 @@ case "${target}" in
sim_gen=MULTI
sim_multi_configs="\
micromips:micromips64,micromipsdsp:32,64,f:mips_micromips\
- mips64r2:mips64r2,mips3d,mips16,mips16e,mdmx,dsp,dsp2,smartmips:32,64,f:mipsisa64r2"
+ mipsisa64r2:mips64r2,mips16,mips16e,mdmx,dsp,dsp2,mips3d,smartmips:32,64,f:mipsisa32r2,mipsisa64r2,mipsisa32r5,mipsisa64r5\
+ mipsisa64r6:mips64r6:32,64,f:mipsisa32r6,mipsisa64r6"
sim_multi_default=mipsisa64r2
;;
mips64*-*-*) sim_igen_filter="32,64,f"
@@ -118,6 +119,11 @@ case "${target}" in
mips32r2:mips32r2,mips3d,mips16,mips16e,mdmx,dsp,dsp2,smartmips:32,f:mipsisa32r2"
sim_multi_default=mipsisa32r2
;;
+ mipsisa32r6*-*-*) sim_gen=IGEN
+ sim_igen_machine="-M mips32r6"
+ sim_igen_filter="32,f"
+ sim_mach_default="mipsisa32r6"
+ ;;
mipsisa32*-*-*) sim_gen=M16
sim_igen_machine="-M mips32,mips16,mips16e,smartmips"
sim_m16_machine="-M mips16,mips16e,mips32"
@@ -130,6 +136,11 @@ case "${target}" in
sim_igen_filter="32,64,f"
sim_mach_default="mipsisa64r2"
;;
+ mipsisa64r6*-*-*) sim_gen=IGEN
+ sim_igen_machine="-M mips64r6"
+ sim_igen_filter="32,64,f"
+ sim_mach_default="mipsisa64r6"
+ ;;
mipsisa64sb1*-*-*) sim_gen=IGEN
sim_igen_machine="-M mips64,mips3d,sb1"
sim_igen_filter="32,64,f"
@@ -216,6 +227,7 @@ if test ${sim_gen} = MULTI; then
#include "sim-main.h"
#include "multi-include.h"
#include "elf-bfd.h"
+#include "elfxx-mips.h"
#include "elf/mips.h"
#define SD sd
@@ -235,7 +247,11 @@ sim_engine_run (SIM_DESC sd,
& EF_MIPS_ARCH_ASE_MICROMIPS)
mach = bfd_mach_mips_micromips;
else
- mach = STATE_ARCHITECTURE (SD)->mach;
+ {
+ mach = _bfd_elf_mips_mach (elf_elfheader (STATE_PROG_BFD (sd))->e_flags);
+ if (!mach)
+ mach = STATE_ARCHITECTURE (SD)->mach;
+ }
switch (mach)
{
diff --git a/sim/mips/cp1.c b/sim/mips/cp1.c
index a6d1b56..196173c 100644
--- a/sim/mips/cp1.c
+++ b/sim/mips/cp1.c
@@ -100,6 +100,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#define FPQNaN_LONG (UNSIGNED64 (0x7FFFFFFFFFFFFFFF))
#define FPQNaN_PS (FP_PS_cat (FPQNaN_SINGLE, FPQNaN_SINGLE))
+static void update_fcsr (sim_cpu *, address_word, sim_fpu_status);
+
static const char *fpu_format_name (FP_formats fmt);
#ifdef DEBUG
static const char *fpu_rounding_mode_name (int rm);
@@ -127,7 +129,7 @@ value_fpr (sim_cpu *cpu,
}
/* For values not yet accessed, set to the desired format. */
- if (fmt < fmt_uninterpreted)
+ if (fmt < fmt_uninterpreted && fmt != fmt_dc32)
{
if (FPR_STATE[fpr] == fmt_uninterpreted)
{
@@ -137,7 +139,10 @@ value_fpr (sim_cpu *cpu,
fpu_format_name (fmt));
#endif /* DEBUG */
}
- else if (fmt != FPR_STATE[fpr])
+ else if (fmt != FPR_STATE[fpr]
+ && !(fmt == fmt_single
+ && FPR_STATE[fpr] == fmt_double
+ && (FGR[fpr] == 0 || FGR[fpr] == 0xFFFFFFFF)))
{
sim_io_eprintf (SD, "FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",
fpr, fpu_format_name (FPR_STATE[fpr]),
@@ -166,6 +171,7 @@ value_fpr (sim_cpu *cpu,
case fmt_uninterpreted_32:
case fmt_single:
case fmt_word:
+ case fmt_dc32:
value = (FGR[fpr] & 0xFFFFFFFF);
break;
@@ -557,8 +563,8 @@ fp_test(uint64_t op1,
if (sim_fpu_is_nan (&wop1) || sim_fpu_is_nan (&wop2))
{
- if ((cond & (1 << 3)) ||
- sim_fpu_is_snan (&wop1) || sim_fpu_is_snan (&wop2))
+ if ((cond & (1 << 3))
+ || sim_fpu_is_snan (&wop1) || sim_fpu_is_snan (&wop2))
status = sim_fpu_status_invalid_snan;
less = 0;
equal = 0;
@@ -581,6 +587,109 @@ fp_test(uint64_t op1,
return status;
}
+static const int sim_fpu_class_mips_mapping[] = {
+ FP_R6CLASS_SNAN, /* SIM_FPU_IS_SNAN = 1, Noisy not-a-number */
+ FP_R6CLASS_QNAN, /* SIM_FPU_IS_QNAN = 2, Quiet not-a-number */
+ FP_R6CLASS_NEGINF, /* SIM_FPU_IS_NINF = 3, -infinity */
+ FP_R6CLASS_POSINF, /* SIM_FPU_IS_PINF = 4, +infinity */
+ FP_R6CLASS_NEGNORM, /* SIM_FPU_IS_NNUMBER = 5, -num - [-MAX .. -MIN] */
+ FP_R6CLASS_POSNORM, /* SIM_FPU_IS_PNUMBER = 6, +num - [+MIN .. +MAX] */
+ FP_R6CLASS_NEGSUB, /* SIM_FPU_IS_NDENORM = 7, -denorm - (MIN .. 0) */
+ FP_R6CLASS_POSSUB, /* SIM_FPU_IS_PDENORM = 8, +denorm - (0 .. MIN) */
+ FP_R6CLASS_NEGZERO, /* SIM_FPU_IS_NZERO = 9, -0 */
+ FP_R6CLASS_POSZERO /* SIM_FPU_IS_PZERO = 10, +0 */
+};
+
+uint64_t
+fp_classify (sim_cpu *cpu,
+ address_word cia,
+ uint64_t op,
+ FP_formats fmt)
+{
+ sim_fpu wop;
+
+ switch (fmt)
+ {
+ case fmt_single:
+ sim_fpu_32to (&wop, op);
+ break;
+ case fmt_double:
+ sim_fpu_64to (&wop, op);
+ break;
+ default:
+ sim_io_error (SD, "Bad switch\n");
+ }
+ return sim_fpu_class_mips_mapping[sim_fpu_classify (&wop) - 1];
+}
+
+int
+fp_rint (sim_cpu *cpu,
+ address_word cia,
+ uint64_t op,
+ uint64_t *ans,
+ FP_formats fmt)
+{
+ sim_fpu wop = {0}, wtemp = {0}, wmagic = {0}, wans = {0};
+ int64_t intermediate;
+ int status = 0;
+ sim_fpu_round round = rounding_mode (GETRM());
+
+ switch (fmt)
+ {
+ case fmt_single:
+ sim_fpu_32to (&wop, op);
+ sim_fpu_32to (&wmagic, 0x4b000000);
+ break;
+ case fmt_double:
+ sim_fpu_64to (&wop, op);
+ sim_fpu_64to (&wmagic, 0x4330000000000000);
+ break;
+ default:
+ sim_io_error (SD, "Bad switch\n");
+ }
+
+ if (sim_fpu_is_nan (&wop) || sim_fpu_is_infinity (&wop))
+ {
+ status = sim_fpu_status_invalid_cvi;
+ update_fcsr (cpu, cia, status);
+ return status;
+ }
+
+ switch (fmt)
+ {
+ case fmt_single:
+ if (sim_fpu_is_ge (&wop, &wmagic))
+ wans = wop;
+ else
+ {
+ sim_fpu_add (&wtemp, &wop, &wmagic);
+ sim_fpu_round_32 (&wtemp, round, sim_fpu_denorm_default);
+ sim_fpu_sub (&wans, &wtemp, &wmagic);
+ }
+ sim_fpu_to32 ((uint32_t *) ans, &wans);
+ break;
+ case fmt_double:
+ if (sim_fpu_is_ge (&wop, &wmagic))
+ wans = wop;
+ else
+ {
+ sim_fpu_add (&wtemp, &wop, &wmagic);
+ sim_fpu_round_64 (&wtemp, round, sim_fpu_denorm_default);
+ sim_fpu_sub (&wans, &wtemp, &wmagic);
+ }
+ sim_fpu_to64 (ans, &wans);
+ break;
+ default:
+ sim_io_error (SD, "Bad switch\n");
+ }
+
+ if (*ans != op && status == 0)
+ status = sim_fpu_status_inexact;
+
+ update_fcsr (cpu, cia, status);
+ return status;
+}
+
void
fp_cmp(sim_cpu *cpu,
address_word cia,
@@ -620,11 +729,91 @@ fp_cmp(sim_cpu *cpu,
break;
}
default:
- sim_io_eprintf (SD, "Bad switch\n");
- abort ();
+ sim_io_error (SD, "Bad switch\n");
}
}
+uint64_t
+fp_r6_cmp (sim_cpu *cpu,
+ address_word cia,
+ uint64_t op1,
+ uint64_t op2,
+ FP_formats fmt,
+ int cond)
+{
+ sim_fpu wop1, wop2;
+ int result = 0;
+ int signalling = cond & 0x8;
+
+ switch (fmt)
+ {
+ case fmt_single:
+ sim_fpu_32to (&wop1, op1);
+ sim_fpu_32to (&wop2, op2);
+ break;
+ case fmt_double:
+ sim_fpu_64to (&wop1, op1);
+ sim_fpu_64to (&wop2, op2);
+ break;
+ default:
+ sim_io_error (SD, "Bad switch\n");
+ }
+
+ switch (cond)
+ {
+ case FP_R6CMP_AF:
+ result = 0;
+ break;
+ case FP_R6CMP_UN:
+ result = sim_fpu_is_un (&wop1, &wop2);
+ break;
+ case FP_R6CMP_OR:
+ result = sim_fpu_is_or (&wop1, &wop2);
+ break;
+ case FP_R6CMP_EQ:
+ result = sim_fpu_is_eq (&wop1, &wop2);
+ break;
+ case FP_R6CMP_NE:
+ result = sim_fpu_is_ne (&wop1, &wop2);
+ break;
+ case FP_R6CMP_LT:
+ result = sim_fpu_is_lt (&wop1, &wop2);
+ break;
+ case FP_R6CMP_LE:
+ result = sim_fpu_is_le (&wop1, &wop2);
+ break;
+ case FP_R6CMP_UEQ:
+ result = sim_fpu_is_un (&wop1, &wop2) || sim_fpu_is_eq (&wop1, &wop2);
+ break;
+ case FP_R6CMP_UNE:
+ result = sim_fpu_is_un (&wop1, &wop2) || sim_fpu_is_ne (&wop1, &wop2);
+ break;
+ case FP_R6CMP_ULT:
+ result = sim_fpu_is_un (&wop1, &wop2) || sim_fpu_is_lt (&wop1, &wop2);
+ break;
+ case FP_R6CMP_ULE:
+ result = sim_fpu_is_un (&wop1, &wop2) || sim_fpu_is_le (&wop1, &wop2);
+ break;
+ default:
+ update_fcsr (cpu, cia, sim_fpu_status_invalid_cmp);
+ break;
+ }
+
+ if (result)
+ {
+ switch (fmt)
+ {
+ case fmt_single:
+ return 0xFFFFFFFF;
+ case fmt_double:
+ return 0xFFFFFFFFFFFFFFFF;
+ default:
+ sim_io_error (SD, "Bad switch\n");
+ }
+ }
+ else
+ return 0;
+}
/* Basic arithmetic operations. */
@@ -635,7 +824,7 @@ fp_unary(sim_cpu *cpu,
uint64_t op,
FP_formats fmt)
{
- sim_fpu wop;
+ sim_fpu wop = {0};
sim_fpu ans;
sim_fpu_round round = rounding_mode (GETRM());
sim_fpu_denorm denorm = denorm_mode (cpu);
@@ -680,8 +869,7 @@ fp_unary(sim_cpu *cpu,
break;
}
default:
- sim_io_eprintf (SD, "Bad switch\n");
- abort ();
+ sim_io_error (SD, "Bad switch\n");
}
update_fcsr (cpu, cia, status);
@@ -696,9 +884,9 @@ fp_binary(sim_cpu *cpu,
uint64_t op2,
FP_formats fmt)
{
- sim_fpu wop1;
- sim_fpu wop2;
- sim_fpu ans;
+ sim_fpu wop1 = {0};
+ sim_fpu wop2 = {0};
+ sim_fpu ans = {0};
sim_fpu_round round = rounding_mode (GETRM());
sim_fpu_denorm denorm = denorm_mode (cpu);
sim_fpu_status status = 0;
@@ -746,8 +934,7 @@ fp_binary(sim_cpu *cpu,
break;
}
default:
- sim_io_eprintf (SD, "Bad switch\n");
- abort ();
+ sim_io_error (SD, "Bad switch\n");
}
update_fcsr (cpu, cia, status);
@@ -786,7 +973,7 @@ inner_mac(int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
ans.normal_exp += scale;
status |= sim_fpu_round_32 (&ans, round, denorm);
wop1 = ans;
- op_status = 0;
+ op_status = 0;
sim_fpu_32to (&wop2, op3);
op_status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
op_status |= sim_fpu_round_32 (&ans, round, denorm);
@@ -812,7 +999,7 @@ inner_mac(int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
ans.normal_exp += scale;
status |= sim_fpu_round_64 (&ans, round, denorm);
wop1 = ans;
- op_status = 0;
+ op_status = 0;
sim_fpu_64to (&wop2, op3);
op_status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
op_status |= sim_fpu_round_64 (&ans, round, denorm);
@@ -881,8 +1068,89 @@ fp_mac(sim_cpu *cpu,
break;
}
default:
- sim_io_eprintf (SD, "Bad switch\n");
- abort ();
+ sim_io_error (SD, "Bad switch\n");
+ }
+
+ update_fcsr (cpu, cia, status);
+ return result;
+}
+
+/* Common FMAC code for .s, .d. Defers setting FCSR to caller. */
+static sim_fpu_status
+inner_fmac (sim_cpu *cpu,
+ int (*sim_fpu_op) (sim_fpu *, const sim_fpu *, const sim_fpu *),
+ uint64_t op1,
+ uint64_t op2,
+ uint64_t op3,
+ sim_fpu_round round,
+ sim_fpu_denorm denorm,
+ FP_formats fmt,
+ uint64_t *result)
+{
+ sim_fpu wop1, wop2, ans;
+ sim_fpu_status status = 0;
+ sim_fpu_status op_status;
+ uint32_t t32 = 0;
+ uint64_t t64 = 0;
+
+ switch (fmt)
+ {
+ case fmt_single:
+ sim_fpu_32to (&wop1, op1);
+ sim_fpu_32to (&wop2, op2);
+ status |= sim_fpu_mul (&ans, &wop1, &wop2);
+ wop1 = ans;
+ op_status = 0;
+ sim_fpu_32to (&wop2, op3);
+ op_status |= (*sim_fpu_op) (&ans, &wop2, &wop1);
+ op_status |= sim_fpu_round_32 (&ans, round, denorm);
+ status |= op_status;
+ sim_fpu_to32 (&t32, &ans);
+ t64 = t32;
+ break;
+ case fmt_double:
+ sim_fpu_64to (&wop1, op1);
+ sim_fpu_64to (&wop2, op2);
+ status |= sim_fpu_mul (&ans, &wop1, &wop2);
+ wop1 = ans;
+ op_status = 0;
+ sim_fpu_64to (&wop2, op3);
+ op_status |= (*sim_fpu_op) (&ans, &wop2, &wop1);
+ op_status |= sim_fpu_round_64 (&ans, round, denorm);
+ status |= op_status;
+ sim_fpu_to64 (&t64, &ans);
+ break;
+ default:
+ sim_io_error (SD, "Bad switch\n");
+ }
+
+ *result = t64;
+ return status;
+}
+
+static uint64_t
+fp_fmac (sim_cpu *cpu,
+ address_word cia,
+ int (*sim_fpu_op) (sim_fpu *, const sim_fpu *, const sim_fpu *),
+ uint64_t op1,
+ uint64_t op2,
+ uint64_t op3,
+ FP_formats fmt)
+{
+ sim_fpu_round round = rounding_mode (GETRM());
+ sim_fpu_denorm denorm = denorm_mode (cpu);
+ sim_fpu_status status = 0;
+ uint64_t result = 0;
+
+ switch (fmt)
+ {
+ case fmt_single:
+ case fmt_double:
+ status = inner_fmac (cpu, sim_fpu_op, op1, op2, op3,
+ round, denorm, fmt, &result);
+ break;
+ default:
+ sim_io_error (SD, "Bad switch\n");
}
update_fcsr (cpu, cia, status);
@@ -972,8 +1240,7 @@ fp_inv_sqrt(sim_cpu *cpu,
break;
}
default:
- sim_io_eprintf (SD, "Bad switch\n");
- abort ();
+ sim_io_error (SD, "Bad switch\n");
}
update_fcsr (cpu, cia, status);
@@ -1040,6 +1307,94 @@ fp_div(sim_cpu *cpu,
}
uint64_t
+fp_min (sim_cpu *cpu,
+ address_word cia,
+ uint64_t op1,
+ uint64_t op2,
+ FP_formats fmt)
+{
+ return fp_binary (cpu, cia, &sim_fpu_min, op1, op2, fmt);
+}
+
+uint64_t
+fp_max (sim_cpu *cpu,
+ address_word cia,
+ uint64_t op1,
+ uint64_t op2,
+ FP_formats fmt)
+{
+ return fp_binary (cpu, cia, &sim_fpu_max, op1, op2, fmt);
+}
+
+uint64_t
+fp_mina (sim_cpu *cpu,
+ address_word cia,
+ uint64_t op1,
+ uint64_t op2,
+ FP_formats fmt)
+{
+ uint64_t ret;
+ sim_fpu wop1 = {0}, wop2 = {0}, waop1, waop2, wans;
+ sim_fpu_status status = 0;
+
+ switch (fmt)
+ {
+ case fmt_single:
+ sim_fpu_32to (&wop1, op1);
+ sim_fpu_32to (&wop2, op2);
+ break;
+ case fmt_double:
+ sim_fpu_64to (&wop1, op1);
+ sim_fpu_64to (&wop2, op2);
+ break;
+ default:
+ sim_io_error (SD, "Bad switch\n");
+ }
+
+ status |= sim_fpu_abs (&waop1, &wop1);
+ status |= sim_fpu_abs (&waop2, &wop2);
+ status |= sim_fpu_min (&wans, &waop1, &waop2);
+ ret = (sim_fpu_is_eq (&wans, &waop1)) ? op1 : op2;
+
+ update_fcsr (cpu, cia, status);
+ return ret;
+}
+
+uint64_t
+fp_maxa (sim_cpu *cpu,
+ address_word cia,
+ uint64_t op1,
+ uint64_t op2,
+ FP_formats fmt)
+{
+ uint64_t ret;
+ sim_fpu wop1 = {0}, wop2 = {0}, waop1, waop2, wans;
+ sim_fpu_status status = 0;
+
+ switch (fmt)
+ {
+ case fmt_single:
+ sim_fpu_32to (&wop1, op1);
+ sim_fpu_32to (&wop2, op2);
+ break;
+ case fmt_double:
+ sim_fpu_64to (&wop1, op1);
+ sim_fpu_64to (&wop2, op2);
+ break;
+ default:
+ sim_io_error (SD, "Bad switch\n");
+ }
+
+ status |= sim_fpu_abs (&waop1, &wop1);
+ status |= sim_fpu_abs (&waop2, &wop2);
+ status |= sim_fpu_max (&wans, &waop1, &waop2);
+ ret = (sim_fpu_is_eq (&wans, &waop1)) ? op1 : op2;
+
+ update_fcsr (cpu, cia, status);
+ return ret;
+}
+
+uint64_t
fp_recip(sim_cpu *cpu,
address_word cia,
uint64_t op,
@@ -1089,6 +1444,28 @@ fp_msub(sim_cpu *cpu,
}
uint64_t
+fp_fmadd (sim_cpu *cpu,
+ address_word cia,
+ uint64_t op1,
+ uint64_t op2,
+ uint64_t op3,
+ FP_formats fmt)
+{
+ return fp_fmac (cpu, cia, &sim_fpu_add, op1, op2, op3, fmt);
+}
+
+uint64_t
+fp_fmsub (sim_cpu *cpu,
+ address_word cia,
+ uint64_t op1,
+ uint64_t op2,
+ uint64_t op3,
+ FP_formats fmt)
+{
+ return fp_fmac (cpu, cia, &sim_fpu_sub, op1, op2, op3, fmt);
+}
+
+uint64_t
fp_nmadd(sim_cpu *cpu,
address_word cia,
uint64_t op1,
@@ -1394,8 +1771,7 @@ convert (sim_cpu *cpu,
status = sim_fpu_i64to (&wop, op, round);
break;
default:
- sim_io_eprintf (SD, "Bad switch\n");
- abort ();
+ sim_io_error (SD, "Bad switch\n");
}
/* Convert sim_fpu format into the output */
@@ -1430,8 +1806,7 @@ convert (sim_cpu *cpu,
break;
default:
result64 = 0;
- sim_io_eprintf (SD, "Bad switch\n");
- abort ();
+ sim_io_error (SD, "Bad switch\n");
}
update_fcsr (cpu, cia, status);
@@ -1481,8 +1856,7 @@ pack_ps(sim_cpu *cpu,
break;
}
default:
- sim_io_eprintf (SD, "Bad switch\n");
- abort ();
+ sim_io_error (SD, "Bad switch\n");
}
return result;
@@ -1517,8 +1891,7 @@ convert_ps (sim_cpu *cpu,
sim_fpu_32to (&wop_l, FP_PS_lower(op));
break;
default:
- sim_io_eprintf (SD, "Bad switch\n");
- abort ();
+ sim_io_error (SD, "Bad switch\n");
}
/* Convert sim_fpu format into the output */
@@ -1538,8 +1911,7 @@ convert_ps (sim_cpu *cpu,
break;
default:
result = 0;
- sim_io_eprintf (SD, "Bad switch\n");
- abort ();
+ sim_io_error (SD, "Bad switch\n");
}
update_fcsr (cpu, cia, status_u | status_l);
diff --git a/sim/mips/cp1.h b/sim/mips/cp1.h
index d6d8a88..5622b93 100644
--- a/sim/mips/cp1.h
+++ b/sim/mips/cp1.h
@@ -43,6 +43,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* FCSR bits for IEEE754-2008 compliance. */
#define fcsr_NAN2008_mask (0x00040000)
#define fcsr_NAN2008_shift (18)
+#define fcsr_ABS2008_mask (0x00080000)
+#define fcsr_ABS2008_shift (19)
#define fenr_FS (0x00000004)
diff --git a/sim/mips/interp.c b/sim/mips/interp.c
index 6501562..c5d0901 100644
--- a/sim/mips/interp.c
+++ b/sim/mips/interp.c
@@ -1549,6 +1549,10 @@ store_word (SIM_DESC sd,
}
}
+#define MIPSR6_P(abfd) \
+ ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R6 \
+ || (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_64R6)
+
/* Load a word from memory. */
static signed_word
@@ -1557,7 +1561,7 @@ load_word (SIM_DESC sd,
address_word cia,
uword64 vaddr)
{
- if ((vaddr & 3) != 0)
+ if ((vaddr & 3) != 0 && !MIPSR6_P (STATE_PROG_BFD (sd)))
{
SIM_CORE_SIGNAL (SD, cpu, cia, read_map, AccessLength_WORD+1, vaddr, read_transfer, sim_core_unaligned_signal);
}
diff --git a/sim/mips/micromips.igen b/sim/mips/micromips.igen
index acbff6f..bb61b3f 100644
--- a/sim/mips/micromips.igen
+++ b/sim/mips/micromips.igen
@@ -1761,7 +1761,7 @@
*micromips32:
*micromips64:
{
- do_sc (SD_, RT, EXTEND12 (IMMEDIATE), BASE, instruction_0);
+ do_sc (SD_, RT, EXTEND12 (IMMEDIATE), BASE, instruction_0, 1);
}
@@ -3074,7 +3074,7 @@
*micromips64:
{
check_u64 (SD_, instruction_0);
- do_scd (SD_, RT, OFFSET, BASE);
+ do_scd (SD_, RT, OFFSET, BASE, 1);
}
110110,5.RT,5.BASE,16.OFFSET:MICROMIPS64:64::SD
diff --git a/sim/mips/mips.igen b/sim/mips/mips.igen
index b0c5e59..dfad422 100644
--- a/sim/mips/mips.igen
+++ b/sim/mips/mips.igen
@@ -46,8 +46,10 @@
:model:::mipsV:mipsisaV:
:model:::mips32:mipsisa32:
:model:::mips32r2:mipsisa32r2:
+:model:::mips32r6:mipsisa32r6:
:model:::mips64:mipsisa64:
:model:::mips64r2:mipsisa64r2:
+:model:::mips64r6:mipsisa64r6:
// Vendor ISAs:
//
@@ -102,7 +104,28 @@
-// Helper:
+// Helpers:
+//
+// Check if given instruction is CTI, if so signal
+//
+:function:::void:signal_if_cti:instruction_word instr
+{
+ uint32_t maj = (instr & 0xfc000000) >> 26;
+ uint32_t special = instr & 0x3f;
+ if ((maj & 0x3e) == 0x06 /* Branch/Jump */
+ || ((maj & 0x38) == 0 && !((maj & 0x6) == 0))
+ || maj == 0x18
+ || (maj & 0x37) == 0x32
+ || (maj & 0x37) == 0x36
+ || ((maj == 0) && (special == 0x9))
+ /* DERET/ERET/WAIT */
+ || ((maj == 0x10) && (instr & 0x02000000)
+ && (special == 0x1f || special == 0x18 || special == 0x20)))
+ {
+ SignalException (ReservedInstruction, instr);
+ }
+}
+
//
// Simulate a 32 bit delayslot instruction
//
@@ -115,12 +138,34 @@
CIA = CIA + 4; /* NOTE not mips16 */
STATE |= simDELAYSLOT;
delay_insn = IMEM32 (CIA); /* NOTE not mips16 */
+ signal_if_cti (SD_, delay_insn);
ENGINE_ISSUE_PREFIX_HOOK();
idecode_issue (CPU_, delay_insn, (CIA));
STATE &= ~simDELAYSLOT;
return target;
}
+//
+// Simulate a 32 bit forbidden slot instruction
+//
+
+:function:::address_word:forbiddenslot32:
+*mips32r6:
+*mips64r6:
+{
+ instruction_word delay_insn;
+ sim_events_slip (SD, 1);
+ DSPC = CIA;
+ CIA = CIA + 4;
+ STATE |= simFORBIDDENSLOT;
+ delay_insn = IMEM32 (CIA);
+ signal_if_cti (SD_, delay_insn);
+ ENGINE_ISSUE_PREFIX_HOOK ();
+ idecode_issue (CPU_, delay_insn, (CIA));
+ STATE &= ~simFORBIDDENSLOT;
+ return CIA + 4;
+}
+
:function:::address_word:nullify_next_insn32:
{
sim_events_slip (SD, 1);
@@ -142,6 +187,7 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*vr4100:
*vr5000:
*r3900:
@@ -154,6 +200,7 @@
*mips64:
*mips64r2:
*micromips64:
+*mips64r6:
{
#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
@@ -184,10 +231,12 @@
*r3900:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
*micromips32:
*micromips64:
+*mips64r6:
{
#if WITH_TARGET_WORD_BITSIZE == 64
return value != (((value & 0xffffffff) ^ 0x80000000) - 0x80000000);
@@ -219,10 +268,12 @@
:function:::void:unpredictable:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
*micromips32:
*micromips64:
+*mips64r6:
{
unpredictable_action (CPU, CIA);
}
@@ -311,8 +362,10 @@
:function:::int:check_mt_hilo:hilo_history *history
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*r3900:
*micromips32:
*micromips64:
@@ -337,8 +390,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -411,8 +466,10 @@
:function:::int:check_mult_hilo:hilo_history *hi, hilo_history *lo
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*r3900:
*micromips32:
*micromips64:
@@ -468,10 +525,12 @@
:function:::int:check_div_hilo:hilo_history *hi, hilo_history *lo
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
*micromips32:
*micromips64:
+*mips64r6:
{
int64_t time = sim_events_time (SD);
hi->op.timestamp = time;
@@ -507,8 +566,10 @@
*mips64r2:
*mips32:
*mips32r2:
+*mips32r6:
*micromips64:
*micromips32:
+*mips64r6:
{
#if 0 /* XXX FIXME: enable this only after some additional testing. */
if (UserMode && (SR & (status_UX|status_PX)) == 0)
@@ -1081,7 +1142,7 @@
}
}
-:function:::void:do_sc:int rt, int offsetarg, int basereg, address_word instruction_0
+:function:::void:do_sc:int rt, int offsetarg, int basereg, address_word instruction_0, int store_ll_bit
{
uint32_t instruction = instruction_0;
address_word base = GPR[basereg];
@@ -1111,12 +1172,13 @@
if (LLBIT)
StoreMemory (AccessLength_WORD, memval, memval1, paddr, vaddr,
isREAL);
- GPR[rt] = LLBIT;
+ if (store_ll_bit)
+ GPR[rt] = LLBIT;
}
}
}
-:function:::void:do_scd:int rt, int roffset, int rbase
+:function:::void:do_scd:int rt, int roffset, int rbase, int store_ll_bit
{
address_word base = GPR[rbase];
address_word offset = EXTEND16 (roffset);
@@ -1137,7 +1199,8 @@
if (LLBIT)
StoreMemory (AccessLength_DOUBLEWORD, memval, memval1, paddr, vaddr,
isREAL);
- GPR[rt] = LLBIT;
+ if (store_ll_bit)
+ GPR[rt] = LLBIT;
}
}
}
@@ -1376,6 +1439,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -1633,6 +1697,7 @@
*mipsII:
*mips32:
*mips32r2:
+*mips32r6:
*micromips32:
{
check_fpu (SD_);
@@ -1763,8 +1828,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -1812,8 +1879,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -1841,8 +1910,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -1868,8 +1939,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -1888,8 +1961,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -1922,6 +1997,17 @@
}
+000100,5.RS,5.RT,16.OFFSET:R6:32::BEQ
+"beq r<RS>, r<RT>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+ address_word offset = EXTEND16 (OFFSET) << 2;
+ if (GPR[RS] == GPR[RT])
+ DELAY_SLOT (NIA + offset);
+ else
+ FORBIDDEN_SLOT ();
+}
010100,5.RS,5.RT,16.OFFSET:NORMAL:32::BEQL
"beql r<RS>, r<RT>, <OFFSET>"
@@ -1957,8 +2043,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -1997,7 +2085,15 @@
}
}
-
+000001,00000,10001,16.OFFSET:REGIMM:32::BAL
+"bal <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+ address_word offset = EXTEND16 (OFFSET) << 2;
+ RA = (CIA + 8);
+ DELAY_SLOT (NIA + offset);
+}
000001,5.RS!31,10011,16.OFFSET:REGIMM:32::BGEZALL
"bgezall r<RS>, <OFFSET>"
@@ -2063,8 +2159,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -2114,8 +2212,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -2165,8 +2265,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -2209,6 +2311,18 @@
+000001,00000,10000,16.OFFSET:REGIMM:32::NAL
+"nal <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+ address_word offset = EXTEND16 (OFFSET) << 2;
+ RA = (CIA + 8);
+ FORBIDDEN_SLOT ();
+}
+
+
+
000001,5.RS!31,10010,16.OFFSET:REGIMM:32::BLTZALL
"bltzall r<RS>, <OFFSET>"
*mipsII:
@@ -2273,8 +2387,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -2322,8 +2438,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -2370,6 +2488,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -2409,6 +2528,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -2432,6 +2552,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -2450,6 +2571,8 @@
if (RT != RD)
Unpredictable ();
check_u64 (SD_, instruction_0);
+ if (RT != RD)
+ Unpredictable ();
do_dclo (SD_, RD, RS);
}
@@ -2464,6 +2587,8 @@
if (RT != RD)
Unpredictable ();
check_u64 (SD_, instruction_0);
+ if (RT != RD)
+ Unpredictable ();
do_dclz (SD_, RD, RS);
}
@@ -2771,6 +2896,7 @@
000000,00001,5.RT,5.RD,5.SHIFT,111010::64::DROR
"dror r<RD>, r<RT>, <SHIFT>"
*mips64r2:
+*mips64r6:
*vr5400:
*vr5500:
{
@@ -2781,6 +2907,7 @@
000000,00001,5.RT,5.RD,5.SHIFT,111110::64::DROR32
"dror32 r<RD>, r<RT>, <SHIFT>"
*mips64r2:
+*mips64r6:
*vr5400:
*vr5500:
{
@@ -2791,6 +2918,7 @@
000000,5.RS,5.RT,5.RD,00001,010110::64::DRORV
"drorv r<RD>, r<RT>, r<RS>"
*mips64r2:
+*mips64r6:
*vr5400:
*vr5500:
{
@@ -2813,6 +2941,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -2828,6 +2957,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -2850,6 +2980,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -2872,6 +3003,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -2887,6 +3019,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -2910,6 +3043,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -2932,6 +3066,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -2947,6 +3082,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -2972,6 +3108,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -2987,6 +3124,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -3009,6 +3147,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -3026,8 +3165,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -3048,8 +3189,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -3071,8 +3214,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -3086,7 +3231,9 @@
"jalr.hb r<RS>":RD == 31
"jalr.hb r<RD>, r<RS>"
*mips32r2:
+*mips32r6:
*mips64r2:
+*mips64r6:
{
address_word temp = GPR[RS];
GPR[RD] = CIA + 8;
@@ -3102,8 +3249,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -3114,7 +3263,9 @@
000000,5.RS,0000000000,10000,001000:SPECIAL:32::JR_HB
"jr.hb r<RS>"
*mips32r2:
+*mips32r6:
*mips64r2:
+*mips64r6:
{
DELAY_SLOT (GPR[RS]);
}
@@ -3232,8 +3383,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -3251,8 +3404,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -3268,6 +3423,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -3335,8 +3491,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -3354,8 +3512,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -3405,8 +3565,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -3424,8 +3586,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -3498,6 +3662,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -3882,8 +4047,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -3908,8 +4075,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -3935,8 +4104,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -3973,7 +4144,9 @@
000000,00001,5.RT,5.RD,5.SHIFT,000010::32::ROR
"ror r<RD>, r<RT>, <SHIFT>"
*mips32r2:
+*mips32r6:
*mips64r2:
+*mips64r6:
*smartmips:
*vr5400:
*vr5500:
@@ -3984,7 +4157,9 @@
000000,5.RS,5.RT,5.RD,00001,000110::32::RORV
"rorv r<RD>, r<RT>, r<RS>"
*mips32r2:
+*mips32r6:
*mips64r2:
+*mips64r6:
*smartmips:
*vr5400:
*vr5500:
@@ -4086,8 +4261,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -4109,7 +4286,7 @@
*vr4100:
*vr5000:
{
- do_sc (SD_, RT, OFFSET, BASE, instruction_0);
+ do_sc (SD_, RT, OFFSET, BASE, instruction_0, 1);
}
@@ -4124,7 +4301,7 @@
*vr5000:
{
check_u64 (SD_, instruction_0);
- do_scd (SD_, RT, OFFSET, BASE);
+ do_scd (SD_, RT, OFFSET, BASE, 1);
}
@@ -4135,6 +4312,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -4200,8 +4378,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -4239,16 +4419,16 @@
000000,00000,5.RT,5.RD,5.SHIFT,000000:SPECIAL:32::SLLb
"nop":RD == 0 && RT == 0 && SHIFT == 0
"ssnop":RD == 0 && RT == 0 && SHIFT == 1
+"ehb":RD == 0 && RT == 0 && SHIFT == 3
"sll r<RD>, r<RT>, <SHIFT>"
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
{
- /* Skip shift for NOP and SSNOP, so that there won't be lots of
- extraneous trace output. */
- if (RD != 0 || RT != 0 || (SHIFT != 0 && SHIFT != 1))
- do_sll (SD_, RT, RD, SHIFT);
+ do_sll (SD_, RT, RD, SHIFT);
}
@@ -4270,8 +4450,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -4296,8 +4478,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -4322,8 +4506,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -4348,8 +4534,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -4375,8 +4563,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -4404,8 +4594,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -4435,8 +4627,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -4465,8 +4659,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -4495,8 +4691,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -4514,8 +4712,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -4542,8 +4742,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -4561,8 +4763,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*r3900:
*vr5000:
@@ -4637,8 +4841,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -4656,8 +4862,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -4674,8 +4882,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -4708,8 +4918,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -4759,8 +4971,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -4776,8 +4990,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -4827,8 +5043,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -4844,8 +5062,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -4886,8 +5106,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -4912,8 +5134,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -4996,6 +5220,8 @@
*mipsIII:
*mipsIV:
*mips32:
+*mips32r6:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -5051,10 +5277,27 @@
if (! COP_Usable (1))
SignalExceptionCoProcessorUnusable (1);
- FCSR &= ~fcsr_NAN2008_mask;
+ FCSR &= ~(fcsr_NAN2008_mask | fcsr_ABS2008_mask);
sim_fpu_quiet_nan_inverted = true;
}
+// Helper:
+//
+// Check that the FPU is currently usable, and signal a CoProcessorUnusable
+// exception if not.
+//
+
+:function:::void:check_fpu:
+*mips32r6:
+*mips64r6:
+{
+ if (! COP_Usable (1))
+ SignalExceptionCoProcessorUnusable (1);
+
+ FCSR |= (fcsr_NAN2008_mask | fcsr_ABS2008_mask);
+ sim_fpu_quiet_nan_inverted = 0;
+ sim_fpu_set_mode (sim_fpu_ieee754_2008);
+}
// Helper:
//
@@ -5067,6 +5310,7 @@
*mipsII:
*mips32:
*mips32r2:
+*mips32r6:
*micromips32:
{
int bigendian = (BigEndianCPU ? ! ReverseEndian : ReverseEndian);
@@ -5102,6 +5346,7 @@
*mips32:
*mips32r2:
*micromips32:
+ *mips32r6:
{
int bigendian = (BigEndianCPU ? ! ReverseEndian : ReverseEndian);
address_word vaddr;
@@ -5131,8 +5376,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -5151,8 +5398,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -5263,8 +5512,10 @@
*mipsIV:
*mipsV:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -5281,8 +5532,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -5328,8 +5581,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
{
do_cfc1 (SD_, RT, FS);
}
@@ -5365,8 +5620,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
{
do_ctc1 (SD_, RT, FS);
}
@@ -5384,8 +5641,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -5400,8 +5659,10 @@
*mipsIV:
*mipsV:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -5433,8 +5694,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -5474,8 +5737,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -5493,8 +5758,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -5526,6 +5793,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -5561,6 +5829,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -5577,8 +5846,10 @@
*mipsIV:
*mipsV:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -5595,8 +5866,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -5610,6 +5883,7 @@
*mipsII:
*mips32:
*mips32r2:
+*mips32r6:
{
check_fpu (SD_);
COP_LD (1, FT, do_load_double (SD_, GPR[BASE], EXTEND16 (OFFSET)));
@@ -5623,6 +5897,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -5684,8 +5959,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -5740,8 +6017,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -5759,8 +6038,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -5869,8 +6150,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -5888,8 +6171,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -5907,8 +6192,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -6005,8 +6292,10 @@
*mipsIV:
*mipsV:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr5000:
{
do_recip_fmt (SD_, FMT, FD, FS);
@@ -6019,8 +6308,10 @@
*mipsIV:
*mipsV:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -6037,8 +6328,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -6052,8 +6345,10 @@
*mipsIV:
*mipsV:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr5000:
{
do_rsqrt_fmt (SD_, FMT, FD, FS);
@@ -6065,6 +6360,7 @@
*mipsII:
*mips32:
*mips32r2:
+*mips32r6:
{
do_sdc1 (SD_, FT, OFFSET, BASE);
}
@@ -6077,6 +6373,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -6088,7 +6385,7 @@
010011,5.BASE,5.INDEX,5.FS,00000001001:COP1X:32,f::SDXC1
"sdxc1 f<FS>, r<INDEX>(r<BASE>)"
-*mips32r2
+*mips32r2:
{
check_fpu (SD_);
do_store_double (SD_, GPR[BASE], GPR[INDEX], COP_SD (1, FS));
@@ -6137,8 +6434,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -6156,8 +6455,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -6176,8 +6477,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -6205,8 +6508,10 @@
*mipsIV:
*mipsV:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -6223,8 +6528,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -6249,8 +6556,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
@@ -6272,8 +6581,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
@@ -6287,8 +6598,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
@@ -6301,11 +6614,23 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
+:function:::void:do_cache:int op, int rbase, int roffset, address_word instruction_0
+{
+ address_word base = GPR[rbase];
+ address_word offset = EXTEND16 (roffset);
+ {
+ address_word vaddr = loadstore_ea (SD_, base, offset);
+ address_word paddr = vaddr;
+ CacheOp(op, vaddr, paddr, instruction_0);
+ }
+}
101111,5.BASE,5.OP,16.OFFSET:NORMAL:32::CACHE
"cache <OP>, <OFFSET>(r<BASE>)"
@@ -6320,13 +6645,7 @@
*vr5000:
*r3900:
{
- address_word base = GPR[BASE];
- address_word offset = EXTEND16 (OFFSET);
- {
- address_word vaddr = loadstore_ea (SD_, base, offset);
- address_word paddr = vaddr;
- CacheOp(OP, vaddr, paddr, instruction_0);
- }
+ do_cache (SD_, OP, BASE, OFFSET, instruction_0);
}
@@ -6337,6 +6656,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
{
check_u64 (SD_, instruction_0);
DecodeCoproc (instruction_0, 0, cp0_dmfc0, RT, RD, SEL);
@@ -6350,6 +6670,7 @@
*mipsV:
*mips64:
*mips64r2:
+*mips64r6:
{
check_u64 (SD_, instruction_0);
DecodeCoproc (instruction_0, 0, cp0_dmtc0, RT, RD, SEL);
@@ -6363,8 +6684,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
{
@@ -6392,8 +6715,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -6412,8 +6737,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
*r3900:
@@ -6446,8 +6773,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*r3900:
{
@@ -6465,8 +6794,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
@@ -6480,8 +6811,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
@@ -6495,8 +6828,10 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
@@ -6510,13 +6845,16 @@
*mipsV:
*mips32:
*mips32r2:
+*mips32r6:
*mips64:
*mips64r2:
+*mips64r6:
*vr4100:
*vr5000:
:include:::mips3264r2.igen
+:include:::mips3264r6.igen
:include:::m16.igen
:include:::m16e.igen
:include:::mdmx.igen
diff --git a/sim/mips/mips3264r2.igen b/sim/mips/mips3264r2.igen
index e0b838c..a28d989 100644
--- a/sim/mips/mips3264r2.igen
+++ b/sim/mips/mips3264r2.igen
@@ -193,6 +193,7 @@
011111,5.RS,5.RT,5.SIZE,5.LSB,000011::64::DEXT
"dext r<RT>, r<RS>, <LSB>, <SIZE+1>"
*mips64r2:
+*mips64r6:
{
check_u64 (SD_, instruction_0);
do_dext (SD_, RT, RS, LSB, SIZE);
@@ -201,6 +202,7 @@
011111,5.RS,5.RT,5.SIZE,5.LSB,000001::64::DEXTM
"dextm r<RT>, r<RS>, <LSB>, <SIZE+33>"
*mips64r2:
+*mips64r6:
{
check_u64 (SD_, instruction_0);
do_dextm (SD_, RT, RS, LSB, SIZE);
@@ -209,6 +211,7 @@
011111,5.RS,5.RT,5.SIZE,5.LSB,000010::64::DEXTU
"dextu r<RT>, r<RS>, <LSB+32>, <SIZE+1>"
*mips64r2:
+*mips64r6:
{
check_u64 (SD_, instruction_0);
do_dextu (SD_, RT, RS, LSB, SIZE);
@@ -219,7 +222,9 @@
"di":RT == 0
"di r<RT>"
*mips32r2:
+*mips32r6:
*mips64r2:
+*mips64r6:
{
do_di (SD_, RT);
}
@@ -228,6 +233,7 @@
011111,5.RS,5.RT,5.MSB,5.LSB,000111::64::DINS
"dins r<RT>, r<RS>, <LSB>, <MSB-LSB+1>"
*mips64r2:
+*mips64r6:
{
check_u64 (SD_, instruction_0);
do_dins (SD_, RT, RS, LSB, MSB);
@@ -236,6 +242,7 @@
011111,5.RS,5.RT,5.MSB,5.LSB,000101::64::DINSM
"dinsm r<RT>, r<RS>, <LSB>, <MSB+32-LSB+1>"
*mips64r2:
+*mips64r6:
{
check_u64 (SD_, instruction_0);
do_dinsm (SD_, RT, RS, LSB, MSB);
@@ -244,6 +251,7 @@
011111,5.RS,5.RT,5.MSB,5.LSB,000110::64::DINSU
"dinsu r<RT>, r<RS>, <LSB+32>, <MSB-LSB+1>"
*mips64r2:
+*mips64r6:
{
check_u64 (SD_, instruction_0);
do_dinsu (SD_, RT, RS, LSB, MSB);
@@ -253,6 +261,7 @@
011111,00000,5.RT,5.RD,00010,100100::64::DSBH
"dsbh r<RD>, r<RT>"
*mips64r2:
+*mips64r6:
{
check_u64 (SD_, instruction_0);
do_dsbh (SD_, RD, RT);
@@ -261,6 +270,7 @@
011111,00000,5.RT,5.RD,00101,100100::64::DSHD
"dshd r<RD>, r<RT>"
*mips64r2:
+*mips64r6:
{
check_u64 (SD_, instruction_0);
do_dshd (SD_, RD, RT);
@@ -270,7 +280,9 @@
"ei":RT == 0
"ei r<RT>"
*mips32r2:
+*mips32r6:
*mips64r2:
+*mips64r6:
{
do_ei (SD_, RT);
}
@@ -279,7 +291,9 @@
011111,5.RS,5.RT,5.SIZE,5.LSB,000000::32::EXT
"ext r<RT>, r<RS>, <LSB>, <SIZE+1>"
*mips32r2:
+*mips32r6:
*mips64r2:
+*mips64r6:
{
do_ext (SD_, RT, RS, LSB, SIZE);
}
@@ -288,7 +302,9 @@
010001,00011,5.RT,5.FS,00000000000:COP1Sa:32,f::MFHC1
"mfhc1 r<RT>, f<FS>"
*mips32r2:
+*mips32r6:
*mips64r2:
+*mips64r6:
{
do_mfhc1 (SD_, RT, FS);
}
@@ -296,7 +312,9 @@
010001,00111,5.RT,5.FS,00000000000:COP1Sa:32,f::MTHC1
"mthc1 r<RT>, f<FS>"
*mips32r2:
+*mips32r6:
*mips64r2:
+*mips64r6:
{
do_mthc1 (SD_, RT, FS);
}
@@ -305,7 +323,9 @@
011111,5.RS,5.RT,5.MSB,5.LSB,000100::32::INS
"ins r<RT>, r<RS>, <LSB>, <MSB-LSB+1>"
*mips32r2:
+*mips32r6:
*mips64r2:
+*mips64r6:
{
do_ins (SD_, RT, RS, LSB, MSB);
}
@@ -314,7 +334,9 @@
011111,00000,5.RT,5.RD,10000,100000::32::SEB
"seb r<RD>, r<RT>"
*mips32r2:
+*mips32r6:
*mips64r2:
+*mips64r6:
{
do_seb (SD_, RD, RT);
}
@@ -322,7 +344,9 @@
011111,00000,5.RT,5.RD,11000,100000::32::SEH
"seh r<RD>, r<RT>"
*mips32r2:
+*mips32r6:
*mips64r2:
+*mips64r6:
{
do_seh (SD_, RD, RT);
}
@@ -331,7 +355,9 @@
000001,5.BASE,11111,16.OFFSET::32::SYNCI
"synci <OFFSET>(r<BASE>)"
*mips32r2:
+*mips32r6:
*mips64r2:
+*mips64r6:
{
// sync i-cache - nothing to do currently
}
@@ -340,7 +366,9 @@
011111,00000,5.RT,5.RD,00000,111011::32::RDHWR
"rdhwr r<RT>, r<RD>"
*mips32r2:
+*mips32r6:
*mips64r2:
+*mips64r6:
{
do_rdhwr (SD_, RT, RD);
}
@@ -349,7 +377,9 @@
011111,00000,5.RT,5.RD,00010,100000::32::WSBH
"wsbh r<RD>, r<RT>"
*mips32r2:
+*mips32r6:
*mips64r2:
+*mips64r6:
{
do_wsbh (SD_, RD, RT);
}
diff --git a/sim/mips/mips3264r6.igen b/sim/mips/mips3264r6.igen
new file mode 100644
index 0000000..b83c309
--- /dev/null
+++ b/sim/mips/mips3264r6.igen
@@ -0,0 +1,1226 @@
+110010,26.OFFSET:POOL32X:32::BC
+"bc <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+ NIA = CIA + (EXTEND26 (OFFSET) << 2) + 4;
+}
+
+111010,26.OFFSET:POOL32X:32::BALC
+"balc <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+ RA = CIA + 4;
+ NIA = CIA + (EXTEND26 (OFFSET) << 2) + 4;
+}
+
+110110,5.RS!0,21.OFFSET:POOL32X:32::BEQZC
+"beqzc r<RS>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+ if (GPR[RS] == 0)
+ NIA = CIA + (EXTEND21 (OFFSET) << 2) + 4;
+ else
+ FORBIDDEN_SLOT ();
+}
+
+110110,00000,5.RT,16.OFFSET:POOL32X:32::JIC
+"jic r<RT>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+ NIA = GPR[RT] + (EXTEND16(OFFSET) << 2);
+}
+
+111110,5.RS!0,21.OFFSET:POOL32X:32::BNEZC
+"bnezc r<RS>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+ if (GPR[RS] != 0)
+ NIA = CIA + (EXTEND21 (OFFSET) << 2) + 4;
+ else
+ FORBIDDEN_SLOT ();
+}
+
+111110,00000,5.RT,16.OFFSET:POOL32X:32::JIALC
+"jialc r<RT>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+ RA = CIA + 4;
+ NIA = GPR[RT] + EXTEND16(OFFSET);
+}
+
+010110,5.RS,5.RT,16.OFFSET:POOL32X:32::B1xxC
+"blezc r<RT>, <OFFSET>": RS==0&&RT!=0
+"bgezc r<RT>, <OFFSET>":RS!=0&&RS==RT
+"bgec r<RS>, r<RT>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+ if (RS == 0 && RT != 0)
+ {
+ //BLEZC
+ if ((signed_word)GPR[RT] <= 0)
+ NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+ else
+ FORBIDDEN_SLOT ();
+ }
+ else if (RS != 0 && RS == RT)
+ {
+ //BGEZC
+ if ((signed_word)GPR[RT] >= 0)
+ NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+ else
+ FORBIDDEN_SLOT ();
+ }
+ else
+ {
+ //BGEC
+ if ((signed_word) GPR[RS] >= (signed_word) GPR[RT])
+ NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+ else
+ FORBIDDEN_SLOT ();
+ }
+}
+
+010111,5.RS,5.RT,16.OFFSET:POOL32X:32::B2xxC
+"bgtzc r<RT>, <OFFSET>":RS==0&&RT!=0
+"bltzc r<RT>, <OFFSET>":RS!=0&&RS==RT
+"bltc r<RS>, r<RT>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+ if (RS == 0 && RT != 0)
+ {
+ //BGTZC
+ if ((signed_word)GPR[RT] > 0)
+ NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+ else
+ FORBIDDEN_SLOT ();
+ }
+ else if (RS != 0 && RS == RT)
+ {
+ //BLTZC
+ if ((signed_word)GPR[RT] < 0)
+ NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+ else
+ FORBIDDEN_SLOT ();
+ }
+ else
+ {
+ //BLTC
+ if ((signed_word) GPR[RS] < (signed_word) GPR[RT])
+ NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+ else
+ FORBIDDEN_SLOT ();
+ }
+}
+
+000110,5.RS,5.RT!0,16.OFFSET:POOL32X:32::B3xxC
+"blezalc r<RT>, <OFFSET>":RS==0
+"bgezalc r<RT>, <OFFSET>":RS!=0&&RS==RT
+"bgeuc r<RS>, r<RT>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+ if (RS == 0 && RT != 0)
+ {
+ //BLEZALC
+ RA = CIA + 4;
+ if ((signed_word)GPR[RT] <= 0)
+ NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+ else
+ FORBIDDEN_SLOT ();
+ }
+ else if (RS != 0 && RS == RT)
+ {
+ //BGEZALC
+ RA = CIA + 4;
+ if ((signed_word)GPR[RT] >= 0)
+ NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+ else
+ FORBIDDEN_SLOT ();
+ }
+ else
+ {
+ //BGEUC
+ if (GPR[RS] >= GPR[RT])
+ NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+ else
+ FORBIDDEN_SLOT ();
+ }
+}
+
+000111,5.RS,5.RT!0,16.OFFSET:POOL32X:32::B4xxC
+"bgtzalc r<RT>, <OFFSET>":RS==0
+"bltzalc r<RT>, <OFFSET>":RS!=0&&RS==RT
+"bltuc r<RS>, r<RT>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+ if (RS == 0 && RT != 0)
+ {
+ //BGTZALC
+ RA = CIA + 4;
+ if ((signed_word)GPR[RT] > 0)
+ NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+ else
+ FORBIDDEN_SLOT ();
+ }
+ else if (RS != 0 && RS == RT)
+ {
+ //BLTZALC
+ RA = CIA + 4;
+ if ((signed_word)GPR[RT] < 0)
+ NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+ else
+ FORBIDDEN_SLOT ();
+ }
+ else
+ {
+ //BLTUC
+ if (GPR[RS] < GPR[RT])
+ NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+ else
+ FORBIDDEN_SLOT ();
+ }
+}
+
+001000,5.RS,5.RT,16.OFFSET:POOL32X:32::BxxxC
+"bovc r<RS>, r<RT>, <OFFSET>":RS>=RT
+"beqzalc r<RT>, <OFFSET>":RS==0&&RT>RS
+"beqc r<RS>, r<RT>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+ if (RS >= RT)
+ {
+ //BOVC
+ ALU32_BEGIN (GPR[RS] & 0x0ffffffff);
+ ALU32_ADD (GPR[RT] & 0x0ffffffff);
+
+ if (ALU32_HAD_OVERFLOW)
+ NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+ else
+ FORBIDDEN_SLOT ();
+ }
+ else if (RS == 0)
+ {
+ RA = CIA + 4;
+ //BEQZALC
+ if (GPR[RT] == 0)
+ NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+ else
+ FORBIDDEN_SLOT ();
+ }
+ else
+ {
+ //BEQC
+ if (GPR[RS] == GPR[RT])
+ NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+ else
+ FORBIDDEN_SLOT ();
+ }
+}
+
+011000,5.RS,5.RT,16.OFFSET:POOL32X:32::BNxxxC
+"bnvc r<RS>, r<RT>, <OFFSET>":RS>=RT
+"bnezalc r<RT>, <OFFSET>":RS==0&&RT>RS
+"bnec r<RS>, r<RT>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+ if (RS >= RT)
+ {
+ //BNVC
+ ALU32_BEGIN (GPR[RS] & 0x0ffffffff);
+ ALU32_ADD (GPR[RT] & 0x0ffffffff);
+
+ if (!ALU32_HAD_OVERFLOW)
+ NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+ else
+ FORBIDDEN_SLOT ();
+ }
+ else if (RS == 0 && RT > RS)
+ {
+ //BNEZALC
+ RA = CIA + 4;
+ if (GPR[RT] != 0)
+ NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+ else
+ FORBIDDEN_SLOT ();
+ }
+ else
+ {
+ //BNEC
+ if (GPR[RT] != GPR[RS])
+ NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+ else
+ FORBIDDEN_SLOT ();
+ }
+}
+
+:%s::::R6COND:int r6cond
+{
+ switch (r6cond)
+ {
+ case FP_R6CMP_SAF:
+ return "SAF";
+ case FP_R6CMP_SUN:
+ return "SUN";
+ case FP_R6CMP_SOR:
+ return "SOR";
+ case FP_R6CMP_SEQ:
+ return "SEQ";
+ case FP_R6CMP_SUNE:
+ return "SUNE";
+ case FP_R6CMP_SUEQ:
+ return "SUEQ";
+ case FP_R6CMP_SNE:
+ return "SNE";
+ case FP_R6CMP_SLT:
+ return "SLT";
+ case FP_R6CMP_SULT:
+ return "SULT";
+ case FP_R6CMP_SLE:
+ return "SLE";
+ case FP_R6CMP_SULE:
+ return "SULE";
+ case FP_R6CMP_AF:
+ return "AF";
+ case FP_R6CMP_UN:
+ return "UN";
+ case FP_R6CMP_OR:
+ return "OR";
+ case FP_R6CMP_EQ:
+ return "EQ";
+ case FP_R6CMP_UNE:
+ return "UNE";
+ case FP_R6CMP_UEQ:
+ return "UEQ";
+ case FP_R6CMP_NE:
+ return "NE";
+ case FP_R6CMP_LT:
+ return "LT";
+ case FP_R6CMP_ULT:
+ return "ULT";
+ case FP_R6CMP_LE:
+ return "LE";
+ case FP_R6CMP_ULE:
+ return "ULE";
+ default:
+ abort ();
+ }
+}
+
+010001,1010,1.FMT,5.FT,5.FS,5.FD,0,5.R6COND:POOL32X:32,f::CMP.cond.fmt
+"cmp.%s<R6COND>.%s<FMT> f<FD>, f<FS>, f<FT>"
+*mips32r6:
+*mips64r6:
+{
+ uint64_t result;
+ check_fpu (SD_);
+ TRACE_ALU_INPUT2 (ValueFPR (FS, FMT), ValueFPR (FT, FMT));
+
+ result = R6Compare (ValueFPR (FS, FMT), ValueFPR (FT, FMT), FMT, R6COND);
+ StoreFPR (FD, FMT, result);
+ TRACE_ALU_RESULT (result);
+}
+
+010001,01001,5.FT,16.OFFSET:POOL32X:32,f::BC1EQZ
+"bc1eqz f<FT>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+ address_word offset = EXTEND16 (OFFSET) << 2;
+ check_fpu (SD_);
+ TRACE_ALU_INPUT1 (FGR[FT]);
+ if ((FGR[FT] & 0x01) == 0)
+ DELAY_SLOT (NIA + offset);
+}
+
+010001,01101,5.FT,16.OFFSET:POOL32X:32,f::BC1NEZ
+"bc1nez f<FT>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+ address_word offset = EXTEND16 (OFFSET) << 2;
+ check_fpu (SD_);
+ TRACE_ALU_INPUT1 (FGR[FT]);
+ if ((FGR[FT] & 0x01) != 0)
+ DELAY_SLOT (NIA + offset);
+}
+010001,1000,1.FMT,5.FT,5.FS,5.FD,011000:POOLX:32,f::MADDF.fmt
+"maddf.%s<FMT> f<FD>, f<FS>, f<FT>"
+*mips32r6:
+*mips64r6:
+{
+ int fmt = FMT;
+ 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]);
+}
+
+010001,1000,1.FMT,5.FT,5.FS,5.FD,011001:POOLX:32,f::MSUBF.fmt
+"msubf.%s<FMT> f<FD>, f<FS>, f<FT>"
+*mips32r6:
+*mips64r6:
+{
+ int fmt = FMT;
+ 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]);
+}
+
+000000,5.RS,5.RT,5.RD,000,2.IMM,000101:SPECIAL:32::LSA
+"lsa r<RD>, r<RS>, r<RT>, <IMM + 1>"
+*mips32r6:
+*mips64r6:
+{
+ uint32_t t = GPR[RS] << (IMM + 1);
+ GPR[RD] = EXTEND32(GPR[RT] + t);
+ TRACE_ALU_RESULT (GPR[RD]);
+}
+
+000000,5.RS,5.RT,5.RD,000,2.IMM,010101:SPECIAL:64::DLSA
+"dlsa r<RD>, r<RS>, r<RT>, <IMM + 1>"
+*mips64r6:
+{
+ uint64_t t = GPR[RS] << (IMM + 1);
+ GPR[RD] = GPR[RT] + t;
+ TRACE_ALU_RESULT (GPR[RD]);
+}
+
+001111,5.RS!0,5.RT,16.IMMEDIATE:POOL32X:32::AUI
+"aui r<RS>, r<RT>, <IMMEDIATE>"
+*mips32r6:
+*mips64r6:
+{
+ TRACE_ALU_INPUT2 (GPR[RS], IMMEDIATE);
+ GPR[RT] = EXTEND32 (GPR[RS] + (EXTEND16 (IMMEDIATE) << 16));
+ TRACE_ALU_RESULT (GPR[RT]);
+}
+
+011101,5.RS!0,5.RT,16.IMMEDIATE:POOL32X:64::DAUI
+"daui r<RS>, r<RT>, <IMMEDIATE>"
+*mips64r6:
+{
+ TRACE_ALU_INPUT2 (GPR[RS], IMMEDIATE);
+ GPR[RT] = GPR[RS] + (EXTEND16 (IMMEDIATE) << 16);
+ TRACE_ALU_RESULT (GPR[RT]);
+}
+
+000001,5.RS,00110,16.IMMEDIATE:POOL32X:64::DAHI
+"dahi r<RS>, <IMMEDIATE>"
+*mips64r6:
+{
+ TRACE_ALU_INPUT2 (GPR[RS], IMMEDIATE);
+ GPR[RS] = GPR[RS] + (EXTEND16 (IMMEDIATE) << 32);
+ TRACE_ALU_RESULT (GPR[RS]);
+}
+
+000001,5.RS,11110,16.IMMEDIATE:POOL32X:64::DATI
+"dati r<RS>, <IMMEDIATE>"
+*mips64r6:
+{
+ TRACE_ALU_INPUT2 (GPR[RS], IMMEDIATE);
+ GPR[RS] = GPR[RS] + (EXTEND16 (IMMEDIATE) << 48);
+ TRACE_ALU_RESULT (GPR[RS]);
+}
+
+011111,5.RS,5.RT,5.RD,010,2.IMMEDIATE,100000:POOL32X:32::ALIGN
+"align r<RD>, r<RS>, r<RT>, <IMMEDIATE>"
+*mips32r6:
+*mips64r6:
+{
+ uint32_t rs = GPR[RS];
+ uint32_t rt = GPR[RT];
+ TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
+ GPR[RD] = EXTEND32 (rs >> 8 * (4 - IMMEDIATE) | rt << 8 * IMMEDIATE);
+ TRACE_ALU_RESULT (GPR[RD]);
+}
+
+011111,5.RS,5.RT,5.RD,01,3.IMMEDIATE,100100:POOL32X:64::DALIGN
+"dalign r<RD>, r<RS>, r<RT>, <IMMEDIATE>"
+*mips64r6:
+{
+ uint64_t rs = GPR[RS];
+ uint64_t rt = GPR[RT];
+ TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
+ GPR[RD] = rs >> 8 * (8 - IMMEDIATE) | rt << 8 * IMMEDIATE;
+ TRACE_ALU_RESULT (GPR[RD]);
+}
+
+011111,00000,5.RT,5.RD,00000,100000:POOL32X:32::BITSWAP
+"bitswap r<RD>, r<RT>"
+*mips32r6:
+*mips64r6:
+{
+ /* Taken from: http://graphics.stanford.edu/~seander/bithacks.html */
+ uint32_t v = GPR[RT];
+
+ TRACE_ALU_INPUT1 (v);
+ v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1);
+ v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2);
+ v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);
+ GPR[RD] = EXTEND32 (v);
+ TRACE_ALU_RESULT(GPR[RD]);
+}
+
+011111,00000,5.RT,5.RD,00000,100100:POOL32X:64::DBITSWAP
+"dbitswap r<RD>, r<RT>"
+*mips64r6:
+{
+ /* Taken from: http://graphics.stanford.edu/~seander/bithacks.html */
+ uint64_t v = GPR[RT];
+
+ TRACE_ALU_INPUT1 (v);
+ v = ((v >> 1) & 0x5555555555555555) | ((v & 0x5555555555555555) << 1);
+ v = ((v >> 2) & 0x3333333333333333) | ((v & 0x3333333333333333) << 2);
+ v = ((v >> 4) & 0x0F0F0F0F0F0F0F0F) | ((v & 0x0F0F0F0F0F0F0F0F) << 4);
+ TRACE_ALU_RESULT(v);
+ GPR[RD] = v;
+}
+
+111011,5.RS,00,19.IMMEDIATE:POOL32X:32::ADDIUPC
+"addiupc r<RS>, <IMMEDIATE>"
+*mips32r6:
+*mips64r6:
+{
+ TRACE_ALU_INPUT1 (IMMEDIATE);
+ GPR[RS] = loadstore_ea (SD_, CIA, EXTEND19 (IMMEDIATE) << 2);
+ TRACE_ALU_RESULT (GPR[RS]);
+}
+
+111011,5.RS,11110,16.IMMEDIATE:POOL32X:32::AUIPC
+"auipc r<RS>, <IMMEDIATE>"
+*mips32r6:
+*mips64r6:
+{
+ TRACE_ALU_INPUT1 (IMMEDIATE);
+ GPR[RS] = loadstore_ea (SD_, CIA, EXTEND32 (IMMEDIATE << 16));
+ TRACE_ALU_RESULT (GPR[RS]);
+}
+
+111011,5.RS,11111,16.IMMEDIATE:POOL32X:32::ALUIPC
+"aluipc r<RS>, <IMMEDIATE>"
+*mips32r6:
+*mips64r6:
+{
+ TRACE_ALU_INPUT1 (IMMEDIATE);
+ GPR[RS] = ~0x0FFFF & loadstore_ea (SD_, CIA, EXTEND32 (IMMEDIATE << 16));
+ TRACE_ALU_RESULT (GPR[RS]);
+}
+
+111011,5.RS,01,19.IMMEDIATE:POOL32X:32::LWPC
+"lwpc r<RS>, <IMMEDIATE>"
+*mips32r6:
+*mips64r6:
+{
+ uint32_t offset = EXTEND19 (IMMEDIATE) << 2;
+ TRACE_ALU_INPUT1 (IMMEDIATE);
+ GPR[RS] = EXTEND32 (do_load (SD_, AccessLength_WORD, CIA, offset));
+ TRACE_ALU_RESULT (GPR[RS]);
+}
+
+111011,5.RS,10,19.IMMEDIATE:POOL32X:64::LWUPC
+"lwupc r<RS>, <IMMEDIATE>"
+*mips64r6:
+{
+ uint32_t offset = EXTEND19 (IMMEDIATE) << 2;
+ TRACE_ALU_INPUT1 (CIA + offset);
+ GPR[RS] = do_load (SD_, AccessLength_WORD, CIA, offset);
+ TRACE_ALU_RESULT (GPR[RS]);
+}
+
+111011,5.RS,110,18.IMMEDIATE:POOL32X:64::LDPC
+"ldpc r<RS>, <IMMEDIATE>"
+*mips64r6:
+{
+ uint32_t offset = EXTEND18 (IMMEDIATE) << 3;
+ TRACE_ALU_INPUT1 (IMMEDIATE);
+ GPR[RS] = do_load (SD_, AccessLength_DOUBLEWORD, CIA, offset);
+ TRACE_ALU_RESULT (GPR[RS]);
+}
+010001,1000,1.FMT,00000,5.FS,5.FD,011010::32,64,f::RINT.fmt
+"rint.%s<FMT> f<FD>, f<FS>"
+*mips32r6:
+*mips64r6:
+{
+ uint64_t result;
+ int fmt = FMT;
+ 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]);
+}
+
+010001,1000,1.FMT,00000,5.FS,5.FD,011011::32,64,f::CLASS.fmt
+"class.%s<FMT> f<FD>, f<FS>"
+*mips32r6:
+*mips64r6:
+{
+ int fmt = FMT;
+ check_fpu (SD_);
+ check_u64 (SD_, instruction_0);
+ check_fmt_p (SD_, fmt, instruction_0);
+ StoreFPR (FD, fmt, Classify (ValueFPR (FS, fmt), fmt));
+}
+
+010001,1000,1.FMT,5.FT,5.FS,5.FD,011100::32,64,f::MIN.fmt
+"min.%s<FMT> f<FD>, f<FS>, f<FT>"
+*mips32r6:
+*mips64r6:
+{
+ int fmt = FMT;
+ 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]);
+}
+
+010001,1000,1.FMT,5.FT,5.FS,5.FD,011110::32,64,f::MAX.fmt
+"max.%s<FMT> f<FD>, f<FS>, f<FT>"
+*mips32r6:
+*mips64r6:
+{
+ int fmt = FMT;
+ 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]);
+}
+
+010001,1000,1.FMT,5.FT,5.FS,5.FD,011101::32,64,f::MINA.fmt
+"mina.%s<FMT> f<FD>, f<FS>, f<FT>"
+*mips32r6:
+*mips64r6:
+{
+ int fmt = FMT;
+ 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]);
+}
+
+010001,1000,1.FMT,5.FT,5.FS,5.FD,011111::32,64,f::MAXA.fmt
+"maxa.%s<FMT> f<FD>, f<FS>, f<FT>"
+*mips32r6:
+*mips64r6:
+{
+ int fmt = FMT;
+ 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]);
+}
+000000,5.RS,5.RT,5.RD,00010,011000:POOL32X:32::MUL
+"mul r<RD>, r<RS>, r<RT>"
+*mips32r6:
+*mips64r6:
+{
+ 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 (VL4_8 (prod));
+ TRACE_ALU_RESULT (GPR[RD]);
+}
+
+000000,5.RS,5.RT,5.RD,00011,011000:POOL32X:32::MUH
+"muh r<RD>, r<RS>, r<RT>"
+*mips32r6:
+*mips64r6:
+{
+ 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]);
+}
+
+000000,5.RS,5.RT,5.RD,00010,011001:POOL32X:32::MULU
+"mulu r<RD>, r<RS>, r<RT>"
+*mips32r6:
+*mips64r6:
+{
+ 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]);
+}
+
+000000,5.RS,5.RT,5.RD,00011,011001:POOL32X:32::MUHU
+"muhu r<RD>, r<RS>, r<RT>"
+*mips32r6:
+*mips64r6:
+{
+ 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]);
+}
+
+000000,5.RS,5.RT,5.RD,00010,011010:POOL32X:32::DIV
+"div r<RD>, r<RS>, r<RT>"
+*mips32r6:
+*mips64r6:
+{
+ 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]);
+}
+
+000000,5.RS,5.RT,5.RD,00011,011010:POOL32X:32::MOD
+"mod r<RD>, r<RS>, r<RT>"
+*mips32r6:
+*mips64r6:
+{
+ 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]);
+}
+
+000000,5.RS,5.RT,5.RD,00010,011011:POOL32X:32::DIVU
+"divu r<RD>, r<RS>, r<RT>"
+*mips32r6:
+*mips64r6:
+{
+ 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]);
+}
+
+000000,5.RS,5.RT,5.RD,00011,011011:POOL32X:32::MODU
+"modu r<RD>, r<RS>, r<RT>"
+*mips32r6:
+*mips64r6:
+{
+ 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]);
+}
+
+000000,5.RS,5.RT,5.RD,00010,011100:POOL32X:64::DMUL
+"dmul r<RD>, r<RS>, r<RT>"
+*mips64r6:
+{
+ uint64_t lo;
+ uint64_t m00;
+ uint64_t m01;
+ uint64_t m10;
+ uint64_t mid;
+ int sign;
+ uint64_t op1 = GPR[RS];
+ uint64_t op2 = GPR[RT];
+
+ check_u64 (SD_, instruction_0);
+ TRACE_ALU_INPUT2 (op1, op2);
+ /* make signed multiply unsigned */
+ sign = 0;
+ if ((int64_t) op1 < 0)
+ {
+ op1 = - op1;
+ ++sign;
+ }
+ if ((int64_t) op2 < 0)
+ {
+ op2 = - op2;
+ ++sign;
+ }
+ /* multiply out the sub products */
+ m00 = ((uint64_t) VL4_8 (op1) * (uint64_t) VL4_8 (op2));
+ m10 = ((uint64_t) VH4_8 (op1) * (uint64_t) VL4_8 (op2));
+ m01 = ((uint64_t) VL4_8 (op1) * (uint64_t) VH4_8 (op2));
+ /* add the products */
+ mid = ((uint64_t) VH4_8 (m00)
+ + (uint64_t) VL4_8 (m10)
+ + (uint64_t) VL4_8 (m01));
+ lo = U8_4 (mid, m00);
+ /* fix the sign */
+ if (sign & 1)
+ lo = -lo;
+
+ GPR[RD] = lo;
+ TRACE_ALU_RESULT (GPR[RD]);
+}
+
+000000,5.RS,5.RT,5.RD,00011,011100:POOL32X:64::DMUH
+"dmuh r<RD>, r<RS>, r<RT>"
+*mips64r6:
+{
+ uint64_t lo;
+ uint64_t hi;
+ uint64_t m00;
+ uint64_t m01;
+ uint64_t m10;
+ uint64_t m11;
+ uint64_t mid;
+ int sign;
+ uint64_t op1 = GPR[RS];
+ uint64_t op2 = GPR[RT];
+
+ check_u64 (SD_, instruction_0);
+ TRACE_ALU_INPUT2 (op1, op2);
+ /* make signed multiply unsigned */
+ sign = 0;
+ if ((int64_t) op1 < 0)
+ {
+ op1 = - op1;
+ ++sign;
+ }
+ if ((int64_t) op2 < 0)
+ {
+ op2 = - op2;
+ ++sign;
+ }
+ /* multiply out the 4 sub products */
+ m00 = ((uint64_t) VL4_8 (op1) * (uint64_t) VL4_8 (op2));
+ m10 = ((uint64_t) VH4_8 (op1) * (uint64_t) VL4_8 (op2));
+ m01 = ((uint64_t) VL4_8 (op1) * (uint64_t) VH4_8 (op2));
+ m11 = ((uint64_t) VH4_8 (op1) * (uint64_t) VH4_8 (op2));
+ /* add the products */
+ mid = ((uint64_t) VH4_8 (m00)
+ + (uint64_t) VL4_8 (m10)
+ + (uint64_t) VL4_8 (m01));
+ lo = U8_4 (mid, m00);
+ hi = (m11
+ + (uint64_t) VH4_8 (mid)
+ + (uint64_t) VH4_8 (m01)
+ + (uint64_t) VH4_8 (m10));
+ /* fix the sign */
+ if (sign & 1)
+ {
+ lo = -lo;
+ if (lo == 0)
+ hi = -hi;
+ else
+ hi = -hi - 1;
+ }
+
+ GPR[RD] = hi;
+ TRACE_ALU_RESULT (GPR[RD]);
+}
+
+000000,5.RS,5.RT,5.RD,00010,011101:POOL32X:64::DMULU
+"dmulu r<RD>, r<RS>, r<RT>"
+*mips64r6:
+{
+ uint64_t lo;
+ uint64_t m00;
+ uint64_t m01;
+ uint64_t m10;
+ uint64_t mid;
+ uint64_t op1 = GPR[RS];
+ uint64_t op2 = GPR[RT];
+
+ check_u64 (SD_, instruction_0);
+ TRACE_ALU_INPUT2 (op1, op2);
+ /* multiply out the sub products */
+ m00 = ((uint64_t) VL4_8 (op1) * (uint64_t) VL4_8 (op2));
+ m10 = ((uint64_t) VH4_8 (op1) * (uint64_t) VL4_8 (op2));
+ m01 = ((uint64_t) VL4_8 (op1) * (uint64_t) VH4_8 (op2));
+ /* add the products */
+ mid = ((uint64_t) VH4_8 (m00)
+ + (uint64_t) VL4_8 (m10)
+ + (uint64_t) VL4_8 (m01));
+ lo = U8_4 (mid, m00);
+
+ GPR[RD] = lo;
+ TRACE_ALU_RESULT (GPR[RD]);
+}
+
+000000,5.RS,5.RT,5.RD,00011,011101:POOL32X:64::DMUHU
+"dmuhu r<RD>, r<RS>, r<RT>"
+*mips64r6:
+{
+ uint64_t lo;
+ uint64_t hi;
+ uint64_t m00;
+ uint64_t m01;
+ uint64_t m10;
+ uint64_t m11;
+ uint64_t mid;
+ uint64_t op1 = GPR[RS];
+ uint64_t op2 = GPR[RT];
+
+ check_u64 (SD_, instruction_0);
+ TRACE_ALU_INPUT2 (op1, op2);
+ /* multiply out the 4 sub products */
+ m00 = ((uint64_t) VL4_8 (op1) * (uint64_t) VL4_8 (op2));
+ m10 = ((uint64_t) VH4_8 (op1) * (uint64_t) VL4_8 (op2));
+ m01 = ((uint64_t) VL4_8 (op1) * (uint64_t) VH4_8 (op2));
+ m11 = ((uint64_t) VH4_8 (op1) * (uint64_t) VH4_8 (op2));
+ /* add the products */
+ mid = ((uint64_t) VH4_8 (m00)
+ + (uint64_t) VL4_8 (m10)
+ + (uint64_t) VL4_8 (m01));
+ lo = U8_4 (mid, m00);
+ hi = (m11
+ + (uint64_t) VH4_8 (mid)
+ + (uint64_t) VH4_8 (m01)
+ + (uint64_t) VH4_8 (m10));
+
+ GPR[RD] = hi;
+ TRACE_ALU_RESULT (GPR[RD]);
+}
+
+000000,5.RS,5.RT,5.RD,00010,011110:POOL32X:64::DDIV
+"ddiv r<RD>, r<RS>, r<RT>"
+*mips64r6:
+{
+ int64_t n = GPR[RS];
+ int64_t d = GPR[RT];
+
+ check_u64 (SD_, instruction_0);
+ TRACE_ALU_INPUT2 (n, d);
+ if (d == 0)
+ GPR[RD] = SIGNED64 (0x8000000000000000);
+ else if (d == -1 && n == SIGNED64 (0x8000000000000000))
+ GPR[RD] = SIGNED64 (0x8000000000000000);
+ else
+ GPR[RD] = (n / d);
+
+ TRACE_ALU_RESULT (GPR[RD]);
+}
+
+000000,5.RS,5.RT,5.RD,00011,011110:POOL32X:64::DMOD
+"dmod r<RD>, r<RS>, r<RT>"
+*mips64r6:
+{
+ int64_t n = GPR[RS];
+ int64_t d = GPR[RT];
+
+ check_u64 (SD_, instruction_0);
+ TRACE_ALU_INPUT2 (n, d);
+ if (d == 0 || (d == -1 && n == SIGNED64 (0x8000000000000000)))
+ GPR[RD] = SIGNED64 (0);
+ else
+ GPR[RD] = (n % d);
+
+ TRACE_ALU_RESULT (GPR[RD]);
+}
+
+000000,5.RS,5.RT,5.RD,00010,011111:POOL32X:64::DDIVU
+"ddivu r<RD>, r<RS>, r<RT>"
+*mips64r6:
+{
+ uint64_t n = GPR[RS];
+ uint64_t d = GPR[RT];
+
+ check_u64 (SD_, instruction_0);
+ TRACE_ALU_INPUT2 (n, d);
+ if (d == 0)
+ GPR[RD] = UNSIGNED64 (0x8000000000000000);
+ else
+ GPR[RD] = (n / d);
+
+ TRACE_ALU_RESULT (GPR[RD]);
+}
+
+000000,5.RS,5.RT,5.RD,00011,011111:POOL32X:64::DMODU
+"dmodu r<RD>, r<RS>, r<RT>"
+*mips64r6:
+{
+ uint64_t n = GPR[RS];
+ uint64_t d = GPR[RT];
+
+ check_u64 (SD_, instruction_0);
+ TRACE_ALU_INPUT2 (n, d);
+ if (d == 0)
+ GPR[RD] = UNSIGNED64 (0);
+ else
+ GPR[RD] = (n % d);
+
+ TRACE_ALU_RESULT (GPR[RD]);
+}
+
+011111,5.BASE,5.RT,9.OFFSET,0,110110:SPECIAL3:32::LL
+"ll r<RT>, <OFFSET>(r<BASE>)"
+*mips32r6:
+*mips64r6:
+{
+ do_ll (SD_, RT, EXTEND9 (OFFSET), BASE);
+}
+
+011111,5.BASE,5.RT,5.RD,0000,1,110110:SPECIAL3:32::LLWP
+"llwp r<RT>, r<RD>, (r<BASE>)"
+*mips32r6:
+*mips64r6:
+{
+ int first, second;
+ int offset;
+
+ if (RT == BASE)
+ {
+ first = RD;
+ second = RT;
+ offset = BigEndianCPU ? 0 : 4;
+ }
+ else
+ {
+ first = RT;
+ second = RD;
+ offset = BigEndianCPU ? 4 : 0;
+ }
+
+ do_ll (SD_, first, offset, BASE);
+ do_ll (SD_, second, offset ^ 4, BASE);
+}
+
+
+011111,5.BASE,5.RT,9.OFFSET,0,100110:SPECIAL3:32::SC
+"sc r<RT>, <OFFSET>(r<BASE>)"
+*mips32r6:
+*mips64r6:
+{
+ do_sc (SD_, RT, EXTEND9 (OFFSET), BASE, instruction_0, 1);
+}
+
+011111,5.BASE,5.RT,9.OFFSET,0,110111:SPECIAL3:64::LLD
+"lld r<RT>, <OFFSET>(r<BASE>)"
+*mips64r6:
+{
+ check_u64 (SD_, instruction_0);
+ do_lld (SD_, RT, EXTEND9 (OFFSET), BASE);
+}
+
+
+011111,5.BASE,5.RT,5.RD,0000,1,100110:SPECIAL3:32::SCWP
+"scwp r<RT>, r<RD>, (r<BASE>)"
+*mips32r6:
+*mips64r6:
+{
+ int offset = BigEndianCPU ? 0 : 4;
+
+ do_sc (SD_, RD, offset, BASE, instruction_0, 0);
+ do_sc (SD_, RT, offset ^ 4, BASE, instruction_0, 1);
+}
+
+011111,5.BASE,5.RT,5.RD,0000,1,110111:SPECIAL3:64::LLDP
+"lldp r<RT>, r<RD>, (r<BASE>)"
+*mips64r6:
+{
+ int first, second;
+ int offset;
+
+ check_u64 (SD_, instruction_0);
+
+ if (RT == BASE)
+ {
+ first = RD;
+ second = RT;
+ offset = BigEndianCPU ? 0 : 8;
+ }
+ else
+ {
+ first = RT;
+ second = RD;
+ offset = BigEndianCPU ? 8 : 0;
+ }
+
+ do_lld (SD_, first, offset, BASE);
+ do_lld (SD_, second, offset ^ 8, BASE);
+}
+
+011111,5.BASE,5.RT,9.OFFSET,0,100111:SPECIAL3:64::SCD
+"scd r<RT>, <OFFSET>(r<BASE>)"
+*mips64r6:
+{
+ check_u64 (SD_, instruction_0);
+ do_scd (SD_, RT, EXTEND9 (OFFSET), BASE, 1);
+}
+
+011111,5.BASE,5.RT,5.RD,0000,1,100111:SPECIAL3:64::SCDP
+"scdp r<RT>, r<RD>, (r<BASE>)"
+*mips64r6:
+{
+ int offset = BigEndianCPU ? 0 : 8;
+ check_u64 (SD_, instruction_0);
+
+ do_scd (SD_, RD, offset, BASE, 0);
+ do_scd (SD_, RT, offset ^ 8, BASE, 1);
+}
+
+011111,5.BASE,5.HINT,9.OFFSET,0,110101:SPECIAL3:32::PREF
+"pref <HINT>, <OFFSET>(r<BASE>)"
+*mips32r6:
+*mips64r6:
+{
+ do_pref (SD_, HINT, EXTEND9 (OFFSET), BASE);
+}
+
+011111,5.BASE,5.HINT,9.OFFSET,0,100101:SPECIAL3:32::CACHE
+"cache <HINT>, <OFFSET>(r<BASE>)"
+*mips32r6:
+*mips64r6:
+{
+ do_cache (SD_, HINT, BASE, EXTEND9 (OFFSET), instruction_0);
+}
+
+
+000000,5.RS,00000,5.RD,00001,010000:POOL32X:32::CLZ
+"clz r<RD>, r<RS>"
+*mips32r6:
+*mips64r6:
+{
+ do_clz (SD_, RD, RS);
+}
+
+000000,5.RS,00000,5.RD,00001,010001:POOL32X:32::CLO
+"clo r<RD>, r<RS>"
+*mips32r6:
+*mips64r6:
+{
+ do_clo (SD_, RD, RS);
+}
+
+000000,5.RS,00000,5.RD,00001,010010:POOL32X:64::DCLZ
+"dclz r<RD>, r<RS>"
+*mips64r6:
+{
+ check_u64 (SD_, instruction_0);
+ do_dclz (SD_, RD, RS);
+}
+
+000000,5.RS,00000,5.RD,00001,010011:POOL32X:64::DCLO
+"dclo r<RD>, r<RS>"
+*mips64r6:
+{
+ check_u64 (SD_, instruction_0);
+ do_dclo (SD_, RD, RS);
+}
+010001,1000,1.FMT,5.FT,5.FS,5.FD,010000:POOL32X:32,f::SEL.fmt
+"sel.%s<FMT> f<FD>, f<FS>, f<FT>"
+*mips32r6:
+*mips64r6:
+{
+ 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));
+}
+
+010001,1000,1.FMT,5.FT,5.FS,5.FD,010100:POOL32X:32,f::SELEQZ.fmt
+"seleqz.%s<FMT> f<FD>, f<FS>, f<FT>"
+*mips32r6:
+*mips64r6:
+{
+ 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));
+}
+
+010001,1000,1.FMT,5.FT,5.FS,5.FD,010111:POOL32X:32,f::SELNEZ.fmt
+"selnez.%s<FMT> f<FD>, f<FS>, f<FT>"
+*mips32r6:
+*mips64r6:
+{
+ 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, 0);
+ else
+ StoreFPR (FD, FMT, ValueFPR (FS, FMT));
+ TRACE_ALU_RESULT (ValueFPR(FD, FMT));
+}
+
+000000,5.RS,5.RT,5.RD,00000,110101:POOL32X:32::SELEQZ
+"seleqz r<RD>, r<RS>, r<RT>"
+*mips32r6:
+*mips64r6:
+{
+ TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
+ if (GPR[RT] != 0)
+ GPR[RD] = 0;
+ else
+ GPR[RD] = GPR[RS];
+ TRACE_ALU_RESULT (GPR[RD]);
+}
+
+000000,5.RS,5.RT,5.RD,00000,110111:POOL32X:32::SELNEZ
+"selnez r<RD>, r<RS>, r<RT>"
+*mips32r6:
+*mips64r6:
+{
+ TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
+ if (GPR[RT] != 0)
+ GPR[RD] = GPR[RS];
+ else
+ GPR[RD] = 0;
+ TRACE_ALU_RESULT (GPR[RD]);
+}
diff --git a/sim/mips/sim-main.h b/sim/mips/sim-main.h
index 8e3e85f..418c659 100644
--- a/sim/mips/sim-main.h
+++ b/sim/mips/sim-main.h
@@ -26,6 +26,8 @@ mips_core_signal ((SD), (CPU), (CIA), (MAP), (NR_BYTES), (ADDR), (TRANSFER), (ER
#include "sim-basics.h"
#include "sim-base.h"
#include "bfd.h"
+#include "elf-bfd.h"
+#include "elf/mips.h"
/* Deprecated macros and types for manipulating 64bit values. Use
../common/sim-bits.h and ../common/sim-endian.h macros instead. */
@@ -72,6 +74,9 @@ typedef enum {
fmt_word = 4,
fmt_long = 5,
fmt_ps = 6,
+ /* The following is a special case for FP conditions where only
+ the lower 32bits are considered. This is a HACK. */
+ fmt_dc32 = 7,
/* The following are well outside the normal acceptable format
range, and are used in the register status vector. */
fmt_unknown = 0x10000000,
@@ -261,6 +266,7 @@ struct _sim_cpu {
#define DSPC ((CPU)->dspc)
#define DELAY_SLOT(TARGET) NIA = delayslot32 (SD_, (TARGET))
+#define FORBIDDEN_SLOT() { NIA = forbiddenslot32 (SD_); }
#define NULLIFY_NEXT_INSTRUCTION() NIA = nullify_next_insn32 (SD_)
@@ -271,15 +277,16 @@ struct _sim_cpu {
#define DSSTATE ((CPU)->dsstate)
/* Flags in the "state" variable: */
-#define simHALTEX (1 << 2) /* 0 = run; 1 = halt on exception */
-#define simHALTIN (1 << 3) /* 0 = run; 1 = halt on interrupt */
-#define simTRACE (1 << 8) /* 0 = do nothing; 1 = trace address activity */
-#define simPCOC0 (1 << 17) /* COC[1] from current */
-#define simPCOC1 (1 << 18) /* COC[1] from previous */
-#define simDELAYSLOT (1 << 24) /* 0 = do nothing; 1 = delay slot entry exists */
-#define simSKIPNEXT (1 << 25) /* 0 = do nothing; 1 = skip instruction */
-#define simSIGINT (1 << 28) /* 0 = do nothing; 1 = SIGINT has occured */
-#define simJALDELAYSLOT (1 << 29) /* 1 = in jal delay slot */
+#define simHALTEX (1 << 2) /* 0 = run; 1 = halt on exception */
+#define simHALTIN (1 << 3) /* 0 = run; 1 = halt on interrupt */
+#define simTRACE (1 << 8) /* 1 = trace address activity */
+#define simPCOC0 (1 << 17) /* COC[1] from current */
+#define simPCOC1 (1 << 18) /* COC[1] from previous */
+#define simDELAYSLOT (1 << 24) /* 1 = delay slot entry exists */
+#define simSKIPNEXT (1 << 25) /* 0 = do nothing; 1 = skip instruction */
+#define simSIGINT (1 << 28) /* 0 = do nothing; 1 = SIGINT has occured */
+#define simJALDELAYSLOT (1 << 29) /* 1 = in jal delay slot */
+#define simFORBIDDENSLOT (1 << 30) /* 1 = n forbidden slot */
#ifndef ENGINE_ISSUE_PREFIX_HOOK
#define ENGINE_ISSUE_PREFIX_HOOK() \
@@ -532,6 +539,10 @@ struct mips_sim_state {
/* Bits reserved for implementations: */
#define status_SBX (1 << 16) /* Enable SiByte SB-1 extensions. */
+/* From R6 onwards, some instructions (e.g. ADDIUPC) change behaviour based
+ * on the Status.UX bits to either sign extend, or act as full 64 bit. */
+#define status_optional_EXTEND32(x) ((SR & status_UX) ? x : EXTEND32(x))
+
#define cause_BD ((unsigned)1 << 31) /* L1 Exception in branch delay slot */
#define cause_BD2 (1 << 30) /* L2 Exception in branch delay slot */
#define cause_CE_mask 0x30000000 /* Coprocessor exception */
@@ -719,8 +730,55 @@ void test_fcsr (SIM_STATE);
/* FPU operations. */
-void fp_cmp (SIM_STATE, uint64_t op1, uint64_t op2, FP_formats fmt, int abs, int cond, int cc);
-#define Compare(op1,op2,fmt,cond,cc) fp_cmp(SIM_ARGS, op1, op2, fmt, 0, cond, cc)
+/* 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)
+
+void fp_cmp (SIM_STATE, uint64_t op1, uint64_t op2, FP_formats fmt,
+ int abs, int cond, int cc);
+#define Compare(op1,op2,fmt,cond,cc) \
+ fp_cmp(SIM_ARGS, op1, op2, fmt, 0, cond, cc)
+uint64_t fp_r6_cmp (SIM_STATE, uint64_t op1, uint64_t op2,
+ FP_formats fmt, int cond);
+#define R6Compare(op1,op2,fmt,cond) fp_r6_cmp(SIM_ARGS, op1, op2, fmt, cond)
+uint64_t fp_classify(SIM_STATE, uint64_t op, FP_formats fmt);
+#define Classify(op, fmt) fp_classify(SIM_ARGS, op, fmt)
+int fp_rint(SIM_STATE, uint64_t op, uint64_t *ans, FP_formats fmt);
+#define RoundToIntegralExact(op, ans, fmt) fp_rint(SIM_ARGS, op, ans, fmt)
uint64_t fp_abs (SIM_STATE, uint64_t op, FP_formats fmt);
#define AbsoluteValue(op,fmt) fp_abs(SIM_ARGS, op, fmt)
uint64_t fp_neg (SIM_STATE, uint64_t op, FP_formats fmt);
@@ -733,6 +791,14 @@ uint64_t fp_mul (SIM_STATE, uint64_t op1, uint64_t op2, FP_formats fmt);
#define Multiply(op1,op2,fmt) fp_mul(SIM_ARGS, op1, op2, fmt)
uint64_t fp_div (SIM_STATE, uint64_t op1, uint64_t op2, FP_formats fmt);
#define Divide(op1,op2,fmt) fp_div(SIM_ARGS, op1, op2, fmt)
+uint64_t fp_min (SIM_STATE, uint64_t op1, uint64_t op2, FP_formats fmt);
+#define Min(op1,op2,fmt) fp_min(SIM_ARGS, op1, op2, fmt)
+uint64_t fp_max (SIM_STATE, uint64_t op1, uint64_t op2, FP_formats fmt);
+#define Max(op1,op2,fmt) fp_max(SIM_ARGS, op1, op2, fmt)
+uint64_t fp_mina (SIM_STATE, uint64_t op1, uint64_t op2, FP_formats fmt);
+#define MinA(op1,op2,fmt) fp_mina(SIM_ARGS, op1, op2, fmt)
+uint64_t fp_maxa (SIM_STATE, uint64_t op1, uint64_t op2, FP_formats fmt);
+#define MaxA(op1,op2,fmt) fp_maxa(SIM_ARGS, op1, op2, fmt)
uint64_t fp_recip (SIM_STATE, uint64_t op, FP_formats fmt);
#define Recip(op,fmt) fp_recip(SIM_ARGS, op, fmt)
uint64_t fp_sqrt (SIM_STATE, uint64_t op, FP_formats fmt);
@@ -741,6 +807,12 @@ uint64_t fp_rsqrt (SIM_STATE, uint64_t op, FP_formats fmt);
#define RSquareRoot(op,fmt) fp_rsqrt(SIM_ARGS, op, fmt)
uint64_t fp_madd (SIM_STATE, uint64_t op1, uint64_t op2,
uint64_t op3, FP_formats fmt);
+#define FusedMultiplyAdd(op1,op2,op3,fmt) fp_fmadd(SIM_ARGS, op1, op2, op3, fmt)
+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);
#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);