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} |