diff options
| author | Yang Liu <numbksco@gmail.com> | 2024-07-20 16:04:07 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-20 10:04:07 +0200 |
| commit | 052bba4578730f82bbf26486dcacd276f135c44d (patch) | |
| tree | 0ecc0b4a0cab8752966d9d72634a1d71bc21eb1b | |
| parent | d1eb01e535b324e23e85535fce5ee4516161c47e (diff) | |
| download | box64-052bba4578730f82bbf26486dcacd276f135c44d.tar.gz box64-052bba4578730f82bbf26486dcacd276f135c44d.zip | |
[LA64_DYNAREC] Added more opcodes (#1700)
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_0f.c | 37 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_64.c | 9 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_660f.c | 54 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_f0.c | 21 | ||||
| -rw-r--r-- | src/dynarec/la64/la64_emitter.h | 10 |
5 files changed, 131 insertions, 0 deletions
diff --git a/src/dynarec/la64/dynarec_la64_0f.c b/src/dynarec/la64/dynarec_la64_0f.c index 3124e7ae..0f795e61 100644 --- a/src/dynarec/la64/dynarec_la64_0f.c +++ b/src/dynarec/la64/dynarec_la64_0f.c @@ -676,6 +676,43 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_shld32c(dyn, ninst, rex, ed, gd, u8, x3, x4); WBACK; break; + case 0xAB: + INST_NAME("BTS Ed, Gd"); + SETFLAGS(X_CF, SF_SUBSET); + SET_DFNONE(); + nextop = F8; + GETGD; + if (MODREG) { + ed = TO_LA64((nextop & 7) + (rex.b << 3)); + wback = 0; + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0); + SRAI_D(x1, gd, 5 + rex.w); + ALSL_D(x3, x1, wback, 2 + rex.w); + LDxw(x1, x3, fixedaddress); + ed = x1; + wback = x3; + } + ANDI(x2, gd, rex.w ? 0x3f : 0x1f); + IFX (X_CF) { + SRL_D(x4, ed, x2); + if (la64_lbt) { + X64_SET_EFLAGS(x4, X_CF); + } else { + BSTRINS_D(xFlags, x4, F_CF, F_CF); + } + } + ADDI_D(x4, xZR, 1); + SLL_D(x4, x4, x2); + OR(ed, ed, x4); + if (wback) { + SDxw(ed, wback, fixedaddress); + SMWRITE(); + } else if (!rex.w) { + ZEROUP(ed); + } + break; case 0xAC: nextop = F8; INST_NAME("SHRD Ed, Gd, Ib"); diff --git a/src/dynarec/la64/dynarec_la64_64.c b/src/dynarec/la64/dynarec_la64_64.c index 95d6566e..ae23ab2e 100644 --- a/src/dynarec/la64/dynarec_la64_64.c +++ b/src/dynarec/la64/dynarec_la64_64.c @@ -70,6 +70,15 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETEDO(x4, 0); emit_add32(dyn, ninst, rex, gd, ed, x3, x4, x5); break; + case 0x2B: + INST_NAME("SUB Gd, Seg:Ed"); + SETFLAGS(X_ALL, SF_SET_PENDING); + grab_segdata(dyn, addr, ninst, x4, seg); + nextop = F8; + GETGD; + GETEDO(x4, 0); + emit_sub32(dyn, ninst, rex, gd, ed, x3, x4, x5); + break; case 0x33: INST_NAME("XOR Gd, Seg:Ed"); SETFLAGS(X_ALL, SF_SET_PENDING); diff --git a/src/dynarec/la64/dynarec_la64_660f.c b/src/dynarec/la64/dynarec_la64_660f.c index 9404ae20..095512d5 100644 --- a/src/dynarec/la64/dynarec_la64_660f.c +++ b/src/dynarec/la64/dynarec_la64_660f.c @@ -1075,6 +1075,36 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int u8 = F8; VSHUF4I_D(v0, v1, 0x8 | (u8 & 1) | ((u8 & 2) << 1)); break; + case 0xD2: + INST_NAME("PSRLD Gx, Ex"); + nextop = F8; + GETGX(q0, 1); + GETEX(q1, 0, 0); + v0 = fpu_get_scratch(dyn); + v1 = fpu_get_scratch(dyn); + VSAT_DU(v0, q1, 31); + VREPLVEI_W(v0, v0, 0); + VLDI(v1, 0b1000000011111); // broadcast 31 as uint32 + VSLT_WU(v1, v1, v0); + VMINI_WU(v0, v0, 31); + VSRL_W(q0, q0, v0); + VSRL_W(q0, q0, v1); + break; + case 0xD3: + INST_NAME("PSRLQ Gx,Ex"); + nextop = F8; + GETGX(q0, 1); + GETEX(q1, 0, 0); + v0 = fpu_get_scratch(dyn); + v1 = fpu_get_scratch(dyn); + d0 = fpu_get_scratch(dyn); + VREPLVEI_D(v0, q1, 0); + VLDI(v1, 0b0110000111111); // broadcast 63 as uint64 + VMIN_DU(d0, v0, v1); + VSLT_DU(v1, v1, v0); + VSRL_D(q0, q0, d0); + VSRL_D(q0, q0, v1); + break; case 0xD4: INST_NAME("PADDQ Gx, Ex"); nextop = F8; @@ -1121,6 +1151,13 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int MOVFR2GR_D(x1, v0); BSTRPICK_D(gd, x1, 15, 0); break; + case 0xD9: + INST_NAME("PSUBUSW Gx, Ex"); + nextop = F8; + GETGX(q0, 1); + GETEX(q1, 0, 0); + VSSUB_HU(q0, q0, q1); + break; case 0xDB: INST_NAME("PAND Gx,Ex"); nextop = F8; @@ -1149,6 +1186,23 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int GETEX(v1, 0, 0); VAVGR_BU(v0, v0, v1); break; + case 0xE1: + INST_NAME("PSRAW Gx, Ex"); + nextop = F8; + GETGX(q0, 1); + GETEX(q1, 0, 0); + v0 = fpu_get_scratch(dyn); + VMINI_HU(v0, q1, 15); + VREPLVEI_H(v0, v0, 0); + VSRA_H(q0, q0, v0); + break; + case 0xE3: + INST_NAME("PAVGW Gx,Ex"); + nextop = F8; + GETGX(v0, 1); + GETEX(v1, 0, 0); + VAVGR_HU(v0, v0, v1); + break; case 0xE4: INST_NAME("PMULHUW Gx,Ex"); nextop = F8; diff --git a/src/dynarec/la64/dynarec_la64_f0.c b/src/dynarec/la64/dynarec_la64_f0.c index 0f7a48d8..bfc918e8 100644 --- a/src/dynarec/la64/dynarec_la64_f0.c +++ b/src/dynarec/la64/dynarec_la64_f0.c @@ -75,6 +75,27 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } SMDMB(); break; + case 0x09: + INST_NAME("LOCK OR Ed, Gd"); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETGD; + SMDMB(); + if (MODREG) { + ed = TO_LA64((nextop & 7) + (rex.b << 3)); + emit_or32(dyn, ninst, rex, ed, gd, x3, x4); + } else { + addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0); + MARKLOCK; + LLxw(x1, wback, 0); + OR(x4, x1, gd); + SCxw(x4, wback, 0); + BEQZ_MARKLOCK(x4); + IFX (X_ALL | X_PEND) + emit_or32(dyn, ninst, rex, x1, gd, x3, x4); + } + SMDMB(); + break; case 0x0F: nextop = F8; switch (nextop) { diff --git a/src/dynarec/la64/la64_emitter.h b/src/dynarec/la64/la64_emitter.h index c243d026..dc06d2a3 100644 --- a/src/dynarec/la64/la64_emitter.h +++ b/src/dynarec/la64/la64_emitter.h @@ -176,6 +176,8 @@ f24-f31 fs0-fs7 Static registers Callee // Made-up formats not found in the spec. #define type_1RI13(opc, imm13, rd) ((opc) << 18 | ((imm13) & 0x1FFFF) << 5 | (rd)) +#define type_2RI1(opc, imm1, rj, rd) ((opc) << 11 | ((imm1) & 0x1) << 10 | (rj) << 5 | (rd)) +#define type_2RI2(opc, imm2, rj, rd) ((opc) << 12 | ((imm2) & 0x3) << 10 | (rj) << 5 | (rd)) #define type_2RI3(opc, imm3, rj, rd) ((opc) << 13 | ((imm3) & 0x7 ) << 10 | (rj) << 5 | (rd)) #define type_2RI4(opc, imm4, rj, rd) ((opc) << 14 | ((imm4) & 0xF ) << 10 | (rj) << 5 | (rd)) #define type_2RI5(opc, imm5, rj, rd) ((opc) << 15 | ((imm5) & 0x1F) << 10 | (rj) << 5 | (rd)) @@ -1380,6 +1382,14 @@ LSX instruction starts with V, LASX instruction starts with XV. #define VSLT_HU(vd, vj, vk) EMIT(type_3R(0b01110000000010001, vk, vj, vd)) #define VSLT_WU(vd, vj, vk) EMIT(type_3R(0b01110000000010010, vk, vj, vd)) #define VSLT_DU(vd, vj, vk) EMIT(type_3R(0b01110000000010011, vk, vj, vd)) +#define VREPLVE_B(vd, vj, rk) EMIT(type_3R(0b01110001001000100, rk, vj, vd)) +#define VREPLVE_H(vd, vj, rk) EMIT(type_3R(0b01110001001000101, rk, vj, vd)) +#define VREPLVE_W(vd, vj, rk) EMIT(type_3R(0b01110001001000110, rk, vj, vd)) +#define VREPLVE_D(vd, vj, rk) EMIT(type_3R(0b01110001001000111, rk, vj, vd)) +#define VREPLVEI_B(vd, vk, imm4) EMIT(type_2RI4(0b011100101111011110, imm4, vk, vd)) +#define VREPLVEI_H(vd, vk, imm3) EMIT(type_2RI3(0b0111001011110111110, imm3, vk, vd)) +#define VREPLVEI_W(vd, vk, imm2) EMIT(type_2RI2(0b01110010111101111110, imm2, vk, vd)) +#define VREPLVEI_D(vd, vk, imm1) EMIT(type_2RI1(0b011100101111011111110, imm1, vk, vd)) #define VBSLL_V(vd, vj, imm5) EMIT(type_2RI5(0b01110010100011100, imm5, vj, vd)) #define VBSRL_V(vd, vj, imm5) EMIT(type_2RI5(0b01110010100011101, imm5, vj, vd)) #define VPACKEV_B(vd, vj, vk) EMIT(type_3R(0b01110001000101100, vk, vj, vd)) |