Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Side by Side Diff: runtime/vm/assembler_x64.h

Issue 8818001: Add 64-bit stubs to call into the runtime and to call native functions. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/assembler_ia32.cc ('k') | runtime/vm/assembler_x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #ifndef VM_ASSEMBLER_X64_H_ 5 #ifndef VM_ASSEMBLER_X64_H_
6 #define VM_ASSEMBLER_X64_H_ 6 #define VM_ASSEMBLER_X64_H_
7 7
8 #ifndef VM_ASSEMBLER_H_ 8 #ifndef VM_ASSEMBLER_H_
9 #error Do not include assembler_x64.h directly; use assembler.h instead. 9 #error Do not include assembler_x64.h directly; use assembler.h instead.
10 #endif 10 #endif
11 11
12 #include "vm/assert.h" 12 #include "vm/assert.h"
13 #include "vm/constants_x64.h" 13 #include "vm/constants_x64.h"
14 #include "vm/utils.h" 14 #include "vm/utils.h"
15 15
16 namespace dart { 16 namespace dart {
17 17
18 // Forward declarations. 18 // Forward declarations.
19 class RuntimeEntry; 19 class RuntimeEntry;
20 20
21 21
22 #if defined(TESTING) || defined(DEBUG) 22 #if defined(TESTING) || defined(DEBUG)
23 23
24 #if defined(TARGET_OS_WINDOWS)
25 // The compiler may dynamically align the stack on Windows, so do not check.
26 #define CHECK_STACK_ALIGNMENT { }
27 #else
24 #define CHECK_STACK_ALIGNMENT { \ 28 #define CHECK_STACK_ALIGNMENT { \
25 UNIMPLEMENTED(); \ 29 uword current_sp; \
30 asm volatile("mov %%rsp, %[current_sp]" : [current_sp] "=r" (current_sp)); \
31 ASSERT((OS::ActivationFrameAlignment() == 0) || \
32 (Utils::IsAligned(current_sp, OS::ActivationFrameAlignment()))); \
26 } 33 }
34 #endif
27 35
28 #else 36 #else
29 37
30 #define CHECK_STACK_ALIGNMENT { } 38 #define CHECK_STACK_ALIGNMENT { }
31 39
32 #endif 40 #endif
33 41
34 42
35 class Immediate : public ValueObject { 43 class Immediate : public ValueObject {
36 public: 44 public:
(...skipping 18 matching lines...) Expand all
55 public: 63 public:
56 uint8_t rex() const { 64 uint8_t rex() const {
57 return rex_; 65 return rex_;
58 } 66 }
59 67
60 uint8_t mod() const { 68 uint8_t mod() const {
61 return (encoding_at(0) >> 6) & 3; 69 return (encoding_at(0) >> 6) & 3;
62 } 70 }
63 71
64 Register rm() const { 72 Register rm() const {
65 int rm_rex = (rex_ & 1) << 3; 73 int rm_rex = (rex_ & REX_B) << 3;
66 return static_cast<Register>(rm_rex + (encoding_at(0) & 7)); 74 return static_cast<Register>(rm_rex + (encoding_at(0) & 7));
67 } 75 }
68 76
69 ScaleFactor scale() const { 77 ScaleFactor scale() const {
70 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3); 78 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
71 } 79 }
72 80
73 Register index() const { 81 Register index() const {
74 int index_rex = (rex_ & 2) << 2; 82 int index_rex = (rex_ & REX_X) << 2;
75 return static_cast<Register>(index_rex + ((encoding_at(1) >> 3) & 7)); 83 return static_cast<Register>(index_rex + ((encoding_at(1) >> 3) & 7));
76 } 84 }
77 85
78 Register base() const { 86 Register base() const {
79 int base_rex = (rex_ & 1) << 3; 87 int base_rex = (rex_ & REX_B) << 3;
80 return static_cast<Register>(base_rex + (encoding_at(1) & 7)); 88 return static_cast<Register>(base_rex + (encoding_at(1) & 7));
81 } 89 }
82 90
83 int8_t disp8() const { 91 int8_t disp8() const {
84 ASSERT(length_ >= 2); 92 ASSERT(length_ >= 2);
85 return static_cast<int8_t>(encoding_[length_ - 1]); 93 return static_cast<int8_t>(encoding_[length_ - 1]);
86 } 94 }
87 95
88 int32_t disp32() const { 96 int32_t disp32() const {
89 ASSERT(length_ >= 5); 97 ASSERT(length_ >= 5);
90 return bit_copy<int32_t>(encoding_[length_ - 4]); 98 return bit_copy<int32_t>(encoding_[length_ - 4]);
91 } 99 }
92 100
93 protected: 101 protected:
94 Operand() : length_(0), rex_(0) { } 102 Operand() : length_(0), rex_(REX_NONE) { }
95 103
96 void SetModRM(int mod, Register rm) { 104 void SetModRM(int mod, Register rm) {
97 ASSERT((mod & ~3) == 0); 105 ASSERT((mod & ~3) == 0);
98 if (rm > 7) rex_ |= 1; 106 if ((rm > 7) && !((rm == R12) && (mod != 3))) {
107 rex_ |= REX_B;
108 }
99 encoding_[0] = (mod << 6) | (rm & 7); 109 encoding_[0] = (mod << 6) | (rm & 7);
100 length_ = 1; 110 length_ = 1;
101 } 111 }
102 112
103 void SetSIB(ScaleFactor scale, Register index, Register base) { 113 void SetSIB(ScaleFactor scale, Register index, Register base) {
104 ASSERT(length_ == 1); 114 ASSERT(length_ == 1);
105 ASSERT((scale & ~3) == 0); 115 ASSERT((scale & ~3) == 0);
106 if (base > 7) { 116 if (base > 7) {
107 ASSERT((rex_ & 1) == 0); // Must not have REX.B already set. 117 ASSERT((rex_ & REX_B) == 0); // Must not have REX.B already set.
108 rex_ |= 1; 118 rex_ |= REX_B;
109 } 119 }
110 if (index > 7) rex_ |= 2; 120 if (index > 7) rex_ |= REX_X;
111 encoding_[1] = (scale << 6) | ((index & 7) << 3) | (base & 7); 121 encoding_[1] = (scale << 6) | ((index & 7) << 3) | (base & 7);
112 length_ = 2; 122 length_ = 2;
113 } 123 }
114 124
115 void SetDisp8(int8_t disp) { 125 void SetDisp8(int8_t disp) {
116 ASSERT(length_ == 1 || length_ == 2); 126 ASSERT(length_ == 1 || length_ == 2);
117 encoding_[length_++] = static_cast<uint8_t>(disp); 127 encoding_[length_++] = static_cast<uint8_t>(disp);
118 } 128 }
119 129
120 void SetDisp32(int32_t disp) { 130 void SetDisp32(int32_t disp) {
121 ASSERT(length_ == 1 || length_ == 2); 131 ASSERT(length_ == 1 || length_ == 2);
122 memmove(&encoding_[length_], &disp, sizeof(disp)); 132 memmove(&encoding_[length_], &disp, sizeof(disp));
123 length_ += sizeof(disp); 133 length_ += sizeof(disp);
124 } 134 }
125 135
126 private: 136 private:
127 uint8_t length_; 137 uint8_t length_;
128 uint8_t rex_; 138 uint8_t rex_;
129 uint8_t encoding_[6]; 139 uint8_t encoding_[6];
130 140
131 explicit Operand(Register reg) : rex_(0) { SetModRM(3, reg); } 141 explicit Operand(Register reg) : rex_(REX_NONE) { SetModRM(3, reg); }
132 142
133 // Get the operand encoding byte at the given index. 143 // Get the operand encoding byte at the given index.
134 uint8_t encoding_at(int index) const { 144 uint8_t encoding_at(int index) const {
135 ASSERT(index >= 0 && index < length_); 145 ASSERT(index >= 0 && index < length_);
136 return encoding_[index]; 146 return encoding_[index];
137 } 147 }
138 148
139 // Returns whether or not this operand is really the given register in 149 // Returns whether or not this operand is really the given register in
140 // disguise. Used from the assembler to generate better encodings. 150 // disguise. Used from the assembler to generate better encodings.
141 bool IsRegister(Register reg) const { 151 bool IsRegister(Register reg) const {
142 return ((reg > 7 ? 1 : 0) == (rex_ & 1)) // REX.B match. 152 return ((reg > 7 ? 1 : 0) == (rex_ & REX_B)) // REX.B match.
143 && ((encoding_at(0) & 0xF8) == 0xC0) // Addressing mode is register. 153 && ((encoding_at(0) & 0xF8) == 0xC0) // Addressing mode is register.
144 && ((encoding_at(0) & 0x07) == reg); // Register codes match. 154 && ((encoding_at(0) & 0x07) == reg); // Register codes match.
145 } 155 }
146 156
147 157
148 friend class Assembler; 158 friend class Assembler;
149 159
150 // TODO(5411081): Add DISALLOW_COPY_AND_ASSIGN(Operand) once the mac 160 // TODO(5411081): Add DISALLOW_COPY_AND_ASSIGN(Operand) once the mac
151 // build issue is resolved. 161 // build issue is resolved.
152 }; 162 };
153 163
154 164
155 class Address : public Operand { 165 class Address : public Operand {
156 public: 166 public:
157 Address(Register base, int32_t disp) { 167 Address(Register base, int32_t disp) {
158 if (disp == 0 && base != RBP) { 168 if ((disp == 0) && ((base & 7) != RBP)) {
159 SetModRM(0, base); 169 SetModRM(0, base);
160 if (base == RSP) SetSIB(TIMES_1, RSP, base); 170 if ((base & 7) == RSP) {
171 SetSIB(TIMES_1, RSP, base);
172 }
161 } else if (Utils::IsInt(8, disp)) { 173 } else if (Utils::IsInt(8, disp)) {
162 SetModRM(1, base); 174 SetModRM(1, base);
163 if (base == RSP) SetSIB(TIMES_1, RSP, base); 175 if ((base & 7) == RSP) {
176 SetSIB(TIMES_1, RSP, base);
177 }
164 SetDisp8(disp); 178 SetDisp8(disp);
165 } else { 179 } else {
166 SetModRM(2, base); 180 SetModRM(2, base);
167 if (base == RSP) SetSIB(TIMES_1, RSP, base); 181 if ((base & 7) == RSP) {
182 SetSIB(TIMES_1, RSP, base);
183 }
168 SetDisp32(disp); 184 SetDisp32(disp);
169 } 185 }
170 } 186 }
171 187
172 Address(Register index, ScaleFactor scale, int32_t disp) { 188 Address(Register index, ScaleFactor scale, int32_t disp) {
173 ASSERT(index != RSP); // Illegal addressing mode. 189 ASSERT(index != RSP); // Illegal addressing mode.
174 SetModRM(0, RSP); 190 SetModRM(0, RSP);
175 SetSIB(scale, index, RBP); 191 SetSIB(scale, index, RBP);
176 SetDisp32(disp); 192 SetDisp32(disp);
177 } 193 }
178 194
179 Address(Register base, Register index, ScaleFactor scale, int32_t disp) { 195 Address(Register base, Register index, ScaleFactor scale, int32_t disp) {
180 ASSERT(index != RSP); // Illegal addressing mode. 196 ASSERT(index != RSP); // Illegal addressing mode.
181 if (disp == 0 && base != RBP) { 197 if ((disp == 0) && ((base & 7) != RBP)) {
182 SetModRM(0, RSP); 198 SetModRM(0, RSP);
183 SetSIB(scale, index, base); 199 SetSIB(scale, index, base);
184 } else if (Utils::IsInt(8, disp)) { 200 } else if (Utils::IsInt(8, disp)) {
185 SetModRM(1, RSP); 201 SetModRM(1, RSP);
186 SetSIB(scale, index, base); 202 SetSIB(scale, index, base);
187 SetDisp8(disp); 203 SetDisp8(disp);
188 } else { 204 } else {
189 SetModRM(2, RSP); 205 SetModRM(2, RSP);
190 SetSIB(scale, index, base); 206 SetSIB(scale, index, base);
191 SetDisp32(disp); 207 SetDisp32(disp);
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 */ 315 */
300 void call(Register reg); 316 void call(Register reg);
301 void call(const Address& address); 317 void call(const Address& address);
302 void call(Label* label); 318 void call(Label* label);
303 void call(const ExternalLabel* label); 319 void call(const ExternalLabel* label);
304 320
305 static const intptr_t kCallExternalLabelSize = 5; 321 static const intptr_t kCallExternalLabelSize = 5;
306 322
307 void pushq(Register reg); 323 void pushq(Register reg);
308 void pushq(const Address& address); 324 void pushq(const Address& address);
325 void pushq(const Immediate& imm);
309 326
310 void popq(Register reg); 327 void popq(Register reg);
311 void popq(const Address& address); 328 void popq(const Address& address);
312 329
313 void movl(Register dst, Register src); 330 void movl(Register dst, Register src);
314 void movl(Register dst, const Immediate& imm); 331 void movl(Register dst, const Immediate& imm);
315 void movl(Register dst, const Address& src); 332 void movl(Register dst, const Address& src);
316 void movl(const Address& dst, Register src); 333 void movl(const Address& dst, Register src);
317 334
318 void movzxb(Register dst, Register src); 335 void movzxb(Register dst, Register src);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 380
364 void xchgl(Register dst, Register src); 381 void xchgl(Register dst, Register src);
365 void xchgq(Register dst, Register src); 382 void xchgq(Register dst, Register src);
366 383
367 void cmpl(Register reg, const Immediate& imm); 384 void cmpl(Register reg, const Immediate& imm);
368 void cmpl(Register reg0, Register reg1); 385 void cmpl(Register reg0, Register reg1);
369 void cmpl(Register reg, const Address& address); 386 void cmpl(Register reg, const Address& address);
370 void cmpl(const Address& address, const Immediate& imm); 387 void cmpl(const Address& address, const Immediate& imm);
371 388
372 void cmpq(Register reg, const Immediate& imm); 389 void cmpq(Register reg, const Immediate& imm);
390 void cmpq(const Address& address, Register reg);
373 void cmpq(const Address& address, const Immediate& imm); 391 void cmpq(const Address& address, const Immediate& imm);
374 void cmpq(Register reg0, Register reg1); 392 void cmpq(Register reg0, Register reg1);
375 void cmpq(Register reg, const Address& address); 393 void cmpq(Register reg, const Address& address);
376 394
377 void testl(Register reg1, Register reg2); 395 void testl(Register reg1, Register reg2);
378 void testl(Register reg, const Immediate& imm); 396 void testl(Register reg, const Immediate& imm);
379 397
380 void testq(Register reg1, Register reg2); 398 void testq(Register reg1, Register reg2);
381 void testq(Register reg, const Immediate& imm); 399 void testq(Register reg, const Immediate& imm);
382 400
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 void EnterFrame(intptr_t frame_space); 516 void EnterFrame(intptr_t frame_space);
499 void LeaveFrame(); 517 void LeaveFrame();
500 518
501 void CallRuntimeFromDart(const RuntimeEntry& entry); 519 void CallRuntimeFromDart(const RuntimeEntry& entry);
502 void CallRuntimeFromStub(const RuntimeEntry& entry); 520 void CallRuntimeFromStub(const RuntimeEntry& entry);
503 521
504 /* 522 /*
505 * Misc. functionality. 523 * Misc. functionality.
506 */ 524 */
507 void SmiTag(Register reg) { 525 void SmiTag(Register reg) {
508 addl(reg, reg); 526 addq(reg, reg);
509 } 527 }
510 528
511 void SmiUntag(Register reg) { 529 void SmiUntag(Register reg) {
512 sarl(reg, Immediate(kSmiTagSize)); 530 sarq(reg, Immediate(kSmiTagSize));
513 } 531 }
514 532
515 int PreferredLoopAlignment() { return 16; } 533 int PreferredLoopAlignment() { return 16; }
516 void Align(int alignment, int offset); 534 void Align(int alignment, int offset);
517 void Bind(Label* label); 535 void Bind(Label* label);
518 536
519 int CodeSize() const { return buffer_.Size(); } 537 int CodeSize() const { return buffer_.Size(); }
520 int prolog_offset() const { return prolog_offset_; } 538 int prolog_offset() const { return prolog_offset_; }
521 const ZoneGrowableArray<int>& GetPointerOffsets() const { 539 const ZoneGrowableArray<int>& GetPointerOffsets() const {
522 return buffer_.pointer_offsets(); 540 return buffer_.pointer_offsets();
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 void EmitNearLabelLink(Label* label); 575 void EmitNearLabelLink(Label* label);
558 576
559 void EmitGenericShift(bool wide, int rm, Register reg, const Immediate& imm); 577 void EmitGenericShift(bool wide, int rm, Register reg, const Immediate& imm);
560 void EmitGenericShift(bool wide, int rm, Register operand, Register shifter); 578 void EmitGenericShift(bool wide, int rm, Register operand, Register shifter);
561 579
562 DISALLOW_ALLOCATION(); 580 DISALLOW_ALLOCATION();
563 DISALLOW_COPY_AND_ASSIGN(Assembler); 581 DISALLOW_COPY_AND_ASSIGN(Assembler);
564 }; 582 };
565 583
566 584
567 enum {
568 REX_NONE = 0,
569 REX_B = 1 << 0,
570 REX_X = 1 << 1,
571 REX_R = 1 << 2,
572 REX_W = 1 << 3
573 };
574
575
576 inline void Assembler::EmitUint8(uint8_t value) { 585 inline void Assembler::EmitUint8(uint8_t value) {
577 buffer_.Emit<uint8_t>(value); 586 buffer_.Emit<uint8_t>(value);
578 } 587 }
579 588
580 589
581 inline void Assembler::EmitInt32(int32_t value) { 590 inline void Assembler::EmitInt32(int32_t value) {
582 buffer_.Emit<int32_t>(value); 591 buffer_.Emit<int32_t>(value);
583 } 592 }
584 593
585 594
586 inline void Assembler::EmitInt64(int64_t value) { 595 inline void Assembler::EmitInt64(int64_t value) {
587 buffer_.Emit<int64_t>(value); 596 buffer_.Emit<int64_t>(value);
588 } 597 }
589 598
590 599
591 inline void Assembler::EmitRegisterREX(Register reg, uint8_t rex) { 600 inline void Assembler::EmitRegisterREX(Register reg, uint8_t rex) {
592 ASSERT(reg != kNoRegister); 601 ASSERT(reg != kNoRegister);
593 rex |= (reg > 7 ? REX_B : REX_NONE); 602 rex |= (reg > 7 ? REX_B : REX_NONE);
594 if (rex != 0) EmitUint8(0x40 | rex); 603 if (rex != REX_NONE) EmitUint8(REX_PREFIX | rex);
595 } 604 }
596 605
597 606
598 inline void Assembler::EmitOperandREX(int rm, 607 inline void Assembler::EmitOperandREX(int rm,
599 const Operand& operand, 608 const Operand& operand,
600 uint8_t rex) { 609 uint8_t rex) {
601 rex |= (rm > 7 ? REX_R : REX_NONE) | operand.rex(); 610 rex |= (rm > 7 ? REX_R : REX_NONE) | operand.rex();
602 if (rex != 0) EmitUint8(0x40 | rex); 611 if (rex != REX_NONE) EmitUint8(REX_PREFIX | rex);
603 } 612 }
604 613
605 614
606 inline void Assembler::EmitFixup(AssemblerFixup* fixup) { 615 inline void Assembler::EmitFixup(AssemblerFixup* fixup) {
607 buffer_.EmitFixup(fixup); 616 buffer_.EmitFixup(fixup);
608 } 617 }
609 618
610 619
611 inline void Assembler::EmitOperandSizeOverride() { 620 inline void Assembler::EmitOperandSizeOverride() {
612 EmitUint8(0x66); 621 EmitUint8(0x66);
613 } 622 }
614 623
615 } // namespace dart 624 } // namespace dart
616 625
617 #endif // VM_ASSEMBLER_X64_H_ 626 #endif // VM_ASSEMBLER_X64_H_
OLDNEW
« no previous file with comments | « runtime/vm/assembler_ia32.cc ('k') | runtime/vm/assembler_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698