about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-05 18:05:42 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-03-05 18:05:42 +0100
commit51194642742de3f182328815c8aabdd6256a562e (patch)
tree9812df672edea0ab3b7eb114adfaaffb9764a2cb /src
parent4a418d72b6edb759cf1b2885493ab0116855d1b4 (diff)
downloadbox64-51194642742de3f182328815c8aabdd6256a562e.tar.gz
box64-51194642742de3f182328815c8aabdd6256a562e.zip
Added some x87 opcodes (D9 and DB prefixes)
Diffstat (limited to 'src')
-rwxr-xr-xsrc/emu/x64run.c18
-rwxr-xr-xsrc/emu/x64run_private.h4
-rw-r--r--src/emu/x64rund9.c289
-rw-r--r--src/emu/x64rundb.c186
4 files changed, 496 insertions, 1 deletions
diff --git a/src/emu/x64run.c b/src/emu/x64run.c
index a2a2113f..35dc865a 100755
--- a/src/emu/x64run.c
+++ b/src/emu/x64run.c
@@ -458,6 +458,24 @@ x64emurun:
             }
             break;
 
+        case 0xD9:                      /* x87 opcodes */
+            if(RunD9(emu, rex)) {
+                unimp = 1;
+                goto fini;
+            }
+            if(emu->quit)
+                goto fini;
+            break;
+
+        case 0xDB:                      /* x87 opcodes */
+            if(RunDB(emu, rex)) {
+                unimp = 1;
+                goto fini;
+            }
+            if(emu->quit)
+                goto fini;
+            break;
+
         case 0xE8:                      /* CALL Id */
             tmp32s = F32S; // call is relative
             Push(emu, R_RIP);
diff --git a/src/emu/x64run_private.h b/src/emu/x64run_private.h
index 2ba10b47..6dda57ec 100755
--- a/src/emu/x64run_private.h
+++ b/src/emu/x64run_private.h
@@ -226,9 +226,11 @@ void UpdateFlags(x64emu_t *emu);
 #define CHECK_FLAGS(emu) if(emu->df) UpdateFlags(emu)
 #define RESET_FLAGS(emu) emu->df = d_none
 
-//void Run67(x64emu_t *emu);
 int Run0F(x64emu_t *emu, rex_t rex);
 int Run66(x64emu_t *emu, rex_t rex);
+//int Run67(x64emu_t *emu, rex_t rex);
+int RunD9(x64emu_t *emu, rex_t rex);
+int RunDB(x64emu_t *emu, rex_t rex);
 //void Run660F(x64emu_t *emu);
 //void Run66D9(x64emu_t *emu);    // x87
 //void Run6766(x64emu_t *emu);
diff --git a/src/emu/x64rund9.c b/src/emu/x64rund9.c
new file mode 100644
index 00000000..52c4c46f
--- /dev/null
+++ b/src/emu/x64rund9.c
@@ -0,0 +1,289 @@
+#define _GNU_SOURCE

+#include <stdint.h>

+#include <stdio.h>

+#include <stdlib.h>

+#include <math.h>

+#include <string.h>

+#include <signal.h>

+#include <sys/types.h>

+#include <unistd.h>

+

+#include "debug.h"

+#include "box64stack.h"

+#include "x64emu.h"

+#include "x64run.h"

+#include "x64emu_private.h"

+#include "x64run_private.h"

+#include "x64primop.h"

+#include "x64trace.h"

+#include "x87emu_private.h"

+#include "box64context.h"

+//#include "my_cpuid.h"

+#include "bridge.h"

+//#include "signals.h"

+#ifdef DYNAREC

+#include "../dynarec/arm_lock_helper.h"

+#endif

+

+#include "modrm.h"

+

+int RunD9(x64emu_t *emu, rex_t rex)

