OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 901 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
912 } | 912 } |
913 | 913 |
914 | 914 |
915 void Simulator::set_dw_register(int dreg, const int* dbl) { | 915 void Simulator::set_dw_register(int dreg, const int* dbl) { |
916 ASSERT((dreg >= 0) && (dreg < num_d_registers)); | 916 ASSERT((dreg >= 0) && (dreg < num_d_registers)); |
917 registers_[dreg] = dbl[0]; | 917 registers_[dreg] = dbl[0]; |
918 registers_[dreg + 1] = dbl[1]; | 918 registers_[dreg + 1] = dbl[1]; |
919 } | 919 } |
920 | 920 |
921 | 921 |
| 922 void Simulator::get_d_register(int dreg, uint64_t* value) { |
| 923 ASSERT((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters())); |
| 924 memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value)); |
| 925 } |
| 926 |
| 927 |
| 928 void Simulator::set_d_register(int dreg, const uint64_t* value) { |
| 929 ASSERT((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters())); |
| 930 memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value)); |
| 931 } |
| 932 |
| 933 |
| 934 void Simulator::get_d_register(int dreg, uint32_t* value) { |
| 935 ASSERT((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters())); |
| 936 memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value) * 2); |
| 937 } |
| 938 |
| 939 |
| 940 void Simulator::set_d_register(int dreg, const uint32_t* value) { |
| 941 ASSERT((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters())); |
| 942 memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value) * 2); |
| 943 } |
| 944 |
| 945 |
| 946 void Simulator::get_q_register(int qreg, uint64_t* value) { |
| 947 ASSERT((qreg >= 0) && (qreg < num_q_registers)); |
| 948 memcpy(value, vfp_registers_ + qreg * 4, sizeof(*value) * 2); |
| 949 } |
| 950 |
| 951 |
| 952 void Simulator::set_q_register(int qreg, const uint64_t* value) { |
| 953 ASSERT((qreg >= 0) && (qreg < num_q_registers)); |
| 954 memcpy(vfp_registers_ + qreg * 4, value, sizeof(*value) * 2); |
| 955 } |
| 956 |
| 957 |
| 958 void Simulator::get_q_register(int qreg, uint32_t* value) { |
| 959 ASSERT((qreg >= 0) && (qreg < num_q_registers)); |
| 960 memcpy(value, vfp_registers_ + qreg * 4, sizeof(*value) * 4); |
| 961 } |
| 962 |
| 963 |
| 964 void Simulator::set_q_register(int qreg, const uint32_t* value) { |
| 965 ASSERT((qreg >= 0) && (qreg < num_q_registers)); |
| 966 memcpy(vfp_registers_ + qreg * 4, value, sizeof(*value) * 4); |
| 967 } |
| 968 |
| 969 |
922 // Raw access to the PC register. | 970 // Raw access to the PC register. |
923 void Simulator::set_pc(int32_t value) { | 971 void Simulator::set_pc(int32_t value) { |
924 pc_modified_ = true; | 972 pc_modified_ = true; |
925 registers_[pc] = value; | 973 registers_[pc] = value; |
926 } | 974 } |
927 | 975 |
928 | 976 |
929 bool Simulator::has_bad_pc() const { | 977 bool Simulator::has_bad_pc() const { |
930 return ((registers_[pc] == bad_lr) || (registers_[pc] == end_sim_pc)); | 978 return ((registers_[pc] == bad_lr) || (registers_[pc] == end_sim_pc)); |
931 } | 979 } |
(...skipping 1657 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2589 int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out); | 2637 int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out); |
2590 int32_t addr = 0; | 2638 int32_t addr = 0; |
2591 switch (instr->PUField()) { | 2639 switch (instr->PUField()) { |
2592 case da_x: { | 2640 case da_x: { |
2593 ASSERT(!instr->HasW()); | 2641 ASSERT(!instr->HasW()); |
2594 Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm"); | 2642 Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm"); |
2595 UNIMPLEMENTED(); | 2643 UNIMPLEMENTED(); |
2596 break; | 2644 break; |
2597 } | 2645 } |
2598 case ia_x: { | 2646 case ia_x: { |
2599 if (instr->HasW()) { | 2647 if (instr->Bit(4) == 0) { |
2600 ASSERT(instr->Bits(5, 4) == 0x1); | 2648 // Memop. |
2601 | 2649 } else { |
2602 if (instr->Bit(22) == 0x1) { // USAT. | 2650 if (instr->Bit(5) == 0) { |
2603 int32_t sat_pos = instr->Bits(20, 16); | 2651 switch (instr->Bits(22, 21)) { |
2604 int32_t sat_val = (1 << sat_pos) - 1; | 2652 case 0: |
2605 int32_t shift = instr->Bits(11, 7); | 2653 if (instr->Bit(20) == 0) { |
2606 int32_t shift_type = instr->Bit(6); | 2654 if (instr->Bit(6) == 0) { |
2607 int32_t rm_val = get_register(instr->RmValue()); | 2655 // Pkhbt. |
2608 if (shift_type == 0) { // LSL | 2656 uint32_t rn_val = get_register(rn); |
2609 rm_val <<= shift; | 2657 uint32_t rm_val = get_register(instr->RmValue()); |
2610 } else { // ASR | 2658 int32_t shift = instr->Bits(11, 7); |
2611 rm_val >>= shift; | 2659 rm_val <<= shift; |
| 2660 set_register(rd, (rn_val & 0xFFFF) | (rm_val & 0xFFFF0000U)); |
| 2661 } else { |
| 2662 // Pkhtb. |
| 2663 uint32_t rn_val = get_register(rn); |
| 2664 int32_t rm_val = get_register(instr->RmValue()); |
| 2665 int32_t shift = instr->Bits(11, 7); |
| 2666 if (shift == 0) { |
| 2667 shift = 32; |
| 2668 } |
| 2669 rm_val >>= shift; |
| 2670 set_register(rd, (rn_val & 0xFFFF0000U) | (rm_val & 0xFFFF)); |
| 2671 } |
| 2672 } else { |
| 2673 UNIMPLEMENTED(); |
| 2674 } |
| 2675 break; |
| 2676 case 1: |
| 2677 UNIMPLEMENTED(); |
| 2678 break; |
| 2679 case 2: |
| 2680 UNIMPLEMENTED(); |
| 2681 break; |
| 2682 case 3: { |
| 2683 // Usat. |
| 2684 int32_t sat_pos = instr->Bits(20, 16); |
| 2685 int32_t sat_val = (1 << sat_pos) - 1; |
| 2686 int32_t shift = instr->Bits(11, 7); |
| 2687 int32_t shift_type = instr->Bit(6); |
| 2688 int32_t rm_val = get_register(instr->RmValue()); |
| 2689 if (shift_type == 0) { // LSL |
| 2690 rm_val <<= shift; |
| 2691 } else { // ASR |
| 2692 rm_val >>= shift; |
| 2693 } |
| 2694 // If saturation occurs, the Q flag should be set in the CPSR. |
| 2695 // There is no Q flag yet, and no instruction (MRS) to read the |
| 2696 // CPSR directly. |
| 2697 if (rm_val > sat_val) { |
| 2698 rm_val = sat_val; |
| 2699 } else if (rm_val < 0) { |
| 2700 rm_val = 0; |
| 2701 } |
| 2702 set_register(rd, rm_val); |
| 2703 break; |
| 2704 } |
2612 } | 2705 } |
2613 // If saturation occurs, the Q flag should be set in the CPSR. | 2706 } else { |
2614 // There is no Q flag yet, and no instruction (MRS) to read the | 2707 switch (instr->Bits(22, 21)) { |
2615 // CPSR directly. | 2708 case 0: |
2616 if (rm_val > sat_val) { | 2709 UNIMPLEMENTED(); |
2617 rm_val = sat_val; | 2710 break; |
2618 } else if (rm_val < 0) { | 2711 case 1: |
2619 rm_val = 0; | 2712 UNIMPLEMENTED(); |
| 2713 break; |
| 2714 case 2: |
| 2715 if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) { |
| 2716 if (instr->Bits(19, 16) == 0xF) { |
| 2717 // Uxtb16. |
| 2718 uint32_t rm_val = get_register(instr->RmValue()); |
| 2719 int32_t rotate = instr->Bits(11, 10); |
| 2720 switch (rotate) { |
| 2721 case 0: |
| 2722 break; |
| 2723 case 1: |
| 2724 rm_val = (rm_val >> 8) | (rm_val << 24); |
| 2725 break; |
| 2726 case 2: |
| 2727 rm_val = (rm_val >> 16) | (rm_val << 16); |
| 2728 break; |
| 2729 case 3: |
| 2730 rm_val = (rm_val >> 24) | (rm_val << 8); |
| 2731 break; |
| 2732 } |
| 2733 set_register(rd, |
| 2734 (rm_val & 0xFF) | (rm_val & 0xFF0000)); |
| 2735 } else { |
| 2736 UNIMPLEMENTED(); |
| 2737 } |
| 2738 } else { |
| 2739 UNIMPLEMENTED(); |
| 2740 } |
| 2741 break; |
| 2742 case 3: |
| 2743 if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) { |
| 2744 if (instr->Bits(19, 16) == 0xF) { |
| 2745 // Uxtb. |
| 2746 uint32_t rm_val = get_register(instr->RmValue()); |
| 2747 int32_t rotate = instr->Bits(11, 10); |
| 2748 switch (rotate) { |
| 2749 case 0: |
| 2750 break; |
| 2751 case 1: |
| 2752 rm_val = (rm_val >> 8) | (rm_val << 24); |
| 2753 break; |
| 2754 case 2: |
| 2755 rm_val = (rm_val >> 16) | (rm_val << 16); |
| 2756 break; |
| 2757 case 3: |
| 2758 rm_val = (rm_val >> 24) | (rm_val << 8); |
| 2759 break; |
| 2760 } |
| 2761 set_register(rd, (rm_val & 0xFF)); |
| 2762 } else { |
| 2763 // Uxtab. |
| 2764 uint32_t rn_val = get_register(rn); |
| 2765 uint32_t rm_val = get_register(instr->RmValue()); |
| 2766 int32_t rotate = instr->Bits(11, 10); |
| 2767 switch (rotate) { |
| 2768 case 0: |
| 2769 break; |
| 2770 case 1: |
| 2771 rm_val = (rm_val >> 8) | (rm_val << 24); |
| 2772 break; |
| 2773 case 2: |
| 2774 rm_val = (rm_val >> 16) | (rm_val << 16); |
| 2775 break; |
| 2776 case 3: |
| 2777 rm_val = (rm_val >> 24) | (rm_val << 8); |
| 2778 break; |
| 2779 } |
| 2780 set_register(rd, rn_val + (rm_val & 0xFF)); |
| 2781 } |
| 2782 } else { |
| 2783 UNIMPLEMENTED(); |
| 2784 } |
| 2785 break; |
2620 } | 2786 } |
2621 set_register(rd, rm_val); | |
2622 } else { // SSAT. | |
2623 UNIMPLEMENTED(); | |
2624 } | 2787 } |
2625 return; | 2788 return; |
2626 } else { | |
2627 Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm"); | |
2628 UNIMPLEMENTED(); | |
2629 } | 2789 } |
2630 break; | 2790 break; |
2631 } | 2791 } |
2632 case db_x: { | 2792 case db_x: { |
2633 if (FLAG_enable_sudiv) { | 2793 if (FLAG_enable_sudiv) { |
2634 if (!instr->HasW()) { | 2794 if (!instr->HasW()) { |
2635 if (instr->Bits(5, 4) == 0x1) { | 2795 if (instr->Bits(5, 4) == 0x1) { |
2636 if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) { | 2796 if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) { |
2637 // sdiv (in V8 notation matching ARM ISA format) rn = rm/rs | 2797 // sdiv (in V8 notation matching ARM ISA format) rn = rm/rs |
2638 // Format(instr, "'sdiv'cond'b 'rn, 'rm, 'rs); | 2798 // Format(instr, "'sdiv'cond'b 'rn, 'rm, 'rs); |
(...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3342 break; | 3502 break; |
3343 default: | 3503 default: |
3344 UNIMPLEMENTED(); // Not used by V8. | 3504 UNIMPLEMENTED(); // Not used by V8. |
3345 } | 3505 } |
3346 } else { | 3506 } else { |
3347 UNIMPLEMENTED(); // Not used by V8. | 3507 UNIMPLEMENTED(); // Not used by V8. |
3348 } | 3508 } |
3349 } | 3509 } |
3350 | 3510 |
3351 | 3511 |
| 3512 void Simulator::DecodeSpecialCondition(Instruction* instr) { |
| 3513 switch (instr->SpecialValue()) { |
| 3514 case 5: |
| 3515 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) && |
| 3516 (instr->Bit(4) == 1)) { |
| 3517 // vmovl signed |
| 3518 int Vd = (instr->Bit(22) << 4) | instr->VdValue(); |
| 3519 int Vm = (instr->Bit(5) << 4) | instr->VmValue(); |
| 3520 int imm3 = instr->Bits(21, 19); |
| 3521 if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED(); |
| 3522 int esize = 8 * imm3; |
| 3523 int elements = 64 / esize; |
| 3524 int8_t from[8]; |
| 3525 get_d_register(Vm, reinterpret_cast<uint64_t*>(from)); |
| 3526 int16_t to[8]; |
| 3527 int e = 0; |
| 3528 while (e < elements) { |
| 3529 to[e] = from[e]; |
| 3530 e++; |
| 3531 } |
| 3532 set_q_register(Vd, reinterpret_cast<uint64_t*>(to)); |
| 3533 } else { |
| 3534 UNIMPLEMENTED(); |
| 3535 } |
| 3536 break; |
| 3537 case 7: |
| 3538 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) && |
| 3539 (instr->Bit(4) == 1)) { |
| 3540 // vmovl unsigned |
| 3541 int Vd = (instr->Bit(22) << 4) | instr->VdValue(); |
| 3542 int Vm = (instr->Bit(5) << 4) | instr->VmValue(); |
| 3543 int imm3 = instr->Bits(21, 19); |
| 3544 if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED(); |
| 3545 int esize = 8 * imm3; |
| 3546 int elements = 64 / esize; |
| 3547 uint8_t from[8]; |
| 3548 get_d_register(Vm, reinterpret_cast<uint64_t*>(from)); |
| 3549 uint16_t to[8]; |
| 3550 int e = 0; |
| 3551 while (e < elements) { |
| 3552 to[e] = from[e]; |
| 3553 e++; |
| 3554 } |
| 3555 set_q_register(Vd, reinterpret_cast<uint64_t*>(to)); |
| 3556 } else { |
| 3557 UNIMPLEMENTED(); |
| 3558 } |
| 3559 break; |
| 3560 case 8: |
| 3561 if (instr->Bits(21, 20) == 0) { |
| 3562 // vst1 |
| 3563 int Vd = (instr->Bit(22) << 4) | instr->VdValue(); |
| 3564 int Rn = instr->VnValue(); |
| 3565 int type = instr->Bits(11, 8); |
| 3566 int Rm = instr->VmValue(); |
| 3567 int32_t address = get_register(Rn); |
| 3568 int regs = 0; |
| 3569 switch (type) { |
| 3570 case nlt_1: |
| 3571 regs = 1; |
| 3572 break; |
| 3573 case nlt_2: |
| 3574 regs = 2; |
| 3575 break; |
| 3576 case nlt_3: |
| 3577 regs = 3; |
| 3578 break; |
| 3579 case nlt_4: |
| 3580 regs = 4; |
| 3581 break; |
| 3582 default: |
| 3583 UNIMPLEMENTED(); |
| 3584 break; |
| 3585 } |
| 3586 int r = 0; |
| 3587 while (r < regs) { |
| 3588 uint32_t data[2]; |
| 3589 get_d_register(Vd + r, data); |
| 3590 WriteW(address, data[0], instr); |
| 3591 WriteW(address + 4, data[1], instr); |
| 3592 address += 8; |
| 3593 r++; |
| 3594 } |
| 3595 if (Rm != 15) { |
| 3596 if (Rm == 13) { |
| 3597 set_register(Rn, address); |
| 3598 } else { |
| 3599 set_register(Rn, get_register(Rn) + get_register(Rm)); |
| 3600 } |
| 3601 } |
| 3602 } else if (instr->Bits(21, 20) == 2) { |
| 3603 // vld1 |
| 3604 int Vd = (instr->Bit(22) << 4) | instr->VdValue(); |
| 3605 int Rn = instr->VnValue(); |
| 3606 int type = instr->Bits(11, 8); |
| 3607 int Rm = instr->VmValue(); |
| 3608 int32_t address = get_register(Rn); |
| 3609 int regs = 0; |
| 3610 switch (type) { |
| 3611 case nlt_1: |
| 3612 regs = 1; |
| 3613 break; |
| 3614 case nlt_2: |
| 3615 regs = 2; |
| 3616 break; |
| 3617 case nlt_3: |
| 3618 regs = 3; |
| 3619 break; |
| 3620 case nlt_4: |
| 3621 regs = 4; |
| 3622 break; |
| 3623 default: |
| 3624 UNIMPLEMENTED(); |
| 3625 break; |
| 3626 } |
| 3627 int r = 0; |
| 3628 while (r < regs) { |
| 3629 uint32_t data[2]; |
| 3630 data[0] = ReadW(address, instr); |
| 3631 data[1] = ReadW(address + 4, instr); |
| 3632 set_d_register(Vd + r, data); |
| 3633 address += 8; |
| 3634 r++; |
| 3635 } |
| 3636 if (Rm != 15) { |
| 3637 if (Rm == 13) { |
| 3638 set_register(Rn, address); |
| 3639 } else { |
| 3640 set_register(Rn, get_register(Rn) + get_register(Rm)); |
| 3641 } |
| 3642 } |
| 3643 } else { |
| 3644 UNIMPLEMENTED(); |
| 3645 } |
| 3646 break; |
| 3647 case 0xA: |
| 3648 case 0xB: |
| 3649 if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) { |
| 3650 // pld: ignore instruction. |
| 3651 } else { |
| 3652 UNIMPLEMENTED(); |
| 3653 } |
| 3654 break; |
| 3655 default: |
| 3656 UNIMPLEMENTED(); |
| 3657 break; |
| 3658 } |
| 3659 } |
| 3660 |
| 3661 |
3352 // Executes the current instruction. | 3662 // Executes the current instruction. |
3353 void Simulator::InstructionDecode(Instruction* instr) { | 3663 void Simulator::InstructionDecode(Instruction* instr) { |
3354 if (v8::internal::FLAG_check_icache) { | 3664 if (v8::internal::FLAG_check_icache) { |
3355 CheckICache(isolate_->simulator_i_cache(), instr); | 3665 CheckICache(isolate_->simulator_i_cache(), instr); |
3356 } | 3666 } |
3357 pc_modified_ = false; | 3667 pc_modified_ = false; |
3358 if (::v8::internal::FLAG_trace_sim) { | 3668 if (::v8::internal::FLAG_trace_sim) { |
3359 disasm::NameConverter converter; | 3669 disasm::NameConverter converter; |
3360 disasm::Disassembler dasm(converter); | 3670 disasm::Disassembler dasm(converter); |
3361 // use a reasonably large buffer | 3671 // use a reasonably large buffer |
3362 v8::internal::EmbeddedVector<char, 256> buffer; | 3672 v8::internal::EmbeddedVector<char, 256> buffer; |
3363 dasm.InstructionDecode(buffer, | 3673 dasm.InstructionDecode(buffer, |
3364 reinterpret_cast<byte*>(instr)); | 3674 reinterpret_cast<byte*>(instr)); |
3365 PrintF(" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr), buffer.start()); | 3675 PrintF(" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr), buffer.start()); |
3366 } | 3676 } |
3367 if (instr->ConditionField() == kSpecialCondition) { | 3677 if (instr->ConditionField() == kSpecialCondition) { |
3368 UNIMPLEMENTED(); | 3678 DecodeSpecialCondition(instr); |
3369 } else if (ConditionallyExecute(instr)) { | 3679 } else if (ConditionallyExecute(instr)) { |
3370 switch (instr->TypeValue()) { | 3680 switch (instr->TypeValue()) { |
3371 case 0: | 3681 case 0: |
3372 case 1: { | 3682 case 1: { |
3373 DecodeType01(instr); | 3683 DecodeType01(instr); |
3374 break; | 3684 break; |
3375 } | 3685 } |
3376 case 2: { | 3686 case 2: { |
3377 DecodeType2(instr); | 3687 DecodeType2(instr); |
3378 break; | 3688 break; |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3577 uintptr_t address = *stack_slot; | 3887 uintptr_t address = *stack_slot; |
3578 set_register(sp, current_sp + sizeof(uintptr_t)); | 3888 set_register(sp, current_sp + sizeof(uintptr_t)); |
3579 return address; | 3889 return address; |
3580 } | 3890 } |
3581 | 3891 |
3582 } } // namespace v8::internal | 3892 } } // namespace v8::internal |
3583 | 3893 |
3584 #endif // USE_SIMULATOR | 3894 #endif // USE_SIMULATOR |
3585 | 3895 |
3586 #endif // V8_TARGET_ARCH_ARM | 3896 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |