Commit f6de983e authored by jacob.bramley@arm.com's avatar jacob.bramley@arm.com

A64: Fix Fmov with signalling NaN literals.

BUG=
R=ulan@chromium.org

Review URL: https://codereview.chromium.org/194753002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19885 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 390d3a0b
......@@ -1419,16 +1419,24 @@ void Assembler::ldrsw(const Register& rt, const MemOperand& src) {
void Assembler::ldr(const Register& rt, uint64_t imm) {
// TODO(all): Constant pool may be garbage collected. Hence we cannot store
// TODO(all): arbitrary values in them. Manually move it for now.
// TODO(all): Fix MacroAssembler::Fmov when this is implemented.
// arbitrary values in them. Manually move it for now. Fix
// MacroAssembler::Fmov when this is implemented.
UNIMPLEMENTED();
}
void Assembler::ldr(const FPRegister& ft, double imm) {
// TODO(all): Constant pool may be garbage collected. Hence we cannot store
// TODO(all): arbitrary values in them. Manually move it for now.
// TODO(all): Fix MacroAssembler::Fmov when this is implemented.
// arbitrary values in them. Manually move it for now. Fix
// MacroAssembler::Fmov when this is implemented.
UNIMPLEMENTED();
}
void Assembler::ldr(const FPRegister& ft, float imm) {
// TODO(all): Constant pool may be garbage collected. Hence we cannot store
// arbitrary values in them. Manually move it for now. Fix
// MacroAssembler::Fmov when this is implemented.
UNIMPLEMENTED();
}
......@@ -1483,16 +1491,16 @@ void Assembler::isb() {
void Assembler::fmov(FPRegister fd, double imm) {
if (fd.Is64Bits() && IsImmFP64(imm)) {
Emit(FMOV_d_imm | Rd(fd) | ImmFP64(imm));
} else if (fd.Is32Bits() && IsImmFP32(imm)) {
Emit(FMOV_s_imm | Rd(fd) | ImmFP32(static_cast<float>(imm)));
} else if ((imm == 0.0) && (copysign(1.0, imm) == 1.0)) {
Register zr = AppropriateZeroRegFor(fd);
fmov(fd, zr);
} else {
ldr(fd, imm);
}
ASSERT(fd.Is64Bits());
ASSERT(IsImmFP64(imm));
Emit(FMOV_d_imm | Rd(fd) | ImmFP64(imm));
}
void Assembler::fmov(FPRegister fd, float imm) {
ASSERT(fd.Is32Bits());
ASSERT(IsImmFP32(imm));
Emit(FMOV_s_imm | Rd(fd) | ImmFP32(imm));
}
......
......@@ -1418,6 +1418,7 @@ class Assembler : public AssemblerBase {
// Load literal to FP register.
void ldr(const FPRegister& ft, double imm);
void ldr(const FPRegister& ft, float imm);
// Move instructions. The default shift of -1 indicates that the move
// instruction will calculate an appropriate 16-bit immediate and left shift
......@@ -1496,6 +1497,7 @@ class Assembler : public AssemblerBase {
// FP instructions.
// Move immediate to FP register.
void fmov(FPRegister fd, double imm);
void fmov(FPRegister fd, float imm);
// Move FP register to register.
void fmov(Register rd, FPRegister fn);
......
......@@ -737,26 +737,44 @@ void MacroAssembler::Fmov(FPRegister fd, Register rn) {
void MacroAssembler::Fmov(FPRegister fd, double imm) {
ASSERT(allow_macro_instructions_);
if ((fd.Is64Bits() && IsImmFP64(imm)) ||
(fd.Is32Bits() && IsImmFP32(imm)) ||
((imm == 0.0) && (copysign(1.0, imm) == 1.0))) {
// These cases can be handled by the Assembler.
if (fd.Is32Bits()) {
Fmov(fd, static_cast<float>(imm));
return;
}
ASSERT(fd.Is64Bits());
if (IsImmFP64(imm)) {
fmov(fd, imm);
} else if ((imm == 0.0) && (copysign(1.0, imm) == 1.0)) {
fmov(fd, xzr);
} else {
UseScratchRegisterScope temps(this);
// TODO(all): The Assembler would try to relocate the immediate with
// Assembler::ldr(const FPRegister& ft, double imm) but it is not
// implemented yet.
if (fd.SizeInBits() == kDRegSizeInBits) {
Register tmp = temps.AcquireX();
Mov(tmp, double_to_rawbits(imm));
Fmov(fd, tmp);
} else {
ASSERT(fd.SizeInBits() == kSRegSizeInBits);
Register tmp = temps.AcquireW();
Mov(tmp, float_to_rawbits(static_cast<float>(imm)));
Fmov(fd, tmp);
}
Register tmp = temps.AcquireX();
// TODO(all): Use Assembler::ldr(const FPRegister& ft, double imm).
Mov(tmp, double_to_rawbits(imm));
Fmov(fd, tmp);
}
}
void MacroAssembler::Fmov(FPRegister fd, float imm) {
ASSERT(allow_macro_instructions_);
if (fd.Is64Bits()) {
Fmov(fd, static_cast<double>(imm));
return;
}
ASSERT(fd.Is32Bits());
if (IsImmFP32(imm)) {
fmov(fd, imm);
} else if ((imm == 0.0) && (copysign(1.0, imm) == 1.0)) {
fmov(fd, wzr);
} else {
UseScratchRegisterScope temps(this);
Register tmp = temps.AcquireW();
// TODO(all): Use Assembler::ldr(const FPRegister& ft, float imm).
Mov(tmp, float_to_rawbits(imm));
Fmov(fd, tmp);
}
}
......
......@@ -357,7 +357,18 @@ class MacroAssembler : public Assembler {
const FPRegister& fm);
inline void Fmov(FPRegister fd, FPRegister fn);
inline void Fmov(FPRegister fd, Register rn);
// Provide explicit double and float interfaces for FP immediate moves, rather
// than relying on implicit C++ casts. This allows signalling NaNs to be
// preserved when the immediate matches the format of fd. Most systems convert
// signalling NaNs to quiet NaNs when converting between float and double.
inline void Fmov(FPRegister fd, double imm);
inline void Fmov(FPRegister fd, float imm);
// Provide a template to allow other types to be converted automatically.
template<typename T>
void Fmov(FPRegister fd, T imm) {
ASSERT(allow_macro_instructions_);
Fmov(fd, static_cast<double>(imm));
}
inline void Fmov(Register rd, FPRegister fn);
inline void Fmsub(const FPRegister& fd,
const FPRegister& fn,
......@@ -394,7 +405,12 @@ class MacroAssembler : public Assembler {
inline void Ldpsw(const Register& rt,
const Register& rt2,
const MemOperand& src);
// Provide both double and float interfaces for FP immediate loads, rather
// than relying on implicit C++ casts. This allows signalling NaNs to be
// preserved when the immediate matches the format of fd. Most systems convert
// signalling NaNs to quiet NaNs when converting between float and double.
inline void Ldr(const FPRegister& ft, double imm);
inline void Ldr(const FPRegister& ft, float imm);
inline void Ldr(const Register& rt, uint64_t imm);
inline void Lsl(const Register& rd, const Register& rn, unsigned shift);
inline void Lsl(const Register& rd, const Register& rn, const Register& rm);
......
......@@ -5473,14 +5473,8 @@ static void FminFmaxFloatHelper(float n, float m, float min, float max,
SETUP();
START();
// TODO(all): Signalling NaNs are sometimes converted by the C compiler to
// quiet NaNs on implicit casts from float to double. Here, we move the raw
// bits into a W register first, so we get the correct value. Fix Fmov so this
// additional step is no longer needed.
__ Mov(w0, float_to_rawbits(n));
__ Fmov(s0, w0);
__ Mov(w0, float_to_rawbits(m));
__ Fmov(s1, w0);
__ Fmov(s0, n);
__ Fmov(s1, m);
__ Fmin(s28, s0, s1);
__ Fmax(s29, s0, s1);
__ Fminnm(s30, s0, s1);
......
......@@ -1273,7 +1273,7 @@ TEST_(load_literal) {
COMPARE_PREFIX(ldr(x10, 0x1234567890abcdefUL), "ldr x10, pc+8");
COMPARE_PREFIX(ldr(w20, 0xfedcba09), "ldr w20, pc+8");
COMPARE_PREFIX(ldr(d11, 1.234), "ldr d11, pc+8");
COMPARE_PREFIX(ldr(s22, 2.5), "ldr s22, pc+8");
COMPARE_PREFIX(ldr(s22, 2.5f), "ldr s22, pc+8");
CLEANUP();
}
......@@ -1361,8 +1361,8 @@ TEST_(cond_cmp_macro) {
TEST_(fmov_imm) {
SET_UP();
COMPARE(fmov(s0, 1.0), "fmov s0, #0x70 (1.0000)");
COMPARE(fmov(s31, -13.0), "fmov s31, #0xaa (-13.0000)");
COMPARE(fmov(s0, 1.0f), "fmov s0, #0x70 (1.0000)");
COMPARE(fmov(s31, -13.0f), "fmov s31, #0xaa (-13.0000)");
COMPARE(fmov(d1, 1.0), "fmov d1, #0x70 (1.0000)");
COMPARE(fmov(d29, -13.0), "fmov d29, #0xaa (-13.0000)");
......
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