diff --git a/src/assemble.rs b/src/assemble.rs index e4ae59c..61d37fc 100644 --- a/src/assemble.rs +++ b/src/assemble.rs @@ -1,13 +1,22 @@ use crate::exit; use log::debug; use progress_bar::*; +use std::collections::HashMap; use std::fs::File; use std::io::Write; -use struct_iterable::Iterable; use crate::insturctions::get_hex; -#[derive(Debug, Default, Iterable)] +#[derive(Debug)] +struct Function { + name: String, + addr: u8, +} + +#[derive(Debug, Default)] +struct Word {} + +#[derive(Debug, Default)] struct Instruction { opt_code: u8, arg1: u8, @@ -17,13 +26,17 @@ struct Instruction { } pub fn assemble(code: Vec, output: String) { - let mut output_file = File::create(&output).unwrap(); + let mut functions: HashMap = HashMap::new(); let mut hex_code: Vec = Vec::new(); init_progress_bar_with_eta(code.len()); set_progress_bar_action("Assembling:", Color::Blue, Style::Bold); + let mut count: u8 = 0; + for line in code.iter() { + count += 1; + let code_line = match line.split_once('#') { Some(s) => s.0, None => line, @@ -32,15 +45,50 @@ pub fn assemble(code: Vec, output: String) { let mut line_split = code_line.split(' ').collect::>(); line_split.retain(|&x| x != ""); debug!("({:?})", line_split); + if line_split.is_empty() { + inc_progress_bar(); continue; } + + if line_split[0].starts_with('.') { + let func_name = line_split[0].replace('.', ""); + if func_name.is_empty() { + set_progress_bar_action("Error", Color::Red, Style::Normal); + finalize_progress_bar(); + eprintln!("Found invalid function name: ({})", func_name); + exit(1) + } + functions.insert(line_split[0].replace('.', ""), count); + inc_progress_bar(); + continue; + } + let opt_code = line_split[0]; - let opt_code_hex = get_hex(&opt_code); + let opt_code_hex = match get_hex(&opt_code) { + Some(i) => i, + None => { + let func_pos = match functions.get(opt_code) { + Some(r) => *r, + None => { + set_progress_bar_action("Error", Color::Red, Style::Normal); + finalize_progress_bar(); + + eprintln!( + "Invalid or unkonw function/instruction called: ({})", + opt_code + ); + exit(1) + } + }; + (func_pos, 0, 1) + } + }; if !(opt_code_hex.1 == (line_split.len() as i32 - 1)) { set_progress_bar_action("Error", Color::Red, Style::Normal); finalize_progress_bar(); + eprintln!( "Found {} arguments for {}, but expected {}", line_split.len() as i32 - 1, @@ -51,8 +99,7 @@ pub fn assemble(code: Vec, output: String) { } let mut instruction = Instruction::default(); - instruction.opt_code = - u8::from_str_radix(opt_code_hex.0.to_string().strip_prefix("0x").unwrap(), 16).unwrap(); + instruction.opt_code = opt_code_hex.0; let mut args: Vec = Vec::new(); @@ -81,7 +128,9 @@ pub fn assemble(code: Vec, output: String) { inc_progress_bar(); } + let mut output_file = File::create(&output).unwrap(); append_hex(&mut output_file, hex_code); + set_progress_bar_action("Done", Color::Green, Style::Bold); finalize_progress_bar(); println!("Finshed assembling progamm, output found in: {}", output); diff --git a/src/insturctions.rs b/src/insturctions.rs index 7fb3f14..4971573 100644 --- a/src/insturctions.rs +++ b/src/insturctions.rs @@ -1,87 +1,87 @@ -pub fn get_hex(function: &str) -> (&str, i32) { +pub fn get_hex(function: &str) -> Option<(u8, i32, i32)> { return match function { // General - "NOP" => ("0x00", 1), - "HALT" => ("0xf0", 1), - "HALI" => ("0xf1", 1), + "NOP" => Some((u8::from_str_radix("00", 16).unwrap(), 1, 0)), + "HALT" => Some((u8::from_str_radix("f0", 16).unwrap(), 1, 0)), + "HALI" => Some((u8::from_str_radix("f1", 16).unwrap(), 1, 0)), //General End // Memory - "LOAD" => ("0x01", 2), - "STOA" => ("0x02", 2), - "MOV" => ("0x03", 3), - "PUSH" => ("0x04", 2), - "POP" => ("0x05", 2), - "LUI" => ("0x062", 2), - "LOADR" => ("0x07", 3), + "LOAD" => Some((u8::from_str_radix("01", 16).unwrap(), 2, 0)), + "STOA" => Some((u8::from_str_radix("02", 16).unwrap(), 2, 0)), + "MOV" => Some((u8::from_str_radix("03", 16).unwrap(), 3, 0)), + "PUSH" => Some((u8::from_str_radix("04", 16).unwrap(), 2, 0)), + "POP" => Some((u8::from_str_radix("05", 16).unwrap(), 2, 0)), + "LUI" => Some((u8::from_str_radix("06", 16).unwrap(), 2, 0)), + "LOADR" => Some((u8::from_str_radix("07", 16).unwrap(), 3, 0)), //Memory End // Math // Standard Unsigned - "ADD" => ("0x10", 4), - "SUB" => ("0x11", 4), - "MUL" => ("0x12", 4), - "DIV" => ("0x13", 4), - "ADDI" => ("0x14", 3), + "ADD" => Some((u8::from_str_radix("10", 16).unwrap(), 4, 0)), + "SUB" => Some((u8::from_str_radix("11", 16).unwrap(), 4, 0)), + "MUL" => Some((u8::from_str_radix("12", 16).unwrap(), 4, 0)), + "DIV" => Some((u8::from_str_radix("13", 16).unwrap(), 4, 0)), + "ADDI" => Some((u8::from_str_radix("14", 16).unwrap(), 3, 0)), // Standard Signed - "ADDS" => ("0x20", 4), - "SUBS" => ("0x21", 4), - "MULS" => ("0x22", 4), - "DIVS" => ("0x23", 4), - "ADDIS" => ("0x24", 3), + "ADDS" => Some((u8::from_str_radix("20", 16).unwrap(), 4, 0)), + "SUBS" => Some((u8::from_str_radix("21", 16).unwrap(), 4, 0)), + "MULS" => Some((u8::from_str_radix("22", 16).unwrap(), 4, 0)), + "DIVS" => Some((u8::from_str_radix("23", 16).unwrap(), 4, 0)), + "ADDIS" => Some((u8::from_str_radix("24", 16).unwrap(), 3, 0)), // Bitwise - "OR" => ("0x16", 4), - "AND" => ("0x17", 4), - "XOR" => ("0x18", 4), - "NOT" => ("0x19", 3), + "OR" => Some((u8::from_str_radix("16", 16).unwrap(), 4, 0)), + "AND" => Some((u8::from_str_radix("17", 16).unwrap(), 4, 0)), + "XOR" => Some((u8::from_str_radix("18", 16).unwrap(), 4, 0)), + "NOT" => Some((u8::from_str_radix("19", 16).unwrap(), 3, 0)), // Advanced - "SHR" => ("0x1A", 4), - "SHL" => ("0x1B", 4), - "SHRS" => ("0x1C", 4), - "SHLS" => ("0x1D", 4), + "SHR" => Some((u8::from_str_radix("1A", 16).unwrap(), 4, 0)), + "SHL" => Some((u8::from_str_radix("1B", 16).unwrap(), 4, 0)), + "SHRS" => Some((u8::from_str_radix("1C", 16).unwrap(), 4, 0)), + "SHLS" => Some((u8::from_str_radix("1D", 16).unwrap(), 4, 0)), // Math End // Jump/Branch - "JAL" => ("0x30", 2), - "JALR" => ("0x31", 3), - "BEG" => ("0x32", 3), - "BNE" => ("0x33", 3), - "BLT" => ("0x34", 3), - "BLE" => ("0x35", 3), - "BGT" => ("0x36", 3), - "BGE" => ("0x37", 3), - "BLTU" => ("0x38", 3), - "BLEU" => ("0x39", 3), - "BGEU" => ("0x3A", 3), - "BGTU" => ("0x3B", 3), + "JAL" => Some((u8::from_str_radix("30", 16).unwrap(), 2, 0)), + "JALR" => Some((u8::from_str_radix("31", 16).unwrap(), 3, 0)), + "BEG" => Some((u8::from_str_radix("32", 16).unwrap(), 3, 0)), + "BNE" => Some((u8::from_str_radix("33", 16).unwrap(), 3, 0)), + "BLT" => Some((u8::from_str_radix("34", 16).unwrap(), 3, 0)), + "BLE" => Some((u8::from_str_radix("35", 16).unwrap(), 3, 0)), + "BGT" => Some((u8::from_str_radix("36", 16).unwrap(), 3, 0)), + "BGE" => Some((u8::from_str_radix("37", 16).unwrap(), 3, 0)), + "BLTU" => Some((u8::from_str_radix("38", 16).unwrap(), 3, 0)), + "BLEU" => Some((u8::from_str_radix("39", 16).unwrap(), 3, 0)), + "BGEU" => Some((u8::from_str_radix("3A", 16).unwrap(), 3, 0)), + "BGTU" => Some((u8::from_str_radix("3B", 16).unwrap(), 3, 0)), // Jump/Branch End // Set - "SEG" => ("0x42", 3), - "SNE" => ("0x43", 3), - "SLT" => ("0x44", 3), - "SLE" => ("0x45", 3), - "SGT" => ("0x46", 3), - "SGE" => ("0x47", 3), - "SLTU" => ("0x48", 3), - "SLEU" => ("0x49", 3), - "SGEU" => ("0x4A", 3), - "SGTU" => ("0x4B", 3), + "SEG" => Some((u8::from_str_radix("42", 16).unwrap(), 3, 0)), + "SNE" => Some((u8::from_str_radix("43", 16).unwrap(), 3, 0)), + "SLT" => Some((u8::from_str_radix("44", 16).unwrap(), 3, 0)), + "SLE" => Some((u8::from_str_radix("45", 16).unwrap(), 3, 0)), + "SGT" => Some((u8::from_str_radix("46", 16).unwrap(), 3, 0)), + "SGE" => Some((u8::from_str_radix("47", 16).unwrap(), 3, 0)), + "SLTU" => Some((u8::from_str_radix("48", 16).unwrap(), 3, 0)), + "SLEU" => Some((u8::from_str_radix("49", 16).unwrap(), 3, 0)), + "SGEU" => Some((u8::from_str_radix("4A", 16).unwrap(), 3, 0)), + "SGTU" => Some((u8::from_str_radix("4B", 16).unwrap(), 3, 0)), // Set End // IO - "IOWI" => ("0x50", 2), - "IOLI" => ("0x51", 2), - "IOW" => ("0x52", 3), - "IOR" => ("0x53", 3), + "IOWI" => Some((u8::from_str_radix("50", 16).unwrap(), 2, 0)), + "IOLI" => Some((u8::from_str_radix("51", 16).unwrap(), 2, 0)), + "IOW" => Some((u8::from_str_radix("52", 16).unwrap(), 3, 0)), + "IOR" => Some((u8::from_str_radix("53", 16).unwrap(), 3, 0)), // IO End // Flash - "LF" => ("0x60", 3), + "LF" => Some((u8::from_str_radix("60", 16).unwrap(), 3, 0)), // Flash End - _ => panic!("There is no such function called {}", function), + _ => None, }; } diff --git a/test.s b/test.s index c19a046..b6d7609 100644 --- a/test.s +++ b/test.s @@ -55,3 +55,10 @@ IOLI 0x02 0x02 IOW 0x03 0x03 0x03 IOR 0x03 0x03 0x03 LF 0x03 0x03 0x03 + +.FUNC +ADD 0x04 0x04 0x04 0x04 +SUB 0x04 0x04 0x04 0x04 +MUL 0x04 0x04 0x04 0x04 +DIV 0x04 0x04 0x04 0x04 +ADDI 0x03 0x03 0x03