33683bd087
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>
441 lines
8.4 KiB
C++
441 lines
8.4 KiB
C++
/*
|
|
* 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
|