JitX64: Implement exception-generating instructions

This commit is contained in:
MerryMage 2016-04-03 15:02:45 +01:00
parent 1f8217a09b
commit a5e3874db8
5 changed files with 66 additions and 11 deletions

View File

@ -190,8 +190,8 @@ static const std::array<Instruction, 221> arm_instruction_table = {{
{ "TST (rsr)", MakeMatcher<5>("cccc00010001nnnn0000ssss0rr1mmmm", &Visitor::TST_rsr) }, // all { "TST (rsr)", MakeMatcher<5>("cccc00010001nnnn0000ssss0rr1mmmm", &Visitor::TST_rsr) }, // all
// Exception Generating instructions // Exception Generating instructions
{ "BKPT", MakeMatcher<0>("----00010010------------0111----", &Visitor::BKPT) }, // ARMv5 { "BKPT", MakeMatcher<3>("cccc00010010vvvvvvvvvvvv0111vvvv", &Visitor::BKPT) }, // ARMv5
{ "SVC", MakeMatcher<0>("----1111------------------------", &Visitor::SVC) }, // all { "SVC", MakeMatcher<2>("cccc1111vvvvvvvvvvvvvvvvvvvvvvvv", &Visitor::SVC) }, // all
{ "UDF", MakeMatcher<0>("111001111111------------1111----", &Visitor::UDF) }, // all { "UDF", MakeMatcher<0>("111001111111------------1111----", &Visitor::UDF) }, // all
// Extension instructions // Extension instructions

View File

@ -133,8 +133,8 @@ public:
virtual void TST_rsr(Cond cond, Register Rn, Register Rs, ShiftType shift, Register Rm) = 0; virtual void TST_rsr(Cond cond, Register Rn, Register Rs, ShiftType shift, Register Rm) = 0;
// Exception generation instructions // Exception generation instructions
virtual void BKPT() = 0; virtual void BKPT(Cond cond, Imm12 imm12, Imm4 imm4) = 0;
virtual void SVC() = 0; virtual void SVC(Cond cond, Imm24 imm24) = 0;
virtual void UDF() = 0; virtual void UDF() = 0;
// Extension functions // Extension functions

View File

@ -395,7 +395,7 @@ static const std::array<Instruction, 27> thumb_instruction_table = { {
{ "BKPT", MakeMatcher("10111110xxxxxxxx", [](Visitor* v, u32 instruction) { { "BKPT", MakeMatcher("10111110xxxxxxxx", [](Visitor* v, u32 instruction) {
// BKPT #imm8 // BKPT #imm8
Imm8 imm8 = bits<0, 7>(instruction); Imm8 imm8 = bits<0, 7>(instruction);
v->BKPT(); v->BKPT(0xE, imm8 >> 4, imm8 & 0xF);
})}, })},
{ "STMIA/LDMIA", MakeMatcher("1100xxxxxxxxxxxx", [](Visitor* v, u32 instruction) { { "STMIA/LDMIA", MakeMatcher("1100xxxxxxxxxxxx", [](Visitor* v, u32 instruction) {
bool L = bits<11, 11>(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", MakeMatcher("11011111xxxxxxxx", [](Visitor* v, u32 instruction) {
// SWI #imm8 // SWI #imm8
Imm8 imm8 = bits<0, 7>(instruction); Imm8 imm8 = bits<0, 7>(instruction);
v->SVC(/*imm8*/); v->SVC(0xE, imm8);
})}, })},
{ "B", MakeMatcher("11100xxxxxxxxxxx", [](Visitor* v, u32 instruction) { { "B", MakeMatcher("11100xxxxxxxxxxx", [](Visitor* v, u32 instruction) {
// B <PC + #offset*2> // B <PC + #offset*2>

View File

@ -2,12 +2,67 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // 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/arm/jit_x64/jit_x64.h"
#include "core/hle/svc.h"
namespace JitX64 { namespace JitX64 {
void JitX64::BKPT() { CompileInterpretInstruction(); } using namespace Gen;
void JitX64::SVC() { CompileInterpretInstruction(); }
void JitX64::UDF() { CompileInterpretInstruction(); } 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();
}
} }

View File

@ -221,8 +221,8 @@ private:
void TST_rsr(Cond cond, ArmReg Rn, ArmReg Rs, ShiftType shift, ArmReg Rm) override; void TST_rsr(Cond cond, ArmReg Rn, ArmReg Rs, ShiftType shift, ArmReg Rm) override;
// Exception generation instructions // Exception generation instructions
void BKPT() override; void BKPT(Cond cond, ArmImm12 imm12, ArmImm4 imm4) override;
void SVC() override; void SVC(Cond cond, ArmImm24 imm24) override;
void UDF() override; void UDF() override;
// Extension functions // Extension functions