Bug 1279248 - Part 25: Extra tests, r=lth

This commit is contained in:
Hannes Verschore 2016-07-29 16:53:48 +02:00
parent ec0937ad53
commit 69caf976c6
11 changed files with 555 additions and 12 deletions

View File

@ -96,6 +96,9 @@ if (hasI64()) {
testConversion('f32', 'convert_s', 'i64', "0x7fffffffffffffff", 9223372036854775807.0);
testConversion('f32', 'convert_s', 'i64', "0x8000000000000000", -9223372036854775808.0);
testConversion('f32', 'convert_s', 'i64', "0x11db9e76a2483", 314159275180032.0);
testConversion('f32', 'convert_s', 'i64', "0x7fffffff", 2147483648.0); // closesth approx.
testConversion('f32', 'convert_s', 'i64', "0x80000000", 2147483648.0);
testConversion('f32', 'convert_s', 'i64', "0x80000001", 2147483648.0); // closesth approx.
testConversion('f64', 'convert_s', 'i64', 1, 1.0);
testConversion('f64', 'convert_s', 'i64', -1, -1.0);
@ -103,6 +106,9 @@ if (hasI64()) {
testConversion('f64', 'convert_s', 'i64', "0x7fffffffffffffff", 9223372036854775807.0);
testConversion('f64', 'convert_s', 'i64', "0x8000000000000000", -9223372036854775808.0);
testConversion('f64', 'convert_s', 'i64', "0x10969d374b968e", 4669201609102990);
testConversion('f64', 'convert_s', 'i64', "0x7fffffff", 2147483647.0);
testConversion('f64', 'convert_s', 'i64', "0x80000000", 2147483648.0);
testConversion('f64', 'convert_s', 'i64', "0x80000001", 2147483649.0);
testConversion('f32', 'convert_u', 'i64', 1, 1.0);
testConversion('f32', 'convert_u', 'i64', 0, 0.0);

View File

@ -158,6 +158,13 @@ if (hasI64()) {
testBinary64('mul', 40, 2, 80);
testBinary64('mul', -1, 2, -2);
testBinary64('mul', 0x123456, "0x9876543210", "0xad77d2c5f941160");
testBinary64('mul', 2, -1, -2);
testBinary64('mul', "0x80000000", -1, -2147483648);
testBinary64('mul', "0x7fffffff", -1, -2147483647);
testBinary64('mul', "0x7fffffffffffffff", -1, "0x8000000000000001");
testBinary64('mul', 2, 2, 4);
testBinary64('mul', "0x80000000", 2, "0x100000000");
testBinary64('mul', "0x7fffffff", 2, "0xfffffffe");
testBinary64('div_s', -40, 2, -20);
testBinary64('div_s', "0x1234567887654321", 2, "0x91a2b3c43b2a190");
testBinary64('div_s', "0x1234567887654321", "0x1000000000", "0x1234567");

View File

@ -954,7 +954,8 @@ class MacroAssembler : public MacroAssemblerSpecific
DEFINED_ON(x86, x64);
inline void branch64(Condition cond, Register64 lhs, Register64 rhs, Label* label)
DEFINED_ON(x86, x64);
// Only NotEqual conditions are allowed for the branch64 variants with Address as lhs.
// On x86 and x64 NotEqual and Equal conditions are allowed for the branch64 variants
// with Address as lhs. On others only the NotEqual condition.
inline void branch64(Condition cond, const Address& lhs, Imm64 val, Label* label) PER_ARCH;
// Compare the value at |lhs| with the value at |rhs|. The scratch

View File

@ -514,12 +514,14 @@ MacroAssembler::maxDouble(FloatRegister other, FloatRegister srcDest, bool handl
void
MacroAssembler::lshiftPtr(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 32);
ma_lsl(imm, dest, dest);
}
void
MacroAssembler::lshift64(Imm32 imm, Register64 dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 64);
as_mov(dest.high, lsl(dest.high, imm.value));
as_orr(dest.high, dest.high, lsr(dest.low, 32 - imm.value));
as_mov(dest.low, lsl(dest.low, imm.value));
@ -534,12 +536,14 @@ MacroAssembler::lshift32(Register src, Register dest)
void
MacroAssembler::lshift32(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 32);
lshiftPtr(imm, dest);
}
void
MacroAssembler::rshiftPtr(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 32);
ma_lsr(imm, dest, dest);
}
@ -552,12 +556,14 @@ MacroAssembler::rshift32(Register src, Register dest)
void
MacroAssembler::rshift32(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 32);
rshiftPtr(imm, dest);
}
void
MacroAssembler::rshiftPtrArithmetic(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 32);
ma_asr(imm, dest, dest);
}
@ -570,12 +576,14 @@ MacroAssembler::rshift32Arithmetic(Register src, Register dest)
void
MacroAssembler::rshift32Arithmetic(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 32);
rshiftPtrArithmetic(imm, dest);
}
void
MacroAssembler::rshift64(Imm32 imm, Register64 dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 64);
as_mov(dest.low, lsr(dest.low, imm.value));
as_orr(dest.low, dest.low, lsl(dest.high, 32 - imm.value));
as_mov(dest.high, lsr(dest.high, imm.value));

