X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=riscv%2Fdecode.h;h=8e506e264ce2617fee9ac81c4b88ef11e6deccff;hb=e85cb99c5e042ebce78f64213677a48ee7ba0491;hp=d0b92ddc470f7ff8f858b50b6bb4e56cccd827a5;hpb=68591c3c451dca19d4751eb62861367f2a3e58b5;p=riscv-isa-sim.git diff --git a/riscv/decode.h b/riscv/decode.h index d0b92dd..8e506e2 100644 --- a/riscv/decode.h +++ b/riscv/decode.h @@ -1,10 +1,19 @@ +// See LICENSE for license details. + #ifndef _RISCV_DECODE_H #define _RISCV_DECODE_H +#if (-1 != ~0) || ((-1 >> 1) != -1) +# error spike requires a two''s-complement c++ implementation +#endif + #define __STDC_LIMIT_MACROS #include - +#include +#include "encoding.h" #include "config.h" +#include "common.h" +#include typedef int int128_t __attribute__((mode(TI))); typedef unsigned int uint128_t __attribute__((mode(TI))); @@ -13,41 +22,8 @@ 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_PS 0x0000000000000004ULL -#define SR_S 0x0000000000000008ULL -#define SR_EF 0x0000000000000010ULL -#define SR_UX 0x0000000000000020ULL -#define SR_SX 0x0000000000000040ULL -#define SR_IM 0x000000000000FF00ULL -#define SR_ZERO ~(SR_ET | SR_PS | SR_S | SR_EF | SR_UX | SR_SX | SR_IM) -#define SR_IM_SHIFT 8 -#define TIMER_IRQ 7 - -#define CAUSE_EXCCODE 0x000000FF -#define CAUSE_IP 0x0000FF00 -#define CAUSE_EXCCODE_SHIFT 0 -#define CAUSE_IP_SHIFT 8 +const int NXPR = 32; +const int NFPR = 32; #define FP_RD_NE 0 #define FP_RD_0 1 @@ -61,7 +37,7 @@ const int JUMP_ALIGN_BITS = 1; #define FPEXC_NX 0x01 #define FPEXC_UF 0x02 #define FPEXC_OF 0x04 -#define FPEXC_DZ 0x02 +#define FPEXC_DZ 0x08 #define FPEXC_NV 0x10 #define FSR_AEXC_SHIFT 0 @@ -72,132 +48,129 @@ const int JUMP_ALIGN_BITS = 1; #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 +class insn_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; +public: + uint32_t bits() { return b; } + reg_t i_imm() { return int64_t(int32_t(b) >> 20); } + reg_t s_imm() { return x(7, 5) | (x(25, 7) << 5) | (imm_sign() << 12); } + reg_t sb_imm() { return (x(8, 4) << 1) | (x(25,6) << 5) | (x(7,1) << 11) | (imm_sign() << 12); } + reg_t u_imm() { return int64_t(int32_t(b) >> 12 << 12); } + reg_t uj_imm() { return (x(21, 10) << 1) | (x(20, 1) << 11) | (x(12, 8) << 12) | (imm_sign() << 20); } + uint32_t rd() { return x(7, 5); } + uint32_t rs1() { return x(15, 5); } + uint32_t rs2() { return x(20, 5); } + uint32_t rs3() { return x(27, 5); } + uint32_t rm() { return x(12, 3); } + reg_t csr() { return x(20, 12); } +private: + uint32_t b; + reg_t x(int lo, int len) { return b << (32-lo-len) >> (32-len); } + reg_t imm_sign() { return int64_t(int32_t(b) >> 31); } }; -struct ltype_t +template +class regfile_t { - unsigned opcode : OPCODE_BITS; - unsigned bigimm : BIGIMM_BITS; - unsigned rd : XPRID_BITS; +public: + void reset() + { + memset(data, 0, sizeof(data)); + } + void write(size_t i, T value) + { + data[i] = value; + } + const T& operator [] (size_t i) const + { + if (zero_reg) + const_cast(data[0]) = 0; + return data[i]; + } +private: + T data[N]; }; -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; -}; +// helpful macros, etc +#define MMU (*p->get_mmu()) +#define RS1 p->get_state()->XPR[insn.rs1()] +#define RS2 p->get_state()->XPR[insn.rs2()] +#define WRITE_RD(value) p->get_state()->XPR.write(insn.rd(), value) + +#ifdef RISCV_ENABLE_COMMITLOG + #undef WRITE_RD + #define WRITE_RD(value) ({ \ + bool in_spvr = p->get_state()->sr & SR_S; \ + reg_t wdata = value; /* value is a func with side-effects */ \ + if (!in_spvr) \ + fprintf(stderr, "x%u 0x%016" PRIx64, insn.rd(), ((uint64_t) wdata)); \ + p->get_state()->XPR.write(insn.rd(), wdata); \ + }) +#endif -union insn_t -{ - itype_t itype; - jtype_t jtype; - rtype_t rtype; - btype_t btype; - ltype_t ltype; - ftype_t ftype; - uint32_t bits; -}; +#define FRS1 p->get_state()->FPR[insn.rs1()] +#define FRS2 p->get_state()->FPR[insn.rs2()] +#define FRS3 p->get_state()->FPR[insn.rs3()] +#define WRITE_FRD(value) p->get_state()->FPR.write(insn.rd(), value) + +#ifdef RISCV_ENABLE_COMMITLOG + #undef WRITE_FRD + #define WRITE_FRD(value) ({ \ + bool in_spvr = p->get_state()->sr & SR_S; \ + freg_t wdata = value; /* value is a func with side-effects */ \ + if (!in_spvr) \ + fprintf(stderr, "f%u 0x%016" PRIx64, insn.rd(), ((uint64_t) wdata)); \ + p->get_state()->FPR.write(insn.rd(), wdata); \ + }) +#endif + -#if 0 -#include -class trace_writeback -{ -public: - trace_writeback(reg_t* _rf, int _rd) : rf(_rf), rd(_rd) {} - reg_t operator = (reg_t rhs) - { - printf("R[%x] <= %llx\n",rd,(long long)rhs); - rf[rd] = rhs; - return rhs; - } +#define SHAMT (insn.i_imm() & 0x3F) +#define BRANCH_TARGET (pc + insn.sb_imm()) +#define JUMP_TARGET (pc + insn.uj_imm()) +#define RM ({ int rm = insn.rm(); \ + if(rm == 7) rm = p->get_state()->frm; \ + if(rm > 4) throw trap_illegal_instruction(); \ + rm; }) -private: - reg_t* rf; - int rd; -}; +#define xpr64 (xprlen == 64) -#define do_writeback(rf,rd) trace_writeback(rf,rd) +#define require_supervisor if(unlikely(!(p->get_state()->sr & SR_S))) throw trap_privileged_instruction() +#define require_xpr64 if(unlikely(!xpr64)) throw trap_illegal_instruction() +#define require_xpr32 if(unlikely(xpr64)) throw trap_illegal_instruction() +#ifndef RISCV_ENABLE_FPU +# define require_fp throw trap_illegal_instruction() #else -#define do_writeback(rf,rd) rf[rd] +# define require_fp if(unlikely(!(p->get_state()->sr & SR_EF))) throw trap_fp_disabled() #endif +#define require_accelerator if(unlikely(!(p->get_state()->sr & SR_EA))) throw trap_accelerator_disabled() -// 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 ((insn.ftype.rm != 7) ? insn.ftype.rm : \ - ((fsr & FSR_RD) >> FSR_RD_SHIFT)) - -#define require_supervisor if(!(sr & SR_S)) throw trap_privileged_instruction -#define xpr64 (xprlen == 64) -#define require_xpr64 if(!xpr64) throw trap_illegal_instruction -#define require_xpr32 if(xpr64) throw trap_illegal_instruction -#define require_fp if(!(sr & SR_EF)) throw trap_fp_disabled #define cmp_trunc(reg) (reg_t(reg) << (64-xprlen)) -#define set_fp_exceptions ({ set_fsr(fsr | \ - (softfloat_exceptionFlags << FSR_AEXC_SHIFT)); \ +#define set_fp_exceptions ({ p->get_state()->fflags |= softfloat_exceptionFlags; \ softfloat_exceptionFlags = 0; }) -static inline sreg_t sext32(int32_t arg) -{ - return arg; -} - -#define sext_xprlen(x) ((sreg_t(x) << (64-xprlen)) >> (64-xprlen)) +#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)) + +#define insn_length(x) \ + (((x) & 0x03) < 0x03 ? 2 : \ + ((x) & 0x1f) < 0x1f ? 4 : \ + ((x) & 0x3f) < 0x3f ? 6 : \ + 8) + +#define set_pc(x) \ + do { if ((x) & 3 /* For now... */) \ + throw trap_instruction_address_misaligned(); \ + npc = (x); \ + } while(0) + +#define validate_csr(which, write) ({ \ + int write_priv = ((which) >> 10) & 3; \ + int read_priv = ((which) >> 8) & 3; \ + if (read_priv > 0 || (write_priv > 0 && (write))) require_supervisor; \ + (which); }) #endif