+{

+    uint8_t nextop;

+    int32_t tmp32s;

+    uint64_t ll;

+    float f;

+    reg64_t *oped;

+

+    nextop = F8;

+    switch (nextop) {

+        case 0xC0:

+        case 0xC1:

+        case 0xC2:

+        case 0xC3:

+        case 0xC4:

+        case 0xC5:

+        case 0xC6:

+        case 0xC7:  /* FLD STx */

+            ll = ST(nextop&7).ll;

+            fpu_do_push(emu);

+            ST0.ll = ll;

+            break;

+        case 0xC8:

+        case 0xC9:

+        case 0xCA:

+        case 0xCB:

+        case 0xCC:

+        case 0xCD:

+        case 0xCE:

+        case 0xCF:  /* FXCH STx */

+            ll = ST(nextop&7).ll;

+            ST(nextop&7).ll = ST0.ll;

+            ST0.ll = ll;

+            break;

+

+        case 0xD0:  /* FNOP */

+            break;

+

+        case 0xE0:  /* FCHS */

+            ST0.d = -ST0.d;

+            break;

+        case 0xE1:  /* FABS */

+            ST0.d = fabs(ST0.d);

+            break;

+        

+        case 0xE4:  /* FTST */

+            fpu_ftst(emu);

+            break;

+        case 0xE5:  /* FXAM */

+            fpu_fxam(emu);

+            break;

+

+        case 0xE8:  /* FLD1 */

+            fpu_do_push(emu);

+            ST0.d = 1.0;

+            break;

+        case 0xE9:  /* FLDL2T */

+            fpu_do_push(emu);

+            ST0.d = L2T;

+            break;

+        case 0xEA:  /* FLDL2E */

+            fpu_do_push(emu);

+            ST0.d = L2E;

+            break;

+        case 0xEB:  /* FLDPI */

+            fpu_do_push(emu);

+            ST0.d = PI;

+            break;

+        case 0xEC:  /* FLDLG2 */

+            fpu_do_push(emu);

+            ST0.d = LG2;

+            break;

+        case 0xED:  /* FLDLN2 */

+            fpu_do_push(emu);

+            ST0.d = LN2;

+            break;

+        case 0xEE:  /* FLDZ */

+            fpu_do_push(emu);

+            ST0.d = 0.0;

+            break;

+

+        case 0xF0:  /* F2XM1 */

+            ST0.d = exp2(ST0.d) - 1.0;

+            break;

+        case 0xF1:  /* FYL2X */

+            ST(1).d *= log2(ST0.d);

+            fpu_do_pop(emu);

+            break;

+        case 0xF2:  /* FPTAN */

+            ST0.d = tan(ST0.d);

+            fpu_do_push(emu);

+            ST0.d = 1.0;

+            emu->sw.f.F87_C2 = 0;

+            break;

+        case 0xF3:  /* FPATAN */

+            ST1.d = atan2(ST1.d, ST0.d);

+            fpu_do_pop(emu);

+            break;

+        case 0xF4:  /* FXTRACT */

+            ST0.d = frexp(ST0.d, &tmp32s);

+            fpu_do_push(emu);

+            ST0.d = tmp32s;

+            break;

+

+        case 0xF8:  /* FPREM */

+            {

+                int e0, e1;

+                frexp(ST0.d, &e0);

+                frexp(ST1.d, &e1);

+                tmp32s = e0 - e1;

+            }

+            if(tmp32s<64)

+            {

+                ll = (int64_t)floor(ST0.d/ST1.d);

+                ST0.d = ST0.d - (ST1.d*ll);

+                emu->sw.f.F87_C2 = 0;

+                emu->sw.f.F87_C1 = (ll&1)?1:0;

+                emu->sw.f.F87_C3 = (ll&2)?1:0;

+                emu->sw.f.F87_C0 = (ll&4)?1:0;

+            } else {

+                ll = (int64_t)(floor((ST0.d/ST1.d))/exp2(tmp32s - 32));

+                ST0.d = ST0.d - ST1.d*ll*exp2(tmp32s - 32);

+                emu->sw.f.F87_C2 = 1;

+            }

+            break;

+        case 0xF5:  /* FPREM1 */

+            // get exponant(ST(0))-exponant(ST(1)) in temp32s

+            {

+                int e0, e1;

+                frexp(ST0.d, &e0);

+                frexp(ST1.d, &e1);

+                tmp32s = e0 - e1;

+            }

+            if(tmp32s<64)

+            {

+                ll = (int64_t)round(ST0.d/ST1.d);

+                ST0.d = ST0.d - (ST1.d*ll);

+                emu->sw.f.F87_C2 = 0;

+                emu->sw.f.F87_C1 = (ll&1)?1:0;

+                emu->sw.f.F87_C3 = (ll&2)?1:0;

+                emu->sw.f.F87_C0 = (ll&4)?1:0;

+            } else {

+                ll = (int64_t)(trunc((ST0.d/ST1.d))/exp2(tmp32s - 32));

+                ST0.d = ST0.d - ST1.d*ll*exp2(tmp32s - 32);

+                emu->sw.f.F87_C2 = 1;

+            }

+            break;

+        case 0xF6:  /* FDECSTP */

+            emu->top=(emu->top-1)&7;    // this will probably break a few things

+            break;

+        case 0xF7:  /* FINCSTP */

+            emu->top=(emu->top+1)&7;    // this will probably break a few things

+            break;

+        case 0xF9:  /* FYL2XP1 */

+            ST(1).d *= log2(ST0.d + 1.0);

+            fpu_do_pop(emu);

+            break;

+        case 0xFA:  /* FSQRT */

+            ST0.d = sqrt(ST0.d);

+            break;

+        case 0xFB:  /* FSINCOS */

+            fpu_do_push(emu);

+            sincos(ST1.d, &ST1.d, &ST0.d);

+            break;

+        case 0xFC:  /* FRNDINT */

+            ST0.d = fpu_round(emu, ST0.d);

+            break;

+        case 0xFD:  /* FSCALE */

+            // this could probably be done by just altering the exponant part of the float...

+            ST0.d *= exp2(trunc(ST1.d));

+            break;

+        case 0xFE:  /* FSIN */

+            ST0.d = sin(ST0.d);

+            break;

+        case 0xFF:  /* FCOS */

+            ST0.d = cos(ST0.d);

+            break;

+

+

+        case 0xD1:

+        case 0xD4:

+        case 0xD5:

+        case 0xD6:

+        case 0xD7:

+        case 0xD8:

+        case 0xD9:

+        case 0xDA:

+        case 0xDB:

+        case 0xDC:

+        case 0xDD:

+        case 0xDE:

+        case 0xDF:

+        case 0xE2:

+        case 0xE3:

+        case 0xE6:

+        case 0xE7:

+        case 0xEF:

+            return 1;

+        default:

+        switch((nextop>>3)&7) {

+            case 0:     /* FLD ST0, Ed float */

+                GETED;

+                fpu_do_push(emu);

+                if(!(((uintptr_t)ED)&3))

+                    ST0.d = *(float*)ED;

+                else {

+                    memcpy(&f, ED, sizeof(float));

+                    ST0.d = f;

+                }

+                break;

+            case 2:     /* FST Ed, ST0 */

+                GETED;

+                if(!(((uintptr_t)ED)&3))

+                    *(float*)ED = ST0.d;

+                else {

+                    f = ST0.d;

+                    memcpy(ED, &f, sizeof(float));

+                }

+                break;

+            case 3:     /* FSTP Ed, ST0 */

+                GETED;

+                if(!(((uintptr_t)ED)&3))

+                    *(float*)ED = ST0.d;

+                else {

+                    f = ST0.d;

+                    memcpy(ED, &f, sizeof(float));

+                }

+                fpu_do_pop(emu);

+                break;

+            case 4:     /* FLDENV m */

+                // warning, incomplete

+                GETED;

+                fpu_loadenv(emu, (char*)ED, 0);

+                break;

+            case 5:     /* FLDCW Ew */

+                GETEW;

+                emu->cw = EW->word[0];

+                // do something with cw?

+                emu->round = (fpu_round_t)((emu->cw >> 10) & 3);

+                break;

+            #if 0

+            case 6:     /* FNSTENV m */

+                // warning, incomplete

+                GETED;

+                fpu_savenv(emu, (char*)ED, 0);

+                // intruction pointer: 48bits

+                // data (operand) pointer: 48bits

+                // last opcode: 11bits save: 16bits restaured (1st and 2nd opcode only)

+                break;

+            #endif

+            case 7: /* FNSTCW Ew */

+                GETEW;

+                EW->word[0] = emu->cw;

+                break;

+            default:

+                return 1;

+        }

+    }

+   return 0;

+}
\ No newline at end of file
diff --git a/src/emu/x64rundb.c b/src/emu/x64rundb.c
new file mode 100644
index 00000000..30a16d44
--- /dev/null
+++ b/src/emu/x64rundb.c
@@ -0,0 +1,186 @@
+#define _GNU_SOURCE

+#include <stdint.h>

+#include <stdio.h>

+#include <stdlib.h>

+#include <math.h>

+#include <string.h>

+#include <signal.h>

+#include <sys/types.h>

+#include <unistd.h>

+

+#include "debug.h"

+#include "box64stack.h"

+#include "x64emu.h"

+#include "x64run.h"

+#include "x64emu_private.h"

+#include "x64run_private.h"

+#include "x64primop.h"

+#include "x64trace.h"

+#include "x87emu_private.h"

+#include "box64context.h"

+//#include "my_cpuid.h"

+#include "bridge.h"

+//#include "signals.h"

+#ifdef DYNAREC

+#include "../dynarec/arm_lock_helper.h"

+#endif

+

+#include "modrm.h"

+

+int RunDB(x64emu_t *emu, rex_t rex)

+{

+    uint8_t nextop;

+    int32_t tmp32s;

+    reg64_t *oped;

+

+    nextop = F8;

+    switch(nextop) {

+    case 0xC0:      /* FCMOVNB ST(0), ST(i) */

+    case 0xC1:

+    case 0xC2:

+    case 0xC3:

+    case 0xC4:

+    case 0xC5:

+    case 0xC6:

+    case 0xC7:

+        CHECK_FLAGS(emu);

+        if(!ACCESS_FLAG(F_CF))

+            ST0.ll = ST(nextop&7).ll;

+        break;

+    case 0xC8:      /* FCMOVNE ST(0), ST(i) */

+    case 0xC9:

+    case 0xCA:

+    case 0xCB:

+    case 0xCC:

+    case 0xCD:

+    case 0xCE:

+    case 0xCF:

+        CHECK_FLAGS(emu);

+        if(!ACCESS_FLAG(F_ZF))

+            ST0.ll = ST(nextop&7).ll;

+        break;

+    case 0xD0:      /* FCMOVNBE ST(0), ST(i) */

+    case 0xD1:

+    case 0xD2:

+    case 0xD3:

+    case 0xD4:

+    case 0xD5:

+    case 0xD6:

+    case 0xD7:

+        CHECK_FLAGS(emu);

+        if(!(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)))

+            ST0.ll = ST(nextop&7).ll;

+        break;

+    case 0xD8:      /* FCMOVNU ST(0), ST(i) */

+    case 0xD9:

+    case 0xDA:

+    case 0xDB:

+    case 0xDC:

+    case 0xDD:

+    case 0xDE:

+    case 0xDF:

+        CHECK_FLAGS(emu);

+        if(!ACCESS_FLAG(F_PF))

+            ST0.ll = ST(nextop&7).ll;

+        break;

+

+    case 0xE1:      /* FDISI8087_NOP */

+        break;

+    case 0xE2:      /* FNCLEX */

+        //Clears the floating-point exception flags (PE, UE, OE, ZE, DE, and IE), 

+        // the exception summary status flag (ES), the stack fault flag (SF), and the busy flag (B) in the FPU status word

+        emu->sw.f.F87_PE = 0;

+        emu->sw.f.F87_UE = 0;

+        emu->sw.f.F87_OE = 0;

+        emu->sw.f.F87_ZE = 0;

+        emu->sw.f.F87_DE = 0;

+        emu->sw.f.F87_IE = 0;

+        emu->sw.f.F87_ES = 0;

+        emu->sw.f.F87_SF = 0;

+        emu->sw.f.F87_B = 0;

+        break;

+    case 0xE3:      /* FNINIT */

+        reset_fpu(emu);

+        break;

+    case 0xE8:  /* FUCOMI ST0, STx */

+    case 0xE9:

+    case 0xEA:

+    case 0xEB:

+    case 0xEC:

+    case 0xED:

+    case 0xEE:

+    case 0xEF:

+        fpu_fcomi(emu, ST(nextop&7).d);   // bad, should handle QNaN and IA interrupt

+        break;

+

+    case 0xF0:  /* FCOMI ST0, STx */

+    case 0xF1:

+    case 0xF2:

+    case 0xF3:

+    case 0xF4:

+    case 0xF5:

+    case 0xF6:

+    case 0xF7:

+        fpu_fcomi(emu, ST(nextop&7).d);

+        break;

+    case 0xE0:

+    case 0xE4:

+    case 0xE5:

+    case 0xE6:

+    case 0xE7:

+        return 1;

+    default:

+        switch((nextop>>3)&7) {

+            case 0: /* FILD ST0, Ed */

+                GETED;

+                fpu_do_push(emu);

+                ST0.d = ED->sdword[0];

+                break;

+            case 1: /* FISTTP Ed, ST0 */

+                GETED;

+                tmp32s = ST0.d; // TODO: Handling of FPU Exception

+                if(tmp32s==0x7fffffff && isgreater(ST0.d, (double)(int32_t)0x7fffffff))

+                    tmp32s = 0x80000000;

+                fpu_do_pop(emu);

+                ED->sdword[0] = tmp32s;

+                break;

+            case 2: /* FIST Ed, ST0 */

+                GETED;

+                if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff) || !isfinite(ST0.d))

+                    ED->sdword[0] = 0x80000000;

+                else {

+                    volatile int32_t tmp = fpu_round(emu, ST0.d);    // tmp to avoid BUS ERROR

+                    ED->sdword[0] = tmp;

+                }

+                break;

+            case 3: /* FISTP Ed, ST0 */

+                GETED;

+                if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff) || !isfinite(ST0.d))

+                    ED->sdword[0] = 0x80000000;

+                else {

+                    volatile int32_t tmp = fpu_round(emu, ST0.d);    // tmp to avoid BUS ERROR

+                    ED->sdword[0] = tmp;

+                }

+                fpu_do_pop(emu);

+                break;

+            case 5: /* FLD ST0, Et */

+                GETED;

+                fpu_do_push(emu);

+                memcpy(&STld(0).ld, ED, 10);

+                LD2D(&STld(0), &ST(0).d);

+                STld(0).ref = ST0.ll;

+                break;

+            case 7: /* FSTP tbyte */

+                GETED;

+                if(ST0.ll!=STld(0).ref)

+                    D2LD(&ST0.d, ED);

+                else

+                    memcpy(ED, &STld(0).ld, 10);

+                fpu_do_pop(emu);

+                break;

+            default:

+                return 1;

+        }

+    }

+  return 0;

+}
\ No newline at end of file