summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2019-11-19 02:47:35 +0300
committerOxore <oxore@protonmail.com>2019-11-19 02:47:35 +0300
commit4955030f13c1d79aef005bb3d292224302afcdfa (patch)
treec8e639c3060024e986c2195108de172c9481a8e8 /src
parenta16b1a7a15aca7896afdada535a4700d67d887cb (diff)
Implement Push and Pop instructions
Diffstat (limited to 'src')
-rw-r--r--src/core.rs37
1 files changed, 33 insertions, 4 deletions
diff --git a/src/core.rs b/src/core.rs
index 37886c5..74f79b0 100644
--- a/src/core.rs
+++ b/src/core.rs
@@ -73,6 +73,7 @@ pub struct Core {
}
const RAM_OFFSET_ACC: u8 = 0xE0;
+const RAM_OFFSET_SP: u8 = 0x80;
const RAM_OFFSET_R0: u8 = 0x00;
const RAM_OFFSET_R1: u8 = 0x01;
const RAM_OFFSET_R2: u8 = 0x02;
@@ -82,6 +83,9 @@ 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;
@@ -321,7 +325,9 @@ impl IncompleteOp {
impl Core {
/// Constructor
pub fn new_with_rom_from_hex(hex: String) -> Result<Self, String> {
- let ram: [u8; u8::max_value() as usize + 1] = [0; u8::max_value() as usize + 1];
+ let mut ram: [u8; u8::max_value() as usize + 1] = [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;
let rom = match Rom::from_hex(hex) {
Ok(value) => value,
Err(err_string) => return Err(err_string),
@@ -377,10 +383,13 @@ impl Core {
fn exec(&mut self, op: Op) {
match op.opname {
Opname::Nop => (),
- Opname::Mov => (self.mov(op.operand1.unwrap(), op.operand2.unwrap())),
+ Opname::Mov => self.mov(
+ op.operand1.expect("MOV has no first operand given"),
+ op.operand2.expect("MOV has no second operand given"),
+ ),
Opname::Illegal => (),
- Opname::Push => (),
- Opname::Pop => (),
+ Opname::Push => self.push(op.operand1.expect("PUSH has no operand given")),
+ Opname::Pop => self.pop(op.operand1.expect("POP has no operand given")),
Opname::Sjmp => {
if let Some(operand) = op.operand1 {
match operand {
@@ -466,6 +475,26 @@ impl Core {
self.ram[dest as usize] = value;
}
+ fn push(&mut self, o: Operand) {
+ match o {
+ Operand::Direct(offset) => {
+ self.ram[RAM_OFFSET_SP as usize] += 1;
+ self.ram[self.ram[RAM_OFFSET_SP as usize] as usize] = self.ram[offset as usize];
+ }
+ other => panic!("PUSH got incompatible operand \"{:?}\"", other),
+ }
+ }
+
+ fn pop(&mut self, o: Operand) {
+ match o {
+ Operand::Direct(offset) => {
+ self.ram[offset as usize] = self.ram[self.ram[RAM_OFFSET_SP as usize] as usize];
+ self.ram[RAM_OFFSET_SP as usize] -= 1;
+ }
+ other => panic!("POP got incompatible operand \"{:?}\"", other),
+ }
+ }
+
fn sjmp(&mut self, reladdr: i8) {
self.pc = (self.pc as i16 + i16::from(reladdr)) as u16;
}