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 |