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.
|
/// emitted code.
|
||||||
const std::uint64_t* tpidrro_el0 = nullptr;
|
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.
|
/// 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 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.
|
/// 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);
|
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) {
|
void A64EmitX64::EmitA64GetTPIDRRO(A64EmitContext& ctx, IR::Inst* inst) {
|
||||||
Xbyak::Reg64 result = ctx.reg_alloc.ScratchGpr();
|
Xbyak::Reg64 result = ctx.reg_alloc.ScratchGpr();
|
||||||
if (conf.tpidrro_el0) {
|
if (conf.tpidrro_el0) {
|
||||||
|
|
|
@ -65,6 +65,14 @@ IR::U32 IREmitter::GetDCZID() {
|
||||||
return Inst<IR::U32>(Opcode::A64GetDCZID);
|
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() {
|
IR::U64 IREmitter::GetTPIDRRO() {
|
||||||
return Inst<IR::U64>(Opcode::A64GetTPIDRRO);
|
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::U64 GetCNTPCT(); // TODO: Ensure sub-basic-block cycle counts are updated before this.
|
||||||
IR::U32 GetCTR();
|
IR::U32 GetCTR();
|
||||||
IR::U32 GetDCZID();
|
IR::U32 GetDCZID();
|
||||||
|
IR::U64 GetTPIDR();
|
||||||
|
void SetTPIDR(const IR::U64& value);
|
||||||
IR::U64 GetTPIDRRO();
|
IR::U64 GetTPIDRRO();
|
||||||
|
|
||||||
void ClearExclusive();
|
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) {
|
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>();
|
const size_t sys_reg = concatenate(Imm<1>{1}, o0, op1, CRn, CRm, op2).ZeroExtend<size_t>();
|
||||||
switch (sys_reg) {
|
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
|
case 0b11'011'0100'0100'000: // FPCR
|
||||||
ir.SetFPCR(X(32, Rt));
|
ir.SetFPCR(X(32, Rt));
|
||||||
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
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) {
|
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>();
|
const size_t sys_reg = concatenate(Imm<1>{1}, o0, op1, CRn, CRm, op2).ZeroExtend<size_t>();
|
||||||
switch (sys_reg) {
|
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
|
case 0b11'011'1101'0000'011: // TPIDRRO_EL0
|
||||||
X(64, Rt, ir.GetTPIDRRO());
|
X(64, Rt, ir.GetTPIDRRO());
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -68,6 +68,8 @@ A64OPC(DataMemoryBarrier, T::Void,
|
||||||
A64OPC(GetCNTPCT, T::U64, )
|
A64OPC(GetCNTPCT, T::U64, )
|
||||||
A64OPC(GetCTR, T::U32, )
|
A64OPC(GetCTR, T::U32, )
|
||||||
A64OPC(GetDCZID, T::U32, )
|
A64OPC(GetDCZID, T::U32, )
|
||||||
|
A64OPC(GetTPIDR, T::U64, )
|
||||||
|
A64OPC(SetTPIDR, T::Void, T::U64 )
|
||||||
A64OPC(GetTPIDRRO, T::U64, )
|
A64OPC(GetTPIDRRO, T::U64, )
|
||||||
|
|
||||||
// Hints
|
// Hints
|
||||||
|
|
Loading…
Add table
Reference in a new issue