summaryrefslogtreecommitdiff
path: root/sim
diff options
context:
space:
mode:
Diffstat (limited to 'sim')
-rw-r--r--sim/arm/ChangeLog4
-rw-r--r--sim/arm/wrapper.c2
-rw-r--r--sim/common/ChangeLog4
-rw-r--r--sim/common/callback.c2
-rw-r--r--sim/igen/ChangeLog15
-rw-r--r--sim/igen/gen.c25
-rw-r--r--sim/igen/igen.c19
-rw-r--r--sim/mips/ChangeLog165
-rw-r--r--sim/mips/Makefile.in2
-rwxr-xr-xsim/mips/configure44
-rw-r--r--sim/mips/configure.in16
-rw-r--r--sim/mips/cp1.c1193
-rw-r--r--sim/mips/interp.c1108
-rw-r--r--sim/mips/mips.igen1426
-rw-r--r--sim/mips/sim-main.h43
-rw-r--r--sim/ppc/ChangeLog16
-rw-r--r--sim/ppc/hw_disk.c3
-rw-r--r--sim/ppc/ppc-instructions14
-rw-r--r--sim/ppc/sim_calls.c12
-rw-r--r--sim/z8k/ChangeLog7
-rw-r--r--sim/z8k/writecode.c9
21 files changed, 2534 insertions, 1595 deletions
diff --git a/sim/arm/ChangeLog b/sim/arm/ChangeLog
index bf7256c4516..04c7e280871 100644
--- a/sim/arm/ChangeLog
+++ b/sim/arm/ChangeLog
@@ -1,3 +1,7 @@
+2002-03-17 Anthony Green <green@redhat.com>
+
+ * wrapper.c (mem_size): Increase the default target memory to 8MB.
+
2002-02-21 Keith Seitz <keiths@redhat.com>
* armos.c (SWIWrite0): Use generic host_callback mechanism
diff --git a/sim/arm/wrapper.c b/sim/arm/wrapper.c
index e00c21b4ca3..773ef354d86 100644
--- a/sim/arm/wrapper.c
+++ b/sim/arm/wrapper.c
@@ -47,7 +47,7 @@ static SIM_OPEN_KIND sim_kind;
static char *myname;
/* Memory size in bytes. */
-static int mem_size = (1 << 21);
+static int mem_size = (1 << 23);
/* Non-zero to display start up banner, and maybe other things. */
static int verbosity;
diff --git a/sim/common/ChangeLog b/sim/common/ChangeLog
index 84c2964a4b0..6935b013c79 100644
--- a/sim/common/ChangeLog
+++ b/sim/common/ChangeLog
@@ -1,3 +1,7 @@
+2002-05-01 Chris Demetriou <cgd@broadcom.com>
+
+ * callback.c: Use 'deprecated' rather than 'depreciated.'
+
2002-02-24 Andrew Cagney <ac131313@redhat.com>
From wiz at danbala:
diff --git a/sim/common/callback.c b/sim/common/callback.c
index 64b4e7cd379..af5de148ad0 100644
--- a/sim/common/callback.c
+++ b/sim/common/callback.c
@@ -435,7 +435,7 @@ os_init (p)
return 1;
}
-/* DEPRECIATED */
+/* DEPRECATED */
/* VARARGS */
static void
diff --git a/sim/igen/ChangeLog b/sim/igen/ChangeLog
index ea88fb0ad06..d5ba8abf638 100644
--- a/sim/igen/ChangeLog
+++ b/sim/igen/ChangeLog
@@ -1,3 +1,18 @@
+2002-05-01 Chris Demetriou <cgd@broadcom.com>
+
+ * igen.c: Use 'deprecated' rather than 'depreciated.'
+
+2002-03-23 Andrew Cagney <ac131313@redhat.com>
+
+ * gen.c (format_name_cmp): New function.
+ (insn_list_insert): Use the instruction field name as an
+ additional key. Different field names indicate different
+ semantics.
+
+2002-03-07 Chris Demetriou <cgd@broadcom.com>
+
+ * igen.c (print_itrace_format): Add support for a new "%#lx" format.
+
Tue May 23 21:39:23 2000 Andrew Cagney <cagney@b1.cygnus.com>
* configure: Regenerated to track ../common/aclocal.m4 changes.
diff --git a/sim/igen/gen.c b/sim/igen/gen.c
index de886190665..7c24b46813f 100644
--- a/sim/igen/gen.c
+++ b/sim/igen/gen.c
@@ -308,7 +308,18 @@ new_opcode_bits (opcode_bits *old_bits,
}
}
-
+/* Same as strcmp(). */
+static int
+format_name_cmp (const char *l, const char *r)
+{
+ if (l == NULL && r == NULL)
+ return 0;
+ if (l != NULL && r == NULL)
+ return -1;
+ if (l == NULL && r != NULL)
+ return +1;
+ return strcmp (l, r);
+}
typedef enum {
@@ -351,6 +362,18 @@ insn_list_insert (insn_list **cur_insn_ptr,
else if (cmp > 0)
continue;
+ /* key#4 sort according to the format-name. If two apparently
+ identical instructions have unique format-names, then the
+ instructions are different. This is because the
+ format-name's use is overloaded, it not only indicates the
+ format name but also provides a unique semantic name for the
+ function. */
+ cmp = format_name_cmp (insn->format_name, (*cur_insn_ptr)->insn->format_name);
+ if (cmp < 0)
+ break;
+ else if (cmp > 0)
+ continue;
+
/* duplicate keys, report problem */
switch (duplicate_action)
{
diff --git a/sim/igen/igen.c b/sim/igen/igen.c
index 094f0cd43bb..1399d30a306 100644
--- a/sim/igen/igen.c
+++ b/sim/igen/igen.c
@@ -445,6 +445,17 @@ print_itrace_format (lf *file,
lf_write (file, param, strlen_param);
}
}
+ else if (strncmp (fmt, "%#lx<", 5) == 0)
+ /* simple hex with 0x prefix*/
+ {
+ if (pass == 1)
+ lf_printf (file, "%%#lx");
+ else
+ {
+ lf_printf (file, "(unsigned long) ");
+ lf_write (file, param, strlen_param);
+ }
+ }
else if (strncmp (fmt, "%08lx<", 6) == 0)
/* simple hex */
{
@@ -1026,7 +1037,7 @@ main (int argc,
printf ("Config options:\n");
printf ("\n");
printf (" -B <bit-size>\n");
- printf ("\t Set the number of bits in an instruction (depreciated).\n");
+ printf ("\t Set the number of bits in an instruction (deprecated).\n");
printf ("\t This option can now be set directly in the instruction table.\n");
printf ("\n");
printf (" -D <data-structure>\n");
@@ -1038,7 +1049,7 @@ main (int argc,
printf ("\t a flag not listed in the <filter-list>.\n");
printf ("\n");
printf (" -H <high-bit>\n");
- printf ("\t Set the number of the high (most significant) instruction bit (depreciated).\n");
+ printf ("\t Set the number of the high (most significant) instruction bit (deprecated).\n");
printf ("\t This option can now be set directly in the instruction table.\n");
printf ("\n");
printf (" -I <directory>\n");
@@ -1109,7 +1120,7 @@ main (int argc,
printf ("\t trace-rule-expansion - report each instruction as it is expanded (before insertion into a decode table)\n");
printf ("\t trace-all - enable all trace options\n");
printf ("\n");
- printf ("\t field-widths - instruction formats specify widths (depreciated)\n");
+ printf ("\t field-widths - instruction formats specify widths (deprecated)\n");
printf ("\t By default, an instruction format specifies bit\n");
printf ("\t positions\n");
printf ("\t This option can now be set directly in the\n");
@@ -1119,7 +1130,7 @@ main (int argc,
printf ("\n");
printf ("Input options:\n");
printf ("\n");
- printf (" -k <cache-rules> (depreciated)\n");
+ printf (" -k <cache-rules> (deprecated)\n");
printf (" -o <decode-rules>\n");
printf (" -i <instruction-table>\n");
printf ("\n");
diff --git a/sim/mips/ChangeLog b/sim/mips/ChangeLog
index 4ffef07d97c..388753966c5 100644
--- a/sim/mips/ChangeLog
+++ b/sim/mips/ChangeLog
@@ -1,3 +1,168 @@
+2002-05-01 Chris Demetriou <cgd@broadcom.com>
+
+ * interp.c: Use 'deprecated' rather than 'depreciated.'
+ * sim-main.h: Likewise.
+
+2002-05-01 Chris Demetriou <cgd@broadcom.com>
+
+ * cp1.c (store_fpr): Remove #ifdef'd out call to UndefinedResult
+ which wouldn't compile anyway.
+ * sim-main.h (unpredictable_action): New function prototype.
+ (Unpredictable): Define to call igen function unpredictable().
+ (NotWordValue): New macro to call igen function not_word_value().
+ (UndefinedResult): Remove.
+ * interp.c (undefined_result): Remove.
+ (unpredictable_action): New function.
+ * mips.igen (not_word_value, unpredictable): New functions.
+ (ADD, ADDI, do_addiu, do_addu, BGEZAL, BGEZALL, BLTZAL, BLTZALL)
+ (CLO, CLZ, MADD, MADDU, MSUB, MSUBU, MUL, do_mult, do_multu)
+ (do_sra, do_srav, do_srl, do_srlv, SUB, do_subu): Invoke
+ NotWordValue() to check for unpredictable inputs, then
+ Unpredictable() to handle them.
+
+2002-02-24 Chris Demetriou <cgd@broadcom.com>
+
+ * mips.igen: Fix formatting of calls to Unpredictable().
+
+2002-04-20 Andrew Cagney <ac131313@redhat.com>
+
+ * interp.c (sim_open): Revert previous change.
+
+2002-04-18 Alexandre Oliva <aoliva@redhat.com>
+
+ * interp.c (sim_open): Disable chunk of code that wrote code in
+ vector table entries.
+
+2002-03-19 Chris Demetriou <cgd@broadcom.com>
+
+ * cp1.c (FP_S_s, FP_D_s, FP_S_be, FP_D_be, FP_S_e, FP_D_e, FP_S_f)
+ (FP_D_f, FP_S_fb, FP_D_fb, FPINF_SINGLE, FPINF_DOUBLE): Remove
+ unused definitions.
+
+2002-03-19 Chris Demetriou <cgd@broadcom.com>
+
+ * cp1.c: Fix many formatting issues.
+
+2002-03-19 Chris G. Demetriou <cgd@broadcom.com>
+
+ * cp1.c (fpu_format_name): New function to replace...
+ (DOFMT): This. Delete, and update all callers.
+ (fpu_rounding_mode_name): New function to replace...
+ (RMMODE): This. Delete, and update all callers.
+
+2002-03-19 Chris G. Demetriou <cgd@broadcom.com>
+
+ * interp.c: Move FPU support routines from here to...
+ * cp1.c: Here. New file.
+ * Makefile.in (SIM_OBJS): Add cp1.o to object list.
+ (cp1.o): New target.
+
+2002-03-12 Chris Demetriou <cgd@broadcom.com>
+
+ * configure.in (mipsisa32*-*-*, mipsisa64*-*-*): New targets.
+ * mips.igen (mips32, mips64): New models, add to all instructions
+ and functions as appropriate.
+ (loadstore_ea, check_u64): New variant for model mips64.
+ (check_fmt_p): New variant for models mipsV and mips64, remove
+ mipsV model marking fro other variant.
+ (SLL) Rename to...
+ (SLLa) this.
+ (CLO, CLZ, MADD, MADDU, MSUB, MSUBU, MUL, SLLb): New instructions
+ for mips32 and mips64.
+ (DCLO, DCLZ): New instructions for mips64.
+
+2002-03-07 Chris Demetriou <cgd@broadcom.com>
+
+ * mips.igen (BREAK, LUI, ORI, SYSCALL, XORI): Print
+ immediate or code as a hex value with the "%#lx" format.
+ (ANDI): Likewise, and fix printed instruction name.
+
+2002-03-05 Chris Demetriou <cgd@broadcom.com>
+
+ * sim-main.h (UndefinedResult, Unpredictable): New macros
+ which currently do nothing.
+
+2002-03-05 Chris Demetriou <cgd@broadcom.com>
+
+ * sim-main.h (status_UX, status_SX, status_KX, status_TS)
+ (status_PX, status_MX, status_CU0, status_CU1, status_CU2)
+ (status_CU3): New definitions.
+
+ * sim-main.h (ExceptionCause): Add new values for MIPS32
+ and MIPS64: MDMX, MCheck, CacheErr. Update comments
+ for DebugBreakPoint and NMIReset to note their status in
+ MIPS32 and MIPS64.
+ (SignalExceptionMDMX, SignalExceptionWatch, SignalExceptionMCheck)
+ (SignalExceptionCacheErr): New exception macros.
+
+2002-03-05 Chris Demetriou <cgd@broadcom.com>
+
+ * mips.igen (check_fpu): Enable check for coprocessor 1 usability.
+ * sim-main.h (COP_Usable): Define, but for now coprocessor 1
+ is always enabled.
+ (SignalExceptionCoProcessorUnusable): Take as argument the
+ unusable coprocessor number.
+
+2002-03-05 Chris Demetriou <cgd@broadcom.com>
+
+ * mips.igen: Fix formatting of all SignalException calls.
+
+2002-03-05 Chris Demetriou <cgd@broadcom.com>
+
+ * sim-main.h (SIGNEXTEND): Remove.
+
+2002-03-04 Chris Demetriou <cgd@broadcom.com>
+
+ * mips.igen: Remove gencode comment from top of file, fix
+ spelling in another comment.
+
+2002-03-04 Chris Demetriou <cgd@broadcom.com>
+
+ * mips.igen (check_fmt, check_fmt_p): New functions to check
+ whether specific floating point formats are usable.
+ (ABS.fmt, ADD.fmt, CEIL.L.fmt, CEIL.W, DIV.fmt, FLOOR.L.fmt)
+ (FLOOR.W.fmt, MOV.fmt, MUL.fmt, NEG.fmt, RECIP.fmt, ROUND.L.fmt)
+ (ROUND.W.fmt, RSQRT.fmt, SQRT.fmt, SUB.fmt, TRUNC.L.fmt, TRUNC.W):
+ Use the new functions.
+ (do_c_cond_fmt): Remove format checks...
+ (C.cond.fmta, C.cond.fmtb): And move them into all callers.
+
+2002-03-03 Chris Demetriou <cgd@broadcom.com>
+
+ * mips.igen: Fix formatting of check_fpu calls.
+
+2002-03-03 Chris Demetriou <cgd@broadcom.com>
+
+ * mips.igen (FLOOR.L.fmt): Store correct destination register.
+
+2002-03-03 Chris Demetriou <cgd@broadcom.com>
+
+ * mips.igen: Remove whitespace at end of lines.
+
+2002-03-02 Chris Demetriou <cgd@broadcom.com>
+
+ * mips.igen (loadstore_ea): New function to do effective
+ address calculations.
+ (do_load, do_load_left, do_load_right, LL, LDD, PREF, do_store,
+ do_store_left, do_store_right, SC, SCD, PREFX, SWC1, SWXC1,
+ CACHE): Use loadstore_ea to do effective address computations.
+
+2002-03-02 Chris Demetriou <cgd@broadcom.com>
+
+ * interp.c (load_word): Use EXTEND32 rather than SIGNEXTEND.
+ * mips.igen (LL, CxC1, MxC1): Likewise.
+
+2002-03-02 Chris Demetriou <cgd@broadcom.com>
+
+ * mips.igen (LL, LLD, PREF, SC, SCD, ABS.fmt, ADD.fmt, CEIL.L.fmt,
+ CEIL.W, CVT.D.fmt, CVT.L.fmt, CVT.S.fmt, CVT.W.fmt, DIV.fmt,
+ FLOOR.L.fmt, FLOOR.W.fmt, MADD.D, MADD.S, MOV.fmt, MOVtf.fmt,
+ MSUB.D, MSUB.S, MUL.fmt, NEG.fmt, NMADD.D, NMADD.S, NMSUB.D,
+ NMSUB.S, PREFX, RECIP.fmt, ROUND.L.fmt, ROUND.W.fmt, RSQRT.fmt,
+ SQRT.fmt, SUB.fmt, SWC1, SWXC1, TRUNC.L.fmt, TRUNC.W, CACHE):
+ Don't split opcode fields by hand, use the opcode field values
+ provided by igen.
+
2002-03-01 Chris Demetriou <cgd@broadcom.com>
* mips.igen (do_divu): Fix spacing.
diff --git a/sim/mips/Makefile.in b/sim/mips/Makefile.in
index 98831755e36..5d0a3364e8f 100644
--- a/sim/mips/Makefile.in
+++ b/sim/mips/Makefile.in
@@ -41,6 +41,7 @@ SIM_OBJS = \
$(SIM_@sim_gen@_OBJ) \
$(SIM_NEW_COMMON_OBJS) \
$(MIPS_EXTRA_OBJS) \
+ cp1.o \
interp.o \
sim-main.o \
sim-hload.o \
@@ -68,6 +69,7 @@ SIM_RUN_OBJS = nrun.o
## COMMON_POST_CONFIG_FRAG
interp.o: $(srcdir)/interp.c config.h sim-main.h itable.h
+cp1.o: $(srcdir)/cp1.c config.h sim-main.h
../igen/igen:
diff --git a/sim/mips/configure b/sim/mips/configure
index 3b94005ca8d..e5f427e10f7 100755
--- a/sim/mips/configure
+++ b/sim/mips/configure
@@ -3764,6 +3764,8 @@ fi
#
case "${target}" in
mips*tx39*) SIM_SUBTARGET="-DSUBTARGET_R3900=1";;
+ mipsisa32*-*-*) SIM_SUBTARGET="-DTARGET_ENABLE_FR=1";;
+ mipsisa64*-*-*) SIM_SUBTARGET="-DTARGET_ENABLE_FR=1";;
*) SIM_SUBTARGET="";;
esac
@@ -3780,6 +3782,8 @@ case "${target}" in
mips64vr*el-*-*) default_endian=LITTLE_ENDIAN ;;
mips64*-*-*) default_endian=BIG_ENDIAN ;;
mips16*-*-*) default_endian=BIG_ENDIAN ;;
+ mipsisa32*-*-*) default_endian=BIG_ENDIAN ;;
+ mipsisa64*-*-*) default_endian=BIG_ENDIAN ;;
mips*-*-*) default_endian=BIG_ENDIAN ;;
*) default_endian=BIG_ENDIAN ;;
esac
@@ -3839,6 +3843,8 @@ mips_addr_bitsize=
case "${target}" in
mips64*-*-*) mips_bitsize=64 ; mips_msb=63 ;;
mips16*-*-*) mips_bitsize=64 ; mips_msb=63 ;;
+ mipsisa32*-*-*) mips_bitsize=32 ; mips_msb=31 ;;
+ mipsisa64*-*-*) mips_bitsize=64 ; mips_msb=63 ;;
mips*-*-*) mips_bitsize=32 ; mips_msb=31 ;;
*) mips_bitsize=64 ; mips_msb=63 ;;
esac
@@ -3916,6 +3922,8 @@ case "${target}" in
;;
mips64*-*-*) mips_fpu=HARD_FLOATING_POINT ;;
mips16*-*-*) mips_fpu=HARD_FLOATING_POINT ;;
+ mipsisa32*-*-*) mips_fpu=HARD_FLOATING_POINT ; mips_fpu_bitsize=64 ;;
+ mipsisa64*-*-*) mips_fpu=HARD_FLOATING_POINT ; mips_fpu_bitsize=64 ;;
mips*-*-*) mips_fpu=HARD_FLOATING_POINT ; mips_fpu_bitsize=32 ;;
*) mips_fpu=HARD_FLOATING_POINT ;;
esac
@@ -4011,6 +4019,14 @@ case "${target}" in
sim_igen_filter="32,64,f"
sim_m16_filter="16"
;;
+ mipsisa32*-*-*) sim_gen=IGEN
+ sim_igen_machine="-M mips32"
+ sim_igen_filter="32,f"
+ ;;
+ mipsisa64*-*-*) sim_gen=IGEN
+ sim_igen_machine="-M mips64"
+ sim_igen_filter="32,64,f"
+ ;;
mips*lsi*) sim_gen=M16
sim_igen_machine="-M mipsIII,mips16"
sim_m16_machine="-M mips16,mipsIII"
@@ -4116,7 +4132,7 @@ esac
# Uses ac_ vars as temps to allow command line to override cache and checks.
# --without-x overrides everything else, but does not touch the cache.
echo $ac_n "checking for X""... $ac_c" 1>&6
-echo "configure:4120: checking for X" >&5
+echo "configure:4136: checking for X" >&5
# Check whether --with-x or --without-x was given.
if test "${with_x+set}" = set; then
@@ -4178,12 +4194,12 @@ if test "$ac_x_includes" = NO; then
# First, try using that file with no special directory specified.
cat > conftest.$ac_ext <<EOF
-#line 4182 "configure"
+#line 4198 "configure"
#include "confdefs.h"
#include <$x_direct_test_include>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:4187: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:4203: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -4252,14 +4268,14 @@ if test "$ac_x_libraries" = NO; then
ac_save_LIBS="$LIBS"
LIBS="-l$x_direct_test_library $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 4256 "configure"
+#line 4272 "configure"
#include "confdefs.h"
int main() {
${x_direct_test_function}()
; return 0; }
EOF
-if { (eval echo configure:4263: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4279: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
LIBS="$ac_save_LIBS"
# We can link X programs with no special library path.
@@ -4352,17 +4368,17 @@ for ac_hdr in string.h strings.h stdlib.h stdlib.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:4356: checking for $ac_hdr" >&5
+echo "configure:4372: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4361 "configure"
+#line 4377 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:4366: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:4382: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -4389,7 +4405,7 @@ fi
done
echo $ac_n "checking for fabs in -lm""... $ac_c" 1>&6
-echo "configure:4393: checking for fabs in -lm" >&5
+echo "configure:4409: checking for fabs in -lm" >&5
ac_lib_var=`echo m'_'fabs | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -4397,7 +4413,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lm $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 4401 "configure"
+#line 4417 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -4408,7 +4424,7 @@ int main() {
fabs()
; return 0; }
EOF
-if { (eval echo configure:4412: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4428: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -4438,12 +4454,12 @@ fi
for ac_func in aint anint sqrt
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:4442: checking for $ac_func" >&5
+echo "configure:4458: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4447 "configure"
+#line 4463 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -4466,7 +4482,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:4470: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4486: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
diff --git a/sim/mips/configure.in b/sim/mips/configure.in
index bff4bc35cc4..d8c40232695 100644
--- a/sim/mips/configure.in
+++ b/sim/mips/configure.in
@@ -19,6 +19,8 @@ SIM_AC_OPTION_WARNINGS
#
case "${target}" in
mips*tx39*) SIM_SUBTARGET="-DSUBTARGET_R3900=1";;
+ mipsisa32*-*-*) SIM_SUBTARGET="-DTARGET_ENABLE_FR=1";;
+ mipsisa64*-*-*) SIM_SUBTARGET="-DTARGET_ENABLE_FR=1";;
*) SIM_SUBTARGET="";;
esac
AC_SUBST(SIM_SUBTARGET)
@@ -35,6 +37,8 @@ case "${target}" in
mips64vr*el-*-*) default_endian=LITTLE_ENDIAN ;;
mips64*-*-*) default_endian=BIG_ENDIAN ;;
mips16*-*-*) default_endian=BIG_ENDIAN ;;
+ mipsisa32*-*-*) default_endian=BIG_ENDIAN ;;
+ mipsisa64*-*-*) default_endian=BIG_ENDIAN ;;
mips*-*-*) default_endian=BIG_ENDIAN ;;
*) default_endian=BIG_ENDIAN ;;
esac
@@ -49,6 +53,8 @@ mips_addr_bitsize=
case "${target}" in
mips64*-*-*) mips_bitsize=64 ; mips_msb=63 ;;
mips16*-*-*) mips_bitsize=64 ; mips_msb=63 ;;
+ mipsisa32*-*-*) mips_bitsize=32 ; mips_msb=31 ;;
+ mipsisa64*-*-*) mips_bitsize=64 ; mips_msb=63 ;;
mips*-*-*) mips_bitsize=32 ; mips_msb=31 ;;
*) mips_bitsize=64 ; mips_msb=63 ;;
esac
@@ -67,6 +73,8 @@ case "${target}" in
;;
mips64*-*-*) mips_fpu=HARD_FLOATING_POINT ;;
mips16*-*-*) mips_fpu=HARD_FLOATING_POINT ;;
+ mipsisa32*-*-*) mips_fpu=HARD_FLOATING_POINT ; mips_fpu_bitsize=64 ;;
+ mipsisa64*-*-*) mips_fpu=HARD_FLOATING_POINT ; mips_fpu_bitsize=64 ;;
mips*-*-*) mips_fpu=HARD_FLOATING_POINT ; mips_fpu_bitsize=32 ;;
*) mips_fpu=HARD_FLOATING_POINT ;;
esac
@@ -116,6 +124,14 @@ case "${target}" in
sim_igen_filter="32,64,f"
sim_m16_filter="16"
;;
+ mipsisa32*-*-*) sim_gen=IGEN
+ sim_igen_machine="-M mips32"
+ sim_igen_filter="32,f"
+ ;;
+ mipsisa64*-*-*) sim_gen=IGEN
+ sim_igen_machine="-M mips64"
+ sim_igen_filter="32,64,f"
+ ;;
mips*lsi*) sim_gen=M16
sim_igen_machine="-M mipsIII,mips16"
sim_m16_machine="-M mips16,mipsIII"
diff --git a/sim/mips/cp1.c b/sim/mips/cp1.c
new file mode 100644
index 00000000000..063c241c277
--- /dev/null
+++ b/sim/mips/cp1.c
@@ -0,0 +1,1193 @@
+/*> cp1.c <*/
+/* Floating Point Support for gdb MIPS simulators
+
+ This file is part of the MIPS sim
+
+ THIS SOFTWARE IS NOT COPYRIGHTED
+
+ Cygnus offers the following for use in the public domain. Cygnus
+ makes no warranty with regard to the software or it's performance
+ and the user accepts the software "AS IS" with all faults.
+
+ CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO
+ THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+ (Originally, this code was in interp.c)
+*/
+
+#include "sim-main.h"
+#include "sim-fpu.h"
+
+/* Within cp1.c we refer to sim_cpu directly. */
+#define CPU cpu
+#define SD sd
+
+/*-- FPU support routines ---------------------------------------------------*/
+
+/* Numbers are held in normalized form. The SINGLE and DOUBLE binary
+ formats conform to ANSI/IEEE Std 754-1985. */
+/* SINGLE precision floating:
+ * seeeeeeeefffffffffffffffffffffff
+ * s = 1bit = sign
+ * e = 8bits = exponent
+ * f = 23bits = fraction
+ */
+/* SINGLE precision fixed:
+ * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
+ * s = 1bit = sign
+ * i = 31bits = integer
+ */
+/* DOUBLE precision floating:
+ * seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff
+ * s = 1bit = sign
+ * e = 11bits = exponent
+ * f = 52bits = fraction
+ */
+/* DOUBLE precision fixed:
+ * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
+ * s = 1bit = sign
+ * i = 63bits = integer
+ */
+
+/* Explicit QNaN values used when value required: */
+#define FPQNaN_SINGLE (0x7FBFFFFF)
+#define FPQNaN_WORD (0x7FFFFFFF)
+#define FPQNaN_DOUBLE ((((uword64) 0x7FF7FFFF) << 32) | 0xFFFFFFFF)
+#define FPQNaN_LONG ((((uword64) 0x7FFFFFFF) << 32) | 0xFFFFFFFF)
+
+static const char *fpu_format_name (FP_formats fmt);
+#ifdef DEBUG
+static const char *fpu_rounding_mode_name (int rm);
+#endif
+
+uword64
+value_fpr (SIM_DESC sd,
+ sim_cpu *cpu,
+ address_word cia,
+ int fpr,
+ FP_formats fmt)
+{
+ uword64 value = 0;
+ int err = 0;
+
+ /* Treat unused register values, as fixed-point 64bit values: */
+ if ((fmt == fmt_uninterpreted) || (fmt == fmt_unknown))
+ {
+#if 1
+ /* If request to read data as "uninterpreted", then use the current
+ encoding: */
+ fmt = FPR_STATE[fpr];
+#else
+ fmt = fmt_long;
+#endif
+ }
+
+ /* For values not yet accessed, set to the desired format: */
+ if (FPR_STATE[fpr] == fmt_uninterpreted)
+ {
+ FPR_STATE[fpr] = fmt;
+#ifdef DEBUG
+ printf ("DBG: Register %d was fmt_uninterpreted. Now %s\n", fpr,
+ fpu_format_name (fmt));
+#endif /* DEBUG */
+ }
+ if (fmt != FPR_STATE[fpr])
+ {
+ 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]),
+ fpu_format_name (fmt), pr_addr (cia));
+ FPR_STATE[fpr] = fmt_unknown;
+ }
+
+ if (FPR_STATE[fpr] == fmt_unknown)
+ {
+ /* Set QNaN value: */
+ switch (fmt)
+ {
+ case fmt_single:
+ value = FPQNaN_SINGLE;
+ break;
+
+ case fmt_double:
+ value = FPQNaN_DOUBLE;
+ break;
+
+ case fmt_word:
+ value = FPQNaN_WORD;
+ break;
+
+ case fmt_long:
+ value = FPQNaN_LONG;
+ break;
+
+ default:
+ err = -1;
+ break;
+ }
+ }
+ else if (SizeFGR () == 64)
+ {
+ switch (fmt)
+ {
+ case fmt_single:
+ case fmt_word:
+ value = (FGR[fpr] & 0xFFFFFFFF);
+ break;
+
+ case fmt_uninterpreted:
+ case fmt_double:
+ case fmt_long:
+ value = FGR[fpr];
+ break;
+
+ default:
+ err = -1;
+ break;
+ }
+ }
+ else
+ {
+ switch (fmt)
+ {
+ case fmt_single:
+ case fmt_word:
+ value = (FGR[fpr] & 0xFFFFFFFF);
+ break;
+
+ case fmt_uninterpreted:
+ case fmt_double:
+ case fmt_long:
+ if ((fpr & 1) == 0)
+ {
+ /* even registers only */
+#ifdef DEBUG
+ printf ("DBG: ValueFPR: FGR[%d] = %s, FGR[%d] = %s\n",
+ fpr + 1, pr_uword64 ((uword64) FGR[fpr+1]),
+ fpr, pr_uword64 ((uword64) FGR[fpr]));
+#endif
+ value = ((((uword64) FGR[fpr+1]) << 32)
+ | (FGR[fpr] & 0xFFFFFFFF));
+ }
+ else
+ {
+ SignalException (ReservedInstruction, 0);
+ }
+ break;
+
+ default :
+ err = -1;
+ break;
+ }
+ }
+
+ if (err)
+ SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR ()");
+
+#ifdef DEBUG
+ printf ("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR () = %d\n",
+ fpr, fpu_format_name (fmt), pr_uword64 (value), pr_addr (cia),
+ SizeFGR ());
+#endif /* DEBUG */
+
+ return (value);
+}
+
+void
+store_fpr (SIM_DESC sd,
+ sim_cpu *cpu,
+ address_word cia,
+ int fpr,
+ FP_formats fmt,
+ uword64 value)
+{
+ int err = 0;
+
+#ifdef DEBUG
+ printf ("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR () = %d, \n",
+ fpr, fpu_format_name (fmt), pr_uword64 (value), pr_addr (cia),
+ SizeFGR ());
+#endif /* DEBUG */
+
+ if (SizeFGR () == 64)
+ {
+ switch (fmt)
+ {
+ case fmt_uninterpreted_32:
+ fmt = fmt_uninterpreted;
+ case fmt_single :
+ case fmt_word :
+ if (STATE_VERBOSE_P (SD))
+ sim_io_eprintf (SD,
+ "Warning: PC 0x%s: interp.c store_fpr DEADCODE\n",
+ pr_addr (cia));
+ FGR[fpr] = (((uword64) 0xDEADC0DE << 32) | (value & 0xFFFFFFFF));
+ FPR_STATE[fpr] = fmt;
+ break;
+
+ case fmt_uninterpreted_64:
+ fmt = fmt_uninterpreted;
+ case fmt_uninterpreted:
+ case fmt_double :
+ case fmt_long :
+ FGR[fpr] = value;
+ FPR_STATE[fpr] = fmt;
+ break;
+
+ default :
+ FPR_STATE[fpr] = fmt_unknown;
+ err = -1;
+ break;
+ }
+ }
+ else
+ {
+ switch (fmt)
+ {
+ case fmt_uninterpreted_32:
+ fmt = fmt_uninterpreted;
+ case fmt_single :
+ case fmt_word :
+ FGR[fpr] = (value & 0xFFFFFFFF);
+ FPR_STATE[fpr] = fmt;
+ break;
+
+ case fmt_uninterpreted_64:
+ fmt = fmt_uninterpreted;
+ case fmt_uninterpreted:
+ case fmt_double :
+ case fmt_long :
+ if ((fpr & 1) == 0)
+ {
+ /* even register number only */
+ FGR[fpr+1] = (value >> 32);
+ FGR[fpr] = (value & 0xFFFFFFFF);
+ FPR_STATE[fpr + 1] = fmt;
+ FPR_STATE[fpr] = fmt;
+ }
+ else
+ {
+ FPR_STATE[fpr] = fmt_unknown;
+ FPR_STATE[fpr + 1] = fmt_unknown;
+ SignalException (ReservedInstruction, 0);
+ }
+ break;
+
+ default :
+ FPR_STATE[fpr] = fmt_unknown;
+ err = -1;
+ break;
+ }
+ }
+
+ if (err)
+ SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR ()");
+
+#ifdef DEBUG
+ printf ("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",
+ fpr, pr_uword64 (FGR[fpr]), fpu_format_name (fmt));
+#endif /* DEBUG */
+
+ return;
+}
+
+int
+NaN (op, fmt)
+ uword64 op;
+ FP_formats fmt;
+{
+ int boolean = 0;
+ switch (fmt)
+ {
+ case fmt_single:
+ case fmt_word:
+ {
+ sim_fpu wop;
+ sim_fpu_32to (&wop, op);
+ boolean = sim_fpu_is_nan (&wop);
+ break;
+ }
+ case fmt_double:
+ case fmt_long:
+ {
+ sim_fpu wop;
+ sim_fpu_64to (&wop, op);
+ boolean = sim_fpu_is_nan (&wop);
+ break;
+ }
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+#ifdef DEBUG
+ printf ("DBG: NaN: returning %d for 0x%s (format = %s)\n",
+ boolean, pr_addr (op), fpu_format_name (fmt));
+#endif /* DEBUG */
+
+ return (boolean);
+}
+
+int
+Infinity (op, fmt)
+ uword64 op;
+ FP_formats fmt;
+{
+ int boolean = 0;
+
+#ifdef DEBUG
+ printf ("DBG: Infinity: format %s 0x%s\n",
+ fpu_format_name (fmt), pr_addr (op));
+#endif /* DEBUG */
+
+ switch (fmt)
+ {
+ case fmt_single:
+ {
+ sim_fpu wop;
+ sim_fpu_32to (&wop, op);
+ boolean = sim_fpu_is_infinity (&wop);
+ break;
+ }
+ case fmt_double:
+ {
+ sim_fpu wop;
+ sim_fpu_64to (&wop, op);
+ boolean = sim_fpu_is_infinity (&wop);
+ break;
+ }
+ default:
+ printf ("DBG: TODO: unrecognised format (%s) for Infinity check\n",
+ fpu_format_name (fmt));
+ break;
+ }
+
+#ifdef DEBUG
+ printf ("DBG: Infinity: returning %d for 0x%s (format = %s)\n",
+ boolean, pr_addr (op), fpu_format_name (fmt));
+#endif /* DEBUG */
+
+ return (boolean);
+}
+
+int
+Less (op1, op2, fmt)
+ uword64 op1;
+ uword64 op2;
+ FP_formats fmt;
+{
+ int boolean = 0;
+
+ /* Argument checking already performed by the FPCOMPARE code */
+
+#ifdef DEBUG
+ printf ("DBG: Less: %s: op1 = 0x%s : op2 = 0x%s\n",
+ fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
+#endif /* DEBUG */
+
+ /* The format type should already have been checked: */
+ switch (fmt)
+ {
+ case fmt_single:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu_32to (&wop1, op1);
+ sim_fpu_32to (&wop2, op2);
+ boolean = sim_fpu_is_lt (&wop1, &wop2);
+ break;
+ }
+ case fmt_double:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu_64to (&wop1, op1);
+ sim_fpu_64to (&wop2, op2);
+ boolean = sim_fpu_is_lt (&wop1, &wop2);
+ break;
+ }
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+#ifdef DEBUG
+ printf ("DBG: Less: returning %d (format = %s)\n",
+ boolean, fpu_format_name (fmt));
+#endif /* DEBUG */
+
+ return (boolean);
+}
+
+int
+Equal (op1, op2, fmt)
+ uword64 op1;
+ uword64 op2;
+ FP_formats fmt;
+{
+ int boolean = 0;
+
+ /* Argument checking already performed by the FPCOMPARE code */
+
+#ifdef DEBUG
+ printf ("DBG: Equal: %s: op1 = 0x%s : op2 = 0x%s\n",
+ fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
+#endif /* DEBUG */
+
+ /* The format type should already have been checked: */
+ switch (fmt)
+ {
+ case fmt_single:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu_32to (&wop1, op1);
+ sim_fpu_32to (&wop2, op2);
+ boolean = sim_fpu_is_eq (&wop1, &wop2);
+ break;
+ }
+ case fmt_double:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu_64to (&wop1, op1);
+ sim_fpu_64to (&wop2, op2);
+ boolean = sim_fpu_is_eq (&wop1, &wop2);
+ break;
+ }
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+#ifdef DEBUG
+ printf ("DBG: Equal: returning %d (format = %s)\n",
+ boolean, fpu_format_name (fmt));
+#endif /* DEBUG */
+
+ return (boolean);
+}
+
+uword64
+AbsoluteValue (op, fmt)
+ uword64 op;
+ FP_formats fmt;
+{
+ uword64 result = 0;
+
+#ifdef DEBUG
+ printf ("DBG: AbsoluteValue: %s: op = 0x%s\n",
+ fpu_format_name (fmt), pr_addr (op));
+#endif /* DEBUG */
+
+ /* The format type should already have been checked: */
+ switch (fmt)
+ {
+ case fmt_single:
+ {
+ sim_fpu wop;
+ unsigned32 ans;
+ sim_fpu_32to (&wop, op);
+ sim_fpu_abs (&wop, &wop);
+ sim_fpu_to32 (&ans, &wop);
+ result = ans;
+ break;
+ }
+ case fmt_double:
+ {
+ sim_fpu wop;
+ unsigned64 ans;
+ sim_fpu_64to (&wop, op);
+ sim_fpu_abs (&wop, &wop);
+ sim_fpu_to64 (&ans, &wop);
+ result = ans;
+ break;
+ }
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+ return (result);
+}
+
+uword64
+Negate (op, fmt)
+ uword64 op;
+ FP_formats fmt;
+{
+ uword64 result = 0;
+
+#ifdef DEBUG
+ printf ("DBG: Negate: %s: op = 0x%s\n",
+ fpu_format_name (fmt), pr_addr (op));
+#endif /* DEBUG */
+
+ /* The format type should already have been checked: */
+ switch (fmt)
+ {
+ case fmt_single:
+ {
+ sim_fpu wop;
+ unsigned32 ans;
+ sim_fpu_32to (&wop, op);
+ sim_fpu_neg (&wop, &wop);
+ sim_fpu_to32 (&ans, &wop);
+ result = ans;
+ break;
+ }
+ case fmt_double:
+ {
+ sim_fpu wop;
+ unsigned64 ans;
+ sim_fpu_64to (&wop, op);
+ sim_fpu_neg (&wop, &wop);
+ sim_fpu_to64 (&ans, &wop);
+ result = ans;
+ break;
+ }
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+ return (result);
+}
+
+uword64
+Add (op1, op2, fmt)
+ uword64 op1;
+ uword64 op2;
+ FP_formats fmt;
+{
+ uword64 result = 0;
+
+#ifdef DEBUG
+ printf ("DBG: Add: %s: op1 = 0x%s : op2 = 0x%s\n",
+ fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
+#endif /* DEBUG */
+
+ /* The registers must specify FPRs valid for operands of type
+ "fmt". If they are not valid, the result is undefined. */
+
+ /* The format type should already have been checked: */
+ switch (fmt)
+ {
+ case fmt_single:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu ans;
+ unsigned32 res;
+ sim_fpu_32to (&wop1, op1);
+ sim_fpu_32to (&wop2, op2);
+ sim_fpu_add (&ans, &wop1, &wop2);
+ sim_fpu_to32 (&res, &ans);
+ result = res;
+ break;
+ }
+ case fmt_double:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu ans;
+ unsigned64 res;
+ sim_fpu_64to (&wop1, op1);
+ sim_fpu_64to (&wop2, op2);
+ sim_fpu_add (&ans, &wop1, &wop2);
+ sim_fpu_to64 (&res, &ans);
+ result = res;
+ break;
+ }
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+#ifdef DEBUG
+ printf ("DBG: Add: returning 0x%s (format = %s)\n",
+ pr_addr (result), fpu_format_name (fmt));
+#endif /* DEBUG */
+
+ return (result);
+}
+
+uword64
+Sub (op1, op2, fmt)
+ uword64 op1;
+ uword64 op2;
+ FP_formats fmt;
+{
+ uword64 result = 0;
+
+#ifdef DEBUG
+ printf ("DBG: Sub: %s: op1 = 0x%s : op2 = 0x%s\n",
+ fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
+#endif /* DEBUG */
+
+ /* The registers must specify FPRs valid for operands of type
+ "fmt". If they are not valid, the result is undefined. */
+
+ /* The format type should already have been checked: */
+ switch (fmt)
+ {
+ case fmt_single:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu ans;
+ unsigned32 res;
+ sim_fpu_32to (&wop1, op1);
+ sim_fpu_32to (&wop2, op2);
+ sim_fpu_sub (&ans, &wop1, &wop2);
+ sim_fpu_to32 (&res, &ans);
+ result = res;
+ }
+ break;
+ case fmt_double:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu ans;
+ unsigned64 res;
+ sim_fpu_64to (&wop1, op1);
+ sim_fpu_64to (&wop2, op2);
+ sim_fpu_sub (&ans, &wop1, &wop2);
+ sim_fpu_to64 (&res, &ans);
+ result = res;
+ }
+ break;
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+#ifdef DEBUG
+ printf ("DBG: Sub: returning 0x%s (format = %s)\n",
+ pr_addr (result), fpu_format_name (fmt));
+#endif /* DEBUG */
+
+ return (result);
+}
+
+uword64
+Multiply (op1, op2, fmt)
+ uword64 op1;
+ uword64 op2;
+ FP_formats fmt;
+{
+ uword64 result = 0;
+
+#ifdef DEBUG
+ printf ("DBG: Multiply: %s: op1 = 0x%s : op2 = 0x%s\n",
+ fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
+#endif /* DEBUG */
+
+ /* The registers must specify FPRs valid for operands of type
+ "fmt". If they are not valid, the result is undefined. */
+
+ /* The format type should already have been checked: */
+ switch (fmt)
+ {
+ case fmt_single:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu ans;
+ unsigned32 res;
+ sim_fpu_32to (&wop1, op1);
+ sim_fpu_32to (&wop2, op2);
+ sim_fpu_mul (&ans, &wop1, &wop2);
+ sim_fpu_to32 (&res, &ans);
+ result = res;
+ break;
+ }
+ case fmt_double:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu ans;
+ unsigned64 res;
+ sim_fpu_64to (&wop1, op1);
+ sim_fpu_64to (&wop2, op2);
+ sim_fpu_mul (&ans, &wop1, &wop2);
+ sim_fpu_to64 (&res, &ans);
+ result = res;
+ break;
+ }
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+#ifdef DEBUG
+ printf ("DBG: Multiply: returning 0x%s (format = %s)\n",
+ pr_addr (result), fpu_format_name (fmt));
+#endif /* DEBUG */
+
+ return (result);
+}
+
+uword64
+Divide (op1, op2, fmt)
+ uword64 op1;
+ uword64 op2;
+ FP_formats fmt;
+{
+ uword64 result = 0;
+
+#ifdef DEBUG
+ printf ("DBG: Divide: %s: op1 = 0x%s : op2 = 0x%s\n",
+ fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
+#endif /* DEBUG */
+
+ /* The registers must specify FPRs valid for operands of type
+ "fmt". If they are not valid, the result is undefined. */
+
+ /* The format type should already have been checked: */
+ switch (fmt)
+ {
+ case fmt_single:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu ans;
+ unsigned32 res;
+ sim_fpu_32to (&wop1, op1);
+ sim_fpu_32to (&wop2, op2);
+ sim_fpu_div (&ans, &wop1, &wop2);
+ sim_fpu_to32 (&res, &ans);
+ result = res;
+ break;
+ }
+ case fmt_double:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu ans;
+ unsigned64 res;
+ sim_fpu_64to (&wop1, op1);
+ sim_fpu_64to (&wop2, op2);
+ sim_fpu_div (&ans, &wop1, &wop2);
+ sim_fpu_to64 (&res, &ans);
+ result = res;
+ break;
+ }
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+#ifdef DEBUG
+ printf ("DBG: Divide: returning 0x%s (format = %s)\n",
+ pr_addr (result), fpu_format_name (fmt));
+#endif /* DEBUG */
+
+ return (result);
+}
+
+uword64 UNUSED
+Recip (op, fmt)
+ uword64 op;
+ FP_formats fmt;
+{
+ uword64 result = 0;
+
+#ifdef DEBUG
+ printf ("DBG: Recip: %s: op = 0x%s\n",
+ fpu_format_name (fmt), pr_addr (op));
+#endif /* DEBUG */
+
+ /* The registers must specify FPRs valid for operands of type
+ "fmt". If they are not valid, the result is undefined. */
+
+ /* The format type should already have been checked: */
+ switch (fmt)
+ {
+ case fmt_single:
+ {
+ sim_fpu wop;
+ sim_fpu ans;
+ unsigned32 res;
+ sim_fpu_32to (&wop, op);
+ sim_fpu_inv (&ans, &wop);
+ sim_fpu_to32 (&res, &ans);
+ result = res;
+ break;
+ }
+ case fmt_double:
+ {
+ sim_fpu wop;
+ sim_fpu ans;
+ unsigned64 res;
+ sim_fpu_64to (&wop, op);
+ sim_fpu_inv (&ans, &wop);
+ sim_fpu_to64 (&res, &ans);
+ result = res;
+ break;
+ }
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+#ifdef DEBUG
+ printf ("DBG: Recip: returning 0x%s (format = %s)\n",
+ pr_addr (result), fpu_format_name (fmt));
+#endif /* DEBUG */
+
+ return (result);
+}
+
+uword64
+SquareRoot (op, fmt)
+ uword64 op;
+ FP_formats fmt;
+{
+ uword64 result = 0;
+
+#ifdef DEBUG
+ printf ("DBG: SquareRoot: %s: op = 0x%s\n",
+ fpu_format_name (fmt), pr_addr (op));
+#endif /* DEBUG */
+
+ /* The registers must specify FPRs valid for operands of type
+ "fmt". If they are not valid, the result is undefined. */
+
+ /* The format type should already have been checked: */
+ switch (fmt)
+ {
+ case fmt_single:
+ {
+ sim_fpu wop;
+ sim_fpu ans;
+ unsigned32 res;
+ sim_fpu_32to (&wop, op);
+ sim_fpu_sqrt (&ans, &wop);
+ sim_fpu_to32 (&res, &ans);
+ result = res;
+ break;
+ }
+ case fmt_double:
+ {
+ sim_fpu wop;
+ sim_fpu ans;
+ unsigned64 res;
+ sim_fpu_64to (&wop, op);
+ sim_fpu_sqrt (&ans, &wop);
+ sim_fpu_to64 (&res, &ans);
+ result = res;
+ break;
+ }
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+#ifdef DEBUG
+ printf ("DBG: SquareRoot: returning 0x%s (format = %s)\n",
+ pr_addr (result), fpu_format_name (fmt));
+#endif /* DEBUG */
+
+ return (result);
+}
+
+#if 0
+uword64
+Max (uword64 op1,
+ uword64 op2,
+ FP_formats fmt)
+{
+ int cmp;
+ unsigned64 result;
+
+#ifdef DEBUG
+ printf ("DBG: Max: %s: op1 = 0x%s : op2 = 0x%s\n",
+ fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
+#endif /* DEBUG */
+
+ /* The registers must specify FPRs valid for operands of type
+ "fmt". If they are not valid, the result is undefined. */
+
+ /* The format type should already have been checked: */
+ switch (fmt)
+ {
+ case fmt_single:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu_32to (&wop1, op1);
+ sim_fpu_32to (&wop2, op2);
+ cmp = sim_fpu_cmp (&wop1, &wop2);
+ break;
+ }
+ case fmt_double:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu_64to (&wop1, op1);
+ sim_fpu_64to (&wop2, op2);
+ cmp = sim_fpu_cmp (&wop1, &wop2);
+ break;
+ }
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+ switch (cmp)
+ {
+ case SIM_FPU_IS_SNAN:
+ case SIM_FPU_IS_QNAN:
+ result = op1;
+ case SIM_FPU_IS_NINF:
+ case SIM_FPU_IS_NNUMBER:
+ case SIM_FPU_IS_NDENORM:
+ case SIM_FPU_IS_NZERO:
+ result = op2; /* op1 - op2 < 0 */
+ case SIM_FPU_IS_PINF:
+ case SIM_FPU_IS_PNUMBER:
+ case SIM_FPU_IS_PDENORM:
+ case SIM_FPU_IS_PZERO:
+ result = op1; /* op1 - op2 > 0 */
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+#ifdef DEBUG
+ printf ("DBG: Max: returning 0x%s (format = %s)\n",
+ pr_addr (result), fpu_format_name (fmt));
+#endif /* DEBUG */
+
+ return (result);
+}
+#endif
+
+#if 0
+uword64
+Min (uword64 op1,
+ uword64 op2,
+ FP_formats fmt)
+{
+ int cmp;
+ unsigned64 result;
+
+#ifdef DEBUG
+ printf ("DBG: Min: %s: op1 = 0x%s : op2 = 0x%s\n",
+ fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
+#endif /* DEBUG */
+
+ /* The registers must specify FPRs valid for operands of type
+ "fmt". If they are not valid, the result is undefined. */
+
+ /* The format type should already have been checked: */
+ switch (fmt)
+ {
+ case fmt_single:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu_32to (&wop1, op1);
+ sim_fpu_32to (&wop2, op2);
+ cmp = sim_fpu_cmp (&wop1, &wop2);
+ break;
+ }
+ case fmt_double:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu_64to (&wop1, op1);
+ sim_fpu_64to (&wop2, op2);
+ cmp = sim_fpu_cmp (&wop1, &wop2);
+ break;
+ }
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+ switch (cmp)
+ {
+ case SIM_FPU_IS_SNAN:
+ case SIM_FPU_IS_QNAN:
+ result = op1;
+ case SIM_FPU_IS_NINF:
+ case SIM_FPU_IS_NNUMBER:
+ case SIM_FPU_IS_NDENORM:
+ case SIM_FPU_IS_NZERO:
+ result = op1; /* op1 - op2 < 0 */
+ case SIM_FPU_IS_PINF:
+ case SIM_FPU_IS_PNUMBER:
+ case SIM_FPU_IS_PDENORM:
+ case SIM_FPU_IS_PZERO:
+ result = op2; /* op1 - op2 > 0 */
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+#ifdef DEBUG
+ printf ("DBG: Min: returning 0x%s (format = %s)\n",
+ pr_addr (result), fpu_format_name (fmt));
+#endif /* DEBUG */
+
+ return (result);
+}
+#endif
+
+uword64
+convert (SIM_DESC sd,
+ sim_cpu *cpu,
+ address_word cia,
+ int rm,
+ uword64 op,
+ FP_formats from,
+ FP_formats to)
+{
+ sim_fpu wop;
+ sim_fpu_round round;
+ unsigned32 result32;
+ unsigned64 result64;
+
+#ifdef DEBUG
+#if 0 /* FIXME: doesn't compile */
+ printf ("DBG: Convert: mode %s : op 0x%s : from %s : to %s : (PC = 0x%s)\n",
+ fpu_rounding_mode_name (rm), pr_addr (op), fpu_format_name (from),
+ fpu_format_name (to), pr_addr (IPC));
+#endif
+#endif /* DEBUG */
+
+ switch (rm)
+ {
+ case FP_RM_NEAREST:
+ /* Round result to nearest representable value. When two
+ representable values are equally near, round to the value
+ that has a least significant bit of zero (i.e. is even). */
+ round = sim_fpu_round_near;
+ break;
+ case FP_RM_TOZERO:
+ /* Round result to the value closest to, and not greater in
+ magnitude than, the result. */
+ round = sim_fpu_round_zero;
+ break;
+ case FP_RM_TOPINF:
+ /* Round result to the value closest to, and not less than,
+ the result. */
+ round = sim_fpu_round_up;
+ break;
+
+ case FP_RM_TOMINF:
+ /* Round result to the value closest to, and not greater than,
+ the result. */
+ round = sim_fpu_round_down;
+ break;
+ default:
+ round = 0;
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+ /* Convert the input to sim_fpu internal format */
+ switch (from)
+ {
+ case fmt_double:
+ sim_fpu_64to (&wop, op);
+ break;
+ case fmt_single:
+ sim_fpu_32to (&wop, op);
+ break;
+ case fmt_word:
+ sim_fpu_i32to (&wop, op, round);
+ break;
+ case fmt_long:
+ sim_fpu_i64to (&wop, op, round);
+ break;
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+ /* Convert sim_fpu format into the output */
+ /* The value WOP is converted to the destination format, rounding
+ using mode RM. When the destination is a fixed-point format, then
+ a source value of Infinity, NaN or one which would round to an
+ integer outside the fixed point range then an IEEE Invalid
+ Operation condition is raised. */
+ switch (to)
+ {
+ case fmt_single:
+ sim_fpu_round_32 (&wop, round, 0);
+ sim_fpu_to32 (&result32, &wop);
+ result64 = result32;
+ break;
+ case fmt_double:
+ sim_fpu_round_64 (&wop, round, 0);
+ sim_fpu_to64 (&result64, &wop);
+ break;
+ case fmt_word:
+ sim_fpu_to32i (&result32, &wop, round);
+ result64 = result32;
+ break;
+ case fmt_long:
+ sim_fpu_to64i (&result64, &wop, round);
+ break;
+ default:
+ result64 = 0;
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+#ifdef DEBUG
+ printf ("DBG: Convert: returning 0x%s (to format = %s)\n",
+ pr_addr (result64), fpu_format_name (to));
+#endif /* DEBUG */
+
+ return (result64);
+}
+
+static const char *
+fpu_format_name (FP_formats fmt)
+{
+ switch (fmt)
+ {
+ case fmt_single:
+ return "single";
+ case fmt_double:
+ return "double";
+ case fmt_word:
+ return "word";
+ case fmt_long:
+ return "long";
+ case fmt_unknown:
+ return "<unknown>";
+ case fmt_uninterpreted:
+ return "<uninterpreted>";
+ case fmt_uninterpreted_32:
+ return "<uninterpreted_32>";
+ case fmt_uninterpreted_64:
+ return "<uninterpreted_64>";
+ default:
+ return "<format error>";
+ }
+}
+
+#ifdef DEBUG
+static const char *
+fpu_rounding_mode_name (int rm)
+{
+ switch (rm)
+ {
+ case FP_RM_NEAREST:
+ return "Round";
+ case FP_RM_TOZERO:
+ return "Trunc";
+ case FP_RM_TOPINF:
+ return "Ceil";
+ case FP_RM_TOMINF:
+ return "Floor";
+ default:
+ return "<rounding mode error>";
+ }
+}
+#endif /* DEBUG */
diff --git a/sim/mips/interp.c b/sim/mips/interp.c
index 95f0ab63f5b..805f72a9236 100644
--- a/sim/mips/interp.c
+++ b/sim/mips/interp.c
@@ -1238,7 +1238,7 @@ sim_monitor (SIM_DESC sd,
sim_write (sd, A0 + 0, (char *)&value, 4);
sim_write (sd, A0 + 4, (char *)&zero, 4);
sim_write (sd, A0 + 8, (char *)&zero, 4);
- /* sim_io_eprintf (sd, "sim: get_mem_info() depreciated\n"); */
+ /* sim_io_eprintf (sd, "sim: get_mem_info() deprecated\n"); */
break;
}
@@ -1426,7 +1426,7 @@ load_word (SIM_DESC sd,
LoadMemory (&memval,NULL,uncached, AccessLength_WORD, paddr, vaddr,
isDATA, isREAL);
byte = (vaddr & mask) ^ (bigend << 2);
- return SIGNEXTEND (((memval >> (8 * byte)) & 0xffffffff), 32);
+ return EXTEND32 (memval >> (8 * byte));
}
}
@@ -1869,1096 +1869,30 @@ signal_exception (SIM_DESC sd,
-#if defined(WARN_RESULT)
-/* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
-/* This function indicates that the result of the operation is
- undefined. However, this should not affect the instruction
- stream. All that is meant to happen is that the destination
- register is set to an undefined result. To keep the simulator
- simple, we just don't bother updating the destination register, so
- the overall result will be undefined. If desired we can stop the
- simulator by raising a pseudo-exception. */
-#define UndefinedResult() undefined_result (sd,cia)
-static void
-undefined_result(sd,cia)
- SIM_DESC sd;
- address_word cia;
-{
- sim_io_eprintf(sd,"UndefinedResult: PC = 0x%s\n",pr_addr(cia));
-#if 0 /* Disabled for the moment, since it actually happens a lot at the moment. */
- state |= simSTOP;
-#endif
- return;
-}
-#endif /* WARN_RESULT */
-
-/*-- FPU support routines ---------------------------------------------------*/
-
-/* Numbers are held in normalized form. The SINGLE and DOUBLE binary
- formats conform to ANSI/IEEE Std 754-1985. */
-/* SINGLE precision floating:
- * seeeeeeeefffffffffffffffffffffff
- * s = 1bit = sign
- * e = 8bits = exponent
- * f = 23bits = fraction
- */
-/* SINGLE precision fixed:
- * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
- * s = 1bit = sign
- * i = 31bits = integer
- */
-/* DOUBLE precision floating:
- * seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff
- * s = 1bit = sign
- * e = 11bits = exponent
- * f = 52bits = fraction
- */
-/* DOUBLE precision fixed:
- * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
- * s = 1bit = sign
- * i = 63bits = integer
- */
-
-/* Extract sign-bit: */
-#define FP_S_s(v) (((v) & ((unsigned)1 << 31)) ? 1 : 0)
-#define FP_D_s(v) (((v) & ((uword64)1 << 63)) ? 1 : 0)
-/* Extract biased exponent: */
-#define FP_S_be(v) (((v) >> 23) & 0xFF)
-#define FP_D_be(v) (((v) >> 52) & 0x7FF)
-/* Extract unbiased Exponent: */
-#define FP_S_e(v) (FP_S_be(v) - 0x7F)
-#define FP_D_e(v) (FP_D_be(v) - 0x3FF)
-/* Extract complete fraction field: */
-#define FP_S_f(v) ((v) & ~((unsigned)0x1FF << 23))
-#define FP_D_f(v) ((v) & ~((uword64)0xFFF << 52))
-/* Extract numbered fraction bit: */
-#define FP_S_fb(b,v) (((v) & (1 << (23 - (b)))) ? 1 : 0)
-#define FP_D_fb(b,v) (((v) & (1 << (52 - (b)))) ? 1 : 0)
-
-/* Explicit QNaN values used when value required: */
-#define FPQNaN_SINGLE (0x7FBFFFFF)
-#define FPQNaN_WORD (0x7FFFFFFF)
-#define FPQNaN_DOUBLE (((uword64)0x7FF7FFFF << 32) | 0xFFFFFFFF)
-#define FPQNaN_LONG (((uword64)0x7FFFFFFF << 32) | 0xFFFFFFFF)
-
-/* Explicit Infinity values used when required: */
-#define FPINF_SINGLE (0x7F800000)
-#define FPINF_DOUBLE (((uword64)0x7FF00000 << 32) | 0x00000000)
-
-#define RMMODE(v) (((v) == FP_RM_NEAREST) ? "Round" : (((v) == FP_RM_TOZERO) ? "Trunc" : (((v) == FP_RM_TOPINF) ? "Ceil" : "Floor")))
-#define DOFMT(v) (((v) == fmt_single) ? "single" : (((v) == fmt_double) ? "double" : (((v) == fmt_word) ? "word" : (((v) == fmt_long) ? "long" : (((v) == fmt_unknown) ? "<unknown>" : (((v) == fmt_uninterpreted) ? "<uninterpreted>" : (((v) == fmt_uninterpreted_32) ? "<uninterpreted_32>" : (((v) == fmt_uninterpreted_64) ? "<uninterpreted_64>" : "<format error>"))))))))
-
-uword64
-value_fpr (SIM_DESC sd,
- sim_cpu *cpu,
- address_word cia,
- int fpr,
- FP_formats fmt)
-{
- uword64 value = 0;
- int err = 0;
-
- /* Treat unused register values, as fixed-point 64bit values: */
- if ((fmt == fmt_uninterpreted) || (fmt == fmt_unknown))
-#if 1
- /* If request to read data as "uninterpreted", then use the current
- encoding: */
- fmt = FPR_STATE[fpr];
-#else
- fmt = fmt_long;
-#endif
-
- /* For values not yet accessed, set to the desired format: */
- if (FPR_STATE[fpr] == fmt_uninterpreted) {
- FPR_STATE[fpr] = fmt;
-#ifdef DEBUG
- printf("DBG: Register %d was fmt_uninterpreted. Now %s\n",fpr,DOFMT(fmt));
-#endif /* DEBUG */
- }
- if (fmt != FPR_STATE[fpr]) {
- sim_io_eprintf(sd,"FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",fpr,DOFMT(FPR_STATE[fpr]),DOFMT(fmt),pr_addr(cia));
- FPR_STATE[fpr] = fmt_unknown;
- }
-
- if (FPR_STATE[fpr] == fmt_unknown) {
- /* Set QNaN value: */
- switch (fmt) {
- case fmt_single:
- value = FPQNaN_SINGLE;
- break;
-
- case fmt_double:
- value = FPQNaN_DOUBLE;
- break;
-
- case fmt_word:
- value = FPQNaN_WORD;
- break;
-
- case fmt_long:
- value = FPQNaN_LONG;
- break;
-
- default:
- err = -1;
- break;
- }
- } else if (SizeFGR() == 64) {
- switch (fmt) {
- case fmt_single:
- case fmt_word:
- value = (FGR[fpr] & 0xFFFFFFFF);
- break;
-
- case fmt_uninterpreted:
- case fmt_double:
- case fmt_long:
- value = FGR[fpr];
- break;
-
- default :
- err = -1;
- break;
- }
- } else {
- switch (fmt) {
- case fmt_single:
- case fmt_word:
- value = (FGR[fpr] & 0xFFFFFFFF);
- break;
-
- case fmt_uninterpreted:
- case fmt_double:
- case fmt_long:
- if ((fpr & 1) == 0) { /* even registers only */
-#ifdef DEBUG
- printf("DBG: ValueFPR: FGR[%d] = %s, FGR[%d] = %s\n",
- fpr+1, pr_uword64( (uword64) FGR[fpr+1] ),
- fpr, pr_uword64( (uword64) FGR[fpr] ));
-#endif
- value = ((((uword64)FGR[fpr+1]) << 32) | (FGR[fpr] & 0xFFFFFFFF));
- } else {
- SignalException(ReservedInstruction,0);
- }
- break;
-
- default :
- err = -1;
- break;
- }
- }
-
- if (err)
- SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR()");
-
-#ifdef DEBUG
- printf("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d\n",fpr,DOFMT(fmt),pr_uword64(value),pr_addr(cia),SizeFGR());
-#endif /* DEBUG */
-
- return(value);
-}
-
-void
-store_fpr (SIM_DESC sd,
- sim_cpu *cpu,
- address_word cia,
- int fpr,
- FP_formats fmt,
- uword64 value)
-{
- int err = 0;
-
-#ifdef DEBUG
- printf("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d,\n",fpr,DOFMT(fmt),pr_uword64(value),pr_addr(cia),SizeFGR());
-#endif /* DEBUG */
-
- if (SizeFGR() == 64) {
- switch (fmt) {
- case fmt_uninterpreted_32:
- fmt = fmt_uninterpreted;
- case fmt_single :
- case fmt_word :
- if (STATE_VERBOSE_P(SD))
- sim_io_eprintf (SD, "Warning: PC 0x%s: interp.c store_fpr DEADCODE\n",
- pr_addr(cia));
- FGR[fpr] = (((uword64)0xDEADC0DE << 32) | (value & 0xFFFFFFFF));
- FPR_STATE[fpr] = fmt;
- break;
-
- case fmt_uninterpreted_64:
- fmt = fmt_uninterpreted;
- case fmt_uninterpreted:
- case fmt_double :
- case fmt_long :
- FGR[fpr] = value;
- FPR_STATE[fpr] = fmt;
- break;
-
- default :
- FPR_STATE[fpr] = fmt_unknown;
- err = -1;
- break;
- }
- } else {
- switch (fmt) {
- case fmt_uninterpreted_32:
- fmt = fmt_uninterpreted;
- case fmt_single :
- case fmt_word :
- FGR[fpr] = (value & 0xFFFFFFFF);
- FPR_STATE[fpr] = fmt;
- break;
-
- case fmt_uninterpreted_64:
- fmt = fmt_uninterpreted;
- case fmt_uninterpreted:
- case fmt_double :
- case fmt_long :
- if ((fpr & 1) == 0) { /* even register number only */
- FGR[fpr+1] = (value >> 32);
- FGR[fpr] = (value & 0xFFFFFFFF);
- FPR_STATE[fpr + 1] = fmt;
- FPR_STATE[fpr] = fmt;
- } else {
- FPR_STATE[fpr] = fmt_unknown;
- FPR_STATE[fpr + 1] = fmt_unknown;
- SignalException(ReservedInstruction,0);
- }
- break;
-
- default :
- FPR_STATE[fpr] = fmt_unknown;
- err = -1;
- break;
- }
- }
-#if defined(WARN_RESULT)
- else
- UndefinedResult();
-#endif /* WARN_RESULT */
-
- if (err)
- SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR()");
-
-#ifdef DEBUG
- printf("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",fpr,pr_uword64(FGR[fpr]),DOFMT(fmt));
-#endif /* DEBUG */
-
- return;
-}
-
-int
-NaN(op,fmt)
- uword64 op;
- FP_formats fmt;
-{
- int boolean = 0;
- switch (fmt) {
- case fmt_single:
- case fmt_word:
- {
- sim_fpu wop;
- sim_fpu_32to (&wop, op);
- boolean = sim_fpu_is_nan (&wop);
- break;
- }
- case fmt_double:
- case fmt_long:
- {
- sim_fpu wop;
- sim_fpu_64to (&wop, op);
- boolean = sim_fpu_is_nan (&wop);
- break;
- }
- default:
- fprintf (stderr, "Bad switch\n");
- abort ();
- }
-
-#ifdef DEBUG
-printf("DBG: NaN: returning %d for 0x%s (format = %s)\n",boolean,pr_addr(op),DOFMT(fmt));
-#endif /* DEBUG */
-
- return(boolean);
-}
-
-int
-Infinity(op,fmt)
- uword64 op;
- FP_formats fmt;
-{
- int boolean = 0;
-
-#ifdef DEBUG
- printf("DBG: Infinity: format %s 0x%s\n",DOFMT(fmt),pr_addr(op));
-#endif /* DEBUG */
-
- switch (fmt) {
- case fmt_single:
- {
- sim_fpu wop;
- sim_fpu_32to (&wop, op);
- boolean = sim_fpu_is_infinity (&wop);
- break;
- }
- case fmt_double:
- {
- sim_fpu wop;
- sim_fpu_64to (&wop, op);
- boolean = sim_fpu_is_infinity (&wop);
- break;
- }
- default:
- printf("DBG: TODO: unrecognised format (%s) for Infinity check\n",DOFMT(fmt));
- break;
- }
-
-#ifdef DEBUG
- printf("DBG: Infinity: returning %d for 0x%s (format = %s)\n",boolean,pr_addr(op),DOFMT(fmt));
-#endif /* DEBUG */
-
- return(boolean);
-}
-
-int
-Less(op1,op2,fmt)
- uword64 op1;
- uword64 op2;
- FP_formats fmt;
-{
- int boolean = 0;
-
- /* Argument checking already performed by the FPCOMPARE code */
-
-#ifdef DEBUG
- printf("DBG: Less: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
-#endif /* DEBUG */
-
- /* The format type should already have been checked: */
- switch (fmt) {
- case fmt_single:
- {
- sim_fpu wop1;
- sim_fpu wop2;
- sim_fpu_32to (&wop1, op1);
- sim_fpu_32to (&wop2, op2);
- boolean = sim_fpu_is_lt (&wop1, &wop2);
- break;
- }
- case fmt_double:
- {
- sim_fpu wop1;
- sim_fpu wop2;
- sim_fpu_64to (&wop1, op1);
- sim_fpu_64to (&wop2, op2);
- boolean = sim_fpu_is_lt (&wop1, &wop2);
- break;
- }
- default:
- fprintf (stderr, "Bad switch\n");
- abort ();
- }
-
-#ifdef DEBUG
- printf("DBG: Less: returning %d (format = %s)\n",boolean,DOFMT(fmt));
-#endif /* DEBUG */
-
- return(boolean);
-}
-
-int
-Equal(op1,op2,fmt)
- uword64 op1;
- uword64 op2;
- FP_formats fmt;
-{
- int boolean = 0;
-
- /* Argument checking already performed by the FPCOMPARE code */
-
-#ifdef DEBUG
- printf("DBG: Equal: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
-#endif /* DEBUG */
-
- /* The format type should already have been checked: */
- switch (fmt) {
- case fmt_single:
- {
- sim_fpu wop1;
- sim_fpu wop2;
- sim_fpu_32to (&wop1, op1);
- sim_fpu_32to (&wop2, op2);
- boolean = sim_fpu_is_eq (&wop1, &wop2);
- break;
- }
- case fmt_double:
- {
- sim_fpu wop1;
- sim_fpu wop2;
- sim_fpu_64to (&wop1, op1);
- sim_fpu_64to (&wop2, op2);
- boolean = sim_fpu_is_eq (&wop1, &wop2);
- break;
- }
- default:
- fprintf (stderr, "Bad switch\n");
- abort ();
- }
-
-#ifdef DEBUG
- printf("DBG: Equal: returning %d (format = %s)\n",boolean,DOFMT(fmt));
-#endif /* DEBUG */
-
- return(boolean);
-}
-
-uword64
-AbsoluteValue(op,fmt)
- uword64 op;
- FP_formats fmt;
-{
- uword64 result = 0;
-
-#ifdef DEBUG
- printf("DBG: AbsoluteValue: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
-#endif /* DEBUG */
-
- /* The format type should already have been checked: */
- switch (fmt) {
- case fmt_single:
- {
- sim_fpu wop;
- unsigned32 ans;
- sim_fpu_32to (&wop, op);
- sim_fpu_abs (&wop, &wop);
- sim_fpu_to32 (&ans, &wop);
- result = ans;
- break;
- }
- case fmt_double:
- {
- sim_fpu wop;
- unsigned64 ans;
- sim_fpu_64to (&wop, op);
- sim_fpu_abs (&wop, &wop);
- sim_fpu_to64 (&ans, &wop);
- result = ans;
- break;
- }
- default:
- fprintf (stderr, "Bad switch\n");
- abort ();
- }
-
- return(result);
-}
-
-uword64
-Negate(op,fmt)
- uword64 op;
- FP_formats fmt;
-{
- uword64 result = 0;
-
-#ifdef DEBUG
- printf("DBG: Negate: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
-#endif /* DEBUG */
-
- /* The format type should already have been checked: */
- switch (fmt) {
- case fmt_single:
- {
- sim_fpu wop;
- unsigned32 ans;
- sim_fpu_32to (&wop, op);
- sim_fpu_neg (&wop, &wop);
- sim_fpu_to32 (&ans, &wop);
- result = ans;
- break;
- }
- case fmt_double:
- {
- sim_fpu wop;
- unsigned64 ans;
- sim_fpu_64to (&wop, op);
- sim_fpu_neg (&wop, &wop);
- sim_fpu_to64 (&ans, &wop);
- result = ans;
- break;
- }
- default:
- fprintf (stderr, "Bad switch\n");
- abort ();
- }
-
- return(result);
-}
-
-uword64
-Add(op1,op2,fmt)
- uword64 op1;
- uword64 op2;
- FP_formats fmt;
-{
- uword64 result = 0;
-
-#ifdef DEBUG
- printf("DBG: Add: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
-#endif /* DEBUG */
-
- /* The registers must specify FPRs valid for operands of type
- "fmt". If they are not valid, the result is undefined. */
-
- /* The format type should already have been checked: */
- switch (fmt) {
- case fmt_single:
- {
- sim_fpu wop1;
- sim_fpu wop2;
- sim_fpu ans;
- unsigned32 res;
- sim_fpu_32to (&wop1, op1);
- sim_fpu_32to (&wop2, op2);
- sim_fpu_add (&ans, &wop1, &wop2);
- sim_fpu_to32 (&res, &ans);
- result = res;
- break;
- }
- case fmt_double:
- {
- sim_fpu wop1;
- sim_fpu wop2;
- sim_fpu ans;
- unsigned64 res;
- sim_fpu_64to (&wop1, op1);
- sim_fpu_64to (&wop2, op2);
- sim_fpu_add (&ans, &wop1, &wop2);
- sim_fpu_to64 (&res, &ans);
- result = res;
- break;
- }
- default:
- fprintf (stderr, "Bad switch\n");
- abort ();
- }
-
-#ifdef DEBUG
- printf("DBG: Add: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
-#endif /* DEBUG */
-
- return(result);
-}
-
-uword64
-Sub(op1,op2,fmt)
- uword64 op1;
- uword64 op2;
- FP_formats fmt;
-{
- uword64 result = 0;
-
-#ifdef DEBUG
- printf("DBG: Sub: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
-#endif /* DEBUG */
-
- /* The registers must specify FPRs valid for operands of type
- "fmt". If they are not valid, the result is undefined. */
-
- /* The format type should already have been checked: */
- switch (fmt) {
- case fmt_single:
- {
- sim_fpu wop1;
- sim_fpu wop2;
- sim_fpu ans;
- unsigned32 res;
- sim_fpu_32to (&wop1, op1);
- sim_fpu_32to (&wop2, op2);
- sim_fpu_sub (&ans, &wop1, &wop2);
- sim_fpu_to32 (&res, &ans);
- result = res;
- }
- break;
- case fmt_double:
- {
- sim_fpu wop1;
- sim_fpu wop2;
- sim_fpu ans;
- unsigned64 res;
- sim_fpu_64to (&wop1, op1);
- sim_fpu_64to (&wop2, op2);
- sim_fpu_sub (&ans, &wop1, &wop2);
- sim_fpu_to64 (&res, &ans);
- result = res;
- }
- break;
- default:
- fprintf (stderr, "Bad switch\n");
- abort ();
- }
-
-#ifdef DEBUG
- printf("DBG: Sub: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
-#endif /* DEBUG */
-
- return(result);
-}
-
-uword64
-Multiply(op1,op2,fmt)
- uword64 op1;
- uword64 op2;
- FP_formats fmt;
-{
- uword64 result = 0;
-
-#ifdef DEBUG
- printf("DBG: Multiply: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
-#endif /* DEBUG */
-
- /* The registers must specify FPRs valid for operands of type
- "fmt". If they are not valid, the result is undefined. */
-
- /* The format type should already have been checked: */
- switch (fmt) {
- case fmt_single:
- {
- sim_fpu wop1;
- sim_fpu wop2;
- sim_fpu ans;
- unsigned32 res;
- sim_fpu_32to (&wop1, op1);
- sim_fpu_32to (&wop2, op2);
- sim_fpu_mul (&ans, &wop1, &wop2);
- sim_fpu_to32 (&res, &ans);
- result = res;
- break;
- }
- case fmt_double:
- {
- sim_fpu wop1;
- sim_fpu wop2;
- sim_fpu ans;
- unsigned64 res;
- sim_fpu_64to (&wop1, op1);
- sim_fpu_64to (&wop2, op2);
- sim_fpu_mul (&ans, &wop1, &wop2);
- sim_fpu_to64 (&res, &ans);
- result = res;
- break;
- }
- default:
- fprintf (stderr, "Bad switch\n");
- abort ();
- }
-
-#ifdef DEBUG
- printf("DBG: Multiply: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
-#endif /* DEBUG */
-
- return(result);
-}
+/* This function implements what the MIPS32 and MIPS64 ISAs define as
+ "UNPREDICTABLE" behaviour.
-uword64
-Divide(op1,op2,fmt)
- uword64 op1;
- uword64 op2;
- FP_formats fmt;
-{
- uword64 result = 0;
-
-#ifdef DEBUG
- printf("DBG: Divide: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
-#endif /* DEBUG */
-
- /* The registers must specify FPRs valid for operands of type
- "fmt". If they are not valid, the result is undefined. */
-
- /* The format type should already have been checked: */
- switch (fmt) {
- case fmt_single:
- {
- sim_fpu wop1;
- sim_fpu wop2;
- sim_fpu ans;
- unsigned32 res;
- sim_fpu_32to (&wop1, op1);
- sim_fpu_32to (&wop2, op2);
- sim_fpu_div (&ans, &wop1, &wop2);
- sim_fpu_to32 (&res, &ans);
- result = res;
- break;
- }
- case fmt_double:
- {
- sim_fpu wop1;
- sim_fpu wop2;
- sim_fpu ans;
- unsigned64 res;
- sim_fpu_64to (&wop1, op1);
- sim_fpu_64to (&wop2, op2);
- sim_fpu_div (&ans, &wop1, &wop2);
- sim_fpu_to64 (&res, &ans);
- result = res;
- break;
- }
- default:
- fprintf (stderr, "Bad switch\n");
- abort ();
- }
-
-#ifdef DEBUG
- printf("DBG: Divide: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
-#endif /* DEBUG */
-
- return(result);
-}
-
-uword64 UNUSED
-Recip(op,fmt)
- uword64 op;
- FP_formats fmt;
-{
- uword64 result = 0;
-
-#ifdef DEBUG
- printf("DBG: Recip: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
-#endif /* DEBUG */
-
- /* The registers must specify FPRs valid for operands of type
- "fmt". If they are not valid, the result is undefined. */
-
- /* The format type should already have been checked: */
- switch (fmt) {
- case fmt_single:
- {
- sim_fpu wop;
- sim_fpu ans;
- unsigned32 res;
- sim_fpu_32to (&wop, op);
- sim_fpu_inv (&ans, &wop);
- sim_fpu_to32 (&res, &ans);
- result = res;
- break;
- }
- case fmt_double:
- {
- sim_fpu wop;
- sim_fpu ans;
- unsigned64 res;
- sim_fpu_64to (&wop, op);
- sim_fpu_inv (&ans, &wop);
- sim_fpu_to64 (&res, &ans);
- result = res;
- break;
- }
- default:
- fprintf (stderr, "Bad switch\n");
- abort ();
- }
-
-#ifdef DEBUG
- printf("DBG: Recip: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
-#endif /* DEBUG */
-
- return(result);
-}
-
-uword64
-SquareRoot(op,fmt)
- uword64 op;
- FP_formats fmt;
-{
- uword64 result = 0;
-
-#ifdef DEBUG
- printf("DBG: SquareRoot: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
-#endif /* DEBUG */
-
- /* The registers must specify FPRs valid for operands of type
- "fmt". If they are not valid, the result is undefined. */
-
- /* The format type should already have been checked: */
- switch (fmt) {
- case fmt_single:
- {
- sim_fpu wop;
- sim_fpu ans;
- unsigned32 res;
- sim_fpu_32to (&wop, op);
- sim_fpu_sqrt (&ans, &wop);
- sim_fpu_to32 (&res, &ans);
- result = res;
- break;
- }
- case fmt_double:
- {
- sim_fpu wop;
- sim_fpu ans;
- unsigned64 res;
- sim_fpu_64to (&wop, op);
- sim_fpu_sqrt (&ans, &wop);
- sim_fpu_to64 (&res, &ans);
- result = res;
- break;
- }
- default:
- fprintf (stderr, "Bad switch\n");
- abort ();
- }
-
-#ifdef DEBUG
- printf("DBG: SquareRoot: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
-#endif /* DEBUG */
-
- return(result);
-}
-
-#if 0
-uword64
-Max (uword64 op1,
- uword64 op2,
- FP_formats fmt)
-{
- int cmp;
- unsigned64 result;
-
-#ifdef DEBUG
- printf("DBG: Max: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
-#endif /* DEBUG */
-
- /* The registers must specify FPRs valid for operands of type
- "fmt". If they are not valid, the result is undefined. */
-
- /* The format type should already have been checked: */
- switch (fmt)
- {
- case fmt_single:
- {
- sim_fpu wop1;
- sim_fpu wop2;
- sim_fpu_32to (&wop1, op1);
- sim_fpu_32to (&wop2, op2);
- cmp = sim_fpu_cmp (&wop1, &wop2);
- break;
- }
- case fmt_double:
- {
- sim_fpu wop1;
- sim_fpu wop2;
- sim_fpu_64to (&wop1, op1);
- sim_fpu_64to (&wop2, op2);
- cmp = sim_fpu_cmp (&wop1, &wop2);
- break;
- }
- default:
- fprintf (stderr, "Bad switch\n");
- abort ();
- }
-
- switch (cmp)
- {
- case SIM_FPU_IS_SNAN:
- case SIM_FPU_IS_QNAN:
- result = op1;
- case SIM_FPU_IS_NINF:
- case SIM_FPU_IS_NNUMBER:
- case SIM_FPU_IS_NDENORM:
- case SIM_FPU_IS_NZERO:
- result = op2; /* op1 - op2 < 0 */
- case SIM_FPU_IS_PINF:
- case SIM_FPU_IS_PNUMBER:
- case SIM_FPU_IS_PDENORM:
- case SIM_FPU_IS_PZERO:
- result = op1; /* op1 - op2 > 0 */
- default:
- fprintf (stderr, "Bad switch\n");
- abort ();
- }
-
-#ifdef DEBUG
- printf("DBG: Max: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
-#endif /* DEBUG */
-
- return(result);
-}
-#endif
-
-#if 0
-uword64
-Min (uword64 op1,
- uword64 op2,
- FP_formats fmt)
-{
- int cmp;
- unsigned64 result;
-
-#ifdef DEBUG
- printf("DBG: Min: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
-#endif /* DEBUG */
-
- /* The registers must specify FPRs valid for operands of type
- "fmt". If they are not valid, the result is undefined. */
-
- /* The format type should already have been checked: */
- switch (fmt)
- {
- case fmt_single:
- {
- sim_fpu wop1;
- sim_fpu wop2;
- sim_fpu_32to (&wop1, op1);
- sim_fpu_32to (&wop2, op2);
- cmp = sim_fpu_cmp (&wop1, &wop2);
- break;
- }
- case fmt_double:
- {
- sim_fpu wop1;
- sim_fpu wop2;
- sim_fpu_64to (&wop1, op1);
- sim_fpu_64to (&wop2, op2);
- cmp = sim_fpu_cmp (&wop1, &wop2);
- break;
- }
- default:
- fprintf (stderr, "Bad switch\n");
- abort ();
- }
+ About UNPREDICTABLE behaviour they say: "UNPREDICTABLE results
+ may vary from processor implementation to processor implementation,
+ instruction to instruction, or as a function of time on the same
+ implementation or instruction. Software can never depend on results
+ that are UNPREDICTABLE. ..." (MIPS64 Architecture for Programmers
+ Volume II, The MIPS64 Instruction Set. MIPS Document MD00087 revision
+ 0.95, page 2.)
- switch (cmp)
- {
- case SIM_FPU_IS_SNAN:
- case SIM_FPU_IS_QNAN:
- result = op1;
- case SIM_FPU_IS_NINF:
- case SIM_FPU_IS_NNUMBER:
- case SIM_FPU_IS_NDENORM:
- case SIM_FPU_IS_NZERO:
- result = op1; /* op1 - op2 < 0 */
- case SIM_FPU_IS_PINF:
- case SIM_FPU_IS_PNUMBER:
- case SIM_FPU_IS_PDENORM:
- case SIM_FPU_IS_PZERO:
- result = op2; /* op1 - op2 > 0 */
- default:
- fprintf (stderr, "Bad switch\n");
- abort ();
- }
-
-#ifdef DEBUG
- printf("DBG: Min: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
-#endif /* DEBUG */
+ For UNPREDICTABLE behaviour, we print a message, if possible print
+ the offending instructions mips.igen instruction name (provided by
+ the caller), and stop the simulator.
- return(result);
-}
-#endif
-
-uword64
-convert (SIM_DESC sd,
- sim_cpu *cpu,
- address_word cia,
- int rm,
- uword64 op,
- FP_formats from,
- FP_formats to)
+ XXX FIXME: eventually, stopping the simulator should be made conditional
+ on a command-line option. */
+void
+unpredictable_action(sim_cpu *cpu, address_word cia)
{
- sim_fpu wop;
- sim_fpu_round round;
- unsigned32 result32;
- unsigned64 result64;
-
-#ifdef DEBUG
-#if 0 /* FIXME: doesn't compile */
- printf("DBG: Convert: mode %s : op 0x%s : from %s : to %s : (PC = 0x%s)\n",RMMODE(rm),pr_addr(op),DOFMT(from),DOFMT(to),pr_addr(IPC));
-#endif
-#endif /* DEBUG */
-
- switch (rm)
- {
- case FP_RM_NEAREST:
- /* Round result to nearest representable value. When two
- representable values are equally near, round to the value
- that has a least significant bit of zero (i.e. is even). */
- round = sim_fpu_round_near;
- break;
- case FP_RM_TOZERO:
- /* Round result to the value closest to, and not greater in
- magnitude than, the result. */
- round = sim_fpu_round_zero;
- break;
- case FP_RM_TOPINF:
- /* Round result to the value closest to, and not less than,
- the result. */
- round = sim_fpu_round_up;
- break;
-
- case FP_RM_TOMINF:
- /* Round result to the value closest to, and not greater than,
- the result. */
- round = sim_fpu_round_down;
- break;
- default:
- round = 0;
- fprintf (stderr, "Bad switch\n");
- abort ();
- }
-
- /* Convert the input to sim_fpu internal format */
- switch (from)
- {
- case fmt_double:
- sim_fpu_64to (&wop, op);
- break;
- case fmt_single:
- sim_fpu_32to (&wop, op);
- break;
- case fmt_word:
- sim_fpu_i32to (&wop, op, round);
- break;
- case fmt_long:
- sim_fpu_i64to (&wop, op, round);
- break;
- default:
- fprintf (stderr, "Bad switch\n");
- abort ();
- }
-
- /* Convert sim_fpu format into the output */
- /* The value WOP is converted to the destination format, rounding
- using mode RM. When the destination is a fixed-point format, then
- a source value of Infinity, NaN or one which would round to an
- integer outside the fixed point range then an IEEE Invalid
- Operation condition is raised. */
- switch (to)
- {
- case fmt_single:
- sim_fpu_round_32 (&wop, round, 0);
- sim_fpu_to32 (&result32, &wop);
- result64 = result32;
- break;
- case fmt_double:
- sim_fpu_round_64 (&wop, round, 0);
- sim_fpu_to64 (&result64, &wop);
- break;
- case fmt_word:
- sim_fpu_to32i (&result32, &wop, round);
- result64 = result32;
- break;
- case fmt_long:
- sim_fpu_to64i (&result64, &wop, round);
- break;
- default:
- result64 = 0;
- fprintf (stderr, "Bad switch\n");
- abort ();
- }
-
-#ifdef DEBUG
- printf("DBG: Convert: returning 0x%s (to format = %s)\n",pr_addr(result64),DOFMT(to));
-#endif /* DEBUG */
+ SIM_DESC sd = CPU_STATE(cpu);
- return(result64);
+ sim_io_eprintf(sd, "UNPREDICTABLE: PC = 0x%s\n", pr_addr (cia));
+ sim_engine_halt (SD, CPU, NULL, cia, sim_stopped, SIM_SIGABRT);
}
diff --git a/sim/mips/mips.igen b/sim/mips/mips.igen
index b5930d58c18..cd96766d885 100644
--- a/sim/mips/mips.igen
+++ b/sim/mips/mips.igen
@@ -1,9 +1,5 @@
// -*- C -*-
//
-// In mips.igen, the semantics for many of the instructions were created
-// using code generated by gencode. Those semantic segments could be
-// greatly simplified.
-//
// <insn> ::=
// <insn-word> { "+" <insn-word> }
// ":" <format-name>
@@ -48,6 +44,8 @@
:model:::mipsIII:mips4000:
:model:::mipsIV:mips8000:
:model:::mipsV:mipsisaV:
+:model:::mips32:mipsisa32:
+:model:::mips64:mipsisa64:
// Vendor ISAs:
//
@@ -109,8 +107,107 @@
return CIA + 8;
}
+
+// Helper:
+//
+// Calculate an effective address given a base and an offset.
+//
+
+:function:::address_word:loadstore_ea:address_word base, address_word offset
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips32:
+*vr4100:
+*vr5000:
+*r3900:
+{
+ return base + offset;
+}
+
+:function:::address_word:loadstore_ea:address_word base, address_word offset
+*mips64:
+{
+#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
+ address computations as defined in the MIPS64 Architecture for
+ Programmers Volume III, Revision 0.95, section 4.9. */
+ if ((SR & (status_KSU_mask|status_EXL|status_ERL|status_UX))
+ == (ksu_user << status_KSU_shift))
+ return (address_word)((signed32)base + (signed32)offset);
+#endif
+ return base + offset;
+}
+
+
+// Helper:
+//
+// Check that a 32-bit register value is properly sign-extended.
+// (See NotWordValue in ISA spec.)
+//
+
+:function:::int:not_word_value:unsigned_word value
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*vr4100:
+*vr5000:
+*r3900:
+{
+ /* For historical simulator compatibility (until documentation is
+ found that makes these operations unpredictable on some of these
+ architectures), this check never returns true. */
+ return 0;
+}
+
+:function:::int:not_word_value:unsigned_word value
+*mips32:
+{
+ /* On MIPS32, since registers are 32-bits, there's no check to be done. */
+ return 0;
+}
+
+:function:::int:not_word_value:unsigned_word value
+*mips64:
+{
+ return ((value >> 32) != (value & 0x80000000 ? 0xFFFFFFFF : 0));
+}
+
+
+// Helper:
+//
+// Handle UNPREDICTABLE operation behaviour. The goal here is to prevent
+// theoretically portable code which invokes non-portable behaviour from
+// running with no indication of the portability issue.
+// (See definition of UNPREDICTABLE in ISA spec.)
+//
+
+:function:::void:unpredictable:
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*vr4100:
+*vr5000:
+*r3900:
+{
+}
+
+:function:::void:unpredictable:
+*mips32:
+*mips64:
+{
+ unpredictable_action (CPU, CIA);
+}
+
+
// Helper:
-//
+//
// Check that an access to a HI/LO register meets timing requirements
//
// The following requirements exist:
@@ -128,7 +225,7 @@
sim_engine_abort (SD, CPU, CIA, "HILO: %s: %s at 0x%08lx too close to MF at 0x%08lx\n",
itable[MY_INDEX].name,
new, (long) CIA,
- (long) history->mf.cia);
+ (long) history->mf.cia);
return 0;
}
return 1;
@@ -151,6 +248,8 @@
}
:function:::int:check_mt_hilo:hilo_history *history
+*mips32:
+*mips64:
*r3900:
{
signed64 time = sim_events_time (SD);
@@ -166,6 +265,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -186,7 +287,7 @@
itable[MY_INDEX].name,
(long) CIA,
(long) history->op.cia,
- (long) peer->mt.cia);
+ (long) peer->mt.cia);
ok = 0;
}
history->mf.timestamp = time;
@@ -218,6 +319,8 @@
// The r3900 mult and multu insns _can_ be exectuted immediatly after
// a mf{hi,lo}
:function:::int:check_mult_hilo:hilo_history *hi, hilo_history *lo
+*mips32:
+*mips64:
*r3900:
{
/* FIXME: could record the fact that a stall occured if we want */
@@ -236,6 +339,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -252,9 +357,9 @@
// Helper:
-//
+//
// Check that the 64-bit instruction can currently be used, and signal
-// an ReservedInstruction exception if not.
+// a ReservedInstruction exception if not.
//
:function:::void:check_u64:instruction_word insn
@@ -264,16 +369,24 @@
*vr4100:
*vr5000:
{
- // On mips64, if UserMode check SR:PX & SR:UX bits.
// The check should be similar to mips64 for any with PX/UX bit equivalents.
}
+:function:::void:check_u64:instruction_word insn
+*mips64:
+{
+#if 0 /* XXX FIXME: enable this only after some additional testing. */
+ if (UserMode && (SR & (status_UX|status_PX)) == 0)
+ SignalException (ReservedInstruction, insn);
+#endif
+}
+
//
// MIPS Architecture:
//
-// CPU Instruction Set (mipsI - mipsV)
+// CPU Instruction Set (mipsI - mipsV, mips32, mips64)
//
@@ -285,10 +398,14 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
+ if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+ Unpredictable ();
TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
{
ALU32_BEGIN (GPR[RS]);
@@ -307,10 +424,14 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
+ if (NotWordValue (GPR[RS]))
+ Unpredictable ();
TRACE_ALU_INPUT2 (GPR[RS], EXTEND16 (IMMEDIATE));
{
ALU32_BEGIN (GPR[RS]);
@@ -324,6 +445,8 @@
:function:::void:do_addiu:int rs, int rt, unsigned16 immediate
{
+ if (NotWordValue (GPR[rs]))
+ Unpredictable ();
TRACE_ALU_INPUT2 (GPR[rs], EXTEND16 (immediate));
GPR[rt] = EXTEND32 (GPR[rs] + EXTEND16 (immediate));
TRACE_ALU_RESULT (GPR[rt]);
@@ -336,6 +459,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -347,6 +472,8 @@
:function:::void:do_addu:int rs, int rt, int rd
{
+ if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+ Unpredictable ();
TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
GPR[rd] = EXTEND32 (GPR[rs] + GPR[rt]);
TRACE_ALU_RESULT (GPR[rd]);
@@ -359,6 +486,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -382,6 +511,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -392,12 +523,14 @@
001100,5.RS,5.RT,16.IMMEDIATE:NORMAL:32::ANDI
-"and r<RT>, r<RS>, <IMMEDIATE>"
+"andi r<RT>, r<RS>, %#lx<IMMEDIATE>"
*mipsI:
*mipsII:
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -416,6 +549,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -437,6 +572,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -461,6 +598,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -483,12 +622,16 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
address_word offset = EXTEND16 (OFFSET) << 2;
check_branch_bug ();
+ if (RS == 31)
+ Unpredictable ();
RA = (CIA + 8);
if ((signed_word) GPR[RS] >= 0)
{
@@ -505,12 +648,16 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
address_word offset = EXTEND16 (OFFSET) << 2;
check_branch_bug ();
+ if (RS == 31)
+ Unpredictable ();
RA = (CIA + 8);
/* NOTE: The branch occurs AFTER the next instruction has been
executed */
@@ -531,6 +678,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -555,6 +704,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -576,6 +727,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -602,6 +755,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -625,6 +780,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -649,6 +806,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -671,12 +830,16 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
address_word offset = EXTEND16 (OFFSET) << 2;
check_branch_bug ();
+ if (RS == 31)
+ Unpredictable ();
RA = (CIA + 8);
/* NOTE: The branch occurs AFTER the next instruction has been
executed */
@@ -695,12 +858,16 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
address_word offset = EXTEND16 (OFFSET) << 2;
check_branch_bug ();
+ if (RS == 31)
+ Unpredictable ();
RA = (CIA + 8);
if ((signed_word) GPR[RS] < 0)
{
@@ -719,6 +886,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -745,6 +914,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -766,6 +937,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -784,12 +957,14 @@
000000,20.CODE,001101:SPECIAL:32::BREAK
-"break <CODE>"
+"break %#lx<CODE>"
*mipsI:
*mipsII:
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -809,24 +984,73 @@
PC = cia - 4; /* reference the branch instruction */
else
PC = cia;
- SignalException(BreakPoint, instruction_0);
+ SignalException (BreakPoint, instruction_0);
}
else
{
- /* If we get this far, we're not an instruction reserved by the sim. Raise
+ /* If we get this far, we're not an instruction reserved by the sim. Raise
the exception. */
- SignalException(BreakPoint, instruction_0);
+ SignalException (BreakPoint, instruction_0);
}
}
+011100,5.RS,5.RT,5.RD,00000,100001:SPECIAL2:32::CLO
+"clo r<RD>, r<RS>"
+*mips32:
+*mips64:
+{
+ unsigned32 temp = GPR[RS];
+ unsigned32 i, mask;
+ if (RT != RD)
+ Unpredictable ();
+ if (NotWordValue (GPR[RS]))
+ Unpredictable ();
+ TRACE_ALU_INPUT1 (GPR[RS]);
+ for (mask = ((unsigned32)1<<31), i = 0; i < 32; ++i)
+ {
+ if ((temp & mask) == 0)
+ break;
+ mask >>= 1;
+ }
+ GPR[RD] = EXTEND32 (i);
+ TRACE_ALU_RESULT (GPR[RD]);
+}
+
+
+
+011100,5.RS,5.RT,5.RD,00000,100000:SPECIAL2:32::CLZ
+"clz r<RD>, r<RS>"
+*mips32:
+*mips64:
+{
+ unsigned32 temp = GPR[RS];
+ unsigned32 i, mask;
+ if (RT != RD)
+ Unpredictable ();
+ if (NotWordValue (GPR[RS]))
+ Unpredictable ();
+ TRACE_ALU_INPUT1 (GPR[RS]);
+ for (mask = ((unsigned32)1<<31), i = 0; i < 32; ++i)
+ {
+ if ((temp & mask) != 0)
+ break;
+ mask >>= 1;
+ }
+ GPR[RD] = EXTEND32 (i);
+ TRACE_ALU_RESULT (GPR[RD]);
+}
+
+
+
000000,5.RS,5.RT,5.RD,00000,101100:SPECIAL:64::DADD
"dadd r<RD>, r<RS>, r<RT>"
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -847,6 +1071,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -874,6 +1099,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -895,6 +1121,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -904,6 +1131,52 @@
+011100,5.RS,5.RT,5.RD,00000,100101:SPECIAL2:64::DCLO
+"dclo r<RD>, r<RS>"
+*mips64:
+{
+ unsigned64 temp = GPR[RS];
+ unsigned32 i;
+ unsigned64 mask;
+ check_u64 (SD_, instruction_0);
+ if (RT != RD)
+ Unpredictable ();
+ TRACE_ALU_INPUT1 (GPR[RS]);
+ for (mask = ((unsigned64)1<<63), i = 0; i < 64; ++i)
+ {
+ if ((temp & mask) == 0)
+ break;
+ mask >>= 1;
+ }
+ GPR[RD] = EXTEND32 (i);
+ TRACE_ALU_RESULT (GPR[RD]);
+}
+
+
+
+011100,5.RS,5.RT,5.RD,00000,100100:SPECIAL2:64::DCLZ
+"dclz r<RD>, r<RS>"
+*mips64:
+{
+ unsigned64 temp = GPR[RS];
+ unsigned32 i;
+ unsigned64 mask;
+ check_u64 (SD_, instruction_0);
+ if (RT != RD)
+ Unpredictable ();
+ TRACE_ALU_INPUT1 (GPR[RS]);
+ for (mask = ((unsigned64)1<<63), i = 0; i < 64; ++i)
+ {
+ if ((temp & mask) != 0)
+ break;
+ mask >>= 1;
+ }
+ GPR[RD] = EXTEND32 (i);
+ TRACE_ALU_RESULT (GPR[RD]);
+}
+
+
+
:function:::void:do_ddiv:int rs, int rt
{
check_div_hilo (SD_, HIHISTORY, LOHISTORY);
@@ -939,6 +1212,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -978,6 +1252,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -1020,6 +1295,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -1057,6 +1334,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -1080,7 +1359,7 @@
unsigned64 op2 = GPR[rt];
check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
- /* make signed multiply unsigned */
+ /* make signed multiply unsigned */
sign = 0;
if (signed_p)
{
@@ -1136,6 +1415,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
{
check_u64 (SD_, instruction_0);
@@ -1163,6 +1443,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
{
check_u64 (SD_, instruction_0);
@@ -1190,6 +1471,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -1203,6 +1485,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -1226,6 +1509,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -1246,6 +1530,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -1259,6 +1544,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -1283,6 +1569,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -1303,6 +1590,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -1316,6 +1604,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -1342,6 +1631,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -1355,6 +1645,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -1381,6 +1672,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -1396,6 +1688,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -1414,6 +1708,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -1433,6 +1729,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -1450,6 +1748,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -1469,7 +1769,7 @@
unsigned64 memval;
address_word vaddr;
- vaddr = base + offset;
+ vaddr = loadstore_ea (SD_, base, offset);
if ((vaddr & access) != 0)
{
SIM_CORE_SIGNAL (SD, STATE_CPU (SD, 0), cia, read_map, access+1, vaddr, read_transfer, sim_core_unaligned_signal);
@@ -1497,7 +1797,7 @@
unsigned_word lhs_mask;
unsigned_word temp;
- vaddr = base + offset;
+ vaddr = loadstore_ea (SD_, base, offset);
AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached, isTARGET, isREAL);
paddr = (paddr ^ (reverseendian & mask));
if (BigEndianMem == 0)
@@ -1548,7 +1848,7 @@
unsigned64 memval;
address_word vaddr;
- vaddr = base + offset;
+ vaddr = loadstore_ea (SD_, base, offset);
AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached, isTARGET, isREAL);
/* NOTE: SPEC is wrong, has `BigEndianMem == 0' not `BigEndianMem != 0' */
paddr = (paddr ^ (reverseendian & mask));
@@ -1575,6 +1875,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -1590,6 +1892,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -1603,6 +1907,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -1617,6 +1922,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -1632,6 +1939,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -1645,6 +1953,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -1660,6 +1969,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -1675,6 +1986,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -1689,15 +2002,15 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
{
- unsigned32 instruction = instruction_0;
- signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16);
- int destreg = ((instruction >> 16) & 0x0000001F);
- signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)];
+ address_word base = GPR[BASE];
+ address_word offset = EXTEND16 (OFFSET);
{
- address_word vaddr = ((unsigned64)op1 + offset);
+ address_word vaddr = loadstore_ea (SD_, base, offset);
address_word paddr;
int uncached;
if ((vaddr & 3) != 0)
@@ -1718,7 +2031,7 @@
paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));
LoadMemory(&memval,&memval1,uncached,AccessLength_WORD,paddr,vaddr,isDATA,isREAL);
byte = ((vaddr & mask) ^ (bigend << shift));
- GPR[destreg] = (SIGNEXTEND(((memval >> (8 * byte)) & 0xFFFFFFFF),32));
+ GPR[RT] = EXTEND32 (memval >> (8 * byte));
LLBIT = 1;
}
}
@@ -1731,16 +2044,15 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
- unsigned32 instruction = instruction_0;
- signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16);
- int destreg = ((instruction >> 16) & 0x0000001F);
- signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)];
+ address_word base = GPR[BASE];
+ address_word offset = EXTEND16 (OFFSET);
check_u64 (SD_, instruction_0);
{
- address_word vaddr = ((unsigned64)op1 + offset);
+ address_word vaddr = loadstore_ea (SD_, base, offset);
address_word paddr;
int uncached;
if ((vaddr & 7) != 0)
@@ -1754,7 +2066,7 @@
unsigned64 memval = 0;
unsigned64 memval1 = 0;
LoadMemory(&memval,&memval1,uncached,AccessLength_DOUBLEWORD,paddr,vaddr,isDATA,isREAL);
- GPR[destreg] = memval;
+ GPR[RT] = memval;
LLBIT = 1;
}
}
@@ -1763,12 +2075,14 @@
001111,00000,5.RT,16.IMMEDIATE:NORMAL:32::LUI
-"lui r<RT>, <IMMEDIATE>"
+"lui r<RT>, %#lx<IMMEDIATE>"
*mipsI:
*mipsII:
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -1786,6 +2100,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -1801,6 +2117,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -1816,6 +2134,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -1831,6 +2151,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -1844,6 +2166,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -1852,6 +2175,44 @@
}
+
+011100,5.RS,5.RT,00000,00000,000000:SPECIAL2:32::MADD
+"madd r<RS>, r<RT>"
+*mips32:
+*mips64:
+{
+ signed64 temp;
+ check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
+ if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
+ temp = (U8_4 (VL4_8 (HI), VL4_8 (LO))
+ + ((signed64) EXTEND32 (GPR[RT]) * (signed64) EXTEND32 (GPR[RS])));
+ LO = EXTEND32 (temp);
+ HI = EXTEND32 (VH4_8 (temp));
+ TRACE_ALU_RESULT2 (HI, LO);
+}
+
+
+
+011100,5.RS,5.RT,00000,00000,000001:SPECIAL2:32::MADDU
+"maddu r<RS>, r<RT>"
+*mips32:
+*mips64:
+{
+ unsigned64 temp;
+ check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
+ if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
+ temp = (U8_4 (VL4_8 (HI), VL4_8 (LO))
+ + ((unsigned64) VL4_8 (GPR[RS]) * (unsigned64) VL4_8 (GPR[RT])));
+ LO = EXTEND32 (temp);
+ HI = EXTEND32 (VH4_8 (temp));
+ TRACE_ALU_RESULT2 (HI, LO);
+}
+
+
:function:::void:do_mfhi:int rd
{
check_mf_hilo (SD_, HIHISTORY, LOHISTORY);
@@ -1867,6 +2228,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -1891,6 +2254,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -1904,6 +2269,8 @@
"movn r<RD>, r<RS>, r<RT>"
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr5000:
{
if (GPR[RT] != 0)
@@ -1916,6 +2283,8 @@
"movz r<RD>, r<RS>, r<RT>"
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr5000:
{
if (GPR[RT] == 0)
@@ -1924,6 +2293,44 @@
+011100,5.RS,5.RT,00000,00000,000100:SPECIAL2:32::MSUB
+"msub r<RS>, r<RT>"
+*mips32:
+*mips64:
+{
+ signed64 temp;
+ check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
+ if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
+ temp = (U8_4 (VL4_8 (HI), VL4_8 (LO))
+ - ((signed64) EXTEND32 (GPR[RT]) * (signed64) EXTEND32 (GPR[RS])));
+ LO = EXTEND32 (temp);
+ HI = EXTEND32 (VH4_8 (temp));
+ TRACE_ALU_RESULT2 (HI, LO);
+}
+
+
+
+011100,5.RS,5.RT,00000,00000,000101:SPECIAL2:32::MSUBU
+"msubu r<RS>, r<RT>"
+*mips32:
+*mips64:
+{
+ unsigned64 temp;
+ check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
+ if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
+ temp = (U8_4 (VL4_8 (HI), VL4_8 (LO))
+ - ((unsigned64) VL4_8 (GPR[RS]) * (unsigned64) VL4_8 (GPR[RT])));
+ LO = EXTEND32 (temp);
+ HI = EXTEND32 (VH4_8 (temp));
+ TRACE_ALU_RESULT2 (HI, LO);
+}
+
+
+
000000,5.RS,000000000000000,010001:SPECIAL:32::MTHI
"mthi r<RS>"
*mipsI:
@@ -1931,6 +2338,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -1948,6 +2357,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -1958,10 +2369,29 @@
+011100,5.RS,5.RT,5.RD,00000,000010:SPECIAL2:32::MUL
+"mul r<RD>, r<RS>, r<RT>"
+*mips32:
+*mips64:
+{
+ signed64 prod;
+ if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
+ prod = (((signed64)(signed32) GPR[RS])
+ * ((signed64)(signed32) GPR[RT]));
+ GPR[RD] = EXTEND32 (VL4_8 (prod));
+ TRACE_ALU_RESULT (GPR[RD]);
+}
+
+
+
:function:::void:do_mult:int rs, int rt, int rd
{
signed64 prod;
check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
+ if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+ Unpredictable ();
TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
prod = (((signed64)(signed32) GPR[rs])
* ((signed64)(signed32) GPR[rt]));
@@ -1979,6 +2409,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
{
do_mult (SD_, RS, RT, 0);
@@ -1999,6 +2431,8 @@
{
unsigned64 prod;
check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
+ if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+ Unpredictable ();
TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
prod = (((unsigned64)(unsigned32) GPR[rs])
* ((unsigned64)(unsigned32) GPR[rt]));
@@ -2016,6 +2450,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
{
do_multu (SD_, RS, RT, 0);
@@ -2045,6 +2481,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -2067,6 +2505,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -2084,12 +2524,14 @@
}
001101,5.RS,5.RT,16.IMMEDIATE:NORMAL:32::ORI
-"ori r<RT>, r<RS>, <IMMEDIATE>"
+"ori r<RT>, r<RS>, %#lx<IMMEDIATE>"
*mipsI:
*mipsII:
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -2102,19 +2544,19 @@
"pref <HINT>, <OFFSET>(r<BASE>)"
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr5000:
{
- unsigned32 instruction = instruction_0;
- signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16);
- int hint = ((instruction >> 16) & 0x0000001F);
- signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)];
+ address_word base = GPR[BASE];
+ address_word offset = EXTEND16 (OFFSET);
{
- address_word vaddr = ((unsigned64)op1 + offset);
+ address_word vaddr = loadstore_ea (SD_, base, offset);
address_word paddr;
int uncached;
{
if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))
- Prefetch(uncached,paddr,vaddr,isDATA,hint);
+ Prefetch(uncached,paddr,vaddr,isDATA,HINT);
}
}
}
@@ -2131,7 +2573,7 @@
unsigned64 memval;
address_word vaddr;
- vaddr = base + offset;
+ vaddr = loadstore_ea (SD_, base, offset);
if ((vaddr & access) != 0)
{
SIM_CORE_SIGNAL (SD, STATE_CPU(SD, 0), cia, read_map, access+1, vaddr, write_transfer, sim_core_unaligned_signal);
@@ -2157,7 +2599,7 @@
int nr_lhs_bits;
int nr_rhs_bits;
- vaddr = base + offset;
+ vaddr = loadstore_ea (SD_, base, offset);
AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached, isTARGET, isREAL);
paddr = (paddr ^ (reverseendian & mask));
if (BigEndianMem == 0)
@@ -2199,7 +2641,7 @@
unsigned64 memval;
address_word vaddr;
- vaddr = base + offset;
+ vaddr = loadstore_ea (SD_, base, offset);
AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached, isTARGET, isREAL);
paddr = (paddr ^ (reverseendian & mask));
if (BigEndianMem != 0)
@@ -2217,6 +2659,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -2231,15 +2675,16 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
{
unsigned32 instruction = instruction_0;
- signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16);
- signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)];
- signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)];
+ address_word base = GPR[BASE];
+ address_word offset = EXTEND16 (OFFSET);
{
- address_word vaddr = ((unsigned64)op1 + offset);
+ address_word vaddr = loadstore_ea (SD_, base, offset);
address_word paddr;
int uncached;
if ((vaddr & 3) != 0)
@@ -2256,12 +2701,12 @@
unsigned int byte;
paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2)));
byte = ((vaddr & mask) ^ (BigEndianCPU << 2));
- memval = ((unsigned64) op2 << (8 * byte));
+ memval = ((unsigned64) GPR[RT] << (8 * byte));
if (LLBIT)
{
StoreMemory(uncached,AccessLength_WORD,memval,memval1,paddr,vaddr,isREAL);
}
- GPR[(instruction >> 16) & 0x0000001F] = LLBIT;
+ GPR[RT] = LLBIT;
}
}
}
@@ -2273,16 +2718,15 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
- unsigned32 instruction = instruction_0;
- signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16);
- signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)];
- signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)];
+ address_word base = GPR[BASE];
+ address_word offset = EXTEND16 (OFFSET);
check_u64 (SD_, instruction_0);
{
- address_word vaddr = ((unsigned64)op1 + offset);
+ address_word vaddr = loadstore_ea (SD_, base, offset);
address_word paddr;
int uncached;
if ((vaddr & 7) != 0)
@@ -2295,12 +2739,12 @@
{
unsigned64 memval = 0;
unsigned64 memval1 = 0;
- memval = op2;
+ memval = GPR[RT];
if (LLBIT)
{
StoreMemory(uncached,AccessLength_DOUBLEWORD,memval,memval1,paddr,vaddr,isREAL);
}
- GPR[(instruction >> 16) & 0x0000001F] = LLBIT;
+ GPR[RT] = LLBIT;
}
}
}
@@ -2312,6 +2756,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -2326,6 +2771,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
{
@@ -2338,6 +2785,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -2351,6 +2799,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
{
@@ -2366,6 +2815,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -2382,7 +2833,7 @@
TRACE_ALU_RESULT (GPR[rd]);
}
-000000,00000,5.RT,5.RD,5.SHIFT,000000:SPECIAL:32::SLL
+000000,00000,5.RT,5.RD,5.SHIFT,000000:SPECIAL:32::SLLa
"nop":RD == 0 && RT == 0 && SHIFT == 0
"sll r<RD>, r<RT>, <SHIFT>"
*mipsI:
@@ -2400,6 +2851,19 @@
do_sll (SD_, RT, RD, SHIFT);
}
+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
+"sll r<RD>, r<RT>, <SHIFT>"
+*mips32:
+*mips64:
+{
+ /* 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);
+}
+
:function:::void:do_sllv:int rs, int rt, int rd
{
@@ -2417,6 +2881,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -2439,6 +2905,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -2461,6 +2929,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -2483,6 +2953,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -2506,6 +2978,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -2517,6 +2991,8 @@
:function:::void:do_sra:int rt, int rd, int shift
{
signed32 temp = (signed32) GPR[rt] >> shift;
+ if (NotWordValue (GPR[rt]))
+ Unpredictable ();
TRACE_ALU_INPUT2 (GPR[rt], shift);
GPR[rd] = EXTEND32 (temp);
TRACE_ALU_RESULT (GPR[rd]);
@@ -2529,6 +3005,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -2542,6 +3020,8 @@
{
int s = MASKED (GPR[rs], 4, 0);
signed32 temp = (signed32) GPR[rt] >> s;
+ if (NotWordValue (GPR[rt]))
+ Unpredictable ();
TRACE_ALU_INPUT2 (GPR[rt], s);
GPR[rd] = EXTEND32 (temp);
TRACE_ALU_RESULT (GPR[rd]);
@@ -2554,6 +3034,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -2566,6 +3048,8 @@
:function:::void:do_srl:int rt, int rd, int shift
{
unsigned32 temp = (unsigned32) GPR[rt] >> shift;
+ if (NotWordValue (GPR[rt]))
+ Unpredictable ();
TRACE_ALU_INPUT2 (GPR[rt], shift);
GPR[rd] = EXTEND32 (temp);
TRACE_ALU_RESULT (GPR[rd]);
@@ -2578,6 +3062,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -2590,6 +3076,8 @@
{
int s = MASKED (GPR[rs], 4, 0);
unsigned32 temp = (unsigned32) GPR[rt] >> s;
+ if (NotWordValue (GPR[rt]))
+ Unpredictable ();
TRACE_ALU_INPUT2 (GPR[rt], s);
GPR[rd] = EXTEND32 (temp);
TRACE_ALU_RESULT (GPR[rd]);
@@ -2602,6 +3090,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -2617,10 +3107,14 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
+ if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+ Unpredictable ();
TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
{
ALU32_BEGIN (GPR[RS]);
@@ -2633,6 +3127,8 @@
:function:::void:do_subu:int rs, int rt, int rd
{
+ if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+ Unpredictable ();
TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
GPR[rd] = EXTEND32 (GPR[rs] - GPR[rt]);
TRACE_ALU_RESULT (GPR[rd]);
@@ -2645,6 +3141,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -2660,6 +3158,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*r3900:
*vr5000:
@@ -2675,6 +3175,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -2690,6 +3192,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -2705,6 +3209,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -2720,6 +3226,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -2729,17 +3237,19 @@
000000,20.CODE,001100:SPECIAL:32::SYSCALL
-"syscall <CODE>"
+"syscall %#lx<CODE>"
*mipsI:
*mipsII:
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- SignalException(SystemCall, instruction_0);
+ SignalException (SystemCall, instruction_0);
}
@@ -2749,11 +3259,13 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
{
if ((signed_word) GPR[RS] == (signed_word) GPR[RT])
- SignalException(Trap, instruction_0);
+ SignalException (Trap, instruction_0);
}
@@ -2763,11 +3275,13 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
{
if ((signed_word) GPR[RS] == (signed_word) EXTEND16 (IMMEDIATE))
- SignalException(Trap, instruction_0);
+ SignalException (Trap, instruction_0);
}
@@ -2777,11 +3291,13 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
{
if ((signed_word) GPR[RS] >= (signed_word) GPR[RT])
- SignalException(Trap, instruction_0);
+ SignalException (Trap, instruction_0);
}
@@ -2791,11 +3307,13 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
{
if ((signed_word) GPR[RS] >= (signed_word) EXTEND16 (IMMEDIATE))
- SignalException(Trap, instruction_0);
+ SignalException (Trap, instruction_0);
}
@@ -2805,11 +3323,13 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
{
if ((unsigned_word) GPR[RS] >= (unsigned_word) EXTEND16 (IMMEDIATE))
- SignalException(Trap, instruction_0);
+ SignalException (Trap, instruction_0);
}
@@ -2819,11 +3339,13 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
{
if ((unsigned_word) GPR[RS] >= (unsigned_word) GPR[RT])
- SignalException(Trap, instruction_0);
+ SignalException (Trap, instruction_0);
}
@@ -2833,11 +3355,13 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
{
if ((signed_word) GPR[RS] < (signed_word) GPR[RT])
- SignalException(Trap, instruction_0);
+ SignalException (Trap, instruction_0);
}
@@ -2847,11 +3371,13 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
{
if ((signed_word) GPR[RS] < (signed_word) EXTEND16 (IMMEDIATE))
- SignalException(Trap, instruction_0);
+ SignalException (Trap, instruction_0);
}
@@ -2861,11 +3387,13 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
{
if ((unsigned_word) GPR[RS] < (unsigned_word) EXTEND16 (IMMEDIATE))
- SignalException(Trap, instruction_0);
+ SignalException (Trap, instruction_0);
}
@@ -2875,11 +3403,13 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
{
if ((unsigned_word) GPR[RS] < (unsigned_word) GPR[RT])
- SignalException(Trap, instruction_0);
+ SignalException (Trap, instruction_0);
}
@@ -2889,11 +3419,13 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
{
if ((signed_word) GPR[RS] != (signed_word) GPR[RT])
- SignalException(Trap, instruction_0);
+ SignalException (Trap, instruction_0);
}
@@ -2903,11 +3435,13 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
{
if ((signed_word) GPR[RS] != (signed_word) EXTEND16 (IMMEDIATE))
- SignalException(Trap, instruction_0);
+ SignalException (Trap, instruction_0);
}
@@ -2925,6 +3459,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -2941,12 +3477,14 @@
}
001110,5.RS,5.RT,16.IMMEDIATE:NORMAL:32::XORI
-"xori r<RT>, r<RS>, <IMMEDIATE>"
+"xori r<RT>, r<RS>, %#lx<IMMEDIATE>"
*mipsI:
*mipsII:
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -3024,26 +3562,80 @@
}
}
+
+// Helpers:
+//
+// Check that the given FPU format is usable, and signal a
+// ReservedInstruction exception if not.
+//
+
+// check_fmt checks that the format is single or double.
+:function:::void:check_fmt:int fmt, instruction_word insn
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips32:
+*mips64:
+*vr4100:
+*vr5000:
+*r3900:
+{
+ if ((fmt != fmt_single) && (fmt != fmt_double))
+ SignalException (ReservedInstruction, insn);
+}
+
+// check_fmt_p checks that the format is single, double, or paired single.
+:function:::void:check_fmt_p:int fmt, instruction_word insn
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mips32:
+*vr4100:
+*vr5000:
+*r3900:
+{
+ /* None of these ISAs support Paired Single, so just fall back to
+ the single/double check. */
+ check_fmt (SD_, fmt, insn);
+}
+
+:function:::void:check_fmt_p:int fmt, instruction_word insn
+*mipsV:
+*mips64:
+{
+#if 0 /* XXX FIXME: FP code doesn't yet support paired single ops. */
+ if ((fmt != fmt_single) && (fmt != fmt_double)
+ && (fmt != fmt_ps || (UserMode && (SR & (status_UX|status_PX)) == 0)))
+ SignalException (ReservedInstruction, insn);
+#else
+ check_fmt (SD_, fmt, insn);
+#endif
+}
+
+
// Helper:
-//
+//
// Check that the FPU is currently usable, and signal a CoProcessorUnusable
// exception if not.
//
:function:::void:check_fpu:
-*mipsI:
+*mipsI:
*mipsII:
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
-#if 0 /* XXX FIXME: For now, never treat the FPU as disabled. */
if (! COP_Usable (1))
SignalExceptionCoProcessorUnusable (1);
-#endif
}
@@ -3054,21 +3646,16 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int format = ((instruction >> 21) & 0x00000007);
- check_fpu(SD_);
- {
- if ((format != fmt_single) && (format != fmt_double))
- SignalException(ReservedInstruction,instruction);
- else
- StoreFPR(destreg,format,AbsoluteValue(ValueFPR(fs,format),format));
- }
+ int fmt = FMT;
+ check_fpu (SD_);
+ check_fmt_p (SD_, fmt, instruction_0);
+ StoreFPR(FD,fmt,AbsoluteValue(ValueFPR(FS,fmt),fmt));
}
@@ -3080,22 +3667,16 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int ft = ((instruction >> 16) & 0x0000001F);
- int format = ((instruction >> 21) & 0x00000007);
- check_fpu(SD_);
- {
- if ((format != fmt_single) && (format != fmt_double))
- SignalException(ReservedInstruction, instruction);
- else
- StoreFPR(destreg,format,Add(ValueFPR(fs,format),ValueFPR(ft,format),format));
- }
+ int fmt = FMT;
+ check_fpu (SD_);
+ check_fmt_p (SD_, fmt, instruction_0);
+ StoreFPR(FD,fmt,Add(ValueFPR(FS,fmt),ValueFPR(FT,fmt),fmt));
}
@@ -3111,7 +3692,7 @@
*mipsII:
*mipsIII:
{
- check_fpu(SD_);
+ check_fpu (SD_);
check_branch_bug ();
TRACE_BRANCH_INPUT (PREVCOC1());
if (PREVCOC1() == TF)
@@ -3137,11 +3718,13 @@
"bc1%s<TF>%s<ND> <CC>, <OFFSET>"
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
#*vr4100:
*vr5000:
*r3900:
{
- check_fpu(SD_);
+ check_fpu (SD_);
check_branch_bug ();
if (GETFCC(CC) == TF)
{
@@ -3166,38 +3749,33 @@
:function:::void:do_c_cond_fmt:int fmt, int ft, int fs, int cc, int cond, instruction_word insn
{
- if ((fmt != fmt_single) && (fmt != fmt_double))
- SignalException (ReservedInstruction, insn);
- else
+ int less;
+ int equal;
+ int unordered;
+ int condition;
+ unsigned64 ofs = ValueFPR (fs, fmt);
+ unsigned64 oft = ValueFPR (ft, fmt);
+ if (NaN (ofs, fmt) || NaN (oft, fmt))
{
- int less;
- int equal;
- int unordered;
- int condition;
- unsigned64 ofs = ValueFPR (fs, fmt);
- unsigned64 oft = ValueFPR (ft, fmt);
- if (NaN (ofs, fmt) || NaN (oft, fmt))
+ if (FCSR & FP_ENABLE (IO))
{
- if (FCSR & FP_ENABLE (IO))
- {
- FCSR |= FP_CAUSE (IO);
- SignalExceptionFPE ();
- }
- less = 0;
- equal = 0;
- unordered = 1;
+ FCSR |= FP_CAUSE (IO);
+ SignalExceptionFPE ();
}
- else
- {
- less = Less (ofs, oft, fmt);
- equal = Equal (ofs, oft, fmt);
- unordered = 0;
- }
- condition = (((cond & (1 << 2)) && less)
- || ((cond & (1 << 1)) && equal)
- || ((cond & (1 << 0)) && unordered));
- SETFCC (cc, condition);
+ less = 0;
+ equal = 0;
+ unordered = 1;
+ }
+ else
+ {
+ less = Less (ofs, oft, fmt);
+ equal = Equal (ofs, oft, fmt);
+ unordered = 0;
}
+ condition = (((cond & (1 << 2)) && less)
+ || ((cond & (1 << 1)) && equal)
+ || ((cond & (1 << 0)) && unordered));
+ SETFCC (cc, condition);
}
010001,10,3.FMT,5.FT,5.FS,3.0,00,11,4.COND:COP1:32,f::C.cond.fmta
@@ -3206,8 +3784,10 @@
*mipsII:
*mipsIII:
{
- check_fpu(SD_);
- do_c_cond_fmt (SD_, FMT, FT, FS, 0, COND, instruction_0);
+ int fmt = FMT;
+ check_fpu (SD_);
+ check_fmt_p (SD_, fmt, instruction_0);
+ do_c_cond_fmt (SD_, fmt, FT, FS, 0, COND, instruction_0);
}
010001,10,3.FMT,5.FT,5.FS,3.CC,00,11,4.COND:COP1:32,f::C.cond.fmtb
@@ -3215,12 +3795,16 @@
"c.%s<COND>.%s<FMT> <CC>, f<FS>, f<FT>"
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- check_fpu(SD_);
- do_c_cond_fmt (SD_, FMT, FT, FS, CC, COND, instruction_0);
+ int fmt = FMT;
+ check_fpu (SD_);
+ check_fmt_p (SD_, fmt, instruction_0);
+ do_c_cond_fmt (SD_, fmt, FT, FS, CC, COND, instruction_0);
}
@@ -3229,21 +3813,15 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int format = ((instruction >> 21) & 0x00000007);
- check_fpu(SD_);
- {
- if ((format != fmt_single) && (format != fmt_double))
- SignalException(ReservedInstruction,instruction);
- else
- StoreFPR(destreg,fmt_long,Convert(FP_RM_TOPINF,ValueFPR(fs,format),format,fmt_long));
- }
+ int fmt = FMT;
+ check_fpu (SD_);
+ check_fmt (SD_, fmt, instruction_0);
+ StoreFPR(FD,fmt_long,Convert(FP_RM_TOPINF,ValueFPR(FS,fmt),fmt,fmt_long));
}
@@ -3252,21 +3830,16 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int format = ((instruction >> 21) & 0x00000007);
- check_fpu(SD_);
- {
- if ((format != fmt_single) && (format != fmt_double))
- SignalException(ReservedInstruction,instruction);
- else
- StoreFPR(destreg,fmt_word,Convert(FP_RM_TOPINF,ValueFPR(fs,format),format,fmt_word));
- }
+ int fmt = FMT;
+ check_fpu (SD_);
+ check_fmt (SD_, fmt, instruction_0);
+ StoreFPR(FD,fmt_word,Convert(FP_RM_TOPINF,ValueFPR(FS,fmt),fmt,fmt_word));
}
@@ -3278,7 +3851,7 @@
*mipsII:
*mipsIII:
{
- check_fpu(SD_);
+ check_fpu (SD_);
if (X)
{
if (FS == 0)
@@ -3291,9 +3864,9 @@
else
{ /* control from */
if (FS == 0)
- PENDING_FILL(RT,SIGNEXTEND(FCR0,32));
+ PENDING_FILL(RT, EXTEND32 (FCR0));
else if (FS == 31)
- PENDING_FILL(RT,SIGNEXTEND(FCR31,32));
+ PENDING_FILL(RT, EXTEND32 (FCR31));
/* else NOP */
}
}
@@ -3301,11 +3874,13 @@
"c%s<X>c1 r<RT>, f<FS>"
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- check_fpu(SD_);
+ check_fpu (SD_);
if (X)
{
/* control to */
@@ -3332,12 +3907,12 @@
if (FS == 0)
{
TRACE_ALU_INPUT1 (FCR0);
- GPR[RT] = SIGNEXTEND (FCR0, 32);
+ GPR[RT] = EXTEND32 (FCR0);
}
else if (FS == 31)
{
TRACE_ALU_INPUT1 (FCR31);
- GPR[RT] = SIGNEXTEND (FCR31, 32);
+ GPR[RT] = EXTEND32 (FCR31);
}
TRACE_ALU_RESULT (GPR[RT]);
/* else NOP */
@@ -3355,20 +3930,19 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int format = ((instruction >> 21) & 0x00000007);
- check_fpu(SD_);
+ int fmt = FMT;
+ check_fpu (SD_);
{
- if ((format == fmt_double) | 0)
- SignalException(ReservedInstruction,instruction);
+ if ((fmt == fmt_double) | 0)
+ SignalException (ReservedInstruction, instruction_0);
else
- StoreFPR(destreg,fmt_double,Convert(GETRM(),ValueFPR(fs,format),format,fmt_double));
+ StoreFPR(FD,fmt_double,Convert(GETRM(),ValueFPR(FS,fmt),fmt,fmt_double));
}
}
@@ -3378,20 +3952,18 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int format = ((instruction >> 21) & 0x00000007);
- check_fpu(SD_);
+ int fmt = FMT;
+ check_fpu (SD_);
{
- if ((format == fmt_long) | ((format == fmt_long) || (format == fmt_word)))
- SignalException(ReservedInstruction,instruction);
+ if ((fmt == fmt_long) | ((fmt == fmt_long) || (fmt == fmt_word)))
+ SignalException (ReservedInstruction, instruction_0);
else
- StoreFPR(destreg,fmt_long,Convert(GETRM(),ValueFPR(fs,format),format,fmt_long));
+ StoreFPR(FD,fmt_long,Convert(GETRM(),ValueFPR(FS,fmt),fmt,fmt_long));
}
}
@@ -3406,20 +3978,19 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int format = ((instruction >> 21) & 0x00000007);
- check_fpu(SD_);
+ int fmt = FMT;
+ check_fpu (SD_);
{
- if ((format == fmt_single) | 0)
- SignalException(ReservedInstruction,instruction);
+ if ((fmt == fmt_single) | 0)
+ SignalException (ReservedInstruction, instruction_0);
else
- StoreFPR(destreg,fmt_single,Convert(GETRM(),ValueFPR(fs,format),format,fmt_single));
+ StoreFPR(FD,fmt_single,Convert(GETRM(),ValueFPR(FS,fmt),fmt,fmt_single));
}
}
@@ -3431,20 +4002,19 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int format = ((instruction >> 21) & 0x00000007);
- check_fpu(SD_);
+ int fmt = FMT;
+ check_fpu (SD_);
{
- if ((format == fmt_word) | ((format == fmt_long) || (format == fmt_word)))
- SignalException(ReservedInstruction,instruction);
+ if ((fmt == fmt_word) | ((fmt == fmt_long) || (fmt == fmt_word)))
+ SignalException (ReservedInstruction, instruction_0);
else
- StoreFPR(destreg,fmt_word,Convert(GETRM(),ValueFPR(fs,format),format,fmt_word));
+ StoreFPR(FD,fmt_word,Convert(GETRM(),ValueFPR(FS,fmt),fmt,fmt_word));
}
}
@@ -3456,22 +4026,16 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int ft = ((instruction >> 16) & 0x0000001F);
- int format = ((instruction >> 21) & 0x00000007);
- check_fpu(SD_);
- {
- if ((format != fmt_single) && (format != fmt_double))
- SignalException(ReservedInstruction,instruction);
- else
- StoreFPR(destreg,format,Divide(ValueFPR(fs,format),ValueFPR(ft,format),format));
- }
+ int fmt = FMT;
+ check_fpu (SD_);
+ check_fmt (SD_, fmt, instruction_0);
+ StoreFPR(FD,fmt,Divide(ValueFPR(FS,fmt),ValueFPR(FT,fmt),fmt));
}
@@ -3481,7 +4045,7 @@
"dm%s<X>c1 r<RT>, f<FS>"
*mipsIII:
{
- check_fpu(SD_);
+ check_fpu (SD_);
check_u64 (SD_, instruction_0);
if (X)
{
@@ -3502,7 +4066,7 @@
else
{
if (STATE_VERBOSE_P(SD))
- sim_io_eprintf (SD,
+ sim_io_eprintf (SD,
"Warning: PC 0x%lx: semantic_DMxC1_COP1Sa 32-bit use of odd FPR number\n",
(long) CIA);
PENDING_FILL(RT,SET64HI(0xDEADC0DE) | 0xBAD0BAD0);
@@ -3513,11 +4077,12 @@
"dm%s<X>c1 r<RT>, f<FS>"
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- check_fpu(SD_);
+ check_fpu (SD_);
check_u64 (SD_, instruction_0);
if (X)
{
@@ -3535,7 +4100,7 @@
else
{
if (STATE_VERBOSE_P(SD))
- sim_io_eprintf (SD,
+ sim_io_eprintf (SD,
"Warning: PC 0x%lx: DMxC1 32-bit use of odd FPR number\n",
(long) CIA);
GPR[RT] = SET64HI (0xDEADC0DE) | 0xBAD0BAD0;
@@ -3549,21 +4114,15 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int format = ((instruction >> 21) & 0x00000007);
- check_fpu(SD_);
- {
- if ((format != fmt_single) && (format != fmt_double))
- SignalException(ReservedInstruction,instruction);
- else
- StoreFPR(destreg,fmt_long,Convert(FP_RM_TOMINF,ValueFPR(fs,format),format,fmt_long));
- }
+ int fmt = FMT;
+ check_fpu (SD_);
+ check_fmt (SD_, fmt, instruction_0);
+ StoreFPR(FD,fmt_long,Convert(FP_RM_TOMINF,ValueFPR(FS,fmt),fmt,fmt_long));
}
@@ -3573,21 +4132,16 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int format = ((instruction >> 21) & 0x00000007);
- check_fpu(SD_);
- {
- if ((format != fmt_single) && (format != fmt_double))
- SignalException(ReservedInstruction,instruction);
- else
- StoreFPR(destreg,fmt_word,Convert(FP_RM_TOMINF,ValueFPR(fs,format),format,fmt_word));
- }
+ int fmt = FMT;
+ check_fpu (SD_);
+ check_fmt (SD_, fmt, instruction_0);
+ StoreFPR(FD,fmt_word,Convert(FP_RM_TOMINF,ValueFPR(FS,fmt),fmt,fmt_word));
}
@@ -3597,11 +4151,13 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- check_fpu(SD_);
+ check_fpu (SD_);
COP_LD (1, FT, do_load (SD_, AccessLength_DOUBLEWORD, GPR[BASE], EXTEND16 (OFFSET)));
}
@@ -3610,27 +4166,30 @@
"ldxc1 f<FD>, r<INDEX>(r<BASE>)"
*mipsIV:
*mipsV:
+*mips64:
*vr5000:
{
- check_fpu(SD_);
+ check_fpu (SD_);
check_u64 (SD_, instruction_0);
COP_LD (1, FD, do_load (SD_, AccessLength_DOUBLEWORD, GPR[BASE], GPR[INDEX]));
}
-110001,5.BASE,5.FT,16.OFFSET:COP1:32,f::LWC1
+110001,5.BASE,5.FT,16.OFFSET:COP1:32,f::LWC1
"lwc1 f<FT>, <OFFSET>(r<BASE>)"
*mipsI:
*mipsII:
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- check_fpu(SD_);
+ check_fpu (SD_);
COP_LW (1, FT, do_load (SD_, AccessLength_WORD, GPR[BASE], EXTEND16 (OFFSET)));
}
@@ -3639,9 +4198,10 @@
"lwxc1 f<FD>, r<INDEX>(r<BASE>)"
*mipsIV:
*mipsV:
+*mips64:
*vr5000:
{
- check_fpu(SD_);
+ check_fpu (SD_);
check_u64 (SD_, instruction_0);
COP_LW (1, FD, do_load (SD_, AccessLength_WORD, GPR[BASE], GPR[INDEX]));
}
@@ -3655,16 +4215,12 @@
"madd.d f<FD>, f<FR>, f<FS>, f<FT>"
*mipsIV:
*mipsV:
+*mips64:
*vr5000:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int ft = ((instruction >> 16) & 0x0000001F);
- int fr = ((instruction >> 21) & 0x0000001F);
- check_fpu(SD_);
+ check_fpu (SD_);
{
- StoreFPR(destreg,fmt_double,Add(Multiply(ValueFPR(fs,fmt_double),ValueFPR(ft,fmt_double),fmt_double),ValueFPR(fr,fmt_double),fmt_double));
+ StoreFPR(FD,fmt_double,Add(Multiply(ValueFPR(FS,fmt_double),ValueFPR(FT,fmt_double),fmt_double),ValueFPR(FR,fmt_double),fmt_double));
}
}
@@ -3673,16 +4229,12 @@
"madd.s f<FD>, f<FR>, f<FS>, f<FT>"
*mipsIV:
*mipsV:
+*mips64:
*vr5000:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int ft = ((instruction >> 16) & 0x0000001F);
- int fr = ((instruction >> 21) & 0x0000001F);
- check_fpu(SD_);
+ check_fpu (SD_);
{
- StoreFPR(destreg,fmt_single,Add(Multiply(ValueFPR(fs,fmt_single),ValueFPR(ft,fmt_single),fmt_single),ValueFPR(fr,fmt_single),fmt_single));
+ StoreFPR(FD,fmt_single,Add(Multiply(ValueFPR(FS,fmt_single),ValueFPR(FT,fmt_single),fmt_single),ValueFPR(FR,fmt_single),fmt_single));
}
}
@@ -3695,13 +4247,13 @@
*mipsII:
*mipsIII:
{
- check_fpu(SD_);
+ check_fpu (SD_);
if (X)
{ /*MTC1*/
if (SizeFGR() == 64)
{
if (STATE_VERBOSE_P(SD))
- sim_io_eprintf (SD,
+ sim_io_eprintf (SD,
"Warning: PC 0x%lx: MTC1 not DMTC1 with 64 bit regs\n",
(long) CIA);
PENDING_FILL ((FS + FGRIDX), (SET64HI(0xDEADC0DE) | VL4_8(GPR[RT])));
@@ -3710,23 +4262,25 @@
PENDING_FILL ((FS + FGRIDX), VL4_8(GPR[RT]));
}
else /*MFC1*/
- PENDING_FILL (RT, SIGNEXTEND(FGR[FS],32));
+ PENDING_FILL (RT, EXTEND32 (FGR[FS]));
}
010001,00,X,00,5.RT,5.FS,00000000000:COP1Sb:32,f::MxC1
"m%s<X>c1 r<RT>, f<FS>"
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
int fs = FS;
- check_fpu(SD_);
+ check_fpu (SD_);
if (X)
/*MTC1*/
StoreFPR (FS, fmt_uninterpreted_32, VL4_8 (GPR[RT]));
else /*MFC1*/
- GPR[RT] = SIGNEXTEND(FGR[FS],32);
+ GPR[RT] = EXTEND32 (FGR[FS]);
}
@@ -3737,18 +4291,16 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int format = ((instruction >> 21) & 0x00000007);
- check_fpu(SD_);
- {
- StoreFPR(destreg,format,ValueFPR(fs,format));
- }
+ int fmt = FMT;
+ check_fpu (SD_);
+ check_fmt_p (SD_, fmt, instruction_0);
+ StoreFPR(FD,fmt,ValueFPR(FS,fmt));
}
@@ -3758,9 +4310,11 @@
"mov%s<TF> r<RD>, r<RS>, <CC>"
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr5000:
{
- check_fpu(SD_);
+ check_fpu (SD_);
if (GETFCC(CC) == TF)
GPR[RD] = GPR[RS];
}
@@ -3772,16 +4326,17 @@
"mov%s<TF>.%s<FMT> f<FD>, f<FS>, <CC>"
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr5000:
{
- unsigned32 instruction = instruction_0;
- int format = ((instruction >> 21) & 0x00000007);
- check_fpu(SD_);
+ int fmt = FMT;
+ check_fpu (SD_);
{
if (GETFCC(CC) == TF)
- StoreFPR (FD, format, ValueFPR (FS, format));
+ StoreFPR (FD, fmt, ValueFPR (FS, fmt));
else
- StoreFPR (FD, format, ValueFPR (FD, format));
+ StoreFPR (FD, fmt, ValueFPR (FD, fmt));
}
}
@@ -3790,9 +4345,11 @@
"movn.%s<FMT> f<FD>, f<FS>, r<RT>"
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr5000:
{
- check_fpu(SD_);
+ check_fpu (SD_);
if (GPR[RT] != 0)
StoreFPR (FD, FMT, ValueFPR (FS, FMT));
else
@@ -3811,9 +4368,11 @@
"movz.%s<FMT> f<FD>, f<FS>, r<RT>"
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr5000:
{
- check_fpu(SD_);
+ check_fpu (SD_);
if (GPR[RT] == 0)
StoreFPR (FD, FMT, ValueFPR (FS, FMT));
else
@@ -3826,17 +4385,11 @@
"msub.d f<FD>, f<FR>, f<FS>, f<FT>"
*mipsIV:
*mipsV:
+*mips64:
*vr5000:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int ft = ((instruction >> 16) & 0x0000001F);
- int fr = ((instruction >> 21) & 0x0000001F);
- check_fpu(SD_);
- {
- StoreFPR(destreg,fmt_double,Sub(Multiply(ValueFPR(fs,fmt_double),ValueFPR(ft,fmt_double),fmt_double),ValueFPR(fr,fmt_double),fmt_double));
- }
+ check_fpu (SD_);
+ StoreFPR(FD,fmt_double,Sub(Multiply(ValueFPR(FS,fmt_double),ValueFPR(FT,fmt_double),fmt_double),ValueFPR(FR,fmt_double),fmt_double));
}
@@ -3845,17 +4398,11 @@
"msub.s f<FD>, f<FR>, f<FS>, f<FT>"
*mipsIV:
*mipsV:
+*mips64:
*vr5000:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int ft = ((instruction >> 16) & 0x0000001F);
- int fr = ((instruction >> 21) & 0x0000001F);
- check_fpu(SD_);
- {
- StoreFPR(destreg,fmt_single,Sub(Multiply(ValueFPR(fs,fmt_single),ValueFPR(ft,fmt_single),fmt_single),ValueFPR(fr,fmt_single),fmt_single));
- }
+ check_fpu (SD_);
+ StoreFPR(FD,fmt_single,Sub(Multiply(ValueFPR(FS,fmt_single),ValueFPR(FT,fmt_single),fmt_single),ValueFPR(FR,fmt_single),fmt_single));
}
@@ -3869,22 +4416,16 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int ft = ((instruction >> 16) & 0x0000001F);
- int format = ((instruction >> 21) & 0x00000007);
- check_fpu(SD_);
- {
- if ((format != fmt_single) && (format != fmt_double))
- SignalException(ReservedInstruction,instruction);
- else
- StoreFPR(destreg,format,Multiply(ValueFPR(fs,format),ValueFPR(ft,format),format));
- }
+ int fmt = FMT;
+ check_fpu (SD_);
+ check_fmt_p (SD_, fmt, instruction_0);
+ StoreFPR(FD,fmt,Multiply(ValueFPR(FS,fmt),ValueFPR(FT,fmt),fmt));
}
@@ -3895,21 +4436,16 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int format = ((instruction >> 21) & 0x00000007);
- check_fpu(SD_);
- {
- if ((format != fmt_single) && (format != fmt_double))
- SignalException(ReservedInstruction,instruction);
- else
- StoreFPR(destreg,format,Negate(ValueFPR(fs,format),format));
- }
+ int fmt = FMT;
+ check_fpu (SD_);
+ check_fmt_p (SD_, fmt, instruction_0);
+ StoreFPR(FD,fmt,Negate(ValueFPR(FS,fmt),fmt));
}
@@ -3918,17 +4454,11 @@
"nmadd.d f<FD>, f<FR>, f<FS>, f<FT>"
*mipsIV:
*mipsV:
+*mips64:
*vr5000:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int ft = ((instruction >> 16) & 0x0000001F);
- int fr = ((instruction >> 21) & 0x0000001F);
- check_fpu(SD_);
- {
- StoreFPR(destreg,fmt_double,Negate(Add(Multiply(ValueFPR(fs,fmt_double),ValueFPR(ft,fmt_double),fmt_double),ValueFPR(fr,fmt_double),fmt_double),fmt_double));
- }
+ check_fpu (SD_);
+ StoreFPR(FD,fmt_double,Negate(Add(Multiply(ValueFPR(FS,fmt_double),ValueFPR(FT,fmt_double),fmt_double),ValueFPR(FR,fmt_double),fmt_double),fmt_double));
}
@@ -3937,17 +4467,11 @@
"nmadd.s f<FD>, f<FR>, f<FS>, f<FT>"
*mipsIV:
*mipsV:
+*mips64:
*vr5000:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int ft = ((instruction >> 16) & 0x0000001F);
- int fr = ((instruction >> 21) & 0x0000001F);
- check_fpu(SD_);
- {
- StoreFPR(destreg,fmt_single,Negate(Add(Multiply(ValueFPR(fs,fmt_single),ValueFPR(ft,fmt_single),fmt_single),ValueFPR(fr,fmt_single),fmt_single),fmt_single));
- }
+ check_fpu (SD_);
+ StoreFPR(FD,fmt_single,Negate(Add(Multiply(ValueFPR(FS,fmt_single),ValueFPR(FT,fmt_single),fmt_single),ValueFPR(FR,fmt_single),fmt_single),fmt_single));
}
@@ -3956,17 +4480,11 @@
"nmsub.d f<FD>, f<FR>, f<FS>, f<FT>"
*mipsIV:
*mipsV:
+*mips64:
*vr5000:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int ft = ((instruction >> 16) & 0x0000001F);
- int fr = ((instruction >> 21) & 0x0000001F);
- check_fpu(SD_);
- {
- StoreFPR(destreg,fmt_double,Negate(Sub(Multiply(ValueFPR(fs,fmt_double),ValueFPR(ft,fmt_double),fmt_double),ValueFPR(fr,fmt_double),fmt_double),fmt_double));
- }
+ check_fpu (SD_);
+ StoreFPR(FD,fmt_double,Negate(Sub(Multiply(ValueFPR(FS,fmt_double),ValueFPR(FT,fmt_double),fmt_double),ValueFPR(FR,fmt_double),fmt_double),fmt_double));
}
@@ -3975,17 +4493,11 @@
"nmsub.s f<FD>, f<FR>, f<FS>, f<FT>"
*mipsIV:
*mipsV:
+*mips64:
*vr5000:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int ft = ((instruction >> 16) & 0x0000001F);
- int fr = ((instruction >> 21) & 0x0000001F);
- check_fpu(SD_);
- {
- StoreFPR(destreg,fmt_single,Negate(Sub(Multiply(ValueFPR(fs,fmt_single),ValueFPR(ft,fmt_single),fmt_single),ValueFPR(fr,fmt_single),fmt_single),fmt_single));
- }
+ check_fpu (SD_);
+ StoreFPR(FD,fmt_single,Negate(Sub(Multiply(ValueFPR(FS,fmt_single),ValueFPR(FT,fmt_single),fmt_single),ValueFPR(FR,fmt_single),fmt_single),fmt_single));
}
@@ -3993,18 +4505,17 @@
"prefx <HINT>, r<INDEX>(r<BASE>)"
*mipsIV:
*mipsV:
+*mips64:
*vr5000:
{
- unsigned32 instruction = instruction_0;
- int fs = ((instruction >> 11) & 0x0000001F);
- signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)];
- signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)];
+ address_word base = GPR[BASE];
+ address_word index = GPR[INDEX];
{
- address_word vaddr = ((unsigned64)op1 + (unsigned64)op2);
+ address_word vaddr = loadstore_ea (SD_, base, index);
address_word paddr;
int uncached;
if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))
- Prefetch(uncached,paddr,vaddr,isDATA,fs);
+ Prefetch(uncached,paddr,vaddr,isDATA,HINT);
}
}
@@ -4012,19 +4523,13 @@
"recip.%s<FMT> f<FD>, f<FS>"
*mipsIV:
*mipsV:
+*mips64:
*vr5000:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int format = ((instruction >> 21) & 0x00000007);
- check_fpu(SD_);
- {
- if ((format != fmt_single) && (format != fmt_double))
- SignalException(ReservedInstruction,instruction);
- else
- StoreFPR(destreg,format,Recip(ValueFPR(fs,format),format));
- }
+ int fmt = FMT;
+ check_fpu (SD_);
+ check_fmt (SD_, fmt, instruction_0);
+ StoreFPR(FD,fmt,Recip(ValueFPR(FS,fmt),fmt));
}
@@ -4033,21 +4538,15 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int format = ((instruction >> 21) & 0x00000007);
- check_fpu(SD_);
- {
- if ((format != fmt_single) && (format != fmt_double))
- SignalException(ReservedInstruction,instruction);
- else
- StoreFPR(destreg,fmt_long,Convert(FP_RM_NEAREST,ValueFPR(fs,format),format,fmt_long));
- }
+ int fmt = FMT;
+ check_fpu (SD_);
+ check_fmt (SD_, fmt, instruction_0);
+ StoreFPR(FD,fmt_long,Convert(FP_RM_NEAREST,ValueFPR(FS,fmt),fmt,fmt_long));
}
@@ -4057,41 +4556,30 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int format = ((instruction >> 21) & 0x00000007);
- check_fpu(SD_);
- {
- if ((format != fmt_single) && (format != fmt_double))
- SignalException(ReservedInstruction,instruction);
- else
- StoreFPR(destreg,fmt_word,Convert(FP_RM_NEAREST,ValueFPR(fs,format),format,fmt_word));
- }
+ int fmt = FMT;
+ check_fpu (SD_);
+ check_fmt (SD_, fmt, instruction_0);
+ StoreFPR(FD,fmt_word,Convert(FP_RM_NEAREST,ValueFPR(FS,fmt),fmt,fmt_word));
}
010001,10,3.FMT,00000,5.FS,5.FD,010110:COP1:32,f::RSQRT.fmt
*mipsIV:
*mipsV:
+*mips64:
"rsqrt.%s<FMT> f<FD>, f<FS>"
*vr5000:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int format = ((instruction >> 21) & 0x00000007);
- check_fpu(SD_);
- {
- if ((format != fmt_single) && (format != fmt_double))
- SignalException(ReservedInstruction,instruction);
- else
- StoreFPR(destreg,format,Recip(SquareRoot(ValueFPR(fs,format),format),format));
- }
+ int fmt = FMT;
+ check_fpu (SD_);
+ check_fmt (SD_, fmt, instruction_0);
+ StoreFPR(FD,fmt,Recip(SquareRoot(ValueFPR(FS,fmt),fmt),fmt));
}
@@ -4101,11 +4589,13 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- check_fpu(SD_);
+ check_fpu (SD_);
do_store (SD_, AccessLength_DOUBLEWORD, GPR[BASE], EXTEND16 (OFFSET), COP_SD (1, FT));
}
@@ -4114,9 +4604,10 @@
"sdxc1 f<FS>, r<INDEX>(r<BASE>)"
*mipsIV:
*mipsV:
+*mips64:
*vr5000:
{
- check_fpu(SD_);
+ check_fpu (SD_);
check_u64 (SD_, instruction_0);
do_store (SD_, AccessLength_DOUBLEWORD, GPR[BASE], GPR[INDEX], COP_SD (1, FS));
}
@@ -4128,21 +4619,16 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int format = ((instruction >> 21) & 0x00000007);
- check_fpu(SD_);
- {
- if ((format != fmt_single) && (format != fmt_double))
- SignalException(ReservedInstruction,instruction);
- else
- StoreFPR(destreg,format,(SquareRoot(ValueFPR(fs,format),format)));
- }
+ int fmt = FMT;
+ check_fpu (SD_);
+ check_fmt (SD_, fmt, instruction_0);
+ StoreFPR(FD,fmt,(SquareRoot(ValueFPR(FS,fmt),fmt)));
}
@@ -4153,22 +4639,16 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int ft = ((instruction >> 16) & 0x0000001F);
- int format = ((instruction >> 21) & 0x00000007);
- check_fpu(SD_);
- {
- if ((format != fmt_single) && (format != fmt_double))
- SignalException(ReservedInstruction,instruction);
- else
- StoreFPR(destreg,format,Sub(ValueFPR(fs,format),ValueFPR(ft,format),format));
- }
+ int fmt = FMT;
+ check_fpu (SD_);
+ check_fmt_p (SD_, fmt, instruction_0);
+ StoreFPR(FD,fmt,Sub(ValueFPR(FS,fmt),ValueFPR(FT,fmt),fmt));
}
@@ -4180,17 +4660,17 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- unsigned32 instruction = instruction_0;
- signed_word offset = EXTEND16 (OFFSET);
- int destreg UNUSED = ((instruction >> 16) & 0x0000001F);
- signed_word op1 UNUSED = GPR[((instruction >> 21) & 0x0000001F)];
- check_fpu(SD_);
+ address_word base = GPR[BASE];
+ address_word offset = EXTEND16 (OFFSET);
+ check_fpu (SD_);
{
- address_word vaddr = ((uword64)op1 + offset);
+ address_word vaddr = loadstore_ea (SD_, base, offset);
address_word paddr;
int uncached;
if ((vaddr & 3) != 0)
@@ -4209,7 +4689,7 @@
unsigned int byte;
paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
byte = ((vaddr & mask) ^ bigendiancpu);
- memval = (((uword64)COP_SW(((instruction >> 26) & 0x3),destreg)) << (8 * byte));
+ memval = (((uword64)COP_SW(((instruction_0 >> 26) & 0x3),FT)) << (8 * byte));
StoreMemory(uncached,AccessLength_WORD,memval,memval1,paddr,vaddr,isREAL);
}
}
@@ -4221,16 +4701,16 @@
"swxc1 f<FS>, r<INDEX>(r<BASE>)"
*mipsIV:
*mipsV:
+*mips64:
*vr5000:
{
- unsigned32 instruction = instruction_0;
- int fs = ((instruction >> 11) & 0x0000001F);
- signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)];
- signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)];
- check_fpu(SD_);
+
+ address_word base = GPR[BASE];
+ address_word index = GPR[INDEX];
+ check_fpu (SD_);
check_u64 (SD_, instruction_0);
{
- address_word vaddr = ((unsigned64)op1 + op2);
+ address_word vaddr = loadstore_ea (SD_, base, index);
address_word paddr;
int uncached;
if ((vaddr & 3) != 0)
@@ -4247,7 +4727,7 @@
unsigned int byte;
paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2)));
byte = ((vaddr & mask) ^ (BigEndianCPU << 2));
- memval = (((unsigned64)COP_SW(1,fs)) << (8 * byte));
+ memval = (((unsigned64)COP_SW(1,FS)) << (8 * byte));
{
StoreMemory(uncached,AccessLength_WORD,memval,memval1,paddr,vaddr,isREAL);
}
@@ -4262,21 +4742,15 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int format = ((instruction >> 21) & 0x00000007);
- check_fpu(SD_);
- {
- if ((format != fmt_single) && (format != fmt_double))
- SignalException(ReservedInstruction,instruction);
- else
- StoreFPR(destreg,fmt_long,Convert(FP_RM_TOZERO,ValueFPR(fs,format),format,fmt_long));
- }
+ int fmt = FMT;
+ check_fpu (SD_);
+ check_fmt (SD_, fmt, instruction_0);
+ StoreFPR(FD,fmt_long,Convert(FP_RM_TOZERO,ValueFPR(FS,fmt),fmt,fmt_long));
}
@@ -4286,21 +4760,16 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- unsigned32 instruction = instruction_0;
- int destreg = ((instruction >> 6) & 0x0000001F);
- int fs = ((instruction >> 11) & 0x0000001F);
- int format = ((instruction >> 21) & 0x00000007);
- check_fpu(SD_);
- {
- if ((format != fmt_single) && (format != fmt_double))
- SignalException(ReservedInstruction,instruction);
- else
- StoreFPR(destreg,fmt_word,Convert(FP_RM_TOZERO,ValueFPR(fs,format),format,fmt_word));
- }
+ int fmt = FMT;
+ check_fpu (SD_);
+ check_fmt (SD_, fmt, instruction_0);
+ StoreFPR(FD,fmt_word,Convert(FP_RM_TOZERO,ValueFPR(FS,fmt),fmt,fmt_word));
}
@@ -4318,6 +4787,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
@@ -4337,6 +4808,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
@@ -4348,6 +4821,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
@@ -4358,6 +4833,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
@@ -4367,20 +4844,20 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
{
- unsigned32 instruction = instruction_0;
- signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16);
- int hint = ((instruction >> 16) & 0x0000001F);
- signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)];
+ address_word base = GPR[BASE];
+ address_word offset = EXTEND16 (OFFSET);
{
- address_word vaddr = (op1 + offset);
+ address_word vaddr = loadstore_ea (SD_, base, offset);
address_word paddr;
int uncached;
if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))
- CacheOp(hint,vaddr,paddr,instruction);
+ CacheOp(OP,vaddr,paddr,instruction_0);
}
}
@@ -4401,6 +4878,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
{
check_u64 (SD_, instruction_0);
DecodeCoproc (instruction_0);
@@ -4412,6 +4890,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
{
check_u64 (SD_, instruction_0);
DecodeCoproc (instruction_0);
@@ -4425,6 +4904,7 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips64:
*vr4100:
*vr5000:
@@ -4434,6 +4914,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
{
@@ -4459,6 +4941,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -4475,6 +4959,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
*r3900:
@@ -4505,6 +4991,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*r3900:
{
@@ -4520,6 +5008,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
@@ -4531,6 +5021,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
@@ -4542,6 +5034,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
@@ -4553,6 +5047,8 @@
*mipsIII:
*mipsIV:
*mipsV:
+*mips32:
+*mips64:
*vr4100:
*vr5000:
diff --git a/sim/mips/sim-main.h b/sim/mips/sim-main.h
index 215a8161ff2..bcdcd80e3fd 100644
--- a/sim/mips/sim-main.h
+++ b/sim/mips/sim-main.h
@@ -43,7 +43,7 @@ typedef address_word sim_cia;
#include "sim-base.h"
-/* Depreciated macros and types for manipulating 64bit values. Use
+/* Deprecated macros and types for manipulating 64bit values. Use
../common/sim-bits.h and ../common/sim-endian.h macros instead. */
typedef signed64 word64;
@@ -56,15 +56,6 @@ typedef unsigned64 uword64;
#define WORD64(h,l) ((word64)((SET64HI(h)|SET64LO(l))))
#define UWORD64(h,l) (SET64HI(h)|SET64LO(l))
-/* Sign-extend the given value (e) as a value (b) bits long. We cannot
- assume the HI32bits of the operand are zero, so we must perform a
- mask to ensure we can use the simple subtraction to sign-extend. */
-#define SIGNEXTEND(e,b) \
- ((unsigned_word) \
- (((e) & ((uword64) 1 << ((b) - 1))) \
- ? (((e) & (((uword64) 1 << (b)) - 1)) - ((uword64)1 << (b))) \
- : ((e) & (((((uword64) 1 << ((b) - 1)) - 1) << 1) | 1))))
-
/* Check if a value will fit within a halfword: */
#define NOTHALFWORDVALUE(v) ((((((uword64)(v)>>16) == 0) && !((v) & ((unsigned)1 << 15))) || (((((uword64)(v)>>32) == 0xFFFFFFFF) && ((((uword64)(v)>>16) & 0xFFFF) == 0xFFFF)) && ((v) & ((unsigned)1 << 15)))) ? (1 == 0) : (1 == 1))
@@ -543,6 +534,18 @@ struct sim_state {
#define status_NMI (1 << 20) /* NMI */
#define status_NMI (1 << 20) /* NMI */
+/* Status bits used by MIPS32/MIPS64. */
+#define status_UX (1 << 5) /* 64-bit user addrs */
+#define status_SX (1 << 6) /* 64-bit supervisor addrs */
+#define status_KX (1 << 7) /* 64-bit kernel addrs */
+#define status_TS (1 << 21) /* TLB shutdown has occurred */
+#define status_PX (1 << 23) /* Enable 64 bit operations */
+#define status_MX (1 << 24) /* Enable MDMX resources */
+#define status_CU0 (1 << 28) /* Coprocessor 0 usable */
+#define status_CU1 (1 << 29) /* Coprocessor 1 usable */
+#define status_CU2 (1 << 30) /* Coprocessor 2 usable */
+#define status_CU3 (1 << 31) /* Coprocessor 3 usable */
+
#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 */
@@ -620,9 +623,12 @@ enum ExceptionCause {
IntegerOverflow = 12, /* Arithmetic overflow (IDT monitor raises SIGFPE) */
Trap = 13,
FPE = 15,
- DebugBreakPoint = 16,
+ DebugBreakPoint = 16, /* Impl. dep. in MIPS32/MIPS64. */
+ MDMX = 22,
Watch = 23,
- NMIReset = 31,
+ MCheck = 24,
+ CacheErr = 30,
+ NMIReset = 31, /* Reserved in MIPS32/MIPS64. */
/* The following exception code is actually private to the simulator
@@ -662,16 +668,23 @@ void signal_exception (SIM_DESC sd, sim_cpu *cpu, address_word cia, int exceptio
#define SignalExceptionSimulatorFault(buf) signal_exception (SD, CPU, cia, SimulatorFault, buf)
#define SignalExceptionFPE() signal_exception (SD, CPU, cia, FPE)
#define SignalExceptionIntegerOverflow() signal_exception (SD, CPU, cia, IntegerOverflow)
-#define SignalExceptionCoProcessorUnusable() signal_exception (SD, CPU, cia, CoProcessorUnusable)
+#define SignalExceptionCoProcessorUnusable(cop) signal_exception (SD, CPU, cia, CoProcessorUnusable)
#define SignalExceptionNMIReset() signal_exception (SD, CPU, cia, NMIReset)
#define SignalExceptionTLBRefillStore() signal_exception (SD, CPU, cia, TLBStore, TLB_REFILL)
#define SignalExceptionTLBRefillLoad() signal_exception (SD, CPU, cia, TLBLoad, TLB_REFILL)
#define SignalExceptionTLBInvalidStore() signal_exception (SD, CPU, cia, TLBStore, TLB_INVALID)
#define SignalExceptionTLBInvalidLoad() signal_exception (SD, CPU, cia, TLBLoad, TLB_INVALID)
#define SignalExceptionTLBModification() signal_exception (SD, CPU, cia, TLBModification)
+#define SignalExceptionMDMX() signal_exception (SD, CPU, cia, MDMX)
+#define SignalExceptionWatch() signal_exception (SD, CPU, cia, Watch)
+#define SignalExceptionMCheck() signal_exception (SD, CPU, cia, MCheck)
+#define SignalExceptionCacheErr() signal_exception (SD, CPU, cia, CacheErr)
/* Co-processor accesses */
+/* XXX FIXME: For now, assume that FPU (cp1) is always usable. */
+#define COP_Usable(coproc_num) (coproc_num == 1)
+
void cop_lw PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int coproc_num, int coproc_reg, unsigned int memword));
void cop_ld PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int coproc_num, int coproc_reg, uword64 memword));
unsigned int cop_sw PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int coproc_num, int coproc_reg));
@@ -758,6 +771,10 @@ INLINE_SIM_MAIN (void) prefetch PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word
#define Prefetch(CCA,pAddr,vAddr,DATA,hint) \
prefetch (SD, CPU, cia, CCA, pAddr, vAddr, DATA, hint)
+void unpredictable_action (sim_cpu *cpu, address_word cia);
+#define NotWordValue(val) not_word_value (SD_, (val))
+#define Unpredictable() unpredictable (SD_)
+
INLINE_SIM_MAIN (unsigned32) ifetch32 PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, address_word vaddr));
#define IMEM32(CIA) ifetch32 (SD, CPU, (CIA), (CIA))
INLINE_SIM_MAIN (unsigned16) ifetch16 PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, address_word vaddr));
diff --git a/sim/ppc/ChangeLog b/sim/ppc/ChangeLog
index 25d96ea78c1..d8198e1a20d 100644
--- a/sim/ppc/ChangeLog
+++ b/sim/ppc/ChangeLog
@@ -1,3 +1,19 @@
+2002-04-15 Elena Zannoni <ezannoni@redhat.com>
+
+ * sim_calls.c (sim_fetch_register, sim_store_register): Return -1 for
+ AltiVec registers as a temporary stopgap.
+
+2002-03-24 David O'Brien <obrien@FreeBSD.org>
+
+ * ppc/hw_disk.c: Export a disk device property.
+
+2002-03-23 Andrew Cagney <ac131313@redhat.com>
+
+ From 2001-12-09 Julien Ducourthial <jducourt@noos.fr>:
+ * ppc-instructions (lswx): Do the register control with the
+ register count. Initialize the right register in the loop.
+ (mtfsfi) : Correct prefix for the instruction.
+
2002-02-24 Andrew Cagney <ac131313@redhat.com>
From wiz at danbala:
diff --git a/sim/ppc/hw_disk.c b/sim/ppc/hw_disk.c
index 5934fead1a1..84086ff1d4a 100644
--- a/sim/ppc/hw_disk.c
+++ b/sim/ppc/hw_disk.c
@@ -232,6 +232,9 @@ hw_disk_init_address(device *me)
space, address, 0/*size*/, access_read_write_exec,
me);
+ /* Tell the world we are a disk. */
+ device_add_string_property(me, "device_type", "disk");
+
/* get the name of the file specifying the disk image */
disk->name_index = 0;
disk->nr_names = device_find_string_array_property(me, "file",
diff --git a/sim/ppc/ppc-instructions b/sim/ppc/ppc-instructions
index 25a9d78c685..6ba0090cac1 100644
--- a/sim/ppc/ppc-instructions
+++ b/sim/ppc/ppc-instructions
@@ -2275,11 +2275,11 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia,
r = RT - 1;
i = 32;
nr = (n + 3) / 4;
- if (((RT + n >= 32)
- ? ((RA >= RT || RA < (RT + n) % 32)
- || (RB >= RT || RB < (RT + n) % 32))
- : ((RA >= RT && RA < RT + n)
- || (RB >= RT && RB < RT + n)))
+ if (((RT + nr >= 32)
+ ? ((RA >= RT || RA < (RT + nr) % 32)
+ || (RB >= RT || RB < (RT + nr) % 32))
+ : ((RA >= RT && RA < RT + nr)
+ || (RB >= RT && RB < RT + nr)))
|| (RT == RA || RT == RB))
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
@@ -2288,7 +2288,7 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia,
while (n > 0) {
if (i == 32) {
r = (r + 1) % 32;
- GPR(i) = 0;
+ GPR(r) = 0;
}
GPR(r) |= INSERTED(MEM(unsigned, EA, 1), i, i+7);
i = i + 8;
@@ -4582,7 +4582,7 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia,
FPSCR_SET(BFA, 0); /* FPSCR_END fixes up FEX/VX */
FPSCR_END(0);
-0.64,6.BF,9./,11./,16.U,20./,21.134,31.Rc:X:f::Move To FPSCR Field Immediate
+0.63,6.BF,9./,11./,16.U,20./,21.134,31.Rc:X:f::Move To FPSCR Field Immediate
FPSCR_BEGIN;
FPSCR_SET(BF, U);
FPSCR_END(Rc);
diff --git a/sim/ppc/sim_calls.c b/sim/ppc/sim_calls.c
index 72f90d23d59..47af5b12a45 100644
--- a/sim/ppc/sim_calls.c
+++ b/sim/ppc/sim_calls.c
@@ -194,7 +194,11 @@ sim_fetch_register (SIM_DESC sd, int regno, unsigned char *buf, int length)
But there are loops that just walk through the entire list of
names and try to get everything. */
regname = gdbarch_register_name (current_gdbarch, regno);
- if (! regname || regname[0] == '\0')
+ /* FIXME: ezannoni 2002/04/15 Remove the 'vr' and 'vscr' check
+ once AltiVec support is committed. */
+ if (! regname || regname[0] == '\0'
+ || (regname[0] == 'v' && regname[1] == 'r')
+ || (strcmp (regname, "vscr") == 0))
return -1;
TRACE(trace_gdb, ("sim_fetch_register(regno=%d(%s), buf=0x%lx)\n",
@@ -215,7 +219,11 @@ sim_store_register (SIM_DESC sd, int regno, unsigned char *buf, int length)
/* See comments in sim_fetch_register, above. */
regname = gdbarch_register_name (current_gdbarch, regno);
- if (! regname || regname[0] == '\0')
+ /* FIXME: ezannoni 2002/04/15 Remove the 'vr' and 'vscr' check
+ once AltiVec support is committed. */
+ if (! regname || regname[0] == '\0'
+ || (regname[0] == 'v' && regname[1] == 'r')
+ || (strcmp (regname, "vscr") == 0))
return -1;
TRACE(trace_gdb, ("sim_store_register(regno=%d(%s), buf=0x%lx)\n",
diff --git a/sim/z8k/ChangeLog b/sim/z8k/ChangeLog
index 64468a129be..8036fe331cf 100644
--- a/sim/z8k/ChangeLog
+++ b/sim/z8k/ChangeLog
@@ -1,3 +1,10 @@
+2002-04-29 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * writecode.c (lookup_inst): Ignore CLASS_IGNORE.
+ (info_args): Treat CLASS_IGNORE like CLASS_BIT.
+ Handle ARG_NIM4.
+ (info_len_in_words): Handle CLASS_IGNORE and ARG_NIM4.
+
Tue May 23 21:39:23 2000 Andrew Cagney <cagney@b1.cygnus.com>
* configure: Regenerated to track ../common/aclocal.m4 changes.
diff --git a/sim/z8k/writecode.c b/sim/z8k/writecode.c
index 8b4c868edea..b398545c04f 100644
--- a/sim/z8k/writecode.c
+++ b/sim/z8k/writecode.c
@@ -139,6 +139,8 @@ lookup_inst (what)
nibl_matched = 0;
break;
+ case CLASS_IGNORE:
+ break;
case CLASS_BIT:
if (datum_value != instr_nibl)
nibl_matched = 0;
@@ -539,6 +541,7 @@ info_args (p)
case CLASS_BIT_1OR2:
emit ("register unsigned int imm_src=(<insn_4>& 2)?2:1;\n");
break;
+ case CLASS_IGNORE:
case CLASS_BIT:
/* Just ignore these, we've already decoded this bit */
nibs++;
@@ -589,6 +592,10 @@ break;
emit ("register unsigned int imm_src=<insn_4>;\n");
nibs++;
break;
+ case ARG_NIM4:
+ emit ("register unsigned int imm_src = - <insn_4>;\n");
+ nibs++;
+ break;
case ARG_IMM2:
emit ("register unsigned int imm_src=<insn_4> & 0x2;\n");
nibs++;
@@ -1938,6 +1945,7 @@ info_len_in_words (o)
{
switch (*p & CLASS_MASK)
{
+ case CLASS_IGNORE:
case CLASS_BIT:
case CLASS_REGN0:
case CLASS_REG:
@@ -1959,6 +1967,7 @@ info_len_in_words (o)
break;
case ARG_IMM2:
case ARG_IMM4:
+ case ARG_NIM4:
case ARG_IMM4M1:
case ARG_IMM_1:
case ARG_IMM_2: