From 59e2c93bb5fd4301a7653c568419376374c2c33a Mon Sep 17 00:00:00 2001 From: Oxore Date: Mon, 11 Nov 2019 01:43:23 +0300 Subject: Add ram and rom, implement basic MOV functionality --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/core.rs | 66 ++++++++++++++++++++++++++++++++------ src/main.rs | 8 ++--- src/ram.rs | 105 ------------------------------------------------------------ src/rom.rs | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 166 insertions(+), 122 deletions(-) delete mode 100644 src/ram.rs create mode 100644 src/rom.rs diff --git a/Cargo.lock b/Cargo.lock index f9daf50..2a26673 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "smemu" +name = "x51emu" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 962e040..a2942d8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "smemu" +name = "x51emu" version = "0.1.0" authors = ["Oxore "] edition = "2018" diff --git a/src/core.rs b/src/core.rs index 64f65fb..cd9dc1d 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,4 +1,4 @@ -use crate::ram::Ram; +use crate::rom::Rom; use std::fmt; #[derive(Debug, Clone)] @@ -13,6 +13,21 @@ 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)] pub enum Operand { Acc, @@ -31,6 +46,16 @@ pub struct Op { operand2: Option, } +const RAM_OFFSET_ACC: u8 = 0xE0; +const RAM_OFFSET_R0: u8 = 0x00; +const RAM_OFFSET_R1: u8 = 0x01; +const RAM_OFFSET_R2: u8 = 0x02; +const RAM_OFFSET_R3: u8 = 0x03; +const RAM_OFFSET_R4: u8 = 0x04; +const RAM_OFFSET_R5: u8 = 0x05; +const RAM_OFFSET_R6: u8 = 0x06; +const RAM_OFFSET_R7: u8 = 0x07; + const OPCODE_NOP: u8 = 0x00; const OPCODE_MOV_A_DATA: u8 = 0x74; const OPCODE_MOV_DIRECT_DATA: u8 = 0x75; @@ -95,19 +120,21 @@ impl Operand { pub struct Core { pc: u16, - ram: Ram, + ram: [u8; u8::max_value() as usize], + rom: Rom, } impl Core { /// /// Constructor /// - pub fn new_with_ram_from_hex(hex: String) -> Result { - let ram = match Ram::from_hex(hex) { + pub fn new_with_rom_from_hex(hex: String) -> Result { + let ram: [u8; u8::max_value() as usize] = [0; u8::max_value() as usize]; + let rom = match Rom::from_hex(hex) { Ok(value) => value, Err(err_string) => return Err(err_string), }; - Ok(Self { pc: 0, ram }) + Ok(Self { pc: 0, ram, rom }) } /// @@ -123,7 +150,7 @@ impl Core { /// Get current instruction /// pub fn op(&self) -> Op { - let op = Isa8051Op::from_u8(self.ram.array[self.pc as usize]); + 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)) } else { @@ -162,7 +189,7 @@ impl Core { fn exec(&mut self, op: Op) { match op.opcode { Isa8051Opcode::Nop => (), - Isa8051Opcode::Mov => (), + Isa8051Opcode::Mov => (self.mov(op.operand1.unwrap(), op.operand2.unwrap())), Isa8051Opcode::Illegal => (), Isa8051Opcode::Push => (), Isa8051Opcode::Pop => (), @@ -179,6 +206,25 @@ impl Core { } } + fn mov(&mut self, o1: Operand, o2: Operand) { + 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::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::Data(r) => r, + Operand::Register(r) => r.to_ram_offset(), + other => panic!("Mov: got incompatible second operand \"{:?}\"", other), + }; + self.ram[dest as usize] = value; + } + fn sjmp(&mut self, reladdr: i8) { self.pc = (self.pc as i16 + i16::from(reladdr)) as u16; } @@ -186,12 +232,12 @@ impl Core { fn map_operand(&self, operand: Isa8051Operand, offset: usize) -> Operand { match operand { Isa8051Operand::Acc => Operand::Acc, - Isa8051Operand::Direct => Operand::Direct(self.ram.array[(self.pc as usize + offset)]), - Isa8051Operand::Data => Operand::Data(self.ram.array[(self.pc as usize + offset)]), + 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.ram.array[(self.pc as usize + offset)] as i8) + Operand::Reladdr(self.rom.array[(self.pc as usize + offset)] as i8) } } } diff --git a/src/main.rs b/src/main.rs index 358ac4e..dc2f600 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,14 +7,14 @@ use std::thread::sleep; use std::{thread, time}; mod core; -mod ram; +mod rom; use self::core::Core; fn core_worker(mut core: Core, should_stop: &Mutex, cvar: &Condvar) { loop { while !(*should_stop.lock().unwrap()) { - core.step(); println!("{}", core.op()); + core.step(); sleep(time::Duration::from_millis(1000)); } @@ -55,7 +55,7 @@ fn main() { let asyncpair = Arc::new((Mutex::new(false), Condvar::new())); let asyncpair2 = asyncpair.clone(); - let core = match Core::new_with_ram_from_hex(data) { + let core = match Core::new_with_rom_from_hex(data) { Ok(value) => value, Err(err_string) => { println!("{}", err_string); @@ -63,8 +63,6 @@ fn main() { } }; - println!("{}", core.op()); - thread::spawn(move || { let (ref should_stop, ref condvar) = *asyncpair2; core_worker(core, should_stop, condvar); diff --git a/src/ram.rs b/src/ram.rs deleted file mode 100644 index c9a0641..0000000 --- a/src/ram.rs +++ /dev/null @@ -1,105 +0,0 @@ -use std::fmt; - -pub struct Ram { - pub array: [u8; u16::max_value() as usize + 1], -} - -impl fmt::Debug for Ram { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut v: Vec = 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::()) - } -} - -enum Rectyp { - Data, - EndOfFile, - //ExtendedSegAddr, - //StartSegAddr, - //ExtendedLinearAddr, - //StartLinearAddr, -} - -struct HexLine { - rectyp: Rectyp, - offset: u16, - data: Vec, -} - -impl HexLine { - fn from(s: &str) -> Result { - // The shortest possible sequence is EOF (:00000001FF) - if s.len() < 11 { - return Err(usize::max_value()); - } - if &s[0..1] != ":" { - return Err(0); - } - let offset = match u16::from_str_radix(&s[3..7], 16) { - Ok(value) => value, - Err(_) => return Err(3), - }; - let bytecount = match usize::from_str_radix(&s[1..3], 16) { - Ok(value) => value, - Err(_) => return Err(1), - }; - - // If EOF reached - if &s[7..9] == "01" { - return Ok(HexLine { - rectyp: Rectyp::EndOfFile, - offset, - data: vec![0], - }); - } else if &s[7..9] == "00" { - let mut counter = 9; - let mut data = vec![]; - while counter < s.len() - 2 && counter < (9 + bytecount * 2) { - data.push(match u8::from_str_radix(&s[counter..counter + 2], 16) { - Ok(value) => value, - Err(_) => return Err(counter), - }); - counter += 2; - } - // TODO: check checksum - return Ok(HexLine { - rectyp: Rectyp::Data, - offset, - data, - }); - } - - Err(3) - } -} - -impl Ram { - pub fn from_hex(hex: String) -> Result { - let mut array = [0; u16::max_value() as usize + 1]; - for (linenum, line) in hex.lines().enumerate() { - let hex_line = match HexLine::from(line) { - Ok(value) => value, - Err(charnum) => return Err(format!("ihex parsing error {}:{}", linenum, charnum)), - }; - let offset = hex_line.offset; - match hex_line.rectyp { - Rectyp::Data => { - for (ptr, byte) in hex_line.data.iter().enumerate() { - array[ptr + offset as usize] = *byte; - } - } - Rectyp::EndOfFile => {} - } - } - Ok(Self { array }) - } -} diff --git a/src/rom.rs b/src/rom.rs new file mode 100644 index 0000000..77e6431 --- /dev/null +++ b/src/rom.rs @@ -0,0 +1,105 @@ +use std::fmt; + +pub struct Rom { + pub array: [u8; u16::max_value() as usize + 1], +} + +impl fmt::Debug for Rom { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut v: Vec = 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::()) + } +} + +enum Rectyp { + Data, + EndOfFile, + //ExtendedSegAddr, + //StartSegAddr, + //ExtendedLinearAddr, + //StartLinearAddr, +} + +struct HexLine { + rectyp: Rectyp, + offset: u16, + data: Vec, +} + +impl HexLine { + fn from(s: &str) -> Result { + // The shortest possible sequence is EOF (:00000001FF) + if s.len() < 11 { + return Err(usize::max_value()); + } + if &s[0..1] != ":" { + return Err(0); + } + let offset = match u16::from_str_radix(&s[3..7], 16) { + Ok(value) => value, + Err(_) => return Err(3), + }; + let bytecount = match usize::from_str_radix(&s[1..3], 16) { + Ok(value) => value, + Err(_) => return Err(1), + }; + + // If EOF reached + if &s[7..9] == "01" { + return Ok(HexLine { + rectyp: Rectyp::EndOfFile, + offset, + data: vec![0], + }); + } else if &s[7..9] == "00" { + let mut counter = 9; + let mut data = vec![]; + while counter < s.len() - 2 && counter < (9 + bytecount * 2) { + data.push(match u8::from_str_radix(&s[counter..counter + 2], 16) { + Ok(value) => value, + Err(_) => return Err(counter), + }); + counter += 2; + } + // TODO: check checksum + return Ok(HexLine { + rectyp: Rectyp::Data, + offset, + data, + }); + } + + Err(3) + } +} + +impl Rom { + pub fn from_hex(hex: String) -> Result { + let mut array = [0; u16::max_value() as usize + 1]; + for (linenum, line) in hex.lines().enumerate() { + let hex_line = match HexLine::from(line) { + Ok(value) => value, + Err(charnum) => return Err(format!("ihex parsing error {}:{}", linenum, charnum)), + }; + let offset = hex_line.offset; + match hex_line.rectyp { + Rectyp::Data => { + for (ptr, byte) in hex_line.data.iter().enumerate() { + array[ptr + offset as usize] = *byte; + } + } + Rectyp::EndOfFile => {} + } + } + Ok(Self { array }) + } +} -- cgit v1.2.3