diff options
| author | phorcys <phorcys@126.com> | 2025-07-22 20:36:15 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-22 14:36:15 +0200 |
| commit | 5f7da532c4ea35e56b2a5839d776e2cd75f34db1 (patch) | |
| tree | 217ff8b40497f178af5e8f61c5565fe1cdabd97b /src | |
| parent | fc1b149fed49905fc4039b68d3b9c1f03247d2f7 (diff) | |
| download | box64-5f7da532c4ea35e56b2a5839d776e2cd75f34db1.tar.gz box64-5f7da532c4ea35e56b2a5839d776e2cd75f34db1.zip | |
[LA64_DYNAREC] Add la64 avx float arith ops, part 1. (#2840)
* V{ADD,SUB,MUL,DIV}{PD,PS,SD,SS}
* VADDSUB{PD,PS}Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_avx_0f.c | 72 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_avx_66_0f.c | 93 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_avx_f2_0f.c | 98 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_avx_f3_0f.c | 76 | ||||
| -rw-r--r-- | src/dynarec/la64/la64_emitter.h | 46 |
5 files changed, 385 insertions, 0 deletions
diff --git a/src/dynarec/la64/dynarec_la64_avx_0f.c b/src/dynarec/la64/dynarec_la64_avx_0f.c index 3a9c9822..01ae9f5b 100644 --- a/src/dynarec/la64/dynarec_la64_avx_0f.c +++ b/src/dynarec/la64/dynarec_la64_avx_0f.c @@ -269,6 +269,78 @@ uintptr_t dynarec64_AVX_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, in GETGY_empty_VYEY_xy(v0, v1, v2, 0); VXOR_Vxy(v0, v1, v2); break; + case 0x58: + INST_NAME("VADDPS Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_xy(v0, v1, v2, 0); + if (!BOX64ENV(dynarec_fastnan)) { + d0 = fpu_get_scratch(dyn); + d1 = fpu_get_scratch(dyn); + VFCMPxy(S, d0, v1, v2, cUN); + } + VFADDxy(S, v0, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + VFCMPxy(S, d1, v0, v0, cUN); + VANDN_Vxy(d0, d0, d1); + VLDIxy(d1, (0b010 << 9) | 0b1111111100); + VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000 + VBITSEL_Vxy(v0, v0, d1, d0); + } + break; + case 0x59: + INST_NAME("VMULPS Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_xy(v0, v1, v2, 0); + if (!BOX64ENV(dynarec_fastnan)) { + d0 = fpu_get_scratch(dyn); + d1 = fpu_get_scratch(dyn); + VFCMPxy(S, d0, v1, v2, cUN); + } + VFMULxy(S, v0, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + VFCMPxy(S, d1, v0, v0, cUN); + VANDN_Vxy(d0, d0, d1); + VLDIxy(d1, (0b010 << 9) | 0b1111111100); + VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000 + VBITSEL_Vxy(v0, v0, d1, d0); + } + break; + case 0x5C: + INST_NAME("VSUBPS Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_xy(v0, v1, v2, 0); + if (!BOX64ENV(dynarec_fastnan)) { + d0 = fpu_get_scratch(dyn); + d1 = fpu_get_scratch(dyn); + VFCMPxy(S, d0, v1, v2, cUN); + } + VFSUBxy(S, v0, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + VFCMPxy(S, d1, v0, v0, cUN); + VANDN_Vxy(d0, d0, d1); + VLDIxy(d1, (0b010 << 9) | 0b1111111100); + VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000 + VBITSEL_Vxy(v0, v0, d1, d0); + } + break; + case 0x5E: + INST_NAME("VDIVPS Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_xy(v0, v1, v2, 0); + if (!BOX64ENV(dynarec_fastnan)) { + d0 = fpu_get_scratch(dyn); + d1 = fpu_get_scratch(dyn); + VFCMPxy(S, d0, v1, v2, cUN); + } + VFDIVxy(S, v0, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + VFCMPxy(S, d1, v0, v0, cUN); + VANDN_Vxy(d0, d0, d1); + VLDIxy(d1, (0b010 << 9) | 0b1111111100); + VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000 + VBITSEL_Vxy(v0, v0, d1, d0); + } + break; case 0x77: if (!vex.l) { INST_NAME("VZEROUPPER"); diff --git a/src/dynarec/la64/dynarec_la64_avx_66_0f.c b/src/dynarec/la64/dynarec_la64_avx_66_0f.c index 13e9a359..d7e2ecf5 100644 --- a/src/dynarec/la64/dynarec_la64_avx_66_0f.c +++ b/src/dynarec/la64/dynarec_la64_avx_66_0f.c @@ -263,6 +263,78 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, GETGY_empty_VYEY_xy(v0, v1, v2, 0); VXOR_Vxy(v0, v1, v2); break; + case 0x58: + INST_NAME("VADDPD Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_xy(v0, v1, v2, 0); + if (!BOX64ENV(dynarec_fastnan)) { + d0 = fpu_get_scratch(dyn); + d1 = fpu_get_scratch(dyn); + VFCMPxy(D, d0, v1, v2, cUN); + } + VFADDxy(D, v0, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + VFCMPxy(D, d1, v0, v0, cUN); + VANDN_Vxy(d0, d0, d1); + VLDIxy(d1, (0b011 << 9) | 0b111111000); + VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000 + VBITSEL_Vxy(v0, v0, d1, d0); + } + break; + case 0x59: + INST_NAME("VMULPD Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_xy(v0, v1, v2, 0); + if (!BOX64ENV(dynarec_fastnan)) { + d0 = fpu_get_scratch(dyn); + d1 = fpu_get_scratch(dyn); + VFCMPxy(D, d0, v1, v2, cUN); + } + VFMULxy(D, v0, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + VFCMPxy(D, d1, v0, v0, cUN); + VANDN_Vxy(d0, d0, d1); + VLDIxy(d1, (0b011 << 9) | 0b111111000); + VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000 + VBITSEL_Vxy(v0, v0, d1, d0); + } + break; + case 0x5C: + INST_NAME("VSUBPD Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_xy(v0, v1, v2, 0); + if (!BOX64ENV(dynarec_fastnan)) { + d0 = fpu_get_scratch(dyn); + d1 = fpu_get_scratch(dyn); + VFCMPxy(D, d0, v1, v2, cUN); + } + VFSUBxy(D, v0, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + VFCMPxy(D, d1, v0, v0, cUN); + VANDN_Vxy(d0, d0, d1); + VLDIxy(d1, (0b011 << 9) | 0b111111000); + VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000 + VBITSEL_Vxy(v0, v0, d1, d0); + } + break; + case 0x5E: + INST_NAME("VDIVPD Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_xy(v0, v1, v2, 0); + if (!BOX64ENV(dynarec_fastnan)) { + d0 = fpu_get_scratch(dyn); + d1 = fpu_get_scratch(dyn); + VFCMPxy(D, d0, v1, v2, cUN); + } + VFDIVxy(D, v0, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + VFCMPxy(D, d1, v0, v0, cUN); + VANDN_Vxy(d0, d0, d1); + VLDIxy(d1, (0b011 << 9) | 0b111111000); + VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000 + VBITSEL_Vxy(v0, v0, d1, d0); + } + break; case 0x60: INST_NAME("VPUNPCKLBW Gx, Vx, Ex"); nextop = F8; @@ -599,6 +671,27 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, VOR_V(v0, d0, d0); } break; + case 0xD0: + INST_NAME("VADDSUBPD Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_xy(v0, v1, v2, 0); + if (!BOX64ENV(dynarec_fastnan)) { + d0 = fpu_get_scratch(dyn); + d1 = fpu_get_scratch(dyn); + VFCMPxy(D, d0, v1, v2, cUN); + } + q0 = fpu_get_scratch(dyn); + VFSUBxy(D, q0, v1, v2); + VFADDxy(D, v0, v1, v2); + VEXTRINSxy(D, v0, q0, 0); + if (!BOX64ENV(dynarec_fastnan)) { + VFCMPxy(D, d1, v0, v0, cUN); + VANDN_Vxy(d0, d0, d1); + VLDIxy(d1, (0b011 << 9) | 0b111111000); + VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000 + VBITSEL_Vxy(v0, v0, d1, d0); + } + break; case 0xD1: INST_NAME("VPSRLW Gx, Vx, Ex"); nextop = F8; diff --git a/src/dynarec/la64/dynarec_la64_avx_f2_0f.c b/src/dynarec/la64/dynarec_la64_avx_f2_0f.c index 0b0eb1df..446ed244 100644 --- a/src/dynarec/la64/dynarec_la64_avx_f2_0f.c +++ b/src/dynarec/la64/dynarec_la64_avx_f2_0f.c @@ -116,6 +116,82 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, VREPLVE_D(q0, q1, 0); } break; + case 0x58: + INST_NAME("VADDSD Gx, Vx, Ex"); + nextop = F8; + GETVYx(v1, 0); + GETEYSD(v2, 0, 0); + GETGYx_empty(v0); + d0 = fpu_get_scratch(dyn); + FADD_D(d0, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + FCMP_D(fcc0, v1, v2, cUN); + BCNEZ_MARK(fcc0); + FCMP_D(fcc1, d0, d0, cOR); + BCNEZ_MARK(fcc1); + FNEG_D(d0, d0); + } + MARK; + VOR_V(v0, v1, v1); + VEXTRINS_D(v0, d0, 0); + break; + case 0x59: + INST_NAME("VMULSD Gx, Vx, Ex"); + nextop = F8; + GETVYx(v1, 0); + GETEYSD(v2, 0, 0); + GETGYx_empty(v0); + d0 = fpu_get_scratch(dyn); + FMUL_D(d0, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + FCMP_D(fcc0, v1, v2, cUN); + BCNEZ_MARK(fcc0); + FCMP_D(fcc1, d0, d0, cOR); + BCNEZ_MARK(fcc1); + FNEG_D(d0, d0); + } + MARK; + VOR_V(v0, v1, v1); + VEXTRINS_D(v0, d0, 0); + break; + case 0x5C: + INST_NAME("VSUBSD Gx, Vx, Ex"); + nextop = F8; + GETVYx(v1, 0); + GETEYSD(v2, 0, 0); + GETGYx_empty(v0); + d0 = fpu_get_scratch(dyn); + FSUB_D(d0, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + FCMP_D(fcc0, v1, v2, cUN); + BCNEZ_MARK(fcc0); + FCMP_D(fcc1, d0, d0, cOR); + BCNEZ_MARK(fcc1); + FNEG_D(d0, d0); + } + MARK; + VOR_V(v0, v1, v1); + VEXTRINS_D(v0, d0, 0); + break; + case 0x5E: + INST_NAME("VDIVSD Gx, Vx, Ex"); + nextop = F8; + GETVYx(v1, 0); + GETEYSD(v2, 0, 0); + GETGYx_empty(v0); + d0 = fpu_get_scratch(dyn); + FDIV_D(d0, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + FCMP_D(fcc0, v1, v2, cUN); + BCNEZ_MARK(fcc0); + FCMP_D(fcc1, d0, d0, cOR); + BCNEZ_MARK(fcc1); + FNEG_D(d0, d0); + } + MARK; + VOR_V(v0, v1, v1); + VEXTRINS_D(v0, d0, 0); + break; case 0x70: INST_NAME("VPSHUFLW Gx, Ex, Ib"); nextop = F8; @@ -130,6 +206,28 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, VEXTRINSxy(D, v0, d0, VEXTRINS_IMM_4_0(0, 0)); } break; + case 0xD0: + INST_NAME("VADDSUBPS Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_xy(v0, v1, v2, 0); + if (!BOX64ENV(dynarec_fastnan)) { + d0 = fpu_get_scratch(dyn); + d1 = fpu_get_scratch(dyn); + VFCMPxy(S, d0, v1, v2, cUN); + } + q0 = fpu_get_scratch(dyn); + VFSUBxy(S, q0, v1, v2); + VFADDxy(S, v0, v1, v2); + VEXTRINSxy(W, v0, q0, VEXTRINS_IMM_4_0(0, 0)); + VEXTRINSxy(W, v0, q0, VEXTRINS_IMM_4_0(2, 2)); + if (!BOX64ENV(dynarec_fastnan)) { + VFCMPxy(S, d1, v0, v0, cUN); + VANDN_Vxy(d0, d0, d1); + VLDIxy(d1, (0b010 << 9) | 0b1111111100); + VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000 + VBITSEL_Vxy(v0, v0, d1, d0); + } + break; case 0xF0: INST_NAME("VLDDQU Gx, Ex"); nextop = F8; diff --git a/src/dynarec/la64/dynarec_la64_avx_f3_0f.c b/src/dynarec/la64/dynarec_la64_avx_f3_0f.c index b8332a4b..2e51ce90 100644 --- a/src/dynarec/la64/dynarec_la64_avx_f3_0f.c +++ b/src/dynarec/la64/dynarec_la64_avx_f3_0f.c @@ -100,6 +100,82 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, VPACKOD_W(q0, q1, q1); } break; + case 0x58: + INST_NAME("VADDSS Gx, Vx, Ex"); + nextop = F8; + GETVYx(v1, 0); + GETEYSD(v2, 0, 0); + GETGYx_empty(v0); + d0 = fpu_get_scratch(dyn); + FADD_S(d0, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + FCMP_S(fcc0, v1, v2, cUN); + BCNEZ_MARK(fcc0); + FCMP_S(fcc1, d0, d0, cOR); + BCNEZ_MARK(fcc1); + FNEG_S(d0, d0); + } + MARK; + VOR_V(v0, v1, v1); + VEXTRINS_W(v0, d0, 0); + break; + case 0x59: + INST_NAME("VMULSS Gx, Vx, Ex"); + nextop = F8; + GETVYx(v1, 0); + GETEYSD(v2, 0, 0); + GETGYx_empty(v0); + d0 = fpu_get_scratch(dyn); + FMUL_S(d0, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + FCMP_S(fcc0, v1, v2, cUN); + BCNEZ_MARK(fcc0); + FCMP_S(fcc1, d0, d0, cOR); + BCNEZ_MARK(fcc1); + FNEG_S(d0, d0); + } + MARK; + VOR_V(v0, v1, v1); + VEXTRINS_W(v0, d0, 0); + break; + case 0x5C: + INST_NAME("VSUBSS Gx, Vx, Ex"); + nextop = F8; + GETVYx(v1, 0); + GETEYSD(v2, 0, 0); + GETGYx_empty(v0); + d0 = fpu_get_scratch(dyn); + FSUB_S(d0, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + FCMP_S(fcc0, v1, v2, cUN); + BCNEZ_MARK(fcc0); + FCMP_S(fcc1, d0, d0, cOR); + BCNEZ_MARK(fcc1); + FNEG_S(d0, d0); + } + MARK; + VOR_V(v0, v1, v1); + VEXTRINS_W(v0, d0, 0); + break; + case 0x5E: + INST_NAME("VDIVSS Gx, Vx, Ex"); + nextop = F8; + GETVYx(v1, 0); + GETEYSD(v2, 0, 0); + GETGYx_empty(v0); + d0 = fpu_get_scratch(dyn); + FDIV_S(d0, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + FCMP_S(fcc0, v1, v2, cUN); + BCNEZ_MARK(fcc0); + FCMP_S(fcc1, d0, d0, cOR); + BCNEZ_MARK(fcc1); + FNEG_S(d0, d0); + } + MARK; + VOR_V(v0, v1, v1); + VEXTRINS_W(v0, d0, 0); + break; case 0x6F: INST_NAME("VMOVDQU Gx, Ex"); nextop = F8; diff --git a/src/dynarec/la64/la64_emitter.h b/src/dynarec/la64/la64_emitter.h index 6fc25100..42899386 100644 --- a/src/dynarec/la64/la64_emitter.h +++ b/src/dynarec/la64/la64_emitter.h @@ -3152,4 +3152,50 @@ LSX instruction starts with V, LASX instruction starts with XV. } \ } while (0) + +#define VFCMPxy(width, vd, vj, vk, cond) \ + do { \ + if (vex.l) { \ + XVFCMP_##width(vd, vj, vk, cond); \ + } else { \ + VFCMP_##width(vd, vj, vk, cond); \ + } \ + } while (0) + +#define VFADDxy(width, vd, vj, vk) \ + do { \ + if (vex.l) { \ + XVFADD_##width(vd, vj, vk); \ + } else { \ + VFADD_##width(vd, vj, vk); \ + } \ + } while (0) + +#define VFSUBxy(width, vd, vj, vk) \ + do { \ + if (vex.l) { \ + XVFSUB_##width(vd, vj, vk); \ + } else { \ + VFSUB_##width(vd, vj, vk); \ + } \ + } while (0) + +#define VFMULxy(width, vd, vj, vk) \ + do { \ + if (vex.l) { \ + XVFMUL_##width(vd, vj, vk); \ + } else { \ + VFMUL_##width(vd, vj, vk); \ + } \ + } while (0) + +#define VFDIVxy(width, vd, vj, vk) \ + do { \ + if (vex.l) { \ + XVFDIV_##width(vd, vj, vk); \ + } else { \ + VFDIV_##width(vd, vj, vk); \ + } \ + } while (0) + #endif //__ARM64_EMITTER_H__ |