summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/arm/insts/pseudo.cc40
-rw-r--r--src/arch/arm/insts/pseudo.hh21
-rw-r--r--src/arch/arm/isa/formats/misc.isa7
-rw-r--r--src/arch/arm/miscregs.cc21
-rw-r--r--src/arch/arm/miscregs.hh10
5 files changed, 88 insertions, 11 deletions
diff --git a/src/arch/arm/insts/pseudo.cc b/src/arch/arm/insts/pseudo.cc
index 40e00accf..e2504d61e 100644
--- a/src/arch/arm/insts/pseudo.cc
+++ b/src/arch/arm/insts/pseudo.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014,2016-2017 ARM Limited
+ * Copyright (c) 2014,2016-2018 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -181,10 +181,8 @@ WarnUnimplemented::generateDisassembly(Addr pc, const SymbolTable *symtab) const
fullMnemonic.size() ? fullMnemonic.c_str() : mnemonic);
}
-
-
McrMrcMiscInst::McrMrcMiscInst(const char *_mnemonic, ExtMachInst _machInst,
- uint64_t _iss, MiscRegIndex _miscReg)
+ uint64_t _iss, MiscRegIndex _miscReg)
: ArmStaticInst(_mnemonic, _machInst, No_OpClass)
{
flags[IsNonSpeculative] = true;
@@ -217,3 +215,37 @@ McrMrcMiscInst::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
return csprintf("%-10s (pipe flush)", mnemonic);
}
+
+McrMrcImplDefined::McrMrcImplDefined(const char *_mnemonic,
+ ExtMachInst _machInst, uint64_t _iss,
+ MiscRegIndex _miscReg)
+ : McrMrcMiscInst(_mnemonic, _machInst, _iss, _miscReg)
+{}
+
+Fault
+McrMrcImplDefined::execute(ExecContext *xc, Trace::InstRecord *traceData) const
+{
+ uint32_t cpsr = xc->readMiscReg(MISCREG_CPSR);
+ uint32_t hcr = xc->readMiscReg(MISCREG_HCR);
+ uint32_t scr = xc->readMiscReg(MISCREG_SCR);
+ uint32_t hdcr = xc->readMiscReg(MISCREG_HDCR);
+ uint32_t hstr = xc->readMiscReg(MISCREG_HSTR);
+ uint32_t hcptr = xc->readMiscReg(MISCREG_HCPTR);
+
+ bool hypTrap = mcrMrc15TrapToHyp(miscReg, hcr, cpsr, scr, hdcr, hstr,
+ hcptr, iss);
+ if (hypTrap) {
+ return std::make_shared<HypervisorTrap>(machInst, iss,
+ EC_TRAPPED_CP15_MCR_MRC);
+ } else {
+ return std::make_shared<UndefinedInstruction>(machInst, false,
+ mnemonic);
+ }
+}
+
+std::string
+McrMrcImplDefined::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+{
+ return csprintf("%-10s (implementation defined)", mnemonic);
+}
diff --git a/src/arch/arm/insts/pseudo.hh b/src/arch/arm/insts/pseudo.hh
index fe28789f0..5fb7499df 100644
--- a/src/arch/arm/insts/pseudo.hh
+++ b/src/arch/arm/insts/pseudo.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014,2016 ARM Limited
+ * Copyright (c) 2014,2016,2018 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -123,7 +123,7 @@ class WarnUnimplemented : public ArmStaticInst
*/
class McrMrcMiscInst : public ArmStaticInst
{
- private:
+ protected:
uint64_t iss;
MiscRegIndex miscReg;
@@ -138,4 +138,21 @@ class McrMrcMiscInst : public ArmStaticInst
};
+/**
+ * This class is also used for IMPLEMENTATION DEFINED registers, whose mcr/mrc
+ * behaviour is trappable even for unimplemented registers.
+ */
+class McrMrcImplDefined : public McrMrcMiscInst
+{
+ public:
+ McrMrcImplDefined(const char *_mnemonic, ExtMachInst _machInst,
+ uint64_t _iss, MiscRegIndex _miscReg);
+
+ Fault execute(ExecContext *xc, Trace::InstRecord *traceData) const;
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+
+};
+
#endif
diff --git a/src/arch/arm/isa/formats/misc.isa b/src/arch/arm/isa/formats/misc.isa
index 4f834b8e1..a9acc21af 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-2017 ARM Limited
+// Copyright (c) 2010-2013,2016-2018 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
@@ -219,6 +219,11 @@ let {{
machInst,
csprintf("miscreg crn:%d opc1:%d crm:%d opc2:%d %s unknown",
crn, opc1, crm, opc2, isRead ? "read" : "write"));
+ case MISCREG_IMPDEF_UNIMPL:
+ return new McrMrcImplDefined(
+ isRead ? "mrc implementation defined" :
+ "mcr implementation defined",
+ machInst, iss, MISCREG_IMPDEF_UNIMPL);
case MISCREG_CP15ISB:
return new Isb(machInst, iss);
case MISCREG_CP15DSB:
diff --git a/src/arch/arm/miscregs.cc b/src/arch/arm/miscregs.cc
index c0b6aa5d5..7d5441ca8 100644
--- a/src/arch/arm/miscregs.cc
+++ b/src/arch/arm/miscregs.cc
@@ -502,6 +502,19 @@ decodeCP15Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2)
}
break;
case 9:
+ // Every cop register with CRn = 9 and CRm in
+ // {0-2}, {5-8} is implementation defined regardless
+ // of opc1 and opc2.
+ switch (crm) {
+ case 0:
+ case 1:
+ case 2:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ return MISCREG_IMPDEF_UNIMPL;
+ }
if (opc1 == 0) {
switch (crm) {
case 12:
@@ -565,7 +578,9 @@ decodeCP15Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2)
case 10:
if (opc1 == 0) {
// crm 0, 1, 4, and 8, with op2 0 - 7, reserved for TLB lockdown
- if (crm == 2) { // TEX Remap Registers
+ if (crm < 2) {
+ return MISCREG_IMPDEF_UNIMPL;
+ } else if (crm == 2) { // TEX Remap Registers
if (opc2 == 0) {
// Selector is TTBCR.EAE
return MISCREG_PRRR_MAIR0;
@@ -609,6 +624,8 @@ decodeCP15Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2)
case 8:
case 15:
// Reserved for DMA operations for TCM access
+ return MISCREG_IMPDEF_UNIMPL;
+ default:
break;
}
}
@@ -689,7 +706,7 @@ decodeCP15Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2)
break;
case 15:
// Implementation defined
- return MISCREG_CP15_UNIMPL;
+ return MISCREG_IMPDEF_UNIMPL;
}
// Unrecognized register
return MISCREG_CP15_UNIMPL;
diff --git a/src/arch/arm/miscregs.hh b/src/arch/arm/miscregs.hh
index cb4dcab8c..9bca3d116 100644
--- a/src/arch/arm/miscregs.hh
+++ b/src/arch/arm/miscregs.hh
@@ -677,7 +677,7 @@ namespace ArmISA
// NUM_PHYS_MISCREGS specifies the number of actual physical
// registers, not considering the following pseudo-registers
- // (dummy registers), like UNKNOWN, CP15_UNIMPL...
+ // (dummy registers), like UNKNOWN, CP15_UNIMPL, MISCREG_IMPDEF_UNIMPL.
// Checkpointing should use this physical index when
// saving/restoring register values.
NUM_PHYS_MISCREGS = 606, // 606
@@ -690,6 +690,11 @@ namespace ArmISA
MISCREG_A64_UNIMPL,
MISCREG_UNKNOWN,
+ // Implementation defined register: this represent
+ // a pool of unimplemented registers whose access can throw
+ // either UNDEFINED or hypervisor trap exception.
+ MISCREG_IMPDEF_UNIMPL,
+
// Total number of Misc Registers: Physical + Dummy
NUM_MISCREGS
};
@@ -1380,7 +1385,8 @@ namespace ArmISA
"cp14_unimpl",
"cp15_unimpl",
"a64_unimpl",
- "unknown"
+ "unknown",
+ "impl_defined"
};
static_assert(sizeof(miscRegName) / sizeof(*miscRegName) == NUM_MISCREGS,