Chromium Code Reviews| Index: test/cctest/test-assembler-mips64.cc |
| diff --git a/test/cctest/test-assembler-mips64.cc b/test/cctest/test-assembler-mips64.cc |
| index 4798bdbcddcf55e34c90dc23f4f3c01c9a5b144b..a50e2ec8e42aa015ed89a2e3e1ba4a3e2305e215 100644 |
| --- a/test/cctest/test-assembler-mips64.cc |
| +++ b/test/cctest/test-assembler-mips64.cc |
| @@ -45,6 +45,7 @@ using namespace v8::internal; |
| typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4); |
| typedef Object* (*F2)(int x, int y, int p2, int p3, int p4); |
| typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4); |
| +typedef Object* (*F4)(int64_t x, int64_t y, int64_t p2, int64_t p3, int64_t p4); |
| // clang-format off |
| @@ -4446,4 +4447,921 @@ TEST(DIV_FMT) { |
| } |
| +uint64_t run_align(uint64_t rs, uint64_t rt, uint8_t bp) { |
|
paul.l...
2015/06/15 04:57:50
I explain in more detail below -- but I don't like
ilija.pavlovic
2015/06/15 10:40:11
Parameter names changed: rs -> rs_value, rt -> rt_
|
| + Isolate* isolate = CcTest::i_isolate(); |
| + HandleScope scope(isolate); |
| + |
| + MacroAssembler assm(isolate, NULL, 0); |
| + |
| + // ALIGN rd, rs, rt, bp |
| + __ align(v0, a0, a1, bp); |
| + __ jr(ra); |
| + __ nop(); |
| + |
| + CodeDesc desc; |
| + assm.GetCode(&desc); |
| + Handle<Code> code = isolate->factory()->NewCode( |
| + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| + |
| + F2 f = FUNCTION_CAST<F2>(code->entry()); |
| + |
| + uint64_t rd = |
|
paul.l...
2015/06/15 04:57:51
Also explained in more detail below, this is not "
ilija.pavlovic
2015/06/15 10:40:11
Variable name "rd" substituted with "res". "bp" re
|
| + reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, rs, rt, bp, 0, 0)); |
| + |
| + return rd; |
| +} |
| + |
| + |
| +TEST(r6_align) { |
| + if (kArchVariant == kMips64r6) { |
| + CcTest::InitializeVM(); |
| + |
| + struct TestCaseAlign { |
| + uint64_t rd_expected; |
| + uint64_t rs; |
| + uint64_t rt; |
| + uint8_t bp; |
| + }; |
| + |
| + struct TestCaseAlign tc[] = { |
| + // rd_expected, rs, rt, bp |
|
paul.l...
2015/06/15 04:57:50
As below, object to these (register) names here fo
ilija.pavlovic
2015/06/15 10:40:11
Following substitutions are performed: rs -> rs_va
|
| + { 0xffffffffaabbccdd, 0x11223344, 0xaabbccdd, 0 }, |
| + { 0xffffffffbbccdd11, 0x11223344, 0xaabbccdd, 1 }, |
| + { 0xffffffffccdd1122, 0x11223344, 0xaabbccdd, 2 }, |
| + { 0xffffffffdd112233, 0x11223344, 0xaabbccdd, 3 }, |
| + }; |
| + |
| + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAlign); |
| + for (size_t i = 0; i < nr_test_cases; ++i) { |
| + CHECK_EQ(tc[i].rd_expected, run_align(tc[i].rs, tc[i].rt, tc[i].bp)); |
| + } |
| + } |
| +} |
| + |
| + |
| +uint64_t run_dalign(uint64_t rs, uint64_t rt, uint8_t bp) { |
| + Isolate* isolate = CcTest::i_isolate(); |
| + HandleScope scope(isolate); |
| + |
| + MacroAssembler assm(isolate, NULL, 0); |
| + |
| + // DALIGN rd, rs, rt, bp |
| + __ dalign(v0, a0, a1, bp); |
| + __ jr(ra); |
| + __ nop(); |
| + |
| + CodeDesc desc; |
| + assm.GetCode(&desc); |
| + Handle<Code> code = isolate->factory()->NewCode( |
| + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| + |
| + F4 f = FUNCTION_CAST<F4>(code->entry()); |
| + uint64_t rd = |
| + reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, rs, rt, bp, 0, 0)); |
| + |
| + return rd; |
| +} |
| + |
| + |
| +TEST(r6_dalign) { |
| + if (kArchVariant == kMips64r6) { |
| + CcTest::InitializeVM(); |
| + |
| + struct TestCaseDalign { |
| + uint64_t rd_expected; |
| + uint64_t rs; |
| + uint64_t rt; |
| + uint8_t bp; |
| + }; |
| + |
| + struct TestCaseDalign tc[] = { |
| + // rd_expected, rs, rt, bp |
| + { 0xaabbccddeeff8899, 0x1122334455667700, 0xaabbccddeeff8899, 0 }, |
| + { 0xbbccddeeff889911, 0x1122334455667700, 0xaabbccddeeff8899, 1 }, |
| + { 0xccddeeff88991122, 0x1122334455667700, 0xaabbccddeeff8899, 2 }, |
| + { 0xddeeff8899112233, 0x1122334455667700, 0xaabbccddeeff8899, 3 }, |
| + { 0xeeff889911223344, 0x1122334455667700, 0xaabbccddeeff8899, 4 }, |
| + { 0xff88991122334455, 0x1122334455667700, 0xaabbccddeeff8899, 5 }, |
| + { 0x8899112233445566, 0x1122334455667700, 0xaabbccddeeff8899, 6 }, |
| + { 0x9911223344556677, 0x1122334455667700, 0xaabbccddeeff8899, 7 } |
| + }; |
| + |
| + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseDalign); |
| + for (size_t i = 0; i < nr_test_cases; ++i) { |
| + CHECK_EQ(tc[i].rd_expected, run_dalign(tc[i].rs, tc[i].rt, tc[i].bp)); |
| + } |
| + } |
| +} |
| + |
| + |
| +uint64_t PC; // The program counter. |
| + |
| +uint64_t run_aluipc(int16_t imm16) { |
| + Isolate* isolate = CcTest::i_isolate(); |
| + HandleScope scope(isolate); |
| + |
| + MacroAssembler assm(isolate, NULL, 0); |
| + |
| + __ aluipc(v0, imm16); |
| + __ jr(ra); |
| + __ nop(); |
| + |
| + CodeDesc desc; |
| + assm.GetCode(&desc); |
| + Handle<Code> code = isolate->factory()->NewCode( |
| + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| + |
| + F2 f = FUNCTION_CAST<F2>(code->entry()); |
| + PC = (uint64_t) f; // Set the program counter. |
| + |
| + uint64_t rs = |
| + reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, imm16, 0, 0, 0, 0)); |
| + |
| + return rs; |
| +} |
| + |
| + |
| +TEST(r6_aluipc) { |
| + if (kArchVariant == kMips64r6) { |
| + CcTest::InitializeVM(); |
| + |
| + struct TestCaseAluipc { |
| + int16_t imm16; |
| + // Expected value of rs register will be calculated later. |
| + // As rs register will be used v0 register. |
| + }; |
| + |
| + struct TestCaseAluipc tc[] = { |
| + // imm16 |
| + { -32768 }, // 0x8000 |
| + { -1 }, // 0xFFFF |
| + { 0 }, |
| + { 1 }, |
| + { 32767 }, // 0x7FFF |
| + }; |
| + |
| + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAluipc); |
| + for (size_t i = 0; i < nr_test_cases; ++i) { |
| + PC = 0; |
| + uint64_t rs = run_aluipc(tc[i].imm16); |
| + // Now, the program_counter (PC) is set. |
| + uint64_t rs_expected = ~0x0FFFF & (PC + (tc[i].imm16 << 16)); |
| + CHECK_EQ(rs_expected, rs); |
| + } |
| + } |
| +} |
| + |
| + |
| +uint64_t run_auipc(int16_t imm16) { |
| + Isolate* isolate = CcTest::i_isolate(); |
| + HandleScope scope(isolate); |
| + |
| + MacroAssembler assm(isolate, NULL, 0); |
| + |
| + __ auipc(v0, imm16); |
| + __ jr(ra); |
| + __ nop(); |
| + |
| + CodeDesc desc; |
| + assm.GetCode(&desc); |
| + Handle<Code> code = isolate->factory()->NewCode( |
| + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| + |
| + F2 f = FUNCTION_CAST<F2>(code->entry()); |
| + PC = (uint64_t) f; // Set the program counter. |
| + |
| + uint64_t rs = |
|
paul.l...
2015/06/15 04:57:50
nit: I'm not comfortable with this use of 'rs' her
ilija.pavlovic
2015/06/15 10:40:11
I agree. "rs" is substituted with "res".
Done.
|
| + reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, imm16, 0, 0, 0, 0)); |
| + |
| + return rs; |
| +} |
| + |
| + |
| +TEST(r6_auipc) { |
| + if (kArchVariant == kMips64r6) { |
| + CcTest::InitializeVM(); |
| + |
| + struct TestCaseAuipc { |
| + int16_t imm16; |
| + // Expected value of rs register will be calculated later. |
| + // As rs register will be used v0 register. |
|
paul.l...
2015/06/15 04:57:50
nit: I also think 'imm16' is not an optimal name f
ilija.pavlovic
2015/06/15 10:40:11
"imm16" is substituted with "offset".
The comment
|
| + }; |
| + |
| + struct TestCaseAuipc tc[] = { |
| + // imm16 |
| + { -32768 }, // 0x8000 |
| + { -1 }, // 0xFFFF |
| + { 0 }, |
| + { 1 }, |
| + { 32767 }, // 0x7FFF |
| + }; |
| + |
| + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAuipc); |
| + for (size_t i = 0; i < nr_test_cases; ++i) { |
| + PC = 0; |
| + uint64_t rs = run_auipc(tc[i].imm16); |
| + // Now, the program_counter (PC) is set. |
| + uint64_t rs_expected = PC + (tc[i].imm16 << 16); |
| + CHECK_EQ(rs_expected, rs); |
| + } |
| + } |
| +} |
| + |
| + |
| +uint64_t run_lwpc(int offset) { |
| + Isolate* isolate = CcTest::i_isolate(); |
| + HandleScope scope(isolate); |
| + |
| + MacroAssembler assm(isolate, NULL, 0); |
| + |
| + // 256k instructions; 2^8k |
| + // addiu t3, a4, 0xffff; (0x250fffff) |
| + // ... |
| + // addiu t0, a4, 0x0000; (0x250c0000) |
| + uint32_t addiu_start_1 = 0x25000000; |
| + for (int32_t i = 0xfffff; i >= 0xc0000; --i) { |
| + uint32_t addiu_new = addiu_start_1 + i; |
| + __ dd(addiu_new); |
| + } |
| + |
| + __ lwpc(t8, offset); // offset 0; 0xef080000 (t8 register) |
| + __ mov(v0, t8); |
| + |
| + // 256k instructions; 2^8k |
| + // addiu a4, a4, 0x0000; (0x25080000) |
| + // ... |
| + // addiu a7, a4, 0xffff; (0x250bffff) |
| + uint32_t addiu_start_2 = 0x25000000; |
| + for (int32_t i = 0x80000; i <= 0xbffff; ++i) { |
| + uint32_t addiu_new = addiu_start_2 + i; |
| + __ dd(addiu_new); |
| + } |
| + |
| + __ jr(ra); |
| + __ nop(); |
| + |
| + CodeDesc desc; |
| + assm.GetCode(&desc); |
| + Handle<Code> code = isolate->factory()->NewCode( |
| + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| + |
| + F2 f = FUNCTION_CAST<F2>(code->entry()); |
| + |
| + uint64_t res = |
| + reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, offset, 0, 0, 0, 0)); |
| + |
| + return res; |
| +} |
| + |
| + |
| +TEST(r6_lwpc) { |
| + if (kArchVariant == kMips64r6) { |
| + CcTest::InitializeVM(); |
| + |
| + struct TestCaseLwpc { |
| + // rs - A word from memory will be stored in t8 register. |
|
paul.l...
2015/06/15 04:57:50
I think this comment no longer applies, and should
ilija.pavlovic
2015/06/15 10:40:11
The comment deleted.
Done.
|
| + int offset; |
| + uint64_t expected_rs; |
|
paul.l...
2015/06/15 04:57:50
nit: I think this should be named expected_res, or
ilija.pavlovic
2015/06/15 10:40:11
"expected_rs" is substituted with "expected_res".
|
| + }; |
| + |
| + struct TestCaseLwpc tc[] = { |
| + // offset, expected_rs |
| + { -262144, 0x250fffff }, // offset 0x40000 |
| + { -4, 0x250c0003 }, |
| + { -1, 0x250c0000 }, |
| + { 0, 0xffffffffef080000 }, |
| + { 1, 0x03001025 }, // mov(v0, t8) |
| + { 2, 0x25080000 }, |
| + { 4, 0x25080002 }, |
| + { 262143, 0x250bfffd }, // offset 0x3ffff |
| + }; |
| + |
| + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLwpc); |
| + for (size_t i = 0; i < nr_test_cases; ++i) { |
| + uint64_t res = run_lwpc(tc[i].offset); |
| + CHECK_EQ(tc[i].expected_rs, res); |
| + } |
| + } |
| +} |
| + |
| + |
| +uint64_t run_lwupc(int rs, int offset) { |
|
paul.l...
2015/06/15 04:57:50
I made an incorrect statement in patchset 3 review
ilija.pavlovic
2015/06/15 10:40:11
Thanks for really detail explanations. You see tha
|
| + Isolate* isolate = CcTest::i_isolate(); |
| + HandleScope scope(isolate); |
| + |
| + MacroAssembler assm(isolate, NULL, 0); |
| + |
| + // 256k instructions; 2^8k |
| + // addiu t3, a4, 0xffff; (0x250fffff) |
| + // ... |
| + // addiu t0, a4, 0x0000; (0x250c0000) |
| + uint32_t addiu_start_1 = 0x25000000; |
| + for (int32_t i = 0xfffff; i >= 0xc0000; --i) { |
| + uint32_t addiu_new = addiu_start_1 + i; |
| + __ dd(addiu_new); |
| + } |
| + |
| + __ lwupc(t8, offset); // offset 0; 0xef080000 (t8 register) |
| + __ mov(v0, t8); |
| + |
| + // 256k instructions; 2^8k |
| + // addiu a4, a4, 0x0000; (0x25080000) |
| + // ... |
| + // addiu a7, a4, 0xffff; (0x250bffff) |
| + uint32_t addiu_start_2 = 0x25000000; |
| + for (int32_t i = 0x80000; i <= 0xbffff; ++i) { |
| + uint32_t addiu_new = addiu_start_2 + i; |
| + __ dd(addiu_new); |
| + } |
| + |
| + __ jr(ra); |
| + __ nop(); |
| + |
| + CodeDesc desc; |
| + assm.GetCode(&desc); |
| + Handle<Code> code = isolate->factory()->NewCode( |
| + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| + |
| + F2 f = FUNCTION_CAST<F2>(code->entry()); |
| + |
| + uint64_t res = |
| + reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, rs, offset, 0, 0, 0)); |
| + |
| + return res; |
| +} |
| + |
| + |
| +TEST(r6_lwupc) { |
| + if (kArchVariant == kMips64r6) { |
| + CcTest::InitializeVM(); |
| + |
| + struct TestCaseLwupc { |
| + int rs; |
| + int offset; |
| + uint64_t expected_rs; |
| + }; |
| + |
| + struct TestCaseLwupc tc[] = { |
| + // rs, offset, expected_rs_value |
| + { t8.code(), -262144, 0x250fffff }, // offset 0x40000 |
| + { t8.code(), -4, 0x250c0003 }, |
|
paul.l...
2015/06/15 04:57:51
As mentioned above, if you're going to pass in a r
ilija.pavlovic
2015/06/15 10:40:11
These entries are deleted.
Done.
|
| + { t8.code(), -1, 0x250c0000 }, |
| + { t8.code(), 0, 0xef100000 }, |
| + { t8.code(), 1, 0x03001025 }, // mov(v0, t8) |
| + { t8.code(), 2, 0x25080000 }, |
| + { t8.code(), 4, 0x25080002 }, |
| + { t8.code(), 262143, 0x250bfffd }, // offset 0x3ffff |
| + }; |
| + |
| + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLwupc); |
| + for (size_t i = 0; i < nr_test_cases; ++i) { |
| + uint64_t res = run_lwupc(tc[i].rs, tc[i].offset); |
| + CHECK_EQ(tc[i].expected_rs, res); |
| + } |
| + } |
| +} |
| + |
| + |
| +uint64_t run_jic(int16_t offset) { |
| + Isolate* isolate = CcTest::i_isolate(); |
| + HandleScope scope(isolate); |
| + |
| + MacroAssembler assm(isolate, NULL, 0); |
| + |
| + Label get_program_counter, stop_execution; |
| + __ push(ra); |
| + __ li(v0, 0); |
| + __ li(t1, 0x66); |
| + |
| + __ addiu(v0, v0, 0x1); // <-- offset = -32 |
| + __ addiu(v0, v0, 0x2); |
| + __ addiu(v0, v0, 0x10); |
| + __ addiu(v0, v0, 0x20); |
| + __ beq(v0, t1, &stop_execution); |
| + __ nop(); |
| + |
| + __ bal(&get_program_counter); // t0 <- program counter |
| + __ nop(); |
| + __ jic(t0, offset); |
| + |
| + __ addiu(v0, v0, 0x100); |
| + __ addiu(v0, v0, 0x200); |
| + __ addiu(v0, v0, 0x1000); |
| + __ addiu(v0, v0, 0x2000); // <--- offset = 16 |
| + __ pop(ra); |
| + __ jr(ra); |
| + __ nop(); |
| + |
| + __ bind(&get_program_counter); |
| + __ mov(t0, ra); |
| + __ jr(ra); |
| + __ nop(); |
| + |
| + __ bind(&stop_execution); |
| + __ pop(ra); |
| + __ jr(ra); |
| + __ nop(); |
| + |
| + CodeDesc desc; |
| + assm.GetCode(&desc); |
| + Handle<Code> code = isolate->factory()->NewCode( |
| + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| + |
| + F2 f = FUNCTION_CAST<F2>(code->entry()); |
| + |
| + uint64_t res = |
| + reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, offset, 0, 0, 0, 0)); |
|
paul.l...
2015/06/15 04:57:50
As above: the value of offset is used at generatio
ilija.pavlovic
2015/06/15 10:40:11
"offset" removed from "CALL_GENERATED_CODE".
Done
|
| + |
| + return res; |
| +} |
| + |
| + |
| +TEST(r6_jic) { |
| + if (kArchVariant == kMips64r6) { |
| + CcTest::InitializeVM(); |
| + |
| + struct TestCaseJic { |
| + // As rt will be used t0 register which will have value of |
| + // the program counter for the jic instruction. |
|
paul.l...
2015/06/15 04:57:50
nit: this comment is not needed. The code above is
ilija.pavlovic
2015/06/15 10:40:11
The comment deleted.
Done.
|
| + int16_t offset; |
| + uint32_t expected_res; |
| + }; |
| + |
| + struct TestCaseJic tc[] = { |
| + // offset, expected_result |
| + { 16, 0x2033 }, |
| + { 4, 0x3333 }, |
| + { -32, 0x66 }, |
| + }; |
| + |
| + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseJic); |
| + for (size_t i = 0; i < nr_test_cases; ++i) { |
| + uint32_t res = run_jic(tc[i].offset); |
| + CHECK_EQ(tc[i].expected_res, res); |
| + } |
| + } |
| +} |
| + |
| + |
| +uint64_t run_beqzc(int32_t rs, int32_t offset) { |
|
paul.l...
2015/06/15 04:57:50
The first parameter here is used as a 'value' that
ilija.pavlovic
2015/06/15 10:40:11
"rs" renamed into "value".
Done.
|
| + Isolate* isolate = CcTest::i_isolate(); |
| + HandleScope scope(isolate); |
| + |
| + MacroAssembler assm(isolate, NULL, 0); |
| + |
| + Label stop_execution; |
| + __ li(v0, 0); |
| + __ li(t1, 0x66); |
| + |
| + __ addiu(v0, v0, 0x1); // <-- offset = -8 |
| + __ addiu(v0, v0, 0x2); |
| + __ addiu(v0, v0, 0x10); |
| + __ addiu(v0, v0, 0x20); |
| + __ beq(v0, t1, &stop_execution); |
| + __ nop(); |
| + |
| + __ beqzc(a0, offset); |
| + |
| + __ addiu(v0, v0, 0x1); |
| + __ addiu(v0, v0, 0x100); |
| + __ addiu(v0, v0, 0x200); |
| + __ addiu(v0, v0, 0x1000); |
| + __ addiu(v0, v0, 0x2000); // <--- offset = 4 |
| + __ jr(ra); |
| + __ nop(); |
| + |
| + __ bind(&stop_execution); |
| + __ jr(ra); |
| + __ nop(); |
| + |
| + CodeDesc desc; |
| + assm.GetCode(&desc); |
| + Handle<Code> code = isolate->factory()->NewCode( |
| + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| + |
| + F2 f = FUNCTION_CAST<F2>(code->entry()); |
| + |
| + uint64_t res = |
| + reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, rs, offset, 0, 0, 0)); |
|
paul.l...
2015/06/15 04:57:50
You are passing in a 'value' as first param, pleas
ilija.pavlovic
2015/06/15 10:40:11
"rs" renamed as "value" and "offset" is substitute
|
| + |
| + return res; |
| +} |
| + |
| + |
| +TEST(r6_beqzc) { |
| + if (kArchVariant == kMips64r6) { |
| + CcTest::InitializeVM(); |
| + |
| + struct TestCaseBeqzc { |
| + uint32_t rs_value; |
| + int32_t offset; |
| + uint32_t expected_res; |
| + }; |
| + |
| + struct TestCaseBeqzc tc[] = { |
| + // rs_value, offset, expected_res |
|
paul.l...
2015/06/15 04:57:51
I suggest you just call this value - since you hav
ilija.pavlovic
2015/06/15 10:40:11
"rs_value" renamed into "value".
Done.
|
| + { 0x0, -8, 0x66 }, |
| + { 0x0, 0, 0x3334 }, |
| + { 0x0, 1, 0x3333 }, |
| + { 0xabc, 1, 0x3334 }, |
| + { 0x0, 4, 0x2033 }, |
| + }; |
| + |
| + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBeqzc); |
| + for (size_t i = 0; i < nr_test_cases; ++i) { |
| + uint32_t res = run_beqzc(tc[i].rs_value, tc[i].offset); |
| + CHECK_EQ(tc[i].expected_res, res); |
| + } |
| + } |
| +} |
| + |
| + |
| +uint64_t run_jialc(int16_t offset) { |
| + Isolate* isolate = CcTest::i_isolate(); |
| + HandleScope scope(isolate); |
| + |
| + MacroAssembler assm(isolate, NULL, 0); |
| + |
| + Label main_block, get_program_counter; |
| + __ push(ra); |
| + __ li(v0, 0); |
| + __ beq(v0, v0, &main_block); |
| + __ nop(); |
| + |
| + // Block 1 |
| + __ addiu(v0, v0, 0x1); // <-- offset = -40 |
| + __ addiu(v0, v0, 0x2); |
| + __ jr(ra); |
| + __ nop(); |
| + |
| + // Block 2 |
| + __ addiu(v0, v0, 0x10); // <-- offset = -24 |
| + __ addiu(v0, v0, 0x20); |
| + __ jr(ra); |
| + __ nop(); |
| + |
| + // Block 3 (Main) |
| + __ bind(&main_block); |
| + __ bal(&get_program_counter); // t0 <- program counter |
| + __ nop(); |
| + __ jialc(t0, offset); |
| + __ addiu(v0, v0, 0x4); |
| + __ pop(ra); |
| + __ jr(ra); |
| + __ nop(); |
| + |
| + // Block 4 |
| + __ addiu(v0, v0, 0x100); // <-- offset = 20 |
| + __ addiu(v0, v0, 0x200); |
| + __ jr(ra); |
| + __ nop(); |
| + |
| + // Block 5 |
| + __ addiu(v0, v0, 0x1000); // <--- offset = 36 |
| + __ addiu(v0, v0, 0x2000); |
| + __ jr(ra); |
| + __ nop(); |
| + |
| + __ bind(&get_program_counter); |
| + __ mov(t0, ra); |
| + __ jr(ra); |
| + __ nop(); |
| + |
| + |
| + CodeDesc desc; |
| + assm.GetCode(&desc); |
| + Handle<Code> code = isolate->factory()->NewCode( |
| + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| + |
| + F2 f = FUNCTION_CAST<F2>(code->entry()); |
| + |
| + uint64_t res = |
| + reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, offset, 0, 0, 0, 0)); |
| + |
| + return res; |
| +} |
| + |
| + |
| +TEST(r6_jialc) { |
| + if (kArchVariant == kMips64r6) { |
| + CcTest::InitializeVM(); |
| + |
| + struct TestCaseJialc { |
| + // As rt will be used t0 register which will have value of |
| + // the program counter for the jialc instruction. |
| + int16_t offset; |
| + uint32_t expected_res; |
| + }; |
| + |
| + struct TestCaseJialc tc[] = { |
| + // offset, expected_res |
| + { -40, 0x7 }, |
| + { -24, 0x34 }, |
| + { 20, 0x304 }, |
| + { 36, 0x3004 } |
| + }; |
| + |
| + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseJialc); |
| + for (size_t i = 0; i < nr_test_cases; ++i) { |
| + uint32_t res = run_jialc(tc[i].offset); |
| + CHECK_EQ(tc[i].expected_res, res); |
| + } |
| + } |
| +} |
| + |
| + |
| +uint64_t run_addiupc(int32_t imm19) { |
| + Isolate* isolate = CcTest::i_isolate(); |
| + HandleScope scope(isolate); |
| + |
| + MacroAssembler assm(isolate, NULL, 0); |
| + |
| + __ addiupc(v0, imm19); |
| + __ jr(ra); |
| + __ nop(); |
| + |
| + CodeDesc desc; |
| + assm.GetCode(&desc); |
| + Handle<Code> code = isolate->factory()->NewCode( |
| + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| + |
| + F2 f = FUNCTION_CAST<F2>(code->entry()); |
| + PC = (uint64_t) f; // Set the program counter. |
| + |
| + uint64_t rs = |
| + reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, imm19, 0, 0, 0, 0)); |
| + |
| + return rs; |
| +} |
| + |
| + |
| +TEST(r6_addiupc) { |
| + if (kArchVariant == kMips64r6) { |
| + CcTest::InitializeVM(); |
| + |
| + struct TestCaseAddiupc { |
| + int32_t imm19; |
| + // Expected value of the rs register will be calculated later. |
| + // As rs register will be used v0 register. |
|
paul.l...
2015/06/15 04:57:50
nit: please delete this comment. I'm not sure what
ilija.pavlovic
2015/06/15 10:40:11
The comment deleted. Also, "rs" renamed into "res"
|
| + }; |
| + |
| + struct TestCaseAddiupc tc[] = { |
| + // imm19 |
| + { -262144 }, // 0x40000 |
| + { -1 }, // 0x7FFFF |
| + { 0 }, |
| + { 1 }, // 0x00001 |
| + { 262143 } // 0x3FFFF |
| + }; |
| + |
| + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAddiupc); |
| + for (size_t i = 0; i < nr_test_cases; ++i) { |
| + PC = 0; |
| + uint64_t rs = run_addiupc(tc[i].imm19); |
| + // Now, the program_counter (PC) is set. |
| + uint64_t rs_expected = PC + (tc[i].imm19 << 2); |
| + CHECK_EQ(rs_expected, rs); |
| + } |
| + } |
| +} |
| + |
| + |
| +uint64_t run_ldpc(int rs, int offset) { |
| + Isolate* isolate = CcTest::i_isolate(); |
| + HandleScope scope(isolate); |
| + |
| + MacroAssembler assm(isolate, NULL, 0); |
| + |
| + // 256k instructions; 2 * 2^7k = 2^8k |
| + // addiu t3, a4, 0xffff; (0x250fffff) |
| + // ... |
| + // addiu t0, a4, 0x0000; (0x250c0000) |
| + uint32_t addiu_start_1 = 0x25000000; |
| + for (int32_t i = 0xfffff; i >= 0xc0000; --i) { |
| + uint32_t addiu_new = addiu_start_1 + i; |
| + __ dd(addiu_new); |
| + } |
| + |
| + __ ldpc(t8, offset); // offset 0; 0xef080000 (t8 register) |
| + __ mov(v0, t8); |
|
paul.l...
2015/06/15 04:57:50
As above: If you are passing in rs, I suggest you
ilija.pavlovic
2015/06/15 10:40:11
"rs" removed from the parameter list.
Done.
|
| + |
| + // 256k instructions; 2 * 2^7k = 2^8k |
| + // addiu a4, a4, 0x0000; (0x25080000) |
| + // ... |
| + // addiu a7, a4, 0xffff; (0x250bffff) |
| + uint32_t addiu_start_2 = 0x25000000; |
| + for (int32_t i = 0x80000; i <= 0xbffff; ++i) { |
| + uint32_t addiu_new = addiu_start_2 + i; |
| + __ dd(addiu_new); |
| + } |
| + |
| + __ jr(ra); |
| + __ nop(); |
| + |
| + CodeDesc desc; |
| + assm.GetCode(&desc); |
| + Handle<Code> code = isolate->factory()->NewCode( |
| + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| + |
| + F2 f = FUNCTION_CAST<F2>(code->entry()); |
| + |
| + uint64_t res = |
| + reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, rs, offset, 0, 0, 0)); |
|
paul.l...
2015/06/15 04:57:50
As above, you cannot use rs or offset at runtime,
ilija.pavlovic
2015/06/15 10:40:11
"rs" and "offset" are substituted with "0".
Done.
|
| + |
| + return res; |
| +} |
| + |
| + |
| +TEST(r6_ldpc) { |
| + if (kArchVariant == kMips64r6) { |
| + CcTest::InitializeVM(); |
| + |
| + struct TestCaseLdpc { |
| + int rs; |
| + int offset; |
| + uint64_t expected_rs; |
| + }; |
| + |
| + struct TestCaseLdpc tc[] = { |
| + // rs, offset, expected_rs_value |
| + { t8.code(), -131072, 0x250ffffe250fffff }, |
| + { t8.code(), -4, 0x250c0006250c0007 }, |
| + { t8.code(), -1, 0x250c0000250c0001 }, |
| + { t8.code(), 0, 0x03001025ef180000 }, |
| + { t8.code(), 1, 0x2508000125080000 }, |
| + { t8.code(), 4, 0x2508000725080006 }, |
| + { t8.code(), 131071, 0x250bfffd250bfffc }, |
| + }; |
| + |
| + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLdpc); |
| + for (size_t i = 0; i < nr_test_cases; ++i) { |
| + uint64_t res = run_ldpc(tc[i].rs, tc[i].offset); |
| + CHECK_EQ(tc[i].expected_rs, res); |
| + } |
| + } |
| +} |
| + |
| + |
| +int64_t run_bc(int32_t offset) { |
| + Isolate* isolate = CcTest::i_isolate(); |
| + HandleScope scope(isolate); |
| + |
| + MacroAssembler assm(isolate, NULL, 0); |
| + |
| + Label continue_1, stop_execution; |
| + __ push(ra); |
| + __ li(v0, 0); |
| + __ li(t8, 0); |
| + __ li(t9, 2); // Condition for the stopping execution. |
| + |
| + uint32_t instruction_addiu = 0x24420001; // addiu v0, v0, 1 |
| + for (int32_t i = -100; i <= -11; ++i) { |
| + __ dd(instruction_addiu); |
| + } |
| + |
| + __ addiu(t8, t8, 1); // -10 |
| + |
| + __ beq(t8, t9, &stop_execution); // -9 |
| + __ nop(); // -8 |
| + __ beq(t8, t8, &continue_1); // -7 |
| + __ nop(); // -6 |
| + |
| + __ bind(&stop_execution); |
| + __ pop(ra); // -5, -4 |
| + __ jr(ra); // -3 |
| + __ nop(); // -2 |
| + |
| + __ bind(&continue_1); |
| + __ bc(offset); // -1 |
| + |
| + for (int32_t i = 0; i <= 99; ++i) { |
| + __ dd(instruction_addiu); |
| + } |
| + |
| + __ pop(ra); |
| + __ jr(ra); |
| + __ nop(); |
| + |
| + CodeDesc desc; |
| + assm.GetCode(&desc); |
| + Handle<Code> code = isolate->factory()->NewCode( |
| + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| + |
| + F2 f = FUNCTION_CAST<F2>(code->entry()); |
| + |
| + int64_t res = |
| + reinterpret_cast<int64_t>(CALL_GENERATED_CODE(f, offset, 0, 0, 0, 0)); |
| + |
| + return res; |
| +} |
| + |
| + |
| +TEST(r6_bc) { |
| + if (kArchVariant == kMips64r6) { |
| + CcTest::InitializeVM(); |
| + |
| + struct TestCaseBc { |
| + int32_t offset; |
| + int64_t expected_res; |
| + }; |
| + |
| + struct TestCaseBc tc[] = { |
| + // offset, expected_result |
| + { -100, (abs(-100) - 10) * 2 }, |
| + { -11, (abs(-100) - 10 + 1) }, |
| + { 0, (abs(-100) - 10 + 1 + 99) }, |
|
paul.l...
2015/06/15 04:57:51
nit; weird brace alignment, if you can line them u
ilija.pavlovic
2015/06/15 10:40:11
Corrected.
Done.
|
| + { 1, (abs(-100) - 10 + 99) }, |
| + { 99, (abs(-100) - 10 + 1) }, |
| + }; |
| + |
| + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBc); |
| + for (size_t i = 0; i < nr_test_cases; ++i) { |
| + int64_t res = run_bc(tc[i].offset); |
| + CHECK_EQ(tc[i].expected_res, res); |
| + } |
| + } |
| +} |
| + |
| + |
| +int64_t run_balc(int32_t offset) { |
| + Isolate* isolate = CcTest::i_isolate(); |
| + HandleScope scope(isolate); |
| + |
| + MacroAssembler assm(isolate, NULL, 0); |
| + |
| + Label continue_1, stop_execution; |
| + __ push(ra); |
| + __ li(v0, 0); |
| + __ li(t8, 0); |
| + __ li(t9, 2); // Condition for stopping execution. |
| + |
| + __ beq(t8, t8, &continue_1); |
| + __ nop(); |
| + |
| + uint32_t instruction_addiu = 0x24420001; // addiu v0, v0, 1 |
| + for (int32_t i = -117; i <= -57; ++i) { |
| + __ dd(instruction_addiu); |
| + } |
| + __ jr(ra); // -56 |
| + __ nop(); // -55 |
| + |
| + for (int32_t i = -54; i <= -4; ++i) { |
| + __ dd(instruction_addiu); |
| + } |
| + __ jr(ra); // -3 |
| + __ nop(); // -2 |
| + |
| + __ bind(&continue_1); |
| + __ balc(offset); // -1 |
| + |
| + __ pop(ra); // 0, 1 |
| + __ jr(ra); // 2 |
| + __ nop(); // 3 |
| + |
| + for (int32_t i = 4; i <= 44; ++i) { |
| + __ dd(instruction_addiu); |
| + } |
| + __ jr(ra); |
| + __ nop(); |
| + |
| + CodeDesc desc; |
| + assm.GetCode(&desc); |
| + Handle<Code> code = isolate->factory()->NewCode( |
| + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| + |
| + F2 f = FUNCTION_CAST<F2>(code->entry()); |
| + |
| + int64_t res = |
| + reinterpret_cast<int64_t>(CALL_GENERATED_CODE(f, offset, 0, 0, 0, 0)); |
| + |
| + return res; |
| +} |
| + |
| + |
| +TEST(r6_balc) { |
| + if (kArchVariant == kMips64r6) { |
| + CcTest::InitializeVM(); |
| + |
| + struct TestCaseBalc { |
| + int32_t offset; |
| + int64_t expected_res; |
| + }; |
| + |
| + struct TestCaseBalc tc[] = { |
| + // offset, expected_result |
| + { -117, 61 }, |
| + { -54, 51 }, |
| + { 0, 0 }, |
| + { 4, 41 }, |
| + }; |
| + |
| + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBalc); |
| + for (size_t i = 0; i < nr_test_cases; ++i) { |
| + int64_t res = run_balc(tc[i].offset); |
| + CHECK_EQ(tc[i].expected_res, res); |
| + } |
| + } |
| +} |
| + |
| + |
| #undef __ |