[LA64_DYNAREC] Addressed more issues reported in #4214 (#4219)

This commit is contained in:
Yang Liu authored and GitHub committed 2026-08-09 00:21:12 +02:00
1 parent da05e01235
commit 78bf553c62
34 files changed
+452 -344

No files matched your search

+68 -20
View File
@@ -111,6 +111,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
INST_NAME("PUSH ES");
LD_HU(x1, xEmu, offsetof(x64emu_t, segs[_ES]));
PUSH1_32(x1);
SMWRITE();
} else {
INST_NAME("Illegal 06");
if (BOX64DRENV(dynarec_safeflags) > 1) {
@@ -128,6 +129,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0x07:
if (rex.is32bits) {
INST_NAME("POP ES");
SMREAD();
POP1_32(x1);
ST_H(x1, xEmu, offsetof(x64emu_t, segs[_ES]));
} else {
@@ -135,7 +137,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_PEND);
} else {
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_FUSION); // Hack to set flags in "don't care" state
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags in "don't care" state
}
GETIP(ip, x7);
BARRIER(BARRIER_FLOAT);
@@ -801,6 +803,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
TABLE64(x3, addr - 4);
LD_W(x1, x3, 0);
PUSH1mz(x1);
SMWRITE();
} else {
if (!i64) {
PUSH1mz(xZR);
@@ -939,7 +942,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x6E:
case 0x6F:
INST_NAME(opcode == 0x6C ? "OUTSB" : "OUTSD");
INST_NAME(opcode == 0x6E ? "OUTSB" : "OUTSD");
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_PEND);
} else {
@@ -1467,7 +1470,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x8C:
nextop = F8;
u8 = (nextop & 38) >> 3;
u8 = (nextop & 0x38) >> 3;
if (u8 > 5) {
INST_NAME("Invalid MOV Ed, Seg");
UDF();
@@ -1478,10 +1481,10 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
if (MODREG) {
SCRATCH_USAGE(0);
gd = TO_NAT((nextop & 7) + (rex.b << 3));
LD_HU(gd, xEmu, offsetof(x64emu_t, segs[(nextop & 0x38) >> 3]));
LD_HU(gd, xEmu, offsetof(x64emu_t, segs[u8]));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
LD_HU(x3, xEmu, offsetof(x64emu_t, segs[(nextop & 0x38) >> 3]));
LD_HU(x3, xEmu, offsetof(x64emu_t, segs[u8]));
ST_H(x3, ed, fixedaddress);
SMWRITE2();
}
@@ -1767,6 +1770,11 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
ANDI(x1, xFlags, 1 << F_DF);
BNEZ_MARK2(x1);
// special optim for large RCX value on forward case only
if (BOX64DRENV(dynarec_safeflags)) {
SUB_D(x1, xRDI, xRSI);
ADDI_D(x6, xZR, 8);
BLTU_MARK(x1, x6);
}
OR(x1, xRSI, xRDI);
ANDI(x1, x1, 7);
BNEZ_MARK(x1);
@@ -2995,8 +3003,8 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
switch ((nextop >> 3) & 7) {
case 0:
INST_NAME("ROL Eb, 1");
GETEB(x1, 0);
SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION); // removed PENDING on purpose
GETEB(x1, 0);
emit_rol8c(dyn, ninst, ed, 1, x4, x5, x6);
EBBACK();
break;
@@ -3124,11 +3132,11 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
switch ((nextop >> 3) & 7) {
case 0:
INST_NAME("ROL Eb, CL");
GETEB(x1, 0);
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_OF | X_CF);
}
SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION); // removed PENDING on purpose
GETEB(x1, 0);
UFLAG_IF {
ANDI(x2, xRCX, 0x1f);
CBZ_NEXT(x2);
@@ -3139,11 +3147,11 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 1:
INST_NAME("ROR Eb, CL");
GETEB(x1, 0);
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_OF | X_CF);
}
SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION); // removed PENDING on purpose
GETEB(x1, 0);
UFLAG_IF {
ANDI(x2, xRCX, 0x1f);
CBZ_NEXT(x2);
@@ -3154,13 +3162,13 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 2:
INST_NAME("RCL Eb, CL");
GETEB(x1, 0);
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_OF | X_CF);
} else {
READFLAGS(X_CF);
}
SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
GETEB(x1, 0);
ANDI(x2, xRCX, 0x1f);
CBZ_NEXT(x2);
emit_rcl8(dyn, ninst, ed, x2, x4, x5, x6);
@@ -3168,13 +3176,13 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 3:
INST_NAME("RCR Eb, CL");
GETEB(x1, 0);
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_OF | X_CF);
} else {
READFLAGS(X_CF);
}
SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
GETEB(x1, 0);
ANDI(x2, xRCX, 0x1f);
CBZ_NEXT(x2);
emit_rcr8(dyn, ninst, ed, x2, x4, x5, x6);
@@ -3183,40 +3191,40 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 4:
case 6:
INST_NAME("SHL Eb, CL");
GETEB(x1, 0);
ANDI(x2, xRCX, 0x1F);
CBZ_NEXT(x2);
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION);
GETEB(x1, 0);
ANDI(x2, xRCX, 0x1F);
CBZ_NEXT(x2);
emit_shl8(dyn, ninst, x1, x2, x5, x4, x6);
EBBACK();
break;
case 5:
INST_NAME("SHR Eb, CL");
GETEB(x1, 0);
ANDI(x2, xRCX, 0x1F);
CBZ_NEXT(x2);
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION);
GETEB(x1, 0);
ANDI(x2, xRCX, 0x1F);
CBZ_NEXT(x2);
emit_shr8(dyn, ninst, x1, x2, x5, x4, x6);
EBBACK();
break;
case 7:
INST_NAME("SAR Eb, CL");
GETSEB(x1, 0);
ANDI(x2, xRCX, 0x1f);
CBZ_NEXT(x2);
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION);
GETSEB(x1, 0);
ANDI(x2, xRCX, 0x1f);
CBZ_NEXT(x2);
emit_sar8(dyn, ninst, x1, x2, x5, x4, x6);
EBBACK();
break;
@@ -4182,7 +4190,6 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
}
// TODO: handle zero divisor
if (rex.w) {
MARKREGd(xRAX);
MARKREGd(xRDX);
@@ -4194,11 +4201,32 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
MARKREGd(xRDX);
SET_DFNONE();
GETSED(0);
if (BOX64ENV(dynarec_div0)) {
BNE_MARK3(ed, xZR);
GETIP_(ip, x7);
STORE_XEMU_CALL();
CALL(const_native_div0, -1, 0, 0);
CLEARIP();
LOAD_XEMU_CALL();
jump_to_epilog(dyn, 0, xRIP, ninst);
MARK3;
}
SLLI_D(x3, xRDX, 32);
ZEROUP2(x2, xRAX);
OR(x3, x3, x2);
DIV_D(x2, x3, ed);
MOD_D(xRDX, x3, ed);
if (BOX64ENV(dynarec_div0)) {
SEXT_W(x5, x2);
BEQ_MARK2(x5, x2);
GETIP_(ip, x7);
STORE_XEMU_CALL();
CALL(const_native_div0, -1, 0, 0);
CLEARIP();
LOAD_XEMU_CALL();
jump_to_epilog(dyn, 0, xRIP, ninst);
MARK2;
}
ZEROUP2(xRAX, x2);
if (NEED_ZEROUP(xRDX)) ZEROUP(xRDX);
} else {
@@ -4208,11 +4236,31 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
&& *(uint8_t*)(dyn->insts[ninst - 1].x64.addr + 1) == 0x99) {
FORCE_DFNONE();
GETED(0);
if (BOX64ENV(dynarec_div0)) {
BNE_MARKF2(ed, xZR);
GETIP_(ip, x7);
STORE_XEMU_CALL();
CALL(const_native_div0, -1, 0, 0);
CLEARIP();
LOAD_XEMU_CALL();
jump_to_epilog(dyn, 0, xRIP, ninst);
MARKF2;
}
DIV_D(x2, xRAX, ed);
MOD_D(xRDX, xRAX, ed);
MV(xRAX, x2);
} else {
GETEDH(x4, x1, 0); // get edd changed addr, so cannot be called 2 times for same op...
if (BOX64ENV(dynarec_div0)) {
BNE_MARKF(ed, xZR);
GETIP_(ip, x7);
STORE_XEMU_CALL();
CALL(const_native_div0, -1, 0, 0);
CLEARIP();
LOAD_XEMU_CALL();
jump_to_epilog(dyn, 0, xRIP, ninst);
MARKF;
}
// need to see if RDX == 0 and RAX not signed
// or RDX == -1 and RAX signed
BNE_MARK2(xRDX, xZR);
+45 -34
View File
@@ -70,7 +70,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
INST_NAME("XGETBV");
ZEROUP2(x1, xRCX);
BEQZ_MARK(x1);
EMIT(0); // Is there any assigned illegal instruction?
UDF();
MARK;
MOV32w(xRAX, 0b111);
MOV32w(xRDX, 0);
@@ -416,7 +416,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETGM(v0);
GETEXSD(v1, 0, 0);
if (BOX64ENV(dynarec_fastround)) {
VFTINTRZ_W_S(v0, v1);
VFTINT_W_S(v0, v1);
} else {
MOVGR2FCSR(FCSR2, xZR); // reset all bits
VFTINT_W_S(v0, v1);
@@ -489,8 +489,6 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETGM(q0);
GETEM(q1, 0);
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn);
VLDI(v0, 0b0000010000111); // broadcast 0b10000111 as byte
VAND_V(v0, v0, q1);
VMINI_BU(v0, v0, 0x1f);
@@ -650,7 +648,6 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0xC8:
INST_NAME("SHA1NEXTE Gx, Ex");
u8 = nextop;
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 0);
@@ -662,7 +659,6 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0xC9:
INST_NAME("SHA1MSG1 Gx, Ex");
u8 = nextop;
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 0);
@@ -673,7 +669,6 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0xCA:
INST_NAME("SHA1MSG2 Gx, Ex");
u8 = nextop;
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 0);
@@ -728,28 +723,48 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
INST_NAME("MOVBE Gd, Ed");
nextop = F8;
GETGDd;
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
LDxw(gd, ed, fixedaddress);
if (rex.w) {
REVB_D(gd, gd);
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
if (rex.w) {
REVB_D(gd, ed);
} else {
REVB_2W(gd, ed);
if (NEED_ZEROUP(gd)) ZEROUP(gd);
}
} else {
REVB_2W(gd, gd);
if (NEED_ZEROUP(gd)) ZEROUP(gd);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
LDxw(gd, ed, fixedaddress);
if (rex.w) {
REVB_D(gd, gd);
} else {
REVB_2W(gd, gd);
if (NEED_ZEROUP(gd)) ZEROUP(gd);
}
}
break;
case 0xF1:
INST_NAME("MOVBE Ed, Gd");
nextop = F8;
GETGDs;
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
if (rex.w)
REVB_D(x1, gd);
else
REVB_2W(x1, gd);
SDxw(x1, wback, fixedaddress);
SMWRITE2();
if (MODREG) { // reg <= reg
ed = TO_NAT((nextop & 7) + (rex.b << 3));
if (rex.w) {
REVB_D(ed, gd);
} else {
REVB_2W(ed, gd);
if (NEED_ZEROUP(ed)) ZEROUP(ed);
}
} else { // mem <= reg
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
if (rex.w)
REVB_D(x1, gd);
else
REVB_2W(x1, gd);
SDxw(x1, wback, fixedaddress);
SMWRITE2();
}
break;
default:
DEFAULT;
@@ -904,7 +919,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
#undef GO
case 0x50:
INST_NAME("MOVMSPKPS Gd, Ex");
INST_NAME("MOVMSKPS Gd, Ex");
nextop = F8;
GETEX(q0, 0, 0);
GETGDd;
@@ -1123,7 +1138,6 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETGX(v0, 1);
GETEX(v1, 0, 0);
q0 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
VFCMP_S(q0, v1, v0, cLT); // ~cLT = un ge eq, if either v0/v1=nan ,choose v1. if eq either is ok,but when +0.0 == -0.0 x86 sse choose v1
VBITSEL_V(v0, v1, v0, q0); // swap v0 v1 => v1 v0 for ~cLT
break;
@@ -1182,7 +1196,6 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
nextop = F8;
GETGM(v0);
GETEM(v1, 0);
q0 = fpu_get_scratch(dyn);
VPACKEV_D(v0, v1, v0);
VSSRANI_BU_H(v0, v0, 0);
break;
@@ -1215,7 +1228,6 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
nextop = F8;
GETGM(v0);
GETEM(v1, 0);
d0 = fpu_get_scratch(dyn);
VPACKEV_D(v0, v1, v0);
VSSRANI_H_W(v0, v0, 0);
break;
@@ -1305,7 +1317,6 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
break;
default:
*ok = 0;
DEFAULT;
}
break;
@@ -1880,21 +1891,21 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SRAI_D(x1, gd, 6);
else
SRAI_W(x1, gd, 5);
if (!rex.w && !rex.is32bits) { ADDI_W(x1, x1, 0); }
ALSLy(x3, x1, wback, 2 + rex.w); // (&ed) += r1*4;
LDxw(x1, x3, fixedaddress);
ed = x1;
wback = x3;
}
ANDI(x2, gd, rex.w ? 0x3f : 0x1f);
SRL_D(x4, ed, x2);
if(cpuext.lbt) {
X64_SET_EFLAGS(x4, X_CF);
} else {
BSTRINS_D(xFlags, x4, 0, 0);
IFX (X_CF) {
SRL_D(x4, ed, x2);
if (cpuext.lbt) {
X64_SET_EFLAGS(x4, X_CF);
} else {
BSTRINS_D(xFlags, x4, F_CF, F_CF);
}
}
ADDI_D(x4, xZR, 1);
ANDI(x2, gd, rex.w ? 0x3f : 0x1f);
SLL_D(x4, x4, x2);
ANDN(ed, ed, x4);
if (wback) {
+7 -7
View File
@@ -248,7 +248,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGWEW(x1, x2, 0);
emit_xor16(dyn, ninst, ed, gd, x4, x5, x6);
emit_xor16(dyn, ninst, ed, gd, x4, x5);
EWBACK;
break;
case 0x33:
@@ -270,7 +270,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
}
GETGWEW(x1, x2, 0);
emit_xor16(dyn, ninst, gd, ed, x3, x4, x5);
emit_xor16(dyn, ninst, gd, ed, x3, x4);
GWBACK;
break;
case 0x35:
@@ -279,7 +279,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
i32 = F16;
BSTRPICK_D(x1, xRAX, 15, 0);
MOV32w(x2, i32);
emit_xor16(dyn, ninst, x1, x2, x3, x4, x5);
emit_xor16(dyn, ninst, x1, x2, x3, x4);
BSTRINSz(xRAX, x1, 15, 0);
break;
case 0x39:
@@ -607,7 +607,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
else
u64 = (uint16_t)(int16_t)F8S;
MOV32w(x5, u64);
emit_xor16(dyn, ninst, x1, x5, x2, x4, x6);
emit_xor16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
case 7: // CMP
@@ -732,7 +732,6 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
break;
case 0x8D:
INST_NAME("LEA Gd, Ed");
nextop = F8;
GETGDw;
if (MODREG) {
@@ -741,6 +740,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
*need_epilog = 1;
*ok = 0;
} else { // mem <= reg
INST_NAME("LEA Gw, Ed");
rex.seg = 0;
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 0, 0);
BSTRINS_D(gd, ed, 15, 0);
@@ -852,7 +852,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
break;
case 0xA1:
INST_NAME("MOV EAX, Od");
INST_NAME("MOV AX, Ow");
if (rex.is32bits && rex.is67)
u64 = F16S;
else if (rex.is32bits || rex.is67)
@@ -870,7 +870,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
BSTRINSz(xRAX, x2, 15, 0);
break;
case 0xA3:
INST_NAME("MOV Od, EAX");
INST_NAME("MOV Ow, AX");
if (rex.is32bits && rex.is67)
u64 = F16S;
else if (rex.is32bits || rex.is67)
+51 -34
View File
@@ -220,9 +220,8 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
case 0x2A:
INST_NAME("CVTPI2PD Gx,Em");
nextop = F8;
GETGX(v0, 1);
GETGX_empty(v0);
GETEM(v1, 0);
q0 = fpu_get_scratch(dyn);
VFFINTL_D_W(v0, v1);
break;
case 0x2B:
@@ -340,7 +339,6 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETGX(q0, 1);
GETEX(q1, 0, 0);
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
VLDI(v0, 0b0000010001111); // broadcast 0b10001111 as byte
VAND_V(v0, v0, q1);
VMINI_BU(v0, v0, 0x1f);
@@ -803,7 +801,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
case 0xDB:
INST_NAME("AESIMC Gx, Ex"); // AES-NI
nextop = F8;
GETEX(q1, 0, 0);
GETEX_AES(q1, 0, 0);
GETGX_empty(q0);
if (q0 != q1) {
VOR_V(q0, q1, q1);
@@ -814,7 +812,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
INST_NAME("AESENC Gx, Ex"); // AES-NI
nextop = F8;
GETG;
GETEX(q1, 0, 0);
GETEX_AES(q1, 0, 0);
GETGX(q0, 1);
if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) {
d0 = SCRATCH;
@@ -842,7 +840,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
INST_NAME("AESDEC Gx, Ex"); // AES-NI
nextop = F8;
GETG;
GETEX(q1, 0, 0);
GETEX_AES(q1, 0, 0);
GETGX(q0, 1);
if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) {
d0 = SCRATCH;
@@ -856,7 +854,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
INST_NAME("AESDECLAST Gx, Ex"); // AES-NI
nextop = F8;
GETG;
GETEX(q1, 0, 0);
GETEX_AES(q1, 0, 0);
GETGX(q0, 1);
if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) {
d0 = SCRATCH;
@@ -870,21 +868,33 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
INST_NAME("MOVBE Gw, Ew");
nextop = F8;
GETGDw;
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 1, 0);
LD_HU(x1, ed, fixedaddress);
REVB_2H(x1, x1);
BSTRINS_D(gd, x1, 15, 0);
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
REVB_2H(x1, ed);
BSTRINS_D(gd, x1, 15, 0);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 1, 0);
LD_HU(x1, ed, fixedaddress);
REVB_2H(x1, x1);
BSTRINS_D(gd, x1, 15, 0);
}
break;
case 0xF1:
INST_NAME("MOVBE Ew, Gw");
nextop = F8;
GETGDs;
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x2, &fixedaddress, rex, NULL, 1, 0);
REVB_2H(x1, gd);
ST_H(x1, wback, fixedaddress);
SMWRITE();
if (MODREG) { // reg <= reg
ed = TO_NAT((nextop & 7) + (rex.b << 3));
REVB_2H(x1, gd);
BSTRINS_D(ed, x1, 15, 0);
} else { // mem <= reg
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x2, &fixedaddress, rex, NULL, 1, 0);
REVB_2H(x1, gd);
ST_H(x1, wback, fixedaddress);
SMWRITE();
}
break;
case 0xF6:
INST_NAME("ADCX Gd, Ed");
@@ -938,7 +948,6 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETEX(q1, 0, 1);
GETGX_empty(q0);
u8 = F8;
v1 = fpu_get_scratch(dyn);
if (u8 & 4) {
VFRINT_S(q0, q1);
} else {
@@ -951,7 +960,6 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETEX(q1, 0, 1);
GETGX_empty(q0);
u8 = F8;
v1 = fpu_get_scratch(dyn);
if (u8 & 4) {
VFRINT_D(q0, q1);
} else {
@@ -1044,7 +1052,6 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETGX(q0, 1);
GETEX(q1, 0, 1);
u8 = F8;
i32 = 0;
if (q0 != q1) {
if (u8 == 0xff) {
VAND_V(q0, q1, q1);
@@ -1163,7 +1170,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
break;
case 0x17:
INST_NAME("EXTRACTPS Ew, Gx, Ib");
INST_NAME("EXTRACTPS Ed, Gx, Ib");
nextop = F8;
GETGX(q0, 0);
if (MODREG) {
@@ -1181,7 +1188,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
break;
case 0x20:
INST_NAME("PINSRB Gx, ED, Ib");
INST_NAME("PINSRB Gx, Ed, Ib");
nextop = F8;
GETGX(q0, 1);
if (MODREG) {
@@ -1223,7 +1230,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
break;
case 0x22:
INST_NAME("PINSRD Gx, ED, Ib");
INST_NAME("PINSRD Gx, Ed, Ib");
nextop = F8;
GETGX(q0, 1);
GETED(1);
@@ -1494,6 +1501,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
break;
#define GO(GETFLAGS, NO, YES, NATNO, NATYES, F, I) \
if (rex.w) return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog); \
READFLAGS(F); \
tmp1 = x1; \
tmp3 = x3; \
@@ -1522,7 +1530,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
case 0x50:
nextop = F8;
INST_NAME("PMOVMSKD Gd, Ex");
INST_NAME("MOVMSKPD Gd, Ex");
GETEX(q0, 0, 0);
GETGDd;
VPICKVE2GR_D(x1, q0, 0);
@@ -1744,7 +1752,6 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
// If both NaN, then copy NaN.
// but x86 will copy the second if either v0[x] or v1[x] is NaN
q0 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
VFCMP_D(q0, v1, v0, cLT); // ~cLT = un ge eq, if either v0/v1=nan ,choose v1. if eq either is ok,but when +0.0 == -0.0 x86 sse choose v1
VBITSEL_V(v0, v1, v0, q0); // swap v0 v1 => v1 v0 for ~cLT
break;
@@ -1923,8 +1930,8 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
case 0x70:
INST_NAME("PSHUFD Gx, Ex, Ib");
nextop = F8;
GETGX(v0, 1);
GETEX(v1, 0, 1);
GETGX_empty(v0);
u8 = F8;
VSHUF4I_W(v0, v1, u8);
break;
@@ -1968,7 +1975,6 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
break;
default:
*ok = 0;
DEFAULT;
}
break;
@@ -2196,6 +2202,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
break;
case 0xA3:
if (rex.w) return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog);
INST_NAME("BT Ew, Gw");
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL & ~X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
@@ -2226,6 +2233,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
break;
case 0xA4:
if (rex.w) return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog);
INST_NAME("SHLD Ew, Gw, Ib");
nextop = F8;
u8 = geted_ib(dyn, addr, ninst, nextop) & 0x1f;
@@ -2241,6 +2249,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
break;
case 0xA5:
if (rex.w) return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog);
nextop = F8;
INST_NAME("SHLD Ew, Gw, CL");
if (BOX64DRENV(dynarec_safeflags) > 1) {
@@ -2255,6 +2264,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
EWBACK;
break;
case 0xAB:
if (rex.w) return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog);
INST_NAME("BTS Ew, Gw");
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL & ~X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
@@ -2294,6 +2304,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
break;
case 0xAC:
if (rex.w) return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog);
nextop = F8;
INST_NAME("SHRD Ew, Gw, Ib");
u8 = geted_ib(dyn, addr, ninst, nextop) & 0x1f;
@@ -2309,6 +2320,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
break;
case 0xAD:
if (rex.w) return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog);
nextop = F8;
INST_NAME("SHRD Ew, Gw, CL");
if (BOX64DRENV(dynarec_safeflags) > 1) {
@@ -2347,6 +2359,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
break;
case 0xAF:
if (rex.w) return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog);
INST_NAME("IMUL Gw, Ew");
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
nextop = F8;
@@ -2372,6 +2385,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
IFXA (X_ALL, cpuext.lbt) SPILL_EFLAGS();
break;
case 0xB3:
if (rex.w) return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog);
INST_NAME("BTR Ew, Gw");
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL & ~X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
@@ -2412,6 +2426,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
break;
case 0xB6:
if (rex.w) return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog);
INST_NAME("MOVZX Gw, Eb");
nextop = F8;
if (MODREG) {
@@ -2433,6 +2448,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
BSTRINS_D(gd, x1, 15, 0); // insert in Gw
break;
case 0xBA:
if (rex.w) return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog);
nextop = F8;
switch ((nextop >> 3) & 7) {
case 4:
@@ -2533,6 +2549,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
break;
case 0xBB:
if (rex.w) return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog);
INST_NAME("BTC Ew, Gw");
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL & ~X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
@@ -2572,6 +2589,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
break;
case 0xBC:
if (rex.w) return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog);
INST_NAME("BSF Gw, Ew");
if (BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
@@ -2599,6 +2617,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
IFX (X_ALL) SPILL_EFLAGS();
break;
case 0xBD:
if (rex.w) return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog);
INST_NAME("BSR Gw, Ew");
if (BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
@@ -2628,6 +2647,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
IFX (X_ALL) SPILL_EFLAGS();
break;
case 0xBE:
if (rex.w) return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog);
INST_NAME("MOVSX Gw, Eb");
nextop = F8;
GETGDw;
@@ -2670,6 +2690,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
BSTRINS_D(gd, ed, 15, 0);
break;
case 0xC1:
if (rex.w) return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog);
INST_NAME("XADD Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
@@ -2720,13 +2741,12 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
if (MODREG) {
GETEX(v0, 0, 1);
u8 = (F8) & 7;
v1 = fpu_get_scratch(dyn);
VPICKVE2GR_HU(gd, v0, u8);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x4, &fixedaddress, rex, NULL, 1, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x4, &fixedaddress, rex, NULL, 14, 1);
u8 = (F8) & 7;
LD_HU(gd, wback, (u8 << 1));
LD_HU(gd, wback, fixedaddress + (u8 << 1));
}
break;
case 0xC6:
@@ -2816,7 +2836,6 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
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
VSLE_DU(v1, v0, v1);
@@ -3130,8 +3149,6 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 0);
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
VABSD_BU(q0, q0, q1);
VHADDW_HU_BU(q0, q0, q0);
VHADDW_WU_HU(q0, q0, q0);
@@ -3141,7 +3158,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
INST_NAME("MASKMOVDQU Gx, Ex");
nextop = F8;
UP32_READ(xRDI);
GETGX(v0, 1);
GETGX(v0, 0);
GETEX(v1, 0, 0);
q0 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
-1
View File
@@ -50,7 +50,6 @@ uintptr_t dynarec64_66F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, in
case 0xB8:
INST_NAME("POPCNT Gw, Ew");
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
SET_DFNONE();
nextop = F8;
GETGDw;
GETEW(x4, 0);
+2 -4
View File
@@ -430,7 +430,6 @@ uintptr_t dynarec64_AVX_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, in
nextop = F8;
GETGY_empty_VYEY_xy(v0, v1, v2, 0);
q0 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
VFCMPxy(S, q0, v2, v1, cULE);
VBITSEL_Vxy(v0, v1, v2, q0);
break;
@@ -464,7 +463,6 @@ uintptr_t dynarec64_AVX_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, in
nextop = F8;
GETGY_empty_VYEY_xy(v0, v1, v2, 0);
q0 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
VFCMPxy(S, q0, v2, v1, cLT);
VBITSEL_Vxy(v0, v2, v1, q0);
break;
@@ -573,12 +571,12 @@ uintptr_t dynarec64_AVX_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, in
case 0x04: VFCMPxy(S, v0, v1, v2, cUNE); break; // Not Equal (or unordered on ARM, not on X86...)
case 0x05: VFCMPxy(S, v0, v2, v1, cULE); break; // Greater or equal or unordered
case 0x06: VFCMPxy(S, v0, v2, v1, cULT); break; // Greater or unordered
case 0x07: VFCMPxy(S, v0, v1, v2, cOR); break; // Greater or unordered
case 0x07: VFCMPxy(S, v0, v1, v2, cOR); break; // Ordered (neither is NaN)
case 0x08: VFCMPxy(S, v0, v1, v2, cUEQ); break; // Equal, or unordered
case 0x09: VFCMPxy(S, v0, v1, v2, cULT); break; // Less than or unordered
case 0x0a: VFCMPxy(S, v0, v1, v2, cULE); break; // Less or equal or unordered
case 0x0b: XVXOR_V(v0, v0, v0); break; // false
case 0x0c: VFCMPxy(S, v0, v1, v2, cNE); break; // Not Eual, ordered
case 0x0c: VFCMPxy(S, v0, v1, v2, cNE); break; // Not Equal, ordered
case 0x0d: VFCMPxy(S, v0, v2, v1, cLE); break; // Greater or Equal ordered
case 0x0e: VFCMPxy(S, v0, v2, v1, cLT); break; // Greater ordered
case 0x0f: VSEQxy(B, v0, v1, v1); break; // true
+4 -5
View File
@@ -162,7 +162,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
}
GETGYx(v0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x4, x5, &fixedaddress, rex, NULL, 0, 0);
VSTELM_D(v0, ed, 0, 1);
VSTELM_D(v0, ed, fixedaddress, 1);
SMWRITE2();
break;
case 0x28:
@@ -659,7 +659,6 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
}
break;
default:
*ok = 0;
DEFAULT;
}
break;
@@ -883,12 +882,12 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
case 0x04: VFCMPxy(D, v0, v1, v2, cUNE); break; // Not Equal (or unordered on ARM, not on X86...)
case 0x05: VFCMPxy(D, v0, v2, v1, cULE); break; // Greater or equal or unordered
case 0x06: VFCMPxy(D, v0, v2, v1, cULT); break; // Greater or unordered
case 0x07: VFCMPxy(D, v0, v1, v2, cOR); break; // Greater or unordered
case 0x07: VFCMPxy(D, v0, v1, v2, cOR); break; // Ordered (neither is NaN)
case 0x08: VFCMPxy(D, v0, v1, v2, cUEQ); break; // Equal, or unordered
case 0x09: VFCMPxy(D, v0, v1, v2, cULT); break; // Less than or unordered
case 0x0a: VFCMPxy(D, v0, v1, v2, cULE); break; // Less or equal or unordered
case 0x0b: XVXOR_V(v0, v0, v0); break; // false
case 0x0c: VFCMPxy(D, v0, v1, v2, cNE); break; // Not Eual, ordered
case 0x0c: VFCMPxy(D, v0, v1, v2, cNE); break; // Not Equal, ordered
case 0x0d: VFCMPxy(D, v0, v2, v1, cLE); break; // Greater or Equal ordered
case 0x0e: VFCMPxy(D, v0, v2, v1, cLT); break; // Greater ordered
case 0x0f: VSEQxy(B, v0, v1, v1); break; // true
@@ -897,7 +896,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
case 0xC4:
INST_NAME("VPINSRW Gx, Vx, ED, Ib");
nextop = F8;
GETEWW(0, x5, 1);
GETEWW(x3, x5, 1);
GETVYx(v1, 0);
GETGYx_empty(v0);
u8 = F8;
+12 -14
View File
@@ -261,11 +261,6 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
GETEYx(v1, 0, 0);
GETGYy_empty(v0);
d0 = fpu_get_scratch(dyn);
/*
xvffintl.s.h convert [h0..h3,h4..h7,h8..h11,h12..h15] to [h0..h3,h8..h11]
xvffinth.s.h convert [h0..h3,h4..h7,h8..h11,h12..h15] to [h4..h7,h12..h15]
so user xvpermi.d to reorder input [h0..h3,h4..h7,h8..h11,h12..h15] to [h0..h3,h8..h11,h4..h7,h12..h15]
*/
XVPERMI_D(d0, v1, 0b11011000);
XVFCVTL_S_H(v0, d0);
} else {
@@ -277,7 +272,10 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
case 0x16:
INST_NAME("VPERMPS Gx, Vx, Ex");
nextop = F8;
if (!vex.l) UDF();
if (!vex.l) {
UDF();
break;
}
GETGY_empty_VYEY_xy(v0, v1, v2, 0);
XVPERM_W(v0, v2, v1);
break;
@@ -292,7 +290,6 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
} else IFX (X_ALL) {
X64_SET_EFLAGS(xZR, X_ALL);
}
SET_DFNONE();
v0 = fpu_get_scratch(dyn);
IFX (X_ZF) {
VAND_Vxy(v0, q1, q0);
@@ -625,7 +622,10 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
case 0x36:
INST_NAME("VPERMD Gx, Vx, Ex");
nextop = F8;
if (!vex.l) UDF();
if (!vex.l) {
UDF();
break;
}
GETGY_empty_VYEY_xy(v0, v1, v2, 0);
XVPERM_W(v0, v2, v1);
break;
@@ -903,7 +903,6 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
wb1 = u8 >> 6; // scale
GETVYxy(v2, 1);
GETGYxy(v0, 1);
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
if (vex.l) {
@@ -990,7 +989,6 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
GETVYx(v2, 1);
GETGYx(v0, 1);
}
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
if (vex.l) {
@@ -1287,7 +1285,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
case 0xDB:
INST_NAME("VAESIMC Gx, Ex");
nextop = F8;
GETEYx(q1, 0, 0);
GETEYx_AES(q1, 0, 0);
GETGYx_empty(q0);
if (q0 != q1) {
VOR_V(q0, q1, q1);
@@ -1297,7 +1295,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
case 0xDC:
INST_NAME("VAESENC Gx, Vx, Ex");
nextop = F8;
GETGY_empty_VYEY_xy(q0, q1, q2, 0);
GETGY_empty_VYEYxy_AES(q0, q1, q2, 0);
if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) {
d0 = SCRATCH;
VOR_Vxy(d0, q2, q2);
@@ -1335,7 +1333,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
case 0xDE:
INST_NAME("VAESDEC Gx, Vx, Ex"); // AES-NI
nextop = F8;
GETGY_empty_VYEY_xy(q0, q1, q2, 0);
GETGY_empty_VYEYxy_AES(q0, q1, q2, 0);
if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) {
d0 = SCRATCH;
VOR_Vxy(d0, q2, q2);
@@ -1354,7 +1352,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
case 0xDF:
INST_NAME("VAESDECLAST Gx, Vx, Ex"); // AES-NI
nextop = F8;
GETGY_empty_VYEY_xy(q0, q1, q2, 0);
GETGY_empty_VYEYxy_AES(q0, q1, q2, 0);
if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) {
d0 = SCRATCH;
VOR_Vxy(d0, q2, q2);
+12 -6
View File
@@ -73,7 +73,10 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
INST_NAME("VPERMQ Gx, Ex, Imm8");
}
nextop = F8;
if (!vex.l) EMIT(0);
if (!vex.l) {
UDF();
break;
}
GETGY_empty_EY_xy(v0, v1, 1);
u8 = F8;
XVPERMI_D(v0, v1, u8);
@@ -140,7 +143,10 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
INST_NAME("VPERM2I128 Gx, Vx, Ex, Imm8");
}
nextop = F8;
if (!vex.l) EMIT(0);
if (!vex.l) {
UDF();
break;
}
GETGY_empty_VYEY_xy(v0, v1, v2, 1);
u8 = F8;
if ((u8 & 0x88) == 0x88) {
@@ -773,12 +779,12 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
INST_NAME("VAESKEYGENASSIST Gx, Ex, Ib");
nextop = F8;
GETG;
GETEYx(q1, 0, 1);
if (vex.l) {
GETGYy(q0, 1);
} else {
GETGYx_empty(q0);
UDF();
break;
}
GETEYx_AES(q1, 0, 1);
GETGYx_empty(q0);
if (q0 != q1)
VOR_V(q0, q1, q1);
u8 = F8;
+2 -2
View File
@@ -432,12 +432,12 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
case 0x04: VFCMP_D(q0, v1, v2, cUNE); break; // Not Equal (or unordered on ARM, not on X86...)
case 0x05: VFCMP_D(q0, v2, v1, cULE); break; // Greater or equal or unordered
case 0x06: VFCMP_D(q0, v2, v1, cULT); break; // Greater or unordered
case 0x07: VFCMP_D(q0, v1, v2, cOR); break; // Greater or unordered
case 0x07: VFCMP_D(q0, v1, v2, cOR); break; // Ordered (neither is NaN)
case 0x08: VFCMP_D(q0, v1, v2, cUEQ); break; // Equal, or unordered
case 0x09: VFCMP_D(q0, v1, v2, cULT); break; // Less than or unordered
case 0x0a: VFCMP_D(q0, v1, v2, cULE); break; // Less or equal or unordered
case 0x0b: break; // false
case 0x0c: VFCMP_D(q0, v1, v2, cNE); break; // Not Eual, ordered
case 0x0c: VFCMP_D(q0, v1, v2, cNE); break; // Not Equal, ordered
case 0x0d: VFCMP_D(q0, v2, v1, cLE); break; // Greater or Equal ordered
case 0x0e: VFCMP_D(q0, v2, v1, cLT); break; // Greater ordered
case 0x0f: VSEQ_B(q0, v1, v1); break; // true
+3 -3
View File
@@ -68,7 +68,7 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
GETGYx(q2, 0);
if (MODREG) {
GETVYx(q1, 0);
GETEYSD(q0, 1, 0);
GETEYSS(q0, 1, 0);
if (q0 != q2) VEXTRINS_W(q0, q2, 0b00000);
if (q0 != q1) {
VEXTRINS_D(q0, q1, 0b10001);
@@ -473,12 +473,12 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
case 0x04: VFCMP_S(q0, v1, v2, cUNE); break; // Not Equal (or unordered on ARM, not on X86...)
case 0x05: VFCMP_S(q0, v2, v1, cULE); break; // Greater or equal or unordered
case 0x06: VFCMP_S(q0, v2, v1, cULT); break; // Greater or unordered
case 0x07: VFCMP_S(q0, v1, v2, cOR); break; // Greater or unordered
case 0x07: VFCMP_S(q0, v1, v2, cOR); break; // Ordered (neither is NaN)
case 0x08: VFCMP_S(q0, v1, v2, cUEQ); break; // Equal, or unordered
case 0x09: VFCMP_S(q0, v1, v2, cULT); break; // Less than or unordered
case 0x0a: VFCMP_S(q0, v1, v2, cULE); break; // Less or equal or unordered
case 0x0b: break; // false
case 0x0c: VFCMP_S(q0, v1, v2, cNE); break; // Not Eual, ordered
case 0x0c: VFCMP_S(q0, v1, v2, cNE); break; // Not Equal, ordered
case 0x0d: VFCMP_S(q0, v2, v1, cLE); break; // Greater or Equal ordered
case 0x0e: VFCMP_S(q0, v2, v1, cLT); break; // Greater ordered
case 0x0f: VSEQ_B(q0, v1, v1); break; // true
-3
View File
@@ -28,13 +28,10 @@ uintptr_t dynarec64_D8(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
uint8_t nextop = F8;
uint8_t ed;
uint8_t wback, wb1;
uint8_t u8;
int64_t fixedaddress;
int unscaled;
int v1, v2;
int s0;
int i1, i2, i3;
MAYUSE(s0);
MAYUSE(v2);
+10 -8
View File
@@ -141,7 +141,8 @@ uintptr_t dynarec64_D9(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
if (i2 >= 0) {
LD_HU(x3, xEmu, offsetof(x64emu_t, fpu_tags));
if (i2 > 0) {
BSTRINS_D(x3, xZR, 15, 0);
NOR(x5, xZR, xZR); // x5 = ~0
BSTRINS_D(x3, x5, 63, 16);
SRLI_D(x3, x3, i2 * 2);
}
ANDI(x3, x3, 0b11);
@@ -373,20 +374,20 @@ uintptr_t dynarec64_D9(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
v0 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
v1 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn);
u8 = x87_setround(dyn, ninst, x1, x2);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x2);
if (ST_IS_F(0)) {
FCMP_S(fcc0, v0, v0, cEQ);
BCNEZ_MARK(fcc0);
B_NEXT_nocond;
B_MARK3_nocond;
MARK; // v0 is not nan
FABS_S(v1, v0);
MOV64x(x3, 1ULL << __FLT_MANT_DIG__);
MOVGR2FR_W(v2, x3);
MOVGR2FR_D(v2, x3);
FFINT_S_L(v2, v2);
FCMP_S(fcc1, v1, v2, cLT);
BCNEZ_MARK2(fcc1);
B_NEXT_nocond;
B_MARK3_nocond;
MARK2;
FTINT_L_S(v1, v0);
FFINT_S_L(v1, v1);
@@ -394,7 +395,7 @@ uintptr_t dynarec64_D9(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
FCMP_D(fcc0, v0, v0, cEQ);
BCNEZ_MARK(fcc0);
B_NEXT_nocond;
B_MARK3_nocond;
MARK; // v0 is not nan
FABS_D(v1, v0);
MOV64x(x3, 1ULL << __DBL_MANT_DIG__);
@@ -402,13 +403,14 @@ uintptr_t dynarec64_D9(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
FFINT_D_L(v2, v2);
FCMP_D(fcc1, v1, v2, cLT);
BCNEZ_MARK2(fcc1);
B_NEXT_nocond;
B_MARK3_nocond;
MARK2;
FTINT_L_D(v1, v0);
FFINT_D_L(v1, v1);
FCOPYSIGN_D(v0, v1, v0);
}
x87_restoreround(dyn, ninst, u8);
MARK3;
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 0xFD:
INST_NAME("FSCALE");
+4 -5
View File
@@ -107,8 +107,8 @@ uintptr_t dynarec64_DB(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0xE2:
INST_NAME("FNCLEX");
LD_H(x2, xEmu, offsetof(x64emu_t, sw));
BSTRINS_D(x2, x2, 7, 0); // IE .. PE, SF, ES
BSTRINS_D(x2, x2, 15, 15); // B
BSTRINS_D(x2, xZR, 7, 0); // IE .. PE, SF, ES
BSTRINS_D(x2, xZR, 15, 15); // B
ST_H(x2, xEmu, offsetof(x64emu_t, sw));
break;
case 0xE3:
@@ -184,6 +184,7 @@ uintptr_t dynarec64_DB(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
MOVGR2FCSR(FCSR2, xZR); // reset all bits
}
FTINT_W_D(v2, v1);
x87_restoreround(dyn, ninst, u8);
if (!BOX64ENV(dynarec_fastround)) {
MOVFCSR2GR(x5, FCSR2); // get back FPSR to check
BSTRPICK_D(x5, x5, FR_V, FR_V);
@@ -193,8 +194,6 @@ uintptr_t dynarec64_DB(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
MARK;
}
FST_S(v2, wback, fixedaddress);
x87_restoreround(dyn, ninst, u8);
break;
break;
case 3:
INST_NAME("FISTP Ed, ST0");
@@ -206,6 +205,7 @@ uintptr_t dynarec64_DB(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
MOVGR2FCSR(FCSR2, xZR); // reset all bits
}
FTINT_W_D(v2, v1);
x87_restoreround(dyn, ninst, u8);
if (!BOX64ENV(dynarec_fastround)) {
MOVFCSR2GR(x5, FCSR2); // get back FPSR to check
BSTRPICK_D(x5, x5, FR_V, FR_V);
@@ -215,7 +215,6 @@ uintptr_t dynarec64_DB(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
MARK;
}
FST_S(v2, wback, fixedaddress);
x87_restoreround(dyn, ninst, u8);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 5:
+5
View File
@@ -151,6 +151,7 @@ uintptr_t dynarec64_DC(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
FLD_D(v2, wback, fixedaddress);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
FADD_D(v1, v1, v2);
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 1:
@@ -161,6 +162,7 @@ uintptr_t dynarec64_DC(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
FLD_D(v2, wback, fixedaddress);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
FMUL_D(v1, v1, v2);
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 2:
@@ -188,6 +190,7 @@ uintptr_t dynarec64_DC(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
FLD_D(v2, wback, fixedaddress);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
FSUB_D(v1, v1, v2);
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 5:
@@ -198,6 +201,7 @@ uintptr_t dynarec64_DC(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
FLD_D(v2, wback, fixedaddress);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
FSUB_D(v1, v2, v1);
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 6:
@@ -208,6 +212,7 @@ uintptr_t dynarec64_DC(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
FLD_D(v2, wback, fixedaddress);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
FDIV_D(v1, v1, v2);
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 7:
+20 -24
View File
@@ -157,35 +157,33 @@ uintptr_t dynarec64_DE(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0);
LD_HU(x2, wback, fixedaddress);
SLLI_D(x2, x2, 48);
SRAI_D(x2, x2, 48);
LD_H(x2, wback, fixedaddress); // sign-extending halfword load
MOVGR2FR_D(v2, x2);
FFINT_D_L(v2, v2);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
FADD_D(v1, v1, v2);
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 1:
INST_NAME("FIMUL ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0);
LD_HU(x2, wback, fixedaddress);
SLLI_D(x2, x2, 48);
SRAI_D(x2, x2, 48);
LD_H(x2, wback, fixedaddress); // sign-extending halfword load
MOVGR2FR_D(v2, x2);
FFINT_D_L(v2, v2);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
FMUL_D(v1, v1, v2);
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 2:
INST_NAME("FICOM ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0);
LD_HU(x2, wback, fixedaddress);
SLLI_D(x2, x2, 48);
SRAI_D(x2, x2, 48);
LD_H(x2, wback, fixedaddress); // sign-extending halfword load
MOVGR2FR_D(v2, x2);
FFINT_D_L(v2, v2);
FCOMD(v1, v2, x1, x2, x3);
@@ -195,9 +193,7 @@ uintptr_t dynarec64_DE(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0);
LD_HU(x2, wback, fixedaddress);
SLLI_D(x2, x2, 48);
SRAI_D(x2, x2, 48);
LD_H(x2, wback, fixedaddress); // sign-extending halfword load
MOVGR2FR_D(v2, x2);
FFINT_D_L(v2, v2);
FCOMD(v1, v2, x1, x2, x3);
@@ -208,52 +204,52 @@ uintptr_t dynarec64_DE(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0);
LD_HU(x2, wback, fixedaddress);
SLLI_D(x2, x2, 48);
SRAI_D(x2, x2, 48);
LD_H(x2, wback, fixedaddress); // sign-extending halfword load
MOVGR2FR_D(v2, x2);
FFINT_D_L(v2, v2);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
FSUB_D(v1, v1, v2);
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 5:
INST_NAME("FISUBR ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0);
LD_HU(x2, wback, fixedaddress);
SLLI_D(x2, x2, 48);
SRAI_D(x2, x2, 48);
LD_H(x2, wback, fixedaddress); // sign-extending halfword load
MOVGR2FR_D(v2, x2);
FFINT_D_L(v2, v2);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
FSUB_D(v1, v2, v1);
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 6:
INST_NAME("FIDIV ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0);
LD_HU(x2, wback, fixedaddress);
SLLI_D(x2, x2, 48);
SRAI_D(x2, x2, 48);
LD_H(x2, wback, fixedaddress); // sign-extending halfword load
MOVGR2FR_D(v2, x2);
FFINT_D_L(v2, v2);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
FDIV_D(v1, v1, v2);
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 7:
INST_NAME("FIDIVR ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0);
LD_HU(x2, wback, fixedaddress);
SLLI_D(x2, x2, 48);
SRAI_D(x2, x2, 48);
LD_H(x2, wback, fixedaddress); // sign-extending halfword load
MOVGR2FR_D(v2, x2);
FFINT_D_L(v2, v2);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
FDIV_D(v1, v2, v1);
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
}
return addr;
+5 -10
View File
@@ -105,7 +105,7 @@ void emit_xor8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s3, int s
}
// emit XOR16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_xor16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
void emit_xor16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX (X_PEND) {
SET_DF(s4, d_xor16);
@@ -114,15 +114,10 @@ void emit_xor16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
}
IFXA (X_ALL, cpuext.lbt) X64_XOR_W(s1, s2);
IFXA (X_ALL, cpuext.lbt) X64_XOR_H(s1, s2);
XOR(s1, s1, s2);
BSTRINS_D(s1, s1, 15, 0);
IFXA (X_SF, BOX64DRENV(dynarec_safeflags)) {
SRLI_D(s3, s1, 15 - F_SF);
X64_SET_EFLAGS(s3, X_SF);
}
BSTRPICK_D(s1, s1, 15, 0);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, res));
@@ -325,7 +320,7 @@ void emit_and8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s3, int s
ANDI(s1, s1, c&0xff);
IFX(X_PEND) {
ST_D(s1, xEmu, offsetof(x64emu_t, res));
ST_B(s1, xEmu, offsetof(x64emu_t, res));
}
if (cpuext.lbt) {
@@ -500,7 +495,7 @@ void emit_or16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
OR(s1, s1, s2);
BSTRPICK_D(s1, s1, 15, 0);
IFX (X_PEND) {
ST_D(s1, xEmu, offsetof(x64emu_t, res));
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}
if (cpuext.lbt) {
+2 -2
View File
@@ -1071,7 +1071,7 @@ void emit_adc8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
CLEAR_FLAGS(s3);
IFX (X_PEND) {
// d_adc8 will use 16bits result to check for CF
// d_adc8b recovers CF from op1/op2/res, so an 8bits result is enough
ST_B(s1, xEmu, offsetof(x64emu_t, res));
}
IFX (X_AF | X_OF) {
@@ -1156,7 +1156,7 @@ void emit_adc16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
CLEAR_FLAGS(s3);
IFX (X_PEND) {
// d_adc16 will use 32bits result to check for CF
// d_adc16b recovers CF from op1/op2/res, so a 16bits result is enough
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}
IFX (X_AF | X_OF) {
+2 -11
View File
@@ -65,12 +65,10 @@ void emit_shl16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
}
SLL_D(s1, s1, s2);
IFX (X_CF | X_OF) {
IFX (X_CF) {
SRLI_D(s5, s1, 16);
ANDI(s5, s5, 1); // LSB == F_CF
IFX (X_CF) {
OR(xFlags, xFlags, s5);
}
OR(xFlags, xFlags, s5);
}
SLLI_D(s1, s1, 48);
@@ -478,7 +476,6 @@ void emit_shr8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
// emit SAR8 instruction, from s1 , shift s2 (!0 and and'd already), store result in s1 using s3, s4 and s5 as scratch
void emit_sar8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
int64_t j64;
IFX (X_PEND) {
ST_B(s2, xEmu, offsetof(x64emu_t, op2));
ST_B(s1, xEmu, offsetof(x64emu_t, op1));
@@ -673,7 +670,6 @@ void emit_sar8c(dynarec_la64_t* dyn, int ninst, int s1, uint32_t c, int s3, int
// emit SHR16 instruction, from s1 , shift s2 (!0 and and'd already), store result in s1 using s3 and s4 as scratch
void emit_shr16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
int64_t j64;
IFX (X_PEND) {
ST_H(s2, xEmu, offsetof(x64emu_t, op2));
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
@@ -804,7 +800,6 @@ void emit_shr16c(dynarec_la64_t* dyn, int ninst, int s1, uint32_t c, int s3, int
// emit SHR32 instruction, from s1 , shift s2 (!0 and and'd already), store result in s1 using s3 and s4 as scratch
void emit_shr32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
int64_t j64;
IFX (X_PEND) {
SDxw(s2, xEmu, offsetof(x64emu_t, op2));
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
@@ -957,7 +952,6 @@ void emit_shr32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
// emit SAR16 instruction, from s1, shift s2 (!0 and and'd already), store result in s1 using s3, s4 and s5 as scratch
void emit_sar16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
int64_t j64;
IFX (X_PEND) {
ST_H(s2, xEmu, offsetof(x64emu_t, op2));
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
@@ -1315,7 +1309,6 @@ void emit_rol8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// emit ROL8 instruction, from s1, c, store result in s1 using s3 s4 and s5 as scratch
void emit_rol8c(dynarec_la64_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4, int s5)
{
int64_t j64;
if (!c) return;
if (cpuext.lbt) {
IFX (X_CF | X_OF) X64_ROTLI_B(s1, c);
@@ -1650,7 +1643,6 @@ void emit_shrd32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, uin
void emit_shrd32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s5, int s3, int s4, int s6)
{
int64_t j64;
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SDxw(s5, xEmu, offsetof(x64emu_t, op2));
@@ -1699,7 +1691,6 @@ void emit_shrd32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int
void emit_shld32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s5, int s3, int s4, int s6)
{
int64_t j64;
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SDxw(s5, xEmu, offsetof(x64emu_t, op2));
+4 -2
View File
@@ -475,7 +475,7 @@ void emit_test8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
AND(s3, s1, s2); // res = s1 & s2
IFX_PENDOR0 {
ST_D(s3, xEmu, offsetof(x64emu_t, res));
ST_B(s3, xEmu, offsetof(x64emu_t, res));
}
IFX(X_SF) {
SRLI_D(s4, s3, 7);
@@ -505,6 +505,7 @@ void emit_test8c(dynarec_la64_t* dyn, int ninst, int s1, uint8_t c, int s3, int
}
NAT_FLAGS_ENABLE_SIGN();
NAT_FLAGS_ENABLE_SF();
if (cpuext.lbt) {
IFX (X_ALL) {
@@ -531,7 +532,7 @@ void emit_test8c(dynarec_la64_t* dyn, int ninst, int s1, uint8_t c, int s3, int
ANDI(s3, s1, c); // res = s1 & c
IFX_PENDOR0 {
ST_D(s3, xEmu, offsetof(x64emu_t, res));
ST_B(s3, xEmu, offsetof(x64emu_t, res));
}
IFX (X_SF) {
SRLI_D(s4, s3, 7);
@@ -715,6 +716,7 @@ void emit_test32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c,
}
NAT_FLAGS_ENABLE_SIGN();
NAT_FLAGS_ENABLE_SF();
if (cpuext.lbt) {
IFX(X_ALL) {
MOV64xw(s3, c);
+5 -7
View File
@@ -187,6 +187,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
nextop = F8;
switch (nextop) {
case 0xAB:
nextop = F8;
if (MODREG) {
INST_NAME("Invalid LOCK BTS");
UDF();
@@ -196,7 +197,6 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
INST_NAME("LOCK BTS Ed, Gd");
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
nextop = F8;
GETGDs;
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
if (rex.w) {
@@ -204,7 +204,6 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
SRAI_W(x1, gd, 3);
}
if (!rex.w && !rex.is32bits) { ADDI_W(x1, x1, 0); }
ADDy(x6, wback, x1);
ANDI(x2, gd, 7);
ANDI(x4, x6, 0b11);
@@ -227,6 +226,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0xB0:
switch (rex.rep) {
case 0:
nextop = F8;
if (MODREG) {
INST_NAME("Invalid LOCK");
UDF();
@@ -235,7 +235,6 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
INST_NAME("LOCK CMPXCHG Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION);
nextop = F8;
ANDI(x6, xRAX, 0xff); // AL
if (rex.rex) {
gb1 = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3));
@@ -330,6 +329,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
break;
case 0xB3:
nextop = F8;
if (MODREG) {
INST_NAME("Invalid LOCK BTR");
UDF();
@@ -339,7 +339,6 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
INST_NAME("LOCK BTR Ed, Gd");
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
nextop = F8;
GETGDs;
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
if (rex.w) {
@@ -347,7 +346,6 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
SRAI_W(x1, gd, 3);
}
if (!rex.w && !rex.is32bits) { ADDI_W(x1, x1, 0); }
ADDy(x6, wback, x1);
ANDI(x2, gd, 7);
@@ -388,7 +386,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
INST_NAME("LOCK BTS Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, LOCK_LOCK, 0, 1);
u8 = F8;
u8 &= (rex.w ? 0x3f : 0x1f);
ADDI_D(x6, wback, u8 >> 3);
@@ -420,7 +418,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
INST_NAME("LOCK BTR Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, LOCK_LOCK, 0, 1);
u8 = F8;
u8 &= (rex.w ? 0x3f : 0x1f);
ADDI_D(x6, wback, u8 >> 3);
+1 -1
View File
@@ -71,7 +71,7 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if (MODREG) {
ed = (nextop & 7) + (rex.b << 3);
d0 = sse_get_reg(dyn, ninst, x1, ed, 0);
d0 = sse_get_reg(dyn, ninst, x1, ed, 1);
xmm_live_read(dyn, ninst, gd, XMM_WIDTH_64);
xmm_scalar_move(dyn, ninst, d0, v0, ed, XMM_SCALAR_SD, XMM_UPPER_PRESERVE);
} else {
+4 -5
View File
@@ -147,8 +147,6 @@ uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
break;
case 0x2D:
INST_NAME("CVTSS2SI Gd, Ex");
if (addr >= 0x1033f98d && addr <= 0x1033f98d + 8)
EMIT(0);
nextop = F8;
GETGDd;
GETEXSS(d0, 0, 0);
@@ -252,14 +250,15 @@ uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, tmp2, tmp3, &fixedaddress, rex, NULL, 1, 0); \
if (dyn->insts[ninst].nat_flags_fusion) { \
NATIVEJUMP(NATNO, 8); \
NATIVEJUMP(NATNO, 4); \
} else { \
if (cpuext.lbt) \
BEQZ(tmp1, 8); \
BEQZ(tmp1, 4); \
else \
B##NO(tmp1, 8); \
B##NO(tmp1, 4); \
} \
LDxw(gd, ed, fixedaddress); \
if (NEED_ZEROUP(gd)) ZEROUP(gd); \
}
GOCOND(0x40, "CMOV", "Gd, Ed");
+30 -32
View File
@@ -53,8 +53,12 @@ void fpu_reset_scratch(dynarec_la64_t* dyn)
int fpu_get_reg_x87(dynarec_la64_t* dyn, int t, int n)
{
int i = X870;
while (dyn->lsx.fpuused[i])
while (i < 24 && dyn->lsx.fpuused[i])
++i;
if (i >= 24) {
dyn->abort = 1;
i = 23;
}
dyn->lsx.fpuused[i] = 1;
dyn->lsx.lsxcache[i].n = n;
dyn->lsx.lsxcache[i].t = t;
@@ -184,24 +188,6 @@ int lsxcache_get_st_f_i64(dynarec_la64_t* dyn, int ninst, int a)
return -1;
}
int lsxcache_get_st_f_noback(dynarec_la64_t* dyn, int ninst, int a)
{
for (int i = 0; i < 24; ++i)
if (dyn->insts[ninst].lsx.lsxcache[i].t == LSX_CACHE_ST_F
&& dyn->insts[ninst].lsx.lsxcache[i].n == a)
return i;
return -1;
}
int lsxcache_get_st_f_i64_noback(dynarec_la64_t* dyn, int ninst, int a)
{
for (int i = 0; i < 24; ++i)
if ((dyn->insts[ninst].lsx.lsxcache[i].t == LSX_CACHE_ST_I64 || dyn->insts[ninst].lsx.lsxcache[i].t == LSX_CACHE_ST_F)
&& dyn->insts[ninst].lsx.lsxcache[i].n == a)
return i;
return -1;
}
int lsxcache_get_current_st_f(dynarec_la64_t* dyn, int a)
{
for (int i = 0; i < 24; ++i)
@@ -229,7 +215,7 @@ static void lsxcache_promote_double_combined(dynarec_la64_t* dyn, int ninst, int
a = dyn->insts[ninst].lsx.combined2;
} else
a = dyn->insts[ninst].lsx.combined1;
int i = lsxcache_get_st_f_i64_noback(dyn, ninst, a);
int i = lsxcache_get_st_f_i64(dyn, ninst, a);
if (i >= 0) {
dyn->insts[ninst].lsx.lsxcache[i].t = LSX_CACHE_ST_D;
if (dyn->insts[ninst].x87precision) dyn->need_x87check = 2;
@@ -282,7 +268,7 @@ static void lsxcache_promote_double_forward(dynarec_la64_t* dyn, int ninst, int
else if (a == dyn->insts[ninst].lsx.combined2)
a = dyn->insts[ninst].lsx.combined1;
}
int i = lsxcache_get_st_f_i64_noback(dyn, ninst, a);
int i = lsxcache_get_st_f_i64(dyn, ninst, a);
if (i < 0) return;
dyn->insts[ninst].lsx.lsxcache[i].t = LSX_CACHE_ST_D;
if (dyn->insts[ninst].x87precision) dyn->need_x87check = 2;
@@ -705,16 +691,10 @@ static uint32_t insert_byte(uint32_t val, uint8_t b, void* address)
return val;
}
static uint16_t extract_half(uint32_t val, void* address)
{
int idx = (((uintptr_t)address) & 3) * 8;
return (val >> idx) & 0xffff;
}
static uint32_t insert_half(uint32_t val, uint16_t h, void* address)
{
int idx = (((uintptr_t)address) & 3) * 8;
val &= ~(0xffff << idx);
val &= ~((uint32_t)0xffff << idx);
val |= (((uint32_t)h) << idx);
return val;
}
@@ -738,9 +718,27 @@ int la64_lock_cas_b_slow(void* addr, uint8_t ref, uint8_t val)
int la64_lock_cas_h_slow(void* addr, uint16_t ref, uint16_t val)
{
uint32_t* aligned = (uint32_t*)(((uintptr_t)addr) & ~3);
uint32_t tmp = *aligned;
return la64_lock_cas_d(aligned, insert_half(tmp, ref, addr), insert_half(tmp, val, addr));
if ((((uintptr_t)addr) & 7) == 7) {
pthread_mutex_lock(&my_context->mutex_lock);
uint16_t* p = (uint16_t*)addr;
uint16_t old = *p;
if (old == ref)
*p = val;
pthread_mutex_unlock(&my_context->mutex_lock);
return old != ref;
}
if ((((uintptr_t)addr) & 3) != 3) {
uint32_t* aligned = (uint32_t*)(((uintptr_t)addr) & ~3);
uint32_t tmp = *aligned;
return la64_lock_cas_d(aligned, insert_half(tmp, ref, addr), insert_half(tmp, val, addr));
}
uint64_t* aligned = (uint64_t*)(((uintptr_t)addr) & ~7ULL);
int idx = (((uintptr_t)addr) & 7) * 8; // 24 here
uint64_t mask = ~((uint64_t)0xffff << idx);
uint64_t old = *aligned;
uint64_t ref64 = (old & mask) | (((uint64_t)ref) << idx);
uint64_t val64 = (old & mask) | (((uint64_t)val) << idx);
return la64_lock_cas_dd(aligned, ref64, val64);
}
void print_opcode(dynarec_native_t* dyn, int ninst, uint32_t opcode)
@@ -958,7 +956,7 @@ void tryEarlyFpuBarrier(dynarec_la64_t* dyn, int last_fpu_used, int ninst)
usefull = 1;
}
if (usefull) {
if ((BOX64ENV(dynarec_dump) && BOX64ENV(dynarec_dump) != 3) || BOX64ENV(dynarec_log) > 1) dynarec_log(LOG_NONE, "Putting early Float Barrier in %d for %d\n", last_fpu_used, ninst);
if ((BOX64ENV(dynarec_dump) && BOX64ENV(dynarec_dump) != 3) || BOX64ENV(dynarec_log) > 1) dynarec_log(LOG_NONE, "Putting early Float Barrier in %d for %d\n", last_fpu_used + 1, ninst);
dyn->insts[last_fpu_used + 1].x64.barrier |= BARRIER_FLOAT;
}
}
+21 -16
View File
@@ -812,6 +812,11 @@ void x87_reget_st(dynarec_la64_t* dyn, int ninst, int s1, int s2, int st)
for (int i = 0; (i < 8) && (ret == -1); ++i)
if (dyn->lsx.x87cache[i] == -1)
ret = i;
if (ret == -1) {
MESSAGE(LOG_DUMP, "Incoherent x87 stack cache, aborting\n");
dyn->abort = 1;
return;
}
// found, setup and grab the value
dyn->lsx.x87cache[ret] = st;
dyn->lsx.x87reg[ret] = fpu_get_reg_x87(dyn, LSX_CACHE_ST_D, st);
@@ -863,15 +868,6 @@ void x87_free(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int st)
dyn->lsx.lsxcache[reg].v = 0;
dyn->lsx.x87cache[ret] = -1;
dyn->lsx.x87reg[ret] = -1;
} else {
// Get top
LD_W(s2, xEmu, offsetof(x64emu_t, top));
// Update
int ast = st - dyn->lsx.x87stack;
if (ast) {
ADDI_D(s2, s2, ast);
ANDI(s2, s2, 7); // (emu->top + i)&7
}
}
// add mark in the freed array
dyn->lsx.tags |= 0b11 << (st * 2);
@@ -1083,7 +1079,8 @@ void x87_purgecache(dynarec_la64_t* dyn, int ninst, int next, int s1, int s2, in
if (a > 0) {
SLLI_D(s1, s1, a * 2);
} else {
BSTRINS_D(s1, xZR, 15, 0);
MOV32w(s3, 0xffff0000);
OR(s1, s1, s3);
SRLI_D(s1, s1, -a * 2);
}
ST_H(s1, xEmu, offsetof(x64emu_t, fpu_tags));
@@ -1284,6 +1281,11 @@ int x87_get_cache(dynarec_la64_t* dyn, int ninst, int populate, int s1, int s2,
for (int i = 0; (i < 8) && (ret == -1); ++i)
if (dyn->lsx.x87cache[i] == -1)
ret = i;
if (ret == -1) {
MESSAGE(LOG_DUMP, "Incoherent x87 stack cache, aborting\n");
dyn->abort = 1;
return -1;
}
// found, setup and grab the value
dyn->lsx.x87cache[ret] = st;
dyn->lsx.x87reg[ret] = fpu_get_reg_x87(dyn, LSX_CACHE_ST_D, st);
@@ -1473,7 +1475,7 @@ void sse_purge07cache(dynarec_la64_t* dyn, int ninst, int s1)
++old;
}
dyn->lsx.xmm_used |= 1 << i;
if (dyn->lsx.lsxcache[dyn->lsx.avxcache[i].reg].t == LSX_CACHE_YMMW) {
if (dyn->lsx.avxcache[i].v != -1 && dyn->lsx.lsxcache[dyn->lsx.avxcache[i].reg].t == LSX_CACHE_YMMW) {
VST(dyn->lsx.avxcache[i].reg, xEmu, offsetof(x64emu_t, xmm[i]));
if (dyn->lsx.avxcache[i].upper_zero_pending) {
VST(VZERO, xEmu, offsetof(x64emu_t, ymm[i]));
@@ -1483,7 +1485,7 @@ void sse_purge07cache(dynarec_la64_t* dyn, int ninst, int s1)
}
fpu_free_reg(dyn, dyn->lsx.avxcache[i].reg);
dyn->lsx.avxcache[i].v = -1;
} else if (dyn->lsx.lsxcache[dyn->lsx.ssecache[i].reg].t == LSX_CACHE_XMMW) {
} else if (dyn->lsx.ssecache[i].v != -1 && dyn->lsx.lsxcache[dyn->lsx.ssecache[i].reg].t == LSX_CACHE_XMMW) {
VST(dyn->lsx.ssecache[i].reg, xEmu, offsetof(x64emu_t, xmm[i]));
fpu_free_reg(dyn, dyn->lsx.ssecache[i].reg);
dyn->lsx.ssecache[i].v = -1;
@@ -1975,8 +1977,7 @@ static void swapCache(dynarec_la64_t* dyn, int ninst, int i, int j, lsxcache_t*
// SWAP
lsx_cache_t tmp;
MESSAGE(LOG_DUMP, "\t - Swapping %d <-> %d\n", i, j);
// There is no VSWP in Arm64 NEON to swap 2 register contents!
// so use a scratch...
// LSX/LASX has no register-swap instruction, so use a scratch...
switch (quad) {
case 2:
XVOR_V(SCRATCH, i, i);
@@ -2015,8 +2016,12 @@ static void loadCache(dynarec_la64_t* dyn, int ninst, int stack_cnt, int s1, int
if (cache->lsxcache[i].t == LSX_CACHE_YMMR || cache->lsxcache[i].t == LSX_CACHE_YMMW)
quad = 2;
int j = i + 1;
while (cache->lsxcache[j].v)
while (j < 24 && cache->lsxcache[j].v)
++j;
if (j >= 24) {
dyn->abort = 1;
j = 23;
}
MESSAGE(LOG_DUMP, "\t - Moving away %d\n", i);
switch (quad) {
case 2:
@@ -2236,7 +2241,7 @@ static void fpuCacheTransform(dynarec_la64_t* dyn, int ninst, int s1, int s2, in
} else if (cache.lsxcache[i].t == LSX_CACHE_ST_F && cache_i2.lsxcache[i].t == LSX_CACHE_ST_I64) {
MESSAGE(LOG_DUMP, "\t - Convert %s\n", getCacheName(cache.lsxcache[i].t, cache.lsxcache[i].n));
VFTINTRZL_L_S(i, i);
cache.lsxcache[i].t = LSX_CACHE_ST_D;
cache.lsxcache[i].t = LSX_CACHE_ST_I64;
} else if (cache.lsxcache[i].t == LSX_CACHE_ST_I64 && cache_i2.lsxcache[i].t == LSX_CACHE_ST_F) {
MESSAGE(LOG_DUMP, "\t - Convert %s\n", getCacheName(cache.lsxcache[i].t, cache.lsxcache[i].n));
VFFINT_S_L(i, i, i);
+61 -9
View File
@@ -316,7 +316,8 @@ static inline int comis_fuse_inverted(int condition)
#define COMIS_SPILL_S() \
IFX (X_ALL) { SPILL_EFLAGS(); }
#define COMIS_SPILL_D() SPILL_EFLAGS()
#define COMIS_SPILL_D() \
IFX (X_ALL) { SPILL_EFLAGS(); }
#define EMIT_COMIS_FLAGS(type, lhs, rhs, tmp) \
do { \
COMIS_MARK(); \
@@ -421,13 +422,13 @@ static inline int comis_fuse_inverted(int condition)
#define GETVDs \
do { \
vd = TO_NAT(vex.v); \
if (rex.w) MARKREGs(vd); \
MARKREGs(vd); \
} while(0)
#define GETVDsd \
do { \
vd = TO_NAT(vex.v); \
if (rex.w) MARKREGsd(vd); \
MARKREGsd(vd); \
} while(0)
// GETGW extract x64 register in gd, that is i
@@ -731,6 +732,16 @@ static inline int comis_fuse_inverted(int condition)
VLD(a, ed, fixedaddress); \
}
#define GETEX_AES(a, w, D) \
if (MODREG) { \
a = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), w); \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 1, D); \
VLD(SCRATCH, ed, fixedaddress); \
a = SCRATCH; \
}
// Put Back EX if it was a memory and not an emm register
#define PUTEX(a) \
if (!MODREG) { \
@@ -861,6 +872,35 @@ static inline int comis_fuse_inverted(int condition)
VLD(a, ed, fixedaddress); \
}
#define GETEYx_AES(a, w, D) \
if (MODREG) { \
a = avx_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), w, LSX_AVX_WIDTH_128); \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, D); \
VLD(SCRATCH, ed, fixedaddress); \
a = SCRATCH; \
}
#define GETEYy_AES(a, w, D) \
if (MODREG) { \
a = avx_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), w, LSX_AVX_WIDTH_256); \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, D); \
XVLD(SCRATCH, ed, fixedaddress); \
a = SCRATCH; \
}
#define GETEYxy_AES(a, w, D) \
if (vex.l) { \
GETEYy_AES(a, w, D); \
} else { \
GETEYx_AES(a, w, D); \
}
#define GETGY_empty_VYEYxy_AES(gx, vx, ex, D) \
GETVYxy(vx, 0); \
GETEYxy_AES(ex, 0, D); \
GETGYxy_empty(gx);
#define GETEYy(a, w, D) \
if (MODREG) { \
a = avx_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), w, LSX_AVX_WIDTH_256); \
@@ -1102,6 +1142,10 @@ static inline int comis_fuse_inverted(int condition)
#define BEQ_MARK2(reg1, reg2) Bxx_gen(EQ, MARK2, reg1, reg2)
// Branch to MARK3 if reg1==reg2 (use j64)
#define BEQ_MARK3(reg1, reg2) Bxx_gen(EQ, MARK3, reg1, reg2)
// Branch to MARKF if reg1==reg2 (use j64)
#define BEQ_MARKF(reg1, reg2) Bxx_gen(EQ, MARKF, reg1, reg2)
// Branch to MARKF2 if reg1==reg2 (use j64)
#define BEQ_MARKF2(reg1, reg2) Bxx_gen(EQ, MARKF2, reg1, reg2)
// Branch to MARKLOCK if reg1==reg2 (use j64)
#define BEQ_MARKLOCK(reg1, reg2) Bxx_gen(EQ, MARKLOCK, reg1, reg2)
// Branch to MARKLOCK2 if reg1==reg2 (use j64)
@@ -1127,6 +1171,14 @@ static inline int comis_fuse_inverted(int condition)
#define BNEZ_MARKLOCK(reg) BxxZ_gen(NE, MARKLOCK, reg)
// Branch to MARKLOCK2 if reg1!=0 (use j64)
#define BNEZ_MARKLOCK2(reg) BxxZ_gen(NE, MARKLOCK2, reg)
// Branch to MARKF if reg1!=reg2 (use j64)
#define BNE_MARKF(reg1, reg2) Bxx_gen(NE, MARKF, reg1, reg2)
// Branch to MARKF2 if reg1!=reg2 (use j64)
#define BNE_MARKF2(reg1, reg2) Bxx_gen(NE, MARKF2, reg1, reg2)
// Branch to MARKF if reg1!=0 (use j64)
#define BNEZ_MARKF(reg) BxxZ_gen(NE, MARKF, reg)
// Branch to MARKF2 if reg1!=0 (use j64)
#define BNEZ_MARKF2(reg) BxxZ_gen(NE, MARKF2, reg)
// Branch to MARK if fcc!=0 (use j64)
#define BCNEZ_MARK(fcc) BCxxZ_gen(NE, MARK, fcc)
@@ -1135,9 +1187,9 @@ static inline int comis_fuse_inverted(int condition)
// Branch to MARK3 if fcc!=0 (use j64)
#define BCNEZ_MARK3(fcc) BCxxZ_gen(NE, MARK3, fcc)
// Branch to MARKLOCK if fcc!=0 (use j64)
#define BCNEZ_MARKLOCK(fcc) BxxZ_gen(NE, MARKLOCK, fcc)
#define BCNEZ_MARKLOCK(fcc) BCxxZ_gen(NE, MARKLOCK, fcc)
// Branch to MARKLOCK2 if fcc!=0 (use j64)
#define BCNEZ_MARKLOCK2(fcc) BxxZ_gen(NE, MARKLOCK2, fcc)
#define BCNEZ_MARKLOCK2(fcc) BCxxZ_gen(NE, MARKLOCK2, fcc)
// Branch to MARK if fcc==0 (use j64)
#define BCEQZ_MARK(fcc) BCxxZ_gen(EQ, MARK, fcc)
@@ -1146,9 +1198,9 @@ static inline int comis_fuse_inverted(int condition)
// Branch to MARK3 if fcc==0 (use j64)
#define BCEQZ_MARK3(fcc) BCxxZ_gen(EQ, MARK3, fcc)
// Branch to MARKLOCK if fcc==0 (use j64)
#define BCEQZ_MARKLOCK(fcc) BxxZ_gen(EQ, MARKLOCK, fcc)
#define BCEQZ_MARKLOCK(fcc) BCxxZ_gen(EQ, MARKLOCK, fcc)
// Branch to MARKLOCK2 if fcc==0 (use j64)
#define BCEQZ_MARKLOCK2(fcc) BxxZ_gen(EQ, MARKLOCK2, fcc)
#define BCEQZ_MARKLOCK2(fcc) BCxxZ_gen(EQ, MARKLOCK2, fcc)
// Branch to MARK if reg1<reg2 (use j64)
#define BLT_MARK(reg1, reg2) Bxx_gen(LT, MARK, reg1, reg2)
@@ -1876,7 +1928,7 @@ void emit_test32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int
void emit_test32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5);
void emit_test8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
void emit_test8c(dynarec_la64_t* dyn, int ninst, int s1, uint8_t c, int s3, int s4, int s5);
void emit_xor16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
void emit_xor16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_xor32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
void emit_xor32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4);
void emit_xor8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4);
@@ -2338,8 +2390,8 @@ uintptr_t dynarec64_DF(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
#define LOCK_8_OP(op, s1, wback, s3, s4, s5, s6) \
if (cpuext.lamcas) { \
LD_BU(s5, wback, 0); \
MV(s1, s5); \
MARKLOCK2; \
MV(s1, s5); \
MV(s6, s5); \
op; \
AMCAS_DB_B(s5, s4, wback); \
-1
View File
@@ -10,7 +10,6 @@
#define READFLAGS(A) \
do { \
dyn->insts[ninst].x64.use_flags = A; \
if (dyn->f != status_none_pending) dyn->f = status_none; \
if (!BOX64ENV(dynarec_df) && (A) & X_PEND) dyn->insts[ninst].x64.use_flags = X_ALL; \
dyn->f = status_none; \
} while (0)
+7 -4
View File
@@ -23,8 +23,11 @@
#define INST_NAME(name)
#define NATIVE_RESTORE_X87PC()
#define X87_CHECK_PRECISION(A) \
do { \
if (dyn->need_x87check) \
dyn->need_x87check = 2; \
#define X87_CHECK_PRECISION(A) \
do { \
if (dyn->need_x87check) { \
dyn->insts[ninst].x87precision = 1; \
if (!ST_IS_F(0)) \
dyn->need_x87check = 2; \
} \
} while (0)
+1 -1
View File
@@ -15,7 +15,7 @@
#define MESSAGE(A, ...) \
do { \
if (dyn->need_dump && dyn->need_dump != 3) dynarec_log(LOG_NONE, __VA_ARGS__); \
if (dyn->need_dump && dyn->need_dump != 3) dynarec_log_prefix(0, LOG_NONE, __VA_ARGS__); \
} while (0)
#define NEW_INST \
if (ninst) { \
+4 -4
View File
@@ -115,10 +115,10 @@ typedef struct vector_liveness_s {
typedef struct instruction_la64_s {
instruction_x64_t x64;
uintptr_t address; // (start) address of the arm emitted instruction
uintptr_t address; // (start) address of the native emitted instruction
uintptr_t epilog; // epilog of current instruction (can be start of next, or barrier stuff)
int size; // size of the arm emitted instruction
int size2; // size of the arm emitted instrucion after pass2
int size; // size of the native emitted instruction
int size2; // size of the native emitted instrucion after pass2
int pred_sz; // size of predecessor list
int *pred; // predecessor array
uintptr_t mark[3];
@@ -279,4 +279,4 @@ void CreateJmpNext(void* addr, void* next);
CALL(const_##A, -1, x1, x2); \
LOAD_XEMU_CALL()
#endif //__DYNAREC_ARM_PRIVATE_H_
#endif //__DYNAREC_LA64_PRIVATE_H_
+49 -57
View File
@@ -27,10 +27,10 @@
#define type_1RI20(opc, imm20, rd) ((opc) << 25 | ((imm20) & 0xFFFFF) << 5 | (rd))
#define type_1RI21(opc, imm21, rj) ((opc) << 26 | ((imm21) & 0xFFFF) << 10 | (rj) << 5 | ((imm21) & 0x1F0000) >> 16)
#define type_hint(opc, imm15) ((opc) << 15 | ((imm15) & 0x7FFF))
#define type_I26(opc, imm26) ((opc) << 26 | ((imm26) & 0xFFFF) << 10 | ((imm26 >> 16) & 0x3FF))
#define type_I26(opc, imm26) ((opc) << 26 | ((imm26) & 0xFFFF) << 10 | (((imm26) >> 16) & 0x3FF))
// Made-up formats not found in the spec.
#define type_1RI13(opc, imm13, rd) ((opc) << 18 | ((imm13) & 0x1FFFF) << 5 | (rd))
#define type_1RI13(opc, imm13, rd) ((opc) << 18 | ((imm13) & 0x1FFF) << 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))
@@ -140,15 +140,15 @@
// GR[rd] = {tmp[GRLEN-1:12], 12'b0}
#define PCALAU12I(rd, imm20) EMIT(type_1RI20(0b0001101, imm20, rd))
#define LL_W(rd, rj, imm) EMIT(type_2RI14(0b00100000, imm >> 2, rj, rd))
#define SC_W(rd, rj, imm) EMIT(type_2RI14(0b00100001, imm >> 2, rj, rd))
#define LL_D(rd, rj, imm) EMIT(type_2RI14(0b00100010, imm >> 2, rj, rd))
#define SC_D(rd, rj, imm) EMIT(type_2RI14(0b00100011, imm >> 2, rj, rd))
#define LL_W(rd, rj, imm) EMIT(type_2RI14(0b00100000, (imm) >> 2, rj, rd))
#define SC_W(rd, rj, imm) EMIT(type_2RI14(0b00100001, (imm) >> 2, rj, rd))
#define LL_D(rd, rj, imm) EMIT(type_2RI14(0b00100010, (imm) >> 2, rj, rd))
#define SC_D(rd, rj, imm) EMIT(type_2RI14(0b00100011, (imm) >> 2, rj, rd))
#define SC_Q(rd, rk, rj) EMIT(type_3R(0b00111000010101110, rk, rj, rd))
#define LLxw(rd, rj, imm) EMIT(type_2RI14(0b00100000 | (rex.w ? 0b10 : 0b00), imm >> 2, rj, rd))
#define SCxw(rd, rj, imm) EMIT(type_2RI14(0b00100001 | (rex.w ? 0b10 : 0b00), imm >> 2, rj, rd))
#define LLxw(rd, rj, imm) EMIT(type_2RI14(0b00100000 | (rex.w ? 0b10 : 0b00), (imm) >> 2, rj, rd))
#define SCxw(rd, rj, imm) EMIT(type_2RI14(0b00100001 | (rex.w ? 0b10 : 0b00), (imm) >> 2, rj, rd))
// DBAR hint
#define DBAR(hint) EMIT(type_hint(0b00111000011100100, hint))
@@ -187,7 +187,7 @@
#define NOP() ANDI(xZR, xZR, 0)
#define BREAK() EMIT(0b1010100)
#define BREAK() BRK(0)
// there is no UDF instruction, use AMSWAP_W($r0, $r1, $r0) like gcc
#define UDF() AMSWAP_W(0, 1, 0)
@@ -482,10 +482,10 @@
// if signed(GR[rj]) >= signed(GR[rd]):
// PC = PC + SignExtend({imm16, 2'b0}, GRLEN)
#define BGE(rj, rd, imm18) EMIT(type_2RI16(0b011001, ((imm18) >> 2), rj, rd))
// if unsigned(GR[rj]) == unsigned(GR[rd]):
// if unsigned(GR[rj]) < unsigned(GR[rd]):
// PC = PC + SignExtend({imm16, 2'b0}, GRLEN)
#define BLTU(rj, rd, imm18) EMIT(type_2RI16(0b011010, ((imm18) >> 2), rj, rd))
// if unsigned(GR[rj]) == unsigned(GR[rd]):
// if unsigned(GR[rj]) >= unsigned(GR[rd]):
// PC = PC + SignExtend({imm16, 2'b0}, GRLEN)
#define BGEU(rj, rd, imm18) EMIT(type_2RI16(0b011011, ((imm18) >> 2), rj, rd))
@@ -496,10 +496,10 @@
// PC = PC + SignExtend({imm21, 2'b0}, GRLEN)
#define BNEZ(rj, imm23) EMIT(type_1RI21(0b010001, ((imm23) >> 2), rj))
#define BGT(rj, rd, imm13) BLT(rd, rj, imm13)
#define BLE(rj, rd, imm13) BGE(rd, rj, imm13)
#define BGTU(rj, rd, imm13) BLTU(rd, rj, imm13)
#define BLEU(rj, rd, imm13) BGEU(rd, rj, imm13)
#define BGT(rj, rd, imm18) BLT(rd, rj, imm18)
#define BLE(rj, rd, imm18) BGE(rd, rj, imm18)
#define BGTU(rj, rd, imm18) BLTU(rd, rj, imm18)
#define BLEU(rj, rd, imm18) BGEU(rd, rj, imm18)
#define SEQ(rd, rj, rk) \
do { \
@@ -1307,14 +1307,14 @@ LSX instruction starts with V, LASX instruction starts with XV.
#define VADDA_H(vd, vj, vk) EMIT(type_3R(0b01110000010111001, vk, vj, vd))
#define VADDA_W(vd, vj, vk) EMIT(type_3R(0b01110000010111010, vk, vj, vd))
#define VADDA_D(vd, vj, vk) EMIT(type_3R(0b01110000010111011, vk, vj, vd))
#define VMAXI_B(vd, vj, imm5) EMIT(type_3R(0b01110010100100000, imm5, vj, vd))
#define VMAXI_H(vd, vj, imm5) EMIT(type_3R(0b01110010100100001, imm5, vj, vd))
#define VMAXI_W(vd, vj, imm5) EMIT(type_3R(0b01110010100100010, imm5, vj, vd))
#define VMAXI_D(vd, vj, imm5) EMIT(type_3R(0b01110010100100011, imm5, vj, vd))
#define VMAXI_BU(vd, vj, imm5) EMIT(type_3R(0b01110010100101000, imm5, vj, vd))
#define VMAXI_HU(vd, vj, imm5) EMIT(type_3R(0b01110010100101001, imm5, vj, vd))
#define VMAXI_WU(vd, vj, imm5) EMIT(type_3R(0b01110010100101010, imm5, vj, vd))
#define VMAXI_DU(vd, vj, imm5) EMIT(type_3R(0b01110010100101011, imm5, vj, vd))
#define VMAXI_B(vd, vj, imm5) EMIT(type_2RI5(0b01110010100100000, imm5, vj, vd))
#define VMAXI_H(vd, vj, imm5) EMIT(type_2RI5(0b01110010100100001, imm5, vj, vd))
#define VMAXI_W(vd, vj, imm5) EMIT(type_2RI5(0b01110010100100010, imm5, vj, vd))
#define VMAXI_D(vd, vj, imm5) EMIT(type_2RI5(0b01110010100100011, imm5, vj, vd))
#define VMAXI_BU(vd, vj, imm5) EMIT(type_2RI5(0b01110010100101000, imm5, vj, vd))
#define VMAXI_HU(vd, vj, imm5) EMIT(type_2RI5(0b01110010100101001, imm5, vj, vd))
#define VMAXI_WU(vd, vj, imm5) EMIT(type_2RI5(0b01110010100101010, imm5, vj, vd))
#define VMAXI_DU(vd, vj, imm5) EMIT(type_2RI5(0b01110010100101011, imm5, vj, vd))
#define VMAX_B(vd, vj, vk) EMIT(type_3R(0b01110000011100000, vk, vj, vd))
#define VMAX_H(vd, vj, vk) EMIT(type_3R(0b01110000011100001, vk, vj, vd))
#define VMAX_W(vd, vj, vk) EMIT(type_3R(0b01110000011100010, vk, vj, vd))
@@ -1323,14 +1323,14 @@ LSX instruction starts with V, LASX instruction starts with XV.
#define VMAX_HU(vd, vj, vk) EMIT(type_3R(0b01110000011101001, vk, vj, vd))
#define VMAX_WU(vd, vj, vk) EMIT(type_3R(0b01110000011101010, vk, vj, vd))
#define VMAX_DU(vd, vj, vk) EMIT(type_3R(0b01110000011101011, vk, vj, vd))
#define VMINI_B(vd, vj, imm5) EMIT(type_3R(0b01110010100100100, imm5, vj, vd))
#define VMINI_H(vd, vj, imm5) EMIT(type_3R(0b01110010100100101, imm5, vj, vd))
#define VMINI_W(vd, vj, imm5) EMIT(type_3R(0b01110010100100110, imm5, vj, vd))
#define VMINI_D(vd, vj, imm5) EMIT(type_3R(0b01110010100100111, imm5, vj, vd))
#define VMINI_BU(vd, vj, imm5) EMIT(type_3R(0b01110010100101100, imm5, vj, vd))
#define VMINI_HU(vd, vj, imm5) EMIT(type_3R(0b01110010100101101, imm5, vj, vd))
#define VMINI_WU(vd, vj, imm5) EMIT(type_3R(0b01110010100101110, imm5, vj, vd))
#define VMINI_DU(vd, vj, imm5) EMIT(type_3R(0b01110010100101111, imm5, vj, vd))
#define VMINI_B(vd, vj, imm5) EMIT(type_2RI5(0b01110010100100100, imm5, vj, vd))
#define VMINI_H(vd, vj, imm5) EMIT(type_2RI5(0b01110010100100101, imm5, vj, vd))
#define VMINI_W(vd, vj, imm5) EMIT(type_2RI5(0b01110010100100110, imm5, vj, vd))
#define VMINI_D(vd, vj, imm5) EMIT(type_2RI5(0b01110010100100111, imm5, vj, vd))
#define VMINI_BU(vd, vj, imm5) EMIT(type_2RI5(0b01110010100101100, imm5, vj, vd))
#define VMINI_HU(vd, vj, imm5) EMIT(type_2RI5(0b01110010100101101, imm5, vj, vd))
#define VMINI_WU(vd, vj, imm5) EMIT(type_2RI5(0b01110010100101110, imm5, vj, vd))
#define VMINI_DU(vd, vj, imm5) EMIT(type_2RI5(0b01110010100101111, imm5, vj, vd))
#define VMIN_B(vd, vj, vk) EMIT(type_3R(0b01110000011100100, vk, vj, vd))
#define VMIN_H(vd, vj, vk) EMIT(type_3R(0b01110000011100101, vk, vj, vd))
#define VMIN_W(vd, vj, vk) EMIT(type_3R(0b01110000011100110, vk, vj, vd))
@@ -1723,14 +1723,14 @@ LSX instruction starts with V, LASX instruction starts with XV.
#define VST(vd, rj, imm12) EMIT(type_2RI12(0b0010110001, imm12, rj, vd))
#define VLDX(vd, rj, rk) EMIT(type_3R(0b00111000010000000, rk, rj, vd))
#define VSTX(vd, rj, rk) EMIT(type_3R(0b00111000010001000, rk, rj, vd))
#define VSTELM_D(vd, rj, imm8, imm1) EMIT(type_2RI9(0b0011000100010, (((imm1) << 8) | (imm8)), rj, vd))
#define VSTELM_W(vd, rj, imm8, imm2) EMIT(type_2RI10(0b001100010010, (((imm2) << 8) | (imm8)), rj, vd))
#define VSTELM_H(vd, rj, imm8, imm3) EMIT(type_2RI11(0b00110001010, (((imm3) << 8) | (imm8)), rj, vd))
#define VSTELM_B(vd, rj, imm8, imm4) EMIT(type_2RI12(0b0011000110, (((imm4) << 8) | (imm8)), rj, vd))
#define VLDREPL_D(vd, rj, imm9) EMIT(type_2RI9(0b0011000000010, imm9, rj, vd))
#define VLDREPL_W(vd, rj, imm10) EMIT(type_2RI10(0b001100000010, imm10, rj, vd))
#define VLDREPL_H(vd, rj, imm11) EMIT(type_2RI11(0b00110000010, imm11, rj, vd))
#define VLDREPL_B(vd, rj, imm12) EMIT(type_2RI12(0b0011000010, imm12, rj, vd))
#define VSTELM_D(vd, rj, imm8, imm1) EMIT(type_2RI9(0b0011000100010, (((imm1) << 8) | ((imm8) & 0xFF)), rj, vd))
#define VSTELM_W(vd, rj, imm8, imm2) EMIT(type_2RI10(0b001100010010, (((imm2) << 8) | ((imm8) & 0xFF)), rj, vd))
#define VSTELM_H(vd, rj, imm8, imm3) EMIT(type_2RI11(0b00110001010, (((imm3) << 8) | ((imm8) & 0xFF)), rj, vd))
#define VSTELM_B(vd, rj, imm8, imm4) EMIT(type_2RI12(0b0011000110, (((imm4) << 8) | ((imm8) & 0xFF)), rj, vd))
#define VLDREPL_D(vd, rj, offset) EMIT(type_2RI9(0b0011000000010, ((offset) >> 3), rj, vd))
#define VLDREPL_W(vd, rj, offset) EMIT(type_2RI10(0b001100000010, ((offset) >> 2), rj, vd))
#define VLDREPL_H(vd, rj, offset) EMIT(type_2RI11(0b00110000010, ((offset) >> 1), rj, vd))
#define VLDREPL_B(vd, rj, offset) EMIT(type_2RI12(0b0011000010, offset, rj, vd))
#define VFCMP_S(vd, vj, vk, cond) EMIT(type_4R(0b000011000101, cond, vk, vj, vd))
#define VFCMP_D(vd, vj, vk, cond) EMIT(type_4R(0b000011000110, cond, vk, vj, vd))
#define XVFCMP_S(vd, vj, vk, cond) EMIT(type_4R(0b000011001001, cond, vk, vj, vd))
@@ -2119,16 +2119,6 @@ LSX instruction starts with V, LASX instruction starts with XV.
#define XVFMAXA_D(vd, vj, vk) EMIT(type_3R(0b01110101010000010, vk, vj, vd))
#define XVFMINA_S(vd, vj, vk) EMIT(type_3R(0b01110101010000101, vk, vj, vd))
#define XVFMINA_D(vd, vj, vk) EMIT(type_3R(0b01110101010000110, vk, vj, vd))
#define XVFRINT_S(xd, xj) EMIT(type_2R(0b0111011010011101001101, xj, xd))
#define XVFRINT_D(xd, xj) EMIT(type_2R(0b0111011010011101001110, xj, xd))
#define XVFRINTRM_S(xd, xj) EMIT(type_2R(0b0111011010011101010001, xj, xd))
#define XVFRINTRM_D(xd, xj) EMIT(type_2R(0b0111011010011101010010, xj, xd))
#define XVFRINTRP_S(xd, xj) EMIT(type_2R(0b0111011010011101010101, xj, xd))
#define XVFRINTRP_D(xd, xj) EMIT(type_2R(0b0111011010011101010110, xj, xd))
#define XVFRINTRZ_S(xd, xj) EMIT(type_2R(0b0111011010011101011001, xj, xd))
#define XVFRINTRZ_D(xd, xj) EMIT(type_2R(0b0111011010011101011010, xj, xd))
#define XVFRINTRNE_S(xd, xj) EMIT(type_2R(0b0111011010011101011101, xj, xd))
#define XVFRINTRNE_D(xd, xj) EMIT(type_2R(0b0111011010011101011110, xj, xd))
#define XVFRINTRRD_S(vd, vj, rm) EMIT(type_2RI4(0b011101101001110101, ((rm & 0b11) << 2) | 0b01, vj, vd))
#define XVFRINTRRD_D(vd, vj, rm) EMIT(type_2RI4(0b011101101001110101, ((rm & 0b11) << 2) | 0b10, vj, vd))
#define XVFCVTL_S_H(xd, xj) EMIT(type_2R(0b0111011010011101111010, xj, xd))
@@ -2287,10 +2277,10 @@ LSX instruction starts with V, LASX instruction starts with XV.
#define VSLLWIL_HU_BU(vd, vj, imm3) EMIT(type_2RI3(0b0111001100001100001, imm3, vj, vd))
#define VSLLWIL_WU_HU(vd, vj, imm4) EMIT(type_2RI4(0b011100110000110001, imm4, vj, vd))
#define VSLLWIL_DU_WU(vd, vj, imm5) EMIT(type_2RI5(0b01110011000011001, imm5, vj, vd))
#define VNEG_B(vd, vj) EMIT(type_2R(0b0111011010011100001100, vj, vd))
#define VNEG_H(vd, vj) EMIT(type_2R(0b0111011010011100001101, vj, vd))
#define VNEG_W(vd, vj) EMIT(type_2R(0b0111011010011100001110, vj, vd))
#define VNEG_D(vd, vj) EMIT(type_2R(0b0111011010011100001111, vj, vd))
#define VNEG_B(vd, vj) EMIT(type_2R(0b0111001010011100001100, vj, vd))
#define VNEG_H(vd, vj) EMIT(type_2R(0b0111001010011100001101, vj, vd))
#define VNEG_W(vd, vj) EMIT(type_2R(0b0111001010011100001110, vj, vd))
#define VNEG_D(vd, vj) EMIT(type_2R(0b0111001010011100001111, vj, vd))
#define XVLD(vd, rj, imm12) EMIT(type_2RI12(0b0010110010, imm12, rj, vd))
#define XVST(vd, rj, imm12) EMIT(type_2RI12(0b0010110011, imm12, rj, vd))
@@ -2300,10 +2290,10 @@ LSX instruction starts with V, LASX instruction starts with XV.
#define XVLDREPL_W(xd, rj, offset) EMIT(type_2RI10(0b001100100010, (offset >> 2), rj, xd))
#define XVLDREPL_H(xd, rj, offset) EMIT(type_2RI11(0b00110010010, (offset >> 1), rj, xd))
#define XVLDREPL_B(xd, rj, offset) EMIT(type_2RI12(0b0011001010, offset, rj, xd))
#define XVSTELM_D(xd, rj, offset, imm2) EMIT(type_2RI10(0b001100110001, ((imm2) << 8) | (offset), rj, xd))
#define XVSTELM_W(xd, rj, offset, imm3) EMIT(type_2RI11(0b00110011001, ((imm3) << 8) | (offset), rj, xd))
#define XVSTELM_H(xd, rj, offset, imm4) EMIT(type_2RI12(0b0011001101, ((imm4) << 8) | (offset), rj, xd))
#define XVSTELM_B(xd, rj, offset, imm5) EMIT(type_2RI13(0b001100111, ((imm5) << 8) | (offset), rj, xd))
#define XVSTELM_D(xd, rj, offset, imm2) EMIT(type_2RI10(0b001100110001, ((imm2) << 8) | ((offset) & 0xFF), rj, xd))
#define XVSTELM_W(xd, rj, offset, imm3) EMIT(type_2RI11(0b00110011001, ((imm3) << 8) | ((offset) & 0xFF), rj, xd))
#define XVSTELM_H(xd, rj, offset, imm4) EMIT(type_2RI12(0b0011001101, ((imm4) << 8) | ((offset) & 0xFF), rj, xd))
#define XVSTELM_B(xd, rj, offset, imm5) EMIT(type_2RI13(0b001100111, ((imm5) << 8) | ((offset) & 0xFF), rj, xd))
#define XVHSELI_D(vd, vj, imm5) EMIT(type_2RI5(0b01110110100111111, imm5, vj, vd))
#define XVROTRI_B(vd, vj, imm3) EMIT(type_2RI3(0b0111011010100000001, imm3, vj, vd))
@@ -3710,6 +3700,8 @@ LSX instruction starts with V, LASX instruction starts with XV.
} \
} while (0)
// NOTE: for vex.l (LASX) and imm > 0, this clobbers the scratch register x5 (the
// immediate must be materialised in a GPR); pass a scratch that is dead at the call site.
#define VREPLVEIxy(width, vd, vj, imm) \
do { \
if (vex.l) { \
+2 -5
View File
@@ -30,15 +30,12 @@ extern void* la64_lock_storeifref(void* p, void* val, void* ref);
// Atomically store value to [p] only if [p] is ref. Return old [p] value (so ref or old)
extern void* la64_lock_storeifref2(void* p, void* val, void* ref);
// Atomically store value to [p] only if [p] is ref. Return new [p] value (so val or old)
// Atomically store value to [p] only if [p] is ref. Return old [p] value (so ref or old)
extern uint32_t la64_lock_storeifref_d(void* p, uint32_t val, uint32_t ref);
// Atomically store value to [p] only if [p] is ref. Return new [p] value (so val or old)
// Atomically store value to [p] only if [p] is ref. Return old [p] value (so ref or old)
extern uint32_t la64_lock_storeifref2_d(void* p, uint32_t val, uint32_t ref);
// decrement atomically the byte at [p] (but only if p not 0)
extern void la64_lock_decifnot0b(void* p);
// atomic store (with memory barrier)
extern void la64_lock_storeb(void* p, uint8_t b);
+5 -4
View File
@@ -51,6 +51,7 @@ void* create_updateflags()
printf_log(LOG_NONE, "Error, UpdateFlags case %d is not handled, will crash later\n", i);
ok = 0;
}
if (!ok) return NULL;
updateflags_pass1(&helper, jmp_df);
helper.native_size = 0;
@@ -60,15 +61,15 @@ void* create_updateflags()
size_t sz = sizeof(void*) + native_size + helper.table64size*sizeof(uint64_t) + 4*sizeof(void*) + 0 + 0 + 0 + sizeof(dynablock_t) + 0;
// dynablock_t* block (arm insts) table64 jmpnext code instsize arch callrets dynablock relocs
void* actual_p = (void*)AllocDynarecMap((uintptr_t)&dummy_code, sz, 1);
if (actual_p == NULL) {
dynarec_log(LOG_INFO, "AllocDynarecMap(%zu) failed, canceling UpdateBlock\n", sz);
return NULL;
}
void* p = (void*)(((uintptr_t)actual_p) + sizeof(void*));
void* tablestart = p + native_size;
void* next = tablestart + helper.table64size * sizeof(uint64_t);
void* instsize = next + 4 * sizeof(void*);
void* callrets = instsize;
if (actual_p == NULL) {
dynarec_log(LOG_INFO, "AllocDynarecMap(%zu) failed, canceling UpdateBlock\n", sz);
return NULL;
}
helper.block = p;
dynablock_t* block = (dynablock_t*)(callrets + 0);
+4 -3
View File
@@ -507,7 +507,7 @@ SETMARK(d_xor8);
SETMARK(d_xor16);
LD_HU(x1, xEmu, offsetof(x64emu_t, res));
OR(x2, xZR, xZR);
emit_xor16(dyn, ninst, x1, x2, x3, x4, x5);
emit_xor16(dyn, ninst, x1, x2, x3, x4);
BR(xRA);
SETMARK(d_xor32);
@@ -987,8 +987,6 @@ SETMARK(d_shrd16);
LD_HU(x1, xEmu, offsetof(x64emu_t, res));
LD_HU(x2, xEmu, offsetof(x64emu_t, op1));
LD_HU(x3, xEmu, offsetof(x64emu_t, op2));
BNEZ(x3, 8);
BR(xRA);
ANDI(x4, x3, 0x0f);
ADDI_D(x4, x4, -16);
SUB_D(x4, xZR, x4);
@@ -997,6 +995,9 @@ SETMARK(d_shrd16);
XOR(x4, x4, x5);
BSTRINS_D(xFlags, x4, F_OF, F_OF);
BSTRINS_D(xFlags, xZR, F_AF, F_AF);
BNEZ(x3, 8 + (cpuext.lbt ? 4 : 0));
SPILL_EFLAGS();
BR(xRA);
ADDI_D(x4, x3, -1);
SRL_D(x4, x2, x4);
BSTRINS_D(xFlags, x4, F_CF, F_CF);