From 92576fbdd379ef29c75ebae27c69d1aa144a571f Mon Sep 17 00:00:00 2001 From: Werner Date: Tue, 16 Nov 2021 10:52:32 -0300 Subject: [PATCH] Simple 8 bits operations --- Cargo.toml | 3 + Examples/Simple.bin | Bin 0 -> 256 bytes Examples/Simple.rs | 14 ++ Source/Instructions.rs | 326 +++++++++++++++++++++++++++++++++++++++++ Source/Operations.rs | 230 +++++++++++++++++++++++++++++ Source/Registers.rs | 47 ++++++ Source/lib.rs | 317 ++++++++++++++++----------------------- 7 files changed, 743 insertions(+), 194 deletions(-) create mode 100644 Examples/Simple.bin create mode 100644 Examples/Simple.rs create mode 100644 Source/Instructions.rs create mode 100644 Source/Operations.rs create mode 100644 Source/Registers.rs diff --git a/Cargo.toml b/Cargo.toml index f5f8b7c..30bc9a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,3 +12,6 @@ name = "Machine" crate-type = ["rlib"] path = "Source/lib.rs" +[[example]] +name = "Simple" +path = "Examples/Simple.rs" diff --git a/Examples/Simple.bin b/Examples/Simple.bin new file mode 100644 index 0000000000000000000000000000000000000000..3ea1f3fa17ab14fcda7f568776ca38ccb982a270 GIT binary patch literal 256 fcmZQ%NMK}4WMN`pWMWEUpgs@^r@om~H1R(GY`OxP literal 0 HcmV?d00001 diff --git a/Examples/Simple.rs b/Examples/Simple.rs new file mode 100644 index 0000000..87be950 --- /dev/null +++ b/Examples/Simple.rs @@ -0,0 +1,14 @@ +#![allow(non_snake_case)] + +use ::Machine::*; +use std::fs; + +fn main() { + let mut vm = Machine::New(0x00); + + let bytecode = fs::read("Examples/Simple.bin").unwrap(); + + vm.LoadProgram(&bytecode, 0x00); + + vm.Execute(); +} diff --git a/Source/Instructions.rs b/Source/Instructions.rs new file mode 100644 index 0000000..872e919 --- /dev/null +++ b/Source/Instructions.rs @@ -0,0 +1,326 @@ +use crate::Machine; + +pub fn Nothing(vm: &mut Machine) -> bool { + vm.program += 1; + false +} + +pub fn LoadRegister(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1]; + let a = vm.memory[vm.program + 2]; + + vm.registers[r as usize] = vm.memory[a as usize]; + + vm.program += 3; + + true +} + +pub fn SaveRegister(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1]; + let a = vm.memory[vm.program + 2]; + + vm.memory[a as usize] = vm.registers[r as usize]; + + vm.program += 3; + + true +} + +pub fn Move(vm: &mut Machine) -> bool { + false +} + +pub fn Add(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + let b = vm.registers[vm.memory[vm.program + 3] as usize]; + + vm.registers[r] = a + b; + vm.program += 4; + + true +} + +pub fn AddAssign(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + + vm.registers[r] += a; + vm.program += 3; + + true +} + +pub fn Subtract(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + let b = vm.registers[vm.memory[vm.program + 3] as usize]; + + vm.registers[r] = a - b; + vm.program += 4; + + true +} + +pub fn SubtractAssign(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + + vm.registers[r] -= a; + vm.program += 3; + + true +} + +pub fn Multiply(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + let b = vm.registers[vm.memory[vm.program + 3] as usize]; + + vm.registers[r] = a * b; + vm.program += 4; + + true +} + +pub fn MultiplyAssign(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + + vm.registers[r] *= a; + vm.program += 3; + + true +} + +pub fn Divide(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + let b = vm.registers[vm.memory[vm.program + 3] as usize]; + + vm.registers[r] = a / b; + vm.program += 4; + + true +} + +pub fn DivideAssign(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + + vm.registers[r] /= a; + vm.program += 3; + + true +} + +pub fn Remainder(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + let b = vm.registers[vm.memory[vm.program + 3] as usize]; + + vm.registers[r] = a % b; + vm.program += 4; + + true +} + +pub fn RemainderAssign(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + + vm.registers[r] %= a; + vm.program += 3; + + true +} + +pub fn Neg(vm: &mut Machine) -> bool { + false +} + +pub fn And(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + let b = vm.registers[vm.memory[vm.program + 3] as usize]; + + vm.registers[r] = a & b; + vm.program += 4; + + true +} + +pub fn AndAssign(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + + vm.registers[r] &= a; + vm.program += 3; + + true +} + +pub fn Or(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + let b = vm.registers[vm.memory[vm.program + 3] as usize]; + + vm.registers[r] = a | b; + vm.program += 4; + + true +} + +pub fn OrAssign(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + + vm.registers[r] |= a; + vm.program += 3; + + true +} + +pub fn Xor(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + let b = vm.registers[vm.memory[vm.program + 3] as usize]; + + vm.registers[r] = a ^ b; + vm.program += 4; + + true +} + +pub fn XorAssign(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + + vm.registers[r] ^= a; + vm.program += 3; + + true +} + +pub fn Not(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + + vm.registers[r] = !a; + vm.program += 3; + + true +} + +pub fn ShiftLeft(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + let b = vm.registers[vm.memory[vm.program + 3] as usize]; + + vm.registers[r] = a << b; + vm.program += 4; + + true +} + +pub fn ShiftLeftAssign(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + + vm.registers[r] <<= a; + vm.program += 3; + + true +} + +pub fn ShiftRight(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + let b = vm.registers[vm.memory[vm.program + 3] as usize]; + + vm.registers[r] = a >> b; + vm.program += 4; + + true +} + +pub fn ShiftRightAssign(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + + vm.registers[r] >>= a; + vm.program += 3; + + true +} + +pub fn Equals(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + let b = vm.registers[vm.memory[vm.program + 3] as usize]; + + vm.registers[r] = (a == b) as u8; + vm.program += 4; + + true +} + +pub fn NotEquals(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + let b = vm.registers[vm.memory[vm.program + 3] as usize]; + + vm.registers[r] = (a != b) as u8; + vm.program += 4; + + true +} + +pub fn LessThan(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + let b = vm.registers[vm.memory[vm.program + 3] as usize]; + + vm.registers[r] = (a < b) as u8; + vm.program += 4; + + true +} + +pub fn LessEquals(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + let b = vm.registers[vm.memory[vm.program + 3] as usize]; + + vm.registers[r] = (a <= b) as u8; + vm.program += 4; + + true +} + +pub fn GreaterThan(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + let b = vm.registers[vm.memory[vm.program + 3] as usize]; + + vm.registers[r] = (a > b) as u8; + vm.program += 4; + + true +} + +pub fn GreaterEquals(vm: &mut Machine) -> bool { + let r = vm.memory[vm.program + 1] as usize; + let a = vm.registers[vm.memory[vm.program + 2] as usize]; + let b = vm.registers[vm.memory[vm.program + 3] as usize]; + + vm.registers[r] = (a >= b) as u8; + vm.program += 4; + + true +} + +pub fn Halt(vm: &mut Machine) -> bool { + false +} diff --git a/Source/Operations.rs b/Source/Operations.rs new file mode 100644 index 0000000..6e4f85f --- /dev/null +++ b/Source/Operations.rs @@ -0,0 +1,230 @@ +/// **0x00** - No operation. +/// +/// ```no_run +/// nop +/// ``` +pub const NOP: u8 = 0x00; + +/// **0x01** - Load register from memory. +/// +/// ```no_run +/// ldr r1 0050 // r1 = mem[0050] +/// ``` +pub const LDR: u8 = 0x01; + +/// **0x02** - Save register in memory. +/// +/// ```no_run +/// svr 0050 r1 // mem[0050] = r1 +/// ``` +pub const SVR: u8 = 0x02; + +/// **0x03** - Move register. +/// +/// ```no_run +/// mov r1 r2 // r1 = r2 +/// ``` +pub const MOV: u8 = 0x03; + +/// **0x04** - The addition operator `+`. +/// +/// ```no_run +/// add r1 r2 r3 // r1 = r2 + r3 +/// ``` +pub const ADD: u8 = 0x04; + +/// **0x05** - The addition assignment operator `+=`. +/// +/// ```no_run +/// add r1 r2 // r1 += r2 +/// ``` +pub const ADD_ASSIGN: u8 = 0x05; + +/// **0x06** - The subtraction operator `-`. +/// +/// ```no_run +/// sub r1 r2 r3 // r1 = r2 - r3 +/// ``` +pub const SUB: u8 = 0x06; + +/// **0x07** - The subtraction assignment operator `-=`. +/// +/// ```no_run +/// sub r1 r2 // r1 -= r2 +/// ``` +pub const SUB_ASSIGN: u8 = 0x07; + +/// **0x08** - The multiplication operator `*`. +/// +/// ```no_run +/// mul r1 r2 r3 // r1 = r2 * r3 +/// ``` +pub const MUL: u8 = 0x08; + +/// **0x09** - The multiplication assignment operator `*=`. +/// +/// ```no_run +/// mul r1 r2 // r1 *= r2 +/// ``` +pub const MUL_ASSIGN: u8 = 0x09; + +/// **0x0A** - The division operator `/`. +/// +/// ```no_run +/// div r1 r2 r3 // r1 = r2 / r3 +/// ``` +pub const DIV: u8 = 0x0A; + +/// **0x0B** - The division assignment operator `/=`. +/// +/// ```no_run +/// div r1 r2 // r1 /= r2 +/// ``` +pub const DIV_ASSIGN: u8 = 0x0B; + +/// **0x0C** - The remainder operator `%`. +/// +/// ```no_run +/// rem r1 r2 r3 // r1 = r2 % r3 +/// ``` +pub const REM: u8 = 0x0C; + +/// **0x0D** - The remainder assignment operator `%=`. +/// +/// ```no_run +/// rem r1 r2 // r1 %= r2 +/// ``` +pub const REM_ASSIGN: u8 = 0x0D; + +/// **0x0E** - Arithmetic negation `-`. +/// +/// ```no_run +/// not r1 r2 // r1 = -r2 +/// ``` +pub const NEG: u8 = 0x0E; + +/// **0x0F** -The bitwise AND operator `&`. +/// +/// ```no_run +/// and r1 r2 r3 // r1 = r2 & r3 +/// ``` +pub const AND: u8 = 0x0F; + +/// **0x10** - The bitwise AND assignment operator `&=`. +/// +/// ```no_run +/// and r1 r2 // r1 &= r2 +/// ``` +pub const AND_ASSIGN: u8 = 0x10; + +/// **0x11** - The bitwise OR operator `|`. +/// +/// ```no_run +/// or r1 r2 r3 // r1 = r2 | r3 +/// ``` +pub const OR: u8 = 0x11; + +/// **0x12** - The bitwise OR assignment operator `|=`. +/// +/// ```no_run +/// or r1 r2 // r1 |= r2 +/// ``` +pub const OR_ASSIGN: u8 = 0x12; + +/// **0x13** - The bitwise XOR operator `^`. +/// +/// ```no_run +/// xor r1 r2 r3 // r1 = r2 ^ r3 +/// ``` +pub const XOR: u8 = 0x13; + +/// **0x14** - The bitwise XOR assignment operator `^=`. +/// +/// ```no_run +/// xor r1 r2 // r1 ^= r2 +/// ``` +pub const XOR_ASSIGN: u8 = 0x14; + +/// **0x15** - Logical negation `!` +/// +/// ```no_run +/// not r1 r2 // r1 = !r2 +/// ``` +pub const NOT: u8 = 0x15; + +/// **0x16** - The left shift operator `<<`. +/// +/// ```no_run +/// shl r1 r2 r3 // r1 = r2 << r3 +/// ``` +pub const SHL: u8 = 0x16; + +/// **0x17** - The left shift assignment operator `<<=`. +/// +/// ```no_run +/// shl r1 r2 // r1 <<= r2 +/// ``` +pub const SHL_ASSIGN: u8 = 0x17; + +/// **0x18** - The right shift operator `>>`. +/// +/// ```no_run +/// shr r1 r2 r3 // r1 = r2 >> r3 +/// ``` +pub const SHR: u8 = 0x18; + +/// **0x19** - The right shift assignment operator `>>=`. +/// +/// ```no_run +/// shr r1 r2 // r1 >>= r2 +/// ``` +pub const SHR_ASSIGN: u8 = 0x19; + +/// **0x1A** - The equality operator `==`. +/// +/// ```no_run +/// eq r1 r2 r3 // r1 = r2 == r3 +/// ``` +pub const EQ: u8 = 0x1A; + +/// **0x1B** - The inequality operator `!=`. +/// +/// ```no_run +/// neq r1 r2 r3 // r1 = r2 != r3 +/// ``` +pub const NEQ: u8 = 0x1B; + +/// **0x1C** - The less than operator `<`. +/// +/// ```no_run +/// lt r1 r2 r3 // r1 = r2 < r3 +/// ``` +pub const LT: u8 = 0x1C; + +/// **0x1D** - The less than or equal to operator `<=`. +/// +/// ```no_run +/// le r1 r2 r3 // r1 = r2 <= r3 +/// ``` +pub const LE: u8 = 0x1D; + +/// **0x1E** - The greater than operator `>`. +/// +/// ```no_run +/// gt r1 r2 r3 // r1 = r2 > r3 +/// ``` +pub const GT: u8 = 0x1E; + +/// **0x1F** - The greater than or equal to operator `>=`. +/// +/// ```no_run +/// ge r1 r2 r3 // r1 = r2 >= r3 +/// ``` +pub const GE: u8 = 0x1F; + +/// **0xFF** - Halt execution. +/// +/// ```no_run +/// hlt +/// ``` +pub const HLT: u8 = 0xFF; diff --git a/Source/Registers.rs b/Source/Registers.rs new file mode 100644 index 0000000..d36a0b2 --- /dev/null +++ b/Source/Registers.rs @@ -0,0 +1,47 @@ +/// **0x00** - r0 +pub const REGISTER_0: u8 = 0x00; + +/// **0x01** - r1 +pub const REGISTER_1: u8 = 0x01; + +/// **0x02** - r2 +pub const REGISTER_2: u8 = 0x02; + +/// **0x03** - r3 +pub const REGISTER_3: u8 = 0x03; + +/// **0x04** - r4 +pub const REGISTER_4: u8 = 0x04; + +/// **0x05** - r5 +pub const REGISTER_5: u8 = 0x05; + +/// **0x06** - r6 +pub const REGISTER_6: u8 = 0x06; + +/// **0x07** - r7 +pub const REGISTER_7: u8 = 0x07; + +/// **0x08** - r8 +pub const REGISTER_8: u8 = 0x08; + +/// **0x09** - r9 +pub const REGISTER_9: u8 = 0x09; + +/// **0x10** - r10 +pub const REGISTER_10: u8 = 0x10; + +/// **0x11** - r11 +pub const REGISTER_11: u8 = 0x11; + +/// **0x12** - r12 +pub const REGISTER_12: u8 = 0x12; + +/// **0x13** - r13 +pub const REGISTER_13: u8 = 0x13; + +/// **0x14** - r14 +pub const REGISTER_14: u8 = 0x14; + +/// **0x15** - r15 +pub const REGISTER_15: u8 = 0x15; diff --git a/Source/lib.rs b/Source/lib.rs index 4c1f363..6c8ee70 100644 --- a/Source/lib.rs +++ b/Source/lib.rs @@ -1,201 +1,130 @@ +#![allow(dead_code)] #![allow(non_snake_case)] +#![allow(unused_imports)] +#![allow(unused_variables)] -#[repr(u8)] -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, TryFromPrimitive)] -pub enum Instruction { - /// **0x00** - No operation. - /// - /// ```no_run - /// nop - /// ``` - Nop = 0x00, +pub mod Instructions; +pub mod Operations; +pub mod Registers; - /// **0x01** - Load register from memory. - /// - /// ```no_run - /// ldr r1 0050 // r1 = mem[0050] - /// ``` - Ldr = 0x01, +use Instructions::*; +use Operations::*; +use Registers::*; - /// **0x02** - Store register in memory. - /// - /// ```no_run - /// str 0050 r1 // mem[0050] = r1 - /// ``` - Str = 0x02, +//#[path = "World.rs"] +//mod _World; +//pub use self::_World::*; - /// **0x03** - Move register. - /// - /// ```no_run - /// mov r1 r2 // r1 = r2 - /// ``` - Mov = 0x03, +pub const ADDRESS_COUNT: usize = 256; +pub const REGISTER_COUNT: usize = 16; - /// **0x04** - Arithmetic addition `+`. - /// - /// ```no_run - /// add r1 r2 r3 // r1 = r2 + r3 - /// ``` - Add = 0x04, - - /// **0x05** - Add with carry. - /// - /// ```no_run - /// adc r1 r2 r3 r4 // r1 = r2 + r3 + r4 - /// ``` - Adc = 0x05, - - /// **0x06** - Arithmetic subtraction `-`. - /// - /// ```no_run - /// sub r1 r2 r3 // r1 = r2 - r3 - /// ``` - Sub = 0x06, - - /// **0x07** - Subtract with carry. - /// - /// ```no_run - /// sbc r1 r2 r3 r4 // r1 = r2 - r3 - 1 - r4 - /// ``` - Sbc = 0x07, - - /// **0x08** - Arithmetic multiplication `*`. - /// - /// ```no_run - /// mul r1 r2 r3 // r1 = r2 * r3 - /// ``` - Mul = 0x08, - - /// **0x09** - Arithmetic division `/`. - /// - /// ```no_run - /// div r1 r2 r3 // r1 = r2 / r3 - /// ``` - Div = 0x09, - - /// **0x0A** - Arithmetic remainder `/`. - /// - /// ```no_run - /// rem r1 r2 r3 // r1 = r2 % r3 - /// ``` - Rem = 0x0A, - - /// **0x0B** - Arithmetic negation `-`. - /// - /// ```no_run - /// not r1 r2 // r1 = -r2 - /// ``` - Neg = 0x0B, - - /// **0x0C** - Bitwise AND `&`. - /// - /// ```no_run - /// and r1 r2 r3 // r1 = r2 & r3 - /// ``` - And = 0x0C, - - /// **0x0D** - Bitwise OR `|`. - /// - /// ```no_run - /// or r1 r2 r3 // r1 = r2 | r3 - /// ``` - Or = 0x0D, - - /// **0x0E** - Bitwise XOR `^`. - /// - /// ```no_run - /// xor r1 r2 r3 // r1 = r2 ^ r3 - /// ``` - Xor = 0x0E, - - /// **0x0F** - Logical negation `!` - /// - /// ```no_run - /// not r1 r2 // r1 = !r2 - /// ``` - Not = 0x0F, - - /// **0x10** - Bitwise NAND. - /// - /// ```no_run - /// nand r1 r2 r3 // r1 = !(r2 & r3) - /// ``` - Nand = 0x10, - - /// **0x11** - Bitwise NOR. - /// - /// ```no_run - /// nor r1 r2 r3 // r1 = !(r2 | r3) - /// ``` - Nor = 0x11, - - /// **0x12** - Bitwise XNOR. - /// - /// ```no_run - /// xnor r1 r2 r3 // r1 = !(r2 ^ r3) - /// ``` - Xnor = 0x12, - - /// **0x13** - Shift left `<<`. - /// - /// ```no_run - /// shl r1 r2 r3 // r1 = r2 << r3 - /// ``` - Shl = 0x13, - - /// **0x14** - Shift right `>>`. - /// - /// ```no_run - /// shr r1 r2 r3 // r1 = r2 >> r3 - /// ``` - Shr = 0x14, - - /// **0x15** - Equality comparation. - /// - /// ```no_run - /// eq r1 r2 r3 // r1 = r2 == r3 - /// ``` - Eq = 0x15, - - /// **0x16** - Inequality comparation. - /// - /// ```no_run - /// neq r1 r2 r3 // r1 = r2 != r3 - /// ``` - Neq = 0x16, - - /// **0x17** - Less comparation. - /// - /// ```no_run - /// lt r1 r2 r3 // r1 = r2 < r3 - /// ``` - Lt = 0x17, - - /// **0x18** - Less-equal comparation. - /// - /// ```no_run - /// le r1 r2 r3 // r1 = r2 <= r3 - /// ``` - Le = 0x18, - - /// **0x19** - Greater comparation. - /// - /// ```no_run - /// gt r1 r2 r3 // r1 = r2 > r3 - /// ``` - Gt = 0x19, - - /// **0x1A** - Greater-equal comparation. - /// - /// ```no_run - /// ge r1 r2 r3 // r1 = r2 >= r3 - /// ``` - Ge = 0x1A, - - /// **0xFF** - Halt execution. - /// - /// ```no_run - /// hlt - /// ``` - Hlt = 0xFF, +pub struct Machine { + pub program: usize, + pub registers: [u8; REGISTER_COUNT], + pub memory: [u8; ADDRESS_COUNT], +} + +impl Machine { + /// Create a machine with program counter. + pub fn New(pc: u16) -> Self { + Self { + program: pc as usize, + registers: [0; REGISTER_COUNT], + memory: [0; ADDRESS_COUNT], + } + } + + pub fn LoadProgram(&mut self, buffer: &[u8], offset: u16) { + let mut i = offset as usize; + + for elem in buffer.to_vec().drain(..) { + self.memory[i] = elem; + i += 1; + } + } + + #[allow(unused_mut)] + pub fn Execute(mut self) { + let mut running = true; + + while running { + self.PrintMemory(); + //self.PrintRegisters(); + + let opcode = self.memory[self.program]; + + running = match opcode { + NOP => Nothing(&mut self), + LDR => LoadRegister(&mut self), + SVR => SaveRegister(&mut self), + //MOV + ADD => Add(&mut self), + ADD_ASSIGN => AddAssign(&mut self), + SUB => Subtract(&mut self), + SUB_ASSIGN => SubtractAssign(&mut self), + MUL => Multiply(&mut self), + MUL_ASSIGN => MultiplyAssign(&mut self), + DIV => Divide(&mut self), + DIV_ASSIGN => DivideAssign(&mut self), + REM => Remainder(&mut self), + REM_ASSIGN => RemainderAssign(&mut self), + //NEG + AND => And(&mut self), + AND_ASSIGN => AndAssign(&mut self), + OR => Or(&mut self), + OR_ASSIGN => OrAssign(&mut self), + XOR => Xor(&mut self), + XOR_ASSIGN => XorAssign(&mut self), + NOT => Xor(&mut self), + SHL => ShiftLeft(&mut self), + SHL_ASSIGN => ShiftLeftAssign(&mut self), + SHR => ShiftRight(&mut self), + SHR_ASSIGN => ShiftRightAssign(&mut self), + EQ => Equals(&mut self), + NEQ => NotEquals(&mut self), + LT => LessThan(&mut self), + LE => LessEquals(&mut self), + GT => GreaterThan(&mut self), + GE => GreaterEquals(&mut self), + HLT => Halt(&mut self), + _ => Nothing(&mut self), + } + } + } + + fn PrintRegisters(&self) { + for data in self.registers.iter() { + print!("{:02x} ", data); + } + + println!(); + } + + fn PrintMemory(&self) { + let mut address = 0; + + for data in self.memory.iter() { + if address % 8 == 0 { + println!(); + } + + print!("{:02x} ", data); + + address += 1; + } + + println!(); + } + + fn GetRegister(&self, register: usize) -> u8 { + self.registers[register] + } + + fn GetProgramCounter(&self) -> u16 { + self.program as u16 + } + + fn SetProgramCounter(&mut self, pc: u16) { + self.program = pc as usize; + } }