diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2024-05-24 15:01:35 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2024-05-24 15:01:46 +0200 |
| commit | fcf0cf00d0a82649ba0cf9f6a8c0450bb6ed5f47 (patch) | |
| tree | 7c3ba3519cf1a9ebdbca47fe3310dbc531212707 /src/emu | |
| parent | 2ee846f48e7fa9b103f0949f63f91712ca7b03ca (diff) | |
| download | box64-fcf0cf00d0a82649ba0cf9f6a8c0450bb6ed5f47.tar.gz box64-fcf0cf00d0a82649ba0cf9f6a8c0450bb6ed5f47.zip | |
Added support for XSAVE/XRSTOR ([ARM64_DYNAREC] too)
Diffstat (limited to 'src/emu')
| -rw-r--r-- | src/emu/x64run0f.c | 27 | ||||
| -rw-r--r-- | src/emu/x87emu_private.c | 83 | ||||
| -rw-r--r-- | src/emu/x87emu_private.h | 2 |
3 files changed, 107 insertions, 5 deletions
diff --git a/src/emu/x64run0f.c b/src/emu/x64run0f.c index f2666e5e..95b8cc12 100644 --- a/src/emu/x64run0f.c +++ b/src/emu/x64run0f.c @@ -91,11 +91,16 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) if(MODREG) switch(nextop) { case 0xD0: - #ifndef TEST_INTERPRETER - emit_signal(emu, SIGILL, (void*)R_RIP, 0); - #else - test->notest = 1; - #endif + if(R_RCX) { + #ifndef TEST_INTERPRETER + emit_signal(emu, SIGILL, (void*)R_RIP, 0); + #else + test->notest = 1; + #endif + } else { + R_RAX = 0b11; // x87 & SSE for now + R_RDX = 0; + } break; case 0xE0: case 0xE1: @@ -1286,6 +1291,18 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GETED(0); ED->dword[0] = emu->mxcsr.x32; break; + case 4: /* XSAVE Ed */ + _GETED(0); + #ifdef TEST_INTERPRETER + emu->sw.f.F87_TOP = emu->top&7; + #else + fpu_xsave(emu, ED, rex.is32bits); + #endif + break; + case 5: /* XRSTOR Ed */ + _GETED(0); + fpu_xrstor(emu, ED, rex.is32bits); + break; case 7: /* CLFLUSH Ed */ _GETED(0); #if defined(DYNAREC) && !defined(TEST_INTERPRETER) diff --git a/src/emu/x87emu_private.c b/src/emu/x87emu_private.c index f6fda3b6..79306a76 100644 --- a/src/emu/x87emu_private.c +++ b/src/emu/x87emu_private.c @@ -430,3 +430,86 @@ void fpu_fxrstor64(x64emu_t* emu, void* ed) // copy SSE regs memcpy(&emu->xmm[0], &p->XmmRegisters[0], sizeof(emu->xmm)); } + +typedef struct xsaveheader_s { + uint64_t xstate_bv; + uint64_t xcomp_bv; + uint8_t reserved[64-16]; +} xsaveheader_t; + +void fpu_xsave(x64emu_t* emu, void* ed, int is32bits) +{ + xsave64_t *p = (xsave64_t*)ed; + xsaveheader_t *h = (xsaveheader_t*)(p+1); + uint32_t rfbm = (0b11&R_EAX); + h->xstate_bv =(h->xstate_bv&~0b11)|rfbm; + h->xcomp_bv = 0; + if(h->xstate_bv&0b01) { + int top = emu->top&7; + int stack = 8-top; + if(emu->fpu_tags == TAGS_EMPTY) + stack = 0; + emu->sw.f.F87_TOP = top; + p->ControlWord = emu->cw.x16; + p->StatusWord = emu->sw.x16; + p->MxCsr = emu->mxcsr.x32; + uint8_t tags = 0; + for (int i=0; i<8; ++i) + tags |= (((emu->fpu_tags>>(i*2))&0b11)?0:1)<<i; + p->TagWord = emu->fpu_tags; + p->ErrorOpcode = 0; + p->ErrorOffset = 0; + p->DataOffset = 0; + // copy FPU/MMX regs... + for(int i=0; i<8; ++i) + memcpy(&p->FloatRegisters[i].q[0], (i<stack)?&ST(i):&emu->mmx[i], sizeof(mmx87_regs_t)); + } + if(((h->xstate_bv&0b10)||(h->xstate_bv&0b100))&&!(h->xstate_bv&0b01)) { + p->MxCsr = emu->mxcsr.x32; + } + // copy SSE regs + if(h->xstate_bv&0b10) { + for(int i=0; i<is32bits?8:16; ++i) + memcpy(&p->XmmRegisters[i], &emu->xmm[i], 16); + } +} + +void fpu_xrstor(x64emu_t* emu, void* ed, int is32bits) +{ + xsave64_t *p = (xsave64_t*)ed; + xsaveheader_t *h = (xsaveheader_t*)(p+1); + int compressed = (h->xcomp_bv>>63); + uint32_t rfbm = (0b11&R_EAX); + uint32_t to_restore = rfbm & h->xstate_bv; + uint32_t to_init = rfbm & ~h->xstate_bv; + // check componant to restore + if(to_restore&0b01) { + emu->cw.x16 = p->ControlWord; + emu->sw.x16 = p->StatusWord; + emu->mxcsr.x32 = p->MxCsr; + if(box64_sse_flushto0) + applyFlushTo0(emu); + emu->top = emu->sw.f.F87_TOP; + uint8_t tags = p->TagWord; + emu->fpu_tags = 0; + for(int i=0; i<8; ++i) + emu->fpu_tags |= (((tags>>i)&1)?0:0b11)<<(i*2); + int top = emu->top&7; + int stack = 8-top; + if(emu->fpu_tags == TAGS_EMPTY) + stack = 0; + // copy back MMX regs... + for(int i=0; i<8; ++i) + memcpy((i<stack)?&ST(i):&emu->mmx[i], &p->FloatRegisters[i].q[0], sizeof(mmx87_regs_t)); + } else if(to_init&0b01) { + reset_fpu(emu); + } + if(((to_restore&0b10)||(to_restore&0b100))&&!(to_restore&0b01)) { + emu->mxcsr.x32 = p->MxCsr; + } + if(to_restore&0b10) { + // copy SSE regs + for(int i=0; i<is32bits?8:16; ++i) + memcpy(&emu->xmm[i], &p->XmmRegisters[i], 16); + } +} \ No newline at end of file diff --git a/src/emu/x87emu_private.h b/src/emu/x87emu_private.h index a3c589df..db5553a2 100644 --- a/src/emu/x87emu_private.h +++ b/src/emu/x87emu_private.h @@ -216,5 +216,7 @@ void fpu_fxsave32(x64emu_t* emu, void* ed); void fpu_fxrstor32(x64emu_t* emu, void* ed); void fpu_fxsave64(x64emu_t* emu, void* ed); void fpu_fxrstor64(x64emu_t* emu, void* ed); +void fpu_xsave(x64emu_t* emu, void* ed, int is32bits); +void fpu_xrstor(x64emu_t* emu, void* ed, int is32bits); #endif //__X87RUN_PRIVATE_H_ |