Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 | 15 |
| 15 namespace dart { | 16 namespace dart { |
| 16 | 17 |
| 18 // Forward declarations. | |
| 19 class RuntimeEntry; | |
| 20 | |
| 21 | |
| 17 #if defined(TESTING) || defined(DEBUG) | 22 #if defined(TESTING) || defined(DEBUG) |
| 18 | 23 |
| 19 #define CHECK_STACK_ALIGNMENT { \ | 24 #define CHECK_STACK_ALIGNMENT { \ |
| 20 UNIMPLEMENTED(); \ | 25 UNIMPLEMENTED(); \ |
| 21 } | 26 } |
| 22 | 27 |
| 23 #else | 28 #else |
| 24 | 29 |
| 25 #define CHECK_STACK_ALIGNMENT { } | 30 #define CHECK_STACK_ALIGNMENT { } |
| 26 | 31 |
| 27 #endif | 32 #endif |
| 28 | 33 |
| 29 | 34 |
| 35 class Immediate : public ValueObject { | |
| 36 public: | |
| 37 explicit Immediate(int64_t value) : value_(value) { } | |
| 38 | |
| 39 int64_t value() const { return value_; } | |
| 40 | |
| 41 bool is_int8() const { return Utils::IsInt(8, value_); } | |
| 42 bool is_uint8() const { return Utils::IsUint(8, value_); } | |
| 43 bool is_uint16() const { return Utils::IsUint(16, value_); } | |
| 44 bool is_int32() const { return Utils::IsInt(32, value_); } | |
| 45 | |
| 46 private: | |
| 47 const int64_t value_; | |
| 48 | |
| 49 // TODO(5411081): Add DISALLOW_COPY_AND_ASSIGN(Immediate) once the mac | |
| 50 // build issue is resolved. | |
| 51 }; | |
| 52 | |
| 53 | |
| 54 class Operand : public ValueObject { | |
| 55 public: | |
| 56 uint8_t rex() const { | |
| 57 return rex_; | |
| 58 } | |
| 59 | |
| 60 uint8_t mod() const { | |
| 61 return (encoding_at(0) >> 6) & 3; | |
| 62 } | |
| 63 | |
| 64 Register rm() const { | |
| 65 int rm_rex = (rex_ & 1) << 3; | |
| 66 return static_cast<Register>(rm_rex + (encoding_at(0) & 7)); | |
| 67 } | |
| 68 | |
| 69 ScaleFactor scale() const { | |
| 70 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3); | |
| 71 } | |
| 72 | |
| 73 Register index() const { | |
| 74 int index_rex = (rex_ & 2) << 2; | |
| 75 return static_cast<Register>(index_rex + ((encoding_at(1) >> 3) & 7)); | |
| 76 } | |
| 77 | |
| 78 Register base() const { | |
| 79 int base_rex = (rex_ & 1) << 3; | |
| 80 return static_cast<Register>(base_rex + (encoding_at(1) & 7)); | |
| 81 } | |
| 82 | |
| 83 int8_t disp8() const { | |
| 84 ASSERT(length_ >= 2); | |
| 85 return static_cast<int8_t>(encoding_[length_ - 1]); | |
| 86 } | |
| 87 | |
| 88 int32_t disp32() const { | |
| 89 ASSERT(length_ >= 5); | |
| 90 return bit_copy<int32_t>(encoding_[length_ - 4]); | |
| 91 } | |
| 92 | |
| 93 protected: | |
| 94 Operand() : length_(0), rex_(0) { } | |
| 95 | |
| 96 void SetModRM(int mod, Register rm) { | |
| 97 ASSERT((mod & ~3) == 0); | |
| 98 if (rm > 7) rex_ |= 1; | |
| 99 encoding_[0] = (mod << 6) | (rm & 7); | |
| 100 length_ = 1; | |
| 101 } | |
| 102 | |
| 103 void SetSIB(ScaleFactor scale, Register index, Register base) { | |
| 104 ASSERT(length_ == 1); | |
| 105 ASSERT((scale & ~3) == 0); | |
| 106 if (base > 7) { | |
| 107 ASSERT((rex_ & 1) == 0); // Must not have REX.B already set. | |
| 108 rex_ |= 1; | |
| 109 } | |
| 110 if (index > 7) rex_ |= 2; | |
| 111 encoding_[1] = (scale << 6) | ((index & 7) << 3) | (base & 7); | |
| 112 length_ = 2; | |
| 113 } | |
| 114 | |
| 115 void SetDisp8(int8_t disp) { | |
| 116 ASSERT(length_ == 1 || length_ == 2); | |
| 117 encoding_[length_++] = static_cast<uint8_t>(disp); | |
| 118 } | |
| 119 | |
| 120 void SetDisp32(int32_t disp) { | |
| 121 ASSERT(length_ == 1 || length_ == 2); | |
| 122 memmove(&encoding_[length_], &disp, sizeof(disp)); | |
| 123 length_ += sizeof(disp); | |
| 124 } | |
| 125 | |
| 126 private: | |
| 127 uint8_t length_; | |
| 128 uint8_t rex_; | |
| 129 uint8_t encoding_[6]; | |
| 130 | |
| 131 explicit Operand(Register reg) : rex_(0) { SetModRM(3, reg); } | |
| 132 | |
| 133 // Get the operand encoding byte at the given index. | |
| 134 uint8_t encoding_at(int index) const { | |
| 135 ASSERT(index >= 0 && index < length_); | |
| 136 return encoding_[index]; | |
| 137 } | |
| 138 | |
| 139 // Returns whether or not this operand is really the given register in | |
| 140 // disguise. Used from the assembler to generate better encodings. | |
| 141 bool IsRegister(Register reg) const { | |
| 142 return ((reg > 7 ? 1 : 0) == (rex_ & 1)) // REX.B match. | |
| 143 && ((encoding_at(0) & 0xF8) == 0xC0) // Addressing mode is register. | |
| 144 && ((encoding_at(0) & 0x07) == reg); // Register codes match. | |
| 145 } | |
| 146 | |
| 147 | |
| 148 friend class Assembler; | |
| 149 | |
| 150 // TODO(5411081): Add DISALLOW_COPY_AND_ASSIGN(Operand) once the mac | |
| 151 // build issue is resolved. | |
| 152 }; | |
| 153 | |
| 154 | |
| 155 class Address : public Operand { | |
| 156 public: | |
| 157 Address(Register base, int32_t disp) { | |
| 158 if (disp == 0 && base != RBP) { | |
| 159 SetModRM(0, base); | |
| 160 if (base == RSP) SetSIB(TIMES_1, RSP, base); | |
| 161 } else if (Utils::IsInt(8, disp)) { | |
| 162 SetModRM(1, base); | |
| 163 if (base == RSP) SetSIB(TIMES_1, RSP, base); | |
| 164 SetDisp8(disp); | |
| 165 } else { | |
| 166 SetModRM(2, base); | |
| 167 if (base == RSP) SetSIB(TIMES_1, RSP, base); | |
| 168 SetDisp32(disp); | |
| 169 } | |
| 170 } | |
| 171 | |
| 172 Address(Register index, ScaleFactor scale, int32_t disp) { | |
| 173 ASSERT(index != RSP); // Illegal addressing mode. | |
| 174 SetModRM(0, RSP); | |
| 175 SetSIB(scale, index, RBP); | |
| 176 SetDisp32(disp); | |
| 177 } | |
| 178 | |
| 179 Address(Register base, Register index, ScaleFactor scale, int32_t disp) { | |
| 180 ASSERT(index != RSP); // Illegal addressing mode. | |
| 181 if (disp == 0 && base != RBP) { | |
| 182 SetModRM(0, RSP); | |
| 183 SetSIB(scale, index, base); | |
| 184 } else if (Utils::IsInt(8, disp)) { | |
| 185 SetModRM(1, RSP); | |
| 186 SetSIB(scale, index, base); | |
| 187 SetDisp8(disp); | |
| 188 } else { | |
| 189 SetModRM(2, RSP); | |
| 190 SetSIB(scale, index, base); | |
| 191 SetDisp32(disp); | |
| 192 } | |
| 193 } | |
| 194 | |
| 195 static Address Absolute(const uword addr) { | |
| 196 UNIMPLEMENTED(); | |
| 197 Address result; | |
| 198 result.SetModRM(0, RBP); | |
| 199 result.SetDisp32(addr); | |
| 200 return result; | |
| 201 } | |
| 202 | |
| 203 private: | |
| 204 Address() {} | |
| 205 | |
| 206 // TODO(5411081): Add DISALLOW_COPY_AND_ASSIGN(Address) once the mac | |
| 207 // build issue is resolved. | |
| 208 }; | |
| 209 | |
| 210 | |
| 211 class FieldAddress : public Address { | |
| 212 public: | |
| 213 FieldAddress(Register base, int32_t disp) | |
| 214 : Address(base, disp - kHeapObjectTag) {} | |
| 215 FieldAddress(Register base, Register index, ScaleFactor scale, int32_t disp) | |
| 216 : Address(base, index, scale, disp - kHeapObjectTag) {} | |
| 217 }; | |
| 218 | |
| 219 | |
| 30 class Label : public ValueObject { | 220 class Label : public ValueObject { |
| 31 public: | 221 public: |
| 32 Label() : position_(0) { } | 222 Label() : position_(0), unresolved_(0) { |
| 223 #ifdef DEBUG | |
| 224 for (int i = 0; i < kMaxUnresolvedBranches; i++) { | |
| 225 unresolved_near_positions_[i] = -1; | |
| 226 } | |
| 227 #endif // DEBUG | |
| 228 } | |
| 33 | 229 |
| 34 ~Label() { | 230 ~Label() { |
| 35 // Assert if label is being destroyed with unresolved branches pending. | 231 // Assert if label is being destroyed with unresolved branches pending. |
| 36 ASSERT(!IsLinked()); | 232 ASSERT(!IsLinked()); |
| 37 } | 233 ASSERT(!HasNear()); |
| 38 | 234 } |
| 39 // Returns the position for bound and linked labels. Cannot be used | 235 |
| 40 // for unused labels. | 236 // Returns the position for bound labels. Cannot be used for unused or linked |
| 237 // labels. | |
| 41 int Position() const { | 238 int Position() const { |
| 42 ASSERT(!IsUnused()); | 239 ASSERT(IsBound()); |
| 43 return IsBound() ? -position_ - kWordSize : position_ - kWordSize; | 240 return -position_ - kWordSize; |
| 241 } | |
| 242 | |
| 243 int LinkPosition() const { | |
| 244 ASSERT(IsLinked()); | |
| 245 return position_ - kWordSize; | |
| 246 } | |
| 247 | |
| 248 int NearPosition() { | |
| 249 ASSERT(HasNear()); | |
| 250 return unresolved_near_positions_[--unresolved_]; | |
| 44 } | 251 } |
| 45 | 252 |
| 46 bool IsBound() const { return position_ < 0; } | 253 bool IsBound() const { return position_ < 0; } |
| 47 bool IsUnused() const { return position_ == 0; } | 254 bool IsUnused() const { return (position_ == 0) && (unresolved_ == 0); } |
| 48 bool IsLinked() const { return position_ > 0; } | 255 bool IsLinked() const { return position_ > 0; } |
| 49 | 256 bool HasNear() const { return unresolved_ != 0; } |
| 50 private: | 257 |
| 51 int position_; | 258 private: |
| 52 | |
| 53 void Reinitialize() { | |
| 54 position_ = 0; | |
| 55 } | |
| 56 | |
| 57 void BindTo(int position) { | 259 void BindTo(int position) { |
| 58 ASSERT(!IsBound()); | 260 ASSERT(!IsBound()); |
| 261 ASSERT(!HasNear()); | |
| 59 position_ = -position - kWordSize; | 262 position_ = -position - kWordSize; |
| 60 ASSERT(IsBound()); | 263 ASSERT(IsBound()); |
| 61 } | 264 } |
| 62 | 265 |
| 63 void LinkTo(int position) { | 266 void LinkTo(int position) { |
| 64 ASSERT(!IsBound()); | 267 ASSERT(!IsBound()); |
| 65 position_ = position + kWordSize; | 268 position_ = position + kWordSize; |
| 66 ASSERT(IsLinked()); | 269 ASSERT(IsLinked()); |
| 67 } | 270 } |
| 68 | 271 |
| 272 void NearLinkTo(int position) { | |
| 273 ASSERT(!IsBound()); | |
| 274 ASSERT(unresolved_ < kMaxUnresolvedBranches); | |
| 275 unresolved_near_positions_[unresolved_++] = position; | |
| 276 } | |
| 277 | |
| 278 static const int kMaxUnresolvedBranches = 20; | |
| 279 | |
| 280 int position_; | |
| 281 int unresolved_; | |
| 282 int unresolved_near_positions_[kMaxUnresolvedBranches]; | |
| 283 | |
| 69 friend class Assembler; | 284 friend class Assembler; |
| 70 DISALLOW_COPY_AND_ASSIGN(Label); | 285 DISALLOW_COPY_AND_ASSIGN(Label); |
| 71 }; | 286 }; |
| 72 | 287 |
| 73 | 288 |
| 74 class Assembler { | 289 class Assembler : public ValueObject { |
| 75 public: | 290 public: |
| 76 Assembler() { } | 291 Assembler() : buffer_(), prolog_offset_(-1) { } |
| 77 ~Assembler() { } | 292 ~Assembler() { } |
| 78 | 293 |
| 79 // Macros for High-level operations. | 294 static const bool kNearJump = true; |
| 80 void AddConstant(Register reg, int value) { | 295 static const bool kFarJump = false; |
| 81 UNIMPLEMENTED(); | 296 |
| 82 } | 297 /* |
| 83 | 298 * Emit Machine Instructions. |
| 84 // Misc. functionality | 299 */ |
| 85 int CodeSize() const { | 300 void call(Register reg); |
| 86 UNIMPLEMENTED(); | 301 void call(const Address& address); |
| 87 return 0; | 302 void call(Label* label); |
| 88 } | 303 void call(const ExternalLabel* label); |
| 89 int prolog_offset() const { | 304 |
| 90 UNIMPLEMENTED(); | 305 static const intptr_t kCallExternalLabelSize = 5; |
| 91 return 0; | 306 |
| 92 } | 307 void pushq(Register reg); |
| 308 void pushq(const Address& address); | |
| 309 | |
| 310 void popq(Register reg); | |
| 311 void popq(const Address& address); | |
| 312 | |
| 313 void movl(Register dst, Register src); | |
| 314 void movl(Register dst, const Immediate& imm); | |
| 315 void movl(Register dst, const Address& src); | |
| 316 void movl(const Address& dst, Register src); | |
| 317 | |
| 318 void movzxb(Register dst, Register src); | |
| 319 void movzxb(Register dst, const Address& src); | |
| 320 void movsxb(Register dst, Register src); | |
| 321 void movsxb(Register dst, const Address& src); | |
| 322 void movb(Register dst, const Address& src); | |
| 323 void movb(const Address& dst, Register src); | |
| 324 void movb(const Address& dst, const Immediate& imm); | |
| 325 | |
| 326 void movzxw(Register dst, Register src); | |
| 327 void movzxw(Register dst, const Address& src); | |
| 328 void movsxw(Register dst, Register src); | |
| 329 void movsxw(Register dst, const Address& src); | |
| 330 void movw(Register dst, const Address& src); | |
| 331 void movw(const Address& dst, Register src); | |
| 332 | |
| 333 void movq(Register dst, const Immediate& imm); | |
| 334 void movq(Register dst, Register src); | |
| 335 void movq(Register dst, const Address& src); | |
| 336 void movq(const Address& dst, Register src); | |
| 337 void movq(const Address& dst, const Immediate& imm); | |
| 338 | |
| 339 void movsxl(Register dst, const Address& src); | |
| 340 | |
| 341 void leaq(Register dst, const Address& src); | |
| 342 | |
| 343 void movss(XmmRegister dst, const Address& src); | |
| 344 void movss(const Address& dst, XmmRegister src); | |
| 345 void movss(XmmRegister dst, XmmRegister src); | |
| 346 | |
| 347 void movd(XmmRegister dst, Register src); | |
| 348 void movd(Register dst, XmmRegister src); | |
| 349 | |
| 350 void addss(XmmRegister dst, XmmRegister src); | |
| 351 void subss(XmmRegister dst, XmmRegister src); | |
| 352 void mulss(XmmRegister dst, XmmRegister src); | |
| 353 void divss(XmmRegister dst, XmmRegister src); | |
| 354 | |
| 355 void movsd(XmmRegister dst, const Address& src); | |
| 356 void movsd(const Address& dst, XmmRegister src); | |
| 357 void movsd(XmmRegister dst, XmmRegister src); | |
| 358 | |
| 359 void addsd(XmmRegister dst, XmmRegister src); | |
| 360 void subsd(XmmRegister dst, XmmRegister src); | |
| 361 void mulsd(XmmRegister dst, XmmRegister src); | |
| 362 void divsd(XmmRegister dst, XmmRegister src); | |
| 363 | |
| 364 void xchgl(Register dst, Register src); | |
| 365 void xchgq(Register dst, Register src); | |
| 366 | |
| 367 void cmpl(Register reg, const Immediate& imm); | |
| 368 void cmpl(Register reg0, Register reg1); | |
| 369 void cmpl(Register reg, const Address& address); | |
| 370 void cmpl(const Address& address, const Immediate& imm); | |
| 371 | |
| 372 void cmpq(Register reg, const Immediate& imm); | |
| 373 void cmpq(const Address& address, const Immediate& imm); | |
| 374 void cmpq(Register reg0, Register reg1); | |
| 375 void cmpq(Register reg, const Address& address); | |
| 376 | |
| 377 void testl(Register reg1, Register reg2); | |
| 378 void testl(Register reg, const Immediate& imm); | |
| 379 | |
| 380 void testq(Register reg1, Register reg2); | |
| 381 void testq(Register reg, const Immediate& imm); | |
| 382 | |
| 383 void andl(Register dst, Register src); | |
| 384 void andl(Register dst, const Immediate& imm); | |
| 385 | |
| 386 void orl(Register dst, Register src); | |
| 387 void orl(Register dst, const Immediate& imm); | |
| 388 | |
| 389 void xorl(Register dst, Register src); | |
| 390 | |
| 391 void andq(Register dst, Register src); | |
| 392 void andq(Register dst, const Immediate& imm); | |
| 393 | |
| 394 void orq(Register dst, Register src); | |
| 395 void orq(Register dst, const Immediate& imm); | |
| 396 | |
| 397 void xorq(Register dst, Register src); | |
| 398 | |
| 399 void addl(Register dst, Register src); | |
| 400 void addl(const Address& address, const Immediate& imm); | |
| 401 | |
| 402 void addq(Register dst, Register src); | |
| 403 void addq(Register reg, const Immediate& imm); | |
| 404 void addq(const Address& address, const Immediate& imm); | |
| 405 | |
| 406 void subl(Register dst, Register src); | |
| 407 | |
| 408 void cdq(); | |
| 409 void cqo(); | |
| 410 | |
| 411 void idivl(Register reg); | |
| 412 void idivq(Register reg); | |
| 413 | |
| 414 void imull(Register dst, Register src); | |
| 415 void imull(Register reg, const Immediate& imm); | |
| 416 | |
| 417 void imulq(Register dst, Register src); | |
| 418 | |
| 419 void subq(Register dst, Register src); | |
| 420 void subq(Register reg, const Immediate& imm); | |
| 421 | |
| 422 void shll(Register reg, const Immediate& imm); | |
| 423 void shll(Register operand, Register shifter); | |
| 424 void shrl(Register reg, const Immediate& imm); | |
| 425 void shrl(Register operand, Register shifter); | |
| 426 void sarl(Register reg, const Immediate& imm); | |
| 427 void sarl(Register operand, Register shifter); | |
| 428 | |
| 429 void shlq(Register reg, const Immediate& imm); | |
| 430 void shlq(Register operand, Register shifter); | |
| 431 void shrq(Register reg, const Immediate& imm); | |
| 432 void shrq(Register operand, Register shifter); | |
| 433 void sarq(Register reg, const Immediate& imm); | |
| 434 void sarq(Register operand, Register shifter); | |
| 435 | |
| 436 void incl(const Address& address); | |
| 437 void decl(const Address& address); | |
| 438 | |
| 439 void incq(Register reg); | |
| 440 void incq(const Address& address); | |
| 441 void decq(Register reg); | |
| 442 void decq(const Address& address); | |
| 443 | |
| 444 void negl(Register reg); | |
| 445 void negq(Register reg); | |
| 446 | |
| 447 void enter(const Immediate& imm); | |
| 448 void leave(); | |
| 449 | |
| 450 void ret(); | |
| 451 void nop(); | |
| 452 void int3(); | |
| 453 void hlt(); | |
| 454 | |
| 455 void j(Condition condition, Label* label, bool near = kFarJump); | |
| 456 | |
| 457 void jmp(Register reg); | |
| 458 void jmp(Label* label, bool near = kFarJump); | |
| 459 void jmp(const ExternalLabel* label); | |
| 460 | |
| 461 void lock(); | |
| 462 void cmpxchgl(const Address& address, Register reg); | |
| 463 void lock_cmpxchgl(const Address& address, Register reg) { | |
| 464 lock(); | |
| 465 cmpxchgl(address, reg); | |
| 466 } | |
| 467 | |
| 468 void cmpxchgq(const Address& address, Register reg); | |
| 469 void lock_cmpxchgq(const Address& address, Register reg) { | |
| 470 lock(); | |
| 471 cmpxchgq(address, reg); | |
| 472 } | |
| 473 | |
| 474 /* | |
| 475 * Macros for High-level operations. | |
| 476 */ | |
| 477 void AddImmediate(Register reg, const Immediate& imm); | |
| 478 | |
| 479 void LoadObject(Register dst, const Object& object); | |
| 480 void PushObject(const Object& object); | |
| 481 void CompareObject(Register reg, const Object& object); | |
| 482 void LoadDoubleConstant(XmmRegister dst, double value); | |
| 483 | |
| 484 void StoreIntoObject(Register object, // Object we are storing into. | |
| 485 const FieldAddress& dest, // Where we are storing into. | |
| 486 Register value); // Value we are storing. | |
| 487 | |
| 488 void DoubleNegate(XmmRegister d); | |
| 489 void FloatNegate(XmmRegister f); | |
| 490 | |
| 491 void DoubleAbs(XmmRegister reg); | |
| 492 | |
| 493 void LockCmpxchgl(const Address& address, Register reg) { | |
| 494 lock(); | |
| 495 cmpxchgl(address, reg); | |
| 496 } | |
| 497 | |
| 498 void EnterFrame(intptr_t frame_space); | |
| 499 void LeaveFrame(); | |
| 500 | |
| 501 void CallRuntimeFromDart(const RuntimeEntry& entry); | |
| 502 void CallRuntimeFromStub(const RuntimeEntry& entry); | |
| 503 | |
| 504 /* | |
| 505 * Misc. functionality | |
|
siva
2011/11/30 21:43:43
missing '.'
regis
2011/11/30 22:02:09
Done.
| |
| 506 */ | |
| 507 void SmiTag(Register reg) { | |
| 508 addl(reg, reg); | |
| 509 } | |
| 510 | |
| 511 void SmiUntag(Register reg) { | |
| 512 sarl(reg, Immediate(kSmiTagSize)); | |
| 513 } | |
| 514 | |
| 515 int PreferredLoopAlignment() { return 16; } | |
| 516 void Align(int alignment, int offset); | |
| 517 void Bind(Label* label); | |
| 518 | |
| 519 int CodeSize() const { return buffer_.Size(); } | |
| 520 int prolog_offset() const { return prolog_offset_; } | |
| 93 const ZoneGrowableArray<int>& GetPointerOffsets() const { | 521 const ZoneGrowableArray<int>& GetPointerOffsets() const { |
| 94 UNIMPLEMENTED(); | 522 return buffer_.pointer_offsets(); |
| 95 return *pointer_offsets_; | 523 } |
| 96 } | 524 |
| 97 void FinalizeInstructions(const MemoryRegion& region) { | 525 void FinalizeInstructions(const MemoryRegion& region) { |
| 98 UNIMPLEMENTED(); | 526 buffer_.FinalizeInstructions(region); |
| 99 } | 527 } |
| 100 | 528 |
| 101 // Debugging and bringup support. | 529 // Debugging and bringup support. |
| 102 void Stop(const char* message) { UNIMPLEMENTED(); } | 530 void Stop(const char* message); |
| 103 void Unimplemented(const char* message); | 531 void Unimplemented(const char* message); |
| 104 void Untested(const char* message); | 532 void Untested(const char* message); |
| 105 void Unreachable(const char* message); | 533 void Unreachable(const char* message); |
| 106 | 534 |
| 107 static void InitializeMemoryWithBreakpoints(uword data, int length) { | 535 static void InitializeMemoryWithBreakpoints(uword data, int length); |
| 108 UNIMPLEMENTED(); | |
| 109 } | |
| 110 | 536 |
| 111 private: | 537 private: |
| 112 ZoneGrowableArray<int>* pointer_offsets_; | 538 AssemblerBuffer buffer_; |
| 539 int prolog_offset_; | |
| 540 | |
| 541 inline void EmitUint8(uint8_t value); | |
| 542 inline void EmitInt32(int32_t value); | |
| 543 inline void EmitInt64(int64_t value); | |
| 544 | |
| 545 inline void EmitRegisterREX(Register reg, uint8_t rex); | |
| 546 inline void EmitRegisterOperand(int rm, int reg); | |
| 547 inline void EmitOperandREX(int rm, const Operand& operand, uint8_t rex); | |
| 548 inline void EmitXmmRegisterOperand(int rm, XmmRegister reg); | |
| 549 inline void EmitFixup(AssemblerFixup* fixup); | |
| 550 inline void EmitOperandSizeOverride(); | |
| 551 | |
| 552 void EmitOperand(int rm, const Operand& operand); | |
| 553 void EmitImmediate(const Immediate& imm); | |
| 554 void EmitComplex(int rm, const Operand& operand, const Immediate& immediate); | |
| 555 void EmitLabel(Label* label, int instruction_size); | |
| 556 void EmitLabelLink(Label* label); | |
| 557 void EmitNearLabelLink(Label* label); | |
| 558 | |
| 559 void EmitGenericShift(bool wide, int rm, Register reg, const Immediate& imm); | |
| 560 void EmitGenericShift(bool wide, int rm, Register operand, Register shifter); | |
| 561 | |
| 113 DISALLOW_ALLOCATION(); | 562 DISALLOW_ALLOCATION(); |
| 114 DISALLOW_COPY_AND_ASSIGN(Assembler); | 563 DISALLOW_COPY_AND_ASSIGN(Assembler); |
| 115 }; | 564 }; |
| 116 | 565 |
| 566 | |
| 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) { | |
| 577 buffer_.Emit<uint8_t>(value); | |
| 578 } | |
| 579 | |
| 580 | |
| 581 inline void Assembler::EmitInt32(int32_t value) { | |
| 582 buffer_.Emit<int32_t>(value); | |
| 583 } | |
| 584 | |
| 585 | |
| 586 inline void Assembler::EmitInt64(int64_t value) { | |
| 587 buffer_.Emit<int64_t>(value); | |
| 588 } | |
| 589 | |
| 590 | |
| 591 inline void Assembler::EmitRegisterREX(Register reg, uint8_t rex) { | |
| 592 ASSERT(reg != kNoRegister); | |
| 593 rex |= (reg > 7 ? REX_B : REX_NONE); | |
| 594 if (rex != 0) EmitUint8(0x40 | rex); | |
| 595 } | |
| 596 | |
| 597 | |
| 598 inline void Assembler::EmitOperandREX(int rm, | |
| 599 const Operand& operand, | |
| 600 uint8_t rex) { | |
| 601 rex |= (rm > 7 ? REX_R : REX_NONE) | operand.rex(); | |
| 602 if (rex != 0) EmitUint8(0x40 | rex); | |
| 603 } | |
| 604 | |
| 605 | |
| 606 inline void Assembler::EmitFixup(AssemblerFixup* fixup) { | |
| 607 buffer_.EmitFixup(fixup); | |
| 608 } | |
| 609 | |
| 610 | |
| 611 inline void Assembler::EmitOperandSizeOverride() { | |
| 612 EmitUint8(0x66); | |
| 613 } | |
| 614 | |
| 117 } // namespace dart | 615 } // namespace dart |
| 118 | 616 |
| 119 #endif // VM_ASSEMBLER_X64_H_ | 617 #endif // VM_ASSEMBLER_X64_H_ |
| OLD | NEW |