diff --git a/src/xenia/cpu/ppc/instr.h b/src/xenia/cpu/ppc/instr.h index b07d1c6d6..b5ecac3a9 100644 --- a/src/xenia/cpu/ppc/instr.h +++ b/src/xenia/cpu/ppc/instr.h @@ -332,6 +332,19 @@ typedef struct { } VX128_4; // kXEPPCInstrFormatVX128_5 struct { + // VD128 = VD128l | (VD128h << 5) + // VA128 = VA128l | (VA128h << 5) | (VA128H << 6) + // VB128 = VB128l | (VB128h << 5) + uint32_t VB128h : 2; + uint32_t VD128h : 2; + uint32_t : 1; + uint32_t VA128h : 1; + uint32_t SH : 4; + uint32_t VA128H : 1; + uint32_t VB128l : 5; + uint32_t VA128l : 5; + uint32_t VD128l : 5; + uint32_t : 6; } VX128_5; // kXEPPCInstrFormatVX128_P struct { diff --git a/src/xenia/cpu/x64/x64_emit_altivec.cc b/src/xenia/cpu/x64/x64_emit_altivec.cc index 6cf9d205b..2f13642b1 100644 --- a/src/xenia/cpu/x64/x64_emit_altivec.cc +++ b/src/xenia/cpu/x64/x64_emit_altivec.cc @@ -48,6 +48,10 @@ namespace x64 { #define VX128_3_VD128 (i.VX128_3.VD128l | (i.VX128_3.VD128h << 5)) #define VX128_3_VB128 (i.VX128_3.VB128l | (i.VX128_3.VB128h << 5)) #define VX128_3_IMM (i.VX128_3.IMM) +#define VX128_5_VD128 (i.VX128_5.VD128l | (i.VX128_5.VD128h << 5)) +#define VX128_5_VA128 (i.VX128_5.VA128l | (i.VX128_5.VA128h << 5)) +#define VX128_5_VB128 (i.VX128_5.VB128l | (i.VX128_5.VB128h << 5)) +#define VX128_5_SH (i.VX128_5.SH) #define VX128_R_VD128 (i.VX128_R.VD128l | (i.VX128_R.VD128h << 5)) #define VX128_R_VA128 (i.VX128_R.VA128l | (i.VX128_R.VA128h << 5) | (i.VX128_R.VA128H << 6)) #define VX128_R_VB128 (i.VX128_R.VB128l | (i.VX128_R.VB128h << 5)) @@ -1184,7 +1188,6 @@ __m128i __emulated_vperm(__m128i va, __m128i vb, __m128i vc) { } int InstrEmit_vperm_(X64Emitter& e, X86Compiler& c, uint32_t vd, uint32_t va, uint32_t vb, uint32_t vc) { // Call emulation function. - XmmVar tva(c.newXmmVar()), tvb(c.newXmmVar()), tvc(c.newXmmVar()); GpVar pva(c.newGpVar()), pvb(c.newGpVar()), pvc(c.newGpVar()); c.lea(pva, e.vr_value(va).m128()); c.lea(pvb, e.vr_value(vb).m128()); @@ -1453,13 +1456,37 @@ XEEMITTER(vslb, 0x10000104, VX )(X64Emitter& e, X86Compiler& c, Instr return 1; } +int InstrEmit_vsldoi_(X64Emitter& e, X86Compiler& c, uint32_t vd, uint32_t va, uint32_t vb, uint32_t sh) { + // (VD) <- ((VA) || (VB)) << (SH << 3) + if (!sh) { + // No shift? + e.update_vr_value(vd, e.vr_value(va)); + e.TraceVR(vd, va, vb); + return 0; + } + XmmVar v(c.newXmmVar()); + c.movaps(v, e.vr_value(va)); + XmmVar v_r(c.newXmmVar()); + c.movaps(v_r, e.vr_value(vb)); + // (VA << SH) OR (VB >> (16 - SH)) + GpVar gt(c.newGpVar()); + c.xor_(gt, gt); + c.pinsrb(v, gt.r8(), imm(15)); + c.pinsrb(v_r, gt.r8(), imm(0)); + c.mov(gt, imm((sysint_t)&__lvsl_table_left[sh])); + c.pshufb(v, xmmword_ptr(gt)); + c.mov(gt, imm((sysint_t)&__lvsl_table_right[sh])); + c.pshufb(v_r, xmmword_ptr(gt)); + c.por(v, v_r); + e.update_vr_value(vd, v); + e.TraceVR(vd, va, vb); + return 0; +} XEEMITTER(vsldoi, 0x1000002C, VXA )(X64Emitter& e, X86Compiler& c, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + return InstrEmit_vsldoi_(e, c, i.VXA.VD, i.VXA.VA, i.VXA.VB, i.VXA.VC & 0xF); } XEEMITTER(vsldoi128, VX128_5(4, 16), VX128_5)(X64Emitter& e, X86Compiler& c, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + return InstrEmit_vsldoi_(e, c, VX128_5_VD128, VX128_5_VA128, VX128_5_VB128, VX128_5_SH); } XEEMITTER(vslh, 0x10000144, VX )(X64Emitter& e, X86Compiler& c, InstrData& i) {