| Index: runtime/vm/assembler_x64.h
|
| ===================================================================
|
| --- runtime/vm/assembler_x64.h (revision 2106)
|
| +++ runtime/vm/assembler_x64.h (working copy)
|
| @@ -21,9 +21,21 @@
|
|
|
| #if defined(TESTING) || defined(DEBUG)
|
|
|
| +#if defined(TARGET_OS_WINDOWS)
|
| #define CHECK_STACK_ALIGNMENT { \
|
| - UNIMPLEMENTED(); \
|
| + uword current_sp; \
|
| + __asm { mov current_sp, rsp } \
|
| + ASSERT((OS::ActivationFrameAlignment() == 0) || \
|
| + (Utils::IsAligned(current_sp, OS::ActivationFrameAlignment()))); \
|
| }
|
| +#else
|
| +#define CHECK_STACK_ALIGNMENT { \
|
| + uword current_sp; \
|
| + asm volatile("mov %%rsp, %[current_sp]" : [current_sp] "=r" (current_sp)); \
|
| + ASSERT((OS::ActivationFrameAlignment() == 0) || \
|
| + (Utils::IsAligned(current_sp, OS::ActivationFrameAlignment()))); \
|
| +}
|
| +#endif
|
|
|
| #else
|
|
|
| @@ -62,7 +74,7 @@
|
| }
|
|
|
| Register rm() const {
|
| - int rm_rex = (rex_ & 1) << 3;
|
| + int rm_rex = (rex_ & REX_B) << 3;
|
| return static_cast<Register>(rm_rex + (encoding_at(0) & 7));
|
| }
|
|
|
| @@ -71,12 +83,12 @@
|
| }
|
|
|
| Register index() const {
|
| - int index_rex = (rex_ & 2) << 2;
|
| + int index_rex = (rex_ & REX_X) << 2;
|
| return static_cast<Register>(index_rex + ((encoding_at(1) >> 3) & 7));
|
| }
|
|
|
| Register base() const {
|
| - int base_rex = (rex_ & 1) << 3;
|
| + int base_rex = (rex_ & REX_B) << 3;
|
| return static_cast<Register>(base_rex + (encoding_at(1) & 7));
|
| }
|
|
|
| @@ -91,11 +103,13 @@
|
| }
|
|
|
| protected:
|
| - Operand() : length_(0), rex_(0) { }
|
| + Operand() : length_(0), rex_(REX_NONE) { }
|
|
|
| void SetModRM(int mod, Register rm) {
|
| ASSERT((mod & ~3) == 0);
|
| - if (rm > 7) rex_ |= 1;
|
| + if ((rm > 7) && !((rm == R12) && (mod != 3))) {
|
| + rex_ |= REX_B;
|
| + }
|
| encoding_[0] = (mod << 6) | (rm & 7);
|
| length_ = 1;
|
| }
|
| @@ -104,10 +118,10 @@
|
| ASSERT(length_ == 1);
|
| ASSERT((scale & ~3) == 0);
|
| if (base > 7) {
|
| - ASSERT((rex_ & 1) == 0); // Must not have REX.B already set.
|
| - rex_ |= 1;
|
| + ASSERT((rex_ & REX_B) == 0); // Must not have REX.B already set.
|
| + rex_ |= REX_B;
|
| }
|
| - if (index > 7) rex_ |= 2;
|
| + if (index > 7) rex_ |= REX_X;
|
| encoding_[1] = (scale << 6) | ((index & 7) << 3) | (base & 7);
|
| length_ = 2;
|
| }
|
| @@ -128,7 +142,7 @@
|
| uint8_t rex_;
|
| uint8_t encoding_[6];
|
|
|
| - explicit Operand(Register reg) : rex_(0) { SetModRM(3, reg); }
|
| + explicit Operand(Register reg) : rex_(REX_NONE) { SetModRM(3, reg); }
|
|
|
| // Get the operand encoding byte at the given index.
|
| uint8_t encoding_at(int index) const {
|
| @@ -139,7 +153,7 @@
|
| // Returns whether or not this operand is really the given register in
|
| // disguise. Used from the assembler to generate better encodings.
|
| bool IsRegister(Register reg) const {
|
| - return ((reg > 7 ? 1 : 0) == (rex_ & 1)) // REX.B match.
|
| + return ((reg > 7 ? 1 : 0) == (rex_ & REX_B)) // REX.B match.
|
| && ((encoding_at(0) & 0xF8) == 0xC0) // Addressing mode is register.
|
| && ((encoding_at(0) & 0x07) == reg); // Register codes match.
|
| }
|
| @@ -155,16 +169,22 @@
|
| class Address : public Operand {
|
| public:
|
| Address(Register base, int32_t disp) {
|
| - if (disp == 0 && base != RBP) {
|
| + if ((disp == 0) && ((base & 7) != RBP)) {
|
| SetModRM(0, base);
|
| - if (base == RSP) SetSIB(TIMES_1, RSP, base);
|
| + if ((base & 7) == RSP) {
|
| + SetSIB(TIMES_1, RSP, base);
|
| + }
|
| } else if (Utils::IsInt(8, disp)) {
|
| SetModRM(1, base);
|
| - if (base == RSP) SetSIB(TIMES_1, RSP, base);
|
| + if ((base & 7) == RSP) {
|
| + SetSIB(TIMES_1, RSP, base);
|
| + }
|
| SetDisp8(disp);
|
| } else {
|
| SetModRM(2, base);
|
| - if (base == RSP) SetSIB(TIMES_1, RSP, base);
|
| + if ((base & 7) == RSP) {
|
| + SetSIB(TIMES_1, RSP, base);
|
| + }
|
| SetDisp32(disp);
|
| }
|
| }
|
| @@ -306,6 +326,7 @@
|
|
|
| void pushq(Register reg);
|
| void pushq(const Address& address);
|
| + void pushq(const Immediate& imm);
|
|
|
| void popq(Register reg);
|
| void popq(const Address& address);
|
| @@ -370,6 +391,7 @@
|
| void cmpl(const Address& address, const Immediate& imm);
|
|
|
| void cmpq(Register reg, const Immediate& imm);
|
| + void cmpq(const Address& address, Register reg);
|
| void cmpq(const Address& address, const Immediate& imm);
|
| void cmpq(Register reg0, Register reg1);
|
| void cmpq(Register reg, const Address& address);
|
| @@ -505,11 +527,11 @@
|
| * Misc. functionality.
|
| */
|
| void SmiTag(Register reg) {
|
| - addl(reg, reg);
|
| + addq(reg, reg);
|
| }
|
|
|
| void SmiUntag(Register reg) {
|
| - sarl(reg, Immediate(kSmiTagSize));
|
| + sarq(reg, Immediate(kSmiTagSize));
|
| }
|
|
|
| int PreferredLoopAlignment() { return 16; }
|
| @@ -564,15 +586,6 @@
|
| };
|
|
|
|
|
| -enum {
|
| - REX_NONE = 0,
|
| - REX_B = 1 << 0,
|
| - REX_X = 1 << 1,
|
| - REX_R = 1 << 2,
|
| - REX_W = 1 << 3
|
| -};
|
| -
|
| -
|
| inline void Assembler::EmitUint8(uint8_t value) {
|
| buffer_.Emit<uint8_t>(value);
|
| }
|
| @@ -591,7 +604,7 @@
|
| inline void Assembler::EmitRegisterREX(Register reg, uint8_t rex) {
|
| ASSERT(reg != kNoRegister);
|
| rex |= (reg > 7 ? REX_B : REX_NONE);
|
| - if (rex != 0) EmitUint8(0x40 | rex);
|
| + if (rex != REX_NONE) EmitUint8(REX_PREFIX | rex);
|
| }
|
|
|
|
|
| @@ -599,7 +612,7 @@
|
| const Operand& operand,
|
| uint8_t rex) {
|
| rex |= (rm > 7 ? REX_R : REX_NONE) | operand.rex();
|
| - if (rex != 0) EmitUint8(0x40 | rex);
|
| + if (rex != REX_NONE) EmitUint8(REX_PREFIX | rex);
|
| }
|
|
|
|
|
|
|