| Index: src/ia32/disasm-ia32.cc
|
| ===================================================================
|
| --- src/ia32/disasm-ia32.cc (revision 3139)
|
| +++ src/ia32/disasm-ia32.cc (working copy)
|
| @@ -204,7 +204,7 @@
|
| InstructionDesc* id = &instructions_[bm[i].b];
|
| id->mnem = bm[i].mnem;
|
| id->op_order_ = bm[i].op_order_;
|
| - assert(id->type == NO_INSTR); // Information already entered
|
| + ASSERT_EQ(NO_INSTR, id->type); // Information not already entered.
|
| id->type = type;
|
| }
|
| }
|
| @@ -216,7 +216,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;
|
| }
|
| @@ -226,7 +226,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 = jump_conditional_mnem[b & 0x0F];
|
| id->type = JUMP_CONDITIONAL_SHORT_INSTR;
|
| }
|
| @@ -321,6 +321,8 @@
|
| int SetCC(byte* data);
|
| int CMov(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, ...);
|
|
|
|
|
| @@ -493,7 +495,7 @@
|
|
|
| // Returns number of bytes used, including *data.
|
| int DisassemblerIA32::F7Instruction(byte* data) {
|
| - assert(*data == 0xF7);
|
| + ASSERT_EQ(0xF7, *data);
|
| byte modrm = *(data+1);
|
| int mod, regop, rm;
|
| get_modrm(modrm, &mod, ®op, &rm);
|
| @@ -526,7 +528,7 @@
|
|
|
| int DisassemblerIA32::D1D3C1Instruction(byte* data) {
|
| byte op = *data;
|
| - assert(op == 0xD1 || op == 0xD3 || op == 0xC1);
|
| + ASSERT(op == 0xD1 || op == 0xD3 || op == 0xC1);
|
| byte modrm = *(data+1);
|
| int mod, regop, rm;
|
| get_modrm(modrm, &mod, ®op, &rm);
|
| @@ -560,7 +562,7 @@
|
| default: UnimplementedInstruction();
|
| }
|
| }
|
| - assert(mnem != NULL);
|
| + ASSERT_NE(NULL, mnem);
|
| AppendToBuffer("%s %s,", mnem, NameOfCPURegister(rm));
|
| if (imm8 > 0) {
|
| AppendToBuffer("%d", imm8);
|
| @@ -576,7 +578,7 @@
|
|
|
| // Returns number of bytes used, including *data.
|
| int DisassemblerIA32::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));
|
| @@ -586,7 +588,7 @@
|
|
|
| // Returns number of bytes used, including *data.
|
| int DisassemblerIA32::JumpConditional(byte* data, const char* comment) {
|
| - 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 = jump_conditional_mnem[cond];
|
| @@ -614,18 +616,18 @@
|
|
|
| // Returns number of bytes used, including *data.
|
| int DisassemblerIA32::SetCC(byte* data) {
|
| - assert(*data == 0x0F);
|
| + ASSERT_EQ(0x0F, *data);
|
| byte cond = *(data+1) & 0x0F;
|
| const char* mnem = set_conditional_mnem[cond];
|
| AppendToBuffer("%s ", mnem);
|
| PrintRightByteOperand(data+2);
|
| - return 3; // includes 0x0F
|
| + return 3; // Includes 0x0F.
|
| }
|
|
|
|
|
| // Returns number of bytes used, including *data.
|
| int DisassemblerIA32::CMov(byte* data) {
|
| - assert(*data == 0x0F);
|
| + ASSERT_EQ(0x0F, *data);
|
| byte cond = *(data + 1) & 0x0F;
|
| const char* mnem = conditional_move_mnem[cond];
|
| int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2);
|
| @@ -635,107 +637,165 @@
|
|
|
| // Returns number of bytes used, including *data.
|
| int DisassemblerIA32::FPUInstruction(byte* data) {
|
| - byte b1 = *data;
|
| - byte b2 = *(data + 1);
|
| - if (b1 == 0xD9) {
|
| - const char* mnem = NULL;
|
| - switch (b2) {
|
| - case 0xE8: mnem = "fld1"; break;
|
| - case 0xEE: mnem = "fldz"; break;
|
| - case 0xE1: mnem = "fabs"; break;
|
| - case 0xE0: mnem = "fchs"; break;
|
| - case 0xF8: mnem = "fprem"; break;
|
| - case 0xF5: mnem = "fprem1"; break;
|
| - case 0xF7: mnem = "fincstp"; break;
|
| - case 0xE4: mnem = "ftst"; 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, ®op, &rm);
|
| - const char* mnem = "?";
|
| - switch (regop) {
|
| - case eax: mnem = "fld_s"; break;
|
| - case ebx: mnem = "fstp_s"; break;
|
| + 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 DisassemblerIA32::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) {
|
| - if ((b2 & 0xF8) == 0xC0) {
|
| - AppendToBuffer("ffree st%d", b2 & 0x7);
|
| - return 2;
|
| - } else {
|
| - int mod, regop, rm;
|
| - get_modrm(*(data+1), &mod, ®op, &rm);
|
| - const char* mnem = "?";
|
| - switch (regop) {
|
| - case eax: mnem = "fld_d"; break;
|
| - case ebx: mnem = "fstp_d"; 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();
|
| }
|
| - AppendToBuffer("%s ", mnem);
|
| - int count = PrintRightOperand(data + 1);
|
| - return count + 1;
|
| - }
|
| - } else if (b1 == 0xDB) {
|
| - int mod, regop, rm;
|
| - get_modrm(*(data+1), &mod, ®op, &rm);
|
| - const char* mnem = "?";
|
| - switch (regop) {
|
| - case eax: mnem = "fild_s"; break;
|
| - case edx: mnem = "fist_s"; break;
|
| - case ebx: mnem = "fistp_s"; break;
|
| - default: 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, ®op, &rm);
|
| - const char* mnem = "?";
|
| - switch (regop) {
|
| - case ebp: mnem = "fild_d"; break;
|
| - case edi: mnem = "fistp_d"; break;
|
| - default: 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 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 DisassemblerIA32::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;
|
| + default:
|
| + 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();
|
| + }
|
| + }
|
| + break;
|
| +
|
| + case 0xDA:
|
| + if (modrm_byte == 0xE9) {
|
| + mnem = "fucompp";
|
| + } else {
|
| + UnimplementedInstruction();
|
| + }
|
| + break;
|
| +
|
| + case 0xDB:
|
| + if ((modrm_byte & 0xF8) == 0xE8) {
|
| + mnem = "fucomi";
|
| + has_register = true;
|
| + } else if (modrm_byte == 0xE2) {
|
| + mnem = "fclex";
|
| + } else {
|
| + UnimplementedInstruction();
|
| + }
|
| + 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;
|
| }
|
|
|
|
|