A64: Implement SVC

This commit is contained in:
MerryMage 2018-01-08 22:03:03 +00:00
parent e5ace37560
commit 68391b0a05
9 changed files with 37 additions and 14 deletions

View file

@ -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

View file

@ -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) {
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) {

View file

@ -62,7 +62,7 @@ std::vector<Matcher<V>> 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"),

View file

@ -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);

View file

@ -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();

View file

@ -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:

View file

@ -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;
}

View file

@ -220,7 +220,8 @@ bool Inst::WritesToFPSCR() const {
bool Inst::CausesCPUException() const {
return op == Opcode::Breakpoint ||
op == Opcode::A32CallSupervisor;
op == Opcode::A32CallSupervisor ||
op == Opcode::A64CallSupervisor;
}
bool Inst::AltersExclusiveState() const {

View file

@ -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 )