IT WORKS HELL YEAH.

This commit is contained in:
2025-06-18 22:53:01 +01:00
parent 1210b19333
commit e281bc2d1d
26 changed files with 715 additions and 188 deletions
+187 -3
View File
@@ -1,6 +1,190 @@
use common::{
instructions,
prelude::{Instruction, RTypeArgs},
args, instructions,
prelude::{ITypeArgs, Instruction, Interrupt, RTypeArgs, Register},
};
use crate::model::{Node, Opcode};
use crate::{
AssembleError, expect_token, expect_type,
model::{Node, Opcode, Token, TokenType},
};
pub fn codegen(nodes: Vec<Node>) -> Result<Vec<Instruction>, AssembleError> {
let mut instructions = vec![];
for node in nodes {
instructions.push(build_instruction(node)?);
}
Ok(instructions)
}
fn build_instruction(node: Node) -> Result<Instruction, AssembleError> {
let opcode = node.opcode();
let args = node.args();
// println!("{node}");
match opcode {
Opcode::Nop => Ok(Instruction::Nop),
Opcode::Mov => {
let src = expect_token!(args.get(0).unwrap(), Register)?;
let dest = expect_token!(args.get(1).unwrap(), Register)?;
Ok(Instruction::Mov(args!(R, sr1: src, dr: dest)))
}
Opcode::Movs => {
let src = expect_token!(args.get(0).unwrap(), Register)?;
let dest = expect_token!(args.get(1).unwrap(), Register)?;
Ok(Instruction::MovSigned(args!(R, sr1: src, dr: dest)))
}
Opcode::Ldb
| Opcode::Ldw
| Opcode::Ldh
| Opcode::Ldbs
| Opcode::Ldhs
| Opcode::Stb
| Opcode::Stw
| Opcode::Sth => {
let base = expect_token!(args.get(0).unwrap(), Register)?;
let dest = expect_token!(args.get(1).unwrap(), Register)?;
let offset = expect_token!(args.get(2).unwrap(), Immediate)?;
let args = args!(I, immediate: offset as u16, r1: base, r2: dest);
match opcode {
Opcode::Ldb => Ok(Instruction::LoadByte(args)),
Opcode::Ldw => Ok(Instruction::LoadWord(args)),
Opcode::Ldh => Ok(Instruction::LoadHalfword(args)),
Opcode::Ldbs => Ok(Instruction::LoadByteSigned(args)),
Opcode::Ldhs => Ok(Instruction::LoadHalfwordSigned(args)),
Opcode::Stb => Ok(Instruction::StoreByte(args)),
Opcode::Stw => Ok(Instruction::StoreWord(args)),
Opcode::Sth => Ok(Instruction::StoreHalfword(args)),
_ => unreachable!(),
}
}
Opcode::Lli => {
let value = expect_token!(args.get(0).unwrap(), Immediate)?;
let dest = expect_token!(args.get(1).unwrap(), Register)?;
let args = args!(I, immediate: value as u16, r1: dest);
Ok(Instruction::LoadLowerImmediate(args))
}
Opcode::Lui => {
let value = expect_token!(args.get(0).unwrap(), Immediate)? >> 16;
let dest = expect_token!(args.get(1).unwrap(), Register)?;
let args = args!(I, immediate: value as u16, r1: dest);
Ok(Instruction::LoadUpperImmediate(args))
}
Opcode::Jmp
| Opcode::Jeq
| Opcode::Jne
| Opcode::Jgt
| Opcode::Jge
| Opcode::Jlt
| Opcode::Jle => {
let address = expect_token!(args.get(0).unwrap(), Immediate)?;
let offset = expect_token!(args.get(1).unwrap(), Register)?;
let args = args!(I, immediate: address as u16, r1: offset);
match opcode {
Opcode::Jmp => Ok(Instruction::Jump(args)),
Opcode::Jeq => Ok(Instruction::JumpEq(args)),
Opcode::Jne => Ok(Instruction::JumpNeq(args)),
Opcode::Jgt => Ok(Instruction::JumpGt(args)),
Opcode::Jge => Ok(Instruction::JumpGe(args)),
Opcode::Jlt => Ok(Instruction::JumpLt(args)),
Opcode::Jle => Ok(Instruction::JumpLe(args)),
_ => unreachable!(),
}
}
Opcode::Cmp => {
let left = expect_token!(args.get(0).unwrap(), Register)?;
let right = expect_token!(args.get(1).unwrap(), Register)?;
Ok(Instruction::Compare(args!(R, sr1: left, sr2: right)))
}
Opcode::Inc => {
let reg = expect_token!(args.get(0).unwrap(), Register)?;
Ok(Instruction::Increment(args!(R, sr1: reg)))
}
Opcode::Dec => {
let reg = expect_token!(args.get(0).unwrap(), Register)?;
Ok(Instruction::Decrement(args!(R, sr1: reg)))
}
Opcode::Shl => {
let reg = expect_token!(args.get(0).unwrap(), Register)?;
let amount = expect_token!(args.get(1).unwrap(), Immediate)? as u8;
Ok(Instruction::ShiftLeft(args!(R, sr1: reg, shamt: amount)))
}
Opcode::Shr => {
let reg = expect_token!(args.get(0).unwrap(), Register)?;
let amount = expect_token!(args.get(1).unwrap(), Immediate)? as u8;
Ok(Instruction::ShiftRight(args!(R, sr1: reg, shamt: amount)))
}
Opcode::Add
| Opcode::Sub
| Opcode::And
| Opcode::Or
| Opcode::Xor
| Opcode::Nand
| Opcode::Nor
| Opcode::Xnor => {
let left = expect_token!(args.get(0).unwrap(), Register)?;
let right = expect_token!(args.get(1).unwrap(), Register)?;
let dest = expect_token!(args.get(2).unwrap(), Register)?;
let args = args!(R, sr1: left, sr2: right, dr: dest);
match opcode {
Opcode::Add => Ok(Instruction::Add(args)),
Opcode::Sub => Ok(Instruction::Sub(args)),
Opcode::And => Ok(Instruction::And(args)),
Opcode::Or => Ok(Instruction::Or(args)),
Opcode::Xor => Ok(Instruction::Xor(args)),
Opcode::Nand => Ok(Instruction::Nand(args)),
Opcode::Nor => Ok(Instruction::Nor(args)),
Opcode::Xnor => Ok(Instruction::Xnor(args)),
_ => unreachable!(),
}
}
Opcode::Iadd | Opcode::Isub => {
let reg = expect_token!(args.get(0).unwrap(), Register)?;
let immediate = expect_token!(args.get(1).unwrap(), Immediate)? as u16;
let dest = expect_token!(args.get(2).unwrap(), Register)?;
let args = args!(I, immediate: immediate, r1: reg, r2: dest);
match opcode {
Opcode::Iadd => Ok(Instruction::AddImmediate(args)),
Opcode::Isub => Ok(Instruction::SubImmediate(args)),
_ => unreachable!(),
}
}
Opcode::Not => {
let reg = expect_token!(args.get(0).unwrap(), Register)?;
let dest = expect_token!(args.get(1).unwrap(), Register)?;
Ok(Instruction::Not(args!(R, sr1: reg, dr: dest)))
}
Opcode::Int => {
let code = expect_token!(args.get(0).unwrap(), Immediate)? as u8;
Ok(Instruction::Interrupt(Interrupt::Software(code)))
}
Opcode::Irt => Ok(Instruction::IntReturn),
Opcode::Hlt => Ok(Instruction::Halt),
Opcode::Data => {
let immediate = expect_token!(args.get(0).unwrap(), Immediate)?;
Ok(Instruction::Data(immediate))
}
Opcode::Segment => {
let immediate = expect_token!(args.get(0).unwrap(), Immediate)?;
Ok(Instruction::Segment(immediate))
}
Opcode::Db
| Opcode::Dh
| Opcode::Dw
| Opcode::Resb
| Opcode::Resh
| Opcode::Resw
| Opcode::Push
| Opcode::Pop
| Opcode::Lwi
| Opcode::Include => todo!(),
}
}