summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/arm/insts/misc.cc12
-rw-r--r--src/arch/arm/insts/misc.hh19
-rw-r--r--src/arch/arm/isa/formats/misc.isa13
-rw-r--r--src/arch/arm/isa/insts/misc.isa100
-rw-r--r--src/arch/arm/isa/templates/misc.isa83
5 files changed, 220 insertions, 7 deletions
diff --git a/src/arch/arm/insts/misc.cc b/src/arch/arm/insts/misc.cc
index ec1b9358c..ba97eff09 100644
--- a/src/arch/arm/insts/misc.cc
+++ b/src/arch/arm/insts/misc.cc
@@ -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
*
@@ -322,6 +322,16 @@ RegImmRegShiftOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
}
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
{
return csprintf("%-10s (inst %#08x)", "unknown", machInst);
diff --git a/src/arch/arm/insts/misc.hh b/src/arch/arm/insts/misc.hh
index c2dcaa847..72d1694c9 100644
--- a/src/arch/arm/insts/misc.hh
+++ b/src/arch/arm/insts/misc.hh
@@ -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:
diff --git a/src/arch/arm/isa/formats/misc.isa b/src/arch/arm/isa/formats/misc.isa
index 26681e40f..4f834b8e1 100644
--- a/src/arch/arm/isa/formats/misc.isa
+++ b/src/arch/arm/isa/formats/misc.isa
@@ -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",
diff --git a/src/arch/arm/isa/insts/misc.isa b/src/arch/arm/isa/insts/misc.isa
index 80ad6cdf4..ef0a6709e 100644
--- a/src/arch/arm/isa/insts/misc.isa
+++ b/src/arch/arm/isa/insts/misc.isa
@@ -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,
diff --git a/src/arch/arm/isa/templates/misc.isa b/src/arch/arm/isa/templates/misc.isa
index 0a23ba5d3..639ff3aca 100644
--- a/src/arch/arm/isa/templates/misc.isa
+++ b/src/arch/arm/isa/templates/misc.isa
@@ -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;
+ }
+}};