Added immediate value support, and fixed alot of bugs. This won't support 3 byte...
authorGabe Black <gblack@eecs.umich.edu>
Thu, 15 Mar 2007 15:29:39 +0000 (15:29 +0000)
committerGabe Black <gblack@eecs.umich.edu>
Thu, 15 Mar 2007 15:29:39 +0000 (15:29 +0000)
--HG--
extra : convert_revision : 4c79bff2592a668e1154916875f019ecafe67022

src/arch/x86/predecoder.hh
src/arch/x86/predecoder_tables.cc
src/arch/x86/types.hh

index 371ce9db98aa4e84ad8b1fad63f5c9e50f502b20..062025a61f1e36b578a3969db0e68a11c7f8f700 100644 (file)
@@ -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;
index 9304eee471487910a0a45caae92a9a138f6163b9..0cebef61a23068ee4b94f57171dbf82926fa2e35 100644 (file)
@@ -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
+        }
+    };
 }
index 68d95de9415b63f20429f9d709bd033825a7f150..583f03d553d4d2089f53b802cfb220b34fd6fa2c 100644 (file)
@@ -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;