From 127fbe99cbc695e680cf980619c091ffc03ec481 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 12 Aug 2016 13:18:38 -0400 Subject: [PATCH] TranslateArm: Implement QSUB8. --- src/backend_x64/emit_x64.cpp | 12 ++++++++++-- src/frontend/disassembler/disassembler_arm.cpp | 4 +++- src/frontend/ir/ir_emitter.cpp | 4 ++++ src/frontend/ir/ir_emitter.h | 1 + src/frontend/ir/opcodes.inc | 1 + src/frontend/translate/translate_arm/parallel.cpp | 6 +++++- tests/arm/fuzz_arm.cpp | 3 ++- 7 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/backend_x64/emit_x64.cpp b/src/backend_x64/emit_x64.cpp index a3b5ee5a..93ad037c 100644 --- a/src/backend_x64/emit_x64.cpp +++ b/src/backend_x64/emit_x64.cpp @@ -1055,7 +1055,7 @@ void EmitX64::EmitByteReverseDual(IR::Block&, IR::Inst* inst) { code->BSWAP(64, result); } -void EmitX64::EmitPackedSaturatedSubU8(IR::Block& block, IR::Inst* inst) { +static void EmitPackedOperation(BlockOfCode* code, RegAlloc& reg_alloc, IR::Inst* inst, void (XEmitter::*fn)(X64Reg, const OpArg&)) { IR::Value a = inst->GetArg(0); IR::Value b = inst->GetArg(1); @@ -1068,11 +1068,19 @@ void EmitX64::EmitPackedSaturatedSubU8(IR::Block& block, IR::Inst* inst) { 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->*fn)(xmm_scratch_a, R(xmm_scratch_b)); code->MOVD_xmm(R(result), xmm_scratch_a); } +void EmitX64::EmitPackedSaturatedSubU8(IR::Block& block, IR::Inst* inst) { + EmitPackedOperation(code, reg_alloc, inst, &XEmitter::PSUBUSB); +} + +void EmitX64::EmitPackedSaturatedSubS8(IR::Block& block, IR::Inst* inst) { + EmitPackedOperation(code, reg_alloc, inst, &XEmitter::PSUBSB); +} + static void DenormalsAreZero32(BlockOfCode* code, X64Reg xmm_value, X64Reg gpr_scratch) { // 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. diff --git a/src/frontend/disassembler/disassembler_arm.cpp b/src/frontend/disassembler/disassembler_arm.cpp index 17b9f28b..d01830c4 100644 --- a/src/frontend/disassembler/disassembler_arm.cpp +++ b/src/frontend/disassembler/disassembler_arm.cpp @@ -667,7 +667,9 @@ public: 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"; } - std::string arm_QSUB8(Cond cond, Reg n, Reg d, Reg m) { return "ice"; } + 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)); + } 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_UQADD16(Cond cond, Reg n, Reg d, Reg m) { return "ice"; } diff --git a/src/frontend/ir/ir_emitter.cpp b/src/frontend/ir/ir_emitter.cpp index 8e6882b8..1ba79157 100644 --- a/src/frontend/ir/ir_emitter.cpp +++ b/src/frontend/ir/ir_emitter.cpp @@ -286,6 +286,10 @@ IR::Value IREmitter::PackedSaturatedSubU8(const IR::Value& a, const IR::Value& b return Inst(IR::Opcode::PackedSaturatedSubU8, {a, b}); } +IR::Value IREmitter::PackedSaturatedSubS8(const IR::Value& a, const IR::Value& b) { + return Inst(IR::Opcode::PackedSaturatedSubS8, {a, b}); +} + IR::Value IREmitter::TransferToFP32(const IR::Value& a) { return Inst(IR::Opcode::TransferToFP32, {a}); } diff --git a/src/frontend/ir/ir_emitter.h b/src/frontend/ir/ir_emitter.h index 7519d614..85edfcfa 100644 --- a/src/frontend/ir/ir_emitter.h +++ b/src/frontend/ir/ir_emitter.h @@ -99,6 +99,7 @@ public: IR::Value ByteReverseHalf(const IR::Value& a); IR::Value ByteReverseDual(const IR::Value& a); IR::Value PackedSaturatedSubU8(const IR::Value& a, const IR::Value& b); + IR::Value PackedSaturatedSubS8(const IR::Value& a, const IR::Value& b); IR::Value TransferToFP32(const IR::Value& a); IR::Value TransferToFP64(const IR::Value& a); diff --git a/src/frontend/ir/opcodes.inc b/src/frontend/ir/opcodes.inc index c0a6b9e7..792cdf25 100644 --- a/src/frontend/ir/opcodes.inc +++ b/src/frontend/ir/opcodes.inc @@ -61,6 +61,7 @@ OPCODE(ByteReverseWord, T::U32, T::U32 OPCODE(ByteReverseHalf, T::U16, T::U16 ) OPCODE(ByteReverseDual, T::U64, T::U64 ) OPCODE(PackedSaturatedSubU8, T::U32, T::U32, T::U32 ) +OPCODE(PackedSaturatedSubS8, T::U32, T::U32, T::U32 ) // Floating-point OPCODE(TransferToFP32, T::F32, T::U32 ) diff --git a/src/frontend/translate/translate_arm/parallel.cpp b/src/frontend/translate/translate_arm/parallel.cpp index e6bf271f..8249a2a1 100644 --- a/src/frontend/translate/translate_arm/parallel.cpp +++ b/src/frontend/translate/translate_arm/parallel.cpp @@ -77,7 +77,11 @@ bool ArmTranslatorVisitor::arm_QSAX(Cond cond, Reg n, Reg d, Reg m) { } bool ArmTranslatorVisitor::arm_QSUB8(Cond cond, Reg n, Reg d, Reg m) { - return InterpretThisInstruction(); + if (ConditionPassed(cond)) { + auto result = ir.PackedSaturatedSubS8(ir.GetRegister(n), ir.GetRegister(m)); + ir.SetRegister(d, result); + } + return true; } bool ArmTranslatorVisitor::arm_QSUB16(Cond cond, Reg n, Reg d, Reg m) { diff --git a/tests/arm/fuzz_arm.cpp b/tests/arm/fuzz_arm.cpp index 38dd6c72..d2866d01 100644 --- a/tests/arm/fuzz_arm.cpp +++ b/tests/arm/fuzz_arm.cpp @@ -829,8 +829,9 @@ 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 saturating_instructions = {{ + const std::array saturating_instructions = {{ InstructionGenerator("cccc01100110nnnndddd11111111mmmm", is_valid), // UQSUB8 + InstructionGenerator("cccc01100010nnnndddd11111111mmmm", is_valid), // QSUB8 }}; SECTION("Parallel Add/Subtract (Saturating)") {