diff --git a/src/backend_x64/a32_emit_x64.cpp b/src/backend_x64/a32_emit_x64.cpp index 7f2f3784..9df22d48 100644 --- a/src/backend_x64/a32_emit_x64.cpp +++ b/src/backend_x64/a32_emit_x64.cpp @@ -584,6 +584,18 @@ void A32EmitX64::EmitA32CallSupervisor(A32EmitContext& ctx, IR::Inst* inst) { code->SwitchMxcsrOnEntry(); } +void A32EmitX64::EmitA32ExceptionRaised(A32EmitContext& ctx, IR::Inst* inst) { + ctx.reg_alloc.HostCall(nullptr); + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + ASSERT(args[0].IsImmediate() && args[1].IsImmediate()); + u32 pc = args[0].GetImmediateU32(); + u64 exception = args[1].GetImmediateU64(); + DEVIRT(config.callbacks, &A32::UserCallbacks::ExceptionRaised).EmitCall(code, [&](Xbyak::Reg64 param1, Xbyak::Reg64 param2) { + code->mov(param1, pc); + code->mov(param2, exception); + }); +} + static u32 GetFpscrImpl(A32JitState* jit_state) { return jit_state->Fpscr(); } diff --git a/src/frontend/A32/ir_emitter.cpp b/src/frontend/A32/ir_emitter.cpp index 38428403..e1ac917f 100644 --- a/src/frontend/A32/ir_emitter.cpp +++ b/src/frontend/A32/ir_emitter.cpp @@ -86,6 +86,10 @@ void IREmitter::CallSupervisor(const IR::U32& value) { Inst(Opcode::A32CallSupervisor, value); } +void IREmitter::ExceptionRaised(const Exception exception) { + Inst(Opcode::A64ExceptionRaised, Imm32(PC()), Imm64(static_cast(exception))); +} + IR::U32 IREmitter::GetCpsr() { return Inst(Opcode::A32GetCpsr); } diff --git a/src/frontend/A32/ir_emitter.h b/src/frontend/A32/ir_emitter.h index 821f35dc..88793372 100644 --- a/src/frontend/A32/ir_emitter.h +++ b/src/frontend/A32/ir_emitter.h @@ -18,6 +18,8 @@ namespace Dynarmic::A32 { +enum class Exception; + /** * Convenience class to construct a basic block of the intermediate representation. * `block` is the resulting block. @@ -41,7 +43,9 @@ public: void BranchWritePC(const IR::U32& value); void BXWritePC(const IR::U32& value); void LoadWritePC(const IR::U32& value); + void CallSupervisor(const IR::U32& value); + void ExceptionRaised(Exception exception); IR::U32 GetCpsr(); void SetCpsr(const IR::U32& value); diff --git a/src/frontend/A32/translate/translate_arm.cpp b/src/frontend/A32/translate/translate_arm.cpp index af1da5ad..09a03ee2 100644 --- a/src/frontend/A32/translate/translate_arm.cpp +++ b/src/frontend/A32/translate/translate_arm.cpp @@ -7,6 +7,7 @@ #include #include "common/assert.h" +#include "dynarmic/A32/config.h" #include "frontend/A32/decoder/arm.h" #include "frontend/A32/decoder/vfp2.h" #include "frontend/A32/location_descriptor.h" @@ -117,7 +118,14 @@ bool ArmTranslatorVisitor::InterpretThisInstruction() { } bool ArmTranslatorVisitor::UnpredictableInstruction() { - ASSERT_MSG(false, "UNPREDICTABLE"); + ir.ExceptionRaised(Exception::UnpredictableInstruction); + ir.SetTerm(IR::Term::CheckHalt{IR::Term::ReturnToDispatch{}}); + return false; +} + +bool ArmTranslatorVisitor::UndefinedInstruction() { + ir.ExceptionRaised(Exception::UndefinedInstruction); + ir.SetTerm(IR::Term::CheckHalt{IR::Term::ReturnToDispatch{}}); return false; } diff --git a/src/frontend/A32/translate/translate_arm/exception_generating.cpp b/src/frontend/A32/translate/translate_arm/exception_generating.cpp index 69c412eb..cbdae36c 100644 --- a/src/frontend/A32/translate/translate_arm/exception_generating.cpp +++ b/src/frontend/A32/translate/translate_arm/exception_generating.cpp @@ -26,7 +26,7 @@ bool ArmTranslatorVisitor::arm_SVC(Cond cond, Imm24 imm24) { } bool ArmTranslatorVisitor::arm_UDF() { - return InterpretThisInstruction(); + return UndefinedInstruction(); } } // namespace Dynarmic::A32 diff --git a/src/frontend/A32/translate/translate_arm/translate_arm.h b/src/frontend/A32/translate/translate_arm/translate_arm.h index 6d63c55c..f137dc93 100644 --- a/src/frontend/A32/translate/translate_arm/translate_arm.h +++ b/src/frontend/A32/translate/translate_arm/translate_arm.h @@ -35,6 +35,7 @@ struct ArmTranslatorVisitor final { bool ConditionPassed(Cond cond); bool InterpretThisInstruction(); bool UnpredictableInstruction(); + bool UndefinedInstruction(); static u32 rotr(u32 x, int shift) { shift &= 31; diff --git a/src/frontend/ir/opcodes.inc b/src/frontend/ir/opcodes.inc index f408a44b..81b958f2 100644 --- a/src/frontend/ir/opcodes.inc +++ b/src/frontend/ir/opcodes.inc @@ -29,6 +29,7 @@ A32OPC(SetGEFlags, T::Void, T::U32 A32OPC(SetGEFlagsCompressed, T::Void, T::U32 ) A32OPC(BXWritePC, T::Void, T::U32 ) A32OPC(CallSupervisor, T::Void, T::U32 ) +A32OPC(ExceptionRaised, T::Void, T::U32, T::U64 ) A32OPC(GetFpscr, T::U32, ) A32OPC(SetFpscr, T::Void, T::U32, ) A32OPC(GetFpscrNZCV, T::U32, )