gem5 [DEVELOP-FOR-25.0]
Loading...
Searching...
No Matches
decoder.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2011 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#include "arch/x86/decoder.hh"
30
31#include "arch/x86/regs/misc.hh"
32#include "base/logging.hh"
33#include "base/trace.hh"
34#include "base/types.hh"
35#include "debug/Decode.hh"
36#include "debug/Decoder.hh"
37
38namespace gem5
39{
40
41namespace X86ISA
42{
43
46{
48 DPRINTF(Decoder, "Setting origPC to %#x\n", origPC);
49 instBytes.reset();
50 chunkIdx = 0;
51
52 emi.rex = 0;
53 emi.legacy = 0;
54 emi.vex = 0;
55
56 emi.opcode.type = BadOpcode;
57 emi.opcode.op = 0;
58
60 emi.immediate = 0;
61 emi.displacement = 0;
62 emi.dispSize = 0;
63
64 emi.modRM = 0;
65 emi.sib = 0;
66
67 return PrefixState;
68}
69
70void
72{
73 // This function drives the decoder state machine.
74
75 // Some sanity checks. You shouldn't try to process more bytes if
76 // there aren't any, and you shouldn't overwrite an already decoded
77 // ExtMachInst.
78 assert(!outOfBytes);
79 assert(!instDone);
80
81 if (state == ResetState) {
83 }
84
85 instBytes.chunks.push_back(fetchChunk);
86
87 // While there's still something to do...
88 while (!instDone && !outOfBytes) {
89 uint8_t nextByte = getNextByte();
90 switch (state) {
91 case PrefixState:
92 state = doPrefixState(nextByte);
93 break;
94 case Vex2Of2State:
95 state = doVex2Of2State(nextByte);
96 break;
97 case Vex2Of3State:
98 state = doVex2Of3State(nextByte);
99 break;
100 case Vex3Of3State:
101 state = doVex3Of3State(nextByte);
102 break;
103 case VexOpcodeState:
104 state = doVexOpcodeState(nextByte);
105 break;
107 state = doOneByteOpcodeState(nextByte);
108 break;
110 state = doTwoByteOpcodeState(nextByte);
111 break;
114 break;
117 break;
118 case ModRMState:
119 state = doModRMState(nextByte);
120 break;
121 case SIBState:
122 state = doSIBState(nextByte);
123 break;
126 break;
127 case ImmediateState:
129 break;
130 case ErrorState:
131 panic("Went to the error state in the decoder.\n");
132 default:
133 panic("Unrecognized state! %d\n", state);
134 }
135 }
136}
137
138// Either get a prefix and record it in the ExtMachInst, or send the
139// state machine on to get the opcode(s).
141Decoder::doPrefixState(uint8_t nextByte)
142{
143 // The REX and VEX prefixes only exist in 64 bit mode, so we use a
144 // different table for that.
145 const int table_idx = emi.mode.submode == SixtyFourBitMode ? 1 : 0;
146 const uint8_t prefix = Prefixes[table_idx][nextByte];
147 State nextState = PrefixState;
148 if (prefix)
149 consumeByte();
150 switch(prefix) {
151 // Operand size override prefixes
153 DPRINTF(Decoder, "Found operand size override prefix.\n");
154 emi.legacy.op = true;
155 break;
157 DPRINTF(Decoder, "Found address size override prefix.\n");
158 emi.legacy.addr = true;
159 break;
160 // Segment override prefixes
161 case CSOverride:
162 case DSOverride:
163 case ESOverride:
164 case FSOverride:
165 case GSOverride:
166 case SSOverride:
167 DPRINTF(Decoder, "Found segment override.\n");
168 emi.legacy.seg = prefix;
169 break;
170 case Lock:
171 DPRINTF(Decoder, "Found lock prefix.\n");
172 emi.legacy.lock = true;
173 break;
174 case Rep:
175 DPRINTF(Decoder, "Found rep prefix.\n");
176 emi.legacy.rep = true;
177 break;
178 case Repne:
179 DPRINTF(Decoder, "Found repne prefix.\n");
180 emi.legacy.repne = true;
181 break;
182 case RexPrefix:
183 DPRINTF(Decoder, "Found Rex prefix %#x.\n", nextByte);
184 emi.rex = nextByte;
185 break;
186 case Vex2Prefix:
187 DPRINTF(Decoder, "Found VEX two-byte prefix %#x.\n", nextByte);
188 emi.vex.present = 1;
189 nextState = Vex2Of2State;
190 break;
191 case Vex3Prefix:
192 DPRINTF(Decoder, "Found VEX three-byte prefix %#x.\n", nextByte);
193 emi.vex.present = 1;
194 nextState = Vex2Of3State;
195 break;
196 case 0:
197 nextState = OneByteOpcodeState;
198 break;
199
200 default:
201 panic("Unrecognized prefix %#x\n", nextByte);
202 }
203 return nextState;
204}
205
207Decoder::doVex2Of2State(uint8_t nextByte)
208{
209 consumeByte();
210 Vex2Of2 vex = nextByte;
211
212 emi.rex.r = !vex.r;
213
214 emi.vex.l = vex.l;
215 emi.vex.v = ~vex.v;
216
217 switch (vex.p) {
218 case 0:
219 break;
220 case 1:
221 emi.legacy.op = 1;
222 break;
223 case 2:
224 emi.legacy.rep = 1;
225 break;
226 case 3:
227 emi.legacy.repne = 1;
228 break;
229 }
230
231 emi.opcode.type = TwoByteOpcode;
232
233 return VexOpcodeState;
234}
235
237Decoder::doVex2Of3State(uint8_t nextByte)
238{
239 if (emi.mode.submode != SixtyFourBitMode && bits(nextByte, 7, 6) == 0x3) {
240 // This was actually an LDS instruction. Reroute to that path.
241 emi.vex.present = 0;
242 emi.opcode.type = OneByteOpcode;
243 emi.opcode.op = 0xC4;
245 nextByte >= 0xA0 && nextByte <= 0xA3);
246 }
247
248 consumeByte();
249 Vex2Of3 vex = nextByte;
250
251 emi.rex.r = !vex.r;
252 emi.rex.x = !vex.x;
253 emi.rex.b = !vex.b;
254
255 switch (vex.m) {
256 case 1:
257 emi.opcode.type = TwoByteOpcode;
258 break;
259 case 2:
260 emi.opcode.type = ThreeByte0F38Opcode;
261 break;
262 case 3:
263 emi.opcode.type = ThreeByte0F3AOpcode;
264 break;
265 default:
266 // These encodings are reserved. Pretend this was an undefined
267 // instruction so the main decoder will behave correctly, and stop
268 // trying to interpret bytes.
269 emi.opcode.type = TwoByteOpcode;
270 emi.opcode.op = 0x0B;
271 instDone = true;
272 return ResetState;
273 }
274 return Vex3Of3State;
275}
276
278Decoder::doVex3Of3State(uint8_t nextByte)
279{
280 if (emi.mode.submode != SixtyFourBitMode && bits(nextByte, 7, 6) == 0x3) {
281 // This was actually an LES instruction. Reroute to that path.
282 emi.vex.present = 0;
283 emi.opcode.type = OneByteOpcode;
284 emi.opcode.op = 0xC5;
286 nextByte >= 0xA0 && nextByte <= 0xA3);
287 }
288
289 consumeByte();
290 Vex3Of3 vex = nextByte;
291
292 emi.rex.w = vex.w;
293
294 emi.vex.l = vex.l;
295 emi.vex.v = ~vex.v;
296
297 switch (vex.p) {
298 case 0:
299 break;
300 case 1:
301 emi.legacy.op = 1;
302 break;
303 case 2:
304 emi.legacy.rep = 1;
305 break;
306 case 3:
307 emi.legacy.repne = 1;
308 break;
309 }
310
311 return VexOpcodeState;
312}
313
316{
317 DPRINTF(Decoder, "Found VEX opcode %#x.\n", nextByte);
318
319 emi.opcode.op = nextByte;
320 consumeByte();
321
322 switch (emi.opcode.type) {
323 case TwoByteOpcode:
325 case ThreeByte0F38Opcode:
328 case ThreeByte0F3AOpcode:
331 default:
332 panic("Unrecognized opcode type %d.\n", emi.opcode.type);
333 }
334}
335
336// Load the first opcode byte. Determine if there are more opcode bytes, and
337// if not, what immediate and/or ModRM is needed.
340{
341 State nextState = ErrorState;
342 consumeByte();
343
344 if (nextByte == 0x0f) {
345 DPRINTF(Decoder, "Found opcode escape byte %#x.\n", nextByte);
346 nextState = TwoByteOpcodeState;
347 } else {
348 DPRINTF(Decoder, "Found one byte opcode %#x.\n", nextByte);
349 emi.opcode.type = OneByteOpcode;
350 emi.opcode.op = nextByte;
351
353 nextByte >= 0xA0 && nextByte <= 0xA3);
354 }
355 return nextState;
356}
357
358// Load the second opcode byte. Determine if there are more opcode bytes, and
359// if not, what immediate and/or ModRM is needed.
362{
363 State nextState = ErrorState;
364 consumeByte();
365 if (nextByte == 0x38) {
366 nextState = ThreeByte0F38OpcodeState;
367 DPRINTF(Decoder, "Found opcode escape byte %#x.\n", nextByte);
368 } else if (nextByte == 0x3a) {
369 nextState = ThreeByte0F3AOpcodeState;
370 DPRINTF(Decoder, "Found opcode escape byte %#x.\n", nextByte);
371 } else {
372 DPRINTF(Decoder, "Found two byte opcode %#x.\n", nextByte);
373 emi.opcode.type = TwoByteOpcode;
374 emi.opcode.op = nextByte;
375
377 }
378 return nextState;
379}
380
381// Load the third opcode byte and determine what immediate and/or ModRM is
382// needed.
385{
386 consumeByte();
387
388 DPRINTF(Decoder, "Found three byte 0F38 opcode %#x.\n", nextByte);
389 emi.opcode.type = ThreeByte0F38Opcode;
390 emi.opcode.op = nextByte;
391
393}
394
395// Load the third opcode byte and determine what immediate and/or ModRM is
396// needed.
399{
400 consumeByte();
401
402 DPRINTF(Decoder, "Found three byte 0F3A opcode %#x.\n", nextByte);
403 emi.opcode.type = ThreeByte0F3AOpcode;
404 emi.opcode.op = nextByte;
405
407}
408
409// Generic opcode processing which determines the immediate size, and whether
410// or not there's a modrm byte.
413 bool addrSizedImm)
414{
415 State nextState = ErrorState;
416 const uint8_t opcode = emi.opcode.op;
417
418 // Figure out the effective operand size. This can be overriden to
419 // a fixed value at the decoder level.
420 int logOpSize;
421 if (emi.rex.w)
422 logOpSize = 3; // 64 bit operand size
423 else if (emi.legacy.op)
424 logOpSize = altOp;
425 else
426 logOpSize = defOp;
427
428 // Set the actual op size.
429 emi.opSize = 1 << logOpSize;
430
431 // Figure out the effective address size. This can be overriden to
432 // a fixed value at the decoder level.
433 int logAddrSize;
434 if (emi.legacy.addr)
435 logAddrSize = altAddr;
436 else
437 logAddrSize = defAddr;
438
439 // Set the actual address size.
440 emi.addrSize = 1 << logAddrSize;
441
442 // Figure out the effective stack width. This can be overriden to
443 // a fixed value at the decoder level.
444 emi.stackSize = 1 << stack;
445
446 // Figure out how big of an immediate we'll retreive based
447 // on the opcode.
448 int immType = immTable[opcode];
449 if (addrSizedImm)
450 immediateSize = SizeTypeToSize[logAddrSize - 1][immType];
451 else
452 immediateSize = SizeTypeToSize[logOpSize - 1][immType];
453
454 // Determine what to expect next.
455 if (modrmTable[opcode]) {
456 nextState = ModRMState;
457 } else {
458 if (immediateSize) {
459 nextState = ImmediateState;
460 } else {
461 instDone = true;
462 nextState = ResetState;
463 }
464 }
465 return nextState;
466}
467
468// Get the ModRM byte and determine what displacement, if any, there is.
469// Also determine whether or not to get the SIB byte, displacement, or
470// immediate next.
472Decoder::doModRMState(uint8_t nextByte)
473{
474 State nextState = ErrorState;
475 ModRM modRM = nextByte;
476 DPRINTF(Decoder, "Found modrm byte %#x.\n", nextByte);
477 if (emi.addrSize == 2) {
478 // Figure out 16 bit displacement size.
479 if ((modRM.mod == 0 && modRM.rm == 6) || modRM.mod == 2)
481 else if (modRM.mod == 1)
483 else
485 } else {
486 // Figure out 32/64 bit displacement size.
487 if ((modRM.mod == 0 && modRM.rm == 5) || modRM.mod == 2)
489 else if (modRM.mod == 1)
491 else
493 }
494
495 // The "test" instruction in group 3 needs an immediate, even though
496 // the other instructions with the same actual opcode don't.
497 if (emi.opcode.type == OneByteOpcode && (modRM.reg & 0x6) == 0) {
498 if (emi.opcode.op == 0xF6)
499 immediateSize = 1;
500 else if (emi.opcode.op == 0xF7)
501 immediateSize = (emi.opSize == 8) ? 4 : emi.opSize;
502 }
503
504 // If there's an SIB, get that next.
505 // There is no SIB in 16 bit mode.
506 if (modRM.rm == 4 && modRM.mod != 3 && emi.addrSize != 2) {
507 nextState = SIBState;
508 } else if (displacementSize) {
509 nextState = DisplacementState;
510 } else if (immediateSize) {
511 nextState = ImmediateState;
512 } else {
513 instDone = true;
514 nextState = ResetState;
515 }
516 // The ModRM byte is consumed no matter what.
517 consumeByte();
518 emi.modRM = modRM;
519 return nextState;
520}
521
522// Get the SIB byte. We don't do anything with it at this point, other
523// than storing it in the ExtMachInst. Determine if we need to get a
524// displacement or immediate next.
526Decoder::doSIBState(uint8_t nextByte)
527{
528 State nextState = ErrorState;
529 emi.sib = nextByte;
530 DPRINTF(Decoder, "Found SIB byte %#x.\n", nextByte);
531 consumeByte();
532 if (emi.modRM.mod == 0 && emi.sib.base == 5)
534 if (displacementSize) {
535 nextState = DisplacementState;
536 } else if (immediateSize) {
537 nextState = ImmediateState;
538 } else {
539 instDone = true;
540 nextState = ResetState;
541 }
542 return nextState;
543}
544
545// Gather up the displacement, or at least as much of it as we can get.
548{
549 State nextState = ErrorState;
550
552 emi.displacement,
554
555 DPRINTF(Decoder, "Collecting %d byte displacement, got %d bytes.\n",
557
559 // Reset this for other immediates.
561 // Sign extend the displacement.
562 switch(displacementSize)
563 {
564 case 1:
565 emi.displacement = sext<8>(emi.displacement);
566 break;
567 case 2:
568 emi.displacement = sext<16>(emi.displacement);
569 break;
570 case 4:
571 emi.displacement = sext<32>(emi.displacement);
572 break;
573 default:
574 panic("Undefined displacement size!\n");
575 }
576 DPRINTF(Decoder, "Collected displacement %#x.\n",
577 emi.displacement);
578 if (immediateSize) {
579 nextState = ImmediateState;
580 } else {
581 instDone = true;
582 nextState = ResetState;
583 }
584
585 emi.dispSize = displacementSize;
586 }
587 else
588 nextState = DisplacementState;
589 return nextState;
590}
591
592// Gather up the immediate, or at least as much of it as we can get.
595{
596 State nextState = ErrorState;
597
599
600 DPRINTF(Decoder, "Collecting %d byte immediate, got %d bytes.\n",
602
604 // Reset this for other immediates.
606
607 //XXX Warning! The following is an observed pattern and might
608 // not always be true!
609
610 // Instructions which use 64 bit operands but 32 bit immediates
611 // need to have the immediate sign extended to 64 bits.
612 // Instructions which use true 64 bit immediates won't be
613 // affected, and instructions that use true 32 bit immediates
614 // won't notice.
615 switch(immediateSize) {
616 case 4:
617 emi.immediate = sext<32>(emi.immediate);
618 break;
619 case 1:
620 emi.immediate = sext<8>(emi.immediate);
621 }
622
623 DPRINTF(Decoder, "Collected immediate %#x.\n",
624 emi.immediate);
625 instDone = true;
626 nextState = ResetState;
627 } else {
628 nextState = ImmediateState;
629 }
630 return nextState;
631}
632
635{
637
638 auto iter = instMap->find(mach_inst);
639 if (iter != instMap->end()) {
640 si = iter->second;
641 } else {
642 si = decodeInst(mach_inst);
643 (*instMap)[mach_inst] = si;
644 }
645
646 si->size(basePC + offset - origPC);
647
648 DPRINTF(Decode, "Decode: Decoded %s instruction: %#x\n",
649 si->getName(), mach_inst);
650 return si;
651}
652
655{
656 if (!instDone)
657 return NULL;
658 instDone = false;
659 updateNPC(next_pc.as<PCState>());
660
662 if (si)
663 return si;
664
665 // We didn't match in the AddrMap, but we still populated an entry. Fix
666 // up its byte masks.
667 const int chunkSize = sizeof(MachInst);
668
669 instBytes.lastOffset = offset;
670
671 Addr firstBasePC = basePC - (instBytes.chunks.size() - 1) * chunkSize;
672 Addr firstOffset = origPC - firstBasePC;
673 Addr totalSize = instBytes.lastOffset - firstOffset +
674 (instBytes.chunks.size() - 1) * chunkSize;
675 int start = firstOffset;
676 instBytes.masks.clear();
677
678 while (totalSize) {
679 int end = start + totalSize;
680 end = (chunkSize < end) ? chunkSize : end;
681 int size = end - start;
682 int idx = instBytes.masks.size();
683
684 MachInst maskVal = mask(size * 8) << (start * 8);
685 assert(maskVal);
686
687 instBytes.masks.push_back(maskVal);
688 instBytes.chunks[idx] &= instBytes.masks[idx];
689 totalSize -= size;
690 start = 0;
691 }
692
693 return decode(emi, origPC);
694}
695
698{
699 return microcodeRom.fetchMicroop(micropc, curMacroop);
700}
701
702} // namespace X86ISA
703} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:209
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,...
Target & as()
Definition pcstate.hh:73
State doPrefixState(uint8_t)
Definition decoder.cc:141
StaticInstPtr decode(ExtMachInst mach_inst, Addr addr)
Decode a machine instruction.
Definition decoder.cc:634
static const ByteTable ImmediateTypeTwoByte
Definition decoder.hh:71
StaticInstPtr fetchRomMicroop(MicroPC micropc, StaticInstPtr curMacroop) override
Definition decoder.cc:697
State doThreeByte0F3AOpcodeState(uint8_t)
Definition decoder.cc:398
static const ByteTable UsesModRMTwoByte
Definition decoder.hh:66
uint8_t getNextByte()
Definition decoder.hh:124
void updateNPC(X86ISA::PCState &nextPC)
Definition decoder.hh:334
State doVex3Of3State(uint8_t)
Definition decoder.cc:278
decode_cache::InstMap< ExtMachInst > * instMap
Definition decoder.hh:245
static const ByteTable UsesModRMThreeByte0F3A
Definition decoder.hh:68
State doVexOpcodeState(uint8_t)
Definition decoder.cc:315
State doDisplacementState()
Definition decoder.cc:547
const uint8_t ByteTable[256]
Definition decoder.hh:62
State doVex2Of2State(uint8_t)
Definition decoder.cc:207
static const ByteTable ImmediateTypeThreeByte0F38
Definition decoder.hh:72
State doVex2Of3State(uint8_t)
Definition decoder.cc:237
Decoder(const X86DecoderParams &p)
Definition decoder.hh:260
void getImmediate(int &collected, uint64_t &current, int size)
Definition decoder.hh:130
State processOpcode(ByteTable &immTable, ByteTable &modrmTable, bool addrSizedImm=false)
Definition decoder.cc:412
static const ByteTable UsesModRMThreeByte0F38
Definition decoder.hh:67
StaticInstPtr decodeInst(ExtMachInst mach_inst)
State doOneByteOpcodeState(uint8_t)
Definition decoder.cc:339
static const uint8_t SizeTypeToSize[3][10]
Definition decoder.hh:61
static const ByteTable Prefixes[2]
Definition decoder.hh:63
State doTwoByteOpcodeState(uint8_t)
Definition decoder.cc:361
X86ISAInst::MicrocodeRom microcodeRom
Definition decoder.hh:75
static const ByteTable ImmediateTypeThreeByte0F3A
Definition decoder.hh:73
State doThreeByte0F38OpcodeState(uint8_t)
Definition decoder.cc:384
static const ByteTable ImmediateTypeOneByte
Definition decoder.hh:70
State doSIBState(uint8_t)
Definition decoder.cc:526
State doModRMState(uint8_t)
Definition decoder.cc:472
static const ByteTable UsesModRMOneByte
Definition decoder.hh:65
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition bitfield.hh:79
constexpr uint64_t sext(uint64_t val)
Sign-extend an N-bit value to 64 bits.
Definition bitfield.hh:129
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:220
Bitfield< 24, 21 > opcode
Definition types.hh:92
This is exposed globally, independent of the ISA.
Definition tlb.cc:65
Bitfield< 3 > addr
Definition types.hh:84
Bitfield< 15, 3 > si
Definition misc.hh:895
@ SixtyFourBitMode
Definition types.hh:204
@ OperandSizeOverride
Definition types.hh:68
@ AddressSizeOverride
Definition types.hh:69
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
RefCountingPtr< StaticInst > StaticInstPtr
uint16_t MicroPC
Definition types.hh:149

Generated on Mon May 26 2025 09:18:58 for gem5 by doxygen 1.13.2