Make the predecoder an object with it's own switched header file. Start adding predec...
authorGabe Black <gblack@eecs.umich.edu>
Thu, 15 Mar 2007 02:47:42 +0000 (02:47 +0000)
committerGabe Black <gblack@eecs.umich.edu>
Thu, 15 Mar 2007 02:47:42 +0000 (02:47 +0000)
src/arch/SConscript:
src/arch/alpha/utility.hh:
src/arch/mips/utility.hh:
src/arch/sparc/utility.hh:
src/cpu/base.hh:
src/cpu/o3/fetch.hh:
src/cpu/o3/fetch_impl.hh:
src/cpu/simple/atomic.cc:
src/cpu/simple/base.cc:
src/cpu/simple/base.hh:
src/cpu/static_inst.hh:
src/arch/alpha/predecoder.hh:
src/arch/mips/predecoder.hh:
src/arch/sparc/predecoder.hh:
    Make the predecoder an object with it's own switched header file.

--HG--
extra : convert_revision : 77206e29089130e86b97164c30022a062699ba86

20 files changed:
src/arch/SConscript
src/arch/alpha/predecoder.hh [new file with mode: 0644]
src/arch/alpha/utility.hh
src/arch/mips/predecoder.hh [new file with mode: 0644]
src/arch/mips/utility.hh
src/arch/sparc/predecoder.hh [new file with mode: 0644]
src/arch/sparc/utility.hh
src/arch/x86/SConscript
src/arch/x86/isa/formats/unknown.isa
src/arch/x86/predecoder.hh [new file with mode: 0644]
src/arch/x86/predecoder_tables.cc [new file with mode: 0644]
src/arch/x86/types.hh
src/arch/x86/utility.hh
src/cpu/base.hh
src/cpu/o3/fetch.hh
src/cpu/o3/fetch_impl.hh
src/cpu/simple/atomic.cc
src/cpu/simple/base.cc
src/cpu/simple/base.hh
src/cpu/static_inst.hh

