summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2020-03-05 00:33:55 +0300
committerOxore <oxore@protonmail.com>2020-03-05 00:36:29 +0300
commit19e0e4cb5f26df537bf07b428700bea30460fd5b (patch)
tree8f55e2525d107d28899aa3b486c3c8485965aa04
parent7d4dfd8af842796c4eb8a88df0cc5ab30f99232d (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.rs93
-rw-r--r--src/main.rs7
-rw-r--r--src/progmem.rs4
-rw-r--r--src/ram.rs50
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;
+ }
+}