gem5  v22.1.0.0
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/generic/decoder.hh"
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 #include "params/X86Decoder.hh"
48 
49 namespace gem5
50 {
51 
52 class BaseISA;
53 
54 namespace X86ISA
55 {
56 
57 class Decoder : public InstDecoder
58 {
59  private:
60  // These are defined and documented in decoder_tables.cc
61  static const uint8_t SizeTypeToSize[3][10];
62  typedef const uint8_t ByteTable[256];
63  static ByteTable Prefixes[2];
64 
69 
74 
76 
77  protected:
78  using MachInst = uint64_t;
79 
80  struct InstBytes
81  {
86 
88  {}
89  };
90 
91  static InstBytes dummy;
92 
93  // The bytes to be predecoded.
96  int chunkIdx;
97  // The pc of the start of fetchChunk.
98  Addr basePC = 0;
99  // The pc the current instruction started at.
101  // The offset into fetchChunk of current processing.
102  int offset = 0;
103  // The extended machine instruction being generated.
105  // Predecoding state.
106  X86Mode mode = LongMode;
108  uint8_t altOp = 0;
109  uint8_t defOp = 0;
110  uint8_t altAddr = 0;
111  uint8_t defAddr = 0;
112  uint8_t stack = 0;
113 
114  uint8_t cpl = 0;
115 
116  uint8_t
118  {
119  return ((uint8_t *)&fetchChunk)[offset];
120  }
121 
122  void
123  getImmediate(int &collected, uint64_t &current, int size)
124  {
125  // Figure out how many bytes we still need to get for the
126  // immediate.
127  int toGet = size - collected;
128  // Figure out how many bytes are left in our "buffer".
129  int remaining = sizeof(MachInst) - offset;
130  // Get as much as we need, up to the amount available.
131  toGet = toGet > remaining ? remaining : toGet;
132 
133  // Shift the bytes we want to be all the way to the right
134  uint64_t partialImm = fetchChunk >> (offset * 8);
135  // Mask off what we don't want.
136  partialImm &= mask(toGet * 8);
137  // Shift it over to overlay with our displacement.
138  partialImm <<= (immediateCollected * 8);
139  // Put it into our displacement.
140  current |= partialImm;
141  // Update how many bytes we've collected.
142  collected += toGet;
143  consumeBytes(toGet);
144  }
145 
146  void
148  {
149  assert(offset <= sizeof(MachInst));
150  if (offset == sizeof(MachInst)) {
151  DPRINTF(Decoder, "At the end of a chunk, idx = %d, chunks = %d.\n",
152  chunkIdx, instBytes->chunks.size());
153  chunkIdx++;
154  if (chunkIdx == instBytes->chunks.size()) {
155  outOfBytes = true;
156  } else {
157  offset = 0;
159  basePC += sizeof(MachInst);
160  }
161  }
162  }
163 
164  void
166  {
167  offset++;
169  }
170 
171  void
172  consumeBytes(int numBytes)
173  {
174  offset += numBytes;
176  }
177 
178  // State machine state.
179  protected:
180  // The size of the displacement value.
182  // The size of the immediate value.
184  // This is how much of any immediate value we've gotten. This is used
185  // for both the actual immediate and the displacement.
187 
188  enum State
189  {
205  // We should never get to this state. Getting here is an error.
206  ErrorState
207  };
208 
210 
211  // Functions to handle each of the states
214  State doPrefixState(uint8_t);
215  State doVex2Of2State(uint8_t);
216  State doVex2Of3State(uint8_t);
217  State doVex3Of3State(uint8_t);
218  State doVexOpcodeState(uint8_t);
219  State doOneByteOpcodeState(uint8_t);
220  State doTwoByteOpcodeState(uint8_t);
223  State doModRMState(uint8_t);
224  State doSIBState(uint8_t);
227 
228  // Process the actual opcode found earlier, using the supplied tables.
229  State processOpcode(ByteTable &immTable, ByteTable &modrmTable,
230  bool addrSizedImm = false);
231  // Process the opcode found with VEX / XOP prefix.
233 
234  protected:
236 
237  typedef RegVal CacheKey;
238 
241  typedef std::unordered_map<CacheKey, DecodePages *> AddrCacheMap;
243 
245  typedef std::unordered_map<
248 
250 
255 
256  void process();
257 
258  public:
259  Decoder(const X86DecoderParams &p) : InstDecoder(p, &fetchChunk)
260  {
261  emi.reset();
262  emi.mode.cpl = cpl;
263  emi.mode.mode = mode;
264  emi.mode.submode = submode;
265  }
266 
267  void
268  setM5Reg(HandyM5Reg m5Reg)
269  {
270  cpl = m5Reg.cpl;
271  mode = (X86Mode)(uint64_t)m5Reg.mode;
272  submode = (X86SubMode)(uint64_t)m5Reg.submode;
273  emi.mode.cpl = cpl;
274  emi.mode.mode = mode;
275  emi.mode.submode = submode;
276  altOp = m5Reg.altOp;
277  defOp = m5Reg.defOp;
278  altAddr = m5Reg.altAddr;
279  defAddr = m5Reg.defAddr;
280  stack = m5Reg.stack;
281 
282  AddrCacheMap::iterator amIter = addrCacheMap.find(m5Reg);
283  if (amIter != addrCacheMap.end()) {
284  decodePages = amIter->second;
285  } else {
286  decodePages = new DecodePages;
287  addrCacheMap[m5Reg] = decodePages;
288  }
289 
290  InstCacheMap::iterator imIter = instCacheMap.find(m5Reg);
291  if (imIter != instCacheMap.end()) {
292  instMap = imIter->second;
293  } else {
295  instCacheMap[m5Reg] = instMap;
296  }
297  }
298 
299  void
300  takeOverFrom(InstDecoder *old) override
301  {
303 
304  Decoder *dec = dynamic_cast<Decoder *>(old);
305  assert(dec);
306 
307  cpl = dec->cpl;
308  mode = dec->mode;
309  submode = dec->submode;
310  emi.mode.cpl = cpl;
311  emi.mode.mode = mode;
312  emi.mode.submode = submode;
313  altOp = dec->altOp;
314  defOp = dec->defOp;
315  altAddr = dec->altAddr;
316  defAddr = dec->defAddr;
317  stack = dec->stack;
318  }
319 
320  void
321  reset() override
322  {
324  state = ResetState;
325  }
326 
327  // Use this to give data to the decoder. This should be used
328  // when there is control flow.
329  void
330  moreBytes(const PCStateBase &pc, Addr fetchPC) override
331  {
332  DPRINTF(Decoder, "Getting more bytes.\n");
333  basePC = fetchPC;
334  offset = (fetchPC >= pc.instAddr()) ? 0 : pc.instAddr() - fetchPC;
336  outOfBytes = false;
337  process();
338  }
339 
340  void
342  {
343  if (!nextPC.size()) {
344  int size = basePC + offset - origPC;
346  "Calculating the instruction size: "
347  "basePC: %#x offset: %#x origPC: %#x size: %d\n",
348  basePC, offset, origPC, size);
349  nextPC.size(size);
350  nextPC.npc(nextPC.pc() + size);
351  }
352  }
353 
354  public:
355  StaticInstPtr decode(PCStateBase &next_pc) override;
356 
358  MicroPC micropc, StaticInstPtr curMacroop) override;
359 };
360 
361 } // namespace X86ISA
362 } // namespace gem5
363 
364 #endif // __ARCH_X86_DECODER_HH__
#define DPRINTF(x,...)
Definition: trace.hh:186
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,...
virtual void takeOverFrom(InstDecoder *old)
Take over the state from an old decoder when switching CPUs.
Definition: decoder.hh:89
virtual void reset()
Definition: decoder.hh:63
State doPrefixState(uint8_t)
Definition: decoder.cc:182
std::unordered_map< CacheKey, decode_cache::InstMap< ExtMachInst > * > InstCacheMap
Definition: decoder.hh:246
StaticInstPtr decode(ExtMachInst mach_inst, Addr addr)
Decode a machine instruction.
Definition: decoder.cc:678
ExtMachInst emi
Definition: decoder.hh:104
static ByteTable ImmediateTypeTwoByte
Definition: decoder.hh:71
State processExtendedOpcode(ByteTable &immTable)
State doFromCacheState()
Definition: decoder.cc:148
void consumeBytes(int numBytes)
Definition: decoder.hh:172
DecodePages * decodePages
Definition: decoder.hh:240
StaticInstPtr fetchRomMicroop(MicroPC micropc, StaticInstPtr curMacroop) override
Definition: decoder.cc:740
InstBytes * instBytes
Definition: decoder.hh:95
void updateOffsetState()
Definition: decoder.hh:147
State doThreeByte0F3AOpcodeState(uint8_t)
Definition: decoder.cc:439
static ByteTable UsesModRMTwoByte
Definition: decoder.hh:66
AddrCacheMap addrCacheMap
Definition: decoder.hh:242
uint8_t getNextByte()
Definition: decoder.hh:117
void updateNPC(X86ISA::PCState &nextPC)
Definition: decoder.hh:341
State doVex3Of3State(uint8_t)
Definition: decoder.cc:319
decode_cache::InstMap< ExtMachInst > * instMap
Definition: decoder.hh:244
static InstBytes dummy
Definition: decoder.hh:91
static ByteTable UsesModRMThreeByte0F3A
Definition: decoder.hh:68
State doVexOpcodeState(uint8_t)
Definition: decoder.cc:356
void takeOverFrom(InstDecoder *old) override
Take over the state from an old decoder when switching CPUs.
Definition: decoder.hh:300
State doDisplacementState()
Definition: decoder.cc:588
decode_cache::AddrMap< Decoder::InstBytes > DecodePages
Definition: decoder.hh:239
RegVal CacheKey
Caching for decoded instruction objects.
Definition: decoder.hh:237
const uint8_t ByteTable[256]
Definition: decoder.hh:62
State doVex2Of2State(uint8_t)
Definition: decoder.cc:248
static ByteTable ImmediateTypeThreeByte0F38
Definition: decoder.hh:72
State doVex2Of3State(uint8_t)
Definition: decoder.cc:278
Decoder(const X86DecoderParams &p)
Definition: decoder.hh:259
void getImmediate(int &collected, uint64_t &current, int size)
Definition: decoder.hh:123
State processOpcode(ByteTable &immTable, ByteTable &modrmTable, bool addrSizedImm=false)
Definition: decoder.cc:453
static ByteTable UsesModRMThreeByte0F38
Definition: decoder.hh:67
StaticInstPtr decodeInst(ExtMachInst mach_inst)
State doImmediateState()
Definition: decoder.cc:635
X86SubMode submode
Definition: decoder.hh:107
static InstCacheMap instCacheMap
Definition: decoder.hh:247
State doOneByteOpcodeState(uint8_t)
Definition: decoder.cc:380
MachInst fetchChunk
Definition: decoder.hh:94
static const uint8_t SizeTypeToSize[3][10]
Definition: decoder.hh:61
State doResetState()
Definition: decoder.cc:47
State doTwoByteOpcodeState(uint8_t)
Definition: decoder.cc:402
static X86ISAInst::MicrocodeRom microcodeRom
Definition: decoder.hh:75
void setM5Reg(HandyM5Reg m5Reg)
Definition: decoder.hh:268
static ByteTable ImmediateTypeThreeByte0F3A
Definition: decoder.hh:73
State doThreeByte0F38OpcodeState(uint8_t)
Definition: decoder.cc:425
static ByteTable ImmediateTypeOneByte
Definition: decoder.hh:70
State doSIBState(uint8_t)
Definition: decoder.cc:567
State doModRMState(uint8_t)
Definition: decoder.cc:513
void reset() override
Definition: decoder.hh:321
void moreBytes(const PCStateBase &pc, Addr fetchPC) override
Feed data to the decoder.
Definition: decoder.hh:330
std::unordered_map< CacheKey, DecodePages * > AddrCacheMap
Definition: decoder.hh:241
static ByteTable UsesModRMOneByte
Definition: decoder.hh:65
uint8_t size() const
Definition: pcstate.hh:87
A sparse map from an Addr to a Value, stored in page chunks.
Definition: decode_cache.hh:52
Bitfield< 19 > pc
Definition: misc.hh:812
Bitfield< 3 > addr
Definition: types.hh:84
Bitfield< 0 > p
Definition: pagetable.hh:151
@ SixtyFourBitMode
Definition: types.hh:204
std::unordered_map< EMI, StaticInstPtr > InstMap
Hash for decoded instructions.
Definition: decode_cache.hh:47
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
T letoh(T value)
Definition: byteswap.hh:173
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
uint16_t MicroPC
Definition: types.hh:149
uint64_t RegVal
Definition: types.hh:173
std::vector< MachInst > chunks
Definition: decoder.hh:83
std::vector< MachInst > masks
Definition: decoder.hh:84
OperatingModeAndCPL mode
Definition: types.hh:245

Generated on Wed Dec 21 2022 10:22:24 for gem5 by doxygen 1.9.1