A64: Implement branch (register)
This commit is contained in:
parent
86d1095df7
commit
23f3afe0b3
8 changed files with 54 additions and 8 deletions
|
@ -198,6 +198,20 @@ void A64EmitX64::EmitA64SetSP(A64EmitContext& ctx, IR::Inst* inst) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void A64EmitX64::EmitA64SetPC(A64EmitContext& ctx, IR::Inst* inst) {
|
||||||
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
|
auto addr = qword[r15 + offsetof(A64JitState, pc)];
|
||||||
|
if (args[0].FitsInImmediateU32()) {
|
||||||
|
code->mov(addr, args[0].GetImmediateU32());
|
||||||
|
} else if (args[0].IsInXmm()) {
|
||||||
|
Xbyak::Xmm to_store = ctx.reg_alloc.UseXmm(args[0]);
|
||||||
|
code->movq(addr, to_store);
|
||||||
|
} else {
|
||||||
|
Xbyak::Reg64 to_store = ctx.reg_alloc.UseGpr(args[0]);
|
||||||
|
code->mov(addr, to_store);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void A64EmitX64::EmitTerminalImpl(IR::Term::Interpret terminal, IR::LocationDescriptor) {
|
void A64EmitX64::EmitTerminalImpl(IR::Term::Interpret terminal, IR::LocationDescriptor) {
|
||||||
code->mov(code->ABI_PARAM1, A64::LocationDescriptor{terminal.next}.PC());
|
code->mov(code->ABI_PARAM1, A64::LocationDescriptor{terminal.next}.PC());
|
||||||
code->mov(code->ABI_PARAM2.cvt32(), 1);
|
code->mov(code->ABI_PARAM2.cvt32(), 1);
|
||||||
|
|
|
@ -53,6 +53,7 @@ public:
|
||||||
SCOPE_EXIT({ this->is_executing = false; });
|
SCOPE_EXIT({ this->is_executing = false; });
|
||||||
jit_state.halt_requested = false;
|
jit_state.halt_requested = false;
|
||||||
|
|
||||||
|
// TODO: Check code alignment
|
||||||
block_of_code.RunCode(&jit_state);
|
block_of_code.RunCode(&jit_state);
|
||||||
|
|
||||||
PerformRequestedCacheInvalidation();
|
PerformRequestedCacheInvalidation();
|
||||||
|
|
|
@ -102,15 +102,15 @@ std::vector<Matcher<V>> GetDecodeTable() {
|
||||||
//INST(&V::MRS, "MRS", "110101010011poooNNNNMMMMooottttt"),
|
//INST(&V::MRS, "MRS", "110101010011poooNNNNMMMMooottttt"),
|
||||||
|
|
||||||
// Unconditonal branch (Register)
|
// Unconditonal branch (Register)
|
||||||
//INST(&V::BR, "BR", "1101011000011111000000nnnnn00000"),
|
INST(&V::BLR, "BLR", "1101011000111111000000nnnnn00000"),
|
||||||
//INST(&V::BRA, "BRAA, BRAAZ, BRAB, BRABZ", "1101011Z0001111100001Mnnnnnmmmmm"),
|
INST(&V::BR, "BR", "1101011000011111000000nnnnn00000"),
|
||||||
//INST(&V::BLR, "BLR", "1101011000111111000000nnnnn00000"),
|
|
||||||
//INST(&V::BLRA, "BLRAA, BLRAAZ, BLRAB, BLRABZ", "1101011Z0011111100001Mnnnnnmmmmm"),
|
|
||||||
//INST(&V::RET, "RET", "1101011001011111000000nnnnn00000"),
|
|
||||||
//INST(&V::RETA, "RETAA, RETAB", "110101100101111100001M1111111111"),
|
|
||||||
//INST(&V::ERET, "ERET", "11010110100111110000001111100000"),
|
|
||||||
//INST(&V::ERETA, "ERETAA, ERETAB", "110101101001111100001M1111111111"),
|
|
||||||
//INST(&V::DRPS, "DRPS", "11010110101111110000001111100000"),
|
//INST(&V::DRPS, "DRPS", "11010110101111110000001111100000"),
|
||||||
|
//INST(&V::ERET, "ERET", "11010110100111110000001111100000"),
|
||||||
|
INST(&V::RET, "RET", "1101011001011111000000nnnnn00000"),
|
||||||
|
//INST(&V::BLRA, "BLRAA, BLRAAZ, BLRAB, BLRABZ", "1101011Z0011111100001Mnnnnnmmmmm"), // ARMv8.3
|
||||||
|
//INST(&V::BRA, "BRAA, BRAAZ, BRAB, BRABZ", "1101011Z0001111100001Mnnnnnmmmmm"), // ARMv8.3
|
||||||
|
//INST(&V::ERETA, "ERETAA, ERETAB", "110101101001111100001M1111111111"), // ARMv8.3
|
||||||
|
//INST(&V::RETA, "RETAA, RETAB", "110101100101111100001M1111111111"), // ARMv8.3
|
||||||
|
|
||||||
// Unconditonal branch (immediate)
|
// Unconditonal branch (immediate)
|
||||||
INST(&V::B_uncond, "B", "000101iiiiiiiiiiiiiiiiiiiiiiiiii"),
|
INST(&V::B_uncond, "B", "000101iiiiiiiiiiiiiiiiiiiiiiiiii"),
|
||||||
|
|
|
@ -62,5 +62,9 @@ void IREmitter::SetSP(const IR::U64& value) {
|
||||||
Inst(Opcode::A64SetSP, value);
|
Inst(Opcode::A64SetSP, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IREmitter::SetPC(const IR::U64& value) {
|
||||||
|
Inst(Opcode::A64SetPC, value);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace IR
|
} // namespace IR
|
||||||
} // namespace Dynarmic
|
} // namespace Dynarmic
|
||||||
|
|
|
@ -40,6 +40,7 @@ public:
|
||||||
void SetW(Reg dest_reg, const IR::U32& value);
|
void SetW(Reg dest_reg, const IR::U32& value);
|
||||||
void SetX(Reg dest_reg, const IR::U64& value);
|
void SetX(Reg dest_reg, const IR::U64& value);
|
||||||
void SetSP(const IR::U64& value);
|
void SetSP(const IR::U64& value);
|
||||||
|
void SetPC(const IR::U64& value);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace IR
|
} // namespace IR
|
||||||
|
|
|
@ -38,5 +38,29 @@ bool TranslatorVisitor::BL(Imm<26> imm26) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::BLR(Reg Rn) {
|
||||||
|
X(64, Reg::R30, ir.Imm64(ir.PC() + 4));
|
||||||
|
ir.PushRSB(ir.current_location.AdvancePC(4));
|
||||||
|
|
||||||
|
auto target = X(64, Rn);
|
||||||
|
ir.SetPC(target);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::BR(Reg Rn) {
|
||||||
|
auto target = X(64, Rn);
|
||||||
|
ir.SetPC(target);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::RET(Reg Rn) {
|
||||||
|
auto target = X(64, Rn);
|
||||||
|
ir.SetPC(target);
|
||||||
|
ir.SetTerm(IR::Term::PopRSBHint{});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace A64
|
} // namespace A64
|
||||||
} // namespace Dynarmic
|
} // namespace Dynarmic
|
||||||
|
|
|
@ -155,6 +155,7 @@ bool Inst::WritesToCoreRegister() const {
|
||||||
case Opcode::A64SetW:
|
case Opcode::A64SetW:
|
||||||
case Opcode::A64SetX:
|
case Opcode::A64SetX:
|
||||||
case Opcode::A64SetSP:
|
case Opcode::A64SetSP:
|
||||||
|
case Opcode::A64SetPC:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -43,6 +43,7 @@ A64OPC(GetSP, T::U64,
|
||||||
A64OPC(SetW, T::Void, T::A64Reg, T::U32 )
|
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 )
|
||||||
|
|
||||||
// Hints
|
// Hints
|
||||||
OPCODE(PushRSB, T::Void, T::U64 )
|
OPCODE(PushRSB, T::Void, T::U64 )
|
||||||
|
|
Loading…
Reference in a new issue