TranslateArm: Implement QADD16/QSUB16/UQADD16/UQSUB16.
This commit is contained in:
parent
4b09c0d032
commit
8e68e6fdd9
7 changed files with 79 additions and 11 deletions
|
@ -1089,6 +1089,22 @@ void EmitX64::EmitPackedSaturatedSubS8(IR::Block& block, IR::Inst* inst) {
|
||||||
EmitPackedOperation(code, reg_alloc, inst, &XEmitter::PSUBSB);
|
EmitPackedOperation(code, reg_alloc, inst, &XEmitter::PSUBSB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmitX64::EmitPackedSaturatedAddU16(IR::Block& block, IR::Inst* inst) {
|
||||||
|
EmitPackedOperation(code, reg_alloc, inst, &XEmitter::PADDUSW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitX64::EmitPackedSaturatedAddS16(IR::Block& block, IR::Inst* inst) {
|
||||||
|
EmitPackedOperation(code, reg_alloc, inst, &XEmitter::PADDSW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitX64::EmitPackedSaturatedSubU16(IR::Block& block, IR::Inst* inst) {
|
||||||
|
EmitPackedOperation(code, reg_alloc, inst, &XEmitter::PSUBUSW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitX64::EmitPackedSaturatedSubS16(IR::Block& block, IR::Inst* inst) {
|
||||||
|
EmitPackedOperation(code, reg_alloc, inst, &XEmitter::PSUBSW);
|
||||||
|
}
|
||||||
|
|
||||||
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.
|
||||||
|
|
|
@ -666,23 +666,31 @@ public:
|
||||||
std::string arm_QADD8(Cond cond, Reg n, Reg d, Reg m) {
|
std::string arm_QADD8(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
return Common::StringFromFormat("qadd8%s %s, %s, %s", CondToString(cond), RegToString(d), RegToString(n), RegToString(m));
|
return Common::StringFromFormat("qadd8%s %s, %s, %s", CondToString(cond), RegToString(d), RegToString(n), RegToString(m));
|
||||||
}
|
}
|
||||||
std::string arm_QADD16(Cond cond, Reg n, Reg d, Reg m) { return "ice"; }
|
std::string arm_QADD16(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
|
return Common::StringFromFormat("qadd16%s %s, %s, %s", CondToString(cond), RegToString(d), RegToString(n), RegToString(m));
|
||||||
|
}
|
||||||
std::string arm_QASX(Cond cond, Reg n, Reg d, Reg m) { return "ice"; }
|
std::string arm_QASX(Cond cond, Reg n, Reg d, Reg m) { return "ice"; }
|
||||||
std::string arm_QSAX(Cond cond, Reg n, Reg d, Reg m) { return "ice"; }
|
std::string arm_QSAX(Cond cond, Reg n, Reg d, Reg m) { return "ice"; }
|
||||||
std::string arm_QSUB8(Cond cond, Reg n, Reg d, Reg m) {
|
std::string arm_QSUB8(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
return Common::StringFromFormat("qsub8%s %s, %s, %s", CondToString(cond), RegToString(d), RegToString(n), RegToString(m));
|
return Common::StringFromFormat("qsub8%s %s, %s, %s", CondToString(cond), RegToString(d), RegToString(n), RegToString(m));
|
||||||
}
|
}
|
||||||
std::string arm_QSUB16(Cond cond, Reg n, Reg d, Reg m) { return "ice"; }
|
std::string arm_QSUB16(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
|
return Common::StringFromFormat("qsub16%s %s, %s, %s", CondToString(cond), RegToString(d), RegToString(n), RegToString(m));
|
||||||
|
}
|
||||||
std::string arm_UQADD8(Cond cond, Reg n, Reg d, Reg m) {
|
std::string arm_UQADD8(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
return Common::StringFromFormat("uqadd8%s %s, %s, %s", CondToString(cond), RegToString(d), RegToString(n), RegToString(m));
|
return Common::StringFromFormat("uqadd8%s %s, %s, %s", CondToString(cond), RegToString(d), RegToString(n), RegToString(m));
|
||||||
}
|
}
|
||||||
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 Common::StringFromFormat("uqadd16%s %s, %s, %s", CondToString(cond), RegToString(d), RegToString(n), RegToString(m));
|
||||||
|
}
|
||||||
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) {
|
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));
|
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 Common::StringFromFormat("uqsub16%s %s, %s, %s", CondToString(cond), RegToString(d), RegToString(n), RegToString(m));
|
||||||
|
}
|
||||||
|
|
||||||
// Parallel Add/Subtract (Halving) instructions
|
// Parallel Add/Subtract (Halving) instructions
|
||||||
std::string arm_SHADD8(Cond cond, Reg n, Reg d, Reg m) { return "ice"; }
|
std::string arm_SHADD8(Cond cond, Reg n, Reg d, Reg m) { return "ice"; }
|
||||||
|
|
|
@ -298,6 +298,22 @@ IR::Value IREmitter::PackedSaturatedSubS8(const IR::Value& a, const IR::Value& b
|
||||||
return Inst(IR::Opcode::PackedSaturatedSubS8, {a, b});
|
return Inst(IR::Opcode::PackedSaturatedSubS8, {a, b});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IR::Value IREmitter::PackedSaturatedAddU16(const IR::Value& a, const IR::Value& b) {
|
||||||
|
return Inst(IR::Opcode::PackedSaturatedAddU16, {a, b});
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::Value IREmitter::PackedSaturatedAddS16(const IR::Value& a, const IR::Value& b) {
|
||||||
|
return Inst(IR::Opcode::PackedSaturatedAddS16, {a, b});
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::Value IREmitter::PackedSaturatedSubU16(const IR::Value& a, const IR::Value& b) {
|
||||||
|
return Inst(IR::Opcode::PackedSaturatedSubU16, {a, b});
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::Value IREmitter::PackedSaturatedSubS16(const IR::Value& a, const IR::Value& b) {
|
||||||
|
return Inst(IR::Opcode::PackedSaturatedSubS16, {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});
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,6 +102,10 @@ public:
|
||||||
IR::Value PackedSaturatedAddS8(const IR::Value& a, const IR::Value& b);
|
IR::Value PackedSaturatedAddS8(const IR::Value& a, const IR::Value& b);
|
||||||
IR::Value PackedSaturatedSubU8(const IR::Value& a, const IR::Value& b);
|
IR::Value PackedSaturatedSubU8(const IR::Value& a, const IR::Value& b);
|
||||||
IR::Value PackedSaturatedSubS8(const IR::Value& a, const IR::Value& b);
|
IR::Value PackedSaturatedSubS8(const IR::Value& a, const IR::Value& b);
|
||||||
|
IR::Value PackedSaturatedAddU16(const IR::Value& a, const IR::Value& b);
|
||||||
|
IR::Value PackedSaturatedAddS16(const IR::Value& a, const IR::Value& b);
|
||||||
|
IR::Value PackedSaturatedSubU16(const IR::Value& a, const IR::Value& b);
|
||||||
|
IR::Value PackedSaturatedSubS16(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);
|
||||||
|
|
|
@ -64,6 +64,10 @@ OPCODE(PackedSaturatedAddU8, T::U32, T::U32, T::U32
|
||||||
OPCODE(PackedSaturatedAddS8, T::U32, T::U32, T::U32 )
|
OPCODE(PackedSaturatedAddS8, T::U32, T::U32, T::U32 )
|
||||||
OPCODE(PackedSaturatedSubU8, T::U32, T::U32, T::U32 )
|
OPCODE(PackedSaturatedSubU8, T::U32, T::U32, T::U32 )
|
||||||
OPCODE(PackedSaturatedSubS8, T::U32, T::U32, T::U32 )
|
OPCODE(PackedSaturatedSubS8, T::U32, T::U32, T::U32 )
|
||||||
|
OPCODE(PackedSaturatedAddU16, T::U32, T::U32, T::U32 )
|
||||||
|
OPCODE(PackedSaturatedAddS16, T::U32, T::U32, T::U32 )
|
||||||
|
OPCODE(PackedSaturatedSubU16, T::U32, T::U32, T::U32 )
|
||||||
|
OPCODE(PackedSaturatedSubS16, T::U32, T::U32, T::U32 )
|
||||||
|
|
||||||
// Floating-point
|
// Floating-point
|
||||||
OPCODE(TransferToFP32, T::F32, T::U32 )
|
OPCODE(TransferToFP32, T::F32, T::U32 )
|
||||||
|
|
|
@ -69,7 +69,11 @@ bool ArmTranslatorVisitor::arm_QADD8(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_QADD16(Cond cond, Reg n, Reg d, Reg m) {
|
bool ArmTranslatorVisitor::arm_QADD16(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto result = ir.PackedSaturatedAddS16(ir.GetRegister(n), ir.GetRegister(m));
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_QASX(Cond cond, Reg n, Reg d, Reg m) {
|
bool ArmTranslatorVisitor::arm_QASX(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
|
@ -89,7 +93,11 @@ bool ArmTranslatorVisitor::arm_QSUB8(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_QSUB16(Cond cond, Reg n, Reg d, Reg m) {
|
bool ArmTranslatorVisitor::arm_QSUB16(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto result = ir.PackedSaturatedSubS16(ir.GetRegister(n), ir.GetRegister(m));
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_UQADD8(Cond cond, Reg n, Reg d, Reg m) {
|
bool ArmTranslatorVisitor::arm_UQADD8(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
|
@ -101,7 +109,11 @@ bool ArmTranslatorVisitor::arm_UQADD8(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_UQADD16(Cond cond, Reg n, Reg d, Reg m) {
|
bool ArmTranslatorVisitor::arm_UQADD16(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto result = ir.PackedSaturatedAddU16(ir.GetRegister(n), ir.GetRegister(m));
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_UQASX(Cond cond, Reg n, Reg d, Reg m) {
|
bool ArmTranslatorVisitor::arm_UQASX(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
|
@ -121,7 +133,11 @@ bool ArmTranslatorVisitor::arm_UQSUB8(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_UQSUB16(Cond cond, Reg n, Reg d, Reg m) {
|
bool ArmTranslatorVisitor::arm_UQSUB16(Cond cond, Reg n, Reg d, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto result = ir.PackedSaturatedSubU16(ir.GetRegister(n), ir.GetRegister(m));
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -829,11 +829,15 @@ TEST_CASE("Fuzz ARM parallel instructions", "[JitX64]") {
|
||||||
return Bits<0, 3>(instr) != 0b1111 && Bits<12, 15>(instr) != 0b1111 && Bits<16, 19>(instr) != 0b1111;
|
return Bits<0, 3>(instr) != 0b1111 && Bits<12, 15>(instr) != 0b1111 && Bits<16, 19>(instr) != 0b1111;
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::array<InstructionGenerator, 4> saturating_instructions = {{
|
const std::array<InstructionGenerator, 8> saturating_instructions = {{
|
||||||
InstructionGenerator("cccc01100110nnnndddd11111111mmmm", is_valid), // UQSUB8
|
|
||||||
InstructionGenerator("cccc01100010nnnndddd11111111mmmm", is_valid), // QSUB8
|
|
||||||
InstructionGenerator("cccc01100010nnnndddd11111001mmmm", is_valid), // QADD8
|
InstructionGenerator("cccc01100010nnnndddd11111001mmmm", is_valid), // QADD8
|
||||||
|
InstructionGenerator("cccc01100010nnnndddd11111111mmmm", is_valid), // QSUB8
|
||||||
InstructionGenerator("cccc01100110nnnndddd11111001mmmm", is_valid), // UQADD8
|
InstructionGenerator("cccc01100110nnnndddd11111001mmmm", is_valid), // UQADD8
|
||||||
|
InstructionGenerator("cccc01100110nnnndddd11111111mmmm", is_valid), // UQSUB8
|
||||||
|
InstructionGenerator("cccc01100010nnnndddd11110001mmmm", is_valid), // QADD16
|
||||||
|
InstructionGenerator("cccc01100010nnnndddd11110111mmmm", is_valid), // QSUB16
|
||||||
|
InstructionGenerator("cccc01100110nnnndddd11110001mmmm", is_valid), // UQADD16
|
||||||
|
InstructionGenerator("cccc01100110nnnndddd11110111mmmm", is_valid), // UQSUB16
|
||||||
}};
|
}};
|
||||||
|
|
||||||
SECTION("Parallel Add/Subtract (Saturating)") {
|
SECTION("Parallel Add/Subtract (Saturating)") {
|
||||||
|
|
Loading…
Reference in a new issue