Merge zizzer.eecs.umich.edu:/bk/newmem
[gem5.git] / src / arch / x86 / types.hh
index 747d173e4b31efacff37906c1af0403e6ab2b31c..298dff80b239383b27d1e5aae0cb6fe9c0f3a02a 100644 (file)
 #ifndef __ARCH_X86_TYPES_HH__
 #define __ARCH_X86_TYPES_HH__
 
-#error X86 is not yet supported!
+#include <inttypes.h>
+#include <iostream>
+
+#include "base/bitfield.hh"
+#include "base/cprintf.hh"
 
 namespace X86ISA
 {
+    //This really determines how many bytes are passed to the predecoder.
+    typedef uint64_t MachInst;
+
+    enum Prefixes {
+        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.
+        Bitfield<2,0> seg;
+    EndBitUnion(LegacyPrefixVector)
+
+    BitUnion8(ModRM)
+        Bitfield<7,6> mod;
+        Bitfield<5,3> reg;
+        Bitfield<2,0> rm;
+    EndBitUnion(ModRM)
+
+    BitUnion8(Sib)
+        Bitfield<7,6> scale;
+        Bitfield<5,3> index;
+        Bitfield<2,0> base;
+    EndBitUnion(Sib)
+
+    BitUnion8(Rex)
+        Bitfield<3> w;
+        Bitfield<2> r;
+        Bitfield<1> x;
+        Bitfield<0> b;
+    EndBitUnion(Rex)
+
+    BitUnion8(Opcode)
+        Bitfield<7,3> top5;
+        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
+        LegacyPrefixVector legacy;
+        Rex rex;
+        //This holds all of the bytes of the opcode
+        struct
+        {
+            //The number of bytes in this opcode. Right now, we ignore that
+            //this can be 3 in some cases
+            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.
+            uint8_t prefixB;
+            //The main opcode byte. The highest addressed byte in the opcode.
+            Opcode op;
+        } opcode;
+        //Modifier bytes
+        ModRM modRM;
+        uint8_t 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;
+
+        //Mode information
+        OperatingMode mode;
+    };
+
+    inline static std::ostream &
+        operator << (std::ostream & os, const ExtMachInst & emi)
+    {
+        ccprintf(os, "\n{\n\tleg = %#x,\n\trex = %#x,\n\t"
+                     "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,
+                     emi.opcode.prefixA, emi.opcode.prefixB,
+                     (uint8_t)emi.modRM, (uint8_t)emi.sib,
+                     emi.immediate, emi.displacement);
+        return os;
+    }
+
+    inline static bool
+        operator == (const ExtMachInst &emi1, const ExtMachInst &emi2)
+    {
+        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;
+        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
+    };
+
+    typedef int RegContextVal;
+
+    typedef uint8_t RegIndex;
 };
 
 #endif // __ARCH_X86_TYPES_HH__