Implement DC instructions

This commit is contained in:
MerryMage
2018-02-11 22:53:46 +00:00
parent a9153218bd
commit 5edd623b9d
18 changed files with 218 additions and 33 deletions

View File

@@ -70,6 +70,17 @@ INST(SEVL, "SEVL", "11010
//INST(SYSL, "SYSL", "1101010100101oooNNNNMMMMooottttt")
//INST(MRS, "MRS", "110101010011poooNNNNMMMMooottttt")
// SYS: Data Cache
INST(DC_IVAC, "DC IVAC", "110101010000100001110110001ttttt")
INST(DC_ISW, "DC ISW", "110101010000100001110110010ttttt")
INST(DC_CSW, "DC CSW", "110101010000100001111010010ttttt")
INST(DC_CISW, "DC CISW", "110101010000100001111110010ttttt")
INST(DC_ZVA, "DC ZVA", "110101010000101101110100001ttttt")
INST(DC_CVAC, "DC CVAC", "110101010000101101111010001ttttt")
INST(DC_CVAU, "DC CVAU", "110101010000101101111011001ttttt")
INST(DC_CVAP, "DC CVAP", "110101010000101101111100001ttttt")
INST(DC_CIVAC, "DC CIVAC", "110101010000101101111110001ttttt")
// Unconditonal branch (Register)
INST(BLR, "BLR", "1101011000111111000000nnnnn00000")
INST(BR, "BR", "1101011000011111000000nnnnn00000")

View File

@@ -13,7 +13,7 @@ namespace Dynarmic::A64 {
using Opcode = IR::Opcode;
u64 IREmitter::PC() {
return current_location.PC();
return current_location->PC();
}
u64 IREmitter::AlignPC(size_t alignment) {
@@ -41,6 +41,10 @@ void IREmitter::ExceptionRaised(Exception exception) {
Inst(Opcode::A64ExceptionRaised, Imm64(PC()), Imm64(static_cast<u64>(exception)));
}
void IREmitter::DataCacheOperationRaised(DataCacheOperation op, const IR::U64& value) {
Inst(Opcode::A64DataCacheOperationRaised, Imm64(static_cast<u64>(op)), value);
}
IR::U8 IREmitter::ReadMemory8(const IR::U64& vaddr) {
return Inst<IR::U8>(Opcode::A64ReadMemory8, vaddr);
}

View File

@@ -8,6 +8,8 @@
#include <initializer_list>
#include <boost/optional.hpp>
#include <dynarmic/A64/config.h>
#include "common/common_types.h"
@@ -25,9 +27,10 @@ namespace Dynarmic::A64 {
*/
class IREmitter : public IR::IREmitter {
public:
explicit IREmitter(IR::Block& block) : IR::IREmitter(block) {}
explicit IREmitter(IR::Block& block, LocationDescriptor descriptor) : IR::IREmitter(block), current_location(descriptor) {}
LocationDescriptor current_location;
boost::optional<LocationDescriptor> current_location;
u64 PC();
u64 AlignPC(size_t alignment);
@@ -38,6 +41,7 @@ public:
void CallSupervisor(u32 imm);
void ExceptionRaised(Exception exception);
void DataCacheOperationRaised(DataCacheOperation op, const IR::U64& value);
IR::U8 ReadMemory8(const IR::U64& vaddr);
IR::U16 ReadMemory16(const IR::U64& vaddr);

View File

@@ -12,8 +12,8 @@ bool TranslatorVisitor::B_cond(Imm<19> imm19, Cond cond) {
s64 offset = concatenate(imm19, Imm<2>{0}).SignExtend<s64>();
u64 target = ir.PC() + offset;
auto cond_pass = IR::Term::LinkBlock{ir.current_location.SetPC(target)};
auto cond_fail = IR::Term::LinkBlock{ir.current_location.AdvancePC(4)};
auto cond_pass = IR::Term::LinkBlock{ir.current_location->SetPC(target)};
auto cond_fail = IR::Term::LinkBlock{ir.current_location->AdvancePC(4)};
ir.SetTerm(IR::Term::If{cond, cond_pass, cond_fail});
return false;
}
@@ -22,7 +22,7 @@ bool TranslatorVisitor::B_uncond(Imm<26> imm26) {
s64 offset = concatenate(imm26, Imm<2>{0}).SignExtend<s64>();
u64 target = ir.PC() + offset;
ir.SetTerm(IR::Term::LinkBlock{ir.current_location.SetPC(target)});
ir.SetTerm(IR::Term::LinkBlock{ir.current_location->SetPC(target)});
return false;
}
@@ -30,10 +30,10 @@ bool TranslatorVisitor::BL(Imm<26> imm26) {
s64 offset = concatenate(imm26, Imm<2>{0}).SignExtend<s64>();
X(64, Reg::R30, ir.Imm64(ir.PC() + 4));
ir.PushRSB(ir.current_location.AdvancePC(4));
ir.PushRSB(ir.current_location->AdvancePC(4));
u64 target = ir.PC() + offset;
ir.SetTerm(IR::Term::LinkBlock{ir.current_location.SetPC(target)});
ir.SetTerm(IR::Term::LinkBlock{ir.current_location->SetPC(target)});
return false;
}
@@ -41,7 +41,7 @@ bool TranslatorVisitor::BLR(Reg Rn) {
auto target = X(64, Rn);
X(64, Reg::R30, ir.Imm64(ir.PC() + 4));
ir.PushRSB(ir.current_location.AdvancePC(4));
ir.PushRSB(ir.current_location->AdvancePC(4));
ir.SetPC(target);
ir.SetTerm(IR::Term::ReturnToDispatch{});
@@ -73,8 +73,8 @@ bool TranslatorVisitor::CBZ(bool sf, Imm<19> imm19, Reg Rt) {
ir.SetCheckBit(ir.IsZero(operand1));
u64 target = ir.PC() + offset;
auto cond_pass = IR::Term::LinkBlock{ir.current_location.SetPC(target)};
auto cond_fail = IR::Term::LinkBlock{ir.current_location.AdvancePC(4)};
auto cond_pass = IR::Term::LinkBlock{ir.current_location->SetPC(target)};
auto cond_fail = IR::Term::LinkBlock{ir.current_location->AdvancePC(4)};
ir.SetTerm(IR::Term::CheckBit{cond_pass, cond_fail});
return false;
}
@@ -88,8 +88,8 @@ bool TranslatorVisitor::CBNZ(bool sf, Imm<19> imm19, Reg Rt) {
ir.SetCheckBit(ir.IsZero(operand1));
u64 target = ir.PC() + offset;
auto cond_pass = IR::Term::LinkBlock{ir.current_location.AdvancePC(4)};
auto cond_fail = IR::Term::LinkBlock{ir.current_location.SetPC(target)};
auto cond_pass = IR::Term::LinkBlock{ir.current_location->AdvancePC(4)};
auto cond_fail = IR::Term::LinkBlock{ir.current_location->SetPC(target)};
ir.SetTerm(IR::Term::CheckBit{cond_pass, cond_fail});
return false;
}
@@ -104,8 +104,8 @@ bool TranslatorVisitor::TBZ(Imm<1> b5, Imm<5> b40, Imm<14> imm14, Reg Rt) {
ir.SetCheckBit(ir.TestBit(operand, ir.Imm8(bit_pos)));
u64 target = ir.PC() + offset;
auto cond_1 = IR::Term::LinkBlock{ir.current_location.AdvancePC(4)};
auto cond_0 = IR::Term::LinkBlock{ir.current_location.SetPC(target)};
auto cond_1 = IR::Term::LinkBlock{ir.current_location->AdvancePC(4)};
auto cond_0 = IR::Term::LinkBlock{ir.current_location->SetPC(target)};
ir.SetTerm(IR::Term::CheckBit{cond_1, cond_0});
return false;
}
@@ -120,8 +120,8 @@ bool TranslatorVisitor::TBNZ(Imm<1> b5, Imm<5> b40, Imm<14> imm14, Reg Rt) {
ir.SetCheckBit(ir.TestBit(operand, ir.Imm8(bit_pos)));
u64 target = ir.PC() + offset;
auto cond_1 = IR::Term::LinkBlock{ir.current_location.SetPC(target)};
auto cond_0 = IR::Term::LinkBlock{ir.current_location.AdvancePC(4)};
auto cond_1 = IR::Term::LinkBlock{ir.current_location->SetPC(target)};
auto cond_0 = IR::Term::LinkBlock{ir.current_location->AdvancePC(4)};
ir.SetTerm(IR::Term::CheckBit{cond_1, cond_0});
return false;
}

View File

@@ -9,8 +9,8 @@
namespace Dynarmic::A64 {
bool TranslatorVisitor::SVC(Imm<16> imm16) {
ir.PushRSB(ir.current_location.AdvancePC(4));
ir.SetPC(ir.Imm64(ir.current_location.PC() + 4));
ir.PushRSB(ir.current_location->AdvancePC(4));
ir.SetPC(ir.Imm64(ir.current_location->PC() + 4));
ir.CallSupervisor(imm16.ZeroExtend());
ir.SetTerm(IR::Term::CheckHalt{IR::Term::PopRSBHint{}});
return false;

View File

@@ -11,7 +11,7 @@
namespace Dynarmic::A64 {
bool TranslatorVisitor::InterpretThisInstruction() {
ir.SetTerm(IR::Term::Interpret(ir.current_location));
ir.SetTerm(IR::Term::Interpret(*ir.current_location));
return false;
}

View File

@@ -141,6 +141,17 @@ struct TranslatorVisitor final {
bool SYSL(Imm<3> op1, Imm<4> CRn, Imm<4> CRm, Imm<3> op2, Reg Rt);
bool MRS(bool o0, Imm<3> op1, Imm<4> CRn, Imm<4> CRm, Imm<3> op2, Reg Rt);
// SYS: Data Cache
bool DC_IVAC(Reg Rt);
bool DC_ISW(Reg Rt);
bool DC_CSW(Reg Rt);
bool DC_CISW(Reg Rt);
bool DC_ZVA(Reg Rt);
bool DC_CVAC(Reg Rt);
bool DC_CVAU(Reg Rt);
bool DC_CVAP(Reg Rt);
bool DC_CIVAC(Reg Rt);
// Unconditonal branch (Register)
bool BR(Reg Rn);
bool BRA(bool Z, bool M, Reg Rn, Reg Rm);

View File

@@ -0,0 +1,52 @@
/* 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::A64 {
static bool DataCacheInstruction(TranslatorVisitor& tv, IREmitter& ir, DataCacheOperation op, const Reg Rt) {
ir.DataCacheOperationRaised(op, tv.X(64, Rt));
return true;
}
bool TranslatorVisitor::DC_IVAC(Reg Rt) {
return DataCacheInstruction(*this, ir, DataCacheOperation::InvaldiateByVAToPoC, Rt);
}
bool TranslatorVisitor::DC_ISW(Reg Rt) {
return DataCacheInstruction(*this, ir, DataCacheOperation::InvalidateBySetWay, Rt);
}
bool TranslatorVisitor::DC_CSW(Reg Rt) {
return DataCacheInstruction(*this, ir, DataCacheOperation::CleanBySetWay, Rt);
}
bool TranslatorVisitor::DC_CISW(Reg Rt) {
return DataCacheInstruction(*this, ir, DataCacheOperation::CleanAndInvalidateBySetWay, Rt);
}
bool TranslatorVisitor::DC_ZVA(Reg Rt) {
return DataCacheInstruction(*this, ir, DataCacheOperation::ZeroByVA, Rt);
}
bool TranslatorVisitor::DC_CVAC(Reg Rt) {
return DataCacheInstruction(*this, ir, DataCacheOperation::CleanByVAToPoC, Rt);
}
bool TranslatorVisitor::DC_CVAU(Reg Rt) {
return DataCacheInstruction(*this, ir, DataCacheOperation::CleanByVAToPoU, Rt);
}
bool TranslatorVisitor::DC_CVAP(Reg Rt) {
return DataCacheInstruction(*this, ir, DataCacheOperation::CleanByVAToPoP, Rt);
}
bool TranslatorVisitor::DC_CIVAC(Reg Rt) {
return DataCacheInstruction(*this, ir, DataCacheOperation::CleanAndInvalidateByVAToPoC, Rt);
}
} // namespace Dynarmic::A64

View File

@@ -18,7 +18,7 @@ IR::Block Translate(LocationDescriptor descriptor, MemoryReadCodeFuncType memory
bool should_continue = true;
while (should_continue) {
const u64 pc = visitor.ir.current_location.PC();
const u64 pc = visitor.ir.current_location->PC();
const u32 instruction = memory_read_code(pc);
if (auto decoder = Decode<TranslatorVisitor>(instruction)) {
@@ -27,13 +27,13 @@ IR::Block Translate(LocationDescriptor descriptor, MemoryReadCodeFuncType memory
should_continue = visitor.InterpretThisInstruction();
}
visitor.ir.current_location = visitor.ir.current_location.AdvancePC(4);
visitor.ir.current_location = visitor.ir.current_location->AdvancePC(4);
block.CycleCount()++;
}
ASSERT_MSG(block.HasTerminal(), "Terminal has not been set");
block.SetEndLocation(visitor.ir.current_location);
block.SetEndLocation(*visitor.ir.current_location);
return block;
}
@@ -48,10 +48,10 @@ bool TranslateSingleInstruction(IR::Block& block, LocationDescriptor descriptor,
should_continue = visitor.InterpretThisInstruction();
}
visitor.ir.current_location = visitor.ir.current_location.AdvancePC(4);
visitor.ir.current_location = visitor.ir.current_location->AdvancePC(4);
block.CycleCount()++;
block.SetEndLocation(visitor.ir.current_location);
block.SetEndLocation(*visitor.ir.current_location);
return should_continue;
}

View File

@@ -269,14 +269,15 @@ bool Inst::IsCoprocessorInstruction() const {
}
bool Inst::MayHaveSideEffects() const {
return op == Opcode::PushRSB ||
op == Opcode::A64SetCheckBit ||
CausesCPUException() ||
WritesToCoreRegister() ||
WritesToCPSR() ||
WritesToFPSCR() ||
AltersExclusiveState() ||
IsMemoryWrite() ||
return op == Opcode::PushRSB ||
op == Opcode::A64SetCheckBit ||
op == Opcode::A64DataCacheOperationRaised ||
CausesCPUException() ||
WritesToCoreRegister() ||
WritesToCPSR() ||
WritesToFPSCR() ||
AltersExclusiveState() ||
IsMemoryWrite() ||
IsCoprocessorInstruction();
}

View File

@@ -58,6 +58,7 @@ A64OPC(SetSP, T::Void, T::U64
A64OPC(SetPC, T::Void, T::U64 )
A64OPC(CallSupervisor, T::Void, T::U32 )
A64OPC(ExceptionRaised, T::Void, T::U64, T::U64 )
A64OPC(DataCacheOperationRaised, T::Void, T::U64, T::U64 )
// Hints
OPCODE(PushRSB, T::Void, T::U64 )