summaryrefslogtreecommitdiff
path: root/src/cpu8051.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu8051.rs')
-rw-r--r--src/cpu8051.rs93
1 files changed, 45 insertions, 48 deletions
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;
}
}