| 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_MIPS | 10 #if V8_TARGET_ARCH_MIPS |
| (...skipping 1911 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1922 typedef void (*SimulatorRuntimeDirectApiCall)(int32_t arg0); | 1922 typedef void (*SimulatorRuntimeDirectApiCall)(int32_t arg0); |
| 1923 typedef void (*SimulatorRuntimeProfilingApiCall)(int32_t arg0, void* arg1); | 1923 typedef void (*SimulatorRuntimeProfilingApiCall)(int32_t arg0, void* arg1); |
| 1924 | 1924 |
| 1925 // This signature supports direct call to accessor getter callback. | 1925 // This signature supports direct call to accessor getter callback. |
| 1926 typedef void (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, int32_t arg1); | 1926 typedef void (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, int32_t arg1); |
| 1927 typedef void (*SimulatorRuntimeProfilingGetterCall)( | 1927 typedef void (*SimulatorRuntimeProfilingGetterCall)( |
| 1928 int32_t arg0, int32_t arg1, void* arg2); | 1928 int32_t arg0, int32_t arg1, void* arg2); |
| 1929 | 1929 |
| 1930 // Software interrupt instructions are used by the simulator to call into the | 1930 // Software interrupt instructions are used by the simulator to call into the |
| 1931 // C-based V8 runtime. They are also used for debugging with simulator. | 1931 // C-based V8 runtime. They are also used for debugging with simulator. |
| 1932 void Simulator::SoftwareInterrupt(Instruction* instr) { | 1932 void Simulator::SoftwareInterrupt() { |
| 1933 // There are several instructions that could get us here, | 1933 // There are several instructions that could get us here, |
| 1934 // the break_ instruction, or several variants of traps. All | 1934 // the break_ instruction, or several variants of traps. All |
| 1935 // Are "SPECIAL" class opcode, and are distinuished by function. | 1935 // Are "SPECIAL" class opcode, and are distinuished by function. |
| 1936 int32_t func = instr->FunctionFieldRaw(); | 1936 int32_t func = instr_.FunctionFieldRaw(); |
| 1937 uint32_t code = (func == BREAK) ? instr->Bits(25, 6) : -1; | 1937 uint32_t code = (func == BREAK) ? instr_.Bits(25, 6) : -1; |
| 1938 | 1938 |
| 1939 // We first check if we met a call_rt_redirected. | 1939 // We first check if we met a call_rt_redirected. |
| 1940 if (instr->InstructionBits() == rtCallRedirInstr) { | 1940 if (instr_.InstructionBits() == rtCallRedirInstr) { |
| 1941 Redirection* redirection = Redirection::FromSwiInstruction(instr); | 1941 Redirection* redirection = |
| 1942 Redirection::FromSwiInstruction(instr_.instr()); |
| 1942 int32_t arg0 = get_register(a0); | 1943 int32_t arg0 = get_register(a0); |
| 1943 int32_t arg1 = get_register(a1); | 1944 int32_t arg1 = get_register(a1); |
| 1944 int32_t arg2 = get_register(a2); | 1945 int32_t arg2 = get_register(a2); |
| 1945 int32_t arg3 = get_register(a3); | 1946 int32_t arg3 = get_register(a3); |
| 1946 | 1947 |
| 1947 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); | 1948 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); |
| 1948 // Args 4 and 5 are on the stack after the reserved space for args 0..3. | 1949 // Args 4 and 5 are on the stack after the reserved space for args 0..3. |
| 1949 int32_t arg4 = stack_pointer[4]; | 1950 int32_t arg4 = stack_pointer[4]; |
| 1950 int32_t arg5 = stack_pointer[5]; | 1951 int32_t arg5 = stack_pointer[5]; |
| 1951 | 1952 |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2166 PrintF("Returned %08x : %08x\n", get_register(v1), get_register(v0)); | 2167 PrintF("Returned %08x : %08x\n", get_register(v1), get_register(v0)); |
| 2167 } | 2168 } |
| 2168 set_register(ra, saved_ra); | 2169 set_register(ra, saved_ra); |
| 2169 set_pc(get_register(ra)); | 2170 set_pc(get_register(ra)); |
| 2170 | 2171 |
| 2171 } else if (func == BREAK && code <= kMaxStopCode) { | 2172 } else if (func == BREAK && code <= kMaxStopCode) { |
| 2172 if (IsWatchpoint(code)) { | 2173 if (IsWatchpoint(code)) { |
| 2173 PrintWatchpoint(code); | 2174 PrintWatchpoint(code); |
| 2174 } else { | 2175 } else { |
| 2175 IncreaseStopCounter(code); | 2176 IncreaseStopCounter(code); |
| 2176 HandleStop(code, instr); | 2177 HandleStop(code, instr_.instr()); |
| 2177 } | 2178 } |
| 2178 } else { | 2179 } else { |
| 2179 // All remaining break_ codes, and all traps are handled here. | 2180 // All remaining break_ codes, and all traps are handled here. |
| 2180 MipsDebugger dbg(this); | 2181 MipsDebugger dbg(this); |
| 2181 dbg.Debug(); | 2182 dbg.Debug(); |
| 2182 } | 2183 } |
| 2183 } | 2184 } |
| 2184 | 2185 |
| 2185 | 2186 |
| 2186 // Stop helper functions. | 2187 // Stop helper functions. |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2409 return result; | 2410 return result; |
| 2410 } | 2411 } |
| 2411 | 2412 |
| 2412 // Handle execution based on instruction types. | 2413 // Handle execution based on instruction types. |
| 2413 | 2414 |
| 2414 void Simulator::DecodeTypeRegisterDRsType() { | 2415 void Simulator::DecodeTypeRegisterDRsType() { |
| 2415 double ft, fs, fd; | 2416 double ft, fs, fd; |
| 2416 uint32_t cc, fcsr_cc; | 2417 uint32_t cc, fcsr_cc; |
| 2417 int64_t i64; | 2418 int64_t i64; |
| 2418 fs = get_fpu_register_double(fs_reg()); | 2419 fs = get_fpu_register_double(fs_reg()); |
| 2419 ft = (get_instr()->FunctionFieldRaw() != MOVF) | 2420 ft = (instr_.FunctionFieldRaw() != MOVF) |
| 2420 ? get_fpu_register_double(ft_reg()) | 2421 ? get_fpu_register_double(ft_reg()) |
| 2421 : 0.0; | 2422 : 0.0; |
| 2422 fd = get_fpu_register_double(fd_reg()); | 2423 fd = get_fpu_register_double(fd_reg()); |
| 2423 int64_t ft_int = bit_cast<int64_t>(ft); | 2424 int64_t ft_int = bit_cast<int64_t>(ft); |
| 2424 int64_t fd_int = bit_cast<int64_t>(fd); | 2425 int64_t fd_int = bit_cast<int64_t>(fd); |
| 2425 cc = get_instr()->FCccValue(); | 2426 cc = instr_.FCccValue(); |
| 2426 fcsr_cc = get_fcsr_condition_bit(cc); | 2427 fcsr_cc = get_fcsr_condition_bit(cc); |
| 2427 switch (get_instr()->FunctionFieldRaw()) { | 2428 switch (instr_.FunctionFieldRaw()) { |
| 2428 case RINT: { | 2429 case RINT: { |
| 2429 DCHECK(IsMipsArchVariant(kMips32r6)); | 2430 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2430 double result, temp, temp_result; | 2431 double result, temp, temp_result; |
| 2431 double upper = std::ceil(fs); | 2432 double upper = std::ceil(fs); |
| 2432 double lower = std::floor(fs); | 2433 double lower = std::floor(fs); |
| 2433 switch (get_fcsr_rounding_mode()) { | 2434 switch (get_fcsr_rounding_mode()) { |
| 2434 case kRoundToNearest: | 2435 case kRoundToNearest: |
| 2435 if (upper - fs < fs - lower) { | 2436 if (upper - fs < fs - lower) { |
| 2436 result = upper; | 2437 result = upper; |
| 2437 } else if (upper - fs > fs - lower) { | 2438 } else if (upper - fs > fs - lower) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2476 break; | 2477 break; |
| 2477 case MOVZ_C: { | 2478 case MOVZ_C: { |
| 2478 DCHECK(IsMipsArchVariant(kMips32r2)); | 2479 DCHECK(IsMipsArchVariant(kMips32r2)); |
| 2479 if (rt() == 0) { | 2480 if (rt() == 0) { |
| 2480 set_fpu_register_double(fd_reg(), fs); | 2481 set_fpu_register_double(fd_reg(), fs); |
| 2481 } | 2482 } |
| 2482 break; | 2483 break; |
| 2483 } | 2484 } |
| 2484 case MOVN_C: { | 2485 case MOVN_C: { |
| 2485 DCHECK(IsMipsArchVariant(kMips32r2)); | 2486 DCHECK(IsMipsArchVariant(kMips32r2)); |
| 2486 int32_t rt_reg = get_instr()->RtValue(); | 2487 int32_t rt_reg = instr_.RtValue(); |
| 2487 int32_t rt = get_register(rt_reg); | 2488 int32_t rt = get_register(rt_reg); |
| 2488 if (rt != 0) { | 2489 if (rt != 0) { |
| 2489 set_fpu_register_double(fd_reg(), fs); | 2490 set_fpu_register_double(fd_reg(), fs); |
| 2490 } | 2491 } |
| 2491 break; | 2492 break; |
| 2492 } | 2493 } |
| 2493 case MOVF: { | 2494 case MOVF: { |
| 2494 // Same function field for MOVT.D and MOVF.D | 2495 // Same function field for MOVT.D and MOVF.D |
| 2495 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; | 2496 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; |
| 2496 ft_cc = get_fcsr_condition_bit(ft_cc); | 2497 ft_cc = get_fcsr_condition_bit(ft_cc); |
| 2497 if (get_instr()->Bit(16)) { // Read Tf bit. | 2498 if (instr_.Bit(16)) { // Read Tf bit. |
| 2498 // MOVT.D | 2499 // MOVT.D |
| 2499 if (test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); | 2500 if (test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); |
| 2500 } else { | 2501 } else { |
| 2501 // MOVF.D | 2502 // MOVF.D |
| 2502 if (!test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); | 2503 if (!test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); |
| 2503 } | 2504 } |
| 2504 break; | 2505 break; |
| 2505 } | 2506 } |
| 2506 case MIN: | 2507 case MIN: |
| 2507 DCHECK(IsMipsArchVariant(kMips32r6)); | 2508 DCHECK(IsMipsArchVariant(kMips32r6)); |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2802 default: | 2803 default: |
| 2803 UNREACHABLE(); | 2804 UNREACHABLE(); |
| 2804 } | 2805 } |
| 2805 } | 2806 } |
| 2806 | 2807 |
| 2807 | 2808 |
| 2808 void Simulator::DecodeTypeRegisterWRsType() { | 2809 void Simulator::DecodeTypeRegisterWRsType() { |
| 2809 float fs = get_fpu_register_float(fs_reg()); | 2810 float fs = get_fpu_register_float(fs_reg()); |
| 2810 float ft = get_fpu_register_float(ft_reg()); | 2811 float ft = get_fpu_register_float(ft_reg()); |
| 2811 int32_t alu_out = 0x12345678; | 2812 int32_t alu_out = 0x12345678; |
| 2812 switch (get_instr()->FunctionFieldRaw()) { | 2813 switch (instr_.FunctionFieldRaw()) { |
| 2813 case CVT_S_W: // Convert word to float (single). | 2814 case CVT_S_W: // Convert word to float (single). |
| 2814 alu_out = get_fpu_register_signed_word(fs_reg()); | 2815 alu_out = get_fpu_register_signed_word(fs_reg()); |
| 2815 set_fpu_register_float(fd_reg(), static_cast<float>(alu_out)); | 2816 set_fpu_register_float(fd_reg(), static_cast<float>(alu_out)); |
| 2816 break; | 2817 break; |
| 2817 case CVT_D_W: // Convert word to double. | 2818 case CVT_D_W: // Convert word to double. |
| 2818 alu_out = get_fpu_register_signed_word(fs_reg()); | 2819 alu_out = get_fpu_register_signed_word(fs_reg()); |
| 2819 set_fpu_register_double(fd_reg(), static_cast<double>(alu_out)); | 2820 set_fpu_register_double(fd_reg(), static_cast<double>(alu_out)); |
| 2820 break; | 2821 break; |
| 2821 case CMP_AF: | 2822 case CMP_AF: |
| 2822 set_fpu_register_word(fd_reg(), 0); | 2823 set_fpu_register_word(fd_reg(), 0); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2898 | 2899 |
| 2899 | 2900 |
| 2900 void Simulator::DecodeTypeRegisterSRsType() { | 2901 void Simulator::DecodeTypeRegisterSRsType() { |
| 2901 float fs, ft, fd; | 2902 float fs, ft, fd; |
| 2902 fs = get_fpu_register_float(fs_reg()); | 2903 fs = get_fpu_register_float(fs_reg()); |
| 2903 ft = get_fpu_register_float(ft_reg()); | 2904 ft = get_fpu_register_float(ft_reg()); |
| 2904 fd = get_fpu_register_float(fd_reg()); | 2905 fd = get_fpu_register_float(fd_reg()); |
| 2905 int32_t ft_int = bit_cast<int32_t>(ft); | 2906 int32_t ft_int = bit_cast<int32_t>(ft); |
| 2906 int32_t fd_int = bit_cast<int32_t>(fd); | 2907 int32_t fd_int = bit_cast<int32_t>(fd); |
| 2907 uint32_t cc, fcsr_cc; | 2908 uint32_t cc, fcsr_cc; |
| 2908 cc = get_instr()->FCccValue(); | 2909 cc = instr_.FCccValue(); |
| 2909 fcsr_cc = get_fcsr_condition_bit(cc); | 2910 fcsr_cc = get_fcsr_condition_bit(cc); |
| 2910 switch (get_instr()->FunctionFieldRaw()) { | 2911 switch (instr_.FunctionFieldRaw()) { |
| 2911 case RINT: { | 2912 case RINT: { |
| 2912 DCHECK(IsMipsArchVariant(kMips32r6)); | 2913 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2913 float result, temp_result; | 2914 float result, temp_result; |
| 2914 double temp; | 2915 double temp; |
| 2915 float upper = std::ceil(fs); | 2916 float upper = std::ceil(fs); |
| 2916 float lower = std::floor(fs); | 2917 float lower = std::floor(fs); |
| 2917 switch (get_fcsr_rounding_mode()) { | 2918 switch (get_fcsr_rounding_mode()) { |
| 2918 case kRoundToNearest: | 2919 case kRoundToNearest: |
| 2919 if (upper - fs < fs - lower) { | 2920 if (upper - fs < fs - lower) { |
| 2920 result = upper; | 2921 result = upper; |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3127 if (rt() != 0) { | 3128 if (rt() != 0) { |
| 3128 set_fpu_register_float(fd_reg(), fs); | 3129 set_fpu_register_float(fd_reg(), fs); |
| 3129 } | 3130 } |
| 3130 break; | 3131 break; |
| 3131 } | 3132 } |
| 3132 case MOVF: { | 3133 case MOVF: { |
| 3133 // Same function field for MOVT.D and MOVF.D | 3134 // Same function field for MOVT.D and MOVF.D |
| 3134 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; | 3135 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; |
| 3135 ft_cc = get_fcsr_condition_bit(ft_cc); | 3136 ft_cc = get_fcsr_condition_bit(ft_cc); |
| 3136 | 3137 |
| 3137 if (get_instr()->Bit(16)) { // Read Tf bit. | 3138 if (instr_.Bit(16)) { // Read Tf bit. |
| 3138 // MOVT.D | 3139 // MOVT.D |
| 3139 if (test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs); | 3140 if (test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs); |
| 3140 } else { | 3141 } else { |
| 3141 // MOVF.D | 3142 // MOVF.D |
| 3142 if (!test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs); | 3143 if (!test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs); |
| 3143 } | 3144 } |
| 3144 break; | 3145 break; |
| 3145 } | 3146 } |
| 3146 case TRUNC_W_S: { // Truncate single to word (round towards 0). | 3147 case TRUNC_W_S: { // Truncate single to word (round towards 0). |
| 3147 float rounded = trunc(fs); | 3148 float rounded = trunc(fs); |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3289 // CVT_W_S CVT_L_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S | 3290 // CVT_W_S CVT_L_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S |
| 3290 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented. | 3291 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented. |
| 3291 UNREACHABLE(); | 3292 UNREACHABLE(); |
| 3292 } | 3293 } |
| 3293 } | 3294 } |
| 3294 | 3295 |
| 3295 | 3296 |
| 3296 void Simulator::DecodeTypeRegisterLRsType() { | 3297 void Simulator::DecodeTypeRegisterLRsType() { |
| 3297 double fs = get_fpu_register_double(fs_reg()); | 3298 double fs = get_fpu_register_double(fs_reg()); |
| 3298 double ft = get_fpu_register_double(ft_reg()); | 3299 double ft = get_fpu_register_double(ft_reg()); |
| 3299 switch (get_instr()->FunctionFieldRaw()) { | 3300 switch (instr_.FunctionFieldRaw()) { |
| 3300 case CVT_D_L: // Mips32r2 instruction. | 3301 case CVT_D_L: // Mips32r2 instruction. |
| 3301 // Watch the signs here, we want 2 32-bit vals | 3302 // Watch the signs here, we want 2 32-bit vals |
| 3302 // to make a sign-64. | 3303 // to make a sign-64. |
| 3303 int64_t i64; | 3304 int64_t i64; |
| 3304 if (IsFp64Mode()) { | 3305 if (IsFp64Mode()) { |
| 3305 i64 = get_fpu_register(fs_reg()); | 3306 i64 = get_fpu_register(fs_reg()); |
| 3306 } else { | 3307 } else { |
| 3307 i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg())); | 3308 i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg())); |
| 3308 i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg() + 1)) << 32; | 3309 i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg() + 1)) << 32; |
| 3309 } | 3310 } |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3391 set_fpu_register(fd_reg(), 0); | 3392 set_fpu_register(fd_reg(), 0); |
| 3392 } | 3393 } |
| 3393 break; | 3394 break; |
| 3394 default: | 3395 default: |
| 3395 UNREACHABLE(); | 3396 UNREACHABLE(); |
| 3396 } | 3397 } |
| 3397 } | 3398 } |
| 3398 | 3399 |
| 3399 | 3400 |
| 3400 void Simulator::DecodeTypeRegisterCOP1() { | 3401 void Simulator::DecodeTypeRegisterCOP1() { |
| 3401 switch (get_instr()->RsFieldRaw()) { | 3402 switch (instr_.RsFieldRaw()) { |
| 3402 case CFC1: | 3403 case CFC1: |
| 3403 // At the moment only FCSR is supported. | 3404 // At the moment only FCSR is supported. |
| 3404 DCHECK(fs_reg() == kFCSRRegister); | 3405 DCHECK(fs_reg() == kFCSRRegister); |
| 3405 set_register(rt_reg(), FCSR_); | 3406 set_register(rt_reg(), FCSR_); |
| 3406 break; | 3407 break; |
| 3407 case MFC1: | 3408 case MFC1: |
| 3408 set_register(rt_reg(), get_fpu_register_word(fs_reg())); | 3409 set_register(rt_reg(), get_fpu_register_word(fs_reg())); |
| 3409 break; | 3410 break; |
| 3410 case MFHC1: | 3411 case MFHC1: |
| 3411 if (IsFp64Mode()) { | 3412 if (IsFp64Mode()) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3454 case PS: | 3455 case PS: |
| 3455 // Not implemented. | 3456 // Not implemented. |
| 3456 UNREACHABLE(); | 3457 UNREACHABLE(); |
| 3457 default: | 3458 default: |
| 3458 UNREACHABLE(); | 3459 UNREACHABLE(); |
| 3459 } | 3460 } |
| 3460 } | 3461 } |
| 3461 | 3462 |
| 3462 | 3463 |
| 3463 void Simulator::DecodeTypeRegisterCOP1X() { | 3464 void Simulator::DecodeTypeRegisterCOP1X() { |
| 3464 switch (get_instr()->FunctionFieldRaw()) { | 3465 switch (instr_.FunctionFieldRaw()) { |
| 3465 case MADD_S: { | 3466 case MADD_S: { |
| 3466 DCHECK(IsMipsArchVariant(kMips32r2)); | 3467 DCHECK(IsMipsArchVariant(kMips32r2)); |
| 3467 float fr, ft, fs; | 3468 float fr, ft, fs; |
| 3468 fr = get_fpu_register_float(fr_reg()); | 3469 fr = get_fpu_register_float(fr_reg()); |
| 3469 fs = get_fpu_register_float(fs_reg()); | 3470 fs = get_fpu_register_float(fs_reg()); |
| 3470 ft = get_fpu_register_float(ft_reg()); | 3471 ft = get_fpu_register_float(ft_reg()); |
| 3471 set_fpu_register_float(fd_reg(), fs * ft + fr); | 3472 set_fpu_register_float(fd_reg(), fs * ft + fr); |
| 3472 break; | 3473 break; |
| 3473 } | 3474 } |
| 3474 case MSUB_S: { | 3475 case MSUB_S: { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 3503 } | 3504 } |
| 3504 } | 3505 } |
| 3505 | 3506 |
| 3506 | 3507 |
| 3507 void Simulator::DecodeTypeRegisterSPECIAL() { | 3508 void Simulator::DecodeTypeRegisterSPECIAL() { |
| 3508 int64_t alu_out = 0x12345678; | 3509 int64_t alu_out = 0x12345678; |
| 3509 int64_t i64hilo = 0; | 3510 int64_t i64hilo = 0; |
| 3510 uint64_t u64hilo = 0; | 3511 uint64_t u64hilo = 0; |
| 3511 bool do_interrupt = false; | 3512 bool do_interrupt = false; |
| 3512 | 3513 |
| 3513 switch (get_instr()->FunctionFieldRaw()) { | 3514 switch (instr_.FunctionFieldRaw()) { |
| 3514 case SELEQZ_S: | 3515 case SELEQZ_S: |
| 3515 DCHECK(IsMipsArchVariant(kMips32r6)); | 3516 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 3516 set_register(rd_reg(), rt() == 0 ? rs() : 0); | 3517 set_register(rd_reg(), rt() == 0 ? rs() : 0); |
| 3517 break; | 3518 break; |
| 3518 case SELNEZ_S: | 3519 case SELNEZ_S: |
| 3519 DCHECK(IsMipsArchVariant(kMips32r6)); | 3520 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 3520 set_register(rd_reg(), rt() != 0 ? rs() : 0); | 3521 set_register(rd_reg(), rt() != 0 ? rs() : 0); |
| 3521 break; | 3522 break; |
| 3522 case JR: { | 3523 case JR: { |
| 3523 int32_t next_pc = rs(); | 3524 int32_t next_pc = rs(); |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3643 set_register(rd_reg(), static_cast<int32_t>(u64hilo >> 32)); | 3644 set_register(rd_reg(), static_cast<int32_t>(u64hilo >> 32)); |
| 3644 break; | 3645 break; |
| 3645 default: | 3646 default: |
| 3646 UNIMPLEMENTED_MIPS(); | 3647 UNIMPLEMENTED_MIPS(); |
| 3647 break; | 3648 break; |
| 3648 } | 3649 } |
| 3649 } | 3650 } |
| 3650 break; | 3651 break; |
| 3651 case DIV: | 3652 case DIV: |
| 3652 if (IsMipsArchVariant(kMips32r6)) { | 3653 if (IsMipsArchVariant(kMips32r6)) { |
| 3653 switch (get_instr()->SaValue()) { | 3654 switch (sa()) { |
| 3654 case DIV_OP: | 3655 case DIV_OP: |
| 3655 if (rs() == INT_MIN && rt() == -1) { | 3656 if (rs() == INT_MIN && rt() == -1) { |
| 3656 set_register(rd_reg(), INT_MIN); | 3657 set_register(rd_reg(), INT_MIN); |
| 3657 } else if (rt() != 0) { | 3658 } else if (rt() != 0) { |
| 3658 set_register(rd_reg(), rs() / rt()); | 3659 set_register(rd_reg(), rs() / rt()); |
| 3659 } | 3660 } |
| 3660 break; | 3661 break; |
| 3661 case MOD_OP: | 3662 case MOD_OP: |
| 3662 if (rs() == INT_MIN && rt() == -1) { | 3663 if (rs() == INT_MIN && rt() == -1) { |
| 3663 set_register(rd_reg(), 0); | 3664 set_register(rd_reg(), 0); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3678 set_register(LO, INT_MIN); | 3679 set_register(LO, INT_MIN); |
| 3679 set_register(HI, 0); | 3680 set_register(HI, 0); |
| 3680 } else if (rt() != 0) { | 3681 } else if (rt() != 0) { |
| 3681 set_register(LO, rs() / rt()); | 3682 set_register(LO, rs() / rt()); |
| 3682 set_register(HI, rs() % rt()); | 3683 set_register(HI, rs() % rt()); |
| 3683 } | 3684 } |
| 3684 } | 3685 } |
| 3685 break; | 3686 break; |
| 3686 case DIVU: | 3687 case DIVU: |
| 3687 if (IsMipsArchVariant(kMips32r6)) { | 3688 if (IsMipsArchVariant(kMips32r6)) { |
| 3688 switch (get_instr()->SaValue()) { | 3689 switch (sa()) { |
| 3689 case DIV_OP: | 3690 case DIV_OP: |
| 3690 if (rt_u() != 0) { | 3691 if (rt_u() != 0) { |
| 3691 set_register(rd_reg(), rs_u() / rt_u()); | 3692 set_register(rd_reg(), rs_u() / rt_u()); |
| 3692 } | 3693 } |
| 3693 break; | 3694 break; |
| 3694 case MOD_OP: | 3695 case MOD_OP: |
| 3695 if (rt_u() != 0) { | 3696 if (rt_u() != 0) { |
| 3696 set_register(rd_reg(), rs_u() % rt_u()); | 3697 set_register(rd_reg(), rs_u() % rt_u()); |
| 3697 } | 3698 } |
| 3698 break; | 3699 break; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3785 // TODO(palfia): Ignore sync instruction for now. | 3786 // TODO(palfia): Ignore sync instruction for now. |
| 3786 break; | 3787 break; |
| 3787 // Conditional moves. | 3788 // Conditional moves. |
| 3788 case MOVN: | 3789 case MOVN: |
| 3789 if (rt()) { | 3790 if (rt()) { |
| 3790 set_register(rd_reg(), rs()); | 3791 set_register(rd_reg(), rs()); |
| 3791 TraceRegWr(rs()); | 3792 TraceRegWr(rs()); |
| 3792 } | 3793 } |
| 3793 break; | 3794 break; |
| 3794 case MOVCI: { | 3795 case MOVCI: { |
| 3795 uint32_t cc = get_instr()->FBccValue(); | 3796 uint32_t cc = instr_.FBccValue(); |
| 3796 uint32_t fcsr_cc = get_fcsr_condition_bit(cc); | 3797 uint32_t fcsr_cc = get_fcsr_condition_bit(cc); |
| 3797 if (get_instr()->Bit(16)) { // Read Tf bit. | 3798 if (instr_.Bit(16)) { // Read Tf bit. |
| 3798 if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs()); | 3799 if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs()); |
| 3799 } else { | 3800 } else { |
| 3800 if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs()); | 3801 if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs()); |
| 3801 } | 3802 } |
| 3802 break; | 3803 break; |
| 3803 } | 3804 } |
| 3804 case MOVZ: | 3805 case MOVZ: |
| 3805 if (!rt()) { | 3806 if (!rt()) { |
| 3806 set_register(rd_reg(), rs()); | 3807 set_register(rd_reg(), rs()); |
| 3807 TraceRegWr(rs()); | 3808 TraceRegWr(rs()); |
| 3808 } | 3809 } |
| 3809 break; | 3810 break; |
| 3810 default: | 3811 default: |
| 3811 UNREACHABLE(); | 3812 UNREACHABLE(); |
| 3812 } | 3813 } |
| 3813 if (do_interrupt) { | 3814 if (do_interrupt) { |
| 3814 SoftwareInterrupt(get_instr()); | 3815 SoftwareInterrupt(); |
| 3815 } | 3816 } |
| 3816 } | 3817 } |
| 3817 | 3818 |
| 3818 | 3819 |
| 3819 void Simulator::DecodeTypeRegisterSPECIAL2() { | 3820 void Simulator::DecodeTypeRegisterSPECIAL2() { |
| 3820 int32_t alu_out; | 3821 int32_t alu_out; |
| 3821 switch (get_instr()->FunctionFieldRaw()) { | 3822 switch (instr_.FunctionFieldRaw()) { |
| 3822 case MUL: | 3823 case MUL: |
| 3823 // Only the lower 32 bits are kept. | 3824 // Only the lower 32 bits are kept. |
| 3824 alu_out = rs_u() * rt_u(); | 3825 alu_out = rs_u() * rt_u(); |
| 3825 // HI and LO are UNPREDICTABLE after the operation. | 3826 // HI and LO are UNPREDICTABLE after the operation. |
| 3826 set_register(LO, Unpredictable); | 3827 set_register(LO, Unpredictable); |
| 3827 set_register(HI, Unpredictable); | 3828 set_register(HI, Unpredictable); |
| 3828 break; | 3829 break; |
| 3829 case CLZ: | 3830 case CLZ: |
| 3830 // MIPS32 spec: If no bits were set in GPR rs, the result written to | 3831 // MIPS32 spec: If no bits were set in GPR rs, the result written to |
| 3831 // GPR rd is 32. | 3832 // GPR rd is 32. |
| 3832 alu_out = base::bits::CountLeadingZeros32(rs_u()); | 3833 alu_out = base::bits::CountLeadingZeros32(rs_u()); |
| 3833 break; | 3834 break; |
| 3834 default: | 3835 default: |
| 3835 alu_out = 0x12345678; | 3836 alu_out = 0x12345678; |
| 3836 UNREACHABLE(); | 3837 UNREACHABLE(); |
| 3837 } | 3838 } |
| 3838 SetResult(rd_reg(), alu_out); | 3839 SetResult(rd_reg(), alu_out); |
| 3839 } | 3840 } |
| 3840 | 3841 |
| 3841 | 3842 |
| 3842 void Simulator::DecodeTypeRegisterSPECIAL3() { | 3843 void Simulator::DecodeTypeRegisterSPECIAL3() { |
| 3843 int32_t alu_out; | 3844 int32_t alu_out; |
| 3844 switch (get_instr()->FunctionFieldRaw()) { | 3845 switch (instr_.FunctionFieldRaw()) { |
| 3845 case INS: { // Mips32r2 instruction. | 3846 case INS: { // Mips32r2 instruction. |
| 3846 // Interpret rd field as 5-bit msb of insert. | 3847 // Interpret rd field as 5-bit msb of insert. |
| 3847 uint16_t msb = rd_reg(); | 3848 uint16_t msb = rd_reg(); |
| 3848 // Interpret sa field as 5-bit lsb of insert. | 3849 // Interpret sa field as 5-bit lsb of insert. |
| 3849 uint16_t lsb = sa(); | 3850 uint16_t lsb = sa(); |
| 3850 uint16_t size = msb - lsb + 1; | 3851 uint16_t size = msb - lsb + 1; |
| 3851 uint32_t mask = (1 << size) - 1; | 3852 uint32_t mask = (1 << size) - 1; |
| 3852 alu_out = (rt_u() & ~(mask << lsb)) | ((rs_u() & mask) << lsb); | 3853 alu_out = (rt_u() & ~(mask << lsb)) | ((rs_u() & mask) << lsb); |
| 3853 // Ins instr leaves result in Rt, rather than Rd. | 3854 // Ins instr leaves result in Rt, rather than Rd. |
| 3854 SetResult(rt_reg(), alu_out); | 3855 SetResult(rt_reg(), alu_out); |
| 3855 break; | 3856 break; |
| 3856 } | 3857 } |
| 3857 case EXT: { // Mips32r2 instruction. | 3858 case EXT: { // Mips32r2 instruction. |
| 3858 // Interpret rd field as 5-bit msb of extract. | 3859 // Interpret rd field as 5-bit msb of extract. |
| 3859 uint16_t msb = rd_reg(); | 3860 uint16_t msb = rd_reg(); |
| 3860 // Interpret sa field as 5-bit lsb of extract. | 3861 // Interpret sa field as 5-bit lsb of extract. |
| 3861 uint16_t lsb = sa(); | 3862 uint16_t lsb = sa(); |
| 3862 uint16_t size = msb + 1; | 3863 uint16_t size = msb + 1; |
| 3863 uint32_t mask = (1 << size) - 1; | 3864 uint32_t mask = (1 << size) - 1; |
| 3864 alu_out = (rs_u() & (mask << lsb)) >> lsb; | 3865 alu_out = (rs_u() & (mask << lsb)) >> lsb; |
| 3865 SetResult(rt_reg(), alu_out); | 3866 SetResult(rt_reg(), alu_out); |
| 3866 break; | 3867 break; |
| 3867 } | 3868 } |
| 3868 case BSHFL: { | 3869 case BSHFL: { |
| 3869 int sa = get_instr()->SaFieldRaw() >> kSaShift; | 3870 int sa = instr_.SaFieldRaw() >> kSaShift; |
| 3870 switch (sa) { | 3871 switch (sa) { |
| 3871 case BITSWAP: { | 3872 case BITSWAP: { |
| 3872 uint32_t input = static_cast<uint32_t>(rt()); | 3873 uint32_t input = static_cast<uint32_t>(rt()); |
| 3873 uint32_t output = 0; | 3874 uint32_t output = 0; |
| 3874 uint8_t i_byte, o_byte; | 3875 uint8_t i_byte, o_byte; |
| 3875 | 3876 |
| 3876 // Reverse the bit in byte for each individual byte | 3877 // Reverse the bit in byte for each individual byte |
| 3877 for (int i = 0; i < 4; i++) { | 3878 for (int i = 0; i < 4; i++) { |
| 3878 output = output >> 8; | 3879 output = output >> 8; |
| 3879 i_byte = input & 0xff; | 3880 i_byte = input & 0xff; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3931 tmp = tmp << 8; | 3932 tmp = tmp << 8; |
| 3932 } | 3933 } |
| 3933 output = output | tmp; | 3934 output = output | tmp; |
| 3934 mask = mask >> 8; | 3935 mask = mask >> 8; |
| 3935 } | 3936 } |
| 3936 | 3937 |
| 3937 alu_out = static_cast<int32_t>(output); | 3938 alu_out = static_cast<int32_t>(output); |
| 3938 break; | 3939 break; |
| 3939 } | 3940 } |
| 3940 default: { | 3941 default: { |
| 3941 const uint8_t bp = get_instr()->Bp2Value(); | 3942 const uint8_t bp = instr_.Bp2Value(); |
| 3942 sa >>= kBp2Bits; | 3943 sa >>= kBp2Bits; |
| 3943 switch (sa) { | 3944 switch (sa) { |
| 3944 case ALIGN: { | 3945 case ALIGN: { |
| 3945 if (bp == 0) { | 3946 if (bp == 0) { |
| 3946 alu_out = static_cast<int32_t>(rt()); | 3947 alu_out = static_cast<int32_t>(rt()); |
| 3947 } else { | 3948 } else { |
| 3948 uint32_t rt_hi = rt() << (8 * bp); | 3949 uint32_t rt_hi = rt() << (8 * bp); |
| 3949 uint32_t rs_lo = rs() >> (8 * (4 - bp)); | 3950 uint32_t rs_lo = rs() >> (8 * (4 - bp)); |
| 3950 alu_out = static_cast<int32_t>(rt_hi | rs_lo); | 3951 alu_out = static_cast<int32_t>(rt_hi | rs_lo); |
| 3951 } | 3952 } |
| 3952 break; | 3953 break; |
| 3953 } | 3954 } |
| 3954 default: | 3955 default: |
| 3955 alu_out = 0x12345678; | 3956 alu_out = 0x12345678; |
| 3956 UNREACHABLE(); | 3957 UNREACHABLE(); |
| 3957 break; | 3958 break; |
| 3958 } | 3959 } |
| 3959 } | 3960 } |
| 3960 } | 3961 } |
| 3961 SetResult(rd_reg(), alu_out); | 3962 SetResult(rd_reg(), alu_out); |
| 3962 break; | 3963 break; |
| 3963 } | 3964 } |
| 3964 default: | 3965 default: |
| 3965 UNREACHABLE(); | 3966 UNREACHABLE(); |
| 3966 } | 3967 } |
| 3967 } | 3968 } |
| 3968 | 3969 |
| 3969 | 3970 void Simulator::DecodeTypeRegister() { |
| 3970 void Simulator::DecodeTypeRegister(Instruction* instr) { | |
| 3971 const Opcode op = instr->OpcodeFieldRaw(); | |
| 3972 | |
| 3973 // Set up the variables if needed before executing the instruction. | |
| 3974 // ConfigureTypeRegister(instr); | |
| 3975 set_instr(instr); | |
| 3976 | |
| 3977 // ---------- Execution. | 3971 // ---------- Execution. |
| 3978 switch (op) { | 3972 switch (instr_.OpcodeFieldRaw()) { |
| 3979 case COP1: | 3973 case COP1: |
| 3980 DecodeTypeRegisterCOP1(); | 3974 DecodeTypeRegisterCOP1(); |
| 3981 break; | 3975 break; |
| 3982 case COP1X: | 3976 case COP1X: |
| 3983 DecodeTypeRegisterCOP1X(); | 3977 DecodeTypeRegisterCOP1X(); |
| 3984 break; | 3978 break; |
| 3985 case SPECIAL: | 3979 case SPECIAL: |
| 3986 DecodeTypeRegisterSPECIAL(); | 3980 DecodeTypeRegisterSPECIAL(); |
| 3987 break; | 3981 break; |
| 3988 case SPECIAL2: | 3982 case SPECIAL2: |
| 3989 DecodeTypeRegisterSPECIAL2(); | 3983 DecodeTypeRegisterSPECIAL2(); |
| 3990 break; | 3984 break; |
| 3991 case SPECIAL3: | 3985 case SPECIAL3: |
| 3992 DecodeTypeRegisterSPECIAL3(); | 3986 DecodeTypeRegisterSPECIAL3(); |
| 3993 break; | 3987 break; |
| 3994 default: | 3988 default: |
| 3995 UNREACHABLE(); | 3989 UNREACHABLE(); |
| 3996 } | 3990 } |
| 3997 } | 3991 } |
| 3998 | 3992 |
| 3999 | 3993 |
| 4000 // Type 2: instructions using a 16, 21 or 26 bits immediate. (e.g. beq, beqc). | 3994 // Type 2: instructions using a 16, 21 or 26 bits immediate. (e.g. beq, beqc). |
| 4001 void Simulator::DecodeTypeImmediate(Instruction* instr) { | 3995 void Simulator::DecodeTypeImmediate() { |
| 4002 // Instruction fields. | 3996 // Instruction fields. |
| 4003 Opcode op = instr->OpcodeFieldRaw(); | 3997 Opcode op = instr_.OpcodeFieldRaw(); |
| 4004 int32_t rs_reg = instr->RsValue(); | 3998 int32_t rs_reg = instr_.RsValue(); |
| 4005 int32_t rs = get_register(instr->RsValue()); | 3999 int32_t rs = get_register(instr_.RsValue()); |
| 4006 uint32_t rs_u = static_cast<uint32_t>(rs); | 4000 uint32_t rs_u = static_cast<uint32_t>(rs); |
| 4007 int32_t rt_reg = instr->RtValue(); // Destination register. | 4001 int32_t rt_reg = instr_.RtValue(); // Destination register. |
| 4008 int32_t rt = get_register(rt_reg); | 4002 int32_t rt = get_register(rt_reg); |
| 4009 int16_t imm16 = instr->Imm16Value(); | 4003 int16_t imm16 = instr_.Imm16Value(); |
| 4010 | 4004 |
| 4011 int32_t ft_reg = instr->FtValue(); // Destination register. | 4005 int32_t ft_reg = instr_.FtValue(); // Destination register. |
| 4012 | 4006 |
| 4013 // Zero extended immediate. | 4007 // Zero extended immediate. |
| 4014 uint32_t oe_imm16 = 0xffff & imm16; | 4008 uint32_t oe_imm16 = 0xffff & imm16; |
| 4015 // Sign extended immediate. | 4009 // Sign extended immediate. |
| 4016 int32_t se_imm16 = imm16; | 4010 int32_t se_imm16 = imm16; |
| 4017 | 4011 |
| 4018 // Next pc. | 4012 // Next pc. |
| 4019 int32_t next_pc = bad_ra; | 4013 int32_t next_pc = bad_ra; |
| 4020 | 4014 |
| 4021 // Used for conditional branch instructions. | 4015 // Used for conditional branch instructions. |
| 4022 bool execute_branch_delay_instruction = false; | 4016 bool execute_branch_delay_instruction = false; |
| 4023 | 4017 |
| 4024 // Used for arithmetic instructions. | 4018 // Used for arithmetic instructions. |
| 4025 int32_t alu_out = 0; | 4019 int32_t alu_out = 0; |
| 4026 | 4020 |
| 4027 // Used for memory instructions. | 4021 // Used for memory instructions. |
| 4028 int32_t addr = 0x0; | 4022 int32_t addr = 0x0; |
| 4029 | 4023 |
| 4030 // Branch instructions common part. | 4024 // Branch instructions common part. |
| 4031 auto BranchAndLinkHelper = [this, instr, &next_pc, | 4025 auto BranchAndLinkHelper = |
| 4032 &execute_branch_delay_instruction]( | 4026 [this, &next_pc, &execute_branch_delay_instruction](bool do_branch) { |
| 4033 bool do_branch) { | 4027 execute_branch_delay_instruction = true; |
| 4034 execute_branch_delay_instruction = true; | 4028 int32_t current_pc = get_pc(); |
| 4035 int32_t current_pc = get_pc(); | 4029 if (do_branch) { |
| 4036 if (do_branch) { | 4030 int16_t imm16 = this->instr_.Imm16Value(); |
| 4037 int16_t imm16 = instr->Imm16Value(); | 4031 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; |
| 4038 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; | 4032 set_register(31, current_pc + 2 * Instruction::kInstrSize); |
| 4039 set_register(31, current_pc + 2 * Instruction::kInstrSize); | 4033 } else { |
| 4040 } else { | 4034 next_pc = current_pc + 2 * Instruction::kInstrSize; |
| 4041 next_pc = current_pc + 2 * Instruction::kInstrSize; | 4035 } |
| 4042 } | 4036 }; |
| 4043 }; | |
| 4044 | 4037 |
| 4045 auto BranchHelper = [this, instr, &next_pc, | 4038 auto BranchHelper = [this, &next_pc, |
| 4046 &execute_branch_delay_instruction](bool do_branch) { | 4039 &execute_branch_delay_instruction](bool do_branch) { |
| 4047 execute_branch_delay_instruction = true; | 4040 execute_branch_delay_instruction = true; |
| 4048 int32_t current_pc = get_pc(); | 4041 int32_t current_pc = get_pc(); |
| 4049 if (do_branch) { | 4042 if (do_branch) { |
| 4050 int16_t imm16 = instr->Imm16Value(); | 4043 int16_t imm16 = this->instr_.Imm16Value(); |
| 4051 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; | 4044 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; |
| 4052 } else { | 4045 } else { |
| 4053 next_pc = current_pc + 2 * Instruction::kInstrSize; | 4046 next_pc = current_pc + 2 * Instruction::kInstrSize; |
| 4054 } | 4047 } |
| 4055 }; | 4048 }; |
| 4056 | 4049 |
| 4057 auto BranchAndLinkCompactHelper = [this, instr, &next_pc](bool do_branch, | 4050 auto BranchAndLinkCompactHelper = [this, &next_pc](bool do_branch, int bits) { |
| 4058 int bits) { | |
| 4059 int32_t current_pc = get_pc(); | 4051 int32_t current_pc = get_pc(); |
| 4060 CheckForbiddenSlot(current_pc); | 4052 CheckForbiddenSlot(current_pc); |
| 4061 if (do_branch) { | 4053 if (do_branch) { |
| 4062 int32_t imm = instr->ImmValue(bits); | 4054 int32_t imm = this->instr_.ImmValue(bits); |
| 4063 imm <<= 32 - bits; | 4055 imm <<= 32 - bits; |
| 4064 imm >>= 32 - bits; | 4056 imm >>= 32 - bits; |
| 4065 next_pc = current_pc + (imm << 2) + Instruction::kInstrSize; | 4057 next_pc = current_pc + (imm << 2) + Instruction::kInstrSize; |
| 4066 set_register(31, current_pc + Instruction::kInstrSize); | 4058 set_register(31, current_pc + Instruction::kInstrSize); |
| 4067 } | 4059 } |
| 4068 }; | 4060 }; |
| 4069 | 4061 |
| 4070 auto BranchCompactHelper = [&next_pc, this, instr](bool do_branch, int bits) { | 4062 auto BranchCompactHelper = [this, &next_pc](bool do_branch, int bits) { |
| 4071 int32_t current_pc = get_pc(); | 4063 int32_t current_pc = get_pc(); |
| 4072 CheckForbiddenSlot(current_pc); | 4064 CheckForbiddenSlot(current_pc); |
| 4073 if (do_branch) { | 4065 if (do_branch) { |
| 4074 int32_t imm = instr->ImmValue(bits); | 4066 int32_t imm = this->instr_.ImmValue(bits); |
| 4075 imm <<= 32 - bits; | 4067 imm <<= 32 - bits; |
| 4076 imm >>= 32 - bits; | 4068 imm >>= 32 - bits; |
| 4077 next_pc = get_pc() + (imm << 2) + Instruction::kInstrSize; | 4069 next_pc = get_pc() + (imm << 2) + Instruction::kInstrSize; |
| 4078 } | 4070 } |
| 4079 }; | 4071 }; |
| 4080 | 4072 |
| 4081 | |
| 4082 switch (op) { | 4073 switch (op) { |
| 4083 // ------------- COP1. Coprocessor instructions. | 4074 // ------------- COP1. Coprocessor instructions. |
| 4084 case COP1: | 4075 case COP1: |
| 4085 switch (instr->RsFieldRaw()) { | 4076 switch (instr_.RsFieldRaw()) { |
| 4086 case BC1: { // Branch on coprocessor condition. | 4077 case BC1: { // Branch on coprocessor condition. |
| 4087 // Floating point. | 4078 // Floating point. |
| 4088 uint32_t cc = instr->FBccValue(); | 4079 uint32_t cc = instr_.FBccValue(); |
| 4089 uint32_t fcsr_cc = get_fcsr_condition_bit(cc); | 4080 uint32_t fcsr_cc = get_fcsr_condition_bit(cc); |
| 4090 uint32_t cc_value = test_fcsr_bit(fcsr_cc); | 4081 uint32_t cc_value = test_fcsr_bit(fcsr_cc); |
| 4091 bool do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value; | 4082 bool do_branch = (instr_.FBtrueValue()) ? cc_value : !cc_value; |
| 4092 BranchHelper(do_branch); | 4083 BranchHelper(do_branch); |
| 4093 break; | 4084 break; |
| 4094 } | 4085 } |
| 4095 case BC1EQZ: | 4086 case BC1EQZ: |
| 4096 BranchHelper(!(get_fpu_register(ft_reg) & 0x1)); | 4087 BranchHelper(!(get_fpu_register(ft_reg) & 0x1)); |
| 4097 break; | 4088 break; |
| 4098 case BC1NEZ: | 4089 case BC1NEZ: |
| 4099 BranchHelper(get_fpu_register(ft_reg) & 0x1); | 4090 BranchHelper(get_fpu_register(ft_reg) & 0x1); |
| 4100 break; | 4091 break; |
| 4101 default: | 4092 default: |
| 4102 UNREACHABLE(); | 4093 UNREACHABLE(); |
| 4103 } | 4094 } |
| 4104 break; | 4095 break; |
| 4105 // ------------- REGIMM class. | 4096 // ------------- REGIMM class. |
| 4106 case REGIMM: | 4097 case REGIMM: |
| 4107 switch (instr->RtFieldRaw()) { | 4098 switch (instr_.RtFieldRaw()) { |
| 4108 case BLTZ: | 4099 case BLTZ: |
| 4109 BranchHelper(rs < 0); | 4100 BranchHelper(rs < 0); |
| 4110 break; | 4101 break; |
| 4111 case BGEZ: | 4102 case BGEZ: |
| 4112 BranchHelper(rs >= 0); | 4103 BranchHelper(rs >= 0); |
| 4113 break; | 4104 break; |
| 4114 case BLTZAL: | 4105 case BLTZAL: |
| 4115 BranchAndLinkHelper(rs < 0); | 4106 BranchAndLinkHelper(rs < 0); |
| 4116 break; | 4107 break; |
| 4117 case BGEZAL: | 4108 case BGEZAL: |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4305 } else { | 4296 } else { |
| 4306 // LUI | 4297 // LUI |
| 4307 SetResult(rt_reg, oe_imm16 << 16); | 4298 SetResult(rt_reg, oe_imm16 << 16); |
| 4308 } | 4299 } |
| 4309 break; | 4300 break; |
| 4310 // ------------- Memory instructions. | 4301 // ------------- Memory instructions. |
| 4311 case LB: | 4302 case LB: |
| 4312 set_register(rt_reg, ReadB(rs + se_imm16)); | 4303 set_register(rt_reg, ReadB(rs + se_imm16)); |
| 4313 break; | 4304 break; |
| 4314 case LH: | 4305 case LH: |
| 4315 set_register(rt_reg, ReadH(rs + se_imm16, instr)); | 4306 set_register(rt_reg, ReadH(rs + se_imm16, instr_.instr())); |
| 4316 break; | 4307 break; |
| 4317 case LWL: { | 4308 case LWL: { |
| 4318 // al_offset is offset of the effective address within an aligned word. | 4309 // al_offset is offset of the effective address within an aligned word. |
| 4319 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; | 4310 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; |
| 4320 uint8_t byte_shift = kPointerAlignmentMask - al_offset; | 4311 uint8_t byte_shift = kPointerAlignmentMask - al_offset; |
| 4321 uint32_t mask = (1 << byte_shift * 8) - 1; | 4312 uint32_t mask = (1 << byte_shift * 8) - 1; |
| 4322 addr = rs + se_imm16 - al_offset; | 4313 addr = rs + se_imm16 - al_offset; |
| 4323 alu_out = ReadW(addr, instr); | 4314 alu_out = ReadW(addr, instr_.instr()); |
| 4324 alu_out <<= byte_shift * 8; | 4315 alu_out <<= byte_shift * 8; |
| 4325 alu_out |= rt & mask; | 4316 alu_out |= rt & mask; |
| 4326 set_register(rt_reg, alu_out); | 4317 set_register(rt_reg, alu_out); |
| 4327 break; | 4318 break; |
| 4328 } | 4319 } |
| 4329 case LW: | 4320 case LW: |
| 4330 set_register(rt_reg, ReadW(rs + se_imm16, instr)); | 4321 set_register(rt_reg, ReadW(rs + se_imm16, instr_.instr())); |
| 4331 break; | 4322 break; |
| 4332 case LBU: | 4323 case LBU: |
| 4333 set_register(rt_reg, ReadBU(rs + se_imm16)); | 4324 set_register(rt_reg, ReadBU(rs + se_imm16)); |
| 4334 break; | 4325 break; |
| 4335 case LHU: | 4326 case LHU: |
| 4336 set_register(rt_reg, ReadHU(rs + se_imm16, instr)); | 4327 set_register(rt_reg, ReadHU(rs + se_imm16, instr_.instr())); |
| 4337 break; | 4328 break; |
| 4338 case LWR: { | 4329 case LWR: { |
| 4339 // al_offset is offset of the effective address within an aligned word. | 4330 // al_offset is offset of the effective address within an aligned word. |
| 4340 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; | 4331 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; |
| 4341 uint8_t byte_shift = kPointerAlignmentMask - al_offset; | 4332 uint8_t byte_shift = kPointerAlignmentMask - al_offset; |
| 4342 uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0; | 4333 uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0; |
| 4343 addr = rs + se_imm16 - al_offset; | 4334 addr = rs + se_imm16 - al_offset; |
| 4344 alu_out = ReadW(addr, instr); | 4335 alu_out = ReadW(addr, instr_.instr()); |
| 4345 alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8; | 4336 alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8; |
| 4346 alu_out |= rt & mask; | 4337 alu_out |= rt & mask; |
| 4347 set_register(rt_reg, alu_out); | 4338 set_register(rt_reg, alu_out); |
| 4348 break; | 4339 break; |
| 4349 } | 4340 } |
| 4350 case SB: | 4341 case SB: |
| 4351 WriteB(rs + se_imm16, static_cast<int8_t>(rt)); | 4342 WriteB(rs + se_imm16, static_cast<int8_t>(rt)); |
| 4352 break; | 4343 break; |
| 4353 case SH: | 4344 case SH: |
| 4354 WriteH(rs + se_imm16, static_cast<uint16_t>(rt), instr); | 4345 WriteH(rs + se_imm16, static_cast<uint16_t>(rt), instr_.instr()); |
| 4355 break; | 4346 break; |
| 4356 case SWL: { | 4347 case SWL: { |
| 4357 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; | 4348 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; |
| 4358 uint8_t byte_shift = kPointerAlignmentMask - al_offset; | 4349 uint8_t byte_shift = kPointerAlignmentMask - al_offset; |
| 4359 uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0; | 4350 uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0; |
| 4360 addr = rs + se_imm16 - al_offset; | 4351 addr = rs + se_imm16 - al_offset; |
| 4361 // Value to be written in memory. | 4352 // Value to be written in memory. |
| 4362 uint32_t mem_value = ReadW(addr, instr) & mask; | 4353 uint32_t mem_value = ReadW(addr, instr_.instr()) & mask; |
| 4363 mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8; | 4354 mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8; |
| 4364 WriteW(addr, mem_value, instr); | 4355 WriteW(addr, mem_value, instr_.instr()); |
| 4365 break; | 4356 break; |
| 4366 } | 4357 } |
| 4367 case SW: | 4358 case SW: |
| 4368 WriteW(rs + se_imm16, rt, instr); | 4359 WriteW(rs + se_imm16, rt, instr_.instr()); |
| 4369 break; | 4360 break; |
| 4370 case SWR: { | 4361 case SWR: { |
| 4371 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; | 4362 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; |
| 4372 uint32_t mask = (1 << al_offset * 8) - 1; | 4363 uint32_t mask = (1 << al_offset * 8) - 1; |
| 4373 addr = rs + se_imm16 - al_offset; | 4364 addr = rs + se_imm16 - al_offset; |
| 4374 uint32_t mem_value = ReadW(addr, instr); | 4365 uint32_t mem_value = ReadW(addr, instr_.instr()); |
| 4375 mem_value = (rt << al_offset * 8) | (mem_value & mask); | 4366 mem_value = (rt << al_offset * 8) | (mem_value & mask); |
| 4376 WriteW(addr, mem_value, instr); | 4367 WriteW(addr, mem_value, instr_.instr()); |
| 4377 break; | 4368 break; |
| 4378 } | 4369 } |
| 4379 case LWC1: | 4370 case LWC1: |
| 4380 set_fpu_register_hi_word(ft_reg, 0); | 4371 set_fpu_register_hi_word(ft_reg, 0); |
| 4381 set_fpu_register_word(ft_reg, ReadW(rs + se_imm16, instr)); | 4372 set_fpu_register_word(ft_reg, |
| 4373 ReadW(rs + se_imm16, instr_.instr())); |
| 4382 break; | 4374 break; |
| 4383 case LDC1: | 4375 case LDC1: |
| 4384 set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr)); | 4376 set_fpu_register_double(ft_reg, |
| 4377 ReadD(rs + se_imm16, instr_.instr())); |
| 4385 break; | 4378 break; |
| 4386 case SWC1: | 4379 case SWC1: |
| 4387 WriteW(rs + se_imm16, get_fpu_register_word(ft_reg), instr); | 4380 WriteW(rs + se_imm16, get_fpu_register_word(ft_reg), |
| 4381 instr_.instr()); |
| 4388 break; | 4382 break; |
| 4389 case SDC1: | 4383 case SDC1: |
| 4390 WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr); | 4384 WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), |
| 4385 instr_.instr()); |
| 4391 break; | 4386 break; |
| 4392 // ------------- PC-Relative instructions. | 4387 // ------------- PC-Relative instructions. |
| 4393 case PCREL: { | 4388 case PCREL: { |
| 4394 // rt field: checking 5-bits. | 4389 // rt field: checking 5-bits. |
| 4395 int32_t imm21 = instr->Imm21Value(); | 4390 int32_t imm21 = instr_.Imm21Value(); |
| 4396 int32_t current_pc = get_pc(); | 4391 int32_t current_pc = get_pc(); |
| 4397 uint8_t rt = (imm21 >> kImm16Bits); | 4392 uint8_t rt = (imm21 >> kImm16Bits); |
| 4398 switch (rt) { | 4393 switch (rt) { |
| 4399 case ALUIPC: | 4394 case ALUIPC: |
| 4400 addr = current_pc + (se_imm16 << 16); | 4395 addr = current_pc + (se_imm16 << 16); |
| 4401 alu_out = static_cast<int64_t>(~0x0FFFF) & addr; | 4396 alu_out = static_cast<int64_t>(~0x0FFFF) & addr; |
| 4402 break; | 4397 break; |
| 4403 case AUIPC: | 4398 case AUIPC: |
| 4404 alu_out = current_pc + (se_imm16 << 16); | 4399 alu_out = current_pc + (se_imm16 << 16); |
| 4405 break; | 4400 break; |
| 4406 default: { | 4401 default: { |
| 4407 int32_t imm19 = instr->Imm19Value(); | 4402 int32_t imm19 = instr_.Imm19Value(); |
| 4408 // rt field: checking the most significant 2-bits. | 4403 // rt field: checking the most significant 2-bits. |
| 4409 rt = (imm21 >> kImm19Bits); | 4404 rt = (imm21 >> kImm19Bits); |
| 4410 switch (rt) { | 4405 switch (rt) { |
| 4411 case LWPC: { | 4406 case LWPC: { |
| 4412 // Set sign. | 4407 // Set sign. |
| 4413 imm19 <<= (kOpcodeBits + kRsBits + 2); | 4408 imm19 <<= (kOpcodeBits + kRsBits + 2); |
| 4414 imm19 >>= (kOpcodeBits + kRsBits + 2); | 4409 imm19 >>= (kOpcodeBits + kRsBits + 2); |
| 4415 addr = current_pc + (imm19 << 2); | 4410 addr = current_pc + (imm19 << 2); |
| 4416 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr); | 4411 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr); |
| 4417 alu_out = *ptr; | 4412 alu_out = *ptr; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 4445 } | 4440 } |
| 4446 | 4441 |
| 4447 // If needed update pc after the branch delay execution. | 4442 // If needed update pc after the branch delay execution. |
| 4448 if (next_pc != bad_ra) { | 4443 if (next_pc != bad_ra) { |
| 4449 set_pc(next_pc); | 4444 set_pc(next_pc); |
| 4450 } | 4445 } |
| 4451 } | 4446 } |
| 4452 | 4447 |
| 4453 | 4448 |
| 4454 // Type 3: instructions using a 26 bytes immediate. (e.g. j, jal). | 4449 // Type 3: instructions using a 26 bytes immediate. (e.g. j, jal). |
| 4455 void Simulator::DecodeTypeJump(Instruction* instr) { | 4450 void Simulator::DecodeTypeJump() { |
| 4451 SimInstruction simInstr = instr_; |
| 4456 // Get current pc. | 4452 // Get current pc. |
| 4457 int32_t current_pc = get_pc(); | 4453 int32_t current_pc = get_pc(); |
| 4458 // Get unchanged bits of pc. | 4454 // Get unchanged bits of pc. |
| 4459 int32_t pc_high_bits = current_pc & 0xf0000000; | 4455 int32_t pc_high_bits = current_pc & 0xf0000000; |
| 4460 // Next pc. | 4456 // Next pc. |
| 4461 int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2); | 4457 |
| 4458 int32_t next_pc = pc_high_bits | (simInstr.Imm26Value() << 2); |
| 4462 | 4459 |
| 4463 // Execute branch delay slot. | 4460 // Execute branch delay slot. |
| 4464 // We don't check for end_sim_pc. First it should not be met as the current pc | 4461 // We don't check for end_sim_pc. First it should not be met as the current pc |
| 4465 // is valid. Secondly a jump should always execute its branch delay slot. | 4462 // is valid. Secondly a jump should always execute its branch delay slot. |
| 4466 Instruction* branch_delay_instr = | 4463 Instruction* branch_delay_instr = |
| 4467 reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize); | 4464 reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize); |
| 4468 BranchDelayInstructionDecode(branch_delay_instr); | 4465 BranchDelayInstructionDecode(branch_delay_instr); |
| 4469 | 4466 |
| 4470 // Update pc and ra if necessary. | 4467 // Update pc and ra if necessary. |
| 4471 // Do this after the branch delay execution. | 4468 // Do this after the branch delay execution. |
| 4472 if (instr->IsLinkingInstruction()) { | 4469 if (simInstr.IsLinkingInstruction()) { |
| 4473 set_register(31, current_pc + 2 * Instruction::kInstrSize); | 4470 set_register(31, current_pc + 2 * Instruction::kInstrSize); |
| 4474 } | 4471 } |
| 4475 set_pc(next_pc); | 4472 set_pc(next_pc); |
| 4476 pc_modified_ = true; | 4473 pc_modified_ = true; |
| 4477 } | 4474 } |
| 4478 | 4475 |
| 4479 | 4476 |
| 4480 // Executes the current instruction. | 4477 // Executes the current instruction. |
| 4481 void Simulator::InstructionDecode(Instruction* instr) { | 4478 void Simulator::InstructionDecode(Instruction* instr) { |
| 4482 if (v8::internal::FLAG_check_icache) { | 4479 if (v8::internal::FLAG_check_icache) { |
| 4483 CheckICache(isolate_->simulator_i_cache(), instr); | 4480 CheckICache(isolate_->simulator_i_cache(), instr); |
| 4484 } | 4481 } |
| 4485 pc_modified_ = false; | 4482 pc_modified_ = false; |
| 4486 v8::internal::EmbeddedVector<char, 256> buffer; | 4483 v8::internal::EmbeddedVector<char, 256> buffer; |
| 4487 if (::v8::internal::FLAG_trace_sim) { | 4484 if (::v8::internal::FLAG_trace_sim) { |
| 4488 SNPrintF(trace_buf_, "%s", ""); | 4485 SNPrintF(trace_buf_, "%s", ""); |
| 4489 disasm::NameConverter converter; | 4486 disasm::NameConverter converter; |
| 4490 disasm::Disassembler dasm(converter); | 4487 disasm::Disassembler dasm(converter); |
| 4491 dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr)); | 4488 dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr)); |
| 4492 } | 4489 } |
| 4493 | 4490 |
| 4494 switch (instr->InstructionType(Instruction::TypeChecks::EXTRA)) { | 4491 instr_ = instr; |
| 4492 switch (instr_.InstructionType()) { |
| 4495 case Instruction::kRegisterType: | 4493 case Instruction::kRegisterType: |
| 4496 DecodeTypeRegister(instr); | 4494 DecodeTypeRegister(); |
| 4497 break; | 4495 break; |
| 4498 case Instruction::kImmediateType: | 4496 case Instruction::kImmediateType: |
| 4499 DecodeTypeImmediate(instr); | 4497 DecodeTypeImmediate(); |
| 4500 break; | 4498 break; |
| 4501 case Instruction::kJumpType: | 4499 case Instruction::kJumpType: |
| 4502 DecodeTypeJump(instr); | 4500 DecodeTypeJump(); |
| 4503 break; | 4501 break; |
| 4504 default: | 4502 default: |
| 4505 UNSUPPORTED(); | 4503 UNSUPPORTED(); |
| 4506 } | 4504 } |
| 4507 if (::v8::internal::FLAG_trace_sim) { | 4505 if (::v8::internal::FLAG_trace_sim) { |
| 4508 PrintF(" 0x%08" PRIxPTR " %-44s %s\n", | 4506 PrintF(" 0x%08" PRIxPTR " %-44s %s\n", |
| 4509 reinterpret_cast<intptr_t>(instr), buffer.start(), | 4507 reinterpret_cast<intptr_t>(instr), buffer.start(), |
| 4510 trace_buf_.start()); | 4508 trace_buf_.start()); |
| 4511 } | 4509 } |
| 4512 if (!pc_modified_) { | 4510 if (!pc_modified_) { |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4697 | 4695 |
| 4698 | 4696 |
| 4699 #undef UNSUPPORTED | 4697 #undef UNSUPPORTED |
| 4700 | 4698 |
| 4701 } // namespace internal | 4699 } // namespace internal |
| 4702 } // namespace v8 | 4700 } // namespace v8 |
| 4703 | 4701 |
| 4704 #endif // USE_SIMULATOR | 4702 #endif // USE_SIMULATOR |
| 4705 | 4703 |
| 4706 #endif // V8_TARGET_ARCH_MIPS | 4704 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |