Chromium Code Reviews| Index: runtime/vm/assembler_x64.h |
| =================================================================== |
| --- runtime/vm/assembler_x64.h (revision 2143) |
| +++ 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 } \ |
|
Ivan Posva
2011/12/07 08:34:51
This has certainly not been tested. Please replace
regis
2011/12/07 19:37:36
As discussed, the compiler on Windows may dynamica
|
| + 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); |
| } |
| } |
| @@ -178,7 +198,7 @@ |
| Address(Register base, Register index, ScaleFactor scale, int32_t disp) { |
| ASSERT(index != RSP); // Illegal addressing mode. |
| - if (disp == 0 && base != RBP) { |
| + if ((disp == 0) && ((base & 7) != RBP)) { |
| SetModRM(0, RSP); |
| SetSIB(scale, index, base); |
| } else if (Utils::IsInt(8, 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); |
| } |