OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 23 matching lines...) Expand all Loading... |
34 #include "src/mips/simulator-mips.h" | 34 #include "src/mips/simulator-mips.h" |
35 #include "src/v8.h" | 35 #include "src/v8.h" |
36 #include "test/cctest/cctest.h" | 36 #include "test/cctest/cctest.h" |
37 | 37 |
38 | 38 |
39 using namespace v8::internal; | 39 using namespace v8::internal; |
40 | 40 |
41 typedef void* (*F)(int x, int y, int p2, int p3, int p4); | 41 typedef void* (*F)(int x, int y, int p2, int p3, int p4); |
42 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4); | 42 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4); |
43 typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4); | 43 typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4); |
| 44 typedef Object* (*F4)(void* p0, void* p1, int p2, int p3, int p4); |
44 | 45 |
45 #define __ masm-> | 46 #define __ masm-> |
46 | 47 |
47 TEST(BYTESWAP) { | 48 TEST(BYTESWAP) { |
48 CcTest::InitializeVM(); | 49 CcTest::InitializeVM(); |
49 Isolate* isolate = CcTest::i_isolate(); | 50 Isolate* isolate = CcTest::i_isolate(); |
50 HandleScope handles(isolate); | 51 HandleScope handles(isolate); |
51 | 52 |
52 struct T { | 53 struct T { |
53 int32_t r1; | 54 int32_t r1; |
(...skipping 960 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1014 | 1015 |
1015 Label handle_mind_nan, handle_maxd_nan, handle_mins_nan, handle_maxs_nan; | 1016 Label handle_mind_nan, handle_maxd_nan, handle_mins_nan, handle_maxs_nan; |
1016 Label back_mind_nan, back_maxd_nan, back_mins_nan, back_maxs_nan; | 1017 Label back_mind_nan, back_maxd_nan, back_mins_nan, back_maxs_nan; |
1017 | 1018 |
1018 __ push(s6); | 1019 __ push(s6); |
1019 __ InitializeRootRegister(); | 1020 __ InitializeRootRegister(); |
1020 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a))); | 1021 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a))); |
1021 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, b))); | 1022 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, b))); |
1022 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, e))); | 1023 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, e))); |
1023 __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, f))); | 1024 __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, f))); |
1024 __ MinNaNCheck_d(f10, f4, f8, &handle_mind_nan); | 1025 __ Float64Min(f10, f4, f8, &handle_mind_nan); |
1025 __ bind(&back_mind_nan); | 1026 __ bind(&back_mind_nan); |
1026 __ MaxNaNCheck_d(f12, f4, f8, &handle_maxd_nan); | 1027 __ Float64Max(f12, f4, f8, &handle_maxd_nan); |
1027 __ bind(&back_maxd_nan); | 1028 __ bind(&back_maxd_nan); |
1028 __ MinNaNCheck_s(f14, f2, f6, &handle_mins_nan); | 1029 __ Float32Min(f14, f2, f6, &handle_mins_nan); |
1029 __ bind(&back_mins_nan); | 1030 __ bind(&back_mins_nan); |
1030 __ MaxNaNCheck_s(f16, f2, f6, &handle_maxs_nan); | 1031 __ Float32Max(f16, f2, f6, &handle_maxs_nan); |
1031 __ bind(&back_maxs_nan); | 1032 __ bind(&back_maxs_nan); |
1032 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, c))); | 1033 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, c))); |
1033 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, d))); | 1034 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, d))); |
1034 __ swc1(f14, MemOperand(a0, offsetof(TestFloat, g))); | 1035 __ swc1(f14, MemOperand(a0, offsetof(TestFloat, g))); |
1035 __ swc1(f16, MemOperand(a0, offsetof(TestFloat, h))); | 1036 __ swc1(f16, MemOperand(a0, offsetof(TestFloat, h))); |
1036 __ pop(s6); | 1037 __ pop(s6); |
1037 __ jr(ra); | 1038 __ jr(ra); |
1038 __ nop(); | 1039 __ nop(); |
1039 | 1040 |
1040 handle_dnan(f10, &handle_mind_nan, &back_mind_nan); | 1041 handle_dnan(f10, &handle_mind_nan, &back_mind_nan); |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1351 CHECK_EQ(rs < rd, run_Sltu(rs, rd, fn_1)); | 1352 CHECK_EQ(rs < rd, run_Sltu(rs, rd, fn_1)); |
1352 | 1353 |
1353 auto fn_2 = [](MacroAssembler* masm, uint32_t imm) { | 1354 auto fn_2 = [](MacroAssembler* masm, uint32_t imm) { |
1354 __ Sltu(v0, a0, a1); | 1355 __ Sltu(v0, a0, a1); |
1355 }; | 1356 }; |
1356 CHECK_EQ(rs < rd, run_Sltu(rs, rd, fn_2)); | 1357 CHECK_EQ(rs < rd, run_Sltu(rs, rd, fn_2)); |
1357 } | 1358 } |
1358 } | 1359 } |
1359 } | 1360 } |
1360 | 1361 |
| 1362 template <typename T, typename Inputs, typename Results> |
| 1363 static ::F4 GenerateMacroFloat32MinMax(MacroAssembler* masm) { |
| 1364 T a = T::from_code(4); // f4 |
| 1365 T b = T::from_code(6); // f6 |
| 1366 T c = T::from_code(8); // f8 |
| 1367 |
| 1368 Label ool_min_abc, ool_min_aab, ool_min_aba; |
| 1369 Label ool_max_abc, ool_max_aab, ool_max_aba; |
| 1370 |
| 1371 Label done_min_abc, done_min_aab, done_min_aba; |
| 1372 Label done_max_abc, done_max_aab, done_max_aba; |
| 1373 |
| 1374 #define FLOAT_MIN_MAX(fminmax, res, x, y, done, ool, res_field) \ |
| 1375 __ lwc1(x, MemOperand(a0, offsetof(Inputs, src1_))); \ |
| 1376 __ lwc1(y, MemOperand(a0, offsetof(Inputs, src2_))); \ |
| 1377 __ fminmax(res, x, y, &ool); \ |
| 1378 __ bind(&done); \ |
| 1379 __ swc1(a, MemOperand(a1, offsetof(Results, res_field))) |
| 1380 |
| 1381 // a = min(b, c); |
| 1382 FLOAT_MIN_MAX(Float32Min, a, b, c, done_min_abc, ool_min_abc, min_abc_); |
| 1383 // a = min(a, b); |
| 1384 FLOAT_MIN_MAX(Float32Min, a, a, b, done_min_aab, ool_min_aab, min_aab_); |
| 1385 // a = min(b, a); |
| 1386 FLOAT_MIN_MAX(Float32Min, a, b, a, done_min_aba, ool_min_aba, min_aba_); |
| 1387 |
| 1388 // a = max(b, c); |
| 1389 FLOAT_MIN_MAX(Float32Max, a, b, c, done_max_abc, ool_max_abc, max_abc_); |
| 1390 // a = max(a, b); |
| 1391 FLOAT_MIN_MAX(Float32Max, a, a, b, done_max_aab, ool_max_aab, max_aab_); |
| 1392 // a = max(b, a); |
| 1393 FLOAT_MIN_MAX(Float32Max, a, b, a, done_max_aba, ool_max_aba, max_aba_); |
| 1394 |
| 1395 #undef FLOAT_MIN_MAX |
| 1396 |
| 1397 __ jr(ra); |
| 1398 __ nop(); |
| 1399 |
| 1400 // Generate out-of-line cases. |
| 1401 __ bind(&ool_min_abc); |
| 1402 __ Float32MinOutOfLine(a, b, c); |
| 1403 __ b(&done_min_abc); |
| 1404 |
| 1405 __ bind(&ool_min_aab); |
| 1406 __ Float32MinOutOfLine(a, a, b); |
| 1407 __ b(&done_min_aab); |
| 1408 |
| 1409 __ bind(&ool_min_aba); |
| 1410 __ Float32MinOutOfLine(a, b, a); |
| 1411 __ b(&done_min_aba); |
| 1412 |
| 1413 __ bind(&ool_max_abc); |
| 1414 __ Float32MaxOutOfLine(a, b, c); |
| 1415 __ b(&done_max_abc); |
| 1416 |
| 1417 __ bind(&ool_max_aab); |
| 1418 __ Float32MaxOutOfLine(a, a, b); |
| 1419 __ b(&done_max_aab); |
| 1420 |
| 1421 __ bind(&ool_max_aba); |
| 1422 __ Float32MaxOutOfLine(a, b, a); |
| 1423 __ b(&done_max_aba); |
| 1424 |
| 1425 CodeDesc desc; |
| 1426 masm->GetCode(&desc); |
| 1427 Handle<Code> code = masm->isolate()->factory()->NewCode( |
| 1428 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1429 #ifdef DEBUG |
| 1430 OFStream os(stdout); |
| 1431 code->Print(os); |
| 1432 #endif |
| 1433 return FUNCTION_CAST<::F4>(code->entry()); |
| 1434 } |
| 1435 |
| 1436 TEST(macro_float_minmax_f32) { |
| 1437 // Test the Float32Min and Float32Max macros. |
| 1438 CcTest::InitializeVM(); |
| 1439 Isolate* isolate = CcTest::i_isolate(); |
| 1440 HandleScope scope(isolate); |
| 1441 |
| 1442 MacroAssembler assembler(isolate, NULL, 0, |
| 1443 v8::internal::CodeObjectRequired::kYes); |
| 1444 MacroAssembler* masm = &assembler; |
| 1445 |
| 1446 struct Inputs { |
| 1447 float src1_; |
| 1448 float src2_; |
| 1449 }; |
| 1450 |
| 1451 struct Results { |
| 1452 // Check all register aliasing possibilities in order to exercise all |
| 1453 // code-paths in the macro assembler. |
| 1454 float min_abc_; |
| 1455 float min_aab_; |
| 1456 float min_aba_; |
| 1457 float max_abc_; |
| 1458 float max_aab_; |
| 1459 float max_aba_; |
| 1460 }; |
| 1461 |
| 1462 ::F4 f = GenerateMacroFloat32MinMax<FPURegister, Inputs, Results>(masm); |
| 1463 Object* dummy = nullptr; |
| 1464 USE(dummy); |
| 1465 |
| 1466 #define CHECK_MINMAX(src1, src2, min, max) \ |
| 1467 do { \ |
| 1468 Inputs inputs = {src1, src2}; \ |
| 1469 Results results; \ |
| 1470 dummy = CALL_GENERATED_CODE(isolate, f, &inputs, &results, 0, 0, 0); \ |
| 1471 CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_abc_)); \ |
| 1472 CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_aab_)); \ |
| 1473 CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_aba_)); \ |
| 1474 CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_abc_)); \ |
| 1475 CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_aab_)); \ |
| 1476 CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_aba_)); \ |
| 1477 /* Use a bit_cast to correctly identify -0.0 and NaNs. */ \ |
| 1478 } while (0) |
| 1479 |
| 1480 float nan_a = std::numeric_limits<float>::quiet_NaN(); |
| 1481 float nan_b = std::numeric_limits<float>::quiet_NaN(); |
| 1482 |
| 1483 CHECK_MINMAX(1.0f, -1.0f, -1.0f, 1.0f); |
| 1484 CHECK_MINMAX(-1.0f, 1.0f, -1.0f, 1.0f); |
| 1485 CHECK_MINMAX(0.0f, -1.0f, -1.0f, 0.0f); |
| 1486 CHECK_MINMAX(-1.0f, 0.0f, -1.0f, 0.0f); |
| 1487 CHECK_MINMAX(-0.0f, -1.0f, -1.0f, -0.0f); |
| 1488 CHECK_MINMAX(-1.0f, -0.0f, -1.0f, -0.0f); |
| 1489 CHECK_MINMAX(0.0f, 1.0f, 0.0f, 1.0f); |
| 1490 CHECK_MINMAX(1.0f, 0.0f, 0.0f, 1.0f); |
| 1491 |
| 1492 CHECK_MINMAX(0.0f, 0.0f, 0.0f, 0.0f); |
| 1493 CHECK_MINMAX(-0.0f, -0.0f, -0.0f, -0.0f); |
| 1494 CHECK_MINMAX(-0.0f, 0.0f, -0.0f, 0.0f); |
| 1495 CHECK_MINMAX(0.0f, -0.0f, -0.0f, 0.0f); |
| 1496 |
| 1497 CHECK_MINMAX(0.0f, nan_a, nan_a, nan_a); |
| 1498 CHECK_MINMAX(nan_a, 0.0f, nan_a, nan_a); |
| 1499 CHECK_MINMAX(nan_a, nan_b, nan_a, nan_a); |
| 1500 CHECK_MINMAX(nan_b, nan_a, nan_b, nan_b); |
| 1501 |
| 1502 #undef CHECK_MINMAX |
| 1503 } |
| 1504 |
| 1505 template <typename T, typename Inputs, typename Results> |
| 1506 static ::F4 GenerateMacroFloat64MinMax(MacroAssembler* masm) { |
| 1507 T a = T::from_code(4); // f4 |
| 1508 T b = T::from_code(6); // f6 |
| 1509 T c = T::from_code(8); // f8 |
| 1510 |
| 1511 Label ool_min_abc, ool_min_aab, ool_min_aba; |
| 1512 Label ool_max_abc, ool_max_aab, ool_max_aba; |
| 1513 |
| 1514 Label done_min_abc, done_min_aab, done_min_aba; |
| 1515 Label done_max_abc, done_max_aab, done_max_aba; |
| 1516 |
| 1517 #define FLOAT_MIN_MAX(fminmax, res, x, y, done, ool, res_field) \ |
| 1518 __ ldc1(x, MemOperand(a0, offsetof(Inputs, src1_))); \ |
| 1519 __ ldc1(y, MemOperand(a0, offsetof(Inputs, src2_))); \ |
| 1520 __ fminmax(res, x, y, &ool); \ |
| 1521 __ bind(&done); \ |
| 1522 __ sdc1(a, MemOperand(a1, offsetof(Results, res_field))) |
| 1523 |
| 1524 // a = min(b, c); |
| 1525 FLOAT_MIN_MAX(Float64Min, a, b, c, done_min_abc, ool_min_abc, min_abc_); |
| 1526 // a = min(a, b); |
| 1527 FLOAT_MIN_MAX(Float64Min, a, a, b, done_min_aab, ool_min_aab, min_aab_); |
| 1528 // a = min(b, a); |
| 1529 FLOAT_MIN_MAX(Float64Min, a, b, a, done_min_aba, ool_min_aba, min_aba_); |
| 1530 |
| 1531 // a = max(b, c); |
| 1532 FLOAT_MIN_MAX(Float64Max, a, b, c, done_max_abc, ool_max_abc, max_abc_); |
| 1533 // a = max(a, b); |
| 1534 FLOAT_MIN_MAX(Float64Max, a, a, b, done_max_aab, ool_max_aab, max_aab_); |
| 1535 // a = max(b, a); |
| 1536 FLOAT_MIN_MAX(Float64Max, a, b, a, done_max_aba, ool_max_aba, max_aba_); |
| 1537 |
| 1538 #undef FLOAT_MIN_MAX |
| 1539 |
| 1540 __ jr(ra); |
| 1541 __ nop(); |
| 1542 |
| 1543 // Generate out-of-line cases. |
| 1544 __ bind(&ool_min_abc); |
| 1545 __ Float64MinOutOfLine(a, b, c); |
| 1546 __ b(&done_min_abc); |
| 1547 |
| 1548 __ bind(&ool_min_aab); |
| 1549 __ Float64MinOutOfLine(a, a, b); |
| 1550 __ b(&done_min_aab); |
| 1551 |
| 1552 __ bind(&ool_min_aba); |
| 1553 __ Float64MinOutOfLine(a, b, a); |
| 1554 __ b(&done_min_aba); |
| 1555 |
| 1556 __ bind(&ool_max_abc); |
| 1557 __ Float64MaxOutOfLine(a, b, c); |
| 1558 __ b(&done_max_abc); |
| 1559 |
| 1560 __ bind(&ool_max_aab); |
| 1561 __ Float64MaxOutOfLine(a, a, b); |
| 1562 __ b(&done_max_aab); |
| 1563 |
| 1564 __ bind(&ool_max_aba); |
| 1565 __ Float64MaxOutOfLine(a, b, a); |
| 1566 __ b(&done_max_aba); |
| 1567 |
| 1568 CodeDesc desc; |
| 1569 masm->GetCode(&desc); |
| 1570 Handle<Code> code = masm->isolate()->factory()->NewCode( |
| 1571 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1572 #ifdef DEBUG |
| 1573 OFStream os(stdout); |
| 1574 code->Print(os); |
| 1575 #endif |
| 1576 return FUNCTION_CAST<::F4>(code->entry()); |
| 1577 } |
| 1578 |
| 1579 TEST(macro_float_minmax_f64) { |
| 1580 // Test the Float64Min and Float64Max macros. |
| 1581 CcTest::InitializeVM(); |
| 1582 Isolate* isolate = CcTest::i_isolate(); |
| 1583 HandleScope scope(isolate); |
| 1584 |
| 1585 MacroAssembler assembler(isolate, NULL, 0, |
| 1586 v8::internal::CodeObjectRequired::kYes); |
| 1587 MacroAssembler* masm = &assembler; |
| 1588 |
| 1589 struct Inputs { |
| 1590 double src1_; |
| 1591 double src2_; |
| 1592 }; |
| 1593 |
| 1594 struct Results { |
| 1595 // Check all register aliasing possibilities in order to exercise all |
| 1596 // code-paths in the macro assembler. |
| 1597 double min_abc_; |
| 1598 double min_aab_; |
| 1599 double min_aba_; |
| 1600 double max_abc_; |
| 1601 double max_aab_; |
| 1602 double max_aba_; |
| 1603 }; |
| 1604 |
| 1605 ::F4 f = GenerateMacroFloat64MinMax<DoubleRegister, Inputs, Results>(masm); |
| 1606 Object* dummy = nullptr; |
| 1607 USE(dummy); |
| 1608 |
| 1609 #define CHECK_MINMAX(src1, src2, min, max) \ |
| 1610 do { \ |
| 1611 Inputs inputs = {src1, src2}; \ |
| 1612 Results results; \ |
| 1613 dummy = CALL_GENERATED_CODE(isolate, f, &inputs, &results, 0, 0, 0); \ |
| 1614 CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_abc_)); \ |
| 1615 CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_aab_)); \ |
| 1616 CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_aba_)); \ |
| 1617 CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_abc_)); \ |
| 1618 CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_aab_)); \ |
| 1619 CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_aba_)); \ |
| 1620 /* Use a bit_cast to correctly identify -0.0 and NaNs. */ \ |
| 1621 } while (0) |
| 1622 |
| 1623 double nan_a = std::numeric_limits<double>::quiet_NaN(); |
| 1624 double nan_b = std::numeric_limits<double>::quiet_NaN(); |
| 1625 |
| 1626 CHECK_MINMAX(1.0, -1.0, -1.0, 1.0); |
| 1627 CHECK_MINMAX(-1.0, 1.0, -1.0, 1.0); |
| 1628 CHECK_MINMAX(0.0, -1.0, -1.0, 0.0); |
| 1629 CHECK_MINMAX(-1.0, 0.0, -1.0, 0.0); |
| 1630 CHECK_MINMAX(-0.0, -1.0, -1.0, -0.0); |
| 1631 CHECK_MINMAX(-1.0, -0.0, -1.0, -0.0); |
| 1632 CHECK_MINMAX(0.0, 1.0, 0.0, 1.0); |
| 1633 CHECK_MINMAX(1.0, 0.0, 0.0, 1.0); |
| 1634 |
| 1635 CHECK_MINMAX(0.0, 0.0, 0.0, 0.0); |
| 1636 CHECK_MINMAX(-0.0, -0.0, -0.0, -0.0); |
| 1637 CHECK_MINMAX(-0.0, 0.0, -0.0, 0.0); |
| 1638 CHECK_MINMAX(0.0, -0.0, -0.0, 0.0); |
| 1639 |
| 1640 CHECK_MINMAX(0.0, nan_a, nan_a, nan_a); |
| 1641 CHECK_MINMAX(nan_a, 0.0, nan_a, nan_a); |
| 1642 CHECK_MINMAX(nan_a, nan_b, nan_a, nan_a); |
| 1643 CHECK_MINMAX(nan_b, nan_a, nan_b, nan_b); |
| 1644 |
| 1645 #undef CHECK_MINMAX |
| 1646 } |
| 1647 |
1361 #undef __ | 1648 #undef __ |
OLD | NEW |