gcc: Clean-up of non-C++0x compliant code, first steps
[gem5.git] / src / arch / x86 / isa / macroop.isa
index 8453a4fe9322212cc31eee4a4fe8ba5f63753c60..94b17ff4c2cde2ee49691dffd14dfff97849a7f3 100644 (file)
@@ -3,43 +3,25 @@
 // Copyright (c) 2007 The Hewlett-Packard Development Company
 // All rights reserved.
 //
-// Redistribution and use of this software in source and binary forms,
-// with or without modification, are permitted provided that the
-// following conditions are met:
+// The license below extends only to copyright in the software and shall
+// not be construed as granting a license to any other intellectual
+// property including but not limited to intellectual property relating
+// to a hardware implementation of the functionality of the software
+// licensed hereunder.  You may use the software subject to the license
+// terms below provided that you ensure that this notice is replicated
+// unmodified and in its entirety in all distributions of the software,
+// modified or unmodified, in source code or in binary form.
 //
-// The software must be used only for Non-Commercial Use which means any
-// use which is NOT directed to receiving any direct monetary
-// compensation for, or commercial advantage from such use.  Illustrative
-// examples of non-commercial use are academic research, personal study,
-// teaching, education and corporate research & development.
-// Illustrative examples of commercial use are distributing products for
-// commercial advantage and providing services using the software for
-// commercial advantage.
-//
-// If you wish to use this software or functionality therein that may be
-// covered by patents for commercial use, please contact:
-//     Director of Intellectual Property Licensing
-//     Office of Strategy and Technology
-//     Hewlett-Packard Company
-//     1501 Page Mill Road
-//     Palo Alto, California  94304
-//
-// Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.  Redistributions
-// in binary form must reproduce the above copyright notice, this list of
-// conditions and the following disclaimer in the documentation and/or
-// other materials provided with the distribution.  Neither the name of
-// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
 // contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.  No right of
-// sublicense is granted herewith.  Derivatives of the software and
-// output created using the software may be prepared, but only for
-// Non-Commercial Uses.  Derivatives of the software may be shared with
-// others provided: (i) the others agree to abide by the list of
-// conditions herein which includes the Non-Commercial Use restrictions;
-// and (ii) such Derivatives of the software include the above copyright
-// notice to acknowledge the contribution from this software where
-// applicable, this list of conditions and the disclaimer below.
+// this software without specific prior written permission.
 //
 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
