about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-06-14 12:19:21 +0200
committerptitSeb <sebastien.chev@gmail.com>2021-06-14 12:19:21 +0200
commit883fc1681d214efe8c2d43089e2e38900d6d7db2 (patch)
tree9d5a19abcebdc6bde925e453dc28bd18beab354d /src
parent6b2b672c5ec8adba9a5a184c114d678339cf6200 (diff)
downloadbox64-883fc1681d214efe8c2d43089e2e38900d6d7db2.tar.gz
box64-883fc1681d214efe8c2d43089e2e38900d6d7db2.zip
Added 66 0F 3A 0B opcode ([DYNAREC] too)
Diffstat (limited to 'src')
-rwxr-xr-xsrc/dynarec/arm64_emitter.h8
-rwxr-xr-xsrc/dynarec/dynarec_arm64_660f.c19
-rwxr-xr-xsrc/dynarec/dynarec_arm64_helper.c7
-rw-r--r--src/emu/x64run660f.c25
4 files changed, 54 insertions, 5 deletions
diff --git a/src/dynarec/arm64_emitter.h b/src/dynarec/arm64_emitter.h
index 3d3fe8f6..7de69a59 100755
--- a/src/dynarec/arm64_emitter.h
+++ b/src/dynarec/arm64_emitter.h
@@ -1208,10 +1208,18 @@
 #define FRINT64XD(Dd, Dn)           EMIT(FRINTxx_scalar(0b01, 0b11, Dn, Dd))
 
 #define FRINT_scalar(type, rmode, Rn, Rd)   (0b11110<<24 | (type)<<22 | 1<<21 | 0b001<<18 | (rmode)<<15 | 0b10000<<10 | (Rn)<<5 | (Rd))
+// round toward 0 (truncate)
 #define FRINTZS(Sd, Sn)             EMIT(FRINT_scalar(0b00, 0b011, Sn, Sd))
+// round toward 0 (truncate)
 #define FRINTZD(Sd, Sn)             EMIT(FRINT_scalar(0b01, 0b011, Sn, Sd))
+// round with current FPCR mode
 #define FRINTXS(Sd, Sn)             EMIT(FRINT_scalar(0b00, 0b110, Sn, Sd))
+// round with current FPCR mode
 #define FRINTXD(Sd, Sn)             EMIT(FRINT_scalar(0b01, 0b110, Sn, Sd))
+// round with mode, mode is 0 = TieEven, 1=+inf, 2=-inf, 3=zero
+#define FRINTRRS(Sd, Sn, mode)      EMIT(FRINT_scalar(0b00, ((mode)&3), Sn, Sd))
+// round with mode, mode is 0 = TieEven, 1=+inf, 2=-inf, 3=zero
+#define FRINTRRD(Dd, Dn, mode)      EMIT(FRINT_scalar(0b01, ((mode)&3), Dn, Dd))
 
 // FMAX / FMIN
 #define FMINMAX_vector(Q, U, o1, sz, Rm, Rn, Rd)    ((Q)<<30 | (U)<<29 | 0b01110<<24 | (o1)<<23 | (sz)<<22 | 0b1<<21 | (Rm)<<16 | 0b11110<<11 | 1<<10 | (Rn)<<5 | (Rd))
diff --git a/src/dynarec/dynarec_arm64_660f.c b/src/dynarec/dynarec_arm64_660f.c
index 45610ab0..66abfafa 100755
--- a/src/dynarec/dynarec_arm64_660f.c
+++ b/src/dynarec/dynarec_arm64_660f.c
@@ -319,6 +319,25 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
         case 0x3A:  // these are some more SSSE3 opcodes

             opcode = F8;

             switch(opcode) {

+                case 0x0B:

+                    INST_NAME("ROUNDSD Gx, Ex, Ib");

+                    nextop = F8;

+                    GETGX(q0);

+                    GETEX(q1, 1);

+                    u8 = F8;

+                    v1 = fpu_get_scratch(dyn);

+                    if(u8&4) {

+                        u8 = sse_setround(dyn, ninst, x1, x2, x3);

+                        FRINTXD(v1, q1);

+                        x87_restoreround(dyn, ninst, u8);

+                    } else {

+                        const uint8_t rounds[] = {0, 2, 1, 3};

+                        MAYUSE(rounds);

+                        FRINTRRD(v1, q1, rounds[u8&3]);

+                    }

+                    VMOVeD(q0, 0, v1, 0);

+                    break;

+

                 case 0x0F:

                     INST_NAME("PALIGNR Gx, Ex, Ib");

                     nextop = F8;

diff --git a/src/dynarec/dynarec_arm64_helper.c b/src/dynarec/dynarec_arm64_helper.c
index b0aedef6..3365cc6b 100755
--- a/src/dynarec/dynarec_arm64_helper.c
+++ b/src/dynarec/dynarec_arm64_helper.c
@@ -901,8 +901,6 @@ void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
 #endif
 }
 
-static int round_map[] = {0, 2, 1, 3};  // map x64 -> arm round flag
-
 // Set rounding according to cw flags, return reg to restore flags
 int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
 {
@@ -924,9 +922,8 @@ int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
     MAYUSE(dyn); MAYUSE(ninst);
     MAYUSE(s1); MAYUSE(s2);
     LDRH_U12(s1, xEmu, offsetof(x64emu_t, mxcsr));
-    UBFXx(s2, s1, 13, 2);    // extract round...
-    MOV64x(s1, (uintptr_t)round_map);
-    LDRw_REG_LSL2(s2, s1, s2);
+    RBITw(s2, s1);              // round is on bits 13-14 on x86,
+    LSRw(s2, s2, 17);           // but we want the reverse of that
     MRS_fpcr(s1);               // get fpscr
     MOVx_REG(s3, s1);
     BFIx(s1, s2, 22, 2);     // inject new round
diff --git a/src/emu/x64run660f.c b/src/emu/x64run660f.c
index 3b2ad0cf..0c287acd 100644
--- a/src/emu/x64run660f.c
+++ b/src/emu/x64run660f.c
@@ -309,6 +309,31 @@ int Run660F(x64emu_t *emu, rex_t rex)
     case 0x3A:  // these are some SSE3 opcodes

         opcode = F8;

         switch(opcode) {

+            case 0x0B:          // ROUNDSD Gx, Ex, u8

+                nextop = F8;

+                GETEX(1);

+                GETGX;

+                tmp8u = F8; // ignoring bit 3 interupt thingy

+                if(tmp8u&4)

+                    tmp8u = (emu->mxcsr>>13)&3;

+                else

+                    tmp8u &= 3;

+                switch(tmp8u) {

+                    case ROUND_Nearest:

+                        GX->d[0] = floor(EX->d[0]+0.5);

+                        break;

+                    case ROUND_Down:

+                        GX->d[0] = floor(EX->d[0]);

+                        break;

+                    case ROUND_Up:

+                        GX->d[0] = ceil(EX->d[0]);

+                        break;

+                    case ROUND_Chop:

+                        GX->d[0] = EX->d[0];

+                        break;

+                }

+                break;

+

             case 0x0F:          // PALIGNR GX, EX, u8

                 nextop = F8;

                 GETEX(1);