types.hh revision 11975:a4ba6d5b9774
1/*
2 * Copyright (c) 2007 The Hewlett-Packard Development Company
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Gabe Black
38 */
39
40#ifndef __ARCH_X86_TYPES_HH__
41#define __ARCH_X86_TYPES_HH__
42
43#include <iostream>
44
45#include "arch/generic/types.hh"
46#include "base/bitunion.hh"
47#include "base/cprintf.hh"
48#include "base/types.hh"
49#include "sim/serialize.hh"
50
51namespace X86ISA
52{
53    //This really determines how many bytes are passed to the decoder.
54    typedef uint64_t MachInst;
55
56    enum Prefixes {
57        NoOverride,
58        ESOverride,
59        CSOverride,
60        SSOverride,
61        DSOverride,
62        FSOverride,
63        GSOverride,
64        RexPrefix,
65        OperandSizeOverride,
66        AddressSizeOverride,
67        Lock,
68        Rep,
69        Repne,
70        Vex2Prefix,
71        Vex3Prefix,
72        XopPrefix,
73    };
74
75    BitUnion8(LegacyPrefixVector)
76        Bitfield<7, 4> decodeVal;
77        Bitfield<7> repne;
78        Bitfield<6> rep;
79        Bitfield<5> lock;
80        Bitfield<4> op;
81        Bitfield<3> addr;
82        //There can be only one segment override, so they share the
83        //first 3 bits in the legacyPrefixes bitfield.
84        Bitfield<2,0> seg;
85    EndBitUnion(LegacyPrefixVector)
86
87    BitUnion8(ModRM)
88        Bitfield<7,6> mod;
89        Bitfield<5,3> reg;
90        Bitfield<2,0> rm;
91    EndBitUnion(ModRM)
92
93    BitUnion8(Sib)
94        Bitfield<7,6> scale;
95        Bitfield<5,3> index;
96        Bitfield<2,0> base;
97    EndBitUnion(Sib)
98
99    BitUnion8(Rex)
100        //This bit doesn't mean anything according to the ISA, but in
101        //this implementation, it being set means an REX prefix was present.
102        Bitfield<6> present;
103        Bitfield<3> w;
104        Bitfield<2> r;
105        Bitfield<1> x;
106        Bitfield<0> b;
107    EndBitUnion(Rex)
108
109    BitUnion(uint32_t, ThreeByteVex)
110        Bitfield<7,0> zero;
111        SubBitUnion(first, 15, 8)
112            // Inverted one-bit extension of ModRM reg field
113            Bitfield<15> r;
114            // Inverted one-bit extension of SIB index field
115            Bitfield<14> x;
116            // Inverted one-bit extension, r/m field or SIB base field
117            Bitfield<13> b;
118            // Opcode map select
119            Bitfield<12, 8> map_select;
120        EndSubBitUnion(first)
121        SubBitUnion(second, 23, 16)
122            // Default operand size override for a general purpose register to
123            // 64-bit size in 64-bit mode; operand configuration specifier for
124            // certain YMM/XMM-based operations.
125            Bitfield<23> w;
126            // Source or destination register selector, in ones' complement
127            // format
128            Bitfield<22, 19>  vvvv;
129            // Vector length specifier
130            Bitfield<18> l;
131            // Implied 66, F2, or F3 opcode extension
132            Bitfield<17, 16> pp;
133        EndSubBitUnion(second)
134    EndBitUnion(ThreeByteVex)
135
136    BitUnion16(TwoByteVex)
137        Bitfield<7,0> zero;
138        SubBitUnion(first, 15, 8)
139            // Inverted one-bit extension of ModRM reg field
140            Bitfield<15> r;
141            // Source or destination register selector, in ones' complement
142            // format
143            Bitfield<14, 11>  vvvv;
144            // Vector length specifier
145            Bitfield<10> l;
146            // Implied 66, F2, or F3 opcode extension
147            Bitfield<9, 8> pp;
148        EndSubBitUnion(first)
149    EndBitUnion(TwoByteVex)
150
151    enum OpcodeType {
152        BadOpcode,
153        OneByteOpcode,
154        TwoByteOpcode,
155        ThreeByte0F38Opcode,
156        ThreeByte0F3AOpcode,
157        Vex,
158    };
159
160    static inline const char *
161    opcodeTypeToStr(OpcodeType type)
162    {
163        switch (type) {
164          case BadOpcode:
165            return "bad";
166          case OneByteOpcode:
167            return "one byte";
168          case TwoByteOpcode:
169            return "two byte";
170          case ThreeByte0F38Opcode:
171            return "three byte 0f38";
172          case ThreeByte0F3AOpcode:
173            return "three byte 0f3a";
174          case Vex:
175            return "vex";
176          default:
177            return "unrecognized!";
178        }
179    }
180
181    BitUnion8(Opcode)
182        Bitfield<7,3> top5;
183        Bitfield<2,0> bottom3;
184    EndBitUnion(Opcode)
185
186    BitUnion8(OperatingMode)
187        Bitfield<3> mode;
188        Bitfield<2,0> submode;
189    EndBitUnion(OperatingMode)
190
191    enum X86Mode {
192        LongMode,
193        LegacyMode
194    };
195
196    enum X86SubMode {
197        SixtyFourBitMode,
198        CompatabilityMode,
199        ProtectedMode,
200        Virtual8086Mode,
201        RealMode
202    };
203
204    //The intermediate structure used by the x86 decoder.
205    struct ExtMachInst
206    {
207        //Prefixes
208        LegacyPrefixVector legacy;
209        Rex rex;
210        // We use the following field for encoding both two byte and three byte
211        // escape sequences
212        ThreeByteVex vex;
213
214        //This holds all of the bytes of the opcode
215        struct
216        {
217            OpcodeType type;
218            //The main opcode byte. The highest addressed byte in the opcode.
219            Opcode op;
220        } opcode;
221        //Modifier bytes
222        ModRM modRM;
223        Sib sib;
224        //Immediate fields
225        uint64_t immediate;
226        uint64_t displacement;
227
228        //The effective operand size.
229        uint8_t opSize;
230        //The effective address size.
231        uint8_t addrSize;
232        //The effective stack size.
233        uint8_t stackSize;
234        //The size of the displacement
235        uint8_t dispSize;
236
237        //Mode information
238        OperatingMode mode;
239    };
240
241    inline static std::ostream &
242        operator << (std::ostream & os, const ExtMachInst & emi)
243    {
244        ccprintf(os, "\n{\n\tleg = %#x,\n\trex = %#x,\n\t"
245                     "vex/xop = %#x,\n\t"
246                     "op = {\n\t\ttype = %s,\n\t\top = %#x,\n\t\t},\n\t"
247                     "modRM = %#x,\n\tsib = %#x,\n\t"
248                     "immediate = %#x,\n\tdisplacement = %#x\n\t"
249                     "dispSize = %d}\n",
250                     (uint8_t)emi.legacy, (uint8_t)emi.rex,
251                     (uint32_t)emi.vex,
252                     opcodeTypeToStr(emi.opcode.type), (uint8_t)emi.opcode.op,
253                     (uint8_t)emi.modRM, (uint8_t)emi.sib,
254                     emi.immediate, emi.displacement, emi.dispSize);
255        return os;
256    }
257
258    inline static bool
259        operator == (const ExtMachInst &emi1, const ExtMachInst &emi2)
260    {
261        if (emi1.legacy != emi2.legacy)
262            return false;
263        if (emi1.rex != emi2.rex)
264            return false;
265        if (emi1.opcode.type != emi2.opcode.type)
266            return false;
267        if (emi1.opcode.op != emi2.opcode.op)
268            return false;
269        if (emi1.modRM != emi2.modRM)
270            return false;
271        if (emi1.sib != emi2.sib)
272            return false;
273        if (emi1.immediate != emi2.immediate)
274            return false;
275        if (emi1.displacement != emi2.displacement)
276            return false;
277        if (emi1.mode != emi2.mode)
278            return false;
279        if (emi1.opSize != emi2.opSize)
280            return false;
281        if (emi1.addrSize != emi2.addrSize)
282            return false;
283        if (emi1.stackSize != emi2.stackSize)
284            return false;
285        if (emi1.dispSize != emi2.dispSize)
286            return false;
287        return true;
288    }
289
290    class PCState : public GenericISA::UPCState<MachInst>
291    {
292      protected:
293        typedef GenericISA::UPCState<MachInst> Base;
294
295        uint8_t _size;
296
297      public:
298        void
299        set(Addr val)
300        {
301            Base::set(val);
302            _size = 0;
303        }
304
305        PCState() {}
306        PCState(Addr val) { set(val); }
307
308        void
309        setNPC(Addr val)
310        {
311            Base::setNPC(val);
312            _size = 0;
313        }
314
315        uint8_t size() const { return _size; }
316        void size(uint8_t newSize) { _size = newSize; }
317
318        bool
319        branching() const
320        {
321            return (this->npc() != this->pc() + size()) ||
322                   (this->nupc() != this->upc() + 1);
323        }
324
325        void
326        advance()
327        {
328            Base::advance();
329            _size = 0;
330        }
331
332        void
333        uEnd()
334        {
335            Base::uEnd();
336            _size = 0;
337        }
338
339        void
340        serialize(CheckpointOut &cp) const
341        {
342            Base::serialize(cp);
343            SERIALIZE_SCALAR(_size);
344        }
345
346        void
347        unserialize(CheckpointIn &cp)
348        {
349            Base::unserialize(cp);
350            UNSERIALIZE_SCALAR(_size);
351        }
352    };
353
354}
355
356namespace std {
357    template<>
358    struct hash<X86ISA::ExtMachInst> {
359        size_t operator()(const X86ISA::ExtMachInst &emi) const {
360            return (((uint64_t)emi.legacy << 40) |
361                    ((uint64_t)emi.rex  << 32) |
362                    ((uint64_t)emi.modRM << 24) |
363                    ((uint64_t)emi.sib << 16) |
364                    ((uint64_t)emi.opcode.type << 8) |
365                    ((uint64_t)emi.opcode.op)) ^
366                    emi.immediate ^ emi.displacement ^
367                    emi.mode ^
368                    emi.opSize ^ emi.addrSize ^
369                    emi.stackSize ^ emi.dispSize;
370        };
371    };
372}
373
374// These two functions allow ExtMachInst to be used with SERIALIZE_SCALAR
375// and UNSERIALIZE_SCALAR.
376template <>
377void
378paramOut(CheckpointOut &cp, const std::string &name,
379         const X86ISA::ExtMachInst &machInst);
380template <>
381void
382paramIn(CheckpointIn &cp, const std::string &name,
383        X86ISA::ExtMachInst &machInst);
384
385#endif // __ARCH_X86_TYPES_HH__
386