Support for twin loads.
authorGabe Black <gblack@eecs.umich.edu>
Sat, 16 Dec 2006 17:54:28 +0000 (12:54 -0500)
committerGabe Black <gblack@eecs.umich.edu>
Sat, 16 Dec 2006 17:54:28 +0000 (12:54 -0500)
src/arch/sparc/isa/decoder.isa:
    Changed the names of the twin loads to match the 2005 spec. They still use the old format though.
src/arch/sparc/isa/formats/mem/blockmem.isa:
    Added code to generate twin loads
src/arch/sparc/isa/formats/mem/util.isa:
    Added an alignment check for twin loads
src/arch/sparc/isa/operands.isa:
    Comment explaining twin load operands.

--HG--
extra : convert_revision : ad42821a97dcda17744875b1e5dc00a9642e59b7

src/arch/sparc/isa/decoder.isa
src/arch/sparc/isa/formats/mem/blockmem.isa
src/arch/sparc/isa/formats/mem/util.isa
src/arch/sparc/isa/operands.isa

index 7a48042c2afe0f6d66cef5c344c0f6f7b1ca2f7b..01fe32ef709e7bd22e8cc52a4b7d71baeb87ce25 100644 (file)
@@ -1030,7 +1030,7 @@ decode OP default Unknown::unknown()
             0x00: lduw({{Rd = Mem.uw;}});
             0x01: ldub({{Rd = Mem.ub;}});
             0x02: lduh({{Rd = Mem.uhw;}});
