Add missing instructions to the IA-32 disasembler
authorsgjesse@chromium.org <sgjesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 11 Jan 2010 15:19:53 +0000 (15:19 +0000)
committersgjesse@chromium.org <sgjesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 11 Jan 2010 15:19:53 +0000 (15:19 +0000)
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
src/ia32/assembler-ia32.h
src/ia32/codegen-ia32.cc
src/ia32/codegen-ia32.h
src/ia32/disasm-ia32.cc
test/cctest/test-disasm-ia32.cc

index c6f4c1d..0e9ffea 100644 (file)
@@ -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> 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_;
index 738b8b6..f35abd5 100644 (file)
@@ -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> code, Hint hint = no_hint);
 
-  // Loop instruction using ecx as counter.
-  void loope(Label* L);
-
   // Floating-point operations
   void fld(int i);
 
index 875099f..ccea82b 100644 (file)
@@ -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.
index 2e98d05..000222f 100644 (file)
@@ -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; }
index 41d8dc4..581cdc0 100644 (file)
@@ -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);
@@ -637,17 +618,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.
 int DisassemblerIA32::SetCC(byte* data) {
   ASSERT_EQ(0x0F, *data);
   byte cond = *(data+1) & 0x0F;
@@ -885,10 +855,6 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> 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<char> out_buffer,
 
       case 0x80:
         { 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);
           int32_t imm = *data;
           AppendToBuffer(",0x%x", imm);
@@ -1092,6 +1067,19 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
                            NameOfXMMRegister(regop),
                            NameOfXMMRegister(rm));
             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 {
             UnimplementedInstruction();
           }
@@ -1128,6 +1116,11 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
         data += 2;
         break;
 
+      case 0x2C:
+        AppendToBuffer("subb eax,0x%x", *reinterpret_cast<uint8_t*>(data+1));
+        data += 2;
+        break;
+
       case 0xA9:
         AppendToBuffer("test eax,0x%x", *reinterpret_cast<int32_t*>(data+1));
         data += 5;
@@ -1198,9 +1191,29 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> 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, &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 {
           UnimplementedInstruction();
         }
@@ -1220,6 +1233,9 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
   }
 
   int instr_len = data - instr;
+  if (instr_len == 0) {
+    printf("%02x", *data);
+  }
   ASSERT(instr_len > 0);  // Ensure progress.
 
   int outp = 0;
index b8b3364..ba4eec2 100644 (file)
@@ -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.