From 075df1469f0244f1800b261b65eeac8bb3f460b9 Mon Sep 17 00:00:00 2001
From: Gabe Black <gblack@eecs.umich.edu>
Date: Thu, 15 Mar 2007 15:29:39 +0000
Subject: Added immediate value support, and fixed alot of bugs. This won't
 support 3 byte opcodes.

--HG--
extra : convert_revision : 4c79bff2592a668e1154916875f019ecafe67022
---
 src/arch/x86/predecoder.hh        | 65 +++++++++++++++++++-------------
 src/arch/x86/predecoder_tables.cc | 79 +++++++++++++++++++++++++++++++++++++++
 src/arch/x86/types.hh             |  6 ++-
 3 files changed, 122 insertions(+), 28 deletions(-)

(limited to 'src/arch')

diff --git a/src/arch/x86/predecoder.hh b/src/arch/x86/predecoder.hh
index 371ce9db9..062025a61 100644
--- a/src/arch/x86/predecoder.hh
+++ b/src/arch/x86/predecoder.hh
@@ -70,8 +70,11 @@ 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 ImmediateTypeToSize[3][10];
 
       protected:
         ThreadContext * tc;
@@ -193,10 +196,11 @@ namespace X86ISA
                         break;
                       case Rex:
                         warn("Found Rex prefix %#x!\n", nextByte);
+                        emi.rexPrefix = nextByte;
                         offset++;
                         break;
                       case 0:
-                        emi.twoByteOpcode = false;
+                        emi.numOpcodes = 0;
                         state = Opcode;
                         break;
                       default:
@@ -204,20 +208,30 @@ namespace X86ISA
                     }
                     break;
                   case Opcode:
