OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 27 matching lines...) Expand all Loading... |
38 | 38 |
39 #include "test/cctest/cctest.h" | 39 #include "test/cctest/cctest.h" |
40 | 40 |
41 using namespace v8::internal; | 41 using namespace v8::internal; |
42 | 42 |
43 | 43 |
44 // Define these function prototypes to match JSEntryFunction in execution.cc. | 44 // Define these function prototypes to match JSEntryFunction in execution.cc. |
45 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4); | 45 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4); |
46 typedef Object* (*F2)(int x, int y, int p2, int p3, int p4); | 46 typedef Object* (*F2)(int x, int y, int p2, int p3, int p4); |
47 typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4); | 47 typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4); |
| 48 typedef Object* (*F4)(int64_t x, int64_t y, int64_t p2, int64_t p3, int64_t p4); |
48 | 49 |
49 // clang-format off | 50 // clang-format off |
50 | 51 |
51 | 52 |
52 #define __ assm. | 53 #define __ assm. |
53 | 54 |
54 TEST(MIPS0) { | 55 TEST(MIPS0) { |
55 CcTest::InitializeVM(); | 56 CcTest::InitializeVM(); |
56 Isolate* isolate = CcTest::i_isolate(); | 57 Isolate* isolate = CcTest::i_isolate(); |
57 HandleScope scope(isolate); | 58 HandleScope scope(isolate); |
(...skipping 4383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4441 test.dOp2 = -5.0; | 4442 test.dOp2 = -5.0; |
4442 test.fOp1 = std::numeric_limits<float>::quiet_NaN(); | 4443 test.fOp1 = std::numeric_limits<float>::quiet_NaN(); |
4443 test.fOp2 = -5.0; | 4444 test.fOp2 = -5.0; |
4444 | 4445 |
4445 (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); | 4446 (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); |
4446 CHECK_EQ(true, std::isnan(test.dRes)); | 4447 CHECK_EQ(true, std::isnan(test.dRes)); |
4447 CHECK_EQ(true, std::isnan(test.fRes)); | 4448 CHECK_EQ(true, std::isnan(test.fRes)); |
4448 } | 4449 } |
4449 | 4450 |
4450 | 4451 |
| 4452 uint64_t run_align(uint64_t rs_value, uint64_t rt_value, uint8_t bp) { |
| 4453 Isolate* isolate = CcTest::i_isolate(); |
| 4454 HandleScope scope(isolate); |
| 4455 |
| 4456 MacroAssembler assm(isolate, NULL, 0); |
| 4457 |
| 4458 __ align(v0, a0, a1, bp); |
| 4459 __ jr(ra); |
| 4460 __ nop(); |
| 4461 |
| 4462 CodeDesc desc; |
| 4463 assm.GetCode(&desc); |
| 4464 Handle<Code> code = isolate->factory()->NewCode( |
| 4465 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 4466 |
| 4467 F2 f = FUNCTION_CAST<F2>(code->entry()); |
| 4468 |
| 4469 uint64_t res = |
| 4470 reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, rs_value, |
| 4471 rt_value, |
| 4472 0, 0, 0)); |
| 4473 |
| 4474 return res; |
| 4475 } |
| 4476 |
| 4477 |
| 4478 TEST(r6_align) { |
| 4479 if (kArchVariant == kMips64r6) { |
| 4480 CcTest::InitializeVM(); |
| 4481 |
| 4482 struct TestCaseAlign { |
| 4483 uint64_t rs_value; |
| 4484 uint64_t rt_value; |
| 4485 uint8_t bp; |
| 4486 uint64_t expected_res; |
| 4487 }; |
| 4488 |
| 4489 struct TestCaseAlign tc[] = { |
| 4490 // rs_value, rt_value, bp, expected_res |
| 4491 { 0x11223344, 0xaabbccdd, 0, 0xffffffffaabbccdd }, |
| 4492 { 0x11223344, 0xaabbccdd, 1, 0xffffffffbbccdd11 }, |
| 4493 { 0x11223344, 0xaabbccdd, 2, 0xffffffffccdd1122 }, |
| 4494 { 0x11223344, 0xaabbccdd, 3, 0xffffffffdd112233 }, |
| 4495 }; |
| 4496 |
| 4497 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAlign); |
| 4498 for (size_t i = 0; i < nr_test_cases; ++i) { |
| 4499 CHECK_EQ(tc[i].expected_res, run_align(tc[i].rs_value, |
| 4500 tc[i].rt_value, |
| 4501 tc[i].bp)); |
| 4502 } |
| 4503 } |
| 4504 } |
| 4505 |
| 4506 |
| 4507 uint64_t run_dalign(uint64_t rs_value, uint64_t rt_value, uint8_t bp) { |
| 4508 Isolate* isolate = CcTest::i_isolate(); |
| 4509 HandleScope scope(isolate); |
| 4510 |
| 4511 MacroAssembler assm(isolate, NULL, 0); |
| 4512 |
| 4513 __ dalign(v0, a0, a1, bp); |
| 4514 __ jr(ra); |
| 4515 __ nop(); |
| 4516 |
| 4517 CodeDesc desc; |
| 4518 assm.GetCode(&desc); |
| 4519 Handle<Code> code = isolate->factory()->NewCode( |
| 4520 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 4521 |
| 4522 F4 f = FUNCTION_CAST<F4>(code->entry()); |
| 4523 uint64_t res = |
| 4524 reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, rs_value, |
| 4525 rt_value, |
| 4526 0, 0, 0)); |
| 4527 |
| 4528 return res; |
| 4529 } |
| 4530 |
| 4531 |
| 4532 TEST(r6_dalign) { |
| 4533 if (kArchVariant == kMips64r6) { |
| 4534 CcTest::InitializeVM(); |
| 4535 |
| 4536 struct TestCaseDalign { |
| 4537 uint64_t rs_value; |
| 4538 uint64_t rt_value; |
| 4539 uint8_t bp; |
| 4540 uint64_t expected_res; |
| 4541 }; |
| 4542 |
| 4543 struct TestCaseDalign tc[] = { |
| 4544 // rs_value, rt_value, bp, expected_res |
| 4545 { 0x1122334455667700, 0xaabbccddeeff8899, 0, 0xaabbccddeeff8899 }, |
| 4546 { 0x1122334455667700, 0xaabbccddeeff8899, 1, 0xbbccddeeff889911 }, |
| 4547 { 0x1122334455667700, 0xaabbccddeeff8899, 2, 0xccddeeff88991122 }, |
| 4548 { 0x1122334455667700, 0xaabbccddeeff8899, 3, 0xddeeff8899112233 }, |
| 4549 { 0x1122334455667700, 0xaabbccddeeff8899, 4, 0xeeff889911223344 }, |
| 4550 { 0x1122334455667700, 0xaabbccddeeff8899, 5, 0xff88991122334455 }, |
| 4551 { 0x1122334455667700, 0xaabbccddeeff8899, 6, 0x8899112233445566 }, |
| 4552 { 0x1122334455667700, 0xaabbccddeeff8899, 7, 0x9911223344556677 } |
| 4553 }; |
| 4554 |
| 4555 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseDalign); |
| 4556 for (size_t i = 0; i < nr_test_cases; ++i) { |
| 4557 CHECK_EQ(tc[i].expected_res, run_dalign(tc[i].rs_value, |
| 4558 tc[i].rt_value, |
| 4559 tc[i].bp)); |
| 4560 } |
| 4561 } |
| 4562 } |
| 4563 |
| 4564 |
| 4565 uint64_t PC; // The program counter. |
| 4566 |
| 4567 uint64_t run_aluipc(int16_t offset) { |
| 4568 Isolate* isolate = CcTest::i_isolate(); |
| 4569 HandleScope scope(isolate); |
| 4570 |
| 4571 MacroAssembler assm(isolate, NULL, 0); |
| 4572 |
| 4573 __ aluipc(v0, offset); |
| 4574 __ jr(ra); |
| 4575 __ nop(); |
| 4576 |
| 4577 CodeDesc desc; |
| 4578 assm.GetCode(&desc); |
| 4579 Handle<Code> code = isolate->factory()->NewCode( |
| 4580 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 4581 |
| 4582 F2 f = FUNCTION_CAST<F2>(code->entry()); |
| 4583 PC = (uint64_t) f; // Set the program counter. |
| 4584 |
| 4585 uint64_t res = |
| 4586 reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); |
| 4587 |
| 4588 return res; |
| 4589 } |
| 4590 |
| 4591 |
| 4592 TEST(r6_aluipc) { |
| 4593 if (kArchVariant == kMips64r6) { |
| 4594 CcTest::InitializeVM(); |
| 4595 |
| 4596 struct TestCaseAluipc { |
| 4597 int16_t offset; |
| 4598 }; |
| 4599 |
| 4600 struct TestCaseAluipc tc[] = { |
| 4601 // offset |
| 4602 { -32768 }, // 0x8000 |
| 4603 { -1 }, // 0xFFFF |
| 4604 { 0 }, |
| 4605 { 1 }, |
| 4606 { 32767 }, // 0x7FFF |
| 4607 }; |
| 4608 |
| 4609 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAluipc); |
| 4610 for (size_t i = 0; i < nr_test_cases; ++i) { |
| 4611 PC = 0; |
| 4612 uint64_t res = run_aluipc(tc[i].offset); |
| 4613 // Now, the program_counter (PC) is set. |
| 4614 uint64_t expected_res = ~0x0FFFF & (PC + (tc[i].offset << 16)); |
| 4615 CHECK_EQ(expected_res, res); |
| 4616 } |
| 4617 } |
| 4618 } |
| 4619 |
| 4620 |
| 4621 uint64_t run_auipc(int16_t offset) { |
| 4622 Isolate* isolate = CcTest::i_isolate(); |
| 4623 HandleScope scope(isolate); |
| 4624 |
| 4625 MacroAssembler assm(isolate, NULL, 0); |
| 4626 |
| 4627 __ auipc(v0, offset); |
| 4628 __ jr(ra); |
| 4629 __ nop(); |
| 4630 |
| 4631 CodeDesc desc; |
| 4632 assm.GetCode(&desc); |
| 4633 Handle<Code> code = isolate->factory()->NewCode( |
| 4634 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 4635 |
| 4636 F2 f = FUNCTION_CAST<F2>(code->entry()); |
| 4637 PC = (uint64_t) f; // Set the program counter. |
| 4638 |
| 4639 uint64_t res = |
| 4640 reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); |
| 4641 |
| 4642 return res; |
| 4643 } |
| 4644 |
| 4645 |
| 4646 TEST(r6_auipc) { |
| 4647 if (kArchVariant == kMips64r6) { |
| 4648 CcTest::InitializeVM(); |
| 4649 |
| 4650 struct TestCaseAuipc { |
| 4651 int16_t offset; |
| 4652 }; |
| 4653 |
| 4654 struct TestCaseAuipc tc[] = { |
| 4655 // offset |
| 4656 { -32768 }, // 0x8000 |
| 4657 { -1 }, // 0xFFFF |
| 4658 { 0 }, |
| 4659 { 1 }, |
| 4660 { 32767 }, // 0x7FFF |
| 4661 }; |
| 4662 |
| 4663 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAuipc); |
| 4664 for (size_t i = 0; i < nr_test_cases; ++i) { |
| 4665 PC = 0; |
| 4666 uint64_t res = run_auipc(tc[i].offset); |
| 4667 // Now, the program_counter (PC) is set. |
| 4668 uint64_t expected_res = PC + (tc[i].offset << 16); |
| 4669 CHECK_EQ(expected_res, res); |
| 4670 } |
| 4671 } |
| 4672 } |
| 4673 |
| 4674 |
| 4675 uint64_t run_lwpc(int offset) { |
| 4676 Isolate* isolate = CcTest::i_isolate(); |
| 4677 HandleScope scope(isolate); |
| 4678 |
| 4679 MacroAssembler assm(isolate, NULL, 0); |
| 4680 |
| 4681 // 256k instructions; 2^8k |
| 4682 // addiu t3, a4, 0xffff; (0x250fffff) |
| 4683 // ... |
| 4684 // addiu t0, a4, 0x0000; (0x250c0000) |
| 4685 uint32_t addiu_start_1 = 0x25000000; |
| 4686 for (int32_t i = 0xfffff; i >= 0xc0000; --i) { |
| 4687 uint32_t addiu_new = addiu_start_1 + i; |
| 4688 __ dd(addiu_new); |
| 4689 } |
| 4690 |
| 4691 __ lwpc(t8, offset); // offset 0; 0xef080000 (t8 register) |
| 4692 __ mov(v0, t8); |
| 4693 |
| 4694 // 256k instructions; 2^8k |
| 4695 // addiu a4, a4, 0x0000; (0x25080000) |
| 4696 // ... |
| 4697 // addiu a7, a4, 0xffff; (0x250bffff) |
| 4698 uint32_t addiu_start_2 = 0x25000000; |
| 4699 for (int32_t i = 0x80000; i <= 0xbffff; ++i) { |
| 4700 uint32_t addiu_new = addiu_start_2 + i; |
| 4701 __ dd(addiu_new); |
| 4702 } |
| 4703 |
| 4704 __ jr(ra); |
| 4705 __ nop(); |
| 4706 |
| 4707 CodeDesc desc; |
| 4708 assm.GetCode(&desc); |
| 4709 Handle<Code> code = isolate->factory()->NewCode( |
| 4710 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 4711 |
| 4712 F2 f = FUNCTION_CAST<F2>(code->entry()); |
| 4713 |
| 4714 uint64_t res = |
| 4715 reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); |
| 4716 |
| 4717 return res; |
| 4718 } |
| 4719 |
| 4720 |
| 4721 TEST(r6_lwpc) { |
| 4722 if (kArchVariant == kMips64r6) { |
| 4723 CcTest::InitializeVM(); |
| 4724 |
| 4725 struct TestCaseLwpc { |
| 4726 int offset; |
| 4727 uint64_t expected_res; |
| 4728 }; |
| 4729 |
| 4730 struct TestCaseLwpc tc[] = { |
| 4731 // offset, expected_res |
| 4732 { -262144, 0x250fffff }, // offset 0x40000 |
| 4733 { -4, 0x250c0003 }, |
| 4734 { -1, 0x250c0000 }, |
| 4735 { 0, 0xffffffffef080000 }, |
| 4736 { 1, 0x03001025 }, // mov(v0, t8) |
| 4737 { 2, 0x25080000 }, |
| 4738 { 4, 0x25080002 }, |
| 4739 { 262143, 0x250bfffd }, // offset 0x3ffff |
| 4740 }; |
| 4741 |
| 4742 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLwpc); |
| 4743 for (size_t i = 0; i < nr_test_cases; ++i) { |
| 4744 uint64_t res = run_lwpc(tc[i].offset); |
| 4745 CHECK_EQ(tc[i].expected_res, res); |
| 4746 } |
| 4747 } |
| 4748 } |
| 4749 |
| 4750 |
| 4751 uint64_t run_lwupc(int offset) { |
| 4752 Isolate* isolate = CcTest::i_isolate(); |
| 4753 HandleScope scope(isolate); |
| 4754 |
| 4755 MacroAssembler assm(isolate, NULL, 0); |
| 4756 |
| 4757 // 256k instructions; 2^8k |
| 4758 // addiu t3, a4, 0xffff; (0x250fffff) |
| 4759 // ... |
| 4760 // addiu t0, a4, 0x0000; (0x250c0000) |
| 4761 uint32_t addiu_start_1 = 0x25000000; |
| 4762 for (int32_t i = 0xfffff; i >= 0xc0000; --i) { |
| 4763 uint32_t addiu_new = addiu_start_1 + i; |
| 4764 __ dd(addiu_new); |
| 4765 } |
| 4766 |
| 4767 __ lwupc(t8, offset); // offset 0; 0xef080000 (t8 register) |
| 4768 __ mov(v0, t8); |
| 4769 |
| 4770 // 256k instructions; 2^8k |
| 4771 // addiu a4, a4, 0x0000; (0x25080000) |
| 4772 // ... |
| 4773 // addiu a7, a4, 0xffff; (0x250bffff) |
| 4774 uint32_t addiu_start_2 = 0x25000000; |
| 4775 for (int32_t i = 0x80000; i <= 0xbffff; ++i) { |
| 4776 uint32_t addiu_new = addiu_start_2 + i; |
| 4777 __ dd(addiu_new); |
| 4778 } |
| 4779 |
| 4780 __ jr(ra); |
| 4781 __ nop(); |
| 4782 |
| 4783 CodeDesc desc; |
| 4784 assm.GetCode(&desc); |
| 4785 Handle<Code> code = isolate->factory()->NewCode( |
| 4786 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 4787 |
| 4788 F2 f = FUNCTION_CAST<F2>(code->entry()); |
| 4789 |
| 4790 uint64_t res = |
| 4791 reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); |
| 4792 |
| 4793 return res; |
| 4794 } |
| 4795 |
| 4796 |
| 4797 TEST(r6_lwupc) { |
| 4798 if (kArchVariant == kMips64r6) { |
| 4799 CcTest::InitializeVM(); |
| 4800 |
| 4801 struct TestCaseLwupc { |
| 4802 int offset; |
| 4803 uint64_t expected_res; |
| 4804 }; |
| 4805 |
| 4806 struct TestCaseLwupc tc[] = { |
| 4807 // offset, expected_res |
| 4808 { -262144, 0x250fffff }, // offset 0x40000 |
| 4809 { -4, 0x250c0003 }, |
| 4810 { -1, 0x250c0000 }, |
| 4811 { 0, 0xef100000 }, |
| 4812 { 1, 0x03001025 }, // mov(v0, t8) |
| 4813 { 2, 0x25080000 }, |
| 4814 { 4, 0x25080002 }, |
| 4815 { 262143, 0x250bfffd }, // offset 0x3ffff |
| 4816 }; |
| 4817 |
| 4818 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLwupc); |
| 4819 for (size_t i = 0; i < nr_test_cases; ++i) { |
| 4820 uint64_t res = run_lwupc(tc[i].offset); |
| 4821 CHECK_EQ(tc[i].expected_res, res); |
| 4822 } |
| 4823 } |
| 4824 } |
| 4825 |
| 4826 |
| 4827 uint64_t run_jic(int16_t offset) { |
| 4828 Isolate* isolate = CcTest::i_isolate(); |
| 4829 HandleScope scope(isolate); |
| 4830 |
| 4831 MacroAssembler assm(isolate, NULL, 0); |
| 4832 |
| 4833 Label get_program_counter, stop_execution; |
| 4834 __ push(ra); |
| 4835 __ li(v0, 0); |
| 4836 __ li(t1, 0x66); |
| 4837 |
| 4838 __ addiu(v0, v0, 0x1); // <-- offset = -32 |
| 4839 __ addiu(v0, v0, 0x2); |
| 4840 __ addiu(v0, v0, 0x10); |
| 4841 __ addiu(v0, v0, 0x20); |
| 4842 __ beq(v0, t1, &stop_execution); |
| 4843 __ nop(); |
| 4844 |
| 4845 __ bal(&get_program_counter); // t0 <- program counter |
| 4846 __ nop(); |
| 4847 __ jic(t0, offset); |
| 4848 |
| 4849 __ addiu(v0, v0, 0x100); |
| 4850 __ addiu(v0, v0, 0x200); |
| 4851 __ addiu(v0, v0, 0x1000); |
| 4852 __ addiu(v0, v0, 0x2000); // <--- offset = 16 |
| 4853 __ pop(ra); |
| 4854 __ jr(ra); |
| 4855 __ nop(); |
| 4856 |
| 4857 __ bind(&get_program_counter); |
| 4858 __ mov(t0, ra); |
| 4859 __ jr(ra); |
| 4860 __ nop(); |
| 4861 |
| 4862 __ bind(&stop_execution); |
| 4863 __ pop(ra); |
| 4864 __ jr(ra); |
| 4865 __ nop(); |
| 4866 |
| 4867 CodeDesc desc; |
| 4868 assm.GetCode(&desc); |
| 4869 Handle<Code> code = isolate->factory()->NewCode( |
| 4870 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 4871 |
| 4872 F2 f = FUNCTION_CAST<F2>(code->entry()); |
| 4873 |
| 4874 uint64_t res = |
| 4875 reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); |
| 4876 |
| 4877 return res; |
| 4878 } |
| 4879 |
| 4880 |
| 4881 TEST(r6_jic) { |
| 4882 if (kArchVariant == kMips64r6) { |
| 4883 CcTest::InitializeVM(); |
| 4884 |
| 4885 struct TestCaseJic { |
| 4886 // As rt will be used t0 register which will have value of |
| 4887 // the program counter for the jic instruction. |
| 4888 int16_t offset; |
| 4889 uint32_t expected_res; |
| 4890 }; |
| 4891 |
| 4892 struct TestCaseJic tc[] = { |
| 4893 // offset, expected_result |
| 4894 { 16, 0x2033 }, |
| 4895 { 4, 0x3333 }, |
| 4896 { -32, 0x66 }, |
| 4897 }; |
| 4898 |
| 4899 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseJic); |
| 4900 for (size_t i = 0; i < nr_test_cases; ++i) { |
| 4901 uint64_t res = run_jic(tc[i].offset); |
| 4902 CHECK_EQ(tc[i].expected_res, res); |
| 4903 } |
| 4904 } |
| 4905 } |
| 4906 |
| 4907 |
| 4908 uint64_t run_beqzc(int32_t value, int32_t offset) { |
| 4909 Isolate* isolate = CcTest::i_isolate(); |
| 4910 HandleScope scope(isolate); |
| 4911 |
| 4912 MacroAssembler assm(isolate, NULL, 0); |
| 4913 |
| 4914 Label stop_execution; |
| 4915 __ li(v0, 0); |
| 4916 __ li(t1, 0x66); |
| 4917 |
| 4918 __ addiu(v0, v0, 0x1); // <-- offset = -8 |
| 4919 __ addiu(v0, v0, 0x2); |
| 4920 __ addiu(v0, v0, 0x10); |
| 4921 __ addiu(v0, v0, 0x20); |
| 4922 __ beq(v0, t1, &stop_execution); |
| 4923 __ nop(); |
| 4924 |
| 4925 __ beqzc(a0, offset); |
| 4926 |
| 4927 __ addiu(v0, v0, 0x1); |
| 4928 __ addiu(v0, v0, 0x100); |
| 4929 __ addiu(v0, v0, 0x200); |
| 4930 __ addiu(v0, v0, 0x1000); |
| 4931 __ addiu(v0, v0, 0x2000); // <--- offset = 4 |
| 4932 __ jr(ra); |
| 4933 __ nop(); |
| 4934 |
| 4935 __ bind(&stop_execution); |
| 4936 __ jr(ra); |
| 4937 __ nop(); |
| 4938 |
| 4939 CodeDesc desc; |
| 4940 assm.GetCode(&desc); |
| 4941 Handle<Code> code = isolate->factory()->NewCode( |
| 4942 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 4943 |
| 4944 F2 f = FUNCTION_CAST<F2>(code->entry()); |
| 4945 |
| 4946 uint64_t res = |
| 4947 reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, value, 0, 0, 0, 0)); |
| 4948 |
| 4949 return res; |
| 4950 } |
| 4951 |
| 4952 |
| 4953 TEST(r6_beqzc) { |
| 4954 if (kArchVariant == kMips64r6) { |
| 4955 CcTest::InitializeVM(); |
| 4956 |
| 4957 struct TestCaseBeqzc { |
| 4958 uint32_t value; |
| 4959 int32_t offset; |
| 4960 uint32_t expected_res; |
| 4961 }; |
| 4962 |
| 4963 struct TestCaseBeqzc tc[] = { |
| 4964 // value, offset, expected_res |
| 4965 { 0x0, -8, 0x66 }, |
| 4966 { 0x0, 0, 0x3334 }, |
| 4967 { 0x0, 1, 0x3333 }, |
| 4968 { 0xabc, 1, 0x3334 }, |
| 4969 { 0x0, 4, 0x2033 }, |
| 4970 }; |
| 4971 |
| 4972 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBeqzc); |
| 4973 for (size_t i = 0; i < nr_test_cases; ++i) { |
| 4974 uint64_t res = run_beqzc(tc[i].value, tc[i].offset); |
| 4975 CHECK_EQ(tc[i].expected_res, res); |
| 4976 } |
| 4977 } |
| 4978 } |
| 4979 |
| 4980 |
| 4981 uint64_t run_jialc(int16_t offset) { |
| 4982 Isolate* isolate = CcTest::i_isolate(); |
| 4983 HandleScope scope(isolate); |
| 4984 |
| 4985 MacroAssembler assm(isolate, NULL, 0); |
| 4986 |
| 4987 Label main_block, get_program_counter; |
| 4988 __ push(ra); |
| 4989 __ li(v0, 0); |
| 4990 __ beq(v0, v0, &main_block); |
| 4991 __ nop(); |
| 4992 |
| 4993 // Block 1 |
| 4994 __ addiu(v0, v0, 0x1); // <-- offset = -40 |
| 4995 __ addiu(v0, v0, 0x2); |
| 4996 __ jr(ra); |
| 4997 __ nop(); |
| 4998 |
| 4999 // Block 2 |
| 5000 __ addiu(v0, v0, 0x10); // <-- offset = -24 |
| 5001 __ addiu(v0, v0, 0x20); |
| 5002 __ jr(ra); |
| 5003 __ nop(); |
| 5004 |
| 5005 // Block 3 (Main) |
| 5006 __ bind(&main_block); |
| 5007 __ bal(&get_program_counter); // t0 <- program counter |
| 5008 __ nop(); |
| 5009 __ jialc(t0, offset); |
| 5010 __ addiu(v0, v0, 0x4); |
| 5011 __ pop(ra); |
| 5012 __ jr(ra); |
| 5013 __ nop(); |
| 5014 |
| 5015 // Block 4 |
| 5016 __ addiu(v0, v0, 0x100); // <-- offset = 20 |
| 5017 __ addiu(v0, v0, 0x200); |
| 5018 __ jr(ra); |
| 5019 __ nop(); |
| 5020 |
| 5021 // Block 5 |
| 5022 __ addiu(v0, v0, 0x1000); // <--- offset = 36 |
| 5023 __ addiu(v0, v0, 0x2000); |
| 5024 __ jr(ra); |
| 5025 __ nop(); |
| 5026 |
| 5027 __ bind(&get_program_counter); |
| 5028 __ mov(t0, ra); |
| 5029 __ jr(ra); |
| 5030 __ nop(); |
| 5031 |
| 5032 |
| 5033 CodeDesc desc; |
| 5034 assm.GetCode(&desc); |
| 5035 Handle<Code> code = isolate->factory()->NewCode( |
| 5036 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 5037 |
| 5038 F2 f = FUNCTION_CAST<F2>(code->entry()); |
| 5039 |
| 5040 uint64_t res = |
| 5041 reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); |
| 5042 |
| 5043 return res; |
| 5044 } |
| 5045 |
| 5046 |
| 5047 TEST(r6_jialc) { |
| 5048 if (kArchVariant == kMips64r6) { |
| 5049 CcTest::InitializeVM(); |
| 5050 |
| 5051 struct TestCaseJialc { |
| 5052 // As rt will be used t0 register which will have value of |
| 5053 // the program counter for the jialc instruction. |
| 5054 int16_t offset; |
| 5055 uint32_t expected_res; |
| 5056 }; |
| 5057 |
| 5058 struct TestCaseJialc tc[] = { |
| 5059 // offset, expected_res |
| 5060 { -40, 0x7 }, |
| 5061 { -24, 0x34 }, |
| 5062 { 20, 0x304 }, |
| 5063 { 36, 0x3004 } |
| 5064 }; |
| 5065 |
| 5066 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseJialc); |
| 5067 for (size_t i = 0; i < nr_test_cases; ++i) { |
| 5068 uint64_t res = run_jialc(tc[i].offset); |
| 5069 CHECK_EQ(tc[i].expected_res, res); |
| 5070 } |
| 5071 } |
| 5072 } |
| 5073 |
| 5074 |
| 5075 uint64_t run_addiupc(int32_t imm19) { |
| 5076 Isolate* isolate = CcTest::i_isolate(); |
| 5077 HandleScope scope(isolate); |
| 5078 |
| 5079 MacroAssembler assm(isolate, NULL, 0); |
| 5080 |
| 5081 __ addiupc(v0, imm19); |
| 5082 __ jr(ra); |
| 5083 __ nop(); |
| 5084 |
| 5085 CodeDesc desc; |
| 5086 assm.GetCode(&desc); |
| 5087 Handle<Code> code = isolate->factory()->NewCode( |
| 5088 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 5089 |
| 5090 F2 f = FUNCTION_CAST<F2>(code->entry()); |
| 5091 PC = (uint64_t) f; // Set the program counter. |
| 5092 |
| 5093 uint64_t res = |
| 5094 reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); |
| 5095 |
| 5096 return res; |
| 5097 } |
| 5098 |
| 5099 |
| 5100 TEST(r6_addiupc) { |
| 5101 if (kArchVariant == kMips64r6) { |
| 5102 CcTest::InitializeVM(); |
| 5103 |
| 5104 struct TestCaseAddiupc { |
| 5105 int32_t imm19; |
| 5106 }; |
| 5107 |
| 5108 struct TestCaseAddiupc tc[] = { |
| 5109 // imm19 |
| 5110 { -262144 }, // 0x40000 |
| 5111 { -1 }, // 0x7FFFF |
| 5112 { 0 }, |
| 5113 { 1 }, // 0x00001 |
| 5114 { 262143 } // 0x3FFFF |
| 5115 }; |
| 5116 |
| 5117 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAddiupc); |
| 5118 for (size_t i = 0; i < nr_test_cases; ++i) { |
| 5119 PC = 0; |
| 5120 uint64_t res = run_addiupc(tc[i].imm19); |
| 5121 // Now, the program_counter (PC) is set. |
| 5122 uint64_t expected_res = PC + (tc[i].imm19 << 2); |
| 5123 CHECK_EQ(expected_res, res); |
| 5124 } |
| 5125 } |
| 5126 } |
| 5127 |
| 5128 |
| 5129 uint64_t run_ldpc(int offset) { |
| 5130 Isolate* isolate = CcTest::i_isolate(); |
| 5131 HandleScope scope(isolate); |
| 5132 |
| 5133 MacroAssembler assm(isolate, NULL, 0); |
| 5134 |
| 5135 // 256k instructions; 2 * 2^7k = 2^8k |
| 5136 // addiu t3, a4, 0xffff; (0x250fffff) |
| 5137 // ... |
| 5138 // addiu t0, a4, 0x0000; (0x250c0000) |
| 5139 uint32_t addiu_start_1 = 0x25000000; |
| 5140 for (int32_t i = 0xfffff; i >= 0xc0000; --i) { |
| 5141 uint32_t addiu_new = addiu_start_1 + i; |
| 5142 __ dd(addiu_new); |
| 5143 } |
| 5144 |
| 5145 __ ldpc(t8, offset); // offset 0; 0xef080000 (t8 register) |
| 5146 __ mov(v0, t8); |
| 5147 |
| 5148 // 256k instructions; 2 * 2^7k = 2^8k |
| 5149 // addiu a4, a4, 0x0000; (0x25080000) |
| 5150 // ... |
| 5151 // addiu a7, a4, 0xffff; (0x250bffff) |
| 5152 uint32_t addiu_start_2 = 0x25000000; |
| 5153 for (int32_t i = 0x80000; i <= 0xbffff; ++i) { |
| 5154 uint32_t addiu_new = addiu_start_2 + i; |
| 5155 __ dd(addiu_new); |
| 5156 } |
| 5157 |
| 5158 __ jr(ra); |
| 5159 __ nop(); |
| 5160 |
| 5161 CodeDesc desc; |
| 5162 assm.GetCode(&desc); |
| 5163 Handle<Code> code = isolate->factory()->NewCode( |
| 5164 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 5165 |
| 5166 F2 f = FUNCTION_CAST<F2>(code->entry()); |
| 5167 |
| 5168 uint64_t res = |
| 5169 reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); |
| 5170 |
| 5171 return res; |
| 5172 } |
| 5173 |
| 5174 |
| 5175 TEST(r6_ldpc) { |
| 5176 if (kArchVariant == kMips64r6) { |
| 5177 CcTest::InitializeVM(); |
| 5178 |
| 5179 struct TestCaseLdpc { |
| 5180 int offset; |
| 5181 uint64_t expected_res; |
| 5182 }; |
| 5183 |
| 5184 struct TestCaseLdpc tc[] = { |
| 5185 // offset, expected_res |
| 5186 { -131072, 0x250ffffe250fffff }, |
| 5187 { -4, 0x250c0006250c0007 }, |
| 5188 { -1, 0x250c0000250c0001 }, |
| 5189 { 0, 0x03001025ef180000 }, |
| 5190 { 1, 0x2508000125080000 }, |
| 5191 { 4, 0x2508000725080006 }, |
| 5192 { 131071, 0x250bfffd250bfffc }, |
| 5193 }; |
| 5194 |
| 5195 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLdpc); |
| 5196 for (size_t i = 0; i < nr_test_cases; ++i) { |
| 5197 uint64_t res = run_ldpc(tc[i].offset); |
| 5198 CHECK_EQ(tc[i].expected_res, res); |
| 5199 } |
| 5200 } |
| 5201 } |
| 5202 |
| 5203 |
| 5204 int64_t run_bc(int32_t offset) { |
| 5205 Isolate* isolate = CcTest::i_isolate(); |
| 5206 HandleScope scope(isolate); |
| 5207 |
| 5208 MacroAssembler assm(isolate, NULL, 0); |
| 5209 |
| 5210 Label continue_1, stop_execution; |
| 5211 __ push(ra); |
| 5212 __ li(v0, 0); |
| 5213 __ li(t8, 0); |
| 5214 __ li(t9, 2); // Condition for the stopping execution. |
| 5215 |
| 5216 uint32_t instruction_addiu = 0x24420001; // addiu v0, v0, 1 |
| 5217 for (int32_t i = -100; i <= -11; ++i) { |
| 5218 __ dd(instruction_addiu); |
| 5219 } |
| 5220 |
| 5221 __ addiu(t8, t8, 1); // -10 |
| 5222 |
| 5223 __ beq(t8, t9, &stop_execution); // -9 |
| 5224 __ nop(); // -8 |
| 5225 __ beq(t8, t8, &continue_1); // -7 |
| 5226 __ nop(); // -6 |
| 5227 |
| 5228 __ bind(&stop_execution); |
| 5229 __ pop(ra); // -5, -4 |
| 5230 __ jr(ra); // -3 |
| 5231 __ nop(); // -2 |
| 5232 |
| 5233 __ bind(&continue_1); |
| 5234 __ bc(offset); // -1 |
| 5235 |
| 5236 for (int32_t i = 0; i <= 99; ++i) { |
| 5237 __ dd(instruction_addiu); |
| 5238 } |
| 5239 |
| 5240 __ pop(ra); |
| 5241 __ jr(ra); |
| 5242 __ nop(); |
| 5243 |
| 5244 CodeDesc desc; |
| 5245 assm.GetCode(&desc); |
| 5246 Handle<Code> code = isolate->factory()->NewCode( |
| 5247 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 5248 |
| 5249 F2 f = FUNCTION_CAST<F2>(code->entry()); |
| 5250 |
| 5251 int64_t res = |
| 5252 reinterpret_cast<int64_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); |
| 5253 |
| 5254 return res; |
| 5255 } |
| 5256 |
| 5257 |
| 5258 TEST(r6_bc) { |
| 5259 if (kArchVariant == kMips64r6) { |
| 5260 CcTest::InitializeVM(); |
| 5261 |
| 5262 struct TestCaseBc { |
| 5263 int32_t offset; |
| 5264 int64_t expected_res; |
| 5265 }; |
| 5266 |
| 5267 struct TestCaseBc tc[] = { |
| 5268 // offset, expected_result |
| 5269 { -100, (abs(-100) - 10) * 2 }, |
| 5270 { -11, (abs(-100) - 10 + 1) }, |
| 5271 { 0, (abs(-100) - 10 + 1 + 99) }, |
| 5272 { 1, (abs(-100) - 10 + 99) }, |
| 5273 { 99, (abs(-100) - 10 + 1) }, |
| 5274 }; |
| 5275 |
| 5276 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBc); |
| 5277 for (size_t i = 0; i < nr_test_cases; ++i) { |
| 5278 int64_t res = run_bc(tc[i].offset); |
| 5279 CHECK_EQ(tc[i].expected_res, res); |
| 5280 } |
| 5281 } |
| 5282 } |
| 5283 |
| 5284 |
| 5285 int64_t run_balc(int32_t offset) { |
| 5286 Isolate* isolate = CcTest::i_isolate(); |
| 5287 HandleScope scope(isolate); |
| 5288 |
| 5289 MacroAssembler assm(isolate, NULL, 0); |
| 5290 |
| 5291 Label continue_1, stop_execution; |
| 5292 __ push(ra); |
| 5293 __ li(v0, 0); |
| 5294 __ li(t8, 0); |
| 5295 __ li(t9, 2); // Condition for stopping execution. |
| 5296 |
| 5297 __ beq(t8, t8, &continue_1); |
| 5298 __ nop(); |
| 5299 |
| 5300 uint32_t instruction_addiu = 0x24420001; // addiu v0, v0, 1 |
| 5301 for (int32_t i = -117; i <= -57; ++i) { |
| 5302 __ dd(instruction_addiu); |
| 5303 } |
| 5304 __ jr(ra); // -56 |
| 5305 __ nop(); // -55 |
| 5306 |
| 5307 for (int32_t i = -54; i <= -4; ++i) { |
| 5308 __ dd(instruction_addiu); |
| 5309 } |
| 5310 __ jr(ra); // -3 |
| 5311 __ nop(); // -2 |
| 5312 |
| 5313 __ bind(&continue_1); |
| 5314 __ balc(offset); // -1 |
| 5315 |
| 5316 __ pop(ra); // 0, 1 |
| 5317 __ jr(ra); // 2 |
| 5318 __ nop(); // 3 |
| 5319 |
| 5320 for (int32_t i = 4; i <= 44; ++i) { |
| 5321 __ dd(instruction_addiu); |
| 5322 } |
| 5323 __ jr(ra); |
| 5324 __ nop(); |
| 5325 |
| 5326 CodeDesc desc; |
| 5327 assm.GetCode(&desc); |
| 5328 Handle<Code> code = isolate->factory()->NewCode( |
| 5329 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 5330 |
| 5331 F2 f = FUNCTION_CAST<F2>(code->entry()); |
| 5332 |
| 5333 int64_t res = |
| 5334 reinterpret_cast<int64_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); |
| 5335 |
| 5336 return res; |
| 5337 } |
| 5338 |
| 5339 |
| 5340 TEST(r6_balc) { |
| 5341 if (kArchVariant == kMips64r6) { |
| 5342 CcTest::InitializeVM(); |
| 5343 |
| 5344 struct TestCaseBalc { |
| 5345 int32_t offset; |
| 5346 int64_t expected_res; |
| 5347 }; |
| 5348 |
| 5349 struct TestCaseBalc tc[] = { |
| 5350 // offset, expected_result |
| 5351 { -117, 61 }, |
| 5352 { -54, 51 }, |
| 5353 { 0, 0 }, |
| 5354 { 4, 41 }, |
| 5355 }; |
| 5356 |
| 5357 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBalc); |
| 5358 for (size_t i = 0; i < nr_test_cases; ++i) { |
| 5359 int64_t res = run_balc(tc[i].offset); |
| 5360 CHECK_EQ(tc[i].expected_res, res); |
| 5361 } |
| 5362 } |
| 5363 } |
| 5364 |
| 5365 |
4451 #undef __ | 5366 #undef __ |
OLD | NEW |