X86: Fix the expected size of the immediate offset in MOV_MI.
[gem5.git] / src / arch / x86 / types.hh
index ca4a15d243424704ca4308336507728a2bcd0154..6fd36b487d80f2b8c9be736446464a235bde22b3 100644 (file)
 #ifndef __ARCH_X86_TYPES_HH__
 #define __ARCH_X86_TYPES_HH__
 
-#include <inttypes.h>
 #include <iostream>
 
-#include "base/bitfield.hh"
+#include "base/bitunion.hh"
 #include "base/cprintf.hh"
+#include "base/types.hh"
 
 namespace X86ISA
 {
@@ -70,25 +70,32 @@ 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,
+        ESOverride,
+        CSOverride,
+        SSOverride,
+        DSOverride,
+        FSOverride,
+        GSOverride,
+        RexPrefix,
+        OperandSizeOverride,
+        AddressSizeOverride,
+        Lock,
+        Rep,
+        Repne
+    };
+
+    BitUnion8(LegacyPrefixVector)
+        Bitfield<7, 4> decodeVal;
+        Bitfield<7> repne;
+        Bitfield<6> rep;
+        Bitfield<5> lock;
+        Bitfield<4> op;
+        Bitfield<3> addr;
         //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;
@@ -103,6 +110,9 @@ namespace X86ISA
     EndBitUnion(Sib)
 
     BitUnion8(Rex)
+        //This bit doesn't mean anything according to the ISA, but in
+        //this implementation, it being set means an REX prefix was present.
+        Bitfield<6> present;
         Bitfield<3> w;
         Bitfield<2> r;
         Bitfield<1> x;
@@ -114,11 +124,29 @@ namespace X86ISA
         Bitfield<2,0> bottom3;
     EndBitUnion(Opcode)
 
+    BitUnion8(OperatingMode)
+        Bitfield<3> mode;
+        Bitfield<2,0> submode;
+    EndBitUnion(OperatingMode)
+
+    enum X86Mode {
+        LongMode,
+        LegacyMode
+    };
+
+    enum X86SubMode {
+        SixtyFourBitMode,
+        CompatabilityMode,
+        ProtectedMode,
+        Virtual8086Mode,
+        RealMode
+    };
+
     //The intermediate structure the x86 predecoder returns.
     struct ExtMachInst
     {
         //Prefixes
-        uint8_t legacy;
+        LegacyPrefixVector legacy;
         Rex rex;
         //This holds all of the bytes of the opcode
         struct
@@ -128,18 +156,32 @@ namespace X86ISA
             uint8_t num;
             //The first byte detected in a 2+ byte opcode. Should be 0xF0.
             uint8_t prefixA;
-            //The second byte detected in a 3+ byte opcode. Could be 0xF0 for
-            //3dnow instructions, or 0x38-0x3F for some SSE instructions.
+            //The second byte detected in a 3+ byte opcode. Could be 0x38-0x3F
+            //for some SSE instructions. 3dNow! instructions are handled as
+            //two byte opcodes and then split out further by the immediate
+            //byte.
             uint8_t prefixB;
             //The main opcode byte. The highest addressed byte in the opcode.
             Opcode op;
         } opcode;
         //Modifier bytes
         ModRM modRM;
-        uint8_t sib;
+        Sib sib;
         //Immediate fields
         uint64_t immediate;
         uint64_t displacement;
+
+        //The effective operand size.
+        uint8_t opSize;
+        //The effective address size.
+        uint8_t addrSize;
+        //The effective stack size.
+        uint8_t stackSize;
+        //The size of the displacement
+        uint8_t dispSize;
+
+        //Mode information
+        OperatingMode mode;
     };
 
     inline static std::ostream &
@@ -149,50 +191,55 @@ namespace X86ISA
                      "op = {\n\t\tnum = %d,\n\t\top = %#x,\n\t\t"
                            "prefixA = %#x,\n\t\tprefixB = %#x\n\t},\n\t"
                      "modRM = %#x,\n\tsib = %#x,\n\t"
-                     "immediate = %#x,\n\tdisplacement = %#x\n}\n",
-                     emi.legacy, (uint8_t)emi.rex,
-                     emi.opcode.num, emi.opcode.op,
+                     "immediate = %#x,\n\tdisplacement = %#x\n\t"
+                     "dispSize = %d}\n",
+                     (uint8_t)emi.legacy, (uint8_t)emi.rex,
+                     emi.opcode.num, (uint8_t)emi.opcode.op,
                      emi.opcode.prefixA, emi.opcode.prefixB,
                      (uint8_t)emi.modRM, (uint8_t)emi.sib,
-                     emi.immediate, emi.displacement);
+                     emi.immediate, emi.displacement, emi.dispSize);
         return os;
     }
 
     inline static bool
         operator == (const ExtMachInst &emi1, const ExtMachInst &emi2)
     {
-        //Since this is empty, it's always equal
+        if(emi1.legacy != emi2.legacy)
+            return false;
+        if(emi1.rex != emi2.rex)
+            return false;
+        if(emi1.opcode.num != emi2.opcode.num)
+            return false;
+        if(emi1.opcode.op != emi2.opcode.op)
+            return false;
+        if(emi1.opcode.prefixA != emi2.opcode.prefixA)
+            return false;
+        if(emi1.opcode.prefixB != emi2.opcode.prefixB)
+            return false;
+        if(emi1.modRM != emi2.modRM)
+            return false;
+        if(emi1.sib != emi2.sib)
+            return false;
+        if(emi1.immediate != emi2.immediate)
+            return false;
+        if(emi1.displacement != emi2.displacement)
+            return false;
+        if(emi1.mode != emi2.mode)
+            return false;
+        if(emi1.opSize != emi2.opSize)
+            return false;
+        if(emi1.addrSize != emi2.addrSize)
+            return false;
+        if(emi1.stackSize != emi2.stackSize)
+            return false;
+        if(emi1.dispSize != emi2.dispSize)
+            return false;
         return true;
     }
 
-    typedef uint64_t IntReg;
-    //XXX Should this be a 128 bit structure for XMM memory ops?
-    typedef uint64_t LargestRead;
-    typedef uint64_t MiscReg;
-
-    //These floating point types are correct for mmx, but not
-    //technically for x87 (80 bits) or at all for xmm (128 bits)
-    typedef double FloatReg;
-    typedef uint64_t FloatRegBits;
-    typedef union
-    {
-        IntReg intReg;
-        FloatReg fpReg;
-        MiscReg ctrlReg;
-    } AnyReg;
-
-    //XXX This is very hypothetical. X87 instructions would need to
-    //change their "context" constantly. It's also not clear how
-    //this would be handled as far as out of order execution.
-    //Maybe x87 instructions are in order?
-    enum RegContextParam
-    {
-        CONTEXT_X87_TOP
+    struct CoreSpecific {
+        int core_type;
     };
-
-    typedef int RegContextVal;
-
-    typedef uint8_t RegIndex;
 };
 
 #endif // __ARCH_X86_TYPES_HH__