Clean up the code a little, fix (I think) a perceived problem with immediate sizes...
authorGabe Black <gblack@eecs.umich.edu>
Fri, 6 Apr 2007 15:19:23 +0000 (15:19 +0000)
committerGabe Black <gblack@eecs.umich.edu>
Fri, 6 Apr 2007 15:19:23 +0000 (15:19 +0000)
--HG--
extra : convert_revision : e59b747198cc79d50045bd2dc45b2e2b97bbffcc

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

index 80971e7cfb8350a38015d8aff610be0f86564a84..573012ee6d3cf3e9b94fd500974b33c4d1ed5207 100644 (file)
@@ -117,37 +117,33 @@ namespace X86ISA
             //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:
-            DPRINTF(Predecoder, "Found cs segment override.\n");
-            break;
           case DSOverride:
-            DPRINTF(Predecoder, "Found ds segment override.\n");
-            break;
           case ESOverride:
-            DPRINTF(Predecoder, "Found es segment override.\n");
-            break;
           case FSOverride:
-            DPRINTF(Predecoder, "Found fs segment override.\n");
-            break;
           case GSOverride:
-            DPRINTF(Predecoder, "Found gs segment override.\n");
-            break;
           case SSOverride:
-            DPRINTF(Predecoder, "Found ss segment override.\n");
+            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);
@@ -198,16 +194,36 @@ namespace X86ISA
             displacementCollected = 0;
             emi.displacement = 0;
 
+            //Figure out the effective operand size. This can be overriden to
+            //a fixed value at the decoder level.
+            if(/*FIXME long mode*/1)
+            {
+                if(emi.rex && emi.rex.w)
+                    emi.opSize = 3; // 64 bit operand size
+                else if(emi.legacy.op)
+                    emi.opSize = 1; // 16 bit operand size
+                else
+                    emi.opSize = 2; // 32 bit operand size
+            }
+            else if(/*FIXME default 32*/1)
+            {
+                if(emi.legacy.op)
+                    emi.opSize = 1; // 16 bit operand size
+                else
+                    emi.opSize = 2; // 32 bit operand size
+            }
+            else // 16 bit default operand size
+            {
+                if(emi.legacy.op)
+                    emi.opSize = 2; // 32 bit operand size
+                else
+                    emi.opSize = 1; // 16 bit operand size
+            }
+
             //Figure out how big of an immediate we'll retreive based
             //on the opcode.
-            int immType = ImmediateType[
-                emi.opcode.num - 1][nextByte];
-            if(0) //16 bit mode
-                immediateSize = ImmediateTypeToSize[0][immType];
-            else if(!(emi.rex & 0x4)) //32 bit mode
-                immediateSize = ImmediateTypeToSize[1][immType];
-            else //64 bit mode
-                immediateSize = ImmediateTypeToSize[2][immType];
+            int immType = ImmediateType[emi.opcode.num - 1][nextByte];
+            immediateSize = SizeTypeToSize[emi.opSize - 1][immType];
 
             //Determine what to expect next
             if (UsesModRM[emi.opcode.num - 1][nextByte]) {
@@ -351,6 +367,16 @@ namespace X86ISA
 
         if(immediateSize == immediateCollected)
         {
+            //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.
+            if(immediateSize == 4)
+                emi.immediate = sext<32>(emi.immediate);
             DPRINTF(Predecoder, "Collected immediate %#x.\n",
                     emi.immediate);
             emiIsReady = true;
index 1df17d6d2f80dc306a0ae61ed47afa19fba3fca0..6562ab9f5e8754f4006be09c2a1e118de4add23a 100644 (file)
@@ -73,7 +73,7 @@ namespace X86ISA
         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];
+        static const uint8_t SizeTypeToSize[3][10];
 
       protected:
         ThreadContext * tc;
index f233ad234d3be5fb5072b32dd45626dd97f8816d..38b9c57a389caf4de98ec8f91314d95e399cf5ee 100644 (file)
@@ -141,7 +141,7 @@ namespace X86ISA
         }
     };
 
-    enum ImmediateTypes {
+    enum SizeType {
         NoImm,
         NI = NoImm,
         ByteImm,
@@ -158,19 +158,19 @@ namespace X86ISA
         VW = VWordImm,
         ZWordImm,
         ZW = ZWordImm,
-        Pointer,
-        PO = Pointer,
         //The enter instruction takes -2- immediates for a total of 3 bytes
         Enter,
-        EN = Enter
+        EN = Enter,
+        Pointer,
+        PO = Pointer
     };
 
-    const uint8_t Predecoder::ImmediateTypeToSize[3][10] =
+    const uint8_t Predecoder::SizeTypeToSize[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
+//       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,   4,    8,    3,    0      }  //64 bit
     };
 
     //This table determines the immediate type. The first index is the
index cdac3c00ee23f24d9d15ef50e7c7bf57bb152eca..022f20ee589ed1f07a7cfd2fa36910e5e51dbbef 100644 (file)
@@ -70,25 +70,31 @@ namespace X86ISA
     typedef uint64_t MachInst;
 
     enum Prefixes {
-        NoOverride = 0,
-        CSOverride = 1,
-        DSOverride = 2,
-        ESOverride = 3,
-        FSOverride = 4,
-        GSOverride = 5,
-        SSOverride = 6,
-        //The Rex prefix obviously doesn't fit in with the above, but putting
-        //it here lets us save double the space the enums take up.
-        RexPrefix = 7,
+        NoOverride,
+        CSOverride,
+        DSOverride,
+        ESOverride,
+        FSOverride,
+        GSOverride,
+        SSOverride,
+        RexPrefix,
+        OperandSizeOverride,
+        AddressSizeOverride,
+        Lock,
+        Rep,
+        Repne
+    };
+
+    BitUnion8(LegacyPrefixVector)
+        Bitfield<7> repne;
+        Bitfield<6> rep;
+        Bitfield<5> lock;
+        Bitfield<4> addr;
+        Bitfield<3> op;
         //There can be only one segment override, so they share the
         //first 3 bits in the legacyPrefixes bitfield.
-        SegmentOverride = 0x7,
-        OperandSizeOverride = 8,
-        AddressSizeOverride = 16,
-        Lock = 32,
-        Rep = 64,
-        Repne = 128
-    };
+        Bitfield<2,0> seg;
+    EndBitUnion(LegacyPrefixVector)
 
     BitUnion8(ModRM)
         Bitfield<7,6> mod;
@@ -118,7 +124,7 @@ namespace X86ISA
     struct ExtMachInst
     {
         //Prefixes
-        uint8_t legacy;
+        LegacyPrefixVector legacy;
         Rex rex;
         //This holds all of the bytes of the opcode
         struct
@@ -140,6 +146,10 @@ namespace X86ISA
         //Immediate fields
         uint64_t immediate;
         uint64_t displacement;
+
+        //The effective operand size.
+        uint8_t opSize;
+        //The
     };
 
     inline static std::ostream &
index e0bd0951558aaf98efeb14656d1b0ca5f818d66c..1c98e7fbcf17505fc37843bf1c484f9dd946ca2c 100644 (file)
@@ -78,7 +78,8 @@ namespace __hash_namespace {
                     ((uint64_t)emi.opcode.prefixA << 16) |
                     ((uint64_t)emi.opcode.prefixB << 8) |
                     ((uint64_t)emi.opcode.op)) ^
-                    emi.immediate ^ emi.displacement;
+                    emi.immediate ^ emi.displacement ^
+                    emi.opSize;
         };
     };
 }