aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/test/cctest/test-assembler-arm.cc
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2016-12-23 16:30:57 +0100
committerMichaël Zasso <targos@protonmail.com>2017-01-26 22:46:17 +0100
commit2739185b790e040c3b044c577327f5d44bffad4a (patch)
tree29a466999212f4c85958379d9d400eec8a185ba5 /deps/v8/test/cctest/test-assembler-arm.cc
parenta67a04d7654faaa04c8da00e42981ebc9fd0911c (diff)
downloadandroid-node-v8-2739185b790e040c3b044c577327f5d44bffad4a.tar.gz
android-node-v8-2739185b790e040c3b044c577327f5d44bffad4a.tar.bz2
android-node-v8-2739185b790e040c3b044c577327f5d44bffad4a.zip
deps: update V8 to 5.5.372.40
PR-URL: https://github.com/nodejs/node/pull/9618 Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/v8/test/cctest/test-assembler-arm.cc')
-rw-r--r--deps/v8/test/cctest/test-assembler-arm.cc572
1 files changed, 504 insertions, 68 deletions
diff --git a/deps/v8/test/cctest/test-assembler-arm.cc b/deps/v8/test/cctest/test-assembler-arm.cc
index 93a19c1a14..de024f8869 100644
--- a/deps/v8/test/cctest/test-assembler-arm.cc
+++ b/deps/v8/test/cctest/test-assembler-arm.cc
@@ -30,11 +30,11 @@
#include "src/v8.h"
#include "test/cctest/cctest.h"
-#include "src/arm/assembler-arm-inl.h"
#include "src/arm/simulator-arm.h"
#include "src/base/utils/random-number-generator.h"
#include "src/disassembler.h"
#include "src/factory.h"
+#include "src/macro-assembler.h"
#include "src/ostreams.h"
using namespace v8::base;
@@ -244,9 +244,8 @@ TEST(4) {
Assembler assm(isolate, NULL, 0);
Label L, C;
-
- if (CpuFeatures::IsSupported(VFP3)) {
- CpuFeatureScope scope(&assm, VFP3);
+ if (CpuFeatures::IsSupported(VFPv3)) {
+ CpuFeatureScope scope(&assm, VFPv3);
__ mov(ip, Operand(sp));
__ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
@@ -267,12 +266,12 @@ TEST(4) {
// Load t.x and t.y, switch values, and store back to the struct.
__ vldr(s0, r4, offsetof(T, x));
- __ vldr(s31, r4, offsetof(T, y));
- __ vmov(s16, s0);
- __ vmov(s0, s31);
- __ vmov(s31, s16);
+ __ vldr(s1, r4, offsetof(T, y));
+ __ vmov(s2, s0);
+ __ vmov(s0, s1);
+ __ vmov(s1, s2);
__ vstr(s0, r4, offsetof(T, x));
- __ vstr(s31, r4, offsetof(T, y));
+ __ vstr(s1, r4, offsetof(T, y));
// Move a literal into a register that can be encoded in the instruction.
__ vmov(d4, 1.0);
@@ -285,13 +284,13 @@ TEST(4) {
// Convert from floating point to integer.
__ vmov(d4, 2.0);
- __ vcvt_s32_f64(s31, d4);
- __ vstr(s31, r4, offsetof(T, i));
+ __ vcvt_s32_f64(s1, d4);
+ __ vstr(s1, r4, offsetof(T, i));
// Convert from integer to floating point.
__ mov(lr, Operand(42));
- __ vmov(s31, lr);
- __ vcvt_f64_s32(d4, s31);
+ __ vmov(s1, lr);
+ __ vcvt_f64_s32(d4, s1);
__ vstr(d4, r4, offsetof(T, f));
// Convert from fixed point to floating point.
@@ -450,62 +449,57 @@ static void TestRoundingMode(VCVTTypes types,
Assembler assm(isolate, NULL, 0);
- if (CpuFeatures::IsSupported(VFP3)) {
- CpuFeatureScope scope(&assm, VFP3);
-
- Label wrong_exception;
-
- __ vmrs(r1);
- // Set custom FPSCR.
- __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask));
- __ orr(r2, r2, Operand(mode));
- __ vmsr(r2);
-
- // Load value, convert, and move back result to r0 if everything went well.
- __ vmov(d1, value);
- switch (types) {
- case s32_f64:
- __ vcvt_s32_f64(s0, d1, kFPSCRRounding);
- break;
-
- case u32_f64:
- __ vcvt_u32_f64(s0, d1, kFPSCRRounding);
- break;
-
- default:
- UNREACHABLE();
- break;
- }
- // Check for vfp exceptions
- __ vmrs(r2);
- __ tst(r2, Operand(kVFPExceptionMask));
- // Check that we behaved as expected.
- __ b(&wrong_exception,
- expected_exception ? eq : ne);
- // There was no exception. Retrieve the result and return.
- __ vmov(r0, s0);
- __ mov(pc, Operand(lr));
+ Label wrong_exception;
- // The exception behaviour is not what we expected.
- // Load a special value and return.
- __ bind(&wrong_exception);
- __ mov(r0, Operand(11223344));
- __ mov(pc, Operand(lr));
+ __ vmrs(r1);
+ // Set custom FPSCR.
+ __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask));
+ __ orr(r2, r2, Operand(mode));
+ __ vmsr(r2);
+
+ // Load value, convert, and move back result to r0 if everything went well.
+ __ vmov(d1, value);
+ switch (types) {
+ case s32_f64:
+ __ vcvt_s32_f64(s0, d1, kFPSCRRounding);
+ break;
+
+ case u32_f64:
+ __ vcvt_u32_f64(s0, d1, kFPSCRRounding);
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+ // Check for vfp exceptions
+ __ vmrs(r2);
+ __ tst(r2, Operand(kVFPExceptionMask));
+ // Check that we behaved as expected.
+ __ b(&wrong_exception, expected_exception ? eq : ne);
+ // There was no exception. Retrieve the result and return.
+ __ vmov(r0, s0);
+ __ mov(pc, Operand(lr));
- CodeDesc desc;
- assm.GetCode(&desc);
- Handle<Code> code = isolate->factory()->NewCode(
- desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+ // The exception behaviour is not what we expected.
+ // Load a special value and return.
+ __ bind(&wrong_exception);
+ __ mov(r0, Operand(11223344));
+ __ mov(pc, Operand(lr));
+
+ CodeDesc desc;
+ assm.GetCode(&desc);
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef DEBUG
- OFStream os(stdout);
- code->Print(os);
+ OFStream os(stdout);
+ code->Print(os);
#endif
- F1 f = FUNCTION_CAST<F1>(code->entry());
- int res =
- reinterpret_cast<int>(CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
- ::printf("res = %d\n", res);
- CHECK_EQ(expected, res);
- }
+ F1 f = FUNCTION_CAST<F1>(code->entry());
+ int res =
+ reinterpret_cast<int>(CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
+ ::printf("res = %d\n", res);
+ CHECK_EQ(expected, res);
}
@@ -1051,9 +1045,8 @@ TEST(13) {
Assembler assm(isolate, NULL, 0);
Label L, C;
-
- if (CpuFeatures::IsSupported(VFP3)) {
- CpuFeatureScope scope(&assm, VFP3);
+ if (CpuFeatures::IsSupported(VFPv3)) {
+ CpuFeatureScope scope(&assm, VFPv3);
__ stm(db_w, sp, r4.bit() | lr.bit());
@@ -2381,6 +2374,400 @@ TEST(ARMv8_vsel) {
}
}
+TEST(ARMv8_vminmax_f64) {
+ // Test the vminnm and vmaxnm floating point instructions.
+ CcTest::InitializeVM();
+ Isolate* isolate = CcTest::i_isolate();
+ HandleScope scope(isolate);
+
+ Assembler assm(isolate, NULL, 0);
+
+ struct Inputs {
+ double left_;
+ double right_;
+ };
+
+ struct Results {
+ double vminnm_;
+ double vmaxnm_;
+ };
+
+ if (CpuFeatures::IsSupported(ARMv8)) {
+ CpuFeatureScope scope(&assm, ARMv8);
+
+ // Create a helper function:
+ // void TestVminmax(const Inputs* inputs,
+ // Results* results);
+ __ vldr(d1, r0, offsetof(Inputs, left_));
+ __ vldr(d2, r0, offsetof(Inputs, right_));
+
+ __ vminnm(d0, d1, d2);
+ __ vstr(d0, r1, offsetof(Results, vminnm_));
+ __ vmaxnm(d0, d1, d2);
+ __ vstr(d0, r1, offsetof(Results, vmaxnm_));
+
+ __ bx(lr);
+
+ CodeDesc desc;
+ assm.GetCode(&desc);
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+#ifdef DEBUG
+ OFStream os(stdout);
+ code->Print(os);
+#endif
+ F4 f = FUNCTION_CAST<F4>(code->entry());
+ Object* dummy = nullptr;
+ USE(dummy);
+
+#define CHECK_VMINMAX(left, right, vminnm, vmaxnm) \
+ do { \
+ Inputs inputs = {left, right}; \
+ Results results; \
+ dummy = CALL_GENERATED_CODE(isolate, f, &inputs, &results, 0, 0, 0); \
+ /* Use a bit_cast to correctly identify -0.0 and NaNs. */ \
+ CHECK_EQ(bit_cast<uint64_t>(vminnm), bit_cast<uint64_t>(results.vminnm_)); \
+ CHECK_EQ(bit_cast<uint64_t>(vmaxnm), bit_cast<uint64_t>(results.vmaxnm_)); \
+ } while (0);
+
+ double nan_a = bit_cast<double>(UINT64_C(0x7ff8000000000001));
+ double nan_b = bit_cast<double>(UINT64_C(0x7ff8000000000002));
+
+ CHECK_VMINMAX(1.0, -1.0, -1.0, 1.0);
+ CHECK_VMINMAX(-1.0, 1.0, -1.0, 1.0);
+ CHECK_VMINMAX(0.0, -1.0, -1.0, 0.0);
+ CHECK_VMINMAX(-1.0, 0.0, -1.0, 0.0);
+ CHECK_VMINMAX(-0.0, -1.0, -1.0, -0.0);
+ CHECK_VMINMAX(-1.0, -0.0, -1.0, -0.0);
+ CHECK_VMINMAX(0.0, 1.0, 0.0, 1.0);
+ CHECK_VMINMAX(1.0, 0.0, 0.0, 1.0);
+
+ CHECK_VMINMAX(0.0, 0.0, 0.0, 0.0);
+ CHECK_VMINMAX(-0.0, -0.0, -0.0, -0.0);
+ CHECK_VMINMAX(-0.0, 0.0, -0.0, 0.0);
+ CHECK_VMINMAX(0.0, -0.0, -0.0, 0.0);
+
+ CHECK_VMINMAX(0.0, nan_a, 0.0, 0.0);
+ CHECK_VMINMAX(nan_a, 0.0, 0.0, 0.0);
+ CHECK_VMINMAX(nan_a, nan_b, nan_a, nan_a);
+ CHECK_VMINMAX(nan_b, nan_a, nan_b, nan_b);
+
+#undef CHECK_VMINMAX
+ }
+}
+
+TEST(ARMv8_vminmax_f32) {
+ // Test the vminnm and vmaxnm floating point instructions.
+ CcTest::InitializeVM();
+ Isolate* isolate = CcTest::i_isolate();
+ HandleScope scope(isolate);
+
+ Assembler assm(isolate, NULL, 0);
+
+ struct Inputs {
+ float left_;
+ float right_;
+ };
+
+ struct Results {
+ float vminnm_;
+ float vmaxnm_;
+ };
+
+ if (CpuFeatures::IsSupported(ARMv8)) {
+ CpuFeatureScope scope(&assm, ARMv8);
+
+ // Create a helper function:
+ // void TestVminmax(const Inputs* inputs,
+ // Results* results);
+ __ vldr(s1, r0, offsetof(Inputs, left_));
+ __ vldr(s2, r0, offsetof(Inputs, right_));
+
+ __ vminnm(s0, s1, s2);
+ __ vstr(s0, r1, offsetof(Results, vminnm_));
+ __ vmaxnm(s0, s1, s2);
+ __ vstr(s0, r1, offsetof(Results, vmaxnm_));
+
+ __ bx(lr);
+
+ CodeDesc desc;
+ assm.GetCode(&desc);
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+#ifdef DEBUG
+ OFStream os(stdout);
+ code->Print(os);
+#endif
+ F4 f = FUNCTION_CAST<F4>(code->entry());
+ Object* dummy = nullptr;
+ USE(dummy);
+
+#define CHECK_VMINMAX(left, right, vminnm, vmaxnm) \
+ do { \
+ Inputs inputs = {left, right}; \
+ Results results; \
+ dummy = CALL_GENERATED_CODE(isolate, f, &inputs, &results, 0, 0, 0); \
+ /* Use a bit_cast to correctly identify -0.0 and NaNs. */ \
+ CHECK_EQ(bit_cast<uint32_t>(vminnm), bit_cast<uint32_t>(results.vminnm_)); \
+ CHECK_EQ(bit_cast<uint32_t>(vmaxnm), bit_cast<uint32_t>(results.vmaxnm_)); \
+ } while (0);
+
+ float nan_a = bit_cast<float>(UINT32_C(0x7fc00001));
+ float nan_b = bit_cast<float>(UINT32_C(0x7fc00002));
+
+ CHECK_VMINMAX(1.0f, -1.0f, -1.0f, 1.0f);
+ CHECK_VMINMAX(-1.0f, 1.0f, -1.0f, 1.0f);
+ CHECK_VMINMAX(0.0f, -1.0f, -1.0f, 0.0f);
+ CHECK_VMINMAX(-1.0f, 0.0f, -1.0f, 0.0f);
+ CHECK_VMINMAX(-0.0f, -1.0f, -1.0f, -0.0f);
+ CHECK_VMINMAX(-1.0f, -0.0f, -1.0f, -0.0f);
+ CHECK_VMINMAX(0.0f, 1.0f, 0.0f, 1.0f);
+ CHECK_VMINMAX(1.0f, 0.0f, 0.0f, 1.0f);
+
+ CHECK_VMINMAX(0.0f, 0.0f, 0.0f, 0.0f);
+ CHECK_VMINMAX(-0.0f, -0.0f, -0.0f, -0.0f);
+ CHECK_VMINMAX(-0.0f, 0.0f, -0.0f, 0.0f);
+ CHECK_VMINMAX(0.0f, -0.0f, -0.0f, 0.0f);
+
+ CHECK_VMINMAX(0.0f, nan_a, 0.0f, 0.0f);
+ CHECK_VMINMAX(nan_a, 0.0f, 0.0f, 0.0f);
+ CHECK_VMINMAX(nan_a, nan_b, nan_a, nan_a);
+ CHECK_VMINMAX(nan_b, nan_a, nan_b, nan_b);
+
+#undef CHECK_VMINMAX
+ }
+}
+
+template <typename T, typename Inputs, typename Results>
+static F4 GenerateMacroFloatMinMax(MacroAssembler& assm) {
+ T a = T::from_code(0); // d0/s0
+ T b = T::from_code(1); // d1/s1
+ T c = T::from_code(2); // d2/s2
+
+ // Create a helper function:
+ // void TestFloatMinMax(const Inputs* inputs,
+ // Results* results);
+ Label ool_min_abc, ool_min_aab, ool_min_aba;
+ Label ool_max_abc, ool_max_aab, ool_max_aba;
+
+ Label done_min_abc, done_min_aab, done_min_aba;
+ Label done_max_abc, done_max_aab, done_max_aba;
+
+ // a = min(b, c);
+ __ vldr(b, r0, offsetof(Inputs, left_));
+ __ vldr(c, r0, offsetof(Inputs, right_));
+ __ FloatMin(a, b, c, &ool_min_abc);
+ __ bind(&done_min_abc);
+ __ vstr(a, r1, offsetof(Results, min_abc_));
+
+ // a = min(a, b);
+ __ vldr(a, r0, offsetof(Inputs, left_));
+ __ vldr(b, r0, offsetof(Inputs, right_));
+ __ FloatMin(a, a, b, &ool_min_aab);
+ __ bind(&done_min_aab);
+ __ vstr(a, r1, offsetof(Results, min_aab_));
+
+ // a = min(b, a);
+ __ vldr(b, r0, offsetof(Inputs, left_));
+ __ vldr(a, r0, offsetof(Inputs, right_));
+ __ FloatMin(a, b, a, &ool_min_aba);
+ __ bind(&done_min_aba);
+ __ vstr(a, r1, offsetof(Results, min_aba_));
+
+ // a = max(b, c);
+ __ vldr(b, r0, offsetof(Inputs, left_));
+ __ vldr(c, r0, offsetof(Inputs, right_));
+ __ FloatMax(a, b, c, &ool_max_abc);
+ __ bind(&done_max_abc);
+ __ vstr(a, r1, offsetof(Results, max_abc_));
+
+ // a = max(a, b);
+ __ vldr(a, r0, offsetof(Inputs, left_));
+ __ vldr(b, r0, offsetof(Inputs, right_));
+ __ FloatMax(a, a, b, &ool_max_aab);
+ __ bind(&done_max_aab);
+ __ vstr(a, r1, offsetof(Results, max_aab_));
+
+ // a = max(b, a);
+ __ vldr(b, r0, offsetof(Inputs, left_));
+ __ vldr(a, r0, offsetof(Inputs, right_));
+ __ FloatMax(a, b, a, &ool_max_aba);
+ __ bind(&done_max_aba);
+ __ vstr(a, r1, offsetof(Results, max_aba_));
+
+ __ bx(lr);
+
+ // Generate out-of-line cases.
+ __ bind(&ool_min_abc);
+ __ FloatMinOutOfLine(a, b, c);
+ __ b(&done_min_abc);
+
+ __ bind(&ool_min_aab);
+ __ FloatMinOutOfLine(a, a, b);
+ __ b(&done_min_aab);
+
+ __ bind(&ool_min_aba);
+ __ FloatMinOutOfLine(a, b, a);
+ __ b(&done_min_aba);
+
+ __ bind(&ool_max_abc);
+ __ FloatMaxOutOfLine(a, b, c);
+ __ b(&done_max_abc);
+
+ __ bind(&ool_max_aab);
+ __ FloatMaxOutOfLine(a, a, b);
+ __ b(&done_max_aab);
+
+ __ bind(&ool_max_aba);
+ __ FloatMaxOutOfLine(a, b, a);
+ __ b(&done_max_aba);
+
+ CodeDesc desc;
+ assm.GetCode(&desc);
+ Handle<Code> code = assm.isolate()->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+#ifdef DEBUG
+ OFStream os(stdout);
+ code->Print(os);
+#endif
+ return FUNCTION_CAST<F4>(code->entry());
+}
+
+TEST(macro_float_minmax_f64) {
+ // Test the FloatMin and FloatMax macros.
+ CcTest::InitializeVM();
+ Isolate* isolate = CcTest::i_isolate();
+ HandleScope scope(isolate);
+
+ MacroAssembler assm(isolate, NULL, 0, CodeObjectRequired::kYes);
+
+ struct Inputs {
+ double left_;
+ double right_;
+ };
+
+ struct Results {
+ // Check all register aliasing possibilities in order to exercise all
+ // code-paths in the macro assembler.
+ double min_abc_;
+ double min_aab_;
+ double min_aba_;
+ double max_abc_;
+ double max_aab_;
+ double max_aba_;
+ };
+
+ F4 f = GenerateMacroFloatMinMax<DwVfpRegister, Inputs, Results>(assm);
+
+ Object* dummy = nullptr;
+ USE(dummy);
+
+#define CHECK_MINMAX(left, right, min, max) \
+ do { \
+ Inputs inputs = {left, right}; \
+ Results results; \
+ dummy = CALL_GENERATED_CODE(isolate, f, &inputs, &results, 0, 0, 0); \
+ /* Use a bit_cast to correctly identify -0.0 and NaNs. */ \
+ CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_abc_)); \
+ CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_aab_)); \
+ CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_aba_)); \
+ CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_abc_)); \
+ CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_aab_)); \
+ CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_aba_)); \
+ } while (0)
+
+ double nan_a = bit_cast<double>(UINT64_C(0x7ff8000000000001));
+ double nan_b = bit_cast<double>(UINT64_C(0x7ff8000000000002));
+
+ CHECK_MINMAX(1.0, -1.0, -1.0, 1.0);
+ CHECK_MINMAX(-1.0, 1.0, -1.0, 1.0);
+ CHECK_MINMAX(0.0, -1.0, -1.0, 0.0);
+ CHECK_MINMAX(-1.0, 0.0, -1.0, 0.0);
+ CHECK_MINMAX(-0.0, -1.0, -1.0, -0.0);
+ CHECK_MINMAX(-1.0, -0.0, -1.0, -0.0);
+ CHECK_MINMAX(0.0, 1.0, 0.0, 1.0);
+ CHECK_MINMAX(1.0, 0.0, 0.0, 1.0);
+
+ CHECK_MINMAX(0.0, 0.0, 0.0, 0.0);
+ CHECK_MINMAX(-0.0, -0.0, -0.0, -0.0);
+ CHECK_MINMAX(-0.0, 0.0, -0.0, 0.0);
+ CHECK_MINMAX(0.0, -0.0, -0.0, 0.0);
+
+ CHECK_MINMAX(0.0, nan_a, nan_a, nan_a);
+ CHECK_MINMAX(nan_a, 0.0, nan_a, nan_a);
+ CHECK_MINMAX(nan_a, nan_b, nan_a, nan_a);
+ CHECK_MINMAX(nan_b, nan_a, nan_b, nan_b);
+
+#undef CHECK_MINMAX
+}
+
+TEST(macro_float_minmax_f32) {
+ // Test the FloatMin and FloatMax macros.
+ CcTest::InitializeVM();
+ Isolate* isolate = CcTest::i_isolate();
+ HandleScope scope(isolate);
+
+ MacroAssembler assm(isolate, NULL, 0, CodeObjectRequired::kYes);
+
+ struct Inputs {
+ float left_;
+ float right_;
+ };
+
+ struct Results {
+ // Check all register aliasing possibilities in order to exercise all
+ // code-paths in the macro assembler.
+ float min_abc_;
+ float min_aab_;
+ float min_aba_;
+ float max_abc_;
+ float max_aab_;
+ float max_aba_;
+ };
+
+ F4 f = GenerateMacroFloatMinMax<SwVfpRegister, Inputs, Results>(assm);
+ Object* dummy = nullptr;
+ USE(dummy);
+
+#define CHECK_MINMAX(left, right, min, max) \
+ do { \
+ Inputs inputs = {left, right}; \
+ Results results; \
+ dummy = CALL_GENERATED_CODE(isolate, f, &inputs, &results, 0, 0, 0); \
+ /* Use a bit_cast to correctly identify -0.0 and NaNs. */ \
+ CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_abc_)); \
+ CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_aab_)); \
+ CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_aba_)); \
+ CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_abc_)); \
+ CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_aab_)); \
+ CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_aba_)); \
+ } while (0)
+
+ float nan_a = bit_cast<float>(UINT32_C(0x7fc00001));
+ float nan_b = bit_cast<float>(UINT32_C(0x7fc00002));
+
+ CHECK_MINMAX(1.0f, -1.0f, -1.0f, 1.0f);
+ CHECK_MINMAX(-1.0f, 1.0f, -1.0f, 1.0f);
+ CHECK_MINMAX(0.0f, -1.0f, -1.0f, 0.0f);
+ CHECK_MINMAX(-1.0f, 0.0f, -1.0f, 0.0f);
+ CHECK_MINMAX(-0.0f, -1.0f, -1.0f, -0.0f);
+ CHECK_MINMAX(-1.0f, -0.0f, -1.0f, -0.0f);
+ CHECK_MINMAX(0.0f, 1.0f, 0.0f, 1.0f);
+ CHECK_MINMAX(1.0f, 0.0f, 0.0f, 1.0f);
+
+ CHECK_MINMAX(0.0f, 0.0f, 0.0f, 0.0f);
+ CHECK_MINMAX(-0.0f, -0.0f, -0.0f, -0.0f);
+ CHECK_MINMAX(-0.0f, 0.0f, -0.0f, 0.0f);
+ CHECK_MINMAX(0.0f, -0.0f, -0.0f, 0.0f);
+
+ CHECK_MINMAX(0.0f, nan_a, nan_a, nan_a);
+ CHECK_MINMAX(nan_a, 0.0f, nan_a, nan_a);
+ CHECK_MINMAX(nan_a, nan_b, nan_a, nan_a);
+ CHECK_MINMAX(nan_b, nan_a, nan_b, nan_b);
+
+#undef CHECK_MINMAX
+}
+
TEST(unaligned_loads) {
// All supported ARM targets allow unaligned accesses.
CcTest::InitializeVM();
@@ -2495,6 +2882,55 @@ TEST(unaligned_stores) {
}
}
+TEST(vswp) {
+ CcTest::InitializeVM();
+ Isolate* isolate = CcTest::i_isolate();
+ HandleScope scope(isolate);
+ Assembler assm(isolate, NULL, 0);
+
+ typedef struct {
+ double result0;
+ double result1;
+ double result2;
+ double result3;
+ } T;
+ T t;
+
+ __ vmov(d0, 1.0);
+ __ vmov(d1, -1.0);
+ __ vswp(d0, d1);
+ __ vstr(d0, r0, offsetof(T, result0));
+ __ vstr(d1, r0, offsetof(T, result1));
+
+ if (CpuFeatures::IsSupported(VFP32DREGS)) {
+ __ vmov(d30, 1.0);
+ __ vmov(d31, -1.0);
+ __ vswp(d30, d31);
+ __ vstr(d30, r0, offsetof(T, result2));
+ __ vstr(d31, r0, offsetof(T, result3));
+ }
+
+ __ bx(lr);
+
+ CodeDesc desc;
+ assm.GetCode(&desc);
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+#ifdef DEBUG
+ OFStream os(stdout);
+ code->Print(os);
+#endif
+ F3 f = FUNCTION_CAST<F3>(code->entry());
+ Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
+ USE(dummy);
+ CHECK_EQ(-1.0, t.result0);
+ CHECK_EQ(1.0, t.result1);
+ if (CpuFeatures::IsSupported(VFP32DREGS)) {
+ CHECK_EQ(-1.0, t.result2);
+ CHECK_EQ(1.0, t.result3);
+ }
+}
+
TEST(regress4292_b) {
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();