riscy_isa/
opcode.rs

1mod amo_function;
2mod amo_ordering;
3mod amo_width;
4mod branch_operation;
5mod load_width;
6mod misc_mem;
7mod op_32_function;
8mod op_function;
9mod op_imm_32_function;
10mod op_imm_function;
11mod store_width;
12mod system_function;
13
14pub use self::{
15    amo_function::AmoFunction,
16    amo_ordering::AmoOrdering,
17    amo_width::AmoWidth,
18    branch_operation::BranchOperation,
19    load_width::LoadWidth,
20    misc_mem::MiscMemFunction,
21    op_32_function::Op32Function,
22    op_function::OpFunction,
23    op_imm_32_function::OpImm32Function,
24    op_imm_function::OpImmFunction,
25    store_width::StoreWidth,
26    system_function::{CSRFunction, EnvironmentFunction, SystemFunction},
27};
28
29#[derive(Copy, Clone, Debug, PartialEq)]
30#[repr(u8)]
31pub enum Opcode {
32    Load(LoadWidth),
33    LoadFp,
34    Custom0,
35    MiscMem(MiscMemFunction),
36    OpImm(OpImmFunction),
37    AuiPc,
38    OpImm32(OpImm32Function),
39
40    Store(StoreWidth),
41    StoreFp,
42    Custom1,
43    Amo(AmoFunction, AmoWidth),
44    Op(OpFunction),
45    Lui,
46    Op32(Op32Function),
47
48    MAdd,
49    MSub,
50    NMSub,
51    NMAdd,
52    OpFp,
53    Reserved0,
54    Custom2,
55
56    Branch(BranchOperation),
57    JAlr,
58    Reserved1,
59    JAl,
60    System(SystemFunction),
61    Reserved2,
62    Custom3,
63
64    // "C" (Compressed) extension
65    CADDI4SPN,
66    CADDI,
67    CNOP,
68    CFLD,
69    CLW,
70    CLD,
71    CSW,
72    CSD,
73    CADDIW,
74    CLI,
75    CADDI16SP,
76    CLUI,
77    CSRLI,
78    CSRAI,
79    CANDI,
80    CSUB,
81    CXOR,
82    COR,
83    CAND,
84    CSUBW,
85    CADDW,
86    CJ,
87    CBEQZ,
88    CBNEZ,
89    CSLLI,
90    CLWSP,
91    CLDSP,
92    CJR,
93    CMV,
94    CBREAK,
95    CJALR,
96    CADD,
97    CSWSP,
98    CSDSP,
99}
100
101impl Opcode {
102    pub fn new_compressed(base: u16) -> Opcode {
103        let op_low = base & 0b11;
104        let op_high = (base >> 13) & 0b111;
105
106        match (op_high, op_low) {
107            (0b000, 0b00) => Opcode::CADDI4SPN,
108            (0b000, 0b01) => {
109                if (base >> 7) & 0b11111 == 0 {
110                    Opcode::CNOP
111                } else {
112                    Opcode::CADDI
113                }
114            }
115            (0b001, 0b00) => Opcode::CFLD, // or is it C.LQ?
116            (0b010, 0b00) => Opcode::CLW,
117            (0b011, 0b00) => Opcode::CLD,
118            (0b110, 0b00) => Opcode::CSW,
119            (0b111, 0b00) => Opcode::CSD,
120            (0b001, 0b01) => Opcode::CADDIW,
121            (0b010, 0b01) => Opcode::CLI,
122            (0b011, 0b01) => {
123                if (base >> 7) & 0b11111 == 2 {
124                    Opcode::CADDI16SP
125                } else {
126                    Opcode::CLUI
127                }
128            }
129            (0b100, 0b01) => {
130                let func3 = (base >> 10) & 0b111;
131                let func2 = (base >> 5) & 0b11;
132                match (func3, func2) {
133                    (0b000, _) | (0b100, _) => Opcode::CSRLI,
134                    (0b001, _) | (0b101, _) => Opcode::CSRAI,
135                    (0b010, _) | (0b110, _) => Opcode::CANDI,
136                    (0b011, 0b00) => Opcode::CSUB,
137                    (0b011, 0b01) => Opcode::CXOR,
138                    (0b011, 0b10) => Opcode::COR,
139                    (0b011, 0b11) => Opcode::CAND,
140                    (0b111, 0b00) => Opcode::CSUBW,
141                    (0b111, 0b01) => Opcode::CADDW,
142                    _ => todo!(
143                        "compressed arithmetic function with func=({:#03b}, {:#02b})",
144                        func3,
145                        func2
146                    ),
147                }
148            }
149            (0b101, 0b01) => Opcode::CJ,
150            (0b110, 0b01) => Opcode::CBEQZ,
151            (0b111, 0b01) => Opcode::CBNEZ,
152            (0b000, 0b10) => Opcode::CSLLI,
153            (0b010, 0b10) => Opcode::CLWSP,
154            (0b011, 0b10) => Opcode::CLDSP,
155            (0b100, 0b10) => {
156                let func12 = (base >> 12) & 0b1;
157                let func11_7 = (base >> 7) & 0b11111;
158                let func6_2 = (base >> 2) & 0b11111;
159
160                match (func12, func11_7, func6_2) {
161                    (0b0, _, 0b00000) => Opcode::CJR,
162                    (0b0, _, _) => Opcode::CMV,
163                    (0b1, 0b0, 0b00000) => unimplemented!("C.EBREAK"),
164                    (0b1, _, 0b00000) => Opcode::CJALR,
165                    (0b1, _, _) => Opcode::CADD,
166                    spec => unimplemented!("compressed opcode 100...10 with func ({:?})", spec),
167                }
168            }
169            (0b110, 0b10) => Opcode::CSWSP,
170            (0b111, 0b10) => Opcode::CSDSP,
171
172            _ => todo!(
173                "compressed instruction with op={:03b}...{:02b} from base={:016b} ({:#04x})",
174                op_high,
175                op_low,
176                base,
177                base
178            ),
179        }
180    }
181
182    pub fn new(base: u16, func3: u8, imm11_0: u16, func5: u8, func7: u8) -> Opcode {
183        let opcode = base & 0b1111111;
184        match opcode {
185            0b0000011 => Opcode::Load(LoadWidth::from_func3(func3)),
186            0b0000111 => Opcode::LoadFp,
187            0b0001011 => unimplemented!("Custom 0"),
188            0b0001111 => Opcode::MiscMem(MiscMemFunction::from_func3(func3)),
189            0b0010011 => Opcode::OpImm(OpImmFunction::from_imm11_0_func3(imm11_0, func3)),
190            0b0010111 => Opcode::AuiPc,
191            0b0011011 => Opcode::OpImm32(OpImm32Function::from_func3_imm(func3, imm11_0)),
192
193            0b0100011 => Opcode::Store(StoreWidth::from_func3(func3)),
194            0b0100111 => Opcode::StoreFp,
195            0b0101011 => unimplemented!("Custom 1"),
196            0b0101111 => Opcode::Amo(AmoFunction::from_func5(func5), AmoWidth::from_func3(func3)),
197            0b0110011 => Opcode::Op(OpFunction::from_func3_func7(func3, func7)),
198            0b0110111 => Opcode::Lui,
199            0b0111011 => Opcode::Op32(Op32Function::from_func3_func7(func3, func7)),
200
201            0b1000011 => Opcode::MAdd,
202            0b1000111 => Opcode::MSub,
203            0b1001011 => Opcode::NMSub,
204            0b1001111 => Opcode::NMAdd,
205            0b1010011 => Opcode::OpFp,
206            0b1010111 => unimplemented!("Reserved 0"),
207            0b1011011 => unimplemented!("Custom 2"),
208
209            0b1100011 => Opcode::Branch(BranchOperation::from_func3(func3)),
210            0b1100111 => Opcode::JAlr,
211            0b1101011 => unimplemented!("Reserved 1"),
212            0b1101111 => Opcode::JAl,
213            0b1110011 => Opcode::System(SystemFunction::from_func3_imm11_0(func3, imm11_0)),
214            0b1110111 => unimplemented!("Reserved 2"),
215            0b1111011 => unimplemented!("Custom 3"),
216
217            _ => panic!("Unknown opcode"),
218        }
219    }
220
221    pub fn opcode_field(&self) -> i32 {
222        match self {
223            Opcode::Load(_) => 0b0000011,
224            Opcode::LoadFp => 0b0000111,
225            Opcode::Custom0 => 0b0001011,
226            Opcode::MiscMem(_) => 0b0001111,
227            Opcode::OpImm(_) => 0b0010011,
228            Opcode::AuiPc => 0b0010111,
229            Opcode::OpImm32(_) => 0b0011011,
230
231            Opcode::Store(_) => 0b0100011,
232            Opcode::StoreFp => 0b0100111,
233            Opcode::Custom1 => 0b0101011,
234            Opcode::Amo(_, _) => 0b0101111,
235            Opcode::Op(_) => 0b0110011,
236            Opcode::Lui => 0b0110111,
237            Opcode::Op32(_) => 0b0111011,
238
239            Opcode::MAdd => 0b1000011,
240            Opcode::MSub => 0b1000111,
241            Opcode::NMSub => 0b1001011,
242            Opcode::NMAdd => 0b1001111,
243            Opcode::OpFp => 0b1010011,
244            Opcode::Reserved0 => 0b1010111,
245            Opcode::Custom2 => 0b1011011,
246
247            Opcode::Branch(_) => 0b1100011,
248            Opcode::JAlr => 0b1100111,
249            Opcode::Reserved1 => 0b1101011,
250            Opcode::JAl => 0b1101111,
251            Opcode::System(_) => 0b1110011,
252            Opcode::Reserved2 => 0b1110111,
253            Opcode::Custom3 => 0b1111011,
254
255            Opcode::CADDI4SPN => 0b00,
256            Opcode::CADDI => 0b01,
257            Opcode::CNOP => 0b01,
258            Opcode::CFLD => 0b00,
259            Opcode::CLW => 0b00,
260            Opcode::CLD => 0b00,
261            Opcode::CSW => 0b00,
262            Opcode::CSD => 0b00,
263            Opcode::CADDIW => 0b01,
264            Opcode::CLI => 0b01,
265            Opcode::CADDI16SP => 0b01,
266            Opcode::CLUI => 0b01,
267            Opcode::CSRLI => 0b01,
268            Opcode::CSRAI => 0b01,
269            Opcode::CANDI => 0b01,
270            Opcode::CSUB => 0b01,
271            Opcode::CXOR => 0b01,
272            Opcode::COR => 0b01,
273            Opcode::CAND => 0b01,
274            Opcode::CSUBW => 0b01,
275            Opcode::CADDW => 0b01,
276            Opcode::CJ => 0b01,
277            Opcode::CBEQZ => 0b01,
278            Opcode::CBNEZ => 0b01,
279            Opcode::CSLLI => 0b10,
280            Opcode::CLWSP => 0b10,
281            Opcode::CLDSP => 0b10,
282            Opcode::CJR => 0b10,
283            Opcode::CMV => 0b10,
284            Opcode::CBREAK => 0b10,
285            Opcode::CJALR => 0b10,
286            Opcode::CADD => 0b10,
287            Opcode::CSWSP => 0b10,
288            Opcode::CSDSP => 0b10,
289        }
290    }
291
292    pub fn funct3_field(&self) -> i32 {
293        match self {
294            Opcode::Load(function) => function.to_func3(),
295            Opcode::OpImm(function) => function.to_func3(),
296            Opcode::Store(function) => function.to_func3(),
297            Opcode::Op(function) => function.to_func3(),
298            Opcode::Branch(function) => function.to_func3(),
299            Opcode::System(_) => 0,
300
301            _ => unimplemented!("opcode {:?} does not have funct3 field", self),
302        }
303    }
304
305    pub fn funct7_field(&self) -> i32 {
306        match self {
307            Opcode::Op(function) => function.to_func7(),
308
309            _ => unimplemented!("opcode {:?} does not have funct7 field", self),
310        }
311    }
312}