decoder.cc revision 9377:6f294e7a93d1
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 * Authors: Gabe Black 29 */ 30 31#include "arch/x86/decoder.hh" 32#include "arch/x86/regs/misc.hh" 33#include "base/misc.hh" 34#include "base/trace.hh" 35#include "base/types.hh" 36#include "debug/Decoder.hh" 37 38namespace X86ISA 39{ 40 41Decoder::State 42Decoder::doResetState() 43{ 44 origPC = basePC + offset; 45 DPRINTF(Decoder, "Setting origPC to %#x\n", origPC); 46 instBytes = &decodePages->lookup(origPC); 47 chunkIdx = 0; 48 49 emi.rex = 0; 50 emi.legacy = 0; 51 emi.opcode.num = 0; 52 emi.opcode.op = 0; 53 emi.opcode.prefixA = emi.opcode.prefixB = 0; 54 55 immediateCollected = 0; 56 emi.immediate = 0; 57 emi.displacement = 0; 58 emi.dispSize = 0; 59 60 emi.modRM = 0; 61 emi.sib = 0; 62 63 if (instBytes->si) { 64 return FromCacheState; 65 } else { 66 instBytes->chunks.clear(); 67 return PrefixState; 68 } 69} 70 71void 72Decoder::process() 73{ 74 //This function drives the decoder state machine. 75 76 //Some sanity checks. You shouldn't try to process more bytes if 77 //there aren't any, and you shouldn't overwrite an already 78 //decoder ExtMachInst. 79 assert(!outOfBytes); 80 assert(!instDone); 81 82 if (state == ResetState) 83 state = doResetState(); 84 if (state == FromCacheState) { 85 state = doFromCacheState(); 86 } else { 87 instBytes->chunks.push_back(fetchChunk); 88 } 89 90 //While there's still something to do... 91 while (!instDone && !outOfBytes) { 92 uint8_t nextByte = getNextByte(); 93 switch (state) { 94 case PrefixState: 95 state = doPrefixState(nextByte); 96 break; 97 case OpcodeState: 98 state = doOpcodeState(nextByte); 99 break; 100 case ModRMState: 101 state = doModRMState(nextByte); 102 break; 103 case SIBState: 104 state = doSIBState(nextByte); 105 break; 106 case DisplacementState: 107 state = doDisplacementState(); 108 break; 109 case ImmediateState: 110 state = doImmediateState(); 111 break; 112 case ErrorState: 113 panic("Went to the error state in the decoder.\n"); 114 default: 115 panic("Unrecognized state! %d\n", state); 116 } 117 } 118} 119 120Decoder::State 121Decoder::doFromCacheState() 122{ 123 DPRINTF(Decoder, "Looking at cache state.\n"); 124 if ((fetchChunk & instBytes->masks[chunkIdx]) != 125 instBytes->chunks[chunkIdx]) { 126 DPRINTF(Decoder, "Decode cache miss.\n"); 127 // The chached chunks didn't match what was fetched. Fall back to the 128 // predecoder. 129 instBytes->chunks[chunkIdx] = fetchChunk; 130 instBytes->chunks.resize(chunkIdx + 1); 131 instBytes->si = NULL; 132 chunkIdx = 0; 133 fetchChunk = instBytes->chunks[0]; 134 offset = origPC % sizeof(MachInst); 135 basePC = origPC - offset; 136 return PrefixState; 137 } else if (chunkIdx == instBytes->chunks.size() - 1) { 138 // We matched the cache, so use its value. 139 instDone = true; 140 offset = instBytes->lastOffset; 141 if (offset == sizeof(MachInst)) 142 outOfBytes = true; 143 return ResetState; 144 } else { 145 // We matched so far, but need to check more chunks. 146 chunkIdx++; 147 outOfBytes = true; 148 return FromCacheState; 149 } 150} 151 152//Either get a prefix and record it in the ExtMachInst, or send the 153//state machine on to get the opcode(s). 154Decoder::State 155Decoder::doPrefixState(uint8_t nextByte) 156{ 157 uint8_t prefix = Prefixes[nextByte]; 158 State nextState = PrefixState; 159 // REX prefixes are only recognized in 64 bit mode. 160 if (prefix == RexPrefix && emi.mode.submode != SixtyFourBitMode) 161 prefix = 0; 162 if (prefix) 163 consumeByte(); 164 switch(prefix) 165 { 166 //Operand size override prefixes 167 case OperandSizeOverride: 168 DPRINTF(Decoder, "Found operand size override prefix.\n"); 169 emi.legacy.op = true; 170 break; 171 case AddressSizeOverride: 172 DPRINTF(Decoder, "Found address size override prefix.\n"); 173 emi.legacy.addr = true; 174 break; 175 //Segment override prefixes 176 case CSOverride: 177 case DSOverride: 178 case ESOverride: 179 case FSOverride: 180 case GSOverride: 181 case SSOverride: 182 DPRINTF(Decoder, "Found segment override.\n"); 183 emi.legacy.seg = prefix; 184 break; 185 case Lock: 186 DPRINTF(Decoder, "Found lock prefix.\n"); 187 emi.legacy.lock = true; 188 break; 189 case Rep: 190 DPRINTF(Decoder, "Found rep prefix.\n"); 191 emi.legacy.rep = true; 192 break; 193 case Repne: 194 DPRINTF(Decoder, "Found repne prefix.\n"); 195 emi.legacy.repne = true; 196 break; 197 case RexPrefix: 198 DPRINTF(Decoder, "Found Rex prefix %#x.\n", nextByte); 199 emi.rex = nextByte; 200 break; 201 case 0: 202 nextState = OpcodeState; 203 break; 204 default: 205 panic("Unrecognized prefix %#x\n", nextByte); 206 } 207 return nextState; 208} 209 210//Load all the opcodes (currently up to 2) and then figure out 211//what immediate and/or ModRM is needed. 212Decoder::State 213Decoder::doOpcodeState(uint8_t nextByte) 214{ 215 State nextState = ErrorState; 216 emi.opcode.num++; 217 //We can't handle 3+ byte opcodes right now 218 assert(emi.opcode.num < 4); 219 consumeByte(); 220 if(emi.opcode.num == 1 && nextByte == 0x0f) 221 { 222 nextState = OpcodeState; 223 DPRINTF(Decoder, "Found two byte opcode.\n"); 224 emi.opcode.prefixA = nextByte; 225 } 226 else if(emi.opcode.num == 2 && (nextByte == 0x38 || nextByte == 0x3A)) 227 { 228 nextState = OpcodeState; 229 DPRINTF(Decoder, "Found three byte opcode.\n"); 230 emi.opcode.prefixB = nextByte; 231 } 232 else 233 { 234 DPRINTF(Decoder, "Found opcode %#x.\n", nextByte); 235 emi.opcode.op = nextByte; 236 237 //Figure out the effective operand size. This can be overriden to 238 //a fixed value at the decoder level. 239 int logOpSize; 240 if (emi.rex.w) 241 logOpSize = 3; // 64 bit operand size 242 else if (emi.legacy.op) 243 logOpSize = altOp; 244 else 245 logOpSize = defOp; 246 247 //Set the actual op size 248 emi.opSize = 1 << logOpSize; 249 250 //Figure out the effective address size. This can be overriden to 251 //a fixed value at the decoder level. 252 int logAddrSize; 253 if(emi.legacy.addr) 254 logAddrSize = altAddr; 255 else 256 logAddrSize = defAddr; 257 258 //Set the actual address size 259 emi.addrSize = 1 << logAddrSize; 260 261 //Figure out the effective stack width. This can be overriden to 262 //a fixed value at the decoder level. 263 emi.stackSize = 1 << stack; 264 265 //Figure out how big of an immediate we'll retreive based 266 //on the opcode. 267 int immType = ImmediateType[emi.opcode.num - 1][nextByte]; 268 if (emi.opcode.num == 1 && nextByte >= 0xA0 && nextByte <= 0xA3) 269 immediateSize = SizeTypeToSize[logAddrSize - 1][immType]; 270 else 271 immediateSize = SizeTypeToSize[logOpSize - 1][immType]; 272 273 //Determine what to expect next 274 if (UsesModRM[emi.opcode.num - 1][nextByte]) { 275 nextState = ModRMState; 276 } else { 277 if(immediateSize) { 278 nextState = ImmediateState; 279 } else { 280 instDone = true; 281 nextState = ResetState; 282 } 283 } 284 } 285 return nextState; 286} 287 288//Get the ModRM byte and determine what displacement, if any, there is. 289//Also determine whether or not to get the SIB byte, displacement, or 290//immediate next. 291Decoder::State 292Decoder::doModRMState(uint8_t nextByte) 293{ 294 State nextState = ErrorState; 295 ModRM modRM; 296 modRM = nextByte; 297 DPRINTF(Decoder, "Found modrm byte %#x.\n", nextByte); 298 if (defOp == 1) { 299 //figure out 16 bit displacement size 300 if ((modRM.mod == 0 && modRM.rm == 6) || modRM.mod == 2) 301 displacementSize = 2; 302 else if (modRM.mod == 1) 303 displacementSize = 1; 304 else 305 displacementSize = 0; 306 } else { 307 //figure out 32/64 bit displacement size 308 if ((modRM.mod == 0 && modRM.rm == 5) || modRM.mod == 2) 309 displacementSize = 4; 310 else if (modRM.mod == 1) 311 displacementSize = 1; 312 else 313 displacementSize = 0; 314 } 315 316 // The "test" instruction in group 3 needs an immediate, even though 317 // the other instructions with the same actual opcode don't. 318 if (emi.opcode.num == 1 && (modRM.reg & 0x6) == 0) { 319 if (emi.opcode.op == 0xF6) 320 immediateSize = 1; 321 else if (emi.opcode.op == 0xF7) 322 immediateSize = (emi.opSize == 8) ? 4 : emi.opSize; 323 } 324 325 //If there's an SIB, get that next. 326 //There is no SIB in 16 bit mode. 327 if (modRM.rm == 4 && modRM.mod != 3) { 328 // && in 32/64 bit mode) 329 nextState = SIBState; 330 } else if(displacementSize) { 331 nextState = DisplacementState; 332 } else if(immediateSize) { 333 nextState = ImmediateState; 334 } else { 335 instDone = true; 336 nextState = ResetState; 337 } 338 //The ModRM byte is consumed no matter what 339 consumeByte(); 340 emi.modRM = modRM; 341 return nextState; 342} 343 344//Get the SIB byte. We don't do anything with it at this point, other 345//than storing it in the ExtMachInst. Determine if we need to get a 346//displacement or immediate next. 347Decoder::State 348Decoder::doSIBState(uint8_t nextByte) 349{ 350 State nextState = ErrorState; 351 emi.sib = nextByte; 352 DPRINTF(Decoder, "Found SIB byte %#x.\n", nextByte); 353 consumeByte(); 354 if (emi.modRM.mod == 0 && emi.sib.base == 5) 355 displacementSize = 4; 356 if (displacementSize) { 357 nextState = DisplacementState; 358 } else if(immediateSize) { 359 nextState = ImmediateState; 360 } else { 361 instDone = true; 362 nextState = ResetState; 363 } 364 return nextState; 365} 366 367//Gather up the displacement, or at least as much of it 368//as we can get. 369Decoder::State 370Decoder::doDisplacementState() 371{ 372 State nextState = ErrorState; 373 374 getImmediate(immediateCollected, 375 emi.displacement, 376 displacementSize); 377 378 DPRINTF(Decoder, "Collecting %d byte displacement, got %d bytes.\n", 379 displacementSize, immediateCollected); 380 381 if(displacementSize == immediateCollected) { 382 //Reset this for other immediates. 383 immediateCollected = 0; 384 //Sign extend the displacement 385 switch(displacementSize) 386 { 387 case 1: 388 emi.displacement = sext<8>(emi.displacement); 389 break; 390 case 2: 391 emi.displacement = sext<16>(emi.displacement); 392 break; 393 case 4: 394 emi.displacement = sext<32>(emi.displacement); 395 break; 396 default: 397 panic("Undefined displacement size!\n"); 398 } 399 DPRINTF(Decoder, "Collected displacement %#x.\n", 400 emi.displacement); 401 if(immediateSize) { 402 nextState = ImmediateState; 403 } else { 404 instDone = true; 405 nextState = ResetState; 406 } 407 408 emi.dispSize = displacementSize; 409 } 410 else 411 nextState = DisplacementState; 412 return nextState; 413} 414 415//Gather up the immediate, or at least as much of it 416//as we can get 417Decoder::State 418Decoder::doImmediateState() 419{ 420 State nextState = ErrorState; 421 422 getImmediate(immediateCollected, 423 emi.immediate, 424 immediateSize); 425 426 DPRINTF(Decoder, "Collecting %d byte immediate, got %d bytes.\n", 427 immediateSize, immediateCollected); 428 429 if(immediateSize == immediateCollected) 430 { 431 //Reset this for other immediates. 432 immediateCollected = 0; 433 434 //XXX Warning! The following is an observed pattern and might 435 //not always be true! 436 437 //Instructions which use 64 bit operands but 32 bit immediates 438 //need to have the immediate sign extended to 64 bits. 439 //Instructions which use true 64 bit immediates won't be 440 //affected, and instructions that use true 32 bit immediates 441 //won't notice. 442 switch(immediateSize) 443 { 444 case 4: 445 emi.immediate = sext<32>(emi.immediate); 446 break; 447 case 1: 448 emi.immediate = sext<8>(emi.immediate); 449 } 450 451 DPRINTF(Decoder, "Collected immediate %#x.\n", 452 emi.immediate); 453 instDone = true; 454 nextState = ResetState; 455 } 456 else 457 nextState = ImmediateState; 458 return nextState; 459} 460 461Decoder::InstBytes Decoder::dummy; 462Decoder::InstCacheMap Decoder::instCacheMap; 463 464StaticInstPtr 465Decoder::decode(ExtMachInst mach_inst, Addr addr) 466{ 467 DecodeCache::InstMap::iterator iter = instMap->find(mach_inst); 468 if (iter != instMap->end()) 469 return iter->second; 470 471 StaticInstPtr si = decodeInst(mach_inst); 472 (*instMap)[mach_inst] = si; 473 return si; 474} 475 476StaticInstPtr 477Decoder::decode(PCState &nextPC) 478{ 479 if (!instDone) 480 return NULL; 481 instDone = false; 482 updateNPC(nextPC); 483 484 StaticInstPtr &si = instBytes->si; 485 if (si) 486 return si; 487 488 // We didn't match in the AddrMap, but we still populated an entry. Fix 489 // up its byte masks. 490 const int chunkSize = sizeof(MachInst); 491 492 instBytes->lastOffset = offset; 493 494 Addr firstBasePC = basePC - (instBytes->chunks.size() - 1) * chunkSize; 495 Addr firstOffset = origPC - firstBasePC; 496 Addr totalSize = instBytes->lastOffset - firstOffset + 497 (instBytes->chunks.size() - 1) * chunkSize; 498 int start = firstOffset; 499 instBytes->masks.clear(); 500 501 while (totalSize) { 502 int end = start + totalSize; 503 end = (chunkSize < end) ? chunkSize : end; 504 int size = end - start; 505 int idx = instBytes->masks.size(); 506 507 MachInst maskVal = mask(size * 8) << (start * 8); 508 assert(maskVal); 509 510 instBytes->masks.push_back(maskVal); 511 instBytes->chunks[idx] &= instBytes->masks[idx]; 512 totalSize -= size; 513 start = 0; 514 } 515 516 si = decode(emi, origPC); 517 return si; 518} 519 520} 521