TranslateArm: Implement QADD8 and UQADD8.

This commit is contained in:
bunnei 2016-08-12 13:26:14 -04:00 committed by MerryMage
parent 127fbe99cb
commit 4b09c0d032
7 changed files with 39 additions and 5 deletions

View file

@ -1073,6 +1073,14 @@ static void EmitPackedOperation(BlockOfCode* code, RegAlloc& reg_alloc, IR::Inst
code->MOVD_xmm(R(result), xmm_scratch_a);
}
void EmitX64::EmitPackedSaturatedAddU8(IR::Block& block, IR::Inst* inst) {
EmitPackedOperation(code, reg_alloc, inst, &XEmitter::PADDUSB);
}
void EmitX64::EmitPackedSaturatedAddS8(IR::Block& block, IR::Inst* inst) {
EmitPackedOperation(code, reg_alloc, inst, &XEmitter::PADDSB);
}
void EmitX64::EmitPackedSaturatedSubU8(IR::Block& block, IR::Inst* inst) {
EmitPackedOperation(code, reg_alloc, inst, &XEmitter::PSUBUSB);
}

View file

@ -663,7 +663,9 @@ public:
std::string arm_USUB16(Cond cond, Reg n, Reg d, Reg m) { return "ice"; }
// Parallel Add/Subtract (Saturating) instructions
std::string arm_QADD8(Cond cond, Reg n, Reg d, Reg m) { return "ice"; }
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));
}
std::string arm_QADD16(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"; }
@ -671,7 +673,9 @@ public:
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_UQADD8(Cond cond, Reg n, Reg d, Reg m) { return "ice"; }
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));
}
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_UQSAX(Cond cond, Reg n, Reg d, Reg m) { return "ice"; }

View file

@ -282,6 +282,14 @@ IR::Value IREmitter::ByteReverseDual(const IR::Value& a) {
return Inst(IR::Opcode::ByteReverseDual, {a});
}
IR::Value IREmitter::PackedSaturatedAddU8(const IR::Value& a, const IR::Value& b) {
return Inst(IR::Opcode::PackedSaturatedAddU8, {a, b});
}
IR::Value IREmitter::PackedSaturatedAddS8(const IR::Value& a, const IR::Value& b) {
return Inst(IR::Opcode::PackedSaturatedAddS8, {a, b});
}
IR::Value IREmitter::PackedSaturatedSubU8(const IR::Value& a, const IR::Value& b) {
return Inst(IR::Opcode::PackedSaturatedSubU8, {a, b});
}

View file

@ -98,6 +98,8 @@ public:
IR::Value ByteReverseWord(const IR::Value& a);
IR::Value ByteReverseHalf(const IR::Value& a);
IR::Value ByteReverseDual(const IR::Value& a);
IR::Value PackedSaturatedAddU8(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 PackedSaturatedSubS8(const IR::Value& a, const IR::Value& b);

View file

@ -60,6 +60,8 @@ OPCODE(ZeroExtendByteToWord, T::U32, T::U8
OPCODE(ByteReverseWord, T::U32, T::U32 )
OPCODE(ByteReverseHalf, T::U16, T::U16 )
OPCODE(ByteReverseDual, T::U64, T::U64 )
OPCODE(PackedSaturatedAddU8, T::U32, T::U32, T::U32 )
OPCODE(PackedSaturatedAddS8, T::U32, T::U32, T::U32 )
OPCODE(PackedSaturatedSubU8, T::U32, T::U32, T::U32 )
OPCODE(PackedSaturatedSubS8, T::U32, T::U32, T::U32 )

View file

@ -61,7 +61,11 @@ bool ArmTranslatorVisitor::arm_USUB16(Cond cond, Reg n, Reg d, Reg m) {
// Parallel Add/Subtract (Saturating) instructions
bool ArmTranslatorVisitor::arm_QADD8(Cond cond, Reg n, Reg d, Reg m) {
return InterpretThisInstruction();
if (ConditionPassed(cond)) {
auto result = ir.PackedSaturatedAddS8(ir.GetRegister(n), ir.GetRegister(m));
ir.SetRegister(d, result);
}
return true;
}
bool ArmTranslatorVisitor::arm_QADD16(Cond cond, Reg n, Reg d, Reg m) {
@ -89,7 +93,11 @@ bool ArmTranslatorVisitor::arm_QSUB16(Cond cond, Reg n, Reg d, Reg m) {
}
bool ArmTranslatorVisitor::arm_UQADD8(Cond cond, Reg n, Reg d, Reg m) {
return InterpretThisInstruction();
if (ConditionPassed(cond)) {
auto result = ir.PackedSaturatedAddU8(ir.GetRegister(n), ir.GetRegister(m));
ir.SetRegister(d, result);
}
return true;
}
bool ArmTranslatorVisitor::arm_UQADD16(Cond cond, Reg n, Reg d, Reg m) {

View file

@ -829,9 +829,11 @@ TEST_CASE("Fuzz ARM parallel instructions", "[JitX64]") {
return Bits<0, 3>(instr) != 0b1111 && Bits<12, 15>(instr) != 0b1111 && Bits<16, 19>(instr) != 0b1111;
};
const std::array<InstructionGenerator, 2> saturating_instructions = {{
const std::array<InstructionGenerator, 4> saturating_instructions = {{
InstructionGenerator("cccc01100110nnnndddd11111111mmmm", is_valid), // UQSUB8
InstructionGenerator("cccc01100010nnnndddd11111111mmmm", is_valid), // QSUB8
InstructionGenerator("cccc01100010nnnndddd11111001mmmm", is_valid), // QADD8
InstructionGenerator("cccc01100110nnnndddd11111001mmmm", is_valid), // UQADD8
}};
SECTION("Parallel Add/Subtract (Saturating)") {