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_addsub.cpp
frontend/A64/translate/impl/data_processing_logical.cpp frontend/A64/translate/impl/data_processing_logical.cpp
frontend/A64/translate/impl/data_processing_pcrel.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.cpp
frontend/A64/translate/impl/impl.h frontend/A64/translate/impl/impl.h
frontend/A64/translate/translate.cpp 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) { void A64EmitX64::EmitTerminalImpl(IR::Term::Interpret terminal, IR::LocationDescriptor) {
//code->mov(qword[r15 + offsetof(A64JitState, pc)], code->ABI_PARAM1.cvt32());
code->SwitchMxcsrOnExit(); code->SwitchMxcsrOnExit();
Devirtualize<&A64::UserCallbacks::InterpreterFallback>(conf.callbacks).EmitCall(code, [&](Xbyak::Reg64 param1, Xbyak::Reg64 param2){ Devirtualize<&A64::UserCallbacks::InterpreterFallback>(conf.callbacks).EmitCall(code, [&](Xbyak::Reg64 param1, Xbyak::Reg64 param2) {
code->mov(param1, A64::LocationDescriptor{terminal.next}.PC()); code->mov(param1, A64::LocationDescriptor{terminal.next}.PC());
code->mov(qword[r15 + offsetof(A64JitState, pc)], param1);
code->mov(param2.cvt32(), 1); code->mov(param2.cvt32(), 1);
}); });
code->ReturnFromRunCode(true); // TODO: Check cycles code->ReturnFromRunCode(true); // TODO: Check cycles
@ -249,8 +258,9 @@ void A64EmitX64::EmitTerminalImpl(IR::Term::LinkBlock terminal, IR::LocationDesc
code->SwitchToFarCode(); code->SwitchToFarCode();
code->align(16); code->align(16);
code->L(dest); code->L(dest);
code->mov(qword[r15 + offsetof(A64JitState, pc)], A64::LocationDescriptor{terminal.next}.PC()); code->mov(rax, A64::LocationDescriptor{terminal.next}.PC());
PushRSBHelper(rax, rbx, terminal.next); code->mov(qword[r15 + offsetof(A64JitState, pc)], rax);
// PushRSBHelper(rax, rbx, terminal.next);
code->ForceReturnFromRunCode(); code->ForceReturnFromRunCode();
code->SwitchToNearCode(); code->SwitchToNearCode();
} }
@ -264,8 +274,8 @@ void A64EmitX64::EmitTerminalImpl(IR::Term::LinkBlockFast terminal, IR::Location
} }
} }
void A64EmitX64::EmitTerminalImpl(IR::Term::PopRSBHint, IR::LocationDescriptor) { void A64EmitX64::EmitTerminalImpl(IR::Term::PopRSBHint, IR::LocationDescriptor initial_location) {
ASSERT(false); EmitTerminalImpl(IR::Term::ReturnToDispatch{}, initial_location);
} }
void A64EmitX64::EmitTerminalImpl(IR::Term::If terminal, IR::LocationDescriptor 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) { if (target_code_ptr) {
code->jg(target_code_ptr); code->jg(target_code_ptr);
} else { } 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->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) { 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) { if (target_code_ptr) {
code->jmp(target_code_ptr); code->jmp(target_code_ptr);
} else { } 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->jmp(code->GetReturnFromRunCodeAddress());
} }
code->EnsurePatchLocationSize(patch_location, 16); code->EnsurePatchLocationSize(patch_location, 30); // TODO: Reduce size
} }
void A64EmitX64::EmitPatchMovRcx(CodePtr target_code_ptr) { 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"), INST(&V::B_cond, "B.cond", "01010100iiiiiiiiiiiiiiiiiii0cccc"),
// Exception generation // Exception generation
//INST(&V::SVC, "SVC", "11010100000iiiiiiiiiiiiiiii00001"), INST(&V::SVC, "SVC", "11010100000iiiiiiiiiiiiiiii00001"),
//INST(&V::HVC, "HVC", "11010100000iiiiiiiiiiiiiiii00010"), //INST(&V::HVC, "HVC", "11010100000iiiiiiiiiiiiiiii00010"),
//INST(&V::SMC, "SMC", "11010100000iiiiiiiiiiiiiiii00011"), //INST(&V::SMC, "SMC", "11010100000iiiiiiiiiiiiiiii00011"),
//INST(&V::BRK, "BRK", "11010100001iiiiiiiiiiiiiiii00000"), //INST(&V::BRK, "BRK", "11010100001iiiiiiiiiiiiiiii00000"),

View file

@ -34,6 +34,10 @@ void IREmitter::SetNZCV(const IR::NZCV& nzcv) {
Inst(Opcode::A64SetNZCV, nzcv); Inst(Opcode::A64SetNZCV, nzcv);
} }
void IREmitter::CallSupervisor(u32 imm) {
Inst(Opcode::A64CallSupervisor, Imm32(imm));
}
IR::U32 IREmitter::GetW(Reg reg) { IR::U32 IREmitter::GetW(Reg reg) {
if (reg == Reg::ZR) if (reg == Reg::ZR)
return Imm32(0); return Imm32(0);

View file

@ -35,6 +35,8 @@ public:
IR::U1 GetCFlag(); IR::U1 GetCFlag();
void SetNZCV(const IR::NZCV& nzcv); void SetNZCV(const IR::NZCV& nzcv);
void CallSupervisor(u32 imm);
IR::U32 GetW(Reg source_reg); IR::U32 GetW(Reg source_reg);
IR::U64 GetX(Reg source_reg); IR::U64 GetX(Reg source_reg);
IR::U64 GetSP(); IR::U64 GetSP();

View file

@ -166,6 +166,8 @@ std::string DumpBlock(const IR::Block& block) {
return fmt::format("#{}", arg.GetU8()); return fmt::format("#{}", arg.GetU8());
case Type::U32: case Type::U32:
return fmt::format("#{:#x}", arg.GetU32()); return fmt::format("#{:#x}", arg.GetU32());
case Type::U64:
return fmt::format("#{:#x}", arg.GetU64());
case Type::A32Reg: case Type::A32Reg:
return A32::RegToString(arg.GetA32RegRef()); return A32::RegToString(arg.GetA32RegRef());
case Type::A32ExtReg: case Type::A32ExtReg:

View file

@ -13,7 +13,7 @@ namespace Dynarmic {
namespace IR { namespace IR {
std::ostream& operator<<(std::ostream& o, const LocationDescriptor& descriptor) { std::ostream& operator<<(std::ostream& o, const LocationDescriptor& descriptor) {
o << fmt::format("{{{{}}}}", descriptor.Value()); o << fmt::format("{{{:016x}}}", descriptor.Value());
return o; return o;
} }

View file

@ -219,8 +219,9 @@ bool Inst::WritesToFPSCR() const {
} }
bool Inst::CausesCPUException() const { bool Inst::CausesCPUException() const {
return op == Opcode::Breakpoint || return op == Opcode::Breakpoint ||
op == Opcode::A32CallSupervisor; op == Opcode::A32CallSupervisor ||
op == Opcode::A64CallSupervisor;
} }
bool Inst::AltersExclusiveState() const { 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(SetX, T::Void, T::A64Reg, T::U64 )
A64OPC(SetSP, T::Void, T::U64 ) A64OPC(SetSP, T::Void, T::U64 )
A64OPC(SetPC, T::Void, T::U64 ) A64OPC(SetPC, T::Void, T::U64 )
A64OPC(CallSupervisor, T::Void, T::U32 )
// Hints // Hints
OPCODE(PushRSB, T::Void, T::U64 ) OPCODE(PushRSB, T::Void, T::U64 )