From 33683bd087c2009db588844e8fa89b454a5c3d77 Mon Sep 17 00:00:00 2001 From: Alec Roelke Date: Wed, 30 Nov 2016 17:12:56 -0500 Subject: [PATCH] riscv: [Patch 8/5] Added some regression tests to RISC-V This patch is the eighth patch in a series adding RISC-V to gem5, and third of the bonus patches to the original series of five. It adds some regression tests to RISC-V. Regression tests included: - se/00.hello - se/02.insttest (split into several binaries which are not included due to large size) The tests added to 00.insttest will need to be build manually; to facilitate this, a Makefile is included. The required toolchain and compiler (riscv64-unknown-elf-gcc) can be built from the riscv-tools GitHub repository at https://github.com/riscv/riscv-tools. Note that because EBREAK only makes sense when gdb is running or while in FS mode, it is not included in the linux-rv64i insttest. ERET is not included because it does not make sense in SE mode and, in fact, causes a panic by design. Note also that not every system call is tested in linux-rv64i; of the ones defined in linux/process.hh, some have been given numbers but not definitions for the toolchain, or are merely stubs that always return 0. Of the ones that do work properly, only a subset are tested due to similar functionality. Signed-off by: Alec Roelke Signed-off by: Jason Lowe-Power --- tests/test-progs/hello/bin/riscv/linux/hello | Bin 0 -> 180264 bytes tests/test-progs/insttest/src/riscv/Makefile | 51 ++ .../test-progs/insttest/src/riscv/insttest.h | 79 ++ tests/test-progs/insttest/src/riscv/rv64a.cpp | 192 +++++ tests/test-progs/insttest/src/riscv/rv64a.h | 299 ++++++++ tests/test-progs/insttest/src/riscv/rv64d.cpp | 708 ++++++++++++++++++ tests/test-progs/insttest/src/riscv/rv64d.h | 323 ++++++++ tests/test-progs/insttest/src/riscv/rv64f.cpp | 694 +++++++++++++++++ tests/test-progs/insttest/src/riscv/rv64f.h | 357 +++++++++ tests/test-progs/insttest/src/riscv/rv64i.cpp | 432 +++++++++++ tests/test-progs/insttest/src/riscv/rv64i.h | 440 +++++++++++ tests/test-progs/insttest/src/riscv/rv64m.cpp | 143 ++++ tests/test-progs/insttest/src/riscv/rv64m.h | 144 ++++ util/regress | 1 + 14 files changed, 3863 insertions(+) create mode 100755 tests/test-progs/hello/bin/riscv/linux/hello create mode 100644 tests/test-progs/insttest/src/riscv/Makefile create mode 100644 tests/test-progs/insttest/src/riscv/insttest.h create mode 100644 tests/test-progs/insttest/src/riscv/rv64a.cpp create mode 100644 tests/test-progs/insttest/src/riscv/rv64a.h create mode 100644 tests/test-progs/insttest/src/riscv/rv64d.cpp create mode 100644 tests/test-progs/insttest/src/riscv/rv64d.h create mode 100644 tests/test-progs/insttest/src/riscv/rv64f.cpp create mode 100644 tests/test-progs/insttest/src/riscv/rv64f.h create mode 100644 tests/test-progs/insttest/src/riscv/rv64i.cpp create mode 100644 tests/test-progs/insttest/src/riscv/rv64i.h create mode 100644 tests/test-progs/insttest/src/riscv/rv64m.cpp create mode 100644 tests/test-progs/insttest/src/riscv/rv64m.h diff --git a/tests/test-progs/hello/bin/riscv/linux/hello b/tests/test-progs/hello/bin/riscv/linux/hello new file mode 100755 index 0000000000000000000000000000000000000000..7f1ca493bce32215b16b9187f98eb795c1e8bfa6 GIT binary patch literal 180264 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 literal 0 HcmV?d00001 diff --git a/tests/test-progs/insttest/src/riscv/Makefile b/tests/test-progs/insttest/src/riscv/Makefile new file mode 100644 index 000000000..5aa8a7a3b --- /dev/null +++ b/tests/test-progs/insttest/src/riscv/Makefile @@ -0,0 +1,51 @@ +# Copyright (c) 2016 The University of Virginia +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Alec Roelke + +CXX=riscv64-unknown-elf-g++ +CFLAGS=--std=c++11 -O3 -static + +TARGETS=rv64i rv64m rv64a rv64f rv64d +PREFIX=../../bin/riscv/linux +BIN=insttest + +all: $(TARGETS) + +$(TARGETS): + -mkdir -p $(PREFIX)-$@ + $(CXX) $< $(CFLAGS) -o $(PREFIX)-$@/$(BIN) + +rv64i: rv64i.cpp +rv64m: rv64m.cpp +rv64a: rv64a.cpp +rv64f: rv64f.cpp +rv64d: rv64d.cpp + +clean: + -rm $(PREFIX)-*/$(BIN) + +.PHONY: all clean diff --git a/tests/test-progs/insttest/src/riscv/insttest.h b/tests/test-progs/insttest/src/riscv/insttest.h new file mode 100644 index 000000000..59b69869c --- /dev/null +++ b/tests/test-progs/insttest/src/riscv/insttest.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016 The University of Virginia + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Alec Roelke + */ + +#pragma once + +#include +#include +#include +#include +#include + +#define IOP(inst, rd, rs1, imm) \ + asm volatile(inst " %0,%1,%2" : "=r" (rd) : "r" (rs1), "i" (imm)) + +#define ROP(inst, rd, rs1, rs2) \ + asm volatile(inst " %0,%1,%2" : "=r" (rd) : "r" (rs1), "r" (rs2)) + +#define FROP(inst, fd, fs1, fs2) \ + asm volatile(inst " %0,%1,%2" : "=f" (fd) : "f" (fs1), "f" (fs2)) + +#define FR4OP(inst, fd, fs1, fs2, fs3) \ + asm volatile(inst " %0,%1,%2,%3" \ + : "=f" (fd) \ + : "f" (fs1), "f" (fs2), "f" (fs3)) + +template std::ostream& +operator<<(std::ostream& os, const std::pair& p) +{ + return os << '(' << p.first << ", " << p.second << ')'; +} + +namespace insttest +{ + +template void +expect(const T& expected, std::function func, + const std::string& test) +{ + using namespace std; + + T result = func(); + cout << test << ": "; + if (result == expected) { + cout << "PASS" << endl; + } else { + cout << "\033[1;31mFAIL\033[0m (expected " << expected << "; found " << + result << ")" << endl; + exit(1); + } +} + +} // namespace insttest diff --git a/tests/test-progs/insttest/src/riscv/rv64a.cpp b/tests/test-progs/insttest/src/riscv/rv64a.cpp new file mode 100644 index 000000000..55150fbc3 --- /dev/null +++ b/tests/test-progs/insttest/src/riscv/rv64a.cpp @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2016 The University of Virginia + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Alec Roelke + */ + +#include +#include + +#include "insttest.h" +#include "rv64a.h" + +int main() +{ + using namespace std; + using namespace insttest; + + // Memory (LR.W, SC.W) + expect>({-1, 0}, []{ + int32_t mem = -1; + int64_t rs2 = 256; + int64_t rd = A::lr_w(mem); + pair result = A::sc_w(rs2, mem); + return pair(rd, result.second); + }, "lr.w/sc.w"); + expect>({true, 200}, []{ + int32_t mem = 200; + pair result = A::sc_w(50, mem); + return pair(result.second == 1, mem); + }, "sc.w, no preceding lr.d"); + + // AMOSWAP.W + expect>({65535, 255}, + []{return A::amoswap_w(255, 65535);}, "amoswap.w"); + expect>({0xFFFFFFFF, -1}, + []{return A::amoswap_w(0xFFFFFFFF, 0xFFFFFFFF);}, + "amoswap.w, sign extend"); + expect>({0x0000000180000000LL, -1}, + []{return A::amoswap_w(0x00000001FFFFFFFFLL, + 0x7FFFFFFF80000000LL);}, + "amoswap.w, truncate"); + + // AMOADD.W + expect>({256, 255}, + []{return A::amoadd_w(255, 1);}, "amoadd.w"); + expect>({0, -1}, + []{return A::amoadd_w(0xFFFFFFFF, 1);}, + "amoadd.w, truncate/overflow"); + expect>({0xFFFFFFFF, 0x7FFFFFFF}, + []{return A::amoadd_w(0x7FFFFFFF, 0x80000000);}, + "amoadd.w, sign extend"); + + // AMOXOR.W + expect>({0xFFFFFFFFAAAAAAAALL, -1}, + []{return A::amoxor_w(-1, 0x5555555555555555LL);}, + "amoxor.w, truncate"); + expect>({0x80000000, -1}, + []{return A::amoxor_w(0xFFFFFFFF, 0x7FFFFFFF);}, + "amoxor.w, sign extend"); + + // AMOAND.W + expect>({0xFFFFFFFF00000000LL, -1}, + []{return A::amoand_w(-1, 0);}, "amoand.w, truncate"); + expect>({0x0000000080000000LL, -1}, + []{return A::amoand_w(0xFFFFFFFF,numeric_limits::min());}, + "amoand.w, sign extend"); + + // AMOOR.W + expect>({0x00000000FFFFFFFFLL, 0}, + []{return A::amoor_w(0, -1);}, "amoor.w, truncate"); + expect>({0x0000000080000000LL, 0}, + []{return A::amoor_w(0, numeric_limits::min());}, + "amoor.w, sign extend"); + + // AMOMIN.W + expect>({0x7FFFFFFF00000001LL, 1}, + []{return A::amomin_w(0x7FFFFFFF00000001LL, 0xFFFFFFFF000000FF);}, + "amomin.w, truncate"); + expect>({0x00000000FFFFFFFELL, -1}, + []{return A::amomin_w(0xFFFFFFFF, -2);}, "amomin.w, sign extend"); + + // AMOMAX.W + expect>({0x70000000000000FFLL, 1}, + []{return A::amomax_w(0x7000000000000001LL,0x7FFFFFFF000000FFLL);}, + "amomax.w, truncate"); + expect>({-1, numeric_limits::min()}, + []{return A::amomax_w(numeric_limits::min(), -1);}, + "amomax.w, sign extend"); + + // AMOMINU.W + expect>({0x0FFFFFFF000000FFLL, -1}, + []{return A::amominu_w(0x0FFFFFFFFFFFFFFFLL, 0xFFFFFFFF000000FF);}, + "amominu.w, truncate"); + expect>({0x0000000080000000LL, -1}, + []{return A::amominu_w(0x00000000FFFFFFFFLL, 0x80000000);}, + "amominu.w, sign extend"); + + // AMOMAXU.W + expect>({-1, 0}, + []{return A::amomaxu_w(0xFFFFFFFF00000000LL, + 0x00000000FFFFFFFFLL);}, + "amomaxu.w, truncate"); + expect>( + {0xFFFFFFFF, numeric_limits::min()}, + []{return A::amomaxu_w(0x80000000, 0xFFFFFFFF);}, + "amomaxu.w, sign extend"); + + // Memory (LR.D, SC.D) + expect>({-1, 0}, []{ + int64_t mem = -1; + int64_t rs2 = 256; + int64_t rd = A::lr_d(mem); + pair result = A::sc_d(rs2, mem); + return pair(rd, result.second); + }, "lr.d/sc.d"); + expect>({true, 200}, []{ + int64_t mem = 200; + pair result = A::sc_d(50, mem); + return pair(result.second == 1, mem); + }, "sc.d, no preceding lr.d"); + + // AMOSWAP.D + expect>({1, -1}, []{return A::amoswap_d(-1, 1);}, + "amoswap.d"); + + // AMOADD.D + expect>({0x7000000000000000LL,0x0FFFFFFFFFFFFFFFLL}, + []{return A::amoadd_d(0x0FFFFFFFFFFFFFFFLL,0x6000000000000001LL);}, + "amoadd.d"); + expect>({0, 0x7FFFFFFFFFFFFFFFLL}, + []{return A::amoadd_d(0x7FFFFFFFFFFFFFFFLL,0x8000000000000001LL);}, + "amoadd.d, overflow"); + + // AMOXOR.D + expect>({-1, 0xAAAAAAAAAAAAAAAALL}, + []{return A::amoxor_d(0xAAAAAAAAAAAAAAAALL,0x5555555555555555LL);}, + "amoxor.d (1)"); + expect>({0, 0xAAAAAAAAAAAAAAAALL}, + []{return A::amoxor_d(0xAAAAAAAAAAAAAAAALL,0xAAAAAAAAAAAAAAAALL);}, + "amoxor.d (0)"); + + // AMOAND.D + expect>({0xAAAAAAAAAAAAAAAALL, -1}, + []{return A::amoand_d(-1, 0xAAAAAAAAAAAAAAAALL);}, "amoand.d"); + + // AMOOR.D + expect>({-1, 0xAAAAAAAAAAAAAAAALL}, + []{return A::amoor_d(0xAAAAAAAAAAAAAAAALL, 0x5555555555555555LL);}, + "amoor.d"); + + // AMOMIN.D + expect>({-1, -1}, + []{return A::amomin_d(-1, 0);}, "amomin.d"); + + // AMOMAX.D + expect>({0, -1}, []{return A::amomax_d(-1, 0);}, + "amomax.d"); + + // AMOMINU.D + expect>({0, -1}, + []{return A::amominu_d(-1, 0);}, "amominu.d"); + + // AMOMAXU.D + expect>({-1, -1}, []{return A::amomaxu_d(-1, 0);}, + "amomaxu.d"); + + return 0; +} diff --git a/tests/test-progs/insttest/src/riscv/rv64a.h b/tests/test-progs/insttest/src/riscv/rv64a.h new file mode 100644 index 000000000..cfd1fd846 --- /dev/null +++ b/tests/test-progs/insttest/src/riscv/rv64a.h @@ -0,0 +1,299 @@ +/* + * Copyright (c) 2016 The University of Virginia + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Alec Roelke + */ + +#pragma once + +#include +#include + +#include "insttest.h" + +namespace A +{ + +inline int64_t +lr_w(int32_t& mem) +{ + int64_t r = 0; + uint64_t addr = (uint64_t)&mem; + asm volatile("lr.w %0,(%1)" : "=r" (r) : "r" (addr) : "memory"); + return r; +} + +inline std::pair +sc_w(int64_t rs2, int32_t& mem) +{ + uint64_t addr = (uint64_t)&mem; + uint64_t rd = -1; + asm volatile("sc.w %0,%2,(%1)" + : "=r" (rd) + : "r" (addr), "r" (rs2) + : "memory"); + return {mem, rd}; +} + +inline std::pair +amoswap_w(int64_t mem, int64_t rs2) +{ + int64_t rd = 0; + uint64_t addr = (uint64_t)&mem; + asm volatile("amoswap.w %0,%2,(%1)" + : "=r" (rd) + : "r" (addr), "r" (rs2) + : "memory"); + return {mem, rd}; +} + +inline std::pair +amoadd_w(int64_t mem, int64_t rs2) +{ + int64_t rd = 0; + uint64_t addr = (uint64_t)&mem; + asm volatile("amoadd.w %0,%2,(%1)" + : "=r" (rd) + : "r" (addr), "r" (rs2) + : "memory"); + return {mem, rd}; +} + +inline std::pair +amoxor_w(uint64_t mem, uint64_t rs2) +{ + uint64_t rd = 0; + uint64_t addr = (uint64_t)&mem; + asm volatile("amoxor.w %0,%2,(%1)" + : "=r" (rd) + : "r" (addr), "r" (rs2) + : "memory"); + return {mem, rd}; +} + +inline std::pair +amoand_w(uint64_t mem, uint64_t rs2) +{ + uint64_t rd = 0; + uint64_t addr = (uint64_t)&mem; + asm volatile("amoand.w %0,%2,(%1)" + : "=r" (rd) + : "r" (addr), "r" (rs2) + : "memory"); + return {mem, rd}; +} + +inline std::pair +amoor_w(uint64_t mem, uint64_t rs2) +{ + uint64_t rd = 0; + uint64_t addr = (uint64_t)&mem; + asm volatile("amoor.w %0,%2,(%1)" + : "=r" (rd) + : "r" (addr), "r" (rs2) + : "memory"); + return {mem, rd}; +} + +inline std::pair +amomin_w(int64_t mem, int64_t rs2) +{ + int64_t rd = 0; + uint64_t addr = (uint64_t)&mem; + asm volatile("amomin.w %0,%2,(%1)" + : "=r" (rd) + : "r" (addr), "r" (rs2) + : "memory"); + return {mem, rd}; +} + +inline std::pair +amomax_w(int64_t mem, int64_t rs2) +{ + int64_t rd = 0; + uint64_t addr = (uint64_t)&mem; + asm volatile("amomax.w %0,%2,(%1)" + : "=r" (rd) + : "r" (addr), "r" (rs2) + : "memory"); + return {mem, rd}; +} + +inline std::pair +amominu_w(uint64_t mem, uint64_t rs2) +{ + uint64_t rd = 0; + uint64_t addr = (uint64_t)&mem; + asm volatile("amominu.w %0,%2,(%1)" + : "=r" (rd) + : "r" (addr), "r" (rs2) + : "memory"); + return {mem, rd}; +} + +inline std::pair +amomaxu_w(uint64_t mem, uint64_t rs2) +{ + uint64_t rd = 0; + uint64_t addr = (uint64_t)&mem; + asm volatile("amomaxu.w %0,%2,(%1)" + : "=r" (rd) + : "r" (addr), "r" (rs2) + : "memory"); + return {mem, rd}; +} + +inline int64_t +lr_d(int64_t& mem) +{ + int64_t r = 0; + uint64_t addr = (uint64_t)&mem; + asm volatile("lr.d %0,(%1)" : "=r" (r) : "r" (addr) : "memory"); + return r; +} + +inline std::pair +sc_d(int64_t rs2, int64_t& mem) +{ + uint64_t addr = (uint64_t)&mem; + uint64_t rd = -1; + asm volatile("sc.d %0,%2,(%1)" + : "=r" (rd) + : "r" (addr), "r" (rs2) + : "memory"); + return {mem, rd}; +} + +inline std::pair +amoswap_d(int64_t mem, int64_t rs2) +{ + int64_t rd = 0; + uint64_t addr = (uint64_t)&mem; + asm volatile("amoswap.d %0,%2,(%1)" + : "=r" (rd) + : "r" (addr), "r" (rs2) + : "memory"); + return {mem, rd}; +} + +inline std::pair +amoadd_d(int64_t mem, int64_t rs2) +{ + int64_t rd = 0; + uint64_t addr = (uint64_t)&mem; + asm volatile("amoadd.d %0,%2,(%1)" + : "=r" (rd) + : "r" (addr), "r" (rs2) + : "memory"); + return {mem, rd}; +} + +inline std::pair +amoxor_d(uint64_t mem, uint64_t rs2) +{ + uint64_t rd = 0; + uint64_t addr = (uint64_t)&mem; + asm volatile("amoxor.d %0,%2,(%1)" + : "=r" (rd) + : "r" (addr), "r" (rs2) + : "memory"); + return {mem, rd}; +} + +inline std::pair +amoand_d(uint64_t mem, uint64_t rs2) +{ + uint64_t rd = 0; + uint64_t addr = (uint64_t)&mem; + asm volatile("amoand.d %0,%2,(%1)" + : "=r" (rd) + : "r" (addr), "r" (rs2) + : "memory"); + return {mem, rd}; +} + +inline std::pair +amoor_d(uint64_t mem, uint64_t rs2) +{ + uint64_t rd = 0; + uint64_t addr = (uint64_t)&mem; + asm volatile("amoor.d %0,%2,(%1)" + : "=r" (rd) + : "r" (addr), "r" (rs2) + : "memory"); + return {mem, rd}; +} + +inline std::pair +amomin_d(int64_t mem, int64_t rs2) +{ + int64_t rd = 0; + uint64_t addr = (uint64_t)&mem; + asm volatile("amomin.d %0,%2,(%1)" + : "=r" (rd) + : "r" (addr), "r" (rs2) + : "memory"); + return {mem, rd}; +} + +inline std::pair +amomax_d(int64_t mem, int64_t rs2) +{ + int64_t rd = 0; + uint64_t addr = (uint64_t)&mem; + asm volatile("amomax.d %0,%2,(%1)" + : "=r" (rd) + : "r" (addr), "r" (rs2) + : "memory"); + return {mem, rd}; +} + +inline std::pair +amominu_d(uint64_t mem, uint64_t rs2) +{ + uint64_t rd = 0; + uint64_t addr = (uint64_t)&mem; + asm volatile("amominu.d %0,%2,(%1)" + : "=r" (rd) + : "r" (addr), "r" (rs2) + : "memory"); + return {mem, rd}; +} + +inline std::pair +amomaxu_d(uint64_t mem, uint64_t rs2) +{ + uint64_t rd = 0; + uint64_t addr = (uint64_t)&mem; + asm volatile("amomaxu.d %0,%2,(%1)" + : "=r" (rd) + : "r" (addr), "r" (rs2) + : "memory"); + return {mem, rd}; +} + +} // namespace A diff --git a/tests/test-progs/insttest/src/riscv/rv64d.cpp b/tests/test-progs/insttest/src/riscv/rv64d.cpp new file mode 100644 index 000000000..adb62d2f5 --- /dev/null +++ b/tests/test-progs/insttest/src/riscv/rv64d.cpp @@ -0,0 +1,708 @@ +/* + * Copyright (c) 2016 The University of Virginia + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Alec Roelke + */ + +#include +#include + +#include "insttest.h" +#include "rv64d.h" +#include "rv64f.h" + +int main() +{ + using namespace std; + using namespace insttest; + + // Memory (FLD, FSD) + expect(3.1415926, []{return D::load(3.1415926);}, "fld"); + expect(1.61803398875, []{return D::store(1.61803398875);}, "fsd"); + + // FMADD.D + expect(D::number(0x4019FD5AED13B1CEULL), + []{return D::fmadd_d(3.1415926, 1.61803398875,1.41421356237);}, + "fmadd.d"); + expect(true, []{ + double fd = D::fmadd_d(numeric_limits::quiet_NaN(), 3.14, + 1.816); + return D::isquietnan(fd); + }, "fmadd.d, quiet NaN"); + expect(true, []{ + double fd = D::fmadd_d(3.14, + numeric_limits::signaling_NaN(), 1.816); + return D::isquietnan(fd); + }, "fmadd.d, signaling NaN"); + expect(numeric_limits::infinity(), + []{return D::fmadd_d(3.14, numeric_limits::infinity(),1.414);}, + "fmadd.d, infinity"); + expect(-numeric_limits::infinity(), + []{return D::fmadd_d(3.14,-numeric_limits::infinity(),1.414);}, + "fmadd.d, -infinity"); + + // FMSUB.D + expect(D::number(0x400d5A1773A85E43ULL), + []{return D::fmsub_d(3.1415926, 1.61803398875, 1.41421356237);}, + "fmsub.d"); + expect(true, []{ + double fd = D::fmsub_d(3.14, numeric_limits::quiet_NaN(), + 1.414); + return D::isquietnan(fd); + }, "fmsub.d, quiet NaN"); + expect(true, []{ + double fd = D::fmsub_d(3.14, 1.816, + numeric_limits::signaling_NaN()); + return D::isquietnan(fd); + }, "fmsub.d, signaling NaN"); + expect(numeric_limits::infinity(), + []{return D::fmsub_d(numeric_limits::infinity(), 1.816, + 1.414);}, + "fmsub.d, infinity"); + expect(-numeric_limits::infinity(), + []{return D::fmsub_d(3.14, -numeric_limits::infinity(), + 1.414);}, + "fmsub.d, -infinity"); + expect(-numeric_limits::infinity(), + []{return D::fmsub_d(3.14, 1.816, + numeric_limits::infinity());}, + "fmsub.d, subtract infinity"); + + // FNMSUB.D + expect(D::number(0xC00D5A1773A85E43ULL), + []{return D::fnmsub_d(3.1415926, 1.61803398875, 1.41421356237);}, + "fnmsub.d"); + expect(true, []{ + double fd = D::fnmsub_d(3.14, 1.816, + numeric_limits::quiet_NaN()); + return D::isquietnan(fd); + }, "fnmsub.d, quiet NaN"); + expect(true, []{ + double fd = D::fnmsub_d(numeric_limits::signaling_NaN(), + 1.816, 1.414); + return D::isquietnan(fd); + }, "fnmsub.d, signaling NaN"); + expect(-numeric_limits::infinity(), + []{return D::fnmsub_d(numeric_limits::infinity(), 1.816, + 1.414);}, + "fnmsub.d, infinity"); + expect(numeric_limits::infinity(), + []{return D::fnmsub_d(3.14, -numeric_limits::infinity(), + 1.414);}, + "fnmsub.d, -infinity"); + expect(numeric_limits::infinity(), + []{return D::fnmsub_d(3.14, 1.816, + numeric_limits::infinity());}, + "fnmsub.d, subtract infinity"); + + // FNMADD.D + expect(D::number(0xC019FD5AED13B1CEULL), + []{return D::fnmadd_d(3.1415926, 1.61803398875, 1.41421356237);}, + "fnmadd.d"); + expect(true, []{ + double fd = D::fnmadd_d(numeric_limits::quiet_NaN(), 3.14, + 1.816); + return D::isquietnan(fd); + }, "fnmadd.d, quiet NaN"); + expect(true, []{ + double fd = D::fnmadd_d(3.14, + numeric_limits::signaling_NaN(), 1.816); + return D::isquietnan(fd); + }, "fnmadd.d, signaling NaN"); + expect(-numeric_limits::infinity(), + []{return D::fnmadd_d(3.14, numeric_limits::infinity(), + 1.414);}, + "fnmadd.d, infinity"); + expect(numeric_limits::infinity(), + []{return D::fnmadd_d(3.14, -numeric_limits::infinity(), + 1.414);}, + "fnmadd.d, -infinity"); + + // FADD.D + expect(D::number(0x4012392540292D7CULL), + []{return D::fadd_d(3.1415926, 1.41421356237);}, "fadd.d"); + expect(true, []{ + double fd = D::fadd_d(numeric_limits::quiet_NaN(), 1.414); + return D::isquietnan(fd); + }, "fadd.d, quiet NaN"); + expect(true, []{ + double fd = D::fadd_d(3.14, + numeric_limits::signaling_NaN()); + return D::isquietnan(fd); + }, "fadd.d, signaling NaN"); + expect(numeric_limits::infinity(), + []{return D::fadd_d(3.14, numeric_limits::infinity());}, + "fadd.d, infinity"); + expect(-numeric_limits::infinity(), + []{return D::fadd_d(-numeric_limits::infinity(), 1.816);}, + "fadd.d, -infinity"); + + // FSUB.D + expect(D::number(0xBFFBA35833AB7AAEULL), + []{return D::fsub_d(1.4142135623, 3.1415926);}, "fsub.d"); + expect(true, []{ + double fd = D::fsub_d(numeric_limits::quiet_NaN(), 1.414); + return D::isquietnan(fd); + }, "fsub.d, quiet NaN"); + expect(true, []{ + double fd = D::fsub_d(3.14, + numeric_limits::signaling_NaN()); + return D::isquietnan(fd); + }, "fsub.d, signaling NaN"); + expect(numeric_limits::infinity(), + []{return D::fsub_d(numeric_limits::infinity(), 3.14);}, + "fsub.d, infinity"); + expect(-numeric_limits::infinity(), + []{return D::fsub_d(-numeric_limits::infinity(), 3.14);}, + "fsub.d, -infinity"); + expect(-numeric_limits::infinity(), + []{return D::fsub_d(1.414, numeric_limits::infinity());}, + "fsub.d, subtract infinity"); + + // FMUL.D + expect(D::number(0x40024E53B708ED9AULL), + []{return D::fmul_d(1.61803398875, 1.4142135623);}, "fmul.d"); + expect(true, []{ + double fd = D::fmul_d(numeric_limits::quiet_NaN(), 1.414); + return D::isquietnan(fd); + }, "fmul.d, quiet NaN"); + expect(true, []{ + double fd = D::fmul_d(1.816, + numeric_limits::signaling_NaN()); + return D::isquietnan(fd); + }, "fmul.d, signaling NaN"); + expect(numeric_limits::infinity(), + []{return D::fmul_d(numeric_limits::infinity(), 2.718);}, + "fmul.d, infinity"); + expect(-numeric_limits::infinity(), + []{return D::fmul_d(2.5966, -numeric_limits::infinity());}, + "fmul.d, -infinity"); + expect(true, []{ + double fd = D::fmul_d(0.0, numeric_limits::infinity()); + return D::isquietnan(fd); + }, "fmul.d, 0*infinity"); + expect(numeric_limits::infinity(), + []{return D::fmul_d(numeric_limits::max(), 2.0);}, + "fmul.d, overflow"); + expect(0.0, + []{return D::fmul_d(numeric_limits::min(), + numeric_limits::min());}, + "fmul.d, underflow"); + + // FDIV.D + expect(2.5, []{return D::fdiv_d(10.0, 4.0);}, "fdiv.d"); + expect(true, []{ + double fd = D::fdiv_d(numeric_limits::quiet_NaN(), 4.0); + return D::isquietnan(fd); + }, "fdiv.d, quiet NaN"); + expect(true, []{ + double fd = D::fdiv_d(10.0, + numeric_limits::signaling_NaN()); + return D::isquietnan(fd); + }, "fdiv.d, signaling NaN"); + expect(numeric_limits::infinity(), + []{return D::fdiv_d(10.0, 0.0);}, "fdiv.d/0"); + expect(0.0, + []{return D::fdiv_d(10.0, numeric_limits::infinity());}, + "fdiv.d/infinity"); + expect(true, []{ + double fd = D::fdiv_d(numeric_limits::infinity(), + numeric_limits::infinity()); + return D::isquietnan(fd); + }, "fdiv.d, infinity/infinity"); + expect(true, []{ + double fd = D::fdiv_d(0.0, 0.0); + return D::isquietnan(fd); + }, "fdiv.d, 0/0"); + expect(numeric_limits::infinity(), + []{return D::fdiv_d(numeric_limits::infinity(), 0.0);}, + "fdiv.d, infinity/0"); + expect(0.0, + []{return D::fdiv_d(0.0, numeric_limits::infinity());}, + "fdiv.d, 0/infinity"); + expect(0.0, + []{return D::fdiv_d(numeric_limits::min(), + numeric_limits::max());}, + "fdiv.d, underflow"); + expect(numeric_limits::infinity(), + []{return D::fdiv_d(numeric_limits::max(), + numeric_limits::min());}, + "fdiv.d, overflow"); + + // FSQRT.D + expect(1e154, []{return D::fsqrt_d(1e308);}, "fsqrt.d"); + expect(true, []{ + double fd = D::fsqrt_d(-1.0); + return D::isquietnan(fd); + }, "fsqrt.d, NaN"); + expect(true, []{ + double fd = D::fsqrt_d(numeric_limits::quiet_NaN()); + return D::isquietnan(fd); + }, "fsqrt.d, quiet NaN"); + expect(true, []{ + double fd = D::fsqrt_d(numeric_limits::signaling_NaN()); + return D::isquietnan(fd); + }, "fsqrt.d, signaling NaN"); + expect(numeric_limits::infinity(), + []{return D::fsqrt_d(numeric_limits::infinity());}, + "fsqrt.d, infinity"); + + // FSGNJ.D + expect(1.0, []{return D::fsgnj_d(1.0, 25.0);}, "fsgnj.d, ++"); + expect(-1.0, []{return D::fsgnj_d(1.0, -25.0);}, "fsgnj.d, +-"); + expect(1.0, []{return D::fsgnj_d(-1.0, 25.0);}, "fsgnj.d, -+"); + expect(-1.0, []{return D::fsgnj_d(-1.0, -25.0);}, "fsgnj.d, --"); + expect(true, []{ + double fd = D::fsgnj_d(numeric_limits::quiet_NaN(), -4.0); + return D::isquietnan(fd); + }, "fsgnj.d, quiet NaN"); + expect(true, []{ + double fd = D::fsgnj_d(numeric_limits::signaling_NaN(), + -4.0); + return D::issignalingnan(fd); + }, "fsgnj.d, signaling NaN"); + expect(4.0, + []{return D::fsgnj_d(4.0, numeric_limits::quiet_NaN());}, + "fsgnj.d, inject NaN"); + expect(-4.0, + []{return D::fsgnj_d(4.0, -numeric_limits::quiet_NaN());}, + "fsgnj.d, inject -NaN"); + + // FSGNJN.D + expect(-1.0, []{return D::fsgnjn_d(1.0, 25.0);}, "fsgnjn.d, ++"); + expect(1.0, []{return D::fsgnjn_d(1.0, -25.0);}, "fsgnjn.d, +-"); + expect(-1.0, []{return D::fsgnjn_d(-1.0, 25.0);}, "fsgnjn.d, -+"); + expect(1.0, []{return D::fsgnjn_d(-1.0, -25.0);}, "fsgnjn.d, --"); + expect(true, []{ + double fd = D::fsgnjn_d(numeric_limits::quiet_NaN(), -4.0); + return D::isquietnan(fd); + }, "fsgnjn.d, quiet NaN"); + expect(true, []{ + double fd = D::fsgnjn_d(numeric_limits::signaling_NaN(), + -4.0); + return D::issignalingnan(fd); + }, "fsgnjn.d, signaling NaN"); + expect(-4.0, + []{return D::fsgnjn_d(4.0, numeric_limits::quiet_NaN());}, + "fsgnjn.d, inject NaN"); + expect(4.0, + []{return D::fsgnjn_d(4.0, -numeric_limits::quiet_NaN());}, + "fsgnjn.d, inject NaN"); + + // FSGNJX.D + expect(1.0, []{return D::fsgnjx_d(1.0, 25.0);}, "fsgnjx.d, ++"); + expect(-1.0, []{return D::fsgnjx_d(1.0, -25.0);}, "fsgnjx.d, +-"); + expect(-1.0, []{return D::fsgnjx_d(-1.0, 25.0);}, "fsgnjx.d, -+"); + expect(1.0, []{return D::fsgnjx_d(-1.0, -25.0);}, "fsgnjx.d, --"); + expect(true, []{ + double fd = D::fsgnjx_d(numeric_limits::quiet_NaN(), -4.0); + return D::isquietnan(fd); + }, "fsgnjx.d, quiet NaN"); + expect(true, []{ + double fd = D::fsgnjx_d(numeric_limits::signaling_NaN(), + -4.0); + return D::issignalingnan(fd); + }, "fsgnjx.d, signaling NaN"); + expect(4.0, + []{return D::fsgnjx_d(4.0, numeric_limits::quiet_NaN());}, + "fsgnjx.d, inject NaN"); + expect(-4.0, + []{return D::fsgnjx_d(4.0, -numeric_limits::quiet_NaN());}, + "fsgnjx.d, inject NaN"); + + // FMIN.D + expect(2.718, []{return D::fmin_d(3.14, 2.718);}, "fmin.d"); + expect(-numeric_limits::infinity(), + []{return D::fmin_d(-numeric_limits::infinity(), + numeric_limits::min());}, + "fmin.d, -infinity"); + expect(numeric_limits::max(), + []{return D::fmin_d(numeric_limits::infinity(), + numeric_limits::max());}, + "fmin.d, infinity"); + expect(-1.414, + []{return D::fmin_d(numeric_limits::quiet_NaN(), -1.414);}, + "fmin.d, quiet NaN first"); + expect(2.718, + []{return D::fmin_d(2.718, numeric_limits::quiet_NaN());}, + "fmin.d, quiet NaN second"); + expect(true, []{ + double fd = D::fmin_d(numeric_limits::quiet_NaN(), + numeric_limits::quiet_NaN()); + return D::isquietnan(fd); + }, "fmin.d, quiet NaN both"); + expect(3.14, + []{return D::fmin_d(numeric_limits::signaling_NaN(), + 3.14);}, + "fmin.d, signaling NaN first"); + expect(1.816, + []{return D::fmin_d(1.816, + numeric_limits::signaling_NaN());}, + "fmin.d, signaling NaN second"); + expect(true, []{ + double fd = D::fmin_d(numeric_limits::signaling_NaN(), + numeric_limits::signaling_NaN()); + return D::issignalingnan(fd); + }, "fmin.d, signaling NaN both"); + + // FMAX.D + expect(3.14, []{return D::fmax_d(3.14, 2.718);}, "fmax.d"); + expect(numeric_limits::min(), + []{return D::fmax_d(-numeric_limits::infinity(), + numeric_limits::min());}, + "fmax.d, -infinity"); + expect(numeric_limits::infinity(), + []{return D::fmax_d(numeric_limits::infinity(), + numeric_limits::max());}, + "fmax.d, infinity"); + expect(-1.414, + []{return D::fmax_d(numeric_limits::quiet_NaN(), -1.414);}, + "fmax.d, quiet NaN first"); + expect(2.718, + []{return D::fmax_d(2.718, numeric_limits::quiet_NaN());}, + "fmax.d, quiet NaN second"); + expect(true, []{ + double fd = D::fmax_d(numeric_limits::quiet_NaN(), + numeric_limits::quiet_NaN()); + return D::isquietnan(fd); + }, "fmax.d, quiet NaN both"); + expect(3.14, + []{return D::fmax_d(numeric_limits::signaling_NaN(), + 3.14);}, + "fmax.d, signaling NaN first"); + expect(1.816, + []{return D::fmax_d(1.816, + numeric_limits::signaling_NaN());}, + "fmax.d, signaling NaN second"); + expect(true, []{ + double fd = D::fmax_d(numeric_limits::signaling_NaN(), + numeric_limits::signaling_NaN()); + return D::issignalingnan(fd); + }, "fmax.d, signaling NaN both"); + + // FCVT.S.D + expect(4.0, []{return D::fcvt_s_d(4.0);}, "fcvt.s.d"); + expect(true, []{ + float fd = D::fcvt_s_d(numeric_limits::quiet_NaN()); + return F::isquietnan(fd); + }, "fcvt.s.d, quiet NaN"); + expect(true, []{ + float fd = D::fcvt_s_d(numeric_limits::signaling_NaN()); + return F::isquietnan(fd); + }, "fcvt.s.d, signaling NaN"); + expect(numeric_limits::infinity(), + []{return D::fcvt_s_d(numeric_limits::infinity());}, + "fcvt.s.d, infinity"); + expect(numeric_limits::infinity(), + []{return D::fcvt_s_d(numeric_limits::max());}, + "fcvt.s.d, overflow"); + expect(0.0, []{return D::fcvt_s_d(numeric_limits::min());}, + "fcvt.s.d, underflow"); + + // FCVT.D.S + expect(D::number(0x4005BE76C0000000), + []{return D::fcvt_d_s(2.718);}, "fcvt.d.s"); + expect(true, []{ + double fd = D::fcvt_d_s(numeric_limits::quiet_NaN()); + return D::isquietnan(fd); + }, "fcvt.d.s, quiet NaN"); + expect(true, []{ + double fd = D::fcvt_d_s(numeric_limits::signaling_NaN()); + return D::isquietnan(fd); + }, "fcvt.d.s, signaling NaN"); + expect(numeric_limits::infinity(), + []{return D::fcvt_d_s(numeric_limits::infinity());}, + "fcvt.d.s, infinity"); + + // FEQ.D + expect(true, []{return D::feq_d(1.414, 1.414);}, "feq.d, equal"); + expect(false,[]{return D::feq_d(2.718, 1.816);}, "feq.d, not equal"); + expect(true, []{return D::feq_d(0.0, -0.0);}, "feq.d, 0 == -0"); + expect(false, + []{return D::feq_d(numeric_limits::quiet_NaN(), -1.0);}, + "feq.d, quiet NaN first"); + expect(false, + []{return D::feq_d(2.0, numeric_limits::quiet_NaN());}, + "feq.d, quiet NaN second"); + expect(false, + []{return D::feq_d(numeric_limits::quiet_NaN(), + numeric_limits::quiet_NaN());}, + "feq.d, quiet NaN both"); + expect(false, + []{return D::feq_d(numeric_limits::signaling_NaN(),-1.0);}, + "feq.d, signaling NaN first"); + expect(false, + []{return D::feq_d(2.0, numeric_limits::signaling_NaN());}, + "feq.d, signaling NaN second"); + expect(false, + []{return D::feq_d(numeric_limits::signaling_NaN(), + numeric_limits::signaling_NaN());}, + "feq.d, signaling NaN both"); + + // FLT.D + expect(false, []{return D::flt_d(1.414, 1.414);}, "flt.d, equal"); + expect(true, []{return D::flt_d(1.816, 2.718);}, "flt.d, less"); + expect(false, []{return D::flt_d(2.718, 1.816);}, "flt.d, greater"); + expect(false, + []{return D::flt_d(numeric_limits::quiet_NaN(), -1.0);}, + "flt.d, quiet NaN first"); + expect(false, + []{return D::flt_d(2.0, numeric_limits::quiet_NaN());}, + "flt.d, quiet NaN second"); + expect(false, + []{return D::flt_d(numeric_limits::quiet_NaN(), + numeric_limits::quiet_NaN());}, + "flt.d, quiet NaN both"); + expect(false, + []{return D::flt_d(numeric_limits::signaling_NaN(),-1.0);}, + "flt.d, signaling NaN first"); + expect(false, + []{return D::flt_d(2.0, numeric_limits::signaling_NaN());}, + "flt.d, signaling NaN second"); + expect(false, + []{return D::flt_d(numeric_limits::signaling_NaN(), + numeric_limits::signaling_NaN());}, + "flt.d, signaling NaN both"); + + // FLE.D + expect(true, []{return D::fle_d(1.414, 1.414);}, "fle.d, equal"); + expect(true, []{return D::fle_d(1.816, 2.718);}, "fle.d, less"); + expect(false, []{return D::fle_d(2.718, 1.816);}, "fle.d, greater"); + expect(true, []{return D::fle_d(0.0, -0.0);}, "fle.d, 0 == -0"); + expect(false, + []{return D::fle_d(numeric_limits::quiet_NaN(), -1.0);}, + "fle.d, quiet NaN first"); + expect(false, + []{return D::fle_d(2.0, numeric_limits::quiet_NaN());}, + "fle.d, quiet NaN second"); + expect(false, + []{return D::fle_d(numeric_limits::quiet_NaN(), + numeric_limits::quiet_NaN());}, + "fle.d, quiet NaN both"); + expect(false, + []{return D::fle_d(numeric_limits::signaling_NaN(),-1.0);}, + "fle.d, signaling NaN first"); + expect(false, + []{return D::fle_d(2.0, numeric_limits::signaling_NaN());}, + "fle.d, signaling NaN second"); + expect(false, + []{return D::fle_d(numeric_limits::signaling_NaN(), + numeric_limits::signaling_NaN());}, + "fle.d, signaling NaN both"); + + // FCLASS.D + expect(0x1, + []{return D::fclass_d(-numeric_limits::infinity());}, + "fclass.d, -infinity"); + expect(0x2, + []{return D::fclass_d(-3.14);}, "fclass.d, -normal"); + expect(0x4, + []{return D::fclass_d(D::number(0x800FFFFFFFFFFFFFULL));}, + "fclass.d, -subnormal"); + expect(0x8, []{return D::fclass_d(-0.0);}, "fclass.d, -0.0"); + expect(0x10, []{return D::fclass_d(0.0);}, "fclass.d, 0.0"); + expect(0x20, + []{return D::fclass_d(D::number(0x000FFFFFFFFFFFFFULL));}, + "fclass.d, subnormal"); + expect(0x40, []{return D::fclass_d(1.816);}, "fclass.d, normal"); + expect(0x80, + []{return D::fclass_d(numeric_limits::infinity());}, + "fclass.d, infinity"); + expect(0x100, + []{return D::fclass_d(numeric_limits::signaling_NaN());}, + "fclass.d, signaling NaN"); + expect(0x200, + []{return D::fclass_d(numeric_limits::quiet_NaN());}, + "fclass.s, quiet NaN"); + + // FCVT.W.D + expect(256, []{return D::fcvt_w_d(256.3);}, + "fcvt.w.d, truncate positive"); + expect(-256, []{return D::fcvt_w_d(-256.2);}, + "fcvt.w.d, truncate negative"); + expect(0, []{return D::fcvt_w_d(0.0);}, "fcvt.w.d, 0.0"); + expect(0, []{return D::fcvt_w_d(-0.0);}, "fcvt.w.d, -0.0"); + expect(numeric_limits::max(), + []{return D::fcvt_w_d(numeric_limits::max());}, + "fcvt.w.d, overflow"); + expect(0, []{return D::fcvt_w_d(numeric_limits::min());}, + "fcvt.w.d, underflow"); + expect(numeric_limits::max(), + []{return D::fcvt_w_d(numeric_limits::infinity());}, + "fcvt.w.d, infinity"); + expect(numeric_limits::min(), + []{return D::fcvt_w_d(-numeric_limits::infinity());}, + "fcvt.w.d, -infinity"); + expect(numeric_limits::max(), + []{return D::fcvt_w_d(numeric_limits::quiet_NaN());}, + "fcvt.w.d, quiet NaN"); + expect(numeric_limits::max(), + []{return D::fcvt_w_d(-numeric_limits::quiet_NaN());}, + "fcvt.w.d, quiet -NaN"); + expect(numeric_limits::max(), + []{return D::fcvt_w_d(numeric_limits::signaling_NaN());}, + "fcvt.w.d, signaling NaN"); + + // FCVT.WU.D + expect(256, []{return D::fcvt_wu_d(256.3);}, + "fcvt.wu.d, truncate positive"); + expect(0, []{return D::fcvt_wu_d(-256.2);}, + "fcvt.wu.d, truncate negative"); + expect(0, []{return D::fcvt_wu_d(0.0);}, "fcvt.wu.d, 0.0"); + expect(0, []{return D::fcvt_wu_d(-0.0);}, "fcvt.wu.d, -0.0"); + expect(numeric_limits::max(), + []{return D::fcvt_wu_d(numeric_limits::max());}, + "fcvt.wu.d, overflow"); + expect(0,[]{return D::fcvt_wu_d(numeric_limits::min());}, + "fcvt.wu.d, underflow"); + expect(numeric_limits::max(), + []{return D::fcvt_wu_d(numeric_limits::infinity());}, + "fcvt.wu.d, infinity"); + expect(0, + []{return D::fcvt_wu_d(-numeric_limits::infinity());}, + "fcvt.wu.d, -infinity"); + expect(0xFFFFFFFFFFFFFFFFULL, + []{return D::fcvt_wu_d(numeric_limits::quiet_NaN());}, + "fcvt.wu.d, quiet NaN"); + expect(0xFFFFFFFFFFFFFFFFULL, + []{return D::fcvt_wu_d(-numeric_limits::quiet_NaN());}, + "fcvt.wu.d, quiet -NaN"); + expect(0xFFFFFFFFFFFFFFFFULL, + []{return D::fcvt_wu_d(numeric_limits::signaling_NaN());}, + "fcvt.wu.d, signaling NaN"); + + // FCVT.D.W + expect(0.0, []{return D::fcvt_d_w(0);}, "fcvt.d.w, 0"); + expect(-2147483648.0, + []{return D::fcvt_d_w(numeric_limits::min());}, + "fcvt.d.w, negative"); + expect(255.0, []{return D::fcvt_d_w(0xFFFFFFFF000000FFLL);}, + "fcvt.d.w, truncate"); + + // FCVT.D.WU + expect(0.0, []{return D::fcvt_d_wu(0);}, "fcvt.d.wu, 0"); + expect(2147483648.0, + []{return D::fcvt_d_wu(numeric_limits::min());}, + "fcvt.d.wu"); + expect(255.0, + []{return D::fcvt_d_wu(0xFFFFFFFF000000FFLL);}, + "fcvt.d.wu, truncate"); + + // FCVT.L.D + expect(256, []{return D::fcvt_l_d(256.3);}, + "fcvt.l.d, truncate positive"); + expect(-256, []{return D::fcvt_l_d(-256.2);}, + "fcvt.l.d, truncate negative"); + expect(0, []{return D::fcvt_l_d(0.0);}, "fcvt.l.d, 0.0"); + expect(0, []{return D::fcvt_l_d(-0.0);}, "fcvt.l.d, -0.0"); + expect(-8589934592LL, []{return D::fcvt_l_d(-8589934592.0);}, + "fcvt.l.d, 32-bit overflow"); + expect(numeric_limits::max(), + []{return D::fcvt_l_d(numeric_limits::max());}, + "fcvt.l.d, overflow"); + expect(0, []{return D::fcvt_l_d(numeric_limits::min());}, + "fcvt.l.d, underflow"); + expect(numeric_limits::max(), + []{return D::fcvt_l_d(numeric_limits::infinity());}, + "fcvt.l.d, infinity"); + expect(numeric_limits::min(), + []{return D::fcvt_l_d(-numeric_limits::infinity());}, + "fcvt.l.d, -infinity"); + expect(numeric_limits::max(), + []{return D::fcvt_l_d(numeric_limits::quiet_NaN());}, + "fcvt.l.d, quiet NaN"); + expect(numeric_limits::max(), + []{return D::fcvt_l_d(-numeric_limits::quiet_NaN());}, + "fcvt.l.d, quiet -NaN"); + expect(numeric_limits::max(), + []{return D::fcvt_l_d(numeric_limits::signaling_NaN());}, + "fcvt.l.d, signaling NaN"); + + // FCVT.LU.D + expect(256, []{return D::fcvt_lu_d(256.3);}, + "fcvt.lu.d, truncate positive"); + expect(0, []{return D::fcvt_lu_d(-256.2);}, + "fcvt.lu.d, truncate negative"); + expect(0, []{return D::fcvt_lu_d(0.0);}, "fcvt.lu.d, 0.0"); + expect(0, []{return D::fcvt_lu_d(-0.0);}, "fcvt.lu.d, -0.0"); + expect(8589934592LL, []{return D::fcvt_lu_d(8589934592.0);}, + "fcvt.lu.d, 32-bit overflow"); + expect(numeric_limits::max(), + []{return D::fcvt_lu_d(numeric_limits::max());}, + "fcvt.lu.d, overflow"); + expect(0,[]{return D::fcvt_lu_d(numeric_limits::min());}, + "fcvt.lu.d, underflow"); + expect(numeric_limits::max(), + []{return D::fcvt_lu_d(numeric_limits::infinity());}, + "fcvt.lu.d, infinity"); + expect(0, + []{return D::fcvt_lu_d(-numeric_limits::infinity());}, + "fcvt.lu.d, -infinity"); + expect(0xFFFFFFFFFFFFFFFFULL, + []{return D::fcvt_lu_d(numeric_limits::quiet_NaN());}, + "fcvt.lu.d, quiet NaN"); + expect(0xFFFFFFFFFFFFFFFFULL, + []{return D::fcvt_lu_d(-numeric_limits::quiet_NaN());}, + "fcvt.lu.d, quiet -NaN"); + expect(0xFFFFFFFFFFFFFFFFULL, + []{return D::fcvt_lu_d(numeric_limits::signaling_NaN());}, + "fcvt.lu.d, signaling NaN"); + + // FMV.X.D + expect(0x40091EB851EB851FULL, []{return D::fmv_x_d(3.14);}, + "fmv.x.d, positive"); + expect(0xC0091EB851EB851FULL, []{return D::fmv_x_d(-3.14);}, + "fmv.x.d, negative"); + expect(0x0000000000000000ULL, []{return D::fmv_x_d(0.0);}, + "fmv.x.d, 0.0"); + expect(0x8000000000000000ULL, []{return D::fmv_x_d(-0.0);}, + "fmv.x.d, -0.0"); + + // FCVT.D.L + expect(0.0, []{return D::fcvt_d_l(0);}, "fcvt.d.l, 0"); + expect(D::number(0xC3E0000000000000), + []{return D::fcvt_d_l(numeric_limits::min());}, + "fcvt.d.l, negative"); + expect(D::number(0xC1EFFFFFE0200000), + []{return D::fcvt_d_l(0xFFFFFFFF000000FFLL);}, + "fcvt.d.l, 32-bit truncate"); + + // FCVT.D.LU + expect(0.0, []{return D::fcvt_d_lu(0);}, "fcvt.d.lu, 0"); + expect(D::number(0x43E0000000000000), + []{return D::fcvt_d_lu(numeric_limits::min());}, + "fcvt.d.lu"); + expect(D::number(0x43EFFFFFFFE00000), + []{return D::fcvt_d_lu(0xFFFFFFFF000000FFLL);}, + "fcvt.d.lu, 32-bit truncate"); + + // FMV.D.X + expect(-numeric_limits::infinity(), + []{return D::fmv_d_x(0xFFF0000000000000ULL);}, "fmv.d.x"); + + return 0; +} diff --git a/tests/test-progs/insttest/src/riscv/rv64d.h b/tests/test-progs/insttest/src/riscv/rv64d.h new file mode 100644 index 000000000..d2c5898c4 --- /dev/null +++ b/tests/test-progs/insttest/src/riscv/rv64d.h @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2016 The University of Virginia + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Alec Roelke + */ + +#pragma once + +#include +#include + +#include "insttest.h" + +namespace D +{ + +constexpr inline uint64_t +bits(double d) +{ + return reinterpret_cast(d); +} + +constexpr inline double +number(uint64_t b) +{ + return reinterpret_cast(b); +} + +inline bool +isquietnan(double f) +{ + return std::isnan(f) && (bits(f)&0x0008000000000000ULL) != 0; +} + +inline bool +issignalingnan(double f) +{ + return std::isnan(f) && (bits(f)&0x0008000000000000ULL) == 0; +} + +inline double +load(double mem) +{ + double fd = std::numeric_limits::signaling_NaN(); + asm volatile("fld %0,%1" + : "=f" (fd) + : "m" (mem)); + return fd; +} + +inline double +store(double fs) +{ + double mem = std::numeric_limits::signaling_NaN(); + asm volatile("fsd %1,%0" : "=m" (mem) : "f" (fs)); + return mem; +} + +inline double +fmadd_d(double fs1, double fs2, double fs3) +{ + double fd = std::numeric_limits::signaling_NaN(); + FR4OP("fmadd.d", fd, fs1, fs2, fs3); + return fd; +} + +inline double +fmsub_d(double fs1, double fs2, double fs3) +{ + double fd = std::numeric_limits::signaling_NaN(); + FR4OP("fmsub.d", fd, fs1, fs2, fs3); + return fd; +} + +inline double +fnmsub_d(double fs1, double fs2, double fs3) +{ + double fd = std::numeric_limits::signaling_NaN(); + FR4OP("fnmsub.d", fd, fs1, fs2, fs3); + return fd; +} + +inline double +fnmadd_d(double fs1, double fs2, double fs3) +{ + double fd = std::numeric_limits::signaling_NaN(); + FR4OP("fnmadd.d", fd, fs1, fs2, fs3); + return fd; +} + +inline double +fadd_d(double fs1, double fs2) +{ + double fd = std::numeric_limits::signaling_NaN(); + FROP("fadd.d", fd, fs1, fs2); + return fd; +} + +inline double +fsub_d(double fs1, double fs2) +{ + double fd = std::numeric_limits::signaling_NaN(); + FROP("fsub.d", fd, fs1, fs2); + return fd; +} + +inline double +fmul_d(double fs1, double fs2) +{ + double fd = std::numeric_limits::signaling_NaN(); + FROP("fmul.d", fd, fs1, fs2); + return fd; +} + +inline double +fdiv_d(double fs1, double fs2) +{ + double fd = std::numeric_limits::signaling_NaN(); + FROP("fdiv.d", fd, fs1, fs2); + return fd; +} + +inline double +fsqrt_d(double fs1) +{ + double fd = std::numeric_limits::signaling_NaN(); + asm volatile("fsqrt.d %0,%1" : "=f" (fd) : "f" (fs1)); + return fd; +} + +inline double +fsgnj_d(double fs1, double fs2) +{ + double fd = std::numeric_limits::signaling_NaN(); + FROP("fsgnj.d", fd, fs1, fs2); + return fd; +} + +inline double +fsgnjn_d(double fs1, double fs2) +{ + double fd = std::numeric_limits::signaling_NaN(); + FROP("fsgnjn.d", fd, fs1, fs2); + return fd; +} + +inline double +fsgnjx_d(double fs1, double fs2) +{ + double fd = std::numeric_limits::signaling_NaN(); + FROP("fsgnjx.d", fd, fs1, fs2); + return fd; +} + +inline double +fmin_d(double fs1, double fs2) +{ + double fd = std::numeric_limits::signaling_NaN(); + FROP("fmin.d", fd, fs1, fs2); + return fd; +} + +inline double +fmax_d(double fs1, double fs2) +{ + double fd = std::numeric_limits::signaling_NaN(); + FROP("fmax.d", fd, fs1, fs2); + return fd; +} + +inline float +fcvt_s_d(double fs1) +{ + float fd = std::numeric_limits::signaling_NaN(); + asm volatile("fcvt.s.d %0,%1" : "=f" (fd) : "f" (fs1)); + return fd; +} + +inline double +fcvt_d_s(float fs1) +{ + double fd = std::numeric_limits::signaling_NaN(); + asm volatile("fcvt.d.s %0,%1" : "=f" (fd) : "f" (fs1)); + return fd; +} + +inline bool +feq_d(double fs1, double fs2) +{ + bool rd = false; + asm volatile("feq.d %0,%1,%2" : "=r" (rd) : "f" (fs1), "f" (fs2)); + return rd; +} + +inline bool +flt_d(double fs1, double fs2) +{ + bool rd = false; + asm volatile("flt.d %0,%1,%2" : "=r" (rd) : "f" (fs1), "f" (fs2)); + return rd; +} + +inline bool +fle_d(double fs1, double fs2) +{ + bool rd = false; + asm volatile("fle.d %0,%1,%2" : "=r" (rd) : "f" (fs1), "f" (fs2)); + return rd; +} + +inline uint64_t +fclass_d(double fs1) +{ + uint64_t rd = -1; + asm volatile("fclass.d %0,%1" : "=r" (rd) : "f" (fs1)); + return rd; +} + +inline int64_t +fcvt_w_d(double fs1) +{ + int64_t rd = 0; + asm volatile("fcvt.w.d %0,%1" : "=r" (rd) : "f" (fs1)); + return rd; +} + +inline uint64_t +fcvt_wu_d(double fs1) +{ + uint64_t rd = 0; + asm volatile("fcvt.wu.d %0,%1" : "=r" (rd) : "f" (fs1)); + return rd; +} + +inline float +fcvt_d_w(int64_t rs1) +{ + double fd = std::numeric_limits::signaling_NaN(); + asm volatile("fcvt.d.w %0,%1" : "=f" (fd) : "r" (rs1)); + return fd; +} + +inline double +fcvt_d_wu(uint64_t rs1) +{ + double fd = std::numeric_limits::signaling_NaN(); + asm volatile("fcvt.d.wu %0,%1" : "=f" (fd) : "r" (rs1)); + return fd; +} + +inline int64_t +fcvt_l_d(double fs1) +{ + int64_t rd = 0; + asm volatile("fcvt.l.d %0,%1" : "=r" (rd) : "f" (fs1)); + return rd; +} + +inline uint64_t +fcvt_lu_d(double fs1) +{ + uint64_t rd = 0; + asm volatile("fcvt.lu.d %0,%1" : "=r" (rd) : "f" (fs1)); + return rd; +} + +inline uint64_t +fmv_x_d(double fs1) +{ + uint64_t rd = 0; + asm volatile("fmv.x.d %0,%1" : "=r" (rd) : "f" (fs1)); + return rd; +} + +inline double +fcvt_d_l(int64_t rs1) +{ + double fd = std::numeric_limits::signaling_NaN(); + asm volatile("fcvt.d.l %0,%1" : "=f" (fd) : "r" (rs1)); + return fd; +} + +inline double +fcvt_d_lu(uint64_t rs1) +{ + double fd = std::numeric_limits::signaling_NaN(); + asm volatile("fcvt.d.lu %0,%1" : "=f" (fd) : "r" (rs1)); + return fd; +} + +inline double +fmv_d_x(uint64_t rs1) +{ + double fd = std::numeric_limits::signaling_NaN(); + asm volatile("fmv.d.x %0,%1" : "=f" (fd) : "r" (rs1)); + return fd; +} + +} // namespace D diff --git a/tests/test-progs/insttest/src/riscv/rv64f.cpp b/tests/test-progs/insttest/src/riscv/rv64f.cpp new file mode 100644 index 000000000..f8b79f42a --- /dev/null +++ b/tests/test-progs/insttest/src/riscv/rv64f.cpp @@ -0,0 +1,694 @@ +/* + * Copyright (c) 2016 The University of Virginia + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Alec Roelke + */ + +#include +#include + +#include "insttest.h" +#include "rv64f.h" + +int main() +{ + using namespace std; + using namespace insttest; + + // FLAGS + expect(0, []{ + F::fsflags(0); + return F::frflags(); + }, "clear fsflags"); + + // Memory + expect(3.14, []{return F::load(3.14);}, "flw"); + expect(1.816, []{return F::store(1.816);}, "fsw"); + + // FMADD.S + expect(7.11624, []{return F::fmadd_s(3.14, 1.816, 1.414);}, + "fmadd.s"); + expect(true, []{ + float fd = F::fmadd_s(numeric_limits::quiet_NaN(), 3.14, + 1.816); + return F::isquietnan(fd); + }, "fmadd.s, quiet NaN"); + expect(true, []{ + float fd = F::fmadd_s(3.14, numeric_limits::signaling_NaN(), + 1.816); + return F::isquietnan(fd); + }, "fmadd.s, signaling NaN"); + expect(numeric_limits::infinity(), + []{return F::fmadd_s(3.14, numeric_limits::infinity(), + 1.414);}, + "fmadd.s, infinity"); + expect(-numeric_limits::infinity(), + []{return F::fmadd_s(3.14, -numeric_limits::infinity(), + 1.414);}, + "fmadd.s, -infinity"); + + // FMSUB.S + expect(4.28824, []{return F::fmsub_s(3.14, 1.816, 1.414);}, + "fmsub.s"); + expect(true, []{ + float fd = F::fmsub_s(3.14, numeric_limits::quiet_NaN(), + 1.816); + return F::isquietnan(fd); + }, "fmsub.s, quiet NaN"); + expect(true, []{ + float fd = F::fmsub_s(3.14, 1.816, + numeric_limits::signaling_NaN()); + return F::isquietnan(fd); + }, "fmsub.s, signaling NaN"); + expect(numeric_limits::infinity(), + []{return F::fmsub_s(numeric_limits::infinity(), 1.816, + 1.414);}, + "fmsub.s, infinity"); + expect(-numeric_limits::infinity(), + []{return F::fmsub_s(3.14, -numeric_limits::infinity(), + 1.414);}, + "fmsub.s, -infinity"); + expect(-numeric_limits::infinity(), + []{return F::fmsub_s(3.14, 1.816, + numeric_limits::infinity());}, + "fmsub.s, subtract infinity"); + + // FNMSUB.S + expect(-4.28824, []{return F::fnmsub_s(3.14, 1.816, 1.414);}, + "fnmsub.s"); + expect(true, []{ + float fd = F::fnmsub_s(3.14, 1.816, + numeric_limits::quiet_NaN()); + return F::isquietnan(fd); + }, "fnmsub.s, quiet NaN"); + expect(true, []{ + float fd = F::fnmsub_s(numeric_limits::signaling_NaN(), + 1.816, 1.414); + return F::isquietnan(fd); + }, "fnmsub.s, signaling NaN"); + expect(-numeric_limits::infinity(), + []{return F::fnmsub_s(numeric_limits::infinity(), + 1.816, 1.414);}, + "fnmsub.s, infinity"); + expect(numeric_limits::infinity(), + []{return F::fnmsub_s(3.14, -numeric_limits::infinity(), + 1.414);}, + "fnmsub.s, -infinity"); + expect(numeric_limits::infinity(), + []{return F::fnmsub_s(3.14, 1.816, + numeric_limits::infinity());}, + "fnmsub.s, subtract infinity"); + + // FNMADD.S + expect(-7.11624, []{return F::fnmadd_s(3.14, 1.816, 1.414);}, + "fnmadd.s"); + expect(true, []{ + float fd = F::fnmadd_s(numeric_limits::quiet_NaN(), 3.14, + 1.816); + return F::isquietnan(fd); + }, "fnmadd.s, quiet NaN"); + expect(true, []{ + float fd = F::fnmadd_s(3.14,numeric_limits::signaling_NaN(), + 1.816); + return F::isquietnan(fd); + }, "fnmadd.s, signaling NaN"); + expect(-numeric_limits::infinity(), + []{return F::fnmadd_s(3.14, numeric_limits::infinity(), + 1.414);}, + "fnmadd.s, infinity"); + expect(numeric_limits::infinity(), + []{return F::fnmadd_s(3.14, -numeric_limits::infinity(), + 1.414);}, + "fnmadd.s, -infinity"); + + // FADD.S + expect(4.554, []{return F::fadd_s(3.14, 1.414);}, "fadd.s"); + expect(true, []{ + float fd = F::fadd_s(numeric_limits::quiet_NaN(), 1.414); + return F::isquietnan(fd); + }, "fadd.s, quiet NaN"); + expect(true, []{ + float fd = F::fadd_s(3.14, numeric_limits::signaling_NaN()); + return F::isquietnan(fd); + }, "fadd.s, signaling NaN"); + expect(numeric_limits::infinity(), + []{return F::fadd_s(3.14, numeric_limits::infinity());}, + "fadd.s, infinity"); + expect(-numeric_limits::infinity(), + []{return F::fadd_s(-numeric_limits::infinity(), 1.816);}, + "fadd.s, -infinity"); + + // FSUB.S + expect(F::number(0xbfdced92), []{return F::fsub_s(1.414, 3.14);}, + "fsub.s"); + expect(true, []{ + float fd = F::fsub_s(numeric_limits::quiet_NaN(), 1.414); + return F::isquietnan(fd); + }, "fsub.s, quiet NaN"); + expect(true, []{ + float fd = F::fsub_s(3.14, numeric_limits::signaling_NaN()); + return F::isquietnan(fd); + }, "fsub.s, signaling NaN"); + expect(numeric_limits::infinity(), + []{return F::fsub_s(numeric_limits::infinity(), 3.14);}, + "fsub.s, infinity"); + expect(-numeric_limits::infinity(), + []{return F::fsub_s(-numeric_limits::infinity(), 3.14);}, + "fsub.s, -infinity"); + expect(-numeric_limits::infinity(), + []{return F::fsub_s(1.414, numeric_limits::infinity());}, + "fsub.s, subtract infinity"); + + // FMUL.S + expect(F::number(0x4024573b), []{return F::fmul_s(1.816, 1.414);}, + "fmul.s"); + expect(true, []{ + float fd = F::fmul_s(numeric_limits::quiet_NaN(), 1.414); + return F::isquietnan(fd); + }, "fmul.s, quiet NaN"); + expect(true, []{ + float fd = F::fmul_s(1.816, + numeric_limits::signaling_NaN()); + return F::isquietnan(fd); + }, "fmul.s, signaling NaN"); + expect(numeric_limits::infinity(), + []{return F::fmul_s(numeric_limits::infinity(), 2.718);}, + "fmul.s, infinity"); + expect(-numeric_limits::infinity(), + []{return F::fmul_s(2.5966, -numeric_limits::infinity());}, + "fmul.s, -infinity"); + expect(true, []{ + float fd = F::fmul_s(0.0, numeric_limits::infinity()); + return F::isquietnan(fd); + }, "fmul.s, 0*infinity"); + expect(numeric_limits::infinity(), + []{return F::fmul_s(numeric_limits::max(), 2.0);}, + "fmul.s, overflow"); + expect(0.0, + []{return F::fmul_s(numeric_limits::min(), + numeric_limits::min());}, + "fmul.s, underflow"); + + // FDIV.S + expect(2.5, []{return F::fdiv_s(10.0, 4.0);}, "fdiv.s"); + expect(true, []{ + float fd = F::fdiv_s(numeric_limits::quiet_NaN(), 4.0); + return F::isquietnan(fd); + }, "fdiv.s, quiet NaN"); + expect(true, []{ + float fd = F::fdiv_s(10.0, numeric_limits::signaling_NaN()); + return F::isquietnan(fd); + }, "fdiv.s, signaling NaN"); + expect(numeric_limits::infinity(), + []{return F::fdiv_s(10.0, 0.0);}, "fdiv.s/0"); + expect(0.0, + []{return F::fdiv_s(10.0, numeric_limits::infinity());}, + "fdiv.s/infinity"); + expect(true, []{ + float fd = F::fdiv_s(numeric_limits::infinity(), + numeric_limits::infinity()); + return F::isquietnan(fd); + }, "fdiv.s, infinity/infinity"); + expect(true, []{ + float fd = F::fdiv_s(0.0, 0.0); + return F::isquietnan(fd); + }, "fdiv.s, 0/0"); + expect(numeric_limits::infinity(), + []{return F::fdiv_s(numeric_limits::infinity(), 0.0);}, + "fdiv.s, infinity/0"); + expect(0.0, + []{return F::fdiv_s(0.0, numeric_limits::infinity());}, + "fdiv.s, 0/infinity"); + expect(0.0, + []{return F::fdiv_s(numeric_limits::min(), + numeric_limits::max());}, + "fdiv.s, underflow"); + expect(numeric_limits::infinity(), + []{return F::fdiv_s(numeric_limits::max(), + numeric_limits::min());}, + "fdiv.s, overflow"); + + // FSQRT.S + expect(0.3, []{return F::fsqrt_s(0.09);}, "fsqrt.s"); + expect(true, []{ + float fd = F::fsqrt_s(-1.0); + return F::isquietnan(fd); + }, "fsqrt.s, NaN"); + expect(true, []{ + float fd = F::fsqrt_s(numeric_limits::quiet_NaN()); + return F::isquietnan(fd); + }, "fsqrt.s, quiet NaN"); + expect(true, []{ + float fd = F::fsqrt_s(numeric_limits::signaling_NaN()); + return F::isquietnan(fd); + }, "fsqrt.s, signaling NaN"); + expect(numeric_limits::infinity(), + []{return F::fsqrt_s(numeric_limits::infinity());}, + "fsqrt.s, infinity"); + + // FSGNJ.S + expect(1.0, []{return F::fsgnj_s(1.0, 25.0);}, "fsgnj.s, ++"); + expect(-1.0, []{return F::fsgnj_s(1.0, -25.0);}, "fsgnj.s, +-"); + expect(1.0, []{return F::fsgnj_s(-1.0, 25.0);}, "fsgnj.s, -+"); + expect(-1.0, []{return F::fsgnj_s(-1.0, -25.0);}, "fsgnj.s, --"); + expect(true, []{ + float fd = F::fsgnj_s(numeric_limits::quiet_NaN(), -4.0); + return F::isquietnan(fd); + }, "fsgnj.s, quiet NaN"); + expect(true, []{ + float fd = F::fsgnj_s(numeric_limits::signaling_NaN(), + -4.0); + return F::issignalingnan(fd); + }, "fsgnj.s, signaling NaN"); + expect(4.0, []{return F::fsgnj_s(4.0, + numeric_limits::quiet_NaN());}, "fsgnj.s, inject NaN"); + expect(-4.0, + []{return F::fsgnj_s(4.0, -numeric_limits::quiet_NaN());}, + "fsgnj.s, inject -NaN"); + + // FSGNJN.S + expect(-1.0, []{return F::fsgnjn_s(1.0, 25.0);}, "fsgnjn.s, ++"); + expect(1.0, []{return F::fsgnjn_s(1.0, -25.0);}, "fsgnjn.s, +-"); + expect(-1.0, []{return F::fsgnjn_s(-1.0, 25.0);}, "fsgnjn.s, -+"); + expect(1.0, []{return F::fsgnjn_s(-1.0, -25.0);}, "fsgnjn.s, --"); + expect(true, []{ + float fd = F::fsgnjn_s(numeric_limits::quiet_NaN(), -4.0); + return F::isquietnan(fd); + }, "fsgnjn.s, quiet NaN"); + expect(true, []{ + float fd = F::fsgnjn_s(numeric_limits::signaling_NaN(), + -4.0); + return F::issignalingnan(fd); + }, "fsgnjn.s, signaling NaN"); + expect(-4.0, + []{return F::fsgnjn_s(4.0, numeric_limits::quiet_NaN());}, + "fsgnjn.s, inject NaN"); + expect(4.0, + []{return F::fsgnjn_s(4.0, -numeric_limits::quiet_NaN());}, + "fsgnjn.s, inject NaN"); + + // FSGNJX.S + expect(1.0, []{return F::fsgnjx_s(1.0, 25.0);}, "fsgnjx.s, ++"); + expect(-1.0, []{return F::fsgnjx_s(1.0, -25.0);}, "fsgnjx.s, +-"); + expect(-1.0, []{return F::fsgnjx_s(-1.0, 25.0);}, "fsgnjx.s, -+"); + expect(1.0, []{return F::fsgnjx_s(-1.0, -25.0);}, "fsgnjx.s, --"); + expect(true, []{ + float fd = F::fsgnjx_s(numeric_limits::quiet_NaN(), -4.0); + return F::isquietnan(fd); + }, "fsgnjx.s, quiet NaN"); + expect(true, []{ + float fd = F::fsgnjx_s(numeric_limits::signaling_NaN(), + -4.0); + return F::issignalingnan(fd); + }, "fsgnjx.s, signaling NaN"); + expect(4.0, + []{return F::fsgnjx_s(4.0, numeric_limits::quiet_NaN());}, + "fsgnjx.s, inject NaN"); + expect(-4.0, + []{return F::fsgnjx_s(4.0, -numeric_limits::quiet_NaN());}, + "fsgnjx.s, inject -NaN"); + + // FMIN.S + expect(2.718, []{return F::fmin_s(3.14, 2.718);}, "fmin.s"); + expect(-numeric_limits::infinity(), + []{return F::fmin_s(-numeric_limits::infinity(), + numeric_limits::min());}, + "fmin.s, -infinity"); + expect(numeric_limits::max(), + []{return F::fmin_s(numeric_limits::infinity(), + numeric_limits::max());}, + "fmin.s, infinity"); + expect(-1.414, + []{return F::fmin_s(numeric_limits::quiet_NaN(), -1.414);}, + "fmin.s, quiet NaN first"); + expect(2.718, + []{return F::fmin_s(2.718, numeric_limits::quiet_NaN());}, + "fmin.s, quiet NaN second"); + expect(true, []{ + float fd = F::fmin_s(numeric_limits::quiet_NaN(), + numeric_limits::quiet_NaN()); + return F::isquietnan(fd); + }, "fmin.s, quiet NaN both"); + expect(3.14, + []{return F::fmin_s(numeric_limits::signaling_NaN(), + 3.14);}, + "fmin.s, signaling NaN first"); + expect(1.816, + []{return F::fmin_s(1.816, + numeric_limits::signaling_NaN());}, + "fmin.s, signaling NaN second"); + expect(true, []{ + float fd = F::fmin_s(numeric_limits::signaling_NaN(), + numeric_limits::signaling_NaN()); + return F::issignalingnan(fd); + }, "fmin.s, signaling NaN both"); + + // FMAX.S + expect(3.14, []{return F::fmax_s(3.14, 2.718);}, "fmax.s"); + expect(numeric_limits::min(), + []{return F::fmax_s(-numeric_limits::infinity(), + numeric_limits::min());}, + "fmax.s, -infinity"); + expect(numeric_limits::infinity(), + []{return F::fmax_s(numeric_limits::infinity(), + numeric_limits::max());}, + "fmax.s, infinity"); + expect(-1.414, + []{return F::fmax_s(numeric_limits::quiet_NaN(), -1.414);}, + "fmax.s, quiet NaN first"); + expect(2.718, + []{return F::fmax_s(2.718, numeric_limits::quiet_NaN());}, + "fmax.s, quiet NaN second"); + expect(true, []{ + float fd = F::fmax_s(numeric_limits::quiet_NaN(), + numeric_limits::quiet_NaN()); + return F::isquietnan(fd); + }, "fmax.s, quiet NaN both"); + expect(3.14, + []{return F::fmax_s(numeric_limits::signaling_NaN(), + 3.14);}, + "fmax.s, signaling NaN first"); + expect(1.816, []{return F::fmax_s(1.816, + numeric_limits::signaling_NaN());}, + "fmax.s, signaling NaN second"); + expect(true, []{ + float fd = F::fmax_s(numeric_limits::signaling_NaN(), + numeric_limits::signaling_NaN()); + return F::issignalingnan(fd); + }, "fmax.s, signaling NaN both"); + + // FCVT.W.S + expect(256, []{return F::fcvt_w_s(256.3);}, + "fcvt.w.s, truncate positive"); + expect(-256, []{return F::fcvt_w_s(-256.2);}, + "fcvt.w.s, truncate negative"); + expect(0, []{return F::fcvt_w_s(0.0);}, "fcvt.w.s, 0.0"); + expect(0, []{return F::fcvt_w_s(-0.0);}, "fcvt.w.s, -0.0"); + expect(numeric_limits::max(), + []{return F::fcvt_w_s(numeric_limits::max());}, + "fcvt.w.s, overflow"); + expect(0, []{return F::fcvt_w_s(numeric_limits::min());}, + "fcvt.w.s, underflow"); + expect(numeric_limits::max(), + []{return F::fcvt_w_s(numeric_limits::infinity());}, + "fcvt.w.s, infinity"); + expect(numeric_limits::min(), + []{return F::fcvt_w_s(-numeric_limits::infinity());}, + "fcvt.w.s, -infinity"); + expect(numeric_limits::max(), + []{return F::fcvt_w_s(numeric_limits::quiet_NaN());}, + "fcvt.w.s, quiet NaN"); + expect(numeric_limits::max(), + []{return F::fcvt_w_s(-numeric_limits::quiet_NaN());}, + "fcvt.w.s, quiet -NaN"); + expect(numeric_limits::max(), + []{return F::fcvt_w_s(numeric_limits::signaling_NaN());}, + "fcvt.w.s, signaling NaN"); + + // FCVT.WU.S + expect(256, []{return F::fcvt_wu_s(256.3);}, + "fcvt.wu.s, truncate positive"); + expect(0, []{return F::fcvt_wu_s(-256.2);}, + "fcvt.wu.s, truncate negative"); + expect(0, []{return F::fcvt_wu_s(0.0);}, "fcvt.wu.s, 0.0"); + expect(0, []{return F::fcvt_wu_s(-0.0);}, "fcvt.wu.s, -0.0"); + expect(numeric_limits::max(), + []{return F::fcvt_wu_s(numeric_limits::max());}, + "fcvt.wu.s, overflow"); + expect(0, []{return F::fcvt_wu_s(numeric_limits::min());}, + "fcvt.wu.s, underflow"); + expect(numeric_limits::max(), + []{return F::fcvt_wu_s(numeric_limits::infinity());}, + "fcvt.wu.s, infinity"); + expect(0, + []{return F::fcvt_wu_s(-numeric_limits::infinity());}, + "fcvt.wu.s, -infinity"); + expect(0xFFFFFFFFFFFFFFFFULL, + []{return F::fcvt_wu_s(numeric_limits::quiet_NaN());}, + "fcvt.wu.s, quiet NaN"); + expect(0xFFFFFFFFFFFFFFFFULL, + []{return F::fcvt_wu_s(-numeric_limits::quiet_NaN());}, + "fcvt.wu.s, quiet -NaN"); + expect(0xFFFFFFFFFFFFFFFFULL, + []{return F::fcvt_wu_s(numeric_limits::signaling_NaN());}, + "fcvt.wu.s, signaling NaN"); + + // FMV.X.S + expect(0x000000004048F5C3ULL, []{return F::fmv_x_s(3.14);}, + "fmv.x.s, positive"); + expect(0xFFFFFFFFC048F5C3ULL, []{return F::fmv_x_s(-3.14);}, + "fmv.x.s, negative"); + expect(0x0000000000000000ULL, []{return F::fmv_x_s(0.0);}, + "fmv.x.s, 0.0"); + expect(0xFFFFFFFF80000000ULL, []{return F::fmv_x_s(-0.0);}, + "fmv.x.s, -0.0"); + + // FEQ.S + expect(true, []{return F::feq_s(1.414, 1.414);}, "feq.s, equal"); + expect(false, []{return F::feq_s(2.718, 1.816);}, + "feq.s, not equal"); + expect(true, []{return F::feq_s(0.0, -0.0);}, "feq.s, 0 == -0"); + expect(false, + []{return F::feq_s(numeric_limits::quiet_NaN(), -1.0);}, + "feq.s, quiet NaN first"); + expect(false, + []{return F::feq_s(2.0, numeric_limits::quiet_NaN());}, + "feq.s, quiet NaN second"); + expect(false, + []{return F::feq_s(numeric_limits::quiet_NaN(), + numeric_limits::quiet_NaN());}, + "feq.s, quiet NaN both"); + expect(false, + []{return F::feq_s(numeric_limits::signaling_NaN(), -1.0);}, + "feq.s, signaling NaN first"); + expect(false, + []{return F::feq_s(2.0, numeric_limits::signaling_NaN());}, + "feq.s, signaling NaN second"); + expect(false, + []{return F::feq_s(numeric_limits::signaling_NaN(), + numeric_limits::signaling_NaN());}, + "feq.s, signaling NaN both"); + + // FLT.S + expect(false, []{return F::flt_s(1.414, 1.414);}, "flt.s, equal"); + expect(true, []{return F::flt_s(1.816, 2.718);}, "flt.s, less"); + expect(false, []{return F::flt_s(2.718, 1.816);}, "flt.s, greater"); + expect(false, + []{return F::flt_s(numeric_limits::quiet_NaN(), -1.0);}, + "flt.s, quiet NaN first"); + expect(false, + []{return F::flt_s(2.0, numeric_limits::quiet_NaN());}, + "flt.s, quiet NaN second"); + expect(false, + []{return F::flt_s(numeric_limits::quiet_NaN(), + numeric_limits::quiet_NaN());}, + "flt.s, quiet NaN both"); + expect(false, + []{return F::flt_s(numeric_limits::signaling_NaN(), -1.0);}, + "flt.s, signaling NaN first"); + expect(false, + []{return F::flt_s(2.0, numeric_limits::signaling_NaN());}, + "flt.s, signaling NaN second"); + expect(false, + []{return F::flt_s(numeric_limits::signaling_NaN(), + numeric_limits::signaling_NaN());}, + "flt.s, signaling NaN both"); + + // FLE.S + expect(true, []{return F::fle_s(1.414, 1.414);}, "fle.s, equal"); + expect(true, []{return F::fle_s(1.816, 2.718);}, "fle.s, less"); + expect(false, []{return F::fle_s(2.718, 1.816);}, "fle.s, greater"); + expect(true, []{return F::fle_s(0.0, -0.0);}, "fle.s, 0 == -0"); + expect(false, + []{return F::fle_s(numeric_limits::quiet_NaN(), -1.0);}, + "fle.s, quiet NaN first"); + expect(false, + []{return F::fle_s(2.0, numeric_limits::quiet_NaN());}, + "fle.s, quiet NaN second"); + expect(false, + []{return F::fle_s(numeric_limits::quiet_NaN(), + numeric_limits::quiet_NaN());}, + "fle.s, quiet NaN both"); + expect(false, + []{return F::fle_s(numeric_limits::signaling_NaN(), -1.0);}, + "fle.s, signaling NaN first"); + expect(false, + []{return F::fle_s(2.0, numeric_limits::signaling_NaN());}, + "fle.s, signaling NaN second"); + expect(false, + []{return F::fle_s(numeric_limits::signaling_NaN(), + numeric_limits::signaling_NaN());}, + "fle.s, signaling NaN both"); + + // FCLASS.S + expect(0x1, + []{return F::fclass_s(-numeric_limits::infinity());}, + "fclass.s, -infinity"); + expect(0x2, []{return F::fclass_s(-3.14);}, "fclass.s, -normal"); + expect(0x4, []{return F::fclass_s(F::number(0x807FFFFF));}, + "fclass.s, -subnormal"); + expect(0x8, []{return F::fclass_s(-0.0);}, "fclass.s, -0.0"); + expect(0x10, []{return F::fclass_s(0.0);}, "fclass.s, 0.0"); + expect(0x20, []{return F::fclass_s(F::number(0x007FFFFF));}, + "fclass.s, subnormal"); + expect(0x40, []{return F::fclass_s(1.816);}, "fclass.s, normal"); + expect(0x80, + []{return F::fclass_s(numeric_limits::infinity());}, + "fclass.s, infinity"); + expect(0x100, + []{return F::fclass_s(numeric_limits::signaling_NaN());}, + "fclass.s, signaling NaN"); + expect(0x200, + []{return F::fclass_s(numeric_limits::quiet_NaN());}, + "fclass.s, quiet NaN"); + + // FCVT.S.W + expect(0.0, []{return F::fcvt_s_w(0);}, "fcvt.s.w, 0"); + expect(-2147483648.0, + []{return F::fcvt_s_w(numeric_limits::min());}, + "fcvt.s.w, negative"); + expect(255.0, []{return F::fcvt_s_w(0xFFFFFFFF000000FFLL);}, + "fcvt.s.w, truncate"); + + // FCVT.S.WU + expect(0.0, []{return F::fcvt_s_wu(0);}, "fcvt.s.wu, 0"); + expect(2147483648.0, + []{return F::fcvt_s_wu(numeric_limits::min());}, + "fcvt.s.wu"); + expect(255.0, []{return F::fcvt_s_wu(0xFFFFFFFF000000FFLL);}, + "fcvt.s.wu, truncate"); + + // FMV.S.X + expect(numeric_limits::infinity(), + []{return F::fmv_s_x(0x7F800000);}, "fmv.s.x"); + expect(-0.0, []{return F::fmv_s_x(0xFFFFFFFF80000000ULL);}, + "fmv.s.x, truncate"); + + // FCSR functions + int rm = F::frrm(); + expect(0x7, []{ // FSRM + F::fsrm(-1); + return F::frrm(); + }, "fsrm"); + expect(0x1F, []{ // FSFLAGS + F::fsflags(0); + F::fsflags(-1); + return F::frflags(); + }, "fsflags"); + expect(0xFF, []{ // FSCSR + F::fsflags(0); + F::fsrm(0); + F::fscsr(-1); + return F::frcsr(); + }, "fscsr"); + expect(rm << 5, [=]{ + F::fscsr(0); + F::fsrm(rm); + return F::frcsr(); + }, "restore initial round mode"); + + F::fsflags(0); + + // FCVT.L.S + expect(256, []{return F::fcvt_l_s(256.3);}, + "fcvt.l.s, truncate positive"); + expect(-256, []{return F::fcvt_l_s(-256.2);}, + "fcvt.l.s, truncate negative"); + expect(0, []{return F::fcvt_l_s(0.0);}, "fcvt.l.s, 0.0"); + expect(0, []{return F::fcvt_l_s(-0.0);}, "fcvt.l.s, -0.0"); + expect(-8589934592LL, []{return F::fcvt_l_s(-8589934592.0);}, + "fcvt.l.s, 32-bit overflow"); + expect(numeric_limits::max(), + []{return F::fcvt_l_s(numeric_limits::max());}, + "fcvt.l.s, overflow"); + expect(0, []{return F::fcvt_l_s(numeric_limits::min());}, + "fcvt.l.s, underflow"); + expect(numeric_limits::max(), + []{return F::fcvt_l_s(numeric_limits::infinity());}, + "fcvt.l.s, infinity"); + expect(numeric_limits::min(), + []{return F::fcvt_l_s(-numeric_limits::infinity());}, + "fcvt.l.s, -infinity"); + expect(numeric_limits::max(), + []{return F::fcvt_l_s(numeric_limits::quiet_NaN());}, + "fcvt.l.s, quiet NaN"); + expect(numeric_limits::max(), + []{return F::fcvt_l_s(-numeric_limits::quiet_NaN());}, + "fcvt.l.s, quiet -NaN"); + expect(numeric_limits::max(), + []{return F::fcvt_l_s(numeric_limits::signaling_NaN());}, + "fcvt.l.s, signaling NaN"); + + // FCVT.LU.S + expect(256, []{return F::fcvt_lu_s(256.3);}, + "fcvt.lu.s, truncate positive"); + expect(0, []{return F::fcvt_lu_s(-256.2);}, + "fcvt.lu.s, truncate negative"); + expect(0, []{return F::fcvt_lu_s(0.0);}, "fcvt.lu.s, 0.0"); + expect(0, []{return F::fcvt_lu_s(-0.0);}, "fcvt.lu.s, -0.0"); + expect(8589934592LL, + []{return F::fcvt_lu_s(8589934592.0);}, + "fcvt.lu.s, 32-bit overflow"); + expect(numeric_limits::max(), + []{return F::fcvt_lu_s(numeric_limits::max());}, + "fcvt.lu.s, overflow"); + expect(0, []{return F::fcvt_lu_s(numeric_limits::min());}, + "fcvt.lu.s, underflow"); + expect(numeric_limits::max(), + []{return F::fcvt_lu_s(numeric_limits::infinity());}, + "fcvt.lu.s, infinity"); + expect(0, + []{return F::fcvt_lu_s(-numeric_limits::infinity());}, + "fcvt.lu.s, -infinity"); + expect(0xFFFFFFFFFFFFFFFFULL, + []{return F::fcvt_lu_s(numeric_limits::quiet_NaN());}, + "fcvt.lu.s, quiet NaN"); + expect(0xFFFFFFFFFFFFFFFFULL, + []{return F::fcvt_lu_s(-numeric_limits::quiet_NaN());}, + "fcvt.lu.s, quiet -NaN"); + expect(0xFFFFFFFFFFFFFFFFULL, + []{return F::fcvt_lu_s(numeric_limits::signaling_NaN());}, + "fcvt.lu.s, signaling NaN"); + + // FCVT.S.L + expect(0.0, []{return F::fcvt_s_l(0);}, "fcvt.s.l, 0"); + expect(-9.223372e18, + []{return F::fcvt_s_l(numeric_limits::min());}, + "fcvt.s.l, negative"); + expect(-4.29496704e9, []{return F::fcvt_s_l(0xFFFFFFFF000000FFLL);}, + "fcvt.s.l, 32-bit truncate"); + + // FCVT.S.LU + expect(0.0, []{return F::fcvt_s_lu(0);}, "fcvt.s.lu, 0"); + expect(9.223372e18, + []{return F::fcvt_s_lu(numeric_limits::min());}, + "fcvt.s.lu"); + expect(1.8446744e19, []{return F::fcvt_s_lu(0xFFFFFFFF000000FFLL);}, + "fcvt.s.lu, 32-bit truncate"); + + return 0; +} diff --git a/tests/test-progs/insttest/src/riscv/rv64f.h b/tests/test-progs/insttest/src/riscv/rv64f.h new file mode 100644 index 000000000..5a6798cc6 --- /dev/null +++ b/tests/test-progs/insttest/src/riscv/rv64f.h @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2016 The University of Virginia + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Alec Roelke + */ + +#pragma once + +#include +#include + +#include "insttest.h" + +namespace F +{ + +constexpr inline uint32_t +bits(float f) +{ + return reinterpret_cast(f); +} + +constexpr inline float +number(uint32_t b) +{ + return reinterpret_cast(b); +} + +inline bool +isquietnan(float f) +{ + return std::isnan(f) && (bits(f)&0x00400000) != 0; +} + +inline bool +issignalingnan(float f) +{ + return std::isnan(f) && (bits(f)&0x00400000) == 0; +} + +inline float +load(float mem) +{ + float fd = std::numeric_limits::signaling_NaN(); + asm volatile("flw %0,%1" + : "=f" (fd) + : "m" (mem)); + return fd; +} + +inline float +store(float fs) +{ + float mem = std::numeric_limits::signaling_NaN(); + asm volatile("fsw %1,%0" : "=m" (mem) : "f" (fs)); + return mem; +} + +inline uint64_t +frflags() +{ + uint64_t rd = -1; + asm volatile("frflags %0" : "=r" (rd)); + return rd; +} + +inline uint64_t +fsflags(uint64_t rs1) +{ + uint64_t rd = -1; + asm volatile("fsflags %0,%1" : "=r" (rd) : "r" (rs1)); + return rd; +} + +inline float +fmadd_s(float fs1, float fs2, float fs3) +{ + float fd = std::numeric_limits::signaling_NaN(); + FR4OP("fmadd.s", fd, fs1, fs2, fs3); + return fd; +} + +inline float +fmsub_s(float fs1, float fs2, float fs3) +{ + float fd = std::numeric_limits::signaling_NaN(); + FR4OP("fmsub.s", fd, fs1, fs2, fs3); + return fd; +} + +inline float +fnmsub_s(float fs1, float fs2, float fs3) +{ + float fd = std::numeric_limits::signaling_NaN(); + FR4OP("fnmsub.s", fd, fs1, fs2, fs3); + return fd; +} + +inline float +fnmadd_s(float fs1, float fs2, float fs3) +{ + float fd = std::numeric_limits::signaling_NaN(); + FR4OP("fnmadd.s", fd, fs1, fs2, fs3); + return fd; +} + +inline float +fadd_s(float fs1, float fs2) +{ + float fd = std::numeric_limits::signaling_NaN(); + FROP("fadd.s", fd, fs1, fs2); + return fd; +} + +inline float +fsub_s(float fs1, float fs2) +{ + float fd = std::numeric_limits::signaling_NaN(); + FROP("fsub.s", fd, fs1, fs2); + return fd; +} + +inline float +fmul_s(float fs1, float fs2) +{ + float fd = std::numeric_limits::signaling_NaN(); + FROP("fmul.s", fd, fs1, fs2); + return fd; +} + +inline float +fdiv_s(float fs1, float fs2) +{ + + float fd = 0.0; + FROP("fdiv.s", fd, fs1, fs2); + return fd; +} + +inline float +fsqrt_s(float fs1) +{ + float fd = std::numeric_limits::infinity(); + asm volatile("fsqrt.s %0,%1" : "=f" (fd) : "f" (fs1)); + return fd; +} + +inline float +fsgnj_s(float fs1, float fs2) +{ + float fd = std::numeric_limits::signaling_NaN(); + FROP("fsgnj.s", fd, fs1, fs2); + return fd; +} + +inline float +fsgnjn_s(float fs1, float fs2) +{ + float fd = std::numeric_limits::signaling_NaN(); + FROP("fsgnjn.s", fd, fs1, fs2); + return fd; +} + +inline float +fsgnjx_s(float fs1, float fs2) +{ + float fd = std::numeric_limits::signaling_NaN(); + FROP("fsgnjx.s", fd, fs1, fs2); + return fd; +} + +inline float +fmin_s(float fs1, float fs2) +{ + float fd = std::numeric_limits::signaling_NaN(); + FROP("fmin.s", fd, fs1, fs2); + return fd; +} + +inline float +fmax_s(float fs1, float fs2) +{ + float fd = std::numeric_limits::signaling_NaN(); + FROP("fmax.s", fd, fs1, fs2); + return fd; +} + +inline int64_t +fcvt_w_s(float fs1) +{ + int64_t rd = 0; + asm volatile("fcvt.w.s %0,%1" : "=r" (rd) : "f" (fs1)); + return rd; +} + +inline uint64_t +fcvt_wu_s(float fs1) +{ + uint64_t rd = 0; + asm volatile("fcvt.wu.s %0,%1" : "=r" (rd) : "f" (fs1)); + return rd; +} + +inline uint64_t +fmv_x_s(float fs1) +{ + uint64_t rd = 0; + asm volatile("fmv.x.s %0,%1" : "=r" (rd) : "f" (fs1)); + return rd; +} + +inline bool +feq_s(float fs1, float fs2) +{ + bool rd = false; + asm volatile("feq.s %0,%1,%2" : "=r" (rd) : "f" (fs1), "f" (fs2)); + return rd; +} + +inline bool +flt_s(float fs1, float fs2) +{ + bool rd = false; + asm volatile("flt.s %0,%1,%2" : "=r" (rd) : "f" (fs1), "f" (fs2)); + return rd; +} + +inline bool +fle_s(float fs1, float fs2) +{ + bool rd = false; + asm volatile("fle.s %0,%1,%2" : "=r" (rd) : "f" (fs1), "f" (fs2)); + return rd; +} + +inline uint64_t +fclass_s(float fs1) +{ + uint64_t rd = -1; + asm volatile("fclass.s %0,%1" : "=r" (rd) : "f" (fs1)); + return rd; +} + +inline float +fcvt_s_w(int64_t rs1) +{ + float fd = std::numeric_limits::signaling_NaN(); + asm volatile("fcvt.s.w %0,%1" : "=f" (fd) : "r" (rs1)); + return fd; +} + +inline float +fcvt_s_wu(uint64_t rs1) +{ + float fd = std::numeric_limits::signaling_NaN(); + asm volatile("fcvt.s.wu %0,%1" : "=f" (fd) : "r" (rs1)); + return fd; +} + +inline float +fmv_s_x(uint64_t rs1) +{ + float fd = std::numeric_limits::signaling_NaN(); + asm volatile("fmv.s.x %0,%1" : "=f" (fd) : "r" (rs1)); + return fd; +} + +inline uint64_t +frcsr() +{ + uint64_t rd = -1; + asm volatile("frcsr %0" : "=r" (rd)); + return rd; +} + +inline uint64_t +frrm() +{ + uint64_t rd = -1; + asm volatile("frrm %0" : "=r" (rd)); + return rd; +} + +inline uint64_t +fscsr(uint64_t rs1) +{ + uint64_t rd = -1; + asm volatile("fscsr %0,%1" : "=r" (rd) : "r" (rs1)); + return rd; +} + +inline uint64_t +fsrm(uint64_t rs1) +{ + uint64_t rd = -1; + asm volatile("fsrm %0,%1" : "=r" (rd) : "r" (rs1)); + return rd; +} + +inline int64_t +fcvt_l_s(float fs1) +{ + int64_t rd = 0; + asm volatile("fcvt.l.s %0,%1" : "=r" (rd) : "f" (fs1)); + return rd; +} + +inline uint64_t +fcvt_lu_s(float fs1) +{ + + int64_t rd = 0; + asm volatile("fcvt.lu.s %0,%1" : "=r" (rd) : "f" (fs1)); + return rd; +} + +inline float +fcvt_s_l(int64_t rs1) +{ + float fd = std::numeric_limits::signaling_NaN(); + asm volatile("fcvt.s.l %0,%1" : "=f" (fd) : "r" (rs1)); + return fd; +} + +inline float +fcvt_s_lu(uint64_t rs1) +{ + float fd = std::numeric_limits::signaling_NaN(); + asm volatile("fcvt.s.lu %0,%1" : "=f" (fd) : "r" (rs1)); + return fd; +} + +} // namespace F diff --git a/tests/test-progs/insttest/src/riscv/rv64i.cpp b/tests/test-progs/insttest/src/riscv/rv64i.cpp new file mode 100644 index 000000000..95e8ee02a --- /dev/null +++ b/tests/test-progs/insttest/src/riscv/rv64i.cpp @@ -0,0 +1,432 @@ +/* + * Copyright (c) 2016 The University of Virginia + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Alec Roelke + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "insttest.h" +#include "rv64i.h" + +int main() +{ + using namespace std; + using namespace insttest; + + // LUI + expect(4096, []{return I::lui(1);}, "lui"); + expect(numeric_limits::min(), + []{return I::lui(0x80000);}, "lui, negative"); + + // AUIPC + expect(true, []{return I::auipc(3);}, "auipc"); + + // Jump (JAL, JALR) + expect(true, []{return I::jal();}, "jal"); + expect(true, []{return I::jalr();}, "jalr"); + + // BEQ + expect(true, []{return I::beq(5, 5);}, "beq, equal"); + expect(false, []{return I::beq(numeric_limits::max(), + numeric_limits::min());}, "beq, not equal"); + + // BNE + expect(false, []{return I::bne(5, 5);}, "bne, equal"); + expect(true, []{return I::bne(numeric_limits::max(), + numeric_limits::min());}, "bne, not equal"); + + // BLT + expect(true, []{return I::blt(numeric_limits::min(), + numeric_limits::max());}, "blt, less"); + expect(false, []{return I::blt(numeric_limits::min(), + numeric_limits::min());}, "blt, equal"); + expect(false, []{return I::blt(numeric_limits::max(), + numeric_limits::min());}, "blt, greater"); + + // BGE + expect(false, []{return I::bge(numeric_limits::min(), + numeric_limits::max());}, "bge, less"); + expect(true, []{return I::bge(numeric_limits::min(), + numeric_limits::min());}, "bge, equal"); + expect(true, []{return I::bge(numeric_limits::max(), + numeric_limits::min());}, "bge, greater"); + + // BLTU + expect(true, []{return I::blt(numeric_limits::min(), + numeric_limits::max());}, "bltu, greater"); + expect(false, []{return I::blt(numeric_limits::min(), + numeric_limits::min());}, "bltu, equal"); + expect(false, []{return I::blt(numeric_limits::max(), + numeric_limits::min());}, "bltu, less"); + + // BGEU + expect(false, []{return I::bge(numeric_limits::min(), + numeric_limits::max());}, "bgeu, greater"); + expect(true, []{return I::bge(numeric_limits::min(), + numeric_limits::min());}, "bgeu, equal"); + expect(true, []{return I::bge(numeric_limits::max(), + numeric_limits::min());}, "bgeu, less"); + + // Load (LB, LH, LW, LBU, LHU) + expect(7, []{return I::load(0x07);}, + "lb, positive"); + expect(numeric_limits::min(), + []{return I::load(0x80);}, "lb, negative"); + expect(1792, []{return I::load(0x0700);}, + "lh, positive"); + expect(numeric_limits::min(), + []{return I::load(0x8000);}, "lh, negative"); + expect(458752, []{return I::load(0x00070000);}, + "lw, positive"); + expect(numeric_limits::min(), + []{return I::load(0x80000000);}, + "lw, negative"); + expect(128, []{return I::load(0x80);}, "lbu"); + expect(32768, []{return I::load(0x8000);}, + "lhu"); + + // Store (SB, SH, SW) + expect(0xFF, []{return I::store(-1);}, "sb"); + expect(0xFFFF, []{return I::store(-1);}, "sh"); + expect(0xFFFFFFFF, []{return I::store(-1);}, "sw"); + + // ADDI + expect(1073742078, []{return I::addi(0x3FFFFFFF, 255);}, + "addi"); + expect(1, []{return I::addi(-1, 2);}, "addi, overflow"); + + // SLTI + expect(true, []{return I::slti(-1, 0);}, "slti, true"); + expect(false, []{return I::slti(0, -1);}, "slti, false"); + + // SLTIU + expect(false, []{return I::sltiu(-1, 0);}, "sltiu, false"); + expect(true, []{return I::sltiu(0, -1);}, "sltiu, true"); + + // XORI + expect(0xFF, []{return I::xori(0xAA, 0x55);}, "xori (1)"); + expect(0, []{return I::xori(0xAA, 0xAA);}, "xori (0)"); + + // ORI + expect(0xFF, []{return I::ori(0xAA, 0x55);}, "ori (1)"); + expect(0xAA, []{return I::ori(0xAA, 0xAA);}, "ori (A)"); + + // ANDI + expect(0, []{return I::andi(-1, 0);}, "andi (0)"); + expect(0x1234567812345678ULL, + []{return I::andi(0x1234567812345678ULL, -1);}, "andi (1)"); + + // SLLI + expect(65280, []{return I::slli(255, 8);}, "slli, general"); + expect(numeric_limits::min(), + []{return I::slli(255, 63);}, "slli, erase"); + + // SRLI + expect(255, []{return I::srli(65280, 8);}, "srli, general"); + expect(0, []{return I::srli(255, 8);}, "srli, erase"); + expect(1, []{return I::srli(numeric_limits::min(), 63);}, + "srli, negative"); + + // SRAI + expect(255, []{return I::srai(65280, 8);}, "srai, general"); + expect(0, []{return I::srai(255, 8);}, "srai, erase"); + expect(-1, + []{return I::srai(numeric_limits::min(), 63);}, + "srai, negative"); + + // ADD + expect(1073742078, []{return I::add(0x3FFFFFFF, 255);}, "add"); + expect(-1, + []{return I::add(0x7FFFFFFFFFFFFFFFLL, 0x8000000000000000LL);}, + "add, overflow"); + + // SUB + expect(65535, []{return I::sub(65536, 1);}, "sub"); + expect(-1, + []{return I::sub(0x7FFFFFFFFFFFFFFFLL, 0x8000000000000000LL);}, + "sub, \"overflow\""); + + // SLL + expect(65280, []{return I::sll(255, 8);}, "sll, general"); + expect(numeric_limits::min(), + []{return I::sll(255, 63);}, "sll, erase"); + + // SLT + expect(true, []{return I::slt(-1, 0);}, "slt, true"); + expect(false, []{return I::slt(0, -1);}, "slt, false"); + + // SLTU + expect(false, []{return I::sltu(-1, 0);}, "sltu, false"); + expect(true, []{return I::sltu(0, -1);}, "sltu, true"); + + // XOR + expect(-1, + []{return I::xor_inst(0xAAAAAAAAAAAAAAAAULL, + 0x5555555555555555ULL);}, + "xor (1)"); + expect(0, + []{return I::xor_inst(0xAAAAAAAAAAAAAAAAULL, + 0xAAAAAAAAAAAAAAAAULL);}, + "xor (0)"); + + // SRL + expect(255, []{return I::srl(65280, 8);}, "srl, general"); + expect(0, []{return I::srl(255, 8);}, "srl, erase"); + expect(1, []{return I::srl(numeric_limits::min(), 63);}, + "srl, negative"); + + // SRA + expect(255, []{return I::sra(65280, 8);}, "sra, general"); + expect(0, []{return I::sra(255, 8);}, "sra, erase"); + expect(-1, []{return I::sra(numeric_limits::min(), 63);}, + "sra, negative"); + + // OR + expect(-1, + []{return I::or_inst(0xAAAAAAAAAAAAAAAAULL, + 0x5555555555555555ULL);}, + "or (1)"); + expect(0xAAAAAAAAAAAAAAAAULL, + []{return I::or_inst(0xAAAAAAAAAAAAAAAAULL, + 0xAAAAAAAAAAAAAAAAULL);}, + "or (A)"); + + // AND + expect(0, []{return I::and_inst(-1, 0);}, "and (0)"); + expect(0x1234567812345678ULL, + []{return I::and_inst(0x1234567812345678ULL, -1);}, "and (-1)"); + + // FENCE/FENCE.I + asm volatile("fence" : : ); + asm volatile("fence.i" : : ); + + // ECALL + char fname[] = "test.txt"; + char teststr[] = "this is a test"; + expect(true, [=]{ + int fd = open(fname, O_CREAT | O_WRONLY | O_TRUNC, 0644); + if (fd < 0) { + return false; + } + size_t n = write(fd, teststr, sizeof(teststr)); + cout << "Bytes written: " << n << endl; + return close(fd) >= 0 && n > 0; + }, "open, write"); + expect(0, [=]{return access(fname, F_OK);}, "access F_OK"); + expect(0, [=]{return access(fname, R_OK);}, "access R_OK"); + expect(0, [=]{return access(fname, W_OK);}, "access W_OK"); + // gem5's implementation of access is incorrect; it should return + // -1 on failure, not -errno. Account for this using an inequality. + expect(true, [=]{return access(fname, X_OK) != 0;}, "access X_OK"); + expect(true, [=]{ + struct stat stat_buf, fstat_buf; + int s = stat(fname, &stat_buf); + if (s < 0) { + return false; + } else { + cout << "stat:" << endl; + cout << "\tst_dev =\t" << stat_buf.st_dev << endl; + cout << "\tst_ino =\t" << stat_buf.st_ino << endl; + cout << "\tst_mode =\t" << stat_buf.st_mode << endl; + cout << "\tst_nlink =\t" << stat_buf.st_nlink << endl; + cout << "\tst_uid =\t" << stat_buf.st_uid << endl; + cout << "\tst_gid =\t" << stat_buf.st_gid << endl; + cout << "\tst_rdev =\t" << stat_buf.st_rdev << endl; + cout << "\tst_size =\t" << stat_buf.st_size << endl; + cout << "\tst_blksize =\t" << stat_buf.st_blksize << endl; + cout << "\tst_blocks =\t" << stat_buf.st_blocks << endl; + } + int fd = open(fname, O_RDONLY); + if (fd < 0) { + return false; + } + int f = fstat(fd, &fstat_buf); + if (f >= 0) { + cout << "fstat:" << endl; + cout << "\tst_dev =\t" << fstat_buf.st_dev << endl; + cout << "\tst_ino =\t" << fstat_buf.st_ino << endl; + cout << "\tst_mode =\t" << fstat_buf.st_mode << endl; + cout << "\tst_nlink =\t" << fstat_buf.st_nlink << endl; + cout << "\tst_uid =\t" << fstat_buf.st_uid << endl; + cout << "\tst_gid =\t" << fstat_buf.st_gid << endl; + cout << "\tst_rdev =\t" << fstat_buf.st_rdev << endl; + cout << "\tst_size =\t" << fstat_buf.st_size << endl; + cout << "\tst_blksize =\t" << fstat_buf.st_blksize << endl; + cout << "\tst_blocks =\t" << fstat_buf.st_blocks << endl; + } + return close(fd) >= 0 && f >= 0; + }, "open, stat"); + expect(true, [=]{ + int fd = open(fname, O_RDONLY); + if (fd < 0) { + return false; + } + char in[128]; + size_t n = read(fd, in, sizeof(in)); + cout << "Bytes read: " << n << endl; + cout << "String read: " << in << endl; + int cl = close(fd); + int un = unlink(fname); + return n > 0 && cl >= 0 && un >= 0 && strcmp(teststr, in) == 0; + }, "open, read, unlink"); + expect(true, []{ + struct tms buf; + clock_t t = times(&buf); + cout << "times:" << endl; + cout << "\ttms_utime =\t" << buf.tms_utime << endl; + cout << "\ttms_stime =\t" << buf.tms_stime << endl; + cout << "\ttms_cutime =\t" << buf.tms_cutime << endl; + cout << "\ttms_cstime =\t" << buf.tms_cstime << endl; + return t > 0; + }, "times"); + expect(0, []{ + struct timeval time; + int res = gettimeofday(&time, nullptr); + cout << "timeval:" << endl; + cout << "\ttv_sec =\t" << time.tv_sec << endl; + cout << "\ttv_usec =\t" << time.tv_usec << endl; + return res; + }, "gettimeofday"); + + // EBREAK not tested because it only makes sense in FS mode or when + // using gdb + + // ERET not tested because it only makes sense in FS mode and will cause + // a panic when used in SE mode + + // CSRs (RDCYCLE, RDTIME, RDINSTRET) + expect(true, []{ + uint64_t cycles = 0; + asm("rdcycle %0" : "=r" (cycles)); + cout << "Cycles: " << cycles << endl; + return cycles > 0; + }, "rdcycle"); + expect(true, []{ + uint64_t time = 0; + asm("rdtime %0" : "=r" (time)); + cout << "Time: " << time << endl; + return time > 0; + }, "rdtime"); + expect(true, []{ + uint64_t instret = 0; + asm("rdinstret %0" : "=r" (instret)); + cout << "Instructions Retired: " << instret << endl; + return instret > 0; + }, "rdinstret"); + + // 64-bit memory (LWU, LD, SD) + expect(0xFFFFFFFF, []{return I::load(-1);}, + "lwu"); + expect(30064771072, + []{return I::load(30064771072);}, "ld"); + expect(-1, []{return I::store(-1);}, "sd"); + + // ADDIW + expect(268435710, []{return I::addiw(0x0FFFFFFF, 255);}, "addiw"); + expect(-2147481602, []{return I::addiw(0x7FFFFFFF, 0x7FF);}, + "addiw, overflow"); + expect(0, []{return I::addiw(0x7FFFFFFFFFFFFFFFLL, 1);}, + "addiw, truncate"); + + // SLLIW + expect(65280, []{return I::slliw(255, 8);}, "slliw, general"); + expect(numeric_limits::min(), + []{return I::slliw(255, 31);}, "slliw, erase"); + expect(numeric_limits::min(), + []{return I::slliw(0xFFFFFFFF00800000LL, 8);}, "slliw, truncate"); + + // SRLIW + expect(255, []{return I::srliw(65280, 8);}, "srliw, general"); + expect(0, []{return I::srliw(255, 8);}, "srliw, erase"); + expect(1, + []{return I::srliw(numeric_limits::min(), 31);}, + "srliw, negative"); + expect(1, []{return I::srliw(0xFFFFFFFF80000000LL, 31);}, + "srliw, truncate"); + + // SRAIW + expect(255, []{return I::sraiw(65280, 8);}, "sraiw, general"); + expect(0, []{return I::sraiw(255, 8);}, "sraiw, erase"); + expect(-1, + []{return I::sraiw(numeric_limits::min(), 31);}, + "sraiw, negative"); + expect(-1, []{return I::sraiw(0x0000000180000000LL, 31);}, + "sraiw, truncate"); + + // ADDW + expect(1073742078, []{return I::addw(0x3FFFFFFF, 255);}, "addw"); + expect(-1, []{return I::addw(0x7FFFFFFF, 0x80000000);}, + "addw, overflow"); + expect(65536, []{return I::addw(0xFFFFFFFF0000FFFFLL, 1);}, + "addw, truncate"); + + // SUBW + expect(65535, []{return I::subw(65536, 1);}, "subw"); + expect(-1, []{return I::subw(0x7FFFFFFF, 0x80000000);}, + "subw, \"overflow\""); + expect(0, + []{return I::subw(0xAAAAAAAAFFFFFFFFULL, 0x55555555FFFFFFFFULL);}, + "subw, truncate"); + + // SLLW + expect(65280, []{return I::sllw(255, 8);}, "sllw, general"); + expect(numeric_limits::min(), + []{return I::sllw(255, 31);}, "sllw, erase"); + expect(numeric_limits::min(), + []{return I::sllw(0xFFFFFFFF00008000LL, 16);}, "sllw, truncate"); + + // SRLW + expect(255, []{return I::srlw(65280, 8);}, "srlw, general"); + expect(0, []{return I::srlw(255, 8);}, "srlw, erase"); + expect(1, + []{return I::srlw(numeric_limits::min(), 31);}, + "srlw, negative"); + expect(1, []{return I::srlw(0x0000000180000000LL, 31);}, + "srlw, truncate"); + + // SRAW + expect(255, []{return I::sraw(65280, 8);}, "sraw, general"); + expect(0, []{return I::sraw(255, 8);}, "sraw, erase"); + expect(-1, + []{return I::sraw(numeric_limits::min(), 31);}, + "sraw, negative"); + expect(1, []{return I::sraw(0xFFFFFFFF40000000LL, 30);}, + "sraw, truncate"); + + return 0; +} diff --git a/tests/test-progs/insttest/src/riscv/rv64i.h b/tests/test-progs/insttest/src/riscv/rv64i.h new file mode 100644 index 000000000..198fb367c --- /dev/null +++ b/tests/test-progs/insttest/src/riscv/rv64i.h @@ -0,0 +1,440 @@ +/* + * Copyright (c) 2016 The University of Virginia + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Alec Roelke + */ + +#pragma once + +#include +#include + +#include "insttest.h" + +namespace I +{ + +inline uint64_t +lui(const uint32_t imm) +{ + int64_t rd = -1; + asm volatile("lui %0,%1" : "=r" (rd) : "i" (imm)); + return rd; +} + +inline bool +auipc(const uint64_t imm) +{ + int64_t rd = -1; + asm volatile("auipc %0,%1" : "=r" (rd) : "i" (imm)); + std::cout << "auipc: 0x" << std::hex << std::uppercase << rd << + std::nouppercase << std::dec << std::endl; + return rd >= imm; +} + +inline bool +jal() +{ + asm volatile goto("jal zero,%l[jallabel]" : : : : jallabel); + return false; + jallabel: + return true; +} + +inline bool +jalr() +{ + int a = 0; + asm volatile("auipc %0,0;" + "jalr t0,%0,12;" + "addi %0,zero,0;" + "sub %0,t0,%0;" + : "+r" (a) + : + : "t0"); + return a == 8; +} + +inline bool +beq(int64_t a, int64_t b) +{ + asm volatile goto("beq %0,%1,%l[beqlabel]" + : + : "r" (a), "r" (b) + : + : beqlabel); + return false; + beqlabel: + return true; +} + +inline bool +bne(int64_t a, int64_t b) +{ + asm volatile goto("bne %0,%1,%l[bnelabel]" + : + : "r" (a), "r" (b) + : + : bnelabel); + return false; + bnelabel: + return true; +} + +inline bool +blt(int64_t a, int64_t b) +{ + asm volatile goto("blt %0,%1,%l[bltlabel]" + : + : "r" (a), "r" (b) + : + : bltlabel); + return false; + bltlabel: + return true; +} + +inline bool +bge(int64_t a, int64_t b) +{ + asm volatile goto("bge %0,%1,%l[bgelabel]" + : + : "r" (a), "r" (b) + : + : bgelabel); + return false; + bgelabel: + return true; +} + +inline bool +bltu(uint64_t a, uint64_t b) +{ + asm volatile goto("bltu %0,%1,%l[bltulabel]" + : + : "r" (a), "r" (b) + : + : bltulabel); + return false; + bltulabel: + return true; +} + +inline bool +bgeu(uint64_t a, uint64_t b) +{ + asm volatile goto("bgeu %0,%1,%l[bgeulabel]" + : + : "r" (a), "r" (b) + : + : bgeulabel); + return false; + bgeulabel: + return true; +} + +template inline R +load(const M& b) +{ + R a = 0; + switch(sizeof(M)) + { + case 1: + if (std::is_signed::value) { + asm volatile("lb %0,%1" : "=r" (a) : "m" (b)); + } else { + asm volatile("lbu %0,%1" : "=r" (a) : "m" (b)); + } + break; + case 2: + if (std::is_signed::value) { + asm volatile("lh %0,%1" : "=r" (a) : "m" (b)); + } else { + asm volatile("lhu %0,%1" : "=r" (a) : "m" (b)); + } + break; + case 4: + if (std::is_signed::value) { + asm volatile("lw %0,%1" : "=r" (a) : "m" (b)); + } else { + asm volatile("lwu %0,%1" : "=r" (a) : "m" (b)); + } + break; + case 8: + asm volatile("ld %0,%1" : "=r" (a) : "m" (b)); + break; + } + return a; +} + +template inline M +store(const M& rs2) +{ + M mem = 0; + switch (sizeof(M)) + { + case 1: + asm volatile("sb %1,%0" : "=m" (mem) : "r" (rs2)); + break; + case 2: + asm volatile("sh %1,%0" : "=m" (mem) : "r" (rs2)); + break; + case 4: + asm volatile("sw %1,%0" : "=m" (mem) : "r" (rs2)); + break; + case 8: + asm volatile("sd %1,%0" : "=m" (mem) : "r" (rs2)); + break; + } + return mem; +} + +inline int64_t +addi(int64_t rs1, const int16_t imm) +{ + int64_t rd = 0; + IOP("addi", rd, rs1, imm); + return rd; +} + +inline bool +slti(int64_t rs1, const int16_t imm) +{ + bool rd = false; + IOP("slti", rd, rs1, imm); + return rd; +} + +inline bool +sltiu(uint64_t rs1, const uint16_t imm) +{ + bool rd = false; + IOP("sltiu", rd, rs1, imm); + return rd; +} + +inline uint64_t +xori(uint64_t rs1, const uint16_t imm) +{ + uint64_t rd = 0; + IOP("xori", rd, rs1, imm); + return rd; +} + +inline uint64_t +ori(uint64_t rs1, const uint16_t imm) +{ + uint64_t rd = 0; + IOP("ori", rd, rs1, imm); + return rd; +} + +inline uint64_t +andi(uint64_t rs1, const uint16_t imm) +{ + uint64_t rd = 0; + IOP("andi", rd, rs1, imm); + return rd; +} + +inline int64_t +slli(int64_t rs1, const uint16_t imm) +{ + int64_t rd = 0; + IOP("slli", rd, rs1, imm); + return rd; +} + +inline uint64_t +srli(uint64_t rs1, const uint16_t imm) +{ + uint64_t rd = 0; + IOP("srli", rd, rs1, imm); + return rd; +} + +inline int64_t +srai(int64_t rs1, const uint16_t imm) +{ + int64_t rd = 0; + IOP("srai", rd, rs1, imm); + return rd; +} + +inline int64_t +add(int64_t rs1, int64_t rs2) +{ + int64_t rd = 0; + ROP("add", rd, rs1, rs2); + return rd; +} + +inline int64_t +sub(int64_t rs1, int64_t rs2) +{ + int64_t rd = 0; + ROP("sub", rd, rs1, rs2); + return rd; +} + +inline int64_t +sll(int64_t rs1, int64_t rs2) +{ + int64_t rd = 0; + ROP("sll", rd, rs1, rs2); + return rd; +} + +inline bool +slt(int64_t rs1, int64_t rs2) +{ + bool rd = false; + ROP("slt", rd, rs1, rs2); + return rd; +} + +inline bool +sltu(uint64_t rs1, uint64_t rs2) +{ + bool rd = false; + ROP("sltu", rd, rs1, rs2); + return rd; +} + +inline uint64_t +xor_inst(uint64_t rs1, uint64_t rs2) +{ + uint64_t rd = 0; + ROP("xor", rd, rs1, rs2); + return rd; +} + +inline uint64_t +srl(uint64_t rs1, uint64_t rs2) +{ + uint64_t rd = 0; + ROP("srl", rd, rs1, rs2); + return rd; +} + +inline int64_t +sra(int64_t rs1, int64_t rs2) +{ + int64_t rd = 0; + ROP("sra", rd, rs1, rs2); + return rd; +} + +inline uint64_t +or_inst(uint64_t rs1, uint64_t rs2) +{ + uint64_t rd = 0; + ROP("or", rd, rs1, rs2); + return rd; +} + +inline uint64_t +and_inst(uint64_t rs1, uint64_t rs2) +{ + uint64_t rd = 0; + ROP("and", rd, rs1, rs2); + return rd; +} + +inline int64_t +addiw(int64_t rs1, const int16_t imm) +{ + int64_t rd = 0; + IOP("addiw", rd, rs1, imm); + return rd; +} + +inline int64_t +slliw(int64_t rs1, const uint16_t imm) +{ + int64_t rd = 0; + IOP("slliw", rd, rs1, imm); + return rd; +} + +inline uint64_t +srliw(uint64_t rs1, const uint16_t imm) +{ + uint64_t rd = 0; + IOP("srliw", rd, rs1, imm); + return rd; +} + +inline int64_t +sraiw(int64_t rs1, const uint16_t imm) +{ + int64_t rd = 0; + IOP("sraiw", rd, rs1, imm); + return rd; +} + +inline int64_t +addw(int64_t rs1, int64_t rs2) +{ + int64_t rd = 0; + ROP("addw", rd, rs1, rs2); + return rd; +} + +inline int64_t +subw(int64_t rs1, int64_t rs2) +{ + int64_t rd = 0; + ROP("subw", rd, rs1, rs2); + return rd; +} + +inline int64_t +sllw(int64_t rs1, int64_t rs2) +{ + int64_t rd = 0; + ROP("sllw", rd, rs1, rs2); + return rd; +} + +inline uint64_t +srlw(uint64_t rs1, uint64_t rs2) +{ + uint64_t rd = 0; + ROP("srlw", rd, rs1, rs2); + return rd; +} + +inline int64_t +sraw(int64_t rs1, int64_t rs2) +{ + int64_t rd = 0; + ROP("sraw", rd, rs1, rs2); + return rd; +} + +} // namespace I diff --git a/tests/test-progs/insttest/src/riscv/rv64m.cpp b/tests/test-progs/insttest/src/riscv/rv64m.cpp new file mode 100644 index 000000000..836d771a1 --- /dev/null +++ b/tests/test-progs/insttest/src/riscv/rv64m.cpp @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2016 The University of Virginia + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Alec Roelke + */ + +#include +#include + +#include "insttest.h" +#include "rv64m.h" + +int main() +{ + using namespace std; + using namespace insttest; + + // MUL + expect(39285, []{return M::mul(873, 45);}, "mul"); + expect(0, []{return M::mul(0x4000000000000000LL, 4);}, + "mul, overflow"); + + // MULH + expect(1, []{return M::mulh(0x4000000000000000LL, 4);}, "mulh"); + expect(-1, []{return M::mulh(numeric_limits::min(), 2);}, + "mulh, negative"); + expect(0, []{return M::mulh(-1, -1);}, "mulh, all bits set"); + + // MULHSU + expect(-1, []{return M::mulhsu(-1, -1);}, "mulhsu, all bits set"); + expect(-1, + []{return M::mulhsu(numeric_limits::min(), 2);},\ + "mulhsu"); + + // MULHU + expect(1, []{return M::mulhu(0x8000000000000000ULL, 2);}, + "mulhu"); + expect(0xFFFFFFFFFFFFFFFEULL, []{return M::mulhu(-1, -1);}, + "mulhu, all bits set"); + + // DIV + expect(-7, []{return M::div(-59, 8);}, "div"); + expect(-1, []{return M::div(255, 0);}, "div/0"); + expect(numeric_limits::min(), + []{return M::div(numeric_limits::min(), -1);}, + "div, overflow"); + + // DIVU + expect(2305843009213693944LL, []{return M::divu(-59, 8);}, + "divu"); + expect(numeric_limits::max(), + []{return M::divu(255, 0);}, "divu/0"); + expect(0, + []{return M::divu(numeric_limits::min(), -1);}, + "divu, \"overflow\""); + + // REM + expect(-3, []{return M::rem(-59, 8);}, "rem"); + expect(255, []{return M::rem(255, 0);}, "rem/0"); + expect(0, []{return M::rem(numeric_limits::min(), -1);}, + "rem, overflow"); + + // REMU + expect(5, []{return M::remu(-59, 8);}, "remu"); + expect(255, []{return M::remu(255, 0);}, "remu/0"); + expect(0x8000000000000000ULL, + []{return M::remu(0x8000000000000000ULL, -1);}, + "remu, \"overflow\""); + + // MULW + expect(-100, + []{return M::mulw(0x7FFFFFFF00000005LL, 0x80000000FFFFFFECLL);}, + "mulw, truncate"); + expect(0, []{return M::mulw(0x40000000, 4);}, "mulw, overflow"); + + // DIVW + expect(-7, + []{return M::divw(0x7FFFFFFFFFFFFFC5LL, 0xFFFFFFFF00000008LL);}, + "divw, truncate"); + expect(-1, []{return M::divw(65535, 0);}, "divw/0"); + expect(numeric_limits::min(), + []{return M::divw(numeric_limits::min(), -1);}, + "divw, overflow"); + + // DIVUW + expect(536870904, + []{return M::divuw(0x7FFFFFFFFFFFFFC5LL, 0xFFFFFFFF00000008LL);}, + "divuw, truncate"); + expect(numeric_limits::max(), + []{return M::divuw(65535, 0);}, "divuw/0"); + expect(0, + []{return M::divuw(numeric_limits::min(), -1);}, + "divuw, \"overflow\""); + expect(-1, + []{return M::divuw(numeric_limits::max(), 1);}, + "divuw, sign extend"); + + // REMW + expect(-3, + []{return M::remw(0x7FFFFFFFFFFFFFC5LL, 0xFFFFFFFF00000008LL);}, + "remw, truncate"); + expect(65535, []{return M::remw(65535, 0);}, "remw/0"); + expect(0, []{return M::remw(numeric_limits::min(), -1);}, + "remw, overflow"); + + // REMUW + expect(5, + []{return M::remuw(0x7FFFFFFFFFFFFFC5LL, 0xFFFFFFFF00000008LL);}, + "remuw, truncate"); + expect(65535, []{return M::remuw(65535, 0);}, "remuw/0"); + expect(numeric_limits::min(), + []{return M::remuw(numeric_limits::min(), -1);}, + "remuw, \"overflow\""); + expect(0xFFFFFFFF80000000, + []{return M::remuw(0x80000000, 0xFFFFFFFF);}, + "remuw, sign extend"); + + return 0; +} diff --git a/tests/test-progs/insttest/src/riscv/rv64m.h b/tests/test-progs/insttest/src/riscv/rv64m.h new file mode 100644 index 000000000..b93a7d623 --- /dev/null +++ b/tests/test-progs/insttest/src/riscv/rv64m.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2016 The University of Virginia + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Alec Roelke + */ + +#pragma once + +#include + +#include "insttest.h" + +namespace M +{ + +inline int64_t +mul(int64_t rs1, int64_t rs2) +{ + int64_t rd = 0; + ROP("mul", rd, rs1, rs2); + return rd; +} + +inline int64_t +mulh(int64_t rs1, int64_t rs2) +{ + int64_t rd = 0; + ROP("mulh", rd, rs1, rs2); + return rd; +} + +inline int64_t +mulhsu(int64_t rs1, uint64_t rs2) +{ + int64_t rd = 0; + ROP("mulhsu", rd, rs1, rs2); + return rd; +} + +inline uint64_t +mulhu(uint64_t rs1, uint64_t rs2) +{ + uint64_t rd = 0; + ROP("mulhu", rd, rs1, rs2); + return rd; +} + +inline int64_t +div(int64_t rs1, int64_t rs2) +{ + int64_t rd = 0; + ROP("div", rd, rs1, rs2); + return rd; +} + +inline uint64_t +divu(uint64_t rs1, uint64_t rs2) +{ + uint64_t rd = 0; + ROP("divu", rd, rs1, rs2); + return rd; +} + +inline int64_t +rem(int64_t rs1, int64_t rs2) +{ + int64_t rd = 0; + ROP("rem", rd, rs1, rs2); + return rd; +} + +inline uint64_t +remu(uint64_t rs1, uint64_t rs2) +{ + uint64_t rd = 0; + ROP("remu", rd, rs1, rs2); + return rd; +} + +inline int64_t +mulw(int64_t rs1, int64_t rs2) +{ + int64_t rd = 0; + ROP("mulw", rd, rs1, rs2); + return rd; +} + +inline int64_t +divw(int64_t rs1, int64_t rs2) +{ + int64_t rd = 0; + ROP("divw", rd, rs1, rs2); + return rd; +} + +inline uint64_t +divuw(uint64_t rs1, uint64_t rs2) +{ + uint64_t rd = 0; + ROP("divuw", rd, rs1, rs2); + return rd; +} + +inline int64_t +remw(int64_t rs1, int64_t rs2) +{ + int64_t rd = 0; + ROP("remw", rd, rs1, rs2); + return rd; +} + +inline uint64_t +remuw(uint64_t rs1, uint64_t rs2) +{ + uint64_t rd = 0; + ROP("remuw", rd, rs1, rs2); + return rd; +} + +} // namespace M diff --git a/util/regress b/util/regress index 29c6f2c31..5cc576b5d 100755 --- a/util/regress +++ b/util/regress @@ -51,6 +51,7 @@ add_option('--builds', 'SPARC,' \ 'X86,X86_MESI_Two_Level,' \ 'ARM,' \ + 'RISCV,' \ 'HSAIL_X86', help="comma-separated build targets to test (default: '%default')") add_option('--modes',