diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-03-05 18:05:42 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-03-05 18:05:42 +0100 |
| commit | 51194642742de3f182328815c8aabdd6256a562e (patch) | |
| tree | 9812df672edea0ab3b7eb114adfaaffb9764a2cb /src | |
| parent | 4a418d72b6edb759cf1b2885493ab0116855d1b4 (diff) | |
| download | box64-51194642742de3f182328815c8aabdd6256a562e.tar.gz box64-51194642742de3f182328815c8aabdd6256a562e.zip | |
Added some x87 opcodes (D9 and DB prefixes)
Diffstat (limited to 'src')
| -rwxr-xr-x | src/emu/x64run.c | 18 | ||||
| -rwxr-xr-x | src/emu/x64run_private.h | 4 | ||||
| -rw-r--r-- | src/emu/x64rund9.c | 289 | ||||
| -rw-r--r-- | src/emu/x64rundb.c | 186 |
4 files changed, 496 insertions, 1 deletions
diff --git a/src/emu/x64run.c b/src/emu/x64run.c index a2a2113f..35dc865a 100755 --- a/src/emu/x64run.c +++ b/src/emu/x64run.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); diff --git a/src/emu/x64run_private.h b/src/emu/x64run_private.h index 2ba10b47..6dda57ec 100755 --- a/src/emu/x64run_private.h +++ b/src/emu/x64run_private.h @@ -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); diff --git a/src/emu/x64rund9.c b/src/emu/x64rund9.c new file mode 100644 index 00000000..52c4c46f --- /dev/null +++ b/src/emu/x64rund9.c @@ -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; +} \ No newline at end of file diff --git a/src/emu/x64rundb.c b/src/emu/x64rundb.c new file mode 100644 index 00000000..30a16d44 --- /dev/null +++ b/src/emu/x64rundb.c @@ -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; +} \ No newline at end of file |