mirror of
https://github.com/guilhermewerner/machine
synced 2025-06-16 13:14:18 +00:00
156 lines
4.0 KiB
Rust
156 lines
4.0 KiB
Rust
use std::panic;
|
|
|
|
use crate::Instructions::*;
|
|
use crate::Operations::*;
|
|
|
|
pub const ADDRESS_COUNT: usize = 256;
|
|
pub const REGISTER_COUNT: usize = 16;
|
|
|
|
pub struct Machine {
|
|
program: usize,
|
|
registers: [u8; REGISTER_COUNT],
|
|
memory: [u8; ADDRESS_COUNT],
|
|
}
|
|
|
|
impl Machine {
|
|
/// Create a machine with program counter.
|
|
pub fn New(pc: u8) -> Self {
|
|
Self {
|
|
program: pc as usize,
|
|
registers: [0; REGISTER_COUNT],
|
|
memory: [0; ADDRESS_COUNT],
|
|
}
|
|
}
|
|
|
|
pub fn LoadProgram(&mut self, buffer: &[u8], offset: u8) {
|
|
let mut i = offset as usize;
|
|
|
|
for elem in buffer.to_vec().drain(..) {
|
|
self.memory[i] = elem;
|
|
i += 1;
|
|
}
|
|
}
|
|
|
|
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 => Not(&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),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
fn PrintRegisters(&self) {
|
|
for data in self.registers.iter() {
|
|
print!("{:02x} ", data);
|
|
}
|
|
|
|
println!();
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
fn PrintMemory(&self) {
|
|
let mut address = 0;
|
|
|
|
for data in self.memory.iter() {
|
|
if address % 8 == 0 {
|
|
println!();
|
|
}
|
|
|
|
print!("{:02x} ", data);
|
|
|
|
address += 1;
|
|
}
|
|
|
|
println!();
|
|
}
|
|
|
|
pub fn GetMemory(&self, addr: u8) -> u8 {
|
|
let index = addr as usize;
|
|
|
|
if index < ADDRESS_COUNT {
|
|
self.memory[index]
|
|
} else {
|
|
panic!("Invalid Address!")
|
|
}
|
|
}
|
|
|
|
pub fn SetMemory(&mut self, addr: u8, val: u8) {
|
|
let index = addr as usize;
|
|
|
|
if index < ADDRESS_COUNT {
|
|
self.memory[index] = val;
|
|
}
|
|
}
|
|
|
|
pub fn GetRegister(&self, reg: u8) -> u8 {
|
|
let index = reg as usize;
|
|
|
|
if index < REGISTER_COUNT {
|
|
self.registers[index]
|
|
} else {
|
|
panic!("Invalid Register!")
|
|
}
|
|
}
|
|
|
|
pub fn SetRegister(&mut self, reg: u8, val: u8) {
|
|
let index = reg as usize;
|
|
|
|
if index < REGISTER_COUNT {
|
|
self.registers[index] = val;
|
|
}
|
|
}
|
|
|
|
pub fn GetAddress(&self) -> u8 {
|
|
self.program as u8
|
|
}
|
|
|
|
pub fn WalkAddress(&mut self, bytes: i8) {
|
|
self.program += bytes as usize;
|
|
}
|
|
|
|
pub fn SetAddress(&mut self, addr: u8) {
|
|
self.program = addr as usize;
|
|
}
|
|
}
|