From 68391b0a058b77688998e5e4dbd6cb9fd3b51dc0 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Mon, 8 Jan 2018 22:03:03 +0000 Subject: [PATCH] A64: Implement SVC --- src/CMakeLists.txt | 1 + src/backend_x64/a64_emit_x64.cpp | 32 +++++++++++++++++-------- src/frontend/A64/decoder/a64.h | 2 +- src/frontend/A64/ir_emitter.cpp | 4 ++++ src/frontend/A64/ir_emitter.h | 2 ++ src/frontend/ir/basic_block.cpp | 2 ++ src/frontend/ir/location_descriptor.cpp | 2 +- src/frontend/ir/microinstruction.cpp | 5 ++-- src/frontend/ir/opcodes.inc | 1 + 9 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5f684831..8eaafb05 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -62,6 +62,7 @@ add_library(dynarmic frontend/A64/translate/impl/data_processing_addsub.cpp frontend/A64/translate/impl/data_processing_logical.cpp frontend/A64/translate/impl/data_processing_pcrel.cpp + frontend/A64/translate/impl/exception_generating.cpp frontend/A64/translate/impl/impl.cpp frontend/A64/translate/impl/impl.h frontend/A64/translate/translate.cpp diff --git a/src/backend_x64/a64_emit_x64.cpp b/src/backend_x64/a64_emit_x64.cpp index db4ceeeb..b02ecf76 100644 --- a/src/backend_x64/a64_emit_x64.cpp +++ b/src/backend_x64/a64_emit_x64.cpp @@ -220,11 +220,20 @@ void A64EmitX64::EmitA64SetPC(A64EmitContext& ctx, IR::Inst* inst) { } } +void A64EmitX64::EmitA64CallSupervisor(A64EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + ASSERT(args[0].IsImmediate()); + u32 imm = args[0].GetImmediateU32(); + Devirtualize<&A64::UserCallbacks::CallSVC>(conf.callbacks).EmitCall(code, [&](Xbyak::Reg64 param1) { + code->mov(param1.cvt32(), imm); + }); +} + void A64EmitX64::EmitTerminalImpl(IR::Term::Interpret terminal, IR::LocationDescriptor) { - //code->mov(qword[r15 + offsetof(A64JitState, pc)], code->ABI_PARAM1.cvt32()); code->SwitchMxcsrOnExit(); - Devirtualize<&A64::UserCallbacks::InterpreterFallback>(conf.callbacks).EmitCall(code, [&](Xbyak::Reg64 param1, Xbyak::Reg64 param2){ + Devirtualize<&A64::UserCallbacks::InterpreterFallback>(conf.callbacks).EmitCall(code, [&](Xbyak::Reg64 param1, Xbyak::Reg64 param2) { code->mov(param1, A64::LocationDescriptor{terminal.next}.PC()); + code->mov(qword[r15 + offsetof(A64JitState, pc)], param1); code->mov(param2.cvt32(), 1); }); code->ReturnFromRunCode(true); // TODO: Check cycles @@ -249,8 +258,9 @@ void A64EmitX64::EmitTerminalImpl(IR::Term::LinkBlock terminal, IR::LocationDesc code->SwitchToFarCode(); code->align(16); code->L(dest); - code->mov(qword[r15 + offsetof(A64JitState, pc)], A64::LocationDescriptor{terminal.next}.PC()); - PushRSBHelper(rax, rbx, terminal.next); + code->mov(rax, A64::LocationDescriptor{terminal.next}.PC()); + code->mov(qword[r15 + offsetof(A64JitState, pc)], rax); + // PushRSBHelper(rax, rbx, terminal.next); code->ForceReturnFromRunCode(); code->SwitchToNearCode(); } @@ -264,8 +274,8 @@ void A64EmitX64::EmitTerminalImpl(IR::Term::LinkBlockFast terminal, IR::Location } } -void A64EmitX64::EmitTerminalImpl(IR::Term::PopRSBHint, IR::LocationDescriptor) { - ASSERT(false); +void A64EmitX64::EmitTerminalImpl(IR::Term::PopRSBHint, IR::LocationDescriptor initial_location) { + EmitTerminalImpl(IR::Term::ReturnToDispatch{}, initial_location); } void A64EmitX64::EmitTerminalImpl(IR::Term::If terminal, IR::LocationDescriptor initial_location) { @@ -295,10 +305,11 @@ void A64EmitX64::EmitPatchJg(const IR::LocationDescriptor& target_desc, CodePtr if (target_code_ptr) { code->jg(target_code_ptr); } else { - code->mov(qword[r15 + offsetof(A64JitState, pc)], A64::LocationDescriptor{target_desc}.PC()); + code->mov(rax, A64::LocationDescriptor{target_desc}.PC()); + code->mov(qword[r15 + offsetof(A64JitState, pc)], rax); code->jg(code->GetReturnFromRunCodeAddress()); } - code->EnsurePatchLocationSize(patch_location, 17); + code->EnsurePatchLocationSize(patch_location, 30); // TODO: Reduce size } void A64EmitX64::EmitPatchJmp(const IR::LocationDescriptor& target_desc, CodePtr target_code_ptr) { @@ -306,10 +317,11 @@ void A64EmitX64::EmitPatchJmp(const IR::LocationDescriptor& target_desc, CodePtr if (target_code_ptr) { code->jmp(target_code_ptr); } else { - code->mov(qword[r15 + offsetof(A64JitState, pc)], A64::LocationDescriptor{target_desc}.PC()); + code->mov(rax, A64::LocationDescriptor{target_desc}.PC()); + code->mov(qword[r15 + offsetof(A64JitState, pc)], rax); code->jmp(code->GetReturnFromRunCodeAddress()); } - code->EnsurePatchLocationSize(patch_location, 16); + code->EnsurePatchLocationSize(patch_location, 30); // TODO: Reduce size } void A64EmitX64::EmitPatchMovRcx(CodePtr target_code_ptr) { diff --git a/src/frontend/A64/decoder/a64.h b/src/frontend/A64/decoder/a64.h index 6cd3e6bb..02349c94 100644 --- a/src/frontend/A64/decoder/a64.h +++ b/src/frontend/A64/decoder/a64.h @@ -62,7 +62,7 @@ std::vector> GetDecodeTable() { INST(&V::B_cond, "B.cond", "01010100iiiiiiiiiiiiiiiiiii0cccc"), // Exception generation - //INST(&V::SVC, "SVC", "11010100000iiiiiiiiiiiiiiii00001"), + INST(&V::SVC, "SVC", "11010100000iiiiiiiiiiiiiiii00001"), //INST(&V::HVC, "HVC", "11010100000iiiiiiiiiiiiiiii00010"), //INST(&V::SMC, "SMC", "11010100000iiiiiiiiiiiiiiii00011"), //INST(&V::BRK, "BRK", "11010100001iiiiiiiiiiiiiiii00000"), diff --git a/src/frontend/A64/ir_emitter.cpp b/src/frontend/A64/ir_emitter.cpp index 46425e78..3e389139 100644 --- a/src/frontend/A64/ir_emitter.cpp +++ b/src/frontend/A64/ir_emitter.cpp @@ -34,6 +34,10 @@ void IREmitter::SetNZCV(const IR::NZCV& nzcv) { Inst(Opcode::A64SetNZCV, nzcv); } +void IREmitter::CallSupervisor(u32 imm) { + Inst(Opcode::A64CallSupervisor, Imm32(imm)); +} + IR::U32 IREmitter::GetW(Reg reg) { if (reg == Reg::ZR) return Imm32(0); diff --git a/src/frontend/A64/ir_emitter.h b/src/frontend/A64/ir_emitter.h index e3cb6c14..c99086b6 100644 --- a/src/frontend/A64/ir_emitter.h +++ b/src/frontend/A64/ir_emitter.h @@ -35,6 +35,8 @@ public: IR::U1 GetCFlag(); void SetNZCV(const IR::NZCV& nzcv); + void CallSupervisor(u32 imm); + IR::U32 GetW(Reg source_reg); IR::U64 GetX(Reg source_reg); IR::U64 GetSP(); diff --git a/src/frontend/ir/basic_block.cpp b/src/frontend/ir/basic_block.cpp index b3a91c55..fa51487d 100644 --- a/src/frontend/ir/basic_block.cpp +++ b/src/frontend/ir/basic_block.cpp @@ -166,6 +166,8 @@ std::string DumpBlock(const IR::Block& block) { return fmt::format("#{}", arg.GetU8()); case Type::U32: return fmt::format("#{:#x}", arg.GetU32()); + case Type::U64: + return fmt::format("#{:#x}", arg.GetU64()); case Type::A32Reg: return A32::RegToString(arg.GetA32RegRef()); case Type::A32ExtReg: diff --git a/src/frontend/ir/location_descriptor.cpp b/src/frontend/ir/location_descriptor.cpp index 0c18c98a..3c071bc7 100644 --- a/src/frontend/ir/location_descriptor.cpp +++ b/src/frontend/ir/location_descriptor.cpp @@ -13,7 +13,7 @@ namespace Dynarmic { namespace IR { std::ostream& operator<<(std::ostream& o, const LocationDescriptor& descriptor) { - o << fmt::format("{{{{}}}}", descriptor.Value()); + o << fmt::format("{{{:016x}}}", descriptor.Value()); return o; } diff --git a/src/frontend/ir/microinstruction.cpp b/src/frontend/ir/microinstruction.cpp index 63b358f2..3476f79d 100644 --- a/src/frontend/ir/microinstruction.cpp +++ b/src/frontend/ir/microinstruction.cpp @@ -219,8 +219,9 @@ bool Inst::WritesToFPSCR() const { } bool Inst::CausesCPUException() const { - return op == Opcode::Breakpoint || - op == Opcode::A32CallSupervisor; + return op == Opcode::Breakpoint || + op == Opcode::A32CallSupervisor || + op == Opcode::A64CallSupervisor; } bool Inst::AltersExclusiveState() const { diff --git a/src/frontend/ir/opcodes.inc b/src/frontend/ir/opcodes.inc index e9ece807..9e14c411 100644 --- a/src/frontend/ir/opcodes.inc +++ b/src/frontend/ir/opcodes.inc @@ -45,6 +45,7 @@ A64OPC(SetW, T::Void, T::A64Reg, T::U32 A64OPC(SetX, T::Void, T::A64Reg, T::U64 ) A64OPC(SetSP, T::Void, T::U64 ) A64OPC(SetPC, T::Void, T::U64 ) +A64OPC(CallSupervisor, T::Void, T::U32 ) // Hints OPCODE(PushRSB, T::Void, T::U64 )