Commit 658ca2f1 authored by sgjesse@chromium.org's avatar sgjesse@chromium.org

Add missing instructions to the IA-32 disasembler

Added newly added instructions to test-disasem-ia32.cc and implemented the missi
ng ones in the disasembler.

Added some asserts to 8-bit instructions which only work with eax, ebx, ecx and
edx (al, bl, cl and dl).

Removed the loope instruction.
Review URL: http://codereview.chromium.org/548002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3577 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent c8605330
...@@ -575,6 +575,7 @@ void Assembler::leave() { ...@@ -575,6 +575,7 @@ void Assembler::leave() {
void Assembler::mov_b(Register dst, const Operand& src) { void Assembler::mov_b(Register dst, const Operand& src) {
ASSERT(dst.code() < 4);
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
EMIT(0x8A); EMIT(0x8A);
...@@ -592,6 +593,7 @@ void Assembler::mov_b(const Operand& dst, int8_t imm8) { ...@@ -592,6 +593,7 @@ void Assembler::mov_b(const Operand& dst, int8_t imm8) {
void Assembler::mov_b(const Operand& dst, Register src) { void Assembler::mov_b(const Operand& dst, Register src) {
ASSERT(src.code() < 4);
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
EMIT(0x88); EMIT(0x88);
...@@ -1208,6 +1210,7 @@ void Assembler::sub(Register dst, const Operand& src) { ...@@ -1208,6 +1210,7 @@ void Assembler::sub(Register dst, const Operand& src) {
void Assembler::subb(Register dst, const Operand& src) { void Assembler::subb(Register dst, const Operand& src) {
ASSERT(dst.code() < 4);
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
EMIT(0x2A); EMIT(0x2A);
...@@ -1600,21 +1603,8 @@ void Assembler::j(Condition cc, Handle<Code> code, Hint hint) { ...@@ -1600,21 +1603,8 @@ void Assembler::j(Condition cc, Handle<Code> code, Hint hint) {
} }
void Assembler::loope(Label* L) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
// Only short backward jumps.
ASSERT(L->is_bound());
int offs = L->pos() - pc_offset();
const int kLoopInstructionSize = 2;
ASSERT(is_int8(offs - kLoopInstructionSize));
EMIT(0xE1);
EMIT((offs - kLoopInstructionSize) & 0xFF);
}
// FPU instructions // FPU instructions
void Assembler::fld(int i) { void Assembler::fld(int i) {
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
......
...@@ -676,9 +676,6 @@ class Assembler : public Malloced { ...@@ -676,9 +676,6 @@ class Assembler : public Malloced {
void j(Condition cc, byte* entry, RelocInfo::Mode rmode, Hint hint = no_hint); void j(Condition cc, byte* entry, RelocInfo::Mode rmode, Hint hint = no_hint);
void j(Condition cc, Handle<Code> code, Hint hint = no_hint); void j(Condition cc, Handle<Code> code, Hint hint = no_hint);
// Loop instruction using ecx as counter.
void loope(Label* L);
// Floating-point operations // Floating-point operations
void fld(int i); void fld(int i);
......
...@@ -9637,48 +9637,51 @@ void SubStringStub::Generate(MacroAssembler* masm) { ...@@ -9637,48 +9637,51 @@ void SubStringStub::Generate(MacroAssembler* masm) {
void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
Register left, Register left,
Register right, Register right,
Register counter,
Register scratch1, Register scratch1,
Register scratch2) { Register scratch2,
ASSERT(counter.is(ecx)); Register scratch3) {
Label compare_lengths, compare_lengths_1; Label compare_lengths, compare_lengths_1;
// Find minimum length. If either length is zero just compare lengths. // Find minimum length. If either length is zero just compare lengths.
__ mov(counter, FieldOperand(left, String::kLengthOffset)); __ mov(scratch1, FieldOperand(left, String::kLengthOffset));
__ test(counter, Operand(counter));
__ j(zero, &compare_lengths_1);
__ mov(scratch1, FieldOperand(right, String::kLengthOffset));
__ test(scratch1, Operand(scratch1)); __ test(scratch1, Operand(scratch1));
__ j(zero, &compare_lengths_1); __ j(zero, &compare_lengths_1);
__ cmp(counter, Operand(scratch1)); __ mov(scratch2, FieldOperand(right, String::kLengthOffset));
__ test(scratch2, Operand(scratch2));
__ j(zero, &compare_lengths_1);
__ cmp(scratch1, Operand(scratch2));
if (CpuFeatures::IsSupported(CMOV)) { if (CpuFeatures::IsSupported(CMOV)) {
CpuFeatures::Scope use_cmov(CMOV); CpuFeatures::Scope use_cmov(CMOV);
__ cmov(greater, counter, Operand(scratch1)); __ cmov(greater, scratch1, Operand(scratch2));
} else { } else {
Label l; Label l;
__ j(less, &l); __ j(less, &l);
__ mov(counter, scratch1); __ mov(scratch1, scratch2);
__ bind(&l); __ bind(&l);
} }
Label result_greater, result_less; Label result_greater, result_less;
Label loop; Label loop;
// Compare next character. // Compare next character.
__ mov(scratch2, Immediate(-1)); // Index into strings. __ mov(scratch3, Immediate(-1)); // Index into strings.
__ bind(&loop); __ bind(&loop);
// Compare characters. // Compare characters.
__ add(Operand(scratch2), Immediate(1)); Label character_compare_done;
__ mov_b(scratch1, Operand(left, __ add(Operand(scratch3), Immediate(1));
scratch2, __ mov_b(scratch2, Operand(left,
scratch3,
times_1, times_1,
SeqAsciiString::kHeaderSize - kHeapObjectTag)); SeqAsciiString::kHeaderSize - kHeapObjectTag));
__ subb(scratch1, Operand(right, __ subb(scratch2, Operand(right,
scratch2, scratch3,
times_1, times_1,
SeqAsciiString::kHeaderSize - kHeapObjectTag)); SeqAsciiString::kHeaderSize - kHeapObjectTag));
__ loope(&loop); __ j(not_equal, &character_compare_done);
__ sub(Operand(scratch1), Immediate(1));
__ j(not_zero, &loop);
// If min length characters match compare lengths otherwise last character // If min length characters match compare lengths otherwise last character
// compare is the result. // compare is the result.
__ bind(&character_compare_done);
__ j(equal, &compare_lengths); __ j(equal, &compare_lengths);
__ j(less, &result_less); __ j(less, &result_less);
__ jmp(&result_greater); __ jmp(&result_greater);
...@@ -9686,9 +9689,9 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, ...@@ -9686,9 +9689,9 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
// Compare lengths. // Compare lengths.
Label result_not_equal; Label result_not_equal;
__ bind(&compare_lengths); __ bind(&compare_lengths);
__ mov(counter, FieldOperand(left, String::kLengthOffset)); __ mov(scratch1, FieldOperand(left, String::kLengthOffset));
__ bind(&compare_lengths_1); __ bind(&compare_lengths_1);
__ sub(counter, FieldOperand(right, String::kLengthOffset)); __ sub(scratch1, FieldOperand(right, String::kLengthOffset));
__ j(not_zero, &result_not_equal); __ j(not_zero, &result_not_equal);
// Result is EQUAL. // Result is EQUAL.
......
...@@ -813,16 +813,13 @@ class StringCompareStub: public StringStubBase { ...@@ -813,16 +813,13 @@ class StringCompareStub: public StringStubBase {
} }
// Compare two flat ascii strings and returns result in eax after popping two // Compare two flat ascii strings and returns result in eax after popping two
// arguments from the stack. Due to the instructions used there are certain // arguments from the stack.
// constraints on the registers that can be passed.
// counter must be ecx
// scratch1 most be one of eax, ebx or edx
static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm, static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
Register left, Register left,
Register right, Register right,
Register counter,
Register scratch1, Register scratch1,
Register scratch2); Register scratch2,
Register scratch3);
private: private:
Major MajorKey() { return StringCompare; } Major MajorKey() { return StringCompare; }
......
...@@ -117,11 +117,6 @@ static const char* jump_conditional_mnem[] = { ...@@ -117,11 +117,6 @@ static const char* jump_conditional_mnem[] = {
}; };
static const char* loop_mnem[] = {
"loopne", "loope", "loop"
};
static const char* set_conditional_mnem[] = { static const char* set_conditional_mnem[] = {
/*0*/ "seto", "setno", "setc", "setnc", /*0*/ "seto", "setno", "setc", "setnc",
/*4*/ "setz", "setnz", "setna", "seta", /*4*/ "setz", "setnz", "setna", "seta",
...@@ -143,7 +138,6 @@ enum InstructionType { ...@@ -143,7 +138,6 @@ enum InstructionType {
ZERO_OPERANDS_INSTR, ZERO_OPERANDS_INSTR,
TWO_OPERANDS_INSTR, TWO_OPERANDS_INSTR,
JUMP_CONDITIONAL_SHORT_INSTR, JUMP_CONDITIONAL_SHORT_INSTR,
LOOP_INSTR,
REGISTER_INSTR, REGISTER_INSTR,
MOVE_REG_INSTR, MOVE_REG_INSTR,
CALL_JUMP_INSTR, CALL_JUMP_INSTR,
...@@ -173,7 +167,6 @@ class InstructionTable { ...@@ -173,7 +167,6 @@ class InstructionTable {
byte end, byte end,
const char* mnem); const char* mnem);
void AddJumpConditionalShort(); void AddJumpConditionalShort();
void AddLoop();
}; };
...@@ -198,7 +191,6 @@ void InstructionTable::Init() { ...@@ -198,7 +191,6 @@ void InstructionTable::Init() {
CopyTable(call_jump_instr, CALL_JUMP_INSTR); CopyTable(call_jump_instr, CALL_JUMP_INSTR);
CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR); CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR);
AddJumpConditionalShort(); AddJumpConditionalShort();
AddLoop();
SetTableRange(REGISTER_INSTR, 0x40, 0x47, "inc"); SetTableRange(REGISTER_INSTR, 0x40, 0x47, "inc");
SetTableRange(REGISTER_INSTR, 0x48, 0x4F, "dec"); SetTableRange(REGISTER_INSTR, 0x48, 0x4F, "dec");
SetTableRange(REGISTER_INSTR, 0x50, 0x57, "push"); SetTableRange(REGISTER_INSTR, 0x50, 0x57, "push");
...@@ -242,16 +234,6 @@ void InstructionTable::AddJumpConditionalShort() { ...@@ -242,16 +234,6 @@ void InstructionTable::AddJumpConditionalShort() {
} }
void InstructionTable::AddLoop() {
for (byte b = 0xE0; b <= 0xE2; b++) {
InstructionDesc* id = &instructions_[b];
ASSERT_EQ(NO_INSTR, id->type); // Information not already entered.
id->mnem = loop_mnem[b & 0x03];
id->type = LOOP_INSTR;
}
}
static InstructionTable instruction_table; static InstructionTable instruction_table;
...@@ -348,7 +330,6 @@ class DisassemblerIA32 { ...@@ -348,7 +330,6 @@ class DisassemblerIA32 {
int JumpShort(byte* data); int JumpShort(byte* data);
int JumpConditional(byte* data, const char* comment); int JumpConditional(byte* data, const char* comment);
int JumpConditionalShort(byte* data, const char* comment); int JumpConditionalShort(byte* data, const char* comment);
int Loop(byte* data);
int SetCC(byte* data); int SetCC(byte* data);
int CMov(byte* data); int CMov(byte* data);
int FPUInstruction(byte* data); int FPUInstruction(byte* data);
...@@ -636,17 +617,6 @@ int DisassemblerIA32::JumpConditionalShort(byte* data, const char* comment) { ...@@ -636,17 +617,6 @@ int DisassemblerIA32::JumpConditionalShort(byte* data, const char* comment) {
} }
// Returns number of bytes used, including *data.
int DisassemblerIA32::Loop(byte* data) {
byte cond = *data & 0x03;
byte b = *(data+1);
byte* dest = data + static_cast<int8_t>(b) + 2;
const char* mnem = loop_mnem[cond];
AppendToBuffer("%s %s", mnem, NameOfAddress(dest));
return 2;
}
// Returns number of bytes used, including *data. // Returns number of bytes used, including *data.
int DisassemblerIA32::SetCC(byte* data) { int DisassemblerIA32::SetCC(byte* data) {
ASSERT_EQ(0x0F, *data); ASSERT_EQ(0x0F, *data);
...@@ -885,10 +855,6 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer, ...@@ -885,10 +855,6 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
data += JumpConditionalShort(data, branch_hint); data += JumpConditionalShort(data, branch_hint);
break; break;
case LOOP_INSTR:
data += Loop(data);
break;
case REGISTER_INSTR: case REGISTER_INSTR:
AppendToBuffer("%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07)); AppendToBuffer("%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07));
data++; data++;
...@@ -1042,7 +1008,16 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer, ...@@ -1042,7 +1008,16 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
case 0x80: case 0x80:
{ data++; { data++;
AppendToBuffer("%s ", "cmpb"); int mod, regop, rm;
get_modrm(*data, &mod, &regop, &rm);
const char* mnem = NULL;
printf("%d\n", regop);
switch (regop) {
case 5: mnem = "subb"; break;
case 7: mnem = "cmpb"; break;
default: UnimplementedInstruction();
}
AppendToBuffer("%s ", mnem);
data += PrintRightOperand(data); data += PrintRightOperand(data);
int32_t imm = *data; int32_t imm = *data;
AppendToBuffer(",0x%x", imm); AppendToBuffer(",0x%x", imm);
...@@ -1092,6 +1067,19 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer, ...@@ -1092,6 +1067,19 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
NameOfXMMRegister(regop), NameOfXMMRegister(regop),
NameOfXMMRegister(rm)); NameOfXMMRegister(rm));
data++; data++;
} else if (*data == 0x6F) {
data++;
int mod, regop, rm;
get_modrm(*data, &mod, &regop, &rm);
AppendToBuffer("movdqa %s,", NameOfXMMRegister(regop));
data += PrintRightOperand(data);
} else if (*data == 0x7F) {
AppendToBuffer("movdqa ");
data++;
int mod, regop, rm;
get_modrm(*data, &mod, &regop, &rm);
data += PrintRightOperand(data);
AppendToBuffer(",%s", NameOfXMMRegister(regop));
} else { } else {
UnimplementedInstruction(); UnimplementedInstruction();
} }
...@@ -1128,6 +1116,11 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer, ...@@ -1128,6 +1116,11 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
data += 2; data += 2;
break; break;
case 0x2C:
AppendToBuffer("subb eax,0x%x", *reinterpret_cast<uint8_t*>(data+1));
data += 2;
break;
case 0xA9: case 0xA9:
AppendToBuffer("test eax,0x%x", *reinterpret_cast<int32_t*>(data+1)); AppendToBuffer("test eax,0x%x", *reinterpret_cast<int32_t*>(data+1));
data += 5; data += 5;
...@@ -1198,9 +1191,29 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer, ...@@ -1198,9 +1191,29 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
break; break;
case 0xF3: case 0xF3:
if (*(data+1) == 0x0F && *(data+2) == 0x2C) { if (*(data+1) == 0x0F) {
data += 3; if (*(data+2) == 0x2C) {
data += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, data); data += 3;
data += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, data);
} else if (*(data+2) == 0x6F) {
data += 3;
int mod, regop, rm;
get_modrm(*data, &mod, &regop, &rm);
AppendToBuffer("movdqu %s,", NameOfXMMRegister(regop));
data += PrintRightOperand(data);
} else if (*(data+2) == 0x7F) {
AppendToBuffer("movdqu ");
data += 3;
int mod, regop, rm;
get_modrm(*data, &mod, &regop, &rm);
data += PrintRightOperand(data);
AppendToBuffer(",%s", NameOfXMMRegister(regop));
} else {
UnimplementedInstruction();
}
} else if (*(data+1) == 0xA5) {
data += 2;
AppendToBuffer("rep_movs");
} else { } else {
UnimplementedInstruction(); UnimplementedInstruction();
} }
...@@ -1220,6 +1233,9 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer, ...@@ -1220,6 +1233,9 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
} }
int instr_len = data - instr; int instr_len = data - instr;
if (instr_len == 0) {
printf("%02x", *data);
}
ASSERT(instr_len > 0); // Ensure progress. ASSERT(instr_len > 0); // Ensure progress.
int outp = 0; int outp = 0;
......
...@@ -57,7 +57,7 @@ static void DummyStaticFunction(Object* result) { ...@@ -57,7 +57,7 @@ static void DummyStaticFunction(Object* result) {
TEST(DisasmIa320) { TEST(DisasmIa320) {
InitializeVM(); InitializeVM();
v8::HandleScope scope; v8::HandleScope scope;
v8::internal::byte buffer[1024]; v8::internal::byte buffer[2048];
Assembler assm(buffer, sizeof buffer); Assembler assm(buffer, sizeof buffer);
DummyStaticFunction(NULL); // just bloody use it (DELETE; debugging) DummyStaticFunction(NULL); // just bloody use it (DELETE; debugging)
...@@ -223,13 +223,16 @@ TEST(DisasmIa320) { ...@@ -223,13 +223,16 @@ TEST(DisasmIa320) {
__ sub(Operand(ebx), Immediate(12)); __ sub(Operand(ebx), Immediate(12));
__ sub(Operand(edx, ecx, times_4, 10000), Immediate(12)); __ sub(Operand(edx, ecx, times_4, 10000), Immediate(12));
__ subb(Operand(edx, ecx, times_4, 10000), 100);
__ subb(Operand(eax), 100);
__ subb(eax, Operand(edx, ecx, times_4, 10000));
__ xor_(ebx, 12345); __ xor_(ebx, 12345);
__ imul(edx, ecx, 12); __ imul(edx, ecx, 12);
__ imul(edx, ecx, 1000); __ imul(edx, ecx, 1000);
__ rep_movs();
__ sub(edx, Operand(ebx, ecx, times_4, 10000)); __ sub(edx, Operand(ebx, ecx, times_4, 10000));
__ sub(edx, Operand(ebx)); __ sub(edx, Operand(ebx));
...@@ -365,6 +368,12 @@ TEST(DisasmIa320) { ...@@ -365,6 +368,12 @@ TEST(DisasmIa320) {
__ movdbl(xmm1, Operand(ebx, ecx, times_4, 10000)); __ movdbl(xmm1, Operand(ebx, ecx, times_4, 10000));
__ movdbl(Operand(ebx, ecx, times_4, 10000), xmm1); __ movdbl(Operand(ebx, ecx, times_4, 10000), xmm1);
__ comisd(xmm0, xmm1); __ comisd(xmm0, xmm1);
// 128 bit move instructions.
__ movdqa(xmm0, Operand(ebx, ecx, times_4, 10000));
__ movdqa(Operand(ebx, ecx, times_4, 10000), xmm0);
__ movdqu(xmm0, Operand(ebx, ecx, times_4, 10000));
__ movdqu(Operand(ebx, ecx, times_4, 10000), xmm0);
} }
// cmov. // cmov.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment