diff options
author | Faraz Shahbazker <fshahbazker@wavecomp.com> | 2022-02-02 11:17:25 +0100 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2022-02-04 19:37:26 -0500 |
commit | 06c441cceffb1437a3af51bfad43dce5fd200d9e (patch) | |
tree | e9622ab76b867b2461991d00658703d630018703 /sim/mips | |
parent | fc3c199facd60cc2facbfeee3e541e6aa6410f52 (diff) | |
download | gdb-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.in | 1 | ||||
-rwxr-xr-x | sim/mips/configure | 22 | ||||
-rw-r--r-- | sim/mips/configure.ac | 20 | ||||
-rw-r--r-- | sim/mips/cp1.c | 432 | ||||
-rw-r--r-- | sim/mips/cp1.h | 2 | ||||
-rw-r--r-- | sim/mips/interp.c | 6 | ||||
-rw-r--r-- | sim/mips/micromips.igen | 4 | ||||
-rw-r--r-- | sim/mips/mips.igen | 380 | ||||
-rw-r--r-- | sim/mips/mips3264r2.igen | 30 | ||||
-rw-r--r-- | sim/mips/mips3264r6.igen | 1226 | ||||
-rw-r--r-- | sim/mips/sim-main.h | 94 |
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); |