7973eacdd0
We now have a mode where the simulator is available but not always used. TEST=ci Change-Id: If271f334150e2a125a014a4baa2e03d726300d35 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/435562 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Slava Egorov <vegorov@google.com>
9327 lines
292 KiB
C++
9327 lines
292 KiB
C++
// 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/compiler/assembler/assembler_test.h"
|
|
#include "vm/compiler/backend/locations.h"
|
|
#include "vm/cpu.h"
|
|
#include "vm/os.h"
|
|
#include "vm/unit_test.h"
|
|
#include "vm/virtual_memory.h"
|
|
#include "vm/zone_text_buffer.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);
|
|
__ RestorePinnedRegisters(); // Setup WRITE_BARRIER_STATE.
|
|
|
|
__ 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(DART_INCLUDE_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(DART_INCLUDE_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(DART_INCLUDE_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(DART_INCLUDE_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(DART_INCLUDE_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(DART_INCLUDE_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(DART_INCLUDE_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(DART_INCLUDE_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(DART_INCLUDE_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(DART_INCLUDE_SIMULATOR)
|
|
return Simulator::Current()->CallD(entry, arg0);
|
|
#else
|
|
typedef double (*F)(intx_t);
|
|
return reinterpret_cast<F>(entry)(arg0);
|
|
#endif
|
|
}
|
|
#if XLEN == 32
|
|
static double CallD(intx_t entry, int64_t arg0) {
|
|
#if defined(DART_INCLUDE_SIMULATOR)
|
|
return Simulator::Current()->CallD(entry, arg0);
|
|
#else
|
|
typedef double (*F)(int64_t);
|
|
return reinterpret_cast<F>(entry)(arg0);
|
|
#endif
|
|
}
|
|
#endif
|
|
static double CallD(intx_t entry, intx_t arg0, double arg1) {
|
|
#if defined(DART_INCLUDE_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(DART_INCLUDE_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(DART_INCLUDE_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(DART_INCLUDE_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(DART_INCLUDE_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(DART_INCLUDE_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(DART_INCLUDE_SIMULATOR)
|
|
return Simulator::Current()->CallI(entry, arg0, arg1);
|
|
#else
|
|
typedef intx_t (*F)(double, double);
|
|
return reinterpret_cast<F>(entry)(arg0, arg1);
|
|
#endif
|
|
}
|
|
#if XLEN == 32
|
|
static int64_t CallI64(intx_t entry, double arg0, double arg1 = 0.0) {
|
|
#if defined(DART_INCLUDE_SIMULATOR)
|
|
return Simulator::Current()->CallI64(entry, arg0, arg1);
|
|
#else
|
|
typedef int64_t (*F)(double, double);
|
|
return reinterpret_cast<F>(entry)(arg0, arg1);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
ASSEMBLER_TEST_GENERATE(LoadUpperImmediate, assembler) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ SetExtensions(RV_G);
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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) {
|
|
__ 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, -4));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(Divide, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ div(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(Divide, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"02b54533 div a0, a0, a1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0, Call(test->entry(), 4, 17));
|
|
EXPECT_EQ(0, Call(test->entry(), -4, 17));
|
|
EXPECT_EQ(0, Call(test->entry(), 4, -17));
|
|
EXPECT_EQ(0, Call(test->entry(), -4, -17));
|
|
EXPECT_EQ(4, Call(test->entry(), 17, 4));
|
|
EXPECT_EQ(-4, Call(test->entry(), -17, 4));
|
|
EXPECT_EQ(-4, Call(test->entry(), 17, -4));
|
|
EXPECT_EQ(4, Call(test->entry(), -17, -4));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DivideUnsigned, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ divu(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DivideUnsigned, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"02b55533 divu a0, a0, a1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0, Call(test->entry(), 4, 17));
|
|
#if XLEN == 32
|
|
EXPECT_EQ(252645134, Call(test->entry(), -4, 17));
|
|
#else
|
|
EXPECT_EQ(1085102592571150094, Call(test->entry(), -4, 17));
|
|
#endif
|
|
EXPECT_EQ(0, Call(test->entry(), 4, -17));
|
|
EXPECT_EQ(1, Call(test->entry(), -4, -17));
|
|
EXPECT_EQ(4, Call(test->entry(), 17, 4));
|
|
#if XLEN == 32
|
|
EXPECT_EQ(1073741819, Call(test->entry(), -17, 4));
|
|
#else
|
|
EXPECT_EQ(4611686018427387899, Call(test->entry(), -17, 4));
|
|
#endif
|
|
EXPECT_EQ(0, Call(test->entry(), 17, -4));
|
|
EXPECT_EQ(0, Call(test->entry(), -17, -4));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(Remainder, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ rem(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(Remainder, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"02b56533 rem a0, a0, a1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(4, Call(test->entry(), 4, 17));
|
|
EXPECT_EQ(-4, Call(test->entry(), -4, 17));
|
|
EXPECT_EQ(4, Call(test->entry(), 4, -17));
|
|
EXPECT_EQ(-4, Call(test->entry(), -4, -17));
|
|
EXPECT_EQ(1, Call(test->entry(), 17, 4));
|
|
EXPECT_EQ(-1, Call(test->entry(), -17, 4));
|
|
EXPECT_EQ(1, Call(test->entry(), 17, -4));
|
|
EXPECT_EQ(-1, Call(test->entry(), -17, -4));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(RemainderUnsigned, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ remu(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(RemainderUnsigned, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"02b57533 remu a0, a0, a1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(4, Call(test->entry(), 4, 17));
|
|
EXPECT_EQ(14, Call(test->entry(), -4, 17));
|
|
EXPECT_EQ(4, Call(test->entry(), 4, -17));
|
|
EXPECT_EQ(13, Call(test->entry(), -4, -17));
|
|
EXPECT_EQ(1, Call(test->entry(), 17, 4));
|
|
EXPECT_EQ(3, Call(test->entry(), -17, 4));
|
|
EXPECT_EQ(17, Call(test->entry(), 17, -4));
|
|
EXPECT_EQ(-17, Call(test->entry(), -17, -4));
|
|
}
|
|
|
|
#if XLEN >= 64
|
|
ASSEMBLER_TEST_GENERATE(MultiplyWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ mulw(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(MultiplyWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"02b5053b mulw 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(DivideWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ divw(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DivideWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"02b5453b divw a0, a0, a1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0, Call(test->entry(), 4, 17));
|
|
EXPECT_EQ(0, Call(test->entry(), -4, 17));
|
|
EXPECT_EQ(0, Call(test->entry(), 4, -17));
|
|
EXPECT_EQ(0, Call(test->entry(), -4, -17));
|
|
EXPECT_EQ(4, Call(test->entry(), 17, 4));
|
|
EXPECT_EQ(-4, Call(test->entry(), -17, 4));
|
|
EXPECT_EQ(-4, Call(test->entry(), 17, -4));
|
|
EXPECT_EQ(4, Call(test->entry(), -17, -4));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DivideUnsignedWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ divuw(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DivideUnsignedWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"02b5553b divuw a0, a0, a1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0, Call(test->entry(), 4, 17));
|
|
EXPECT_EQ(252645134, Call(test->entry(), -4, 17));
|
|
EXPECT_EQ(0, Call(test->entry(), 4, -17));
|
|
EXPECT_EQ(1, Call(test->entry(), -4, -17));
|
|
EXPECT_EQ(4, Call(test->entry(), 17, 4));
|
|
EXPECT_EQ(1073741819, Call(test->entry(), -17, 4));
|
|
EXPECT_EQ(0, Call(test->entry(), 17, -4));
|
|
EXPECT_EQ(0, Call(test->entry(), -17, -4));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(RemainderWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ remw(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(RemainderWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"02b5653b remw a0, a0, a1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(4, Call(test->entry(), 4, 17));
|
|
EXPECT_EQ(-4, Call(test->entry(), -4, 17));
|
|
EXPECT_EQ(4, Call(test->entry(), 4, -17));
|
|
EXPECT_EQ(-4, Call(test->entry(), -4, -17));
|
|
EXPECT_EQ(1, Call(test->entry(), 17, 4));
|
|
EXPECT_EQ(-1, Call(test->entry(), -17, 4));
|
|
EXPECT_EQ(1, Call(test->entry(), 17, -4));
|
|
EXPECT_EQ(-1, Call(test->entry(), -17, -4));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(RemainderUnsignedWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ remuw(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(RemainderUnsignedWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"02b5753b remuw a0, a0, a1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(4, Call(test->entry(), 4, 17));
|
|
EXPECT_EQ(14, Call(test->entry(), -4, 17));
|
|
EXPECT_EQ(4, Call(test->entry(), 4, -17));
|
|
EXPECT_EQ(13, Call(test->entry(), -4, -17));
|
|
EXPECT_EQ(1, Call(test->entry(), 17, 4));
|
|
EXPECT_EQ(3, Call(test->entry(), -17, 4));
|
|
EXPECT_EQ(17, Call(test->entry(), 17, -4));
|
|
EXPECT_EQ(-17, Call(test->entry(), -17, -4));
|
|
}
|
|
#endif
|
|
|
|
ASSEMBLER_TEST_GENERATE(LoadReserveStoreConditionalWord_Success, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
|
|
Label retry;
|
|
__ Bind(&retry);
|
|
__ lrw(T0, Address(A0));
|
|
__ addi(T0, T0, 1);
|
|
__ scw(A1, T0, Address(A0));
|
|
__ bnez(A1, &retry);
|
|
__ mv(A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(LoadReserveStoreConditionalWord_Success, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"100522af lr.w t0, (a0)\n"
|
|
"00128293 addi t0, t0, 1\n"
|
|
"185525af sc.w a1, t0, (a0)\n"
|
|
"fe059ae3 bnez a1, -12\n"
|
|
"00058513 mv a0, a1\n"
|
|
"00008067 ret\n");
|
|
|
|
int32_t* value = reinterpret_cast<int32_t*>(malloc(sizeof(int32_t)));
|
|
*value = 0b1100;
|
|
EXPECT_EQ(0, Call(test->entry(), reinterpret_cast<intx_t>(value)));
|
|
EXPECT_EQ(0b1101, *value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(LoadReserveStoreConditionalWord_Failure, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ li(T0, 42);
|
|
__ scw(A0, T0, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(LoadReserveStoreConditionalWord_Failure, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"02a00293 li t0, 42\n"
|
|
"1855252f sc.w a0, t0, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int32_t* value = reinterpret_cast<int32_t*>(malloc(sizeof(int32_t)));
|
|
*value = 0b1100;
|
|
EXPECT_EQ(false, 0 == Call(test->entry(), reinterpret_cast<intx_t>(value)));
|
|
EXPECT_EQ(0b1100, *value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoSwapWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ amoswapw(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoSwapWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"08b5252f amoswap.w a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int32_t* value = reinterpret_cast<int32_t*>(malloc(sizeof(int32_t)));
|
|
*value = 0b1100;
|
|
EXPECT_EQ(0b1100,
|
|
Call(test->entry(), reinterpret_cast<intx_t>(value), 0b1010));
|
|
EXPECT_EQ(0b1010, *value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoAddWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ amoaddw(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoAddWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"00b5252f amoadd.w a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int32_t* value = reinterpret_cast<int32_t*>(malloc(sizeof(int32_t)));
|
|
*value = 42;
|
|
EXPECT_EQ(42, Call(test->entry(), reinterpret_cast<intx_t>(value), 10));
|
|
EXPECT_EQ(52, *value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoXorWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ amoxorw(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoXorWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"20b5252f amoxor.w a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int32_t* value = reinterpret_cast<int32_t*>(malloc(sizeof(int32_t)));
|
|
*value = 0b1100;
|
|
EXPECT_EQ(0b1100,
|
|
Call(test->entry(), reinterpret_cast<intx_t>(value), 0b1010));
|
|
EXPECT_EQ(0b0110, *value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoAndWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ amoandw(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoAndWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"60b5252f amoand.w a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int32_t* value = reinterpret_cast<int32_t*>(malloc(sizeof(int32_t)));
|
|
*value = 0b1100;
|
|
EXPECT_EQ(0b1100,
|
|
Call(test->entry(), reinterpret_cast<intx_t>(value), 0b1010));
|
|
EXPECT_EQ(0b1000, *value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoOrWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ amoorw(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoOrWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"40b5252f amoor.w a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int32_t* value = reinterpret_cast<int32_t*>(malloc(sizeof(int32_t)));
|
|
*value = 0b1100;
|
|
EXPECT_EQ(0b1100,
|
|
Call(test->entry(), reinterpret_cast<intx_t>(value), 0b1010));
|
|
EXPECT_EQ(0b1110, *value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoMinWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ amominw(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoMinWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"80b5252f amomin.w a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int32_t* value = reinterpret_cast<int32_t*>(malloc(sizeof(int32_t)));
|
|
*value = -7;
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -4));
|
|
EXPECT_EQ(-7, *value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -7));
|
|
EXPECT_EQ(-7, *value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -11));
|
|
EXPECT_EQ(-11, *value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoMaxWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ amomaxw(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoMaxWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"a0b5252f amomax.w a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int32_t* value = reinterpret_cast<int32_t*>(malloc(sizeof(int32_t)));
|
|
*value = -7;
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -11));
|
|
EXPECT_EQ(-7, *value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -7));
|
|
EXPECT_EQ(-7, *value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -4));
|
|
EXPECT_EQ(-4, *value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoMinUnsignedWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ amominuw(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoMinUnsignedWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"c0b5252f amominu.w a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int32_t* value = reinterpret_cast<int32_t*>(malloc(sizeof(int32_t)));
|
|
*value = -7;
|
|
EXPECT_EQ(sign_extend(static_cast<uint32_t>(-7)),
|
|
Call(test->entry(), reinterpret_cast<intx_t>(value), -4));
|
|
EXPECT_EQ(-7, *value);
|
|
EXPECT_EQ(sign_extend(static_cast<uint32_t>(-7)),
|
|
Call(test->entry(), reinterpret_cast<intx_t>(value), -7));
|
|
EXPECT_EQ(-7, *value);
|
|
EXPECT_EQ(sign_extend(static_cast<uint32_t>(-7)),
|
|
Call(test->entry(), reinterpret_cast<intx_t>(value), -11));
|
|
EXPECT_EQ(-11, *value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoMaxUnsignedWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ amomaxuw(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoMaxUnsignedWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"e0b5252f amomaxu.w a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int32_t* value = reinterpret_cast<int32_t*>(malloc(sizeof(int32_t)));
|
|
*value = -7;
|
|
EXPECT_EQ(sign_extend(static_cast<uint32_t>(-7)),
|
|
Call(test->entry(), reinterpret_cast<intx_t>(value), -11));
|
|
EXPECT_EQ(-7, *value);
|
|
EXPECT_EQ(sign_extend(static_cast<uint32_t>(-7)),
|
|
Call(test->entry(), reinterpret_cast<intx_t>(value), -7));
|
|
EXPECT_EQ(-7, *value);
|
|
EXPECT_EQ(sign_extend(static_cast<uint32_t>(-7)),
|
|
Call(test->entry(), reinterpret_cast<intx_t>(value), -4));
|
|
EXPECT_EQ(-4, *value);
|
|
}
|
|
|
|
#if XLEN >= 64
|
|
ASSEMBLER_TEST_GENERATE(LoadReserveStoreConditionalDoubleWord_Success,
|
|
assembler) {
|
|
__ SetExtensions(RV_G);
|
|
|
|
Label retry;
|
|
__ Bind(&retry);
|
|
__ lrd(T0, Address(A0));
|
|
__ addi(T0, T0, 1);
|
|
__ scd(A1, T0, Address(A0));
|
|
__ bnez(A1, &retry);
|
|
__ mv(A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(LoadReserveStoreConditionalDoubleWord_Success, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"100532af lr.d t0, (a0)\n"
|
|
"00128293 addi t0, t0, 1\n"
|
|
"185535af sc.d a1, t0, (a0)\n"
|
|
"fe059ae3 bnez a1, -12\n"
|
|
"00058513 mv a0, a1\n"
|
|
"00008067 ret\n");
|
|
|
|
int64_t* value = reinterpret_cast<int64_t*>(malloc(sizeof(int64_t)));
|
|
*value = 0b1100;
|
|
EXPECT_EQ(0, Call(test->entry(), reinterpret_cast<intx_t>(value)));
|
|
EXPECT_EQ(0b1101, *value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(LoadReserveStoreConditionalDoubleWord_Failure,
|
|
assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ li(T0, 42);
|
|
__ scd(A0, T0, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(LoadReserveStoreConditionalDoubleWord_Failure, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"02a00293 li t0, 42\n"
|
|
"1855352f sc.d a0, t0, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int64_t* value = reinterpret_cast<int64_t*>(malloc(sizeof(int64_t)));
|
|
*value = 0b1100;
|
|
EXPECT_EQ(false, 0 == Call(test->entry(), reinterpret_cast<intx_t>(value)));
|
|
EXPECT_EQ(0b1100, *value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoSwapDoubleWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ amoswapd(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoSwapDoubleWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"08b5352f amoswap.d a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int64_t* value = reinterpret_cast<int64_t*>(malloc(sizeof(int64_t)));
|
|
*value = 0b1100;
|
|
EXPECT_EQ(0b1100,
|
|
Call(test->entry(), reinterpret_cast<intx_t>(value), 0b1010));
|
|
EXPECT_EQ(0b1010, *value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoAddDoubleWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ amoaddd(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoAddDoubleWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"00b5352f amoadd.d a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int64_t* value = reinterpret_cast<int64_t*>(malloc(sizeof(int64_t)));
|
|
*value = 42;
|
|
EXPECT_EQ(42, Call(test->entry(), reinterpret_cast<intx_t>(value), 10));
|
|
EXPECT_EQ(52, *value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoXorDoubleWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ amoxord(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoXorDoubleWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"20b5352f amoxor.d a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int64_t* value = reinterpret_cast<int64_t*>(malloc(sizeof(int64_t)));
|
|
*value = 0b1100;
|
|
EXPECT_EQ(0b1100,
|
|
Call(test->entry(), reinterpret_cast<intx_t>(value), 0b1010));
|
|
EXPECT_EQ(0b0110, *value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoAndDoubleWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ amoandd(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoAndDoubleWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"60b5352f amoand.d a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int64_t* value = reinterpret_cast<int64_t*>(malloc(sizeof(int64_t)));
|
|
*value = 0b1100;
|
|
EXPECT_EQ(0b1100,
|
|
Call(test->entry(), reinterpret_cast<intx_t>(value), 0b1010));
|
|
EXPECT_EQ(0b1000, *value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoOrDoubleWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ amoord(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoOrDoubleWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"40b5352f amoor.d a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int64_t* value = reinterpret_cast<int64_t*>(malloc(sizeof(int64_t)));
|
|
*value = 0b1100;
|
|
EXPECT_EQ(0b1100,
|
|
Call(test->entry(), reinterpret_cast<intx_t>(value), 0b1010));
|
|
EXPECT_EQ(0b1110, *value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoMinDoubleWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ amomind(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoMinDoubleWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"80b5352f amomin.d a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int64_t* value = reinterpret_cast<int64_t*>(malloc(sizeof(int64_t)));
|
|
*value = -7;
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -4));
|
|
EXPECT_EQ(-7, *value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -7));
|
|
EXPECT_EQ(-7, *value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -11));
|
|
EXPECT_EQ(-11, *value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoMaxDoubleWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ amomaxd(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoMaxDoubleWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"a0b5352f amomax.d a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int64_t* value = reinterpret_cast<int64_t*>(malloc(sizeof(int64_t)));
|
|
*value = -7;
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -11));
|
|
EXPECT_EQ(-7, *value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -7));
|
|
EXPECT_EQ(-7, *value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -4));
|
|
EXPECT_EQ(-4, *value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoMinUnsignedDoubleWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ amominud(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoMinUnsignedDoubleWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"c0b5352f amominu.d a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int64_t* value = reinterpret_cast<int64_t*>(malloc(sizeof(int64_t)));
|
|
*value = -7;
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -4));
|
|
EXPECT_EQ(-7, *value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -7));
|
|
EXPECT_EQ(-7, *value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -11));
|
|
EXPECT_EQ(-11, *value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoMaxUnsignedDoubleWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ amomaxud(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoMaxUnsignedDoubleWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"e0b5352f amomaxu.d a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int64_t* value = reinterpret_cast<int64_t*>(malloc(sizeof(int64_t)));
|
|
*value = -7;
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -11));
|
|
EXPECT_EQ(-7, *value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -7));
|
|
EXPECT_EQ(-7, *value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -4));
|
|
EXPECT_EQ(-4, *value);
|
|
}
|
|
#endif
|
|
|
|
ASSEMBLER_TEST_GENERATE(LoadSingleFloat, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ flw(FA0, Address(A0, 1 * sizeof(float)));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(LoadSingleFloat, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"00452507 flw fa0, 4(a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
float* data = reinterpret_cast<float*>(malloc(3 * sizeof(float)));
|
|
data[0] = 1.7f;
|
|
data[1] = 2.8f;
|
|
data[2] = 3.9f;
|
|
EXPECT_EQ(data[1], CallF(test->entry(), reinterpret_cast<intx_t>(data)));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(StoreSingleFloat, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fsw(FA0, Address(A0, 1 * sizeof(float)));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(StoreSingleFloat, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"00a52227 fsw fa0, 4(a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
float* data = reinterpret_cast<float*>(malloc(3 * sizeof(float)));
|
|
data[0] = 1.7f;
|
|
data[1] = 2.8f;
|
|
data[2] = 3.9f;
|
|
CallF(test->entry(), reinterpret_cast<intx_t>(data), 4.2f);
|
|
EXPECT_EQ(4.2f, data[1]);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleMultiplyAdd, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fmadds(FA0, FA0, FA1, FA2);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleMultiplyAdd, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"60b50543 fmadd.s fa0, fa0, fa1, fa2\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(22.0, CallF(test->entry(), 3.0, 5.0, 7.0));
|
|
EXPECT_EQ(-8.0, CallF(test->entry(), -3.0, 5.0, 7.0));
|
|
EXPECT_EQ(-8.0, CallF(test->entry(), 3.0, -5.0, 7.0));
|
|
EXPECT_EQ(8.0, CallF(test->entry(), 3.0, 5.0, -7.0));
|
|
|
|
EXPECT_EQ(26.0, CallF(test->entry(), 7.0, 3.0, 5.0));
|
|
EXPECT_EQ(-16.0, CallF(test->entry(), -7.0, 3.0, 5.0));
|
|
EXPECT_EQ(-16.0, CallF(test->entry(), 7.0, -3.0, 5.0));
|
|
EXPECT_EQ(16.0, CallF(test->entry(), 7.0, 3.0, -5.0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleMultiplySubtract, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fmsubs(FA0, FA0, FA1, FA2);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleMultiplySubtract, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"60b50547 fmsub.s fa0, fa0, fa1, fa2\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(8.0, CallF(test->entry(), 3.0, 5.0, 7.0));
|
|
EXPECT_EQ(-22.0, CallF(test->entry(), -3.0, 5.0, 7.0));
|
|
EXPECT_EQ(-22.0, CallF(test->entry(), 3.0, -5.0, 7.0));
|
|
EXPECT_EQ(22.0, CallF(test->entry(), 3.0, 5.0, -7.0));
|
|
|
|
EXPECT_EQ(16.0, CallF(test->entry(), 7.0, 3.0, 5.0));
|
|
EXPECT_EQ(-26.0, CallF(test->entry(), -7.0, 3.0, 5.0));
|
|
EXPECT_EQ(-26.0, CallF(test->entry(), 7.0, -3.0, 5.0));
|
|
EXPECT_EQ(26.0, CallF(test->entry(), 7.0, 3.0, -5.0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleNegateMultiplySubtract, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fnmsubs(FA0, FA0, FA1, FA2);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleNegateMultiplySubtract, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"60b5054b fnmsub.s fa0, fa0, fa1, fa2\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-8.0, CallF(test->entry(), 3.0, 5.0, 7.0));
|
|
EXPECT_EQ(22.0, CallF(test->entry(), -3.0, 5.0, 7.0));
|
|
EXPECT_EQ(22.0, CallF(test->entry(), 3.0, -5.0, 7.0));
|
|
EXPECT_EQ(-22.0, CallF(test->entry(), 3.0, 5.0, -7.0));
|
|
|
|
EXPECT_EQ(-16.0, CallF(test->entry(), 7.0, 3.0, 5.0));
|
|
EXPECT_EQ(26.0, CallF(test->entry(), -7.0, 3.0, 5.0));
|
|
EXPECT_EQ(26.0, CallF(test->entry(), 7.0, -3.0, 5.0));
|
|
EXPECT_EQ(-26.0, CallF(test->entry(), 7.0, 3.0, -5.0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleNegateMultiplyAdd, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fnmadds(FA0, FA0, FA1, FA2);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleNegateMultiplyAdd, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"60b5054f fnmadd.s fa0, fa0, fa1, fa2\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-22.0, CallF(test->entry(), 3.0, 5.0, 7.0));
|
|
EXPECT_EQ(8.0, CallF(test->entry(), -3.0, 5.0, 7.0));
|
|
EXPECT_EQ(8.0, CallF(test->entry(), 3.0, -5.0, 7.0));
|
|
EXPECT_EQ(-8.0, CallF(test->entry(), 3.0, 5.0, -7.0));
|
|
|
|
EXPECT_EQ(-26.0, CallF(test->entry(), 7.0, 3.0, 5.0));
|
|
EXPECT_EQ(16.0, CallF(test->entry(), -7.0, 3.0, 5.0));
|
|
EXPECT_EQ(16.0, CallF(test->entry(), 7.0, -3.0, 5.0));
|
|
EXPECT_EQ(-16.0, CallF(test->entry(), 7.0, 3.0, -5.0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleAdd, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fadds(FA0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleAdd, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"00b50553 fadd.s fa0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(8.0f, CallF(test->entry(), 3.0f, 5.0f));
|
|
EXPECT_EQ(2.0f, CallF(test->entry(), -3.0f, 5.0f));
|
|
EXPECT_EQ(-2.0f, CallF(test->entry(), 3.0f, -5.0f));
|
|
EXPECT_EQ(-8.0f, CallF(test->entry(), -3.0f, -5.0f));
|
|
|
|
EXPECT_EQ(10.0f, CallF(test->entry(), 7.0f, 3.0f));
|
|
EXPECT_EQ(-4.0f, CallF(test->entry(), -7.0f, 3.0f));
|
|
EXPECT_EQ(4.0f, CallF(test->entry(), 7.0f, -3.0f));
|
|
EXPECT_EQ(-10.0f, CallF(test->entry(), -7.0f, -3.0f));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleSubtract, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fsubs(FA0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleSubtract, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"08b50553 fsub.s fa0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-2.0f, CallF(test->entry(), 3.0f, 5.0f));
|
|
EXPECT_EQ(-8.0f, CallF(test->entry(), -3.0f, 5.0f));
|
|
EXPECT_EQ(8.0f, CallF(test->entry(), 3.0f, -5.0f));
|
|
EXPECT_EQ(2.0f, CallF(test->entry(), -3.0f, -5.0f));
|
|
|
|
EXPECT_EQ(4.0f, CallF(test->entry(), 7.0f, 3.0f));
|
|
EXPECT_EQ(-10.0f, CallF(test->entry(), -7.0f, 3.0f));
|
|
EXPECT_EQ(10.0f, CallF(test->entry(), 7.0f, -3.0f));
|
|
EXPECT_EQ(-4.0f, CallF(test->entry(), -7.0f, -3.0f));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleMultiply, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fmuls(FA0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleMultiply, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"10b50553 fmul.s fa0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(15.0f, CallF(test->entry(), 3.0f, 5.0f));
|
|
EXPECT_EQ(-15.0f, CallF(test->entry(), -3.0f, 5.0f));
|
|
EXPECT_EQ(-15.0f, CallF(test->entry(), 3.0f, -5.0f));
|
|
EXPECT_EQ(15.0f, CallF(test->entry(), -3.0f, -5.0f));
|
|
|
|
EXPECT_EQ(21.0f, CallF(test->entry(), 7.0f, 3.0f));
|
|
EXPECT_EQ(-21.0f, CallF(test->entry(), -7.0f, 3.0f));
|
|
EXPECT_EQ(-21.0f, CallF(test->entry(), 7.0f, -3.0f));
|
|
EXPECT_EQ(21.0f, CallF(test->entry(), -7.0f, -3.0f));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleDivide, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fdivs(FA0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleDivide, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"18b50553 fdiv.s fa0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(2.0f, CallF(test->entry(), 10.0f, 5.0f));
|
|
EXPECT_EQ(-2.0f, CallF(test->entry(), -10.0f, 5.0f));
|
|
EXPECT_EQ(-2.0f, CallF(test->entry(), 10.0f, -5.0f));
|
|
EXPECT_EQ(2.0f, CallF(test->entry(), -10.0f, -5.0f));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleSquareRoot, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fsqrts(FA0, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleSquareRoot, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"58050553 fsqrt.s fa0, fa0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0.0f, CallF(test->entry(), 0.0f));
|
|
EXPECT_EQ(1.0f, CallF(test->entry(), 1.0f));
|
|
EXPECT_EQ(2.0f, CallF(test->entry(), 4.0f));
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), 9.0f));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleSignInject, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fsgnjs(FA0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleSignInject, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"20b50553 fsgnj.s fa0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, 5.0f));
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), -3.0f, 5.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), 3.0f, -5.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, -5.0f));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleNegatedSignInject, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fsgnjns(FA0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleNegatedSignInject, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"20b51553 fsgnjn.s fa0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), 3.0f, 5.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, 5.0f));
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, -5.0f));
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), -3.0f, -5.0f));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleXorSignInject, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fsgnjxs(FA0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleXorSignInject, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"20b52553 fsgnjx.s fa0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, 5.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, 5.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), 3.0f, -5.0f));
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), -3.0f, -5.0f));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleMin, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fmins(FA0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleMin, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"28b50553 fmin.s fa0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(1.0f, CallF(test->entry(), 3.0f, 1.0f));
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, 3.0f));
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, 5.0f));
|
|
EXPECT_EQ(-1.0f, CallF(test->entry(), 3.0f, -1.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), 3.0f, -3.0f));
|
|
EXPECT_EQ(-5.0f, CallF(test->entry(), 3.0f, -5.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, 1.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, 3.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, 5.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, -1.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, -3.0f));
|
|
EXPECT_EQ(-5.0f, CallF(test->entry(), -3.0f, -5.0f));
|
|
|
|
EXPECT_EQ(bit_cast<uint32_t>(-0.0f),
|
|
bit_cast<uint32_t>(CallF(test->entry(), 0.0f, -0.0f)));
|
|
EXPECT_EQ(bit_cast<uint32_t>(-0.0f),
|
|
bit_cast<uint32_t>(CallF(test->entry(), -0.0f, 0.0f)));
|
|
|
|
float qNAN = std::numeric_limits<float>::quiet_NaN();
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, qNAN));
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), qNAN, 3.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, qNAN));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), qNAN, -3.0f));
|
|
|
|
float sNAN = std::numeric_limits<float>::signaling_NaN();
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, sNAN));
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), sNAN, 3.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, sNAN));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), sNAN, -3.0f));
|
|
|
|
EXPECT_EQ(bit_cast<uint32_t>(qNAN),
|
|
bit_cast<uint32_t>(CallF(test->entry(), qNAN, qNAN)));
|
|
EXPECT_EQ(bit_cast<uint32_t>(qNAN),
|
|
bit_cast<uint32_t>(CallF(test->entry(), sNAN, sNAN)));
|
|
EXPECT_EQ(bit_cast<uint32_t>(qNAN),
|
|
bit_cast<uint32_t>(CallF(test->entry(), qNAN, sNAN)));
|
|
EXPECT_EQ(bit_cast<uint32_t>(qNAN),
|
|
bit_cast<uint32_t>(CallF(test->entry(), sNAN, qNAN)));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleMax, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fmaxs(FA0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleMax, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"28b51553 fmax.s fa0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, 1.0f));
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, 3.0f));
|
|
EXPECT_EQ(5.0f, CallF(test->entry(), 3.0f, 5.0f));
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, -1.0f));
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, -3.0f));
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, -5.0f));
|
|
EXPECT_EQ(1.0f, CallF(test->entry(), -3.0f, 1.0f));
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), -3.0f, 3.0f));
|
|
EXPECT_EQ(5.0f, CallF(test->entry(), -3.0f, 5.0f));
|
|
EXPECT_EQ(-1.0f, CallF(test->entry(), -3.0f, -1.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, -3.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, -5.0f));
|
|
|
|
EXPECT_EQ(bit_cast<uint32_t>(0.0f),
|
|
bit_cast<uint32_t>(CallF(test->entry(), 0.0f, -0.0f)));
|
|
EXPECT_EQ(bit_cast<uint32_t>(0.0f),
|
|
bit_cast<uint32_t>(CallF(test->entry(), -0.0f, 0.0f)));
|
|
|
|
float qNAN = std::numeric_limits<float>::quiet_NaN();
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, qNAN));
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), qNAN, 3.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, qNAN));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), qNAN, -3.0f));
|
|
|
|
float sNAN = std::numeric_limits<float>::signaling_NaN();
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, sNAN));
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), sNAN, 3.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, sNAN));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), sNAN, -3.0f));
|
|
|
|
EXPECT_EQ(bit_cast<uint32_t>(qNAN),
|
|
bit_cast<uint32_t>(CallF(test->entry(), qNAN, qNAN)));
|
|
EXPECT_EQ(bit_cast<uint32_t>(qNAN),
|
|
bit_cast<uint32_t>(CallF(test->entry(), sNAN, sNAN)));
|
|
EXPECT_EQ(bit_cast<uint32_t>(qNAN),
|
|
bit_cast<uint32_t>(CallF(test->entry(), qNAN, sNAN)));
|
|
EXPECT_EQ(bit_cast<uint32_t>(qNAN),
|
|
bit_cast<uint32_t>(CallF(test->entry(), sNAN, qNAN)));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleEqual, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ feqs(A0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleEqual, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"a0b52553 feq.s a0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, 1.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), 3.0f, 3.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, 5.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, -1.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, -3.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, -5.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0f, 1.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0f, 3.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0f, 5.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0f, -1.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0f, -3.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0f, -5.0f));
|
|
|
|
float qNAN = std::numeric_limits<float>::quiet_NaN();
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, qNAN));
|
|
EXPECT_EQ(0, CallI(test->entry(), qNAN, 3.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0f, qNAN));
|
|
EXPECT_EQ(0, CallI(test->entry(), qNAN, -3.0f));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleLessThan, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ flts(A0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleLessThan, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"a0b51553 flt.s a0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, 1.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, 3.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), 3.0f, 5.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, -1.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, -3.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, -5.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0f, 1.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0f, 3.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0f, 5.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0f, -1.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0f, -3.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0f, -5.0f));
|
|
|
|
float qNAN = std::numeric_limits<float>::quiet_NaN();
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, qNAN));
|
|
EXPECT_EQ(0, CallI(test->entry(), qNAN, 3.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0f, qNAN));
|
|
EXPECT_EQ(0, CallI(test->entry(), qNAN, -3.0f));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleLessOrEqual, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fles(A0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleLessOrEqual, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"a0b50553 fle.s a0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, 1.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), 3.0f, 3.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), 3.0f, 5.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, -1.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, -3.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, -5.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0f, 1.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0f, 3.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0f, 5.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0f, -1.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0f, -3.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0f, -5.0f));
|
|
|
|
float qNAN = std::numeric_limits<float>::quiet_NaN();
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, qNAN));
|
|
EXPECT_EQ(0, CallI(test->entry(), qNAN, 3.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0f, qNAN));
|
|
EXPECT_EQ(0, CallI(test->entry(), qNAN, -3.0f));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleClassify, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fclasss(A0, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleClassify, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"e0051553 fclass.s a0, fa0\n"
|
|
"00008067 ret\n");
|
|
// Neg infinity
|
|
EXPECT_EQ(1 << 0,
|
|
CallI(test->entry(), -std::numeric_limits<float>::infinity()));
|
|
// Neg normal
|
|
EXPECT_EQ(1 << 1, CallI(test->entry(), -1.0f));
|
|
// Neg subnormal
|
|
EXPECT_EQ(1 << 2,
|
|
CallI(test->entry(), -std::numeric_limits<float>::min() / 2.0f));
|
|
// Neg zero
|
|
EXPECT_EQ(1 << 3, CallI(test->entry(), -0.0f));
|
|
// Pos zero
|
|
EXPECT_EQ(1 << 4, CallI(test->entry(), 0.0f));
|
|
// Pos subnormal
|
|
EXPECT_EQ(1 << 5,
|
|
CallI(test->entry(), std::numeric_limits<float>::min() / 2.0f));
|
|
// Pos normal
|
|
EXPECT_EQ(1 << 6, CallI(test->entry(), 1.0f));
|
|
// Pos infinity
|
|
EXPECT_EQ(1 << 7,
|
|
CallI(test->entry(), std::numeric_limits<float>::infinity()));
|
|
// Signaling NaN
|
|
EXPECT_EQ(1 << 8,
|
|
CallI(test->entry(), std::numeric_limits<float>::signaling_NaN()));
|
|
// Queit NaN
|
|
EXPECT_EQ(1 << 9,
|
|
CallI(test->entry(), std::numeric_limits<float>::quiet_NaN()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertSingleToWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtws(A0, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertSingleToWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"c0050553 fcvt.w.s a0, fa0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-42, CallI(test->entry(), static_cast<float>(-42)));
|
|
EXPECT_EQ(0, CallI(test->entry(), static_cast<float>(0)));
|
|
EXPECT_EQ(42, CallI(test->entry(), static_cast<float>(42)));
|
|
EXPECT_EQ(sign_extend(kMinInt32),
|
|
CallI(test->entry(), static_cast<float>(kMinInt32)));
|
|
EXPECT_EQ(sign_extend(kMaxInt32),
|
|
CallI(test->entry(), static_cast<float>(kMaxInt32)));
|
|
EXPECT_EQ(sign_extend(kMaxInt32),
|
|
CallI(test->entry(), static_cast<float>(kMaxUint32)));
|
|
EXPECT_EQ(sign_extend(kMinInt32),
|
|
CallI(test->entry(), static_cast<float>(kMinInt64)));
|
|
EXPECT_EQ(sign_extend(kMaxInt32),
|
|
CallI(test->entry(), static_cast<float>(kMaxInt64)));
|
|
EXPECT_EQ(sign_extend(kMaxInt32),
|
|
CallI(test->entry(), static_cast<float>(kMaxUint64)));
|
|
EXPECT_EQ(sign_extend(kMinInt32),
|
|
CallI(test->entry(), -std::numeric_limits<float>::infinity()));
|
|
EXPECT_EQ(sign_extend(kMaxInt32),
|
|
CallI(test->entry(), std::numeric_limits<float>::infinity()));
|
|
EXPECT_EQ(sign_extend(kMaxInt32),
|
|
CallI(test->entry(), std::numeric_limits<float>::signaling_NaN()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertSingleToWord_RNE, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtws(A0, FA0, RNE);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertSingleToWord_RNE, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"c0050553 fcvt.w.s a0, fa0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-44, CallI(test->entry(), -43.6f));
|
|
EXPECT_EQ(-44, CallI(test->entry(), -43.5f));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.4f));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.0f));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -42.6f));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.5f));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.4f));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), -0.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), +0.0f));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.0f));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.4f));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.5f));
|
|
EXPECT_EQ(43, CallI(test->entry(), 42.6f));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.0f));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.4f));
|
|
EXPECT_EQ(44, CallI(test->entry(), 43.5f));
|
|
EXPECT_EQ(44, CallI(test->entry(), 43.6f));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertSingleToWord_RTZ, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtws(A0, FA0, RTZ);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertSingleToWord_RTZ, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"c0051553 fcvt.w.s a0, fa0, rtz\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.6f));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.5f));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.4f));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.0f));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.6f));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.5f));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.4f));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), -0.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), +0.0f));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.0f));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.4f));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.5f));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.6f));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.0f));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.4f));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.5f));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.6f));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertSingleToWord_RDN, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtws(A0, FA0, RDN);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertSingleToWord_RDN, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"c0052553 fcvt.w.s a0, fa0, rdn\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-44, CallI(test->entry(), -43.6f));
|
|
EXPECT_EQ(-44, CallI(test->entry(), -43.5f));
|
|
EXPECT_EQ(-44, CallI(test->entry(), -43.4f));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.0f));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -42.6f));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -42.5f));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -42.4f));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), -0.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), +0.0f));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.0f));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.4f));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.5f));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.6f));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.0f));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.4f));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.5f));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.6f));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertSingleToWord_RUP, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtws(A0, FA0, RUP);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertSingleToWord_RUP, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"c0053553 fcvt.w.s a0, fa0, rup\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.6f));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.5f));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.4f));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.0f));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.6f));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.5f));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.4f));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), -0.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), +0.0f));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.0f));
|
|
EXPECT_EQ(43, CallI(test->entry(), 42.4f));
|
|
EXPECT_EQ(43, CallI(test->entry(), 42.5f));
|
|
EXPECT_EQ(43, CallI(test->entry(), 42.6f));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.0f));
|
|
EXPECT_EQ(44, CallI(test->entry(), 43.5f));
|
|
EXPECT_EQ(44, CallI(test->entry(), 43.5f));
|
|
EXPECT_EQ(44, CallI(test->entry(), 43.6f));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertSingleToWord_RMM, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtws(A0, FA0, RMM);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertSingleToWord_RMM, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"c0054553 fcvt.w.s a0, fa0, rmm\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-44, CallI(test->entry(), -43.6f));
|
|
EXPECT_EQ(-44, CallI(test->entry(), -43.5f));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.4f));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.0f));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -42.6f));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -42.5f));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.4f));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), -0.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), +0.0f));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.0f));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.4f));
|
|
EXPECT_EQ(43, CallI(test->entry(), 42.5f));
|
|
EXPECT_EQ(43, CallI(test->entry(), 42.6f));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.0f));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.4f));
|
|
EXPECT_EQ(44, CallI(test->entry(), 43.5f));
|
|
EXPECT_EQ(44, CallI(test->entry(), 43.6f));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertSingleToUnsignedWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtwus(A0, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertSingleToUnsignedWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"c0150553 fcvt.wu.s a0, fa0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0, CallI(test->entry(), static_cast<float>(-42)));
|
|
EXPECT_EQ(0, CallI(test->entry(), static_cast<float>(0)));
|
|
EXPECT_EQ(42, CallI(test->entry(), static_cast<float>(42)));
|
|
EXPECT_EQ(sign_extend(0),
|
|
CallI(test->entry(), static_cast<float>(kMinInt32)));
|
|
// float loss of precision
|
|
EXPECT_EQ(-2147483648, CallI(test->entry(), static_cast<float>(kMaxInt32)));
|
|
EXPECT_EQ(sign_extend(kMaxUint32),
|
|
CallI(test->entry(), static_cast<float>(kMaxUint32)));
|
|
EXPECT_EQ(sign_extend(0),
|
|
CallI(test->entry(), static_cast<float>(kMinInt64)));
|
|
EXPECT_EQ(sign_extend(kMaxUint32),
|
|
CallI(test->entry(), static_cast<float>(kMaxInt64)));
|
|
EXPECT_EQ(sign_extend(kMaxUint32),
|
|
CallI(test->entry(), static_cast<float>(kMaxUint64)));
|
|
EXPECT_EQ(sign_extend(0),
|
|
CallI(test->entry(), -std::numeric_limits<float>::infinity()));
|
|
EXPECT_EQ(sign_extend(kMaxUint32),
|
|
CallI(test->entry(), std::numeric_limits<float>::infinity()));
|
|
EXPECT_EQ(sign_extend(kMaxUint32),
|
|
CallI(test->entry(), std::numeric_limits<float>::signaling_NaN()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertWordToSingle, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtsw(FA0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertWordToSingle, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"d0050553 fcvt.s.w fa0, a0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-42.0f, CallF(test->entry(), sign_extend(-42)));
|
|
EXPECT_EQ(0.0f, CallF(test->entry(), sign_extend(0)));
|
|
EXPECT_EQ(42.0f, CallF(test->entry(), sign_extend(42)));
|
|
EXPECT_EQ(static_cast<float>(kMinInt32),
|
|
CallF(test->entry(), sign_extend(kMinInt32)));
|
|
EXPECT_EQ(static_cast<float>(kMaxInt32),
|
|
CallF(test->entry(), sign_extend(kMaxInt32)));
|
|
EXPECT_EQ(-1.0f, CallF(test->entry(), sign_extend(kMaxUint32)));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertUnsignedWordToSingle, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtswu(FA0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertUnsignedWordToSingle, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"d0150553 fcvt.s.wu fa0, a0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(
|
|
static_cast<float>(static_cast<uint32_t>(static_cast<int32_t>(-42))),
|
|
CallF(test->entry(), sign_extend(-42)));
|
|
EXPECT_EQ(0.0f, CallF(test->entry(), sign_extend(0)));
|
|
EXPECT_EQ(42.0f, CallF(test->entry(), sign_extend(42)));
|
|
EXPECT_EQ(static_cast<float>(static_cast<uint32_t>(kMinInt32)),
|
|
CallF(test->entry(), sign_extend(kMinInt32)));
|
|
EXPECT_EQ(static_cast<float>(kMaxInt32),
|
|
CallF(test->entry(), sign_extend(kMaxInt32)));
|
|
EXPECT_EQ(static_cast<float>(kMaxUint32),
|
|
CallF(test->entry(), sign_extend(kMaxUint32)));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleMove, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fmvs(FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleMove, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"20b58553 fmv.s fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(36.0f, CallF(test->entry(), 42.0f, 36.0f));
|
|
EXPECT_EQ(std::numeric_limits<float>::infinity(),
|
|
CallF(test->entry(), -std::numeric_limits<float>::infinity(),
|
|
std::numeric_limits<float>::infinity()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleAbsoluteValue, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fabss(FA0, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleAbsoluteValue, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"20a52553 fabs.s fa0, fa0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0.0f, CallF(test->entry(), 0.0f));
|
|
EXPECT_EQ(0.0f, CallF(test->entry(), -0.0f));
|
|
EXPECT_EQ(42.0f, CallF(test->entry(), 42.0f));
|
|
EXPECT_EQ(42.0f, CallF(test->entry(), -42.0f));
|
|
EXPECT_EQ(std::numeric_limits<float>::infinity(),
|
|
CallF(test->entry(), std::numeric_limits<float>::infinity()));
|
|
EXPECT_EQ(std::numeric_limits<float>::infinity(),
|
|
CallF(test->entry(), -std::numeric_limits<float>::infinity()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleNegate, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fnegs(FA0, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleNegate, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"20a51553 fneg.s fa0, fa0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-0.0f, CallF(test->entry(), 0.0f));
|
|
EXPECT_EQ(0.0f, CallF(test->entry(), -0.0f));
|
|
EXPECT_EQ(-42.0f, CallF(test->entry(), 42.0f));
|
|
EXPECT_EQ(42.0f, CallF(test->entry(), -42.0f));
|
|
EXPECT_EQ(-std::numeric_limits<float>::infinity(),
|
|
CallF(test->entry(), std::numeric_limits<float>::infinity()));
|
|
EXPECT_EQ(std::numeric_limits<float>::infinity(),
|
|
CallF(test->entry(), -std::numeric_limits<float>::infinity()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(BitCastSingleToInteger, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fmvxw(A0, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(BitCastSingleToInteger, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"e0050553 fmv.x.w a0, fa0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(bit_cast<int32_t>(0.0f), CallI(test->entry(), 0.0f));
|
|
EXPECT_EQ(bit_cast<int32_t>(-0.0f), CallI(test->entry(), -0.0f));
|
|
EXPECT_EQ(bit_cast<int32_t>(42.0f), CallI(test->entry(), 42.0f));
|
|
EXPECT_EQ(bit_cast<int32_t>(-42.0f), CallI(test->entry(), -42.0f));
|
|
EXPECT_EQ(bit_cast<int32_t>(std::numeric_limits<float>::quiet_NaN()),
|
|
CallI(test->entry(), std::numeric_limits<float>::quiet_NaN()));
|
|
EXPECT_EQ(bit_cast<int32_t>(std::numeric_limits<float>::signaling_NaN()),
|
|
CallI(test->entry(), std::numeric_limits<float>::signaling_NaN()));
|
|
EXPECT_EQ(bit_cast<int32_t>(std::numeric_limits<float>::infinity()),
|
|
CallI(test->entry(), std::numeric_limits<float>::infinity()));
|
|
EXPECT_EQ(bit_cast<int32_t>(-std::numeric_limits<float>::infinity()),
|
|
CallI(test->entry(), -std::numeric_limits<float>::infinity()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(BitCastIntegerToSingle, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fmvwx(FA0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(BitCastIntegerToSingle, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"f0050553 fmv.w.x fa0, a0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0.0f, CallF(test->entry(), sign_extend(bit_cast<int32_t>(0.0f))));
|
|
EXPECT_EQ(-0.0f, CallF(test->entry(), sign_extend(bit_cast<int32_t>(-0.0f))));
|
|
EXPECT_EQ(42.0f, CallF(test->entry(), sign_extend(bit_cast<int32_t>(42.0f))));
|
|
EXPECT_EQ(-42.0f,
|
|
CallF(test->entry(), sign_extend(bit_cast<int32_t>(-42.0f))));
|
|
EXPECT_EQ(true, isnan(CallF(test->entry(),
|
|
sign_extend(bit_cast<int32_t>(
|
|
std::numeric_limits<float>::quiet_NaN())))));
|
|
EXPECT_EQ(true,
|
|
isnan(CallF(test->entry(),
|
|
sign_extend(bit_cast<int32_t>(
|
|
std::numeric_limits<float>::signaling_NaN())))));
|
|
EXPECT_EQ(std::numeric_limits<float>::infinity(),
|
|
CallF(test->entry(), sign_extend(bit_cast<int32_t>(
|
|
std::numeric_limits<float>::infinity()))));
|
|
EXPECT_EQ(
|
|
-std::numeric_limits<float>::infinity(),
|
|
CallF(test->entry(), sign_extend(bit_cast<int32_t>(
|
|
-std::numeric_limits<float>::infinity()))));
|
|
}
|
|
|
|
#if XLEN >= 64
|
|
ASSEMBLER_TEST_GENERATE(ConvertSingleToDoubleWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtls(A0, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertSingleToDoubleWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"c0250553 fcvt.l.s a0, fa0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-42, CallI(test->entry(), static_cast<float>(-42)));
|
|
EXPECT_EQ(0, CallI(test->entry(), static_cast<float>(0)));
|
|
EXPECT_EQ(42, CallI(test->entry(), static_cast<float>(42)));
|
|
EXPECT_EQ(static_cast<int64_t>(kMinInt32),
|
|
CallI(test->entry(), static_cast<float>(kMinInt32)));
|
|
// float loses precision:
|
|
EXPECT_EQ(static_cast<int64_t>(kMaxInt32) + 1,
|
|
CallI(test->entry(), static_cast<float>(kMaxInt32)));
|
|
EXPECT_EQ(static_cast<int64_t>(kMaxUint32) + 1,
|
|
CallI(test->entry(), static_cast<float>(kMaxUint32)));
|
|
EXPECT_EQ(kMinInt64, CallI(test->entry(), static_cast<float>(kMinInt64)));
|
|
EXPECT_EQ(kMaxInt64, CallI(test->entry(), static_cast<float>(kMaxInt64)));
|
|
EXPECT_EQ(kMaxInt64, CallI(test->entry(), static_cast<float>(kMaxUint64)));
|
|
EXPECT_EQ(kMinInt64,
|
|
CallI(test->entry(), -std::numeric_limits<float>::infinity()));
|
|
EXPECT_EQ(kMaxInt64,
|
|
CallI(test->entry(), std::numeric_limits<float>::infinity()));
|
|
EXPECT_EQ(kMaxInt64,
|
|
CallI(test->entry(), std::numeric_limits<float>::signaling_NaN()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertSingleToUnsignedDoubleWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtlus(A0, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertSingleToUnsignedDoubleWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"c0350553 fcvt.lu.s a0, fa0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0, CallI(test->entry(), static_cast<float>(-42)));
|
|
EXPECT_EQ(0, CallI(test->entry(), static_cast<float>(0)));
|
|
EXPECT_EQ(42, CallI(test->entry(), static_cast<float>(42)));
|
|
EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(0)),
|
|
CallI(test->entry(), static_cast<float>(kMinInt32)));
|
|
EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxInt32) + 1),
|
|
CallI(test->entry(), static_cast<float>(kMaxInt32)));
|
|
EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxUint32) + 1),
|
|
CallI(test->entry(), static_cast<float>(kMaxUint32)));
|
|
EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(0)),
|
|
CallI(test->entry(), static_cast<float>(kMinInt64)));
|
|
EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxInt64) + 1),
|
|
CallI(test->entry(), static_cast<float>(kMaxInt64)));
|
|
EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxUint64)),
|
|
CallI(test->entry(), static_cast<float>(kMaxUint64)));
|
|
EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(0)),
|
|
CallI(test->entry(), -std::numeric_limits<float>::infinity()));
|
|
EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxUint64)),
|
|
CallI(test->entry(), std::numeric_limits<float>::infinity()));
|
|
EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxUint64)),
|
|
CallI(test->entry(), std::numeric_limits<float>::signaling_NaN()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertDoubleWordToSingle, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtsl(FA0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertDoubleWordToSingle, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"d0250553 fcvt.s.l fa0, a0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0.0f, CallF(test->entry(), sign_extend(0)));
|
|
EXPECT_EQ(42.0f, CallF(test->entry(), sign_extend(42)));
|
|
EXPECT_EQ(-42.0f, CallF(test->entry(), sign_extend(-42)));
|
|
EXPECT_EQ(static_cast<float>(kMinInt32),
|
|
CallF(test->entry(), sign_extend(kMinInt32)));
|
|
EXPECT_EQ(static_cast<float>(kMaxInt32),
|
|
CallF(test->entry(), sign_extend(kMaxInt32)));
|
|
EXPECT_EQ(static_cast<float>(sign_extend(kMaxUint32)),
|
|
CallF(test->entry(), sign_extend(kMaxUint32)));
|
|
EXPECT_EQ(static_cast<float>(kMinInt64),
|
|
CallF(test->entry(), sign_extend(kMinInt64)));
|
|
EXPECT_EQ(static_cast<float>(kMaxInt64),
|
|
CallF(test->entry(), sign_extend(kMaxInt64)));
|
|
EXPECT_EQ(static_cast<float>(sign_extend(kMaxUint64)),
|
|
CallF(test->entry(), sign_extend(kMaxUint64)));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertUnsignedDoubleWordToSingle, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtslu(FA0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertUnsignedDoubleWordToSingle, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"d0350553 fcvt.s.lu fa0, a0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0.0f, CallF(test->entry(), sign_extend(0)));
|
|
EXPECT_EQ(42.0f, CallF(test->entry(), sign_extend(42)));
|
|
EXPECT_EQ(static_cast<float>(static_cast<uint64_t>(sign_extend(-42))),
|
|
CallF(test->entry(), sign_extend(-42)));
|
|
EXPECT_EQ(static_cast<float>(static_cast<uint64_t>(sign_extend(kMinInt32))),
|
|
CallF(test->entry(), sign_extend(kMinInt32)));
|
|
EXPECT_EQ(static_cast<float>(static_cast<uint64_t>(sign_extend(kMaxInt32))),
|
|
CallF(test->entry(), sign_extend(kMaxInt32)));
|
|
EXPECT_EQ(static_cast<float>(static_cast<uint64_t>(sign_extend(kMaxUint32))),
|
|
CallF(test->entry(), sign_extend(kMaxUint32)));
|
|
EXPECT_EQ(static_cast<float>(static_cast<uint64_t>(sign_extend(kMinInt64))),
|
|
CallF(test->entry(), sign_extend(kMinInt64)));
|
|
EXPECT_EQ(static_cast<float>(static_cast<uint64_t>(sign_extend(kMaxInt64))),
|
|
CallF(test->entry(), sign_extend(kMaxInt64)));
|
|
EXPECT_EQ(static_cast<float>(kMaxUint64),
|
|
CallF(test->entry(), sign_extend(kMaxUint64)));
|
|
}
|
|
#endif
|
|
|
|
ASSEMBLER_TEST_GENERATE(LoadDoubleFloat, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fld(FA0, Address(A0, 1 * sizeof(double)));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(LoadDoubleFloat, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"00853507 fld fa0, 8(a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
double* data = reinterpret_cast<double*>(malloc(3 * sizeof(double)));
|
|
data[0] = 1.7;
|
|
data[1] = 2.8;
|
|
data[2] = 3.9;
|
|
EXPECT_EQ(data[1], CallD(test->entry(), reinterpret_cast<intx_t>(data)));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(StoreDoubleFloat, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fsd(FA0, Address(A0, 1 * sizeof(double)));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(StoreDoubleFloat, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"00a53427 fsd fa0, 8(a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
double* data = reinterpret_cast<double*>(malloc(3 * sizeof(double)));
|
|
data[0] = 1.7;
|
|
data[1] = 2.8;
|
|
data[2] = 3.9;
|
|
CallD(test->entry(), reinterpret_cast<intx_t>(data), 4.2);
|
|
EXPECT_EQ(4.2, data[1]);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleMultiplyAdd, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fmaddd(FA0, FA0, FA1, FA2);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleMultiplyAdd, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"62b50543 fmadd.d fa0, fa0, fa1, fa2\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(22.0, CallD(test->entry(), 3.0, 5.0, 7.0));
|
|
EXPECT_EQ(-8.0, CallD(test->entry(), -3.0, 5.0, 7.0));
|
|
EXPECT_EQ(-8.0, CallD(test->entry(), 3.0, -5.0, 7.0));
|
|
EXPECT_EQ(8.0, CallD(test->entry(), 3.0, 5.0, -7.0));
|
|
|
|
EXPECT_EQ(26.0, CallD(test->entry(), 7.0, 3.0, 5.0));
|
|
EXPECT_EQ(-16.0, CallD(test->entry(), -7.0, 3.0, 5.0));
|
|
EXPECT_EQ(-16.0, CallD(test->entry(), 7.0, -3.0, 5.0));
|
|
EXPECT_EQ(16.0, CallD(test->entry(), 7.0, 3.0, -5.0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleMultiplySubtract, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fmsubd(FA0, FA0, FA1, FA2);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleMultiplySubtract, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"62b50547 fmsub.d fa0, fa0, fa1, fa2\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(8.0, CallD(test->entry(), 3.0, 5.0, 7.0));
|
|
EXPECT_EQ(-22.0, CallD(test->entry(), -3.0, 5.0, 7.0));
|
|
EXPECT_EQ(-22.0, CallD(test->entry(), 3.0, -5.0, 7.0));
|
|
EXPECT_EQ(22.0, CallD(test->entry(), 3.0, 5.0, -7.0));
|
|
|
|
EXPECT_EQ(16.0, CallD(test->entry(), 7.0, 3.0, 5.0));
|
|
EXPECT_EQ(-26.0, CallD(test->entry(), -7.0, 3.0, 5.0));
|
|
EXPECT_EQ(-26.0, CallD(test->entry(), 7.0, -3.0, 5.0));
|
|
EXPECT_EQ(26.0, CallD(test->entry(), 7.0, 3.0, -5.0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleNegateMultiplySubtract, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fnmsubd(FA0, FA0, FA1, FA2);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleNegateMultiplySubtract, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"62b5054b fnmsub.d fa0, fa0, fa1, fa2\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-8.0, CallD(test->entry(), 3.0, 5.0, 7.0));
|
|
EXPECT_EQ(22.0, CallD(test->entry(), -3.0, 5.0, 7.0));
|
|
EXPECT_EQ(22.0, CallD(test->entry(), 3.0, -5.0, 7.0));
|
|
EXPECT_EQ(-22.0, CallD(test->entry(), 3.0, 5.0, -7.0));
|
|
|
|
EXPECT_EQ(-16.0, CallD(test->entry(), 7.0, 3.0, 5.0));
|
|
EXPECT_EQ(26.0, CallD(test->entry(), -7.0, 3.0, 5.0));
|
|
EXPECT_EQ(26.0, CallD(test->entry(), 7.0, -3.0, 5.0));
|
|
EXPECT_EQ(-26.0, CallD(test->entry(), 7.0, 3.0, -5.0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleNegateMultiplyAdd, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fnmaddd(FA0, FA0, FA1, FA2);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleNegateMultiplyAdd, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"62b5054f fnmadd.d fa0, fa0, fa1, fa2\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-22.0, CallD(test->entry(), 3.0, 5.0, 7.0));
|
|
EXPECT_EQ(8.0, CallD(test->entry(), -3.0, 5.0, 7.0));
|
|
EXPECT_EQ(8.0, CallD(test->entry(), 3.0, -5.0, 7.0));
|
|
EXPECT_EQ(-8.0, CallD(test->entry(), 3.0, 5.0, -7.0));
|
|
|
|
EXPECT_EQ(-26.0, CallD(test->entry(), 7.0, 3.0, 5.0));
|
|
EXPECT_EQ(16.0, CallD(test->entry(), -7.0, 3.0, 5.0));
|
|
EXPECT_EQ(16.0, CallD(test->entry(), 7.0, -3.0, 5.0));
|
|
EXPECT_EQ(-16.0, CallD(test->entry(), 7.0, 3.0, -5.0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleAdd, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ faddd(FA0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleAdd, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"02b50553 fadd.d fa0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(8.0, CallD(test->entry(), 3.0, 5.0));
|
|
EXPECT_EQ(2.0, CallD(test->entry(), -3.0, 5.0));
|
|
EXPECT_EQ(-2.0, CallD(test->entry(), 3.0, -5.0));
|
|
EXPECT_EQ(-8.0, CallD(test->entry(), -3.0, -5.0));
|
|
|
|
EXPECT_EQ(10.0, CallD(test->entry(), 7.0, 3.0));
|
|
EXPECT_EQ(-4.0, CallD(test->entry(), -7.0, 3.0));
|
|
EXPECT_EQ(4.0, CallD(test->entry(), 7.0, -3.0));
|
|
EXPECT_EQ(-10.0, CallD(test->entry(), -7.0, -3.0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleSubtract, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fsubd(FA0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleSubtract, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"0ab50553 fsub.d fa0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-2.0, CallD(test->entry(), 3.0, 5.0));
|
|
EXPECT_EQ(-8.0, CallD(test->entry(), -3.0, 5.0));
|
|
EXPECT_EQ(8.0, CallD(test->entry(), 3.0, -5.0));
|
|
EXPECT_EQ(2.0, CallD(test->entry(), -3.0, -5.0));
|
|
|
|
EXPECT_EQ(4.0, CallD(test->entry(), 7.0, 3.0));
|
|
EXPECT_EQ(-10.0, CallD(test->entry(), -7.0, 3.0));
|
|
EXPECT_EQ(10.0, CallD(test->entry(), 7.0, -3.0));
|
|
EXPECT_EQ(-4.0, CallD(test->entry(), -7.0, -3.0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleMultiply, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fmuld(FA0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleMultiply, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"12b50553 fmul.d fa0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(15.0, CallD(test->entry(), 3.0, 5.0));
|
|
EXPECT_EQ(-15.0, CallD(test->entry(), -3.0, 5.0));
|
|
EXPECT_EQ(-15.0, CallD(test->entry(), 3.0, -5.0));
|
|
EXPECT_EQ(15.0, CallD(test->entry(), -3.0, -5.0));
|
|
|
|
EXPECT_EQ(21.0, CallD(test->entry(), 7.0, 3.0));
|
|
EXPECT_EQ(-21.0, CallD(test->entry(), -7.0, 3.0));
|
|
EXPECT_EQ(-21.0, CallD(test->entry(), 7.0, -3.0));
|
|
EXPECT_EQ(21.0, CallD(test->entry(), -7.0, -3.0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleDivide, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fdivd(FA0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleDivide, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"1ab50553 fdiv.d fa0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(2.0, CallD(test->entry(), 10.0, 5.0));
|
|
EXPECT_EQ(-2.0, CallD(test->entry(), -10.0, 5.0));
|
|
EXPECT_EQ(-2.0, CallD(test->entry(), 10.0, -5.0));
|
|
EXPECT_EQ(2.0, CallD(test->entry(), -10.0, -5.0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleSquareRoot, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fsqrtd(FA0, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleSquareRoot, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"5a050553 fsqrt.d fa0, fa0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0.0, CallD(test->entry(), 0.0));
|
|
EXPECT_EQ(1.0, CallD(test->entry(), 1.0));
|
|
EXPECT_EQ(2.0, CallD(test->entry(), 4.0));
|
|
EXPECT_EQ(3.0, CallD(test->entry(), 9.0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleSignInject, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fsgnjd(FA0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleSignInject, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"22b50553 fsgnj.d fa0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(3.0, CallD(test->entry(), 3.0, 5.0));
|
|
EXPECT_EQ(3.0, CallD(test->entry(), -3.0, 5.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), 3.0, -5.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, -5.0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleNegatedSignInject, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fsgnjnd(FA0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleNegatedSignInject, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"22b51553 fsgnjn.d fa0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), 3.0, 5.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, 5.0));
|
|
EXPECT_EQ(3.0, CallD(test->entry(), 3.0, -5.0));
|
|
EXPECT_EQ(3.0, CallD(test->entry(), -3.0, -5.0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleXorSignInject, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fsgnjxd(FA0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleXorSignInject, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"22b52553 fsgnjx.d fa0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(3.0, CallD(test->entry(), 3.0, 5.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, 5.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), 3.0, -5.0));
|
|
EXPECT_EQ(3.0, CallD(test->entry(), -3.0, -5.0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleMin, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fmind(FA0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleMin, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"2ab50553 fmin.d fa0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(1.0, CallD(test->entry(), 3.0, 1.0));
|
|
EXPECT_EQ(3.0, CallD(test->entry(), 3.0, 3.0));
|
|
EXPECT_EQ(3.0, CallD(test->entry(), 3.0, 5.0));
|
|
EXPECT_EQ(-1.0, CallD(test->entry(), 3.0, -1.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), 3.0, -3.0));
|
|
EXPECT_EQ(-5.0, CallD(test->entry(), 3.0, -5.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, 1.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, 3.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, 5.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, -1.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, -3.0));
|
|
EXPECT_EQ(-5.0, CallD(test->entry(), -3.0, -5.0));
|
|
|
|
EXPECT_EQ(bit_cast<uint64_t>(-0.0),
|
|
bit_cast<uint64_t>(CallD(test->entry(), 0.0, -0.0)));
|
|
EXPECT_EQ(bit_cast<uint64_t>(-0.0),
|
|
bit_cast<uint64_t>(CallD(test->entry(), -0.0, 0.0)));
|
|
|
|
double qNAN = std::numeric_limits<double>::quiet_NaN();
|
|
EXPECT_EQ(3.0, CallD(test->entry(), 3.0, qNAN));
|
|
EXPECT_EQ(3.0, CallD(test->entry(), qNAN, 3.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, qNAN));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), qNAN, -3.0));
|
|
|
|
double sNAN = std::numeric_limits<double>::signaling_NaN();
|
|
EXPECT_EQ(3.0, CallD(test->entry(), 3.0, sNAN));
|
|
EXPECT_EQ(3.0, CallD(test->entry(), sNAN, 3.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, sNAN));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), sNAN, -3.0));
|
|
|
|
EXPECT_EQ(bit_cast<uint64_t>(qNAN),
|
|
bit_cast<uint64_t>(CallD(test->entry(), sNAN, sNAN)));
|
|
EXPECT_EQ(bit_cast<uint64_t>(qNAN),
|
|
bit_cast<uint64_t>(CallD(test->entry(), qNAN, qNAN)));
|
|
EXPECT_EQ(bit_cast<uint64_t>(qNAN),
|
|
bit_cast<uint64_t>(CallD(test->entry(), qNAN, sNAN)));
|
|
EXPECT_EQ(bit_cast<uint64_t>(qNAN),
|
|
bit_cast<uint64_t>(CallD(test->entry(), sNAN, qNAN)));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleMax, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fmaxd(FA0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleMax, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"2ab51553 fmax.d fa0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(3.0, CallD(test->entry(), 3.0, 1.0));
|
|
EXPECT_EQ(3.0, CallD(test->entry(), 3.0, 3.0));
|
|
EXPECT_EQ(5.0, CallD(test->entry(), 3.0, 5.0));
|
|
EXPECT_EQ(3.0, CallD(test->entry(), 3.0, -1.0));
|
|
EXPECT_EQ(3.0, CallD(test->entry(), 3.0, -3.0));
|
|
EXPECT_EQ(3.0, CallD(test->entry(), 3.0, -5.0));
|
|
EXPECT_EQ(1.0, CallD(test->entry(), -3.0, 1.0));
|
|
EXPECT_EQ(3.0, CallD(test->entry(), -3.0, 3.0));
|
|
EXPECT_EQ(5.0, CallD(test->entry(), -3.0, 5.0));
|
|
EXPECT_EQ(-1.0, CallD(test->entry(), -3.0, -1.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, -3.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, -5.0));
|
|
|
|
EXPECT_EQ(bit_cast<uint64_t>(0.0),
|
|
bit_cast<uint64_t>(CallD(test->entry(), 0.0, -0.0)));
|
|
EXPECT_EQ(bit_cast<uint64_t>(0.0),
|
|
bit_cast<uint64_t>(CallD(test->entry(), -0.0, 0.0)));
|
|
|
|
double qNAN = std::numeric_limits<double>::quiet_NaN();
|
|
EXPECT_EQ(3.0, CallD(test->entry(), 3.0, qNAN));
|
|
EXPECT_EQ(3.0, CallD(test->entry(), qNAN, 3.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, qNAN));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), qNAN, -3.0));
|
|
|
|
double sNAN = std::numeric_limits<double>::signaling_NaN();
|
|
EXPECT_EQ(3.0, CallD(test->entry(), 3.0, sNAN));
|
|
EXPECT_EQ(3.0, CallD(test->entry(), sNAN, 3.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, sNAN));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), sNAN, -3.0));
|
|
|
|
EXPECT_EQ(bit_cast<uint64_t>(qNAN),
|
|
bit_cast<uint64_t>(CallD(test->entry(), sNAN, sNAN)));
|
|
EXPECT_EQ(bit_cast<uint64_t>(qNAN),
|
|
bit_cast<uint64_t>(CallD(test->entry(), qNAN, qNAN)));
|
|
EXPECT_EQ(bit_cast<uint64_t>(qNAN),
|
|
bit_cast<uint64_t>(CallD(test->entry(), qNAN, sNAN)));
|
|
EXPECT_EQ(bit_cast<uint64_t>(qNAN),
|
|
bit_cast<uint64_t>(CallD(test->entry(), sNAN, qNAN)));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleToSingle, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtsd(FA0, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleToSingle, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"40150553 fcvt.s.d fa0, fa0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0.0f, CallF(test->entry(), 0.0));
|
|
EXPECT_EQ(42.0f, CallF(test->entry(), 42.0));
|
|
EXPECT_EQ(-42.0f, CallF(test->entry(), -42.0));
|
|
EXPECT_EQ(true, isnan(CallF(test->entry(),
|
|
std::numeric_limits<double>::quiet_NaN())));
|
|
EXPECT_EQ(true, isnan(CallF(test->entry(),
|
|
std::numeric_limits<double>::signaling_NaN())));
|
|
EXPECT_EQ(std::numeric_limits<float>::infinity(),
|
|
CallF(test->entry(), std::numeric_limits<double>::infinity()));
|
|
EXPECT_EQ(-std::numeric_limits<float>::infinity(),
|
|
CallF(test->entry(), -std::numeric_limits<double>::infinity()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleToDouble, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtds(FA0, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleToDouble, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"42050553 fcvt.d.s fa0, fa0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0.0, CallD(test->entry(), 0.0f));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), 42.0f));
|
|
EXPECT_EQ(-42.0, CallD(test->entry(), -42.0f));
|
|
EXPECT_EQ(true, isnan(CallD(test->entry(),
|
|
std::numeric_limits<float>::quiet_NaN())));
|
|
EXPECT_EQ(true, isnan(CallD(test->entry(),
|
|
std::numeric_limits<float>::signaling_NaN())));
|
|
EXPECT_EQ(std::numeric_limits<double>::infinity(),
|
|
CallD(test->entry(), std::numeric_limits<float>::infinity()));
|
|
EXPECT_EQ(-std::numeric_limits<double>::infinity(),
|
|
CallD(test->entry(), -std::numeric_limits<float>::infinity()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(NaNBoxing, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(NaNBoxing, test) {
|
|
EXPECT_DISASSEMBLY("00008067 ret\n");
|
|
EXPECT_EQ(true, isnan(CallD(test->entry(), 42.0f)));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleEqual, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ feqd(A0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleEqual, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"a2b52553 feq.d a0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, 1.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), 3.0, 3.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, 5.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, -1.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, -3.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, -5.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0, 1.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0, 3.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0, 5.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0, -1.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0, -3.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0, -5.0));
|
|
|
|
double qNAN = std::numeric_limits<double>::quiet_NaN();
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, qNAN));
|
|
EXPECT_EQ(0, CallI(test->entry(), qNAN, 3.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0, qNAN));
|
|
EXPECT_EQ(0, CallI(test->entry(), qNAN, -3.0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleLessThan, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fltd(A0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleLessThan, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"a2b51553 flt.d a0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, 1.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, 3.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), 3.0, 5.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, -1.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, -3.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, -5.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0, 1.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0, 3.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0, 5.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0, -1.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0, -3.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0, -5.0));
|
|
|
|
double qNAN = std::numeric_limits<double>::quiet_NaN();
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, qNAN));
|
|
EXPECT_EQ(0, CallI(test->entry(), qNAN, 3.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0, qNAN));
|
|
EXPECT_EQ(0, CallI(test->entry(), qNAN, -3.0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleLessOrEqual, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fled(A0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleLessOrEqual, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"a2b50553 fle.d a0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, 1.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), 3.0, 3.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), 3.0, 5.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, -1.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, -3.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, -5.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0, 1.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0, 3.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0, 5.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0, -1.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0, -3.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0, -5.0));
|
|
|
|
double qNAN = std::numeric_limits<double>::quiet_NaN();
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, qNAN));
|
|
EXPECT_EQ(0, CallI(test->entry(), qNAN, 3.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0, qNAN));
|
|
EXPECT_EQ(0, CallI(test->entry(), qNAN, -3.0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleClassify, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fclassd(A0, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleClassify, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"e2051553 fclass.d a0, fa0\n"
|
|
"00008067 ret\n");
|
|
// Neg infinity
|
|
EXPECT_EQ(1 << 0,
|
|
CallI(test->entry(), -std::numeric_limits<double>::infinity()));
|
|
// Neg normal
|
|
EXPECT_EQ(1 << 1, CallI(test->entry(), -1.0));
|
|
// Neg subnormal
|
|
EXPECT_EQ(1 << 2,
|
|
CallI(test->entry(), -std::numeric_limits<double>::min() / 2.0));
|
|
// Neg zero
|
|
EXPECT_EQ(1 << 3, CallI(test->entry(), -0.0));
|
|
// Pos zero
|
|
EXPECT_EQ(1 << 4, CallI(test->entry(), 0.0));
|
|
// Pos subnormal
|
|
EXPECT_EQ(1 << 5,
|
|
CallI(test->entry(), std::numeric_limits<double>::min() / 2.0));
|
|
// Pos normal
|
|
EXPECT_EQ(1 << 6, CallI(test->entry(), 1.0));
|
|
// Pos infinity
|
|
EXPECT_EQ(1 << 7,
|
|
CallI(test->entry(), std::numeric_limits<double>::infinity()));
|
|
// Signaling NaN
|
|
EXPECT_EQ(1 << 8,
|
|
CallI(test->entry(), std::numeric_limits<double>::signaling_NaN()));
|
|
// Queit NaN
|
|
EXPECT_EQ(1 << 9,
|
|
CallI(test->entry(), std::numeric_limits<double>::quiet_NaN()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertDoubleToWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtwd(A0, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertDoubleToWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"c2050553 fcvt.w.d a0, fa0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-42, CallI(test->entry(), static_cast<double>(-42)));
|
|
EXPECT_EQ(0, CallI(test->entry(), static_cast<double>(0)));
|
|
EXPECT_EQ(42, CallI(test->entry(), static_cast<double>(42)));
|
|
EXPECT_EQ(sign_extend(kMinInt32),
|
|
CallI(test->entry(), static_cast<double>(kMinInt32)));
|
|
EXPECT_EQ(sign_extend(kMaxInt32),
|
|
CallI(test->entry(), static_cast<double>(kMaxInt32)));
|
|
EXPECT_EQ(sign_extend(kMaxInt32),
|
|
CallI(test->entry(), static_cast<double>(kMaxUint32)));
|
|
EXPECT_EQ(sign_extend(kMinInt32),
|
|
CallI(test->entry(), static_cast<double>(kMinInt64)));
|
|
EXPECT_EQ(sign_extend(kMaxInt32),
|
|
CallI(test->entry(), static_cast<double>(kMaxInt64)));
|
|
EXPECT_EQ(sign_extend(kMaxInt32),
|
|
CallI(test->entry(), static_cast<double>(kMaxUint64)));
|
|
EXPECT_EQ(sign_extend(kMinInt32),
|
|
CallI(test->entry(), -std::numeric_limits<double>::infinity()));
|
|
EXPECT_EQ(sign_extend(kMaxInt32),
|
|
CallI(test->entry(), std::numeric_limits<double>::infinity()));
|
|
EXPECT_EQ(sign_extend(kMaxInt32),
|
|
CallI(test->entry(), std::numeric_limits<double>::signaling_NaN()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertDoubleToUnsignedWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtwud(A0, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertDoubleToUnsignedWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"c2150553 fcvt.wu.d a0, fa0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0, CallI(test->entry(), static_cast<double>(-42)));
|
|
EXPECT_EQ(0, CallI(test->entry(), static_cast<double>(0)));
|
|
EXPECT_EQ(42, CallI(test->entry(), static_cast<double>(42)));
|
|
EXPECT_EQ(sign_extend(0),
|
|
CallI(test->entry(), static_cast<double>(kMinInt32)));
|
|
EXPECT_EQ(sign_extend(kMaxInt32),
|
|
CallI(test->entry(), static_cast<double>(kMaxInt32)));
|
|
EXPECT_EQ(sign_extend(kMaxUint32),
|
|
CallI(test->entry(), static_cast<double>(kMaxUint32)));
|
|
EXPECT_EQ(sign_extend(0),
|
|
CallI(test->entry(), static_cast<double>(kMinInt64)));
|
|
EXPECT_EQ(sign_extend(kMaxUint32),
|
|
CallI(test->entry(), static_cast<double>(kMaxInt64)));
|
|
EXPECT_EQ(sign_extend(kMaxUint32),
|
|
CallI(test->entry(), static_cast<double>(kMaxUint64)));
|
|
EXPECT_EQ(sign_extend(0),
|
|
CallI(test->entry(), -std::numeric_limits<double>::infinity()));
|
|
EXPECT_EQ(sign_extend(kMaxUint32),
|
|
CallI(test->entry(), std::numeric_limits<double>::infinity()));
|
|
EXPECT_EQ(sign_extend(kMaxUint32),
|
|
CallI(test->entry(), std::numeric_limits<double>::signaling_NaN()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertWordToDouble, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtdw(FA0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertWordToDouble, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"d2050553 fcvt.d.w fa0, a0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-42.0, CallD(test->entry(), sign_extend(-42)));
|
|
EXPECT_EQ(0.0, CallD(test->entry(), sign_extend(0)));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), sign_extend(42)));
|
|
EXPECT_EQ(static_cast<double>(kMinInt32),
|
|
CallD(test->entry(), sign_extend(kMinInt32)));
|
|
EXPECT_EQ(static_cast<double>(kMaxInt32),
|
|
CallD(test->entry(), sign_extend(kMaxInt32)));
|
|
EXPECT_EQ(-1.0, CallD(test->entry(), sign_extend(kMaxUint32)));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertUnsignedWordToDouble, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtdwu(FA0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertUnsignedWordToDouble, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"d2150553 fcvt.d.wu fa0, a0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(
|
|
static_cast<double>(static_cast<uint32_t>(static_cast<int32_t>(-42))),
|
|
CallD(test->entry(), sign_extend(-42)));
|
|
EXPECT_EQ(0.0, CallD(test->entry(), sign_extend(0)));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), sign_extend(42)));
|
|
EXPECT_EQ(static_cast<double>(static_cast<uint32_t>(kMinInt32)),
|
|
CallD(test->entry(), sign_extend(kMinInt32)));
|
|
EXPECT_EQ(static_cast<double>(kMaxInt32),
|
|
CallD(test->entry(), sign_extend(kMaxInt32)));
|
|
EXPECT_EQ(static_cast<double>(kMaxUint32),
|
|
CallD(test->entry(), sign_extend(kMaxUint32)));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleMove, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fmvd(FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleMove, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"22b58553 fmv.d fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(36.0, CallD(test->entry(), 42.0, 36.0));
|
|
EXPECT_EQ(std::numeric_limits<double>::infinity(),
|
|
CallD(test->entry(), -std::numeric_limits<double>::infinity(),
|
|
std::numeric_limits<double>::infinity()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleAbsoluteValue, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fabsd(FA0, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleAbsoluteValue, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"22a52553 fabs.d fa0, fa0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0.0, CallD(test->entry(), 0.0));
|
|
EXPECT_EQ(0.0, CallD(test->entry(), -0.0));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), 42.0));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), -42.0));
|
|
EXPECT_EQ(std::numeric_limits<double>::infinity(),
|
|
CallD(test->entry(), std::numeric_limits<double>::infinity()));
|
|
EXPECT_EQ(std::numeric_limits<double>::infinity(),
|
|
CallD(test->entry(), -std::numeric_limits<double>::infinity()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleNegate, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fnegd(FA0, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleNegate, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"22a51553 fneg.d fa0, fa0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-0.0, CallD(test->entry(), 0.0));
|
|
EXPECT_EQ(0.0, CallD(test->entry(), -0.0));
|
|
EXPECT_EQ(-42.0, CallD(test->entry(), 42.0));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), -42.0));
|
|
EXPECT_EQ(-std::numeric_limits<double>::infinity(),
|
|
CallD(test->entry(), std::numeric_limits<double>::infinity()));
|
|
EXPECT_EQ(std::numeric_limits<double>::infinity(),
|
|
CallD(test->entry(), -std::numeric_limits<double>::infinity()));
|
|
}
|
|
|
|
#if XLEN >= 64
|
|
ASSEMBLER_TEST_GENERATE(ConvertDoubleToDoubleWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtld(A0, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertDoubleToDoubleWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"c2250553 fcvt.l.d a0, fa0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-42, CallI(test->entry(), static_cast<double>(-42)));
|
|
EXPECT_EQ(0, CallI(test->entry(), static_cast<double>(0)));
|
|
EXPECT_EQ(42, CallI(test->entry(), static_cast<double>(42)));
|
|
EXPECT_EQ(static_cast<int64_t>(kMinInt32),
|
|
CallI(test->entry(), static_cast<double>(kMinInt32)));
|
|
EXPECT_EQ(static_cast<int64_t>(kMaxInt32),
|
|
CallI(test->entry(), static_cast<double>(kMaxInt32)));
|
|
EXPECT_EQ(static_cast<int64_t>(kMaxUint32),
|
|
CallI(test->entry(), static_cast<double>(kMaxUint32)));
|
|
EXPECT_EQ(kMinInt64, CallI(test->entry(), static_cast<double>(kMinInt64)));
|
|
EXPECT_EQ(kMaxInt64, CallI(test->entry(), static_cast<double>(kMaxInt64)));
|
|
EXPECT_EQ(kMaxInt64, CallI(test->entry(), static_cast<double>(kMaxUint64)));
|
|
EXPECT_EQ(kMinInt64,
|
|
CallI(test->entry(), -std::numeric_limits<double>::infinity()));
|
|
EXPECT_EQ(kMaxInt64,
|
|
CallI(test->entry(), std::numeric_limits<double>::infinity()));
|
|
EXPECT_EQ(kMaxInt64,
|
|
CallI(test->entry(), std::numeric_limits<double>::signaling_NaN()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertDoubleToDoubleWord_RNE, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtld(A0, FA0, RNE);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertDoubleToDoubleWord_RNE, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"c2250553 fcvt.l.d a0, fa0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-44, CallI(test->entry(), -43.6));
|
|
EXPECT_EQ(-44, CallI(test->entry(), -43.5));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.4));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.0));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -42.6));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.5));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.4));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), -0.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), +0.0));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.0));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.4));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.5));
|
|
EXPECT_EQ(43, CallI(test->entry(), 42.6));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.0));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.4));
|
|
EXPECT_EQ(44, CallI(test->entry(), 43.5));
|
|
EXPECT_EQ(44, CallI(test->entry(), 43.6));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertDoubleToDoubleWord_RTZ, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtld(A0, FA0, RTZ);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertDoubleToDoubleWord_RTZ, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"c2251553 fcvt.l.d a0, fa0, rtz\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.6));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.5));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.4));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.0));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.6));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.5));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.4));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), -0.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), +0.0));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.0));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.4));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.5));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.6));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.0));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.4));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.5));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.6));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertDoubleToDoubleWord_RDN, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtld(A0, FA0, RDN);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertDoubleToDoubleWord_RDN, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"c2252553 fcvt.l.d a0, fa0, rdn\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-44, CallI(test->entry(), -43.6));
|
|
EXPECT_EQ(-44, CallI(test->entry(), -43.5));
|
|
EXPECT_EQ(-44, CallI(test->entry(), -43.4));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.0));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -42.6));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -42.5));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -42.4));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), -0.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), +0.0));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.0));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.4));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.5));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.6));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.0));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.4));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.5));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.6));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertDoubleToDoubleWord_RUP, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtld(A0, FA0, RUP);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertDoubleToDoubleWord_RUP, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"c2253553 fcvt.l.d a0, fa0, rup\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.6));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.5));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.4));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.0));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.6));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.5));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.4));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), -0.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), +0.0));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.0));
|
|
EXPECT_EQ(43, CallI(test->entry(), 42.4));
|
|
EXPECT_EQ(43, CallI(test->entry(), 42.5));
|
|
EXPECT_EQ(43, CallI(test->entry(), 42.6));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.0));
|
|
EXPECT_EQ(44, CallI(test->entry(), 43.5));
|
|
EXPECT_EQ(44, CallI(test->entry(), 43.5));
|
|
EXPECT_EQ(44, CallI(test->entry(), 43.6));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertDoubleToDoubleWord_RMM, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtld(A0, FA0, RMM);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertDoubleToDoubleWord_RMM, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"c2254553 fcvt.l.d a0, fa0, rmm\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(-44, CallI(test->entry(), -43.6));
|
|
EXPECT_EQ(-44, CallI(test->entry(), -43.5));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.4));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -43.0));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -42.6));
|
|
EXPECT_EQ(-43, CallI(test->entry(), -42.5));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.4));
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), -0.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), +0.0));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.0));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.4));
|
|
EXPECT_EQ(43, CallI(test->entry(), 42.5));
|
|
EXPECT_EQ(43, CallI(test->entry(), 42.6));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.0));
|
|
EXPECT_EQ(43, CallI(test->entry(), 43.4));
|
|
EXPECT_EQ(44, CallI(test->entry(), 43.5));
|
|
EXPECT_EQ(44, CallI(test->entry(), 43.6));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertDoubleToUnsignedDoubleWord, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtlud(A0, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertDoubleToUnsignedDoubleWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"c2350553 fcvt.lu.d a0, fa0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0, CallI(test->entry(), static_cast<double>(-42)));
|
|
EXPECT_EQ(0, CallI(test->entry(), static_cast<double>(0)));
|
|
EXPECT_EQ(42, CallI(test->entry(), static_cast<double>(42)));
|
|
EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(0)),
|
|
CallI(test->entry(), static_cast<double>(kMinInt32)));
|
|
EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxInt32)),
|
|
CallI(test->entry(), static_cast<double>(kMaxInt32)));
|
|
EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxUint32)),
|
|
CallI(test->entry(), static_cast<double>(kMaxUint32)));
|
|
EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(0)),
|
|
CallI(test->entry(), static_cast<double>(kMinInt64)));
|
|
EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxInt64) + 1),
|
|
CallI(test->entry(), static_cast<double>(kMaxInt64)));
|
|
EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxUint64)),
|
|
CallI(test->entry(), static_cast<double>(kMaxUint64)));
|
|
EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(0)),
|
|
CallI(test->entry(), -std::numeric_limits<double>::infinity()));
|
|
EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxUint64)),
|
|
CallI(test->entry(), std::numeric_limits<double>::infinity()));
|
|
EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxUint64)),
|
|
CallI(test->entry(), std::numeric_limits<double>::signaling_NaN()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(BitCastDoubleToInteger, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fmvxd(A0, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(BitCastDoubleToInteger, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"e2050553 fmv.x.d a0, fa0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(bit_cast<int64_t>(0.0), CallI(test->entry(), 0.0));
|
|
EXPECT_EQ(bit_cast<int64_t>(-0.0), CallI(test->entry(), -0.0));
|
|
EXPECT_EQ(bit_cast<int64_t>(42.0), CallI(test->entry(), 42.0));
|
|
EXPECT_EQ(bit_cast<int64_t>(-42.0), CallI(test->entry(), -42.0));
|
|
EXPECT_EQ(bit_cast<int64_t>(std::numeric_limits<double>::quiet_NaN()),
|
|
CallI(test->entry(), std::numeric_limits<double>::quiet_NaN()));
|
|
EXPECT_EQ(bit_cast<int64_t>(std::numeric_limits<double>::signaling_NaN()),
|
|
CallI(test->entry(), std::numeric_limits<double>::signaling_NaN()));
|
|
EXPECT_EQ(bit_cast<int64_t>(std::numeric_limits<double>::infinity()),
|
|
CallI(test->entry(), std::numeric_limits<double>::infinity()));
|
|
EXPECT_EQ(bit_cast<int64_t>(-std::numeric_limits<double>::infinity()),
|
|
CallI(test->entry(), -std::numeric_limits<double>::infinity()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertDoubleWordToDouble, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtdl(FA0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertDoubleWordToDouble, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"d2250553 fcvt.d.l fa0, a0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0.0, CallD(test->entry(), sign_extend(0)));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), sign_extend(42)));
|
|
EXPECT_EQ(-42.0, CallD(test->entry(), sign_extend(-42)));
|
|
EXPECT_EQ(static_cast<double>(kMinInt32),
|
|
CallD(test->entry(), sign_extend(kMinInt32)));
|
|
EXPECT_EQ(static_cast<double>(kMaxInt32),
|
|
CallD(test->entry(), sign_extend(kMaxInt32)));
|
|
EXPECT_EQ(static_cast<double>(sign_extend(kMaxUint32)),
|
|
CallD(test->entry(), sign_extend(kMaxUint32)));
|
|
EXPECT_EQ(static_cast<double>(kMinInt64),
|
|
CallD(test->entry(), sign_extend(kMinInt64)));
|
|
EXPECT_EQ(static_cast<double>(kMaxInt64),
|
|
CallD(test->entry(), sign_extend(kMaxInt64)));
|
|
EXPECT_EQ(static_cast<double>(sign_extend(kMaxUint64)),
|
|
CallD(test->entry(), sign_extend(kMaxUint64)));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConvertUnsignedDoubleWordToDouble, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fcvtdlu(FA0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConvertUnsignedDoubleWordToDouble, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"d2350553 fcvt.d.lu fa0, a0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0.0, CallD(test->entry(), sign_extend(0)));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), sign_extend(42)));
|
|
EXPECT_EQ(static_cast<double>(static_cast<uint64_t>(sign_extend(-42))),
|
|
CallD(test->entry(), sign_extend(-42)));
|
|
EXPECT_EQ(static_cast<double>(static_cast<uint64_t>(sign_extend(kMinInt32))),
|
|
CallD(test->entry(), sign_extend(kMinInt32)));
|
|
EXPECT_EQ(static_cast<double>(static_cast<uint64_t>(sign_extend(kMaxInt32))),
|
|
CallD(test->entry(), sign_extend(kMaxInt32)));
|
|
EXPECT_EQ(static_cast<double>(static_cast<uint64_t>(sign_extend(kMaxUint32))),
|
|
CallD(test->entry(), sign_extend(kMaxUint32)));
|
|
EXPECT_EQ(static_cast<double>(static_cast<uint64_t>(sign_extend(kMinInt64))),
|
|
CallD(test->entry(), sign_extend(kMinInt64)));
|
|
EXPECT_EQ(static_cast<double>(static_cast<uint64_t>(sign_extend(kMaxInt64))),
|
|
CallD(test->entry(), sign_extend(kMaxInt64)));
|
|
EXPECT_EQ(static_cast<double>(kMaxUint64),
|
|
CallD(test->entry(), sign_extend(kMaxUint64)));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(BitCastIntegerToDouble, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
__ fmvdx(FA0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(BitCastIntegerToDouble, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"f2050553 fmv.d.x fa0, a0\n"
|
|
"00008067 ret\n");
|
|
EXPECT_EQ(0.0, CallD(test->entry(), bit_cast<int64_t>(0.0)));
|
|
EXPECT_EQ(-0.0, CallD(test->entry(), bit_cast<int64_t>(-0.0)));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), bit_cast<int64_t>(42.0)));
|
|
EXPECT_EQ(-42.0, CallD(test->entry(), bit_cast<int64_t>(-42.0)));
|
|
EXPECT_EQ(true, isnan(CallD(test->entry(),
|
|
bit_cast<int64_t>(
|
|
std::numeric_limits<double>::quiet_NaN()))));
|
|
EXPECT_EQ(true,
|
|
isnan(CallD(test->entry(),
|
|
bit_cast<int64_t>(
|
|
std::numeric_limits<double>::signaling_NaN()))));
|
|
EXPECT_EQ(std::numeric_limits<double>::infinity(),
|
|
CallD(test->entry(),
|
|
bit_cast<int64_t>(std::numeric_limits<double>::infinity())));
|
|
EXPECT_EQ(-std::numeric_limits<double>::infinity(),
|
|
CallD(test->entry(),
|
|
bit_cast<int64_t>(-std::numeric_limits<double>::infinity())));
|
|
}
|
|
#endif
|
|
|
|
ASSEMBLER_TEST_GENERATE(Fibonacci, assembler) {
|
|
__ SetExtensions(RV_G);
|
|
Label fib, base, done;
|
|
__ Bind(&fib);
|
|
__ subi(SP, SP, sizeof(uintx_t) * 4);
|
|
__ sx(RA, Address(SP, 3 * sizeof(uintx_t)));
|
|
__ sx(A0, Address(SP, 2 * sizeof(uintx_t)));
|
|
__ subi(A0, A0, 1);
|
|
__ blez(A0, &base);
|
|
|
|
__ jal(&fib);
|
|
__ sx(A0, Address(SP, 1 * sizeof(uintx_t)));
|
|
__ lx(A0, Address(SP, 2 * sizeof(uintx_t)));
|
|
__ subi(A0, A0, 2);
|
|
__ jal(&fib);
|
|
__ lx(A1, Address(SP, 1 * sizeof(uintx_t)));
|
|
__ add(A0, A0, A1);
|
|
__ j(&done);
|
|
|
|
__ Bind(&base);
|
|
__ li(A0, 1);
|
|
|
|
__ Bind(&done);
|
|
__ lx(RA, Address(SP, 3 * sizeof(uintx_t)));
|
|
__ addi(SP, SP, sizeof(uintx_t) * 4);
|
|
__ ret();
|
|
__ trap();
|
|
}
|
|
ASSEMBLER_TEST_RUN(Fibonacci, test) {
|
|
#if XLEN == 32
|
|
EXPECT_DISASSEMBLY(
|
|
"ff010113 addi sp, sp, -16\n"
|
|
"00112623 sw ra, 12(sp)\n"
|
|
"00a12423 sw a0, 8(sp)\n"
|
|
"fff50513 addi a0, a0, -1\n"
|
|
"02a05263 blez a0, +36\n"
|
|
"fedff0ef jal -20\n"
|
|
"00a12223 sw a0, 4(sp)\n"
|
|
"00812503 lw a0, 8(sp)\n"
|
|
"ffe50513 addi a0, a0, -2\n"
|
|
"fddff0ef jal -36\n"
|
|
"00412583 lw a1, 4(sp)\n"
|
|
"00b50533 add a0, a0, a1\n"
|
|
"0080006f j +8\n"
|
|
"00100513 li a0, 1\n"
|
|
"00c12083 lw ra, 12(sp)\n"
|
|
"01010113 addi sp, sp, 16\n"
|
|
"00008067 ret\n"
|
|
"00000000 trap\n");
|
|
#elif XLEN == 64
|
|
EXPECT_DISASSEMBLY(
|
|
"fe010113 addi sp, sp, -32\n"
|
|
"00113c23 sd ra, 24(sp)\n"
|
|
"00a13823 sd a0, 16(sp)\n"
|
|
"fff50513 addi a0, a0, -1\n"
|
|
"02a05263 blez a0, +36\n"
|
|
"fedff0ef jal -20\n"
|
|
"00a13423 sd a0, 8(sp)\n"
|
|
"01013503 ld a0, 16(sp)\n"
|
|
"ffe50513 addi a0, a0, -2\n"
|
|
"fddff0ef jal -36\n"
|
|
"00813583 ld a1, 8(sp)\n"
|
|
"00b50533 add a0, a0, a1\n"
|
|
"0080006f j +8\n"
|
|
"00100513 li a0, 1\n"
|
|
"01813083 ld ra, 24(sp)\n"
|
|
"02010113 addi sp, sp, 32\n"
|
|
"00008067 ret\n"
|
|
"00000000 trap\n");
|
|
#else
|
|
#error Unimplemented
|
|
#endif
|
|
EXPECT_EQ(1, Call(test->entry(), 0));
|
|
EXPECT_EQ(1, Call(test->entry(), 1));
|
|
EXPECT_EQ(2, Call(test->entry(), 2));
|
|
EXPECT_EQ(3, Call(test->entry(), 3));
|
|
EXPECT_EQ(5, Call(test->entry(), 4));
|
|
EXPECT_EQ(8, Call(test->entry(), 5));
|
|
EXPECT_EQ(13, Call(test->entry(), 6));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedLoadStoreWordSP_0, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
|
|
__ subi(SP, SP, 256);
|
|
__ sw(A1, Address(SP, 0));
|
|
__ lw(A0, Address(SP, 0));
|
|
__ addi(SP, SP, 256);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedLoadStoreWordSP_0, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 7111 addi sp, sp, -256\n"
|
|
" c02e sw a1, 0(sp)\n"
|
|
" 4502 lw a0, 0(sp)\n"
|
|
" 6111 addi sp, sp, 256\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(sign_extend(0xAB010203), Call(test->entry(), 0, 0xAB010203));
|
|
EXPECT_EQ(sign_extend(0xCD020405), Call(test->entry(), 0, 0xCD020405));
|
|
EXPECT_EQ(sign_extend(0xEF030607), Call(test->entry(), 0, 0xEF030607));
|
|
}
|
|
ASSEMBLER_TEST_GENERATE(CompressedLoadStoreWordSP_Pos, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
|
|
__ subi(SP, SP, 256);
|
|
__ sw(A1, Address(SP, 4));
|
|
__ lw(A0, Address(SP, 4));
|
|
__ addi(SP, SP, 256);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedLoadStoreWordSP_Pos, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 7111 addi sp, sp, -256\n"
|
|
" c22e sw a1, 4(sp)\n"
|
|
" 4512 lw a0, 4(sp)\n"
|
|
" 6111 addi sp, sp, 256\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(sign_extend(0xAB010203), Call(test->entry(), 0, 0xAB010203));
|
|
EXPECT_EQ(sign_extend(0xCD020405), Call(test->entry(), 0, 0xCD020405));
|
|
EXPECT_EQ(sign_extend(0xEF030607), Call(test->entry(), 0, 0xEF030607));
|
|
}
|
|
|
|
#if XLEN == 32
|
|
ASSEMBLER_TEST_GENERATE(CompressedLoadStoreSingleFloatSP_0, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ subi(SP, SP, 256);
|
|
__ fsw(FA1, Address(SP, 0));
|
|
__ flw(FA0, Address(SP, 0));
|
|
__ addi(SP, SP, 256);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedLoadStoreSingleFloatSP_0, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 7111 addi sp, sp, -256\n"
|
|
" e02e fsw fa1, 0(sp)\n"
|
|
" 6502 flw fa0, 0(sp)\n"
|
|
" 6111 addi sp, sp, 256\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(1.7f, CallF(test->entry(), 0.0f, 1.7f));
|
|
EXPECT_EQ(2.8f, CallF(test->entry(), 0.0f, 2.8f));
|
|
EXPECT_EQ(3.9f, CallF(test->entry(), 0.0f, 3.9f));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedLoadStoreSingleFloatSP_Pos, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ subi(SP, SP, 256);
|
|
__ fsw(FA1, Address(SP, 4));
|
|
__ flw(FA0, Address(SP, 4));
|
|
__ addi(SP, SP, 256);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedLoadStoreSingleFloatSP_Pos, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 7111 addi sp, sp, -256\n"
|
|
" e22e fsw fa1, 4(sp)\n"
|
|
" 6512 flw fa0, 4(sp)\n"
|
|
" 6111 addi sp, sp, 256\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(1.7f, CallF(test->entry(), 0.0f, 1.7f));
|
|
EXPECT_EQ(2.8f, CallF(test->entry(), 0.0f, 2.8f));
|
|
EXPECT_EQ(3.9f, CallF(test->entry(), 0.0f, 3.9f));
|
|
}
|
|
#endif
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedLoadStoreDoubleFloatSP_0, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ subi(SP, SP, 256);
|
|
__ fsd(FA1, Address(SP, 0));
|
|
__ fld(FA0, Address(SP, 0));
|
|
__ addi(SP, SP, 256);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedLoadStoreDoubleFloatSP_0, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 7111 addi sp, sp, -256\n"
|
|
" a02e fsd fa1, 0(sp)\n"
|
|
" 2502 fld fa0, 0(sp)\n"
|
|
" 6111 addi sp, sp, 256\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(1.7, CallD(test->entry(), 0.0, 1.7));
|
|
EXPECT_EQ(2.8, CallD(test->entry(), 0.0, 2.8));
|
|
EXPECT_EQ(3.9, CallD(test->entry(), 0.0, 3.9));
|
|
}
|
|
ASSEMBLER_TEST_GENERATE(CompressedLoadStoreDoubleFloatSP_Pos, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ subi(SP, SP, 256);
|
|
__ fsd(FA1, Address(SP, 8));
|
|
__ fld(FA0, Address(SP, 8));
|
|
__ addi(SP, SP, 256);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedLoadStoreDoubleFloatSP_Pos, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 7111 addi sp, sp, -256\n"
|
|
" a42e fsd fa1, 8(sp)\n"
|
|
" 2522 fld fa0, 8(sp)\n"
|
|
" 6111 addi sp, sp, 256\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(1.7, CallD(test->entry(), 0.0, 1.7));
|
|
EXPECT_EQ(2.8, CallD(test->entry(), 0.0, 2.8));
|
|
EXPECT_EQ(3.9, CallD(test->entry(), 0.0, 3.9));
|
|
}
|
|
|
|
#if XLEN >= 64
|
|
ASSEMBLER_TEST_GENERATE(CompressedLoadStoreDoubleWordSP_0, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ subi(SP, SP, 256);
|
|
__ sd(A1, Address(SP, 0));
|
|
__ ld(A0, Address(SP, 0));
|
|
__ addi(SP, SP, 256);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedLoadStoreDoubleWordSP_0, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 7111 addi sp, sp, -256\n"
|
|
" e02e sd a1, 0(sp)\n"
|
|
" 6502 ld a0, 0(sp)\n"
|
|
" 6111 addi sp, sp, 256\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ((intx_t)0xAB01020304050607,
|
|
Call(test->entry(), 0, 0xAB01020304050607));
|
|
EXPECT_EQ((intx_t)0xCD02040505060708,
|
|
Call(test->entry(), 0, 0xCD02040505060708));
|
|
EXPECT_EQ((intx_t)0xEF03060708090A0B,
|
|
Call(test->entry(), 0, 0xEF03060708090A0B));
|
|
}
|
|
ASSEMBLER_TEST_GENERATE(CompressedLoadStoreDoubleWordSP_Pos, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ subi(SP, SP, 256);
|
|
__ sd(A1, Address(SP, 8));
|
|
__ ld(A0, Address(SP, 8));
|
|
__ addi(SP, SP, 256);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedLoadStoreDoubleWordSP_Pos, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 7111 addi sp, sp, -256\n"
|
|
" e42e sd a1, 8(sp)\n"
|
|
" 6522 ld a0, 8(sp)\n"
|
|
" 6111 addi sp, sp, 256\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ((intx_t)0xAB01020304050607,
|
|
Call(test->entry(), 0, 0xAB01020304050607));
|
|
EXPECT_EQ((intx_t)0xCD02040505060708,
|
|
Call(test->entry(), 0, 0xCD02040505060708));
|
|
EXPECT_EQ((intx_t)0xEF03060708090A0B,
|
|
Call(test->entry(), 0, 0xEF03060708090A0B));
|
|
}
|
|
#endif
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedLoadWord_0, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ lw(A0, Address(A0, 0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedLoadWord_0, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 4108 lw a0, 0(a0)\n"
|
|
" 8082 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(CompressedLoadWord_Pos, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ lw(A0, Address(A0, 4));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedLoadWord_Pos, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 4148 lw a0, 4(a0)\n"
|
|
" 8082 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(CompressedStoreWord_0, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ sw(A1, Address(A0, 0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedStoreWord_0, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" c10c sw a1, 0(a0)\n"
|
|
" 8082 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(CompressedStoreWord_Pos, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ sw(A1, Address(A0, 4));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedStoreWord_Pos, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" c14c sw a1, 4(a0)\n"
|
|
" 8082 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]);
|
|
}
|
|
|
|
#if XLEN == 32
|
|
ASSEMBLER_TEST_GENERATE(CompressedLoadSingleFloat, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ flw(FA0, Address(A0, 1 * sizeof(float)));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedLoadSingleFloat, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 6148 flw fa0, 4(a0)\n"
|
|
" 8082 ret\n");
|
|
|
|
float* data = reinterpret_cast<float*>(malloc(3 * sizeof(float)));
|
|
data[0] = 1.7f;
|
|
data[1] = 2.8f;
|
|
data[2] = 3.9f;
|
|
EXPECT_EQ(data[1], CallF(test->entry(), reinterpret_cast<intx_t>(data)));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedStoreSingleFloat, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ fsw(FA0, Address(A0, 1 * sizeof(float)));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedStoreSingleFloat, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" e148 fsw fa0, 4(a0)\n"
|
|
" 8082 ret\n");
|
|
|
|
float* data = reinterpret_cast<float*>(malloc(3 * sizeof(float)));
|
|
data[0] = 1.7f;
|
|
data[1] = 2.8f;
|
|
data[2] = 3.9f;
|
|
CallF(test->entry(), reinterpret_cast<intx_t>(data), 4.2f);
|
|
EXPECT_EQ(4.2f, data[1]);
|
|
}
|
|
#endif
|
|
|
|
#if XLEN >= 64
|
|
ASSEMBLER_TEST_GENERATE(CompressedLoadDoubleWord_0, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ ld(A0, Address(A0, 0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedLoadDoubleWord_0, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 6108 ld a0, 0(a0)\n"
|
|
" 8082 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(CompressedLoadDoubleWord_Pos, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ ld(A0, Address(A0, 8));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedLoadDoubleWord_Pos, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 6508 ld a0, 8(a0)\n"
|
|
" 8082 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(CompressedStoreDoubleWord_0, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ sd(A1, Address(A0, 0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedStoreDoubleWord_0, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" e10c sd a1, 0(a0)\n"
|
|
" 8082 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(CompressedStoreDoubleWord_Pos, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ sd(A1, Address(A0, 8));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedStoreDoubleWord_Pos, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" e50c sd a1, 8(a0)\n"
|
|
" 8082 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(CompressedLoadDoubleFloat, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ fld(FA0, Address(A0, 1 * sizeof(double)));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedLoadDoubleFloat, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 2508 fld fa0, 8(a0)\n"
|
|
" 8082 ret\n");
|
|
|
|
double* data = reinterpret_cast<double*>(malloc(3 * sizeof(double)));
|
|
data[0] = 1.7;
|
|
data[1] = 2.8;
|
|
data[2] = 3.9;
|
|
EXPECT_EQ(data[1], CallD(test->entry(), reinterpret_cast<intx_t>(data)));
|
|
free(data);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedStoreDoubleFloat, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ fsd(FA0, Address(A0, 1 * sizeof(double)));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedStoreDoubleFloat, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" a508 fsd fa0, 8(a0)\n"
|
|
" 8082 ret\n");
|
|
|
|
double* data = reinterpret_cast<double*>(malloc(3 * sizeof(double)));
|
|
data[0] = 1.7;
|
|
data[1] = 2.8;
|
|
data[2] = 3.9;
|
|
CallD(test->entry(), reinterpret_cast<intx_t>(data), 4.2);
|
|
EXPECT_EQ(4.2, data[1]);
|
|
}
|
|
#endif
|
|
|
|
#if XLEN == 32
|
|
ASSEMBLER_TEST_GENERATE(CompressedJumpAndLink, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
|
|
Label label1, label2;
|
|
__ mv(T3, RA);
|
|
__ jal(&label1, Assembler::kNearJump); // Forward.
|
|
__ sub(A0, T0, T1);
|
|
__ mv(RA, T3);
|
|
__ ret();
|
|
__ trap();
|
|
|
|
__ Bind(&label2);
|
|
__ mv(T5, RA);
|
|
__ li(T1, 7);
|
|
__ jr(T5);
|
|
__ trap();
|
|
|
|
__ Bind(&label1);
|
|
__ mv(T4, RA);
|
|
__ li(T0, 4);
|
|
__ jal(&label2, Assembler::kNearJump); // Backward.
|
|
__ mv(RA, T4);
|
|
__ jr(T4);
|
|
__ trap();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedJumpAndLink, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 8e06 mv t3, ra\n"
|
|
" 2811 jal +20\n"
|
|
"40628533 sub a0, t0, t1\n"
|
|
" 80f2 mv ra, t3\n"
|
|
" 8082 ret\n"
|
|
" 0000 trap\n"
|
|
" 8f06 mv t5, ra\n"
|
|
" 431d li t1, 7\n"
|
|
" 8f02 jr t5\n"
|
|
" 0000 trap\n"
|
|
" 8e86 mv t4, ra\n"
|
|
" 4291 li t0, 4\n"
|
|
" 3fd5 jal -12\n"
|
|
" 80f6 mv ra, t4\n"
|
|
" 8e82 jr t4\n"
|
|
" 0000 trap\n");
|
|
EXPECT_EQ(-3, Call(test->entry()));
|
|
}
|
|
#endif
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedJump, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
Label label1, label2;
|
|
__ j(&label1, Assembler::kNearJump); // Forward.
|
|
__ trap();
|
|
__ Bind(&label2);
|
|
__ li(T1, 7);
|
|
__ sub(A0, T0, T1);
|
|
__ ret();
|
|
__ Bind(&label1);
|
|
__ li(T0, 4);
|
|
__ j(&label2, Assembler::kNearJump); // Backward.
|
|
__ trap();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedJump, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" a031 j +12\n"
|
|
" 0000 trap\n"
|
|
" 431d li t1, 7\n"
|
|
"40628533 sub a0, t0, t1\n"
|
|
" 8082 ret\n"
|
|
" 4291 li t0, 4\n"
|
|
" bfdd j -10\n"
|
|
" 0000 trap\n");
|
|
EXPECT_EQ(-3, Call(test->entry()));
|
|
}
|
|
|
|
static int CompressedJumpAndLinkRegister_label1 = 0;
|
|
static int CompressedJumpAndLinkRegister_label2 = 0;
|
|
ASSEMBLER_TEST_GENERATE(CompressedJumpAndLinkRegister, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
Label label1, label2;
|
|
__ mv(T3, RA);
|
|
__ jalr(A1); // Forward.
|
|
__ sub(A0, T0, T1);
|
|
__ jr(T3);
|
|
__ trap();
|
|
|
|
__ Bind(&label2);
|
|
__ mv(T5, RA);
|
|
__ li(T1, 7);
|
|
__ jr(T5);
|
|
__ trap();
|
|
|
|
__ Bind(&label1);
|
|
__ mv(T4, RA);
|
|
__ li(T0, 4);
|
|
__ jalr(A2); // Backward.
|
|
__ jr(T4);
|
|
__ trap();
|
|
|
|
CompressedJumpAndLinkRegister_label1 = label1.Position();
|
|
CompressedJumpAndLinkRegister_label2 = label2.Position();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedJumpAndLinkRegister, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 8e06 mv t3, ra\n"
|
|
" 9582 jalr a1\n"
|
|
"40628533 sub a0, t0, t1\n"
|
|
" 8e02 jr t3\n"
|
|
" 0000 trap\n"
|
|
" 8f06 mv t5, ra\n"
|
|
" 431d li t1, 7\n"
|
|
" 8f02 jr t5\n"
|
|
" 0000 trap\n"
|
|
" 8e86 mv t4, ra\n"
|
|
" 4291 li t0, 4\n"
|
|
" 9602 jalr a2\n"
|
|
" 8e82 jr t4\n"
|
|
" 0000 trap\n");
|
|
EXPECT_EQ(-3,
|
|
Call(test->entry(), 0,
|
|
static_cast<intx_t>(test->entry() +
|
|
CompressedJumpAndLinkRegister_label1),
|
|
static_cast<intx_t>(test->entry() +
|
|
CompressedJumpAndLinkRegister_label2)));
|
|
}
|
|
|
|
static int CompressedJumpRegister_label = 0;
|
|
ASSEMBLER_TEST_GENERATE(CompressedJumpRegister, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
Label label;
|
|
__ jr(A1);
|
|
__ trap();
|
|
__ Bind(&label);
|
|
__ li(A0, 42);
|
|
__ ret();
|
|
CompressedJumpRegister_label = label.Position();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedJumpRegister, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 8582 jr a1\n"
|
|
" 0000 trap\n"
|
|
"02a00513 li a0, 42\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(42, Call(test->entry(), 0,
|
|
static_cast<intx_t>(test->entry() +
|
|
CompressedJumpRegister_label)));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedBranchEqualZero, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
Label label;
|
|
__ beqz(A0, &label, Assembler::kNearJump);
|
|
__ li(A0, 3);
|
|
__ ret();
|
|
__ Bind(&label);
|
|
__ li(A0, 4);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedBranchEqualZero, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" c119 beqz a0, +6\n"
|
|
" 450d li a0, 3\n"
|
|
" 8082 ret\n"
|
|
" 4511 li a0, 4\n"
|
|
" 8082 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(CompressedBranchNotEqualZero, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
Label label;
|
|
__ bnez(A0, &label, Assembler::kNearJump);
|
|
__ li(A0, 3);
|
|
__ ret();
|
|
__ Bind(&label);
|
|
__ li(A0, 4);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedBranchNotEqualZero, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" e119 bnez a0, +6\n"
|
|
" 450d li a0, 3\n"
|
|
" 8082 ret\n"
|
|
" 4511 li a0, 4\n"
|
|
" 8082 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(CompressedLoadImmediate, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ li(A0, -7);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedLoadImmediate, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 5565 li a0, -7\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(-7, Call(test->entry()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedLoadUpperImmediate, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ lui(A0, 7 << 12);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedLoadUpperImmediate, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 651d lui a0, 28672\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(7 << 12, Call(test->entry()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedAddImmediate, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ addi(A0, A0, 19);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedAddImmediate, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 054d addi a0, a0, 19\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(42, Call(test->entry(), 23));
|
|
}
|
|
|
|
#if XLEN == 64
|
|
ASSEMBLER_TEST_GENERATE(CompressedAddImmediateWord, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ addiw(A0, A0, 19);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedAddImmediateWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 254d addiw a0, a0, 19\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(19, Call(test->entry(), 0xFFFFFFFF00000000));
|
|
EXPECT_EQ(-237, Call(test->entry(), 0x00000000FFFFFF00));
|
|
}
|
|
#endif
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedAddImmediateSP16, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ addi(SP, SP, -128);
|
|
__ addi(SP, SP, +128);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedAddImmediateSP16, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 7119 addi sp, sp, -128\n"
|
|
" 6109 addi sp, sp, 128\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(0, Call(test->entry(), 0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedAddImmediateSP4N, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ addi(A1, SP, 36);
|
|
__ sub(A0, A1, SP);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedAddImmediateSP4N, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 104c addi a1, sp, 36\n"
|
|
"40258533 sub a0, a1, sp\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(36, Call(test->entry()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedShiftLeftLogicalImmediate, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ slli(A0, A0, 3);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedShiftLeftLogicalImmediate, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 050e slli a0, a0, 0x3\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(0, Call(test->entry(), 0));
|
|
EXPECT_EQ(336, Call(test->entry(), 42));
|
|
EXPECT_EQ(15872, Call(test->entry(), 1984));
|
|
EXPECT_EQ(-336, Call(test->entry(), -42));
|
|
EXPECT_EQ(-15872, Call(test->entry(), -1984));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedShiftLeftLogicalImmediate_Max, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ slli(A0, A0, XLEN - 1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedShiftLeftLogicalImmediate_Max, test) {
|
|
#if XLEN == 32
|
|
EXPECT_DISASSEMBLY(
|
|
" 057e slli a0, a0, 0x1f\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(0, Call(test->entry(), 0));
|
|
EXPECT_EQ(static_cast<intx_t>(0x80000000), Call(test->entry(), 1));
|
|
EXPECT_EQ(static_cast<intx_t>(0x80000000), Call(test->entry(), -1));
|
|
#elif XLEN == 64
|
|
EXPECT_DISASSEMBLY(
|
|
" 157e slli a0, a0, 0x3f\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(0, Call(test->entry(), 0));
|
|
EXPECT_EQ(static_cast<intx_t>(0x8000000000000000), Call(test->entry(), 1));
|
|
EXPECT_EQ(static_cast<intx_t>(0x8000000000000000), Call(test->entry(), -1));
|
|
#endif
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedShiftRightLogicalImmediate, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ srli(A0, A0, 3);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedShiftRightLogicalImmediate, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 810d srli a0, a0, 0x3\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(0, Call(test->entry(), 0));
|
|
EXPECT_EQ(5, Call(test->entry(), 42));
|
|
EXPECT_EQ(248, Call(test->entry(), 1984));
|
|
EXPECT_EQ(static_cast<intx_t>(static_cast<uintx_t>(-42) >> 3),
|
|
Call(test->entry(), -42));
|
|
EXPECT_EQ(static_cast<intx_t>(static_cast<uintx_t>(-1984) >> 3),
|
|
Call(test->entry(), -1984));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedShiftRightLogicalImmediate_Max, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ srli(A0, A0, XLEN - 1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedShiftRightLogicalImmediate_Max, test) {
|
|
#if XLEN == 32
|
|
EXPECT_DISASSEMBLY(
|
|
" 817d srli a0, a0, 0x1f\n"
|
|
" 8082 ret\n");
|
|
#elif XLEN == 64
|
|
EXPECT_DISASSEMBLY(
|
|
" 917d srli a0, a0, 0x3f\n"
|
|
" 8082 ret\n");
|
|
#endif
|
|
EXPECT_EQ(0, Call(test->entry(), 0));
|
|
EXPECT_EQ(0, Call(test->entry(), 1));
|
|
EXPECT_EQ(1, Call(test->entry(), -1));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedShiftRightArithmeticImmediate, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ srai(A0, A0, 3);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedShiftRightArithmeticImmediate, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 850d srai a0, a0, 0x3\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(0, Call(test->entry(), 0));
|
|
EXPECT_EQ(5, Call(test->entry(), 42));
|
|
EXPECT_EQ(248, Call(test->entry(), 1984));
|
|
EXPECT_EQ(-6, Call(test->entry(), -42));
|
|
EXPECT_EQ(-248, Call(test->entry(), -1984));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedShiftRightArithmeticImmediate_Max,
|
|
assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ srai(A0, A0, XLEN - 1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedShiftRightArithmeticImmediate_Max, test) {
|
|
#if XLEN == 32
|
|
EXPECT_DISASSEMBLY(
|
|
" 857d srai a0, a0, 0x1f\n"
|
|
" 8082 ret\n");
|
|
#elif XLEN == 64
|
|
EXPECT_DISASSEMBLY(
|
|
" 957d srai a0, a0, 0x3f\n"
|
|
" 8082 ret\n");
|
|
#endif
|
|
EXPECT_EQ(0, Call(test->entry(), 0));
|
|
EXPECT_EQ(0, Call(test->entry(), 1));
|
|
EXPECT_EQ(-1, Call(test->entry(), -1));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedAndImmediate, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ andi(A0, A0, 6);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedAndImmediate, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 8919 andi a0, a0, 6\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(0, Call(test->entry(), 0));
|
|
EXPECT_EQ(2, Call(test->entry(), 43));
|
|
EXPECT_EQ(0, Call(test->entry(), 1984));
|
|
EXPECT_EQ(6, Call(test->entry(), -42));
|
|
EXPECT_EQ(0, Call(test->entry(), -1984));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedAndImmediate2, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ andi(A0, A0, -6);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedAndImmediate2, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 9969 andi a0, a0, -6\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(0, Call(test->entry(), 0));
|
|
EXPECT_EQ(42, Call(test->entry(), 43));
|
|
EXPECT_EQ(1984, Call(test->entry(), 1984));
|
|
EXPECT_EQ(-46, Call(test->entry(), -42));
|
|
EXPECT_EQ(-1984, Call(test->entry(), -1984));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedMove, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ mv(A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedMove, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 852e mv a0, a1\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(42, Call(test->entry(), 0, 42));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedAdd, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ add(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedAdd, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 952e add a0, a0, a1\n"
|
|
" 8082 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(CompressedAnd, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ and_(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedAnd, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 8d6d and a0, a0, a1\n"
|
|
" 8082 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(CompressedOr, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ or_(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedOr, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 8d4d or a0, a0, a1\n"
|
|
" 8082 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(CompressedXor, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ xor_(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedXor, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 8d2d xor a0, a0, a1\n"
|
|
" 8082 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(CompressedSubtract, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ sub(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedSubtract, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 8d0d sub a0, a0, a1\n"
|
|
" 8082 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));
|
|
}
|
|
|
|
#if XLEN >= 64
|
|
ASSEMBLER_TEST_GENERATE(CompressedAddWord, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ addw(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedAddWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 9d2d addw a0, a0, a1\n"
|
|
" 8082 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(CompressedSubtractWord, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ subw(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedSubtractWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 9d0d subw a0, a0, a1\n"
|
|
" 8082 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));
|
|
}
|
|
#endif
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedNop, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ nop();
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedNop, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 0001 nop\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(123, Call(test->entry(), 123));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedEnvironmentBreak, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ ebreak();
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedEnvironmentBreak, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 9002 ebreak\n"
|
|
" 8082 ret\n");
|
|
|
|
// Not running: would trap.
|
|
}
|
|
|
|
#if XLEN >= 64
|
|
ASSEMBLER_TEST_GENERATE(AddUnsignedWord, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ adduw(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AddUnsignedWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"08b5053b add.uw a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(0x200000001, Call(test->entry(), 0x1, 0x200000000));
|
|
EXPECT_EQ(0x200000001, Call(test->entry(), 0x100000001, 0x200000000));
|
|
EXPECT_EQ(0x2FFFFFFFF, Call(test->entry(), -0x1, 0x200000000));
|
|
}
|
|
#endif
|
|
|
|
ASSEMBLER_TEST_GENERATE(Shift1Add, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ sh1add(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(Shift1Add, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"20b52533 sh1add a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(1002, Call(test->entry(), 1, 1000));
|
|
EXPECT_EQ(1000, Call(test->entry(), 0, 1000));
|
|
EXPECT_EQ(998, Call(test->entry(), -1, 1000));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(Shift2Add, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ sh2add(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(Shift2Add, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"20b54533 sh2add a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(1004, Call(test->entry(), 1, 1000));
|
|
EXPECT_EQ(1000, Call(test->entry(), 0, 1000));
|
|
EXPECT_EQ(996, Call(test->entry(), -1, 1000));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(Shift3Add, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ sh3add(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(Shift3Add, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"20b56533 sh3add a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(1008, Call(test->entry(), 1, 1000));
|
|
EXPECT_EQ(1000, Call(test->entry(), 0, 1000));
|
|
EXPECT_EQ(992, Call(test->entry(), -1, 1000));
|
|
}
|
|
|
|
#if XLEN >= 64
|
|
ASSEMBLER_TEST_GENERATE(Shift1AddUnsignedWord, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ sh1adduw(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(Shift1AddUnsignedWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"20b5253b sh1add.uw a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(1002, Call(test->entry(), 1, 1000));
|
|
EXPECT_EQ(1002, Call(test->entry(), 0x100000001, 1000));
|
|
EXPECT_EQ(1000, Call(test->entry(), 0, 1000));
|
|
EXPECT_EQ(8589935590, Call(test->entry(), -1, 1000));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(Shift2AddUnsignedWord, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ sh2adduw(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(Shift2AddUnsignedWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"20b5453b sh2add.uw a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(1004, Call(test->entry(), 1, 1000));
|
|
EXPECT_EQ(1004, Call(test->entry(), 0x100000001, 1000));
|
|
EXPECT_EQ(1000, Call(test->entry(), 0, 1000));
|
|
EXPECT_EQ(17179870180, Call(test->entry(), -1, 1000));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(Shift3AddUnsignedWord, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ sh3adduw(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(Shift3AddUnsignedWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"20b5653b sh3add.uw a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(1008, Call(test->entry(), 1, 1000));
|
|
EXPECT_EQ(1008, Call(test->entry(), 0x100000001, 1000));
|
|
EXPECT_EQ(1000, Call(test->entry(), 0, 1000));
|
|
EXPECT_EQ(34359739360, Call(test->entry(), -1, 1000));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ShiftLeftLogicalImmediateUnsignedWord, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ slliuw(A0, A0, 8);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ShiftLeftLogicalImmediateUnsignedWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"0885151b slli.uw a0, a0, 0x8\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(0x100, Call(test->entry(), 0x1));
|
|
EXPECT_EQ(0x1000000000, Call(test->entry(), 0x10000000));
|
|
EXPECT_EQ(0, Call(test->entry(), 0x100000000));
|
|
EXPECT_EQ(0x100, Call(test->entry(), 0x100000001));
|
|
}
|
|
#endif
|
|
|
|
ASSEMBLER_TEST_GENERATE(AndNot, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ andn(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AndNot, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"40b57533 andn a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(6, Call(test->entry(), 7, 17));
|
|
EXPECT_EQ(0, Call(test->entry(), 7, -17));
|
|
EXPECT_EQ(-24, Call(test->entry(), -7, 17));
|
|
EXPECT_EQ(16, Call(test->entry(), -7, -17));
|
|
EXPECT_EQ(16, Call(test->entry(), 17, 7));
|
|
EXPECT_EQ(0, Call(test->entry(), 17, -7));
|
|
EXPECT_EQ(-24, Call(test->entry(), -17, 7));
|
|
EXPECT_EQ(6, Call(test->entry(), -17, -7));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(OrNot, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ orn(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(OrNot, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"40b56533 orn a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(-17, Call(test->entry(), 7, 17));
|
|
EXPECT_EQ(23, Call(test->entry(), 7, -17));
|
|
EXPECT_EQ(-1, Call(test->entry(), -7, 17));
|
|
EXPECT_EQ(-7, Call(test->entry(), -7, -17));
|
|
EXPECT_EQ(-7, Call(test->entry(), 17, 7));
|
|
EXPECT_EQ(23, Call(test->entry(), 17, -7));
|
|
EXPECT_EQ(-1, Call(test->entry(), -17, 7));
|
|
EXPECT_EQ(-17, Call(test->entry(), -17, -7));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(XorNot, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ xnor(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(XorNot, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"40b54533 xnor a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(-23, Call(test->entry(), 7, 17));
|
|
EXPECT_EQ(23, Call(test->entry(), 7, -17));
|
|
EXPECT_EQ(23, Call(test->entry(), -7, 17));
|
|
EXPECT_EQ(-23, Call(test->entry(), -7, -17));
|
|
EXPECT_EQ(-23, Call(test->entry(), 17, 7));
|
|
EXPECT_EQ(23, Call(test->entry(), 17, -7));
|
|
EXPECT_EQ(23, Call(test->entry(), -17, 7));
|
|
EXPECT_EQ(-23, Call(test->entry(), -17, -7));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CountLeadingZeroes, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ clz(A0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CountLeadingZeroes, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"60051513 clz a0, a0\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(XLEN, Call(test->entry(), 0));
|
|
EXPECT_EQ(XLEN - 1, Call(test->entry(), 1));
|
|
EXPECT_EQ(XLEN - 2, Call(test->entry(), 2));
|
|
EXPECT_EQ(XLEN - 3, Call(test->entry(), 4));
|
|
EXPECT_EQ(XLEN - 8, Call(test->entry(), 240));
|
|
EXPECT_EQ(0, Call(test->entry(), -1));
|
|
EXPECT_EQ(0, Call(test->entry(), -2));
|
|
EXPECT_EQ(0, Call(test->entry(), -4));
|
|
EXPECT_EQ(0, Call(test->entry(), -240));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CountTrailingZeroes, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ ctz(A0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CountTrailingZeroes, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"60151513 ctz a0, a0\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(XLEN, Call(test->entry(), 0));
|
|
EXPECT_EQ(0, Call(test->entry(), 1));
|
|
EXPECT_EQ(1, Call(test->entry(), 2));
|
|
EXPECT_EQ(2, Call(test->entry(), 4));
|
|
EXPECT_EQ(4, Call(test->entry(), 240));
|
|
EXPECT_EQ(0, Call(test->entry(), -1));
|
|
EXPECT_EQ(1, Call(test->entry(), -2));
|
|
EXPECT_EQ(2, Call(test->entry(), -4));
|
|
EXPECT_EQ(4, Call(test->entry(), -240));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CountPopulation, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ cpop(A0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CountPopulation, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"60251513 cpop a0, a0\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(0, Call(test->entry(), 0));
|
|
EXPECT_EQ(1, Call(test->entry(), 1));
|
|
EXPECT_EQ(3, Call(test->entry(), 7));
|
|
EXPECT_EQ(4, Call(test->entry(), 30));
|
|
EXPECT_EQ(XLEN, Call(test->entry(), -1));
|
|
EXPECT_EQ(XLEN - 2, Call(test->entry(), -7));
|
|
EXPECT_EQ(XLEN - 4, Call(test->entry(), -30));
|
|
}
|
|
|
|
#if XLEN >= 64
|
|
ASSEMBLER_TEST_GENERATE(CountLeadingZeroesWord, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ clzw(A0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CountLeadingZeroesWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"6005151b clzw a0, a0\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(32, Call(test->entry(), 0));
|
|
EXPECT_EQ(31, Call(test->entry(), 1));
|
|
EXPECT_EQ(30, Call(test->entry(), 2));
|
|
EXPECT_EQ(29, Call(test->entry(), 4));
|
|
EXPECT_EQ(24, Call(test->entry(), 240));
|
|
EXPECT_EQ(0, Call(test->entry(), -1));
|
|
EXPECT_EQ(0, Call(test->entry(), -2));
|
|
EXPECT_EQ(0, Call(test->entry(), -4));
|
|
EXPECT_EQ(0, Call(test->entry(), -240));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CountTrailingZeroesWord, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ ctzw(A0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CountTrailingZeroesWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"6015151b ctzw a0, a0\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(32, Call(test->entry(), 0));
|
|
EXPECT_EQ(0, Call(test->entry(), 1));
|
|
EXPECT_EQ(1, Call(test->entry(), 2));
|
|
EXPECT_EQ(2, Call(test->entry(), 4));
|
|
EXPECT_EQ(4, Call(test->entry(), 240));
|
|
EXPECT_EQ(0, Call(test->entry(), -1));
|
|
EXPECT_EQ(1, Call(test->entry(), -2));
|
|
EXPECT_EQ(2, Call(test->entry(), -4));
|
|
EXPECT_EQ(4, Call(test->entry(), -240));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CountPopulationWord, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ cpopw(A0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CountPopulationWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"6025151b cpopw a0, a0\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(0, Call(test->entry(), 0));
|
|
EXPECT_EQ(1, Call(test->entry(), 1));
|
|
EXPECT_EQ(3, Call(test->entry(), 7));
|
|
EXPECT_EQ(4, Call(test->entry(), 30));
|
|
EXPECT_EQ(32, Call(test->entry(), -1));
|
|
EXPECT_EQ(30, Call(test->entry(), -7));
|
|
EXPECT_EQ(28, Call(test->entry(), -30));
|
|
EXPECT_EQ(0, Call(test->entry(), 0x7FFFFFFF00000000));
|
|
}
|
|
#endif
|
|
|
|
ASSEMBLER_TEST_GENERATE(Max, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ max(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(Max, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"0ab56533 max a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(17, Call(test->entry(), 7, 17));
|
|
EXPECT_EQ(17, Call(test->entry(), -7, 17));
|
|
EXPECT_EQ(7, Call(test->entry(), 7, -17));
|
|
EXPECT_EQ(-7, Call(test->entry(), -7, -17));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(MaxUnsigned, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ maxu(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(MaxUnsigned, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"0ab57533 maxu a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(17, Call(test->entry(), 7, 17));
|
|
EXPECT_EQ(-7, Call(test->entry(), -7, 17));
|
|
EXPECT_EQ(-17, Call(test->entry(), 7, -17));
|
|
EXPECT_EQ(-7, Call(test->entry(), -7, -17));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(Min, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ min(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(Min, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"0ab54533 min a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(7, Call(test->entry(), 7, 17));
|
|
EXPECT_EQ(-7, Call(test->entry(), -7, 17));
|
|
EXPECT_EQ(-17, Call(test->entry(), 7, -17));
|
|
EXPECT_EQ(-17, Call(test->entry(), -7, -17));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(MinUnsigned, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ minu(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(MinUnsigned, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"0ab55533 minu a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(7, Call(test->entry(), 7, 17));
|
|
EXPECT_EQ(17, Call(test->entry(), -7, 17));
|
|
EXPECT_EQ(7, Call(test->entry(), 7, -17));
|
|
EXPECT_EQ(-17, Call(test->entry(), -7, -17));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SignExtendByte, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ sextb(A0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SignExtendByte, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"60451513 sext.b a0, a0\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(1, Call(test->entry(), 1));
|
|
EXPECT_EQ(127, Call(test->entry(), 127));
|
|
EXPECT_EQ(-128, Call(test->entry(), 128));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SignExtendHalfWord, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ sexth(A0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SignExtendHalfWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"60551513 sext.h a0, a0\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(0, Call(test->entry(), 0));
|
|
EXPECT_EQ(0x7BCD, Call(test->entry(), 0x12347BCD));
|
|
EXPECT_EQ(-1, Call(test->entry(), 0xFFFF));
|
|
EXPECT_EQ(-1, Call(test->entry(), -1));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ZeroExtendHalfWord, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ zexth(A0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ZeroExtendHalfWord, test) {
|
|
#if XLEN == 32
|
|
EXPECT_DISASSEMBLY(
|
|
"08054533 zext.h a0, a0\n"
|
|
" 8082 ret\n");
|
|
#else
|
|
EXPECT_DISASSEMBLY(
|
|
"0805453b zext.h a0, a0\n"
|
|
" 8082 ret\n");
|
|
#endif
|
|
|
|
EXPECT_EQ(0, Call(test->entry(), 0));
|
|
EXPECT_EQ(0xABCD, Call(test->entry(), 0x1234ABCD));
|
|
EXPECT_EQ(0xFFFF, Call(test->entry(), 0xFFFF));
|
|
EXPECT_EQ(0xFFFF, Call(test->entry(), -1));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(RotateRight, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ ror(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(RotateRight, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"60b55533 ror a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
#if XLEN == 32
|
|
EXPECT_EQ(static_cast<intx_t>(0x12345678),
|
|
Call(test->entry(), 0x12345678, 0));
|
|
EXPECT_EQ(static_cast<intx_t>(0x81234567),
|
|
Call(test->entry(), 0x12345678, 4));
|
|
EXPECT_EQ(static_cast<intx_t>(0x23456781),
|
|
Call(test->entry(), 0x12345678, 28));
|
|
EXPECT_EQ(static_cast<intx_t>(0x81234567),
|
|
Call(test->entry(), 0x12345678, 36));
|
|
#else
|
|
EXPECT_EQ(static_cast<intx_t>(0x0123456789ABCDEF),
|
|
Call(test->entry(), 0x0123456789ABCDEF, 0));
|
|
EXPECT_EQ(static_cast<intx_t>(0xF0123456789ABCDE),
|
|
Call(test->entry(), 0x0123456789ABCDEF, 4));
|
|
EXPECT_EQ(static_cast<intx_t>(0x123456789ABCDEF0),
|
|
Call(test->entry(), 0x0123456789ABCDEF, 60));
|
|
EXPECT_EQ(static_cast<intx_t>(0xF0123456789ABCDE),
|
|
Call(test->entry(), 0x0123456789ABCDEF, 68));
|
|
#endif
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(RotateLeft, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ rol(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(RotateLeft, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"60b51533 rol a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
#if XLEN == 32
|
|
EXPECT_EQ(static_cast<intx_t>(0x12345678),
|
|
Call(test->entry(), 0x12345678, 0));
|
|
EXPECT_EQ(static_cast<intx_t>(0x23456781),
|
|
Call(test->entry(), 0x12345678, 4));
|
|
EXPECT_EQ(static_cast<intx_t>(0x81234567),
|
|
Call(test->entry(), 0x12345678, 28));
|
|
EXPECT_EQ(static_cast<intx_t>(0x23456781),
|
|
Call(test->entry(), 0x12345678, 36));
|
|
#else
|
|
EXPECT_EQ(static_cast<intx_t>(0x0123456789ABCDEF),
|
|
Call(test->entry(), 0x0123456789ABCDEF, 0));
|
|
EXPECT_EQ(static_cast<intx_t>(0x123456789ABCDEF0),
|
|
Call(test->entry(), 0x0123456789ABCDEF, 4));
|
|
EXPECT_EQ(static_cast<intx_t>(0xF0123456789ABCDE),
|
|
Call(test->entry(), 0x0123456789ABCDEF, 60));
|
|
EXPECT_EQ(static_cast<intx_t>(0x123456789ABCDEF0),
|
|
Call(test->entry(), 0x0123456789ABCDEF, 68));
|
|
#endif
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(RotateRightImmediate, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ rori(A0, A0, 4);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(RotateRightImmediate, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"60455513 rori a0, a0, 0x4\n"
|
|
" 8082 ret\n");
|
|
|
|
#if XLEN == 32
|
|
EXPECT_EQ(static_cast<intx_t>(0x81234567), Call(test->entry(), 0x12345678));
|
|
#else
|
|
EXPECT_EQ(static_cast<intx_t>(0xF0123456789ABCDE),
|
|
Call(test->entry(), 0x0123456789ABCDEF));
|
|
#endif
|
|
}
|
|
|
|
#if XLEN >= 64
|
|
ASSEMBLER_TEST_GENERATE(RotateRightWord, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ rorw(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(RotateRightWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"60b5553b rorw a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(sign_extend(0x12345678), Call(test->entry(), 0x12345678, 0));
|
|
EXPECT_EQ(sign_extend(0x81234567), Call(test->entry(), 0x12345678, 4));
|
|
EXPECT_EQ(sign_extend(0x23456781), Call(test->entry(), 0x12345678, 28));
|
|
EXPECT_EQ(sign_extend(0x81234567), Call(test->entry(), 0x12345678, 36));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(RotateLeftWord, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ rolw(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(RotateLeftWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"60b5153b rolw a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(sign_extend(0x12345678), Call(test->entry(), 0x12345678, 0));
|
|
EXPECT_EQ(sign_extend(0x23456781), Call(test->entry(), 0x12345678, 4));
|
|
EXPECT_EQ(sign_extend(0x81234567), Call(test->entry(), 0x12345678, 28));
|
|
EXPECT_EQ(sign_extend(0x23456781), Call(test->entry(), 0x12345678, 36));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(RotateRightImmediateWord, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ roriw(A0, A0, 4);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(RotateRightImmediateWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"6045551b roriw a0, a0, 0x4\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(sign_extend(0x81234567), Call(test->entry(), 0x12345678));
|
|
}
|
|
#endif
|
|
|
|
ASSEMBLER_TEST_GENERATE(OrCombineBytes, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ orcb(A0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(OrCombineBytes, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"28755513 orc.b a0, a0\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(0, Call(test->entry(), 0));
|
|
EXPECT_EQ(-1, Call(test->entry(), -1));
|
|
EXPECT_EQ(0x00FF00FF, Call(test->entry(), 0x00010001));
|
|
#if XLEN >= 64
|
|
EXPECT_EQ(0x00FF00FF00FF00FF, Call(test->entry(), 0x0001000100010001));
|
|
#endif
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ByteReverse, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ rev8(A0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ByteReverse, test) {
|
|
#if XLEN == 32
|
|
EXPECT_DISASSEMBLY(
|
|
"69855513 rev8 a0, a0\n"
|
|
" 8082 ret\n");
|
|
#else
|
|
EXPECT_DISASSEMBLY(
|
|
"6b855513 rev8 a0, a0\n"
|
|
" 8082 ret\n");
|
|
#endif
|
|
|
|
EXPECT_EQ(0, Call(test->entry(), 0));
|
|
EXPECT_EQ(-1, Call(test->entry(), -1));
|
|
#if XLEN == 32
|
|
EXPECT_EQ(0x11223344, Call(test->entry(), 0x44332211));
|
|
#elif XLEN == 64
|
|
EXPECT_EQ(0x1122334455667788, Call(test->entry(), 0x8877665544332211));
|
|
#endif
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CarrylessMultiply, assembler) {
|
|
__ SetExtensions(RV_GC | RV_Zbc);
|
|
__ clmul(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CarrylessMultiply, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"0ab51533 clmul a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
#if XLEN == 32
|
|
EXPECT_EQ(0x55555555, Call(test->entry(), -1, -1));
|
|
#else
|
|
EXPECT_EQ(0x5555555555555555, Call(test->entry(), -1, -1));
|
|
#endif
|
|
EXPECT_EQ(0, Call(test->entry(), -1, 0));
|
|
EXPECT_EQ(-1, Call(test->entry(), -1, 1));
|
|
EXPECT_EQ(0, Call(test->entry(), 0, -1));
|
|
EXPECT_EQ(0, Call(test->entry(), 0, 0));
|
|
EXPECT_EQ(0, Call(test->entry(), 0, 1));
|
|
EXPECT_EQ(-1, Call(test->entry(), 1, -1));
|
|
EXPECT_EQ(0, Call(test->entry(), 1, 0));
|
|
EXPECT_EQ(1, Call(test->entry(), 1, 1));
|
|
|
|
EXPECT_EQ(4, Call(test->entry(), 2, 2));
|
|
EXPECT_EQ(5, Call(test->entry(), 3, 3));
|
|
EXPECT_EQ(16, Call(test->entry(), 4, 4));
|
|
EXPECT_EQ(20, Call(test->entry(), 6, 6));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CarrylessMultiplyHigh, assembler) {
|
|
__ SetExtensions(RV_GC | RV_Zbc);
|
|
__ clmulh(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CarrylessMultiplyHigh, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"0ab53533 clmulh a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
#if XLEN == 32
|
|
EXPECT_EQ(0x55555555, Call(test->entry(), -1, -1));
|
|
#else
|
|
EXPECT_EQ(0x5555555555555555, Call(test->entry(), -1, -1));
|
|
#endif
|
|
EXPECT_EQ(0, Call(test->entry(), -1, 0));
|
|
EXPECT_EQ(0, Call(test->entry(), -1, 1));
|
|
EXPECT_EQ(0, Call(test->entry(), 0, -1));
|
|
EXPECT_EQ(0, Call(test->entry(), 0, 0));
|
|
EXPECT_EQ(0, Call(test->entry(), 0, 1));
|
|
EXPECT_EQ(0, Call(test->entry(), 1, -1));
|
|
EXPECT_EQ(0, Call(test->entry(), 1, 0));
|
|
EXPECT_EQ(0, Call(test->entry(), 1, 1));
|
|
|
|
EXPECT_EQ(0, Call(test->entry(), 2, 2));
|
|
EXPECT_EQ(0, Call(test->entry(), 3, 3));
|
|
EXPECT_EQ(0, Call(test->entry(), 4, 4));
|
|
EXPECT_EQ(0, Call(test->entry(), 6, 6));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CarrylessMultiplyReversed, assembler) {
|
|
__ SetExtensions(RV_GC | RV_Zbc);
|
|
__ clmulr(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CarrylessMultiplyReversed, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"0ab52533 clmulr a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
#if XLEN == 32
|
|
EXPECT_EQ(-0x55555556, Call(test->entry(), -1, -1));
|
|
#else
|
|
EXPECT_EQ(-0x5555555555555556, Call(test->entry(), -1, -1));
|
|
#endif
|
|
EXPECT_EQ(0, Call(test->entry(), -1, 0));
|
|
EXPECT_EQ(1, Call(test->entry(), -1, 1));
|
|
EXPECT_EQ(0, Call(test->entry(), 0, -1));
|
|
EXPECT_EQ(0, Call(test->entry(), 0, 0));
|
|
EXPECT_EQ(0, Call(test->entry(), 0, 1));
|
|
EXPECT_EQ(1, Call(test->entry(), 1, -1));
|
|
EXPECT_EQ(0, Call(test->entry(), 1, 0));
|
|
EXPECT_EQ(0, Call(test->entry(), 1, 1));
|
|
|
|
EXPECT_EQ(0, Call(test->entry(), 2, 2));
|
|
EXPECT_EQ(0, Call(test->entry(), 3, 3));
|
|
EXPECT_EQ(0, Call(test->entry(), 4, 4));
|
|
EXPECT_EQ(0, Call(test->entry(), 6, 6));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(BitClear, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ bclr(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(BitClear, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"48b51533 bclr a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(42, Call(test->entry(), 42, 0));
|
|
EXPECT_EQ(40, Call(test->entry(), 42, 1));
|
|
EXPECT_EQ(42, Call(test->entry(), 42, 2));
|
|
EXPECT_EQ(34, Call(test->entry(), 42, 3));
|
|
EXPECT_EQ(42, Call(test->entry(), 42, 4));
|
|
EXPECT_EQ(10, Call(test->entry(), 42, 5));
|
|
EXPECT_EQ(42, Call(test->entry(), 42, 6));
|
|
EXPECT_EQ(42, Call(test->entry(), 42, 7));
|
|
EXPECT_EQ(42, Call(test->entry(), 42, 8));
|
|
|
|
EXPECT_EQ(42, Call(test->entry(), 42, 64));
|
|
EXPECT_EQ(40, Call(test->entry(), 42, 65));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(BitClearImmediate, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ bclri(A0, A0, 3);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(BitClearImmediate, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"48351513 bclri a0, a0, 0x3\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(0, Call(test->entry(), 0));
|
|
EXPECT_EQ(7, Call(test->entry(), 7));
|
|
EXPECT_EQ(0, Call(test->entry(), 8));
|
|
EXPECT_EQ(1, Call(test->entry(), 9));
|
|
EXPECT_EQ(-15, Call(test->entry(), -7));
|
|
EXPECT_EQ(-16, Call(test->entry(), -8));
|
|
EXPECT_EQ(-9, Call(test->entry(), -9));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(BitClearImmediate2, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ bclri(A0, A0, XLEN - 1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(BitClearImmediate2, test) {
|
|
#if XLEN == 32
|
|
EXPECT_DISASSEMBLY(
|
|
"49f51513 bclri a0, a0, 0x1f\n"
|
|
" 8082 ret\n");
|
|
#elif XLEN == 64
|
|
EXPECT_DISASSEMBLY(
|
|
"4bf51513 bclri a0, a0, 0x3f\n"
|
|
" 8082 ret\n");
|
|
#endif
|
|
|
|
EXPECT_EQ(0, Call(test->entry(), 0));
|
|
EXPECT_EQ(1, Call(test->entry(), 1));
|
|
EXPECT_EQ(kMaxIntX, Call(test->entry(), -1));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(BitExtract, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ bext(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(BitExtract, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"48b55533 bext a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(0, Call(test->entry(), 42, 0));
|
|
EXPECT_EQ(1, Call(test->entry(), 42, 1));
|
|
EXPECT_EQ(0, Call(test->entry(), 42, 2));
|
|
EXPECT_EQ(1, Call(test->entry(), 42, 3));
|
|
EXPECT_EQ(0, Call(test->entry(), 42, 4));
|
|
EXPECT_EQ(1, Call(test->entry(), 42, 5));
|
|
EXPECT_EQ(0, Call(test->entry(), 42, 6));
|
|
EXPECT_EQ(0, Call(test->entry(), 42, 7));
|
|
EXPECT_EQ(0, Call(test->entry(), 42, 8));
|
|
|
|
EXPECT_EQ(0, Call(test->entry(), 42, 64));
|
|
EXPECT_EQ(1, Call(test->entry(), 42, 65));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(BitExtractImmediate, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ bexti(A0, A0, 3);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(BitExtractImmediate, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"48355513 bexti a0, a0, 0x3\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(0, Call(test->entry(), 0));
|
|
EXPECT_EQ(0, Call(test->entry(), 7));
|
|
EXPECT_EQ(1, Call(test->entry(), 8));
|
|
EXPECT_EQ(1, Call(test->entry(), 9));
|
|
EXPECT_EQ(1, Call(test->entry(), -7));
|
|
EXPECT_EQ(1, Call(test->entry(), -8));
|
|
EXPECT_EQ(0, Call(test->entry(), -9));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(BitExtractImmediate2, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ bexti(A0, A0, XLEN - 1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(BitExtractImmediate2, test) {
|
|
#if XLEN == 32
|
|
EXPECT_DISASSEMBLY(
|
|
"49f55513 bexti a0, a0, 0x1f\n"
|
|
" 8082 ret\n");
|
|
#elif XLEN == 64
|
|
EXPECT_DISASSEMBLY(
|
|
"4bf55513 bexti a0, a0, 0x3f\n"
|
|
" 8082 ret\n");
|
|
#endif
|
|
|
|
EXPECT_EQ(0, Call(test->entry(), 0));
|
|
EXPECT_EQ(0, Call(test->entry(), 1));
|
|
EXPECT_EQ(1, Call(test->entry(), -1));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(BitInvert, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ binv(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(BitInvert, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"68b51533 binv a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(43, Call(test->entry(), 42, 0));
|
|
EXPECT_EQ(40, Call(test->entry(), 42, 1));
|
|
EXPECT_EQ(46, Call(test->entry(), 42, 2));
|
|
EXPECT_EQ(34, Call(test->entry(), 42, 3));
|
|
EXPECT_EQ(58, Call(test->entry(), 42, 4));
|
|
EXPECT_EQ(10, Call(test->entry(), 42, 5));
|
|
EXPECT_EQ(106, Call(test->entry(), 42, 6));
|
|
EXPECT_EQ(170, Call(test->entry(), 42, 7));
|
|
EXPECT_EQ(298, Call(test->entry(), 42, 8));
|
|
|
|
EXPECT_EQ(43, Call(test->entry(), 42, 64));
|
|
EXPECT_EQ(40, Call(test->entry(), 42, 65));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(BitInvertImmediate, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ binvi(A0, A0, 3);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(BitInvertImmediate, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"68351513 binvi a0, a0, 0x3\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(8, Call(test->entry(), 0));
|
|
EXPECT_EQ(15, Call(test->entry(), 7));
|
|
EXPECT_EQ(0, Call(test->entry(), 8));
|
|
EXPECT_EQ(1, Call(test->entry(), 9));
|
|
EXPECT_EQ(-15, Call(test->entry(), -7));
|
|
EXPECT_EQ(-16, Call(test->entry(), -8));
|
|
EXPECT_EQ(-1, Call(test->entry(), -9));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(BitInvertImmediate2, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ binvi(A0, A0, XLEN - 1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(BitInvertImmediate2, test) {
|
|
#if XLEN == 32
|
|
EXPECT_DISASSEMBLY(
|
|
"69f51513 binvi a0, a0, 0x1f\n"
|
|
" 8082 ret\n");
|
|
#elif XLEN == 64
|
|
EXPECT_DISASSEMBLY(
|
|
"6bf51513 binvi a0, a0, 0x3f\n"
|
|
" 8082 ret\n");
|
|
#endif
|
|
|
|
EXPECT_EQ(kMinIntX, Call(test->entry(), 0));
|
|
EXPECT_EQ(kMinIntX + 1, Call(test->entry(), 1));
|
|
EXPECT_EQ(kMaxIntX, Call(test->entry(), -1));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(BitSet, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ bset(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(BitSet, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"28b51533 bset a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(43, Call(test->entry(), 42, 0));
|
|
EXPECT_EQ(42, Call(test->entry(), 42, 1));
|
|
EXPECT_EQ(46, Call(test->entry(), 42, 2));
|
|
EXPECT_EQ(42, Call(test->entry(), 42, 3));
|
|
EXPECT_EQ(58, Call(test->entry(), 42, 4));
|
|
EXPECT_EQ(42, Call(test->entry(), 42, 5));
|
|
EXPECT_EQ(106, Call(test->entry(), 42, 6));
|
|
EXPECT_EQ(170, Call(test->entry(), 42, 7));
|
|
EXPECT_EQ(298, Call(test->entry(), 42, 8));
|
|
|
|
EXPECT_EQ(43, Call(test->entry(), 42, 64));
|
|
EXPECT_EQ(42, Call(test->entry(), 42, 65));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(BitSetImmediate, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ bseti(A0, A0, 3);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(BitSetImmediate, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"28351513 bseti a0, a0, 0x3\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(8, Call(test->entry(), 0));
|
|
EXPECT_EQ(15, Call(test->entry(), 7));
|
|
EXPECT_EQ(8, Call(test->entry(), 8));
|
|
EXPECT_EQ(9, Call(test->entry(), 9));
|
|
EXPECT_EQ(-7, Call(test->entry(), -7));
|
|
EXPECT_EQ(-8, Call(test->entry(), -8));
|
|
EXPECT_EQ(-1, Call(test->entry(), -9));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(BitSetImmediate2, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ bseti(A0, A0, XLEN - 1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(BitSetImmediate2, test) {
|
|
#if XLEN == 32
|
|
EXPECT_DISASSEMBLY(
|
|
"29f51513 bseti a0, a0, 0x1f\n"
|
|
" 8082 ret\n");
|
|
#elif XLEN == 64
|
|
EXPECT_DISASSEMBLY(
|
|
"2bf51513 bseti a0, a0, 0x3f\n"
|
|
" 8082 ret\n");
|
|
#endif
|
|
|
|
EXPECT_EQ(kMinIntX, Call(test->entry(), 0));
|
|
EXPECT_EQ(kMinIntX + 1, Call(test->entry(), 1));
|
|
EXPECT_EQ(-1, Call(test->entry(), -1));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConditionalZeroIfEqualsZero, assembler) {
|
|
__ SetExtensions(RV_GC | RV_Zicond);
|
|
__ czeroeqz(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConditionalZeroIfEqualsZero, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"0eb55533 czero.eqz a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(0, Call(test->entry(), 42, 0));
|
|
EXPECT_EQ(42, Call(test->entry(), 42, 1));
|
|
EXPECT_EQ(42, Call(test->entry(), 42, -1));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ConditionalZeroIfNotEqualsZero, assembler) {
|
|
__ SetExtensions(RV_GC | RV_Zicond);
|
|
__ czeronez(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ConditionalZeroIfNotEqualsZero, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"0eb57533 czero.nez a0, a0, a1\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(42, Call(test->entry(), 42, 0));
|
|
EXPECT_EQ(0, Call(test->entry(), 42, 1));
|
|
EXPECT_EQ(0, Call(test->entry(), 42, -1));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedLoadByteUnsigned_0, assembler) {
|
|
__ SetExtensions(RV_GC | RV_Zcb);
|
|
__ lbu(A0, Address(A0, 0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedLoadByteUnsigned_0, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 8108 lbu a0, 0(a0)\n"
|
|
" 8082 ret\n");
|
|
|
|
uint8_t values[3];
|
|
values[0] = 0xAB;
|
|
values[1] = 0xCD;
|
|
values[2] = 0xEF;
|
|
|
|
EXPECT_EQ(0xCD, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedLoadByteUnsigned_Pos, assembler) {
|
|
__ SetExtensions(RV_GC | RV_Zcb);
|
|
__ lbu(A0, Address(A0, 1));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedLoadByteUnsigned_Pos, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 8148 lbu a0, 1(a0)\n"
|
|
" 8082 ret\n");
|
|
|
|
uint8_t values[3];
|
|
values[0] = 0xAB;
|
|
values[1] = 0xCD;
|
|
values[2] = 0xEF;
|
|
|
|
EXPECT_EQ(0xEF, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedLoadHalfword_0, assembler) {
|
|
__ SetExtensions(RV_GC | RV_Zcb);
|
|
__ lh(A0, Address(A0, 0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedLoadHalfword_0, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 8548 lh a0, 0(a0)\n"
|
|
" 8082 ret\n");
|
|
|
|
uint16_t values[3];
|
|
values[0] = 0xAB01;
|
|
values[1] = 0xCD02;
|
|
values[2] = 0xEF03;
|
|
|
|
EXPECT_EQ(-13054, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedLoadHalfword_Pos, assembler) {
|
|
__ SetExtensions(RV_GC | RV_Zcb);
|
|
__ lh(A0, Address(A0, 2));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedLoadHalfword_Pos, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 8568 lh a0, 2(a0)\n"
|
|
" 8082 ret\n");
|
|
|
|
uint16_t values[3];
|
|
values[0] = 0xAB01;
|
|
values[1] = 0xCD02;
|
|
values[2] = 0xEF03;
|
|
|
|
EXPECT_EQ(-4349, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedLoadHalfwordUnsigned_0, assembler) {
|
|
__ SetExtensions(RV_GC | RV_Zcb);
|
|
__ lhu(A0, Address(A0, 0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedLoadHalfwordUnsigned_0, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 8508 lhu a0, 0(a0)\n"
|
|
" 8082 ret\n");
|
|
|
|
uint16_t values[3];
|
|
values[0] = 0xAB01;
|
|
values[1] = 0xCD02;
|
|
values[2] = 0xEF03;
|
|
|
|
EXPECT_EQ(0xCD02, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedLoadHalfwordUnsigned_Pos, assembler) {
|
|
__ SetExtensions(RV_GC | RV_Zcb);
|
|
__ lhu(A0, Address(A0, 2));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedLoadHalfwordUnsigned_Pos, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 8528 lhu a0, 2(a0)\n"
|
|
" 8082 ret\n");
|
|
|
|
uint16_t values[3];
|
|
values[0] = 0xAB01;
|
|
values[1] = 0xCD02;
|
|
values[2] = 0xEF03;
|
|
|
|
EXPECT_EQ(0xEF03, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedStoreByte_0, assembler) {
|
|
__ SetExtensions(RV_GC | RV_Zcb);
|
|
__ sb(A1, Address(A0, 0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedStoreByte_0, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 890c sb a1, 0(a0)\n"
|
|
" 8082 ret\n");
|
|
|
|
uint8_t values[3];
|
|
values[0] = 0;
|
|
values[1] = 0;
|
|
values[2] = 0;
|
|
|
|
Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xCD);
|
|
EXPECT_EQ(0, values[0]);
|
|
EXPECT_EQ(0xCD, values[1]);
|
|
EXPECT_EQ(0, values[2]);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedStoreByte_Pos, assembler) {
|
|
__ SetExtensions(RV_GC | RV_Zcb);
|
|
__ sb(A1, Address(A0, 1));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedStoreByte_Pos, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 894c sb a1, 1(a0)\n"
|
|
" 8082 ret\n");
|
|
|
|
uint8_t values[3];
|
|
values[0] = 0;
|
|
values[1] = 0;
|
|
values[2] = 0;
|
|
|
|
Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xEF);
|
|
EXPECT_EQ(0, values[0]);
|
|
EXPECT_EQ(0, values[1]);
|
|
EXPECT_EQ(0xEF, values[2]);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedStoreHalfword_0, assembler) {
|
|
__ SetExtensions(RV_GC | RV_Zcb);
|
|
__ sh(A1, Address(A0, 0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedStoreHalfword_0, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 8d0c sh a1, 0(a0)\n"
|
|
" 8082 ret\n");
|
|
|
|
uint16_t values[3];
|
|
values[0] = 0;
|
|
values[1] = 0;
|
|
values[2] = 0;
|
|
|
|
Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xCD02);
|
|
EXPECT_EQ(0, values[0]);
|
|
EXPECT_EQ(0xCD02, values[1]);
|
|
EXPECT_EQ(0, values[2]);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedStoreHalfword_Pos, assembler) {
|
|
__ SetExtensions(RV_GC | RV_Zcb);
|
|
__ sh(A1, Address(A0, 2));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedStoreHalfword_Pos, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 8d2c sh a1, 2(a0)\n"
|
|
" 8082 ret\n");
|
|
|
|
uint16_t values[3];
|
|
values[0] = 0;
|
|
values[1] = 0;
|
|
values[2] = 0;
|
|
|
|
Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xEF03);
|
|
EXPECT_EQ(0, values[0]);
|
|
EXPECT_EQ(0, values[1]);
|
|
EXPECT_EQ(0xEF03, values[2]);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedSignExtendByte, assembler) {
|
|
__ SetExtensions(RV_GCB | RV_Zcb);
|
|
__ sextb(A0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedSignExtendByte, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 9d65 sext.b a0, a0\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(1, Call(test->entry(), 1));
|
|
EXPECT_EQ(127, Call(test->entry(), 127));
|
|
EXPECT_EQ(-128, Call(test->entry(), 128));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedZeroExtendByte, assembler) {
|
|
__ SetExtensions(RV_GCB | RV_Zcb);
|
|
__ zextb(A0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedZeroExtendByte, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 9d61 zext.b a0, a0\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(1, Call(test->entry(), 1));
|
|
EXPECT_EQ(0xCD, Call(test->entry(), 0x1234ABCD));
|
|
EXPECT_EQ(0xFF, Call(test->entry(), 0xFF));
|
|
EXPECT_EQ(0xFF, Call(test->entry(), -1));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedSignExtendHalfword, assembler) {
|
|
__ SetExtensions(RV_GCB | RV_Zcb);
|
|
__ sexth(A0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedSignExtendHalfword, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 9d6d sext.h a0, a0\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(1, Call(test->entry(), 1));
|
|
EXPECT_EQ(0x7BCD, Call(test->entry(), 0x12347BCD));
|
|
EXPECT_EQ(-1, Call(test->entry(), 0xFFFF));
|
|
EXPECT_EQ(-1, Call(test->entry(), -1));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedZeroExtendHalfword, assembler) {
|
|
__ SetExtensions(RV_GCB | RV_Zcb);
|
|
__ zexth(A0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedZeroExtendHalfword, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 9d69 zext.h a0, a0\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(0, Call(test->entry(), 0));
|
|
EXPECT_EQ(0xABCD, Call(test->entry(), 0x1234ABCD));
|
|
EXPECT_EQ(0xFFFF, Call(test->entry(), 0xFFFF));
|
|
EXPECT_EQ(0xFFFF, Call(test->entry(), -1));
|
|
}
|
|
|
|
#if XLEN >= 64
|
|
ASSEMBLER_TEST_GENERATE(CompressedZeroExtendWord, assembler) {
|
|
__ SetExtensions(RV_GCB | RV_Zcb);
|
|
__ zextw(A0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedZeroExtendWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 9d71 zext.w a0, a0\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(0, Call(test->entry(), 0));
|
|
EXPECT_EQ(0x1234ABCD, Call(test->entry(), 0x11234ABCD));
|
|
EXPECT_EQ(0xFFFFFFFF, Call(test->entry(), 0xFFFFFFFF));
|
|
EXPECT_EQ(0xFFFFFFFF, Call(test->entry(), -1));
|
|
}
|
|
#endif // XLEN >= 64
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedNot, assembler) {
|
|
__ SetExtensions(RV_GCB | RV_Zcb);
|
|
__ not_(A0, A0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedNot, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 9d75 not a0, a0\n"
|
|
" 8082 ret\n");
|
|
|
|
EXPECT_EQ(~42, Call(test->entry(), 42));
|
|
EXPECT_EQ(~-42, Call(test->entry(), -42));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(CompressedMultiply, assembler) {
|
|
__ SetExtensions(RV_GCB | RV_Zcb);
|
|
__ mul(A0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(CompressedMultiply, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 9d4d mul a0, a0, a1\n"
|
|
" 8082 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(AmoSwapByte, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zabha);
|
|
__ amoswapb(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoSwapByte, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"08b5052f amoswap.b a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int8_t value = 0b1100;
|
|
|
|
EXPECT_EQ(0b1100,
|
|
Call(test->entry(), reinterpret_cast<intx_t>(&value), 0b1010));
|
|
EXPECT_EQ(0b1010, value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoAddByte, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zabha);
|
|
__ amoaddb(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoAddByte, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"00b5052f amoadd.b a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int8_t value = 42;
|
|
|
|
EXPECT_EQ(42, Call(test->entry(), reinterpret_cast<intx_t>(&value), 10));
|
|
EXPECT_EQ(52, value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoXorByte, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zabha);
|
|
__ amoxorb(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoXorByte, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"20b5052f amoxor.b a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int8_t value = 0b1100;
|
|
|
|
EXPECT_EQ(0b1100,
|
|
Call(test->entry(), reinterpret_cast<intx_t>(&value), 0b1010));
|
|
EXPECT_EQ(0b0110, value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoAndByte, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zabha);
|
|
__ amoandb(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoAndByte, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"60b5052f amoand.b a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int8_t value = 0b1100;
|
|
|
|
EXPECT_EQ(0b1100,
|
|
Call(test->entry(), reinterpret_cast<intx_t>(&value), 0b1010));
|
|
EXPECT_EQ(0b1000, value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoOrByte, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zabha);
|
|
__ amoorb(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoOrByte, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"40b5052f amoor.b a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int8_t value = 0b1100;
|
|
|
|
EXPECT_EQ(0b1100,
|
|
Call(test->entry(), reinterpret_cast<intx_t>(&value), 0b1010));
|
|
EXPECT_EQ(0b1110, value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoMinByte, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zabha);
|
|
__ amominb(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoMinByte, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"80b5052f amomin.b a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int8_t value = -7;
|
|
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -4));
|
|
EXPECT_EQ(-7, value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -7));
|
|
EXPECT_EQ(-7, value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -11));
|
|
EXPECT_EQ(-11, value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoMaxByte, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zabha);
|
|
__ amomaxb(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoMaxByte, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"a0b5052f amomax.b a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int8_t value = -7;
|
|
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -11));
|
|
EXPECT_EQ(-7, value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -7));
|
|
EXPECT_EQ(-7, value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -4));
|
|
EXPECT_EQ(-4, value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoMinUnsignedByte, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zabha);
|
|
__ amominub(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoMinUnsignedByte, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"c0b5052f amominu.b a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int8_t value = -7;
|
|
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -4));
|
|
EXPECT_EQ(-7, value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -7));
|
|
EXPECT_EQ(-7, value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -11));
|
|
EXPECT_EQ(-11, value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoMaxUnsignedByte, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zabha);
|
|
__ amomaxub(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoMaxUnsignedByte, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"e0b5052f amomaxu.b a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int8_t value = -7;
|
|
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -11));
|
|
EXPECT_EQ(-7, value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -7));
|
|
EXPECT_EQ(-7, value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -4));
|
|
EXPECT_EQ(-4, value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoSwapHalfword, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zabha);
|
|
__ amoswaph(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoSwapHalfword, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"08b5152f amoswap.h a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int16_t value = 0b1100;
|
|
|
|
EXPECT_EQ(0b1100,
|
|
Call(test->entry(), reinterpret_cast<intx_t>(&value), 0b1010));
|
|
EXPECT_EQ(0b1010, value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoAddHalfword, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zabha);
|
|
__ amoaddh(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoAddHalfword, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"00b5152f amoadd.h a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int16_t value = 42;
|
|
|
|
EXPECT_EQ(42, Call(test->entry(), reinterpret_cast<intx_t>(&value), 10));
|
|
EXPECT_EQ(52, value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoXorHalfword, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zabha);
|
|
__ amoxorh(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoXorHalfword, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"20b5152f amoxor.h a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int16_t value = 0b1100;
|
|
|
|
EXPECT_EQ(0b1100,
|
|
Call(test->entry(), reinterpret_cast<intx_t>(&value), 0b1010));
|
|
EXPECT_EQ(0b0110, value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoAndHalfword, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zabha);
|
|
__ amoandh(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoAndHalfword, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"60b5152f amoand.h a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int16_t value = 0b1100;
|
|
|
|
EXPECT_EQ(0b1100,
|
|
Call(test->entry(), reinterpret_cast<intx_t>(&value), 0b1010));
|
|
EXPECT_EQ(0b1000, value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoOrHalfword, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zabha);
|
|
__ amoorh(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoOrHalfword, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"40b5152f amoor.h a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int16_t value = 0b1100;
|
|
|
|
EXPECT_EQ(0b1100,
|
|
Call(test->entry(), reinterpret_cast<intx_t>(&value), 0b1010));
|
|
EXPECT_EQ(0b1110, value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoMinHalfword, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zabha);
|
|
__ amominh(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoMinHalfword, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"80b5152f amomin.h a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int16_t value = -7;
|
|
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -4));
|
|
EXPECT_EQ(-7, value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -7));
|
|
EXPECT_EQ(-7, value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -11));
|
|
EXPECT_EQ(-11, value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoMaxHalfword, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zabha);
|
|
__ amomaxh(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoMaxHalfword, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"a0b5152f amomax.h a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int16_t value = -7;
|
|
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -11));
|
|
EXPECT_EQ(-7, value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -7));
|
|
EXPECT_EQ(-7, value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -4));
|
|
EXPECT_EQ(-4, value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoMinUnsignedHalfword, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zabha);
|
|
__ amominuh(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoMinUnsignedHalfword, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"c0b5152f amominu.h a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int16_t value = -7;
|
|
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -4));
|
|
EXPECT_EQ(-7, value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -7));
|
|
EXPECT_EQ(-7, value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -11));
|
|
EXPECT_EQ(-11, value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AmoMaxUnsignedHalfword, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zabha);
|
|
__ amomaxuh(A0, A1, Address(A0));
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AmoMaxUnsignedHalfword, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"e0b5152f amomaxu.h a0, a1, (a0)\n"
|
|
"00008067 ret\n");
|
|
|
|
int16_t value = -7;
|
|
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -11));
|
|
EXPECT_EQ(-7, value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -7));
|
|
EXPECT_EQ(-7, value);
|
|
EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(&value), -4));
|
|
EXPECT_EQ(-4, value);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(FloatLoadImmediateSingle, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zfa);
|
|
for (intptr_t i = 0; i < 32; i++) {
|
|
__ flis(FRegister(i), i);
|
|
}
|
|
}
|
|
ASSEMBLER_TEST_RUN(FloatLoadImmediateSingle, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"f0100053 flis ft0, -1.000000\n"
|
|
"f01080d3 flis ft1, min\n"
|
|
"f0110153 flis ft2, 0.000015\n"
|
|
"f01181d3 flis ft3, 0.000031\n"
|
|
"f0120253 flis ft4, 0.003906\n"
|
|
"f01282d3 flis ft5, 0.007812\n"
|
|
"f0130353 flis ft6, 0.062500\n"
|
|
"f01383d3 flis ft7, 0.125000\n"
|
|
"f0140453 flis fs0, 0.250000\n"
|
|
"f01484d3 flis fs1, 0.312500\n"
|
|
"f0150553 flis fa0, 0.375000\n"
|
|
"f01585d3 flis fa1, 0.437500\n"
|
|
"f0160653 flis fa2, 0.500000\n"
|
|
"f01686d3 flis fa3, 0.625000\n"
|
|
"f0170753 flis fa4, 0.750000\n"
|
|
"f01787d3 flis fa5, 0.875000\n"
|
|
"f0180853 flis fa6, 1.000000\n"
|
|
"f01888d3 flis fa7, 1.250000\n"
|
|
"f0190953 flis fs2, 1.500000\n"
|
|
"f01989d3 flis fs3, 1.750000\n"
|
|
"f01a0a53 flis fs4, 2.000000\n"
|
|
"f01a8ad3 flis fs5, 2.500000\n"
|
|
"f01b0b53 flis fs6, 3.000000\n"
|
|
"f01b8bd3 flis fs7, 4.000000\n"
|
|
"f01c0c53 flis fs8, 8.000000\n"
|
|
"f01c8cd3 flis fs9, 16.000000\n"
|
|
"f01d0d53 flis fs10, 128.000000\n"
|
|
"f01d8dd3 flis fs11, 256.000000\n"
|
|
"f01e0e53 flis ft8, 32768.000000\n"
|
|
"f01e8ed3 flis ft9, 65536.000000\n"
|
|
"f01f0f53 flis ft10, inf\n"
|
|
"f01f8fd3 flis ft11, nan\n");
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(FloatLoadImmediateDouble, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zfa);
|
|
for (intptr_t i = 0; i < 32; i++) {
|
|
__ flid(FRegister(i), i);
|
|
}
|
|
}
|
|
ASSEMBLER_TEST_RUN(FloatLoadImmediateDouble, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"f2100053 flid ft0, -1.000000\n"
|
|
"f21080d3 flid ft1, min\n"
|
|
"f2110153 flid ft2, 0.000015\n"
|
|
"f21181d3 flid ft3, 0.000031\n"
|
|
"f2120253 flid ft4, 0.003906\n"
|
|
"f21282d3 flid ft5, 0.007812\n"
|
|
"f2130353 flid ft6, 0.062500\n"
|
|
"f21383d3 flid ft7, 0.125000\n"
|
|
"f2140453 flid fs0, 0.250000\n"
|
|
"f21484d3 flid fs1, 0.312500\n"
|
|
"f2150553 flid fa0, 0.375000\n"
|
|
"f21585d3 flid fa1, 0.437500\n"
|
|
"f2160653 flid fa2, 0.500000\n"
|
|
"f21686d3 flid fa3, 0.625000\n"
|
|
"f2170753 flid fa4, 0.750000\n"
|
|
"f21787d3 flid fa5, 0.875000\n"
|
|
"f2180853 flid fa6, 1.000000\n"
|
|
"f21888d3 flid fa7, 1.250000\n"
|
|
"f2190953 flid fs2, 1.500000\n"
|
|
"f21989d3 flid fs3, 1.750000\n"
|
|
"f21a0a53 flid fs4, 2.000000\n"
|
|
"f21a8ad3 flid fs5, 2.500000\n"
|
|
"f21b0b53 flid fs6, 3.000000\n"
|
|
"f21b8bd3 flid fs7, 4.000000\n"
|
|
"f21c0c53 flid fs8, 8.000000\n"
|
|
"f21c8cd3 flid fs9, 16.000000\n"
|
|
"f21d0d53 flid fs10, 128.000000\n"
|
|
"f21d8dd3 flid fs11, 256.000000\n"
|
|
"f21e0e53 flid ft8, 32768.000000\n"
|
|
"f21e8ed3 flid ft9, 65536.000000\n"
|
|
"f21f0f53 flid ft10, inf\n"
|
|
"f21f8fd3 flid ft11, nan\n");
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleMinM, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zfa);
|
|
__ fminms(FA0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleMinM, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"28b52553 fminm.s fa0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
|
|
EXPECT_EQ(1.0f, CallF(test->entry(), 3.0f, 1.0f));
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, 3.0f));
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, 5.0f));
|
|
EXPECT_EQ(-1.0f, CallF(test->entry(), 3.0f, -1.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), 3.0f, -3.0f));
|
|
EXPECT_EQ(-5.0f, CallF(test->entry(), 3.0f, -5.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, 1.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, 3.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, 5.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, -1.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, -3.0f));
|
|
EXPECT_EQ(-5.0f, CallF(test->entry(), -3.0f, -5.0f));
|
|
|
|
EXPECT_BITEQ(-0.0f, CallF(test->entry(), 0.0f, -0.0f));
|
|
EXPECT_BITEQ(-0.0f, CallF(test->entry(), -0.0f, 0.0f));
|
|
|
|
float qNAN = std::numeric_limits<float>::quiet_NaN();
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), 3.0f, qNAN));
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), qNAN, 3.0f));
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), -3.0f, qNAN));
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), qNAN, -3.0f));
|
|
|
|
float sNAN = std::numeric_limits<float>::signaling_NaN();
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), 3.0f, sNAN));
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), sNAN, 3.0f));
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), -3.0f, sNAN));
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), sNAN, -3.0f));
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), qNAN, qNAN));
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), sNAN, sNAN));
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), qNAN, sNAN));
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), sNAN, qNAN));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleMaxM, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zfa);
|
|
__ fmaxms(FA0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleMaxM, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"28b53553 fmaxm.s fa0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, 1.0f));
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, 3.0f));
|
|
EXPECT_EQ(5.0f, CallF(test->entry(), 3.0f, 5.0f));
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, -1.0f));
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, -3.0f));
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, -5.0f));
|
|
EXPECT_EQ(1.0f, CallF(test->entry(), -3.0f, 1.0f));
|
|
EXPECT_EQ(3.0f, CallF(test->entry(), -3.0f, 3.0f));
|
|
EXPECT_EQ(5.0f, CallF(test->entry(), -3.0f, 5.0f));
|
|
EXPECT_EQ(-1.0f, CallF(test->entry(), -3.0f, -1.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, -3.0f));
|
|
EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, -5.0f));
|
|
|
|
EXPECT_BITEQ(0.0f, CallF(test->entry(), 0.0f, -0.0f));
|
|
EXPECT_BITEQ(0.0f, CallF(test->entry(), -0.0f, 0.0f));
|
|
|
|
float qNAN = std::numeric_limits<float>::quiet_NaN();
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), 3.0f, qNAN));
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), qNAN, 3.0f));
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), -3.0f, qNAN));
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), qNAN, -3.0f));
|
|
|
|
float sNAN = std::numeric_limits<float>::signaling_NaN();
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), 3.0f, sNAN));
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), sNAN, 3.0f));
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), -3.0f, sNAN));
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), sNAN, -3.0f));
|
|
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), qNAN, qNAN));
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), sNAN, sNAN));
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), qNAN, sNAN));
|
|
EXPECT_BITEQ(qNAN, CallF(test->entry(), sNAN, qNAN));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleMinM, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zfa);
|
|
__ fminmd(FA0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleMinM, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"2ab52553 fminm.d fa0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
|
|
EXPECT_EQ(1.0, CallD(test->entry(), 3.0, 1.0));
|
|
EXPECT_EQ(3.0, CallD(test->entry(), 3.0, 3.0));
|
|
EXPECT_EQ(3.0, CallD(test->entry(), 3.0, 5.0));
|
|
EXPECT_EQ(-1.0, CallD(test->entry(), 3.0, -1.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), 3.0, -3.0));
|
|
EXPECT_EQ(-5.0, CallD(test->entry(), 3.0, -5.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, 1.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, 3.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, 5.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, -1.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, -3.0));
|
|
EXPECT_EQ(-5.0, CallD(test->entry(), -3.0, -5.0));
|
|
|
|
EXPECT_BITEQ(-0.0, CallD(test->entry(), 0.0, -0.0));
|
|
EXPECT_BITEQ(-0.0, CallD(test->entry(), -0.0, 0.0));
|
|
|
|
double qNAN = std::numeric_limits<double>::quiet_NaN();
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), 3.0, qNAN));
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), qNAN, 3.0));
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), -3.0, qNAN));
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), qNAN, -3.0));
|
|
|
|
double sNAN = std::numeric_limits<double>::signaling_NaN();
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), 3.0, sNAN));
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), sNAN, 3.0));
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), -3.0, sNAN));
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), sNAN, -3.0));
|
|
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), qNAN, qNAN));
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), sNAN, sNAN));
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), qNAN, sNAN));
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), sNAN, qNAN));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleMaxM, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zfa);
|
|
__ fmaxmd(FA0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleMaxM, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"2ab53553 fmaxm.d fa0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
|
|
EXPECT_EQ(3.0, CallD(test->entry(), 3.0, 1.0));
|
|
EXPECT_EQ(3.0, CallD(test->entry(), 3.0, 3.0));
|
|
EXPECT_EQ(5.0, CallD(test->entry(), 3.0, 5.0));
|
|
EXPECT_EQ(3.0, CallD(test->entry(), 3.0, -1.0));
|
|
EXPECT_EQ(3.0, CallD(test->entry(), 3.0, -3.0));
|
|
EXPECT_EQ(3.0, CallD(test->entry(), 3.0, -5.0));
|
|
EXPECT_EQ(1.0, CallD(test->entry(), -3.0, 1.0));
|
|
EXPECT_EQ(3.0, CallD(test->entry(), -3.0, 3.0));
|
|
EXPECT_EQ(5.0, CallD(test->entry(), -3.0, 5.0));
|
|
EXPECT_EQ(-1.0, CallD(test->entry(), -3.0, -1.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, -3.0));
|
|
EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, -5.0));
|
|
|
|
EXPECT_BITEQ(0.0, CallD(test->entry(), 0.0, -0.0));
|
|
EXPECT_BITEQ(0.0, CallD(test->entry(), -0.0, 0.0));
|
|
|
|
double qNAN = std::numeric_limits<double>::quiet_NaN();
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), 3.0, qNAN));
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), qNAN, 3.0));
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), -3.0, qNAN));
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), qNAN, -3.0));
|
|
|
|
double sNAN = std::numeric_limits<double>::signaling_NaN();
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), 3.0, sNAN));
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), sNAN, 3.0));
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), -3.0, sNAN));
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), sNAN, -3.0));
|
|
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), qNAN, qNAN));
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), sNAN, sNAN));
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), qNAN, sNAN));
|
|
EXPECT_BITEQ(qNAN, CallD(test->entry(), sNAN, qNAN));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(RoundSingle, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zfa);
|
|
__ frounds(FA0, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(RoundSingle, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"40450553 fround.s fa0, fa0\n"
|
|
"00008067 ret\n");
|
|
|
|
EXPECT_EQ(-44.0f, CallF(test->entry(), -43.6f));
|
|
EXPECT_EQ(-44.0f, CallF(test->entry(), -43.5f));
|
|
EXPECT_EQ(-43.0f, CallF(test->entry(), -43.4f));
|
|
EXPECT_EQ(-43.0f, CallF(test->entry(), -43.0f));
|
|
EXPECT_EQ(-43.0f, CallF(test->entry(), -42.6f));
|
|
EXPECT_EQ(-42.0f, CallF(test->entry(), -42.5f));
|
|
EXPECT_EQ(-42.0f, CallF(test->entry(), -42.4f));
|
|
EXPECT_EQ(-42.0f, CallF(test->entry(), -42.0f));
|
|
EXPECT_BITEQ(-0.0f, CallF(test->entry(), -0.0f));
|
|
EXPECT_BITEQ(+0.0f, CallF(test->entry(), +0.0f));
|
|
EXPECT_EQ(42.0f, CallF(test->entry(), 42.0f));
|
|
EXPECT_EQ(42.0f, CallF(test->entry(), 42.4f));
|
|
EXPECT_EQ(42.0f, CallF(test->entry(), 42.5f));
|
|
EXPECT_EQ(43.0f, CallF(test->entry(), 42.6f));
|
|
EXPECT_EQ(43.0f, CallF(test->entry(), 43.0f));
|
|
EXPECT_EQ(43.0f, CallF(test->entry(), 43.4f));
|
|
EXPECT_EQ(44.0f, CallF(test->entry(), 43.5f));
|
|
EXPECT_EQ(44.0f, CallF(test->entry(), 43.6f));
|
|
|
|
EXPECT_EQ(-std::numeric_limits<float>::infinity(),
|
|
CallF(test->entry(), -std::numeric_limits<float>::infinity()));
|
|
EXPECT_EQ(std::numeric_limits<float>::infinity(),
|
|
CallF(test->entry(), std::numeric_limits<float>::infinity()));
|
|
EXPECT_BITEQ(std::numeric_limits<float>::quiet_NaN(),
|
|
CallF(test->entry(), std::numeric_limits<float>::quiet_NaN()));
|
|
EXPECT_BITEQ(
|
|
std::numeric_limits<float>::quiet_NaN(),
|
|
CallF(test->entry(), std::numeric_limits<float>::signaling_NaN()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(RoundSingle_RTZ, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zfa);
|
|
__ frounds(FA0, FA0, RTZ);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(RoundSingle_RTZ, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"40451553 fround.s fa0, fa0, rtz\n"
|
|
"00008067 ret\n");
|
|
|
|
EXPECT_EQ(-43.0f, CallF(test->entry(), -43.6f));
|
|
EXPECT_EQ(-43.0f, CallF(test->entry(), -43.5f));
|
|
EXPECT_EQ(-43.0f, CallF(test->entry(), -43.4f));
|
|
EXPECT_EQ(-43.0f, CallF(test->entry(), -43.0f));
|
|
EXPECT_EQ(-42.0f, CallF(test->entry(), -42.6f));
|
|
EXPECT_EQ(-42.0f, CallF(test->entry(), -42.5f));
|
|
EXPECT_EQ(-42.0f, CallF(test->entry(), -42.4f));
|
|
EXPECT_EQ(-42.0f, CallF(test->entry(), -42.0f));
|
|
EXPECT_BITEQ(-0.0f, CallF(test->entry(), -0.0f));
|
|
EXPECT_BITEQ(+0.0f, CallF(test->entry(), +0.0f));
|
|
EXPECT_EQ(42.0f, CallF(test->entry(), 42.0f));
|
|
EXPECT_EQ(42.0f, CallF(test->entry(), 42.4f));
|
|
EXPECT_EQ(42.0f, CallF(test->entry(), 42.5f));
|
|
EXPECT_EQ(42.0f, CallF(test->entry(), 42.6f));
|
|
EXPECT_EQ(43.0f, CallF(test->entry(), 43.0f));
|
|
EXPECT_EQ(43.0f, CallF(test->entry(), 43.4f));
|
|
EXPECT_EQ(43.0f, CallF(test->entry(), 43.5f));
|
|
EXPECT_EQ(43.0f, CallF(test->entry(), 43.6f));
|
|
|
|
EXPECT_EQ(-std::numeric_limits<float>::infinity(),
|
|
CallF(test->entry(), -std::numeric_limits<float>::infinity()));
|
|
EXPECT_EQ(std::numeric_limits<float>::infinity(),
|
|
CallF(test->entry(), std::numeric_limits<float>::infinity()));
|
|
EXPECT_BITEQ(std::numeric_limits<float>::quiet_NaN(),
|
|
CallF(test->entry(), std::numeric_limits<float>::quiet_NaN()));
|
|
EXPECT_BITEQ(
|
|
std::numeric_limits<float>::quiet_NaN(),
|
|
CallF(test->entry(), std::numeric_limits<float>::signaling_NaN()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(RoundSingle_RDN, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zfa);
|
|
__ frounds(FA0, FA0, RDN);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(RoundSingle_RDN, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"40452553 fround.s fa0, fa0, rdn\n"
|
|
"00008067 ret\n");
|
|
|
|
EXPECT_EQ(-44.0f, CallF(test->entry(), -43.6f));
|
|
EXPECT_EQ(-44.0f, CallF(test->entry(), -43.5f));
|
|
EXPECT_EQ(-44.0f, CallF(test->entry(), -43.4f));
|
|
EXPECT_EQ(-43.0f, CallF(test->entry(), -43.0f));
|
|
EXPECT_EQ(-43.0f, CallF(test->entry(), -42.6f));
|
|
EXPECT_EQ(-43.0f, CallF(test->entry(), -42.5f));
|
|
EXPECT_EQ(-43.0f, CallF(test->entry(), -42.4f));
|
|
EXPECT_EQ(-42.0f, CallF(test->entry(), -42.0f));
|
|
EXPECT_BITEQ(-0.0f, CallF(test->entry(), -0.0f));
|
|
EXPECT_BITEQ(+0.0f, CallF(test->entry(), +0.0f));
|
|
EXPECT_EQ(42.0f, CallF(test->entry(), 42.0f));
|
|
EXPECT_EQ(42.0f, CallF(test->entry(), 42.4f));
|
|
EXPECT_EQ(42.0f, CallF(test->entry(), 42.5f));
|
|
EXPECT_EQ(42.0f, CallF(test->entry(), 42.6f));
|
|
EXPECT_EQ(43.0f, CallF(test->entry(), 43.0f));
|
|
EXPECT_EQ(43.0f, CallF(test->entry(), 43.4f));
|
|
EXPECT_EQ(43.0f, CallF(test->entry(), 43.5f));
|
|
EXPECT_EQ(43.0f, CallF(test->entry(), 43.6f));
|
|
|
|
EXPECT_EQ(-std::numeric_limits<float>::infinity(),
|
|
CallF(test->entry(), -std::numeric_limits<float>::infinity()));
|
|
EXPECT_EQ(std::numeric_limits<float>::infinity(),
|
|
CallF(test->entry(), std::numeric_limits<float>::infinity()));
|
|
EXPECT_BITEQ(std::numeric_limits<float>::quiet_NaN(),
|
|
CallF(test->entry(), std::numeric_limits<float>::quiet_NaN()));
|
|
EXPECT_BITEQ(
|
|
std::numeric_limits<float>::quiet_NaN(),
|
|
CallF(test->entry(), std::numeric_limits<float>::signaling_NaN()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(RoundSingle_RUP, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zfa);
|
|
__ frounds(FA0, FA0, RUP);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(RoundSingle_RUP, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"40453553 fround.s fa0, fa0, rup\n"
|
|
"00008067 ret\n");
|
|
|
|
EXPECT_EQ(-43.0f, CallF(test->entry(), -43.6f));
|
|
EXPECT_EQ(-43.0f, CallF(test->entry(), -43.5f));
|
|
EXPECT_EQ(-43.0f, CallF(test->entry(), -43.4f));
|
|
EXPECT_EQ(-43.0f, CallF(test->entry(), -43.0f));
|
|
EXPECT_EQ(-42.0f, CallF(test->entry(), -42.6f));
|
|
EXPECT_EQ(-42.0f, CallF(test->entry(), -42.5f));
|
|
EXPECT_EQ(-42.0f, CallF(test->entry(), -42.4f));
|
|
EXPECT_EQ(-42.0f, CallF(test->entry(), -42.0f));
|
|
EXPECT_BITEQ(-0.0f, CallF(test->entry(), -0.0f));
|
|
EXPECT_BITEQ(+0.0f, CallF(test->entry(), +0.0f));
|
|
EXPECT_EQ(42.0f, CallF(test->entry(), 42.0f));
|
|
EXPECT_EQ(43.0f, CallF(test->entry(), 42.4f));
|
|
EXPECT_EQ(43.0f, CallF(test->entry(), 42.5f));
|
|
EXPECT_EQ(43.0f, CallF(test->entry(), 42.6f));
|
|
EXPECT_EQ(43.0f, CallF(test->entry(), 43.0f));
|
|
EXPECT_EQ(44.0f, CallF(test->entry(), 43.4f));
|
|
EXPECT_EQ(44.0f, CallF(test->entry(), 43.5f));
|
|
EXPECT_EQ(44.0f, CallF(test->entry(), 43.6f));
|
|
|
|
EXPECT_EQ(-std::numeric_limits<float>::infinity(),
|
|
CallF(test->entry(), -std::numeric_limits<float>::infinity()));
|
|
EXPECT_EQ(std::numeric_limits<float>::infinity(),
|
|
CallF(test->entry(), std::numeric_limits<float>::infinity()));
|
|
EXPECT_BITEQ(std::numeric_limits<float>::quiet_NaN(),
|
|
CallF(test->entry(), std::numeric_limits<float>::quiet_NaN()));
|
|
EXPECT_BITEQ(
|
|
std::numeric_limits<float>::quiet_NaN(),
|
|
CallF(test->entry(), std::numeric_limits<float>::signaling_NaN()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(RoundSingle_RMM, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zfa);
|
|
__ frounds(FA0, FA0, RMM);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(RoundSingle_RMM, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"40454553 fround.s fa0, fa0, rmm\n"
|
|
"00008067 ret\n");
|
|
|
|
EXPECT_EQ(-44.0f, CallF(test->entry(), -43.6f));
|
|
EXPECT_EQ(-44.0f, CallF(test->entry(), -43.5f));
|
|
EXPECT_EQ(-43.0f, CallF(test->entry(), -43.4f));
|
|
EXPECT_EQ(-43.0f, CallF(test->entry(), -43.0f));
|
|
EXPECT_EQ(-43.0f, CallF(test->entry(), -42.6f));
|
|
EXPECT_EQ(-43.0f, CallF(test->entry(), -42.5f));
|
|
EXPECT_EQ(-42.0f, CallF(test->entry(), -42.4f));
|
|
EXPECT_EQ(-42.0f, CallF(test->entry(), -42.0f));
|
|
EXPECT_BITEQ(-0.0f, CallF(test->entry(), -0.0f));
|
|
EXPECT_BITEQ(+0.0f, CallF(test->entry(), +0.0f));
|
|
EXPECT_EQ(42.0f, CallF(test->entry(), 42.0f));
|
|
EXPECT_EQ(42.0f, CallF(test->entry(), 42.4f));
|
|
EXPECT_EQ(43.0f, CallF(test->entry(), 42.5f));
|
|
EXPECT_EQ(43.0f, CallF(test->entry(), 42.6f));
|
|
EXPECT_EQ(43.0f, CallF(test->entry(), 43.0f));
|
|
EXPECT_EQ(43.0f, CallF(test->entry(), 43.4f));
|
|
EXPECT_EQ(44.0f, CallF(test->entry(), 43.5f));
|
|
EXPECT_EQ(44.0f, CallF(test->entry(), 43.6f));
|
|
|
|
EXPECT_EQ(-std::numeric_limits<float>::infinity(),
|
|
CallF(test->entry(), -std::numeric_limits<float>::infinity()));
|
|
EXPECT_EQ(std::numeric_limits<float>::infinity(),
|
|
CallF(test->entry(), std::numeric_limits<float>::infinity()));
|
|
EXPECT_BITEQ(std::numeric_limits<float>::quiet_NaN(),
|
|
CallF(test->entry(), std::numeric_limits<float>::quiet_NaN()));
|
|
EXPECT_BITEQ(
|
|
std::numeric_limits<float>::quiet_NaN(),
|
|
CallF(test->entry(), std::numeric_limits<float>::signaling_NaN()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(RoundDouble, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zfa);
|
|
__ froundd(FA0, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(RoundDouble, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"42450553 fround.d fa0, fa0\n"
|
|
"00008067 ret\n");
|
|
|
|
EXPECT_EQ(-44.0, CallD(test->entry(), -43.6));
|
|
EXPECT_EQ(-44.0, CallD(test->entry(), -43.5));
|
|
EXPECT_EQ(-43.0, CallD(test->entry(), -43.4));
|
|
EXPECT_EQ(-43.0, CallD(test->entry(), -43.0));
|
|
EXPECT_EQ(-43.0, CallD(test->entry(), -42.6));
|
|
EXPECT_EQ(-42.0, CallD(test->entry(), -42.5));
|
|
EXPECT_EQ(-42.0, CallD(test->entry(), -42.4));
|
|
EXPECT_EQ(-42.0, CallD(test->entry(), -42.0));
|
|
EXPECT_BITEQ(-0.0, CallD(test->entry(), -0.0));
|
|
EXPECT_BITEQ(+0.0, CallD(test->entry(), +0.0));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), 42.0));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), 42.4));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), 42.5));
|
|
EXPECT_EQ(43.0, CallD(test->entry(), 42.6));
|
|
EXPECT_EQ(43.0, CallD(test->entry(), 43.0));
|
|
EXPECT_EQ(43.0, CallD(test->entry(), 43.4));
|
|
EXPECT_EQ(44.0, CallD(test->entry(), 43.5));
|
|
EXPECT_EQ(44.0, CallD(test->entry(), 43.6));
|
|
|
|
EXPECT_EQ(-std::numeric_limits<double>::infinity(),
|
|
CallD(test->entry(), -std::numeric_limits<double>::infinity()));
|
|
EXPECT_EQ(std::numeric_limits<double>::infinity(),
|
|
CallD(test->entry(), std::numeric_limits<double>::infinity()));
|
|
EXPECT_BITEQ(std::numeric_limits<double>::quiet_NaN(),
|
|
CallD(test->entry(), std::numeric_limits<double>::quiet_NaN()));
|
|
EXPECT_BITEQ(
|
|
std::numeric_limits<double>::quiet_NaN(),
|
|
CallD(test->entry(), std::numeric_limits<double>::signaling_NaN()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(RoundDouble_RTZ, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zfa);
|
|
__ froundd(FA0, FA0, RTZ);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(RoundDouble_RTZ, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"42451553 fround.d fa0, fa0, rtz\n"
|
|
"00008067 ret\n");
|
|
|
|
EXPECT_EQ(-43.0, CallD(test->entry(), -43.6));
|
|
EXPECT_EQ(-43.0, CallD(test->entry(), -43.5));
|
|
EXPECT_EQ(-43.0, CallD(test->entry(), -43.4));
|
|
EXPECT_EQ(-43.0, CallD(test->entry(), -43.0));
|
|
EXPECT_EQ(-42.0, CallD(test->entry(), -42.6));
|
|
EXPECT_EQ(-42.0, CallD(test->entry(), -42.5));
|
|
EXPECT_EQ(-42.0, CallD(test->entry(), -42.4));
|
|
EXPECT_EQ(-42.0, CallD(test->entry(), -42.0));
|
|
EXPECT_BITEQ(-0.0, CallD(test->entry(), -0.0));
|
|
EXPECT_BITEQ(+0.0, CallD(test->entry(), +0.0));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), 42.0));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), 42.4));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), 42.5));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), 42.6));
|
|
EXPECT_EQ(43.0, CallD(test->entry(), 43.0));
|
|
EXPECT_EQ(43.0, CallD(test->entry(), 43.4));
|
|
EXPECT_EQ(43.0, CallD(test->entry(), 43.5));
|
|
EXPECT_EQ(43.0, CallD(test->entry(), 43.6));
|
|
|
|
EXPECT_EQ(-std::numeric_limits<double>::infinity(),
|
|
CallD(test->entry(), -std::numeric_limits<double>::infinity()));
|
|
EXPECT_EQ(std::numeric_limits<double>::infinity(),
|
|
CallD(test->entry(), std::numeric_limits<double>::infinity()));
|
|
EXPECT_BITEQ(std::numeric_limits<double>::quiet_NaN(),
|
|
CallD(test->entry(), std::numeric_limits<double>::quiet_NaN()));
|
|
EXPECT_BITEQ(
|
|
std::numeric_limits<double>::quiet_NaN(),
|
|
CallD(test->entry(), std::numeric_limits<double>::signaling_NaN()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(RoundDouble_RDN, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zfa);
|
|
__ froundd(FA0, FA0, RDN);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(RoundDouble_RDN, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"42452553 fround.d fa0, fa0, rdn\n"
|
|
"00008067 ret\n");
|
|
|
|
EXPECT_EQ(-44.0, CallD(test->entry(), -43.6));
|
|
EXPECT_EQ(-44.0, CallD(test->entry(), -43.5));
|
|
EXPECT_EQ(-44.0, CallD(test->entry(), -43.4));
|
|
EXPECT_EQ(-43.0, CallD(test->entry(), -43.0));
|
|
EXPECT_EQ(-43.0, CallD(test->entry(), -42.6));
|
|
EXPECT_EQ(-43.0, CallD(test->entry(), -42.5));
|
|
EXPECT_EQ(-43.0, CallD(test->entry(), -42.4));
|
|
EXPECT_EQ(-42.0, CallD(test->entry(), -42.0));
|
|
EXPECT_BITEQ(-0.0, CallD(test->entry(), -0.0));
|
|
EXPECT_BITEQ(+0.0, CallD(test->entry(), +0.0));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), 42.0));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), 42.4));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), 42.5));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), 42.6));
|
|
EXPECT_EQ(43.0, CallD(test->entry(), 43.0));
|
|
EXPECT_EQ(43.0, CallD(test->entry(), 43.4));
|
|
EXPECT_EQ(43.0, CallD(test->entry(), 43.5));
|
|
EXPECT_EQ(43.0, CallD(test->entry(), 43.6));
|
|
|
|
EXPECT_EQ(-std::numeric_limits<double>::infinity(),
|
|
CallD(test->entry(), -std::numeric_limits<double>::infinity()));
|
|
EXPECT_EQ(std::numeric_limits<double>::infinity(),
|
|
CallD(test->entry(), std::numeric_limits<double>::infinity()));
|
|
EXPECT_BITEQ(std::numeric_limits<double>::quiet_NaN(),
|
|
CallD(test->entry(), std::numeric_limits<double>::quiet_NaN()));
|
|
EXPECT_BITEQ(
|
|
std::numeric_limits<double>::quiet_NaN(),
|
|
CallD(test->entry(), std::numeric_limits<double>::signaling_NaN()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(RoundDouble_RUP, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zfa);
|
|
__ froundd(FA0, FA0, RUP);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(RoundDouble_RUP, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"42453553 fround.d fa0, fa0, rup\n"
|
|
"00008067 ret\n");
|
|
|
|
EXPECT_EQ(-43.0, CallD(test->entry(), -43.6));
|
|
EXPECT_EQ(-43.0, CallD(test->entry(), -43.5));
|
|
EXPECT_EQ(-43.0, CallD(test->entry(), -43.4));
|
|
EXPECT_EQ(-43.0, CallD(test->entry(), -43.0));
|
|
EXPECT_EQ(-42.0, CallD(test->entry(), -42.6));
|
|
EXPECT_EQ(-42.0, CallD(test->entry(), -42.5));
|
|
EXPECT_EQ(-42.0, CallD(test->entry(), -42.4));
|
|
EXPECT_EQ(-42.0, CallD(test->entry(), -42.0));
|
|
EXPECT_BITEQ(-0.0, CallD(test->entry(), -0.0));
|
|
EXPECT_BITEQ(+0.0, CallD(test->entry(), +0.0));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), 42.0));
|
|
EXPECT_EQ(43.0, CallD(test->entry(), 42.4));
|
|
EXPECT_EQ(43.0, CallD(test->entry(), 42.5));
|
|
EXPECT_EQ(43.0, CallD(test->entry(), 42.6));
|
|
EXPECT_EQ(43.0, CallD(test->entry(), 43.0));
|
|
EXPECT_EQ(44.0, CallD(test->entry(), 43.4));
|
|
EXPECT_EQ(44.0, CallD(test->entry(), 43.5));
|
|
EXPECT_EQ(44.0, CallD(test->entry(), 43.6));
|
|
|
|
EXPECT_EQ(-std::numeric_limits<double>::infinity(),
|
|
CallD(test->entry(), -std::numeric_limits<double>::infinity()));
|
|
EXPECT_EQ(std::numeric_limits<double>::infinity(),
|
|
CallD(test->entry(), std::numeric_limits<double>::infinity()));
|
|
EXPECT_BITEQ(std::numeric_limits<double>::quiet_NaN(),
|
|
CallD(test->entry(), std::numeric_limits<double>::quiet_NaN()));
|
|
EXPECT_BITEQ(
|
|
std::numeric_limits<double>::quiet_NaN(),
|
|
CallD(test->entry(), std::numeric_limits<double>::signaling_NaN()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(RoundDouble_RMM, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zfa);
|
|
__ froundd(FA0, FA0, RMM);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(RoundDouble_RMM, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"42454553 fround.d fa0, fa0, rmm\n"
|
|
"00008067 ret\n");
|
|
|
|
EXPECT_EQ(-44.0, CallD(test->entry(), -43.6));
|
|
EXPECT_EQ(-44.0, CallD(test->entry(), -43.5));
|
|
EXPECT_EQ(-43.0, CallD(test->entry(), -43.4));
|
|
EXPECT_EQ(-43.0, CallD(test->entry(), -43.0));
|
|
EXPECT_EQ(-43.0, CallD(test->entry(), -42.6));
|
|
EXPECT_EQ(-43.0, CallD(test->entry(), -42.5));
|
|
EXPECT_EQ(-42.0, CallD(test->entry(), -42.4));
|
|
EXPECT_EQ(-42.0, CallD(test->entry(), -42.0));
|
|
EXPECT_BITEQ(-0.0, CallD(test->entry(), -0.0));
|
|
EXPECT_BITEQ(+0.0, CallD(test->entry(), +0.0));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), 42.0));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), 42.4));
|
|
EXPECT_EQ(43.0, CallD(test->entry(), 42.5));
|
|
EXPECT_EQ(43.0, CallD(test->entry(), 42.6));
|
|
EXPECT_EQ(43.0, CallD(test->entry(), 43.0));
|
|
EXPECT_EQ(43.0, CallD(test->entry(), 43.4));
|
|
EXPECT_EQ(44.0, CallD(test->entry(), 43.5));
|
|
EXPECT_EQ(44.0, CallD(test->entry(), 43.6));
|
|
|
|
EXPECT_EQ(-std::numeric_limits<double>::infinity(),
|
|
CallD(test->entry(), -std::numeric_limits<double>::infinity()));
|
|
EXPECT_EQ(std::numeric_limits<double>::infinity(),
|
|
CallD(test->entry(), std::numeric_limits<double>::infinity()));
|
|
EXPECT_BITEQ(std::numeric_limits<double>::quiet_NaN(),
|
|
CallD(test->entry(), std::numeric_limits<double>::quiet_NaN()));
|
|
EXPECT_BITEQ(
|
|
std::numeric_limits<double>::quiet_NaN(),
|
|
CallD(test->entry(), std::numeric_limits<double>::signaling_NaN()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(ModularConvertDoubleToWord, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zfa);
|
|
__ fcvtmodwd(A0, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(ModularConvertDoubleToWord, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"c2851553 fcvtmod.w.d a0, fa0, rtz\n"
|
|
"00008067 ret\n");
|
|
|
|
EXPECT_EQ(-42, CallI(test->entry(), -42.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), 0.0));
|
|
EXPECT_EQ(42, CallI(test->entry(), 42.0));
|
|
EXPECT_EQ(sign_extend(kMinInt32),
|
|
CallI(test->entry(), static_cast<double>(kMinInt32)));
|
|
EXPECT_EQ(sign_extend(kMaxInt32),
|
|
CallI(test->entry(), static_cast<double>(kMaxInt32)));
|
|
EXPECT_EQ(-1, CallI(test->entry(), static_cast<double>(kMaxUint32)));
|
|
EXPECT_EQ(0, CallI(test->entry(), static_cast<double>(kMinInt64)));
|
|
EXPECT_EQ(0, CallI(test->entry(), static_cast<double>(kMaxInt64)));
|
|
EXPECT_EQ(0, CallI(test->entry(), static_cast<double>(kMaxUint64)));
|
|
EXPECT_EQ(0,
|
|
CallI(test->entry(), -std::numeric_limits<double>::denorm_min()));
|
|
EXPECT_EQ(0, CallI(test->entry(), std::numeric_limits<double>::denorm_min()));
|
|
EXPECT_EQ(0, CallI(test->entry(), -std::numeric_limits<double>::infinity()));
|
|
EXPECT_EQ(0, CallI(test->entry(), std::numeric_limits<double>::infinity()));
|
|
EXPECT_EQ(0,
|
|
CallI(test->entry(), std::numeric_limits<double>::signaling_NaN()));
|
|
}
|
|
|
|
#if XLEN == 32
|
|
ASSEMBLER_TEST_GENERATE(BitCastDoubleToIntegerHigh, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zfa);
|
|
__ fmvxw(A0, FA0);
|
|
__ fmvhxd(A1, FA0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(BitCastDoubleToIntegerHigh, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"e0050553 fmv.x.w a0, fa0\n"
|
|
"e21505d3 fmvh.x.d a1, fa0\n"
|
|
"00008067 ret\n");
|
|
|
|
EXPECT_EQ(bit_cast<int64_t>(0.0), CallI64(test->entry(), 0.0));
|
|
EXPECT_EQ(bit_cast<int64_t>(-0.0), CallI64(test->entry(), -0.0));
|
|
EXPECT_EQ(bit_cast<int64_t>(42.0), CallI64(test->entry(), 42.0));
|
|
EXPECT_EQ(bit_cast<int64_t>(-42.0), CallI64(test->entry(), -42.0));
|
|
EXPECT_EQ(bit_cast<int64_t>(std::numeric_limits<double>::quiet_NaN()),
|
|
CallI64(test->entry(), std::numeric_limits<double>::quiet_NaN()));
|
|
EXPECT_EQ(
|
|
bit_cast<int64_t>(std::numeric_limits<double>::signaling_NaN()),
|
|
CallI64(test->entry(), std::numeric_limits<double>::signaling_NaN()));
|
|
EXPECT_EQ(bit_cast<int64_t>(std::numeric_limits<double>::infinity()),
|
|
CallI64(test->entry(), std::numeric_limits<double>::infinity()));
|
|
EXPECT_EQ(bit_cast<int64_t>(-std::numeric_limits<double>::infinity()),
|
|
CallI64(test->entry(), -std::numeric_limits<double>::infinity()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(BitCastIntegerPairToDouble, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zfa);
|
|
__ fmvpdx(FA0, A0, A1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(BitCastIntegerPairToDouble, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"b2b50553 fmvp.d.x fa0, a0, a1\n"
|
|
"00008067 ret\n");
|
|
|
|
EXPECT_BITEQ(0.0, CallD(test->entry(), bit_cast<int64_t>(0.0)));
|
|
EXPECT_BITEQ(-0.0, CallD(test->entry(), bit_cast<int64_t>(-0.0)));
|
|
EXPECT_EQ(42.0, CallD(test->entry(), bit_cast<int64_t>(42.0)));
|
|
EXPECT_EQ(-42.0, CallD(test->entry(), bit_cast<int64_t>(-42.0)));
|
|
EXPECT_BITEQ(
|
|
std::numeric_limits<double>::quiet_NaN(),
|
|
CallD(test->entry(),
|
|
bit_cast<int64_t>(std::numeric_limits<double>::quiet_NaN())));
|
|
EXPECT_BITEQ(
|
|
std::numeric_limits<double>::signaling_NaN(),
|
|
CallD(test->entry(),
|
|
bit_cast<int64_t>(std::numeric_limits<double>::signaling_NaN())));
|
|
EXPECT_BITEQ(
|
|
std::numeric_limits<double>::infinity(),
|
|
CallD(test->entry(),
|
|
bit_cast<int64_t>(std::numeric_limits<double>::infinity())));
|
|
EXPECT_BITEQ(
|
|
-std::numeric_limits<double>::infinity(),
|
|
CallD(test->entry(),
|
|
bit_cast<int64_t>(-std::numeric_limits<double>::infinity())));
|
|
}
|
|
#endif // XLEN == 32
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleLessThanQuiet, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zfa);
|
|
__ fltqs(A0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleLessThanQuiet, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"a0b55553 fltq.s a0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, 1.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, 3.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), 3.0f, 5.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, -1.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, -3.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, -5.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0f, 1.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0f, 3.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0f, 5.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0f, -1.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0f, -3.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0f, -5.0f));
|
|
|
|
float qNAN = std::numeric_limits<float>::quiet_NaN();
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, qNAN));
|
|
EXPECT_EQ(0, CallI(test->entry(), qNAN, 3.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0f, qNAN));
|
|
EXPECT_EQ(0, CallI(test->entry(), qNAN, -3.0f));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SingleLessOrEqualQuiet, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zfa);
|
|
__ fleqs(A0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SingleLessOrEqualQuiet, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"a0b54553 fleq.s a0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, 1.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), 3.0f, 3.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), 3.0f, 5.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, -1.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, -3.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, -5.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0f, 1.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0f, 3.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0f, 5.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0f, -1.0f));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0f, -3.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0f, -5.0f));
|
|
|
|
float qNAN = std::numeric_limits<float>::quiet_NaN();
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0f, qNAN));
|
|
EXPECT_EQ(0, CallI(test->entry(), qNAN, 3.0f));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0f, qNAN));
|
|
EXPECT_EQ(0, CallI(test->entry(), qNAN, -3.0f));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleLessThanQuiet, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zfa);
|
|
__ fltqd(A0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleLessThanQuiet, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"a2b55553 fltq.d a0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, 1.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, 3.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), 3.0, 5.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, -1.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, -3.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, -5.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0, 1.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0, 3.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0, 5.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0, -1.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0, -3.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0, -5.0));
|
|
|
|
double qNAN = std::numeric_limits<double>::quiet_NaN();
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, qNAN));
|
|
EXPECT_EQ(0, CallI(test->entry(), qNAN, 3.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0, qNAN));
|
|
EXPECT_EQ(0, CallI(test->entry(), qNAN, -3.0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(DoubleLessOrEqualQuiet, assembler) {
|
|
__ SetExtensions(RV_G | RV_Zfa);
|
|
__ fleqd(A0, FA0, FA1);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(DoubleLessOrEqualQuiet, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"a2b54553 fleq.d a0, fa0, fa1\n"
|
|
"00008067 ret\n");
|
|
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, 1.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), 3.0, 3.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), 3.0, 5.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, -1.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, -3.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, -5.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0, 1.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0, 3.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0, 5.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0, -1.0));
|
|
EXPECT_EQ(1, CallI(test->entry(), -3.0, -3.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0, -5.0));
|
|
|
|
double qNAN = std::numeric_limits<double>::quiet_NaN();
|
|
EXPECT_EQ(0, CallI(test->entry(), 3.0, qNAN));
|
|
EXPECT_EQ(0, CallI(test->entry(), qNAN, 3.0));
|
|
EXPECT_EQ(0, CallI(test->entry(), -3.0, qNAN));
|
|
EXPECT_EQ(0, CallI(test->entry(), qNAN, -3.0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(LoadByteAcquire, assembler) {
|
|
__ SetExtensions(RV_GC | RV_Zalasr);
|
|
__ lb(A0, Address(A1), std::memory_order_acquire);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(LoadByteAcquire, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"3405852f lb.aq a0, (a1)\n"
|
|
" 8082 ret\n");
|
|
|
|
int8_t data = -42;
|
|
EXPECT_EQ(-42, Call(test->entry(), 0, reinterpret_cast<intx_t>(&data)));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(LoadHalfwordAcquire, assembler) {
|
|
__ SetExtensions(RV_GC | RV_Zalasr);
|
|
__ lh(A0, Address(A1), std::memory_order_acquire);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(LoadHalfwordAcquire, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"3405952f lh.aq a0, (a1)\n"
|
|
" 8082 ret\n");
|
|
|
|
int16_t data = -42;
|
|
EXPECT_EQ(-42, Call(test->entry(), 0, reinterpret_cast<intx_t>(&data)));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(LoadWordAcquire, assembler) {
|
|
__ SetExtensions(RV_GC | RV_Zalasr);
|
|
__ lw(A0, Address(A1), std::memory_order_acquire);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(LoadWordAcquire, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"3405a52f lw.aq a0, (a1)\n"
|
|
" 8082 ret\n");
|
|
|
|
int32_t data = -42;
|
|
EXPECT_EQ(-42, Call(test->entry(), 0, reinterpret_cast<intx_t>(&data)));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(StoreByteRelease, assembler) {
|
|
__ SetExtensions(RV_GC | RV_Zalasr);
|
|
__ sb(A0, Address(A1), std::memory_order_release);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(StoreByteRelease, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"3aa5802f sb.rl a0, (a1)\n"
|
|
" 8082 ret\n");
|
|
|
|
int8_t data = 0;
|
|
EXPECT_EQ(-42, Call(test->entry(), -42, reinterpret_cast<intx_t>(&data)));
|
|
EXPECT_EQ(-42, data);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(StoreHalfwordRelease, assembler) {
|
|
__ SetExtensions(RV_GC | RV_Zalasr);
|
|
__ sh(A0, Address(A1), std::memory_order_release);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(StoreHalfwordRelease, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"3aa5902f sh.rl a0, (a1)\n"
|
|
" 8082 ret\n");
|
|
|
|
int16_t data = 0;
|
|
EXPECT_EQ(-42, Call(test->entry(), -42, reinterpret_cast<intx_t>(&data)));
|
|
EXPECT_EQ(-42, data);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(StoreWordRelease, assembler) {
|
|
__ SetExtensions(RV_GC | RV_Zalasr);
|
|
__ sw(A0, Address(A1), std::memory_order_release);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(StoreWordRelease, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"3aa5a02f sw.rl a0, (a1)\n"
|
|
" 8082 ret\n");
|
|
|
|
int32_t data = 0;
|
|
EXPECT_EQ(-42, Call(test->entry(), -42, reinterpret_cast<intx_t>(&data)));
|
|
EXPECT_EQ(-42, data);
|
|
}
|
|
|
|
#if XLEN >= 64
|
|
ASSEMBLER_TEST_GENERATE(LoadDoubleWordAcquire, assembler) {
|
|
__ SetExtensions(RV_GC | RV_Zalasr);
|
|
__ ld(A0, Address(A1), std::memory_order_acquire);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(LoadDoubleWordAcquire, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"3405b52f ld.aq a0, (a1)\n"
|
|
" 8082 ret\n");
|
|
|
|
int64_t data = -42;
|
|
EXPECT_EQ(-42, Call(test->entry(), 0, reinterpret_cast<intx_t>(&data)));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(StoreDoubleWordRelease, assembler) {
|
|
__ SetExtensions(RV_GC | RV_Zalasr);
|
|
__ sd(A0, Address(A1), std::memory_order_release);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(StoreDoubleWordRelease, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"3aa5b02f sd.rl a0, (a1)\n"
|
|
" 8082 ret\n");
|
|
|
|
int64_t data = 0;
|
|
EXPECT_EQ(-42, Call(test->entry(), -42, reinterpret_cast<intx_t>(&data)));
|
|
EXPECT_EQ(-42, data);
|
|
}
|
|
#endif // XLEN >= 64
|
|
|
|
ASSEMBLER_TEST_GENERATE(LoadImmediate_MaxInt32, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ LoadImmediate(A0, kMaxInt32);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(LoadImmediate_MaxInt32, test) {
|
|
#if XLEN == 32
|
|
EXPECT_DISASSEMBLY(
|
|
"80000537 lui a0, -2147483648\n"
|
|
" 157d addi a0, a0, -1\n"
|
|
" 8082 ret\n");
|
|
#elif XLEN == 64
|
|
EXPECT_DISASSEMBLY(
|
|
"80000537 lui a0, -2147483648\n"
|
|
" 357d addiw a0, a0, -1\n"
|
|
" 8082 ret\n");
|
|
#endif
|
|
EXPECT_EQ(kMaxInt32, Call(test->entry()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(LoadImmediate_MinInt32, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ LoadImmediate(A0, kMinInt32);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(LoadImmediate_MinInt32, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"80000537 lui a0, -2147483648\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(kMinInt32, Call(test->entry()));
|
|
}
|
|
|
|
#if XLEN >= 64
|
|
ASSEMBLER_TEST_GENERATE(LoadImmediate_MinInt64, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ LoadImmediate(A0, kMinInt64);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(LoadImmediate_MinInt64, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 557d li a0, -1\n"
|
|
" 157e slli a0, a0, 0x3f\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(kMinInt64, Call(test->entry()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(LoadImmediate_Full, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ LoadImmediate(A0, 0xABCDABCDABCDABCD);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(LoadImmediate_Full, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"feaf3537 lui a0, -22073344\n"
|
|
"6af5051b addiw a0, a0, 1711\n"
|
|
" 0532 slli a0, a0, 0xc\n"
|
|
"36b50513 addi a0, a0, 875\n"
|
|
" 053a slli a0, a0, 0xe\n"
|
|
"cdb50513 addi a0, a0, -805\n"
|
|
" 0532 slli a0, a0, 0xc\n"
|
|
"bcd50513 addi a0, a0, -1075\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(static_cast<int64_t>(0xABCDABCDABCDABCD), Call(test->entry()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(LoadImmediate_LuiAddiwSlli, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ LoadImmediate(A0, 0x7BCDABCD00000);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(LoadImmediate_LuiAddiwSlli, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"7bcdb537 lui a0, 2077077504\n"
|
|
"bcd5051b addiw a0, a0, -1075\n"
|
|
" 0552 slli a0, a0, 0x14\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(static_cast<int64_t>(0x7BCDABCD00000), Call(test->entry()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(LoadImmediate_LuiSlli, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ LoadImmediate(A0, 0xABCDE00000000000);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(LoadImmediate_LuiSlli, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"d5e6f537 lui a0, -706285568\n"
|
|
" 1506 slli a0, a0, 0x21\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(static_cast<int64_t>(0xABCDE00000000000), Call(test->entry()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(LoadImmediate_LiSlli, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ LoadImmediate(A0, 0xABC00000000000);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(LoadImmediate_LiSlli, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"2af00513 li a0, 687\n"
|
|
" 153a slli a0, a0, 0x2e\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(static_cast<int64_t>(0xABC00000000000), Call(test->entry()));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(LoadImmediate_LiSlliAddi, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ LoadImmediate(A0, 0xFF000000000000FF);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(LoadImmediate_LiSlliAddi, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 557d li a0, -1\n"
|
|
" 1562 slli a0, a0, 0x38\n"
|
|
"0ff50513 addi a0, a0, 255\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(static_cast<int64_t>(0xFF000000000000FF), Call(test->entry()));
|
|
}
|
|
#endif
|
|
|
|
ASSEMBLER_TEST_GENERATE(BitwiseImmediates_GC, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
__ AndImmediate(A0, A1, ~0x10000000);
|
|
__ OrImmediate(A0, A1, 0x10000000);
|
|
__ XorImmediate(A0, A1, 0x10000000);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(BitwiseImmediates_GC, test) {
|
|
#if XLEN == 32
|
|
EXPECT_DISASSEMBLY(
|
|
"f0000737 lui tmp2, -268435456\n"
|
|
" 177d addi tmp2, tmp2, -1\n"
|
|
"00e5f533 and a0, a1, tmp2\n"
|
|
"10000737 lui tmp2, 268435456\n"
|
|
"00e5e533 or a0, a1, tmp2\n"
|
|
"10000737 lui tmp2, 268435456\n"
|
|
"00e5c533 xor a0, a1, tmp2\n"
|
|
" 8082 ret\n");
|
|
#else
|
|
EXPECT_DISASSEMBLY(
|
|
"f0000737 lui tmp2, -268435456\n"
|
|
" 377d addiw tmp2, tmp2, -1\n"
|
|
"00e5f533 and a0, a1, tmp2\n"
|
|
"10000737 lui tmp2, 268435456\n"
|
|
"00e5e533 or a0, a1, tmp2\n"
|
|
"10000737 lui tmp2, 268435456\n"
|
|
"00e5c533 xor a0, a1, tmp2\n"
|
|
" 8082 ret\n");
|
|
#endif
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(BitwiseImmediates_GCB, assembler) {
|
|
__ SetExtensions(RV_GCB);
|
|
__ AndImmediate(A0, A1, ~0x10000000);
|
|
__ OrImmediate(A0, A1, 0x10000000);
|
|
__ XorImmediate(A0, A1, 0x10000000);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(BitwiseImmediates_GCB, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"49c59513 bclri a0, a1, 0x1c\n"
|
|
"29c59513 bseti a0, a1, 0x1c\n"
|
|
"69c59513 binvi a0, a1, 0x1c\n"
|
|
" 8082 ret\n");
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AddImmediateBranchOverflow, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
Label overflow;
|
|
|
|
__ AddImmediateBranchOverflow(A0, A0, 2, &overflow);
|
|
__ ret();
|
|
__ Bind(&overflow);
|
|
__ li(A0, 0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AddImmediateBranchOverflow, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 872a mv tmp2, a0\n"
|
|
" 0509 addi a0, a0, 2\n"
|
|
"00e54363 blt a0, tmp2, +6\n"
|
|
" 8082 ret\n"
|
|
" 4501 li a0, 0\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(kMaxIntX - 1, Call(test->entry(), kMaxIntX - 3));
|
|
EXPECT_EQ(kMaxIntX, Call(test->entry(), kMaxIntX - 2));
|
|
EXPECT_EQ(0, Call(test->entry(), kMaxIntX - 1));
|
|
EXPECT_EQ(0, Call(test->entry(), kMaxIntX));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AddBranchOverflow_NonDestructive, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
Label overflow;
|
|
|
|
__ AddBranchOverflow(A0, A1, A2, &overflow);
|
|
__ ret();
|
|
__ Bind(&overflow);
|
|
__ li(A0, 0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AddBranchOverflow_NonDestructive, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"00c58533 add a0, a1, a2\n"
|
|
"00062693 slti tmp, a2, 0\n"
|
|
"00b52733 slt tmp2, a0, a1\n"
|
|
"00e69363 bne tmp, tmp2, +6\n"
|
|
" 8082 ret\n"
|
|
" 4501 li a0, 0\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(kMaxIntX - 1, Call(test->entry(), 42, kMaxIntX, -1));
|
|
EXPECT_EQ(kMaxIntX, Call(test->entry(), 42, kMaxIntX, 0));
|
|
EXPECT_EQ(0, Call(test->entry(), 42, kMaxIntX, 1));
|
|
|
|
EXPECT_EQ(0, Call(test->entry(), 42, kMinIntX, -1));
|
|
EXPECT_EQ(kMinIntX + 1, Call(test->entry(), 42, kMinIntX, 1));
|
|
EXPECT_EQ(kMinIntX, Call(test->entry(), 42, kMinIntX, 0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(AddBranchOverflow_Destructive, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
Label overflow;
|
|
|
|
__ AddBranchOverflow(A0, A1, A0, &overflow);
|
|
__ ret();
|
|
__ Bind(&overflow);
|
|
__ li(A0, 0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(AddBranchOverflow_Destructive, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"00052693 slti tmp, a0, 0\n"
|
|
" 952e add a0, a0, a1\n"
|
|
"00b52733 slt tmp2, a0, a1\n"
|
|
"00e69363 bne tmp, tmp2, +6\n"
|
|
" 8082 ret\n"
|
|
" 4501 li a0, 0\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(kMaxIntX - 1, Call(test->entry(), kMaxIntX, -1));
|
|
EXPECT_EQ(kMaxIntX, Call(test->entry(), kMaxIntX, 0));
|
|
EXPECT_EQ(0, Call(test->entry(), kMaxIntX, 1));
|
|
|
|
EXPECT_EQ(0, Call(test->entry(), kMinIntX, -1));
|
|
EXPECT_EQ(kMinIntX + 1, Call(test->entry(), kMinIntX, 1));
|
|
EXPECT_EQ(kMinIntX, Call(test->entry(), kMinIntX, 0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SubtractImmediateBranchOverflow, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
Label overflow;
|
|
|
|
__ SubtractImmediateBranchOverflow(A0, A0, 2, &overflow);
|
|
__ ret();
|
|
__ Bind(&overflow);
|
|
__ li(A0, 0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SubtractImmediateBranchOverflow, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
" 872a mv tmp2, a0\n"
|
|
" 1579 addi a0, a0, -2\n"
|
|
"00a74363 blt tmp2, a0, +6\n"
|
|
" 8082 ret\n"
|
|
" 4501 li a0, 0\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(kMinIntX + 1, Call(test->entry(), kMinIntX + 3));
|
|
EXPECT_EQ(kMinIntX, Call(test->entry(), kMinIntX + 2));
|
|
EXPECT_EQ(0, Call(test->entry(), kMinIntX + 1));
|
|
EXPECT_EQ(0, Call(test->entry(), kMinIntX));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SubtractBranchOverflow_NonDestructive, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
|
|
Label overflow;
|
|
__ SubtractBranchOverflow(A0, A1, A2, &overflow);
|
|
__ ret();
|
|
__ Bind(&overflow);
|
|
__ li(A0, 0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SubtractBranchOverflow_NonDestructive, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"40c58533 sub a0, a1, a2\n"
|
|
"00062693 slti tmp, a2, 0\n"
|
|
"00a5a733 slt tmp2, a1, a0\n"
|
|
"00e69363 bne tmp, tmp2, +6\n"
|
|
" 8082 ret\n"
|
|
" 4501 li a0, 0\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(kMaxIntX - 1, Call(test->entry(), 42, kMaxIntX, 1));
|
|
EXPECT_EQ(kMaxIntX, Call(test->entry(), 42, kMaxIntX, 0));
|
|
EXPECT_EQ(0, Call(test->entry(), 42, kMaxIntX, -1));
|
|
|
|
EXPECT_EQ(0, Call(test->entry(), 42, kMinIntX, 1));
|
|
EXPECT_EQ(kMinIntX + 1, Call(test->entry(), 42, kMinIntX, -1));
|
|
EXPECT_EQ(kMinIntX, Call(test->entry(), 42, kMinIntX, 0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(SubtractBranchOverflow_Destructive, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
|
|
Label overflow;
|
|
__ SubtractBranchOverflow(A0, A0, A1, &overflow);
|
|
__ ret();
|
|
__ Bind(&overflow);
|
|
__ li(A0, 0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(SubtractBranchOverflow_Destructive, test) {
|
|
EXPECT_DISASSEMBLY(
|
|
"00052693 slti tmp, a0, 0\n"
|
|
" 8d0d sub a0, a0, a1\n"
|
|
"00b52733 slt tmp2, a0, a1\n"
|
|
"00e69363 bne tmp, tmp2, +6\n"
|
|
" 8082 ret\n"
|
|
" 4501 li a0, 0\n"
|
|
" 8082 ret\n");
|
|
EXPECT_EQ(kMaxIntX - 1, Call(test->entry(), kMaxIntX, 1));
|
|
EXPECT_EQ(kMaxIntX, Call(test->entry(), kMaxIntX, 0));
|
|
EXPECT_EQ(0, Call(test->entry(), kMaxIntX, -1));
|
|
|
|
EXPECT_EQ(0, Call(test->entry(), kMinIntX, 1));
|
|
EXPECT_EQ(kMinIntX + 1, Call(test->entry(), kMinIntX, -1));
|
|
EXPECT_EQ(kMinIntX, Call(test->entry(), kMinIntX, 0));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(MultiplyImmediateBranchOverflow, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
Label overflow;
|
|
|
|
__ MultiplyImmediateBranchOverflow(A0, A0, 2, &overflow);
|
|
__ ret();
|
|
__ Bind(&overflow);
|
|
__ li(A0, 0);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(MultiplyImmediateBranchOverflow, test) {
|
|
#if XLEN == 64
|
|
EXPECT_DISASSEMBLY(
|
|
" 4709 li tmp2, 2\n"
|
|
"02e516b3 mulh tmp, a0, tmp2\n"
|
|
"02e50533 mul a0, a0, tmp2\n"
|
|
"43f55713 srai tmp2, a0, 0x3f\n"
|
|
"00e69363 bne tmp, tmp2, +6\n"
|
|
" 8082 ret\n"
|
|
" 4501 li a0, 0\n"
|
|
" 8082 ret\n");
|
|
#elif XLEN == 32
|
|
EXPECT_DISASSEMBLY(
|
|
" 4709 li tmp2, 2\n"
|
|
"02e516b3 mulh tmp, a0, tmp2\n"
|
|
"02e50533 mul a0, a0, tmp2\n"
|
|
"41f55713 srai tmp2, a0, 0x1f\n"
|
|
"00e69363 bne tmp, tmp2, +6\n"
|
|
" 8082 ret\n"
|
|
" 4501 li a0, 0\n"
|
|
" 8082 ret\n");
|
|
#endif
|
|
EXPECT_EQ(0, Call(test->entry(), kMinIntX));
|
|
EXPECT_EQ(0, Call(test->entry(), kMaxIntX));
|
|
EXPECT_EQ(-2, Call(test->entry(), -1));
|
|
EXPECT_EQ(2, Call(test->entry(), 1));
|
|
EXPECT_EQ(kMinIntX, Call(test->entry(), kMinIntX / 2));
|
|
EXPECT_EQ(kMaxIntX - 1, Call(test->entry(), (kMaxIntX - 1) / 2));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(MultiplyBranchOverflow_NonDestructive, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
|
|
Label overflow;
|
|
__ MultiplyBranchOverflow(A0, A1, A2, &overflow);
|
|
__ ret();
|
|
__ Bind(&overflow);
|
|
__ li(A0, 42);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(MultiplyBranchOverflow_NonDestructive, test) {
|
|
#if XLEN == 64
|
|
EXPECT_DISASSEMBLY(
|
|
"02c596b3 mulh tmp, a1, a2\n"
|
|
"02c58533 mul a0, a1, a2\n"
|
|
"43f55713 srai tmp2, a0, 0x3f\n"
|
|
"00e69363 bne tmp, tmp2, +6\n"
|
|
" 8082 ret\n"
|
|
"02a00513 li a0, 42\n"
|
|
" 8082 ret\n");
|
|
#elif XLEN == 32
|
|
EXPECT_DISASSEMBLY(
|
|
"02c596b3 mulh tmp, a1, a2\n"
|
|
"02c58533 mul a0, a1, a2\n"
|
|
"41f55713 srai tmp2, a0, 0x1f\n"
|
|
"00e69363 bne tmp, tmp2, +6\n"
|
|
" 8082 ret\n"
|
|
"02a00513 li a0, 42\n"
|
|
" 8082 ret\n");
|
|
#endif
|
|
EXPECT_EQ(42, Call(test->entry(), 42, kMaxIntX, -2));
|
|
EXPECT_EQ(-kMaxIntX, Call(test->entry(), 42, kMaxIntX, -1));
|
|
EXPECT_EQ(0, Call(test->entry(), 42, kMaxIntX, 0));
|
|
EXPECT_EQ(kMaxIntX, Call(test->entry(), 42, kMaxIntX, 1));
|
|
EXPECT_EQ(42, Call(test->entry(), 42, kMaxIntX, 2));
|
|
|
|
EXPECT_EQ(42, Call(test->entry(), 42, kMinIntX, -2));
|
|
EXPECT_EQ(42, Call(test->entry(), 42, kMinIntX, -1));
|
|
EXPECT_EQ(0, Call(test->entry(), 42, kMinIntX, 0));
|
|
EXPECT_EQ(kMinIntX, Call(test->entry(), 42, kMinIntX, 1));
|
|
EXPECT_EQ(42, Call(test->entry(), 42, kMinIntX, 2));
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(MultiplyBranchOverflow_Destructive, assembler) {
|
|
__ SetExtensions(RV_GC);
|
|
|
|
Label overflow;
|
|
__ MultiplyBranchOverflow(A0, A0, A1, &overflow);
|
|
__ ret();
|
|
__ Bind(&overflow);
|
|
__ li(A0, 42);
|
|
__ ret();
|
|
}
|
|
ASSEMBLER_TEST_RUN(MultiplyBranchOverflow_Destructive, test) {
|
|
#if XLEN == 64
|
|
EXPECT_DISASSEMBLY(
|
|
"02b516b3 mulh tmp, a0, a1\n"
|
|
"02b50533 mul a0, a0, a1\n"
|
|
"43f55713 srai tmp2, a0, 0x3f\n"
|
|
"00e69363 bne tmp, tmp2, +6\n"
|
|
" 8082 ret\n"
|
|
"02a00513 li a0, 42\n"
|
|
" 8082 ret\n");
|
|
#elif XLEN == 32
|
|
EXPECT_DISASSEMBLY(
|
|
"02b516b3 mulh tmp, a0, a1\n"
|
|
"02b50533 mul a0, a0, a1\n"
|
|
"41f55713 srai tmp2, a0, 0x1f\n"
|
|
"00e69363 bne tmp, tmp2, +6\n"
|
|
" 8082 ret\n"
|
|
"02a00513 li a0, 42\n"
|
|
" 8082 ret\n");
|
|
#endif
|
|
EXPECT_EQ(42, Call(test->entry(), kMaxIntX, -2));
|
|
EXPECT_EQ(-kMaxIntX, Call(test->entry(), kMaxIntX, -1));
|
|
EXPECT_EQ(0, Call(test->entry(), kMaxIntX, 0));
|
|
EXPECT_EQ(kMaxIntX, Call(test->entry(), kMaxIntX, 1));
|
|
EXPECT_EQ(42, Call(test->entry(), kMaxIntX, 2));
|
|
|
|
EXPECT_EQ(42, Call(test->entry(), kMinIntX, -2));
|
|
EXPECT_EQ(42, Call(test->entry(), kMinIntX, -1));
|
|
EXPECT_EQ(0, Call(test->entry(), kMinIntX, 0));
|
|
EXPECT_EQ(kMinIntX, Call(test->entry(), kMinIntX, 1));
|
|
EXPECT_EQ(42, Call(test->entry(), kMinIntX, 2));
|
|
}
|
|
|
|
#define TEST_ENCODING(type, name) \
|
|
VM_UNIT_TEST_CASE(Encoding##name) { \
|
|
for (intptr_t v = -(1 << 21); v <= (1 << 21); v++) { \
|
|
type value = static_cast<type>(v); \
|
|
if (!Is##name(value)) continue; \
|
|
int32_t encoded = Encode##name(value); \
|
|
type decoded = Decode##name(encoded); \
|
|
EXPECT_EQ(value, decoded); \
|
|
} \
|
|
}
|
|
|
|
TEST_ENCODING(Register, Rd)
|
|
TEST_ENCODING(Register, Rs1)
|
|
TEST_ENCODING(Register, Rs2)
|
|
TEST_ENCODING(FRegister, FRd)
|
|
TEST_ENCODING(FRegister, FRs1)
|
|
TEST_ENCODING(FRegister, FRs2)
|
|
TEST_ENCODING(FRegister, FRs3)
|
|
TEST_ENCODING(Funct2, Funct2)
|
|
TEST_ENCODING(Funct3, Funct3)
|
|
TEST_ENCODING(Funct5, Funct5)
|
|
TEST_ENCODING(Funct7, Funct7)
|
|
TEST_ENCODING(Funct12, Funct12)
|
|
TEST_ENCODING(RoundingMode, RoundingMode)
|
|
TEST_ENCODING(intptr_t, BTypeImm)
|
|
TEST_ENCODING(intptr_t, JTypeImm)
|
|
TEST_ENCODING(intptr_t, ITypeImm)
|
|
TEST_ENCODING(intptr_t, STypeImm)
|
|
TEST_ENCODING(intptr_t, UTypeImm)
|
|
|
|
TEST_ENCODING(Register, CRd)
|
|
TEST_ENCODING(Register, CRs1)
|
|
TEST_ENCODING(Register, CRs2)
|
|
TEST_ENCODING(Register, CRdp)
|
|
TEST_ENCODING(Register, CRs1p)
|
|
TEST_ENCODING(Register, CRs2p)
|
|
TEST_ENCODING(FRegister, CFRd)
|
|
TEST_ENCODING(FRegister, CFRs1)
|
|
TEST_ENCODING(FRegister, CFRs2)
|
|
TEST_ENCODING(FRegister, CFRdp)
|
|
TEST_ENCODING(FRegister, CFRs1p)
|
|
TEST_ENCODING(FRegister, CFRs2p)
|
|
TEST_ENCODING(intptr_t, CSPLoad4Imm)
|
|
TEST_ENCODING(intptr_t, CSPLoad8Imm)
|
|
TEST_ENCODING(intptr_t, CSPStore4Imm)
|
|
TEST_ENCODING(intptr_t, CSPStore8Imm)
|
|
TEST_ENCODING(intptr_t, CMem1Imm)
|
|
TEST_ENCODING(intptr_t, CMem2Imm)
|
|
TEST_ENCODING(intptr_t, CMem4Imm)
|
|
TEST_ENCODING(intptr_t, CMem8Imm)
|
|
TEST_ENCODING(intptr_t, CJImm)
|
|
TEST_ENCODING(intptr_t, CBImm)
|
|
TEST_ENCODING(intptr_t, CIImm)
|
|
TEST_ENCODING(intptr_t, CUImm)
|
|
TEST_ENCODING(intptr_t, CI16Imm)
|
|
TEST_ENCODING(intptr_t, CI4SPNImm)
|
|
TEST_ENCODING(intptr_t, CShamt)
|
|
|
|
#undef TEST_ENCODING
|
|
|
|
static void RangeCheck(Assembler* assembler, Register value, Register temp) {
|
|
const Register return_reg = CallingConventions::kReturnReg;
|
|
Label in_range;
|
|
__ RangeCheck(value, temp, kFirstErrorCid, kLastErrorCid,
|
|
AssemblerBase::kIfInRange, &in_range);
|
|
__ LoadImmediate(return_reg, 0);
|
|
__ Ret();
|
|
__ Bind(&in_range);
|
|
__ LoadImmediate(return_reg, 1);
|
|
__ Ret();
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(RangeCheckNoTemp, assembler) {
|
|
const Register value = CallingConventions::ArgumentRegisters[0];
|
|
const Register temp = kNoRegister;
|
|
RangeCheck(assembler, value, temp);
|
|
}
|
|
|
|
ASSEMBLER_TEST_RUN(RangeCheckNoTemp, test) {
|
|
intptr_t result;
|
|
result = test->Invoke<intptr_t, intptr_t>(kErrorCid);
|
|
EXPECT_EQ(1, result);
|
|
result = test->Invoke<intptr_t, intptr_t>(kUnwindErrorCid);
|
|
EXPECT_EQ(1, result);
|
|
result = test->Invoke<intptr_t, intptr_t>(kFunctionCid);
|
|
EXPECT_EQ(0, result);
|
|
result = test->Invoke<intptr_t, intptr_t>(kMintCid);
|
|
EXPECT_EQ(0, result);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(RangeCheckWithTemp, assembler) {
|
|
const Register value = CallingConventions::ArgumentRegisters[0];
|
|
const Register temp = CallingConventions::ArgumentRegisters[1];
|
|
RangeCheck(assembler, value, temp);
|
|
}
|
|
|
|
ASSEMBLER_TEST_RUN(RangeCheckWithTemp, test) {
|
|
intptr_t result;
|
|
result = test->Invoke<intptr_t, intptr_t>(kErrorCid);
|
|
EXPECT_EQ(1, result);
|
|
result = test->Invoke<intptr_t, intptr_t>(kUnwindErrorCid);
|
|
EXPECT_EQ(1, result);
|
|
result = test->Invoke<intptr_t, intptr_t>(kFunctionCid);
|
|
EXPECT_EQ(0, result);
|
|
result = test->Invoke<intptr_t, intptr_t>(kMintCid);
|
|
EXPECT_EQ(0, result);
|
|
}
|
|
|
|
ASSEMBLER_TEST_GENERATE(RangeCheckWithTempReturnValue, assembler) {
|
|
const Register value = CallingConventions::ArgumentRegisters[0];
|
|
const Register temp = CallingConventions::ArgumentRegisters[1];
|
|
const Register return_reg = CallingConventions::kReturnReg;
|
|
Label in_range;
|
|
__ RangeCheck(value, temp, kFirstErrorCid, kLastErrorCid,
|
|
AssemblerBase::kIfInRange, &in_range);
|
|
__ Bind(&in_range);
|
|
__ MoveRegister(return_reg, value);
|
|
__ Ret();
|
|
}
|
|
|
|
ASSEMBLER_TEST_RUN(RangeCheckWithTempReturnValue, test) {
|
|
intptr_t result;
|
|
result = test->Invoke<intptr_t, intptr_t>(kErrorCid);
|
|
EXPECT_EQ(kErrorCid, result);
|
|
result = test->Invoke<intptr_t, intptr_t>(kUnwindErrorCid);
|
|
EXPECT_EQ(kUnwindErrorCid, result);
|
|
result = test->Invoke<intptr_t, intptr_t>(kFunctionCid);
|
|
EXPECT_EQ(kFunctionCid, result);
|
|
result = test->Invoke<intptr_t, intptr_t>(kMintCid);
|
|
EXPECT_EQ(kMintCid, result);
|
|
}
|
|
|
|
void EnterTestFrame(Assembler* assembler) {
|
|
__ EnterFrame(0);
|
|
__ PushRegister(CODE_REG);
|
|
__ PushRegister(THR);
|
|
__ PushRegister(PP);
|
|
__ MoveRegister(CODE_REG, A0);
|
|
__ MoveRegister(THR, A1);
|
|
__ LoadPoolPointer(PP);
|
|
}
|
|
|
|
void LeaveTestFrame(Assembler* assembler) {
|
|
__ PopRegister(PP);
|
|
__ PopRegister(THR);
|
|
__ PopRegister(CODE_REG);
|
|
|
|
__ LeaveFrame();
|
|
}
|
|
|
|
// Tests that JumpAndLink only clobbers CODE_REG in JIT mode and does not
|
|
// clobber any allocatable registers in AOT mode.
|
|
ASSEMBLER_TEST_GENERATE(JumpAndLinkPreservesRegisters, assembler) {
|
|
const auto& do_nothing_just_return =
|
|
AssemblerTest::Generate("DoNothing", [](auto assembler) { __ Ret(); });
|
|
|
|
EnterTestFrame(assembler);
|
|
__ PushRegister(RA);
|
|
|
|
const RegisterSet clobbered_regs(
|
|
kDartAvailableCpuRegs & ~(static_cast<RegList>(1) << A0),
|
|
/*fpu_register_mask=*/0);
|
|
__ PushRegisters(clobbered_regs);
|
|
|
|
Label done;
|
|
|
|
const auto check_all_allocatable_registers_are_preserved_by_call = [&]() {
|
|
for (auto reg : RegisterRange(kDartAvailableCpuRegs)) {
|
|
__ LoadImmediate(reg, static_cast<int32_t>(reg));
|
|
}
|
|
__ JumpAndLink(do_nothing_just_return);
|
|
for (auto reg : RegisterRange(kDartAvailableCpuRegs)) {
|
|
// We expect CODE_REG to be clobbered in JIT mode.
|
|
if (!FLAG_precompiled_mode && reg == CODE_REG) continue;
|
|
|
|
Label ok;
|
|
__ CompareImmediate(reg, static_cast<int32_t>(reg));
|
|
__ BranchIf(EQ, &ok, Assembler::kNearJump);
|
|
__ LoadImmediate(A0, reg);
|
|
__ j(&done);
|
|
__ Bind(&ok);
|
|
}
|
|
};
|
|
|
|
check_all_allocatable_registers_are_preserved_by_call();
|
|
|
|
FLAG_precompiled_mode = true;
|
|
check_all_allocatable_registers_are_preserved_by_call();
|
|
FLAG_precompiled_mode = false;
|
|
|
|
__ LoadImmediate(A0, 42); // 42 is SUCCESS.
|
|
__ Bind(&done);
|
|
__ PopRegisters(clobbered_regs);
|
|
__ PopRegister(RA);
|
|
LeaveTestFrame(assembler);
|
|
__ Ret();
|
|
}
|
|
|
|
ASSEMBLER_TEST_RUN(JumpAndLinkPreservesRegisters, test) {
|
|
const intptr_t result = test->InvokeWithCodeAndThread<int64_t>();
|
|
EXPECT_EQ(42, result);
|
|
}
|
|
|
|
void CheckIsIdentity(Expect& expect, AssemblerTest* test) {
|
|
for (size_t i = 0; i < ARRAY_SIZE(kRegRegImmInputs); ++i) {
|
|
const intptr_t input = kRegRegImmInputs[i];
|
|
const intptr_t result = test->Invoke<intptr_t, intptr_t>(input);
|
|
expect.Equals(input, result);
|
|
}
|
|
}
|
|
|
|
void CheckMovesInputToReturnOnly(Expect& expect,
|
|
AssemblerTest* test,
|
|
bool is_direct) {
|
|
ZoneTextBuffer buf(Thread::Current()->zone());
|
|
RELEASE_ASSERT(RegRegImmTests::kInputReg == RegRegImmTests::kReturnReg);
|
|
if (!is_direct) {
|
|
// Since the instruction encoding is also printed by RelativeDisasembly(),
|
|
// this test is more brittle than for architectures where it isn't.
|
|
RELEASE_ASSERT(RegRegImmTests::kInputReg == A0);
|
|
RELEASE_ASSERT(RegRegImmTests::kInputReg != TMP);
|
|
buf.AddString(" 86aa mv tmp, a0\n");
|
|
buf.AddString(" 8536 mv a0, tmp\n");
|
|
}
|
|
buf.AddString(" 8082 ret\n");
|
|
expect.StringEquals(buf.buffer(), test->RelativeDisassembly());
|
|
}
|
|
|
|
#define GENERATE_ASSEMBLER_IDENTITY_TEST(inst, rhs) \
|
|
ASSEMBLER_TEST_GENERATE(inst##_##rhs##_Identity_Direct, assembler) { \
|
|
RELEASE_ASSERT(RegRegImmTests::kInputReg == RegRegImmTests::kReturnReg); \
|
|
__ inst(RegRegImmTests::kReturnReg, RegRegImmTests::kInputReg, rhs, \
|
|
kWordBytes); \
|
|
__ Ret(); \
|
|
} \
|
|
ASSEMBLER_TEST_RUN(inst##_##rhs##_Identity_Direct, test) { \
|
|
Expect expect(__FILE__, __LINE__); \
|
|
CheckIsIdentity(expect, test); \
|
|
CheckMovesInputToReturnOnly(expect, test, /*is_direct=*/true); \
|
|
} \
|
|
ASSEMBLER_TEST_GENERATE(inst##_##rhs##_Identity_Indirect, assembler) { \
|
|
RELEASE_ASSERT(RegRegImmTests::kInputReg == RegRegImmTests::kReturnReg); \
|
|
RELEASE_ASSERT(RegRegImmTests::kInputReg != TMP); \
|
|
__ inst(TMP, RegRegImmTests::kInputReg, rhs, kWordBytes); \
|
|
__ MoveRegister(RegRegImmTests::kReturnReg, TMP); \
|
|
__ Ret(); \
|
|
} \
|
|
ASSEMBLER_TEST_RUN(inst##_##rhs##_Identity_Indirect, test) { \
|
|
Expect expect(__FILE__, __LINE__); \
|
|
CheckIsIdentity(expect, test); \
|
|
CheckMovesInputToReturnOnly(expect, test, /*is_direct=*/false); \
|
|
}
|
|
|
|
#if XLEN == 32
|
|
GENERATE_ASSEMBLER_IDENTITY_TEST(AndImmediate, kMaxUint32)
|
|
#else
|
|
GENERATE_ASSEMBLER_IDENTITY_TEST(AndImmediate, kMaxUint64)
|
|
#endif
|
|
GENERATE_ASSEMBLER_IDENTITY_TEST(LslImmediate, 0)
|
|
GENERATE_ASSEMBLER_IDENTITY_TEST(ArithmeticShiftRightImmediate, 0)
|
|
|
|
#undef GENERATE_ASSEMBLER_IDENTITY_TEST
|
|
|
|
intptr_t RegRegImmTests::Lsl(intptr_t value, intptr_t shift, OperandSize sz) {
|
|
return ExtendValue(static_cast<uintptr_t>(value) << shift, sz);
|
|
}
|
|
|
|
intptr_t RegRegImmTests::Asr(intptr_t value, intptr_t shift, OperandSize sz) {
|
|
return ExtendValue(SignExtendValue(value, sz) >> shift, sz);
|
|
}
|
|
|
|
} // namespace compiler
|
|
} // namespace dart
|
|
|
|
#endif // defined(TARGET_ARCH_RISCV)
|