From d5294178750b50fdd6c042902c40322093ef95a0 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 1 Feb 2021 16:11:25 -0500 Subject: [PATCH 01/18] thumb32: Implement SADD16/UADD16 --- src/CMakeLists.txt | 1 + src/frontend/A32/decoder/thumb32.h | 4 +- .../A32/translate/impl/thumb32_parallel.cpp | 38 +++++++++++++++ .../A32/translate/impl/translate_thumb.h | 4 ++ tests/A32/fuzz_thumb.cpp | 46 +++++++------------ 5 files changed, 61 insertions(+), 32 deletions(-) create mode 100644 src/frontend/A32/translate/impl/thumb32_parallel.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 487384ed..1126ad42 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -152,6 +152,7 @@ if ("A32" IN_LIST DYNARMIC_FRONTENDS) frontend/A32/translate/impl/thumb16.cpp frontend/A32/translate/impl/thumb32.cpp frontend/A32/translate/impl/thumb32_misc.cpp + frontend/A32/translate/impl/thumb32_parallel.cpp frontend/A32/translate/impl/translate_arm.h frontend/A32/translate/impl/translate_thumb.h frontend/A32/translate/impl/vfp.cpp diff --git a/src/frontend/A32/decoder/thumb32.h b/src/frontend/A32/decoder/thumb32.h index 954a36f7..ffc03de2 100644 --- a/src/frontend/A32/decoder/thumb32.h +++ b/src/frontend/A32/decoder/thumb32.h @@ -235,7 +235,7 @@ std::optional>> DecodeThumb32(u32 //INST(&V::thumb32_UXTAB, "UXTAB", "111110100101----1111----1-------"), // Parallel Addition and Subtraction (signed) - //INST(&V::thumb32_SADD16, "SADD16", "111110101001----1111----0000----"), + INST(&V::thumb32_SADD16, "SADD16", "111110101001nnnn1111dddd0000mmmm"), //INST(&V::thumb32_SASX, "SASX", "111110101010----1111----0000----"), //INST(&V::thumb32_SSAX, "SSAX", "111110101110----1111----0000----"), //INST(&V::thumb32_SSUB16, "SSUB16", "111110101101----1111----0000----"), @@ -255,7 +255,7 @@ std::optional>> DecodeThumb32(u32 //INST(&V::thumb32_SHSUB8, "SHSUB8", "111110101100----1111----0010----"), // Parallel Addition and Subtraction (unsigned) - //INST(&V::thumb32_UADD16, "UADD16", "111110101001----1111----0100----"), + INST(&V::thumb32_UADD16, "UADD16", "111110101001nnnn1111dddd0100mmmm"), //INST(&V::thumb32_UASX, "UASX", "111110101010----1111----0100----"), //INST(&V::thumb32_USAX, "USAX", "111110101110----1111----0100----"), //INST(&V::thumb32_USUB16, "USUB16", "111110101101----1111----0100----"), diff --git a/src/frontend/A32/translate/impl/thumb32_parallel.cpp b/src/frontend/A32/translate/impl/thumb32_parallel.cpp new file mode 100644 index 00000000..0fa41d1b --- /dev/null +++ b/src/frontend/A32/translate/impl/thumb32_parallel.cpp @@ -0,0 +1,38 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#include "frontend/A32/translate/impl/translate_thumb.h" + +namespace Dynarmic::A32 { + +bool ThumbTranslatorVisitor::thumb32_SADD16(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedAddS16(reg_n, reg_m); + + ir.SetRegister(d, result.result); + ir.SetGEFlags(result.ge); + return true; +} + +bool ThumbTranslatorVisitor::thumb32_UADD16(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedAddU16(reg_n, reg_m); + + ir.SetRegister(d, result.result); + ir.SetGEFlags(result.ge); + return true; +} + +} // namespace Dynarmic::A32 diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index 2dfe5d8a..07f568cc 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -127,6 +127,10 @@ struct ThumbTranslatorVisitor final { bool thumb32_REV16(Reg n, Reg d, Reg m); bool thumb32_REVSH(Reg n, Reg d, Reg m); bool thumb32_SEL(Reg n, Reg d, Reg m); + + // thumb32 parallel add/sub instructions + bool thumb32_SADD16(Reg n, Reg d, Reg m); + bool thumb32_UADD16(Reg n, Reg d, Reg m); }; } // namespace Dynarmic::A32 diff --git a/tests/A32/fuzz_thumb.cpp b/tests/A32/fuzz_thumb.cpp index dbc5dece..9e69868c 100644 --- a/tests/A32/fuzz_thumb.cpp +++ b/tests/A32/fuzz_thumb.cpp @@ -361,6 +361,13 @@ TEST_CASE("Fuzz Thumb instructions set 2 (affects PC)", "[JitX64][Thumb][Thumb16 } TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { + const auto three_reg_not_r15 = [](u32 inst) { + const auto d = Common::Bits<8, 11>(inst); + const auto m = Common::Bits<0, 3>(inst); + const auto n = Common::Bits<16, 19>(inst); + return d != 15 && m != 15 && n != 15; + }; + const std::array instructions = { ThumbInstGen("111110101011nnnn1111dddd1000mmmm", // CLZ [](u32 inst) { @@ -370,33 +377,13 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { return m == n && d != 15 && m != 15; }), ThumbInstGen("111110101000nnnn1111dddd1000mmmm", // QADD - [](u32 inst) { - const auto d = Common::Bits<8, 11>(inst); - const auto m = Common::Bits<0, 3>(inst); - const auto n = Common::Bits<16, 19>(inst); - return d != 15 && m != 15 && n != 15; - }), + three_reg_not_r15), ThumbInstGen("111110101000nnnn1111dddd1001mmmm", // QDADD - [](u32 inst) { - const auto d = Common::Bits<8, 11>(inst); - const auto m = Common::Bits<0, 3>(inst); - const auto n = Common::Bits<16, 19>(inst); - return d != 15 && m != 15 && n != 15; - }), + three_reg_not_r15), ThumbInstGen("111110101000nnnn1111dddd1011mmmm", // QDSUB - [](u32 inst) { - const auto d = Common::Bits<8, 11>(inst); - const auto m = Common::Bits<0, 3>(inst); - const auto n = Common::Bits<16, 19>(inst); - return d != 15 && m != 15 && n != 15; - }), + three_reg_not_r15), ThumbInstGen("111110101000nnnn1111dddd1010mmmm", // QSUB - [](u32 inst) { - const auto d = Common::Bits<8, 11>(inst); - const auto m = Common::Bits<0, 3>(inst); - const auto n = Common::Bits<16, 19>(inst); - return d != 15 && m != 15 && n != 15; - }), + three_reg_not_r15), ThumbInstGen("111110101001nnnn1111dddd1010mmmm", // RBIT [](u32 inst) { const auto d = Common::Bits<8, 11>(inst); @@ -425,13 +412,12 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { const auto n = Common::Bits<16, 19>(inst); return m == n && d != 15 && m != 15; }), + ThumbInstGen("111110101001nnnn1111dddd0000mmmm", // SADD16 + three_reg_not_r15), ThumbInstGen("111110101010nnnn1111dddd1000mmmm", // SEL - [](u32 inst) { - const auto d = Common::Bits<8, 11>(inst); - const auto m = Common::Bits<0, 3>(inst); - const auto n = Common::Bits<16, 19>(inst); - return d != 15 && m != 15 && n != 15; - }), + three_reg_not_r15), + ThumbInstGen("111110101001nnnn1111dddd0100mmmm", // UADD16 + three_reg_not_r15), }; const auto instruction_select = [&]() -> u32 { From 21e404d3ab780f231677308b87f83c892611b844 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 1 Feb 2021 16:30:08 -0500 Subject: [PATCH 02/18] thumb32: Implement SASX/UASX --- src/frontend/A32/decoder/thumb32.h | 4 +-- .../A32/translate/impl/thumb32_parallel.cpp | 28 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 2 ++ tests/A32/fuzz_thumb.cpp | 4 +++ 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/frontend/A32/decoder/thumb32.h b/src/frontend/A32/decoder/thumb32.h index ffc03de2..2e819088 100644 --- a/src/frontend/A32/decoder/thumb32.h +++ b/src/frontend/A32/decoder/thumb32.h @@ -236,7 +236,7 @@ std::optional>> DecodeThumb32(u32 // Parallel Addition and Subtraction (signed) INST(&V::thumb32_SADD16, "SADD16", "111110101001nnnn1111dddd0000mmmm"), - //INST(&V::thumb32_SASX, "SASX", "111110101010----1111----0000----"), + INST(&V::thumb32_SASX, "SASX", "111110101010nnnn1111dddd0000mmmm"), //INST(&V::thumb32_SSAX, "SSAX", "111110101110----1111----0000----"), //INST(&V::thumb32_SSUB16, "SSUB16", "111110101101----1111----0000----"), //INST(&V::thumb32_SADD8, "SADD8", "111110101000----1111----0000----"), @@ -256,7 +256,7 @@ std::optional>> DecodeThumb32(u32 // Parallel Addition and Subtraction (unsigned) INST(&V::thumb32_UADD16, "UADD16", "111110101001nnnn1111dddd0100mmmm"), - //INST(&V::thumb32_UASX, "UASX", "111110101010----1111----0100----"), + INST(&V::thumb32_UASX, "UASX", "111110101010nnnn1111dddd0100mmmm"), //INST(&V::thumb32_USAX, "USAX", "111110101110----1111----0100----"), //INST(&V::thumb32_USUB16, "USUB16", "111110101101----1111----0100----"), //INST(&V::thumb32_UADD8, "UADD8", "111110101000----1111----0100----"), diff --git a/src/frontend/A32/translate/impl/thumb32_parallel.cpp b/src/frontend/A32/translate/impl/thumb32_parallel.cpp index 0fa41d1b..48f9759e 100644 --- a/src/frontend/A32/translate/impl/thumb32_parallel.cpp +++ b/src/frontend/A32/translate/impl/thumb32_parallel.cpp @@ -21,6 +21,20 @@ bool ThumbTranslatorVisitor::thumb32_SADD16(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_SASX(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedAddSubS16(reg_n, reg_m); + + ir.SetRegister(d, result.result); + ir.SetGEFlags(result.ge); + return true; +} + bool ThumbTranslatorVisitor::thumb32_UADD16(Reg n, Reg d, Reg m) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); @@ -35,4 +49,18 @@ bool ThumbTranslatorVisitor::thumb32_UADD16(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_UASX(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedAddSubU16(reg_n, reg_m); + + ir.SetRegister(d, result.result); + ir.SetGEFlags(result.ge); + return true; +} + } // namespace Dynarmic::A32 diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index 07f568cc..65df3225 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -130,7 +130,9 @@ struct ThumbTranslatorVisitor final { // thumb32 parallel add/sub instructions bool thumb32_SADD16(Reg n, Reg d, Reg m); + bool thumb32_SASX(Reg n, Reg d, Reg m); bool thumb32_UADD16(Reg n, Reg d, Reg m); + bool thumb32_UASX(Reg n, Reg d, Reg m); }; } // namespace Dynarmic::A32 diff --git a/tests/A32/fuzz_thumb.cpp b/tests/A32/fuzz_thumb.cpp index 9e69868c..164c381e 100644 --- a/tests/A32/fuzz_thumb.cpp +++ b/tests/A32/fuzz_thumb.cpp @@ -414,10 +414,14 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { }), ThumbInstGen("111110101001nnnn1111dddd0000mmmm", // SADD16 three_reg_not_r15), + ThumbInstGen("111110101010nnnn1111dddd0000mmmm", // SASX + three_reg_not_r15), ThumbInstGen("111110101010nnnn1111dddd1000mmmm", // SEL three_reg_not_r15), ThumbInstGen("111110101001nnnn1111dddd0100mmmm", // UADD16 three_reg_not_r15), + ThumbInstGen("111110101010nnnn1111dddd0100mmmm", // UASX + three_reg_not_r15), }; const auto instruction_select = [&]() -> u32 { From 0e28c634567919ad682165564f82dbe942719d49 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 1 Feb 2021 16:36:18 -0500 Subject: [PATCH 03/18] thumb32: Implement SSAX/USAX --- src/frontend/A32/decoder/thumb32.h | 4 +-- .../A32/translate/impl/thumb32_parallel.cpp | 28 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 2 ++ tests/A32/fuzz_thumb.cpp | 4 +++ 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/frontend/A32/decoder/thumb32.h b/src/frontend/A32/decoder/thumb32.h index 2e819088..aeac8d18 100644 --- a/src/frontend/A32/decoder/thumb32.h +++ b/src/frontend/A32/decoder/thumb32.h @@ -237,7 +237,7 @@ std::optional>> DecodeThumb32(u32 // Parallel Addition and Subtraction (signed) INST(&V::thumb32_SADD16, "SADD16", "111110101001nnnn1111dddd0000mmmm"), INST(&V::thumb32_SASX, "SASX", "111110101010nnnn1111dddd0000mmmm"), - //INST(&V::thumb32_SSAX, "SSAX", "111110101110----1111----0000----"), + INST(&V::thumb32_SSAX, "SSAX", "111110101110nnnn1111dddd0000mmmm"), //INST(&V::thumb32_SSUB16, "SSUB16", "111110101101----1111----0000----"), //INST(&V::thumb32_SADD8, "SADD8", "111110101000----1111----0000----"), //INST(&V::thumb32_SSUB8, "SSUB8", "111110101100----1111----0000----"), @@ -257,7 +257,7 @@ std::optional>> DecodeThumb32(u32 // Parallel Addition and Subtraction (unsigned) INST(&V::thumb32_UADD16, "UADD16", "111110101001nnnn1111dddd0100mmmm"), INST(&V::thumb32_UASX, "UASX", "111110101010nnnn1111dddd0100mmmm"), - //INST(&V::thumb32_USAX, "USAX", "111110101110----1111----0100----"), + INST(&V::thumb32_USAX, "USAX", "111110101110nnnn1111dddd0100mmmm"), //INST(&V::thumb32_USUB16, "USUB16", "111110101101----1111----0100----"), //INST(&V::thumb32_UADD8, "UADD8", "111110101000----1111----0100----"), //INST(&V::thumb32_USUB8, "USUB8", "111110101100----1111----0100----"), diff --git a/src/frontend/A32/translate/impl/thumb32_parallel.cpp b/src/frontend/A32/translate/impl/thumb32_parallel.cpp index 48f9759e..32fac7dc 100644 --- a/src/frontend/A32/translate/impl/thumb32_parallel.cpp +++ b/src/frontend/A32/translate/impl/thumb32_parallel.cpp @@ -35,6 +35,20 @@ bool ThumbTranslatorVisitor::thumb32_SASX(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_SSAX(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedSubAddS16(reg_n, reg_m); + + ir.SetRegister(d, result.result); + ir.SetGEFlags(result.ge); + return true; +} + bool ThumbTranslatorVisitor::thumb32_UADD16(Reg n, Reg d, Reg m) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); @@ -63,4 +77,18 @@ bool ThumbTranslatorVisitor::thumb32_UASX(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_USAX(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedSubAddU16(reg_n, reg_m); + + ir.SetRegister(d, result.result); + ir.SetGEFlags(result.ge); + return true; +} + } // namespace Dynarmic::A32 diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index 65df3225..54662723 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -131,8 +131,10 @@ struct ThumbTranslatorVisitor final { // thumb32 parallel add/sub instructions bool thumb32_SADD16(Reg n, Reg d, Reg m); bool thumb32_SASX(Reg n, Reg d, Reg m); + bool thumb32_SSAX(Reg n, Reg d, Reg m); bool thumb32_UADD16(Reg n, Reg d, Reg m); bool thumb32_UASX(Reg n, Reg d, Reg m); + bool thumb32_USAX(Reg n, Reg d, Reg m); }; } // namespace Dynarmic::A32 diff --git a/tests/A32/fuzz_thumb.cpp b/tests/A32/fuzz_thumb.cpp index 164c381e..d239f4b2 100644 --- a/tests/A32/fuzz_thumb.cpp +++ b/tests/A32/fuzz_thumb.cpp @@ -418,10 +418,14 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101010nnnn1111dddd1000mmmm", // SEL three_reg_not_r15), + ThumbInstGen("111110101110nnnn1111dddd0000mmmm", // SSAX + three_reg_not_r15), ThumbInstGen("111110101001nnnn1111dddd0100mmmm", // UADD16 three_reg_not_r15), ThumbInstGen("111110101010nnnn1111dddd0100mmmm", // UASX three_reg_not_r15), + ThumbInstGen("111110101110nnnn1111dddd0100mmmm", // USAX + three_reg_not_r15), }; const auto instruction_select = [&]() -> u32 { From 8f42fd5c0e5d2e2f00826653d5a1944f1e3744d3 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 1 Feb 2021 16:41:02 -0500 Subject: [PATCH 04/18] thumb32: Implement SSUB16/USUB16 --- src/frontend/A32/decoder/thumb32.h | 4 +-- .../A32/translate/impl/thumb32_parallel.cpp | 28 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 2 ++ tests/A32/fuzz_thumb.cpp | 4 +++ 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/frontend/A32/decoder/thumb32.h b/src/frontend/A32/decoder/thumb32.h index aeac8d18..452466ee 100644 --- a/src/frontend/A32/decoder/thumb32.h +++ b/src/frontend/A32/decoder/thumb32.h @@ -238,7 +238,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_SADD16, "SADD16", "111110101001nnnn1111dddd0000mmmm"), INST(&V::thumb32_SASX, "SASX", "111110101010nnnn1111dddd0000mmmm"), INST(&V::thumb32_SSAX, "SSAX", "111110101110nnnn1111dddd0000mmmm"), - //INST(&V::thumb32_SSUB16, "SSUB16", "111110101101----1111----0000----"), + INST(&V::thumb32_SSUB16, "SSUB16", "111110101101nnnn1111dddd0000mmmm"), //INST(&V::thumb32_SADD8, "SADD8", "111110101000----1111----0000----"), //INST(&V::thumb32_SSUB8, "SSUB8", "111110101100----1111----0000----"), //INST(&V::thumb32_QADD16, "QADD16", "111110101001----1111----0001----"), @@ -258,7 +258,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_UADD16, "UADD16", "111110101001nnnn1111dddd0100mmmm"), INST(&V::thumb32_UASX, "UASX", "111110101010nnnn1111dddd0100mmmm"), INST(&V::thumb32_USAX, "USAX", "111110101110nnnn1111dddd0100mmmm"), - //INST(&V::thumb32_USUB16, "USUB16", "111110101101----1111----0100----"), + INST(&V::thumb32_USUB16, "USUB16", "111110101101nnnn1111dddd0100mmmm"), //INST(&V::thumb32_UADD8, "UADD8", "111110101000----1111----0100----"), //INST(&V::thumb32_USUB8, "USUB8", "111110101100----1111----0100----"), //INST(&V::thumb32_UQADD16, "UQADD16", "111110101001----1111----0101----"), diff --git a/src/frontend/A32/translate/impl/thumb32_parallel.cpp b/src/frontend/A32/translate/impl/thumb32_parallel.cpp index 32fac7dc..3589a137 100644 --- a/src/frontend/A32/translate/impl/thumb32_parallel.cpp +++ b/src/frontend/A32/translate/impl/thumb32_parallel.cpp @@ -49,6 +49,20 @@ bool ThumbTranslatorVisitor::thumb32_SSAX(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_SSUB16(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedSubS16(reg_n, reg_m); + + ir.SetRegister(d, result.result); + ir.SetGEFlags(result.ge); + return true; +} + bool ThumbTranslatorVisitor::thumb32_UADD16(Reg n, Reg d, Reg m) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); @@ -91,4 +105,18 @@ bool ThumbTranslatorVisitor::thumb32_USAX(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_USUB16(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedSubU16(reg_n, reg_m); + + ir.SetRegister(d, result.result); + ir.SetGEFlags(result.ge); + return true; +} + } // namespace Dynarmic::A32 diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index 54662723..fe8bb751 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -132,9 +132,11 @@ struct ThumbTranslatorVisitor final { bool thumb32_SADD16(Reg n, Reg d, Reg m); bool thumb32_SASX(Reg n, Reg d, Reg m); bool thumb32_SSAX(Reg n, Reg d, Reg m); + bool thumb32_SSUB16(Reg n, Reg d, Reg m); bool thumb32_UADD16(Reg n, Reg d, Reg m); bool thumb32_UASX(Reg n, Reg d, Reg m); bool thumb32_USAX(Reg n, Reg d, Reg m); + bool thumb32_USUB16(Reg n, Reg d, Reg m); }; } // namespace Dynarmic::A32 diff --git a/tests/A32/fuzz_thumb.cpp b/tests/A32/fuzz_thumb.cpp index d239f4b2..e0a5f889 100644 --- a/tests/A32/fuzz_thumb.cpp +++ b/tests/A32/fuzz_thumb.cpp @@ -420,12 +420,16 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101110nnnn1111dddd0000mmmm", // SSAX three_reg_not_r15), + ThumbInstGen("111110101101nnnn1111dddd0000mmmm", // SSUB16 + three_reg_not_r15), ThumbInstGen("111110101001nnnn1111dddd0100mmmm", // UADD16 three_reg_not_r15), ThumbInstGen("111110101010nnnn1111dddd0100mmmm", // UASX three_reg_not_r15), ThumbInstGen("111110101110nnnn1111dddd0100mmmm", // USAX three_reg_not_r15), + ThumbInstGen("111110101101nnnn1111dddd0100mmmm", // USUB16 + three_reg_not_r15), }; const auto instruction_select = [&]() -> u32 { From 271354ee95e4207eb731de879b963ed4b35e4aa0 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 1 Feb 2021 16:43:35 -0500 Subject: [PATCH 05/18] thumb32: Implement SADD8/UADD8 --- src/frontend/A32/decoder/thumb32.h | 4 +-- .../A32/translate/impl/thumb32_parallel.cpp | 28 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 2 ++ tests/A32/fuzz_thumb.cpp | 4 +++ 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/frontend/A32/decoder/thumb32.h b/src/frontend/A32/decoder/thumb32.h index 452466ee..0371e1e3 100644 --- a/src/frontend/A32/decoder/thumb32.h +++ b/src/frontend/A32/decoder/thumb32.h @@ -239,7 +239,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_SASX, "SASX", "111110101010nnnn1111dddd0000mmmm"), INST(&V::thumb32_SSAX, "SSAX", "111110101110nnnn1111dddd0000mmmm"), INST(&V::thumb32_SSUB16, "SSUB16", "111110101101nnnn1111dddd0000mmmm"), - //INST(&V::thumb32_SADD8, "SADD8", "111110101000----1111----0000----"), + INST(&V::thumb32_SADD8, "SADD8", "111110101000nnnn1111dddd0000mmmm"), //INST(&V::thumb32_SSUB8, "SSUB8", "111110101100----1111----0000----"), //INST(&V::thumb32_QADD16, "QADD16", "111110101001----1111----0001----"), //INST(&V::thumb32_QASX, "QASX", "111110101010----1111----0001----"), @@ -259,7 +259,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_UASX, "UASX", "111110101010nnnn1111dddd0100mmmm"), INST(&V::thumb32_USAX, "USAX", "111110101110nnnn1111dddd0100mmmm"), INST(&V::thumb32_USUB16, "USUB16", "111110101101nnnn1111dddd0100mmmm"), - //INST(&V::thumb32_UADD8, "UADD8", "111110101000----1111----0100----"), + INST(&V::thumb32_UADD8, "UADD8", "111110101000nnnn1111dddd0100mmmm"), //INST(&V::thumb32_USUB8, "USUB8", "111110101100----1111----0100----"), //INST(&V::thumb32_UQADD16, "UQADD16", "111110101001----1111----0101----"), //INST(&V::thumb32_UQASX, "UQASX", "111110101010----1111----0101----"), diff --git a/src/frontend/A32/translate/impl/thumb32_parallel.cpp b/src/frontend/A32/translate/impl/thumb32_parallel.cpp index 3589a137..fea76338 100644 --- a/src/frontend/A32/translate/impl/thumb32_parallel.cpp +++ b/src/frontend/A32/translate/impl/thumb32_parallel.cpp @@ -7,6 +7,20 @@ namespace Dynarmic::A32 { +bool ThumbTranslatorVisitor::thumb32_SADD8(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedAddS8(reg_n, reg_m); + + ir.SetRegister(d, result.result); + ir.SetGEFlags(result.ge); + return true; +} + bool ThumbTranslatorVisitor::thumb32_SADD16(Reg n, Reg d, Reg m) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); @@ -63,6 +77,20 @@ bool ThumbTranslatorVisitor::thumb32_SSUB16(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_UADD8(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedAddU8(reg_n, reg_m); + + ir.SetRegister(d, result.result); + ir.SetGEFlags(result.ge); + return true; +} + bool ThumbTranslatorVisitor::thumb32_UADD16(Reg n, Reg d, Reg m) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index fe8bb751..e2c52c18 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -129,10 +129,12 @@ struct ThumbTranslatorVisitor final { bool thumb32_SEL(Reg n, Reg d, Reg m); // thumb32 parallel add/sub instructions + bool thumb32_SADD8(Reg n, Reg d, Reg m); bool thumb32_SADD16(Reg n, Reg d, Reg m); bool thumb32_SASX(Reg n, Reg d, Reg m); bool thumb32_SSAX(Reg n, Reg d, Reg m); bool thumb32_SSUB16(Reg n, Reg d, Reg m); + bool thumb32_UADD8(Reg n, Reg d, Reg m); bool thumb32_UADD16(Reg n, Reg d, Reg m); bool thumb32_UASX(Reg n, Reg d, Reg m); bool thumb32_USAX(Reg n, Reg d, Reg m); diff --git a/tests/A32/fuzz_thumb.cpp b/tests/A32/fuzz_thumb.cpp index e0a5f889..ee730459 100644 --- a/tests/A32/fuzz_thumb.cpp +++ b/tests/A32/fuzz_thumb.cpp @@ -412,6 +412,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { const auto n = Common::Bits<16, 19>(inst); return m == n && d != 15 && m != 15; }), + ThumbInstGen("111110101000nnnn1111dddd0000mmmm", // SADD8 + three_reg_not_r15), ThumbInstGen("111110101001nnnn1111dddd0000mmmm", // SADD16 three_reg_not_r15), ThumbInstGen("111110101010nnnn1111dddd0000mmmm", // SASX @@ -422,6 +424,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101101nnnn1111dddd0000mmmm", // SSUB16 three_reg_not_r15), + ThumbInstGen("111110101000nnnn1111dddd0100mmmm", // UADD8 + three_reg_not_r15), ThumbInstGen("111110101001nnnn1111dddd0100mmmm", // UADD16 three_reg_not_r15), ThumbInstGen("111110101010nnnn1111dddd0100mmmm", // UASX From 6f593da41b77322ce82c2e9f770693b006e13de3 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 1 Feb 2021 16:47:12 -0500 Subject: [PATCH 06/18] thumb32: Implement SSUB8/USUB8 --- src/frontend/A32/decoder/thumb32.h | 4 +-- .../A32/translate/impl/thumb32_parallel.cpp | 28 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 2 ++ tests/A32/fuzz_thumb.cpp | 4 +++ 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/frontend/A32/decoder/thumb32.h b/src/frontend/A32/decoder/thumb32.h index 0371e1e3..dce4b27f 100644 --- a/src/frontend/A32/decoder/thumb32.h +++ b/src/frontend/A32/decoder/thumb32.h @@ -240,7 +240,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_SSAX, "SSAX", "111110101110nnnn1111dddd0000mmmm"), INST(&V::thumb32_SSUB16, "SSUB16", "111110101101nnnn1111dddd0000mmmm"), INST(&V::thumb32_SADD8, "SADD8", "111110101000nnnn1111dddd0000mmmm"), - //INST(&V::thumb32_SSUB8, "SSUB8", "111110101100----1111----0000----"), + INST(&V::thumb32_SSUB8, "SSUB8", "111110101100nnnn1111dddd0000mmmm"), //INST(&V::thumb32_QADD16, "QADD16", "111110101001----1111----0001----"), //INST(&V::thumb32_QASX, "QASX", "111110101010----1111----0001----"), //INST(&V::thumb32_QSAX, "QSAX", "111110101110----1111----0001----"), @@ -260,7 +260,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_USAX, "USAX", "111110101110nnnn1111dddd0100mmmm"), INST(&V::thumb32_USUB16, "USUB16", "111110101101nnnn1111dddd0100mmmm"), INST(&V::thumb32_UADD8, "UADD8", "111110101000nnnn1111dddd0100mmmm"), - //INST(&V::thumb32_USUB8, "USUB8", "111110101100----1111----0100----"), + INST(&V::thumb32_USUB8, "USUB8", "111110101100nnnn1111dddd0100mmmm"), //INST(&V::thumb32_UQADD16, "UQADD16", "111110101001----1111----0101----"), //INST(&V::thumb32_UQASX, "UQASX", "111110101010----1111----0101----"), //INST(&V::thumb32_UQSAX, "UQSAX", "111110101110----1111----0101----"), diff --git a/src/frontend/A32/translate/impl/thumb32_parallel.cpp b/src/frontend/A32/translate/impl/thumb32_parallel.cpp index fea76338..6db7ebe1 100644 --- a/src/frontend/A32/translate/impl/thumb32_parallel.cpp +++ b/src/frontend/A32/translate/impl/thumb32_parallel.cpp @@ -63,6 +63,20 @@ bool ThumbTranslatorVisitor::thumb32_SSAX(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_SSUB8(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedSubS8(reg_n, reg_m); + + ir.SetRegister(d, result.result); + ir.SetGEFlags(result.ge); + return true; +} + bool ThumbTranslatorVisitor::thumb32_SSUB16(Reg n, Reg d, Reg m) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); @@ -133,6 +147,20 @@ bool ThumbTranslatorVisitor::thumb32_USAX(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_USUB8(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedSubU8(reg_n, reg_m); + + ir.SetRegister(d, result.result); + ir.SetGEFlags(result.ge); + return true; +} + bool ThumbTranslatorVisitor::thumb32_USUB16(Reg n, Reg d, Reg m) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index e2c52c18..8a01ec3e 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -133,11 +133,13 @@ struct ThumbTranslatorVisitor final { bool thumb32_SADD16(Reg n, Reg d, Reg m); bool thumb32_SASX(Reg n, Reg d, Reg m); bool thumb32_SSAX(Reg n, Reg d, Reg m); + bool thumb32_SSUB8(Reg n, Reg d, Reg m); bool thumb32_SSUB16(Reg n, Reg d, Reg m); bool thumb32_UADD8(Reg n, Reg d, Reg m); bool thumb32_UADD16(Reg n, Reg d, Reg m); bool thumb32_UASX(Reg n, Reg d, Reg m); bool thumb32_USAX(Reg n, Reg d, Reg m); + bool thumb32_USUB8(Reg n, Reg d, Reg m); bool thumb32_USUB16(Reg n, Reg d, Reg m); }; diff --git a/tests/A32/fuzz_thumb.cpp b/tests/A32/fuzz_thumb.cpp index ee730459..d031ef47 100644 --- a/tests/A32/fuzz_thumb.cpp +++ b/tests/A32/fuzz_thumb.cpp @@ -422,6 +422,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101110nnnn1111dddd0000mmmm", // SSAX three_reg_not_r15), + ThumbInstGen("111110101100nnnn1111dddd0000mmmm", // SSUB8 + three_reg_not_r15), ThumbInstGen("111110101101nnnn1111dddd0000mmmm", // SSUB16 three_reg_not_r15), ThumbInstGen("111110101000nnnn1111dddd0100mmmm", // UADD8 @@ -432,6 +434,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101110nnnn1111dddd0100mmmm", // USAX three_reg_not_r15), + ThumbInstGen("111110101100nnnn1111dddd0100mmmm", // USUB8 + three_reg_not_r15), ThumbInstGen("111110101101nnnn1111dddd0100mmmm", // USUB16 three_reg_not_r15), }; From f52b8f924c47ebfb1e7cfce7e95522ea079533ac Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 1 Feb 2021 16:52:18 -0500 Subject: [PATCH 07/18] thumb32: Implement QADD16/UQADD16 --- src/frontend/A32/decoder/thumb32.h | 4 +-- .../A32/translate/impl/thumb32_parallel.cpp | 26 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 3 +++ tests/A32/fuzz_thumb.cpp | 4 +++ 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/frontend/A32/decoder/thumb32.h b/src/frontend/A32/decoder/thumb32.h index dce4b27f..fe5464b6 100644 --- a/src/frontend/A32/decoder/thumb32.h +++ b/src/frontend/A32/decoder/thumb32.h @@ -241,7 +241,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_SSUB16, "SSUB16", "111110101101nnnn1111dddd0000mmmm"), INST(&V::thumb32_SADD8, "SADD8", "111110101000nnnn1111dddd0000mmmm"), INST(&V::thumb32_SSUB8, "SSUB8", "111110101100nnnn1111dddd0000mmmm"), - //INST(&V::thumb32_QADD16, "QADD16", "111110101001----1111----0001----"), + INST(&V::thumb32_QADD16, "QADD16", "111110101001nnnn1111dddd0001mmmm"), //INST(&V::thumb32_QASX, "QASX", "111110101010----1111----0001----"), //INST(&V::thumb32_QSAX, "QSAX", "111110101110----1111----0001----"), //INST(&V::thumb32_QSUB16, "QSUB16", "111110101101----1111----0001----"), @@ -261,7 +261,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_USUB16, "USUB16", "111110101101nnnn1111dddd0100mmmm"), INST(&V::thumb32_UADD8, "UADD8", "111110101000nnnn1111dddd0100mmmm"), INST(&V::thumb32_USUB8, "USUB8", "111110101100nnnn1111dddd0100mmmm"), - //INST(&V::thumb32_UQADD16, "UQADD16", "111110101001----1111----0101----"), + INST(&V::thumb32_UQADD16, "UQADD16", "111110101001nnnn1111dddd0101mmmm"), //INST(&V::thumb32_UQASX, "UQASX", "111110101010----1111----0101----"), //INST(&V::thumb32_UQSAX, "UQSAX", "111110101110----1111----0101----"), //INST(&V::thumb32_UQSUB16, "UQSUB16", "111110101101----1111----0101----"), diff --git a/src/frontend/A32/translate/impl/thumb32_parallel.cpp b/src/frontend/A32/translate/impl/thumb32_parallel.cpp index 6db7ebe1..3e637d5c 100644 --- a/src/frontend/A32/translate/impl/thumb32_parallel.cpp +++ b/src/frontend/A32/translate/impl/thumb32_parallel.cpp @@ -175,4 +175,30 @@ bool ThumbTranslatorVisitor::thumb32_USUB16(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_QADD16(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedSaturatedAddS16(reg_n, reg_m); + + ir.SetRegister(d, result); + return true; +} + +bool ThumbTranslatorVisitor::thumb32_UQADD16(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedSaturatedAddU16(reg_n, reg_m); + + ir.SetRegister(d, result); + return true; +} + } // namespace Dynarmic::A32 diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index 8a01ec3e..22bb2b12 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -141,6 +141,9 @@ struct ThumbTranslatorVisitor final { bool thumb32_USAX(Reg n, Reg d, Reg m); bool thumb32_USUB8(Reg n, Reg d, Reg m); bool thumb32_USUB16(Reg n, Reg d, Reg m); + + bool thumb32_QADD16(Reg n, Reg d, Reg m); + bool thumb32_UQADD16(Reg n, Reg d, Reg m); }; } // namespace Dynarmic::A32 diff --git a/tests/A32/fuzz_thumb.cpp b/tests/A32/fuzz_thumb.cpp index d031ef47..12416a60 100644 --- a/tests/A32/fuzz_thumb.cpp +++ b/tests/A32/fuzz_thumb.cpp @@ -378,6 +378,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { }), ThumbInstGen("111110101000nnnn1111dddd1000mmmm", // QADD three_reg_not_r15), + ThumbInstGen("111110101001nnnn1111dddd0001mmmm", // QADD16 + three_reg_not_r15), ThumbInstGen("111110101000nnnn1111dddd1001mmmm", // QDADD three_reg_not_r15), ThumbInstGen("111110101000nnnn1111dddd1011mmmm", // QDSUB @@ -432,6 +434,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101010nnnn1111dddd0100mmmm", // UASX three_reg_not_r15), + ThumbInstGen("111110101001nnnn1111dddd0101mmmm", // UQADD16 + three_reg_not_r15), ThumbInstGen("111110101110nnnn1111dddd0100mmmm", // USAX three_reg_not_r15), ThumbInstGen("111110101100nnnn1111dddd0100mmmm", // USUB8 From ad7c8bd042fc1c8416830dd7cbdf622f24036a3d Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 1 Feb 2021 16:57:48 -0500 Subject: [PATCH 08/18] thumb32: Implement QASX/UQASX --- src/frontend/A32/decoder/thumb32.h | 4 +- .../A32/translate/impl/thumb32_parallel.cpp | 45 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 2 + tests/A32/fuzz_thumb.cpp | 4 ++ 4 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/frontend/A32/decoder/thumb32.h b/src/frontend/A32/decoder/thumb32.h index fe5464b6..15f0abc3 100644 --- a/src/frontend/A32/decoder/thumb32.h +++ b/src/frontend/A32/decoder/thumb32.h @@ -242,7 +242,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_SADD8, "SADD8", "111110101000nnnn1111dddd0000mmmm"), INST(&V::thumb32_SSUB8, "SSUB8", "111110101100nnnn1111dddd0000mmmm"), INST(&V::thumb32_QADD16, "QADD16", "111110101001nnnn1111dddd0001mmmm"), - //INST(&V::thumb32_QASX, "QASX", "111110101010----1111----0001----"), + INST(&V::thumb32_QASX, "QASX", "111110101010nnnn1111dddd0001mmmm"), //INST(&V::thumb32_QSAX, "QSAX", "111110101110----1111----0001----"), //INST(&V::thumb32_QSUB16, "QSUB16", "111110101101----1111----0001----"), //INST(&V::thumb32_QADD8, "QADD8", "111110101000----1111----0001----"), @@ -262,7 +262,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_UADD8, "UADD8", "111110101000nnnn1111dddd0100mmmm"), INST(&V::thumb32_USUB8, "USUB8", "111110101100nnnn1111dddd0100mmmm"), INST(&V::thumb32_UQADD16, "UQADD16", "111110101001nnnn1111dddd0101mmmm"), - //INST(&V::thumb32_UQASX, "UQASX", "111110101010----1111----0101----"), + INST(&V::thumb32_UQASX, "UQASX", "111110101010nnnn1111dddd0101mmmm"), //INST(&V::thumb32_UQSAX, "UQSAX", "111110101110----1111----0101----"), //INST(&V::thumb32_UQSUB16, "UQSUB16", "111110101101----1111----0101----"), //INST(&V::thumb32_UQADD8, "UQADD8", "111110101000----1111----0101----"), diff --git a/src/frontend/A32/translate/impl/thumb32_parallel.cpp b/src/frontend/A32/translate/impl/thumb32_parallel.cpp index 3e637d5c..1efbb22b 100644 --- a/src/frontend/A32/translate/impl/thumb32_parallel.cpp +++ b/src/frontend/A32/translate/impl/thumb32_parallel.cpp @@ -6,6 +6,13 @@ #include "frontend/A32/translate/impl/translate_thumb.h" namespace Dynarmic::A32 { +static IR::U32 Pack2x16To1x32(A32::IREmitter& ir, IR::U32 lo, IR::U32 hi) { + return ir.Or(ir.And(lo, ir.Imm32(0xFFFF)), ir.LogicalShiftLeft(hi, ir.Imm8(16), ir.Imm1(0)).result); +} + +static IR::U16 MostSignificantHalf(A32::IREmitter& ir, IR::U32 value) { + return ir.LeastSignificantHalf(ir.LogicalShiftRight(value, ir.Imm8(16), ir.Imm1(0)).result); +} bool ThumbTranslatorVisitor::thumb32_SADD8(Reg n, Reg d, Reg m) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { @@ -188,6 +195,25 @@ bool ThumbTranslatorVisitor::thumb32_QADD16(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_QASX(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto Rn = ir.GetRegister(n); + const auto Rm = ir.GetRegister(m); + const auto Rn_lo = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(Rn)); + const auto Rn_hi = ir.SignExtendHalfToWord(MostSignificantHalf(ir, Rn)); + const auto Rm_lo = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(Rm)); + const auto Rm_hi = ir.SignExtendHalfToWord(MostSignificantHalf(ir, Rm)); + const auto diff = ir.SignedSaturation(ir.Sub(Rn_lo, Rm_hi), 16).result; + const auto sum = ir.SignedSaturation(ir.Add(Rn_hi, Rm_lo), 16).result; + const auto result = Pack2x16To1x32(ir, diff, sum); + + ir.SetRegister(d, result); + return true; +} + bool ThumbTranslatorVisitor::thumb32_UQADD16(Reg n, Reg d, Reg m) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); @@ -201,4 +227,23 @@ bool ThumbTranslatorVisitor::thumb32_UQADD16(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_UQASX(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto Rn = ir.GetRegister(n); + const auto Rm = ir.GetRegister(m); + const auto Rn_lo = ir.ZeroExtendHalfToWord(ir.LeastSignificantHalf(Rn)); + const auto Rn_hi = ir.ZeroExtendHalfToWord(MostSignificantHalf(ir, Rn)); + const auto Rm_lo = ir.ZeroExtendHalfToWord(ir.LeastSignificantHalf(Rm)); + const auto Rm_hi = ir.ZeroExtendHalfToWord(MostSignificantHalf(ir, Rm)); + const auto diff = ir.UnsignedSaturation(ir.Sub(Rn_lo, Rm_hi), 16).result; + const auto sum = ir.UnsignedSaturation(ir.Add(Rn_hi, Rm_lo), 16).result; + const auto result = Pack2x16To1x32(ir, diff, sum); + + ir.SetRegister(d, result); + return true; +} + } // namespace Dynarmic::A32 diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index 22bb2b12..c5ea19dd 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -143,7 +143,9 @@ struct ThumbTranslatorVisitor final { bool thumb32_USUB16(Reg n, Reg d, Reg m); bool thumb32_QADD16(Reg n, Reg d, Reg m); + bool thumb32_QASX(Reg n, Reg d, Reg m); bool thumb32_UQADD16(Reg n, Reg d, Reg m); + bool thumb32_UQASX(Reg n, Reg d, Reg m); }; } // namespace Dynarmic::A32 diff --git a/tests/A32/fuzz_thumb.cpp b/tests/A32/fuzz_thumb.cpp index 12416a60..4ff5a482 100644 --- a/tests/A32/fuzz_thumb.cpp +++ b/tests/A32/fuzz_thumb.cpp @@ -380,6 +380,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101001nnnn1111dddd0001mmmm", // QADD16 three_reg_not_r15), + ThumbInstGen("111110101010nnnn1111dddd0001mmmm", // QASX + three_reg_not_r15), ThumbInstGen("111110101000nnnn1111dddd1001mmmm", // QDADD three_reg_not_r15), ThumbInstGen("111110101000nnnn1111dddd1011mmmm", // QDSUB @@ -436,6 +438,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101001nnnn1111dddd0101mmmm", // UQADD16 three_reg_not_r15), + ThumbInstGen("111110101010nnnn1111dddd0101mmmm", // UQASX + three_reg_not_r15), ThumbInstGen("111110101110nnnn1111dddd0100mmmm", // USAX three_reg_not_r15), ThumbInstGen("111110101100nnnn1111dddd0100mmmm", // USUB8 From 416fe26df00538fac19cac1b88edd2894ab08c08 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 1 Feb 2021 17:01:29 -0500 Subject: [PATCH 09/18] thumb32: Implement QSAX/UQSAX --- src/frontend/A32/decoder/thumb32.h | 4 +- .../A32/translate/impl/thumb32_parallel.cpp | 38 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 2 + tests/A32/fuzz_thumb.cpp | 4 ++ 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/frontend/A32/decoder/thumb32.h b/src/frontend/A32/decoder/thumb32.h index 15f0abc3..18331827 100644 --- a/src/frontend/A32/decoder/thumb32.h +++ b/src/frontend/A32/decoder/thumb32.h @@ -243,7 +243,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_SSUB8, "SSUB8", "111110101100nnnn1111dddd0000mmmm"), INST(&V::thumb32_QADD16, "QADD16", "111110101001nnnn1111dddd0001mmmm"), INST(&V::thumb32_QASX, "QASX", "111110101010nnnn1111dddd0001mmmm"), - //INST(&V::thumb32_QSAX, "QSAX", "111110101110----1111----0001----"), + INST(&V::thumb32_QSAX, "QSAX", "111110101110nnnn1111dddd0001mmmm"), //INST(&V::thumb32_QSUB16, "QSUB16", "111110101101----1111----0001----"), //INST(&V::thumb32_QADD8, "QADD8", "111110101000----1111----0001----"), //INST(&V::thumb32_QSUB8, "QSUB8", "111110101100----1111----0001----"), @@ -263,7 +263,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_USUB8, "USUB8", "111110101100nnnn1111dddd0100mmmm"), INST(&V::thumb32_UQADD16, "UQADD16", "111110101001nnnn1111dddd0101mmmm"), INST(&V::thumb32_UQASX, "UQASX", "111110101010nnnn1111dddd0101mmmm"), - //INST(&V::thumb32_UQSAX, "UQSAX", "111110101110----1111----0101----"), + INST(&V::thumb32_UQSAX, "UQSAX", "111110101110nnnn1111dddd0101mmmm"), //INST(&V::thumb32_UQSUB16, "UQSUB16", "111110101101----1111----0101----"), //INST(&V::thumb32_UQADD8, "UQADD8", "111110101000----1111----0101----"), //INST(&V::thumb32_UQSUB8, "UQSUB8", "111110101100----1111----0101----"), diff --git a/src/frontend/A32/translate/impl/thumb32_parallel.cpp b/src/frontend/A32/translate/impl/thumb32_parallel.cpp index 1efbb22b..9bd865ae 100644 --- a/src/frontend/A32/translate/impl/thumb32_parallel.cpp +++ b/src/frontend/A32/translate/impl/thumb32_parallel.cpp @@ -214,6 +214,25 @@ bool ThumbTranslatorVisitor::thumb32_QASX(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_QSAX(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto Rn = ir.GetRegister(n); + const auto Rm = ir.GetRegister(m); + const auto Rn_lo = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(Rn)); + const auto Rn_hi = ir.SignExtendHalfToWord(MostSignificantHalf(ir, Rn)); + const auto Rm_lo = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(Rm)); + const auto Rm_hi = ir.SignExtendHalfToWord(MostSignificantHalf(ir, Rm)); + const auto sum = ir.SignedSaturation(ir.Add(Rn_lo, Rm_hi), 16).result; + const auto diff = ir.SignedSaturation(ir.Sub(Rn_hi, Rm_lo), 16).result; + const auto result = Pack2x16To1x32(ir, sum, diff); + + ir.SetRegister(d, result); + return true; +} + bool ThumbTranslatorVisitor::thumb32_UQADD16(Reg n, Reg d, Reg m) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); @@ -246,4 +265,23 @@ bool ThumbTranslatorVisitor::thumb32_UQASX(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_UQSAX(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto Rn = ir.GetRegister(n); + const auto Rm = ir.GetRegister(m); + const auto Rn_lo = ir.ZeroExtendHalfToWord(ir.LeastSignificantHalf(Rn)); + const auto Rn_hi = ir.ZeroExtendHalfToWord(MostSignificantHalf(ir, Rn)); + const auto Rm_lo = ir.ZeroExtendHalfToWord(ir.LeastSignificantHalf(Rm)); + const auto Rm_hi = ir.ZeroExtendHalfToWord(MostSignificantHalf(ir, Rm)); + const auto sum = ir.UnsignedSaturation(ir.Add(Rn_lo, Rm_hi), 16).result; + const auto diff = ir.UnsignedSaturation(ir.Sub(Rn_hi, Rm_lo), 16).result; + const auto result = Pack2x16To1x32(ir, sum, diff); + + ir.SetRegister(d, result); + return true; +} + } // namespace Dynarmic::A32 diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index c5ea19dd..16e1233e 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -144,8 +144,10 @@ struct ThumbTranslatorVisitor final { bool thumb32_QADD16(Reg n, Reg d, Reg m); bool thumb32_QASX(Reg n, Reg d, Reg m); + bool thumb32_QSAX(Reg n, Reg d, Reg m); bool thumb32_UQADD16(Reg n, Reg d, Reg m); bool thumb32_UQASX(Reg n, Reg d, Reg m); + bool thumb32_UQSAX(Reg n, Reg d, Reg m); }; } // namespace Dynarmic::A32 diff --git a/tests/A32/fuzz_thumb.cpp b/tests/A32/fuzz_thumb.cpp index 4ff5a482..9d9fda33 100644 --- a/tests/A32/fuzz_thumb.cpp +++ b/tests/A32/fuzz_thumb.cpp @@ -386,6 +386,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101000nnnn1111dddd1011mmmm", // QDSUB three_reg_not_r15), + ThumbInstGen("111110101110nnnn1111dddd0001mmmm", // QSAX + three_reg_not_r15), ThumbInstGen("111110101000nnnn1111dddd1010mmmm", // QSUB three_reg_not_r15), ThumbInstGen("111110101001nnnn1111dddd1010mmmm", // RBIT @@ -440,6 +442,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101010nnnn1111dddd0101mmmm", // UQASX three_reg_not_r15), + ThumbInstGen("111110101110nnnn1111dddd0101mmmm", // UQSAX + three_reg_not_r15), ThumbInstGen("111110101110nnnn1111dddd0100mmmm", // USAX three_reg_not_r15), ThumbInstGen("111110101100nnnn1111dddd0100mmmm", // USUB8 From d923fb24c6f7f4ef3e81906d75c15904f9cdfa3e Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 1 Feb 2021 17:05:17 -0500 Subject: [PATCH 10/18] thumb32: Implement QSUB16/UQSUB16 --- src/frontend/A32/decoder/thumb32.h | 4 +-- .../A32/translate/impl/thumb32_parallel.cpp | 26 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 2 ++ tests/A32/fuzz_thumb.cpp | 4 +++ 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/frontend/A32/decoder/thumb32.h b/src/frontend/A32/decoder/thumb32.h index 18331827..09da4857 100644 --- a/src/frontend/A32/decoder/thumb32.h +++ b/src/frontend/A32/decoder/thumb32.h @@ -244,7 +244,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_QADD16, "QADD16", "111110101001nnnn1111dddd0001mmmm"), INST(&V::thumb32_QASX, "QASX", "111110101010nnnn1111dddd0001mmmm"), INST(&V::thumb32_QSAX, "QSAX", "111110101110nnnn1111dddd0001mmmm"), - //INST(&V::thumb32_QSUB16, "QSUB16", "111110101101----1111----0001----"), + INST(&V::thumb32_QSUB16, "QSUB16", "111110101101nnnn1111dddd0001mmmm"), //INST(&V::thumb32_QADD8, "QADD8", "111110101000----1111----0001----"), //INST(&V::thumb32_QSUB8, "QSUB8", "111110101100----1111----0001----"), //INST(&V::thumb32_SHADD16, "SHADD16", "111110101001----1111----0010----"), @@ -264,7 +264,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_UQADD16, "UQADD16", "111110101001nnnn1111dddd0101mmmm"), INST(&V::thumb32_UQASX, "UQASX", "111110101010nnnn1111dddd0101mmmm"), INST(&V::thumb32_UQSAX, "UQSAX", "111110101110nnnn1111dddd0101mmmm"), - //INST(&V::thumb32_UQSUB16, "UQSUB16", "111110101101----1111----0101----"), + INST(&V::thumb32_UQSUB16, "UQSUB16", "111110101101nnnn1111dddd0101mmmm"), //INST(&V::thumb32_UQADD8, "UQADD8", "111110101000----1111----0101----"), //INST(&V::thumb32_UQSUB8, "UQSUB8", "111110101100----1111----0101----"), //INST(&V::thumb32_UHADD16, "UHADD16", "111110101001----1111----0110----"), diff --git a/src/frontend/A32/translate/impl/thumb32_parallel.cpp b/src/frontend/A32/translate/impl/thumb32_parallel.cpp index 9bd865ae..26373fad 100644 --- a/src/frontend/A32/translate/impl/thumb32_parallel.cpp +++ b/src/frontend/A32/translate/impl/thumb32_parallel.cpp @@ -233,6 +233,19 @@ bool ThumbTranslatorVisitor::thumb32_QSAX(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_QSUB16(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedSaturatedSubS16(reg_n, reg_m); + + ir.SetRegister(d, result); + return true; +} + bool ThumbTranslatorVisitor::thumb32_UQADD16(Reg n, Reg d, Reg m) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); @@ -284,4 +297,17 @@ bool ThumbTranslatorVisitor::thumb32_UQSAX(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_UQSUB16(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedSaturatedSubU16(reg_n, reg_m); + + ir.SetRegister(d, result); + return true; +} + } // namespace Dynarmic::A32 diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index 16e1233e..6ef23c0d 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -145,9 +145,11 @@ struct ThumbTranslatorVisitor final { bool thumb32_QADD16(Reg n, Reg d, Reg m); bool thumb32_QASX(Reg n, Reg d, Reg m); bool thumb32_QSAX(Reg n, Reg d, Reg m); + bool thumb32_QSUB16(Reg n, Reg d, Reg m); bool thumb32_UQADD16(Reg n, Reg d, Reg m); bool thumb32_UQASX(Reg n, Reg d, Reg m); bool thumb32_UQSAX(Reg n, Reg d, Reg m); + bool thumb32_UQSUB16(Reg n, Reg d, Reg m); }; } // namespace Dynarmic::A32 diff --git a/tests/A32/fuzz_thumb.cpp b/tests/A32/fuzz_thumb.cpp index 9d9fda33..700193f9 100644 --- a/tests/A32/fuzz_thumb.cpp +++ b/tests/A32/fuzz_thumb.cpp @@ -390,6 +390,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101000nnnn1111dddd1010mmmm", // QSUB three_reg_not_r15), + ThumbInstGen("111110101101nnnn1111dddd0001mmmm", // QSUB16 + three_reg_not_r15), ThumbInstGen("111110101001nnnn1111dddd1010mmmm", // RBIT [](u32 inst) { const auto d = Common::Bits<8, 11>(inst); @@ -444,6 +446,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101110nnnn1111dddd0101mmmm", // UQSAX three_reg_not_r15), + ThumbInstGen("111110101101nnnn1111dddd0101mmmm", // UQSUB16 + three_reg_not_r15), ThumbInstGen("111110101110nnnn1111dddd0100mmmm", // USAX three_reg_not_r15), ThumbInstGen("111110101100nnnn1111dddd0100mmmm", // USUB8 From 874ab6a7b6fbe057ed23179e3d98149996b36bc2 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 1 Feb 2021 17:08:00 -0500 Subject: [PATCH 11/18] thumb32: Implement QADD8/UQADD8 --- src/frontend/A32/decoder/thumb32.h | 4 +-- .../A32/translate/impl/thumb32_parallel.cpp | 26 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 2 ++ tests/A32/fuzz_thumb.cpp | 4 +++ 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/frontend/A32/decoder/thumb32.h b/src/frontend/A32/decoder/thumb32.h index 09da4857..ece127a9 100644 --- a/src/frontend/A32/decoder/thumb32.h +++ b/src/frontend/A32/decoder/thumb32.h @@ -245,7 +245,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_QASX, "QASX", "111110101010nnnn1111dddd0001mmmm"), INST(&V::thumb32_QSAX, "QSAX", "111110101110nnnn1111dddd0001mmmm"), INST(&V::thumb32_QSUB16, "QSUB16", "111110101101nnnn1111dddd0001mmmm"), - //INST(&V::thumb32_QADD8, "QADD8", "111110101000----1111----0001----"), + INST(&V::thumb32_QADD8, "QADD8", "111110101000nnnn1111dddd0001mmmm"), //INST(&V::thumb32_QSUB8, "QSUB8", "111110101100----1111----0001----"), //INST(&V::thumb32_SHADD16, "SHADD16", "111110101001----1111----0010----"), //INST(&V::thumb32_SHASX, "SHASX", "111110101010----1111----0010----"), @@ -265,7 +265,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_UQASX, "UQASX", "111110101010nnnn1111dddd0101mmmm"), INST(&V::thumb32_UQSAX, "UQSAX", "111110101110nnnn1111dddd0101mmmm"), INST(&V::thumb32_UQSUB16, "UQSUB16", "111110101101nnnn1111dddd0101mmmm"), - //INST(&V::thumb32_UQADD8, "UQADD8", "111110101000----1111----0101----"), + INST(&V::thumb32_UQADD8, "UQADD8", "111110101000nnnn1111dddd0101mmmm"), //INST(&V::thumb32_UQSUB8, "UQSUB8", "111110101100----1111----0101----"), //INST(&V::thumb32_UHADD16, "UHADD16", "111110101001----1111----0110----"), //INST(&V::thumb32_UHASX, "UHASX", "111110101010----1111----0110----"), diff --git a/src/frontend/A32/translate/impl/thumb32_parallel.cpp b/src/frontend/A32/translate/impl/thumb32_parallel.cpp index 26373fad..ff9f3858 100644 --- a/src/frontend/A32/translate/impl/thumb32_parallel.cpp +++ b/src/frontend/A32/translate/impl/thumb32_parallel.cpp @@ -182,6 +182,19 @@ bool ThumbTranslatorVisitor::thumb32_USUB16(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_QADD8(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedSaturatedAddS8(reg_n, reg_m); + + ir.SetRegister(d, result); + return true; +} + bool ThumbTranslatorVisitor::thumb32_QADD16(Reg n, Reg d, Reg m) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); @@ -246,6 +259,19 @@ bool ThumbTranslatorVisitor::thumb32_QSUB16(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_UQADD8(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedSaturatedAddU8(reg_n, reg_m); + + ir.SetRegister(d, result); + return true; +} + bool ThumbTranslatorVisitor::thumb32_UQADD16(Reg n, Reg d, Reg m) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index 6ef23c0d..7011ff0b 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -142,10 +142,12 @@ struct ThumbTranslatorVisitor final { bool thumb32_USUB8(Reg n, Reg d, Reg m); bool thumb32_USUB16(Reg n, Reg d, Reg m); + bool thumb32_QADD8(Reg n, Reg d, Reg m); bool thumb32_QADD16(Reg n, Reg d, Reg m); bool thumb32_QASX(Reg n, Reg d, Reg m); bool thumb32_QSAX(Reg n, Reg d, Reg m); bool thumb32_QSUB16(Reg n, Reg d, Reg m); + bool thumb32_UQADD8(Reg n, Reg d, Reg m); bool thumb32_UQADD16(Reg n, Reg d, Reg m); bool thumb32_UQASX(Reg n, Reg d, Reg m); bool thumb32_UQSAX(Reg n, Reg d, Reg m); diff --git a/tests/A32/fuzz_thumb.cpp b/tests/A32/fuzz_thumb.cpp index 700193f9..d0a2dbe9 100644 --- a/tests/A32/fuzz_thumb.cpp +++ b/tests/A32/fuzz_thumb.cpp @@ -378,6 +378,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { }), ThumbInstGen("111110101000nnnn1111dddd1000mmmm", // QADD three_reg_not_r15), + ThumbInstGen("111110101000nnnn1111dddd0001mmmm", // QADD8 + three_reg_not_r15), ThumbInstGen("111110101001nnnn1111dddd0001mmmm", // QADD16 three_reg_not_r15), ThumbInstGen("111110101010nnnn1111dddd0001mmmm", // QASX @@ -440,6 +442,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101010nnnn1111dddd0100mmmm", // UASX three_reg_not_r15), + ThumbInstGen("111110101000nnnn1111dddd0101mmmm", // UQADD8 + three_reg_not_r15), ThumbInstGen("111110101001nnnn1111dddd0101mmmm", // UQADD16 three_reg_not_r15), ThumbInstGen("111110101010nnnn1111dddd0101mmmm", // UQASX From aa49b0db89536557e5816efba1cb53950229d5cc Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 1 Feb 2021 17:10:17 -0500 Subject: [PATCH 12/18] thumb32: Implement QSUB8/UQSUB8 --- src/frontend/A32/decoder/thumb32.h | 4 +-- .../A32/translate/impl/thumb32_parallel.cpp | 26 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 2 ++ tests/A32/fuzz_thumb.cpp | 4 +++ 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/frontend/A32/decoder/thumb32.h b/src/frontend/A32/decoder/thumb32.h index ece127a9..24e1ec56 100644 --- a/src/frontend/A32/decoder/thumb32.h +++ b/src/frontend/A32/decoder/thumb32.h @@ -246,7 +246,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_QSAX, "QSAX", "111110101110nnnn1111dddd0001mmmm"), INST(&V::thumb32_QSUB16, "QSUB16", "111110101101nnnn1111dddd0001mmmm"), INST(&V::thumb32_QADD8, "QADD8", "111110101000nnnn1111dddd0001mmmm"), - //INST(&V::thumb32_QSUB8, "QSUB8", "111110101100----1111----0001----"), + INST(&V::thumb32_QSUB8, "QSUB8", "111110101100nnnn1111dddd0001mmmm"), //INST(&V::thumb32_SHADD16, "SHADD16", "111110101001----1111----0010----"), //INST(&V::thumb32_SHASX, "SHASX", "111110101010----1111----0010----"), //INST(&V::thumb32_SHSAX, "SHSAX", "111110101110----1111----0010----"), @@ -266,7 +266,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_UQSAX, "UQSAX", "111110101110nnnn1111dddd0101mmmm"), INST(&V::thumb32_UQSUB16, "UQSUB16", "111110101101nnnn1111dddd0101mmmm"), INST(&V::thumb32_UQADD8, "UQADD8", "111110101000nnnn1111dddd0101mmmm"), - //INST(&V::thumb32_UQSUB8, "UQSUB8", "111110101100----1111----0101----"), + INST(&V::thumb32_UQSUB8, "UQSUB8", "111110101100nnnn1111dddd0101mmmm"), //INST(&V::thumb32_UHADD16, "UHADD16", "111110101001----1111----0110----"), //INST(&V::thumb32_UHASX, "UHASX", "111110101010----1111----0110----"), //INST(&V::thumb32_UHSAX, "UHSAX", "111110101110----1111----0110----"), diff --git a/src/frontend/A32/translate/impl/thumb32_parallel.cpp b/src/frontend/A32/translate/impl/thumb32_parallel.cpp index ff9f3858..b3b5cd3b 100644 --- a/src/frontend/A32/translate/impl/thumb32_parallel.cpp +++ b/src/frontend/A32/translate/impl/thumb32_parallel.cpp @@ -246,6 +246,19 @@ bool ThumbTranslatorVisitor::thumb32_QSAX(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_QSUB8(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedSaturatedSubS8(reg_n, reg_m); + + ir.SetRegister(d, result); + return true; +} + bool ThumbTranslatorVisitor::thumb32_QSUB16(Reg n, Reg d, Reg m) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); @@ -323,6 +336,19 @@ bool ThumbTranslatorVisitor::thumb32_UQSAX(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_UQSUB8(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedSaturatedSubU8(reg_n, reg_m); + + ir.SetRegister(d, result); + return true; +} + bool ThumbTranslatorVisitor::thumb32_UQSUB16(Reg n, Reg d, Reg m) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index 7011ff0b..a88f406b 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -146,11 +146,13 @@ struct ThumbTranslatorVisitor final { bool thumb32_QADD16(Reg n, Reg d, Reg m); bool thumb32_QASX(Reg n, Reg d, Reg m); bool thumb32_QSAX(Reg n, Reg d, Reg m); + bool thumb32_QSUB8(Reg n, Reg d, Reg m); bool thumb32_QSUB16(Reg n, Reg d, Reg m); bool thumb32_UQADD8(Reg n, Reg d, Reg m); bool thumb32_UQADD16(Reg n, Reg d, Reg m); bool thumb32_UQASX(Reg n, Reg d, Reg m); bool thumb32_UQSAX(Reg n, Reg d, Reg m); + bool thumb32_UQSUB8(Reg n, Reg d, Reg m); bool thumb32_UQSUB16(Reg n, Reg d, Reg m); }; diff --git a/tests/A32/fuzz_thumb.cpp b/tests/A32/fuzz_thumb.cpp index d0a2dbe9..47064207 100644 --- a/tests/A32/fuzz_thumb.cpp +++ b/tests/A32/fuzz_thumb.cpp @@ -392,6 +392,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101000nnnn1111dddd1010mmmm", // QSUB three_reg_not_r15), + ThumbInstGen("111110101100nnnn1111dddd0001mmmm", // QSUB8 + three_reg_not_r15), ThumbInstGen("111110101101nnnn1111dddd0001mmmm", // QSUB16 three_reg_not_r15), ThumbInstGen("111110101001nnnn1111dddd1010mmmm", // RBIT @@ -450,6 +452,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101110nnnn1111dddd0101mmmm", // UQSAX three_reg_not_r15), + ThumbInstGen("111110101100nnnn1111dddd0101mmmm", // UQSUB8 + three_reg_not_r15), ThumbInstGen("111110101101nnnn1111dddd0101mmmm", // UQSUB16 three_reg_not_r15), ThumbInstGen("111110101110nnnn1111dddd0100mmmm", // USAX From 94f8efbb033e9838148009f6cff4e536c089e1c0 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 1 Feb 2021 17:13:44 -0500 Subject: [PATCH 13/18] thumb32: Implement SHADD16/UHADD16 --- src/frontend/A32/decoder/thumb32.h | 4 +-- .../A32/translate/impl/thumb32_parallel.cpp | 26 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 3 +++ tests/A32/fuzz_thumb.cpp | 4 +++ 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/frontend/A32/decoder/thumb32.h b/src/frontend/A32/decoder/thumb32.h index 24e1ec56..7b9c5c01 100644 --- a/src/frontend/A32/decoder/thumb32.h +++ b/src/frontend/A32/decoder/thumb32.h @@ -247,7 +247,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_QSUB16, "QSUB16", "111110101101nnnn1111dddd0001mmmm"), INST(&V::thumb32_QADD8, "QADD8", "111110101000nnnn1111dddd0001mmmm"), INST(&V::thumb32_QSUB8, "QSUB8", "111110101100nnnn1111dddd0001mmmm"), - //INST(&V::thumb32_SHADD16, "SHADD16", "111110101001----1111----0010----"), + INST(&V::thumb32_SHADD16, "SHADD16", "111110101001nnnn1111dddd0010mmmm"), //INST(&V::thumb32_SHASX, "SHASX", "111110101010----1111----0010----"), //INST(&V::thumb32_SHSAX, "SHSAX", "111110101110----1111----0010----"), //INST(&V::thumb32_SHSUB16, "SHSUB16", "111110101101----1111----0010----"), @@ -267,7 +267,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_UQSUB16, "UQSUB16", "111110101101nnnn1111dddd0101mmmm"), INST(&V::thumb32_UQADD8, "UQADD8", "111110101000nnnn1111dddd0101mmmm"), INST(&V::thumb32_UQSUB8, "UQSUB8", "111110101100nnnn1111dddd0101mmmm"), - //INST(&V::thumb32_UHADD16, "UHADD16", "111110101001----1111----0110----"), + INST(&V::thumb32_UHADD16, "UHADD16", "111110101001nnnn1111dddd0110mmmm"), //INST(&V::thumb32_UHASX, "UHASX", "111110101010----1111----0110----"), //INST(&V::thumb32_UHSAX, "UHSAX", "111110101110----1111----0110----"), //INST(&V::thumb32_UHSUB16, "UHSUB16", "111110101101----1111----0110----"), diff --git a/src/frontend/A32/translate/impl/thumb32_parallel.cpp b/src/frontend/A32/translate/impl/thumb32_parallel.cpp index b3b5cd3b..c00b8c5a 100644 --- a/src/frontend/A32/translate/impl/thumb32_parallel.cpp +++ b/src/frontend/A32/translate/impl/thumb32_parallel.cpp @@ -362,4 +362,30 @@ bool ThumbTranslatorVisitor::thumb32_UQSUB16(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_SHADD16(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedHalvingAddS16(reg_n, reg_m); + + ir.SetRegister(d, result); + return true; +} + +bool ThumbTranslatorVisitor::thumb32_UHADD16(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedHalvingAddU16(reg_n, reg_m); + + ir.SetRegister(d, result); + return true; +} + } // namespace Dynarmic::A32 diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index a88f406b..25413df2 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -154,6 +154,9 @@ struct ThumbTranslatorVisitor final { bool thumb32_UQSAX(Reg n, Reg d, Reg m); bool thumb32_UQSUB8(Reg n, Reg d, Reg m); bool thumb32_UQSUB16(Reg n, Reg d, Reg m); + + bool thumb32_SHADD16(Reg n, Reg d, Reg m); + bool thumb32_UHADD16(Reg n, Reg d, Reg m); }; } // namespace Dynarmic::A32 diff --git a/tests/A32/fuzz_thumb.cpp b/tests/A32/fuzz_thumb.cpp index 47064207..b02f0c4b 100644 --- a/tests/A32/fuzz_thumb.cpp +++ b/tests/A32/fuzz_thumb.cpp @@ -432,6 +432,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101010nnnn1111dddd1000mmmm", // SEL three_reg_not_r15), + ThumbInstGen("111110101001nnnn1111dddd0010mmmm", // SHADD16 + three_reg_not_r15), ThumbInstGen("111110101110nnnn1111dddd0000mmmm", // SSAX three_reg_not_r15), ThumbInstGen("111110101100nnnn1111dddd0000mmmm", // SSUB8 @@ -444,6 +446,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101010nnnn1111dddd0100mmmm", // UASX three_reg_not_r15), + ThumbInstGen("111110101001nnnn1111dddd0110mmmm", // UHADD16 + three_reg_not_r15), ThumbInstGen("111110101000nnnn1111dddd0101mmmm", // UQADD8 three_reg_not_r15), ThumbInstGen("111110101001nnnn1111dddd0101mmmm", // UQADD16 From f0a219fcd0d9dceb3d8a69d400a8368c4977f346 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 1 Feb 2021 17:16:28 -0500 Subject: [PATCH 14/18] thumb32: Implement SHASX/UHASX --- src/frontend/A32/decoder/thumb32.h | 4 +-- .../A32/translate/impl/thumb32_parallel.cpp | 26 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 2 ++ tests/A32/fuzz_thumb.cpp | 4 +++ 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/frontend/A32/decoder/thumb32.h b/src/frontend/A32/decoder/thumb32.h index 7b9c5c01..02da295a 100644 --- a/src/frontend/A32/decoder/thumb32.h +++ b/src/frontend/A32/decoder/thumb32.h @@ -248,7 +248,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_QADD8, "QADD8", "111110101000nnnn1111dddd0001mmmm"), INST(&V::thumb32_QSUB8, "QSUB8", "111110101100nnnn1111dddd0001mmmm"), INST(&V::thumb32_SHADD16, "SHADD16", "111110101001nnnn1111dddd0010mmmm"), - //INST(&V::thumb32_SHASX, "SHASX", "111110101010----1111----0010----"), + INST(&V::thumb32_SHASX, "SHASX", "111110101010nnnn1111dddd0010mmmm"), //INST(&V::thumb32_SHSAX, "SHSAX", "111110101110----1111----0010----"), //INST(&V::thumb32_SHSUB16, "SHSUB16", "111110101101----1111----0010----"), //INST(&V::thumb32_SHADD8, "SHADD8", "111110101000----1111----0010----"), @@ -268,7 +268,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_UQADD8, "UQADD8", "111110101000nnnn1111dddd0101mmmm"), INST(&V::thumb32_UQSUB8, "UQSUB8", "111110101100nnnn1111dddd0101mmmm"), INST(&V::thumb32_UHADD16, "UHADD16", "111110101001nnnn1111dddd0110mmmm"), - //INST(&V::thumb32_UHASX, "UHASX", "111110101010----1111----0110----"), + INST(&V::thumb32_UHASX, "UHASX", "111110101010nnnn1111dddd0110mmmm"), //INST(&V::thumb32_UHSAX, "UHSAX", "111110101110----1111----0110----"), //INST(&V::thumb32_UHSUB16, "UHSUB16", "111110101101----1111----0110----"), //INST(&V::thumb32_UHADD8, "UHADD8", "111110101000----1111----0110----"), diff --git a/src/frontend/A32/translate/impl/thumb32_parallel.cpp b/src/frontend/A32/translate/impl/thumb32_parallel.cpp index c00b8c5a..0c5fca8e 100644 --- a/src/frontend/A32/translate/impl/thumb32_parallel.cpp +++ b/src/frontend/A32/translate/impl/thumb32_parallel.cpp @@ -375,6 +375,19 @@ bool ThumbTranslatorVisitor::thumb32_SHADD16(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_SHASX(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedHalvingAddSubS16(reg_n, reg_m); + + ir.SetRegister(d, result); + return true; +} + bool ThumbTranslatorVisitor::thumb32_UHADD16(Reg n, Reg d, Reg m) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); @@ -388,4 +401,17 @@ bool ThumbTranslatorVisitor::thumb32_UHADD16(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_UHASX(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedHalvingAddSubU16(reg_n, reg_m); + + ir.SetRegister(d, result); + return true; +} + } // namespace Dynarmic::A32 diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index 25413df2..8edfd506 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -156,7 +156,9 @@ struct ThumbTranslatorVisitor final { bool thumb32_UQSUB16(Reg n, Reg d, Reg m); bool thumb32_SHADD16(Reg n, Reg d, Reg m); + bool thumb32_SHASX(Reg n, Reg d, Reg m); bool thumb32_UHADD16(Reg n, Reg d, Reg m); + bool thumb32_UHASX(Reg n, Reg d, Reg m); }; } // namespace Dynarmic::A32 diff --git a/tests/A32/fuzz_thumb.cpp b/tests/A32/fuzz_thumb.cpp index b02f0c4b..d9dcd349 100644 --- a/tests/A32/fuzz_thumb.cpp +++ b/tests/A32/fuzz_thumb.cpp @@ -434,6 +434,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101001nnnn1111dddd0010mmmm", // SHADD16 three_reg_not_r15), + ThumbInstGen("111110101010nnnn1111dddd0010mmmm", // SHASX + three_reg_not_r15), ThumbInstGen("111110101110nnnn1111dddd0000mmmm", // SSAX three_reg_not_r15), ThumbInstGen("111110101100nnnn1111dddd0000mmmm", // SSUB8 @@ -448,6 +450,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101001nnnn1111dddd0110mmmm", // UHADD16 three_reg_not_r15), + ThumbInstGen("111110101010nnnn1111dddd0110mmmm", // UHASX + three_reg_not_r15), ThumbInstGen("111110101000nnnn1111dddd0101mmmm", // UQADD8 three_reg_not_r15), ThumbInstGen("111110101001nnnn1111dddd0101mmmm", // UQADD16 From 51b7c32d02c04ce264d423f8842bcdd5b1fa8017 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 1 Feb 2021 17:19:04 -0500 Subject: [PATCH 15/18] thumb32: Implement SHSAX/UHSAX --- src/frontend/A32/decoder/thumb32.h | 4 +-- .../A32/translate/impl/thumb32_parallel.cpp | 26 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 2 ++ tests/A32/fuzz_thumb.cpp | 4 +++ 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/frontend/A32/decoder/thumb32.h b/src/frontend/A32/decoder/thumb32.h index 02da295a..b84994d3 100644 --- a/src/frontend/A32/decoder/thumb32.h +++ b/src/frontend/A32/decoder/thumb32.h @@ -249,7 +249,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_QSUB8, "QSUB8", "111110101100nnnn1111dddd0001mmmm"), INST(&V::thumb32_SHADD16, "SHADD16", "111110101001nnnn1111dddd0010mmmm"), INST(&V::thumb32_SHASX, "SHASX", "111110101010nnnn1111dddd0010mmmm"), - //INST(&V::thumb32_SHSAX, "SHSAX", "111110101110----1111----0010----"), + INST(&V::thumb32_SHSAX, "SHSAX", "111110101110nnnn1111dddd0010mmmm"), //INST(&V::thumb32_SHSUB16, "SHSUB16", "111110101101----1111----0010----"), //INST(&V::thumb32_SHADD8, "SHADD8", "111110101000----1111----0010----"), //INST(&V::thumb32_SHSUB8, "SHSUB8", "111110101100----1111----0010----"), @@ -269,7 +269,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_UQSUB8, "UQSUB8", "111110101100nnnn1111dddd0101mmmm"), INST(&V::thumb32_UHADD16, "UHADD16", "111110101001nnnn1111dddd0110mmmm"), INST(&V::thumb32_UHASX, "UHASX", "111110101010nnnn1111dddd0110mmmm"), - //INST(&V::thumb32_UHSAX, "UHSAX", "111110101110----1111----0110----"), + INST(&V::thumb32_UHSAX, "UHSAX", "111110101110nnnn1111dddd0110mmmm"), //INST(&V::thumb32_UHSUB16, "UHSUB16", "111110101101----1111----0110----"), //INST(&V::thumb32_UHADD8, "UHADD8", "111110101000----1111----0110----"), //INST(&V::thumb32_UHSUB8, "UHSUB8", "111110101100----1111----0110----"), diff --git a/src/frontend/A32/translate/impl/thumb32_parallel.cpp b/src/frontend/A32/translate/impl/thumb32_parallel.cpp index 0c5fca8e..c5e6a878 100644 --- a/src/frontend/A32/translate/impl/thumb32_parallel.cpp +++ b/src/frontend/A32/translate/impl/thumb32_parallel.cpp @@ -388,6 +388,19 @@ bool ThumbTranslatorVisitor::thumb32_SHASX(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_SHSAX(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedHalvingSubAddS16(reg_n, reg_m); + + ir.SetRegister(d, result); + return true; +} + bool ThumbTranslatorVisitor::thumb32_UHADD16(Reg n, Reg d, Reg m) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); @@ -414,4 +427,17 @@ bool ThumbTranslatorVisitor::thumb32_UHASX(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_UHSAX(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedHalvingSubAddU16(reg_n, reg_m); + + ir.SetRegister(d, result); + return true; +} + } // namespace Dynarmic::A32 diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index 8edfd506..20088da3 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -157,8 +157,10 @@ struct ThumbTranslatorVisitor final { bool thumb32_SHADD16(Reg n, Reg d, Reg m); bool thumb32_SHASX(Reg n, Reg d, Reg m); + bool thumb32_SHSAX(Reg n, Reg d, Reg m); bool thumb32_UHADD16(Reg n, Reg d, Reg m); bool thumb32_UHASX(Reg n, Reg d, Reg m); + bool thumb32_UHSAX(Reg n, Reg d, Reg m); }; } // namespace Dynarmic::A32 diff --git a/tests/A32/fuzz_thumb.cpp b/tests/A32/fuzz_thumb.cpp index d9dcd349..8931c2ac 100644 --- a/tests/A32/fuzz_thumb.cpp +++ b/tests/A32/fuzz_thumb.cpp @@ -436,6 +436,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101010nnnn1111dddd0010mmmm", // SHASX three_reg_not_r15), + ThumbInstGen("111110101110nnnn1111dddd0010mmmm", // SHSAX + three_reg_not_r15), ThumbInstGen("111110101110nnnn1111dddd0000mmmm", // SSAX three_reg_not_r15), ThumbInstGen("111110101100nnnn1111dddd0000mmmm", // SSUB8 @@ -452,6 +454,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101010nnnn1111dddd0110mmmm", // UHASX three_reg_not_r15), + ThumbInstGen("111110101110nnnn1111dddd0110mmmm", // UHSAX + three_reg_not_r15), ThumbInstGen("111110101000nnnn1111dddd0101mmmm", // UQADD8 three_reg_not_r15), ThumbInstGen("111110101001nnnn1111dddd0101mmmm", // UQADD16 From afad76078df0bb5f08b91cf54412b404c4e86e93 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 1 Feb 2021 17:21:24 -0500 Subject: [PATCH 16/18] thumb32: Implement SHSUB16/UHSUB16 --- src/frontend/A32/decoder/thumb32.h | 4 +-- .../A32/translate/impl/thumb32_parallel.cpp | 26 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 2 ++ tests/A32/fuzz_thumb.cpp | 4 +++ 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/frontend/A32/decoder/thumb32.h b/src/frontend/A32/decoder/thumb32.h index b84994d3..be111ad7 100644 --- a/src/frontend/A32/decoder/thumb32.h +++ b/src/frontend/A32/decoder/thumb32.h @@ -250,7 +250,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_SHADD16, "SHADD16", "111110101001nnnn1111dddd0010mmmm"), INST(&V::thumb32_SHASX, "SHASX", "111110101010nnnn1111dddd0010mmmm"), INST(&V::thumb32_SHSAX, "SHSAX", "111110101110nnnn1111dddd0010mmmm"), - //INST(&V::thumb32_SHSUB16, "SHSUB16", "111110101101----1111----0010----"), + INST(&V::thumb32_SHSUB16, "SHSUB16", "111110101101nnnn1111dddd0010mmmm"), //INST(&V::thumb32_SHADD8, "SHADD8", "111110101000----1111----0010----"), //INST(&V::thumb32_SHSUB8, "SHSUB8", "111110101100----1111----0010----"), @@ -270,7 +270,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_UHADD16, "UHADD16", "111110101001nnnn1111dddd0110mmmm"), INST(&V::thumb32_UHASX, "UHASX", "111110101010nnnn1111dddd0110mmmm"), INST(&V::thumb32_UHSAX, "UHSAX", "111110101110nnnn1111dddd0110mmmm"), - //INST(&V::thumb32_UHSUB16, "UHSUB16", "111110101101----1111----0110----"), + INST(&V::thumb32_UHSUB16, "UHSUB16", "111110101101nnnn1111dddd0110mmmm"), //INST(&V::thumb32_UHADD8, "UHADD8", "111110101000----1111----0110----"), //INST(&V::thumb32_UHSUB8, "UHSUB8", "111110101100----1111----0110----"), diff --git a/src/frontend/A32/translate/impl/thumb32_parallel.cpp b/src/frontend/A32/translate/impl/thumb32_parallel.cpp index c5e6a878..e5792f9c 100644 --- a/src/frontend/A32/translate/impl/thumb32_parallel.cpp +++ b/src/frontend/A32/translate/impl/thumb32_parallel.cpp @@ -401,6 +401,19 @@ bool ThumbTranslatorVisitor::thumb32_SHSAX(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_SHSUB16(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedHalvingSubS16(reg_n, reg_m); + + ir.SetRegister(d, result); + return true; +} + bool ThumbTranslatorVisitor::thumb32_UHADD16(Reg n, Reg d, Reg m) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); @@ -440,4 +453,17 @@ bool ThumbTranslatorVisitor::thumb32_UHSAX(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_UHSUB16(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedHalvingSubU16(reg_n, reg_m); + + ir.SetRegister(d, result); + return true; +} + } // namespace Dynarmic::A32 diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index 20088da3..ea8c572e 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -158,9 +158,11 @@ struct ThumbTranslatorVisitor final { bool thumb32_SHADD16(Reg n, Reg d, Reg m); bool thumb32_SHASX(Reg n, Reg d, Reg m); bool thumb32_SHSAX(Reg n, Reg d, Reg m); + bool thumb32_SHSUB16(Reg n, Reg d, Reg m); bool thumb32_UHADD16(Reg n, Reg d, Reg m); bool thumb32_UHASX(Reg n, Reg d, Reg m); bool thumb32_UHSAX(Reg n, Reg d, Reg m); + bool thumb32_UHSUB16(Reg n, Reg d, Reg m); }; } // namespace Dynarmic::A32 diff --git a/tests/A32/fuzz_thumb.cpp b/tests/A32/fuzz_thumb.cpp index 8931c2ac..23827c71 100644 --- a/tests/A32/fuzz_thumb.cpp +++ b/tests/A32/fuzz_thumb.cpp @@ -438,6 +438,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101110nnnn1111dddd0010mmmm", // SHSAX three_reg_not_r15), + ThumbInstGen("111110101101nnnn1111dddd0010mmmm", // SHSUB16 + three_reg_not_r15), ThumbInstGen("111110101110nnnn1111dddd0000mmmm", // SSAX three_reg_not_r15), ThumbInstGen("111110101100nnnn1111dddd0000mmmm", // SSUB8 @@ -456,6 +458,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101110nnnn1111dddd0110mmmm", // UHSAX three_reg_not_r15), + ThumbInstGen("111110101101nnnn1111dddd0110mmmm", // UHSUB16 + three_reg_not_r15), ThumbInstGen("111110101000nnnn1111dddd0101mmmm", // UQADD8 three_reg_not_r15), ThumbInstGen("111110101001nnnn1111dddd0101mmmm", // UQADD16 From 9d2570470e2fd927631347ca3dd910ca42044595 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 1 Feb 2021 17:23:40 -0500 Subject: [PATCH 17/18] thumb32: Implement SHADD8/UHADD8 --- src/frontend/A32/decoder/thumb32.h | 4 +-- .../A32/translate/impl/thumb32_parallel.cpp | 26 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 2 ++ tests/A32/fuzz_thumb.cpp | 4 +++ 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/frontend/A32/decoder/thumb32.h b/src/frontend/A32/decoder/thumb32.h index be111ad7..675797d9 100644 --- a/src/frontend/A32/decoder/thumb32.h +++ b/src/frontend/A32/decoder/thumb32.h @@ -251,7 +251,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_SHASX, "SHASX", "111110101010nnnn1111dddd0010mmmm"), INST(&V::thumb32_SHSAX, "SHSAX", "111110101110nnnn1111dddd0010mmmm"), INST(&V::thumb32_SHSUB16, "SHSUB16", "111110101101nnnn1111dddd0010mmmm"), - //INST(&V::thumb32_SHADD8, "SHADD8", "111110101000----1111----0010----"), + INST(&V::thumb32_SHADD8, "SHADD8", "111110101000nnnn1111dddd0010mmmm"), //INST(&V::thumb32_SHSUB8, "SHSUB8", "111110101100----1111----0010----"), // Parallel Addition and Subtraction (unsigned) @@ -271,7 +271,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_UHASX, "UHASX", "111110101010nnnn1111dddd0110mmmm"), INST(&V::thumb32_UHSAX, "UHSAX", "111110101110nnnn1111dddd0110mmmm"), INST(&V::thumb32_UHSUB16, "UHSUB16", "111110101101nnnn1111dddd0110mmmm"), - //INST(&V::thumb32_UHADD8, "UHADD8", "111110101000----1111----0110----"), + INST(&V::thumb32_UHADD8, "UHADD8", "111110101000nnnn1111dddd0110mmmm"), //INST(&V::thumb32_UHSUB8, "UHSUB8", "111110101100----1111----0110----"), // Miscellaneous Operations diff --git a/src/frontend/A32/translate/impl/thumb32_parallel.cpp b/src/frontend/A32/translate/impl/thumb32_parallel.cpp index e5792f9c..89f91393 100644 --- a/src/frontend/A32/translate/impl/thumb32_parallel.cpp +++ b/src/frontend/A32/translate/impl/thumb32_parallel.cpp @@ -362,6 +362,19 @@ bool ThumbTranslatorVisitor::thumb32_UQSUB16(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_SHADD8(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedHalvingAddS8(reg_n, reg_m); + + ir.SetRegister(d, result); + return true; +} + bool ThumbTranslatorVisitor::thumb32_SHADD16(Reg n, Reg d, Reg m) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); @@ -414,6 +427,19 @@ bool ThumbTranslatorVisitor::thumb32_SHSUB16(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_UHADD8(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedHalvingAddU8(reg_n, reg_m); + + ir.SetRegister(d, result); + return true; +} + bool ThumbTranslatorVisitor::thumb32_UHADD16(Reg n, Reg d, Reg m) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index ea8c572e..a57ea7ff 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -155,10 +155,12 @@ struct ThumbTranslatorVisitor final { bool thumb32_UQSUB8(Reg n, Reg d, Reg m); bool thumb32_UQSUB16(Reg n, Reg d, Reg m); + bool thumb32_SHADD8(Reg n, Reg d, Reg m); bool thumb32_SHADD16(Reg n, Reg d, Reg m); bool thumb32_SHASX(Reg n, Reg d, Reg m); bool thumb32_SHSAX(Reg n, Reg d, Reg m); bool thumb32_SHSUB16(Reg n, Reg d, Reg m); + bool thumb32_UHADD8(Reg n, Reg d, Reg m); bool thumb32_UHADD16(Reg n, Reg d, Reg m); bool thumb32_UHASX(Reg n, Reg d, Reg m); bool thumb32_UHSAX(Reg n, Reg d, Reg m); diff --git a/tests/A32/fuzz_thumb.cpp b/tests/A32/fuzz_thumb.cpp index 23827c71..f39148ed 100644 --- a/tests/A32/fuzz_thumb.cpp +++ b/tests/A32/fuzz_thumb.cpp @@ -432,6 +432,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101010nnnn1111dddd1000mmmm", // SEL three_reg_not_r15), + ThumbInstGen("111110101000nnnn1111dddd0010mmmm", // SHADD8 + three_reg_not_r15), ThumbInstGen("111110101001nnnn1111dddd0010mmmm", // SHADD16 three_reg_not_r15), ThumbInstGen("111110101010nnnn1111dddd0010mmmm", // SHASX @@ -452,6 +454,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101010nnnn1111dddd0100mmmm", // UASX three_reg_not_r15), + ThumbInstGen("111110101000nnnn1111dddd0110mmmm", // UHADD8 + three_reg_not_r15), ThumbInstGen("111110101001nnnn1111dddd0110mmmm", // UHADD16 three_reg_not_r15), ThumbInstGen("111110101010nnnn1111dddd0110mmmm", // UHASX From 23619c8c6a6e58a0e0d451e2ee0ae80299e90810 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 1 Feb 2021 17:25:56 -0500 Subject: [PATCH 18/18] thumb32: Implement SHSUB8/UHSUB8 --- src/frontend/A32/decoder/thumb32.h | 4 +-- .../A32/translate/impl/thumb32_parallel.cpp | 26 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 2 ++ tests/A32/fuzz_thumb.cpp | 4 +++ 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/frontend/A32/decoder/thumb32.h b/src/frontend/A32/decoder/thumb32.h index 675797d9..1df3832f 100644 --- a/src/frontend/A32/decoder/thumb32.h +++ b/src/frontend/A32/decoder/thumb32.h @@ -252,7 +252,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_SHSAX, "SHSAX", "111110101110nnnn1111dddd0010mmmm"), INST(&V::thumb32_SHSUB16, "SHSUB16", "111110101101nnnn1111dddd0010mmmm"), INST(&V::thumb32_SHADD8, "SHADD8", "111110101000nnnn1111dddd0010mmmm"), - //INST(&V::thumb32_SHSUB8, "SHSUB8", "111110101100----1111----0010----"), + INST(&V::thumb32_SHSUB8, "SHSUB8", "111110101100nnnn1111dddd0010mmmm"), // Parallel Addition and Subtraction (unsigned) INST(&V::thumb32_UADD16, "UADD16", "111110101001nnnn1111dddd0100mmmm"), @@ -272,7 +272,7 @@ std::optional>> DecodeThumb32(u32 INST(&V::thumb32_UHSAX, "UHSAX", "111110101110nnnn1111dddd0110mmmm"), INST(&V::thumb32_UHSUB16, "UHSUB16", "111110101101nnnn1111dddd0110mmmm"), INST(&V::thumb32_UHADD8, "UHADD8", "111110101000nnnn1111dddd0110mmmm"), - //INST(&V::thumb32_UHSUB8, "UHSUB8", "111110101100----1111----0110----"), + INST(&V::thumb32_UHSUB8, "UHSUB8", "111110101100nnnn1111dddd0110mmmm"), // Miscellaneous Operations INST(&V::thumb32_QADD, "QADD", "111110101000nnnn1111dddd1000mmmm"), diff --git a/src/frontend/A32/translate/impl/thumb32_parallel.cpp b/src/frontend/A32/translate/impl/thumb32_parallel.cpp index 89f91393..8d10c725 100644 --- a/src/frontend/A32/translate/impl/thumb32_parallel.cpp +++ b/src/frontend/A32/translate/impl/thumb32_parallel.cpp @@ -414,6 +414,19 @@ bool ThumbTranslatorVisitor::thumb32_SHSAX(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_SHSUB8(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedHalvingSubS8(reg_n, reg_m); + + ir.SetRegister(d, result); + return true; +} + bool ThumbTranslatorVisitor::thumb32_SHSUB16(Reg n, Reg d, Reg m) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); @@ -479,6 +492,19 @@ bool ThumbTranslatorVisitor::thumb32_UHSAX(Reg n, Reg d, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_UHSUB8(Reg n, Reg d, Reg m) { + if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto reg_m = ir.GetRegister(m); + const auto reg_n = ir.GetRegister(n); + const auto result = ir.PackedHalvingSubU8(reg_n, reg_m); + + ir.SetRegister(d, result); + return true; +} + bool ThumbTranslatorVisitor::thumb32_UHSUB16(Reg n, Reg d, Reg m) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index a57ea7ff..1c140dd0 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -159,11 +159,13 @@ struct ThumbTranslatorVisitor final { bool thumb32_SHADD16(Reg n, Reg d, Reg m); bool thumb32_SHASX(Reg n, Reg d, Reg m); bool thumb32_SHSAX(Reg n, Reg d, Reg m); + bool thumb32_SHSUB8(Reg n, Reg d, Reg m); bool thumb32_SHSUB16(Reg n, Reg d, Reg m); bool thumb32_UHADD8(Reg n, Reg d, Reg m); bool thumb32_UHADD16(Reg n, Reg d, Reg m); bool thumb32_UHASX(Reg n, Reg d, Reg m); bool thumb32_UHSAX(Reg n, Reg d, Reg m); + bool thumb32_UHSUB8(Reg n, Reg d, Reg m); bool thumb32_UHSUB16(Reg n, Reg d, Reg m); }; diff --git a/tests/A32/fuzz_thumb.cpp b/tests/A32/fuzz_thumb.cpp index f39148ed..5b6b6244 100644 --- a/tests/A32/fuzz_thumb.cpp +++ b/tests/A32/fuzz_thumb.cpp @@ -440,6 +440,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101110nnnn1111dddd0010mmmm", // SHSAX three_reg_not_r15), + ThumbInstGen("111110101100nnnn1111dddd0010mmmm", // SHSUB8 + three_reg_not_r15), ThumbInstGen("111110101101nnnn1111dddd0010mmmm", // SHSUB16 three_reg_not_r15), ThumbInstGen("111110101110nnnn1111dddd0000mmmm", // SSAX @@ -462,6 +464,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { three_reg_not_r15), ThumbInstGen("111110101110nnnn1111dddd0110mmmm", // UHSAX three_reg_not_r15), + ThumbInstGen("111110101100nnnn1111dddd0110mmmm", // UHSUB8 + three_reg_not_r15), ThumbInstGen("111110101101nnnn1111dddd0110mmmm", // UHSUB16 three_reg_not_r15), ThumbInstGen("111110101000nnnn1111dddd0101mmmm", // UQADD8