Deleted Added
sdiff udiff text old ( 9024:5851586f399c ) new ( 9376:270c9a75e91f )
full compact
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;

--- 24 unchanged lines hidden (view full) ---

33#include "base/misc.hh"
34#include "base/trace.hh"
35#include "base/types.hh"
36#include "cpu/thread_context.hh"
37#include "debug/Decoder.hh"
38
39namespace X86ISA
40{
41
42Decoder::State
43Decoder::doResetState()
44{
45 origPC = basePC + offset;
46 DPRINTF(Decoder, "Setting origPC to %#x\n", origPC);
47 instBytes = &decodePages->lookup(origPC);
48 chunkIdx = 0;
49
50 emi.rex = 0;
51 emi.legacy = 0;
52 emi.opcode.num = 0;
53 emi.opcode.op = 0;
54 emi.opcode.prefixA = emi.opcode.prefixB = 0;
55
56 immediateCollected = 0;
57 emi.immediate = 0;
58 emi.displacement = 0;
59 emi.dispSize = 0;
60
61 emi.modRM = 0;
62 emi.sib = 0;
63
64 if (instBytes->si) {
65 return FromCacheState;
66 } else {
67 instBytes->chunks.clear();
68 return PrefixState;
69 }
70}
71
72void
73Decoder::process()
74{
75 //This function drives the decoder state machine.
76
77 //Some sanity checks. You shouldn't try to process more bytes if
78 //there aren't any, and you shouldn't overwrite an already
79 //decoder ExtMachInst.
80 assert(!outOfBytes);
81 assert(!instDone);
82
83 if (state == ResetState)
84 state = doResetState();
85 if (state == FromCacheState) {
86 state = doFromCacheState();
87 } else {
88 instBytes->chunks.push_back(fetchChunk);
89 }
90
91 //While there's still something to do...
92 while (!instDone && !outOfBytes) {
93 uint8_t nextByte = getNextByte();
94 switch (state) {
95 case PrefixState:
96 state = doPrefixState(nextByte);
97 break;
98 case OpcodeState:
99 state = doOpcodeState(nextByte);
100 break;
101 case ModRMState:
102 state = doModRMState(nextByte);

--- 10 unchanged lines hidden (view full) ---

113 case ErrorState:
114 panic("Went to the error state in the decoder.\n");
115 default:
116 panic("Unrecognized state! %d\n", state);
117 }
118 }
119}
120
121Decoder::State
122Decoder::doFromCacheState()
123{
124 DPRINTF(Decoder, "Looking at cache state.\n");
125 if ((fetchChunk & instBytes->masks[chunkIdx]) !=
126 instBytes->chunks[chunkIdx]) {
127 DPRINTF(Decoder, "Decode cache miss.\n");
128 // The chached chunks didn't match what was fetched. Fall back to the
129 // predecoder.
130 instBytes->chunks[chunkIdx] = fetchChunk;
131 instBytes->chunks.resize(chunkIdx + 1);
132 instBytes->si = NULL;
133 chunkIdx = 0;
134 fetchChunk = instBytes->chunks[0];
135 offset = origPC % sizeof(MachInst);
136 basePC = origPC - offset;
137 return PrefixState;
138 } else if (chunkIdx == instBytes->chunks.size() - 1) {
139 // We matched the cache, so use its value.
140 instDone = true;
141 offset = instBytes->lastOffset;
142 if (offset == sizeof(MachInst))
143 outOfBytes = true;
144 return ResetState;
145 } else {
146 // We matched so far, but need to check more chunks.
147 chunkIdx++;
148 outOfBytes = true;
149 return FromCacheState;
150 }
151}
152
153//Either get a prefix and record it in the ExtMachInst, or send the
154//state machine on to get the opcode(s).
155Decoder::State
156Decoder::doPrefixState(uint8_t nextByte)
157{
158 uint8_t prefix = Prefixes[nextByte];
159 State nextState = PrefixState;
160 // REX prefixes are only recognized in 64 bit mode.
161 if (prefix == RexPrefix && emi.mode.submode != SixtyFourBitMode)
162 prefix = 0;
163 if (prefix)
164 consumeByte();

--- 40 unchanged lines hidden (view full) ---

205 default:
206 panic("Unrecognized prefix %#x\n", nextByte);
207 }
208 return nextState;
209}
210
211//Load all the opcodes (currently up to 2) and then figure out
212//what immediate and/or ModRM is needed.
213Decoder::State
214Decoder::doOpcodeState(uint8_t nextByte)
215{
216 State nextState = ErrorState;
217 emi.opcode.num++;
218 //We can't handle 3+ byte opcodes right now
219 assert(emi.opcode.num < 4);
220 consumeByte();
221 if(emi.opcode.num == 1 && nextByte == 0x0f)
222 {

--- 13 unchanged lines hidden (view full) ---

236 emi.opcode.op = nextByte;
237
238 //Figure out the effective operand size. This can be overriden to
239 //a fixed value at the decoder level.
240 int logOpSize;
241 if (emi.rex.w)
242 logOpSize = 3; // 64 bit operand size
243 else if (emi.legacy.op)
244 logOpSize = altOp;
245 else
246 logOpSize = defOp;
247
248 //Set the actual op size
249 emi.opSize = 1 << logOpSize;
250
251 //Figure out the effective address size. This can be overriden to
252 //a fixed value at the decoder level.
253 int logAddrSize;
254 if(emi.legacy.addr)
255 logAddrSize = altAddr;
256 else
257 logAddrSize = defAddr;
258
259 //Set the actual address size
260 emi.addrSize = 1 << logAddrSize;
261
262 //Figure out the effective stack width. This can be overriden to
263 //a fixed value at the decoder level.
264 emi.stackSize = 1 << stack;
265
266 //Figure out how big of an immediate we'll retreive based
267 //on the opcode.
268 int immType = ImmediateType[emi.opcode.num - 1][nextByte];
269 if (emi.opcode.num == 1 && nextByte >= 0xA0 && nextByte <= 0xA3)
270 immediateSize = SizeTypeToSize[logAddrSize - 1][immType];
271 else
272 immediateSize = SizeTypeToSize[logOpSize - 1][immType];

--- 11 unchanged lines hidden (view full) ---

284 }
285 }
286 return nextState;
287}
288
289//Get the ModRM byte and determine what displacement, if any, there is.
290//Also determine whether or not to get the SIB byte, displacement, or
291//immediate next.
292Decoder::State
293Decoder::doModRMState(uint8_t nextByte)
294{
295 State nextState = ErrorState;
296 ModRM modRM;
297 modRM = nextByte;
298 DPRINTF(Decoder, "Found modrm byte %#x.\n", nextByte);
299 if (defOp == 1) {
300 //figure out 16 bit displacement size
301 if ((modRM.mod == 0 && modRM.rm == 6) || modRM.mod == 2)
302 displacementSize = 2;
303 else if (modRM.mod == 1)
304 displacementSize = 1;
305 else
306 displacementSize = 0;
307 } else {

--- 32 unchanged lines hidden (view full) ---

340 consumeByte();
341 emi.modRM = modRM;
342 return nextState;
343}
344
345//Get the SIB byte. We don't do anything with it at this point, other
346//than storing it in the ExtMachInst. Determine if we need to get a
347//displacement or immediate next.
348Decoder::State
349Decoder::doSIBState(uint8_t nextByte)
350{
351 State nextState = ErrorState;
352 emi.sib = nextByte;
353 DPRINTF(Decoder, "Found SIB byte %#x.\n", nextByte);
354 consumeByte();
355 if (emi.modRM.mod == 0 && emi.sib.base == 5)
356 displacementSize = 4;
357 if (displacementSize) {

--- 4 unchanged lines hidden (view full) ---

362 instDone = true;
363 nextState = ResetState;
364 }
365 return nextState;
366}
367
368//Gather up the displacement, or at least as much of it
369//as we can get.
370Decoder::State
371Decoder::doDisplacementState()
372{
373 State nextState = ErrorState;
374
375 getImmediate(immediateCollected,
376 emi.displacement,
377 displacementSize);
378
379 DPRINTF(Decoder, "Collecting %d byte displacement, got %d bytes.\n",

--- 30 unchanged lines hidden (view full) ---

410 }
411 else
412 nextState = DisplacementState;
413 return nextState;
414}
415
416//Gather up the immediate, or at least as much of it
417//as we can get
418Decoder::State
419Decoder::doImmediateState()
420{
421 State nextState = ErrorState;
422
423 getImmediate(immediateCollected,
424 emi.immediate,
425 immediateSize);
426
427 DPRINTF(Decoder, "Collecting %d byte immediate, got %d bytes.\n",

--- 26 unchanged lines hidden (view full) ---

454 instDone = true;
455 nextState = ResetState;
456 }
457 else
458 nextState = ImmediateState;
459 return nextState;
460}
461
462Decoder::InstBytes Decoder::dummy;
463Decoder::InstCacheMap Decoder::instCacheMap;
464
465StaticInstPtr
466Decoder::decode(ExtMachInst mach_inst, Addr addr)
467{
468 DecodeCache::InstMap::iterator iter = instMap->find(mach_inst);
469 if (iter != instMap->end())
470 return iter->second;
471
472 StaticInstPtr si = decodeInst(mach_inst);
473 (*instMap)[mach_inst] = si;
474 return si;
475}
476
477StaticInstPtr
478Decoder::decode(PCState &nextPC)
479{
480 if (!instDone)
481 return NULL;
482 instDone = false;
483 updateNPC(nextPC);
484
485 StaticInstPtr &si = instBytes->si;
486 if (si)
487 return si;
488
489 // We didn't match in the AddrMap, but we still populated an entry. Fix
490 // up its byte masks.
491 const int chunkSize = sizeof(MachInst);
492
493 instBytes->lastOffset = offset;
494
495 Addr firstBasePC = basePC - (instBytes->chunks.size() - 1) * chunkSize;
496 Addr firstOffset = origPC - firstBasePC;
497 Addr totalSize = instBytes->lastOffset - firstOffset +
498 (instBytes->chunks.size() - 1) * chunkSize;
499 int start = firstOffset;
500 instBytes->masks.clear();
501
502 while (totalSize) {
503 int end = start + totalSize;
504 end = (chunkSize < end) ? chunkSize : end;
505 int size = end - start;
506 int idx = instBytes->masks.size();
507
508 MachInst maskVal = mask(size * 8) << (start * 8);
509 assert(maskVal);
510
511 instBytes->masks.push_back(maskVal);
512 instBytes->chunks[idx] &= instBytes->masks[idx];
513 totalSize -= size;
514 start = 0;
515 }
516
517 si = decode(emi, origPC);
518 return si;
519}
520
521}