1/* 2 * Copyright (c) 2016 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 <iostream> 35 36#include "insttest.h" 37 38namespace I 39{ 40 41inline uint64_t 42lui(const uint32_t imm) 43{ 44 int64_t rd = -1; 45 asm volatile("lui %0,%1" : "=r" (rd) : "i" (imm)); 46 return rd; 47} 48 49inline bool 50auipc(const uint64_t imm) 51{ 52 int64_t rd = -1; 53 asm volatile("auipc %0,%1" : "=r" (rd) : "i" (imm)); 54 std::cout << "auipc: 0x" << std::hex << std::uppercase << rd << 55 std::nouppercase << std::dec << std::endl; 56 return rd >= imm; 57} 58 59inline bool 60jal() 61{ 62 asm volatile goto("jal zero,%l[jallabel]" : : : : jallabel); 63 return false; 64 jallabel: 65 return true; 66} 67 68inline bool 69jalr() 70{ 71 int a = 0; 72 asm volatile("auipc %0,0;" 73 "jalr t0,%0,12;" 74 "addi %0,zero,0;" 75 "sub %0,t0,%0;" 76 : "+r" (a) 77 : 78 : "t0"); 79 return a == 8; 80} 81 82inline bool 83beq(int64_t a, int64_t b) 84{ 85 asm volatile goto("beq %0,%1,%l[beqlabel]" 86 : 87 : "r" (a), "r" (b) 88 : 89 : beqlabel); 90 return false; 91 beqlabel: 92 return true; 93} 94 95inline bool 96bne(int64_t a, int64_t b) 97{ 98 asm volatile goto("bne %0,%1,%l[bnelabel]" 99 : 100 : "r" (a), "r" (b) 101 : 102 : bnelabel); 103 return false; 104 bnelabel: 105 return true; 106} 107 108inline bool 109blt(int64_t a, int64_t b) 110{ 111 asm volatile goto("blt %0,%1,%l[bltlabel]" 112 : 113 : "r" (a), "r" (b) 114 : 115 : bltlabel); 116 return false; 117 bltlabel: 118 return true; 119} 120 121inline bool 122bge(int64_t a, int64_t b) 123{ 124 asm volatile goto("bge %0,%1,%l[bgelabel]" 125 : 126 : "r" (a), "r" (b) 127 : 128 : bgelabel); 129 return false; 130 bgelabel: 131 return true; 132} 133 134inline bool 135bltu(uint64_t a, uint64_t b) 136{ 137 asm volatile goto("bltu %0,%1,%l[bltulabel]" 138 : 139 : "r" (a), "r" (b) 140 : 141 : bltulabel); 142 return false; 143 bltulabel: 144 return true; 145} 146 147inline bool 148bgeu(uint64_t a, uint64_t b) 149{ 150 asm volatile goto("bgeu %0,%1,%l[bgeulabel]" 151 : 152 : "r" (a), "r" (b) 153 : 154 : bgeulabel); 155 return false; 156 bgeulabel: 157 return true; 158} 159 160template<typename M, typename R> inline R 161load(const M& b) 162{ 163 R a = 0; 164 switch(sizeof(M)) 165 { 166 case 1: 167 if (std::is_signed<M>::value) { 168 asm volatile("lb %0,%1" : "=r" (a) : "m" (b)); 169 } else { 170 asm volatile("lbu %0,%1" : "=r" (a) : "m" (b)); 171 } 172 break; 173 case 2: 174 if (std::is_signed<M>::value) { 175 asm volatile("lh %0,%1" : "=r" (a) : "m" (b)); 176 } else { 177 asm volatile("lhu %0,%1" : "=r" (a) : "m" (b)); 178 } 179 break; 180 case 4: 181 if (std::is_signed<M>::value) { 182 asm volatile("lw %0,%1" : "=r" (a) : "m" (b)); 183 } else { 184 asm volatile("lwu %0,%1" : "=r" (a) : "m" (b)); 185 } 186 break; 187 case 8: 188 asm volatile("ld %0,%1" : "=r" (a) : "m" (b)); 189 break; 190 } 191 return a; 192} 193 194template<typename M> inline M 195store(const M& rs2) 196{ 197 M mem = 0; 198 switch (sizeof(M)) 199 { 200 case 1: 201 asm volatile("sb %1,%0" : "=m" (mem) : "r" (rs2)); 202 break; 203 case 2: 204 asm volatile("sh %1,%0" : "=m" (mem) : "r" (rs2)); 205 break; 206 case 4: 207 asm volatile("sw %1,%0" : "=m" (mem) : "r" (rs2)); 208 break; 209 case 8: 210 asm volatile("sd %1,%0" : "=m" (mem) : "r" (rs2)); 211 break; 212 } 213 return mem; 214} 215 216inline int64_t 217addi(int64_t rs1, const int16_t imm) 218{ 219 int64_t rd = 0; 220 IOP("addi", rd, rs1, imm); 221 return rd; 222} 223 224inline bool 225slti(int64_t rs1, const int16_t imm) 226{ 227 bool rd = false; 228 IOP("slti", rd, rs1, imm); 229 return rd; 230} 231 232inline bool 233sltiu(uint64_t rs1, const uint16_t imm) 234{ 235 bool rd = false; 236 IOP("sltiu", rd, rs1, imm); 237 return rd; 238} 239 240inline uint64_t 241xori(uint64_t rs1, const uint16_t imm) 242{ 243 uint64_t rd = 0; 244 IOP("xori", rd, rs1, imm); 245 return rd; 246} 247 248inline uint64_t 249ori(uint64_t rs1, const uint16_t imm) 250{ 251 uint64_t rd = 0; 252 IOP("ori", rd, rs1, imm); 253 return rd; 254} 255 256inline uint64_t 257andi(uint64_t rs1, const uint16_t imm) 258{ 259 uint64_t rd = 0; 260 IOP("andi", rd, rs1, imm); 261 return rd; 262} 263 264inline int64_t 265slli(int64_t rs1, const uint16_t imm) 266{ 267 int64_t rd = 0; 268 IOP("slli", rd, rs1, imm); 269 return rd; 270} 271 272inline uint64_t 273srli(uint64_t rs1, const uint16_t imm) 274{ 275 uint64_t rd = 0; 276 IOP("srli", rd, rs1, imm); 277 return rd; 278} 279 280inline int64_t 281srai(int64_t rs1, const uint16_t imm) 282{ 283 int64_t rd = 0; 284 IOP("srai", rd, rs1, imm); 285 return rd; 286} 287 288inline int64_t 289add(int64_t rs1, int64_t rs2) 290{ 291 int64_t rd = 0; 292 ROP("add", rd, rs1, rs2); 293 return rd; 294} 295 296inline int64_t 297sub(int64_t rs1, int64_t rs2) 298{ 299 int64_t rd = 0; 300 ROP("sub", rd, rs1, rs2); 301 return rd; 302} 303 304inline int64_t 305sll(int64_t rs1, int64_t rs2) 306{ 307 int64_t rd = 0; 308 ROP("sll", rd, rs1, rs2); 309 return rd; 310} 311 312inline bool 313slt(int64_t rs1, int64_t rs2) 314{ 315 bool rd = false; 316 ROP("slt", rd, rs1, rs2); 317 return rd; 318} 319 320inline bool 321sltu(uint64_t rs1, uint64_t rs2) 322{ 323 bool rd = false; 324 ROP("sltu", rd, rs1, rs2); 325 return rd; 326} 327 328inline uint64_t 329xor_inst(uint64_t rs1, uint64_t rs2) 330{ 331 uint64_t rd = 0; 332 ROP("xor", rd, rs1, rs2); 333 return rd; 334} 335 336inline uint64_t 337srl(uint64_t rs1, uint64_t rs2) 338{ 339 uint64_t rd = 0; 340 ROP("srl", rd, rs1, rs2); 341 return rd; 342} 343 344inline int64_t 345sra(int64_t rs1, int64_t rs2) 346{ 347 int64_t rd = 0; 348 ROP("sra", rd, rs1, rs2); 349 return rd; 350} 351 352inline uint64_t 353or_inst(uint64_t rs1, uint64_t rs2) 354{ 355 uint64_t rd = 0; 356 ROP("or", rd, rs1, rs2); 357 return rd; 358} 359 360inline uint64_t 361and_inst(uint64_t rs1, uint64_t rs2) 362{ 363 uint64_t rd = 0; 364 ROP("and", rd, rs1, rs2); 365 return rd; 366} 367 368inline int64_t 369addiw(int64_t rs1, const int16_t imm) 370{ 371 int64_t rd = 0; 372 IOP("addiw", rd, rs1, imm); 373 return rd; 374} 375 376inline int64_t 377slliw(int64_t rs1, const uint16_t imm) 378{ 379 int64_t rd = 0; 380 IOP("slliw", rd, rs1, imm); 381 return rd; 382} 383 384inline uint64_t 385srliw(uint64_t rs1, const uint16_t imm) 386{ 387 uint64_t rd = 0; 388 IOP("srliw", rd, rs1, imm); 389 return rd; 390} 391 392inline int64_t 393sraiw(int64_t rs1, const uint16_t imm) 394{ 395 int64_t rd = 0; 396 IOP("sraiw", rd, rs1, imm); 397 return rd; 398} 399 400inline int64_t 401addw(int64_t rs1, int64_t rs2) 402{ 403 int64_t rd = 0; 404 ROP("addw", rd, rs1, rs2); 405 return rd; 406} 407 408inline int64_t 409subw(int64_t rs1, int64_t rs2) 410{ 411 int64_t rd = 0; 412 ROP("subw", rd, rs1, rs2); 413 return rd; 414} 415 416inline int64_t 417sllw(int64_t rs1, int64_t rs2) 418{ 419 int64_t rd = 0; 420 ROP("sllw", rd, rs1, rs2); 421 return rd; 422} 423 424inline uint64_t 425srlw(uint64_t rs1, uint64_t rs2) 426{ 427 uint64_t rd = 0; 428 ROP("srlw", rd, rs1, rs2); 429 return rd; 430} 431 432inline int64_t 433sraw(int64_t rs1, int64_t rs2) 434{ 435 int64_t rd = 0; 436 ROP("sraw", rd, rs1, rs2); 437 return rd; 438} 439 440} // namespace I 441