From 896cf44f9652e6d3558de52b6a6e1acb12eefd67 Mon Sep 17 00:00:00 2001 From: Thomas Guillemard Date: Sun, 21 Jan 2018 13:17:47 +0100 Subject: [PATCH] A64: Implement REV, REV32, and REV16 (#126) --- src/CMakeLists.txt | 1 + src/frontend/A64/decoder/a64.inc | 6 +- .../impl/data_processing_register.cpp | 64 +++++++++++++++++++ src/frontend/A64/translate/impl/impl.h | 2 +- tests/A64/a64.cpp | 56 ++++++++++++++++ 5 files changed, 125 insertions(+), 4 deletions(-) create mode 100644 src/frontend/A64/translate/impl/data_processing_register.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6a7c0b77..d5a69974 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -65,6 +65,7 @@ add_library(dynarmic frontend/A64/translate/impl/data_processing_conditional_select.cpp frontend/A64/translate/impl/data_processing_logical.cpp frontend/A64/translate/impl/data_processing_pcrel.cpp + frontend/A64/translate/impl/data_processing_register.cpp frontend/A64/translate/impl/exception_generating.cpp frontend/A64/translate/impl/impl.cpp frontend/A64/translate/impl/impl.h diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc index f2580158..3977c365 100644 --- a/src/frontend/A64/decoder/a64.inc +++ b/src/frontend/A64/decoder/a64.inc @@ -286,11 +286,11 @@ INST(UnallocatedEncoding, "", "10111 // Data Processing - Register - 1 source //INST(RBIT_int, "RBIT", "z101101011000000000000nnnnnddddd") -//INST(REV16_int, "REV16", "z101101011000000000001nnnnnddddd") -//INST(REV, "REV", "z10110101100000000001-nnnnnddddd") +INST(REV16_int, "REV16", "z101101011000000000001nnnnnddddd") +INST(REV, "REV", "z10110101100000000001onnnnnddddd") //INST(CLZ_int, "CLZ", "z101101011000000000100nnnnnddddd") //INST(CLS_int, "CLS", "z101101011000000000101nnnnnddddd") -//INST(REV32_int, "REV32", "1101101011000000000010nnnnnddddd") +INST(REV32_int, "REV32", "1101101011000000000010nnnnnddddd") //INST(PACDA, "PACDA, PACDZA", "110110101100000100Z010nnnnnddddd") //INST(PACDB, "PACDB, PACDZB", "110110101100000100Z011nnnnnddddd") //INST(AUTDA, "AUTDA, AUTDZA", "110110101100000100Z110nnnnnddddd") diff --git a/src/frontend/A64/translate/impl/data_processing_register.cpp b/src/frontend/A64/translate/impl/data_processing_register.cpp new file mode 100644 index 00000000..76da759c --- /dev/null +++ b/src/frontend/A64/translate/impl/data_processing_register.cpp @@ -0,0 +1,64 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2018 MerryMage + * This software may be used and distributed according to the terms of the GNU + * General Public License version 2 or any later version. + */ + +#include "frontend/A64/translate/impl/impl.h" + +namespace Dynarmic { +namespace A64 { + +bool TranslatorVisitor::REV(bool sf, bool opc_0, Reg Rn, Reg Rd) +{ + if (!sf && opc_0) return UnallocatedEncoding(); + + size_t datasize = sf ? 64 : 32; + + IR::U32U64 operand = X(datasize, Rn); + IR::U32U64 result; + + if (sf) { + result = ir.ByteReverseDual(operand); + } else { + result = ir.ByteReverseWord(operand); + } + X(datasize, Rd, result); + return true; +} + +bool TranslatorVisitor::REV32_int(Reg Rn, Reg Rd) +{ + IR::U64 operand = ir.GetX(Rn); + IR::U32 lo = ir.ByteReverseWord(ir.LeastSignificantWord(operand)); + IR::U32 hi = ir.ByteReverseWord(ir.MostSignificantWord(operand).result); + IR::U64 result = ir.Pack2x32To1x64(lo, hi); + X(64, Rd, result); + return true; +} + +bool TranslatorVisitor::REV16_int(bool sf, Reg Rn, Reg Rd) +{ + size_t datasize = sf ? 64 : 32; + + IR::U32U64 operand = X(datasize, Rn); + IR::U32U64 result; + IR::U32U64 hihalf; + IR::U32U64 lohalf; + + + if (sf) { + hihalf = ir.And(ir.LogicalShiftRight(IR::U64(operand), ir.Imm8(8)), ir.Imm64(0x00FF00FF00FF00FF)); + lohalf = ir.And(ir.LogicalShiftLeft(IR::U64(operand), ir.Imm8(8)), ir.Imm64(0xFF00FF00FF00FF00)); + } else { + hihalf = ir.And(ir.LogicalShiftRight(operand, ir.Imm8(8), ir.Imm1(0)).result, ir.Imm32(0x00FF00FF)); + lohalf = ir.And(ir.LogicalShiftLeft(operand, ir.Imm8(8), ir.Imm1(0)).result, ir.Imm32(0xFF00FF00)); + } + + result = ir.Or(hihalf, lohalf); + X(datasize, Rd, result); + return true; +} + +} // namespace A64 +} // namespace Dynarmic \ No newline at end of file diff --git a/src/frontend/A64/translate/impl/impl.h b/src/frontend/A64/translate/impl/impl.h index a7261063..066b086a 100644 --- a/src/frontend/A64/translate/impl/impl.h +++ b/src/frontend/A64/translate/impl/impl.h @@ -335,7 +335,7 @@ struct TranslatorVisitor final { // Data Processing - Register - 1 source bool RBIT_int(bool sf, Reg Rn, Reg Rd); bool REV16_int(bool sf, Reg Rn, Reg Rd); - bool REV(bool sf, Reg Rn, Reg Rd); + bool REV(bool sf, bool opc_0, Reg Rn, Reg Rd); bool CLZ_int(bool sf, Reg Rn, Reg Rd); bool CLS_int(bool sf, Reg Rn, Reg Rd); bool REV32_int(Reg Rn, Reg Rd); diff --git a/tests/A64/a64.cpp b/tests/A64/a64.cpp index 3d5c5d43..6b62f979 100644 --- a/tests/A64/a64.cpp +++ b/tests/A64/a64.cpp @@ -29,6 +29,62 @@ TEST_CASE("A64: ADD", "[a64]") { REQUIRE(jit.GetPC() == 4); } +TEST_CASE("A64: REV", "[a64]") { + TestEnv env; + Dynarmic::A64::Jit jit{Dynarmic::A64::UserConfig{&env}}; + + env.code_mem[0] = 0xdac00c00; // REV X0, X0 + env.code_mem[1] = 0x5ac00821; // REV W1, W1 + env.code_mem[2] = 0x14000000; // B . + + jit.SetRegister(0, 0xaabbccddeeff1100); + jit.SetRegister(1, 0xaabbccdd); + jit.SetPC(0); + + env.ticks_left = 3; + jit.Run(); + + REQUIRE(jit.GetRegister(0) == 0x11ffeeddccbbaa); + REQUIRE(jit.GetRegister(1) == 0xddccbbaa); + REQUIRE(jit.GetPC() == 8); +} + +TEST_CASE("A64: REV32", "[a64]") { + TestEnv env; + Dynarmic::A64::Jit jit{Dynarmic::A64::UserConfig{&env}}; + + env.code_mem[0] = 0xdac00800; // REV32 X0, X0 + env.code_mem[1] = 0x14000000; // B . + + jit.SetRegister(0, 0xaabbccddeeff1100); + jit.SetPC(0); + + env.ticks_left = 2; + jit.Run(); + REQUIRE(jit.GetRegister(0) == 0xddccbbaa0011ffee); + REQUIRE(jit.GetPC() == 4); +} + +TEST_CASE("A64: REV16", "[a64]") { + TestEnv env; + Dynarmic::A64::Jit jit{Dynarmic::A64::UserConfig{&env}}; + + env.code_mem[0] = 0xdac00400; // REV16 X0, X0 + env.code_mem[1] = 0x5ac00421; // REV16 W1, W1 + env.code_mem[2] = 0x14000000; // B . + + jit.SetRegister(0, 0xaabbccddeeff1100); + jit.SetRegister(1, 0xaabbccdd); + + jit.SetPC(0); + + env.ticks_left = 3; + jit.Run(); + REQUIRE(jit.GetRegister(0) == 0xbbaaddccffee0011); + REQUIRE(jit.GetRegister(1) == 0xbbaaddcc); + REQUIRE(jit.GetPC() == 8); +} + TEST_CASE("A64: AND", "[a64]") { TestEnv env; Dynarmic::A64::Jit jit{Dynarmic::A64::UserConfig{&env}};