[a64] Implement `OPCODE_SWIZZLE`

This commit is contained in:
Wunkolo 2024-05-10 10:19:30 -07:00
parent c4b263894d
commit f73c8fe947
1 changed files with 34 additions and 1 deletions

View File

@ -1139,7 +1139,40 @@ EMITTER_OPCODE_TABLE(OPCODE_PERMUTE, PERMUTE_I32, PERMUTE_V128);
// ============================================================================
struct SWIZZLE
: Sequence<SWIZZLE, I<OPCODE_SWIZZLE, V128Op, V128Op, OffsetOp>> {
static void Emit(A64Emitter& e, const EmitArgType& i){};
static void Emit(A64Emitter& e, const EmitArgType& i) {
auto element_type = i.instr->flags;
if (element_type == INT8_TYPE) {
assert_always();
} else if (element_type == INT16_TYPE) {
assert_always();
} else if (element_type == INT32_TYPE || element_type == FLOAT32_TYPE) {
// Four 2-bit word-indices packed into one 8-bit value
const uint8_t swizzle_mask = static_cast<uint8_t>(i.src2.value);
// Convert to byte-indices
const vec128_t indice_vec =
vec128i(((swizzle_mask >> 0) & 0b11) * 0x04'04'04'04 + 0x03'02'01'00,
((swizzle_mask >> 2) & 0b11) * 0x04'04'04'04 + 0x03'02'01'00,
((swizzle_mask >> 4) & 0b11) * 0x04'04'04'04 + 0x03'02'01'00,
((swizzle_mask >> 6) & 0b11) * 0x04'04'04'04 + 0x03'02'01'00);
const QReg indices = Q0;
e.LoadConstantV(indices, indice_vec);
QReg table0 = Q0;
if (i.src1.is_constant) {
e.LoadConstantV(table0, i.src1.constant());
} else {
table0 = i.src1;
}
e.TBL(i.dest.reg().B16(), List{table0.B16()}, indices.B16());
} else if (element_type == INT64_TYPE || element_type == FLOAT64_TYPE) {
assert_always();
} else {
assert_always();
}
};
};
EMITTER_OPCODE_TABLE(OPCODE_SWIZZLE, SWIZZLE);