Author: erik.co...@gmail.com Date: Mon Jun 29 02:32:06 2009 New Revision: 2292
Modified: branches/bleeding_edge/src/arm/assembler-arm.cc branches/bleeding_edge/src/arm/disasm-arm.cc branches/bleeding_edge/src/ia32/assembler-ia32.cc branches/bleeding_edge/src/ia32/assembler-ia32.h branches/bleeding_edge/src/x64/assembler-x64.cc branches/bleeding_edge/src/x64/assembler-x64.h branches/bleeding_edge/test/cctest/test-assembler-x64.cc Log: * Add missing imul instruction on Intel. * Fix incorrect signedness in disassembly of umull/mull on ARM. * Fix incorrect register order in disassembly of umull/mull. * Fix incorrect assembly of umull on ARM. * Remove retroactively obsoleted restriction on choice of registers in mul instructions on ARM. Review URL: http://codereview.chromium.org/150002 Modified: branches/bleeding_edge/src/arm/assembler-arm.cc ============================================================================== --- branches/bleeding_edge/src/arm/assembler-arm.cc (original) +++ branches/bleeding_edge/src/arm/assembler-arm.cc Mon Jun 29 02:32:06 2009 @@ -816,7 +816,6 @@ void Assembler::mla(Register dst, Register src1, Register src2, Register srcA, SBit s, Condition cond) { ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc)); - ASSERT(!dst.is(src1)); emit(cond | A | s | dst.code()*B16 | srcA.code()*B12 | src2.code()*B8 | B7 | B4 | src1.code()); } @@ -825,7 +824,6 @@ void Assembler::mul(Register dst, Register src1, Register src2, SBit s, Condition cond) { ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc)); - ASSERT(!dst.is(src1)); emit(cond | s | dst.code()*B16 | src2.code()*B8 | B7 | B4 | src1.code()); } @@ -837,7 +835,7 @@ SBit s, Condition cond) { ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); - ASSERT(!dstL.is(dstH) && !dstH.is(src1) && !src1.is(dstL)); + ASSERT(!dstL.is(dstH)); emit(cond | B23 | B22 | A | s | dstH.code()*B16 | dstL.code()*B12 | src2.code()*B8 | B7 | B4 | src1.code()); } @@ -850,7 +848,7 @@ SBit s, Condition cond) { ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); - ASSERT(!dstL.is(dstH) && !dstH.is(src1) && !src1.is(dstL)); + ASSERT(!dstL.is(dstH)); emit(cond | B23 | B22 | s | dstH.code()*B16 | dstL.code()*B12 | src2.code()*B8 | B7 | B4 | src1.code()); } @@ -863,7 +861,7 @@ SBit s, Condition cond) { ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); - ASSERT(!dstL.is(dstH) && !dstH.is(src1) && !src1.is(dstL)); + ASSERT(!dstL.is(dstH)); emit(cond | B23 | A | s | dstH.code()*B16 | dstL.code()*B12 | src2.code()*B8 | B7 | B4 | src1.code()); } @@ -876,8 +874,8 @@ SBit s, Condition cond) { ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); - ASSERT(!dstL.is(dstH) && !dstH.is(src1) && !src1.is(dstL)); - emit(cond | B23 | s | dstH.code()*B16 | dstL.code()*B12 | + ASSERT(!dstL.is(dstH)); + emit(cond | B23 | B22 | s | dstH.code()*B16 | dstL.code()*B12 | src2.code()*B8 | B7 | B4 | src1.code()); } Modified: branches/bleeding_edge/src/arm/disasm-arm.cc ============================================================================== --- branches/bleeding_edge/src/arm/disasm-arm.cc (original) +++ branches/bleeding_edge/src/arm/disasm-arm.cc Mon Jun 29 02:32:06 2009 @@ -438,7 +438,7 @@ return 6; } case 'u': { // 'u: signed or unsigned multiplies - if (instr->Bit(22) == 0) { + if (instr->Bit(22) == 1) { Print("u"); } else { Print("s"); @@ -499,7 +499,7 @@ Format(instr, "mla'cond's 'rd, 'rm, 'rs, 'rn"); } } else { - Format(instr, "'um'al'cond's 'rn, 'rd, 'rs, 'rm"); + Format(instr, "'um'al'cond's 'rn, 'rd, 'rm, 'rs"); } } else { Unknown(instr); // not used by V8 Modified: branches/bleeding_edge/src/ia32/assembler-ia32.cc ============================================================================== --- branches/bleeding_edge/src/ia32/assembler-ia32.cc (original) +++ branches/bleeding_edge/src/ia32/assembler-ia32.cc Mon Jun 29 02:32:06 2009 @@ -919,6 +919,14 @@ } +void Assembler::imul(Register reg) { + EnsureSpace ensure_space(this); + last_pc_ = pc_; + EMIT(0xF7); + EMIT(0xE8 | reg.code()); +} + + void Assembler::imul(Register dst, const Operand& src) { EnsureSpace ensure_space(this); last_pc_ = pc_; Modified: branches/bleeding_edge/src/ia32/assembler-ia32.h ============================================================================== --- branches/bleeding_edge/src/ia32/assembler-ia32.h (original) +++ branches/bleeding_edge/src/ia32/assembler-ia32.h Mon Jun 29 02:32:06 2009 @@ -544,15 +544,18 @@ void idiv(Register src); - void imul(Register dst, const Operand& src); - void imul(Register dst, Register src, int32_t imm32); + // Signed multiply instructions. + void imul(Register src); // edx:eax = eax * src. + void imul(Register dst, const Operand& src); // dst = dst * src. + void imul(Register dst, Register src, int32_t imm32); // dst = src * imm32. void inc(Register dst); void inc(const Operand& dst); void lea(Register dst, const Operand& src); - void mul(Register src); + // Unsigned multiply instruction. + void mul(Register src); // edx:eax = eax * reg. void neg(Register dst); Modified: branches/bleeding_edge/src/x64/assembler-x64.cc ============================================================================== --- branches/bleeding_edge/src/x64/assembler-x64.cc (original) +++ branches/bleeding_edge/src/x64/assembler-x64.cc Mon Jun 29 02:32:06 2009 @@ -750,6 +750,15 @@ } +void Assembler::imul(Register src) { + EnsureSpace ensure_space(this); + last_pc_ = pc_; + emit_rex_64(src); + emit(0xF7); + emit_modrm(0x5, src); +} + + void Assembler::imul(Register dst, Register src) { EnsureSpace ensure_space(this); last_pc_ = pc_; Modified: branches/bleeding_edge/src/x64/assembler-x64.h ============================================================================== --- branches/bleeding_edge/src/x64/assembler-x64.h (original) +++ branches/bleeding_edge/src/x64/assembler-x64.h Mon Jun 29 02:32:06 2009 @@ -605,12 +605,13 @@ // Divide rdx:rax by src. Quotient in rax, remainder in rdx. void idiv(Register src); - void imul(Register dst, Register src); - void imul(Register dst, const Operand& src); - // Performs the operation dst = src * imm. - void imul(Register dst, Register src, Immediate imm); + // Signed multiply instructions. + void imul(Register src); // rdx:rax = rax * src. + void imul(Register dst, Register src); // dst = dst * src. + void imul(Register dst, const Operand& src); // dst = dst * src. + void imul(Register dst, Register src, Immediate imm); // dst = src * imm. // Multiply 32 bit registers - void imull(Register dst, Register src); + void imull(Register dst, Register src); // dst = dst * src. void incq(Register dst); void incq(const Operand& dst); Modified: branches/bleeding_edge/test/cctest/test-assembler-x64.cc ============================================================================== --- branches/bleeding_edge/test/cctest/test-assembler-x64.cc (original) +++ branches/bleeding_edge/test/cctest/test-assembler-x64.cc Mon Jun 29 02:32:06 2009 @@ -44,6 +44,7 @@ using v8::internal::rax; using v8::internal::rsi; using v8::internal::rdi; +using v8::internal::rdx; using v8::internal::rbp; using v8::internal::rsp; using v8::internal::FUNCTION_CAST; @@ -63,8 +64,8 @@ // with GCC. A different convention is used on 64-bit windows. typedef int (*F0)(); -typedef int (*F1)(int x); -typedef int (*F2)(int x, int y); +typedef int (*F1)(int64_t x); +typedef int (*F2)(int64_t x, int64_t y); #define __ assm. @@ -130,7 +131,7 @@ CHECK(buffer); Assembler assm(buffer, actual_size); - // Assemble a simple function that copies argument 2 and returns it. + // Assemble a simple function that adds arguments returning the sum. __ movq(rax, rsi); __ addq(rax, rdi); __ ret(0); @@ -140,6 +141,33 @@ // Call the function from C++. int result = FUNCTION_CAST<F2>(buffer)(3, 2); CHECK_EQ(5, result); +} + +TEST(AssemblerX64ImulOperation) { + // Allocate an executable page of memory. + size_t actual_size; + byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, + &actual_size, + true)); + CHECK(buffer); + Assembler assm(buffer, actual_size); + + // Assemble a simple function that multiplies arguments returning the high + // word. + __ movq(rax, rsi); + __ imul(rdi); + __ movq(rax, rdx); + __ ret(0); + + CodeDesc desc; + assm.GetCode(&desc); + // Call the function from C++. + int result = FUNCTION_CAST<F2>(buffer)(3, 2); + CHECK_EQ(0, result); + result = FUNCTION_CAST<F2>(buffer)(0x100000000l, 0x100000000l); + CHECK_EQ(1, result); + result = FUNCTION_CAST<F2>(buffer)(-0x100000000l, 0x100000000l); + CHECK_EQ(-1, result); } TEST(AssemblerX64MemoryOperands) { --~--~---------~--~----~------------~-------~--~----~ v8-dev mailing list v8-dev@googlegroups.com http://groups.google.com/group/v8-dev -~----------~----~----~----~------~----~------~--~---