blob: b59601720f521042d49f8795eb796fbc6e406098 [file] [log] [blame]
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h"
#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
#include "vm/compiler/assembler/assembler.h"
#include "vm/cpu.h"
#include "vm/os.h"
#include "vm/unit_test.h"
#include "vm/virtual_memory.h"
namespace dart {
namespace compiler {
#define __ assembler->
#if defined(PRODUCT)
#define EXPECT_DISASSEMBLY(expected)
#else
#define EXPECT_DISASSEMBLY(expected) \
EXPECT_STREQ(expected, test->RelativeDisassembly())
#endif
// Called from assembler_test.cc.
// RA: return address.
// A0: value.
// A1: growable array.
// A2: current thread.
ASSEMBLER_TEST_GENERATE(StoreIntoObject, assembler) {
__ PushRegister(RA);
__ PushNativeCalleeSavedRegisters();
__ mv(THR, A2);
__ lx(WRITE_BARRIER_MASK, Address(THR, Thread::write_barrier_mask_offset()));
__ StoreIntoObject(A1, FieldAddress(A1, GrowableObjectArray::data_offset()),
A0);
__ PopNativeCalleeSavedRegisters();
__ PopRegister(RA);
__ ret();
}
static intx_t Call(intx_t entry,
intx_t arg0 = 0,
intx_t arg1 = 0,
intx_t arg2 = 0,
intx_t arg3 = 0) {
#if defined(USING_SIMULATOR)
return Simulator::Current()->Call(entry, arg0, arg1, arg2, arg3);
#else
typedef intx_t (*F)(intx_t, intx_t, intx_t, intx_t);
return reinterpret_cast<F>(entry)(arg0, arg1, arg2, arg3);
#endif
}
static float CallF(intx_t entry, intx_t arg0) {
#if defined(USING_SIMULATOR)
return Simulator::Current()->CallF(entry, arg0);
#else
typedef float (*F)(intx_t);
return reinterpret_cast<F>(entry)(arg0);
#endif
}
static float CallF(intx_t entry, intx_t arg0, float arg1) {
#if defined(USING_SIMULATOR)
return Simulator::Current()->CallF(entry, arg0, arg1);
#else
typedef float (*F)(intx_t, float);
return reinterpret_cast<F>(entry)(arg0, arg1);
#endif
}
static float CallF(intx_t entry, double arg0) {
#if defined(USING_SIMULATOR)
return Simulator::Current()->CallF(entry, arg0);
#else
typedef float (*F)(double);
return reinterpret_cast<F>(entry)(arg0);
#endif
}
static float CallF(intx_t entry, float arg0) {
#if defined(USING_SIMULATOR)
return Simulator::Current()->CallF(entry, arg0);
#else
typedef float (*F)(float);
return reinterpret_cast<F>(entry)(arg0);
#endif
}
static float CallF(intx_t entry, float arg0, float arg1) {
#if defined(USING_SIMULATOR)
return Simulator::Current()->CallF(entry, arg0, arg1);
#else
typedef float (*F)(float, float);
return reinterpret_cast<F>(entry)(arg0, arg1);
#endif
}
static float CallF(intx_t entry, float arg0, float arg1, float arg2) {
#if defined(USING_SIMULATOR)
return Simulator::Current()->CallF(entry, arg0, arg1, arg2);
#else
typedef float (*F)(float, float, float);
return reinterpret_cast<F>(entry)(arg0, arg1, arg2);
#endif
}
static intx_t CallI(intx_t entry, float arg0) {
#if defined(USING_SIMULATOR)
return Simulator::Current()->CallI(entry, arg0);
#else
typedef intx_t (*F)(float);
return reinterpret_cast<F>(entry)(arg0);
#endif
}
static intx_t CallI(intx_t entry, float arg0, float arg1) {
#if defined(USING_SIMULATOR)
return Simulator::Current()->CallI(entry, arg0, arg1);
#else
typedef intx_t (*F)(float, float);
return reinterpret_cast<F>(entry)(arg0, arg1);
#endif
}
static double CallD(intx_t entry, intx_t arg0) {
#if defined(USING_SIMULATOR)
return Simulator::Current()->CallD(entry, arg0);
#else
typedef double (*F)(intx_t);
return reinterpret_cast<F>(entry)(arg0);
#endif
}
static double CallD(intx_t entry, intx_t arg0, double arg1) {
#if defined(USING_SIMULATOR)
return Simulator::Current()->CallD(entry, arg0, arg1);
#else
typedef double (*F)(intx_t, double);
return reinterpret_cast<F>(entry)(arg0, arg1);
#endif
}
static double CallD(intx_t entry, float arg0) {
#if defined(USING_SIMULATOR)
return Simulator::Current()->CallD(entry, arg0);
#else
typedef double (*F)(float);
return reinterpret_cast<F>(entry)(arg0);
#endif
}
static double CallD(intx_t entry, double arg0) {
#if defined(USING_SIMULATOR)
return Simulator::Current()->CallD(entry, arg0);
#else
typedef double (*F)(double);
return reinterpret_cast<F>(entry)(arg0);
#endif
}
static double CallD(intx_t entry, double arg0, double arg1) {
#if defined(USING_SIMULATOR)
return Simulator::Current()->CallD(entry, arg0, arg1);
#else
typedef double (*F)(double, double);
return reinterpret_cast<F>(entry)(arg0, arg1);
#endif
}
static double CallD(intx_t entry, double arg0, double arg1, double arg2) {
#if defined(USING_SIMULATOR)
return Simulator::Current()->CallD(entry, arg0, arg1, arg2);
#else
typedef double (*F)(double, double, double);
return reinterpret_cast<F>(entry)(arg0, arg1, arg2);
#endif
}
static intx_t CallI(intx_t entry, double arg0) {
#if defined(USING_SIMULATOR)
return Simulator::Current()->CallI(entry, arg0);
#else
typedef intx_t (*F)(double);
return reinterpret_cast<F>(entry)(arg0);
#endif
}
static intx_t CallI(intx_t entry, double arg0, double arg1) {
#if defined(USING_SIMULATOR)
return Simulator::Current()->CallI(entry, arg0, arg1);
#else
typedef intx_t (*F)(double, double);
return reinterpret_cast<F>(entry)(arg0, arg1);
#endif
}
ASSEMBLER_TEST_GENERATE(LoadUpperImmediate, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ lui(A0, 42 << 16);
__ ret();
}
ASSEMBLER_TEST_RUN(LoadUpperImmediate, test) {
EXPECT_DISASSEMBLY(
"002a0537 lui a0, 2752512\n"
"00008067 ret\n");
EXPECT_EQ(42 << 16, Call(test->entry()));
}
ASSEMBLER_TEST_GENERATE(AddUpperImmediatePC, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ auipc(A0, 0);
__ ret();
}
ASSEMBLER_TEST_RUN(AddUpperImmediatePC, test) {
EXPECT_DISASSEMBLY(
"00000517 auipc a0, 0\n"
"00008067 ret\n");
EXPECT_EQ(test->entry(), static_cast<uintx_t>(Call(test->entry())));
}
ASSEMBLER_TEST_GENERATE(JumpAndLink, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
Label label1, label2;
__ jal(T4, &label1); // Forward.
__ sub(A0, T0, T1);
__ ret();
__ trap();
__ Bind(&label2);
__ li(T1, 7);
__ jalr(ZR, T5);
__ trap();
__ Bind(&label1);
__ li(T0, 4);
__ jal(T5, &label2); // Backward.
__ jalr(ZR, T4);
__ trap();
}
ASSEMBLER_TEST_RUN(JumpAndLink, test) {
EXPECT_DISASSEMBLY(
"01c00eef jal t4, +28\n"
"40628533 sub a0, t0, t1\n"
"00008067 ret\n"
"00000000 trap\n"
"00700313 li t1, 7\n"
"000f0067 jr t5\n"
"00000000 trap\n"
"00400293 li t0, 4\n"
"ff1fff6f jal t5, -16\n"
"000e8067 jr t4\n"
"00000000 trap\n");
EXPECT_EQ(-3, Call(test->entry()));
}
ASSEMBLER_TEST_GENERATE(Jump, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
Label label1, label2;
__ j(&label1); // Forward.
__ trap();
__ Bind(&label2);
__ li(T1, 7);
__ sub(A0, T0, T1);
__ ret();
__ Bind(&label1);
__ li(T0, 4);
__ j(&label2); // Backward.
__ trap();
}
ASSEMBLER_TEST_RUN(Jump, test) {
EXPECT_DISASSEMBLY(
"0140006f j +20\n"
"00000000 trap\n"
"00700313 li t1, 7\n"
"40628533 sub a0, t0, t1\n"
"00008067 ret\n"
"00400293 li t0, 4\n"
"ff1ff06f j -16\n"
"00000000 trap\n");
EXPECT_EQ(-3, Call(test->entry()));
}
ASSEMBLER_TEST_GENERATE(JumpAndLinkRegister, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
/* 00 */ __ jalr(T4, A1, 28); // Forward.
/* 04 */ __ sub(A0, T0, T1);
/* 08 */ __ ret();
/* 12 */ __ trap();
/* 16 */ __ li(T1, 7);
/* 20 */ __ jalr(ZR, T5);
/* 24 */ __ trap();
/* 28 */ __ li(T0, 4);
/* 32 */ __ jalr(T5, A1, 16); // Backward.
/* 36 */ __ jalr(ZR, T4);
/* 40 */ __ trap();
}
ASSEMBLER_TEST_RUN(JumpAndLinkRegister, test) {
EXPECT_DISASSEMBLY(
"01c58ee7 jalr t4, 28(a1)\n"
"40628533 sub a0, t0, t1\n"
"00008067 ret\n"
"00000000 trap\n"
"00700313 li t1, 7\n"
"000f0067 jr t5\n"
"00000000 trap\n"
"00400293 li t0, 4\n"
"01058f67 jalr t5, 16(a1)\n"
"000e8067 jr t4\n"
"00000000 trap\n");
EXPECT_EQ(-3, Call(test->entry(), 0, test->entry()));
}
ASSEMBLER_TEST_GENERATE(JumpRegister, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
/* 00 */ __ jr(A1, 20); // Forward.
/* 04 */ __ trap();
/* 08 */ __ li(T1, 7);
/* 12 */ __ sub(A0, T0, T1);
/* 16 */ __ ret();
/* 20 */ __ li(T0, 4);
/* 24 */ __ jr(A1, 8); // Backward.
/* 28 */ __ trap();
}
ASSEMBLER_TEST_RUN(JumpRegister, test) {
EXPECT_DISASSEMBLY(
"01458067 jr 20(a1)\n"
"00000000 trap\n"
"00700313 li t1, 7\n"
"40628533 sub a0, t0, t1\n"
"00008067 ret\n"
"00400293 li t0, 4\n"
"00858067 jr 8(a1)\n"
"00000000 trap\n");
EXPECT_EQ(-3, Call(test->entry(), 0, test->entry()));
}
ASSEMBLER_TEST_GENERATE(BranchEqualForward, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
Label label;
__ beq(A0, A1, &label);
__ li(A0, 3);
__ ret();
__ Bind(&label);
__ li(A0, 4);
__ ret();
}
ASSEMBLER_TEST_RUN(BranchEqualForward, test) {
EXPECT_DISASSEMBLY(
"00b50663 beq a0, a1, +12\n"
"00300513 li a0, 3\n"
"00008067 ret\n"
"00400513 li a0, 4\n"
"00008067 ret\n");
EXPECT_EQ(4, Call(test->entry(), 1, 1));
EXPECT_EQ(3, Call(test->entry(), 1, 0));
EXPECT_EQ(3, Call(test->entry(), 1, -1));
EXPECT_EQ(3, Call(test->entry(), 0, 1));
EXPECT_EQ(4, Call(test->entry(), 0, 0));
EXPECT_EQ(3, Call(test->entry(), 0, -1));
EXPECT_EQ(3, Call(test->entry(), -1, 1));
EXPECT_EQ(3, Call(test->entry(), -1, 0));
EXPECT_EQ(4, Call(test->entry(), -1, -1));
}
ASSEMBLER_TEST_GENERATE(BranchEqualForwardFar, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
Label label;
__ beq(A0, A1, &label);
__ li(A0, 3);
__ ret();
for (intptr_t i = 0; i < (1 << 13); i++) {
__ ebreak();
}
__ Bind(&label);
__ li(A0, 4);
__ ret();
}
ASSEMBLER_TEST_RUN(BranchEqualForwardFar, test) {
// EXPECT_DISASSEMBLY(constant too big);
EXPECT_EQ(4, Call(test->entry(), 1, 1));
EXPECT_EQ(3, Call(test->entry(), 1, 0));
EXPECT_EQ(3, Call(test->entry(), 1, -1));
EXPECT_EQ(3, Call(test->entry(), 0, 1));
EXPECT_EQ(4, Call(test->entry(), 0, 0));
EXPECT_EQ(3, Call(test->entry(), 0, -1));
EXPECT_EQ(3, Call(test->entry(), -1, 1));
EXPECT_EQ(3, Call(test->entry(), -1, 0));
EXPECT_EQ(4, Call(test->entry(), -1, -1));
}
ASSEMBLER_TEST_GENERATE(BranchNotEqualForward, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
Label label;
__ bne(A0, A1, &label);
__ li(A0, 3);
__ ret();
__ Bind(&label);
__ li(A0, 4);
__ ret();
}
ASSEMBLER_TEST_RUN(BranchNotEqualForward, test) {
EXPECT_DISASSEMBLY(
"00b51663 bne a0, a1, +12\n"
"00300513 li a0, 3\n"
"00008067 ret\n"
"00400513 li a0, 4\n"
"00008067 ret\n");
EXPECT_EQ(3, Call(test->entry(), 1, 1));
EXPECT_EQ(4, Call(test->entry(), 1, 0));
EXPECT_EQ(4, Call(test->entry(), 1, -1));
EXPECT_EQ(4, Call(test->entry(), 0, 1));
EXPECT_EQ(3, Call(test->entry(), 0, 0));
EXPECT_EQ(4, Call(test->entry(), 0, -1));
EXPECT_EQ(4, Call(test->entry(), -1, 1));
EXPECT_EQ(4, Call(test->entry(), -1, 0));
EXPECT_EQ(3, Call(test->entry(), -1, -1));
}
ASSEMBLER_TEST_GENERATE(BranchNotEqualForwardFar, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
Label label;
__ bne(A0, A1, &label);
__ li(A0, 3);
__ ret();
for (intptr_t i = 0; i < (1 << 13); i++) {
__ ebreak();
}
__ Bind(&label);
__ li(A0, 4);
__ ret();
}
ASSEMBLER_TEST_RUN(BranchNotEqualForwardFar, test) {
// EXPECT_DISASSEMBLY(constant too big);
EXPECT_EQ(3, Call(test->entry(), 1, 1));
EXPECT_EQ(4, Call(test->entry(), 1, 0));
EXPECT_EQ(4, Call(test->entry(), 1, -1));
EXPECT_EQ(4, Call(test->entry(), 0, 1));
EXPECT_EQ(3, Call(test->entry(), 0, 0));
EXPECT_EQ(4, Call(test->entry(), 0, -1));
EXPECT_EQ(4, Call(test->entry(), -1, 1));
EXPECT_EQ(4, Call(test->entry(), -1, 0));
EXPECT_EQ(3, Call(test->entry(), -1, -1));
}
ASSEMBLER_TEST_GENERATE(BranchLessThanForward, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
Label label;
__ blt(A0, A1, &label);
__ li(A0, 3);
__ ret();
__ Bind(&label);
__ li(A0, 4);
__ ret();
}
ASSEMBLER_TEST_RUN(BranchLessThanForward, test) {
EXPECT_DISASSEMBLY(
"00b54663 blt a0, a1, +12\n"
"00300513 li a0, 3\n"
"00008067 ret\n"
"00400513 li a0, 4\n"
"00008067 ret\n");
EXPECT_EQ(3, Call(test->entry(), 1, 1));
EXPECT_EQ(3, Call(test->entry(), 1, 0));
EXPECT_EQ(3, Call(test->entry(), 1, -1));
EXPECT_EQ(4, Call(test->entry(), 0, 1));
EXPECT_EQ(3, Call(test->entry(), 0, 0));
EXPECT_EQ(3, Call(test->entry(), 0, -1));
EXPECT_EQ(4, Call(test->entry(), -1, 1));
EXPECT_EQ(4, Call(test->entry(), -1, 0));
EXPECT_EQ(3, Call(test->entry(), -1, -1));
}
ASSEMBLER_TEST_GENERATE(BranchLessThanForwardFar, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
Label label;
__ blt(A0, A1, &label);
__ li(A0, 3);
__ ret();
for (intptr_t i = 0; i < (1 << 13); i++) {
__ ebreak();
}
__ Bind(&label);
__ li(A0, 4);
__ ret();
}
ASSEMBLER_TEST_RUN(BranchLessThanForwardFar, test) {
// EXPECT_DISASSEMBLY(constant too big);
EXPECT_EQ(3, Call(test->entry(), 1, 1));
EXPECT_EQ(3, Call(test->entry(), 1, 0));
EXPECT_EQ(3, Call(test->entry(), 1, -1));
EXPECT_EQ(4, Call(test->entry(), 0, 1));
EXPECT_EQ(3, Call(test->entry(), 0, 0));
EXPECT_EQ(3, Call(test->entry(), 0, -1));
EXPECT_EQ(4, Call(test->entry(), -1, 1));
EXPECT_EQ(4, Call(test->entry(), -1, 0));
EXPECT_EQ(3, Call(test->entry(), -1, -1));
}
ASSEMBLER_TEST_GENERATE(BranchLessOrEqualForward, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
Label label;
__ ble(A0, A1, &label);
__ li(A0, 3);
__ ret();
__ Bind(&label);
__ li(A0, 4);
__ ret();
}
ASSEMBLER_TEST_RUN(BranchLessOrEqualForward, test) {
EXPECT_DISASSEMBLY(
"00a5d663 ble a0, a1, +12\n"
"00300513 li a0, 3\n"
"00008067 ret\n"
"00400513 li a0, 4\n"
"00008067 ret\n");
EXPECT_EQ(4, Call(test->entry(), 1, 1));
EXPECT_EQ(3, Call(test->entry(), 1, 0));
EXPECT_EQ(3, Call(test->entry(), 1, -1));
EXPECT_EQ(4, Call(test->entry(), 0, 1));
EXPECT_EQ(4, Call(test->entry(), 0, 0));
EXPECT_EQ(3, Call(test->entry(), 0, -1));
EXPECT_EQ(4, Call(test->entry(), -1, 1));
EXPECT_EQ(4, Call(test->entry(), -1, 0));
EXPECT_EQ(4, Call(test->entry(), -1, -1));
}
ASSEMBLER_TEST_GENERATE(BranchLessOrEqualForwardFar, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
Label label;
__ ble(A0, A1, &label);
__ li(A0, 3);
__ ret();
for (intptr_t i = 0; i < (1 << 13); i++) {
__ ebreak();
}
__ Bind(&label);
__ li(A0, 4);
__ ret();
}
ASSEMBLER_TEST_RUN(BranchLessOrEqualForwardFar, test) {
// EXPECT_DISASSEMBLY(constant too big);
EXPECT_EQ(4, Call(test->entry(), 1, 1));
EXPECT_EQ(3, Call(test->entry(), 1, 0));
EXPECT_EQ(3, Call(test->entry(), 1, -1));
EXPECT_EQ(4, Call(test->entry(), 0, 1));
EXPECT_EQ(4, Call(test->entry(), 0, 0));
EXPECT_EQ(3, Call(test->entry(), 0, -1));
EXPECT_EQ(4, Call(test->entry(), -1, 1));
EXPECT_EQ(4, Call(test->entry(), -1, 0));
EXPECT_EQ(4, Call(test->entry(), -1, -1));
}
ASSEMBLER_TEST_GENERATE(BranchGreaterThanForward, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
Label label;
__ bgt(A0, A1, &label);
__ li(A0, 3);
__ ret();
__ Bind(&label);
__ li(A0, 4);
__ ret();
}
ASSEMBLER_TEST_RUN(BranchGreaterThanForward, test) {
EXPECT_DISASSEMBLY(
"00a5c663 blt a1, a0, +12\n"
"00300513 li a0, 3\n"
"00008067 ret\n"
"00400513 li a0, 4\n"
"00008067 ret\n");
EXPECT_EQ(3, Call(test->entry(), 1, 1));
EXPECT_EQ(4, Call(test->entry(), 1, 0));
EXPECT_EQ(4, Call(test->entry(), 1, -1));
EXPECT_EQ(3, Call(test->entry(), 0, 1));
EXPECT_EQ(3, Call(test->entry(), 0, 0));
EXPECT_EQ(4, Call(test->entry(), 0, -1));
EXPECT_EQ(3, Call(test->entry(), -1, 1));
EXPECT_EQ(3, Call(test->entry(), -1, 0));
EXPECT_EQ(3, Call(test->entry(), -1, -1));
}
ASSEMBLER_TEST_GENERATE(BranchGreaterOrEqualForward, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
Label label;
__ bge(A0, A1, &label);
__ li(A0, 3);
__ ret();
__ Bind(&label);
__ li(A0, 4);
__ ret();
}
ASSEMBLER_TEST_RUN(BranchGreaterOrEqualForward, test) {
EXPECT_DISASSEMBLY(
"00b55663 ble a1, a0, +12\n"
"00300513 li a0, 3\n"
"00008067 ret\n"
"00400513 li a0, 4\n"
"00008067 ret\n");
EXPECT_EQ(4, Call(test->entry(), 1, 1));
EXPECT_EQ(4, Call(test->entry(), 1, 0));
EXPECT_EQ(4, Call(test->entry(), 1, -1));
EXPECT_EQ(3, Call(test->entry(), 0, 1));
EXPECT_EQ(4, Call(test->entry(), 0, 0));
EXPECT_EQ(4, Call(test->entry(), 0, -1));
EXPECT_EQ(3, Call(test->entry(), -1, 1));
EXPECT_EQ(3, Call(test->entry(), -1, 0));
EXPECT_EQ(4, Call(test->entry(), -1, -1));
}
ASSEMBLER_TEST_GENERATE(BranchLessThanUnsignedForward, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
Label label;
__ bltu(A0, A1, &label);
__ li(A0, 3);
__ ret();
__ Bind(&label);
__ li(A0, 4);
__ ret();
}
ASSEMBLER_TEST_RUN(BranchLessThanUnsignedForward, test) {
EXPECT_DISASSEMBLY(
"00b56663 bltu a0, a1, +12\n"
"00300513 li a0, 3\n"
"00008067 ret\n"
"00400513 li a0, 4\n"
"00008067 ret\n");
EXPECT_EQ(3, Call(test->entry(), 1, 1));
EXPECT_EQ(3, Call(test->entry(), 1, 0));
EXPECT_EQ(4, Call(test->entry(), 1, -1));
EXPECT_EQ(4, Call(test->entry(), 0, 1));
EXPECT_EQ(3, Call(test->entry(), 0, 0));
EXPECT_EQ(4, Call(test->entry(), 0, -1));
EXPECT_EQ(3, Call(test->entry(), -1, 1));
EXPECT_EQ(3, Call(test->entry(), -1, 0));
EXPECT_EQ(3, Call(test->entry(), -1, -1));
}
ASSEMBLER_TEST_GENERATE(BranchLessOrEqualUnsignedForward, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
Label label;
__ bleu(A0, A1, &label);
__ li(A0, 3);
__ ret();
__ Bind(&label);
__ li(A0, 4);
__ ret();
}
ASSEMBLER_TEST_RUN(BranchLessOrEqualUnsignedForward, test) {
EXPECT_DISASSEMBLY(
"00a5f663 bleu a0, a1, +12\n"
"00300513 li a0, 3\n"
"00008067 ret\n"
"00400513 li a0, 4\n"
"00008067 ret\n");
EXPECT_EQ(4, Call(test->entry(), 1, 1));
EXPECT_EQ(3, Call(test->entry(), 1, 0));
EXPECT_EQ(4, Call(test->entry(), 1, -1));
EXPECT_EQ(4, Call(test->entry(), 0, 1));
EXPECT_EQ(4, Call(test->entry(), 0, 0));
EXPECT_EQ(4, Call(test->entry(), 0, -1));
EXPECT_EQ(3, Call(test->entry(), -1, 1));
EXPECT_EQ(3, Call(test->entry(), -1, 0));
EXPECT_EQ(4, Call(test->entry(), -1, -1));
}
ASSEMBLER_TEST_GENERATE(BranchGreaterThanUnsignedForward, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
Label label;
__ bgtu(A0, A1, &label);
__ li(A0, 3);
__ ret();
__ Bind(&label);
__ li(A0, 4);
__ ret();
}
ASSEMBLER_TEST_RUN(BranchGreaterThanUnsignedForward, test) {
EXPECT_DISASSEMBLY(
"00a5e663 bltu a1, a0, +12\n"
"00300513 li a0, 3\n"
"00008067 ret\n"
"00400513 li a0, 4\n"
"00008067 ret\n");
EXPECT_EQ(3, Call(test->entry(), 1, 1));
EXPECT_EQ(4, Call(test->entry(), 1, 0));
EXPECT_EQ(3, Call(test->entry(), 1, -1));
EXPECT_EQ(3, Call(test->entry(), 0, 1));
EXPECT_EQ(3, Call(test->entry(), 0, 0));
EXPECT_EQ(3, Call(test->entry(), 0, -1));
EXPECT_EQ(4, Call(test->entry(), -1, 1));
EXPECT_EQ(4, Call(test->entry(), -1, 0));
EXPECT_EQ(3, Call(test->entry(), -1, -1));
}
ASSEMBLER_TEST_GENERATE(BranchGreaterOrEqualUnsignedForward, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
Label label;
__ bgeu(A0, A1, &label);
__ li(A0, 3);
__ ret();
__ Bind(&label);
__ li(A0, 4);
__ ret();
}
ASSEMBLER_TEST_RUN(BranchGreaterOrEqualUnsignedForward, test) {
EXPECT_DISASSEMBLY(
"00b57663 bleu a1, a0, +12\n"
"00300513 li a0, 3\n"
"00008067 ret\n"
"00400513 li a0, 4\n"
"00008067 ret\n");
EXPECT_EQ(4, Call(test->entry(), 1, 1));
EXPECT_EQ(4, Call(test->entry(), 1, 0));
EXPECT_EQ(3, Call(test->entry(), 1, -1));
EXPECT_EQ(3, Call(test->entry(), 0, 1));
EXPECT_EQ(4, Call(test->entry(), 0, 0));
EXPECT_EQ(3, Call(test->entry(), 0, -1));
EXPECT_EQ(4, Call(test->entry(), -1, 1));
EXPECT_EQ(4, Call(test->entry(), -1, 0));
EXPECT_EQ(4, Call(test->entry(), -1, -1));
}
ASSEMBLER_TEST_GENERATE(LoadByte_0, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ lb(A0, Address(A0, 0));
__ ret();
}
ASSEMBLER_TEST_RUN(LoadByte_0, test) {
EXPECT_DISASSEMBLY(
"00050503 lb a0, 0(a0)\n"
"00008067 ret\n");
uint8_t* values = reinterpret_cast<uint8_t*>(malloc(3 * sizeof(uint8_t)));
values[0] = 0xAB;
values[1] = 0xCD;
values[2] = 0xEF;
EXPECT_EQ(-51, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
free(values);
}
ASSEMBLER_TEST_GENERATE(LoadByte_Pos, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ lb(A0, Address(A0, 1));
__ ret();
}
ASSEMBLER_TEST_RUN(LoadByte_Pos, test) {
EXPECT_DISASSEMBLY(
"00150503 lb a0, 1(a0)\n"
"00008067 ret\n");
uint8_t* values = reinterpret_cast<uint8_t*>(malloc(3 * sizeof(uint8_t)));
values[0] = 0xAB;
values[1] = 0xCD;
values[2] = 0xEF;
EXPECT_EQ(-17, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
free(values);
}
ASSEMBLER_TEST_GENERATE(LoadByte_Neg, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ lb(A0, Address(A0, -1));
__ ret();
}
ASSEMBLER_TEST_RUN(LoadByte_Neg, test) {
EXPECT_DISASSEMBLY(
"fff50503 lb a0, -1(a0)\n"
"00008067 ret\n");
uint8_t* values = reinterpret_cast<uint8_t*>(malloc(3 * sizeof(uint8_t)));
values[0] = 0xAB;
values[1] = 0xCD;
values[2] = 0xEF;
EXPECT_EQ(-85, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
free(values);
}
ASSEMBLER_TEST_GENERATE(LoadByteUnsigned_0, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ lbu(A0, Address(A0, 0));
__ ret();
}
ASSEMBLER_TEST_RUN(LoadByteUnsigned_0, test) {
EXPECT_DISASSEMBLY(
"00054503 lbu a0, 0(a0)\n"
"00008067 ret\n");
uint8_t* values = reinterpret_cast<uint8_t*>(malloc(3 * sizeof(uint8_t)));
values[0] = 0xAB;
values[1] = 0xCD;
values[2] = 0xEF;
EXPECT_EQ(0xCD, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
free(values);
}
ASSEMBLER_TEST_GENERATE(LoadByteUnsigned_Pos, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ lbu(A0, Address(A0, 1));
__ ret();
}
ASSEMBLER_TEST_RUN(LoadByteUnsigned_Pos, test) {
EXPECT_DISASSEMBLY(
"00154503 lbu a0, 1(a0)\n"
"00008067 ret\n");
uint8_t* values = reinterpret_cast<uint8_t*>(malloc(3 * sizeof(uint8_t)));
values[0] = 0xAB;
values[1] = 0xCD;
values[2] = 0xEF;
EXPECT_EQ(0xEF, Call(test->entry(), reinterpret_cast<intx_t>((&values[1]))));
free(values);
}
ASSEMBLER_TEST_GENERATE(LoadByteUnsigned_Neg, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ lbu(A0, Address(A0, -1));
__ ret();
}
ASSEMBLER_TEST_RUN(LoadByteUnsigned_Neg, test) {
EXPECT_DISASSEMBLY(
"fff54503 lbu a0, -1(a0)\n"
"00008067 ret\n");
uint8_t* values = reinterpret_cast<uint8_t*>(malloc(3 * sizeof(uint8_t)));
values[0] = 0xAB;
values[1] = 0xCD;
values[2] = 0xEF;
EXPECT_EQ(0xAB, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
}
ASSEMBLER_TEST_GENERATE(LoadHalfword_0, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ lh(A0, Address(A0, 0));
__ ret();
}
ASSEMBLER_TEST_RUN(LoadHalfword_0, test) {
EXPECT_DISASSEMBLY(
"00051503 lh a0, 0(a0)\n"
"00008067 ret\n");
uint16_t* values = reinterpret_cast<uint16_t*>(malloc(3 * sizeof(uint16_t)));
values[0] = 0xAB01;
values[1] = 0xCD02;
values[2] = 0xEF03;
EXPECT_EQ(-13054, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
}
ASSEMBLER_TEST_GENERATE(LoadHalfword_Pos, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ lh(A0, Address(A0, 2));
__ ret();
}
ASSEMBLER_TEST_RUN(LoadHalfword_Pos, test) {
EXPECT_DISASSEMBLY(
"00251503 lh a0, 2(a0)\n"
"00008067 ret\n");
uint16_t* values = reinterpret_cast<uint16_t*>(malloc(3 * sizeof(uint16_t)));
values[0] = 0xAB01;
values[1] = 0xCD02;
values[2] = 0xEF03;
EXPECT_EQ(-4349, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
}
ASSEMBLER_TEST_GENERATE(LoadHalfword_Neg, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ lh(A0, Address(A0, -2));
__ ret();
}
ASSEMBLER_TEST_RUN(LoadHalfword_Neg, test) {
EXPECT_DISASSEMBLY(
"ffe51503 lh a0, -2(a0)\n"
"00008067 ret\n");
uint16_t* values = reinterpret_cast<uint16_t*>(malloc(3 * sizeof(uint16_t)));
values[0] = 0xAB01;
values[1] = 0xCD02;
values[2] = 0xEF03;
EXPECT_EQ(-21759, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
}
ASSEMBLER_TEST_GENERATE(LoadHalfwordUnsigned_0, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ lhu(A0, Address(A0, 0));
__ ret();
}
ASSEMBLER_TEST_RUN(LoadHalfwordUnsigned_0, test) {
EXPECT_DISASSEMBLY(
"00055503 lhu a0, 0(a0)\n"
"00008067 ret\n");
uint16_t* values = reinterpret_cast<uint16_t*>(malloc(3 * sizeof(uint16_t)));
values[0] = 0xAB01;
values[1] = 0xCD02;
values[2] = 0xEF03;
EXPECT_EQ(0xCD02, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
}
ASSEMBLER_TEST_GENERATE(LoadHalfwordUnsigned_Pos, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ lhu(A0, Address(A0, 2));
__ ret();
}
ASSEMBLER_TEST_RUN(LoadHalfwordUnsigned_Pos, test) {
EXPECT_DISASSEMBLY(
"00255503 lhu a0, 2(a0)\n"
"00008067 ret\n");
uint16_t* values = reinterpret_cast<uint16_t*>(malloc(3 * sizeof(uint16_t)));
values[0] = 0xAB01;
values[1] = 0xCD02;
values[2] = 0xEF03;
EXPECT_EQ(0xEF03, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
}
ASSEMBLER_TEST_GENERATE(LoadHalfwordUnsigned_Neg, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ lhu(A0, Address(A0, -2));
__ ret();
}
ASSEMBLER_TEST_RUN(LoadHalfwordUnsigned_Neg, test) {
EXPECT_DISASSEMBLY(
"ffe55503 lhu a0, -2(a0)\n"
"00008067 ret\n");
uint16_t* values = reinterpret_cast<uint16_t*>(malloc(3 * sizeof(uint16_t)));
values[0] = 0xAB01;
values[1] = 0xCD02;
values[2] = 0xEF03;
EXPECT_EQ(0xAB01, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
}
ASSEMBLER_TEST_GENERATE(LoadWord_0, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ lw(A0, Address(A0, 0));
__ ret();
}
ASSEMBLER_TEST_RUN(LoadWord_0, test) {
EXPECT_DISASSEMBLY(
"00052503 lw a0, 0(a0)\n"
"00008067 ret\n");
uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t)));
values[0] = 0xAB010203;
values[1] = 0xCD020405;
values[2] = 0xEF030607;
EXPECT_EQ(-855505915,
Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
}
ASSEMBLER_TEST_GENERATE(LoadWord_Pos, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ lw(A0, Address(A0, 4));
__ ret();
}
ASSEMBLER_TEST_RUN(LoadWord_Pos, test) {
EXPECT_DISASSEMBLY(
"00452503 lw a0, 4(a0)\n"
"00008067 ret\n");
uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t)));
values[0] = 0xAB010203;
values[1] = 0xCD020405;
values[2] = 0xEF030607;
EXPECT_EQ(-285014521,
Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
}
ASSEMBLER_TEST_GENERATE(LoadWord_Neg, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ lw(A0, Address(A0, -4));
__ ret();
}
ASSEMBLER_TEST_RUN(LoadWord_Neg, test) {
EXPECT_DISASSEMBLY(
"ffc52503 lw a0, -4(a0)\n"
"00008067 ret\n");
uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t)));
values[0] = 0xAB010203;
values[1] = 0xCD020405;
values[2] = 0xEF030607;
EXPECT_EQ(-1425997309,
Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
}
ASSEMBLER_TEST_GENERATE(StoreWord_0, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ sw(A1, Address(A0, 0));
__ ret();
}
ASSEMBLER_TEST_RUN(StoreWord_0, test) {
EXPECT_DISASSEMBLY(
"00b52023 sw a1, 0(a0)\n"
"00008067 ret\n");
uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t)));
values[0] = 0;
values[1] = 0;
values[2] = 0;
Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xCD020405);
EXPECT_EQ(0u, values[0]);
EXPECT_EQ(0xCD020405, values[1]);
EXPECT_EQ(0u, values[2]);
}
ASSEMBLER_TEST_GENERATE(StoreWord_Pos, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ sw(A1, Address(A0, 4));
__ ret();
}
ASSEMBLER_TEST_RUN(StoreWord_Pos, test) {
EXPECT_DISASSEMBLY(
"00b52223 sw a1, 4(a0)\n"
"00008067 ret\n");
uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t)));
values[0] = 0;
values[1] = 0;
values[2] = 0;
Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xEF030607);
EXPECT_EQ(0u, values[0]);
EXPECT_EQ(0u, values[1]);
EXPECT_EQ(0xEF030607, values[2]);
}
ASSEMBLER_TEST_GENERATE(StoreWord_Neg, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ sw(A1, Address(A0, -4));
__ ret();
}
ASSEMBLER_TEST_RUN(StoreWord_Neg, test) {
EXPECT_DISASSEMBLY(
"feb52e23 sw a1, -4(a0)\n"
"00008067 ret\n");
uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t)));
values[0] = 0;
values[1] = 0;
values[2] = 0;
Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xAB010203);
EXPECT_EQ(0xAB010203, values[0]);
EXPECT_EQ(0u, values[1]);
EXPECT_EQ(0u, values[2]);
}
#if XLEN >= 64
ASSEMBLER_TEST_GENERATE(LoadWordUnsigned_0, assembler) {
__ lwu(A0, Address(A0, 0));
__ ret();
}
ASSEMBLER_TEST_RUN(LoadWordUnsigned_0, test) {
EXPECT_DISASSEMBLY(
"00056503 lwu a0, 0(a0)\n"
"00008067 ret\n");
uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t)));
values[0] = 0xAB010203;
values[1] = 0xCD020405;
values[2] = 0xEF030607;
EXPECT_EQ(0xCD020405,
Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
}
ASSEMBLER_TEST_GENERATE(LoadWordUnsigned_Pos, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ lwu(A0, Address(A0, 4));
__ ret();
}
ASSEMBLER_TEST_RUN(LoadWordUnsigned_Pos, test) {
EXPECT_DISASSEMBLY(
"00456503 lwu a0, 4(a0)\n"
"00008067 ret\n");
uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t)));
values[0] = 0xAB010203;
values[1] = 0xCD020405;
values[2] = 0xEF030607;
EXPECT_EQ(0xEF030607,
Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
}
ASSEMBLER_TEST_GENERATE(LoadWordUnsigned_Neg, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ lwu(A0, Address(A0, -4));
__ ret();
}
ASSEMBLER_TEST_RUN(LoadWordUnsigned_Neg, test) {
EXPECT_DISASSEMBLY(
"ffc56503 lwu a0, -4(a0)\n"
"00008067 ret\n");
uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t)));
values[0] = 0xAB010203;
values[1] = 0xCD020405;
values[2] = 0xEF030607;
EXPECT_EQ(0xAB010203,
Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
}
ASSEMBLER_TEST_GENERATE(LoadDoubleWord_0, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ ld(A0, Address(A0, 0));
__ ret();
}
ASSEMBLER_TEST_RUN(LoadDoubleWord_0, test) {
EXPECT_DISASSEMBLY(
"00053503 ld a0, 0(a0)\n"
"00008067 ret\n");
uint64_t* values = reinterpret_cast<uint64_t*>(malloc(3 * sizeof(uint64_t)));
values[0] = 0xAB01020304050607;
values[1] = 0xCD02040505060708;
values[2] = 0xEF03060708090A0B;
EXPECT_EQ(-3674369926375274744,
Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
}
ASSEMBLER_TEST_GENERATE(LoadDoubleWord_Pos, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ ld(A0, Address(A0, 8));
__ ret();
}
ASSEMBLER_TEST_RUN(LoadDoubleWord_Pos, test) {
EXPECT_DISASSEMBLY(
"00853503 ld a0, 8(a0)\n"
"00008067 ret\n");
uint64_t* values = reinterpret_cast<uint64_t*>(malloc(3 * sizeof(uint64_t)));
values[0] = 0xAB01020304050607;
values[1] = 0xCD02040505060708;
values[2] = 0xEF03060708090A0B;
EXPECT_EQ(-1224128046445295093,
Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
}
ASSEMBLER_TEST_GENERATE(LoadDoubleWord_Neg, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ ld(A0, Address(A0, -8));
__ ret();
}
ASSEMBLER_TEST_RUN(LoadDoubleWord_Neg, test) {
EXPECT_DISASSEMBLY(
"ff853503 ld a0, -8(a0)\n"
"00008067 ret\n");
uint64_t* values = reinterpret_cast<uint64_t*>(malloc(3 * sizeof(uint64_t)));
values[0] = 0xAB01020304050607;
values[1] = 0xCD02040505060708;
values[2] = 0xEF03060708090A0B;
EXPECT_EQ(-6124611806271568377,
Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
}
ASSEMBLER_TEST_GENERATE(StoreDoubleWord_0, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ sd(A1, Address(A0, 0));
__ ret();
}
ASSEMBLER_TEST_RUN(StoreDoubleWord_0, test) {
EXPECT_DISASSEMBLY(
"00b53023 sd a1, 0(a0)\n"
"00008067 ret\n");
uint64_t* values = reinterpret_cast<uint64_t*>(malloc(3 * sizeof(uint64_t)));
values[0] = 0;
values[1] = 0;
values[2] = 0;
Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xCD02040505060708);
EXPECT_EQ(0u, values[0]);
EXPECT_EQ(0xCD02040505060708, values[1]);
EXPECT_EQ(0u, values[2]);
}
ASSEMBLER_TEST_GENERATE(StoreDoubleWord_Pos, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ sd(A1, Address(A0, 8));
__ ret();
}
ASSEMBLER_TEST_RUN(StoreDoubleWord_Pos, test) {
EXPECT_DISASSEMBLY(
"00b53423 sd a1, 8(a0)\n"
"00008067 ret\n");
uint64_t* values = reinterpret_cast<uint64_t*>(malloc(3 * sizeof(uint64_t)));
values[0] = 0;
values[1] = 0;
values[2] = 0;
Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xEF03060708090A0B);
EXPECT_EQ(0u, values[0]);
EXPECT_EQ(0u, values[1]);
EXPECT_EQ(0xEF03060708090A0B, values[2]);
}
ASSEMBLER_TEST_GENERATE(StoreDoubleWord_Neg, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ sd(A1, Address(A0, -8));
__ ret();
}
ASSEMBLER_TEST_RUN(StoreDoubleWord_Neg, test) {
EXPECT_DISASSEMBLY(
"feb53c23 sd a1, -8(a0)\n"
"00008067 ret\n");
uint64_t* values = reinterpret_cast<uint64_t*>(malloc(3 * sizeof(uint64_t)));
values[0] = 0;
values[1] = 0;
values[2] = 0;
Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xAB01020304050607);
EXPECT_EQ(0xAB01020304050607, values[0]);
EXPECT_EQ(0u, values[1]);
EXPECT_EQ(0u, values[2]);
}
#endif
ASSEMBLER_TEST_GENERATE(AddImmediate1, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ addi(A0, A0, 42);
__ ret();
}
ASSEMBLER_TEST_RUN(AddImmediate1, test) {
EXPECT_DISASSEMBLY(
"02a50513 addi a0, a0, 42\n"
"00008067 ret\n");
EXPECT_EQ(42, Call(test->entry(), 0));
EXPECT_EQ(40, Call(test->entry(), -2));
EXPECT_EQ(0, Call(test->entry(), -42));
}
ASSEMBLER_TEST_GENERATE(AddImmediate2, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ addi(A0, A0, -42);
__ ret();
}
ASSEMBLER_TEST_RUN(AddImmediate2, test) {
EXPECT_DISASSEMBLY(
"fd650513 addi a0, a0, -42\n"
"00008067 ret\n");
EXPECT_EQ(-42, Call(test->entry(), 0));
EXPECT_EQ(-44, Call(test->entry(), -2));
EXPECT_EQ(38, Call(test->entry(), 80));
}
ASSEMBLER_TEST_GENERATE(SetLessThanImmediate1, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ slti(A0, A0, 7);
__ ret();
}
ASSEMBLER_TEST_RUN(SetLessThanImmediate1, test) {
EXPECT_DISASSEMBLY(
"00752513 slti a0, a0, 7\n"
"00008067 ret\n");
EXPECT_EQ(1, Call(test->entry(), 6));
EXPECT_EQ(0, Call(test->entry(), 7));
EXPECT_EQ(0, Call(test->entry(), 8));
EXPECT_EQ(1, Call(test->entry(), -6));
EXPECT_EQ(1, Call(test->entry(), -7));
EXPECT_EQ(1, Call(test->entry(), -8));
}
ASSEMBLER_TEST_GENERATE(SetLessThanImmediate2, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ slti(A0, A0, -7);
__ ret();
}
ASSEMBLER_TEST_RUN(SetLessThanImmediate2, test) {
EXPECT_DISASSEMBLY(
"ff952513 slti a0, a0, -7\n"
"00008067 ret\n");
EXPECT_EQ(0, Call(test->entry(), 6));
EXPECT_EQ(0, Call(test->entry(), 7));
EXPECT_EQ(0, Call(test->entry(), 8));
EXPECT_EQ(0, Call(test->entry(), -6));
EXPECT_EQ(0, Call(test->entry(), -7));
EXPECT_EQ(1, Call(test->entry(), -8));
}
ASSEMBLER_TEST_GENERATE(SetLessThanImmediateUnsigned1, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ sltiu(A0, A0, 7);
__ ret();
}
ASSEMBLER_TEST_RUN(SetLessThanImmediateUnsigned1, test) {
EXPECT_DISASSEMBLY(
"00753513 sltiu a0, a0, 7\n"
"00008067 ret\n");
EXPECT_EQ(1, Call(test->entry(), 6));
EXPECT_EQ(0, Call(test->entry(), 7));
EXPECT_EQ(0, Call(test->entry(), 8));
EXPECT_EQ(0, Call(test->entry(), -6));
EXPECT_EQ(0, Call(test->entry(), -7));
EXPECT_EQ(0, Call(test->entry(), -8));
}
ASSEMBLER_TEST_GENERATE(SetLessThanImmediateUnsigned2, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ sltiu(A0, A0, -7);
__ ret();
}
ASSEMBLER_TEST_RUN(SetLessThanImmediateUnsigned2, test) {
EXPECT_DISASSEMBLY(
"ff953513 sltiu a0, a0, -7\n"
"00008067 ret\n");
EXPECT_EQ(1, Call(test->entry(), 6));
EXPECT_EQ(1, Call(test->entry(), 7));
EXPECT_EQ(1, Call(test->entry(), 8));
EXPECT_EQ(0, Call(test->entry(), -6));
EXPECT_EQ(0, Call(test->entry(), -7));
EXPECT_EQ(1, Call(test->entry(), -8));
}
ASSEMBLER_TEST_GENERATE(XorImmediate1, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ xori(A0, A0, 42);
__ ret();
}
ASSEMBLER_TEST_RUN(XorImmediate1, test) {
EXPECT_DISASSEMBLY(
"02a54513 xori a0, a0, 42\n"
"00008067 ret\n");
EXPECT_EQ(42, Call(test->entry(), 0));
EXPECT_EQ(43, Call(test->entry(), 1));
EXPECT_EQ(32, Call(test->entry(), 10));
EXPECT_EQ(-43, Call(test->entry(), -1));
EXPECT_EQ(-36, Call(test->entry(), -10));
}
ASSEMBLER_TEST_GENERATE(XorImmediate2, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ xori(A0, A0, -42);
__ ret();
}
ASSEMBLER_TEST_RUN(XorImmediate2, test) {
EXPECT_DISASSEMBLY(
"fd654513 xori a0, a0, -42\n"
"00008067 ret\n");
EXPECT_EQ(-42, Call(test->entry(), 0));
EXPECT_EQ(-41, Call(test->entry(), 1));
EXPECT_EQ(-36, Call(test->entry(), 10));
EXPECT_EQ(41, Call(test->entry(), -1));
EXPECT_EQ(32, Call(test->entry(), -10));
}
ASSEMBLER_TEST_GENERATE(OrImmediate1, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ ori(A0, A0, -6);
__ ret();
}
ASSEMBLER_TEST_RUN(OrImmediate1, test) {
EXPECT_DISASSEMBLY(
"ffa56513 ori a0, a0, -6\n"
"00008067 ret\n");
EXPECT_EQ(-6, Call(test->entry(), 0));
EXPECT_EQ(-5, Call(test->entry(), 1));
EXPECT_EQ(-5, Call(test->entry(), 11));
EXPECT_EQ(-1, Call(test->entry(), -1));
EXPECT_EQ(-1, Call(test->entry(), -11));
}
ASSEMBLER_TEST_GENERATE(OrImmediate2, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ ori(A0, A0, 6);
__ ret();
}
ASSEMBLER_TEST_RUN(OrImmediate2, test) {
EXPECT_DISASSEMBLY(
"00656513 ori a0, a0, 6\n"
"00008067 ret\n");
EXPECT_EQ(6, Call(test->entry(), 0));
EXPECT_EQ(7, Call(test->entry(), 1));
EXPECT_EQ(15, Call(test->entry(), 11));
EXPECT_EQ(-1, Call(test->entry(), -1));
EXPECT_EQ(-9, Call(test->entry(), -11));
}
ASSEMBLER_TEST_GENERATE(AndImmediate1, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ andi(A0, A0, -6);
__ ret();
}
ASSEMBLER_TEST_RUN(AndImmediate1, test) {
EXPECT_DISASSEMBLY(
"ffa57513 andi a0, a0, -6\n"
"00008067 ret\n");
EXPECT_EQ(0, Call(test->entry(), 0));
EXPECT_EQ(0, Call(test->entry(), 1));
EXPECT_EQ(10, Call(test->entry(), 11));
EXPECT_EQ(-6, Call(test->entry(), -1));
EXPECT_EQ(-16, Call(test->entry(), -11));
}
ASSEMBLER_TEST_GENERATE(AndImmediate2, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ andi(A0, A0, 6);
__ ret();
}
ASSEMBLER_TEST_RUN(AndImmediate2, test) {
EXPECT_DISASSEMBLY(
"00657513 andi a0, a0, 6\n"
"00008067 ret\n");
EXPECT_EQ(0, Call(test->entry(), 0));
EXPECT_EQ(0, Call(test->entry(), 1));
EXPECT_EQ(2, Call(test->entry(), 11));
EXPECT_EQ(6, Call(test->entry(), -1));
EXPECT_EQ(4, Call(test->entry(), -11));
}
ASSEMBLER_TEST_GENERATE(ShiftLeftLogicalImmediate, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ slli(A0, A0, 2);
__ ret();
}
ASSEMBLER_TEST_RUN(ShiftLeftLogicalImmediate, test) {
EXPECT_DISASSEMBLY(
"00251513 slli a0, a0, 0x2\n"
"00008067 ret\n");
EXPECT_EQ(84, Call(test->entry(), 21));
EXPECT_EQ(4, Call(test->entry(), 1));
EXPECT_EQ(0, Call(test->entry(), 0));
EXPECT_EQ(-4, Call(test->entry(), -1));
EXPECT_EQ(-84, Call(test->entry(), -21));
}
ASSEMBLER_TEST_GENERATE(ShiftLeftLogicalImmediate2, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ slli(A0, A0, XLEN - 1);
__ ret();
}
ASSEMBLER_TEST_RUN(ShiftLeftLogicalImmediate2, test) {
#if XLEN == 32
EXPECT_DISASSEMBLY(
"01f51513 slli a0, a0, 0x1f\n"
"00008067 ret\n");
#elif XLEN == 64
EXPECT_DISASSEMBLY(
"03f51513 slli a0, a0, 0x3f\n"
"00008067 ret\n");
#endif
EXPECT_EQ(0, Call(test->entry(), 2));
EXPECT_EQ(kMinIntX, Call(test->entry(), 1));
EXPECT_EQ(0, Call(test->entry(), 0));
EXPECT_EQ(kMinIntX, Call(test->entry(), -1));
EXPECT_EQ(0, Call(test->entry(), -2));
}
ASSEMBLER_TEST_GENERATE(ShiftRightLogicalImmediate, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ srli(A0, A0, 2);
__ ret();
}
ASSEMBLER_TEST_RUN(ShiftRightLogicalImmediate, test) {
EXPECT_DISASSEMBLY(
"00255513 srli a0, a0, 0x2\n"
"00008067 ret\n");
EXPECT_EQ(5, Call(test->entry(), 21));
EXPECT_EQ(0, Call(test->entry(), 1));
EXPECT_EQ(0, Call(test->entry(), 0));
EXPECT_EQ(static_cast<intx_t>(static_cast<uintx_t>(-1) >> 2),
Call(test->entry(), -1));
EXPECT_EQ(static_cast<intx_t>(static_cast<uintx_t>(-21) >> 2),
Call(test->entry(), -21));
}
ASSEMBLER_TEST_GENERATE(ShiftRightLogicalImmediate2, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ srli(A0, A0, XLEN - 1);
__ ret();
}
ASSEMBLER_TEST_RUN(ShiftRightLogicalImmediate2, test) {
#if XLEN == 32
EXPECT_DISASSEMBLY(
"01f55513 srli a0, a0, 0x1f\n"
"00008067 ret\n");
#elif XLEN == 64
EXPECT_DISASSEMBLY(
"03f55513 srli a0, a0, 0x3f\n"
"00008067 ret\n");
#endif
EXPECT_EQ(0, Call(test->entry(), 21));
EXPECT_EQ(0, Call(test->entry(), 1));
EXPECT_EQ(0, Call(test->entry(), 0));
EXPECT_EQ(1, Call(test->entry(), -1));
EXPECT_EQ(1, Call(test->entry(), -21));
}
ASSEMBLER_TEST_GENERATE(ShiftRightArithmeticImmediate, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ srai(A0, A0, 2);
__ ret();
}
ASSEMBLER_TEST_RUN(ShiftRightArithmeticImmediate, test) {
EXPECT_DISASSEMBLY(
"40255513 srai a0, a0, 0x2\n"
"00008067 ret\n");
EXPECT_EQ(5, Call(test->entry(), 21));
EXPECT_EQ(0, Call(test->entry(), 1));
EXPECT_EQ(0, Call(test->entry(), 0));
EXPECT_EQ(-1, Call(test->entry(), -1));
EXPECT_EQ(-6, Call(test->entry(), -21));
}
ASSEMBLER_TEST_GENERATE(ShiftRightArithmeticImmediate2, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ srai(A0, A0, XLEN - 1);
__ ret();
}
ASSEMBLER_TEST_RUN(ShiftRightArithmeticImmediate2, test) {
#if XLEN == 32
EXPECT_DISASSEMBLY(
"41f55513 srai a0, a0, 0x1f\n" // CHECK
"00008067 ret\n");
#elif XLEN == 64
EXPECT_DISASSEMBLY(
"43f55513 srai a0, a0, 0x3f\n" // CHECK
"00008067 ret\n");
#endif
EXPECT_EQ(0, Call(test->entry(), 21));
EXPECT_EQ(0, Call(test->entry(), 1));
EXPECT_EQ(0, Call(test->entry(), 0));
EXPECT_EQ(-1, Call(test->entry(), -1));
EXPECT_EQ(-1, Call(test->entry(), -21));
}
ASSEMBLER_TEST_GENERATE(Add, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ add(A0, A0, A1);
__ ret();
}
ASSEMBLER_TEST_RUN(Add, test) {
EXPECT_DISASSEMBLY(
"00b50533 add a0, a0, a1\n"
"00008067 ret\n");
EXPECT_EQ(24, Call(test->entry(), 7, 17));
EXPECT_EQ(-10, Call(test->entry(), 7, -17));
EXPECT_EQ(10, Call(test->entry(), -7, 17));
EXPECT_EQ(-24, Call(test->entry(), -7, -17));
EXPECT_EQ(24, Call(test->entry(), 17, 7));
EXPECT_EQ(10, Call(test->entry(), 17, -7));
EXPECT_EQ(-10, Call(test->entry(), -17, 7));
EXPECT_EQ(-24, Call(test->entry(), -17, -7));
}
ASSEMBLER_TEST_GENERATE(Subtract, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ sub(A0, A0, A1);
__ ret();
}
ASSEMBLER_TEST_RUN(Subtract, test) {
EXPECT_DISASSEMBLY(
"40b50533 sub a0, a0, a1\n"
"00008067 ret\n");
EXPECT_EQ(-10, Call(test->entry(), 7, 17));
EXPECT_EQ(24, Call(test->entry(), 7, -17));
EXPECT_EQ(-24, Call(test->entry(), -7, 17));
EXPECT_EQ(10, Call(test->entry(), -7, -17));
EXPECT_EQ(10, Call(test->entry(), 17, 7));
EXPECT_EQ(24, Call(test->entry(), 17, -7));
EXPECT_EQ(-24, Call(test->entry(), -17, 7));
EXPECT_EQ(-10, Call(test->entry(), -17, -7));
}
ASSEMBLER_TEST_GENERATE(ShiftLeftLogical, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ sll(A0, A0, A1);
__ ret();
}
ASSEMBLER_TEST_RUN(ShiftLeftLogical, test) {
EXPECT_DISASSEMBLY(
"00b51533 sll a0, a0, a1\n"
"00008067 ret\n");
EXPECT_EQ(2176, Call(test->entry(), 17, 7));
EXPECT_EQ(-2176, Call(test->entry(), -17, 7));
EXPECT_EQ(34, Call(test->entry(), 17, 1));
EXPECT_EQ(-34, Call(test->entry(), -17, 1));
EXPECT_EQ(17, Call(test->entry(), 17, 0));
EXPECT_EQ(-17, Call(test->entry(), -17, 0));
}
ASSEMBLER_TEST_GENERATE(SetLessThan, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ slt(A0, A0, A1);
__ ret();
}
ASSEMBLER_TEST_RUN(SetLessThan, test) {
EXPECT_DISASSEMBLY(
"00b52533 slt a0, a0, a1\n"
"00008067 ret\n");
EXPECT_EQ(0, Call(test->entry(), 7, 7));
EXPECT_EQ(0, Call(test->entry(), -7, -7));
EXPECT_EQ(1, Call(test->entry(), 7, 17));
EXPECT_EQ(0, Call(test->entry(), 7, -17));
EXPECT_EQ(1, Call(test->entry(), -7, 17));
EXPECT_EQ(0, Call(test->entry(), -7, -17));
EXPECT_EQ(0, Call(test->entry(), 17, 7));
EXPECT_EQ(0, Call(test->entry(), 17, -7));
EXPECT_EQ(1, Call(test->entry(), -17, 7));
EXPECT_EQ(1, Call(test->entry(), -17, -7));
}
ASSEMBLER_TEST_GENERATE(SetLessThanUnsigned, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ sltu(A0, A0, A1);
__ ret();
}
ASSEMBLER_TEST_RUN(SetLessThanUnsigned, test) {
EXPECT_DISASSEMBLY(
"00b53533 sltu a0, a0, a1\n"
"00008067 ret\n");
EXPECT_EQ(0, Call(test->entry(), 7, 7));
EXPECT_EQ(0, Call(test->entry(), -7, -7));
EXPECT_EQ(1, Call(test->entry(), 7, 17));
EXPECT_EQ(1, Call(test->entry(), 7, -17));
EXPECT_EQ(0, Call(test->entry(), -7, 17));
EXPECT_EQ(0, Call(test->entry(), -7, -17));
EXPECT_EQ(0, Call(test->entry(), 17, 7));
EXPECT_EQ(1, Call(test->entry(), 17, -7));
EXPECT_EQ(0, Call(test->entry(), -17, 7));
EXPECT_EQ(1, Call(test->entry(), -17, -7));
}
ASSEMBLER_TEST_GENERATE(Xor, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ xor_(A0, A0, A1);
__ ret();
}
ASSEMBLER_TEST_RUN(Xor, test) {
EXPECT_DISASSEMBLY(
"00b54533 xor a0, a0, a1\n"
"00008067 ret\n");
EXPECT_EQ(22, Call(test->entry(), 7, 17));
EXPECT_EQ(-24, Call(test->entry(), 7, -17));
EXPECT_EQ(-24, Call(test->entry(), -7, 17));
EXPECT_EQ(22, Call(test->entry(), -7, -17));
EXPECT_EQ(22, Call(test->entry(), 17, 7));
EXPECT_EQ(-24, Call(test->entry(), 17, -7));
EXPECT_EQ(-24, Call(test->entry(), -17, 7));
EXPECT_EQ(22, Call(test->entry(), -17, -7));
}
ASSEMBLER_TEST_GENERATE(ShiftRightLogical, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ srl(A0, A0, A1);
__ ret();
}
ASSEMBLER_TEST_RUN(ShiftRightLogical, test) {
EXPECT_DISASSEMBLY(
"00b55533 srl a0, a0, a1\n"
"00008067 ret\n");
EXPECT_EQ(0, Call(test->entry(), 17, 7));
EXPECT_EQ(static_cast<intx_t>(static_cast<uintx_t>(-17) >> 7),
Call(test->entry(), -17, 7));
EXPECT_EQ(8, Call(test->entry(), 17, 1));
EXPECT_EQ(static_cast<intx_t>(static_cast<uintx_t>(-17) >> 1),
Call(test->entry(), -17, 1));
EXPECT_EQ(17, Call(test->entry(), 17, 0));
EXPECT_EQ(-17, Call(test->entry(), -17, 0));
}
ASSEMBLER_TEST_GENERATE(ShiftRightArithmetic, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ sra(A0, A0, A1);
__ ret();
}
ASSEMBLER_TEST_RUN(ShiftRightArithmetic, test) {
EXPECT_DISASSEMBLY(
"40b55533 sra a0, a0, a1\n"
"00008067 ret\n");
EXPECT_EQ(0, Call(test->entry(), 17, 7));
EXPECT_EQ(-1, Call(test->entry(), -17, 7));
EXPECT_EQ(8, Call(test->entry(), 17, 1));
EXPECT_EQ(-9, Call(test->entry(), -17, 1));
EXPECT_EQ(17, Call(test->entry(), 17, 0));
EXPECT_EQ(-17, Call(test->entry(), -17, 0));
}
ASSEMBLER_TEST_GENERATE(Or, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ or_(A0, A0, A1);
__ ret();
}
ASSEMBLER_TEST_RUN(Or, test) {
EXPECT_DISASSEMBLY(
"00b56533 or a0, a0, a1\n"
"00008067 ret\n");
EXPECT_EQ(23, Call(test->entry(), 7, 17));
EXPECT_EQ(-17, Call(test->entry(), 7, -17));
EXPECT_EQ(-7, Call(test->entry(), -7, 17));
EXPECT_EQ(-1, Call(test->entry(), -7, -17));
EXPECT_EQ(23, Call(test->entry(), 17, 7));
EXPECT_EQ(-7, Call(test->entry(), 17, -7));
EXPECT_EQ(-17, Call(test->entry(), -17, 7));
EXPECT_EQ(-1, Call(test->entry(), -17, -7));
}
ASSEMBLER_TEST_GENERATE(And, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ and_(A0, A0, A1);
__ ret();
}
ASSEMBLER_TEST_RUN(And, test) {
EXPECT_DISASSEMBLY(
"00b57533 and a0, a0, a1\n"
"00008067 ret\n");
EXPECT_EQ(1, Call(test->entry(), 7, 17));
EXPECT_EQ(7, Call(test->entry(), 7, -17));
EXPECT_EQ(17, Call(test->entry(), -7, 17));
EXPECT_EQ(-23, Call(test->entry(), -7, -17));
EXPECT_EQ(1, Call(test->entry(), 17, 7));
EXPECT_EQ(17, Call(test->entry(), 17, -7));
EXPECT_EQ(7, Call(test->entry(), -17, 7));
EXPECT_EQ(-23, Call(test->entry(), -17, -7));
}
ASSEMBLER_TEST_GENERATE(Fence, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ fence();
__ fence(kRead, kWrite);
__ fence(kInput, kOutput);
__ fence(kMemory, kMemory);
__ fence(kAll, kAll);
__ ret();
}
ASSEMBLER_TEST_RUN(Fence, test) {
EXPECT_DISASSEMBLY(
"0ff0000f fence\n"
"0210000f fence r,w\n"
"0840000f fence i,o\n"
"0330000f fence rw,rw\n"
"0ff0000f fence\n"
"00008067 ret\n");
Call(test->entry());
}
ASSEMBLER_TEST_GENERATE(InstructionFence, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ fencei();
__ ret();
}
ASSEMBLER_TEST_RUN(InstructionFence, test) {
EXPECT_DISASSEMBLY(
"0000100f fence.i\n"
"00008067 ret\n");
Call(test->entry());
}
ASSEMBLER_TEST_GENERATE(EnvironmentCall, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ ecall();
__ ret();
}
ASSEMBLER_TEST_RUN(EnvironmentCall, test) {
EXPECT_DISASSEMBLY(
"00000073 ecall\n"
"00008067 ret\n");
// Not running: would trap.
}
ASSEMBLER_TEST_GENERATE(EnvironmentBreak, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ ebreak();
__ ret();
}
ASSEMBLER_TEST_RUN(EnvironmentBreak, test) {
EXPECT_DISASSEMBLY(
"00100073 ebreak\n"
"00008067 ret\n");
// Not running: would trap.
}
ASSEMBLER_TEST_GENERATE(ControlStatusRegisters, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ csrrw(T0, 0x123, S1);
__ csrrs(T1, 0x123, S2);
__ csrrc(T2, 0x123, S3);
__ csrr(T3, 0x123);
__ csrw(0x123, S4);
__ csrs(0x123, S5);
__ csrc(0x123, S6);
__ csrrwi(T1, 0x123, 1);
__ csrrsi(T2, 0x123, 2);
__ csrrci(T3, 0x123, 3);
__ csrwi(0x123, 4);
__ csrsi(0x123, 5);
__ csrci(0x123, 6);
__ ret();
}
ASSEMBLER_TEST_RUN(ControlStatusRegisters, test) {
EXPECT_DISASSEMBLY(
"123492f3 csrrw t0, 0x123, thr\n"
"12392373 csrrs t1, 0x123, s2\n"
"1239b3f3 csrrc t2, 0x123, s3\n"
"12302e73 csrr t3, 0x123\n"
"123a1073 csrw 0x123, s4\n"
"123aa073 csrs 0x123, s5\n"
"123b3073 csrc 0x123, s6\n"
"1230d373 csrrwi t1, 0x123, 1\n"
"123163f3 csrrsi t2, 0x123, 2\n"
"1231fe73 csrrci t3, 0x123, 3\n"
"12325073 csrwi 0x123, 4\n"
"1232e073 csrsi 0x123, 5\n"
"12337073 csrci 0x123, 6\n"
"00008067 ret\n");
// Not running: would trap.
}
ASSEMBLER_TEST_GENERATE(Nop, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ nop();
__ ret();
}
ASSEMBLER_TEST_RUN(Nop, test) {
EXPECT_DISASSEMBLY(
"00000013 nop\n"
"00008067 ret\n");
EXPECT_EQ(123, Call(test->entry(), 123));
}
ASSEMBLER_TEST_GENERATE(Move, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ mv(A0, A1);
__ ret();
}
ASSEMBLER_TEST_RUN(Move, test) {
EXPECT_DISASSEMBLY(
"00058513 mv a0, a1\n"
"00008067 ret\n");
EXPECT_EQ(36, Call(test->entry(), 42, 36));
}
ASSEMBLER_TEST_GENERATE(Not, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ not_(A0, A0);
__ ret();
}
ASSEMBLER_TEST_RUN(Not, test) {
EXPECT_DISASSEMBLY(
"fff54513 not a0, a0\n"
"00008067 ret\n");
EXPECT_EQ(~42, Call(test->entry(), 42));
EXPECT_EQ(~-42, Call(test->entry(), -42));
}
ASSEMBLER_TEST_GENERATE(Negate, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ neg(A0, A0);
__ ret();
}
ASSEMBLER_TEST_RUN(Negate, test) {
EXPECT_DISASSEMBLY(
"40a00533 neg a0, a0\n"
"00008067 ret\n");
EXPECT_EQ(-42, Call(test->entry(), 42));
EXPECT_EQ(42, Call(test->entry(), -42));
}
ASSEMBLER_TEST_GENERATE(SetNotEqualToZero, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ snez(A0, A0);
__ ret();
}
ASSEMBLER_TEST_RUN(SetNotEqualToZero, test) {
EXPECT_DISASSEMBLY(
"00a03533 snez a0, a0\n"
"00008067 ret\n");
EXPECT_EQ(1, Call(test->entry(), -42));
EXPECT_EQ(0, Call(test->entry(), 0));
EXPECT_EQ(1, Call(test->entry(), 42));
}
ASSEMBLER_TEST_GENERATE(SetEqualToZero, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ seqz(A0, A0);
__ ret();
}
ASSEMBLER_TEST_RUN(SetEqualToZero, test) {
EXPECT_DISASSEMBLY(
"00153513 seqz a0, a0\n"
"00008067 ret\n");
EXPECT_EQ(0, Call(test->entry(), -42));
EXPECT_EQ(1, Call(test->entry(), 0));
EXPECT_EQ(0, Call(test->entry(), 42));
}
ASSEMBLER_TEST_GENERATE(SetLessThanZero, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ sltz(A0, A0);
__ ret();
}
ASSEMBLER_TEST_RUN(SetLessThanZero, test) {
EXPECT_DISASSEMBLY(
"00052533 sltz a0, a0\n"
"00008067 ret\n");
EXPECT_EQ(1, Call(test->entry(), -42));
EXPECT_EQ(0, Call(test->entry(), 0));
EXPECT_EQ(0, Call(test->entry(), 42));
}
ASSEMBLER_TEST_GENERATE(SetGreaterThanZero, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ sgtz(A0, A0);
__ ret();
}
ASSEMBLER_TEST_RUN(SetGreaterThanZero, test) {
EXPECT_DISASSEMBLY(
"00a02533 sgtz a0, a0\n"
"00008067 ret\n");
EXPECT_EQ(0, Call(test->entry(), -42));
EXPECT_EQ(0, Call(test->entry(), 0));
EXPECT_EQ(1, Call(test->entry(), 42));
}
ASSEMBLER_TEST_GENERATE(BranchEqualZero, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
Label label;
__ beqz(A0, &label);
__ li(A0, 3);
__ ret();
__ Bind(&label);
__ li(A0, 4);
__ ret();
}
ASSEMBLER_TEST_RUN(BranchEqualZero, test) {
EXPECT_DISASSEMBLY(
"00050663 beqz a0, +12\n"
"00300513 li a0, 3\n"
"00008067 ret\n"
"00400513 li a0, 4\n"
"00008067 ret\n");
EXPECT_EQ(3, Call(test->entry(), -42));
EXPECT_EQ(4, Call(test->entry(), 0));
EXPECT_EQ(3, Call(test->entry(), 42));
}
ASSEMBLER_TEST_GENERATE(BranchNotEqualZero, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
Label label;
__ bnez(A0, &label);
__ li(A0, 3);
__ ret();
__ Bind(&label);
__ li(A0, 4);
__ ret();
}
ASSEMBLER_TEST_RUN(BranchNotEqualZero, test) {
EXPECT_DISASSEMBLY(
"00051663 bnez a0, +12\n"
"00300513 li a0, 3\n"
"00008067 ret\n"
"00400513 li a0, 4\n"
"00008067 ret\n");
EXPECT_EQ(4, Call(test->entry(), -42));
EXPECT_EQ(3, Call(test->entry(), 0));
EXPECT_EQ(4, Call(test->entry(), 42));
}
ASSEMBLER_TEST_GENERATE(BranchLessOrEqualZero, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
Label label;
__ blez(A0, &label);
__ li(A0, 3);
__ ret();
__ Bind(&label);
__ li(A0, 4);
__ ret();
}
ASSEMBLER_TEST_RUN(BranchLessOrEqualZero, test) {
EXPECT_DISASSEMBLY(
"00a05663 blez a0, +12\n"
"00300513 li a0, 3\n"
"00008067 ret\n"
"00400513 li a0, 4\n"
"00008067 ret\n");
EXPECT_EQ(4, Call(test->entry(), -42));
EXPECT_EQ(4, Call(test->entry(), 0));
EXPECT_EQ(3, Call(test->entry(), 42));
}
ASSEMBLER_TEST_GENERATE(BranchGreaterOrEqualZero, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
Label label;
__ bgez(A0, &label);
__ li(A0, 3);
__ ret();
__ Bind(&label);
__ li(A0, 4);
__ ret();
}
ASSEMBLER_TEST_RUN(BranchGreaterOrEqualZero, test) {
EXPECT_DISASSEMBLY(
"00055663 bgez a0, +12\n"
"00300513 li a0, 3\n"
"00008067 ret\n"
"00400513 li a0, 4\n"
"00008067 ret\n");
EXPECT_EQ(3, Call(test->entry(), -42));
EXPECT_EQ(4, Call(test->entry(), 0));
EXPECT_EQ(4, Call(test->entry(), 42));
}
ASSEMBLER_TEST_GENERATE(BranchLessThanZero, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
Label label;
__ bltz(A0, &label);
__ li(A0, 3);
__ ret();
__ Bind(&label);
__ li(A0, 4);
__ ret();
}
ASSEMBLER_TEST_RUN(BranchLessThanZero, test) {
EXPECT_DISASSEMBLY(
"00054663 bltz a0, +12\n"
"00300513 li a0, 3\n"
"00008067 ret\n"
"00400513 li a0, 4\n"
"00008067 ret\n");
EXPECT_EQ(4, Call(test->entry(), -42));
EXPECT_EQ(3, Call(test->entry(), 0));
EXPECT_EQ(3, Call(test->entry(), 42));
}
ASSEMBLER_TEST_GENERATE(BranchGreaterThanZero, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
Label label;
__ bgtz(A0, &label);
__ li(A0, 3);
__ ret();
__ Bind(&label);
__ li(A0, 4);
__ ret();
}
ASSEMBLER_TEST_RUN(BranchGreaterThanZero, test) {
EXPECT_DISASSEMBLY(
"00a04663 bgtz a0, +12\n"
"00300513 li a0, 3\n"
"00008067 ret\n"
"00400513 li a0, 4\n"
"00008067 ret\n");
EXPECT_EQ(3, Call(test->entry(), -42));
EXPECT_EQ(3, Call(test->entry(), 0));
EXPECT_EQ(4, Call(test->entry(), 42));
}
#if XLEN >= 64
ASSEMBLER_TEST_GENERATE(AddImmediateWord1, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ addiw(A0, A0, 42);
__ ret();
}
ASSEMBLER_TEST_RUN(AddImmediateWord1, test) {
EXPECT_DISASSEMBLY(
"02a5051b addiw a0, a0, 42\n"
"00008067 ret\n");
EXPECT_EQ(42, Call(test->entry(), 0));
EXPECT_EQ(40, Call(test->entry(), -2));
EXPECT_EQ(0, Call(test->entry(), -42));
}
ASSEMBLER_TEST_GENERATE(AddImmediateWord2, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ addiw(A0, A0, -42);
__ ret();
}
ASSEMBLER_TEST_RUN(AddImmediateWord2, test) {
EXPECT_DISASSEMBLY(
"fd65051b addiw a0, a0, -42\n"
"00008067 ret\n");
EXPECT_EQ(-42, Call(test->entry(), 0));
EXPECT_EQ(-44, Call(test->entry(), -2));
EXPECT_EQ(38, Call(test->entry(), 80));
}
ASSEMBLER_TEST_GENERATE(ShiftLeftLogicalImmediateWord, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ slliw(A0, A0, 2);
__ ret();
}
ASSEMBLER_TEST_RUN(ShiftLeftLogicalImmediateWord, test) {
EXPECT_DISASSEMBLY(
"0025151b slliw a0, a0, 0x2\n"
"00008067 ret\n");
EXPECT_EQ(84, Call(test->entry(), 21));
EXPECT_EQ(4, Call(test->entry(), 1));
EXPECT_EQ(0, Call(test->entry(), 0));
EXPECT_EQ(-4, Call(test->entry(), -1));
EXPECT_EQ(-84, Call(test->entry(), -21));
}
ASSEMBLER_TEST_GENERATE(ShiftRightLogicalImmediateWord, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ srliw(A0, A0, 2);
__ ret();
}
ASSEMBLER_TEST_RUN(ShiftRightLogicalImmediateWord, test) {
EXPECT_DISASSEMBLY(
"0025551b srliw a0, a0, 0x2\n"
"00008067 ret\n");
EXPECT_EQ(5, Call(test->entry(), 21));
EXPECT_EQ(0, Call(test->entry(), 1));
EXPECT_EQ(0, Call(test->entry(), 0));
EXPECT_EQ(sign_extend(static_cast<uint32_t>(-1) >> 2),
Call(test->entry(), -1));
EXPECT_EQ(sign_extend(static_cast<uint32_t>(-21) >> 2),
Call(test->entry(), -21));
}
ASSEMBLER_TEST_GENERATE(ShiftRightArithmeticImmediateWord, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ sraiw(A0, A0, 2);
__ ret();
}
ASSEMBLER_TEST_RUN(ShiftRightArithmeticImmediateWord, test) {
EXPECT_DISASSEMBLY(
"4025551b sraiw a0, a0, 0x2\n"
"00008067 ret\n");
EXPECT_EQ(5, Call(test->entry(), 21));
EXPECT_EQ(0, Call(test->entry(), 1));
EXPECT_EQ(0, Call(test->entry(), 0));
EXPECT_EQ(-1, Call(test->entry(), -1));
EXPECT_EQ(-6, Call(test->entry(), -21));
}
ASSEMBLER_TEST_GENERATE(AddWord, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ addw(A0, A0, A1);
__ ret();
}
ASSEMBLER_TEST_RUN(AddWord, test) {
EXPECT_DISASSEMBLY(
"00b5053b addw a0, a0, a1\n"
"00008067 ret\n");
EXPECT_EQ(24, Call(test->entry(), 7, 17));
EXPECT_EQ(-10, Call(test->entry(), 7, -17));
EXPECT_EQ(10, Call(test->entry(), -7, 17));
EXPECT_EQ(-24, Call(test->entry(), -7, -17));
EXPECT_EQ(24, Call(test->entry(), 17, 7));
EXPECT_EQ(10, Call(test->entry(), 17, -7));
EXPECT_EQ(-10, Call(test->entry(), -17, 7));
EXPECT_EQ(-24, Call(test->entry(), -17, -7));
EXPECT_EQ(3, Call(test->entry(), 0x200000002, 0x100000001));
}
ASSEMBLER_TEST_GENERATE(SubtractWord, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ subw(A0, A0, A1);
__ ret();
}
ASSEMBLER_TEST_RUN(SubtractWord, test) {
EXPECT_DISASSEMBLY(
"40b5053b subw a0, a0, a1\n"
"00008067 ret\n");
EXPECT_EQ(-10, Call(test->entry(), 7, 17));
EXPECT_EQ(24, Call(test->entry(), 7, -17));
EXPECT_EQ(-24, Call(test->entry(), -7, 17));
EXPECT_EQ(10, Call(test->entry(), -7, -17));
EXPECT_EQ(10, Call(test->entry(), 17, 7));
EXPECT_EQ(24, Call(test->entry(), 17, -7));
EXPECT_EQ(-24, Call(test->entry(), -17, 7));
EXPECT_EQ(-10, Call(test->entry(), -17, -7));
EXPECT_EQ(1, Call(test->entry(), 0x200000002, 0x100000001));
}
ASSEMBLER_TEST_GENERATE(ShiftLeftLogicalWord, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ sllw(A0, A0, A1);
__ ret();
}
ASSEMBLER_TEST_RUN(ShiftLeftLogicalWord, test) {
EXPECT_DISASSEMBLY(
"00b5153b sllw a0, a0, a1\n"
"00008067 ret\n");
EXPECT_EQ(2176, Call(test->entry(), 17, 7));
EXPECT_EQ(-2176, Call(test->entry(), -17, 7));
EXPECT_EQ(34, Call(test->entry(), 17, 1));
EXPECT_EQ(-34, Call(test->entry(), -17, 1));
EXPECT_EQ(17, Call(test->entry(), 17, 0));
EXPECT_EQ(-17, Call(test->entry(), -17, 0));
EXPECT_EQ(0x10, Call(test->entry(), 0x10000001, 4));
}
ASSEMBLER_TEST_GENERATE(ShiftRightLogicalWord, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ srlw(A0, A0, A1);
__ ret();
}
ASSEMBLER_TEST_RUN(ShiftRightLogicalWord, test) {
EXPECT_DISASSEMBLY(
"00b5553b srlw a0, a0, a1\n"
"00008067 ret\n");
EXPECT_EQ(0, Call(test->entry(), 17, 7));
EXPECT_EQ(sign_extend(static_cast<uint32_t>(-17) >> 7),
Call(test->entry(), -17, 7));
EXPECT_EQ(8, Call(test->entry(), 17, 1));
EXPECT_EQ(sign_extend(static_cast<uint32_t>(-17) >> 1),
Call(test->entry(), -17, 1));
EXPECT_EQ(17, Call(test->entry(), 17, 0));
EXPECT_EQ(-17, Call(test->entry(), -17, 0));
}
ASSEMBLER_TEST_GENERATE(ShiftRightArithmeticWord, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ sraw(A0, A0, A1);
__ ret();
}
ASSEMBLER_TEST_RUN(ShiftRightArithmeticWord, test) {
EXPECT_DISASSEMBLY(
"40b5553b sraw a0, a0, a1\n"
"00008067 ret\n");
EXPECT_EQ(0, Call(test->entry(), 17, 7));
EXPECT_EQ(-1, Call(test->entry(), -17, 7));
EXPECT_EQ(8, Call(test->entry(), 17, 1));
EXPECT_EQ(-9, Call(test->entry(), -17, 1));
EXPECT_EQ(17, Call(test->entry(), 17, 0));
EXPECT_EQ(-17, Call(test->entry(), -17, 0));
}
ASSEMBLER_TEST_GENERATE(NegateWord, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ negw(A0, A0);
__ ret();
}
ASSEMBLER_TEST_RUN(NegateWord, test) {
EXPECT_DISASSEMBLY(
"40a0053b negw a0, a0\n"
"00008067 ret\n");
EXPECT_EQ(0, Call(test->entry(), 0));
EXPECT_EQ(-42, Call(test->entry(), 42));
EXPECT_EQ(42, Call(test->entry(), -42));
EXPECT_EQ(1, Call(test->entry(), 0x10FFFFFFFF));
}
ASSEMBLER_TEST_GENERATE(SignExtendWord, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ sextw(A0, A0);
__ ret();
}
ASSEMBLER_TEST_RUN(SignExtendWord, test) {
EXPECT_DISASSEMBLY(
"0005051b sext.w a0, a0\n"
"00008067 ret\n");
EXPECT_EQ(0, Call(test->entry(), 0));
EXPECT_EQ(42, Call(test->entry(), 42));
EXPECT_EQ(-42, Call(test->entry(), -42));
EXPECT_EQ(-1, Call(test->entry(), 0x10FFFFFFFF));
}
#endif // XLEN >= 64
ASSEMBLER_TEST_GENERATE(Multiply, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ mul(A0, A0, A1);
__ ret();
}
ASSEMBLER_TEST_RUN(Multiply, test) {
EXPECT_DISASSEMBLY(
"02b50533 mul a0, a0, a1\n"
"00008067 ret\n");
EXPECT_EQ(68, Call(test->entry(), 4, 17));
EXPECT_EQ(-68, Call(test->entry(), -4, 17));
EXPECT_EQ(-68, Call(test->entry(), 4, -17));
EXPECT_EQ(68, Call(test->entry(), -4, -17));
EXPECT_EQ(68, Call(test->entry(), 17, 4));
EXPECT_EQ(-68, Call(test->entry(), -17, 4));
EXPECT_EQ(-68, Call(test->entry(), 17, -4));
EXPECT_EQ(68, Call(test->entry(), -17, -4));
}
ASSEMBLER_TEST_GENERATE(MultiplyHigh, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ mulh(A0, A0, A1);
__ ret();
}
ASSEMBLER_TEST_RUN(MultiplyHigh, test) {
EXPECT_DISASSEMBLY(
"02b51533 mulh a0, a0, a1\n"
"00008067 ret\n");
EXPECT_EQ(0, Call(test->entry(), 4, 17));
EXPECT_EQ(-1, Call(test->entry(), -4, 17));
EXPECT_EQ(-1, Call(test->entry(), 4, -17));
EXPECT_EQ(0, Call(test->entry(), -4, -17));
EXPECT_EQ(0, Call(test->entry(), 17, 4));
EXPECT_EQ(-1, Call(test->entry(), -17, 4));
EXPECT_EQ(-1, Call(test->entry(), 17, -4));
EXPECT_EQ(0, Call(test->entry(), -17, -4));
}
ASSEMBLER_TEST_GENERATE(MultiplyHighSignedUnsigned, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ mulhsu(A0, A0, A1);
__ ret();
}
ASSEMBLER_TEST_RUN(MultiplyHighSignedUnsigned, test) {
EXPECT_DISASSEMBLY(
"02b52533 mulhsu a0, a0, a1\n"
"00008067 ret\n");
EXPECT_EQ(0, Call(test->entry(), 4, 17));
EXPECT_EQ(-1, Call(test->entry(), -4, 17));
EXPECT_EQ(3, Call(test->entry(), 4, -17));
EXPECT_EQ(-4, Call(test->entry(), -4, -17));
EXPECT_EQ(0, Call(test->entry(), 17, 4));
EXPECT_EQ(-1, Call(test->entry(), -17, 4));
EXPECT_EQ(16, Call(test->entry(), 17, -4));
EXPECT_EQ(-17, Call(test->entry(), -17, -4));
}
ASSEMBLER_TEST_GENERATE(MultiplyHighUnsigned, assembler) {
FLAG_use_compressed_instructions = false;
__ SetExtensions(RV_G);
__ mulhu(A0, A0, A1);
__ ret();
}
ASSEMBLER_TEST_RUN(MultiplyHighUnsigned, test) {
EXPECT_DISASSEMBLY(
"02b53533 mulhu a0, a0, a1\n"
"00008067 ret\n");
EXPECT_EQ(0, Call(test->entry(), 4, 17));
EXPECT_EQ(16, Call(test->entry(), -4, 17));
EXPECT_EQ(3, Call(test->entry(), 4, -17));
EXPECT_EQ(-21, Call(test->entry(), -4, -17));
EXPECT_EQ(0, Call(test->entry(), 17, 4));
EXPECT_EQ(3, Call(test->entry(), -17, 4));
EXPECT_EQ(16, Call(test->entry(), 17, -4));
EXPECT_EQ(-21, Call(test->entry(), -17