mirror of
https://github.com/ran-j/PS2Recomp.git
synced 2026-10-05 11:38:24 -04:00
Issue 11 vu0 macro (#48)
* Add missing VU0 Special1 macro translations * Fix VU0 macro decode and field ops Align Special2 decoding with fhi_flo, implement VCLIPw/VABS, and fix field variants (VADDx/VSUBx/VMULx). Keep C++17 compatibility by replacing unordered_set::contains and remove dead ADDIU return. Update Special2 metadata for VWAITQ. * vu0: complete macro mappings and add coverage test * review: clean up vu macro handling * fix: restore C++20 contains in code generator * fix: correct VU0 Special2 instruction encoding in decoder test --------- Co-authored-by: Antonio Guastella <antonioguastella@energine.it> Co-authored-by: Ranieri <ran-junior@hotmail.com>
This commit is contained in:
committed by
GitHub
parent
b7973593ee
commit
4961710407
@@ -1769,10 +1769,93 @@ namespace ps2recomp
|
||||
case COP2_CO + 15:
|
||||
{
|
||||
uint8_t vu_func = inst.function;
|
||||
if (vu_func >= 0x3C) // Special2 Table
|
||||
if (vu_func >= 0x3C)
|
||||
{
|
||||
switch (vu_func)
|
||||
uint8_t vu_fhi_flo = (uint8_t)((((inst.raw >> 6) & 0x1F) << 2) | (inst.raw & 0x3));
|
||||
|
||||
switch (vu_fhi_flo)
|
||||
{
|
||||
case VU0_S2_VADDAx:
|
||||
case VU0_S2_VADDAy:
|
||||
case VU0_S2_VADDAz:
|
||||
case VU0_S2_VADDAw:
|
||||
return translateVU_VADDA_Field(inst);
|
||||
case VU0_S2_VSUBAx:
|
||||
case VU0_S2_VSUBAy:
|
||||
case VU0_S2_VSUBAz:
|
||||
case VU0_S2_VSUBAw:
|
||||
return translateVU_VSUBA_Field(inst);
|
||||
case VU0_S2_VMADDAx:
|
||||
case VU0_S2_VMADDAy:
|
||||
case VU0_S2_VMADDAz:
|
||||
case VU0_S2_VMADDAw:
|
||||
return translateVU_VMADDA_Field(inst);
|
||||
case VU0_S2_VMSUBAx:
|
||||
case VU0_S2_VMSUBAy:
|
||||
case VU0_S2_VMSUBAz:
|
||||
case VU0_S2_VMSUBAw:
|
||||
return translateVU_VMSUBA_Field(inst);
|
||||
case VU0_S2_VMULAx:
|
||||
case VU0_S2_VMULAy:
|
||||
case VU0_S2_VMULAz:
|
||||
case VU0_S2_VMULAw:
|
||||
return translateVU_VMULA_Field(inst);
|
||||
case VU0_S2_VADDA:
|
||||
return translateVU_VADDA(inst);
|
||||
case VU0_S2_VADDAq:
|
||||
return translateVU_VADDAq(inst);
|
||||
case VU0_S2_VADDAi:
|
||||
return translateVU_VADDAi(inst);
|
||||
case VU0_S2_VMADDA:
|
||||
return translateVU_VMADDA(inst);
|
||||
case VU0_S2_VMADDAq:
|
||||
return translateVU_VMADDAq(inst);
|
||||
case VU0_S2_VMADDAi:
|
||||
return translateVU_VMADDAi(inst);
|
||||
case VU0_S2_VSUBA:
|
||||
return translateVU_VSUBA(inst);
|
||||
case VU0_S2_VSUBAq:
|
||||
return translateVU_VSUBAq(inst);
|
||||
case VU0_S2_VSUBAi:
|
||||
return translateVU_VSUBAi(inst);
|
||||
case VU0_S2_VMSUBA:
|
||||
return translateVU_VMSUBA(inst);
|
||||
case VU0_S2_VMSUBAq:
|
||||
return translateVU_VMSUBAq(inst);
|
||||
case VU0_S2_VMSUBAi:
|
||||
return translateVU_VMSUBAi(inst);
|
||||
case VU0_S2_VMULA:
|
||||
return translateVU_VMULA(inst);
|
||||
case VU0_S2_VMULAq:
|
||||
return translateVU_VMULAq(inst);
|
||||
case VU0_S2_VMULAi:
|
||||
return translateVU_VMULAi(inst);
|
||||
case VU0_S2_VOPMULA:
|
||||
return translateVU_VOPMULA(inst);
|
||||
case VU0_S2_VITOF0:
|
||||
return translateVU_VITOF(inst, 0);
|
||||
case VU0_S2_VITOF4:
|
||||
return translateVU_VITOF(inst, 4);
|
||||
case VU0_S2_VITOF12:
|
||||
return translateVU_VITOF(inst, 12);
|
||||
case VU0_S2_VITOF15:
|
||||
return translateVU_VITOF(inst, 15);
|
||||
case VU0_S2_VFTOI0:
|
||||
return translateVU_VFTOI(inst, 0);
|
||||
case VU0_S2_VFTOI4:
|
||||
return translateVU_VFTOI(inst, 4);
|
||||
case VU0_S2_VFTOI12:
|
||||
return translateVU_VFTOI(inst, 12);
|
||||
case VU0_S2_VFTOI15:
|
||||
return translateVU_VFTOI(inst, 15);
|
||||
case VU0_S2_VLQI:
|
||||
return translateVU_VLQI(inst);
|
||||
case VU0_S2_VSQI:
|
||||
return translateVU_VSQI(inst);
|
||||
case VU0_S2_VLQD:
|
||||
return translateVU_VLQD(inst);
|
||||
case VU0_S2_VSQD:
|
||||
return translateVU_VSQD(inst);
|
||||
case VU0_S2_VDIV:
|
||||
return translateVU_VDIV(inst);
|
||||
case VU0_S2_VSQRT:
|
||||
@@ -1780,7 +1863,7 @@ namespace ps2recomp
|
||||
case VU0_S2_VRSQRT:
|
||||
return translateVU_VRSQRT(inst);
|
||||
case VU0_S2_VWAITQ:
|
||||
return fmt::format("// Unhandled VU0 VWAITQ instruction: 0x{:X}", vu_func);
|
||||
return fmt::format("// VWAITQ (Q already resolved in this runtime)");
|
||||
case VU0_S2_VMTIR:
|
||||
return translateVU_VMTIR(inst);
|
||||
case VU0_S2_VMFIR:
|
||||
@@ -1789,6 +1872,42 @@ namespace ps2recomp
|
||||
return translateVU_VILWR(inst);
|
||||
case VU0_S2_VISWR:
|
||||
return translateVU_VISWR(inst);
|
||||
case VU0_S2_VABS:
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
return fmt::format("{{ __m128 res = _mm_and_ps(ctx->vu0_vf[{}], _mm_castsi128_ps(_mm_set1_epi32(0x7FFFFFFF))); "
|
||||
"__m128i mask = _mm_set_epi32({}, {}, {}, {}); "
|
||||
"ctx->vu0_vf[{}] = _mm_blendv_ps(ctx->vu0_vf[{}], res, _mm_castsi128_ps(mask)); }}",
|
||||
inst.rs,
|
||||
(dest_mask & 0x8) ? -1 : 0, (dest_mask & 0x4) ? -1 : 0,
|
||||
(dest_mask & 0x2) ? -1 : 0, (dest_mask & 0x1) ? -1 : 0,
|
||||
inst.rt, inst.rt);
|
||||
}
|
||||
case VU0_S2_VMOVE:
|
||||
return fmt::format("ctx->vu0_vf[{}] = ctx->vu0_vf[{}];", inst.rt, inst.rs);
|
||||
case VU0_S2_VMR32:
|
||||
return fmt::format("ctx->vu0_vf[{}] = _mm_shuffle_ps(ctx->vu0_vf[{}], ctx->vu0_vf[{}], _MM_SHUFFLE(0,0,0,1));", inst.rt, inst.rs, inst.rs);
|
||||
case VU0_S2_VCLIPw:
|
||||
{
|
||||
uint8_t field = inst.function & 0x3;
|
||||
std::string shuffle_pattern = fmt::format("_MM_SHUFFLE({},{},{},{})", field, field, field, field);
|
||||
|
||||
return fmt::format(
|
||||
"{{ __m128 fs = ctx->vu0_vf[{}]; "
|
||||
"__m128 ft = _mm_shuffle_ps(ctx->vu0_vf[{}], ctx->vu0_vf[{}], {}); "
|
||||
"__m128 neg_ft = _mm_xor_ps(ft, _mm_castsi128_ps(_mm_set1_epi32(0x80000000))); "
|
||||
"__m128 gt = _mm_cmpgt_ps(fs, ft); "
|
||||
"__m128 lt = _mm_cmplt_ps(fs, neg_ft); "
|
||||
"uint32_t gt_mask = (uint32_t)_mm_movemask_ps(gt); "
|
||||
"uint32_t lt_mask = (uint32_t)_mm_movemask_ps(lt); "
|
||||
"uint32_t flags = ((lt_mask & 0x1) << 0) | ((gt_mask & 0x1) << 1) | "
|
||||
"((lt_mask & 0x2) << 1) | ((gt_mask & 0x2) << 2) | "
|
||||
"((lt_mask & 0x4) << 2) | ((gt_mask & 0x4) << 3); "
|
||||
"ctx->vu0_clip_flags = ((ctx->vu0_clip_flags << 6) | (flags & 0x3F)) & 0xFFFFFF; }}",
|
||||
inst.rs, inst.rt, inst.rt, shuffle_pattern);
|
||||
}
|
||||
case VU0_S2_VNOP:
|
||||
return fmt::format("// NOP operation, no action needed for VU0");
|
||||
case VU0_S2_VRNEXT:
|
||||
return translateVU_VRNEXT(inst);
|
||||
case VU0_S2_VRGET:
|
||||
@@ -1797,95 +1916,107 @@ namespace ps2recomp
|
||||
return translateVU_VRINIT(inst);
|
||||
case VU0_S2_VRXOR:
|
||||
return translateVU_VRXOR(inst);
|
||||
case VU0_S2_VABS:
|
||||
return fmt::format("ctx->vu0_vf[{}] = _mm_andnot_ps(_mm_set1_ps(-0.0f), ctx->vu0_vf[{}]);", inst.rt, inst.rs); // FT, FS
|
||||
case VU0_S2_VNOP:
|
||||
return fmt::format("// NOP operation, no action needed for VU0"); // No operation
|
||||
case VU0_S2_VMOVE:
|
||||
return fmt::format("ctx->vu0_vf[{}] = ctx->vu0_vf[{}];", inst.rt, inst.rs); // FT, FS
|
||||
case VU0_S2_VMR32:
|
||||
return fmt::format("ctx->vu0_vf[{}] = _mm_shuffle_ps(ctx->vu0_vf[{}], ctx->vu0_vf[{}], _MM_SHUFFLE(0,0,0,1));", inst.rt, inst.rs, inst.rs); // FT, FS
|
||||
default:
|
||||
return fmt::format("// Unhandled VU0 Special2 function: 0x{:X}", vu_func);
|
||||
return fmt::format("// Unhandled VU0 Special2 fhi_flo: 0x{:X}", vu_fhi_flo);
|
||||
}
|
||||
}
|
||||
else // Special1 Table
|
||||
|
||||
// Special1 Table (function-based)
|
||||
switch (vu_func)
|
||||
{
|
||||
switch (vu_func)
|
||||
{
|
||||
case VU0_S1_VADDx:
|
||||
case VU0_S1_VADDy:
|
||||
case VU0_S1_VADDz:
|
||||
case VU0_S1_VADDw:
|
||||
return translateVU_VADD_Field(inst);
|
||||
case VU0_S1_VSUBx:
|
||||
case VU0_S1_VSUBy:
|
||||
case VU0_S1_VSUBz:
|
||||
case VU0_S1_VSUBw:
|
||||
return translateVU_VSUB_Field(inst);
|
||||
case VU0_S1_VMULx:
|
||||
case VU0_S1_VMULy:
|
||||
case VU0_S1_VMULz:
|
||||
case VU0_S1_VMULw:
|
||||
return translateVU_VMUL_Field(inst);
|
||||
case VU0_S1_VADD:
|
||||
return translateVU_VADD(inst);
|
||||
case VU0_S1_VSUB:
|
||||
return translateVU_VSUB(inst);
|
||||
case VU0_S1_VMUL:
|
||||
return translateVU_VMUL(inst);
|
||||
case VU0_S1_VIADD:
|
||||
return translateVU_VIADD(inst);
|
||||
case VU0_S1_VISUB:
|
||||
return translateVU_VISUB(inst);
|
||||
case VU0_S1_VIADDI:
|
||||
return translateVU_VIADDI(inst);
|
||||
case VU0_S1_VIAND:
|
||||
return translateVU_VIAND(inst);
|
||||
case VU0_S1_VIOR:
|
||||
return translateVU_VIOR(inst);
|
||||
case VU0_S1_VCALLMS:
|
||||
return translateVU_VCALLMS(inst);
|
||||
case VU0_S1_VCALLMSR:
|
||||
return translateVU_VCALLMSR(inst);
|
||||
case VU0_S1_VADDq:
|
||||
return fmt::format("ctx->vu0_vf[{}] = PS2_VADD(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_q));", inst.rd, inst.rs);
|
||||
case VU0_S1_VSUBq:
|
||||
return fmt::format("ctx->vu0_vf[{}] = PS2_VSUB(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_q));", inst.rd, inst.rs);
|
||||
case VU0_S1_VMULq:
|
||||
return fmt::format("ctx->vu0_vf[{}] = PS2_VMUL(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_q));", inst.rd, inst.rs);
|
||||
case VU0_S1_VADDi:
|
||||
return fmt::format("ctx->vu0_vf[{}] = PS2_VADD(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_i));", inst.rd, inst.rs);
|
||||
case VU0_S1_VSUBi:
|
||||
return fmt::format("ctx->vu0_vf[{}] = PS2_VSUB(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_i));", inst.rd, inst.rs);
|
||||
case VU0_S1_VMULi:
|
||||
return fmt::format("ctx->vu0_vf[{}] = PS2_VMUL(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_i));", inst.rd, inst.rs);
|
||||
case VU0_S1_VMADDx:
|
||||
case VU0_S1_VMADDy:
|
||||
case VU0_S1_VMADDz:
|
||||
case VU0_S1_VMADDw:
|
||||
return translateVU_VMADD_Field(inst);
|
||||
case VU0_S1_VMAXx:
|
||||
return fmt::format("ctx->vu0_vf[{}] = _mm_max_ps(ctx->vu0_vf[{}], _mm_shuffle_ps(ctx->vu0_vf[{}], ctx->vu0_vf[{}], _MM_SHUFFLE(0,0,0,0)));", inst.rd, inst.rs, inst.rt, inst.rt);
|
||||
case VU0_S1_VMAXz:
|
||||
return fmt::format("ctx->vu0_vf[{}] = _mm_max_ps(ctx->vu0_vf[{}], _mm_shuffle_ps(ctx->vu0_vf[{}], ctx->vu0_vf[{}], _MM_SHUFFLE(2,2,2,2)));", inst.rd, inst.rs, inst.rt, inst.rt);
|
||||
case VU0_S1_VMINIx:
|
||||
case VU0_S1_VMINIy:
|
||||
case VU0_S1_VMINIw:
|
||||
return translateVU_VMINI_Field(inst);
|
||||
case VU0_S1_VMADD:
|
||||
return translateVU_VMADD(inst);
|
||||
case VU0_S1_VMAX:
|
||||
return translateVU_VMAX(inst);
|
||||
case VU0_S1_VOPMSUB:
|
||||
return translateVU_VOPMSUB(inst);
|
||||
case VU0_S1_VMINI:
|
||||
return translateVU_VMINI(inst);
|
||||
default:
|
||||
return fmt::format("// Unhandled VU0 Special1 function: 0x{:X}", vu_func);
|
||||
}
|
||||
case VU0_S1_VADDx:
|
||||
case VU0_S1_VADDy:
|
||||
case VU0_S1_VADDz:
|
||||
case VU0_S1_VADDw:
|
||||
return translateVU_VADD_Field(inst);
|
||||
case VU0_S1_VSUBx:
|
||||
case VU0_S1_VSUBy:
|
||||
case VU0_S1_VSUBz:
|
||||
case VU0_S1_VSUBw:
|
||||
return translateVU_VSUB_Field(inst);
|
||||
case VU0_S1_VMULx:
|
||||
case VU0_S1_VMULy:
|
||||
case VU0_S1_VMULz:
|
||||
case VU0_S1_VMULw:
|
||||
return translateVU_VMUL_Field(inst);
|
||||
case VU0_S1_VADD:
|
||||
return translateVU_VADD(inst);
|
||||
case VU0_S1_VSUB:
|
||||
return translateVU_VSUB(inst);
|
||||
case VU0_S1_VMUL:
|
||||
return translateVU_VMUL(inst);
|
||||
case VU0_S1_VIADD:
|
||||
return translateVU_VIADD(inst);
|
||||
case VU0_S1_VISUB:
|
||||
return translateVU_VISUB(inst);
|
||||
case VU0_S1_VIADDI:
|
||||
return translateVU_VIADDI(inst);
|
||||
case VU0_S1_VIAND:
|
||||
return translateVU_VIAND(inst);
|
||||
case VU0_S1_VIOR:
|
||||
return translateVU_VIOR(inst);
|
||||
case VU0_S1_VCALLMS:
|
||||
return translateVU_VCALLMS(inst);
|
||||
case VU0_S1_VCALLMSR:
|
||||
return translateVU_VCALLMSR(inst);
|
||||
case VU0_S1_VADDq:
|
||||
return fmt::format("ctx->vu0_vf[{}] = PS2_VADD(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_q));", inst.rd, inst.rs);
|
||||
case VU0_S1_VSUBq:
|
||||
return fmt::format("ctx->vu0_vf[{}] = PS2_VSUB(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_q));", inst.rd, inst.rs);
|
||||
case VU0_S1_VMULq:
|
||||
return fmt::format("ctx->vu0_vf[{}] = PS2_VMUL(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_q));", inst.rd, inst.rs);
|
||||
case VU0_S1_VADDi:
|
||||
return fmt::format("ctx->vu0_vf[{}] = PS2_VADD(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_i));", inst.rd, inst.rs);
|
||||
case VU0_S1_VSUBi:
|
||||
return fmt::format("ctx->vu0_vf[{}] = PS2_VSUB(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_i));", inst.rd, inst.rs);
|
||||
case VU0_S1_VMULi:
|
||||
return fmt::format("ctx->vu0_vf[{}] = PS2_VMUL(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_i));", inst.rd, inst.rs);
|
||||
case VU0_S1_VMADDx:
|
||||
case VU0_S1_VMADDy:
|
||||
case VU0_S1_VMADDz:
|
||||
case VU0_S1_VMADDw:
|
||||
return translateVU_VMADD_Field(inst);
|
||||
case VU0_S1_VMSUBx:
|
||||
case VU0_S1_VMSUBy:
|
||||
case VU0_S1_VMSUBz:
|
||||
case VU0_S1_VMSUBw:
|
||||
return translateVU_VMSUB_Field(inst);
|
||||
case VU0_S1_VMAXx:
|
||||
case VU0_S1_VMAXy:
|
||||
case VU0_S1_VMAXz:
|
||||
case VU0_S1_VMAXw:
|
||||
return translateVU_VMAX_Field(inst);
|
||||
case VU0_S1_VMINIx:
|
||||
case VU0_S1_VMINIy:
|
||||
case VU0_S1_VMINIz:
|
||||
case VU0_S1_VMINIw:
|
||||
return translateVU_VMINI_Field(inst);
|
||||
case VU0_S1_VMAXi:
|
||||
return translateVU_VMAXi(inst);
|
||||
case VU0_S1_VMINIi:
|
||||
return translateVU_VMINIi(inst);
|
||||
case VU0_S1_VMADD:
|
||||
return translateVU_VMADD(inst);
|
||||
case VU0_S1_VMADDq:
|
||||
return translateVU_VMADDq(inst);
|
||||
case VU0_S1_VMADDi:
|
||||
return translateVU_VMADDi(inst);
|
||||
case VU0_S1_VMAX:
|
||||
return translateVU_VMAX(inst);
|
||||
case VU0_S1_VOPMSUB:
|
||||
return translateVU_VOPMSUB(inst);
|
||||
case VU0_S1_VMINI:
|
||||
return translateVU_VMINI(inst);
|
||||
case VU0_S1_VMSUB:
|
||||
return translateVU_VMSUB(inst);
|
||||
case VU0_S1_VMSUBq:
|
||||
return translateVU_VMSUBq(inst);
|
||||
case VU0_S1_VMSUBi:
|
||||
return translateVU_VMSUBi(inst);
|
||||
default:
|
||||
return fmt::format("// Unhandled VU0 Special1 function: 0x{:X}", vu_func);
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
return fmt::format("// Unhandled COP2 format: 0x{:X}", format);
|
||||
}
|
||||
@@ -1894,19 +2025,25 @@ namespace ps2recomp
|
||||
std::string CodeGenerator::translateVU_VADD_Field(const Instruction &inst)
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
return fmt::format("{{ __m128 res = PS2_VADD(ctx->vu0_vf[{}], ctx->vu0_vf[{}]); __m128i mask = _mm_set_epi32({}, {}, {}, {}); ctx->vu0_vf[{}] = PS2_VBLEND(ctx->vu0_vf[{}], res, _mm_castsi128_ps(mask)); }}", inst.rs, inst.rt, (dest_mask & 0x8) ? -1 : 0, (dest_mask & 0x4) ? -1 : 0, (dest_mask & 0x2) ? -1 : 0, (dest_mask & 0x1) ? -1 : 0, inst.rd, inst.rd);
|
||||
uint8_t field = inst.function & 0x3;
|
||||
std::string shuffle_pattern = fmt::format("_MM_SHUFFLE({},{},{},{})", field, field, field, field);
|
||||
return fmt::format("{{ __m128 res = PS2_VADD(ctx->vu0_vf[{}], _mm_shuffle_ps(ctx->vu0_vf[{}], ctx->vu0_vf[{}], {})); __m128i mask = _mm_set_epi32({}, {}, {}, {}); ctx->vu0_vf[{}] = _mm_blendv_ps(ctx->vu0_vf[{}], res, _mm_castsi128_ps(mask)); }}", inst.rs, inst.rt, inst.rt, shuffle_pattern, (dest_mask & 0x8) ? -1 : 0, (dest_mask & 0x4) ? -1 : 0, (dest_mask & 0x2) ? -1 : 0, (dest_mask & 0x1) ? -1 : 0, inst.rd, inst.rd);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VSUB_Field(const Instruction &inst)
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
return fmt::format("{{ __m128 res = PS2_VSUB(ctx->vu0_vf[{}], ctx->vu0_vf[{}]); __m128i mask = _mm_set_epi32({}, {}, {}, {}); ctx->vu0_vf[{}] = PS2_VBLEND(ctx->vu0_vf[{}], res, _mm_castsi128_ps(mask)); }}", inst.rs, inst.rt, (dest_mask & 0x8) ? -1 : 0, (dest_mask & 0x4) ? -1 : 0, (dest_mask & 0x2) ? -1 : 0, (dest_mask & 0x1) ? -1 : 0, inst.rd, inst.rd);
|
||||
uint8_t field = inst.function & 0x3;
|
||||
std::string shuffle_pattern = fmt::format("_MM_SHUFFLE({},{},{},{})", field, field, field, field);
|
||||
return fmt::format("{{ __m128 res = PS2_VSUB(ctx->vu0_vf[{}], _mm_shuffle_ps(ctx->vu0_vf[{}], ctx->vu0_vf[{}], {})); __m128i mask = _mm_set_epi32({}, {}, {}, {}); ctx->vu0_vf[{}] = _mm_blendv_ps(ctx->vu0_vf[{}], res, _mm_castsi128_ps(mask)); }}", inst.rs, inst.rt, inst.rt, shuffle_pattern, (dest_mask & 0x8) ? -1 : 0, (dest_mask & 0x4) ? -1 : 0, (dest_mask & 0x2) ? -1 : 0, (dest_mask & 0x1) ? -1 : 0, inst.rd, inst.rd);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMUL_Field(const Instruction &inst)
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
return fmt::format("{{ __m128 res = PS2_VMUL(ctx->vu0_vf[{}], ctx->vu0_vf[{}]); __m128i mask = _mm_set_epi32({}, {}, {}, {}); ctx->vu0_vf[{}] = PS2_VBLEND(ctx->vu0_vf[{}], res, _mm_castsi128_ps(mask)); }}", inst.rs, inst.rt, (dest_mask & 0x8) ? -1 : 0, (dest_mask & 0x4) ? -1 : 0, (dest_mask & 0x2) ? -1 : 0, (dest_mask & 0x1) ? -1 : 0, inst.rd, inst.rd);
|
||||
uint8_t field = inst.function & 0x3;
|
||||
std::string shuffle_pattern = fmt::format("_MM_SHUFFLE({},{},{},{})", field, field, field, field);
|
||||
return fmt::format("{{ __m128 res = PS2_VMUL(ctx->vu0_vf[{}], _mm_shuffle_ps(ctx->vu0_vf[{}], ctx->vu0_vf[{}], {})); __m128i mask = _mm_set_epi32({}, {}, {}, {}); ctx->vu0_vf[{}] = _mm_blendv_ps(ctx->vu0_vf[{}], res, _mm_castsi128_ps(mask)); }}", inst.rs, inst.rt, inst.rt, shuffle_pattern, (dest_mask & 0x8) ? -1 : 0, (dest_mask & 0x4) ? -1 : 0, (dest_mask & 0x2) ? -1 : 0, (dest_mask & 0x1) ? -1 : 0, inst.rd, inst.rd);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VADD(const Instruction &inst)
|
||||
@@ -2268,6 +2405,24 @@ namespace ps2recomp
|
||||
inst.rd, inst.rd);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMSUB_Field(const Instruction &inst)
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
uint8_t field = inst.function & 0x3; // Extract field from function code
|
||||
|
||||
std::string shuffle_pattern = fmt::format("_MM_SHUFFLE({},{},{},{})", field, field, field, field);
|
||||
|
||||
return fmt::format("{{ __m128 mul_res = PS2_VMUL(ctx->vu0_vf[{}], _mm_shuffle_ps(ctx->vu0_vf[{}], ctx->vu0_vf[{}], {})); "
|
||||
"__m128 res = PS2_VSUB(ctx->vu0_acc, mul_res); "
|
||||
"__m128i mask = _mm_set_epi32({}, {}, {}, {}); "
|
||||
"ctx->vu0_vf[{}] = _mm_blendv_ps(ctx->vu0_vf[{}], res, _mm_castsi128_ps(mask)); "
|
||||
"ctx->vu0_acc = res; }}",
|
||||
inst.rs, inst.rt, inst.rt, shuffle_pattern,
|
||||
(dest_mask & 0x8) ? -1 : 0, (dest_mask & 0x4) ? -1 : 0,
|
||||
(dest_mask & 0x2) ? -1 : 0, (dest_mask & 0x1) ? -1 : 0,
|
||||
inst.rd, inst.rd);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMINI_Field(const Instruction &inst)
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
@@ -2284,6 +2439,22 @@ namespace ps2recomp
|
||||
inst.rd, inst.rd);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMAX_Field(const Instruction &inst)
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
uint8_t field = inst.function & 0x3;
|
||||
|
||||
std::string shuffle_pattern = fmt::format("_MM_SHUFFLE({},{},{},{})", field, field, field, field);
|
||||
|
||||
return fmt::format("{{ __m128 res = _mm_max_ps(ctx->vu0_vf[{}], _mm_shuffle_ps(ctx->vu0_vf[{}], ctx->vu0_vf[{}], {})); "
|
||||
"__m128i mask = _mm_set_epi32({}, {}, {}, {}); "
|
||||
"ctx->vu0_vf[{}] = _mm_blendv_ps(ctx->vu0_vf[{}], res, _mm_castsi128_ps(mask)); }}",
|
||||
inst.rs, inst.rt, inst.rt, shuffle_pattern,
|
||||
(dest_mask & 0x8) ? -1 : 0, (dest_mask & 0x4) ? -1 : 0,
|
||||
(dest_mask & 0x2) ? -1 : 0, (dest_mask & 0x1) ? -1 : 0,
|
||||
inst.rd, inst.rd);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMADD(const Instruction &inst)
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
@@ -2298,6 +2469,34 @@ namespace ps2recomp
|
||||
inst.rd, inst.rd);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMADDq(const Instruction &inst)
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
return fmt::format("{{ __m128 mul_res = PS2_VMUL(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_q)); "
|
||||
"__m128 res = PS2_VADD(ctx->vu0_acc, mul_res); "
|
||||
"__m128i mask = _mm_set_epi32({}, {}, {}, {}); "
|
||||
"ctx->vu0_vf[{}] = _mm_blendv_ps(ctx->vu0_vf[{}], res, _mm_castsi128_ps(mask)); "
|
||||
"ctx->vu0_acc = res; }}",
|
||||
inst.rs,
|
||||
(dest_mask & 0x8) ? -1 : 0, (dest_mask & 0x4) ? -1 : 0,
|
||||
(dest_mask & 0x2) ? -1 : 0, (dest_mask & 0x1) ? -1 : 0,
|
||||
inst.rd, inst.rd);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMADDi(const Instruction &inst)
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
return fmt::format("{{ __m128 mul_res = PS2_VMUL(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_i)); "
|
||||
"__m128 res = PS2_VADD(ctx->vu0_acc, mul_res); "
|
||||
"__m128i mask = _mm_set_epi32({}, {}, {}, {}); "
|
||||
"ctx->vu0_vf[{}] = _mm_blendv_ps(ctx->vu0_vf[{}], res, _mm_castsi128_ps(mask)); "
|
||||
"ctx->vu0_acc = res; }}",
|
||||
inst.rs,
|
||||
(dest_mask & 0x8) ? -1 : 0, (dest_mask & 0x4) ? -1 : 0,
|
||||
(dest_mask & 0x2) ? -1 : 0, (dest_mask & 0x1) ? -1 : 0,
|
||||
inst.rd, inst.rd);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMAX(const Instruction &inst)
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
@@ -2310,6 +2509,18 @@ namespace ps2recomp
|
||||
inst.rd, inst.rd);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMAXi(const Instruction &inst)
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
return fmt::format("{{ __m128 res = _mm_max_ps(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_i)); "
|
||||
"__m128i mask = _mm_set_epi32({}, {}, {}, {}); "
|
||||
"ctx->vu0_vf[{}] = _mm_blendv_ps(ctx->vu0_vf[{}], res, _mm_castsi128_ps(mask)); }}",
|
||||
inst.rs,
|
||||
(dest_mask & 0x8) ? -1 : 0, (dest_mask & 0x4) ? -1 : 0,
|
||||
(dest_mask & 0x2) ? -1 : 0, (dest_mask & 0x1) ? -1 : 0,
|
||||
inst.rd, inst.rd);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VOPMSUB(const Instruction &inst)
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
@@ -2336,6 +2547,307 @@ namespace ps2recomp
|
||||
inst.rd, inst.rd);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMINIi(const Instruction &inst)
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
return fmt::format("{{ __m128 res = _mm_min_ps(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_i)); "
|
||||
"__m128i mask = _mm_set_epi32({}, {}, {}, {}); "
|
||||
"ctx->vu0_vf[{}] = _mm_blendv_ps(ctx->vu0_vf[{}], res, _mm_castsi128_ps(mask)); }}",
|
||||
inst.rs,
|
||||
(dest_mask & 0x8) ? -1 : 0, (dest_mask & 0x4) ? -1 : 0,
|
||||
(dest_mask & 0x2) ? -1 : 0, (dest_mask & 0x1) ? -1 : 0,
|
||||
inst.rd, inst.rd);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMSUB(const Instruction &inst)
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
return fmt::format("{{ __m128 mul_res = PS2_VMUL(ctx->vu0_vf[{}], ctx->vu0_vf[{}]); "
|
||||
"__m128 res = PS2_VSUB(ctx->vu0_acc, mul_res); "
|
||||
"__m128i mask = _mm_set_epi32({}, {}, {}, {}); "
|
||||
"ctx->vu0_vf[{}] = _mm_blendv_ps(ctx->vu0_vf[{}], res, _mm_castsi128_ps(mask)); "
|
||||
"ctx->vu0_acc = res; }}",
|
||||
inst.rs, inst.rt,
|
||||
(dest_mask & 0x8) ? -1 : 0, (dest_mask & 0x4) ? -1 : 0,
|
||||
(dest_mask & 0x2) ? -1 : 0, (dest_mask & 0x1) ? -1 : 0,
|
||||
inst.rd, inst.rd);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMSUBq(const Instruction &inst)
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
return fmt::format("{{ __m128 mul_res = PS2_VMUL(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_q)); "
|
||||
"__m128 res = PS2_VSUB(ctx->vu0_acc, mul_res); "
|
||||
"__m128i mask = _mm_set_epi32({}, {}, {}, {}); "
|
||||
"ctx->vu0_vf[{}] = _mm_blendv_ps(ctx->vu0_vf[{}], res, _mm_castsi128_ps(mask)); "
|
||||
"ctx->vu0_acc = res; }}",
|
||||
inst.rs,
|
||||
(dest_mask & 0x8) ? -1 : 0, (dest_mask & 0x4) ? -1 : 0,
|
||||
(dest_mask & 0x2) ? -1 : 0, (dest_mask & 0x1) ? -1 : 0,
|
||||
inst.rd, inst.rd);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMSUBi(const Instruction &inst)
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
return fmt::format("{{ __m128 mul_res = PS2_VMUL(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_i)); "
|
||||
"__m128 res = PS2_VSUB(ctx->vu0_acc, mul_res); "
|
||||
"__m128i mask = _mm_set_epi32({}, {}, {}, {}); "
|
||||
"ctx->vu0_vf[{}] = _mm_blendv_ps(ctx->vu0_vf[{}], res, _mm_castsi128_ps(mask)); "
|
||||
"ctx->vu0_acc = res; }}",
|
||||
inst.rs,
|
||||
(dest_mask & 0x8) ? -1 : 0, (dest_mask & 0x4) ? -1 : 0,
|
||||
(dest_mask & 0x2) ? -1 : 0, (dest_mask & 0x1) ? -1 : 0,
|
||||
inst.rd, inst.rd);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VADDA_Field(const Instruction &inst)
|
||||
{
|
||||
uint8_t field = inst.function & 0x3;
|
||||
std::string shuffle_pattern = fmt::format("_MM_SHUFFLE({},{},{},{})", field, field, field, field);
|
||||
|
||||
return fmt::format("{{ __m128 res = PS2_VADD(ctx->vu0_vf[{}], _mm_shuffle_ps(ctx->vu0_vf[{}], ctx->vu0_vf[{}], {})); "
|
||||
"ctx->vu0_acc = res; }}",
|
||||
inst.rs, inst.rt, inst.rt, shuffle_pattern);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VSUBA_Field(const Instruction &inst)
|
||||
{
|
||||
uint8_t field = inst.function & 0x3;
|
||||
std::string shuffle_pattern = fmt::format("_MM_SHUFFLE({},{},{},{})", field, field, field, field);
|
||||
|
||||
return fmt::format("{{ __m128 res = PS2_VSUB(ctx->vu0_vf[{}], _mm_shuffle_ps(ctx->vu0_vf[{}], ctx->vu0_vf[{}], {})); "
|
||||
"ctx->vu0_acc = res; }}",
|
||||
inst.rs, inst.rt, inst.rt, shuffle_pattern);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMADDA_Field(const Instruction &inst)
|
||||
{
|
||||
uint8_t field = inst.function & 0x3;
|
||||
std::string shuffle_pattern = fmt::format("_MM_SHUFFLE({},{},{},{})", field, field, field, field);
|
||||
|
||||
return fmt::format("{{ __m128 mul_res = PS2_VMUL(ctx->vu0_vf[{}], _mm_shuffle_ps(ctx->vu0_vf[{}], ctx->vu0_vf[{}], {})); "
|
||||
"__m128 res = PS2_VADD(ctx->vu0_acc, mul_res); "
|
||||
"ctx->vu0_acc = res; }}",
|
||||
inst.rs, inst.rt, inst.rt, shuffle_pattern);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMSUBA_Field(const Instruction &inst)
|
||||
{
|
||||
uint8_t field = inst.function & 0x3;
|
||||
std::string shuffle_pattern = fmt::format("_MM_SHUFFLE({},{},{},{})", field, field, field, field);
|
||||
|
||||
return fmt::format("{{ __m128 mul_res = PS2_VMUL(ctx->vu0_vf[{}], _mm_shuffle_ps(ctx->vu0_vf[{}], ctx->vu0_vf[{}], {})); "
|
||||
"__m128 res = PS2_VSUB(ctx->vu0_acc, mul_res); "
|
||||
"ctx->vu0_acc = res; }}",
|
||||
inst.rs, inst.rt, inst.rt, shuffle_pattern);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMULA_Field(const Instruction &inst)
|
||||
{
|
||||
uint8_t field = inst.function & 0x3;
|
||||
std::string shuffle_pattern = fmt::format("_MM_SHUFFLE({},{},{},{})", field, field, field, field);
|
||||
|
||||
return fmt::format("{{ __m128 res = PS2_VMUL(ctx->vu0_vf[{}], _mm_shuffle_ps(ctx->vu0_vf[{}], ctx->vu0_vf[{}], {})); "
|
||||
"ctx->vu0_acc = res; }}",
|
||||
inst.rs, inst.rt, inst.rt, shuffle_pattern);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VADDA(const Instruction &inst)
|
||||
{
|
||||
return fmt::format("ctx->vu0_acc = PS2_VADD(ctx->vu0_vf[{}], ctx->vu0_vf[{}]);",
|
||||
inst.rs, inst.rt);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VADDAq(const Instruction &inst)
|
||||
{
|
||||
return fmt::format("ctx->vu0_acc = PS2_VADD(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_q));",
|
||||
inst.rs);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VADDAi(const Instruction &inst)
|
||||
{
|
||||
return fmt::format("ctx->vu0_acc = PS2_VADD(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_i));",
|
||||
inst.rs);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VSUBA(const Instruction &inst)
|
||||
{
|
||||
return fmt::format("ctx->vu0_acc = PS2_VSUB(ctx->vu0_vf[{}], ctx->vu0_vf[{}]);",
|
||||
inst.rs, inst.rt);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VSUBAq(const Instruction &inst)
|
||||
{
|
||||
return fmt::format("ctx->vu0_acc = PS2_VSUB(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_q));",
|
||||
inst.rs);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VSUBAi(const Instruction &inst)
|
||||
{
|
||||
return fmt::format("ctx->vu0_acc = PS2_VSUB(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_i));",
|
||||
inst.rs);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMADDA(const Instruction &inst)
|
||||
{
|
||||
return fmt::format("{{ __m128 mul_res = PS2_VMUL(ctx->vu0_vf[{}], ctx->vu0_vf[{}]); "
|
||||
"ctx->vu0_acc = PS2_VADD(ctx->vu0_acc, mul_res); }}",
|
||||
inst.rs, inst.rt);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMADDAq(const Instruction &inst)
|
||||
{
|
||||
return fmt::format("{{ __m128 mul_res = PS2_VMUL(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_q)); "
|
||||
"ctx->vu0_acc = PS2_VADD(ctx->vu0_acc, mul_res); }}",
|
||||
inst.rs);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMADDAi(const Instruction &inst)
|
||||
{
|
||||
return fmt::format("{{ __m128 mul_res = PS2_VMUL(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_i)); "
|
||||
"ctx->vu0_acc = PS2_VADD(ctx->vu0_acc, mul_res); }}",
|
||||
inst.rs);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMSUBA(const Instruction &inst)
|
||||
{
|
||||
return fmt::format("{{ __m128 mul_res = PS2_VMUL(ctx->vu0_vf[{}], ctx->vu0_vf[{}]); "
|
||||
"ctx->vu0_acc = PS2_VSUB(ctx->vu0_acc, mul_res); }}",
|
||||
inst.rs, inst.rt);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMSUBAq(const Instruction &inst)
|
||||
{
|
||||
return fmt::format("{{ __m128 mul_res = PS2_VMUL(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_q)); "
|
||||
"ctx->vu0_acc = PS2_VSUB(ctx->vu0_acc, mul_res); }}",
|
||||
inst.rs);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMSUBAi(const Instruction &inst)
|
||||
{
|
||||
return fmt::format("{{ __m128 mul_res = PS2_VMUL(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_i)); "
|
||||
"ctx->vu0_acc = PS2_VSUB(ctx->vu0_acc, mul_res); }}",
|
||||
inst.rs);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMULA(const Instruction &inst)
|
||||
{
|
||||
return fmt::format("ctx->vu0_acc = PS2_VMUL(ctx->vu0_vf[{}], ctx->vu0_vf[{}]);",
|
||||
inst.rs, inst.rt);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMULAq(const Instruction &inst)
|
||||
{
|
||||
return fmt::format("ctx->vu0_acc = PS2_VMUL(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_q));",
|
||||
inst.rs);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VMULAi(const Instruction &inst)
|
||||
{
|
||||
return fmt::format("ctx->vu0_acc = PS2_VMUL(ctx->vu0_vf[{}], _mm_set1_ps(ctx->vu0_i));",
|
||||
inst.rs);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VOPMULA(const Instruction &inst)
|
||||
{
|
||||
return fmt::format("ctx->vu0_acc = PS2_VMUL(ctx->vu0_vf[{}], ctx->vu0_vf[{}]);",
|
||||
inst.rs, inst.rt);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VITOF(const Instruction &inst, int shift)
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
float scale = (shift == 0) ? 1.0f : (1.0f / static_cast<float>(1 << shift));
|
||||
|
||||
return fmt::format("{{ __m128i src = _mm_castps_si128(ctx->vu0_vf[{}]); "
|
||||
"__m128 res = _mm_cvtepi32_ps(src); "
|
||||
"res = _mm_mul_ps(res, _mm_set1_ps({}f)); "
|
||||
"__m128i mask = _mm_set_epi32({}, {}, {}, {}); "
|
||||
"ctx->vu0_vf[{}] = _mm_blendv_ps(ctx->vu0_vf[{}], res, _mm_castsi128_ps(mask)); }}",
|
||||
inst.rs, scale,
|
||||
(dest_mask & 0x8) ? -1 : 0, (dest_mask & 0x4) ? -1 : 0,
|
||||
(dest_mask & 0x2) ? -1 : 0, (dest_mask & 0x1) ? -1 : 0,
|
||||
inst.rt, inst.rt);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VFTOI(const Instruction &inst, int shift)
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
float scale = (shift == 0) ? 1.0f : static_cast<float>(1 << shift);
|
||||
|
||||
return fmt::format("{{ __m128 src = ctx->vu0_vf[{}]; "
|
||||
"src = _mm_mul_ps(src, _mm_set1_ps({}f)); "
|
||||
"__m128i res_i = _mm_cvttps_epi32(src); "
|
||||
"__m128 res = _mm_castsi128_ps(res_i); "
|
||||
"__m128i mask = _mm_set_epi32({}, {}, {}, {}); "
|
||||
"ctx->vu0_vf[{}] = _mm_blendv_ps(ctx->vu0_vf[{}], res, _mm_castsi128_ps(mask)); }}",
|
||||
inst.rs, scale,
|
||||
(dest_mask & 0x8) ? -1 : 0, (dest_mask & 0x4) ? -1 : 0,
|
||||
(dest_mask & 0x2) ? -1 : 0, (dest_mask & 0x1) ? -1 : 0,
|
||||
inst.rt, inst.rt);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VLQI(const Instruction &inst)
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
return fmt::format("{{ uint32_t addr = ((uint32_t)(ctx->vi[{}] & 0x3FF)) << 4; "
|
||||
"__m128 res = _mm_castsi128_ps(READ128(addr)); "
|
||||
"__m128i mask = _mm_set_epi32({}, {}, {}, {}); "
|
||||
"ctx->vu0_vf[{}] = _mm_blendv_ps(ctx->vu0_vf[{}], res, _mm_castsi128_ps(mask)); "
|
||||
"ctx->vi[{}] = (ctx->vi[{}] + 1) & 0x3FF; }}",
|
||||
inst.rs,
|
||||
(dest_mask & 0x8) ? -1 : 0, (dest_mask & 0x4) ? -1 : 0,
|
||||
(dest_mask & 0x2) ? -1 : 0, (dest_mask & 0x1) ? -1 : 0,
|
||||
inst.rt, inst.rt,
|
||||
inst.rs, inst.rs);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VSQI(const Instruction &inst)
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
return fmt::format("{{ uint32_t addr = ((uint32_t)(ctx->vi[{}] & 0x3FF)) << 4; "
|
||||
"__m128i old_val = READ128(addr); "
|
||||
"__m128 res = _mm_blendv_ps(_mm_castsi128_ps(old_val), ctx->vu0_vf[{}], _mm_castsi128_ps(_mm_set_epi32({}, {}, {}, {}))); "
|
||||
"WRITE128(addr, _mm_castps_si128(res)); "
|
||||
"ctx->vi[{}] = (ctx->vi[{}] + 1) & 0x3FF; }}",
|
||||
inst.rs,
|
||||
inst.rt,
|
||||
(dest_mask & 0x8) ? -1 : 0, (dest_mask & 0x4) ? -1 : 0,
|
||||
(dest_mask & 0x2) ? -1 : 0, (dest_mask & 0x1) ? -1 : 0,
|
||||
inst.rs, inst.rs);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VLQD(const Instruction &inst)
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
return fmt::format("{{ ctx->vi[{}] = (ctx->vi[{}] - 1) & 0x3FF; "
|
||||
"uint32_t addr = ((uint32_t)(ctx->vi[{}] & 0x3FF)) << 4; "
|
||||
"__m128 res = _mm_castsi128_ps(READ128(addr)); "
|
||||
"__m128i mask = _mm_set_epi32({}, {}, {}, {}); "
|
||||
"ctx->vu0_vf[{}] = _mm_blendv_ps(ctx->vu0_vf[{}], res, _mm_castsi128_ps(mask)); }}",
|
||||
inst.rs, inst.rs,
|
||||
inst.rs,
|
||||
(dest_mask & 0x8) ? -1 : 0, (dest_mask & 0x4) ? -1 : 0,
|
||||
(dest_mask & 0x2) ? -1 : 0, (dest_mask & 0x1) ? -1 : 0,
|
||||
inst.rt, inst.rt);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VSQD(const Instruction &inst)
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
return fmt::format("{{ ctx->vi[{}] = (ctx->vi[{}] - 1) & 0x3FF; "
|
||||
"uint32_t addr = ((uint32_t)(ctx->vi[{}] & 0x3FF)) << 4; "
|
||||
"__m128i old_val = READ128(addr); "
|
||||
"__m128 res = _mm_blendv_ps(_mm_castsi128_ps(old_val), ctx->vu0_vf[{}], _mm_castsi128_ps(_mm_set_epi32({}, {}, {}, {}))); "
|
||||
"WRITE128(addr, _mm_castps_si128(res)); }}",
|
||||
inst.rs, inst.rs,
|
||||
inst.rs,
|
||||
inst.rt,
|
||||
(dest_mask & 0x8) ? -1 : 0, (dest_mask & 0x4) ? -1 : 0,
|
||||
(dest_mask & 0x2) ? -1 : 0, (dest_mask & 0x1) ? -1 : 0);
|
||||
}
|
||||
|
||||
std::string CodeGenerator::translateVU_VRGET(const Instruction &inst)
|
||||
{
|
||||
uint8_t dest_mask = inst.vectorInfo.vectorField;
|
||||
|
||||
Reference in New Issue
Block a user