mirror of
https://github.com/ptitSeb/box64.git
synced 2024-11-24 06:59:53 +00:00
Added some x87 opcodes (D9 and DB prefixes)
This commit is contained in:
parent
4a418d72b6
commit
5119464274
@ -111,6 +111,8 @@ set(ELFLOADER_SRC
|
||||
"${BOX64_ROOT}/src/emu/x64run.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run0f.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run66.c"
|
||||
"${BOX64_ROOT}/src/emu/x64rund9.c"
|
||||
"${BOX64_ROOT}/src/emu/x64rundb.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run_private.c"
|
||||
"${BOX64_ROOT}/src/emu/x64syscall.c"
|
||||
"${BOX64_ROOT}/src/emu/x64tls.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);
|
||||
|
@ -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);
|
||||
|
289
src/emu/x64rund9.c
Normal file
289
src/emu/x64rund9.c
Normal file
@ -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;
|
||||
}
|
186
src/emu/x64rundb.c
Normal file
186
src/emu/x64rundb.c
Normal file
@ -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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user