| Index: test/cctest/test-assembler-mips64.cc
 | 
| diff --git a/test/cctest/test-assembler-mips64.cc b/test/cctest/test-assembler-mips64.cc
 | 
| index 0494a755c972085db7eac867e5ccb199ef0e875b..f2d57e280e9168b15bc4075a039a680c8c779a90 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
 | 
|  
 | 
| @@ -4448,4 +4449,918 @@ TEST(DIV_FMT) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| +uint64_t run_align(uint64_t rs_value, uint64_t rt_value, uint8_t bp) {
 | 
| +  Isolate* isolate = CcTest::i_isolate();
 | 
| +  HandleScope scope(isolate);
 | 
| +
 | 
| +  MacroAssembler assm(isolate, NULL, 0);
 | 
| +
 | 
| +  __ 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 res =
 | 
| +      reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, rs_value,
 | 
| +                                                        rt_value,
 | 
| +                                                        0, 0, 0));
 | 
| +
 | 
| +  return res;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +TEST(r6_align) {
 | 
| +  if (kArchVariant == kMips64r6) {
 | 
| +    CcTest::InitializeVM();
 | 
| +
 | 
| +    struct TestCaseAlign {
 | 
| +      uint64_t  rs_value;
 | 
| +      uint64_t  rt_value;
 | 
| +      uint8_t   bp;
 | 
| +      uint64_t  expected_res;
 | 
| +    };
 | 
| +
 | 
| +    struct TestCaseAlign tc[] = {
 | 
| +      // rs_value,    rt_value,    bp, expected_res
 | 
| +      {  0x11223344,  0xaabbccdd,   0, 0xffffffffaabbccdd },
 | 
| +      {  0x11223344,  0xaabbccdd,   1, 0xffffffffbbccdd11 },
 | 
| +      {  0x11223344,  0xaabbccdd,   2, 0xffffffffccdd1122 },
 | 
| +      {  0x11223344,  0xaabbccdd,   3, 0xffffffffdd112233 },
 | 
| +    };
 | 
| +
 | 
| +    size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAlign);
 | 
| +    for (size_t i = 0; i < nr_test_cases; ++i) {
 | 
| +      CHECK_EQ(tc[i].expected_res, run_align(tc[i].rs_value,
 | 
| +                                              tc[i].rt_value,
 | 
| +                                              tc[i].bp));
 | 
| +    }
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +uint64_t run_dalign(uint64_t rs_value, uint64_t rt_value, uint8_t bp) {
 | 
| +  Isolate* isolate = CcTest::i_isolate();
 | 
| +  HandleScope scope(isolate);
 | 
| +
 | 
| +  MacroAssembler assm(isolate, NULL, 0);
 | 
| +
 | 
| +  __ 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 res =
 | 
| +      reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, rs_value,
 | 
| +                                                        rt_value,
 | 
| +                                                        0, 0, 0));
 | 
| +
 | 
