gem5  v20.0.0.2
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
decoder.hh
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012 Google
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met: redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer;
9  * redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution;
12  * neither the name of the copyright holders nor the names of its
13  * contributors may be used to endorse or promote products derived from
14  * this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #ifndef __ARCH_X86_DECODER_HH__
30 #define __ARCH_X86_DECODER_HH__
31 
32 #include <cassert>
33 #include <unordered_map>
34 #include <vector>
35 
36 #include "arch/x86/regs/misc.hh"
37 #include "arch/x86/types.hh"
38 #include "base/bitfield.hh"
39 #include "base/logging.hh"
40 #include "base/trace.hh"
41 #include "base/types.hh"
42 #include "cpu/decode_cache.hh"
43 #include "cpu/static_inst.hh"
44 #include "debug/Decoder.hh"
45 
46 namespace X86ISA
47 {
48 
49 class ISA;
50 class Decoder
51 {
52  private:
53  //These are defined and documented in decoder_tables.cc
54  static const uint8_t SizeTypeToSize[3][10];
55  typedef const uint8_t ByteTable[256];
56  static ByteTable Prefixes;
57 
58  static ByteTable UsesModRMOneByte;
59  static ByteTable UsesModRMTwoByte;
60  static ByteTable UsesModRMThreeByte0F38;
61  static ByteTable UsesModRMThreeByte0F3A;
62 
63  static ByteTable ImmediateTypeOneByte;
64  static ByteTable ImmediateTypeTwoByte;
65  static ByteTable ImmediateTypeThreeByte0F38;
66  static ByteTable ImmediateTypeThreeByte0F3A;
67  static ByteTable ImmediateTypeVex[10];
68 
69  protected:
70  struct InstBytes
71  {
76 
77  InstBytes() : lastOffset(0)
78  {}
79  };
80 
81  static InstBytes dummy;
82 
83  //The bytes to be predecoded
86  int chunkIdx;
87  //The pc of the start of fetchChunk
89  //The pc the current instruction started at
91  //The offset into fetchChunk of current processing
92  int offset;
93  //The extended machine instruction being generated
95  //Predecoding state
96  X86Mode mode;
98  uint8_t altOp;
99  uint8_t defOp;
100  uint8_t altAddr;
101  uint8_t defAddr;
102  uint8_t stack;
103 
104  uint8_t getNextByte()
105  {
106  return ((uint8_t *)&fetchChunk)[offset];
107  }
108 
109  void getImmediate(int &collected, uint64_t &current, int size)
110  {
111  //Figure out how many bytes we still need to get for the
112  //immediate.
113  int toGet = size - collected;
114  //Figure out how many bytes are left in our "buffer"
115  int remaining = sizeof(MachInst) - offset;
116  //Get as much as we need, up to the amount available.
117  toGet = toGet > remaining ? remaining : toGet;
118 
119  //Shift the bytes we want to be all the way to the right
120  uint64_t partialImm = fetchChunk >> (offset * 8);
121  //Mask off what we don't want
122  partialImm &= mask(toGet * 8);
123  //Shift it over to overlay with our displacement.
124  partialImm <<= (immediateCollected * 8);
125  //Put it into our displacement
126  current |= partialImm;
127  //Update how many bytes we've collected.
128  collected += toGet;
129  consumeBytes(toGet);
130  }
131 
133  {
134  assert(offset <= sizeof(MachInst));
135  if (offset == sizeof(MachInst)) {
136  DPRINTF(Decoder, "At the end of a chunk, idx = %d, chunks = %d.\n",
137  chunkIdx, instBytes->chunks.size());
138  chunkIdx++;
139  if (chunkIdx == instBytes->chunks.size()) {
140  outOfBytes = true;
141  } else {
142  offset = 0;
143  fetchChunk = instBytes->chunks[chunkIdx];
144  basePC += sizeof(MachInst);
145  }
146  }
147  }
148 
149  void consumeByte()
150  {
151  offset++;
153  }
154 
155  void consumeBytes(int numBytes)
156  {
157  offset += numBytes;
159  }
160 
161  //State machine state
162  protected:
163  //Whether or not we're out of bytes
165  //Whether we've completed generating an ExtMachInst
166  bool instDone;
167  //The size of the displacement value
169  //The size of the immediate value
171  //This is how much of any immediate value we've gotten. This is used
172  //for both the actual immediate and the displacement.
174 
175  enum State {
191  //We should never get to this state. Getting here is an error.
193  };
194 
196 
197  //Functions to handle each of the states
200  State doPrefixState(uint8_t);
201  State doVex2Of2State(uint8_t);
202  State doVex2Of3State(uint8_t);
203  State doVex3Of3State(uint8_t);
204  State doVexOpcodeState(uint8_t);
205  State doOneByteOpcodeState(uint8_t);
206  State doTwoByteOpcodeState(uint8_t);
209  State doModRMState(uint8_t);
210  State doSIBState(uint8_t);
213 
214  //Process the actual opcode found earlier, using the supplied tables.
215  State processOpcode(ByteTable &immTable, ByteTable &modrmTable,
216  bool addrSizedImm = false);
217  // Process the opcode found with VEX / XOP prefix.
218  State processExtendedOpcode(ByteTable &immTable);
219 
220  protected:
222 
223  typedef RegVal CacheKey;
224 
226  DecodePages *decodePages;
227  typedef std::unordered_map<CacheKey, DecodePages *> AddrCacheMap;
228  AddrCacheMap addrCacheMap;
229 
231  typedef std::unordered_map<
233  static InstCacheMap instCacheMap;
234 
235  public:
236  Decoder(ISA* isa = nullptr) : basePC(0), origPC(0), offset(0),
237  outOfBytes(true), instDone(false),
238  state(ResetState)
239  {
240  emi.reset();
241  mode = LongMode;
242  submode = SixtyFourBitMode;
243  emi.mode.mode = mode;
244  emi.mode.submode = submode;
245  altOp = 0;
246  defOp = 0;
247  altAddr = 0;
248  defAddr = 0;
249  stack = 0;
250  instBytes = &dummy;
251  decodePages = NULL;
252  instMap = NULL;
253  }
254 
255  void setM5Reg(HandyM5Reg m5Reg)
256  {
257  mode = (X86Mode)(uint64_t)m5Reg.mode;
258  submode = (X86SubMode)(uint64_t)m5Reg.submode;
259  emi.mode.mode = mode;
260  emi.mode.submode = submode;
261  altOp = m5Reg.altOp;
262  defOp = m5Reg.defOp;
263  altAddr = m5Reg.altAddr;
264  defAddr = m5Reg.defAddr;
265  stack = m5Reg.stack;
266 
267  AddrCacheMap::iterator amIter = addrCacheMap.find(m5Reg);
268  if (amIter != addrCacheMap.end()) {
269  decodePages = amIter->second;
270  } else {
271  decodePages = new DecodePages;
272  addrCacheMap[m5Reg] = decodePages;
273  }
274 
275  InstCacheMap::iterator imIter = instCacheMap.find(m5Reg);
276  if (imIter != instCacheMap.end()) {
277  instMap = imIter->second;
278  } else {
279  instMap = new DecodeCache::InstMap<ExtMachInst>;
280  instCacheMap[m5Reg] = instMap;
281  }
282  }
283 
285  {
286  mode = old->mode;
287  submode = old->submode;
288  emi.mode.mode = mode;
289  emi.mode.submode = submode;
290  altOp = old->altOp;
291  defOp = old->defOp;
292  altAddr = old->altAddr;
293  defAddr = old->defAddr;
294  stack = old->stack;
295  }
296 
297  void reset()
298  {
299  state = ResetState;
300  }
301 
302  void process();
303 
304  //Use this to give data to the decoder. This should be used
305  //when there is control flow.
306  void moreBytes(const PCState &pc, Addr fetchPC, MachInst data)
307  {
308  DPRINTF(Decoder, "Getting more bytes.\n");
309  basePC = fetchPC;
310  offset = (fetchPC >= pc.instAddr()) ? 0 : pc.instAddr() - fetchPC;
311  fetchChunk = letoh(data);
312  outOfBytes = false;
313  process();
314  }
315 
317  {
318  return outOfBytes;
319  }
320 
321  bool instReady()
322  {
323  return instDone;
324  }
325 
326  void
328  {
329  if (!nextPC.size()) {
330  int size = basePC + offset - origPC;
332  "Calculating the instruction size: "
333  "basePC: %#x offset: %#x origPC: %#x size: %d\n",
334  basePC, offset, origPC, size);
335  nextPC.size(size);
336  nextPC.npc(nextPC.pc() + size);
337  }
338  }
339 
340  public:
342 
348 };
349 
350 } // namespace X86ISA
351 
352 #endif // __ARCH_X86_DECODER_HH__
#define DPRINTF(x,...)
Definition: trace.hh:222
void process()
Definition: decoder.cc:72
static ByteTable UsesModRMThreeByte0F38
Definition: decoder.hh:60
int displacementSize
Definition: decoder.hh:168
RegVal CacheKey
Caching for decoded instruction objects.
Definition: decoder.hh:223
State doVex3Of3State(uint8_t)
Definition: decoder.cc:314
ExtMachInst emi
Definition: decoder.hh:94
uint8_t size() const
Definition: types.hh:312
Addr instAddr() const
Returns the memory address the bytes of this instruction came from.
Definition: types.hh:68
bool needMoreBytes()
Definition: decoder.hh:316
State doVex2Of3State(uint8_t)
Definition: decoder.cc:273
static ByteTable Prefixes
Definition: decoder.hh:56
void updateOffsetState()
Definition: decoder.hh:132
void moreBytes(const PCState &pc, Addr fetchPC, MachInst data)
Definition: decoder.hh:306
State doTwoByteOpcodeState(uint8_t)
Definition: decoder.cc:397
static ByteTable ImmediateTypeVex[10]
Definition: decoder.hh:67
X86Mode mode
Definition: decoder.hh:96
uint64_t RegVal
Definition: types.hh:166
static const uint8_t SizeTypeToSize[3][10]
Definition: decoder.hh:54
X86SubMode submode
Definition: decoder.hh:97
T letoh(T value)
Definition: byteswap.hh:141
Bitfield< 19 > pc
Definition: misc.hh:805
bool instReady()
Definition: decoder.hh:321
std::unordered_map< CacheKey, DecodePages * > AddrCacheMap
Definition: decoder.hh:227
uint8_t altOp
Definition: decoder.hh:98
State doPrefixState(uint8_t)
Definition: decoder.cc:176
StaticInstPtr decodeInst(ExtMachInst mach_inst)
void reset()
Definition: decoder.hh:297
uint8_t defOp
Definition: decoder.hh:99
State doSIBState(uint8_t)
Definition: decoder.cc:563
int immediateCollected
Definition: decoder.hh:173
static ByteTable ImmediateTypeThreeByte0F3A
Definition: decoder.hh:66
static ByteTable UsesModRMOneByte
Definition: decoder.hh:58
DecodePages * decodePages
Definition: decoder.hh:226
uint8_t getNextByte()
Definition: decoder.hh:104
static ByteTable UsesModRMTwoByte
Definition: decoder.hh:59
static InstCacheMap instCacheMap
Definition: decoder.hh:233
X86SubMode
Definition: types.hh:189
uint8_t stack
Definition: decoder.hh:102
mask
Definition: misc.hh:796
State processOpcode(ByteTable &immTable, ByteTable &modrmTable, bool addrSizedImm=false)
Definition: decoder.cc:448
void consumeBytes(int numBytes)
Definition: decoder.hh:155
State doVexOpcodeState(uint8_t)
Definition: decoder.cc:351
void setM5Reg(HandyM5Reg m5Reg)
Definition: decoder.hh:255
uint64_t MachInst
Definition: types.hh:52
static ByteTable ImmediateTypeTwoByte
Definition: decoder.hh:64
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,16,32,64}_t.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:140
AddrCacheMap addrCacheMap
Definition: decoder.hh:228
static ByteTable ImmediateTypeOneByte
Definition: decoder.hh:63
StaticInstPtr decode(ExtMachInst mach_inst, Addr addr)
Decode a machine instruction.
Definition: decoder.cc:680
Addr npc() const
Definition: types.hh:149
A sparse map from an Addr to a Value, stored in page chunks.
Definition: decode_cache.hh:53
DecodeCache::AddrMap< Decoder::InstBytes > DecodePages
Definition: decoder.hh:225
State doResetState()
Definition: decoder.cc:41
State doVex2Of2State(uint8_t)
Definition: decoder.cc:243
State doModRMState(uint8_t)
Definition: decoder.cc:508
Decoder(ISA *isa=nullptr)
Definition: decoder.hh:236
static InstBytes dummy
Definition: decoder.hh:81
std::vector< MachInst > masks
Definition: decoder.hh:74
InstBytes * instBytes
Definition: decoder.hh:85
This is exposed globally, independent of the ISA.
Definition: acpi.hh:55
DecodeCache::InstMap< ExtMachInst > * instMap
Definition: decoder.hh:230
State doDisplacementState()
Definition: decoder.cc:585
State doOneByteOpcodeState(uint8_t)
Definition: decoder.cc:375
void consumeByte()
Definition: decoder.hh:149
State doThreeByte0F38OpcodeState(uint8_t)
Definition: decoder.cc:420
OperatingMode mode
Definition: types.hh:233
const uint8_t ByteTable[256]
Definition: decoder.hh:55
static ByteTable ImmediateTypeThreeByte0F38
Definition: decoder.hh:65
void takeOverFrom(Decoder *old)
Definition: decoder.hh:284
State doImmediateState()
Definition: decoder.cc:633
MachInst fetchChunk
Definition: decoder.hh:84
std::unordered_map< EMI, StaticInstPtr > InstMap
Hash for decoded instructions.
Definition: decode_cache.hh:49
State doFromCacheState()
Definition: decoder.cc:142
void updateNPC(X86ISA::PCState &nextPC)
Definition: decoder.hh:327
std::vector< MachInst > chunks
Definition: decoder.hh:73
State doThreeByte0F3AOpcodeState(uint8_t)
Definition: decoder.cc:434
State processExtendedOpcode(ByteTable &immTable)
const char data[]
Bitfield< 3 > addr
Definition: types.hh:79
uint8_t altAddr
Definition: decoder.hh:100
std::unordered_map< CacheKey, DecodeCache::InstMap< ExtMachInst > * > InstCacheMap
Definition: decoder.hh:232
uint8_t defAddr
Definition: decoder.hh:101
static ByteTable UsesModRMThreeByte0F3A
Definition: decoder.hh:61
void getImmediate(int &collected, uint64_t &current, int size)
Definition: decoder.hh:109

Generated on Mon Jun 8 2020 15:34:38 for gem5 by doxygen 1.8.13