diff options
| author | Yang Liu <numbksco@gmail.com> | 2024-05-03 15:42:25 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-03 09:42:25 +0200 |
| commit | aad6a1698459ac44403e71bacce276cd76bac5db (patch) | |
| tree | a976f6f84f9000003bb80ef814b1dc9b9099576b /src | |
| parent | 9b00df93c2f68ea8737aea88800ede3f92327f4b (diff) | |
| download | box64-aad6a1698459ac44403e71bacce276cd76bac5db.tar.gz box64-aad6a1698459ac44403e71bacce276cd76bac5db.zip | |
[LA64_DYNAREC] Added more opcodes (#1488)
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_00.c | 50 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_0f.c | 21 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_66.c | 68 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_emit_logic.c | 35 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_f0.c | 22 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_f20f.c | 16 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_helper.h | 5 |
7 files changed, 216 insertions, 1 deletions
diff --git a/src/dynarec/la64/dynarec_la64_00.c b/src/dynarec/la64/dynarec_la64_00.c index f934c5f3..02bbbee2 100644 --- a/src/dynarec/la64/dynarec_la64_00.c +++ b/src/dynarec/la64/dynarec_la64_00.c @@ -1073,6 +1073,56 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni ADD_D(xRDI, xRDI, x3); } break; + case 0xAE: + switch (rep) { + case 1: + case 2: + if (rep == 1) { + INST_NAME("REPNZ SCASB"); + } else { + INST_NAME("REPZ SCASB"); + } + MAYSETFLAGS(); + SETFLAGS(X_ALL, SF_SET_PENDING); + CBZ_NEXT(xRCX); + ANDI(x1, xRAX, 0xff); + ANDI(x2, xFlags, 1 << F_DF); + BNEZ_MARK2(x2); + MARK; // Part with DF==0 + LD_BU(x2, xRDI, 0); + ADDI_D(xRDI, xRDI, 1); + ADDI_D(xRCX, xRCX, -1); + if (rep == 1) { + BEQ_MARK3(x1, x2); + } else { + BNE_MARK3(x1, x2); + } + BNE_MARK(xRCX, xZR); + B_MARK3_nocond; + MARK2; // Part with DF==1 + LD_BU(x2, xRDI, 0); + ADDI_D(xRDI, xRDI, -1); + ADDI_D(xRCX, xRCX, -1); + if (rep == 1) { + BEQ_MARK3(x1, x2); + } else { + BNE_MARK3(x1, x2); + } + BNE_MARK2(xRCX, xZR); + MARK3; // end + emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6); + break; + default: + INST_NAME("SCASB"); + SETFLAGS(X_ALL, SF_SET_PENDING); + GETDIR(x3, x1, 1); + ANDI(x1, xRAX, 0xff); + LD_BU(x2, xRDI, 0); + ADD_D(xRDI, xRDI, x3); + emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6); + break; + } + break; case 0xB0: case 0xB1: case 0xB2: diff --git a/src/dynarec/la64/dynarec_la64_0f.c b/src/dynarec/la64/dynarec_la64_0f.c index fb8cf96d..5cc8ee71 100644 --- a/src/dynarec/la64/dynarec_la64_0f.c +++ b/src/dynarec/la64/dynarec_la64_0f.c @@ -265,6 +265,27 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni #undef GO + case 0x54: + INST_NAME("ANDPS Gx, Ex"); + nextop = F8; + GETEX(q0, 0, 0); + GETGX(v0, 1); + VAND_V(v0, v0, q0); + break; + case 0x55: + INST_NAME("ANDNPS Gx, Ex"); + nextop = F8; + GETEX(q0, 0, 0); + GETGX(v0, 1); + VANDN_V(v0, v0, q0); + break; + case 0x56: + INST_NAME("ORPS Gx, Ex"); + nextop = F8; + GETEX(q0, 0, 0); + GETGX(v0, 1); + VOR_V(v0, v0, q0); + break; case 0x57: INST_NAME("XORPS Gx, Ex"); nextop = F8; diff --git a/src/dynarec/la64/dynarec_la64_66.c b/src/dynarec/la64/dynarec_la64_66.c index 2d6d0f81..f4469e73 100644 --- a/src/dynarec/la64/dynarec_la64_66.c +++ b/src/dynarec/la64/dynarec_la64_66.c @@ -58,7 +58,15 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni return dynarec64_00(dyn, addr - 1, ip, ninst, rex, rep, ok, need_epilog); // addr-1, to "put back" opcode switch (opcode) { - + case 0x03: + INST_NAME("ADD Gw, Ew"); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETGW(x1); + GETEW(x2, 0); + emit_add16(dyn, ninst, x1, x2, x3, x4, x6); + GWBACK; + break; case 0x0F: switch (rep) { case 0: addr = dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog); break; @@ -76,6 +84,42 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_sbb16(dyn, ninst, x1, x2, x4, x5, x6); EWBACK; break; + case 0x25: + INST_NAME("AND AX, Iw"); + SETFLAGS(X_ALL, SF_SET_PENDING); + i32 = F16; + BSTRPICK_D(x1, xRAX, 15, 0); + MOV32w(x2, i32); + emit_and16(dyn, ninst, x1, x2, x3, x4); + BSTRINS_D(xRAX, x1, 0, 15); + break; + case 0x29: + INST_NAME("SUB Ew, Gw"); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETGW(x1); + GETEW(x2, 0); + emit_sub16(dyn, ninst, x2, x1, x4, x5, x6); + EWBACK; + break; + case 0x2B: + INST_NAME("SUB Gw, Ew"); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETGW(x1); + GETEW(x2, 0); + emit_sub16(dyn, ninst, x1, x2, x3, x4, x5); + GWBACK; + break; + case 0x2D: + INST_NAME("SUB AX, Iw"); + SETFLAGS(X_ALL, SF_SET_PENDING); + i32 = F16; + BSTRPICK_D(x1, xRAX, 15, 0); + MOV32w(x2, i32); + emit_sub16(dyn, ninst, x1, x2, x3, x4, x5); + BSTRINS_D(xRAX, x1, 0, 15); + break; case 0x31: INST_NAME("XOR Ew, Gw"); SETFLAGS(X_ALL, SF_SET_PENDING); @@ -93,6 +137,14 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETEW(x1, 0); emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6); break; + case 0x3B: + INST_NAME("CMP Gw, Ew"); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETGW(x1); + GETEW(x2, 0); + emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6); + break; case 0x81: case 0x83: nextop = F8; @@ -208,6 +260,20 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni BSTRINS_D(gd, x2, 15, 0); } break; + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + INST_NAME("MOV Reg16, Iw"); + u16 = F16; + MOV32w(x1, u16); + gd = xRAX + (opcode & 7) + (rex.b << 3); + BSTRINS_D(gd, x1, 15, 0); + break; case 0xC1: nextop = F8; switch ((nextop >> 3) & 7) { diff --git a/src/dynarec/la64/dynarec_la64_emit_logic.c b/src/dynarec/la64/dynarec_la64_emit_logic.c index 0b3e6904..345dab9f 100644 --- a/src/dynarec/la64/dynarec_la64_emit_logic.c +++ b/src/dynarec/la64/dynarec_la64_emit_logic.c @@ -331,6 +331,41 @@ void emit_and8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s3, int s } } +void emit_and16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4) +{ + IFX (X_PEND) { + SET_DF(s3, d_tst16); + } else IFX (X_ALL) { + SET_DFNONE(); + } + + IFXA (X_ALL, la64_lbt) { + X64_AND_W(s1, s2); + } + + AND(s1, s1, s2); // res = s1 & s2 + + + IFX (X_PEND) { + ST_H(s1, xEmu, offsetof(x64emu_t, res)); + } + + if (la64_lbt) return; + + CLEAR_FLAGS(s3); + IFX (X_SF) { + SRLI_D(s3, s1, 15); + BEQZ(s3, 8); + ORI(xFlags, xFlags, 1 << F_SF); + } + IFX (X_ZF) { + BNEZ(s1, 8); + ORI(xFlags, xFlags, 1 << F_ZF); + } + IFX (X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} // emit AND32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch void emit_and32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4) diff --git a/src/dynarec/la64/dynarec_la64_f0.c b/src/dynarec/la64/dynarec_la64_f0.c index 12616391..03e16a8b 100644 --- a/src/dynarec/la64/dynarec_la64_f0.c +++ b/src/dynarec/la64/dynarec_la64_f0.c @@ -8,6 +8,7 @@ #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" @@ -152,6 +153,27 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni DEFAULT; } break; + case 0x29: + INST_NAME("LOCK SUB Ed, Gd"); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETGD; + SMDMB(); + if (MODREG) { + ed = TO_LA64((nextop & 7) + (rex.b << 3)); + emit_sub32(dyn, ninst, rex, ed, gd, x3, x4, x5); + } else { + addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0); + MARKLOCK; + LLxw(x1, wback, 0); + SUB_D(x4, x1, gd); + SCxw(x4, wback, 0); + BEQZ_MARKLOCK(x4); + IFX (X_ALL | X_PEND) + emit_sub32(dyn, ninst, rex, x1, gd, x3, x4, x5); + } + SMDMB(); + break; case 0x81: case 0x83: nextop = F8; diff --git a/src/dynarec/la64/dynarec_la64_f20f.c b/src/dynarec/la64/dynarec_la64_f20f.c index 74f76744..6167883d 100644 --- a/src/dynarec/la64/dynarec_la64_f20f.c +++ b/src/dynarec/la64/dynarec_la64_f20f.c @@ -8,6 +8,7 @@ #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" @@ -77,6 +78,21 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int SMWRITE2(); } break; + case 0x2A: + INST_NAME("CVTSI2SD Gx, Ed"); + nextop = F8; + GETGX(v0, 1); + GETED(0); + d1 = fpu_get_scratch(dyn); + if (rex.w) { + MOVGR2FR_D(d1, ed); + FFINT_D_L(d1, d1); + } else { + MOVGR2FR_W(d1, ed); + FFINT_D_W(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_helper.h b/src/dynarec/la64/dynarec_la64_helper.h index 8828f8b8..5fa9d127 100644 --- a/src/dynarec/la64/dynarec_la64_helper.h +++ b/src/dynarec/la64/dynarec_la64_helper.h @@ -198,6 +198,9 @@ // Write ed back to original register / memory #define EWBACK EWBACKW(ed) +// Write back gd in correct register +#define GWBACK BSTRINS_D((TO_LA64(((nextop & 0x38) >> 3) + (rex.r << 3))), gd, 15, 0); + // GETEB will use i for ed, and can use r3 for wback. #define GETEB(i, D) \ if (MODREG) { \ @@ -754,6 +757,7 @@ void* la64_next(x64emu_t* emu, uintptr_t addr); #define emit_xor32c STEPNAME(emit_xor32c) #define emit_and8 STEPNAME(emit_and8) #define emit_and8c STEPNAME(emit_and8c) +#define emit_and16 STEPNAME(emit_and16) #define emit_and32 STEPNAME(emit_and32) #define emit_and32c STEPNAME(emit_and32c) #define emit_shl32 STEPNAME(emit_shl32) @@ -836,6 +840,7 @@ void emit_xor32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i void emit_xor32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); void emit_and8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4); void emit_and8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); +void emit_and16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4); void emit_and32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); void emit_and32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4); void emit_shl32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); |