diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-03-18 15:08:26 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-03-18 15:08:26 +0100 |
| commit | cb25e077f99e608ecce1f8358ea9f33421a1e810 (patch) | |
| tree | 3da1e920bae17c9ae840bb1ec7e40004deaf5abc /src | |
| parent | 0551f13f0ee258d6325285e20833328950e18bbc (diff) | |
| download | box64-cb25e077f99e608ecce1f8358ea9f33421a1e810.tar.gz box64-cb25e077f99e608ecce1f8358ea9f33421a1e810.zip | |
[DYNAREC] Added CC 'Native call' and 0F 1F NOP opcodes
Diffstat (limited to 'src')
| -rwxr-xr-x | src/dynarec/arm64_epilog.S | 60 | ||||
| -rwxr-xr-x | src/dynarec/arm64_printer.c | 2 | ||||
| -rwxr-xr-x | src/dynarec/arm64_prolog.S | 29 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_00.c | 57 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_0f.c | 98 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_helper.h | 14 | ||||
| -rwxr-xr-x | src/emu/x64emu_private.h | 4 | ||||
| -rwxr-xr-x | src/main.c | 3 |
8 files changed, 199 insertions, 68 deletions
diff --git a/src/dynarec/arm64_epilog.S b/src/dynarec/arm64_epilog.S index 99723873..1a3b3ddc 100755 --- a/src/dynarec/arm64_epilog.S +++ b/src/dynarec/arm64_epilog.S @@ -29,25 +29,16 @@ arm64_epilog: str x27, [x0, (8 * 17)] // put back reg value in emu, including EIP (so x27 must be EIP now) //restore all used register //vpop {d8-d15} - ldr x10, [sp, (8 * 0)] - ldr x11, [sp, (8 * 1)] - ldr x12, [sp, (8 * 2)] - ldr x13, [sp, (8 * 3)] - ldr x14, [sp, (8 * 4)] - ldr x15, [sp, (8 * 5)] - ldr x16, [sp, (8 * 6)] - ldr x17, [sp, (8 * 7)] - ldr x18, [sp, (8 * 8)] - ldr x19, [sp, (8 * 9)] - ldr x20, [sp, (8 * 10)] - ldr x21, [sp, (8 * 11)] - ldr x22, [sp, (8 * 12)] - ldr x23, [sp, (8 * 13)] - ldr x24, [sp, (8 * 14)] - ldr x25, [sp, (8 * 15)] - ldr x26, [sp, (8 * 16)] - ldr x27, [sp, (8 * 17)] - add sp, sp, (8 * 18) + ldr x19, [sp, (8 * 0)] + ldr x20, [sp, (8 * 1)] + ldr x21, [sp, (8 * 2)] + ldr x22, [sp, (8 * 3)] + ldr x23, [sp, (8 * 4)] + ldr x24, [sp, (8 * 5)] + ldr x25, [sp, (8 * 6)] + ldr x26, [sp, (8 * 7)] + ldr x27, [sp, (8 * 8)] + add sp, sp, (8 * 10) ldp lr, fp, [sp], 16 // saved lr //end, return... ret @@ -57,25 +48,16 @@ arm64_epilog: arm64_epilog_fast: //restore all used register //vpop {d8-d15} - ldr x10, [sp, (8 * 0)] - ldr x11, [sp, (8 * 1)] - ldr x12, [sp, (8 * 2)] - ldr x13, [sp, (8 * 3)] - ldr x14, [sp, (8 * 4)] - ldr x15, [sp, (8 * 5)] - ldr x16, [sp, (8 * 6)] - ldr x17, [sp, (8 * 7)] - ldr x18, [sp, (8 * 8)] - ldr x19, [sp, (8 * 9)] - ldr x20, [sp, (8 * 10)] - ldr x21, [sp, (8 * 11)] - ldr x22, [sp, (8 * 12)] - ldr x23, [sp, (8 * 13)] - ldr x24, [sp, (8 * 14)] - ldr x25, [sp, (8 * 15)] - ldr x26, [sp, (8 * 16)] - ldr x27, [sp, (8 * 17)] - add sp, sp, (8 * 18) - ldp lr, fp, [sp, 16]! // saved lr + ldr x19, [sp, (8 * 0)] + ldr x20, [sp, (8 * 1)] + ldr x21, [sp, (8 * 2)] + ldr x22, [sp, (8 * 3)] + ldr x23, [sp, (8 * 4)] + ldr x24, [sp, (8 * 5)] + ldr x25, [sp, (8 * 6)] + ldr x26, [sp, (8 * 7)] + ldr x27, [sp, (8 * 8)] + add sp, sp, (8 * 10) + ldp lr, fp, [sp], 16 // saved lr //end, return... ret diff --git a/src/dynarec/arm64_printer.c b/src/dynarec/arm64_printer.c index 082260b9..0f9abb55 100755 --- a/src/dynarec/arm64_printer.c +++ b/src/dynarec/arm64_printer.c @@ -423,6 +423,8 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr) snprintf(buff, sizeof(buff), "UXTB %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn]); else if(immr==0 && imms==0b001111) snprintf(buff, sizeof(buff), "UXTH %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn]); + else if(imms>=immr) + snprintf(buff, sizeof(buff), "UBFX %s, %s, %d, %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], immr, imms-immr+1); else snprintf(buff, sizeof(buff), "UBFM %s, %s, %d, %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], immr, imms); diff --git a/src/dynarec/arm64_prolog.S b/src/dynarec/arm64_prolog.S index c1dc3b48..679af0ce 100755 --- a/src/dynarec/arm64_prolog.S +++ b/src/dynarec/arm64_prolog.S @@ -10,25 +10,16 @@ arm64_prolog: //save all 18 used register stp lr, fp, [sp, -16]! // save lr - sub sp, sp, (8 * 18) - str x10, [sp, (8 * 0)] - str x11, [sp, (8 * 1)] - str x12, [sp, (8 * 2)] - str x13, [sp, (8 * 3)] - str x14, [sp, (8 * 4)] - str x15, [sp, (8 * 5)] - str x16, [sp, (8 * 6)] - str x17, [sp, (8 * 7)] - str x18, [sp, (8 * 8)] - str x19, [sp, (8 * 9)] - str x20, [sp, (8 * 10)] - str x21, [sp, (8 * 11)] - str x22, [sp, (8 * 12)] - str x23, [sp, (8 * 13)] - str x24, [sp, (8 * 14)] - str x25, [sp, (8 * 15)] - str x26, [sp, (8 * 16)] - str x27, [sp, (8 * 17)] + sub sp, sp, (8 * 10) + str x19, [sp, (8 * 0)] + str x20, [sp, (8 * 1)] + str x21, [sp, (8 * 2)] + str x22, [sp, (8 * 3)] + str x23, [sp, (8 * 4)] + str x24, [sp, (8 * 5)] + str x25, [sp, (8 * 6)] + str x26, [sp, (8 * 7)] + str x27, [sp, (8 * 8)] //vpush {d8-d15} // save NEON regs? //setup emu -> register ldr x10, [x0, (8 * 0)] diff --git a/src/dynarec/dynarec_arm64_00.c b/src/dynarec/dynarec_arm64_00.c index bfc53bfc..a70fba00 100755 --- a/src/dynarec/dynarec_arm64_00.c +++ b/src/dynarec/dynarec_arm64_00.c @@ -109,6 +109,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin emit_or32c(dyn, ninst, rex, xRAX, i32, x3, x4); break; + case 0x0F: + addr = dynarec64_0F(dyn, addr, ip, ninst, rex, ok, need_epilog); + break; + case 0x21: INST_NAME("AND Ed, Gd"); SETFLAGS(X_ALL, SF_SET); @@ -487,7 +491,6 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0xC3: INST_NAME("RET"); // SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...) - // ^^^ that hack break PlantsVsZombies and GOG Setup under wine.... READFLAGS(X_PEND); // so instead, force the defered flags, so it's not too slow, and flags are not lost BARRIER(2); ret_to_epilog(dyn, ninst); @@ -495,6 +498,58 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin *ok = 0; break; + case 0xCC: + SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...) + if(PK(0)=='S' && PK(1)=='C') { + addr+=2; + BARRIER(2); + INST_NAME("Special Box64 instruction"); + if((PK64(0)==0)) + { + addr+=8; + MESSAGE(LOG_DEBUG, "Exit x64 Emu\n"); + //GETIP(ip+1+2); // no use + //STORE_XEMU_REGS(xRIP); // no need, done in epilog + MOV32w(x1, 1); + STRw_U12(x1, xEmu, offsetof(x64emu_t, quit)); + *ok = 0; + *need_epilog = 1; + } else { + MESSAGE(LOG_DUMP, "Native Call to %s\n", GetNativeName(GetNativeFnc(ip))); + x87_forget(dyn, ninst, x3, x4, 0); + sse_purge07cache(dyn, ninst, x3); + GETIP(ip+1); // read the 0xCC + STORE_XEMU_MINIMUM(xRIP); + CALL_S(x64Int3, -1); + LOAD_XEMU_MINIMUM(xRIP); + addr+=8+8; + TABLE64(x3, addr); // expected return address + CMPSx_REG(xRIP, x3); + B_MARK(cNE); + LDRw_U12(x1, xEmu, offsetof(x64emu_t, quit)); + CMPSw_U12(x1, 1); + B_NEXT(cNE); + MARK; + jump_to_epilog(dyn, 0, xRIP, ninst); + } + } else { + #if 0 + INST_NAME("INT 3"); + // check if TRAP signal is handled + LDRx_U12(x1, xEmu, offsetof(x64emu_t, context)); + MOV32w(x2, offsetof(box64context_t, signals[SIGTRAP])); + LDRx_REG_LSL3(x3, x1, x2); + CMPSx_U12(x3, 0); + B_NEXT(cNE); + MOV32w(x1, SIGTRAP); + CALL_(raise, -1, 0); + break; + #else + DEFAULT; + #endif + } + break; + case 0xE8: INST_NAME("CALL Id"); i32 = F32S; diff --git a/src/dynarec/dynarec_arm64_0f.c b/src/dynarec/dynarec_arm64_0f.c new file mode 100755 index 00000000..bc2bdd86 --- /dev/null +++ b/src/dynarec/dynarec_arm64_0f.c @@ -0,0 +1,98 @@ +#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 "my_cpuid.h" +#include "emu/x87emu_private.h" + +#include "dynarec_arm64_functions.h" +#include "dynarec_arm64_helper.h" + +#define GETGX(a) \ + gd = (nextop&0x38)>>3+(rex.r<<3); \ + a = sse_get_reg(dyn, ninst, x1, gd) +#define GETEX(a) \ + if(MODREG) { \ + a = sse_get_reg(dyn, ninst, x1, nextop&7+(rex.b<<3)); \ + } else { \ + addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0); \ + a = fpu_get_scratch_quad(dyn); \ + VLD1Q_64(a, ed); \ + } +#define GETGM(a) \ + gd = (nextop&0x38)>>3; \ + a = mmx_get_reg(dyn, ninst, x1, gd) +#define GETEM(a) \ + if(MODREG) { \ + a = mmx_get_reg(dyn, ninst, x1, nextop&7); \ + } else { \ + addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0); \ + a = fpu_get_scratch_double(dyn); \ + VLD1_64(a, ed); \ + } +#define PUTEM(a) \ + if(!MODREG) { \ + VST1_64(a, ed); \ + } + +uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog) +{ + uint8_t opcode = F8; + uint8_t nextop, u8; + int32_t i32, i32_, j32; + uint8_t gd, ed; + uint8_t wback, wb1, wb2; + uint8_t eb1, eb2; + uint8_t gb1, gb2; + int v0, v1, v2; + int q0, q1; + int d0, d1; + int s0; + int fixedaddress; + int parity; + MAYUSE(s0); + MAYUSE(q1); + MAYUSE(v2); + MAYUSE(gb2); + MAYUSE(gb1); + MAYUSE(eb2); + MAYUSE(eb1); + MAYUSE(wb2); + MAYUSE(j32); + #if STEP == 3 + //static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 }; + #endif + + switch(opcode) { + + + + case 0x1F: + INST_NAME("NOP (multibyte)"); + nextop = F8; + FAKEED; + break; + + + default: + DEFAULT; + } + return addr; +} + diff --git a/src/dynarec/dynarec_arm64_helper.h b/src/dynarec/dynarec_arm64_helper.h index 68042470..28dfc97e 100755 --- a/src/dynarec/dynarec_arm64_helper.h +++ b/src/dynarec/dynarec_arm64_helper.h @@ -93,11 +93,11 @@ } #define WBACKO(O) if(wback) {STR_REG_LSL_IMM5(ed, wback, O, 0);} //FAKEELike GETED, but doesn't get anything -#define FAKEED if((nextop&0xC0)!=0xC0) { \ +#define FAKEED if(!MODREG) { \ addr = fakeed(dyn, addr, ninst, nextop); \ } // GETGW extract x64 register in gd, that is i -#define GETGW(i) gd = xEAX+((nextop&0x38)>>3); UXTH(i, gd, 0); gd = i; +#define GETGW(i) gd = xEAX+((nextop&0x38)>>3)+(rex.r<<3); UXTH(i, gd, 0); gd = i; //GETEWW will use i for ed, and can use w for wback. #define GETEWW(w, i) if((nextop&0xC0)==0xC0) { \ wback = xEAX+(nextop&7);\ @@ -139,7 +139,7 @@ // Write w back to original register / memory #define EWBACKW(w) if(wb1) {STRH_IMM8(w, wback, fixedaddress);} else {BFI(wback, w, 0, 16);} // Write back gd in correct register -#define GWBACK BFI((xEAX+((nextop&0x38)>>3)), gd, 0, 16); +#define GWBACK BFI((xEAX+((nextop&0x38)>>3)+(rex.r<<3)), gd, 0, 16); //GETEB will use i for ed, and can use r3 for wback. #define GETEB(i) if((nextop&0xC0)==0xC0) { \ wback = (nextop&7); \ @@ -190,12 +190,14 @@ gb2 = ((gd&4)>>2); \ gb1 = xEAX+(gd&3); \ gd = i; \ + nopenope! \ UXTB(gd, gb1, gb2); //GETSGB signe extend GB, will use i for gd #define GETSGB(i) gd = (nextop&0x38)>>3; \ gb2 = ((gd&4)>>2); \ gb1 = xEAX+(gd&3); \ gd = i; \ + nopenope! \ SXTB(gd, gb1, gb2); // Write gb (gd) back to original register / memory #define GBBACK BFI(gb1, gd, gb2*8, 8); @@ -373,7 +375,7 @@ LOAD_REG(R8); \ LOAD_REG(R9); \ LDRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags)); \ - if(A) {LDRx_U12(A, xEmu, offsetof(x64emu_t, ip));} + if(A) {LDRx_U12(A, xEmu, offsetof(x64emu_t, ip)); if(A==xRIP) dyn->last_ip = 0;} #define SET_DFNONE(S) if(!dyn->dfnone) {MOVZw(S, d_none); STRw_U12(S, xEmu, offsetof(x64emu_t, df)); dyn->dfnone=1;} #define SET_DF(S, N) if(N) {MOVZw(S, N); STRw_U12(S, xEmu, offsetof(x64emu_t, df)); dyn->dfnone=0;} else SET_DFNONE(S) @@ -443,7 +445,7 @@ #define GETIP_(A) \ if(dyn->last_ip && (A-dyn->last_ip)<0x1000) { \ uint64_t delta = A-dyn->last_ip; \ - ADDx_U12(xRIP, xRIP, delta); \ + if(delta) {ADDx_U12(xRIP, xRIP, delta);} \ } else { \ TABLE64(xRIP, A); \ } @@ -737,7 +739,7 @@ void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1); void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1); uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog); -//uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog); +uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); //uintptr_t dynarec64_FS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog); //uintptr_t dynarec64_GS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog); //uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog); diff --git a/src/emu/x64emu_private.h b/src/emu/x64emu_private.h index 27bb60f1..ed7ae653 100755 --- a/src/emu/x64emu_private.h +++ b/src/emu/x64emu_private.h @@ -63,8 +63,6 @@ typedef struct x64emu_s { // cpu helpers reg64_t zero; reg64_t *sbiidx[16]; - // scratch stack, used for alignement of double and 64bits ints on arm. 200 elements should be enough - uint64_t scratch[200]; // emu control int quit; int error; @@ -73,6 +71,8 @@ typedef struct x64emu_s { int exit; int quitonlongjmp; // quit if longjmp is called int longjmp; // if quit because of longjmp + // scratch stack, used for alignement of double and 64bits ints on arm. 200 elements should be enough + uint64_t scratch[200]; // local stack, do be deleted when emu is freed void* stack2free; // this is the stack to free (can be NULL) void* init_stack; // initial stack (owned or not) diff --git a/src/main.c b/src/main.c index 0811136c..c14591b0 100755 --- a/src/main.c +++ b/src/main.c @@ -933,7 +933,8 @@ int main(int argc, const char **argv, const char **env) { if(ld_preload.size) { for (int i=0; i<ld_preload.size; ++i) { if(AddNeededLib(NULL, NULL, 0, ld_preload.paths[i], my_context, emu)) { - printf_log(LOG_INFO, "Warning, cannot pre-load lib: \"%s\"\n", ld_preload.paths[i]); + if(!strstr(ld_preload.paths[i], "vgpreload_")) + printf_log(LOG_INFO, "Warning, cannot pre-load lib: \"%s\"\n", ld_preload.paths[i]); } } } |