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

Unified 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, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/arm/simulator-arm.h ('k') | src/arm/stub-cache-arm.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/arm/simulator-arm.cc
===================================================================
--- src/arm/simulator-arm.cc (revision 7006)
+++ src/arm/simulator-arm.cc (working copy)
@@ -740,10 +740,10 @@
// offset from the svc instruction so the simulator knows what to call.
class Redirection {
public:
- Redirection(void* external_function, bool fp_return)
+ Redirection(void* external_function, ExternalReference::Type type)
: external_function_(external_function),
swi_instruction_(al | (0xf*B24) | kCallRtRedirected),
- fp_return_(fp_return),
+ type_(type),
next_(NULL) {
Isolate* isolate = Isolate::Current();
next_ = isolate->simulator_redirection();
@@ -759,15 +759,16 @@
}
void* external_function() { return external_function_; }
- bool fp_return() { return fp_return_; }
+ ExternalReference::Type type() { return type_; }
- static Redirection* Get(void* external_function, bool fp_return) {
+ static Redirection* Get(void* external_function,
+ ExternalReference::Type type) {
Isolate* isolate = Isolate::Current();
Redirection* current = isolate->simulator_redirection();
for (; current != NULL; current = current->next_) {
if (current->external_function_ == external_function) return current;
}
- return new Redirection(external_function, fp_return);
+ return new Redirection(external_function, type);
}
static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
@@ -780,14 +781,14 @@
private:
void* external_function_;
uint32_t swi_instruction_;
- bool fp_return_;
+ ExternalReference::Type type_;
Redirection* next_;
};
void* Simulator::RedirectExternalReference(void* external_function,
- bool fp_return) {
- Redirection* redirection = Redirection::Get(external_function, fp_return);
+ ExternalReference::Type type) {
+ Redirection* redirection = Redirection::Get(external_function, type);
return redirection->address_of_swi_instruction();
}
@@ -1530,6 +1531,9 @@
int32_t arg2,
int32_t arg3);
+// This signature supports direct call in to API function native callback
+// (refer to InvocationCallback in v8.h).
+typedef v8::Handle<v8::Value> (*SimulatorRuntimeApiCall)(int32_t arg0);
// Software interrupt instructions are used by the simulator to call into the
// C-based V8 runtime.
@@ -1552,9 +1556,9 @@
// This is dodgy but it works because the C entry stubs are never moved.
// See comment in codegen-arm.cc and bug 1242173.
int32_t saved_lr = get_register(lr);
- if (redirection->fp_return()) {
- intptr_t external =
- reinterpret_cast<intptr_t>(redirection->external_function());
+ intptr_t external =
+ reinterpret_cast<intptr_t>(redirection->external_function());
+ if (redirection->type() == ExternalReference::FP_RETURN_CALL) {
SimulatorRuntimeFPCall target =
reinterpret_cast<SimulatorRuntimeFPCall>(external);
if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
@@ -1570,9 +1574,28 @@
CHECK(stack_aligned);
double result = target(arg0, arg1, arg2, arg3);
SetFpResult(result);
+ } else if (redirection->type() == ExternalReference::DIRECT_CALL) {
+ SimulatorRuntimeApiCall target =
+ reinterpret_cast<SimulatorRuntimeApiCall>(external);
+ if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
+ PrintF(
+ "Call to host function at %p args %08x",
+ FUNCTION_ADDR(target),
+ arg0);
+ if (!stack_aligned) {
+ PrintF(" with unaligned stack %08x\n", get_register(sp));
+ }
+ PrintF("\n");
+ }
+ CHECK(stack_aligned);
+ v8::Handle<v8::Value> result = target(arg0);
+ if (::v8::internal::FLAG_trace_sim) {
+ PrintF("Returned %p\n", reinterpret_cast<void *>(*result));
+ }
+ set_register(r0, (int32_t) *result);
} else {
- intptr_t external =
- reinterpret_cast<int32_t>(redirection->external_function());
+ // builtin call.
+ ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL);
SimulatorRuntimeCall target =
reinterpret_cast<SimulatorRuntimeCall>(external);
if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
@@ -2447,6 +2470,11 @@
int d = instr->VFPDRegValue(kSinglePrecision);
set_s_register_from_float(d, get_float_from_s_register(m));
}
+ } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
+ // vabs
+ double dm_value = get_double_from_d_register(vm);
+ double dd_value = fabs(dm_value);
+ set_d_register_from_double(vd, dd_value);
} else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
DecodeVCVTBetweenDoubleAndSingle(instr);
} else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
@@ -2536,7 +2564,7 @@
(overflow_vfp_flag_ << 2) |
(div_zero_vfp_flag_ << 1) |
(inv_op_vfp_flag_ << 0) |
- (FPSCR_rounding_mode_ << 22);
+ (FPSCR_rounding_mode_);
set_register(rt, fpscr);
}
} else if ((instr->VLValue() == 0x0) &&
@@ -2559,7 +2587,7 @@
div_zero_vfp_flag_ = (rt_value >> 1) & 1;
inv_op_vfp_flag_ = (rt_value >> 0) & 1;
FPSCR_rounding_mode_ =
- static_cast<FPSCRRoundingModes>((rt_value >> 22) & 3);
+ static_cast<VFPRoundingMode>((rt_value) & kVFPRoundingModeMask);
}
} else {
UNIMPLEMENTED(); // Not used by V8.
@@ -2648,87 +2676,135 @@
}
}
+bool get_inv_op_vfp_flag(VFPRoundingMode mode,
+ double val,
+ bool unsigned_) {
+ ASSERT((mode == RN) || (mode == RM) || (mode == RZ));
+ double max_uint = static_cast<double>(0xffffffffu);
+ double max_int = static_cast<double>(kMaxInt);
+ double min_int = static_cast<double>(kMinInt);
+ // Check for NaN.
+ if (val != val) {
+ return true;
+ }
+
+ // Check for overflow. This code works because 32bit integers can be
+ // exactly represented by ieee-754 64bit floating-point values.
+ switch (mode) {
+ case RN:
+ return unsigned_ ? (val >= (max_uint + 0.5)) ||
+ (val < -0.5)
+ : (val >= (max_int + 0.5)) ||
+ (val < (min_int - 0.5));
+
+ case RM:
+ return unsigned_ ? (val >= (max_uint + 1.0)) ||
+ (val < 0)
+ : (val >= (max_int + 1.0)) ||
+ (val < min_int);
+
+ case RZ:
+ return unsigned_ ? (val >= (max_uint + 1.0)) ||
+ (val <= -1)
+ : (val >= (max_int + 1.0)) ||
+ (val <= (min_int - 1.0));
+ default:
+ UNREACHABLE();
+ return true;
+ }
+}
+
+
+// We call this function only if we had a vfp invalid exception.
+// It returns the correct saturated value.
+int VFPConversionSaturate(double val, bool unsigned_res) {
+ if (val != val) {
+ return 0;
+ } else {
+ if (unsigned_res) {
+ return (val < 0) ? 0 : 0xffffffffu;
+ } else {
+ return (val < 0) ? kMinInt : kMaxInt;
+ }
+ }
+}
+
+
void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
- ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
+ ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7) &&
+ (instr->Bits(27, 23) == 0x1D));
ASSERT(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
(((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
// Conversion between floating-point and integer.
bool to_integer = (instr->Bit(18) == 1);
- VFPRegPrecision src_precision = kSinglePrecision;
- if (instr->SzValue() == 1) {
- src_precision = kDoublePrecision;
- }
+ VFPRegPrecision src_precision = (instr->SzValue() == 1) ? kDoublePrecision
+ : kSinglePrecision;
if (to_integer) {
- bool unsigned_integer = (instr->Bit(16) == 0);
- FPSCRRoundingModes mode;
- if (instr->Bit(7) != 1) {
- // Use FPSCR defined rounding mode.
- mode = FPSCR_rounding_mode_;
- // Only RZ and RM modes are supported.
- ASSERT((mode == RM) || (mode == RZ));
- } else {
- // VFP uses round towards zero by default.
- mode = RZ;
- }
+ // We are playing with code close to the C++ standard's limits below,
+ // hence the very simple code and heavy checks.
+ //
+ // Note:
+ // C++ defines default type casting from floating point to integer as
+ // (close to) rounding toward zero ("fractional part discarded").
int dst = instr->VFPDRegValue(kSinglePrecision);
int src = instr->VFPMRegValue(src_precision);
- int32_t kMaxInt = v8::internal::kMaxInt;
- int32_t kMinInt = v8::internal::kMinInt;
- switch (mode) {
- case RM:
- if (src_precision == kDoublePrecision) {
- double val = get_double_from_d_register(src);
- inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val);
+ // Bit 7 in vcvt instructions indicates if we should use the FPSCR rounding
+ // mode or the default Round to Zero mode.
+ VFPRoundingMode mode = (instr->Bit(7) != 1) ? FPSCR_rounding_mode_
+ : RZ;
+ ASSERT((mode == RM) || (mode == RZ) || (mode == RN));
- int sint = unsigned_integer ? static_cast<uint32_t>(val) :
- static_cast<int32_t>(val);
- sint = sint > val ? sint - 1 : sint;
+ bool unsigned_integer = (instr->Bit(16) == 0);
+ bool double_precision = (src_precision == kDoublePrecision);
- set_s_register_from_sinteger(dst, sint);
- } else {
- float val = get_float_from_s_register(src);
+ double val = double_precision ? get_double_from_d_register(src)
+ : get_float_from_s_register(src);
- inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val);
+ int temp = unsigned_integer ? static_cast<uint32_t>(val)
+ : static_cast<int32_t>(val);
- int sint = unsigned_integer ? static_cast<uint32_t>(val) :
- static_cast<int32_t>(val);
- sint = sint > val ? sint - 1 : sint;
+ inv_op_vfp_flag_ = get_inv_op_vfp_flag(mode, val, unsigned_integer);
- set_s_register_from_sinteger(dst, sint);
+ if (inv_op_vfp_flag_) {
+ temp = VFPConversionSaturate(val, unsigned_integer);
+ } else {
+ switch (mode) {
+ case RN: {
+ double abs_diff =
+ unsigned_integer ? fabs(val - static_cast<uint32_t>(temp))
+ : fabs(val - temp);
+ int val_sign = (val > 0) ? 1 : -1;
+ if (abs_diff > 0.5) {
+ temp += val_sign;
+ } else if (abs_diff == 0.5) {
+ // Round to even if exactly halfway.
+ temp = ((temp % 2) == 0) ? temp : temp + val_sign;
+ }
+ break;
}
- break;
- case RZ:
- if (src_precision == kDoublePrecision) {
- double val = get_double_from_d_register(src);
- inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val);
+ case RM:
+ temp = temp > val ? temp - 1 : temp;
+ break;
- int sint = unsigned_integer ? static_cast<uint32_t>(val) :
- static_cast<int32_t>(val);
+ case RZ:
+ // Nothing to do.
+ break;
- set_s_register_from_sinteger(dst, sint);
- } else {
- float val = get_float_from_s_register(src);
+ default:
+ UNREACHABLE();
+ }
+ }
- inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val);
+ // Update the destination register.
+ set_s_register_from_sinteger(dst, temp);
- int sint = unsigned_integer ? static_cast<uint32_t>(val) :
- static_cast<int32_t>(val);
-
- set_s_register_from_sinteger(dst, sint);
- }
- break;
-
- default:
- UNREACHABLE();
- }
-
} else {
bool unsigned_integer = (instr->Bit(7) == 0);
« 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