index 74be5f8d1c88f235b5bb9e82e53b3ba1b2b10c39..77fbc6e6fe696be9acdd5082db005bc15fb35d1a 100644 (file)
@@ -55,6 +55,7 @@ isa_switch_hdrs = Split('''
         locked_mem.hh
         mmaped_ipr.hh
        process.hh
+       predecoder.hh
        regfile.hh
        remote_gdb.hh
        stacktrace.hh
diff --git a/src/arch/alpha/predecoder.hh b/src/arch/alpha/predecoder.hh
new file mode 100644 (file)
index 0000000..4e89f53
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#ifndef __ARCH_ALPHA_PREDECODER_HH__
+#define __ARCH_ALPHA_PREDECODER_HH__
+
+#include "arch/alpha/types.hh"
+#include "base/misc.hh"
+#include "sim/host.hh"
+
+class ThreadContext;
+
+namespace AlphaISA
+{
+    class Predecoder
+    {
+      protected:
+        ThreadContext * tc;
+        //The pc of the current instruction
+        Addr fetchPC;
+        //The extended machine instruction being generated
+        ExtMachInst ext_inst;
+
+      public:
+        Predecoder(ThreadContext * _tc) : tc(_tc)
+        {}
+
+        ThreadContext * getTC()
+        {
+            return tc;
+        }
+
+        void setTC(ThreadContext * _tc)
+        {
+            tc = _tc;
+        }
+
+        void process()
+        {
+        }
+
+        //Use this to give data to the predecoder. This should be used
+        //when there is control flow.
+        void moreBytes(Addr pc, Addr off, MachInst inst)
+        {
+            fetchPC = pc;
+            assert(off == 0);
+            ext_inst = inst;
+#if FULL_SYSTEM
+            if (pc && 0x1)
+                ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32);
+#endif
+        }
+
+        //Use this to give data to the predecoder. This should be used
+        //when instructions are executed in order.
+        void moreBytes(MachInst machInst)
+        {
+            moreBytes(fetchPC + sizeof(machInst), 0, machInst);
+        }
+
+        bool needMoreBytes()
+        {
+            return true;
+        }
+
+        bool extMachInstReady()
+        {
+            return true;
+        }
+
+        //This returns a constant reference to the ExtMachInst to avoid a copy
+        const ExtMachInst & getExtMachInst()
+        {
+            return ext_inst;
+        }
+    };
+};
+
+#endif // __ARCH_ALPHA_PREDECODER_HH__
index e4b8368a8a9cbce3d9676e6ca899d8b063d0f6ac..95d52c3fec70c047ea416d33c070594f0e36f70f 100644 (file)
@@ -48,21 +48,6 @@ namespace AlphaISA
         return (tc->readMiscRegNoEffect(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
     }
 
-    enum PredecodeResult {
-        MoreBytes = 1,
-        ExtMIReady = 2
-    };
-
-    static inline unsigned int
-    predecode(ExtMachInst & ext_inst, Addr pc, MachInst inst, ThreadContext *) {
-        ext_inst = inst;
-#if FULL_SYSTEM
-        if (pc && 0x1)
-            ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32);
-#endif
-        return MoreBytes | ExtMIReady;
-    }
-
     inline bool isCallerSaveIntegerRegister(unsigned int reg) {
         panic("register classification not implemented");
         return (reg >= 1 && reg <= 8 || reg >= 22 && reg <= 25 || reg == 27);
diff --git a/src/arch/mips/predecoder.hh b/src/arch/mips/predecoder.hh
new file mode 100644 (file)
index 0000000..a25cce8
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#ifndef __ARCH_MIPS_PREDECODER_HH__
+#define __ARCH_MIPS_PREDECODER_HH__
+
+#include "arch/mips/types.hh"
+#include "base/misc.hh"
+#include "sim/host.hh"
+
+class ThreadContext;
+
+namespace MipsISA
+{
+    class Predecoder
+    {
+      protected:
+        ThreadContext * tc;
+        //The extended machine instruction being generated
+        ExtMachInst emi;
+
+      public:
+        Predecoder(ThreadContext * _tc) : tc(_tc)
+        {}
+
+        ThreadContext * getTC()
+        {
+            return tc;
+        }
+
+        void setTC(ThreadContext * _tc)
+        {
+            tc = _tc;
+        }
+
+        void process()
+        {
+        }
+
+        //Use this to give data to the predecoder. This should be used
+        //when there is control flow.
+        void moreBytes(Addr currPC, Addr off, MachInst inst)
+        {
+            assert(off == 0);
+            emi = inst;
+        }
+
+        //Use this to give data to the predecoder. This should be used
+        //when instructions are executed in order.
+        void moreBytes(MachInst machInst)
+        {
+            moreBytes(0, 0, machInst);
+        }
+
+        bool needMoreBytes()
+        {
+            return true;
+        }
+
+        bool extMachInstReady()
+        {
+            return true;
+        }
+
+        //This returns a constant reference to the ExtMachInst to avoid a copy
+        const ExtMachInst & getExtMachInst()
+        {
+            return emi;
+        }
+    };
+};
+
+#endif // __ARCH_MIPS_PREDECODER_HH__
index 26cac942711ea147d17332f41b9cd045390adf70..609f4b071becb482388518580382fa6c2598c20e 100644 (file)
@@ -87,17 +87,6 @@ namespace MipsISA {
         panic("makeRegisterCopy not implemented");
         return 0;
     }
-
-    enum PredecodeResult {
-        MoreBytes = 1,
-        ExtMIReady = 2
-    };
-
-    static inline unsigned int
-    predecode(ExtMachInst &emi, Addr, MachInst inst, ThreadContext *) {
-        emi = inst;
-        return MoreBytes | ExtMIReady;
-    }
 };
 
 
diff --git a/src/arch/sparc/predecoder.hh b/src/arch/sparc/predecoder.hh
new file mode 100644 (file)
index 0000000..71b14b0
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#ifndef __ARCH_SPARC_PREDECODER_HH__
+#define __ARCH_SPARC_PREDECODER_HH__
+
+#include "arch/sparc/types.hh"
+#include "base/misc.hh"
+#include "sim/host.hh"
+
+class ThreadContext;
+
+namespace SparcISA
+{
+    class Predecoder
+    {
+      protected:
+        ThreadContext * tc;
+        //The extended machine instruction being generated
+        ExtMachInst emi;
+
+      public:
+        Predecoder(ThreadContext * _tc) : tc(_tc)
+        {}
+
+        ThreadContext * getTC()
+        {
+            return tc;
+        }
+
+        void setTC(ThreadContext * _tc)
+        {
+            tc = _tc;
+        }
+
+        void process()
+        {
+        }
+
+        //Use this to give data to the predecoder. This should be used
+        //when there is control flow.
+        void moreBytes(Addr currPC, Addr off, MachInst inst)
+        {
+            assert(off == 0);
+
+            emi = inst;
+            //The I bit, bit 13, is used to figure out where the ASI
+            //should come from. Use that in the ExtMachInst. This is
+            //slightly redundant, but it removes the need to put a condition
+            //into all the execute functions
+            if(inst & (1 << 13))
+                emi |= (static_cast<ExtMachInst>(
+                            tc->readMiscRegNoEffect(MISCREG_ASI))
+                        << (sizeof(MachInst) * 8));
+            else
+                emi |= (static_cast<ExtMachInst>(bits(inst, 12, 5))
+                        << (sizeof(MachInst) * 8));
+        }
+
+        //Use this to give data to the predecoder. This should be used
+        //when instructions are executed in order.
+        void moreBytes(MachInst machInst)
+        {
+            moreBytes(0, 0, machInst);
+        }
+
+        bool needMoreBytes()
+        {
+            return true;
+        }
+
+        bool extMachInstReady()
+        {
+            return true;
+        }
+
+        //This returns a constant reference to the ExtMachInst to avoid a copy
+        const ExtMachInst & getExtMachInst()
+        {
+            return emi;
+        }
+    };
+};
+
+#endif // __ARCH_SPARC_PREDECODER_HH__
index 4b662b5ac9857beb0cba08ab3fad27349c2e7b4b..278b39fb7d6f0eba773cdfc3840a3fc5595ca4a3 100644 (file)
@@ -48,28 +48,6 @@ namespace SparcISA
                 tc->readMiscRegNoEffect(MISCREG_HPSTATE & (1 << 2)));
     }
 
-    enum PredecodeResult {
-        MoreBytes = 1,
-        ExtMIReady = 2
-    };
-
-    inline unsigned int
-    predecode(ExtMachInst &emi, Addr currPC, MachInst inst,
-            ThreadContext * xc) {
-        emi = inst;
-        //The I bit, bit 13, is used to figure out where the ASI
-        //should come from. Use that in the ExtMachInst. This is
-        //slightly redundant, but it removes the need to put a condition
-        //into all the execute functions
-        if(inst & (1 << 13))
-            emi |= (static_cast<ExtMachInst>(xc->readMiscRegNoEffect(MISCREG_ASI))
-                    << (sizeof(MachInst) * 8));
-        else
-            emi |= (static_cast<ExtMachInst>(bits(inst, 12, 5))
-                    << (sizeof(MachInst) * 8));
-        return MoreBytes | ExtMIReady;
-    }
-
     inline bool isCallerSaveIntegerRegister(unsigned int reg) {
         panic("register classification not implemented");
         return false;
index fff29ba8969abb0ad3fcda8a70376fce5c380e22..8be59e0c00c848adcdcefaad00ad517bdc3faeea 100644 (file)
@@ -103,6 +103,7 @@ base_sources = Split('''
        miscregfile.cc
        regfile.cc
        remote_gdb.cc
+       predecoder_tables.cc
        ''')
 
 # Full-system sources
index 605ddcb6951bd4624a8ce79a1925edeb3844c2de..43ddc20c1a6b5a162e656c417ffc0ddcc7a4c660 100644 (file)
@@ -120,7 +120,8 @@ output exec {{
         Fault Unknown::execute(%(CPU_exec_context)s *xc,
                 Trace::InstRecord *traceData) const
         {
-            panic("No instructions are implemented for X86!\n");
+            warn("No instructions are implemented for X86!\n");
+            return NoFault;
         }
 }};
 
diff --git a/src/arch/x86/predecoder.hh b/src/arch/x86/predecoder.hh
new file mode 100644 (file)
index 0000000..371ce9d
--- /dev/null
@@ -0,0 +1,412 @@
+/*
+ * 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 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
+ * 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 IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#ifndef __ARCH_X86_PREDECODER_HH__
+#define __ARCH_X86_PREDECODER_HH__
+
+#include "arch/x86/types.hh"
+#include "base/bitfield.hh"
+#include "base/misc.hh"
+#include "sim/host.hh"
+
+class ThreadContext;
+
+namespace X86ISA
+{
+    class Predecoder
+    {
+      private:
+        static const uint8_t Prefixes[256];
+        static const uint8_t UsesModRM[2][256];
+
+      protected:
+        ThreadContext * tc;
+        //The bytes to be predecoded
+        MachInst fetchChunk;
+        //The pc of the start of fetchChunk
+        Addr basePC;
+        //The offset into fetchChunk of current processing
+        int offset;
+        //The extended machine instruction being generated
+        ExtMachInst emi;
+
+        //State machine state
+      protected:
+        //Whether or not we're out of bytes
+        bool outOfBytes;
+        //Whether we've completed generating an ExtMachInst
+        bool emiIsReady;
+        //The size of the displacement value
+        int displacementSize;
+        int displacementCollected;
+        //The size of the immediate value
+        int immediateSize;
+        int immediateCollected;
+
+        //These are local to some of the states. I need to turn the states
+        //into inline functions to clean things up a bit.
+        int toGet;
+        int remaining;
+        MachInst partialDisp;
+
+        enum State {
+            Prefix,
+            Opcode,
+            ModRM,
+            SIB,
+            Displacement,
+            Immediate
+        };
+
+        State state;
+
+      public:
+        Predecoder(ThreadContext * _tc) :
+            tc(_tc), basePC(0), offset(0),
+            outOfBytes(true), emiIsReady(false),
+            state(Prefix)
+        {}
+
+        ThreadContext * getTC()
+        {
+            return tc;
+        }
+
+        void setTC(ThreadContext * _tc)
+        {
+            tc = _tc;
+        }
+
+        void process()
+        {
+            warn("About to process some bytes\n");
+            assert(!outOfBytes);
+            assert(!emiIsReady);
+            while(!emiIsReady && !outOfBytes)
+            {
+                uint8_t nextByte = (fetchChunk >> (offset * 8)) & 0xff;
+                switch(state)
+                {
+                  case Prefix:
+                    uint8_t prefix = Prefixes[nextByte];
+                    switch(prefix)
+                    {
+                        //Operand size override prefixes
+                      case OperandSizeOverride:
+                        warn("Found operand size override prefix!\n");
+                        offset++;
+                        break;
+                      case AddressSizeOverride:
+                        warn("Found address size override prefix!\n");
+                        offset++;
+                        break;
+                        //Segment override prefixes
+                      case CSOverride:
+                        warn("Found cs segment override!\n");
+                        offset++;
+                        break;
+                      case DSOverride:
+                        warn("Found ds segment override!\n");
+                        offset++;
+                        break;
+                      case ESOverride:
+                        warn("Found es segment override!\n");
+                        offset++;
+                        break;
+                      case FSOverride:
+                        warn("Found fs segment override!\n");
+                        offset++;
+                        break;
+                      case GSOverride:
+                        warn("Found gs segment override!\n");
+                        offset++;
+                        break;
+                      case SSOverride:
+                        warn("Found ss segment override!\n");
+                        offset++;
+                        break;
+                      case Lock:
+                        warn("Found lock prefix!\n");
+                        offset++;
+                        break;
+                      case Rep:
+                        warn("Found rep prefix!\n");
+                        offset++;
+                        break;
+                      case Repne:
+                        warn("Found repne prefix!\n");
+                        offset++;
+                        break;
+                      case Rex:
+                        warn("Found Rex prefix %#x!\n", nextByte);
+                        offset++;
+                        break;
+                      case 0:
+                        emi.twoByteOpcode = false;
+                        state = Opcode;
+                        break;
+                      default:
+                        panic("Unrecognized prefix %#x\n", nextByte);
+                    }
+                    break;
+                  case Opcode:
+                    if(nextByte == 0xf0)
+                    {
+                        warn("Found two byte opcode!\n");
+                        emi.twoByteOpcode = true;
+                    }
+                    else
+                    {
+                        warn("Found opcode %#x!\n", nextByte);
+                        if (UsesModRM[emi.twoByteOpcode ? 1 : 0][nextByte]) {
+                            state = ModRM;
+                        } else if(0 /* uses immediate */) {
+                            //Figure out how big the immediate should be
+                            immediateCollected = 0;
+                            emi.immediate = 0;
+                            state = Immediate;
+                        } else {
+                            emiIsReady = true;
+                            state = Prefix;
+                        }
+                    }
+                    offset++;
+                    break;
+                  case ModRM:
+                    warn("Found modrm byte %#x!\n", nextByte);
+                    if (0) {//in 16 bit mode
+                        //figure out 16 bit displacement size
+                        if(nextByte & 0xC7 == 0x06 ||
+                                nextByte & 0xC0 == 0x40)
+                            displacementSize = 1;
+                        else if(nextByte & 0xC7 == 0x80)
+                            displacementSize = 2;
+                        else
+                            displacementSize = 0;
+                    } else {
+                        //figure out 32/64 bit displacement size
+                        if(nextByte & 0xC7 == 0x06 ||
+                                nextByte & 0xC0 == 0x40)
+                            displacementSize = 4;
+                        else if(nextByte & 0xC7 == 0x80)
+                            displacementSize = 2;
+                        else
+                            displacementSize = 4;
+                    }
+                    //If there's an SIB, get that next.
+                    //There is no SIB in 16 bit mode.
+                    if(nextByte & 0x7 == 4 &&
+                            nextByte & 0xC0 != 0xC0) {
+                            // && in 32/64 bit mode)
+                        state = SIB;
+                    } else if(displacementSize) {
+                        displacementCollected = 0;
+                        emi.displacement = 0;
+                        state = Displacement;
+                    } else if(immediateSize) {
+                        immediateCollected = 0;
+                        emi.immediate = 0;
+                        state = Immediate;
+                    } else {
+                        emiIsReady = true;
+                        state = Prefix;
+                    }
+                    //The ModRM byte is consumed no matter what
+                    offset++;
+                    break;
+                  case SIB:
+                    warn("Found SIB byte %#x!\n", nextByte);
+                    offset++;
+                    if(displacementSize) {
+                        displacementCollected = 0;
+                        emi.displacement = 0;
+                        state = Displacement;
+                    } else if(immediateSize) {
+                        immediateCollected = 0;
+                        emi.immediate = 0;
+                        state = Immediate;
+                    } else {
+                        emiIsReady = true;
+                        state = Prefix;
+                    }
+                    break;
+                  case Displacement:
+                    //Gather up the displacement, or at least as much of it
+                    //as we can get.
+
+                    //Figure out how many bytes we still need to get for the
+                    //displacement.
+                    toGet = displacementSize - displacementCollected;
+                    //Figure out how many bytes are left in our "buffer"
+                    remaining = sizeof(MachInst) - offset;
+                    //Get as much as we need, up to the amount available.
+                    toGet = toGet > remaining ? remaining : toGet;
+
+                    //Shift the bytes we want to be all the way to the right
+                    partialDisp = fetchChunk >> offset;
+                    //Mask off what we don't want
+                    partialDisp &= mask(toGet * 8);
+                    //Shift it over to overlay with our displacement.
+                    partialDisp <<= displacementCollected;
+                    //Put it into our displacement
+                    emi.displacement |= partialDisp;
+                    //Update how many bytes we've collected.
+                    displacementCollected += toGet;
+
+                    if(displacementSize == displacementCollected) {
+                        //Sign extend the displacement
+                        switch(displacementSize)
+                        {
+                          case 1:
+                            emi.displacement = sext<8>(emi.displacement);
+                            break;
+                          case 2:
+                            emi.displacement = sext<16>(emi.displacement);
+                            break;
+                          case 4:
+                            emi.displacement = sext<32>(emi.displacement);
+                            break;
+                          default:
+                            panic("Undefined displacement size!\n");
+                        }
+                        if(immediateSize) {
+                            immediateCollected = 0;
+                            emi.immediate = 0;
+                            state = Immediate;
+                        } else {
+                            emiIsReady = true;
+                            state = Prefix;
+                        }
+                    }
+                    break;
+                  case Immediate:
+                    //Gather up the displacement, or at least as much of it
+                    //as we can get
+
+                    //Figure out how many bytes we still need to get for the
+                    //immediate.
+                    toGet = immediateSize - immediateCollected;
+                    //Figure out how many bytes are left in our "buffer"
+                    remaining = sizeof(MachInst) - offset;
+                    //Get as much as we need, up to the amount available.
+                    toGet = toGet > remaining ? remaining : toGet;
+
+                    //Shift the bytes we want to be all the way to the right
+                    partialDisp = fetchChunk >> offset;
+                    //Mask off what we don't want
+                    partialDisp &= mask(toGet * 8);
+                    //Shift it over to overlay with our immediate.
+                    partialDisp <<= displacementCollected;
+                    //Put it into our immediate
+                    emi.displacement |= partialDisp;
+                    //Update how many bytes we've collected.
+                    displacementCollected += toGet;
+                    if(immediateSize == immediateCollected)
+                    {
+                        emiIsReady = true;
+                        state = Prefix;
+                    }
+                    break;
+                  default:
+                    panic("Unrecognized state! %d\n", state);
+                }
+                if(offset == sizeof(MachInst))
+                    outOfBytes = true;
+            }
+        }
+
+        //Use this to give data to the predecoder. This should be used
+        //when there is control flow.
+        void moreBytes(Addr currPC, Addr off, MachInst data)
+        {
+            basePC = currPC;
+            offset = off;
+            fetchChunk = data;
+            assert(off < sizeof(MachInst));
+            outOfBytes = false;
+            warn("About to call process.\n");
+            process();
+        }
+
+        //Use this to give data to the predecoder. This should be used
+        //when instructions are executed in order.
+        void moreBytes(MachInst machInst)
+        {
+            moreBytes(basePC + sizeof(machInst), 0, machInst);
+        }
+
+        bool needMoreBytes()
+        {
+            return outOfBytes;
+        }
+
+        bool extMachInstReady()
+        {
+            return emiIsReady;
+        }
+
+        //This returns a constant reference to the ExtMachInst to avoid a copy
+        const ExtMachInst & getExtMachInst()
+        {
+            assert(emiIsReady);
+            emiIsReady = false;
+            return emi;
+        }
+    };
+};
+
+#endif // __ARCH_X86_PREDECODER_HH__
diff --git a/src/arch/x86/predecoder_tables.cc b/src/arch/x86/predecoder_tables.cc
new file mode 100644 (file)
index 0000000..9304eee
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * 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 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
+ * 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 IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#include "arch/x86/predecoder.hh"
+#include "arch/x86/types.hh"
+
+namespace X86ISA
+{
+    const uint8_t CS = CSOverride;
+    const uint8_t DS = DSOverride;
+    const uint8_t ES = ESOverride;
+    const uint8_t FS = FSOverride;
+    const uint8_t GS = GSOverride;
+    const uint8_t SS = SSOverride;
+
+    const uint8_t OO = OperandSizeOverride;
+    const uint8_t AO = AddressSizeOverride;
+    const uint8_t LO = Lock;
+    const uint8_t RE = Rep;
+    const uint8_t RN = Repne;
+    const uint8_t RX = Rex;
+
+    //This table identifies whether a byte is a prefix, and if it is,
+    //which prefix it is.
+    const uint8_t Predecoder::Prefixes[256] =
+    {    //LSB
+// MSB   0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F
+/*   0*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*   1*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*   2*/ 0 , 0 , 0 , 0 , 0 , 0 , ES, 0 , 0 , 0 , 0 , 0 , 0 , 0 , CS, 0,
+/*   3*/ 0 , 0 , 0 , 0 , 0 , 0 , SS, 0 , 0 , 0 , 0 , 0 , 0 , 0 , DS, 0,
+/*   4*/ RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX,
+/*   5*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*   6*/ 0 , 0 , 0 , 0 , FS, GS, OO, AO, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*   7*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*   8*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*   9*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*   A*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*   B*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*   C*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*   D*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*   E*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*   F*/ LO, 0 , RN, RE, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
+    };
+
+    //This table identifies whether a particular opcode uses the ModRM byte
+    const uint8_t Predecoder::UsesModRM[2][256] =
+    {//For one byte instructions
+        {    //LSB
+//     MSB   0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F
+/*      0 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0,
+/*      1 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0,
+/*      2 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0,
+/*      3 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0,
+/*      4 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*      5 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*      6 */ 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1 , 0 , 0 , 0 , 0,
+/*      7 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*      8 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
+/*      9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*      A */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*      B */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*      C */ 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*      D */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
+/*      E */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*      F */ 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1
+        },
+    //For two byte instructions
+        {    //LSB
+//     MSB   0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F
+/*      0 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1,
+/*      1 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*      2 */ 1 , 1 , 1 , 1 , 1 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
+/*      3 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*      4 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
+/*      5 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
+/*      6 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
+/*      7 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1,
+/*      8 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*      9 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
+/*      A */ 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1,
+/*      B */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1,
+/*      C */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/*      D */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
+/*      E */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
+/*      F */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0
+        }
+    };
+}
index 3f3c1ca0ea8ef89f875cb7b4e2ab11fef517e702..68d95de9415b63f20429f9d709bd033825a7f150 100644 (file)
 #define __ARCH_X86_TYPES_HH__
 
 #include <inttypes.h>
+#include <iostream>
 
 namespace X86ISA
 {
     //This really determines how many bytes are passed to the predecoder.
     typedef uint64_t MachInst;
+
+    enum Prefixes {
+        NoOverride = 0,
+        CSOverride = 1,
+        DSOverride = 2,
+        ESOverride = 3,
+        FSOverride = 4,
+        GSOverride = 5,
+        SSOverride = 6,
+        //The Rex prefix obviously doesn't fit in with the above, but putting
+        //it here lets us save double the space the enums take up.
+        Rex = 7,
+        //There can be only one segment override, so they share the
+        //first 3 bits in the legacyPrefixes bitfield.
+        SegmentOverride = 0x7,
+        OperandSizeOverride = 8,
+        AddressSizeOverride = 16,
+        Lock = 32,
+        Rep = 64,
+        Repne = 128
+    };
+
     //The intermediate structure the x86 predecoder returns.
     struct ExtMachInst
     {
-        //Empty for now...
+      public: //XXX These should be hidden in the future
+
+        uint8_t legacyPrefixes;
+        uint8_t rexPrefix;
+        bool twoByteOpcode;
+        uint8_t opcode;
+        uint64_t immediate;
+        uint64_t displacement;
+
+      public:
+
+        //These are to pacify the decoder for now. This will go away once
+        //it can handle non integer inputs, and in the mean time allow me to
+        //excercise the predecoder a little.
+        operator unsigned int()
+        {
+            return 0;
+        }
+
+        ExtMachInst(unsigned int)
+        {;}
+
+        ExtMachInst()
+        {;}
     };
 
-    bool operator == (const ExtMachInst &emi1, const ExtMachInst &emi2)
+    inline static std::ostream &
+        operator << (std::ostream & os, const ExtMachInst & emi)
+    {
+        os << "{X86 ExtMachInst}";
+        return os;
+    }
+
+    inline static bool
+        operator == (const ExtMachInst &emi1, const ExtMachInst &emi2)
     {
         //Since this is empty, it's always equal
         return true;
index 0baa249c3900b4cb285c678e93589b55dfdcc077..8c5d20c6e20f9e84390491eb0a5a9d3808bce360 100644 (file)
 #define __ARCH_X86_UTILITY_HH__
 
 #include "arch/x86/types.hh"
+#include "base/hashmap.hh"
 #include "base/misc.hh"
 #include "sim/host.hh"
 
 class ThreadContext;
 
+namespace __hash_namespace {
+    template<>
+    struct hash<X86ISA::ExtMachInst> {
+        size_t operator()(const X86ISA::ExtMachInst &emi) const {
+            //Because these are all the same, return 0
+            return 0;
+        };
+    };
+}
+
 namespace X86ISA
 {
     static inline bool
@@ -72,18 +83,6 @@ namespace X86ISA
         return false;
     }
 
-    PredecodeResult {
-        MoreBytes = 1,
-        ExtMIReady = 2
-    };
-
-    unsigned int
-    predecode(ExtMachInst &extMachInst, Addr currPC, MachInst machInst,
-            ThreadContext * xc) {
-        //Do something to fill up extMachInst...
-        return MoreBytes | ExtMIReady;
-    }
-
     inline bool isCallerSaveIntegerRegister(unsigned int reg) {
         panic("register classification not implemented");
         return false;
index d4213887dd50a626987e898a62f3147b75f56ac4..85f5b772545c1df421fdedb1e3d1673a4ded6b24 100644 (file)
 
 #include <vector>
 
+#include "arch/isa_traits.hh"
 #include "base/statistics.hh"
 #include "config/full_system.hh"
 #include "sim/eventq.hh"
 #include "mem/mem_object.hh"
-#include "arch/isa_traits.hh"
 
 #if FULL_SYSTEM
 #include "arch/interrupts.hh"
@@ -50,6 +50,11 @@ class ThreadContext;
 class System;
 class Port;
 
+namespace TheISA
+{
+    class Predecoder;
+}
+
 class CPUProgressEvent : public Event
 {
   protected:
@@ -125,6 +130,7 @@ class BaseCPU : public MemObject
 
   protected:
     std::vector<ThreadContext *> threadContexts;
+    std::vector<TheISA::Predecoder *> predecoders;
 
   public:
 
index 8347ed7756abc48b26ea8542dd4cf24785ffeeb0..da7ce00f5743520a69e5e2b20cd04e3b6fbe7526 100644 (file)
@@ -33,6 +33,7 @@
 #define __CPU_O3_FETCH_HH__
 
 #include "arch/utility.hh"
+#include "arch/predecoder.hh"
 #include "base/statistics.hh"
 #include "base/timebuf.hh"
 #include "cpu/pc_event.hh"
@@ -338,6 +339,9 @@ class DefaultFetch
     /** BPredUnit. */
     BPredUnit branchPred;
 
+    /** Predecoder. */
+    TheISA::Predecoder predecoder;
+
     /** Per-thread fetch PC. */
     Addr PC[Impl::MaxThreads];
 
index 89faeb1ab705fdd992818a62afd9f7ff24618c17..1256dd2333b9083e613b0963162bc854a3f6cbc8 100644 (file)
@@ -103,6 +103,7 @@ DefaultFetch<Impl>::IcachePort::recvRetry()
 template<class Impl>
 DefaultFetch<Impl>::DefaultFetch(Params *params)
     : branchPred(params),
+      predecoder(NULL),
       decodeToFetchDelay(params->decodeToFetchDelay),
       renameToFetchDelay(params->renameToFetchDelay),
       iewToFetchDelay(params->iewToFetchDelay),
@@ -1117,9 +1118,10 @@ DefaultFetch<Impl>::fetch(bool &status_change)
             inst = TheISA::gtoh(*reinterpret_cast<TheISA::MachInst *>
                         (&cacheData[tid][offset]));
 
-            //unsigned int result =
-                TheISA::predecode(ext_inst, fetch_PC, inst,
-                        cpu->thread[tid]->getTC());
+            predecoder.setTC(cpu->thread[tid]->getTC());
+            predecoder.moreBytes(fetch_PC, 0, inst);
+
+            ext_inst = predecoder.getExtMachInst();
 
             // Create a new DynInst from the instruction fetched.
             DynInstPtr instruction = new DynInst(ext_inst,
index df7e780e639588275a9f0294337bfaa72148d926..0361db012916aa0b0eedc05031d0ebfa6700a94a 100644 (file)
@@ -500,17 +500,28 @@ AtomicSimpleCPU::tick()
         Fault fault = setupFetchRequest(ifetch_req);
 
         if (fault == NoFault) {
-            ifetch_pkt->reinitFromRequest();
+            Tick icache_latency = 0;
+            bool icache_access = false;
+            dcache_access = false; // assume no dcache access
 
-            Tick icache_latency = icachePort.sendAtomic(ifetch_pkt);
-            // ifetch_req is initialized to read the instruction directly
-            // into the CPU object's inst field.
+            //Fetch more instruction memory if necessary
+            if(predecoder.needMoreBytes())
+            {
+                icache_access = true;
+                ifetch_pkt->reinitFromRequest();
+
+                icache_latency = icachePort.sendAtomic(ifetch_pkt);
+                // ifetch_req is initialized to read the instruction directly
+                // into the CPU object's inst field.
+            }
 
-            dcache_access = false; // assume no dcache access
             preExecute();
 
-            fault = curStaticInst->execute(this, traceData);
-            postExecute();
+            if(curStaticInst)
+            {
+                fault = curStaticInst->execute(this, traceData);
+                postExecute();
+            }
 
             // @todo remove me after debugging with legion done
             if (curStaticInst && (!curStaticInst->isMicroOp() ||
@@ -518,7 +529,8 @@ AtomicSimpleCPU::tick()
                 instCnt++;
 
             if (simulate_stalls) {
-                Tick icache_stall = icache_latency - cycles(1);
+                Tick icache_stall =
+                    icache_access ? icache_latency - cycles(1) : 0;
                 Tick dcache_stall =
                     dcache_access ? dcache_latency - cycles(1) : 0;
                 Tick stall_cycles = (icache_stall + dcache_stall) / cycles(1);
@@ -529,8 +541,8 @@ AtomicSimpleCPU::tick()
             }
 
         }
-
-        advancePC(fault);
+        if(predecoder.needMoreBytes())
+            advancePC(fault);
     }
 
     if (_status != Idle)
index c27be02bfee5a34d7d46eb8c4792f85cc909a3f5..2ad3285424bc94af004e6d9b74ce5347ce37aae1 100644 (file)
@@ -70,7 +70,7 @@ using namespace std;
 using namespace TheISA;
 
 BaseSimpleCPU::BaseSimpleCPU(Params *p)
-    : BaseCPU(p), thread(NULL)
+    : BaseCPU(p), thread(NULL), predecoder(NULL)
 {
 #if FULL_SYSTEM
     thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb);
@@ -370,11 +370,16 @@ BaseSimpleCPU::preExecute()
         StaticInstPtr instPtr = NULL;
 
         //Predecode, ie bundle up an ExtMachInst
-        unsigned int result =
-            predecode(extMachInst, thread->readPC(), inst, thread->getTC());
+        //This should go away once the constructor can be set up properly
+        predecoder.setTC(thread->getTC());
+        //If more fetch data is needed, pass it in.
+        if(predecoder.needMoreBytes())
+            predecoder.moreBytes(thread->readPC(), 0, inst);
+        else
+            predecoder.process();
         //If an instruction is ready, decode it
-        if (result & ExtMIReady)
-            instPtr = StaticInst::decode(extMachInst);
+        if (predecoder.extMachInstReady())
+            instPtr = StaticInst::decode(predecoder.getExtMachInst());
 
         //If we decoded an instruction and it's microcoded, start pulling
         //out micro ops
@@ -446,9 +451,9 @@ BaseSimpleCPU::advancePC(Fault fault)
         fault->invoke(tc);
         thread->setMicroPC(0);
         thread->setNextMicroPC(1);
-    } else {
+    } else if (predecoder.needMoreBytes()) {
         //If we're at the last micro op for this instruction
-        if (curStaticInst->isLastMicroOp()) {
+        if (curStaticInst && curStaticInst->isLastMicroOp()) {
             //We should be working with a macro op
             assert(curMacroStaticInst);
             //Close out this macro op, and clean up the
@@ -467,13 +472,9 @@ BaseSimpleCPU::advancePC(Fault fault)
         } else {
             // go to the next instruction
             thread->setPC(thread->readNextPC());
-#if ISA_HAS_DELAY_SLOT
             thread->setNextPC(thread->readNextNPC());
             thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
             assert(thread->readNextPC() != thread->readNextNPC());
-#else
-            thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
-#endif
         }
     }
 
index 10787c474655243e6ec3b99e3c9d429672bd84eb..a7686bbb1bd2cc915ae59c26d616262829f08a52 100644 (file)
@@ -33,6 +33,7 @@
 #ifndef __CPU_SIMPLE_BASE_HH__
 #define __CPU_SIMPLE_BASE_HH__
 
+#include "arch/predecoder.hh"
 #include "base/statistics.hh"
 #include "config/full_system.hh"
 #include "cpu/base.hh"
@@ -63,6 +64,10 @@ class Process;
 class RemoteGDB;
 class GDBListener;
 
+namespace TheISA
+{
+    class Predecoder;
+}
 class ThreadContext;
 class Checkpoint;
 
@@ -123,8 +128,8 @@ class BaseSimpleCPU : public BaseCPU
     // current instruction
     TheISA::MachInst inst;
 
-    // current extended machine instruction
-    TheISA::ExtMachInst extMachInst;
+    // The predecoder
+    TheISA::Predecoder predecoder;
 
     // Static data storage
     TheISA::LargestRead dataReg;
index 3424c3086402237ba82f8cd84e235fe1c90d0f81..a58ac85d61b84b938e50240e57674a6187530b00 100644 (file)
@@ -35,6 +35,7 @@
 #include <string>
 
 #include "arch/isa_traits.hh"
+#include "arch/utility.hh"
 #include "sim/faults.hh"
 #include "base/bitfield.hh"
 #include "base/hashmap.hh"