riscu/
instruction.rs

1use crate::types::*;
2use crate::Register;
3
4#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
5pub enum Instruction {
6    // LUI
7    Lui(UType),
8
9    // Jal
10    Jal(JType),
11
12    // Jalr
13    Jalr(IType),
14
15    // Branch
16    Beq(BType),
17
18    // Load
19    Ld(IType),
20
21    // Store
22    Sd(SType),
23
24    // OP-imm
25    Addi(IType),
26
27    // OP
28    Add(RType),
29    Sub(RType),
30    Sltu(RType),
31    Mul(RType),
32    Divu(RType),
33    Remu(RType),
34
35    // System
36    Ecall(IType),
37}
38
39// opcodes
40const OP_LD: u32 = 3; // 0000011, I format (LD)
41const OP_IMM: u32 = 19; // 0010011, I format (ADDI, NOP)
42const OP_SD: u32 = 35; // 0100011, S format (SD)
43const OP_OP: u32 = 51; // 0110011, R format (ADD, SUB, MUL, DIVU, REMU, SLTU)
44const OP_LUI: u32 = 55; // 0110111, U format (LUI)
45const OP_BRANCH: u32 = 99; // 1100011, B format (BEQ)
46const OP_JALR: u32 = 103; // 1100111, I format (JALR)
47const OP_JAL: u32 = 111; // 1101111, J format (JAL)
48const OP_SYSTEM: u32 = 115; // 1110011, I format (ECALL)
49
50// f3-codes
51const F3_ADDI: u32 = 0; // 000
52const F3_ADD: u32 = 0; // 000
53const F3_SUB: u32 = 0; // 000
54const F3_MUL: u32 = 0; // 000
55const F3_DIVU: u32 = 5; // 101
56const F3_REMU: u32 = 7; // 111
57const F3_SLTU: u32 = 3; // 011
58const F3_LD: u32 = 3; // 011
59const F3_SD: u32 = 3; // 011
60const F3_BEQ: u32 = 0; // 000
61const F3_JALR: u32 = 0; // 000
62const F3_ECALL: u32 = 0; // 000
63
64// f7-codes
65const F7_ADD: u32 = 0; // 0000000
66const F7_MUL: u32 = 1; // 0000001
67const F7_SUB: u32 = 32; // 0100000
68const F7_DIVU: u32 = 1; // 0000001
69const F7_REMU: u32 = 1; // 0000001
70const F7_SLTU: u32 = 0; // 0000000
71
72impl Instruction {
73    pub fn new_nop() -> Instruction {
74        Self::new_addi(Register::Zero, Register::Zero, 0)
75    }
76    pub fn new_add(rd: Register, rs1: Register, rs2: Register) -> Instruction {
77        Instruction::Add(RType::new(F7_ADD, F3_ADD, OP_OP, rs1, rs2, rd))
78    }
79    pub fn new_sub(rd: Register, rs1: Register, rs2: Register) -> Instruction {
80        Instruction::Sub(RType::new(F7_SUB, F3_SUB, OP_OP, rs1, rs2, rd))
81    }
82    pub fn new_mul(rd: Register, rs1: Register, rs2: Register) -> Instruction {
83        Instruction::Mul(RType::new(F7_MUL, F3_MUL, OP_OP, rs1, rs2, rd))
84    }
85    pub fn new_divu(rd: Register, rs1: Register, rs2: Register) -> Instruction {
86        Instruction::Divu(RType::new(F7_DIVU, F3_DIVU, OP_OP, rs1, rs2, rd))
87    }
88    pub fn new_remu(rd: Register, rs1: Register, rs2: Register) -> Instruction {
89        Instruction::Remu(RType::new(F7_REMU, F3_REMU, OP_OP, rs1, rs2, rd))
90    }
91    pub fn new_sltu(rd: Register, rs1: Register, rs2: Register) -> Instruction {
92        Instruction::Sltu(RType::new(F7_SLTU, F3_SLTU, OP_OP, rs1, rs2, rd))
93    }
94    pub fn new_addi(rd: Register, rs1: Register, immediate: i32) -> Instruction {
95        Instruction::Addi(IType::new(immediate, F3_ADDI, OP_IMM, rd, rs1))
96    }
97    pub fn new_ld(rd: Register, rs1: Register, immediate: i32) -> Instruction {
98        Instruction::Ld(IType::new(immediate, F3_LD, OP_LD, rd, rs1))
99    }
100    pub fn new_ecall() -> Instruction {
101        Instruction::Ecall(IType::new(
102            0,
103            F3_ECALL,
104            OP_SYSTEM,
105            Register::Zero,
106            Register::Zero,
107        ))
108    }
109    pub fn new_jalr(rd: Register, rs1: Register, immediate: i32) -> Instruction {
110        Instruction::Jalr(IType::new(immediate, F3_JALR, OP_JALR, rd, rs1))
111    }
112    pub fn new_sd(rs1: Register, rs2: Register, immediate: i32) -> Instruction {
113        Instruction::Sd(SType::new(immediate, F3_SD, OP_SD, rs1, rs2))
114    }
115    pub fn new_beq(rs1: Register, rs2: Register, immediate: i32) -> Instruction {
116        Instruction::Beq(BType::new(immediate, F3_BEQ, OP_BRANCH, rs1, rs2))
117    }
118    pub fn new_jal(rd: Register, immediate: i32) -> Instruction {
119        Instruction::Jal(JType::new(immediate, OP_JAL, rd))
120    }
121    pub fn new_lui(rd: Register, immediate: i32) -> Instruction {
122        Instruction::Lui(UType::new(immediate, OP_LUI, rd))
123    }
124}