Commit a72e3525 authored by haitao.feng@intel.com's avatar haitao.feng@intel.com

Refactor the arithmetic instructions for x64

R=verwaest@chromium.org

Review URL: https://codereview.chromium.org/214753002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20329 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent dae7ecbf
...@@ -467,24 +467,30 @@ void Assembler::emit_operand(int code, const Operand& adr) { ...@@ -467,24 +467,30 @@ void Assembler::emit_operand(int code, const Operand& adr) {
// Assembler Instruction implementations. // Assembler Instruction implementations.
void Assembler::arithmetic_op(byte opcode, Register reg, const Operand& op) { void Assembler::arithmetic_op(byte opcode,
Register reg,
const Operand& op,
int size) {
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
emit_rex_64(reg, op); emit_rex(reg, op, size);
emit(opcode); emit(opcode);
emit_operand(reg, op); emit_operand(reg, op);
} }
void Assembler::arithmetic_op(byte opcode, Register reg, Register rm_reg) { void Assembler::arithmetic_op(byte opcode,
Register reg,
Register rm_reg,
int size) {
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
ASSERT((opcode & 0xC6) == 2); ASSERT((opcode & 0xC6) == 2);
if (rm_reg.low_bits() == 4) { // Forces SIB byte. if (rm_reg.low_bits() == 4) { // Forces SIB byte.
// Swap reg and rm_reg and change opcode operand order. // Swap reg and rm_reg and change opcode operand order.
emit_rex_64(rm_reg, reg); emit_rex(rm_reg, reg, size);
emit(opcode ^ 0x02); emit(opcode ^ 0x02);
emit_modrm(rm_reg, reg); emit_modrm(rm_reg, reg);
} else { } else {
emit_rex_64(reg, rm_reg); emit_rex(reg, rm_reg, size);
emit(opcode); emit(opcode);
emit_modrm(reg, rm_reg); emit_modrm(reg, rm_reg);
} }
...@@ -520,37 +526,45 @@ void Assembler::arithmetic_op_16(byte opcode, ...@@ -520,37 +526,45 @@ void Assembler::arithmetic_op_16(byte opcode,
} }
void Assembler::arithmetic_op_32(byte opcode, Register reg, Register rm_reg) { void Assembler::arithmetic_op_8(byte opcode, Register reg, const Operand& op) {
EnsureSpace ensure_space(this);
if (!reg.is_byte_register()) {
// Register is not one of al, bl, cl, dl. Its encoding needs REX.
emit_rex_32(reg);
}
emit(opcode);
emit_operand(reg, op);
}
void Assembler::arithmetic_op_8(byte opcode, Register reg, Register rm_reg) {
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
ASSERT((opcode & 0xC6) == 2); ASSERT((opcode & 0xC6) == 2);
if (rm_reg.low_bits() == 4) { // Forces SIB byte. if (rm_reg.low_bits() == 4) { // Forces SIB byte.
// Swap reg and rm_reg and change opcode operand order. // Swap reg and rm_reg and change opcode operand order.
emit_optional_rex_32(rm_reg, reg); if (!rm_reg.is_byte_register() || !reg.is_byte_register()) {
emit(opcode ^ 0x02); // E.g. 0x03 -> 0x01 for ADD. // Register is not one of al, bl, cl, dl. Its encoding needs REX.
emit_rex_32(rm_reg, reg);
}
emit(opcode ^ 0x02);
emit_modrm(rm_reg, reg); emit_modrm(rm_reg, reg);
} else { } else {
emit_optional_rex_32(reg, rm_reg); if (!reg.is_byte_register() || !rm_reg.is_byte_register()) {
// Register is not one of al, bl, cl, dl. Its encoding needs REX.
emit_rex_32(reg, rm_reg);
}
emit(opcode); emit(opcode);
emit_modrm(reg, rm_reg); emit_modrm(reg, rm_reg);
} }
} }
void Assembler::arithmetic_op_32(byte opcode,
Register reg,
const Operand& rm_reg) {
EnsureSpace ensure_space(this);
emit_optional_rex_32(reg, rm_reg);
emit(opcode);
emit_operand(reg, rm_reg);
}
void Assembler::immediate_arithmetic_op(byte subcode, void Assembler::immediate_arithmetic_op(byte subcode,
Register dst, Register dst,
Immediate src) { Immediate src,
int size) {
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
emit_rex_64(dst); emit_rex(dst, size);
if (is_int8(src.value_)) { if (is_int8(src.value_)) {
emit(0x83); emit(0x83);
emit_modrm(subcode, dst); emit_modrm(subcode, dst);
...@@ -567,9 +581,10 @@ void Assembler::immediate_arithmetic_op(byte subcode, ...@@ -567,9 +581,10 @@ void Assembler::immediate_arithmetic_op(byte subcode,
void Assembler::immediate_arithmetic_op(byte subcode, void Assembler::immediate_arithmetic_op(byte subcode,
const Operand& dst, const Operand& dst,
Immediate src) { Immediate src,
int size) {
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
emit_rex_64(dst); emit_rex(dst, size);
if (is_int8(src.value_)) { if (is_int8(src.value_)) {
emit(0x83); emit(0x83);
emit_operand(subcode, dst); emit_operand(subcode, dst);
...@@ -621,43 +636,6 @@ void Assembler::immediate_arithmetic_op_16(byte subcode, ...@@ -621,43 +636,6 @@ void Assembler::immediate_arithmetic_op_16(byte subcode,
} }
void Assembler::immediate_arithmetic_op_32(byte subcode,
Register dst,
Immediate src) {
EnsureSpace ensure_space(this);
emit_optional_rex_32(dst);
if (is_int8(src.value_)) {
emit(0x83);
emit_modrm(subcode, dst);
emit(src.value_);
} else if (dst.is(rax)) {
emit(0x05 | (subcode << 3));
emitl(src.value_);
} else {
emit(0x81);
emit_modrm(subcode, dst);
emitl(src.value_);
}
}
void Assembler::immediate_arithmetic_op_32(byte subcode,
const Operand& dst,
Immediate src) {
EnsureSpace ensure_space(this);
emit_optional_rex_32(dst);
if (is_int8(src.value_)) {
emit(0x83);
emit_operand(subcode, dst);
emit(src.value_);
} else {
emit(0x81);
emit_operand(subcode, dst);
emitl(src.value_);
}
}
void Assembler::immediate_arithmetic_op_8(byte subcode, void Assembler::immediate_arithmetic_op_8(byte subcode,
const Operand& dst, const Operand& dst,
Immediate src) { Immediate src) {
...@@ -675,8 +653,8 @@ void Assembler::immediate_arithmetic_op_8(byte subcode, ...@@ -675,8 +653,8 @@ void Assembler::immediate_arithmetic_op_8(byte subcode,
Immediate src) { Immediate src) {
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
if (!dst.is_byte_register()) { if (!dst.is_byte_register()) {
// Use 64-bit mode byte registers. // Register is not one of al, bl, cl, dl. Its encoding needs REX.
emit_rex_64(dst); emit_rex_32(dst);
} }
ASSERT(is_int8(src.value_) || is_uint8(src.value_)); ASSERT(is_int8(src.value_) || is_uint8(src.value_));
emit(0x80); emit(0x80);
......
This diff is collapsed.
...@@ -141,6 +141,37 @@ TEST(AssemblerX64ArithmeticOperations) { ...@@ -141,6 +141,37 @@ TEST(AssemblerX64ArithmeticOperations) {
} }
TEST(AssemblerX64CmpbOperation) {
// 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(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
// Assemble a function that compare argument byte returing 1 if equal else 0.
// On Windows, it compares rcx with rdx which does not require REX prefix;
// on Linux, it compares rdi with rsi which requires REX prefix.
Label done;
__ movq(rax, Immediate(1));
__ cmpb(arg1, arg2);
__ j(equal, &done);
__ movq(rax, Immediate(0));
__ bind(&done);
__ ret(0);
CodeDesc desc;
assm.GetCode(&desc);
// Call the function from C++.
int result = FUNCTION_CAST<F2>(buffer)(0x1002, 0x2002);
CHECK_EQ(1, result);
result = FUNCTION_CAST<F2>(buffer)(0x1002, 0x2003);
CHECK_EQ(0, result);
}
TEST(AssemblerX64ImulOperation) { TEST(AssemblerX64ImulOperation) {
// Allocate an executable page of memory. // Allocate an executable page of memory.
size_t actual_size; 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