arch: teach ISA parser how to split code across files
[gem5.git] / src / arch / sparc / isa / base.isa
index 122ad2b5202bd5b738e9550c09b7089b9eb1a489..3c95c26383a090ac6af520330d8902b5a63e5ee7 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (c) 2006 The Regents of The University of Michigan
+// Copyright (c) 2006-2007 The Regents of The University of Michigan
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -67,7 +67,27 @@ output header {{
             OverflowSet=0x7
         };
 
-        extern char * CondTestAbbrev[];
+        enum FpCondTest
+        {
+            FAlways=0x8,
+            FNever=0x0,
+            FUnordered=0x7,
+            FGreater=0x6,
+            FUnorderedOrGreater=0x5,
+            FLess=0x4,
+            FUnorderedOrLess=0x3,
+            FLessOrGreater=0x2,
+            FNotEqual=0x1,
+            FEqual=0x9,
+            FUnorderedOrEqual=0xA,
+            FGreaterOrEqual=0xB,
+            FUnorderedOrGreaterOrEqual=0xC,
+            FLessOrEqual=0xD,
+            FUnorderedOrLessOrEqual=0xE,
+            FOrdered=0xF
+        };
+
+        extern const char *CondTestAbbrev[];
 
         /**
          * Base class for all SPARC static instructions.
@@ -91,11 +111,16 @@ output header {{
 
             void printRegArray(std::ostream &os,
                 const RegIndex indexArray[], int num) const;
+
+            void advancePC(SparcISA::PCState &pcState) const;
         };
 
+        bool passesFpCondition(uint32_t fcc, uint32_t condition);
+
         bool passesCondition(uint32_t codes, uint32_t condition);
 
-        inline int64_t sign_ext(uint64_t data, int origWidth)
+        inline int64_t
+        sign_ext(uint64_t data, int origWidth)
         {
             int shiftAmount = 64 - origWidth;
             return (((int64_t)data) << shiftAmount) >> shiftAmount;
@@ -104,24 +129,24 @@ output header {{
 
 output decoder {{
 
-        char * CondTestAbbrev[] =
+        const char *CondTestAbbrev[] =
         {
-            "nev", //Never
-            "e", //Equal
-            "le", //Less or Equal
-            "l", //Less
-            "leu", //Less or Equal Unsigned
-            "c", //Carry set
-            "n", //Negative
-            "o", //Overflow set
-            "a", //Always
-            "ne", //Not Equal
-            "g", //Greater
-            "ge", //Greater or Equal
-            "gu", //Greater Unsigned
-            "cc", //Carry clear
-            "p", //Positive
-            "oc" //Overflow Clear
+            "nev", // Never
+            "e", // Equal
+            "le", // Less or Equal
+            "l", // Less
+            "leu", // Less or Equal Unsigned
+            "c", // Carry set
+            "n", // Negative
+            "o", // Overflow set
+            "a", // Always
+            "ne", // Not Equal
+            "g", // Greater
+            "ge", // Greater or Equal
+            "gu", // Greater Unsigned
+            "cc", // Carry clear
+            "p", // Positive
+            "oc" // Overflow Clear
         };
 }};
 
@@ -132,9 +157,79 @@ def template ROrImmDecode {{
     }
 }};
 
+output header {{
+    union DoubleSingle
+    {
+        double d;
+        uint64_t ui;
+        uint32_t s[2];
+        DoubleSingle(double _d) : d(_d)
+        {}
+        DoubleSingle(uint64_t _ui) : ui(_ui)
+        {}
+        DoubleSingle(uint32_t _s0, uint32_t _s1)
+        {
+            s[0] = _s0;
+            s[1] = _s1;
+        }
+    };
+}};
+
+let {{
+    def filterDoubles(code):
+        assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE)
+        for opName in ("Frd", "Frs1", "Frs2", "Frd_N"):
+            next_pos = 0
+            operandsREString = (r'''
+            (?<!\w)             # neg. lookbehind assertion: prevent partial matches
+            ((%s)(?:_([^\W_]+))?)   # match: operand with optional '.' then suffix
+            (?!\w)             # neg. lookahead assertion: prevent partial matches
+            ''' % opName)
+            operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE)
+            is_src = False
+            is_dest = False
+            extension = None
+            foundOne = False
+            while 1:
+                match = operandsRE.search(code, next_pos)
+                if not match:
+                    break
+                foundOne = True
+                op = match.groups()
+                (op_full, op_base, op_ext) = op
+                is_dest_local = (assignRE.match(code, match.end()) != None)
+                is_dest = is_dest or is_dest_local
+                is_src = is_src or not is_dest_local
+                if extension and extension != op_ext:
+                    raise Exception, "Inconsistent extensions in double filter."
+                extension = op_ext
+                next_pos = match.end()
+            if foundOne:
+                # Get rid of any unwanted extension
+                code = operandsRE.sub(op_base, code)
+                is_int = False
+                member = "d"
+                if extension in ("sb", "ub", "shw", "uhw", "sw", "uw", "sdw", "udw"):
+                    is_int = True
+                    member = "ui"
+                if is_src:
+                    code = ("%s = DoubleSingle(%s_high, %s_low).%s;" % \
+                        (opName, opName, opName, member)) + code
+                if is_dest:
+                    code += '''
+                        %s_low = DoubleSingle(%s).s[1];
+                        %s_high = DoubleSingle(%s).s[0];''' % \
+                             (opName, opName, opName, opName)
+                if is_int:
+                    code = ("uint64_t %s;" % opName) + code
+                else:
+                    code = ("double %s;" % opName) + code
+        return code
+}};
+
 let {{
     def splitOutImm(code):
-        matcher = re.compile(r'Rs(?P<rNum>\d)_or_imm(?P<iNum>\d+)(?P<typeQual>\.\w+)?')
+        matcher = re.compile(r'Rs(?P<rNum>\d)_or_imm(?P<iNum>\d+)(?P<typeQual>_[^\W_]+)?')
         rOrImmMatch = matcher.search(code)
         if (rOrImmMatch == None):
             return (False, code, '', '', '')
@@ -158,27 +253,32 @@ output decoder {{
         void SparcStaticInst::printRegArray(std::ostream &os,
             const RegIndex indexArray[], int num) const
         {
-            if(num <= 0)
+            if (num <= 0)
                 return;
             printReg(os, indexArray[0]);
-            for(int x = 1; x < num; x++)
-            {
+            for (int x = 1; x < num; x++) {
                 os << ", ";
                 printReg(os, indexArray[x]);
             }
         }
 
+        void
+        SparcStaticInst::advancePC(SparcISA::PCState &pcState) const
+        {
+            pcState.advance();
+        }
+
         void
         SparcStaticInst::printSrcReg(std::ostream &os, int reg) const
         {
-            if(_numSrcRegs > reg)
+            if (_numSrcRegs > reg)
                 printReg(os, _srcRegIdx[reg]);
         }
 
         void
         SparcStaticInst::printDestReg(std::ostream &os, int reg) const
         {
-            if(_numDestRegs > reg)
+            if (_numDestRegs > reg)
                 printReg(os, _destRegIdx[reg]);
         }
 
@@ -189,28 +289,155 @@ output decoder {{
             const int MaxOutput = 16;
             const int MaxLocal = 24;
             const int MaxInput = 32;
-            const int MaxMicroReg = 33;
-            if (reg == FramePointerReg)
-                ccprintf(os, "%%fp");
-            else if (reg == StackPointerReg)
-                ccprintf(os, "%%sp");
-            else if(reg < MaxGlobal)
-                ccprintf(os, "%%g%d", reg);
-            else if(reg < MaxOutput)
-                ccprintf(os, "%%o%d", reg - MaxGlobal);
-            else if(reg < MaxLocal)
-                ccprintf(os, "%%l%d", reg - MaxOutput);
-            else if(reg < MaxInput)
-                ccprintf(os, "%%i%d", reg - MaxLocal);
-            else if(reg < MaxMicroReg)
-                ccprintf(os, "%%u%d", reg - MaxInput);
-            else {
-                ccprintf(os, "%%f%d", reg - FP_Base_DepTag);
+            const int MaxMicroReg = 40;
+            if (reg < FP_Reg_Base) {
+                // If we used a register from the next or previous window,
+                // take out the offset.
+                while (reg >= MaxMicroReg)
+                    reg -= MaxMicroReg;
+                if (reg == FramePointerReg)
+                    ccprintf(os, "%%fp");
+                else if (reg == StackPointerReg)
+                    ccprintf(os, "%%sp");
+                else if (reg < MaxGlobal)
+                    ccprintf(os, "%%g%d", reg);
+                else if (reg < MaxOutput)
+                    ccprintf(os, "%%o%d", reg - MaxGlobal);
+                else if (reg < MaxLocal)
+                    ccprintf(os, "%%l%d", reg - MaxOutput);
+                else if (reg < MaxInput)
+                    ccprintf(os, "%%i%d", reg - MaxLocal);
+                else if (reg < MaxMicroReg)
+                    ccprintf(os, "%%u%d", reg - MaxInput);
+                // The fake int regs that are really control regs
+                else {
+                    switch (reg - MaxMicroReg) {
+                      case 1:
+                        ccprintf(os, "%%y");
+                        break;
+                      case 2:
+                        ccprintf(os, "%%ccr");
+                        break;
+                      case 3:
+                        ccprintf(os, "%%cansave");
+                        break;
+                      case 4:
+                        ccprintf(os, "%%canrestore");
+                        break;
+                      case 5:
+                        ccprintf(os, "%%cleanwin");
+                        break;
+                      case 6:
+                        ccprintf(os, "%%otherwin");
+                        break;
+                      case 7:
+                        ccprintf(os, "%%wstate");
+                        break;
+                    }
+                }
+            } else if (reg < Misc_Reg_Base) {
+                ccprintf(os, "%%f%d", reg - FP_Reg_Base);
+            } else {
+                switch (reg - Misc_Reg_Base) {
+                  case MISCREG_ASI:
+                    ccprintf(os, "%%asi");
+                    break;
+                  case MISCREG_FPRS:
+                    ccprintf(os, "%%fprs");
+                    break;
+                  case MISCREG_PCR:
+                    ccprintf(os, "%%pcr");
+                    break;
+                  case MISCREG_PIC:
+                    ccprintf(os, "%%pic");
+                    break;
+                  case MISCREG_GSR:
+                    ccprintf(os, "%%gsr");
+                    break;
+                  case MISCREG_SOFTINT:
+                    ccprintf(os, "%%softint");
+                    break;
+                  case MISCREG_SOFTINT_SET:
+                    ccprintf(os, "%%softint_set");
+                    break;
+                  case MISCREG_SOFTINT_CLR:
+                    ccprintf(os, "%%softint_clr");
+                    break;
+                  case MISCREG_TICK_CMPR:
+                    ccprintf(os, "%%tick_cmpr");
+                    break;
+                  case MISCREG_STICK:
+                    ccprintf(os, "%%stick");
+                    break;
+                  case MISCREG_STICK_CMPR:
+                    ccprintf(os, "%%stick_cmpr");
+                    break;
+                  case MISCREG_TPC:
+                    ccprintf(os, "%%tpc");
+                    break;
+                  case MISCREG_TNPC:
+                    ccprintf(os, "%%tnpc");
+                    break;
+                  case MISCREG_TSTATE:
+                    ccprintf(os, "%%tstate");
+                    break;
+                  case MISCREG_TT:
+                    ccprintf(os, "%%tt");
+                    break;
+                  case MISCREG_TICK:
+                    ccprintf(os, "%%tick");
+                    break;
+                  case MISCREG_TBA:
+                    ccprintf(os, "%%tba");
+                    break;
+                  case MISCREG_PSTATE:
+                    ccprintf(os, "%%pstate");
+                    break;
+                  case MISCREG_TL:
+                    ccprintf(os, "%%tl");
+                    break;
+                  case MISCREG_PIL:
+                    ccprintf(os, "%%pil");
+                    break;
+                  case MISCREG_CWP:
+                    ccprintf(os, "%%cwp");
+                    break;
+                  case MISCREG_GL:
+                    ccprintf(os, "%%gl");
+                    break;
+                  case MISCREG_HPSTATE:
+                    ccprintf(os, "%%hpstate");
+                    break;
+                  case MISCREG_HTSTATE:
+                    ccprintf(os, "%%htstate");
+                    break;
+                  case MISCREG_HINTP:
+                    ccprintf(os, "%%hintp");
+                    break;
+                  case MISCREG_HTBA:
+                    ccprintf(os, "%%htba");
+                    break;
+                  case MISCREG_HSTICK_CMPR:
+                    ccprintf(os, "%%hstick_cmpr");
+                    break;
+                  case MISCREG_HVER:
+                    ccprintf(os, "%%hver");
+                    break;
+                  case MISCREG_STRAND_STS_REG:
+                    ccprintf(os, "%%strand_sts_reg");
+                    break;
+                  case MISCREG_FSR:
+                    ccprintf(os, "%%fsr");
+                    break;
+                  default:
+                    ccprintf(os, "%%ctrl%d", reg - Misc_Reg_Base);
+                }
             }
         }
 
-        std::string SparcStaticInst::generateDisassembly(Addr pc,
-            const SymbolTable *symtab) const
+        std::string
+        SparcStaticInst::generateDisassembly(Addr pc,
+                const SymbolTable *symtab) const
         {
             std::stringstream ss;
 
@@ -219,21 +446,17 @@ output decoder {{
             // just print the first two source regs... if there's
             // a third one, it's a read-modify-write dest (Rc),
             // e.g. for CMOVxx
-            if(_numSrcRegs > 0)
-            {
+            if (_numSrcRegs > 0)
                 printReg(ss, _srcRegIdx[0]);
-            }
-            if(_numSrcRegs > 1)
-            {
+            if (_numSrcRegs > 1) {
                 ss << ",";
                 printReg(ss, _srcRegIdx[1]);
             }
 
             // just print the first dest... if there's a second one,
             // it's generally implicit
-            if(_numDestRegs > 0)
-            {
-                if(_numSrcRegs > 0)
+            if (_numDestRegs > 0) {
+                if (_numSrcRegs > 0)
                     ss << ",";
                     printReg(ss, _destRegIdx[0]);
             }
@@ -241,12 +464,62 @@ output decoder {{
             return ss.str();
         }
 
-        bool passesCondition(uint32_t codes, uint32_t condition)
+        bool
+        passesFpCondition(uint32_t fcc, uint32_t condition)
+        {
+            bool u = (fcc == 3);
+            bool g = (fcc == 2);
+            bool l = (fcc == 1);
+            bool e = (fcc == 0);
+            switch (condition) {
+              case FAlways:
+                return 1;
+              case FNever:
+                return 0;
+              case FUnordered:
+                return u;
+              case FGreater:
+                return g;
+              case FUnorderedOrGreater:
+                return u || g;
+              case FLess:
+                return l;
+              case FUnorderedOrLess:
+                return u || l;
+              case FLessOrGreater:
+                return l || g;
+              case FNotEqual:
+                return l || g || u;
+              case FEqual:
+                return e;
+              case FUnorderedOrEqual:
+                return u || e;
+              case FGreaterOrEqual:
+                return g || e;
+              case FUnorderedOrGreaterOrEqual:
+                return u || g || e;
+              case FLessOrEqual:
+                return l || e;
+              case FUnorderedOrLessOrEqual:
+                return u || l || e;
+              case FOrdered:
+                return e || l || g;
+            }
+            panic("Tried testing condition nonexistant "
+                    "condition code %d", condition);
+        }
+
+        bool
+        passesCondition(uint32_t codes, uint32_t condition)
         {
             CondCodes condCodes;
-            condCodes.bits = codes;
-            switch(condition)
-            {
+            condCodes.bits =  0;
+            condCodes.c = codes & 0x1 ? 1 : 0;
+            condCodes.v = codes & 0x2 ? 1 : 0;
+            condCodes.z = codes & 0x4 ? 1 : 0;
+            condCodes.n = codes & 0x8 ? 1 : 0;
+
+            switch (condition) {
               case Always:
                 return true;
               case Never:
@@ -285,3 +558,25 @@ output decoder {{
         }
 }};
 
+output exec {{
+    /// Check "FP enabled" machine status bit.  Called when executing any FP
+    /// instruction.
+    /// @retval Full-system mode: NoFault if FP is enabled, FpDisabled
+    /// if not.  Non-full-system mode: always returns NoFault.
+    static inline Fault
+    checkFpEnableFault(CPU_EXEC_CONTEXT *xc)
+    {
+        if (FullSystem) {
+            PSTATE pstate = xc->readMiscReg(MISCREG_PSTATE);
+            if (pstate.pef && xc->readMiscReg(MISCREG_FPRS) & 0x4) {
+                return NoFault;
+            } else {
+                return new FpDisabled;
+            }
+        } else {
+            return NoFault;
+        }
+    }
+}};
+
+