| 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 722 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 733 | 733 |
| 734 // When the generated code calls an external reference we need to catch that in | 734 // When the generated code calls an external reference we need to catch that in |
| 735 // the simulator. The external reference will be a function compiled for the | 735 // the simulator. The external reference will be a function compiled for the |
| 736 // host architecture. We need to call that function instead of trying to | 736 // host architecture. We need to call that function instead of trying to |
| 737 // execute it with the simulator. We do that by redirecting the external | 737 // execute it with the simulator. We do that by redirecting the external |
| 738 // reference to a svc (Supervisor Call) instruction that is handled by | 738 // reference to a svc (Supervisor Call) instruction that is handled by |
| 739 // the simulator. We write the original destination of the jump just at a known | 739 // the simulator. We write the original destination of the jump just at a known |
| 740 // offset from the svc instruction so the simulator knows what to call. | 740 // offset from the svc instruction so the simulator knows what to call. |
| 741 class Redirection { | 741 class Redirection { |
| 742 public: | 742 public: |
| 743 Redirection(void* external_function, bool fp_return) | 743 Redirection(void* external_function, ExternalReference::Type type) |
| 744 : external_function_(external_function), | 744 : external_function_(external_function), |
| 745 swi_instruction_(al | (0xf*B24) | kCallRtRedirected), | 745 swi_instruction_(al | (0xf*B24) | kCallRtRedirected), |
| 746 fp_return_(fp_return), | 746 type_(type), |
| 747 next_(NULL) { | 747 next_(NULL) { |
| 748 Isolate* isolate = Isolate::Current(); | 748 Isolate* isolate = Isolate::Current(); |
| 749 next_ = isolate->simulator_redirection(); | 749 next_ = isolate->simulator_redirection(); |
| 750 Simulator::current(isolate)-> | 750 Simulator::current(isolate)-> |
| 751 FlushICache(isolate->simulator_i_cache(), | 751 FlushICache(isolate->simulator_i_cache(), |
| 752 reinterpret_cast<void*>(&swi_instruction_), | 752 reinterpret_cast<void*>(&swi_instruction_), |
| 753 Instruction::kInstrSize); | 753 Instruction::kInstrSize); |
| 754 isolate->set_simulator_redirection(this); | 754 isolate->set_simulator_redirection(this); |
| 755 } | 755 } |
| 756 | 756 |
| 757 void* address_of_swi_instruction() { | 757 void* address_of_swi_instruction() { |
| 758 return reinterpret_cast<void*>(&swi_instruction_); | 758 return reinterpret_cast<void*>(&swi_instruction_); |
| 759 } | 759 } |
| 760 | 760 |
| 761 void* external_function() { return external_function_; } | 761 void* external_function() { return external_function_; } |
| 762 bool fp_return() { return fp_return_; } | 762 ExternalReference::Type type() { return type_; } |
| 763 | 763 |
| 764 static Redirection* Get(void* external_function, bool fp_return) { | 764 static Redirection* Get(void* external_function, |
| 765 ExternalReference::Type type) { |
| 765 Isolate* isolate = Isolate::Current(); | 766 Isolate* isolate = Isolate::Current(); |
| 766 Redirection* current = isolate->simulator_redirection(); | 767 Redirection* current = isolate->simulator_redirection(); |
| 767 for (; current != NULL; current = current->next_) { | 768 for (; current != NULL; current = current->next_) { |
| 768 if (current->external_function_ == external_function) return current; | 769 if (current->external_function_ == external_function) return current; |
| 769 } | 770 } |
| 770 return new Redirection(external_function, fp_return); | 771 return new Redirection(external_function, type); |
| 771 } | 772 } |
| 772 | 773 |
| 773 static Redirection* FromSwiInstruction(Instruction* swi_instruction) { | 774 static Redirection* FromSwiInstruction(Instruction* swi_instruction) { |
| 774 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction); | 775 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction); |
| 775 char* addr_of_redirection = | 776 char* addr_of_redirection = |
| 776 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_); | 777 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_); |
| 777 return reinterpret_cast<Redirection*>(addr_of_redirection); | 778 return reinterpret_cast<Redirection*>(addr_of_redirection); |
| 778 } | 779 } |
| 779 | 780 |
| 780 private: | 781 private: |
| 781 void* external_function_; | 782 void* external_function_; |
| 782 uint32_t swi_instruction_; | 783 uint32_t swi_instruction_; |
| 783 bool fp_return_; | 784 ExternalReference::Type type_; |
| 784 Redirection* next_; | 785 Redirection* next_; |
| 785 }; | 786 }; |
| 786 | 787 |
| 787 | 788 |
| 788 void* Simulator::RedirectExternalReference(void* external_function, | 789 void* Simulator::RedirectExternalReference(void* external_function, |
| 789 bool fp_return) { | 790 ExternalReference::Type type) { |
| 790 Redirection* redirection = Redirection::Get(external_function, fp_return); | 791 Redirection* redirection = Redirection::Get(external_function, type); |
| 791 return redirection->address_of_swi_instruction(); | 792 return redirection->address_of_swi_instruction(); |
| 792 } | 793 } |
| 793 | 794 |
| 794 | 795 |
| 795 // Get the active Simulator for the current thread. | 796 // Get the active Simulator for the current thread. |
| 796 Simulator* Simulator::current(Isolate* isolate) { | 797 Simulator* Simulator::current(Isolate* isolate) { |
| 797 v8::internal::Isolate::PerIsolateThreadData* isolate_data = | 798 v8::internal::Isolate::PerIsolateThreadData* isolate_data = |
| 798 Isolate::CurrentPerIsolateThreadData(); | 799 Isolate::CurrentPerIsolateThreadData(); |
| 799 if (isolate_data == NULL) { | 800 if (isolate_data == NULL) { |
| 800 Isolate::EnterDefaultIsolate(); | 801 Isolate::EnterDefaultIsolate(); |
| (...skipping 722 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1523 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, | 1524 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, |
| 1524 int32_t arg1, | 1525 int32_t arg1, |
| 1525 int32_t arg2, | 1526 int32_t arg2, |
| 1526 int32_t arg3, | 1527 int32_t arg3, |
| 1527 int32_t arg4); | 1528 int32_t arg4); |
| 1528 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0, | 1529 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0, |
| 1529 int32_t arg1, | 1530 int32_t arg1, |
| 1530 int32_t arg2, | 1531 int32_t arg2, |
| 1531 int32_t arg3); | 1532 int32_t arg3); |
| 1532 | 1533 |
| 1534 // This signature supports direct call in to API function native callback |
| 1535 // (refer to InvocationCallback in v8.h). |
| 1536 typedef v8::Handle<v8::Value> (*SimulatorRuntimeApiCall)(int32_t arg0); |
| 1533 | 1537 |
| 1534 // Software interrupt instructions are used by the simulator to call into the | 1538 // Software interrupt instructions are used by the simulator to call into the |
| 1535 // C-based V8 runtime. | 1539 // C-based V8 runtime. |
| 1536 void Simulator::SoftwareInterrupt(Instruction* instr) { | 1540 void Simulator::SoftwareInterrupt(Instruction* instr) { |
| 1537 int svc = instr->SvcValue(); | 1541 int svc = instr->SvcValue(); |
| 1538 switch (svc) { | 1542 switch (svc) { |
| 1539 case kCallRtRedirected: { | 1543 case kCallRtRedirected: { |
| 1540 // Check if stack is aligned. Error if not aligned is reported below to | 1544 // Check if stack is aligned. Error if not aligned is reported below to |
| 1541 // include information on the function called. | 1545 // include information on the function called. |
| 1542 bool stack_aligned = | 1546 bool stack_aligned = |
| 1543 (get_register(sp) | 1547 (get_register(sp) |
| 1544 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0; | 1548 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0; |
| 1545 Redirection* redirection = Redirection::FromSwiInstruction(instr); | 1549 Redirection* redirection = Redirection::FromSwiInstruction(instr); |
| 1546 int32_t arg0 = get_register(r0); | 1550 int32_t arg0 = get_register(r0); |
| 1547 int32_t arg1 = get_register(r1); | 1551 int32_t arg1 = get_register(r1); |
| 1548 int32_t arg2 = get_register(r2); | 1552 int32_t arg2 = get_register(r2); |
| 1549 int32_t arg3 = get_register(r3); | 1553 int32_t arg3 = get_register(r3); |
| 1550 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); | 1554 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); |
| 1551 int32_t arg4 = *stack_pointer; | 1555 int32_t arg4 = *stack_pointer; |
| 1552 // This is dodgy but it works because the C entry stubs are never moved. | 1556 // This is dodgy but it works because the C entry stubs are never moved. |
| 1553 // See comment in codegen-arm.cc and bug 1242173. | 1557 // See comment in codegen-arm.cc and bug 1242173. |
| 1554 int32_t saved_lr = get_register(lr); | 1558 int32_t saved_lr = get_register(lr); |
| 1555 if (redirection->fp_return()) { | 1559 intptr_t external = |
| 1556 intptr_t external = | 1560 reinterpret_cast<intptr_t>(redirection->external_function()); |
| 1557 reinterpret_cast<intptr_t>(redirection->external_function()); | 1561 if (redirection->type() == ExternalReference::FP_RETURN_CALL) { |
| 1558 SimulatorRuntimeFPCall target = | 1562 SimulatorRuntimeFPCall target = |
| 1559 reinterpret_cast<SimulatorRuntimeFPCall>(external); | 1563 reinterpret_cast<SimulatorRuntimeFPCall>(external); |
| 1560 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | 1564 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { |
| 1561 double x, y; | 1565 double x, y; |
| 1562 GetFpArgs(&x, &y); | 1566 GetFpArgs(&x, &y); |
| 1563 PrintF("Call to host function at %p with args %f, %f", | 1567 PrintF("Call to host function at %p with args %f, %f", |
| 1564 FUNCTION_ADDR(target), x, y); | 1568 FUNCTION_ADDR(target), x, y); |
| 1565 if (!stack_aligned) { | 1569 if (!stack_aligned) { |
| 1566 PrintF(" with unaligned stack %08x\n", get_register(sp)); | 1570 PrintF(" with unaligned stack %08x\n", get_register(sp)); |
| 1567 } | 1571 } |
| 1568 PrintF("\n"); | 1572 PrintF("\n"); |
| 1569 } | 1573 } |
| 1570 CHECK(stack_aligned); | 1574 CHECK(stack_aligned); |
| 1571 double result = target(arg0, arg1, arg2, arg3); | 1575 double result = target(arg0, arg1, arg2, arg3); |
| 1572 SetFpResult(result); | 1576 SetFpResult(result); |
| 1577 } else if (redirection->type() == ExternalReference::DIRECT_CALL) { |
| 1578 SimulatorRuntimeApiCall target = |
| 1579 reinterpret_cast<SimulatorRuntimeApiCall>(external); |
| 1580 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { |
| 1581 PrintF( |
| 1582 "Call to host function at %p args %08x", |
| 1583 FUNCTION_ADDR(target), |
| 1584 arg0); |
| 1585 if (!stack_aligned) { |
| 1586 PrintF(" with unaligned stack %08x\n", get_register(sp)); |
| 1587 } |
| 1588 PrintF("\n"); |
| 1589 } |
| 1590 CHECK(stack_aligned); |
| 1591 v8::Handle<v8::Value> result = target(arg0); |
| 1592 if (::v8::internal::FLAG_trace_sim) { |
| 1593 PrintF("Returned %p\n", reinterpret_cast<void *>(*result)); |
| 1594 } |
| 1595 set_register(r0, (int32_t) *result); |
| 1573 } else { | 1596 } else { |
| 1574 intptr_t external = | 1597 // builtin call. |
| 1575 reinterpret_cast<int32_t>(redirection->external_function()); | 1598 ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL); |
| 1576 SimulatorRuntimeCall target = | 1599 SimulatorRuntimeCall target = |
| 1577 reinterpret_cast<SimulatorRuntimeCall>(external); | 1600 reinterpret_cast<SimulatorRuntimeCall>(external); |
| 1578 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | 1601 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { |
| 1579 PrintF( | 1602 PrintF( |
| 1580 "Call to host function at %p args %08x, %08x, %08x, %08x, %0xc", | 1603 "Call to host function at %p args %08x, %08x, %08x, %08x, %0xc", |
| 1581 FUNCTION_ADDR(target), | 1604 FUNCTION_ADDR(target), |
| 1582 arg0, | 1605 arg0, |
| 1583 arg1, | 1606 arg1, |
| 1584 arg2, | 1607 arg2, |
| 1585 arg3, | 1608 arg3, |
| (...skipping 854 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2440 // vmov register to register. | 2463 // vmov register to register. |
| 2441 if (instr->SzValue() == 0x1) { | 2464 if (instr->SzValue() == 0x1) { |
| 2442 int m = instr->VFPMRegValue(kDoublePrecision); | 2465 int m = instr->VFPMRegValue(kDoublePrecision); |
| 2443 int d = instr->VFPDRegValue(kDoublePrecision); | 2466 int d = instr->VFPDRegValue(kDoublePrecision); |
| 2444 set_d_register_from_double(d, get_double_from_d_register(m)); | 2467 set_d_register_from_double(d, get_double_from_d_register(m)); |
| 2445 } else { | 2468 } else { |
| 2446 int m = instr->VFPMRegValue(kSinglePrecision); | 2469 int m = instr->VFPMRegValue(kSinglePrecision); |
| 2447 int d = instr->VFPDRegValue(kSinglePrecision); | 2470 int d = instr->VFPDRegValue(kSinglePrecision); |
| 2448 set_s_register_from_float(d, get_float_from_s_register(m)); | 2471 set_s_register_from_float(d, get_float_from_s_register(m)); |
| 2449 } | 2472 } |
| 2473 } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) { |
| 2474 // vabs |
| 2475 double dm_value = get_double_from_d_register(vm); |
| 2476 double dd_value = fabs(dm_value); |
| 2477 set_d_register_from_double(vd, dd_value); |
| 2450 } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) { | 2478 } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) { |
| 2451 DecodeVCVTBetweenDoubleAndSingle(instr); | 2479 DecodeVCVTBetweenDoubleAndSingle(instr); |
| 2452 } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) { | 2480 } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) { |
| 2453 DecodeVCVTBetweenFloatingPointAndInteger(instr); | 2481 DecodeVCVTBetweenFloatingPointAndInteger(instr); |
| 2454 } else if (((instr->Opc2Value() >> 1) == 0x6) && | 2482 } else if (((instr->Opc2Value() >> 1) == 0x6) && |
| 2455 (instr->Opc3Value() & 0x1)) { | 2483 (instr->Opc3Value() & 0x1)) { |
| 2456 DecodeVCVTBetweenFloatingPointAndInteger(instr); | 2484 DecodeVCVTBetweenFloatingPointAndInteger(instr); |
| 2457 } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && | 2485 } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && |
| 2458 (instr->Opc3Value() & 0x1)) { | 2486 (instr->Opc3Value() & 0x1)) { |
| 2459 DecodeVCMP(instr); | 2487 DecodeVCMP(instr); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2529 // Emulate FPSCR from the Simulator flags. | 2557 // Emulate FPSCR from the Simulator flags. |
| 2530 uint32_t fpscr = (n_flag_FPSCR_ << 31) | | 2558 uint32_t fpscr = (n_flag_FPSCR_ << 31) | |
| 2531 (z_flag_FPSCR_ << 30) | | 2559 (z_flag_FPSCR_ << 30) | |
| 2532 (c_flag_FPSCR_ << 29) | | 2560 (c_flag_FPSCR_ << 29) | |
| 2533 (v_flag_FPSCR_ << 28) | | 2561 (v_flag_FPSCR_ << 28) | |
| 2534 (inexact_vfp_flag_ << 4) | | 2562 (inexact_vfp_flag_ << 4) | |
| 2535 (underflow_vfp_flag_ << 3) | | 2563 (underflow_vfp_flag_ << 3) | |
| 2536 (overflow_vfp_flag_ << 2) | | 2564 (overflow_vfp_flag_ << 2) | |
| 2537 (div_zero_vfp_flag_ << 1) | | 2565 (div_zero_vfp_flag_ << 1) | |
| 2538 (inv_op_vfp_flag_ << 0) | | 2566 (inv_op_vfp_flag_ << 0) | |
| 2539 (FPSCR_rounding_mode_ << 22); | 2567 (FPSCR_rounding_mode_); |
| 2540 set_register(rt, fpscr); | 2568 set_register(rt, fpscr); |
| 2541 } | 2569 } |
| 2542 } else if ((instr->VLValue() == 0x0) && | 2570 } else if ((instr->VLValue() == 0x0) && |
| 2543 (instr->VCValue() == 0x0) && | 2571 (instr->VCValue() == 0x0) && |
| 2544 (instr->VAValue() == 0x7) && | 2572 (instr->VAValue() == 0x7) && |
| 2545 (instr->Bits(19, 16) == 0x1)) { | 2573 (instr->Bits(19, 16) == 0x1)) { |
| 2546 // vmsr | 2574 // vmsr |
| 2547 uint32_t rt = instr->RtValue(); | 2575 uint32_t rt = instr->RtValue(); |
| 2548 if (rt == pc) { | 2576 if (rt == pc) { |
| 2549 UNREACHABLE(); | 2577 UNREACHABLE(); |
| 2550 } else { | 2578 } else { |
| 2551 uint32_t rt_value = get_register(rt); | 2579 uint32_t rt_value = get_register(rt); |
| 2552 n_flag_FPSCR_ = (rt_value >> 31) & 1; | 2580 n_flag_FPSCR_ = (rt_value >> 31) & 1; |
| 2553 z_flag_FPSCR_ = (rt_value >> 30) & 1; | 2581 z_flag_FPSCR_ = (rt_value >> 30) & 1; |
| 2554 c_flag_FPSCR_ = (rt_value >> 29) & 1; | 2582 c_flag_FPSCR_ = (rt_value >> 29) & 1; |
| 2555 v_flag_FPSCR_ = (rt_value >> 28) & 1; | 2583 v_flag_FPSCR_ = (rt_value >> 28) & 1; |
| 2556 inexact_vfp_flag_ = (rt_value >> 4) & 1; | 2584 inexact_vfp_flag_ = (rt_value >> 4) & 1; |
| 2557 underflow_vfp_flag_ = (rt_value >> 3) & 1; | 2585 underflow_vfp_flag_ = (rt_value >> 3) & 1; |
| 2558 overflow_vfp_flag_ = (rt_value >> 2) & 1; | 2586 overflow_vfp_flag_ = (rt_value >> 2) & 1; |
| 2559 div_zero_vfp_flag_ = (rt_value >> 1) & 1; | 2587 div_zero_vfp_flag_ = (rt_value >> 1) & 1; |
| 2560 inv_op_vfp_flag_ = (rt_value >> 0) & 1; | 2588 inv_op_vfp_flag_ = (rt_value >> 0) & 1; |
| 2561 FPSCR_rounding_mode_ = | 2589 FPSCR_rounding_mode_ = |
| 2562 static_cast<FPSCRRoundingModes>((rt_value >> 22) & 3); | 2590 static_cast<VFPRoundingMode>((rt_value) & kVFPRoundingModeMask); |
| 2563 } | 2591 } |
| 2564 } else { | 2592 } else { |
| 2565 UNIMPLEMENTED(); // Not used by V8. | 2593 UNIMPLEMENTED(); // Not used by V8. |
| 2566 } | 2594 } |
| 2567 } | 2595 } |
| 2568 } | 2596 } |
| 2569 | 2597 |
| 2570 | 2598 |
| 2571 void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters( | 2599 void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters( |
| 2572 Instruction* instr) { | 2600 Instruction* instr) { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2641 | 2669 |
| 2642 if (dst_precision == kSinglePrecision) { | 2670 if (dst_precision == kSinglePrecision) { |
| 2643 double val = get_double_from_d_register(src); | 2671 double val = get_double_from_d_register(src); |
| 2644 set_s_register_from_float(dst, static_cast<float>(val)); | 2672 set_s_register_from_float(dst, static_cast<float>(val)); |
| 2645 } else { | 2673 } else { |
| 2646 float val = get_float_from_s_register(src); | 2674 float val = get_float_from_s_register(src); |
| 2647 set_d_register_from_double(dst, static_cast<double>(val)); | 2675 set_d_register_from_double(dst, static_cast<double>(val)); |
| 2648 } | 2676 } |
| 2649 } | 2677 } |
| 2650 | 2678 |
| 2679 bool get_inv_op_vfp_flag(VFPRoundingMode mode, |
| 2680 double val, |
| 2681 bool unsigned_) { |
| 2682 ASSERT((mode == RN) || (mode == RM) || (mode == RZ)); |
| 2683 double max_uint = static_cast<double>(0xffffffffu); |
| 2684 double max_int = static_cast<double>(kMaxInt); |
| 2685 double min_int = static_cast<double>(kMinInt); |
| 2686 |
| 2687 // Check for NaN. |
| 2688 if (val != val) { |
| 2689 return true; |
| 2690 } |
| 2691 |
| 2692 // Check for overflow. This code works because 32bit integers can be |
| 2693 // exactly represented by ieee-754 64bit floating-point values. |
| 2694 switch (mode) { |
| 2695 case RN: |
| 2696 return unsigned_ ? (val >= (max_uint + 0.5)) || |
| 2697 (val < -0.5) |
| 2698 : (val >= (max_int + 0.5)) || |
| 2699 (val < (min_int - 0.5)); |
| 2700 |
| 2701 case RM: |
| 2702 return unsigned_ ? (val >= (max_uint + 1.0)) || |
| 2703 (val < 0) |
| 2704 : (val >= (max_int + 1.0)) || |
| 2705 (val < min_int); |
| 2706 |
| 2707 case RZ: |
| 2708 return unsigned_ ? (val >= (max_uint + 1.0)) || |
| 2709 (val <= -1) |
| 2710 : (val >= (max_int + 1.0)) || |
| 2711 (val <= (min_int - 1.0)); |
| 2712 default: |
| 2713 UNREACHABLE(); |
| 2714 return true; |
| 2715 } |
| 2716 } |
| 2717 |
| 2718 |
| 2719 // We call this function only if we had a vfp invalid exception. |
| 2720 // It returns the correct saturated value. |
| 2721 int VFPConversionSaturate(double val, bool unsigned_res) { |
| 2722 if (val != val) { |
| 2723 return 0; |
| 2724 } else { |
| 2725 if (unsigned_res) { |
| 2726 return (val < 0) ? 0 : 0xffffffffu; |
| 2727 } else { |
| 2728 return (val < 0) ? kMinInt : kMaxInt; |
| 2729 } |
| 2730 } |
| 2731 } |
| 2732 |
| 2651 | 2733 |
| 2652 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) { | 2734 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) { |
| 2653 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); | 2735 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7) && |
| 2736 (instr->Bits(27, 23) == 0x1D)); |
| 2654 ASSERT(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) || | 2737 ASSERT(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) || |
| 2655 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1))); | 2738 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1))); |
| 2656 | 2739 |
| 2657 // Conversion between floating-point and integer. | 2740 // Conversion between floating-point and integer. |
| 2658 bool to_integer = (instr->Bit(18) == 1); | 2741 bool to_integer = (instr->Bit(18) == 1); |
| 2659 | 2742 |
| 2660 VFPRegPrecision src_precision = kSinglePrecision; | 2743 VFPRegPrecision src_precision = (instr->SzValue() == 1) ? kDoublePrecision |
| 2661 if (instr->SzValue() == 1) { | 2744 : kSinglePrecision; |
| 2662 src_precision = kDoublePrecision; | |
| 2663 } | |
| 2664 | 2745 |
| 2665 if (to_integer) { | 2746 if (to_integer) { |
| 2666 bool unsigned_integer = (instr->Bit(16) == 0); | 2747 // We are playing with code close to the C++ standard's limits below, |
| 2667 FPSCRRoundingModes mode; | 2748 // hence the very simple code and heavy checks. |
| 2668 if (instr->Bit(7) != 1) { | 2749 // |
| 2669 // Use FPSCR defined rounding mode. | 2750 // Note: |
| 2670 mode = FPSCR_rounding_mode_; | 2751 // C++ defines default type casting from floating point to integer as |
| 2671 // Only RZ and RM modes are supported. | 2752 // (close to) rounding toward zero ("fractional part discarded"). |
| 2672 ASSERT((mode == RM) || (mode == RZ)); | |
| 2673 } else { | |
| 2674 // VFP uses round towards zero by default. | |
| 2675 mode = RZ; | |
| 2676 } | |
| 2677 | 2753 |
| 2678 int dst = instr->VFPDRegValue(kSinglePrecision); | 2754 int dst = instr->VFPDRegValue(kSinglePrecision); |
| 2679 int src = instr->VFPMRegValue(src_precision); | 2755 int src = instr->VFPMRegValue(src_precision); |
| 2680 int32_t kMaxInt = v8::internal::kMaxInt; | |
| 2681 int32_t kMinInt = v8::internal::kMinInt; | |
| 2682 switch (mode) { | |
| 2683 case RM: | |
| 2684 if (src_precision == kDoublePrecision) { | |
| 2685 double val = get_double_from_d_register(src); | |
| 2686 | 2756 |
| 2687 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); | 2757 // Bit 7 in vcvt instructions indicates if we should use the FPSCR rounding |
| 2758 // mode or the default Round to Zero mode. |
| 2759 VFPRoundingMode mode = (instr->Bit(7) != 1) ? FPSCR_rounding_mode_ |
| 2760 : RZ; |
| 2761 ASSERT((mode == RM) || (mode == RZ) || (mode == RN)); |
| 2688 | 2762 |
| 2689 int sint = unsigned_integer ? static_cast<uint32_t>(val) : | 2763 bool unsigned_integer = (instr->Bit(16) == 0); |
| 2690 static_cast<int32_t>(val); | 2764 bool double_precision = (src_precision == kDoublePrecision); |
| 2691 sint = sint > val ? sint - 1 : sint; | |
| 2692 | 2765 |
| 2693 set_s_register_from_sinteger(dst, sint); | 2766 double val = double_precision ? get_double_from_d_register(src) |
| 2694 } else { | 2767 : get_float_from_s_register(src); |
| 2695 float val = get_float_from_s_register(src); | |
| 2696 | 2768 |
| 2697 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); | 2769 int temp = unsigned_integer ? static_cast<uint32_t>(val) |
| 2770 : static_cast<int32_t>(val); |
| 2698 | 2771 |
| 2699 int sint = unsigned_integer ? static_cast<uint32_t>(val) : | 2772 inv_op_vfp_flag_ = get_inv_op_vfp_flag(mode, val, unsigned_integer); |
| 2700 static_cast<int32_t>(val); | |
| 2701 sint = sint > val ? sint - 1 : sint; | |
| 2702 | 2773 |
| 2703 set_s_register_from_sinteger(dst, sint); | 2774 if (inv_op_vfp_flag_) { |
| 2775 temp = VFPConversionSaturate(val, unsigned_integer); |
| 2776 } else { |
| 2777 switch (mode) { |
| 2778 case RN: { |
| 2779 double abs_diff = |
| 2780 unsigned_integer ? fabs(val - static_cast<uint32_t>(temp)) |
| 2781 : fabs(val - temp); |
| 2782 int val_sign = (val > 0) ? 1 : -1; |
| 2783 if (abs_diff > 0.5) { |
| 2784 temp += val_sign; |
| 2785 } else if (abs_diff == 0.5) { |
| 2786 // Round to even if exactly halfway. |
| 2787 temp = ((temp % 2) == 0) ? temp : temp + val_sign; |
| 2788 } |
| 2789 break; |
| 2704 } | 2790 } |
| 2705 break; | |
| 2706 case RZ: | |
| 2707 if (src_precision == kDoublePrecision) { | |
| 2708 double val = get_double_from_d_register(src); | |
| 2709 | 2791 |
| 2710 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); | 2792 case RM: |
| 2793 temp = temp > val ? temp - 1 : temp; |
| 2794 break; |
| 2711 | 2795 |
| 2712 int sint = unsigned_integer ? static_cast<uint32_t>(val) : | 2796 case RZ: |
| 2713 static_cast<int32_t>(val); | 2797 // Nothing to do. |
| 2798 break; |
| 2714 | 2799 |
| 2715 set_s_register_from_sinteger(dst, sint); | 2800 default: |
| 2716 } else { | 2801 UNREACHABLE(); |
| 2717 float val = get_float_from_s_register(src); | 2802 } |
| 2803 } |
| 2718 | 2804 |
| 2719 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); | 2805 // Update the destination register. |
| 2720 | 2806 set_s_register_from_sinteger(dst, temp); |
| 2721 int sint = unsigned_integer ? static_cast<uint32_t>(val) : | |
| 2722 static_cast<int32_t>(val); | |
| 2723 | |
| 2724 set_s_register_from_sinteger(dst, sint); | |
| 2725 } | |
| 2726 break; | |
| 2727 | |
| 2728 default: | |
| 2729 UNREACHABLE(); | |
| 2730 } | |
| 2731 | 2807 |
| 2732 } else { | 2808 } else { |
| 2733 bool unsigned_integer = (instr->Bit(7) == 0); | 2809 bool unsigned_integer = (instr->Bit(7) == 0); |
| 2734 | 2810 |
| 2735 int dst = instr->VFPDRegValue(src_precision); | 2811 int dst = instr->VFPDRegValue(src_precision); |
| 2736 int src = instr->VFPMRegValue(kSinglePrecision); | 2812 int src = instr->VFPMRegValue(kSinglePrecision); |
| 2737 | 2813 |
| 2738 int val = get_sinteger_from_s_register(src); | 2814 int val = get_sinteger_from_s_register(src); |
| 2739 | 2815 |
| 2740 if (src_precision == kDoublePrecision) { | 2816 if (src_precision == kDoublePrecision) { |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3049 uintptr_t address = *stack_slot; | 3125 uintptr_t address = *stack_slot; |
| 3050 set_register(sp, current_sp + sizeof(uintptr_t)); | 3126 set_register(sp, current_sp + sizeof(uintptr_t)); |
| 3051 return address; | 3127 return address; |
| 3052 } | 3128 } |
| 3053 | 3129 |
| 3054 } } // namespace v8::internal | 3130 } } // namespace v8::internal |
| 3055 | 3131 |
| 3056 #endif // USE_SIMULATOR | 3132 #endif // USE_SIMULATOR |
| 3057 | 3133 |
| 3058 #endif // V8_TARGET_ARCH_ARM | 3134 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |