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() {
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_;
......
......@@ -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);
......
......@@ -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.
......
......@@ -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; }
......
......@@ -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<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);
......@@ -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;
......
......@@ -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.
......
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