/* * 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