From 4a30e3f58e090dc278486f8427f34c1e76d1ce67 Mon Sep 17 00:00:00 2001 From: "erik.corry@gmail.com" Date: Mon, 29 Jun 2009 09:32:06 +0000 Subject: [PATCH] * 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 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2292 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/assembler-arm.cc | 12 +++++------- src/arm/disasm-arm.cc | 4 ++-- src/ia32/assembler-ia32.cc | 8 ++++++++ src/ia32/assembler-ia32.h | 9 ++++++--- src/x64/assembler-x64.cc | 9 +++++++++ src/x64/assembler-x64.h | 11 ++++++----- test/cctest/test-assembler-x64.cc | 34 +++++++++++++++++++++++++++++++--- 7 files changed, 67 insertions(+), 20 deletions(-) diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc index 6ec8f46..20aa39c 100644 --- a/src/arm/assembler-arm.cc +++ b/src/arm/assembler-arm.cc @@ -816,7 +816,6 @@ void Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) { 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::mla(Register dst, Register src1, Register src2, Register srcA, 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 @@ void Assembler::smlal(Register dstL, 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 @@ void Assembler::smull(Register dstL, 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 @@ void Assembler::umlal(Register dstL, 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 @@ void Assembler::umull(Register dstL, 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()); } diff --git a/src/arm/disasm-arm.cc b/src/arm/disasm-arm.cc index 8083ce3..908c45a 100644 --- a/src/arm/disasm-arm.cc +++ b/src/arm/disasm-arm.cc @@ -438,7 +438,7 @@ int Decoder::FormatOption(Instr* instr, const char* format) { 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 @@ void Decoder::DecodeType01(Instr* instr) { 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 diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc index 5968610..f3cb854 100644 --- a/src/ia32/assembler-ia32.cc +++ b/src/ia32/assembler-ia32.cc @@ -919,6 +919,14 @@ void Assembler::idiv(Register src) { } +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_; diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h index 92c390c..70b510e 100644 --- a/src/ia32/assembler-ia32.h +++ b/src/ia32/assembler-ia32.h @@ -544,15 +544,18 @@ class Assembler : public Malloced { 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); diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc index 7da6a8f..ced7577 100644 --- a/src/x64/assembler-x64.cc +++ b/src/x64/assembler-x64.cc @@ -750,6 +750,15 @@ void Assembler::idiv(Register src) { } +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_; diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h index 0d98e5f..4e1eeff 100644 --- a/src/x64/assembler-x64.h +++ b/src/x64/assembler-x64.h @@ -605,12 +605,13 @@ class Assembler : public Malloced { // 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); diff --git a/test/cctest/test-assembler-x64.cc b/test/cctest/test-assembler-x64.cc index 9e95f32..cd750c5 100644 --- a/test/cctest/test-assembler-x64.cc +++ b/test/cctest/test-assembler-x64.cc @@ -44,6 +44,7 @@ using v8::internal::Label; 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 @@ using v8::internal::greater; // 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 @@ TEST(AssemblerX64ArithmeticOperations) { 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); @@ -142,6 +143,33 @@ TEST(AssemblerX64ArithmeticOperations) { CHECK_EQ(5, result); } +TEST(AssemblerX64ImulOperation) { + // Allocate an executable page of memory. + size_t actual_size; + byte* buffer = static_cast(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(buffer)(3, 2); + CHECK_EQ(0, result); + result = FUNCTION_CAST(buffer)(0x100000000l, 0x100000000l); + CHECK_EQ(1, result); + result = FUNCTION_CAST(buffer)(-0x100000000l, 0x100000000l); + CHECK_EQ(-1, result); +} + TEST(AssemblerX64MemoryOperands) { // Allocate an executable page of memory. size_t actual_size; -- 2.7.4