| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 #include <math.h> // for isnan. | 5 #include <math.h> // for isnan. |
| 6 #include <setjmp.h> | 6 #include <setjmp.h> |
| 7 #include <stdlib.h> | 7 #include <stdlib.h> |
| 8 | 8 |
| 9 #include "vm/globals.h" | 9 #include "vm/globals.h" |
| 10 #if defined(TARGET_ARCH_ARM64) | 10 #if defined(TARGET_ARCH_ARM64) |
| (...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 521 } | 521 } |
| 522 | 522 |
| 523 if (out_size == kXRegSizeInBits) { | 523 if (out_size == kXRegSizeInBits) { |
| 524 set_register(rd, alu_out, instr->RdMode()); | 524 set_register(rd, alu_out, instr->RdMode()); |
| 525 } else { | 525 } else { |
| 526 set_wregister(rd, alu_out, instr->RdMode()); | 526 set_wregister(rd, alu_out, instr->RdMode()); |
| 527 } | 527 } |
| 528 } | 528 } |
| 529 | 529 |
| 530 | 530 |
| 531 void Simulator::DecodePCRel(Instr* instr) { |
| 532 const int op = instr->Bit(31); |
| 533 if (op == 0) { |
| 534 // Format(instr, "adr 'rd, 'pcrel") |
| 535 const Register rd = instr->RdField(); |
| 536 const int64_t immhi = instr->SImm19Field(); |
| 537 const int64_t immlo = instr->Bits(29, 2); |
| 538 const int64_t off = (immhi << 2) | immlo; |
| 539 const int64_t dest = get_pc() + off; |
| 540 set_register(rd, dest, instr->RdMode()); |
| 541 } else { |
| 542 UnimplementedInstruction(instr); |
| 543 } |
| 544 } |
| 545 |
| 546 |
| 531 void Simulator::DecodeDPImmediate(Instr* instr) { | 547 void Simulator::DecodeDPImmediate(Instr* instr) { |
| 532 if (instr->IsMoveWideOp()) { | 548 if (instr->IsMoveWideOp()) { |
| 533 DecodeMoveWide(instr); | 549 DecodeMoveWide(instr); |
| 534 } else if (instr->IsAddSubImmOp()) { | 550 } else if (instr->IsAddSubImmOp()) { |
| 535 DecodeAddSubImm(instr); | 551 DecodeAddSubImm(instr); |
| 536 } else if (instr->IsLogicalImmOp()) { | 552 } else if (instr->IsLogicalImmOp()) { |
| 537 DecodeLogicalImm(instr); | 553 DecodeLogicalImm(instr); |
| 554 } else if (instr->IsPCRelOp()) { |
| 555 DecodePCRel(instr); |
| 538 } else { | 556 } else { |
| 539 UnimplementedInstruction(instr); | 557 UnimplementedInstruction(instr); |
| 540 } | 558 } |
| 541 } | 559 } |
| 542 | 560 |
| 543 | 561 |
| 562 void Simulator::DecodeCompareAndBranch(Instr* instr) { |
| 563 const int op = instr->Bit(24); |
| 564 const Register rt = instr->RtField(); |
| 565 const int64_t imm19 = instr->SImm19Field(); |
| 566 const int64_t dest = get_pc() + (imm19 << 2); |
| 567 const int64_t mask = instr->SFField() == 1 ? kXRegMask : kWRegMask; |
| 568 const int64_t rt_val = get_register(rt, R31IsZR) & mask; |
| 569 if (op == 0) { |
| 570 // Format(instr, "cbz'sf 'rt, 'dest19"); |
| 571 if (rt_val == 0) { |
| 572 set_pc(dest); |
| 573 } |
| 574 } else { |
| 575 // Format(instr, "cbnz'sf 'rt, 'dest19"); |
| 576 if (rt_val != 0) { |
| 577 set_pc(dest); |
| 578 } |
| 579 } |
| 580 } |
| 581 |
| 582 |
| 583 bool Simulator::ConditionallyExecute(Instr* instr) { |
| 584 switch (instr->ConditionField()) { |
| 585 case EQ: return z_flag_; |
| 586 case NE: return !z_flag_; |
| 587 case CS: return c_flag_; |
| 588 case CC: return !c_flag_; |
| 589 case MI: return n_flag_; |
| 590 case PL: return !n_flag_; |
| 591 case VS: return v_flag_; |
| 592 case VC: return !v_flag_; |
| 593 case HI: return c_flag_ && !z_flag_; |
| 594 case LS: return !c_flag_ || z_flag_; |
| 595 case GE: return n_flag_ == v_flag_; |
| 596 case LT: return n_flag_ != v_flag_; |
| 597 case GT: return !z_flag_ && (n_flag_ == v_flag_); |
| 598 case LE: return z_flag_ || (n_flag_ != v_flag_); |
| 599 case AL: return true; |
| 600 default: UNREACHABLE(); |
| 601 } |
| 602 return false; |
| 603 } |
| 604 |
| 605 |
| 606 void Simulator::DecodeConditionalBranch(Instr* instr) { |
| 607 // Format(instr, "b'cond 'dest19"); |
| 608 if ((instr->Bit(24) != 0) || (instr->Bit(4) != 0)) { |
| 609 UnimplementedInstruction(instr); |
| 610 } |
| 611 const int64_t imm19 = instr->SImm19Field(); |
| 612 const int64_t dest = get_pc() + (imm19 << 2); |
| 613 if (ConditionallyExecute(instr)) { |
| 614 set_pc(dest); |
| 615 } |
| 616 } |
| 617 |
| 618 |
| 544 void Simulator::DecodeExceptionGen(Instr* instr) { | 619 void Simulator::DecodeExceptionGen(Instr* instr) { |
| 545 UnimplementedInstruction(instr); | 620 UnimplementedInstruction(instr); |
| 546 } | 621 } |
| 547 | 622 |
| 548 | 623 |
| 549 void Simulator::DecodeSystem(Instr* instr) { | 624 void Simulator::DecodeSystem(Instr* instr) { |
| 550 if ((instr->Bits(0, 8) == 0x5f) && (instr->Bits(12, 4) == 2) && | 625 if ((instr->Bits(0, 8) == 0x5f) && (instr->Bits(12, 4) == 2) && |
| 551 (instr->Bits(16, 3) == 3) && (instr->Bits(19, 2) == 0) && | 626 (instr->Bits(16, 3) == 3) && (instr->Bits(19, 2) == 0) && |
| 552 (instr->Bit(21) == 0)) { | 627 (instr->Bit(21) == 0)) { |
| 553 if (instr->Bits(8, 4) == 0) { | 628 if (instr->Bits(8, 4) == 0) { |
| 554 // Format(instr, "nop"); | 629 // Format(instr, "nop"); |
| 555 } else { | 630 } else { |
| 556 UnimplementedInstruction(instr); | 631 UnimplementedInstruction(instr); |
| 557 } | 632 } |
| 558 } else { | 633 } else { |
| 559 UnimplementedInstruction(instr); | 634 UnimplementedInstruction(instr); |
| 560 } | 635 } |
| 561 } | 636 } |
| 562 | 637 |
| 563 | 638 |
| 639 void Simulator::DecodeTestAndBranch(Instr* instr) { |
| 640 const int op = instr->Bit(24); |
| 641 const int bitpos = instr->Bits(19, 4) | (instr->Bit(31) << 5); |
| 642 const int64_t imm14 = instr->SImm14Field(); |
| 643 const int64_t dest = get_pc() + (imm14 << 2); |
| 644 const Register rt = instr->RtField(); |
| 645 const int64_t rt_val = get_register(rt, R31IsZR); |
| 646 if (op == 0) { |
| 647 // Format(instr, "tbz'sf 'rt, 'bitpos, 'dest14"); |
| 648 if ((rt_val & (1 << bitpos)) == 0) { |
| 649 set_pc(dest); |
| 650 } |
| 651 } else { |
| 652 // Format(instr, "tbnz'sf 'rt, 'bitpos, 'dest14"); |
| 653 if ((rt_val & (1 << bitpos)) != 0) { |
| 654 set_pc(dest); |
| 655 } |
| 656 } |
| 657 } |
| 658 |
| 659 |
| 660 void Simulator::DecodeUnconditionalBranch(Instr* instr) { |
| 661 const bool link = instr->Bit(31) == 1; |
| 662 const int64_t imm26 = instr->SImm26Field(); |
| 663 const int64_t dest = get_pc() + (imm26 << 2); |
| 664 const int64_t ret = get_pc() + Instr::kInstrSize; |
| 665 set_pc(dest); |
| 666 if (link) { |
| 667 set_register(LR, ret); |
| 668 } |
| 669 } |
| 670 |
| 671 |
| 564 void Simulator::DecodeUnconditionalBranchReg(Instr* instr) { | 672 void Simulator::DecodeUnconditionalBranchReg(Instr* instr) { |
| 565 if ((instr->Bits(0, 5) == 0) && (instr->Bits(10, 6) == 0) && | 673 if ((instr->Bits(0, 5) == 0) && (instr->Bits(10, 6) == 0) && |
| 566 (instr->Bits(16, 5) == 0x1f)) { | 674 (instr->Bits(16, 5) == 0x1f)) { |
| 567 switch (instr->Bits(21, 4)) { | 675 switch (instr->Bits(21, 4)) { |
| 676 case 0: { |
| 677 // Format(instr, "br 'rn"); |
| 678 const Register rn = instr->RnField(); |
| 679 const int64_t dest = get_register(rn, instr->RnMode()); |
| 680 set_pc(dest); |
| 681 break; |
| 682 } |
| 683 case 1: { |
| 684 // Format(instr, "blr 'rn"); |
| 685 const Register rn = instr->RnField(); |
| 686 const int64_t dest = get_register(rn, instr->RnMode()); |
| 687 const int64_t ret = get_pc() + Instr::kInstrSize; |
| 688 set_pc(dest); |
| 689 set_register(LR, ret); |
| 690 break; |
| 691 } |
| 568 case 2: { | 692 case 2: { |
| 569 // Format(instr, "ret 'rn"); | 693 // Format(instr, "ret 'rn"); |
| 570 const Register rn = instr->RnField(); | 694 const Register rn = instr->RnField(); |
| 571 const int64_t rn_val = get_register(rn, instr->RnMode()); | 695 const int64_t rn_val = get_register(rn, instr->RnMode()); |
| 572 set_pc(rn_val); | 696 set_pc(rn_val); |
| 573 break; | 697 break; |
| 574 } | 698 } |
| 575 default: | 699 default: |
| 576 UnimplementedInstruction(instr); | 700 UnimplementedInstruction(instr); |
| 577 break; | 701 break; |
| 578 } | 702 } |
| 579 } else { | 703 } else { |
| 580 UnimplementedInstruction(instr); | 704 UnimplementedInstruction(instr); |
| 581 } | 705 } |
| 582 } | 706 } |
| 583 | 707 |
| 584 | 708 |
| 585 void Simulator::DecodeCompareBranch(Instr* instr) { | 709 void Simulator::DecodeCompareBranch(Instr* instr) { |
| 586 if (instr->IsExceptionGenOp()) { | 710 if (instr->IsCompareAndBranchOp()) { |
| 711 DecodeCompareAndBranch(instr); |
| 712 } else if (instr->IsConditionalBranchOp()) { |
| 713 DecodeConditionalBranch(instr); |
| 714 } else if (instr->IsExceptionGenOp()) { |
| 587 DecodeExceptionGen(instr); | 715 DecodeExceptionGen(instr); |
| 588 } else if (instr->IsSystemOp()) { | 716 } else if (instr->IsSystemOp()) { |
| 589 DecodeSystem(instr); | 717 DecodeSystem(instr); |
| 718 } else if (instr->IsTestAndBranchOp()) { |
| 719 DecodeTestAndBranch(instr); |
| 720 } else if (instr->IsUnconditionalBranchOp()) { |
| 721 DecodeUnconditionalBranch(instr); |
| 590 } else if (instr->IsUnconditionalBranchRegOp()) { | 722 } else if (instr->IsUnconditionalBranchRegOp()) { |
| 591 DecodeUnconditionalBranchReg(instr); | 723 DecodeUnconditionalBranchReg(instr); |
| 592 } else { | 724 } else { |
| 593 UnimplementedInstruction(instr); | 725 UnimplementedInstruction(instr); |
| 594 } | 726 } |
| 595 } | 727 } |
| 596 | 728 |
| 597 | 729 |
| 598 void Simulator::DecodeLoadStoreReg(Instr* instr) { | 730 void Simulator::DecodeLoadStoreReg(Instr* instr) { |
| 599 // TODO(zra): SIMD loads and stores have bit 26 (V) set. | 731 // TODO(zra): SIMD loads and stores have bit 26 (V) set. |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 804 value = (value << 48) >> 48; | 936 value = (value << 48) >> 48; |
| 805 break; | 937 break; |
| 806 case SXTW: | 938 case SXTW: |
| 807 value = (value << 32) >> 32; | 939 value = (value << 32) >> 32; |
| 808 break; | 940 break; |
| 809 case UXTX: | 941 case UXTX: |
| 810 case SXTX: | 942 case SXTX: |
| 811 break; | 943 break; |
| 812 default: | 944 default: |
| 813 UNREACHABLE(); | 945 UNREACHABLE(); |
| 946 break; |
| 814 } | 947 } |
| 815 int64_t mask = (reg_size == kXRegSizeInBits) ? kXRegMask : kWRegMask; | 948 int64_t mask = (reg_size == kXRegSizeInBits) ? kXRegMask : kWRegMask; |
| 816 return (value << amount) & mask; | 949 return (value << amount) & mask; |
| 817 } | 950 } |
| 818 | 951 |
| 819 | 952 |
| 820 int64_t Simulator::DecodeShiftExtendOperand(Instr* instr) { | 953 int64_t Simulator::DecodeShiftExtendOperand(Instr* instr) { |
| 821 const Register rm = instr->RmField(); | 954 const Register rm = instr->RmField(); |
| 822 const int64_t rm_val = get_register(rm, R31IsZR); | 955 const int64_t rm_val = get_register(rm, R31IsZR); |
| 823 const uint8_t size = instr->SFField() ? kXRegSizeInBits : kWRegSizeInBits; | 956 const uint8_t size = instr->SFField() ? kXRegSizeInBits : kWRegSizeInBits; |
| 824 if (instr->IsShift()) { | 957 if (instr->IsShift()) { |
| 825 const Shift shift_type = instr->ShiftTypeField(); | 958 const Shift shift_type = instr->ShiftTypeField(); |
| 826 const uint8_t shift_amount = instr->Imm6Field(); | 959 const uint8_t shift_amount = instr->Imm6Field(); |
| 827 return ShiftOperand(size, rm_val, shift_type, shift_amount); | 960 return ShiftOperand(size, rm_val, shift_type, shift_amount); |
| 828 } else { | 961 } else { |
| 829 ASSERT(instr->IsExtend()); | 962 ASSERT(instr->IsExtend()); |
| 830 const Extend extend_type = instr->ExtendTypeField(); | 963 const Extend extend_type = instr->ExtendTypeField(); |
| 831 const uint8_t shift_amount = instr->Imm3Field(); | 964 const uint8_t shift_amount = instr->Imm3Field(); |
| 832 return ExtendOperand(size, rm_val, extend_type, shift_amount); | 965 return ExtendOperand(size, rm_val, extend_type, shift_amount); |
| 833 } | 966 } |
| 834 UNREACHABLE(); | 967 UNREACHABLE(); |
| 835 return -1; | 968 return -1; |
| 836 } | 969 } |
| 837 | 970 |
| 838 | 971 |
| 839 void Simulator::DecodeAddSubShiftExt(Instr* instr) { | 972 void Simulator::DecodeAddSubShiftExt(Instr* instr) { |
| 840 switch (instr->Bit(30)) { | 973 // Format(instr, "add'sf's 'rd, 'rn, 'shift_op"); |
| 841 case 0: { | 974 // also, sub, cmp, etc. |
| 842 // Format(instr, "add'sf's 'rd, 'rn, 'shift_op"); | 975 const bool subtract = instr->Bit(30) == 1; |
| 843 const Register rd = instr->RdField(); | 976 const Register rd = instr->RdField(); |
| 844 const Register rn = instr->RnField(); | 977 const Register rn = instr->RnField(); |
| 845 const int64_t rm_val = DecodeShiftExtendOperand(instr); | 978 const int64_t rm_val = DecodeShiftExtendOperand(instr); |
| 846 if (instr->SFField()) { | 979 if (instr->SFField()) { |
| 847 // 64-bit add. | 980 // 64-bit add. |
| 848 const int64_t rn_val = get_register(rn, instr->RnMode()); | 981 const int64_t rn_val = get_register(rn, instr->RnMode()); |
| 849 const int64_t alu_out = rn_val + rm_val; | 982 int64_t alu_out = 0; |
| 850 set_register(rd, alu_out, instr->RdMode()); | 983 if (subtract) { |
| 851 if (instr->HasS()) { | 984 alu_out = rn_val - rm_val; |
| 852 SetNZFlagsX(alu_out); | 985 } else { |
| 853 SetCFlag(CarryFromX(rn_val, rm_val)); | 986 alu_out = rn_val + rm_val; |
| 854 SetVFlag(OverflowFromX(alu_out, rn_val, rm_val, true)); | |
| 855 } | |
| 856 } else { | |
| 857 // 32-bit add. | |
| 858 const int32_t rn_val = get_wregister(rn, instr->RnMode()); | |
| 859 const int32_t rm_val32 = static_cast<int32_t>(rm_val & kWRegMask); | |
| 860 const int32_t alu_out = rn_val + rm_val32; | |
| 861 set_wregister(rd, alu_out, instr->RdMode()); | |
| 862 if (instr->HasS()) { | |
| 863 SetNZFlagsW(alu_out); | |
| 864 SetCFlag(CarryFromW(rn_val, rm_val32)); | |
| 865 SetVFlag(OverflowFromW(alu_out, rn_val, rm_val32, true)); | |
| 866 } | |
| 867 } | |
| 868 break; | |
| 869 } | 987 } |
| 870 default: | 988 set_register(rd, alu_out, instr->RdMode()); |
| 871 UnimplementedInstruction(instr); | 989 if (instr->HasS()) { |
| 872 break; | 990 SetNZFlagsX(alu_out); |
| 991 SetCFlag(CarryFromX(rn_val, rm_val)); |
| 992 SetVFlag(OverflowFromX(alu_out, rn_val, rm_val, !subtract)); |
| 993 } |
| 994 } else { |
| 995 // 32-bit add. |
| 996 const int32_t rn_val = get_wregister(rn, instr->RnMode()); |
| 997 const int32_t rm_val32 = static_cast<int32_t>(rm_val & kWRegMask); |
| 998 int32_t alu_out = 0; |
| 999 if (subtract) { |
| 1000 alu_out = rn_val - rm_val32; |
| 1001 } else { |
| 1002 alu_out = rn_val + rm_val32; |
| 1003 } |
| 1004 set_wregister(rd, alu_out, instr->RdMode()); |
| 1005 if (instr->HasS()) { |
| 1006 SetNZFlagsW(alu_out); |
| 1007 SetCFlag(CarryFromW(rn_val, rm_val32)); |
| 1008 SetVFlag(OverflowFromW(alu_out, rn_val, rm_val32, !subtract)); |
| 1009 } |
| 873 } | 1010 } |
| 874 } | 1011 } |
| 875 | 1012 |
| 876 | 1013 |
| 877 void Simulator::DecodeLogicalShift(Instr* instr) { | 1014 void Simulator::DecodeLogicalShift(Instr* instr) { |
| 878 const int op = (instr->Bits(29, 2) << 1) | instr->Bit(21); | 1015 const int op = (instr->Bits(29, 2) << 1) | instr->Bit(21); |
| 879 const Register rd = instr->RdField(); | 1016 const Register rd = instr->RdField(); |
| 880 const Register rn = instr->RnField(); | 1017 const Register rn = instr->RnField(); |
| 881 const int64_t rn_val = get_register(rn, instr->RnMode()); | 1018 const int64_t rn_val = get_register(rn, instr->RnMode()); |
| 882 const int64_t rm_val = DecodeShiftExtendOperand(instr); | 1019 const int64_t rm_val = DecodeShiftExtendOperand(instr); |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1118 int64_t return_value; | 1255 int64_t return_value; |
| 1119 return_value = get_register(R0); | 1256 return_value = get_register(R0); |
| 1120 return return_value; | 1257 return return_value; |
| 1121 } | 1258 } |
| 1122 | 1259 |
| 1123 } // namespace dart | 1260 } // namespace dart |
| 1124 | 1261 |
| 1125 #endif // !defined(HOST_ARCH_ARM64) | 1262 #endif // !defined(HOST_ARCH_ARM64) |
| 1126 | 1263 |
| 1127 #endif // defined TARGET_ARCH_ARM64 | 1264 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |