mirror of
https://github.com/ptitSeb/box64.git
synced 2026-11-08 17:39:19 -10:00
1 parent
da05e01235
commit
78bf553c62
34 files changed
+452
-344
No files matched your search
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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); \
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
@@ -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) { \
|
||||
|
||||
@@ -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_
|
||||
@@ -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) { \
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user