rv64c.h revision 12121
1/* 2 * Copyright (c) 2017 The University of Virginia 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Alec Roelke 29 */ 30 31#pragma once 32 33#include <cstdint> 34#include <type_traits> 35 36#include "insttest.h" 37 38#define CIOP(op, r, imm) asm volatile(op " %0,%1" : "+r" (r) : "i" (imm)); 39#define CROP(op, rd, rs) asm volatile(op " %0,%1" : "+r" (rd) : "r" (rs)) 40 41namespace C 42{ 43 44inline int64_t 45c_li(const int8_t imm) 46{ 47 int64_t rd = 0; 48 CIOP("c.li", rd, imm); 49 return rd; 50} 51 52inline int64_t 53c_lui(const int8_t imm) 54{ 55 int64_t rd = 0; 56 CIOP("c.lui", rd, imm); 57 return rd; 58} 59 60inline int64_t 61c_addi(int64_t r, const int8_t imm) 62{ 63 CIOP("c.addi", r, imm); 64 return r; 65} 66 67inline int64_t 68c_addiw(int64_t r, const int8_t imm) 69{ 70 CIOP("c.addiw", r, imm); 71 return r; 72} 73 74inline uint64_t 75c_addi4spn(const int16_t imm) 76{ 77 uint64_t rd = 0; 78 asm volatile("c.addi4spn %0,sp,%1" : "=r" (rd) : "i" (imm)); 79 return rd; 80} 81 82inline uint64_t 83c_slli(uint64_t r, uint8_t shamt) 84{ 85 CIOP("c.slli", r, shamt); 86 return r; 87} 88 89inline uint64_t 90c_srli(uint64_t r, uint8_t shamt) 91{ 92 CIOP("c.srli", r, shamt); 93 return r; 94} 95 96inline int64_t 97c_srai(int64_t r, uint8_t shamt) 98{ 99 CIOP("c.srai", r, shamt); 100 return r; 101} 102 103inline uint64_t 104c_andi(uint64_t r, uint8_t imm) 105{ 106 CIOP("c.andi", r, imm); 107 return r; 108} 109 110inline int64_t 111c_mv(int64_t rs) 112{ 113 int64_t rd = 0; 114 CROP("c.mv", rd, rs); 115 return rd; 116} 117 118inline int64_t 119c_add(int64_t rd, int64_t rs) 120{ 121 CROP("c.add", rd, rs); 122 return rd; 123} 124 125inline uint64_t 126c_and(int64_t rd, int64_t rs) 127{ 128 CROP("c.and", rd, rs); 129 return rd; 130} 131 132inline uint64_t 133c_or(int64_t rd, int64_t rs) 134{ 135 CROP("c.or", rd, rs); 136 return rd; 137} 138 139inline uint64_t 140c_xor(int64_t rd, int64_t rs) 141{ 142 CROP("c.xor", rd, rs); 143 return rd; 144} 145 146inline int64_t 147c_sub(int64_t rd, int64_t rs) 148{ 149 CROP("c.sub", rd, rs); 150 return rd; 151} 152 153inline int64_t 154c_addw(int64_t rd, int64_t rs) 155{ 156 CROP("c.addw", rd, rs); 157 return rd; 158} 159 160inline int64_t 161c_subw(int64_t rd, int64_t rs) 162{ 163 CROP("c.subw", rd, rs); 164 return rd; 165} 166 167template<typename M, typename R> inline R 168c_load(M m) 169{ 170 R r = 0; 171 switch (sizeof(M)) 172 { 173 case 4: 174 asm volatile("c.lw %0,0(%1)" : "=r" (r) : "r" (&m) : "memory"); 175 break; 176 case 8: 177 if (std::is_floating_point<M>::value) 178 asm volatile("c.fld %0,0(%1)" : "=f" (r) : "r" (&m) : "memory"); 179 else 180 asm volatile("c.ld %0,0(%1)" : "=r" (r) : "r" (&m) : "memory"); 181 break; 182 } 183 return r; 184} 185 186template<typename M> inline M 187c_store(const M& rs) 188{ 189 M mem = 0; 190 switch (sizeof(M)) 191 { 192 case 4: 193 asm volatile("c.sw %0,0(%1)" : : "r" (rs), "r" (&mem) : "memory"); 194 break; 195 case 8: 196 if (std::is_floating_point<M>::value) 197 asm volatile("c.fsd %0,0(%1)" : : "f" (rs), "r" (&mem) : "memory"); 198 else 199 asm volatile("c.sd %0,0(%1)" : : "r" (rs), "r" (&mem) : "memory"); 200 break; 201 } 202 return mem; 203} 204 205inline bool 206c_j() 207{ 208 asm volatile goto("c.j %l[jallabel]" : : : : jallabel); 209 return false; 210 jallabel: 211 return true; 212} 213 214inline bool 215c_jr() 216{ 217 uint64_t a = 0; 218 asm volatile("auipc %0,0;" 219 "c.addi %0,12;" 220 "c.jr %0;" 221 "addi %0,zero,0;" 222 "addi %0,%0,0;" 223 : "+r" (a)); 224 return a > 0; 225} 226 227inline bool 228c_jalr() 229{ 230 int64_t a = 0; 231 asm volatile("auipc %0,0;" 232 "c.addi %0,12;" 233 "c.jalr %0;" 234 "addi %0,zero,0;" 235 "sub %0,ra,%0;" 236 : "+r" (a) 237 : 238 : "ra"); 239 return a == -4; 240} 241 242inline bool 243c_beqz(int64_t a) 244{ 245 asm volatile goto("c.beqz %0,%l[beqlabel]" 246 : 247 : "r" (a) 248 : 249 : beqlabel); 250 return false; 251 beqlabel: 252 return true; 253} 254 255inline bool 256c_bnez(int64_t a) 257{ 258 asm volatile goto("c.bnez %0,%l[beqlabel]" 259 : 260 : "r" (a) 261 : 262 : beqlabel); 263 return false; 264 beqlabel: 265 return true; 266} 267 268} // namespace C