arch-arm: ISA param for treating MISCREG_IMPDEF_UNIMPL as NOP
authorGiacomo Travaglini <giacomo.travaglini@arm.com>
Wed, 9 May 2018 16:52:37 +0000 (17:52 +0100)
committerGiacomo Travaglini <giacomo.travaglini@arm.com>
Tue, 29 May 2018 10:17:47 +0000 (10:17 +0000)
In the Arm ISA there are some sys reg numbers which are reserved for
implementation defined registers. The default behaviour is to to treat
them as unimplemented registers. It is now possible to change this
behaviour at runtime and treat them as NOP. In this way an access to
those register won't make simulation fail.

Change-Id: I0d108299a6d5aa81fcdabdaef04eafe46df92343
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/10504
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>

src/arch/arm/ArmISA.py
src/arch/arm/isa.cc
src/arch/arm/isa.hh
src/arch/arm/isa/formats/aarch64.isa
src/arch/arm/isa/formats/misc.isa
src/arch/arm/miscregs.cc

index 7956570bd0ee7d6ec6f2206e3f54618456205c47..78dd04330823df3bef709506cb7ac7d40bcd74fd 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2012-2013, 2015-2016 ARM Limited
+# Copyright (c) 2012-2013, 2015-2016, 2018 ARM Limited
 # All rights reserved.
 #
 # The license below extends only to copyright in the software and shall
@@ -111,3 +111,9 @@ class ArmISA(SimObject):
     # Reserved for future expansion
     id_aa64mmfr1_el1 = Param.UInt64(0x0000000000000000,
         "AArch64 Memory Model Feature Register 1")
+
+    # Any access (read/write) to an unimplemented
+    # Implementation Defined registers is not causing an Undefined Instruction.
+    # It is rather executed as a NOP.
+    impdef_nop = Param.Bool(False,
+        "Any access to a MISCREG_IMPDEF_UNIMPL register is executed as NOP")
index 296f8eb4ad4bb2d882cfbdb004c5e879bb164942..a4e9c7975cd2c2f025c8ef15eee21c3bd9f27394 100644 (file)
@@ -61,7 +61,8 @@ ISA::ISA(Params *p)
       system(NULL),
       _decoderFlavour(p->decoderFlavour),
       _vecRegRenameMode(p->vecRegRenameMode),
-      pmu(p->pmu)
+      pmu(p->pmu),
+      impdefAsNop(p->impdef_nop)
 {
     miscRegs[MISCREG_SCTLR_RST] = 0;
 
index c8ae5c22ded0ede090ef9d7f838926c112d675a9..9158b62aaadf0941e80bfd1c6b301eae068d3b9d 100644 (file)
@@ -90,6 +90,12 @@ namespace ArmISA
         bool haveLargeAsid64;
         uint8_t physAddrRange64;
 
+        /**
+         * If true, accesses to IMPLEMENTATION DEFINED registers are treated
+         * as NOP hence not causing UNDEFINED INSTRUCTION.
+         */
+        bool impdefAsNop;
+
         /** MiscReg metadata **/
         struct MiscRegLUTEntry {
             uint32_t lower;  // Lower half mapped to this register
index 00bd0770fce90cce0e190d209da5151da43272ae..722cd7415dc3f6b559d03976220788e15beb46b0 100644 (file)
@@ -377,6 +377,20 @@ namespace Aarch64
                         return new FailUnimplemented(read ? "mrs" : "msr",
                             machInst, full_mnemonic);
 
+                    } else if (miscReg == MISCREG_IMPDEF_UNIMPL) {
+                        auto full_mnemonic =
+                            csprintf("%s op0:%d op1:%d crn:%d crm:%d op2:%d",
+                                     read ? "mrs" : "msr",
+                                     op0, op1, crn, crm, op2);
+
+                        if (miscRegInfo[miscReg][MISCREG_WARN_NOT_FAIL]) {
+                            return new WarnUnimplemented(read ? "mrs" : "msr",
+                                machInst, full_mnemonic + " treated as NOP");
+                        } else {
+                            return new FailUnimplemented(read ? "mrs" : "msr",
+                                machInst, full_mnemonic);
+                        }
+
                     } else if (miscRegInfo[miscReg][MISCREG_IMPLEMENTED]) {
                         if (miscReg == MISCREG_NZCV) {
                             if (read)
index 4f1960b952f9450279dde61700dfd1c001d2ba4b..739741786fcaec6a7dd853204ed3b86ef0b1e539 100644 (file)
@@ -220,10 +220,22 @@ let {{
                     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);
+
+            if (miscRegInfo[miscReg][MISCREG_WARN_NOT_FAIL]) {
+                auto mnemonic =
+                    csprintf("miscreg crn:%d opc1:%d crm:%d opc2:%d %s",
+                             crn, opc1, crm, opc2, isRead ? "read" : "write");
+
+                return new WarnUnimplemented(
+                    isRead ? "mrc implementation defined" :
+                             "mcr implementation defined",
+                    machInst, mnemonic + " treated as NOP");
+            } else {
+                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:
index 31b3580be8b5e2b038aba5179b086890d33f31ff..8dd56c791919088700cbe0390c5c2954c570e69b 100644 (file)
@@ -4008,6 +4008,9 @@ ISA::initializeMiscRegMetadata()
       .unimplemented()
       .warnNotFail();
     InitReg(MISCREG_UNKNOWN);
+    InitReg(MISCREG_IMPDEF_UNIMPL)
+      .unimplemented()
+      .warnNotFail(impdefAsNop);
 
     // Register mappings for some unimplemented registers:
     // ESR_EL1 -> DFSR