Index: runtime/vm/disassembler_x64.cc |
diff --git a/runtime/vm/disassembler_x64.cc b/runtime/vm/disassembler_x64.cc |
index 37d818454ca75b619ccfce1063dc150359fc5806..60118f1c74693267c32341315c30f91f0725026e 100644 |
--- a/runtime/vm/disassembler_x64.cc |
+++ b/runtime/vm/disassembler_x64.cc |
@@ -374,8 +374,8 @@ class DisassemblerX64 : public ValueObject { |
return xmm_regs[reg]; |
} |
- void AppendToBuffer(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); |
- void AppendAddressToBuffer(uint8_t* addr); |
+ void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); |
+ void PrintAddress(uint8_t* addr); |
int PrintOperands(const char* mnem, |
OperandType op_order, |
@@ -388,7 +388,9 @@ class DisassemblerX64 : public ValueObject { |
int PrintRightOperand(uint8_t* modrmp); |
int PrintRightByteOperand(uint8_t* modrmp); |
int PrintRightXMMOperand(uint8_t* modrmp); |
+ void PrintDisp(int disp, const char* after); |
int PrintImmediate(uint8_t* data, OperandSize size); |
+ void PrintImmediateValue(int64_t value); |
int PrintImmediateOp(uint8_t* data); |
const char* TwoByteMnemonic(uint8_t opcode); |
int TwoByteOpcodeInstruction(uint8_t* data); |
@@ -406,7 +408,7 @@ class DisassemblerX64 : public ValueObject { |
bool DecodeInstructionType(uint8_t** data); |
void UnimplementedInstruction() { |
- AppendToBuffer("'Unimplemented Instruction'"); |
+ Print("'Unimplemented Instruction'"); |
} |
char* buffer_; // Decode instructions into this buffer. |
@@ -426,7 +428,7 @@ class DisassemblerX64 : public ValueObject { |
// Append the str to the output buffer. |
-void DisassemblerX64::AppendToBuffer(const char* format, ...) { |
+void DisassemblerX64::Print(const char* format, ...) { |
intptr_t available = buffer_size_ - buffer_pos_; |
if (available <= 1) { |
ASSERT(buffer_[buffer_pos_] == '\0'); |
@@ -454,7 +456,8 @@ int DisassemblerX64::PrintRightOperandHelper( |
case 0: |
if ((rm & 7) == 5) { |
int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 1); |
- AppendToBuffer("[rip%s%#x]", disp < 0 ? "-" : "+", Utils::Abs(disp)); |
+ Print("[rip"); |
+ PrintDisp(disp, "]"); |
return 5; |
} else if ((rm & 7) == 4) { |
// Codes for SIB byte. |
@@ -464,28 +467,27 @@ int DisassemblerX64::PrintRightOperandHelper( |
if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) { |
// index == rsp means no index. Only use sib byte with no index for |
// rsp and r12 base. |
- AppendToBuffer("[%s]", NameOfCPURegister(base)); |
+ Print("[%s]", NameOfCPURegister(base)); |
return 2; |
} else if (base == 5) { |
// base == rbp means no base register (when mod == 0). |
int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2); |
- AppendToBuffer("[%s*%d+%#x]", |
- NameOfCPURegister(index), |
- 1 << scale, disp); |
+ Print("[%s*%d", NameOfCPURegister(index), 1 << scale); |
+ PrintDisp(disp, "]"); |
return 6; |
} else if (index != 4 && base != 5) { |
// [base+index*scale] |
- AppendToBuffer("[%s+%s*%d]", |
- NameOfCPURegister(base), |
- NameOfCPURegister(index), |
- 1 << scale); |
+ Print("[%s+%s*%d]", |
+ NameOfCPURegister(base), |
+ NameOfCPURegister(index), |
+ 1 << scale); |
return 2; |
} else { |
UnimplementedInstruction(); |
return 1; |
} |
} else { |
- AppendToBuffer("[%s]", NameOfCPURegister(rm)); |
+ Print("[%s]", NameOfCPURegister(rm)); |
return 1; |
} |
break; |
@@ -498,41 +500,27 @@ int DisassemblerX64::PrintRightOperandHelper( |
int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 2) |
: *reinterpret_cast<char*>(modrmp + 2); |
if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) { |
- if (-disp > 0) { |
- AppendToBuffer("[%s-%#x]", NameOfCPURegister(base), -disp); |
- } else { |
- AppendToBuffer("[%s+%#x]", NameOfCPURegister(base), disp); |
- } |
+ Print("[%s", NameOfCPURegister(base)); |
+ PrintDisp(disp, "]"); |
} else { |
- if (-disp > 0) { |
- AppendToBuffer("[%s+%s*%d-%#x]", |
- NameOfCPURegister(base), |
- NameOfCPURegister(index), |
- 1 << scale, |
- -disp); |
- } else { |
- AppendToBuffer("[%s+%s*%d+%#x]", |
- NameOfCPURegister(base), |
- NameOfCPURegister(index), |
- 1 << scale, |
- disp); |
- } |
+ Print("[%s+%s*%d", |
+ NameOfCPURegister(base), |
+ NameOfCPURegister(index), |
+ 1 << scale); |
+ PrintDisp(disp, "]"); |
} |
return mod == 2 ? 6 : 3; |
} else { |
// No sib. |
int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 1) |
: *reinterpret_cast<char*>(modrmp + 1); |
- if (-disp > 0) { |
- AppendToBuffer("[%s-%#x]", NameOfCPURegister(rm), -disp); |
- } else { |
- AppendToBuffer("[%s+%#x]", NameOfCPURegister(rm), disp); |
- } |
+ Print("[%s", NameOfCPURegister(rm)); |
+ PrintDisp(disp, "]"); |
return (mod == 2) ? 5 : 2; |
} |
break; |
case 3: |
- AppendToBuffer("%s", (this->*register_name)(rm)); |
+ Print("%s", (this->*register_name)(rm)); |
return 1; |
default: |
UnimplementedInstruction(); |
@@ -567,10 +555,29 @@ int DisassemblerX64::PrintImmediate(uint8_t* data, OperandSize size) { |
value = 0; // Initialize variables on all paths to satisfy the compiler. |
count = 0; |
} |
- AppendToBuffer("%#" Px64 "", value); |
+ PrintImmediateValue(value); |
return count; |
} |
+void DisassemblerX64::PrintImmediateValue(int64_t value) { |
+ if ((value >= 0) && (value <= 9)) { |
+ Print("%" Pd64 "", value); |
+ } else { |
+ Print("%#" Px64 "", value); |
+ } |
+} |
+ |
+void DisassemblerX64::PrintDisp(int disp, const char* after) { |
+ if (-disp > 0) { |
+ Print("-%#x", -disp); |
+ } else { |
+ Print("+%#x", disp); |
+ } |
+ if (after != NULL) Print("%s", after); |
+} |
+ |
+ |
+ |
// Returns number of bytes used by machine instruction, including *data byte. |
// Writes immediate instructions to 'tmp_buffer_'. |
@@ -608,9 +615,9 @@ int DisassemblerX64::PrintImmediateOp(uint8_t* data) { |
default: |
UnimplementedInstruction(); |
} |
- AppendToBuffer("%s%c ", mnem, operand_size_code()); |
+ Print("%s%c ", mnem, operand_size_code()); |
int count = PrintRightOperand(data + 1); |
- AppendToBuffer(","); |
+ Print(","); |
OperandSize immediate_size = byte_size_immediate ? BYTE_SIZE : operand_size(); |
count += PrintImmediate(data + 1 + count, immediate_size); |
return 1 + count; |
@@ -644,15 +651,15 @@ int DisassemblerX64::F6F7Instruction(uint8_t* data) { |
default: |
UnimplementedInstruction(); |
} |
- AppendToBuffer("%s%c %s", |
- mnem, |
- operand_size_code(), |
- NameOfCPURegister(rm)); |
+ Print("%s%c %s", |
+ mnem, |
+ operand_size_code(), |
+ NameOfCPURegister(rm)); |
return 2; |
} else if (regop == 0) { |
- AppendToBuffer("test%c ", operand_size_code()); |
+ Print("test%c ", operand_size_code()); |
int count = PrintRightOperand(data + 1); // Use name of 64-bit register. |
- AppendToBuffer(",0x"); |
+ Print(","); |
count += PrintImmediate(data + 1 + count, operand_size()); |
return 1 + count; |
} else { |
@@ -712,15 +719,15 @@ int DisassemblerX64::ShiftInstruction(uint8_t* data) { |
imm8 = *(data + 2); |
num_bytes = 3; |
} |
- AppendToBuffer("%s%c %s,", |
- mnem, |
- operand_size_code(), |
- byte_size_operand_ ? NameOfByteCPURegister(rm) |
- : NameOfCPURegister(rm)); |
+ Print("%s%c %s,", |
+ mnem, |
+ operand_size_code(), |
+ byte_size_operand_ ? NameOfByteCPURegister(rm) |
+ : NameOfCPURegister(rm)); |
if (op == 0xD2) { |
- AppendToBuffer("cl"); |
+ Print("cl"); |
} else { |
- AppendToBuffer("%d", imm8); |
+ Print("%d", imm8); |
} |
return num_bytes; |
} |
@@ -758,19 +765,16 @@ int DisassemblerX64::PrintOperands(const char* mnem, |
: NameOfCPURegister(regop); |
switch (op_order) { |
case REG_OPER_OP_ORDER: { |
- AppendToBuffer("%s%c %s,", |
- mnem, |
- operand_size_code(), |
- register_name); |
+ Print("%s%c %s,", mnem, operand_size_code(), register_name); |
advance = byte_size_operand_ ? PrintRightByteOperand(data) |
: PrintRightOperand(data); |
break; |
} |
case OPER_REG_OP_ORDER: { |
- AppendToBuffer("%s%c ", mnem, operand_size_code()); |
+ Print("%s%c ", mnem, operand_size_code()); |
advance = byte_size_operand_ ? PrintRightByteOperand(data) |
: PrintRightOperand(data); |
- AppendToBuffer(",%s", register_name); |
+ Print(",%s", register_name); |
break; |
} |
default: |
@@ -803,9 +807,9 @@ static const char* ObjectToCStringNoGC(const Object& obj) { |
} |
-void DisassemblerX64::AppendAddressToBuffer(uint8_t* addr_byte_ptr) { |
+void DisassemblerX64::PrintAddress(uint8_t* addr_byte_ptr) { |
uword addr = reinterpret_cast<uword>(addr_byte_ptr); |
- AppendToBuffer("%#" Px "", addr); |
+ Print("%#" Px "", addr); |
// Try to print as heap object or stub name |
if (((addr & kSmiTagMask) == kHeapObjectTag) && |
reinterpret_cast<RawObject*>(addr)->IsWellFormed() && |
@@ -819,25 +823,25 @@ void DisassemblerX64::AppendAddressToBuffer(uint8_t* addr_byte_ptr) { |
const Array& arr = Array::Cast(obj); |
intptr_t len = arr.Length(); |
if (len > 5) len = 5; // Print a max of 5 elements. |
- AppendToBuffer(" Array["); |
+ Print(" Array["); |
int i = 0; |
Object& element = Object::Handle(); |
while (i < len) { |
element = arr.At(i); |
- if (i > 0) AppendToBuffer(", "); |
- AppendToBuffer("%s", ObjectToCStringNoGC(element)); |
+ if (i > 0) Print(", "); |
+ Print("%s", ObjectToCStringNoGC(element)); |
i++; |
} |
- if (i < arr.Length()) AppendToBuffer(", ..."); |
- AppendToBuffer("]"); |
+ if (i < arr.Length()) Print(", ..."); |
+ Print("]"); |
return; |
} |
- AppendToBuffer(" '%s'", ObjectToCStringNoGC(obj)); |
+ Print(" '%s'", ObjectToCStringNoGC(obj)); |
} else { |
// 'addr' is not an object, but probably a code address. |
const char* name_of_stub = StubCode::NameOfStub(addr); |
if (name_of_stub != NULL) { |
- AppendToBuffer(" [stub: %s]", name_of_stub); |
+ Print(" [stub: %s]", name_of_stub); |
} |
} |
} |
@@ -848,8 +852,8 @@ int DisassemblerX64::JumpShort(uint8_t* data) { |
ASSERT(0xEB == *data); |
uint8_t b = *(data + 1); |
uint8_t* dest = data + static_cast<int8_t>(b) + 2; |
- AppendToBuffer("jmp "); |
- AppendAddressToBuffer(dest); |
+ Print("jmp "); |
+ PrintAddress(dest); |
return 2; |
} |
@@ -860,8 +864,8 @@ int DisassemblerX64::JumpConditional(uint8_t* data) { |
uint8_t cond = *(data + 1) & 0x0F; |
uint8_t* dest = data + *reinterpret_cast<int32_t*>(data + 2) + 6; |
const char* mnem = conditional_code_suffix[cond]; |
- AppendToBuffer("j%s ", mnem); |
- AppendAddressToBuffer(dest); |
+ Print("j%s ", mnem); |
+ PrintAddress(dest); |
return 6; // includes 0x0F |
} |
@@ -872,8 +876,8 @@ int DisassemblerX64::JumpConditionalShort(uint8_t* data) { |
uint8_t b = *(data + 1); |
uint8_t* dest = data + static_cast<int8_t>(b) + 2; |
const char* mnem = conditional_code_suffix[cond]; |
- AppendToBuffer("j%s ", mnem); |
- AppendAddressToBuffer(dest); |
+ Print("j%s ", mnem); |
+ PrintAddress(dest); |
return 2; |
} |
@@ -883,7 +887,7 @@ int DisassemblerX64::SetCC(uint8_t* data) { |
ASSERT(0x0F == *data); |
uint8_t cond = *(data + 1) & 0x0F; |
const char* mnem = conditional_code_suffix[cond]; |
- AppendToBuffer("set%s%c ", mnem, operand_size_code()); |
+ Print("set%s%c ", mnem, operand_size_code()); |
PrintRightByteOperand(data + 2); |
return 3; // includes 0x0F |
} |
@@ -942,7 +946,7 @@ int DisassemblerX64::MemoryFPUInstruction(int escape_opcode, |
default: UnimplementedInstruction(); |
} |
- AppendToBuffer("%s ", mnem); |
+ Print("%s ", mnem); |
int count = PrintRightOperand(modrm_start); |
return count + 1; |
} |
@@ -1058,9 +1062,9 @@ int DisassemblerX64::RegisterFPUInstruction(int escape_opcode, |
} |
if (has_register) { |
- AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7); |
+ Print("%s st%d", mnem, modrm_byte & 0x7); |
} else { |
- AppendToBuffer("%s", mnem); |
+ Print("%s", mnem); |
} |
return 2; |
} |
@@ -1078,11 +1082,11 @@ bool DisassemblerX64::DecodeInstructionType(uint8_t** data) { |
} else if ((current & 0xF0) == 0x40) { // REX prefix. |
setRex(current); |
// TODO(srdjan): Should we enable printing of REX.W? |
- // if (rex_w()) AppendToBuffer("REX.W "); |
+ // if (rex_w()) Print("REX.W "); |
} else if ((current & 0xFE) == 0xF2) { // Group 1 prefix (0xF2 or 0xF3). |
group_1_prefix_ = current; |
} else if (current == 0xF0) { |
- AppendToBuffer("lock "); |
+ Print("lock "); |
} else { // Not a prefix - an opcode. |
break; |
} |
@@ -1098,13 +1102,13 @@ bool DisassemblerX64::DecodeInstructionType(uint8_t** data) { |
// String move or compare operations. |
if (group_1_prefix_ == REP_PREFIX) { |
// REP. |
- AppendToBuffer("rep "); |
+ Print("rep "); |
} |
// TODO(srdjan): Should we enable printing of REX.W? |
- // if (rex_w()) AppendToBuffer("REX.W "); |
- AppendToBuffer("%s%c", idesc.mnem, operand_size_code()); |
+ // if (rex_w()) Print("REX.W "); |
+ Print("%s%c", idesc.mnem, operand_size_code()); |
} else { |
- AppendToBuffer("%s%c", idesc.mnem, operand_size_code()); |
+ Print("%s%c", idesc.mnem, operand_size_code()); |
} |
(*data)++; |
break; |
@@ -1119,16 +1123,16 @@ bool DisassemblerX64::DecodeInstructionType(uint8_t** data) { |
break; |
case REGISTER_INSTR: |
- AppendToBuffer("%s%c %s", |
- idesc.mnem, |
- operand_size_code(), |
- NameOfCPURegister(base_reg(current & 0x07))); |
+ Print("%s%c %s", |
+ idesc.mnem, |
+ operand_size_code(), |
+ NameOfCPURegister(base_reg(current & 0x07))); |
(*data)++; |
break; |
case PUSHPOP_INSTR: |
- AppendToBuffer("%s %s", |
- idesc.mnem, |
- NameOfCPURegister(base_reg(current & 0x07))); |
+ Print("%s %s", |
+ idesc.mnem, |
+ NameOfCPURegister(base_reg(current & 0x07))); |
(*data)++; |
break; |
case MOVE_REG_INSTR: { |
@@ -1152,17 +1156,17 @@ bool DisassemblerX64::DecodeInstructionType(uint8_t** data) { |
default: |
UNREACHABLE(); |
} |
- AppendToBuffer("mov%c %s,", |
- operand_size_code(), |
- NameOfCPURegister(base_reg(current & 0x07))); |
- AppendAddressToBuffer(addr); |
+ Print("mov%c %s,", |
+ operand_size_code(), |
+ NameOfCPURegister(base_reg(current & 0x07))); |
+ PrintAddress(addr); |
break; |
} |
case CALL_JUMP_INSTR: { |
uint8_t* addr = *data + *reinterpret_cast<int32_t*>(*data + 1) + 5; |
- AppendToBuffer("%s ", idesc.mnem); |
- AppendAddressToBuffer(addr); |
+ Print("%s ", idesc.mnem); |
+ PrintAddress(addr); |
(*data) += 5; |
break; |
} |
@@ -1170,8 +1174,8 @@ bool DisassemblerX64::DecodeInstructionType(uint8_t** data) { |
case SHORT_IMMEDIATE_INSTR: { |
uint8_t* addr = |
reinterpret_cast<uint8_t*>(*reinterpret_cast<int32_t*>(*data + 1)); |
- AppendToBuffer("%s rax, ", idesc.mnem); |
- AppendAddressToBuffer(addr); |
+ Print("%s rax, ", idesc.mnem); |
+ PrintAddress(addr); |
(*data) += 5; |
break; |
} |
@@ -1200,25 +1204,25 @@ int DisassemblerX64::TwoByteOpcodeInstruction(uint8_t* data) { |
if (opcode == 0xC6) { |
int mod, regop, rm; |
get_modrm(*current, &mod, ®op, &rm); |
- AppendToBuffer("shufpd %s, ", NameOfXMMRegister(regop)); |
+ Print("shufpd %s, ", NameOfXMMRegister(regop)); |
current += PrintRightXMMOperand(current); |
- AppendToBuffer(" [%x]", *current); |
+ Print(" [%x]", *current); |
current++; |
} else if (opcode == 0x3A) { |
uint8_t third_byte = *current; |
current = data + 3; |
if (third_byte == 0x17) { |
get_modrm(*current, &mod, ®op, &rm); |
- AppendToBuffer("extractps "); // reg/m32, xmm, imm8 |
+ Print("extractps "); // reg/m32, xmm, imm8 |
current += PrintRightOperand(current); |
- AppendToBuffer(", %s, %d", NameOfCPURegister(regop), (*current) & 3); |
+ Print(", %s, %d", NameOfCPURegister(regop), (*current) & 3); |
current += 1; |
} else if (third_byte == 0x0b) { |
get_modrm(*current, &mod, ®op, &rm); |
// roundsd xmm, xmm/m64, imm8 |
- AppendToBuffer("roundsd %s, ", NameOfCPURegister(regop)); |
+ Print("roundsd %s, ", NameOfCPURegister(regop)); |
current += PrintRightOperand(current); |
- AppendToBuffer(", %d", (*current) & 3); |
+ Print(", %d", (*current) & 3); |
current += 1; |
} else { |
UnimplementedInstruction(); |
@@ -1235,38 +1239,38 @@ int DisassemblerX64::TwoByteOpcodeInstruction(uint8_t* data) { |
} else if (mod == 2) { // 32-bit displacement. |
current += 4; |
} // else no immediate displacement. |
- AppendToBuffer("nop"); |
+ Print("nop"); |
} else if (opcode == 0x28) { |
- AppendToBuffer("movapd %s, ", NameOfXMMRegister(regop)); |
+ Print("movapd %s, ", NameOfXMMRegister(regop)); |
current += PrintRightXMMOperand(current); |
} else if (opcode == 0x29) { |
- AppendToBuffer("movapd "); |
+ Print("movapd "); |
current += PrintRightXMMOperand(current); |
- AppendToBuffer(", %s", NameOfXMMRegister(regop)); |
+ Print(", %s", NameOfXMMRegister(regop)); |
} else if (opcode == 0x6E) { |
- AppendToBuffer("mov%c %s,", |
- rex_w() ? 'q' : 'd', |
- NameOfXMMRegister(regop)); |
+ Print("mov%c %s,", |
+ rex_w() ? 'q' : 'd', |
+ NameOfXMMRegister(regop)); |
current += PrintRightOperand(current); |
} else if (opcode == 0x6F) { |
- AppendToBuffer("movdqa %s,", |
- NameOfXMMRegister(regop)); |
+ Print("movdqa %s,", |
+ NameOfXMMRegister(regop)); |
current += PrintRightXMMOperand(current); |
} else if (opcode == 0x7E) { |
- AppendToBuffer("mov%c ", |
- rex_w() ? 'q' : 'd'); |
+ Print("mov%c ", |
+ rex_w() ? 'q' : 'd'); |
current += PrintRightOperand(current); |
- AppendToBuffer(", %s", NameOfXMMRegister(regop)); |
+ Print(", %s", NameOfXMMRegister(regop)); |
} else if (opcode == 0x7F) { |
- AppendToBuffer("movdqa "); |
+ Print("movdqa "); |
current += PrintRightXMMOperand(current); |
- AppendToBuffer(", %s", NameOfXMMRegister(regop)); |
+ Print(", %s", NameOfXMMRegister(regop)); |
} else if (opcode == 0xD6) { |
- AppendToBuffer("movq "); |
+ Print("movq "); |
current += PrintRightXMMOperand(current); |
- AppendToBuffer(", %s", NameOfXMMRegister(regop)); |
+ Print(", %s", NameOfXMMRegister(regop)); |
} else if (opcode == 0x50) { |
- AppendToBuffer("movmskpd %s,", NameOfCPURegister(regop)); |
+ Print("movmskpd %s,", NameOfCPURegister(regop)); |
current += PrintRightXMMOperand(current); |
} else { |
const char* mnemonic = "?"; |
@@ -1307,7 +1311,7 @@ int DisassemblerX64::TwoByteOpcodeInstruction(uint8_t* data) { |
} else { |
UnimplementedInstruction(); |
} |
- AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop)); |
+ Print("%s %s,", mnemonic, NameOfXMMRegister(regop)); |
current += PrintRightXMMOperand(current); |
} |
} |
@@ -1316,42 +1320,42 @@ int DisassemblerX64::TwoByteOpcodeInstruction(uint8_t* data) { |
if (opcode == 0x11 || opcode == 0x10) { |
// MOVSD: Move scalar double-precision fp to/from/between XMM registers. |
- AppendToBuffer("movsd "); |
+ Print("movsd "); |
int mod, regop, rm; |
get_modrm(*current, &mod, ®op, &rm); |
if (opcode == 0x11) { |
current += PrintRightXMMOperand(current); |
- AppendToBuffer(",%s", NameOfXMMRegister(regop)); |
+ Print(",%s", NameOfXMMRegister(regop)); |
} else { |
- AppendToBuffer("%s,", NameOfXMMRegister(regop)); |
+ Print("%s,", NameOfXMMRegister(regop)); |
current += PrintRightXMMOperand(current); |
} |
} else if (opcode == 0x2A) { |
// CVTSI2SD: integer to XMM double conversion. |
int mod, regop, rm; |
get_modrm(*current, &mod, ®op, &rm); |
- AppendToBuffer("%sd %s,", mnemonic, NameOfXMMRegister(regop)); |
+ Print("%sd %s,", mnemonic, NameOfXMMRegister(regop)); |
current += PrintRightOperand(current); |
} else if (opcode == 0x2C) { |
// CVTTSD2SI: |
// Convert with truncation scalar double-precision FP to integer. |
int mod, regop, rm; |
get_modrm(*current, &mod, ®op, &rm); |
- AppendToBuffer("cvttsd2si%c %s,", |
+ Print("cvttsd2si%c %s,", |
operand_size_code(), NameOfCPURegister(regop)); |
current += PrintRightXMMOperand(current); |
} else if (opcode == 0x2D) { |
// CVTSD2SI: Convert scalar double-precision FP to integer. |
int mod, regop, rm; |
get_modrm(*current, &mod, ®op, &rm); |
- AppendToBuffer("cvtsd2si%c %s,", |
+ Print("cvtsd2si%c %s,", |
operand_size_code(), NameOfCPURegister(regop)); |
current += PrintRightXMMOperand(current); |
} else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) { |
// XMM arithmetic. Mnemonic was retrieved at the start of this function. |
int mod, regop, rm; |
get_modrm(*current, &mod, ®op, &rm); |
- AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop)); |
+ Print("%s %s,", mnemonic, NameOfXMMRegister(regop)); |
current += PrintRightXMMOperand(current); |
} else { |
UnimplementedInstruction(); |
@@ -1360,46 +1364,46 @@ int DisassemblerX64::TwoByteOpcodeInstruction(uint8_t* data) { |
// Instructions with prefix 0xF3. |
if (opcode == 0x11 || opcode == 0x10) { |
// MOVSS: Move scalar double-precision fp to/from/between XMM registers. |
- AppendToBuffer("movss "); |
+ Print("movss "); |
int mod, regop, rm; |
get_modrm(*current, &mod, ®op, &rm); |
if (opcode == 0x11) { |
current += PrintRightOperand(current); |
- AppendToBuffer(",%s", NameOfXMMRegister(regop)); |
+ Print(",%s", NameOfXMMRegister(regop)); |
} else { |
- AppendToBuffer("%s,", NameOfXMMRegister(regop)); |
+ Print("%s,", NameOfXMMRegister(regop)); |
current += PrintRightOperand(current); |
} |
} else if (opcode == 0x2A) { |
// CVTSI2SS: integer to XMM single conversion. |
int mod, regop, rm; |
get_modrm(*current, &mod, ®op, &rm); |
- AppendToBuffer("%ss %s,", mnemonic, NameOfXMMRegister(regop)); |
+ Print("%ss %s,", mnemonic, NameOfXMMRegister(regop)); |
current += PrintRightOperand(current); |
} else if (opcode == 0x2C) { |
// CVTTSS2SI: |
// Convert with truncation scalar single-precision FP to dword integer. |
int mod, regop, rm; |
get_modrm(*current, &mod, ®op, &rm); |
- AppendToBuffer("cvttss2si%c %s,", |
- operand_size_code(), NameOfCPURegister(regop)); |
+ Print("cvttss2si%c %s,", |
+ operand_size_code(), NameOfCPURegister(regop)); |
current += PrintRightXMMOperand(current); |
} else if (opcode == 0x5A) { |
// CVTSS2SD: |
// Convert scalar single-precision FP to scalar double-precision FP. |
int mod, regop, rm; |
get_modrm(*current, &mod, ®op, &rm); |
- AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop)); |
+ Print("cvtss2sd %s,", NameOfXMMRegister(regop)); |
current += PrintRightXMMOperand(current); |
} else if (opcode == 0x7E) { |
int mod, regop, rm; |
get_modrm(*current, &mod, ®op, &rm); |
- AppendToBuffer("movq %s, ", NameOfXMMRegister(regop)); |
+ Print("movq %s, ", NameOfXMMRegister(regop)); |
current += PrintRightXMMOperand(current); |
} else if (opcode == 0x58) { |
int mod, regop, rm; |
get_modrm(*current, &mod, ®op, &rm); |
- AppendToBuffer("addss %s,", NameOfXMMRegister(regop)); |
+ Print("addss %s,", NameOfXMMRegister(regop)); |
current += PrintRightXMMOperand(current); |
} else { |
UnimplementedInstruction(); |
@@ -1417,42 +1421,42 @@ int DisassemblerX64::TwoByteOpcodeInstruction(uint8_t* data) { |
} else if (mod == 2) { // 32-bit displacement. |
current += 4; |
} // else no immediate displacement. |
- AppendToBuffer("nop"); |
+ Print("nop"); |
} else if (opcode == 0x28) { |
// movaps xmm, xmm/m128 |
int mod, regop, rm; |
get_modrm(*current, &mod, ®op, &rm); |
- AppendToBuffer("movaps %s, ", NameOfXMMRegister(regop)); |
+ Print("movaps %s, ", NameOfXMMRegister(regop)); |
current += PrintRightXMMOperand(current); |
} else if (opcode == 0x29) { |
// movaps xmm/m128, xmm |
int mod, regop, rm; |
get_modrm(*current, &mod, ®op, &rm); |
- AppendToBuffer("movaps "); |
+ Print("movaps "); |
current += PrintRightXMMOperand(current); |
- AppendToBuffer(", %s", NameOfXMMRegister(regop)); |
+ Print(", %s", NameOfXMMRegister(regop)); |
} else if (opcode == 0x11) { |
// movups xmm/m128, xmm |
int mod, regop, rm; |
get_modrm(*current, &mod, ®op, &rm); |
- AppendToBuffer("movups "); |
+ Print("movups "); |
current += PrintRightXMMOperand(current); |
- AppendToBuffer(", %s", NameOfXMMRegister(regop)); |
+ Print(", %s", NameOfXMMRegister(regop)); |
} else if (opcode == 0x10) { |
// movups xmm, xmm/m128 |
int mod, regop, rm; |
get_modrm(*current, &mod, ®op, &rm); |
- AppendToBuffer("movups %s, ", NameOfXMMRegister(regop)); |
+ Print("movups %s, ", NameOfXMMRegister(regop)); |
current += PrintRightXMMOperand(current); |
} else if (opcode == 0x50) { |
int mod, regop, rm; |
get_modrm(*current, &mod, ®op, &rm); |
- AppendToBuffer("movmskps %s,", NameOfCPURegister(regop)); |
+ Print("movmskps %s,", NameOfCPURegister(regop)); |
current += PrintRightXMMOperand(current); |
} else if (opcode == 0xA2 || opcode == 0x31) { |
// RDTSC or CPUID |
- AppendToBuffer("%s", mnemonic); |
+ Print("%s", mnemonic); |
} else if ((opcode & 0xF0) == 0x40) { |
// CMOVcc: conditional move. |
@@ -1490,19 +1494,19 @@ int DisassemblerX64::TwoByteOpcodeInstruction(uint8_t* data) { |
} |
int mod, regop, rm; |
get_modrm(*current, &mod, ®op, &rm); |
- AppendToBuffer("%s %s, ", mnemonic, NameOfXMMRegister(regop)); |
+ Print("%s %s, ", mnemonic, NameOfXMMRegister(regop)); |
current += PrintRightXMMOperand(current); |
} else if (opcode == 0xC2 || opcode == 0xC6) { |
int mod, regop, rm; |
get_modrm(*current, &mod, ®op, &rm); |
if (opcode == 0xC2) { |
- AppendToBuffer("cmpps %s, ", NameOfXMMRegister(regop)); |
+ Print("cmpps %s, ", NameOfXMMRegister(regop)); |
} else { |
ASSERT(opcode == 0xC6); |
- AppendToBuffer("shufps %s, ", NameOfXMMRegister(regop)); |
+ Print("shufps %s, ", NameOfXMMRegister(regop)); |
} |
current += PrintRightXMMOperand(current); |
- AppendToBuffer(" [%x]", *current); |
+ Print(" [%x]", *current); |
current++; |
} else if ((opcode & 0xF0) == 0x80) { |
// Jcc: Conditional jump (branch). |
@@ -1521,17 +1525,17 @@ int DisassemblerX64::TwoByteOpcodeInstruction(uint8_t* data) { |
} else if (((opcode & 0xFE) == 0xA4) || ((opcode & 0xFE) == 0xAC) || |
(opcode == 0xAB) || (opcode == 0xA3) || (opcode == 0xBD)) { |
// SHLD, SHRD (double-prec. shift), BTS (bit test and set), BT (bit test). |
- AppendToBuffer("%s%c ", mnemonic, operand_size_code()); |
+ Print("%s%c ", mnemonic, operand_size_code()); |
int mod, regop, rm; |
get_modrm(*current, &mod, ®op, &rm); |
current += PrintRightOperand(current); |
- AppendToBuffer(",%s", NameOfCPURegister(regop)); |
+ Print(",%s", NameOfCPURegister(regop)); |
if ((opcode == 0xAB) || (opcode == 0xA3) || (opcode == 0xBD)) { |
// Done. |
} else if ((opcode == 0xA5) || (opcode == 0xAD)) { |
- AppendToBuffer(",cl"); |
+ Print(",cl"); |
} else { |
- AppendToBuffer(","); |
+ Print(","); |
current += PrintImmediate(current, BYTE_SIZE); |
} |
} else { |
@@ -1607,14 +1611,15 @@ int DisassemblerX64::InstructionDecode(uword pc) { |
if (!processed) { |
switch (*data) { |
case 0xC2: |
- AppendToBuffer("ret %#x", *reinterpret_cast<uint16_t*>(data + 1)); |
+ Print("ret "); |
+ PrintImmediateValue(*reinterpret_cast<uint16_t*>(data + 1)); |
data += 3; |
break; |
case 0xC8: |
- AppendToBuffer("enter %d, %d", |
- *reinterpret_cast<uint16_t*>(data + 1), |
- data[3]); |
+ Print("enter %d, %d", |
+ *reinterpret_cast<uint16_t*>(data + 1), |
+ data[3]); |
data += 4; |
break; |
@@ -1624,10 +1629,11 @@ int DisassemblerX64::InstructionDecode(uword pc) { |
get_modrm(*(data + 1), &mod, ®op, &rm); |
int32_t imm = *data == 0x6B ? *(data + 2) |
: *reinterpret_cast<int32_t*>(data + 2); |
- AppendToBuffer("imul%c %s,%s,%#x", |
- operand_size_code(), |
- NameOfCPURegister(regop), |
- NameOfCPURegister(rm), imm); |
+ Print("imul%c %s,%s,", |
+ operand_size_code(), |
+ NameOfCPURegister(regop), |
+ NameOfCPURegister(rm)); |
+ PrintImmediateValue(imm); |
data += 2 + (*data == 0x6B ? 1 : 4); |
break; |
} |
@@ -1646,7 +1652,7 @@ int DisassemblerX64::InstructionDecode(uword pc) { |
int mod, regop, rm; |
get_modrm(*data, &mod, ®op, &rm); |
if (regop == 0) { |
- AppendToBuffer("pop "); |
+ Print("pop "); |
data += PrintRightOperand(data); |
} |
} |
@@ -1677,9 +1683,9 @@ int DisassemblerX64::InstructionDecode(uword pc) { |
mnem = "???"; |
} |
if (regop <= 1) { |
- AppendToBuffer("%s%c ", mnem, operand_size_code()); |
+ Print("%s%c ", mnem, operand_size_code()); |
} else { |
- AppendToBuffer("%s ", mnem); |
+ Print("%s ", mnem); |
} |
data += PrintRightOperand(data); |
} |
@@ -1691,16 +1697,18 @@ int DisassemblerX64::InstructionDecode(uword pc) { |
bool is_byte = *data == 0xC6; |
data++; |
if (is_byte) { |
- AppendToBuffer("movb "); |
+ Print("movb "); |
data += PrintRightByteOperand(data); |
int32_t imm = *data; |
- AppendToBuffer(",%#x", imm); |
+ Print(","); |
+ PrintImmediateValue(imm); |
data++; |
} else { |
- AppendToBuffer("mov%c ", operand_size_code()); |
+ Print("mov%c ", operand_size_code()); |
data += PrintRightOperand(data); |
int32_t imm = *reinterpret_cast<int32_t*>(data); |
- AppendToBuffer(",%#x", imm); |
+ Print(","); |
+ PrintImmediateValue(imm); |
data += 4; |
} |
} |
@@ -1708,10 +1716,11 @@ int DisassemblerX64::InstructionDecode(uword pc) { |
case 0x80: { |
data++; |
- AppendToBuffer("cmpb "); |
+ Print("cmpb "); |
data += PrintRightByteOperand(data); |
int32_t imm = *data; |
- AppendToBuffer(",%#x", imm); |
+ Print(","); |
+ PrintImmediateValue(imm); |
data++; |
} |
break; |
@@ -1724,13 +1733,13 @@ int DisassemblerX64::InstructionDecode(uword pc) { |
data++; |
get_modrm(*data, &mod, ®op, &rm); |
if (is_byte) { |
- AppendToBuffer("movb "); |
+ Print("movb "); |
data += PrintRightByteOperand(data); |
- AppendToBuffer(",%s", NameOfByteCPURegister(regop)); |
+ Print(",%s", NameOfByteCPURegister(regop)); |
} else { |
- AppendToBuffer("mov%c ", operand_size_code()); |
+ Print("mov%c ", operand_size_code()); |
data += PrintRightOperand(data); |
- AppendToBuffer(",%s", NameOfCPURegister(regop)); |
+ Print(",%s", NameOfCPURegister(regop)); |
} |
} |
break; |
@@ -1745,11 +1754,9 @@ int DisassemblerX64::InstructionDecode(uword pc) { |
case 0x97: { |
int reg = (*data & 0x7) | (rex_b() ? 8 : 0); |
if (reg == 0) { |
- AppendToBuffer("nop"); // Common name for xchg rax,rax. |
+ Print("nop"); // Common name for xchg rax,rax. |
} else { |
- AppendToBuffer("xchg%c rax, %s", |
- operand_size_code(), |
- NameOfCPURegister(reg)); |
+ Print("xchg%c rax, %s", operand_size_code(), NameOfCPURegister(reg)); |
} |
data++; |
} |
@@ -1776,13 +1783,10 @@ int DisassemblerX64::InstructionDecode(uword pc) { |
uint8_t is_32bit = (opcode >= 0xB8); |
int reg = (opcode & 0x7) | (rex_b() ? 8 : 0); |
if (is_32bit) { |
- AppendToBuffer("mov%c %s, ", |
- operand_size_code(), |
- NameOfCPURegister(reg)); |
+ Print("mov%c %s,", operand_size_code(), NameOfCPURegister(reg)); |
data += PrintImmediate(data, DOUBLEWORD_SIZE); |
} else { |
- AppendToBuffer("movb %s, ", |
- NameOfByteCPURegister(reg)); |
+ Print("movb %s,", NameOfByteCPURegister(reg)); |
data += PrintImmediate(data, BYTE_SIZE); |
} |
break; |
@@ -1792,7 +1796,7 @@ int DisassemblerX64::InstructionDecode(uword pc) { |
int mod, regop, rm; |
get_modrm(*data, &mod, ®op, &rm); |
if (regop == 1) { |
- AppendToBuffer("decb "); |
+ Print("decb "); |
data += PrintRightByteOperand(data); |
} else { |
UnimplementedInstruction(); |
@@ -1800,12 +1804,14 @@ int DisassemblerX64::InstructionDecode(uword pc) { |
break; |
} |
case 0x68: |
- AppendToBuffer("push %#x", *reinterpret_cast<int32_t*>(data + 1)); |
+ Print("push "); |
+ PrintImmediateValue(*reinterpret_cast<int32_t*>(data + 1)); |
data += 5; |
break; |
case 0x6A: |
- AppendToBuffer("push %#x", *reinterpret_cast<int8_t*>(data + 1)); |
+ Print("push "); |
+ PrintImmediateValue(*reinterpret_cast<int8_t*>(data + 1)); |
data += 2; |
break; |
@@ -1813,21 +1819,21 @@ int DisassemblerX64::InstructionDecode(uword pc) { |
case 0xA3: |
switch (operand_size()) { |
case DOUBLEWORD_SIZE: { |
- AppendAddressToBuffer( |
+ PrintAddress( |
reinterpret_cast<uint8_t*>( |
*reinterpret_cast<int32_t*>(data + 1))); |
if (*data == 0xA1) { // Opcode 0xA1 |
- AppendToBuffer("movzxlq rax,("); |
- AppendAddressToBuffer( |
+ Print("movzxlq rax,("); |
+ PrintAddress( |
reinterpret_cast<uint8_t*>( |
*reinterpret_cast<int32_t*>(data + 1))); |
- AppendToBuffer(")"); |
+ Print(")"); |
} else { // Opcode 0xA3 |
- AppendToBuffer("movzxlq ("); |
- AppendAddressToBuffer( |
+ Print("movzxlq ("); |
+ PrintAddress( |
reinterpret_cast<uint8_t*>( |
*reinterpret_cast<int32_t*>(data + 1))); |
- AppendToBuffer("),rax"); |
+ Print("),rax"); |
} |
data += 5; |
break; |
@@ -1835,13 +1841,13 @@ int DisassemblerX64::InstructionDecode(uword pc) { |
case QUADWORD_SIZE: { |
// New x64 instruction mov rax,(imm_64). |
if (*data == 0xA1) { // Opcode 0xA1 |
- AppendToBuffer("movq rax,("); |
- AppendAddressToBuffer(*reinterpret_cast<uint8_t**>(data + 1)); |
- AppendToBuffer(")"); |
+ Print("movq rax,("); |
+ PrintAddress(*reinterpret_cast<uint8_t**>(data + 1)); |
+ Print(")"); |
} else { // Opcode 0xA3 |
- AppendToBuffer("movq ("); |
- AppendAddressToBuffer(*reinterpret_cast<uint8_t**>(data + 1)); |
- AppendToBuffer("),rax"); |
+ Print("movq ("); |
+ PrintAddress(*reinterpret_cast<uint8_t**>(data + 1)); |
+ Print("),rax"); |
} |
data += 9; |
break; |
@@ -1853,7 +1859,8 @@ int DisassemblerX64::InstructionDecode(uword pc) { |
break; |
case 0xA8: |
- AppendToBuffer("test al,%#x", *reinterpret_cast<uint8_t*>(data + 1)); |
+ Print("test al,"); |
+ PrintImmediateValue(*reinterpret_cast<uint8_t*>(data + 1)); |
data += 2; |
break; |
@@ -1875,9 +1882,8 @@ int DisassemblerX64::InstructionDecode(uword pc) { |
default: |
UNREACHABLE(); |
} |
- AppendToBuffer("test%c rax,%#" Px64 "", |
- operand_size_code(), |
- value); |
+ Print("test%c rax,", operand_size_code()); |
+ PrintImmediateValue(value); |
break; |
} |
case 0xD1: // fall through |