gem5  v19.0.0.0
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  * Authors: Gabe Black
29  */
30 
31 #ifndef __ARCH_X86_DECODER_HH__
32 #define __ARCH_X86_DECODER_HH__
33 
34 #include <cassert>
35 #include <unordered_map>
36 #include <vector>
37 
38 #include "arch/x86/regs/misc.hh"
39 #include "arch/x86/types.hh"
40 #include "base/bitfield.hh"
41 #include "base/logging.hh"
42 #include "base/trace.hh"
43 #include "base/types.hh"
44 #include "cpu/decode_cache.hh"
45 #include "cpu/static_inst.hh"
46 #include "debug/Decoder.hh"
47 
48 namespace X86ISA
49 {
50 
51 class ISA;
52 class Decoder
53 {
54  private:
55  //These are defined and documented in decoder_tables.cc
56  static const uint8_t SizeTypeToSize[3][10];
57  typedef const uint8_t ByteTable[256];
58  static ByteTable Prefixes;
59 
60  static ByteTable UsesModRMOneByte;
61  static ByteTable UsesModRMTwoByte;
62  static ByteTable UsesModRMThreeByte0F38;
63  static ByteTable UsesModRMThreeByte0F3A;
64 
65  static ByteTable ImmediateTypeOneByte;
66  static ByteTable ImmediateTypeTwoByte;
67  static ByteTable ImmediateTypeThreeByte0F38;
68  static ByteTable ImmediateTypeThreeByte0F3A;
69  static ByteTable ImmediateTypeVex[10];
70 
71  protected:
72  struct InstBytes
73  {
78 
79  InstBytes() : lastOffset(0)
80  {}
81  };
82 
83  static InstBytes dummy;
84 
85  //The bytes to be predecoded
88  int chunkIdx;
89  //The pc of the start of fetchChunk
91  //The pc the current instruction started at
93  //The offset into fetchChunk of current processing
94  int offset;
95  //The extended machine instruction being generated
97  //Predecoding state
98  X86Mode mode;
100  uint8_t altOp;
101  uint8_t defOp;
102  uint8_t altAddr;
103  uint8_t defAddr;
104  uint8_t stack;
105 
106  uint8_t getNextByte()
107  {
108  return ((uint8_t *)&fetchChunk)[offset];
109  }
110 
111  void getImmediate(int &collected, uint64_t &current, int size)
112  {
113  //Figure out how many bytes we still need to get for the
114  //immediate.
115  int toGet = size - collected;
116  //Figure out how many bytes are left in our "buffer"
117  int remaining = sizeof(MachInst) - offset;
118  //Get as much as we need, up to the amount available.
119  toGet = toGet > remaining ? remaining : toGet;
120 
121  //Shift the bytes we want to be all the way to the right
122  uint64_t partialImm = fetchChunk >> (offset * 8);
123  //Mask off what we don't want
124  partialImm &= mask(toGet * 8);
125  //Shift it over to overlay with our displacement.
126  partialImm <<= (immediateCollected * 8);
127  //Put it into our displacement
128  current |= partialImm;
129  //Update how many bytes we've collected.
130  collected += toGet;
131  consumeBytes(toGet);
132  }
133 
135  {
136  assert(offset <= sizeof(MachInst));
137  if (offset == sizeof(MachInst)) {
138  DPRINTF(Decoder, "At the end of a chunk, idx = %d, chunks = %d.\n",
139  chunkIdx, instBytes->chunks.size());
140  chunkIdx++;
141  if (chunkIdx == instBytes->chunks.size()) {
142  outOfBytes = true;
143  } else {
144  offset = 0;
145  fetchChunk = instBytes->chunks[chunkIdx];
146  basePC += sizeof(MachInst);
147  }
148  }
149  }
150 
151  void consumeByte()
152  {
153  offset++;
155  }
156 
157  void consumeBytes(int numBytes)
158  {
159  offset += numBytes;
161  }
162 
163  //State machine state
164  protected:
165  //Whether or not we're out of bytes
167  //Whether we've completed generating an ExtMachInst
168  bool instDone;
169  //The size of the displacement value
171  //The size of the immediate value
173  //This is how much of any immediate value we've gotten. This is used
174  //for both the actual immediate and the displacement.
176 
177  enum State {
193  //We should never get to this state. Getting here is an error.
195  };
196 
198 
199  //Functions to handle each of the states
202  State doPrefixState(uint8_t);
203  State doVex2Of2State(uint8_t);
204  State doVex2Of3State(uint8_t);
205  State doVex3Of3State(uint8_t);
206  State doVexOpcodeState(uint8_t);
207  State doOneByteOpcodeState(uint8_t);
208  State doTwoByteOpcodeState(uint8_t);
211  State doModRMState(uint8_t);
212  State doSIBState(uint8_t);
215 
216  //Process the actual opcode found earlier, using the supplied tables.
217  State processOpcode(ByteTable &immTable, ByteTable &modrmTable,
218  bool addrSizedImm = false);
219  // Process the opcode found with VEX / XOP prefix.
220  State processExtendedOpcode(ByteTable &immTable);
221 
222  protected:
224 
225  typedef RegVal CacheKey;
226 
228  DecodePages *decodePages;
229  typedef std::unordered_map<CacheKey, DecodePages *> AddrCacheMap;
230  AddrCacheMap addrCacheMap;
231 
233  typedef std::unordered_map<
235  static InstCacheMap instCacheMap;
236 
237  public:
238  Decoder(ISA* isa = nullptr) : basePC(0), origPC(0), offset(0),
239  outOfBytes(true), instDone(false),
240  state(ResetState)
241  {
242  emi.reset();
243  mode = LongMode;
244  submode = SixtyFourBitMode;
245  emi.mode.mode = mode;
246  emi.mode.submode = submode;
247  altOp = 0;
248  defOp = 0;
249  altAddr = 0;
250  defAddr = 0;
251  stack = 0;
252  instBytes = &dummy;
253  decodePages = NULL;
254  instMap = NULL;
255  }
256 
257  void setM5Reg(HandyM5Reg m5Reg)
258  {
259  mode = (X86Mode)(uint64_t)m5Reg.mode;
260  submode = (X86SubMode)(uint64_t)m5Reg.submode;
261  emi.mode.mode = mode;
262  emi.mode.submode = submode;
263  altOp = m5Reg.altOp;
264  defOp = m5Reg.defOp;
265  altAddr = m5Reg.altAddr;
266  defAddr = m5Reg.defAddr;
267  stack = m5Reg.stack;
268 
269  AddrCacheMap::iterator amIter = addrCacheMap.find(m5Reg);
270  if (amIter != addrCacheMap.end()) {
271  decodePages = amIter->second;
272  } else {
273  decodePages = new DecodePages;
274  addrCacheMap[m5Reg] = decodePages;
275  }
276 
277  InstCacheMap::iterator imIter = instCacheMap.find(m5Reg);
278  if (imIter != instCacheMap.end()) {
279  instMap = imIter->second;
280  } else {
281  instMap = new DecodeCache::InstMap<ExtMachInst>;
282  instCacheMap[m5Reg] = instMap;
283  }
284  }
285 
287  {
288  mode = old->mode;
289  submode = old->submode;
290  emi.mode.mode = mode;
291  emi.mode.submode = submode;
292  altOp = old->altOp;
293  defOp = old->defOp;
294  altAddr = old->altAddr;
295  defAddr = old->defAddr;
296  stack = old->stack;
297  }
298 
299  void reset()
300  {
301  state = ResetState;
302  }
303 
304  void process();
305 
306  //Use this to give data to the decoder. This should be used
307  //when there is control flow.
308  void moreBytes(const PCState &pc, Addr fetchPC, MachInst data)
309  {
310  DPRINTF(Decoder, "Getting more bytes.\n");
311  basePC = fetchPC;
312  offset = (fetchPC >= pc.instAddr()) ? 0 : pc.instAddr() - fetchPC;
313  fetchChunk = letoh(data);
314  outOfBytes = false;
315  process();
316  }
317 
319  {
320  return outOfBytes;
321  }
322 
323  bool instReady()
324  {
325  return instDone;
326  }
327 
328  void
330  {
331  if (!nextPC.size()) {
332  int size = basePC + offset - origPC;
334  "Calculating the instruction size: "
335  "basePC: %#x offset: %#x origPC: %#x size: %d\n",
336  basePC, offset, origPC, size);
337  nextPC.size(size);
338  nextPC.npc(nextPC.pc() + size);
339  }
340  }
341 
342  public:
344 
350 };
351 
352 } // namespace X86ISA
353 
354 #endif // __ARCH_X86_DECODER_HH__
#define DPRINTF(x,...)
Definition: trace.hh:229
void process()
Definition: decoder.cc:74
static ByteTable UsesModRMThreeByte0F38
Definition: decoder.hh:62
int displacementSize
Definition: decoder.hh:170
RegVal CacheKey
Caching for decoded instruction objects.
Definition: decoder.hh:225
State doVex3Of3State(uint8_t)
Definition: decoder.cc:316
ExtMachInst emi
Definition: decoder.hh:96
uint8_t size() const
Definition: types.hh:314
Addr instAddr() const
Returns the memory address the bytes of this instruction came from.
Definition: types.hh:70
bool needMoreBytes()
Definition: decoder.hh:318
State doVex2Of3State(uint8_t)
Definition: decoder.cc:275
static ByteTable Prefixes
Definition: decoder.hh:58
void updateOffsetState()
Definition: decoder.hh:134
void moreBytes(const PCState &pc, Addr fetchPC, MachInst data)
Definition: decoder.hh:308
State doTwoByteOpcodeState(uint8_t)
Definition: decoder.cc:399
static ByteTable ImmediateTypeVex[10]
Definition: decoder.hh:69
X86Mode mode
Definition: decoder.hh:98
uint64_t RegVal
Definition: types.hh:168
static const uint8_t SizeTypeToSize[3][10]
Definition: decoder.hh:56
X86SubMode submode
Definition: decoder.hh:99
T letoh(T value)
Definition: byteswap.hh:145
Bitfield< 19 > pc
Definition: misc.hh:807
bool instReady()
Definition: decoder.hh:323
std::unordered_map< CacheKey, DecodePages * > AddrCacheMap
Definition: decoder.hh:229
uint8_t altOp
Definition: decoder.hh:100
State doPrefixState(uint8_t)
Definition: decoder.cc:178
StaticInstPtr decodeInst(ExtMachInst mach_inst)
void reset()
Definition: decoder.hh:299
uint8_t defOp
Definition: decoder.hh:101
State doSIBState(uint8_t)
Definition: decoder.cc:565
int immediateCollected
Definition: decoder.hh:175
static ByteTable ImmediateTypeThreeByte0F3A
Definition: decoder.hh:68
static ByteTable UsesModRMOneByte
Definition: decoder.hh:60
DecodePages * decodePages
Definition: decoder.hh:228
uint8_t getNextByte()
Definition: decoder.hh:106
static ByteTable UsesModRMTwoByte
Definition: decoder.hh:61
static InstCacheMap instCacheMap
Definition: decoder.hh:235
X86SubMode
Definition: types.hh:191
uint8_t stack
Definition: decoder.hh:104
mask
Definition: misc.hh:798
State processOpcode(ByteTable &immTable, ByteTable &modrmTable, bool addrSizedImm=false)
Definition: decoder.cc:450
void consumeBytes(int numBytes)
Definition: decoder.hh:157
State doVexOpcodeState(uint8_t)
Definition: decoder.cc:353
void setM5Reg(HandyM5Reg m5Reg)
Definition: decoder.hh:257
uint64_t MachInst
Definition: types.hh:54
static ByteTable ImmediateTypeTwoByte
Definition: decoder.hh:66
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:142
AddrCacheMap addrCacheMap
Definition: decoder.hh:230
static ByteTable ImmediateTypeOneByte
Definition: decoder.hh:65
StaticInstPtr decode(ExtMachInst mach_inst, Addr addr)
Decode a machine instruction.
Definition: decoder.cc:682
Addr npc() const
Definition: types.hh:151
A sparse map from an Addr to a Value, stored in page chunks.
Definition: decode_cache.hh:55
DecodeCache::AddrMap< Decoder::InstBytes > DecodePages
Definition: decoder.hh:227
State doResetState()
Definition: decoder.cc:43
State doVex2Of2State(uint8_t)
Definition: decoder.cc:245
State doModRMState(uint8_t)
Definition: decoder.cc:510
Decoder(ISA *isa=nullptr)
Definition: decoder.hh:238
static InstBytes dummy
Definition: decoder.hh:83
std::vector< MachInst > masks
Definition: decoder.hh:76
InstBytes * instBytes
Definition: decoder.hh:87
This is exposed globally, independent of the ISA.
Definition: acpi.hh:57
DecodeCache::InstMap< ExtMachInst > * instMap
Definition: decoder.hh:232
State doDisplacementState()
Definition: decoder.cc:587
State doOneByteOpcodeState(uint8_t)
Definition: decoder.cc:377
void consumeByte()
Definition: decoder.hh:151
State doThreeByte0F38OpcodeState(uint8_t)
Definition: decoder.cc:422
OperatingMode mode
Definition: types.hh:235
const uint8_t ByteTable[256]
Definition: decoder.hh:57
static ByteTable ImmediateTypeThreeByte0F38
Definition: decoder.hh:67
void takeOverFrom(Decoder *old)
Definition: decoder.hh:286
State doImmediateState()
Definition: decoder.cc:635
MachInst fetchChunk
Definition: decoder.hh:86
std::unordered_map< EMI, StaticInstPtr > InstMap
Hash for decoded instructions.
Definition: decode_cache.hh:51
State doFromCacheState()
Definition: decoder.cc:144
void updateNPC(X86ISA::PCState &nextPC)
Definition: decoder.hh:329
std::vector< MachInst > chunks
Definition: decoder.hh:75
State doThreeByte0F3AOpcodeState(uint8_t)
Definition: decoder.cc:436
State processExtendedOpcode(ByteTable &immTable)
const char data[]
Bitfield< 3 > addr
Definition: types.hh:81
uint8_t altAddr
Definition: decoder.hh:102
std::unordered_map< CacheKey, DecodeCache::InstMap< ExtMachInst > * > InstCacheMap
Definition: decoder.hh:234
uint8_t defAddr
Definition: decoder.hh:103
static ByteTable UsesModRMThreeByte0F3A
Definition: decoder.hh:63
void getImmediate(int &collected, uint64_t &current, int size)
Definition: decoder.hh:111

Generated on Fri Feb 28 2020 16:26:55 for gem5 by doxygen 1.8.13