ARM: Fix RFE macrop.
authorMatt Horsnell <Matt.Horsnell@arm.com>
Fri, 18 Mar 2011 00:20:19 +0000 (19:20 -0500)
committerMatt Horsnell <Matt.Horsnell@arm.com>
Fri, 18 Mar 2011 00:20:19 +0000 (19:20 -0500)
This changes the RFE macroop into 3 microops:

URa = [sp]; URb = [sp+4]; // load CPSR,PC values from stack
sp = sp + offset;         // optionally auto-increment
PC = URa; CPSR = URb;     // write to the PC and CPSR.

Importantly:
- writing to PC is handled in the last micro-op.
- loading occurs prior to state changes.

src/arch/arm/insts/macromem.cc
src/arch/arm/insts/macromem.hh
src/arch/arm/insts/mem.hh
src/arch/arm/intregs.hh
src/arch/arm/isa/insts/ldr.isa
src/arch/arm/isa/insts/macromem.isa
src/arch/arm/isa/insts/mem.isa
src/arch/arm/isa/templates/macromem.isa
src/arch/arm/isa/templates/mem.isa

index 2a45cf2e680ae6c975c6091244c070527bae77e5..c03b7ccc174905d98b1adeb770b6d67b915c108d 100644 (file)
@@ -895,6 +895,15 @@ MicroIntImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
     return ss.str();
 }
 
+std::string
+MicroSetPCCPSR::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+{
+    std::stringstream ss;
+    printMnemonic(ss);
+    ss << "[PC,CPSR]";
+    return ss.str();
+}
+
 std::string
 MicroIntMov::generateDisassembly(Addr pc, const SymbolTable *symtab) const
 {
index 1a2db8b9a49c14ff9aed501ade20a8cbe78853f9..4933a1e7cf7080cdfd3ca762f91f21215c373aea 100644 (file)
@@ -134,6 +134,27 @@ class MicroNeonMixLaneOp : public MicroNeonMixOp
     {
     }
 };
+
+/**
+ * Microops of the form
+ * PC   = IntRegA
+ * CPSR = IntRegB
+ */
+class MicroSetPCCPSR : public MicroOp
+{
+    protected:
+    IntRegIndex ura, urb, urc;
+
+    MicroSetPCCPSR(const char *mnem, ExtMachInst machInst, OpClass __opClass,
+                   IntRegIndex _ura, IntRegIndex _urb, IntRegIndex _urc)
+        : MicroOp(mnem, machInst, __opClass),
+          ura(_ura), urb(_urb), urc(_urc)
+    {
+    }
+
+    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+};
+
 /**
  * Microops of the form IntRegA = IntRegB
  */
index a4fc626033d02ef4962c4b601364f0bf201c5782..324d86fed55c9a08b1446d44ecfa06e5e434c631 100644 (file)
@@ -97,14 +97,18 @@ class RfeOp : public MightBeMicro
     IntRegIndex base;
     AddrMode mode;
     bool wb;
-    static const unsigned numMicroops = 2;
+    IntRegIndex ura, urb, urc;
+    static const unsigned numMicroops = 3;
 
     StaticInstPtr *uops;
 
     RfeOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
           IntRegIndex _base, AddrMode _mode, bool _wb)
         : MightBeMicro(mnem, _machInst, __opClass),
-          base(_base), mode(_mode), wb(_wb), uops(NULL)
+          base(_base), mode(_mode), wb(_wb),
+          ura(INTREG_UREG0), urb(INTREG_UREG1),
+          urc(INTREG_UREG2),
+          uops(NULL)
     {}
 
     virtual
index 4b2cc560da60a4419b2d19c356773fc9df63cf55..2cbed6c59a535da20a6d719bbd95008e05cfd373 100644 (file)
@@ -110,6 +110,8 @@ enum IntRegIndex
 
     INTREG_ZERO, // Dummy zero reg since there has to be one.
     INTREG_UREG0,
+    INTREG_UREG1,
+    INTREG_UREG2,
     INTREG_CONDCODES,
     INTREG_FPCONDCODES,
 
index c60a91a500f2995b9c9a6061d3ab87aea45dfe61..2e45f2875821f72c9001d3cc3fd71b49b5ab3d43 100644 (file)
@@ -67,7 +67,7 @@ let {{
             self.memFlags = ["ArmISA::TLB::MustBeOne"]
             self.codeBlobs = {"postacc_code" : ""}
 
-        def emitHelper(self, base = 'Memory', wbDecl = None, instFlags = []):
+        def emitHelper(self, base = 'Memory', wbDecl = None, instFlags = [], pcDecl = None):
 
             global header_output, decoder_output, exec_output
 
@@ -76,7 +76,8 @@ let {{
             (newHeader,
              newDecoder,
              newExec) = self.fillTemplates(self.name, self.Name, codeBlobs,
-                                           self.memFlags, instFlags, base, wbDecl)
+                                           self.memFlags, instFlags, base,
+                                           wbDecl, pcDecl)
 
             header_output += newHeader
             decoder_output += newDecoder
@@ -104,26 +105,18 @@ let {{
                 wbDiff = 8
             accCode = '''
             CPSR cpsr = Cpsr;
-            SCTLR sctlr = Sctlr;
-            // Use the version of NPC that gets set before NextThumb
-            pNPC = cSwap<uint32_t>(Mem.ud, cpsr.e);
-            uint32_t tempSpsr = cSwap<uint32_t>(Mem.ud >> 32, cpsr.e);
-            uint32_t newCpsr =
-                cpsrWriteByInstr(cpsr | CondCodes, tempSpsr,
-                                 0xF, true, sctlr.nmfi);
-            Cpsr = ~CondCodesMask & newCpsr;
-            NextThumb = ((CPSR)newCpsr).t;
-            NextJazelle = ((CPSR)newCpsr).j;
-            ForcedItState = ((((CPSR)tempSpsr).it2 << 2) & 0xFC)
-                | (((CPSR)tempSpsr).it1 & 0x3);
-            CondCodes = CondCodesMask & newCpsr;
+            URc = cpsr | CondCodes;
+            URa = cSwap<uint32_t>(Mem.ud, cpsr.e);
+            URb = cSwap<uint32_t>(Mem.ud >> 32, cpsr.e);
             '''
             self.codeBlobs["memacc_code"] = accCode
 
             wbDecl = None
+            pcDecl = "MicroUopSetPCCPSR(machInst, INTREG_UREG0, INTREG_UREG1, INTREG_UREG2);"
+
             if self.writeback:
                 wbDecl = "MicroAddiUop(machInst, base, base, %d);" % wbDiff
-            self.emitHelper('RfeOp', wbDecl, ["IsSerializeAfter", "IsNonSpeculative"])
+            self.emitHelper('RfeOp', wbDecl, ["IsSerializeAfter", "IsNonSpeculative"], pcDecl)
 
     class LoadImmInst(LoadInst):
         def __init__(self, *args, **kargs):
index 0e3bcc648a5fc2ffec2d54b5bb8b84c5359d29bd..d6c929353627a4f00305282b5946db2b4acb8f04 100644 (file)
@@ -608,23 +608,48 @@ let {{
                                     'predicate_test': predicateTest},
                                    ['IsMicroop'])
 
+    setPCCPSRDecl = '''
+                    CPSR cpsrOrCondCodes = URc;
+                    SCTLR sctlr = Sctlr;
+                    pNPC = URa;
+                    uint32_t newCpsr =
+                    cpsrWriteByInstr(cpsrOrCondCodes, URb,
+                                     0xF, true, sctlr.nmfi);
+                    Cpsr = ~CondCodesMask & newCpsr;
+                    NextThumb = ((CPSR)newCpsr).t;
+                    NextJazelle = ((CPSR)newCpsr).j;
+                    ForcedItState = ((((CPSR)URb).it2 << 2) & 0xFC)
+                                    | (((CPSR)URb).it1 & 0x3);
+                    CondCodes = CondCodesMask & newCpsr;
+                    '''
+
+    microUopSetPCCPSRIop = InstObjParams('uopSet_uop', 'MicroUopSetPCCPSR',
+                                         'MicroSetPCCPSR',
+                                         {'code': setPCCPSRDecl,
+                                          'predicate_test': predicateTest},
+                                         ['IsMicroop'])
+
     header_output = MicroIntImmDeclare.subst(microAddiUopIop) + \
                     MicroIntImmDeclare.subst(microSubiUopIop) + \
                     MicroIntRegDeclare.subst(microAddUopIop) + \
                     MicroIntRegDeclare.subst(microSubUopIop) + \
-                    MicroIntMovDeclare.subst(microUopRegMovIop)
+                    MicroIntMovDeclare.subst(microUopRegMovIop) + \
+                    MicroSetPCCPSRDeclare.subst(microUopSetPCCPSRIop)
 
     decoder_output = MicroIntImmConstructor.subst(microAddiUopIop) + \
                      MicroIntImmConstructor.subst(microSubiUopIop) + \
                      MicroIntRegConstructor.subst(microAddUopIop) + \
                      MicroIntRegConstructor.subst(microSubUopIop) + \
-                     MicroIntMovConstructor.subst(microUopRegMovIop)
+                     MicroIntMovConstructor.subst(microUopRegMovIop) + \
+                     MicroSetPCCPSRConstructor.subst(microUopSetPCCPSRIop)
 
     exec_output = PredOpExecute.subst(microAddiUopIop) + \
                   PredOpExecute.subst(microSubiUopIop) + \
                   PredOpExecute.subst(microAddUopIop) + \
                   PredOpExecute.subst(microSubUopIop) + \
-                  PredOpExecute.subst(microUopRegMovIop)
+                  PredOpExecute.subst(microUopRegMovIop) + \
+                  PredOpExecute.subst(microUopSetPCCPSRIop)
+
 }};
 
 let {{
index 507f8cd4bf07bf1f02b5d44f1f72cfeb0a1fac17..d0c0f07104c824cc27dd3c27709f2a4554790da5 100644 (file)
@@ -48,7 +48,7 @@ let {{
             self.constructTemplate = eval(self.decConstBase + 'Constructor')
 
         def fillTemplates(self, name, Name, codeBlobs, memFlags, instFlags,
-                          base = 'Memory', wbDecl = None):
+                          base = 'Memory', wbDecl = None, pcDecl = None):
             # Make sure flags are in lists (convert to lists if not).
             memFlags = makeList(memFlags)
             instFlags = makeList(instFlags)
@@ -65,12 +65,26 @@ let {{
             macroName = Name
             instFlagsCopy = list(instFlags)
             codeBlobsCopy = dict(codeBlobs)
-            if wbDecl is not None:
+
+            use_uops = 0
+            if wbDecl is not None or pcDecl is not None:
                 instFlagsCopy.append('IsMicroop')
                 Name = Name + 'Acc'
+                use_uops = 1
+
+            use_wb = 0
+            use_pc = 0
+            if wbDecl is not None:
+                use_wb = 1
+            if pcDecl is not None:
+                use_pc = 1
+
             codeBlobsCopy['acc_name'] = Name
             codeBlobsCopy['wb_decl'] = wbDecl
+            codeBlobsCopy['pc_decl'] = pcDecl
             codeBlobsCopy['use_uops'] = 0
+            codeBlobsCopy['use_wb'] = 0
+            codeBlobsCopy['use_pc'] = 0
 
             iop = InstObjParams(name, Name, base,
                                 codeBlobsCopy, instFlagsCopy)
@@ -81,11 +95,14 @@ let {{
                           self.initiateAccTemplate.subst(iop) + \
                           self.completeAccTemplate.subst(iop)
 
-            if wbDecl is not None:
+            if wbDecl is not None or pcDecl is not None:
                 iop = InstObjParams(name, macroName, base,
                                     { "wb_decl" : wbDecl,
+                                      "pc_decl" : pcDecl,
                                       "acc_name" : Name,
-                                      "use_uops" : 1 },
+                                      "use_uops" : use_uops,
+                                      "use_pc" : use_pc,
+                                      "use_wb" : use_wb },
                                     ['IsMacroop'])
                 header_output += self.declareTemplate.subst(iop)
                 decoder_output += self.constructTemplate.subst(iop)
index b7ca7fa488bf2dbf8080e9fb3952d4c23b62e9aa..a7f7f0da8aeacdfe37d8fcc32c474e6ce816ca6f 100644 (file)
@@ -107,6 +107,41 @@ def template MicroNeonMemDeclare {{
     };
 }};
 
+////////////////////////////////////////////////////////////////////
+//
+// PC   = Integer(ura)
+// CPSR = Integer(urb)
+//
+
+def template MicroSetPCCPSRDeclare {{
+    class %(class_name)s : public %(base_class)s
+    {
+      public:
+        %(class_name)s(ExtMachInst machInst,
+                       IntRegIndex _ura,
+                       IntRegIndex _urb,
+                       IntRegIndex _urc);
+        %(BasicExecDeclare)s
+    };
+}};
+
+def template MicroSetPCCPSRConstructor {{
+    %(class_name)s::%(class_name)s(ExtMachInst machInst,
+                                   IntRegIndex _ura,
+                                   IntRegIndex _urb,
+                                   IntRegIndex _urc)
+          : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
+                           _ura, _urb, _urc)
+    {
+        %(constructor)s;
+        if (!(condCode == COND_AL || condCode == COND_UC)) {
+            for (int x = 0; x < _numDestRegs; x++) {
+                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
+            }
+        }
+    }
+}};
+
 ////////////////////////////////////////////////////////////////////
 //
 // Integer = Integer op Integer microops
index 3d073b3225fb00a963cb625c7afa0ce9e44b95b4..dcfd47ace628e51d19d69c9fb53d7a9b7166bc21 100644 (file)
@@ -917,9 +917,9 @@ def template CompleteAccDeclare {{
 
 def template RfeConstructor {{
     inline %(class_name)s::%(class_name)s(ExtMachInst machInst,
-            uint32_t _base, int _mode, bool _wb)
-         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
-                 (IntRegIndex)_base, (AddrMode)_mode, _wb)
+                                          uint32_t _base, int _mode, bool _wb)
+        : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
+                         (IntRegIndex)_base, (AddrMode)_mode, _wb)
     {
         %(constructor)s;
         if (!(condCode == COND_AL || condCode == COND_UC)) {
@@ -928,12 +928,18 @@ def template RfeConstructor {{
             }
         }
 #if %(use_uops)d
-        assert(numMicroops >= 2);
-        uops = new StaticInstPtr[numMicroops];
-        uops[0] = new %(acc_name)s(machInst, _base, _mode, _wb);
-        uops[0]->setDelayedCommit();
-        uops[1] = new %(wb_decl)s;
-        uops[1]->setLastMicroop();
+        uops = new StaticInstPtr[1 + %(use_wb)d + %(use_pc)d];
+        int uopIdx = 0;
+        uops[uopIdx] = new %(acc_name)s(machInst, _base, _mode, _wb);
+        uops[uopIdx]->setDelayedCommit();
+#if %(use_wb)d
+        uops[++uopIdx] = new %(wb_decl)s;
+        uops[uopIdx]->setDelayedCommit();
+#endif
+#if %(use_pc)d
+        uops[++uopIdx] = new %(pc_decl)s;
+#endif
+        uops[uopIdx]->setLastMicroop();
 #endif
     }
 }};