/* * 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"); }