View File

@ -541,12 +541,14 @@ MacroAssembler::maxDouble(FloatRegister other, FloatRegister srcDest, bool handl
void
MacroAssembler::lshiftPtr(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 64);
Lsl(ARMRegister(dest, 64), ARMRegister(dest, 64), imm.value);
}
void
MacroAssembler::lshift64(Imm32 imm, Register64 dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 64);
lshiftPtr(imm, dest.reg);
}
@ -559,18 +561,21 @@ MacroAssembler::lshift32(Register shift, Register dest)
void
MacroAssembler::lshift32(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 32);
Lsl(ARMRegister(dest, 32), ARMRegister(dest, 32), imm.value);
}
void
MacroAssembler::rshiftPtr(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 64);
Lsr(ARMRegister(dest, 64), ARMRegister(dest, 64), imm.value);
}
void
MacroAssembler::rshiftPtr(Imm32 imm, Register src, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 64);
Lsr(ARMRegister(dest, 64), ARMRegister(src, 64), imm.value);
}
@ -583,12 +588,14 @@ MacroAssembler::rshift32(Register shift, Register dest)
void
MacroAssembler::rshift32(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 32);
Lsr(ARMRegister(dest, 32), ARMRegister(dest, 32), imm.value);
}
void
MacroAssembler::rshiftPtrArithmetic(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 64);
Asr(ARMRegister(dest, 64), ARMRegister(dest, 64), imm.value);
}
@ -601,12 +608,14 @@ MacroAssembler::rshift32Arithmetic(Register shift, Register dest)
void
MacroAssembler::rshift32Arithmetic(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 32);
Asr(ARMRegister(dest, 32), ARMRegister(dest, 32), imm.value);
}
void
MacroAssembler::rshift64(Imm32 imm, Register64 dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 64);
rshiftPtr(imm, dest.reg);
}

View File

@ -230,12 +230,14 @@ MacroAssembler::inc64(AbsoluteAddress dest)
void
MacroAssembler::lshiftPtr(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 32);
ma_sll(dest, dest, imm);
}
void
MacroAssembler::lshift64(Imm32 imm, Register64 dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 64);
ScratchRegisterScope scratch(*this);
as_sll(dest.high, dest.high, imm.value);
as_srl(scratch, dest.low, 32 - imm.value);
@ -246,18 +248,21 @@ MacroAssembler::lshift64(Imm32 imm, Register64 dest)
void
MacroAssembler::rshiftPtr(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 32);
ma_srl(dest, dest, imm);
}
void
MacroAssembler::rshiftPtrArithmetic(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 32);
ma_sra(dest, dest, imm);
}
void
MacroAssembler::rshift64(Imm32 imm, Register64 dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 64);
ScratchRegisterScope scratch(*this);
as_srl(dest.low, dest.low, imm.value);
as_sll(scratch, dest.high, 32 - imm.value);

View File

