IT WORKS HELL YEAH.
This commit is contained in:
+187
-3
@@ -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!(),
|
||||
}
|
||||
}
|
||||
|
||||
+43
-11
@@ -29,7 +29,14 @@ fn try_expand(
|
||||
match node.opcode() {
|
||||
Opcode::Push => expand_push(node.clone(), result)?,
|
||||
Opcode::Pop => expand_pop(node.clone(), result)?,
|
||||
Opcode::Ldb | Opcode::Ldh | Opcode::Ldw => expand_ldx(node.clone(), result)?,
|
||||
Opcode::Ldb
|
||||
| Opcode::Ldbs
|
||||
| Opcode::Ldh
|
||||
| Opcode::Ldhs
|
||||
| Opcode::Ldw
|
||||
| Opcode::Stb
|
||||
| Opcode::Sth
|
||||
| Opcode::Stw => expand_ldx(node.clone(), result)?,
|
||||
Opcode::Lwi => expand_lwi(node.clone(), result)?,
|
||||
Opcode::Resb | Opcode::Resh | Opcode::Resw => expand_resx(node.clone(), result)?,
|
||||
Opcode::Db | Opcode::Dh | Opcode::Dw => expand_dx(node.clone(), result)?,
|
||||
@@ -43,8 +50,20 @@ fn expand_push(current: Node, nodes: &mut Vec<Node>) -> Result<(), AssembleError
|
||||
let reg = expect_type!(current.arg(0).unwrap(), Register)?;
|
||||
|
||||
nodes.extend(vec![
|
||||
node!(label, Opcode::Iadd, reg.clone(), Token::Immediate(4)),
|
||||
node!(None, Opcode::Stw, reg, Token::Register(Register::Spr)),
|
||||
node!(
|
||||
label,
|
||||
Opcode::Iadd,
|
||||
reg.clone(),
|
||||
Token::Immediate(4),
|
||||
reg.clone()
|
||||
),
|
||||
node!(
|
||||
None,
|
||||
Opcode::Stw,
|
||||
reg,
|
||||
Token::Register(Register::Spr),
|
||||
Token::Immediate(0)
|
||||
),
|
||||
]);
|
||||
|
||||
Ok(())
|
||||
@@ -55,8 +74,20 @@ fn expand_pop(current: Node, nodes: &mut Vec<Node>) -> Result<(), AssembleError>
|
||||
let reg = expect_type!(current.arg(0).unwrap(), Register)?;
|
||||
|
||||
nodes.extend(vec![
|
||||
node!(label, Opcode::Isub, reg.clone(), Token::Immediate(4)),
|
||||
node!(None, Opcode::Ldw, reg, Token::Register(Register::Spr)),
|
||||
node!(
|
||||
label,
|
||||
Opcode::Isub,
|
||||
reg.clone(),
|
||||
Token::Immediate(4),
|
||||
reg.clone()
|
||||
),
|
||||
node!(
|
||||
None,
|
||||
Opcode::Ldw,
|
||||
reg,
|
||||
Token::Register(Register::Spr),
|
||||
Token::Immediate(0)
|
||||
),
|
||||
]);
|
||||
|
||||
Ok(())
|
||||
@@ -65,24 +96,25 @@ fn expand_pop(current: Node, nodes: &mut Vec<Node>) -> Result<(), AssembleError>
|
||||
fn expand_ldx(current: Node, nodes: &mut Vec<Node>) -> Result<(), AssembleError> {
|
||||
let opcode = current.opcode();
|
||||
let name = expect_type!(current.arg(0).unwrap(), Symbol)?;
|
||||
let reg = expect_type!(current.arg(2).unwrap(), Register)?;
|
||||
let reg = expect_type!(current.arg(1).unwrap(), Register)?;
|
||||
let offset = expect_type!(current.arg(2).unwrap(), Immediate)?;
|
||||
|
||||
nodes.extend(vec![
|
||||
node!(current.label(), Opcode::Lli, name.clone(), reg.clone()),
|
||||
node!(None, Opcode::Lui, name.clone(), reg.clone()),
|
||||
node!(None, opcode, reg.clone(), Token::Immediate(0), reg),
|
||||
node!(None, opcode, reg.clone(), reg, offset),
|
||||
]);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn expand_lwi(current: Node, nodes: &mut Vec<Node>) -> Result<(), AssembleError> {
|
||||
let reg = expect_type!(current.arg(0).unwrap(), Register)?;
|
||||
let name = expect_type!(current.arg(1).unwrap(), Symbol)?;
|
||||
let val = expect_type!(current.arg(0).unwrap(), Symbol, Immediate)?;
|
||||
let reg = expect_type!(current.arg(1).unwrap(), Register)?;
|
||||
|
||||
nodes.extend(vec![
|
||||
node!(current.label(), Opcode::Lli, name.clone(), reg.clone()),
|
||||
node!(None, Opcode::Lui, name.clone(), reg.clone()),
|
||||
node!(current.label(), Opcode::Lli, val.clone(), reg.clone()),
|
||||
node!(None, Opcode::Lui, val.clone(), reg.clone()),
|
||||
]);
|
||||
|
||||
Ok(())
|
||||
|
||||
+16
-11
@@ -9,10 +9,11 @@ use std::{
|
||||
use common::prelude::Instruction;
|
||||
|
||||
use crate::{
|
||||
codegen::codegen,
|
||||
expand::expand_pseudo_ops,
|
||||
model::{Node, Symbol, Token, TokenType},
|
||||
parser::{Parser, Program},
|
||||
resolver::{resolve_dependencies, resolve_symbols},
|
||||
resolver::{create_sections, resolve_dependencies, resolve_symbols},
|
||||
};
|
||||
|
||||
pub mod codegen;
|
||||
@@ -22,26 +23,25 @@ pub mod model;
|
||||
pub mod parser;
|
||||
pub mod resolver;
|
||||
|
||||
pub fn assemble(src: &Path) -> Vec<Instruction> {
|
||||
pub fn assemble(src: &Path) -> Result<Vec<Instruction>, AssembleError> {
|
||||
let mut modules = HashSet::<u64>::new();
|
||||
let mut program = Program::new();
|
||||
|
||||
let hash = quick_hash(src);
|
||||
modules.insert(hash);
|
||||
|
||||
match prepare_dependency(src, &mut modules, &mut program) {
|
||||
Ok(_) => {}
|
||||
Err(err) => println!("BIG ERROR {err:?}"),
|
||||
}
|
||||
|
||||
prepare_dependency(src, &mut modules, &mut program)?;
|
||||
let mut nodes = program.nodes;
|
||||
resolve_symbols(&mut nodes).unwrap();
|
||||
|
||||
for node in nodes {
|
||||
println!("{node}");
|
||||
create_sections(&mut nodes)?;
|
||||
resolve_symbols(&mut nodes)?;
|
||||
|
||||
let instructions = codegen(nodes)?;
|
||||
for inst in instructions.iter() {
|
||||
println!("{}", inst);
|
||||
}
|
||||
|
||||
vec![]
|
||||
Ok(instructions)
|
||||
}
|
||||
|
||||
fn prepare_dependency(
|
||||
@@ -71,6 +71,7 @@ fn prepare_dependency(
|
||||
|
||||
log(&format!("{:20} {:20}", "Resolving Deps", filename));
|
||||
let nodes = resolve_dependencies(parsed)?;
|
||||
|
||||
let deps = Parser::get_dependencies(&nodes)?;
|
||||
|
||||
log(&format!(
|
||||
@@ -79,6 +80,10 @@ fn prepare_dependency(
|
||||
));
|
||||
let nodes = expand_pseudo_ops(nodes, file_hash)?;
|
||||
|
||||
for n in nodes.iter() {
|
||||
println!("{}", n);
|
||||
}
|
||||
|
||||
program.add_module(nodes);
|
||||
|
||||
for dep in deps {
|
||||
|
||||
+11
-6
@@ -13,10 +13,15 @@ fn main() {
|
||||
let src = PathBuf::from(input_path);
|
||||
let mut output_file = fs::File::create(output_path).unwrap();
|
||||
|
||||
assembler::assemble(&src)
|
||||
.iter()
|
||||
.map(|i| i.encode())
|
||||
.for_each(|i| {
|
||||
output_file.write_all(&i.to_le_bytes()).unwrap();
|
||||
});
|
||||
match assembler::assemble(&src) {
|
||||
Ok(res) => {
|
||||
res.iter().map(|i| i.encode()).for_each(|i| {
|
||||
output_file.write_all(&i.to_le_bytes()).unwrap();
|
||||
});
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("{}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,6 +141,7 @@ impl fmt::Display for Opcode {
|
||||
|
||||
// special - generated by assembler
|
||||
Opcode::Data => write!(f, "data"),
|
||||
Opcode::Segment => write!(f, "[SEGMENT]"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -249,6 +250,7 @@ pub enum Opcode {
|
||||
|
||||
// fake instructions (these aren't present in the binary as instructions)
|
||||
Data,
|
||||
Segment,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -376,6 +378,7 @@ impl Opcode {
|
||||
Self::Hlt => Some(0x24),
|
||||
Self::Iadd => Some(0x25),
|
||||
Self::Isub => Some(0x26),
|
||||
Self::Segment => Some(0x27),
|
||||
// Pseudo-instructions don't have opcode values
|
||||
_ => None,
|
||||
}
|
||||
|
||||
+50
-34
@@ -68,6 +68,8 @@ impl Parser {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
println!("{:?}", self.peek_next()?);
|
||||
|
||||
// check if the Node starts with a label
|
||||
let label = expect_token!(self.peek_next()?, Symbol).ok();
|
||||
if label.is_some() {
|
||||
@@ -85,32 +87,25 @@ impl Parser {
|
||||
args = vec![reg1, reg2];
|
||||
}
|
||||
|
||||
Opcode::Ldb | Opcode::Ldbs | Opcode::Ldh | Opcode::Ldhs | Opcode::Ldw => {
|
||||
Opcode::Ldb
|
||||
| Opcode::Ldbs
|
||||
| Opcode::Ldh
|
||||
| Opcode::Ldhs
|
||||
| Opcode::Ldw
|
||||
| Opcode::Stb
|
||||
| Opcode::Sth
|
||||
| Opcode::Stw => {
|
||||
let base = expect_type!(self.next()?, Register, Symbol)?;
|
||||
let dest = expect_type!(self.next()?, Register, Symbol)?;
|
||||
let dest = expect_type!(self.next()?, Register)?;
|
||||
|
||||
let mut offset = Token::Immediate(0);
|
||||
if let Ok(next) = self.peek_next() {
|
||||
if let Ok(_) = expect_type!(next, Register, Immediate) {
|
||||
if let Ok(_) = expect_type!(next, Immediate) {
|
||||
offset = self.next()?;
|
||||
}
|
||||
}
|
||||
|
||||
args = vec![base, offset, dest];
|
||||
}
|
||||
|
||||
Opcode::Stb | Opcode::Sth | Opcode::Stw => {
|
||||
let base = expect_type!(self.next()?, Register, Symbol)?;
|
||||
let dest = expect_type!(self.next()?, Register, Symbol)?;
|
||||
|
||||
let mut offset = Token::Immediate(0);
|
||||
if let Ok(next) = self.peek_next() {
|
||||
if let Ok(_) = expect_type!(next, Register, Immediate) {
|
||||
offset = self.next()?;
|
||||
}
|
||||
}
|
||||
|
||||
args = vec![base, offset, dest];
|
||||
args = vec![base, dest, offset];
|
||||
}
|
||||
|
||||
Opcode::Add
|
||||
@@ -159,14 +154,31 @@ impl Parser {
|
||||
| Opcode::Jlt
|
||||
| Opcode::Jle => {
|
||||
let imm = expect_type!(self.next()?, Immediate, Symbol)?;
|
||||
args = vec![imm];
|
||||
let offset = if expect_type!(self.peek_next()?, Register).is_ok() {
|
||||
self.next()?
|
||||
} else {
|
||||
Token::Register(Register::Zero)
|
||||
};
|
||||
args = vec![imm, offset];
|
||||
}
|
||||
|
||||
// I-type instructions
|
||||
Opcode::Lui | Opcode::Lli | Opcode::Lwi | Opcode::Iadd | Opcode::Isub => {
|
||||
let reg = expect_type!(self.next()?, Register)?;
|
||||
Opcode::Lui | Opcode::Lli | Opcode::Lwi => {
|
||||
let imm = expect_type!(self.next()?, Immediate, Symbol)?;
|
||||
args = vec![reg, imm];
|
||||
let reg = expect_type!(self.next()?, Register)?;
|
||||
args = vec![imm, reg];
|
||||
}
|
||||
|
||||
// Immediate Arithmetic
|
||||
Opcode::Iadd | Opcode::Isub => {
|
||||
let reg = expect_type!(self.next()?, Register)?;
|
||||
let imm = expect_type!(self.next()?, Immediate)?;
|
||||
let reg2 = if expect_type!(self.peek_next()?, Register).is_ok() {
|
||||
self.next()?
|
||||
} else {
|
||||
reg.clone()
|
||||
};
|
||||
args = vec![reg, imm, reg2];
|
||||
}
|
||||
|
||||
// D-type pseudoinstructions (data definition)
|
||||
@@ -199,10 +211,10 @@ impl Parser {
|
||||
|
||||
// Instructions with no arguments
|
||||
Opcode::Hlt | Opcode::Nop | Opcode::Irt => {
|
||||
args = Vec::new();
|
||||
args = vec![];
|
||||
}
|
||||
|
||||
Opcode::Data => {
|
||||
Opcode::Data | Opcode::Segment => {
|
||||
return Err(AssembleError::Generic);
|
||||
}
|
||||
}
|
||||
@@ -238,14 +250,14 @@ impl Parser {
|
||||
Opcode::Dh => {
|
||||
// dh can take u16 immediates
|
||||
while !self.tokens.is_empty() {
|
||||
if let Token::Immediate(val) = self.tokens.last().unwrap() {
|
||||
if *val <= u16::MAX as u32 {
|
||||
match self.tokens.last().unwrap() {
|
||||
Token::StringLit(_) => {
|
||||
values.push(self.tokens.pop().unwrap());
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
Token::Immediate(val) if *val <= u16::MAX as u32 => {
|
||||
values.push(self.tokens.pop().unwrap());
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -253,10 +265,14 @@ impl Parser {
|
||||
Opcode::Dw => {
|
||||
// dw can take u32 immediates
|
||||
while !self.tokens.is_empty() {
|
||||
if let Token::Immediate(_) = self.tokens.last().unwrap() {
|
||||
values.push(self.tokens.pop().unwrap());
|
||||
} else {
|
||||
break;
|
||||
match self.tokens.last().unwrap() {
|
||||
Token::StringLit(_) => {
|
||||
values.push(self.tokens.pop().unwrap());
|
||||
}
|
||||
Token::Immediate(val) if *val <= u32::MAX as u32 => {
|
||||
values.push(self.tokens.pop().unwrap());
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
use std::{collections::HashMap, path::PathBuf};
|
||||
|
||||
use common::prelude::Register;
|
||||
|
||||
use crate::{
|
||||
AssembleError,
|
||||
model::{Module, Node, Opcode, Symbol, Token},
|
||||
quick_hash,
|
||||
node, quick_hash,
|
||||
};
|
||||
|
||||
pub fn resolve_symbols(nodes: &mut Vec<Node>) -> Result<(), AssembleError> {
|
||||
@@ -119,3 +121,36 @@ pub fn resolve_dependencies(mut nodes: Vec<Node>) -> Result<Vec<Node>, AssembleE
|
||||
|
||||
Ok(nodes)
|
||||
}
|
||||
|
||||
pub fn create_sections(nodes: &mut Vec<Node>) -> Result<(), AssembleError> {
|
||||
let mut res = Vec::<Node>::with_capacity(nodes.len());
|
||||
|
||||
res.push(node!(None, Opcode::Segment, Token::Immediate(0)));
|
||||
|
||||
for n in nodes.iter() {
|
||||
if n.opcode() == Opcode::Data {
|
||||
res.push(n.clone());
|
||||
}
|
||||
}
|
||||
|
||||
res.push(node!(None, Opcode::Segment, Token::Immediate(1)));
|
||||
let start = res.len() + 1;
|
||||
res.insert(
|
||||
0,
|
||||
node!(
|
||||
None,
|
||||
Opcode::Jmp,
|
||||
Token::Immediate(start as u32 * 4),
|
||||
Token::Register(Register::Zero)
|
||||
),
|
||||
);
|
||||
for n in nodes.iter() {
|
||||
if !matches!(n.opcode(), Opcode::Data | Opcode::Include) {
|
||||
res.push(n.clone());
|
||||
}
|
||||
}
|
||||
|
||||
*nodes = res;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user