TranslateArm: Implement UQSUB8.
This commit is contained in:
parent
1029fd27ce
commit
86fe29c6d2
7 changed files with 49 additions and 2 deletions
|
@ -1055,6 +1055,24 @@ void EmitX64::EmitByteReverseDual(IR::Block&, IR::Inst* inst) {
|
||||||
code->BSWAP(64, result);
|
code->BSWAP(64, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmitX64::EmitPackedSaturatedSubU8(IR::Block& block, IR::Inst* inst) {
|
||||||
|
IR::Value a = inst->GetArg(0);
|
||||||
|
IR::Value b = inst->GetArg(1);
|
||||||
|
|
||||||
|
X64Reg result = reg_alloc.UseDefRegister(a, inst, any_gpr);
|
||||||
|
OpArg op_arg = reg_alloc.UseOpArg(b, any_gpr);
|
||||||
|
|
||||||
|
X64Reg xmm_scratch_a = reg_alloc.ScratchRegister(any_xmm);
|
||||||
|
X64Reg xmm_scratch_b = reg_alloc.ScratchRegister(any_xmm);
|
||||||
|
|
||||||
|
code->MOVD_xmm(xmm_scratch_a, R(result));
|
||||||
|
code->MOVD_xmm(xmm_scratch_b, op_arg);
|
||||||
|
|
||||||
|
code->PSUBUSB(xmm_scratch_a, R(xmm_scratch_b));
|
||||||
|
|
||||||
|
code->MOVD_xmm(R(result), xmm_scratch_a);
|
||||||
|
}
|
||||||
|
|
||||||
static void DenormalsAreZero32(BlockOfCode* code, X64Reg xmm_value, X64Reg gpr_scratch) {
|
static void DenormalsAreZero32(BlockOfCode* code, X64Reg xmm_value, X64Reg gpr_scratch) {
|
||||||
// We need to report back whether we've found a denormal on input.
|
// We need to report back whether we've found a denormal on input.
|
||||||
// SSE doesn't do this for us when SSE's DAZ is enabled.
|
// SSE doesn't do this for us when SSE's DAZ is enabled.
|
||||||
|
|
|
@ -673,7 +673,9 @@ public:
|
||||||
std::string arm_UQADD16(Cond cond, Reg n, Reg d, Reg m) { return "ice"; }
|
std::string arm_UQADD16(Cond cond, Reg n, Reg d, Reg m) { return "ice"; }
|
||||||
std::string arm_UQASX(Cond cond, Reg n, Reg d, Reg m) { return "ice"; }
|
std::string arm_UQASX(Cond cond, Reg n, Reg d, Reg m) { return "ice"; }
|
||||||
std::string arm_UQSAX(Cond cond, Reg n, Reg d, Reg m) { return "ice"; }
|
std::string arm_UQSAX(Cond cond, Reg n, Reg d, Reg m) { return "ice"; }
|
||||||
std::string arm_UQSUB8(Cond cond, Reg n, Reg d, Reg m) { return "ice"; }
|
std::string arm_UQSUB8(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
|
return Common::StringFromFormat("uqsub8%s %s, %s, %s", CondToString(cond), RegToString(d), RegToString(n), RegToString(m));
|
||||||
|
}
|
||||||
std::string arm_UQSUB16(Cond cond, Reg n, Reg d, Reg m) { return "ice"; }
|
std::string arm_UQSUB16(Cond cond, Reg n, Reg d, Reg m) { return "ice"; }
|
||||||
|
|
||||||
// Parallel Add/Subtract (Halving) instructions
|
// Parallel Add/Subtract (Halving) instructions
|
||||||
|
|
|
@ -282,6 +282,10 @@ IR::Value IREmitter::ByteReverseDual(const IR::Value& a) {
|
||||||
return Inst(IR::Opcode::ByteReverseDual, {a});
|
return Inst(IR::Opcode::ByteReverseDual, {a});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IR::Value IREmitter::PackedSaturatedSubU8(const IR::Value& a, const IR::Value& b) {
|
||||||
|
return Inst(IR::Opcode::PackedSaturatedSubU8, {a, b});
|
||||||
|
}
|
||||||
|
|
||||||
IR::Value IREmitter::TransferToFP32(const IR::Value& a) {
|
IR::Value IREmitter::TransferToFP32(const IR::Value& a) {
|
||||||
return Inst(IR::Opcode::TransferToFP32, {a});
|
return Inst(IR::Opcode::TransferToFP32, {a});
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,6 +98,7 @@ public:
|
||||||
IR::Value ByteReverseWord(const IR::Value& a);
|
IR::Value ByteReverseWord(const IR::Value& a);
|
||||||
IR::Value ByteReverseHalf(const IR::Value& a);
|
IR::Value ByteReverseHalf(const IR::Value& a);
|
||||||
IR::Value ByteReverseDual(const IR::Value& a);
|
IR::Value ByteReverseDual(const IR::Value& a);
|
||||||
|
IR::Value PackedSaturatedSubU8(const IR::Value& a, const IR::Value& b);
|
||||||
|
|
||||||
IR::Value TransferToFP32(const IR::Value& a);
|
IR::Value TransferToFP32(const IR::Value& a);
|
||||||
IR::Value TransferToFP64(const IR::Value& a);
|
IR::Value TransferToFP64(const IR::Value& a);
|
||||||
|
|
|
@ -60,6 +60,7 @@ OPCODE(ZeroExtendByteToWord, T::U32, T::U8
|
||||||
OPCODE(ByteReverseWord, T::U32, T::U32 )
|
OPCODE(ByteReverseWord, T::U32, T::U32 )
|
||||||
OPCODE(ByteReverseHalf, T::U16, T::U16 )
|
OPCODE(ByteReverseHalf, T::U16, T::U16 )
|
||||||
OPCODE(ByteReverseDual, T::U64, T::U64 )
|
OPCODE(ByteReverseDual, T::U64, T::U64 )
|
||||||
|
OPCODE(PackedSaturatedSubU8, T::U32, T::U32, T::U32 )
|
||||||
|
|
||||||
// Floating-point
|
// Floating-point
|
||||||
OPCODE(TransferToFP32, T::F32, T::U32 )
|
OPCODE(TransferToFP32, T::F32, T::U32 )
|
||||||
|
|
|
@ -101,7 +101,11 @@ bool ArmTranslatorVisitor::arm_UQSAX(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_UQSUB8(Cond cond, Reg n, Reg d, Reg m) {
|
bool ArmTranslatorVisitor::arm_UQSUB8(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto result = ir.PackedSaturatedSubU8(ir.GetRegister(n), ir.GetRegister(m));
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_UQSUB16(Cond cond, Reg n, Reg d, Reg m) {
|
bool ArmTranslatorVisitor::arm_UQSUB16(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
|
|
|
@ -822,3 +822,20 @@ TEST_CASE("Fuzz ARM multiply instructions", "[JitX64]") {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Fuzz ARM parallel instructions", "[JitX64]") {
|
||||||
|
const auto is_valid = [](u32 instr) -> bool {
|
||||||
|
// R15 as Rd, Rn, or Rm is UNPREDICTABLE
|
||||||
|
return Bits<0, 3>(instr) != 0b1111 && Bits<12, 15>(instr) != 0b1111 && Bits<16, 19>(instr) != 0b1111;
|
||||||
|
};
|
||||||
|
|
||||||
|
const std::array<InstructionGenerator, 1> saturating_instructions = {{
|
||||||
|
InstructionGenerator("cccc01100110nnnndddd11111111mmmm", is_valid), // UQSUB8
|
||||||
|
}};
|
||||||
|
|
||||||
|
SECTION("Parallel Add/Subtract (Saturating)") {
|
||||||
|
FuzzJitArm(1, 1, 10000, [&saturating_instructions]() -> u32 {
|
||||||
|
return saturating_instructions[RandInt<size_t>(0, saturating_instructions.size() - 1)].Generate();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue