about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2022-10-22 10:23:24 +0200
committerptitSeb <sebastien.chev@gmail.com>2022-10-22 10:23:24 +0200
commit21161ae38e0299e1072e061649925171b770d325 (patch)
tree279fa0a7eac5b16466ecb0ff41ad91696f6bc348 /src
parentaa074d71219b7b233735242400a10a70bff18d3b (diff)
downloadbox64-21161ae38e0299e1072e061649925171b770d325.tar.gz
box64-21161ae38e0299e1072e061649925171b770d325.zip
[DYNAREC] Added DE opcodes
Diffstat (limited to 'src')
-rwxr-xr-xsrc/dynarec/arm64/arm64_emitter.h28
-rwxr-xr-xsrc/dynarec/arm64/dynarec_arm64_00.c4
-rw-r--r--src/dynarec/arm64/dynarec_arm64_de.c284
-rwxr-xr-xsrc/dynarec/arm64/dynarec_arm64_helper.h2
4 files changed, 303 insertions, 15 deletions
diff --git a/src/dynarec/arm64/arm64_emitter.h b/src/dynarec/arm64/arm64_emitter.h
index 4b7d985a..fd714800 100755
--- a/src/dynarec/arm64/arm64_emitter.h
+++ b/src/dynarec/arm64/arm64_emitter.h
@@ -683,7 +683,9 @@
  
 // VLDR
 #define VMEM_gen(size, opc, imm12, Rn, Rt)  ((size)<<30 | 0b111<<27 | 1<<26 | 0b01<<24 | (opc)<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
-// imm14 must be 3-aligned
+// imm13 must be 1-aligned
+#define VLDR16_U12(Ht, Rn, imm13)           EMIT(VMEM_gen(0b01, 0b01, ((uint32_t)((imm13)>>1))&0xfff, Rn, Ht))
+// imm14 must be 2-aligned
 #define VLDR32_U12(Dt, Rn, imm14)           EMIT(VMEM_gen(0b10, 0b01, ((uint32_t)((imm14)>>2))&0xfff, Rn, Dt))
 // imm15 must be 3-aligned
 #define VLDR64_U12(Dt, Rn, imm15)           EMIT(VMEM_gen(0b11, 0b01, ((uint32_t)((imm15)>>3))&0xfff, Rn, Dt))
@@ -695,22 +697,22 @@
 #define VSTR64_U12(Dt, Rn, imm15)           EMIT(VMEM_gen(0b11, 0b00, ((uint32_t)(imm15>>3))&0xfff, Rn, Dt))
 // imm16 must be 4-aligned
 #define VSTR128_U12(Qt, Rn, imm16)          EMIT(VMEM_gen(0b00, 0b10, ((uint32_t)((imm16)>>4))&0xfff, Rn, Qt))
-// (imm14) must be 1-aligned
-#define VSTR16_U12(Ht, Rn, imm14)           EMIT(VMEM_gen(0b01, 0b00, ((uint32_t)(imm14>>1))&0xfff, Rn, Ht))
+// (imm13) must be 1-aligned
+#define VSTR16_U12(Ht, Rn, imm13)           EMIT(VMEM_gen(0b01, 0b00, ((uint32_t)(imm13>>1))&0xfff, Rn, Ht))
 
 #define VMEMUR_vector(size, opc, imm9, Rn, Rt)  ((size)<<30 | 0b111<<27 | 1<<26 | (opc)<<22 | (imm9)<<12 | (Rn)<<5 | (Rt))
 // signed offset, no alignement!
-#define VLDR8_I9(Vt, Rn, imm9)              EMIT(VMEMUR(0b00, 0b01, (imm9)&0b111111111, Rn, Vt))
-#define VLDR16_I9(Vt, Rn, imm9)             EMIT(VMEMUR(0b01, 0b01, (imm9)&0b111111111, Rn, Vt))
-#define VLDR32_I9(Vt, Rn, imm9)             EMIT(VMEMUR(0b10, 0b01, (imm9)&0b111111111, Rn, Vt))
-#define VLDR64_I9(Vt, Rn, imm9)             EMIT(VMEMUR(0b11, 0b01, (imm9)&0b111111111, Rn, Vt))
-#define VLDR128_I9(Vt, Rn, imm9)            EMIT(VMEMUR(0b00, 0b11, (imm9)&0b111111111, Rn, Vt))
+#define VLDR8_I9(Vt, Rn, imm9)              EMIT(VMEMUR_vector(0b00, 0b01, (imm9)&0b111111111, Rn, Vt))
+#define VLDR16_I9(Vt, Rn, imm9)             EMIT(VMEMUR_vector(0b01, 0b01, (imm9)&0b111111111, Rn, Vt))
+#define VLDR32_I9(Vt, Rn, imm9)             EMIT(VMEMUR_vector(0b10, 0b01, (imm9)&0b111111111, Rn, Vt))
+#define VLDR64_I9(Vt, Rn, imm9)             EMIT(VMEMUR_vector(0b11, 0b01, (imm9)&0b111111111, Rn, Vt))
+#define VLDR128_I9(Vt, Rn, imm9)            EMIT(VMEMUR_vector(0b00, 0b11, (imm9)&0b111111111, Rn, Vt))
 // signed offset, no alignement!
-#define VSTR8_I9(Vt, Rn, imm9)              EMIT(VMEMUR(0b00, 0b00, (imm9)&0b111111111, Rn, Vt))
-#define VSTR16_I9(Vt, Rn, imm9)             EMIT(VMEMUR(0b01, 0b00, (imm9)&0b111111111, Rn, Vt))
-#define VSTR32_I9(Vt, Rn, imm9)             EMIT(VMEMUR(0b10, 0b00, (imm9)&0b111111111, Rn, Vt))
-#define VSTR64_I9(Vt, Rn, imm9)             EMIT(VMEMUR(0b11, 0b00, (imm9)&0b111111111, Rn, Vt))
-#define VSTR128_I9(Vt, Rn, imm9)            EMIT(VMEMUR(0b00, 0b10, (imm9)&0b111111111, Rn, Vt))
+#define VSTR8_I9(Vt, Rn, imm9)              EMIT(VMEMUR_vector(0b00, 0b00, (imm9)&0b111111111, Rn, Vt))
+#define VSTR16_I9(Vt, Rn, imm9)             EMIT(VMEMUR_vector(0b01, 0b00, (imm9)&0b111111111, Rn, Vt))
+#define VSTR32_I9(Vt, Rn, imm9)             EMIT(VMEMUR_vector(0b10, 0b00, (imm9)&0b111111111, Rn, Vt))
+#define VSTR64_I9(Vt, Rn, imm9)             EMIT(VMEMUR_vector(0b11, 0b00, (imm9)&0b111111111, Rn, Vt))
+#define VSTR128_I9(Vt, Rn, imm9)            EMIT(VMEMUR_vector(0b00, 0b10, (imm9)&0b111111111, Rn, Vt))
 
 #define VMEMW_gen(size, opc, imm9, op2, Rn, Rt)  ((size)<<30 | 0b111<<27 | 1<<26 | (opc)<<22 | (imm9)<<12 | (op2)<<10 | 0b01<<10 | (Rn)<<5 | (Rt))
 #define VLDR64_S9_postindex(Rt, Rn, imm9)   EMIT(VMEMW_gen(0b11, 0b01, (imm9)&0x1ff, 0b01, Rn, Rt))
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c
index b662c0e1..4cdb7bea 100755
--- a/src/dynarec/arm64/dynarec_arm64_00.c
+++ b/src/dynarec/arm64/dynarec_arm64_00.c
@@ -2016,7 +2016,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
         case 0xDD:
             addr = dynarec64_DD(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
             break;
-
+        case 0xDE:
+            addr = dynarec64_DE(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
+            break;
         case 0xDF:
             addr = dynarec64_DF(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
             break;
diff --git a/src/dynarec/arm64/dynarec_arm64_de.c b/src/dynarec/arm64/dynarec_arm64_de.c
new file mode 100644
index 00000000..ae7fccb7
--- /dev/null
+++ b/src/dynarec/arm64/dynarec_arm64_de.c
@@ -0,0 +1,284 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <pthread.h>
+#include <errno.h>
+
+#include "debug.h"
+#include "box64context.h"
+#include "dynarec.h"
+#include "emu/x64emu_private.h"
+#include "emu/x64run_private.h"
+#include "x64run.h"
+#include "x64emu.h"
+#include "box64stack.h"
+#include "callback.h"
+#include "emu/x64run_private.h"
+#include "x64trace.h"
+#include "emu/x87emu_private.h"
+#include "dynarec_native.h"
+
+#include "arm64_printer.h"
+#include "dynarec_arm64_private.h"
+#include "dynarec_arm64_helper.h"
+#include "dynarec_arm64_functions.h"
+
+
+uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
+{
+    (void)ip; (void)rep; (void)need_epilog;
+
+    uint8_t nextop = F8;
+    uint8_t wback;
+    int64_t fixedaddress;
+    int v1, v2;
+
+    MAYUSE(v2);
+    MAYUSE(v1);
+
+    switch(nextop) {
+        case 0xC0:
+        case 0xC1:
+        case 0xC2:
+        case 0xC3:
+        case 0xC4:
+        case 0xC5:
+        case 0xC6:
+        case 0xC7:
+            INST_NAME("FADDP STx, ST0");
+            v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
+            v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
+            if(ST_IS_F(0)) {
+                FADDS(v1, v1, v2);
+            } else {
+                FADDD(v1, v1, v2);
+            }
+            x87_do_pop(dyn, ninst, x3);
+            break;
+        case 0xC8:
+        case 0xC9:
+        case 0xCA:
+        case 0xCB:
+        case 0xCC:
+        case 0xCD:
+        case 0xCE:
+        case 0xCF:
+            INST_NAME("FMULP STx, ST0");
+            v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
+            v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
+            if(ST_IS_F(0)) {
+                FMULS(v1, v1, v2);
+            } else {
+                FMULD(v1, v1, v2);
+            }
+            x87_do_pop(dyn, ninst, x3);
+            break;
+        case 0xD0:
+        case 0xD1:
+        case 0xD2:
+        case 0xD3:
+        case 0xD4:
+        case 0xD5:
+        case 0xD6:
+        case 0xD7:
+            INST_NAME("FCOMP ST0, STx"); //yep
+            v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
+            v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
+            if(ST_IS_F(0)) {
+                FCMPS(v1, v2);
+            } else {
+                FCMPD(v1, v2);
+            }
+            FCOM(x1, x2, x3);
+            x87_do_pop(dyn, ninst, x3);
+            break;
+        case 0xD9:
+            INST_NAME("FCOMPP ST0, STx");
+            v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
+            v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
+            if(ST_IS_F(0)) {
+                FCMPS(v1, v2);
+            } else {
+                FCMPD(v1, v2);
+            }
+            FCOM(x1, x2, x3);
+            x87_do_pop(dyn, ninst, x3);
+            x87_do_pop(dyn, ninst, x3);
+            break;
+        case 0xE0:
+        case 0xE1:
+        case 0xE2:
+        case 0xE3:
+        case 0xE4:
+        case 0xE5:
+        case 0xE6:
+        case 0xE7:
+            INST_NAME("FSUBRP STx, ST0");
+            v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
+            v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
+            if(ST_IS_F(0)) {
+                FSUBS(v1, v2, v1);
+            } else {
+                FSUBD(v1, v2, v1);
+            }
+            x87_do_pop(dyn, ninst, x3);
+            break;
+        case 0xE8:
+        case 0xE9:
+        case 0xEA:
+        case 0xEB:
+        case 0xEC:
+        case 0xED:
+        case 0xEE:
+        case 0xEF:
+            INST_NAME("FSUBP STx, ST0");
+            v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
+            v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
+            if(ST_IS_F(0)) {
+                FSUBS(v1, v1, v2);
+            } else {
+                FSUBD(v1, v1, v2);
+            }
+            x87_do_pop(dyn, ninst, x3);
+            break;
+        case 0xF0:
+        case 0xF1:
+        case 0xF2:
+        case 0xF3:
+        case 0xF4:
+        case 0xF5:
+        case 0xF6:
+        case 0xF7:
+            INST_NAME("FDIVRP STx, ST0");
+            v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
+            v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
+            if(ST_IS_F(0)) {
+                FDIVS(v1, v2, v1);
+            } else {
+                FDIVD(v1, v2, v1);
+            }
+            x87_do_pop(dyn, ninst, x3);
+            break;       
+        case 0xF8:
+        case 0xF9:
+        case 0xFA:
+        case 0xFB:
+        case 0xFC:
+        case 0xFD:
+        case 0xFE:
+        case 0xFF:
+            INST_NAME("FDIVP STx, ST0");
+            v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
+            v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
+            if(ST_IS_F(0)) {
+                FDIVS(v1, v1, v2);
+            } else {
+                FDIVD(v1, v1, v2);
+            }
+            x87_do_pop(dyn, ninst, x3);
+            break;
+        case 0xD8:
+        case 0xDA:
+        case 0xDB:
+        case 0xDC:
+        case 0xDD:
+        case 0xDE:
+        case 0xDF:
+            return 0;
+        default:
+            switch((nextop>>3)&7) {
+                case 0:
+                    INST_NAME("FIADD ST0, word[ED]");
+                    v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
+                    v2 = fpu_get_scratch(dyn);
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
+                    VLDR16_U12(v2, wback, fixedaddress);
+                    SXTL_16(v2, v2);
+                    SXTL_32(v2, v2);
+                    SCVTFDD(v2, v2);
+                    FADDD(v1, v1, v2);
+                    break;
+                case 1:
+                    INST_NAME("FIMUL ST0, word[ED]");
+                    v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
+                    v2 = fpu_get_scratch(dyn);
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
+                    VLDR16_U12(v2, wback, fixedaddress);
+                    SXTL_16(v2, v2);
+                    SXTL_32(v2, v2);
+                    SCVTFDD(v2, v2);
+                    FMULD(v1, v1, v2);
+                    break;
+                case 2:
+                    INST_NAME("FICOM ST0, word[ED]");
+                    v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
+                    v2 = fpu_get_scratch(dyn);
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
+                    VLDR16_U12(v2, wback, fixedaddress);
+                    SXTL_16(v2, v2);
+                    SXTL_32(v2, v2);
+                    SCVTFDD(v2, v2);
+                    FCMPD(v1, v2);
+                    FCOM(x1, x2, x3);
+                    break;
+                case 3:
+                    INST_NAME("FICOMP ST0, word[ED]");
+                    v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
+                    v2 = fpu_get_scratch(dyn);
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
+                    VLDR16_U12(v2, wback, fixedaddress);
+                    SXTL_16(v2, v2);
+                    SXTL_32(v2, v2);
+                    SCVTFDD(v2, v2);
+                    FCMPD(v1, v2);
+                    FCOM(x1, x2, x3);
+                    x87_do_pop(dyn, ninst, x3);
+                    break;
+                case 4:
+                    INST_NAME("FISUB ST0, word[ED]");
+                    v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
+                    v2 = fpu_get_scratch(dyn);
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
+                    VLDR16_U12(v2, wback, fixedaddress);
+                    SXTL_16(v2, v2);
+                    SXTL_32(v2, v2);
+                    SCVTFDD(v2, v2);
+                    FSUBD(v1, v1, v2);
+                    break;
+                case 5:
+                    INST_NAME("FISUBR ST0, word[ED]");
+                    v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
+                    v2 = fpu_get_scratch(dyn);
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
+                    VLDR16_U12(v2, wback, fixedaddress);
+                    SXTL_16(v2, v2);
+                    SXTL_32(v2, v2);
+                    SCVTFDD(v2, v2);
+                    FSUBD(v1, v2, v1);
+                    break;
+                case 6:
+                    INST_NAME("FIDIV ST0, word[ED]");
+                    v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
+                    v2 = fpu_get_scratch(dyn);
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
+                    VLDR16_U12(v2, wback, fixedaddress);
+                    SXTL_16(v2, v2);
+                    SXTL_32(v2, v2);
+                    SCVTFDD(v2, v2);
+                    FDIVD(v1, v1, v2);
+                    break;
+                case 7:
+                    INST_NAME("FIDIVR ST0, word[ED]");
+                    v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
+                    v2 = fpu_get_scratch(dyn);
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
+                    VLDR16_U12(v2, wback, fixedaddress);
+                    SXTL_16(v2, v2);
+                    SXTL_32(v2, v2);
+                    SCVTFDD(v2, v2);
+                    FDIVD(v1, v2, v1);
+                    break;
+            }
+    }
+    return addr;
+}
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h
index 6472989a..ef9508cd 100755
--- a/src/dynarec/arm64/dynarec_arm64_helper.h
+++ b/src/dynarec/arm64/dynarec_arm64_helper.h
@@ -1060,7 +1060,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
 uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
-//uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
+uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);