core.rsannotatedcore.rssource405 lines · 9.8 KB · raw
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}