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

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

Issue 1046873004: MIPS: Refactor simulator and add selection instructions for r6. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 8 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
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 #include "src/v8.h" 10 #include "src/v8.h"
(...skipping 2061 matching lines...) Expand 10 before | Expand all | Expand 10 after
2072 *do_interrupt = rs != rt; 2072 *do_interrupt = rs != rt;
2073 break; 2073 break;
2074 case MOVN: 2074 case MOVN:
2075 case MOVZ: 2075 case MOVZ:
2076 case MOVCI: 2076 case MOVCI:
2077 // No action taken on decode. 2077 // No action taken on decode.
2078 break; 2078 break;
2079 case DIV: 2079 case DIV:
2080 case DIVU: 2080 case DIVU:
2081 // div and divu never raise exceptions. 2081 // div and divu never raise exceptions.
2082 case SELEQZ_S:
2083 case SELNEZ_S:
2082 break; 2084 break;
2083 default: 2085 default:
2084 UNREACHABLE(); 2086 UNREACHABLE();
2085 } 2087 }
2086 break; 2088 break;
2087 case SPECIAL2: 2089 case SPECIAL2:
2088 switch (instr->FunctionFieldRaw()) { 2090 switch (instr->FunctionFieldRaw()) {
2089 case MUL: 2091 case MUL:
2090 *alu_out = rs_u * rt_u; // Only the lower 32 bits are kept. 2092 *alu_out = rs_u * rt_u; // Only the lower 32 bits are kept.
2091 break; 2093 break;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2123 default: 2125 default:
2124 UNREACHABLE(); 2126 UNREACHABLE();
2125 } 2127 }
2126 break; 2128 break;
2127 default: 2129 default:
2128 UNREACHABLE(); 2130 UNREACHABLE();
2129 } 2131 }
2130 } 2132 }
2131 2133
2132 2134
2133 void Simulator::DecodeTypeRegister(Instruction* instr) { 2135 void Simulator::DecodeTypeRegisterDRsType(Instruction* instr,
2134 // Instruction fields. 2136 const int32_t& fr_reg,
2135 const Opcode op = instr->OpcodeFieldRaw(); 2137 const int32_t& fs_reg,
2136 const int32_t rs_reg = instr->RsValue(); 2138 const int32_t& ft_reg,
2137 const int32_t rs = get_register(rs_reg); 2139 const int32_t& fd_reg) {
2138 const uint32_t rs_u = static_cast<uint32_t>(rs); 2140 double ft, fs;
2139 const int32_t rt_reg = instr->RtValue(); 2141 uint32_t cc, fcsr_cc;
2140 const int32_t rt = get_register(rt_reg); 2142 int64_t i64;
2141 const uint32_t rt_u = static_cast<uint32_t>(rt); 2143 fs = get_fpu_register_double(fs_reg);
2142 const int32_t rd_reg = instr->RdValue(); 2144 ft = get_fpu_register_double(ft_reg);
2143 2145 int64_t ft_int = static_cast<int64_t>(ft);
2144 const int32_t fr_reg = instr->FrValue(); 2146 cc = instr->FCccValue();
2145 const int32_t fs_reg = instr->FsValue(); 2147 fcsr_cc = get_fcsr_condition_bit(cc);
2146 const int32_t ft_reg = instr->FtValue(); 2148 switch (instr->FunctionFieldRaw()) {
2147 const int32_t fd_reg = instr->FdValue(); 2149 case SELEQZ_C:
2148 int64_t i64hilo = 0; 2150 DCHECK(IsMipsArchVariant(kMips32r6));
2149 uint64_t u64hilo = 0; 2151 set_fpu_register_double(fd_reg, (ft_int & 0x1) == 0 ? fs : 0.0);
2150 2152 break;
2151 // ALU output. 2153 case SELNEZ_C:
2152 // It should not be used as is. Instructions using it should always 2154 DCHECK(IsMipsArchVariant(kMips32r6));
2153 // initialize it first. 2155 set_fpu_register_double(fd_reg, (ft_int & 0x1) != 0 ? fs : 0.0);
2154 int32_t alu_out = 0x12345678; 2156 break;
2155 2157 case ADD_D:
2156 // For break and trap instructions. 2158 set_fpu_register_double(fd_reg, fs + ft);
2157 bool do_interrupt = false; 2159 break;
2158 2160 case SUB_D:
2159 // For jr and jalr. 2161 set_fpu_register_double(fd_reg, fs - ft);
2160 // Get current pc. 2162 break;
2161 int32_t current_pc = get_pc(); 2163 case MUL_D:
2162 // Next pc 2164 set_fpu_register_double(fd_reg, fs * ft);
2163 int32_t next_pc = 0; 2165 break;
2164 int32_t return_addr_reg = 31; 2166 case DIV_D:
2165 2167 set_fpu_register_double(fd_reg, fs / ft);
2166 // Set up the variables if needed before executing the instruction. 2168 break;
2167 ConfigureTypeRegister(instr, 2169 case ABS_D:
2168 &alu_out, 2170 set_fpu_register_double(fd_reg, fabs(fs));
2169 &i64hilo, 2171 break;
2170 &u64hilo, 2172 case MOV_D:
2171 &next_pc, 2173 set_fpu_register_double(fd_reg, fs);
2172 &return_addr_reg, 2174 break;
2173 &do_interrupt); 2175 case NEG_D:
2174 2176 set_fpu_register_double(fd_reg, -fs);
2175 // ---------- Raise exceptions triggered. 2177 break;
2176 SignalExceptions(); 2178 case SQRT_D:
2177 2179 set_fpu_register_double(fd_reg, fast_sqrt(fs));
2178 // ---------- Execution. 2180 break;
2179 switch (op) { 2181 case C_UN_D:
2180 case COP1: 2182 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2181 switch (instr->RsFieldRaw()) { 2183 break;
2182 case CFC1: 2184 case C_EQ_D:
2183 set_register(rt_reg, alu_out); 2185 set_fcsr_bit(fcsr_cc, (fs == ft));
2184 break; 2186 break;
2185 case MFC1: 2187 case C_UEQ_D:
2186 set_register(rt_reg, alu_out); 2188 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
2187 break; 2189 break;
2188 case MFHC1: 2190 case C_OLT_D:
2189 set_register(rt_reg, alu_out); 2191 set_fcsr_bit(fcsr_cc, (fs < ft));
2190 break; 2192 break;
2191 case CTC1: 2193 case C_ULT_D:
2192 // At the moment only FCSR is supported. 2194 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
2193 DCHECK(fs_reg == kFCSRRegister); 2195 break;
2194 FCSR_ = registers_[rt_reg]; 2196 case C_OLE_D:
2195 break; 2197 set_fcsr_bit(fcsr_cc, (fs <= ft));
2196 case MTC1: 2198 break;
2197 // Hardware writes upper 32-bits to zero on mtc1. 2199 case C_ULE_D:
2198 set_fpu_register_hi_word(fs_reg, 0); 2200 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
2199 set_fpu_register_word(fs_reg, registers_[rt_reg]); 2201 break;
2200 break; 2202 case CVT_W_D: // Convert double to word.
2201 case MTHC1: 2203 // Rounding modes are not yet supported.
2202 set_fpu_register_hi_word(fs_reg, registers_[rt_reg]); 2204 DCHECK((FCSR_ & 3) == 0);
2203 break; 2205 // In rounding mode 0 it should behave like ROUND.
2204 case S: 2206 case ROUND_W_D: // Round double to word (round half to even).
2205 float f; 2207 {
2206 switch (instr->FunctionFieldRaw()) { 2208 double rounded = std::floor(fs + 0.5);
2207 case CVT_D_S: 2209 int32_t result = static_cast<int32_t>(rounded);
2208 f = get_fpu_register_float(fs_reg); 2210 if ((result & 1) != 0 && result - fs == 0.5) {
2209 set_fpu_register_double(fd_reg, static_cast<double>(f)); 2211 // If the number is halfway between two integers,
2210 break; 2212 // round to the even one.
2211 default: 2213 result--;
2212 // CVT_W_S CVT_L_S TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S 2214 }
2213 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented. 2215 set_fpu_register_word(fd_reg, result);
2214 UNREACHABLE(); 2216 if (set_fcsr_round_error(fs, rounded)) {
2215 } 2217 set_fpu_register_word(fd_reg, kFPUInvalidResult);
2216 break; 2218 }
2217 case D: 2219 } break;
2218 double ft, fs; 2220 case TRUNC_W_D: // Truncate double to word (round towards 0).
2219 uint32_t cc, fcsr_cc; 2221 {
2220 int64_t i64; 2222 double rounded = trunc(fs);
2221 fs = get_fpu_register_double(fs_reg); 2223 int32_t result = static_cast<int32_t>(rounded);
2222 ft = get_fpu_register_double(ft_reg); 2224 set_fpu_register_word(fd_reg, result);
2223 cc = instr->FCccValue(); 2225 if (set_fcsr_round_error(fs, rounded)) {
2224 fcsr_cc = get_fcsr_condition_bit(cc); 2226 set_fpu_register_word(fd_reg, kFPUInvalidResult);
2225 switch (instr->FunctionFieldRaw()) { 2227 }
2226 case ADD_D: 2228 } break;
2227 set_fpu_register_double(fd_reg, fs + ft); 2229 case FLOOR_W_D: // Round double to word towards negative infinity.
2228 break; 2230 {
2229 case SUB_D: 2231 double rounded = std::floor(fs);
2230 set_fpu_register_double(fd_reg, fs - ft); 2232 int32_t result = static_cast<int32_t>(rounded);
2231 break; 2233 set_fpu_register_word(fd_reg, result);
2232 case MUL_D: 2234 if (set_fcsr_round_error(fs, rounded)) {
2233 set_fpu_register_double(fd_reg, fs * ft); 2235 set_fpu_register_word(fd_reg, kFPUInvalidResult);
2234 break; 2236 }
2235 case DIV_D: 2237 } break;
2236 set_fpu_register_double(fd_reg, fs / ft); 2238 case CEIL_W_D: // Round double to word towards positive infinity.
2237 break; 2239 {
2238 case ABS_D: 2240 double rounded = std::ceil(fs);
2239 set_fpu_register_double(fd_reg, fabs(fs)); 2241 int32_t result = static_cast<int32_t>(rounded);
2240 break; 2242 set_fpu_register_word(fd_reg, result);
2241 case MOV_D: 2243 if (set_fcsr_round_error(fs, rounded)) {
2242 set_fpu_register_double(fd_reg, fs); 2244 set_fpu_register_word(fd_reg, kFPUInvalidResult);
2243 break; 2245 }
2244 case NEG_D: 2246 } break;
2245 set_fpu_register_double(fd_reg, -fs); 2247 case CVT_S_D: // Convert double to float (single).
2246 break; 2248 set_fpu_register_float(fd_reg, static_cast<float>(fs));
2247 case SQRT_D: 2249 break;
2248 set_fpu_register_double(fd_reg, fast_sqrt(fs)); 2250 case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word.
2249 break; 2251 double rounded = trunc(fs);
2250 case C_UN_D: 2252 i64 = static_cast<int64_t>(rounded);
2251 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); 2253 if (IsFp64Mode()) {
2252 break; 2254 set_fpu_register(fd_reg, i64);
2253 case C_EQ_D: 2255 } else {
2254 set_fcsr_bit(fcsr_cc, (fs == ft)); 2256 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2255 break; 2257 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2256 case C_UEQ_D: 2258 }
2257 set_fcsr_bit(fcsr_cc, 2259 break;
2258 (fs == ft) || (std::isnan(fs) || std::isnan(ft))); 2260 }
2259 break; 2261 case TRUNC_L_D: { // Mips32r2 instruction.
paul.l... 2015/03/31 04:02:01 This comment (and many other like it need to be ch
2260 case C_OLT_D: 2262 double rounded = trunc(fs);
2261 set_fcsr_bit(fcsr_cc, (fs < ft)); 2263 i64 = static_cast<int64_t>(rounded);
2262 break; 2264 if (IsFp64Mode()) {
2263 case C_ULT_D: 2265 set_fpu_register(fd_reg, i64);
2264 set_fcsr_bit(fcsr_cc, 2266 } else {
2265 (fs < ft) || (std::isnan(fs) || std::isnan(ft))); 2267 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2266 break; 2268 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2267 case C_OLE_D: 2269 }
2268 set_fcsr_bit(fcsr_cc, (fs <= ft)); 2270 break;
2269 break; 2271 }
2270 case C_ULE_D: 2272 case ROUND_L_D: { // Mips32r2 instruction.
2271 set_fcsr_bit(fcsr_cc, 2273 double rounded = fs > 0 ? std::floor(fs + 0.5) : std::ceil(fs - 0.5);
2272 (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); 2274 i64 = static_cast<int64_t>(rounded);
2273 break; 2275 if (IsFp64Mode()) {
2274 case CVT_W_D: // Convert double to word. 2276 set_fpu_register(fd_reg, i64);
2275 // Rounding modes are not yet supported. 2277 } else {
2276 DCHECK((FCSR_ & 3) == 0); 2278 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2277 // In rounding mode 0 it should behave like ROUND. 2279 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2278 case ROUND_W_D: // Round double to word (round half to even). 2280 }
2279 { 2281 break;
2280 double rounded = std::floor(fs + 0.5); 2282 }
2281 int32_t result = static_cast<int32_t>(rounded); 2283 case FLOOR_L_D: // Mips32r2 instruction.
2282 if ((result & 1) != 0 && result - fs == 0.5) { 2284 i64 = static_cast<int64_t>(std::floor(fs));
2283 // If the number is halfway between two integers, 2285 if (IsFp64Mode()) {
2284 // round to the even one. 2286 set_fpu_register(fd_reg, i64);
2285 result--; 2287 } else {
2286 } 2288 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2287 set_fpu_register_word(fd_reg, result); 2289 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2288 if (set_fcsr_round_error(fs, rounded)) { 2290 }
2289 set_fpu_register_word(fd_reg, kFPUInvalidResult); 2291 break;
2290 } 2292 case CEIL_L_D: // Mips32r2 instruction.
2291 } 2293 i64 = static_cast<int64_t>(std::ceil(fs));
2292 break; 2294 if (IsFp64Mode()) {
2293 case TRUNC_W_D: // Truncate double to word (round towards 0). 2295 set_fpu_register(fd_reg, i64);
2294 { 2296 } else {
2295 double rounded = trunc(fs); 2297 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2296 int32_t result = static_cast<int32_t>(rounded); 2298 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2297 set_fpu_register_word(fd_reg, result); 2299 }
2298 if (set_fcsr_round_error(fs, rounded)) { 2300 break;
2299 set_fpu_register_word(fd_reg, kFPUInvalidResult); 2301 case C_F_D:
2300 } 2302 UNIMPLEMENTED_MIPS();
2301 } 2303 break;
2302 break; 2304 default:
2303 case FLOOR_W_D: // Round double to word towards negative infinity. 2305 UNREACHABLE();
2304 { 2306 }
2305 double rounded = std::floor(fs); 2307 }
2306 int32_t result = static_cast<int32_t>(rounded); 2308
2307 set_fpu_register_word(fd_reg, result); 2309
2308 if (set_fcsr_round_error(fs, rounded)) { 2310 void Simulator::DecodeTypeRegisterWRsType(Instruction* instr, int32_t& alu_out,
2309 set_fpu_register_word(fd_reg, kFPUInvalidResult); 2311 const int32_t& fd_reg,
2310 } 2312 const int32_t& fs_reg) {
2311 } 2313 switch (instr->FunctionFieldRaw()) {
2312 break; 2314 case CVT_S_W: // Convert word to float (single).
2313 case CEIL_W_D: // Round double to word towards positive infinity. 2315 alu_out = get_fpu_register_signed_word(fs_reg);
2314 { 2316 set_fpu_register_float(fd_reg, static_cast<float>(alu_out));
2315 double rounded = std::ceil(fs); 2317 break;
2316 int32_t result = static_cast<int32_t>(rounded); 2318 case CVT_D_W: // Convert word to double.
2317 set_fpu_register_word(fd_reg, result); 2319 alu_out = get_fpu_register_signed_word(fs_reg);
2318 if (set_fcsr_round_error(fs, rounded)) { 2320 set_fpu_register_double(fd_reg, static_cast<double>(alu_out));
2319 set_fpu_register_word(fd_reg, kFPUInvalidResult); 2321 break;
2320 } 2322 default: // Mips64r6 CMP.S instructions unimplemented.
2321 } 2323 UNREACHABLE();
2322 break; 2324 }
2323 case CVT_S_D: // Convert double to float (single). 2325 }
2324 set_fpu_register_float(fd_reg, static_cast<float>(fs)); 2326
2325 break; 2327
2326 case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word. 2328 void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
2327 double rounded = trunc(fs); 2329 const int32_t& ft_reg,
2328 i64 = static_cast<int64_t>(rounded); 2330 const int32_t& fs_reg,
2329 if (IsFp64Mode()) { 2331 const int32_t& fd_reg) {
2330 set_fpu_register(fd_reg, i64); 2332 float f;
2331 } else { 2333 double ft = get_fpu_register_double(ft_reg);
2332 set_fpu_register_word(fd_reg, i64 & 0xffffffff); 2334 int64_t ft_int = static_cast<int64_t>(ft);
2333 set_fpu_register_word(fd_reg + 1, i64 >> 32); 2335 switch (instr->FunctionFieldRaw()) {
2334 } 2336 case CVT_D_S:
2335 break; 2337 f = get_fpu_register_float(fs_reg);
2336 } 2338 set_fpu_register_double(fd_reg, static_cast<double>(f));
2337 case TRUNC_L_D: { // Mips32r2 instruction. 2339 break;
2338 double rounded = trunc(fs); 2340 case SELEQZ_C:
2339 i64 = static_cast<int64_t>(rounded); 2341 DCHECK(IsMipsArchVariant(kMips32r6));
2340 if (IsFp64Mode()) { 2342 set_fpu_register_double(
2341 set_fpu_register(fd_reg, i64); 2343 fd_reg, (ft_int & 0x1) == 0 ? get_fpu_register_double(fs_reg) : 0.0);
2342 } else { 2344 break;
2343 set_fpu_register_word(fd_reg, i64 & 0xffffffff); 2345 case SELNEZ_C:
2344 set_fpu_register_word(fd_reg + 1, i64 >> 32); 2346 DCHECK(IsMipsArchVariant(kMips32r6));
2345 } 2347 set_fpu_register_double(
2346 break; 2348 fd_reg, (ft_int & 0x1) != 0 ? get_fpu_register_double(fs_reg) : 0.0);
2347 } 2349 break;
2348 case ROUND_L_D: { // Mips32r2 instruction. 2350 default:
2349 double rounded = 2351 // CVT_W_S CVT_L_S TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S
2350 fs > 0 ? std::floor(fs + 0.5) : std::ceil(fs - 0.5); 2352 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented.
2351 i64 = static_cast<int64_t>(rounded); 2353 UNREACHABLE();
2352 if (IsFp64Mode()) { 2354 }
2353 set_fpu_register(fd_reg, i64); 2355 }
2354 } else { 2356
2355 set_fpu_register_word(fd_reg, i64 & 0xffffffff); 2357
2356 set_fpu_register_word(fd_reg + 1, i64 >> 32); 2358 void Simulator::DecodeTypeRegisterLRsType(Instruction* instr,
2357 } 2359 const int32_t& ft_reg,
2358 break; 2360 const int32_t& fs_reg,
2359 } 2361 const int32_t& fd_reg) {
2360 case FLOOR_L_D: // Mips32r2 instruction. 2362 double fs = get_fpu_register_double(fs_reg);
2361 i64 = static_cast<int64_t>(std::floor(fs)); 2363 double ft = get_fpu_register_double(ft_reg);
2362 if (IsFp64Mode()) { 2364 switch (instr->FunctionFieldRaw()) {
2363 set_fpu_register(fd_reg, i64); 2365 case CVT_D_L: // Mips32r2 instruction.
2364 } else { 2366 // Watch the signs here, we want 2 32-bit vals
2365 set_fpu_register_word(fd_reg, i64 & 0xffffffff); 2367 // to make a sign-64.
2366 set_fpu_register_word(fd_reg + 1, i64 >> 32); 2368 int64_t i64;
2367 } 2369 if (IsFp64Mode()) {
2368 break; 2370 i64 = get_fpu_register(fs_reg);
2369 case CEIL_L_D: // Mips32r2 instruction. 2371 } else {
2370 i64 = static_cast<int64_t>(std::ceil(fs)); 2372 i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg));
2371 if (IsFp64Mode()) { 2373 i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg + 1)) << 32;
2372 set_fpu_register(fd_reg, i64); 2374 }
2373 } else { 2375 set_fpu_register_double(fd_reg, static_cast<double>(i64));
2374 set_fpu_register_word(fd_reg, i64 & 0xffffffff); 2376 break;
2375 set_fpu_register_word(fd_reg + 1, i64 >> 32); 2377 case CVT_S_L:
2376 } 2378 UNIMPLEMENTED_MIPS();
2377 break; 2379 break;
2378 case C_F_D: 2380 case CMP_AF: // Mips64r6 CMP.D instructions.
2379 UNIMPLEMENTED_MIPS(); 2381 UNIMPLEMENTED_MIPS();
2380 break; 2382 break;
2381 default: 2383 case CMP_UN:
2382 UNREACHABLE(); 2384 if (std::isnan(fs) || std::isnan(ft)) {
2383 } 2385 set_fpu_register(fd_reg, -1);
2384 break; 2386 } else {
2385 case W: 2387 set_fpu_register(fd_reg, 0);
2386 switch (instr->FunctionFieldRaw()) { 2388 }
2387 case CVT_S_W: // Convert word to float (single). 2389 break;
2388 alu_out = get_fpu_register_signed_word(fs_reg); 2390 case CMP_EQ:
2389 set_fpu_register_float(fd_reg, static_cast<float>(alu_out)); 2391 if (fs == ft) {
2390 break; 2392 set_fpu_register(fd_reg, -1);
2391 case CVT_D_W: // Convert word to double. 2393 } else {
2392 alu_out = get_fpu_register_signed_word(fs_reg); 2394 set_fpu_register(fd_reg, 0);
2393 set_fpu_register_double(fd_reg, static_cast<double>(alu_out)); 2395 }
2394 break; 2396 break;
2395 default: // Mips64r6 CMP.S instructions unimplemented. 2397 case CMP_UEQ:
2396 UNREACHABLE(); 2398 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
2397 } 2399 set_fpu_register(fd_reg, -1);
2398 break; 2400 } else {
2399 case L: 2401 set_fpu_register(fd_reg, 0);
2400 fs = get_fpu_register_double(fs_reg); 2402 }
2401 ft = get_fpu_register_double(ft_reg); 2403 break;
2402 switch (instr->FunctionFieldRaw()) { 2404 case CMP_LT:
2403 case CVT_D_L: // Mips32r2 instruction. 2405 if (fs < ft) {
2404 // Watch the signs here, we want 2 32-bit vals 2406 set_fpu_register(fd_reg, -1);
2405 // to make a sign-64. 2407 } else {
2406 if (IsFp64Mode()) { 2408 set_fpu_register(fd_reg, 0);
2407 i64 = get_fpu_register(fs_reg); 2409 }
2408 } else { 2410 break;
2409 i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg)); 2411 case CMP_ULT:
2410 i64 |= static_cast<int64_t>( 2412 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
2411 get_fpu_register_word(fs_reg + 1)) << 32; 2413 set_fpu_register(fd_reg, -1);
2412 } 2414 } else {
2413 set_fpu_register_double(fd_reg, static_cast<double>(i64)); 2415 set_fpu_register(fd_reg, 0);
2414 break; 2416 }
2415 case CVT_S_L: 2417 break;
2416 UNIMPLEMENTED_MIPS(); 2418 case CMP_LE:
2417 break; 2419 if (fs <= ft) {
2418 case CMP_AF: // Mips64r6 CMP.D instructions. 2420 set_fpu_register(fd_reg, -1);
2419 UNIMPLEMENTED_MIPS(); 2421 } else {
2420 break; 2422 set_fpu_register(fd_reg, 0);
2421 case CMP_UN: 2423 }
2422 if (std::isnan(fs) || std::isnan(ft)) { 2424 break;
2423 set_fpu_register(fd_reg, -1); 2425 case CMP_ULE:
2424 } else { 2426 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
2425 set_fpu_register(fd_reg, 0); 2427 set_fpu_register(fd_reg, -1);
2426 } 2428 } else {
2427 break; 2429 set_fpu_register(fd_reg, 0);
2428 case CMP_EQ: 2430 }
2429 if (fs == ft) { 2431 break;
2430 set_fpu_register(fd_reg, -1); 2432 default: // CMP_OR CMP_UNE CMP_NE UNIMPLEMENTED.
2431 } else { 2433 UNREACHABLE();
2432 set_fpu_register(fd_reg, 0); 2434 }
2433 } 2435 }
2434 break; 2436
2435 case CMP_UEQ: 2437
2436 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { 2438 void Simulator::DecodeTypeRegisterCOP1(
2437 set_fpu_register(fd_reg, -1); 2439 Instruction* instr, const int32_t& rs_reg, const int32_t& rs,
2438 } else { 2440 const uint32_t& rs_u, const int32_t& rt_reg, const int32_t& rt,
2439 set_fpu_register(fd_reg, 0); 2441 const uint32_t& rt_u, const int32_t& rd_reg, const int32_t& fr_reg,
2440 } 2442 const int32_t& fs_reg, const int32_t& ft_reg, const int32_t& fd_reg,
2441 break; 2443 int64_t& i64hilo, uint64_t& u64hilo, int32_t& alu_out, bool& do_interrupt,
2442 case CMP_LT: 2444 int32_t& current_pc, int32_t& next_pc, int32_t& return_addr_reg) {
2443 if (fs < ft) { 2445 switch (instr->RsFieldRaw()) {
2444 set_fpu_register(fd_reg, -1); 2446 case CFC1:
2445 } else { 2447 set_register(rt_reg, alu_out);
2446 set_fpu_register(fd_reg, 0); 2448 break;
2447 } 2449 case MFC1:
2448 break; 2450 set_register(rt_reg, alu_out);
2449 case CMP_ULT: 2451 break;
2450 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { 2452 case MFHC1:
2451 set_fpu_register(fd_reg, -1); 2453 set_register(rt_reg, alu_out);
2452 } else { 2454 break;
2453 set_fpu_register(fd_reg, 0); 2455 case CTC1:
2454 } 2456 // At the moment only FCSR is supported.
2455 break; 2457 DCHECK(fs_reg == kFCSRRegister);
2456 case CMP_LE: 2458 FCSR_ = registers_[rt_reg];
2457 if (fs <= ft) { 2459 break;
2458 set_fpu_register(fd_reg, -1); 2460 case MTC1:
2459 } else { 2461 // Hardware writes upper 32-bits to zero on mtc1.
2460 set_fpu_register(fd_reg, 0); 2462 set_fpu_register_hi_word(fs_reg, 0);
2461 } 2463 set_fpu_register_word(fs_reg, registers_[rt_reg]);
2462 break; 2464 break;
2463 case CMP_ULE: 2465 case MTHC1:
2464 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { 2466 set_fpu_register_hi_word(fs_reg, registers_[rt_reg]);
2465 set_fpu_register(fd_reg, -1); 2467 break;
2466 } else { 2468 case S: {
2467 set_fpu_register(fd_reg, 0); 2469 DecodeTypeRegisterSRsType(instr, ft_reg, fs_reg, fd_reg);
2468 } 2470 break;
2469 break; 2471 }
2470 default: // CMP_OR CMP_UNE CMP_NE UNIMPLEMENTED. 2472 case D:
2471 UNREACHABLE(); 2473 DecodeTypeRegisterDRsType(instr, fr_reg, fs_reg, ft_reg, fd_reg);
2472 } 2474 break;
2473 break; 2475 case W:
2474 default: 2476 DecodeTypeRegisterWRsType(instr, alu_out, fd_reg, fs_reg);
2475 UNREACHABLE(); 2477 break;
2476 } 2478 case L:
2477 break; 2479 DecodeTypeRegisterLRsType(instr, ft_reg, fs_reg, fd_reg);
2478 case COP1X: 2480 break;
2479 switch (instr->FunctionFieldRaw()) { 2481 default:
2480 case MADD_D: 2482 UNREACHABLE();
2481 double fr, ft, fs; 2483 }
2482 fr = get_fpu_register_double(fr_reg); 2484 }
2483 fs = get_fpu_register_double(fs_reg); 2485
2484 ft = get_fpu_register_double(ft_reg); 2486
2485 set_fpu_register_double(fd_reg, fs * ft + fr); 2487 void Simulator::DecodeTypeRegisterCOP1X(Instruction* instr,
2486 break; 2488 const int32_t& fr_reg,
2487 default: 2489 const int32_t& fs_reg,
2488 UNREACHABLE(); 2490 const int32_t& ft_reg,
2489 } 2491 const int32_t& fd_reg) {
2490 break; 2492 switch (instr->FunctionFieldRaw()) {
2491 case SPECIAL: 2493 case MADD_D:
2492 switch (instr->FunctionFieldRaw()) { 2494 double fr, ft, fs;
2495 fr = get_fpu_register_double(fr_reg);
2496 fs = get_fpu_register_double(fs_reg);
2497 ft = get_fpu_register_double(ft_reg);
2498 set_fpu_register_double(fd_reg, fs * ft + fr);
2499 break;
2500 default:
2501 UNREACHABLE();
2502 }
2503 }
2504
2505
2506 void Simulator::DecodeTypeRegisterSPECIAL(
2507 Instruction* instr, const int32_t& rs_reg, const int32_t& rs,
2508 const uint32_t& rs_u, const int32_t& rt_reg, const int32_t& rt,
2509 const uint32_t& rt_u, const int32_t& rd_reg, const int32_t& fr_reg,
2510 const int32_t& fs_reg, const int32_t& ft_reg, const int32_t& fd_reg,
2511 int64_t& i64hilo, uint64_t& u64hilo, int32_t& alu_out, bool& do_interrupt,
2512 int32_t& current_pc, int32_t& next_pc, int32_t& return_addr_reg) {
2513 switch (instr->FunctionFieldRaw()) {
2514 case SELEQZ_S:
2515 DCHECK(IsMipsArchVariant(kMips32r6));
2516 set_register(rd_reg, rt == 0 ? rs : 0);
2517 break;
2518 case SELNEZ_S:
2519 DCHECK(IsMipsArchVariant(kMips32r6));
2520 set_register(rd_reg, rt != 0 ? rs : 0);
2521 break;
2493 case JR: { 2522 case JR: {
2494 Instruction* branch_delay_instr = reinterpret_cast<Instruction*>( 2523 Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
2495 current_pc+Instruction::kInstrSize); 2524 current_pc+Instruction::kInstrSize);
2496 BranchDelayInstructionDecode(branch_delay_instr); 2525 BranchDelayInstructionDecode(branch_delay_instr);
2497 set_pc(next_pc); 2526 set_pc(next_pc);
2498 pc_modified_ = true; 2527 pc_modified_ = true;
2499 break; 2528 break;
2500 } 2529 }
2501 case JALR: { 2530 case JALR: {
2502 Instruction* branch_delay_instr = reinterpret_cast<Instruction*>( 2531 Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
2631 if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs); 2660 if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2632 } 2661 }
2633 break; 2662 break;
2634 } 2663 }
2635 case MOVZ: 2664 case MOVZ:
2636 if (!rt) set_register(rd_reg, rs); 2665 if (!rt) set_register(rd_reg, rs);
2637 break; 2666 break;
2638 default: // For other special opcodes we do the default operation. 2667 default: // For other special opcodes we do the default operation.
2639 set_register(rd_reg, alu_out); 2668 set_register(rd_reg, alu_out);
2640 } 2669 }
2670 }
2671
2672
2673 void Simulator::DecodeTypeRegisterSPECIAL2(Instruction* instr,
2674 const int32_t& rd_reg,
2675 int32_t& alu_out) {
2676 switch (instr->FunctionFieldRaw()) {
2677 case MUL:
2678 set_register(rd_reg, alu_out);
2679 // HI and LO are UNPREDICTABLE after the operation.
2680 set_register(LO, Unpredictable);
2681 set_register(HI, Unpredictable);
2682 break;
2683 default: // For other special2 opcodes we do the default operation.
2684 set_register(rd_reg, alu_out);
2685 }
2686 }
2687
2688
2689 void Simulator::DecodeTypeRegisterSPECIAL3(Instruction* instr,
2690 const int32_t& rt_reg,
2691 int32_t& alu_out) {
2692 switch (instr->FunctionFieldRaw()) {
2693 case INS:
2694 // Ins instr leaves result in Rt, rather than Rd.
2695 set_register(rt_reg, alu_out);
2696 break;
2697 case EXT:
2698 // Ext instr leaves result in Rt, rather than Rd.
2699 set_register(rt_reg, alu_out);
2700 break;
2701 default:
2702 UNREACHABLE();
2703 }
2704 }
2705
2706
2707 void Simulator::DecodeTypeRegister(Instruction* instr) {
2708 // Instruction fields.
2709 const Opcode op = instr->OpcodeFieldRaw();
2710 const int32_t rs_reg = instr->RsValue();
2711 const int32_t rs = get_register(rs_reg);
2712 const uint32_t rs_u = static_cast<uint32_t>(rs);
2713 const int32_t rt_reg = instr->RtValue();
2714 const int32_t rt = get_register(rt_reg);
2715 const uint32_t rt_u = static_cast<uint32_t>(rt);
2716 const int32_t rd_reg = instr->RdValue();
2717
2718 const int32_t fr_reg = instr->FrValue();
2719 const int32_t fs_reg = instr->FsValue();
2720 const int32_t ft_reg = instr->FtValue();
2721 const int32_t fd_reg = instr->FdValue();
2722 int64_t i64hilo = 0;
2723 uint64_t u64hilo = 0;
2724
2725 // ALU output.
2726 // It should not be used as is. Instructions using it should always
2727 // initialize it first.
2728 int32_t alu_out = 0x12345678;
2729
2730 // For break and trap instructions.
2731 bool do_interrupt = false;
2732
2733 // For jr and jalr.
2734 // Get current pc.
2735 int32_t current_pc = get_pc();
2736 // Next pc
2737 int32_t next_pc = 0;
2738 int32_t return_addr_reg = 31;
2739
2740 // Set up the variables if needed before executing the instruction.
2741 ConfigureTypeRegister(instr, &alu_out, &i64hilo, &u64hilo, &next_pc,
2742 &return_addr_reg, &do_interrupt);
2743
2744 // ---------- Raise exceptions triggered.
2745 SignalExceptions();
2746
2747 // ---------- Execution.
2748 switch (op) {
2749 case COP1:
2750 DecodeTypeRegisterCOP1(instr, rs_reg, rs, rs_u, rt_reg, rt, rt_u, rd_reg,
2751 fr_reg, fs_reg, ft_reg, fd_reg, i64hilo, u64hilo,
2752 alu_out, do_interrupt, current_pc, next_pc,
2753 return_addr_reg);
2754 break;
2755 case COP1X:
2756 DecodeTypeRegisterCOP1X(instr, fr_reg, fs_reg, ft_reg, fd_reg);
2757 break;
2758 case SPECIAL:
2759 DecodeTypeRegisterSPECIAL(instr, rs_reg, rs, rs_u, rt_reg, rt, rt_u,
2760 rd_reg, fr_reg, fs_reg, ft_reg, fd_reg, i64hilo,
2761 u64hilo, alu_out, do_interrupt, current_pc,
2762 next_pc, return_addr_reg);
2641 break; 2763 break;
2642 case SPECIAL2: 2764 case SPECIAL2:
2643 switch (instr->FunctionFieldRaw()) { 2765 DecodeTypeRegisterSPECIAL2(instr, rd_reg, alu_out);
2644 case MUL:
2645 set_register(rd_reg, alu_out);
2646 // HI and LO are UNPREDICTABLE after the operation.
2647 set_register(LO, Unpredictable);
2648 set_register(HI, Unpredictable);
2649 break;
2650 default: // For other special2 opcodes we do the default operation.
2651 set_register(rd_reg, alu_out);
2652 }
2653 break; 2766 break;
2654 case SPECIAL3: 2767 case SPECIAL3:
2655 switch (instr->FunctionFieldRaw()) { 2768 DecodeTypeRegisterSPECIAL3(instr, rt_reg, alu_out);
2656 case INS:
2657 // Ins instr leaves result in Rt, rather than Rd.
2658 set_register(rt_reg, alu_out);
2659 break;
2660 case EXT:
2661 // Ext instr leaves result in Rt, rather than Rd.
2662 set_register(rt_reg, alu_out);
2663 break;
2664 default:
2665 UNREACHABLE();
2666 }
2667 break; 2769 break;
2668 // Unimplemented opcodes raised an error in the configuration step before, 2770 // Unimplemented opcodes raised an error in the configuration step before,
2669 // so we can use the default here to set the destination register in common 2771 // so we can use the default here to set the destination register in common
2670 // cases. 2772 // cases.
2671 default: 2773 default:
2672 set_register(rd_reg, alu_out); 2774 set_register(rd_reg, alu_out);
2673 } 2775 }
2674 } 2776 }
2675 2777
2676 2778
(...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after
3260 } 3362 }
3261 3363
3262 3364
3263 #undef UNSUPPORTED 3365 #undef UNSUPPORTED
3264 3366
3265 } } // namespace v8::internal 3367 } } // namespace v8::internal
3266 3368
3267 #endif // USE_SIMULATOR 3369 #endif // USE_SIMULATOR
3268 3370
3269 #endif // V8_TARGET_ARCH_MIPS 3371 #endif // V8_TARGET_ARCH_MIPS
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698