instruction.rs 11.73 KiB
use std::fmt::Debug;
use super::{registers::Register, Imm12, Imm32};
pub type Label = String;
#[derive(Clone, Hash, PartialEq, Eq)]
#[allow(dead_code)]
pub enum Inst {
    Nop,
    /// **Placeholder(u8)**: a placeholder for the instruction.
    Placeholder(u8),
    /// **Comment(comment)**: a comment.
    Comment(String),
    /// **Zero(size)**: reserve the memory with the size.
    Zero(usize),
    /// **Word(int)**: store the integer to the memory.
    Word(i32),
    /// **Beqz(rs, label)**: go to the label if rs is zero.
    Beqz(Register, Label),
    /// **Bnez(rs, label)**: go to the label if rs is not zero.
    Bnez(Register, Label),
    /// **J(label)**: jump to the label.
    J(Label),
    /// **Call(label)**: call the function.
    Call(Label),
    /// **Ret**: return from the function.
    Ret,
    /// **Lw(rd, rs, offset)**: load the memory at rs + offset to rd.
    Lw(Register, Register, Imm12),
    /// **Sw(rs2, rs1, offset)**: store the value of rs2 to rs1 + offset.
    Sw(Register, Register, Imm12),
    /// **Add(rd, rs1, rs2)**: add rs1 and rs2, and store the result to rd.
    Add(Register, Register, Register),
    /// **Addi(rd, rs, imm)**: add rs and imm, and store the result to rd.
    Addi(Register, Register, Imm12),
    /// **Sub(rd, rs1, rs2)**: subtract rs2 from rs1, and store the result to rd.
    Sub(Register, Register, Register),
    /// **Slt(rd, rs1, rs2)**: compare if rs1 is less than rs2, and store the result to rd.
    Slt(Register, Register, Register),
    /// **Sgt(rd, rs1, rs2)**: compare if rs1 is greater than rs2, and store the result to rd.
    Sgt(Register, Register, Register),
    /// **SeqZ(rd, rs)**: Judge if rs is zero, and store the result to rd.
    SeqZ(Register, Register),
    /// **SneZ(rd, rs)**: Judge if rs is not zero, and store the result to rd.
    SneZ(Register, Register),
    /// **Xor(rd, rs1, rs2)**: calculate the bitwise xor of rs1 and rs2, and store the result to rd.
    Xor(Register, Register, Register),
    /// **Xori(rd, rs, imm)**: calculate the bitwise xor of rs and imm, and store the result to rd.
    Xori(Register, Register, Imm12),
    /// **Or(rd, rs1, rs2)**: calculate the bitwise or of rs1 and rs2, and store the result to rd.
    Or(Register, Register, Register),
    /// **Ori(rd, rs, imm)**: calculate the bitwise or of rs and imm, and store the result to rd.
    Ori(Register, Register, Imm12),
    /// **And(rd, rs1, rs2)**: calculate the bitwise and of rs1 and rs2, and store the result to rd.
    And(Register, Register, Register),
    /// **Andi(rd, rs, imm)**: calculate the bitwise and of rs and imm, and store the result to rd.
    Andi(Register, Register, Imm12),
    /// **Sll(rd, rs1, rs2)**: shift left logical rs1 by rs2 bits, and store the result to rd.
    Sll(Register, Register, Register),
    /// **Slli(rd, rs, imm)**: shift left logical rs by imm bits, and store the result to rd.
    Slli(Register, Register, Imm12),
    /// **Srl(rd, rs1, rs2)**: shift right logical rs1 by rs2 bits, and store the result to rd.
    Srl(Register, Register, Register),
    /// **Srli(rd, rs, imm)**: shift right logical rs by imm bits, and store the result to rd.
    Srli(Register, Register, Imm12),
    /// **Sra(rd, rs1, rs2)**: shift right arithmetic rs1 by rs2 bits, and store the result to rd.
    Sra(Register, Register, Register),
    /// **Srai(rd, rs, imm)**: shift right arithmetic rs by imm bits, and store the result to rd.
    Srai(Register, Register, Imm12),
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
/// **Mul(rd, rs1, rs2)**: multiply rs1 by rs2, and store the result to rd. Mul(Register, Register, Register), /// **Div(rd, rs1, rs2)**: divide rs1 by rs2, and store the result to rd. Div(Register, Register, Register), /// **Rem(rd, rs1, rs2)**: calculate the remainder of rs1 divided by rs2, and store the result to rd. Rem(Register, Register, Register), /// **Li(rd, imm)**: load the immediate value to rd. Li(Register, Imm32), /// **La(rd, label)**: load the address of label to rd. La(Register, Label), /// **Mv(rd, rs)**: move the value of rs to rd. Mv(Register, Register), } impl Inst { pub fn dump(&self) -> String { match self { Inst::Nop => String::new(), Inst::Placeholder(_) => String::new(), Inst::Comment(comment) => format!("# {}", comment), Inst::Zero(size) => format!(".zero {}", size), Inst::Word(int) => format!(".word {}", int), Inst::Beqz(rs, label) => format!("beqz {}, {}", rs, label), Inst::Bnez(rs, label) => format!("bnez {}, {}", rs, label), Inst::J(label) => format!("j {}", label), Inst::Call(label) => format!("call {}", label), Inst::Ret => format!("ret"), Inst::Lw(rd, rs, offset) => format!("lw {}, {}({})", rd, offset, rs), Inst::Sw(rs2, rs1, offset) => format!("sw {}, {}({})", rs2, offset, rs1), Inst::Add(rd, rs1, rs2) => format!("add {}, {}, {}", rd, rs1, rs2), Inst::Addi(rd, rs, imm) => format!("addi {}, {}, {}", rd, rs, imm), Inst::Sub(rd, rs1, rs2) => format!("sub {}, {}, {}", rd, rs1, rs2), Inst::Slt(rd, rs1, rs2) => format!("slt {}, {}, {}", rd, rs1, rs2), Inst::Sgt(rd, rs1, rs2) => format!("sgt {}, {}, {}", rd, rs1, rs2), Inst::SeqZ(rd, rs) => format!("seqz {}, {}", rd, rs), Inst::SneZ(rd, rs) => format!("snez {}, {}", rd, rs), Inst::Xor(rd, rs1, rs2) => format!("xor {}, {}, {}", rd, rs1, rs2), Inst::Xori(rd, rs, imm) => format!("xori {}, {}, {}", rd, rs, imm), Inst::Or(rd, rs1, rs2) => format!("or {}, {}, {}", rd, rs1, rs2), Inst::Ori(rd, rs, imm) => format!("ori {}, {}, {}", rd, rs, imm), Inst::And(rd, rs1, rs2) => format!("and {}, {}, {}", rd, rs1, rs2), Inst::Andi(rd, rs, imm) => format!("andi {}, {}, {}", rd, rs, imm), Inst::Sll(rd, rs1, rs2) => format!("sll {}, {}, {}", rd, rs1, rs2), Inst::Slli(rd, rs, imm) => format!("slli {}, {}, {}", rd, rs, imm), Inst::Srl(rd, rs1, rs2) => format!("srl {}, {}, {}", rd, rs1, rs2), Inst::Srli(rd, rs, imm) => format!("srli {}, {}, {}", rd, rs, imm), Inst::Sra(rd, rs1, rs2) => format!("sra {}, {}, {}", rd, rs1, rs2), Inst::Srai(rd, rs, imm) => format!("srai {}, {}, {}", rd, rs, imm), Inst::Mul(rd, rs1, rs2) => format!("mul {}, {}, {}", rd, rs1, rs2), Inst::Div(rd, rs1, rs2) => format!("div {}, {}, {}", rd, rs1, rs2), Inst::Rem(rd, rs1, rs2) => format!("rem {}, {}, {}", rd, rs1, rs2), Inst::Li(rd, imm) => format!("li {}, {}", rd, imm), Inst::La(rd, label) => format!("la {}, {}", rd, label), Inst::Mv(rd, rs) => format!("mv {}, {}", rd, rs), } } pub fn regs_mut(&mut self) -> Vec<&mut Register> { match self { Inst::Nop => vec![], Inst::Placeholder(_) => vec![], Inst::Comment(_) => vec![], Inst::Zero(_) => vec![], Inst::Word(_) => vec![], Inst::Beqz(rs, _) => vec![rs], Inst::Bnez(rs, _) => vec![rs], Inst::J(_) => vec![], Inst::Call(_) => vec![], Inst::Ret => vec![], Inst::Lw(rd, rs, _) => vec![rd, rs],
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
Inst::Sw(rs2, rs1, _) => vec![rs2, rs1], Inst::Add(rd, rs1, rs2) => vec![rd, rs1, rs2], Inst::Addi(rd, rs, _) => vec![rd, rs], Inst::Sub(rd, rs1, rs2) => vec![rd, rs1, rs2], Inst::Slt(rd, rs1, rs2) => vec![rd, rs1, rs2], Inst::Sgt(rd, rs1, rs2) => vec![rd, rs1, rs2], Inst::SeqZ(rd, rs) => vec![rd, rs], Inst::SneZ(rd, rs) => vec![rd, rs], Inst::Xor(rd, rs1, rs2) => vec![rd, rs1, rs2], Inst::Xori(rd, rs, _) => vec![rd, rs], Inst::Or(rd, rs1, rs2) => vec![rd, rs1, rs2], Inst::Ori(rd, rs, _) => vec![rd, rs], Inst::And(rd, rs1, rs2) => vec![rd, rs1, rs2], Inst::Andi(rd, rs, _) => vec![rd, rs], Inst::Sll(rd, rs1, rs2) => vec![rd, rs1, rs2], Inst::Slli(rd, rs, _) => vec![rd, rs], Inst::Srl(rd, rs1, rs2) => vec![rd, rs1, rs2], Inst::Srli(rd, rs, _) => vec![rd, rs], Inst::Sra(rd, rs1, rs2) => vec![rd, rs1, rs2], Inst::Srai(rd, rs, _) => vec![rd, rs], Inst::Mul(rd, rs1, rs2) => vec![rd, rs1, rs2], Inst::Div(rd, rs1, rs2) => vec![rd, rs1, rs2], Inst::Rem(rd, rs1, rs2) => vec![rd, rs1, rs2], Inst::Li(rd, _) => vec![rd], Inst::La(rd, _) => vec![rd], Inst::Mv(rd, rs) => vec![rd, rs], } } pub fn regs(&self) -> Vec<&Register> { let mut regs = self.src_regs(); if let Some(rd) = self.dest_reg() { regs.push(rd); } regs } pub fn dest_reg(&self) -> Option<&Register> { match self { Inst::Lw(rd, _, _) => Some(rd), Inst::Add(rd, _, _) => Some(rd), Inst::Addi(rd, _, _) => Some(rd), Inst::Sub(rd, _, _) => Some(rd), Inst::Slt(rd, _, _) => Some(rd), Inst::Sgt(rd, _, _) => Some(rd), Inst::SeqZ(rd, _) => Some(rd), Inst::SneZ(rd, _) => Some(rd), Inst::Xor(rd, _, _) => Some(rd), Inst::Xori(rd, _, _) => Some(rd), Inst::Or(rd, _, _) => Some(rd), Inst::Ori(rd, _, _) => Some(rd), Inst::And(rd, _, _) => Some(rd), Inst::Andi(rd, _, _) => Some(rd), Inst::Sll(rd, _, _) => Some(rd), Inst::Slli(rd, _, _) => Some(rd), Inst::Srl(rd, _, _) => Some(rd), Inst::Srli(rd, _, _) => Some(rd), Inst::Sra(rd, _, _) => Some(rd), Inst::Srai(rd, _, _) => Some(rd), Inst::Mul(rd, _, _) => Some(rd), Inst::Div(rd, _, _) => Some(rd), Inst::Rem(rd, _, _) => Some(rd), Inst::Li(rd, _) => Some(rd), Inst::La(rd, _) => Some(rd), Inst::Mv(rd, _) => Some(rd), _ => None, } } pub fn src_regs(&self) -> Vec<&Register> {
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
match self { Inst::Lw(_, rs, _) => vec![rs], Inst::Sw(rs2, rs1, _) => vec![rs1, rs2], Inst::Add(_, rs1, rs2) => vec![rs1, rs2], Inst::Addi(_, rs, _) => vec![rs], Inst::Sub(_, rs1, rs2) => vec![rs1, rs2], Inst::Slt(_, rs1, rs2) => vec![rs1, rs2], Inst::Sgt(_, rs1, rs2) => vec![rs1, rs2], Inst::SeqZ(_, rs) => vec![rs], Inst::SneZ(_, rs) => vec![rs], Inst::Xor(_, rs1, rs2) => vec![rs1, rs2], Inst::Xori(_, rs, _) => vec![rs], Inst::Or(_, rs1, rs2) => vec![rs1, rs2], Inst::Ori(_, rs, _) => vec![rs], Inst::And(_, rs1, rs2) => vec![rs1, rs2], Inst::Andi(_, rs, _) => vec![rs], Inst::Sll(_, rs1, rs2) => vec![rs1, rs2], Inst::Slli(_, rs, _) => vec![rs], Inst::Srl(_, rs1, rs2) => vec![rs1, rs2], Inst::Srli(_, rs, _) => vec![rs], Inst::Sra(_, rs1, rs2) => vec![rs1, rs2], Inst::Srai(_, rs, _) => vec![rs], Inst::Mul(_, rs1, rs2) => vec![rs1, rs2], Inst::Div(_, rs1, rs2) => vec![rs1, rs2], Inst::Rem(_, rs1, rs2) => vec![rs1, rs2], Inst::Mv(_, rs) => vec![rs], _ => vec![], } } } impl Debug for Inst { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.dump()) } } #[derive(Debug, Clone)] pub enum Directive { Text, Data, } impl Directive { pub fn dump(&self) -> String { match self { Directive::Text => String::from("\n.text"), Directive::Data => String::from("\n.data"), } } }