diff options
author | Oxore <oxore@protonmail.com> | 2020-03-05 00:33:55 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2020-03-05 00:36:29 +0300 |
commit | 19e0e4cb5f26df537bf07b428700bea30460fd5b (patch) | |
tree | 8f55e2525d107d28899aa3b486c3c8485965aa04 | |
parent | 7d4dfd8af842796c4eb8a88df0cc5ab30f99232d (diff) |
Use bus for all memory types, etc.
Rename Memory to Bus
-rw-r--r-- | src/bus.rs (renamed from src/memory.rs) | 2 | ||||
-rw-r--r-- | src/cpu8051.rs | 93 | ||||
-rw-r--r-- | src/main.rs | 7 | ||||
-rw-r--r-- | src/progmem.rs | 4 | ||||
-rw-r--r-- | src/ram.rs | 50 |
5 files changed, 103 insertions, 53 deletions
diff --git a/src/memory.rs b/src/bus.rs index 3949f75..e3b6579 100644 --- a/src/memory.rs +++ b/src/bus.rs @@ -1,6 +1,6 @@ extern crate num_traits; -pub trait Memory<Addr> +pub trait Bus<Addr> where Addr: Copy + core::ops::Add<Output = Addr> + num_traits::identities::One, { diff --git a/src/cpu8051.rs b/src/cpu8051.rs index 2a0fbe8..8702484 100644 --- a/src/cpu8051.rs +++ b/src/cpu8051.rs @@ -1,6 +1,12 @@ -use crate::memory::Memory; -use crate::progmem::ProgramMemory; +use super::bus::Bus; +use super::progmem::ProgramMemory; +use super::ram::Ram; +use super::ram::RAM_OFFSET_ACC; +use super::ram::RAM_OFFSET_SP; + use std::fmt; +use std::rc::Rc; +use std::cell::RefCell; #[derive(Debug, Clone, Copy)] pub enum Opname { @@ -80,15 +86,13 @@ pub struct Op { pub struct Cpu8051 { pc: u16, - ram: [u8; u8::max_value() as usize + 1], - progmem: ProgramMemory, - extmem: [u8; u16::max_value() as usize + 1], + ram: Rc<RefCell<dyn Bus<u8>>>, + progmem: Rc<RefCell<dyn Bus<u16>>>, + extmem: Rc<RefCell<dyn Bus<u16>>>, } -const RAM_OFFSET_ACC: u8 = 0xE0; const RAM_OFFSET_DPH: u8 = 0x82; const RAM_OFFSET_DPL: u8 = 0x83; -const RAM_OFFSET_SP: u8 = 0x80; const RAM_OFFSET_R0: u8 = 0x00; const RAM_OFFSET_R1: u8 = 0x01; const RAM_OFFSET_R2: u8 = 0x02; @@ -98,9 +102,6 @@ const RAM_OFFSET_R5: u8 = 0x05; const RAM_OFFSET_R6: u8 = 0x06; const RAM_OFFSET_R7: u8 = 0x07; -const RESET_VALUE_ACC: u8 = 0x00; -const RESET_VALUE_SP: u8 = 0x07; - const OPCODE_NOP: u8 = 0x00; const OPCODE_AJMP_P0: u8 = 0x01; const OPCODE_LJMP: u8 = 0x02; @@ -395,18 +396,15 @@ impl IncompleteOp { impl Cpu8051 { /// Constructor pub fn new() -> Self { - let mut ram = [0; u8::max_value() as usize + 1]; - ram[RAM_OFFSET_SP as usize] = RESET_VALUE_SP; - ram[RAM_OFFSET_ACC as usize] = RESET_VALUE_ACC; Self { pc: 0, - ram, - progmem: ProgramMemory::new(), - extmem: [0xFF; u16::max_value() as usize + 1], + ram: Rc::new(RefCell::new(Ram::new())), + progmem: Rc::new(RefCell::new(ProgramMemory::new())), + extmem: Rc::new(RefCell::new(ProgramMemory::new())), } } - pub fn rom(mut self, rom: ProgramMemory) -> Self { + pub fn rom(mut self, rom: Rc<RefCell<dyn Bus<u16>>>) -> Self { self.progmem = rom; self } @@ -425,7 +423,7 @@ impl Cpu8051 { /// Get current instruction pub fn op(&self) -> Op { - let op = IncompleteOp::from_u8(self.progmem.get(self.pc)); + let op = IncompleteOp::from_u8(self.progmem.borrow().get(self.pc)); let mut operands: Vec<Option<Operand>> = vec![op.operand1, op.operand2, op.operand3] .iter() .scan(1, |offset, &x| { @@ -488,11 +486,11 @@ impl Cpu8051 { fn fetch_operand(&self, operand: IncompleteOperand, offset: u16) -> Operand { match operand { IncompleteOperand::Acc => Operand::Acc, - IncompleteOperand::Direct => Operand::Direct(self.progmem.get(self.pc + offset)), - IncompleteOperand::Data => Operand::Data(self.progmem.get(self.pc + offset)), + IncompleteOperand::Direct => Operand::Direct(self.progmem.borrow().get(self.pc + offset)), + IncompleteOperand::Data => Operand::Data(self.progmem.borrow().get(self.pc + offset)), IncompleteOperand::Data16 => Operand::Data16({ - let high = self.progmem.get(self.pc + offset); - let low = self.progmem.get(self.pc + offset + 1); + let high = self.progmem.borrow().get(self.pc + offset); + let low = self.progmem.borrow().get(self.pc + offset + 1); u16::from(high) << 8 & u16::from(low) }), IncompleteOperand::Dptr => Operand::Dptr, @@ -500,15 +498,15 @@ impl Cpu8051 { IncompleteOperand::Indirect(r) => Operand::Indirect(r), IncompleteOperand::Register(r) => Operand::Register(r), IncompleteOperand::Reladdr => { - Operand::Reladdr(self.progmem.get(self.pc + offset) as i8) + Operand::Reladdr(self.progmem.borrow().get(self.pc + offset) as i8) } IncompleteOperand::Addr11(high) => Operand::Addr11({ - let low = self.progmem.get(self.pc + offset); + let low = self.progmem.borrow().get(self.pc + offset); u16::from(high) << 8 & u16::from(low) }), IncompleteOperand::Addr16 => Operand::Addr16({ - let high = self.progmem.get(self.pc + offset); - let low = self.progmem.get(self.pc + offset + 1); + let high = self.progmem.borrow().get(self.pc + offset); + let low = self.progmem.borrow().get(self.pc + offset + 1); u16::from(high) << 8 & u16::from(low) }), } @@ -518,19 +516,19 @@ impl Cpu8051 { let dest = match o1 { Operand::Acc => RAM_OFFSET_ACC, Operand::Direct(dir) => dir, - Operand::Indirect(r) => self.ram[r.to_ram_offset() as usize], + Operand::Indirect(r) => self.ram.borrow().get(r.to_ram_offset()), Operand::Register(r) => r.to_ram_offset(), other => panic!("MOV got incompatible first operand \"{:?}\"", other), }; let value = match o2 { Operand::Acc => RAM_OFFSET_ACC, Operand::Direct(dir) => dir, - Operand::Indirect(r) => self.ram[r.to_ram_offset() as usize], + Operand::Indirect(r) => self.ram.borrow().get(r.to_ram_offset()), Operand::Data(data) => data, Operand::Register(r) => r.to_ram_offset(), other => panic!("MOV got incompatible second operand \"{:?}\"", other), }; - self.ram[dest as usize] = value; + self.ram.borrow_mut().set(dest, value); } fn mov16(&mut self, o1: Operand, o2: Operand) { @@ -545,15 +543,14 @@ impl Cpu8051 { other ), }; - self.ram[dest as usize] = (value >> 8) as u8; - self.ram[dest as usize + 1] = value as u8; + self.ram.borrow_mut().set_word(dest, value); } fn movx_to(&mut self, o1: Operand, o2: Operand) { let dest = match o1 { Operand::AtDptr => { - let dph = self.ram[RAM_OFFSET_DPH as usize]; - let dpl = self.ram[RAM_OFFSET_DPL as usize]; + let dph = self.ram.borrow().get(RAM_OFFSET_DPH); + let dpl = self.ram.borrow().get(RAM_OFFSET_DPL); u16::from(dph) << 8 & u16::from(dpl) } other => panic!( @@ -562,13 +559,13 @@ impl Cpu8051 { ), }; let value = match o2 { - Operand::Acc => self.ram[RAM_OFFSET_ACC as usize], + Operand::Acc => self.ram.borrow().get(RAM_OFFSET_ACC), other => panic!( "MOVX (MovxTo) got incompatible second operand \"{:?}\"", other ), }; - self.extmem[dest as usize] = value; + self.extmem.borrow_mut().set(dest, value); } fn movx_from(&mut self, o1: Operand, o2: Operand) { @@ -581,26 +578,25 @@ impl Cpu8051 { }; let value = match o2 { Operand::AtDptr => { - let dph = u16::from(self.ram[RAM_OFFSET_DPH as usize]); - let dpl = u16::from(self.ram[RAM_OFFSET_DPL as usize]); - let dptr = (dph << 8) + dpl; - self.extmem[dptr as usize] + let dptr = self.ram.borrow().get_word(RAM_OFFSET_DPH); + self.extmem.borrow().get(dptr) } other => panic!( "MOVX (MovxFrom) got incompatible second operand \"{:?}\"", other ), }; - self.extmem[dest as usize] = value; + self.extmem.borrow_mut().set(dest as u16 ,value); } fn push(&mut self, operand: Operand) { match operand { Operand::Direct(offset) => { - self.ram[RAM_OFFSET_SP as usize] += 1; - let value = self.ram[offset as usize]; - let sp = self.ram[RAM_OFFSET_SP as usize]; - self.ram[sp as usize] = value; + let sp = self.ram.borrow().get(RAM_OFFSET_SP); + self.ram.borrow_mut().set(RAM_OFFSET_SP, sp + 1); + let value = self.ram.borrow().get(offset); + let sp = self.ram.borrow().get(RAM_OFFSET_SP); + self.ram.borrow_mut().set(sp, value); } other => panic!("PUSH got incompatible operand \"{:?}\"", other), } @@ -609,9 +605,10 @@ impl Cpu8051 { fn pop(&mut self, operand: Operand) { match operand { Operand::Direct(offset) => { - let sp = self.ram[RAM_OFFSET_SP as usize]; - self.ram[offset as usize] = self.ram[sp as usize]; - self.ram[RAM_OFFSET_SP as usize] -= 1; + let sp = self.ram.borrow().get(RAM_OFFSET_SP); + let stacktop = self.ram.borrow().get(sp); + self.ram.borrow_mut().set(offset, stacktop); + self.ram.borrow_mut().set(RAM_OFFSET_SP, sp - 1); } other => panic!("POP got incompatible operand \"{:?}\"", other), } @@ -647,7 +644,7 @@ impl Cpu8051 { fn jnz(&mut self, operand: Operand) { match operand { Operand::Reladdr(reladdr) => { - if self.ram[usize::from(RAM_OFFSET_ACC)] != 0 { + if self.ram.borrow().get(RAM_OFFSET_ACC) != 0 { self.pc = (self.pc as i16 + i16::from(reladdr)) as u16; } } diff --git a/src/main.rs b/src/main.rs index f43a33e..5aa3307 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,10 +6,13 @@ use std::io::prelude::*; use std::sync::mpsc::{channel, Receiver, Sender}; use std::thread; use std::time::Duration; +use std::rc::Rc; +use std::cell::RefCell; mod cpu8051; -mod memory; +mod bus; mod progmem; +mod ram; use self::cpu8051::Cpu8051; use self::progmem::ProgramMemory; @@ -135,7 +138,7 @@ fn main() { fs::read_to_string(filename).unwrap_or_else(|_| panic!("Unable to read file {}", filename)); let cpu = Cpu8051::new().rom(match ProgramMemory::from_hex(data) { - Ok(value) => value, + Ok(value) => Rc::new(RefCell::new(value)), Err(err_string) => { println!("{}", err_string); return; diff --git a/src/progmem.rs b/src/progmem.rs index 325eab1..93f31fd 100644 --- a/src/progmem.rs +++ b/src/progmem.rs @@ -1,4 +1,4 @@ -use crate::memory::Memory; +use super::bus::Bus; use std::fmt; pub struct ProgramMemory { @@ -125,7 +125,7 @@ impl ProgramMemory { } } -impl Memory<u16> for ProgramMemory { +impl Bus<u16> for ProgramMemory { fn get(&self, a: u16) -> u8 { self.array[a as usize] } diff --git a/src/ram.rs b/src/ram.rs new file mode 100644 index 0000000..7027a0e --- /dev/null +++ b/src/ram.rs @@ -0,0 +1,50 @@ +use super::bus::Bus; +use std::fmt; + +const RESET_VALUE_ACC: u8 = 0x00; +const RESET_VALUE_SP: u8 = 0x07; + +pub const RAM_OFFSET_ACC: u8 = 0xE0; +pub const RAM_OFFSET_SP: u8 = 0x80; + +pub struct Ram { + array: [u8; u8::max_value() as usize + 1], +} + +impl fmt::Debug for Ram { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut v: Vec<char> = vec![]; + for (c, x) in self.array.iter().enumerate() { + for hex_char in format!("{:02X}", *x).chars() { + v.push(hex_char); + } + v.push(' '); + if c % 8 == 7 { + v.push('\n'); + } + } + write!(f, "{}", v.iter().collect::<String>()) + } +} + +impl Ram { + /// Empty constructor + pub fn new() -> Self { + let mut array = [0; u8::max_value() as usize + 1]; + array[RAM_OFFSET_SP as usize] = RESET_VALUE_SP; + array[RAM_OFFSET_ACC as usize] = RESET_VALUE_ACC; + Self { + array, + } + } +} + +impl Bus<u8> for Ram { + fn get(&self, a: u8) -> u8 { + self.array[a as usize] + } + + fn set(&mut self, a: u8, v: u8) { + self.array[a as usize] = v; + } +} |