A64: Implement SBFM, BFM, UBFM

This commit is contained in:
MerryMage 2018-01-17 00:10:28 +00:00
parent cdbc8d07a5
commit 9f57283a30
6 changed files with 91 additions and 6 deletions

View file

@ -61,6 +61,7 @@ add_library(dynarmic
frontend/A64/location_descriptor.h frontend/A64/location_descriptor.h
frontend/A64/translate/impl/branch.cpp frontend/A64/translate/impl/branch.cpp
frontend/A64/translate/impl/data_processing_addsub.cpp frontend/A64/translate/impl/data_processing_addsub.cpp
frontend/A64/translate/impl/data_processing_bitfield.cpp
frontend/A64/translate/impl/data_processing_logical.cpp frontend/A64/translate/impl/data_processing_logical.cpp
frontend/A64/translate/impl/data_processing_pcrel.cpp frontend/A64/translate/impl/data_processing_pcrel.cpp
frontend/A64/translate/impl/exception_generating.cpp frontend/A64/translate/impl/exception_generating.cpp

View file

@ -101,6 +101,8 @@ inline int HighestSetBit(T value) {
template <typename T> template <typename T>
inline T Ones(size_t count) { inline T Ones(size_t count) {
ASSERT_MSG(count <= BitSize<T>(), "count larger than bitsize of T"); ASSERT_MSG(count <= BitSize<T>(), "count larger than bitsize of T");
if (count == BitSize<T>())
return ~static_cast<T>(0);
return ~(~static_cast<T>(0) << count); return ~(~static_cast<T>(0) << count);
} }

View file

@ -20,9 +20,9 @@ INST(MOVZ, "MOVZ", "z1010
INST(MOVK, "MOVK", "z11100101ssiiiiiiiiiiiiiiiiddddd") INST(MOVK, "MOVK", "z11100101ssiiiiiiiiiiiiiiiiddddd")
// Data processing - Immediate - Bitfield // Data processing - Immediate - Bitfield
//INST(SBFM, "SBFM", "z00100110Nrrrrrrssssssnnnnnddddd") INST(SBFM, "SBFM", "z00100110Nrrrrrrssssssnnnnnddddd")
//INST(BFM, "BFM", "z01100110Nrrrrrrssssssnnnnnddddd") INST(BFM, "BFM", "z01100110Nrrrrrrssssssnnnnnddddd")
//INST(UBFM, "UBFM", "z10100110Nrrrrrrssssssnnnnnddddd") INST(UBFM, "UBFM", "z10100110Nrrrrrrssssssnnnnnddddd")
// Data processing - Immediate - Extract // Data processing - Immediate - Extract
//INST(EXTR, "EXTR", "z00100111N0mmmmmssssssnnnnnddddd") //INST(EXTR, "EXTR", "z00100111N0mmmmmssssssnnnnnddddd")

View file

@ -0,0 +1,81 @@
/* 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 {
static IR::U32U64 ReplicateBit(IREmitter& ir, const IR::U32U64& value, u8 bit_position_to_replicate) {
u8 datasize = value.GetType() == IR::Type::U64 ? 64 : 32;
auto bit = ir.LogicalShiftLeft(value, ir.Imm8(datasize - 1 - bit_position_to_replicate));
return ir.ArithmeticShiftRight(bit, ir.Imm8(datasize - 1));
}
bool TranslatorVisitor::SBFM(bool sf, bool N, Imm<6> immr, Imm<6> imms, Reg Rn, Reg Rd) {
size_t datasize = sf ? 64 : 32;
if (sf && !N) return ReservedValue();
if (!sf && (N || immr.Bit<5>() || imms.Bit<5>())) return ReservedValue();
u8 R = immr.ZeroExtend<u8>();
u8 S = imms.ZeroExtend<u8>();
auto masks = DecodeBitMasks(N, imms, immr, false);
if (!masks) return ReservedValue();
auto src = X(datasize, Rn);
auto bot = ir.And(ir.RotateRight(src, ir.Imm8(R)), I(datasize, masks->wmask));
auto top = ReplicateBit(ir, src, S);
top = ir.And(top, I(datasize, ~masks->tmask));
bot = ir.And(bot, I(datasize, masks->tmask));
X(datasize, Rd, ir.Or(top, bot));
return true;
}
bool TranslatorVisitor::BFM(bool sf, bool N, Imm<6> immr, Imm<6> imms, Reg Rn, Reg Rd) {
size_t datasize = sf ? 64 : 32;
if (sf && !N) return ReservedValue();
if (!sf && (N || immr.Bit<5>() || imms.Bit<5>())) return ReservedValue();
u8 R = immr.ZeroExtend<u8>();
auto masks = DecodeBitMasks(N, imms, immr, false);
if (!masks) return ReservedValue();
auto dst = X(datasize, Rd);
auto src = X(datasize, Rn);
auto bot = ir.Or(ir.And(dst, I(datasize, ~masks->wmask)), ir.And(ir.RotateRight(src, ir.Imm8(R)), I(datasize, masks->wmask)));
X(datasize, Rd, ir.Or(ir.And(dst, I(datasize, ~masks->tmask)), ir.And(bot, I(datasize, masks->tmask))));
return true;
}
bool TranslatorVisitor::UBFM(bool sf, bool N, Imm<6> immr, Imm<6> imms, Reg Rn, Reg Rd) {
size_t datasize = sf ? 64 : 32;
if (sf && !N) return ReservedValue();
if (!sf && (N || immr.Bit<5>() || imms.Bit<5>())) return ReservedValue();
u8 R = immr.ZeroExtend<u8>();
auto masks = DecodeBitMasks(N, imms, immr, false);
if (!masks) return ReservedValue();
auto src = X(datasize, Rn);
auto bot = ir.And(ir.RotateRight(src, ir.Imm8(R)), I(datasize, masks->wmask));
X(datasize, Rd, ir.And(bot, I(datasize, masks->tmask)));
return true;
}
} // namespace A64
} // namespace Dynarmic

View file

@ -10,7 +10,6 @@ namespace Dynarmic {
namespace A64 { namespace A64 {
bool TranslatorVisitor::SVC(Imm<16> imm16) { bool TranslatorVisitor::SVC(Imm<16> imm16) {
printf("translator %x\n", imm16.ZeroExtend());
// ir.PushRSB(ir.current_location.AdvancePC(4)); // TODO // ir.PushRSB(ir.current_location.AdvancePC(4)); // TODO
ir.SetPC(ir.Imm64(ir.current_location.PC() + 4)); ir.SetPC(ir.Imm64(ir.current_location.PC() + 4));
ir.CallSupervisor(imm16.ZeroExtend()); ir.CallSupervisor(imm16.ZeroExtend());

View file

@ -115,7 +115,7 @@ restart:
if (!should_continue) if (!should_continue)
goto restart; goto restart;
for (const auto& ir_inst : block) for (const auto& ir_inst : block)
if (ir_inst.CausesCPUException() || ir_inst.IsMemoryWrite() || ir_inst.GetOpcode() == IR::Opcode::A64ExceptionRaised) if (ir_inst.IsMemoryWrite() || ir_inst.GetOpcode() == IR::Opcode::A64ExceptionRaised || ir_inst.GetOpcode() == IR::Opcode::A64CallSupervisor)
goto restart; goto restart;
return instruction; return instruction;
@ -155,13 +155,15 @@ static void TestInstance(const std::array<u64, 31>& regs, const std::vector<u32>
} }
TEST_CASE("A64: Single random instruction", "[a64]") { TEST_CASE("A64: Single random instruction", "[a64]") {
for (size_t iteration = 0; iteration < 10000; ++iteration) { for (size_t iteration = 0; iteration < 100000; ++iteration) {
std::array<u64, 31> regs; std::array<u64, 31> regs;
std::generate_n(regs.begin(), 31, []{ return RandInt<u64>(0, ~u64(0)); }); std::generate_n(regs.begin(), 31, []{ return RandInt<u64>(0, ~u64(0)); });
std::vector<u32> instructions; std::vector<u32> instructions;
instructions.push_back(GenRandomInst(0)); instructions.push_back(GenRandomInst(0));
u32 pstate = RandInt<u32>(0, 0xF) << 28; u32 pstate = RandInt<u32>(0, 0xF) << 28;
// printf("%08x\n", instructions[0]);
TestInstance(regs, instructions, pstate); TestInstance(regs, instructions, pstate);
} }
} }