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 <jason@lowepower.com>
This commit is contained in:
parent
ee0c261e10
commit
33683bd087
14 changed files with 3863 additions and 0 deletions
BIN
tests/test-progs/hello/bin/riscv/linux/hello
Executable file
BIN
tests/test-progs/hello/bin/riscv/linux/hello
Executable file
Binary file not shown.
51
tests/test-progs/insttest/src/riscv/Makefile
Normal file
51
tests/test-progs/insttest/src/riscv/Makefile
Normal file
|
@ -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
|
79
tests/test-progs/insttest/src/riscv/insttest.h
Normal file
79
tests/test-progs/insttest/src/riscv/insttest.h
Normal file
|
@ -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 <cmath>
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#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<typename A, typename B> std::ostream&
|
||||
operator<<(std::ostream& os, const std::pair<A, B>& p)
|
||||
{
|
||||
return os << '(' << p.first << ", " << p.second << ')';
|
||||
}
|
||||
|
||||
namespace insttest
|
||||
{
|
||||
|
||||
template<typename T> void
|
||||
expect(const T& expected, std::function<T()> 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
|
192
tests/test-progs/insttest/src/riscv/rv64a.cpp
Normal file
192
tests/test-progs/insttest/src/riscv/rv64a.cpp
Normal file
|
@ -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 <cstdint>
|
||||
#include <limits>
|
||||
|
||||
#include "insttest.h"
|
||||
#include "rv64a.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace std;
|
||||
using namespace insttest;
|
||||
|
||||
// Memory (LR.W, SC.W)
|
||||
expect<pair<int64_t, uint64_t>>({-1, 0}, []{
|
||||
int32_t mem = -1;
|
||||
int64_t rs2 = 256;
|
||||
int64_t rd = A::lr_w(mem);
|
||||
pair<int64_t, uint64_t> result = A::sc_w(rs2, mem);
|
||||
return pair<int64_t, uint64_t>(rd, result.second);
|
||||
}, "lr.w/sc.w");
|
||||
expect<pair<bool, int64_t>>({true, 200}, []{
|
||||
int32_t mem = 200;
|
||||
pair<int64_t, uint64_t> result = A::sc_w(50, mem);
|
||||
return pair<bool, int64_t>(result.second == 1, mem);
|
||||
}, "sc.w, no preceding lr.d");
|
||||
|
||||
// AMOSWAP.W
|
||||
expect<pair<int64_t, int64_t>>({65535, 255},
|
||||
[]{return A::amoswap_w(255, 65535);}, "amoswap.w");
|
||||
expect<pair<int64_t, int64_t>>({0xFFFFFFFF, -1},
|
||||
[]{return A::amoswap_w(0xFFFFFFFF, 0xFFFFFFFF);},
|
||||
"amoswap.w, sign extend");
|
||||
expect<pair<int64_t, int64_t>>({0x0000000180000000LL, -1},
|
||||
[]{return A::amoswap_w(0x00000001FFFFFFFFLL,
|
||||
0x7FFFFFFF80000000LL);},
|
||||
"amoswap.w, truncate");
|
||||
|
||||
// AMOADD.W
|
||||
expect<pair<int64_t, int64_t>>({256, 255},
|
||||
[]{return A::amoadd_w(255, 1);}, "amoadd.w");
|
||||
expect<pair<int64_t, int64_t>>({0, -1},
|
||||
[]{return A::amoadd_w(0xFFFFFFFF, 1);},
|
||||
"amoadd.w, truncate/overflow");
|
||||
expect<pair<int64_t, int64_t>>({0xFFFFFFFF, 0x7FFFFFFF},
|
||||
[]{return A::amoadd_w(0x7FFFFFFF, 0x80000000);},
|
||||
"amoadd.w, sign extend");
|
||||
|
||||
// AMOXOR.W
|
||||
expect<pair<uint64_t, uint64_t>>({0xFFFFFFFFAAAAAAAALL, -1},
|
||||
[]{return A::amoxor_w(-1, 0x5555555555555555LL);},
|
||||
"amoxor.w, truncate");
|
||||
expect<pair<uint64_t, uint64_t>>({0x80000000, -1},
|
||||
[]{return A::amoxor_w(0xFFFFFFFF, 0x7FFFFFFF);},
|
||||
"amoxor.w, sign extend");
|
||||
|
||||
// AMOAND.W
|
||||
expect<pair<uint64_t, uint64_t>>({0xFFFFFFFF00000000LL, -1},
|
||||
[]{return A::amoand_w(-1, 0);}, "amoand.w, truncate");
|
||||
expect<pair<uint64_t, uint64_t>>({0x0000000080000000LL, -1},
|
||||
[]{return A::amoand_w(0xFFFFFFFF,numeric_limits<int32_t>::min());},
|
||||
"amoand.w, sign extend");
|
||||
|
||||
// AMOOR.W
|
||||
expect<pair<uint64_t, uint64_t>>({0x00000000FFFFFFFFLL, 0},
|
||||
[]{return A::amoor_w(0, -1);}, "amoor.w, truncate");
|
||||
expect<pair<uint64_t, uint64_t>>({0x0000000080000000LL, 0},
|
||||
[]{return A::amoor_w(0, numeric_limits<int32_t>::min());},
|
||||
"amoor.w, sign extend");
|
||||
|
||||
// AMOMIN.W
|
||||
expect<pair<int64_t, int64_t>>({0x7FFFFFFF00000001LL, 1},
|
||||
[]{return A::amomin_w(0x7FFFFFFF00000001LL, 0xFFFFFFFF000000FF);},
|
||||
"amomin.w, truncate");
|
||||
expect<pair<int64_t, int64_t>>({0x00000000FFFFFFFELL, -1},
|
||||
[]{return A::amomin_w(0xFFFFFFFF, -2);}, "amomin.w, sign extend");
|
||||
|
||||
// AMOMAX.W
|
||||
expect<pair<int64_t, int64_t>>({0x70000000000000FFLL, 1},
|
||||
[]{return A::amomax_w(0x7000000000000001LL,0x7FFFFFFF000000FFLL);},
|
||||
"amomax.w, truncate");
|
||||
expect<pair<int64_t, int64_t>>({-1, numeric_limits<int32_t>::min()},
|
||||
[]{return A::amomax_w(numeric_limits<int32_t>::min(), -1);},
|
||||
"amomax.w, sign extend");
|
||||
|
||||
// AMOMINU.W
|
||||
expect<pair<uint64_t, uint64_t>>({0x0FFFFFFF000000FFLL, -1},
|
||||
[]{return A::amominu_w(0x0FFFFFFFFFFFFFFFLL, 0xFFFFFFFF000000FF);},
|
||||
"amominu.w, truncate");
|
||||
expect<pair<uint64_t, uint64_t>>({0x0000000080000000LL, -1},
|
||||
[]{return A::amominu_w(0x00000000FFFFFFFFLL, 0x80000000);},
|
||||
"amominu.w, sign extend");
|
||||
|
||||
// AMOMAXU.W
|
||||
expect<pair<uint64_t, uint64_t>>({-1, 0},
|
||||
[]{return A::amomaxu_w(0xFFFFFFFF00000000LL,
|
||||
0x00000000FFFFFFFFLL);},
|
||||
"amomaxu.w, truncate");
|
||||
expect<pair<uint64_t, uint64_t>>(
|
||||
{0xFFFFFFFF, numeric_limits<int32_t>::min()},
|
||||
[]{return A::amomaxu_w(0x80000000, 0xFFFFFFFF);},
|
||||
"amomaxu.w, sign extend");
|
||||
|
||||
// Memory (LR.D, SC.D)
|
||||
expect<pair<int64_t, uint64_t>>({-1, 0}, []{
|
||||
int64_t mem = -1;
|
||||
int64_t rs2 = 256;
|
||||
int64_t rd = A::lr_d(mem);
|
||||
pair<int64_t, uint64_t> result = A::sc_d(rs2, mem);
|
||||
return pair<int64_t, uint64_t>(rd, result.second);
|
||||
}, "lr.d/sc.d");
|
||||
expect<pair<bool, int64_t>>({true, 200}, []{
|
||||
int64_t mem = 200;
|
||||
pair<int64_t, uint64_t> result = A::sc_d(50, mem);
|
||||
return pair<bool, int64_t>(result.second == 1, mem);
|
||||
}, "sc.d, no preceding lr.d");
|
||||
|
||||
// AMOSWAP.D
|
||||
expect<pair<int64_t, int64_t>>({1, -1}, []{return A::amoswap_d(-1, 1);},
|
||||
"amoswap.d");
|
||||
|
||||
// AMOADD.D
|
||||
expect<pair<int64_t, int64_t>>({0x7000000000000000LL,0x0FFFFFFFFFFFFFFFLL},
|
||||
[]{return A::amoadd_d(0x0FFFFFFFFFFFFFFFLL,0x6000000000000001LL);},
|
||||
"amoadd.d");
|
||||
expect<pair<int64_t, int64_t>>({0, 0x7FFFFFFFFFFFFFFFLL},
|
||||
[]{return A::amoadd_d(0x7FFFFFFFFFFFFFFFLL,0x8000000000000001LL);},
|
||||
"amoadd.d, overflow");
|
||||
|
||||
// AMOXOR.D
|
||||
expect<pair<int64_t, int64_t>>({-1, 0xAAAAAAAAAAAAAAAALL},
|
||||
[]{return A::amoxor_d(0xAAAAAAAAAAAAAAAALL,0x5555555555555555LL);},
|
||||
"amoxor.d (1)");
|
||||
expect<pair<int64_t, int64_t>>({0, 0xAAAAAAAAAAAAAAAALL},
|
||||
[]{return A::amoxor_d(0xAAAAAAAAAAAAAAAALL,0xAAAAAAAAAAAAAAAALL);},
|
||||
"amoxor.d (0)");
|
||||
|
||||
// AMOAND.D
|
||||
expect<pair<int64_t, int64_t>>({0xAAAAAAAAAAAAAAAALL, -1},
|
||||
[]{return A::amoand_d(-1, 0xAAAAAAAAAAAAAAAALL);}, "amoand.d");
|
||||
|
||||
// AMOOR.D
|
||||
expect<pair<int64_t, int64_t>>({-1, 0xAAAAAAAAAAAAAAAALL},
|
||||
[]{return A::amoor_d(0xAAAAAAAAAAAAAAAALL, 0x5555555555555555LL);},
|
||||
"amoor.d");
|
||||
|
||||
// AMOMIN.D
|
||||
expect<pair<int64_t, int64_t>>({-1, -1},
|
||||
[]{return A::amomin_d(-1, 0);}, "amomin.d");
|
||||
|
||||
// AMOMAX.D
|
||||
expect<pair<int64_t, int64_t>>({0, -1}, []{return A::amomax_d(-1, 0);},
|
||||
"amomax.d");
|
||||
|
||||
// AMOMINU.D
|
||||
expect<pair<uint64_t, uint64_t>>({0, -1},
|
||||
[]{return A::amominu_d(-1, 0);}, "amominu.d");
|
||||
|
||||
// AMOMAXU.D
|
||||
expect<pair<uint64_t, uint64_t>>({-1, -1}, []{return A::amomaxu_d(-1, 0);},
|
||||
"amomaxu.d");
|
||||
|
||||
return 0;
|
||||
}
|
299
tests/test-progs/insttest/src/riscv/rv64a.h
Normal file
299
tests/test-progs/insttest/src/riscv/rv64a.h
Normal file
|
@ -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 <cstdint>
|
||||
#include <tuple>
|
||||
|
||||
#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<int64_t, uint64_t>
|
||||
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<int64_t, int64_t>
|
||||
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<int64_t, int64_t>
|
||||
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<uint64_t, uint64_t>
|
||||
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<uint64_t, uint64_t>
|
||||
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<uint64_t, uint64_t>
|
||||
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<int64_t, int64_t>
|
||||
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<int64_t, int64_t>
|
||||
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<uint64_t, uint64_t>
|
||||
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<uint64_t, uint64_t>
|
||||
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<int64_t, uint64_t>
|
||||
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<int64_t, int64_t>
|
||||
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<int64_t, int64_t>
|
||||
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<uint64_t, uint64_t>
|
||||
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<uint64_t, uint64_t>
|
||||
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<uint64_t, uint64_t>
|
||||
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<int64_t, int64_t>
|
||||
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<int64_t, int64_t>
|
||||
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<uint64_t, uint64_t>
|
||||
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<uint64_t, uint64_t>
|
||||
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
|
708
tests/test-progs/insttest/src/riscv/rv64d.cpp
Normal file
708
tests/test-progs/insttest/src/riscv/rv64d.cpp
Normal file
|
@ -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 <cstdint>
|
||||
#include <limits>
|
||||
|
||||
#include "insttest.h"
|
||||
#include "rv64d.h"
|
||||
#include "rv64f.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace std;
|
||||
using namespace insttest;
|
||||
|
||||
// Memory (FLD, FSD)
|
||||
expect<double>(3.1415926, []{return D::load(3.1415926);}, "fld");
|
||||
expect<double>(1.61803398875, []{return D::store(1.61803398875);}, "fsd");
|
||||
|
||||
// FMADD.D
|
||||
expect<double>(D::number(0x4019FD5AED13B1CEULL),
|
||||
[]{return D::fmadd_d(3.1415926, 1.61803398875,1.41421356237);},
|
||||
"fmadd.d");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fmadd_d(numeric_limits<double>::quiet_NaN(), 3.14,
|
||||
1.816);
|
||||
return D::isquietnan(fd);
|
||||
}, "fmadd.d, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fmadd_d(3.14,
|
||||
numeric_limits<double>::signaling_NaN(), 1.816);
|
||||
return D::isquietnan(fd);
|
||||
}, "fmadd.d, signaling NaN");
|
||||
expect<double>(numeric_limits<double>::infinity(),
|
||||
[]{return D::fmadd_d(3.14, numeric_limits<double>::infinity(),1.414);},
|
||||
"fmadd.d, infinity");
|
||||
expect<double>(-numeric_limits<double>::infinity(),
|
||||
[]{return D::fmadd_d(3.14,-numeric_limits<double>::infinity(),1.414);},
|
||||
"fmadd.d, -infinity");
|
||||
|
||||
// FMSUB.D
|
||||
expect<double>(D::number(0x400d5A1773A85E43ULL),
|
||||
[]{return D::fmsub_d(3.1415926, 1.61803398875, 1.41421356237);},
|
||||
"fmsub.d");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fmsub_d(3.14, numeric_limits<double>::quiet_NaN(),
|
||||
1.414);
|
||||
return D::isquietnan(fd);
|
||||
}, "fmsub.d, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fmsub_d(3.14, 1.816,
|
||||
numeric_limits<double>::signaling_NaN());
|
||||
return D::isquietnan(fd);
|
||||
}, "fmsub.d, signaling NaN");
|
||||
expect<double>(numeric_limits<double>::infinity(),
|
||||
[]{return D::fmsub_d(numeric_limits<double>::infinity(), 1.816,
|
||||
1.414);},
|
||||
"fmsub.d, infinity");
|
||||
expect<double>(-numeric_limits<double>::infinity(),
|
||||
[]{return D::fmsub_d(3.14, -numeric_limits<double>::infinity(),
|
||||
1.414);},
|
||||
"fmsub.d, -infinity");
|
||||
expect<double>(-numeric_limits<double>::infinity(),
|
||||
[]{return D::fmsub_d(3.14, 1.816,
|
||||
numeric_limits<double>::infinity());},
|
||||
"fmsub.d, subtract infinity");
|
||||
|
||||
// FNMSUB.D
|
||||
expect<double>(D::number(0xC00D5A1773A85E43ULL),
|
||||
[]{return D::fnmsub_d(3.1415926, 1.61803398875, 1.41421356237);},
|
||||
"fnmsub.d");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fnmsub_d(3.14, 1.816,
|
||||
numeric_limits<double>::quiet_NaN());
|
||||
return D::isquietnan(fd);
|
||||
}, "fnmsub.d, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fnmsub_d(numeric_limits<double>::signaling_NaN(),
|
||||
1.816, 1.414);
|
||||
return D::isquietnan(fd);
|
||||
}, "fnmsub.d, signaling NaN");
|
||||
expect<double>(-numeric_limits<double>::infinity(),
|
||||
[]{return D::fnmsub_d(numeric_limits<double>::infinity(), 1.816,
|
||||
1.414);},
|
||||
"fnmsub.d, infinity");
|
||||
expect<double>(numeric_limits<double>::infinity(),
|
||||
[]{return D::fnmsub_d(3.14, -numeric_limits<double>::infinity(),
|
||||
1.414);},
|
||||
"fnmsub.d, -infinity");
|
||||
expect<double>(numeric_limits<double>::infinity(),
|
||||
[]{return D::fnmsub_d(3.14, 1.816,
|
||||
numeric_limits<double>::infinity());},
|
||||
"fnmsub.d, subtract infinity");
|
||||
|
||||
// FNMADD.D
|
||||
expect<double>(D::number(0xC019FD5AED13B1CEULL),
|
||||
[]{return D::fnmadd_d(3.1415926, 1.61803398875, 1.41421356237);},
|
||||
"fnmadd.d");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fnmadd_d(numeric_limits<double>::quiet_NaN(), 3.14,
|
||||
1.816);
|
||||
return D::isquietnan(fd);
|
||||
}, "fnmadd.d, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fnmadd_d(3.14,
|
||||
numeric_limits<double>::signaling_NaN(), 1.816);
|
||||
return D::isquietnan(fd);
|
||||
}, "fnmadd.d, signaling NaN");
|
||||
expect<double>(-numeric_limits<double>::infinity(),
|
||||
[]{return D::fnmadd_d(3.14, numeric_limits<double>::infinity(),
|
||||
1.414);},
|
||||
"fnmadd.d, infinity");
|
||||
expect<double>(numeric_limits<double>::infinity(),
|
||||
[]{return D::fnmadd_d(3.14, -numeric_limits<double>::infinity(),
|
||||
1.414);},
|
||||
"fnmadd.d, -infinity");
|
||||
|
||||
// FADD.D
|
||||
expect<double>(D::number(0x4012392540292D7CULL),
|
||||
[]{return D::fadd_d(3.1415926, 1.41421356237);}, "fadd.d");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fadd_d(numeric_limits<double>::quiet_NaN(), 1.414);
|
||||
return D::isquietnan(fd);
|
||||
}, "fadd.d, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fadd_d(3.14,
|
||||
numeric_limits<double>::signaling_NaN());
|
||||
return D::isquietnan(fd);
|
||||
}, "fadd.d, signaling NaN");
|
||||
expect<double>(numeric_limits<double>::infinity(),
|
||||
[]{return D::fadd_d(3.14, numeric_limits<double>::infinity());},
|
||||
"fadd.d, infinity");
|
||||
expect<double>(-numeric_limits<double>::infinity(),
|
||||
[]{return D::fadd_d(-numeric_limits<double>::infinity(), 1.816);},
|
||||
"fadd.d, -infinity");
|
||||
|
||||
// FSUB.D
|
||||
expect<double>(D::number(0xBFFBA35833AB7AAEULL),
|
||||
[]{return D::fsub_d(1.4142135623, 3.1415926);}, "fsub.d");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fsub_d(numeric_limits<double>::quiet_NaN(), 1.414);
|
||||
return D::isquietnan(fd);
|
||||
}, "fsub.d, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fsub_d(3.14,
|
||||
numeric_limits<double>::signaling_NaN());
|
||||
return D::isquietnan(fd);
|
||||
}, "fsub.d, signaling NaN");
|
||||
expect<double>(numeric_limits<double>::infinity(),
|
||||
[]{return D::fsub_d(numeric_limits<double>::infinity(), 3.14);},
|
||||
"fsub.d, infinity");
|
||||
expect<double>(-numeric_limits<double>::infinity(),
|
||||
[]{return D::fsub_d(-numeric_limits<double>::infinity(), 3.14);},
|
||||
"fsub.d, -infinity");
|
||||
expect<double>(-numeric_limits<double>::infinity(),
|
||||
[]{return D::fsub_d(1.414, numeric_limits<double>::infinity());},
|
||||
"fsub.d, subtract infinity");
|
||||
|
||||
// FMUL.D
|
||||
expect<double>(D::number(0x40024E53B708ED9AULL),
|
||||
[]{return D::fmul_d(1.61803398875, 1.4142135623);}, "fmul.d");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fmul_d(numeric_limits<double>::quiet_NaN(), 1.414);
|
||||
return D::isquietnan(fd);
|
||||
}, "fmul.d, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fmul_d(1.816,
|
||||
numeric_limits<double>::signaling_NaN());
|
||||
return D::isquietnan(fd);
|
||||
}, "fmul.d, signaling NaN");
|
||||
expect<double>(numeric_limits<double>::infinity(),
|
||||
[]{return D::fmul_d(numeric_limits<double>::infinity(), 2.718);},
|
||||
"fmul.d, infinity");
|
||||
expect<double>(-numeric_limits<double>::infinity(),
|
||||
[]{return D::fmul_d(2.5966, -numeric_limits<double>::infinity());},
|
||||
"fmul.d, -infinity");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fmul_d(0.0, numeric_limits<double>::infinity());
|
||||
return D::isquietnan(fd);
|
||||
}, "fmul.d, 0*infinity");
|
||||
expect<double>(numeric_limits<double>::infinity(),
|
||||
[]{return D::fmul_d(numeric_limits<double>::max(), 2.0);},
|
||||
"fmul.d, overflow");
|
||||
expect<double>(0.0,
|
||||
[]{return D::fmul_d(numeric_limits<double>::min(),
|
||||
numeric_limits<double>::min());},
|
||||
"fmul.d, underflow");
|
||||
|
||||
// FDIV.D
|
||||
expect<double>(2.5, []{return D::fdiv_d(10.0, 4.0);}, "fdiv.d");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fdiv_d(numeric_limits<double>::quiet_NaN(), 4.0);
|
||||
return D::isquietnan(fd);
|
||||
}, "fdiv.d, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fdiv_d(10.0,
|
||||
numeric_limits<double>::signaling_NaN());
|
||||
return D::isquietnan(fd);
|
||||
}, "fdiv.d, signaling NaN");
|
||||
expect<double>(numeric_limits<double>::infinity(),
|
||||
[]{return D::fdiv_d(10.0, 0.0);}, "fdiv.d/0");
|
||||
expect<double>(0.0,
|
||||
[]{return D::fdiv_d(10.0, numeric_limits<double>::infinity());},
|
||||
"fdiv.d/infinity");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fdiv_d(numeric_limits<double>::infinity(),
|
||||
numeric_limits<double>::infinity());
|
||||
return D::isquietnan(fd);
|
||||
}, "fdiv.d, infinity/infinity");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fdiv_d(0.0, 0.0);
|
||||
return D::isquietnan(fd);
|
||||
}, "fdiv.d, 0/0");
|
||||
expect<double>(numeric_limits<double>::infinity(),
|
||||
[]{return D::fdiv_d(numeric_limits<double>::infinity(), 0.0);},
|
||||
"fdiv.d, infinity/0");
|
||||
expect<double>(0.0,
|
||||
[]{return D::fdiv_d(0.0, numeric_limits<double>::infinity());},
|
||||
"fdiv.d, 0/infinity");
|
||||
expect<double>(0.0,
|
||||
[]{return D::fdiv_d(numeric_limits<double>::min(),
|
||||
numeric_limits<double>::max());},
|
||||
"fdiv.d, underflow");
|
||||
expect<double>(numeric_limits<double>::infinity(),
|
||||
[]{return D::fdiv_d(numeric_limits<double>::max(),
|
||||
numeric_limits<double>::min());},
|
||||
"fdiv.d, overflow");
|
||||
|
||||
// FSQRT.D
|
||||
expect<double>(1e154, []{return D::fsqrt_d(1e308);}, "fsqrt.d");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fsqrt_d(-1.0);
|
||||
return D::isquietnan(fd);
|
||||
}, "fsqrt.d, NaN");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fsqrt_d(numeric_limits<double>::quiet_NaN());
|
||||
return D::isquietnan(fd);
|
||||
}, "fsqrt.d, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fsqrt_d(numeric_limits<double>::signaling_NaN());
|
||||
return D::isquietnan(fd);
|
||||
}, "fsqrt.d, signaling NaN");
|
||||
expect<double>(numeric_limits<double>::infinity(),
|
||||
[]{return D::fsqrt_d(numeric_limits<double>::infinity());},
|
||||
"fsqrt.d, infinity");
|
||||
|
||||
// FSGNJ.D
|
||||
expect<double>(1.0, []{return D::fsgnj_d(1.0, 25.0);}, "fsgnj.d, ++");
|
||||
expect<double>(-1.0, []{return D::fsgnj_d(1.0, -25.0);}, "fsgnj.d, +-");
|
||||
expect<double>(1.0, []{return D::fsgnj_d(-1.0, 25.0);}, "fsgnj.d, -+");
|
||||
expect<double>(-1.0, []{return D::fsgnj_d(-1.0, -25.0);}, "fsgnj.d, --");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fsgnj_d(numeric_limits<double>::quiet_NaN(), -4.0);
|
||||
return D::isquietnan(fd);
|
||||
}, "fsgnj.d, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fsgnj_d(numeric_limits<double>::signaling_NaN(),
|
||||
-4.0);
|
||||
return D::issignalingnan(fd);
|
||||
}, "fsgnj.d, signaling NaN");
|
||||
expect<double>(4.0,
|
||||
[]{return D::fsgnj_d(4.0, numeric_limits<double>::quiet_NaN());},
|
||||
"fsgnj.d, inject NaN");
|
||||
expect<double>(-4.0,
|
||||
[]{return D::fsgnj_d(4.0, -numeric_limits<double>::quiet_NaN());},
|
||||
"fsgnj.d, inject -NaN");
|
||||
|
||||
// FSGNJN.D
|
||||
expect<double>(-1.0, []{return D::fsgnjn_d(1.0, 25.0);}, "fsgnjn.d, ++");
|
||||
expect<double>(1.0, []{return D::fsgnjn_d(1.0, -25.0);}, "fsgnjn.d, +-");
|
||||
expect<double>(-1.0, []{return D::fsgnjn_d(-1.0, 25.0);}, "fsgnjn.d, -+");
|
||||
expect<double>(1.0, []{return D::fsgnjn_d(-1.0, -25.0);}, "fsgnjn.d, --");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fsgnjn_d(numeric_limits<double>::quiet_NaN(), -4.0);
|
||||
return D::isquietnan(fd);
|
||||
}, "fsgnjn.d, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fsgnjn_d(numeric_limits<double>::signaling_NaN(),
|
||||
-4.0);
|
||||
return D::issignalingnan(fd);
|
||||
}, "fsgnjn.d, signaling NaN");
|
||||
expect<double>(-4.0,
|
||||
[]{return D::fsgnjn_d(4.0, numeric_limits<double>::quiet_NaN());},
|
||||
"fsgnjn.d, inject NaN");
|
||||
expect<double>(4.0,
|
||||
[]{return D::fsgnjn_d(4.0, -numeric_limits<double>::quiet_NaN());},
|
||||
"fsgnjn.d, inject NaN");
|
||||
|
||||
// FSGNJX.D
|
||||
expect<double>(1.0, []{return D::fsgnjx_d(1.0, 25.0);}, "fsgnjx.d, ++");
|
||||
expect<double>(-1.0, []{return D::fsgnjx_d(1.0, -25.0);}, "fsgnjx.d, +-");
|
||||
expect<double>(-1.0, []{return D::fsgnjx_d(-1.0, 25.0);}, "fsgnjx.d, -+");
|
||||
expect<double>(1.0, []{return D::fsgnjx_d(-1.0, -25.0);}, "fsgnjx.d, --");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fsgnjx_d(numeric_limits<double>::quiet_NaN(), -4.0);
|
||||
return D::isquietnan(fd);
|
||||
}, "fsgnjx.d, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fsgnjx_d(numeric_limits<double>::signaling_NaN(),
|
||||
-4.0);
|
||||
return D::issignalingnan(fd);
|
||||
}, "fsgnjx.d, signaling NaN");
|
||||
expect<double>(4.0,
|
||||
[]{return D::fsgnjx_d(4.0, numeric_limits<double>::quiet_NaN());},
|
||||
"fsgnjx.d, inject NaN");
|
||||
expect<double>(-4.0,
|
||||
[]{return D::fsgnjx_d(4.0, -numeric_limits<double>::quiet_NaN());},
|
||||
"fsgnjx.d, inject NaN");
|
||||
|
||||
// FMIN.D
|
||||
expect<double>(2.718, []{return D::fmin_d(3.14, 2.718);}, "fmin.d");
|
||||
expect<double>(-numeric_limits<double>::infinity(),
|
||||
[]{return D::fmin_d(-numeric_limits<double>::infinity(),
|
||||
numeric_limits<double>::min());},
|
||||
"fmin.d, -infinity");
|
||||
expect<double>(numeric_limits<double>::max(),
|
||||
[]{return D::fmin_d(numeric_limits<double>::infinity(),
|
||||
numeric_limits<double>::max());},
|
||||
"fmin.d, infinity");
|
||||
expect<double>(-1.414,
|
||||
[]{return D::fmin_d(numeric_limits<double>::quiet_NaN(), -1.414);},
|
||||
"fmin.d, quiet NaN first");
|
||||
expect<double>(2.718,
|
||||
[]{return D::fmin_d(2.718, numeric_limits<double>::quiet_NaN());},
|
||||
"fmin.d, quiet NaN second");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fmin_d(numeric_limits<double>::quiet_NaN(),
|
||||
numeric_limits<double>::quiet_NaN());
|
||||
return D::isquietnan(fd);
|
||||
}, "fmin.d, quiet NaN both");
|
||||
expect<double>(3.14,
|
||||
[]{return D::fmin_d(numeric_limits<double>::signaling_NaN(),
|
||||
3.14);},
|
||||
"fmin.d, signaling NaN first");
|
||||
expect<double>(1.816,
|
||||
[]{return D::fmin_d(1.816,
|
||||
numeric_limits<double>::signaling_NaN());},
|
||||
"fmin.d, signaling NaN second");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fmin_d(numeric_limits<double>::signaling_NaN(),
|
||||
numeric_limits<double>::signaling_NaN());
|
||||
return D::issignalingnan(fd);
|
||||
}, "fmin.d, signaling NaN both");
|
||||
|
||||
// FMAX.D
|
||||
expect<double>(3.14, []{return D::fmax_d(3.14, 2.718);}, "fmax.d");
|
||||
expect<double>(numeric_limits<double>::min(),
|
||||
[]{return D::fmax_d(-numeric_limits<double>::infinity(),
|
||||
numeric_limits<double>::min());},
|
||||
"fmax.d, -infinity");
|
||||
expect<double>(numeric_limits<double>::infinity(),
|
||||
[]{return D::fmax_d(numeric_limits<double>::infinity(),
|
||||
numeric_limits<double>::max());},
|
||||
"fmax.d, infinity");
|
||||
expect<double>(-1.414,
|
||||
[]{return D::fmax_d(numeric_limits<double>::quiet_NaN(), -1.414);},
|
||||
"fmax.d, quiet NaN first");
|
||||
expect<double>(2.718,
|
||||
[]{return D::fmax_d(2.718, numeric_limits<double>::quiet_NaN());},
|
||||
"fmax.d, quiet NaN second");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fmax_d(numeric_limits<double>::quiet_NaN(),
|
||||
numeric_limits<double>::quiet_NaN());
|
||||
return D::isquietnan(fd);
|
||||
}, "fmax.d, quiet NaN both");
|
||||
expect<double>(3.14,
|
||||
[]{return D::fmax_d(numeric_limits<double>::signaling_NaN(),
|
||||
3.14);},
|
||||
"fmax.d, signaling NaN first");
|
||||
expect<double>(1.816,
|
||||
[]{return D::fmax_d(1.816,
|
||||
numeric_limits<double>::signaling_NaN());},
|
||||
"fmax.d, signaling NaN second");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fmax_d(numeric_limits<double>::signaling_NaN(),
|
||||
numeric_limits<double>::signaling_NaN());
|
||||
return D::issignalingnan(fd);
|
||||
}, "fmax.d, signaling NaN both");
|
||||
|
||||
// FCVT.S.D
|
||||
expect<float>(4.0, []{return D::fcvt_s_d(4.0);}, "fcvt.s.d");
|
||||
expect<bool>(true, []{
|
||||
float fd = D::fcvt_s_d(numeric_limits<double>::quiet_NaN());
|
||||
return F::isquietnan(fd);
|
||||
}, "fcvt.s.d, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
float fd = D::fcvt_s_d(numeric_limits<double>::signaling_NaN());
|
||||
return F::isquietnan(fd);
|
||||
}, "fcvt.s.d, signaling NaN");
|
||||
expect<float>(numeric_limits<float>::infinity(),
|
||||
[]{return D::fcvt_s_d(numeric_limits<double>::infinity());},
|
||||
"fcvt.s.d, infinity");
|
||||
expect<float>(numeric_limits<float>::infinity(),
|
||||
[]{return D::fcvt_s_d(numeric_limits<double>::max());},
|
||||
"fcvt.s.d, overflow");
|
||||
expect<float>(0.0, []{return D::fcvt_s_d(numeric_limits<double>::min());},
|
||||
"fcvt.s.d, underflow");
|
||||
|
||||
// FCVT.D.S
|
||||
expect<double>(D::number(0x4005BE76C0000000),
|
||||
[]{return D::fcvt_d_s(2.718);}, "fcvt.d.s");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fcvt_d_s(numeric_limits<float>::quiet_NaN());
|
||||
return D::isquietnan(fd);
|
||||
}, "fcvt.d.s, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
double fd = D::fcvt_d_s(numeric_limits<float>::signaling_NaN());
|
||||
return D::isquietnan(fd);
|
||||
}, "fcvt.d.s, signaling NaN");
|
||||
expect<double>(numeric_limits<double>::infinity(),
|
||||
[]{return D::fcvt_d_s(numeric_limits<float>::infinity());},
|
||||
"fcvt.d.s, infinity");
|
||||
|
||||
// FEQ.D
|
||||
expect<bool>(true, []{return D::feq_d(1.414, 1.414);}, "feq.d, equal");
|
||||
expect<bool>(false,[]{return D::feq_d(2.718, 1.816);}, "feq.d, not equal");
|
||||
expect<bool>(true, []{return D::feq_d(0.0, -0.0);}, "feq.d, 0 == -0");
|
||||
expect<bool>(false,
|
||||
[]{return D::feq_d(numeric_limits<double>::quiet_NaN(), -1.0);},
|
||||
"feq.d, quiet NaN first");
|
||||
expect<bool>(false,
|
||||
[]{return D::feq_d(2.0, numeric_limits<double>::quiet_NaN());},
|
||||
"feq.d, quiet NaN second");
|
||||
expect<bool>(false,
|
||||
[]{return D::feq_d(numeric_limits<double>::quiet_NaN(),
|
||||
numeric_limits<double>::quiet_NaN());},
|
||||
"feq.d, quiet NaN both");
|
||||
expect<bool>(false,
|
||||
[]{return D::feq_d(numeric_limits<double>::signaling_NaN(),-1.0);},
|
||||
"feq.d, signaling NaN first");
|
||||
expect<bool>(false,
|
||||
[]{return D::feq_d(2.0, numeric_limits<double>::signaling_NaN());},
|
||||
"feq.d, signaling NaN second");
|
||||
expect<bool>(false,
|
||||
[]{return D::feq_d(numeric_limits<double>::signaling_NaN(),
|
||||
numeric_limits<double>::signaling_NaN());},
|
||||
"feq.d, signaling NaN both");
|
||||
|
||||
// FLT.D
|
||||
expect<bool>(false, []{return D::flt_d(1.414, 1.414);}, "flt.d, equal");
|
||||
expect<bool>(true, []{return D::flt_d(1.816, 2.718);}, "flt.d, less");
|
||||
expect<bool>(false, []{return D::flt_d(2.718, 1.816);}, "flt.d, greater");
|
||||
expect<bool>(false,
|
||||
[]{return D::flt_d(numeric_limits<double>::quiet_NaN(), -1.0);},
|
||||
"flt.d, quiet NaN first");
|
||||
expect<bool>(false,
|
||||
[]{return D::flt_d(2.0, numeric_limits<double>::quiet_NaN());},
|
||||
"flt.d, quiet NaN second");
|
||||
expect<bool>(false,
|
||||
[]{return D::flt_d(numeric_limits<double>::quiet_NaN(),
|
||||
numeric_limits<double>::quiet_NaN());},
|
||||
"flt.d, quiet NaN both");
|
||||
expect<bool>(false,
|
||||
[]{return D::flt_d(numeric_limits<double>::signaling_NaN(),-1.0);},
|
||||
"flt.d, signaling NaN first");
|
||||
expect<bool>(false,
|
||||
[]{return D::flt_d(2.0, numeric_limits<double>::signaling_NaN());},
|
||||
"flt.d, signaling NaN second");
|
||||
expect<bool>(false,
|
||||
[]{return D::flt_d(numeric_limits<double>::signaling_NaN(),
|
||||
numeric_limits<double>::signaling_NaN());},
|
||||
"flt.d, signaling NaN both");
|
||||
|
||||
// FLE.D
|
||||
expect<bool>(true, []{return D::fle_d(1.414, 1.414);}, "fle.d, equal");
|
||||
expect<bool>(true, []{return D::fle_d(1.816, 2.718);}, "fle.d, less");
|
||||
expect<bool>(false, []{return D::fle_d(2.718, 1.816);}, "fle.d, greater");
|
||||
expect<bool>(true, []{return D::fle_d(0.0, -0.0);}, "fle.d, 0 == -0");
|
||||
expect<bool>(false,
|
||||
[]{return D::fle_d(numeric_limits<double>::quiet_NaN(), -1.0);},
|
||||
"fle.d, quiet NaN first");
|
||||
expect<bool>(false,
|
||||
[]{return D::fle_d(2.0, numeric_limits<double>::quiet_NaN());},
|
||||
"fle.d, quiet NaN second");
|
||||
expect<bool>(false,
|
||||
[]{return D::fle_d(numeric_limits<double>::quiet_NaN(),
|
||||
numeric_limits<double>::quiet_NaN());},
|
||||
"fle.d, quiet NaN both");
|
||||
expect<bool>(false,
|
||||
[]{return D::fle_d(numeric_limits<double>::signaling_NaN(),-1.0);},
|
||||
"fle.d, signaling NaN first");
|
||||
expect<bool>(false,
|
||||
[]{return D::fle_d(2.0, numeric_limits<double>::signaling_NaN());},
|
||||
"fle.d, signaling NaN second");
|
||||
expect<bool>(false,
|
||||
[]{return D::fle_d(numeric_limits<double>::signaling_NaN(),
|
||||
numeric_limits<double>::signaling_NaN());},
|
||||
"fle.d, signaling NaN both");
|
||||
|
||||
// FCLASS.D
|
||||
expect<uint64_t>(0x1,
|
||||
[]{return D::fclass_d(-numeric_limits<double>::infinity());},
|
||||
"fclass.d, -infinity");
|
||||
expect<uint64_t>(0x2,
|
||||
[]{return D::fclass_d(-3.14);}, "fclass.d, -normal");
|
||||
expect<uint64_t>(0x4,
|
||||
[]{return D::fclass_d(D::number(0x800FFFFFFFFFFFFFULL));},
|
||||
"fclass.d, -subnormal");
|
||||
expect<uint64_t>(0x8, []{return D::fclass_d(-0.0);}, "fclass.d, -0.0");
|
||||
expect<uint64_t>(0x10, []{return D::fclass_d(0.0);}, "fclass.d, 0.0");
|
||||
expect<uint64_t>(0x20,
|
||||
[]{return D::fclass_d(D::number(0x000FFFFFFFFFFFFFULL));},
|
||||
"fclass.d, subnormal");
|
||||
expect<uint64_t>(0x40, []{return D::fclass_d(1.816);}, "fclass.d, normal");
|
||||
expect<uint64_t>(0x80,
|
||||
[]{return D::fclass_d(numeric_limits<double>::infinity());},
|
||||
"fclass.d, infinity");
|
||||
expect<uint64_t>(0x100,
|
||||
[]{return D::fclass_d(numeric_limits<double>::signaling_NaN());},
|
||||
"fclass.d, signaling NaN");
|
||||
expect<uint64_t>(0x200,
|
||||
[]{return D::fclass_d(numeric_limits<double>::quiet_NaN());},
|
||||
"fclass.s, quiet NaN");
|
||||
|
||||
// FCVT.W.D
|
||||
expect<int64_t>(256, []{return D::fcvt_w_d(256.3);},
|
||||
"fcvt.w.d, truncate positive");
|
||||
expect<int64_t>(-256, []{return D::fcvt_w_d(-256.2);},
|
||||
"fcvt.w.d, truncate negative");
|
||||
expect<int64_t>(0, []{return D::fcvt_w_d(0.0);}, "fcvt.w.d, 0.0");
|
||||
expect<int64_t>(0, []{return D::fcvt_w_d(-0.0);}, "fcvt.w.d, -0.0");
|
||||
expect<int64_t>(numeric_limits<int32_t>::max(),
|
||||
[]{return D::fcvt_w_d(numeric_limits<double>::max());},
|
||||
"fcvt.w.d, overflow");
|
||||
expect<int64_t>(0, []{return D::fcvt_w_d(numeric_limits<double>::min());},
|
||||
"fcvt.w.d, underflow");
|
||||
expect<int64_t>(numeric_limits<int32_t>::max(),
|
||||
[]{return D::fcvt_w_d(numeric_limits<double>::infinity());},
|
||||
"fcvt.w.d, infinity");
|
||||
expect<int64_t>(numeric_limits<int32_t>::min(),
|
||||
[]{return D::fcvt_w_d(-numeric_limits<double>::infinity());},
|
||||
"fcvt.w.d, -infinity");
|
||||
expect<int64_t>(numeric_limits<int32_t>::max(),
|
||||
[]{return D::fcvt_w_d(numeric_limits<double>::quiet_NaN());},
|
||||
"fcvt.w.d, quiet NaN");
|
||||
expect<int64_t>(numeric_limits<int32_t>::max(),
|
||||
[]{return D::fcvt_w_d(-numeric_limits<double>::quiet_NaN());},
|
||||
"fcvt.w.d, quiet -NaN");
|
||||
expect<int64_t>(numeric_limits<int32_t>::max(),
|
||||
[]{return D::fcvt_w_d(numeric_limits<double>::signaling_NaN());},
|
||||
"fcvt.w.d, signaling NaN");
|
||||
|
||||
// FCVT.WU.D
|
||||
expect<uint64_t>(256, []{return D::fcvt_wu_d(256.3);},
|
||||
"fcvt.wu.d, truncate positive");
|
||||
expect<uint64_t>(0, []{return D::fcvt_wu_d(-256.2);},
|
||||
"fcvt.wu.d, truncate negative");
|
||||
expect<uint64_t>(0, []{return D::fcvt_wu_d(0.0);}, "fcvt.wu.d, 0.0");
|
||||
expect<uint64_t>(0, []{return D::fcvt_wu_d(-0.0);}, "fcvt.wu.d, -0.0");
|
||||
expect<uint64_t>(numeric_limits<uint64_t>::max(),
|
||||
[]{return D::fcvt_wu_d(numeric_limits<double>::max());},
|
||||
"fcvt.wu.d, overflow");
|
||||
expect<uint64_t>(0,[]{return D::fcvt_wu_d(numeric_limits<double>::min());},
|
||||
"fcvt.wu.d, underflow");
|
||||
expect<uint64_t>(numeric_limits<uint64_t>::max(),
|
||||
[]{return D::fcvt_wu_d(numeric_limits<double>::infinity());},
|
||||
"fcvt.wu.d, infinity");
|
||||
expect<uint64_t>(0,
|
||||
[]{return D::fcvt_wu_d(-numeric_limits<double>::infinity());},
|
||||
"fcvt.wu.d, -infinity");
|
||||
expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
|
||||
[]{return D::fcvt_wu_d(numeric_limits<double>::quiet_NaN());},
|
||||
"fcvt.wu.d, quiet NaN");
|
||||
expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
|
||||
[]{return D::fcvt_wu_d(-numeric_limits<double>::quiet_NaN());},
|
||||
"fcvt.wu.d, quiet -NaN");
|
||||
expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
|
||||
[]{return D::fcvt_wu_d(numeric_limits<double>::signaling_NaN());},
|
||||
"fcvt.wu.d, signaling NaN");
|
||||
|
||||
// FCVT.D.W
|
||||
expect<double>(0.0, []{return D::fcvt_d_w(0);}, "fcvt.d.w, 0");
|
||||
expect<double>(-2147483648.0,
|
||||
[]{return D::fcvt_d_w(numeric_limits<int32_t>::min());},
|
||||
"fcvt.d.w, negative");
|
||||
expect<double>(255.0, []{return D::fcvt_d_w(0xFFFFFFFF000000FFLL);},
|
||||
"fcvt.d.w, truncate");
|
||||
|
||||
// FCVT.D.WU
|
||||
expect<double>(0.0, []{return D::fcvt_d_wu(0);}, "fcvt.d.wu, 0");
|
||||
expect<double>(2147483648.0,
|
||||
[]{return D::fcvt_d_wu(numeric_limits<int32_t>::min());},
|
||||
"fcvt.d.wu");
|
||||
expect<double>(255.0,
|
||||
[]{return D::fcvt_d_wu(0xFFFFFFFF000000FFLL);},
|
||||
"fcvt.d.wu, truncate");
|
||||
|
||||
// FCVT.L.D
|
||||
expect<int64_t>(256, []{return D::fcvt_l_d(256.3);},
|
||||
"fcvt.l.d, truncate positive");
|
||||
expect<int64_t>(-256, []{return D::fcvt_l_d(-256.2);},
|
||||
"fcvt.l.d, truncate negative");
|
||||
expect<int64_t>(0, []{return D::fcvt_l_d(0.0);}, "fcvt.l.d, 0.0");
|
||||
expect<int64_t>(0, []{return D::fcvt_l_d(-0.0);}, "fcvt.l.d, -0.0");
|
||||
expect<int64_t>(-8589934592LL, []{return D::fcvt_l_d(-8589934592.0);},
|
||||
"fcvt.l.d, 32-bit overflow");
|
||||
expect<int64_t>(numeric_limits<int64_t>::max(),
|
||||
[]{return D::fcvt_l_d(numeric_limits<double>::max());},
|
||||
"fcvt.l.d, overflow");
|
||||
expect<int64_t>(0, []{return D::fcvt_l_d(numeric_limits<double>::min());},
|
||||
"fcvt.l.d, underflow");
|
||||
expect<int64_t>(numeric_limits<int64_t>::max(),
|
||||
[]{return D::fcvt_l_d(numeric_limits<double>::infinity());},
|
||||
"fcvt.l.d, infinity");
|
||||
expect<int64_t>(numeric_limits<int64_t>::min(),
|
||||
[]{return D::fcvt_l_d(-numeric_limits<double>::infinity());},
|
||||
"fcvt.l.d, -infinity");
|
||||
expect<int64_t>(numeric_limits<int64_t>::max(),
|
||||
[]{return D::fcvt_l_d(numeric_limits<double>::quiet_NaN());},
|
||||
"fcvt.l.d, quiet NaN");
|
||||
expect<int64_t>(numeric_limits<int64_t>::max(),
|
||||
[]{return D::fcvt_l_d(-numeric_limits<double>::quiet_NaN());},
|
||||
"fcvt.l.d, quiet -NaN");
|
||||
expect<int64_t>(numeric_limits<int64_t>::max(),
|
||||
[]{return D::fcvt_l_d(numeric_limits<double>::signaling_NaN());},
|
||||
"fcvt.l.d, signaling NaN");
|
||||
|
||||
// FCVT.LU.D
|
||||
expect<uint64_t>(256, []{return D::fcvt_lu_d(256.3);},
|
||||
"fcvt.lu.d, truncate positive");
|
||||
expect<uint64_t>(0, []{return D::fcvt_lu_d(-256.2);},
|
||||
"fcvt.lu.d, truncate negative");
|
||||
expect<uint64_t>(0, []{return D::fcvt_lu_d(0.0);}, "fcvt.lu.d, 0.0");
|
||||
expect<uint64_t>(0, []{return D::fcvt_lu_d(-0.0);}, "fcvt.lu.d, -0.0");
|
||||
expect<uint64_t>(8589934592LL, []{return D::fcvt_lu_d(8589934592.0);},
|
||||
"fcvt.lu.d, 32-bit overflow");
|
||||
expect<uint64_t>(numeric_limits<uint64_t>::max(),
|
||||
[]{return D::fcvt_lu_d(numeric_limits<double>::max());},
|
||||
"fcvt.lu.d, overflow");
|
||||
expect<uint64_t>(0,[]{return D::fcvt_lu_d(numeric_limits<double>::min());},
|
||||
"fcvt.lu.d, underflow");
|
||||
expect<uint64_t>(numeric_limits<uint64_t>::max(),
|
||||
[]{return D::fcvt_lu_d(numeric_limits<double>::infinity());},
|
||||
"fcvt.lu.d, infinity");
|
||||
expect<uint64_t>(0,
|
||||
[]{return D::fcvt_lu_d(-numeric_limits<double>::infinity());},
|
||||
"fcvt.lu.d, -infinity");
|
||||
expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
|
||||
[]{return D::fcvt_lu_d(numeric_limits<double>::quiet_NaN());},
|
||||
"fcvt.lu.d, quiet NaN");
|
||||
expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
|
||||
[]{return D::fcvt_lu_d(-numeric_limits<double>::quiet_NaN());},
|
||||
"fcvt.lu.d, quiet -NaN");
|
||||
expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
|
||||
[]{return D::fcvt_lu_d(numeric_limits<double>::signaling_NaN());},
|
||||
"fcvt.lu.d, signaling NaN");
|
||||
|
||||
// FMV.X.D
|
||||
expect<uint64_t>(0x40091EB851EB851FULL, []{return D::fmv_x_d(3.14);},
|
||||
"fmv.x.d, positive");
|
||||
expect<uint64_t>(0xC0091EB851EB851FULL, []{return D::fmv_x_d(-3.14);},
|
||||
"fmv.x.d, negative");
|
||||
expect<uint64_t>(0x0000000000000000ULL, []{return D::fmv_x_d(0.0);},
|
||||
"fmv.x.d, 0.0");
|
||||
expect<uint64_t>(0x8000000000000000ULL, []{return D::fmv_x_d(-0.0);},
|
||||
"fmv.x.d, -0.0");
|
||||
|
||||
// FCVT.D.L
|
||||
expect<double>(0.0, []{return D::fcvt_d_l(0);}, "fcvt.d.l, 0");
|
||||
expect<double>(D::number(0xC3E0000000000000),
|
||||
[]{return D::fcvt_d_l(numeric_limits<int64_t>::min());},
|
||||
"fcvt.d.l, negative");
|
||||
expect<double>(D::number(0xC1EFFFFFE0200000),
|
||||
[]{return D::fcvt_d_l(0xFFFFFFFF000000FFLL);},
|
||||
"fcvt.d.l, 32-bit truncate");
|
||||
|
||||
// FCVT.D.LU
|
||||
expect<double>(0.0, []{return D::fcvt_d_lu(0);}, "fcvt.d.lu, 0");
|
||||
expect<double>(D::number(0x43E0000000000000),
|
||||
[]{return D::fcvt_d_lu(numeric_limits<int64_t>::min());},
|
||||
"fcvt.d.lu");
|
||||
expect<double>(D::number(0x43EFFFFFFFE00000),
|
||||
[]{return D::fcvt_d_lu(0xFFFFFFFF000000FFLL);},
|
||||
"fcvt.d.lu, 32-bit truncate");
|
||||
|
||||
// FMV.D.X
|
||||
expect<double>(-numeric_limits<float>::infinity(),
|
||||
[]{return D::fmv_d_x(0xFFF0000000000000ULL);}, "fmv.d.x");
|
||||
|
||||
return 0;
|
||||
}
|
323
tests/test-progs/insttest/src/riscv/rv64d.h
Normal file
323
tests/test-progs/insttest/src/riscv/rv64d.h
Normal file
|
@ -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 <cstdint>
|
||||
#include <limits>
|
||||
|
||||
#include "insttest.h"
|
||||
|
||||
namespace D
|
||||
{
|
||||
|
||||
constexpr inline uint64_t
|
||||
bits(double d)
|
||||
{
|
||||
return reinterpret_cast<uint64_t&>(d);
|
||||
}
|
||||
|
||||
constexpr inline double
|
||||
number(uint64_t b)
|
||||
{
|
||||
return reinterpret_cast<double&>(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<double>::signaling_NaN();
|
||||
asm volatile("fld %0,%1"
|
||||
: "=f" (fd)
|
||||
: "m" (mem));
|
||||
return fd;
|
||||
}
|
||||
|
||||
inline double
|
||||
store(double fs)
|
||||
{
|
||||
double mem = std::numeric_limits<double>::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<double>::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<double>::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<double>::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<double>::signaling_NaN();
|
||||
FR4OP("fnmadd.d", fd, fs1, fs2, fs3);
|
||||
return fd;
|
||||
}
|
||||
|
||||
inline double
|
||||
fadd_d(double fs1, double fs2)
|
||||
{
|
||||
double fd = std::numeric_limits<double>::signaling_NaN();
|
||||
FROP("fadd.d", fd, fs1, fs2);
|
||||
return fd;
|
||||
}
|
||||
|
||||
inline double
|
||||
fsub_d(double fs1, double fs2)
|
||||
{
|
||||
double fd = std::numeric_limits<double>::signaling_NaN();
|
||||
FROP("fsub.d", fd, fs1, fs2);
|
||||
return fd;
|
||||
}
|
||||
|
||||
inline double
|
||||
fmul_d(double fs1, double fs2)
|
||||
{
|
||||
double fd = std::numeric_limits<double>::signaling_NaN();
|
||||
FROP("fmul.d", fd, fs1, fs2);
|
||||
return fd;
|
||||
}
|
||||
|
||||
inline double
|
||||
fdiv_d(double fs1, double fs2)
|
||||
{
|
||||
double fd = std::numeric_limits<double>::signaling_NaN();
|
||||
FROP("fdiv.d", fd, fs1, fs2);
|
||||
return fd;
|
||||
}
|
||||
|
||||
inline double
|
||||
fsqrt_d(double fs1)
|
||||
{
|
||||
double fd = std::numeric_limits<double>::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<double>::signaling_NaN();
|
||||
FROP("fsgnj.d", fd, fs1, fs2);
|
||||
return fd;
|
||||
}
|
||||
|
||||
inline double
|
||||
fsgnjn_d(double fs1, double fs2)
|
||||
{
|
||||
double fd = std::numeric_limits<double>::signaling_NaN();
|
||||
FROP("fsgnjn.d", fd, fs1, fs2);
|
||||
return fd;
|
||||
}
|
||||
|
||||
inline double
|
||||
fsgnjx_d(double fs1, double fs2)
|
||||
{
|
||||
double fd = std::numeric_limits<double>::signaling_NaN();
|
||||
FROP("fsgnjx.d", fd, fs1, fs2);
|
||||
return fd;
|
||||
}
|
||||
|
||||
inline double
|
||||
fmin_d(double fs1, double fs2)
|
||||
{
|
||||
double fd = std::numeric_limits<double>::signaling_NaN();
|
||||
FROP("fmin.d", fd, fs1, fs2);
|
||||
return fd;
|
||||
}
|
||||
|
||||
inline double
|
||||
fmax_d(double fs1, double fs2)
|
||||
{
|
||||
double fd = std::numeric_limits<double>::signaling_NaN();
|
||||
FROP("fmax.d", fd, fs1, fs2);
|
||||
return fd;
|
||||
}
|
||||
|
||||
inline float
|
||||
fcvt_s_d(double fs1)
|
||||
{
|
||||
float fd = std::numeric_limits<float>::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<double>::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<double>::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<double>::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<double>::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<double>::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<double>::signaling_NaN();
|
||||
asm volatile("fmv.d.x %0,%1" : "=f" (fd) : "r" (rs1));
|
||||
return fd;
|
||||
}
|
||||
|
||||
} // namespace D
|
694
tests/test-progs/insttest/src/riscv/rv64f.cpp
Normal file
694
tests/test-progs/insttest/src/riscv/rv64f.cpp
Normal file
|
@ -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 <cstdint>
|
||||
#include <limits>
|
||||
|
||||
#include "insttest.h"
|
||||
#include "rv64f.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace std;
|
||||
using namespace insttest;
|
||||
|
||||
// FLAGS
|
||||
expect<uint64_t>(0, []{
|
||||
F::fsflags(0);
|
||||
return F::frflags();
|
||||
}, "clear fsflags");
|
||||
|
||||
// Memory
|
||||
expect<float>(3.14, []{return F::load(3.14);}, "flw");
|
||||
expect<float>(1.816, []{return F::store(1.816);}, "fsw");
|
||||
|
||||
// FMADD.S
|
||||
expect<float>(7.11624, []{return F::fmadd_s(3.14, 1.816, 1.414);},
|
||||
"fmadd.s");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fmadd_s(numeric_limits<float>::quiet_NaN(), 3.14,
|
||||
1.816);
|
||||
return F::isquietnan(fd);
|
||||
}, "fmadd.s, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fmadd_s(3.14, numeric_limits<float>::signaling_NaN(),
|
||||
1.816);
|
||||
return F::isquietnan(fd);
|
||||
}, "fmadd.s, signaling NaN");
|
||||
expect<float>(numeric_limits<float>::infinity(),
|
||||
[]{return F::fmadd_s(3.14, numeric_limits<float>::infinity(),
|
||||
1.414);},
|
||||
"fmadd.s, infinity");
|
||||
expect<float>(-numeric_limits<float>::infinity(),
|
||||
[]{return F::fmadd_s(3.14, -numeric_limits<float>::infinity(),
|
||||
1.414);},
|
||||
"fmadd.s, -infinity");
|
||||
|
||||
// FMSUB.S
|
||||
expect<float>(4.28824, []{return F::fmsub_s(3.14, 1.816, 1.414);},
|
||||
"fmsub.s");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fmsub_s(3.14, numeric_limits<float>::quiet_NaN(),
|
||||
1.816);
|
||||
return F::isquietnan(fd);
|
||||
}, "fmsub.s, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fmsub_s(3.14, 1.816,
|
||||
numeric_limits<float>::signaling_NaN());
|
||||
return F::isquietnan(fd);
|
||||
}, "fmsub.s, signaling NaN");
|
||||
expect<float>(numeric_limits<float>::infinity(),
|
||||
[]{return F::fmsub_s(numeric_limits<float>::infinity(), 1.816,
|
||||
1.414);},
|
||||
"fmsub.s, infinity");
|
||||
expect<float>(-numeric_limits<float>::infinity(),
|
||||
[]{return F::fmsub_s(3.14, -numeric_limits<float>::infinity(),
|
||||
1.414);},
|
||||
"fmsub.s, -infinity");
|
||||
expect<float>(-numeric_limits<float>::infinity(),
|
||||
[]{return F::fmsub_s(3.14, 1.816,
|
||||
numeric_limits<float>::infinity());},
|
||||
"fmsub.s, subtract infinity");
|
||||
|
||||
// FNMSUB.S
|
||||
expect<float>(-4.28824, []{return F::fnmsub_s(3.14, 1.816, 1.414);},
|
||||
"fnmsub.s");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fnmsub_s(3.14, 1.816,
|
||||
numeric_limits<float>::quiet_NaN());
|
||||
return F::isquietnan(fd);
|
||||
}, "fnmsub.s, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fnmsub_s(numeric_limits<float>::signaling_NaN(),
|
||||
1.816, 1.414);
|
||||
return F::isquietnan(fd);
|
||||
}, "fnmsub.s, signaling NaN");
|
||||
expect<float>(-numeric_limits<float>::infinity(),
|
||||
[]{return F::fnmsub_s(numeric_limits<float>::infinity(),
|
||||
1.816, 1.414);},
|
||||
"fnmsub.s, infinity");
|
||||
expect<float>(numeric_limits<float>::infinity(),
|
||||
[]{return F::fnmsub_s(3.14, -numeric_limits<float>::infinity(),
|
||||
1.414);},
|
||||
"fnmsub.s, -infinity");
|
||||
expect<float>(numeric_limits<float>::infinity(),
|
||||
[]{return F::fnmsub_s(3.14, 1.816,
|
||||
numeric_limits<float>::infinity());},
|
||||
"fnmsub.s, subtract infinity");
|
||||
|
||||
// FNMADD.S
|
||||
expect<float>(-7.11624, []{return F::fnmadd_s(3.14, 1.816, 1.414);},
|
||||
"fnmadd.s");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fnmadd_s(numeric_limits<float>::quiet_NaN(), 3.14,
|
||||
1.816);
|
||||
return F::isquietnan(fd);
|
||||
}, "fnmadd.s, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fnmadd_s(3.14,numeric_limits<float>::signaling_NaN(),
|
||||
1.816);
|
||||
return F::isquietnan(fd);
|
||||
}, "fnmadd.s, signaling NaN");
|
||||
expect<float>(-numeric_limits<float>::infinity(),
|
||||
[]{return F::fnmadd_s(3.14, numeric_limits<float>::infinity(),
|
||||
1.414);},
|
||||
"fnmadd.s, infinity");
|
||||
expect<float>(numeric_limits<float>::infinity(),
|
||||
[]{return F::fnmadd_s(3.14, -numeric_limits<float>::infinity(),
|
||||
1.414);},
|
||||
"fnmadd.s, -infinity");
|
||||
|
||||
// FADD.S
|
||||
expect<float>(4.554, []{return F::fadd_s(3.14, 1.414);}, "fadd.s");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fadd_s(numeric_limits<float>::quiet_NaN(), 1.414);
|
||||
return F::isquietnan(fd);
|
||||
}, "fadd.s, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fadd_s(3.14, numeric_limits<float>::signaling_NaN());
|
||||
return F::isquietnan(fd);
|
||||
}, "fadd.s, signaling NaN");
|
||||
expect<float>(numeric_limits<float>::infinity(),
|
||||
[]{return F::fadd_s(3.14, numeric_limits<float>::infinity());},
|
||||
"fadd.s, infinity");
|
||||
expect<float>(-numeric_limits<float>::infinity(),
|
||||
[]{return F::fadd_s(-numeric_limits<float>::infinity(), 1.816);},
|
||||
"fadd.s, -infinity");
|
||||
|
||||
// FSUB.S
|
||||
expect<float>(F::number(0xbfdced92), []{return F::fsub_s(1.414, 3.14);},
|
||||
"fsub.s");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fsub_s(numeric_limits<float>::quiet_NaN(), 1.414);
|
||||
return F::isquietnan(fd);
|
||||
}, "fsub.s, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fsub_s(3.14, numeric_limits<float>::signaling_NaN());
|
||||
return F::isquietnan(fd);
|
||||
}, "fsub.s, signaling NaN");
|
||||
expect<float>(numeric_limits<float>::infinity(),
|
||||
[]{return F::fsub_s(numeric_limits<float>::infinity(), 3.14);},
|
||||
"fsub.s, infinity");
|
||||
expect<float>(-numeric_limits<float>::infinity(),
|
||||
[]{return F::fsub_s(-numeric_limits<float>::infinity(), 3.14);},
|
||||
"fsub.s, -infinity");
|
||||
expect<float>(-numeric_limits<float>::infinity(),
|
||||
[]{return F::fsub_s(1.414, numeric_limits<float>::infinity());},
|
||||
"fsub.s, subtract infinity");
|
||||
|
||||
// FMUL.S
|
||||
expect<float>(F::number(0x4024573b), []{return F::fmul_s(1.816, 1.414);},
|
||||
"fmul.s");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fmul_s(numeric_limits<float>::quiet_NaN(), 1.414);
|
||||
return F::isquietnan(fd);
|
||||
}, "fmul.s, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fmul_s(1.816,
|
||||
numeric_limits<float>::signaling_NaN());
|
||||
return F::isquietnan(fd);
|
||||
}, "fmul.s, signaling NaN");
|
||||
expect<float>(numeric_limits<float>::infinity(),
|
||||
[]{return F::fmul_s(numeric_limits<float>::infinity(), 2.718);},
|
||||
"fmul.s, infinity");
|
||||
expect<float>(-numeric_limits<float>::infinity(),
|
||||
[]{return F::fmul_s(2.5966, -numeric_limits<float>::infinity());},
|
||||
"fmul.s, -infinity");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fmul_s(0.0, numeric_limits<float>::infinity());
|
||||
return F::isquietnan(fd);
|
||||
}, "fmul.s, 0*infinity");
|
||||
expect<float>(numeric_limits<float>::infinity(),
|
||||
[]{return F::fmul_s(numeric_limits<float>::max(), 2.0);},
|
||||
"fmul.s, overflow");
|
||||
expect<float>(0.0,
|
||||
[]{return F::fmul_s(numeric_limits<float>::min(),
|
||||
numeric_limits<float>::min());},
|
||||
"fmul.s, underflow");
|
||||
|
||||
// FDIV.S
|
||||
expect<float>(2.5, []{return F::fdiv_s(10.0, 4.0);}, "fdiv.s");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fdiv_s(numeric_limits<float>::quiet_NaN(), 4.0);
|
||||
return F::isquietnan(fd);
|
||||
}, "fdiv.s, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fdiv_s(10.0, numeric_limits<float>::signaling_NaN());
|
||||
return F::isquietnan(fd);
|
||||
}, "fdiv.s, signaling NaN");
|
||||
expect<float>(numeric_limits<float>::infinity(),
|
||||
[]{return F::fdiv_s(10.0, 0.0);}, "fdiv.s/0");
|
||||
expect<float>(0.0,
|
||||
[]{return F::fdiv_s(10.0, numeric_limits<float>::infinity());},
|
||||
"fdiv.s/infinity");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fdiv_s(numeric_limits<float>::infinity(),
|
||||
numeric_limits<float>::infinity());
|
||||
return F::isquietnan(fd);
|
||||
}, "fdiv.s, infinity/infinity");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fdiv_s(0.0, 0.0);
|
||||
return F::isquietnan(fd);
|
||||
}, "fdiv.s, 0/0");
|
||||
expect<float>(numeric_limits<float>::infinity(),
|
||||
[]{return F::fdiv_s(numeric_limits<float>::infinity(), 0.0);},
|
||||
"fdiv.s, infinity/0");
|
||||
expect<float>(0.0,
|
||||
[]{return F::fdiv_s(0.0, numeric_limits<float>::infinity());},
|
||||
"fdiv.s, 0/infinity");
|
||||
expect<float>(0.0,
|
||||
[]{return F::fdiv_s(numeric_limits<float>::min(),
|
||||
numeric_limits<float>::max());},
|
||||
"fdiv.s, underflow");
|
||||
expect<float>(numeric_limits<float>::infinity(),
|
||||
[]{return F::fdiv_s(numeric_limits<float>::max(),
|
||||
numeric_limits<float>::min());},
|
||||
"fdiv.s, overflow");
|
||||
|
||||
// FSQRT.S
|
||||
expect<float>(0.3, []{return F::fsqrt_s(0.09);}, "fsqrt.s");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fsqrt_s(-1.0);
|
||||
return F::isquietnan(fd);
|
||||
}, "fsqrt.s, NaN");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fsqrt_s(numeric_limits<float>::quiet_NaN());
|
||||
return F::isquietnan(fd);
|
||||
}, "fsqrt.s, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fsqrt_s(numeric_limits<float>::signaling_NaN());
|
||||
return F::isquietnan(fd);
|
||||
}, "fsqrt.s, signaling NaN");
|
||||
expect<float>(numeric_limits<float>::infinity(),
|
||||
[]{return F::fsqrt_s(numeric_limits<float>::infinity());},
|
||||
"fsqrt.s, infinity");
|
||||
|
||||
// FSGNJ.S
|
||||
expect<float>(1.0, []{return F::fsgnj_s(1.0, 25.0);}, "fsgnj.s, ++");
|
||||
expect<float>(-1.0, []{return F::fsgnj_s(1.0, -25.0);}, "fsgnj.s, +-");
|
||||
expect<float>(1.0, []{return F::fsgnj_s(-1.0, 25.0);}, "fsgnj.s, -+");
|
||||
expect<float>(-1.0, []{return F::fsgnj_s(-1.0, -25.0);}, "fsgnj.s, --");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fsgnj_s(numeric_limits<float>::quiet_NaN(), -4.0);
|
||||
return F::isquietnan(fd);
|
||||
}, "fsgnj.s, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fsgnj_s(numeric_limits<float>::signaling_NaN(),
|
||||
-4.0);
|
||||
return F::issignalingnan(fd);
|
||||
}, "fsgnj.s, signaling NaN");
|
||||
expect<float>(4.0, []{return F::fsgnj_s(4.0,
|
||||
numeric_limits<float>::quiet_NaN());}, "fsgnj.s, inject NaN");
|
||||
expect<float>(-4.0,
|
||||
[]{return F::fsgnj_s(4.0, -numeric_limits<float>::quiet_NaN());},
|
||||
"fsgnj.s, inject -NaN");
|
||||
|
||||
// FSGNJN.S
|
||||
expect<float>(-1.0, []{return F::fsgnjn_s(1.0, 25.0);}, "fsgnjn.s, ++");
|
||||
expect<float>(1.0, []{return F::fsgnjn_s(1.0, -25.0);}, "fsgnjn.s, +-");
|
||||
expect<float>(-1.0, []{return F::fsgnjn_s(-1.0, 25.0);}, "fsgnjn.s, -+");
|
||||
expect<float>(1.0, []{return F::fsgnjn_s(-1.0, -25.0);}, "fsgnjn.s, --");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fsgnjn_s(numeric_limits<float>::quiet_NaN(), -4.0);
|
||||
return F::isquietnan(fd);
|
||||
}, "fsgnjn.s, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fsgnjn_s(numeric_limits<float>::signaling_NaN(),
|
||||
-4.0);
|
||||
return F::issignalingnan(fd);
|
||||
}, "fsgnjn.s, signaling NaN");
|
||||
expect<float>(-4.0,
|
||||
[]{return F::fsgnjn_s(4.0, numeric_limits<float>::quiet_NaN());},
|
||||
"fsgnjn.s, inject NaN");
|
||||
expect<float>(4.0,
|
||||
[]{return F::fsgnjn_s(4.0, -numeric_limits<float>::quiet_NaN());},
|
||||
"fsgnjn.s, inject NaN");
|
||||
|
||||
// FSGNJX.S
|
||||
expect<float>(1.0, []{return F::fsgnjx_s(1.0, 25.0);}, "fsgnjx.s, ++");
|
||||
expect<float>(-1.0, []{return F::fsgnjx_s(1.0, -25.0);}, "fsgnjx.s, +-");
|
||||
expect<float>(-1.0, []{return F::fsgnjx_s(-1.0, 25.0);}, "fsgnjx.s, -+");
|
||||
expect<float>(1.0, []{return F::fsgnjx_s(-1.0, -25.0);}, "fsgnjx.s, --");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fsgnjx_s(numeric_limits<float>::quiet_NaN(), -4.0);
|
||||
return F::isquietnan(fd);
|
||||
}, "fsgnjx.s, quiet NaN");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fsgnjx_s(numeric_limits<float>::signaling_NaN(),
|
||||
-4.0);
|
||||
return F::issignalingnan(fd);
|
||||
}, "fsgnjx.s, signaling NaN");
|
||||
expect<float>(4.0,
|
||||
[]{return F::fsgnjx_s(4.0, numeric_limits<float>::quiet_NaN());},
|
||||
"fsgnjx.s, inject NaN");
|
||||
expect<float>(-4.0,
|
||||
[]{return F::fsgnjx_s(4.0, -numeric_limits<float>::quiet_NaN());},
|
||||
"fsgnjx.s, inject -NaN");
|
||||
|
||||
// FMIN.S
|
||||
expect<float>(2.718, []{return F::fmin_s(3.14, 2.718);}, "fmin.s");
|
||||
expect<float>(-numeric_limits<float>::infinity(),
|
||||
[]{return F::fmin_s(-numeric_limits<float>::infinity(),
|
||||
numeric_limits<float>::min());},
|
||||
"fmin.s, -infinity");
|
||||
expect<float>(numeric_limits<float>::max(),
|
||||
[]{return F::fmin_s(numeric_limits<float>::infinity(),
|
||||
numeric_limits<float>::max());},
|
||||
"fmin.s, infinity");
|
||||
expect<float>(-1.414,
|
||||
[]{return F::fmin_s(numeric_limits<float>::quiet_NaN(), -1.414);},
|
||||
"fmin.s, quiet NaN first");
|
||||
expect<float>(2.718,
|
||||
[]{return F::fmin_s(2.718, numeric_limits<float>::quiet_NaN());},
|
||||
"fmin.s, quiet NaN second");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fmin_s(numeric_limits<float>::quiet_NaN(),
|
||||
numeric_limits<float>::quiet_NaN());
|
||||
return F::isquietnan(fd);
|
||||
}, "fmin.s, quiet NaN both");
|
||||
expect<float>(3.14,
|
||||
[]{return F::fmin_s(numeric_limits<float>::signaling_NaN(),
|
||||
3.14);},
|
||||
"fmin.s, signaling NaN first");
|
||||
expect<float>(1.816,
|
||||
[]{return F::fmin_s(1.816,
|
||||
numeric_limits<float>::signaling_NaN());},
|
||||
"fmin.s, signaling NaN second");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fmin_s(numeric_limits<float>::signaling_NaN(),
|
||||
numeric_limits<float>::signaling_NaN());
|
||||
return F::issignalingnan(fd);
|
||||
}, "fmin.s, signaling NaN both");
|
||||
|
||||
// FMAX.S
|
||||
expect<float>(3.14, []{return F::fmax_s(3.14, 2.718);}, "fmax.s");
|
||||
expect<float>(numeric_limits<float>::min(),
|
||||
[]{return F::fmax_s(-numeric_limits<float>::infinity(),
|
||||
numeric_limits<float>::min());},
|
||||
"fmax.s, -infinity");
|
||||
expect<float>(numeric_limits<float>::infinity(),
|
||||
[]{return F::fmax_s(numeric_limits<float>::infinity(),
|
||||
numeric_limits<float>::max());},
|
||||
"fmax.s, infinity");
|
||||
expect<float>(-1.414,
|
||||
[]{return F::fmax_s(numeric_limits<float>::quiet_NaN(), -1.414);},
|
||||
"fmax.s, quiet NaN first");
|
||||
expect<float>(2.718,
|
||||
[]{return F::fmax_s(2.718, numeric_limits<float>::quiet_NaN());},
|
||||
"fmax.s, quiet NaN second");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fmax_s(numeric_limits<float>::quiet_NaN(),
|
||||
numeric_limits<float>::quiet_NaN());
|
||||
return F::isquietnan(fd);
|
||||
}, "fmax.s, quiet NaN both");
|
||||
expect<float>(3.14,
|
||||
[]{return F::fmax_s(numeric_limits<float>::signaling_NaN(),
|
||||
3.14);},
|
||||
"fmax.s, signaling NaN first");
|
||||
expect<float>(1.816, []{return F::fmax_s(1.816,
|
||||
numeric_limits<float>::signaling_NaN());},
|
||||
"fmax.s, signaling NaN second");
|
||||
expect<bool>(true, []{
|
||||
float fd = F::fmax_s(numeric_limits<float>::signaling_NaN(),
|
||||
numeric_limits<float>::signaling_NaN());
|
||||
return F::issignalingnan(fd);
|
||||
}, "fmax.s, signaling NaN both");
|
||||
|
||||
// FCVT.W.S
|
||||
expect<int64_t>(256, []{return F::fcvt_w_s(256.3);},
|
||||
"fcvt.w.s, truncate positive");
|
||||
expect<int64_t>(-256, []{return F::fcvt_w_s(-256.2);},
|
||||
"fcvt.w.s, truncate negative");
|
||||
expect<int64_t>(0, []{return F::fcvt_w_s(0.0);}, "fcvt.w.s, 0.0");
|
||||
expect<int64_t>(0, []{return F::fcvt_w_s(-0.0);}, "fcvt.w.s, -0.0");
|
||||
expect<int64_t>(numeric_limits<int32_t>::max(),
|
||||
[]{return F::fcvt_w_s(numeric_limits<float>::max());},
|
||||
"fcvt.w.s, overflow");
|
||||
expect<int64_t>(0, []{return F::fcvt_w_s(numeric_limits<float>::min());},
|
||||
"fcvt.w.s, underflow");
|
||||
expect<int64_t>(numeric_limits<int32_t>::max(),
|
||||
[]{return F::fcvt_w_s(numeric_limits<float>::infinity());},
|
||||
"fcvt.w.s, infinity");
|
||||
expect<int64_t>(numeric_limits<int32_t>::min(),
|
||||
[]{return F::fcvt_w_s(-numeric_limits<float>::infinity());},
|
||||
"fcvt.w.s, -infinity");
|
||||
expect<int64_t>(numeric_limits<int32_t>::max(),
|
||||
[]{return F::fcvt_w_s(numeric_limits<float>::quiet_NaN());},
|
||||
"fcvt.w.s, quiet NaN");
|
||||
expect<int64_t>(numeric_limits<int32_t>::max(),
|
||||
[]{return F::fcvt_w_s(-numeric_limits<float>::quiet_NaN());},
|
||||
"fcvt.w.s, quiet -NaN");
|
||||
expect<int64_t>(numeric_limits<int32_t>::max(),
|
||||
[]{return F::fcvt_w_s(numeric_limits<float>::signaling_NaN());},
|
||||
"fcvt.w.s, signaling NaN");
|
||||
|
||||
// FCVT.WU.S
|
||||
expect<uint64_t>(256, []{return F::fcvt_wu_s(256.3);},
|
||||
"fcvt.wu.s, truncate positive");
|
||||
expect<uint64_t>(0, []{return F::fcvt_wu_s(-256.2);},
|
||||
"fcvt.wu.s, truncate negative");
|
||||
expect<uint64_t>(0, []{return F::fcvt_wu_s(0.0);}, "fcvt.wu.s, 0.0");
|
||||
expect<uint64_t>(0, []{return F::fcvt_wu_s(-0.0);}, "fcvt.wu.s, -0.0");
|
||||
expect<uint64_t>(numeric_limits<uint64_t>::max(),
|
||||
[]{return F::fcvt_wu_s(numeric_limits<float>::max());},
|
||||
"fcvt.wu.s, overflow");
|
||||
expect<uint64_t>(0, []{return F::fcvt_wu_s(numeric_limits<float>::min());},
|
||||
"fcvt.wu.s, underflow");
|
||||
expect<uint64_t>(numeric_limits<uint64_t>::max(),
|
||||
[]{return F::fcvt_wu_s(numeric_limits<float>::infinity());},
|
||||
"fcvt.wu.s, infinity");
|
||||
expect<uint64_t>(0,
|
||||
[]{return F::fcvt_wu_s(-numeric_limits<float>::infinity());},
|
||||
"fcvt.wu.s, -infinity");
|
||||
expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
|
||||
[]{return F::fcvt_wu_s(numeric_limits<float>::quiet_NaN());},
|
||||
"fcvt.wu.s, quiet NaN");
|
||||
expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
|
||||
[]{return F::fcvt_wu_s(-numeric_limits<float>::quiet_NaN());},
|
||||
"fcvt.wu.s, quiet -NaN");
|
||||
expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
|
||||
[]{return F::fcvt_wu_s(numeric_limits<float>::signaling_NaN());},
|
||||
"fcvt.wu.s, signaling NaN");
|
||||
|
||||
// FMV.X.S
|
||||
expect<uint64_t>(0x000000004048F5C3ULL, []{return F::fmv_x_s(3.14);},
|
||||
"fmv.x.s, positive");
|
||||
expect<uint64_t>(0xFFFFFFFFC048F5C3ULL, []{return F::fmv_x_s(-3.14);},
|
||||
"fmv.x.s, negative");
|
||||
expect<uint64_t>(0x0000000000000000ULL, []{return F::fmv_x_s(0.0);},
|
||||
"fmv.x.s, 0.0");
|
||||
expect<uint64_t>(0xFFFFFFFF80000000ULL, []{return F::fmv_x_s(-0.0);},
|
||||
"fmv.x.s, -0.0");
|
||||
|
||||
// FEQ.S
|
||||
expect<bool>(true, []{return F::feq_s(1.414, 1.414);}, "feq.s, equal");
|
||||
expect<bool>(false, []{return F::feq_s(2.718, 1.816);},
|
||||
"feq.s, not equal");
|
||||
expect<bool>(true, []{return F::feq_s(0.0, -0.0);}, "feq.s, 0 == -0");
|
||||
expect<bool>(false,
|
||||
[]{return F::feq_s(numeric_limits<float>::quiet_NaN(), -1.0);},
|
||||
"feq.s, quiet NaN first");
|
||||
expect<bool>(false,
|
||||
[]{return F::feq_s(2.0, numeric_limits<float>::quiet_NaN());},
|
||||
"feq.s, quiet NaN second");
|
||||
expect<bool>(false,
|
||||
[]{return F::feq_s(numeric_limits<float>::quiet_NaN(),
|
||||
numeric_limits<float>::quiet_NaN());},
|
||||
"feq.s, quiet NaN both");
|
||||
expect<bool>(false,
|
||||
[]{return F::feq_s(numeric_limits<float>::signaling_NaN(), -1.0);},
|
||||
"feq.s, signaling NaN first");
|
||||
expect<bool>(false,
|
||||
[]{return F::feq_s(2.0, numeric_limits<float>::signaling_NaN());},
|
||||
"feq.s, signaling NaN second");
|
||||
expect<bool>(false,
|
||||
[]{return F::feq_s(numeric_limits<float>::signaling_NaN(),
|
||||
numeric_limits<float>::signaling_NaN());},
|
||||
"feq.s, signaling NaN both");
|
||||
|
||||
// FLT.S
|
||||
expect<bool>(false, []{return F::flt_s(1.414, 1.414);}, "flt.s, equal");
|
||||
expect<bool>(true, []{return F::flt_s(1.816, 2.718);}, "flt.s, less");
|
||||
expect<bool>(false, []{return F::flt_s(2.718, 1.816);}, "flt.s, greater");
|
||||
expect<bool>(false,
|
||||
[]{return F::flt_s(numeric_limits<float>::quiet_NaN(), -1.0);},
|
||||
"flt.s, quiet NaN first");
|
||||
expect<bool>(false,
|
||||
[]{return F::flt_s(2.0, numeric_limits<float>::quiet_NaN());},
|
||||
"flt.s, quiet NaN second");
|
||||
expect<bool>(false,
|
||||
[]{return F::flt_s(numeric_limits<float>::quiet_NaN(),
|
||||
numeric_limits<float>::quiet_NaN());},
|
||||
"flt.s, quiet NaN both");
|
||||
expect<bool>(false,
|
||||
[]{return F::flt_s(numeric_limits<float>::signaling_NaN(), -1.0);},
|
||||
"flt.s, signaling NaN first");
|
||||
expect<bool>(false,
|
||||
[]{return F::flt_s(2.0, numeric_limits<float>::signaling_NaN());},
|
||||
"flt.s, signaling NaN second");
|
||||
expect<bool>(false,
|
||||
[]{return F::flt_s(numeric_limits<float>::signaling_NaN(),
|
||||
numeric_limits<float>::signaling_NaN());},
|
||||
"flt.s, signaling NaN both");
|
||||
|
||||
// FLE.S
|
||||
expect<bool>(true, []{return F::fle_s(1.414, 1.414);}, "fle.s, equal");
|
||||
expect<bool>(true, []{return F::fle_s(1.816, 2.718);}, "fle.s, less");
|
||||
expect<bool>(false, []{return F::fle_s(2.718, 1.816);}, "fle.s, greater");
|
||||
expect<bool>(true, []{return F::fle_s(0.0, -0.0);}, "fle.s, 0 == -0");
|
||||
expect<bool>(false,
|
||||
[]{return F::fle_s(numeric_limits<float>::quiet_NaN(), -1.0);},
|
||||
"fle.s, quiet NaN first");
|
||||
expect<bool>(false,
|
||||
[]{return F::fle_s(2.0, numeric_limits<float>::quiet_NaN());},
|
||||
"fle.s, quiet NaN second");
|
||||
expect<bool>(false,
|
||||
[]{return F::fle_s(numeric_limits<float>::quiet_NaN(),
|
||||
numeric_limits<float>::quiet_NaN());},
|
||||
"fle.s, quiet NaN both");
|
||||
expect<bool>(false,
|
||||
[]{return F::fle_s(numeric_limits<float>::signaling_NaN(), -1.0);},
|
||||
"fle.s, signaling NaN first");
|
||||
expect<bool>(false,
|
||||
[]{return F::fle_s(2.0, numeric_limits<float>::signaling_NaN());},
|
||||
"fle.s, signaling NaN second");
|
||||
expect<bool>(false,
|
||||
[]{return F::fle_s(numeric_limits<float>::signaling_NaN(),
|
||||
numeric_limits<float>::signaling_NaN());},
|
||||
"fle.s, signaling NaN both");
|
||||
|
||||
// FCLASS.S
|
||||
expect<uint64_t>(0x1,
|
||||
[]{return F::fclass_s(-numeric_limits<float>::infinity());},
|
||||
"fclass.s, -infinity");
|
||||
expect<uint64_t>(0x2, []{return F::fclass_s(-3.14);}, "fclass.s, -normal");
|
||||
expect<uint64_t>(0x4, []{return F::fclass_s(F::number(0x807FFFFF));},
|
||||
"fclass.s, -subnormal");
|
||||
expect<uint64_t>(0x8, []{return F::fclass_s(-0.0);}, "fclass.s, -0.0");
|
||||
expect<uint64_t>(0x10, []{return F::fclass_s(0.0);}, "fclass.s, 0.0");
|
||||
expect<uint64_t>(0x20, []{return F::fclass_s(F::number(0x007FFFFF));},
|
||||
"fclass.s, subnormal");
|
||||
expect<uint64_t>(0x40, []{return F::fclass_s(1.816);}, "fclass.s, normal");
|
||||
expect<uint64_t>(0x80,
|
||||
[]{return F::fclass_s(numeric_limits<float>::infinity());},
|
||||
"fclass.s, infinity");
|
||||
expect<uint64_t>(0x100,
|
||||
[]{return F::fclass_s(numeric_limits<float>::signaling_NaN());},
|
||||
"fclass.s, signaling NaN");
|
||||
expect<uint64_t>(0x200,
|
||||
[]{return F::fclass_s(numeric_limits<float>::quiet_NaN());},
|
||||
"fclass.s, quiet NaN");
|
||||
|
||||
// FCVT.S.W
|
||||
expect<float>(0.0, []{return F::fcvt_s_w(0);}, "fcvt.s.w, 0");
|
||||
expect<float>(-2147483648.0,
|
||||
[]{return F::fcvt_s_w(numeric_limits<int32_t>::min());},
|
||||
"fcvt.s.w, negative");
|
||||
expect<float>(255.0, []{return F::fcvt_s_w(0xFFFFFFFF000000FFLL);},
|
||||
"fcvt.s.w, truncate");
|
||||
|
||||
// FCVT.S.WU
|
||||
expect<float>(0.0, []{return F::fcvt_s_wu(0);}, "fcvt.s.wu, 0");
|
||||
expect<float>(2147483648.0,
|
||||
[]{return F::fcvt_s_wu(numeric_limits<int32_t>::min());},
|
||||
"fcvt.s.wu");
|
||||
expect<float>(255.0, []{return F::fcvt_s_wu(0xFFFFFFFF000000FFLL);},
|
||||
"fcvt.s.wu, truncate");
|
||||
|
||||
// FMV.S.X
|
||||
expect<float>(numeric_limits<float>::infinity(),
|
||||
[]{return F::fmv_s_x(0x7F800000);}, "fmv.s.x");
|
||||
expect<float>(-0.0, []{return F::fmv_s_x(0xFFFFFFFF80000000ULL);},
|
||||
"fmv.s.x, truncate");
|
||||
|
||||
// FCSR functions
|
||||
int rm = F::frrm();
|
||||
expect<uint64_t>(0x7, []{ // FSRM
|
||||
F::fsrm(-1);
|
||||
return F::frrm();
|
||||
}, "fsrm");
|
||||
expect<uint64_t>(0x1F, []{ // FSFLAGS
|
||||
F::fsflags(0);
|
||||
F::fsflags(-1);
|
||||
return F::frflags();
|
||||
}, "fsflags");
|
||||
expect<uint64_t>(0xFF, []{ // FSCSR
|
||||
F::fsflags(0);
|
||||
F::fsrm(0);
|
||||
F::fscsr(-1);
|
||||
return F::frcsr();
|
||||
}, "fscsr");
|
||||
expect<int>(rm << 5, [=]{
|
||||
F::fscsr(0);
|
||||
F::fsrm(rm);
|
||||
return F::frcsr();
|
||||
}, "restore initial round mode");
|
||||
|
||||
F::fsflags(0);
|
||||
|
||||
// FCVT.L.S
|
||||
expect<int64_t>(256, []{return F::fcvt_l_s(256.3);},
|
||||
"fcvt.l.s, truncate positive");
|
||||
expect<int64_t>(-256, []{return F::fcvt_l_s(-256.2);},
|
||||
"fcvt.l.s, truncate negative");
|
||||
expect<int64_t>(0, []{return F::fcvt_l_s(0.0);}, "fcvt.l.s, 0.0");
|
||||
expect<int64_t>(0, []{return F::fcvt_l_s(-0.0);}, "fcvt.l.s, -0.0");
|
||||
expect<int64_t>(-8589934592LL, []{return F::fcvt_l_s(-8589934592.0);},
|
||||
"fcvt.l.s, 32-bit overflow");
|
||||
expect<int64_t>(numeric_limits<int64_t>::max(),
|
||||
[]{return F::fcvt_l_s(numeric_limits<float>::max());},
|
||||
"fcvt.l.s, overflow");
|
||||
expect<int64_t>(0, []{return F::fcvt_l_s(numeric_limits<float>::min());},
|
||||
"fcvt.l.s, underflow");
|
||||
expect<int64_t>(numeric_limits<int64_t>::max(),
|
||||
[]{return F::fcvt_l_s(numeric_limits<float>::infinity());},
|
||||
"fcvt.l.s, infinity");
|
||||
expect<int64_t>(numeric_limits<int64_t>::min(),
|
||||
[]{return F::fcvt_l_s(-numeric_limits<float>::infinity());},
|
||||
"fcvt.l.s, -infinity");
|
||||
expect<int64_t>(numeric_limits<int64_t>::max(),
|
||||
[]{return F::fcvt_l_s(numeric_limits<float>::quiet_NaN());},
|
||||
"fcvt.l.s, quiet NaN");
|
||||
expect<int64_t>(numeric_limits<int64_t>::max(),
|
||||
[]{return F::fcvt_l_s(-numeric_limits<float>::quiet_NaN());},
|
||||
"fcvt.l.s, quiet -NaN");
|
||||
expect<int64_t>(numeric_limits<int64_t>::max(),
|
||||
[]{return F::fcvt_l_s(numeric_limits<float>::signaling_NaN());},
|
||||
"fcvt.l.s, signaling NaN");
|
||||
|
||||
// FCVT.LU.S
|
||||
expect<uint64_t>(256, []{return F::fcvt_lu_s(256.3);},
|
||||
"fcvt.lu.s, truncate positive");
|
||||
expect<uint64_t>(0, []{return F::fcvt_lu_s(-256.2);},
|
||||
"fcvt.lu.s, truncate negative");
|
||||
expect<uint64_t>(0, []{return F::fcvt_lu_s(0.0);}, "fcvt.lu.s, 0.0");
|
||||
expect<uint64_t>(0, []{return F::fcvt_lu_s(-0.0);}, "fcvt.lu.s, -0.0");
|
||||
expect<uint64_t>(8589934592LL,
|
||||
[]{return F::fcvt_lu_s(8589934592.0);},
|
||||
"fcvt.lu.s, 32-bit overflow");
|
||||
expect<uint64_t>(numeric_limits<uint64_t>::max(),
|
||||
[]{return F::fcvt_lu_s(numeric_limits<float>::max());},
|
||||
"fcvt.lu.s, overflow");
|
||||
expect<uint64_t>(0, []{return F::fcvt_lu_s(numeric_limits<float>::min());},
|
||||
"fcvt.lu.s, underflow");
|
||||
expect<uint64_t>(numeric_limits<uint64_t>::max(),
|
||||
[]{return F::fcvt_lu_s(numeric_limits<float>::infinity());},
|
||||
"fcvt.lu.s, infinity");
|
||||
expect<uint64_t>(0,
|
||||
[]{return F::fcvt_lu_s(-numeric_limits<float>::infinity());},
|
||||
"fcvt.lu.s, -infinity");
|
||||
expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
|
||||
[]{return F::fcvt_lu_s(numeric_limits<float>::quiet_NaN());},
|
||||
"fcvt.lu.s, quiet NaN");
|
||||
expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
|
||||
[]{return F::fcvt_lu_s(-numeric_limits<float>::quiet_NaN());},
|
||||
"fcvt.lu.s, quiet -NaN");
|
||||
expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
|
||||
[]{return F::fcvt_lu_s(numeric_limits<float>::signaling_NaN());},
|
||||
"fcvt.lu.s, signaling NaN");
|
||||
|
||||
// FCVT.S.L
|
||||
expect<float>(0.0, []{return F::fcvt_s_l(0);}, "fcvt.s.l, 0");
|
||||
expect<float>(-9.223372e18,
|
||||
[]{return F::fcvt_s_l(numeric_limits<int64_t>::min());},
|
||||
"fcvt.s.l, negative");
|
||||
expect<float>(-4.29496704e9, []{return F::fcvt_s_l(0xFFFFFFFF000000FFLL);},
|
||||
"fcvt.s.l, 32-bit truncate");
|
||||
|
||||
// FCVT.S.LU
|
||||
expect<float>(0.0, []{return F::fcvt_s_lu(0);}, "fcvt.s.lu, 0");
|
||||
expect<float>(9.223372e18,
|
||||
[]{return F::fcvt_s_lu(numeric_limits<int64_t>::min());},
|
||||
"fcvt.s.lu");
|
||||
expect<float>(1.8446744e19, []{return F::fcvt_s_lu(0xFFFFFFFF000000FFLL);},
|
||||
"fcvt.s.lu, 32-bit truncate");
|
||||
|
||||
return 0;
|
||||
}
|
357
tests/test-progs/insttest/src/riscv/rv64f.h
Normal file
357
tests/test-progs/insttest/src/riscv/rv64f.h
Normal file
|
@ -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 <cstdint>
|
||||
#include <limits>
|
||||
|
||||
#include "insttest.h"
|
||||
|
||||
namespace F
|
||||
{
|
||||
|
||||
constexpr inline uint32_t
|
||||
bits(float f)
|
||||
{
|
||||
return reinterpret_cast<uint32_t&>(f);
|
||||
}
|
||||
|
||||
constexpr inline float
|
||||
number(uint32_t b)
|
||||
{
|
||||
return reinterpret_cast<float&>(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<float>::signaling_NaN();
|
||||
asm volatile("flw %0,%1"
|
||||
: "=f" (fd)
|
||||
: "m" (mem));
|
||||
return fd;
|
||||
}
|
||||
|
||||
inline float
|
||||
store(float fs)
|
||||
{
|
||||
float mem = std::numeric_limits<float>::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<float>::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<float>::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<float>::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<float>::signaling_NaN();
|
||||
FR4OP("fnmadd.s", fd, fs1, fs2, fs3);
|
||||
return fd;
|
||||
}
|
||||
|
||||
inline float
|
||||
fadd_s(float fs1, float fs2)
|
||||
{
|
||||
float fd = std::numeric_limits<float>::signaling_NaN();
|
||||
FROP("fadd.s", fd, fs1, fs2);
|
||||
return fd;
|
||||
}
|
||||
|
||||
inline float
|
||||
fsub_s(float fs1, float fs2)
|
||||
{
|
||||
float fd = std::numeric_limits<float>::signaling_NaN();
|
||||
FROP("fsub.s", fd, fs1, fs2);
|
||||
return fd;
|
||||
}
|
||||
|
||||
inline float
|
||||
fmul_s(float fs1, float fs2)
|
||||
{
|
||||
float fd = std::numeric_limits<float>::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<float>::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<float>::signaling_NaN();
|
||||
FROP("fsgnj.s", fd, fs1, fs2);
|
||||
return fd;
|
||||
}
|
||||
|
||||
inline float
|
||||
fsgnjn_s(float fs1, float fs2)
|
||||
{
|
||||
float fd = std::numeric_limits<float>::signaling_NaN();
|
||||
FROP("fsgnjn.s", fd, fs1, fs2);
|
||||
return fd;
|
||||
}
|
||||
|
||||
inline float
|
||||
fsgnjx_s(float fs1, float fs2)
|
||||
{
|
||||
float fd = std::numeric_limits<float>::signaling_NaN();
|
||||
FROP("fsgnjx.s", fd, fs1, fs2);
|
||||
return fd;
|
||||
}
|
||||
|
||||
inline float
|
||||
fmin_s(float fs1, float fs2)
|
||||
{
|
||||
float fd = std::numeric_limits<float>::signaling_NaN();
|
||||
FROP("fmin.s", fd, fs1, fs2);
|
||||
return fd;
|
||||
}
|
||||
|
||||
inline float
|
||||
fmax_s(float fs1, float fs2)
|
||||
{
|
||||
float fd = std::numeric_limits<float>::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<float>::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<float>::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<float>::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<float>::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<float>::signaling_NaN();
|
||||
asm volatile("fcvt.s.lu %0,%1" : "=f" (fd) : "r" (rs1));
|
||||
return fd;
|
||||
}
|
||||
|
||||
} // namespace F
|
432
tests/test-progs/insttest/src/riscv/rv64i.cpp
Normal file
432
tests/test-progs/insttest/src/riscv/rv64i.cpp
Normal file
|
@ -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 <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/times.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
#include "insttest.h"
|
||||
#include "rv64i.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace std;
|
||||
using namespace insttest;
|
||||
|
||||
// LUI
|
||||
expect<int64_t>(4096, []{return I::lui(1);}, "lui");
|
||||
expect<int64_t>(numeric_limits<int32_t>::min(),
|
||||
[]{return I::lui(0x80000);}, "lui, negative");
|
||||
|
||||
// AUIPC
|
||||
expect<bool>(true, []{return I::auipc(3);}, "auipc");
|
||||
|
||||
// Jump (JAL, JALR)
|
||||
expect<bool>(true, []{return I::jal();}, "jal");
|
||||
expect<bool>(true, []{return I::jalr();}, "jalr");
|
||||
|
||||
// BEQ
|
||||
expect<bool>(true, []{return I::beq(5, 5);}, "beq, equal");
|
||||
expect<bool>(false, []{return I::beq(numeric_limits<int64_t>::max(),
|
||||
numeric_limits<int64_t>::min());}, "beq, not equal");
|
||||
|
||||
// BNE
|
||||
expect<bool>(false, []{return I::bne(5, 5);}, "bne, equal");
|
||||
expect<bool>(true, []{return I::bne(numeric_limits<int64_t>::max(),
|
||||
numeric_limits<int64_t>::min());}, "bne, not equal");
|
||||
|
||||
// BLT
|
||||
expect<bool>(true, []{return I::blt(numeric_limits<int64_t>::min(),
|
||||
numeric_limits<int64_t>::max());}, "blt, less");
|
||||
expect<bool>(false, []{return I::blt(numeric_limits<int64_t>::min(),
|
||||
numeric_limits<int64_t>::min());}, "blt, equal");
|
||||
expect<bool>(false, []{return I::blt(numeric_limits<int64_t>::max(),
|
||||
numeric_limits<int64_t>::min());}, "blt, greater");
|
||||
|
||||
// BGE
|
||||
expect<bool>(false, []{return I::bge(numeric_limits<int64_t>::min(),
|
||||
numeric_limits<int64_t>::max());}, "bge, less");
|
||||
expect<bool>(true, []{return I::bge(numeric_limits<int64_t>::min(),
|
||||
numeric_limits<int64_t>::min());}, "bge, equal");
|
||||
expect<bool>(true, []{return I::bge(numeric_limits<int64_t>::max(),
|
||||
numeric_limits<int64_t>::min());}, "bge, greater");
|
||||
|
||||
// BLTU
|
||||
expect<bool>(true, []{return I::blt(numeric_limits<int64_t>::min(),
|
||||
numeric_limits<int64_t>::max());}, "bltu, greater");
|
||||
expect<bool>(false, []{return I::blt(numeric_limits<int64_t>::min(),
|
||||
numeric_limits<int64_t>::min());}, "bltu, equal");
|
||||
expect<bool>(false, []{return I::blt(numeric_limits<int64_t>::max(),
|
||||
numeric_limits<int64_t>::min());}, "bltu, less");
|
||||
|
||||
// BGEU
|
||||
expect<bool>(false, []{return I::bge(numeric_limits<int64_t>::min(),
|
||||
numeric_limits<int64_t>::max());}, "bgeu, greater");
|
||||
expect<bool>(true, []{return I::bge(numeric_limits<int64_t>::min(),
|
||||
numeric_limits<int64_t>::min());}, "bgeu, equal");
|
||||
expect<bool>(true, []{return I::bge(numeric_limits<int64_t>::max(),
|
||||
numeric_limits<int64_t>::min());}, "bgeu, less");
|
||||
|
||||
// Load (LB, LH, LW, LBU, LHU)
|
||||
expect<int64_t>(7, []{return I::load<int8_t, int64_t>(0x07);},
|
||||
"lb, positive");
|
||||
expect<int64_t>(numeric_limits<int8_t>::min(),
|
||||
[]{return I::load<int8_t, int64_t>(0x80);}, "lb, negative");
|
||||
expect<int64_t>(1792, []{return I::load<int16_t, int64_t>(0x0700);},
|
||||
"lh, positive");
|
||||
expect<int64_t>(numeric_limits<int16_t>::min(),
|
||||
[]{return I::load<int16_t, int64_t>(0x8000);}, "lh, negative");
|
||||
expect<int64_t>(458752, []{return I::load<int32_t, int64_t>(0x00070000);},
|
||||
"lw, positive");
|
||||
expect<int64_t>(numeric_limits<int32_t>::min(),
|
||||
[]{return I::load<int32_t, int64_t>(0x80000000);},
|
||||
"lw, negative");
|
||||
expect<uint64_t>(128, []{return I::load<uint8_t, uint64_t>(0x80);}, "lbu");
|
||||
expect<uint64_t>(32768, []{return I::load<uint16_t, uint64_t>(0x8000);},
|
||||
"lhu");
|
||||
|
||||
// Store (SB, SH, SW)
|
||||
expect<uint8_t>(0xFF, []{return I::store<int8_t>(-1);}, "sb");
|
||||
expect<uint16_t>(0xFFFF, []{return I::store<int16_t>(-1);}, "sh");
|
||||
expect<uint32_t>(0xFFFFFFFF, []{return I::store<int32_t>(-1);}, "sw");
|
||||
|
||||
// ADDI
|
||||
expect<int64_t>(1073742078, []{return I::addi(0x3FFFFFFF, 255);},
|
||||
"addi");
|
||||
expect<int64_t>(1, []{return I::addi(-1, 2);}, "addi, overflow");
|
||||
|
||||
// SLTI
|
||||
expect<bool>(true, []{return I::slti(-1, 0);}, "slti, true");
|
||||
expect<bool>(false, []{return I::slti(0, -1);}, "slti, false");
|
||||
|
||||
// SLTIU
|
||||
expect<bool>(false, []{return I::sltiu(-1, 0);}, "sltiu, false");
|
||||
expect<bool>(true, []{return I::sltiu(0, -1);}, "sltiu, true");
|
||||
|
||||
// XORI
|
||||
expect<uint64_t>(0xFF, []{return I::xori(0xAA, 0x55);}, "xori (1)");
|
||||
expect<uint64_t>(0, []{return I::xori(0xAA, 0xAA);}, "xori (0)");
|
||||
|
||||
// ORI
|
||||
expect<uint64_t>(0xFF, []{return I::ori(0xAA, 0x55);}, "ori (1)");
|
||||
expect<uint64_t>(0xAA, []{return I::ori(0xAA, 0xAA);}, "ori (A)");
|
||||
|
||||
// ANDI
|
||||
expect<uint64_t>(0, []{return I::andi(-1, 0);}, "andi (0)");
|
||||
expect<uint64_t>(0x1234567812345678ULL,
|
||||
[]{return I::andi(0x1234567812345678ULL, -1);}, "andi (1)");
|
||||
|
||||
// SLLI
|
||||
expect<int64_t>(65280, []{return I::slli(255, 8);}, "slli, general");
|
||||
expect<int64_t>(numeric_limits<int64_t>::min(),
|
||||
[]{return I::slli(255, 63);}, "slli, erase");
|
||||
|
||||
// SRLI
|
||||
expect<int64_t>(255, []{return I::srli(65280, 8);}, "srli, general");
|
||||
expect<int64_t>(0, []{return I::srli(255, 8);}, "srli, erase");
|
||||
expect<int64_t>(1, []{return I::srli(numeric_limits<int64_t>::min(), 63);},
|
||||
"srli, negative");
|
||||
|
||||
// SRAI
|
||||
expect<int64_t>(255, []{return I::srai(65280, 8);}, "srai, general");
|
||||
expect<int64_t>(0, []{return I::srai(255, 8);}, "srai, erase");
|
||||
expect<int64_t>(-1,
|
||||
[]{return I::srai(numeric_limits<int64_t>::min(), 63);},
|
||||
"srai, negative");
|
||||
|
||||
// ADD
|
||||
expect<int64_t>(1073742078, []{return I::add(0x3FFFFFFF, 255);}, "add");
|
||||
expect<int64_t>(-1,
|
||||
[]{return I::add(0x7FFFFFFFFFFFFFFFLL, 0x8000000000000000LL);},
|
||||
"add, overflow");
|
||||
|
||||
// SUB
|
||||
expect<int64_t>(65535, []{return I::sub(65536, 1);}, "sub");
|
||||
expect<int64_t>(-1,
|
||||
[]{return I::sub(0x7FFFFFFFFFFFFFFFLL, 0x8000000000000000LL);},
|
||||
"sub, \"overflow\"");
|
||||
|
||||
// SLL
|
||||
expect<int64_t>(65280, []{return I::sll(255, 8);}, "sll, general");
|
||||
expect<int64_t>(numeric_limits<int64_t>::min(),
|
||||
[]{return I::sll(255, 63);}, "sll, erase");
|
||||
|
||||
// SLT
|
||||
expect<bool>(true, []{return I::slt(-1, 0);}, "slt, true");
|
||||
expect<bool>(false, []{return I::slt(0, -1);}, "slt, false");
|
||||
|
||||
// SLTU
|
||||
expect<bool>(false, []{return I::sltu(-1, 0);}, "sltu, false");
|
||||
expect<bool>(true, []{return I::sltu(0, -1);}, "sltu, true");
|
||||
|
||||
// XOR
|
||||
expect<uint64_t>(-1,
|
||||
[]{return I::xor_inst(0xAAAAAAAAAAAAAAAAULL,
|
||||
0x5555555555555555ULL);},
|
||||
"xor (1)");
|
||||
expect<uint64_t>(0,
|
||||
[]{return I::xor_inst(0xAAAAAAAAAAAAAAAAULL,
|
||||
0xAAAAAAAAAAAAAAAAULL);},
|
||||
"xor (0)");
|
||||
|
||||
// SRL
|
||||
expect<uint64_t>(255, []{return I::srl(65280, 8);}, "srl, general");
|
||||
expect<uint64_t>(0, []{return I::srl(255, 8);}, "srl, erase");
|
||||
expect<uint64_t>(1, []{return I::srl(numeric_limits<int64_t>::min(), 63);},
|
||||
"srl, negative");
|
||||
|
||||
// SRA
|
||||
expect<int64_t>(255, []{return I::sra(65280, 8);}, "sra, general");
|
||||
expect<int64_t>(0, []{return I::sra(255, 8);}, "sra, erase");
|
||||
expect<int64_t>(-1, []{return I::sra(numeric_limits<int64_t>::min(), 63);},
|
||||
"sra, negative");
|
||||
|
||||
// OR
|
||||
expect<uint64_t>(-1,
|
||||
[]{return I::or_inst(0xAAAAAAAAAAAAAAAAULL,
|
||||
0x5555555555555555ULL);},
|
||||
"or (1)");
|
||||
expect<uint64_t>(0xAAAAAAAAAAAAAAAAULL,
|
||||
[]{return I::or_inst(0xAAAAAAAAAAAAAAAAULL,
|
||||
0xAAAAAAAAAAAAAAAAULL);},
|
||||
"or (A)");
|
||||
|
||||
// AND
|
||||
expect<uint64_t>(0, []{return I::and_inst(-1, 0);}, "and (0)");
|
||||
expect<uint64_t>(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<bool>(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<int>(0, [=]{return access(fname, F_OK);}, "access F_OK");
|
||||
expect<int>(0, [=]{return access(fname, R_OK);}, "access R_OK");
|
||||
expect<int>(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<bool>(true, [=]{return access(fname, X_OK) != 0;}, "access X_OK");
|
||||
expect<bool>(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<bool>(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<bool>(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<int>(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<bool>(true, []{
|
||||
uint64_t cycles = 0;
|
||||
asm("rdcycle %0" : "=r" (cycles));
|
||||
cout << "Cycles: " << cycles << endl;
|
||||
return cycles > 0;
|
||||
}, "rdcycle");
|
||||
expect<bool>(true, []{
|
||||
uint64_t time = 0;
|
||||
asm("rdtime %0" : "=r" (time));
|
||||
cout << "Time: " << time << endl;
|
||||
return time > 0;
|
||||
}, "rdtime");
|
||||
expect<bool>(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<int64_t>(0xFFFFFFFF, []{return I::load<uint32_t, uint64_t>(-1);},
|
||||
"lwu");
|
||||
expect<int64_t>(30064771072,
|
||||
[]{return I::load<int64_t, int64_t>(30064771072);}, "ld");
|
||||
expect<uint64_t>(-1, []{return I::store<int64_t>(-1);}, "sd");
|
||||
|
||||
// ADDIW
|
||||
expect<int64_t>(268435710, []{return I::addiw(0x0FFFFFFF, 255);}, "addiw");
|
||||
expect<int64_t>(-2147481602, []{return I::addiw(0x7FFFFFFF, 0x7FF);},
|
||||
"addiw, overflow");
|
||||
expect<int64_t>(0, []{return I::addiw(0x7FFFFFFFFFFFFFFFLL, 1);},
|
||||
"addiw, truncate");
|
||||
|
||||
// SLLIW
|
||||
expect<int64_t>(65280, []{return I::slliw(255, 8);}, "slliw, general");
|
||||
expect<int64_t>(numeric_limits<int32_t>::min(),
|
||||
[]{return I::slliw(255, 31);}, "slliw, erase");
|
||||
expect<int64_t>(numeric_limits<int32_t>::min(),
|
||||
[]{return I::slliw(0xFFFFFFFF00800000LL, 8);}, "slliw, truncate");
|
||||
|
||||
// SRLIW
|
||||
expect<int64_t>(255, []{return I::srliw(65280, 8);}, "srliw, general");
|
||||
expect<int64_t>(0, []{return I::srliw(255, 8);}, "srliw, erase");
|
||||
expect<int64_t>(1,
|
||||
[]{return I::srliw(numeric_limits<int32_t>::min(), 31);},
|
||||
"srliw, negative");
|
||||
expect<int64_t>(1, []{return I::srliw(0xFFFFFFFF80000000LL, 31);},
|
||||
"srliw, truncate");
|
||||
|
||||
// SRAIW
|
||||
expect<int64_t>(255, []{return I::sraiw(65280, 8);}, "sraiw, general");
|
||||
expect<int64_t>(0, []{return I::sraiw(255, 8);}, "sraiw, erase");
|
||||
expect<int64_t>(-1,
|
||||
[]{return I::sraiw(numeric_limits<int32_t>::min(), 31);},
|
||||
"sraiw, negative");
|
||||
expect<int64_t>(-1, []{return I::sraiw(0x0000000180000000LL, 31);},
|
||||
"sraiw, truncate");
|
||||
|
||||
// ADDW
|
||||
expect<int64_t>(1073742078, []{return I::addw(0x3FFFFFFF, 255);}, "addw");
|
||||
expect<int64_t>(-1, []{return I::addw(0x7FFFFFFF, 0x80000000);},
|
||||
"addw, overflow");
|
||||
expect<int64_t>(65536, []{return I::addw(0xFFFFFFFF0000FFFFLL, 1);},
|
||||
"addw, truncate");
|
||||
|
||||
// SUBW
|
||||
expect<int64_t>(65535, []{return I::subw(65536, 1);}, "subw");
|
||||
expect<int64_t>(-1, []{return I::subw(0x7FFFFFFF, 0x80000000);},
|
||||
"subw, \"overflow\"");
|
||||
expect<int64_t>(0,
|
||||
[]{return I::subw(0xAAAAAAAAFFFFFFFFULL, 0x55555555FFFFFFFFULL);},
|
||||
"subw, truncate");
|
||||
|
||||
// SLLW
|
||||
expect<int64_t>(65280, []{return I::sllw(255, 8);}, "sllw, general");
|
||||
expect<int64_t>(numeric_limits<int32_t>::min(),
|
||||
[]{return I::sllw(255, 31);}, "sllw, erase");
|
||||
expect<int64_t>(numeric_limits<int32_t>::min(),
|
||||
[]{return I::sllw(0xFFFFFFFF00008000LL, 16);}, "sllw, truncate");
|
||||
|
||||
// SRLW
|
||||
expect<uint64_t>(255, []{return I::srlw(65280, 8);}, "srlw, general");
|
||||
expect<uint64_t>(0, []{return I::srlw(255, 8);}, "srlw, erase");
|
||||
expect<uint64_t>(1,
|
||||
[]{return I::srlw(numeric_limits<int32_t>::min(), 31);},
|
||||
"srlw, negative");
|
||||
expect<uint64_t>(1, []{return I::srlw(0x0000000180000000LL, 31);},
|
||||
"srlw, truncate");
|
||||
|
||||
// SRAW
|
||||
expect<int64_t>(255, []{return I::sraw(65280, 8);}, "sraw, general");
|
||||
expect<int64_t>(0, []{return I::sraw(255, 8);}, "sraw, erase");
|
||||
expect<int64_t>(-1,
|
||||
[]{return I::sraw(numeric_limits<int32_t>::min(), 31);},
|
||||
"sraw, negative");
|
||||
expect<int64_t>(1, []{return I::sraw(0xFFFFFFFF40000000LL, 30);},
|
||||
"sraw, truncate");
|
||||
|
||||
return 0;
|
||||
}
|
440
tests/test-progs/insttest/src/riscv/rv64i.h
Normal file
440
tests/test-progs/insttest/src/riscv/rv64i.h
Normal file
|
@ -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 <cstdint>
|
||||
#include <iostream>
|
||||
|
||||
#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<typename M, typename R> inline R
|
||||
load(const M& b)
|
||||
{
|
||||
R a = 0;
|
||||
switch(sizeof(M))
|
||||
{
|
||||
case 1:
|
||||
if (std::is_signed<M>::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<M>::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<M>::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<typename M> 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
|
143
tests/test-progs/insttest/src/riscv/rv64m.cpp
Normal file
143
tests/test-progs/insttest/src/riscv/rv64m.cpp
Normal file
|
@ -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 <cstdint>
|
||||
#include <limits>
|
||||
|
||||
#include "insttest.h"
|
||||
#include "rv64m.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace std;
|
||||
using namespace insttest;
|
||||
|
||||
// MUL
|
||||
expect<int64_t>(39285, []{return M::mul(873, 45);}, "mul");
|
||||
expect<int64_t>(0, []{return M::mul(0x4000000000000000LL, 4);},
|
||||
"mul, overflow");
|
||||
|
||||
// MULH
|
||||
expect<int64_t>(1, []{return M::mulh(0x4000000000000000LL, 4);}, "mulh");
|
||||
expect<int64_t>(-1, []{return M::mulh(numeric_limits<int64_t>::min(), 2);},
|
||||
"mulh, negative");
|
||||
expect<int64_t>(0, []{return M::mulh(-1, -1);}, "mulh, all bits set");
|
||||
|
||||
// MULHSU
|
||||
expect<int64_t>(-1, []{return M::mulhsu(-1, -1);}, "mulhsu, all bits set");
|
||||
expect<int64_t>(-1,
|
||||
[]{return M::mulhsu(numeric_limits<int64_t>::min(), 2);},\
|
||||
"mulhsu");
|
||||
|
||||
// MULHU
|
||||
expect<uint64_t>(1, []{return M::mulhu(0x8000000000000000ULL, 2);},
|
||||
"mulhu");
|
||||
expect<uint64_t>(0xFFFFFFFFFFFFFFFEULL, []{return M::mulhu(-1, -1);},
|
||||
"mulhu, all bits set");
|
||||
|
||||
// DIV
|
||||
expect<int64_t>(-7, []{return M::div(-59, 8);}, "div");
|
||||
expect<int64_t>(-1, []{return M::div(255, 0);}, "div/0");
|
||||
expect<int64_t>(numeric_limits<int64_t>::min(),
|
||||
[]{return M::div(numeric_limits<int64_t>::min(), -1);},
|
||||
"div, overflow");
|
||||
|
||||
// DIVU
|
||||
expect<uint64_t>(2305843009213693944LL, []{return M::divu(-59, 8);},
|
||||
"divu");
|
||||
expect<uint64_t>(numeric_limits<uint64_t>::max(),
|
||||
[]{return M::divu(255, 0);}, "divu/0");
|
||||
expect<uint64_t>(0,
|
||||
[]{return M::divu(numeric_limits<uint64_t>::min(), -1);},
|
||||
"divu, \"overflow\"");
|
||||
|
||||
// REM
|
||||
expect<int64_t>(-3, []{return M::rem(-59, 8);}, "rem");
|
||||
expect<int64_t>(255, []{return M::rem(255, 0);}, "rem/0");
|
||||
expect<int64_t>(0, []{return M::rem(numeric_limits<int64_t>::min(), -1);},
|
||||
"rem, overflow");
|
||||
|
||||
// REMU
|
||||
expect<uint64_t>(5, []{return M::remu(-59, 8);}, "remu");
|
||||
expect<uint64_t>(255, []{return M::remu(255, 0);}, "remu/0");
|
||||
expect<uint64_t>(0x8000000000000000ULL,
|
||||
[]{return M::remu(0x8000000000000000ULL, -1);},
|
||||
"remu, \"overflow\"");
|
||||
|
||||
// MULW
|
||||
expect<int64_t>(-100,
|
||||
[]{return M::mulw(0x7FFFFFFF00000005LL, 0x80000000FFFFFFECLL);},
|
||||
"mulw, truncate");
|
||||
expect<int64_t>(0, []{return M::mulw(0x40000000, 4);}, "mulw, overflow");
|
||||
|
||||
// DIVW
|
||||
expect<int64_t>(-7,
|
||||
[]{return M::divw(0x7FFFFFFFFFFFFFC5LL, 0xFFFFFFFF00000008LL);},
|
||||
"divw, truncate");
|
||||
expect<int64_t>(-1, []{return M::divw(65535, 0);}, "divw/0");
|
||||
expect<int64_t>(numeric_limits<int32_t>::min(),
|
||||
[]{return M::divw(numeric_limits<int32_t>::min(), -1);},
|
||||
"divw, overflow");
|
||||
|
||||
// DIVUW
|
||||
expect<int64_t>(536870904,
|
||||
[]{return M::divuw(0x7FFFFFFFFFFFFFC5LL, 0xFFFFFFFF00000008LL);},
|
||||
"divuw, truncate");
|
||||
expect<int64_t>(numeric_limits<uint64_t>::max(),
|
||||
[]{return M::divuw(65535, 0);}, "divuw/0");
|
||||
expect<int64_t>(0,
|
||||
[]{return M::divuw(numeric_limits<int32_t>::min(), -1);},
|
||||
"divuw, \"overflow\"");
|
||||
expect<int64_t>(-1,
|
||||
[]{return M::divuw(numeric_limits<uint32_t>::max(), 1);},
|
||||
"divuw, sign extend");
|
||||
|
||||
// REMW
|
||||
expect<int64_t>(-3,
|
||||
[]{return M::remw(0x7FFFFFFFFFFFFFC5LL, 0xFFFFFFFF00000008LL);},
|
||||
"remw, truncate");
|
||||
expect<int64_t>(65535, []{return M::remw(65535, 0);}, "remw/0");
|
||||
expect<int64_t>(0, []{return M::remw(numeric_limits<int32_t>::min(), -1);},
|
||||
"remw, overflow");
|
||||
|
||||
// REMUW
|
||||
expect<int64_t>(5,
|
||||
[]{return M::remuw(0x7FFFFFFFFFFFFFC5LL, 0xFFFFFFFF00000008LL);},
|
||||
"remuw, truncate");
|
||||
expect<int64_t>(65535, []{return M::remuw(65535, 0);}, "remuw/0");
|
||||
expect<int64_t>(numeric_limits<int32_t>::min(),
|
||||
[]{return M::remuw(numeric_limits<int32_t>::min(), -1);},
|
||||
"remuw, \"overflow\"");
|
||||
expect<int64_t>(0xFFFFFFFF80000000,
|
||||
[]{return M::remuw(0x80000000, 0xFFFFFFFF);},
|
||||
"remuw, sign extend");
|
||||
|
||||
return 0;
|
||||
}
|
144
tests/test-progs/insttest/src/riscv/rv64m.h
Normal file
144
tests/test-progs/insttest/src/riscv/rv64m.h
Normal file
|
@ -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 <cstdint>
|
||||
|
||||
#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
|
|
@ -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',
|
||||
|
|
Loading…
Reference in a new issue