| Index: test/cctest/test-assembler-mips64.cc
|
| diff --git a/test/cctest/test-assembler-mips64.cc b/test/cctest/test-assembler-mips64.cc
|
| index 97f9984b212288876ce8a345038c3fef5a53846b..4798bdbcddcf55e34c90dc23f4f3c01c9a5b144b 100644
|
| --- a/test/cctest/test-assembler-mips64.cc
|
| +++ b/test/cctest/test-assembler-mips64.cc
|
| @@ -3284,4 +3284,1166 @@ TEST(jump_tables3) {
|
| }
|
|
|
|
|
| +TEST(BITSWAP) {
|
| + // Test BITSWAP
|
| + if (kArchVariant == kMips64r6) {
|
| + CcTest::InitializeVM();
|
| + Isolate* isolate = CcTest::i_isolate();
|
| + HandleScope scope(isolate);
|
| +
|
| + typedef struct {
|
| + int64_t r1;
|
| + int64_t r2;
|
| + int64_t r3;
|
| + int64_t r4;
|
| + int64_t r5;
|
| + int64_t r6;
|
| + } T;
|
| + T t;
|
| +
|
| + Assembler assm(isolate, NULL, 0);
|
| +
|
| + __ ld(a4, MemOperand(a0, OFFSET_OF(T, r1)));
|
| + __ nop();
|
| + __ bitswap(a6, a4);
|
| + __ sd(a6, MemOperand(a0, OFFSET_OF(T, r1)));
|
| +
|
| + __ ld(a4, MemOperand(a0, OFFSET_OF(T, r2)));
|
| + __ nop();
|
| + __ bitswap(a6, a4);
|
| + __ sd(a6, MemOperand(a0, OFFSET_OF(T, r2)));
|
| +
|
| + __ ld(a4, MemOperand(a0, OFFSET_OF(T, r3)));
|
| + __ nop();
|
| + __ bitswap(a6, a4);
|
| + __ sd(a6, MemOperand(a0, OFFSET_OF(T, r3)));
|
| +
|
| + __ ld(a4, MemOperand(a0, OFFSET_OF(T, r4)));
|
| + __ nop();
|
| + __ bitswap(a6, a4);
|
| + __ sd(a6, MemOperand(a0, OFFSET_OF(T, r4)));
|
| +
|
| + __ ld(a4, MemOperand(a0, OFFSET_OF(T, r5)));
|
| + __ nop();
|
| + __ dbitswap(a6, a4);
|
| + __ sd(a6, MemOperand(a0, OFFSET_OF(T, r5)));
|
| +
|
| + __ ld(a4, MemOperand(a0, OFFSET_OF(T, r6)));
|
| + __ nop();
|
| + __ dbitswap(a6, a4);
|
| + __ sd(a6, MemOperand(a0, OFFSET_OF(T, r6)));
|
| +
|
| + __ jr(ra);
|
| + __ nop();
|
| +
|
| + CodeDesc desc;
|
| + assm.GetCode(&desc);
|
| + Handle<Code> code = isolate->factory()->NewCode(
|
| + desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
|
| + F3 f = FUNCTION_CAST<F3>(code->entry());
|
| + t.r1 = 0x00102100781A15C3;
|
| + t.r2 = 0x001021008B71FCDE;
|
| + t.r3 = 0xFF8017FF781A15C3;
|
| + t.r4 = 0xFF8017FF8B71FCDE;
|
| + t.r5 = 0x10C021098B71FCDE;
|
| + t.r6 = 0xFB8017FF781A15C3;
|
| + Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
|
| + USE(dummy);
|
| +
|
| + CHECK_EQ(static_cast<int64_t>(0x000000001E58A8C3L), t.r1);
|
| + CHECK_EQ(static_cast<int64_t>(0xFFFFFFFFD18E3F7BL), t.r2);
|
| + CHECK_EQ(static_cast<int64_t>(0x000000001E58A8C3L), t.r3);
|
| + CHECK_EQ(static_cast<int64_t>(0xFFFFFFFFD18E3F7BL), t.r4);
|
| + CHECK_EQ(static_cast<int64_t>(0x08038490D18E3F7BL), t.r5);
|
| + CHECK_EQ(static_cast<int64_t>(0xDF01E8FF1E58A8C3L), t.r6);
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(class_fmt) {
|
| + if (kArchVariant == kMips64r6) {
|
| + // Test CLASS.fmt instruction.
|
| + CcTest::InitializeVM();
|
| + Isolate* isolate = CcTest::i_isolate();
|
| + HandleScope scope(isolate);
|
| +
|
| + typedef struct {
|
| + double dSignalingNan;
|
| + double dQuietNan;
|
| + double dNegInf;
|
| + double dNegNorm;
|
| + double dNegSubnorm;
|
| + double dNegZero;
|
| + double dPosInf;
|
| + double dPosNorm;
|
| + double dPosSubnorm;
|
| + double dPosZero;
|
| + float fSignalingNan;
|
| + float fQuietNan;
|
| + float fNegInf;
|
| + float fNegNorm;
|
| + float fNegSubnorm;
|
| + float fNegZero;
|
| + float fPosInf;
|
| + float fPosNorm;
|
| + float fPosSubnorm;
|
| + float fPosZero; } T;
|
| + T t;
|
| +
|
| + // Create a function that accepts &t, and loads, manipulates, and stores
|
| + // the doubles t.a ... t.f.
|
| + MacroAssembler assm(isolate, NULL, 0);
|
| +
|
| + __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, dSignalingNan)));
|
| + __ class_d(f6, f4);
|
| + __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, dSignalingNan)));
|
| +
|
| + __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, dQuietNan)));
|
| + __ class_d(f6, f4);
|
| + __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, dQuietNan)));
|
| +
|
| + __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, dNegInf)));
|
| + __ class_d(f6, f4);
|
| + __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, dNegInf)));
|
| +
|
| + __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, dNegNorm)));
|
| + __ class_d(f6, f4);
|
| + __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, dNegNorm)));
|
| +
|
| + __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, dNegSubnorm)));
|
| + __ class_d(f6, f4);
|
| + __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, dNegSubnorm)));
|
| +
|
| + __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, dNegZero)));
|
| + __ class_d(f6, f4);
|
| + __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, dNegZero)));
|
| +
|
| + __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, dPosInf)));
|
| + __ class_d(f6, f4);
|
| + __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, dPosInf)));
|
| +
|
| + __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, dPosNorm)));
|
| + __ class_d(f6, f4);
|
| + __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, dPosNorm)));
|
| +
|
| + __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, dPosSubnorm)));
|
| + __ class_d(f6, f4);
|
| + __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, dPosSubnorm)));
|
| +
|
| + __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, dPosZero)));
|
| + __ class_d(f6, f4);
|
| + __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, dPosZero)));
|
| +
|
| + // Testing instruction CLASS.S
|
| + __ lwc1(f4, MemOperand(a0, OFFSET_OF(T, fSignalingNan)));
|
| + __ class_s(f6, f4);
|
| + __ swc1(f6, MemOperand(a0, OFFSET_OF(T, fSignalingNan)));
|
| +
|
| + __ lwc1(f4, MemOperand(a0, OFFSET_OF(T, fQuietNan)));
|
| + __ class_s(f6, f4);
|
| + __ swc1(f6, MemOperand(a0, OFFSET_OF(T, fQuietNan)));
|
| +
|
| + __ lwc1(f4, MemOperand(a0, OFFSET_OF(T, fNegInf)));
|
| + __ class_s(f6, f4);
|
| + __ swc1(f6, MemOperand(a0, OFFSET_OF(T, fNegInf)));
|
| +
|
| + __ lwc1(f4, MemOperand(a0, OFFSET_OF(T, fNegNorm)));
|
| + __ class_s(f6, f4);
|
| + __ swc1(f6, MemOperand(a0, OFFSET_OF(T, fNegNorm)));
|
| +
|
| + __ lwc1(f4, MemOperand(a0, OFFSET_OF(T, fNegSubnorm)));
|
| + __ class_s(f6, f4);
|
| + __ swc1(f6, MemOperand(a0, OFFSET_OF(T, fNegSubnorm)));
|
| +
|
| + __ lwc1(f4, MemOperand(a0, OFFSET_OF(T, fNegZero)));
|
| + __ class_s(f6, f4);
|
| + __ swc1(f6, MemOperand(a0, OFFSET_OF(T, fNegZero)));
|
| +
|
| + __ lwc1(f4, MemOperand(a0, OFFSET_OF(T, fPosInf)));
|
| + __ class_s(f6, f4);
|
| + __ swc1(f6, MemOperand(a0, OFFSET_OF(T, fPosInf)));
|
| +
|
| + __ lwc1(f4, MemOperand(a0, OFFSET_OF(T, fPosNorm)));
|
| + __ class_s(f6, f4);
|
| + __ swc1(f6, MemOperand(a0, OFFSET_OF(T, fPosNorm)));
|
| +
|
| + __ lwc1(f4, MemOperand(a0, OFFSET_OF(T, fPosSubnorm)));
|
| + __ class_s(f6, f4);
|
| + __ swc1(f6, MemOperand(a0, OFFSET_OF(T, fPosSubnorm)));
|
| +
|
| + __ lwc1(f4, MemOperand(a0, OFFSET_OF(T, fPosZero)));
|
| + __ class_s(f6, f4);
|
| + __ swc1(f6, MemOperand(a0, OFFSET_OF(T, fPosZero)));
|
| +
|
| + __ jr(ra);
|
| + __ nop();
|
| +
|
| + CodeDesc desc;
|
| + assm.GetCode(&desc);
|
| + Handle<Code> code = isolate->factory()->NewCode(
|
| + desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
|
| + F3 f = FUNCTION_CAST<F3>(code->entry());
|
| +
|
| + // Double test values.
|
| + t.dSignalingNan = std::numeric_limits<double>::signaling_NaN();
|
| + t.dQuietNan = std::numeric_limits<double>::quiet_NaN();
|
| + t.dNegInf = -1.0 / 0.0;
|
| + t.dNegNorm = -5.0;
|
| + t.dNegSubnorm = -DBL_MIN / 2.0;
|
| + t.dNegZero = -0.0;
|
| + t.dPosInf = 2.0 / 0.0;
|
| + t.dPosNorm = 275.35;
|
| + t.dPosSubnorm = DBL_MIN / 2.0;
|
| + t.dPosZero = +0.0;
|
| + // Float test values
|
| +
|
| + t.fSignalingNan = std::numeric_limits<float>::signaling_NaN();
|
| + t.fQuietNan = std::numeric_limits<float>::quiet_NaN();
|
| + t.fNegInf = -0.5/0.0;
|
| + t.fNegNorm = -FLT_MIN;
|
| + t.fNegSubnorm = -FLT_MIN / 1.5;
|
| + t.fNegZero = -0.0;
|
| + t.fPosInf = 100000.0 / 0.0;
|
| + t.fPosNorm = FLT_MAX;
|
| + t.fPosSubnorm = FLT_MIN / 20.0;
|
| + t.fPosZero = +0.0;
|
| +
|
| + Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
|
| + USE(dummy);
|
| + // Expected double results.
|
| + CHECK_EQ(bit_cast<uint64_t>(t.dNegInf), 0x004);
|
| + CHECK_EQ(bit_cast<uint64_t>(t.dNegNorm), 0x008);
|
| + CHECK_EQ(bit_cast<uint64_t>(t.dNegSubnorm), 0x010);
|
| + CHECK_EQ(bit_cast<uint64_t>(t.dNegZero), 0x020);
|
| + CHECK_EQ(bit_cast<uint64_t>(t.dPosInf), 0x040);
|
| + CHECK_EQ(bit_cast<uint64_t>(t.dPosNorm), 0x080);
|
| + CHECK_EQ(bit_cast<uint64_t>(t.dPosSubnorm), 0x100);
|
| + CHECK_EQ(bit_cast<uint64_t>(t.dPosZero), 0x200);
|
| +
|
| + // Expected float results.
|
| + CHECK_EQ(bit_cast<uint32_t>(t.fNegInf), 0x004);
|
| + CHECK_EQ(bit_cast<uint32_t>(t.fNegNorm), 0x008);
|
| + CHECK_EQ(bit_cast<uint32_t>(t.fNegSubnorm), 0x010);
|
| + CHECK_EQ(bit_cast<uint32_t>(t.fNegZero), 0x020);
|
| + CHECK_EQ(bit_cast<uint32_t>(t.fPosInf), 0x040);
|
| + CHECK_EQ(bit_cast<uint32_t>(t.fPosNorm), 0x080);
|
| + CHECK_EQ(bit_cast<uint32_t>(t.fPosSubnorm), 0x100);
|
| + CHECK_EQ(bit_cast<uint32_t>(t.fPosZero), 0x200);
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(ABS) {
|
| + CcTest::InitializeVM();
|
| + Isolate* isolate = CcTest::i_isolate();
|
| + HandleScope scope(isolate);
|
| + MacroAssembler assm(isolate, NULL, 0);
|
| +
|
| + typedef struct test_float {
|
| + int64_t fir;
|
| + double a;
|
| + float b;
|
| + double fcsr;
|
| + } TestFloat;
|
| +
|
| + TestFloat test;
|
| +
|
| + // Save FIR.
|
| + __ cfc1(a1, FCSR);
|
| + __ sd(a1, MemOperand(a0, OFFSET_OF(TestFloat, fcsr)));
|
| + // Disable FPU exceptions.
|
| + __ ctc1(zero_reg, FCSR);
|
| +
|
| + __ ldc1(f4, MemOperand(a0, OFFSET_OF(TestFloat, a)));
|
| + __ abs_d(f10, f4);
|
| + __ sdc1(f10, MemOperand(a0, OFFSET_OF(TestFloat, a)));
|
| +
|
| + __ lwc1(f4, MemOperand(a0, OFFSET_OF(TestFloat, b)));
|
| + __ abs_s(f10, f4);
|
| + __ swc1(f10, MemOperand(a0, OFFSET_OF(TestFloat, b)));
|
| +
|
| + // Restore FCSR.
|
| + __ ctc1(a1, FCSR);
|
| +
|
| + __ jr(ra);
|
| + __ nop();
|
| +
|
| + CodeDesc desc;
|
| + assm.GetCode(&desc);
|
| + Handle<Code> code = isolate->factory()->NewCode(
|
| + desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
|
| + F3 f = FUNCTION_CAST<F3>(code->entry());
|
| + test.a = -2.0;
|
| + test.b = -2.0;
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(test.a, 2.0);
|
| + CHECK_EQ(test.b, 2.0);
|
| +
|
| + test.a = 2.0;
|
| + test.b = 2.0;
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(test.a, 2.0);
|
| + CHECK_EQ(test.b, 2.0);
|
| +
|
| + // Testing biggest positive number
|
| + test.a = std::numeric_limits<double>::max();
|
| + test.b = std::numeric_limits<float>::max();
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(test.a, std::numeric_limits<double>::max());
|
| + CHECK_EQ(test.b, std::numeric_limits<float>::max());
|
| +
|
| + // Testing smallest negative number
|
| + test.a = -std::numeric_limits<double>::lowest();
|
| + test.b = -std::numeric_limits<float>::lowest();
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(test.a, std::numeric_limits<double>::max());
|
| + CHECK_EQ(test.b, std::numeric_limits<float>::max());
|
| +
|
| + // Testing smallest positive number
|
| + test.a = -std::numeric_limits<double>::min();
|
| + test.b = -std::numeric_limits<float>::min();
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(test.a, std::numeric_limits<double>::min());
|
| + CHECK_EQ(test.b, std::numeric_limits<float>::min());
|
| +
|
| + // Testing infinity
|
| + test.a = -std::numeric_limits<double>::max()
|
| + / std::numeric_limits<double>::min();
|
| + test.b = -std::numeric_limits<float>::max()
|
| + / std::numeric_limits<float>::min();
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(test.a, std::numeric_limits<double>::max()
|
| + / std::numeric_limits<double>::min());
|
| + CHECK_EQ(test.b, std::numeric_limits<float>::max()
|
| + / std::numeric_limits<float>::min());
|
| +
|
| + test.a = std::numeric_limits<double>::quiet_NaN();
|
| + test.b = std::numeric_limits<float>::quiet_NaN();
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(std::isnan(test.a), true);
|
| + CHECK_EQ(std::isnan(test.b), true);
|
| +
|
| + test.a = std::numeric_limits<double>::signaling_NaN();
|
| + test.b = std::numeric_limits<float>::signaling_NaN();
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(std::isnan(test.a), true);
|
| + CHECK_EQ(std::isnan(test.b), true);
|
| +}
|
| +
|
| +
|
| +TEST(ADD_FMT) {
|
| + CcTest::InitializeVM();
|
| + Isolate* isolate = CcTest::i_isolate();
|
| + HandleScope scope(isolate);
|
| + MacroAssembler assm(isolate, NULL, 0);
|
| +
|
| + typedef struct test_float {
|
| + double a;
|
| + double b;
|
| + double c;
|
| + float fa;
|
| + float fb;
|
| + float fc;
|
| + } TestFloat;
|
| +
|
| + TestFloat test;
|
| +
|
| + __ ldc1(f4, MemOperand(a0, OFFSET_OF(TestFloat, a)));
|
| + __ ldc1(f8, MemOperand(a0, OFFSET_OF(TestFloat, b)));
|
| + __ add_d(f10, f8, f4);
|
| + __ sdc1(f10, MemOperand(a0, OFFSET_OF(TestFloat, c)));
|
| +
|
| + __ lwc1(f4, MemOperand(a0, OFFSET_OF(TestFloat, fa)));
|
| + __ lwc1(f8, MemOperand(a0, OFFSET_OF(TestFloat, fb)));
|
| + __ add_s(f10, f8, f4);
|
| + __ swc1(f10, MemOperand(a0, OFFSET_OF(TestFloat, fc)));
|
| +
|
| + __ jr(ra);
|
| + __ nop();
|
| +
|
| + CodeDesc desc;
|
| + assm.GetCode(&desc);
|
| + Handle<Code> code = isolate->factory()->NewCode(
|
| + desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
|
| + F3 f = FUNCTION_CAST<F3>(code->entry());
|
| + test.a = 2.0;
|
| + test.b = 3.0;
|
| + test.fa = 2.0;
|
| + test.fb = 3.0;
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(test.c, 5.0);
|
| + CHECK_EQ(test.fc, 5.0);
|
| +
|
| + test.a = std::numeric_limits<double>::max();
|
| + test.b = std::numeric_limits<double>::lowest();
|
| + test.fa = std::numeric_limits<float>::max();
|
| + test.fb = std::numeric_limits<float>::lowest();
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(test.c, 0.0);
|
| + CHECK_EQ(test.fc, 0.0);
|
| +
|
| + test.a = std::numeric_limits<double>::max();
|
| + test.b = std::numeric_limits<double>::max();
|
| + test.fa = std::numeric_limits<float>::max();
|
| + test.fb = std::numeric_limits<float>::max();
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(std::isfinite(test.c), false);
|
| + CHECK_EQ(std::isfinite(test.fc), false);
|
| +
|
| + test.a = 5.0;
|
| + test.b = std::numeric_limits<double>::signaling_NaN();
|
| + test.fa = 5.0;
|
| + test.fb = std::numeric_limits<float>::signaling_NaN();
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(std::isnan(test.c), true);
|
| + CHECK_EQ(std::isnan(test.fc), true);
|
| +}
|
| +
|
| +
|
| +TEST(C_COND_FMT) {
|
| + if (kArchVariant == kMips64r2) {
|
| + CcTest::InitializeVM();
|
| + Isolate* isolate = CcTest::i_isolate();
|
| + HandleScope scope(isolate);
|
| + MacroAssembler assm(isolate, NULL, 0);
|
| +
|
| + typedef struct test_float {
|
| + double dOp1;
|
| + double dOp2;
|
| + uint32_t dF;
|
| + uint32_t dUn;
|
| + uint32_t dEq;
|
| + uint32_t dUeq;
|
| + uint32_t dOlt;
|
| + uint32_t dUlt;
|
| + uint32_t dOle;
|
| + uint32_t dUle;
|
| + float fOp1;
|
| + float fOp2;
|
| + uint32_t fF;
|
| + uint32_t fUn;
|
| + uint32_t fEq;
|
| + uint32_t fUeq;
|
| + uint32_t fOlt;
|
| + uint32_t fUlt;
|
| + uint32_t fOle;
|
| + uint32_t fUle;
|
| + } TestFloat;
|
| +
|
| + TestFloat test;
|
| +
|
| + __ li(t1, 1);
|
| +
|
| + __ ldc1(f4, MemOperand(a0, OFFSET_OF(TestFloat, dOp1)));
|
| + __ ldc1(f6, MemOperand(a0, OFFSET_OF(TestFloat, dOp2)));
|
| +
|
| + __ lwc1(f14, MemOperand(a0, OFFSET_OF(TestFloat, fOp1)));
|
| + __ lwc1(f16, MemOperand(a0, OFFSET_OF(TestFloat, fOp2)));
|
| +
|
| + __ mov(t2, zero_reg);
|
| + __ mov(t3, zero_reg);
|
| + __ c_d(F, f4, f6, 0);
|
| + __ c_s(F, f14, f16, 2);
|
| + __ movt(t2, t1, 0);
|
| + __ movt(t3, t1, 2);
|
| + __ sw(t2, MemOperand(a0, OFFSET_OF(TestFloat, dF)) );
|
| + __ sw(t3, MemOperand(a0, OFFSET_OF(TestFloat, fF)) );
|
| +
|
| + __ mov(t2, zero_reg);
|
| + __ mov(t3, zero_reg);
|
| + __ c_d(UN, f4, f6, 2);
|
| + __ c_s(UN, f14, f16, 4);
|
| + __ movt(t2, t1, 2);
|
| + __ movt(t3, t1, 4);
|
| + __ sw(t2, MemOperand(a0, OFFSET_OF(TestFloat, dUn)) );
|
| + __ sw(t3, MemOperand(a0, OFFSET_OF(TestFloat, fUn)) );
|
| +
|
| + __ mov(t2, zero_reg);
|
| + __ mov(t3, zero_reg);
|
| + __ c_d(EQ, f4, f6, 4);
|
| + __ c_s(EQ, f14, f16, 6);
|
| + __ movt(t2, t1, 4);
|
| + __ movt(t3, t1, 6);
|
| + __ sw(t2, MemOperand(a0, OFFSET_OF(TestFloat, dEq)) );
|
| + __ sw(t3, MemOperand(a0, OFFSET_OF(TestFloat, fEq)) );
|
| +
|
| + __ mov(t2, zero_reg);
|
| + __ mov(t3, zero_reg);
|
| + __ c_d(UEQ, f4, f6, 6);
|
| + __ c_s(UEQ, f14, f16, 0);
|
| + __ movt(t2, t1, 6);
|
| + __ movt(t3, t1, 0);
|
| + __ sw(t2, MemOperand(a0, OFFSET_OF(TestFloat, dUeq)) );
|
| + __ sw(t3, MemOperand(a0, OFFSET_OF(TestFloat, fUeq)) );
|
| +
|
| + __ mov(t2, zero_reg);
|
| + __ mov(t3, zero_reg);
|
| + __ c_d(OLT, f4, f6, 0);
|
| + __ c_s(OLT, f14, f16, 2);
|
| + __ movt(t2, t1, 0);
|
| + __ movt(t3, t1, 2);
|
| + __ sw(t2, MemOperand(a0, OFFSET_OF(TestFloat, dOlt)) );
|
| + __ sw(t3, MemOperand(a0, OFFSET_OF(TestFloat, fOlt)) );
|
| +
|
| + __ mov(t2, zero_reg);
|
| + __ mov(t3, zero_reg);
|
| + __ c_d(ULT, f4, f6, 2);
|
| + __ c_s(ULT, f14, f16, 4);
|
| + __ movt(t2, t1, 2);
|
| + __ movt(t3, t1, 4);
|
| + __ sw(t2, MemOperand(a0, OFFSET_OF(TestFloat, dUlt)) );
|
| + __ sw(t3, MemOperand(a0, OFFSET_OF(TestFloat, fUlt)) );
|
| +
|
| + __ mov(t2, zero_reg);
|
| + __ mov(t3, zero_reg);
|
| + __ c_d(OLE, f4, f6, 4);
|
| + __ c_s(OLE, f14, f16, 6);
|
| + __ movt(t2, t1, 4);
|
| + __ movt(t3, t1, 6);
|
| + __ sw(t2, MemOperand(a0, OFFSET_OF(TestFloat, dOle)) );
|
| + __ sw(t3, MemOperand(a0, OFFSET_OF(TestFloat, fOle)) );
|
| +
|
| + __ mov(t2, zero_reg);
|
| + __ mov(t3, zero_reg);
|
| + __ c_d(ULE, f4, f6, 6);
|
| + __ c_s(ULE, f14, f16, 0);
|
| + __ movt(t2, t1, 6);
|
| + __ movt(t3, t1, 0);
|
| + __ sw(t2, MemOperand(a0, OFFSET_OF(TestFloat, dUle)) );
|
| + __ sw(t3, MemOperand(a0, OFFSET_OF(TestFloat, fUle)) );
|
| +
|
| + __ jr(ra);
|
| + __ nop();
|
| +
|
| + CodeDesc desc;
|
| + assm.GetCode(&desc);
|
| + Handle<Code> code = isolate->factory()->NewCode(
|
| + desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
|
| + F3 f = FUNCTION_CAST<F3>(code->entry());
|
| + test.dOp1 = 2.0;
|
| + test.dOp2 = 3.0;
|
| + test.fOp1 = 2.0;
|
| + test.fOp2 = 3.0;
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(test.dF, 0);
|
| + CHECK_EQ(test.dUn, 0);
|
| + CHECK_EQ(test.dEq, 0);
|
| + CHECK_EQ(test.dUeq, 0);
|
| + CHECK_EQ(test.dOlt, 1);
|
| + CHECK_EQ(test.dUlt, 1);
|
| + CHECK_EQ(test.dOle, 1);
|
| + CHECK_EQ(test.dUle, 1);
|
| + CHECK_EQ(test.fF, 0);
|
| + CHECK_EQ(test.fUn, 0);
|
| + CHECK_EQ(test.fEq, 0);
|
| + CHECK_EQ(test.fUeq, 0);
|
| + CHECK_EQ(test.fOlt, 1);
|
| + CHECK_EQ(test.fUlt, 1);
|
| + CHECK_EQ(test.fOle, 1);
|
| + CHECK_EQ(test.fUle, 1);
|
| +
|
| + test.dOp1 = std::numeric_limits<double>::max();
|
| + test.dOp2 = std::numeric_limits<double>::min();
|
| + test.fOp1 = std::numeric_limits<float>::min();
|
| + test.fOp2 = std::numeric_limits<float>::lowest();
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(test.dF, 0);
|
| + CHECK_EQ(test.dUn, 0);
|
| + CHECK_EQ(test.dEq, 0);
|
| + CHECK_EQ(test.dUeq, 0);
|
| + CHECK_EQ(test.dOlt, 0);
|
| + CHECK_EQ(test.dUlt, 0);
|
| + CHECK_EQ(test.dOle, 0);
|
| + CHECK_EQ(test.dUle, 0);
|
| + CHECK_EQ(test.fF, 0);
|
| + CHECK_EQ(test.fUn, 0);
|
| + CHECK_EQ(test.fEq, 0);
|
| + CHECK_EQ(test.fUeq, 0);
|
| + CHECK_EQ(test.fOlt, 0);
|
| + CHECK_EQ(test.fUlt, 0);
|
| + CHECK_EQ(test.fOle, 0);
|
| + CHECK_EQ(test.fUle, 0);
|
| +
|
| + test.dOp1 = std::numeric_limits<double>::lowest();
|
| + test.dOp2 = std::numeric_limits<double>::lowest();
|
| + test.fOp1 = std::numeric_limits<float>::max();
|
| + test.fOp2 = std::numeric_limits<float>::max();
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(test.dF, 0);
|
| + CHECK_EQ(test.dUn, 0);
|
| + CHECK_EQ(test.dEq, 1);
|
| + CHECK_EQ(test.dUeq, 1);
|
| + CHECK_EQ(test.dOlt, 0);
|
| + CHECK_EQ(test.dUlt, 0);
|
| + CHECK_EQ(test.dOle, 1);
|
| + CHECK_EQ(test.dUle, 1);
|
| + CHECK_EQ(test.fF, 0);
|
| + CHECK_EQ(test.fUn, 0);
|
| + CHECK_EQ(test.fEq, 1);
|
| + CHECK_EQ(test.fUeq, 1);
|
| + CHECK_EQ(test.fOlt, 0);
|
| + CHECK_EQ(test.fUlt, 0);
|
| + CHECK_EQ(test.fOle, 1);
|
| + CHECK_EQ(test.fUle, 1);
|
| +
|
| + test.dOp1 = std::numeric_limits<double>::quiet_NaN();
|
| + test.dOp2 = 0.0;
|
| + test.fOp1 = std::numeric_limits<float>::quiet_NaN();
|
| + test.fOp2 = 0.0;
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(test.dF, 0);
|
| + CHECK_EQ(test.dUn, 1);
|
| + CHECK_EQ(test.dEq, 0);
|
| + CHECK_EQ(test.dUeq, 1);
|
| + CHECK_EQ(test.dOlt, 0);
|
| + CHECK_EQ(test.dUlt, 1);
|
| + CHECK_EQ(test.dOle, 0);
|
| + CHECK_EQ(test.dUle, 1);
|
| + CHECK_EQ(test.fF, 0);
|
| + CHECK_EQ(test.fUn, 1);
|
| + CHECK_EQ(test.fEq, 0);
|
| + CHECK_EQ(test.fUeq, 1);
|
| + CHECK_EQ(test.fOlt, 0);
|
| + CHECK_EQ(test.fUlt, 1);
|
| + CHECK_EQ(test.fOle, 0);
|
| + CHECK_EQ(test.fUle, 1);
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(CMP_COND_FMT) {
|
| + if (kArchVariant == kMips64r6) {
|
| + CcTest::InitializeVM();
|
| + Isolate* isolate = CcTest::i_isolate();
|
| + HandleScope scope(isolate);
|
| + MacroAssembler assm(isolate, NULL, 0);
|
| +
|
| + typedef struct test_float {
|
| + double dOp1;
|
| + double dOp2;
|
| + double dF;
|
| + double dUn;
|
| + double dEq;
|
| + double dUeq;
|
| + double dOlt;
|
| + double dUlt;
|
| + double dOle;
|
| + double dUle;
|
| + double dOr;
|
| + double dUne;
|
| + double dNe;
|
| + float fOp1;
|
| + float fOp2;
|
| + float fF;
|
| + float fUn;
|
| + float fEq;
|
| + float fUeq;
|
| + float fOlt;
|
| + float fUlt;
|
| + float fOle;
|
| + float fUle;
|
| + float fOr;
|
| + float fUne;
|
| + float fNe;
|
| + } TestFloat;
|
| +
|
| + TestFloat test;
|
| +
|
| + __ li(t1, 1);
|
| +
|
| + __ ldc1(f4, MemOperand(a0, OFFSET_OF(TestFloat, dOp1)));
|
| + __ ldc1(f6, MemOperand(a0, OFFSET_OF(TestFloat, dOp2)));
|
| +
|
| + __ lwc1(f14, MemOperand(a0, OFFSET_OF(TestFloat, fOp1)));
|
| + __ lwc1(f16, MemOperand(a0, OFFSET_OF(TestFloat, fOp2)));
|
| +
|
| + __ cmp_d(F, f2, f4, f6);
|
| + __ cmp_s(F, f12, f14, f16);
|
| + __ sdc1(f2, MemOperand(a0, OFFSET_OF(TestFloat, dF)) );
|
| + __ swc1(f12, MemOperand(a0, OFFSET_OF(TestFloat, fF)) );
|
| +
|
| + __ cmp_d(UN, f2, f4, f6);
|
| + __ cmp_s(UN, f12, f14, f16);
|
| + __ sdc1(f2, MemOperand(a0, OFFSET_OF(TestFloat, dUn)) );
|
| + __ swc1(f12, MemOperand(a0, OFFSET_OF(TestFloat, fUn)) );
|
| +
|
| + __ cmp_d(EQ, f2, f4, f6);
|
| + __ cmp_s(EQ, f12, f14, f16);
|
| + __ sdc1(f2, MemOperand(a0, OFFSET_OF(TestFloat, dEq)) );
|
| + __ swc1(f12, MemOperand(a0, OFFSET_OF(TestFloat, fEq)) );
|
| +
|
| + __ cmp_d(UEQ, f2, f4, f6);
|
| + __ cmp_s(UEQ, f12, f14, f16);
|
| + __ sdc1(f2, MemOperand(a0, OFFSET_OF(TestFloat, dUeq)) );
|
| + __ swc1(f12, MemOperand(a0, OFFSET_OF(TestFloat, fUeq)) );
|
| +
|
| + __ cmp_d(LT, f2, f4, f6);
|
| + __ cmp_s(LT, f12, f14, f16);
|
| + __ sdc1(f2, MemOperand(a0, OFFSET_OF(TestFloat, dOlt)) );
|
| + __ swc1(f12, MemOperand(a0, OFFSET_OF(TestFloat, fOlt)) );
|
| +
|
| + __ cmp_d(ULT, f2, f4, f6);
|
| + __ cmp_s(ULT, f12, f14, f16);
|
| + __ sdc1(f2, MemOperand(a0, OFFSET_OF(TestFloat, dUlt)) );
|
| + __ swc1(f12, MemOperand(a0, OFFSET_OF(TestFloat, fUlt)) );
|
| +
|
| + __ cmp_d(LE, f2, f4, f6);
|
| + __ cmp_s(LE, f12, f14, f16);
|
| + __ sdc1(f2, MemOperand(a0, OFFSET_OF(TestFloat, dOle)) );
|
| + __ swc1(f12, MemOperand(a0, OFFSET_OF(TestFloat, fOle)) );
|
| +
|
| + __ cmp_d(ULE, f2, f4, f6);
|
| + __ cmp_s(ULE, f12, f14, f16);
|
| + __ sdc1(f2, MemOperand(a0, OFFSET_OF(TestFloat, dUle)) );
|
| + __ swc1(f12, MemOperand(a0, OFFSET_OF(TestFloat, fUle)) );
|
| +
|
| + __ cmp_d(ORD, f2, f4, f6);
|
| + __ cmp_s(ORD, f12, f14, f16);
|
| + __ sdc1(f2, MemOperand(a0, OFFSET_OF(TestFloat, dOr)) );
|
| + __ swc1(f12, MemOperand(a0, OFFSET_OF(TestFloat, fOr)) );
|
| +
|
| + __ cmp_d(UNE, f2, f4, f6);
|
| + __ cmp_s(UNE, f12, f14, f16);
|
| + __ sdc1(f2, MemOperand(a0, OFFSET_OF(TestFloat, dUne)) );
|
| + __ swc1(f12, MemOperand(a0, OFFSET_OF(TestFloat, fUne)) );
|
| +
|
| + __ cmp_d(NE, f2, f4, f6);
|
| + __ cmp_s(NE, f12, f14, f16);
|
| + __ sdc1(f2, MemOperand(a0, OFFSET_OF(TestFloat, dNe)) );
|
| + __ swc1(f12, MemOperand(a0, OFFSET_OF(TestFloat, fNe)) );
|
| +
|
| + __ jr(ra);
|
| + __ nop();
|
| +
|
| + CodeDesc desc;
|
| + assm.GetCode(&desc);
|
| + Handle<Code> code = isolate->factory()->NewCode(
|
| + desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
|
| + F3 f = FUNCTION_CAST<F3>(code->entry());
|
| + uint64_t dTrue = 0xFFFFFFFFFFFFFFFF;
|
| + uint64_t dFalse = 0x0000000000000000;
|
| + uint32_t fTrue = 0xFFFFFFFF;
|
| + uint32_t fFalse = 0x00000000;
|
| +
|
| + test.dOp1 = 2.0;
|
| + test.dOp2 = 3.0;
|
| + test.fOp1 = 2.0;
|
| + test.fOp2 = 3.0;
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dFalse);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dTrue);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dTrue);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dOle), dTrue);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dNe), dTrue);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fFalse);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fTrue);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fTrue);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fOle), fTrue);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue);
|
| +
|
| + test.dOp1 = std::numeric_limits<double>::max();
|
| + test.dOp2 = std::numeric_limits<double>::min();
|
| + test.fOp1 = std::numeric_limits<float>::min();
|
| + test.fOp2 = std::numeric_limits<float>::lowest();
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dFalse);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dFalse);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dOle), dFalse);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dUle), dFalse);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dNe), dTrue);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fFalse);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fFalse);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fOle), fFalse);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fUle), fFalse);
|
| +
|
| + test.dOp1 = std::numeric_limits<double>::lowest();
|
| + test.dOp2 = std::numeric_limits<double>::lowest();
|
| + test.fOp1 = std::numeric_limits<float>::max();
|
| + test.fOp2 = std::numeric_limits<float>::max();
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dEq), dTrue);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dTrue);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dFalse);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dOle), dTrue);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dUne), dFalse);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dNe), dFalse);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fEq), fTrue);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fTrue);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fFalse);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fOle), fTrue);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue);
|
| +
|
| + test.dOp1 = std::numeric_limits<double>::quiet_NaN();
|
| + test.dOp2 = 0.0;
|
| + test.fOp1 = std::numeric_limits<float>::quiet_NaN();
|
| + test.fOp2 = 0.0;
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dUn), dTrue);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dTrue);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dTrue);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dOle), dFalse);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dOr), dFalse);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue);
|
| + CHECK_EQ(bit_cast<uint64_t>(test.dNe), dFalse);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fUn), fTrue);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fTrue);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fTrue);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fOle), fFalse);
|
| + CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue);
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(CVT) {
|
| + CcTest::InitializeVM();
|
| + Isolate* isolate = CcTest::i_isolate();
|
| + HandleScope scope(isolate);
|
| + MacroAssembler assm(isolate, NULL, 0);
|
| +
|
| + typedef struct test_float {
|
| + float cvt_d_s_in;
|
| + double cvt_d_s_out;
|
| + int32_t cvt_d_w_in;
|
| + double cvt_d_w_out;
|
| + int64_t cvt_d_l_in;
|
| + double cvt_d_l_out;
|
| +
|
| + float cvt_l_s_in;
|
| + int64_t cvt_l_s_out;
|
| + double cvt_l_d_in;
|
| + int64_t cvt_l_d_out;
|
| +
|
| + double cvt_s_d_in;
|
| + float cvt_s_d_out;
|
| + int32_t cvt_s_w_in;
|
| + float cvt_s_w_out;
|
| + int64_t cvt_s_l_in;
|
| + float cvt_s_l_out;
|
| +
|
| + float cvt_w_s_in;
|
| + int32_t cvt_w_s_out;
|
| + double cvt_w_d_in;
|
| + int32_t cvt_w_d_out;
|
| + } TestFloat;
|
| +
|
| + TestFloat test;
|
| +
|
| + // Save FCSR.
|
| + __ cfc1(a1, FCSR);
|
| + // Disable FPU exceptions.
|
| + __ ctc1(zero_reg, FCSR);
|
| +
|
| +#define GENERATE_CVT_TEST(x, y, z) \
|
| + __ y##c1(f0, MemOperand(a0, OFFSET_OF(TestFloat, x##_in))); \
|
| + __ x(f0, f0); \
|
| + __ nop(); \
|
| + __ z##c1(f0, MemOperand(a0, OFFSET_OF(TestFloat, x##_out)));
|
| +
|
| + GENERATE_CVT_TEST(cvt_d_s, lw, sd)
|
| + GENERATE_CVT_TEST(cvt_d_w, lw, sd)
|
| + GENERATE_CVT_TEST(cvt_d_l, ld, sd)
|
| +
|
| + GENERATE_CVT_TEST(cvt_l_s, lw, sd)
|
| + GENERATE_CVT_TEST(cvt_l_d, ld, sd)
|
| +
|
| + GENERATE_CVT_TEST(cvt_s_d, ld, sw)
|
| + GENERATE_CVT_TEST(cvt_s_w, lw, sw)
|
| + GENERATE_CVT_TEST(cvt_s_l, ld, sw)
|
| +
|
| + GENERATE_CVT_TEST(cvt_w_s, lw, sw)
|
| + GENERATE_CVT_TEST(cvt_w_d, ld, sw)
|
| +
|
| + // Restore FCSR.
|
| + __ ctc1(a1, FCSR);
|
| +
|
| + __ jr(ra);
|
| + __ nop();
|
| +
|
| + CodeDesc desc;
|
| + assm.GetCode(&desc);
|
| + Handle<Code> code = isolate->factory()->NewCode(
|
| + desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
|
| + F3 f = FUNCTION_CAST<F3>(code->entry());
|
| +
|
| + test.cvt_d_s_in = -0.51;
|
| + test.cvt_d_w_in = -1;
|
| + test.cvt_d_l_in = -1;
|
| + test.cvt_l_s_in = -0.51;
|
| + test.cvt_l_d_in = -0.51;
|
| + test.cvt_s_d_in = -0.51;
|
| + test.cvt_s_w_in = -1;
|
| + test.cvt_s_l_in = -1;
|
| + test.cvt_w_s_in = -0.51;
|
| + test.cvt_w_d_in = -0.51;
|
| +
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in));
|
| + CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in));
|
| + CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in));
|
| + CHECK_EQ(test.cvt_l_s_out, -1);
|
| + CHECK_EQ(test.cvt_l_d_out, -1);
|
| + CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in));
|
| + CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in));
|
| + CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in));
|
| + CHECK_EQ(test.cvt_w_s_out, -1);
|
| + CHECK_EQ(test.cvt_w_d_out, -1);
|
| +
|
| +
|
| + test.cvt_d_s_in = 0.49;
|
| + test.cvt_d_w_in = 1;
|
| + test.cvt_d_l_in = 1;
|
| + test.cvt_l_s_in = 0.49;
|
| + test.cvt_l_d_in = 0.49;
|
| + test.cvt_s_d_in = 0.49;
|
| + test.cvt_s_w_in = 1;
|
| + test.cvt_s_l_in = 1;
|
| + test.cvt_w_s_in = 0.49;
|
| + test.cvt_w_d_in = 0.49;
|
| +
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in));
|
| + CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in));
|
| + CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in));
|
| + CHECK_EQ(test.cvt_l_s_out, 0);
|
| + CHECK_EQ(test.cvt_l_d_out, 0);
|
| + CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in));
|
| + CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in));
|
| + CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in));
|
| + CHECK_EQ(test.cvt_w_s_out, 0);
|
| + CHECK_EQ(test.cvt_w_d_out, 0);
|
| +
|
| + test.cvt_d_s_in = std::numeric_limits<float>::max();
|
| + test.cvt_d_w_in = std::numeric_limits<int32_t>::max();
|
| + test.cvt_d_l_in = std::numeric_limits<int64_t>::max();
|
| + test.cvt_l_s_in = std::numeric_limits<float>::max();
|
| + test.cvt_l_d_in = std::numeric_limits<double>::max();
|
| + test.cvt_s_d_in = std::numeric_limits<double>::max();
|
| + test.cvt_s_w_in = std::numeric_limits<int32_t>::max();
|
| + test.cvt_s_l_in = std::numeric_limits<int64_t>::max();
|
| + test.cvt_w_s_in = std::numeric_limits<float>::max();
|
| + test.cvt_w_d_in = std::numeric_limits<double>::max();
|
| +
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in));
|
| + CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in));
|
| + CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in));
|
| + CHECK_EQ(test.cvt_l_s_out, std::numeric_limits<int64_t>::max());
|
| + CHECK_EQ(test.cvt_l_d_out, std::numeric_limits<int64_t>::max());
|
| + CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in));
|
| + CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in));
|
| + CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in));
|
| + CHECK_EQ(test.cvt_w_s_out, std::numeric_limits<int32_t>::max());
|
| + CHECK_EQ(test.cvt_w_d_out, std::numeric_limits<int32_t>::max());
|
| +
|
| +
|
| + test.cvt_d_s_in = std::numeric_limits<float>::lowest();
|
| + test.cvt_d_w_in = std::numeric_limits<int32_t>::lowest();
|
| + test.cvt_d_l_in = std::numeric_limits<int64_t>::lowest();
|
| + test.cvt_l_s_in = std::numeric_limits<float>::lowest();
|
| + test.cvt_l_d_in = std::numeric_limits<double>::lowest();
|
| + test.cvt_s_d_in = std::numeric_limits<double>::lowest();
|
| + test.cvt_s_w_in = std::numeric_limits<int32_t>::lowest();
|
| + test.cvt_s_l_in = std::numeric_limits<int64_t>::lowest();
|
| + test.cvt_w_s_in = std::numeric_limits<float>::lowest();
|
| + test.cvt_w_d_in = std::numeric_limits<double>::lowest();
|
| +
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in));
|
| + CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in));
|
| + CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in));
|
| + // The returned value when converting from fixed-point to float-point
|
| + // is not consistent between board, simulator and specification
|
| + // in this test case, therefore modifying the test
|
| + CHECK(test.cvt_l_s_out == std::numeric_limits<int64_t>::min() ||
|
| + test.cvt_l_s_out == std::numeric_limits<int64_t>::max());
|
| + CHECK(test.cvt_l_d_out == std::numeric_limits<int64_t>::min() ||
|
| + test.cvt_l_d_out == std::numeric_limits<int64_t>::max());
|
| + CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in));
|
| + CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in));
|
| + CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in));
|
| + CHECK(test.cvt_w_s_out == std::numeric_limits<int32_t>::min() ||
|
| + test.cvt_w_s_out == std::numeric_limits<int32_t>::max());
|
| + CHECK(test.cvt_w_d_out == std::numeric_limits<int32_t>::min() ||
|
| + test.cvt_w_d_out == std::numeric_limits<int32_t>::max());
|
| +
|
| +
|
| + test.cvt_d_s_in = std::numeric_limits<float>::min();
|
| + test.cvt_d_w_in = std::numeric_limits<int32_t>::min();
|
| + test.cvt_d_l_in = std::numeric_limits<int64_t>::min();
|
| + test.cvt_l_s_in = std::numeric_limits<float>::min();
|
| + test.cvt_l_d_in = std::numeric_limits<double>::min();
|
| + test.cvt_s_d_in = std::numeric_limits<double>::min();
|
| + test.cvt_s_w_in = std::numeric_limits<int32_t>::min();
|
| + test.cvt_s_l_in = std::numeric_limits<int64_t>::min();
|
| + test.cvt_w_s_in = std::numeric_limits<float>::min();
|
| + test.cvt_w_d_in = std::numeric_limits<double>::min();
|
| +
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in));
|
| + CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in));
|
| + CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in));
|
| + CHECK_EQ(test.cvt_l_s_out, 0);
|
| + CHECK_EQ(test.cvt_l_d_out, 0);
|
| + CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in));
|
| + CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in));
|
| + CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in));
|
| + CHECK_EQ(test.cvt_w_s_out, 0);
|
| + CHECK_EQ(test.cvt_w_d_out, 0);
|
| +}
|
| +
|
| +
|
| +TEST(DIV_FMT) {
|
| + CcTest::InitializeVM();
|
| + Isolate* isolate = CcTest::i_isolate();
|
| + HandleScope scope(isolate);
|
| + MacroAssembler assm(isolate, NULL, 0);
|
| +
|
| + typedef struct test {
|
| + double dOp1;
|
| + double dOp2;
|
| + double dRes;
|
| + float fOp1;
|
| + float fOp2;
|
| + float fRes;
|
| + } Test;
|
| +
|
| + Test test;
|
| +
|
| + // Save FCSR.
|
| + __ cfc1(a1, FCSR);
|
| + // Disable FPU exceptions.
|
| + __ ctc1(zero_reg, FCSR);
|
| +
|
| + __ ldc1(f4, MemOperand(a0, OFFSET_OF(Test, dOp1)) );
|
| + __ ldc1(f2, MemOperand(a0, OFFSET_OF(Test, dOp2)) );
|
| + __ nop();
|
| + __ div_d(f6, f4, f2);
|
| + __ sdc1(f6, MemOperand(a0, OFFSET_OF(Test, dRes)) );
|
| +
|
| + __ lwc1(f4, MemOperand(a0, OFFSET_OF(Test, fOp1)) );
|
| + __ lwc1(f2, MemOperand(a0, OFFSET_OF(Test, fOp2)) );
|
| + __ nop();
|
| + __ div_s(f6, f4, f2);
|
| + __ swc1(f6, MemOperand(a0, OFFSET_OF(Test, fRes)) );
|
| +
|
| + // Restore FCSR.
|
| + __ ctc1(a1, FCSR);
|
| +
|
| + __ jr(ra);
|
| + __ nop();
|
| + CodeDesc desc;
|
| + assm.GetCode(&desc);
|
| + Handle<Code> code = isolate->factory()->NewCode(
|
| + desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
|
| + F3 f = FUNCTION_CAST<F3>(code->entry());
|
| +
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| +
|
| + const int test_size = 3;
|
| +
|
| + double dOp1[test_size] = {
|
| + 5.0,
|
| + DBL_MAX,
|
| + DBL_MAX,
|
| + };
|
| + double dOp2[test_size] = {
|
| + 2.0,
|
| + 2.0,
|
| + -DBL_MAX,
|
| + };
|
| + double dRes[test_size] = {
|
| + 2.5,
|
| + DBL_MAX / 2.0,
|
| + -1.0,
|
| + };
|
| + float fOp1[test_size] = {
|
| + 5.0,
|
| + FLT_MAX,
|
| + FLT_MAX,
|
| + };
|
| + float fOp2[test_size] = {
|
| + 2.0,
|
| + 2.0,
|
| + -FLT_MAX,
|
| + };
|
| + float fRes[test_size] = {
|
| + 2.5,
|
| + FLT_MAX / 2.0,
|
| + -1.0,
|
| + };
|
| +
|
| + for (int i = 0; i < test_size; i++) {
|
| + test.dOp1 = dOp1[i];
|
| + test.dOp2 = dOp2[i];
|
| + test.fOp1 = fOp1[i];
|
| + test.fOp2 = fOp2[i];
|
| +
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(test.dRes, dRes[i]);
|
| + CHECK_EQ(test.fRes, fRes[i]);
|
| + }
|
| +
|
| + test.dOp1 = DBL_MAX;
|
| + test.dOp2 = -0.0;
|
| + test.fOp1 = FLT_MAX;
|
| + test.fOp2 = -0.0;
|
| +
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(false, std::isfinite(test.dRes));
|
| + CHECK_EQ(false, std::isfinite(test.fRes));
|
| +
|
| + test.dOp1 = 0.0;
|
| + test.dOp2 = -0.0;
|
| + test.fOp1 = 0.0;
|
| + test.fOp2 = -0.0;
|
| +
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(true, std::isnan(test.dRes));
|
| + CHECK_EQ(true, std::isnan(test.fRes));
|
| +
|
| + test.dOp1 = std::numeric_limits<double>::quiet_NaN();
|
| + test.dOp2 = -5.0;
|
| + test.fOp1 = std::numeric_limits<float>::quiet_NaN();
|
| + test.fOp2 = -5.0;
|
| +
|
| + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
|
| + CHECK_EQ(true, std::isnan(test.dRes));
|
| + CHECK_EQ(true, std::isnan(test.fRes));
|
| +}
|
| +
|
| +
|
| #undef __
|
|
|