[LA64_DYNAREC] Added a dedicated vzero register (#3926)

This commit is contained in:
Yang Liu authored and GitHub committed 2026-06-04 18:57:07 +02:00
1 parent 1a2ad946cb
commit dab3fdc351
15 files changed
+135 -147

No files matched your search

+4 -11
View File
@@ -501,8 +501,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
VLDI(v0, 0b0000010000111); // broadcast 0b10000111 as byte
VAND_V(v0, v0, q1);
VMINI_BU(v0, v0, 0x1f);
VXOR_V(v1, v1, v1);
VSHUF_B(q0, v1, q0, v0);
VSHUF_B(q0, VZERO, q0, v0);
break;
case 0x01:
INST_NAME("PHADDW Gm, Em");
@@ -639,27 +638,21 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
v0 = fpu_get_scratch(dyn);
VXOR_V(v0, v0, v0);
VABSD_B(q0, q1, v0);
VABSD_B(q0, q1, VZERO);
break;
case 0x1D:
INST_NAME("PABSW Gm, Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
v0 = fpu_get_scratch(dyn);
VXOR_V(v0, v0, v0);
VABSD_H(q0, q1, v0);
VABSD_H(q0, q1, VZERO);
break;
case 0x1E:
INST_NAME("PABSD Gm, Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
v0 = fpu_get_scratch(dyn);
VXOR_V(v0, v0, v0);
VABSD_W(q0, q1, v0);
VABSD_W(q0, q1, VZERO);
break;
case 0xC8 ... 0xCD:
u8 = nextop;
+8 -18
View File
@@ -369,8 +369,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
VLDI(v0, 0b0000010001111); // broadcast 0b10001111 as byte
VAND_V(v0, v0, q1);
VMINI_BU(v0, v0, 0x1f);
VXOR_V(v1, v1, v1);
VSHUF_B(q0, v1, q0, v0);
VSHUF_B(q0, VZERO, q0, v0);
break;
case 0x01:
INST_NAME("PHADDW Gx, Ex");
@@ -576,18 +575,14 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
nextop = F8;
GETEX(q1, 0, 0);
GETGX_empty(q0);
v0 = fpu_get_scratch(dyn);
VXOR_V(v0, v0, v0);
VABSD_B(q0, q1, v0);
VABSD_B(q0, q1, VZERO);
break;
case 0x1D:
INST_NAME("PABSW Gx, Ex");
nextop = F8;
GETEX(q1, 0, 0);
GETGX_empty(q0);
v0 = fpu_get_scratch(dyn);
VXOR_V(v0, v0, v0);
VABSD_H(q0, q1, v0);
VABSD_H(q0, q1, VZERO);
break;
case 0x1E:
INST_NAME("PABSD Gx, Ex");
@@ -1247,11 +1242,10 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
VEXTRINS_W(q0, q2, VEXTRINS_IMM_4_0(((u8 >> 4) & 3), 0)); // src index is zero when Ex is mem operand
}
uint8_t zmask = u8 & 0xf;
VXOR_V(q2, q2, q2);
if (zmask) {
for (uint8_t i = 0; i < 4; i++) {
if (zmask & (1 << i)) {
VEXTRINS_W(q0, q2, VEXTRINS_IMM_4_0(i, 0));
VEXTRINS_W(q0, VZERO, VEXTRINS_IMM_4_0(i, 0));
}
}
}
@@ -1277,12 +1271,10 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
u8 = F8;
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn);
VFMUL_S(v0, q0, q1);
VXOR_V(v2, v2, v2);
for (int i = 0; i < 4; ++i) {
if (!(u8 & (1 << (4 + i)))) {
VEXTRINS_W(v0, v2, (i << 4));
VEXTRINS_W(v0, VZERO, (i << 4));
}
}
VSHUF4I_W(v1, v0, 0b10110001); // v0[a,b,c,d] v1[b,a,d,c]
@@ -1292,7 +1284,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
VREPLVEI_W(q0, v0, 0);
for (int i = 0; i < 4; ++i) {
if (!(u8 & (1 << i))) {
VEXTRINS_W(q0, v2, (i << 4));
VEXTRINS_W(q0, VZERO, (i << 4));
}
}
break;
@@ -1304,12 +1296,10 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
u8 = F8;
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn);
VFMUL_D(v0, q0, q1);
VXOR_V(v2, v2, v2);
for (int i = 0; i < 2; ++i) {
if (!(u8 & (1 << (4 + i)))) {
VEXTRINS_D(v0, v2, (i << 4));
VEXTRINS_D(v0, VZERO, (i << 4));
}
}
VSHUF4I_W(v1, v0, 0b01001110); // v0[a,b] v1[b,a]
@@ -1317,7 +1307,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
VREPLVEI_D(q0, v0, 0);
for (int i = 0; i < 2; ++i) {
if (!(u8 & (1 << i))) {
VEXTRINS_D(q0, v2, (i << 4));
VEXTRINS_D(q0, VZERO, (i << 4));
}
}
break;
+19 -23
View File
@@ -8,7 +8,6 @@ static inline void la64_subbytes_lsx(dynarec_la64_t* dyn, int ninst, int dst, in
{
(void)dyn;
(void)ninst;
VXOR_V(zero, zero, zero);
VANDI_B(t0, dst, 0x0f);
VSRLI_B(t1, dst, 4);
VLD(tab, x5, 1 * 16);
@@ -42,7 +41,6 @@ static inline void la64_subbytes_lasx(dynarec_la64_t* dyn, int ninst, int dst, i
{
(void)dyn;
(void)ninst;
XVXOR_V(zero, zero, zero);
XVANDI_B(t0, dst, 0x0f);
XVSRLI_B(t1, dst, 4);
XVLD(tab, x5, 1 * 32);
@@ -172,7 +170,7 @@ static inline void la64_aesimc_lasx(dynarec_la64_t* dyn, int ninst, int dst)
static inline void la64_aeselast_lsx(dynarec_la64_t* dyn, int ninst, int dst)
{
int zero = fpu_get_scratch(dyn);
int zero = VZERO;
int t0 = fpu_get_scratch(dyn);
int t1 = fpu_get_scratch(dyn);
int t2 = fpu_get_scratch(dyn);
@@ -187,7 +185,7 @@ static inline void la64_aeselast_lsx(dynarec_la64_t* dyn, int ninst, int dst)
static inline void la64_aeselast_lasx(dynarec_la64_t* dyn, int ninst, int dst)
{
int zero = fpu_get_scratch(dyn);
int zero = VZERO;
int t0 = fpu_get_scratch(dyn);
int t1 = fpu_get_scratch(dyn);
int t2 = fpu_get_scratch(dyn);
@@ -202,43 +200,45 @@ static inline void la64_aeselast_lasx(dynarec_la64_t* dyn, int ninst, int dst)
static inline void la64_aese_lsx(dynarec_la64_t* dyn, int ninst, int dst)
{
int zero = fpu_get_scratch(dyn);
int zero = VZERO;
int t0 = fpu_get_scratch(dyn);
int t1 = fpu_get_scratch(dyn);
int t2 = fpu_get_scratch(dyn);
int t3 = fpu_get_scratch(dyn);
int tab = fpu_get_scratch(dyn);
int tab_hi = fpu_get_scratch(dyn);
TABLE64C(x5, const_la64_vpaes_enc_tables);
la64_subbytes_lsx(dyn, ninst, dst, zero, t0, t1, t2, t3, tab);
VLD(tab, x5, 6 * 16);
VSHUF_B(dst, dst, dst, tab);
VLD(tab, x5, 7 * 16);
VLD(zero, x5, 8 * 16);
la64_mixcolumns_xtime_lsx(dyn, ninst, dst, tab, zero, t0, t1, t2, t3);
VLD(tab_hi, x5, 8 * 16);
la64_mixcolumns_xtime_lsx(dyn, ninst, dst, tab, tab_hi, t0, t1, t2, t3);
}
static inline void la64_aese_lasx(dynarec_la64_t* dyn, int ninst, int dst)
{
int zero = fpu_get_scratch(dyn);
int zero = VZERO;
int t0 = fpu_get_scratch(dyn);
int t1 = fpu_get_scratch(dyn);
int t2 = fpu_get_scratch(dyn);
int t3 = fpu_get_scratch(dyn);
int tab = fpu_get_scratch(dyn);
int tab_hi = fpu_get_scratch(dyn);
TABLE64C(x5, const_la64_vpaes_enc_tables_xv);
la64_subbytes_lasx(dyn, ninst, dst, zero, t0, t1, t2, t3, tab);
XVLD(tab, x5, 6 * 32);
XVSHUF_B(dst, dst, dst, tab);
XVLD(tab, x5, 7 * 32);
XVLD(zero, x5, 8 * 32);
la64_mixcolumns_xtime_lasx(dyn, ninst, dst, tab, zero, t0, t1, t2, t3);
XVLD(tab_hi, x5, 8 * 32);
la64_mixcolumns_xtime_lasx(dyn, ninst, dst, tab, tab_hi, t0, t1, t2, t3);
}
static inline void la64_aesdlast_lsx(dynarec_la64_t* dyn, int ninst, int dst)
{
int zero = fpu_get_scratch(dyn);
int zero = VZERO;
int t0 = fpu_get_scratch(dyn);
int t1 = fpu_get_scratch(dyn);
int t2 = fpu_get_scratch(dyn);
@@ -249,7 +249,6 @@ static inline void la64_aesdlast_lsx(dynarec_la64_t* dyn, int ninst, int dst)
TABLE64C(x5, const_la64_vpaes_dec_tables);
VLD(tab, x5, 6 * 16);
VSHUF_B(dst, dst, dst, tab);
VXOR_V(zero, zero, zero);
VXORI_B(dst, dst, 99);
VANDI_B(t0, dst, 0x0f);
VSRLI_B(t1, dst, 4);
@@ -282,7 +281,7 @@ static inline void la64_aesdlast_lsx(dynarec_la64_t* dyn, int ninst, int dst)
static inline void la64_aesdlast_lasx(dynarec_la64_t* dyn, int ninst, int dst)
{
int zero = fpu_get_scratch(dyn);
int zero = VZERO;
int t0 = fpu_get_scratch(dyn);
int t1 = fpu_get_scratch(dyn);
int t2 = fpu_get_scratch(dyn);
@@ -293,7 +292,6 @@ static inline void la64_aesdlast_lasx(dynarec_la64_t* dyn, int ninst, int dst)
TABLE64C(x5, const_la64_vpaes_dec_tables_xv);
XVLD(tab, x5, 6 * 32);
XVSHUF_B(dst, dst, dst, tab);
XVXOR_V(zero, zero, zero);
XVXORI_B(dst, dst, 99);
XVANDI_B(t0, dst, 0x0f);
XVSRLI_B(t1, dst, 4);
@@ -326,7 +324,7 @@ static inline void la64_aesdlast_lasx(dynarec_la64_t* dyn, int ninst, int dst)
static inline void la64_aesd_lsx(dynarec_la64_t* dyn, int ninst, int dst)
{
int zero = fpu_get_scratch(dyn);
int zero = VZERO;
int t0 = fpu_get_scratch(dyn);
int t1 = fpu_get_scratch(dyn);
int t2 = fpu_get_scratch(dyn);
@@ -337,7 +335,6 @@ static inline void la64_aesd_lsx(dynarec_la64_t* dyn, int ninst, int dst)
TABLE64C(x5, const_la64_vpaes_dec_tables);
VLD(tab, x5, 6 * 16);
VSHUF_B(dst, dst, dst, tab);
VXOR_V(zero, zero, zero);
VXORI_B(dst, dst, 99);
VANDI_B(t0, dst, 0x0f);
VSRLI_B(t1, dst, 4);
@@ -367,13 +364,13 @@ static inline void la64_aesd_lsx(dynarec_la64_t* dyn, int ninst, int dst)
VSHUF_B(t1, zero, tab, t3);
VXOR_V(dst, t0, t1);
VLD(tab, x5, 7 * 16);
VLD(zero, x5, 8 * 16);
la64_invmixcolumns_xtime_lsx(dyn, ninst, dst, tab, zero, t0, t1, t2, t3);
VLD(t4, x5, 8 * 16);
la64_invmixcolumns_xtime_lsx(dyn, ninst, dst, tab, t4, t0, t1, t2, t3);
}
static inline void la64_aesd_lasx(dynarec_la64_t* dyn, int ninst, int dst)
{
int zero = fpu_get_scratch(dyn);
int zero = VZERO;
int t0 = fpu_get_scratch(dyn);
int t1 = fpu_get_scratch(dyn);
int t2 = fpu_get_scratch(dyn);
@@ -384,7 +381,6 @@ static inline void la64_aesd_lasx(dynarec_la64_t* dyn, int ninst, int dst)
TABLE64C(x5, const_la64_vpaes_dec_tables_xv);
XVLD(tab, x5, 6 * 32);
XVSHUF_B(dst, dst, dst, tab);
XVXOR_V(zero, zero, zero);
XVXORI_B(dst, dst, 99);
XVANDI_B(t0, dst, 0x0f);
XVSRLI_B(t1, dst, 4);
@@ -414,13 +410,13 @@ static inline void la64_aesd_lasx(dynarec_la64_t* dyn, int ninst, int dst)
XVSHUF_B(t1, zero, tab, t3);
XVXOR_V(dst, t0, t1);
XVLD(tab, x5, 7 * 32);
XVLD(zero, x5, 8 * 32);
la64_invmixcolumns_xtime_lasx(dyn, ninst, dst, tab, zero, t0, t1, t2, t3);
XVLD(t4, x5, 8 * 32);
la64_invmixcolumns_xtime_lasx(dyn, ninst, dst, tab, t4, t0, t1, t2, t3);
}
static inline void la64_aeskeygenassist_lsx(dynarec_la64_t* dyn, int ninst, int dst, uint8_t imm)
{
int zero = fpu_get_scratch(dyn);
int zero = VZERO;
int t0 = fpu_get_scratch(dyn);
int t1 = fpu_get_scratch(dyn);
int t2 = fpu_get_scratch(dyn);
+2 -4
View File
@@ -506,14 +506,12 @@ uintptr_t dynarec64_AVX_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, in
if (vex.v != 0) {
UDF();
} else {
q2 = fpu_get_scratch(dyn);
XVXOR_V(q2, q2, q2);
for (int i = 0; i < (rex.is32bits ? 8 : 16); ++i) {
if (dyn->lsx.avxcache[i].v != -1) {
q1 = avx_get_reg(dyn, ninst, x1, i, 1, LSX_AVX_WIDTH_256);
XVPERMI_Q(q1, q2, XVPERMI_IMM_4_0(0, 2));
XVPERMI_Q(q1, VZERO, XVPERMI_IMM_4_0(0, 2));
} else {
VST(q2, xEmu, offsetof(x64emu_t, ymm[i]));
VST(VZERO, xEmu, offsetof(x64emu_t, ymm[i]));
}
}
SMWRITE2();
+6 -7
View File
@@ -378,12 +378,11 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
if (BOX64ENV(dynarec_fastround) <= 1) {
u8 = sse_setround(dyn, ninst, x6, x4);
}
d0 = fpu_get_scratch(dyn);
if (vex.l) {
XVXOR_V(d0, d0, d0);
XVFCVT_S_D(v0, d0, v1);
XVFCVT_S_D(v0, VZERO, v1);
XVPERMI_D(v0, v0, 0b11011000);
} else {
d0 = fpu_get_scratch(dyn);
VFCVT_S_D(d0, v1, v1);
XVPICKVE_D(v0, d0, 0);
}
@@ -1177,12 +1176,11 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
nextop = F8;
GETEYxy(v1, 0, 0);
GETGYx_empty(v0);
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
if (vex.l) {
XVXOR_V(d0, d0, d0);
XVFTINTRZ_W_D(d1, d0, v1); // v0 [lo0, lo1, --, --, hi0, hi1, --, -- ]
d1 = fpu_get_scratch(dyn);
XVFTINTRZ_W_D(d1, VZERO, v1); // v0 [lo0, lo1, --, --, hi0, hi1, --, -- ]
if (!BOX64ENV(dynarec_fastround)) {
d0 = fpu_get_scratch(dyn);
q0 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
XVLDI(q0, 0b1001110000000); // broadcast 0x80000000 to all
@@ -1198,6 +1196,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
}
XVPERMI_D(v0, v0, 0b11011000);
} else {
d0 = fpu_get_scratch(dyn);
VFTINTRZ_W_D(d0, v1, v1);
if (!BOX64ENV(dynarec_fastround)) {
q0 = fpu_get_scratch(dyn);
+10 -27
View File
@@ -63,12 +63,10 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
nextop = F8;
GETGY_empty_VYEY_xy(v0, v1, v2, 0);
q0 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
VLDIxy(q0, 0b0000010001111); // broadcast 0b10001111 as byte
VAND_Vxy(q0, q0, v2);
VMINIxy(BU, q0, q0, 0x1f);
VXOR_Vxy(q1, q1, q1);
VSHUF_Bxy(v0, q1, v1, q0);
VSHUF_Bxy(v0, VZERO, v1, q0);
break;
case 0x01:
INST_NAME("VPHADDW Gx, Vx, Ex");
@@ -346,25 +344,19 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
INST_NAME("VPABSB Gx, Ex");
nextop = F8;
GETGY_empty_EY_xy(v0, v1, 0);
q0 = fpu_get_scratch(dyn);
XVXOR_V(q0, q0, q0);
VABSDxy(B, v0, v1, q0);
VABSDxy(B, v0, v1, VZERO);
break;
case 0x1D:
INST_NAME("VPABSW Gx, Ex");
nextop = F8;
GETGY_empty_EY_xy(v0, v1, 0);
q0 = fpu_get_scratch(dyn);
XVXOR_V(q0, q0, q0);
VABSDxy(H, v0, v1, q0);
VABSDxy(H, v0, v1, VZERO);
break;
case 0x1E:
INST_NAME("VPABSD Gx, Ex");
nextop = F8;
GETGY_empty_EY_xy(v0, v1, 0);
q0 = fpu_get_scratch(dyn);
XVXOR_V(q0, q0, q0);
VABSDxy(W, v0, v1, q0);
VABSDxy(W, v0, v1, VZERO);
break;
case 0x20:
INST_NAME("VPMOVSXBW Gx, Ex");
@@ -498,32 +490,26 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
INST_NAME("VMASKMOVPS Gx, Vx, Ex");
nextop = F8;
GETGY_empty_VYEY_xy(v0, v1, v2, 0);
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
if (vex.l) {
XVXOR_V(d0, d0, d0);
XVSLTI_W(d1, v1, 0); // create all-one mask for negetive element.
XVBITSEL_V(v0, d0, v2, d1);
XVBITSEL_V(v0, VZERO, v2, d1);
} else {
VXOR_V(d0, d0, d0);
VSLTI_W(d1, v1, 0); // create all-one mask for negetive element.
VBITSEL_V(v0, d0, v2, d1);
VBITSEL_V(v0, VZERO, v2, d1);
}
break;
case 0x2D:
INST_NAME("VMASKMOVPD Gx, Vx, Ex");
nextop = F8;
GETGY_empty_VYEY_xy(v0, v1, v2, 0);
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
if (vex.l) {
XVXOR_V(d0, d0, d0);
XVSLTI_D(d1, v1, 0); // create all-one mask for negetive element.
XVBITSEL_V(v0, d0, v2, d1);
XVBITSEL_V(v0, VZERO, v2, d1);
} else {
VXOR_V(d0, d0, d0);
VSLTI_D(d1, v1, 0); // create all-one mask for negetive element.
VBITSEL_V(v0, d0, v2, d1);
VBITSEL_V(v0, VZERO, v2, d1);
}
break;
case 0x2E:
@@ -836,24 +822,21 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
INST_NAME("VPMASKMOVD/Q Gx, Vx, Ex");
nextop = F8;
GETGY_empty_VYEY_xy(v0, v1, v2, 0);
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
if (vex.l) {
XVXOR_V(d0, d0, d0);
if (rex.w) {
XVSLTI_D(d1, v1, 0);
} else {
XVSLTI_W(d1, v1, 0);
}
XVBITSEL_V(v0, d0, v2, d1);
XVBITSEL_V(v0, VZERO, v2, d1);
} else {
VXOR_V(d0, d0, d0);
if (rex.w) {
VSLTI_D(d1, v1, 0);
} else {
VSLTI_W(d1, v1, 0);
}
VBITSEL_V(v0, d0, v2, d1);
VBITSEL_V(v0, VZERO, v2, d1);
}
break;
case 0x8E:
+10 -20
View File
@@ -35,7 +35,7 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
int cacheupd = 0;
int v0, v1, v2;
int q0, q1, q2;
int d0, d1, d2;
int d0, d1;
int s0;
uint64_t tmp64u;
int64_t j64;
@@ -147,7 +147,6 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
XVXOR_V(v0, v0, v0);
break;
}
d0 = fpu_get_scratch(dyn);
uint8_t zero_low = (u8 & 0x8) >> 3;
uint8_t zero_up = (u8 & 0x80) >> 7;
uint8_t vec_lo = (u8 & 0x2) >> 1;
@@ -165,13 +164,12 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
}
break;
}
XVXOR_V(d0, d0, d0);
if (zero_low) {
XVORI_B(v0, vec_hi ? v2 : v1, 0);
XVPERMI_Q(v0, d0, XVPERMI_IMM_4_0(2 + index_hi, 0));
XVPERMI_Q(v0, VZERO, XVPERMI_IMM_4_0(2 + index_hi, 0));
} else {
XVORI_B(v0, vec_lo ? v2 : v1, 0);
XVPERMI_Q(v0, d0, XVPERMI_IMM_4_0(0, 2 + index_lo));
XVPERMI_Q(v0, VZERO, XVPERMI_IMM_4_0(0, 2 + index_lo));
}
break;
case 0x08:
@@ -507,7 +505,6 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
GETEYSD(v1, 1, 1);
}
u8 = F8;
d0 = fpu_get_scratch(dyn);
if (u8 & 4) {
u8 = sse_setround(dyn, ninst, x4, x5);
} else {
@@ -517,13 +514,11 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
u8 = x4;
}
if (vex.l) {
XVXOR_V(d0, d0, d0);
XVFCVT_H_S(v1, d0, v0);
XVFCVT_H_S(v1, VZERO, v0);
XVPERMI_D(v1, v1, 0b11011000);
PUTEYx(v1);
} else {
XVXOR_V(d0, d0, d0);
VFCVT_H_S(v1, d0, v0);
VFCVT_H_S(v1, VZERO, v0);
PUTEYSD(v1);
}
x87_restoreround(dyn, ninst, u8);
@@ -573,10 +568,9 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
}
uint8_t zmask = u8 & 0xf;
if (zmask) {
VXOR_V(q1, q1, q1);
for (uint8_t i = 0; i < 4; i++) {
if (zmask & (1 << i)) {
VEXTRINS_W(v0, q1, VEXTRINS_IMM_4_0(i, 0));
VEXTRINS_W(v0, VZERO, VEXTRINS_IMM_4_0(i, 0));
}
}
}
@@ -606,12 +600,10 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
u8 = F8;
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
d2 = fpu_get_scratch(dyn);
VFMULxy(S, d0, v1, v2);
VXOR_Vxy(d2, d2, d2);
for (int i = 0; i < 4; ++i) {
if (!(u8 & (1 << (4 + i)))) {
VEXTRINSxy(W, d0, d2, (i << 4));
VEXTRINSxy(W, d0, VZERO, (i << 4));
}
}
VSHUF4Ixy(W, d1, d0, 0b10110001); // v0[a,b,c,d] v1[b,a,d,c]
@@ -621,7 +613,7 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
VREPLVEIxy(W, v0, d0, 0);
for (int i = 0; i < 4; ++i) {
if (!(u8 & (1 << i))) {
VEXTRINSxy(W, v0, d2, (i << 4));
VEXTRINSxy(W, v0, VZERO, (i << 4));
}
}
break;
@@ -632,12 +624,10 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
u8 = F8;
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
d2 = fpu_get_scratch(dyn);
VFMULxy(D, d0, v1, v2);
VXOR_Vxy(d2, d2, d2);
for (int i = 0; i < 2; ++i) {
if (!(u8 & (1 << (4 + i)))) {
VEXTRINSxy(D, d0, d2, (i << 4));
VEXTRINSxy(D, d0, VZERO, (i << 4));
}
}
VSHUF4Ixy(W, d1, d0, 0b01001110); // v0[a,b] v1[b,a]
@@ -645,7 +635,7 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
VREPLVEIxy(D, v0, d0, 0);
for (int i = 0; i < 2; ++i) {
if (!(u8 & (1 << i))) {
VEXTRINSxy(D, v0, d2, (i << 4));
VEXTRINSxy(D, v0, VZERO, (i << 4));
}
}
break;
+6 -8
View File
@@ -202,9 +202,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
d1 = fpu_get_scratch(dyn);
FSQRT_D(d1, v2);
if (!BOX64ENV(dynarec_fastnan)) {
d0 = fpu_get_scratch(dyn);
VXOR_V(d0, d0, d0);
FCMP_D(fcc0, v2, d0, cLT);
FCMP_D(fcc0, v2, VZERO, cLT);
BCEQZ(fcc0, 4 + 4);
FNEG_D(d1, d1);
}
@@ -438,8 +436,8 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
GETVYx(v1, 0);
GETEYSD(v2, 0, 1);
GETGYx(v0, 1);
q0 = fpu_get_scratch(dyn);
u8 = F8;
q0 = ((u8 & 0xf) == 0x0b) ? VZERO : fpu_get_scratch(dyn);
switch (u8 & 0xf) {
case 0x00: VFCMP_D(q0, v1, v2, cEQ); break; // Equal, not unordered
case 0x01: VFCMP_D(q0, v1, v2, cLT); break; // Less than
@@ -452,7 +450,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
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: VXOR_V(q0, q0, q0); break; // false
case 0x0b: break; // false
case 0x0c: VFCMP_D(q0, v1, v2, cNE); break; // Not Eual, 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
@@ -495,18 +493,17 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
GETEYxy(v1, 0, 0);
GETGYx_empty(v0);
u8 = sse_setround(dyn, ninst, x1, x2);
d0 = fpu_get_scratch(dyn);
if (vex.l) {
if (!BOX64ENV(dynarec_fastround)) {
q0 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
q2 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
XVFTINT_L_D(q2, v1);
XVFCMP_D(d1, v1, v1, cUN); // get NaN mask
}
XVXOR_V(d0, d0, d0);
XVFTINT_W_D(v0, d0, v1); // v0 [lo0, lo1, --, --, hi0, hi1, --, -- ]
XVFTINT_W_D(v0, VZERO, v1); // v0 [lo0, lo1, --, --, hi0, hi1, --, -- ]
if (!BOX64ENV(dynarec_fastround)) {
XVLDI(q0, 0b1001110000000); // broadcast 0x80000000 to all
MOV32w(x5, 0x7FFFFFFF);
@@ -519,6 +516,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
}
XVPERMI_D(v0, v0, 0b11011000);
} else {
d0 = fpu_get_scratch(dyn);
VFTINT_W_D(d0, v1, v1);
if (!BOX64ENV(dynarec_fastround)) {
q0 = fpu_get_scratch(dyn);
+3 -5
View File
@@ -194,9 +194,7 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
d1 = fpu_get_scratch(dyn);
FSQRT_S(d1, v2);
if (!BOX64ENV(dynarec_fastnan)) {
d0 = fpu_get_scratch(dyn);
VXOR_V(d0, d0, d0);
FCMP_S(fcc0, v2, d0, cLT);
FCMP_S(fcc0, v2, VZERO, cLT);
BCEQZ(fcc0, 4 + 4);
FNEG_S(d1, d1);
}
@@ -475,8 +473,8 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
GETVYx(v1, 0);
GETEYSS(v2, 0, 1);
GETGYx(v0, 1);
q0 = fpu_get_scratch(dyn);
u8 = F8;
q0 = ((u8 & 0xf) == 0x0b) ? VZERO : fpu_get_scratch(dyn);
switch (u8 & 0xf) {
case 0x00: VFCMP_S(q0, v1, v2, cEQ); break; // Equal, not unordered
case 0x01: VFCMP_S(q0, v1, v2, cLT); break; // Less than
@@ -489,7 +487,7 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
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: VXOR_V(q0, q0, q0); break; // false
case 0x0b: break; // false
case 0x0c: VFCMP_S(q0, v1, v2, cNE); break; // Not Eual, 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
+7 -2
View File
@@ -35,7 +35,12 @@
// Get a FPU scratch reg
int fpu_get_scratch(dynarec_la64_t* dyn)
{
return SCRATCH0 + dyn->lsx.fpu_scratch++; // return an Sx
int ret = SCRATCH0 + dyn->lsx.fpu_scratch++; // return an Sx
if (ret >= SCRATCH_LIMIT) {
dyn->abort = 1;
ret = SCRATCH_LIMIT - 1;
}
return ret;
}
// Reset scratch regs counter
void fpu_reset_scratch(dynarec_la64_t* dyn)
@@ -922,4 +927,4 @@ void propagateFpuBarrier(dynarec_la64_t* dyn)
last_fpu_used = -1; // reset the last_fpu_used...
}
}
}
}
+4 -1
View File
@@ -3,7 +3,10 @@
#include "../dynarec_native_functions.h"
#define SCRATCH0 24
#define SCRATCH0 24
#define VZERO 30
#define SCRATCH 31
#define SCRATCH_LIMIT VZERO
typedef struct x64emu_s x64emu_t;
typedef struct dynarec_la64_s dynarec_la64_t;
+15 -15
View File
@@ -25,8 +25,6 @@
#include "dynarec_la64_functions.h"
#include "../dynarec_helper.h"
#define SCRATCH 31
/* setup r2 to address pointed by ED, also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
uintptr_t geted(dynarec_la64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, uint8_t scratch, int64_t* fixaddress, rex_t rex, int* l, int i12, int delta)
{
@@ -545,6 +543,7 @@ void call_c(dynarec_la64_t* dyn, int ninst, la64_consts_t fnc, int reg, int ret,
if (arg6) MV(A6, arg6);
MV(A0, xEmu);
JIRL(xRA, reg, 0);
LA64_RESTORE_VZERO();
if (ret >= 0) {
MV(ret, A0);
}
@@ -600,6 +599,7 @@ void call_n(dynarec_la64_t* dyn, int ninst, void* fnc, int w)
// because native function might be very different on a next run: different function address, different brick, different everything basicaly
// and we don't have a relocation mecanism here, it's too complex
JIRL(xRA, x3, 0x0);
LA64_RESTORE_VZERO();
// put return value in x64 regs
if (w > 0) {
MV(xRAX, A0);
@@ -1421,11 +1421,11 @@ void sse_purge07cache(dynarec_la64_t* dyn, int ninst, int s1)
if (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].dirty) {
XVXOR_V(SCRATCH, SCRATCH, SCRATCH);
VST(VZERO, xEmu, offsetof(x64emu_t, ymm[i]));
} else {
XVPERMI_Q(SCRATCH, dyn->lsx.avxcache[i].reg, XVPERMI_IMM_4_0(0, 1));
VST(SCRATCH, xEmu, offsetof(x64emu_t, ymm[i]));
}
VST(SCRATCH, xEmu, offsetof(x64emu_t, ymm[i]));
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) {
@@ -1546,11 +1546,11 @@ void avx_forget_reg(dynarec_la64_t* dyn, int ninst, int a)
if (dyn->lsx.lsxcache[dyn->lsx.avxcache[a].reg].t == LSX_CACHE_YMMW) {
VST(dyn->lsx.avxcache[a].reg, xEmu, offsetof(x64emu_t, xmm[a]));
if (dyn->lsx.avxcache[a].dirty) {
XVXOR_V(SCRATCH, SCRATCH, SCRATCH);
VST(VZERO, xEmu, offsetof(x64emu_t, ymm[a]));
} else {
XVPERMI_Q(SCRATCH, dyn->lsx.avxcache[a].reg, XVPERMI_IMM_4_0(0, 1));
VST(SCRATCH, xEmu, offsetof(x64emu_t, ymm[a]));
}
VST(SCRATCH, xEmu, offsetof(x64emu_t, ymm[a]));
}
fpu_free_reg(dyn, dyn->lsx.avxcache[a].reg);
dyn->lsx.avxcache[a].v = -1;
@@ -1565,12 +1565,12 @@ void avx_reflect_reg(dynarec_la64_t* dyn, int ninst, int a)
if (dyn->lsx.lsxcache[dyn->lsx.avxcache[a].reg].t == LSX_CACHE_YMMW) {
VST(dyn->lsx.avxcache[a].reg, xEmu, offsetof(x64emu_t, xmm[a]));
if (dyn->lsx.avxcache[a].dirty) {
XVXOR_V(SCRATCH, SCRATCH, SCRATCH);
XVPERMI_Q(dyn->lsx.avxcache[a].reg, SCRATCH, 0b00000010);
XVPERMI_Q(dyn->lsx.avxcache[a].reg, VZERO, 0b00000010);
VST(VZERO, xEmu, offsetof(x64emu_t, ymm[a]));
} else {
XVPERMI_Q(SCRATCH, dyn->lsx.avxcache[a].reg, XVPERMI_IMM_4_0(0, 1));
VST(SCRATCH, xEmu, offsetof(x64emu_t, ymm[a]));
}
VST(SCRATCH, xEmu, offsetof(x64emu_t, ymm[a]));
dyn->lsx.avxcache[a].dirty = 0;
}
}
@@ -1586,8 +1586,7 @@ void avx_cleancache(dynarec_la64_t* dyn, int ninst)
MESSAGE(LOG_DUMP, "\tClean AVX Cache ------\n");
++old;
}
XVXOR_V(SCRATCH, SCRATCH, SCRATCH);
XVPERMI_Q(dyn->lsx.avxcache[i].reg, SCRATCH, 0b00000010);
XVPERMI_Q(dyn->lsx.avxcache[i].reg, VZERO, 0b00000010);
dyn->lsx.avxcache[i].dirty = 0;
}
}
@@ -1610,11 +1609,11 @@ static void avx_purgecache(dynarec_la64_t* dyn, int ninst, int next, int s1)
}
VST(dyn->lsx.avxcache[i].reg, xEmu, offsetof(x64emu_t, xmm[i]));
if (dyn->lsx.avxcache[i].dirty) {
XVXOR_V(SCRATCH, SCRATCH, SCRATCH);
VST(VZERO, xEmu, offsetof(x64emu_t, ymm[i]));
} else {
XVPERMI_Q(SCRATCH, dyn->lsx.avxcache[i].reg, XVPERMI_IMM_4_0(0, 1));
VST(SCRATCH, xEmu, offsetof(x64emu_t, ymm[i]));
}
VST(SCRATCH, xEmu, offsetof(x64emu_t, ymm[i]));
} else {
MESSAGE(LOG_DUMP, "\tAVX Cache for YMM%d is not write, no need to store back %d\n", i, dyn->lsx.lsxcache[dyn->lsx.avxcache[i].reg].t);
}
@@ -1694,8 +1693,7 @@ void fpu_popcache(dynarec_la64_t* dyn, int ninst, int s1, int not07)
VLD(SCRATCH, xEmu, offsetof(x64emu_t, ymm[i]));
XVPERMI_Q(dyn->lsx.avxcache[i].reg, SCRATCH, XVPERMI_IMM_4_0(0, 2));
} else {
XVXOR_V(SCRATCH, SCRATCH, SCRATCH);
XVPERMI_Q(dyn->lsx.avxcache[i].reg, SCRATCH, XVPERMI_IMM_4_0(0, 2));
XVPERMI_Q(dyn->lsx.avxcache[i].reg, VZERO, XVPERMI_IMM_4_0(0, 2));
}
}
}
@@ -2252,6 +2250,7 @@ static void flagsCacheTransform(dynarec_la64_t* dyn, int ninst, int s1)
}
TABLE64C(s1, const_updateflags_la64);
JIRL(xRA, s1, 0);
LA64_RESTORE_VZERO();
MARKF2;
}
MESSAGE(LOG_DUMP, "\t---- Flags fetch\n");
@@ -2306,6 +2305,7 @@ void checkCRC(dynarec_la64_t* dyn, int ninst)
LD_D(x1, x6, offsetof(dynablock_t, x64_addr));
LD_WU(x2, x6, offsetof(dynablock_t, x64_size));
JIRL(xRA, x3, 0x0);
LA64_RESTORE_VZERO();
// done, result in x1, load the stored hash (sign extended, as the crc will also be sign extended)
LD_W(x2, x6, offsetof(dynablock_t, hash));
// compare computed crc with stored one, jump to continue is equal
+17 -6
View File
@@ -21,6 +21,15 @@
#include "la64_emitter.h"
#include "../emu/x64primop.h"
#include "dynarec_la64_consts.h"
#include "dynarec_la64_functions.h"
#define LA64_RESTORE_VZERO() \
do { \
if (cpuext.lasx) \
XVXOR_V(VZERO, VZERO, VZERO); \
else \
VXOR_V(VZERO, VZERO, VZERO); \
} while (0)
#define F8 *(uint8_t*)(addr++)
#define F8S *(int8_t*)(addr++)
@@ -959,12 +968,13 @@
#endif
#ifndef READFLAGS
#define READFLAGS(A) \
if ((A) != X_PEND \
&& (dyn->f == status_unk)) { \
TABLE64C(x6, const_updateflags_la64); \
JIRL(xRA, x6, 0); \
dyn->f = status_none; \
#define READFLAGS(A) \
if ((A) != X_PEND \
&& (dyn->f == status_unk)) { \
TABLE64C(x6, const_updateflags_la64); \
JIRL(xRA, x6, 0); \
LA64_RESTORE_VZERO(); \
dyn->f = status_none; \
}
#endif
@@ -1003,6 +1013,7 @@
&& ((dyn->f == status_unk) || (dyn->f == status_set))) { \
TABLE64C(x6, const_updateflags_la64); \
JIRL(xRA, x6, 0); \
LA64_RESTORE_VZERO(); \
dyn->f = status_none; \
}
+13
View File
@@ -10,9 +10,20 @@
.text
.align 4
.extern cpuext
.extern LinkNext
.extern LinkNextInvalid
.macro restore_vzero
.word 0x71277bde // vxor.v $vr30, $vr30, $vr30
la.global $r19, cpuext
ldptr.d $r19, $r19, 0
andi $r19, $r19, 0x20
beqz $r19, 1f
.word 0x75277bde // xvxor.v $xr30, $xr30, $xr30
1:
.endm
.global la64_next
.global la64_next_invalid
@@ -41,6 +52,7 @@ la64_next:
bl LinkNext
// preserve return value
move $r16, $a0
restore_vzero
// pop regs
ld.d RDI, $sp, 0
ld.d RSI, $sp, 8
@@ -81,6 +93,7 @@ la64_next_invalid:
bl LinkNextInvalid
// preserve return value
move $r16, $a0
restore_vzero
// pop regs
ld.d RDI, $sp, 0
ld.d RSI, $sp, 8
+11
View File
@@ -12,6 +12,16 @@
.extern cpuext
.macro restore_vzero
.word 0x71277bde // vxor.v $vr30, $vr30, $vr30
la.global $r19, cpuext
ldptr.d $r19, $r19, 0
andi $r19, $r19, 0x20
beqz $r19, 1f
.word 0x75277bde // xvxor.v $xr30, $xr30, $xr30
1:
.endm
.global la64_prolog
la64_prolog:
//save all 18 used register
@@ -72,5 +82,6 @@ la64_prolog:
addi.d $sp, $sp, -16
// save old sp into xSavedSP
addi.d SavedSP, $sp, 16
restore_vzero
//jump to function
jirl $r0, $r16, 0