From 87564875546719680073db67f424b005811a3212 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Mon, 12 Feb 2018 00:06:44 +0000 Subject: [PATCH] A64: Partially implement MRS --- include/dynarmic/A64/config.h | 4 ++++ src/backend_x64/a64_emit_x64.cpp | 17 +++++++++++++++++ src/frontend/A64/decoder/a64.inc | 2 +- src/frontend/A64/ir_emitter.cpp | 8 ++++++++ src/frontend/A64/ir_emitter.h | 2 ++ src/frontend/A64/translate/impl/impl.h | 2 +- src/frontend/A64/translate/impl/system.cpp | 13 +++++++++++++ src/frontend/ir/opcodes.inc | 2 ++ 8 files changed, 48 insertions(+), 2 deletions(-) diff --git a/include/dynarmic/A64/config.h b/include/dynarmic/A64/config.h index ca105c7b..312f71a6 100644 --- a/include/dynarmic/A64/config.h +++ b/include/dynarmic/A64/config.h @@ -107,6 +107,10 @@ struct UserConfig { /// DCZID_EL0<4> is 0 if the DC ZVA instruction is permitted. std::uint32_t dczid_el0 = 4; + /// Pointer to where TPIDRRO_EL0 is stored. This pointer will be inserted into + /// emitted code. + const std::uint64_t* tpidrro_el0 = nullptr; + // Determines whether AddTicks and GetTicksRemaining are called. // If false, execution will continue until soon after Jit::HaltExecution is called. // bool enable_ticks = true; // TODO diff --git a/src/backend_x64/a64_emit_x64.cpp b/src/backend_x64/a64_emit_x64.cpp index 98e6b56f..fefb4140 100644 --- a/src/backend_x64/a64_emit_x64.cpp +++ b/src/backend_x64/a64_emit_x64.cpp @@ -324,6 +324,23 @@ void A64EmitX64::EmitA64DataMemoryBarrier(A64EmitContext&, IR::Inst*) { code.lfence(); } +void A64EmitX64::EmitA64GetDCZID(A64EmitContext& ctx, IR::Inst* inst) { + Xbyak::Reg32 result = ctx.reg_alloc.ScratchGpr().cvt32(); + code.mov(result, conf.dczid_el0); + ctx.reg_alloc.DefineValue(inst, result); +} + +void A64EmitX64::EmitA64GetTPIDRRO(A64EmitContext& ctx, IR::Inst* inst) { + Xbyak::Reg64 result = ctx.reg_alloc.ScratchGpr(); + if (conf.tpidrro_el0) { + code.mov(result, u64(conf.tpidrro_el0)); + code.mov(result, qword[result]); + } else { + code.xor_(result.cvt32(), result.cvt32()); + } + ctx.reg_alloc.DefineValue(inst, result); +} + void A64EmitX64::EmitA64ReadMemory8(A64EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); ctx.reg_alloc.HostCall(inst, {}, args[0]); diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc index e1c26acf..f3fdbf4f 100644 --- a/src/frontend/A64/decoder/a64.inc +++ b/src/frontend/A64/decoder/a64.inc @@ -68,7 +68,7 @@ INST(DMB, "DMB", "11010 //INST(SYS, "SYS", "1101010100001oooNNNNMMMMooottttt") //INST(MSR_reg, "MSR (register)", "110101010001poooNNNNMMMMooottttt") //INST(SYSL, "SYSL", "1101010100101oooNNNNMMMMooottttt") -//INST(MRS, "MRS", "110101010011poooNNNNMMMMooottttt") +INST(MRS, "MRS", "110101010011poooNNNNMMMMooottttt") // SYS: Data Cache INST(DC_IVAC, "DC IVAC", "110101010000100001110110001ttttt") diff --git a/src/frontend/A64/ir_emitter.cpp b/src/frontend/A64/ir_emitter.cpp index b717709c..659ff131 100644 --- a/src/frontend/A64/ir_emitter.cpp +++ b/src/frontend/A64/ir_emitter.cpp @@ -53,6 +53,14 @@ void IREmitter::DataMemoryBarrier() { Inst(Opcode::A64DataMemoryBarrier); } +IR::U32 IREmitter::GetDCZID() { + return Inst(Opcode::A64GetDCZID); +} + +IR::U64 IREmitter::GetTPIDRRO() { + return Inst(Opcode::A64GetTPIDRRO); +} + IR::U8 IREmitter::ReadMemory8(const IR::U64& vaddr) { return Inst(Opcode::A64ReadMemory8, vaddr); } diff --git a/src/frontend/A64/ir_emitter.h b/src/frontend/A64/ir_emitter.h index 1c0c3686..68784c6e 100644 --- a/src/frontend/A64/ir_emitter.h +++ b/src/frontend/A64/ir_emitter.h @@ -44,6 +44,8 @@ public: void DataCacheOperationRaised(DataCacheOperation op, const IR::U64& value); void DataSynchronizationBarrier(); void DataMemoryBarrier(); + IR::U32 GetDCZID(); + IR::U64 GetTPIDRRO(); IR::U8 ReadMemory8(const IR::U64& vaddr); IR::U16 ReadMemory16(const IR::U64& vaddr); diff --git a/src/frontend/A64/translate/impl/impl.h b/src/frontend/A64/translate/impl/impl.h index 322dbecb..26aa7659 100644 --- a/src/frontend/A64/translate/impl/impl.h +++ b/src/frontend/A64/translate/impl/impl.h @@ -139,7 +139,7 @@ struct TranslatorVisitor final { bool SYS(Imm<3> op1, Imm<4> CRn, Imm<4> CRm, Imm<3> op2, Reg Rt); bool MSR_reg(bool o0, Imm<3> op1, Imm<4> CRn, Imm<4> CRm, Imm<3> op2, Reg Rt); 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); + bool MRS(Imm<1> o0, Imm<3> op1, Imm<4> CRn, Imm<4> CRm, Imm<3> op2, Reg Rt); // SYS: Data Cache bool DC_IVAC(Reg Rt); diff --git a/src/frontend/A64/translate/impl/system.cpp b/src/frontend/A64/translate/impl/system.cpp index 074cc74a..f6ee1bcd 100644 --- a/src/frontend/A64/translate/impl/system.cpp +++ b/src/frontend/A64/translate/impl/system.cpp @@ -46,4 +46,17 @@ bool TranslatorVisitor::DMB(Imm<4> /*CRm*/) { return true; } +bool TranslatorVisitor::MRS(Imm<1> o0, Imm<3> op1, Imm<4> CRn, Imm<4> CRm, Imm<3> op2, Reg Rt) { + const size_t sys_reg = concatenate(Imm<1>{1}, o0, op1, CRn, CRm, op2).ZeroExtend(); + switch (sys_reg) { + case 0b11'011'1101'0000'011: // TPIDRRO_EL0 + X(64, Rt, ir.GetTPIDRRO()); + return true; + case 0b11'011'0000'0000'111: // DCZID_EL0 + X(32, Rt, ir.GetDCZID()); + return true; + } + return InterpretThisInstruction(); +} + } // namespace Dynarmic::A64 diff --git a/src/frontend/ir/opcodes.inc b/src/frontend/ir/opcodes.inc index 05cb2469..461f663d 100644 --- a/src/frontend/ir/opcodes.inc +++ b/src/frontend/ir/opcodes.inc @@ -61,6 +61,8 @@ A64OPC(ExceptionRaised, T::Void, T::U64, T::U64 A64OPC(DataCacheOperationRaised, T::Void, T::U64, T::U64 ) A64OPC(DataSynchronizationBarrier, T::Void, ) A64OPC(DataMemoryBarrier, T::Void, ) +A64OPC(GetDCZID, T::U32, ) +A64OPC(GetTPIDRRO, T::U64, ) // Hints OPCODE(PushRSB, T::Void, T::U64 )