OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_ARM64_SIMULATOR_ARM64_H_ | 5 #ifndef V8_ARM64_SIMULATOR_ARM64_H_ |
6 #define V8_ARM64_SIMULATOR_ARM64_H_ | 6 #define V8_ARM64_SIMULATOR_ARM64_H_ |
7 | 7 |
8 #include <stdarg.h> | 8 #include <stdarg.h> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 // describes the bits which are not modifiable. | 126 // describes the bits which are not modifiable. |
127 SimSystemRegister(uint32_t value, uint32_t write_ignore_mask) | 127 SimSystemRegister(uint32_t value, uint32_t write_ignore_mask) |
128 : value_(value), write_ignore_mask_(write_ignore_mask) { } | 128 : value_(value), write_ignore_mask_(write_ignore_mask) { } |
129 | 129 |
130 uint32_t value_; | 130 uint32_t value_; |
131 uint32_t write_ignore_mask_; | 131 uint32_t write_ignore_mask_; |
132 }; | 132 }; |
133 | 133 |
134 | 134 |
135 // Represent a register (r0-r31, v0-v31). | 135 // Represent a register (r0-r31, v0-v31). |
| 136 template<int kSizeInBytes> |
136 class SimRegisterBase { | 137 class SimRegisterBase { |
137 public: | 138 public: |
138 template<typename T> | 139 template<typename T> |
139 void Set(T new_value) { | 140 void Set(T new_value, unsigned size = sizeof(T)) { |
140 value_ = 0; | 141 ASSERT(size <= kSizeInBytes); |
141 memcpy(&value_, &new_value, sizeof(T)); | 142 ASSERT(size <= sizeof(new_value)); |
| 143 // All AArch64 registers are zero-extending; Writing a W register clears the |
| 144 // top bits of the corresponding X register. |
| 145 memset(value_, 0, kSizeInBytes); |
| 146 memcpy(value_, &new_value, size); |
142 } | 147 } |
143 | 148 |
| 149 // Copy 'size' bytes of the register to the result, and zero-extend to fill |
| 150 // the result. |
144 template<typename T> | 151 template<typename T> |
145 T Get() const { | 152 T Get(unsigned size = sizeof(T)) const { |
| 153 ASSERT(size <= kSizeInBytes); |
146 T result; | 154 T result; |
147 memcpy(&result, &value_, sizeof(T)); | 155 memset(&result, 0, sizeof(result)); |
| 156 memcpy(&result, value_, size); |
148 return result; | 157 return result; |
149 } | 158 } |
150 | 159 |
151 protected: | 160 protected: |
152 int64_t value_; | 161 uint8_t value_[kSizeInBytes]; |
153 }; | 162 }; |
154 | 163 typedef SimRegisterBase<kXRegSize> SimRegister; // r0-r31 |
155 | 164 typedef SimRegisterBase<kDRegSize> SimFPRegister; // v0-v31 |
156 typedef SimRegisterBase SimRegister; // r0-r31 | |
157 typedef SimRegisterBase SimFPRegister; // v0-v31 | |
158 | 165 |
159 | 166 |
160 class Simulator : public DecoderVisitor { | 167 class Simulator : public DecoderVisitor { |
161 public: | 168 public: |
162 explicit Simulator(Decoder<DispatchingDecoderVisitor>* decoder, | 169 explicit Simulator(Decoder<DispatchingDecoderVisitor>* decoder, |
163 Isolate* isolate = NULL, | 170 Isolate* isolate = NULL, |
164 FILE* stream = stderr); | 171 FILE* stream = stderr); |
165 Simulator(); | 172 Simulator(); |
166 ~Simulator(); | 173 ~Simulator(); |
167 | 174 |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
314 LogProcessorState(); | 321 LogProcessorState(); |
315 increment_pc(); | 322 increment_pc(); |
316 CheckBreakpoints(); | 323 CheckBreakpoints(); |
317 } | 324 } |
318 | 325 |
319 // Declare all Visitor functions. | 326 // Declare all Visitor functions. |
320 #define DECLARE(A) void Visit##A(Instruction* instr); | 327 #define DECLARE(A) void Visit##A(Instruction* instr); |
321 VISITOR_LIST(DECLARE) | 328 VISITOR_LIST(DECLARE) |
322 #undef DECLARE | 329 #undef DECLARE |
323 | 330 |
324 bool IsZeroRegister(unsigned code, Reg31Mode r31mode) const { | 331 // Register accessors. |
325 return ((code == 31) && (r31mode == Reg31IsZeroRegister)); | |
326 } | |
327 | 332 |
328 // Register accessors. | |
329 // Return 'size' bits of the value of an integer register, as the specified | 333 // Return 'size' bits of the value of an integer register, as the specified |
330 // type. The value is zero-extended to fill the result. | 334 // type. The value is zero-extended to fill the result. |
331 // | 335 // |
| 336 // The only supported values of 'size' are kXRegSizeInBits and |
| 337 // kWRegSizeInBits. |
| 338 template<typename T> |
| 339 T reg(unsigned size, unsigned code, |
| 340 Reg31Mode r31mode = Reg31IsZeroRegister) const { |
| 341 unsigned size_in_bytes = size / 8; |
| 342 ASSERT(size_in_bytes <= sizeof(T)); |
| 343 ASSERT((size == kXRegSizeInBits) || (size == kWRegSizeInBits)); |
| 344 ASSERT(code < kNumberOfRegisters); |
| 345 |
| 346 if ((code == 31) && (r31mode == Reg31IsZeroRegister)) { |
| 347 T result; |
| 348 memset(&result, 0, sizeof(result)); |
| 349 return result; |
| 350 } |
| 351 return registers_[code].Get<T>(size_in_bytes); |
| 352 } |
| 353 |
| 354 // Like reg(), but infer the access size from the template type. |
332 template<typename T> | 355 template<typename T> |
333 T reg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const { | 356 T reg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const { |
334 ASSERT(code < kNumberOfRegisters); | 357 return reg<T>(sizeof(T) * 8, code, r31mode); |
335 if (IsZeroRegister(code, r31mode)) { | |
336 return 0; | |
337 } | |
338 return registers_[code].Get<T>(); | |
339 } | 358 } |
340 | 359 |
341 // Common specialized accessors for the reg() template. | 360 // Common specialized accessors for the reg() template. |
342 int32_t wreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const { | 361 int32_t wreg(unsigned code, |
| 362 Reg31Mode r31mode = Reg31IsZeroRegister) const { |
343 return reg<int32_t>(code, r31mode); | 363 return reg<int32_t>(code, r31mode); |
344 } | 364 } |
345 | 365 |
346 int64_t xreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const { | 366 int64_t xreg(unsigned code, |
| 367 Reg31Mode r31mode = Reg31IsZeroRegister) const { |
347 return reg<int64_t>(code, r31mode); | 368 return reg<int64_t>(code, r31mode); |
348 } | 369 } |
349 | 370 |
| 371 int64_t reg(unsigned size, unsigned code, |
| 372 Reg31Mode r31mode = Reg31IsZeroRegister) const { |
| 373 return reg<int64_t>(size, code, r31mode); |
| 374 } |
| 375 |
350 // Write 'size' bits of 'value' into an integer register. The value is | 376 // Write 'size' bits of 'value' into an integer register. The value is |
351 // zero-extended. This behaviour matches AArch64 register writes. | 377 // zero-extended. This behaviour matches AArch64 register writes. |
| 378 // |
| 379 // The only supported values of 'size' are kXRegSizeInBits and |
| 380 // kWRegSizeInBits. |
| 381 template<typename T> |
| 382 void set_reg(unsigned size, unsigned code, T value, |
| 383 Reg31Mode r31mode = Reg31IsZeroRegister) { |
| 384 unsigned size_in_bytes = size / 8; |
| 385 ASSERT(size_in_bytes <= sizeof(T)); |
| 386 ASSERT((size == kXRegSizeInBits) || (size == kWRegSizeInBits)); |
| 387 ASSERT(code < kNumberOfRegisters); |
| 388 |
| 389 if ((code == 31) && (r31mode == Reg31IsZeroRegister)) { |
| 390 return; |
| 391 } |
| 392 return registers_[code].Set(value, size_in_bytes); |
| 393 } |
352 | 394 |
353 // Like set_reg(), but infer the access size from the template type. | 395 // Like set_reg(), but infer the access size from the template type. |
354 template<typename T> | 396 template<typename T> |
355 void set_reg(unsigned code, T value, | 397 void set_reg(unsigned code, T value, |
356 Reg31Mode r31mode = Reg31IsZeroRegister) { | 398 Reg31Mode r31mode = Reg31IsZeroRegister) { |
357 ASSERT(code < kNumberOfRegisters); | 399 set_reg(sizeof(value) * 8, code, value, r31mode); |
358 if (!IsZeroRegister(code, r31mode)) | |
359 registers_[code].Set(value); | |
360 } | 400 } |
361 | 401 |
362 // Common specialized accessors for the set_reg() template. | 402 // Common specialized accessors for the set_reg() template. |
363 void set_wreg(unsigned code, int32_t value, | 403 void set_wreg(unsigned code, int32_t value, |
364 Reg31Mode r31mode = Reg31IsZeroRegister) { | 404 Reg31Mode r31mode = Reg31IsZeroRegister) { |
365 set_reg(code, value, r31mode); | 405 set_reg(kWRegSizeInBits, code, value, r31mode); |
366 } | 406 } |
367 | 407 |
368 void set_xreg(unsigned code, int64_t value, | 408 void set_xreg(unsigned code, int64_t value, |
369 Reg31Mode r31mode = Reg31IsZeroRegister) { | 409 Reg31Mode r31mode = Reg31IsZeroRegister) { |
370 set_reg(code, value, r31mode); | 410 set_reg(kXRegSizeInBits, code, value, r31mode); |
371 } | 411 } |
372 | 412 |
373 // Commonly-used special cases. | 413 // Commonly-used special cases. |
374 template<typename T> | 414 template<typename T> |
375 void set_lr(T value) { | 415 void set_lr(T value) { |
376 ASSERT(sizeof(T) == kPointerSize); | 416 ASSERT(sizeof(T) == kPointerSize); |
377 set_reg(kLinkRegCode, value); | 417 set_reg(kLinkRegCode, value); |
378 } | 418 } |
379 | 419 |
380 template<typename T> | 420 template<typename T> |
381 void set_sp(T value) { | 421 void set_sp(T value) { |
382 ASSERT(sizeof(T) == kPointerSize); | 422 ASSERT(sizeof(T) == kPointerSize); |
383 set_reg(31, value, Reg31IsStackPointer); | 423 set_reg(31, value, Reg31IsStackPointer); |
384 } | 424 } |
385 | 425 |
386 int64_t sp() { return xreg(31, Reg31IsStackPointer); } | 426 int64_t sp() { return xreg(31, Reg31IsStackPointer); } |
387 int64_t jssp() { return xreg(kJSSPCode, Reg31IsStackPointer); } | 427 int64_t jssp() { return xreg(kJSSPCode, Reg31IsStackPointer); } |
388 int64_t fp() { | 428 int64_t fp() { |
389 return xreg(kFramePointerRegCode, Reg31IsStackPointer); | 429 return xreg(kFramePointerRegCode, Reg31IsStackPointer); |
390 } | 430 } |
391 Instruction* lr() { return reg<Instruction*>(kLinkRegCode); } | 431 Instruction* lr() { return reg<Instruction*>(kLinkRegCode); } |
392 | 432 |
393 Address get_sp() { return reg<Address>(31, Reg31IsStackPointer); } | 433 Address get_sp() { return reg<Address>(31, Reg31IsStackPointer); } |
394 | 434 |
| 435 // Return 'size' bits of the value of a floating-point register, as the |
| 436 // specified type. The value is zero-extended to fill the result. |
| 437 // |
| 438 // The only supported values of 'size' are kDRegSizeInBits and |
| 439 // kSRegSizeInBits. |
| 440 template<typename T> |
| 441 T fpreg(unsigned size, unsigned code) const { |
| 442 unsigned size_in_bytes = size / 8; |
| 443 ASSERT(size_in_bytes <= sizeof(T)); |
| 444 ASSERT((size == kDRegSizeInBits) || (size == kSRegSizeInBits)); |
| 445 ASSERT(code < kNumberOfFPRegisters); |
| 446 return fpregisters_[code].Get<T>(size_in_bytes); |
| 447 } |
| 448 |
| 449 // Like fpreg(), but infer the access size from the template type. |
395 template<typename T> | 450 template<typename T> |
396 T fpreg(unsigned code) const { | 451 T fpreg(unsigned code) const { |
397 ASSERT(code < kNumberOfRegisters); | 452 return fpreg<T>(sizeof(T) * 8, code); |
398 return fpregisters_[code].Get<T>(); | |
399 } | 453 } |
400 | 454 |
401 // Common specialized accessors for the fpreg() template. | 455 // Common specialized accessors for the fpreg() template. |
402 float sreg(unsigned code) const { | 456 float sreg(unsigned code) const { |
403 return fpreg<float>(code); | 457 return fpreg<float>(code); |
404 } | 458 } |
405 | 459 |
406 uint32_t sreg_bits(unsigned code) const { | 460 uint32_t sreg_bits(unsigned code) const { |
407 return fpreg<uint32_t>(code); | 461 return fpreg<uint32_t>(code); |
408 } | 462 } |
(...skipping 15 matching lines...) Expand all Loading... |
424 return 0.0; | 478 return 0.0; |
425 } | 479 } |
426 } | 480 } |
427 | 481 |
428 // Write 'value' into a floating-point register. The value is zero-extended. | 482 // Write 'value' into a floating-point register. The value is zero-extended. |
429 // This behaviour matches AArch64 register writes. | 483 // This behaviour matches AArch64 register writes. |
430 template<typename T> | 484 template<typename T> |
431 void set_fpreg(unsigned code, T value) { | 485 void set_fpreg(unsigned code, T value) { |
432 ASSERT((sizeof(value) == kDRegSize) || (sizeof(value) == kSRegSize)); | 486 ASSERT((sizeof(value) == kDRegSize) || (sizeof(value) == kSRegSize)); |
433 ASSERT(code < kNumberOfFPRegisters); | 487 ASSERT(code < kNumberOfFPRegisters); |
434 fpregisters_[code].Set(value); | 488 fpregisters_[code].Set(value, sizeof(value)); |
435 } | 489 } |
436 | 490 |
437 // Common specialized accessors for the set_fpreg() template. | 491 // Common specialized accessors for the set_fpreg() template. |
438 void set_sreg(unsigned code, float value) { | 492 void set_sreg(unsigned code, float value) { |
439 set_fpreg(code, value); | 493 set_fpreg(code, value); |
440 } | 494 } |
441 | 495 |
442 void set_sreg_bits(unsigned code, uint32_t value) { | 496 void set_sreg_bits(unsigned code, uint32_t value) { |
443 set_fpreg(code, value); | 497 set_fpreg(code, value); |
444 } | 498 } |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
564 default: | 618 default: |
565 UNREACHABLE(); | 619 UNREACHABLE(); |
566 return false; | 620 return false; |
567 } | 621 } |
568 } | 622 } |
569 | 623 |
570 bool ConditionFailed(Condition cond) { | 624 bool ConditionFailed(Condition cond) { |
571 return !ConditionPassed(cond); | 625 return !ConditionPassed(cond); |
572 } | 626 } |
573 | 627 |
574 template<typename T> | 628 void AddSubHelper(Instruction* instr, int64_t op2); |
575 void AddSubHelper(Instruction* instr, T op2); | 629 int64_t AddWithCarry(unsigned reg_size, |
576 template<typename T> | 630 bool set_flags, |
577 T AddWithCarry(bool set_flags, | 631 int64_t src1, |
578 T src1, | 632 int64_t src2, |
579 T src2, | 633 int64_t carry_in = 0); |
580 T carry_in = 0); | 634 void LogicalHelper(Instruction* instr, int64_t op2); |
581 template<typename T> | 635 void ConditionalCompareHelper(Instruction* instr, int64_t op2); |
582 void AddSubWithCarry(Instruction* instr); | |
583 template<typename T> | |
584 void LogicalHelper(Instruction* instr, T op2); | |
585 template<typename T> | |
586 void ConditionalCompareHelper(Instruction* instr, T op2); | |
587 void LoadStoreHelper(Instruction* instr, | 636 void LoadStoreHelper(Instruction* instr, |
588 int64_t offset, | 637 int64_t offset, |
589 AddrMode addrmode); | 638 AddrMode addrmode); |
590 void LoadStorePairHelper(Instruction* instr, AddrMode addrmode); | 639 void LoadStorePairHelper(Instruction* instr, AddrMode addrmode); |
591 uint8_t* LoadStoreAddress(unsigned addr_reg, | 640 uint8_t* LoadStoreAddress(unsigned addr_reg, |
592 int64_t offset, | 641 int64_t offset, |
593 AddrMode addrmode); | 642 AddrMode addrmode); |
594 void LoadStoreWriteBack(unsigned addr_reg, | 643 void LoadStoreWriteBack(unsigned addr_reg, |
595 int64_t offset, | 644 int64_t offset, |
596 AddrMode addrmode); | 645 AddrMode addrmode); |
597 void CheckMemoryAccess(uint8_t* address, uint8_t* stack); | 646 void CheckMemoryAccess(uint8_t* address, uint8_t* stack); |
598 | 647 |
599 uint64_t MemoryRead(uint8_t* address, unsigned num_bytes); | 648 uint64_t MemoryRead(uint8_t* address, unsigned num_bytes); |
600 uint8_t MemoryRead8(uint8_t* address); | 649 uint8_t MemoryRead8(uint8_t* address); |
601 uint16_t MemoryRead16(uint8_t* address); | 650 uint16_t MemoryRead16(uint8_t* address); |
602 uint32_t MemoryRead32(uint8_t* address); | 651 uint32_t MemoryRead32(uint8_t* address); |
603 float MemoryReadFP32(uint8_t* address); | 652 float MemoryReadFP32(uint8_t* address); |
604 uint64_t MemoryRead64(uint8_t* address); | 653 uint64_t MemoryRead64(uint8_t* address); |
605 double MemoryReadFP64(uint8_t* address); | 654 double MemoryReadFP64(uint8_t* address); |
606 | 655 |
607 void MemoryWrite(uint8_t* address, uint64_t value, unsigned num_bytes); | 656 void MemoryWrite(uint8_t* address, uint64_t value, unsigned num_bytes); |
608 void MemoryWrite32(uint8_t* address, uint32_t value); | 657 void MemoryWrite32(uint8_t* address, uint32_t value); |
609 void MemoryWriteFP32(uint8_t* address, float value); | 658 void MemoryWriteFP32(uint8_t* address, float value); |
610 void MemoryWrite64(uint8_t* address, uint64_t value); | 659 void MemoryWrite64(uint8_t* address, uint64_t value); |
611 void MemoryWriteFP64(uint8_t* address, double value); | 660 void MemoryWriteFP64(uint8_t* address, double value); |
612 | 661 |
613 | 662 int64_t ShiftOperand(unsigned reg_size, |
614 template <typename T> | 663 int64_t value, |
615 T ShiftOperand(T value, | 664 Shift shift_type, |
| 665 unsigned amount); |
| 666 int64_t Rotate(unsigned reg_width, |
| 667 int64_t value, |
616 Shift shift_type, | 668 Shift shift_type, |
617 unsigned amount); | 669 unsigned amount); |
618 template <typename T> | 670 int64_t ExtendValue(unsigned reg_width, |
619 T ExtendValue(T value, | 671 int64_t value, |
620 Extend extend_type, | 672 Extend extend_type, |
621 unsigned left_shift = 0); | 673 unsigned left_shift = 0); |
622 template <typename T> | |
623 void Extract(Instruction* instr); | |
624 template <typename T> | |
625 void DataProcessing2Source(Instruction* instr); | |
626 template <typename T> | |
627 void BitfieldHelper(Instruction* instr); | |
628 | 674 |
629 uint64_t ReverseBits(uint64_t value, unsigned num_bits); | 675 uint64_t ReverseBits(uint64_t value, unsigned num_bits); |
630 uint64_t ReverseBytes(uint64_t value, ReverseByteMode mode); | 676 uint64_t ReverseBytes(uint64_t value, ReverseByteMode mode); |
631 | 677 |
632 template <typename T> | 678 template <typename T> |
633 T FPDefaultNaN() const; | 679 T FPDefaultNaN() const; |
634 | 680 |
635 void FPCompare(double val0, double val1); | 681 void FPCompare(double val0, double val1); |
636 double FPRoundInt(double value, FPRounding round_mode); | 682 double FPRoundInt(double value, FPRounding round_mode); |
637 double FPToDouble(float value); | 683 double FPToDouble(float value); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
743 // functions, or to save and restore it when entering and leaving generated | 789 // functions, or to save and restore it when entering and leaving generated |
744 // code. | 790 // code. |
745 void AssertSupportedFPCR() { | 791 void AssertSupportedFPCR() { |
746 ASSERT(fpcr().FZ() == 0); // No flush-to-zero support. | 792 ASSERT(fpcr().FZ() == 0); // No flush-to-zero support. |
747 ASSERT(fpcr().RMode() == FPTieEven); // Ties-to-even rounding only. | 793 ASSERT(fpcr().RMode() == FPTieEven); // Ties-to-even rounding only. |
748 | 794 |
749 // The simulator does not support half-precision operations so fpcr().AHP() | 795 // The simulator does not support half-precision operations so fpcr().AHP() |
750 // is irrelevant, and is not checked here. | 796 // is irrelevant, and is not checked here. |
751 } | 797 } |
752 | 798 |
753 template <typename T> | 799 static int CalcNFlag(uint64_t result, unsigned reg_size) { |
754 static int CalcNFlag(T result) { | 800 return (result >> (reg_size - 1)) & 1; |
755 return (result >> (sizeof(T) * 8 - 1)) & 1; | |
756 } | 801 } |
757 | 802 |
758 static int CalcZFlag(uint64_t result) { | 803 static int CalcZFlag(uint64_t result) { |
759 return result == 0; | 804 return result == 0; |
760 } | 805 } |
761 | 806 |
762 static const uint32_t kConditionFlagsMask = 0xf0000000; | 807 static const uint32_t kConditionFlagsMask = 0xf0000000; |
763 | 808 |
764 // Stack | 809 // Stack |
765 byte* stack_; | 810 byte* stack_; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
828 static void UnregisterCTryCatch() { | 873 static void UnregisterCTryCatch() { |
829 Simulator::current(Isolate::Current())->PopAddress(); | 874 Simulator::current(Isolate::Current())->PopAddress(); |
830 } | 875 } |
831 }; | 876 }; |
832 | 877 |
833 #endif // !defined(USE_SIMULATOR) | 878 #endif // !defined(USE_SIMULATOR) |
834 | 879 |
835 } } // namespace v8::internal | 880 } } // namespace v8::internal |
836 | 881 |
837 #endif // V8_ARM64_SIMULATOR_ARM64_H_ | 882 #endif // V8_ARM64_SIMULATOR_ARM64_H_ |
OLD | NEW |