diff options
| author | Yang Liu <numbksco@gmail.com> | 2024-06-18 16:01:12 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-06-18 10:01:12 +0200 |
| commit | 8dfbe80b41794e77bc082aef70135c75393df567 (patch) | |
| tree | 7006cddf0b987b2a379762ffe13ec9014aed90b5 /src/dynarec | |
| parent | 2bcc997e4b2a43a124e03b75f2f65de99f96e982 (diff) | |
| download | box64-8dfbe80b41794e77bc082aef70135c75393df567.tar.gz box64-8dfbe80b41794e77bc082aef70135c75393df567.zip | |
[LA64_DYNAREC] Added more opcodes (#1597)
Diffstat (limited to 'src/dynarec')
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_0f.c | 13 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_64.c | 9 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_66.c | 23 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_660f.c | 10 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_6664.c | 70 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_67.c | 33 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_f0.c | 36 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_f20f.c | 16 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_f30f.c | 24 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_helper.h | 2 | ||||
| -rw-r--r-- | src/dynarec/la64/la64_emitter.h | 9 |
11 files changed, 245 insertions, 0 deletions
diff --git a/src/dynarec/la64/dynarec_la64_0f.c b/src/dynarec/la64/dynarec_la64_0f.c index 8c0e633c..0c40f766 100644 --- a/src/dynarec/la64/dynarec_la64_0f.c +++ b/src/dynarec/la64/dynarec_la64_0f.c @@ -708,6 +708,19 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } else switch ((nextop >> 3) & 7) { + case 0: + INST_NAME("FXSAVE Ed"); + MESSAGE(LOG_DUMP, "Need Optimization\n"); + SKIPTEST(x1); + fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + if (MODREG) { + DEFAULT; + } else { + addr = geted(dyn, addr, ninst, nextop, &ed, x1, x3, &fixedaddress, rex, NULL, 0, 0); + if (ed != x1) { MV(x1, ed); } + CALL(rex.w ? ((void*)fpu_fxsave64) : ((void*)fpu_fxsave32), -1); + } + break; case 2: INST_NAME("LDMXCSR Md"); GETED(0); diff --git a/src/dynarec/la64/dynarec_la64_64.c b/src/dynarec/la64/dynarec_la64_64.c index 152db7b3..0e7b96d6 100644 --- a/src/dynarec/la64/dynarec_la64_64.c +++ b/src/dynarec/la64/dynarec_la64_64.c @@ -79,6 +79,15 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETEDO(x4, 0); emit_xor32(dyn, ninst, rex, gd, ed, x3, x4); break; + case 0x64: + addr = dynarec64_64(dyn, addr, ip, ninst, rex, rep, _FS, ok, need_epilog); + break; + case 0x65: + addr = dynarec64_64(dyn, addr, ip, ninst, rex, rep, _GS, ok, need_epilog); + break; + case 0x66: + addr = dynarec64_6664(dyn, addr, ip, ninst, rex, seg, ok, need_epilog); + break; case 0x81: case 0x83: nextop = F8; diff --git a/src/dynarec/la64/dynarec_la64_66.c b/src/dynarec/la64/dynarec_la64_66.c index 8250d502..5130a3b0 100644 --- a/src/dynarec/la64/dynarec_la64_66.c +++ b/src/dynarec/la64/dynarec_la64_66.c @@ -220,6 +220,15 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_cmp16_0(dyn, ninst, x1, x3, x4); } break; + case 0x64: + addr = dynarec64_6664(dyn, addr, ip, ninst, rex, _FS, ok, need_epilog); + break; + case 0x65: + addr = dynarec64_6664(dyn, addr, ip, ninst, rex, _GS, ok, need_epilog); + break; + case 0x66: + addr = dynarec64_66(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); + break; case 0x69: case 0x6B: if (opcode == 0x69) { @@ -537,6 +546,20 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni UFLAG_RES(ed); UFLAG_DF(x3, d_shr16); break; + case 7: + INST_NAME("SAR Ew, Ib"); + SETFLAGS(X_ALL, SF_PENDING); + UFLAG_IF { MESSAGE(LOG_DUMP, "Need Optimization for flags\n"); } + GETSEW(x1, 1); + u8 = F8; + UFLAG_IF { MOV32w(x2, (u8 & 15)); } + UFLAG_OP12(ed, x2) + SRAI_D(ed, ed, u8 & 15); + if (MODREG) BSTRPICK_D(ed, ed, 15, 0); + EWBACK; + UFLAG_RES(ed); + UFLAG_DF(x3, d_sar16); + break; default: DEFAULT; } diff --git a/src/dynarec/la64/dynarec_la64_660f.c b/src/dynarec/la64/dynarec_la64_660f.c index 08fbde4e..70e1ae41 100644 --- a/src/dynarec/la64/dynarec_la64_660f.c +++ b/src/dynarec/la64/dynarec_la64_660f.c @@ -868,6 +868,16 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int SMWRITE2(); } break; + case 0xD7: + INST_NAME("PMOVMSKB Gd, Ex"); + nextop = F8; + GETEX(q0, 0, 0); + GETGD; + v0 = fpu_get_scratch(dyn); + VMSKLTZ_B(v0, q0); + MOVFR2GR_D(x1, v0); + BSTRINS_D(gd, x1, 15, 0); + break; case 0xDB: INST_NAME("PAND Gx,Ex"); nextop = F8; diff --git a/src/dynarec/la64/dynarec_la64_6664.c b/src/dynarec/la64/dynarec_la64_6664.c new file mode 100644 index 00000000..01db8021 --- /dev/null +++ b/src/dynarec/la64/dynarec_la64_6664.c @@ -0,0 +1,70 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <errno.h> + +#include "debug.h" +#include "box64context.h" +#include "dynarec.h" +#include "emu/x64emu_private.h" +#include "emu/x64run_private.h" +#include "la64_emitter.h" +#include "x64run.h" +#include "x64emu.h" +#include "box64stack.h" +#include "callback.h" +#include "emu/x64run_private.h" +#include "x64trace.h" +#include "dynarec_native.h" + +#include "la64_printer.h" +#include "dynarec_la64_private.h" +#include "dynarec_la64_helper.h" +#include "dynarec_la64_functions.h" + +uintptr_t dynarec64_6664(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int seg, int* ok, int* need_epilog) +{ + (void)ip; + (void)need_epilog; + + uint8_t opcode = F8; + uint8_t nextop; + uint8_t gd, ed; + int64_t j64; + int v0, v1; + int64_t fixedaddress; + int unscaled; + MAYUSE(j64); + + GETREX(); + + switch (opcode) { + case 0x8B: + INST_NAME("MOV Gd, FS:Ed"); + nextop = F8; + GETGD; + if (MODREG) { // reg <= reg + ed = TO_LA64((nextop & 7) + (rex.b << 3)); + if (rex.w) { + MV(gd, ed); + } else { + if (ed != gd) BSTRINS_D(gd, ed, 15, 0); + } + } else { // mem <= reg + grab_segdata(dyn, addr, ninst, x4, seg); + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); + if (rex.w) { + LDX_D(gd, ed, x4); + } else { + LDX_HU(x1, ed, x4); + BSTRINS_D(gd, x1, 15, 0); + } + } + break; + + default: + DEFAULT; + } + return addr; +} diff --git a/src/dynarec/la64/dynarec_la64_67.c b/src/dynarec/la64/dynarec_la64_67.c index 5b81eb9d..242d315e 100644 --- a/src/dynarec/la64/dynarec_la64_67.c +++ b/src/dynarec/la64/dynarec_la64_67.c @@ -62,6 +62,39 @@ uintptr_t dynarec64_67(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } switch(opcode) { + case 0x88: + INST_NAME("MOV Eb, Gb"); + nextop = F8; + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); + if (rex.rex) { + gb2 = 0; + gb1 = TO_LA64(gd); + } else { + gb2 = ((gd & 4) << 1); + gb1 = TO_LA64(gd & 3); + } + if (gb2) { + gd = x4; + BSTRPICK_D(gd, gb1, gb2 + 7, gb2); + } else { + gd = gb1; // no need to extract + } + if (MODREG) { + ed = (nextop & 7) + (rex.b << 3); + if (rex.rex) { + eb1 = TO_LA64(ed); + eb2 = 0; + } else { + eb1 = TO_LA64(ed & 3); // Ax, Cx, Dx or Bx + eb2 = ((ed & 4) >> 2); // L or H + } + BSTRINS_D(eb1, gd, eb2 * 8 + 7, eb2 * 8); + } else { + addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0); + ST_B(gb1, ed, fixedaddress); + SMWRITELOCK(lock); + } + break; case 0x89: INST_NAME("MOV Ed, Gd"); nextop = F8; diff --git a/src/dynarec/la64/dynarec_la64_f0.c b/src/dynarec/la64/dynarec_la64_f0.c index b6183de6..26610d2c 100644 --- a/src/dynarec/la64/dynarec_la64_f0.c +++ b/src/dynarec/la64/dynarec_la64_f0.c @@ -337,6 +337,42 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SMDMB(); } break; + case 1: // OR + if (opcode == 0x81) { + INST_NAME("LOCK OR Ed, Id"); + } else { + INST_NAME("LOCK OR Ed, Ib"); + } + SETFLAGS(X_ALL, SF_SET_PENDING); + if (MODREG) { + if (opcode == 0x81) + i64 = F32S; + else + i64 = F8S; + ed = TO_LA64((nextop & 7) + (rex.b << 3)); + emit_or32c(dyn, ninst, rex, ed, i64, x3, x4); + } else { + addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, (opcode == 0x81) ? 4 : 1); + if (opcode == 0x81) + i64 = F32S; + else + i64 = F8S; + if (i64 <= -2048 || i64 > 2048) + MOV64xw(x3, i64); + MARKLOCK; + LLxw(x1, wback, 0); + if (i64 >= -2048 && i64 < 2048) { + ORI(x4, x1, i64); + } else { + OR(x4, x1, x3); + } + if (!rex.w) ZEROUP(x4); + SCxw(x4, wback, 0); + BEQZ_MARKLOCK(x4); + IFX (X_ALL | X_PEND) + emit_or32c(dyn, ninst, rex, x1, i64, x3, x4); + } + break; case 5: // SUB if (opcode == 0x81) { INST_NAME("LOCK SUB Ed, Id"); diff --git a/src/dynarec/la64/dynarec_la64_f20f.c b/src/dynarec/la64/dynarec_la64_f20f.c index 7c14361d..133b8a2b 100644 --- a/src/dynarec/la64/dynarec_la64_f20f.c +++ b/src/dynarec/la64/dynarec_la64_f20f.c @@ -154,6 +154,22 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int } } break; + case 0x51: + INST_NAME("SQRTSD Gx, Ex"); + nextop = F8; + GETGX_empty(v0); + d1 = fpu_get_scratch(dyn); + GETEXSD(d0, 0, 0); + FSQRT_D(d1, d0); + if (!box64_dynarec_fastnan) { + v1 = fpu_get_scratch(dyn); + MOVGR2FR_D(v1, xZR); + FCMP_D(fcc0, d0, v1, cLT); + BCEQZ(fcc0, 4 + 4); + FNEG_D(d1, d1); + } + VEXTRINS_D(v0, d1, 0); + break; case 0x58: INST_NAME("ADDSD Gx, Ex"); nextop = F8; diff --git a/src/dynarec/la64/dynarec_la64_f30f.c b/src/dynarec/la64/dynarec_la64_f30f.c index 1d147a0a..196e386f 100644 --- a/src/dynarec/la64/dynarec_la64_f30f.c +++ b/src/dynarec/la64/dynarec_la64_f30f.c @@ -284,6 +284,30 @@ uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int SMWRITE2(); } break; + case 0xBC: + INST_NAME("TZCNT Gd, Ed"); + SETFLAGS(X_ZF, SF_SUBSET); + SET_DFNONE(); + nextop = F8; + GETED(0); + GETGD; + if (!rex.w && MODREG) { + AND(x4, ed, xMASK); + ed = x4; + } + RESTORE_EFLAGS(x1); + ANDI(xFlags, xFlags, ~((1 << F_ZF) | (1 << F_CF))); + BNE_MARK(ed, xZR); + ORI(xFlags, xFlags, 1 << F_CF); + MOV32w(gd, rex.w ? 64 : 32); + SPILL_EFLAGS(); + B_NEXT_nocond; + MARK; + CTZxw(gd, ed); + BNE(gd, xZR, 4 + 4); + ORI(xFlags, xFlags, 1 << F_ZF); + SPILL_EFLAGS(); + break; case 0xC2: INST_NAME("CMPSS Gx, Ex, Ib"); nextop = F8; diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h index 060917ce..1c921498 100644 --- a/src/dynarec/la64/dynarec_la64_helper.h +++ b/src/dynarec/la64/dynarec_la64_helper.h @@ -745,6 +745,7 @@ void* la64_next(x64emu_t* emu, uintptr_t addr); #define dynarec64_0F STEPNAME(dynarec64_0F) #define dynarec64_64 STEPNAME(dynarec64_64) #define dynarec64_66 STEPNAME(dynarec64_66) +#define dynarec64_6664 STEPNAME(dynarec64_6664) #define dynarec64_67 STEPNAME(dynarec64_67) #define dynarec64_F30F STEPNAME(dynarec64_F30F) #define dynarec64_660F STEPNAME(dynarec64_660F) @@ -973,6 +974,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog); uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); +uintptr_t dynarec64_6664(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int seg, int* ok, int* need_epilog); uintptr_t dynarec64_67(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); diff --git a/src/dynarec/la64/la64_emitter.h b/src/dynarec/la64/la64_emitter.h index c912f666..5d872d9c 100644 --- a/src/dynarec/la64/la64_emitter.h +++ b/src/dynarec/la64/la64_emitter.h @@ -528,6 +528,15 @@ f24-f31 fs0-fs7 Static registers Callee } \ } while (0) +#define CTZxw(rd, rj) \ + do { \ + if (rex.w) { \ + CTZ_D(rd, rj); \ + } else { \ + CTZ_W(rd, rj); \ + } \ + } while (0) + // GR[rd] = SignExtend(GR[rj][7:0], GRLEN) #define EXT_W_B(rd, rj) EMIT(type_2R(0b0000000000000000010111, rj, rd)) |