ir: Add opcodes for signed saturated doubling multiplies
This commit is contained in:
parent
a1e46e9881
commit
a0231e5546
5 changed files with 629 additions and 539 deletions
|
@ -2757,6 +2757,80 @@ void EmitX64::EmitVectorSignedSaturatedAbs64(EmitContext& ctx, IR::Inst* inst) {
|
|||
});
|
||||
}
|
||||
|
||||
void EmitX64::EmitVectorSignedSaturatedDoublingMultiplyReturnHigh16(EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
||||
const Xbyak::Xmm x = ctx.reg_alloc.UseScratchXmm(args[0]);
|
||||
const Xbyak::Xmm y = ctx.reg_alloc.UseScratchXmm(args[1]);
|
||||
const Xbyak::Xmm tmp = ctx.reg_alloc.ScratchXmm();
|
||||
|
||||
code.movdqa(tmp, x);
|
||||
code.pmulhw(tmp, y);
|
||||
code.paddw(tmp, tmp);
|
||||
code.pmullw(y, x);
|
||||
code.psrlw(y, 15);
|
||||
code.por(y, tmp);
|
||||
|
||||
code.movdqa(x, code.MConst(xword, 0x8000800080008000, 0x8000800080008000));
|
||||
code.pcmpeqw(x, y);
|
||||
code.movdqa(tmp, x);
|
||||
code.pxor(x, y);
|
||||
|
||||
// Check if any saturation occurred (i.e. if any halfwords in x were
|
||||
// 0x8000 before saturating
|
||||
const Xbyak::Reg64 mask = ctx.reg_alloc.ScratchGpr();
|
||||
code.pmovmskb(mask, tmp);
|
||||
code.test(mask.cvt32(), 0b1010'1010'1010'1010);
|
||||
code.setnz(mask.cvt8());
|
||||
code.or_(code.byte[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], mask.cvt8());
|
||||
|
||||
ctx.reg_alloc.DefineValue(inst, x);
|
||||
}
|
||||
|
||||
void EmitX64::EmitVectorSignedSaturatedDoublingMultiplyReturnHigh32(EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
||||
const Xbyak::Xmm x = ctx.reg_alloc.UseScratchXmm(args[0]);
|
||||
const Xbyak::Xmm y = ctx.reg_alloc.UseScratchXmm(args[1]);
|
||||
const Xbyak::Xmm tmp1 = ctx.reg_alloc.ScratchXmm();
|
||||
const Xbyak::Xmm tmp2 = ctx.reg_alloc.ScratchXmm();
|
||||
|
||||
code.movdqa(tmp1, x);
|
||||
code.punpckldq(tmp1, y);
|
||||
|
||||
code.movdqa(tmp2, y);
|
||||
code.punpckldq(tmp2, x);
|
||||
|
||||
code.pmuldq(tmp2, tmp1);
|
||||
code.paddq(tmp2, tmp2);
|
||||
|
||||
code.movdqa(tmp1, x);
|
||||
code.punpckhdq(tmp1, y);
|
||||
code.punpckhdq(y, x);
|
||||
|
||||
code.pmuldq(y, tmp1);
|
||||
code.paddq(y, y);
|
||||
|
||||
code.pshufd(tmp1, tmp2, 0b11101101);
|
||||
code.pshufd(x, y, 0b11101101);
|
||||
code.punpcklqdq(tmp1, x);
|
||||
|
||||
code.movdqa(x, code.MConst(xword, 0x8000000080000000, 0x8000000080000000));
|
||||
code.pcmpeqd(x, tmp1);
|
||||
code.movdqa(tmp2, x);
|
||||
code.pxor(x, tmp1);
|
||||
|
||||
// Check if any saturation occurred (i.e. if any words in x were
|
||||
// 0x80000000 before saturating
|
||||
const Xbyak::Reg64 mask = ctx.reg_alloc.ScratchGpr();
|
||||
code.pmovmskb(mask, tmp2);
|
||||
code.test(mask.cvt32(), 0b1000'1000'1000'1000);
|
||||
code.setnz(mask.cvt8());
|
||||
code.or_(code.byte[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], mask.cvt8());
|
||||
|
||||
ctx.reg_alloc.DefineValue(inst, x);
|
||||
}
|
||||
|
||||
static void EmitVectorSignedSaturatedNarrowToSigned(size_t original_esize, BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
const Xbyak::Xmm src = ctx.reg_alloc.UseXmm(args[0]);
|
||||
|
|
|
@ -1511,6 +1511,17 @@ U128 IREmitter::VectorSignedSaturatedAbs(size_t esize, const U128& a) {
|
|||
return {};
|
||||
}
|
||||
|
||||
U128 IREmitter::VectorSignedSaturatedDoublingMultiplyReturnHigh(size_t esize, const U128& a, const U128& b) {
|
||||
switch (esize) {
|
||||
case 16:
|
||||
return Inst<U128>(Opcode::VectorSignedSaturatedDoublingMultiplyReturnHigh16, a, b);
|
||||
case 32:
|
||||
return Inst<U128>(Opcode::VectorSignedSaturatedDoublingMultiplyReturnHigh32, a, b);
|
||||
}
|
||||
UNREACHABLE();
|
||||
return {};
|
||||
}
|
||||
|
||||
U128 IREmitter::VectorSignedSaturatedNarrowToSigned(size_t original_esize, const U128& a) {
|
||||
switch (original_esize) {
|
||||
case 16:
|
||||
|
|
|
@ -264,6 +264,7 @@ public:
|
|||
U128 VectorSignExtend(size_t original_esize, const U128& a);
|
||||
U128 VectorSignedAbsoluteDifference(size_t esize, const U128& a, const U128& b);
|
||||
U128 VectorSignedSaturatedAbs(size_t esize, const U128& a);
|
||||
U128 VectorSignedSaturatedDoublingMultiplyReturnHigh(size_t esize, const U128& a, const U128& b);
|
||||
U128 VectorSignedSaturatedNarrowToSigned(size_t original_esize, const U128& a);
|
||||
U128 VectorSignedSaturatedNarrowToUnsigned(size_t original_esize, const U128& a);
|
||||
U128 VectorSub(size_t esize, const U128& a, const U128& b);
|
||||
|
|
|
@ -357,6 +357,8 @@ bool Inst::WritesToFPSRCumulativeSaturationBit() const {
|
|||
case Opcode::VectorSignedSaturatedNarrowToUnsigned16:
|
||||
case Opcode::VectorSignedSaturatedNarrowToUnsigned32:
|
||||
case Opcode::VectorSignedSaturatedNarrowToUnsigned64:
|
||||
case Opcode::VectorSignedSaturatedDoublingMultiplyReturnHigh16:
|
||||
case Opcode::VectorSignedSaturatedDoublingMultiplyReturnHigh32:
|
||||
case Opcode::VectorUnsignedSaturatedNarrow16:
|
||||
case Opcode::VectorUnsignedSaturatedNarrow32:
|
||||
case Opcode::VectorUnsignedSaturatedNarrow64:
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue