arm: Add support for the mcr dc{ic,i,c}mvac, dccmvau instructions
This patch adds support for the ARMv7 cache maintenance intructions: * mcr dccmvac cleans a VA to the PoC * mcr dcimvac invalidates a VA to the PoC * mcr dccimvac cleans and invalidates a VA to the PoC * mcr dccmvau cleans a VA to the PoU Change-Id: I6511f203039ca145cc9128ddf61d09d6d7e40c10 Reviewed-by: Stephan Diestelhorst <stephan.diestelhorst@arm.com> Reviewed-by: Anouk Van Laer <anouk.vanlaer@arm.com> Reviewed-on: https://gem5-review.googlesource.com/5059 Maintainer: Andreas Sandberg <andreas.sandberg@arm.com> Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2012-2013 ARM Limited
|
||||
* Copyright (c) 2010, 2012-2013, 2017 ARM Limited
|
||||
* Copyright (c) 2013 Advanced Micro Devices, Inc.
|
||||
* All rights reserved
|
||||
*
|
||||
@@ -321,6 +321,16 @@ RegImmRegShiftOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
MiscRegRegImmMemOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss);
|
||||
printIntReg(ss, op1);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
UnknownOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2012-2013 ARM Limited
|
||||
* Copyright (c) 2010, 2012-2013, 2017 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -344,6 +344,23 @@ class RegImmRegShiftOp : public PredOp
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
class MiscRegRegImmMemOp : public PredOp
|
||||
{
|
||||
protected:
|
||||
MiscRegIndex dest;
|
||||
IntRegIndex op1;
|
||||
uint64_t imm;
|
||||
|
||||
MiscRegRegImmMemOp(const char *mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, MiscRegIndex _dest, IntRegIndex _op1,
|
||||
uint64_t _imm) :
|
||||
PredOp(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), imm(_imm)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
class UnknownOp : public PredOp
|
||||
{
|
||||
protected:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// -*- mode:c++ -*-
|
||||
|
||||
// Copyright (c) 2010-2013,2016 ARM Limited
|
||||
// Copyright (c) 2010-2013,2016-2017 ARM Limited
|
||||
// All rights reserved
|
||||
//
|
||||
// The license below extends only to copyright in the software and shall
|
||||
@@ -219,15 +219,20 @@ let {{
|
||||
machInst,
|
||||
csprintf("miscreg crn:%d opc1:%d crm:%d opc2:%d %s unknown",
|
||||
crn, opc1, crm, opc2, isRead ? "read" : "write"));
|
||||
case MISCREG_DCCMVAC:
|
||||
return new McrMrcMiscInst(isRead ? "mrc dccmvac" : "mcr dccmvac",
|
||||
machInst, iss, MISCREG_DCCMVAC);
|
||||
case MISCREG_CP15ISB:
|
||||
return new Isb(machInst, iss);
|
||||
case MISCREG_CP15DSB:
|
||||
return new Dsb(machInst, iss);
|
||||
case MISCREG_CP15DMB:
|
||||
return new Dmb(machInst, iss);
|
||||
case MISCREG_DCIMVAC:
|
||||
return new McrDcimvac(machInst, miscReg, rt, iss);
|
||||
case MISCREG_DCCMVAC:
|
||||
return new McrDccmvac(machInst, miscReg, rt, iss);
|
||||
case MISCREG_DCCMVAU:
|
||||
return new McrDccmvau(machInst, miscReg, rt, iss);
|
||||
case MISCREG_DCCIMVAC:
|
||||
return new McrDccimvac(machInst, miscReg, rt, iss);
|
||||
default:
|
||||
if (miscRegInfo[miscReg][MISCREG_WARN_NOT_FAIL]) {
|
||||
std::string full_mnem = csprintf("%s %s",
|
||||
|
||||
@@ -1063,6 +1063,106 @@ let {{
|
||||
decoder_output += BasicConstructor.subst(clrexIop)
|
||||
exec_output += PredOpExecute.subst(clrexIop)
|
||||
|
||||
McrDcCheckCode = '''
|
||||
int preFlatDest = flattenMiscRegNsBanked(dest, xc->tcBase());
|
||||
MiscRegIndex miscReg = (MiscRegIndex) xc->tcBase()->flattenRegId(
|
||||
RegId(MiscRegClass, preFlatDest)).index();
|
||||
bool hypTrap = mcrMrc15TrapToHyp(miscReg, Hcr, Cpsr, Scr, Hdcr, Hstr,
|
||||
Hcptr, imm);
|
||||
bool can_write, undefined;
|
||||
std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr);
|
||||
|
||||
// if we're in non secure PL1 mode then we can trap regardless
|
||||
// of whether the register is accessible, in other modes we
|
||||
// trap if only if the register IS accessible.
|
||||
if (undefined || (!can_write & !(hypTrap & !inUserMode(Cpsr) &
|
||||
!inSecureState(Scr, Cpsr)))) {
|
||||
return std::make_shared<UndefinedInstruction>(machInst, false,
|
||||
mnemonic);
|
||||
}
|
||||
if (hypTrap) {
|
||||
return std::make_shared<HypervisorTrap>(machInst, imm,
|
||||
EC_TRAPPED_CP15_MCR_MRC);
|
||||
}
|
||||
'''
|
||||
|
||||
McrDcimvacCode = '''
|
||||
const Request::Flags memAccessFlags(ArmISA::TLB::MustBeOne |
|
||||
Request::INVALIDATE |
|
||||
Request::DST_POC);
|
||||
EA = Op1;
|
||||
'''
|
||||
McrDcimvacIop = InstObjParams("mcr dcimvac", "McrDcimvac",
|
||||
"MiscRegRegImmMemOp",
|
||||
{"memacc_code": McrDcCheckCode,
|
||||
"postacc_code": "",
|
||||
"ea_code": McrDcimvacCode,
|
||||
"predicate_test": predicateTest},
|
||||
['IsMemRef', 'IsStore'])
|
||||
header_output += MiscRegRegImmMemOpDeclare.subst(McrDcimvacIop)
|
||||
decoder_output += MiscRegRegImmOpConstructor.subst(McrDcimvacIop)
|
||||
exec_output += Mcr15Execute.subst(McrDcimvacIop) + \
|
||||
Mcr15InitiateAcc.subst(McrDcimvacIop) + \
|
||||
Mcr15CompleteAcc.subst(McrDcimvacIop)
|
||||
|
||||
McrDccmvacCode = '''
|
||||
const Request::Flags memAccessFlags(ArmISA::TLB::MustBeOne |
|
||||
Request::CLEAN |
|
||||
Request::DST_POC);
|
||||
EA = Op1;
|
||||
'''
|
||||
McrDccmvacIop = InstObjParams("mcr dccmvac", "McrDccmvac",
|
||||
"MiscRegRegImmMemOp",
|
||||
{"memacc_code": McrDcCheckCode,
|
||||
"postacc_code": "",
|
||||
"ea_code": McrDccmvacCode,
|
||||
"predicate_test": predicateTest},
|
||||
['IsMemRef', 'IsStore'])
|
||||
header_output += MiscRegRegImmMemOpDeclare.subst(McrDccmvacIop)
|
||||
decoder_output += MiscRegRegImmOpConstructor.subst(McrDccmvacIop)
|
||||
exec_output += Mcr15Execute.subst(McrDccmvacIop) + \
|
||||
Mcr15InitiateAcc.subst(McrDccmvacIop) + \
|
||||
Mcr15CompleteAcc.subst(McrDccmvacIop)
|
||||
|
||||
McrDccmvauCode = '''
|
||||
const Request::Flags memAccessFlags(ArmISA::TLB::MustBeOne |
|
||||
Request::CLEAN |
|
||||
Request::DST_POU);
|
||||
EA = Op1;
|
||||
'''
|
||||
McrDccmvauIop = InstObjParams("mcr dccmvau", "McrDccmvau",
|
||||
"MiscRegRegImmMemOp",
|
||||
{"memacc_code": McrDcCheckCode,
|
||||
"postacc_code": "",
|
||||
"ea_code": McrDccmvauCode,
|
||||
"predicate_test": predicateTest},
|
||||
['IsMemRef', 'IsStore'])
|
||||
header_output += MiscRegRegImmMemOpDeclare.subst(McrDccmvauIop)
|
||||
decoder_output += MiscRegRegImmOpConstructor.subst(McrDccmvauIop)
|
||||
exec_output += Mcr15Execute.subst(McrDccmvauIop) + \
|
||||
Mcr15InitiateAcc.subst(McrDccmvauIop) + \
|
||||
Mcr15CompleteAcc.subst(McrDccmvauIop)
|
||||
|
||||
McrDccimvacCode = '''
|
||||
const Request::Flags memAccessFlags(ArmISA::TLB::MustBeOne |
|
||||
Request::CLEAN |
|
||||
Request::INVALIDATE |
|
||||
Request::DST_POC);
|
||||
EA = Op1;
|
||||
'''
|
||||
McrDccimvacIop = InstObjParams("mcr dccimvac", "McrDccimvac",
|
||||
"MiscRegRegImmMemOp",
|
||||
{"memacc_code": McrDcCheckCode,
|
||||
"postacc_code": "",
|
||||
"ea_code": McrDccimvacCode,
|
||||
"predicate_test": predicateTest},
|
||||
['IsMemRef', 'IsStore'])
|
||||
header_output += MiscRegRegImmMemOpDeclare.subst(McrDccimvacIop)
|
||||
decoder_output += MiscRegRegImmOpConstructor.subst(McrDccimvacIop)
|
||||
exec_output += Mcr15Execute.subst(McrDccimvacIop) + \
|
||||
Mcr15InitiateAcc.subst(McrDccimvacIop) + \
|
||||
Mcr15CompleteAcc.subst(McrDccimvacIop)
|
||||
|
||||
isbCode = '''
|
||||
// If the barrier is due to a CP15 access check for hyp traps
|
||||
if ((imm != 0) && mcrMrc15TrapToHyp(MISCREG_CP15ISB, Hcr, Cpsr, Scr,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// -*- mode:c++ -*-
|
||||
|
||||
// Copyright (c) 2010-2013 ARM Limited
|
||||
// Copyright (c) 2010-2013,2017 ARM Limited
|
||||
// All rights reserved
|
||||
//
|
||||
// The license below extends only to copyright in the software and shall
|
||||
@@ -614,3 +614,84 @@ def template RegImmRegShiftOpConstructor {{
|
||||
}
|
||||
}};
|
||||
|
||||
def template MiscRegRegImmMemOpDeclare {{
|
||||
class %(class_name)s : public %(base_class)s
|
||||
{
|
||||
protected:
|
||||
public:
|
||||
// Constructor
|
||||
%(class_name)s(ExtMachInst machInst,
|
||||
MiscRegIndex _dest, IntRegIndex _op1,
|
||||
uint64_t _imm);
|
||||
Fault execute(ExecContext *, Trace::InstRecord *) const;
|
||||
Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
|
||||
Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const;
|
||||
};
|
||||
}};
|
||||
|
||||
def template Mcr15Execute {{
|
||||
Fault %(class_name)s::execute(ExecContext *xc,
|
||||
Trace::InstRecord *traceData) const
|
||||
{
|
||||
Addr EA;
|
||||
Fault fault = NoFault;
|
||||
|
||||
%(op_decl)s;
|
||||
%(op_rd)s;
|
||||
%(ea_code)s;
|
||||
|
||||
if (%(predicate_test)s) {
|
||||
if (fault == NoFault) {
|
||||
%(memacc_code)s;
|
||||
}
|
||||
|
||||
if (fault == NoFault) {
|
||||
Addr size = 64;
|
||||
EA &= ~(size - 1);
|
||||
fault = xc->writeMem(NULL, size, EA, memAccessFlags, NULL);
|
||||
}
|
||||
} else {
|
||||
xc->setPredicate(false);
|
||||
}
|
||||
|
||||
return fault;
|
||||
}
|
||||
}};
|
||||
|
||||
def template Mcr15InitiateAcc {{
|
||||
Fault %(class_name)s::initiateAcc(ExecContext *xc,
|
||||
Trace::InstRecord *traceData) const
|
||||
{
|
||||
Addr EA;
|
||||
Fault fault = NoFault;
|
||||
|
||||
%(op_decl)s;
|
||||
%(op_rd)s;
|
||||
%(ea_code)s;
|
||||
|
||||
if (%(predicate_test)s) {
|
||||
if (fault == NoFault) {
|
||||
%(memacc_code)s;
|
||||
}
|
||||
|
||||
if (fault == NoFault) {
|
||||
Addr size = 64;
|
||||
EA &= ~(size - 1);
|
||||
fault = xc->writeMem(NULL, size, EA, memAccessFlags, NULL);
|
||||
}
|
||||
} else {
|
||||
xc->setPredicate(false);
|
||||
}
|
||||
|
||||
return fault;
|
||||
}
|
||||
}};
|
||||
|
||||
def template Mcr15CompleteAcc {{
|
||||
Fault %(class_name)s::completeAcc(PacketPtr pkt,
|
||||
ExecContext *xc,
|
||||
Trace::InstRecord *traceData) const
|
||||
{
|
||||
return NoFault;
|
||||
}
|
||||
}};
|
||||
|
||||
Reference in New Issue
Block a user