@ -177,30 +177,35 @@ MacroAssembler::inc64(AbsoluteAddress dest)
void
MacroAssembler::lshiftPtr(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 64);
ma_dsll(dest, dest, imm);
}
void
MacroAssembler::lshift64(Imm32 imm, Register64 dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 64);
ma_dsll(dest.reg, dest.reg, imm);
}
void
MacroAssembler::rshiftPtr(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 64);
ma_dsrl(dest, dest, imm);
}
void
MacroAssembler::rshiftPtrArithmetic(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 64);
ma_dsra(dest, dest, imm);
}
void
MacroAssembler::rshift64(Imm32 imm, Register64 dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 64);
ma_dsrl(dest.reg, dest.reg, imm);
}

View File

@ -327,12 +327,14 @@ MacroAssembler::neg64(Register64 reg)
void
MacroAssembler::lshiftPtr(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 64);
shlq(imm, dest);
}
void
MacroAssembler::lshift64(Imm32 imm, Register64 dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 64);
lshiftPtr(imm, dest.reg);
}
@ -346,6 +348,7 @@ MacroAssembler::lshift64(Register shift, Register64 srcDest)
void
MacroAssembler::rshiftPtr(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 64);
shrq(imm, dest);
}
@ -365,12 +368,14 @@ MacroAssembler::rshift64(Register shift, Register64 srcDest)
void
MacroAssembler::rshiftPtrArithmetic(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 64);
sarq(imm, dest);
}
void
MacroAssembler::rshift64Arithmetic(Imm32 imm, Register64 dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 64);
rshiftPtrArithmetic(imm, dest.reg);
}
@ -582,7 +587,7 @@ MacroAssembler::branch64(Condition cond, Register64 lhs, Register64 rhs, Label*
void
MacroAssembler::branch64(Condition cond, const Address& lhs, Imm64 val, Label* label)
{
MOZ_ASSERT(cond == Assembler::NotEqual,
MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal,
"other condition codes not supported");
branchPtr(cond, lhs, ImmWord(val.value), label);
@ -592,7 +597,7 @@ void
MacroAssembler::branch64(Condition cond, const Address& lhs, const Address& rhs, Register scratch,
Label* label)
{
MOZ_ASSERT(cond == Assembler::NotEqual,
MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal,
"other condition codes not supported");
MOZ_ASSERT(lhs.base != scratch);
MOZ_ASSERT(rhs.base != scratch);
@ -746,7 +751,7 @@ MacroAssembler::truncateFloat32ToUInt64(Address src, Address dest, Register temp
// For unsigned conversion the case of [INT64, UINT64] needs to get handle seperately.
loadPtr(dest, temp);
branch32(Assembler::Condition::NotSigned, temp, Imm32(0), &done);
branchPtr(Assembler::Condition::NotSigned, temp, Imm32(0), &done);
// Move the value inside INT64 range.
storeFloat32(floatTemp, dest);
@ -774,7 +779,7 @@ MacroAssembler::truncateDoubleToUInt64(Address src, Address dest, Register temp,
// For unsigned conversion the case of [INT64, UINT64] needs to get handle seperately.
loadPtr(dest, temp);
branch32(Assembler::Condition::NotSigned, temp, Imm32(0), &done);
branchPtr(Assembler::Condition::NotSigned, temp, Imm32(0), &done);
// Move the value inside INT64 range.
storeDouble(floatTemp, dest);

View File

@ -351,13 +351,15 @@ MacroAssembler::neg64(Register64 reg)
void
MacroAssembler::lshiftPtr(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 32);
shll(imm, dest);
}
void
MacroAssembler::lshift64(Imm32 imm, Register64 dest)
{
if ((imm.value & INT32_MAX) < 32) {
MOZ_ASSERT(0 <= imm.value && imm.value < 64);
if (imm.value < 32) {
shldl(imm, dest.low, dest.high);
shll(imm, dest.low);
return;
@ -392,13 +394,15 @@ MacroAssembler::lshift64(Register shift, Register64 srcDest)
void
MacroAssembler::rshiftPtr(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 32);
shrl(imm, dest);
}
void
MacroAssembler::rshift64(Imm32 imm, Register64 dest)
{
if ((imm.value & INT32_MAX) < 32) {
MOZ_ASSERT(0 <= imm.value && imm.value < 64);
if (imm.value < 32) {
shrdl(imm, dest.high, dest.low);
shrl(imm, dest.high);
return;
@ -433,13 +437,15 @@ MacroAssembler::rshift64(Register shift, Register64 srcDest)
void
MacroAssembler::rshiftPtrArithmetic(Imm32 imm, Register dest)
{
MOZ_ASSERT(0 <= imm.value && imm.value < 32);
sarl(imm, dest);
}
void
MacroAssembler::rshift64Arithmetic(Imm32 imm, Register64 dest)
{
if ((imm.value & INT32_MAX) < 32) {
MOZ_ASSERT(0 <= imm.value && imm.value < 64);
if (imm.value < 32) {
shrdl(imm, dest.high, dest.low);
sarl(imm, dest.high);
return;
@ -715,27 +721,41 @@ MacroAssembler::branch64(Condition cond, Register64 lhs, Register64 rhs, Label*
void
MacroAssembler::branch64(Condition cond, const Address& lhs, Imm64 val, Label* label)
{
MOZ_ASSERT(cond == Assembler::NotEqual,
MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal,
"other condition codes not supported");
branch32(cond, lhs, val.firstHalf(), label);
Label done;
if (cond == Assembler::Equal)
branch32(Assembler::NotEqual, lhs, val.firstHalf(), &done);
else
branch32(Assembler::NotEqual, lhs, val.firstHalf(), label);
branch32(cond, Address(lhs.base, lhs.offset + sizeof(uint32_t)), val.secondHalf(), label);
bind(&done);
}
void
MacroAssembler::branch64(Condition cond, const Address& lhs, const Address& rhs, Register scratch,
Label* label)
{
MOZ_ASSERT(cond == Assembler::NotEqual,
MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal,
"other condition codes not supported");
MOZ_ASSERT(lhs.base != scratch);
MOZ_ASSERT(rhs.base != scratch);
Label done;
load32(rhs, scratch);
branch32(cond, lhs, scratch, label);
if (cond == Assembler::Equal)
branch32(Assembler::NotEqual, lhs, scratch, &done);
else
branch32(Assembler::NotEqual, lhs, scratch, label);
load32(Address(rhs.base, rhs.offset + sizeof(uint32_t)), scratch);
branch32(cond, Address(lhs.base, lhs.offset + sizeof(uint32_t)), scratch, label);
bind(&done);
}
void

View File

@ -114,6 +114,7 @@ if CONFIG['ENABLE_ION']:
'testJitDCEinGVN.cpp',
'testJitFoldsTo.cpp',
'testJitGVN.cpp',
'testJitMacroAssembler.cpp',
'testJitMoveEmitterCycles-mips32.cpp',
'testJitMoveEmitterCycles.cpp',
'testJitRangeAnalysis.cpp',

View File

@ -0,0 +1,476 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "jit/IonAnalysis.h"
#include "jit/Linker.h"
#include "jit/MacroAssembler.h"
#include "jit/MIRGenerator.h"
#include "jit/MIRGraph.h"
#include "jit/ValueNumbering.h"
#include "js/Value.h"
#include "jsapi-tests/tests.h"
#include "jit/MacroAssembler-inl.h"
using namespace js;
using namespace js::jit;
using mozilla::PositiveInfinity;
using mozilla::NegativeInfinity;
#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
typedef void (*EnterTest)();
static bool Prepare(MacroAssembler& masm)
{
AllocatableRegisterSet regs(RegisterSet::Volatile());
LiveRegisterSet save(regs.asLiveSet());
masm.PushRegsInMask(save);
return true;
}
static bool Execute(JSContext* cx, MacroAssembler& masm)
{
AllocatableRegisterSet regs(RegisterSet::Volatile());
LiveRegisterSet save(regs.asLiveSet());
masm.PopRegsInMask(save);
masm.ret(); // Add return statement to be sure.
if (masm.oom())
return false;
Linker linker(masm);
JitCode* code = linker.newCode<CanGC>(cx, OTHER_CODE);
if (!code)
return false;
if (!ExecutableAllocator::makeExecutable(code->raw(), code->bufferSize()))
return false;
EnterTest test = code->as<EnterTest>();
test();
return true;
}
BEGIN_TEST(testJitMacroAssembler_truncateDoubleToInt64)
{
MacroAssembler masm(cx);
if (!Prepare(masm))
return false;
AllocatableGeneralRegisterSet allRegs(GeneralRegisterSet::All());
AllocatableFloatRegisterSet allFloatRegs(FloatRegisterSet::All());
FloatRegister input = allFloatRegs.takeAny();
#ifdef JS_NUNBOX32
Register64 output(allRegs.takeAny(), allRegs.takeAny());
#else
Register64 output(allRegs.takeAny());
#endif
Register temp = allRegs.takeAny();
masm.reserveStack(sizeof(int32_t));
#define TEST(INPUT, OUTPUT) \
{ \
Label next; \
masm.loadConstantDouble(double(INPUT), input); \
masm.storeDouble(input, Operand(esp, 0)); \
masm.truncateDoubleToInt64(Address(esp, 0), Address(esp, 0), temp); \
masm.branch64(Assembler::Equal, Address(esp, 0), Imm64(OUTPUT), &next); \
masm.printf("truncateDoubleToInt64("#INPUT") failed\n"); \
masm.breakpoint(); \
masm.bind(&next); \
}
TEST(0, 0);
TEST(-0, 0);
TEST(1, 1);
TEST(9223372036854774784.0, 9223372036854774784);
TEST(-9223372036854775808.0, 0x8000000000000000);
TEST(9223372036854775808.0, 0x8000000000000000);
TEST(JS::GenericNaN(), 0x8000000000000000);
TEST(PositiveInfinity<double>(), 0x8000000000000000);
TEST(NegativeInfinity<double>(), 0x8000000000000000);
#undef TEST
masm.freeStack(sizeof(int32_t));
return Execute(cx, masm);
}
END_TEST(testJitMacroAssembler_truncateDoubleToInt64)
BEGIN_TEST(testJitMacroAssembler_truncateDoubleToUInt64)
{
MacroAssembler masm(cx);
if (!Prepare(masm))
return false;
AllocatableGeneralRegisterSet allRegs(GeneralRegisterSet::All());
AllocatableFloatRegisterSet allFloatRegs(FloatRegisterSet::All());
FloatRegister input = allFloatRegs.takeAny();
FloatRegister floatTemp = allFloatRegs.takeAny();
#ifdef JS_NUNBOX32
Register64 output(allRegs.takeAny(), allRegs.takeAny());
#else
Register64 output(allRegs.takeAny());
#endif
Register temp = allRegs.takeAny();
masm.reserveStack(sizeof(int32_t));
#define TEST(INPUT, OUTPUT) \
{ \
Label next; \
masm.loadConstantDouble(double(INPUT), input); \
masm.storeDouble(input, Operand(esp, 0)); \
masm.truncateDoubleToUInt64(Address(esp, 0), Address(esp, 0), temp, floatTemp); \
masm.branch64(Assembler::Equal, Address(esp, 0), Imm64(OUTPUT), &next); \
masm.printf("truncateDoubleToUInt64("#INPUT") failed\n"); \
masm.breakpoint(); \
masm.bind(&next); \
}
TEST(0, 0);
TEST(1, 1);
TEST(9223372036854774784.0, 9223372036854774784);
TEST((uint64_t)0x8000000000000000, 0x8000000000000000);
TEST((uint64_t)0x8000000000000001, 0x8000000000000000);
TEST((uint64_t)0x8006004000000001, 0x8006004000000000);
TEST(-0.0, 0);
TEST(-0.5, 0);
TEST(-0.99, 0);
TEST(JS::GenericNaN(), 0x8000000000000000);
TEST(PositiveInfinity<double>(), 0x8000000000000000);
TEST(NegativeInfinity<double>(), 0x8000000000000000);
#undef TEST
masm.freeStack(sizeof(int32_t));
return Execute(cx, masm);
}
END_TEST(testJitMacroAssembler_truncateDoubleToUInt64)
BEGIN_TEST(testJitMacroAssembler_branchDoubleNotInInt64Range)
{
MacroAssembler masm(cx);
if (!Prepare(masm))
return false;
AllocatableGeneralRegisterSet allRegs(GeneralRegisterSet::All());
AllocatableFloatRegisterSet allFloatRegs(FloatRegisterSet::All());
FloatRegister input = allFloatRegs.takeAny();
#ifdef JS_NUNBOX32
Register64 output(allRegs.takeAny(), allRegs.takeAny());
#else
Register64 output(allRegs.takeAny());
#endif
Register temp = allRegs.takeAny();
masm.reserveStack(sizeof(int32_t));
#define TEST(INPUT, OUTPUT) \
{ \
Label next; \
masm.loadConstantDouble(double(INPUT), input); \
masm.storeDouble(input, Operand(esp, 0)); \
if (OUTPUT) { \
masm.branchDoubleNotInInt64Range(Address(esp, 0), temp, &next); \
} else { \
Label fail; \
masm.branchDoubleNotInInt64Range(Address(esp, 0), temp, &fail); \
masm.jump(&next); \
masm.bind(&fail); \
} \
masm.printf("branchDoubleNotInInt64Range("#INPUT") failed\n"); \
masm.breakpoint(); \
masm.bind(&next); \
}
TEST(0, false);
TEST(-0, false);
TEST(1, false);
TEST(9223372036854774784.0, false);
TEST(-9223372036854775808.0, true);
TEST(9223372036854775808.0, true);
TEST(JS::GenericNaN(), true);
TEST(PositiveInfinity<double>(), true);
TEST(NegativeInfinity<double>(), true);
#undef TEST
masm.freeStack(sizeof(int32_t));
return Execute(cx, masm);
}
END_TEST(testJitMacroAssembler_branchDoubleNotInInt64Range)
BEGIN_TEST(testJitMacroAssembler_branchDoubleNotInUInt64Range)
{
MacroAssembler masm(cx);
if (!Prepare(masm))
return false;
AllocatableGeneralRegisterSet allRegs(GeneralRegisterSet::All());
AllocatableFloatRegisterSet allFloatRegs(FloatRegisterSet::All());
FloatRegister input = allFloatRegs.takeAny();
#ifdef JS_NUNBOX32
Register64 output(allRegs.takeAny(), allRegs.takeAny());
#else
Register64 output(allRegs.takeAny());
#endif
Register temp = allRegs.takeAny();
masm.reserveStack(sizeof(int32_t));
#define TEST(INPUT, OUTPUT) \
{ \
Label next; \
masm.loadConstantDouble(double(INPUT), input); \
masm.storeDouble(input, Operand(esp, 0)); \
if (OUTPUT) { \
masm.branchDoubleNotInUInt64Range(Address(esp, 0), temp, &next); \
} else { \
Label fail; \
masm.branchDoubleNotInUInt64Range(Address(esp, 0), temp, &fail); \
masm.jump(&next); \
masm.bind(&fail); \
} \
masm.printf("branchDoubleNotInUInt64Range("#INPUT") failed\n"); \
masm.breakpoint(); \
masm.bind(&next); \
}
TEST(0, false);
TEST(1, false);
TEST(9223372036854774784.0, false);
TEST((uint64_t)0x8000000000000000, false);
TEST((uint64_t)0x8000000000000001, false);
TEST((uint64_t)0x8006004000000001, false);
TEST(-0.0, true);
TEST(-0.5, true);
TEST(-0.99, true);
TEST(JS::GenericNaN(), true);
TEST(PositiveInfinity<double>(), true);
TEST(NegativeInfinity<double>(), true);
#undef TEST
masm.freeStack(sizeof(int32_t));
return Execute(cx, masm);
}
END_TEST(testJitMacroAssembler_branchDoubleNotInUInt64Range)
BEGIN_TEST(testJitMacroAssembler_lshift64)
{
MacroAssembler masm(cx);
if (!Prepare(masm))
return false;
AllocatableGeneralRegisterSet allRegs(GeneralRegisterSet::All());
AllocatableFloatRegisterSet allFloatRegs(FloatRegisterSet::All());
#if defined(JS_CODEGEN_X86)
Register shift = ecx;
allRegs.take(shift);
#elif defined(JS_CODEGEN_X64)
Register shift = rcx;
allRegs.take(shift);
#else
Register shift = allRegs.takeAny();
#endif
#ifdef JS_NUNBOX32
Register64 input(allRegs.takeAny(), allRegs.takeAny());
#else
Register64 input(allRegs.takeAny());
#endif
masm.reserveStack(sizeof(int32_t));
#define TEST(SHIFT, INPUT, OUTPUT) \
{ \
Label next; \
masm.move64(Imm64(INPUT), input); \
masm.move32(Imm32(SHIFT), shift); \
masm.lshift64(shift, input); \
masm.branch64(Assembler::Equal, input, Imm64(OUTPUT), &next); \
masm.printf("lshift64("#SHIFT", "#INPUT") failed\n"); \
masm.breakpoint(); \
masm.bind(&next); \
} \
{ \
Label next; \
masm.move64(Imm64(INPUT), input); \
masm.lshift64(Imm32(SHIFT & 0x3f), input); \
masm.branch64(Assembler::Equal, input, Imm64(OUTPUT), &next); \
masm.printf("lshift64(Imm32("#SHIFT"&0x3f), "#INPUT") failed\n"); \
masm.breakpoint(); \
masm.bind(&next); \
}
TEST(0, 1, 1);
TEST(1, 1, 2);
TEST(2, 1, 4);
TEST(32, 1, 0x0000000100000000);
TEST(33, 1, 0x0000000200000000);
TEST(0, -1, 0xffffffffffffffff);
TEST(1, -1, 0xfffffffffffffffe);
TEST(2, -1, 0xfffffffffffffffc);
TEST(32, -1, 0xffffffff00000000);
TEST(0xffffffff, 1, 0x8000000000000000);
TEST(0xfffffffe, 1, 0x4000000000000000);
TEST(0xfffffffd, 1, 0x2000000000000000);
TEST(0x80000001, 1, 2);
#undef TEST
masm.freeStack(sizeof(int32_t));
return Execute(cx, masm);
}
END_TEST(testJitMacroAssembler_lshift64)
BEGIN_TEST(testJitMacroAssembler_rshift64Arithmetic)
{
MacroAssembler masm(cx);
if (!Prepare(masm))
return false;
AllocatableGeneralRegisterSet allRegs(GeneralRegisterSet::All());
AllocatableFloatRegisterSet allFloatRegs(FloatRegisterSet::All());
#if defined(JS_CODEGEN_X86)
Register shift = ecx;
allRegs.take(shift);
#elif defined(JS_CODEGEN_X64)
Register shift = rcx;
allRegs.take(shift);
#else
Register shift = allRegs.takeAny();
#endif
#ifdef JS_NUNBOX32
Register64 input(allRegs.takeAny(), allRegs.takeAny());
#else
Register64 input(allRegs.takeAny());
#endif
masm.reserveStack(sizeof(int32_t));
#define TEST(SHIFT, INPUT, OUTPUT) \
{ \
Label next; \
masm.move64(Imm64(INPUT), input); \
masm.move32(Imm32(SHIFT), shift); \
masm.rshift64Arithmetic(shift, input); \
masm.branch64(Assembler::Equal, input, Imm64(OUTPUT), &next); \
masm.printf("rshift64Arithmetic("#SHIFT", "#INPUT") failed\n"); \
masm.breakpoint(); \
masm.bind(&next); \
} \
{ \
Label next; \
masm.move64(Imm64(INPUT), input); \
masm.rshift64Arithmetic(Imm32(SHIFT & 0x3f), input); \
masm.branch64(Assembler::Equal, input, Imm64(OUTPUT), &next); \
masm.printf("rshift64Arithmetic(Imm32("#SHIFT"&0x3f), "#INPUT") failed\n"); \
masm.breakpoint(); \
masm.bind(&next); \
}
TEST(0, 0x4000000000000000, 0x4000000000000000);
TEST(1, 0x4000000000000000, 0x2000000000000000);
TEST(2, 0x4000000000000000, 0x1000000000000000);
TEST(32, 0x4000000000000000, 0x0000000040000000);
TEST(0, 0x8000000000000000, 0x8000000000000000);
TEST(1, 0x8000000000000000, 0xc000000000000000);
TEST(2, 0x8000000000000000, 0xe000000000000000);
TEST(32, 0x8000000000000000, 0xffffffff80000000);
TEST(0xffffffff, 0x8000000000000000, 0xffffffffffffffff);
TEST(0xfffffffe, 0x8000000000000000, 0xfffffffffffffffe);
TEST(0xfffffffd, 0x8000000000000000, 0xfffffffffffffffc);
TEST(0x80000001, 0x8000000000000000, 0xc000000000000000);
#undef TEST
masm.freeStack(sizeof(int32_t));
return Execute(cx, masm);
}
END_TEST(testJitMacroAssembler_rshift64Arithmetic)
BEGIN_TEST(testJitMacroAssembler_rshift64)
{
MacroAssembler masm(cx);
if (!Prepare(masm))
return false;
AllocatableGeneralRegisterSet allRegs(GeneralRegisterSet::All());
AllocatableFloatRegisterSet allFloatRegs(FloatRegisterSet::All());
#if defined(JS_CODEGEN_X86)
Register shift = ecx;
allRegs.take(shift);
#elif defined(JS_CODEGEN_X64)
Register shift = rcx;
allRegs.take(shift);
#else
Register shift = allRegs.takeAny();
#endif
#ifdef JS_NUNBOX32
Register64 input(allRegs.takeAny(), allRegs.takeAny());
#else
Register64 input(allRegs.takeAny());
#endif
masm.reserveStack(sizeof(int32_t));
#define TEST(SHIFT, INPUT, OUTPUT) \
{ \
Label next; \
masm.move64(Imm64(INPUT), input); \
masm.move32(Imm32(SHIFT), shift); \
masm.rshift64(shift, input); \
masm.branch64(Assembler::Equal, input, Imm64(OUTPUT), &next); \
masm.printf("rshift64("#SHIFT", "#INPUT") failed\n"); \
masm.breakpoint(); \
masm.bind(&next); \
} \
{ \
Label next; \
masm.move64(Imm64(INPUT), input); \
masm.rshift64(Imm32(SHIFT & 0x3f), input); \
masm.branch64(Assembler::Equal, input, Imm64(OUTPUT), &next); \
masm.printf("rshift64(Imm32("#SHIFT"&0x3f), "#INPUT") failed\n"); \
masm.breakpoint(); \
masm.bind(&next); \
}
TEST(0, 0x4000000000000000, 0x4000000000000000);
TEST(1, 0x4000000000000000, 0x2000000000000000);
TEST(2, 0x4000000000000000, 0x1000000000000000);
TEST(32, 0x4000000000000000, 0x0000000040000000);
TEST(0, 0x8000000000000000, 0x8000000000000000);
TEST(1, 0x8000000000000000, 0x4000000000000000);
TEST(2, 0x8000000000000000, 0x2000000000000000);
TEST(32, 0x8000000000000000, 0x0000000080000000);
TEST(0xffffffff, 0x8000000000000000, 0x0000000000000001);
TEST(0xfffffffe, 0x8000000000000000, 0x0000000000000002);
TEST(0xfffffffd, 0x8000000000000000, 0x0000000000000004);
TEST(0x80000001, 0x8000000000000000, 0x4000000000000000);
#undef TEST
masm.freeStack(sizeof(int32_t));
return Execute(cx, masm);
}
END_TEST(testJitMacroAssembler_rshift64)
#endif