use crate::hardware::memory::Memory;
use crate::hardware::Registers;
#[derive(PartialEq, Debug)]
pub enum OpCode {
Br = 0,
Add = 1,
Ld = 2,
St = 3,
Jsr = 4,
And = 5,
Ldr = 6,
Str = 7,
Rti = 8,
Not = 9,
Ldi = 10,
Sti = 11,
Jmp = 12,
Res = 13,
Lea = 14,
Trap = 15,
}
impl OpCode {
pub fn get(op_code: u16) -> Option<OpCode> {
match op_code {
0 => Some(OpCode::Br),
1 => Some(OpCode::Add),
2 => Some(OpCode::Ld),
3 => Some(OpCode::St),
4 => Some(OpCode::Jsr),
5 => Some(OpCode::And),
6 => Some(OpCode::Ldr),
7 => Some(OpCode::Str),
8 => Some(OpCode::Rti),
9 => Some(OpCode::Not),
10 => Some(OpCode::Ldi),
11 => Some(OpCode::Sti),
12 => Some(OpCode::Jmp),
13 => Some(OpCode::Res),
14 => Some(OpCode::Lea),
15 => Some(OpCode::Trap),
_ => None,
}
}
}
pub fn execute_instruction(instr: u16, mut registers: &mut Registers, mut memory: &mut Memory) {
let op_code = extract_op_code(&instr);
match op_code {
Some(OpCode::Add) => super::add::add(instr, &mut registers),
Some(OpCode::And) => super::and::and(instr, &mut registers),
Some(OpCode::Not) => super::not::not(instr, &mut registers),
Some(OpCode::Br) => super::br::br(instr, &mut registers),
Some(OpCode::Jmp) => super::jmp::jmp(instr, &mut registers),
Some(OpCode::Jsr) => super::jsr::jsr(instr, &mut registers),
Some(OpCode::Ld) => super::ld::ld(instr, &mut registers, &mut memory),
Some(OpCode::Ldi) => super::ldi::ldi(instr, &mut registers, &mut memory),
Some(OpCode::Ldr) => super::ldr::ldr(instr, &mut registers, &mut memory),
Some(OpCode::Lea) => super::lea::lea(instr, &mut registers),
Some(OpCode::St) => super::st::st(instr, &mut registers, &mut memory),
Some(OpCode::Sti) => super::sti::sti(instr, &mut registers, &mut memory),
Some(OpCode::Str) => super::str::str(instr, &mut registers, &mut memory),
Some(OpCode::Trap) => super::trap::trap(instr, &mut registers, &mut memory),
_ => {}
}
}
fn extract_op_code(instruction: &u16) -> Option<OpCode> {
OpCode::get(instruction >> 12)
}
#[cfg(test)]
mod extract_op_code_test {
use super::*;
#[test]
fn extract_test() {
let four = 16384;
assert_eq!(Some(OpCode::Jsr), extract_op_code(&four));
}
}
#[cfg(test)]
mod op_code_test {
use super::*;
#[test]
fn op_codes_initial_values() {
assert_eq!(Some(OpCode::Br), OpCode::get(0));
assert_eq!(Some(OpCode::Add), OpCode::get(1));
assert_eq!(Some(OpCode::Ld), OpCode::get(2));
assert_eq!(Some(OpCode::St), OpCode::get(3));
assert_eq!(Some(OpCode::Jsr), OpCode::get(4));
assert_eq!(Some(OpCode::And), OpCode::get(5));
assert_eq!(Some(OpCode::Ldr), OpCode::get(6));
assert_eq!(Some(OpCode::Str), OpCode::get(7));
assert_eq!(Some(OpCode::Rti), OpCode::get(8));
assert_eq!(Some(OpCode::Not), OpCode::get(9));
assert_eq!(Some(OpCode::Ldi), OpCode::get(10));
assert_eq!(Some(OpCode::Sti), OpCode::get(11));
assert_eq!(Some(OpCode::Jmp), OpCode::get(12));
assert_eq!(Some(OpCode::Res), OpCode::get(13));
assert_eq!(Some(OpCode::Lea), OpCode::get(14));
assert_eq!(Some(OpCode::Trap), OpCode::get(15));
}
}