aboutsummaryrefslogtreecommitdiff
path: root/riscv/decode.h
blob: f99e9ebe30328ecdd3a0bbfe164bff7390d98dc3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#ifndef _RISCV_DECODE_H
#define _RISCV_DECODE_H

#define __STDC_LIMIT_MACROS
#include <stdint.h>
typedef int int128_t __attribute__((mode(TI)));
typedef unsigned int uint128_t __attribute__((mode(TI)));

#define support_64bit 1
typedef int64_t sreg_t;
typedef uint64_t reg_t;
typedef uint64_t freg_t;

const int OPCODE_BITS = 7;
const int JTYPE_OPCODE_BITS = 5;

const int GPR_BITS = 8*sizeof(reg_t);
const int GPRID_BITS = 5;
const int NGPR = 1 << GPRID_BITS;

const int FPR_BITS = 64;
const int FPRID_BITS = 5;
const int NFPR = 1 << FPRID_BITS;

const int IMM_BITS = 12;
const int TARGET_BITS = 27;
const int SHAMT_BITS = 6;
const int FUNCT_BITS = 3;
const int FUNCTR_BITS = 7;
const int FFUNCT_BITS = 5;
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 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 10
#define FSR_RD   (0x7 << FSR_RD_SHIFT)

#define FPEXC_NX 0x01
#define FPEXC_UF 0x02
#define FPEXC_OF 0x04
#define FPEXC_DZ 0x02
#define FPEXC_NV 0x10

#define FSR_CEXC_SHIFT 5
#define FSR_NVC  (FPEXC_NV << FSR_CEXC_SHIFT)
#define FSR_OFC  (FPEXC_OF << FSR_CEXC_SHIFT)
#define FSR_UFC  (FPEXC_UF << FSR_CEXC_SHIFT)
#define FSR_DZC  (FPEXC_DZ << FSR_CEXC_SHIFT)
#define FSR_NXC  (FPEXC_NX << FSR_CEXC_SHIFT)
#define FSR_CEXC (FSR_NVC | FSR_OFC | FSR_UFC | FSR_DZC | FSR_NXC)

#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 | FSR_CEXC)

// note: bit fields are in little-endian order
struct itype_t
{
  unsigned imm12 : IMM_BITS;
  unsigned funct : FUNCT_BITS;
  unsigned rs1 : GPRID_BITS;
  unsigned rdi : GPRID_BITS;
  unsigned opcode : OPCODE_BITS;
};

struct jtype_t
{
  unsigned target : TARGET_BITS;
  unsigned jump_opcode : JTYPE_OPCODE_BITS;
};

struct rtype_t
{
  unsigned rdr : GPRID_BITS;
  unsigned functr : FUNCTR_BITS;
  unsigned funct : FUNCT_BITS;
  unsigned rs1 : GPRID_BITS;
  unsigned rs2 : GPRID_BITS;
  unsigned opcode : OPCODE_BITS;
};

struct btype_t
{
  unsigned bigimm : BIGIMM_BITS;
  unsigned rdi : GPRID_BITS;
  unsigned opcode : OPCODE_BITS;
};

struct ftype_t
{
  unsigned rdr : FPRID_BITS;
  unsigned rs3 : FPRID_BITS;
  unsigned ffunct : FFUNCT_BITS;
  unsigned rs1 : FPRID_BITS;
  unsigned rs2 : FPRID_BITS;
  unsigned opcode : OPCODE_BITS;
};

union insn_t
{
  itype_t itype;
  jtype_t jtype;
  rtype_t rtype;
  btype_t btype;
  ftype_t ftype;
  uint32_t bits;
};

// helpful macros, etc
#define RS1 R[insn.rtype.rs1]
#define RS2 R[insn.rtype.rs2]
#define RDR R[insn.rtype.rdr]
#define RDI R[insn.itype.rdi]
#define FRS1 FR[insn.ftype.rs1]
#define FRS2 FR[insn.ftype.rs2]
#define FRS3 FR[insn.ftype.rs3]
#define FRDR FR[insn.ftype.rdr]
#define FRDI FR[insn.itype.rdi]
#define BIGIMM insn.btype.bigimm
#define IMM insn.itype.imm12
#define SIMM ((int32_t)((uint32_t)insn.itype.imm12<<(32-IMM_BITS))>>(32-IMM_BITS))
#define SHAMT (insn.itype.imm12 & 0x3F)
#define SHAMTW (insn.itype.imm12 & 0x1F)
#define TARGET insn.jtype.target
#define BRANCH_TARGET (npc + (SIMM << BRANCH_ALIGN_BITS))
#define JUMP_TARGET ((npc & ~((1<<(TARGET_BITS+JUMP_ALIGN_BITS))-1)) + (TARGET << JUMP_ALIGN_BITS))

#define require_supervisor if(!(sr & SR_S)) throw trap_privileged_instruction
#define require64 if(gprlen != 64) throw trap_illegal_instruction
#define require_fp if(!(sr & SR_EF)) throw trap_fp_disabled
#define cmp_trunc(reg) (reg_t(reg) << (64-gprlen))
#define set_fp_exceptions ({ set_fsr((fsr & ~FSR_CEXC) | \
                                (softfloat_exceptionFlags << FSR_AEXC_SHIFT) | \
                                (softfloat_exceptionFlags << FSR_CEXC_SHIFT)); \
                             softfloat_exceptionFlags = 0; })

static inline sreg_t sext32(int32_t arg)
{
  return arg;
}

#endif