Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1497)

Unified Diff: src/x64/disasm-x64.cc

Issue 316010: Add fucomip instruction to disassembler. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/ia32/disasm-ia32.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/x64/disasm-x64.cc
===================================================================
--- src/x64/disasm-x64.cc (revision 3139)
+++ src/x64/disasm-x64.cc (working copy)
@@ -218,7 +218,7 @@
OperandType op_order = bm[i].op_order_;
id->op_order_ =
static_cast<OperandType>(op_order & ~BYTE_SIZE_OPERAND_FLAG);
- assert(id->type == NO_INSTR); // Information not already entered
+ ASSERT_EQ(NO_INSTR, id->type); // Information not already entered
id->type = type;
id->byte_size_operation = ((op_order & BYTE_SIZE_OPERAND_FLAG) != 0);
}
@@ -232,7 +232,7 @@
const char* mnem) {
for (byte b = start; b <= end; b++) {
InstructionDesc* id = &instructions_[b];
- assert(id->type == NO_INSTR); // Information already entered
+ ASSERT_EQ(NO_INSTR, id->type); // Information not already entered
id->mnem = mnem;
id->type = type;
id->byte_size_operation = byte_size;
@@ -243,7 +243,7 @@
void InstructionTable::AddJumpConditionalShort() {
for (byte b = 0x70; b <= 0x7F; b++) {
InstructionDesc* id = &instructions_[b];
- assert(id->type == NO_INSTR); // Information already entered
+ ASSERT_EQ(NO_INSTR, id->type); // Information not already entered
id->mnem = NULL; // Computed depending on condition code.
id->type = JUMP_CONDITIONAL_SHORT_INSTR;
}
@@ -393,6 +393,7 @@
RegisterNameMapping register_name);
int PrintRightOperand(byte* modrmp);
int PrintRightByteOperand(byte* modrmp);
+ int PrintRightXMMOperand(byte* modrmp);
int PrintOperands(const char* mnem,
OperandType op_order,
byte* data);
@@ -400,13 +401,15 @@
int PrintImmediateOp(byte* data);
const char* TwoByteMnemonic(byte opcode);
int TwoByteOpcodeInstruction(byte* data);
- int F7Instruction(byte* data);
+ int F6F7Instruction(byte* data);
int ShiftInstruction(byte* data);
int JumpShort(byte* data);
int JumpConditional(byte* data);
int JumpConditionalShort(byte* data);
int SetCC(byte* data);
int FPUInstruction(byte* data);
+ int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start);
+ int RegisterFPUInstruction(int escape_opcode, byte modrm_byte);
void AppendToBuffer(const char* format, ...);
void UnimplementedInstruction() {
@@ -568,6 +571,12 @@
}
+int DisassemblerX64::PrintRightXMMOperand(byte* modrmp) {
+ return PrintRightOperandHelper(modrmp,
+ &DisassemblerX64::NameOfXMMRegister);
+}
+
+
// Returns number of bytes used including the current *data.
// Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'.
int DisassemblerX64::PrintOperands(const char* mnem,
@@ -648,8 +657,8 @@
// Returns number of bytes used, including *data.
-int DisassemblerX64::F7Instruction(byte* data) {
- assert(*data == 0xF7);
+int DisassemblerX64::F6F7Instruction(byte* data) {
+ ASSERT(*data == 0xF7 || *data == 0xF6);
byte modrm = *(data + 1);
int mod, regop, rm;
get_modrm(modrm, &mod, &regop, &rm);
@@ -676,19 +685,12 @@
operand_size_code(),
NameOfCPURegister(rm));
return 2;
- } else if (mod == 3 && regop == 0) {
- int32_t imm = *reinterpret_cast<int32_t*>(data + 2);
- AppendToBuffer("test%c %s,0x%x",
- operand_size_code(),
- NameOfCPURegister(rm),
- imm);
- return 6;
} else if (regop == 0) {
AppendToBuffer("test%c ", operand_size_code());
- int count = PrintRightOperand(data + 1);
- int32_t imm = *reinterpret_cast<int32_t*>(data + 1 + count);
- AppendToBuffer(",0x%x", imm);
- return 1 + count + 4 /*int32_t*/;
+ int count = PrintRightOperand(data + 1); // Use name of 64-bit register.
+ AppendToBuffer(",0x");
+ count += PrintImmediate(data + 1 + count, operand_size());
+ return 1 + count;
} else {
UnimplementedInstruction();
return 2;
@@ -739,7 +741,7 @@
UnimplementedInstruction();
return num_bytes;
}
- assert(mnem != NULL);
+ ASSERT_NE(NULL, mnem);
if (op == 0xD0) {
imm8 = 1;
} else if (op == 0xC0) {
@@ -762,7 +764,7 @@
// Returns number of bytes used, including *data.
int DisassemblerX64::JumpShort(byte* data) {
- assert(*data == 0xEB);
+ ASSERT_EQ(0xEB, *data);
byte b = *(data + 1);
byte* dest = data + static_cast<int8_t>(b) + 2;
AppendToBuffer("jmp %s", NameOfAddress(dest));
@@ -772,7 +774,7 @@
// Returns number of bytes used, including *data.
int DisassemblerX64::JumpConditional(byte* data) {
- assert(*data == 0x0F);
+ ASSERT_EQ(0x0F, *data);
byte cond = *(data + 1) & 0x0F;
byte* dest = data + *reinterpret_cast<int32_t*>(data + 2) + 6;
const char* mnem = conditional_code_suffix[cond];
@@ -794,7 +796,7 @@
// Returns number of bytes used, including *data.
int DisassemblerX64::SetCC(byte* data) {
- assert(*data == 0x0F);
+ ASSERT_EQ(0x0F, *data);
byte cond = *(data + 1) & 0x0F;
const char* mnem = conditional_code_suffix[cond];
AppendToBuffer("set%s%c ", mnem, operand_size_code());
@@ -805,168 +807,170 @@
// Returns number of bytes used, including *data.
int DisassemblerX64::FPUInstruction(byte* data) {
- byte b1 = *data;
- byte b2 = *(data + 1);
- if (b1 == 0xD9) {
- const char* mnem = NULL;
- switch (b2) {
- case 0xE0:
- mnem = "fchs";
- break;
- case 0xE1:
- mnem = "fabs";
- break;
- case 0xE4:
- mnem = "ftst";
- break;
- case 0xF5:
- mnem = "fprem1";
- break;
- case 0xF7:
- mnem = "fincstp";
- break;
- case 0xE8:
- mnem = "fld1";
- break;
- case 0xEE:
- mnem = "fldz";
- break;
- case 0xF8:
- mnem = "fprem";
- break;
- }
- if (mnem != NULL) {
- AppendToBuffer("%s", mnem);
- return 2;
- } else if ((b2 & 0xF8) == 0xC8) {
- AppendToBuffer("fxch st%d", b2 & 0x7);
- return 2;
- } else {
- int mod, regop, rm;
- get_modrm(*(data + 1), &mod, &regop, &rm);
- const char* mnem = "?";
- switch (regop) {
- case 0:
- mnem = "fld_s";
- break;
- case 3:
- mnem = "fstp_s";
- break;
- default:
- UnimplementedInstruction();
+ byte escape_opcode = *data;
+ ASSERT_EQ(0xD8, escape_opcode & 0xF8);
+ byte modrm_byte = *(data+1);
+
+ if (modrm_byte >= 0xC0) {
+ return RegisterFPUInstruction(escape_opcode, modrm_byte);
+ } else {
+ return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1);
+ }
+}
+
+int DisassemblerX64::MemoryFPUInstruction(int escape_opcode,
+ int modrm_byte,
+ byte* modrm_start) {
+ const char* mnem = "?";
+ int regop = (modrm_byte >> 3) & 0x7; // reg/op field of modrm byte.
+ switch (escape_opcode) {
+ case 0xD9: switch (regop) {
+ case 0: mnem = "fld_s"; break;
+ case 3: mnem = "fstp_s"; break;
+ case 7: mnem = "fstcw"; break;
+ default: UnimplementedInstruction();
}
- AppendToBuffer("%s ", mnem);
- int count = PrintRightOperand(data + 1);
- return count + 1;
- }
- } else if (b1 == 0xDD) {
- int mod, regop, rm;
- get_modrm(*(data + 1), &mod, &regop, &rm);
- if (mod == 3) {
- switch (regop) {
- case 0:
- AppendToBuffer("ffree st%d", rm & 7);
- break;
- case 2:
- AppendToBuffer("fstp st%d", rm & 7);
- break;
- default:
- UnimplementedInstruction();
- break;
+ break;
+
+ case 0xDB: switch (regop) {
+ case 0: mnem = "fild_s"; break;
+ case 1: mnem = "fisttp_s"; break;
+ case 2: mnem = "fist_s"; break;
+ case 3: mnem = "fistp_s"; break;
+ default: UnimplementedInstruction();
}
- return 2;
- } else {
- const char* mnem = "?";
- switch (regop) {
- case 0:
- mnem = "fld_d";
+ break;
+
+ case 0xDD: switch (regop) {
+ case 0: mnem = "fld_d"; break;
+ case 3: mnem = "fstp_d"; break;
+ default: UnimplementedInstruction();
+ }
+ break;
+
+ case 0xDF: switch (regop) {
+ case 5: mnem = "fild_d"; break;
+ case 7: mnem = "fistp_d"; break;
+ default: UnimplementedInstruction();
+ }
+ break;
+
+ default: UnimplementedInstruction();
+ }
+ AppendToBuffer("%s ", mnem);
+ int count = PrintRightOperand(modrm_start);
+ return count + 1;
+}
+
+int DisassemblerX64::RegisterFPUInstruction(int escape_opcode,
+ byte modrm_byte) {
+ bool has_register = false; // Is the FPU register encoded in modrm_byte?
+ const char* mnem = "?";
+
+ switch (escape_opcode) {
+ case 0xD8:
+ UnimplementedInstruction();
+ break;
+
+ case 0xD9:
+ switch (modrm_byte & 0xF8) {
+ case 0xC8:
+ mnem = "fxch";
+ has_register = true;
break;
- case 3:
- mnem = "fstp_d";
- break;
default:
- UnimplementedInstruction();
+ switch (modrm_byte) {
+ case 0xE0: mnem = "fchs"; break;
+ case 0xE1: mnem = "fabs"; break;
+ case 0xE4: mnem = "ftst"; break;
+ case 0xE8: mnem = "fld1"; break;
+ case 0xEE: mnem = "fldz"; break;
+ case 0xF5: mnem = "fprem1"; break;
+ case 0xF7: mnem = "fincstp"; break;
+ case 0xF8: mnem = "fprem"; break;
+ case 0xFE: mnem = "fsin"; break;
+ case 0xFF: mnem = "fcos"; break;
+ default: UnimplementedInstruction();
+ }
}
- AppendToBuffer("%s ", mnem);
- int count = PrintRightOperand(data + 1);
- return count + 1;
- }
- } else if (b1 == 0xDB) {
- int mod, regop, rm;
- get_modrm(*(data + 1), &mod, &regop, &rm);
- const char* mnem = "?";
- switch (regop) {
- case 0:
- mnem = "fild_s";
- break;
- case 2:
- mnem = "fist_s";
- break;
- case 3:
- mnem = "fistp_s";
- break;
- default:
+ break;
+
+ case 0xDA:
+ if (modrm_byte == 0xE9) {
+ mnem = "fucompp";
+ } else {
UnimplementedInstruction();
- }
- AppendToBuffer("%s ", mnem);
- int count = PrintRightOperand(data + 1);
- return count + 1;
- } else if (b1 == 0xDF) {
- if (b2 == 0xE0) {
- AppendToBuffer("fnstsw_ax");
- return 2;
- }
- int mod, regop, rm;
- get_modrm(*(data + 1), &mod, &regop, &rm);
- const char* mnem = "?";
- switch (regop) {
- case 5:
- mnem = "fild_d";
- break;
- case 7:
- mnem = "fistp_d";
- break;
- default:
+ }
+ break;
+
+ case 0xDB:
+ if ((modrm_byte & 0xF8) == 0xE8) {
+ mnem = "fucomi";
+ has_register = true;
+ } else if (modrm_byte == 0xE2) {
+ mnem = "fclex";
+ } else {
UnimplementedInstruction();
- }
- AppendToBuffer("%s ", mnem);
- int count = PrintRightOperand(data + 1);
- return count + 1;
- } else if (b1 == 0xDC || b1 == 0xDE) {
- bool is_pop = (b1 == 0xDE);
- if (is_pop && b2 == 0xD9) {
- AppendToBuffer("fcompp");
- return 2;
- }
- const char* mnem = "FP0xDC";
- switch (b2 & 0xF8) {
- case 0xC0:
- mnem = "fadd";
- break;
- case 0xE8:
- mnem = "fsub";
- break;
- case 0xC8:
- mnem = "fmul";
- break;
- case 0xF8:
- mnem = "fdiv";
- break;
- default:
- UnimplementedInstruction();
- }
- AppendToBuffer("%s%s st%d", mnem, is_pop ? "p" : "", b2 & 0x7);
- return 2;
- } else if (b1 == 0xDA && b2 == 0xE9) {
- const char* mnem = "fucompp";
+ }
+ break;
+
+ case 0xDC:
+ has_register = true;
+ switch (modrm_byte & 0xF8) {
+ case 0xC0: mnem = "fadd"; break;
+ case 0xE8: mnem = "fsub"; break;
+ case 0xC8: mnem = "fmul"; break;
+ case 0xF8: mnem = "fdiv"; break;
+ default: UnimplementedInstruction();
+ }
+ break;
+
+ case 0xDD:
+ has_register = true;
+ switch (modrm_byte & 0xF8) {
+ case 0xC0: mnem = "ffree"; break;
+ case 0xD8: mnem = "fstp"; break;
+ default: UnimplementedInstruction();
+ }
+ break;
+
+ case 0xDE:
+ if (modrm_byte == 0xD9) {
+ mnem = "fcompp";
+ } else {
+ has_register = true;
+ switch (modrm_byte & 0xF8) {
+ case 0xC0: mnem = "faddp"; break;
+ case 0xE8: mnem = "fsubp"; break;
+ case 0xC8: mnem = "fmulp"; break;
+ case 0xF8: mnem = "fdivp"; break;
+ default: UnimplementedInstruction();
+ }
+ }
+ break;
+
+ case 0xDF:
+ if (modrm_byte == 0xE0) {
+ mnem = "fnstsw_ax";
+ } else if ((modrm_byte & 0xF8) == 0xE8) {
+ mnem = "fucomip";
+ has_register = true;
+ }
+ break;
+
+ default: UnimplementedInstruction();
+ }
+
+ if (has_register) {
+ AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7);
+ } else {
AppendToBuffer("%s", mnem);
- return 2;
}
- AppendToBuffer("Unknown FP instruction");
return 2;
}
+
// Handle all two-byte opcodes, which start with 0x0F.
// These instructions may be affected by an 0x66, 0xF2, or 0xF3 prefix.
// We do not use any three-byte opcodes, which start with 0x0F38 or 0x0F3A.
@@ -1045,13 +1049,13 @@
int mod, regop, rm;
get_modrm(*current, &mod, &regop, &rm);
AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
- data += PrintRightOperand(data);
+ current += PrintRightOperand(current);
} else if ((opcode & 0xF8) == 0x58) {
// XMM arithmetic. Mnemonic was retrieved at the start of this function.
int mod, regop, rm;
get_modrm(*current, &mod, &regop, &rm);
- AppendToBuffer("%s %s,%s", mnemonic, NameOfXMMRegister(regop),
- NameOfXMMRegister(rm));
+ AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
+ current += PrintRightXMMOperand(current);
} else {
UnimplementedInstruction();
}
@@ -1060,7 +1064,7 @@
// CVTTSS2SI: Convert scalar single-precision FP to dword integer.
// Assert that mod is not 3, so source is memory, not an XMM register.
- ASSERT((*current & 0xC0) != 0xC0);
+ ASSERT_NE(0xC0, *current & 0xC0);
current += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, current);
} else {
UnimplementedInstruction();
@@ -1236,18 +1240,6 @@
break;
}
- case 0xF6: {
- int mod, regop, rm;
- get_modrm(*(data + 1), &mod, &regop, &rm);
- if (mod == 3 && regop == 0) {
- AppendToBuffer("testb %s,%d", NameOfCPURegister(rm), *(data + 2));
- } else {
- UnimplementedInstruction();
- }
- data += 3;
- break;
- }
-
case 0x81: // fall through
case 0x83: // 0x81 with sign extension bit set
data += PrintImmediateOp(data);
@@ -1344,7 +1336,7 @@
case 0x95:
case 0x96:
case 0x97: {
- int reg = (current & 0x7) | (rex_b() ? 8 : 0);
+ int reg = (*data & 0x7) | (rex_b() ? 8 : 0);
if (reg == 0) {
AppendToBuffer("nop"); // Common name for xchg rax,rax.
} else {
@@ -1352,9 +1344,10 @@
operand_size_code(),
NameOfCPURegister(reg));
}
+ data++;
}
+ break;
-
case 0xFE: {
data++;
int mod, regop, rm;
@@ -1465,8 +1458,10 @@
data += JumpShort(data);
break;
+ case 0xF6:
+ byte_size_operand_ = true; // fall through
case 0xF7:
- data += F7Instruction(data);
+ data += F6F7Instruction(data);
break;
default:
« no previous file with comments | « src/ia32/disasm-ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698