Commit 269b35a3 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[arm] [simulator] Box floats and doubles

This prepares fixes in the implementations of vabs and vneg (potentially
more). In order to implement them correctly, we need to preserve the
exact bit pattern.

R=ahaas@chromium.org, rodolph.perfetta@arm.com

Bug: v8:6947
Change-Id: I7194a60371a6e3c9ffba32981c90090ffafaa610
Reviewed-on: https://chromium-review.googlesource.com/722941Reviewed-by: 's avatarRodolph Perfetta <rodolph.perfetta@arm.com>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48648}
parent 526c31d0
......@@ -10,7 +10,7 @@
namespace v8 {
namespace internal {
double Instruction::DoubleImmedVmov() const {
Float64 Instruction::DoubleImmedVmov() const {
// Reconstruct a double from the immediate encoded in the vmov instruction.
//
// instruction: [xxxxxxxx,xxxxabcd,xxxxxxxx,xxxxefgh]
......@@ -25,9 +25,7 @@ double Instruction::DoubleImmedVmov() const {
high16 |= Bit(19) << 15; // axxxxxxx,xxxxxxxx.
uint64_t imm = high16 << 48;
double d;
memcpy(&d, &imm, 8);
return d;
return Float64::FromBits(imm);
}
......
......@@ -9,6 +9,7 @@
#include "src/base/logging.h"
#include "src/base/macros.h"
#include "src/boxed-float.h"
#include "src/globals.h"
// ARM EABI is required.
......@@ -662,7 +663,7 @@ class Instruction {
inline bool HasLink() const { return LinkValue() == 1; }
// Decode the double immediate from a vmov instruction.
double DoubleImmedVmov() const;
Float64 DoubleImmedVmov() const;
// Instructions are read of out a code stream. The only way to get a
// reference to an instruction is to convert a pointer. There is no way
......
......@@ -468,7 +468,7 @@ int Decoder::FormatOption(Instruction* instr, const char* format) {
return 4;
}
case 'd': { // 'd: vmov double immediate.
double d = instr->DoubleImmedVmov();
double d = instr->DoubleImmedVmov().get_scalar();
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "#%g", d);
return 1;
}
......
This diff is collapsed.
......@@ -16,6 +16,7 @@
#include "src/allocation.h"
#include "src/base/lazy-instance.h"
#include "src/base/platform/mutex.h"
#include "src/boxed-float.h"
#if !defined(USE_SIMULATOR)
// Running without a simulator on a native arm platform.
......@@ -158,20 +159,26 @@ class Simulator {
void set_s_register(int reg, unsigned int value);
unsigned int get_s_register(int reg) const;
void set_d_register_from_double(int dreg, const double& dbl) {
void set_d_register_from_double(int dreg, const Float64 dbl) {
SetVFPRegister<Float64, 2>(dreg, dbl);
}
void set_d_register_from_double(int dreg, const double dbl) {
SetVFPRegister<double, 2>(dreg, dbl);
}
double get_double_from_d_register(int dreg) {
return GetFromVFPRegister<double, 2>(dreg);
Float64 get_double_from_d_register(int dreg) {
return GetFromVFPRegister<Float64, 2>(dreg);
}
void set_s_register_from_float(int sreg, const Float32 flt) {
SetVFPRegister<Float32, 1>(sreg, flt);
}
void set_s_register_from_float(int sreg, const float flt) {
SetVFPRegister<float, 1>(sreg, flt);
}
float get_float_from_s_register(int sreg) {
return GetFromVFPRegister<float, 1>(sreg);
Float32 get_float_from_s_register(int sreg) {
return GetFromVFPRegister<Float32, 1>(sreg);
}
void set_s_register_from_sinteger(int sreg, const int sint) {
......@@ -208,7 +215,6 @@ class Simulator {
// Alternative: call a 2-argument double function.
void CallFP(byte* entry, double d0, double d1);
int32_t CallFPReturnsInt(byte* entry, double d0, double d1);
double CallFPReturnsDouble(byte* entry, double d0, double d1);
// Push an address onto the JS stack.
uintptr_t PushAddress(uintptr_t address);
......@@ -277,6 +283,8 @@ class Simulator {
void Copy_FPSCR_to_APSR();
inline float canonicalizeNaN(float value);
inline double canonicalizeNaN(double value);
inline Float32 canonicalizeNaN(Float32 value);
inline Float64 canonicalizeNaN(Float64 value);
// Helper functions to decode common "addressing" modes
int32_t GetShiftRm(Instruction* instr, bool* carry_out);
......
......@@ -7,6 +7,7 @@
#include <cmath>
#include "src/base/macros.h"
#include "src/globals.h"
namespace v8 {
namespace internal {
......@@ -19,7 +20,10 @@ class Float32 {
public:
Float32() : bit_pattern_(0) {}
explicit Float32(uint32_t bit_pattern) : bit_pattern_(bit_pattern) {}
Float32(const Float32&) = default;
explicit constexpr Float32(uint32_t bit_pattern)
: bit_pattern_(bit_pattern) {}
// This constructor does not guarantee that bit pattern of the input value
// is preserved if the input is a NaN.
......@@ -33,12 +37,21 @@ class Float32 {
float get_scalar() const { return bit_cast<float>(bit_pattern_); }
static Float32 FromBits(uint32_t bits) { return Float32(bits); }
bool is_nan() const {
// Even though {get_scalar()} might flip the quiet NaN bit, it's ok here,
// because this does not change the is_nan property.
return std::isnan(get_scalar());
}
static constexpr Float32 FromBits(uint32_t bits) { return Float32(bits); }
private:
uint32_t bit_pattern_;
};
static_assert(IS_TRIVIALLY_COPYABLE(Float32),
"Float32 should be trivially copyable");
// Safety wrapper for a 64-bit floating-point value to make sure we don't lose
// the exact bit pattern during deoptimization when passing this value. Note
// that there is intentionally no way to construct it from a {double} value.
......@@ -46,16 +59,36 @@ class Float32 {
class Float64 {
public:
Float64() : bit_pattern_(0) {}
Float64(const Float64&) = default;
// This constructor does not guarantee that bit pattern of the input value
// is preserved if the input is a NaN.
explicit Float64(double value) : bit_pattern_(bit_cast<uint64_t>(value)) {
// Check that the provided value is not a NaN, because the bit pattern of a
// NaN may be changed by a bit_cast, e.g. for signalling NaNs on ia32.
DCHECK(!std::isnan(value));
}
uint64_t get_bits() const { return bit_pattern_; }
double get_scalar() const { return bit_cast<double>(bit_pattern_); }
bool is_hole_nan() const { return bit_pattern_ == kHoleNanInt64; }
static Float64 FromBits(uint64_t bits) { return Float64(bits); }
bool is_nan() const {
// Even though {get_scalar()} might flip the quiet NaN bit, it's ok here,
// because this does not change the is_nan property.
return std::isnan(get_scalar());
}
static constexpr Float64 FromBits(uint64_t bits) { return Float64(bits); }
private:
explicit Float64(uint64_t bit_pattern) : bit_pattern_(bit_pattern) {}
explicit constexpr Float64(uint64_t bit_pattern)
: bit_pattern_(bit_pattern) {}
uint64_t bit_pattern_;
};
static_assert(IS_TRIVIALLY_COPYABLE(Float64),
"Float64 should be trivially copyable");
} // namespace internal
} // namespace v8
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment