ir: Add opcode for reversing bits in a vector
This commit is contained in:
parent
9de60b60bb
commit
64b1f2d468
4 changed files with 49 additions and 0 deletions
|
@ -1276,6 +1276,49 @@ void EmitX64::EmitVectorPopulationCount(EmitContext& ctx, IR::Inst* inst) {
|
|||
});
|
||||
}
|
||||
|
||||
void EmitX64::EmitVectorReverseBits(EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
||||
const Xbyak::Xmm data = ctx.reg_alloc.UseScratchXmm(args[0]);
|
||||
const Xbyak::Xmm high_nibble_reg = ctx.reg_alloc.ScratchXmm();
|
||||
|
||||
code.movdqa(high_nibble_reg, code.MConst(xword, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0));
|
||||
code.pand(high_nibble_reg, data);
|
||||
code.pxor(data, high_nibble_reg);
|
||||
code.psrld(high_nibble_reg, 4);
|
||||
|
||||
if (code.DoesCpuSupport(Xbyak::util::Cpu::tSSSE3)) {
|
||||
// High lookup
|
||||
const Xbyak::Xmm high_reversed_reg = ctx.reg_alloc.ScratchXmm();
|
||||
code.movdqa(high_reversed_reg, code.MConst(xword, 0xE060A020C0408000, 0xF070B030D0509010));
|
||||
code.pshufb(high_reversed_reg, data);
|
||||
|
||||
// Low lookup (low nibble equivalent of the above)
|
||||
code.movdqa(data, code.MConst(xword, 0x0E060A020C040800, 0x0F070B030D050901));
|
||||
code.pshufb(data, high_nibble_reg);
|
||||
code.por(data, high_reversed_reg);
|
||||
} else {
|
||||
code.pslld(data, 4);
|
||||
code.por(data, high_nibble_reg);
|
||||
|
||||
code.movdqa(high_nibble_reg, code.MConst(xword, 0xCCCCCCCCCCCCCCCC, 0xCCCCCCCCCCCCCCCC));
|
||||
code.pand(high_nibble_reg, data);
|
||||
code.pxor(data, high_nibble_reg);
|
||||
code.psrld(high_nibble_reg, 2);
|
||||
code.pslld(data, 2);
|
||||
code.por(data, high_nibble_reg);
|
||||
|
||||
code.movdqa(high_nibble_reg, code.MConst(xword, 0xAAAAAAAAAAAAAAAA, 0xAAAAAAAAAAAAAAAA));
|
||||
code.pand(high_nibble_reg, data);
|
||||
code.pxor(data, high_nibble_reg);
|
||||
code.psrld(high_nibble_reg, 1);
|
||||
code.paddd(data, data);
|
||||
code.por(data, high_nibble_reg);
|
||||
}
|
||||
|
||||
ctx.reg_alloc.DefineValue(inst, data);
|
||||
}
|
||||
|
||||
enum class ShuffleType {
|
||||
LowHalfwords,
|
||||
HighHalfwords,
|
||||
|
|
|
@ -1143,6 +1143,10 @@ U128 IREmitter::VectorPopulationCount(const U128& a) {
|
|||
return Inst<U128>(Opcode::VectorPopulationCount, a);
|
||||
}
|
||||
|
||||
U128 IREmitter::VectorReverseBits(const U128& a) {
|
||||
return Inst<U128>(Opcode::VectorReverseBits, a);
|
||||
}
|
||||
|
||||
U128 IREmitter::VectorShuffleHighHalfwords(const U128& a, u8 mask) {
|
||||
return Inst<U128>(Opcode::VectorShuffleHighHalfwords, a, mask);
|
||||
}
|
||||
|
|
|
@ -242,6 +242,7 @@ public:
|
|||
U128 VectorPairedAdd(size_t esize, const U128& a, const U128& b);
|
||||
U128 VectorPairedAddLower(size_t esize, const U128& a, const U128& b);
|
||||
U128 VectorPopulationCount(const U128& a);
|
||||
U128 VectorReverseBits(const U128& a);
|
||||
U128 VectorShuffleHighHalfwords(const U128& a, u8 mask);
|
||||
U128 VectorShuffleLowHalfwords(const U128& a, u8 mask);
|
||||
U128 VectorShuffleWords(const U128& a, u8 mask);
|
||||
|
|
|
@ -296,6 +296,7 @@ OPCODE(VectorPairedAdd16, T::U128, T::U128, T::U
|
|||
OPCODE(VectorPairedAdd32, T::U128, T::U128, T::U128 )
|
||||
OPCODE(VectorPairedAdd64, T::U128, T::U128, T::U128 )
|
||||
OPCODE(VectorPopulationCount, T::U128, T::U128 )
|
||||
OPCODE(VectorReverseBits, T::U128, T::U128 )
|
||||
OPCODE(VectorShuffleHighHalfwords, T::U128, T::U128, T::U8 )
|
||||
OPCODE(VectorShuffleLowHalfwords, T::U128, T::U128, T::U8 )
|
||||
OPCODE(VectorShuffleWords, T::U128, T::U128, T::U8 )
|
||||
|
|
Loading…
Reference in a new issue