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

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

Issue 6606006: [Isolates] Merge 6500:6700 from bleeding_edge to isolates. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: '' Created 9 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « src/arm/simulator-arm.h ('k') | src/arm/stub-cache-arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/arm/simulator-arm.h ('k') | src/arm/stub-cache-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698