diff options
author | Oxore <oxore@protonmail.com> | 2019-11-19 01:33:39 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2019-11-19 01:33:39 +0300 |
commit | 2376146fe9ceee4429b77c4364eaf52ce57dd80c (patch) | |
tree | 1d9fa385dd7db69d7f5b2fca93cecba741534bf0 /src/core.rs | |
parent | 7bd685bfa30474e8af5675aa622a502ba2f18797 (diff) |
Refactor naming in core.rs
Diffstat (limited to 'src/core.rs')
-rw-r--r-- | src/core.rs | 434 |
1 files changed, 213 insertions, 221 deletions
diff --git a/src/core.rs b/src/core.rs index f239cdd..1ec7bae 100644 --- a/src/core.rs +++ b/src/core.rs @@ -2,6 +2,18 @@ use crate::rom::Rom; use std::fmt; #[derive(Debug, Clone, Copy)] +pub enum Opname { + Nop, + Ajmp, + Ljmp, + Mov, + Push, + Pop, + Illegal, + Sjmp, +} + +#[derive(Debug, Clone, Copy)] pub enum Register { R0, R1, @@ -13,19 +25,16 @@ pub enum Register { R7, } -impl Register { - fn to_ram_offset(&self) -> u8 { - match self { - Register::R0 => RAM_OFFSET_R0, - Register::R1 => RAM_OFFSET_R1, - Register::R2 => RAM_OFFSET_R2, - Register::R3 => RAM_OFFSET_R3, - Register::R4 => RAM_OFFSET_R4, - Register::R5 => RAM_OFFSET_R5, - Register::R6 => RAM_OFFSET_R6, - Register::R7 => RAM_OFFSET_R7, - } - } +#[derive(Debug, Clone, Copy)] +enum IncompleteOperand { + Acc, + Direct, + Data, + Indirect(Register), + Register(Register), + Reladdr, + Addr11(u8), + Addr16, } #[derive(Debug, Clone)] @@ -40,14 +49,28 @@ pub enum Operand { Addr16(u16), } +#[derive(Debug, Clone, Copy)] +struct IncompleteOp { + opname: Opname, + size: usize, + operand1: Option<IncompleteOperand>, + operand2: Option<IncompleteOperand>, +} + #[derive(Debug, Clone)] pub struct Op { - opcode: Isa8051Opcode, + opname: Opname, size: usize, operand1: Option<Operand>, operand2: Option<Operand>, } +pub struct Core { + pc: u16, + ram: [u8; u8::max_value() as usize + 1], + rom: Rom, +} + const RAM_OFFSET_ACC: u8 = 0xE0; const RAM_OFFSET_R0: u8 = 0x00; const RAM_OFFSET_R1: u8 = 0x01; @@ -85,202 +108,184 @@ const OPCODE_MOV_A_R7: u8 = 0xEF; const OPCODE_PUSH: u8 = 0xC0; const OPCODE_POP: u8 = 0xD0; -const OP_LUT: [Isa8051Op; u8::max_value() as usize + 1] = { - let mut lut = [Isa8051Op { - opcode: Isa8051Opcode::Illegal, +const OP_LUT: [IncompleteOp; u8::max_value() as usize + 1] = { + let mut lut = [IncompleteOp { + opname: Opname::Illegal, size: 1, operand1: None, operand2: None, }; u8::max_value() as usize + 1]; - lut[OPCODE_NOP as usize] = Isa8051Op { - opcode: Isa8051Opcode::Nop, + lut[OPCODE_NOP as usize] = IncompleteOp { + opname: Opname::Nop, size: 1, operand1: None, operand2: None, }; - lut[OPCODE_AJMP_P0 as usize] = Isa8051Op { - opcode: Isa8051Opcode::Ajmp, + lut[OPCODE_AJMP_P0 as usize] = IncompleteOp { + opname: Opname::Ajmp, size: 2, - operand1: Some(Isa8051Operand::Addr11(0)), + operand1: Some(IncompleteOperand::Addr11(0)), operand2: None, }; - lut[OPCODE_LJMP as usize] = Isa8051Op { - opcode: Isa8051Opcode::Ljmp, + lut[OPCODE_LJMP as usize] = IncompleteOp { + opname: Opname::Ljmp, size: 3, - operand1: Some(Isa8051Operand::Addr16), + operand1: Some(IncompleteOperand::Addr16), operand2: None, }; - lut[OPCODE_AJMP_P1 as usize] = Isa8051Op { - opcode: Isa8051Opcode::Ajmp, + lut[OPCODE_AJMP_P1 as usize] = IncompleteOp { + opname: Opname::Ajmp, size: 2, - operand1: Some(Isa8051Operand::Addr11(1)), + operand1: Some(IncompleteOperand::Addr11(1)), operand2: None, }; - lut[OPCODE_AJMP_P2 as usize] = Isa8051Op { - opcode: Isa8051Opcode::Ajmp, + lut[OPCODE_AJMP_P2 as usize] = IncompleteOp { + opname: Opname::Ajmp, size: 2, - operand1: Some(Isa8051Operand::Addr11(2)), + operand1: Some(IncompleteOperand::Addr11(2)), operand2: None, }; - lut[OPCODE_AJMP_P3 as usize] = Isa8051Op { - opcode: Isa8051Opcode::Ajmp, + lut[OPCODE_AJMP_P3 as usize] = IncompleteOp { + opname: Opname::Ajmp, size: 2, - operand1: Some(Isa8051Operand::Addr11(3)), + operand1: Some(IncompleteOperand::Addr11(3)), operand2: None, }; - lut[OPCODE_MOV_A_DATA as usize] = Isa8051Op { - opcode: Isa8051Opcode::Mov, + lut[OPCODE_MOV_A_DATA as usize] = IncompleteOp { + opname: Opname::Mov, size: 2, - operand1: Some(Isa8051Operand::Acc), - operand2: Some(Isa8051Operand::Data), + operand1: Some(IncompleteOperand::Acc), + operand2: Some(IncompleteOperand::Data), }; - lut[OPCODE_MOV_DIRECT_DATA as usize] = Isa8051Op { - opcode: Isa8051Opcode::Mov, + lut[OPCODE_MOV_DIRECT_DATA as usize] = IncompleteOp { + opname: Opname::Mov, size: 3, - operand1: Some(Isa8051Operand::Direct), - operand2: Some(Isa8051Operand::Data), + operand1: Some(IncompleteOperand::Direct), + operand2: Some(IncompleteOperand::Data), }; - lut[OPCODE_SJMP as usize] = Isa8051Op { - opcode: Isa8051Opcode::Sjmp, + lut[OPCODE_SJMP as usize] = IncompleteOp { + opname: Opname::Sjmp, size: 2, - operand1: Some(Isa8051Operand::Reladdr), + operand1: Some(IncompleteOperand::Reladdr), operand2: None, }; - lut[OPCODE_AJMP_P4 as usize] = Isa8051Op { - opcode: Isa8051Opcode::Ajmp, + lut[OPCODE_AJMP_P4 as usize] = IncompleteOp { + opname: Opname::Ajmp, size: 2, - operand1: Some(Isa8051Operand::Addr11(4)), + operand1: Some(IncompleteOperand::Addr11(4)), operand2: None, }; - lut[OPCODE_AJMP_P5 as usize] = Isa8051Op { - opcode: Isa8051Opcode::Ajmp, + lut[OPCODE_AJMP_P5 as usize] = IncompleteOp { + opname: Opname::Ajmp, size: 2, - operand1: Some(Isa8051Operand::Addr11(5)), + operand1: Some(IncompleteOperand::Addr11(5)), operand2: None, }; - lut[OPCODE_AJMP_P6 as usize] = Isa8051Op { - opcode: Isa8051Opcode::Ajmp, + lut[OPCODE_AJMP_P6 as usize] = IncompleteOp { + opname: Opname::Ajmp, size: 2, - operand1: Some(Isa8051Operand::Addr11(6)), + operand1: Some(IncompleteOperand::Addr11(6)), operand2: None, }; - lut[OPCODE_AJMP_P7 as usize] = Isa8051Op { - opcode: Isa8051Opcode::Ajmp, + lut[OPCODE_AJMP_P7 as usize] = IncompleteOp { + opname: Opname::Ajmp, size: 2, - operand1: Some(Isa8051Operand::Addr11(7)), + operand1: Some(IncompleteOperand::Addr11(7)), operand2: None, }; - lut[OPCODE_MOV_A_DIRECT as usize] = Isa8051Op { - opcode: Isa8051Opcode::Mov, + lut[OPCODE_MOV_A_DIRECT as usize] = IncompleteOp { + opname: Opname::Mov, size: 2, - operand1: Some(Isa8051Operand::Acc), - operand2: Some(Isa8051Operand::Direct), + operand1: Some(IncompleteOperand::Acc), + operand2: Some(IncompleteOperand::Direct), }; - lut[OPCODE_MOV_A_INDIRECT_R0 as usize] = Isa8051Op { - opcode: Isa8051Opcode::Mov, + lut[OPCODE_MOV_A_INDIRECT_R0 as usize] = IncompleteOp { + opname: Opname::Mov, size: 1, - operand1: Some(Isa8051Operand::Acc), - operand2: Some(Isa8051Operand::Indirect(Register::R0)), + operand1: Some(IncompleteOperand::Acc), + operand2: Some(IncompleteOperand::Indirect(Register::R0)), }; - lut[OPCODE_MOV_A_INDIRECT_R1 as usize] = Isa8051Op { - opcode: Isa8051Opcode::Mov, + lut[OPCODE_MOV_A_INDIRECT_R1 as usize] = IncompleteOp { + opname: Opname::Mov, size: 1, - operand1: Some(Isa8051Operand::Acc), - operand2: Some(Isa8051Operand::Indirect(Register::R1)), + operand1: Some(IncompleteOperand::Acc), + operand2: Some(IncompleteOperand::Indirect(Register::R1)), }; - lut[OPCODE_MOV_A_R0 as usize] = Isa8051Op { - opcode: Isa8051Opcode::Mov, + lut[OPCODE_MOV_A_R0 as usize] = IncompleteOp { + opname: Opname::Mov, size: 1, - operand1: Some(Isa8051Operand::Acc), - operand2: Some(Isa8051Operand::Register(Register::R0)), + operand1: Some(IncompleteOperand::Acc), + operand2: Some(IncompleteOperand::Register(Register::R0)), }; - lut[OPCODE_MOV_A_R1 as usize] = Isa8051Op { - opcode: Isa8051Opcode::Mov, + lut[OPCODE_MOV_A_R1 as usize] = IncompleteOp { + opname: Opname::Mov, size: 1, - operand1: Some(Isa8051Operand::Acc), - operand2: Some(Isa8051Operand::Register(Register::R1)), + operand1: Some(IncompleteOperand::Acc), + operand2: Some(IncompleteOperand::Register(Register::R1)), }; - lut[OPCODE_MOV_A_R2 as usize] = Isa8051Op { - opcode: Isa8051Opcode::Mov, + lut[OPCODE_MOV_A_R2 as usize] = IncompleteOp { + opname: Opname::Mov, size: 1, - operand1: Some(Isa8051Operand::Acc), - operand2: Some(Isa8051Operand::Register(Register::R2)), + operand1: Some(IncompleteOperand::Acc), + operand2: Some(IncompleteOperand::Register(Register::R2)), }; - lut[OPCODE_MOV_A_R3 as usize] = Isa8051Op { - opcode: Isa8051Opcode::Mov, + lut[OPCODE_MOV_A_R3 as usize] = IncompleteOp { + opname: Opname::Mov, size: 1, - operand1: Some(Isa8051Operand::Acc), - operand2: Some(Isa8051Operand::Register(Register::R3)), + operand1: Some(IncompleteOperand::Acc), + operand2: Some(IncompleteOperand::Register(Register::R3)), }; - lut[OPCODE_MOV_A_R4 as usize] = Isa8051Op { - opcode: Isa8051Opcode::Mov, + lut[OPCODE_MOV_A_R4 as usize] = IncompleteOp { + opname: Opname::Mov, size: 1, - operand1: Some(Isa8051Operand::Acc), - operand2: Some(Isa8051Operand::Register(Register::R4)), + operand1: Some(IncompleteOperand::Acc), + operand2: Some(IncompleteOperand::Register(Register::R4)), }; - lut[OPCODE_MOV_A_R5 as usize] = Isa8051Op { - opcode: Isa8051Opcode::Mov, + lut[OPCODE_MOV_A_R5 as usize] = IncompleteOp { + opname: Opname::Mov, size: 1, - operand1: Some(Isa8051Operand::Acc), - operand2: Some(Isa8051Operand::Register(Register::R5)), + operand1: Some(IncompleteOperand::Acc), + operand2: Some(IncompleteOperand::Register(Register::R5)), }; - lut[OPCODE_MOV_A_R6 as usize] = Isa8051Op { - opcode: Isa8051Opcode::Mov, + lut[OPCODE_MOV_A_R6 as usize] = IncompleteOp { + opname: Opname::Mov, size: 1, - operand1: Some(Isa8051Operand::Acc), - operand2: Some(Isa8051Operand::Register(Register::R6)), + operand1: Some(IncompleteOperand::Acc), + operand2: Some(IncompleteOperand::Register(Register::R6)), }; - lut[OPCODE_MOV_A_R7 as usize] = Isa8051Op { - opcode: Isa8051Opcode::Mov, + lut[OPCODE_MOV_A_R7 as usize] = IncompleteOp { + opname: Opname::Mov, size: 1, - operand1: Some(Isa8051Operand::Acc), - operand2: Some(Isa8051Operand::Register(Register::R7)), + operand1: Some(IncompleteOperand::Acc), + operand2: Some(IncompleteOperand::Register(Register::R7)), }; - lut[OPCODE_PUSH as usize] = Isa8051Op { - opcode: Isa8051Opcode::Push, + lut[OPCODE_PUSH as usize] = IncompleteOp { + opname: Opname::Push, size: 2, - operand1: Some(Isa8051Operand::Direct), + operand1: Some(IncompleteOperand::Direct), operand2: None, }; - lut[OPCODE_POP as usize] = Isa8051Op { - opcode: Isa8051Opcode::Pop, + lut[OPCODE_POP as usize] = IncompleteOp { + opname: Opname::Pop, size: 2, - operand1: Some(Isa8051Operand::Direct), + operand1: Some(IncompleteOperand::Direct), operand2: None, }; lut }; -impl fmt::Display for Operand { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "{}", - match self { - Operand::Acc => "A".to_string(), - Operand::Direct(dir) => format!("{:x}h", dir), - Operand::Indirect(r) => format!("@{:?}", r), - Operand::Data(data) => format!("#{}", data), - Operand::Register(r) => format!("{:?}", r), - Operand::Reladdr(rel) => format!("{}", rel), - Operand::Addr11(rel) => format!("{}", rel), - Operand::Addr16(rel) => format!("{}", rel), - } - ) - } -} - -impl fmt::Display for Op { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut output = String::new(); - output.push_str(&format!("{} ", self.opcode)); - if let Some(op1) = &self.operand1 { - output.push_str(&format!("{}", op1)); - } - if let Some(op2) = &self.operand2 { - output.push_str(&format!(",{}", op2)); +impl Register { + fn to_ram_offset(&self) -> u8 { + match self { + Register::R0 => RAM_OFFSET_R0, + Register::R1 => RAM_OFFSET_R1, + Register::R2 => RAM_OFFSET_R2, + Register::R3 => RAM_OFFSET_R3, + Register::R4 => RAM_OFFSET_R4, + Register::R5 => RAM_OFFSET_R5, + Register::R6 => RAM_OFFSET_R6, + Register::R7 => RAM_OFFSET_R7, } - write!(f, "{}", output) } } @@ -299,16 +304,14 @@ impl Operand { } } -pub struct Core { - pc: u16, - ram: [u8; u8::max_value() as usize + 1], - rom: Rom, +impl IncompleteOp { + fn from_u8(data: u8) -> Self { + OP_LUT[data as usize] + } } 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 rom = match Rom::from_hex(hex) { @@ -318,22 +321,18 @@ impl Core { Ok(Self { pc: 0, ram, rom }) } - /// /// Fetch and execute one instruction - /// pub fn step(&mut self) -> u16 { let op = self.fetch(); self.exec(op); self.pc } - /// /// Get current instruction - /// pub fn op(&self) -> Op { - let op = Isa8051Op::from_u8(self.rom.array[self.pc as usize]); - let operand1 = if let Some(operand) = op.operand1 { - Some(self.map_operand(operand, 1)) + let op = IncompleteOp::from_u8(self.rom.array[self.pc as usize]); + let operand1 = if let Some(incomplete_operand) = op.operand1 { + Some(self.fetch_operand(incomplete_operand, 1)) } else { None }; @@ -341,40 +340,35 @@ impl Core { Some(o) => o.size(), _ => 0, }; - let operand2 = if let Some(operand) = op.operand2 { - Some(self.map_operand(operand, operand2_offset)) + let operand2 = if let Some(incomplete_operand) = op.operand2 { + Some(self.fetch_operand(incomplete_operand, operand2_offset)) } else { None }; Op { - opcode: op.opcode, + opname: op.opname, size: op.size, operand1, operand2, } } - /// - /// Increment PC - /// Return the whole operation - /// + /// Increment PC, return the whole operation fn fetch(&mut self) -> Op { let op = self.op(); self.pc += op.size as u16; op } - /// /// Execute one instruction without incrementing PC - /// fn exec(&mut self, op: Op) { - match op.opcode { - Isa8051Opcode::Nop => (), - Isa8051Opcode::Mov => (self.mov(op.operand1.unwrap(), op.operand2.unwrap())), - Isa8051Opcode::Illegal => (), - Isa8051Opcode::Push => (), - Isa8051Opcode::Pop => (), - Isa8051Opcode::Sjmp => { + match op.opname { + Opname::Nop => (), + Opname::Mov => (self.mov(op.operand1.unwrap(), op.operand2.unwrap())), + Opname::Illegal => (), + Opname::Push => (), + Opname::Pop => (), + Opname::Sjmp => { if let Some(operand) = op.operand1 { match operand { Operand::Reladdr(reladdr) => self.sjmp(reladdr), @@ -384,7 +378,7 @@ impl Core { panic!("SJMP has no operand given") } } - Isa8051Opcode::Ajmp => { + Opname::Ajmp => { if let Some(operand) = op.operand1 { match operand { Operand::Addr11(addr) => self.ajmp(addr), @@ -394,7 +388,7 @@ impl Core { panic!("AJMP has no operand given") } } - Isa8051Opcode::Ljmp => { + Opname::Ljmp => { if let Some(operand) = op.operand1 { match operand { Operand::Addr16(addr) => self.ljmp(addr), @@ -407,6 +401,29 @@ impl Core { } } + /// Get operand by offset, based on meta information + fn fetch_operand(&self, operand: IncompleteOperand, offset: usize) -> Operand { + match operand { + IncompleteOperand::Acc => Operand::Acc, + IncompleteOperand::Direct => { + Operand::Direct(self.rom.array[(self.pc as usize + offset)]) + } + IncompleteOperand::Data => Operand::Data(self.rom.array[(self.pc as usize + offset)]), + IncompleteOperand::Indirect(r) => Operand::Indirect(r), + IncompleteOperand::Register(r) => Operand::Register(r), + IncompleteOperand::Reladdr => { + Operand::Reladdr(self.rom.array[(self.pc as usize + offset)] as i8) + } + IncompleteOperand::Addr11(high) => Operand::Addr11( + self.rom.array[(self.pc as usize + offset)] as u16 + (u16::from(high) << 8), + ), + IncompleteOperand::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)]), + ), + } + } + fn mov(&mut self, o1: Operand, o2: Operand) { let dest = match o1 { Operand::Acc => RAM_OFFSET_ACC, @@ -437,68 +454,43 @@ impl Core { fn ljmp(&mut self, pageaddr: u16) { self.pc = pageaddr; } +} - fn map_operand(&self, operand: Isa8051Operand, offset: usize) -> Operand { - match operand { - Isa8051Operand::Acc => Operand::Acc, - Isa8051Operand::Direct => Operand::Direct(self.rom.array[(self.pc as usize + offset)]), - Isa8051Operand::Data => Operand::Data(self.rom.array[(self.pc as usize + offset)]), - Isa8051Operand::Indirect(r) => Operand::Indirect(r), - Isa8051Operand::Register(r) => Operand::Register(r), - Isa8051Operand::Reladdr => { - Operand::Reladdr(self.rom.array[(self.pc as usize + offset)] as i8) +impl fmt::Display for Operand { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{}", + match self { + Operand::Acc => "A".to_string(), + Operand::Direct(dir) => format!("{:x}h", dir), + Operand::Indirect(r) => format!("@{:?}", r), + Operand::Data(data) => format!("#{}", data), + Operand::Register(r) => format!("{:?}", r), + Operand::Reladdr(rel) => format!("{}", rel), + Operand::Addr11(rel) => format!("{}", rel), + Operand::Addr16(rel) => format!("{}", rel), } - 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)]), - ), - } + ) } } -#[derive(Debug, Clone, Copy)] -pub enum Isa8051Operand { - Acc, - Direct, - Data, - Indirect(Register), - Register(Register), - Reladdr, - Addr11(u8), - Addr16, -} - -#[derive(Debug, Clone, Copy)] -pub enum Isa8051Opcode { - Nop, - Ajmp, - Ljmp, - Mov, - Push, - Pop, - Illegal, - Sjmp, -} - -impl fmt::Display for Isa8051Opcode { +impl fmt::Display for Op { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:?}", self) + let mut output = String::new(); + output.push_str(&format!("{} ", self.opname)); + if let Some(op1) = &self.operand1 { + output.push_str(&format!("{}", op1)); + } + if let Some(op2) = &self.operand2 { + output.push_str(&format!(",{}", op2)); + } + write!(f, "{}", output) } } -#[derive(Debug, Clone, Copy)] -pub struct Isa8051Op { - opcode: Isa8051Opcode, - size: usize, - operand1: Option<Isa8051Operand>, - operand2: Option<Isa8051Operand>, -} - -impl Isa8051Op { - fn from_u8(data: u8) -> Self { - OP_LUT[data as usize] +impl fmt::Display for Opname { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?}", self) } } |