use crate::error::{AssemblerError, Result};
use crate::opcode_table::{create_instruction_map, encode_opcode};
use std::collections::HashMap;
pub struct Opcodes {
opcodes: HashMap<String, u8>,
}
impl Opcodes {
pub fn new() -> Self {
Self {
opcodes: create_instruction_map(),
}
}
pub fn get_opcode(&self, name: &str) -> Result<u8> {
const OPS: [&str; 32] = [
"LIT", "INC", "POP", "NIP", "SWP", "ROT", "DUP", "OVR",
"EQU", "NEQ", "GTH", "LTH", "JMP", "JCN", "JSR", "STH",
"LDZ", "STZ", "LDR", "STR", "LDA", "STA", "DEI", "DEO",
"ADD", "SUB", "MUL", "DIV", "AND", "ORA", "EOR", "SFT"
];
let name = name.trim();
for (i, &base) in OPS.iter().enumerate() {
if name.len() < 3 { continue; }
if &name[..3].to_ascii_uppercase() != base { continue; }
let mut opcode = i as u8;
let mut m = 3;
if i == 0 { opcode |= 1 << 7; }
let chars: Vec<char> = name.chars().collect();
while m < chars.len() {
match chars[m] {
'2' => opcode |= 1 << 5,
'r' => opcode |= 1 << 6,
'k' => opcode |= 1 << 7,
_ => return Err(crate::error::AssemblerError::SyntaxError {
path: "".to_string(),
line: 0,
position: 0,
message: format!("Invalid mode flag '{}' in opcode '{}'", chars[m], name),
source_line: "".to_string(),
}),
}
m += 1;
}
return Ok(opcode);
}
if name.eq_ignore_ascii_case("BRK") {
return Ok(0x00);
}
Err(crate::error::AssemblerError::SyntaxError {
path: "".to_string(),
line: 0,
position: 0,
message: format!("Unknown opcode '{}'", name),
source_line: "".to_string(),
})
}
pub fn apply_modes(opcode: u8, short_mode: bool, return_mode: bool, keep_mode: bool) -> u8 {
encode_opcode(opcode, short_mode, return_mode, keep_mode)
}
}
impl Default for Opcodes {
fn default() -> Self {
Self::new()
}
}