1use crate::traits::{BusInterface, InterruptLine}; 2use jgenesis_common::num::{GetBit, U16Ext}; 3 4mod instructions; 5 6#[derive(Debug, Clone, Copy, PartialEq, Eq)] 7#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))] 8pub struct Flags { 9 pub sign: bool, 10 pub zero: bool, 11 pub y: bool, 12 pub half_carry: bool, 13 pub x: bool, 14 pub overflow: bool, 15 pub subtract: bool, 16 pub carry: bool, 17} 18 19impl From<Flags> for u8 { 20 fn from(value: Flags) -> Self { 21 (u8::from(value.sign) << 7) 22 | (u8::from(value.zero) << 6) 23 | (u8::from(value.y) << 5) 24 | (u8::from(value.half_carry) << 4) 25 | (u8::from(value.x) << 3) 26 | (u8::from(value.overflow) << 2) 27 | (u8::from(value.subtract) << 1) 28 | u8::from(value.carry) 29 } 30} 31 32impl From<u8> for Flags { 33 fn from(value: u8) -> Self { 34 Self { 35 sign: value.bit(7), 36 zero: value.bit(6), 37 y: value.bit(5), 38 half_carry: value.bit(4), 39 x: value.bit(3), 40 overflow: value.bit(2), 41 subtract: value.bit(1), 42 carry: value.bit(0), 43 } 44 } 45} 46 47#[derive(Debug, Clone, Copy, PartialEq, Eq)] 48#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))] 49pub enum InterruptMode { 50 Mode0, 51 Mode1, 52 Mode2, 53} 54 55#[derive(Debug, Clone)] 56#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))] 57pub struct Registers { 58 pub a: u8, 59 pub f: Flags, 60 pub b: u8, 61 pub c: u8, 62 pub d: u8, 63 pub e: u8, 64 pub h: u8, 65 pub l: u8, 66 pub ap: u8, 67 pub fp: Flags, 68 pub bp: u8, 69 pub cp: u8, 70 pub dp: u8, 71 pub ep: u8, 72 pub hp: u8, 73 pub lp: u8, 74 pub i: u8, 75 pub r: u8, 76 pub ix: u16, 77 pub iy: u16, 78 pub sp: u16, 79 pub pc: u16, 80 pub iff1: bool, 81 pub iff2: bool, 82 pub interrupt_mode: InterruptMode, 83 pub interrupt_delay: bool, 84 pub last_nmi: InterruptLine, 85 pub halted: bool, 86} 87 88impl Registers { 89 #[must_use] 90 pub fn new() -> Self { 91 Self { 92 a: 0xFF, 93 f: 0xFF.into(), 94 b: 0xFF, 95 c: 0xFF, 96 d: 0xFF, 97 e: 0xFF, 98 h: 0xFF, 99 l: 0xFF, 100 ap: 0xFF, 101 fp: 0xFF.into(), 102 bp: 0xFF, 103 cp: 0xFF, 104 dp: 0xFF, 105 ep: 0xFF, 106 hp: 0xFF, 107 lp: 0xFF, 108 i: 0xFF, 109 r: 0xFF, 110 ix: 0xFFFF, 111 iy: 0xFFFF, 112 sp: 0xFFFF, 113 pc: 0x0000, 114 iff1: false, 115 iff2: false, 116 interrupt_mode: InterruptMode::Mode0, 117 interrupt_delay: false, 118 last_nmi: InterruptLine::High, 119 halted: false, 120 } 121 } 122 123 fn increment_r(&mut self) { 124 self.r = (self.r.wrapping_add(1) & 0x7F) | (self.r & 0x80); 125 } 126} 127 128impl Default for Registers { 129 fn default() -> Self { 130 Self::new() 131 } 132} 133 134#[derive(Debug, Clone, Copy, PartialEq, Eq)] 135pub enum Register8 { 136 A, 137 B, 138 C, 139 D, 140 E, 141 H, 142 L, 143 I, 144 R, 145 IXHigh, 146 IXLow, 147 IYHigh, 148 IYLow, 149} 150 151impl Register8 { 152 fn read_from(self, registers: &Registers) -> u8 { 153 match self { 154 Self::A => registers.a, 155 Self::B => registers.b, 156 Self::C => registers.c, 157 Self::D => registers.d, 158 Self::E => registers.e, 159 Self::H => registers.h, 160 Self::L => registers.l, 161 Self::I => registers.i, 162 Self::R => registers.r, 163 Self::IXHigh => registers.ix.msb(), 164 Self::IXLow => registers.ix.lsb(), 165 Self::IYHigh => registers.iy.msb(), 166 Self::IYLow => registers.iy.lsb(), 167 } 168 } 169 170 fn write_to(self, value: u8, registers: &mut Registers) { 171 match self { 172 Self::A => { 173 registers.a = value; 174 } 175 Self::B => { 176 registers.b = value; 177 } 178 Self::C => { 179 registers.c = value; 180 } 181 Self::D => { 182 registers.d = value; 183 } 184 Self::E => { 185 registers.e = value; 186 } 187 Self::H => { 188 registers.h = value; 189 } 190 Self::L => { 191 registers.l = value; 192 } 193 Self::I => { 194 registers.i = value; 195 } 196 Self::R => { 197 registers.r = value; 198 } 199 Self::IXHigh => { 200 registers.ix.set_msb(value); 201 } 202 Self::IXLow => { 203 registers.ix.set_lsb(value); 204 } 205 Self::IYHigh => { 206 registers.iy.set_msb(value); 207 } 208 Self::IYLow => { 209 registers.iy.set_lsb(value); 210 } 211 } 212 } 213} 214 215#[derive(Debug, Clone, Copy, PartialEq, Eq)] 216pub enum Register16 { 217 AF, 218 BC, 219 DE, 220 HL, 221 IX, 222 IY, 223 SP, 224} 225 226impl Register16 { 227 fn read_from(self, registers: &Registers) -> u16 { 228 match self { 229 Self::AF => u16::from_be_bytes([registers.a, registers.f.into()]), 230 Self::BC => u16::from_be_bytes([registers.b, registers.c]), 231 Self::DE => u16::from_be_bytes([registers.d, registers.e]), 232 Self::HL => u16::from_be_bytes([registers.h, registers.l]), 233 Self::IX => registers.ix, 234 Self::IY => registers.iy, 235 Self::SP => registers.sp, 236 } 237 } 238 239 fn write_to(self, value: u16, registers: &mut Registers) { 240 match self { 241 Self::AF => { 242 let [a, f] = value.to_be_bytes(); 243 registers.a = a; 244 registers.f = f.into(); 245 } 246 Self::BC => { 247 let [b, c] = value.to_be_bytes(); 248 registers.b = b; 249 registers.c = c; 250 } 251 Self::DE => { 252 let [d, e] = value.to_be_bytes(); 253 registers.d = d; 254 registers.e = e; 255 } 256 Self::HL => { 257 let [h, l] = value.to_be_bytes(); 258 registers.h = h; 259 registers.l = l; 260 } 261 Self::IX => { 262 registers.ix = value; 263 } 264 Self::IY => { 265 registers.iy = value; 266 } 267 Self::SP => { 268 registers.sp = value; 269 } 270 } 271 } 272} 273 274#[derive(Debug, Clone, Copy, PartialEq, Eq)] 275pub enum IndexRegister { 276 IX, 277 IY, 278} 279 280impl IndexRegister { 281 fn read_from(self, registers: &Registers) -> u16 { 282 match self { 283 Self::IX => registers.ix, 284 Self::IY => registers.iy, 285 } 286 } 287 288 fn high_byte(self) -> Register8 { 289 match self { 290 Self::IX => Register8::IXHigh, 291 Self::IY => Register8::IYHigh, 292 } 293 } 294 295 fn low_byte(self) -> Register8 { 296 match self { 297 Self::IX => Register8::IXLow, 298 Self::IY => Register8::IYLow, 299 } 300 } 301} 302 303impl From<IndexRegister> for Register16 { 304 fn from(value: IndexRegister) -> Self { 305 match value { 306 IndexRegister::IX => Register16::IX, 307 IndexRegister::IY => Register16::IY, 308 } 309 } 310} 311 312#[derive(Debug, Clone)] 313#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))] 314pub struct Z80 { 315 registers: Registers, 316 stalled: bool, 317 t_cycles_wait: u32, 318} 319 320impl Z80 { 321 const MINIMUM_T_CYCLES: u32 = 4; 322 323 #[must_use] 324 pub fn new() -> Self { 325 Self { registers: Registers::new(), stalled: false, t_cycles_wait: 0 } 326 } 327 328 #[must_use] 329 pub fn pc(&self) -> u16 { 330 self.registers.pc 331 } 332 333 pub fn set_pc(&mut self, pc: u16) { 334 self.registers.pc = pc; 335 } 336 337 #[must_use] 338 pub fn registers(&self) -> &Registers { 339 &self.registers 340 } 341 342 pub fn set_sp(&mut self, sp: u16) { 343 self.registers.sp = sp; 344 } 345 346 pub fn set_interrupt_mode(&mut self, mode: InterruptMode) { 347 self.registers.interrupt_mode = mode; 348 } 349 350 #[must_use] 351 #[inline] 352 pub fn stalled(&self) -> bool { 353 self.stalled 354 } 355 356 /// Execute a single instruction (or the interrupt service routine) and return how many T-cycles it took. 357 pub fn execute_instruction<B: BusInterface>(&mut self, bus: &mut B) -> u32 { 358 if bus.reset() { 359 // RESET is asserted; reset internal state 360 self.registers.i = 0; 361 self.registers.r = 0; 362 self.registers.pc = 0; 363 self.registers.iff1 = false; 364 self.registers.iff2 = false; 365 self.registers.interrupt_mode = InterruptMode::Mode0; 366 self.registers.interrupt_delay = false; 367 self.registers.last_nmi = InterruptLine::High; 368 self.registers.halted = false; 369 self.stalled = false; 370 371 return Self::MINIMUM_T_CYCLES; 372 } 373 374 if bus.busreq() { 375 // BUSREQ is asserted; Z80 is halted 376 self.stalled = true; 377 return Self::MINIMUM_T_CYCLES; 378 } 379 380 self.stalled = false; 381 382 instructions::execute(self, bus) 383 } 384 385 /// Tick the Z80 for a single T-cycle. 386 /// 387 /// When run using this method, the Z80 will immediately execute an instruction in full and 388 /// internally record how many cycles the instruction took; the next instruction will be 389 /// executed after calling `tick()` that many times, and so on. 390 #[inline] 391 pub fn tick<B: BusInterface>(&mut self, bus: &mut B) { 392 if self.t_cycles_wait > 0 { 393 self.t_cycles_wait -= 1; 394 } else { 395 // Subtract 1 to account for the current tick() call 396 self.t_cycles_wait = self.execute_instruction(bus) - 1; 397 } 398 } 399} 400 401impl Default for Z80 { 402 fn default() -> Self { 403 Self::new() 404 } 405}