| Index: src/x64/assembler-x64.cc
|
| diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc
|
| index 7a7fc6c87bcae85226d288b86a25060ab907ac49..aeb4ddfc6bd350630b136cafa9042ee3e906eb6e 100644
|
| --- a/src/x64/assembler-x64.cc
|
| +++ b/src/x64/assembler-x64.cc
|
| @@ -2045,159 +2045,137 @@ void Assembler::store_rax(ExternalReference ref) {
|
|
|
| void Assembler::testb(Register dst, Register src) {
|
| EnsureSpace ensure_space(this);
|
| - if (src.low_bits() == 4) {
|
| - emit_rex_32(src, dst);
|
| - emit(0x84);
|
| - emit_modrm(src, dst);
|
| - } else {
|
| - if (!dst.is_byte_register() || !src.is_byte_register()) {
|
| - // Register is not one of al, bl, cl, dl. Its encoding needs REX.
|
| - emit_rex_32(dst, src);
|
| - }
|
| - emit(0x84);
|
| - emit_modrm(dst, src);
|
| - }
|
| + emit_test(dst, src, sizeof(int8_t));
|
| }
|
|
|
| -
|
| void Assembler::testb(Register reg, Immediate mask) {
|
| DCHECK(is_int8(mask.value_) || is_uint8(mask.value_));
|
| - EnsureSpace ensure_space(this);
|
| - if (reg.is(rax)) {
|
| - emit(0xA8);
|
| - emit(mask.value_); // Low byte emitted.
|
| - } else {
|
| - if (!reg.is_byte_register()) {
|
| - // Register is not one of al, bl, cl, dl. Its encoding needs REX.
|
| - emit_rex_32(reg);
|
| - }
|
| - emit(0xF6);
|
| - emit_modrm(0x0, reg);
|
| - emit(mask.value_); // Low byte emitted.
|
| - }
|
| + emit_test(reg, mask, sizeof(int8_t));
|
| }
|
|
|
| -
|
| void Assembler::testb(const Operand& op, Immediate mask) {
|
| DCHECK(is_int8(mask.value_) || is_uint8(mask.value_));
|
| - EnsureSpace ensure_space(this);
|
| - emit_optional_rex_32(rax, op);
|
| - emit(0xF6);
|
| - emit_operand(rax, op); // Operation code 0
|
| - emit(mask.value_); // Low byte emitted.
|
| + emit_test(op, mask, sizeof(int8_t));
|
| }
|
|
|
|
|
| void Assembler::testb(const Operand& op, Register reg) {
|
| - 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, op);
|
| - } else {
|
| - emit_optional_rex_32(reg, op);
|
| - }
|
| - emit(0x84);
|
| - emit_operand(reg, op);
|
| + emit_test(op, reg, sizeof(int8_t));
|
| }
|
|
|
| void Assembler::testw(Register dst, Register src) {
|
| - EnsureSpace ensure_space(this);
|
| - emit(0x66);
|
| - if (!dst.is_byte_register() || !src.is_byte_register()) {
|
| - // Register is not one of al, bl, cl, dl. Its encoding needs REX.
|
| - emit_rex_32(dst, src);
|
| - }
|
| - emit(0x85);
|
| - emit_modrm(dst, src);
|
| + emit_test(dst, src, sizeof(uint16_t));
|
| }
|
|
|
| void Assembler::testw(Register reg, Immediate mask) {
|
| - DCHECK(is_int16(mask.value_) || is_uint16(mask.value_));
|
| - EnsureSpace ensure_space(this);
|
| - emit(0x66);
|
| - if (reg.is(rax)) {
|
| - emit(0xA9);
|
| - emitw(mask.value_);
|
| - } else {
|
| - if (!reg.is_byte_register()) {
|
| - emit_rex_32(reg);
|
| - }
|
| - emit(0xF7);
|
| - emit_modrm(0x0, reg);
|
| - emitw(mask.value_);
|
| - }
|
| + emit_test(reg, mask, sizeof(int16_t));
|
| }
|
|
|
| void Assembler::testw(const Operand& op, Immediate mask) {
|
| - DCHECK(is_int16(mask.value_) || is_uint16(mask.value_));
|
| - EnsureSpace ensure_space(this);
|
| - emit(0x66);
|
| - emit_optional_rex_32(rax, op);
|
| - emit(0xF7);
|
| - emit_operand(rax, op);
|
| - emitw(mask.value_);
|
| + emit_test(op, mask, sizeof(int16_t));
|
| }
|
|
|
| void Assembler::testw(const Operand& op, Register reg) {
|
| - EnsureSpace ensure_space(this);
|
| - emit(0x66);
|
| - emit_optional_rex_32(reg, op);
|
| - emit(0x85);
|
| - emit_operand(rax, op);
|
| + emit_test(op, reg, sizeof(int16_t));
|
| }
|
|
|
| void Assembler::emit_test(Register dst, Register src, int size) {
|
| EnsureSpace ensure_space(this);
|
| - if (src.low_bits() == 4) {
|
| - emit_rex(src, dst, size);
|
| - emit(0x85);
|
| - emit_modrm(src, dst);
|
| + if (src.low_bits() == 4) std::swap(dst, src);
|
| + if (size == sizeof(int16_t)) {
|
| + emit(0x66);
|
| + size = sizeof(int32_t);
|
| + }
|
| + bool byte_operand = size == sizeof(int8_t);
|
| + if (byte_operand) {
|
| + size = sizeof(int32_t);
|
| + if (!src.is_byte_register() || !dst.is_byte_register()) {
|
| + emit_rex_32(dst, src);
|
| + }
|
| } else {
|
| emit_rex(dst, src, size);
|
| - emit(0x85);
|
| - emit_modrm(dst, src);
|
| }
|
| + emit(byte_operand ? 0x84 : 0x85);
|
| + emit_modrm(dst, src);
|
| }
|
|
|
|
|
| void Assembler::emit_test(Register reg, Immediate mask, int size) {
|
| - // testl with a mask that fits in the low byte is exactly testb.
|
| if (is_uint8(mask.value_)) {
|
| - testb(reg, mask);
|
| - return;
|
| + size = sizeof(int8_t);
|
| + } else if (is_uint16(mask.value_)) {
|
| + size = sizeof(int16_t);
|
| }
|
| EnsureSpace ensure_space(this);
|
| - if (reg.is(rax)) {
|
| - emit_rex(rax, size);
|
| - emit(0xA9);
|
| - emit(mask);
|
| + bool half_word = size == sizeof(int16_t);
|
| + if (half_word) {
|
| + emit(0x66);
|
| + size = sizeof(int32_t);
|
| + }
|
| + bool byte_operand = size == sizeof(int8_t);
|
| + if (byte_operand) {
|
| + size = sizeof(int32_t);
|
| + if (!reg.is_byte_register()) emit_rex_32(reg);
|
| } else {
|
| emit_rex(reg, size);
|
| - emit(0xF7);
|
| + }
|
| + if (reg.is(rax)) {
|
| + emit(byte_operand ? 0xA8 : 0xA9);
|
| + } else {
|
| + emit(byte_operand ? 0xF6 : 0xF7);
|
| emit_modrm(0x0, reg);
|
| + }
|
| + if (byte_operand) {
|
| + emit(mask.value_);
|
| + } else if (half_word) {
|
| + emitw(mask.value_);
|
| + } else {
|
| emit(mask);
|
| }
|
| }
|
|
|
| -
|
| void Assembler::emit_test(const Operand& op, Immediate mask, int size) {
|
| - // testl with a mask that fits in the low byte is exactly testb.
|
| if (is_uint8(mask.value_)) {
|
| - testb(op, mask);
|
| - return;
|
| + size = sizeof(int8_t);
|
| + } else if (is_uint16(mask.value_)) {
|
| + size = sizeof(int16_t);
|
| }
|
| EnsureSpace ensure_space(this);
|
| + bool half_word = size == sizeof(int16_t);
|
| + if (half_word) {
|
| + emit(0x66);
|
| + size = sizeof(int32_t);
|
| + }
|
| + bool byte_operand = size == sizeof(int8_t);
|
| + if (byte_operand) {
|
| + size = sizeof(int32_t);
|
| + }
|
| emit_rex(rax, op, size);
|
| - emit(0xF7);
|
| + emit(byte_operand ? 0xF6 : 0xF7);
|
| emit_operand(rax, op); // Operation code 0
|
| - emit(mask);
|
| + if (byte_operand) {
|
| + emit(mask.value_);
|
| + } else if (half_word) {
|
| + emitw(mask.value_);
|
| + } else {
|
| + emit(mask);
|
| + }
|
| }
|
|
|
| -
|
| void Assembler::emit_test(const Operand& op, Register reg, int size) {
|
| EnsureSpace ensure_space(this);
|
| - emit_rex(reg, op, size);
|
| - emit(0x85);
|
| + if (size == sizeof(int16_t)) {
|
| + emit(0x66);
|
| + size = sizeof(int32_t);
|
| + }
|
| + bool byte_operand = size == sizeof(int8_t);
|
| + if (byte_operand) {
|
| + size = sizeof(int32_t);
|
| + if (!reg.is_byte_register()) emit_rex_32(reg, op);
|
| + } else {
|
| + emit_rex(reg, op, size);
|
| + }
|
| + emit(byte_operand ? 0x84 : 0x85);
|
| emit_operand(reg, op);
|
| }
|
|
|
|
|