@@ -72,41 +54,13 @@ def template MacroExecPanic {{
 output header {{
 
         // Base class for combinationally generated macroops
-        class Macroop : public StaticInst
+        class Macroop : public X86ISA::MacroopBase
         {
-          protected:
-            const uint32_t numMicroops;
-
-            //Constructor.
+          public:
             Macroop(const char *mnem, ExtMachInst _machInst,
-                    uint32_t _numMicroops)
-                        : StaticInst(mnem, _machInst, No_OpClass),
-                        numMicroops(_numMicroops)
-            {
-                assert(numMicroops);
-                microops = new StaticInstPtr[numMicroops];
-                flags[IsMacroop] = true;
-            }
-
-            ~Macroop()
-            {
-                delete [] microops;
-            }
-
-            StaticInstPtr * microops;
-
-            StaticInstPtr fetchMicroop(MicroPC microPC)
-            {
-                assert(microPC < numMicroops);
-                return microops[microPC];
-            }
-
-            std::string generateDisassembly(Addr pc,
-                    const SymbolTable *symtab) const
-            {
-                return mnemonic;
-            }
-
+                    uint32_t _numMicroops, X86ISA::EmulEnv _env)
+                        : MacroopBase(mnem, _machInst, _numMicroops, _env)
+            {}
             %(MacroExecPanic)s
         };
 }};
@@ -126,22 +80,46 @@ def template MacroDeclare {{
              */
             class %(class_name)s : public %(base_class)s
             {
+              private:
+                %(declareLabels)s
               public:
                 // Constructor.
-                %(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv env);
+                %(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv _env);
+
+                std::string
+                generateDisassembly(Addr pc, const SymbolTable *symtab) const;
             };
-        };
+        }
+}};
+
+def template MacroDisassembly {{
+    std::string
+    X86Macroop::%(class_name)s::generateDisassembly(Addr pc,
+            const SymbolTable *symtab) const
+    {
+        std::stringstream out;
+        out << mnemonic << "\t";
+
+        int regSize = %(regSize)s;
+        %(disassembly)s
+        // Shut up gcc.
+        regSize = regSize;
+        return out.str();
+    }
 }};
 
 // Basic instruction class constructor template.
 def template MacroConstructor {{
         inline X86Macroop::%(class_name)s::%(class_name)s(
-                ExtMachInst machInst, EmulEnv env)
-            : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s)
+                ExtMachInst machInst, EmulEnv _env)
+            : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s, _env)
         {
             %(adjust_env)s;
-            %(do_modrm)s;
+            %(adjust_imm)s;
+            %(adjust_disp)s;
+            %(init_env)s;
             %(constructor)s;
+            const char *macrocodeBlock = "%(class_name)s";
             //alloc_microops is the code that sets up the microops
             //array in the parent class.
             %(alloc_microops)s;
@@ -151,42 +129,102 @@ def template MacroConstructor {{
 let {{
     from micro_asm import Combinational_Macroop, Rom_Macroop
     class X86Macroop(Combinational_Macroop):
+        def add_microop(self, mnemonic, microop):
+            microop.mnemonic = mnemonic
+            microop.micropc = len(self.microops)
+            self.microops.append(microop)
         def setAdjustEnv(self, val):
             self.adjust_env = val
+        def adjustImm(self, val):
+            self.adjust_imm += val
+        def adjustDisp(self, val):
+            self.adjust_disp += val
+        def serializing(self):
+            self.serializing = True
         def __init__(self, name):
             super(X86Macroop, self).__init__(name)
             self.directives = {
-                "adjust_env" : self.setAdjustEnv
+                "adjust_env" : self.setAdjustEnv,
+                "adjust_imm" : self.adjustImm,
+                "adjust_disp" : self.adjustDisp,
+                "serializing" : self.serializing
             }
             self.declared = False
             self.adjust_env = ""
-            self.doModRM = ""
+            self.init_env = ""
+            self.adjust_imm = '''
+                uint64_t adjustedImm = IMMEDIATE;
+                //This is to pacify gcc in case the immediate isn't used.
+                adjustedImm = adjustedImm;
+            '''
+            self.adjust_disp = '''
+                uint64_t adjustedDisp = DISPLACEMENT;
+                //This is to pacify gcc in case the displacement isn't used.
+                adjustedDisp = adjustedDisp;
+            '''
+            self.serializing = False
         def getAllocator(self, env):
-            return "new X86Macroop::%s(machInst, %s)" % (self.name, env.getAllocator())
+            return "new X86Macroop::%s(machInst, %s)" % \
+                    (self.name, env.getAllocator())
+        def getMnemonic(self):
+            mnemonic = self.name.lower()
+            mnemonic = re.match(r'[^_]*', mnemonic).group(0)
+            return mnemonic
         def getDeclaration(self):
             #FIXME This first parameter should be the mnemonic. I need to
             #write some code which pulls that out
-            iop = InstObjParams(self.name, self.name, "Macroop", {"code" : ""})
+            declareLabels = ""
+            for (label, microop) in self.labels.items():
+                declareLabels += "const static uint64_t label_%s = %d;\n" \
+                                  % (label, microop.micropc)
+            iop = InstObjParams(self.getMnemonic(), self.name, "Macroop",
+                    {"code" : "",
+                     "declareLabels" : declareLabels
+                    })
             return MacroDeclare.subst(iop);
-        def getDefinition(self):
+        def getDefinition(self, env):
             #FIXME This first parameter should be the mnemonic. I need to
             #write some code which pulls that out
             numMicroops = len(self.microops)
             allocMicroops = ''
             micropc = 0
             for op in self.microops:
+                flags = ["IsMicroop"]
+                if micropc == numMicroops - 1:
+                    flags.append("IsLastMicroop")
+                    if self.serializing:
+                        flags.append("IsSerializing")
+                        flags.append("IsSerializeAfter")
+                else:
+                    flags.append("IsDelayedCommit")
+                if micropc == 0:
+                    flags.append("IsFirstMicroop")
                 allocMicroops += \
                     "microops[%d] = %s;\n" % \
-                    (micropc, op.getAllocator(True, False,
-                                              micropc == 0,
-                                              micropc == numMicroops - 1))
+                    (micropc, op.getAllocator(flags))
                 micropc += 1
-            iop = InstObjParams(self.name, self.name, "Macroop",
+            if env.useStackSize:
+                useStackSize = "true"
+            else:
+                useStackSize = "false"
+            if env.memoryInst:
+                memoryInst = "true"
+            else:
+                memoryInst = "false"
+            regSize = '''(%s || (env.base == INTREG_RSP && %s) ?
+                         env.stackSize :
+                         env.dataSize)''' % (useStackSize, memoryInst)
+            iop = InstObjParams(self.getMnemonic(), self.name, "Macroop",
                                 {"code" : "", "num_microops" : numMicroops,
                                  "alloc_microops" : allocMicroops,
                                  "adjust_env" : self.adjust_env,
-                                 "do_modrm" : self.doModRM})
-            return MacroConstructor.subst(iop);
+                                 "adjust_imm" : self.adjust_imm,
+                                 "adjust_disp" : self.adjust_disp,
+                                 "disassembly" : env.disassembly,
+                                 "regSize" : regSize,
+                                 "init_env" : self.initEnv})
+            return MacroConstructor.subst(iop) + \
+                   MacroDisassembly.subst(iop);
 }};
 
 let {{
@@ -196,18 +234,50 @@ let {{
             self.regUsed = False
             self.regm = "0"
             self.regmUsed = False
+            self.seg = "SEGMENT_REG_DS"
+            self.size = None
             self.addressSize = "ADDRSIZE"
             self.dataSize = "OPSIZE"
             self.stackSize = "STACKSIZE"
             self.doModRM = False
+            self.disassembly = ""
+            self.firstArgument = True
+            self.useStackSize = False
+            self.memoryInst = False
+
+        def addToDisassembly(self, code):
+            if not self.firstArgument:
+                self.disassembly += "out << \", \";\n"
+            self.firstArgument = False
+            self.disassembly += code
 
         def getAllocator(self):
+            if self.size == 'b':
+                self.dataSize = 1
+            elif self.size == 'd':
+                self.dataSize = 4
+            #This is for "double plus" which is normally a double word unless
+            #the REX W bit is set, in which case it's a quad word. It's used
+            #for some SSE instructions.
+            elif self.size == 'dp':
+                self.dataSize = "(REX_W ? 8 : 4)"
+            elif self.size == 'q':
+                self.dataSize = 8
+            elif self.size == 'v':
+                self.dataSize = "OPSIZE"
+            elif self.size == 'w':
+                self.dataSize = 2
+            elif self.size == 'z':
+                self.dataSize = "((OPSIZE == 8) ? 4 : OPSIZE)"
+            elif self.size:
+                raise Exception, "Unrecognized size type %s!" % self.size
             return '''EmulEnv(%(reg)s,
                               %(regm)s,
                               %(dataSize)s,
                               %(addressSize)s,
                               %(stackSize)s)''' % \
                 self.__dict__
+
         def addReg(self, reg):
             if not self.regUsed:
                 self.reg = reg
@@ -217,10 +287,18 @@ let {{
                 self.regmUsed = True
             else:
                 raise Exception, "EmulEnv is out of register specialization spots."
+        def setSize(self, size):
+            if not self.size:
+                self.size = size
+            else:
+                if self.size != size:
+                    raise Exception, "Conflicting register sizes %s and %s!" %\
+                        (self.size, size)
 }};
 
 let {{
     doModRMString = "env.doModRM(machInst);\n"
+    noModRMString = "env.setSeg(machInst);\n"
     def genMacroop(Name, env):
         blocks = OutputBlocks()
         if not macroopDict.has_key(Name):
@@ -228,9 +306,11 @@ let {{
         macroop = macroopDict[Name]
         if not macroop.declared:
             if env.doModRM:
-                macroop.doModRM = doModRMString
+                macroop.initEnv = doModRMString
+            else:
+                macroop.initEnv = noModRMString
             blocks.header_output = macroop.getDeclaration()
-            blocks.decoder_output = macroop.getDefinition()
+            blocks.decoder_output = macroop.getDefinition(env)
             macroop.declared = True
         blocks.decode_block = "return %s;\n" % macroop.getAllocator(env)
         return blocks