riscv_decode/
lib.rs

1#![no_std]
2
3mod compressed;
4mod instruction;
5pub mod types;
6
7use types::*;
8
9pub use instruction::Instruction;
10
11#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
12pub enum DecodingError {
13    /// Instruction's opcode is reserved for custom extentions and thus can't be decoded further.
14    Custom,
15    /// Instruction's opcode is reserved for future standard extentions.
16    Reserved,
17    /// Instruction bit pattern not defined in current specification.
18    Unknown,
19    /// More bits from the instruction are required to fully decode it.
20    Truncated,
21    /// Instruction type is well defined but is part of some extension this library doesn't support
22    /// decoding yet.
23    Unimplemented,
24}
25
26type DecodingResult = Result<Instruction, DecodingError>;
27
28/// Return the length (in bytes) of an instruction given the low 16 bits of it.
29///
30/// The current spec reserves a bit pattern for instructions of length >= 192 bits, but for
31/// simplicity this function just returns 24 in that case. The largest instructions currently
32/// defined are 4 bytes so it will likely be a long time until this diffence matters.
33pub fn instruction_length(i: u16) -> usize {
34    if i & 0b11 != 0b11 {
35        2
36    } else if i & 0b11100 != 0b11100 {
37        4
38    } else if i & 0b111111 == 0b011111 {
39        6
40    } else if i & 0b1111111 == 0b011111 {
41        8
42    } else {
43        10 + 2 * ((i >> 12) & 0b111) as usize
44    }
45}
46
47/// Decode the given instruction.
48pub fn decode(i: u32) -> DecodingResult {
49    match i & 0b11 {
50        0b00 => compressed::decode_q00(i),
51        0b01 => compressed::decode_q01(i),
52        0b10 => compressed::decode_q10(i),
53        0b11 => match (i >> 2) & 0b11111 {
54            0b00000 => decode_load(i),
55            0b00001 => match (i >> 12) & 0b111 {
56                0b010 => Ok(Instruction::Flw(IType(i))),
57                _ => Err(DecodingError::Unknown),
58            },
59            0b00010 => Err(DecodingError::Custom),
60            0b00011 => decode_misc_mem(i),
61            0b00100 => decode_op_imm(i),
62            0b00101 => Ok(Instruction::Auipc(UType(i))),
63            0b00110 => decode_op_imm32(i),
64            0b00111 => Err(DecodingError::Reserved), // 48bit instruction
65
66            0b01000 => decode_store(i),
67            0b01001 => match (i >> 12) & 0b111 {
68                0b010 => Ok(Instruction::Fsw(SType(i))),
69                _ => Err(DecodingError::Unknown),
70            },
71            0b01010 => Err(DecodingError::Custom),
72            0b01011 => decode_amo(i),
73            0b01100 => decode_op(i),
74            0b01101 => Ok(Instruction::Lui(UType(i))),
75            0b01110 => decode_op32(i),
76            0b01111 => Err(DecodingError::Reserved), // 64bit instruction
77
78            0b10000 => match (i >> 25) & 0b11 {
79                0b00 => Ok(Instruction::Fmadds(R4Type(i))),
80                _ => Err(DecodingError::Unknown),
81            },
82            0b10001 => match (i >> 25) & 0b11 {
83                0b00 => Ok(Instruction::Fmsubs(R4Type(i))),
84                _ => Err(DecodingError::Unknown),
85            },
86            0b10010 => match (i >> 25) & 0b11 {
87                0b00 => Ok(Instruction::Fnmsubs(R4Type(i))),
88                _ => Err(DecodingError::Unknown),
89            },
90            0b10011 => match (i >> 25) & 0b11 {
91                0b00 => Ok(Instruction::Fnmadds(R4Type(i))),
92                _ => Err(DecodingError::Unknown),
93            },
94            0b10100 => decode_opfp(i), // OP-FP
95            0b10101 => Err(DecodingError::Reserved),
96            0b10110 => Err(DecodingError::Custom),
97            0b10111 => Err(DecodingError::Reserved), // 48bit instruction
98
99            0b11000 => decode_branch(i),
100            0b11001 => Ok(Instruction::Jalr(IType(i))),
101            0b11010 => Err(DecodingError::Reserved),
102            0b11011 => Ok(Instruction::Jal(JType(i))),
103            0b11100 => decode_system(i),
104            0b11101 => Err(DecodingError::Reserved),
105            0b11110 => Err(DecodingError::Custom),
106            0b11111 => Err(DecodingError::Reserved), // >= 80bit instruction
107            _ => unreachable!(),
108        },
109        _ => unreachable!(),
110    }
111}
112
113fn decode_opfp(i: u32) -> Result<Instruction, DecodingError> {
114    match (i >> 25) & 0b1111111 {
115        0b0000000 => Ok(Instruction::Fadds(RType(i))),
116        0b0000100 => Ok(Instruction::Fsubs(RType(i))),
117        0b0001000 => Ok(Instruction::Fmuls(RType(i))),
118        0b0001100 => Ok(Instruction::Fdivs(RType(i))),
119        0b0101100 if i >> 20 & 0b11111 == 0 => Ok(Instruction::Fsqrts(RType(i))),
120        0b0010000 => match i >> 12 & 0b111 {
121            0b000 => Ok(Instruction::Fsgnjs(RType(i))),
122            0b001 => Ok(Instruction::Fsgnjns(RType(i))),
123            0b010 => Ok(Instruction::Fsgnjxs(RType(i))),
124            _ => Err(DecodingError::Unknown),
125        },
126        0b0010100 => match i >> 12 & 0b111 {
127            0b000 => Ok(Instruction::Fmins(RType(i))),
128            0b001 => Ok(Instruction::Fmaxs(RType(i))),
129            _ => Err(DecodingError::Unknown),
130        },
131        0b1100000 => match i >> 20 & 0b11111 {
132            0b00000 => Ok(Instruction::Fcvtws(RType(i))),
133            0b00001 => Ok(Instruction::Fcvtwus(RType(i))),
134            _ => Err(DecodingError::Unknown),
135        },
136        0b1110000 if i >> 20 & 0b11111 == 0 && i >> 12 & 0b111 == 0 => {
137            Ok(Instruction::Fmvxw(RType(i)))
138        }
139        0b1010000 => match i >> 12 & 0b111 {
140            0b010 => Ok(Instruction::Feqs(RType(i))),
141            0b001 => Ok(Instruction::Flts(RType(i))),
142            0b000 => Ok(Instruction::Fles(RType(i))),
143            _ => Err(DecodingError::Unknown),
144        },
145        0b1110000 if i >> 20 & 0b11111 == 0 && i >> 12 & 0b111 == 0b001 => {
146            Ok(Instruction::Fclasss(RType(i)))
147        }
148        0b1101000 if i >> 20 & 0b11111 == 0 => Ok(Instruction::Fcvtsw(RType(i))),
149        0b1101000 if i >> 20 & 0b11111 == 1 => Ok(Instruction::Fcvtswu(RType(i))),
150        0b1111000 if i >> 20 & 0b11111 == 0 && i >> 12 & 0b111 == 0 => {
151            Ok(Instruction::Fmvwx(RType(i)))
152        }
153        _ => Err(DecodingError::Unknown),
154    }
155}
156
157fn decode_load(i: u32) -> DecodingResult {
158    match (i >> 12) & 0b111 {
159        0b000 => Ok(Instruction::Lb(IType(i))),
160        0b001 => Ok(Instruction::Lh(IType(i))),
161        0b010 => Ok(Instruction::Lw(IType(i))),
162        0b011 => Ok(Instruction::Ld(IType(i))),
163        0b100 => Ok(Instruction::Lbu(IType(i))),
164        0b101 => Ok(Instruction::Lhu(IType(i))),
165        0b110 => Ok(Instruction::Lwu(IType(i))),
166        0b111 => Err(DecodingError::Reserved),
167        _ => unreachable!(),
168    }
169}
170
171fn decode_misc_mem(i: u32) -> DecodingResult {
172    if i == 0b001000000001111 {
173        Ok(Instruction::FenceI)
174    } else if i & 0xf00fff80 == 0 {
175        Ok(Instruction::Fence(FenceType(i)))
176    } else {
177        Err(DecodingError::Reserved)
178    }
179}
180
181fn decode_op_imm(i: u32) -> DecodingResult {
182    match (i >> 12) & 0b111 {
183        0b000 => Ok(Instruction::Addi(IType(i))),
184        0b001 => match i >> 26 {
185            0 => Ok(Instruction::Slli(ShiftType(i))),
186            _ => Err(DecodingError::Unknown),
187        },
188        0b010 => Ok(Instruction::Slti(IType(i))),
189        0b011 => Ok(Instruction::Sltiu(IType(i))),
190        0b100 => Ok(Instruction::Xori(IType(i))),
191        0b101 => match i >> 26 {
192            0b000000 => Ok(Instruction::Srli(ShiftType(i))),
193            0b010000 => Ok(Instruction::Srai(ShiftType(i))),
194            _ => Err(DecodingError::Unknown),
195        },
196        0b110 => Ok(Instruction::Ori(IType(i))),
197        0b111 => Ok(Instruction::Andi(IType(i))),
198        _ => unreachable!(),
199    }
200}
201
202fn decode_op_imm32(i: u32) -> DecodingResult {
203    match (i >> 25, (i >> 12) & 0b111) {
204        (_, 0b000) => Ok(Instruction::Addiw(IType(i))),
205        (0b0000000, 0b001) => Ok(Instruction::Slliw(ShiftType(i))),
206        (0b0000000, 0b101) => Ok(Instruction::Srliw(ShiftType(i))),
207        (0b0100000, 0b101) => Ok(Instruction::Sraiw(ShiftType(i))),
208        _ => Err(DecodingError::Unknown),
209    }
210}
211
212fn decode_store(i: u32) -> DecodingResult {
213    match (i >> 12) & 0b111 {
214        0b000 => Ok(Instruction::Sb(SType(i))),
215        0b001 => Ok(Instruction::Sh(SType(i))),
216        0b010 => Ok(Instruction::Sw(SType(i))),
217        0b011 => Ok(Instruction::Sd(SType(i))),
218        _ => Err(DecodingError::Unknown),
219    }
220}
221
222fn decode_op(i: u32) -> DecodingResult {
223    match (i >> 25, (i >> 12) & 0b111) {
224        (0b0000000, 0b000) => Ok(Instruction::Add(RType(i))),
225        (0b0100000, 0b000) => Ok(Instruction::Sub(RType(i))),
226        (0b0000000, 0b001) => Ok(Instruction::Sll(RType(i))),
227        (0b0000000, 0b010) => Ok(Instruction::Slt(RType(i))),
228        (0b0000000, 0b011) => Ok(Instruction::Sltu(RType(i))),
229        (0b0000000, 0b100) => Ok(Instruction::Xor(RType(i))),
230        (0b0000000, 0b101) => Ok(Instruction::Srl(RType(i))),
231        (0b0100000, 0b101) => Ok(Instruction::Sra(RType(i))),
232        (0b0000000, 0b110) => Ok(Instruction::Or(RType(i))),
233        (0b0000000, 0b111) => Ok(Instruction::And(RType(i))),
234
235        (0b0000001, 0b000) => Ok(Instruction::Mul(RType(i))),
236        (0b0000001, 0b001) => Ok(Instruction::Mulh(RType(i))),
237        (0b0000001, 0b010) => Ok(Instruction::Mulhsu(RType(i))),
238        (0b0000001, 0b011) => Ok(Instruction::Mulhu(RType(i))),
239        (0b0000001, 0b100) => Ok(Instruction::Div(RType(i))),
240        (0b0000001, 0b101) => Ok(Instruction::Divu(RType(i))),
241        (0b0000001, 0b110) => Ok(Instruction::Rem(RType(i))),
242        (0b0000001, 0b111) => Ok(Instruction::Remu(RType(i))),
243        _ => Err(DecodingError::Unknown),
244    }
245}
246
247fn decode_op32(i: u32) -> DecodingResult {
248    match (i >> 25, (i >> 12) & 0b111) {
249        (0b0000000, 0b000) => Ok(Instruction::Addw(RType(i))),
250        (0b0100000, 0b000) => Ok(Instruction::Subw(RType(i))),
251        (0b0000000, 0b001) => Ok(Instruction::Sllw(RType(i))),
252        (0b0000000, 0b101) => Ok(Instruction::Srlw(RType(i))),
253        (0b0100000, 0b101) => Ok(Instruction::Sraw(RType(i))),
254
255        (0b0000001, 0b000) => Ok(Instruction::Mulw(RType(i))),
256        (0b0000001, 0b100) => Ok(Instruction::Divw(RType(i))),
257        (0b0000001, 0b101) => Ok(Instruction::Divuw(RType(i))),
258        (0b0000001, 0b110) => Ok(Instruction::Remw(RType(i))),
259        (0b0000001, 0b111) => Ok(Instruction::Remuw(RType(i))),
260        _ => Err(DecodingError::Unknown),
261    }
262}
263
264fn decode_branch(i: u32) -> DecodingResult {
265    match (i >> 12) & 0b111 {
266        0b000 => Ok(Instruction::Beq(BType(i))),
267        0b001 => Ok(Instruction::Bne(BType(i))),
268        0b010 => Err(DecodingError::Unknown),
269        0b011 => Err(DecodingError::Unknown),
270        0b100 => Ok(Instruction::Blt(BType(i))),
271        0b101 => Ok(Instruction::Bge(BType(i))),
272        0b110 => Ok(Instruction::Bltu(BType(i))),
273        0b111 => Ok(Instruction::Bgeu(BType(i))),
274        _ => unreachable!(),
275    }
276}
277
278fn decode_system(i: u32) -> DecodingResult {
279    match i {
280        // Environment Call and Breakpoint
281        0b000000000000_00000_000_00000_1110011 => return Ok(Instruction::Ecall),
282        0b000000000001_00000_000_00000_1110011 => return Ok(Instruction::Ebreak),
283        // Trap-Return Instructions
284        0b0000000_00010_00000_000_00000_1110011 => return Ok(Instruction::Uret),
285        0b0001000_00010_00000_000_00000_1110011 => return Ok(Instruction::Sret),
286        0b0011000_00010_00000_000_00000_1110011 => return Ok(Instruction::Mret),
287        // Interrupt-Management Instructions
288        0b0001000_00101_00000_000_00000_1110011 => return Ok(Instruction::Wfi),
289        _ => {}
290    }
291
292    match (i >> 12) & 0b111 {
293        0b001 => return Ok(Instruction::Csrrw(CsrType(i))),
294        0b010 => return Ok(Instruction::Csrrs(CsrType(i))),
295        0b011 => return Ok(Instruction::Csrrc(CsrType(i))),
296        0b101 => return Ok(Instruction::Csrrwi(CsrIType(i))),
297        0b110 => return Ok(Instruction::Csrrsi(CsrIType(i))),
298        0b111 => return Ok(Instruction::Csrrci(CsrIType(i))),
299        _ => {}
300    }
301
302    // Memory-Management Instructions
303    const SFENCE_VMA_MASK: u32 = 0b1111111_00000_00000_111_11111_1111111;
304    const SFENCE_VMA_VALUE: u32 = 0b0001001_00000_00000_000_00000_1110011;
305    if i & SFENCE_VMA_MASK == SFENCE_VMA_VALUE {
306        return Ok(Instruction::SfenceVma(RType(i)));
307    }
308
309    Err(DecodingError::Unknown)
310}
311
312fn decode_amo(i: u32) -> DecodingResult {
313    match (i >> 27, (i >> 12) & 0b111) {
314        (0b00010, 0b010) => Ok(Instruction::LrW(RType(i))),
315        (0b00011, 0b010) => Ok(Instruction::ScW(RType(i))),
316        (0b00001, 0b010) => Ok(Instruction::AmoswapW(RType(i))),
317        (0b00000, 0b010) => Ok(Instruction::AmoaddW(RType(i))),
318        (0b00100, 0b010) => Ok(Instruction::AmoxorW(RType(i))),
319        (0b01100, 0b010) => Ok(Instruction::AmoandW(RType(i))),
320        (0b01000, 0b010) => Ok(Instruction::AmoorW(RType(i))),
321        (0b10000, 0b010) => Ok(Instruction::AmominW(RType(i))),
322        (0b10100, 0b010) => Ok(Instruction::AmomaxW(RType(i))),
323        (0b11000, 0b010) => Ok(Instruction::AmominuW(RType(i))),
324        (0b11100, 0b010) => Ok(Instruction::AmomaxuW(RType(i))),
325
326        (0b00010, 0b011) => Ok(Instruction::LrD(RType(i))),
327        (0b00011, 0b011) => Ok(Instruction::ScD(RType(i))),
328        (0b00001, 0b011) => Ok(Instruction::AmoswapD(RType(i))),
329        (0b00000, 0b011) => Ok(Instruction::AmoaddD(RType(i))),
330        (0b00100, 0b011) => Ok(Instruction::AmoxorD(RType(i))),
331        (0b01100, 0b011) => Ok(Instruction::AmoandD(RType(i))),
332        (0b01000, 0b011) => Ok(Instruction::AmoorD(RType(i))),
333        (0b10000, 0b011) => Ok(Instruction::AmominD(RType(i))),
334        (0b10100, 0b011) => Ok(Instruction::AmomaxD(RType(i))),
335        (0b11000, 0b011) => Ok(Instruction::AmominuD(RType(i))),
336        (0b11100, 0b011) => Ok(Instruction::AmomaxuD(RType(i))),
337        _ => Err(DecodingError::Unknown),
338    }
339}
340
341#[cfg(test)]
342mod tests {
343    use super::*;
344    use Instruction::*;
345
346    // Nearly all tests are derived from the output of
347    // [riscv-tests](https://github.com/riscv/riscv-tests)
348    //
349    // Examples of individual instructions were extracted with a simple bash command (see below),
350    // and then post-processed with emacs macros.
351    //
352    // $ rg "\tbne\t" | sort -R | tail -n 3 | xclip -selection c
353
354    #[test]
355    fn decoding() {
356        assert_eq!(decode(0x00001a37).unwrap(), Lui(UType(0x00001a37))); // lui x20,0x1
357        assert_eq!(decode(0x800002b7).unwrap(), Lui(UType(0x800002b7))); // lui x5,0x80000
358        assert_eq!(decode(0x212120b7).unwrap(), Lui(UType(0x212120b7))); // lui x1,0x21212
359        assert_eq!(decode(0xffffe517).unwrap(), Auipc(UType(0xffffe517))); // auipc x10,0xffffe
360        assert_eq!(decode(0xfffff797).unwrap(), Auipc(UType(0xfffff797))); // auipc x15,0xfffff
361        assert_eq!(decode(0xfffff797).unwrap(), Auipc(UType(0xfffff797))); // auipc x15,0xfffff
362        assert_eq!(decode(0xfe1ff06f).unwrap(), Jal(JType(0xfe1ff06f))); // jal x0,800029ec
363        assert_eq!(decode(0x0000006f).unwrap(), Jal(JType(0x0000006f))); // jal x0,80002258
364        assert_eq!(decode(0xf89ff06f).unwrap(), Jal(JType(0xf89ff06f))); // jal x0,800027ac
365        assert_eq!(decode(0x00008067).unwrap(), Jalr(IType(0x00008067))); // jalr x0,0(x1)
366        assert_eq!(decode(0x00008067).unwrap(), Jalr(IType(0x00008067))); // jalr x0,0(x1)
367        assert_eq!(decode(0x000f0067).unwrap(), Jalr(IType(0x000f0067))); // jalr x0,0(x30)
368    }
369
370    #[test]
371    fn load() {
372        assert_eq!(decode(0x02008283).unwrap(), Lb(IType(0x02008283))); // lb x5,32(x1)
373        assert_eq!(decode(0x00708283).unwrap(), Lb(IType(0x00708283))); // lb x5,7(x1)
374        assert_eq!(decode(0x00108f03).unwrap(), Lb(IType(0x00108f03))); // lb x30,1(x1)
375        assert_eq!(decode(0x00411f03).unwrap(), Lh(IType(0x00411f03))); // Lh x30,4(x2)
376        assert_eq!(decode(0x00611f03).unwrap(), Lh(IType(0x00611f03))); // Lh x30,6(x2)
377        assert_eq!(decode(0x00811f03).unwrap(), Lh(IType(0x00811f03))); // Lh x30,8(x2)
378        assert_eq!(decode(0x02052403).unwrap(), Lw(IType(0x02052403))); // Lw x8,32(x10)
379        assert_eq!(decode(0x03452683).unwrap(), Lw(IType(0x03452683))); // Lw x13,52(x10)
380        assert_eq!(decode(0x0006a703).unwrap(), Lw(IType(0x0006a703))); // Lw x14,0(x13)
381        assert_eq!(decode(0x0006c783).unwrap(), Lbu(IType(0x0006c783))); // Lbu x15,0(x13)
382        assert_eq!(decode(0x0006c703).unwrap(), Lbu(IType(0x0006c703))); // Lbu x14,0(x13)
383        assert_eq!(decode(0x0007c683).unwrap(), Lbu(IType(0x0007c683))); // Lbu x13,0(x15)
384        assert_eq!(decode(0x0060df03).unwrap(), Lhu(IType(0x0060df03))); // Lhu x30,6(x1)
385        assert_eq!(decode(0xffe0df03).unwrap(), Lhu(IType(0xffe0df03))); // Lhu x30,-2(x1)
386        assert_eq!(decode(0x0002d303).unwrap(), Lhu(IType(0x0002d303))); // Lhu x6,0(x5)
387        assert_eq!(decode(0x00346303).unwrap(), Lwu(IType(0x00346303))); // Lwu x6,3(x8)
388        assert_eq!(decode(0x0080ef03).unwrap(), Lwu(IType(0x0080ef03))); // Lwu x30,8(x1)
389        assert_eq!(decode(0x0000ef03).unwrap(), Lwu(IType(0x0000ef03))); // Lwu x30,0(x1)
390        assert_eq!(decode(0x01853683).unwrap(), Ld(IType(0x01853683))); // Ld x13,24(x10)
391        assert_eq!(decode(0x02013c03).unwrap(), Ld(IType(0x02013c03))); // Ld x24,32(x2)
392        assert_eq!(decode(0x0007b703).unwrap(), Ld(IType(0x0007b703))); // Ld x14,0(x15)
393    }
394
395    #[test]
396    fn misc_mem() {
397        assert_eq!(decode(0x0310000f).unwrap(), Fence(FenceType(0x0310000f))); // fence rw,w
398        assert_eq!(decode(0x0820000f).unwrap(), Fence(FenceType(0x0820000f))); // fence i,r
399        assert_eq!(decode(0x0ff0000f).unwrap(), Fence(FenceType(0x0ff0000f))); // fence iorw,iorw
400        assert_eq!(decode(0x0000100f).unwrap(), FenceI); // fence.i
401    }
402
403    #[test]
404    fn op_imm() {
405        assert_eq!(decode(0x00200793).unwrap(), Addi(IType(0x00200793))); // addi x15,x0,2
406        assert_eq!(decode(0x00000013).unwrap(), Addi(IType(0x00000013))); // addi x0,x0,0
407        assert_eq!(decode(0x00000013).unwrap(), Addi(IType(0x00000013))); // addi x0,x0,0
408        assert_eq!(decode(0x00381813).unwrap(), Slli(ShiftType(0x00381813))); // slli x16,x16,0x3
409        assert_eq!(decode(0x01059793).unwrap(), Slli(ShiftType(0x01059793))); // slli x15,x11,0x10
410        assert_eq!(decode(0x03079793).unwrap(), Slli(ShiftType(0x03079793))); // slli x15,x15,0x30
411        assert_eq!(decode(0x0010af13).unwrap(), Slti(IType(0x0010af13))); // slti x30,x1,1
412        assert_eq!(decode(0x7ff0af13).unwrap(), Slti(IType(0x7ff0af13))); // slti x30,x1,2047
413        assert_eq!(decode(0x8000af13).unwrap(), Slti(IType(0x8000af13))); // slti x30,x1,-2048
414        assert_eq!(decode(0x0017b613).unwrap(), Sltiu(IType(0x0017b613))); // sltiu x12,x15,1
415        assert_eq!(decode(0xfff0bf13).unwrap(), Sltiu(IType(0xfff0bf13))); // sltiu x30,x1,-1
416        assert_eq!(decode(0x0017b613).unwrap(), Sltiu(IType(0x0017b613))); // sltiu x12,x15,1
417        assert_eq!(decode(0xfff6c693).unwrap(), Xori(IType(0xfff6c693))); // xori x13,x13,-1
418        assert_eq!(decode(0x999ac093).unwrap(), Xori(IType(0x999ac093))); // xori x1,x21,-1639
419        assert_eq!(decode(0xfff6c693).unwrap(), Xori(IType(0xfff6c693))); // xori x13,x13,-1
420        assert_eq!(decode(0x00c7d793).unwrap(), Srli(ShiftType(0x00c7d793))); // srli x15,x15,0xc
421        assert_eq!(decode(0x0207d793).unwrap(), Srli(ShiftType(0x0207d793))); // srli x15,x15,0x20
422        assert_eq!(decode(0x00c7d793).unwrap(), Srli(ShiftType(0x00c7d793))); // srli x15,x15,0xc
423        assert_eq!(decode(0x40e0df13).unwrap(), Srai(ShiftType(0x40e0df13))); // srai x30,x1,0xe
424        assert_eq!(decode(0x41f55893).unwrap(), Srai(ShiftType(0x41f55893))); // srai x17,x10,0x1f
425        assert_eq!(decode(0x40e0df13).unwrap(), Srai(ShiftType(0x40e0df13))); // srai x30,x1,0xe
426        assert_eq!(decode(0x00156513).unwrap(), Ori(IType(0x00156513))); // ori x10,x10,1
427        assert_eq!(decode(0x04076713).unwrap(), Ori(IType(0x04076713))); // ori x14,x14,64
428        assert_eq!(decode(0x5391e193).unwrap(), Ori(IType(0x5391e193))); // ori x3,x3,1337
429        assert_eq!(decode(0xff867693).unwrap(), Andi(IType(0xff867693))); // andi x13,x12,-8
430        assert_eq!(decode(0x08077693).unwrap(), Andi(IType(0x08077693))); // andi x13,x14,128
431        assert_eq!(decode(0x04077693).unwrap(), Andi(IType(0x04077693))); // andi x13,x14,64
432    }
433
434    #[test]
435    fn op_imm32() {
436        assert_eq!(decode(0x0010009b).unwrap(), Addiw(IType(0x0010009b))); // addiw x1,x0,1
437        assert_eq!(decode(0xfff0809b).unwrap(), Addiw(IType(0xfff0809b))); // addiw x1,x1,-1
438        assert_eq!(decode(0xfff0809b).unwrap(), Addiw(IType(0xfff0809b))); // addiw x1,x1,-1
439        assert_eq!(decode(0x0057979b).unwrap(), Slliw(ShiftType(0x0057979b))); // slliw x15,x15,0x5
440        assert_eq!(decode(0x0057979b).unwrap(), Slliw(ShiftType(0x0057979b))); // slliw x15,x15,0x5
441        assert_eq!(decode(0x00e09f1b).unwrap(), Slliw(ShiftType(0x00e09f1b))); // slliw x30,x1,0xe
442        assert_eq!(decode(0x0017d61b).unwrap(), Srliw(ShiftType(0x0017d61b))); // srliw x12,x15,0x1
443        assert_eq!(decode(0x01f0df1b).unwrap(), Srliw(ShiftType(0x01f0df1b))); // srliw x30,x1,0x1f
444        assert_eq!(decode(0x0017d61b).unwrap(), Srliw(ShiftType(0x0017d61b))); // srliw x12,x15,0x1
445        assert_eq!(decode(0x41f0df1b).unwrap(), Sraiw(ShiftType(0x41f0df1b))); // sraiw x30,x1,0x1f
446        assert_eq!(decode(0x4000df1b).unwrap(), Sraiw(ShiftType(0x4000df1b))); // sraiw x30,x1,0x0
447        assert_eq!(decode(0x4070d09b).unwrap(), Sraiw(ShiftType(0x4070d09b))); // sraiw x1,x1,0x7
448    }
449
450    #[test]
451    fn store() {
452        assert_eq!(decode(0x00e78023).unwrap(), Sb(SType(0x00e78023))); // sb x14,0(x15)
453        assert_eq!(decode(0x001101a3).unwrap(), Sb(SType(0x001101a3))); // sb x1,3(x2)
454        assert_eq!(decode(0xfee78fa3).unwrap(), Sb(SType(0xfee78fa3))); // sb x14,-1(x15)
455        assert_eq!(decode(0xfe209d23).unwrap(), Sh(SType(0xfe209d23))); // sh x2,-6(x1)
456        assert_eq!(decode(0x00111223).unwrap(), Sh(SType(0x00111223))); // sh x1,4(x2)
457        assert_eq!(decode(0x00111523).unwrap(), Sh(SType(0x00111523))); // sh x1,10(x2)
458        assert_eq!(decode(0x05612c23).unwrap(), Sw(SType(0x05612c23))); // sw x22,88(x2)
459        assert_eq!(decode(0x01b12e23).unwrap(), Sw(SType(0x01b12e23))); // sw x27,28(x2)
460        assert_eq!(decode(0x01052223).unwrap(), Sw(SType(0x01052223))); // sw x16,4(x10)
461        assert_eq!(decode(0x0b613823).unwrap(), Sd(SType(0x0b613823))); // sd x22,176(x2)
462        assert_eq!(decode(0x09213823).unwrap(), Sd(SType(0x09213823))); // sd x18,144(x2)
463        assert_eq!(decode(0x00f6b423).unwrap(), Sd(SType(0x00f6b423))); // sd x15,8(x13)
464    }
465
466    #[test]
467    fn op() {
468        assert_eq!(decode(0x00c58633).unwrap(), Add(RType(0x00c58633))); // add x12,x11,x12
469        assert_eq!(decode(0x00d506b3).unwrap(), Add(RType(0x00d506b3))); // add x13,x10,x13
470        assert_eq!(decode(0x00a70533).unwrap(), Add(RType(0x00a70533))); // add x10,x14,x10
471        assert_eq!(decode(0x40b50533).unwrap(), Sub(RType(0x40b50533))); // sub x10,x10,x11
472        assert_eq!(decode(0x40e78533).unwrap(), Sub(RType(0x40e78533))); // sub x10,x15,x14
473        assert_eq!(decode(0x41060633).unwrap(), Sub(RType(0x41060633))); // sub x12,x12,x16
474        assert_eq!(decode(0x00209f33).unwrap(), Sll(RType(0x00209f33))); // sll x30,x1,x2
475        assert_eq!(decode(0x00209f33).unwrap(), Sll(RType(0x00209f33))); // sll x30,x1,x2
476        assert_eq!(decode(0x00209f33).unwrap(), Sll(RType(0x00209f33))); // sll x30,x1,x2
477        assert_eq!(decode(0x0020af33).unwrap(), Slt(RType(0x0020af33))); // slt x30,x1,x2
478        assert_eq!(decode(0x0020af33).unwrap(), Slt(RType(0x0020af33))); // slt x30,x1,x2
479        assert_eq!(decode(0x0020af33).unwrap(), Slt(RType(0x0020af33))); // slt x30,x1,x2
480        assert_eq!(decode(0x0020bf33).unwrap(), Sltu(RType(0x0020bf33))); // sltu x30,x1,x2
481        assert_eq!(decode(0x0020bf33).unwrap(), Sltu(RType(0x0020bf33))); // sltu x30,x1,x2
482        assert_eq!(decode(0x000030b3).unwrap(), Sltu(RType(0x000030b3))); // sltu x1,x0,x0
483        assert_eq!(decode(0x00f647b3).unwrap(), Xor(RType(0x00f647b3))); // xor x15,x12,x15
484        assert_eq!(decode(0x0020cf33).unwrap(), Xor(RType(0x0020cf33))); // xor x30,x1,x2
485        assert_eq!(decode(0x0020c133).unwrap(), Xor(RType(0x0020c133))); // xor x2,x1,x2
486        assert_eq!(decode(0x0020d0b3).unwrap(), Srl(RType(0x0020d0b3))); // srl x1,x1,x2
487        assert_eq!(decode(0x0020df33).unwrap(), Srl(RType(0x0020df33))); // srl x30,x1,x2
488        assert_eq!(decode(0x0020df33).unwrap(), Srl(RType(0x0020df33))); // srl x30,x1,x2
489        assert_eq!(decode(0x4020df33).unwrap(), Sra(RType(0x4020df33))); // sra x30,x1,x2
490        assert_eq!(decode(0x400050b3).unwrap(), Sra(RType(0x400050b3))); // sra x1,x0,x0
491        assert_eq!(decode(0x4020d133).unwrap(), Sra(RType(0x4020d133))); // sra x2,x1,x2
492        assert_eq!(decode(0x00b7e5b3).unwrap(), Or(RType(0x00b7e5b3))); // or x11,x15,x11
493        assert_eq!(decode(0x00f665b3).unwrap(), Or(RType(0x00f665b3))); // or x11,x12,x15
494        assert_eq!(decode(0x00b7e7b3).unwrap(), Or(RType(0x00b7e7b3))); // or x15,x15,x11
495        assert_eq!(decode(0x00d57533).unwrap(), And(RType(0x00d57533))); // and x10,x10,x13
496        assert_eq!(decode(0x00b7f733).unwrap(), And(RType(0x00b7f733))); // and x14,x15,x11
497        assert_eq!(decode(0x00c7f733).unwrap(), And(RType(0x00c7f733))); // and x14,x15,x12
498        assert_eq!(decode(0x021080b3).unwrap(), Mul(RType(0x021080b3))); // mul x1,x1,x1
499        assert_eq!(decode(0x02208f33).unwrap(), Mul(RType(0x02208f33))); // mul x30,x1,x2
500        assert_eq!(decode(0x02208133).unwrap(), Mul(RType(0x02208133))); // mul x2,x1,x2
501        assert_eq!(decode(0x02209133).unwrap(), Mulh(RType(0x02209133))); // mulh x2,x1,x2
502        assert_eq!(decode(0x02209f33).unwrap(), Mulh(RType(0x02209f33))); // mulh x30,x1,x2
503        assert_eq!(decode(0x02209f33).unwrap(), Mulh(RType(0x02209f33))); // mulh x30,x1,x2
504        assert_eq!(decode(0x0220a133).unwrap(), Mulhsu(RType(0x0220a133))); // mulhsu x2,x1,x2
505        assert_eq!(decode(0x0220af33).unwrap(), Mulhsu(RType(0x0220af33))); // mulhsu x30,x1,x2
506        assert_eq!(decode(0x0220af33).unwrap(), Mulhsu(RType(0x0220af33))); // mulhsu x30,x1,x2
507        assert_eq!(decode(0x0220bf33).unwrap(), Mulhu(RType(0x0220bf33))); // mulhu x30,x1,x2
508        assert_eq!(decode(0x0220bf33).unwrap(), Mulhu(RType(0x0220bf33))); // mulhu x30,x1,x2
509        assert_eq!(decode(0x0220bf33).unwrap(), Mulhu(RType(0x0220bf33))); // mulhu x30,x1,x2
510        assert_eq!(decode(0x0220cf33).unwrap(), Div(RType(0x0220cf33))); // div x30,x1,x2
511        assert_eq!(decode(0x0220cf33).unwrap(), Div(RType(0x0220cf33))); // div x30,x1,x2
512        assert_eq!(decode(0x0220cf33).unwrap(), Div(RType(0x0220cf33))); // div x30,x1,x2
513        assert_eq!(decode(0x0220df33).unwrap(), Divu(RType(0x0220df33))); // divu x30,x1,x2
514        assert_eq!(decode(0x0220df33).unwrap(), Divu(RType(0x0220df33))); // divu x30,x1,x2
515        assert_eq!(decode(0x0220df33).unwrap(), Divu(RType(0x0220df33))); // divu x30,x1,x2
516        assert_eq!(decode(0x0220ef33).unwrap(), Rem(RType(0x0220ef33))); // rem x30,x1,x2
517        assert_eq!(decode(0x0220ef33).unwrap(), Rem(RType(0x0220ef33))); // rem x30,x1,x2
518        assert_eq!(decode(0x0220ef33).unwrap(), Rem(RType(0x0220ef33))); // rem x30,x1,x2
519        assert_eq!(decode(0x0220ff33).unwrap(), Remu(RType(0x0220ff33))); // remu x30,x1,x2
520        assert_eq!(decode(0x0220ff33).unwrap(), Remu(RType(0x0220ff33))); // remu x30,x1,x2
521        assert_eq!(decode(0x0220ff33).unwrap(), Remu(RType(0x0220ff33))); // remu x30,x1,x2
522    }
523
524    #[test]
525    fn op32() {
526        assert_eq!(decode(0x00c687bb).unwrap(), Addw(RType(0x00c687bb))); // addw x15,x13,x12
527        assert_eq!(decode(0x00c687bb).unwrap(), Addw(RType(0x00c687bb))); // addw x15,x13,x12
528        assert_eq!(decode(0x00208f3b).unwrap(), Addw(RType(0x00208f3b))); // addw x30,x1,x2
529        assert_eq!(decode(0x40e5053b).unwrap(), Subw(RType(0x40e5053b))); // subw x10,x10,x14
530        assert_eq!(decode(0x40e5053b).unwrap(), Subw(RType(0x40e5053b))); // subw x10,x10,x14
531        assert_eq!(decode(0x40e5053b).unwrap(), Subw(RType(0x40e5053b))); // subw x10,x10,x14
532        assert_eq!(decode(0x001090bb).unwrap(), Sllw(RType(0x001090bb))); // sllw x1,x1,x1
533        assert_eq!(decode(0x00209f3b).unwrap(), Sllw(RType(0x00209f3b))); // sllw x30,x1,x2
534        assert_eq!(decode(0x00209f3b).unwrap(), Sllw(RType(0x00209f3b))); // sllw x30,x1,x2
535        assert_eq!(decode(0x0020df3b).unwrap(), Srlw(RType(0x0020df3b))); // srlw x30,x1,x2
536        assert_eq!(decode(0x0020df3b).unwrap(), Srlw(RType(0x0020df3b))); // srlw x30,x1,x2
537        assert_eq!(decode(0x0020d13b).unwrap(), Srlw(RType(0x0020d13b))); // srlw x2,x1,x2
538        assert_eq!(decode(0x4020df3b).unwrap(), Sraw(RType(0x4020df3b))); // sraw x30,x1,x2
539        assert_eq!(decode(0x4020df3b).unwrap(), Sraw(RType(0x4020df3b))); // sraw x30,x1,x2
540        assert_eq!(decode(0x4020df3b).unwrap(), Sraw(RType(0x4020df3b))); // sraw x30,x1,x2
541        assert_eq!(decode(0x02208f3b).unwrap(), Mulw(RType(0x02208f3b))); // mulw x30,x1,x2
542        assert_eq!(decode(0x02208f3b).unwrap(), Mulw(RType(0x02208f3b))); // mulw x30,x1,x2
543        assert_eq!(decode(0x02208f3b).unwrap(), Mulw(RType(0x02208f3b))); // mulw x30,x1,x2
544        assert_eq!(decode(0x0220cf3b).unwrap(), Divw(RType(0x0220cf3b))); // divw x30,x1,x2
545        assert_eq!(decode(0x0220cf3b).unwrap(), Divw(RType(0x0220cf3b))); // divw x30,x1,x2
546        assert_eq!(decode(0x0220cf3b).unwrap(), Divw(RType(0x0220cf3b))); // divw x30,x1,x2
547        assert_eq!(decode(0x0220df3b).unwrap(), Divuw(RType(0x0220df3b))); // divuw x30,x1,x2
548        assert_eq!(decode(0x0220df3b).unwrap(), Divuw(RType(0x0220df3b))); // divuw x30,x1,x2
549        assert_eq!(decode(0x0220df3b).unwrap(), Divuw(RType(0x0220df3b))); // divuw x30,x1,x2
550        assert_eq!(decode(0x0220ef3b).unwrap(), Remw(RType(0x0220ef3b))); // remw x30,x1,x2
551        assert_eq!(decode(0x0220ef3b).unwrap(), Remw(RType(0x0220ef3b))); // remw x30,x1,x2
552        assert_eq!(decode(0x0220ef3b).unwrap(), Remw(RType(0x0220ef3b))); // remw x30,x1,x2
553        assert_eq!(decode(0x0220ff3b).unwrap(), Remuw(RType(0x0220ff3b))); // remuw x30,x1,x2
554        assert_eq!(decode(0x0220ff3b).unwrap(), Remuw(RType(0x0220ff3b))); // remuw x30,x1,x2
555        assert_eq!(decode(0x0220ff3b).unwrap(), Remuw(RType(0x0220ff3b))); // remuw x30,x1,x2
556    }
557
558    #[test]
559    fn branch() {
560        assert_eq!(decode(0x10e78463).unwrap(), Beq(BType(0x10e78463))); // beq x15,x14,800024b8
561        assert_eq!(decode(0x00050a63).unwrap(), Beq(BType(0x00050a63))); // beq x10,x0,80002538
562        assert_eq!(decode(0x1b5a0463).unwrap(), Beq(BType(0x1b5a0463))); // beq x20,x21,80002a10
563        assert_eq!(decode(0xfe5210e3).unwrap(), Bne(BType(0xfe5210e3))); // bne x4,x5,800001f4
564        assert_eq!(decode(0x00e79a63).unwrap(), Bne(BType(0x00e79a63))); // bne x15,x14,80002184
565        assert_eq!(decode(0x25df1863).unwrap(), Bne(BType(0x25df1863))); // bne x30,x29,80002f90
566        assert_eq!(decode(0x1220c063).unwrap(), Blt(BType(0x1220c063))); // blt x1,x2,800003c4
567        assert_eq!(decode(0x00054863).unwrap(), Blt(BType(0x00054863))); // blt x10,x0,800000c4
568        assert_eq!(decode(0xfe20cee3).unwrap(), Blt(BType(0xfe20cee3))); // blt x1,x2,80000158
569        assert_eq!(decode(0x000f5463).unwrap(), Bge(BType(0x000f5463))); // bge x30,x0,8000003c
570        assert_eq!(decode(0x0020d663).unwrap(), Bge(BType(0x0020d663))); // bge x1,x2,80002b88
571        assert_eq!(decode(0x0620d463).unwrap(), Bge(BType(0x0620d463))); // bge x1,x2,80002f04
572        assert_eq!(decode(0xfec7ece3).unwrap(), Bltu(BType(0xfec7ece3))); // bltu x15,x12,800020a8
573        assert_eq!(decode(0xfec7ece3).unwrap(), Bltu(BType(0xfec7ece3))); // bltu x15,x12,800020a8
574        assert_eq!(decode(0x0020e663).unwrap(), Bltu(BType(0x0020e663))); // bltu x1,x2,80002b18
575        assert_eq!(decode(0x00f5f463).unwrap(), Bgeu(BType(0x00f5f463))); // bgeu x11,x15,80002290
576        assert_eq!(decode(0x00f5f463).unwrap(), Bgeu(BType(0x00f5f463))); // bgeu x11,x15,80002290
577        assert_eq!(decode(0xfec572e3).unwrap(), Bgeu(BType(0xfec572e3))); // bgeu x10,x12,80002084
578    }
579
580    #[test]
581    fn system() {
582        assert_eq!(decode(0x00000073).unwrap(), Ecall); // ecall
583        assert_eq!(decode(0x10200073).unwrap(), Sret); // sret
584        assert_eq!(decode(0x30200073).unwrap(), Mret); // mret
585        assert_eq!(decode(0x10500073).unwrap(), Wfi); // wfi
586        assert_eq!(decode(0x10569073).unwrap(), Csrrw(CsrType(0x10569073))); // csrrw x0,stvec,x13
587        assert_eq!(decode(0x18079073).unwrap(), Csrrw(CsrType(0x18079073))); // csrrw x0,satp,x15
588        assert_eq!(decode(0x10551073).unwrap(), Csrrw(CsrType(0x10551073))); // csrrw x0,stvec,x10
589        assert_eq!(decode(0x1007a073).unwrap(), Csrrs(CsrType(0x1007a073))); // csrrs x0,sstatus,x15
590        assert_eq!(decode(0x1006a073).unwrap(), Csrrs(CsrType(0x1006a073))); // csrrs x0,sstatus,x13
591        assert_eq!(decode(0x1004b073).unwrap(), Csrrc(CsrType(0x1004b073))); // csrrc x0,sstatus,x9
592        assert_eq!(decode(0x100db073).unwrap(), Csrrc(CsrType(0x100db073))); // csrrc x0,sstatus,x27
593        assert_eq!(decode(0x1006b073).unwrap(), Csrrc(CsrType(0x1006b073))); // csrrc x0,sstatus,x13
594        assert_eq!(decode(0x14005073).unwrap(), Csrrwi(CsrIType(0x14005073))); // csrrwi x0,sscratch,0
595        assert_eq!(decode(0x10016073).unwrap(), Csrrsi(CsrIType(0x10016073))); // csrrsi x0,sstatus,2
596        assert_eq!(decode(0x100176f3).unwrap(), Csrrci(CsrIType(0x100176f3))); // csrrci x13,sstatus,2
597        assert_eq!(decode(0x10017773).unwrap(), Csrrci(CsrIType(0x10017773))); // csrrci x14,sstatus,2
598    }
599
600    #[test]
601    fn float() {
602        assert_eq!(decode(0x0004a787).unwrap(), Flw(IType(0x0004a787))); // flw fa5,0(s1)
603        assert_eq!(decode(0x1e872687).unwrap(), Flw(IType(0x1e872687))); // flw fa3,488(a4)
604        assert_eq!(decode(0x1e472707).unwrap(), Flw(IType(0x1e472707))); // flw fa4,484(a4)
605        assert_eq!(decode(0x00aa2027).unwrap(), Fsw(SType(0x00aa2027))); // fsw fa0,0(s4)
606        assert_eq!(decode(0x00f4a027).unwrap(), Fsw(SType(0x00f4a027))); // fsw fa5,0(s1)
607        assert_eq!(decode(0x00fba827).unwrap(), Fsw(SType(0x00fba827))); // fsw fa5,16(s7)
608        assert_eq!(decode(0xd19b1543).unwrap(), Fmadds(R4Type(0xd19b1543))); // fmadd.s fa0,fs6,fs9,fs10,rtz
609        assert_eq!(decode(0x114f8bc3).unwrap(), Fmadds(R4Type(0x114f8bc3))); // fmadd.s fs7,ft11,fs4,ft2,rne
610        assert_eq!(decode(0x08cf53c3).unwrap(), Fmadds(R4Type(0x08cf53c3))); // fmadd.s ft7,ft10,fa2,ft1,unknown
611        assert_eq!(decode(0x3166dd47).unwrap(), Fmsubs(R4Type(0x3166dd47))); // fmsub.s fs10,fa3,fs6,ft6,unknown
612        assert_eq!(decode(0x50077347).unwrap(), Fmsubs(R4Type(0x50077347))); // fmsub.s ft6,fa4,ft0,fa0
613        assert_eq!(decode(0xb903e1c7).unwrap(), Fmsubs(R4Type(0xb903e1c7))); // fmsub.s ft3,ft7,fa6,fs7,unknown
614        assert_eq!(decode(0xc9cd48cb).unwrap(), Fnmsubs(R4Type(0xc9cd48cb))); // fnmsub.s fa7,fs10,ft8,fs9,rmm
615        assert_eq!(decode(0xa1ee44cb).unwrap(), Fnmsubs(R4Type(0xa1ee44cb))); // fnmsub.s fs1,ft8,ft10,fs4,rmm
616        assert_eq!(decode(0xf8db734b).unwrap(), Fnmsubs(R4Type(0xf8db734b))); // fnmsub.s ft6,fs6,fa3,ft11
617        assert_eq!(decode(0x19613e4f).unwrap(), Fnmadds(R4Type(0x19613e4f))); // fnmadd.s ft8,ft2,fs6,ft3,rup
618        assert_eq!(decode(0xc944cfcf).unwrap(), Fnmadds(R4Type(0xc944cfcf))); // fnmadd.s ft11,fs1,fs4,fs9,rmm
619        assert_eq!(decode(0x191506cf).unwrap(), Fnmadds(R4Type(0x191506cf))); // fnmadd.s fa3,fa0,fa7,ft3,rne
620        assert_eq!(decode(0x0127f553).unwrap(), Fadds(RType(0x0127f553))); // fadd.s fa0,fa5,fs2
621        assert_eq!(decode(0x01257553).unwrap(), Fadds(RType(0x01257553))); // fadd.s fa0,fa0,fs2
622        assert_eq!(decode(0x0135f9d3).unwrap(), Fadds(RType(0x0135f9d3))); // fadd.s fs3,fa1,fs3
623        assert_eq!(decode(0x0897f7d3).unwrap(), Fsubs(RType(0x0897f7d3))); // fsub.s fa5,fa5,fs1
624        assert_eq!(decode(0x0957f7d3).unwrap(), Fsubs(RType(0x0957f7d3))); // fsub.s fa5,fa5,fs5
625        assert_eq!(decode(0x0935f753).unwrap(), Fsubs(RType(0x0935f753))); // fsub.s fa4,fa1,fs3
626        assert_eq!(decode(0x10f97953).unwrap(), Fmuls(RType(0x10f97953))); // fmul.s fs2,fs2,fa5
627        assert_eq!(decode(0x1187f7d3).unwrap(), Fmuls(RType(0x1187f7d3))); // fmul.s fa5,fa5,fs8
628        assert_eq!(decode(0x116b7553).unwrap(), Fmuls(RType(0x116b7553))); // fmul.s fa0,fs6,fs6
629        assert_eq!(decode(0x1947f553).unwrap(), Fdivs(RType(0x1947f553))); // fdiv.s fa0,fa5,fs4
630        assert_eq!(decode(0x18a7f553).unwrap(), Fdivs(RType(0x18a7f553))); // fdiv.s fa0,fa5,fa0
631        assert_eq!(decode(0x18f777d3).unwrap(), Fdivs(RType(0x18f777d3))); // fdiv.s fa5,fa4,fa5
632        assert_eq!(decode(0x58057553).unwrap(), Fsqrts(RType(0x58057553))); // fsqrt.s fa0,fa0
633        assert_eq!(decode(0x580e35d3).unwrap(), Fsqrts(RType(0x580e35d3))); // fsqrt.s fa1,ft8,rup
634        assert_eq!(decode(0x5808c0d3).unwrap(), Fsqrts(RType(0x5808c0d3))); // fsqrt.s ft1,fa7,rmm
635        assert_eq!(decode(0x21ca0ed3).unwrap(), Fsgnjs(RType(0x21ca0ed3))); // fsgnj.s ft9,fs4,ft8
636        assert_eq!(decode(0x20d103d3).unwrap(), Fsgnjs(RType(0x20d103d3))); // fsgnj.s ft7,ft2,fa3
637        assert_eq!(decode(0x209c0d53).unwrap(), Fsgnjs(RType(0x209c0d53))); // fsgnj.s fs10,fs8,fs1
638        assert_eq!(decode(0x21dd1b53).unwrap(), Fsgnjns(RType(0x21dd1b53))); // fsgnjn.s fs6,fs10,ft9
639        assert_eq!(decode(0x20971153).unwrap(), Fsgnjns(RType(0x20971153))); // fsgnjn.s ft2,fa4,fs1
640        assert_eq!(decode(0x211d1953).unwrap(), Fsgnjns(RType(0x211d1953))); // fsgnjn.s fs2,fs10,fa7
641        assert_eq!(decode(0x20eb2153).unwrap(), Fsgnjxs(RType(0x20eb2153))); // fsgnjx.s ft2,fs6,fa4
642        assert_eq!(decode(0x219fa7d3).unwrap(), Fsgnjxs(RType(0x219fa7d3))); // fsgnjx.s fa5,ft11,fs9
643        assert_eq!(decode(0x215baad3).unwrap(), Fsgnjxs(RType(0x215baad3))); // fsgnjx.s fs5,fs7,fs5
644        assert_eq!(decode(0x286b82d3).unwrap(), Fmins(RType(0x286b82d3))); // fmin.s ft5,fs7,ft6
645        assert_eq!(decode(0x29ac88d3).unwrap(), Fmins(RType(0x29ac88d3))); // fmin.s fa7,fs9,fs10
646        assert_eq!(decode(0x29728c53).unwrap(), Fmins(RType(0x29728c53))); // fmin.s fs8,ft5,fs7
647        assert_eq!(decode(0x29441153).unwrap(), Fmaxs(RType(0x29441153))); // fmax.s ft2,fs0,fs4
648        assert_eq!(decode(0x29689fd3).unwrap(), Fmaxs(RType(0x29689fd3))); // fmax.s ft11,fa7,fs6
649        assert_eq!(decode(0x286a1fd3).unwrap(), Fmaxs(RType(0x286a1fd3))); // fmax.s ft11,fs4,ft6
650        assert_eq!(decode(0xc0056553).unwrap(), Fcvtws(RType(0xc0056553))); // fcvt.w.s a0,fa0,unknown
651        assert_eq!(decode(0xc006fad3).unwrap(), Fcvtws(RType(0xc006fad3))); // fcvt.w.s s5,fa3
652        assert_eq!(decode(0xc00fa8d3).unwrap(), Fcvtws(RType(0xc00fa8d3))); // fcvt.w.s a7,ft11,rdn
653        assert_eq!(decode(0xc014cb53).unwrap(), Fcvtwus(RType(0xc014cb53))); // fcvt.wu.s s6,fs1,rmm
654        assert_eq!(decode(0xc01698d3).unwrap(), Fcvtwus(RType(0xc01698d3))); // fcvt.wu.s a7,fa3,rtz
655        assert_eq!(decode(0xc01e5dd3).unwrap(), Fcvtwus(RType(0xc01e5dd3))); // fcvt.wu.s s11,ft8,unknown
656        assert_eq!(decode(0xe00482d3).unwrap(), Fmvxw(RType(0xe00482d3))); // fmv.x.w t0,fs1
657        assert_eq!(decode(0xe00d86d3).unwrap(), Fmvxw(RType(0xe00d86d3))); // fmv.x.w a3,fs11
658        assert_eq!(decode(0xe0088053).unwrap(), Fmvxw(RType(0xe0088053))); // fmv.x.w zero,fa7
659        assert_eq!(decode(0xa0742153).unwrap(), Feqs(RType(0xa0742153))); // feq.s sp,fs0,ft7
660        assert_eq!(decode(0xa0a0a153).unwrap(), Feqs(RType(0xa0a0a153))); // feq.s sp,ft1,fa0
661        assert_eq!(decode(0xa1aba853).unwrap(), Feqs(RType(0xa1aba853))); // feq.s a6,fs7,fs10
662        assert_eq!(decode(0xa0651953).unwrap(), Flts(RType(0xa0651953))); // flt.s s2,fa0,ft6
663        assert_eq!(decode(0xa0ab9f53).unwrap(), Flts(RType(0xa0ab9f53))); // flt.s t5,fs7,fa0
664        assert_eq!(decode(0xa19595d3).unwrap(), Flts(RType(0xa19595d3))); // flt.s a1,fa1,fs9
665        assert_eq!(decode(0xa1ff8d53).unwrap(), Fles(RType(0xa1ff8d53))); // fle.s s10,ft11,ft11
666        assert_eq!(decode(0xa0f40653).unwrap(), Fles(RType(0xa0f40653))); // fle.s a2,fs0,fa5
667        assert_eq!(decode(0xa1ab0c53).unwrap(), Fles(RType(0xa1ab0c53))); // fle.s s8,fs6,fs10
668        assert_eq!(decode(0xe00a1e53).unwrap(), Fclasss(RType(0xe00a1e53))); // fclass.s t3,fs4
669        assert_eq!(decode(0xe00f1c53).unwrap(), Fclasss(RType(0xe00f1c53))); // fclass.s s8,ft10
670        assert_eq!(decode(0xe00e9d53).unwrap(), Fclasss(RType(0xe00e9d53))); // fclass.s s10,ft9
671        assert_eq!(decode(0xd009d7d3).unwrap(), Fcvtsw(RType(0xd009d7d3))); // fcvt.s.w fa5,s3,unknown
672        assert_eq!(decode(0xd001a953).unwrap(), Fcvtsw(RType(0xd001a953))); // fcvt.s.w fs2,gp,rdn
673        assert_eq!(decode(0xd00507d3).unwrap(), Fcvtsw(RType(0xd00507d3))); // fcvt.s.w fa5,a0,rne
674        assert_eq!(decode(0xd01c27d3).unwrap(), Fcvtswu(RType(0xd01c27d3))); // fcvt.s.wu fa5,s8,rdn
675        assert_eq!(decode(0xd019edd3).unwrap(), Fcvtswu(RType(0xd019edd3))); // fcvt.s.wu fs11,s3,unknown
676        assert_eq!(decode(0xd012c3d3).unwrap(), Fcvtswu(RType(0xd012c3d3))); // fcvt.s.wu ft7,t0,rmm
677        assert_eq!(decode(0xf0000e53).unwrap(), Fmvwx(RType(0xf0000e53))); // fmv.w.x ft8,zero
678        assert_eq!(decode(0xf0098053).unwrap(), Fmvwx(RType(0xf0098053))); // fmv.w.x ft0,s3
679        assert_eq!(decode(0xf00081d3).unwrap(), Fmvwx(RType(0xf00081d3))); // fmv.w.x ft3,ra
680    }
681
682    #[test]
683    fn amo() {
684        assert_eq!(decode(0x08b6a72f).unwrap(), AmoswapW(RType(0x08b6a72f))); // amoswap.w a4,a1,(a3)
685        assert_eq!(decode(0x00b6a72f).unwrap(), AmoaddW(RType(0x00b6a72f))); // amoadd.w a4,a1,(a3)
686        assert_eq!(decode(0x20b6a72f).unwrap(), AmoxorW(RType(0x20b6a72f))); // amoxor.w a4,a1,(a3)
687        assert_eq!(decode(0x60b6a72f).unwrap(), AmoandW(RType(0x60b6a72f))); // amoand.w a4,a1,(a3)
688        assert_eq!(decode(0x40b6a72f).unwrap(), AmoorW(RType(0x40b6a72f))); // amoor.w a4,a1,(a3)
689        assert_eq!(decode(0x80b6a72f).unwrap(), AmominW(RType(0x80b6a72f))); // amomin.w a4,a1,(a3)
690        assert_eq!(decode(0xa0b6a72f).unwrap(), AmomaxW(RType(0xa0b6a72f))); // amomax.w a4,a1,(a3)
691        assert_eq!(decode(0xc0b6a72f).unwrap(), AmominuW(RType(0xc0b6a72f))); // amominu.w a4,a1,(a3)
692        assert_eq!(decode(0xe0b6a72f).unwrap(), AmomaxuW(RType(0xe0b6a72f))); // amomaxu.w a4,a1,(a3)
693        assert_eq!(decode(0x100525af).unwrap(), LrW(RType(0x100525af))); // lr.w a1,(a0)
694        assert_eq!(decode(0x180525af).unwrap(), ScW(RType(0x180525af))); // sc.w a1,zero,(a0)
695        assert_eq!(decode(0x08b6b72f).unwrap(), AmoswapD(RType(0x08b6b72f))); // amoswap.d a4,a1,(a3)
696        assert_eq!(decode(0x00b6b72f).unwrap(), AmoaddD(RType(0x00b6b72f))); // amoadd.d a4,a1,(a3)
697        assert_eq!(decode(0x20b6b72f).unwrap(), AmoxorD(RType(0x20b6b72f))); // amoxor.d a4,a1,(a3)
698        assert_eq!(decode(0x60b6b72f).unwrap(), AmoandD(RType(0x60b6b72f))); // amoand.d a4,a1,(a3)
699        assert_eq!(decode(0x40b6b72f).unwrap(), AmoorD(RType(0x40b6b72f))); // amoor.d a4,a1,(a3)
700        assert_eq!(decode(0x80b6b72f).unwrap(), AmominD(RType(0x80b6b72f))); // amomin.d a4,a1,(a3)
701        assert_eq!(decode(0xa0b6b72f).unwrap(), AmomaxD(RType(0xa0b6b72f))); // amomax.d a4,a1,(a3)
702        assert_eq!(decode(0xc0b6b72f).unwrap(), AmominuD(RType(0xc0b6b72f))); // amominu.d a4,a1,(a3)
703        assert_eq!(decode(0xe0b6b72f).unwrap(), AmomaxuD(RType(0xe0b6b72f))); // amomaxu.d a4,a1,(a3)
704        assert_eq!(decode(0x1005372f).unwrap(), LrD(RType(0x1005372f))); // lr.d a1,(a0)
705        assert_eq!(decode(0x180535af).unwrap(), ScD(RType(0x180535af))); // sc.d a1,zero,(a0)
706    }
707}