diff --git a/src/backend_x64/a64_emit_x64.cpp b/src/backend_x64/a64_emit_x64.cpp index e4b97838..1719a0f1 100644 --- a/src/backend_x64/a64_emit_x64.cpp +++ b/src/backend_x64/a64_emit_x64.cpp @@ -198,6 +198,20 @@ void A64EmitX64::EmitA64SetSP(A64EmitContext& ctx, IR::Inst* inst) { } } +void A64EmitX64::EmitA64SetPC(A64EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + auto addr = qword[r15 + offsetof(A64JitState, pc)]; + if (args[0].FitsInImmediateU32()) { + code->mov(addr, args[0].GetImmediateU32()); + } else if (args[0].IsInXmm()) { + Xbyak::Xmm to_store = ctx.reg_alloc.UseXmm(args[0]); + code->movq(addr, to_store); + } else { + Xbyak::Reg64 to_store = ctx.reg_alloc.UseGpr(args[0]); + code->mov(addr, to_store); + } +} + void A64EmitX64::EmitTerminalImpl(IR::Term::Interpret terminal, IR::LocationDescriptor) { code->mov(code->ABI_PARAM1, A64::LocationDescriptor{terminal.next}.PC()); code->mov(code->ABI_PARAM2.cvt32(), 1); diff --git a/src/backend_x64/a64_interface.cpp b/src/backend_x64/a64_interface.cpp index c41c06bd..0d5d164f 100644 --- a/src/backend_x64/a64_interface.cpp +++ b/src/backend_x64/a64_interface.cpp @@ -53,6 +53,7 @@ public: SCOPE_EXIT({ this->is_executing = false; }); jit_state.halt_requested = false; + // TODO: Check code alignment block_of_code.RunCode(&jit_state); PerformRequestedCacheInvalidation(); diff --git a/src/frontend/A64/decoder/a64.h b/src/frontend/A64/decoder/a64.h index de29ab8d..70f5b233 100644 --- a/src/frontend/A64/decoder/a64.h +++ b/src/frontend/A64/decoder/a64.h @@ -102,15 +102,15 @@ std::vector> GetDecodeTable() { //INST(&V::MRS, "MRS", "110101010011poooNNNNMMMMooottttt"), // Unconditonal branch (Register) - //INST(&V::BR, "BR", "1101011000011111000000nnnnn00000"), - //INST(&V::BRA, "BRAA, BRAAZ, BRAB, BRABZ", "1101011Z0001111100001Mnnnnnmmmmm"), - //INST(&V::BLR, "BLR", "1101011000111111000000nnnnn00000"), - //INST(&V::BLRA, "BLRAA, BLRAAZ, BLRAB, BLRABZ", "1101011Z0011111100001Mnnnnnmmmmm"), - //INST(&V::RET, "RET", "1101011001011111000000nnnnn00000"), - //INST(&V::RETA, "RETAA, RETAB", "110101100101111100001M1111111111"), - //INST(&V::ERET, "ERET", "11010110100111110000001111100000"), - //INST(&V::ERETA, "ERETAA, ERETAB", "110101101001111100001M1111111111"), + INST(&V::BLR, "BLR", "1101011000111111000000nnnnn00000"), + INST(&V::BR, "BR", "1101011000011111000000nnnnn00000"), //INST(&V::DRPS, "DRPS", "11010110101111110000001111100000"), + //INST(&V::ERET, "ERET", "11010110100111110000001111100000"), + INST(&V::RET, "RET", "1101011001011111000000nnnnn00000"), + //INST(&V::BLRA, "BLRAA, BLRAAZ, BLRAB, BLRABZ", "1101011Z0011111100001Mnnnnnmmmmm"), // ARMv8.3 + //INST(&V::BRA, "BRAA, BRAAZ, BRAB, BRABZ", "1101011Z0001111100001Mnnnnnmmmmm"), // ARMv8.3 + //INST(&V::ERETA, "ERETAA, ERETAB", "110101101001111100001M1111111111"), // ARMv8.3 + //INST(&V::RETA, "RETAA, RETAB", "110101100101111100001M1111111111"), // ARMv8.3 // Unconditonal branch (immediate) INST(&V::B_uncond, "B", "000101iiiiiiiiiiiiiiiiiiiiiiiiii"), diff --git a/src/frontend/A64/ir_emitter.cpp b/src/frontend/A64/ir_emitter.cpp index e0f6029e..41e6d4af 100644 --- a/src/frontend/A64/ir_emitter.cpp +++ b/src/frontend/A64/ir_emitter.cpp @@ -62,5 +62,9 @@ void IREmitter::SetSP(const IR::U64& value) { Inst(Opcode::A64SetSP, value); } +void IREmitter::SetPC(const IR::U64& value) { + Inst(Opcode::A64SetPC, value); +} + } // namespace IR } // namespace Dynarmic diff --git a/src/frontend/A64/ir_emitter.h b/src/frontend/A64/ir_emitter.h index 27e16cc3..d840aaa6 100644 --- a/src/frontend/A64/ir_emitter.h +++ b/src/frontend/A64/ir_emitter.h @@ -40,6 +40,7 @@ public: void SetW(Reg dest_reg, const IR::U32& value); void SetX(Reg dest_reg, const IR::U64& value); void SetSP(const IR::U64& value); + void SetPC(const IR::U64& value); }; } // namespace IR diff --git a/src/frontend/A64/translate/impl/branch.cpp b/src/frontend/A64/translate/impl/branch.cpp index 305d81ce..d32340cc 100644 --- a/src/frontend/A64/translate/impl/branch.cpp +++ b/src/frontend/A64/translate/impl/branch.cpp @@ -38,5 +38,29 @@ bool TranslatorVisitor::BL(Imm<26> imm26) { return false; } +bool TranslatorVisitor::BLR(Reg Rn) { + X(64, Reg::R30, ir.Imm64(ir.PC() + 4)); + ir.PushRSB(ir.current_location.AdvancePC(4)); + + auto target = X(64, Rn); + ir.SetPC(target); + ir.SetTerm(IR::Term::ReturnToDispatch{}); + return false; +} + +bool TranslatorVisitor::BR(Reg Rn) { + auto target = X(64, Rn); + ir.SetPC(target); + ir.SetTerm(IR::Term::ReturnToDispatch{}); + return false; +} + +bool TranslatorVisitor::RET(Reg Rn) { + auto target = X(64, Rn); + ir.SetPC(target); + ir.SetTerm(IR::Term::PopRSBHint{}); + return false; +} + } // namespace A64 } // namespace Dynarmic diff --git a/src/frontend/ir/microinstruction.cpp b/src/frontend/ir/microinstruction.cpp index 46a806c5..dda2de02 100644 --- a/src/frontend/ir/microinstruction.cpp +++ b/src/frontend/ir/microinstruction.cpp @@ -155,6 +155,7 @@ bool Inst::WritesToCoreRegister() const { case Opcode::A64SetW: case Opcode::A64SetX: case Opcode::A64SetSP: + case Opcode::A64SetPC: return true; default: diff --git a/src/frontend/ir/opcodes.inc b/src/frontend/ir/opcodes.inc index 9cdc3c78..23170529 100644 --- a/src/frontend/ir/opcodes.inc +++ b/src/frontend/ir/opcodes.inc @@ -43,6 +43,7 @@ A64OPC(GetSP, T::U64, 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 ) // Hints OPCODE(PushRSB, T::Void, T::U64 )