+                    emi.numOpcodes++;
+                    assert(emi.numOpcodes < 2);
                     if(nextByte == 0xf0)
                     {
                         warn("Found two byte opcode!\n");
-                        emi.twoByteOpcode = true;
                     }
                     else
                     {
+                        immediateCollected = 0;
+                        displacementCollected = 0;
+                        emi.immediate = 0;
+                        emi.displacement = 0;
+                        int immType = ImmediateType[
+                            emi.numOpcodes - 1][nextByte];
+                        if(0) //16 bit mode
+                            immediateSize = ImmediateTypeToSize[0][immType];
+                        else if(!(emi.rexPrefix & 0x4)) //32 bit mode
+                            immediateSize = ImmediateTypeToSize[1][immType];
+                        else //64 bit mode
+                            immediateSize = ImmediateTypeToSize[2][immType];
                         warn("Found opcode %#x!\n", nextByte);
-                        if (UsesModRM[emi.twoByteOpcode ? 1 : 0][nextByte]) {
+                        if (UsesModRM[emi.numOpcodes - 1][nextByte]) {
                             state = ModRM;
-                        } else if(0 /* uses immediate */) {
-                            //Figure out how big the immediate should be
-                            immediateCollected = 0;
-                            emi.immediate = 0;
+                        } else if(immediateSize) {
                             state = Immediate;
                         } else {
                             emiIsReady = true;
@@ -231,21 +245,21 @@ namespace X86ISA
                     if (0) {//in 16 bit mode
                         //figure out 16 bit displacement size
                         if(nextByte & 0xC7 == 0x06 ||
-                                nextByte & 0xC0 == 0x40)
-                            displacementSize = 1;
-                        else if(nextByte & 0xC7 == 0x80)
+                                nextByte & 0xC0 == 0x80)
                             displacementSize = 2;
+                        else if(nextByte & 0xC0 == 0x40)
+                            displacementSize = 1;
                         else
                             displacementSize = 0;
                     } else {
                         //figure out 32/64 bit displacement size
-                        if(nextByte & 0xC7 == 0x06 ||
-                                nextByte & 0xC0 == 0x40)
+                        if(nextByte & 0xC7 == 0x05 ||
+                                nextByte & 0xC0 == 0x80)
                             displacementSize = 4;
-                        else if(nextByte & 0xC7 == 0x80)
+                        else if(nextByte & 0xC0 == 0x40)
                             displacementSize = 2;
                         else
-                            displacementSize = 4;
+                            displacementSize = 0;
                     }
                     //If there's an SIB, get that next.
                     //There is no SIB in 16 bit mode.
@@ -254,12 +268,8 @@ namespace X86ISA
                             // && in 32/64 bit mode)
                         state = SIB;
                     } else if(displacementSize) {
-                        displacementCollected = 0;
-                        emi.displacement = 0;
                         state = Displacement;
                     } else if(immediateSize) {
-                        immediateCollected = 0;
-                        emi.immediate = 0;
                         state = Immediate;
                     } else {
                         emiIsReady = true;
@@ -272,12 +282,8 @@ namespace X86ISA
                     warn("Found SIB byte %#x!\n", nextByte);
                     offset++;
                     if(displacementSize) {
-                        displacementCollected = 0;
-                        emi.displacement = 0;
                         state = Displacement;
                     } else if(immediateSize) {
-                        immediateCollected = 0;
-                        emi.immediate = 0;
                         state = Immediate;
                     } else {
                         emiIsReady = true;
@@ -306,6 +312,9 @@ namespace X86ISA
                     emi.displacement |= partialDisp;
                     //Update how many bytes we've collected.
                     displacementCollected += toGet;
+                    offset += toGet;
+                    warn("Collecting %d byte displacement, got %d bytes!\n",
+                            displacementSize, toGet);
 
                     if(displacementSize == displacementCollected) {
                         //Sign extend the displacement
@@ -324,8 +333,6 @@ namespace X86ISA
                             panic("Undefined displacement size!\n");
                         }
                         if(immediateSize) {
-                            immediateCollected = 0;
-                            emi.immediate = 0;
                             state = Immediate;
                         } else {
                             emiIsReady = true;
@@ -350,11 +357,15 @@ namespace X86ISA
                     //Mask off what we don't want
                     partialDisp &= mask(toGet * 8);
                     //Shift it over to overlay with our immediate.
-                    partialDisp <<= displacementCollected;
+                    partialDisp <<= immediateCollected;
                     //Put it into our immediate
-                    emi.displacement |= partialDisp;
+                    emi.immediate |= partialDisp;
                     //Update how many bytes we've collected.
-                    displacementCollected += toGet;
+                    immediateCollected += toGet;
+                    offset += toGet;
+                    warn("Collecting %d byte immediate, got %d bytes!\n",
+                            immediateSize, toGet);
+
                     if(immediateSize == immediateCollected)
                     {
                         emiIsReady = true;
diff --git a/src/arch/x86/predecoder_tables.cc b/src/arch/x86/predecoder_tables.cc
index 9304eee47..0cebef61a 100644
--- a/src/arch/x86/predecoder_tables.cc
+++ b/src/arch/x86/predecoder_tables.cc
@@ -140,4 +140,83 @@ namespace X86ISA
 /*      F */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0
         }
     };
+
+    enum ImmediateTypes {
+        NoImm,
+        NI = NoImm,
+        ByteImm,
+        BY = ByteImm,
+        WordImm,
+        WO = WordImm,
+        DWordImm,
+        DW = DWordImm,
+        QWordImm,
+        QW = QWordImm,
+        OWordImm,
+        OW = OWordImm,
+        VWordImm,
+        VW = VWordImm,
+        ZWordImm,
+        ZW = ZWordImm,
+        Pointer,
+        PO = Pointer,
+        //The enter instruction takes -2- immediates for a total of 3 bytes
+        Enter,
+        EN = Enter
+    };
+
+    const uint8_t Predecoder::ImmediateTypeToSize[3][10] =
+    {
+//       noimm byte word dword qword oword vword zword enter
+        {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,   4,    8,    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 */ BY, VW, BY, 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 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+/*      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, 0 , 0 , 0 , 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
+        }
+    };
 }
diff --git a/src/arch/x86/types.hh b/src/arch/x86/types.hh
index 68d95de94..583f03d55 100644
--- a/src/arch/x86/types.hh
+++ b/src/arch/x86/types.hh
@@ -94,7 +94,11 @@ namespace X86ISA
 
         uint8_t legacyPrefixes;
         uint8_t rexPrefix;
-        bool twoByteOpcode;
+        //Right now, we ignore that this can be 3 in
+        //some cases
+        uint8_t numOpcodes;
+        //This will need to be decoded specially later
+        bool is3dnow;
         uint8_t opcode;
         uint64_t immediate;
         uint64_t displacement;
-- 
cgit v1.2.3


From 6cdd434f7f94afc81aa09c411c00969cd80cc833 Mon Sep 17 00:00:00 2001
From: Gabe Black <gblack@eecs.umich.edu>
Date: Thu, 15 Mar 2007 16:13:40 +0000
Subject: Changed warns to DPRINTFs and multiply by 8 where needed.

--HG--
extra : convert_revision : 9db0bc2420ceb5828a79881fa0b420a2d5e5f358
---
 src/arch/x86/predecoder.hh | 69 +++++++++++++++++++++-------------------------
 1 file changed, 31 insertions(+), 38 deletions(-)

(limited to 'src/arch')

diff --git a/src/arch/x86/predecoder.hh b/src/arch/x86/predecoder.hh
index 062025a61..f1dee6bf4 100644
--- a/src/arch/x86/predecoder.hh
+++ b/src/arch/x86/predecoder.hh
@@ -61,6 +61,7 @@
 #include "arch/x86/types.hh"
 #include "base/bitfield.hh"
 #include "base/misc.hh"
+#include "base/trace.hh"
 #include "sim/host.hh"
 
 class ThreadContext;
@@ -136,7 +137,6 @@ namespace X86ISA
 
         void process()
         {
-            warn("About to process some bytes\n");
             assert(!outOfBytes);
             assert(!emiIsReady);
             while(!emiIsReady && !outOfBytes)
@@ -146,58 +146,48 @@ namespace X86ISA
                 {
                   case Prefix:
                     uint8_t prefix = Prefixes[nextByte];
+                    if(prefix)
+                        offset++;
                     switch(prefix)
                     {
                         //Operand size override prefixes
                       case OperandSizeOverride:
-                        warn("Found operand size override prefix!\n");
-                        offset++;
+                        DPRINTF(Predecoder, "Found operand size override prefix.\n");
                         break;
                       case AddressSizeOverride:
-                        warn("Found address size override prefix!\n");
-                        offset++;
+                        DPRINTF(Predecoder, "Found address size override prefix.\n");
                         break;
                         //Segment override prefixes
                       case CSOverride:
-                        warn("Found cs segment override!\n");
-                        offset++;
+                        DPRINTF(Predecoder, "Found cs segment override.\n");
                         break;
                       case DSOverride:
-                        warn("Found ds segment override!\n");
-                        offset++;
+                        DPRINTF(Predecoder, "Found ds segment override.\n");
                         break;
                       case ESOverride:
-                        warn("Found es segment override!\n");
-                        offset++;
+                        DPRINTF(Predecoder, "Found es segment override.\n");
                         break;
                       case FSOverride:
-                        warn("Found fs segment override!\n");
-                        offset++;
+                        DPRINTF(Predecoder, "Found fs segment override.\n");
                         break;
                       case GSOverride:
-                        warn("Found gs segment override!\n");
-                        offset++;
+                        DPRINTF(Predecoder, "Found gs segment override.\n");
                         break;
                       case SSOverride:
-                        warn("Found ss segment override!\n");
-                        offset++;
+                        DPRINTF(Predecoder, "Found ss segment override.\n");
                         break;
                       case Lock:
-                        warn("Found lock prefix!\n");
-                        offset++;
+                        DPRINTF(Predecoder, "Found lock prefix.\n");
                         break;
                       case Rep:
-                        warn("Found rep prefix!\n");
-                        offset++;
+                        DPRINTF(Predecoder, "Found rep prefix.\n");
                         break;
                       case Repne:
-                        warn("Found repne prefix!\n");
-                        offset++;
+                        DPRINTF(Predecoder, "Found repne prefix.\n");
                         break;
                       case Rex:
-                        warn("Found Rex prefix %#x!\n", nextByte);
+                        DPRINTF(Predecoder, "Found Rex prefix %#x.\n", nextByte);
                         emi.rexPrefix = nextByte;
-                        offset++;
                         break;
                       case 0:
                         emi.numOpcodes = 0;
@@ -212,7 +202,7 @@ namespace X86ISA
                     assert(emi.numOpcodes < 2);
                     if(nextByte == 0xf0)
                     {
-                        warn("Found two byte opcode!\n");
+                        DPRINTF(Predecoder, "Found two byte opcode.\n");
                     }
                     else
                     {
@@ -228,7 +218,7 @@ namespace X86ISA
                             immediateSize = ImmediateTypeToSize[1][immType];
                         else //64 bit mode
                             immediateSize = ImmediateTypeToSize[2][immType];
-                        warn("Found opcode %#x!\n", nextByte);
+                        DPRINTF(Predecoder, "Found opcode %#x.\n", nextByte);
                         if (UsesModRM[emi.numOpcodes - 1][nextByte]) {
                             state = ModRM;
                         } else if(immediateSize) {
@@ -241,7 +231,7 @@ namespace X86ISA
                     offset++;
                     break;
                   case ModRM:
-                    warn("Found modrm byte %#x!\n", nextByte);
+                    DPRINTF(Predecoder, "Found modrm byte %#x.\n", nextByte);
                     if (0) {//in 16 bit mode
                         //figure out 16 bit displacement size
                         if(nextByte & 0xC7 == 0x06 ||
@@ -279,7 +269,7 @@ namespace X86ISA
                     offset++;
                     break;
                   case SIB:
-                    warn("Found SIB byte %#x!\n", nextByte);
+                    DPRINTF(Predecoder, "Found SIB byte %#x.\n", nextByte);
                     offset++;
                     if(displacementSize) {
                         state = Displacement;
@@ -303,18 +293,18 @@ namespace X86ISA
                     toGet = toGet > remaining ? remaining : toGet;
 
                     //Shift the bytes we want to be all the way to the right
-                    partialDisp = fetchChunk >> offset;
+                    partialDisp = fetchChunk >> (offset * 8);
                     //Mask off what we don't want
                     partialDisp &= mask(toGet * 8);
                     //Shift it over to overlay with our displacement.
-                    partialDisp <<= displacementCollected;
+                    partialDisp <<= (displacementCollected * 8);
                     //Put it into our displacement
                     emi.displacement |= partialDisp;
                     //Update how many bytes we've collected.
                     displacementCollected += toGet;
                     offset += toGet;
-                    warn("Collecting %d byte displacement, got %d bytes!\n",
-                            displacementSize, toGet);
+                    DPRINTF(Predecoder, "Collecting %d byte displacement, got %d bytes.\n",
+                            displacementSize, displacementCollected);
 
                     if(displacementSize == displacementCollected) {
                         //Sign extend the displacement
@@ -332,6 +322,8 @@ namespace X86ISA
                           default:
                             panic("Undefined displacement size!\n");
                         }
+                        DPRINTF(Predecoder, "Collected displacement %#x.\n",
+                                emi.displacement);
                         if(immediateSize) {
                             state = Immediate;
                         } else {
@@ -353,21 +345,23 @@ namespace X86ISA
                     toGet = toGet > remaining ? remaining : toGet;
 
                     //Shift the bytes we want to be all the way to the right
-                    partialDisp = fetchChunk >> offset;
+                    partialDisp = fetchChunk >> (offset * 8);
                     //Mask off what we don't want
                     partialDisp &= mask(toGet * 8);
                     //Shift it over to overlay with our immediate.
-                    partialDisp <<= immediateCollected;
+                    partialDisp <<= (immediateCollected * 8);
                     //Put it into our immediate
                     emi.immediate |= partialDisp;
                     //Update how many bytes we've collected.
                     immediateCollected += toGet;
                     offset += toGet;
-                    warn("Collecting %d byte immediate, got %d bytes!\n",
-                            immediateSize, toGet);
+                    DPRINTF(Predecoder, "Collecting %d byte immediate, got %d bytes.\n",
+                            immediateSize, immediateCollected);
 
                     if(immediateSize == immediateCollected)
                     {
+                        DPRINTF(Predecoder, "Collected immediate %#x.\n",
+                                emi.immediate);
                         emiIsReady = true;
                         state = Prefix;
                     }
@@ -389,7 +383,6 @@ namespace X86ISA
             fetchChunk = data;
             assert(off < sizeof(MachInst));
             outOfBytes = false;
-            warn("About to call process.\n");
             process();
         }
 
-- 
cgit v1.2.3