in runtime/disassembler-x64.cpp [1093:1220]
bool DisassemblerX64::decodeInstructionType(uint8_t** data) {
uint8_t current;
// Scan for prefixes.
while (true) {
current = **data;
if (current == OPERAND_SIZE_OVERRIDE_PREFIX) { // Group 3 prefix.
operand_size_ = current;
} else if ((current & 0xF0) == 0x40) {
// REX prefix.
setRex(current);
// TODO(srdjan): Should we enable printing of REX.W?
// if (rexW()) print("REX.W ");
} else if ((current & 0xFE) == 0xF2) { // Group 1 prefix (0xF2 or 0xF3).
group_1_prefix_ = current;
} else if (current == 0xF0) {
print("lock ");
} else { // Not a prefix - an opcode.
break;
}
(*data)++;
}
const InstructionDesc& idesc = instruction_table.get(current);
byte_size_operand_ = idesc.byte_size_operation;
switch (idesc.type) {
case ZERO_OPERANDS_INSTR:
if (current >= 0xA4 && current <= 0xA7) {
// String move or compare operations.
if (group_1_prefix_ == REP_PREFIX) {
// REP.
print("rep ");
}
if ((current & 0x01) == 0x01) {
// Operation size: word, dword or qword
switch (operandSize()) {
case WORD_SIZE:
print("%sw", idesc.mnem);
break;
case DOUBLEWORD_SIZE:
print("%sl", idesc.mnem);
break;
case QUADWORD_SIZE:
print("%sq", idesc.mnem);
break;
default:
UNREACHABLE("bad operand size");
}
} else {
// Operation size: byte
print("%s", idesc.mnem);
}
} else if (current == 0x99 && rexW()) {
print("cqo"); // Cdql is called cdq and cdqq is called cqo.
} else {
print("%s", idesc.mnem);
}
(*data)++;
break;
case TWO_OPERANDS_INSTR:
(*data)++;
(*data) += printOperands(idesc.mnem, idesc.op_order_, *data);
break;
case JUMP_CONDITIONAL_SHORT_INSTR:
(*data) += jumpConditionalShort(*data);
break;
case REGISTER_INSTR:
print("%s%s %s", idesc.mnem, operandSizeCode(),
nameOfCPURegister(baseReg(current & 0x07)));
(*data)++;
break;
case PUSHPOP_INSTR:
print("%s %s", idesc.mnem, nameOfCPURegister(baseReg(current & 0x07)));
(*data)++;
break;
case MOVE_REG_INSTR: {
intptr_t addr = 0;
int imm_bytes = 0;
switch (operandSize()) {
case WORD_SIZE:
addr = LoadUnaligned(reinterpret_cast<int16_t*>(*data + 1));
imm_bytes = 2;
break;
case DOUBLEWORD_SIZE:
addr = LoadUnaligned(reinterpret_cast<int32_t*>(*data + 1));
imm_bytes = 4;
break;
case QUADWORD_SIZE:
addr = LoadUnaligned(reinterpret_cast<int64_t*>(*data + 1));
imm_bytes = 8;
break;
default:
UNREACHABLE("bad operand size");
}
(*data) += 1 + imm_bytes;
print("mov%s %s,", operandSizeCode(),
nameOfCPURegister(baseReg(current & 0x07)));
printImmediateValue(addr, /*signed_value=*/false, imm_bytes);
break;
}
case CALL_JUMP_INSTR: {
int32_t disp = LoadUnaligned(reinterpret_cast<int32_t*>(*data + 1)) + 5;
print("%s ", idesc.mnem);
printJump(*data, disp);
(*data) += 5;
break;
}
case SHORT_IMMEDIATE_INSTR: {
print("%s%s %s,", idesc.mnem, operandSizeCode(), rax());
printImmediate(*data + 1, DOUBLEWORD_SIZE);
(*data) += 5;
break;
}
case NO_INSTR:
return false;
default:
UNIMPLEMENTED("type not implemented");
}
return true;
}