changeset f2102d45a753 in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=f2102d45a753
description:
        x86: Make fprem like the fprem on a real x87

        The current implementation of fprem simply does an fmod and doesn't
        simulate any of the iterative behavior in a real fprem. This isn't
        normally a problem, however, it can lead to problems when switching
        between CPU models. If switching from a real CPU in the middle of an
        fprem loop to a simulated CPU, the output of the fprem loop becomes
        correupted. This changeset changes the fprem implementation to work
        like the one on real hardware.

diffstat:

 src/arch/x86/isa/insts/x87/arithmetic/partial_remainder.py |   4 +-
 src/arch/x86/isa/microops/fpop.isa                         |  27 ++++++++++++-
 2 files changed, 27 insertions(+), 4 deletions(-)

diffs (56 lines):

diff -r 9db8a438608c -r f2102d45a753 
src/arch/x86/isa/insts/x87/arithmetic/partial_remainder.py
--- a/src/arch/x86/isa/insts/x87/arithmetic/partial_remainder.py        Tue Jun 
18 16:10:22 2013 +0200
+++ b/src/arch/x86/isa/insts/x87/arithmetic/partial_remainder.py        Tue Jun 
18 16:10:42 2013 +0200
@@ -37,10 +37,10 @@
 
 microcode = '''
 def macroop FPREM {
-    premfp st(0), st(1), st(0)
+    premfp st(0), st(1), st(0), SetStatus=True
 };
 
 def macroop FPREM1 {
-    premfp st(0), st(1), st(0)
+    premfp st(0), st(1), st(0), SetStatus=True
 };
 '''
diff -r 9db8a438608c -r f2102d45a753 src/arch/x86/isa/microops/fpop.isa
--- a/src/arch/x86/isa/microops/fpop.isa        Tue Jun 18 16:10:22 2013 +0200
+++ b/src/arch/x86/isa/microops/fpop.isa        Tue Jun 18 16:10:42 2013 +0200
@@ -330,11 +330,34 @@
 
     class PremFp(FpBinaryOp):
         code = '''
-            FpDestReg = fmod(FpSrcReg1, FpSrcReg2);
-            DPRINTF(X86, "src1: %lf, src2: %lf, dest: %lf\\n", FpSrcReg1, 
FpSrcReg2, FpDestReg);
+            MiscReg new_fsw(FSW);
+            int src1_exp;
+            int src2_exp;
+            std::frexp(FpSrcReg1, &src1_exp);
+            std::frexp(FpSrcReg2, &src2_exp);
+
+            const int d(src2_exp - src1_exp);
+            if (d < 64) {
+                const int64_t q(std::trunc(FpSrcReg2 / FpSrcReg1));
+                FpDestReg = FpSrcReg2 - FpSrcReg1 * q;
+                new_fsw &= ~(CC0Bit | CC1Bit | CC2Bit | CC2Bit);
+                new_fsw |= (q & 0x1) ? CC1Bit : 0;
+                new_fsw |= (q & 0x2) ? CC3Bit : 0;
+                new_fsw |= (q & 0x4) ? CC0Bit : 0;
+            } else {
+                const int n(42);
+                const int64_t qq(std::trunc(
+                    FpSrcReg2 / std::ldexp(FpSrcReg1, d - n)));
+                FpDestReg = FpSrcReg2 - std::ldexp(FpSrcReg1 * qq, d - n);
+                new_fsw |= CC2Bit;
+            }
+            DPRINTF(X86, "src1: %lf, src2: %lf, dest: %lf, FSW: 0x%x\\n",
+                    FpSrcReg1, FpSrcReg2, FpDestReg, new_fsw);
         '''
         op_class = 'FloatDivOp'
 
+        flag_code = 'FSW = new_fsw;'
+
     class Compfp(FpBinaryOp):
         def __init__(self, src1, src2, spm=0, setStatus=False, \
                 dataSize="env.dataSize"):
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to