Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Unified Diff: test/cctest/test-assembler-mips64.cc

Issue 1144373003: MIPS: Implemented PC-relative instructions for R6. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Corrections according review comments. Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « test/cctest/test-assembler-mips.cc ('k') | test/cctest/test-disasm-mips.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 __
« no previous file with comments | « test/cctest/test-assembler-mips.cc ('k') | test/cctest/test-disasm-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698