From eef537fd993f7a879a44f5786bc528e03b0e61bc Mon Sep 17 00:00:00 2001 From: Alec Roelke Date: Sun, 9 Jul 2017 16:24:27 -0400 Subject: [PATCH] arch-riscv,tests: Add insttests for RV64C This patch adds instruction tests for the RV64C extension implementation. It also updates existing executables for the latest riscv-tools now that they are compatible. [Update for changes to parents.] Change-Id: Id4cfd966a8cae39b0d728b02849622fd00ee7e0e Reviewed-on: https://gem5-review.googlesource.com/3862 Maintainer: Jason Lowe-Power Reviewed-by: Jason Lowe-Power --- tests/test-progs/insttest/src/riscv/Makefile | 5 +- .../test-progs/insttest/src/riscv/insttest.h | 1 - tests/test-progs/insttest/src/riscv/rv64c.cpp | 256 +++++++++++++++++ tests/test-progs/insttest/src/riscv/rv64c.h | 268 ++++++++++++++++++ 4 files changed, 527 insertions(+), 3 deletions(-) create mode 100644 tests/test-progs/insttest/src/riscv/rv64c.cpp create mode 100644 tests/test-progs/insttest/src/riscv/rv64c.h diff --git a/tests/test-progs/insttest/src/riscv/Makefile b/tests/test-progs/insttest/src/riscv/Makefile index c493b40ce..921e37259 100644 --- a/tests/test-progs/insttest/src/riscv/Makefile +++ b/tests/test-progs/insttest/src/riscv/Makefile @@ -27,9 +27,9 @@ # Authors: Alec Roelke CXX=riscv64-unknown-linux-gnu-g++ -CFLAGS=--std=c++11 -O3 -static +CFLAGS=-std=gnu++11 -O3 -static -march=rv64gc -TARGETS=rv64i rv64m rv64a rv64f rv64d +TARGETS=rv64i rv64m rv64a rv64f rv64d rv64c PREFIX=../../bin/riscv/linux BIN=insttest @@ -44,6 +44,7 @@ rv64m: rv64m.cpp rv64a: rv64a.cpp rv64f: rv64f.cpp rv64d: rv64d.cpp +rv64c: rv64c.cpp clean: -rm $(PREFIX)-*/$(BIN) diff --git a/tests/test-progs/insttest/src/riscv/insttest.h b/tests/test-progs/insttest/src/riscv/insttest.h index 59b69869c..be1b86e23 100644 --- a/tests/test-progs/insttest/src/riscv/insttest.h +++ b/tests/test-progs/insttest/src/riscv/insttest.h @@ -72,7 +72,6 @@ expect(const T& expected, std::function func, } else { cout << "\033[1;31mFAIL\033[0m (expected " << expected << "; found " << result << ")" << endl; - exit(1); } } diff --git a/tests/test-progs/insttest/src/riscv/rv64c.cpp b/tests/test-progs/insttest/src/riscv/rv64c.cpp new file mode 100644 index 000000000..869784d72 --- /dev/null +++ b/tests/test-progs/insttest/src/riscv/rv64c.cpp @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2017 The University of Virginia + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Alec Roelke + */ + +#include + +#include "insttest.h" +#include "rv64c.h" +#include "rv64d.h" + +int main() +{ + using namespace insttest; + using namespace std; + + // C.LWSP + expect(true, []{ + uint64_t lw = 0, lwsp = -1; + int64_t i = 16; + asm volatile("lw %0,%2(sp);" + "c.lwsp %1,%2(sp);" + : "=r" (lw), "=r" (lwsp) + : "i" (i)); + return lw == lwsp; + }, "c.lwsp"); + + // C.LDSP + expect(true, []{ + uint64_t ld = 0, ldsp = -1; + int64_t i = 8; + asm volatile("ld %0,%2(sp);" + "c.ldsp %1,%2(sp);" + : "=r" (ld), "=r" (ldsp) + : "i" (i)); + return ld == ldsp; + }, "c.ldsp"); + + // C.FLDSP + expect(true, []{ + double fld = 0.0, fldsp = -1.0; + int64_t i = 32; + asm volatile("fld %0,%2(sp);" + "c.fldsp %1,%2(sp);" + : "=f" (fld), "=f" (fldsp) + : "i" (i)); + return D::bits(fld) == D::bits(fldsp); + }, "c.fldsp"); + + // C.SWSP + expect(true, []{ + int64_t value = -1, result = 0; + asm volatile("addi sp,sp,-8;" + "c.swsp %1,8(sp);" + "lw %0,8(sp);" + "addi sp,sp,8;" + : "=r" (result) + : "r" (value) + : "memory"); + return value == result; + }, "c.swsp"); + + // C.SDSP + expect(true, []{ + int64_t value = -1, result = 0; + asm volatile("addi sp,sp,-8;" + "c.sdsp %1,8(sp);" + "ld %0,8(sp);" + "addi sp,sp,8;" + : "=r" (result) + : "r" (value) + : "memory"); + return value == result; + }, "c.sdsp"); + + // C.FSDSP + expect(true, []{ + double value = 0.1, result = numeric_limits::signaling_NaN(); + asm volatile("addi sp,sp,-8;" + "c.fsdsp %1,8(sp);" + "fld %0,8(sp);" + "addi sp,sp,8;" + : "=f" (result) + : "f" (value) + : "memory"); + return value == result; + }, "c.fsdsp"); + + // C.LW, C.LD, C.FLD + expect(458752, + []{return C::c_load(0x00070000);}, + "c.lw, positive"); + expect(numeric_limits::min(), + []{return C::c_load(0x80000000);}, + "c.lw, negative"); + expect(30064771072, + []{return C::c_load(30064771072);}, "c.ld"); + expect(3.1415926, []{return C::c_load(3.1415926);}, + "c.fld"); + + // C.SW, C.SD, C.FSD + expect(0xFFFFFFFF, []{return C::c_store(-1);}, "c.sw"); + expect(-1, []{return C::c_store(-1);}, "c.sd"); + expect(1.61803398875, + []{return C::c_store(1.61803398875);}, "c.fsd"); + + // C.J, C.JR, C.JALR + expect(true, []{return C::c_j();}, "c.j"); + expect(true, []{return C::c_jr();}, "c.jr"); + expect(true, []{return C::c_jalr();}, "c.jalr"); + + // C.BEQZ + expect(true, []{return C::c_beqz(0);}, "c.beqz, zero"); + expect(false, []{return C::c_beqz(7);}, "c.beqz, not zero"); + + // C.BNEZ + expect(true, []{return C::c_bnez(15);}, "c.bnez, not zero"); + expect(false, []{return C::c_bnez(0);}, "c.bnez, zero"); + + // C.LI + expect(1, []{return C::c_li(1);}, "c.li"); + expect(-1, []{return C::c_li(-1);}, "c.li, sign extend"); + + // C.LUI + expect(4096, []{return C::c_lui(1);}, "c.lui"); + // Note that sign extension can't be tested here because apparently the + // compiler doesn't allow the 6th (sign) bit of the immediate to be 1 + + // C.ADDI + expect(15, []{return C::c_addi(7, 8);}, "c.addi"); + + // C.ADDIW + expect(15, []{return C::c_addiw(8, 7);}, "c.addiw"); + expect(1, []{return C::c_addiw(0xFFFFFFFF, 2);}, + "c.addiw, overflow"); + expect(1, []{return C::c_addiw(0x100000001, 0);}, + "c.addiw, truncate"); + + // C.ADDI16SP + expect(true, []{ + uint64_t sp = 0, rd = 0; + const int16_t i = 4; + asm volatile("mv %0,sp;" + "c.addi16sp sp,%2;" + "mv %1,sp;" + "mv sp,%0;" + : "+r" (sp), "=r" (rd) + : "i" (i*16)); + return rd == sp + i*16; + }, "c.addi16sp"); + + // C.ADDI4SPN + expect(true, []{ + uint64_t sp = 0, rd = 0; + const int16_t i = 3; + asm volatile("mv %0,sp;" + "c.addi4spn %1,sp,%2;" + : "=r" (sp), "=r" (rd) + : "i" (i*4)); + return rd == sp + i*4; + }, "c.addi4spn"); + + // C.SLLI + expect(16, []{return C::c_slli(1, 4);}, "c.slli"); + expect(0, []{return C::c_slli(8, 61);}, "c.slli, overflow"); + + // C.SRLI + expect(4, []{return C::c_srli(128, 5);}, "c.srli"); + expect(0, []{return C::c_srli(128, 8);}, "c.srli, overflow"); + expect(1, []{return C::c_srli(-1, 63);}, "c.srli, -1"); + + // C.SRAI + expect(4, []{return C::c_srai(128, 5);}, "c.srai"); + expect(0, []{return C::c_srai(128, 8);}, "c.srai, overflow"); + expect(-1, []{return C::c_srai(-2, 63);}, "c.srai, -1"); + + // C.ANDI + expect(0, []{return C::c_andi(-1, 0);}, "c.andi (0)"); + expect(0x1234567812345678ULL, + []{return C::c_andi(0x1234567812345678ULL, -1);}, "c.andi (1)"); + + // C.MV + expect(1024, []{return C::c_mv(1024);}, "c.mv"); + + // C.ADD + expect(15, []{return C::c_add(10, 5);}, "c.add"); + + // C.AND + expect(0, []{return C::c_and(-1, 0);}, "c.and (0)"); + expect(0x1234567812345678ULL, + []{return C::c_and(0x1234567812345678ULL, -1);}, "c.and (-1)"); + + // C.OR + expect(-1, + []{return C::c_or(0xAAAAAAAAAAAAAAAAULL, + 0x5555555555555555ULL);}, + "c.or (1)"); + expect(0xAAAAAAAAAAAAAAAAULL, + []{return C::c_or(0xAAAAAAAAAAAAAAAAULL, + 0xAAAAAAAAAAAAAAAAULL);}, + "c.or (A)"); + + // C.XOR + expect(-1, + []{return C::c_xor(0xAAAAAAAAAAAAAAAAULL, + 0x5555555555555555ULL);}, + "c.xor (1)"); + expect(0, + []{return C::c_xor(0xAAAAAAAAAAAAAAAAULL, + 0xAAAAAAAAAAAAAAAAULL);}, + "c.xor (0)"); + + // C.SUB + expect(65535, []{return C::c_sub(65536, 1);}, "c.sub"); + + // C.ADDW + expect(1073742078, []{return C::c_addw(0x3FFFFFFF, 255);}, + "c.addw"); + expect(-1, []{return C::c_addw(0x7FFFFFFF, 0x80000000);}, + "c.addw, overflow"); + expect(65536, []{return C::c_addw(0xFFFFFFFF0000FFFFLL, 1);}, + "c.addw, truncate"); + + // C.SUBW + expect(65535, []{return C::c_subw(65536, 1);}, "c.subw"); + expect(-1, []{return C::c_subw(0x7FFFFFFF, 0x80000000);}, + "c.subw, \"overflow\""); + expect(0, + []{return C::c_subw(0xAAAAAAAAFFFFFFFFULL,0x55555555FFFFFFFFULL);}, + "c.subw, truncate"); +} \ No newline at end of file diff --git a/tests/test-progs/insttest/src/riscv/rv64c.h b/tests/test-progs/insttest/src/riscv/rv64c.h new file mode 100644 index 000000000..26d900910 --- /dev/null +++ b/tests/test-progs/insttest/src/riscv/rv64c.h @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2017 The University of Virginia + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Alec Roelke + */ + +#pragma once + +#include +#include + +#include "insttest.h" + +#define CIOP(op, r, imm) asm volatile(op " %0,%1" : "+r" (r) : "i" (imm)); +#define CROP(op, rd, rs) asm volatile(op " %0,%1" : "+r" (rd) : "r" (rs)) + +namespace C +{ + +inline int64_t +c_li(const int8_t imm) +{ + int64_t rd = 0; + CIOP("c.li", rd, imm); + return rd; +} + +inline int64_t +c_lui(const int8_t imm) +{ + int64_t rd = 0; + CIOP("c.lui", rd, imm); + return rd; +} + +inline int64_t +c_addi(int64_t r, const int8_t imm) +{ + CIOP("c.addi", r, imm); + return r; +} + +inline int64_t +c_addiw(int64_t r, const int8_t imm) +{ + CIOP("c.addiw", r, imm); + return r; +} + +inline uint64_t +c_addi4spn(const int16_t imm) +{ + uint64_t rd = 0; + asm volatile("c.addi4spn %0,sp,%1" : "=r" (rd) : "i" (imm)); + return rd; +} + +inline uint64_t +c_slli(uint64_t r, uint8_t shamt) +{ + CIOP("c.slli", r, shamt); + return r; +} + +inline uint64_t +c_srli(uint64_t r, uint8_t shamt) +{ + CIOP("c.srli", r, shamt); + return r; +} + +inline int64_t +c_srai(int64_t r, uint8_t shamt) +{ + CIOP("c.srai", r, shamt); + return r; +} + +inline uint64_t +c_andi(uint64_t r, uint8_t imm) +{ + CIOP("c.andi", r, imm); + return r; +} + +inline int64_t +c_mv(int64_t rs) +{ + int64_t rd = 0; + CROP("c.mv", rd, rs); + return rd; +} + +inline int64_t +c_add(int64_t rd, int64_t rs) +{ + CROP("c.add", rd, rs); + return rd; +} + +inline uint64_t +c_and(int64_t rd, int64_t rs) +{ + CROP("c.and", rd, rs); + return rd; +} + +inline uint64_t +c_or(int64_t rd, int64_t rs) +{ + CROP("c.or", rd, rs); + return rd; +} + +inline uint64_t +c_xor(int64_t rd, int64_t rs) +{ + CROP("c.xor", rd, rs); + return rd; +} + +inline int64_t +c_sub(int64_t rd, int64_t rs) +{ + CROP("c.sub", rd, rs); + return rd; +} + +inline int64_t +c_addw(int64_t rd, int64_t rs) +{ + CROP("c.addw", rd, rs); + return rd; +} + +inline int64_t +c_subw(int64_t rd, int64_t rs) +{ + CROP("c.subw", rd, rs); + return rd; +} + +template inline R +c_load(M m) +{ + R r = 0; + switch (sizeof(M)) + { + case 4: + asm volatile("c.lw %0,0(%1)" : "=r" (r) : "r" (&m) : "memory"); + break; + case 8: + if (std::is_floating_point::value) + asm volatile("c.fld %0,0(%1)" : "=f" (r) : "r" (&m) : "memory"); + else + asm volatile("c.ld %0,0(%1)" : "=r" (r) : "r" (&m) : "memory"); + break; + } + return r; +} + +template inline M +c_store(const M& rs) +{ + M mem = 0; + switch (sizeof(M)) + { + case 4: + asm volatile("c.sw %0,0(%1)" : : "r" (rs), "r" (&mem) : "memory"); + break; + case 8: + if (std::is_floating_point::value) + asm volatile("c.fsd %0,0(%1)" : : "f" (rs), "r" (&mem) : "memory"); + else + asm volatile("c.sd %0,0(%1)" : : "r" (rs), "r" (&mem) : "memory"); + break; + } + return mem; +} + +inline bool +c_j() +{ + asm volatile goto("c.j %l[jallabel]" : : : : jallabel); + return false; + jallabel: + return true; +} + +inline bool +c_jr() +{ + uint64_t a = 0; + asm volatile("auipc %0,0;" + "c.addi %0,12;" + "c.jr %0;" + "addi %0,zero,0;" + "addi %0,%0,0;" + : "+r" (a)); + return a > 0; +} + +inline bool +c_jalr() +{ + int64_t a = 0; + asm volatile("auipc %0,0;" + "c.addi %0,12;" + "c.jalr %0;" + "addi %0,zero,0;" + "sub %0,ra,%0;" + : "+r" (a) + : + : "ra"); + return a == -4; +} + +inline bool +c_beqz(int64_t a) +{ + asm volatile goto("c.beqz %0,%l[beqlabel]" + : + : "r" (a) + : + : beqlabel); + return false; + beqlabel: + return true; +} + +inline bool +c_bnez(int64_t a) +{ + asm volatile goto("c.bnez %0,%l[beqlabel]" + : + : "r" (a) + : + : beqlabel); + return false; + beqlabel: + return true; +} + +} // namespace C \ No newline at end of file -- 2.30.2