-            0x03: ldd({{
+            0x03: ldtw({{
                 uint64_t val = Mem.udw;
                 RdLow = val<31:0>;
                 RdHigh = val<63:32>;
@@ -1040,7 +1040,7 @@ decode OP default Unknown::unknown()
             0x04: stw({{Mem.uw = Rd.sw;}});
             0x05: stb({{Mem.ub = Rd.sb;}});
             0x06: sth({{Mem.uhw = Rd.shw;}});
-            0x07: std({{Mem.udw = RdLow<31:0> | (RdHigh<31:0> << 32);}});
+            0x07: sttw({{Mem.udw = RdLow<31:0> | (RdHigh<31:0> << 32);}});
         }
         format Load {
             0x08: ldsw({{Rd = (int32_t)Mem.sw;}});
@@ -1060,7 +1060,7 @@ decode OP default Unknown::unknown()
             0x10: lduwa({{Rd = Mem.uw;}}, {{EXT_ASI}});
             0x11: lduba({{Rd = Mem.ub;}}, {{EXT_ASI}});
             0x12: lduha({{Rd = Mem.uhw;}}, {{EXT_ASI}});
-            0x13: ldda({{
+            0x13: ldtwa({{
                 uint64_t val = Mem.udw;
                 RdLow = val<31:0>;
                 RdHigh = val<63:32>;
@@ -1070,7 +1070,7 @@ decode OP default Unknown::unknown()
             0x14: stwa({{Mem.uw = Rd;}}, {{EXT_ASI}});
             0x15: stba({{Mem.ub = Rd;}}, {{EXT_ASI}});
             0x16: stha({{Mem.uhw = Rd;}}, {{EXT_ASI}});
-            0x17: stda({{Mem.udw = RdLow<31:0> | RdHigh<31:0> << 32;}}, {{EXT_ASI}});
+            0x17: sttwa({{Mem.udw = RdLow<31:0> | RdHigh<31:0> << 32;}}, {{EXT_ASI}});
         }
         format LoadAlt {
             0x18: ldswa({{Rd = (int32_t)Mem.sw;}}, {{EXT_ASI}});
index 7a1a58d13cb0f45a0be2c4b4f9fc9098e64f5fe6..fcd61a5b487e565d62e75f99f458a75afffabb29 100644 (file)
@@ -91,6 +91,65 @@ output header {{
         };
 }};
 
+output header {{
+
+        class TwinMem : public SparcMacroInst
+        {
+          protected:
+
+            // Constructor
+            // We make the assumption that all block memory operations
+            // Will take 8 instructions to execute
+            TwinMem(const char *mnem, ExtMachInst _machInst) :
+                SparcMacroInst(mnem, _machInst, No_OpClass, 8)
+            {}
+        };
+
+        class TwinMemImm : public BlockMem
+        {
+          protected:
+
+            // Constructor
+            TwinMemImm(const char *mnem, ExtMachInst _machInst) :
+                BlockMem(mnem, _machInst)
+            {}
+        };
+
+        class TwinMemMicro : public SparcMicroInst
+        {
+          protected:
+
+            // Constructor
+            TwinMemMicro(const char *mnem, ExtMachInst _machInst,
+                    OpClass __opClass, int8_t _offset) :
+                SparcMicroInst(mnem, _machInst, __opClass),
+                offset(_offset)
+            {}
+
+            std::string generateDisassembly(Addr pc,
+                const SymbolTable *symtab) const;
+
+            const int8_t offset;
+        };
+
+        class TwinMemImmMicro : public BlockMemMicro
+        {
+          protected:
+
+            // Constructor
+            TwinMemImmMicro(const char *mnem, ExtMachInst _machInst,
+                    OpClass __opClass, int8_t _offset) :
+                BlockMemMicro(mnem, _machInst, __opClass, _offset),
+                imm(sext<13>(SIMM13))
+            {}
+
+            std::string generateDisassembly(Addr pc,
+                const SymbolTable *symtab) const;
+
+            const int32_t imm;
+        };
+}};
+
 output decoder {{
         std::string BlockMemMicro::generateDisassembly(Addr pc,
                 const SymbolTable *symtab) const
@@ -242,6 +301,39 @@ def template BlockMemDeclare {{
         };
 }};
 
+def template TwinMemDeclare {{
+        /**
+         * Static instruction class for a block memory operation
+         */
+        class %(class_name)s : public %(base_class)s
+        {
+          public:
+            //Constructor
+            %(class_name)s(ExtMachInst machInst);
+
+          protected:
+            class %(class_name)s_0 : public %(base_class)sMicro
+            {
+              public:
+                //Constructor
+                %(class_name)s_0(ExtMachInst machInst);
+                %(BasicExecDeclare)s
+                %(InitiateAccDeclare)s
+                %(CompleteAccDeclare)s
+            };
+
+            class %(class_name)s_1 : public %(base_class)sMicro
+            {
+              public:
+                //Constructor
+                %(class_name)s_1(ExtMachInst machInst);
+                %(BasicExecDeclare)s
+                %(InitiateAccDeclare)s
+                %(CompleteAccDeclare)s
+            };
+        };
+}};
+
 // Basic instruction class constructor template.
 def template BlockMemConstructor {{
         inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
@@ -259,6 +351,17 @@ def template BlockMemConstructor {{
         }
 }};
 
+// Basic instruction class constructor template.
+def template TwinMemConstructor {{
+        inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
+            : %(base_class)s("%(mnemonic)s", machInst)
+        {
+            %(constructor)s;
+            microOps[0] = new %(class_name)s_0(machInst);
+            microOps[1] = new %(class_name)s_1(machInst);
+        }
+}};
+
 def template BlockMemMicroConstructor {{
         inline %(class_name)s::
             %(class_name)s_%(micro_pc)s::
@@ -312,6 +415,47 @@ let {{
                     asi, opt_flags);
             faultCode = ''
         return (header_output, decoder_output, exec_output, decode_block)
+
+
+    def doTwinLoadFormat(code, faultCode, name, Name, asi, opt_flags):
+        addrCalcReg = 'EA = Rs1 + Rs2 + offset;'
+        addrCalcImm = 'EA = Rs1 + imm + offset;'
+        iop = InstObjParams(name, Name, 'TwinMem', code, opt_flags)
+        iop_imm = InstObjParams(name, Name + 'Imm', 'TwinMemImm', code, opt_flags)
+        header_output = TwinMemDeclare.subst(iop) + TwinMemDeclare.subst(iop_imm)
+        decoder_output = TwinMemConstructor.subst(iop) + TwinMemConstructor.subst(iop_imm)
+        decode_block = ROrImmDecode.subst(iop)
+        matcher = re.compile(r'RdTwin')
+        exec_output = ''
+        for microPc in range(2):
+            flag_code = ''
+            pcedCode = ''
+            if (microPc == 1):
+                flag_code = "flags[IsLastMicroOp] = true;"
+                pcedCode = matcher.sub("RdHigh", code)
+            else:
+                flag_code = "flags[IsDelayedCommit] = true;"
+                pcedCode = matcher.sub("RdLow", code)
+            iop = InstObjParams(name, Name, 'TwinMem', pcedCode,
+                    opt_flags, {"ea_code": addrCalcReg,
+                    "fault_check": faultCode, "micro_pc": microPc,
+                    "set_flags": flag_code})
+            iop_imm = InstObjParams(name, Name + 'Imm', 'TwinMemImm', pcedCode,
+                    opt_flags, {"ea_code": addrCalcImm,
+                    "fault_check": faultCode, "micro_pc": microPc,
+                    "set_flags": flag_code})
+            decoder_output += BlockMemMicroConstructor.subst(iop)
+            decoder_output += BlockMemMicroConstructor.subst(iop_imm)
+            exec_output += doDualSplitExecute(
+                    pcedCode, addrCalcReg, addrCalcImm, execute, faultCode,
+                    makeMicroName(name, microPc),
+                    makeMicroName(name + "Imm", microPc),
+                    makeMicroName(Name, microPc),
+                    makeMicroName(Name + "Imm", microPc),
+                    asi, opt_flags);
+            faultCode = ''
+        return (header_output, decoder_output, exec_output, decode_block)
+
 }};
 
 def format BlockLoad(code, asi, *opt_flags) {{
@@ -337,3 +481,11 @@ def format BlockStore(code, asi, *opt_flags) {{
          decode_block) = doBlockMemFormat(code, faultCode,
              StoreExecute, name, Name, asi, opt_flags)
 }};
+
+def format TwinLoad(code, asi, *opt_flags) {{
+    faultCode = AlternateASIPrivFaultCheck + TwinAlignmentFaultCheck
+    (header_output,
+     decoder_output,
+     exec_output,
+     decode_block) = doTwinLoadFormat(code, faultCode, name, Name, asi, opt_flags)
+}};
index 3e9fd7a7dee9a01d4c78b436d808f22686640fa0..3f9146c21008774bd0271ba7517222cafd37aa19 100644 (file)
@@ -284,6 +284,12 @@ let {{
         else if(EA & 0x3f)
             fault = new MemAddressNotAligned;
     '''
+    TwinAlignmentFaultCheck = '''
+        if(RD & 0xe)
+            fault = new IllegalInstruction;
+        else if(EA & 0x1f)
+            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
index 80ed7362cb9be17114dbe9b884a0047b57d57d22..abb82f88c28a1a90a49f8e2838f5b560977ce846 100644 (file)
@@ -57,6 +57,9 @@ def operands {{
     # For clarity, descriptions that depend on unsigned behavior should
     # explicitly specify '.uq'.
     'Rd':              ('IntReg', 'udw', 'RD', 'IsInteger', 1),
+    # For microcoded twin load instructions, RdTwin appears in the "code"
+    # for the instruction and is replaced by RdLow or RdHigh by the format
+    # before it's processed by the iop.
     'RdLow':           ('IntReg', 'udw', 'RD & (~1)', 'IsInteger', 2),
     'RdHigh':          ('IntReg', 'udw', 'RD | 1', 'IsInteger', 3),
     'Rs1':             ('IntReg', 'udw', 'RS1', 'IsInteger', 4),