| +  return res;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +TEST(r6_dalign) {
 | 
| +  if (kArchVariant == kMips64r6) {
 | 
| +    CcTest::InitializeVM();
 | 
| +
 | 
| +    struct TestCaseDalign {
 | 
| +      uint64_t  rs_value;
 | 
| +      uint64_t  rt_value;
 | 
| +      uint8_t   bp;
 | 
| +      uint64_t  expected_res;
 | 
| +    };
 | 
| +
 | 
| +    struct TestCaseDalign tc[] = {
 | 
| +      // rs_value,           rt_value,            bp, expected_res
 | 
| +      { 0x1122334455667700,  0xaabbccddeeff8899,   0, 0xaabbccddeeff8899 },
 | 
| +      { 0x1122334455667700,  0xaabbccddeeff8899,   1, 0xbbccddeeff889911 },
 | 
| +      { 0x1122334455667700,  0xaabbccddeeff8899,   2, 0xccddeeff88991122 },
 | 
| +      { 0x1122334455667700,  0xaabbccddeeff8899,   3, 0xddeeff8899112233 },
 | 
| +      { 0x1122334455667700,  0xaabbccddeeff8899,   4, 0xeeff889911223344 },
 | 
| +      { 0x1122334455667700,  0xaabbccddeeff8899,   5, 0xff88991122334455 },
 | 
| +      { 0x1122334455667700,  0xaabbccddeeff8899,   6, 0x8899112233445566 },
 | 
| +      { 0x1122334455667700,  0xaabbccddeeff8899,   7, 0x9911223344556677 }
 | 
| +    };
 | 
| +
 | 
| +    size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseDalign);
 | 
| +    for (size_t i = 0; i < nr_test_cases; ++i) {
 | 
| +      CHECK_EQ(tc[i].expected_res, run_dalign(tc[i].rs_value,
 | 
| +                                              tc[i].rt_value,
 | 
| +                                              tc[i].bp));
 | 
| +    }
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +uint64_t PC;  // The program counter.
 | 
| +
 | 
| +uint64_t run_aluipc(int16_t offset) {
 | 
| +  Isolate* isolate = CcTest::i_isolate();
 | 
| +  HandleScope scope(isolate);
 | 
| +
 | 
| +  MacroAssembler assm(isolate, NULL, 0);
 | 
| +
 | 
| +  __ aluipc(v0, offset);
 | 
| +  __ 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 res =
 | 
| +      reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
 | 
| +
 | 
| +  return res;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +TEST(r6_aluipc) {
 | 
| +  if (kArchVariant == kMips64r6) {
 | 
| +    CcTest::InitializeVM();
 | 
| +
 | 
| +    struct TestCaseAluipc {
 | 
| +      int16_t   offset;
 | 
| +    };
 | 
| +
 | 
| +    struct TestCaseAluipc tc[] = {
 | 
| +      // offset
 | 
| +      { -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 res = run_aluipc(tc[i].offset);
 | 
| +      // Now, the program_counter (PC) is set.
 | 
| +      uint64_t expected_res = ~0x0FFFF & (PC + (tc[i].offset << 16));
 | 
| +      CHECK_EQ(expected_res, res);
 | 
| +    }
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +uint64_t run_auipc(int16_t offset) {
 | 
| +  Isolate* isolate = CcTest::i_isolate();
 | 
| +  HandleScope scope(isolate);
 | 
| +
 | 
| +  MacroAssembler assm(isolate, NULL, 0);
 | 
| +
 | 
| +  __ auipc(v0, offset);
 | 
| +  __ 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 res =
 | 
| +      reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
 | 
| +
 | 
| +  return res;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +TEST(r6_auipc) {
 | 
| +  if (kArchVariant == kMips64r6) {
 | 
| +    CcTest::InitializeVM();
 | 
| +
 | 
| +    struct TestCaseAuipc {
 | 
| +      int16_t   offset;
 | 
| +    };
 | 
| +
 | 
| +    struct TestCaseAuipc tc[] = {
 | 
| +      // offset
 | 
| +      { -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 res = run_auipc(tc[i].offset);
 | 
| +      // Now, the program_counter (PC) is set.
 | 
| +      uint64_t expected_res = PC + (tc[i].offset << 16);
 | 
| +      CHECK_EQ(expected_res, res);
 | 
| +    }
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +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, 0, 0, 0, 0, 0));
 | 
| +
 | 
| +  return res;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +TEST(r6_lwpc) {
 | 
| +  if (kArchVariant == kMips64r6) {
 | 
| +    CcTest::InitializeVM();
 | 
| +
 | 
| +    struct TestCaseLwpc {
 | 
| +      int       offset;
 | 
| +      uint64_t  expected_res;
 | 
| +    };
 | 
| +
 | 
| +    struct TestCaseLwpc tc[] = {
 | 
| +      // offset,   expected_res
 | 
| +      { -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_res, res);
 | 
| +    }
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +uint64_t run_lwupc(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);
 | 
| +  }
 | 
| +
 | 
| +  __ 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, 0, 0, 0, 0, 0));
 | 
| +
 | 
| +  return res;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +TEST(r6_lwupc) {
 | 
| +  if (kArchVariant == kMips64r6) {
 | 
| +    CcTest::InitializeVM();
 | 
| +
 | 
| +    struct TestCaseLwupc {
 | 
| +      int       offset;
 | 
| +      uint64_t  expected_res;
 | 
| +    };
 | 
| +
 | 
| +    struct TestCaseLwupc tc[] = {
 | 
| +      // offset,    expected_res
 | 
| +      { -262144,    0x250fffff },   // offset 0x40000
 | 
| +      {      -4,    0x250c0003 },
 | 
| +      {      -1,    0x250c0000 },
 | 
| +      {       0,    0xef100000 },
 | 
| +      {       1,    0x03001025 },   // mov(v0, t8)
 | 
| +      {       2,    0x25080000 },
 | 
| +      {       4,    0x25080002 },
 | 
| +      {  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].offset);
 | 
| +      CHECK_EQ(tc[i].expected_res, 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, 0, 0, 0, 0, 0));
 | 
| +
 | 
| +  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.
 | 
| +      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) {
 | 
| +      uint64_t res = run_jic(tc[i].offset);
 | 
| +      CHECK_EQ(tc[i].expected_res, res);
 | 
| +    }
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +uint64_t run_beqzc(int32_t value, int32_t offset) {
 | 
| +  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, value, 0, 0, 0, 0));
 | 
| +
 | 
| +  return res;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +TEST(r6_beqzc) {
 | 
| +  if (kArchVariant == kMips64r6) {
 | 
| +    CcTest::InitializeVM();
 | 
| +
 | 
| +    struct TestCaseBeqzc {
 | 
| +      uint32_t  value;
 | 
| +      int32_t   offset;
 | 
| +      uint32_t  expected_res;
 | 
| +    };
 | 
| +
 | 
| +    struct TestCaseBeqzc tc[] = {
 | 
| +      //    value,    offset,   expected_res
 | 
| +      {       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) {
 | 
| +      uint64_t res = run_beqzc(tc[i].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, 0, 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) {
 | 
| +      uint64_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 res =
 | 
| +      reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
 | 
| +
 | 
| +  return res;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +TEST(r6_addiupc) {
 | 
| +  if (kArchVariant == kMips64r6) {
 | 
| +    CcTest::InitializeVM();
 | 
| +
 | 
| +    struct TestCaseAddiupc {
 | 
| +      int32_t   imm19;
 | 
| +    };
 | 
| +
 | 
| +    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 res = run_addiupc(tc[i].imm19);
 | 
| +      // Now, the program_counter (PC) is set.
 | 
| +      uint64_t expected_res = PC + (tc[i].imm19 << 2);
 | 
| +      CHECK_EQ(expected_res, res);
 | 
| +    }
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +uint64_t run_ldpc(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);
 | 
| +
 | 
| +  // 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, 0, 0, 0, 0, 0));
 | 
| +
 | 
| +  return res;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +TEST(r6_ldpc) {
 | 
| +  if (kArchVariant == kMips64r6) {
 | 
| +    CcTest::InitializeVM();
 | 
| +
 | 
| +    struct TestCaseLdpc {
 | 
| +      int       offset;
 | 
| +      uint64_t  expected_res;
 | 
| +    };
 | 
| +
 | 
| +    struct TestCaseLdpc tc[] = {
 | 
| +      // offset,         expected_res
 | 
| +      { -131072,         0x250ffffe250fffff },
 | 
| +      {      -4,         0x250c0006250c0007 },
 | 
| +      {      -1,         0x250c0000250c0001 },
 | 
| +      {       0,         0x03001025ef180000 },
 | 
| +      {       1,         0x2508000125080000 },
 | 
| +      {       4,         0x2508000725080006 },
 | 
| +      {  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].offset);
 | 
| +      CHECK_EQ(tc[i].expected_res, 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, 0, 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) },
 | 
| +      {          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, 0, 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 __
 | 
| 
 |