Revision: 20329
Author: [email protected]
Date: Fri Mar 28 11:13:14 2014 UTC
Log: Refactor the arithmetic instructions for x64
[email protected]
Review URL: https://codereview.chromium.org/214753002
http://code.google.com/p/v8/source/detail?r=20329
Modified:
/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
=======================================
--- /branches/bleeding_edge/src/x64/assembler-x64.cc Fri Mar 28 04:55:00
2014 UTC
+++ /branches/bleeding_edge/src/x64/assembler-x64.cc Fri Mar 28 11:13:14
2014 UTC
@@ -467,24 +467,30 @@
// 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);
- emit_rex_64(reg, op);
+ emit_rex(reg, op, size);
emit(opcode);
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);
ASSERT((opcode & 0xC6) == 2);
if (rm_reg.low_bits() == 4) { // Forces SIB byte.
// 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_modrm(rm_reg, reg);
} else {
- emit_rex_64(reg, rm_reg);
+ emit_rex(reg, rm_reg, size);
emit(opcode);
emit_modrm(reg, rm_reg);
}
@@ -520,37 +526,45 @@
}
-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);
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.
- emit_optional_rex_32(rm_reg, reg);
- emit(opcode ^ 0x02); // E.g. 0x03 -> 0x01 for ADD.
+ if (!rm_reg.is_byte_register() || !reg.is_byte_register()) {
+ // 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);
} 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_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,
Register dst,
- Immediate src) {
+ Immediate src,
+ int size) {
EnsureSpace ensure_space(this);
- emit_rex_64(dst);
+ emit_rex(dst, size);
if (is_int8(src.value_)) {
emit(0x83);
emit_modrm(subcode, dst);
@@ -567,9 +581,10 @@
void Assembler::immediate_arithmetic_op(byte subcode,
const Operand& dst,
- Immediate src) {
+ Immediate src,
+ int size) {
EnsureSpace ensure_space(this);
- emit_rex_64(dst);
+ emit_rex(dst, size);
if (is_int8(src.value_)) {
emit(0x83);
emit_operand(subcode, dst);
@@ -619,43 +634,6 @@
emitw(src.value_);
}
}
-
-
-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,
@@ -675,8 +653,8 @@
Immediate src) {
EnsureSpace ensure_space(this);
if (!dst.is_byte_register()) {
- // Use 64-bit mode byte registers.
- emit_rex_64(dst);
+ // Register is not one of al, bl, cl, dl. Its encoding needs REX.
+ emit_rex_32(dst);
}
ASSERT(is_int8(src.value_) || is_uint8(src.value_));
emit(0x80);
=======================================
--- /branches/bleeding_edge/src/x64/assembler-x64.h Fri Mar 28 04:55:00
2014 UTC
+++ /branches/bleeding_edge/src/x64/assembler-x64.h Fri Mar 28 11:13:14
2014 UTC
@@ -692,6 +692,8 @@
// - Instructions on 64-bit (quadword) operands/registers use 'q'.
// - Instructions on operands/registers with pointer size use 'p'.
+ STATIC_ASSERT(kPointerSize == kInt64Size || kPointerSize == kInt32Size);
+
#define DECLARE_INSTRUCTION(instruction) \
template<class P1> \
void instruction##p(P1 p1) { \
@@ -818,15 +820,15 @@
void cmpb_al(Immediate src);
void cmpb(Register dst, Register src) {
- arithmetic_op(0x3A, dst, src);
+ arithmetic_op_8(0x3A, dst, src);
}
void cmpb(Register dst, const Operand& src) {
- arithmetic_op(0x3A, dst, src);
+ arithmetic_op_8(0x3A, dst, src);
}
void cmpb(const Operand& dst, Register src) {
- arithmetic_op(0x38, src, dst);
+ arithmetic_op_8(0x38, src, dst);
}
void cmpb(const Operand& dst, Immediate src) {
@@ -1382,14 +1384,16 @@
// AND, OR, XOR, or CMP. The encodings of these operations are all
// similar, differing just in the opcode or in the reg field of the
// ModR/M byte.
+ void arithmetic_op_8(byte opcode, Register reg, Register rm_reg);
+ void arithmetic_op_8(byte opcode, Register reg, const Operand& rm_reg);
void arithmetic_op_16(byte opcode, Register reg, Register rm_reg);
void arithmetic_op_16(byte opcode, Register reg, const Operand& rm_reg);
- void arithmetic_op_32(byte opcode, Register reg, Register rm_reg);
- void arithmetic_op_32(byte opcode, Register reg, const Operand& rm_reg);
- void arithmetic_op(byte opcode, Register reg, Register rm_reg);
- void arithmetic_op(byte opcode, Register reg, const Operand& rm_reg);
- void immediate_arithmetic_op(byte subcode, Register dst, Immediate src);
- void immediate_arithmetic_op(byte subcode, const Operand& dst, Immediate
src);
+ // Operate on operands/registers with pointer size, 32-bit or 64-bit
size.
+ void arithmetic_op(byte opcode, Register reg, Register rm_reg, int size);
+ void arithmetic_op(byte opcode,
+ Register reg,
+ const Operand& rm_reg,
+ int size);
// Operate on a byte in memory or register.
void immediate_arithmetic_op_8(byte subcode,
Register dst,
@@ -1404,13 +1408,15 @@
void immediate_arithmetic_op_16(byte subcode,
const Operand& dst,
Immediate src);
- // Operate on a 32-bit word in memory or register.
- void immediate_arithmetic_op_32(byte subcode,
- Register dst,
- Immediate src);
- void immediate_arithmetic_op_32(byte subcode,
- const Operand& dst,
- Immediate src);
+ // Operate on operands/registers with pointer size, 32-bit or 64-bit
size.
+ void immediate_arithmetic_op(byte subcode,
+ Register dst,
+ Immediate src,
+ int size);
+ void immediate_arithmetic_op(byte subcode,
+ const Operand& dst,
+ Immediate src,
+ int size);
// Emit machine code for a shift operation.
void shift(Register dst, Immediate shift_amount, int subcode, int size);
@@ -1428,138 +1434,63 @@
// Arithmetics
void emit_add(Register dst, Register src, int size) {
- if (size == kInt64Size) {
- arithmetic_op(0x03, dst, src);
- } else {
- ASSERT(size == kInt32Size);
- arithmetic_op_32(0x03, dst, src);
- }
+ arithmetic_op(0x03, dst, src, size);
}
void emit_add(Register dst, Immediate src, int size) {
- if (size == kInt64Size) {
- immediate_arithmetic_op(0x0, dst, src);
- } else {
- ASSERT(size == kInt32Size);
- immediate_arithmetic_op_32(0x0, dst, src);
- }
+ immediate_arithmetic_op(0x0, dst, src, size);
}
void emit_add(Register dst, const Operand& src, int size) {
- if (size == kInt64Size) {
- arithmetic_op(0x03, dst, src);
- } else {
- ASSERT(size == kInt32Size);
- arithmetic_op_32(0x03, dst, src);
- }
+ arithmetic_op(0x03, dst, src, size);
}
void emit_add(const Operand& dst, Register src, int size) {
- if (size == kInt64Size) {
- arithmetic_op(0x1, src, dst);
- } else {
- ASSERT(size == kInt32Size);
- arithmetic_op_32(0x1, src, dst);
- }
+ arithmetic_op(0x1, src, dst, size);
}
void emit_add(const Operand& dst, Immediate src, int size) {
- if (size == kInt64Size) {
- immediate_arithmetic_op(0x0, dst, src);
- } else {
- ASSERT(size == kInt32Size);
- immediate_arithmetic_op_32(0x0, dst, src);
- }
+ immediate_arithmetic_op(0x0, dst, src, size);
}
void emit_and(Register dst, Register src, int size) {
- if (size == kInt64Size) {
- arithmetic_op(0x23, dst, src);
- } else {
- ASSERT(size == kInt32Size);
- arithmetic_op_32(0x23, dst, src);
- }
+ arithmetic_op(0x23, dst, src, size);
}
void emit_and(Register dst, const Operand& src, int size) {
- if (size == kInt64Size) {
- arithmetic_op(0x23, dst, src);
- } else {
- ASSERT(size == kInt32Size);
- arithmetic_op_32(0x23, dst, src);
- }
+ arithmetic_op(0x23, dst, src, size);
}
void emit_and(const Operand& dst, Register src, int size) {
- if (size == kInt64Size) {
- arithmetic_op(0x21, src, dst);
- } else {
- ASSERT(size == kInt32Size);
- arithmetic_op_32(0x21, src, dst);
- }
+ arithmetic_op(0x21, src, dst, size);
}
void emit_and(Register dst, Immediate src, int size) {
- if (size == kInt64Size) {
- immediate_arithmetic_op(0x4, dst, src);
- } else {
- ASSERT(size == kInt32Size);
- immediate_arithmetic_op_32(0x4, dst, src);
- }
+ immediate_arithmetic_op(0x4, dst, src, size);
}
void emit_and(const Operand& dst, Immediate src, int size) {
- if (size == kInt64Size) {
- immediate_arithmetic_op(0x4, dst, src);
- } else {
- ASSERT(size == kInt32Size);
- immediate_arithmetic_op_32(0x4, dst, src);
- }
+ immediate_arithmetic_op(0x4, dst, src, size);
}
void emit_cmp(Register dst, Register src, int size) {
- if (size == kInt64Size) {
- arithmetic_op(0x3B, dst, src);
- } else {
- ASSERT(size == kInt32Size);
- arithmetic_op_32(0x3B, dst, src);
- }
+ arithmetic_op(0x3B, dst, src, size);
}
void emit_cmp(Register dst, const Operand& src, int size) {
- if (size == kInt64Size) {
- arithmetic_op(0x3B, dst, src);
- } else {
- ASSERT(size == kInt32Size);
- arithmetic_op_32(0x3B, dst, src);
- }
+ arithmetic_op(0x3B, dst, src, size);
}
void emit_cmp(const Operand& dst, Register src, int size) {
- if (size == kInt64Size) {
- arithmetic_op(0x39, src, dst);
- } else {
- ASSERT(size == kInt32Size);
- arithmetic_op_32(0x39, src, dst);
- }
+ arithmetic_op(0x39, src, dst, size);
}
void emit_cmp(Register dst, Immediate src, int size) {
- if (size == kInt64Size) {
- immediate_arithmetic_op(0x7, dst, src);
- } else {
- ASSERT(size == kInt32Size);
- immediate_arithmetic_op_32(0x7, dst, src);
- }
+ immediate_arithmetic_op(0x7, dst, src, size);
}
void emit_cmp(const Operand& dst, Immediate src, int size) {
- if (size == kInt64Size) {
- immediate_arithmetic_op(0x7, dst, src);
- } else {
- ASSERT(size == kInt32Size);
- immediate_arithmetic_op_32(0x7, dst, src);
- }
+ immediate_arithmetic_op(0x7, dst, src, size);
}
void emit_dec(Register dst, int size);
@@ -1599,99 +1530,49 @@
void emit_not(const Operand& dst, int size);
void emit_or(Register dst, Register src, int size) {
- if (size == kInt64Size) {
- arithmetic_op(0x0B, dst, src);
- } else {
- arithmetic_op_32(0x0B, dst, src);
- }
+ arithmetic_op(0x0B, dst, src, size);
}
void emit_or(Register dst, const Operand& src, int size) {
- if (size == kInt64Size) {
- arithmetic_op(0x0B, dst, src);
- } else {
- arithmetic_op_32(0x0B, dst, src);
- }
+ arithmetic_op(0x0B, dst, src, size);
}
void emit_or(const Operand& dst, Register src, int size) {
- if (size == kInt64Size) {
- arithmetic_op(0x9, src, dst);
- } else {
- arithmetic_op_32(0x9, src, dst);
- }
+ arithmetic_op(0x9, src, dst, size);
}
void emit_or(Register dst, Immediate src, int size) {
- if (size == kInt64Size) {
- immediate_arithmetic_op(0x1, dst, src);
- } else {
- immediate_arithmetic_op_32(0x1, dst, src);
- }
+ immediate_arithmetic_op(0x1, dst, src, size);
}
void emit_or(const Operand& dst, Immediate src, int size) {
- if (size == kInt64Size) {
- immediate_arithmetic_op(0x1, dst, src);
- } else {
- immediate_arithmetic_op_32(0x1, dst, src);
- }
+ immediate_arithmetic_op(0x1, dst, src, size);
}
void emit_repmovs(int size);
void emit_sbb(Register dst, Register src, int size) {
- if (size == kInt64Size) {
- arithmetic_op(0x1b, dst, src);
- } else {
- ASSERT(size == kInt32Size);
- arithmetic_op_32(0x1b, dst, src);
- }
+ arithmetic_op(0x1b, dst, src, size);
}
void emit_sub(Register dst, Register src, int size) {
- if (size == kInt64Size) {
- arithmetic_op(0x2B, dst, src);
- } else {
- ASSERT(size == kInt32Size);
- arithmetic_op_32(0x2B, dst, src);
- }
+ arithmetic_op(0x2B, dst, src, size);
}
void emit_sub(Register dst, Immediate src, int size) {
- if (size == kInt64Size) {
- immediate_arithmetic_op(0x5, dst, src);
- } else {
- ASSERT(size == kInt32Size);
- immediate_arithmetic_op_32(0x5, dst, src);
- }
+ immediate_arithmetic_op(0x5, dst, src, size);
}
void emit_sub(Register dst, const Operand& src, int size) {
- if (size == kInt64Size) {
- arithmetic_op(0x2B, dst, src);
- } else {
- ASSERT(size == kInt32Size);
- arithmetic_op_32(0x2B, dst, src);
- }
+ arithmetic_op(0x2B, dst, src, size);
}
void emit_sub(const Operand& dst, Register src, int size) {
- if (size == kInt64Size) {
- arithmetic_op(0x29, src, dst);
- } else {
- ASSERT(size == kInt32Size);
- arithmetic_op_32(0x29, src, dst);
- }
+ arithmetic_op(0x29, src, dst, size);
}
void emit_sub(const Operand& dst, Immediate src, int size) {
- if (size == kInt64Size) {
- immediate_arithmetic_op(0x5, dst, src);
- } else {
- ASSERT(size == kInt32Size);
- immediate_arithmetic_op_32(0x5, dst, src);
- }
+ immediate_arithmetic_op(0x5, dst, src, size);
}
void emit_test(Register dst, Register src, int size);
@@ -1703,52 +1584,29 @@
void emit_xchg(Register dst, Register src, int size);
void emit_xor(Register dst, Register src, int size) {
- if (size == kInt64Size) {
- if (dst.code() == src.code()) {
- arithmetic_op_32(0x33, dst, src);
- } else {
- arithmetic_op(0x33, dst, src);
- }
+ if (size == kInt64Size && dst.code() == src.code()) {
+ // 32 bit operations zero the top 32 bits of 64 bit registers.
Therefore
+ // there is no need to make this a 64 bit operation.
+ arithmetic_op(0x33, dst, src, kInt32Size);
} else {
- ASSERT(size == kInt32Size);
- arithmetic_op_32(0x33, dst, src);
+ arithmetic_op(0x33, dst, src, size);
}
}
void emit_xor(Register dst, const Operand& src, int size) {
- if (size == kInt64Size) {
- arithmetic_op(0x33, dst, src);
- } else {
- ASSERT(size == kInt32Size);
- arithmetic_op_32(0x33, dst, src);
- }
+ arithmetic_op(0x33, dst, src, size);
}
void emit_xor(Register dst, Immediate src, int size) {
- if (size == kInt64Size) {
- immediate_arithmetic_op(0x6, dst, src);
- } else {
- ASSERT(size == kInt32Size);
- immediate_arithmetic_op_32(0x6, dst, src);
- }
+ immediate_arithmetic_op(0x6, dst, src, size);
}
void emit_xor(const Operand& dst, Immediate src, int size) {
- if (size == kInt64Size) {
- immediate_arithmetic_op(0x6, dst, src);
- } else {
- ASSERT(size == kInt32Size);
- immediate_arithmetic_op_32(0x6, dst, src);
- }
+ immediate_arithmetic_op(0x6, dst, src, size);
}
void emit_xor(const Operand& dst, Register src, int size) {
- if (size == kInt64Size) {
- arithmetic_op(0x31, src, dst);
- } else {
- ASSERT(size == kInt32Size);
- arithmetic_op_32(0x31, src, dst);
- }
+ arithmetic_op(0x31, src, dst, size);
}
friend class CodePatcher;
=======================================
--- /branches/bleeding_edge/test/cctest/test-assembler-x64.cc Fri Mar 28
04:55:00 2014 UTC
+++ /branches/bleeding_edge/test/cctest/test-assembler-x64.cc Fri Mar 28
11:13:14 2014 UTC
@@ -139,6 +139,37 @@
int result = FUNCTION_CAST<F2>(buffer)(3, 2);
CHECK_EQ(5, result);
}
+
+
+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) {
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.