diff options
author | Andrew Waterman <waterman@s141.Millennium.Berkeley.EDU> | 2011-06-19 20:47:29 -0700 |
---|---|---|
committer | Andrew Waterman <waterman@s141.Millennium.Berkeley.EDU> | 2011-06-19 20:47:29 -0700 |
commit | 77452a26e7d95d29dbaa797595ae683f03a3345b (patch) | |
tree | e7aaae682f73a20ceb4d3366528b0cd38378f49d /riscv | |
parent | 740f981cfd55604d46598144dccac26dd53f643c (diff) | |
download | spike-77452a26e7d95d29dbaa797595ae683f03a3345b.zip spike-77452a26e7d95d29dbaa797595ae683f03a3345b.tar.gz spike-77452a26e7d95d29dbaa797595ae683f03a3345b.tar.bz2 |
temporary undoing of renaming
Diffstat (limited to 'riscv')
294 files changed, 3310 insertions, 0 deletions
diff --git a/riscv/common.h b/riscv/common.h new file mode 100644 index 0000000..801baf8 --- /dev/null +++ b/riscv/common.h @@ -0,0 +1,9 @@ +#ifndef _RISCV_COMMON_H +#define _RISCV_COMMON_H + +#define static_assert(x) switch (x) case 0: case (x): + +#define likely(x) __builtin_expect(x, 1) +#define unlikely(x) __builtin_expect(x, 0) + +#endif diff --git a/riscv/decode.h b/riscv/decode.h new file mode 100644 index 0000000..f78c8f4 --- /dev/null +++ b/riscv/decode.h @@ -0,0 +1,301 @@ +#ifndef _RISCV_DECODE_H +#define _RISCV_DECODE_H + +#define __STDC_LIMIT_MACROS +#include <stdint.h> +#include "common.h" +#include "config.h" + +typedef int int128_t __attribute__((mode(TI))); +typedef unsigned int uint128_t __attribute__((mode(TI))); + +typedef int64_t sreg_t; +typedef uint64_t reg_t; +typedef uint64_t freg_t; + +const int OPCODE_BITS = 7; + +const int XPRID_BITS = 5; +const int NXPR = 1 << XPRID_BITS; + +const int FPR_BITS = 64; +const int FPRID_BITS = 5; +const int NFPR = 1 << FPRID_BITS; + +const int IMM_BITS = 12; +const int IMMLO_BITS = 7; +const int TARGET_BITS = 25; +const int FUNCT_BITS = 3; +const int FUNCTR_BITS = 7; +const int FFUNCT_BITS = 2; +const int RM_BITS = 3; +const int BIGIMM_BITS = 20; +const int BRANCH_ALIGN_BITS = 1; +const int JUMP_ALIGN_BITS = 1; + +#define SR_ET 0x0000000000000001ULL +#define SR_EF 0x0000000000000002ULL +#define SR_EV 0x0000000000000004ULL +#define SR_EC 0x0000000000000008ULL +#define SR_PS 0x0000000000000010ULL +#define SR_S 0x0000000000000020ULL +#define SR_UX 0x0000000000000040ULL +#define SR_SX 0x0000000000000080ULL +#define SR_IM 0x000000000000FF00ULL +#define SR_VM 0x0000000000010000ULL +#define SR_ZERO ~(SR_ET|SR_EF|SR_EV|SR_EC|SR_PS|SR_S|SR_UX|SR_SX|SR_IM|SR_VM) +#define SR_IM_SHIFT 8 +#define IPI_IRQ 5 +#define TIMER_IRQ 7 + +#define CAUSE_EXCCODE 0x000000FF +#define CAUSE_IP 0x0000FF00 +#define CAUSE_EXCCODE_SHIFT 0 +#define CAUSE_IP_SHIFT 8 + +#define FP_RD_NE 0 +#define FP_RD_0 1 +#define FP_RD_DN 2 +#define FP_RD_UP 3 +#define FP_RD_NMM 4 + +#define FSR_RD_SHIFT 5 +#define FSR_RD (0x7 << FSR_RD_SHIFT) + +#define FPEXC_NX 0x01 +#define FPEXC_UF 0x02 +#define FPEXC_OF 0x04 +#define FPEXC_DZ 0x08 +#define FPEXC_NV 0x10 + +#define FSR_AEXC_SHIFT 0 +#define FSR_NVA (FPEXC_NV << FSR_AEXC_SHIFT) +#define FSR_OFA (FPEXC_OF << FSR_AEXC_SHIFT) +#define FSR_UFA (FPEXC_UF << FSR_AEXC_SHIFT) +#define FSR_DZA (FPEXC_DZ << FSR_AEXC_SHIFT) +#define FSR_NXA (FPEXC_NX << FSR_AEXC_SHIFT) +#define FSR_AEXC (FSR_NVA | FSR_OFA | FSR_UFA | FSR_DZA | FSR_NXA) + +#define FSR_ZERO ~(FSR_RD | FSR_AEXC) + +// note: bit fields are in little-endian order +struct itype_t +{ + unsigned opcode : OPCODE_BITS; + unsigned funct : FUNCT_BITS; + signed imm12 : IMM_BITS; + unsigned rs1 : XPRID_BITS; + unsigned rd : XPRID_BITS; +}; + +struct btype_t +{ + unsigned opcode : OPCODE_BITS; + unsigned funct : FUNCT_BITS; + unsigned immlo : IMMLO_BITS; + unsigned rs2 : XPRID_BITS; + unsigned rs1 : XPRID_BITS; + signed immhi : IMM_BITS-IMMLO_BITS; +}; + +struct jtype_t +{ + unsigned jump_opcode : OPCODE_BITS; + signed target : TARGET_BITS; +}; + +struct rtype_t +{ + unsigned opcode : OPCODE_BITS; + unsigned funct : FUNCT_BITS; + unsigned functr : FUNCTR_BITS; + unsigned rs2 : XPRID_BITS; + unsigned rs1 : XPRID_BITS; + unsigned rd : XPRID_BITS; +}; + +struct ltype_t +{ + unsigned opcode : OPCODE_BITS; + unsigned bigimm : BIGIMM_BITS; + unsigned rd : XPRID_BITS; +}; + +struct ftype_t +{ + unsigned opcode : OPCODE_BITS; + unsigned ffunct : FFUNCT_BITS; + unsigned rm : RM_BITS; + unsigned rs3 : FPRID_BITS; + unsigned rs2 : FPRID_BITS; + unsigned rs1 : FPRID_BITS; + unsigned rd : FPRID_BITS; +}; + +union insn_t +{ + itype_t itype; + jtype_t jtype; + rtype_t rtype; + btype_t btype; + ltype_t ltype; + ftype_t ftype; + uint32_t bits; +}; + +#include <stdio.h> +class do_writeback +{ +public: + do_writeback(reg_t* _rf, int _rd) : rf(_rf), rd(_rd) {} + + const do_writeback& operator = (reg_t rhs) + { +#if 0 + printf("R[%x] <= %llx\n",rd,(long long)rhs); +#endif + rf[rd] = rhs; + rf[0] = 0; + return *this; + } + + operator reg_t() { return rf[rd]; } + +private: + reg_t* rf; + int rd; +}; + +#define throw_illegal_instruction \ + ({ if (utmode) throw trap_vector_illegal_instruction; \ + else throw trap_illegal_instruction; }) + +// helpful macros, etc +#define RS1 XPR[insn.rtype.rs1] +#define RS2 XPR[insn.rtype.rs2] +#define RD do_writeback(XPR,insn.rtype.rd) +#define RA do_writeback(XPR,1) +#define FRS1 FPR[insn.ftype.rs1] +#define FRS2 FPR[insn.ftype.rs2] +#define FRS3 FPR[insn.ftype.rs3] +#define FRD FPR[insn.ftype.rd] +#define BIGIMM insn.ltype.bigimm +#define SIMM insn.itype.imm12 +#define BIMM ((signed)insn.btype.immlo | (insn.btype.immhi << IMMLO_BITS)) +#define SHAMT (insn.itype.imm12 & 0x3F) +#define SHAMTW (insn.itype.imm12 & 0x1F) +#define TARGET insn.jtype.target +#define BRANCH_TARGET (pc + (BIMM << BRANCH_ALIGN_BITS)) +#define JUMP_TARGET (pc + (TARGET << JUMP_ALIGN_BITS)) +#define RM ({ int rm = insn.ftype.rm; \ + if(rm == 7) rm = (fsr & FSR_RD) >> FSR_RD_SHIFT; \ + if(rm > 4) throw_illegal_instruction; \ + rm; }) + +#define require_supervisor if(unlikely(!(sr & SR_S))) throw trap_privileged_instruction +#define xpr64 (xprlen == 64) +#define require_xpr64 if(unlikely(!xpr64)) throw_illegal_instruction +#define require_xpr32 if(unlikely(xpr64)) throw_illegal_instruction +#define require_fp if(unlikely(!(sr & SR_EF))) throw trap_fp_disabled +#define require_vector \ + ({ if(!(sr & SR_EV)) throw trap_vector_disabled; \ + else if (!utmode && (vecbanks_count < 3)) throw trap_vector_bank; \ + }) +#define cmp_trunc(reg) (reg_t(reg) << (64-xprlen)) +#define set_fp_exceptions ({ set_fsr(fsr | \ + (softfloat_exceptionFlags << FSR_AEXC_SHIFT)); \ + softfloat_exceptionFlags = 0; }) + +#define sext32(x) ((sreg_t)(int32_t)(x)) +#define zext32(x) ((reg_t)(uint32_t)(x)) +#define sext_xprlen(x) ((sreg_t(x) << (64-xprlen)) >> (64-xprlen)) +#define zext_xprlen(x) ((reg_t(x) << (64-xprlen)) >> (64-xprlen)) + +#ifndef RISCV_ENABLE_RVC +# define set_pc(x) \ + do { if((x) & (sizeof(insn_t)-1)) \ + { badvaddr = (x); throw trap_instruction_address_misaligned; } \ + npc = (x); \ + } while(0) +#else +# define set_pc(x) \ + do { if((x) & ((sr & SR_EC) ? 1 : 3)) \ + { badvaddr = (x); throw trap_instruction_address_misaligned; } \ + npc = (x); \ + } while(0) +#endif + +// RVC stuff + +#define INSN_IS_RVC(x) (((x) & 0x3) < 0x3) +#define insn_length(x) (INSN_IS_RVC(x) ? 2 : 4) +#define require_rvc if(!(sr & SR_EC)) throw_illegal_instruction + +#define CRD_REGNUM ((insn.bits >> 5) & 0x1f) +#define CRD do_writeback(XPR, CRD_REGNUM) +#define CRS1 XPR[(insn.bits >> 10) & 0x1f] +#define CRS2 XPR[(insn.bits >> 5) & 0x1f] +#define CIMM6 ((int32_t)((insn.bits >> 10) & 0x3f) << 26 >> 26) +#define CIMM5U ((insn.bits >> 5) & 0x1f) +#define CIMM5 ((int32_t)CIMM5U << 27 >> 27) +#define CIMM10 ((int32_t)((insn.bits >> 5) & 0x3ff) << 22 >> 22) +#define CBRANCH_TARGET (pc + (CIMM5 << BRANCH_ALIGN_BITS)) +#define CJUMP_TARGET (pc + (CIMM10 << JUMP_ALIGN_BITS)) + +static const int rvc_rs1_regmap[8] = { 20, 21, 2, 3, 4, 5, 6, 7 }; +#define rvc_rd_regmap rvc_rs1_regmap +#define rvc_rs2b_regmap rvc_rs1_regmap +static const int rvc_rs2_regmap[8] = { 20, 21, 2, 3, 4, 5, 6, 0 }; +#define CRDS XPR[rvc_rd_regmap[(insn.bits >> 13) & 0x7]] +#define FCRDS FPR[rvc_rd_regmap[(insn.bits >> 13) & 0x7]] +#define CRS1S XPR[rvc_rs1_regmap[(insn.bits >> 10) & 0x7]] +#define CRS2S XPR[rvc_rs2_regmap[(insn.bits >> 13) & 0x7]] +#define CRS2BS XPR[rvc_rs2b_regmap[(insn.bits >> 5) & 0x7]] +#define FCRS2S FPR[rvc_rs2_regmap[(insn.bits >> 13) & 0x7]] + +// vector stuff +#define VL vl + +#define UT_RS1(idx) uts[idx]->XPR[insn.rtype.rs1] +#define UT_RS2(idx) uts[idx]->XPR[insn.rtype.rs2] +#define UT_RD(idx) do_writeback(uts[idx]->XPR,insn.rtype.rd) +#define UT_RA(idx) do_writeback(uts[idx]->XPR,1) +#define UT_FRS1(idx) uts[idx]->FPR[insn.ftype.rs1] +#define UT_FRS2(idx) uts[idx]->FPR[insn.ftype.rs2] +#define UT_FRS3(idx) uts[idx]->FPR[insn.ftype.rs3] +#define UT_FRD(idx) uts[idx]->FPR[insn.ftype.rd] +#define UT_RM(idx) ((insn.ftype.rm != 7) ? insn.ftype.rm : \ + ((uts[idx]->fsr & FSR_RD) >> FSR_RD_SHIFT)) + +#define UT_LOOP_START for (int i=0;i<VL; i++) { +#define UT_LOOP_END } +#define UT_LOOP_RS1 UT_RS1(i) +#define UT_LOOP_RS2 UT_RS2(i) +#define UT_LOOP_RD UT_RD(i) +#define UT_LOOP_RA UT_RA(i) +#define UT_LOOP_FRS1 UT_FRS1(i) +#define UT_LOOP_FRS2 UT_FRS2(i) +#define UT_LOOP_FRS3 UT_FRS3(i) +#define UT_LOOP_FRD UT_FRD(i) +#define UT_LOOP_RM UT_RM(i) + +#define VEC_LOAD(dst, func, inc) \ + reg_t addr = RS1; \ + UT_LOOP_START \ + UT_LOOP_##dst = mmu.func(addr); \ + addr += inc; \ + UT_LOOP_END + +#define VEC_STORE(src, func, inc) \ + reg_t addr = RS1; \ + UT_LOOP_START \ + mmu.func(addr, UT_LOOP_##src); \ + addr += inc; \ + UT_LOOP_END + +enum vt_command_t +{ + vt_command_stop, +}; + +#endif diff --git a/riscv/dispatch b/riscv/dispatch new file mode 100755 index 0000000..b96b364 --- /dev/null +++ b/riscv/dispatch @@ -0,0 +1,77 @@ +#!/usr/bin/python +import sys + +if len(sys.argv) == 3: + numfiles = int(sys.argv[1]) + tablesz = int(sys.argv[2]) + filenum = numfiles+1 +else: + filenum = int(sys.argv[1]) + numfiles = int(sys.argv[2]) + tablesz = int(sys.argv[3]) + +match = {} +mask = {} +seen = {} +for line in sys.stdin: + (name, mtch, msk) = line.split('(')[1].split(')')[0].split(',') + match[name] = int(mtch,16) + mask[name] = int(msk,16) + +redundant = {} +for name in match.iterkeys(): + if (mask[name] & (tablesz-1)) == mask[name]: + for i in range(match[name]+1, tablesz): + if (i & mask[name]) == match[name]: + redundant[i] = match[name] + +illegal = -1 +for i in range(0, tablesz): + used = 0 + for name in match.iterkeys(): + if match[name] % tablesz == (i & mask[name]): + used = 1 + if not used and illegal == -1: + illegal = i + elif not used: + redundant[i] = illegal + +if filenum == numfiles: + print '#include "processor.h"' + print 'const insn_func_t processor_t::dispatch_table[DISPATCH_TABLE_SIZE] = {' + for i in range(0, tablesz): + func = i + if i in redundant: + func = redundant[i] + print ' &processor_t::insn_func_%d,' % func + print '};' + +if filenum == numfiles+1: + print 'static const size_t DISPATCH_TABLE_SIZE = %d;' % tablesz + print 'static const insn_func_t dispatch_table[DISPATCH_TABLE_SIZE];' + for i in range(0, tablesz): + if i not in redundant: + print 'reg_t insn_func_%d(insn_t insn, reg_t reg);' % i + sys.exit(0) + +print '#include "insn_header.h"' + +for i in range(0, tablesz): + if i % numfiles != filenum or i in redundant: + continue + + print 'reg_t processor_t::insn_func_%d(insn_t insn, reg_t pc)' % i + print '{' + for name in match.iterkeys(): + if match[name] % tablesz == (i & mask[name]): + print ' if((insn.bits & 0x%x) == 0x%x)' % (mask[name] & ~(tablesz-1), \ + match[name] & ~(tablesz-1)) + print ' {' + print ' reg_t npc = pc + insn_length(0x%x);' % match[name] + print ' #include "insns/%s.h"' % name + print ' return npc;' + print ' }' + print ' else', + + print ' throw trap_illegal_instruction;' + print '}\n' diff --git a/riscv/dispatch.h b/riscv/dispatch.h new file mode 100644 index 0000000..7091899 --- /dev/null +++ b/riscv/dispatch.h @@ -0,0 +1,254 @@ +static const size_t DISPATCH_TABLE_SIZE = 1024; +static const insn_func_t dispatch_table[DISPATCH_TABLE_SIZE]; +reg_t insn_func_0(insn_t insn, reg_t reg); +reg_t insn_func_1(insn_t insn, reg_t reg); +reg_t insn_func_2(insn_t insn, reg_t reg); +reg_t insn_func_3(insn_t insn, reg_t reg); +reg_t insn_func_4(insn_t insn, reg_t reg); +reg_t insn_func_5(insn_t insn, reg_t reg); +reg_t insn_func_6(insn_t insn, reg_t reg); +reg_t insn_func_7(insn_t insn, reg_t reg); +reg_t insn_func_8(insn_t insn, reg_t reg); +reg_t insn_func_9(insn_t insn, reg_t reg); +reg_t insn_func_10(insn_t insn, reg_t reg); +reg_t insn_func_11(insn_t insn, reg_t reg); +reg_t insn_func_12(insn_t insn, reg_t reg); +reg_t insn_func_13(insn_t insn, reg_t reg); +reg_t insn_func_15(insn_t insn, reg_t reg); +reg_t insn_func_16(insn_t insn, reg_t reg); +reg_t insn_func_17(insn_t insn, reg_t reg); +reg_t insn_func_18(insn_t insn, reg_t reg); +reg_t insn_func_19(insn_t insn, reg_t reg); +reg_t insn_func_20(insn_t insn, reg_t reg); +reg_t insn_func_21(insn_t insn, reg_t reg); +reg_t insn_func_22(insn_t insn, reg_t reg); +reg_t insn_func_24(insn_t insn, reg_t reg); +reg_t insn_func_25(insn_t insn, reg_t reg); +reg_t insn_func_26(insn_t insn, reg_t reg); +reg_t insn_func_27(insn_t insn, reg_t reg); +reg_t insn_func_28(insn_t insn, reg_t reg); +reg_t insn_func_29(insn_t insn, reg_t reg); +reg_t insn_func_34(insn_t insn, reg_t reg); +reg_t insn_func_35(insn_t insn, reg_t reg); +reg_t insn_func_50(insn_t insn, reg_t reg); +reg_t insn_func_51(insn_t insn, reg_t reg); +reg_t insn_func_55(insn_t insn, reg_t reg); +reg_t insn_func_57(insn_t insn, reg_t reg); +reg_t insn_func_58(insn_t insn, reg_t reg); +reg_t insn_func_59(insn_t insn, reg_t reg); +reg_t insn_func_66(insn_t insn, reg_t reg); +reg_t insn_func_67(insn_t insn, reg_t reg); +reg_t insn_func_71(insn_t insn, reg_t reg); +reg_t insn_func_75(insn_t insn, reg_t reg); +reg_t insn_func_79(insn_t insn, reg_t reg); +reg_t insn_func_82(insn_t insn, reg_t reg); +reg_t insn_func_83(insn_t insn, reg_t reg); +reg_t insn_func_89(insn_t insn, reg_t reg); +reg_t insn_func_90(insn_t insn, reg_t reg); +reg_t insn_func_98(insn_t insn, reg_t reg); +reg_t insn_func_99(insn_t insn, reg_t reg); +reg_t insn_func_103(insn_t insn, reg_t reg); +reg_t insn_func_107(insn_t insn, reg_t reg); +reg_t insn_func_111(insn_t insn, reg_t reg); +reg_t insn_func_114(insn_t insn, reg_t reg); +reg_t insn_func_115(insn_t insn, reg_t reg); +reg_t insn_func_119(insn_t insn, reg_t reg); +reg_t insn_func_121(insn_t insn, reg_t reg); +reg_t insn_func_122(insn_t insn, reg_t reg); +reg_t insn_func_123(insn_t insn, reg_t reg); +reg_t insn_func_130(insn_t insn, reg_t reg); +reg_t insn_func_131(insn_t insn, reg_t reg); +reg_t insn_func_139(insn_t insn, reg_t reg); +reg_t insn_func_143(insn_t insn, reg_t reg); +reg_t insn_func_146(insn_t insn, reg_t reg); +reg_t insn_func_147(insn_t insn, reg_t reg); +reg_t insn_func_153(insn_t insn, reg_t reg); +reg_t insn_func_154(insn_t insn, reg_t reg); +reg_t insn_func_155(insn_t insn, reg_t reg); +reg_t insn_func_162(insn_t insn, reg_t reg); +reg_t insn_func_163(insn_t insn, reg_t reg); +reg_t insn_func_175(insn_t insn, reg_t reg); +reg_t insn_func_178(insn_t insn, reg_t reg); +reg_t insn_func_179(insn_t insn, reg_t reg); +reg_t insn_func_185(insn_t insn, reg_t reg); +reg_t insn_func_186(insn_t insn, reg_t reg); +reg_t insn_func_187(insn_t insn, reg_t reg); +reg_t insn_func_194(insn_t insn, reg_t reg); +reg_t insn_func_195(insn_t insn, reg_t reg); +reg_t insn_func_199(insn_t insn, reg_t reg); +reg_t insn_func_203(insn_t insn, reg_t reg); +reg_t insn_func_207(insn_t insn, reg_t reg); +reg_t insn_func_210(insn_t insn, reg_t reg); +reg_t insn_func_211(insn_t insn, reg_t reg); +reg_t insn_func_217(insn_t insn, reg_t reg); +reg_t insn_func_218(insn_t insn, reg_t reg); +reg_t insn_func_226(insn_t insn, reg_t reg); +reg_t insn_func_227(insn_t insn, reg_t reg); +reg_t insn_func_235(insn_t insn, reg_t reg); +reg_t insn_func_242(insn_t insn, reg_t reg); +reg_t insn_func_243(insn_t insn, reg_t reg); +reg_t insn_func_247(insn_t insn, reg_t reg); +reg_t insn_func_249(insn_t insn, reg_t reg); +reg_t insn_func_250(insn_t insn, reg_t reg); +reg_t insn_func_251(insn_t insn, reg_t reg); +reg_t insn_func_258(insn_t insn, reg_t reg); +reg_t insn_func_259(insn_t insn, reg_t reg); +reg_t insn_func_263(insn_t insn, reg_t reg); +reg_t insn_func_267(insn_t insn, reg_t reg); +reg_t insn_func_271(insn_t insn, reg_t reg); +reg_t insn_func_274(insn_t insn, reg_t reg); +reg_t insn_func_275(insn_t insn, reg_t reg); +reg_t insn_func_281(insn_t insn, reg_t reg); +reg_t insn_func_282(insn_t insn, reg_t reg); +reg_t insn_func_284(insn_t insn, reg_t reg); +reg_t insn_func_290(insn_t insn, reg_t reg); +reg_t insn_func_291(insn_t insn, reg_t reg); +reg_t insn_func_295(insn_t insn, reg_t reg); +reg_t insn_func_299(insn_t insn, reg_t reg); +reg_t insn_func_303(insn_t insn, reg_t reg); +reg_t insn_func_306(insn_t insn, reg_t reg); +reg_t insn_func_307(insn_t insn, reg_t reg); +reg_t insn_func_313(insn_t insn, reg_t reg); +reg_t insn_func_314(insn_t insn, reg_t reg); +reg_t insn_func_322(insn_t insn, reg_t reg); +reg_t insn_func_338(insn_t insn, reg_t reg); +reg_t insn_func_345(insn_t insn, reg_t reg); +reg_t insn_func_346(insn_t insn, reg_t reg); +reg_t insn_func_354(insn_t insn, reg_t reg); +reg_t insn_func_363(insn_t insn, reg_t reg); +reg_t insn_func_370(insn_t insn, reg_t reg); +reg_t insn_func_371(insn_t insn, reg_t reg); +reg_t insn_func_375(insn_t insn, reg_t reg); +reg_t insn_func_377(insn_t insn, reg_t reg); +reg_t insn_func_378(insn_t insn, reg_t reg); +reg_t insn_func_379(insn_t insn, reg_t reg); +reg_t insn_func_386(insn_t insn, reg_t reg); +reg_t insn_func_387(insn_t insn, reg_t reg); +reg_t insn_func_391(insn_t insn, reg_t reg); +reg_t insn_func_395(insn_t insn, reg_t reg); +reg_t insn_func_399(insn_t insn, reg_t reg); +reg_t insn_func_402(insn_t insn, reg_t reg); +reg_t insn_func_403(insn_t insn, reg_t reg); +reg_t insn_func_409(insn_t insn, reg_t reg); +reg_t insn_func_410(insn_t insn, reg_t reg); +reg_t insn_func_418(insn_t insn, reg_t reg); +reg_t insn_func_419(insn_t insn, reg_t reg); +reg_t insn_func_423(insn_t insn, reg_t reg); +reg_t insn_func_427(insn_t insn, reg_t reg); +reg_t insn_func_434(insn_t insn, reg_t reg); +reg_t insn_func_435(insn_t insn, reg_t reg); +reg_t insn_func_441(insn_t insn, reg_t reg); +reg_t insn_func_442(insn_t insn, reg_t reg); +reg_t insn_func_450(insn_t insn, reg_t reg); +reg_t insn_func_466(insn_t insn, reg_t reg); +reg_t insn_func_473(insn_t insn, reg_t reg); +reg_t insn_func_474(insn_t insn, reg_t reg); +reg_t insn_func_482(insn_t insn, reg_t reg); +reg_t insn_func_498(insn_t insn, reg_t reg); +reg_t insn_func_499(insn_t insn, reg_t reg); +reg_t insn_func_503(insn_t insn, reg_t reg); +reg_t insn_func_505(insn_t insn, reg_t reg); +reg_t insn_func_506(insn_t insn, reg_t reg); +reg_t insn_func_507(insn_t insn, reg_t reg); +reg_t insn_func_514(insn_t insn, reg_t reg); +reg_t insn_func_515(insn_t insn, reg_t reg); +reg_t insn_func_523(insn_t insn, reg_t reg); +reg_t insn_func_530(insn_t insn, reg_t reg); +reg_t insn_func_531(insn_t insn, reg_t reg); +reg_t insn_func_537(insn_t insn, reg_t reg); +reg_t insn_func_538(insn_t insn, reg_t reg); +reg_t insn_func_540(insn_t insn, reg_t reg); +reg_t insn_func_546(insn_t insn, reg_t reg); +reg_t insn_func_559(insn_t insn, reg_t reg); +reg_t insn_func_562(insn_t insn, reg_t reg); +reg_t insn_func_563(insn_t insn, reg_t reg); +reg_t insn_func_569(insn_t insn, reg_t reg); +reg_t insn_func_570(insn_t insn, reg_t reg); +reg_t insn_func_571(insn_t insn, reg_t reg); +reg_t insn_func_578(insn_t insn, reg_t reg); +reg_t insn_func_594(insn_t insn, reg_t reg); +reg_t insn_func_595(insn_t insn, reg_t reg); +reg_t insn_func_601(insn_t insn, reg_t reg); +reg_t insn_func_602(insn_t insn, reg_t reg); +reg_t insn_func_610(insn_t insn, reg_t reg); +reg_t insn_func_611(insn_t insn, reg_t reg); +reg_t insn_func_619(insn_t insn, reg_t reg); +reg_t insn_func_626(insn_t insn, reg_t reg); +reg_t insn_func_631(insn_t insn, reg_t reg); +reg_t insn_func_633(insn_t insn, reg_t reg); +reg_t insn_func_634(insn_t insn, reg_t reg); +reg_t insn_func_635(insn_t insn, reg_t reg); +reg_t insn_func_642(insn_t insn, reg_t reg); +reg_t insn_func_643(insn_t insn, reg_t reg); +reg_t insn_func_651(insn_t insn, reg_t reg); +reg_t insn_func_658(insn_t insn, reg_t reg); +reg_t insn_func_659(insn_t insn, reg_t reg); +reg_t insn_func_665(insn_t insn, reg_t reg); +reg_t insn_func_666(insn_t insn, reg_t reg); +reg_t insn_func_667(insn_t insn, reg_t reg); +reg_t insn_func_674(insn_t insn, reg_t reg); +reg_t insn_func_687(insn_t insn, reg_t reg); +reg_t insn_func_690(insn_t insn, reg_t reg); +reg_t insn_func_691(insn_t insn, reg_t reg); +reg_t insn_func_697(insn_t insn, reg_t reg); +reg_t insn_func_698(insn_t insn, reg_t reg); +reg_t insn_func_699(insn_t insn, reg_t reg); +reg_t insn_func_706(insn_t insn, reg_t reg); +reg_t insn_func_722(insn_t insn, reg_t reg); +reg_t insn_func_723(insn_t insn, reg_t reg); +reg_t insn_func_729(insn_t insn, reg_t reg); +reg_t insn_func_730(insn_t insn, reg_t reg); +reg_t insn_func_738(insn_t insn, reg_t reg); +reg_t insn_func_739(insn_t insn, reg_t reg); +reg_t insn_func_754(insn_t insn, reg_t reg); +reg_t insn_func_755(insn_t insn, reg_t reg); +reg_t insn_func_759(insn_t insn, reg_t reg); +reg_t insn_func_761(insn_t insn, reg_t reg); +reg_t insn_func_762(insn_t insn, reg_t reg); +reg_t insn_func_763(insn_t insn, reg_t reg); +reg_t insn_func_770(insn_t insn, reg_t reg); +reg_t insn_func_771(insn_t insn, reg_t reg); +reg_t insn_func_779(insn_t insn, reg_t reg); +reg_t insn_func_786(insn_t insn, reg_t reg); +reg_t insn_func_787(insn_t insn, reg_t reg); +reg_t insn_func_793(insn_t insn, reg_t reg); +reg_t insn_func_794(insn_t insn, reg_t reg); +reg_t insn_func_796(insn_t insn, reg_t reg); +reg_t insn_func_802(insn_t insn, reg_t reg); +reg_t insn_func_815(insn_t insn, reg_t reg); +reg_t insn_func_818(insn_t insn, reg_t reg); +reg_t insn_func_819(insn_t insn, reg_t reg); +reg_t insn_func_825(insn_t insn, reg_t reg); +reg_t insn_func_826(insn_t insn, reg_t reg); +reg_t insn_func_827(insn_t insn, reg_t reg); +reg_t insn_func_834(insn_t insn, reg_t reg); +reg_t insn_func_850(insn_t insn, reg_t reg); +reg_t insn_func_857(insn_t insn, reg_t reg); +reg_t insn_func_858(insn_t insn, reg_t reg); +reg_t insn_func_866(insn_t insn, reg_t reg); +reg_t insn_func_867(insn_t insn, reg_t reg); +reg_t insn_func_882(insn_t insn, reg_t reg); +reg_t insn_func_889(insn_t insn, reg_t reg); +reg_t insn_func_890(insn_t insn, reg_t reg); +reg_t insn_func_898(insn_t insn, reg_t reg); +reg_t insn_func_914(insn_t insn, reg_t reg); +reg_t insn_func_915(insn_t insn, reg_t reg); +reg_t insn_func_921(insn_t insn, reg_t reg); +reg_t insn_func_922(insn_t insn, reg_t reg); +reg_t insn_func_930(insn_t insn, reg_t reg); +reg_t insn_func_943(insn_t insn, reg_t reg); +reg_t insn_func_946(insn_t insn, reg_t reg); +reg_t insn_func_947(insn_t insn, reg_t reg); +reg_t insn_func_953(insn_t insn, reg_t reg); +reg_t insn_func_954(insn_t insn, reg_t reg); +reg_t insn_func_955(insn_t insn, reg_t reg); +reg_t insn_func_962(insn_t insn, reg_t reg); +reg_t insn_func_978(insn_t insn, reg_t reg); +reg_t insn_func_985(insn_t insn, reg_t reg); +reg_t insn_func_986(insn_t insn, reg_t reg); +reg_t insn_func_994(insn_t insn, reg_t reg); +reg_t insn_func_995(insn_t insn, reg_t reg); +reg_t insn_func_1010(insn_t insn, reg_t reg); +reg_t insn_func_1011(insn_t insn, reg_t reg); +reg_t insn_func_1017(insn_t insn, reg_t reg); +reg_t insn_func_1018(insn_t insn, reg_t reg); diff --git a/riscv/htif.cc b/riscv/htif.cc new file mode 100644 index 0000000..02809d0 --- /dev/null +++ b/riscv/htif.cc @@ -0,0 +1,143 @@ +#include "htif.h" +#include "common.h" +#include "sim.h" +#include <unistd.h> +#include <stdexcept> +#include <stdlib.h> +#include <errno.h> +#include <assert.h> + +enum +{ + APP_CMD_READ_MEM, + APP_CMD_WRITE_MEM, + APP_CMD_READ_CONTROL_REG, + APP_CMD_WRITE_CONTROL_REG, + APP_CMD_START, + APP_CMD_STOP, + APP_CMD_ACK, + APP_CMD_NACK +}; + +#define APP_DATA_ALIGN 8 +#define APP_MAX_DATA_SIZE 1024 +struct packet +{ + uint16_t cmd; + uint16_t seqno; + uint32_t data_size; + uint64_t addr; + uint8_t data[APP_MAX_DATA_SIZE]; +}; + +htif_t::htif_t(int _tohost_fd, int _fromhost_fd) + : sim(NULL), tohost_fd(_tohost_fd), fromhost_fd(_fromhost_fd), seqno(1) +{ +} + +htif_t::~htif_t() +{ + close(tohost_fd); + close(fromhost_fd); +} + +void htif_t::init(sim_t* _sim) +{ + sim = _sim; +} + +void htif_t::wait_for_start() +{ + while(wait_for_packet() != APP_CMD_START); +} + +void htif_t::wait_for_fromhost_write() +{ + while(wait_for_packet() != APP_CMD_WRITE_CONTROL_REG); +} + +void htif_t::send_packet(packet* p) +{ + int bytes = write(tohost_fd,p,offsetof(packet,data)+p->data_size); + if((size_t)bytes != offsetof(packet,data) + p->data_size) + { + const char* error = bytes == -1 ? strerror(errno) : "not all bytes sent"; + fprintf(stderr,"HTIF error: %s\n", error); + exit(-1); + } +} + +void htif_t::nack(uint16_t nack_seqno) +{ + packet p = {APP_CMD_NACK,nack_seqno,0,0}; + send_packet(&p); +} + +int htif_t::wait_for_packet() +{ + while(1) + { + packet p; + int bytes = read(fromhost_fd,&p,sizeof(p)); + if(bytes < (int)offsetof(packet,data)) + { + const char* error = bytes == -1 ? strerror(errno) : "too few bytes read"; + fprintf(stderr,"HTIF error: %s\n", error); + exit(-1); + } + + if(p.seqno != seqno) + { + nack(p.seqno); + continue; + } + + packet ackpacket = {APP_CMD_ACK,seqno,0,0}; + + switch(p.cmd) + { + case APP_CMD_START: + break; + case APP_CMD_STOP: + sim->stop(); + break; + case APP_CMD_READ_MEM: + assert(p.addr % APP_DATA_ALIGN == 0); + assert(p.data_size % APP_DATA_ALIGN == 0); + assert(p.data_size <= APP_MAX_DATA_SIZE); + assert(p.addr <= sim->memsz && p.addr+p.data_size <= sim->memsz); + ackpacket.data_size = p.data_size; + + static_assert(APP_DATA_ALIGN >= sizeof(uint64_t)) + for(size_t i = 0; i < p.data_size/8; i++) + ((uint64_t*)ackpacket.data)[i] = sim->mmu->load_uint64(p.addr+i*8); + break; + case APP_CMD_WRITE_MEM: + assert(p.addr % APP_DATA_ALIGN == 0); + assert(p.data_size % APP_DATA_ALIGN == 0); + assert(p.data_size <= bytes - offsetof(packet,data)); + assert(p.addr <= sim->memsz && p.addr+p.data_size <= sim->memsz); + + for(size_t i = 0; i < p.data_size/8; i++) + sim->mmu->store_uint64(p.addr+i*8, ((uint64_t*)p.data)[i]); + break; + case APP_CMD_READ_CONTROL_REG: + assert(p.addr == 16); + assert(p.data_size == sizeof(reg_t)); + ackpacket.data_size = sizeof(reg_t); + memcpy(ackpacket.data,&sim->tohost,sizeof(reg_t)); + break; + case APP_CMD_WRITE_CONTROL_REG: + assert(p.addr == 17); + assert(p.data_size == sizeof(reg_t)); + sim->tohost = 0; + memcpy(&sim->fromhost,p.data,sizeof(reg_t)); + break; + } + + send_packet(&ackpacket); + seqno++; + return p.cmd; + } +} + diff --git a/riscv/htif.h b/riscv/htif.h new file mode 100644 index 0000000..0106695 --- /dev/null +++ b/riscv/htif.h @@ -0,0 +1,35 @@ +#ifndef _HTIF_H +#define _HTIF_H + +#include <stdint.h> + +class sim_t; +struct packet; + +// this class implements the host-target interface for program loading, etc. +class htif_t +{ +public: + htif_t(int _tohost_fd, int _fromhost_fd); + ~htif_t(); + void init(sim_t* _sim); + + // wait for host to send start command + void wait_for_start(); + + // we block on the host if the target machine reads the fromhost register, + // which provides determinism in tohost/fromhost communication. + void wait_for_fromhost_write(); + +private: + sim_t* sim; + int tohost_fd; + int fromhost_fd; + uint16_t seqno; + + void nack(uint16_t seqno); + void send_packet(packet* p); + int wait_for_packet(); +}; + +#endif diff --git a/riscv/icsim.cc b/riscv/icsim.cc new file mode 100644 index 0000000..308e7ed --- /dev/null +++ b/riscv/icsim.cc @@ -0,0 +1,100 @@ +#include "icsim.h" +#include <stdexcept> +#include <iostream> +#include <iomanip> + +icsim_t::icsim_t(size_t _sets, size_t _ways, size_t _linesz, const char* _name) + : sets(_sets), ways(_ways), linesz(_linesz), idx_mask(_sets-1), name(_name) +{ + if(sets == 0 || (sets & (sets-1))) + throw std::logic_error("sets not a power of 2"); + if(linesz == 0 || (linesz & (linesz-1))) + throw std::logic_error("linesz not a power of 2"); + + idx_shift = 0; + while(_linesz >>= 1) + idx_shift++; + + tags = new uint64_t[sets*ways]; + memset(tags, 0, sets*ways*sizeof(uint64_t)); + + read_accesses = 0; + read_misses = 0; + bytes_read = 0; + write_accesses = 0; + write_misses = 0; + bytes_written = 0; + writebacks = 0; +} + +icsim_t::icsim_t(const icsim_t& rhs) + : sets(rhs.sets), ways(rhs.ways), linesz(rhs.linesz), + idx_shift(rhs.idx_shift), idx_mask(rhs.idx_mask), name(rhs.name) +{ + tags = new uint64_t[sets*ways]; + memcpy(tags, rhs.tags, sets*ways*sizeof(uint64_t)); +} + +icsim_t::~icsim_t() +{ + delete [] tags; +} + +void icsim_t::print_stats() +{ + if(read_accesses + write_accesses == 0) + return; + + float mr = 100.0f*(read_misses+write_misses)/(read_accesses+write_accesses); + + std::cout << std::setprecision(3) << std::fixed; + std::cout << name << " "; + std::cout << "Bytes Read: " << bytes_read << std::endl; + std::cout << name << " "; + std::cout << "Bytes Written: " << bytes_written << std::endl; + std::cout << name << " "; + std::cout << "Read Accesses: " << read_accesses << std::endl; + std::cout << name << " "; + std::cout << "Write Accesses: " << write_accesses << std::endl; + std::cout << name << " "; + std::cout << "Read Misses: " << read_misses << std::endl; + std::cout << name << " "; + std::cout << "Write Misses: " << write_misses << std::endl; + std::cout << name << " "; + std::cout << "Writebacks: " << writebacks << std::endl; + std::cout << name << " "; + std::cout << "Miss Rate: " << mr << '%' << std::endl; + + float cr = read_accesses == 0 ? 0.0f : 100.0f*bytes_read/(4*read_accesses); + if(name == "I$") + { + std::cout << name << " "; + std::cout << "RVC compression ratio: " << cr << '%' << std::endl; + } +} + +void icsim_t::tick(uint64_t pc, int insnlen, bool store) +{ + store ? write_accesses++ : read_accesses++; + (store ? bytes_written : bytes_read) += insnlen; + + size_t idx = (pc >> idx_shift) & idx_mask; + size_t tag = (pc >> idx_shift) | VALID; + + for(size_t i = 0; i < ways; i++) + { + if(tag == (tags[idx + i*sets] & ~DIRTY)) // hit + { + if(store) + tags[idx + i*sets] |= DIRTY; + return; + } + } + + store ? write_misses++ : read_misses++; + + size_t way = lfsr.next() % ways; + if((tags[idx + way*sets] & (VALID | DIRTY)) == (VALID | DIRTY)) + writebacks++; + tags[idx + way*sets] = tag; +} diff --git a/riscv/icsim.h b/riscv/icsim.h new file mode 100644 index 0000000..ec6eae4 --- /dev/null +++ b/riscv/icsim.h @@ -0,0 +1,55 @@ +#ifndef _RISCV_ICSIM_H +#define _RISCV_ICSIM_H + +// this file models a simple cache to estimate hit/miss rates. +// it is currently unused. + +#include <cstring> +#include <string> +#include <stdint.h> + +class lfsr_t +{ +public: + lfsr_t() : reg(1) {} + lfsr_t(const lfsr_t& lfsr) : reg(lfsr.reg) {} + uint32_t next() { return reg = (reg>>1)^(-(reg&1) & 0xd0000001); } +private: + uint32_t reg; +}; + +class icsim_t +{ +public: + icsim_t(size_t sets, size_t ways, size_t linesz, const char* name); + icsim_t(const icsim_t& rhs); + ~icsim_t(); + + void tick(uint64_t pc, int insnlen, bool store); + void print_stats(); +private: + lfsr_t lfsr; + + size_t sets; + size_t ways; + size_t linesz; + size_t idx_shift; + size_t idx_mask; + + uint64_t* tags; + + uint64_t read_accesses; + uint64_t read_misses; + uint64_t bytes_read; + uint64_t write_accesses; + uint64_t write_misses; + uint64_t bytes_written; + uint64_t writebacks; + + std::string name; + + static const uint64_t VALID = 1ULL << 63; + static const uint64_t DIRTY = 1ULL << 62; +}; + +#endif diff --git a/riscv/insn_header.h b/riscv/insn_header.h new file mode 100644 index 0000000..9ea3586 --- /dev/null +++ b/riscv/insn_header.h @@ -0,0 +1,7 @@ +#include "processor.h" +#include "config.h" +#include "sim.h" +#include "softfloat.h" +#include "platform.h" // softfloat isNaNF32UI, etc. +#include "internals.h" // ditto +#include <assert.h> diff --git a/riscv/insns/add.h b/riscv/insns/add.h new file mode 100644 index 0000000..34d49ff --- /dev/null +++ b/riscv/insns/add.h @@ -0,0 +1 @@ +RD = sext_xprlen(RS1 + RS2); diff --git a/riscv/insns/addi.h b/riscv/insns/addi.h new file mode 100644 index 0000000..88881e5 --- /dev/null +++ b/riscv/insns/addi.h @@ -0,0 +1 @@ +RD = sext_xprlen(RS1 + SIMM); diff --git a/riscv/insns/addiw.h b/riscv/insns/addiw.h new file mode 100644 index 0000000..23ae278 --- /dev/null +++ b/riscv/insns/addiw.h @@ -0,0 +1,2 @@ +require_xpr64; +RD = sext32(SIMM + RS1); diff --git a/riscv/insns/addw.h b/riscv/insns/addw.h new file mode 100644 index 0000000..4e2ed56 --- /dev/null +++ b/riscv/insns/addw.h @@ -0,0 +1,2 @@ +require_xpr64; +RD = sext32(RS1 + RS2); diff --git a/riscv/insns/amoadd_d.h b/riscv/insns/amoadd_d.h new file mode 100644 index 0000000..b8450bf --- /dev/null +++ b/riscv/insns/amoadd_d.h @@ -0,0 +1,4 @@ +require_xpr64; +reg_t v = mmu.load_uint64(RS1); +mmu.store_uint64(RS1, RS2 + v); +RD = v; diff --git a/riscv/insns/amoadd_w.h b/riscv/insns/amoadd_w.h new file mode 100644 index 0000000..033b3c8 --- /dev/null +++ b/riscv/insns/amoadd_w.h @@ -0,0 +1,3 @@ +reg_t v = mmu.load_int32(RS1); +mmu.store_uint32(RS1, RS2 + v); +RD = v; diff --git a/riscv/insns/amoand_d.h b/riscv/insns/amoand_d.h new file mode 100644 index 0000000..586eb7f --- /dev/null +++ b/riscv/insns/amoand_d.h @@ -0,0 +1,4 @@ +require_xpr64; +reg_t v = mmu.load_uint64(RS1); +mmu.store_uint64(RS1, RS2 & v); +RD = v; diff --git a/riscv/insns/amoand_w.h b/riscv/insns/amoand_w.h new file mode 100644 index 0000000..18a9249 --- /dev/null +++ b/riscv/insns/amoand_w.h @@ -0,0 +1,3 @@ +reg_t v = mmu.load_int32(RS1); +mmu.store_uint32(RS1, RS2 & v); +RD = v; diff --git a/riscv/insns/amomax_d.h b/riscv/insns/amomax_d.h new file mode 100644 index 0000000..1a0bc8a --- /dev/null +++ b/riscv/insns/amomax_d.h @@ -0,0 +1,4 @@ +require_xpr64; +sreg_t v = mmu.load_int64(RS1); +mmu.store_uint64(RS1, std::max(sreg_t(RS2),v)); +RD = v; diff --git a/riscv/insns/amomax_w.h b/riscv/insns/amomax_w.h new file mode 100644 index 0000000..ff9c2da --- /dev/null +++ b/riscv/insns/amomax_w.h @@ -0,0 +1,3 @@ +int32_t v = mmu.load_int32(RS1); +mmu.store_uint32(RS1, std::max(int32_t(RS2),v)); +RD = v; diff --git a/riscv/insns/amomaxu_d.h b/riscv/insns/amomaxu_d.h new file mode 100644 index 0000000..ccfaf1d --- /dev/null +++ b/riscv/insns/amomaxu_d.h @@ -0,0 +1,4 @@ +require_xpr64; +reg_t v = mmu.load_uint64(RS1); +mmu.store_uint64(RS1, std::max(RS2,v)); +RD = v; diff --git a/riscv/insns/amomaxu_w.h b/riscv/insns/amomaxu_w.h new file mode 100644 index 0000000..075847d --- /dev/null +++ b/riscv/insns/amomaxu_w.h @@ -0,0 +1,3 @@ +uint32_t v = mmu.load_int32(RS1); +mmu.store_uint32(RS1, std::max(uint32_t(RS2),v)); +RD = (int32_t)v; diff --git a/riscv/insns/amomin_d.h b/riscv/insns/amomin_d.h new file mode 100644 index 0000000..4f3b6d6 --- /dev/null +++ b/riscv/insns/amomin_d.h @@ -0,0 +1,4 @@ +require_xpr64; +sreg_t v = mmu.load_int64(RS1); +mmu.store_uint64(RS1, std::min(sreg_t(RS2),v)); +RD = v; diff --git a/riscv/insns/amomin_w.h b/riscv/insns/amomin_w.h new file mode 100644 index 0000000..529ad50 --- /dev/null +++ b/riscv/insns/amomin_w.h @@ -0,0 +1,3 @@ +int32_t v = mmu.load_int32(RS1); +mmu.store_uint32(RS1, std::min(int32_t(RS2),v)); +RD = v; diff --git a/riscv/insns/amominu_d.h b/riscv/insns/amominu_d.h new file mode 100644 index 0000000..c09c51a --- /dev/null +++ b/riscv/insns/amominu_d.h @@ -0,0 +1,4 @@ +require_xpr64; +reg_t v = mmu.load_uint64(RS1); +mmu.store_uint64(RS1, std::min(RS2,v)); +RD = v; diff --git a/riscv/insns/amominu_w.h b/riscv/insns/amominu_w.h new file mode 100644 index 0000000..d8d6377 --- /dev/null +++ b/riscv/insns/amominu_w.h @@ -0,0 +1,3 @@ +uint32_t v = mmu.load_int32(RS1); +mmu.store_uint32(RS1, std::min(uint32_t(RS2),v)); +RD = (int32_t)v; diff --git a/riscv/insns/amoor_d.h b/riscv/insns/amoor_d.h new file mode 100644 index 0000000..76a4508 --- /dev/null +++ b/riscv/insns/amoor_d.h @@ -0,0 +1,4 @@ +require_xpr64; +reg_t v = mmu.load_uint64(RS1); +mmu.store_uint64(RS1, RS2 | v); +RD = v; diff --git a/riscv/insns/amoor_w.h b/riscv/insns/amoor_w.h new file mode 100644 index 0000000..741fbef --- /dev/null +++ b/riscv/insns/amoor_w.h @@ -0,0 +1,3 @@ +reg_t v = mmu.load_int32(RS1); +mmu.store_uint32(RS1, RS2 | v); +RD = v; diff --git a/riscv/insns/amoswap_d.h b/riscv/insns/amoswap_d.h new file mode 100644 index 0000000..43e3538 --- /dev/null +++ b/riscv/insns/amoswap_d.h @@ -0,0 +1,4 @@ +require_xpr64; +reg_t v = mmu.load_uint64(RS1); +mmu.store_uint64(RS1, RS2); +RD = v; diff --git a/riscv/insns/amoswap_w.h b/riscv/insns/amoswap_w.h new file mode 100644 index 0000000..30e6102 --- /dev/null +++ b/riscv/insns/amoswap_w.h @@ -0,0 +1,3 @@ +reg_t v = mmu.load_int32(RS1); +mmu.store_uint32(RS1, RS2); +RD = v; diff --git a/riscv/insns/and.h b/riscv/insns/and.h new file mode 100644 index 0000000..88ac1d8 --- /dev/null +++ b/riscv/insns/and.h @@ -0,0 +1 @@ +RD = RS1 & RS2; diff --git a/riscv/insns/andi.h b/riscv/insns/andi.h new file mode 100644 index 0000000..5caea16 --- /dev/null +++ b/riscv/insns/andi.h @@ -0,0 +1 @@ +RD = SIMM & RS1; diff --git a/riscv/insns/beq.h b/riscv/insns/beq.h new file mode 100644 index 0000000..7b26488 --- /dev/null +++ b/riscv/insns/beq.h @@ -0,0 +1,2 @@ +if(cmp_trunc(RS1) == cmp_trunc(RS2)) + set_pc(BRANCH_TARGET); diff --git a/riscv/insns/bge.h b/riscv/insns/bge.h new file mode 100644 index 0000000..dca544b --- /dev/null +++ b/riscv/insns/bge.h @@ -0,0 +1,2 @@ +if(sreg_t(cmp_trunc(RS1)) >= sreg_t(cmp_trunc(RS2))) + set_pc(BRANCH_TARGET); diff --git a/riscv/insns/bgeu.h b/riscv/insns/bgeu.h new file mode 100644 index 0000000..6325466 --- /dev/null +++ b/riscv/insns/bgeu.h @@ -0,0 +1,2 @@ +if(cmp_trunc(RS1) >= cmp_trunc(RS2)) + set_pc(BRANCH_TARGET); diff --git a/riscv/insns/blt.h b/riscv/insns/blt.h new file mode 100644 index 0000000..d84fd7a --- /dev/null +++ b/riscv/insns/blt.h @@ -0,0 +1,2 @@ +if(sreg_t(cmp_trunc(RS1)) < sreg_t(cmp_trunc(RS2))) + set_pc(BRANCH_TARGET); diff --git a/riscv/insns/bltu.h b/riscv/insns/bltu.h new file mode 100644 index 0000000..250fd4f --- /dev/null +++ b/riscv/insns/bltu.h @@ -0,0 +1,2 @@ +if(cmp_trunc(RS1) < cmp_trunc(RS2)) + set_pc(BRANCH_TARGET); diff --git a/riscv/insns/bne.h b/riscv/insns/bne.h new file mode 100644 index 0000000..f775721 --- /dev/null +++ b/riscv/insns/bne.h @@ -0,0 +1,2 @@ +if(cmp_trunc(RS1) != cmp_trunc(RS2)) + set_pc(BRANCH_TARGET); diff --git a/riscv/insns/break.h b/riscv/insns/break.h new file mode 100644 index 0000000..7fd3d66 --- /dev/null +++ b/riscv/insns/break.h @@ -0,0 +1 @@ +throw trap_breakpoint; diff --git a/riscv/insns/c_add.h b/riscv/insns/c_add.h new file mode 100644 index 0000000..2170d69 --- /dev/null +++ b/riscv/insns/c_add.h @@ -0,0 +1,2 @@ +require_rvc; +CRD = CRS1 + CRS2; diff --git a/riscv/insns/c_add3.h b/riscv/insns/c_add3.h new file mode 100644 index 0000000..914c85d --- /dev/null +++ b/riscv/insns/c_add3.h @@ -0,0 +1,2 @@ +require_rvc; +CRDS = CRS1S + CRS2BS; diff --git a/riscv/insns/c_addi.h b/riscv/insns/c_addi.h new file mode 100644 index 0000000..448e31a --- /dev/null +++ b/riscv/insns/c_addi.h @@ -0,0 +1,10 @@ +require_rvc; +if(CRD_REGNUM == 0) +{ + reg_t temp = CRS1; + if(CIMM6 & 0x20) + RA = npc; + set_pc(temp); +} +else + CRD = sext_xprlen(CRS2 + CIMM6); diff --git a/riscv/insns/c_addiw.h b/riscv/insns/c_addiw.h new file mode 100644 index 0000000..6a1e0a3 --- /dev/null +++ b/riscv/insns/c_addiw.h @@ -0,0 +1,3 @@ +require_rvc; +require_xpr64; +CRD = sext32(CRS2 + CIMM6); diff --git a/riscv/insns/c_and3.h b/riscv/insns/c_and3.h new file mode 100644 index 0000000..b506d6a --- /dev/null +++ b/riscv/insns/c_and3.h @@ -0,0 +1,2 @@ +require_rvc; +CRDS = CRS1S & CRS2BS; diff --git a/riscv/insns/c_beq.h b/riscv/insns/c_beq.h new file mode 100644 index 0000000..031d96d --- /dev/null +++ b/riscv/insns/c_beq.h @@ -0,0 +1,3 @@ +require_rvc; +if(cmp_trunc(CRS1S) == cmp_trunc(CRS2S)) + set_pc(CBRANCH_TARGET); diff --git a/riscv/insns/c_bne.h b/riscv/insns/c_bne.h new file mode 100644 index 0000000..caf9229 --- /dev/null +++ b/riscv/insns/c_bne.h @@ -0,0 +1,3 @@ +require_rvc; +if(cmp_trunc(CRS1S) != cmp_trunc(CRS2S)) + set_pc(CBRANCH_TARGET); diff --git a/riscv/insns/c_fld.h b/riscv/insns/c_fld.h new file mode 100644 index 0000000..a726039 --- /dev/null +++ b/riscv/insns/c_fld.h @@ -0,0 +1,3 @@ +require_rvc; +require_fp; +FCRDS = mmu.load_int64(CRS1S+CIMM5*8); diff --git a/riscv/insns/c_flw.h b/riscv/insns/c_flw.h new file mode 100644 index 0000000..cdb7221 --- /dev/null +++ b/riscv/insns/c_flw.h @@ -0,0 +1,3 @@ +require_rvc; +require_fp; +FCRDS = mmu.load_int32(CRS1S+CIMM5*4); diff --git a/riscv/insns/c_fsd.h b/riscv/insns/c_fsd.h new file mode 100644 index 0000000..20814fd --- /dev/null +++ b/riscv/insns/c_fsd.h @@ -0,0 +1,3 @@ +require_rvc; +require_fp; +mmu.store_uint64(CRS1S+CIMM5*8, FCRS2S); diff --git a/riscv/insns/c_fsw.h b/riscv/insns/c_fsw.h new file mode 100644 index 0000000..1d21629 --- /dev/null +++ b/riscv/insns/c_fsw.h @@ -0,0 +1,3 @@ +require_rvc; +require_fp; +mmu.store_uint32(CRS1S+CIMM5*4, FCRS2S); diff --git a/riscv/insns/c_j.h b/riscv/insns/c_j.h new file mode 100644 index 0000000..5ba9c73 --- /dev/null +++ b/riscv/insns/c_j.h @@ -0,0 +1,2 @@ +require_rvc; +set_pc(CJUMP_TARGET); diff --git a/riscv/insns/c_ld.h b/riscv/insns/c_ld.h new file mode 100644 index 0000000..f9c07af --- /dev/null +++ b/riscv/insns/c_ld.h @@ -0,0 +1,3 @@ +require_rvc; +require_xpr64; +CRDS = mmu.load_int64(CRS1S+CIMM5*8); diff --git a/riscv/insns/c_ld0.h b/riscv/insns/c_ld0.h new file mode 100644 index 0000000..f51a966 --- /dev/null +++ b/riscv/insns/c_ld0.h @@ -0,0 +1,3 @@ +require_rvc; +require_xpr64; +CRD = mmu.load_int64(CRS1); diff --git a/riscv/insns/c_ldsp.h b/riscv/insns/c_ldsp.h new file mode 100644 index 0000000..1fbd9bd --- /dev/null +++ b/riscv/insns/c_ldsp.h @@ -0,0 +1,3 @@ +require_rvc; +require_xpr64; +CRD = mmu.load_int64(XPR[30]+CIMM6*8); diff --git a/riscv/insns/c_li.h b/riscv/insns/c_li.h new file mode 100644 index 0000000..e65614e --- /dev/null +++ b/riscv/insns/c_li.h @@ -0,0 +1,2 @@ +require_rvc; +CRD = CIMM6; diff --git a/riscv/insns/c_lw.h b/riscv/insns/c_lw.h new file mode 100644 index 0000000..4796ab8 --- /dev/null +++ b/riscv/insns/c_lw.h @@ -0,0 +1,2 @@ +require_rvc; +CRDS = mmu.load_int32(CRS1S+CIMM5*4); diff --git a/riscv/insns/c_lw0.h b/riscv/insns/c_lw0.h new file mode 100644 index 0000000..d263a80 --- /dev/null +++ b/riscv/insns/c_lw0.h @@ -0,0 +1,2 @@ +require_rvc; +CRD = mmu.load_int32(CRS1); diff --git a/riscv/insns/c_lwsp.h b/riscv/insns/c_lwsp.h new file mode 100644 index 0000000..318342a --- /dev/null +++ b/riscv/insns/c_lwsp.h @@ -0,0 +1,2 @@ +require_rvc; +CRD = mmu.load_int32(XPR[30]+CIMM6*4); diff --git a/riscv/insns/c_move.h b/riscv/insns/c_move.h new file mode 100644 index 0000000..b0aef33 --- /dev/null +++ b/riscv/insns/c_move.h @@ -0,0 +1,2 @@ +require_rvc; +CRD = CRS1; diff --git a/riscv/insns/c_or3.h b/riscv/insns/c_or3.h new file mode 100644 index 0000000..143e2ae --- /dev/null +++ b/riscv/insns/c_or3.h @@ -0,0 +1,2 @@ +require_rvc; +CRDS = CRS1S | CRS2BS; diff --git a/riscv/insns/c_sd.h b/riscv/insns/c_sd.h new file mode 100644 index 0000000..b2eb456 --- /dev/null +++ b/riscv/insns/c_sd.h @@ -0,0 +1,3 @@ +require_rvc; +require_xpr64; +mmu.store_uint64(CRS1S+CIMM5*8, CRS2S); diff --git a/riscv/insns/c_sdsp.h b/riscv/insns/c_sdsp.h new file mode 100644 index 0000000..ca97d51 --- /dev/null +++ b/riscv/insns/c_sdsp.h @@ -0,0 +1,3 @@ +require_rvc; +require_xpr64; +mmu.store_uint64(XPR[30]+CIMM6*8, CRS2); diff --git a/riscv/insns/c_slli.h b/riscv/insns/c_slli.h new file mode 100644 index 0000000..5026767 --- /dev/null +++ b/riscv/insns/c_slli.h @@ -0,0 +1,5 @@ +require_rvc; +if(xpr64) + CRDS = CRDS << CIMM5U; +else + CRDS = sext32(CRDS << CIMM5U); diff --git a/riscv/insns/c_slli32.h b/riscv/insns/c_slli32.h new file mode 100644 index 0000000..1e3e958 --- /dev/null +++ b/riscv/insns/c_slli32.h @@ -0,0 +1,3 @@ +require_rvc; +require_xpr64; +CRDS = CRDS << (32+CIMM5U); diff --git a/riscv/insns/c_slliw.h b/riscv/insns/c_slliw.h new file mode 100644 index 0000000..9e428f5 --- /dev/null +++ b/riscv/insns/c_slliw.h @@ -0,0 +1,3 @@ +require_rvc; +require_xpr64; +CRDS = sext32(CRDS << CIMM5U); diff --git a/riscv/insns/c_srai.h b/riscv/insns/c_srai.h new file mode 100644 index 0000000..aa33424 --- /dev/null +++ b/riscv/insns/c_srai.h @@ -0,0 +1,5 @@ +require_rvc; +if(xpr64) + CRDS = sreg_t(CRDS) >> CIMM5U; +else + CRDS = sext32(int32_t(CRDS) >> CIMM5U); diff --git a/riscv/insns/c_srai32.h b/riscv/insns/c_srai32.h new file mode 100644 index 0000000..ca7b024 --- /dev/null +++ b/riscv/insns/c_srai32.h @@ -0,0 +1,3 @@ +require_rvc; +require_xpr64; +CRDS = sreg_t(CRDS) >> (32+CIMM5U); diff --git a/riscv/insns/c_srli.h b/riscv/insns/c_srli.h new file mode 100644 index 0000000..56e0681 --- /dev/null +++ b/riscv/insns/c_srli.h @@ -0,0 +1,5 @@ +require_rvc; +if(xpr64) + CRDS = CRDS >> CIMM5U; +else + CRDS = sext32(uint32_t(CRDS) >> CIMM5U); diff --git a/riscv/insns/c_srli32.h b/riscv/insns/c_srli32.h new file mode 100644 index 0000000..4f5b8ea --- /dev/null +++ b/riscv/insns/c_srli32.h @@ -0,0 +1,3 @@ +require_rvc; +require_xpr64; +CRDS = CRDS >> (32+CIMM5U); diff --git a/riscv/insns/c_sub.h b/riscv/insns/c_sub.h new file mode 100644 index 0000000..9fd8932 --- /dev/null +++ b/riscv/insns/c_sub.h @@ -0,0 +1,2 @@ +require_rvc; +CRD = CRS1 - CRS2; diff --git a/riscv/insns/c_sub3.h b/riscv/insns/c_sub3.h new file mode 100644 index 0000000..53afc84 --- /dev/null +++ b/riscv/insns/c_sub3.h @@ -0,0 +1,2 @@ +require_rvc; +CRDS = CRS1S - CRS2BS; diff --git a/riscv/insns/c_sw.h b/riscv/insns/c_sw.h new file mode 100644 index 0000000..f604adf --- /dev/null +++ b/riscv/insns/c_sw.h @@ -0,0 +1,2 @@ +require_rvc; +mmu.store_uint32(CRS1S+CIMM5*4, CRS2S); diff --git a/riscv/insns/c_swsp.h b/riscv/insns/c_swsp.h new file mode 100644 index 0000000..0508f12 --- /dev/null +++ b/riscv/insns/c_swsp.h @@ -0,0 +1,2 @@ +require_rvc; +mmu.store_uint32(XPR[30]+CIMM6*4, CRS2); diff --git a/riscv/insns/cflush.h b/riscv/insns/cflush.h new file mode 100644 index 0000000..5117ca0 --- /dev/null +++ b/riscv/insns/cflush.h @@ -0,0 +1 @@ +require_supervisor; diff --git a/riscv/insns/di.h b/riscv/insns/di.h new file mode 100644 index 0000000..31280d5 --- /dev/null +++ b/riscv/insns/di.h @@ -0,0 +1,4 @@ +require_supervisor; +uint32_t temp = sr; +set_sr(sr & ~SR_ET); +RD = temp; diff --git a/riscv/insns/div.h b/riscv/insns/div.h new file mode 100644 index 0000000..82a4066 --- /dev/null +++ b/riscv/insns/div.h @@ -0,0 +1,6 @@ +if(RS2 == 0) + RD = UINT64_MAX; +else if(sreg_t(RS1) == INT64_MIN && sreg_t(RS2) == -1) + RD = RS1; +else + RD = sext_xprlen(sext_xprlen(RS1) / sext_xprlen(RS2)); diff --git a/riscv/insns/divu.h b/riscv/insns/divu.h new file mode 100644 index 0000000..681afd2 --- /dev/null +++ b/riscv/insns/divu.h @@ -0,0 +1,4 @@ +if(RS2 == 0) + RD = UINT64_MAX; +else + RD = sext_xprlen(zext_xprlen(RS1) / zext_xprlen(RS2)); diff --git a/riscv/insns/divuw.h b/riscv/insns/divuw.h new file mode 100644 index 0000000..0ceb040 --- /dev/null +++ b/riscv/insns/divuw.h @@ -0,0 +1,5 @@ +require_xpr64; +if(RS2 == 0) + RD = UINT64_MAX; +else + RD = sext32(zext32(RS1) / zext32(RS2)); diff --git a/riscv/insns/divw.h b/riscv/insns/divw.h new file mode 100644 index 0000000..51c3d80 --- /dev/null +++ b/riscv/insns/divw.h @@ -0,0 +1,7 @@ +require_xpr64; +if(RS2 == 0) + RD = UINT64_MAX; +else if(int32_t(RS1) == INT32_MIN && int32_t(RS2) == -1) + RD = RS1; +else + RD = sext32(int32_t(RS1) / int32_t(RS2)); diff --git a/riscv/insns/ei.h b/riscv/insns/ei.h new file mode 100644 index 0000000..8306aeb --- /dev/null +++ b/riscv/insns/ei.h @@ -0,0 +1,4 @@ +require_supervisor; +uint32_t temp = sr; +set_sr(sr | SR_ET); +RD = temp; diff --git a/riscv/insns/eret.h b/riscv/insns/eret.h new file mode 100644 index 0000000..46d5bed --- /dev/null +++ b/riscv/insns/eret.h @@ -0,0 +1,5 @@ +require_supervisor; +if(sr & SR_ET) + throw trap_illegal_instruction; +set_sr(((sr & SR_PS) ? sr : (sr & ~SR_S)) | SR_ET); +set_pc(epc); diff --git a/riscv/insns/fadd_d.h b/riscv/insns/fadd_d.h new file mode 100644 index 0000000..48c76a7 --- /dev/null +++ b/riscv/insns/fadd_d.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = f64_add(FRS1, FRS2); +set_fp_exceptions; diff --git a/riscv/insns/fadd_s.h b/riscv/insns/fadd_s.h new file mode 100644 index 0000000..2fd5429 --- /dev/null +++ b/riscv/insns/fadd_s.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = f32_add(FRS1, FRS2); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_d_l.h b/riscv/insns/fcvt_d_l.h new file mode 100644 index 0000000..68c0482 --- /dev/null +++ b/riscv/insns/fcvt_d_l.h @@ -0,0 +1,5 @@ +require_xpr64; +require_fp; +softfloat_roundingMode = RM; +FRD = i64_to_f64(RS1); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_d_lu.h b/riscv/insns/fcvt_d_lu.h new file mode 100644 index 0000000..2032758 --- /dev/null +++ b/riscv/insns/fcvt_d_lu.h @@ -0,0 +1,5 @@ +require_xpr64; +require_fp; +softfloat_roundingMode = RM; +FRD = ui64_to_f64(RS1); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_d_s.h b/riscv/insns/fcvt_d_s.h new file mode 100644 index 0000000..6b1a09c --- /dev/null +++ b/riscv/insns/fcvt_d_s.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = f32_to_f64(FRS1); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_d_w.h b/riscv/insns/fcvt_d_w.h new file mode 100644 index 0000000..52abd75 --- /dev/null +++ b/riscv/insns/fcvt_d_w.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = i32_to_f64((int32_t)RS1); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_d_wu.h b/riscv/insns/fcvt_d_wu.h new file mode 100644 index 0000000..61a8a78 --- /dev/null +++ b/riscv/insns/fcvt_d_wu.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = ui32_to_f64((uint32_t)RS1); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_l_d.h b/riscv/insns/fcvt_l_d.h new file mode 100644 index 0000000..206ba4f --- /dev/null +++ b/riscv/insns/fcvt_l_d.h @@ -0,0 +1,5 @@ +require_xpr64; +require_fp; +softfloat_roundingMode = RM; +RD = f64_to_i64(FRS1, RM, true); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_l_s.h b/riscv/insns/fcvt_l_s.h new file mode 100644 index 0000000..e05f476 --- /dev/null +++ b/riscv/insns/fcvt_l_s.h @@ -0,0 +1,5 @@ +require_xpr64; +require_fp; +softfloat_roundingMode = RM; +RD = f32_to_i64(FRS1, RM, true); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_lu_d.h b/riscv/insns/fcvt_lu_d.h new file mode 100644 index 0000000..44c3dd6 --- /dev/null +++ b/riscv/insns/fcvt_lu_d.h @@ -0,0 +1,5 @@ +require_xpr64; +require_fp; +softfloat_roundingMode = RM; +RD = f64_to_ui64(FRS1, RM, true); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_lu_s.h b/riscv/insns/fcvt_lu_s.h new file mode 100644 index 0000000..13de436 --- /dev/null +++ b/riscv/insns/fcvt_lu_s.h @@ -0,0 +1,5 @@ +require_xpr64; +require_fp; +softfloat_roundingMode = RM; +RD = f32_to_ui64(FRS1, RM, true); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_s_d.h b/riscv/insns/fcvt_s_d.h new file mode 100644 index 0000000..e5289c4 --- /dev/null +++ b/riscv/insns/fcvt_s_d.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = f64_to_f32(FRS1); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_s_l.h b/riscv/insns/fcvt_s_l.h new file mode 100644 index 0000000..f149229 --- /dev/null +++ b/riscv/insns/fcvt_s_l.h @@ -0,0 +1,5 @@ +require_xpr64; +require_fp; +softfloat_roundingMode = RM; +FRD = i64_to_f32(RS1); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_s_lu.h b/riscv/insns/fcvt_s_lu.h new file mode 100644 index 0000000..d9d0946 --- /dev/null +++ b/riscv/insns/fcvt_s_lu.h @@ -0,0 +1,5 @@ +require_xpr64; +require_fp; +softfloat_roundingMode = RM; +FRD = ui64_to_f32(RS1); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_s_w.h b/riscv/insns/fcvt_s_w.h new file mode 100644 index 0000000..dedebb5 --- /dev/null +++ b/riscv/insns/fcvt_s_w.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = i32_to_f32((int32_t)RS1); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_s_wu.h b/riscv/insns/fcvt_s_wu.h new file mode 100644 index 0000000..abb782c --- /dev/null +++ b/riscv/insns/fcvt_s_wu.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = ui32_to_f32((uint32_t)RS1); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_w_d.h b/riscv/insns/fcvt_w_d.h new file mode 100644 index 0000000..88dc3d3 --- /dev/null +++ b/riscv/insns/fcvt_w_d.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +RD = sext32(f64_to_i32(FRS1, RM, true)); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_w_s.h b/riscv/insns/fcvt_w_s.h new file mode 100644 index 0000000..f14cc19 --- /dev/null +++ b/riscv/insns/fcvt_w_s.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +RD = sext32(f32_to_i32(FRS1, RM, true)); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_wu_d.h b/riscv/insns/fcvt_wu_d.h new file mode 100644 index 0000000..43ad6f6 --- /dev/null +++ b/riscv/insns/fcvt_wu_d.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +RD = sext32(f64_to_ui32(FRS1, RM, true)); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_wu_s.h b/riscv/insns/fcvt_wu_s.h new file mode 100644 index 0000000..ff7a11c --- /dev/null +++ b/riscv/insns/fcvt_wu_s.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +RD = sext32(f32_to_ui32(FRS1, RM, true)); +set_fp_exceptions; diff --git a/riscv/insns/fdiv_d.h b/riscv/insns/fdiv_d.h new file mode 100644 index 0000000..aa00c98 --- /dev/null +++ b/riscv/insns/fdiv_d.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = f64_div(FRS1, FRS2); +set_fp_exceptions; diff --git a/riscv/insns/fdiv_s.h b/riscv/insns/fdiv_s.h new file mode 100644 index 0000000..8c76587 --- /dev/null +++ b/riscv/insns/fdiv_s.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = f32_div(FRS1, FRS2); +set_fp_exceptions; diff --git a/riscv/insns/fence.h b/riscv/insns/fence.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/fence.h diff --git a/riscv/insns/fence_g_cv.h b/riscv/insns/fence_g_cv.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/fence_g_cv.h diff --git a/riscv/insns/fence_g_v.h b/riscv/insns/fence_g_v.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/fence_g_v.h diff --git a/riscv/insns/fence_i.h b/riscv/insns/fence_i.h new file mode 100644 index 0000000..a2dbffe --- /dev/null +++ b/riscv/insns/fence_i.h @@ -0,0 +1 @@ +mmu.flush_icache(); diff --git a/riscv/insns/fence_l_cv.h b/riscv/insns/fence_l_cv.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/fence_l_cv.h diff --git a/riscv/insns/fence_l_v.h b/riscv/insns/fence_l_v.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/fence_l_v.h diff --git a/riscv/insns/feq_d.h b/riscv/insns/feq_d.h new file mode 100644 index 0000000..9db8760 --- /dev/null +++ b/riscv/insns/feq_d.h @@ -0,0 +1,3 @@ +require_fp; +RD = f64_eq(FRS1, FRS2); +set_fp_exceptions; diff --git a/riscv/insns/feq_s.h b/riscv/insns/feq_s.h new file mode 100644 index 0000000..658e8f6 --- /dev/null +++ b/riscv/insns/feq_s.h @@ -0,0 +1,3 @@ +require_fp; +RD = f32_eq(FRS1, FRS2); +set_fp_exceptions; diff --git a/riscv/insns/fld.h b/riscv/insns/fld.h new file mode 100644 index 0000000..123dea4 --- /dev/null +++ b/riscv/insns/fld.h @@ -0,0 +1,2 @@ +require_fp; +FRD = mmu.load_int64(RS1+SIMM); diff --git a/riscv/insns/fle_d.h b/riscv/insns/fle_d.h new file mode 100644 index 0000000..da76187 --- /dev/null +++ b/riscv/insns/fle_d.h @@ -0,0 +1,3 @@ +require_fp; +RD = f64_le(FRS1, FRS2); +set_fp_exceptions; diff --git a/riscv/insns/fle_s.h b/riscv/insns/fle_s.h new file mode 100644 index 0000000..9c83a17 --- /dev/null +++ b/riscv/insns/fle_s.h @@ -0,0 +1,3 @@ +require_fp; +RD = f32_le(FRS1, FRS2); +set_fp_exceptions; diff --git a/riscv/insns/flt_d.h b/riscv/insns/flt_d.h new file mode 100644 index 0000000..01d135a --- /dev/null +++ b/riscv/insns/flt_d.h @@ -0,0 +1,3 @@ +require_fp; +RD = f64_lt(FRS1, FRS2); +set_fp_exceptions; diff --git a/riscv/insns/flt_s.h b/riscv/insns/flt_s.h new file mode 100644 index 0000000..52eee5d --- /dev/null +++ b/riscv/insns/flt_s.h @@ -0,0 +1,3 @@ +require_fp; +RD = f32_lt(FRS1, FRS2); +set_fp_exceptions; diff --git a/riscv/insns/flw.h b/riscv/insns/flw.h new file mode 100644 index 0000000..335fd7d --- /dev/null +++ b/riscv/insns/flw.h @@ -0,0 +1,2 @@ +require_fp; +FRD = mmu.load_int32(RS1+SIMM); diff --git a/riscv/insns/fmadd_d.h b/riscv/insns/fmadd_d.h new file mode 100644 index 0000000..f67853e --- /dev/null +++ b/riscv/insns/fmadd_d.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = f64_mulAdd(FRS1, FRS2, FRS3); +set_fp_exceptions; diff --git a/riscv/insns/fmadd_s.h b/riscv/insns/fmadd_s.h new file mode 100644 index 0000000..19db642 --- /dev/null +++ b/riscv/insns/fmadd_s.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = f32_mulAdd(FRS1, FRS2, FRS3); +set_fp_exceptions; diff --git a/riscv/insns/fmax_d.h b/riscv/insns/fmax_d.h new file mode 100644 index 0000000..cbbb343 --- /dev/null +++ b/riscv/insns/fmax_d.h @@ -0,0 +1,4 @@ +require_fp; +FRD = isNaNF64UI(FRS2) || f64_le_quiet(FRS2,FRS1) /* && FRS1 not NaN */ + ? FRS1 : FRS2; +set_fp_exceptions; diff --git a/riscv/insns/fmax_s.h b/riscv/insns/fmax_s.h new file mode 100644 index 0000000..8df665f --- /dev/null +++ b/riscv/insns/fmax_s.h @@ -0,0 +1,4 @@ +require_fp; +FRD = isNaNF32UI(FRS2) || f32_le_quiet(FRS2,FRS1) /* && FRS1 not NaN */ + ? FRS1 : FRS2; +set_fp_exceptions; diff --git a/riscv/insns/fmin_d.h b/riscv/insns/fmin_d.h new file mode 100644 index 0000000..3d3d454 --- /dev/null +++ b/riscv/insns/fmin_d.h @@ -0,0 +1,4 @@ +require_fp; +FRD = isNaNF64UI(FRS2) || f64_lt_quiet(FRS1,FRS2) /* && FRS1 not NaN */ + ? FRS1 : FRS2; +set_fp_exceptions; diff --git a/riscv/insns/fmin_s.h b/riscv/insns/fmin_s.h new file mode 100644 index 0000000..994c860 --- /dev/null +++ b/riscv/insns/fmin_s.h @@ -0,0 +1,4 @@ +require_fp; +FRD = isNaNF32UI(FRS2) || f32_lt_quiet(FRS1,FRS2) /* && FRS1 not NaN */ + ? FRS1 : FRS2; +set_fp_exceptions; diff --git a/riscv/insns/fmovn.h b/riscv/insns/fmovn.h new file mode 100644 index 0000000..394b56c --- /dev/null +++ b/riscv/insns/fmovn.h @@ -0,0 +1,2 @@ +require_vector; +if (RS1 & 0x1) FRD = FRS2; diff --git a/riscv/insns/fmovz.h b/riscv/insns/fmovz.h new file mode 100644 index 0000000..7862216 --- /dev/null +++ b/riscv/insns/fmovz.h @@ -0,0 +1,2 @@ +require_vector; +if (~RS1 & 0x1) FRD = FRS2; diff --git a/riscv/insns/fmsub_d.h b/riscv/insns/fmsub_d.h new file mode 100644 index 0000000..b1e9340 --- /dev/null +++ b/riscv/insns/fmsub_d.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = f64_mulAdd(FRS1, FRS2, FRS3 ^ (uint64_t)INT64_MIN); +set_fp_exceptions; diff --git a/riscv/insns/fmsub_s.h b/riscv/insns/fmsub_s.h new file mode 100644 index 0000000..d3349f5 --- /dev/null +++ b/riscv/insns/fmsub_s.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = f32_mulAdd(FRS1, FRS2, FRS3 ^ (uint32_t)INT32_MIN); +set_fp_exceptions; diff --git a/riscv/insns/fmul_d.h b/riscv/insns/fmul_d.h new file mode 100644 index 0000000..a8adedd --- /dev/null +++ b/riscv/insns/fmul_d.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = f64_mul(FRS1, FRS2); +set_fp_exceptions; diff --git a/riscv/insns/fmul_s.h b/riscv/insns/fmul_s.h new file mode 100644 index 0000000..6475578 --- /dev/null +++ b/riscv/insns/fmul_s.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = f32_mul(FRS1, FRS2); +set_fp_exceptions; diff --git a/riscv/insns/fnmadd_d.h b/riscv/insns/fnmadd_d.h new file mode 100644 index 0000000..1e2ee27 --- /dev/null +++ b/riscv/insns/fnmadd_d.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = f64_mulAdd(FRS1, FRS2, FRS3) ^ (uint64_t)INT64_MIN; +set_fp_exceptions; diff --git a/riscv/insns/fnmadd_s.h b/riscv/insns/fnmadd_s.h new file mode 100644 index 0000000..78abb78 --- /dev/null +++ b/riscv/insns/fnmadd_s.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = f32_mulAdd(FRS1, FRS2, FRS3) ^ (uint32_t)INT32_MIN; +set_fp_exceptions; diff --git a/riscv/insns/fnmsub_d.h b/riscv/insns/fnmsub_d.h new file mode 100644 index 0000000..ae643a5 --- /dev/null +++ b/riscv/insns/fnmsub_d.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = f64_mulAdd(FRS1, FRS2, FRS3 ^ (uint64_t)INT64_MIN) ^ (uint64_t)INT64_MIN; +set_fp_exceptions; diff --git a/riscv/insns/fnmsub_s.h b/riscv/insns/fnmsub_s.h new file mode 100644 index 0000000..cbb70ba --- /dev/null +++ b/riscv/insns/fnmsub_s.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = f32_mulAdd(FRS1, FRS2, FRS3 ^ (uint32_t)INT32_MIN) ^ (uint32_t)INT32_MIN; +set_fp_exceptions; diff --git a/riscv/insns/fsd.h b/riscv/insns/fsd.h new file mode 100644 index 0000000..113398e --- /dev/null +++ b/riscv/insns/fsd.h @@ -0,0 +1,2 @@ +require_fp; +mmu.store_uint64(RS1+BIMM, FRS2); diff --git a/riscv/insns/fsgnj_d.h b/riscv/insns/fsgnj_d.h new file mode 100644 index 0000000..f66e804 --- /dev/null +++ b/riscv/insns/fsgnj_d.h @@ -0,0 +1,2 @@ +require_fp; +FRD = (FRS1 &~ INT64_MIN) | (FRS2 & INT64_MIN); diff --git a/riscv/insns/fsgnj_s.h b/riscv/insns/fsgnj_s.h new file mode 100644 index 0000000..35609ac --- /dev/null +++ b/riscv/insns/fsgnj_s.h @@ -0,0 +1,2 @@ +require_fp; +FRD = (FRS1 &~ (uint32_t)INT32_MIN) | (FRS2 & (uint32_t)INT32_MIN); diff --git a/riscv/insns/fsgnjn_d.h b/riscv/insns/fsgnjn_d.h new file mode 100644 index 0000000..22de215 --- /dev/null +++ b/riscv/insns/fsgnjn_d.h @@ -0,0 +1,2 @@ +require_fp; +FRD = (FRS1 &~ INT64_MIN) | ((~FRS2) & INT64_MIN); diff --git a/riscv/insns/fsgnjn_s.h b/riscv/insns/fsgnjn_s.h new file mode 100644 index 0000000..dd66d71 --- /dev/null +++ b/riscv/insns/fsgnjn_s.h @@ -0,0 +1,2 @@ +require_fp; +FRD = (FRS1 &~ (uint32_t)INT32_MIN) | ((~FRS2) & (uint32_t)INT32_MIN); diff --git a/riscv/insns/fsgnjx_d.h b/riscv/insns/fsgnjx_d.h new file mode 100644 index 0000000..331b6e4 --- /dev/null +++ b/riscv/insns/fsgnjx_d.h @@ -0,0 +1,2 @@ +require_fp; +FRD = FRS1 ^ (FRS2 & INT64_MIN); diff --git a/riscv/insns/fsgnjx_s.h b/riscv/insns/fsgnjx_s.h new file mode 100644 index 0000000..b455406 --- /dev/null +++ b/riscv/insns/fsgnjx_s.h @@ -0,0 +1,2 @@ +require_fp; +FRD = FRS1 ^ (FRS2 & (uint32_t)INT32_MIN); diff --git a/riscv/insns/fsqrt_d.h b/riscv/insns/fsqrt_d.h new file mode 100644 index 0000000..7647c9c --- /dev/null +++ b/riscv/insns/fsqrt_d.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = f64_sqrt(FRS1); +set_fp_exceptions; diff --git a/riscv/insns/fsqrt_s.h b/riscv/insns/fsqrt_s.h new file mode 100644 index 0000000..426f241 --- /dev/null +++ b/riscv/insns/fsqrt_s.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = f32_sqrt(FRS1); +set_fp_exceptions; diff --git a/riscv/insns/fsub_d.h b/riscv/insns/fsub_d.h new file mode 100644 index 0000000..e25eebb --- /dev/null +++ b/riscv/insns/fsub_d.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = f64_sub(FRS1, FRS2); +set_fp_exceptions; diff --git a/riscv/insns/fsub_s.h b/riscv/insns/fsub_s.h new file mode 100644 index 0000000..6c64d04 --- /dev/null +++ b/riscv/insns/fsub_s.h @@ -0,0 +1,4 @@ +require_fp; +softfloat_roundingMode = RM; +FRD = f32_sub(FRS1, FRS2); +set_fp_exceptions; diff --git a/riscv/insns/fsw.h b/riscv/insns/fsw.h new file mode 100644 index 0000000..23d3333 --- /dev/null +++ b/riscv/insns/fsw.h @@ -0,0 +1,2 @@ +require_fp; +mmu.store_uint32(RS1+BIMM, FRS2); diff --git a/riscv/insns/j.h b/riscv/insns/j.h new file mode 100644 index 0000000..3a4da2a --- /dev/null +++ b/riscv/insns/j.h @@ -0,0 +1 @@ +set_pc(JUMP_TARGET); diff --git a/riscv/insns/jal.h b/riscv/insns/jal.h new file mode 100644 index 0000000..41dc403 --- /dev/null +++ b/riscv/insns/jal.h @@ -0,0 +1,2 @@ +RA = npc; +set_pc(JUMP_TARGET); diff --git a/riscv/insns/jalr_c.h b/riscv/insns/jalr_c.h new file mode 100644 index 0000000..91be911 --- /dev/null +++ b/riscv/insns/jalr_c.h @@ -0,0 +1,3 @@ +reg_t temp = RS1; +RD = npc; +set_pc(temp + SIMM); diff --git a/riscv/insns/jalr_j.h b/riscv/insns/jalr_j.h new file mode 100644 index 0000000..0d2ef12 --- /dev/null +++ b/riscv/insns/jalr_j.h @@ -0,0 +1 @@ +#include "insns/jalr_c.h" diff --git a/riscv/insns/jalr_r.h b/riscv/insns/jalr_r.h new file mode 100644 index 0000000..0d2ef12 --- /dev/null +++ b/riscv/insns/jalr_r.h @@ -0,0 +1 @@ +#include "insns/jalr_c.h" diff --git a/riscv/insns/lb.h b/riscv/insns/lb.h new file mode 100644 index 0000000..81ba7de --- /dev/null +++ b/riscv/insns/lb.h @@ -0,0 +1 @@ +RD = mmu.load_int8(RS1+SIMM); diff --git a/riscv/insns/lbu.h b/riscv/insns/lbu.h new file mode 100644 index 0000000..12c688a --- /dev/null +++ b/riscv/insns/lbu.h @@ -0,0 +1 @@ +RD = mmu.load_uint8(RS1+SIMM); diff --git a/riscv/insns/ld.h b/riscv/insns/ld.h new file mode 100644 index 0000000..940d348 --- /dev/null +++ b/riscv/insns/ld.h @@ -0,0 +1,2 @@ +require_xpr64; +RD = mmu.load_int64(RS1+SIMM); diff --git a/riscv/insns/lh.h b/riscv/insns/lh.h new file mode 100644 index 0000000..ec25bc4 --- /dev/null +++ b/riscv/insns/lh.h @@ -0,0 +1 @@ +RD = mmu.load_int16(RS1+SIMM); diff --git a/riscv/insns/lhu.h b/riscv/insns/lhu.h new file mode 100644 index 0000000..0999c00 --- /dev/null +++ b/riscv/insns/lhu.h @@ -0,0 +1 @@ +RD = mmu.load_uint16(RS1+SIMM); diff --git a/riscv/insns/lui.h b/riscv/insns/lui.h new file mode 100644 index 0000000..6af2a2a --- /dev/null +++ b/riscv/insns/lui.h @@ -0,0 +1 @@ +RD = sext32(BIGIMM << IMM_BITS); diff --git a/riscv/insns/lw.h b/riscv/insns/lw.h new file mode 100644 index 0000000..769c9fd --- /dev/null +++ b/riscv/insns/lw.h @@ -0,0 +1 @@ +RD = mmu.load_int32(RS1+SIMM); diff --git a/riscv/insns/lwu.h b/riscv/insns/lwu.h new file mode 100644 index 0000000..f8f9841 --- /dev/null +++ b/riscv/insns/lwu.h @@ -0,0 +1,2 @@ +require_xpr64; +RD = mmu.load_uint32(RS1+SIMM); diff --git a/riscv/insns/mffsr.h b/riscv/insns/mffsr.h new file mode 100644 index 0000000..29debc4 --- /dev/null +++ b/riscv/insns/mffsr.h @@ -0,0 +1,2 @@ +require_fp; +RD = fsr; diff --git a/riscv/insns/mfpcr.h b/riscv/insns/mfpcr.h new file mode 100644 index 0000000..7de089e --- /dev/null +++ b/riscv/insns/mfpcr.h @@ -0,0 +1,68 @@ +require_supervisor; + +reg_t val; + +switch(insn.rtype.rs2) +{ + case 0: + val = sr; + break; + case 1: + val = epc; + break; + case 2: + val = badvaddr; + break; + case 3: + val = evec; + break; + case 4: + val = count; + break; + case 5: + val = compare; + break; + case 6: + val = cause; + break; + case 7: + val = 0; + cause &= ~(1 << (IPI_IRQ+CAUSE_IP_SHIFT)); + break; + + case 8: + val = mmu.memsz >> PGSHIFT; + break; + + case 9: + val = mmu.get_ptbr(); + break; + + case 10: + val = id; + break; + + case 11: + val = vecbanks; + break; + + case 12: + val = sim.num_cores(); + break; + + case 17: + val = sim.get_fromhost(); + break; + + case 24: + val = pcr_k0; + break; + case 25: + val = pcr_k1; + break; + + default: + val = -1; +} + +RD = sext_xprlen(val); diff --git a/riscv/insns/mftx_d.h b/riscv/insns/mftx_d.h new file mode 100644 index 0000000..31be4cb --- /dev/null +++ b/riscv/insns/mftx_d.h @@ -0,0 +1,3 @@ +require_xpr64; +require_fp; +RD = FRS2; diff --git a/riscv/insns/mftx_s.h b/riscv/insns/mftx_s.h new file mode 100644 index 0000000..589b33b --- /dev/null +++ b/riscv/insns/mftx_s.h @@ -0,0 +1,2 @@ +require_fp; +RD = sext32(FRS2); diff --git a/riscv/insns/movn.h b/riscv/insns/movn.h new file mode 100644 index 0000000..402d6d3 --- /dev/null +++ b/riscv/insns/movn.h @@ -0,0 +1,2 @@ +require_vector; +if (RS1 & 0x1) RD = RS2; diff --git a/riscv/insns/movz.h b/riscv/insns/movz.h new file mode 100644 index 0000000..74cf8a9 --- /dev/null +++ b/riscv/insns/movz.h @@ -0,0 +1,2 @@ +require_vector; +if (~RS1 & 0x1) RD = RS2; diff --git a/riscv/insns/mtfsr.h b/riscv/insns/mtfsr.h new file mode 100644 index 0000000..cc6f9ea --- /dev/null +++ b/riscv/insns/mtfsr.h @@ -0,0 +1,4 @@ +require_fp; +uint32_t tmp = fsr; +set_fsr(RS1); +RD = tmp; diff --git a/riscv/insns/mtpcr.h b/riscv/insns/mtpcr.h new file mode 100644 index 0000000..59f864f --- /dev/null +++ b/riscv/insns/mtpcr.h @@ -0,0 +1,45 @@ +require_supervisor; + +switch(insn.rtype.rs2) +{ + case 0: + set_sr(RS1); + break; + case 1: + epc = RS1; + break; + case 3: + evec = RS1; + break; + case 4: + count = RS1; + break; + case 5: + cause &= ~(1 << (TIMER_IRQ+CAUSE_IP_SHIFT)); + compare = RS1; + break; + + case 7: + sim.send_ipi(RS1); + break; + + case 9: + mmu.set_ptbr(RS1); + break; + + case 11: + vecbanks = RS1 & 0xff; + vecbanks_count = __builtin_popcountll(vecbanks); + break; + + case 16: + sim.set_tohost(RS1); + break; + + case 24: + pcr_k0 = RS1; + break; + case 25: + pcr_k1 = RS1; + break; +} diff --git a/riscv/insns/mul.h b/riscv/insns/mul.h new file mode 100644 index 0000000..770d733 --- /dev/null +++ b/riscv/insns/mul.h @@ -0,0 +1 @@ +RD = sext_xprlen(RS1 * RS2); diff --git a/riscv/insns/mulh.h b/riscv/insns/mulh.h new file mode 100644 index 0000000..f771a62 --- /dev/null +++ b/riscv/insns/mulh.h @@ -0,0 +1,8 @@ +if(xpr64) +{ + int64_t a = RS1; + int64_t b = RS2; + RD = (int128_t(a) * int128_t(b)) >> 64; +} +else + RD = sext32((sext32(RS1) * sext32(RS2)) >> 32); diff --git a/riscv/insns/mulhsu.h b/riscv/insns/mulhsu.h new file mode 100644 index 0000000..c832657 --- /dev/null +++ b/riscv/insns/mulhsu.h @@ -0,0 +1,8 @@ +if(xpr64) +{ + int64_t a = RS1; + uint64_t b = RS2; + RD = (int128_t(a) * uint128_t(b)) >> 64; +} +else + RD = sext32((sext32(RS1) * reg_t((uint32_t)RS2)) >> 32); diff --git a/riscv/insns/mulhu.h b/riscv/insns/mulhu.h new file mode 100644 index 0000000..6334426 --- /dev/null +++ b/riscv/insns/mulhu.h @@ -0,0 +1,4 @@ +if(xpr64) + RD = (uint128_t(RS1) * uint128_t(RS2)) >> 64; +else + RD = sext32(((uint64_t)(uint32_t)RS1 * (uint64_t)(uint32_t)RS2) >> 32); diff --git a/riscv/insns/mulw.h b/riscv/insns/mulw.h new file mode 100644 index 0000000..7b0a934 --- /dev/null +++ b/riscv/insns/mulw.h @@ -0,0 +1,2 @@ +require_xpr64; +RD = sext32(RS1 * RS2); diff --git a/riscv/insns/mxtf_d.h b/riscv/insns/mxtf_d.h new file mode 100644 index 0000000..29792ec --- /dev/null +++ b/riscv/insns/mxtf_d.h @@ -0,0 +1,3 @@ +require_xpr64; +require_fp; +FRD = RS1; diff --git a/riscv/insns/mxtf_s.h b/riscv/insns/mxtf_s.h new file mode 100644 index 0000000..54546ea --- /dev/null +++ b/riscv/insns/mxtf_s.h @@ -0,0 +1,2 @@ +require_fp; +FRD = RS1; diff --git a/riscv/insns/or.h b/riscv/insns/or.h new file mode 100644 index 0000000..07bcac3 --- /dev/null +++ b/riscv/insns/or.h @@ -0,0 +1 @@ +RD = RS1 | RS2; diff --git a/riscv/insns/ori.h b/riscv/insns/ori.h new file mode 100644 index 0000000..9561b97 --- /dev/null +++ b/riscv/insns/ori.h @@ -0,0 +1 @@ +RD = SIMM | RS1; diff --git a/riscv/insns/rdcycle.h b/riscv/insns/rdcycle.h new file mode 100644 index 0000000..9b966a6 --- /dev/null +++ b/riscv/insns/rdcycle.h @@ -0,0 +1 @@ +RD = cycle; diff --git a/riscv/insns/rdinstret.h b/riscv/insns/rdinstret.h new file mode 100644 index 0000000..9b966a6 --- /dev/null +++ b/riscv/insns/rdinstret.h @@ -0,0 +1 @@ +RD = cycle; diff --git a/riscv/insns/rdnpc.h b/riscv/insns/rdnpc.h new file mode 100644 index 0000000..5525421 --- /dev/null +++ b/riscv/insns/rdnpc.h @@ -0,0 +1 @@ +RD = npc; diff --git a/riscv/insns/rdtime.h b/riscv/insns/rdtime.h new file mode 100644 index 0000000..9b966a6 --- /dev/null +++ b/riscv/insns/rdtime.h @@ -0,0 +1 @@ +RD = cycle; diff --git a/riscv/insns/rem.h b/riscv/insns/rem.h new file mode 100644 index 0000000..ac82a56 --- /dev/null +++ b/riscv/insns/rem.h @@ -0,0 +1,6 @@ +if(RS2 == 0) + RD = RS1; +else if(sreg_t(RS1) == INT64_MIN && sreg_t(RS2) == -1) + RD = 0; +else + RD = sext_xprlen(sext_xprlen(RS1) % sext_xprlen(RS2)); diff --git a/riscv/insns/remu.h b/riscv/insns/remu.h new file mode 100644 index 0000000..c698aca --- /dev/null +++ b/riscv/insns/remu.h @@ -0,0 +1,4 @@ +if(RS2 == 0) + RD = RS1; +else + RD = sext_xprlen(zext_xprlen(RS1) % zext_xprlen(RS2)); diff --git a/riscv/insns/remuw.h b/riscv/insns/remuw.h new file mode 100644 index 0000000..8234af3 --- /dev/null +++ b/riscv/insns/remuw.h @@ -0,0 +1,5 @@ +require_xpr64; +if(RS2 == 0) + RD = RS1; +else + RD = sext32(zext_xprlen(RS1) % zext_xprlen(RS2)); diff --git a/riscv/insns/remw.h b/riscv/insns/remw.h new file mode 100644 index 0000000..93c3858 --- /dev/null +++ b/riscv/insns/remw.h @@ -0,0 +1,7 @@ +require_xpr64; +if(RS2 == 0) + RD = RS1; +else if(int32_t(RS1) == INT32_MIN && int32_t(RS2) == -1) + RD = 0; +else + RD = sext32(int32_t(RS1) % int32_t(RS2)); diff --git a/riscv/insns/sb.h b/riscv/insns/sb.h new file mode 100644 index 0000000..af5bd10 --- /dev/null +++ b/riscv/insns/sb.h @@ -0,0 +1 @@ +mmu.store_uint8(RS1+BIMM, RS2); diff --git a/riscv/insns/sd.h b/riscv/insns/sd.h new file mode 100644 index 0000000..2009149 --- /dev/null +++ b/riscv/insns/sd.h @@ -0,0 +1,2 @@ +require_xpr64; +mmu.store_uint64(RS1+BIMM, RS2); diff --git a/riscv/insns/sh.h b/riscv/insns/sh.h new file mode 100644 index 0000000..a484e1e --- /dev/null +++ b/riscv/insns/sh.h @@ -0,0 +1 @@ +mmu.store_uint16(RS1+BIMM, RS2); diff --git a/riscv/insns/sll.h b/riscv/insns/sll.h new file mode 100644 index 0000000..86eb966 --- /dev/null +++ b/riscv/insns/sll.h @@ -0,0 +1 @@ +RD = sext_xprlen(RS1 << (RS2 & (xprlen-1))); diff --git a/riscv/insns/slli.h b/riscv/insns/slli.h new file mode 100644 index 0000000..bfaf430 --- /dev/null +++ b/riscv/insns/slli.h @@ -0,0 +1,8 @@ +if(xpr64) + RD = RS1 << SHAMT; +else +{ + if(SHAMT & 0x20) + throw trap_illegal_instruction; + RD = sext32(RS1 << SHAMT); +} diff --git a/riscv/insns/slliw.h b/riscv/insns/slliw.h new file mode 100644 index 0000000..1f6e50d --- /dev/null +++ b/riscv/insns/slliw.h @@ -0,0 +1,2 @@ +require_xpr64; +RD = sext32(RS1 << SHAMTW); diff --git a/riscv/insns/sllw.h b/riscv/insns/sllw.h new file mode 100644 index 0000000..f3356d8 --- /dev/null +++ b/riscv/insns/sllw.h @@ -0,0 +1,2 @@ +require_xpr64; +RD = sext32(RS1 << (RS2 & 0x1F)); diff --git a/riscv/insns/slt.h b/riscv/insns/slt.h new file mode 100644 index 0000000..5c50534 --- /dev/null +++ b/riscv/insns/slt.h @@ -0,0 +1 @@ +RD = sreg_t(cmp_trunc(RS1)) < sreg_t(cmp_trunc(RS2)); diff --git a/riscv/insns/slti.h b/riscv/insns/slti.h new file mode 100644 index 0000000..1dcd892 --- /dev/null +++ b/riscv/insns/slti.h @@ -0,0 +1 @@ +RD = sreg_t(cmp_trunc(RS1)) < sreg_t(cmp_trunc(SIMM)); diff --git a/riscv/insns/sltiu.h b/riscv/insns/sltiu.h new file mode 100644 index 0000000..45e579b --- /dev/null +++ b/riscv/insns/sltiu.h @@ -0,0 +1 @@ +RD = cmp_trunc(RS1) < cmp_trunc(SIMM); diff --git a/riscv/insns/sltu.h b/riscv/insns/sltu.h new file mode 100644 index 0000000..2c5bdc3 --- /dev/null +++ b/riscv/insns/sltu.h @@ -0,0 +1 @@ +RD = cmp_trunc(RS1) < cmp_trunc(RS2); diff --git a/riscv/insns/sra.h b/riscv/insns/sra.h new file mode 100644 index 0000000..7102da0 --- /dev/null +++ b/riscv/insns/sra.h @@ -0,0 +1 @@ +RD = sext_xprlen(sext_xprlen(RS1) >> (RS2 & (xprlen-1))); diff --git a/riscv/insns/srai.h b/riscv/insns/srai.h new file mode 100644 index 0000000..bb17d27 --- /dev/null +++ b/riscv/insns/srai.h @@ -0,0 +1,8 @@ +if(xpr64) + RD = sreg_t(RS1) >> SHAMT; +else +{ + if(SHAMT & 0x20) + throw trap_illegal_instruction; + RD = sext32(int32_t(RS1) >> SHAMT); +} diff --git a/riscv/insns/sraiw.h b/riscv/insns/sraiw.h new file mode 100644 index 0000000..4c56730 --- /dev/null +++ b/riscv/insns/sraiw.h @@ -0,0 +1,2 @@ +require_xpr64; +RD = sext32(int32_t(RS1) >> SHAMTW); diff --git a/riscv/insns/sraw.h b/riscv/insns/sraw.h new file mode 100644 index 0000000..d178374 --- /dev/null +++ b/riscv/insns/sraw.h @@ -0,0 +1,2 @@ +require_xpr64; +RD = sext32(int32_t(RS1) >> (RS2 & 0x1F)); diff --git a/riscv/insns/srl.h b/riscv/insns/srl.h new file mode 100644 index 0000000..8230d27 --- /dev/null +++ b/riscv/insns/srl.h @@ -0,0 +1,4 @@ +if(xpr64) + RD = RS1 >> (RS2 & 0x3F); +else + RD = sext32((uint32_t)RS1 >> (RS2 & 0x1F)); diff --git a/riscv/insns/srli.h b/riscv/insns/srli.h new file mode 100644 index 0000000..5378fd1 --- /dev/null +++ b/riscv/insns/srli.h @@ -0,0 +1,8 @@ +if(xpr64) + RD = RS1 >> SHAMT; +else +{ + if(SHAMT & 0x20) + throw trap_illegal_instruction; + RD = sext32((uint32_t)RS1 >> SHAMT); +} diff --git a/riscv/insns/srliw.h b/riscv/insns/srliw.h new file mode 100644 index 0000000..c400507 --- /dev/null +++ b/riscv/insns/srliw.h @@ -0,0 +1,2 @@ +require_xpr64; +RD = sext32((uint32_t)RS1 >> SHAMTW); diff --git a/riscv/insns/srlw.h b/riscv/insns/srlw.h new file mode 100644 index 0000000..b206f7c --- /dev/null +++ b/riscv/insns/srlw.h @@ -0,0 +1,2 @@ +require_xpr64; +RD = sext32((uint32_t)RS1 >> (RS2 & 0x1F)); diff --git a/riscv/insns/stop.h b/riscv/insns/stop.h new file mode 100644 index 0000000..791a82c --- /dev/null +++ b/riscv/insns/stop.h @@ -0,0 +1,3 @@ +require_vector; +utmode = false; +throw vt_command_stop; diff --git a/riscv/insns/sub.h b/riscv/insns/sub.h new file mode 100644 index 0000000..2b1e057 --- /dev/null +++ b/riscv/insns/sub.h @@ -0,0 +1 @@ +RD = sext_xprlen(RS1 - RS2); diff --git a/riscv/insns/subw.h b/riscv/insns/subw.h new file mode 100644 index 0000000..28db334 --- /dev/null +++ b/riscv/insns/subw.h @@ -0,0 +1,3 @@ +require_xpr64; +RD = sext32(RS1 - RS2); + diff --git a/riscv/insns/sw.h b/riscv/insns/sw.h new file mode 100644 index 0000000..dbe260f --- /dev/null +++ b/riscv/insns/sw.h @@ -0,0 +1 @@ +mmu.store_uint32(RS1+BIMM, RS2); diff --git a/riscv/insns/syscall.h b/riscv/insns/syscall.h new file mode 100644 index 0000000..2c7199d --- /dev/null +++ b/riscv/insns/syscall.h @@ -0,0 +1 @@ +throw trap_syscall; diff --git a/riscv/insns/utidx.h b/riscv/insns/utidx.h new file mode 100644 index 0000000..b3c944c --- /dev/null +++ b/riscv/insns/utidx.h @@ -0,0 +1,2 @@ +require_vector; +RD = utidx; diff --git a/riscv/insns/vf.h b/riscv/insns/vf.h new file mode 100644 index 0000000..7779645 --- /dev/null +++ b/riscv/insns/vf.h @@ -0,0 +1,8 @@ +require_vector; +for (int i=0; i<VL; i++) +{ + uts[i]->pc = RS1+SIMM; + uts[i]->utmode = true; + while (uts[i]->utmode) + uts[i]->step(1, false); // XXX +} diff --git a/riscv/insns/vfld.h b/riscv/insns/vfld.h new file mode 100644 index 0000000..9b40470 --- /dev/null +++ b/riscv/insns/vfld.h @@ -0,0 +1,3 @@ +require_vector; +require_fp; +VEC_LOAD(FRD, load_int64, 8); diff --git a/riscv/insns/vflsegd.h b/riscv/insns/vflsegd.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vflsegd.h diff --git a/riscv/insns/vflsegstd.h b/riscv/insns/vflsegstd.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vflsegstd.h diff --git a/riscv/insns/vflsegstw.h b/riscv/insns/vflsegstw.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vflsegstw.h diff --git a/riscv/insns/vflsegw.h b/riscv/insns/vflsegw.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vflsegw.h diff --git a/riscv/insns/vflstd.h b/riscv/insns/vflstd.h new file mode 100644 index 0000000..fa9b32d --- /dev/null +++ b/riscv/insns/vflstd.h @@ -0,0 +1,3 @@ +require_vector; +require_fp; +VEC_LOAD(FRD, load_int64, RS2); diff --git a/riscv/insns/vflstw.h b/riscv/insns/vflstw.h new file mode 100644 index 0000000..716c818 --- /dev/null +++ b/riscv/insns/vflstw.h @@ -0,0 +1,3 @@ +require_vector; +require_fp; +VEC_LOAD(FRD, load_int32, RS2); diff --git a/riscv/insns/vflw.h b/riscv/insns/vflw.h new file mode 100644 index 0000000..75fdd04 --- /dev/null +++ b/riscv/insns/vflw.h @@ -0,0 +1,3 @@ +require_vector; +require_fp; +VEC_LOAD(FRD, load_int32, 4); diff --git a/riscv/insns/vfmst.h b/riscv/insns/vfmst.h new file mode 100644 index 0000000..686d7c5 --- /dev/null +++ b/riscv/insns/vfmst.h @@ -0,0 +1,4 @@ +require_vector; +require_fp; +assert(0 <= RS2 && RS2 < MAX_UTS); +UT_FRD(RS2) = FRS1; diff --git a/riscv/insns/vfmsv.h b/riscv/insns/vfmsv.h new file mode 100644 index 0000000..a9aa876 --- /dev/null +++ b/riscv/insns/vfmsv.h @@ -0,0 +1,5 @@ +require_vector; +require_fp; +UT_LOOP_START + UT_LOOP_FRD = FRS1; +UT_LOOP_END diff --git a/riscv/insns/vfmts.h b/riscv/insns/vfmts.h new file mode 100644 index 0000000..a6da126 --- /dev/null +++ b/riscv/insns/vfmts.h @@ -0,0 +1,4 @@ +require_vector; +require_fp; +assert(0 <= RS2 && RS2 < MAX_UTS); +FRD = UT_FRS1(RS2); diff --git a/riscv/insns/vfmvv.h b/riscv/insns/vfmvv.h new file mode 100644 index 0000000..279da21 --- /dev/null +++ b/riscv/insns/vfmvv.h @@ -0,0 +1,5 @@ +require_vector; +require_fp; +UT_LOOP_START + UT_LOOP_FRD = UT_LOOP_FRS1; +UT_LOOP_END diff --git a/riscv/insns/vfsd.h b/riscv/insns/vfsd.h new file mode 100644 index 0000000..f619fc8 --- /dev/null +++ b/riscv/insns/vfsd.h @@ -0,0 +1,3 @@ +require_vector; +require_fp; +VEC_STORE(FRD, store_uint64, 8); diff --git a/riscv/insns/vfssegd.h b/riscv/insns/vfssegd.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vfssegd.h diff --git a/riscv/insns/vfssegstd.h b/riscv/insns/vfssegstd.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vfssegstd.h diff --git a/riscv/insns/vfssegstw.h b/riscv/insns/vfssegstw.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vfssegstw.h diff --git a/riscv/insns/vfssegw.h b/riscv/insns/vfssegw.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vfssegw.h diff --git a/riscv/insns/vfsstd.h b/riscv/insns/vfsstd.h new file mode 100644 index 0000000..b3bb260 --- /dev/null +++ b/riscv/insns/vfsstd.h @@ -0,0 +1,3 @@ +require_vector; +require_fp; +VEC_STORE(FRD, store_uint64, RS2); diff --git a/riscv/insns/vfsstw.h b/riscv/insns/vfsstw.h new file mode 100644 index 0000000..9cef9b0 --- /dev/null +++ b/riscv/insns/vfsstw.h @@ -0,0 +1,3 @@ +require_vector; +require_fp; +VEC_STORE(FRD, store_uint32, RS2); diff --git a/riscv/insns/vfsw.h b/riscv/insns/vfsw.h new file mode 100644 index 0000000..3fe3d3f --- /dev/null +++ b/riscv/insns/vfsw.h @@ -0,0 +1,3 @@ +require_vector; +require_fp; +VEC_STORE(FRD, store_uint32, 4); diff --git a/riscv/insns/vlb.h b/riscv/insns/vlb.h new file mode 100644 index 0000000..618380a --- /dev/null +++ b/riscv/insns/vlb.h @@ -0,0 +1,2 @@ +require_vector; +VEC_LOAD(RD, load_int8, 1); diff --git a/riscv/insns/vlbu.h b/riscv/insns/vlbu.h new file mode 100644 index 0000000..f92c8b5 --- /dev/null +++ b/riscv/insns/vlbu.h @@ -0,0 +1,2 @@ +require_vector; +VEC_LOAD(RD, load_uint8, 1); diff --git a/riscv/insns/vld.h b/riscv/insns/vld.h new file mode 100644 index 0000000..fb7a3c5 --- /dev/null +++ b/riscv/insns/vld.h @@ -0,0 +1,3 @@ +require_vector; +require_xpr64; +VEC_LOAD(RD, load_int64, 8); diff --git a/riscv/insns/vlh.h b/riscv/insns/vlh.h new file mode 100644 index 0000000..269c2a8 --- /dev/null +++ b/riscv/insns/vlh.h @@ -0,0 +1,2 @@ +require_vector; +VEC_LOAD(RD, load_int16, 2); diff --git a/riscv/insns/vlhu.h b/riscv/insns/vlhu.h new file mode 100644 index 0000000..7a2019d --- /dev/null +++ b/riscv/insns/vlhu.h @@ -0,0 +1,2 @@ +require_vector; +VEC_LOAD(RD, load_uint16, 2); diff --git a/riscv/insns/vlsegb.h b/riscv/insns/vlsegb.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vlsegb.h diff --git a/riscv/insns/vlsegbu.h b/riscv/insns/vlsegbu.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vlsegbu.h diff --git a/riscv/insns/vlsegd.h b/riscv/insns/vlsegd.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vlsegd.h diff --git a/riscv/insns/vlsegh.h b/riscv/insns/vlsegh.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vlsegh.h diff --git a/riscv/insns/vlseghu.h b/riscv/insns/vlseghu.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vlseghu.h diff --git a/riscv/insns/vlsegstb.h b/riscv/insns/vlsegstb.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vlsegstb.h diff --git a/riscv/insns/vlsegstbu.h b/riscv/insns/vlsegstbu.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vlsegstbu.h diff --git a/riscv/insns/vlsegstd.h b/riscv/insns/vlsegstd.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vlsegstd.h diff --git a/riscv/insns/vlsegsth.h b/riscv/insns/vlsegsth.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vlsegsth.h diff --git a/riscv/insns/vlsegsthu.h b/riscv/insns/vlsegsthu.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vlsegsthu.h diff --git a/riscv/insns/vlsegstw.h b/riscv/insns/vlsegstw.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vlsegstw.h diff --git a/riscv/insns/vlsegstwu.h b/riscv/insns/vlsegstwu.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vlsegstwu.h diff --git a/riscv/insns/vlsegw.h b/riscv/insns/vlsegw.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vlsegw.h diff --git a/riscv/insns/vlsegwu.h b/riscv/insns/vlsegwu.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vlsegwu.h diff --git a/riscv/insns/vlstb.h b/riscv/insns/vlstb.h new file mode 100644 index 0000000..219d90e --- /dev/null +++ b/riscv/insns/vlstb.h @@ -0,0 +1,2 @@ +require_vector; +VEC_LOAD(RD, load_int8, RS2); diff --git a/riscv/insns/vlstbu.h b/riscv/insns/vlstbu.h new file mode 100644 index 0000000..09faa29 --- /dev/null +++ b/riscv/insns/vlstbu.h @@ -0,0 +1,2 @@ +require_vector; +VEC_LOAD(RD, load_uint8, RS2); diff --git a/riscv/insns/vlstd.h b/riscv/insns/vlstd.h new file mode 100644 index 0000000..5e5de9c --- /dev/null +++ b/riscv/insns/vlstd.h @@ -0,0 +1,3 @@ +require_vector; +require_xpr64; +VEC_LOAD(RD, load_int64, RS2); diff --git a/riscv/insns/vlsth.h b/riscv/insns/vlsth.h new file mode 100644 index 0000000..af6b5b5 --- /dev/null +++ b/riscv/insns/vlsth.h @@ -0,0 +1,2 @@ +require_vector; +VEC_LOAD(RD, load_int16, RS2); diff --git a/riscv/insns/vlsthu.h b/riscv/insns/vlsthu.h new file mode 100644 index 0000000..0fe8452 --- /dev/null +++ b/riscv/insns/vlsthu.h @@ -0,0 +1,2 @@ +require_vector; +VEC_LOAD(RD, load_uint16, RS2); diff --git a/riscv/insns/vlstw.h b/riscv/insns/vlstw.h new file mode 100644 index 0000000..5375dc0 --- /dev/null +++ b/riscv/insns/vlstw.h @@ -0,0 +1,2 @@ +require_vector; +VEC_LOAD(RD, load_int32, RS2); diff --git a/riscv/insns/vlstwu.h b/riscv/insns/vlstwu.h new file mode 100644 index 0000000..328e23f --- /dev/null +++ b/riscv/insns/vlstwu.h @@ -0,0 +1,2 @@ +require_vector; +VEC_LOAD(RD, load_uint32, RS2); diff --git a/riscv/insns/vlw.h b/riscv/insns/vlw.h new file mode 100644 index 0000000..6e35911 --- /dev/null +++ b/riscv/insns/vlw.h @@ -0,0 +1,2 @@ +require_vector; +VEC_LOAD(RD, load_int32, 4); diff --git a/riscv/insns/vlwu.h b/riscv/insns/vlwu.h new file mode 100644 index 0000000..4fa1489 --- /dev/null +++ b/riscv/insns/vlwu.h @@ -0,0 +1,2 @@ +require_vector; +VEC_LOAD(RD, load_uint32, 4); diff --git a/riscv/insns/vmst.h b/riscv/insns/vmst.h new file mode 100644 index 0000000..f4d03d9 --- /dev/null +++ b/riscv/insns/vmst.h @@ -0,0 +1,3 @@ +require_vector; +assert(0 <= RS2 && RS2 < MAX_UTS); +UT_RD(RS2) = RS1; diff --git a/riscv/insns/vmsv.h b/riscv/insns/vmsv.h new file mode 100644 index 0000000..c6f4c2c --- /dev/null +++ b/riscv/insns/vmsv.h @@ -0,0 +1,4 @@ +require_vector; +UT_LOOP_START + UT_LOOP_RD = RS1; +UT_LOOP_END diff --git a/riscv/insns/vmts.h b/riscv/insns/vmts.h new file mode 100644 index 0000000..2d463bc --- /dev/null +++ b/riscv/insns/vmts.h @@ -0,0 +1,3 @@ +require_vector; +assert(0 <= RS2 && RS2 < MAX_UTS); +RD = UT_RS1(RS2); diff --git a/riscv/insns/vmvv.h b/riscv/insns/vmvv.h new file mode 100644 index 0000000..91d63d4 --- /dev/null +++ b/riscv/insns/vmvv.h @@ -0,0 +1,4 @@ +require_vector; +UT_LOOP_START + UT_LOOP_RD = UT_LOOP_RS1; +UT_LOOP_END diff --git a/riscv/insns/vsb.h b/riscv/insns/vsb.h new file mode 100644 index 0000000..c3d5b9d --- /dev/null +++ b/riscv/insns/vsb.h @@ -0,0 +1,2 @@ +require_vector; +VEC_STORE(RD, store_uint8, 1); diff --git a/riscv/insns/vsd.h b/riscv/insns/vsd.h new file mode 100644 index 0000000..9c02069 --- /dev/null +++ b/riscv/insns/vsd.h @@ -0,0 +1,3 @@ +require_vector; +require_xpr64; +VEC_STORE(RD, store_uint64, 8); diff --git a/riscv/insns/vsetvl.h b/riscv/insns/vsetvl.h new file mode 100644 index 0000000..c2212ff --- /dev/null +++ b/riscv/insns/vsetvl.h @@ -0,0 +1,3 @@ +require_vector; +setvl(RS1); +RD = VL; diff --git a/riscv/insns/vsh.h b/riscv/insns/vsh.h new file mode 100644 index 0000000..623eda8 --- /dev/null +++ b/riscv/insns/vsh.h @@ -0,0 +1,2 @@ +require_vector; +VEC_STORE(RD, store_uint16, 2); diff --git a/riscv/insns/vssegb.h b/riscv/insns/vssegb.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vssegb.h diff --git a/riscv/insns/vssegd.h b/riscv/insns/vssegd.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vssegd.h diff --git a/riscv/insns/vssegh.h b/riscv/insns/vssegh.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vssegh.h diff --git a/riscv/insns/vssegstb.h b/riscv/insns/vssegstb.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vssegstb.h diff --git a/riscv/insns/vssegstd.h b/riscv/insns/vssegstd.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vssegstd.h diff --git a/riscv/insns/vssegsth.h b/riscv/insns/vssegsth.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vssegsth.h diff --git a/riscv/insns/vssegstw.h b/riscv/insns/vssegstw.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vssegstw.h diff --git a/riscv/insns/vssegw.h b/riscv/insns/vssegw.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vssegw.h diff --git a/riscv/insns/vsstb.h b/riscv/insns/vsstb.h new file mode 100644 index 0000000..b83cc50 --- /dev/null +++ b/riscv/insns/vsstb.h @@ -0,0 +1,2 @@ +require_vector; +VEC_STORE(RD, store_uint8, RS2); diff --git a/riscv/insns/vsstd.h b/riscv/insns/vsstd.h new file mode 100644 index 0000000..26868d2 --- /dev/null +++ b/riscv/insns/vsstd.h @@ -0,0 +1,3 @@ +require_vector; +require_xpr64; +VEC_STORE(RD, store_uint64, RS2); diff --git a/riscv/insns/vssth.h b/riscv/insns/vssth.h new file mode 100644 index 0000000..3904331 --- /dev/null +++ b/riscv/insns/vssth.h @@ -0,0 +1,2 @@ +require_vector; +VEC_STORE(RD, store_uint16, RS2); diff --git a/riscv/insns/vsstw.h b/riscv/insns/vsstw.h new file mode 100644 index 0000000..8f05953 --- /dev/null +++ b/riscv/insns/vsstw.h @@ -0,0 +1,2 @@ +require_vector; +VEC_STORE(RD, store_uint32, RS2); diff --git a/riscv/insns/vsw.h b/riscv/insns/vsw.h new file mode 100644 index 0000000..662d4e3 --- /dev/null +++ b/riscv/insns/vsw.h @@ -0,0 +1,2 @@ +require_vector; +VEC_STORE(RD, store_uint32, 4); diff --git a/riscv/insns/vtcfgivl.h b/riscv/insns/vtcfgivl.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/riscv/insns/vtcfgivl.h diff --git a/riscv/insns/vvcfgivl.h b/riscv/insns/vvcfgivl.h new file mode 100644 index 0000000..0ded9f8 --- /dev/null +++ b/riscv/insns/vvcfgivl.h @@ -0,0 +1,6 @@ +require_vector; +nxpr_use = SIMM & 0x3f; +nfpr_use = (SIMM >> 6) & 0x3f; +vcfg(); +setvl(RS1); +RD = VL; diff --git a/riscv/insns/xor.h b/riscv/insns/xor.h new file mode 100644 index 0000000..49b1783 --- /dev/null +++ b/riscv/insns/xor.h @@ -0,0 +1 @@ +RD = RS1 ^ RS2; diff --git a/riscv/insns/xori.h b/riscv/insns/xori.h new file mode 100644 index 0000000..5852aac --- /dev/null +++ b/riscv/insns/xori.h @@ -0,0 +1 @@ +RD = SIMM ^ RS1; diff --git a/riscv/interactive.cc b/riscv/interactive.cc new file mode 100644 index 0000000..4f7891f --- /dev/null +++ b/riscv/interactive.cc @@ -0,0 +1,256 @@ +#include "sim.h" +#include "htif.h" +#include <sys/mman.h> +#include <map> +#include <iostream> +#include <climits> +#include <assert.h> + +void sim_t::interactive() +{ + putchar(':'); + char s[128]; + std::cin.getline(s,sizeof(s)-1); + + char* p = strtok(s," "); + if(!p) + { + interactive_run_noisy(std::string("r"), std::vector<std::string>(1,"1")); + return; + } + std::string cmd = p; + + std::vector<std::string> args; + while((p = strtok(NULL," "))) + args.push_back(p); + + + typedef void (sim_t::*interactive_func)(const std::string&, const std::vector<std::string>&); + std::map<std::string,interactive_func> funcs; + + funcs["r"] = &sim_t::interactive_run_noisy; + funcs["rs"] = &sim_t::interactive_run_silent; + funcs["rp"] = &sim_t::interactive_run_proc_noisy; + funcs["rps"] = &sim_t::interactive_run_proc_silent; + funcs["reg"] = &sim_t::interactive_reg; + funcs["fregs"] = &sim_t::interactive_fregs; + funcs["fregd"] = &sim_t::interactive_fregd; + funcs["mem"] = &sim_t::interactive_mem; + funcs["str"] = &sim_t::interactive_str; + funcs["until"] = &sim_t::interactive_until; + funcs["while"] = &sim_t::interactive_until; + funcs["q"] = &sim_t::interactive_quit; + + try + { + if(funcs.count(cmd)) + (this->*funcs[cmd])(cmd, args); + } + catch(trap_t t) {} +} + +void sim_t::interactive_run_noisy(const std::string& cmd, const std::vector<std::string>& args) +{ + interactive_run(cmd,args,true); +} + +void sim_t::interactive_run_silent(const std::string& cmd, const std::vector<std::string>& args) +{ + interactive_run(cmd,args,false); +} + +void sim_t::interactive_run(const std::string& cmd, const std::vector<std::string>& args, bool noisy) +{ + if(args.size()) + step_all(atoll(args[0].c_str()),1,noisy); + else + while(1) step_all(1,1,noisy); +} + +void sim_t::interactive_run_proc_noisy(const std::string& cmd, const std::vector<std::string>& args) +{ + interactive_run_proc(cmd,args,true); +} + +void sim_t::interactive_run_proc_silent(const std::string& cmd, const std::vector<std::string>& args) +{ + interactive_run_proc(cmd,args,false); +} + +void sim_t::interactive_run_proc(const std::string& cmd, const std::vector<std::string>& a, bool noisy) +{ + if(a.size() == 0) + return; + + int p = atoi(a[0].c_str()); + if(p >= (int)num_cores()) + return; + + if(a.size() == 2) + procs[p]->step(atoi(a[1].c_str()),noisy); + else + while(1) procs[p]->step(1,noisy); +} + +void sim_t::interactive_quit(const std::string& cmd, const std::vector<std::string>& args) +{ + stop(); +} + +reg_t sim_t::get_pc(const std::vector<std::string>& args) +{ + if(args.size() != 1) + throw trap_illegal_instruction; + + int p = atoi(args[0].c_str()); + if(p >= (int)num_cores()) + throw trap_illegal_instruction; + + return procs[p]->pc; +} + +reg_t sim_t::get_reg(const std::vector<std::string>& args) +{ + if(args.size() != 2) + throw trap_illegal_instruction; + + int p = atoi(args[0].c_str()); + int r = atoi(args[1].c_str()); + if(p >= (int)num_cores() || r >= NXPR) + throw trap_illegal_instruction; + + return procs[p]->XPR[r]; +} + +reg_t sim_t::get_freg(const std::vector<std::string>& args) +{ + if(args.size() != 2) + throw trap_illegal_instruction; + + int p = atoi(args[0].c_str()); + int r = atoi(args[1].c_str()); + if(p >= (int)num_cores() || r >= NFPR) + throw trap_illegal_instruction; + + return procs[p]->FPR[r]; +} + +void sim_t::interactive_reg(const std::string& cmd, const std::vector<std::string>& args) +{ + printf("0x%016llx\n",(unsigned long long)get_reg(args)); +} + +union fpr +{ + reg_t r; + float s; + double d; +}; + +void sim_t::interactive_fregs(const std::string& cmd, const std::vector<std::string>& args) +{ + fpr f; + f.r = get_freg(args); + printf("%g\n",f.s); +} + +void sim_t::interactive_fregd(const std::string& cmd, const std::vector<std::string>& args) +{ + fpr f; + f.r = get_freg(args); + printf("%g\n",f.d); +} + +reg_t sim_t::get_mem(const std::vector<std::string>& args) +{ + if(args.size() != 1 && args.size() != 2) + throw trap_illegal_instruction; + + std::string addr_str = args[0]; + if(args.size() == 2) + { + int p = atoi(args[0].c_str()); + if(p >= (int)num_cores()) + throw trap_illegal_instruction; + mmu->set_vm_enabled(!!(procs[p]->sr & SR_VM)); + mmu->set_ptbr(procs[p]->mmu.get_ptbr()); + addr_str = args[1]; + } + + reg_t addr = strtol(addr_str.c_str(),NULL,16), val; + if(addr == LONG_MAX) + addr = strtoul(addr_str.c_str(),NULL,16); + + switch(addr % 8) + { + case 0: + val = mmu->load_uint64(addr); + break; + case 4: + val = mmu->load_uint32(addr); + break; + case 2: + case 6: + val = mmu->load_uint16(addr); + break; + default: + val = mmu->load_uint8(addr); + break; + } + return val; +} + +void sim_t::interactive_mem(const std::string& cmd, const std::vector<std::string>& args) +{ + printf("0x%016llx\n",(unsigned long long)get_mem(args)); +} + +void sim_t::interactive_str(const std::string& cmd, const std::vector<std::string>& args) +{ + if(args.size() != 1) + throw trap_illegal_instruction; + + reg_t addr = strtol(args[0].c_str(),NULL,16); + + char ch; + while((ch = mmu->load_uint8(addr++))) + putchar(ch); + + putchar('\n'); +} + +void sim_t::interactive_until(const std::string& cmd, const std::vector<std::string>& args) +{ + if(args.size() < 3) + return; + + std::string scmd = args[0]; + reg_t val = strtol(args[args.size()-1].c_str(),NULL,16); + if(val == LONG_MAX) + val = strtoul(args[args.size()-1].c_str(),NULL,16); + + std::vector<std::string> args2; + args2 = std::vector<std::string>(args.begin()+1,args.end()-1); + + while(1) + { + reg_t current; + if(scmd == "reg") + current = get_reg(args2); + else if(scmd == "pc") + current = get_pc(args2); + else if(scmd == "mem") + current = get_mem(args2); + else if(scmd == "tohost") + current = tohost; + else + return; + + if(cmd == "until" && current == val) + break; + if(cmd == "while" && current != val) + break; + + step_all(1,1,false); + } +} diff --git a/riscv/mmu.cc b/riscv/mmu.cc new file mode 100644 index 0000000..b2c8c98 --- /dev/null +++ b/riscv/mmu.cc @@ -0,0 +1,104 @@ +#include "mmu.h" +#include "sim.h" +#include "processor.h" + +mmu_t::mmu_t(char* _mem, size_t _memsz) + : mem(_mem), memsz(_memsz), badvaddr(0), + ptbr(0), supervisor(true), vm_enabled(false) +{ + flush_tlb(); +} + +mmu_t::~mmu_t() +{ +} + +void mmu_t::flush_tlb() +{ + memset(tlb_insn_tag, -1, sizeof(tlb_insn_tag)); + memset(tlb_load_tag, -1, sizeof(tlb_load_tag)); + memset(tlb_store_tag, -1, sizeof(tlb_store_tag)); + + flush_icache(); +} + +void mmu_t::flush_icache() +{ + memset(icache_tag, -1, sizeof(icache_tag)); +} + +void* mmu_t::refill(reg_t addr, bool store, bool fetch) +{ + reg_t idx = (addr >> PGSHIFT) % TLB_ENTRIES; + reg_t expected_tag = addr & ~(PGSIZE-1); + + reg_t pte = walk(addr); + + reg_t pte_perm = pte & PTE_PERM; + if(supervisor) // shift supervisor permission bits into user perm bits + pte_perm = (pte_perm/(PTE_SX/PTE_UX)) & PTE_PERM; + pte_perm |= pte & PTE_E; + + reg_t perm = (fetch ? PTE_UX : store ? PTE_UW : PTE_UR) | PTE_E; + if(unlikely((pte_perm & perm) != perm)) + { + badvaddr = addr; + throw store ? trap_store_access_fault + : fetch ? trap_instruction_access_fault + : trap_load_access_fault; + } + + tlb_load_tag[idx] = (pte_perm & PTE_UR) ? expected_tag : -1; + tlb_store_tag[idx] = (pte_perm & PTE_UW) ? expected_tag : -1; + tlb_insn_tag[idx] = (pte_perm & PTE_UX) ? expected_tag : -1; + tlb_data[idx] = (long)(pte >> PTE_PPN_SHIFT << PGSHIFT) + (long)mem; + + return (void*)(((long)addr & (PGSIZE-1)) | tlb_data[idx]); +} + +pte_t mmu_t::walk(reg_t addr) +{ + pte_t pte = 0; + + if(!vm_enabled) + { + if(addr < memsz) + pte = PTE_E | PTE_PERM | ((addr >> PGSHIFT) << PTE_PPN_SHIFT); + } + else + { + reg_t base = ptbr; + reg_t ptd; + + int ptshift = (LEVELS-1)*PTIDXBITS; + for(reg_t i = 0; i < LEVELS; i++, ptshift -= PTIDXBITS) + { + reg_t idx = (addr >> (PGSHIFT+ptshift)) & ((1<<PTIDXBITS)-1); + + reg_t pte_addr = base + idx*sizeof(pte_t); + if(pte_addr >= memsz) + break; + + ptd = *(pte_t*)(mem+pte_addr); + if(ptd & PTE_E) + { + // if this PTE is from a larger PT, fake a leaf + // PTE so the TLB will work right + reg_t vpn = addr >> PGSHIFT; + ptd |= (vpn & ((1<<(ptshift))-1)) << PTE_PPN_SHIFT; + + // fault if physical addr is invalid + reg_t ppn = ptd >> PTE_PPN_SHIFT; + if((ppn << PGSHIFT) + (addr & (PGSIZE-1)) < memsz) + pte = ptd; + break; + } + else if(!(ptd & PTE_T)) + break; + + base = (ptd >> PTE_PPN_SHIFT) << PGSHIFT; + } + } + + return pte; +} diff --git a/riscv/mmu.h b/riscv/mmu.h new file mode 100644 index 0000000..fb186ee --- /dev/null +++ b/riscv/mmu.h @@ -0,0 +1,191 @@ +#ifndef _RISCV_MMU_H +#define _RISCV_MMU_H + +#include "decode.h" +#include "trap.h" +#include "common.h" +#include "processor.h" + +class processor_t; + +// virtual memory configuration +typedef reg_t pte_t; +const reg_t LEVELS = 4; +const reg_t PGSHIFT = 12; +const reg_t PGSIZE = 1 << PGSHIFT; +const reg_t PTIDXBITS = PGSHIFT - (sizeof(pte_t) == 8 ? 3 : 2); +const reg_t PPN_BITS = 8*sizeof(reg_t) - PGSHIFT; + +// page table entry (PTE) fields +#define PTE_T 0x001 // Entry is a page Table descriptor +#define PTE_E 0x002 // Entry is a page table Entry +#define PTE_R 0x004 // Referenced +#define PTE_D 0x008 // Dirty +#define PTE_UX 0x010 // User eXecute permission +#define PTE_UW 0x020 // User Read permission +#define PTE_UR 0x040 // User Write permission +#define PTE_SX 0x080 // Supervisor eXecute permission +#define PTE_SW 0x100 // Supervisor Read permission +#define PTE_SR 0x200 // Supervisor Write permission +#define PTE_PERM (PTE_SR | PTE_SW | PTE_SX | PTE_UR | PTE_UW | PTE_UX) +#define PTE_PERM_SHIFT 4 +#define PTE_PPN_SHIFT 12 // LSB of physical page number in the PTE + +// this class implements a processor's port into the virtual memory system. +// an MMU and instruction cache are maintained for simulator performance. +class mmu_t +{ +public: + mmu_t(char* _mem, size_t _memsz); + ~mmu_t(); + + // template for functions that load an aligned value from memory + #define load_func(type) \ + type##_t load_##type(reg_t addr) { \ + if(unlikely(addr % sizeof(type##_t))) \ + { \ + badvaddr = addr; \ + throw trap_load_address_misaligned; \ + } \ + void* paddr = translate(addr, false, false); \ + return *(type##_t*)paddr; \ + } + + // load value from memory at aligned address; zero extend to register width + load_func(uint8) + load_func(uint16) + load_func(uint32) + load_func(uint64) + + // load value from memory at aligned address; sign extend to register width + load_func(int8) + load_func(int16) + load_func(int32) + load_func(int64) + + // template for functions that store an aligned value to memory + #define store_func(type) \ + void store_##type(reg_t addr, type##_t val) { \ + if(unlikely(addr % sizeof(type##_t))) \ + { \ + badvaddr = addr; \ + throw trap_store_address_misaligned; \ + } \ + void* paddr = translate(addr, true, false); \ + *(type##_t*)paddr = val; \ + } + + // store value to memory at aligned address + store_func(uint8) + store_func(uint16) + store_func(uint32) + store_func(uint64) + + // load instruction from memory at aligned address. + // (needed because instruction alignment requirement is variable + // if RVC is supported) + // returns the instruction at the specified address, given the current + // RVC mode. func is set to a pointer to a function that knows how to + // execute the returned instruction. + insn_t __attribute__((always_inline)) load_insn(reg_t addr, bool rvc, + insn_func_t* func) + { + insn_t insn; + + #ifdef RISCV_ENABLE_RVC + if(addr % 4 == 2 && rvc) // fetch across word boundary + { + void* addr_lo = translate(addr, false, true); + insn.bits = *(uint16_t*)addr_lo; + + *func = processor_t::dispatch_table + [insn.bits % processor_t::DISPATCH_TABLE_SIZE]; + + if(!INSN_IS_RVC(insn.bits)) + { + void* addr_hi = translate(addr+2, false, true); + insn.bits |= (uint32_t)*(uint16_t*)addr_hi << 16; + } + } + else + #endif + { + reg_t idx = (addr/sizeof(insn_t)) % ICACHE_ENTRIES; + insn_t data = icache_data[idx]; + *func = icache_func[idx]; + if(likely(icache_tag[idx] == addr)) + return data; + + // the processor guarantees alignment based upon rvc mode + void* paddr = translate(addr, false, true); + insn = *(insn_t*)paddr; + + icache_tag[idx] = addr; + icache_data[idx] = insn; + icache_func[idx] = *func = processor_t::dispatch_table + [insn.bits % processor_t::DISPATCH_TABLE_SIZE]; + } + + return insn; + } + + // get the virtual address that caused a fault + reg_t get_badvaddr() { return badvaddr; } + + // get/set the page table base register + reg_t get_ptbr() { return ptbr; } + void set_ptbr(reg_t addr) { ptbr = addr & ~(PGSIZE-1); flush_tlb(); } + + // keep the MMU in sync with processor mode + void set_supervisor(bool sup) { supervisor = sup; } + void set_vm_enabled(bool en) { vm_enabled = en; } + + // flush the TLB and instruction cache + void flush_tlb(); + void flush_icache(); + +private: + char* mem; + size_t memsz; + reg_t badvaddr; + + reg_t ptbr; + bool supervisor; + bool vm_enabled; + + // implement a TLB for simulator performance + static const reg_t TLB_ENTRIES = 256; + long tlb_data[TLB_ENTRIES]; + reg_t tlb_insn_tag[TLB_ENTRIES]; + reg_t tlb_load_tag[TLB_ENTRIES]; + reg_t tlb_store_tag[TLB_ENTRIES]; + + // implement an instruction cache for simulator performance + static const reg_t ICACHE_ENTRIES = 256; + insn_t icache_data[ICACHE_ENTRIES]; + insn_func_t icache_func[ICACHE_ENTRIES]; + reg_t icache_tag[ICACHE_ENTRIES]; + + // finish translation on a TLB miss and upate the TLB + void* refill(reg_t addr, bool store, bool fetch); + + // perform a page table walk for a given virtual address + pte_t walk(reg_t addr); + + // translate a virtual address to a physical address + void* translate(reg_t addr, bool store, bool fetch) + { + reg_t idx = (addr >> PGSHIFT) % TLB_ENTRIES; + + reg_t* tlb_tag = fetch ? tlb_insn_tag : store ? tlb_store_tag :tlb_load_tag; + reg_t expected_tag = addr & ~(PGSIZE-1); + if(likely(tlb_tag[idx] == expected_tag)) + return (void*)(((long)addr & (PGSIZE-1)) | tlb_data[idx]); + + return refill(addr, store, fetch); + } + + friend class processor_t; +}; + +#endif diff --git a/riscv/opcodes.h b/riscv/opcodes.h new file mode 100644 index 0000000..b37b833 --- /dev/null +++ b/riscv/opcodes.h @@ -0,0 +1,272 @@ +DECLARE_INSN(movn, 0x6f7, 0x1ffff) +DECLARE_INSN(vfsstw, 0x150f, 0x1ffff) +DECLARE_INSN(remuw, 0x7bb, 0x1ffff) +DECLARE_INSN(fmin_d, 0x180d3, 0x1ffff) +DECLARE_INSN(vlsthu, 0x128b, 0x1ffff) +DECLARE_INSN(c_swsp, 0x8, 0x1f) +DECLARE_INSN(bltu, 0x363, 0x3ff) +DECLARE_INSN(vlsegstwu, 0xb0b, 0xfff) +DECLARE_INSN(movz, 0x2f7, 0x1ffff) +DECLARE_INSN(fcvt_lu_s, 0x9053, 0x3ff1ff) +DECLARE_INSN(fence_l_cv, 0x32f, 0x3ff) +DECLARE_INSN(fmin_s, 0x18053, 0x1ffff) +DECLARE_INSN(c_lw0, 0x12, 0x801f) +DECLARE_INSN(slliw, 0x9b, 0x3f83ff) +DECLARE_INSN(lb, 0x3, 0x3ff) +DECLARE_INSN(vlwu, 0x30b, 0x3fffff) +DECLARE_INSN(fcvt_d_l, 0xc0d3, 0x3ff1ff) +DECLARE_INSN(lh, 0x83, 0x3ff) +DECLARE_INSN(fcvt_d_w, 0xe0d3, 0x3ff1ff) +DECLARE_INSN(lw, 0x103, 0x3ff) +DECLARE_INSN(add, 0x33, 0x1ffff) +DECLARE_INSN(fcvt_d_s, 0x100d3, 0x3ff1ff) +DECLARE_INSN(fence_g_v, 0x2af, 0x3ff) +DECLARE_INSN(mfpcr, 0x17b, 0x7c1ffff) +DECLARE_INSN(c_fsd, 0x18, 0x1f) +DECLARE_INSN(fmax_d, 0x190d3, 0x1ffff) +DECLARE_INSN(bne, 0xe3, 0x3ff) +DECLARE_INSN(rdcycle, 0x277, 0x7ffffff) +DECLARE_INSN(fcvt_s_d, 0x11053, 0x3ff1ff) +DECLARE_INSN(vlh, 0x8b, 0x3fffff) +DECLARE_INSN(bgeu, 0x3e3, 0x3ff) +DECLARE_INSN(vflstd, 0x158b, 0x1ffff) +DECLARE_INSN(c_li, 0x0, 0x1f) +DECLARE_INSN(di, 0xfb, 0x7ffffff) +DECLARE_INSN(sltiu, 0x193, 0x3ff) +DECLARE_INSN(mtpcr, 0x1fb, 0xf801ffff) +DECLARE_INSN(vlb, 0xb, 0x3fffff) +DECLARE_INSN(stop, 0x177, 0xffffffff) +DECLARE_INSN(vld, 0x18b, 0x3fffff) +DECLARE_INSN(c_slli, 0x19, 0x1c1f) +DECLARE_INSN(break, 0xf7, 0xffffffff) +DECLARE_INSN(cflush, 0x2fb, 0xffffffff) +DECLARE_INSN(fcvt_s_w, 0xe053, 0x3ff1ff) +DECLARE_INSN(vflstw, 0x150b, 0x1ffff) +DECLARE_INSN(mul, 0x433, 0x1ffff) +DECLARE_INSN(c_lw, 0xa, 0x1f) +DECLARE_INSN(vlw, 0x10b, 0x3fffff) +DECLARE_INSN(vssegstw, 0x90f, 0xfff) +DECLARE_INSN(amominu_d, 0x19ab, 0x1ffff) +DECLARE_INSN(c_sdsp, 0x6, 0x1f) +DECLARE_INSN(utidx, 0x1f7, 0x7ffffff) +DECLARE_INSN(srli, 0x293, 0x3f03ff) +DECLARE_INSN(c_srli, 0x819, 0x1c1f) +DECLARE_INSN(c_ldsp, 0x4, 0x1f) +DECLARE_INSN(c_flw, 0x14, 0x1f) +DECLARE_INSN(c_srai32, 0x1419, 0x1c1f) +DECLARE_INSN(amominu_w, 0x192b, 0x1ffff) +DECLARE_INSN(divuw, 0x6bb, 0x1ffff) +DECLARE_INSN(mulw, 0x43b, 0x1ffff) +DECLARE_INSN(vssegstd, 0x98f, 0xfff) +DECLARE_INSN(srlw, 0x2bb, 0x1ffff) +DECLARE_INSN(vssegstb, 0x80f, 0xfff) +DECLARE_INSN(mftx_d, 0x1c0d3, 0x7c1ffff) +DECLARE_INSN(div, 0x633, 0x1ffff) +DECLARE_INSN(c_ld, 0x9, 0x1f) +DECLARE_INSN(mftx_s, 0x1c053, 0x7c1ffff) +DECLARE_INSN(vssegsth, 0x88f, 0xfff) +DECLARE_INSN(vvcfgivl, 0xf3, 0x3ff) +DECLARE_INSN(j, 0x67, 0x7f) +DECLARE_INSN(ei, 0x7b, 0x7ffffff) +DECLARE_INSN(fence, 0x12f, 0x3ff) +DECLARE_INSN(vsw, 0x10f, 0x3fffff) +DECLARE_INSN(fnmsub_s, 0x4b, 0x1ff) +DECLARE_INSN(vfssegstd, 0xd8f, 0xfff) +DECLARE_INSN(fcvt_l_s, 0x8053, 0x3ff1ff) +DECLARE_INSN(fle_s, 0x17053, 0x1ffff) +DECLARE_INSN(vsb, 0xf, 0x3fffff) +DECLARE_INSN(mffsr, 0x1d053, 0x7ffffff) +DECLARE_INSN(fdiv_s, 0x3053, 0x1f1ff) +DECLARE_INSN(vlstbu, 0x120b, 0x1ffff) +DECLARE_INSN(vsetvl, 0x2f3, 0x3fffff) +DECLARE_INSN(fle_d, 0x170d3, 0x1ffff) +DECLARE_INSN(fence_i, 0xaf, 0x3ff) +DECLARE_INSN(vlsegbu, 0x220b, 0x1ffff) +DECLARE_INSN(fnmsub_d, 0xcb, 0x1ff) +DECLARE_INSN(addw, 0x3b, 0x1ffff) +DECLARE_INSN(sll, 0xb3, 0x1ffff) +DECLARE_INSN(xor, 0x233, 0x1ffff) +DECLARE_INSN(sub, 0x10033, 0x1ffff) +DECLARE_INSN(eret, 0x27b, 0xffffffff) +DECLARE_INSN(blt, 0x263, 0x3ff) +DECLARE_INSN(vsstw, 0x110f, 0x1ffff) +DECLARE_INSN(mtfsr, 0x1f053, 0x3fffff) +DECLARE_INSN(vssth, 0x108f, 0x1ffff) +DECLARE_INSN(rem, 0x733, 0x1ffff) +DECLARE_INSN(srliw, 0x29b, 0x3f83ff) +DECLARE_INSN(lui, 0x37, 0x7f) +DECLARE_INSN(vsstb, 0x100f, 0x1ffff) +DECLARE_INSN(fcvt_s_lu, 0xd053, 0x3ff1ff) +DECLARE_INSN(vsstd, 0x118f, 0x1ffff) +DECLARE_INSN(addi, 0x13, 0x3ff) +DECLARE_INSN(vfmst, 0x1173, 0x1ffff) +DECLARE_INSN(mulh, 0x4b3, 0x1ffff) +DECLARE_INSN(fmul_s, 0x2053, 0x1f1ff) +DECLARE_INSN(vlsegsthu, 0xa8b, 0xfff) +DECLARE_INSN(srai, 0x10293, 0x3f03ff) +DECLARE_INSN(amoand_d, 0x9ab, 0x1ffff) +DECLARE_INSN(flt_d, 0x160d3, 0x1ffff) +DECLARE_INSN(sraw, 0x102bb, 0x1ffff) +DECLARE_INSN(fmul_d, 0x20d3, 0x1f1ff) +DECLARE_INSN(ld, 0x183, 0x3ff) +DECLARE_INSN(ori, 0x313, 0x3ff) +DECLARE_INSN(flt_s, 0x16053, 0x1ffff) +DECLARE_INSN(addiw, 0x1b, 0x3ff) +DECLARE_INSN(amoand_w, 0x92b, 0x1ffff) +DECLARE_INSN(feq_s, 0x15053, 0x1ffff) +DECLARE_INSN(fsgnjx_d, 0x70d3, 0x1ffff) +DECLARE_INSN(sra, 0x102b3, 0x1ffff) +DECLARE_INSN(c_lwsp, 0x5, 0x1f) +DECLARE_INSN(bge, 0x2e3, 0x3ff) +DECLARE_INSN(c_add3, 0x1c, 0x31f) +DECLARE_INSN(sraiw, 0x1029b, 0x3f83ff) +DECLARE_INSN(vssegd, 0x218f, 0x1ffff) +DECLARE_INSN(srl, 0x2b3, 0x1ffff) +DECLARE_INSN(vfmts, 0x1973, 0x1ffff) +DECLARE_INSN(fsgnjx_s, 0x7053, 0x1ffff) +DECLARE_INSN(vfmsv, 0x973, 0x3fffff) +DECLARE_INSN(feq_d, 0x150d3, 0x1ffff) +DECLARE_INSN(fcvt_d_wu, 0xf0d3, 0x3ff1ff) +DECLARE_INSN(vmts, 0x1873, 0x1ffff) +DECLARE_INSN(or, 0x333, 0x1ffff) +DECLARE_INSN(rdinstret, 0xa77, 0x7ffffff) +DECLARE_INSN(fcvt_wu_d, 0xb0d3, 0x3ff1ff) +DECLARE_INSN(subw, 0x1003b, 0x1ffff) +DECLARE_INSN(jalr_c, 0x6b, 0x3ff) +DECLARE_INSN(fmax_s, 0x19053, 0x1ffff) +DECLARE_INSN(amomaxu_d, 0x1dab, 0x1ffff) +DECLARE_INSN(c_slliw, 0x1819, 0x1c1f) +DECLARE_INSN(jalr_j, 0x16b, 0x3ff) +DECLARE_INSN(c_fld, 0x15, 0x1f) +DECLARE_INSN(vlstw, 0x110b, 0x1ffff) +DECLARE_INSN(vlsth, 0x108b, 0x1ffff) +DECLARE_INSN(xori, 0x213, 0x3ff) +DECLARE_INSN(jalr_r, 0xeb, 0x3ff) +DECLARE_INSN(amomaxu_w, 0x1d2b, 0x1ffff) +DECLARE_INSN(fcvt_wu_s, 0xb053, 0x3ff1ff) +DECLARE_INSN(vlstb, 0x100b, 0x1ffff) +DECLARE_INSN(vlstd, 0x118b, 0x1ffff) +DECLARE_INSN(c_ld0, 0x8012, 0x801f) +DECLARE_INSN(rdtime, 0x677, 0x7ffffff) +DECLARE_INSN(andi, 0x393, 0x3ff) +DECLARE_INSN(c_srli32, 0xc19, 0x1c1f) +DECLARE_INSN(fsgnjn_d, 0x60d3, 0x1ffff) +DECLARE_INSN(fnmadd_s, 0x4f, 0x1ff) +DECLARE_INSN(jal, 0x6f, 0x7f) +DECLARE_INSN(lwu, 0x303, 0x3ff) +DECLARE_INSN(vlsegstbu, 0xa0b, 0xfff) +DECLARE_INSN(c_beq, 0x10, 0x1f) +DECLARE_INSN(vlhu, 0x28b, 0x3fffff) +DECLARE_INSN(vfsstd, 0x158f, 0x1ffff) +DECLARE_INSN(c_bne, 0x11, 0x1f) +DECLARE_INSN(fnmadd_d, 0xcf, 0x1ff) +DECLARE_INSN(fence_g_cv, 0x3af, 0x3ff) +DECLARE_INSN(amoadd_d, 0x1ab, 0x1ffff) +DECLARE_INSN(c_sw, 0xd, 0x1f) +DECLARE_INSN(amomax_w, 0x152b, 0x1ffff) +DECLARE_INSN(c_move, 0x2, 0x801f) +DECLARE_INSN(fmovn, 0xef7, 0x1ffff) +DECLARE_INSN(c_fsw, 0x16, 0x1f) +DECLARE_INSN(c_j, 0x8002, 0x801f) +DECLARE_INSN(mulhsu, 0x533, 0x1ffff) +DECLARE_INSN(c_sd, 0xc, 0x1f) +DECLARE_INSN(amoadd_w, 0x12b, 0x1ffff) +DECLARE_INSN(fcvt_d_lu, 0xd0d3, 0x3ff1ff) +DECLARE_INSN(amomax_d, 0x15ab, 0x1ffff) +DECLARE_INSN(fcvt_w_d, 0xa0d3, 0x3ff1ff) +DECLARE_INSN(fmovz, 0xaf7, 0x1ffff) +DECLARE_INSN(c_or3, 0x21c, 0x31f) +DECLARE_INSN(vmvv, 0x73, 0x3fffff) +DECLARE_INSN(vfssegstw, 0xd0f, 0xfff) +DECLARE_INSN(slt, 0x133, 0x1ffff) +DECLARE_INSN(mxtf_d, 0x1e0d3, 0x3fffff) +DECLARE_INSN(sllw, 0xbb, 0x1ffff) +DECLARE_INSN(amoor_d, 0xdab, 0x1ffff) +DECLARE_INSN(slti, 0x113, 0x3ff) +DECLARE_INSN(remu, 0x7b3, 0x1ffff) +DECLARE_INSN(flw, 0x107, 0x3ff) +DECLARE_INSN(remw, 0x73b, 0x1ffff) +DECLARE_INSN(sltu, 0x1b3, 0x1ffff) +DECLARE_INSN(slli, 0x93, 0x3f03ff) +DECLARE_INSN(c_and3, 0x31c, 0x31f) +DECLARE_INSN(vssegw, 0x210f, 0x1ffff) +DECLARE_INSN(amoor_w, 0xd2b, 0x1ffff) +DECLARE_INSN(vsd, 0x18f, 0x3fffff) +DECLARE_INSN(beq, 0x63, 0x3ff) +DECLARE_INSN(fld, 0x187, 0x3ff) +DECLARE_INSN(mxtf_s, 0x1e053, 0x3fffff) +DECLARE_INSN(fsub_s, 0x1053, 0x1f1ff) +DECLARE_INSN(and, 0x3b3, 0x1ffff) +DECLARE_INSN(vtcfgivl, 0x1f3, 0x3ff) +DECLARE_INSN(lbu, 0x203, 0x3ff) +DECLARE_INSN(vf, 0x3f3, 0xf80003ff) +DECLARE_INSN(vlsegstw, 0x90b, 0xfff) +DECLARE_INSN(syscall, 0x77, 0xffffffff) +DECLARE_INSN(fsgnj_s, 0x5053, 0x1ffff) +DECLARE_INSN(c_addi, 0x1, 0x1f) +DECLARE_INSN(vfmvv, 0x173, 0x3fffff) +DECLARE_INSN(vlstwu, 0x130b, 0x1ffff) +DECLARE_INSN(c_sub3, 0x11c, 0x31f) +DECLARE_INSN(vsh, 0x8f, 0x3fffff) +DECLARE_INSN(vlsegstb, 0x80b, 0xfff) +DECLARE_INSN(vlsegstd, 0x98b, 0xfff) +DECLARE_INSN(vflsegd, 0x258b, 0x1ffff) +DECLARE_INSN(vflsegw, 0x250b, 0x1ffff) +DECLARE_INSN(vlsegsth, 0x88b, 0xfff) +DECLARE_INSN(fsgnj_d, 0x50d3, 0x1ffff) +DECLARE_INSN(vflsegstw, 0xd0b, 0xfff) +DECLARE_INSN(c_sub, 0x801a, 0x801f) +DECLARE_INSN(mulhu, 0x5b3, 0x1ffff) +DECLARE_INSN(fcvt_l_d, 0x80d3, 0x3ff1ff) +DECLARE_INSN(vmsv, 0x873, 0x3fffff) +DECLARE_INSN(vmst, 0x1073, 0x1ffff) +DECLARE_INSN(fadd_d, 0xd3, 0x1f1ff) +DECLARE_INSN(fcvt_s_wu, 0xf053, 0x3ff1ff) +DECLARE_INSN(rdnpc, 0x26b, 0x7ffffff) +DECLARE_INSN(fcvt_s_l, 0xc053, 0x3ff1ff) +DECLARE_INSN(vflsegstd, 0xd8b, 0xfff) +DECLARE_INSN(c_add, 0x1a, 0x801f) +DECLARE_INSN(fcvt_lu_d, 0x90d3, 0x3ff1ff) +DECLARE_INSN(vfld, 0x58b, 0x3fffff) +DECLARE_INSN(fsub_d, 0x10d3, 0x1f1ff) +DECLARE_INSN(fmadd_s, 0x43, 0x1ff) +DECLARE_INSN(fcvt_w_s, 0xa053, 0x3ff1ff) +DECLARE_INSN(vssegh, 0x208f, 0x1ffff) +DECLARE_INSN(fsqrt_s, 0x4053, 0x3ff1ff) +DECLARE_INSN(c_srai, 0x1019, 0x1c1f) +DECLARE_INSN(amomin_w, 0x112b, 0x1ffff) +DECLARE_INSN(fsgnjn_s, 0x6053, 0x1ffff) +DECLARE_INSN(c_slli32, 0x419, 0x1c1f) +DECLARE_INSN(vlsegwu, 0x230b, 0x1ffff) +DECLARE_INSN(vfsw, 0x50f, 0x3fffff) +DECLARE_INSN(amoswap_d, 0x5ab, 0x1ffff) +DECLARE_INSN(fence_l_v, 0x22f, 0x3ff) +DECLARE_INSN(fsqrt_d, 0x40d3, 0x3ff1ff) +DECLARE_INSN(vflw, 0x50b, 0x3fffff) +DECLARE_INSN(fdiv_d, 0x30d3, 0x1f1ff) +DECLARE_INSN(fmadd_d, 0xc3, 0x1ff) +DECLARE_INSN(divw, 0x63b, 0x1ffff) +DECLARE_INSN(amomin_d, 0x11ab, 0x1ffff) +DECLARE_INSN(divu, 0x6b3, 0x1ffff) +DECLARE_INSN(amoswap_w, 0x52b, 0x1ffff) +DECLARE_INSN(vfsd, 0x58f, 0x3fffff) +DECLARE_INSN(fadd_s, 0x53, 0x1f1ff) +DECLARE_INSN(vlsegb, 0x200b, 0x1ffff) +DECLARE_INSN(fsd, 0x1a7, 0x3ff) +DECLARE_INSN(vlsegd, 0x218b, 0x1ffff) +DECLARE_INSN(vlsegh, 0x208b, 0x1ffff) +DECLARE_INSN(sw, 0x123, 0x3ff) +DECLARE_INSN(fmsub_s, 0x47, 0x1ff) +DECLARE_INSN(vfssegw, 0x250f, 0x1ffff) +DECLARE_INSN(c_addiw, 0x1d, 0x1f) +DECLARE_INSN(lhu, 0x283, 0x3ff) +DECLARE_INSN(sh, 0xa3, 0x3ff) +DECLARE_INSN(vlsegw, 0x210b, 0x1ffff) +DECLARE_INSN(fsw, 0x127, 0x3ff) +DECLARE_INSN(vlbu, 0x20b, 0x3fffff) +DECLARE_INSN(sb, 0x23, 0x3ff) +DECLARE_INSN(fmsub_d, 0xc7, 0x1ff) +DECLARE_INSN(vlseghu, 0x228b, 0x1ffff) +DECLARE_INSN(vssegb, 0x200f, 0x1ffff) +DECLARE_INSN(vfssegd, 0x258f, 0x1ffff) +DECLARE_INSN(sd, 0x1a3, 0x3ff) diff --git a/riscv/processor.cc b/riscv/processor.cc new file mode 100644 index 0000000..2a53cca --- /dev/null +++ b/riscv/processor.cc @@ -0,0 +1,240 @@ +#include "processor.h" +#include "common.h" +#include "config.h" +#include "sim.h" +#include <bfd.h> +#include <dis-asm.h> +#include <cmath> +#include <cstdlib> +#include <iostream> +#include <assert.h> + +processor_t::processor_t(sim_t* _sim, mmu_t* _mmu, uint32_t _id) + : sim(*_sim), mmu(*_mmu), id(_id), utidx(0) +{ + reset(); + + // create microthreads + for (int i=0; i<MAX_UTS; i++) + uts[i] = new processor_t(&sim, &mmu, id, i); +} + +processor_t::processor_t(sim_t* _sim, mmu_t* _mmu, uint32_t _id, + uint32_t _utidx) + : sim(*_sim), mmu(*_mmu), id(_id), utidx(_utidx) +{ + reset(); + set_sr(sr | SR_EF | SR_EV); + + // microthreads don't possess their own microthreads + for (int i=0; i<MAX_UTS; i++) + uts[i] = NULL; +} + +processor_t::~processor_t() +{ +} + +void processor_t::reset() +{ + run = false; + + // the ISA guarantees the following initial state + set_sr(SR_S | SR_SX); + pc = 0; + + // the following state is undefined upon boot-up, + // but we zero it for determinism + memset(XPR,0,sizeof(XPR)); + memset(FPR,0,sizeof(FPR)); + + evec = 0; + epc = 0; + badvaddr = 0; + cause = 0; + pcr_k0 = 0; + pcr_k1 = 0; + count = 0; + compare = 0; + cycle = 0; + set_fsr(0); + + // vector stuff + vecbanks = 0xff; + vecbanks_count = 8; + utidx = -1; + vlmax = 32; + vl = 0; + nxfpr_bank = 256; + nxpr_use = 32; + nfpr_use = 32; +} + +void processor_t::set_sr(uint32_t val) +{ + sr = val & ~SR_ZERO; // clear SR bits that read as zero + +#ifndef RISCV_ENABLE_64BIT + sr &= ~(SR_SX | SR_UX); // SX=UX=0 for RV32 implementations +#endif +#ifndef RISCV_ENABLE_FPU + sr &= ~SR_EF; +#endif +#ifndef RISCV_ENABLE_RVC + sr &= ~SR_EC; +#endif +#ifndef RISCV_ENABLE_VEC + sr &= ~SR_EV; +#endif + + // update MMU state and flush TLB + mmu.set_vm_enabled(sr & SR_VM); + mmu.set_supervisor(sr & SR_S); + mmu.flush_tlb(); + + // set the fixed-point register length + xprlen = ((sr & SR_S) ? (sr & SR_SX) : (sr & SR_UX)) ? 64 : 32; +} + +void processor_t::set_fsr(uint32_t val) +{ + fsr = val & ~FSR_ZERO; // clear FSR bits that read as zero +} + +void processor_t::vcfg() +{ + if (nxpr_use + nfpr_use < 2) + vlmax = nxfpr_bank * vecbanks_count; + else + vlmax = (nxfpr_bank / (nxpr_use + nfpr_use - 1)) * vecbanks_count; + + vlmax = std::min(vlmax, MAX_UTS); +} + +void processor_t::setvl(int vlapp) +{ + vl = std::min(vlmax, vlapp); +} + +void processor_t::take_interrupt() +{ + uint32_t interrupts = (cause & CAUSE_IP) >> CAUSE_IP_SHIFT; + interrupts &= (sr & SR_IM) >> SR_IM_SHIFT; + + if(interrupts && (sr & SR_ET)) + throw trap_interrupt; +} + +void processor_t::step(size_t n, bool noisy) +{ + if(!run) + return; + + size_t i = 0; + while(1) try + { + take_interrupt(); + + mmu_t& _mmu = mmu; + insn_t insn; + insn_func_t func; + reg_t npc = pc; + + // execute_insn fetches and executes one instruction + #define execute_insn(noisy) \ + do { \ + insn = _mmu.load_insn(npc, sr & SR_EC, &func); \ + if(noisy) disasm(insn,pc); \ + npc = func(this, insn, npc); \ + pc = npc; \ + } while(0) + + if(noisy) for( ; i < n; i++) // print out instructions as we go + execute_insn(true); + else + { + // unrolled for speed + for( ; n > 3 && i < n-3; i+=4) + { + execute_insn(false); + execute_insn(false); + execute_insn(false); + execute_insn(false); + } + for( ; i < n; i++) + execute_insn(false); + } + + break; + } + catch(trap_t t) + { + // an exception occurred in the target processor + i++; + take_trap(t,noisy); + } + catch(vt_command_t cmd) + { + // this microthread has finished + i++; + assert(cmd == vt_command_stop); + break; + } + catch(halt_t t) + { + // sleep until IPI + reset(); + return; + } + + cycle += i; + + // update timer and possibly register a timer interrupt + uint32_t old_count = count; + count += i; + if(old_count < compare && uint64_t(old_count) + i >= compare) + cause |= 1 << (TIMER_IRQ+CAUSE_IP_SHIFT); +} + +void processor_t::take_trap(trap_t t, bool noisy) +{ + if(noisy) + printf("core %3d: trap %s, pc 0x%016llx\n", + id, trap_name(t), (unsigned long long)pc); + + // switch to supervisor, set previous supervisor bit, disable traps + set_sr((((sr & ~SR_ET) | SR_S) & ~SR_PS) | ((sr & SR_S) ? SR_PS : 0)); + cause = (cause & ~CAUSE_EXCCODE) | (t << CAUSE_EXCCODE_SHIFT); + epc = pc; + pc = evec; + badvaddr = mmu.get_badvaddr(); +} + +void processor_t::deliver_ipi() +{ + cause |= 1 << (IPI_IRQ+CAUSE_IP_SHIFT); + run = true; +} + +void processor_t::disasm(insn_t insn, reg_t pc) +{ + printf("core %3d: 0x%016llx (0x%08x) ",id,(unsigned long long)pc,insn.bits); + + #ifdef RISCV_HAVE_LIBOPCODES + disassemble_info info; + INIT_DISASSEMBLE_INFO(info, stdout, fprintf); + info.flavour = bfd_target_unknown_flavour; + info.arch = bfd_arch_mips; + info.mach = 101; // XXX bfd_mach_mips_riscv requires modified bfd.h + info.endian = BFD_ENDIAN_LITTLE; + info.buffer = (bfd_byte*)&insn; + info.buffer_length = sizeof(insn); + info.buffer_vma = pc; + + int ret = print_insn_little_mips(pc, &info); + assert(ret == insn_length(insn.bits)); + #else + printf("unknown"); + #endif + printf("\n"); +} diff --git a/riscv/processor.h b/riscv/processor.h new file mode 100644 index 0000000..3bc1177 --- /dev/null +++ b/riscv/processor.h @@ -0,0 +1,89 @@ +#ifndef _RISCV_PROCESSOR_H +#define _RISCV_PROCESSOR_H + +#include "decode.h" +#include <cstring> +#include "trap.h" + +#define MAX_UTS 2048 + +class processor_t; +class mmu_t; +typedef reg_t (*insn_func_t)(processor_t*, insn_t, reg_t); +class sim_t; + +// this class represents one processor in a RISC-V machine. +class processor_t +{ +public: + processor_t(sim_t* _sim, mmu_t* _mmu, uint32_t _id); + ~processor_t(); + + void step(size_t n, bool noisy); // run for n cycles + void deliver_ipi(); // register an interprocessor interrupt + +private: + sim_t& sim; + mmu_t& mmu; // main memory is always accessed via the mmu + + // user-visible architected state + reg_t XPR[NXPR]; + freg_t FPR[NFPR]; + reg_t pc; + uint32_t fsr; + + // counters + reg_t cycle; + + // privileged control registers + reg_t epc; + reg_t badvaddr; + reg_t cause; + reg_t evec; + reg_t pcr_k0; + reg_t pcr_k1; + uint32_t id; + uint32_t sr; // only modify the status register using set_sr() + uint32_t count; + uint32_t compare; + + // # of bits in an XPR (32 or 64). (redundant with sr) + int xprlen; + + // is this processor running? (deliver_ipi() sets this) + bool run; + + // functions + void reset(); // resets architected state; halts processor if it was running + void take_interrupt(); // take a trap if any interrupts are pending + void set_sr(uint32_t val); // set the status register + void set_fsr(uint32_t val); // set the floating-point status register + void take_trap(trap_t t, bool noisy); // take an exception + void disasm(insn_t insn, reg_t pc); // disassemble and print an instruction + + // vector stuff + void vcfg(); + void setvl(int vlapp); + + reg_t vecbanks; + uint32_t vecbanks_count; + + bool utmode; + uint32_t utidx; + int vlmax; + int vl; + int nxfpr_bank; + int nxpr_use; + int nfpr_use; + processor_t* uts[MAX_UTS]; + + // this constructor is used for each of the uts + processor_t(sim_t* _sim, mmu_t* _mmu, uint32_t _id, uint32_t _utidx); + + friend class sim_t; + friend class mmu_t; + + #include "dispatch.h" +}; + +#endif diff --git a/riscv/riscv-isa-run.cc b/riscv/riscv-isa-run.cc new file mode 100644 index 0000000..a0af8de --- /dev/null +++ b/riscv/riscv-isa-run.cc @@ -0,0 +1,56 @@ +#include <stdio.h> +#include "sim.h" +#include "htif.h" + +static void help() +{ + fprintf(stderr, "usage: riscv-isa-run -f <fd> -t <fd> [additional options]\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -f <fd> From-host pipe file descriptor\n"); + fprintf(stderr, " -t <fd> To-host pipe file descriptor\n"); + fprintf(stderr, " -p <n> Simulate <n> processors\n"); + fprintf(stderr, " -d Interactive debug mode\n"); + exit(1); +} + +int main(int argc, char** argv) +{ + bool debug = false; + int nprocs = 1; + int fromhost_fd = -1, tohost_fd = -1; + + // parse command-line arguments + for(int c; (c = getopt(argc,argv,"hdp:f:t:")) != -1; ) + { + switch(c) + { + case 'd': + debug = true; + break; + case 'p': + nprocs = atoi(optarg); + break; + case 'f': + fromhost_fd = atoi(optarg); + break; + case 't': + tohost_fd = atoi(optarg); + break; + default: + fprintf(stderr, "unknown option: -%c", optopt); + case 'h': + help(); + } + } + + // we require -f and -t to be specified so we can communicate with the host + if(fromhost_fd == -1 || tohost_fd == -1) + help(); + + // initialize host-target interface + htif_t htif(tohost_fd, fromhost_fd); + + // initalize simulator and run to completion + sim_t s(nprocs, &htif); + s.run(debug); +} diff --git a/riscv/riscv.ac b/riscv/riscv.ac new file mode 100644 index 0000000..5766d6d --- /dev/null +++ b/riscv/riscv.ac @@ -0,0 +1,32 @@ +AC_ARG_ENABLE([fpu], AS_HELP_STRING([--disable-fpu], [Disable floating-point])) +AS_IF([test "x$enable_fpu" != "xno"], [ + AC_DEFINE([RISCV_ENABLE_FPU],,[Define if floating-point instructions are supported]) +]) + +AC_ARG_ENABLE([64bit], AS_HELP_STRING([--disable-64bit], [Disable 64-bit mode])) +AS_IF([test "x$enable_64bit" != "xno"], [ + AC_DEFINE([RISCV_ENABLE_64BIT],,[Define if 64-bit mode is supported]) +]) + +AC_ARG_ENABLE([rvc], AS_HELP_STRING([--enable-rvc], [Enable instruction compression])) +AS_IF([test "x$enable_rvc" = "xyes"], [ + AC_DEFINE([RISCV_ENABLE_RVC],,[Define if instruction compression is supported]) +]) + +AC_ARG_ENABLE([vec], AS_HELP_STRING([--disable-vec], [Disable vector processor])) +AS_IF([test "x$enable_vec" != "xno"], [ + AC_DEFINE([RISCV_ENABLE_VEC],,[Define if vector processor is supported]) +]) + +libopc=`dirname \`which riscv-gcc\``/../`$ac_config_guess`/riscv/lib/libopcodes.a +AC_CHECK_FILES([$libopc],[have_libopcodes="yes"],[have_libopcodes="no"]) + +AC_SEARCH_LIBS([bfd_init],[bfd],[],[have_libopcodes="no"]) + +AS_IF([test "$have_libopcodes" = "no"],[ + AC_MSG_WARN([Could not find opcodes library]) + AC_MSG_WARN([Build will not include disassembly support]) +],[ + LIBS="$libopc $LIBS" + AC_DEFINE([RISCV_HAVE_LIBOPCODES],,[Define if libopcodes exists]) +]) diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in new file mode 100644 index 0000000..50dc76a --- /dev/null +++ b/riscv/riscv.mk.in @@ -0,0 +1,50 @@ +riscv_subproject_deps = \ + softfloat_riscv \ + softfloat \ + +riscv_hdrs = \ + htif.h \ + common.h \ + decode.h \ + mmu.h \ + processor.h \ + sim.h \ + trap.h \ + opcodes.h \ + insn_header.h \ + dispatch.h \ + +NDISPATCH := 10 +DISPATCH_SRCS := \ + dispatch0.cc \ + dispatch1.cc \ + dispatch2.cc \ + dispatch3.cc \ + dispatch4.cc \ + dispatch5.cc \ + dispatch6.cc \ + dispatch7.cc \ + dispatch8.cc \ + dispatch9.cc \ + dispatch10.cc \ + +$(DISPATCH_SRCS): %.cc: dispatch $(wildcard insns/*.h) $(riscv_hdrs) + $< $(subst dispatch,,$(subst .cc,,$@)) $(NDISPATCH) 1024 < $(src_dir)/riscv/opcodes.h > $@ + +$(src_dir)/riscv/dispatch.h: %.h: dispatch + $< $(NDISPATCH) 1024 < $(src_dir)/riscv/opcodes.h > $@ + +riscv_srcs = \ + htif.cc \ + processor.cc \ + sim.cc \ + interactive.cc \ + trap.cc \ + icsim.cc \ + mmu.cc \ + $(DISPATCH_SRCS) \ + +riscv_test_srcs = + +riscv_install_prog_srcs = \ + riscv-isa-run.cc \ diff --git a/riscv/sim.cc b/riscv/sim.cc new file mode 100644 index 0000000..85d0995 --- /dev/null +++ b/riscv/sim.cc @@ -0,0 +1,92 @@ +#include "sim.h" +#include "htif.h" +#include <sys/mman.h> +#include <map> +#include <iostream> +#include <climits> +#include <assert.h> + +sim_t::sim_t(int _nprocs, htif_t* _htif) + : htif(_htif), + procs(_nprocs), + running(false) +{ + // allocate target machine's memory, shrinking it as necessary + // until the allocation succeeds + + size_t memsz0 = sizeof(size_t) == 8 ? 0x100000000ULL : 0x70000000UL; + size_t quantum = std::max(PGSIZE, (reg_t)sysconf(_SC_PAGESIZE)); + memsz0 = memsz0/quantum*quantum; + + memsz = memsz0; + mem = (char*)mmap64(NULL, memsz, PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); + + if(mem == MAP_FAILED) + { + while(mem == MAP_FAILED && (memsz = memsz*10/11/quantum*quantum)) + mem = (char*)mmap64(NULL, memsz, PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); + assert(mem != MAP_FAILED); + fprintf(stderr, "warning: only got %lu bytes of target mem (wanted %lu)\n", + (unsigned long)memsz, (unsigned long)memsz0); + } + + mmu = new mmu_t(mem, memsz); + + for(size_t i = 0; i < num_cores(); i++) + procs[i] = new processor_t(this, new mmu_t(mem, memsz), i); + + htif->init(this); +} + +sim_t::~sim_t() +{ + for(size_t i = 0; i < num_cores(); i++) + { + mmu_t* pmmu = &procs[i]->mmu; + delete procs[i]; + delete pmmu; + } + delete mmu; + munmap(mem, memsz); +} + +void sim_t::set_tohost(reg_t val) +{ + fromhost = 0; + tohost = val; +} + +reg_t sim_t::get_fromhost() +{ + htif->wait_for_fromhost_write(); + return fromhost; +} + +void sim_t::send_ipi(reg_t who) +{ + if(who < num_cores()) + procs[who]->deliver_ipi(); +} + +void sim_t::run(bool debug) +{ + htif->wait_for_start(); + + // start core 0 + send_ipi(0); + + for(running = true; running; ) + { + if(!debug) + step_all(100,100,false); + else + interactive(); + } +} + +void sim_t::step_all(size_t n, size_t interleave, bool noisy) +{ + for(size_t j = 0; j < n; j+=interleave) + for(int i = 0; i < (int)num_cores(); i++) + procs[i]->step(interleave,noisy); +} diff --git a/riscv/sim.h b/riscv/sim.h new file mode 100644 index 0000000..c4058d3 --- /dev/null +++ b/riscv/sim.h @@ -0,0 +1,82 @@ +#ifndef _RISCV_SIM_H +#define _RISCV_SIM_H + +#include <vector> +#include <string> +#include "processor.h" +#include "mmu.h" + +class htif_t; + +// this class encapsulates the processors and memory in a RISC-V machine. +class sim_t +{ +public: + sim_t(int _nprocs, htif_t* _htif); + ~sim_t(); + + // run the simulation to completion + void run(bool debug); + + // communicate with the host machine + void set_tohost(reg_t val); + reg_t get_fromhost(); + + // deliver an IPI to a specific processor + void send_ipi(reg_t who); + + // returns the number of processors in this simulator + size_t num_cores() { return procs.size(); } + +private: + htif_t* htif; + + // global registers for communication with host machine + reg_t tohost; + reg_t fromhost; + + // main memory, shared between processors + char* mem; + size_t memsz; // memory size in bytes + mmu_t* mmu; // debug port into main memory + + // processors + std::vector<processor_t*> procs; + + // terminate the simulation loop after the current iteration + void stop() { running = false; } + bool running; + + // run each processor for n instructions; interleave instructions are + // run on a processor before moving on to the next processor. + // interleave must divide n. + // if noisy, print out the instructions as they execute. + void step_all(size_t n, size_t interleave, bool noisy); + + // presents a prompt for introspection into the simulation + void interactive(); + + // functions that help implement interactive() + void interactive_quit(const std::string& cmd, const std::vector<std::string>& args); + void interactive_run(const std::string& cmd, const std::vector<std::string>& args, bool noisy); + void interactive_run_noisy(const std::string& cmd, const std::vector<std::string>& args); + void interactive_run_silent(const std::string& cmd, const std::vector<std::string>& args); + void interactive_run_proc(const std::string& cmd, const std::vector<std::string>& args, bool noisy); + void interactive_run_proc_noisy(const std::string& cmd, const std::vector<std::string>& args); + void interactive_run_proc_silent(const std::string& cmd, const std::vector<std::string>& args); + void interactive_reg(const std::string& cmd, const std::vector<std::string>& args); + void interactive_fregs(const std::string& cmd, const std::vector<std::string>& args); + void interactive_fregd(const std::string& cmd, const std::vector<std::string>& args); + void interactive_mem(const std::string& cmd, const std::vector<std::string>& args); + void interactive_str(const std::string& cmd, const std::vector<std::string>& args); + void interactive_until(const std::string& cmd, const std::vector<std::string>& args); + reg_t get_reg(const std::vector<std::string>& args); + reg_t get_freg(const std::vector<std::string>& args); + reg_t get_mem(const std::vector<std::string>& args); + reg_t get_pc(const std::vector<std::string>& args); + reg_t get_tohost(const std::vector<std::string>& args); + + friend class htif_t; +}; + +#endif diff --git a/riscv/trap.cc b/riscv/trap.cc new file mode 100644 index 0000000..d873a19 --- /dev/null +++ b/riscv/trap.cc @@ -0,0 +1,10 @@ +#include "trap.h" + +const char* trap_name(trap_t t) +{ + #define DECLARE_TRAP(x) "trap_"#x + static const char* names[] = { TRAP_LIST }; + #undef DECLARE_TRAP + + return (unsigned)t >= sizeof(names)/sizeof(names[0]) ? "unknown" : names[t]; +} diff --git a/riscv/trap.h b/riscv/trap.h new file mode 100644 index 0000000..ad5491a --- /dev/null +++ b/riscv/trap.h @@ -0,0 +1,44 @@ +#ifndef _RISCV_TRAP_H +#define _RISCV_TRAP_H + +#define TRAP_LIST \ + DECLARE_TRAP(instruction_address_misaligned), \ + DECLARE_TRAP(instruction_access_fault), \ + DECLARE_TRAP(illegal_instruction), \ + DECLARE_TRAP(privileged_instruction), \ + DECLARE_TRAP(fp_disabled), \ + DECLARE_TRAP(interrupt), \ + DECLARE_TRAP(syscall), \ + DECLARE_TRAP(breakpoint), \ + DECLARE_TRAP(load_address_misaligned), \ + DECLARE_TRAP(store_address_misaligned), \ + DECLARE_TRAP(load_access_fault), \ + DECLARE_TRAP(store_access_fault), \ + DECLARE_TRAP(vector_disabled), \ + DECLARE_TRAP(vector_bank), \ + DECLARE_TRAP(vector_illegal_instruction), \ + DECLARE_TRAP(reserved1), \ + DECLARE_TRAP(reserved2), \ + DECLARE_TRAP(reserved3), \ + DECLARE_TRAP(int0), \ + DECLARE_TRAP(int1), \ + DECLARE_TRAP(int2), \ + DECLARE_TRAP(int3), \ + DECLARE_TRAP(int4), \ + DECLARE_TRAP(int5), \ + DECLARE_TRAP(int6), \ + DECLARE_TRAP(int7), \ + +#define DECLARE_TRAP(x) trap_##x +enum trap_t +{ + TRAP_LIST + NUM_TRAPS +}; +#undef DECLARE_TRAP + +struct halt_t {}; // thrown to stop the processor from running + +extern "C" const char* trap_name(trap_t t); + +#endif |