OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 2263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2274 // Not sign extending, so load as unsigned. | 2274 // Not sign extending, so load as unsigned. |
2275 uint16_t halfword = ReadH(addr, instr); | 2275 uint16_t halfword = ReadH(addr, instr); |
2276 set_register(rd, halfword); | 2276 set_register(rd, halfword); |
2277 } else { | 2277 } else { |
2278 Debugger dbg(this); | 2278 Debugger dbg(this); |
2279 dbg.Stop(instr); | 2279 dbg.Stop(instr); |
2280 } | 2280 } |
2281 } | 2281 } |
2282 | 2282 |
2283 | 2283 |
2284 // Depending on value of last_bit flag glue register code from vm and m values | |
2285 // (where m is expected to be a single bit). | |
2286 static int GlueRegCode(bool last_bit, int vm, int m) { | |
2287 return last_bit ? ((vm << 1) | m) : ((m << 4) | vm); | |
2288 } | |
2289 | |
2290 | |
2291 // void Simulator::DecodeTypeVFP(Instr* instr) | 2284 // void Simulator::DecodeTypeVFP(Instr* instr) |
2292 // The Following ARMv7 VFPv instructions are currently supported. | 2285 // The Following ARMv7 VFPv instructions are currently supported. |
2293 // vmov :Sn = Rt | 2286 // vmov :Sn = Rt |
2294 // vmov :Rt = Sn | 2287 // vmov :Rt = Sn |
2295 // vcvt: Dd = Sm | 2288 // vcvt: Dd = Sm |
2296 // vcvt: Sd = Dm | 2289 // vcvt: Sd = Dm |
2297 // Dd = vadd(Dn, Dm) | 2290 // Dd = vadd(Dn, Dm) |
2298 // Dd = vsub(Dn, Dm) | 2291 // Dd = vsub(Dn, Dm) |
2299 // Dd = vmul(Dn, Dm) | 2292 // Dd = vmul(Dn, Dm) |
2300 // Dd = vdiv(Dn, Dm) | 2293 // Dd = vdiv(Dn, Dm) |
2301 // vcmp(Dd, Dm) | 2294 // vcmp(Dd, Dm) |
2302 // vmrs | 2295 // vmrs |
2303 // Dd = vsqrt(Dm) | 2296 // Dd = vsqrt(Dm) |
2304 void Simulator::DecodeTypeVFP(Instr* instr) { | 2297 void Simulator::DecodeTypeVFP(Instr* instr) { |
2305 ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) ); | 2298 ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) ); |
2306 ASSERT(instr->Bits(11, 9) == 0x5); | 2299 ASSERT(instr->Bits(11, 9) == 0x5); |
2307 | 2300 |
2308 int vm = instr->VmField(); | 2301 // Obtain double precision register codes. |
2309 int vd = instr->VdField(); | 2302 int vm = instr->VFPMRegCode(kDoublePrecision); |
2310 int vn = instr->VnField(); | 2303 int vd = instr->VFPDRegCode(kDoublePrecision); |
| 2304 int vn = instr->VFPNRegCode(kDoublePrecision); |
2311 | 2305 |
2312 if (instr->Bit(4) == 0) { | 2306 if (instr->Bit(4) == 0) { |
2313 if (instr->Opc1Field() == 0x7) { | 2307 if (instr->Opc1Field() == 0x7) { |
2314 // Other data processing instructions | 2308 // Other data processing instructions |
2315 if ((instr->Opc2Field() == 0x0) && (instr->Opc3Field() == 0x1)) { | 2309 if ((instr->Opc2Field() == 0x0) && (instr->Opc3Field() == 0x1)) { |
2316 // vmov register to register. | 2310 // vmov register to register. |
2317 if (instr->SzField() == 0x1) { | 2311 if (instr->SzField() == 0x1) { |
2318 set_d_register_from_double(vd, get_double_from_d_register(vm)); | 2312 int m = instr->VFPMRegCode(kDoublePrecision); |
| 2313 int d = instr->VFPDRegCode(kDoublePrecision); |
| 2314 set_d_register_from_double(d, get_double_from_d_register(m)); |
2319 } else { | 2315 } else { |
2320 set_s_register_from_float(vd, get_float_from_s_register(vm)); | 2316 int m = instr->VFPMRegCode(kSinglePrecision); |
| 2317 int d = instr->VFPDRegCode(kSinglePrecision); |
| 2318 set_s_register_from_float(d, get_float_from_s_register(m)); |
2321 } | 2319 } |
2322 } else if ((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3)) { | 2320 } else if ((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3)) { |
2323 DecodeVCVTBetweenDoubleAndSingle(instr); | 2321 DecodeVCVTBetweenDoubleAndSingle(instr); |
2324 } else if ((instr->Opc2Field() == 0x8) && (instr->Opc3Field() & 0x1)) { | 2322 } else if ((instr->Opc2Field() == 0x8) && (instr->Opc3Field() & 0x1)) { |
2325 DecodeVCVTBetweenFloatingPointAndInteger(instr); | 2323 DecodeVCVTBetweenFloatingPointAndInteger(instr); |
2326 } else if (((instr->Opc2Field() >> 1) == 0x6) && | 2324 } else if (((instr->Opc2Field() >> 1) == 0x6) && |
2327 (instr->Opc3Field() & 0x1)) { | 2325 (instr->Opc3Field() & 0x1)) { |
2328 DecodeVCVTBetweenFloatingPointAndInteger(instr); | 2326 DecodeVCVTBetweenFloatingPointAndInteger(instr); |
2329 } else if (((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) && | 2327 } else if (((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) && |
2330 (instr->Opc3Field() & 0x1)) { | 2328 (instr->Opc3Field() & 0x1)) { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2403 } | 2401 } |
2404 } | 2402 } |
2405 } | 2403 } |
2406 | 2404 |
2407 | 2405 |
2408 void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instr* instr) { | 2406 void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instr* instr) { |
2409 ASSERT((instr->Bit(4) == 1) && (instr->VCField() == 0x0) && | 2407 ASSERT((instr->Bit(4) == 1) && (instr->VCField() == 0x0) && |
2410 (instr->VAField() == 0x0)); | 2408 (instr->VAField() == 0x0)); |
2411 | 2409 |
2412 int t = instr->RtField(); | 2410 int t = instr->RtField(); |
2413 int n = GlueRegCode(true, instr->VnField(), instr->NField()); | 2411 int n = instr->VFPNRegCode(kSinglePrecision); |
2414 bool to_arm_register = (instr->VLField() == 0x1); | 2412 bool to_arm_register = (instr->VLField() == 0x1); |
2415 | 2413 |
2416 if (to_arm_register) { | 2414 if (to_arm_register) { |
2417 int32_t int_value = get_sinteger_from_s_register(n); | 2415 int32_t int_value = get_sinteger_from_s_register(n); |
2418 set_register(t, int_value); | 2416 set_register(t, int_value); |
2419 } else { | 2417 } else { |
2420 int32_t rs_val = get_register(t); | 2418 int32_t rs_val = get_register(t); |
2421 set_s_register_from_sinteger(n, rs_val); | 2419 set_s_register_from_sinteger(n, rs_val); |
2422 } | 2420 } |
2423 } | 2421 } |
2424 | 2422 |
2425 | 2423 |
2426 void Simulator::DecodeVCMP(Instr* instr) { | 2424 void Simulator::DecodeVCMP(Instr* instr) { |
2427 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7)); | 2425 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7)); |
2428 ASSERT(((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) && | 2426 ASSERT(((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) && |
2429 (instr->Opc3Field() & 0x1)); | 2427 (instr->Opc3Field() & 0x1)); |
| 2428 // Comparison. |
2430 | 2429 |
2431 // Comparison. | 2430 VFPRegPrecision precision = kSinglePrecision; |
2432 bool dp_operation = (instr->SzField() == 1); | 2431 if (instr->SzField() == 1) { |
| 2432 precision = kDoublePrecision; |
| 2433 } |
2433 | 2434 |
2434 if (instr->Bit(7) != 0) { | 2435 if (instr->Bit(7) != 0) { |
2435 // Raising exceptions for quiet NaNs are not supported. | 2436 // Raising exceptions for quiet NaNs are not supported. |
2436 UNIMPLEMENTED(); // Not used by V8. | 2437 UNIMPLEMENTED(); // Not used by V8. |
2437 } | 2438 } |
2438 | 2439 |
2439 int d = GlueRegCode(!dp_operation, instr->VdField(), instr->DField()); | 2440 int d = instr->VFPDRegCode(precision); |
2440 int m = 0; | 2441 int m = 0; |
2441 if (instr->Opc2Field() == 0x4) { | 2442 if (instr->Opc2Field() == 0x4) { |
2442 m = GlueRegCode(!dp_operation, instr->VmField(), instr->MField()); | 2443 m = instr->VFPMRegCode(precision); |
2443 } | 2444 } |
2444 | 2445 |
2445 if (dp_operation) { | 2446 if (precision == kDoublePrecision) { |
2446 double dd_value = get_double_from_d_register(d); | 2447 double dd_value = get_double_from_d_register(d); |
2447 double dm_value = 0.0; | 2448 double dm_value = 0.0; |
2448 if (instr->Opc2Field() == 0x4) { | 2449 if (instr->Opc2Field() == 0x4) { |
2449 dm_value = get_double_from_d_register(m); | 2450 dm_value = get_double_from_d_register(m); |
2450 } | 2451 } |
2451 | 2452 |
2452 Compute_FPSCR_Flags(dd_value, dm_value); | 2453 Compute_FPSCR_Flags(dd_value, dm_value); |
2453 } else { | 2454 } else { |
2454 UNIMPLEMENTED(); // Not used by V8. | 2455 UNIMPLEMENTED(); // Not used by V8. |
2455 } | 2456 } |
2456 } | 2457 } |
2457 | 2458 |
2458 | 2459 |
2459 void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instr* instr) { | 2460 void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instr* instr) { |
2460 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7)); | 2461 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7)); |
2461 ASSERT((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3)); | 2462 ASSERT((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3)); |
2462 | 2463 |
2463 bool double_to_single = (instr->SzField() == 1); | 2464 VFPRegPrecision dst_precision = kDoublePrecision; |
2464 int dst = GlueRegCode(double_to_single, instr->VdField(), instr->DField()); | 2465 VFPRegPrecision src_precision = kSinglePrecision; |
2465 int src = GlueRegCode(!double_to_single, instr->VmField(), instr->MField()); | 2466 if (instr->SzField() == 1) { |
| 2467 dst_precision = kSinglePrecision; |
| 2468 src_precision = kDoublePrecision; |
| 2469 } |
2466 | 2470 |
2467 if (double_to_single) { | 2471 int dst = instr->VFPDRegCode(dst_precision); |
| 2472 int src = instr->VFPMRegCode(src_precision); |
| 2473 |
| 2474 if (dst_precision == kSinglePrecision) { |
2468 double val = get_double_from_d_register(src); | 2475 double val = get_double_from_d_register(src); |
2469 set_s_register_from_float(dst, static_cast<float>(val)); | 2476 set_s_register_from_float(dst, static_cast<float>(val)); |
2470 } else { | 2477 } else { |
2471 float val = get_float_from_s_register(src); | 2478 float val = get_float_from_s_register(src); |
2472 set_d_register_from_double(dst, static_cast<double>(val)); | 2479 set_d_register_from_double(dst, static_cast<double>(val)); |
2473 } | 2480 } |
2474 } | 2481 } |
2475 | 2482 |
2476 | 2483 |
2477 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instr* instr) { | 2484 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instr* instr) { |
2478 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7)); | 2485 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7)); |
2479 ASSERT(((instr->Opc2Field() == 0x8) && (instr->Opc3Field() & 0x1)) || | 2486 ASSERT(((instr->Opc2Field() == 0x8) && (instr->Opc3Field() & 0x1)) || |
2480 (((instr->Opc2Field() >> 1) == 0x6) && (instr->Opc3Field() & 0x1))); | 2487 (((instr->Opc2Field() >> 1) == 0x6) && (instr->Opc3Field() & 0x1))); |
2481 | 2488 |
2482 // Conversion between floating-point and integer. | 2489 // Conversion between floating-point and integer. |
2483 int vd = instr->VdField(); | 2490 bool to_integer = (instr->Bit(18) == 1); |
2484 int d = instr->DField(); | |
2485 int vm = instr->VmField(); | |
2486 int m = instr->MField(); | |
2487 | 2491 |
2488 bool to_integer = (instr->Bit(18) == 1); | 2492 VFPRegPrecision src_precision = kSinglePrecision; |
2489 bool dp_operation = (instr->SzField() == 1); | 2493 if (instr->SzField() == 1) { |
| 2494 src_precision = kDoublePrecision; |
| 2495 } |
| 2496 |
2490 if (to_integer) { | 2497 if (to_integer) { |
2491 bool unsigned_integer = (instr->Bit(16) == 0); | 2498 bool unsigned_integer = (instr->Bit(16) == 0); |
2492 if (instr->Bit(7) != 1) { | 2499 if (instr->Bit(7) != 1) { |
2493 // Only rounding towards zero supported. | 2500 // Only rounding towards zero supported. |
2494 UNIMPLEMENTED(); // Not used by V8. | 2501 UNIMPLEMENTED(); // Not used by V8. |
2495 } | 2502 } |
2496 | 2503 |
2497 int dst = GlueRegCode(true, vd, d); | 2504 int dst = instr->VFPDRegCode(kSinglePrecision); |
2498 int src = GlueRegCode(!dp_operation, vm, m); | 2505 int src = instr->VFPMRegCode(src_precision); |
2499 | 2506 |
2500 if (dp_operation) { | 2507 if (src_precision == kDoublePrecision) { |
2501 double val = get_double_from_d_register(src); | 2508 double val = get_double_from_d_register(src); |
2502 | 2509 |
2503 int sint = unsigned_integer ? static_cast<uint32_t>(val) : | 2510 int sint = unsigned_integer ? static_cast<uint32_t>(val) : |
2504 static_cast<int32_t>(val); | 2511 static_cast<int32_t>(val); |
2505 | 2512 |
2506 set_s_register_from_sinteger(dst, sint); | 2513 set_s_register_from_sinteger(dst, sint); |
2507 } else { | 2514 } else { |
2508 float val = get_float_from_s_register(src); | 2515 float val = get_float_from_s_register(src); |
2509 | 2516 |
2510 int sint = unsigned_integer ? static_cast<uint32_t>(val) : | 2517 int sint = unsigned_integer ? static_cast<uint32_t>(val) : |
2511 static_cast<int32_t>(val); | 2518 static_cast<int32_t>(val); |
2512 | 2519 |
2513 set_s_register_from_sinteger(dst, sint); | 2520 set_s_register_from_sinteger(dst, sint); |
2514 } | 2521 } |
2515 } else { | 2522 } else { |
2516 bool unsigned_integer = (instr->Bit(7) == 0); | 2523 bool unsigned_integer = (instr->Bit(7) == 0); |
2517 | 2524 |
2518 int dst = GlueRegCode(!dp_operation, vd, d); | 2525 int dst = instr->VFPDRegCode(src_precision); |
2519 int src = GlueRegCode(true, vm, m); | 2526 int src = instr->VFPMRegCode(kSinglePrecision); |
2520 | 2527 |
2521 int val = get_sinteger_from_s_register(src); | 2528 int val = get_sinteger_from_s_register(src); |
2522 | 2529 |
2523 if (dp_operation) { | 2530 if (src_precision == kDoublePrecision) { |
2524 if (unsigned_integer) { | 2531 if (unsigned_integer) { |
2525 set_d_register_from_double(dst, | 2532 set_d_register_from_double(dst, |
2526 static_cast<double>((uint32_t)val)); | 2533 static_cast<double>((uint32_t)val)); |
2527 } else { | 2534 } else { |
2528 set_d_register_from_double(dst, static_cast<double>(val)); | 2535 set_d_register_from_double(dst, static_cast<double>(val)); |
2529 } | 2536 } |
2530 } else { | 2537 } else { |
2531 if (unsigned_integer) { | 2538 if (unsigned_integer) { |
2532 set_s_register_from_float(dst, | 2539 set_s_register_from_float(dst, |
2533 static_cast<float>((uint32_t)val)); | 2540 static_cast<float>((uint32_t)val)); |
(...skipping 10 matching lines...) Expand all Loading... |
2544 // Dm = vmov(Rt, Rt2) | 2551 // Dm = vmov(Rt, Rt2) |
2545 // <Rt, Rt2> = vmov(Dm) | 2552 // <Rt, Rt2> = vmov(Dm) |
2546 // Ddst = MEM(Rbase + 4*offset). | 2553 // Ddst = MEM(Rbase + 4*offset). |
2547 // MEM(Rbase + 4*offset) = Dsrc. | 2554 // MEM(Rbase + 4*offset) = Dsrc. |
2548 void Simulator::DecodeType6CoprocessorIns(Instr* instr) { | 2555 void Simulator::DecodeType6CoprocessorIns(Instr* instr) { |
2549 ASSERT((instr->TypeField() == 6)); | 2556 ASSERT((instr->TypeField() == 6)); |
2550 | 2557 |
2551 if (instr->CoprocessorField() == 0xA) { | 2558 if (instr->CoprocessorField() == 0xA) { |
2552 switch (instr->OpcodeField()) { | 2559 switch (instr->OpcodeField()) { |
2553 case 0x8: | 2560 case 0x8: |
2554 case 0xC: { // Load and store float to memory. | 2561 case 0xA: |
| 2562 case 0xC: |
| 2563 case 0xE: { // Load and store single precision float to memory. |
2555 int rn = instr->RnField(); | 2564 int rn = instr->RnField(); |
2556 int vd = instr->VdField(); | 2565 int vd = instr->VFPDRegCode(kSinglePrecision); |
2557 int offset = instr->Immed8Field(); | 2566 int offset = instr->Immed8Field(); |
2558 if (!instr->HasU()) { | 2567 if (!instr->HasU()) { |
2559 offset = -offset; | 2568 offset = -offset; |
2560 } | 2569 } |
2561 | 2570 |
2562 int32_t address = get_register(rn) + 4 * offset; | 2571 int32_t address = get_register(rn) + 4 * offset; |
2563 if (instr->HasL()) { | 2572 if (instr->HasL()) { |
2564 // Load double from memory: vldr. | 2573 // Load double from memory: vldr. |
2565 set_s_register_from_sinteger(vd, ReadW(address, instr)); | 2574 set_s_register_from_sinteger(vd, ReadW(address, instr)); |
2566 } else { | 2575 } else { |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2825 uintptr_t address = *stack_slot; | 2834 uintptr_t address = *stack_slot; |
2826 set_register(sp, current_sp + sizeof(uintptr_t)); | 2835 set_register(sp, current_sp + sizeof(uintptr_t)); |
2827 return address; | 2836 return address; |
2828 } | 2837 } |
2829 | 2838 |
2830 } } // namespace assembler::arm | 2839 } } // namespace assembler::arm |
2831 | 2840 |
2832 #endif // __arm__ | 2841 #endif // __arm__ |
2833 | 2842 |
2834 #endif // V8_TARGET_ARCH_ARM | 2843 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |