A64: Implement SVC
This commit is contained in:
parent
e5ace37560
commit
68391b0a05
9 changed files with 37 additions and 14 deletions
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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"),
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
Loading…
Reference in a new issue