1use core::panic;
2use std::fmt::Display;
3use std::ops;
4
5type RegisterType = u32;
6pub const XLEN: u8 = 32;
7
8#[derive(Clone, PartialEq, Debug)]
9pub struct InstructionWithLabel {
10 pub inst: Instruction,
11 pub labels: Vec<Label>,
12 pub ir: Option<String>,
14}
15
16impl InstructionWithLabel {
17 pub fn new(inst: Instruction, labels: Vec<Label>, ir: Option<String>) -> Self {
18 Self { inst, labels, ir }
19 }
20
21 pub fn with_label(self, labels: Vec<Label>) -> Self {
22 Self { labels, ..self }
23 }
24}
25
26impl From<Instruction> for InstructionWithLabel {
27 fn from(value: Instruction) -> Self {
28 Self::new(value, vec![], None)
29 }
30}
31
32#[derive(Clone, PartialEq, Debug)]
33pub enum Instruction {
34 R(RInstruction),
35 I(IInstruction),
36 S(SInstruction),
37 J(JInstruction),
38 U(UInstruction),
39 SB(SBInstruction),
40}
41
42impl Instruction {
43 pub fn with_ir(self, ir: Option<String>) -> InstructionWithLabel {
44 InstructionWithLabel::new(self, vec![], ir)
45 }
46
47 pub fn mv(rd: Register, rs1: Register) -> Instruction {
50 Instruction::R(RInstruction {
51 op: RInstructionOp::Add,
52 rs1,
53 rs2: Register::zero(),
54 rd,
55 })
56 }
57
58 pub fn li(rd: Register, imm: Immediate) -> Instruction {
59 Instruction::I(IInstruction {
60 op: IInstructionOp::Addi,
61 imm,
62 rs1: Register::zero(),
63 rd,
64 })
65 }
66
67 pub fn ret() -> Instruction {
68 Instruction::I(IInstruction {
69 op: IInstructionOp::Jalr,
70 imm: Immediate::new(0),
71 rs1: Register::ra(),
72 rd: Register::zero(),
73 })
74 }
75
76 #[allow(dead_code)]
77 pub fn nop() -> Instruction {
78 Instruction::I(IInstruction {
79 op: IInstructionOp::Addi,
80 imm: Immediate::new(0),
81 rs1: Register::zero(),
82 rd: Register::zero(),
83 })
84 }
85
86 pub fn sw(rs2: Register, rs1: Register, imm: Immediate) -> Instruction {
90 Instruction::S(SInstruction {
91 op: SInstructionOp::Sw,
92 rs1,
93 rs2,
94 imm,
95 })
96 }
97
98 pub fn lw(rd: Register, rs1: Register, imm: Immediate) -> Instruction {
100 Instruction::I(IInstruction {
101 op: IInstructionOp::Lw,
102 rs1,
103 rd,
104 imm,
105 })
106 }
107
108 pub fn addi(rd: Register, rs1: Register, imm: i32) -> Instruction {
109 Instruction::I(IInstruction {
110 op: IInstructionOp::Addi,
111 rs1,
112 rd,
113 imm: Immediate::for_i(imm),
114 })
115 }
116
117 pub fn add(rd: Register, rs1: Register, rs2: Register) -> Instruction {
118 Instruction::R(RInstruction {
119 op: RInstructionOp::Add,
120 rs1,
121 rs2,
122 rd,
123 })
124 }
125}
126
127impl Display for Instruction {
128 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
129 use Instruction::*;
130 match self {
131 R(ri) => write!(f, "{}", ri.generate_asm()),
132 I(ii) => write!(f, "{}", ii.generate_asm()),
133 S(si) => write!(f, "{}", si.generate_asm()),
134 J(ji) => write!(f, "{}", ji.generate_asm()),
135 U(ui) => write!(f, "{}", ui.generate_asm()),
136 SB(sbi) => write!(f, "{}", sbi.generate_asm()),
137 }
138 }
139}
140
141#[derive(Clone, PartialEq, Debug)]
161pub struct RInstruction {
162 pub op: RInstructionOp,
163 pub rs1: Register,
164 pub rs2: Register,
165 pub rd: Register,
166}
167
168#[derive(Clone, PartialEq, Debug)]
169pub enum RInstructionOp {
170 Add,
171 Sub,
172 And,
173 Or,
174 ShiftLeft,
175 ShiftRight,
176 Slt,
178
179 Mul,
180 Div,
181 Rem,
182}
183
184#[derive(Clone, PartialEq, Debug)]
185pub struct IInstruction {
186 pub op: IInstructionOp,
187 pub imm: Immediate,
188 pub rs1: Register,
189 pub rd: Register,
190}
191
192impl IInstruction {
193 pub fn is_nop(&self) -> bool {
194 self.op == IInstructionOp::Addi
195 && self.imm.value() == 0
196 && self.rs1.is_zero()
197 && self.rd.is_zero()
198 }
199}
200
201#[derive(Clone, PartialEq, Debug)]
202pub enum IInstructionOp {
203 Andi,
204 Ori,
205 Addi,
206 Jalr,
207 Ecall,
208 Lw,
210 Lb,
212 Xori,
213 Slti,
215 Sltiu,
217}
218
219#[derive(Clone, PartialEq, Debug)]
220pub struct SInstruction {
221 pub op: SInstructionOp,
222 pub imm: Immediate,
223 pub rs1: Register,
224 pub rs2: Register,
225}
226
227#[derive(Clone, PartialEq, Debug)]
228pub enum SInstructionOp {
229 Sw,
231 Sb,
233}
234
235#[derive(Clone, PartialEq, Debug)]
236pub struct JInstruction {
237 pub op: JInstructionOp,
238 pub imm: RelAddress,
239 pub rd: Register,
240}
241
242#[derive(Clone, PartialEq, Debug)]
243pub enum JInstructionOp {
244 Jal,
245}
246
247#[derive(Clone, PartialEq, Debug)]
248pub struct UInstruction {
249 pub op: UInstructionOp,
250 pub imm: Immediate,
251 pub rd: Register,
252}
253
254#[derive(Clone, PartialEq, Debug)]
255pub enum UInstructionOp {
256 Lui,
257}
258
259#[derive(Clone, PartialEq, Debug)]
260pub struct SBInstruction {
261 pub op: SBInstructionOp,
262 pub imm: RelAddress,
263 pub rs1: Register,
264 pub rs2: Register,
265}
266
267#[derive(Clone, PartialEq, Debug)]
268pub enum SBInstructionOp {
269 #[allow(dead_code)]
271 Beq,
272 Bne,
274}
275
276pub trait GenerateCode {
277 fn generate_code(&self) -> RegisterType;
278 fn generate_asm(&self) -> String;
279}
280
281impl GenerateCode for RInstruction {
282 fn generate_code(&self) -> RegisterType {
283 use RInstructionOp::*;
284
285 let rs2 = self.rs2.as_int();
286 let rs1 = self.rs1.as_int();
287 let rd = self.rd.as_int();
288
289 let (funct7, funct3, opcode) = match self.op {
290 Add => (0b0000000, 0b000, 0b0110011),
291 Sub => (0b0100000, 0b000, 0b0110011),
292 And => (0b0000000, 0b111, 0b0110011),
293 Or => (0b0000000, 0b110, 0b0110011),
294 ShiftLeft => (0b0000000, 0b001, 0b0110011),
295 ShiftRight => (0b0000000, 0b101, 0b0110011),
296 Slt => (0b0000000, 0b010, 0b0110011),
297 Mul => (0b0000001, 0b000, 0b0110011),
298 Div => (0b0000001, 0b100, 0b0110011),
299 Rem => (0b0000001, 0b110, 0b0110011),
300 };
301
302 (funct7 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) | (rd << 7) | opcode
303 }
304
305 fn generate_asm(&self) -> String {
306 use RInstructionOp::*;
307
308 let name = match self.op {
309 Add => "add",
310 Sub => "sub",
311 And => "and",
312 Or => "or",
313 ShiftLeft => "sll",
314 ShiftRight => "srl",
315 Slt => "slt",
316 Mul => "mul",
317 Div => "div",
318 Rem => "rem",
319 };
320
321 format!("{} {}, {}, {}", name, self.rd, self.rs1, self.rs2)
322 }
323}
324
325impl GenerateCode for IInstruction {
326 fn generate_code(&self) -> RegisterType {
327 use IInstructionOp::*;
328
329 assert!(
330 (self.imm.value() & !0xfff) == 0,
331 "Immediate of IInstruction must be under 0x1000. But the value is 0x{:x}.",
332 self.imm.value()
333 );
334
335 let imm = (self.imm.value() as u32) & 0xfff;
336 let rs1 = self.rs1.as_int();
337
338 let (funct3, opcode) = match self.op {
339 Andi => (0b111, 0b0010011),
340 Ori => (0b110, 0b0010011),
341 Addi => (0b000, 0b0010011),
342 Jalr => (0b000, 0b1100111),
343 Ecall => (0b000, 0b1110011),
344 Lw => (0b010, 0b0000011),
345 Lb => (0b000, 0b0000011),
346 Xori => (0b100, 0b0010011),
347 Slti => (0b010, 0b0010011),
348 Sltiu => (0b011, 0b0010011),
349 };
350
351 let rd = self.rd.as_int();
352
353 (imm << 20) | (rs1 << 15) | (funct3 << 12) | (rd << 7) | opcode
354 }
355
356 fn generate_asm(&self) -> String {
357 use IInstructionOp::*;
358
359 if self.is_nop() {
360 return "nop".to_string();
361 }
362
363 match self.op {
364 Andi | Ori | Addi | Jalr | Xori | Slti | Sltiu => {
365 let mut imm = self.imm.value();
366 if imm >> 11 & 1 == 1 {
367 imm |= 0xffff_f000u32 as i32;
369 }
370 let name = match self.op {
371 Andi => "andi",
372 Ori => "ori",
373 Addi => "addi",
374 Jalr => "jalr",
375 Xori => "xori",
376 Slti => "slti",
377 Sltiu => "sltiu",
378 _ => panic!("Unknown op: {:?}", self.op),
379 };
380 format!("{} {}, {}, {}", name, self.rd, self.rs1, imm)
381 }
382 Ecall => "ecall".to_string(),
383 Lw => {
384 format!("lw {}, {}({})", self.rd, self.imm, self.rs1)
385 }
386 Lb => {
387 format!("lb {}, {}({})", self.rd, self.imm, self.rs1)
388 }
389 }
390 }
391}
392
393impl GenerateCode for SInstruction {
394 fn generate_code(&self) -> RegisterType {
395 use SInstructionOp::*;
396
397 let rs1 = self.rs1.as_int();
398 let rs2 = self.rs2.as_int();
399
400 let imm = self.imm.uvalue();
401 let imm1 = (imm >> 5) & 0b111_1111;
402 let imm2 = imm & 0b1_1111;
403
404 let (funct3, opcode) = match self.op {
405 Sw => (0b010, 0b0100011),
406 Sb => (0b000, 0b0100011),
407 };
408
409 (imm1 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) | (imm2 << 7) | opcode
410 }
411
412 fn generate_asm(&self) -> String {
413 use SInstructionOp::*;
414
415 let name = match self.op {
416 Sw => "sw",
417 Sb => "sb",
418 };
419
420 format!("{} {}, {}({})", name, self.rs2, self.imm, self.rs1)
421 }
422}
423
424impl GenerateCode for JInstruction {
425 fn generate_code(&self) -> RegisterType {
426 use JInstructionOp::*;
427
428 let imm = self.imm.value();
429
430 assert!(imm & 1 == 0);
431 let imm = imm >> 1;
432
433 let imm = (imm & (0b1 << 19))
434 | ((imm & 0b11_1111_1111) << 9)
435 | ((imm & (0b1 << 10)) >> 2)
436 | ((imm & (0b1111_1111 << 11)) >> 11);
437
438 let rd = self.rd.as_int();
439
440 let opcode = match self.op {
441 Jal => 0b1101111,
442 };
443
444 (imm << 12) | (rd << 7) | opcode
445 }
446
447 fn generate_asm(&self) -> String {
448 use JInstructionOp::*;
449
450 match self.op {
451 Jal => {
452 format!("jal {}, {}", self.rd, self.imm)
453 }
454 }
455 }
456}
457
458impl GenerateCode for UInstruction {
459 fn generate_code(&self) -> RegisterType {
460 use UInstructionOp::*;
461
462 let imm = self.imm.uvalue() & 0xfffff000;
463 let rd = self.rd.as_int();
464
465 let opcode = match self.op {
466 Lui => 0b0110111,
467 };
468
469 imm | (rd << 7) | opcode
470 }
471
472 fn generate_asm(&self) -> String {
473 use UInstructionOp::*;
474
475 match self.op {
476 Lui => {
477 let imm = self.imm.uvalue() & 0xfffff000;
478 format!("lui {}, {}", self.rd, imm >> 12)
479 }
480 }
481 }
482}
483
484impl GenerateCode for SBInstruction {
485 fn generate_code(&self) -> RegisterType {
486 use SBInstructionOp::*;
487
488 let imm = self.imm.value();
489 assert!(imm & 1 == 0);
490 let imm_upper = ((imm & (1 << 12)) >> 5) | ((imm >> 5) & 0b11111);
492 let imm_lower = (imm & 0b11110) | ((imm >> 11) & 1);
494
495 let rs1 = self.rs1.as_int();
496 let rs2 = self.rs2.as_int();
497
498 let (opcode, funct3) = match self.op {
499 Beq => (0b1100011, 0b000),
500 Bne => (0b1100011, 0b001),
501 };
502
503 (imm_upper << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) | (imm_lower << 7) | opcode
504 }
505
506 fn generate_asm(&self) -> String {
507 use SBInstructionOp::*;
508
509 let name = match self.op {
510 Beq => "beq",
511 Bne => "bne",
512 };
513 format!("{} {}, {}, {}", name, self.rs1, self.rs2, self.imm)
514 }
515}
516
517#[derive(Clone, PartialEq, Debug)]
518pub struct Label {
519 pub name: String,
520}
521
522impl Label {
523 pub fn new(name: String) -> Self {
524 Self { name }
525 }
526}
527
528#[derive(Clone, PartialEq, Debug)]
529pub enum RelAddress {
530 Label(Label),
531 Immediate(Immediate),
532}
533
534impl RelAddress {
535 fn value(&self) -> RegisterType {
536 match self {
537 RelAddress::Label(_) => unimplemented!(),
538 RelAddress::Immediate(imm) => imm.uvalue(),
539 }
540 }
541}
542
543impl Display for RelAddress {
544 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
545 match self {
546 RelAddress::Label(label) => write!(f, "{}", label.name),
547 RelAddress::Immediate(imm) => write!(f, "{}", imm.value()),
548 }
549 }
550}
551
552#[derive(Clone, Copy, PartialEq, Debug)]
553pub enum Register {
554 Integer(u32),
555 Float(u32),
557}
558
559impl Register {
560 pub fn zero() -> Register {
561 Register::Integer(0)
562 }
563
564 pub fn is_zero(&self) -> bool {
565 self.as_int() == 0
566 }
567
568 pub fn ra() -> Register {
569 Register::Integer(1)
570 }
571
572 pub fn sp() -> Register {
573 Register::Integer(2)
574 }
575
576 #[allow(dead_code)]
577 pub fn gp() -> Register {
578 Register::Integer(3)
579 }
580
581 #[allow(dead_code)]
582 pub fn tp() -> Register {
583 Register::Integer(4)
584 }
585
586 pub fn t(i: u32) -> Register {
587 match i {
588 0..=2 => Register::Integer(5 + i),
589 3.. => Register::Integer(28 - 3 + i),
590 }
591 }
592
593 #[allow(dead_code)]
594 pub fn fp() -> Register {
595 Self::s(0)
596 }
597
598 pub fn s(i: u32) -> Register {
599 match i {
600 0 | 1 => Register::Integer(8 + i),
601 2.. => Register::Integer(18 - 2 + i),
602 }
603 }
604
605 pub fn a(i: u32) -> Register {
606 Register::Integer(10 + i)
607 }
608
609 pub fn as_int(&self) -> u32 {
610 if let Register::Integer(i) = self {
611 if i >= &32u32 {
612 panic!("Register #{} is invalid!", *i)
613 } else {
614 *i
615 }
616 } else {
617 panic!("Register {} is invalid!", self)
618 }
619 }
620}
621
622impl Display for Register {
623 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
624 match self {
625 Register::Integer(i) => match i {
626 0 => write!(f, "zero"),
627 1 => write!(f, "ra"),
628 2 => write!(f, "sp"),
629 3 => write!(f, "gp"),
630 4 => write!(f, "tp"),
631 5..=7 => write!(f, "t{}", i - 5),
632 8 => write!(f, "s0"),
633 9 => write!(f, "s1"),
634 10..=17 => write!(f, "a{}", i - 10),
635 18..=27 => write!(f, "s{}", i - 16),
636 28..=31 => write!(f, "t{}", i - 25),
637 _ => write!(f, "(invalid register {})", i),
638 },
639 Register::Float(i) => {
640 write!(f, "f{}", i)
641 }
642 }
643 }
644}
645
646#[derive(Clone, PartialEq, Debug)]
647pub enum Immediate {
648 Value(i32),
649 Label(Label),
650}
651
652impl Immediate {
653 pub fn new(value: i32) -> Immediate {
654 Immediate::Value(value)
655 }
656
657 pub fn value(&self) -> i32 {
658 match self {
659 Immediate::Value(value) => *value,
660 Immediate::Label(_) => todo!(),
661 }
662 }
663
664 pub fn uvalue(&self) -> u32 {
665 self.value() as u32
666 }
667
668 pub fn for_i(value: i32) -> Self {
670 Self::new(value & 0xfff)
671 }
672}
673
674impl ops::Add<Immediate> for Immediate {
675 type Output = Immediate;
676
677 fn add(self, rhs: Immediate) -> Self::Output {
678 Immediate::new(self.value() + rhs.value())
680 }
681}
682
683impl ops::MulAssign<i32> for Immediate {
684 fn mul_assign(&mut self, rhs: i32) {
685 match self {
686 Immediate::Value(value) => {
687 *value *= rhs;
688 }
689 Immediate::Label(_) => todo!(),
690 }
691 }
692}
693
694impl Display for Immediate {
695 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
696 write!(f, "{}", self.value())
697 }
698}