OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <limits.h> | 5 #include <limits.h> |
6 #include <stdarg.h> | 6 #include <stdarg.h> |
7 #include <stdlib.h> | 7 #include <stdlib.h> |
8 #include <cmath> | 8 #include <cmath> |
9 | 9 |
10 #if V8_TARGET_ARCH_MIPS64 | 10 #if V8_TARGET_ARCH_MIPS64 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
89 // Set or delete a breakpoint. Returns true if successful. | 89 // Set or delete a breakpoint. Returns true if successful. |
90 bool SetBreakpoint(Instruction* breakpc); | 90 bool SetBreakpoint(Instruction* breakpc); |
91 bool DeleteBreakpoint(Instruction* breakpc); | 91 bool DeleteBreakpoint(Instruction* breakpc); |
92 | 92 |
93 // Undo and redo all breakpoints. This is needed to bracket disassembly and | 93 // Undo and redo all breakpoints. This is needed to bracket disassembly and |
94 // execution to skip past breakpoints when run from the debugger. | 94 // execution to skip past breakpoints when run from the debugger. |
95 void UndoBreakpoints(); | 95 void UndoBreakpoints(); |
96 void RedoBreakpoints(); | 96 void RedoBreakpoints(); |
97 }; | 97 }; |
98 | 98 |
99 #define UNSUPPORTED() printf("Sim: Unsupported instruction.\n"); | 99 inline void UNSUPPORTED() { printf("Sim: Unsupported instruction.\n"); } |
100 | 100 |
101 void MipsDebugger::Stop(Instruction* instr) { | 101 void MipsDebugger::Stop(Instruction* instr) { |
102 // Get the stop code. | 102 // Get the stop code. |
103 uint32_t code = instr->Bits(25, 6); | 103 uint32_t code = instr->Bits(25, 6); |
104 PrintF("Simulator hit (%u)\n", code); | 104 PrintF("Simulator hit (%u)\n", code); |
105 // TODO(yuyin): 2 -> 3? | 105 // TODO(yuyin): 2 -> 3? |
106 sim_->set_pc(sim_->get_pc() + 3 * Instruction::kInstrSize); | 106 sim_->set_pc(sim_->get_pc() + 3 * Instruction::kInstrSize); |
107 Debug(); | 107 Debug(); |
108 } | 108 } |
109 | 109 |
(...skipping 1818 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1928 typedef void (*SimulatorRuntimeDirectApiCall)(int64_t arg0); | 1928 typedef void (*SimulatorRuntimeDirectApiCall)(int64_t arg0); |
1929 typedef void (*SimulatorRuntimeProfilingApiCall)(int64_t arg0, void* arg1); | 1929 typedef void (*SimulatorRuntimeProfilingApiCall)(int64_t arg0, void* arg1); |
1930 | 1930 |
1931 // This signature supports direct call to accessor getter callback. | 1931 // This signature supports direct call to accessor getter callback. |
1932 typedef void (*SimulatorRuntimeDirectGetterCall)(int64_t arg0, int64_t arg1); | 1932 typedef void (*SimulatorRuntimeDirectGetterCall)(int64_t arg0, int64_t arg1); |
1933 typedef void (*SimulatorRuntimeProfilingGetterCall)( | 1933 typedef void (*SimulatorRuntimeProfilingGetterCall)( |
1934 int64_t arg0, int64_t arg1, void* arg2); | 1934 int64_t arg0, int64_t arg1, void* arg2); |
1935 | 1935 |
1936 // Software interrupt instructions are used by the simulator to call into the | 1936 // Software interrupt instructions are used by the simulator to call into the |
1937 // C-based V8 runtime. They are also used for debugging with simulator. | 1937 // C-based V8 runtime. They are also used for debugging with simulator. |
1938 void Simulator::SoftwareInterrupt(Instruction* instr) { | 1938 void Simulator::SoftwareInterrupt() { |
1939 // There are several instructions that could get us here, | 1939 // There are several instructions that could get us here, |
1940 // the break_ instruction, or several variants of traps. All | 1940 // the break_ instruction, or several variants of traps. All |
1941 // Are "SPECIAL" class opcode, and are distinuished by function. | 1941 // Are "SPECIAL" class opcode, and are distinuished by function. |
1942 int32_t func = instr->FunctionFieldRaw(); | 1942 int32_t func = instr_.FunctionFieldRaw(); |
1943 uint32_t code = (func == BREAK) ? instr->Bits(25, 6) : -1; | 1943 uint32_t code = (func == BREAK) ? instr_.Bits(25, 6) : -1; |
1944 // We first check if we met a call_rt_redirected. | 1944 // We first check if we met a call_rt_redirected. |
1945 if (instr->InstructionBits() == rtCallRedirInstr) { | 1945 if (instr_.InstructionBits() == rtCallRedirInstr) { |
1946 Redirection* redirection = Redirection::FromSwiInstruction(instr); | 1946 Redirection* redirection = Redirection::FromSwiInstruction(instr_.instr()); |
1947 int64_t arg0 = get_register(a0); | 1947 int64_t arg0 = get_register(a0); |
1948 int64_t arg1 = get_register(a1); | 1948 int64_t arg1 = get_register(a1); |
1949 int64_t arg2 = get_register(a2); | 1949 int64_t arg2 = get_register(a2); |
1950 int64_t arg3 = get_register(a3); | 1950 int64_t arg3 = get_register(a3); |
1951 int64_t arg4, arg5; | 1951 int64_t arg4, arg5; |
1952 | 1952 |
1953 arg4 = get_register(a4); // Abi n64 register a4. | 1953 arg4 = get_register(a4); // Abi n64 register a4. |
1954 arg5 = get_register(a5); // Abi n64 register a5. | 1954 arg5 = get_register(a5); // Abi n64 register a5. |
1955 | 1955 |
1956 bool fp_call = | 1956 bool fp_call = |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2162 get_register(v0)); | 2162 get_register(v0)); |
2163 } | 2163 } |
2164 set_register(ra, saved_ra); | 2164 set_register(ra, saved_ra); |
2165 set_pc(get_register(ra)); | 2165 set_pc(get_register(ra)); |
2166 | 2166 |
2167 } else if (func == BREAK && code <= kMaxStopCode) { | 2167 } else if (func == BREAK && code <= kMaxStopCode) { |
2168 if (IsWatchpoint(code)) { | 2168 if (IsWatchpoint(code)) { |
2169 PrintWatchpoint(code); | 2169 PrintWatchpoint(code); |
2170 } else { | 2170 } else { |
2171 IncreaseStopCounter(code); | 2171 IncreaseStopCounter(code); |
2172 HandleStop(code, instr); | 2172 HandleStop(code, instr_.instr()); |
2173 } | 2173 } |
2174 } else { | 2174 } else { |
2175 // All remaining break_ codes, and all traps are handled here. | 2175 // All remaining break_ codes, and all traps are handled here. |
2176 MipsDebugger dbg(this); | 2176 MipsDebugger dbg(this); |
2177 dbg.Debug(); | 2177 dbg.Debug(); |
2178 } | 2178 } |
2179 } | 2179 } |
2180 | 2180 |
2181 | 2181 |
2182 // Stop helper functions. | 2182 // Stop helper functions. |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2410 // Handle execution based on instruction types. | 2410 // Handle execution based on instruction types. |
2411 | 2411 |
2412 void Simulator::DecodeTypeRegisterSRsType() { | 2412 void Simulator::DecodeTypeRegisterSRsType() { |
2413 float fs, ft, fd; | 2413 float fs, ft, fd; |
2414 fs = get_fpu_register_float(fs_reg()); | 2414 fs = get_fpu_register_float(fs_reg()); |
2415 ft = get_fpu_register_float(ft_reg()); | 2415 ft = get_fpu_register_float(ft_reg()); |
2416 fd = get_fpu_register_float(fd_reg()); | 2416 fd = get_fpu_register_float(fd_reg()); |
2417 int32_t ft_int = bit_cast<int32_t>(ft); | 2417 int32_t ft_int = bit_cast<int32_t>(ft); |
2418 int32_t fd_int = bit_cast<int32_t>(fd); | 2418 int32_t fd_int = bit_cast<int32_t>(fd); |
2419 uint32_t cc, fcsr_cc; | 2419 uint32_t cc, fcsr_cc; |
2420 cc = get_instr()->FCccValue(); | 2420 cc = instr_.FCccValue(); |
2421 fcsr_cc = get_fcsr_condition_bit(cc); | 2421 fcsr_cc = get_fcsr_condition_bit(cc); |
2422 switch (get_instr()->FunctionFieldRaw()) { | 2422 switch (instr_.FunctionFieldRaw()) { |
2423 case RINT: { | 2423 case RINT: { |
2424 DCHECK(kArchVariant == kMips64r6); | 2424 DCHECK(kArchVariant == kMips64r6); |
2425 float result, temp_result; | 2425 float result, temp_result; |
2426 double temp; | 2426 double temp; |
2427 float upper = std::ceil(fs); | 2427 float upper = std::ceil(fs); |
2428 float lower = std::floor(fs); | 2428 float lower = std::floor(fs); |
2429 switch (get_fcsr_rounding_mode()) { | 2429 switch (get_fcsr_rounding_mode()) { |
2430 case kRoundToNearest: | 2430 case kRoundToNearest: |
2431 if (upper - fs < fs - lower) { | 2431 if (upper - fs < fs - lower) { |
2432 result = upper; | 2432 result = upper; |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2756 if (rt() != 0) { | 2756 if (rt() != 0) { |
2757 set_fpu_register_float(fd_reg(), fs); | 2757 set_fpu_register_float(fd_reg(), fs); |
2758 } | 2758 } |
2759 break; | 2759 break; |
2760 } | 2760 } |
2761 case MOVF: { | 2761 case MOVF: { |
2762 // Same function field for MOVT.D and MOVF.D | 2762 // Same function field for MOVT.D and MOVF.D |
2763 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; | 2763 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; |
2764 ft_cc = get_fcsr_condition_bit(ft_cc); | 2764 ft_cc = get_fcsr_condition_bit(ft_cc); |
2765 | 2765 |
2766 if (get_instr()->Bit(16)) { // Read Tf bit. | 2766 if (instr_.Bit(16)) { // Read Tf bit. |
2767 // MOVT.D | 2767 // MOVT.D |
2768 if (test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs); | 2768 if (test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs); |
2769 } else { | 2769 } else { |
2770 // MOVF.D | 2770 // MOVF.D |
2771 if (!test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs); | 2771 if (!test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs); |
2772 } | 2772 } |
2773 break; | 2773 break; |
2774 } | 2774 } |
2775 default: | 2775 default: |
2776 // TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S | 2776 // TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S |
2777 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented. | 2777 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented. |
2778 UNREACHABLE(); | 2778 UNREACHABLE(); |
2779 } | 2779 } |
2780 } | 2780 } |
2781 | 2781 |
2782 | 2782 |
2783 void Simulator::DecodeTypeRegisterDRsType() { | 2783 void Simulator::DecodeTypeRegisterDRsType() { |
2784 double ft, fs, fd; | 2784 double ft, fs, fd; |
2785 uint32_t cc, fcsr_cc; | 2785 uint32_t cc, fcsr_cc; |
2786 fs = get_fpu_register_double(fs_reg()); | 2786 fs = get_fpu_register_double(fs_reg()); |
2787 ft = (get_instr()->FunctionFieldRaw() != MOVF) | 2787 ft = (instr_.FunctionFieldRaw() != MOVF) ? get_fpu_register_double(ft_reg()) |
2788 ? get_fpu_register_double(ft_reg()) | 2788 : 0.0; |
2789 : 0.0; | |
2790 fd = get_fpu_register_double(fd_reg()); | 2789 fd = get_fpu_register_double(fd_reg()); |
2791 cc = get_instr()->FCccValue(); | 2790 cc = instr_.FCccValue(); |
2792 fcsr_cc = get_fcsr_condition_bit(cc); | 2791 fcsr_cc = get_fcsr_condition_bit(cc); |
2793 int64_t ft_int = bit_cast<int64_t>(ft); | 2792 int64_t ft_int = bit_cast<int64_t>(ft); |
2794 int64_t fd_int = bit_cast<int64_t>(fd); | 2793 int64_t fd_int = bit_cast<int64_t>(fd); |
2795 switch (get_instr()->FunctionFieldRaw()) { | 2794 switch (instr_.FunctionFieldRaw()) { |
2796 case RINT: { | 2795 case RINT: { |
2797 DCHECK(kArchVariant == kMips64r6); | 2796 DCHECK(kArchVariant == kMips64r6); |
2798 double result, temp, temp_result; | 2797 double result, temp, temp_result; |
2799 double upper = std::ceil(fs); | 2798 double upper = std::ceil(fs); |
2800 double lower = std::floor(fs); | 2799 double lower = std::floor(fs); |
2801 switch (get_fcsr_rounding_mode()) { | 2800 switch (get_fcsr_rounding_mode()) { |
2802 case kRoundToNearest: | 2801 case kRoundToNearest: |
2803 if (upper - fs < fs - lower) { | 2802 if (upper - fs < fs - lower) { |
2804 result = upper; | 2803 result = upper; |
2805 } else if (upper - fs > fs - lower) { | 2804 } else if (upper - fs > fs - lower) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2853 DCHECK(kArchVariant == kMips64r2); | 2852 DCHECK(kArchVariant == kMips64r2); |
2854 if (rt() != 0) { | 2853 if (rt() != 0) { |
2855 set_fpu_register_double(fd_reg(), fs); | 2854 set_fpu_register_double(fd_reg(), fs); |
2856 } | 2855 } |
2857 break; | 2856 break; |
2858 } | 2857 } |
2859 case MOVF: { | 2858 case MOVF: { |
2860 // Same function field for MOVT.D and MOVF.D | 2859 // Same function field for MOVT.D and MOVF.D |
2861 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; | 2860 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; |
2862 ft_cc = get_fcsr_condition_bit(ft_cc); | 2861 ft_cc = get_fcsr_condition_bit(ft_cc); |
2863 if (get_instr()->Bit(16)) { // Read Tf bit. | 2862 if (instr_.Bit(16)) { // Read Tf bit. |
2864 // MOVT.D | 2863 // MOVT.D |
2865 if (test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); | 2864 if (test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); |
2866 } else { | 2865 } else { |
2867 // MOVF.D | 2866 // MOVF.D |
2868 if (!test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); | 2867 if (!test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); |
2869 } | 2868 } |
2870 break; | 2869 break; |
2871 } | 2870 } |
2872 case MINA: | 2871 case MINA: |
2873 DCHECK(kArchVariant == kMips64r6); | 2872 DCHECK(kArchVariant == kMips64r6); |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3144 default: | 3143 default: |
3145 UNREACHABLE(); | 3144 UNREACHABLE(); |
3146 } | 3145 } |
3147 } | 3146 } |
3148 | 3147 |
3149 | 3148 |
3150 void Simulator::DecodeTypeRegisterWRsType() { | 3149 void Simulator::DecodeTypeRegisterWRsType() { |
3151 float fs = get_fpu_register_float(fs_reg()); | 3150 float fs = get_fpu_register_float(fs_reg()); |
3152 float ft = get_fpu_register_float(ft_reg()); | 3151 float ft = get_fpu_register_float(ft_reg()); |
3153 int64_t alu_out = 0x12345678; | 3152 int64_t alu_out = 0x12345678; |
3154 switch (get_instr()->FunctionFieldRaw()) { | 3153 switch (instr_.FunctionFieldRaw()) { |
3155 case CVT_S_W: // Convert word to float (single). | 3154 case CVT_S_W: // Convert word to float (single). |
3156 alu_out = get_fpu_register_signed_word(fs_reg()); | 3155 alu_out = get_fpu_register_signed_word(fs_reg()); |
3157 set_fpu_register_float(fd_reg(), static_cast<float>(alu_out)); | 3156 set_fpu_register_float(fd_reg(), static_cast<float>(alu_out)); |
3158 break; | 3157 break; |
3159 case CVT_D_W: // Convert word to double. | 3158 case CVT_D_W: // Convert word to double. |
3160 alu_out = get_fpu_register_signed_word(fs_reg()); | 3159 alu_out = get_fpu_register_signed_word(fs_reg()); |
3161 set_fpu_register_double(fd_reg(), static_cast<double>(alu_out)); | 3160 set_fpu_register_double(fd_reg(), static_cast<double>(alu_out)); |
3162 break; | 3161 break; |
3163 case CMP_AF: | 3162 case CMP_AF: |
3164 set_fpu_register_word(fd_reg(), 0); | 3163 set_fpu_register_word(fd_reg(), 0); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3236 default: | 3235 default: |
3237 UNREACHABLE(); | 3236 UNREACHABLE(); |
3238 } | 3237 } |
3239 } | 3238 } |
3240 | 3239 |
3241 | 3240 |
3242 void Simulator::DecodeTypeRegisterLRsType() { | 3241 void Simulator::DecodeTypeRegisterLRsType() { |
3243 double fs = get_fpu_register_double(fs_reg()); | 3242 double fs = get_fpu_register_double(fs_reg()); |
3244 double ft = get_fpu_register_double(ft_reg()); | 3243 double ft = get_fpu_register_double(ft_reg()); |
3245 int64_t i64; | 3244 int64_t i64; |
3246 switch (get_instr()->FunctionFieldRaw()) { | 3245 switch (instr_.FunctionFieldRaw()) { |
3247 case CVT_D_L: // Mips32r2 instruction. | 3246 case CVT_D_L: // Mips32r2 instruction. |
3248 i64 = get_fpu_register(fs_reg()); | 3247 i64 = get_fpu_register(fs_reg()); |
3249 set_fpu_register_double(fd_reg(), static_cast<double>(i64)); | 3248 set_fpu_register_double(fd_reg(), static_cast<double>(i64)); |
3250 break; | 3249 break; |
3251 case CVT_S_L: | 3250 case CVT_S_L: |
3252 i64 = get_fpu_register(fs_reg()); | 3251 i64 = get_fpu_register(fs_reg()); |
3253 set_fpu_register_float(fd_reg(), static_cast<float>(i64)); | 3252 set_fpu_register_float(fd_reg(), static_cast<float>(i64)); |
3254 break; | 3253 break; |
3255 case CMP_AF: | 3254 case CMP_AF: |
3256 set_fpu_register(fd_reg(), 0); | 3255 set_fpu_register(fd_reg(), 0); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3325 set_fpu_register(fd_reg(), 0); | 3324 set_fpu_register(fd_reg(), 0); |
3326 } | 3325 } |
3327 break; | 3326 break; |
3328 default: | 3327 default: |
3329 UNREACHABLE(); | 3328 UNREACHABLE(); |
3330 } | 3329 } |
3331 } | 3330 } |
3332 | 3331 |
3333 | 3332 |
3334 void Simulator::DecodeTypeRegisterCOP1() { | 3333 void Simulator::DecodeTypeRegisterCOP1() { |
3335 switch (get_instr()->RsFieldRaw()) { | 3334 switch (instr_.RsFieldRaw()) { |
3336 case BC1: // Branch on coprocessor condition. | 3335 case BC1: // Branch on coprocessor condition. |
3337 case BC1EQZ: | 3336 case BC1EQZ: |
3338 case BC1NEZ: | 3337 case BC1NEZ: |
3339 UNREACHABLE(); | 3338 UNREACHABLE(); |
3340 break; | 3339 break; |
3341 case CFC1: | 3340 case CFC1: |
3342 // At the moment only FCSR is supported. | 3341 // At the moment only FCSR is supported. |
3343 DCHECK(fs_reg() == kFCSRRegister); | 3342 DCHECK(fs_reg() == kFCSRRegister); |
3344 set_register(rt_reg(), FCSR_); | 3343 set_register(rt_reg(), FCSR_); |
3345 break; | 3344 break; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3388 case L: | 3387 case L: |
3389 DecodeTypeRegisterLRsType(); | 3388 DecodeTypeRegisterLRsType(); |
3390 break; | 3389 break; |
3391 default: | 3390 default: |
3392 UNREACHABLE(); | 3391 UNREACHABLE(); |
3393 } | 3392 } |
3394 } | 3393 } |
3395 | 3394 |
3396 | 3395 |
3397 void Simulator::DecodeTypeRegisterCOP1X() { | 3396 void Simulator::DecodeTypeRegisterCOP1X() { |
3398 switch (get_instr()->FunctionFieldRaw()) { | 3397 switch (instr_.FunctionFieldRaw()) { |
3399 case MADD_S: { | 3398 case MADD_S: { |
3400 DCHECK(kArchVariant == kMips64r2); | 3399 DCHECK(kArchVariant == kMips64r2); |
3401 float fr, ft, fs; | 3400 float fr, ft, fs; |
3402 fr = get_fpu_register_float(fr_reg()); | 3401 fr = get_fpu_register_float(fr_reg()); |
3403 fs = get_fpu_register_float(fs_reg()); | 3402 fs = get_fpu_register_float(fs_reg()); |
3404 ft = get_fpu_register_float(ft_reg()); | 3403 ft = get_fpu_register_float(ft_reg()); |
3405 set_fpu_register_float(fd_reg(), fs * ft + fr); | 3404 set_fpu_register_float(fd_reg(), fs * ft + fr); |
3406 break; | 3405 break; |
3407 } | 3406 } |
3408 case MSUB_S: { | 3407 case MSUB_S: { |
(...skipping 28 matching lines...) Expand all Loading... | |
3437 } | 3436 } |
3438 } | 3437 } |
3439 | 3438 |
3440 | 3439 |
3441 void Simulator::DecodeTypeRegisterSPECIAL() { | 3440 void Simulator::DecodeTypeRegisterSPECIAL() { |
3442 int64_t i64hilo; | 3441 int64_t i64hilo; |
3443 uint64_t u64hilo; | 3442 uint64_t u64hilo; |
3444 int64_t alu_out; | 3443 int64_t alu_out; |
3445 bool do_interrupt = false; | 3444 bool do_interrupt = false; |
3446 | 3445 |
3447 switch (get_instr()->FunctionFieldRaw()) { | 3446 switch (instr_.FunctionFieldRaw()) { |
3448 case SELEQZ_S: | 3447 case SELEQZ_S: |
3449 DCHECK(kArchVariant == kMips64r6); | 3448 DCHECK(kArchVariant == kMips64r6); |
3450 set_register(rd_reg(), rt() == 0 ? rs() : 0); | 3449 set_register(rd_reg(), rt() == 0 ? rs() : 0); |
3451 break; | 3450 break; |
3452 case SELNEZ_S: | 3451 case SELNEZ_S: |
3453 DCHECK(kArchVariant == kMips64r6); | 3452 DCHECK(kArchVariant == kMips64r6); |
3454 set_register(rd_reg(), rt() != 0 ? rs() : 0); | 3453 set_register(rd_reg(), rt() != 0 ? rs() : 0); |
3455 break; | 3454 break; |
3456 case JR: { | 3455 case JR: { |
3457 int64_t next_pc = rs(); | 3456 int64_t next_pc = rs(); |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3683 break; | 3682 break; |
3684 } | 3683 } |
3685 } | 3684 } |
3686 break; | 3685 break; |
3687 case DMULTU: | 3686 case DMULTU: |
3688 UNIMPLEMENTED_MIPS(); | 3687 UNIMPLEMENTED_MIPS(); |
3689 break; | 3688 break; |
3690 case DIV: | 3689 case DIV: |
3691 case DDIV: { | 3690 case DDIV: { |
3692 const int64_t int_min_value = | 3691 const int64_t int_min_value = |
3693 get_instr()->FunctionFieldRaw() == DIV ? INT_MIN : LONG_MIN; | 3692 instr_.FunctionFieldRaw() == DIV ? INT_MIN : LONG_MIN; |
3694 switch (kArchVariant) { | 3693 switch (kArchVariant) { |
3695 case kMips64r2: | 3694 case kMips64r2: |
3696 // Divide by zero and overflow was not checked in the | 3695 // Divide by zero and overflow was not checked in the |
3697 // configuration step - div and divu do not raise exceptions. On | 3696 // configuration step - div and divu do not raise exceptions. On |
3698 // division by 0 the result will be UNPREDICTABLE. On overflow | 3697 // division by 0 the result will be UNPREDICTABLE. On overflow |
3699 // (INT_MIN/-1), return INT_MIN which is what the hardware does. | 3698 // (INT_MIN/-1), return INT_MIN which is what the hardware does. |
3700 if (rs() == int_min_value && rt() == -1) { | 3699 if (rs() == int_min_value && rt() == -1) { |
3701 set_register(LO, int_min_value); | 3700 set_register(LO, int_min_value); |
3702 set_register(HI, 0); | 3701 set_register(HI, 0); |
3703 } else if (rt() != 0) { | 3702 } else if (rt() != 0) { |
(...skipping 25 matching lines...) Expand all Loading... | |
3729 default: | 3728 default: |
3730 break; | 3729 break; |
3731 } | 3730 } |
3732 break; | 3731 break; |
3733 } | 3732 } |
3734 case DIVU: | 3733 case DIVU: |
3735 switch (kArchVariant) { | 3734 switch (kArchVariant) { |
3736 case kMips64r6: { | 3735 case kMips64r6: { |
3737 uint32_t rt_u_32 = static_cast<uint32_t>(rt_u()); | 3736 uint32_t rt_u_32 = static_cast<uint32_t>(rt_u()); |
3738 uint32_t rs_u_32 = static_cast<uint32_t>(rs_u()); | 3737 uint32_t rs_u_32 = static_cast<uint32_t>(rs_u()); |
3739 switch (get_instr()->SaValue()) { | 3738 switch (sa()) { |
3740 case DIV_OP: | 3739 case DIV_OP: |
3741 if (rt_u_32 != 0) { | 3740 if (rt_u_32 != 0) { |
3742 set_register(rd_reg(), rs_u_32 / rt_u_32); | 3741 set_register(rd_reg(), rs_u_32 / rt_u_32); |
3743 } | 3742 } |
3744 break; | 3743 break; |
3745 case MOD_OP: | 3744 case MOD_OP: |
3746 if (rt_u() != 0) { | 3745 if (rt_u() != 0) { |
3747 set_register(rd_reg(), rs_u_32 % rt_u_32); | 3746 set_register(rd_reg(), rs_u_32 % rt_u_32); |
3748 } | 3747 } |
3749 break; | 3748 break; |
3750 default: | 3749 default: |
3751 UNIMPLEMENTED_MIPS(); | 3750 UNIMPLEMENTED_MIPS(); |
3752 break; | 3751 break; |
3753 } | 3752 } |
3754 } break; | 3753 } break; |
3755 default: { | 3754 default: { |
3756 if (rt_u() != 0) { | 3755 if (rt_u() != 0) { |
3757 uint32_t rt_u_32 = static_cast<uint32_t>(rt_u()); | 3756 uint32_t rt_u_32 = static_cast<uint32_t>(rt_u()); |
3758 uint32_t rs_u_32 = static_cast<uint32_t>(rs_u()); | 3757 uint32_t rs_u_32 = static_cast<uint32_t>(rs_u()); |
3759 set_register(LO, rs_u_32 / rt_u_32); | 3758 set_register(LO, rs_u_32 / rt_u_32); |
3760 set_register(HI, rs_u_32 % rt_u_32); | 3759 set_register(HI, rs_u_32 % rt_u_32); |
3761 } | 3760 } |
3762 } | 3761 } |
3763 } | 3762 } |
3764 break; | 3763 break; |
3765 case DDIVU: | 3764 case DDIVU: |
3766 switch (kArchVariant) { | 3765 switch (kArchVariant) { |
3767 case kMips64r6: { | 3766 case kMips64r6: { |
3768 switch (get_instr()->SaValue()) { | 3767 switch (instr_.SaValue()) { |
3769 case DIV_OP: | 3768 case DIV_OP: |
3770 if (rt_u() != 0) { | 3769 if (rt_u() != 0) { |
3771 set_register(rd_reg(), rs_u() / rt_u()); | 3770 set_register(rd_reg(), rs_u() / rt_u()); |
3772 } | 3771 } |
3773 break; | 3772 break; |
3774 case MOD_OP: | 3773 case MOD_OP: |
3775 if (rt_u() != 0) { | 3774 if (rt_u() != 0) { |
3776 set_register(rd_reg(), rs_u() % rt_u()); | 3775 set_register(rd_reg(), rs_u() % rt_u()); |
3777 } | 3776 } |
3778 break; | 3777 break; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3880 case SYNC: | 3879 case SYNC: |
3881 // TODO(palfia): Ignore sync instruction for now. | 3880 // TODO(palfia): Ignore sync instruction for now. |
3882 break; | 3881 break; |
3883 // Conditional moves. | 3882 // Conditional moves. |
3884 case MOVN: | 3883 case MOVN: |
3885 if (rt()) { | 3884 if (rt()) { |
3886 SetResult(rd_reg(), rs()); | 3885 SetResult(rd_reg(), rs()); |
3887 } | 3886 } |
3888 break; | 3887 break; |
3889 case MOVCI: { | 3888 case MOVCI: { |
3890 uint32_t cc = get_instr()->FBccValue(); | 3889 uint32_t cc = instr_.FBccValue(); |
3891 uint32_t fcsr_cc = get_fcsr_condition_bit(cc); | 3890 uint32_t fcsr_cc = get_fcsr_condition_bit(cc); |
3892 if (get_instr()->Bit(16)) { // Read Tf bit. | 3891 if (instr_.Bit(16)) { // Read Tf bit. |
3893 if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs()); | 3892 if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs()); |
3894 } else { | 3893 } else { |
3895 if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs()); | 3894 if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs()); |
3896 } | 3895 } |
3897 break; | 3896 break; |
3898 } | 3897 } |
3899 case MOVZ: | 3898 case MOVZ: |
3900 if (!rt()) { | 3899 if (!rt()) { |
3901 SetResult(rd_reg(), rs()); | 3900 SetResult(rd_reg(), rs()); |
3902 } | 3901 } |
3903 break; | 3902 break; |
3904 default: | 3903 default: |
3905 UNREACHABLE(); | 3904 UNREACHABLE(); |
3906 } | 3905 } |
3907 if (do_interrupt) { | 3906 if (do_interrupt) { |
3908 SoftwareInterrupt(get_instr()); | 3907 SoftwareInterrupt(); |
3909 } | 3908 } |
3910 } | 3909 } |
3911 | 3910 |
3912 | 3911 |
3913 void Simulator::DecodeTypeRegisterSPECIAL2() { | 3912 void Simulator::DecodeTypeRegisterSPECIAL2() { |
3914 int64_t alu_out; | 3913 int64_t alu_out; |
3915 switch (get_instr()->FunctionFieldRaw()) { | 3914 switch (instr_.FunctionFieldRaw()) { |
3916 case MUL: | 3915 case MUL: |
3917 alu_out = static_cast<int32_t>(rs_u()) * static_cast<int32_t>(rt_u()); | 3916 alu_out = static_cast<int32_t>(rs_u()) * static_cast<int32_t>(rt_u()); |
3918 SetResult(rd_reg(), alu_out); | 3917 SetResult(rd_reg(), alu_out); |
3919 // HI and LO are UNPREDICTABLE after the operation. | 3918 // HI and LO are UNPREDICTABLE after the operation. |
3920 set_register(LO, Unpredictable); | 3919 set_register(LO, Unpredictable); |
3921 set_register(HI, Unpredictable); | 3920 set_register(HI, Unpredictable); |
3922 break; | 3921 break; |
3923 case CLZ: | 3922 case CLZ: |
3924 // MIPS32 spec: If no bits were set in GPR rs(), the result written to | 3923 // MIPS32 spec: If no bits were set in GPR rs(), the result written to |
3925 // GPR rd is 32. | 3924 // GPR rd is 32. |
3926 alu_out = base::bits::CountLeadingZeros32(static_cast<uint32_t>(rs_u())); | 3925 alu_out = base::bits::CountLeadingZeros32(static_cast<uint32_t>(rs_u())); |
3927 SetResult(rd_reg(), alu_out); | 3926 SetResult(rd_reg(), alu_out); |
3928 break; | 3927 break; |
3929 case DCLZ: | 3928 case DCLZ: |
3930 // MIPS64 spec: If no bits were set in GPR rs(), the result written to | 3929 // MIPS64 spec: If no bits were set in GPR rs(), the result written to |
3931 // GPR rd is 64. | 3930 // GPR rd is 64. |
3932 alu_out = base::bits::CountLeadingZeros64(static_cast<uint64_t>(rs_u())); | 3931 alu_out = base::bits::CountLeadingZeros64(static_cast<uint64_t>(rs_u())); |
3933 SetResult(rd_reg(), alu_out); | 3932 SetResult(rd_reg(), alu_out); |
3934 break; | 3933 break; |
3935 default: | 3934 default: |
3936 alu_out = 0x12345678; | 3935 alu_out = 0x12345678; |
3937 UNREACHABLE(); | 3936 UNREACHABLE(); |
3938 } | 3937 } |
3939 } | 3938 } |
3940 | 3939 |
3941 | 3940 |
3942 void Simulator::DecodeTypeRegisterSPECIAL3() { | 3941 void Simulator::DecodeTypeRegisterSPECIAL3() { |
3943 int64_t alu_out; | 3942 int64_t alu_out; |
3944 switch (get_instr()->FunctionFieldRaw()) { | 3943 switch (instr_.FunctionFieldRaw()) { |
3945 case INS: { // Mips64r2 instruction. | 3944 case INS: { // Mips64r2 instruction. |
3946 // Interpret rd field as 5-bit msb of insert. | 3945 // Interpret rd field as 5-bit msb of insert. |
3947 uint16_t msb = rd_reg(); | 3946 uint16_t msb = rd_reg(); |
3948 // Interpret sa field as 5-bit lsb of insert. | 3947 // Interpret sa field as 5-bit lsb of insert. |
3949 uint16_t lsb = sa(); | 3948 uint16_t lsb = sa(); |
3950 uint16_t size = msb - lsb + 1; | 3949 uint16_t size = msb - lsb + 1; |
3951 uint64_t mask = (1ULL << size) - 1; | 3950 uint64_t mask = (1ULL << size) - 1; |
3952 alu_out = static_cast<int32_t>((rt_u() & ~(mask << lsb)) | | 3951 alu_out = static_cast<int32_t>((rt_u() & ~(mask << lsb)) | |
3953 ((rs_u() & mask) << lsb)); | 3952 ((rs_u() & mask) << lsb)); |
3954 SetResult(rt_reg(), alu_out); | 3953 SetResult(rt_reg(), alu_out); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4003 uint16_t msb = rd_reg(); | 4002 uint16_t msb = rd_reg(); |
4004 // Interpret sa field as 5-bit lsb of extract. | 4003 // Interpret sa field as 5-bit lsb of extract. |
4005 uint16_t lsb = sa() + 32; | 4004 uint16_t lsb = sa() + 32; |
4006 uint16_t size = msb + 1; | 4005 uint16_t size = msb + 1; |
4007 uint64_t mask = (1ULL << size) - 1; | 4006 uint64_t mask = (1ULL << size) - 1; |
4008 alu_out = static_cast<int64_t>((rs_u() & (mask << lsb)) >> lsb); | 4007 alu_out = static_cast<int64_t>((rs_u() & (mask << lsb)) >> lsb); |
4009 SetResult(rt_reg(), alu_out); | 4008 SetResult(rt_reg(), alu_out); |
4010 break; | 4009 break; |
4011 } | 4010 } |
4012 case BSHFL: { | 4011 case BSHFL: { |
4013 int32_t sa = get_instr()->SaFieldRaw() >> kSaShift; | 4012 int32_t sa = instr_.SaFieldRaw() >> kSaShift; |
4014 switch (sa) { | 4013 switch (sa) { |
4015 case BITSWAP: { | 4014 case BITSWAP: { |
4016 uint32_t input = static_cast<uint32_t>(rt()); | 4015 uint32_t input = static_cast<uint32_t>(rt()); |
4017 uint32_t output = 0; | 4016 uint32_t output = 0; |
4018 uint8_t i_byte, o_byte; | 4017 uint8_t i_byte, o_byte; |
4019 | 4018 |
4020 // Reverse the bit in byte for each individual byte | 4019 // Reverse the bit in byte for each individual byte |
4021 for (int i = 0; i < 4; i++) { | 4020 for (int i = 0; i < 4; i++) { |
4022 output = output >> 8; | 4021 output = output >> 8; |
4023 i_byte = input & 0xff; | 4022 i_byte = input & 0xff; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4081 | 4080 |
4082 // Extending sign | 4081 // Extending sign |
4083 if (mask & output) { | 4082 if (mask & output) { |
4084 output |= 0xFFFFFFFF00000000; | 4083 output |= 0xFFFFFFFF00000000; |
4085 } | 4084 } |
4086 | 4085 |
4087 alu_out = static_cast<int64_t>(output); | 4086 alu_out = static_cast<int64_t>(output); |
4088 break; | 4087 break; |
4089 } | 4088 } |
4090 default: { | 4089 default: { |
4091 const uint8_t bp2 = get_instr()->Bp2Value(); | 4090 const uint8_t bp2 = instr_.Bp2Value(); |
4092 sa >>= kBp2Bits; | 4091 sa >>= kBp2Bits; |
4093 switch (sa) { | 4092 switch (sa) { |
4094 case ALIGN: { | 4093 case ALIGN: { |
4095 if (bp2 == 0) { | 4094 if (bp2 == 0) { |
4096 alu_out = static_cast<int32_t>(rt()); | 4095 alu_out = static_cast<int32_t>(rt()); |
4097 } else { | 4096 } else { |
4098 uint64_t rt_hi = rt() << (8 * bp2); | 4097 uint64_t rt_hi = rt() << (8 * bp2); |
4099 uint64_t rs_lo = rs() >> (8 * (4 - bp2)); | 4098 uint64_t rs_lo = rs() >> (8 * (4 - bp2)); |
4100 alu_out = static_cast<int32_t>(rt_hi | rs_lo); | 4099 alu_out = static_cast<int32_t>(rt_hi | rs_lo); |
4101 } | 4100 } |
4102 break; | 4101 break; |
4103 } | 4102 } |
4104 default: | 4103 default: |
4105 alu_out = 0x12345678; | 4104 alu_out = 0x12345678; |
4106 UNREACHABLE(); | 4105 UNREACHABLE(); |
4107 break; | 4106 break; |
4108 } | 4107 } |
4109 break; | 4108 break; |
4110 } | 4109 } |
4111 } | 4110 } |
4112 SetResult(rd_reg(), alu_out); | 4111 SetResult(rd_reg(), alu_out); |
4113 break; | 4112 break; |
4114 } | 4113 } |
4115 case DBSHFL: { | 4114 case DBSHFL: { |
4116 int32_t sa = get_instr()->SaFieldRaw() >> kSaShift; | 4115 int32_t sa = instr_.SaFieldRaw() >> kSaShift; |
4117 switch (sa) { | 4116 switch (sa) { |
4118 case DBITSWAP: { | 4117 case DBITSWAP: { |
4119 switch (sa) { | 4118 switch (sa) { |
4120 case DBITSWAP_SA: { // Mips64r6 | 4119 case DBITSWAP_SA: { // Mips64r6 |
4121 uint64_t input = static_cast<uint64_t>(rt()); | 4120 uint64_t input = static_cast<uint64_t>(rt()); |
4122 uint64_t output = 0; | 4121 uint64_t output = 0; |
4123 uint8_t i_byte, o_byte; | 4122 uint8_t i_byte, o_byte; |
4124 | 4123 |
4125 // Reverse the bit in byte for each individual byte | 4124 // Reverse the bit in byte for each individual byte |
4126 for (int i = 0; i < 8; i++) { | 4125 for (int i = 0; i < 8; i++) { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4180 else | 4179 else |
4181 tmp = tmp << 48; | 4180 tmp = tmp << 48; |
4182 output = output | tmp; | 4181 output = output | tmp; |
4183 mask = mask >> 16; | 4182 mask = mask >> 16; |
4184 } | 4183 } |
4185 | 4184 |
4186 alu_out = static_cast<int64_t>(output); | 4185 alu_out = static_cast<int64_t>(output); |
4187 break; | 4186 break; |
4188 } | 4187 } |
4189 default: { | 4188 default: { |
4190 const uint8_t bp3 = get_instr()->Bp3Value(); | 4189 const uint8_t bp3 = instr_.Bp3Value(); |
4191 sa >>= kBp3Bits; | 4190 sa >>= kBp3Bits; |
4192 switch (sa) { | 4191 switch (sa) { |
4193 case DALIGN: { | 4192 case DALIGN: { |
4194 if (bp3 == 0) { | 4193 if (bp3 == 0) { |
4195 alu_out = static_cast<int64_t>(rt()); | 4194 alu_out = static_cast<int64_t>(rt()); |
4196 } else { | 4195 } else { |
4197 uint64_t rt_hi = rt() << (8 * bp3); | 4196 uint64_t rt_hi = rt() << (8 * bp3); |
4198 uint64_t rs_lo = rs() >> (8 * (8 - bp3)); | 4197 uint64_t rs_lo = rs() >> (8 * (8 - bp3)); |
4199 alu_out = static_cast<int64_t>(rt_hi | rs_lo); | 4198 alu_out = static_cast<int64_t>(rt_hi | rs_lo); |
4200 } | 4199 } |
4201 break; | 4200 break; |
4202 } | 4201 } |
4203 default: | 4202 default: |
4204 alu_out = 0x12345678; | 4203 alu_out = 0x12345678; |
4205 UNREACHABLE(); | 4204 UNREACHABLE(); |
4206 break; | 4205 break; |
4207 } | 4206 } |
4208 break; | 4207 break; |
4209 } | 4208 } |
4210 } | 4209 } |
4211 SetResult(rd_reg(), alu_out); | 4210 SetResult(rd_reg(), alu_out); |
4212 break; | 4211 break; |
4213 } | 4212 } |
4214 default: | 4213 default: |
4215 UNREACHABLE(); | 4214 UNREACHABLE(); |
4216 } | 4215 } |
4217 } | 4216 } |
4218 | 4217 |
4219 | 4218 void Simulator::DecodeTypeRegister() { |
4220 void Simulator::DecodeTypeRegister(Instruction* instr) { | |
4221 set_instr(instr); | |
4222 | |
4223 // ---------- Execution. | 4219 // ---------- Execution. |
4224 switch (instr->OpcodeFieldRaw()) { | 4220 switch (instr_.OpcodeFieldRaw()) { |
4225 case COP1: | 4221 case COP1: |
4226 DecodeTypeRegisterCOP1(); | 4222 DecodeTypeRegisterCOP1(); |
4227 break; | 4223 break; |
4228 case COP1X: | 4224 case COP1X: |
4229 DecodeTypeRegisterCOP1X(); | 4225 DecodeTypeRegisterCOP1X(); |
4230 break; | 4226 break; |
4231 case SPECIAL: | 4227 case SPECIAL: |
4232 DecodeTypeRegisterSPECIAL(); | 4228 DecodeTypeRegisterSPECIAL(); |
4233 break; | 4229 break; |
4234 case SPECIAL2: | 4230 case SPECIAL2: |
4235 DecodeTypeRegisterSPECIAL2(); | 4231 DecodeTypeRegisterSPECIAL2(); |
4236 break; | 4232 break; |
4237 case SPECIAL3: | 4233 case SPECIAL3: |
4238 DecodeTypeRegisterSPECIAL3(); | 4234 DecodeTypeRegisterSPECIAL3(); |
4239 break; | 4235 break; |
4240 // Unimplemented opcodes raised an error in the configuration step before, | 4236 // Unimplemented opcodes raised an error in the configuration step before, |
4241 // so we can use the default here to set the destination register in common | 4237 // so we can use the default here to set the destination register in common |
4242 // cases. | 4238 // cases. |
4243 default: | 4239 default: |
4244 UNREACHABLE(); | 4240 UNREACHABLE(); |
4245 } | 4241 } |
4246 } | 4242 } |
4247 | 4243 |
4248 | 4244 |
4249 // Type 2: instructions using a 16, 21 or 26 bits immediate. (e.g. beq, beqc). | 4245 // Type 2: instructions using a 16, 21 or 26 bits immediate. (e.g. beq, beqc). |
4250 void Simulator::DecodeTypeImmediate(Instruction* instr) { | 4246 void Simulator::DecodeTypeImmediate() { |
4251 // Instruction fields. | 4247 // Instruction fields. |
4252 Opcode op = instr->OpcodeFieldRaw(); | 4248 Opcode op = instr_.OpcodeFieldRaw(); |
4253 int32_t rs_reg = instr->RsValue(); | 4249 int32_t rs_reg = instr_.RsValue(); |
4254 int64_t rs = get_register(instr->RsValue()); | 4250 int64_t rs = get_register(instr_.RsValue()); |
4255 uint64_t rs_u = static_cast<uint64_t>(rs); | 4251 uint64_t rs_u = static_cast<uint64_t>(rs); |
4256 int32_t rt_reg = instr->RtValue(); // Destination register. | 4252 int32_t rt_reg = instr_.RtValue(); // Destination register. |
4257 int64_t rt = get_register(rt_reg); | 4253 int64_t rt = get_register(rt_reg); |
4258 int16_t imm16 = instr->Imm16Value(); | 4254 int16_t imm16 = instr_.Imm16Value(); |
4259 int32_t imm18 = instr->Imm18Value(); | 4255 int32_t imm18 = instr_.Imm18Value(); |
4260 | 4256 |
4261 int32_t ft_reg = instr->FtValue(); // Destination register. | 4257 int32_t ft_reg = instr_.FtValue(); // Destination register. |
4262 | 4258 |
4263 // Zero extended immediate. | 4259 // Zero extended immediate. |
4264 uint64_t oe_imm16 = 0xffff & imm16; | 4260 uint64_t oe_imm16 = 0xffff & imm16; |
4265 // Sign extended immediate. | 4261 // Sign extended immediate. |
4266 int64_t se_imm16 = imm16; | 4262 int64_t se_imm16 = imm16; |
4267 int64_t se_imm18 = imm18 | ((imm18 & 0x20000) ? 0xfffffffffffc0000 : 0); | 4263 int64_t se_imm18 = imm18 | ((imm18 & 0x20000) ? 0xfffffffffffc0000 : 0); |
4268 | 4264 |
4269 // Next pc. | 4265 // Next pc. |
4270 int64_t next_pc = bad_ra; | 4266 int64_t next_pc = bad_ra; |
4271 | 4267 |
4272 // Used for conditional branch instructions. | 4268 // Used for conditional branch instructions. |
4273 bool execute_branch_delay_instruction = false; | 4269 bool execute_branch_delay_instruction = false; |
4274 | 4270 |
4275 // Used for arithmetic instructions. | 4271 // Used for arithmetic instructions. |
4276 int64_t alu_out = 0; | 4272 int64_t alu_out = 0; |
4277 | 4273 |
4278 // Used for memory instructions. | 4274 // Used for memory instructions. |
4279 int64_t addr = 0x0; | 4275 int64_t addr = 0x0; |
4280 // Alignment for 32-bit integers used in LWL, LWR, etc. | 4276 // Alignment for 32-bit integers used in LWL, LWR, etc. |
4281 const int kInt32AlignmentMask = sizeof(uint32_t) - 1; | 4277 const int kInt32AlignmentMask = sizeof(uint32_t) - 1; |
4282 // Alignment for 64-bit integers used in LDL, LDR, etc. | 4278 // Alignment for 64-bit integers used in LDL, LDR, etc. |
4283 const int kInt64AlignmentMask = sizeof(uint64_t) - 1; | 4279 const int kInt64AlignmentMask = sizeof(uint64_t) - 1; |
4284 | 4280 |
4285 // Branch instructions common part. | 4281 // Branch instructions common part. |
4286 auto BranchAndLinkHelper = [this, instr, &next_pc, | 4282 auto BranchAndLinkHelper = |
4287 &execute_branch_delay_instruction]( | 4283 [this, &next_pc, &execute_branch_delay_instruction](bool do_branch) { |
4288 bool do_branch) { | 4284 execute_branch_delay_instruction = true; |
4289 execute_branch_delay_instruction = true; | 4285 int64_t current_pc = get_pc(); |
4290 int64_t current_pc = get_pc(); | 4286 if (do_branch) { |
4291 if (do_branch) { | 4287 int16_t imm16 = instr_.Imm16Value(); |
4292 int16_t imm16 = instr->Imm16Value(); | 4288 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; |
4293 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; | 4289 set_register(31, current_pc + 2 * Instruction::kInstrSize); |
4294 set_register(31, current_pc + 2 * Instruction::kInstrSize); | 4290 } else { |
4295 } else { | 4291 next_pc = current_pc + 2 * Instruction::kInstrSize; |
4296 next_pc = current_pc + 2 * Instruction::kInstrSize; | 4292 } |
4297 } | 4293 }; |
4298 }; | |
4299 | 4294 |
4300 auto BranchHelper = [this, instr, &next_pc, | 4295 auto BranchHelper = [this, &next_pc, |
4301 &execute_branch_delay_instruction](bool do_branch) { | 4296 &execute_branch_delay_instruction](bool do_branch) { |
4302 execute_branch_delay_instruction = true; | 4297 execute_branch_delay_instruction = true; |
4303 int64_t current_pc = get_pc(); | 4298 int64_t current_pc = get_pc(); |
4304 if (do_branch) { | 4299 if (do_branch) { |
4305 int16_t imm16 = instr->Imm16Value(); | 4300 int16_t imm16 = instr_.Imm16Value(); |
4306 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; | 4301 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; |
4307 } else { | 4302 } else { |
4308 next_pc = current_pc + 2 * Instruction::kInstrSize; | 4303 next_pc = current_pc + 2 * Instruction::kInstrSize; |
4309 } | 4304 } |
4310 }; | 4305 }; |
4311 | 4306 |
4312 auto BranchAndLinkCompactHelper = [this, instr, &next_pc](bool do_branch, | 4307 auto BranchAndLinkCompactHelper = [this, &next_pc](bool do_branch, int bits) { |
4313 int bits) { | |
4314 int64_t current_pc = get_pc(); | 4308 int64_t current_pc = get_pc(); |
4315 CheckForbiddenSlot(current_pc); | 4309 CheckForbiddenSlot(current_pc); |
4316 if (do_branch) { | 4310 if (do_branch) { |
4317 int32_t imm = instr->ImmValue(bits); | 4311 int32_t imm = instr_.ImmValue(bits); |
4318 imm <<= 32 - bits; | 4312 imm <<= 32 - bits; |
4319 imm >>= 32 - bits; | 4313 imm >>= 32 - bits; |
4320 next_pc = current_pc + (imm << 2) + Instruction::kInstrSize; | 4314 next_pc = current_pc + (imm << 2) + Instruction::kInstrSize; |
4321 set_register(31, current_pc + Instruction::kInstrSize); | 4315 set_register(31, current_pc + Instruction::kInstrSize); |
4322 } | 4316 } |
4323 }; | 4317 }; |
4324 | 4318 |
4325 auto BranchCompactHelper = [&next_pc, this, instr](bool do_branch, int bits) { | 4319 auto BranchCompactHelper = [this, &next_pc](bool do_branch, int bits) { |
4326 int64_t current_pc = get_pc(); | 4320 int64_t current_pc = get_pc(); |
4327 CheckForbiddenSlot(current_pc); | 4321 CheckForbiddenSlot(current_pc); |
4328 if (do_branch) { | 4322 if (do_branch) { |
4329 int32_t imm = instr->ImmValue(bits); | 4323 int32_t imm = instr_.ImmValue(bits); |
4330 imm <<= 32 - bits; | 4324 imm <<= 32 - bits; |
4331 imm >>= 32 - bits; | 4325 imm >>= 32 - bits; |
4332 next_pc = get_pc() + (imm << 2) + Instruction::kInstrSize; | 4326 next_pc = get_pc() + (imm << 2) + Instruction::kInstrSize; |
4333 } | 4327 } |
4334 }; | 4328 }; |
4335 | 4329 |
4336 switch (op) { | 4330 switch (op) { |
4337 // ------------- COP1. Coprocessor instructions. | 4331 // ------------- COP1. Coprocessor instructions. |
4338 case COP1: | 4332 case COP1: |
4339 switch (instr->RsFieldRaw()) { | 4333 switch (instr_.RsFieldRaw()) { |
4340 case BC1: { // Branch on coprocessor condition. | 4334 case BC1: { // Branch on coprocessor condition. |
4341 uint32_t cc = instr->FBccValue(); | 4335 uint32_t cc = instr_.FBccValue(); |
4342 uint32_t fcsr_cc = get_fcsr_condition_bit(cc); | 4336 uint32_t fcsr_cc = get_fcsr_condition_bit(cc); |
4343 uint32_t cc_value = test_fcsr_bit(fcsr_cc); | 4337 uint32_t cc_value = test_fcsr_bit(fcsr_cc); |
4344 bool do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value; | 4338 bool do_branch = (instr_.FBtrueValue()) ? cc_value : !cc_value; |
4345 BranchHelper(do_branch); | 4339 BranchHelper(do_branch); |
4346 break; | 4340 break; |
4347 } | 4341 } |
4348 case BC1EQZ: | 4342 case BC1EQZ: |
4349 BranchHelper(!(get_fpu_register(ft_reg) & 0x1)); | 4343 BranchHelper(!(get_fpu_register(ft_reg) & 0x1)); |
4350 break; | 4344 break; |
4351 case BC1NEZ: | 4345 case BC1NEZ: |
4352 BranchHelper(get_fpu_register(ft_reg) & 0x1); | 4346 BranchHelper(get_fpu_register(ft_reg) & 0x1); |
4353 break; | 4347 break; |
4354 default: | 4348 default: |
4355 UNREACHABLE(); | 4349 UNREACHABLE(); |
4356 } | 4350 } |
4357 break; | 4351 break; |
4358 // ------------- REGIMM class. | 4352 // ------------- REGIMM class. |
4359 case REGIMM: | 4353 case REGIMM: |
4360 switch (instr->RtFieldRaw()) { | 4354 switch (instr_.RtFieldRaw()) { |
4361 case BLTZ: | 4355 case BLTZ: |
4362 BranchHelper(rs < 0); | 4356 BranchHelper(rs < 0); |
4363 break; | 4357 break; |
4364 case BGEZ: | 4358 case BGEZ: |
4365 BranchHelper(rs >= 0); | 4359 BranchHelper(rs >= 0); |
4366 break; | 4360 break; |
4367 case BLTZAL: | 4361 case BLTZAL: |
4368 BranchAndLinkHelper(rs < 0); | 4362 BranchAndLinkHelper(rs < 0); |
4369 break; | 4363 break; |
4370 case BGEZAL: | 4364 case BGEZAL: |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4568 case DAUI: | 4562 case DAUI: |
4569 DCHECK(kArchVariant == kMips64r6); | 4563 DCHECK(kArchVariant == kMips64r6); |
4570 DCHECK(rs_reg != 0); | 4564 DCHECK(rs_reg != 0); |
4571 SetResult(rt_reg, rs + (se_imm16 << 16)); | 4565 SetResult(rt_reg, rs + (se_imm16 << 16)); |
4572 break; | 4566 break; |
4573 // ------------- Memory instructions. | 4567 // ------------- Memory instructions. |
4574 case LB: | 4568 case LB: |
4575 set_register(rt_reg, ReadB(rs + se_imm16)); | 4569 set_register(rt_reg, ReadB(rs + se_imm16)); |
4576 break; | 4570 break; |
4577 case LH: | 4571 case LH: |
4578 set_register(rt_reg, ReadH(rs + se_imm16, instr)); | 4572 set_register(rt_reg, ReadH(rs + se_imm16, instr_.instr())); |
4579 break; | 4573 break; |
4580 case LWL: { | 4574 case LWL: { |
4581 // al_offset is offset of the effective address within an aligned word. | 4575 // al_offset is offset of the effective address within an aligned word. |
4582 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask; | 4576 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask; |
4583 uint8_t byte_shift = kInt32AlignmentMask - al_offset; | 4577 uint8_t byte_shift = kInt32AlignmentMask - al_offset; |
4584 uint32_t mask = (1 << byte_shift * 8) - 1; | 4578 uint32_t mask = (1 << byte_shift * 8) - 1; |
4585 addr = rs + se_imm16 - al_offset; | 4579 addr = rs + se_imm16 - al_offset; |
4586 int32_t val = ReadW(addr, instr); | 4580 int32_t val = ReadW(addr, instr_.instr()); |
4587 val <<= byte_shift * 8; | 4581 val <<= byte_shift * 8; |
4588 val |= rt & mask; | 4582 val |= rt & mask; |
4589 set_register(rt_reg, static_cast<int64_t>(val)); | 4583 set_register(rt_reg, static_cast<int64_t>(val)); |
4590 break; | 4584 break; |
4591 } | 4585 } |
4592 case LW: | 4586 case LW: |
4593 set_register(rt_reg, ReadW(rs + se_imm16, instr)); | 4587 set_register(rt_reg, ReadW(rs + se_imm16, instr_.instr())); |
4594 break; | 4588 break; |
4595 case LWU: | 4589 case LWU: |
4596 set_register(rt_reg, ReadWU(rs + se_imm16, instr)); | 4590 set_register(rt_reg, ReadWU(rs + se_imm16, instr_.instr())); |
4597 break; | 4591 break; |
4598 case LD: | 4592 case LD: |
4599 set_register(rt_reg, Read2W(rs + se_imm16, instr)); | 4593 set_register(rt_reg, Read2W(rs + se_imm16, instr_.instr())); |
4600 break; | 4594 break; |
4601 case LBU: | 4595 case LBU: |
4602 set_register(rt_reg, ReadBU(rs + se_imm16)); | 4596 set_register(rt_reg, ReadBU(rs + se_imm16)); |
4603 break; | 4597 break; |
4604 case LHU: | 4598 case LHU: |
4605 set_register(rt_reg, ReadHU(rs + se_imm16, instr)); | 4599 set_register(rt_reg, ReadHU(rs + se_imm16, instr_.instr())); |
4606 break; | 4600 break; |
4607 case LWR: { | 4601 case LWR: { |
4608 // al_offset is offset of the effective address within an aligned word. | 4602 // al_offset is offset of the effective address within an aligned word. |
4609 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask; | 4603 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask; |
4610 uint8_t byte_shift = kInt32AlignmentMask - al_offset; | 4604 uint8_t byte_shift = kInt32AlignmentMask - al_offset; |
4611 uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0; | 4605 uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0; |
4612 addr = rs + se_imm16 - al_offset; | 4606 addr = rs + se_imm16 - al_offset; |
4613 alu_out = ReadW(addr, instr); | 4607 alu_out = ReadW(addr, instr_.instr()); |
4614 alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8; | 4608 alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8; |
4615 alu_out |= rt & mask; | 4609 alu_out |= rt & mask; |
4616 set_register(rt_reg, alu_out); | 4610 set_register(rt_reg, alu_out); |
4617 break; | 4611 break; |
4618 } | 4612 } |
4619 case LDL: { | 4613 case LDL: { |
4620 // al_offset is offset of the effective address within an aligned word. | 4614 // al_offset is offset of the effective address within an aligned word. |
4621 uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask; | 4615 uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask; |
4622 uint8_t byte_shift = kInt64AlignmentMask - al_offset; | 4616 uint8_t byte_shift = kInt64AlignmentMask - al_offset; |
4623 uint64_t mask = (1UL << byte_shift * 8) - 1; | 4617 uint64_t mask = (1UL << byte_shift * 8) - 1; |
4624 addr = rs + se_imm16 - al_offset; | 4618 addr = rs + se_imm16 - al_offset; |
4625 alu_out = Read2W(addr, instr); | 4619 alu_out = Read2W(addr, instr_.instr()); |
4626 alu_out <<= byte_shift * 8; | 4620 alu_out <<= byte_shift * 8; |
4627 alu_out |= rt & mask; | 4621 alu_out |= rt & mask; |
4628 set_register(rt_reg, alu_out); | 4622 set_register(rt_reg, alu_out); |
4629 break; | 4623 break; |
4630 } | 4624 } |
4631 case LDR: { | 4625 case LDR: { |
4632 // al_offset is offset of the effective address within an aligned word. | 4626 // al_offset is offset of the effective address within an aligned word. |
4633 uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask; | 4627 uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask; |
4634 uint8_t byte_shift = kInt64AlignmentMask - al_offset; | 4628 uint8_t byte_shift = kInt64AlignmentMask - al_offset; |
4635 uint64_t mask = al_offset ? (~0UL << (byte_shift + 1) * 8) : 0UL; | 4629 uint64_t mask = al_offset ? (~0UL << (byte_shift + 1) * 8) : 0UL; |
4636 addr = rs + se_imm16 - al_offset; | 4630 addr = rs + se_imm16 - al_offset; |
4637 alu_out = Read2W(addr, instr); | 4631 alu_out = Read2W(addr, instr_.instr()); |
4638 alu_out = alu_out >> al_offset * 8; | 4632 alu_out = alu_out >> al_offset * 8; |
4639 alu_out |= rt & mask; | 4633 alu_out |= rt & mask; |
4640 set_register(rt_reg, alu_out); | 4634 set_register(rt_reg, alu_out); |
4641 break; | 4635 break; |
4642 } | 4636 } |
4643 case SB: | 4637 case SB: |
4644 WriteB(rs + se_imm16, static_cast<int8_t>(rt)); | 4638 WriteB(rs + se_imm16, static_cast<int8_t>(rt)); |
4645 break; | 4639 break; |
4646 case SH: | 4640 case SH: |
4647 WriteH(rs + se_imm16, static_cast<uint16_t>(rt), instr); | 4641 WriteH(rs + se_imm16, static_cast<uint16_t>(rt), instr_.instr()); |
4648 break; | 4642 break; |
4649 case SWL: { | 4643 case SWL: { |
4650 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask; | 4644 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask; |
4651 uint8_t byte_shift = kInt32AlignmentMask - al_offset; | 4645 uint8_t byte_shift = kInt32AlignmentMask - al_offset; |
4652 uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0; | 4646 uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0; |
4653 addr = rs + se_imm16 - al_offset; | 4647 addr = rs + se_imm16 - al_offset; |
4654 uint64_t mem_value = ReadW(addr, instr) & mask; | 4648 uint64_t mem_value = ReadW(addr, instr_.instr()) & mask; |
4655 mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8; | 4649 mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8; |
4656 WriteW(addr, static_cast<int32_t>(mem_value), instr); | 4650 WriteW(addr, static_cast<int32_t>(mem_value), instr_.instr()); |
4657 break; | 4651 break; |
4658 } | 4652 } |
4659 case SW: | 4653 case SW: |
4660 WriteW(rs + se_imm16, static_cast<int32_t>(rt), instr); | 4654 WriteW(rs + se_imm16, static_cast<int32_t>(rt), instr_.instr()); |
4661 break; | 4655 break; |
4662 case SD: | 4656 case SD: |
4663 Write2W(rs + se_imm16, rt, instr); | 4657 Write2W(rs + se_imm16, rt, instr_.instr()); |
4664 break; | 4658 break; |
4665 case SWR: { | 4659 case SWR: { |
4666 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask; | 4660 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask; |
4667 uint32_t mask = (1 << al_offset * 8) - 1; | 4661 uint32_t mask = (1 << al_offset * 8) - 1; |
4668 addr = rs + se_imm16 - al_offset; | 4662 addr = rs + se_imm16 - al_offset; |
4669 uint64_t mem_value = ReadW(addr, instr); | 4663 uint64_t mem_value = ReadW(addr, instr_.instr()); |
4670 mem_value = (rt << al_offset * 8) | (mem_value & mask); | 4664 mem_value = (rt << al_offset * 8) | (mem_value & mask); |
4671 WriteW(addr, static_cast<int32_t>(mem_value), instr); | 4665 WriteW(addr, static_cast<int32_t>(mem_value), instr_.instr()); |
4672 break; | 4666 break; |
4673 } | 4667 } |
4674 case SDL: { | 4668 case SDL: { |
4675 uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask; | 4669 uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask; |
4676 uint8_t byte_shift = kInt64AlignmentMask - al_offset; | 4670 uint8_t byte_shift = kInt64AlignmentMask - al_offset; |
4677 uint64_t mask = byte_shift ? (~0UL << (al_offset + 1) * 8) : 0; | 4671 uint64_t mask = byte_shift ? (~0UL << (al_offset + 1) * 8) : 0; |
4678 addr = rs + se_imm16 - al_offset; | 4672 addr = rs + se_imm16 - al_offset; |
4679 uint64_t mem_value = Read2W(addr, instr) & mask; | 4673 uint64_t mem_value = Read2W(addr, instr_.instr()) & mask; |
4680 mem_value |= rt >> byte_shift * 8; | 4674 mem_value |= rt >> byte_shift * 8; |
4681 Write2W(addr, mem_value, instr); | 4675 Write2W(addr, mem_value, instr_.instr()); |
4682 break; | 4676 break; |
4683 } | 4677 } |
4684 case SDR: { | 4678 case SDR: { |
4685 uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask; | 4679 uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask; |
4686 uint64_t mask = (1UL << al_offset * 8) - 1; | 4680 uint64_t mask = (1UL << al_offset * 8) - 1; |
4687 addr = rs + se_imm16 - al_offset; | 4681 addr = rs + se_imm16 - al_offset; |
4688 uint64_t mem_value = Read2W(addr, instr); | 4682 uint64_t mem_value = Read2W(addr, instr_.instr()); |
4689 mem_value = (rt << al_offset * 8) | (mem_value & mask); | 4683 mem_value = (rt << al_offset * 8) | (mem_value & mask); |
4690 Write2W(addr, mem_value, instr); | 4684 Write2W(addr, mem_value, instr_.instr()); |
4691 break; | 4685 break; |
4692 } | 4686 } |
4693 case LWC1: | 4687 case LWC1: |
4694 set_fpu_register(ft_reg, kFPUInvalidResult); // Trash upper 32 bits. | 4688 set_fpu_register(ft_reg, kFPUInvalidResult); // Trash upper 32 bits. |
4695 set_fpu_register_word(ft_reg, ReadW(rs + se_imm16, instr)); | 4689 set_fpu_register_word(ft_reg, ReadW(rs + se_imm16, instr_.instr())); |
4696 break; | 4690 break; |
4697 case LDC1: | 4691 case LDC1: |
4698 set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr)); | 4692 set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr_.instr())); |
4699 break; | 4693 break; |
4700 case SWC1: { | 4694 case SWC1: { |
4701 int32_t alu_out_32 = static_cast<int32_t>(get_fpu_register(ft_reg)); | 4695 int32_t alu_out_32 = static_cast<int32_t>(get_fpu_register(ft_reg)); |
4702 WriteW(rs + se_imm16, alu_out_32, instr); | 4696 WriteW(rs + se_imm16, alu_out_32, instr_.instr()); |
4703 break; | 4697 break; |
4704 } | 4698 } |
4705 case SDC1: | 4699 case SDC1: |
4706 WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr); | 4700 WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr_.instr()); |
4707 break; | 4701 break; |
4708 // ------------- PC-Relative instructions. | 4702 // ------------- PC-Relative instructions. |
4709 case PCREL: { | 4703 case PCREL: { |
4710 // rt field: checking 5-bits. | 4704 // rt field: checking 5-bits. |
4711 int32_t imm21 = instr->Imm21Value(); | 4705 int32_t imm21 = instr_.Imm21Value(); |
4712 int64_t current_pc = get_pc(); | 4706 int64_t current_pc = get_pc(); |
4713 uint8_t rt = (imm21 >> kImm16Bits); | 4707 uint8_t rt = (imm21 >> kImm16Bits); |
4714 switch (rt) { | 4708 switch (rt) { |
4715 case ALUIPC: | 4709 case ALUIPC: |
4716 addr = current_pc + (se_imm16 << 16); | 4710 addr = current_pc + (se_imm16 << 16); |
4717 alu_out = static_cast<int64_t>(~0x0FFFF) & addr; | 4711 alu_out = static_cast<int64_t>(~0x0FFFF) & addr; |
4718 break; | 4712 break; |
4719 case AUIPC: | 4713 case AUIPC: |
4720 alu_out = current_pc + (se_imm16 << 16); | 4714 alu_out = current_pc + (se_imm16 << 16); |
4721 break; | 4715 break; |
4722 default: { | 4716 default: { |
4723 int32_t imm19 = instr->Imm19Value(); | 4717 int32_t imm19 = instr_.Imm19Value(); |
4724 // rt field: checking the most significant 3-bits. | 4718 // rt field: checking the most significant 3-bits. |
4725 rt = (imm21 >> kImm18Bits); | 4719 rt = (imm21 >> kImm18Bits); |
4726 switch (rt) { | 4720 switch (rt) { |
4727 case LDPC: | 4721 case LDPC: |
4728 addr = | 4722 addr = |
4729 (current_pc & static_cast<int64_t>(~0x7)) + (se_imm18 << 3); | 4723 (current_pc & static_cast<int64_t>(~0x7)) + (se_imm18 << 3); |
4730 alu_out = Read2W(addr, instr); | 4724 alu_out = Read2W(addr, instr_.instr()); |
4731 break; | 4725 break; |
4732 default: { | 4726 default: { |
4733 // rt field: checking the most significant 2-bits. | 4727 // rt field: checking the most significant 2-bits. |
4734 rt = (imm21 >> kImm19Bits); | 4728 rt = (imm21 >> kImm19Bits); |
4735 switch (rt) { | 4729 switch (rt) { |
4736 case LWUPC: { | 4730 case LWUPC: { |
4737 // Set sign. | 4731 // Set sign. |
4738 imm19 <<= (kOpcodeBits + kRsBits + 2); | 4732 imm19 <<= (kOpcodeBits + kRsBits + 2); |
4739 imm19 >>= (kOpcodeBits + kRsBits + 2); | 4733 imm19 >>= (kOpcodeBits + kRsBits + 2); |
4740 addr = current_pc + (imm19 << 2); | 4734 addr = current_pc + (imm19 << 2); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4784 } | 4778 } |
4785 | 4779 |
4786 // If needed update pc after the branch delay execution. | 4780 // If needed update pc after the branch delay execution. |
4787 if (next_pc != bad_ra) { | 4781 if (next_pc != bad_ra) { |
4788 set_pc(next_pc); | 4782 set_pc(next_pc); |
4789 } | 4783 } |
4790 } | 4784 } |
4791 | 4785 |
4792 | 4786 |
4793 // Type 3: instructions using a 26 bytes immediate. (e.g. j, jal). | 4787 // Type 3: instructions using a 26 bytes immediate. (e.g. j, jal). |
4794 void Simulator::DecodeTypeJump(Instruction* instr) { | 4788 void Simulator::DecodeTypeJump() { |
4789 SimInstruction simInstr = instr_; | |
Ilija.Pavlovic1
2016/09/29 10:13:40
Why this variable is defined? instr_ is the same t
balazs.kilvady
2016/09/29 10:57:41
A copy of the current instruction is needed here a
Ilija.Pavlovic1
2016/09/29 13:15:33
Acknowledged.
| |
4795 // Get current pc. | 4790 // Get current pc. |
4796 int64_t current_pc = get_pc(); | 4791 int64_t current_pc = get_pc(); |
4797 // Get unchanged bits of pc. | 4792 // Get unchanged bits of pc. |
4798 int64_t pc_high_bits = current_pc & 0xfffffffff0000000; | 4793 int64_t pc_high_bits = current_pc & 0xfffffffff0000000; |
4799 // Next pc. | 4794 // Next pc. |
4800 int64_t next_pc = pc_high_bits | (instr->Imm26Value() << 2); | 4795 int64_t next_pc = pc_high_bits | (simInstr.Imm26Value() << 2); |
4801 | 4796 |
4802 // Execute branch delay slot. | 4797 // Execute branch delay slot. |
4803 // We don't check for end_sim_pc. First it should not be met as the current pc | 4798 // We don't check for end_sim_pc. First it should not be met as the current pc |
4804 // is valid. Secondly a jump should always execute its branch delay slot. | 4799 // is valid. Secondly a jump should always execute its branch delay slot. |
4805 Instruction* branch_delay_instr = | 4800 Instruction* branch_delay_instr = |
4806 reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize); | 4801 reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize); |
4807 BranchDelayInstructionDecode(branch_delay_instr); | 4802 BranchDelayInstructionDecode(branch_delay_instr); |
4808 | 4803 |
4809 // Update pc and ra if necessary. | 4804 // Update pc and ra if necessary. |
4810 // Do this after the branch delay execution. | 4805 // Do this after the branch delay execution. |
4811 if (instr->IsLinkingInstruction()) { | 4806 if (simInstr.IsLinkingInstruction()) { |
4812 set_register(31, current_pc + 2 * Instruction::kInstrSize); | 4807 set_register(31, current_pc + 2 * Instruction::kInstrSize); |
4813 } | 4808 } |
4814 set_pc(next_pc); | 4809 set_pc(next_pc); |
4815 pc_modified_ = true; | 4810 pc_modified_ = true; |
4816 } | 4811 } |
4817 | 4812 |
4818 | 4813 |
4819 // Executes the current instruction. | 4814 // Executes the current instruction. |
4820 void Simulator::InstructionDecode(Instruction* instr) { | 4815 void Simulator::InstructionDecode(Instruction* instr) { |
4821 if (v8::internal::FLAG_check_icache) { | 4816 if (v8::internal::FLAG_check_icache) { |
4822 CheckICache(isolate_->simulator_i_cache(), instr); | 4817 CheckICache(isolate_->simulator_i_cache(), instr); |
4823 } | 4818 } |
4824 pc_modified_ = false; | 4819 pc_modified_ = false; |
4825 | 4820 |
4826 v8::internal::EmbeddedVector<char, 256> buffer; | 4821 v8::internal::EmbeddedVector<char, 256> buffer; |
4827 | 4822 |
4828 if (::v8::internal::FLAG_trace_sim) { | 4823 if (::v8::internal::FLAG_trace_sim) { |
4829 SNPrintF(trace_buf_, " "); | 4824 SNPrintF(trace_buf_, " "); |
4830 disasm::NameConverter converter; | 4825 disasm::NameConverter converter; |
4831 disasm::Disassembler dasm(converter); | 4826 disasm::Disassembler dasm(converter); |
4832 // Use a reasonably large buffer. | 4827 // Use a reasonably large buffer. |
4833 dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr)); | 4828 dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr)); |
4834 } | 4829 } |
4835 | 4830 |
4836 switch (instr->InstructionType(Instruction::TypeChecks::EXTRA)) { | 4831 instr_ = instr; |
Ilija.Pavlovic1
2016/09/29 10:13:39
Was it possible to do the same thing as for Decode
balazs.kilvady
2016/09/29 10:57:41
No, this function is the main entry point for proc
Ilija.Pavlovic1
2016/09/29 13:15:33
Acknowledged.
| |
4832 switch (instr_.InstructionType()) { | |
4837 case Instruction::kRegisterType: | 4833 case Instruction::kRegisterType: |
4838 DecodeTypeRegister(instr); | 4834 DecodeTypeRegister(); |
4839 break; | 4835 break; |
4840 case Instruction::kImmediateType: | 4836 case Instruction::kImmediateType: |
4841 DecodeTypeImmediate(instr); | 4837 DecodeTypeImmediate(); |
4842 break; | 4838 break; |
4843 case Instruction::kJumpType: | 4839 case Instruction::kJumpType: |
4844 DecodeTypeJump(instr); | 4840 DecodeTypeJump(); |
4845 break; | 4841 break; |
4846 default: | 4842 default: |
4847 UNSUPPORTED(); | 4843 UNSUPPORTED(); |
4848 } | 4844 } |
4849 | 4845 |
4850 if (::v8::internal::FLAG_trace_sim) { | 4846 if (::v8::internal::FLAG_trace_sim) { |
4851 PrintF(" 0x%08" PRIxPTR " %-44s %s\n", | 4847 PrintF(" 0x%08" PRIxPTR " %-44s %s\n", |
4852 reinterpret_cast<intptr_t>(instr), buffer.start(), | 4848 reinterpret_cast<intptr_t>(instr), buffer.start(), |
4853 trace_buf_.start()); | 4849 trace_buf_.start()); |
4854 } | 4850 } |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5053 } | 5049 } |
5054 | 5050 |
5055 | 5051 |
5056 #undef UNSUPPORTED | 5052 #undef UNSUPPORTED |
5057 } // namespace internal | 5053 } // namespace internal |
5058 } // namespace v8 | 5054 } // namespace v8 |
5059 | 5055 |
5060 #endif // USE_SIMULATOR | 5056 #endif // USE_SIMULATOR |
5061 | 5057 |
5062 #endif // V8_TARGET_ARCH_MIPS64 | 5058 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |