A64: Implement system register TPIDR_EL0

This commit is contained in:
MerryMage 2018-02-20 17:56:20 +00:00
parent e3da92024e
commit e4697b1676
6 changed files with 43 additions and 0 deletions

View file

@ -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.

View file

@ -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) {

View file

@ -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);
}

View file

@ -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();

View file

@ -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;

View file

@ -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