| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 namespace mips { | 44 namespace mips { |
| 45 | 45 |
| 46 using ::v8::internal::Object; | 46 using ::v8::internal::Object; |
| 47 using ::v8::internal::PrintF; | 47 using ::v8::internal::PrintF; |
| 48 using ::v8::internal::OS; | 48 using ::v8::internal::OS; |
| 49 using ::v8::internal::ReadLine; | 49 using ::v8::internal::ReadLine; |
| 50 using ::v8::internal::DeleteArray; | 50 using ::v8::internal::DeleteArray; |
| 51 | 51 |
| 52 // Utils functions | 52 // Utils functions |
| 53 bool HaveSameSign(int32_t a, int32_t b) { | 53 bool HaveSameSign(int32_t a, int32_t b) { |
| 54 return ((a ^ b) > 0); | 54 return ((a ^ b) >= 0); |
| 55 } | 55 } |
| 56 | 56 |
| 57 | 57 |
| 58 // This macro provides a platform independent use of sscanf. The reason for | 58 // This macro provides a platform independent use of sscanf. The reason for |
| 59 // SScanF not being implemented in a platform independent was through | 59 // SScanF not being implemented in a platform independent was through |
| 60 // ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time | 60 // ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time |
| 61 // Library does not provide vsscanf. | 61 // Library does not provide vsscanf. |
| 62 #define SScanF sscanf // NOLINT | 62 #define SScanF sscanf // NOLINT |
| 63 | 63 |
| 64 // The Debugger class is used by the simulator while debugging simulated MIPS | 64 // The Debugger class is used by the simulator while debugging simulated MIPS |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 break; | 277 break; |
| 278 } else { | 278 } else { |
| 279 // Use sscanf to parse the individual parts of the command line. At the | 279 // Use sscanf to parse the individual parts of the command line. At the |
| 280 // moment no command expects more than two parameters. | 280 // moment no command expects more than two parameters. |
| 281 int args = SScanF(line, | 281 int args = SScanF(line, |
| 282 "%" XSTR(COMMAND_SIZE) "s " | 282 "%" XSTR(COMMAND_SIZE) "s " |
| 283 "%" XSTR(ARG_SIZE) "s " | 283 "%" XSTR(ARG_SIZE) "s " |
| 284 "%" XSTR(ARG_SIZE) "s", | 284 "%" XSTR(ARG_SIZE) "s", |
| 285 cmd, arg1, arg2); | 285 cmd, arg1, arg2); |
| 286 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { | 286 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { |
| 287 if (!(reinterpret_cast<Instruction*>(sim_->get_pc())->IsTrap())) { | 287 Instruction* instr = reinterpret_cast<Instruction*>(sim_->get_pc()); |
| 288 if (!(instr->IsTrap()) || |
| 289 instr->InstructionBits() == rtCallRedirInstr) { |
| 288 sim_->InstructionDecode( | 290 sim_->InstructionDecode( |
| 289 reinterpret_cast<Instruction*>(sim_->get_pc())); | 291 reinterpret_cast<Instruction*>(sim_->get_pc())); |
| 290 } else { | 292 } else { |
| 291 // Allow si to jump over generated breakpoints. | 293 // Allow si to jump over generated breakpoints. |
| 292 PrintF("/!\\ Jumping over generated breakpoint.\n"); | 294 PrintF("/!\\ Jumping over generated breakpoint.\n"); |
| 293 sim_->set_pc(sim_->get_pc() + Instruction::kInstructionSize); | 295 sim_->set_pc(sim_->get_pc() + Instruction::kInstructionSize); |
| 294 } | 296 } |
| 295 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { | 297 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { |
| 296 // Execute the one instruction we broke at with breakpoints disabled. | 298 // Execute the one instruction we broke at with breakpoints disabled. |
| 297 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc())); | 299 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc())); |
| 298 // Leave the debugger shell. | 300 // Leave the debugger shell. |
| 299 done = true; | 301 done = true; |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 pc_modified_ = false; | 495 pc_modified_ = false; |
| 494 icount_ = 0; | 496 icount_ = 0; |
| 495 break_pc_ = NULL; | 497 break_pc_ = NULL; |
| 496 break_instr_ = 0; | 498 break_instr_ = 0; |
| 497 | 499 |
| 498 // Setup architecture state. | 500 // Setup architecture state. |
| 499 // All registers are initialized to zero to start with. | 501 // All registers are initialized to zero to start with. |
| 500 for (int i = 0; i < kNumSimuRegisters; i++) { | 502 for (int i = 0; i < kNumSimuRegisters; i++) { |
| 501 registers_[i] = 0; | 503 registers_[i] = 0; |
| 502 } | 504 } |
| 505 for (int i = 0; i < kNumFPURegisters; i++) { |
| 506 FPUregisters_[i] = 0; |
| 507 } |
| 508 FPUccr_ = 0; |
| 503 | 509 |
| 504 // The sp is initialized to point to the bottom (high address) of the | 510 // The sp is initialized to point to the bottom (high address) of the |
| 505 // allocated stack area. To be safe in potential stack underflows we leave | 511 // allocated stack area. To be safe in potential stack underflows we leave |
| 506 // some buffer below. | 512 // some buffer below. |
| 507 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64; | 513 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64; |
| 508 // The ra and pc are initialized to a known bad value that will cause an | 514 // The ra and pc are initialized to a known bad value that will cause an |
| 509 // access violation if the simulator ever tries to execute it. | 515 // access violation if the simulator ever tries to execute it. |
| 510 registers_[pc] = bad_ra; | 516 registers_[pc] = bad_ra; |
| 511 registers_[ra] = bad_ra; | 517 registers_[ra] = bad_ra; |
| 512 InitializeCoverage(); | 518 InitializeCoverage(); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 622 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters)); | 628 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters)); |
| 623 return FPUregisters_[fpureg]; | 629 return FPUregisters_[fpureg]; |
| 624 } | 630 } |
| 625 | 631 |
| 626 double Simulator::get_fpu_register_double(int fpureg) const { | 632 double Simulator::get_fpu_register_double(int fpureg) const { |
| 627 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0)); | 633 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0)); |
| 628 return *v8i::BitCast<double*, int32_t*>( | 634 return *v8i::BitCast<double*, int32_t*>( |
| 629 const_cast<int32_t*>(&FPUregisters_[fpureg])); | 635 const_cast<int32_t*>(&FPUregisters_[fpureg])); |
| 630 } | 636 } |
| 631 | 637 |
| 638 // Helper functions for setting and testing the FPU condition code bits. |
| 639 void Simulator::set_fpu_ccr_bit(uint32_t cc, bool value) { |
| 640 ASSERT(is_uint3(cc)); |
| 641 if (value) { |
| 642 FPUccr_ |= (1 << cc); |
| 643 } else { |
| 644 FPUccr_ &= ~(1 << cc); |
| 645 } |
| 646 } |
| 647 |
| 648 bool Simulator::test_fpu_ccr_bit(uint32_t cc) { |
| 649 ASSERT(is_uint3(cc)); |
| 650 return FPUccr_ & (1 << cc); |
| 651 } |
| 652 |
| 653 |
| 632 // Raw access to the PC register. | 654 // Raw access to the PC register. |
| 633 void Simulator::set_pc(int32_t value) { | 655 void Simulator::set_pc(int32_t value) { |
| 634 pc_modified_ = true; | 656 pc_modified_ = true; |
| 635 registers_[pc] = value; | 657 registers_[pc] = value; |
| 636 } | 658 } |
| 637 | 659 |
| 638 // Raw access to the PC register without the special adjustment when reading. | 660 // Raw access to the PC register without the special adjustment when reading. |
| 639 int32_t Simulator::get_pc() const { | 661 int32_t Simulator::get_pc() const { |
| 640 return registers_[pc]; | 662 return registers_[pc]; |
| 641 } | 663 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 669 PrintF("Unaligned write at 0x%08x, pc=%p\n", addr, instr); | 691 PrintF("Unaligned write at 0x%08x, pc=%p\n", addr, instr); |
| 670 OS::Abort(); | 692 OS::Abort(); |
| 671 } | 693 } |
| 672 | 694 |
| 673 | 695 |
| 674 double Simulator::ReadD(int32_t addr, Instruction* instr) { | 696 double Simulator::ReadD(int32_t addr, Instruction* instr) { |
| 675 if ((addr & kDoubleAlignmentMask) == 0) { | 697 if ((addr & kDoubleAlignmentMask) == 0) { |
| 676 double* ptr = reinterpret_cast<double*>(addr); | 698 double* ptr = reinterpret_cast<double*>(addr); |
| 677 return *ptr; | 699 return *ptr; |
| 678 } | 700 } |
| 679 PrintF("Unaligned read at 0x%08x, pc=%p\n", addr, instr); | 701 PrintF("Unaligned (double) read at 0x%08x, pc=%p\n", addr, instr); |
| 680 OS::Abort(); | 702 OS::Abort(); |
| 681 return 0; | 703 return 0; |
| 682 } | 704 } |
| 683 | 705 |
| 684 | 706 |
| 685 void Simulator::WriteD(int32_t addr, double value, Instruction* instr) { | 707 void Simulator::WriteD(int32_t addr, double value, Instruction* instr) { |
| 686 if ((addr & kDoubleAlignmentMask) == 0) { | 708 if ((addr & kDoubleAlignmentMask) == 0) { |
| 687 double* ptr = reinterpret_cast<double*>(addr); | 709 double* ptr = reinterpret_cast<double*>(addr); |
| 688 *ptr = value; | 710 *ptr = value; |
| 689 return; | 711 return; |
| 690 } | 712 } |
| 691 PrintF("Unaligned write at 0x%08x, pc=%p\n", addr, instr); | 713 PrintF("Unaligned (double) write at 0x%08x, pc=%p\n", addr, instr); |
| 692 OS::Abort(); | 714 OS::Abort(); |
| 693 } | 715 } |
| 694 | 716 |
| 695 | 717 |
| 696 uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) { | 718 uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) { |
| 697 if ((addr & 1) == 0) { | 719 if ((addr & 1) == 0) { |
| 698 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); | 720 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); |
| 699 return *ptr; | 721 return *ptr; |
| 700 } | 722 } |
| 701 PrintF("Unaligned unsigned halfword read at 0x%08x, pc=%p\n", addr, instr); | 723 PrintF("Unaligned unsigned halfword read at 0x%08x, pc=%p\n", addr, instr); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 738 | 760 |
| 739 | 761 |
| 740 uint32_t Simulator::ReadBU(int32_t addr) { | 762 uint32_t Simulator::ReadBU(int32_t addr) { |
| 741 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); | 763 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); |
| 742 return *ptr & 0xff; | 764 return *ptr & 0xff; |
| 743 } | 765 } |
| 744 | 766 |
| 745 | 767 |
| 746 int32_t Simulator::ReadB(int32_t addr) { | 768 int32_t Simulator::ReadB(int32_t addr) { |
| 747 int8_t* ptr = reinterpret_cast<int8_t*>(addr); | 769 int8_t* ptr = reinterpret_cast<int8_t*>(addr); |
| 748 return ((*ptr << 24) >> 24) & 0xff; | 770 return *ptr; |
| 749 } | 771 } |
| 750 | 772 |
| 751 | 773 |
| 752 void Simulator::WriteB(int32_t addr, uint8_t value) { | 774 void Simulator::WriteB(int32_t addr, uint8_t value) { |
| 753 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); | 775 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); |
| 754 *ptr = value; | 776 *ptr = value; |
| 755 } | 777 } |
| 756 | 778 |
| 757 | 779 |
| 758 void Simulator::WriteB(int32_t addr, int8_t value) { | 780 void Simulator::WriteB(int32_t addr, int8_t value) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 774 PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n", | 796 PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n", |
| 775 instr, format); | 797 instr, format); |
| 776 UNIMPLEMENTED_MIPS(); | 798 UNIMPLEMENTED_MIPS(); |
| 777 } | 799 } |
| 778 | 800 |
| 779 | 801 |
| 780 // Calls into the V8 runtime are based on this very simple interface. | 802 // Calls into the V8 runtime are based on this very simple interface. |
| 781 // Note: To be able to return two values from some calls the code in runtime.cc | 803 // Note: To be able to return two values from some calls the code in runtime.cc |
| 782 // uses the ObjectPair which is essentially two 32-bit values stuffed into a | 804 // uses the ObjectPair which is essentially two 32-bit values stuffed into a |
| 783 // 64-bit value. With the code below we assume that all runtime calls return | 805 // 64-bit value. With the code below we assume that all runtime calls return |
| 784 // 64 bits of result. If they don't, the r1 result register contains a bogus | 806 // 64 bits of result. If they don't, the v1 result register contains a bogus |
| 785 // value, which is fine because it is caller-saved. | 807 // value, which is fine because it is caller-saved. |
| 786 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, | 808 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, |
| 787 int32_t arg1, | 809 int32_t arg1, |
| 788 int32_t arg2, | 810 int32_t arg2, |
| 789 int32_t arg3); | 811 int32_t arg3); |
| 790 typedef double (*SimulatorRuntimeFPCall)(double fparg0, | 812 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0, |
| 791 double fparg1); | 813 int32_t arg1, |
| 792 | 814 int32_t arg2, |
| 815 int32_t arg3); |
| 793 | 816 |
| 794 // Software interrupt instructions are used by the simulator to call into the | 817 // Software interrupt instructions are used by the simulator to call into the |
| 795 // C-based V8 runtime. | 818 // C-based V8 runtime. |
| 796 void Simulator::SoftwareInterrupt(Instruction* instr) { | 819 void Simulator::SoftwareInterrupt(Instruction* instr) { |
| 797 // We first check if we met a call_rt_redirected. | 820 // We first check if we met a call_rt_redirected. |
| 798 if (instr->InstructionBits() == rtCallRedirInstr) { | 821 if (instr->InstructionBits() == rtCallRedirInstr) { |
| 799 Redirection* redirection = Redirection::FromSwiInstruction(instr); | 822 Redirection* redirection = Redirection::FromSwiInstruction(instr); |
| 800 int32_t arg0 = get_register(a0); | 823 int32_t arg0 = get_register(a0); |
| 801 int32_t arg1 = get_register(a1); | 824 int32_t arg1 = get_register(a1); |
| 802 int32_t arg2 = get_register(a2); | 825 int32_t arg2 = get_register(a2); |
| 803 int32_t arg3 = get_register(a3); | 826 int32_t arg3 = get_register(a3); |
| 804 // fp args are (not always) in f12 and f14. | 827 int32_t result_l, result_h; |
| 805 // See MIPS conventions for more details. | |
| 806 double fparg0 = get_fpu_register_double(f12); | |
| 807 double fparg1 = get_fpu_register_double(f14); | |
| 808 // This is dodgy but it works because the C entry stubs are never moved. | 828 // This is dodgy but it works because the C entry stubs are never moved. |
| 809 // See comment in codegen-arm.cc and bug 1242173. | 829 // See comment in codegen-arm.cc and bug 1242173. |
| 810 int32_t saved_ra = get_register(ra); | 830 int32_t saved_ra = get_register(ra); |
| 831 |
| 832 intptr_t external = |
| 833 reinterpret_cast<int32_t>(redirection->external_function()); |
| 834 SimulatorRuntimeCall target = |
| 835 reinterpret_cast<SimulatorRuntimeCall>(external); |
| 836 |
| 837 if (::v8::internal::FLAG_trace_sim) { |
| 838 PrintF( |
| 839 "Call to host function at %p with args %08x, %08x, %08x, %08x\n", |
| 840 FUNCTION_ADDR(target), |
| 841 arg0, |
| 842 arg1, |
| 843 arg2, |
| 844 arg3); |
| 845 } |
| 846 |
| 847 // Based on CpuFeatures::IsSupported(FPU), Mips will use either hardware |
| 848 // FPU, or gcc soft-float routines. Hardware FPU is simulated in this |
| 849 // simulator. Soft-float has additional abstraction of ExternalReference, |
| 850 // to support serialization. Finally, when simulated on x86 host, the |
| 851 // x86 softfloat routines are used, and this Redirection infrastructure |
| 852 // lets simulated-mips make calls into x86 C code. |
| 853 // When doing that, the 'double' return type must be handled differently |
| 854 // than the usual int64_t return. The data is returned in different |
| 855 // registers and cannot be cast from one type to the other. However, the |
| 856 // calling arguments are passed the same way in both cases. |
| 811 if (redirection->fp_return()) { | 857 if (redirection->fp_return()) { |
| 812 intptr_t external = | |
| 813 reinterpret_cast<intptr_t>(redirection->external_function()); | |
| 814 SimulatorRuntimeFPCall target = | 858 SimulatorRuntimeFPCall target = |
| 815 reinterpret_cast<SimulatorRuntimeFPCall>(external); | 859 reinterpret_cast<SimulatorRuntimeFPCall>(external); |
| 816 if (::v8::internal::FLAG_trace_sim) { | 860 double result = target(arg0, arg1, arg2, arg3); |
| 817 PrintF("Call to host function at %p with args %f, %f\n", | 861 uint64_t u64; |
| 818 FUNCTION_ADDR(target), fparg0, fparg1); | 862 u64 = *v8i::BitCast<uint64_t*, double*>(const_cast<double*>(&result)); |
| 819 } | 863 result_h = static_cast<uint32_t>(u64 >> 32); |
| 820 double result = target(fparg0, fparg1); | 864 result_l = static_cast<uint32_t>(u64 & 0xffffffff); |
| 821 set_fpu_register_double(f0, result); | |
| 822 } else { | 865 } else { |
| 823 intptr_t external = | |
| 824 reinterpret_cast<int32_t>(redirection->external_function()); | |
| 825 SimulatorRuntimeCall target = | |
| 826 reinterpret_cast<SimulatorRuntimeCall>(external); | |
| 827 if (::v8::internal::FLAG_trace_sim) { | |
| 828 PrintF( | |
| 829 "Call to host function at %p with args %08x, %08x, %08x, %08x\n", | |
| 830 FUNCTION_ADDR(target), | |
| 831 arg0, | |
| 832 arg1, | |
| 833 arg2, | |
| 834 arg3); | |
| 835 } | |
| 836 int64_t result = target(arg0, arg1, arg2, arg3); | 866 int64_t result = target(arg0, arg1, arg2, arg3); |
| 837 int32_t lo_res = static_cast<int32_t>(result); | 867 result_l = static_cast<int32_t>(result); |
| 838 int32_t hi_res = static_cast<int32_t>(result >> 32); | 868 result_h = static_cast<int32_t>(result >> 32); |
| 839 if (::v8::internal::FLAG_trace_sim) { | 869 } |
| 840 PrintF("Returned %08x\n", lo_res); | 870 set_register(v0, result_l); |
| 841 } | 871 set_register(v1, result_h); |
| 842 set_register(v0, lo_res); | 872 if (::v8::internal::FLAG_trace_sim) { |
| 843 set_register(v1, hi_res); | 873 PrintF("Returned %08x : %08x\n", result_h, result_l); |
| 844 } | 874 } |
| 845 set_register(ra, saved_ra); | 875 set_register(ra, saved_ra); |
| 846 set_pc(get_register(ra)); | 876 set_pc(get_register(ra)); |
| 847 } else { | 877 } else { |
| 848 Debugger dbg(this); | 878 Debugger dbg(this); |
| 849 dbg.Debug(); | 879 dbg.Debug(); |
| 850 } | 880 } |
| 851 } | 881 } |
| 852 | 882 |
| 853 void Simulator::SignalExceptions() { | 883 void Simulator::SignalExceptions() { |
| 854 for (int i = 1; i < kNumExceptions; i++) { | 884 for (int i = 1; i < kNumExceptions; i++) { |
| 855 if (exceptions[i] != 0) { | 885 if (exceptions[i] != 0) { |
| 856 V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", i); | 886 V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", i); |
| 857 } | 887 } |
| 858 } | 888 } |
| 859 } | 889 } |
| 860 | 890 |
| 861 // Handle execution based on instruction types. | 891 // Handle execution based on instruction types. |
| 862 void Simulator::DecodeTypeRegister(Instruction* instr) { | 892 void Simulator::DecodeTypeRegister(Instruction* instr) { |
| 863 // Instruction fields | 893 // Instruction fields. |
| 864 Opcode op = instr->OpcodeFieldRaw(); | 894 Opcode op = instr->OpcodeFieldRaw(); |
| 865 int32_t rs_reg = instr->RsField(); | 895 int32_t rs_reg = instr->RsField(); |
| 866 int32_t rs = get_register(rs_reg); | 896 int32_t rs = get_register(rs_reg); |
| 867 uint32_t rs_u = static_cast<uint32_t>(rs); | 897 uint32_t rs_u = static_cast<uint32_t>(rs); |
| 868 int32_t rt_reg = instr->RtField(); | 898 int32_t rt_reg = instr->RtField(); |
| 869 int32_t rt = get_register(rt_reg); | 899 int32_t rt = get_register(rt_reg); |
| 870 uint32_t rt_u = static_cast<uint32_t>(rt); | 900 uint32_t rt_u = static_cast<uint32_t>(rt); |
| 871 int32_t rd_reg = instr->RdField(); | 901 int32_t rd_reg = instr->RdField(); |
| 872 uint32_t sa = instr->SaField(); | 902 uint32_t sa = instr->SaField(); |
| 873 | 903 |
| 874 int32_t fs_reg= instr->FsField(); | 904 int32_t fs_reg = instr->FsField(); |
| 905 int32_t ft_reg = instr->FtField(); |
| 906 int32_t fd_reg = instr->FdField(); |
| 907 int64_t i64hilo = 0; |
| 908 uint64_t u64hilo = 0; |
| 875 | 909 |
| 876 // ALU output | 910 // ALU output |
| 877 // It should not be used as is. Instructions using it should always initialize | 911 // It should not be used as is. Instructions using it should always |
| 878 // it first. | 912 // initialize it first. |
| 879 int32_t alu_out = 0x12345678; | 913 int32_t alu_out = 0x12345678; |
| 880 // Output or temporary for floating point. | |
| 881 double fp_out = 0.0; | |
| 882 | 914 |
| 883 // For break and trap instructions. | 915 // For break and trap instructions. |
| 884 bool do_interrupt = false; | 916 bool do_interrupt = false; |
| 885 | 917 |
| 886 // For jr and jalr | 918 // For jr and jalr |
| 887 // Get current pc. | 919 // Get current pc. |
| 888 int32_t current_pc = get_pc(); | 920 int32_t current_pc = get_pc(); |
| 889 // Next pc | 921 // Next pc |
| 890 int32_t next_pc = 0; | 922 int32_t next_pc = 0; |
| 891 | 923 |
| 892 // ---------- Configuration | 924 // ---------- Configuration |
| 893 switch (op) { | 925 switch (op) { |
| 894 case COP1: // Coprocessor instructions | 926 case COP1: // Coprocessor instructions |
| 895 switch (instr->RsFieldRaw()) { | 927 switch (instr->RsFieldRaw()) { |
| 896 case BC1: // branch on coprocessor condition | 928 case BC1: // Handled in DecodeTypeImmed, should never come here. |
| 897 UNREACHABLE(); | 929 UNREACHABLE(); |
| 898 break; | 930 break; |
| 899 case MFC1: | 931 case MFC1: |
| 900 alu_out = get_fpu_register(fs_reg); | 932 alu_out = get_fpu_register(fs_reg); |
| 901 break; | 933 break; |
| 902 case MFHC1: | 934 case MFHC1: |
| 903 fp_out = get_fpu_register_double(fs_reg); | 935 UNIMPLEMENTED_MIPS(); |
| 904 alu_out = *v8i::BitCast<int32_t*, double*>(&fp_out); | |
| 905 break; | 936 break; |
| 906 case MTC1: | 937 case MTC1: |
| 907 case MTHC1: | 938 case MTHC1: |
| 908 // Do the store in the execution step. | 939 // Do the store in the execution step. |
| 909 break; | 940 break; |
| 910 case S: | 941 case S: |
| 911 case D: | 942 case D: |
| 912 case W: | 943 case W: |
| 913 case L: | 944 case L: |
| 914 case PS: | 945 case PS: |
| (...skipping 27 matching lines...) Expand all Loading... |
| 942 case SRAV: | 973 case SRAV: |
| 943 alu_out = rt >> rs; | 974 alu_out = rt >> rs; |
| 944 break; | 975 break; |
| 945 case MFHI: | 976 case MFHI: |
| 946 alu_out = get_register(HI); | 977 alu_out = get_register(HI); |
| 947 break; | 978 break; |
| 948 case MFLO: | 979 case MFLO: |
| 949 alu_out = get_register(LO); | 980 alu_out = get_register(LO); |
| 950 break; | 981 break; |
| 951 case MULT: | 982 case MULT: |
| 952 UNIMPLEMENTED_MIPS(); | 983 i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt); |
| 953 break; | 984 break; |
| 954 case MULTU: | 985 case MULTU: |
| 955 UNIMPLEMENTED_MIPS(); | 986 u64hilo = static_cast<uint64_t>(rs_u) * static_cast<uint64_t>(rt_u); |
| 956 break; | 987 break; |
| 957 case DIV: | 988 case DIV: |
| 958 case DIVU: | 989 case DIVU: |
| 959 exceptions[kDivideByZero] = rt == 0; | 990 exceptions[kDivideByZero] = rt == 0; |
| 960 break; | 991 break; |
| 961 case ADD: | 992 case ADD: |
| 962 if (HaveSameSign(rs, rt)) { | 993 if (HaveSameSign(rs, rt)) { |
| 963 if (rs > 0) { | 994 if (rs > 0) { |
| 964 exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - rt); | 995 exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - rt); |
| 965 } else if (rs < 0) { | 996 } else if (rs < 0) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1017 break; | 1048 break; |
| 1018 case TLTU: | 1049 case TLTU: |
| 1019 do_interrupt = rs_u < rt_u; | 1050 do_interrupt = rs_u < rt_u; |
| 1020 break; | 1051 break; |
| 1021 case TEQ: | 1052 case TEQ: |
| 1022 do_interrupt = rs == rt; | 1053 do_interrupt = rs == rt; |
| 1023 break; | 1054 break; |
| 1024 case TNE: | 1055 case TNE: |
| 1025 do_interrupt = rs != rt; | 1056 do_interrupt = rs != rt; |
| 1026 break; | 1057 break; |
| 1058 case MOVN: |
| 1059 case MOVZ: |
| 1060 // No action taken on decode. |
| 1061 break; |
| 1027 default: | 1062 default: |
| 1028 UNREACHABLE(); | 1063 UNREACHABLE(); |
| 1029 }; | 1064 }; |
| 1030 break; | 1065 break; |
| 1031 case SPECIAL2: | 1066 case SPECIAL2: |
| 1032 switch (instr->FunctionFieldRaw()) { | 1067 switch (instr->FunctionFieldRaw()) { |
| 1033 case MUL: | 1068 case MUL: |
| 1034 alu_out = rs_u * rt_u; // Only the lower 32 bits are kept. | 1069 alu_out = rs_u * rt_u; // Only the lower 32 bits are kept. |
| 1035 break; | 1070 break; |
| 1071 case CLZ: |
| 1072 alu_out = __builtin_clz(rs_u); |
| 1073 break; |
| 1036 default: | 1074 default: |
| 1037 UNREACHABLE(); | 1075 UNREACHABLE(); |
| 1038 } | 1076 }; |
| 1077 break; |
| 1078 case SPECIAL3: |
| 1079 switch (instr->FunctionFieldRaw()) { |
| 1080 case INS: { // mips32r2 instruction. |
| 1081 // Interpret Rd field as 5-bit msb of insert. |
| 1082 uint16_t msb = rd_reg; |
| 1083 // Interpret sa field as 5-bit lsb of insert. |
| 1084 uint16_t lsb = sa; |
| 1085 uint16_t size = msb - lsb + 1; |
| 1086 uint16_t mask = (1 << size) - 1; |
| 1087 alu_out = (rt_u & ~(mask << lsb)) | ((rs_u & mask) << lsb); |
| 1088 } |
| 1089 break; |
| 1090 case EXT: { // mips32r2 instruction. |
| 1091 // Interpret Rd field as 5-bit msb of extract. |
| 1092 uint16_t msb = rd_reg; |
| 1093 // Interpret sa field as 5-bit lsb of extract. |
| 1094 uint16_t lsb = sa; |
| 1095 uint16_t size = msb - lsb + 1; |
| 1096 uint16_t mask = (1 << size) - 1; |
| 1097 alu_out = (rs_u & (mask << lsb)) >> lsb; |
| 1098 } |
| 1099 break; |
| 1100 default: |
| 1101 UNREACHABLE(); |
| 1102 }; |
| 1039 break; | 1103 break; |
| 1040 default: | 1104 default: |
| 1041 UNREACHABLE(); | 1105 UNREACHABLE(); |
| 1042 }; | 1106 }; |
| 1043 | 1107 |
| 1044 // ---------- Raise exceptions triggered. | 1108 // ---------- Raise exceptions triggered. |
| 1045 SignalExceptions(); | 1109 SignalExceptions(); |
| 1046 | 1110 |
| 1047 // ---------- Execution | 1111 // ---------- Execution |
| 1048 switch (op) { | 1112 switch (op) { |
| 1049 case COP1: | 1113 case COP1: |
| 1050 switch (instr->RsFieldRaw()) { | 1114 switch (instr->RsFieldRaw()) { |
| 1051 case BC1: // branch on coprocessor condition | 1115 case BC1: // branch on coprocessor condition |
| 1052 UNREACHABLE(); | 1116 UNREACHABLE(); |
| 1053 break; | 1117 break; |
| 1054 case MFC1: | 1118 case MFC1: |
| 1055 case MFHC1: | |
| 1056 set_register(rt_reg, alu_out); | 1119 set_register(rt_reg, alu_out); |
| 1057 break; | 1120 break; |
| 1121 case MFHC1: |
| 1122 UNIMPLEMENTED_MIPS(); |
| 1123 break; |
| 1058 case MTC1: | 1124 case MTC1: |
| 1059 // We don't need to set the higher bits to 0, because MIPS ISA says | |
| 1060 // they are in an unpredictable state after executing MTC1. | |
| 1061 FPUregisters_[fs_reg] = registers_[rt_reg]; | 1125 FPUregisters_[fs_reg] = registers_[rt_reg]; |
| 1062 FPUregisters_[fs_reg+1] = Unpredictable; | |
| 1063 break; | 1126 break; |
| 1064 case MTHC1: | 1127 case MTHC1: |
| 1065 // Here we need to keep the lower bits unchanged. | 1128 UNIMPLEMENTED_MIPS(); |
| 1066 FPUregisters_[fs_reg+1] = registers_[rt_reg]; | |
| 1067 break; | 1129 break; |
| 1068 case S: | 1130 case S: |
| 1069 switch (instr->FunctionFieldRaw()) { | 1131 switch (instr->FunctionFieldRaw()) { |
| 1070 case CVT_D_S: | 1132 case CVT_D_S: |
| 1071 case CVT_W_S: | 1133 case CVT_W_S: |
| 1072 case CVT_L_S: | 1134 case CVT_L_S: |
| 1073 case CVT_PS_S: | 1135 case CVT_PS_S: |
| 1074 UNIMPLEMENTED_MIPS(); | 1136 UNIMPLEMENTED_MIPS(); |
| 1075 break; | 1137 break; |
| 1076 default: | 1138 default: |
| 1077 UNREACHABLE(); | 1139 UNREACHABLE(); |
| 1078 } | 1140 } |
| 1079 break; | 1141 break; |
| 1080 case D: | 1142 case D: |
| 1143 double ft, fs; |
| 1144 uint32_t cc; |
| 1145 fs = get_fpu_register_double(fs_reg); |
| 1146 ft = get_fpu_register_double(ft_reg); |
| 1147 cc = instr->FCccField(); |
| 1081 switch (instr->FunctionFieldRaw()) { | 1148 switch (instr->FunctionFieldRaw()) { |
| 1149 case ADD_D: |
| 1150 set_fpu_register_double(fd_reg, fs + ft); |
| 1151 break; |
| 1152 case SUB_D: |
| 1153 set_fpu_register_double(fd_reg, fs - ft); |
| 1154 break; |
| 1155 case MUL_D: |
| 1156 set_fpu_register_double(fd_reg, fs * ft); |
| 1157 break; |
| 1158 case DIV_D: |
| 1159 set_fpu_register_double(fd_reg, fs / ft); |
| 1160 break; |
| 1161 case ABS_D: |
| 1162 set_fpu_register_double(fd_reg, fs < 0 ? -fs : fs); |
| 1163 break; |
| 1164 case MOV_D: |
| 1165 set_fpu_register_double(fd_reg, fs); |
| 1166 break; |
| 1167 case NEG_D: |
| 1168 set_fpu_register_double(fd_reg, -fs); |
| 1169 break; |
| 1170 case CVT_W_D: // Convert double to word |
| 1171 set_fpu_register(fd_reg, static_cast<int32_t>(fs)); |
| 1172 break; |
| 1173 case C_UN_D: |
| 1174 set_fpu_ccr_bit(cc, isnan(fs) || isnan(ft)); |
| 1175 break; |
| 1176 case C_EQ_D: |
| 1177 set_fpu_ccr_bit(cc, (fs == ft)); |
| 1178 break; |
| 1179 case C_UEQ_D: |
| 1180 set_fpu_ccr_bit(cc, (fs == ft) || (isnan(fs) || isnan(ft))); |
| 1181 break; |
| 1182 case C_OLT_D: |
| 1183 set_fpu_ccr_bit(cc, (fs < ft)); |
| 1184 break; |
| 1185 case C_ULT_D: |
| 1186 set_fpu_ccr_bit(cc, (fs < ft) || (isnan(fs) || isnan(ft))); |
| 1187 break; |
| 1188 case C_OLE_D: |
| 1189 set_fpu_ccr_bit(cc, (fs <= ft)); |
| 1190 break; |
| 1191 case C_ULE_D: |
| 1192 set_fpu_ccr_bit(cc, (fs <= ft) || (isnan(fs) || isnan(ft))); |
| 1193 break; |
| 1194 case C_F_D: |
| 1082 case CVT_S_D: | 1195 case CVT_S_D: |
| 1083 case CVT_W_D: | |
| 1084 case CVT_L_D: | 1196 case CVT_L_D: |
| 1085 UNIMPLEMENTED_MIPS(); | 1197 UNIMPLEMENTED_MIPS(); |
| 1086 break; | 1198 break; |
| 1087 default: | 1199 default: |
| 1088 UNREACHABLE(); | 1200 UNREACHABLE(); |
| 1089 } | 1201 } |
| 1090 break; | 1202 break; |
| 1091 case W: | 1203 case W: |
| 1092 switch (instr->FunctionFieldRaw()) { | 1204 switch (instr->FunctionFieldRaw()) { |
| 1093 case CVT_S_W: | 1205 case CVT_S_W: |
| 1094 UNIMPLEMENTED_MIPS(); | 1206 UNIMPLEMENTED_MIPS(); |
| 1095 break; | 1207 break; |
| 1096 case CVT_D_W: // Convert word to double. | 1208 case CVT_D_W: // Convert word to double. |
| 1097 set_fpu_register(rd_reg, static_cast<double>(rs)); | 1209 alu_out = get_fpu_register(fs_reg); |
| 1210 set_fpu_register_double(fd_reg, static_cast<double>(alu_out)); |
| 1098 break; | 1211 break; |
| 1099 default: | 1212 default: |
| 1100 UNREACHABLE(); | 1213 UNREACHABLE(); |
| 1101 }; | 1214 }; |
| 1102 break; | 1215 break; |
| 1103 case L: | 1216 case L: |
| 1104 switch (instr->FunctionFieldRaw()) { | 1217 switch (instr->FunctionFieldRaw()) { |
| 1105 case CVT_S_L: | 1218 case CVT_S_L: |
| 1106 case CVT_D_L: | 1219 case CVT_D_L: |
| 1107 UNIMPLEMENTED_MIPS(); | 1220 UNIMPLEMENTED_MIPS(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1130 Instruction* branch_delay_instr = reinterpret_cast<Instruction*>( | 1243 Instruction* branch_delay_instr = reinterpret_cast<Instruction*>( |
| 1131 current_pc+Instruction::kInstructionSize); | 1244 current_pc+Instruction::kInstructionSize); |
| 1132 BranchDelayInstructionDecode(branch_delay_instr); | 1245 BranchDelayInstructionDecode(branch_delay_instr); |
| 1133 set_register(31, current_pc + 2* Instruction::kInstructionSize); | 1246 set_register(31, current_pc + 2* Instruction::kInstructionSize); |
| 1134 set_pc(next_pc); | 1247 set_pc(next_pc); |
| 1135 pc_modified_ = true; | 1248 pc_modified_ = true; |
| 1136 break; | 1249 break; |
| 1137 } | 1250 } |
| 1138 // Instructions using HI and LO registers. | 1251 // Instructions using HI and LO registers. |
| 1139 case MULT: | 1252 case MULT: |
| 1253 set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff)); |
| 1254 set_register(HI, static_cast<int32_t>(i64hilo >> 32)); |
| 1255 break; |
| 1140 case MULTU: | 1256 case MULTU: |
| 1257 set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff)); |
| 1258 set_register(HI, static_cast<int32_t>(u64hilo >> 32)); |
| 1141 break; | 1259 break; |
| 1142 case DIV: | 1260 case DIV: |
| 1143 // Divide by zero was checked in the configuration step. | 1261 // Divide by zero was checked in the configuration step. |
| 1144 set_register(LO, rs / rt); | 1262 set_register(LO, rs / rt); |
| 1145 set_register(HI, rs % rt); | 1263 set_register(HI, rs % rt); |
| 1146 break; | 1264 break; |
| 1147 case DIVU: | 1265 case DIVU: |
| 1148 set_register(LO, rs_u / rt_u); | 1266 set_register(LO, rs_u / rt_u); |
| 1149 set_register(HI, rs_u % rt_u); | 1267 set_register(HI, rs_u % rt_u); |
| 1150 break; | 1268 break; |
| 1151 // Break and trap instructions | 1269 // Break and trap instructions. |
| 1152 case BREAK: | 1270 case BREAK: |
| 1153 case TGE: | 1271 case TGE: |
| 1154 case TGEU: | 1272 case TGEU: |
| 1155 case TLT: | 1273 case TLT: |
| 1156 case TLTU: | 1274 case TLTU: |
| 1157 case TEQ: | 1275 case TEQ: |
| 1158 case TNE: | 1276 case TNE: |
| 1159 if (do_interrupt) { | 1277 if (do_interrupt) { |
| 1160 SoftwareInterrupt(instr); | 1278 SoftwareInterrupt(instr); |
| 1161 } | 1279 } |
| 1162 break; | 1280 break; |
| 1281 // Conditional moves. |
| 1282 case MOVN: |
| 1283 if (rt) set_register(rd_reg, rs); |
| 1284 break; |
| 1285 case MOVZ: |
| 1286 if (!rt) set_register(rd_reg, rs); |
| 1287 break; |
| 1163 default: // For other special opcodes we do the default operation. | 1288 default: // For other special opcodes we do the default operation. |
| 1164 set_register(rd_reg, alu_out); | 1289 set_register(rd_reg, alu_out); |
| 1165 }; | 1290 }; |
| 1166 break; | 1291 break; |
| 1167 case SPECIAL2: | 1292 case SPECIAL2: |
| 1168 switch (instr->FunctionFieldRaw()) { | 1293 switch (instr->FunctionFieldRaw()) { |
| 1169 case MUL: | 1294 case MUL: |
| 1170 set_register(rd_reg, alu_out); | 1295 set_register(rd_reg, alu_out); |
| 1171 // HI and LO are UNPREDICTABLE after the operation. | 1296 // HI and LO are UNPREDICTABLE after the operation. |
| 1172 set_register(LO, Unpredictable); | 1297 set_register(LO, Unpredictable); |
| 1173 set_register(HI, Unpredictable); | 1298 set_register(HI, Unpredictable); |
| 1174 break; | 1299 break; |
| 1300 default: // For other special2 opcodes we do the default operation. |
| 1301 set_register(rd_reg, alu_out); |
| 1302 } |
| 1303 break; |
| 1304 case SPECIAL3: |
| 1305 switch (instr->FunctionFieldRaw()) { |
| 1306 case INS: |
| 1307 // Ins instr leaves result in Rt, rather than Rd. |
| 1308 set_register(rt_reg, alu_out); |
| 1309 break; |
| 1310 case EXT: |
| 1311 // Ext instr leaves result in Rt, rather than Rd. |
| 1312 set_register(rt_reg, alu_out); |
| 1313 break; |
| 1175 default: | 1314 default: |
| 1176 UNREACHABLE(); | 1315 UNREACHABLE(); |
| 1177 } | 1316 }; |
| 1178 break; | 1317 break; |
| 1179 // Unimplemented opcodes raised an error in the configuration step before, | 1318 // Unimplemented opcodes raised an error in the configuration step before, |
| 1180 // so we can use the default here to set the destination register in common | 1319 // so we can use the default here to set the destination register in common |
| 1181 // cases. | 1320 // cases. |
| 1182 default: | 1321 default: |
| 1183 set_register(rd_reg, alu_out); | 1322 set_register(rd_reg, alu_out); |
| 1184 }; | 1323 }; |
| 1185 } | 1324 } |
| 1186 | 1325 |
| 1187 // Type 2: instructions using a 16 bytes immediate. (eg: addi, beq) | 1326 // Type 2: instructions using a 16 bytes immediate. (eg: addi, beq) |
| 1188 void Simulator::DecodeTypeImmediate(Instruction* instr) { | 1327 void Simulator::DecodeTypeImmediate(Instruction* instr) { |
| 1189 // Instruction fields | 1328 // Instruction fields. |
| 1190 Opcode op = instr->OpcodeFieldRaw(); | 1329 Opcode op = instr->OpcodeFieldRaw(); |
| 1191 int32_t rs = get_register(instr->RsField()); | 1330 int32_t rs = get_register(instr->RsField()); |
| 1192 uint32_t rs_u = static_cast<uint32_t>(rs); | 1331 uint32_t rs_u = static_cast<uint32_t>(rs); |
| 1193 int32_t rt_reg = instr->RtField(); // destination register | 1332 int32_t rt_reg = instr->RtField(); // destination register |
| 1194 int32_t rt = get_register(rt_reg); | 1333 int32_t rt = get_register(rt_reg); |
| 1195 int16_t imm16 = instr->Imm16Field(); | 1334 int16_t imm16 = instr->Imm16Field(); |
| 1196 | 1335 |
| 1197 int32_t ft_reg = instr->FtField(); // destination register | 1336 int32_t ft_reg = instr->FtField(); // destination register |
| 1198 int32_t ft = get_register(ft_reg); | |
| 1199 | 1337 |
| 1200 // zero extended immediate | 1338 // Zero extended immediate. |
| 1201 uint32_t oe_imm16 = 0xffff & imm16; | 1339 uint32_t oe_imm16 = 0xffff & imm16; |
| 1202 // sign extended immediate | 1340 // Sign extended immediate. |
| 1203 int32_t se_imm16 = imm16; | 1341 int32_t se_imm16 = imm16; |
| 1204 | 1342 |
| 1205 // Get current pc. | 1343 // Get current pc. |
| 1206 int32_t current_pc = get_pc(); | 1344 int32_t current_pc = get_pc(); |
| 1207 // Next pc. | 1345 // Next pc. |
| 1208 int32_t next_pc = bad_ra; | 1346 int32_t next_pc = bad_ra; |
| 1209 | 1347 |
| 1210 // Used for conditional branch instructions | 1348 // Used for conditional branch instructions. |
| 1211 bool do_branch = false; | 1349 bool do_branch = false; |
| 1212 bool execute_branch_delay_instruction = false; | 1350 bool execute_branch_delay_instruction = false; |
| 1213 | 1351 |
| 1214 // Used for arithmetic instructions | 1352 // Used for arithmetic instructions. |
| 1215 int32_t alu_out = 0; | 1353 int32_t alu_out = 0; |
| 1216 // Floating point | 1354 // Floating point. |
| 1217 double fp_out = 0.0; | 1355 double fp_out = 0.0; |
| 1356 uint32_t cc, cc_value; |
| 1218 | 1357 |
| 1219 // Used for memory instructions | 1358 // Used for memory instructions. |
| 1220 int32_t addr = 0x0; | 1359 int32_t addr = 0x0; |
| 1221 | 1360 |
| 1222 // ---------- Configuration (and execution for REGIMM) | 1361 // ---------- Configuration (and execution for REGIMM) |
| 1223 switch (op) { | 1362 switch (op) { |
| 1224 // ------------- COP1. Coprocessor instructions | 1363 // ------------- COP1. Coprocessor instructions. |
| 1225 case COP1: | 1364 case COP1: |
| 1226 switch (instr->RsFieldRaw()) { | 1365 switch (instr->RsFieldRaw()) { |
| 1227 case BC1: // branch on coprocessor condition | 1366 case BC1: // Branch on coprocessor condition. |
| 1228 UNIMPLEMENTED_MIPS(); | 1367 cc = instr->FBccField(); |
| 1368 cc_value = test_fpu_ccr_bit(cc); |
| 1369 do_branch = (instr->FBtrueField()) ? cc_value : !cc_value; |
| 1370 execute_branch_delay_instruction = true; |
| 1371 // Set next_pc |
| 1372 if (do_branch) { |
| 1373 next_pc = current_pc + (imm16 << 2) + Instruction::kInstructionSize; |
| 1374 } else { |
| 1375 next_pc = current_pc + kBranchReturnOffset; |
| 1376 } |
| 1229 break; | 1377 break; |
| 1230 default: | 1378 default: |
| 1231 UNREACHABLE(); | 1379 UNREACHABLE(); |
| 1232 }; | 1380 }; |
| 1233 break; | 1381 break; |
| 1234 // ------------- REGIMM class | 1382 // ------------- REGIMM class |
| 1235 case REGIMM: | 1383 case REGIMM: |
| 1236 switch (instr->RtFieldRaw()) { | 1384 switch (instr->RtFieldRaw()) { |
| 1237 case BLTZ: | 1385 case BLTZ: |
| 1238 do_branch = (rs < 0); | 1386 do_branch = (rs < 0); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1315 alu_out = rs ^ oe_imm16; | 1463 alu_out = rs ^ oe_imm16; |
| 1316 break; | 1464 break; |
| 1317 case LUI: | 1465 case LUI: |
| 1318 alu_out = (oe_imm16 << 16); | 1466 alu_out = (oe_imm16 << 16); |
| 1319 break; | 1467 break; |
| 1320 // ------------- Memory instructions | 1468 // ------------- Memory instructions |
| 1321 case LB: | 1469 case LB: |
| 1322 addr = rs + se_imm16; | 1470 addr = rs + se_imm16; |
| 1323 alu_out = ReadB(addr); | 1471 alu_out = ReadB(addr); |
| 1324 break; | 1472 break; |
| 1473 case LH: |
| 1474 addr = rs + se_imm16; |
| 1475 alu_out = ReadH(addr, instr); |
| 1476 break; |
| 1325 case LW: | 1477 case LW: |
| 1326 addr = rs + se_imm16; | 1478 addr = rs + se_imm16; |
| 1327 alu_out = ReadW(addr, instr); | 1479 alu_out = ReadW(addr, instr); |
| 1328 break; | 1480 break; |
| 1329 case LBU: | 1481 case LBU: |
| 1330 addr = rs + se_imm16; | 1482 addr = rs + se_imm16; |
| 1331 alu_out = ReadBU(addr); | 1483 alu_out = ReadBU(addr); |
| 1332 break; | 1484 break; |
| 1485 case LHU: |
| 1486 addr = rs + se_imm16; |
| 1487 alu_out = ReadHU(addr, instr); |
| 1488 break; |
| 1333 case SB: | 1489 case SB: |
| 1334 addr = rs + se_imm16; | 1490 addr = rs + se_imm16; |
| 1335 break; | 1491 break; |
| 1492 case SH: |
| 1493 addr = rs + se_imm16; |
| 1494 break; |
| 1336 case SW: | 1495 case SW: |
| 1337 addr = rs + se_imm16; | 1496 addr = rs + se_imm16; |
| 1338 break; | 1497 break; |
| 1339 case LWC1: | 1498 case LWC1: |
| 1340 addr = rs + se_imm16; | 1499 addr = rs + se_imm16; |
| 1341 alu_out = ReadW(addr, instr); | 1500 alu_out = ReadW(addr, instr); |
| 1342 break; | 1501 break; |
| 1343 case LDC1: | 1502 case LDC1: |
| 1344 addr = rs + se_imm16; | 1503 addr = rs + se_imm16; |
| 1345 fp_out = ReadD(addr, instr); | 1504 fp_out = ReadD(addr, instr); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1380 case SLTI: | 1539 case SLTI: |
| 1381 case SLTIU: | 1540 case SLTIU: |
| 1382 case ANDI: | 1541 case ANDI: |
| 1383 case ORI: | 1542 case ORI: |
| 1384 case XORI: | 1543 case XORI: |
| 1385 case LUI: | 1544 case LUI: |
| 1386 set_register(rt_reg, alu_out); | 1545 set_register(rt_reg, alu_out); |
| 1387 break; | 1546 break; |
| 1388 // ------------- Memory instructions | 1547 // ------------- Memory instructions |
| 1389 case LB: | 1548 case LB: |
| 1549 case LH: |
| 1390 case LW: | 1550 case LW: |
| 1391 case LBU: | 1551 case LBU: |
| 1552 case LHU: |
| 1392 set_register(rt_reg, alu_out); | 1553 set_register(rt_reg, alu_out); |
| 1393 break; | 1554 break; |
| 1394 case SB: | 1555 case SB: |
| 1395 WriteB(addr, static_cast<int8_t>(rt)); | 1556 WriteB(addr, static_cast<int8_t>(rt)); |
| 1396 break; | 1557 break; |
| 1558 case SH: |
| 1559 WriteH(addr, static_cast<uint16_t>(rt), instr); |
| 1560 break; |
| 1397 case SW: | 1561 case SW: |
| 1398 WriteW(addr, rt, instr); | 1562 WriteW(addr, rt, instr); |
| 1399 break; | 1563 break; |
| 1400 case LWC1: | 1564 case LWC1: |
| 1401 set_fpu_register(ft_reg, alu_out); | 1565 set_fpu_register(ft_reg, alu_out); |
| 1402 break; | 1566 break; |
| 1403 case LDC1: | 1567 case LDC1: |
| 1404 set_fpu_register_double(ft_reg, fp_out); | 1568 set_fpu_register_double(ft_reg, fp_out); |
| 1405 break; | 1569 break; |
| 1406 case SWC1: | 1570 case SWC1: |
| 1407 addr = rs + se_imm16; | 1571 addr = rs + se_imm16; |
| 1408 WriteW(addr, get_fpu_register(ft_reg), instr); | 1572 WriteW(addr, get_fpu_register(ft_reg), instr); |
| 1409 break; | 1573 break; |
| 1410 case SDC1: | 1574 case SDC1: |
| 1411 addr = rs + se_imm16; | 1575 addr = rs + se_imm16; |
| 1412 WriteD(addr, ft, instr); | 1576 WriteD(addr, get_fpu_register_double(ft_reg), instr); |
| 1413 break; | 1577 break; |
| 1414 default: | 1578 default: |
| 1415 break; | 1579 break; |
| 1416 }; | 1580 }; |
| 1417 | 1581 |
| 1418 | 1582 |
| 1419 if (execute_branch_delay_instruction) { | 1583 if (execute_branch_delay_instruction) { |
| 1420 // Execute branch delay slot | 1584 // Execute branch delay slot |
| 1421 // We don't check for end_sim_pc. First it should not be met as the current | 1585 // We don't check for end_sim_pc. First it should not be met as the current |
| 1422 // pc is valid. Secondly a jump should always execute its branch delay slot. | 1586 // pc is valid. Secondly a jump should always execute its branch delay slot. |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1530 ASSERT(argument_count >= 4); | 1694 ASSERT(argument_count >= 4); |
| 1531 set_register(a0, va_arg(parameters, int32_t)); | 1695 set_register(a0, va_arg(parameters, int32_t)); |
| 1532 set_register(a1, va_arg(parameters, int32_t)); | 1696 set_register(a1, va_arg(parameters, int32_t)); |
| 1533 set_register(a2, va_arg(parameters, int32_t)); | 1697 set_register(a2, va_arg(parameters, int32_t)); |
| 1534 set_register(a3, va_arg(parameters, int32_t)); | 1698 set_register(a3, va_arg(parameters, int32_t)); |
| 1535 | 1699 |
| 1536 // Remaining arguments passed on stack. | 1700 // Remaining arguments passed on stack. |
| 1537 int original_stack = get_register(sp); | 1701 int original_stack = get_register(sp); |
| 1538 // Compute position of stack on entry to generated code. | 1702 // Compute position of stack on entry to generated code. |
| 1539 int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t) | 1703 int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t) |
| 1540 - kArgsSlotsSize); | 1704 - kCArgsSlotsSize); |
| 1541 if (OS::ActivationFrameAlignment() != 0) { | 1705 if (OS::ActivationFrameAlignment() != 0) { |
| 1542 entry_stack &= -OS::ActivationFrameAlignment(); | 1706 entry_stack &= -OS::ActivationFrameAlignment(); |
| 1543 } | 1707 } |
| 1544 // Store remaining arguments on stack, from low to high memory. | 1708 // Store remaining arguments on stack, from low to high memory. |
| 1545 intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack); | 1709 intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack); |
| 1546 for (int i = 4; i < argument_count; i++) { | 1710 for (int i = 4; i < argument_count; i++) { |
| 1547 stack_argument[i - 4 + kArgsSlotsNum] = va_arg(parameters, int32_t); | 1711 stack_argument[i - 4 + kArgsSlotsNum] = va_arg(parameters, int32_t); |
| 1548 } | 1712 } |
| 1549 va_end(parameters); | 1713 va_end(parameters); |
| 1550 set_register(sp, entry_stack); | 1714 set_register(sp, entry_stack); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1639 return address; | 1803 return address; |
| 1640 } | 1804 } |
| 1641 | 1805 |
| 1642 | 1806 |
| 1643 #undef UNSUPPORTED | 1807 #undef UNSUPPORTED |
| 1644 | 1808 |
| 1645 } } // namespace assembler::mips | 1809 } } // namespace assembler::mips |
| 1646 | 1810 |
| 1647 #endif // !defined(__mips) | 1811 #endif // !defined(__mips) |
| 1648 | 1812 |
| OLD | NEW |