Move around more SPARC memory code, and make block memory operations work with the...
authorGabe Black <gblack@eecs.umich.edu>
Mon, 23 Oct 2006 15:17:15 +0000 (11:17 -0400)
committerGabe Black <gblack@eecs.umich.edu>
Mon, 23 Oct 2006 15:17:15 +0000 (11:17 -0400)
--HG--
extra : convert_revision : 37358504c4d05d78d08c19ba3d0c99d38c4babf5

src/arch/sparc/isa/formats/mem/basicmem.isa
src/arch/sparc/isa/formats/mem/blockmem.isa
src/arch/sparc/isa/formats/mem/util.isa

index b524f309acd2e67e8737e231b6dee2dc20287490..c13194d0f74ca989ddac6af9d6a4303ec42e81bc 100644 (file)
@@ -146,26 +146,18 @@ def template MemDeclare {{
 }};
 
 let {{
-    # XXX Need to take care of pstate.hpriv as well. The lower ASIs are split
-    # into ones that are available in priv and hpriv, and those that are only
-    # available in hpriv
-    privilegedString = '''if(bits(Pstate,2,2) == 0 && (EXT_ASI & 0x80) == 0)
-                return new PrivilegedAction;
-            if(AsiIsAsIfUser(EXT_ASI) && !bits(Pstate,2,2))
-                return new PrivilegedAction;'''
-
-    def doMemFormat(code, execute, priv, name, Name, opt_flags):
+    def doMemFormat(code, execute, faultCode, name, Name, opt_flags):
         addrCalcReg = 'EA = Rs1 + Rs2;'
         addrCalcImm = 'EA = Rs1 + imm;'
         iop = InstObjParams(name, Name, 'Mem', code,
-                opt_flags, {"priv_check": priv, "ea_code": addrCalcReg})
+                opt_flags, {"fault_check": faultCode, "ea_code": addrCalcReg})
         iop_imm = InstObjParams(name, Name + "Imm", 'MemImm', code,
-                opt_flags, {"priv_check": priv, "ea_code": addrCalcImm})
+                opt_flags, {"fault_check": faultCode, "ea_code": addrCalcImm})
         header_output = MemDeclare.subst(iop) + MemDeclare.subst(iop_imm)
         decoder_output = BasicConstructor.subst(iop) + BasicConstructor.subst(iop_imm)
         decode_block = ROrImmDecode.subst(iop)
         exec_output = doSplitExecute(code, addrCalcReg, addrCalcImm, execute,
-                priv, name, name + "Imm", Name, Name + "Imm", opt_flags)
+                faultCode, name, name + "Imm", Name, Name + "Imm", opt_flags)
         return (header_output, decoder_output, exec_output, decode_block)
 }};
 
@@ -174,7 +166,7 @@ def format LoadAlt(code, *opt_flags) {{
          decoder_output,
          exec_output,
          decode_block) = doMemFormat(code, LoadExecute,
-            privelegedString, name, Name, opt_flags)
+            AlternateAsiPrivFaultCheck, name, Name, opt_flags)
 }};
 
 def format StoreAlt(code, *opt_flags) {{
@@ -182,7 +174,7 @@ def format StoreAlt(code, *opt_flags) {{
          decoder_output,
          exec_output,
          decode_block) = doMemFormat(code, StoreExecute,
-            privilegedString, name, Name, opt_flags)
+            AlternateAsiPrivFaultCheck, name, Name, opt_flags)
 }};
 
 def format Load(code, *opt_flags) {{
index 8584662a1c26847a1a7160e720fe25afc121609e..93ad1b2b8bee02a040c5f59bbeba06970c7917b2 100644 (file)
@@ -166,6 +166,8 @@ def template BlockMemDeclare {{
                 //Constructor
                 %(class_name)s_0(ExtMachInst machInst);
                 %(BasicExecDeclare)s
+                %(InitiateAccDeclare)s
+                %(CompleteAccDeclare)s
             };
 
             class %(class_name)s_1 : public %(base_class)sMicro
@@ -174,6 +176,8 @@ def template BlockMemDeclare {{
                 //Constructor
                 %(class_name)s_1(ExtMachInst machInst);
                 %(BasicExecDeclare)s
+                %(InitiateAccDeclare)s
+                %(CompleteAccDeclare)s
             };
 
             class %(class_name)s_2 : public %(base_class)sMicro
@@ -182,6 +186,8 @@ def template BlockMemDeclare {{
                 //Constructor
                 %(class_name)s_2(ExtMachInst machInst);
                 %(BasicExecDeclare)s
+                %(InitiateAccDeclare)s
+                %(CompleteAccDeclare)s
             };
 
             class %(class_name)s_3 : public %(base_class)sMicro
@@ -190,6 +196,8 @@ def template BlockMemDeclare {{
                 //Constructor
                 %(class_name)s_3(ExtMachInst machInst);
                 %(BasicExecDeclare)s
+                %(InitiateAccDeclare)s
+                %(CompleteAccDeclare)s
             };
 
             class %(class_name)s_4 : public %(base_class)sMicro
@@ -198,6 +206,8 @@ def template BlockMemDeclare {{
                 //Constructor
                 %(class_name)s_4(ExtMachInst machInst);
                 %(BasicExecDeclare)s
+                %(InitiateAccDeclare)s
+                %(CompleteAccDeclare)s
             };
 
             class %(class_name)s_5 : public %(base_class)sMicro
@@ -206,6 +216,8 @@ def template BlockMemDeclare {{
                 //Constructor
                 %(class_name)s_5(ExtMachInst machInst);
                 %(BasicExecDeclare)s
+                %(InitiateAccDeclare)s
+                %(CompleteAccDeclare)s
             };
 
             class %(class_name)s_6 : public %(base_class)sMicro
@@ -214,6 +226,8 @@ def template BlockMemDeclare {{
                 //Constructor
                 %(class_name)s_6(ExtMachInst machInst);
                 %(BasicExecDeclare)s
+                %(InitiateAccDeclare)s
+                %(CompleteAccDeclare)s
             };
 
             class %(class_name)s_7 : public %(base_class)sMicro
@@ -222,6 +236,8 @@ def template BlockMemDeclare {{
                 //Constructor
                 %(class_name)s_7(ExtMachInst machInst);
                 %(BasicExecDeclare)s
+                %(InitiateAccDeclare)s
+                %(CompleteAccDeclare)s
             };
         };
 }};
@@ -255,72 +271,12 @@ def template BlockMemMicroConstructor {{
     }
 }};
 
-def template MicroLoadExecute {{
-        Fault %(class_name)s::%(class_name)s_%(micro_pc)s::execute(
-                %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
-        {
-            Fault fault = NoFault;
-            Addr EA;
-            %(op_decl)s;
-            %(op_rd)s;
-            %(ea_code)s;
-            %(fault_check)s;
-            DPRINTF(Sparc, "The address is 0x%x\n", EA);
-            xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0);
-            %(code)s;
-
-            if(fault == NoFault)
-            {
-                //Write the resulting state to the execution context
-                %(op_wb)s;
-            }
-
-            return fault;
-        }
-}};
-
-def template MicroStoreExecute {{
-        Fault %(class_name)s::%(class_name)s_%(micro_pc)s::execute(
-                %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
-        {
-            Fault fault = NoFault;
-            uint64_t write_result = 0;
-            Addr EA;
-            %(op_decl)s;
-            %(op_rd)s;
-            %(ea_code)s;
-            %(fault_check)s;
-            DPRINTF(Sparc, "The address is 0x%x\n", EA);
-            %(code)s;
-
-            if(fault == NoFault)
-            {
-                xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result);
-                //Write the resulting state to the execution context
-                %(op_wb)s;
-            }
-
-            return fault;
-        }
-}};
-
 let {{
 
-    def doBlockMemFormat(code, execute, name, Name, opt_flags):
+    def doBlockMemFormat(code, faultCode, execute, name, Name, opt_flags):
         # XXX Need to take care of pstate.hpriv as well. The lower ASIs
         # are split into ones that are available in priv and hpriv, and
         # those that are only available in hpriv
-        faultCheck = '''if(bits(Pstate,2,2) == 0 && (EXT_ASI & 0x80) == 0)
-                    return new PrivilegedAction;
-                if(AsiIsAsIfUser((ASI)EXT_ASI) && !bits(Pstate,2,2))
-                    return new PrivilegedAction;
-                //The LSB can be zero, since it's really the MSB in doubles
-                //and quads
-                if(RD & 0xe)
-                    return new IllegalInstruction;
-                if(EA & 0x3f)
-                    return new MemAddressNotAligned;
-                '''
         addrCalcReg = 'EA = Rs1 + Rs2 + offset;'
         addrCalcImm = 'EA = Rs1 + imm + offset;'
         iop = InstObjParams(name, Name, 'BlockMem', code, opt_flags)
@@ -330,39 +286,52 @@ let {{
         decode_block = ROrImmDecode.subst(iop)
         matcher = re.compile(r'Frd_N')
         exec_output = ''
-        for microPC in range(8):
+        for microPc in range(8):
             flag_code = ''
-            if (microPC == 7):
+            if (microPc == 7):
                 flag_code = "flags[IsLastMicroOp] = true;"
-            pcedCode = matcher.sub("Frd_%d" % microPC, code)
+            pcedCode = matcher.sub("Frd_%d" % microPc, code)
             iop = InstObjParams(name, Name, 'BlockMem', pcedCode,
                     opt_flags, {"ea_code": addrCalcReg,
-                    "fault_check": faultCheck, "micro_pc": microPC,
+                    "fault_check": faultCode, "micro_pc": microPc,
                     "set_flags": flag_code})
             iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', pcedCode,
                     opt_flags, {"ea_code": addrCalcImm,
-                    "fault_check": faultCheck, "micro_pc": microPC,
+                    "fault_check": faultCode, "micro_pc": microPc,
                     "set_flags": flag_code})
-            exec_output += execute.subst(iop)
-            exec_output += execute.subst(iop_imm)
             decoder_output += BlockMemMicroConstructor.subst(iop)
             decoder_output += BlockMemMicroConstructor.subst(iop_imm)
-            faultCheck = ''
+            exec_output += doSplitExecute(
+                    pcedCode, addrCalcReg, addrCalcImm, execute, faultCode,
+                    makeMicroName(name, microPc),
+                    makeMicroName(name + "Imm", microPc),
+                    makeMicroName(Name, microPc),
+                    makeMicroName(Name + "Imm", microPc),
+                    opt_flags);
+            faultCode = ''
         return (header_output, decoder_output, exec_output, decode_block)
 }};
 
 def format BlockLoad(code, *opt_flags) {{
+        # We need to make sure to check the highest priority fault last.
+        # That way, if other faults have been detected, they'll be overwritten
+        # rather than the other way around.
+        faultCode = AlternateASIPrivFaultCheck + BlockAlignmentFaultCheck
         (header_output,
          decoder_output,
          exec_output,
-         decode_block) = doBlockMemFormat(code, MicroLoadExecute,
-             name, Name, opt_flags)
+         decode_block) = doBlockMemFormat(code, faultCode,
+             LoadExecute, name, Name, opt_flags)
 }};
 
 def format BlockStore(code, *opt_flags) {{
+        # We need to make sure to check the highest priority fault last.
+        # That way, if other faults have been detected, they'll be overwritten
+        # rather than the other way around.
+        faultCode = AlternateASIPrivFaultCheck + BlockAlignmentFaultCheck
         (header_output,
          decoder_output,
          exec_output,
-         decode_block) = doBlockMemFormat(code, MicroStoreExecute,
-            name, Name, opt_flags)
+         decode_block) = doBlockMemFormat(code, faultCode,
+             StoreExecute, name, Name, opt_flags)
 }};
index 296ae188805deac582b6e61e84c94a7c9bc44e0c..241a25d17acbe0594ba8ef0648af8e25c30f3fde 100644 (file)
@@ -42,11 +42,17 @@ def template LoadExecute {{
             Addr EA;
             %(op_decl)s;
             %(op_rd)s;
-            %(priv_check)s;
             %(ea_code)s;
             DPRINTF(Sparc, "The address is 0x%x\n", EA);
-            fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0);
-            %(code)s;
+            %(fault_check)s;
+            if(fault == NoFault)
+            {
+                fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0);
+            }
+            if(fault == NoFault)
+            {
+                %(code)s;
+            }
             if(fault == NoFault)
             {
                 //Write the resulting state to the execution context
@@ -64,9 +70,12 @@ def template LoadExecute {{
             uint%(mem_acc_size)s_t Mem;
             %(ea_decl)s;
             %(ea_rd)s;
-            %(priv_check)s;
             %(ea_code)s;
-            fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0);
+            %(fault_check)s;
+            if(fault == NoFault)
+            {
+                fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0);
+            }
             return fault;
         }
 
@@ -96,11 +105,13 @@ def template StoreExecute {{
             Addr EA;
             %(op_decl)s;
             %(op_rd)s;
-            %(priv_check)s;
             %(ea_code)s;
             DPRINTF(Sparc, "The address is 0x%x\n", EA);
-            %(code)s;
-
+            %(fault_check)s;
+            if(fault == NoFault)
+            {
+                %(code)s;
+            }
             if(fault == NoFault)
             {
                 fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result);
@@ -122,10 +133,13 @@ def template StoreExecute {{
             Addr EA;
             %(op_decl)s;
             %(op_rd)s;
-            %(priv_check)s;
             %(ea_code)s;
             DPRINTF(Sparc, "The address is 0x%x\n", EA);
-            %(code)s;
+            %(fault_check)s;
+            if(fault == NoFault)
+            {
+                %(code)s;
+            }
             if(fault == NoFault)
             {
                 fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result);
@@ -155,23 +169,52 @@ def template CompleteAccDeclare {{
     Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
 }};
 
+//Here are some code snippets which check for various fault conditions
+let {{
+    # The LSB can be zero, since it's really the MSB in doubles and quads
+    # and we're dealing with doubles
+    BlockAlignmentFaultCheck = '''
+        if(RD & 0xe)
+            fault = new IllegalInstruction;
+        else if(EA & 0x3f)
+            fault = new MemAddressNotAligned;
+    '''
+    # XXX Need to take care of pstate.hpriv as well. The lower ASIs
+    # are split into ones that are available in priv and hpriv, and
+    # those that are only available in hpriv
+    AlternateASIPrivFaultCheck = '''
+        if(bits(Pstate,2,2) == 0 && (EXT_ASI & 0x80) == 0)
+            fault = new PrivilegedAction;
+        else if(AsiIsAsIfUser((ASI)EXT_ASI) && !bits(Pstate,2,2))
+            fault = new PrivilegedAction;
+    '''
+
+}};
+
+//A simple function to generate the name of the macro op of a certain
+//instruction at a certain micropc
+let {{
+    def makeMicroName(name, microPc):
+        return name + "::" + name + "_" + str(microPc)
+}};
+
 //This function properly generates the execute functions for one of the
 //templates above. This is needed because in one case, ea computation,
-//privelege checks and the actual code all occur in the same function,
+//fault checks and the actual code all occur in the same function,
 //and in the other they're distributed across two. Also note that for
 //execute functions, the name of the base class doesn't matter.
 let {{
     def doSplitExecute(code, eaRegCode, eaImmCode, execute,
-            priv, nameReg, nameImm, NameReg, NameImm, opt_flags):
+            faultCode, nameReg, nameImm, NameReg, NameImm, opt_flags):
         codeIop = InstObjParams(nameReg, NameReg, '', code, opt_flags)
         executeCode = ''
         for (eaCode, name, Name) in (
                 (eaRegCode, nameReg, NameReg),
                 (eaImmCode, nameImm, NameImm)):
             eaIop = InstObjParams(name, Name, '', eaCode,
-                    opt_flags, {"priv_check": priv})
+                    opt_flags, {"fault_check": faultCode})
             iop = InstObjParams(name, Name, '', code, opt_flags,
-                    {"priv_check": priv, "ea_code" : eaCode})
+                    {"fault_check": faultCode, "ea_code" : eaCode})
             (iop.ea_decl,
              iop.ea_rd,
              iop.ea_wb) = (eaIop.op_decl, eaIop.op_rd, eaIop.op_wb)