mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-25 07:40:13 +00:00
JitX64: Implement exception-generating instructions
This commit is contained in:
parent
1f8217a09b
commit
a5e3874db8
@ -190,8 +190,8 @@ static const std::array<Instruction, 221> arm_instruction_table = {{
|
||||
{ "TST (rsr)", MakeMatcher<5>("cccc00010001nnnn0000ssss0rr1mmmm", &Visitor::TST_rsr) }, // all
|
||||
|
||||
// Exception Generating instructions
|
||||
{ "BKPT", MakeMatcher<0>("----00010010------------0111----", &Visitor::BKPT) }, // ARMv5
|
||||
{ "SVC", MakeMatcher<0>("----1111------------------------", &Visitor::SVC) }, // all
|
||||
{ "BKPT", MakeMatcher<3>("cccc00010010vvvvvvvvvvvv0111vvvv", &Visitor::BKPT) }, // ARMv5
|
||||
{ "SVC", MakeMatcher<2>("cccc1111vvvvvvvvvvvvvvvvvvvvvvvv", &Visitor::SVC) }, // all
|
||||
{ "UDF", MakeMatcher<0>("111001111111------------1111----", &Visitor::UDF) }, // all
|
||||
|
||||
// Extension instructions
|
||||
|
@ -133,8 +133,8 @@ public:
|
||||
virtual void TST_rsr(Cond cond, Register Rn, Register Rs, ShiftType shift, Register Rm) = 0;
|
||||
|
||||
// Exception generation instructions
|
||||
virtual void BKPT() = 0;
|
||||
virtual void SVC() = 0;
|
||||
virtual void BKPT(Cond cond, Imm12 imm12, Imm4 imm4) = 0;
|
||||
virtual void SVC(Cond cond, Imm24 imm24) = 0;
|
||||
virtual void UDF() = 0;
|
||||
|
||||
// Extension functions
|
||||
|
@ -395,7 +395,7 @@ static const std::array<Instruction, 27> thumb_instruction_table = { {
|
||||
{ "BKPT", MakeMatcher("10111110xxxxxxxx", [](Visitor* v, u32 instruction) {
|
||||
// BKPT #imm8
|
||||
Imm8 imm8 = bits<0, 7>(instruction);
|
||||
v->BKPT();
|
||||
v->BKPT(0xE, imm8 >> 4, imm8 & 0xF);
|
||||
})},
|
||||
{ "STMIA/LDMIA", MakeMatcher("1100xxxxxxxxxxxx", [](Visitor* v, u32 instruction) {
|
||||
bool L = bits<11, 11>(instruction);
|
||||
@ -418,7 +418,7 @@ static const std::array<Instruction, 27> thumb_instruction_table = { {
|
||||
{ "SWI", MakeMatcher("11011111xxxxxxxx", [](Visitor* v, u32 instruction) {
|
||||
// SWI #imm8
|
||||
Imm8 imm8 = bits<0, 7>(instruction);
|
||||
v->SVC(/*imm8*/);
|
||||
v->SVC(0xE, imm8);
|
||||
})},
|
||||
{ "B", MakeMatcher("11100xxxxxxxxxxx", [](Visitor* v, u32 instruction) {
|
||||
// B <PC + #offset*2>
|
||||
|
@ -2,12 +2,67 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/x64/abi.h"
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
#include "core/hle/svc.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
void JitX64::BKPT() { CompileInterpretInstruction(); }
|
||||
void JitX64::SVC() { CompileInterpretInstruction(); }
|
||||
void JitX64::UDF() { CompileInterpretInstruction(); }
|
||||
using namespace Gen;
|
||||
|
||||
static void Breakpoint(u32 imm) {
|
||||
LOG_DEBUG(Core_ARM11, "Breakpoint instruction hit. Immediate: 0x%08X", imm);
|
||||
}
|
||||
|
||||
void JitX64::BKPT(Cond cond, ArmImm12 imm12, ArmImm4 imm4) {
|
||||
cond_manager.CompileCond((ConditionCode) cond);
|
||||
|
||||
ASSERT_MSG(false, "BKPT instruction @ pc=0x%08X", current.arm_pc);
|
||||
|
||||
reg_alloc.FlushX64(ABI_PARAM1);
|
||||
reg_alloc.LockX64(ABI_PARAM1);
|
||||
|
||||
code->MOV(32, R(ABI_PARAM1), Imm32((imm12 << 4) | imm4));
|
||||
CompileCallHost(reinterpret_cast<const void* const>(&Breakpoint));
|
||||
|
||||
reg_alloc.UnlockX64(ABI_PARAM1);
|
||||
|
||||
current.arm_pc += GetInstSize();
|
||||
}
|
||||
|
||||
static void ServiceCall(u64 imm) {
|
||||
SVC::CallSVC(imm & 0xFFFF);
|
||||
}
|
||||
|
||||
void JitX64::SVC(Cond cond, ArmImm24 imm24) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
// Flush and write out absolutely everything.
|
||||
code->MOV(32, MJitStateArmPC(), Imm32(current.arm_pc));
|
||||
reg_alloc.FlushEverything();
|
||||
|
||||
reg_alloc.LockX64(ABI_PARAM1);
|
||||
code->MOV(64, R(ABI_PARAM1), Imm32(imm24));
|
||||
CompileCallHost(reinterpret_cast<const void* const>(&ServiceCall));
|
||||
reg_alloc.UnlockX64(ABI_PARAM1);
|
||||
|
||||
// Some service calls require a task switch, so go back to the dispatcher to check.
|
||||
current.arm_pc += GetInstSize();
|
||||
code->ADD(32, MJitStateArmPC(), Imm32(GetInstSize()));
|
||||
CompileReturnToDispatch();
|
||||
|
||||
stop_compilation = true;
|
||||
}
|
||||
|
||||
void JitX64::UDF() {
|
||||
cond_manager.Always();
|
||||
|
||||
ASSERT_MSG(false, "UDF instruction @ pc=0x%08X", current.arm_pc);
|
||||
|
||||
current.arm_pc += GetInstSize();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -221,8 +221,8 @@ private:
|
||||
void TST_rsr(Cond cond, ArmReg Rn, ArmReg Rs, ShiftType shift, ArmReg Rm) override;
|
||||
|
||||
// Exception generation instructions
|
||||
void BKPT() override;
|
||||
void SVC() override;
|
||||
void BKPT(Cond cond, ArmImm12 imm12, ArmImm4 imm4) override;
|
||||
void SVC(Cond cond, ArmImm24 imm24) override;
|
||||
void UDF() override;
|
||||
|
||||
// Extension functions
|
||||
|
Loading…
Reference in New Issue
Block a user