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