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

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

Issue 1310883005: MIPS: Optimize simulator. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: DecodeTypeImmediate(): BranchCommon refinement. Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« src/mips/simulator-mips.h ('K') | « src/mips/simulator-mips.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 938 matching lines...) Expand 10 before | Expand all | Expand 10 after
949 if (i_cache_ == NULL) { 949 if (i_cache_ == NULL) {
950 i_cache_ = new v8::internal::HashMap(&ICacheMatch); 950 i_cache_ = new v8::internal::HashMap(&ICacheMatch);
951 isolate_->set_simulator_i_cache(i_cache_); 951 isolate_->set_simulator_i_cache(i_cache_);
952 } 952 }
953 Initialize(isolate); 953 Initialize(isolate);
954 // Set up simulator support first. Some of this information is needed to 954 // Set up simulator support first. Some of this information is needed to
955 // setup the architecture state. 955 // setup the architecture state.
956 stack_ = reinterpret_cast<char*>(malloc(stack_size_)); 956 stack_ = reinterpret_cast<char*>(malloc(stack_size_));
957 pc_modified_ = false; 957 pc_modified_ = false;
958 icount_ = 0; 958 icount_ = 0;
959 type_immediate_count_ = 0;
960 type_register_count_ = 0;
961 type_register_cop1_count_ = 0;
962 type_register_cop1x_count_ = 0;
963 type_register_special_count_ = 0;
964 type_register_special2_count_ = 0;
965 type_register_special3_count_ = 0;
966 type_jump_count_ = 0;
959 break_count_ = 0; 967 break_count_ = 0;
960 break_pc_ = NULL; 968 break_pc_ = NULL;
961 break_instr_ = 0; 969 break_instr_ = 0;
962 970
963 // Set up architecture state. 971 // Set up architecture state.
964 // All registers are initialized to zero to start with. 972 // All registers are initialized to zero to start with.
965 for (int i = 0; i < kNumSimuRegisters; i++) { 973 for (int i = 0; i < kNumSimuRegisters; i++) {
966 registers_[i] = 0; 974 registers_[i] = 0;
967 } 975 }
968 for (int i = 0; i < kNumFPURegisters; i++) { 976 for (int i = 0; i < kNumFPURegisters; i++) {
969 FPUregisters_[i] = 0; 977 FPUregisters_[i] = 0;
970 } 978 }
971 FCSR_ = 0; 979 FCSR_ = 0;
972 980
973 // The sp is initialized to point to the bottom (high address) of the 981 // The sp is initialized to point to the bottom (high address) of the
974 // allocated stack area. To be safe in potential stack underflows we leave 982 // allocated stack area. To be safe in potential stack underflows we leave
975 // some buffer below. 983 // some buffer below.
976 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size_ - 64; 984 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size_ - 64;
977 // The ra and pc are initialized to a known bad value that will cause an 985 // The ra and pc are initialized to a known bad value that will cause an
978 // access violation if the simulator ever tries to execute it. 986 // access violation if the simulator ever tries to execute it.
979 registers_[pc] = bad_ra; 987 registers_[pc] = bad_ra;
980 registers_[ra] = bad_ra; 988 registers_[ra] = bad_ra;
981 InitializeCoverage(); 989 InitializeCoverage();
982 for (int i = 0; i < kNumExceptions; i++) {
983 exceptions[i] = 0;
984 }
985
986 last_debugger_input_ = NULL; 990 last_debugger_input_ = NULL;
987 } 991 }
988 992
989 993
990 Simulator::~Simulator() { free(stack_); } 994 Simulator::~Simulator() {
995 fprintf(stderr, "executed instructions: %" PRIu64 "\n", icount_);
paul.l... 2015/09/02 17:30:13 See my other comment (simulator-mips.h) about thes
balazs.kilvady 2015/09/04 12:57:15 Done.
996 fprintf(stderr, "IMMEDIATE instructions: %" PRIu64 "\n",
997 type_immediate_count_);
998 fprintf(stderr, "JUMP instructions: %" PRIu64 "\n", type_jump_count_);
999 fprintf(stderr, "REGISTER instructions: %" PRIu64 "\n", type_register_count_);
1000 fprintf(stderr, "REGISTER/COP1 instructions: %" PRIu64 "\n",
1001 type_register_cop1_count_);
1002 fprintf(stderr, "REGISTER/COP1X instructions: %" PRIu64 "\n",
1003 type_register_cop1x_count_);
1004 fprintf(stderr, "REGISTER/SPECIAL instructions: %" PRIu64 "\n",
1005 type_register_special_count_);
1006 fprintf(stderr, "REGISTER/SPECIAL2 instructions: %" PRIu64 "\n",
1007 type_register_special2_count_);
1008 fprintf(stderr, "REGISTER/SPECIAL3 instructions: %" PRIu64 "\n",
1009 type_register_special3_count_);
1010 free(stack_);
1011 }
991 1012
992 1013
993 // When the generated code calls an external reference we need to catch that in 1014 // When the generated code calls an external reference we need to catch that in
994 // the simulator. The external reference will be a function compiled for the 1015 // the simulator. The external reference will be a function compiled for the
995 // host architecture. We need to call that function instead of trying to 1016 // host architecture. We need to call that function instead of trying to
996 // execute it with the simulator. We do that by redirecting the external 1017 // execute it with the simulator. We do that by redirecting the external
997 // reference to a swi (software-interrupt) instruction that is handled by 1018 // reference to a swi (software-interrupt) instruction that is handled by
998 // the simulator. We write the original destination of the jump just at a known 1019 // the simulator. We write the original destination of the jump just at a known
999 // offset from the swi instruction so the simulator knows what to call. 1020 // offset from the swi instruction so the simulator knows what to call.
1000 class Redirection { 1021 class Redirection {
(...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after
1621 void Simulator::TraceRegWr(int32_t value) { 1642 void Simulator::TraceRegWr(int32_t value) {
1622 if (::v8::internal::FLAG_trace_sim) { 1643 if (::v8::internal::FLAG_trace_sim) {
1623 SNPrintF(trace_buf_, "%08x", value); 1644 SNPrintF(trace_buf_, "%08x", value);
1624 } 1645 }
1625 } 1646 }
1626 1647
1627 1648
1628 // TODO(plind): consider making icount_ printing a flag option. 1649 // TODO(plind): consider making icount_ printing a flag option.
1629 void Simulator::TraceMemRd(int32_t addr, int32_t value) { 1650 void Simulator::TraceMemRd(int32_t addr, int32_t value) {
1630 if (::v8::internal::FLAG_trace_sim) { 1651 if (::v8::internal::FLAG_trace_sim) {
1631 SNPrintF(trace_buf_, "%08x <-- [%08x] (%d)", value, addr, icount_); 1652 SNPrintF(trace_buf_, "%08x <-- [%08x] (%" PRIu64 ")", value, addr,
1653 icount_);
1632 } 1654 }
1633 } 1655 }
1634 1656
1635 1657
1636 void Simulator::TraceMemWr(int32_t addr, int32_t value, TraceType t) { 1658 void Simulator::TraceMemWr(int32_t addr, int32_t value, TraceType t) {
1637 if (::v8::internal::FLAG_trace_sim) { 1659 if (::v8::internal::FLAG_trace_sim) {
1638 switch (t) { 1660 switch (t) {
1639 case BYTE: 1661 case BYTE:
1640 SNPrintF(trace_buf_, " %02x --> [%08x]", 1662 SNPrintF(trace_buf_, " %02x --> [%08x]",
1641 static_cast<int8_t>(value), addr); 1663 static_cast<int8_t>(value), addr);
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after
2094 2116
2095 // Stop helper functions. 2117 // Stop helper functions.
2096 bool Simulator::IsWatchpoint(uint32_t code) { 2118 bool Simulator::IsWatchpoint(uint32_t code) {
2097 return (code <= kMaxWatchpointCode); 2119 return (code <= kMaxWatchpointCode);
2098 } 2120 }
2099 2121
2100 2122
2101 void Simulator::PrintWatchpoint(uint32_t code) { 2123 void Simulator::PrintWatchpoint(uint32_t code) {
2102 MipsDebugger dbg(this); 2124 MipsDebugger dbg(this);
2103 ++break_count_; 2125 ++break_count_;
2104 PrintF("\n---- break %d marker: %3d (instr count: %8d) ----------" 2126 PrintF("\n---- break %d marker: %3d (instr count: %" PRIu64
2127 ") ----------"
2105 "----------------------------------", 2128 "----------------------------------",
2106 code, break_count_, icount_); 2129 code, break_count_, icount_);
2107 dbg.PrintAllRegs(); // Print registers and continue running. 2130 dbg.PrintAllRegs(); // Print registers and continue running.
2108 } 2131 }
2109 2132
2110 2133
2111 void Simulator::HandleStop(uint32_t code, Instruction* instr) { 2134 void Simulator::HandleStop(uint32_t code, Instruction* instr) {
2112 // Stop if it is enabled, otherwise go on jumping over the stop 2135 // Stop if it is enabled, otherwise go on jumping over the stop
2113 // and the message address. 2136 // and the message address.
2114 if (IsEnabledStop(code)) { 2137 if (IsEnabledStop(code)) {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
2178 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n", 2201 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
2179 code, code, state, count, watched_stops_[code].desc); 2202 code, code, state, count, watched_stops_[code].desc);
2180 } else { 2203 } else {
2181 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n", 2204 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n",
2182 code, code, state, count); 2205 code, code, state, count);
2183 } 2206 }
2184 } 2207 }
2185 } 2208 }
2186 2209
2187 2210
2188 void Simulator::SignalExceptions() { 2211 void Simulator::SignalException(Exception e) {
2189 for (int i = 1; i < kNumExceptions; i++) { 2212 V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.",
2190 if (exceptions[i] != 0) { 2213 static_cast<int>(e));
2191 V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", i);
2192 }
2193 }
2194 } 2214 }
2195 2215
2196 2216
2197 // Handle execution based on instruction types. 2217 void Simulator::DecodeTypeRegisterDRsType() {
2198
2199 void Simulator::ConfigureTypeRegister(Instruction* instr,
2200 int32_t* alu_out,
2201 int64_t* i64hilo,
2202 uint64_t* u64hilo,
2203 int32_t* next_pc,
2204 int32_t* return_addr_reg,
2205 bool* do_interrupt) {
2206 // Every local variable declared here needs to be const.
2207 // This is to make sure that changed values are sent back to
2208 // DecodeTypeRegister correctly.
2209
2210 // Instruction fields.
2211 const Opcode op = instr->OpcodeFieldRaw();
2212 const int32_t rs_reg = instr->RsValue();
2213 const int32_t rs = get_register(rs_reg);
2214 const uint32_t rs_u = static_cast<uint32_t>(rs);
2215 const int32_t rt_reg = instr->RtValue();
2216 const int32_t rt = get_register(rt_reg);
2217 const uint32_t rt_u = static_cast<uint32_t>(rt);
2218 const int32_t rd_reg = instr->RdValue();
2219 const uint32_t sa = instr->SaValue();
2220 const uint8_t bp = instr->Bp2Value();
2221
2222 const int32_t fs_reg = instr->FsValue();
2223
2224
2225 // ---------- Configuration.
2226 switch (op) {
2227 case COP1: // Coprocessor instructions.
2228 switch (instr->RsFieldRaw()) {
2229 case CFC1:
2230 // At the moment only FCSR is supported.
2231 DCHECK(fs_reg == kFCSRRegister);
2232 *alu_out = FCSR_;
2233 break;
2234 case MFC1:
2235 *alu_out = get_fpu_register_word(fs_reg);
2236 break;
2237 case MFHC1:
2238 *alu_out = get_fpu_register_hi_word(fs_reg);
2239 break;
2240 case CTC1:
2241 case MTC1:
2242 case MTHC1:
2243 case S:
2244 case D:
2245 case W:
2246 case L:
2247 case PS:
2248 // Do everything in the execution step.
2249 break;
2250 default:
2251 // BC1 BC1EQZ BC1NEZ handled in DecodeTypeImmed, should never come here.
2252 UNREACHABLE();
2253 }
2254 break;
2255 case COP1X:
2256 break;
2257 case SPECIAL:
2258 switch (instr->FunctionFieldRaw()) {
2259 case JR:
2260 case JALR:
2261 *next_pc = get_register(instr->RsValue());
2262 *return_addr_reg = instr->RdValue();
2263 break;
2264 case SLL:
2265 *alu_out = rt << sa;
2266 break;
2267 case SRL:
2268 if (rs_reg == 0) {
2269 // Regular logical right shift of a word by a fixed number of
2270 // bits instruction. RS field is always equal to 0.
2271 *alu_out = rt_u >> sa;
2272 } else {
2273 // Logical right-rotate of a word by a fixed number of bits. This
2274 // is special case of SRL instruction, added in MIPS32 Release 2.
2275 // RS field is equal to 00001.
2276 *alu_out = base::bits::RotateRight32(rt_u, sa);
2277 }
2278 break;
2279 case SRA:
2280 *alu_out = rt >> sa;
2281 break;
2282 case SLLV:
2283 *alu_out = rt << rs;
2284 break;
2285 case SRLV:
2286 if (sa == 0) {
2287 // Regular logical right-shift of a word by a variable number of
2288 // bits instruction. SA field is always equal to 0.
2289 *alu_out = rt_u >> rs;
2290 } else {
2291 // Logical right-rotate of a word by a variable number of bits.
2292 // This is special case od SRLV instruction, added in MIPS32
2293 // Release 2. SA field is equal to 00001.
2294 *alu_out = base::bits::RotateRight32(rt_u, rs_u);
2295 }
2296 break;
2297 case SRAV:
2298 *alu_out = rt >> rs;
2299 break;
2300 case MFHI: // MFHI == CLZ on R6.
2301 if (!IsMipsArchVariant(kMips32r6)) {
2302 DCHECK(instr->SaValue() == 0);
2303 *alu_out = get_register(HI);
2304 } else {
2305 // MIPS spec: If no bits were set in GPR rs, the result written to
2306 // GPR rd is 32.
2307 DCHECK(instr->SaValue() == 1);
2308 *alu_out = base::bits::CountLeadingZeros32(rs_u);
2309 }
2310 break;
2311 case MFLO:
2312 *alu_out = get_register(LO);
2313 break;
2314 case MULT: // MULT == MUL_MUH.
2315 if (!IsMipsArchVariant(kMips32r6)) {
2316 *i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt);
2317 } else {
2318 switch (instr->SaValue()) {
2319 case MUL_OP:
2320 case MUH_OP:
2321 *i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt);
2322 break;
2323 default:
2324 UNIMPLEMENTED_MIPS();
2325 break;
2326 }
2327 }
2328 break;
2329 case MULTU: // MULTU == MUL_MUH_U.
2330 if (!IsMipsArchVariant(kMips32r6)) {
2331 *u64hilo = static_cast<uint64_t>(rs_u) *
2332 static_cast<uint64_t>(rt_u);
2333 } else {
2334 switch (instr->SaValue()) {
2335 case MUL_OP:
2336 case MUH_OP:
2337 *u64hilo = static_cast<uint64_t>(rs_u) *
2338 static_cast<uint64_t>(rt_u);
2339 break;
2340 default:
2341 UNIMPLEMENTED_MIPS();
2342 break;
2343 }
2344 }
2345 break;
2346 case ADD:
2347 if (HaveSameSign(rs, rt)) {
2348 if (rs > 0) {
2349 exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - rt);
2350 } else if (rs < 0) {
2351 exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue - rt);
2352 }
2353 }
2354 *alu_out = rs + rt;
2355 break;
2356 case ADDU:
2357 *alu_out = rs + rt;
2358 break;
2359 case SUB:
2360 if (!HaveSameSign(rs, rt)) {
2361 if (rs > 0) {
2362 exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue + rt);
2363 } else if (rs < 0) {
2364 exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue + rt);
2365 }
2366 }
2367 *alu_out = rs - rt;
2368 break;
2369 case SUBU:
2370 *alu_out = rs - rt;
2371 break;
2372 case AND:
2373 *alu_out = rs & rt;
2374 break;
2375 case OR:
2376 *alu_out = rs | rt;
2377 break;
2378 case XOR:
2379 *alu_out = rs ^ rt;
2380 break;
2381 case NOR:
2382 *alu_out = ~(rs | rt);
2383 break;
2384 case SLT:
2385 *alu_out = rs < rt ? 1 : 0;
2386 break;
2387 case SLTU:
2388 *alu_out = rs_u < rt_u ? 1 : 0;
2389 break;
2390 // Break and trap instructions.
2391 case BREAK:
2392 *do_interrupt = true;
2393 break;
2394 case TGE:
2395 *do_interrupt = rs >= rt;
2396 break;
2397 case TGEU:
2398 *do_interrupt = rs_u >= rt_u;
2399 break;
2400 case TLT:
2401 *do_interrupt = rs < rt;
2402 break;
2403 case TLTU:
2404 *do_interrupt = rs_u < rt_u;
2405 break;
2406 case TEQ:
2407 *do_interrupt = rs == rt;
2408 break;
2409 case TNE:
2410 *do_interrupt = rs != rt;
2411 break;
2412 case MOVN:
2413 case MOVZ:
2414 case MOVCI:
2415 // No action taken on decode.
2416 break;
2417 case DIV:
2418 case DIVU:
2419 // div and divu never raise exceptions.
2420 case SELEQZ_S:
2421 case SELNEZ_S:
2422 break;
2423 default:
2424 UNREACHABLE();
2425 }
2426 break;
2427 case SPECIAL2:
2428 switch (instr->FunctionFieldRaw()) {
2429 case MUL:
2430 *alu_out = rs_u * rt_u; // Only the lower 32 bits are kept.
2431 break;
2432 case CLZ:
2433 // MIPS32 spec: If no bits were set in GPR rs, the result written to
2434 // GPR rd is 32.
2435 *alu_out = base::bits::CountLeadingZeros32(rs_u);
2436 break;
2437 default:
2438 UNREACHABLE();
2439 }
2440 break;
2441 case SPECIAL3:
2442 switch (instr->FunctionFieldRaw()) {
2443 case INS: { // Mips32r2 instruction.
2444 // Interpret rd field as 5-bit msb of insert.
2445 uint16_t msb = rd_reg;
2446 // Interpret sa field as 5-bit lsb of insert.
2447 uint16_t lsb = sa;
2448 uint16_t size = msb - lsb + 1;
2449 uint32_t mask = (1 << size) - 1;
2450 *alu_out = (rt_u & ~(mask << lsb)) | ((rs_u & mask) << lsb);
2451 break;
2452 }
2453 case EXT: { // Mips32r2 instruction.
2454 // Interpret rd field as 5-bit msb of extract.
2455 uint16_t msb = rd_reg;
2456 // Interpret sa field as 5-bit lsb of extract.
2457 uint16_t lsb = sa;
2458 uint16_t size = msb + 1;
2459 uint32_t mask = (1 << size) - 1;
2460 *alu_out = (rs_u & (mask << lsb)) >> lsb;
2461 break;
2462 }
2463 case BSHFL: {
2464 int sa = instr->SaFieldRaw() >> kSaShift;
2465 switch (sa) {
2466 case BITSWAP: {
2467 uint32_t input = static_cast<uint32_t>(rt);
2468 uint32_t output = 0;
2469 uint8_t i_byte, o_byte;
2470
2471 // Reverse the bit in byte for each individual byte
2472 for (int i = 0; i < 4; i++) {
2473 output = output >> 8;
2474 i_byte = input & 0xff;
2475
2476 // Fast way to reverse bits in byte
2477 // Devised by Sean Anderson, July 13, 2001
2478 o_byte =
2479 static_cast<uint8_t>(((i_byte * 0x0802LU & 0x22110LU) |
2480 (i_byte * 0x8020LU & 0x88440LU)) *
2481 0x10101LU >>
2482 16);
2483
2484 output = output | (static_cast<uint32_t>(o_byte << 24));
2485 input = input >> 8;
2486 }
2487
2488 *alu_out = static_cast<int32_t>(output);
2489 break;
2490 }
2491 case SEB:
2492 case SEH:
2493 case WSBH:
2494 UNREACHABLE();
2495 break;
2496 default: {
2497 sa >>= kBp2Bits;
2498 switch (sa) {
2499 case ALIGN: {
2500 if (bp == 0) {
2501 *alu_out = static_cast<int32_t>(rt);
2502 } else {
2503 uint32_t rt_hi = rt << (8 * bp);
2504 uint32_t rs_lo = rs >> (8 * (4 - bp));
2505 *alu_out = static_cast<int32_t>(rt_hi | rs_lo);
2506 }
2507 break;
2508 }
2509 default:
2510 UNREACHABLE();
2511 break;
2512 }
2513 }
2514 }
2515 break;
2516 }
2517 default:
2518 UNREACHABLE();
2519 }
2520 break;
2521 default:
2522 UNREACHABLE();
2523 }
2524 }
2525
2526
2527 void Simulator::DecodeTypeRegisterDRsType(Instruction* instr,
2528 const int32_t& fr_reg,
2529 const int32_t& fs_reg,
2530 const int32_t& ft_reg,
2531 const int32_t& fd_reg) {
2532 double ft, fs, fd; 2218 double ft, fs, fd;
2533 uint32_t cc, fcsr_cc; 2219 uint32_t cc, fcsr_cc;
2534 int64_t i64; 2220 int64_t i64;
2535 fs = get_fpu_register_double(fs_reg); 2221 fs = get_fpu_register_double(fs_reg());
2536 ft = (instr->FunctionFieldRaw() != MOVF) ? get_fpu_register_double(ft_reg) 2222 ft = (get_instr()->FunctionFieldRaw() != MOVF)
2537 : 0.0; 2223 ? get_fpu_register_double(ft_reg())
2538 fd = get_fpu_register_double(fd_reg); 2224 : 0.0;
2225 fd = get_fpu_register_double(fd_reg());
2539 int64_t ft_int = bit_cast<int64_t>(ft); 2226 int64_t ft_int = bit_cast<int64_t>(ft);
2540 int64_t fd_int = bit_cast<int64_t>(fd); 2227 int64_t fd_int = bit_cast<int64_t>(fd);
2541 cc = instr->FCccValue(); 2228 cc = get_instr()->FCccValue();
2542 fcsr_cc = get_fcsr_condition_bit(cc); 2229 fcsr_cc = get_fcsr_condition_bit(cc);
2543 switch (instr->FunctionFieldRaw()) { 2230 switch (get_instr()->FunctionFieldRaw()) {
2544 case RINT: { 2231 case RINT: {
2545 DCHECK(IsMipsArchVariant(kMips32r6)); 2232 DCHECK(IsMipsArchVariant(kMips32r6));
2546 double result, temp, temp_result; 2233 double result, temp, temp_result;
2547 double upper = std::ceil(fs); 2234 double upper = std::ceil(fs);
2548 double lower = std::floor(fs); 2235 double lower = std::floor(fs);
2549 switch (get_fcsr_rounding_mode()) { 2236 switch (get_fcsr_rounding_mode()) {
2550 case kRoundToNearest: 2237 case kRoundToNearest:
2551 if (upper - fs < fs - lower) { 2238 if (upper - fs < fs - lower) {
2552 result = upper; 2239 result = upper;
2553 } else if (upper - fs > fs - lower) { 2240 } else if (upper - fs > fs - lower) {
(...skipping 11 matching lines...) Expand all
2565 case kRoundToZero: 2252 case kRoundToZero:
2566 result = (fs > 0 ? lower : upper); 2253 result = (fs > 0 ? lower : upper);
2567 break; 2254 break;
2568 case kRoundToPlusInf: 2255 case kRoundToPlusInf:
2569 result = upper; 2256 result = upper;
2570 break; 2257 break;
2571 case kRoundToMinusInf: 2258 case kRoundToMinusInf:
2572 result = lower; 2259 result = lower;
2573 break; 2260 break;
2574 } 2261 }
2575 set_fpu_register_double(fd_reg, result); 2262 set_fpu_register_double(fd_reg(), result);
2576 if (result != fs) { 2263 if (result != fs) {
2577 set_fcsr_bit(kFCSRInexactFlagBit, true); 2264 set_fcsr_bit(kFCSRInexactFlagBit, true);
2578 } 2265 }
2579 break; 2266 break;
2580 } 2267 }
2581 case SEL: 2268 case SEL:
2582 DCHECK(IsMipsArchVariant(kMips32r6)); 2269 DCHECK(IsMipsArchVariant(kMips32r6));
2583 set_fpu_register_double(fd_reg, (fd_int & 0x1) == 0 ? fs : ft); 2270 set_fpu_register_double(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft);
2584 break; 2271 break;
2585 case SELEQZ_C: 2272 case SELEQZ_C:
2586 DCHECK(IsMipsArchVariant(kMips32r6)); 2273 DCHECK(IsMipsArchVariant(kMips32r6));
2587 set_fpu_register_double(fd_reg, (ft_int & 0x1) == 0 ? fs : 0.0); 2274 set_fpu_register_double(fd_reg(), (ft_int & 0x1) == 0 ? fs : 0.0);
2588 break; 2275 break;
2589 case SELNEZ_C: 2276 case SELNEZ_C:
2590 DCHECK(IsMipsArchVariant(kMips32r6)); 2277 DCHECK(IsMipsArchVariant(kMips32r6));
2591 set_fpu_register_double(fd_reg, (ft_int & 0x1) != 0 ? fs : 0.0); 2278 set_fpu_register_double(fd_reg(), (ft_int & 0x1) != 0 ? fs : 0.0);
2592 break; 2279 break;
2593 case MOVZ_C: { 2280 case MOVZ_C: {
2594 DCHECK(IsMipsArchVariant(kMips32r2)); 2281 DCHECK(IsMipsArchVariant(kMips32r2));
2595 int32_t rt_reg = instr->RtValue(); 2282 if (rt() == 0) {
2596 int32_t rt = get_register(rt_reg); 2283 set_fpu_register_double(fd_reg(), fs);
2597 if (rt == 0) {
2598 set_fpu_register_double(fd_reg, fs);
2599 } 2284 }
2600 break; 2285 break;
2601 } 2286 }
2602 case MOVN_C: { 2287 case MOVN_C: {
2603 DCHECK(IsMipsArchVariant(kMips32r2)); 2288 DCHECK(IsMipsArchVariant(kMips32r2));
2604 int32_t rt_reg = instr->RtValue(); 2289 int32_t rt_reg = get_instr()->RtValue();
2605 int32_t rt = get_register(rt_reg); 2290 int32_t rt = get_register(rt_reg);
2606 if (rt != 0) { 2291 if (rt != 0) {
2607 set_fpu_register_double(fd_reg, fs); 2292 set_fpu_register_double(fd_reg(), fs);
2608 } 2293 }
2609 break; 2294 break;
2610 } 2295 }
2611 case MOVF: { 2296 case MOVF: {
2612 // Same function field for MOVT.D and MOVF.D 2297 // Same function field for MOVT.D and MOVF.D
2613 uint32_t ft_cc = (ft_reg >> 2) & 0x7; 2298 uint32_t ft_cc = (ft_reg() >> 2) & 0x7;
2614 ft_cc = get_fcsr_condition_bit(ft_cc); 2299 ft_cc = get_fcsr_condition_bit(ft_cc);
2615 if (instr->Bit(16)) { // Read Tf bit. 2300 if (get_instr()->Bit(16)) { // Read Tf bit.
2616 // MOVT.D 2301 // MOVT.D
2617 if (test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg, fs); 2302 if (test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs);
2618 } else { 2303 } else {
2619 // MOVF.D 2304 // MOVF.D
2620 if (!test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg, fs); 2305 if (!test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs);
2621 } 2306 }
2622 break; 2307 break;
2623 } 2308 }
2624 case MIN: 2309 case MIN:
2625 DCHECK(IsMipsArchVariant(kMips32r6)); 2310 DCHECK(IsMipsArchVariant(kMips32r6));
2626 fs = get_fpu_register_double(fs_reg); 2311 fs = get_fpu_register_double(fs_reg());
2627 if (std::isnan(fs) && std::isnan(ft)) { 2312 if (std::isnan(fs) && std::isnan(ft)) {
2628 set_fpu_register_double(fd_reg, fs); 2313 set_fpu_register_double(fd_reg(), fs);
2629 } else if (std::isnan(fs) && !std::isnan(ft)) { 2314 } else if (std::isnan(fs) && !std::isnan(ft)) {
2630 set_fpu_register_double(fd_reg, ft); 2315 set_fpu_register_double(fd_reg(), ft);
2631 } else if (!std::isnan(fs) && std::isnan(ft)) { 2316 } else if (!std::isnan(fs) && std::isnan(ft)) {
2632 set_fpu_register_double(fd_reg, fs); 2317 set_fpu_register_double(fd_reg(), fs);
2633 } else { 2318 } else {
2634 set_fpu_register_double(fd_reg, (fs >= ft) ? ft : fs); 2319 set_fpu_register_double(fd_reg(), (fs >= ft) ? ft : fs);
2635 } 2320 }
2636 break; 2321 break;
2637 case MINA: 2322 case MINA:
2638 DCHECK(IsMipsArchVariant(kMips32r6)); 2323 DCHECK(IsMipsArchVariant(kMips32r6));
2639 fs = get_fpu_register_double(fs_reg); 2324 fs = get_fpu_register_double(fs_reg());
2640 if (std::isnan(fs) && std::isnan(ft)) { 2325 if (std::isnan(fs) && std::isnan(ft)) {
2641 set_fpu_register_double(fd_reg, fs); 2326 set_fpu_register_double(fd_reg(), fs);
2642 } else if (std::isnan(fs) && !std::isnan(ft)) { 2327 } else if (std::isnan(fs) && !std::isnan(ft)) {
2643 set_fpu_register_double(fd_reg, ft); 2328 set_fpu_register_double(fd_reg(), ft);
2644 } else if (!std::isnan(fs) && std::isnan(ft)) { 2329 } else if (!std::isnan(fs) && std::isnan(ft)) {
2645 set_fpu_register_double(fd_reg, fs); 2330 set_fpu_register_double(fd_reg(), fs);
2646 } else { 2331 } else {
2647 double result; 2332 double result;
2648 if (fabs(fs) > fabs(ft)) { 2333 if (fabs(fs) > fabs(ft)) {
2649 result = ft; 2334 result = ft;
2650 } else if (fabs(fs) < fabs(ft)) { 2335 } else if (fabs(fs) < fabs(ft)) {
2651 result = fs; 2336 result = fs;
2652 } else { 2337 } else {
2653 result = (fs > ft ? fs : ft); 2338 result = (fs > ft ? fs : ft);
2654 } 2339 }
2655 set_fpu_register_double(fd_reg, result); 2340 set_fpu_register_double(fd_reg(), result);
2656 } 2341 }
2657 break; 2342 break;
2658 case MAXA: 2343 case MAXA:
2659 DCHECK(IsMipsArchVariant(kMips32r6)); 2344 DCHECK(IsMipsArchVariant(kMips32r6));
2660 fs = get_fpu_register_double(fs_reg); 2345 fs = get_fpu_register_double(fs_reg());
2661 if (std::isnan(fs) && std::isnan(ft)) { 2346 if (std::isnan(fs) && std::isnan(ft)) {
2662 set_fpu_register_double(fd_reg, fs); 2347 set_fpu_register_double(fd_reg(), fs);
2663 } else if (std::isnan(fs) && !std::isnan(ft)) { 2348 } else if (std::isnan(fs) && !std::isnan(ft)) {
2664 set_fpu_register_double(fd_reg, ft); 2349 set_fpu_register_double(fd_reg(), ft);
2665 } else if (!std::isnan(fs) && std::isnan(ft)) { 2350 } else if (!std::isnan(fs) && std::isnan(ft)) {
2666 set_fpu_register_double(fd_reg, fs); 2351 set_fpu_register_double(fd_reg(), fs);
2667 } else { 2352 } else {
2668 double result; 2353 double result;
2669 if (fabs(fs) < fabs(ft)) { 2354 if (fabs(fs) < fabs(ft)) {
2670 result = ft; 2355 result = ft;
2671 } else if (fabs(fs) > fabs(ft)) { 2356 } else if (fabs(fs) > fabs(ft)) {
2672 result = fs; 2357 result = fs;
2673 } else { 2358 } else {
2674 result = (fs > ft ? fs : ft); 2359 result = (fs > ft ? fs : ft);
2675 } 2360 }
2676 set_fpu_register_double(fd_reg, result); 2361 set_fpu_register_double(fd_reg(), result);
2677 } 2362 }
2678 break; 2363 break;
2679 case MAX: 2364 case MAX:
2680 DCHECK(IsMipsArchVariant(kMips32r6)); 2365 DCHECK(IsMipsArchVariant(kMips32r6));
2681 fs = get_fpu_register_double(fs_reg); 2366 fs = get_fpu_register_double(fs_reg());
2682 if (std::isnan(fs) && std::isnan(ft)) { 2367 if (std::isnan(fs) && std::isnan(ft)) {
2683 set_fpu_register_double(fd_reg, fs); 2368 set_fpu_register_double(fd_reg(), fs);
2684 } else if (std::isnan(fs) && !std::isnan(ft)) { 2369 } else if (std::isnan(fs) && !std::isnan(ft)) {
2685 set_fpu_register_double(fd_reg, ft); 2370 set_fpu_register_double(fd_reg(), ft);
2686 } else if (!std::isnan(fs) && std::isnan(ft)) { 2371 } else if (!std::isnan(fs) && std::isnan(ft)) {
2687 set_fpu_register_double(fd_reg, fs); 2372 set_fpu_register_double(fd_reg(), fs);
2688 } else { 2373 } else {
2689 set_fpu_register_double(fd_reg, (fs <= ft) ? ft : fs); 2374 set_fpu_register_double(fd_reg(), (fs <= ft) ? ft : fs);
2690 } 2375 }
2691 break; 2376 break;
2692 break; 2377 break;
2693 case ADD_D: 2378 case ADD_D:
2694 set_fpu_register_double(fd_reg, fs + ft); 2379 set_fpu_register_double(fd_reg(), fs + ft);
2695 break; 2380 break;
2696 case SUB_D: 2381 case SUB_D:
2697 set_fpu_register_double(fd_reg, fs - ft); 2382 set_fpu_register_double(fd_reg(), fs - ft);
2698 break; 2383 break;
2699 case MUL_D: 2384 case MUL_D:
2700 set_fpu_register_double(fd_reg, fs * ft); 2385 set_fpu_register_double(fd_reg(), fs * ft);
2701 break; 2386 break;
2702 case DIV_D: 2387 case DIV_D:
2703 set_fpu_register_double(fd_reg, fs / ft); 2388 set_fpu_register_double(fd_reg(), fs / ft);
2704 break; 2389 break;
2705 case ABS_D: 2390 case ABS_D:
2706 set_fpu_register_double(fd_reg, fabs(fs)); 2391 set_fpu_register_double(fd_reg(), fabs(fs));
2707 break; 2392 break;
2708 case MOV_D: 2393 case MOV_D:
2709 set_fpu_register_double(fd_reg, fs); 2394 set_fpu_register_double(fd_reg(), fs);
2710 break; 2395 break;
2711 case NEG_D: 2396 case NEG_D:
2712 set_fpu_register_double(fd_reg, -fs); 2397 set_fpu_register_double(fd_reg(), -fs);
2713 break; 2398 break;
2714 case SQRT_D: 2399 case SQRT_D:
2715 set_fpu_register_double(fd_reg, fast_sqrt(fs)); 2400 set_fpu_register_double(fd_reg(), fast_sqrt(fs));
2716 break; 2401 break;
2717 case RSQRT_D: { 2402 case RSQRT_D: {
2718 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); 2403 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2719 double result = 1.0 / fast_sqrt(fs); 2404 double result = 1.0 / fast_sqrt(fs);
2720 set_fpu_register_double(fd_reg, result); 2405 set_fpu_register_double(fd_reg(), result);
2721 break; 2406 break;
2722 } 2407 }
2723 case RECIP_D: { 2408 case RECIP_D: {
2724 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); 2409 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2725 double result = 1.0 / fs; 2410 double result = 1.0 / fs;
2726 set_fpu_register_double(fd_reg, result); 2411 set_fpu_register_double(fd_reg(), result);
2727 break; 2412 break;
2728 } 2413 }
2729 case C_UN_D: 2414 case C_UN_D:
2730 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); 2415 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2731 break; 2416 break;
2732 case C_EQ_D: 2417 case C_EQ_D:
2733 set_fcsr_bit(fcsr_cc, (fs == ft)); 2418 set_fcsr_bit(fcsr_cc, (fs == ft));
2734 break; 2419 break;
2735 case C_UEQ_D: 2420 case C_UEQ_D:
2736 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); 2421 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
2737 break; 2422 break;
2738 case C_OLT_D: 2423 case C_OLT_D:
2739 set_fcsr_bit(fcsr_cc, (fs < ft)); 2424 set_fcsr_bit(fcsr_cc, (fs < ft));
2740 break; 2425 break;
2741 case C_ULT_D: 2426 case C_ULT_D:
2742 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); 2427 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
2743 break; 2428 break;
2744 case C_OLE_D: 2429 case C_OLE_D:
2745 set_fcsr_bit(fcsr_cc, (fs <= ft)); 2430 set_fcsr_bit(fcsr_cc, (fs <= ft));
2746 break; 2431 break;
2747 case C_ULE_D: 2432 case C_ULE_D:
2748 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); 2433 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
2749 break; 2434 break;
2750 case CVT_W_D: { // Convert double to word. 2435 case CVT_W_D: { // Convert double to word.
2751 double rounded; 2436 double rounded;
2752 int32_t result; 2437 int32_t result;
2753 round_according_to_fcsr(fs, rounded, result, fs); 2438 round_according_to_fcsr(fs, rounded, result, fs);
2754 set_fpu_register_word(fd_reg, result); 2439 set_fpu_register_word(fd_reg(), result);
2755 if (set_fcsr_round_error(fs, rounded)) { 2440 if (set_fcsr_round_error(fs, rounded)) {
2756 set_fpu_register_word(fd_reg, kFPUInvalidResult); 2441 set_fpu_register_word(fd_reg(), kFPUInvalidResult);
2757 } 2442 }
2758 } break; 2443 } break;
2759 case ROUND_W_D: // Round double to word (round half to even). 2444 case ROUND_W_D: // Round double to word (round half to even).
2760 { 2445 {
2761 double rounded = std::floor(fs + 0.5); 2446 double rounded = std::floor(fs + 0.5);
2762 int32_t result = static_cast<int32_t>(rounded); 2447 int32_t result = static_cast<int32_t>(rounded);
2763 if ((result & 1) != 0 && result - fs == 0.5) { 2448 if ((result & 1) != 0 && result - fs == 0.5) {
2764 // If the number is halfway between two integers, 2449 // If the number is halfway between two integers,
2765 // round to the even one. 2450 // round to the even one.
2766 result--; 2451 result--;
2767 } 2452 }
2768 set_fpu_register_word(fd_reg, result); 2453 set_fpu_register_word(fd_reg(), result);
2769 if (set_fcsr_round_error(fs, rounded)) { 2454 if (set_fcsr_round_error(fs, rounded)) {
2770 set_fpu_register_word(fd_reg, kFPUInvalidResult); 2455 set_fpu_register_word(fd_reg(), kFPUInvalidResult);
2771 } 2456 }
2772 } break; 2457 } break;
2773 case TRUNC_W_D: // Truncate double to word (round towards 0). 2458 case TRUNC_W_D: // Truncate double to word (round towards 0).
2774 { 2459 {
2775 double rounded = trunc(fs); 2460 double rounded = trunc(fs);
2776 int32_t result = static_cast<int32_t>(rounded); 2461 int32_t result = static_cast<int32_t>(rounded);
2777 set_fpu_register_word(fd_reg, result); 2462 set_fpu_register_word(fd_reg(), result);
2778 if (set_fcsr_round_error(fs, rounded)) { 2463 if (set_fcsr_round_error(fs, rounded)) {
2779 set_fpu_register_word(fd_reg, kFPUInvalidResult); 2464 set_fpu_register_word(fd_reg(), kFPUInvalidResult);
2780 } 2465 }
2781 } break; 2466 } break;
2782 case FLOOR_W_D: // Round double to word towards negative infinity. 2467 case FLOOR_W_D: // Round double to word towards negative infinity.
2783 { 2468 {
2784 double rounded = std::floor(fs); 2469 double rounded = std::floor(fs);
2785 int32_t result = static_cast<int32_t>(rounded); 2470 int32_t result = static_cast<int32_t>(rounded);
2786 set_fpu_register_word(fd_reg, result); 2471 set_fpu_register_word(fd_reg(), result);
2787 if (set_fcsr_round_error(fs, rounded)) { 2472 if (set_fcsr_round_error(fs, rounded)) {
2788 set_fpu_register_word(fd_reg, kFPUInvalidResult); 2473 set_fpu_register_word(fd_reg(), kFPUInvalidResult);
2789 } 2474 }
2790 } break; 2475 } break;
2791 case CEIL_W_D: // Round double to word towards positive infinity. 2476 case CEIL_W_D: // Round double to word towards positive infinity.
2792 { 2477 {
2793 double rounded = std::ceil(fs); 2478 double rounded = std::ceil(fs);
2794 int32_t result = static_cast<int32_t>(rounded); 2479 int32_t result = static_cast<int32_t>(rounded);
2795 set_fpu_register_word(fd_reg, result); 2480 set_fpu_register_word(fd_reg(), result);
2796 if (set_fcsr_round_error(fs, rounded)) { 2481 if (set_fcsr_round_error(fs, rounded)) {
2797 set_fpu_register_word(fd_reg, kFPUInvalidResult); 2482 set_fpu_register_word(fd_reg(), kFPUInvalidResult);
2798 } 2483 }
2799 } break; 2484 } break;
2800 case CVT_S_D: // Convert double to float (single). 2485 case CVT_S_D: // Convert double to float (single).
2801 set_fpu_register_float(fd_reg, static_cast<float>(fs)); 2486 set_fpu_register_float(fd_reg(), static_cast<float>(fs));
2802 break; 2487 break;
2803 case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word. 2488 case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word.
2804 if (IsFp64Mode()) { 2489 if (IsFp64Mode()) {
2805 int64_t result; 2490 int64_t result;
2806 double rounded; 2491 double rounded;
2807 round64_according_to_fcsr(fs, rounded, result, fs); 2492 round64_according_to_fcsr(fs, rounded, result, fs);
2808 set_fpu_register(fd_reg, result); 2493 set_fpu_register(fd_reg(), result);
2809 if (set_fcsr_round64_error(fs, rounded)) { 2494 if (set_fcsr_round64_error(fs, rounded)) {
2810 set_fpu_register(fd_reg, kFPU64InvalidResult); 2495 set_fpu_register(fd_reg(), kFPU64InvalidResult);
2811 } 2496 }
2812 } else { 2497 } else {
2813 UNSUPPORTED(); 2498 UNSUPPORTED();
2814 } 2499 }
2815 break; 2500 break;
2816 break; 2501 break;
2817 } 2502 }
2818 case TRUNC_L_D: { // Mips32r2 instruction. 2503 case TRUNC_L_D: { // Mips32r2 instruction.
2819 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); 2504 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2820 double rounded = trunc(fs); 2505 double rounded = trunc(fs);
2821 i64 = static_cast<int64_t>(rounded); 2506 i64 = static_cast<int64_t>(rounded);
2822 if (IsFp64Mode()) { 2507 if (IsFp64Mode()) {
2823 set_fpu_register(fd_reg, i64); 2508 set_fpu_register(fd_reg(), i64);
2824 if (set_fcsr_round64_error(fs, rounded)) { 2509 if (set_fcsr_round64_error(fs, rounded)) {
2825 set_fpu_register(fd_reg, kFPU64InvalidResult); 2510 set_fpu_register(fd_reg(), kFPU64InvalidResult);
2826 } 2511 }
2827 } else { 2512 } else {
2828 UNSUPPORTED(); 2513 UNSUPPORTED();
2829 } 2514 }
2830 break; 2515 break;
2831 } 2516 }
2832 case ROUND_L_D: { // Mips32r2 instruction. 2517 case ROUND_L_D: { // Mips32r2 instruction.
2833 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); 2518 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2834 double rounded = std::floor(fs + 0.5); 2519 double rounded = std::floor(fs + 0.5);
2835 int64_t result = static_cast<int64_t>(rounded); 2520 int64_t result = static_cast<int64_t>(rounded);
2836 if ((result & 1) != 0 && result - fs == 0.5) { 2521 if ((result & 1) != 0 && result - fs == 0.5) {
2837 // If the number is halfway between two integers, 2522 // If the number is halfway between two integers,
2838 // round to the even one. 2523 // round to the even one.
2839 result--; 2524 result--;
2840 } 2525 }
2841 int64_t i64 = static_cast<int64_t>(result); 2526 int64_t i64 = static_cast<int64_t>(result);
2842 if (IsFp64Mode()) { 2527 if (IsFp64Mode()) {
2843 set_fpu_register(fd_reg, i64); 2528 set_fpu_register(fd_reg(), i64);
2844 if (set_fcsr_round64_error(fs, rounded)) { 2529 if (set_fcsr_round64_error(fs, rounded)) {
2845 set_fpu_register(fd_reg, kFPU64InvalidResult); 2530 set_fpu_register(fd_reg(), kFPU64InvalidResult);
2846 } 2531 }
2847 } else { 2532 } else {
2848 UNSUPPORTED(); 2533 UNSUPPORTED();
2849 } 2534 }
2850 break; 2535 break;
2851 } 2536 }
2852 case FLOOR_L_D: { // Mips32r2 instruction. 2537 case FLOOR_L_D: { // Mips32r2 instruction.
2853 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); 2538 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2854 double rounded = std::floor(fs); 2539 double rounded = std::floor(fs);
2855 int64_t i64 = static_cast<int64_t>(rounded); 2540 int64_t i64 = static_cast<int64_t>(rounded);
2856 if (IsFp64Mode()) { 2541 if (IsFp64Mode()) {
2857 set_fpu_register(fd_reg, i64); 2542 set_fpu_register(fd_reg(), i64);
2858 if (set_fcsr_round64_error(fs, rounded)) { 2543 if (set_fcsr_round64_error(fs, rounded)) {
2859 set_fpu_register(fd_reg, kFPU64InvalidResult); 2544 set_fpu_register(fd_reg(), kFPU64InvalidResult);
2860 } 2545 }
2861 } else { 2546 } else {
2862 UNSUPPORTED(); 2547 UNSUPPORTED();
2863 } 2548 }
2864 break; 2549 break;
2865 } 2550 }
2866 case CEIL_L_D: { // Mips32r2 instruction. 2551 case CEIL_L_D: { // Mips32r2 instruction.
2867 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); 2552 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2868 double rounded = std::ceil(fs); 2553 double rounded = std::ceil(fs);
2869 int64_t i64 = static_cast<int64_t>(rounded); 2554 int64_t i64 = static_cast<int64_t>(rounded);
2870 if (IsFp64Mode()) { 2555 if (IsFp64Mode()) {
2871 set_fpu_register(fd_reg, i64); 2556 set_fpu_register(fd_reg(), i64);
2872 if (set_fcsr_round64_error(fs, rounded)) { 2557 if (set_fcsr_round64_error(fs, rounded)) {
2873 set_fpu_register(fd_reg, kFPU64InvalidResult); 2558 set_fpu_register(fd_reg(), kFPU64InvalidResult);
2874 } 2559 }
2875 } else { 2560 } else {
2876 UNSUPPORTED(); 2561 UNSUPPORTED();
2877 } 2562 }
2878 break; 2563 break;
2879 } 2564 }
2880 case CLASS_D: { // Mips32r6 instruction 2565 case CLASS_D: { // Mips32r6 instruction
2881 // Convert double input to uint64_t for easier bit manipulation 2566 // Convert double input to uint64_t for easier bit manipulation
2882 uint64_t classed = bit_cast<uint64_t>(fs); 2567 uint64_t classed = bit_cast<uint64_t>(fs);
2883 2568
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2931 } 2616 }
2932 2617
2933 // Calculating result according to description of CLASS.D instruction 2618 // Calculating result according to description of CLASS.D instruction
2934 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) | 2619 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) |
2935 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) | 2620 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) |
2936 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan; 2621 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan;
2937 2622
2938 DCHECK(result != 0); 2623 DCHECK(result != 0);
2939 2624
2940 dResult = bit_cast<double>(result); 2625 dResult = bit_cast<double>(result);
2941 set_fpu_register_double(fd_reg, dResult); 2626 set_fpu_register_double(fd_reg(), dResult);
2942 2627
2943 break; 2628 break;
2944 } 2629 }
2945 case C_F_D: { 2630 case C_F_D: {
2946 set_fcsr_bit(fcsr_cc, false); 2631 set_fcsr_bit(fcsr_cc, false);
2947 break; 2632 break;
2948 } 2633 }
2949 default: 2634 default:
2950 UNREACHABLE(); 2635 UNREACHABLE();
2951 } 2636 }
2952 } 2637 }
2953 2638
2954 2639
2955 void Simulator::DecodeTypeRegisterWRsType(Instruction* instr, int32_t& alu_out, 2640 void Simulator::DecodeTypeRegisterWRsType() {
2956 const int32_t& fd_reg, 2641 float fs = get_fpu_register_float(fs_reg());
2957 const int32_t& fs_reg, 2642 float ft = get_fpu_register_float(ft_reg());
2958 const int32_t& ft_reg) { 2643 int32_t alu_out = 0x12345678;
2959 float fs = get_fpu_register_float(fs_reg); 2644 switch (get_instr()->FunctionFieldRaw()) {
2960 float ft = get_fpu_register_float(ft_reg);
2961 switch (instr->FunctionFieldRaw()) {
2962 case CVT_S_W: // Convert word to float (single). 2645 case CVT_S_W: // Convert word to float (single).
2963 alu_out = get_fpu_register_signed_word(fs_reg); 2646 alu_out = get_fpu_register_signed_word(fs_reg());
2964 set_fpu_register_float(fd_reg, static_cast<float>(alu_out)); 2647 set_fpu_register_float(fd_reg(), static_cast<float>(alu_out));
2965 break; 2648 break;
2966 case CVT_D_W: // Convert word to double. 2649 case CVT_D_W: // Convert word to double.
2967 alu_out = get_fpu_register_signed_word(fs_reg); 2650 alu_out = get_fpu_register_signed_word(fs_reg());
2968 set_fpu_register_double(fd_reg, static_cast<double>(alu_out)); 2651 set_fpu_register_double(fd_reg(), static_cast<double>(alu_out));
2969 break; 2652 break;
2970 case CMP_AF: 2653 case CMP_AF:
2971 set_fpu_register_word(fd_reg, 0); 2654 set_fpu_register_word(fd_reg(), 0);
2972 break; 2655 break;
2973 case CMP_UN: 2656 case CMP_UN:
2974 if (std::isnan(fs) || std::isnan(ft)) { 2657 if (std::isnan(fs) || std::isnan(ft)) {
2975 set_fpu_register_word(fd_reg, -1); 2658 set_fpu_register_word(fd_reg(), -1);
2976 } else { 2659 } else {
2977 set_fpu_register_word(fd_reg, 0); 2660 set_fpu_register_word(fd_reg(), 0);
2978 } 2661 }
2979 break; 2662 break;
2980 case CMP_EQ: 2663 case CMP_EQ:
2981 if (fs == ft) { 2664 if (fs == ft) {
2982 set_fpu_register_word(fd_reg, -1); 2665 set_fpu_register_word(fd_reg(), -1);
2983 } else { 2666 } else {
2984 set_fpu_register_word(fd_reg, 0); 2667 set_fpu_register_word(fd_reg(), 0);
2985 } 2668 }
2986 break; 2669 break;
2987 case CMP_UEQ: 2670 case CMP_UEQ:
2988 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { 2671 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
2989 set_fpu_register_word(fd_reg, -1); 2672 set_fpu_register_word(fd_reg(), -1);
2990 } else { 2673 } else {
2991 set_fpu_register_word(fd_reg, 0); 2674 set_fpu_register_word(fd_reg(), 0);
2992 } 2675 }
2993 break; 2676 break;
2994 case CMP_LT: 2677 case CMP_LT:
2995 if (fs < ft) { 2678 if (fs < ft) {
2996 set_fpu_register_word(fd_reg, -1); 2679 set_fpu_register_word(fd_reg(), -1);
2997 } else { 2680 } else {
2998 set_fpu_register_word(fd_reg, 0); 2681 set_fpu_register_word(fd_reg(), 0);
2999 } 2682 }
3000 break; 2683 break;
3001 case CMP_ULT: 2684 case CMP_ULT:
3002 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { 2685 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
3003 set_fpu_register_word(fd_reg, -1); 2686 set_fpu_register_word(fd_reg(), -1);
3004 } else { 2687 } else {
3005 set_fpu_register_word(fd_reg, 0); 2688 set_fpu_register_word(fd_reg(), 0);
3006 } 2689 }
3007 break; 2690 break;
3008 case CMP_LE: 2691 case CMP_LE:
3009 if (fs <= ft) { 2692 if (fs <= ft) {
3010 set_fpu_register_word(fd_reg, -1); 2693 set_fpu_register_word(fd_reg(), -1);
3011 } else { 2694 } else {
3012 set_fpu_register_word(fd_reg, 0); 2695 set_fpu_register_word(fd_reg(), 0);
3013 } 2696 }
3014 break; 2697 break;
3015 case CMP_ULE: 2698 case CMP_ULE:
3016 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { 2699 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
3017 set_fpu_register_word(fd_reg, -1); 2700 set_fpu_register_word(fd_reg(), -1);
3018 } else { 2701 } else {
3019 set_fpu_register_word(fd_reg, 0); 2702 set_fpu_register_word(fd_reg(), 0);
3020 } 2703 }
3021 break; 2704 break;
3022 case CMP_OR: 2705 case CMP_OR:
3023 if (!std::isnan(fs) && !std::isnan(ft)) { 2706 if (!std::isnan(fs) && !std::isnan(ft)) {
3024 set_fpu_register_word(fd_reg, -1); 2707 set_fpu_register_word(fd_reg(), -1);
3025 } else { 2708 } else {
3026 set_fpu_register_word(fd_reg, 0); 2709 set_fpu_register_word(fd_reg(), 0);
3027 } 2710 }
3028 break; 2711 break;
3029 case CMP_UNE: 2712 case CMP_UNE:
3030 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { 2713 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) {
3031 set_fpu_register_word(fd_reg, -1); 2714 set_fpu_register_word(fd_reg(), -1);
3032 } else { 2715 } else {
3033 set_fpu_register_word(fd_reg, 0); 2716 set_fpu_register_word(fd_reg(), 0);
3034 } 2717 }
3035 break; 2718 break;
3036 case CMP_NE: 2719 case CMP_NE:
3037 if (fs != ft) { 2720 if (fs != ft) {
3038 set_fpu_register_word(fd_reg, -1); 2721 set_fpu_register_word(fd_reg(), -1);
3039 } else { 2722 } else {
3040 set_fpu_register_word(fd_reg, 0); 2723 set_fpu_register_word(fd_reg(), 0);
3041 } 2724 }
3042 break; 2725 break;
3043 default: 2726 default:
3044 UNREACHABLE(); 2727 UNREACHABLE();
3045 } 2728 }
3046 } 2729 }
3047 2730
3048 2731
3049 void Simulator::DecodeTypeRegisterSRsType(Instruction* instr, 2732 void Simulator::DecodeTypeRegisterSRsType() {
3050 const int32_t& ft_reg,
3051 const int32_t& fs_reg,
3052 const int32_t& fd_reg) {
3053 float fs, ft, fd; 2733 float fs, ft, fd;
3054 fs = get_fpu_register_float(fs_reg); 2734 fs = get_fpu_register_float(fs_reg());
3055 ft = get_fpu_register_float(ft_reg); 2735 ft = get_fpu_register_float(ft_reg());
3056 fd = get_fpu_register_float(fd_reg); 2736 fd = get_fpu_register_float(fd_reg());
3057 int32_t ft_int = bit_cast<int32_t>(ft); 2737 int32_t ft_int = bit_cast<int32_t>(ft);
3058 int32_t fd_int = bit_cast<int32_t>(fd); 2738 int32_t fd_int = bit_cast<int32_t>(fd);
3059 uint32_t cc, fcsr_cc; 2739 uint32_t cc, fcsr_cc;
3060 cc = instr->FCccValue(); 2740 cc = get_instr()->FCccValue();
3061 fcsr_cc = get_fcsr_condition_bit(cc); 2741 fcsr_cc = get_fcsr_condition_bit(cc);
3062 switch (instr->FunctionFieldRaw()) { 2742 switch (get_instr()->FunctionFieldRaw()) {
3063 case RINT: { 2743 case RINT: {
3064 DCHECK(IsMipsArchVariant(kMips32r6)); 2744 DCHECK(IsMipsArchVariant(kMips32r6));
3065 float result, temp_result; 2745 float result, temp_result;
3066 double temp; 2746 double temp;
3067 float upper = std::ceil(fs); 2747 float upper = std::ceil(fs);
3068 float lower = std::floor(fs); 2748 float lower = std::floor(fs);
3069 switch (get_fcsr_rounding_mode()) { 2749 switch (get_fcsr_rounding_mode()) {
3070 case kRoundToNearest: 2750 case kRoundToNearest:
3071 if (upper - fs < fs - lower) { 2751 if (upper - fs < fs - lower) {
3072 result = upper; 2752 result = upper;
(...skipping 12 matching lines...) Expand all
3085 case kRoundToZero: 2765 case kRoundToZero:
3086 result = (fs > 0 ? lower : upper); 2766 result = (fs > 0 ? lower : upper);
3087 break; 2767 break;
3088 case kRoundToPlusInf: 2768 case kRoundToPlusInf:
3089 result = upper; 2769 result = upper;
3090 break; 2770 break;
3091 case kRoundToMinusInf: 2771 case kRoundToMinusInf:
3092 result = lower; 2772 result = lower;
3093 break; 2773 break;
3094 } 2774 }
3095 set_fpu_register_float(fd_reg, result); 2775 set_fpu_register_float(fd_reg(), result);
3096 if (result != fs) { 2776 if (result != fs) {
3097 set_fcsr_bit(kFCSRInexactFlagBit, true); 2777 set_fcsr_bit(kFCSRInexactFlagBit, true);
3098 } 2778 }
3099 break; 2779 break;
3100 } 2780 }
3101 case ADD_S: 2781 case ADD_S:
3102 set_fpu_register_float(fd_reg, fs + ft); 2782 set_fpu_register_float(fd_reg(), fs + ft);
3103 break; 2783 break;
3104 case SUB_S: 2784 case SUB_S:
3105 set_fpu_register_float(fd_reg, fs - ft); 2785 set_fpu_register_float(fd_reg(), fs - ft);
3106 break; 2786 break;
3107 case MUL_S: 2787 case MUL_S:
3108 set_fpu_register_float(fd_reg, fs * ft); 2788 set_fpu_register_float(fd_reg(), fs * ft);
3109 break; 2789 break;
3110 case DIV_S: 2790 case DIV_S:
3111 set_fpu_register_float(fd_reg, fs / ft); 2791 set_fpu_register_float(fd_reg(), fs / ft);
3112 break; 2792 break;
3113 case ABS_S: 2793 case ABS_S:
3114 set_fpu_register_float(fd_reg, fabs(fs)); 2794 set_fpu_register_float(fd_reg(), fabs(fs));
3115 break; 2795 break;
3116 case MOV_S: 2796 case MOV_S:
3117 set_fpu_register_float(fd_reg, fs); 2797 set_fpu_register_float(fd_reg(), fs);
3118 break; 2798 break;
3119 case NEG_S: 2799 case NEG_S:
3120 set_fpu_register_float(fd_reg, -fs); 2800 set_fpu_register_float(fd_reg(), -fs);
3121 break; 2801 break;
3122 case SQRT_S: 2802 case SQRT_S:
3123 set_fpu_register_float(fd_reg, fast_sqrt(fs)); 2803 set_fpu_register_float(fd_reg(), fast_sqrt(fs));
3124 break; 2804 break;
3125 case RSQRT_S: { 2805 case RSQRT_S: {
3126 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); 2806 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
3127 float result = 1.0 / fast_sqrt(fs); 2807 float result = 1.0 / fast_sqrt(fs);
3128 set_fpu_register_float(fd_reg, result); 2808 set_fpu_register_float(fd_reg(), result);
3129 break; 2809 break;
3130 } 2810 }
3131 case RECIP_S: { 2811 case RECIP_S: {
3132 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); 2812 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
3133 float result = 1.0 / fs; 2813 float result = 1.0 / fs;
3134 set_fpu_register_float(fd_reg, result); 2814 set_fpu_register_float(fd_reg(), result);
3135 break; 2815 break;
3136 } 2816 }
3137 case C_F_D: 2817 case C_F_D:
3138 set_fcsr_bit(fcsr_cc, false); 2818 set_fcsr_bit(fcsr_cc, false);
3139 break; 2819 break;
3140 case C_UN_D: 2820 case C_UN_D:
3141 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); 2821 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
3142 break; 2822 break;
3143 case C_EQ_D: 2823 case C_EQ_D:
3144 set_fcsr_bit(fcsr_cc, (fs == ft)); 2824 set_fcsr_bit(fcsr_cc, (fs == ft));
3145 break; 2825 break;
3146 case C_UEQ_D: 2826 case C_UEQ_D:
3147 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); 2827 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
3148 break; 2828 break;
3149 case C_OLT_D: 2829 case C_OLT_D:
3150 set_fcsr_bit(fcsr_cc, (fs < ft)); 2830 set_fcsr_bit(fcsr_cc, (fs < ft));
3151 break; 2831 break;
3152 case C_ULT_D: 2832 case C_ULT_D:
3153 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); 2833 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
3154 break; 2834 break;
3155 case C_OLE_D: 2835 case C_OLE_D:
3156 set_fcsr_bit(fcsr_cc, (fs <= ft)); 2836 set_fcsr_bit(fcsr_cc, (fs <= ft));
3157 break; 2837 break;
3158 case C_ULE_D: 2838 case C_ULE_D:
3159 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); 2839 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
3160 break; 2840 break;
3161 case CVT_D_S: 2841 case CVT_D_S:
3162 set_fpu_register_double(fd_reg, static_cast<double>(fs)); 2842 set_fpu_register_double(fd_reg(), static_cast<double>(fs));
3163 break; 2843 break;
3164 case SEL: 2844 case SEL:
3165 DCHECK(IsMipsArchVariant(kMips32r6)); 2845 DCHECK(IsMipsArchVariant(kMips32r6));
3166 set_fpu_register_float(fd_reg, (fd_int & 0x1) == 0 ? fs : ft); 2846 set_fpu_register_float(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft);
3167 break; 2847 break;
3168 case CLASS_S: { // Mips32r6 instruction 2848 case CLASS_S: { // Mips32r6 instruction
3169 // Convert float input to uint32_t for easier bit manipulation 2849 // Convert float input to uint32_t for easier bit manipulation
3170 float fs = get_fpu_register_float(fs_reg); 2850 float fs = get_fpu_register_float(fs_reg());
3171 uint32_t classed = bit_cast<uint32_t>(fs); 2851 uint32_t classed = bit_cast<uint32_t>(fs);
3172 2852
3173 // Extracting sign, exponent and mantissa from the input float 2853 // Extracting sign, exponent and mantissa from the input float
3174 uint32_t sign = (classed >> 31) & 1; 2854 uint32_t sign = (classed >> 31) & 1;
3175 uint32_t exponent = (classed >> 23) & 0x000000ff; 2855 uint32_t exponent = (classed >> 23) & 0x000000ff;
3176 uint32_t mantissa = classed & 0x007fffff; 2856 uint32_t mantissa = classed & 0x007fffff;
3177 uint32_t result; 2857 uint32_t result;
3178 float fResult; 2858 float fResult;
3179 2859
3180 // Setting flags if input float is negative infinity, 2860 // Setting flags if input float is negative infinity,
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
3220 } 2900 }
3221 2901
3222 // Calculating result according to description of CLASS.S instruction 2902 // Calculating result according to description of CLASS.S instruction
3223 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) | 2903 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) |
3224 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) | 2904 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) |
3225 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan; 2905 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan;
3226 2906
3227 DCHECK(result != 0); 2907 DCHECK(result != 0);
3228 2908
3229 fResult = bit_cast<float>(result); 2909 fResult = bit_cast<float>(result);
3230 set_fpu_register_float(fd_reg, fResult); 2910 set_fpu_register_float(fd_reg(), fResult);
3231 2911
3232 break; 2912 break;
3233 } 2913 }
3234 case SELEQZ_C: 2914 case SELEQZ_C:
3235 DCHECK(IsMipsArchVariant(kMips32r6)); 2915 DCHECK(IsMipsArchVariant(kMips32r6));
3236 set_fpu_register_float( 2916 set_fpu_register_float(fd_reg(), (ft_int & 0x1) == 0
3237 fd_reg, (ft_int & 0x1) == 0 ? get_fpu_register_float(fs_reg) : 0.0); 2917 ? get_fpu_register_float(fs_reg())
2918 : 0.0);
3238 break; 2919 break;
3239 case SELNEZ_C: 2920 case SELNEZ_C:
3240 DCHECK(IsMipsArchVariant(kMips32r6)); 2921 DCHECK(IsMipsArchVariant(kMips32r6));
3241 set_fpu_register_float( 2922 set_fpu_register_float(fd_reg(), (ft_int & 0x1) != 0
3242 fd_reg, (ft_int & 0x1) != 0 ? get_fpu_register_float(fs_reg) : 0.0); 2923 ? get_fpu_register_float(fs_reg())
2924 : 0.0);
3243 break; 2925 break;
3244 case MOVZ_C: { 2926 case MOVZ_C: {
3245 DCHECK(IsMipsArchVariant(kMips32r2)); 2927 DCHECK(IsMipsArchVariant(kMips32r2));
3246 int32_t rt_reg = instr->RtValue(); 2928 if (rt() == 0) {
3247 int32_t rt = get_register(rt_reg); 2929 set_fpu_register_float(fd_reg(), fs);
3248 if (rt == 0) {
3249 set_fpu_register_float(fd_reg, fs);
3250 } 2930 }
3251 break; 2931 break;
3252 } 2932 }
3253 case MOVN_C: { 2933 case MOVN_C: {
3254 DCHECK(IsMipsArchVariant(kMips32r2)); 2934 DCHECK(IsMipsArchVariant(kMips32r2));
3255 int32_t rt_reg = instr->RtValue(); 2935 if (rt() != 0) {
3256 int32_t rt = get_register(rt_reg); 2936 set_fpu_register_float(fd_reg(), fs);
3257 if (rt != 0) {
3258 set_fpu_register_float(fd_reg, fs);
3259 } 2937 }
3260 break; 2938 break;
3261 } 2939 }
3262 case MOVF: { 2940 case MOVF: {
3263 // Same function field for MOVT.D and MOVF.D 2941 // Same function field for MOVT.D and MOVF.D
3264 uint32_t ft_cc = (ft_reg >> 2) & 0x7; 2942 uint32_t ft_cc = (ft_reg() >> 2) & 0x7;
3265 ft_cc = get_fcsr_condition_bit(ft_cc); 2943 ft_cc = get_fcsr_condition_bit(ft_cc);
3266 2944
3267 if (instr->Bit(16)) { // Read Tf bit. 2945 if (get_instr()->Bit(16)) { // Read Tf bit.
3268 // MOVT.D 2946 // MOVT.D
3269 if (test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg, fs); 2947 if (test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs);
3270 } else { 2948 } else {
3271 // MOVF.D 2949 // MOVF.D
3272 if (!test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg, fs); 2950 if (!test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs);
3273 } 2951 }
3274 break; 2952 break;
3275 } 2953 }
3276 case TRUNC_W_S: { // Truncate single to word (round towards 0). 2954 case TRUNC_W_S: { // Truncate single to word (round towards 0).
3277 float rounded = trunc(fs); 2955 float rounded = trunc(fs);
3278 int32_t result = static_cast<int32_t>(rounded); 2956 int32_t result = static_cast<int32_t>(rounded);
3279 set_fpu_register_word(fd_reg, result); 2957 set_fpu_register_word(fd_reg(), result);
3280 if (set_fcsr_round_error(fs, rounded)) { 2958 if (set_fcsr_round_error(fs, rounded)) {
3281 set_fpu_register_word(fd_reg, kFPUInvalidResult); 2959 set_fpu_register_word(fd_reg(), kFPUInvalidResult);
3282 } 2960 }
3283 } break; 2961 } break;
3284 case TRUNC_L_S: { // Mips32r2 instruction. 2962 case TRUNC_L_S: { // Mips32r2 instruction.
3285 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); 2963 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
3286 float rounded = trunc(fs); 2964 float rounded = trunc(fs);
3287 int64_t i64 = static_cast<int64_t>(rounded); 2965 int64_t i64 = static_cast<int64_t>(rounded);
3288 if (IsFp64Mode()) { 2966 if (IsFp64Mode()) {
3289 set_fpu_register(fd_reg, i64); 2967 set_fpu_register(fd_reg(), i64);
3290 if (set_fcsr_round64_error(fs, rounded)) { 2968 if (set_fcsr_round64_error(fs, rounded)) {
3291 set_fpu_register(fd_reg, kFPU64InvalidResult); 2969 set_fpu_register(fd_reg(), kFPU64InvalidResult);
3292 } 2970 }
3293 } else { 2971 } else {
3294 UNSUPPORTED(); 2972 UNSUPPORTED();
3295 } 2973 }
3296 break; 2974 break;
3297 } 2975 }
3298 case FLOOR_W_S: // Round double to word towards negative infinity. 2976 case FLOOR_W_S: // Round double to word towards negative infinity.
3299 { 2977 {
3300 float rounded = std::floor(fs); 2978 float rounded = std::floor(fs);
3301 int32_t result = static_cast<int32_t>(rounded); 2979 int32_t result = static_cast<int32_t>(rounded);
3302 set_fpu_register_word(fd_reg, result); 2980 set_fpu_register_word(fd_reg(), result);
3303 if (set_fcsr_round_error(fs, rounded)) { 2981 if (set_fcsr_round_error(fs, rounded)) {
3304 set_fpu_register_word(fd_reg, kFPUInvalidResult); 2982 set_fpu_register_word(fd_reg(), kFPUInvalidResult);
3305 } 2983 }
3306 } break; 2984 } break;
3307 case FLOOR_L_S: { // Mips32r2 instruction. 2985 case FLOOR_L_S: { // Mips32r2 instruction.
3308 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); 2986 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
3309 float rounded = std::floor(fs); 2987 float rounded = std::floor(fs);
3310 int64_t i64 = static_cast<int64_t>(rounded); 2988 int64_t i64 = static_cast<int64_t>(rounded);
3311 if (IsFp64Mode()) { 2989 if (IsFp64Mode()) {
3312 set_fpu_register(fd_reg, i64); 2990 set_fpu_register(fd_reg(), i64);
3313 if (set_fcsr_round64_error(fs, rounded)) { 2991 if (set_fcsr_round64_error(fs, rounded)) {
3314 set_fpu_register(fd_reg, kFPU64InvalidResult); 2992 set_fpu_register(fd_reg(), kFPU64InvalidResult);
3315 } 2993 }
3316 } else { 2994 } else {
3317 UNSUPPORTED(); 2995 UNSUPPORTED();
3318 } 2996 }
3319 break; 2997 break;
3320 } 2998 }
3321 case ROUND_W_S: { 2999 case ROUND_W_S: {
3322 float rounded = std::floor(fs + 0.5); 3000 float rounded = std::floor(fs + 0.5);
3323 int32_t result = static_cast<int32_t>(rounded); 3001 int32_t result = static_cast<int32_t>(rounded);
3324 if ((result & 1) != 0 && result - fs == 0.5) { 3002 if ((result & 1) != 0 && result - fs == 0.5) {
3325 // If the number is halfway between two integers, 3003 // If the number is halfway between two integers,
3326 // round to the even one. 3004 // round to the even one.
3327 result--; 3005 result--;
3328 } 3006 }
3329 set_fpu_register_word(fd_reg, result); 3007 set_fpu_register_word(fd_reg(), result);
3330 if (set_fcsr_round_error(fs, rounded)) { 3008 if (set_fcsr_round_error(fs, rounded)) {
3331 set_fpu_register_word(fd_reg, kFPUInvalidResult); 3009 set_fpu_register_word(fd_reg(), kFPUInvalidResult);
3332 } 3010 }
3333 break; 3011 break;
3334 } 3012 }
3335 case ROUND_L_S: { // Mips32r2 instruction. 3013 case ROUND_L_S: { // Mips32r2 instruction.
3336 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); 3014 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
3337 float rounded = std::floor(fs + 0.5); 3015 float rounded = std::floor(fs + 0.5);
3338 int64_t result = static_cast<int64_t>(rounded); 3016 int64_t result = static_cast<int64_t>(rounded);
3339 if ((result & 1) != 0 && result - fs == 0.5) { 3017 if ((result & 1) != 0 && result - fs == 0.5) {
3340 // If the number is halfway between two integers, 3018 // If the number is halfway between two integers,
3341 // round to the even one. 3019 // round to the even one.
3342 result--; 3020 result--;
3343 } 3021 }
3344 int64_t i64 = static_cast<int64_t>(result); 3022 int64_t i64 = static_cast<int64_t>(result);
3345 if (IsFp64Mode()) { 3023 if (IsFp64Mode()) {
3346 set_fpu_register(fd_reg, i64); 3024 set_fpu_register(fd_reg(), i64);
3347 if (set_fcsr_round64_error(fs, rounded)) { 3025 if (set_fcsr_round64_error(fs, rounded)) {
3348 set_fpu_register(fd_reg, kFPU64InvalidResult); 3026 set_fpu_register(fd_reg(), kFPU64InvalidResult);
3349 } 3027 }
3350 } else { 3028 } else {
3351 UNSUPPORTED(); 3029 UNSUPPORTED();
3352 } 3030 }
3353 break; 3031 break;
3354 } 3032 }
3355 case CEIL_W_S: // Round double to word towards positive infinity. 3033 case CEIL_W_S: // Round double to word towards positive infinity.
3356 { 3034 {
3357 float rounded = std::ceil(fs); 3035 float rounded = std::ceil(fs);
3358 int32_t result = static_cast<int32_t>(rounded); 3036 int32_t result = static_cast<int32_t>(rounded);
3359 set_fpu_register_word(fd_reg, result); 3037 set_fpu_register_word(fd_reg(), result);
3360 if (set_fcsr_round_error(fs, rounded)) { 3038 if (set_fcsr_round_error(fs, rounded)) {
3361 set_fpu_register_word(fd_reg, kFPUInvalidResult); 3039 set_fpu_register_word(fd_reg(), kFPUInvalidResult);
3362 } 3040 }
3363 } break; 3041 } break;
3364 case CEIL_L_S: { // Mips32r2 instruction. 3042 case CEIL_L_S: { // Mips32r2 instruction.
3365 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); 3043 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
3366 float rounded = std::ceil(fs); 3044 float rounded = std::ceil(fs);
3367 int64_t i64 = static_cast<int64_t>(rounded); 3045 int64_t i64 = static_cast<int64_t>(rounded);
3368 if (IsFp64Mode()) { 3046 if (IsFp64Mode()) {
3369 set_fpu_register(fd_reg, i64); 3047 set_fpu_register(fd_reg(), i64);
3370 if (set_fcsr_round64_error(fs, rounded)) { 3048 if (set_fcsr_round64_error(fs, rounded)) {
3371 set_fpu_register(fd_reg, kFPU64InvalidResult); 3049 set_fpu_register(fd_reg(), kFPU64InvalidResult);
3372 } 3050 }
3373 } else { 3051 } else {
3374 UNSUPPORTED(); 3052 UNSUPPORTED();
3375 } 3053 }
3376 break; 3054 break;
3377 } 3055 }
3378 case MIN: 3056 case MIN:
3379 DCHECK(IsMipsArchVariant(kMips32r6)); 3057 DCHECK(IsMipsArchVariant(kMips32r6));
3380 fs = get_fpu_register_float(fs_reg); 3058 fs = get_fpu_register_float(fs_reg());
3381 if (std::isnan(fs) && std::isnan(ft)) { 3059 if (std::isnan(fs) && std::isnan(ft)) {
3382 set_fpu_register_float(fd_reg, fs); 3060 set_fpu_register_float(fd_reg(), fs);
3383 } else if (std::isnan(fs) && !std::isnan(ft)) { 3061 } else if (std::isnan(fs) && !std::isnan(ft)) {
3384 set_fpu_register_float(fd_reg, ft); 3062 set_fpu_register_float(fd_reg(), ft);
3385 } else if (!std::isnan(fs) && std::isnan(ft)) { 3063 } else if (!std::isnan(fs) && std::isnan(ft)) {
3386 set_fpu_register_float(fd_reg, fs); 3064 set_fpu_register_float(fd_reg(), fs);
3387 } else { 3065 } else {
3388 set_fpu_register_float(fd_reg, (fs >= ft) ? ft : fs); 3066 set_fpu_register_float(fd_reg(), (fs >= ft) ? ft : fs);
3389 } 3067 }
3390 break; 3068 break;
3391 case MAX: 3069 case MAX:
3392 DCHECK(IsMipsArchVariant(kMips32r6)); 3070 DCHECK(IsMipsArchVariant(kMips32r6));
3393 fs = get_fpu_register_float(fs_reg); 3071 fs = get_fpu_register_float(fs_reg());
3394 if (std::isnan(fs) && std::isnan(ft)) { 3072 if (std::isnan(fs) && std::isnan(ft)) {
3395 set_fpu_register_float(fd_reg, fs); 3073 set_fpu_register_float(fd_reg(), fs);
3396 } else if (std::isnan(fs) && !std::isnan(ft)) { 3074 } else if (std::isnan(fs) && !std::isnan(ft)) {
3397 set_fpu_register_float(fd_reg, ft); 3075 set_fpu_register_float(fd_reg(), ft);
3398 } else if (!std::isnan(fs) && std::isnan(ft)) { 3076 } else if (!std::isnan(fs) && std::isnan(ft)) {
3399 set_fpu_register_float(fd_reg, fs); 3077 set_fpu_register_float(fd_reg(), fs);
3400 } else { 3078 } else {
3401 set_fpu_register_float(fd_reg, (fs <= ft) ? ft : fs); 3079 set_fpu_register_float(fd_reg(), (fs <= ft) ? ft : fs);
3402 } 3080 }
3403 break; 3081 break;
3404 case MINA: 3082 case MINA:
3405 DCHECK(IsMipsArchVariant(kMips32r6)); 3083 DCHECK(IsMipsArchVariant(kMips32r6));
3406 fs = get_fpu_register_float(fs_reg); 3084 fs = get_fpu_register_float(fs_reg());
3407 if (std::isnan(fs) && std::isnan(ft)) { 3085 if (std::isnan(fs) && std::isnan(ft)) {
3408 set_fpu_register_float(fd_reg, fs); 3086 set_fpu_register_float(fd_reg(), fs);
3409 } else if (std::isnan(fs) && !std::isnan(ft)) { 3087 } else if (std::isnan(fs) && !std::isnan(ft)) {
3410 set_fpu_register_float(fd_reg, ft); 3088 set_fpu_register_float(fd_reg(), ft);
3411 } else if (!std::isnan(fs) && std::isnan(ft)) { 3089 } else if (!std::isnan(fs) && std::isnan(ft)) {
3412 set_fpu_register_float(fd_reg, fs); 3090 set_fpu_register_float(fd_reg(), fs);
3413 } else { 3091 } else {
3414 float result; 3092 float result;
3415 if (fabs(fs) > fabs(ft)) { 3093 if (fabs(fs) > fabs(ft)) {
3416 result = ft; 3094 result = ft;
3417 } else if (fabs(fs) < fabs(ft)) { 3095 } else if (fabs(fs) < fabs(ft)) {
3418 result = fs; 3096 result = fs;
3419 } else { 3097 } else {
3420 result = (fs > ft ? fs : ft); 3098 result = (fs > ft ? fs : ft);
3421 } 3099 }
3422 set_fpu_register_float(fd_reg, result); 3100 set_fpu_register_float(fd_reg(), result);
3423 } 3101 }
3424 break; 3102 break;
3425 case MAXA: 3103 case MAXA:
3426 DCHECK(IsMipsArchVariant(kMips32r6)); 3104 DCHECK(IsMipsArchVariant(kMips32r6));
3427 fs = get_fpu_register_float(fs_reg); 3105 fs = get_fpu_register_float(fs_reg());
3428 if (std::isnan(fs) && std::isnan(ft)) { 3106 if (std::isnan(fs) && std::isnan(ft)) {
3429 set_fpu_register_float(fd_reg, fs); 3107 set_fpu_register_float(fd_reg(), fs);
3430 } else if (std::isnan(fs) && !std::isnan(ft)) { 3108 } else if (std::isnan(fs) && !std::isnan(ft)) {
3431 set_fpu_register_float(fd_reg, ft); 3109 set_fpu_register_float(fd_reg(), ft);
3432 } else if (!std::isnan(fs) && std::isnan(ft)) { 3110 } else if (!std::isnan(fs) && std::isnan(ft)) {
3433 set_fpu_register_float(fd_reg, fs); 3111 set_fpu_register_float(fd_reg(), fs);
3434 } else { 3112 } else {
3435 float result; 3113 float result;
3436 if (fabs(fs) < fabs(ft)) { 3114 if (fabs(fs) < fabs(ft)) {
3437 result = ft; 3115 result = ft;
3438 } else if (fabs(fs) > fabs(ft)) { 3116 } else if (fabs(fs) > fabs(ft)) {
3439 result = fs; 3117 result = fs;
3440 } else { 3118 } else {
3441 result = (fs > ft ? fs : ft); 3119 result = (fs > ft ? fs : ft);
3442 } 3120 }
3443 set_fpu_register_float(fd_reg, result); 3121 set_fpu_register_float(fd_reg(), result);
3444 } 3122 }
3445 break; 3123 break;
3446 case CVT_L_S: { 3124 case CVT_L_S: {
3447 if (IsFp64Mode()) { 3125 if (IsFp64Mode()) {
3448 int64_t result; 3126 int64_t result;
3449 float rounded; 3127 float rounded;
3450 round64_according_to_fcsr(fs, rounded, result, fs); 3128 round64_according_to_fcsr(fs, rounded, result, fs);
3451 set_fpu_register(fd_reg, result); 3129 set_fpu_register(fd_reg(), result);
3452 if (set_fcsr_round64_error(fs, rounded)) { 3130 if (set_fcsr_round64_error(fs, rounded)) {
3453 set_fpu_register(fd_reg, kFPU64InvalidResult); 3131 set_fpu_register(fd_reg(), kFPU64InvalidResult);
3454 } 3132 }
3455 } else { 3133 } else {
3456 UNSUPPORTED(); 3134 UNSUPPORTED();
3457 } 3135 }
3458 break; 3136 break;
3459 } 3137 }
3460 case CVT_W_S: { 3138 case CVT_W_S: {
3461 float rounded; 3139 float rounded;
3462 int32_t result; 3140 int32_t result;
3463 round_according_to_fcsr(fs, rounded, result, fs); 3141 round_according_to_fcsr(fs, rounded, result, fs);
3464 set_fpu_register_word(fd_reg, result); 3142 set_fpu_register_word(fd_reg(), result);
3465 if (set_fcsr_round_error(fs, rounded)) { 3143 if (set_fcsr_round_error(fs, rounded)) {
3466 set_fpu_register_word(fd_reg, kFPUInvalidResult); 3144 set_fpu_register_word(fd_reg(), kFPUInvalidResult);
3467 } 3145 }
3468 break; 3146 break;
3469 } 3147 }
3470 default: 3148 default:
3471 // CVT_W_S CVT_L_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S 3149 // CVT_W_S CVT_L_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S
3472 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented. 3150 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented.
3473 UNREACHABLE(); 3151 UNREACHABLE();
3474 } 3152 }
3475 } 3153 }
3476 3154
3477 3155
3478 void Simulator::DecodeTypeRegisterLRsType(Instruction* instr, 3156 void Simulator::DecodeTypeRegisterLRsType() {
3479 const int32_t& ft_reg, 3157 double fs = get_fpu_register_double(fs_reg());
3480 const int32_t& fs_reg, 3158 double ft = get_fpu_register_double(ft_reg());
3481 const int32_t& fd_reg) { 3159 switch (get_instr()->FunctionFieldRaw()) {
3482 double fs = get_fpu_register_double(fs_reg);
3483 double ft = get_fpu_register_double(ft_reg);
3484 switch (instr->FunctionFieldRaw()) {
3485 case CVT_D_L: // Mips32r2 instruction. 3160 case CVT_D_L: // Mips32r2 instruction.
3486 // Watch the signs here, we want 2 32-bit vals 3161 // Watch the signs here, we want 2 32-bit vals
3487 // to make a sign-64. 3162 // to make a sign-64.
3488 int64_t i64; 3163 int64_t i64;
3489 if (IsFp64Mode()) { 3164 if (IsFp64Mode()) {
3490 i64 = get_fpu_register(fs_reg); 3165 i64 = get_fpu_register(fs_reg());
3491 } else { 3166 } else {
3492 i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg)); 3167 i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg()));
3493 i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg + 1)) << 32; 3168 i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg() + 1)) << 32;
3494 } 3169 }
3495 set_fpu_register_double(fd_reg, static_cast<double>(i64)); 3170 set_fpu_register_double(fd_reg(), static_cast<double>(i64));
3496 break; 3171 break;
3497 case CVT_S_L: 3172 case CVT_S_L:
3498 if (IsFp64Mode()) { 3173 if (IsFp64Mode()) {
3499 i64 = get_fpu_register(fs_reg); 3174 i64 = get_fpu_register(fs_reg());
3500 } else { 3175 } else {
3501 i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg)); 3176 i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg()));
3502 i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg + 1)) << 32; 3177 i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg() + 1)) << 32;
3503 } 3178 }
3504 set_fpu_register_float(fd_reg, static_cast<float>(i64)); 3179 set_fpu_register_float(fd_reg(), static_cast<float>(i64));
3505 break; 3180 break;
3506 case CMP_AF: // Mips64r6 CMP.D instructions. 3181 case CMP_AF: // Mips64r6 CMP.D instructions.
3507 set_fpu_register(fd_reg, 0); 3182 set_fpu_register(fd_reg(), 0);
3508 break; 3183 break;
3509 case CMP_UN: 3184 case CMP_UN:
3510 if (std::isnan(fs) || std::isnan(ft)) { 3185 if (std::isnan(fs) || std::isnan(ft)) {
3511 set_fpu_register(fd_reg, -1); 3186 set_fpu_register(fd_reg(), -1);
3512 } else { 3187 } else {
3513 set_fpu_register(fd_reg, 0); 3188 set_fpu_register(fd_reg(), 0);
3514 } 3189 }
3515 break; 3190 break;
3516 case CMP_EQ: 3191 case CMP_EQ:
3517 if (fs == ft) { 3192 if (fs == ft) {
3518 set_fpu_register(fd_reg, -1); 3193 set_fpu_register(fd_reg(), -1);
3519 } else { 3194 } else {
3520 set_fpu_register(fd_reg, 0); 3195 set_fpu_register(fd_reg(), 0);
3521 } 3196 }
3522 break; 3197 break;
3523 case CMP_UEQ: 3198 case CMP_UEQ:
3524 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { 3199 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
3525 set_fpu_register(fd_reg, -1); 3200 set_fpu_register(fd_reg(), -1);
3526 } else { 3201 } else {
3527 set_fpu_register(fd_reg, 0); 3202 set_fpu_register(fd_reg(), 0);
3528 } 3203 }
3529 break; 3204 break;
3530 case CMP_LT: 3205 case CMP_LT:
3531 if (fs < ft) { 3206 if (fs < ft) {
3532 set_fpu_register(fd_reg, -1); 3207 set_fpu_register(fd_reg(), -1);
3533 } else { 3208 } else {
3534 set_fpu_register(fd_reg, 0); 3209 set_fpu_register(fd_reg(), 0);
3535 } 3210 }
3536 break; 3211 break;
3537 case CMP_ULT: 3212 case CMP_ULT:
3538 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { 3213 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
3539 set_fpu_register(fd_reg, -1); 3214 set_fpu_register(fd_reg(), -1);
3540 } else { 3215 } else {
3541 set_fpu_register(fd_reg, 0); 3216 set_fpu_register(fd_reg(), 0);
3542 } 3217 }
3543 break; 3218 break;
3544 case CMP_LE: 3219 case CMP_LE:
3545 if (fs <= ft) { 3220 if (fs <= ft) {
3546 set_fpu_register(fd_reg, -1); 3221 set_fpu_register(fd_reg(), -1);
3547 } else { 3222 } else {
3548 set_fpu_register(fd_reg, 0); 3223 set_fpu_register(fd_reg(), 0);
3549 } 3224 }
3550 break; 3225 break;
3551 case CMP_ULE: 3226 case CMP_ULE:
3552 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { 3227 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
3553 set_fpu_register(fd_reg, -1); 3228 set_fpu_register(fd_reg(), -1);
3554 } else { 3229 } else {
3555 set_fpu_register(fd_reg, 0); 3230 set_fpu_register(fd_reg(), 0);
3556 } 3231 }
3557 break; 3232 break;
3558 case CMP_OR: 3233 case CMP_OR:
3559 if (!std::isnan(fs) && !std::isnan(ft)) { 3234 if (!std::isnan(fs) && !std::isnan(ft)) {
3560 set_fpu_register(fd_reg, -1); 3235 set_fpu_register(fd_reg(), -1);
3561 } else { 3236 } else {
3562 set_fpu_register(fd_reg, 0); 3237 set_fpu_register(fd_reg(), 0);
3563 } 3238 }
3564 break; 3239 break;
3565 case CMP_UNE: 3240 case CMP_UNE:
3566 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { 3241 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) {
3567 set_fpu_register(fd_reg, -1); 3242 set_fpu_register(fd_reg(), -1);
3568 } else { 3243 } else {
3569 set_fpu_register(fd_reg, 0); 3244 set_fpu_register(fd_reg(), 0);
3570 } 3245 }
3571 break; 3246 break;
3572 case CMP_NE: 3247 case CMP_NE:
3573 if (fs != ft && (!std::isnan(fs) && !std::isnan(ft))) { 3248 if (fs != ft && (!std::isnan(fs) && !std::isnan(ft))) {
3574 set_fpu_register(fd_reg, -1); 3249 set_fpu_register(fd_reg(), -1);
3575 } else { 3250 } else {
3576 set_fpu_register(fd_reg, 0); 3251 set_fpu_register(fd_reg(), 0);
3577 } 3252 }
3578 break; 3253 break;
3579 default: 3254 default:
3580 UNREACHABLE(); 3255 UNREACHABLE();
3581 } 3256 }
3582 } 3257 }
3583 3258
3584 3259
3585 void Simulator::DecodeTypeRegisterCOP1( 3260 void Simulator::DecodeTypeRegisterCOP1() {
3586 Instruction* instr, const int32_t& rs_reg, const int32_t& rs, 3261 switch (get_instr()->RsFieldRaw()) {
3587 const uint32_t& rs_u, const int32_t& rt_reg, const int32_t& rt,
3588 const uint32_t& rt_u, const int32_t& rd_reg, const int32_t& fr_reg,
3589 const int32_t& fs_reg, const int32_t& ft_reg, const int32_t& fd_reg,
3590 int64_t& i64hilo, uint64_t& u64hilo, int32_t& alu_out, bool& do_interrupt,
3591 int32_t& current_pc, int32_t& next_pc, int32_t& return_addr_reg) {
3592 switch (instr->RsFieldRaw()) {
3593 case CFC1: 3262 case CFC1:
3594 set_register(rt_reg, alu_out); 3263 // At the moment only FCSR is supported.
3264 DCHECK(fs_reg() == kFCSRRegister);
3265 set_register(rt_reg(), FCSR_);
3595 break; 3266 break;
3596 case MFC1: 3267 case MFC1:
3597 set_register(rt_reg, alu_out); 3268 set_register(rt_reg(), get_fpu_register_word(fs_reg()));
3598 break; 3269 break;
3599 case MFHC1: 3270 case MFHC1:
3600 set_register(rt_reg, alu_out); 3271 set_register(rt_reg(), get_fpu_register_hi_word(fs_reg()));
3601 break; 3272 break;
3602 case CTC1: 3273 case CTC1:
3603 // At the moment only FCSR is supported. 3274 // At the moment only FCSR is supported.
3604 DCHECK(fs_reg == kFCSRRegister); 3275 DCHECK(fs_reg() == kFCSRRegister);
3605 FCSR_ = registers_[rt_reg]; 3276 FCSR_ = registers_[rt_reg()];
3606 break; 3277 break;
3607 case MTC1: 3278 case MTC1:
3608 // Hardware writes upper 32-bits to zero on mtc1. 3279 // Hardware writes upper 32-bits to zero on mtc1.
3609 set_fpu_register_hi_word(fs_reg, 0); 3280 set_fpu_register_hi_word(fs_reg(), 0);
3610 set_fpu_register_word(fs_reg, registers_[rt_reg]); 3281 set_fpu_register_word(fs_reg(), registers_[rt_reg()]);
3611 break; 3282 break;
3612 case MTHC1: 3283 case MTHC1:
3613 set_fpu_register_hi_word(fs_reg, registers_[rt_reg]); 3284 set_fpu_register_hi_word(fs_reg(), registers_[rt_reg()]);
3614 break; 3285 break;
3615 case S: { 3286 case S: {
3616 DecodeTypeRegisterSRsType(instr, ft_reg, fs_reg, fd_reg); 3287 DecodeTypeRegisterSRsType();
3617 break; 3288 break;
3618 } 3289 }
3619 case D: 3290 case D:
3620 DecodeTypeRegisterDRsType(instr, fr_reg, fs_reg, ft_reg, fd_reg); 3291 DecodeTypeRegisterDRsType();
3621 break; 3292 break;
3622 case W: 3293 case W:
3623 DecodeTypeRegisterWRsType(instr, alu_out, fd_reg, fs_reg, ft_reg); 3294 DecodeTypeRegisterWRsType();
3624 break; 3295 break;
3625 case L: 3296 case L:
3626 DecodeTypeRegisterLRsType(instr, ft_reg, fs_reg, fd_reg); 3297 DecodeTypeRegisterLRsType();
3627 break; 3298 break;
3299 case PS:
3300 // Not implemented.
3301 UNREACHABLE();
3628 default: 3302 default:
3629 UNREACHABLE(); 3303 UNREACHABLE();
3630 } 3304 }
3631 } 3305 }
3632 3306
3633 3307
3634 void Simulator::DecodeTypeRegisterCOP1X(Instruction* instr, 3308 void Simulator::DecodeTypeRegisterCOP1X() {
3635 const int32_t& fr_reg, 3309 switch (get_instr()->FunctionFieldRaw()) {
3636 const int32_t& fs_reg,
3637 const int32_t& ft_reg,
3638 const int32_t& fd_reg) {
3639 switch (instr->FunctionFieldRaw()) {
3640 case MADD_D: 3310 case MADD_D:
3641 double fr, ft, fs; 3311 double fr, ft, fs;
3642 fr = get_fpu_register_double(fr_reg); 3312 fr = get_fpu_register_double(fr_reg());
3643 fs = get_fpu_register_double(fs_reg); 3313 fs = get_fpu_register_double(fs_reg());
3644 ft = get_fpu_register_double(ft_reg); 3314 ft = get_fpu_register_double(ft_reg());
3645 set_fpu_register_double(fd_reg, fs * ft + fr); 3315 set_fpu_register_double(fd_reg(), fs * ft + fr);
3646 break; 3316 break;
3647 default: 3317 default:
3648 UNREACHABLE(); 3318 UNREACHABLE();
3649 } 3319 }
3650 } 3320 }
3651 3321
3652 3322
3653 void Simulator::DecodeTypeRegisterSPECIAL( 3323 void Simulator::DecodeTypeRegisterSPECIAL() {
3654 Instruction* instr, const int32_t& rs_reg, const int32_t& rs, 3324 int64_t alu_out = 0x12345678;
3655 const uint32_t& rs_u, const int32_t& rt_reg, const int32_t& rt, 3325 int64_t i64hilo = 0;
3656 const uint32_t& rt_u, const int32_t& rd_reg, const int32_t& fr_reg, 3326 uint64_t u64hilo = 0;
3657 const int32_t& fs_reg, const int32_t& ft_reg, const int32_t& fd_reg, 3327 bool do_interrupt = false;
3658 int64_t& i64hilo, uint64_t& u64hilo, int32_t& alu_out, bool& do_interrupt, 3328
3659 int32_t& current_pc, int32_t& next_pc, int32_t& return_addr_reg) { 3329 switch (get_instr()->FunctionFieldRaw()) {
3660 switch (instr->FunctionFieldRaw()) {
3661 case SELEQZ_S: 3330 case SELEQZ_S:
3662 DCHECK(IsMipsArchVariant(kMips32r6)); 3331 DCHECK(IsMipsArchVariant(kMips32r6));
3663 set_register(rd_reg, rt == 0 ? rs : 0); 3332 set_register(rd_reg(), rt() == 0 ? rs() : 0);
3664 break; 3333 break;
3665 case SELNEZ_S: 3334 case SELNEZ_S:
3666 DCHECK(IsMipsArchVariant(kMips32r6)); 3335 DCHECK(IsMipsArchVariant(kMips32r6));
3667 set_register(rd_reg, rt != 0 ? rs : 0); 3336 set_register(rd_reg(), rt() != 0 ? rs() : 0);
3668 break; 3337 break;
3669 case JR: { 3338 case JR: {
3670 Instruction* branch_delay_instr = reinterpret_cast<Instruction*>( 3339 int32_t next_pc = rs();
3671 current_pc+Instruction::kInstrSize); 3340 int32_t current_pc = get_pc();
3672 BranchDelayInstructionDecode(branch_delay_instr); 3341 Instruction* branch_delay_instr =
3673 set_pc(next_pc); 3342 reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize);
3674 pc_modified_ = true; 3343 BranchDelayInstructionDecode(branch_delay_instr);
3675 break; 3344 set_pc(next_pc);
3676 } 3345 pc_modified_ = true;
3677 case JALR: { 3346 break;
3678 Instruction* branch_delay_instr = reinterpret_cast<Instruction*>( 3347 }
3679 current_pc+Instruction::kInstrSize); 3348 case JALR: {
3680 BranchDelayInstructionDecode(branch_delay_instr); 3349 int32_t next_pc = rs();
3681 set_register(return_addr_reg, 3350 int32_t return_addr_reg = rd_reg();
3682 current_pc + 2 * Instruction::kInstrSize); 3351 int32_t current_pc = get_pc();
3683 set_pc(next_pc); 3352 Instruction* branch_delay_instr =
3684 pc_modified_ = true; 3353 reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize);
3685 break; 3354 BranchDelayInstructionDecode(branch_delay_instr);
3686 } 3355 set_register(return_addr_reg, current_pc + 2 * Instruction::kInstrSize);
3687 // Instructions using HI and LO registers. 3356 set_pc(next_pc);
3688 case MULT: 3357 pc_modified_ = true;
3689 if (!IsMipsArchVariant(kMips32r6)) { 3358 break;
3690 set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff)); 3359 }
3691 set_register(HI, static_cast<int32_t>(i64hilo >> 32)); 3360 case SLL:
3692 } else { 3361 alu_out = rt() << sa();
3693 switch (instr->SaValue()) { 3362 set_result(rd_reg(), static_cast<int32_t>(alu_out));
3694 case MUL_OP: 3363 break;
3695 set_register(rd_reg, 3364 case SRL:
3696 static_cast<int32_t>(i64hilo & 0xffffffff)); 3365 if (rs_reg() == 0) {
3697 break; 3366 // Regular logical right shift of a word by a fixed number of
3698 case MUH_OP: 3367 // bits instruction. RS field is always equal to 0.
3699 set_register(rd_reg, static_cast<int32_t>(i64hilo >> 32)); 3368 alu_out = rt_u() >> sa();
3700 break; 3369 } else {
3701 default: 3370 // Logical right-rotate of a word by a fixed number of bits. This
3702 UNIMPLEMENTED_MIPS(); 3371 // is special case of SRL instruction, added in MIPS32 Release 2.
3703 break; 3372 // RS field is equal to 00001.
3373 alu_out = base::bits::RotateRight32(rt_u(), sa());
3374 }
3375 set_result(rd_reg(), static_cast<int32_t>(alu_out));
3376 break;
3377 case SRA:
3378 alu_out = rt() >> sa();
3379 set_result(rd_reg(), static_cast<int32_t>(alu_out));
3380 break;
3381 case SLLV:
3382 alu_out = rt() << rs();
3383 set_result(rd_reg(), static_cast<int32_t>(alu_out));
3384 break;
3385 case SRLV:
3386 if (sa() == 0) {
3387 // Regular logical right-shift of a word by a variable number of
3388 // bits instruction. SA field is always equal to 0.
3389 alu_out = rt_u() >> rs();
3390 } else {
3391 // Logical right-rotate of a word by a variable number of bits.
3392 // This is special case od SRLV instruction, added in MIPS32
3393 // Release 2. SA field is equal to 00001.
3394 alu_out = base::bits::RotateRight32(rt_u(), rs_u());
3395 }
3396 set_result(rd_reg(), static_cast<int32_t>(alu_out));
3397 break;
3398 case SRAV:
3399 alu_out = rt() >> rs();
3400 set_result(rd_reg(), static_cast<int32_t>(alu_out));
3401 break;
3402 case MFHI: // MFHI == CLZ on R6.
3403 if (!IsMipsArchVariant(kMips32r6)) {
3404 DCHECK(sa() == 0);
3405 alu_out = get_register(HI);
3406 } else {
3407 // MIPS spec: If no bits were set in GPR rs, the result written to
3408 // GPR rd is 32.
3409 DCHECK(sa() == 1);
3410 alu_out = base::bits::CountLeadingZeros32(rs_u());
3411 }
3412 set_result(rd_reg(), static_cast<int32_t>(alu_out));
3413 break;
3414 case MFLO:
3415 alu_out = get_register(LO);
3416 set_result(rd_reg(), static_cast<int32_t>(alu_out));
3417 break;
3418 // Instructions using HI and LO registers.
3419 case MULT:
3420 i64hilo = static_cast<int64_t>(rs()) * static_cast<int64_t>(rt());
3421 if (!IsMipsArchVariant(kMips32r6)) {
3422 set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
3423 set_register(HI, static_cast<int32_t>(i64hilo >> 32));
3424 } else {
3425 switch (sa()) {
3426 case MUL_OP:
3427 set_register(rd_reg(), static_cast<int32_t>(i64hilo & 0xffffffff));
3428 break;
3429 case MUH_OP:
3430 set_register(rd_reg(), static_cast<int32_t>(i64hilo >> 32));
3431 break;
3432 default:
3433 UNIMPLEMENTED_MIPS();
3434 break;
3435 }
3436 }
3437 break;
3438 case MULTU:
3439 u64hilo = static_cast<uint64_t>(rs_u()) * static_cast<uint64_t>(rt_u());
3440 if (!IsMipsArchVariant(kMips32r6)) {
3441 set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
3442 set_register(HI, static_cast<int32_t>(u64hilo >> 32));
3443 } else {
3444 switch (sa()) {
3445 case MUL_OP:
3446 set_register(rd_reg(), static_cast<int32_t>(u64hilo & 0xffffffff));
3447 break;
3448 case MUH_OP:
3449 set_register(rd_reg(), static_cast<int32_t>(u64hilo >> 32));
3450 break;
3451 default:
3452 UNIMPLEMENTED_MIPS();
3453 break;
3454 }
3455 }
3456 break;
3457 case DIV:
3458 if (IsMipsArchVariant(kMips32r6)) {
3459 switch (get_instr()->SaValue()) {
3460 case DIV_OP:
3461 if (rs() == INT_MIN && rt() == -1) {
3462 set_register(rd_reg(), INT_MIN);
3463 } else if (rt() != 0) {
3464 set_register(rd_reg(), rs() / rt());
3704 } 3465 }
3705 } 3466 break;
3706 break; 3467 case MOD_OP:
3707 case MULTU: 3468 if (rs() == INT_MIN && rt() == -1) {
3708 if (!IsMipsArchVariant(kMips32r6)) { 3469 set_register(rd_reg(), 0);
3709 set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff)); 3470 } else if (rt() != 0) {
3710 set_register(HI, static_cast<int32_t>(u64hilo >> 32)); 3471 set_register(rd_reg(), rs() % rt());
3711 } else {
3712 switch (instr->SaValue()) {
3713 case MUL_OP:
3714 set_register(rd_reg,
3715 static_cast<int32_t>(u64hilo & 0xffffffff));
3716 break;
3717 case MUH_OP:
3718 set_register(rd_reg, static_cast<int32_t>(u64hilo >> 32));
3719 break;
3720 default:
3721 UNIMPLEMENTED_MIPS();
3722 break;
3723 } 3472 }
3724 } 3473 break;
3725 break; 3474 default:
3726 case DIV: 3475 UNIMPLEMENTED_MIPS();
3727 if (IsMipsArchVariant(kMips32r6)) { 3476 break;
3728 switch (instr->SaValue()) { 3477 }
3729 case DIV_OP: 3478 } else {
3730 if (rs == INT_MIN && rt == -1) { 3479 // Divide by zero and overflow was not checked in the
3731 set_register(rd_reg, INT_MIN); 3480 // configuration step - div and divu do not raise exceptions. On
3732 } else if (rt != 0) { 3481 // division by 0 the result will be UNPREDICTABLE. On overflow
3733 set_register(rd_reg, rs / rt); 3482 // (INT_MIN/-1), return INT_MIN which is what the hardware does.
3734 } 3483 if (rs() == INT_MIN && rt() == -1) {
3735 break; 3484 set_register(LO, INT_MIN);
3736 case MOD_OP: 3485 set_register(HI, 0);
3737 if (rs == INT_MIN && rt == -1) { 3486 } else if (rt() != 0) {
3738 set_register(rd_reg, 0); 3487 set_register(LO, rs() / rt());
3739 } else if (rt != 0) { 3488 set_register(HI, rs() % rt());
3740 set_register(rd_reg, rs % rt); 3489 }
3741 } 3490 }
3742 break; 3491 break;
3743 default: 3492 case DIVU:
3744 UNIMPLEMENTED_MIPS(); 3493 if (IsMipsArchVariant(kMips32r6)) {
3745 break; 3494 switch (get_instr()->SaValue()) {
3495 case DIV_OP:
3496 if (rt_u() != 0) {
3497 set_register(rd_reg(), rs_u() / rt_u());
3746 } 3498 }
3747 } else { 3499 break;
3748 // Divide by zero and overflow was not checked in the 3500 case MOD_OP:
3749 // configuration step - div and divu do not raise exceptions. On 3501 if (rt_u() != 0) {
3750 // division by 0 the result will be UNPREDICTABLE. On overflow 3502 set_register(rd_reg(), rs_u() % rt_u());
3751 // (INT_MIN/-1), return INT_MIN which is what the hardware does.
3752 if (rs == INT_MIN && rt == -1) {
3753 set_register(LO, INT_MIN);
3754 set_register(HI, 0);
3755 } else if (rt != 0) {
3756 set_register(LO, rs / rt);
3757 set_register(HI, rs % rt);
3758 } 3503 }
3759 } 3504 break;
3760 break; 3505 default:
3761 case DIVU: 3506 UNIMPLEMENTED_MIPS();
3762 if (IsMipsArchVariant(kMips32r6)) { 3507 break;
3763 switch (instr->SaValue()) { 3508 }
3764 case DIV_OP: 3509 } else {
3765 if (rt_u != 0) { 3510 if (rt_u() != 0) {
3766 set_register(rd_reg, rs_u / rt_u); 3511 set_register(LO, rs_u() / rt_u());
3767 } 3512 set_register(HI, rs_u() % rt_u());
3768 break; 3513 }
3769 case MOD_OP: 3514 }
3770 if (rt_u != 0) { 3515 break;
3771 set_register(rd_reg, rs_u % rt_u); 3516 case ADD:
3772 } 3517 if (HaveSameSign(rs(), rt())) {
3773 break; 3518 if (rs() > 0) {
3774 default: 3519 if (rs() <= (Registers::kMaxValue - rt())) {
3775 UNIMPLEMENTED_MIPS(); 3520 SignalException(kIntegerOverflow);
3776 break; 3521 }
3777 } 3522 } else if (rs() < 0) {
3778 } else { 3523 if (rs() >= (Registers::kMinValue - rt())) {
3779 if (rt_u != 0) { 3524 SignalException(kIntegerUnderflow);
3780 set_register(LO, rs_u / rt_u); 3525 }
3781 set_register(HI, rs_u % rt_u); 3526 }
3782 } 3527 }
3783 } 3528 set_result(rd_reg(), rs() + rt());
3784 break; 3529 break;
3785 // Break and trap instructions. 3530 case ADDU:
3786 case BREAK: 3531 set_result(rd_reg(), rs() + rt());
3787 case TGE: 3532 break;
3788 case TGEU: 3533 case SUB:
3789 case TLT: 3534 if (!HaveSameSign(rs(), rt())) {
3790 case TLTU: 3535 if (rs() > 0) {
3791 case TEQ: 3536 if (rs() <= (Registers::kMaxValue + rt())) {
3792 case TNE: 3537 SignalException(kIntegerOverflow);
3793 if (do_interrupt) { 3538 }
3794 SoftwareInterrupt(instr); 3539 } else if (rs() < 0) {
3795 } 3540 if (rs() >= (Registers::kMinValue + rt())) {
3796 break; 3541 SignalException(kIntegerUnderflow);
3797 // Conditional moves. 3542 }
3798 case MOVN: 3543 }
3799 if (rt) { 3544 }
3800 set_register(rd_reg, rs); 3545 set_result(rd_reg(), rs() - rt());
3801 TraceRegWr(rs); 3546 break;
3802 } 3547 case SUBU:
3803 break; 3548 set_result(rd_reg(), rs() - rt());
3804 case MOVCI: { 3549 break;
3805 uint32_t cc = instr->FBccValue(); 3550 case AND:
3806 uint32_t fcsr_cc = get_fcsr_condition_bit(cc); 3551 set_result(rd_reg(), rs() & rt());
3807 if (instr->Bit(16)) { // Read Tf bit. 3552 break;
3808 if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs); 3553 case OR:
3809 } else { 3554 set_result(rd_reg(), rs() | rt());
3810 if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs); 3555 break;
3811 } 3556 case XOR:
3812 break; 3557 set_result(rd_reg(), rs() ^ rt());
3813 } 3558 break;
3814 case MOVZ: 3559 case NOR:
3815 if (!rt) { 3560 set_result(rd_reg(), ~(rs() | rt()));
3816 set_register(rd_reg, rs); 3561 break;
3817 TraceRegWr(rs); 3562 case SLT:
3818 } 3563 set_result(rd_reg(), rs() < rt() ? 1 : 0);
3819 break; 3564 break;
3820 default: // For other special opcodes we do the default operation. 3565 case SLTU:
3821 set_register(rd_reg, alu_out); 3566 set_result(rd_reg(), rs_u() < rt_u() ? 1 : 0);
3822 TraceRegWr(alu_out); 3567 break;
3823 } 3568 // Break and trap instructions.
3569 case BREAK:
3570 do_interrupt = true;
3571 break;
3572 case TGE:
3573 do_interrupt = rs() >= rt();
3574 break;
3575 case TGEU:
3576 do_interrupt = rs_u() >= rt_u();
3577 break;
3578 case TLT:
3579 do_interrupt = rs() < rt();
3580 break;
3581 case TLTU:
3582 do_interrupt = rs_u() < rt_u();
3583 break;
3584 case TEQ:
3585 do_interrupt = rs() == rt();
3586 break;
3587 case TNE:
3588 do_interrupt = rs() != rt();
3589 break;
3590 // Conditional moves.
3591 case MOVN:
3592 if (rt()) {
3593 set_register(rd_reg(), rs());
3594 TraceRegWr(rs());
3595 }
3596 break;
3597 case MOVCI: {
3598 uint32_t cc = get_instr()->FBccValue();
3599 uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
3600 if (get_instr()->Bit(16)) { // Read Tf bit.
3601 if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs());
3602 } else {
3603 if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs());
3604 }
3605 break;
3606 }
3607 case MOVZ:
3608 if (!rt()) {
3609 set_register(rd_reg(), rs());
3610 TraceRegWr(rs());
3611 }
3612 break;
3613 default:
3614 UNREACHABLE();
3615 }
3616 if (do_interrupt) {
3617 SoftwareInterrupt(get_instr());
3618 }
3824 } 3619 }
3825 3620
3826 3621
3827 void Simulator::DecodeTypeRegisterSPECIAL2(Instruction* instr, 3622 void Simulator::DecodeTypeRegisterSPECIAL2() {
3828 const int32_t& rd_reg, 3623 int32_t alu_out;
3829 int32_t& alu_out) { 3624 switch (get_instr()->FunctionFieldRaw()) {
3830 switch (instr->FunctionFieldRaw()) {
3831 case MUL: 3625 case MUL:
3832 set_register(rd_reg, alu_out); 3626 // Only the lower 32 bits are kept.
3833 TraceRegWr(alu_out); 3627 alu_out = rs_u() * rt_u();
3834 // HI and LO are UNPREDICTABLE after the operation. 3628 // HI and LO are UNPREDICTABLE after the operation.
3835 set_register(LO, Unpredictable); 3629 set_register(LO, Unpredictable);
3836 set_register(HI, Unpredictable); 3630 set_register(HI, Unpredictable);
3837 break; 3631 break;
3838 default: // For other special2 opcodes we do the default operation. 3632 case CLZ:
3839 set_register(rd_reg, alu_out); 3633 // MIPS32 spec: If no bits were set in GPR rs, the result written to
3840 TraceRegWr(alu_out); 3634 // GPR rd is 32.
3635 alu_out = base::bits::CountLeadingZeros32(rs_u());
3636 break;
3637 default:
3638 alu_out = 0x12345678;
3639 UNREACHABLE();
3841 } 3640 }
3641 set_result(rd_reg(), alu_out);
3842 } 3642 }
3843 3643
3844 3644
3845 void Simulator::DecodeTypeRegisterSPECIAL3(Instruction* instr, 3645 void Simulator::DecodeTypeRegisterSPECIAL3() {
3846 const int32_t& rt_reg, 3646 int32_t alu_out;
3847 const int32_t& rd_reg, 3647 switch (get_instr()->FunctionFieldRaw()) {
3848 int32_t& alu_out) { 3648 case INS: { // Mips32r2 instruction.
3849 switch (instr->FunctionFieldRaw()) { 3649 // Interpret rd field as 5-bit msb of insert.
3850 case INS: 3650 uint16_t msb = rd_reg();
3651 // Interpret sa field as 5-bit lsb of insert.
3652 uint16_t lsb = sa();
3653 uint16_t size = msb - lsb + 1;
3654 uint32_t mask = (1 << size) - 1;
3655 alu_out = (rt_u() & ~(mask << lsb)) | ((rs_u() & mask) << lsb);
3851 // Ins instr leaves result in Rt, rather than Rd. 3656 // Ins instr leaves result in Rt, rather than Rd.
3852 set_register(rt_reg, alu_out); 3657 set_result(rt_reg(), alu_out);
3853 TraceRegWr(alu_out); 3658 break;
3854 break; 3659 }
3855 case EXT: 3660 case EXT: { // Mips32r2 instruction.
3856 set_register(rt_reg, alu_out); 3661 // Interpret rd field as 5-bit msb of extract.
3857 TraceRegWr(alu_out); 3662 uint16_t msb = rd_reg();
3858 break; 3663 // Interpret sa field as 5-bit lsb of extract.
3859 case BSHFL: 3664 uint16_t lsb = sa();
3860 set_register(rd_reg, alu_out); 3665 uint16_t size = msb + 1;
3861 TraceRegWr(alu_out); 3666 uint32_t mask = (1 << size) - 1;
3862 break; 3667 alu_out = (rs_u() & (mask << lsb)) >> lsb;
3668 set_result(rt_reg(), alu_out);
3669 break;
3670 }
3671 case BSHFL: {
3672 int sa = get_instr()->SaFieldRaw() >> kSaShift;
3673 switch (sa) {
3674 case BITSWAP: {
3675 uint32_t input = static_cast<uint32_t>(rt());
3676 uint32_t output = 0;
3677 uint8_t i_byte, o_byte;
3678
3679 // Reverse the bit in byte for each individual byte
3680 for (int i = 0; i < 4; i++) {
3681 output = output >> 8;
3682 i_byte = input & 0xff;
3683
3684 // Fast way to reverse bits in byte
3685 // Devised by Sean Anderson, July 13, 2001
3686 o_byte = static_cast<uint8_t>(((i_byte * 0x0802LU & 0x22110LU) |
3687 (i_byte * 0x8020LU & 0x88440LU)) *
3688 0x10101LU >>
3689 16);
3690
3691 output = output | (static_cast<uint32_t>(o_byte << 24));
3692 input = input >> 8;
3693 }
3694
3695 alu_out = static_cast<int32_t>(output);
3696 break;
3697 }
3698 case SEB:
3699 case SEH:
3700 case WSBH:
3701 alu_out = 0x12345678;
3702 UNREACHABLE();
3703 break;
3704 default: {
3705 const uint8_t bp = get_instr()->Bp2Value();
3706 sa >>= kBp2Bits;
3707 switch (sa) {
3708 case ALIGN: {
3709 if (bp == 0) {
3710 alu_out = static_cast<int32_t>(rt());
3711 } else {
3712 uint32_t rt_hi = rt() << (8 * bp);
3713 uint32_t rs_lo = rs() >> (8 * (4 - bp));
3714 alu_out = static_cast<int32_t>(rt_hi | rs_lo);
3715 }
3716 break;
3717 }
3718 default:
3719 alu_out = 0x12345678;
3720 UNREACHABLE();
3721 break;
3722 }
3723 }
3724 }
3725 set_result(rd_reg(), alu_out);
3726 break;
3727 }
3863 default: 3728 default:
3864 UNREACHABLE(); 3729 UNREACHABLE();
3865 } 3730 }
3866 } 3731 }
3867 3732
3868 3733
3869 void Simulator::DecodeTypeRegister(Instruction* instr) { 3734 void Simulator::DecodeTypeRegister(Instruction* instr) {
3870 // Instruction fields.
3871 const Opcode op = instr->OpcodeFieldRaw(); 3735 const Opcode op = instr->OpcodeFieldRaw();
3872 const int32_t rs_reg = instr->RsValue();
3873 const int32_t rs = get_register(rs_reg);
3874 const uint32_t rs_u = static_cast<uint32_t>(rs);
3875 const int32_t rt_reg = instr->RtValue();
3876 const int32_t rt = get_register(rt_reg);
3877 const uint32_t rt_u = static_cast<uint32_t>(rt);
3878 const int32_t rd_reg = instr->RdValue();
3879
3880 const int32_t fr_reg = instr->FrValue();
3881 const int32_t fs_reg = instr->FsValue();
3882 const int32_t ft_reg = instr->FtValue();
3883 const int32_t fd_reg = instr->FdValue();
3884 int64_t i64hilo = 0;
3885 uint64_t u64hilo = 0;
3886
3887 // ALU output.
3888 // It should not be used as is. Instructions using it should always
3889 // initialize it first.
3890 int32_t alu_out = 0x12345678;
3891
3892 // For break and trap instructions.
3893 bool do_interrupt = false;
3894
3895 // For jr and jalr.
3896 // Get current pc.
3897 int32_t current_pc = get_pc();
3898 // Next pc
3899 int32_t next_pc = 0;
3900 int32_t return_addr_reg = 31;
3901 3736
3902 // Set up the variables if needed before executing the instruction. 3737 // Set up the variables if needed before executing the instruction.
3903 ConfigureTypeRegister(instr, &alu_out, &i64hilo, &u64hilo, &next_pc, 3738 // ConfigureTypeRegister(instr);
3904 &return_addr_reg, &do_interrupt); 3739 set_instr(instr);
3905
3906 // ---------- Raise exceptions triggered.
3907 SignalExceptions();
3908 3740
3909 // ---------- Execution. 3741 // ---------- Execution.
3910 switch (op) { 3742 switch (op) {
3911 case COP1: 3743 case COP1:
3912 DecodeTypeRegisterCOP1(instr, rs_reg, rs, rs_u, rt_reg, rt, rt_u, rd_reg, 3744 DecodeTypeRegisterCOP1();
3913 fr_reg, fs_reg, ft_reg, fd_reg, i64hilo, u64hilo, 3745 ++type_register_cop1_count_;
3914 alu_out, do_interrupt, current_pc, next_pc,
3915 return_addr_reg);
3916 break; 3746 break;
3917 case COP1X: 3747 case COP1X:
3918 DecodeTypeRegisterCOP1X(instr, fr_reg, fs_reg, ft_reg, fd_reg); 3748 DecodeTypeRegisterCOP1X();
3749 ++type_register_cop1x_count_;
3919 break; 3750 break;
3920 case SPECIAL: 3751 case SPECIAL:
3921 DecodeTypeRegisterSPECIAL(instr, rs_reg, rs, rs_u, rt_reg, rt, rt_u, 3752 DecodeTypeRegisterSPECIAL();
3922 rd_reg, fr_reg, fs_reg, ft_reg, fd_reg, i64hilo, 3753 ++type_register_special_count_;
3923 u64hilo, alu_out, do_interrupt, current_pc,
3924 next_pc, return_addr_reg);
3925 break; 3754 break;
3926 case SPECIAL2: 3755 case SPECIAL2:
3927 DecodeTypeRegisterSPECIAL2(instr, rd_reg, alu_out); 3756 DecodeTypeRegisterSPECIAL2();
3757 ++type_register_special2_count_;
3928 break; 3758 break;
3929 case SPECIAL3: 3759 case SPECIAL3:
3930 DecodeTypeRegisterSPECIAL3(instr, rt_reg, rd_reg, alu_out); 3760 DecodeTypeRegisterSPECIAL3();
3761 ++type_register_special3_count_;
3931 break; 3762 break;
3932 // Unimplemented opcodes raised an error in the configuration step before,
3933 // so we can use the default here to set the destination register in common
3934 // cases.
3935 default: 3763 default:
3936 set_register(rd_reg, alu_out); 3764 UNREACHABLE();
3937 } 3765 }
3938 } 3766 }
3939 3767
3940 3768
3769 void Simulator::ArithmeticCommon(const int32_t rt_reg, const int32_t alu_out) {
paul.l... 2015/09/02 17:30:13 I think this could be better named SetResult() or
balazs.kilvady 2015/09/04 12:57:15 Done.
3770 set_register(rt_reg, alu_out);
3771 TraceRegWr(alu_out);
3772 }
3773
3774
3775 // Branch instructions common part.
paul.l... 2015/09/02 17:30:13 I am ok with this as a macro -- it let's you avoid
balazs.kilvady 2015/09/04 12:57:15 The only reason for using macros to avoid using in
3776 #define BranchCommon(do_branch) \
3777 execute_branch_delay_instruction = true; \
3778 if (do_branch) { \
3779 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; \
3780 if (instr->IsLinkingInstruction()) { \
3781 set_register(31, current_pc + 2 * Instruction::kInstrSize); \
3782 } \
3783 } else { \
3784 next_pc = current_pc + 2 * Instruction::kInstrSize; \
3785 }
3786
3787 #define BranchNoLinkingCommon(do_branch) \
3788 execute_branch_delay_instruction = true; \
3789 if (do_branch) { \
3790 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; \
3791 } else { \
3792 next_pc = current_pc + 2 * Instruction::kInstrSize; \
3793 }
3794
3795
3941 // Type 2: instructions using a 16 bytes immediate. (e.g. addi, beq). 3796 // Type 2: instructions using a 16 bytes immediate. (e.g. addi, beq).
3942 void Simulator::DecodeTypeImmediate(Instruction* instr) { 3797 void Simulator::DecodeTypeImmediate(Instruction* instr) {
3943 // Instruction fields. 3798 // Instruction fields.
3944 Opcode op = instr->OpcodeFieldRaw(); 3799 Opcode op = instr->OpcodeFieldRaw();
3945 int32_t rs_reg = instr->RsValue(); 3800 int32_t rs_reg = instr->RsValue();
3946 int32_t rs = get_register(instr->RsValue()); 3801 int32_t rs = get_register(instr->RsValue());
3947 uint32_t rs_u = static_cast<uint32_t>(rs); 3802 uint32_t rs_u = static_cast<uint32_t>(rs);
3948 int32_t rt_reg = instr->RtValue(); // Destination register. 3803 int32_t rt_reg = instr->RtValue(); // Destination register.
3949 int32_t rt = get_register(rt_reg); 3804 int32_t rt = get_register(rt_reg);
3950 int16_t imm16 = instr->Imm16Value(); 3805 int16_t imm16 = instr->Imm16Value();
3951 int32_t imm19 = instr->Imm19Value();
3952 int32_t imm21 = instr->Imm21Value(); 3806 int32_t imm21 = instr->Imm21Value();
3953 int32_t imm26 = instr->Imm26Value(); 3807 int32_t imm26 = instr->Imm26Value();
3954 3808
3955 int32_t ft_reg = instr->FtValue(); // Destination register. 3809 int32_t ft_reg = instr->FtValue(); // Destination register.
3956 int64_t ft; 3810 int64_t ft;
3957 3811
3958 // Zero extended immediate. 3812 // Zero extended immediate.
3959 uint32_t oe_imm16 = 0xffff & imm16; 3813 uint32_t oe_imm16 = 0xffff & imm16;
3960 // Sign extended immediate. 3814 // Sign extended immediate.
3961 int32_t se_imm16 = imm16; 3815 int32_t se_imm16 = imm16;
3962 int32_t se_imm19 = imm19 | ((imm19 & 0x40000) ? 0xfff80000 : 0);
3963 int32_t se_imm26 = imm26 | ((imm26 & 0x2000000) ? 0xfc000000 : 0); 3816 int32_t se_imm26 = imm26 | ((imm26 & 0x2000000) ? 0xfc000000 : 0);
3964 3817
3965
3966 // Get current pc. 3818 // Get current pc.
3967 int32_t current_pc = get_pc(); 3819 int32_t current_pc = get_pc();
3968 // Next pc. 3820 // Next pc.
3969 int32_t next_pc = bad_ra; 3821 int32_t next_pc = bad_ra;
3970 // pc increment
3971 int16_t pc_increment;
3972 3822
3973 // Used for conditional branch instructions. 3823 // Used for conditional branch instructions.
3974 bool do_branch = false; 3824 bool do_branch = false;
3975 bool execute_branch_delay_instruction = false; 3825 bool execute_branch_delay_instruction = false;
3976 3826
3977 // Used for arithmetic instructions. 3827 // Used for arithmetic instructions.
3978 int32_t alu_out = 0; 3828 int32_t alu_out = 0;
3979 // Floating point.
3980 double fp_out = 0.0;
3981 uint32_t cc, cc_value, fcsr_cc;
3982 3829
3983 // Used for memory instructions. 3830 // Used for memory instructions.
3984 int32_t addr = 0x0; 3831 int32_t addr = 0x0;
3985 // Value to be written in memory.
3986 uint32_t mem_value = 0x0;
3987 3832
3988 // ---------- Configuration (and execution for REGIMM). 3833 // ---------- Configuration (and execution for REGIMM).
3989 switch (op) { 3834 switch (op) {
3990 // ------------- COP1. Coprocessor instructions. 3835 // ------------- COP1. Coprocessor instructions.
3991 case COP1: 3836 case COP1:
3992 switch (instr->RsFieldRaw()) { 3837 switch (instr->RsFieldRaw()) {
3993 case BC1: // Branch on coprocessor condition. 3838 case BC1: { // Branch on coprocessor condition.
3994 cc = instr->FBccValue(); 3839 // Floating point.
3995 fcsr_cc = get_fcsr_condition_bit(cc); 3840 uint32_t cc = instr->FBccValue();
3996 cc_value = test_fcsr_bit(fcsr_cc); 3841 uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
3842 uint32_t cc_value = test_fcsr_bit(fcsr_cc);
3997 do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value; 3843 do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value;
3998 execute_branch_delay_instruction = true; 3844 execute_branch_delay_instruction = true;
3999 // Set next_pc. 3845 // Set next_pc.
4000 if (do_branch) { 3846 if (do_branch) {
4001 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; 3847 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
4002 } else { 3848 } else {
4003 next_pc = current_pc + kBranchReturnOffset; 3849 next_pc = current_pc + kBranchReturnOffset;
4004 } 3850 }
4005 break; 3851 break;
3852 }
4006 case BC1EQZ: 3853 case BC1EQZ:
4007 ft = get_fpu_register(ft_reg); 3854 ft = get_fpu_register(ft_reg);
4008 do_branch = (ft & 0x1) ? false : true; 3855 do_branch = (ft & 0x1) ? false : true;
4009 execute_branch_delay_instruction = true; 3856 execute_branch_delay_instruction = true;
4010 // Set next_pc. 3857 // Set next_pc.
4011 if (do_branch) { 3858 if (do_branch) {
4012 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; 3859 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
4013 } else { 3860 } else {
4014 next_pc = current_pc + kBranchReturnOffset; 3861 next_pc = current_pc + kBranchReturnOffset;
4015 } 3862 }
(...skipping 10 matching lines...) Expand all
4026 } 3873 }
4027 break; 3874 break;
4028 default: 3875 default:
4029 UNREACHABLE(); 3876 UNREACHABLE();
4030 } 3877 }
4031 break; 3878 break;
4032 // ------------- REGIMM class. 3879 // ------------- REGIMM class.
4033 case REGIMM: 3880 case REGIMM:
4034 switch (instr->RtFieldRaw()) { 3881 switch (instr->RtFieldRaw()) {
4035 case BLTZ: 3882 case BLTZ:
4036 do_branch = (rs < 0); 3883 do_branch = rs < 0;
4037 break; 3884 break;
4038 case BLTZAL: 3885 case BLTZAL:
4039 do_branch = rs < 0; 3886 do_branch = rs < 0;
4040 break; 3887 break;
4041 case BGEZ: 3888 case BGEZ:
4042 do_branch = rs >= 0; 3889 do_branch = rs >= 0;
4043 break; 3890 break;
4044 case BGEZAL: 3891 case BGEZAL:
4045 do_branch = rs >= 0; 3892 do_branch = rs >= 0;
4046 break; 3893 break;
4047 default: 3894 default:
paul.l... 2015/09/02 17:30:13 This is not necessary, but it might read a bit mor
balazs.kilvady 2015/09/04 12:57:15 Done.
4048 UNREACHABLE(); 3895 UNREACHABLE();
4049 } 3896 }
4050 switch (instr->RtFieldRaw()) { 3897 BranchCommon(do_branch);
4051 case BLTZ: 3898 break; // case REGIMM.
4052 case BLTZAL:
4053 case BGEZ:
4054 case BGEZAL:
4055 // Branch instructions common part.
4056 execute_branch_delay_instruction = true;
4057 // Set next_pc.
4058 if (do_branch) {
4059 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
4060 if (instr->IsLinkingInstruction()) {
4061 set_register(31, current_pc + kBranchReturnOffset);
4062 }
4063 } else {
4064 next_pc = current_pc + kBranchReturnOffset;
4065 }
4066 default:
4067 break;
4068 }
4069 break; // case REGIMM.
4070 // ------------- Branch instructions. 3899 // ------------- Branch instructions.
4071 // When comparing to zero, the encoding of rt field is always 0, so we don't 3900 // When comparing to zero, the encoding of rt field is always 0, so we don't
4072 // need to replace rt with zero. 3901 // need to replace rt with zero.
4073 case BEQ: 3902 case BEQ:
4074 do_branch = (rs == rt); 3903 BranchNoLinkingCommon(rs == rt);
4075 break; 3904 break;
4076 case BNE: 3905 case BNE:
4077 do_branch = rs != rt; 3906 BranchNoLinkingCommon(rs != rt);
4078 break; 3907 break;
4079 case BLEZ: 3908 case BLEZ:
4080 do_branch = rs <= 0; 3909 BranchNoLinkingCommon(rs <= 0);
4081 break; 3910 break;
4082 case BGTZ: 3911 case BGTZ:
4083 do_branch = rs > 0; 3912 BranchNoLinkingCommon(rs > 0);
4084 break; 3913 break;
4085 case POP66: { 3914 case POP66: {
4086 if (rs_reg) { // BEQZC 3915 if (rs_reg) { // BEQZC
4087 int32_t se_imm21 = 3916 int32_t se_imm21 =
4088 static_cast<int32_t>(imm21 << (kOpcodeBits + kRsBits)); 3917 static_cast<int32_t>(imm21 << (kOpcodeBits + kRsBits));
4089 se_imm21 = se_imm21 >> (kOpcodeBits + kRsBits); 3918 se_imm21 = se_imm21 >> (kOpcodeBits + kRsBits);
4090 if (rs == 0) 3919 if (rs == 0)
4091 next_pc = current_pc + 4 + (se_imm21 << 2); 3920 next_pc = current_pc + 4 + (se_imm21 << 2);
4092 else 3921 else
4093 next_pc = current_pc + 4; 3922 next_pc = current_pc + 4;
(...skipping 12 matching lines...) Expand all
4106 set_register(31, current_pc + 4); 3935 set_register(31, current_pc + 4);
4107 next_pc = current_pc + 4 + (se_imm26 << 2); 3936 next_pc = current_pc + 4 + (se_imm26 << 2);
4108 set_pc(next_pc); 3937 set_pc(next_pc);
4109 pc_modified_ = true; 3938 pc_modified_ = true;
4110 break; 3939 break;
4111 } 3940 }
4112 // ------------- Arithmetic instructions. 3941 // ------------- Arithmetic instructions.
4113 case ADDI: 3942 case ADDI:
4114 if (HaveSameSign(rs, se_imm16)) { 3943 if (HaveSameSign(rs, se_imm16)) {
4115 if (rs > 0) { 3944 if (rs > 0) {
4116 exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - se_imm16); 3945 if (rs <= (Registers::kMaxValue - se_imm16)) {
3946 SignalException(kIntegerOverflow);
3947 }
4117 } else if (rs < 0) { 3948 } else if (rs < 0) {
4118 exceptions[kIntegerUnderflow] = 3949 if (rs >= (Registers::kMinValue - se_imm16)) {
4119 rs < (Registers::kMinValue - se_imm16); 3950 SignalException(kIntegerUnderflow);
3951 }
4120 } 3952 }
4121 } 3953 }
4122 alu_out = rs + se_imm16; 3954 alu_out = rs + se_imm16;
3955 ArithmeticCommon(rt_reg, alu_out);
paul.l... 2015/09/02 17:30:12 Here (using above naming suggestion) you can just
balazs.kilvady 2015/09/04 12:57:15 Done.
4123 break; 3956 break;
4124 case ADDIU: 3957 case ADDIU:
4125 alu_out = rs + se_imm16; 3958 alu_out = rs + se_imm16;
3959 ArithmeticCommon(rt_reg, alu_out);
4126 break; 3960 break;
4127 case SLTI: 3961 case SLTI:
4128 alu_out = (rs < se_imm16) ? 1 : 0; 3962 alu_out = (rs < se_imm16) ? 1 : 0;
3963 ArithmeticCommon(rt_reg, alu_out);
4129 break; 3964 break;
4130 case SLTIU: 3965 case SLTIU:
4131 alu_out = (rs_u < static_cast<uint32_t>(se_imm16)) ? 1 : 0; 3966 alu_out = (rs_u < static_cast<uint32_t>(se_imm16)) ? 1 : 0;
3967 ArithmeticCommon(rt_reg, alu_out);
paul.l... 2015/09/02 17:30:12 Here may be a case where use of 'alu_out' does enh
balazs.kilvady 2015/09/04 12:57:15 Done.
4132 break; 3968 break;
4133 case ANDI: 3969 case ANDI:
4134 alu_out = rs & oe_imm16; 3970 alu_out = rs & oe_imm16;
3971 ArithmeticCommon(rt_reg, alu_out);
4135 break; 3972 break;
4136 case ORI: 3973 case ORI:
4137 alu_out = rs | oe_imm16; 3974 alu_out = rs | oe_imm16;
3975 ArithmeticCommon(rt_reg, alu_out);
4138 break; 3976 break;
4139 case XORI: 3977 case XORI:
4140 alu_out = rs ^ oe_imm16; 3978 alu_out = rs ^ oe_imm16;
3979 ArithmeticCommon(rt_reg, alu_out);
4141 break; 3980 break;
4142 case LUI: 3981 case LUI:
4143 alu_out = (oe_imm16 << 16); 3982 alu_out = (oe_imm16 << 16);
3983 ArithmeticCommon(rt_reg, alu_out);
4144 break; 3984 break;
4145 // ------------- Memory instructions. 3985 // ------------- Memory instructions.
4146 case LB: 3986 case LB:
4147 addr = rs + se_imm16; 3987 addr = rs + se_imm16;
4148 alu_out = ReadB(addr); 3988 alu_out = ReadB(addr);
3989 set_register(rt_reg, alu_out);
paul.l... 2015/09/02 17:30:12 Any reason this is not ArithmeticCommon() (a.k.a S
balazs.kilvady 2015/09/04 12:57:15 Done.
4149 break; 3990 break;
4150 case LH: 3991 case LH:
4151 addr = rs + se_imm16; 3992 addr = rs + se_imm16;
4152 alu_out = ReadH(addr, instr); 3993 alu_out = ReadH(addr, instr);
3994 set_register(rt_reg, alu_out);
4153 break; 3995 break;
4154 case LWL: { 3996 case LWL: {
4155 // al_offset is offset of the effective address within an aligned word. 3997 // al_offset is offset of the effective address within an aligned word.
4156 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; 3998 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
4157 uint8_t byte_shift = kPointerAlignmentMask - al_offset; 3999 uint8_t byte_shift = kPointerAlignmentMask - al_offset;
4158 uint32_t mask = (1 << byte_shift * 8) - 1; 4000 uint32_t mask = (1 << byte_shift * 8) - 1;
4159 addr = rs + se_imm16 - al_offset; 4001 addr = rs + se_imm16 - al_offset;
4160 alu_out = ReadW(addr, instr); 4002 alu_out = ReadW(addr, instr);
4161 alu_out <<= byte_shift * 8; 4003 alu_out <<= byte_shift * 8;
4162 alu_out |= rt & mask; 4004 alu_out |= rt & mask;
4005 set_register(rt_reg, alu_out);
4163 break; 4006 break;
4164 } 4007 }
4165 case LW: 4008 case LW:
4166 addr = rs + se_imm16; 4009 addr = rs + se_imm16;
4167 alu_out = ReadW(addr, instr); 4010 alu_out = ReadW(addr, instr);
4011 set_register(rt_reg, alu_out);
4168 break; 4012 break;
4169 case LBU: 4013 case LBU:
4170 addr = rs + se_imm16; 4014 addr = rs + se_imm16;
4171 alu_out = ReadBU(addr); 4015 alu_out = ReadBU(addr);
4016 set_register(rt_reg, alu_out);
4172 break; 4017 break;
4173 case LHU: 4018 case LHU:
4174 addr = rs + se_imm16; 4019 addr = rs + se_imm16;
4175 alu_out = ReadHU(addr, instr); 4020 alu_out = ReadHU(addr, instr);
4021 set_register(rt_reg, alu_out);
4176 break; 4022 break;
4177 case LWR: { 4023 case LWR: {
4178 // al_offset is offset of the effective address within an aligned word. 4024 // al_offset is offset of the effective address within an aligned word.
4179 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; 4025 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
4180 uint8_t byte_shift = kPointerAlignmentMask - al_offset; 4026 uint8_t byte_shift = kPointerAlignmentMask - al_offset;
4181 uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0; 4027 uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
4182 addr = rs + se_imm16 - al_offset; 4028 addr = rs + se_imm16 - al_offset;
4183 alu_out = ReadW(addr, instr); 4029 alu_out = ReadW(addr, instr);
4184 alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8; 4030 alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8;
4185 alu_out |= rt & mask; 4031 alu_out |= rt & mask;
4032 set_register(rt_reg, alu_out);
4186 break; 4033 break;
4187 } 4034 }
4188 case SB: 4035 case SB:
4189 addr = rs + se_imm16; 4036 addr = rs + se_imm16;
4037 WriteB(addr, static_cast<int8_t>(rt));
4190 break; 4038 break;
4191 case SH: 4039 case SH:
4192 addr = rs + se_imm16; 4040 addr = rs + se_imm16;
4041 WriteH(addr, static_cast<uint16_t>(rt), instr);
4193 break; 4042 break;
4194 case SWL: { 4043 case SWL: {
4195 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; 4044 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
4196 uint8_t byte_shift = kPointerAlignmentMask - al_offset; 4045 uint8_t byte_shift = kPointerAlignmentMask - al_offset;
4197 uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0; 4046 uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
4198 addr = rs + se_imm16 - al_offset; 4047 addr = rs + se_imm16 - al_offset;
4199 mem_value = ReadW(addr, instr) & mask; 4048 // Value to be written in memory.
4049 uint32_t mem_value = ReadW(addr, instr) & mask;
4200 mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8; 4050 mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8;
4051 WriteW(addr, mem_value, instr);
4201 break; 4052 break;
4202 } 4053 }
4203 case SW: 4054 case SW:
4204 addr = rs + se_imm16; 4055 addr = rs + se_imm16;
4056 WriteW(addr, rt, instr);
4205 break; 4057 break;
4206 case SWR: { 4058 case SWR: {
4207 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; 4059 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
4208 uint32_t mask = (1 << al_offset * 8) - 1; 4060 uint32_t mask = (1 << al_offset * 8) - 1;
4209 addr = rs + se_imm16 - al_offset; 4061 addr = rs + se_imm16 - al_offset;
4210 mem_value = ReadW(addr, instr); 4062 uint32_t mem_value = ReadW(addr, instr);
4211 mem_value = (rt << al_offset * 8) | (mem_value & mask); 4063 mem_value = (rt << al_offset * 8) | (mem_value & mask);
4064 WriteW(addr, mem_value, instr);
4212 break; 4065 break;
4213 } 4066 }
4214 case LWC1: 4067 case LWC1:
4215 addr = rs + se_imm16; 4068 addr = rs + se_imm16;
4216 alu_out = ReadW(addr, instr); 4069 alu_out = ReadW(addr, instr);
4070 set_fpu_register_hi_word(ft_reg, 0);
4071 set_fpu_register_word(ft_reg, alu_out);
4217 break; 4072 break;
4218 case LDC1: 4073 case LDC1:
4219 addr = rs + se_imm16; 4074 addr = rs + se_imm16;
4220 fp_out = ReadD(addr, instr); 4075 set_fpu_register_double(ft_reg, ReadD(addr, instr));
4221 break; 4076 break;
4222 case SWC1: 4077 case SWC1:
4078 addr = rs + se_imm16;
4079 WriteW(addr, get_fpu_register_word(ft_reg), instr);
4080 break;
4223 case SDC1: 4081 case SDC1:
4224 addr = rs + se_imm16; 4082 addr = rs + se_imm16;
4083 WriteD(addr, get_fpu_register_double(ft_reg), instr);
4225 break; 4084 break;
4226 // ------------- JIALC and BNEZC instructions. 4085 // ------------- JIALC and BNEZC instructions.
4227 case POP76: 4086 case POP76: {
4228 // Next pc. 4087 // Next pc.
4229 next_pc = rt + se_imm16; 4088 next_pc = rt + se_imm16;
4230 // The instruction after the jump is NOT executed. 4089 // The instruction after the jump is NOT executed.
4231 pc_increment = Instruction::kInstrSize; 4090 int16_t pc_increment = Instruction::kInstrSize;
4232 if (instr->IsLinkingInstruction()) { 4091 if (instr->IsLinkingInstruction()) {
4233 set_register(31, current_pc + pc_increment); 4092 set_register(31, current_pc + pc_increment);
4234 } 4093 }
4235 set_pc(next_pc); 4094 set_pc(next_pc);
4236 pc_modified_ = true; 4095 pc_modified_ = true;
4237 break; 4096 break;
4097 }
4238 // ------------- PC-Relative instructions. 4098 // ------------- PC-Relative instructions.
4239 case PCREL: { 4099 case PCREL: {
4240 // rt field: checking 5-bits. 4100 // rt field: checking 5-bits.
4241 uint8_t rt = (imm21 >> kImm16Bits); 4101 uint8_t rt = (imm21 >> kImm16Bits);
4242 switch (rt) { 4102 switch (rt) {
4243 case ALUIPC: 4103 case ALUIPC:
4244 addr = current_pc + (se_imm16 << 16); 4104 addr = current_pc + (se_imm16 << 16);
4245 alu_out = static_cast<int64_t>(~0x0FFFF) & addr; 4105 alu_out = static_cast<int64_t>(~0x0FFFF) & addr;
4246 break; 4106 break;
4247 case AUIPC: 4107 case AUIPC:
4248 alu_out = current_pc + (se_imm16 << 16); 4108 alu_out = current_pc + (se_imm16 << 16);
4249 break; 4109 break;
4250 default: { 4110 default: {
4111 int32_t imm19 = instr->Imm19Value();
4251 // rt field: checking the most significant 2-bits. 4112 // rt field: checking the most significant 2-bits.
4252 rt = (imm21 >> kImm19Bits); 4113 rt = (imm21 >> kImm19Bits);
4253 switch (rt) { 4114 switch (rt) {
4254 case LWPC: { 4115 case LWPC: {
4255 int32_t offset = imm19;
4256 // Set sign. 4116 // Set sign.
4257 offset <<= (kOpcodeBits + kRsBits + 2); 4117 imm19 <<= (kOpcodeBits + kRsBits + 2);
4258 offset >>= (kOpcodeBits + kRsBits + 2); 4118 imm19 >>= (kOpcodeBits + kRsBits + 2);
4259 addr = current_pc + (offset << 2); 4119 addr = current_pc + (imm19 << 2);
4260 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr); 4120 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr);
4261 alu_out = *ptr; 4121 alu_out = *ptr;
4262 break; 4122 break;
4263 } 4123 }
4264 case ADDIUPC: 4124 case ADDIUPC: {
4125 int32_t se_imm19 = imm19 | ((imm19 & 0x40000) ? 0xfff80000 : 0);
4265 alu_out = current_pc + (se_imm19 << 2); 4126 alu_out = current_pc + (se_imm19 << 2);
4266 break; 4127 break;
4128 }
4267 default: 4129 default:
4268 UNREACHABLE(); 4130 UNREACHABLE();
4269 break; 4131 break;
4270 } 4132 }
4271 } 4133 }
4272 } 4134 }
4135 set_register(rs_reg, alu_out);
4273 break; 4136 break;
4274 } 4137 }
4275 default: 4138 default:
4276 UNREACHABLE(); 4139 UNREACHABLE();
4277 } 4140 }
4278 4141
4279 // ---------- Raise exceptions triggered.
4280 SignalExceptions();
4281
4282 // ---------- Execution.
4283 switch (op) {
4284 // ------------- Branch instructions.
4285 case BEQ:
4286 case BNE:
4287 case BLEZ:
4288 case BGTZ:
4289 // Branch instructions common part.
4290 execute_branch_delay_instruction = true;
4291 // Set next_pc.
4292 if (do_branch) {
4293 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
4294 if (instr->IsLinkingInstruction()) {
4295 set_register(31, current_pc + 2* Instruction::kInstrSize);
4296 }
4297 } else {
4298 next_pc = current_pc + 2 * Instruction::kInstrSize;
4299 }
4300 break;
4301 // ------------- Arithmetic instructions.
4302 case ADDI:
4303 case ADDIU:
4304 case SLTI:
4305 case SLTIU:
4306 case ANDI:
4307 case ORI:
4308 case XORI:
4309 case LUI:
4310 set_register(rt_reg, alu_out);
4311 TraceRegWr(alu_out);
4312 break;
4313 // ------------- Memory instructions.
4314 case LB:
4315 case LH:
4316 case LWL:
4317 case LW:
4318 case LBU:
4319 case LHU:
4320 case LWR:
4321 set_register(rt_reg, alu_out);
4322 break;
4323 case SB:
4324 WriteB(addr, static_cast<int8_t>(rt));
4325 break;
4326 case SH:
4327 WriteH(addr, static_cast<uint16_t>(rt), instr);
4328 break;
4329 case SWL:
4330 WriteW(addr, mem_value, instr);
4331 break;
4332 case SW:
4333 WriteW(addr, rt, instr);
4334 break;
4335 case SWR:
4336 WriteW(addr, mem_value, instr);
4337 break;
4338 case LWC1:
4339 set_fpu_register_hi_word(ft_reg, 0);
4340 set_fpu_register_word(ft_reg, alu_out);
4341 break;
4342 case LDC1:
4343 set_fpu_register_double(ft_reg, fp_out);
4344 break;
4345 case SWC1:
4346 addr = rs + se_imm16;
4347 WriteW(addr, get_fpu_register_word(ft_reg), instr);
4348 break;
4349 case SDC1:
4350 addr = rs + se_imm16;
4351 WriteD(addr, get_fpu_register_double(ft_reg), instr);
4352 break;
4353 case PCREL:
4354 set_register(rs_reg, alu_out);
4355 default:
4356 break;
4357 }
4358
4359
4360 if (execute_branch_delay_instruction) { 4142 if (execute_branch_delay_instruction) {
4361 // Execute branch delay slot 4143 // Execute branch delay slot
4362 // We don't check for end_sim_pc. First it should not be met as the current 4144 // We don't check for end_sim_pc. First it should not be met as the current
4363 // pc is valid. Secondly a jump should always execute its branch delay slot. 4145 // pc is valid. Secondly a jump should always execute its branch delay slot.
4364 Instruction* branch_delay_instr = 4146 Instruction* branch_delay_instr =
4365 reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize); 4147 reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize);
4366 BranchDelayInstructionDecode(branch_delay_instr); 4148 BranchDelayInstructionDecode(branch_delay_instr);
4367 } 4149 }
4368 4150
4369 // If needed update pc after the branch delay execution. 4151 // If needed update pc after the branch delay execution.
4370 if (next_pc != bad_ra) { 4152 if (next_pc != bad_ra) {
4371 set_pc(next_pc); 4153 set_pc(next_pc);
4372 } 4154 }
4373 } 4155 }
4374 4156
4157 #undef BranchCommon
4158 #undef BranchNoLinkingCommon
4159
4375 4160
4376 // Type 3: instructions using a 26 bytes immediate. (e.g. j, jal). 4161 // Type 3: instructions using a 26 bytes immediate. (e.g. j, jal).
4377 void Simulator::DecodeTypeJump(Instruction* instr) { 4162 void Simulator::DecodeTypeJump(Instruction* instr) {
4378 // Get current pc. 4163 // Get current pc.
4379 int32_t current_pc = get_pc(); 4164 int32_t current_pc = get_pc();
4380 // Get unchanged bits of pc. 4165 // Get unchanged bits of pc.
4381 int32_t pc_high_bits = current_pc & 0xf0000000; 4166 int32_t pc_high_bits = current_pc & 0xf0000000;
4382 // Next pc. 4167 // Next pc.
4383 int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2); 4168 int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2);
4384 4169
(...skipping 21 matching lines...) Expand all
4406 } 4191 }
4407 pc_modified_ = false; 4192 pc_modified_ = false;
4408 v8::internal::EmbeddedVector<char, 256> buffer; 4193 v8::internal::EmbeddedVector<char, 256> buffer;
4409 if (::v8::internal::FLAG_trace_sim) { 4194 if (::v8::internal::FLAG_trace_sim) {
4410 SNPrintF(trace_buf_, "%s", ""); 4195 SNPrintF(trace_buf_, "%s", "");
4411 disasm::NameConverter converter; 4196 disasm::NameConverter converter;
4412 disasm::Disassembler dasm(converter); 4197 disasm::Disassembler dasm(converter);
4413 dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr)); 4198 dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
4414 } 4199 }
4415 4200
4416 switch (instr->InstructionType()) { 4201 switch (instr->InstructionType(Instruction::TypeChecks::EXTRA)) {
4417 case Instruction::kRegisterType: 4202 case Instruction::kRegisterType:
4418 DecodeTypeRegister(instr); 4203 DecodeTypeRegister(instr);
4204 ++type_register_count_;
4419 break; 4205 break;
4420 case Instruction::kImmediateType: 4206 case Instruction::kImmediateType:
4421 DecodeTypeImmediate(instr); 4207 DecodeTypeImmediate(instr);
4208 ++type_immediate_count_;
4422 break; 4209 break;
4423 case Instruction::kJumpType: 4210 case Instruction::kJumpType:
4424 DecodeTypeJump(instr); 4211 DecodeTypeJump(instr);
4212 ++type_jump_count_;
4425 break; 4213 break;
4426 default: 4214 default:
4427 UNSUPPORTED(); 4215 UNSUPPORTED();
4428 } 4216 }
4429 if (::v8::internal::FLAG_trace_sim) { 4217 if (::v8::internal::FLAG_trace_sim) {
4430 PrintF(" 0x%08x %-44s %s\n", reinterpret_cast<intptr_t>(instr), 4218 PrintF(" 0x%08x %-44s %s\n", reinterpret_cast<intptr_t>(instr),
4431 buffer.start(), trace_buf_.start()); 4219 buffer.start(), trace_buf_.start());
4432 } 4220 }
4433 if (!pc_modified_) { 4221 if (!pc_modified_) {
4434 set_register(pc, reinterpret_cast<int32_t>(instr) + 4222 set_register(pc, reinterpret_cast<int32_t>(instr) +
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
4618 4406
4619 4407
4620 #undef UNSUPPORTED 4408 #undef UNSUPPORTED
4621 4409
4622 } // namespace internal 4410 } // namespace internal
4623 } // namespace v8 4411 } // namespace v8
4624 4412
4625 #endif // USE_SIMULATOR 4413 #endif // USE_SIMULATOR
4626 4414
4627 #endif // V8_TARGET_ARCH_MIPS 4415 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« src/mips/simulator-mips.h ('K') | « src/mips/simulator-mips.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698