diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-04-03 14:32:04 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-04-03 14:32:04 +0200 |
| commit | a8495b00f2dd4475a04f58509c762f1efdca048d (patch) | |
| tree | 5693e1cefc40c8932f3e3a66974c2572ef2da6bd | |
| parent | ae70f168a8dd40b3d903eac2170f107ea9f0d127 (diff) | |
| download | box64-a8495b00f2dd4475a04f58509c762f1efdca048d.tar.gz box64-a8495b00f2dd4475a04f58509c762f1efdca048d.zip | |
[DYNAREC] Added DB opcodes
| -rwxr-xr-x | CMakeLists.txt | 2 | ||||
| -rwxr-xr-x | src/dynarec/arm64_emitter.h | 23 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_00.c | 4 | ||||
| -rw-r--r-- | src/dynarec/dynarec_arm64_db.c | 247 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_helper.c | 12 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_helper.h | 5 |
6 files changed, 281 insertions, 12 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e7ed6f3..d7e124df 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -289,7 +289,7 @@ if(ARM_DYNAREC) #"${BOX64_ROOT}/src/dynarec/dynarec_arm64_d8.c" "${BOX64_ROOT}/src/dynarec/dynarec_arm64_d9.c" #"${BOX64_ROOT}/src/dynarec/dynarec_arm64_da.c" - #"${BOX64_ROOT}/src/dynarec/dynarec_arm64_db.c" + "${BOX64_ROOT}/src/dynarec/dynarec_arm64_db.c" #"${BOX64_ROOT}/src/dynarec/dynarec_arm64_dc.c" #"${BOX64_ROOT}/src/dynarec/dynarec_arm64_dd.c" #"${BOX64_ROOT}/src/dynarec/dynarec_arm64_de.c" diff --git a/src/dynarec/arm64_emitter.h b/src/dynarec/arm64_emitter.h index d7e2a007..8695771b 100755 --- a/src/dynarec/arm64_emitter.h +++ b/src/dynarec/arm64_emitter.h @@ -612,8 +612,13 @@ // MSR : to System register #define MSR_nzvc(Rt) EMIT(MRS_gen(0, 1, 3, 4, 2, 0, Rt)) // mrs x0, fpcr : 1101010100 1 1 1 011 0100 0100 000 00000 o0=1(op0=3), op1=0b011(3) CRn=0b0100(4) CRm=0b0100(4) op2=2 -#define VMRS(Rt) EMIT(MRS_gen(1, 1, 3, 4, 4, 0, Rt)) -#define VMSR(Rt) EMIT(MRS_gen(0, 1, 3, 4, 4, 0, Rt)) +#define MRS_fpcr(Rt) EMIT(MRS_gen(1, 1, 3, 4, 4, 0, Rt)) +#define MSR_fpcr(Rt) EMIT(MRS_gen(0, 1, 3, 4, 4, 0, Rt)) + +// FCSEL +#define FCSEL_scalar(type, Rm, cond, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | (Rm)<<16 | (cond)<<12 | 0b11<<10 | (Rn)<<5 | (Rd)) +#define FCSELS(Sd, Sn, Sm, cond) EMIT(FCSEL_scalar(0b00, Sm, cond, Sn, Sd)) +#define FCSELD(Dd, Dn, Dm, cond) EMIT(FCSEL_scalar(0b01, Dm, cond, Dn, Dd)) // VLDR #define VMEM_gen(size, opc, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | 1<<26 | 0b01<<24 | (opc)<<22 | (imm12)<<10 | (Rn)<<5 | (Rt)) @@ -1098,8 +1103,8 @@ #define SCVTFDx(Dd, Xn) EMIT(SCVTF_scalar(1, 0b01, 0b00, 0b010, Xn, Dd)) #define SCVTF_vector_scalar(U, sz, Rn, Rd) (1<<30 | (U)<<29 | 0b11110<<24 | (sz)<<22 | 0b10000<<17 | 0b11101<<12 | 0b10<<10 | (Rn)<<5 | (Rd)) -#define SCVTFSS(Vd, Vn) EMIT(SCVT_vector_scalar(0, 0, Vn, Vd)) -#define SCVTFDD(Vd, Vn) EMIT(SCVT_vector_scalar(0, 1, Vn, Vd)) +#define SCVTFSS(Vd, Vn) EMIT(SCVTF_vector_scalar(0, 0, Vn, Vd)) +#define SCVTFDD(Vd, Vn) EMIT(SCVTF_vector_scalar(0, 1, Vn, Vd)) #define SCVTF_vector(Q, U, sz, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (sz)<<22 | 0b10000<<17 | 0b11101<<12 | 0b10<<10 | (Rn)<<5 | (Rd)) #define SCVTFS(Vd, Vn) EMIT(SCVTF_vector(0, 0, 0, Vn, Vd)) @@ -1113,6 +1118,16 @@ #define VFRINTISQ(Vd,Vn) EMIT(FRINT_vector(1, 1, 1, 0, 1, Vn, Vd)) #define VFRINTIDQ(Vd,Vn) EMIT(FRINT_vector(1, 1, 1, 1, 1, Vn, Vd)) +#define FRINT_scalar(type, op, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | 0b0100<<17 | (op)<<15 | 0b10000<<10 | (Rn)<<5 | (Rd)) +#define FRINT32ZS(Sd, Sn) EMIT(FRINT_scalar(0b00, 0b00, Sn, Sd)) +#define FRINT32ZD(Dd, Dn) EMIT(FRINT_scalar(0b01, 0b00, Dn, Dd)) +#define FRINT32XS(Sd, Sn) EMIT(FRINT_scalar(0b00, 0b01, Sn, Sd)) +#define FRINT32XD(Dd, Dn) EMIT(FRINT_scalar(0b01, 0b01, Dn, Dd)) +#define FRINT64ZS(Sd, Sn) EMIT(FRINT_scalar(0b00, 0b10, Sn, Sd)) +#define FRINT64ZD(Dd, Dn) EMIT(FRINT_scalar(0b01, 0b10, Dn, Dd)) +#define FRINT64XS(Sd, Sn) EMIT(FRINT_scalar(0b00, 0b11, Sn, Sd)) +#define FRINT64XD(Dd, Dn) EMIT(FRINT_scalar(0b01, 0b11, 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)) #define VFMINS(Vd, Vn, Vm) EMIT(FMINMAX_vector(0, 0, 1, 0, Vm, Vn, Vd)) diff --git a/src/dynarec/dynarec_arm64_00.c b/src/dynarec/dynarec_arm64_00.c index 9329cf3d..e2a8c339 100755 --- a/src/dynarec/dynarec_arm64_00.c +++ b/src/dynarec/dynarec_arm64_00.c @@ -1833,6 +1833,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin addr = dynarec64_D9(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); break; + case 0xDB: + addr = dynarec64_DB(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); + break; + case 0xE8: INST_NAME("CALL Id"); i32 = F32S; diff --git a/src/dynarec/dynarec_arm64_db.c b/src/dynarec/dynarec_arm64_db.c new file mode 100644 index 00000000..b271d860 --- /dev/null +++ b/src/dynarec/dynarec_arm64_db.c @@ -0,0 +1,247 @@ +#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 "dynarec_arm64.h" +#include "dynarec_arm64_private.h" +#include "arm64_printer.h" +#include "emu/x87emu_private.h" + +#include "dynarec_arm64_helper.h" +#include "dynarec_arm64_functions.h" + + +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) +{ + uint8_t nextop = F8; + uint8_t ed; + uint8_t wback; + uint8_t u8; + int fixedaddress; + int v1, v2; + int s0; + int j32; + + MAYUSE(s0); + MAYUSE(v2); + MAYUSE(v1); + MAYUSE(j32); + + switch(nextop) { + case 0xC0: + case 0xC1: + case 0xC2: + case 0xC3: + case 0xC4: + case 0xC5: + case 0xC6: + case 0xC7: + INST_NAME("FCMOVNB ST0, STx"); + READFLAGS(X_CF); + v1 = x87_get_st(dyn, ninst, x1, x2, 0); + v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7); + TSTw_mask(xFlags, 0, 0); //mask=1<<F_CF + FCSELD(v1, v2, v1, cEQ); // F_CF==0 + break; + case 0xC8: + case 0xC9: + case 0xCA: + case 0xCB: + case 0xCC: + case 0xCD: + case 0xCE: + case 0xCF: + INST_NAME("FCMOVNE ST0, STx"); + READFLAGS(X_ZF); + v1 = x87_get_st(dyn, ninst, x1, x2, 0); + v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7); + TSTw_mask(xFlags, 0b011010, 0); //mask=1<<F_ZF + FCSELD(v1, v2, v1, cEQ); // F_ZF==0 + break; + case 0xD0: + case 0xD1: + case 0xD2: + case 0xD3: + case 0xD4: + case 0xD5: + case 0xD6: + case 0xD7: + INST_NAME("FCMOVNBE ST0, STx"); + READFLAGS(X_CF|X_ZF); + v1 = x87_get_st(dyn, ninst, x1, x2, 0); + v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7); + MOV32w(x1, (1<<F_CF)|(1<<F_ZF)); + TSTw_REG(xFlags, x1); + FCSELD(v1, v2, v1, cEQ); // F_CF==0 & F_ZF==0 + break; + case 0xD8: + case 0xD9: + case 0xDA: + case 0xDB: + case 0xDC: + case 0xDD: + case 0xDE: + case 0xDF: + INST_NAME("FCMOVNU ST0, STx"); + READFLAGS(X_PF); + v1 = x87_get_st(dyn, ninst, x1, x2, 0); + v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7); + TSTw_mask(xFlags, 0b011110, 0); //mask=1<<F_PF + FCSELD(v1, v2, v1, cEQ); // F_PF==0 + break; + case 0xE1: + INST_NAME("FDISI8087_NOP"); // so.. NOP? + break; + case 0xE2: + INST_NAME("FNCLEX"); + LDRH_U12(x2, xEmu, offsetof(x64emu_t, sw)); + MOV32w(x1, 0); + BFIw(x2, x1, 0, 8); // IE .. PE, SF, ES + BFIw(x2, x1, 15, 1); // B + STRH_U12(x2, xEmu, offsetof(x64emu_t, sw)); + break; + case 0xE3: + INST_NAME("FNINIT"); + x87_purgecache(dyn, ninst, x1, x2, x3); + CALL(reset_fpu, -1); + break; + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xED: + case 0xEE: + case 0xEF: + INST_NAME("FUCOMI ST0, STx"); + SETFLAGS(X_ALL, SF_SET); + v1 = x87_get_st(dyn, ninst, x1, x2, 0); + v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7); + FCMPD(v1, v2); + FCOMI(x1, x2); + break; + case 0xF0: + case 0xF1: + case 0xF2: + case 0xF3: + case 0xF4: + case 0xF5: + case 0xF6: + case 0xF7: + INST_NAME("FCOMI ST0, STx"); + SETFLAGS(X_ALL, SF_SET); + v1 = x87_get_st(dyn, ninst, x1, x2, 0); + v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7); + FCMPD(v1, v2); + FCOMI(x1, x2); + break; + + case 0xE0: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + DEFAULT; + break; + + default: + switch((nextop>>3)&7) { + case 0: + INST_NAME("FILD ST0, Ed"); + v1 = x87_do_push(dyn, ninst); + s0 = fpu_get_scratch(dyn); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0); + VLDR32_U12(s0, ed, fixedaddress); + SXTL_32(v1, s0); + SCVTFDD(v1, v1); + break; + case 1: + INST_NAME("FISTTP Ed, ST0"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0); + if(MODREG) { + ed = xRAX+(nextop&7)+(rex.b<<3); + wback = 0; + } else { + addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0); + ed = x1; + } + s0 = fpu_get_scratch(dyn); + FRINT32ZD(s0, v1); + FCVTZSwD(ed, s0); + WBACK; + x87_do_pop(dyn, ninst); + break; + case 2: + INST_NAME("FIST Ed, ST0"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0); + u8 = x87_setround(dyn, ninst, x1, x2, x4); // x1 have the modified RPSCR reg + if(MODREG) { + ed = xRAX+(nextop&7)+(rex.b<<3); + wback = 0; + } else { + addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0); + ed = x1; + } + s0 = fpu_get_scratch(dyn); + FRINT32XD(s0, v1); + FCVTZSwD(ed, s0); + WBACK; + x87_restoreround(dyn, ninst, u8); + break; + case 3: + INST_NAME("FISTP Ed, ST0"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0); + u8 = x87_setround(dyn, ninst, x1, x2, x4); // x1 have the modified RPSCR reg + if(MODREG) { + ed = xRAX+(nextop&7)+(rex.b<<3); + wback = 0; + } else { + addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0); + ed = x1; + } + s0 = fpu_get_scratch(dyn); + FRINT32XD(s0, v1); + FCVTZSwD(ed, s0); + WBACK; + x87_restoreround(dyn, ninst, u8); + x87_do_pop(dyn, ninst); + break; + case 5: + INST_NAME("FLD tbyte"); + x87_do_push_empty(dyn, ninst, x1); + addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0); + if(ed!=x1) { + MOVx_REG(x1, ed); + } + CALL(arm_fld, -1); + break; + case 7: + INST_NAME("FSTP tbyte"); + x87_forget(dyn, ninst, x1, x3, 0); + addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0); + if(ed!=x1) { + MOVx_REG(x1, ed); + } + CALL(arm_fstp, -1); + x87_do_pop(dyn, ninst); + break; + default: + DEFAULT; + } + } + return addr; +} + diff --git a/src/dynarec/dynarec_arm64_helper.c b/src/dynarec/dynarec_arm64_helper.c index b5193bb1..07d2ed0a 100755 --- a/src/dynarec/dynarec_arm64_helper.c +++ b/src/dynarec/dynarec_arm64_helper.c @@ -602,7 +602,7 @@ void x87_do_pop(dynarec_arm_t* dyn, int ninst) #endif } -static void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3) +void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3) { #if STEP > 1 int ret = 0; @@ -850,10 +850,10 @@ int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3) UBFXx(s2, s1, 10, 2); // extract round... MOV64x(s1, (uintptr_t)round_map); LDRw_REG_LSL2(s2, s1, s2); - VMRS(s1); // get fpscr + MRS_fpcr(s1); // get fpscr MOVx_REG(s3, s1); BFIx(s1, s2, 22, 2); // inject new round - VMSR(s1); // put new fpscr + MSR_fpcr(s1); // put new fpscr return s3; } @@ -864,17 +864,17 @@ int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3) UBFXx(s2, s1, 13, 2); // extract round... MOV64x(s1, (uintptr_t)round_map); LDRw_REG_LSL2(s2, s1, s2); - VMRS(s1); // get fpscr + MRS_fpcr(s1); // get fpscr MOVx_REG(s3, s1); BFIx(s1, s2, 22, 2); // inject new round - VMSR(s1); // put new fpscr + MSR_fpcr(s1); // put new fpscr return s3; } // Restore round flag void x87_restoreround(dynarec_arm_t* dyn, int ninst, int s1) { - VMSR(s1); // put back fpscr + MSR_fpcr(s1); // put back fpscr } // MMX helpers diff --git a/src/dynarec/dynarec_arm64_helper.h b/src/dynarec/dynarec_arm64_helper.h index 26557afe..438ec223 100755 --- a/src/dynarec/dynarec_arm64_helper.h +++ b/src/dynarec/dynarec_arm64_helper.h @@ -682,6 +682,7 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr); #define fpu_reset STEPNAME(fpu_reset) #define fpu_purgecache STEPNAME(fpu_purgecache) #define mmx_purgecache STEPNAME(mmx_purgecache) +#define x87_purgecache STEPNAME(x87_purgecache) #ifdef HAVE_TRACE #define fpu_reflectcache STEPNAME(fpu_reflectcache) #endif @@ -823,6 +824,8 @@ void fpu_reset(dynarec_arm_t* dyn, int ninst); void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3); // purge MMX cache void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int s1); +// purge x87 cache +void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3); #ifdef HAVE_TRACE void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3); #endif @@ -838,7 +841,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin //uintptr_t dynarec64_D8(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_D9(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_DA(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_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_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); |