From 658ca2f174f494ed63d60dcec43d0409600fb2c9 Mon Sep 17 00:00:00 2001 From: "sgjesse@chromium.org" Date: Mon, 11 Jan 2010 15:19:53 +0000 Subject: [PATCH] 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 --- src/ia32/assembler-ia32.cc | 16 ++---- src/ia32/assembler-ia32.h | 3 -- src/ia32/codegen-ia32.cc | 41 ++++++++------- src/ia32/codegen-ia32.h | 9 ++-- src/ia32/disasm-ia32.cc | 92 +++++++++++++++++++-------------- test/cctest/test-disasm-ia32.cc | 13 ++++- 6 files changed, 93 insertions(+), 81 deletions(-) diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc index c6f4c1daa0..0e9ffeaab8 100644 --- a/src/ia32/assembler-ia32.cc +++ b/src/ia32/assembler-ia32.cc @@ -575,6 +575,7 @@ void Assembler::leave() { void Assembler::mov_b(Register dst, const Operand& src) { + ASSERT(dst.code() < 4); EnsureSpace ensure_space(this); last_pc_ = pc_; EMIT(0x8A); @@ -592,6 +593,7 @@ void Assembler::mov_b(const Operand& dst, int8_t imm8) { void Assembler::mov_b(const Operand& dst, Register src) { + ASSERT(src.code() < 4); EnsureSpace ensure_space(this); last_pc_ = pc_; EMIT(0x88); @@ -1208,6 +1210,7 @@ void Assembler::sub(Register dst, const Operand& src) { void Assembler::subb(Register dst, const Operand& src) { + ASSERT(dst.code() < 4); EnsureSpace ensure_space(this); last_pc_ = pc_; EMIT(0x2A); @@ -1600,21 +1603,8 @@ void Assembler::j(Condition cc, Handle 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 - void Assembler::fld(int i) { EnsureSpace ensure_space(this); last_pc_ = pc_; diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h index 738b8b65a9..f35abd5756 100644 --- a/src/ia32/assembler-ia32.h +++ b/src/ia32/assembler-ia32.h @@ -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, Handle code, Hint hint = no_hint); - // Loop instruction using ecx as counter. - void loope(Label* L); - // Floating-point operations void fld(int i); diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc index 875099f263..ccea82b1df 100644 --- a/src/ia32/codegen-ia32.cc +++ b/src/ia32/codegen-ia32.cc @@ -9637,48 +9637,51 @@ void SubStringStub::Generate(MacroAssembler* masm) { void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, Register left, Register right, - Register counter, Register scratch1, - Register scratch2) { - ASSERT(counter.is(ecx)); + Register scratch2, + Register scratch3) { Label compare_lengths, compare_lengths_1; // Find minimum length. If either length is zero just compare lengths. - __ mov(counter, FieldOperand(left, String::kLengthOffset)); - __ test(counter, Operand(counter)); - __ j(zero, &compare_lengths_1); - __ mov(scratch1, FieldOperand(right, String::kLengthOffset)); + __ mov(scratch1, FieldOperand(left, String::kLengthOffset)); __ test(scratch1, Operand(scratch1)); __ 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)) { CpuFeatures::Scope use_cmov(CMOV); - __ cmov(greater, counter, Operand(scratch1)); + __ cmov(greater, scratch1, Operand(scratch2)); } else { Label l; __ j(less, &l); - __ mov(counter, scratch1); + __ mov(scratch1, scratch2); __ bind(&l); } Label result_greater, result_less; Label loop; // Compare next character. - __ mov(scratch2, Immediate(-1)); // Index into strings. + __ mov(scratch3, Immediate(-1)); // Index into strings. __ bind(&loop); // Compare characters. - __ add(Operand(scratch2), Immediate(1)); - __ mov_b(scratch1, Operand(left, - scratch2, + Label character_compare_done; + __ add(Operand(scratch3), Immediate(1)); + __ mov_b(scratch2, Operand(left, + scratch3, times_1, SeqAsciiString::kHeaderSize - kHeapObjectTag)); - __ subb(scratch1, Operand(right, - scratch2, + __ subb(scratch2, Operand(right, + scratch3, times_1, 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 // compare is the result. + __ bind(&character_compare_done); __ j(equal, &compare_lengths); __ j(less, &result_less); __ jmp(&result_greater); @@ -9686,9 +9689,9 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, // Compare lengths. Label result_not_equal; __ bind(&compare_lengths); - __ mov(counter, FieldOperand(left, String::kLengthOffset)); + __ mov(scratch1, FieldOperand(left, String::kLengthOffset)); __ bind(&compare_lengths_1); - __ sub(counter, FieldOperand(right, String::kLengthOffset)); + __ sub(scratch1, FieldOperand(right, String::kLengthOffset)); __ j(not_zero, &result_not_equal); // Result is EQUAL. diff --git a/src/ia32/codegen-ia32.h b/src/ia32/codegen-ia32.h index 2e98d0564e..000222ff1c 100644 --- a/src/ia32/codegen-ia32.h +++ b/src/ia32/codegen-ia32.h @@ -813,16 +813,13 @@ class StringCompareStub: public StringStubBase { } // 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 - // constraints on the registers that can be passed. - // counter must be ecx - // scratch1 most be one of eax, ebx or edx + // arguments from the stack. static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm, Register left, Register right, - Register counter, Register scratch1, - Register scratch2); + Register scratch2, + Register scratch3); private: Major MajorKey() { return StringCompare; } diff --git a/src/ia32/disasm-ia32.cc b/src/ia32/disasm-ia32.cc index 41d8dc4f3a..581cdc0754 100644 --- a/src/ia32/disasm-ia32.cc +++ b/src/ia32/disasm-ia32.cc @@ -117,11 +117,6 @@ static const char* jump_conditional_mnem[] = { }; -static const char* loop_mnem[] = { - "loopne", "loope", "loop" -}; - - static const char* set_conditional_mnem[] = { /*0*/ "seto", "setno", "setc", "setnc", /*4*/ "setz", "setnz", "setna", "seta", @@ -143,7 +138,6 @@ enum InstructionType { ZERO_OPERANDS_INSTR, TWO_OPERANDS_INSTR, JUMP_CONDITIONAL_SHORT_INSTR, - LOOP_INSTR, REGISTER_INSTR, MOVE_REG_INSTR, CALL_JUMP_INSTR, @@ -173,7 +167,6 @@ class InstructionTable { byte end, const char* mnem); void AddJumpConditionalShort(); - void AddLoop(); }; @@ -198,7 +191,6 @@ void InstructionTable::Init() { CopyTable(call_jump_instr, CALL_JUMP_INSTR); CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR); AddJumpConditionalShort(); - AddLoop(); SetTableRange(REGISTER_INSTR, 0x40, 0x47, "inc"); SetTableRange(REGISTER_INSTR, 0x48, 0x4F, "dec"); SetTableRange(REGISTER_INSTR, 0x50, 0x57, "push"); @@ -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; @@ -348,7 +330,6 @@ class DisassemblerIA32 { int JumpShort(byte* data); int JumpConditional(byte* data, const char* comment); int JumpConditionalShort(byte* data, const char* comment); - int Loop(byte* data); int SetCC(byte* data); int CMov(byte* data); int FPUInstruction(byte* data); @@ -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(b) + 2; - const char* mnem = loop_mnem[cond]; - AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); - return 2; -} - - // Returns number of bytes used, including *data. int DisassemblerIA32::SetCC(byte* data) { ASSERT_EQ(0x0F, *data); @@ -885,10 +855,6 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector out_buffer, data += JumpConditionalShort(data, branch_hint); break; - case LOOP_INSTR: - data += Loop(data); - break; - case REGISTER_INSTR: AppendToBuffer("%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07)); data++; @@ -1042,7 +1008,16 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector out_buffer, case 0x80: { data++; - AppendToBuffer("%s ", "cmpb"); + int mod, regop, rm; + get_modrm(*data, &mod, ®op, &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); int32_t imm = *data; AppendToBuffer(",0x%x", imm); @@ -1092,6 +1067,19 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector out_buffer, NameOfXMMRegister(regop), NameOfXMMRegister(rm)); data++; + } else if (*data == 0x6F) { + data++; + int mod, regop, rm; + get_modrm(*data, &mod, ®op, &rm); + AppendToBuffer("movdqa %s,", NameOfXMMRegister(regop)); + data += PrintRightOperand(data); + } else if (*data == 0x7F) { + AppendToBuffer("movdqa "); + data++; + int mod, regop, rm; + get_modrm(*data, &mod, ®op, &rm); + data += PrintRightOperand(data); + AppendToBuffer(",%s", NameOfXMMRegister(regop)); } else { UnimplementedInstruction(); } @@ -1128,6 +1116,11 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector out_buffer, data += 2; break; + case 0x2C: + AppendToBuffer("subb eax,0x%x", *reinterpret_cast(data+1)); + data += 2; + break; + case 0xA9: AppendToBuffer("test eax,0x%x", *reinterpret_cast(data+1)); data += 5; @@ -1198,9 +1191,29 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector out_buffer, break; case 0xF3: - if (*(data+1) == 0x0F && *(data+2) == 0x2C) { - data += 3; - data += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, data); + if (*(data+1) == 0x0F) { + if (*(data+2) == 0x2C) { + 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, ®op, &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, ®op, &rm); + data += PrintRightOperand(data); + AppendToBuffer(",%s", NameOfXMMRegister(regop)); + } else { + UnimplementedInstruction(); + } + } else if (*(data+1) == 0xA5) { + data += 2; + AppendToBuffer("rep_movs"); } else { UnimplementedInstruction(); } @@ -1220,6 +1233,9 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector out_buffer, } int instr_len = data - instr; + if (instr_len == 0) { + printf("%02x", *data); + } ASSERT(instr_len > 0); // Ensure progress. int outp = 0; diff --git a/test/cctest/test-disasm-ia32.cc b/test/cctest/test-disasm-ia32.cc index b8b3364ac4..ba4eec26ac 100644 --- a/test/cctest/test-disasm-ia32.cc +++ b/test/cctest/test-disasm-ia32.cc @@ -57,7 +57,7 @@ static void DummyStaticFunction(Object* result) { TEST(DisasmIa320) { InitializeVM(); v8::HandleScope scope; - v8::internal::byte buffer[1024]; + v8::internal::byte buffer[2048]; Assembler assm(buffer, sizeof buffer); DummyStaticFunction(NULL); // just bloody use it (DELETE; debugging) @@ -223,13 +223,16 @@ TEST(DisasmIa320) { __ sub(Operand(ebx), 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); __ imul(edx, ecx, 12); __ imul(edx, ecx, 1000); - + __ rep_movs(); __ sub(edx, Operand(ebx, ecx, times_4, 10000)); __ sub(edx, Operand(ebx)); @@ -365,6 +368,12 @@ TEST(DisasmIa320) { __ movdbl(xmm1, Operand(ebx, ecx, times_4, 10000)); __ movdbl(Operand(ebx, ecx, times_4, 10000), 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.