Commit 4a30e3f5 authored by erik.corry@gmail.com's avatar erik.corry@gmail.com

* 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
parent a1622491
......@@ -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());
}
......
......@@ -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
......
......@@ -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_;
......
......@@ -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);
......
......@@ -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_;
......
......@@ -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);
......
......@@ -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<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) {
// Allocate an executable page of memory.
size_t actual_size;
......
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