summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2019-11-18 04:01:59 +0300
committerOxore <oxore@protonmail.com>2019-11-18 04:01:59 +0300
commit7bd685bfa30474e8af5675aa622a502ba2f18797 (patch)
tree8195adcc79f040d49c5adeca46b30c9385a06303
parent8b7dbd123183d0dd648d7897eeece1bbfcfe4a0f (diff)
Implement LJMP instruction
-rw-r--r--src/core.rs32
1 files changed, 31 insertions, 1 deletions
diff --git a/src/core.rs b/src/core.rs
index 01ec71f..f239cdd 100644
--- a/src/core.rs
+++ b/src/core.rs
@@ -37,6 +37,7 @@ pub enum Operand {
Register(Register),
Reladdr(i8),
Addr11(u16),
+ Addr16(u16),
}
#[derive(Debug, Clone)]
@@ -59,6 +60,7 @@ const RAM_OFFSET_R7: u8 = 0x07;
const OPCODE_NOP: u8 = 0x00;
const OPCODE_AJMP_P0: u8 = 0x01;
+const OPCODE_LJMP: u8 = 0x02;
const OPCODE_AJMP_P1: u8 = 0x21;
const OPCODE_AJMP_P2: u8 = 0x41;
const OPCODE_AJMP_P3: u8 = 0x61;
@@ -102,6 +104,12 @@ const OP_LUT: [Isa8051Op; u8::max_value() as usize + 1] = {
operand1: Some(Isa8051Operand::Addr11(0)),
operand2: None,
};
+ lut[OPCODE_LJMP as usize] = Isa8051Op {
+ opcode: Isa8051Opcode::Ljmp,
+ size: 3,
+ operand1: Some(Isa8051Operand::Addr16),
+ operand2: None,
+ };
lut[OPCODE_AJMP_P1 as usize] = Isa8051Op {
opcode: Isa8051Opcode::Ajmp,
size: 2,
@@ -256,6 +264,7 @@ impl fmt::Display for Operand {
Operand::Register(r) => format!("{:?}", r),
Operand::Reladdr(rel) => format!("{}", rel),
Operand::Addr11(rel) => format!("{}", rel),
+ Operand::Addr16(rel) => format!("{}", rel),
}
)
}
@@ -285,6 +294,7 @@ impl Operand {
Operand::Register(_) => 0,
Operand::Reladdr(_) => 1,
Operand::Addr11(_) => 1,
+ Operand::Addr16(_) => 2,
}
}
}
@@ -384,6 +394,16 @@ impl Core {
panic!("AJMP has no operand given")
}
}
+ Isa8051Opcode::Ljmp => {
+ if let Some(operand) = op.operand1 {
+ match operand {
+ Operand::Addr16(addr) => self.ljmp(addr),
+ _ => panic!("LJMP got incompatible operand"),
+ }
+ } else {
+ panic!("LJMP has no operand given")
+ }
+ }
}
}
@@ -411,7 +431,11 @@ impl Core {
}
fn ajmp(&mut self, pageaddr: u16) {
- self.pc = (self.pc & !0x4FFu16) + pageaddr as u16;
+ self.pc = (self.pc & !0x4FFu16) + pageaddr;
+ }
+
+ fn ljmp(&mut self, pageaddr: u16) {
+ self.pc = pageaddr;
}
fn map_operand(&self, operand: Isa8051Operand, offset: usize) -> Operand {
@@ -427,6 +451,10 @@ impl Core {
Isa8051Operand::Addr11(high) => Operand::Addr11(
self.rom.array[(self.pc as usize + offset)] as u16 + (u16::from(high) << 8),
),
+ Isa8051Operand::Addr16 => Operand::Addr16(
+ (u16::from(self.rom.array[(self.pc as usize + offset)]) << 8)
+ + u16::from(self.rom.array[(self.pc as usize + offset + 1)]),
+ ),
}
}
}
@@ -440,12 +468,14 @@ pub enum Isa8051Operand {
Register(Register),
Reladdr,
Addr11(u8),
+ Addr16,
}
#[derive(Debug, Clone, Copy)]
pub enum Isa8051Opcode {
Nop,
Ajmp,
+ Ljmp,
Mov,
Push,
Pop,