CPU: Merge the predecoder and decoder.
authorGabe Black <gblack@eecs.umich.edu>
Sat, 26 May 2012 20:44:46 +0000 (13:44 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Sat, 26 May 2012 20:44:46 +0000 (13:44 -0700)
These classes are always used together, and merging them will give the ISAs
more flexibility in how they cache things and manage the process.

--HG--
rename : src/arch/x86/predecoder_tables.cc => src/arch/x86/decoder_tables.cc

44 files changed:
src/arch/SConscript
src/arch/alpha/decoder.hh
src/arch/alpha/isa/main.isa
src/arch/alpha/predecoder.hh [deleted file]
src/arch/arm/SConscript
src/arch/arm/decoder.cc
src/arch/arm/decoder.hh
src/arch/arm/predecoder.cc [deleted file]
src/arch/arm/predecoder.hh [deleted file]
src/arch/arm/types.hh
src/arch/mips/decoder.hh
src/arch/mips/predecoder.hh [deleted file]
src/arch/power/decoder.hh
src/arch/power/predecoder.hh [deleted file]
src/arch/sparc/decoder.hh
src/arch/sparc/predecoder.hh [deleted file]
src/arch/x86/SConscript
src/arch/x86/decoder.cc
src/arch/x86/decoder.hh
src/arch/x86/decoder_tables.cc [new file with mode: 0644]
src/arch/x86/emulenv.cc
src/arch/x86/isa/decoder/one_byte_opcodes.isa
src/arch/x86/predecoder.cc [deleted file]
src/arch/x86/predecoder.hh [deleted file]
src/arch/x86/predecoder_tables.cc [deleted file]
src/arch/x86/types.hh
src/cpu/base.hh
src/cpu/checker/cpu.hh
src/cpu/checker/cpu_impl.hh
src/cpu/inorder/cpu.cc
src/cpu/inorder/cpu.hh
src/cpu/inorder/resources/cache_unit.cc
src/cpu/inorder/resources/cache_unit.hh
src/cpu/inorder/resources/fetch_unit.cc
src/cpu/inorder/resources/fetch_unit.hh
src/cpu/inorder/thread_context.hh
src/cpu/legiontrace.cc
src/cpu/o3/fetch.hh
src/cpu/o3/fetch_impl.hh
src/cpu/o3/thread_context.hh
src/cpu/simple/atomic.cc
src/cpu/simple/base.cc
src/cpu/simple/base.hh
src/cpu/simple_thread.cc

index f271f487f5904c169c424efd6aa71792bca95111..b4f94a65f36ee896cd88bf9fa57e2e87ad717c89 100644 (file)
@@ -54,7 +54,6 @@ isa_switch_hdrs = Split('''
         mmapped_ipr.hh
         mt.hh
         process.hh
-        predecoder.hh
         registers.hh
         remote_gdb.hh
         stacktrace.hh
index a41ed06bbfe921f62c880d18bc17b4997577b3df..4233c2d444c0c8e7347de52115c5b362f59a556a 100644 (file)
 #include "arch/types.hh"
 #include "cpu/decode_cache.hh"
 #include "cpu/static_inst_fwd.hh"
+#include "sim/full_system.hh"
 
 namespace AlphaISA
 {
 
 class Decoder
 {
+  protected:
+    ThreadContext *tc;
+
+    // The extended machine instruction being generated
+    ExtMachInst ext_inst;
+    bool instDone;
+
+  public:
+    Decoder(ThreadContext * _tc) : tc(_tc), instDone(false)
+    {}
+
+    ThreadContext *
+    getTC()
+    {
+        return tc;
+    }
+
+    void
+    setTC(ThreadContext * _tc)
+    {
+        tc = _tc;
+    }
+
+    void
+    process()
+    { }
+
+    void
+    reset()
+    {
+        instDone = false;
+    }
+
+    // Use this to give data to the predecoder. This should be used
+    // when there is control flow.
+    void
+    moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
+    {
+        ext_inst = inst;
+        instDone = true;
+        if (FullSystem)
+            ext_inst |= (static_cast<ExtMachInst>(pc.pc() & 0x1) << 32);
+    }
+
+    bool
+    needMoreBytes()
+    {
+        return true;
+    }
+
+    bool
+    instReady()
+    {
+        return instDone;
+    }
+
   protected:
     /// A cache of decoded instruction objects.
     static DecodeCache defaultCache;
@@ -55,6 +112,15 @@ class Decoder
     {
         return defaultCache.decode(this, mach_inst, addr);
     }
+
+    StaticInstPtr
+    decode(AlphaISA::PCState &nextPC)
+    {
+        if (!instDone)
+            return NULL;
+        instDone = false;
+        return decode(ext_inst, nextPC.instAddr());
+    }
 };
 
 } // namespace AlphaISA
index 1bc00e75327a23ed575e881b43211e1dc6488aad..cb43c1357d8cf5e019de6a9214c8adcdd9d99eb1 100644 (file)
@@ -73,6 +73,7 @@ using namespace AlphaISA;
 output exec {{
 #include <cmath>
 
+#include "arch/alpha/decoder.hh"
 #include "arch/alpha/registers.hh"
 #include "arch/alpha/regredir.hh"
 #include "arch/generic/memhelpers.hh"
diff --git a/src/arch/alpha/predecoder.hh b/src/arch/alpha/predecoder.hh
deleted file mode 100644 (file)
index a08cdda..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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 "base/types.hh"
-#include "sim/full_system.hh"
-
-class ThreadContext;
-
-namespace AlphaISA {
-
-class Predecoder
-{
-  protected:
-    ThreadContext *tc;
-
-    // The extended machine instruction being generated
-    ExtMachInst ext_inst;
-    bool emiIsReady;
-
-  public:
-    Predecoder(ThreadContext * _tc)
-        : tc(_tc), emiIsReady(false)
-    {}
-
-    ThreadContext *
-    getTC()
-    {
-        return tc;
-    }
-
-    void
-    setTC(ThreadContext * _tc)
-    {
-        tc = _tc;
-    }
-
-    void
-    process()
-    { }
-
-    void
-    reset()
-    {
-        emiIsReady = false;
-    }
-
-    // Use this to give data to the predecoder. This should be used
-    // when there is control flow.
-    void
-    moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
-    {
-        ext_inst = inst;
-        emiIsReady = true;
-        if (FullSystem)
-            ext_inst |= (static_cast<ExtMachInst>(pc.pc() & 0x1) << 32);
-    }
-
-    bool
-    needMoreBytes()
-    {
-        return true;
-    }
-
-    bool
-    extMachInstReady()
-    {
-        return emiIsReady;
-    }
-
-    // This returns a constant reference to the ExtMachInst to avoid a copy
-    const ExtMachInst &
-    getExtMachInst(PCState &pc)
-    {
-        emiIsReady = false;
-        return ext_inst;
-    }
-};
-
-} // namespace AlphaISA
-
-#endif // __ARCH_ALPHA_PREDECODER_HH__
index 0f94455bd87bd22c9aa18673f17774476720422d..44b6286a068bcb1d66ad44e544a91255a9d5ad5b 100644 (file)
@@ -62,7 +62,6 @@ if env['TARGET_ISA'] == 'arm':
     Source('linux/system.cc')
     Source('miscregs.cc')
     Source('nativetrace.cc')
-    Source('predecoder.cc')
     Source('process.cc')
     Source('remote_gdb.cc')
     Source('stacktrace.cc')
@@ -78,9 +77,9 @@ if env['TARGET_ISA'] == 'arm':
     SimObject('ArmTLB.py')
 
     DebugFlag('Arm')
-    DebugFlag('TLBVerbose')
+    DebugFlag('Decoder', "Instructions returned by the predecoder")
     DebugFlag('Faults', "Trace Exceptions, interrupts, svc/swi")
-    DebugFlag('Predecoder', "Instructions returned by the predecoder")
+    DebugFlag('TLBVerbose')
 
     # Add in files generated by the ISA description.
     isa_desc_files = env.ISADesc('isa/main.isa')
index be46ff5404a9e72c7a6b20190c3d7f0772e499fd..65badbc49595f0c59b75364cfe60848cfe286f3e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google
+ * Copyright (c) 2012 Google
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  */
 
 #include "arch/arm/decoder.hh"
+#include "arch/arm/isa_traits.hh"
+#include "arch/arm/utility.hh"
+#include "base/trace.hh"
+#include "cpu/thread_context.hh"
+#include "debug/Decoder.hh"
 
 namespace ArmISA
 {
 
 DecodeCache Decoder::defaultCache;
 
+void
+Decoder::process()
+{
+    // emi is typically ready, with some caveats below...
+    instDone = true;
+
+    if (!emi.thumb) {
+        emi.instBits = data;
+        emi.sevenAndFour = bits(data, 7) && bits(data, 4);
+        emi.isMisc = (bits(data, 24, 23) == 0x2 &&
+                      bits(data, 20) == 0);
+        consumeBytes(4);
+        DPRINTF(Decoder, "Arm inst: %#x.\n", (uint64_t)emi);
+    } else {
+        uint16_t word = (data >> (offset * 8));
+        if (bigThumb) {
+            // A 32 bit thumb inst is half collected.
+            emi.instBits = emi.instBits | word;
+            bigThumb = false;
+            consumeBytes(2);
+            DPRINTF(Decoder, "Second half of 32 bit Thumb: %#x.\n",
+                    emi.instBits);
+        } else {
+            uint16_t highBits = word & 0xF800;
+            if (highBits == 0xE800 || highBits == 0xF000 ||
+                    highBits == 0xF800) {
+                // The start of a 32 bit thumb inst.
+                emi.bigThumb = 1;
+                if (offset == 0) {
+                    // We've got the whole thing.
+                    emi.instBits = (data >> 16) | (data << 16);
+                    DPRINTF(Decoder, "All of 32 bit Thumb: %#x.\n",
+                            emi.instBits);
+                    consumeBytes(4);
+                } else {
+                    // We only have the first half word.
+                    DPRINTF(Decoder,
+                            "First half of 32 bit Thumb.\n");
+                    emi.instBits = (uint32_t)word << 16;
+                    bigThumb = true;
+                    consumeBytes(2);
+                    // emi not ready yet.
+                    instDone = false;
+                }
+            } else {
+                // A 16 bit thumb inst.
+                consumeBytes(2);
+                emi.instBits = word;
+                // Set the condition code field artificially.
+                emi.condCode = COND_UC;
+                DPRINTF(Decoder, "16 bit Thumb: %#x.\n",
+                        emi.instBits);
+                if (bits(word, 15, 8) == 0xbf &&
+                        bits(word, 3, 0) != 0x0) {
+                    foundIt = true;
+                    itBits = bits(word, 7, 0);
+                    DPRINTF(Decoder,
+                            "IT detected, cond = %#x, mask = %#x\n",
+                            itBits.cond, itBits.mask);
+                }
+            }
+        }
+    }
+}
+
+//Use this to give data to the decoder. This should be used
+//when there is control flow.
+void
+Decoder::moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
+{
+    data = inst;
+    offset = (fetchPC >= pc.instAddr()) ? 0 : pc.instAddr() - fetchPC;
+    emi.thumb = pc.thumb();
+    FPSCR fpscr = tc->readMiscReg(MISCREG_FPSCR);
+    emi.fpscrLen = fpscr.len;
+    emi.fpscrStride = fpscr.stride;
+
+    outOfBytes = false;
+    process();
+}
+
 }
index a91d70f484a9126dddb32c890b402a2e107c4333..dd51fd08258934edb54e899f22f49a8cd0da0d21 100644 (file)
 #ifndef __ARCH_ARM_DECODER_HH__
 #define __ARCH_ARM_DECODER_HH__
 
-#include "arch/types.hh"
+#include <cassert>
+
+#include "arch/arm/miscregs.hh"
+#include "arch/arm/types.hh"
+#include "base/types.hh"
 #include "cpu/decode_cache.hh"
-#include "cpu/static_inst_fwd.hh"
+
+class ThreadContext;
 
 namespace ArmISA
 {
 
 class Decoder
 {
+  protected:
+    ThreadContext * tc;
+    //The extended machine instruction being generated
+    ExtMachInst emi;
+    MachInst data;
+    bool bigThumb;
+    bool instDone;
+    bool outOfBytes;
+    int offset;
+    bool foundIt;
+    ITSTATE itBits;
+
+  public:
+    void reset()
+    {
+        bigThumb = false;
+        offset = 0;
+        emi = 0;
+        instDone = false;
+        outOfBytes = true;
+        foundIt = false;
+    }
+
+    Decoder(ThreadContext * _tc) : tc(_tc), data(0)
+    {
+        reset();
+    }
+
+    ThreadContext * getTC()
+    {
+        return tc;
+    }
+
+    void
+    setTC(ThreadContext * _tc)
+    {
+        tc = _tc;
+    }
+
+    void process();
+
+    //Use this to give data to the decoder. This should be used
+    //when there is control flow.
+    void moreBytes(const PCState &pc, Addr fetchPC, MachInst inst);
+
+    //Use this to give data to the decoder. This should be used
+    //when instructions are executed in order.
+    void moreBytes(MachInst machInst)
+    {
+        moreBytes(0, 0, machInst);
+    }
+
+    inline void consumeBytes(int numBytes)
+    {
+        offset += numBytes;
+        assert(offset <= sizeof(MachInst));
+        if (offset == sizeof(MachInst))
+            outOfBytes = true;
+    }
+
+    bool needMoreBytes() const
+    {
+        return outOfBytes;
+    }
+
+    bool instReady() const
+    {
+        return instDone;
+    }
+
+    int getInstSize() const
+    {
+        return (!emi.thumb || emi.bigThumb) ? 4 : 2;
+    }
+
   protected:
     /// A cache of decoded instruction objects.
     static DecodeCache defaultCache;
@@ -55,6 +135,25 @@ class Decoder
     {
         return defaultCache.decode(this, mach_inst, addr);
     }
+
+    StaticInstPtr
+    decode(ArmISA::PCState &nextPC)
+    {
+        if (!instDone)
+            return NULL;
+
+        assert(instDone);
+        ExtMachInst thisEmi = emi;
+        nextPC.npc(nextPC.pc() + getInstSize());
+        if (foundIt)
+            nextPC.nextItstate(itBits);
+        thisEmi.itstate = nextPC.itstate();
+        nextPC.size(getInstSize());
+        emi = 0;
+        instDone = false;
+        foundIt = false;
+        return decode(thisEmi, nextPC.instAddr());
+    }
 };
 
 } // namespace ArmISA
diff --git a/src/arch/arm/predecoder.cc b/src/arch/arm/predecoder.cc
deleted file mode 100644 (file)
index a221f4e..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2010 ARM Limited
- * All rights reserved
- *
- * 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.
- *
- * Copyright (c) 2006 The Regents of The University of Michigan
- * Copyright (c) 2007-2008 The Florida State University
- * 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
- */
-
-#include "arch/arm/isa_traits.hh"
-#include "arch/arm/predecoder.hh"
-#include "arch/arm/utility.hh"
-#include "base/trace.hh"
-#include "cpu/thread_context.hh"
-#include "debug/Predecoder.hh"
-
-namespace ArmISA
-{
-
-void
-Predecoder::process()
-{
-    // emi is typically ready, with some caveats below...
-    emiReady = true;
-
-    if (!emi.thumb) {
-        emi.instBits = data;
-        emi.sevenAndFour = bits(data, 7) && bits(data, 4);
-        emi.isMisc = (bits(data, 24, 23) == 0x2 &&
-                      bits(data, 20) == 0);
-        consumeBytes(4);
-        DPRINTF(Predecoder, "Arm inst: %#x.\n", (uint64_t)emi);
-    } else {
-        uint16_t word = (data >> (offset * 8));
-        if (bigThumb) {
-            // A 32 bit thumb inst is half collected.
-            emi.instBits = emi.instBits | word;
-            bigThumb = false;
-            consumeBytes(2);
-            DPRINTF(Predecoder, "Second half of 32 bit Thumb: %#x.\n",
-                    emi.instBits);
-        } else {
-            uint16_t highBits = word & 0xF800;
-            if (highBits == 0xE800 || highBits == 0xF000 ||
-                    highBits == 0xF800) {
-                // The start of a 32 bit thumb inst.
-                emi.bigThumb = 1;
-                if (offset == 0) {
-                    // We've got the whole thing.
-                    emi.instBits = (data >> 16) | (data << 16);
-                    DPRINTF(Predecoder, "All of 32 bit Thumb: %#x.\n",
-                            emi.instBits);
-                    consumeBytes(4);
-                } else {
-                    // We only have the first half word.
-                    DPRINTF(Predecoder,
-                            "First half of 32 bit Thumb.\n");
-                    emi.instBits = (uint32_t)word << 16;
-                    bigThumb = true;
-                    consumeBytes(2);
-                    // emi not ready yet.
-                    emiReady = false;
-                }
-            } else {
-                // A 16 bit thumb inst.
-                consumeBytes(2);
-                emi.instBits = word;
-                // Set the condition code field artificially.
-                emi.condCode = COND_UC;
-                DPRINTF(Predecoder, "16 bit Thumb: %#x.\n",
-                        emi.instBits);
-                if (bits(word, 15, 8) == 0xbf &&
-                        bits(word, 3, 0) != 0x0) {
-                    foundIt = true;
-                    itBits = bits(word, 7, 0);
-                    DPRINTF(Predecoder,
-                            "IT detected, cond = %#x, mask = %#x\n",
-                            itBits.cond, itBits.mask);
-                }
-            }
-        }
-    }
-}
-
-//Use this to give data to the predecoder. This should be used
-//when there is control flow.
-void
-Predecoder::moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
-{
-    data = inst;
-    offset = (fetchPC >= pc.instAddr()) ? 0 : pc.instAddr() - fetchPC;
-    emi.thumb = pc.thumb();
-    FPSCR fpscr = tc->readMiscReg(MISCREG_FPSCR);
-    emi.fpscrLen = fpscr.len;
-    emi.fpscrStride = fpscr.stride;
-
-    outOfBytes = false;
-    process();
-}
-
-}
diff --git a/src/arch/arm/predecoder.hh b/src/arch/arm/predecoder.hh
deleted file mode 100644 (file)
index 87ba177..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (c) 2010 ARM Limited
- * All rights reserved
- *
- * 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.
- *
- * Copyright (c) 2006 The Regents of The University of Michigan
- * Copyright (c) 2007-2008 The Florida State University
- * 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
- *          Stephen Hines
- */
-
-#ifndef __ARCH_ARM_PREDECODER_HH__
-#define __ARCH_ARM_PREDECODER_HH__
-
-#include <cassert>
-
-#include "arch/arm/miscregs.hh"
-#include "arch/arm/types.hh"
-#include "base/types.hh"
-
-class ThreadContext;
-
-namespace ArmISA
-{
-    class Predecoder
-    {
-      protected:
-        ThreadContext * tc;
-        //The extended machine instruction being generated
-        ExtMachInst emi;
-        MachInst data;
-        bool bigThumb;
-        bool emiReady;
-        bool outOfBytes;
-        int offset;
-        bool foundIt;
-        ITSTATE itBits;
-
-      public:
-        void reset()
-        {
-            bigThumb = false;
-            offset = 0;
-            emi = 0;
-            emiReady = false;
-            outOfBytes = true;
-            foundIt = false;
-        }
-
-        Predecoder(ThreadContext * _tc) :
-            tc(_tc), data(0)
-        {
-            reset();
-        }
-
-        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(const PCState &pc, Addr fetchPC, MachInst 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);
-        }
-
-        inline void consumeBytes(int numBytes)
-        {
-            offset += numBytes;
-            assert(offset <= sizeof(MachInst));
-            if (offset == sizeof(MachInst))
-                outOfBytes = true;
-        }
-
-        bool needMoreBytes() const
-        {
-            return outOfBytes;
-        }
-
-        bool extMachInstReady() const
-        {
-            return emiReady;
-        }
-
-        int getInstSize() const
-        {
-            return (!emi.thumb || emi.bigThumb) ? 4 : 2;
-        }
-
-        //This returns a constant reference to the ExtMachInst to avoid a copy
-        ExtMachInst getExtMachInst(PCState &pc)
-        {
-            assert(emiReady);
-            ExtMachInst thisEmi = emi;
-            pc.npc(pc.pc() + getInstSize());
-            if (foundIt)
-                pc.nextItstate(itBits);
-            thisEmi.itstate = pc.itstate();
-            pc.size(getInstSize());
-            emi = 0;
-            emiReady = false;
-            foundIt = false;
-            return thisEmi;
-        }
-    };
-}
-
-#endif // __ARCH_ARM_PREDECODER_HH__
index 31dec7bcbe23e3a95eee35f6a153442da9e8fd2b..ebebbcc460315d556144085b20e3c9abbaa7dd23 100644 (file)
@@ -48,7 +48,7 @@
 #include "base/hashmap.hh"
 #include "base/misc.hh"
 #include "base/types.hh"
-#include "debug/Predecoder.hh"
+#include "debug/Decoder.hh"
 
 namespace ArmISA
 {
@@ -342,7 +342,7 @@ namespace ArmISA
                 ITSTATE it = _itstate;
                 uint8_t cond_mask = it.mask;
                 uint8_t thumb_cond = it.cond;
-                DPRINTF(Predecoder, "Advancing ITSTATE from %#x,%#x.\n",
+                DPRINTF(Decoder, "Advancing ITSTATE from %#x,%#x.\n",
                         thumb_cond, cond_mask);
                 cond_mask <<= 1;
                 uint8_t new_bit = bits(cond_mask, 4);
@@ -351,7 +351,7 @@ namespace ArmISA
                     thumb_cond = 0;
                 else
                     replaceBits(thumb_cond, 0, new_bit);
-                DPRINTF(Predecoder, "Advancing ITSTATE to %#x,%#x.\n",
+                DPRINTF(Decoder, "Advancing ITSTATE to %#x,%#x.\n",
                         thumb_cond, cond_mask);
                 it.mask = cond_mask;
                 it.cond = thumb_cond;
index f5940daad200b44851cdb8ca1638b73d65258a9e..95385961d890f3b5ee499aca6b6b1cd9e98c75a9 100644 (file)
 #ifndef __ARCH_MIPS_DECODER_HH__
 #define __ARCH_MIPS_DECODER_HH__
 
-#include "arch/types.hh"
+#include "arch/mips/types.hh"
+#include "base/misc.hh"
+#include "base/types.hh"
 #include "cpu/decode_cache.hh"
 #include "cpu/static_inst_fwd.hh"
 
+class ThreadContext;
+
 namespace MipsISA
 {
 
 class Decoder
 {
+  protected:
+    ThreadContext * tc;
+    //The extended machine instruction being generated
+    ExtMachInst emi;
+    bool instDone;
+
+  public:
+    Decoder(ThreadContext * _tc) : tc(_tc), instDone(false)
+    {}
+
+    ThreadContext *getTC()
+    {
+        return tc;
+    }
+
+    void
+    setTC(ThreadContext *_tc)
+    {
+        tc = _tc;
+    }
+
+    void
+    process()
+    {
+    }
+
+    void
+    reset()
+    {
+        instDone = false;
+    }
+
+    //Use this to give data to the decoder. This should be used
+    //when there is control flow.
+    void
+    moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
+    {
+        emi = inst;
+        instDone = true;
+    }
+
+    bool
+    needMoreBytes()
+    {
+        return true;
+    }
+
+    bool
+    instReady()
+    {
+        return instDone;
+    }
+
   protected:
     /// A cache of decoded instruction objects.
     static DecodeCache defaultCache;
@@ -55,6 +112,15 @@ class Decoder
     {
         return defaultCache.decode(this, mach_inst, addr);
     }
+
+    StaticInstPtr
+    decode(MipsISA::PCState &nextPC)
+    {
+        if (!instDone)
+            return NULL;
+        instDone = false;
+        return decode(emi, nextPC.instAddr());
+    }
 };
 
 } // namespace MipsISA
diff --git a/src/arch/mips/predecoder.hh b/src/arch/mips/predecoder.hh
deleted file mode 100644 (file)
index 4220b76..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-
-/*
- * 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 "base/types.hh"
-
-class ThreadContext;
-
-namespace MipsISA
-{
-
-class Predecoder
-{
-  protected:
-    ThreadContext * tc;
-    //The extended machine instruction being generated
-    ExtMachInst emi;
-    bool emiIsReady;
-
-  public:
-    Predecoder(ThreadContext * _tc) : tc(_tc), emiIsReady(false)
-    {}
-
-    ThreadContext *getTC()
-    {
-        return tc;
-    }
-
-    void
-    setTC(ThreadContext *_tc)
-    {
-        tc = _tc;
-    }
-
-    void
-    process()
-    {
-    }
-
-    void
-    reset()
-    {
-        emiIsReady = false;
-    }
-
-    //Use this to give data to the predecoder. This should be used
-    //when there is control flow.
-    void
-    moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
-    {
-        emi = inst;
-        emiIsReady = true;
-    }
-
-    bool
-    needMoreBytes()
-    {
-        return true;
-    }
-
-    bool
-    extMachInstReady()
-    {
-        return emiIsReady;
-    }
-
-    //This returns a constant reference to the ExtMachInst to avoid a copy
-    const ExtMachInst &
-    getExtMachInst(PCState &pc)
-    {
-        emiIsReady = false;
-        return emi;
-    }
-};
-
-};
-
-#endif // __ARCH_MIPS_PREDECODER_HH__
index 34537bb566a469d687b33abdfe7a3312141efa59..c45473a9008b56724c240dab41ba8ecb2073d7c1 100644 (file)
@@ -40,6 +40,69 @@ namespace PowerISA
 
 class Decoder
 {
+  protected:
+    ThreadContext * tc;
+
+    // The extended machine instruction being generated
+    ExtMachInst emi;
+    bool instDone;
+
+  public:
+    Decoder(ThreadContext * _tc) : tc(_tc), instDone(false)
+    {
+    }
+
+    ThreadContext *
+    getTC()
+    {
+        return tc;
+    }
+
+    void
+    setTC(ThreadContext * _tc)
+    {
+        tc = _tc;
+    }
+
+    void
+    process()
+    {
+    }
+
+    void
+    reset()
+    {
+        instDone = false;
+    }
+
+    // Use this to give data to the predecoder. This should be used
+    // when there is control flow.
+    void
+    moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
+    {
+        emi = inst;
+        instDone = true;
+    }
+
+    // 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
+    instReady()
+    {
+        return instDone;
+    }
   protected:
     /// A cache of decoded instruction objects.
     static DecodeCache defaultCache;
@@ -55,6 +118,15 @@ class Decoder
     {
         return defaultCache.decode(this, mach_inst, addr);
     }
+
+    StaticInstPtr
+    decode(PowerISA::PCState &nextPC)
+    {
+        if (!instDone)
+            return NULL;
+        instDone = false;
+        return decode(emi, nextPC.instAddr());
+    }
 };
 
 } // namespace PowerISA
diff --git a/src/arch/power/predecoder.hh b/src/arch/power/predecoder.hh
deleted file mode 100644 (file)
index 8b10890..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * Copyright (c) 2007-2008 The Florida State University
- * Copyright (c) 2009 The University of Edinburgh
- * 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
- *          Stephen Hines
- *          Timothy M. Jones
- */
-
-#ifndef __ARCH_ARM_PREDECODER_HH__
-#define __ARCH_ARM_PREDECODER_HH__
-
-#include "arch/power/types.hh"
-#include "base/misc.hh"
-#include "base/types.hh"
-
-class ThreadContext;
-
-namespace PowerISA
-{
-
-class Predecoder
-{
-  protected:
-    ThreadContext * tc;
-
-    // The extended machine instruction being generated
-    ExtMachInst emi;
-    bool emiIsReady;
-
-  public:
-    Predecoder(ThreadContext * _tc)
-        : tc(_tc), emiIsReady(false)
-    {
-    }
-
-    ThreadContext *
-    getTC()
-    {
-        return tc;
-    }
-
-    void
-    setTC(ThreadContext * _tc)
-    {
-        tc = _tc;
-    }
-
-    void
-    process()
-    {
-    }
-
-    void
-    reset()
-    {
-        emiIsReady = false;
-    }
-
-    // Use this to give data to the predecoder. This should be used
-    // when there is control flow.
-    void
-    moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
-    {
-        emi = inst;
-        emiIsReady = true;
-    }
-
-    // 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 emiIsReady;
-    }
-
-    // This returns a constant reference to the ExtMachInst to avoid a copy
-    const ExtMachInst &
-    getExtMachInst(PCState &pcState)
-    {
-        emiIsReady = false;
-        return emi;
-    }
-};
-
-} // namespace PowerISA
-
-#endif // __ARCH_POWER_PREDECODER_HH__
index 9c8e740b82e05658458466d778af7dd0000acdbd..999a605a7e19add14dc7667f079d3a3038d43d9b 100644 (file)
 #ifndef __ARCH_SPARC_DECODER_HH__
 #define __ARCH_SPARC_DECODER_HH__
 
+#include "arch/sparc/registers.hh"
 #include "arch/types.hh"
 #include "cpu/decode_cache.hh"
 #include "cpu/static_inst_fwd.hh"
+#include "cpu/thread_context.hh"
+
+class ThreadContext;
 
 namespace SparcISA
 {
 
 class Decoder
 {
+  protected:
+    ThreadContext * tc;
+    // The extended machine instruction being generated
+    ExtMachInst emi;
+    bool instDone;
+
+  public:
+    Decoder(ThreadContext * _tc) : tc(_tc), instDone(false)
+    {}
+
+    ThreadContext *
+    getTC()
+    {
+        return tc;
+    }
+
+    void
+    setTC(ThreadContext * _tc)
+    {
+        tc = _tc;
+    }
+
+    void process() {}
+
+    void
+    reset()
+    {
+        instDone = false;
+    }
+
+    // Use this to give data to the predecoder. This should be used
+    // when there is control flow.
+    void
+    moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
+    {
+        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));
+        }
+        instDone = true;
+    }
+
+    bool
+    needMoreBytes()
+    {
+        return true;
+    }
+
+    bool
+    instReady()
+    {
+        return instDone;
+    }
+
   protected:
     /// A cache of decoded instruction objects.
     static DecodeCache defaultCache;
@@ -55,6 +122,15 @@ class Decoder
     {
         return defaultCache.decode(this, mach_inst, addr);
     }
+
+    StaticInstPtr
+    decode(SparcISA::PCState &nextPC)
+    {
+        if (!instDone)
+            return NULL;
+        instDone = false;
+        return decode(emi, nextPC.instAddr());
+    }
 };
 
 } // namespace SparcISA
diff --git a/src/arch/sparc/predecoder.hh b/src/arch/sparc/predecoder.hh
deleted file mode 100644 (file)
index a7a5436..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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/registers.hh"
-#include "arch/sparc/types.hh"
-#include "base/bitfield.hh"
-#include "base/misc.hh"
-#include "base/types.hh"
-#include "cpu/thread_context.hh"
-
-class ThreadContext;
-
-namespace SparcISA
-{
-
-class Predecoder
-{
-  protected:
-    ThreadContext * tc;
-    // The extended machine instruction being generated
-    ExtMachInst emi;
-    bool emiIsReady;
-
-  public:
-    Predecoder(ThreadContext * _tc) : tc(_tc), emiIsReady(false)
-    {}
-
-    ThreadContext *
-    getTC()
-    {
-        return tc;
-    }
-
-    void
-    setTC(ThreadContext * _tc)
-    {
-        tc = _tc;
-    }
-
-    void process() {}
-
-    void
-    reset()
-    {
-        emiIsReady = false;
-    }
-
-    // Use this to give data to the predecoder. This should be used
-    // when there is control flow.
-    void
-    moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
-    {
-        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));
-        }
-        emiIsReady = true;
-    }
-
-    bool
-    needMoreBytes()
-    {
-        return true;
-    }
-
-    bool
-    extMachInstReady()
-    {
-        return emiIsReady;
-    }
-
-    // This returns a constant reference to the ExtMachInst to avoid a copy
-    const ExtMachInst &
-    getExtMachInst(PCState &pcState)
-    {
-        emiIsReady = false;
-        return emi;
-    }
-};
-};
-
-#endif // __ARCH_SPARC_PREDECODER_HH__
index 27b12fe2097f528960718fa0be4e79938cc0bb94..92b30ced1db01013f4b333f2dee900847b18e8df 100644 (file)
@@ -45,6 +45,7 @@ Import('*')
 if env['TARGET_ISA'] == 'x86':
     Source('cpuid.cc')
     Source('decoder.cc')
+    Source('decoder_tables.cc')
     Source('emulenv.cc')
     Source('faults.cc')
     Source('insts/badmicroop.cc')
@@ -63,8 +64,6 @@ if env['TARGET_ISA'] == 'x86':
     Source('nativetrace.cc')
     Source('pagetable.cc')
     Source('pagetable_walker.cc')
-    Source('predecoder.cc')
-    Source('predecoder_tables.cc')
     Source('process.cc')
     Source('remote_gdb.cc')
     Source('stacktrace.cc')
@@ -83,7 +82,7 @@ if env['TARGET_ISA'] == 'x86':
     DebugFlag('LocalApic', "Local APIC debugging")
     DebugFlag('PageTableWalker', \
               "Page table walker state machine debugging")
-    DebugFlag('Predecoder', "Predecoder debug output")
+    DebugFlag('Decoder', "Decoder debug output")
     DebugFlag('X86', "Generic X86 ISA debugging")
 
     python_files = (
index 469858301c73ded43aa0db204b9534b00074a47e..d7199fa8226daaa8de1067e04c934a2b7ef9ee80 100644 (file)
  */
 
 #include "arch/x86/decoder.hh"
+#include "arch/x86/regs/misc.hh"
+#include "base/misc.hh"
+#include "base/trace.hh"
+#include "base/types.hh"
+#include "cpu/thread_context.hh"
+#include "debug/Decoder.hh"
 
 namespace X86ISA
 {
+void Decoder::doReset()
+{
+    origPC = basePC + offset;
+    DPRINTF(Decoder, "Setting origPC to %#x\n", origPC);
+    emi.rex = 0;
+    emi.legacy = 0;
+    emi.opcode.num = 0;
+    emi.opcode.op = 0;
+    emi.opcode.prefixA = emi.opcode.prefixB = 0;
+
+    immediateCollected = 0;
+    emi.immediate = 0;
+    emi.displacement = 0;
+    emi.dispSize = 0;
+
+    emi.modRM = 0;
+    emi.sib = 0;
+    m5Reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
+    emi.mode.mode = m5Reg.mode;
+    emi.mode.submode = m5Reg.submode;
+}
+
+void Decoder::process()
+{
+    //This function drives the decoder state machine.
+
+    //Some sanity checks. You shouldn't try to process more bytes if
+    //there aren't any, and you shouldn't overwrite an already
+    //decoder ExtMachInst.
+    assert(!outOfBytes);
+    assert(!instDone);
+
+    //While there's still something to do...
+    while(!instDone && !outOfBytes)
+    {
+        uint8_t nextByte = getNextByte();
+        switch(state)
+        {
+          case ResetState:
+            doReset();
+            state = PrefixState;
+          case PrefixState:
+            state = doPrefixState(nextByte);
+            break;
+          case OpcodeState:
+            state = doOpcodeState(nextByte);
+            break;
+          case ModRMState:
+            state = doModRMState(nextByte);
+            break;
+          case SIBState:
+            state = doSIBState(nextByte);
+            break;
+          case DisplacementState:
+            state = doDisplacementState();
+            break;
+          case ImmediateState:
+            state = doImmediateState();
+            break;
+          case ErrorState:
+            panic("Went to the error state in the decoder.\n");
+          default:
+            panic("Unrecognized state! %d\n", state);
+        }
+    }
+}
+
+//Either get a prefix and record it in the ExtMachInst, or send the
+//state machine on to get the opcode(s).
+Decoder::State Decoder::doPrefixState(uint8_t nextByte)
+{
+    uint8_t prefix = Prefixes[nextByte];
+    State nextState = PrefixState;
+    // REX prefixes are only recognized in 64 bit mode.
+    if (prefix == RexPrefix && emi.mode.submode != SixtyFourBitMode)
+        prefix = 0;
+    if (prefix)
+        consumeByte();
+    switch(prefix)
+    {
+        //Operand size override prefixes
+      case OperandSizeOverride:
+        DPRINTF(Decoder, "Found operand size override prefix.\n");
+        emi.legacy.op = true;
+        break;
+      case AddressSizeOverride:
+        DPRINTF(Decoder, "Found address size override prefix.\n");
+        emi.legacy.addr = true;
+        break;
+        //Segment override prefixes
+      case CSOverride:
+      case DSOverride:
+      case ESOverride:
+      case FSOverride:
+      case GSOverride:
+      case SSOverride:
+        DPRINTF(Decoder, "Found segment override.\n");
+        emi.legacy.seg = prefix;
+        break;
+      case Lock:
+        DPRINTF(Decoder, "Found lock prefix.\n");
+        emi.legacy.lock = true;
+        break;
+      case Rep:
+        DPRINTF(Decoder, "Found rep prefix.\n");
+        emi.legacy.rep = true;
+        break;
+      case Repne:
+        DPRINTF(Decoder, "Found repne prefix.\n");
+        emi.legacy.repne = true;
+        break;
+      case RexPrefix:
+        DPRINTF(Decoder, "Found Rex prefix %#x.\n", nextByte);
+        emi.rex = nextByte;
+        break;
+      case 0:
+        nextState = OpcodeState;
+        break;
+      default:
+        panic("Unrecognized prefix %#x\n", nextByte);
+    }
+    return nextState;
+}
+
+//Load all the opcodes (currently up to 2) and then figure out
+//what immediate and/or ModRM is needed.
+Decoder::State Decoder::doOpcodeState(uint8_t nextByte)
+{
+    State nextState = ErrorState;
+    emi.opcode.num++;
+    //We can't handle 3+ byte opcodes right now
+    assert(emi.opcode.num < 4);
+    consumeByte();
+    if(emi.opcode.num == 1 && nextByte == 0x0f)
+    {
+        nextState = OpcodeState;
+        DPRINTF(Decoder, "Found two byte opcode.\n");
+        emi.opcode.prefixA = nextByte;
+    }
+    else if(emi.opcode.num == 2 && (nextByte == 0x38 || nextByte == 0x3A))
+    {
+        nextState = OpcodeState;
+        DPRINTF(Decoder, "Found three byte opcode.\n");
+        emi.opcode.prefixB = nextByte;
+    }
+    else
+    {
+        DPRINTF(Decoder, "Found opcode %#x.\n", nextByte);
+        emi.opcode.op = nextByte;
+
+        //Figure out the effective operand size. This can be overriden to
+        //a fixed value at the decoder level.
+        int logOpSize;
+        if (emi.rex.w)
+            logOpSize = 3; // 64 bit operand size
+        else if (emi.legacy.op)
+            logOpSize = m5Reg.altOp;
+        else
+            logOpSize = m5Reg.defOp;
+
+        //Set the actual op size
+        emi.opSize = 1 << logOpSize;
+
+        //Figure out the effective address size. This can be overriden to
+        //a fixed value at the decoder level.
+        int logAddrSize;
+        if(emi.legacy.addr)
+            logAddrSize = m5Reg.altAddr;
+        else
+            logAddrSize = m5Reg.defAddr;
+
+        //Set the actual address size
+        emi.addrSize = 1 << logAddrSize;
+
+        //Figure out the effective stack width. This can be overriden to
+        //a fixed value at the decoder level.
+        emi.stackSize = 1 << m5Reg.stack;
+
+        //Figure out how big of an immediate we'll retreive based
+        //on the opcode.
+        int immType = ImmediateType[emi.opcode.num - 1][nextByte];
+        if (emi.opcode.num == 1 && nextByte >= 0xA0 && nextByte <= 0xA3)
+            immediateSize = SizeTypeToSize[logAddrSize - 1][immType];
+        else
+            immediateSize = SizeTypeToSize[logOpSize - 1][immType];
+
+        //Determine what to expect next
+        if (UsesModRM[emi.opcode.num - 1][nextByte]) {
+            nextState = ModRMState;
+        } else {
+            if(immediateSize) {
+                nextState = ImmediateState;
+            } else {
+                instDone = true;
+                nextState = ResetState;
+            }
+        }
+    }
+    return nextState;
+}
+
+//Get the ModRM byte and determine what displacement, if any, there is.
+//Also determine whether or not to get the SIB byte, displacement, or
+//immediate next.
+Decoder::State Decoder::doModRMState(uint8_t nextByte)
+{
+    State nextState = ErrorState;
+    ModRM modRM;
+    modRM = nextByte;
+    DPRINTF(Decoder, "Found modrm byte %#x.\n", nextByte);
+    if (m5Reg.defOp == 1) {
+        //figure out 16 bit displacement size
+        if ((modRM.mod == 0 && modRM.rm == 6) || modRM.mod == 2)
+            displacementSize = 2;
+        else if (modRM.mod == 1)
+            displacementSize = 1;
+        else
+            displacementSize = 0;
+    } else {
+        //figure out 32/64 bit displacement size
+        if ((modRM.mod == 0 && modRM.rm == 5) || modRM.mod == 2)
+            displacementSize = 4;
+        else if (modRM.mod == 1)
+            displacementSize = 1;
+        else
+            displacementSize = 0;
+    }
+
+    // The "test" instruction in group 3 needs an immediate, even though
+    // the other instructions with the same actual opcode don't.
+    if (emi.opcode.num == 1 && (modRM.reg & 0x6) == 0) {
+       if (emi.opcode.op == 0xF6)
+           immediateSize = 1;
+       else if (emi.opcode.op == 0xF7)
+           immediateSize = (emi.opSize == 8) ? 4 : emi.opSize;
+    }
+
+    //If there's an SIB, get that next.
+    //There is no SIB in 16 bit mode.
+    if (modRM.rm == 4 && modRM.mod != 3) {
+            // && in 32/64 bit mode)
+        nextState = SIBState;
+    } else if(displacementSize) {
+        nextState = DisplacementState;
+    } else if(immediateSize) {
+        nextState = ImmediateState;
+    } else {
+        instDone = true;
+        nextState = ResetState;
+    }
+    //The ModRM byte is consumed no matter what
+    consumeByte();
+    emi.modRM = modRM;
+    return nextState;
+}
+
+//Get the SIB byte. We don't do anything with it at this point, other
+//than storing it in the ExtMachInst. Determine if we need to get a
+//displacement or immediate next.
+Decoder::State Decoder::doSIBState(uint8_t nextByte)
+{
+    State nextState = ErrorState;
+    emi.sib = nextByte;
+    DPRINTF(Decoder, "Found SIB byte %#x.\n", nextByte);
+    consumeByte();
+    if (emi.modRM.mod == 0 && emi.sib.base == 5)
+        displacementSize = 4;
+    if (displacementSize) {
+        nextState = DisplacementState;
+    } else if(immediateSize) {
+        nextState = ImmediateState;
+    } else {
+        instDone = true;
+        nextState = ResetState;
+    }
+    return nextState;
+}
+
+//Gather up the displacement, or at least as much of it
+//as we can get.
+Decoder::State Decoder::doDisplacementState()
+{
+    State nextState = ErrorState;
+
+    getImmediate(immediateCollected,
+            emi.displacement,
+            displacementSize);
+
+    DPRINTF(Decoder, "Collecting %d byte displacement, got %d bytes.\n",
+            displacementSize, immediateCollected);
+
+    if(displacementSize == immediateCollected) {
+        //Reset this for other immediates.
+        immediateCollected = 0;
+        //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");
+        }
+        DPRINTF(Decoder, "Collected displacement %#x.\n",
+                emi.displacement);
+        if(immediateSize) {
+            nextState = ImmediateState;
+        } else {
+            instDone = true;
+            nextState = ResetState;
+        }
+
+        emi.dispSize = displacementSize;
+    }
+    else
+        nextState = DisplacementState;
+    return nextState;
+}
+
+//Gather up the immediate, or at least as much of it
+//as we can get
+Decoder::State Decoder::doImmediateState()
+{
+    State nextState = ErrorState;
+
+    getImmediate(immediateCollected,
+            emi.immediate,
+            immediateSize);
+
+    DPRINTF(Decoder, "Collecting %d byte immediate, got %d bytes.\n",
+            immediateSize, immediateCollected);
+
+    if(immediateSize == immediateCollected)
+    {
+        //Reset this for other immediates.
+        immediateCollected = 0;
+
+        //XXX Warning! The following is an observed pattern and might
+        //not always be true!
+
+        //Instructions which use 64 bit operands but 32 bit immediates
+        //need to have the immediate sign extended to 64 bits.
+        //Instructions which use true 64 bit immediates won't be
+        //affected, and instructions that use true 32 bit immediates
+        //won't notice.
+        switch(immediateSize)
+        {
+          case 4:
+            emi.immediate = sext<32>(emi.immediate);
+            break;
+          case 1:
+            emi.immediate = sext<8>(emi.immediate);
+        }
+
+        DPRINTF(Decoder, "Collected immediate %#x.\n",
+                emi.immediate);
+        instDone = true;
+        nextState = ResetState;
+    }
+    else
+        nextState = ImmediateState;
+    return nextState;
+}
 
 DecodeCache Decoder::defaultCache;
 
index 769284adbc33cdd222b601f448de3afb4a58a531..300e2238c512d4a626497d9a91a4f2a90cfcb3d1 100644 (file)
 #ifndef __ARCH_X86_DECODER_HH__
 #define __ARCH_X86_DECODER_HH__
 
-#include "arch/types.hh"
+#include <cassert>
+
+#include "arch/x86/regs/misc.hh"
+#include "arch/x86/types.hh"
+#include "base/bitfield.hh"
+#include "base/misc.hh"
+#include "base/trace.hh"
+#include "base/types.hh"
 #include "cpu/decode_cache.hh"
 #include "cpu/static_inst_fwd.hh"
+#include "debug/Decoder.hh"
+
+class ThreadContext;
 
 namespace X86ISA
 {
 
 class Decoder
 {
+  private:
+    //These are defined and documented in decoder_tables.cc
+    static const uint8_t Prefixes[256];
+    static const uint8_t UsesModRM[2][256];
+    static const uint8_t ImmediateType[2][256];
+    static const uint8_t SizeTypeToSize[3][10];
+
+  protected:
+    ThreadContext * tc;
+    //The bytes to be predecoded
+    MachInst fetchChunk;
+    //The pc of the start of fetchChunk
+    Addr basePC;
+    //The pc the current instruction started at
+    Addr origPC;
+    //The offset into fetchChunk of current processing
+    int offset;
+    //The extended machine instruction being generated
+    ExtMachInst emi;
+    HandyM5Reg m5Reg;
+
+    inline uint8_t getNextByte()
+    {
+        return ((uint8_t *)&fetchChunk)[offset];
+    }
+
+    void getImmediate(int &collected, uint64_t &current, int size)
+    {
+        //Figure out how many bytes we still need to get for the
+        //immediate.
+        int toGet = size - collected;
+        //Figure out how many bytes are left in our "buffer"
+        int 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
+        uint64_t partialImm = fetchChunk >> (offset * 8);
+        //Mask off what we don't want
+        partialImm &= mask(toGet * 8);
+        //Shift it over to overlay with our displacement.
+        partialImm <<= (immediateCollected * 8);
+        //Put it into our displacement
+        current |= partialImm;
+        //Update how many bytes we've collected.
+        collected += toGet;
+        consumeBytes(toGet);
+    }
+
+    inline void consumeByte()
+    {
+        offset++;
+        assert(offset <= sizeof(MachInst));
+        if(offset == sizeof(MachInst))
+            outOfBytes = true;
+    }
+
+    inline void consumeBytes(int numBytes)
+    {
+        offset += numBytes;
+        assert(offset <= sizeof(MachInst));
+        if(offset == sizeof(MachInst))
+            outOfBytes = true;
+    }
+
+    void doReset();
+
+    //State machine state
+  protected:
+    //Whether or not we're out of bytes
+    bool outOfBytes;
+    //Whether we've completed generating an ExtMachInst
+    bool instDone;
+    //The size of the displacement value
+    int displacementSize;
+    //The size of the immediate value
+    int immediateSize;
+    //This is how much of any immediate value we've gotten. This is used
+    //for both the actual immediate and the displacement.
+    int immediateCollected;
+
+    enum State {
+        ResetState,
+        PrefixState,
+        OpcodeState,
+        ModRMState,
+        SIBState,
+        DisplacementState,
+        ImmediateState,
+        //We should never get to this state. Getting here is an error.
+        ErrorState
+    };
+
+    State state;
+
+    //Functions to handle each of the states
+    State doPrefixState(uint8_t);
+    State doOpcodeState(uint8_t);
+    State doModRMState(uint8_t);
+    State doSIBState(uint8_t);
+    State doDisplacementState();
+    State doImmediateState();
+
+  public:
+    Decoder(ThreadContext * _tc) :
+        tc(_tc), basePC(0), origPC(0), offset(0),
+        outOfBytes(true), instDone(false),
+        state(ResetState)
+    {
+        emi.mode.mode = LongMode;
+        emi.mode.submode = SixtyFourBitMode;
+        m5Reg = 0;
+    }
+
+    void reset()
+    {
+        state = ResetState;
+    }
+
+    ThreadContext * getTC()
+    {
+        return tc;
+    }
+
+    void setTC(ThreadContext * _tc)
+    {
+        tc = _tc;
+    }
+
+    void process();
+
+    //Use this to give data to the decoder. This should be used
+    //when there is control flow.
+    void moreBytes(const PCState &pc, Addr fetchPC, MachInst data)
+    {
+        DPRINTF(Decoder, "Getting more bytes.\n");
+        basePC = fetchPC;
+        offset = (fetchPC >= pc.instAddr()) ? 0 : pc.instAddr() - fetchPC;
+        fetchChunk = data;
+        outOfBytes = false;
+        process();
+    }
+
+    bool needMoreBytes()
+    {
+        return outOfBytes;
+    }
+
+    bool instReady()
+    {
+        return instDone;
+    }
+
+    void
+    updateNPC(X86ISA::PCState &nextPC)
+    {
+        if (!nextPC.size()) {
+            int size = basePC + offset - origPC;
+            DPRINTF(Decoder,
+                    "Calculating the instruction size: "
+                    "basePC: %#x offset: %#x origPC: %#x size: %d\n",
+                    basePC, offset, origPC, size);
+            nextPC.size(size);
+            nextPC.npc(nextPC.pc() + size);
+        }
+    }
+
   protected:
     /// A cache of decoded instruction objects.
     static DecodeCache defaultCache;
@@ -55,6 +232,16 @@ class Decoder
     {
         return defaultCache.decode(this, mach_inst, addr);
     }
+
+    StaticInstPtr
+    decode(X86ISA::PCState &nextPC)
+    {
+        if (!instDone)
+            return NULL;
+        instDone = false;
+        updateNPC(nextPC);
+        return decode(emi, origPC);
+    }
 };
 
 } // namespace X86ISA
diff --git a/src/arch/x86/decoder_tables.cc b/src/arch/x86/decoder_tables.cc
new file mode 100644 (file)
index 0000000..a132cb8
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2007-2008 The Hewlett-Packard Development Company
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * 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
+ */
+
+#include "arch/x86/decoder.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 = RexPrefix;
+
+    //This table identifies whether a byte is a prefix, and if it is,
+    //which prefix it is.
+    const uint8_t Decoder::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 Decoder::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 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
+/*      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
+        }
+    };
+
+    enum SizeType {
+        NoImm,
+        NI = NoImm,
+        ByteImm,
+        BY = ByteImm,
+        WordImm,
+        WO = WordImm,
+        DWordImm,
+        DW = DWordImm,
+        QWordImm,
+        QW = QWordImm,
+        OWordImm,
+        OW = OWordImm,
+        VWordImm,
+        VW = VWordImm,
+        ZWordImm,
+        ZW = ZWordImm,
+        //The enter instruction takes -2- immediates for a total of 3 bytes
+        Enter,
+        EN = Enter,
+        Pointer,
+        PO = Pointer
+    };
+
+    const uint8_t Decoder::SizeTypeToSize[3][10] =
+    {
+//       noimm byte word dword qword oword vword zword enter pointer
+        {0,    1,   2,   4,    8,    16,   2,    2,    3,    4      }, //16 bit
+        {0,    1,   2,   4,    8,    16,   4,    4,    3,    6      }, //32 bit
+        {0,    1,   2,   4,    8,    16,   8,    4,    3,    0      }  //64 bit
+    };
+
+    //This table determines the immediate type. The first index is the
+    //number of bytes in the instruction, and the second is the meaningful
+    //byte of the opcode. I didn't use the NI constant here for the sake
+    //of clarity.
+    const uint8_t Decoder::ImmediateType[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 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 ,
+/*      1 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 ,
+/*      2 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 ,
+/*      3 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 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 , 0 , 0 , 0 , 0 , 0 , 0 , ZW, ZW, BY, BY, 0 , 0 , 0 , 0 ,
+/*      7 */ BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY,
+/*      8 */ BY, ZW, BY, BY, 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 */ VW, VW, VW, VW, 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 ,
+/*      B */ BY, BY, BY, BY, BY, BY, BY, BY, VW, VW, VW, VW, VW, VW, VW, VW,
+/*      C */ BY, BY, WO, 0 , 0 , 0 , BY, ZW, EN, 0 , WO, 0 , 0 , BY, 0 , 0 ,
+/*      D */ 0 , 0 , 0 , 0 , BY, BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+/*      E */ BY, BY, BY, BY, BY, BY, BY, BY, ZW, ZW, PO, BY, 0 , 0 , 0 , 0 ,
+/*      F */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
+        },
+    //For two byte instructions
+        {    //LSB
+//     MSB   0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F
+/*      0 */ 0 , 0 , 0 , 0 , WO, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , BY ,
+/*      0 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+/*      2 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+/*      3 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 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 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+/*      7 */ BY, BY, BY, BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+/*      8 */ ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW,
+/*      9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+/*      A */ 0 , 0 , 0 , 0 , BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , BY, 0 , 0 , 0 ,
+/*      B */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ZW, 0 , BY, 0 , 0 , 0 , 0 , 0 ,
+/*      C */ 0 , 0 , BY, 0 , BY, BY, BY, 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 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
+        }
+    };
+}
index e6c170d0f1c26801ad8f8f1b452536628a8d7af8..49df32ecaaf627c9bf33f52330cfd652c09f3011 100644 (file)
@@ -53,7 +53,7 @@ void EmulEnv::doModRM(const ExtMachInst & machInst)
         index = machInst.sib.index | (machInst.rex.x << 3);
         base = machInst.sib.base | (machInst.rex.b << 3);
         //In this special case, we don't use a base. The displacement also
-        //changes, but that's managed by the predecoder.
+        //changes, but that's managed by the decoder.
         if (machInst.sib.base == INTREG_RBP && machInst.modRM.mod == 0)
             base = NUM_INTREGS;
         //In -this- special case, we don't use an index.
index 66a0c8c46da65834365c9b1ee3d8ca1aa0315d1c..040f5d04f11c1c4c90011ab7d88c0bd38cbf3d6e 100644 (file)
                 0x4: int3();
                 0x5: decode FullSystemInt default int_Ib() {
                     0: decode IMMEDIATE {
-                        // Really only the LSB matters, but the predecoder
+                        // Really only the LSB matters, but the decoder
                         // will sign extend it, and there's no easy way to
                         // specify only checking the first byte.
                         -0x80: SyscallInst::int80('xc->syscall(Rax)',
diff --git a/src/arch/x86/predecoder.cc b/src/arch/x86/predecoder.cc
deleted file mode 100644 (file)
index a4aa93b..0000000
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * Copyright (c) 2007-2008 The Hewlett-Packard Development Company
- * All rights reserved.
- *
- * 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.
- *
- * 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
- */
-
-#include "arch/x86/regs/misc.hh"
-#include "arch/x86/predecoder.hh"
-#include "base/misc.hh"
-#include "base/trace.hh"
-#include "base/types.hh"
-#include "cpu/thread_context.hh"
-#include "debug/Predecoder.hh"
-
-namespace X86ISA
-{
-    void Predecoder::doReset()
-    {
-        origPC = basePC + offset;
-        DPRINTF(Predecoder, "Setting origPC to %#x\n", origPC);
-        emi.rex = 0;
-        emi.legacy = 0;
-        emi.opcode.num = 0;
-        emi.opcode.op = 0;
-        emi.opcode.prefixA = emi.opcode.prefixB = 0;
-
-        immediateCollected = 0;
-        emi.immediate = 0;
-        emi.displacement = 0;
-        emi.dispSize = 0;
-
-        emi.modRM = 0;
-        emi.sib = 0;
-        m5Reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
-        emi.mode.mode = m5Reg.mode;
-        emi.mode.submode = m5Reg.submode;
-    }
-
-    void Predecoder::process()
-    {
-        //This function drives the predecoder state machine.
-
-        //Some sanity checks. You shouldn't try to process more bytes if
-        //there aren't any, and you shouldn't overwrite an already
-        //predecoder ExtMachInst.
-        assert(!outOfBytes);
-        assert(!emiIsReady);
-
-        //While there's still something to do...
-        while(!emiIsReady && !outOfBytes)
-        {
-            uint8_t nextByte = getNextByte();
-            switch(state)
-            {
-              case ResetState:
-                doReset();
-                state = PrefixState;
-              case PrefixState:
-                state = doPrefixState(nextByte);
-                break;
-              case OpcodeState:
-                state = doOpcodeState(nextByte);
-                break;
-              case ModRMState:
-                state = doModRMState(nextByte);
-                break;
-              case SIBState:
-                state = doSIBState(nextByte);
-                break;
-              case DisplacementState:
-                state = doDisplacementState();
-                break;
-              case ImmediateState:
-                state = doImmediateState();
-                break;
-              case ErrorState:
-                panic("Went to the error state in the predecoder.\n");
-              default:
-                panic("Unrecognized state! %d\n", state);
-            }
-        }
-    }
-
-    //Either get a prefix and record it in the ExtMachInst, or send the
-    //state machine on to get the opcode(s).
-    Predecoder::State Predecoder::doPrefixState(uint8_t nextByte)
-    {
-        uint8_t prefix = Prefixes[nextByte];
-        State nextState = PrefixState;
-        // REX prefixes are only recognized in 64 bit mode.
-        if (prefix == RexPrefix && emi.mode.submode != SixtyFourBitMode)
-            prefix = 0;
-        if (prefix)
-            consumeByte();
-        switch(prefix)
-        {
-            //Operand size override prefixes
-          case OperandSizeOverride:
-            DPRINTF(Predecoder, "Found operand size override prefix.\n");
-            emi.legacy.op = true;
-            break;
-          case AddressSizeOverride:
-            DPRINTF(Predecoder, "Found address size override prefix.\n");
-            emi.legacy.addr = true;
-            break;
-            //Segment override prefixes
-          case CSOverride:
-          case DSOverride:
-          case ESOverride:
-          case FSOverride:
-          case GSOverride:
-          case SSOverride:
-            DPRINTF(Predecoder, "Found segment override.\n");
-            emi.legacy.seg = prefix;
-            break;
-          case Lock:
-            DPRINTF(Predecoder, "Found lock prefix.\n");
-            emi.legacy.lock = true;
-            break;
-          case Rep:
-            DPRINTF(Predecoder, "Found rep prefix.\n");
-            emi.legacy.rep = true;
-            break;
-          case Repne:
-            DPRINTF(Predecoder, "Found repne prefix.\n");
-            emi.legacy.repne = true;
-            break;
-          case RexPrefix:
-            DPRINTF(Predecoder, "Found Rex prefix %#x.\n", nextByte);
-            emi.rex = nextByte;
-            break;
-          case 0:
-            nextState = OpcodeState;
-            break;
-          default:
-            panic("Unrecognized prefix %#x\n", nextByte);
-        }
-        return nextState;
-    }
-
-    //Load all the opcodes (currently up to 2) and then figure out
-    //what immediate and/or ModRM is needed.
-    Predecoder::State Predecoder::doOpcodeState(uint8_t nextByte)
-    {
-        State nextState = ErrorState;
-        emi.opcode.num++;
-        //We can't handle 3+ byte opcodes right now
-        assert(emi.opcode.num < 4);
-        consumeByte();
-        if(emi.opcode.num == 1 && nextByte == 0x0f)
-        {
-            nextState = OpcodeState;
-            DPRINTF(Predecoder, "Found two byte opcode.\n");
-            emi.opcode.prefixA = nextByte;
-        }
-        else if(emi.opcode.num == 2 && (nextByte == 0x38 || nextByte == 0x3A))
-        {
-            nextState = OpcodeState;
-            DPRINTF(Predecoder, "Found three byte opcode.\n");
-            emi.opcode.prefixB = nextByte;
-        }
-        else
-        {
-            DPRINTF(Predecoder, "Found opcode %#x.\n", nextByte);
-            emi.opcode.op = nextByte;
-
-            //Figure out the effective operand size. This can be overriden to
-            //a fixed value at the decoder level.
-            int logOpSize;
-            if (emi.rex.w)
-                logOpSize = 3; // 64 bit operand size
-            else if (emi.legacy.op)
-                logOpSize = m5Reg.altOp;
-            else
-                logOpSize = m5Reg.defOp;
-
-            //Set the actual op size
-            emi.opSize = 1 << logOpSize;
-
-            //Figure out the effective address size. This can be overriden to
-            //a fixed value at the decoder level.
-            int logAddrSize;
-            if(emi.legacy.addr)
-                logAddrSize = m5Reg.altAddr;
-            else
-                logAddrSize = m5Reg.defAddr;
-
-            //Set the actual address size
-            emi.addrSize = 1 << logAddrSize;
-
-            //Figure out the effective stack width. This can be overriden to
-            //a fixed value at the decoder level.
-            emi.stackSize = 1 << m5Reg.stack;
-
-            //Figure out how big of an immediate we'll retreive based
-            //on the opcode.
-            int immType = ImmediateType[emi.opcode.num - 1][nextByte];
-            if (emi.opcode.num == 1 && nextByte >= 0xA0 && nextByte <= 0xA3)
-                immediateSize = SizeTypeToSize[logAddrSize - 1][immType];
-            else
-                immediateSize = SizeTypeToSize[logOpSize - 1][immType];
-
-            //Determine what to expect next
-            if (UsesModRM[emi.opcode.num - 1][nextByte]) {
-                nextState = ModRMState;
-            } else {
-                if(immediateSize) {
-                    nextState = ImmediateState;
-                } else {
-                    emiIsReady = true;
-                    nextState = ResetState;
-                }
-            }
-        }
-        return nextState;
-    }
-
-    //Get the ModRM byte and determine what displacement, if any, there is.
-    //Also determine whether or not to get the SIB byte, displacement, or
-    //immediate next.
-    Predecoder::State Predecoder::doModRMState(uint8_t nextByte)
-    {
-        State nextState = ErrorState;
-        ModRM modRM;
-        modRM = nextByte;
-        DPRINTF(Predecoder, "Found modrm byte %#x.\n", nextByte);
-        if (m5Reg.defOp == 1) {
-            //figure out 16 bit displacement size
-            if ((modRM.mod == 0 && modRM.rm == 6) || modRM.mod == 2)
-                displacementSize = 2;
-            else if (modRM.mod == 1)
-                displacementSize = 1;
-            else
-                displacementSize = 0;
-        } else {
-            //figure out 32/64 bit displacement size
-            if ((modRM.mod == 0 && modRM.rm == 5) || modRM.mod == 2)
-                displacementSize = 4;
-            else if (modRM.mod == 1)
-                displacementSize = 1;
-            else
-                displacementSize = 0;
-        }
-
-        // The "test" instruction in group 3 needs an immediate, even though
-        // the other instructions with the same actual opcode don't.
-        if (emi.opcode.num == 1 && (modRM.reg & 0x6) == 0) {
-           if (emi.opcode.op == 0xF6)
-               immediateSize = 1;
-           else if (emi.opcode.op == 0xF7)
-               immediateSize = (emi.opSize == 8) ? 4 : emi.opSize;
-        }
-
-        //If there's an SIB, get that next.
-        //There is no SIB in 16 bit mode.
-        if (modRM.rm == 4 && modRM.mod != 3) {
-                // && in 32/64 bit mode)
-            nextState = SIBState;
-        } else if(displacementSize) {
-            nextState = DisplacementState;
-        } else if(immediateSize) {
-            nextState = ImmediateState;
-        } else {
-            emiIsReady = true;
-            nextState = ResetState;
-        }
-        //The ModRM byte is consumed no matter what
-        consumeByte();
-        emi.modRM = modRM;
-        return nextState;
-    }
-
-    //Get the SIB byte. We don't do anything with it at this point, other
-    //than storing it in the ExtMachInst. Determine if we need to get a
-    //displacement or immediate next.
-    Predecoder::State Predecoder::doSIBState(uint8_t nextByte)
-    {
-        State nextState = ErrorState;
-        emi.sib = nextByte;
-        DPRINTF(Predecoder, "Found SIB byte %#x.\n", nextByte);
-        consumeByte();
-        if (emi.modRM.mod == 0 && emi.sib.base == 5)
-            displacementSize = 4;
-        if (displacementSize) {
-            nextState = DisplacementState;
-        } else if(immediateSize) {
-            nextState = ImmediateState;
-        } else {
-            emiIsReady = true;
-            nextState = ResetState;
-        }
-        return nextState;
-    }
-
-    //Gather up the displacement, or at least as much of it
-    //as we can get.
-    Predecoder::State Predecoder::doDisplacementState()
-    {
-        State nextState = ErrorState;
-
-        getImmediate(immediateCollected,
-                emi.displacement,
-                displacementSize);
-
-        DPRINTF(Predecoder, "Collecting %d byte displacement, got %d bytes.\n",
-                displacementSize, immediateCollected);
-
-        if(displacementSize == immediateCollected) {
-            //Reset this for other immediates.
-            immediateCollected = 0;
-            //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");
-            }
-            DPRINTF(Predecoder, "Collected displacement %#x.\n",
-                    emi.displacement);
-            if(immediateSize) {
-                nextState = ImmediateState;
-            } else {
-                emiIsReady = true;
-                nextState = ResetState;
-            }
-
-            emi.dispSize = displacementSize;
-        }
-        else
-            nextState = DisplacementState;
-        return nextState;
-    }
-
-    //Gather up the immediate, or at least as much of it
-    //as we can get
-    Predecoder::State Predecoder::doImmediateState()
-    {
-        State nextState = ErrorState;
-
-        getImmediate(immediateCollected,
-                emi.immediate,
-                immediateSize);
-
-        DPRINTF(Predecoder, "Collecting %d byte immediate, got %d bytes.\n",
-                immediateSize, immediateCollected);
-
-        if(immediateSize == immediateCollected)
-        {
-            //Reset this for other immediates.
-            immediateCollected = 0;
-
-            //XXX Warning! The following is an observed pattern and might
-            //not always be true!
-
-            //Instructions which use 64 bit operands but 32 bit immediates
-            //need to have the immediate sign extended to 64 bits.
-            //Instructions which use true 64 bit immediates won't be
-            //affected, and instructions that use true 32 bit immediates
-            //won't notice.
-            switch(immediateSize)
-            {
-              case 4:
-                emi.immediate = sext<32>(emi.immediate);
-                break;
-              case 1:
-                emi.immediate = sext<8>(emi.immediate);
-            }
-
-            DPRINTF(Predecoder, "Collected immediate %#x.\n",
-                    emi.immediate);
-            emiIsReady = true;
-            nextState = ResetState;
-        }
-        else
-            nextState = ImmediateState;
-        return nextState;
-    }
-}
diff --git a/src/arch/x86/predecoder.hh b/src/arch/x86/predecoder.hh
deleted file mode 100644 (file)
index f7c6368..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (c) 2007 The Hewlett-Packard Development Company
- * All rights reserved.
- *
- * 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.
- *
- * 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_X86_PREDECODER_HH__
-#define __ARCH_X86_PREDECODER_HH__
-
-#include <cassert>
-
-#include "arch/x86/regs/misc.hh"
-#include "arch/x86/types.hh"
-#include "base/bitfield.hh"
-#include "base/misc.hh"
-#include "base/trace.hh"
-#include "base/types.hh"
-#include "debug/Predecoder.hh"
-
-class ThreadContext;
-
-namespace X86ISA
-{
-    class Predecoder
-    {
-      private:
-        //These are defined and documented in predecoder_tables.cc
-        static const uint8_t Prefixes[256];
-        static const uint8_t UsesModRM[2][256];
-        static const uint8_t ImmediateType[2][256];
-        static const uint8_t SizeTypeToSize[3][10];
-
-      protected:
-        ThreadContext * tc;
-        //The bytes to be predecoded
-        MachInst fetchChunk;
-        //The pc of the start of fetchChunk
-        Addr basePC;
-        //The pc the current instruction started at
-        Addr origPC;
-        //The offset into fetchChunk of current processing
-        int offset;
-        //The extended machine instruction being generated
-        ExtMachInst emi;
-        HandyM5Reg m5Reg;
-
-        inline uint8_t getNextByte()
-        {
-            return ((uint8_t *)&fetchChunk)[offset];
-        }
-
-        void getImmediate(int &collected, uint64_t &current, int size)
-        {
-            //Figure out how many bytes we still need to get for the
-            //immediate.
-            int toGet = size - collected;
-            //Figure out how many bytes are left in our "buffer"
-            int 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
-            uint64_t partialImm = fetchChunk >> (offset * 8);
-            //Mask off what we don't want
-            partialImm &= mask(toGet * 8);
-            //Shift it over to overlay with our displacement.
-            partialImm <<= (immediateCollected * 8);
-            //Put it into our displacement
-            current |= partialImm;
-            //Update how many bytes we've collected.
-            collected += toGet;
-            consumeBytes(toGet);
-        }
-
-        inline void consumeByte()
-        {
-            offset++;
-            assert(offset <= sizeof(MachInst));
-            if(offset == sizeof(MachInst))
-                outOfBytes = true;
-        }
-
-        inline void consumeBytes(int numBytes)
-        {
-            offset += numBytes;
-            assert(offset <= sizeof(MachInst));
-            if(offset == sizeof(MachInst))
-                outOfBytes = true;
-        }
-
-        void doReset();
-
-        //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;
-        //The size of the immediate value
-        int immediateSize;
-        //This is how much of any immediate value we've gotten. This is used
-        //for both the actual immediate and the displacement.
-        int immediateCollected;
-
-        enum State {
-            ResetState,
-            PrefixState,
-            OpcodeState,
-            ModRMState,
-            SIBState,
-            DisplacementState,
-            ImmediateState,
-            //We should never get to this state. Getting here is an error.
-            ErrorState
-        };
-
-        State state;
-
-        //Functions to handle each of the states
-        State doPrefixState(uint8_t);
-        State doOpcodeState(uint8_t);
-        State doModRMState(uint8_t);
-        State doSIBState(uint8_t);
-        State doDisplacementState();
-        State doImmediateState();
-
-      public:
-        Predecoder(ThreadContext * _tc) :
-            tc(_tc), basePC(0), origPC(0), offset(0),
-            outOfBytes(true), emiIsReady(false),
-            state(ResetState)
-        {
-            emi.mode.mode = LongMode;
-            emi.mode.submode = SixtyFourBitMode;
-            m5Reg = 0;
-        }
-
-        void reset()
-        {
-            state = ResetState;
-        }
-
-        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(const PCState &pc, Addr fetchPC, MachInst data)
-        {
-            DPRINTF(Predecoder, "Getting more bytes.\n");
-            basePC = fetchPC;
-            offset = (fetchPC >= pc.instAddr()) ? 0 : pc.instAddr() - fetchPC;
-            fetchChunk = data;
-            outOfBytes = false;
-            process();
-        }
-
-        bool needMoreBytes()
-        {
-            return outOfBytes;
-        }
-
-        bool extMachInstReady()
-        {
-            return emiIsReady;
-        }
-
-        int
-        getInstSize()
-        {
-            int size = basePC + offset - origPC;
-            DPRINTF(Predecoder,
-                    "Calculating the instruction size: "
-                    "basePC: %#x offset: %#x origPC: %#x size: %d\n",
-                    basePC, offset, origPC, size);
-            return size;
-        }
-
-        //This returns a constant reference to the ExtMachInst to avoid a copy
-        const ExtMachInst &
-        getExtMachInst(X86ISA::PCState &nextPC)
-        {
-            assert(emiIsReady);
-            emiIsReady = false;
-            if (!nextPC.size()) {
-                Addr size = getInstSize();
-                nextPC.size(size);
-                nextPC.npc(nextPC.pc() + size);
-            }
-            return emi;
-        }
-    };
-}
-
-#endif // __ARCH_X86_PREDECODER_HH__
diff --git a/src/arch/x86/predecoder_tables.cc b/src/arch/x86/predecoder_tables.cc
deleted file mode 100644 (file)
index 3931e4c..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (c) 2007-2008 The Hewlett-Packard Development Company
- * All rights reserved.
- *
- * 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.
- *
- * 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
- */
-
-#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 = RexPrefix;
-
-    //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 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
-/*      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
-        }
-    };
-
-    enum SizeType {
-        NoImm,
-        NI = NoImm,
-        ByteImm,
-        BY = ByteImm,
-        WordImm,
-        WO = WordImm,
-        DWordImm,
-        DW = DWordImm,
-        QWordImm,
-        QW = QWordImm,
-        OWordImm,
-        OW = OWordImm,
-        VWordImm,
-        VW = VWordImm,
-        ZWordImm,
-        ZW = ZWordImm,
-        //The enter instruction takes -2- immediates for a total of 3 bytes
-        Enter,
-        EN = Enter,
-        Pointer,
-        PO = Pointer
-    };
-
-    const uint8_t Predecoder::SizeTypeToSize[3][10] =
-    {
-//       noimm byte word dword qword oword vword zword enter pointer
-        {0,    1,   2,   4,    8,    16,   2,    2,    3,    4      }, //16 bit
-        {0,    1,   2,   4,    8,    16,   4,    4,    3,    6      }, //32 bit
-        {0,    1,   2,   4,    8,    16,   8,    4,    3,    0      }  //64 bit
-    };
-
-    //This table determines the immediate type. The first index is the
-    //number of bytes in the instruction, and the second is the meaningful
-    //byte of the opcode. I didn't use the NI constant here for the sake
-    //of clarity.
-    const uint8_t Predecoder::ImmediateType[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 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 ,
-/*      1 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 ,
-/*      2 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 ,
-/*      3 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 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 , 0 , 0 , 0 , 0 , 0 , 0 , ZW, ZW, BY, BY, 0 , 0 , 0 , 0 ,
-/*      7 */ BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY,
-/*      8 */ BY, ZW, BY, BY, 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 */ VW, VW, VW, VW, 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 ,
-/*      B */ BY, BY, BY, BY, BY, BY, BY, BY, VW, VW, VW, VW, VW, VW, VW, VW,
-/*      C */ BY, BY, WO, 0 , 0 , 0 , BY, ZW, EN, 0 , WO, 0 , 0 , BY, 0 , 0 ,
-/*      D */ 0 , 0 , 0 , 0 , BY, BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
-/*      E */ BY, BY, BY, BY, BY, BY, BY, BY, ZW, ZW, PO, BY, 0 , 0 , 0 , 0 ,
-/*      F */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
-        },
-    //For two byte instructions
-        {    //LSB
-//     MSB   0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F
-/*      0 */ 0 , 0 , 0 , 0 , WO, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , BY ,
-/*      0 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
-/*      2 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
-/*      3 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 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 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
-/*      7 */ BY, BY, BY, BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
-/*      8 */ ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW,
-/*      9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
-/*      A */ 0 , 0 , 0 , 0 , BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , BY, 0 , 0 , 0 ,
-/*      B */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ZW, 0 , BY, 0 , 0 , 0 , 0 , 0 ,
-/*      C */ 0 , 0 , BY, 0 , BY, BY, BY, 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 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
-        }
-    };
-}
index 6d9f600ff9fb7b7571850d065ebfc78ca3caa4d7..a604c3efc5752053d6b9d36fcc07575dcbea16e7 100644 (file)
@@ -51,7 +51,7 @@
 
 namespace X86ISA
 {
-    //This really determines how many bytes are passed to the predecoder.
+    //This really determines how many bytes are passed to the decoder.
     typedef uint64_t MachInst;
 
     enum Prefixes {
@@ -127,7 +127,7 @@ namespace X86ISA
         RealMode
     };
 
-    //The intermediate structure the x86 predecoder returns.
+    //The intermediate structure used by the x86 decoder.
     struct ExtMachInst
     {
         //Prefixes
index 5d88e064b90fad10a285477bdc59d46e78f89712..b99b25d1745a64d415212db11f44563fdfa210c2 100644 (file)
@@ -64,11 +64,6 @@ class CheckerCPU;
 class ThreadContext;
 class System;
 
-namespace TheISA
-{
-    class Predecoder;
-}
-
 class CPUProgressEvent : public Event
 {
   protected:
@@ -257,7 +252,6 @@ class BaseCPU : public MemObject
 
   protected:
     std::vector<ThreadContext *> threadContexts;
-    std::vector<TheISA::Predecoder *> predecoders;
 
     Trace::InstTracer * tracer;
 
index d816578ae728cd09da3ff5137d552e9620143c76..72dc2ce3e0de543ed8c72b48e492c8229f7c929a 100644 (file)
@@ -47,7 +47,6 @@
 #include <map>
 #include <queue>
 
-#include "arch/predecoder.hh"
 #include "arch/types.hh"
 #include "base/statistics.hh"
 #include "cpu/base.hh"
@@ -156,9 +155,6 @@ class CheckerCPU : public BaseCPU
     // keep them all in a std::queue
     std::queue<Result> result;
 
-    // current instruction
-    TheISA::MachInst machInst;
-
     // Pointer to the one memory request.
     RequestPtr memReq;
 
@@ -401,8 +397,7 @@ class Checker : public CheckerCPU
 
   public:
     Checker(Params *p)
-        : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL),
-          predecoder(NULL)
+        : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL)
     { }
 
     void switchOut();
@@ -434,7 +429,6 @@ class Checker : public CheckerCPU
     bool updateThisCycle;
 
     DynInstPtr unverifiedInst;
-    TheISA::Predecoder predecoder;
 
     std::list<DynInstPtr> instList;
     typedef typename std::list<DynInstPtr>::iterator InstListIt;
index dcc6b01f9357e2f0bd948130bcb45226f1007af7..40f1cef6ad4aad98b36e453329de4ad1706d9cf3 100644 (file)
@@ -69,7 +69,7 @@ Checker<Impl>::advancePC(Fault fault)
     if (fault != NoFault) {
         curMacroStaticInst = StaticInst::nullStaticInstPtr;
         fault->invoke(tc, curStaticInst);
-        predecoder.reset();
+        thread->decoder.reset();
     } else {
         if (curStaticInst) {
             if (curStaticInst->isLastMicroop())
@@ -113,7 +113,7 @@ Checker<Impl>::handlePendingInt()
               "a non-interuptable instruction!", curTick());
     }
     boundaryInst = NULL;
-    predecoder.reset();
+    thread->decoder.reset();
     curMacroStaticInst = StaticInst::nullStaticInstPtr;
 }
 
@@ -239,6 +239,8 @@ Checker<Impl>::verify(DynInstPtr &completed_inst)
             Addr fetch_PC = thread->instAddr();
             fetch_PC = (fetch_PC & PCMask) + fetchOffset;
 
+            MachInst machInst;
+
             // If not in the middle of a macro instruction
             if (!curMacroStaticInst) {
                 // set up memory request for instruction fetch
@@ -304,24 +306,18 @@ Checker<Impl>::verify(DynInstPtr &completed_inst)
                     StaticInstPtr instPtr = NULL;
 
                     //Predecode, ie bundle up an ExtMachInst
-                    predecoder.setTC(thread->getTC());
+                    thread->decoder.setTC(thread->getTC());
                     //If more fetch data is needed, pass it in.
                     Addr fetchPC = (pcState.instAddr() & PCMask) + fetchOffset;
-                    predecoder.moreBytes(pcState, fetchPC, machInst);
+                    thread->decoder.moreBytes(pcState, fetchPC, machInst);
 
                     //If an instruction is ready, decode it.
                     //Otherwise, we'll have to fetch beyond the
                     //MachInst at the current pc.
-                    if (predecoder.extMachInstReady()) {
+                    if (thread->decoder.instReady()) {
                         fetchDone = true;
-                        ExtMachInst newMachInst =
-                            predecoder.getExtMachInst(pcState);
+                        instPtr = thread->decoder.decode(pcState);
                         thread->pcState(pcState);
-                        instPtr = thread->decoder.decode(newMachInst,
-                                                         pcState.instAddr());
-#if THE_ISA != X86_ISA
-                            machInst = newMachInst;
-#endif
                     } else {
                         fetchDone = false;
                         fetchOffset += sizeof(TheISA::MachInst);
@@ -344,8 +340,8 @@ Checker<Impl>::verify(DynInstPtr &completed_inst)
                 }
             }
         }
-        // reset predecoder on Checker
-        predecoder.reset();
+        // reset decoder on Checker
+        thread->decoder.reset();
 
         // Check Checker and CPU get same instruction, and record
         // any faults the CPU may have had.
@@ -477,17 +473,9 @@ Checker<Impl>::validateInst(DynInstPtr &inst)
         }
     }
 
-
-    MachInst mi;
-#if THE_ISA != X86_ISA
-    mi = static_cast<MachInst>(inst->staticInst->machInst);
-#endif
-
-    if (mi != machInst) {
-        panic("%lli: Binary instructions do not match! Inst: %#x, "
-             "checker: %#x",
-             curTick(), mi, machInst);
-        handleError(inst);
+    if (curStaticInst != inst->staticInst) {
+        warn("%lli: StaticInstPtrs don't match. (%s, %s).\n", curTick(),
+                curStaticInst->getName(), inst->staticInst->getName());
     }
 }
 
index 9ad0a26805ba414a23c32ddaf8e81390183a9c88..3c27cf4b24dff03da7343a305d8c879f5765e7eb 100644 (file)
@@ -1773,9 +1773,9 @@ InOrderCPU::getDTBPtr()
 }
 
 TheISA::Decoder *
-InOrderCPU::getDecoderPtr()
+InOrderCPU::getDecoderPtr(unsigned tid)
 {
-    return &resPool->getInstUnit()->decoder;
+    return resPool->getInstUnit()->decoder[tid];
 }
 
 Fault
index 29fe6bc3b1396323885e4fbcc6a5c2420a83cbbe..615d0eb90a24b289722120211bc8186be580fd1f 100644 (file)
@@ -342,7 +342,7 @@ class InOrderCPU : public BaseCPU
     TheISA::TLB *getITBPtr();
     TheISA::TLB *getDTBPtr();
 
-    TheISA::Decoder *getDecoderPtr();
+    TheISA::Decoder *getDecoderPtr(unsigned tid);
 
     /** Accessor Type for the SkedCache */
     typedef uint32_t SkedID;
index a4dc23d47fcc80b3864d775fa933ccf11de6aff1..21d7bb6e227fe12d1050b9bd5d15bdb1a3ec75dc 100644 (file)
@@ -34,7 +34,6 @@
 
 #include "arch/isa_traits.hh"
 #include "arch/locked_mem.hh"
-#include "arch/predecoder.hh"
 #include "arch/utility.hh"
 #include "config/the_isa.hh"
 #include "cpu/inorder/resources/cache_unit.hh"
index f0878d24d81fb6dea801aca221c0e431f7b8223e..dda39a7a59a9b14dda190a495b3c68be6d28cfbd 100644 (file)
@@ -36,7 +36,6 @@
 #include <string>
 #include <vector>
 
-#include "arch/predecoder.hh"
 #include "arch/tlb.hh"
 #include "base/hashmap.hh"
 #include "config/the_isa.hh"
index cc4b8b53e3017fe65ef28159c500c270a1d76f9e..07669ef2a9f1cf6332f792b772c9123b9f1b378b 100644 (file)
@@ -34,7 +34,6 @@
 
 #include "arch/isa_traits.hh"
 #include "arch/locked_mem.hh"
-#include "arch/predecoder.hh"
 #include "arch/utility.hh"
 #include "config/the_isa.hh"
 #include "cpu/inorder/resources/cache_unit.hh"
@@ -60,7 +59,7 @@ FetchUnit::FetchUnit(string res_name, int res_id, int res_width,
       instSize(sizeof(TheISA::MachInst)), fetchBuffSize(params->fetchBuffSize)
 {
     for (int tid = 0; tid < MaxThreads; tid++)
-        predecoder[tid] = new Predecoder(NULL);
+        decoder[tid] = new Decoder(NULL);
 }
 
 FetchUnit::~FetchUnit()
@@ -92,7 +91,6 @@ void
 FetchUnit::createMachInst(std::list<FetchBlock*>::iterator fetch_it,
                           DynInstPtr inst)
 {
-    ExtMachInst ext_inst;
     Addr block_addr = cacheBlockAlign(inst->getMemAddr());
     Addr fetch_addr = inst->getMemAddr();
     unsigned fetch_offset = (fetch_addr - block_addr) / instSize;
@@ -111,13 +109,11 @@ FetchUnit::createMachInst(std::list<FetchBlock*>::iterator fetch_it,
     MachInst mach_inst =
         TheISA::gtoh(fetchInsts[fetch_offset]);
 
-    predecoder[tid]->setTC(cpu->thread[tid]->getTC());
-    predecoder[tid]->moreBytes(instPC, inst->instAddr(), mach_inst);
-    assert(predecoder[tid]->extMachInstReady());
-    ext_inst = predecoder[tid]->getExtMachInst(instPC);
-
+    decoder[tid]->setTC(cpu->thread[tid]->getTC());
+    decoder[tid]->moreBytes(instPC, inst->instAddr(), mach_inst);
+    assert(decoder[tid]->instReady());
+    inst->setStaticInst(decoder[tid]->decode(instPC));
     inst->pcState(instPC);
-    inst->setStaticInst(decoder.decode(ext_inst, instPC.instAddr()));
 }
 
 void
@@ -582,7 +578,7 @@ void
 FetchUnit::trap(Fault fault, ThreadID tid, DynInstPtr inst)
 {
     //@todo: per thread?
-    predecoder[tid]->reset();
+    decoder[tid]->reset();
 
     //@todo: squash using dummy inst seq num
     squash(NULL, NumStages - 1, 0, tid);
index eb99cd570495413b96b7e3a1469574aea86588db..82d5d99e0804e4cbc1f7fe273327f438fc0f384d 100644 (file)
@@ -37,7 +37,6 @@
 #include <vector>
 
 #include "arch/decoder.hh"
-#include "arch/predecoder.hh"
 #include "arch/tlb.hh"
 #include "config/the_isa.hh"
 #include "cpu/inorder/resources/cache_unit.hh"
@@ -89,7 +88,7 @@ class FetchUnit : public CacheUnit
 
     void trap(Fault fault, ThreadID tid, DynInstPtr inst);
 
-    TheISA::Decoder decoder;
+    TheISA::Decoder *decoder[ThePipeline::MaxThreads];
 
   private:
     void squashCacheRequest(CacheReqPtr req_ptr);
@@ -129,8 +128,6 @@ class FetchUnit : public CacheUnit
 
     int fetchBuffSize;
 
-    TheISA::Predecoder *predecoder[ThePipeline::MaxThreads];
-
     /** Valid Cache Blocks*/
     std::list<FetchBlock*> fetchBuffer;
 
index b7d0dda9c36f58cfff1dd93a1c6975c5d45bc639..9b588cde0e54be6af520ebfa5e3924d38df29a8e 100644 (file)
@@ -83,7 +83,11 @@ class InOrderThreadContext : public ThreadContext
      */
     CheckerCPU *getCheckerCpuPtr() { return NULL; }
 
-    TheISA::Decoder *getDecoderPtr() { return cpu->getDecoderPtr(); }
+    TheISA::Decoder *
+    getDecoderPtr()
+    {
+        return cpu->getDecoderPtr(thread->contextId());
+    }
 
     System *getSystemPtr() { return cpu->system; }
 
index 34c732c54ff8d2e644708c4a01feaf81f391ae41..c000f57fced976530e87368b174c5d468a06ffb2 100644 (file)
@@ -43,7 +43,6 @@
 #include <iomanip>
 
 #include "arch/sparc/decoder.hh"
-#include "arch/sparc/predecoder.hh"
 #include "arch/sparc/registers.hh"
 #include "arch/sparc/utility.hh"
 #include "arch/tlb.hh"
@@ -146,7 +145,6 @@ Trace::LegionTraceRecord::dump()
 {
     ostream &outs = Trace::output();
 
-    static TheISA::Predecoder predecoder(NULL);
     // Compare
     bool compared = false;
     bool diffPC   = false;
@@ -423,15 +421,14 @@ Trace::LegionTraceRecord::dump()
                          << staticInst->disassemble(m5Pc, debugSymbolTable)
                          << endl;
 
-                    predecoder.setTC(thread);
-                    predecoder.moreBytes(m5Pc, m5Pc, shared_data->instruction);
+                    TheISA::Decoder *decoder = thread->getDecoderPtr();
+                    decoder->setTC(thread);
+                    decoder->moreBytes(m5Pc, m5Pc, shared_data->instruction);
 
-                    assert(predecoder.extMachInstReady());
+                    assert(decoder->instReady());
 
                     PCState tempPC = pc;
-                    StaticInstPtr legionInst =
-                        thread->getDecoderPtr()->decode(
-                                predecoder.getExtMachInst(tempPC), lgnPc);
+                    StaticInstPtr legionInst = decoder->decode(tempPC);
                     outs << setfill(' ') << setw(15)
                          << " Legion Inst: "
                          << "0x" << setw(8) << setfill('0') << hex
index 4748348893ef00bc1640895ca15b89dc3cedb994..6bf5f4588629940c3dfc9fac9698748489567c90 100644 (file)
@@ -45,7 +45,6 @@
 #define __CPU_O3_FETCH_HH__
 
 #include "arch/decoder.hh"
-#include "arch/predecoder.hh"
 #include "arch/utility.hh"
 #include "base/statistics.hh"
 #include "config/the_isa.hh"
@@ -340,7 +339,7 @@ class DefaultFetch
     }
 
     /** The decoder. */
-    TheISA::Decoder decoder;
+    TheISA::Decoder *decoder[Impl::MaxThreads];
 
   private:
     DynInstPtr buildInst(ThreadID tid, StaticInstPtr staticInst,
@@ -398,9 +397,6 @@ class DefaultFetch
     /** BPredUnit. */
     BPredUnit branchPred;
 
-    /** Predecoder. */
-    TheISA::Predecoder predecoder;
-
     TheISA::PCState pc[Impl::MaxThreads];
 
     Addr fetchOffset[Impl::MaxThreads];
index f4ce77f227ee26bb0bc319518607bc98abd7c0c2..b6eb25c087df81d5aadf49b14bc5113915914c6a 100644 (file)
@@ -73,7 +73,6 @@ template<class Impl>
 DefaultFetch<Impl>::DefaultFetch(O3CPU *_cpu, DerivO3CPUParams *params)
     : cpu(_cpu),
       branchPred(params),
-      predecoder(NULL),
       numInst(0),
       decodeToFetchDelay(params->decodeToFetchDelay),
       renameToFetchDelay(params->renameToFetchDelay),
@@ -132,6 +131,9 @@ DefaultFetch<Impl>::DefaultFetch(O3CPU *_cpu, DerivO3CPUParams *params)
 
     // Get the size of an instruction.
     instSize = sizeof(TheISA::MachInst);
+
+    for (int i = 0; i < Impl::MaxThreads; i++)
+        decoder[i] = new TheISA::Decoder(NULL);
 }
 
 template <class Impl>
@@ -660,7 +662,7 @@ DefaultFetch<Impl>::finishTranslation(Fault fault, RequestPtr mem_req)
         DPRINTF(Fetch, "[tid:%i]: Translation faulted, building noop.\n", tid);
         // We will use a nop in ordier to carry the fault.
         DynInstPtr instruction = buildInst(tid,
-                decoder.decode(TheISA::NoopMachInst, fetchPC.instAddr()),
+                decoder[tid]->decode(TheISA::NoopMachInst, fetchPC.instAddr()),
                 NULL, fetchPC, fetchPC, false);
 
         instruction->setPredTarg(fetchPC);
@@ -693,7 +695,7 @@ DefaultFetch<Impl>::doSquash(const TheISA::PCState &newPC,
         macroop[tid] = squashInst->macroop;
     else
         macroop[tid] = NULL;
-    predecoder.reset();
+    decoder[tid]->reset();
 
     // Clear the icache miss if it's outstanding.
     if (fetchStatus[tid] == IcacheWaitResponse) {
@@ -1193,8 +1195,9 @@ DefaultFetch<Impl>::fetch(bool &status_change)
 
         // We need to process more memory if we aren't going to get a
         // StaticInst from the rom, the current macroop, or what's already
-        // in the predecoder.
-        bool needMem = !inRom && !curMacroop && !predecoder.extMachInstReady();
+        // in the decoder.
+        bool needMem = !inRom && !curMacroop &&
+            !decoder[tid]->instReady();
         fetchAddr = (thisPC.instAddr() + pcOffset) & BaseCPU::PCMask;
         Addr block_PC = icacheBlockAlignPC(fetchAddr);
 
@@ -1222,10 +1225,10 @@ DefaultFetch<Impl>::fetch(bool &status_change)
             }
             MachInst inst = TheISA::gtoh(cacheInsts[blkOffset]);
 
-            predecoder.setTC(cpu->thread[tid]->getTC());
-            predecoder.moreBytes(thisPC, fetchAddr, inst);
+            decoder[tid]->setTC(cpu->thread[tid]->getTC());
+            decoder[tid]->moreBytes(thisPC, fetchAddr, inst);
 
-            if (predecoder.needMoreBytes()) {
+            if (decoder[tid]->needMoreBytes()) {
                 blkOffset++;
                 fetchAddr += instSize;
                 pcOffset += instSize;
@@ -1236,11 +1239,8 @@ DefaultFetch<Impl>::fetch(bool &status_change)
         // the memory we've processed so far.
         do {
             if (!(curMacroop || inRom)) {
-                if (predecoder.extMachInstReady()) {
-                    ExtMachInst extMachInst =
-                        predecoder.getExtMachInst(thisPC);
-                    staticInst =
-                        decoder.decode(extMachInst, thisPC.instAddr());
+                if (decoder[tid]->instReady()) {
+                    staticInst = decoder[tid]->decode(thisPC);
 
                     // Increment stat of fetched instructions.
                     ++fetchedInsts;
@@ -1311,7 +1311,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
                 status_change = true;
                 break;
             }
-        } while ((curMacroop || predecoder.extMachInstReady()) &&
+        } while ((curMacroop || decoder[tid]->instReady()) &&
                  numInst < fetchWidth);
     }
 
index b4108e25cdf492cfe59032560bd3092d2581de14..5c236ee0cf2e51d177e0f04d68dca8f7ee2f121b 100755 (executable)
@@ -85,7 +85,11 @@ class O3ThreadContext : public ThreadContext
 
     CheckerCPU *getCheckerCpuPtr() { return NULL; }
 
-    TheISA::Decoder *getDecoderPtr() { return &cpu->fetch.decoder; }
+    TheISA::Decoder *
+    getDecoderPtr()
+    {
+        return cpu->fetch.decoder[thread->threadId()];
+    }
 
     /** Returns a pointer to this CPU. */
     virtual BaseCPU *getCpuPtr() { return cpu; }
index 87f41a7218cbc57c4706624598ac51edc8d8c835..f12c2c174b97708c6fba813337811bfd9d80234d 100644 (file)
@@ -465,12 +465,12 @@ AtomicSimpleCPU::tick()
             dcache_access = false; // assume no dcache access
 
             if (needToFetch) {
-                // This is commented out because the predecoder would act like
+                // This is commented out because the decoder would act like
                 // a tiny cache otherwise. It wouldn't be flushed when needed
                 // like the I cache. It should be flushed, and when that works
                 // this code should be uncommented.
                 //Fetch more instruction memory if necessary
-                //if(predecoder.needMoreBytes())
+                //if(decoder.needMoreBytes())
                 //{
                     icache_access = true;
                     Packet ifetch_pkt = Packet(&ifetch_req, MemCmd::ReadReq);
index ca4090870ca6c2eb219b09d9d64c3dfb7f80056e..bdc4b0f44e869eab55485a0aadaa0a517b92975f 100644 (file)
@@ -85,7 +85,7 @@ using namespace std;
 using namespace TheISA;
 
 BaseSimpleCPU::BaseSimpleCPU(BaseSimpleCPUParams *p)
-    : BaseCPU(p), traceData(NULL), thread(NULL), predecoder(NULL)
+    : BaseCPU(p), traceData(NULL), thread(NULL)
 {
     if (FullSystem)
         thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb);
@@ -332,7 +332,7 @@ BaseSimpleCPU::checkForInterrupts()
             fetchOffset = 0;
             interrupts->updateIntrInfo(tc);
             interrupt->invoke(tc);
-            predecoder.reset();
+            thread->decoder.reset();
         }
     }
 }
@@ -378,23 +378,24 @@ BaseSimpleCPU::preExecute()
         //We're not in the middle of a macro instruction
         StaticInstPtr instPtr = NULL;
 
+        TheISA::Decoder *decoder = &(thread->decoder);
+
         //Predecode, ie bundle up an ExtMachInst
         //This should go away once the constructor can be set up properly
-        predecoder.setTC(thread->getTC());
+        decoder->setTC(thread->getTC());
         //If more fetch data is needed, pass it in.
         Addr fetchPC = (pcState.instAddr() & PCMask) + fetchOffset;
-        //if(predecoder.needMoreBytes())
-            predecoder.moreBytes(pcState, fetchPC, inst);
+        //if(decoder->needMoreBytes())
+            decoder->moreBytes(pcState, fetchPC, inst);
         //else
-        //    predecoder.process();
+        //    decoder->process();
 
-        //If an instruction is ready, decode it. Otherwise, we'll have to
+        //Decode an instruction if one is ready. Otherwise, we'll have to
         //fetch beyond the MachInst at the current pc.
-        if (predecoder.extMachInstReady()) {
+        instPtr = decoder->decode(pcState);
+        if (instPtr) {
             stayAtPC = false;
-            ExtMachInst machInst = predecoder.getExtMachInst(pcState);
             thread->pcState(pcState);
-            instPtr = thread->decoder.decode(machInst, pcState.instAddr());
         } else {
             stayAtPC = true;
             fetchOffset += sizeof(MachInst);
@@ -505,7 +506,7 @@ BaseSimpleCPU::advancePC(Fault fault)
     if (fault != NoFault) {
         curMacroStaticInst = StaticInst::nullStaticInstPtr;
         fault->invoke(tc, curStaticInst);
-        predecoder.reset();
+        thread->decoder.reset();
     } else {
         if (curStaticInst) {
             if (curStaticInst->isLastMicroop())
index 34b039fc0ead6f0d2b72bd6d7d2e8db22b779a23..9bf144326d994bd2ef18e2c16c53107efa78bb2b 100644 (file)
@@ -45,8 +45,6 @@
 #ifndef __CPU_SIMPLE_BASE_HH__
 #define __CPU_SIMPLE_BASE_HH__
 
-#include "arch/decoder.hh"
-#include "arch/predecoder.hh"
 #include "base/statistics.hh"
 #include "config/the_isa.hh"
 #include "cpu/base.hh"
@@ -71,7 +69,6 @@ namespace TheISA
 {
     class DTB;
     class ITB;
-    class Predecoder;
 }
 
 namespace Trace {
@@ -154,9 +151,6 @@ class BaseSimpleCPU : public BaseCPU
     // current instruction
     TheISA::MachInst inst;
 
-    // The predecoder
-    TheISA::Predecoder predecoder;
-
     StaticInstPtr curStaticInst;
     StaticInstPtr curMacroStaticInst;
 
index 1781c28500a0d2b1067c1aa8669f8ced8002fa28..c114d04ac05f64ccd38a19459f23deff62832c46 100644 (file)
@@ -63,7 +63,7 @@ SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
                            Process *_process, TheISA::TLB *_itb,
                            TheISA::TLB *_dtb)
     : ThreadState(_cpu, _thread_num, _process), system(_sys), itb(_itb),
-      dtb(_dtb)
+      dtb(_dtb), decoder(NULL)
 {
     clearArchRegs();
     tc = new ProxyThreadContext<SimpleThread>(this);
@@ -71,7 +71,8 @@ SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
 SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
                            TheISA::TLB *_itb, TheISA::TLB *_dtb,
                            bool use_kernel_stats)
-    : ThreadState(_cpu, _thread_num, NULL), system(_sys), itb(_itb), dtb(_dtb)
+    : ThreadState(_cpu, _thread_num, NULL), system(_sys), itb(_itb), dtb(_dtb),
+      decoder(NULL)
 {
     tc = new ProxyThreadContext<SimpleThread>(this);
 
@@ -98,7 +99,7 @@ SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
 }
 
 SimpleThread::SimpleThread()
-    : ThreadState(NULL, -1, NULL)
+    : ThreadState(NULL, -1, NULL), decoder(NULL)
 {
     tc = new ProxyThreadContext<SimpleThread>(this);
 }