Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(338)

Side by Side Diff: src/mips/simulator-mips.cc

Issue 1320006: Updates and fixes for MIPS support. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698