From ac347f3613b78c4dac0bf98e62a738b50e68db15 Mon Sep 17 00:00:00 2001 From: pjht Date: Thu, 12 Oct 2023 13:11:38 -0500 Subject: [PATCH] Work --- Cargo.lock | 7 + Cargo.toml | 1 + src/card.rs | 8 +- src/cpu.rs | 496 +++++++++++++++++++++++++++++++--------- src/cpu/opcode.rs | 6 +- src/cpu/opcode_table.rs | 4 +- src/main.rs | 66 ++++-- src/ram.rs | 7 +- 8 files changed, 458 insertions(+), 137 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c0bafdb..fdf146b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -135,6 +135,7 @@ dependencies = [ "ron", "serde", "soloud", + "ux", ] [[package]] @@ -2632,6 +2633,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "ux" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cb3ff47e36907a6267572c1e398ff32ef78ac5131de8aa272e53846592c207e" + [[package]] name = "vec_map" version = "0.8.2" diff --git a/Cargo.toml b/Cargo.toml index dbb2aef..0fd20d8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,3 +19,4 @@ rand = "0.8.5" ron = "0.8.0" serde = { version = "1.0.171", features = ["derive"] } soloud = "1.0.2" +ux = "0.1.5" diff --git a/src/card.rs b/src/card.rs index 89db6a1..ef99dd0 100644 --- a/src/card.rs +++ b/src/card.rs @@ -1,14 +1,12 @@ +use crate::ram::RamCard; use eframe::egui; use enum_dispatch::enum_dispatch; -use crate::ram::RamCard; #[enum_dispatch(CardEnum)] pub enum CardEnum { - RamCard + RamCard, } - - #[enum_dispatch] pub trait Card { fn new(_settings: ron::Value) -> CardEnum; @@ -28,5 +26,3 @@ pub trait Card { fn draw_settings_ui(&mut self, _ui: egui::Ui) {} fn serialize_settings(&self) -> String; } - - diff --git a/src/cpu.rs b/src/cpu.rs index be10b2f..6c172ca 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -8,8 +8,9 @@ use std::{ use bitflags::bitflags; use opcode_table::OPCODE_TABLE; +use ux::{u4, u5}; -use self::opcode::{Opcode, Register, RegisterPair}; +use self::opcode::{Condition, Opcode, Register, RegisterPair}; bitflags! { #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -188,6 +189,7 @@ pub struct I8080 { z: u8, tmp: u8, halted: bool, + inte: bool, } impl Display for I8080 { @@ -224,12 +226,14 @@ impl I8080 { z: rand::random(), tmp: rand::random(), halted: rand::random(), + inte: rand::random(), } } pub fn reset(&mut self) { self.pc = 0; self.halted = false; + self.inte = false; } pub fn get_mem_cycle(&self) -> MemCycle { @@ -250,7 +254,7 @@ impl I8080 { Opcode::Lhld => MemCycle::Read(self.pc), Opcode::Shld => MemCycle::Read(self.pc), Opcode::Ldax(rp) => MemCycle::Read(self.get_pair(rp)), - Opcode::Stax(rp) => MemCycle::Read(self.get_pair(rp)), + Opcode::Stax(rp) => MemCycle::Write(self.get_pair(rp), self.regs.a), Opcode::Add(_) => MemCycle::Read(self.get_pair(RegisterPair::HL)), Opcode::Adi => MemCycle::Read(self.pc), Opcode::Adc(_) => MemCycle::Read(self.get_pair(RegisterPair::HL)), @@ -259,8 +263,8 @@ impl I8080 { Opcode::Sui => MemCycle::Read(self.pc), Opcode::Sbb(_) => MemCycle::Read(self.get_pair(RegisterPair::HL)), Opcode::Sbi => MemCycle::Read(self.pc), - Opcode::Inr(_) => MemCycle::Read(self.get_pair(RegisterPair::HL)), - Opcode::Dcr(_) => MemCycle::Read(self.get_pair(RegisterPair::HL)), + Opcode::InrM => MemCycle::Read(self.get_pair(RegisterPair::HL)), + Opcode::DcrM => MemCycle::Read(self.get_pair(RegisterPair::HL)), Opcode::Ana(_) => MemCycle::Read(self.get_pair(RegisterPair::HL)), Opcode::Ani => MemCycle::Read(self.pc), Opcode::Xra(_) => MemCycle::Read(self.get_pair(RegisterPair::HL)), @@ -270,14 +274,13 @@ impl I8080 { Opcode::Cmp(_) => MemCycle::Read(self.get_pair(RegisterPair::HL)), Opcode::Cpi => MemCycle::Read(self.pc), Opcode::Jmp => MemCycle::Read(self.pc), - Opcode::Jcc(_) => MemCycle::Read(self.pc), Opcode::Call => MemCycle::Read(self.pc), - Opcode::Ccc(_) => MemCycle::Read(self.pc), Opcode::Ret => MemCycle::Read(self.sp), - Opcode::Rcc(_) => MemCycle::StackRead(self.sp), Opcode::Rst(_) => MemCycle::StackWrite(self.sp, (self.pc >> 8) as u8), - Opcode::Push(_) => MemCycle::StackRead(self.sp), + Opcode::Push(rp) => MemCycle::StackWrite(self.sp, (self.get_pair(rp) >> 8) as u8), + Opcode::PushPsw => MemCycle::StackWrite(self.sp, self.regs.a), Opcode::Pop(_) => MemCycle::StackRead(self.sp), + Opcode::PopPsw => MemCycle::StackRead(self.sp), Opcode::Xthl => MemCycle::StackRead(self.sp), Opcode::In => MemCycle::Read(self.pc), Opcode::Out => MemCycle::Read(self.pc), @@ -290,15 +293,16 @@ impl I8080 { Opcode::Sta => MemCycle::Read(self.pc), Opcode::Lhld => MemCycle::Read(self.pc), Opcode::Shld => MemCycle::Read(self.pc), - Opcode::Inr(_) => MemCycle::Write(self.get_pair(RegisterPair::HL), self.tmp), - Opcode::Dcr(_) => MemCycle::Write(self.get_pair(RegisterPair::HL), self.tmp), + Opcode::InrM => MemCycle::Write(self.get_pair(RegisterPair::HL), self.tmp), + Opcode::DcrM => MemCycle::Write(self.get_pair(RegisterPair::HL), self.tmp), Opcode::Jmp => MemCycle::Read(self.pc), - Opcode::Jcc(_) => MemCycle::Read(self.pc), Opcode::Call => MemCycle::Read(self.pc), - Opcode::Ccc(_) => MemCycle::Read(self.pc), Opcode::Ret => MemCycle::StackRead(self.sp), - Opcode::Rcc(_) => MemCycle::StackRead(self.sp), Opcode::Rst(_) => MemCycle::StackWrite(self.sp, 0), + Opcode::Push(rp) => MemCycle::StackWrite(self.sp, self.get_pair(rp) as u8), + Opcode::PushPsw => MemCycle::StackWrite(self.sp, self.get_flags()), + Opcode::Pop(_) => MemCycle::StackRead(self.sp), + Opcode::PopPsw => MemCycle::StackRead(self.sp), Opcode::Xthl => MemCycle::StackRead(self.sp), Opcode::In => MemCycle::In(self.get_wz()), Opcode::Out => MemCycle::Out(self.get_wz(), self.regs.a), @@ -310,7 +314,6 @@ impl I8080 { Opcode::Lhld => MemCycle::Read(self.get_wz()), Opcode::Shld => MemCycle::Write(self.get_wz(), self.regs.l), Opcode::Call => MemCycle::StackWrite(self.sp, (self.pc >> 8) as u8), - Opcode::Ccc(_) => MemCycle::StackWrite(self.sp, (self.pc >> 8) as u8), Opcode::Xthl => MemCycle::StackWrite(self.sp, self.regs.h), _ => unreachable!(), }, @@ -335,6 +338,7 @@ impl I8080 { self.get_mem_cycle(), data ); + let mut cond_failed = false; match self.cycle { MCycle::M1 => { self.pc += 1; @@ -351,7 +355,7 @@ impl I8080 { } Opcode::MviM => (), Opcode::Mvi(_) => (), - Opcode::Lxi(_) => (), + Opcode::Lxi(_) => {} Opcode::Lda => (), Opcode::Sta => (), Opcode::Lhld => (), @@ -364,30 +368,44 @@ impl I8080 { } Opcode::AddM => (), Opcode::Add(src) => { - let a = self.regs.a; - let b = self.regs[src]; - let res = (a as u16) + (b as u16); - self.sign = ((res as u8) & 0x80) > 0; - self.zero = (res as u8) == 0; - self.aux_carry = (a & 0x0f) + (b & 0x0f) > 0x0f; - self.parity = (res as u8).count_ones() % 2 == 0; - self.carry = res > 0xff; - self.regs.a = res as u8; + let (ac, cy, res) = Self::add_8bit(self.regs.a, self.regs[src]); + self.update_arith_flags(ac, cy, res); + self.regs.a = res; } Opcode::Adi => (), Opcode::AdcM => (), - Opcode::Adc(_) => todo!(), + Opcode::Adc(src) => { + let (ac, cy, res) = Self::adc_8bit(self.regs.a, self.regs[src], self.carry); + self.update_arith_flags(ac, cy, res); + self.regs.a = res; + } Opcode::Aci => (), Opcode::SubM => (), - Opcode::Sub(_) => todo!(), + Opcode::Sub(src) => { + let (ac, cy, res) = Self::sub_8bit(self.regs.a, self.regs[src]); + self.update_arith_flags(ac, cy, res); + self.regs.a = res; + } Opcode::Sui => (), Opcode::SbbM => (), - Opcode::Sbb(_) => todo!(), + Opcode::Sbb(src) => { + let (ac, cy, res) = Self::sbb_8bit(self.regs.a, self.regs[src], self.carry); + self.update_arith_flags(ac, cy, res); + self.regs.a = res; + } Opcode::Sbi => (), Opcode::InrM => (), - Opcode::Inr(_) => todo!(), + Opcode::Inr(src) => { + let (ac, _cy, res) = Self::add_8bit(self.regs[src], 1); + self.update_arith_flags(ac, self.carry, res); + self.regs[src] = res; + } Opcode::DcrM => (), - Opcode::Dcr(_) => todo!(), + Opcode::Dcr(src) => { + let (ac, _cy, res) = Self::sub_8bit(self.regs[src], 1); + self.update_arith_flags(ac, self.carry, res); + self.regs[src] = res; + } Opcode::Inx(dst) => self.set_pair(dst, self.get_pair(dst) + 1), Opcode::Dcx(dst) => self.set_pair(dst, self.get_pair(dst) + 2), Opcode::Dad(src) => { @@ -399,16 +417,28 @@ impl I8080 { } Opcode::Daa => todo!(), Opcode::AnaM => (), - Opcode::Ana(_) => todo!(), + Opcode::Ana(src) => { + self.regs.a &= self.regs[src]; + self.update_logic_flags(self.regs.a); + } Opcode::Ani => (), Opcode::XraM => (), - Opcode::Xra(_) => todo!(), + Opcode::Xra(src) => { + self.regs.a ^= self.regs[src]; + self.update_logic_flags(self.regs.a); + } Opcode::Xri => (), Opcode::OraM => (), - Opcode::Ora(_) => todo!(), + Opcode::Ora(src) => { + self.regs.a |= self.regs[src]; + self.update_logic_flags(self.regs.a); + } Opcode::Ori => (), Opcode::CmpM => (), - Opcode::Cmp(_) => todo!(), + Opcode::Cmp(src) => { + let (ac, cy, res) = Self::sub_8bit(self.regs.a, self.regs[src]); + self.update_arith_flags(ac, cy, res); + } Opcode::Cpi => (), Opcode::Rlc => todo!(), Opcode::Rrc => todo!(), @@ -418,20 +448,54 @@ impl I8080 { Opcode::Cmc => todo!(), Opcode::Stc => todo!(), Opcode::Jmp => (), - Opcode::Jcc(_) => todo!(), - Opcode::Call => todo!(), - Opcode::Ccc(_) => todo!(), + Opcode::Jcc(cc) => { + cond_failed = !self.check_cond(cc); + if cond_failed { + self.pc += 2; + } + self.opcode = Opcode::Jmp; // Identical after M1 + } + Opcode::Call => { + self.sp -= 1; + } + Opcode::Ccc(cc) => { + cond_failed = !self.check_cond(cc); + if cond_failed { + self.pc += 2; + } else { + self.sp -= 1; + } + self.opcode = Opcode::Call; // Identical after M1 + } Opcode::Ret => (), - Opcode::Rcc(_) => todo!(), - Opcode::Rst(_) => todo!(), - Opcode::Pchl => todo!(), - Opcode::Push(_) => todo!(), + Opcode::Rcc(cc) => { + cond_failed = !self.check_cond(cc); + self.opcode = Opcode::Ret; // Identical after M1 + } + Opcode::Rst(_) => { + self.w = 0; + self.sp -= 1; + } + Opcode::Pchl => { + self.pc = self.get_pair(RegisterPair::HL); + } + Opcode::Push(_) => { + self.sp -= 1; + } + Opcode::PushPsw => { + self.sp -= 1; + } Opcode::Pop(_) => (), + Opcode::PopPsw => (), Opcode::Xthl => (), Opcode::In => (), Opcode::Out => (), - Opcode::Ei => todo!(), - Opcode::Di => todo!(), + Opcode::Ei => { + self.inte = false; + } + Opcode::Di => { + self.inte = false; + } Opcode::Hlt => self.halted = true, Opcode::Nop => (), } @@ -446,7 +510,10 @@ impl I8080 { Opcode::Mvi(dst) => { self.regs[dst] = data; } - Opcode::Lxi(_) => todo!(), + Opcode::Lxi(_) => { + self.z = data; + self.pc += 1; + } Opcode::Lda => { self.z = data; self.pc += 1; @@ -455,62 +522,159 @@ impl I8080 { self.z = data; self.pc += 1; } - Opcode::Lhld => todo!(), - Opcode::Shld => todo!(), - Opcode::Ldax(_) => todo!(), - Opcode::Stax(_) => todo!(), - Opcode::AddM => { - let a = self.regs.a; - let b = data; - let res = (a as u16) + (b as u16); - self.sign = ((res as u8) & 0x80) > 0; - self.zero = (res as u8) == 0; - self.aux_carry = (a & 0x0f) + (b & 0x0f) > 0x0f; - self.parity = (res as u8).count_ones() % 2 == 0; - self.carry = res > 0xff; - self.regs.a = res as u8; + Opcode::Lhld => { + self.z = data; + self.pc += 1; + } + Opcode::Shld => { + self.z = data; + self.pc += 1; + } + Opcode::Ldax(_) => { + self.regs.a = data; + } + Opcode::Stax(_) => (), + Opcode::AddM => { + let (ac, cy, res) = Self::add_8bit(self.regs.a, data); + self.update_arith_flags(ac, cy, res); + self.regs.a = res; + } + Opcode::Adi => { + let (ac, cy, res) = Self::add_8bit(self.regs.a, data); + self.update_arith_flags(ac, cy, res); + self.regs.a = res; + self.pc += 1; + } + Opcode::AdcM => { + let (ac, cy, res) = Self::adc_8bit(self.regs.a, data, self.carry); + self.update_arith_flags(ac, cy, res); + self.regs.a = res; + } + Opcode::Aci => { + let (ac, cy, res) = Self::adc_8bit(self.regs.a, data, self.carry); + self.update_arith_flags(ac, cy, res); + self.regs.a = res; + self.pc += 1; + } + Opcode::SubM => { + let (ac, cy, res) = Self::sub_8bit(self.regs.a, data); + self.update_arith_flags(ac, cy, res); + self.regs.a = res; + } + Opcode::Sui => { + let (ac, cy, res) = Self::sub_8bit(self.regs.a, data); + self.update_arith_flags(ac, cy, res); + self.regs.a = res; + self.pc += 1; + } + Opcode::SbbM => { + let (ac, cy, res) = Self::sbb_8bit(self.regs.a, data, self.carry); + self.update_arith_flags(ac, cy, res); + self.regs.a = res; + } + Opcode::Sbi => { + let (ac, cy, res) = Self::sbb_8bit(self.regs.a, data, self.carry); + self.update_arith_flags(ac, cy, res); + self.regs.a = res; + self.pc += 1; + } + Opcode::InrM => { + let (ac, _cy, res) = Self::add_8bit(data, 1); + self.update_arith_flags(ac, self.carry, self.tmp); + self.tmp = res; + } + Opcode::DcrM => { + let (ac, _cy, res) = Self::sub_8bit(data, 1); + self.update_arith_flags(ac, self.carry, self.tmp); + self.tmp = res; + } + Opcode::AnaM => { + self.regs.a &= data; + self.update_logic_flags(self.regs.a); + } + Opcode::Ani => { + self.regs.a &= data; + self.update_logic_flags(self.regs.a); + self.pc += 1; + } + Opcode::XraM => { + self.regs.a ^= data; + self.update_logic_flags(self.regs.a); + } + Opcode::Xri => { + self.regs.a ^= data; + self.update_logic_flags(self.regs.a); + self.pc += 1; + } + Opcode::OraM => { + self.regs.a |= data; + self.update_logic_flags(self.regs.a); + } + Opcode::Ori => { + self.regs.a ^= data; + self.update_logic_flags(self.regs.a); + self.pc += 1; + } + Opcode::CmpM => { + let (ac, cy, res) = Self::sub_8bit(self.regs.a, data); + self.update_arith_flags(ac, cy, res); + } + Opcode::Cpi => { + let (ac, cy, res) = Self::sub_8bit(self.regs.a, data); + self.update_arith_flags(ac, cy, res); + self.pc += 1; } - Opcode::Adi => todo!(), - Opcode::AdcM => todo!(), - Opcode::Aci => todo!(), - Opcode::SubM => todo!(), - Opcode::Sui => todo!(), - Opcode::SbbM => todo!(), - Opcode::Sbi => todo!(), - Opcode::InrM => todo!(), - Opcode::DcrM => todo!(), - Opcode::AnaM => todo!(), - Opcode::Ani => todo!(), - Opcode::XraM => todo!(), - Opcode::Xri => todo!(), - Opcode::OraM => todo!(), - Opcode::Ori => todo!(), - Opcode::CmpM => todo!(), - Opcode::Cpi => todo!(), Opcode::Jmp => { self.z = data; self.pc += 1; } - Opcode::Jcc(_) => todo!(), - Opcode::Call => todo!(), - Opcode::Ccc(_) => todo!(), - Opcode::Ret => todo!(), - Opcode::Rcc(_) => todo!(), - Opcode::Rst(_) => todo!(), - Opcode::Push(_) => todo!(), - Opcode::Pop(_) => todo!(), + Opcode::Call => { + self.z = data; + self.pc += 1; + } + Opcode::Ret => { + self.z = data; + self.pc += 1; + } + Opcode::Rst(_) => { + self.sp -= 1; + } + Opcode::Push(_) => { + self.sp -= 1; + } + Opcode::PushPsw => { + self.sp -= 1; + } + Opcode::Pop(_) => { + self.sp += 1; + self.z = data; + } + Opcode::PopPsw => { + self.sp += 1; + self.set_flags(data); + } Opcode::Xthl => { self.sp += 1; self.z = data; } - Opcode::In => todo!(), - Opcode::Out => todo!(), - Opcode::Hlt => todo!(), + Opcode::In => { + self.w = data; + self.z = data; + self.pc += 1; + } + Opcode::Out => { + self.w = data; + self.z = data; + self.pc += 1; + } _ => unreachable!(), }, MCycle::M3 => match self.opcode { Opcode::MviM => (), - Opcode::Lxi(_) => todo!(), + Opcode::Lxi(rp) => { + self.w = data; + self.set_pair(rp, self.get_wz()); + } Opcode::Lda => { self.w = data; self.pc += 1; @@ -519,22 +683,46 @@ impl I8080 { self.w = data; self.pc += 1; } - Opcode::Lhld => todo!(), - Opcode::Shld => { - self.set_wz(self.get_wz() + 1); + Opcode::Lhld => { + self.w = data; + self.pc += 1; } - Opcode::Inr(_) => todo!(), - Opcode::Dcr(_) => todo!(), + Opcode::Shld => { + self.w = data; + self.pc += 1; + } + Opcode::InrM => (), + Opcode::DcrM => (), Opcode::Jmp => { self.w = data; self.pc = self.get_wz(); } - Opcode::Jcc(_) => todo!(), - Opcode::Call => todo!(), - Opcode::Ccc(_) => todo!(), - Opcode::Ret => todo!(), - Opcode::Rcc(_) => todo!(), - Opcode::Rst(_) => todo!(), + Opcode::Call => { + self.w = data; + self.pc += 1; + } + Opcode::Ret => { + self.w = data; + self.pc += 1; + } + Opcode::Rst(n) => { + self.z = n << 3; + self.pc = self.get_wz(); + } + Opcode::Push(_) => (), + Opcode::PushPsw => (), + Opcode::Pop(rp) => { + self.sp += 1; + self.z = data; + self.set_pair(rp, self.get_wz()); + } + Opcode::PopPsw => { + self.sp += 1; + self.regs.a = data; + } + Opcode::Xthl => { + self.w = data; + } _ => unreachable!(), }, MCycle::M4 => match self.opcode { @@ -542,21 +730,34 @@ impl I8080 { self.regs.a = data; } Opcode::Sta => (), - Opcode::Lhld => todo!(), - Opcode::Shld => todo!(), - Opcode::Call => todo!(), - Opcode::Ccc(_) => todo!(), - Opcode::Xthl => (), + Opcode::Lhld => { + self.set_wz(self.get_wz() + 1); + self.regs.l = data; + } + Opcode::Shld => { + self.set_wz(self.get_wz() + 1); + } + Opcode::Call => { + self.sp -= 1; + } + Opcode::Xthl => { + self.sp -= 1; + } _ => unreachable!(), }, MCycle::M5 => match self.opcode { - Opcode::Call => todo!(), - Opcode::Ccc(_) => todo!(), - Opcode::Xthl => (), + Opcode::Lhld => { + self.regs.h = data; + } + Opcode::Shld => (), + Opcode::Call => (), + Opcode::Xthl => { + self.set_pair(RegisterPair::HL, self.get_wz()); + } _ => unreachable!(), }, } - if self.cycle == self.opcode.max_m_cycle() { + if self.cycle == self.opcode.max_m_cycle() || cond_failed { println!("Instruction done"); self.cycle = MCycle::M1; } else { @@ -564,6 +765,73 @@ impl I8080 { } } + fn nibblize(n: u8) -> (u4, u4) { + (u4::new(n >> 4), u4::new(n & 0xF)) + } + + fn join_nibbles(nh: u4, nl: u4) -> u8 { + (u8::from(nh) << 4) | u8::from(nl) + } + + fn add_4bit(a: u4, b: u4, cy: bool) -> (bool, u4) { + let res: u5 = u5::from(a) + u5::from(b) + u5::new(cy as u8); + ( + (res >> 4) > u5::new(0), + (res & u5::new(0xF)).try_into().unwrap(), + ) + } + + fn add_8bit(a: u8, b: u8) -> (bool, bool, u8) { + Self::adc_8bit(a, b, false) + } + + fn adc_8bit(a: u8, b: u8, cy: bool) -> (bool, bool, u8) { + let (ah, al) = Self::nibblize(a); + let (bh, bl) = Self::nibblize(b); + let (ac, sl) = Self::add_4bit(al, bl, cy); + let (cy, sh) = Self::add_4bit(ah, bh, ac); + let sum = Self::join_nibbles(sh, sl); + (ac, cy, sum) + } + + fn sub_8bit(a: u8, b: u8) -> (bool, bool, u8) { + Self::sbb_8bit(a, b, true) + } + + fn sbb_8bit(a: u8, b: u8, cy: bool) -> (bool, bool, u8) { + let (ah, al) = Self::nibblize(a); + let (bh, bl) = Self::nibblize(!b); + let (ac, sl) = Self::add_4bit(al, bl, cy); + let (cy, sh) = Self::add_4bit(ah, bh, ac); + let sum = Self::join_nibbles(sh, sl); + (ac, cy, sum) + } + + fn update_logic_flags(&mut self, res: u8) { + self.update_arith_flags(false, false, res); + } + + fn update_arith_flags(&mut self, ac: bool, cy: bool, res: u8) { + self.sign = (res & 0x80) > 0; + self.zero = res == 0; + self.aux_carry = ac; + self.parity = res.count_ones() % 2 == 0; + self.carry = cy; + } + + fn check_cond(&self, cond: Condition) -> bool { + match cond { + Condition::NZ => !self.zero, + Condition::Z => self.zero, + Condition::NC => !self.carry, + Condition::C => self.carry, + Condition::PO => !self.parity, + Condition::PE => self.parity, + Condition::P => !self.sign, + Condition::M => self.sign, + } + } + fn get_pair(&self, pair: RegisterPair) -> u16 { match pair { RegisterPair::BC => ((self.regs.b as u16) << 8) | (self.regs.c as u16), @@ -599,4 +867,20 @@ impl I8080 { self.w = (val >> 8) as u8; self.z = val as u8; } + + fn get_flags(&self) -> u8 { + 0b10 | self.carry as u8 + | (self.parity as u8) << 2 + | (self.aux_carry as u8) << 4 + | (self.zero as u8) << 6 + | (self.sign as u8) << 7 + } + + fn set_flags(&mut self, flags: u8) { + self.carry = (flags & (1 << 0)) > 0; + self.parity = (flags & (1 << 2)) > 0; + self.aux_carry = (flags & (1 << 4)) > 0; + self.zero = (flags & (1 << 6)) > 0; + self.sign = (flags & (1 << 7)) > 0; + } } diff --git a/src/cpu/opcode.rs b/src/cpu/opcode.rs index 3b485de..64ab060 100644 --- a/src/cpu/opcode.rs +++ b/src/cpu/opcode.rs @@ -5,7 +5,7 @@ pub(super) enum RegisterPair { BC, DE, HL, - SP, // PSW for push/pop + SP, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -95,7 +95,9 @@ pub(super) enum Opcode { Rst(u8), Pchl, Push(RegisterPair), + PushPsw, Pop(RegisterPair), + PopPsw, Xthl, In, Out, @@ -169,7 +171,9 @@ impl Opcode { Self::Rst(_) => MCycle::M3, Self::Pchl => MCycle::M1, Self::Push(_) => MCycle::M3, + Self::PushPsw => MCycle::M3, Self::Pop(_) => MCycle::M3, + Self::PopPsw => MCycle::M3, Self::Xthl => MCycle::M5, Self::In => MCycle::M3, Self::Out => MCycle::M3, diff --git a/src/cpu/opcode_table.rs b/src/cpu/opcode_table.rs index 6ee89b0..991902e 100644 --- a/src/cpu/opcode_table.rs +++ b/src/cpu/opcode_table.rs @@ -245,11 +245,11 @@ pub(super) static OPCODE_TABLE: [Opcode; 256] = [ Xri, Rst(5), Rcc(Condition::P), - Pop(RegisterPair::SP), // Actually PSW + PopPsw, Jcc(Condition::P), Di, Ccc(Condition::P), - Push(RegisterPair::SP), // Actually PSW + PushPsw, Ori, Rst(6), Rcc(Condition::M), diff --git a/src/main.rs b/src/main.rs index d004dc6..44cf941 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ -mod cpu; mod card; +mod cpu; mod ram; use std::{ @@ -235,7 +235,7 @@ impl AltairEmulator { mem[0x10] = 0x4; mem[0x11] = 0x5; // 0: 072 020 000 - // 3: 107 + // 3: 107 // 4: 072 021 000 // 7: 200 // 10: 062 022 000 @@ -482,6 +482,14 @@ impl eframe::App for AltairEmulator { || pressed_keys.contains(&Keycode::U) || pressed_keys.contains(&Keycode::I) || pressed_keys.contains(&Keycode::O) + || pressed_keys.contains(&Keycode::S) + || pressed_keys.contains(&Keycode::D) + || pressed_keys.contains(&Keycode::F) + || pressed_keys.contains(&Keycode::G) + || pressed_keys.contains(&Keycode::H) + || pressed_keys.contains(&Keycode::J) + || pressed_keys.contains(&Keycode::K) + || pressed_keys.contains(&Keycode::L) { switch_clicked = true; } @@ -541,36 +549,53 @@ impl eframe::App for AltairEmulator { } } } - let newstate = if pressed_keys.contains(&Keycode::LShift) - || pressed_keys.contains(&Keycode::RShift) - { - SwitchState::Down - } else { - SwitchState::Up - }; if pressed_keys.contains(&Keycode::W) { - self.runstop = newstate; + self.runstop = SwitchState::Up; } if pressed_keys.contains(&Keycode::E) { - self.single_step = newstate; + self.single_step = SwitchState::Up; } if pressed_keys.contains(&Keycode::R) { - self.exam = newstate; + self.exam = SwitchState::Up; } if pressed_keys.contains(&Keycode::T) { - self.dep = newstate; + self.dep = SwitchState::Up; } if pressed_keys.contains(&Keycode::Y) { - self.reset = newstate; + self.reset = SwitchState::Up; } if pressed_keys.contains(&Keycode::U) { - self.prot = newstate; + self.prot = SwitchState::Up; } if pressed_keys.contains(&Keycode::I) { - self.aux1 = newstate; + self.aux1 = SwitchState::Up; } if pressed_keys.contains(&Keycode::O) { - self.aux2 = newstate; + self.aux2 = SwitchState::Up; + } + if pressed_keys.contains(&Keycode::S) { + self.runstop = SwitchState::Down; + } + if pressed_keys.contains(&Keycode::D) { + self.single_step = SwitchState::Down; + } + if pressed_keys.contains(&Keycode::F) { + self.exam = SwitchState::Down; + } + if pressed_keys.contains(&Keycode::G) { + self.dep = SwitchState::Down; + } + if pressed_keys.contains(&Keycode::H) { + self.reset = SwitchState::Down; + } + if pressed_keys.contains(&Keycode::J) { + self.prot = SwitchState::Down; + } + if pressed_keys.contains(&Keycode::K) { + self.aux1 = SwitchState::Down; + } + if pressed_keys.contains(&Keycode::L) { + self.aux2 = SwitchState::Down; } if let Some(kbd_ad) = kbd_ad { switch_clicked = true; @@ -688,7 +713,10 @@ enum OptionsCategory { impl OptionWindow { fn new(ctx: &egui::Context, options: Options) -> Self { Modal::new(ctx, "options_modal").open(); - Self { options, category: OptionsCategory::General } + Self { + options, + category: OptionsCategory::General, + } } fn draw(&mut self, ctx: &egui::Context, options: &mut Options) -> bool { let modal = Modal::new(ctx, "options_modal"); @@ -701,7 +729,7 @@ impl OptionWindow { match self.category { OptionsCategory::General => { ui.checkbox(&mut self.options.fan_enabled, "Fan enabled"); - }, + } OptionsCategory::Cards => { ui.heading("TODO"); } diff --git a/src/ram.rs b/src/ram.rs index 04be1b0..8d85203 100644 --- a/src/ram.rs +++ b/src/ram.rs @@ -1,4 +1,4 @@ -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use crate::card::{Card, CardEnum}; @@ -19,7 +19,7 @@ impl Card for RamCard { ram.resize(settings.size as usize, 0); CardEnum::RamCard(Self { ram, - start_addr: settings.start_addr + start_addr: settings.start_addr, }) } @@ -27,6 +27,7 @@ impl Card for RamCard { ron::to_string(&RamCardSettings { size: self.ram.len() as u16, start_addr: self.start_addr, - }).unwrap() + }) + .unwrap() } }