1use std::fmt::{Display, Formatter};
2
3use crate::{
4 immediates::{
5 BImmediate, C16SPImmediate, CBImmediate, CDImmediate, CDSPImmediate, CIImmediate,
6 CJImmediate, CSDSPImmediate, CSWSPImmediate, CShamt, CWImmediate, CWSPImmediate,
7 CWideImmediate, IImmediate, JImmediate, SImmediate, Shamt,
8 },
9 instruction::Instruction,
10 register::{CFRegister, CIRegister, FRegister, IRegister},
11};
12
13#[derive(Debug, PartialEq)]
14pub enum CInstruction {
15 ADDI4SPN {
19 dest: CIRegister,
20 imm: CWideImmediate,
21 },
22 FLD {
23 dest: CFRegister,
24 base: CIRegister,
25 offset: CDImmediate,
26 },
27 LW {
28 dest: CIRegister,
29 base: CIRegister,
30 offset: CWImmediate,
31 },
32 LD {
33 dest: CIRegister,
34 base: CIRegister,
35 offset: CDImmediate,
36 },
37 FSD {
38 src: CFRegister,
39 base: CIRegister,
40 offset: CDImmediate,
41 },
42 SW {
43 src: CIRegister,
44 base: CIRegister,
45 offset: CWImmediate,
46 },
47 SD {
48 src: CIRegister,
49 base: CIRegister,
50 offset: CDImmediate,
51 },
52 ADDI {
53 dest: IRegister,
54 imm: CIImmediate,
55 },
56 ADDIW {
57 dest: IRegister,
58 imm: CIImmediate,
59 },
60 LI {
61 dest: IRegister,
62 imm: CIImmediate,
63 },
64 ADDI16SP {
65 imm: C16SPImmediate,
66 },
67 LUI {
68 dest: IRegister,
69 imm: CIImmediate,
70 },
71 SRLI {
72 dest: CIRegister,
73 shamt: CShamt,
74 },
75 SRAI {
76 dest: CIRegister,
77 shamt: CShamt,
78 },
79 ANDI {
80 dest: CIRegister,
81 imm: CIImmediate,
82 },
83 SUB {
84 dest: CIRegister,
85 src: CIRegister,
86 },
87 XOR {
88 dest: CIRegister,
89 src: CIRegister,
90 },
91 OR {
92 dest: CIRegister,
93 src: CIRegister,
94 },
95 AND {
96 dest: CIRegister,
97 src: CIRegister,
98 },
99 SUBW {
100 dest: CIRegister,
101 src: CIRegister,
102 },
103 ADDW {
104 dest: CIRegister,
105 src: CIRegister,
106 },
107 J {
108 offset: CJImmediate,
109 },
110 BEQZ {
111 src: CIRegister,
112 offset: CBImmediate,
113 },
114 BNEZ {
115 src: CIRegister,
116 offset: CBImmediate,
117 },
118 SLLI {
119 dest: IRegister,
120 shamt: CShamt,
121 },
122 FLDSP {
123 dest: FRegister,
124 offset: CDSPImmediate,
125 },
126 LWSP {
127 dest: IRegister,
128 offset: CWSPImmediate,
129 },
130 LDSP {
131 dest: IRegister,
132 offset: CDSPImmediate,
133 },
134 JR {
135 src: IRegister,
136 },
137 MV {
138 dest: IRegister,
139 src: IRegister,
140 },
141 EBREAK,
142 JALR {
143 src: IRegister,
144 },
145 ADD {
146 dest: IRegister,
147 src: IRegister,
148 },
149 FSDSP {
150 src: FRegister,
151 offset: CSDSPImmediate,
152 },
153 SWSP {
154 src: IRegister,
155 offset: CSWSPImmediate,
156 },
157 SDSP {
158 src: IRegister,
159 offset: CSDSPImmediate,
160 },
161}
162
163impl Display for CInstruction {
164 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
165 match self {
166 CInstruction::ADDI4SPN { dest, imm } => write!(f, "c.addi4spn {dest},{imm}"),
167 CInstruction::FLD {
168 dest: rd,
169 base,
170 offset,
171 } => write!(f, "c.fld {rd},{offset}({base})"),
172 CInstruction::LW {
173 dest: rd,
174 base,
175 offset,
176 } => write!(f, "c.lw {rd},{offset}({base})"),
177 CInstruction::LD {
178 dest: rd,
179 base,
180 offset,
181 } => write!(f, "c.ld {rd},{offset}({base})"),
182 CInstruction::FSD { src, base, offset } => write!(f, "c.fsd {src},{offset}({base})"),
183 CInstruction::SW { src, base, offset } => write!(f, "c.sw {src},{offset}({base})"),
184 CInstruction::SD { src, base, offset } => write!(f, "c.sd {src},{offset}({base})"),
185 CInstruction::ADDI { dest, imm } => write!(f, "c.addi {dest},{imm}"),
186 CInstruction::ADDIW { dest, imm } => write!(f, "c.addiw {dest},{imm}"),
187 CInstruction::LI { dest, imm } => write!(f, "c.li {dest},{imm}"),
188 CInstruction::ADDI16SP { imm } => write!(f, "c.addi16sp {imm}"),
189 CInstruction::LUI { dest, imm } => write!(f, "c.lui {dest},{imm}"),
190 CInstruction::SRLI { dest, shamt } => write!(f, "c.srli {dest},{shamt}"),
191 CInstruction::SRAI { dest, shamt } => write!(f, "c.srai {dest},{shamt}"),
192 CInstruction::ANDI { dest, imm } => write!(f, "c.andi {dest},{imm}"),
193 CInstruction::SUB { dest: rd, src: rs2 } => write!(f, "c.sub {rd},{rs2}"),
194 CInstruction::XOR { dest: rd, src: rs2 } => write!(f, "c.xor {rd},{rs2}"),
195 CInstruction::OR { dest: rd, src: rs2 } => write!(f, "c.or {rd},{rs2}"),
196 CInstruction::AND { dest: rd, src: rs2 } => write!(f, "c.and {rd},{rs2}"),
197 CInstruction::SUBW { dest: rd, src: rs2 } => write!(f, "c.subw {rd},{rs2}"),
198 CInstruction::ADDW { dest: rd, src: rs2 } => write!(f, "c.addw {rd},{rs2}"),
199 CInstruction::J { offset } => write!(f, "c.j {offset}"),
200 CInstruction::BEQZ { src, offset } => write!(f, "c.beqz {src},{offset}"),
201 CInstruction::BNEZ { src, offset } => write!(f, "c.bnez {src},{offset}"),
202 CInstruction::SLLI { dest, shamt } => write!(f, "c.slli {dest},{shamt}"),
203 CInstruction::FLDSP { dest, offset } => write!(f, "c.fldsp {dest},{offset}"),
204 CInstruction::LWSP { dest, offset } => write!(f, "c.lwsp {dest},{offset}"),
205 CInstruction::LDSP { dest, offset } => write!(f, "c.ldsp {dest},{offset}"),
206 CInstruction::JR { src } => write!(f, "c.jr {src}"),
207 CInstruction::MV { dest, src } => write!(f, "c.mv {dest},{src}"),
208 CInstruction::EBREAK => write!(f, "c.ebreak"),
209 CInstruction::JALR { src } => write!(f, "c.jalr {src}"),
210 CInstruction::ADD { dest: rd, src: rs2 } => write!(f, "c.add {rd},{rs2}"),
211 CInstruction::FSDSP { src, offset } => write!(f, "c.fsdsp {src},{offset}"),
212 CInstruction::SWSP { src, offset } => write!(f, "c.swsp {src},{offset}"),
213 CInstruction::SDSP { src, offset } => write!(f, "c.sdsp {src},{offset}"),
214 }
215 }
216}
217
218impl CInstruction {
219 pub fn decode(instruction: u16) -> Result<Self, String> {
221 let crs2 = CIRegister::try_from((instruction >> 2) & 0b111).unwrap();
222 let cfrd = CFRegister::try_from((instruction >> 2) & 0b111).unwrap();
223
224 let crs1 = CIRegister::from((instruction >> 7) & 0b111);
225
226 let ciimmediate = CIImmediate::from_u16(instruction);
227
228 let cshamt = CShamt::from_u16(instruction);
229
230 let rd = IRegister::from_int(((instruction >> 7) & 0b1_1111) as u32);
231 let frd = FRegister::try_from(((instruction >> 7) & 0b1_1111) as u32).unwrap();
232 let rs2 = IRegister::from_int(((instruction >> 2) & 0b1_1111) as u32);
233 let frs2 = FRegister::try_from(((instruction >> 2) & 0b1_1111) as u32).unwrap();
234
235 match instruction & 0b11 {
236 0b00 => match instruction >> 13 {
237 0b000 => {
238 let imm = CWideImmediate::from_u16(instruction);
239 if imm.val() == 0 {
240 Err("compressed illegal instruction".to_owned())
241 } else {
242 Ok(CInstruction::ADDI4SPN { dest: crs2, imm })
243 }
244 }
245 0b001 => Ok(CInstruction::FLD {
246 dest: cfrd,
247 base: crs1,
248 offset: CDImmediate::from_u16(instruction),
249 }),
250 0b010 => Ok(CInstruction::LW {
251 dest: crs2,
252 base: crs1,
253 offset: CWImmediate::from_u16(instruction),
254 }),
255 0b011 => Ok(CInstruction::LD {
256 dest: crs2,
257 base: crs1,
258 offset: CDImmediate::from_u16(instruction),
259 }),
260 0b100 => Err("reserved opcode in C instruction".to_owned()),
261 0b101 => Ok(CInstruction::FSD {
262 src: cfrd,
263 base: crs1,
264 offset: CDImmediate::from_u16(instruction),
265 }),
266 0b110 => Ok(CInstruction::SW {
267 src: crs2,
268 base: crs1,
269 offset: CWImmediate::from_u16(instruction),
270 }),
271 0b111 => Ok(CInstruction::SD {
272 src: crs2,
273 base: crs1,
274 offset: CDImmediate::from_u16(instruction),
275 }),
276 _ => unreachable!(),
277 },
278 0b01 => match instruction >> 13 {
279 0b000 => Ok(CInstruction::ADDI {
280 dest: rd,
281 imm: ciimmediate,
282 }),
283 0b001 => Ok(CInstruction::ADDIW {
284 dest: rd,
285 imm: ciimmediate,
286 }),
287 0b010 => Ok(CInstruction::LI {
288 dest: rd,
289 imm: ciimmediate,
290 }),
291 0b011 => {
292 if (instruction >> 7) & 0b111 == 2 {
293 Ok(CInstruction::ADDI16SP {
294 imm: C16SPImmediate::from_u16(instruction),
295 })
296 } else {
297 Ok(CInstruction::LUI {
298 dest: rd,
299 imm: ciimmediate,
300 })
301 }
302 }
303 0b100 => match (instruction >> 10) & 0b11 {
304 0b00 => Ok(CInstruction::SRLI {
305 dest: crs1,
306 shamt: cshamt,
307 }),
308 0b01 => Ok(CInstruction::SRAI {
309 dest: crs1,
310 shamt: cshamt,
311 }),
312 0b10 => Ok(CInstruction::ANDI {
313 dest: crs1,
314 imm: ciimmediate,
315 }),
316 0b11 => match ((instruction >> 5) & 0b11, (instruction >> 12) & 0b1) {
317 (0b00, 0b0) => Ok(CInstruction::SUB {
318 dest: crs1,
319 src: crs2,
320 }),
321 (0b01, 0b0) => Ok(CInstruction::XOR {
322 dest: crs1,
323 src: crs2,
324 }),
325 (0b10, 0b0) => Ok(CInstruction::OR {
326 dest: crs1,
327 src: crs2,
328 }),
329 (0b11, 0b0) => Ok(CInstruction::AND {
330 dest: crs1,
331 src: crs2,
332 }),
333 (0b00, 0b1) => Ok(CInstruction::SUBW {
334 dest: crs1,
335 src: crs2,
336 }),
337 (0b01, 0b1) => Ok(CInstruction::ADDW {
338 dest: crs1,
339 src: crs2,
340 }),
341 _ => Err("Reserved instruction".to_owned()),
342 },
343 _ => unreachable!(),
344 },
345 0b101 => Ok(CInstruction::J {
346 offset: CJImmediate::from_u16(instruction),
347 }),
348 0b110 => Ok(CInstruction::BEQZ {
349 src: crs1,
350 offset: CBImmediate::from_u16(instruction),
351 }),
352 0b111 => Ok(CInstruction::BNEZ {
353 src: crs1,
354 offset: CBImmediate::from_u16(instruction),
355 }),
356 _ => unreachable!(),
357 },
358 0b10 => match instruction >> 13 {
359 0b000 => Ok(CInstruction::SLLI {
360 dest: rd,
361 shamt: cshamt,
362 }),
363 0b001 => Ok(CInstruction::FLDSP {
364 dest: frd,
365 offset: CDSPImmediate::from_u16(instruction),
366 }),
367 0b010 => Ok(CInstruction::LWSP {
368 dest: rd,
369 offset: CWSPImmediate::from_u16(instruction),
370 }),
371 0b011 => Ok(CInstruction::LDSP {
372 dest: rd,
373 offset: CDSPImmediate::from_u16(instruction),
374 }),
375 0b100 => {
376 match (
377 (instruction >> 12) & 0b1,
378 (instruction >> 7) & 0b1_1111,
379 (instruction >> 2) & 0b1_1111,
380 ) {
381 (0, _, 0) => Ok(CInstruction::JR { src: rd }),
382 (0, _, _) => Ok(CInstruction::MV { dest: rd, src: rs2 }),
383 (1, 0, 0) => Ok(CInstruction::EBREAK),
384 (1, _, 0) => Ok(CInstruction::JALR { src: rd }),
385 (1, _, _) => Ok(CInstruction::ADD { dest: rd, src: rs2 }),
386 _ => unreachable!(),
387 }
388 }
389 0b101 => Ok(CInstruction::FSDSP {
390 src: frs2,
391 offset: CSDSPImmediate::from_u16(instruction),
392 }),
393 0b110 => Ok(CInstruction::SWSP {
394 src: rs2,
395 offset: CSWSPImmediate::from_u16(instruction),
396 }),
397 0b111 => Ok(CInstruction::SDSP {
398 src: rs2,
399 offset: CSDSPImmediate::from_u16(instruction),
400 }),
401 _ => unreachable!(),
402 },
403 0b11 => {
404 Err("attempting to decode larger instruction as though it were 16 bits".to_owned())
405 }
406 _ => unreachable!(),
407 }
408 }
409
410 pub fn disassemble(instruction: &CInstruction) -> String {
411 format!("{}", instruction)
412 }
413
414 pub fn expand(&self) -> Instruction {
421 match self {
422 CInstruction::ADDI4SPN { dest, imm } => Instruction::ADDI {
423 dest: dest.expand(),
424 src: IRegister::StackPointer,
425 imm: IImmediate::try_from(imm.val()).unwrap(),
426 },
427 CInstruction::FLD { .. } => todo!(), CInstruction::LW { dest, base, offset } => Instruction::LW {
429 dest: dest.expand(),
430 base: base.expand(),
431 offset: IImmediate::try_from(offset.val()).unwrap(),
432 },
433 CInstruction::LD { dest, base, offset } => Instruction::LD {
434 dest: dest.expand(),
435 base: base.expand(),
436 offset: IImmediate::try_from(offset.val()).unwrap(),
437 },
438 CInstruction::FSD { .. } => todo!(), CInstruction::SW { src, base, offset } => Instruction::SW {
440 src: src.expand(),
441 base: base.expand(),
442 offset: SImmediate::try_from(offset.val()).unwrap(),
443 },
444 CInstruction::SD { src, base, offset } => Instruction::SD {
445 src: src.expand(),
446 base: base.expand(),
447 offset: SImmediate::try_from(offset.val()).unwrap(),
448 },
449 CInstruction::ADDI { dest, imm } => Instruction::ADDI {
450 dest: *dest,
451 src: *dest,
452 imm: IImmediate::try_from(imm.val()).unwrap(),
453 },
454 CInstruction::ADDIW { dest, imm } => Instruction::ADDIW {
455 dest: *dest,
456 src: *dest,
457 imm: IImmediate::try_from(imm.val()).unwrap(),
458 },
459 CInstruction::LI { dest, imm } => Instruction::ADDI {
460 dest: *dest,
461 src: IRegister::Zero,
462 imm: IImmediate::try_from(imm.val()).unwrap(),
463 },
464 CInstruction::ADDI16SP { imm } => Instruction::ADDI {
465 dest: IRegister::StackPointer,
466 src: IRegister::StackPointer,
467 imm: IImmediate::try_from(imm.val()).unwrap(),
468 },
469 CInstruction::LUI { dest, imm } => Instruction::ADDI {
470 dest: *dest,
471 src: IRegister::Zero,
472 imm: IImmediate::try_from(imm.val()).unwrap(),
473 },
474 CInstruction::SRLI { dest, shamt } => Instruction::SRLI {
475 dest: dest.expand(),
476 src: dest.expand(),
477 shamt: Shamt::try_from(shamt.val()).unwrap(),
478 },
479 CInstruction::SRAI { dest, shamt } => Instruction::SRAI {
480 dest: dest.expand(),
481 src: dest.expand(),
482 shamt: Shamt::try_from(shamt.val()).unwrap(),
483 },
484 CInstruction::ANDI { dest, imm } => Instruction::ANDI {
485 dest: dest.expand(),
486 src: dest.expand(),
487 imm: IImmediate::try_from(imm.val()).unwrap(),
488 },
489 CInstruction::SUB { dest, src } => Instruction::SUB {
490 dest: dest.expand(),
491 src1: dest.expand(),
492 src2: src.expand(),
493 },
494 CInstruction::XOR { dest, src } => Instruction::XOR {
495 dest: dest.expand(),
496 src1: dest.expand(),
497 src2: src.expand(),
498 },
499 CInstruction::OR { dest, src } => Instruction::OR {
500 dest: dest.expand(),
501 src1: dest.expand(),
502 src2: src.expand(),
503 },
504 CInstruction::AND { dest, src } => Instruction::AND {
505 dest: dest.expand(),
506 src1: dest.expand(),
507 src2: src.expand(),
508 },
509 CInstruction::SUBW { dest, src } => Instruction::SUBW {
510 dest: dest.expand(),
511 src1: dest.expand(),
512 src2: src.expand(),
513 },
514 CInstruction::ADDW { dest, src } => Instruction::ADDW {
515 dest: dest.expand(),
516 src1: dest.expand(),
517 src2: src.expand(),
518 },
519 CInstruction::J { offset } => Instruction::JAL {
520 dest: IRegister::Zero,
521 offset: JImmediate::try_from(offset.val()).unwrap(),
522 },
523 CInstruction::BEQZ { src, offset } => Instruction::BEQ {
524 src1: src.expand(),
525 src2: IRegister::Zero,
526 offset: BImmediate::try_from(offset.val()).unwrap(),
527 },
528 CInstruction::BNEZ { src, offset } => Instruction::BNE {
529 src1: src.expand(),
530 src2: IRegister::Zero,
531 offset: BImmediate::try_from(offset.val()).unwrap(),
532 },
533 CInstruction::SLLI { dest, shamt } => Instruction::SLLI {
534 dest: *dest,
535 src: *dest,
536 shamt: Shamt::try_from(shamt.val()).unwrap(),
537 },
538 CInstruction::FLDSP { .. } => todo!(), CInstruction::LWSP { dest, offset } => Instruction::LW {
540 dest: *dest,
541 base: IRegister::StackPointer,
542 offset: IImmediate::try_from(offset.val()).unwrap(),
543 },
544 CInstruction::LDSP { dest, offset } => Instruction::LD {
545 dest: *dest,
546 base: IRegister::StackPointer,
547 offset: IImmediate::try_from(offset.val()).unwrap(),
548 },
549 CInstruction::JR { src } => Instruction::JALR {
550 dest: IRegister::Zero,
551 base: *src,
552 offset: IImmediate::try_from(0).unwrap(),
553 },
554 CInstruction::MV { dest, src } => Instruction::ADD {
555 dest: *dest,
556 src1: IRegister::Zero,
557 src2: *src,
558 },
559 CInstruction::EBREAK => Instruction::EBREAK,
560 CInstruction::JALR { src } => Instruction::JALR {
561 dest: IRegister::ReturnAddress,
562 base: *src,
563 offset: IImmediate::try_from(0).unwrap(),
564 },
565 CInstruction::ADD { dest, src } => Instruction::ADD {
567 dest: *dest,
568 src1: *dest,
569 src2: *src,
570 },
571 CInstruction::FSDSP { .. } => todo!(), CInstruction::SWSP { src, offset } => Instruction::SW {
573 src: *src,
574 base: IRegister::StackPointer,
575 offset: SImmediate::try_from(offset.val()).unwrap(),
576 },
577 CInstruction::SDSP { src, offset } => Instruction::SD {
578 src: *src,
579 base: IRegister::StackPointer,
580 offset: SImmediate::try_from(offset.val()).unwrap(),
581 },
582 }
583 }
584
585 pub fn encode(instruction: &CInstruction) -> u16 {
587 match instruction {
588 CInstruction::ADDI4SPN { dest, imm } => 0b000 << 13 | imm.to_u16() | dest.rs2(),
589 CInstruction::FLD { dest, base, offset } => {
590 0b001 << 13 | offset.to_u16() | base.rs1() | dest.rs2()
591 }
592 CInstruction::LW { dest, base, offset } => {
593 0b010 << 13 | offset.to_u16() | base.rs1() | dest.rs2()
594 }
595 CInstruction::LD { dest, base, offset } => {
596 0b011 << 13 | offset.to_u16() | base.rs1() | dest.rs2()
597 }
598 CInstruction::FSD { src, base, offset } => {
599 0b101 << 13 | offset.to_u16() | base.rs1() | src.rs2()
600 }
601 CInstruction::SW { src, base, offset } => {
602 0b0110 << 13 | offset.to_u16() | base.rs1() | src.rs2()
603 }
604 CInstruction::SD { src, base, offset } => {
605 0b111 << 13 | offset.to_u16() | base.rs1() | src.rs2()
606 }
607 CInstruction::ADDI { dest, imm } => {
608 0b000 << 13 | imm.to_u16() | dest.rd() as u16 | 0b01
609 }
610 CInstruction::ADDIW { dest, imm } => {
611 0b001 << 13 | imm.to_u16() | dest.rd() as u16 | 0b01
612 }
613 CInstruction::LI { dest, imm } => 0b010 << 13 | imm.to_u16() | dest.rd() as u16 | 0b01,
614 CInstruction::ADDI16SP { imm } => 0b011 << 13 | imm.to_u16() | 0b10 << 7 | 0b01,
615 CInstruction::LUI { dest, imm } => 0b011 << 13 | imm.to_u16() | dest.rd() as u16 | 0b01,
616 CInstruction::SRLI { dest, shamt } => {
617 0b100 << 13 | shamt.to_u16() | 0b00 << 10 | dest.rs1() | 0b01
618 }
619 CInstruction::SRAI { dest, shamt } => {
620 0b100 << 13 | shamt.to_u16() | 0b01 << 10 | dest.rs1() | 0b01
621 }
622 CInstruction::ANDI { dest, imm } => {
623 0b100 << 13 | imm.to_u16() | 0b10 << 10 | dest.rs1() | 0b01
624 }
625 CInstruction::SUB { dest, src } => {
626 0b100 << 13 | 0b11 << 10 | dest.rs1() | 0b00 << 5 | src.rs2() | 0b01
627 }
628 CInstruction::XOR { dest, src } => {
629 0b100 << 13 | 0b11 << 10 | dest.rs1() | 0b01 << 5 | src.rs2() | 0b01
630 }
631 CInstruction::OR { dest, src } => {
632 0b100 << 13 | 0b11 << 10 | dest.rs1() | 0b10 << 5 | src.rs2() | 0b01
633 }
634 CInstruction::AND { dest, src } => {
635 0b100 << 13 | 0b11 << 10 | dest.rs1() | 0b11 << 5 | src.rs2() | 0b01
636 }
637 CInstruction::SUBW { dest, src } => {
638 0b100 << 13 | 1 << 12 | 0b11 << 10 | dest.rs1() | 0b00 << 5 | src.rs2() | 0b01
639 }
640 CInstruction::ADDW { dest, src } => {
641 0b100 << 13 | 1 << 12 | 0b11 << 10 | dest.rs1() | 0b01 << 5 | src.rs2() | 0b01
642 }
643 CInstruction::J { offset } => 0b101 << 13 | offset.to_u16() | 0b01,
644 CInstruction::BEQZ { src, offset } => 0b110 << 13 | offset.to_u16() | src.rs1() | 0b01,
645 CInstruction::BNEZ { src, offset } => 0b111 << 13 | offset.to_u16() | src.rs1() | 0b01,
646 CInstruction::SLLI { dest, shamt } => {
647 0b000 << 13 | shamt.to_u16() | dest.rd() as u16 | 0b10
648 }
649 CInstruction::FLDSP { dest, offset } => {
650 0b001 << 13 | offset.to_u16() | dest.rd() as u16 | 0b10
651 }
652 CInstruction::LWSP { dest, offset } => {
653 0b010 << 13 | offset.to_u16() | dest.rd() as u16 | 0b10
654 }
655 CInstruction::LDSP { dest, offset } => {
656 0b011 << 13 | offset.to_u16() | dest.rd() as u16 | 0b10
657 }
658 CInstruction::JR { src } => 0b100 << 13 | src.rd() as u16 | 0b10,
659 CInstruction::MV { dest, src } => {
660 0b100 << 13 | dest.rd() as u16 | (src.rd() >> 5) as u16 | 0b10
661 }
662 CInstruction::EBREAK => 0b100 << 13 | 0b1 << 12 | 0b10,
663 CInstruction::JALR { src } => 0b100 << 13 | 0b1 << 12 | src.rd() as u16 | 0b10,
664 CInstruction::ADD { dest, src } => {
665 0b100 << 13 | 0b1 << 12 | dest.rd() as u16 | (src.rd() >> 5) as u16 | 0b10
666 }
667 CInstruction::FSDSP { src, offset } => {
668 0b101 << 13 | offset.to_u16() | (src.rd() >> 5) as u16 | 0b10
669 }
670 CInstruction::SWSP { src, offset } => {
671 0b110 << 13 | offset.to_u16() | (src.rd() >> 5) as u16 | 0b10
672 }
673 CInstruction::SDSP { src, offset } => {
674 0b111 << 13 | offset.to_u16() | (src.rd() >> 5) as u16 | 0b10
675 }
676 }
677 }
678}