A64: Implement system register TPIDR_EL0
This commit is contained in:
parent
e3da92024e
commit
e4697b1676
6 changed files with 43 additions and 0 deletions
|
@ -120,6 +120,10 @@ struct UserConfig {
|
|||
/// emitted code.
|
||||
const std::uint64_t* tpidrro_el0 = nullptr;
|
||||
|
||||
/// Pointer to where TPIDR_EL0 is stored. This pointer will be inserted into
|
||||
/// emitted code.
|
||||
const std::uint64_t* tpidr_el0 = nullptr;
|
||||
|
||||
/// Pointer to the page table which we can use for direct page table access.
|
||||
/// If an entry in page_table is null, the relevant memory callback will be called.
|
||||
/// If page_table is nullptr, all memory accesses hit the memory callbacks.
|
||||
|
|
|
@ -530,6 +530,27 @@ void A64EmitX64::EmitA64GetDCZID(A64EmitContext& ctx, IR::Inst* inst) {
|
|||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
||||
void A64EmitX64::EmitA64GetTPIDR(A64EmitContext& ctx, IR::Inst* inst) {
|
||||
Xbyak::Reg64 result = ctx.reg_alloc.ScratchGpr();
|
||||
if (conf.tpidr_el0) {
|
||||
code.mov(result, u64(conf.tpidr_el0));
|
||||
code.mov(result, qword[result]);
|
||||
} else {
|
||||
code.xor_(result.cvt32(), result.cvt32());
|
||||
}
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
||||
void A64EmitX64::EmitA64SetTPIDR(A64EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
Xbyak::Reg64 value = ctx.reg_alloc.UseGpr(args[0]);
|
||||
Xbyak::Reg64 addr = ctx.reg_alloc.ScratchGpr();
|
||||
if (conf.tpidr_el0) {
|
||||
code.mov(addr, u64(conf.tpidr_el0));
|
||||
code.mov(qword[addr], value);
|
||||
}
|
||||
}
|
||||
|
||||
void A64EmitX64::EmitA64GetTPIDRRO(A64EmitContext& ctx, IR::Inst* inst) {
|
||||
Xbyak::Reg64 result = ctx.reg_alloc.ScratchGpr();
|
||||
if (conf.tpidrro_el0) {
|
||||
|
|
|
@ -65,6 +65,14 @@ IR::U32 IREmitter::GetDCZID() {
|
|||
return Inst<IR::U32>(Opcode::A64GetDCZID);
|
||||
}
|
||||
|
||||
IR::U64 IREmitter::GetTPIDR() {
|
||||
return Inst<IR::U64>(Opcode::A64GetTPIDR);
|
||||
}
|
||||
|
||||
void IREmitter::SetTPIDR(const IR::U64& value) {
|
||||
Inst(Opcode::A64SetTPIDR, value);
|
||||
}
|
||||
|
||||
IR::U64 IREmitter::GetTPIDRRO() {
|
||||
return Inst<IR::U64>(Opcode::A64GetTPIDRRO);
|
||||
}
|
||||
|
|
|
@ -47,6 +47,8 @@ public:
|
|||
IR::U64 GetCNTPCT(); // TODO: Ensure sub-basic-block cycle counts are updated before this.
|
||||
IR::U32 GetCTR();
|
||||
IR::U32 GetDCZID();
|
||||
IR::U64 GetTPIDR();
|
||||
void SetTPIDR(const IR::U64& value);
|
||||
IR::U64 GetTPIDRRO();
|
||||
|
||||
void ClearExclusive();
|
||||
|
|
|
@ -54,6 +54,9 @@ bool TranslatorVisitor::DMB(Imm<4> /*CRm*/) {
|
|||
bool TranslatorVisitor::MSR_reg(Imm<1> o0, Imm<3> op1, Imm<4> CRn, Imm<4> CRm, Imm<3> op2, Reg Rt) {
|
||||
const size_t sys_reg = concatenate(Imm<1>{1}, o0, op1, CRn, CRm, op2).ZeroExtend<size_t>();
|
||||
switch (sys_reg) {
|
||||
case 0b11'011'1101'0000'010: // TPIDR_EL0
|
||||
ir.SetTPIDR(X(64, Rt));
|
||||
return true;
|
||||
case 0b11'011'0100'0100'000: // FPCR
|
||||
ir.SetFPCR(X(32, Rt));
|
||||
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||
|
@ -68,6 +71,9 @@ bool TranslatorVisitor::MSR_reg(Imm<1> o0, Imm<3> op1, Imm<4> CRn, Imm<4> CRm, I
|
|||
bool TranslatorVisitor::MRS(Imm<1> o0, Imm<3> op1, Imm<4> CRn, Imm<4> CRm, Imm<3> op2, Reg Rt) {
|
||||
const size_t sys_reg = concatenate(Imm<1>{1}, o0, op1, CRn, CRm, op2).ZeroExtend<size_t>();
|
||||
switch (sys_reg) {
|
||||
case 0b11'011'1101'0000'010: // TPIDR_EL0
|
||||
X(64, Rt, ir.GetTPIDR());
|
||||
return true;
|
||||
case 0b11'011'1101'0000'011: // TPIDRRO_EL0
|
||||
X(64, Rt, ir.GetTPIDRRO());
|
||||
return true;
|
||||
|
|
|
@ -68,6 +68,8 @@ A64OPC(DataMemoryBarrier, T::Void,
|
|||
A64OPC(GetCNTPCT, T::U64, )
|
||||
A64OPC(GetCTR, T::U32, )
|
||||
A64OPC(GetDCZID, T::U32, )
|
||||
A64OPC(GetTPIDR, T::U64, )
|
||||
A64OPC(SetTPIDR, T::Void, T::U64 )
|
||||
A64OPC(GetTPIDRRO, T::U64, )
|
||||
|
||||
// Hints
|
||||
|
|
Loading…
Reference in a new issue