tgbr/
cpu.rs

1use bitvec::prelude::*;
2use log::{debug, log_enabled, trace, Level};
3use serde::{Deserialize, Serialize};
4
5use crate::{
6    context,
7    util::{trait_alias, ConstEval},
8};
9
10#[derive(Default, Serialize, Deserialize)]
11pub struct Cpu {
12    halting: bool,
13    interrupt_master_enable: bool,
14    prev_interrupt_enable: bool,
15    reg: Register,
16    cycle: u64,
17    period: u64,
18}
19
20trait_alias!(pub trait Context = context::Bus + context::InterruptFlag);
21
22#[derive(Default, Serialize, Deserialize)]
23pub struct Register {
24    pub a: u8,
25    pub f: Flag,
26    pub b: u8,
27    pub c: u8,
28    pub d: u8,
29    pub e: u8,
30    pub h: u8,
31    pub l: u8,
32    pub sp: u16,
33    pub pc: u16,
34}
35
36impl Register {
37    fn af(&self) -> u16 {
38        ((self.a as u16) << 8) | (self.f.pack() as u16)
39    }
40
41    fn set_af(&mut self, value: u16) {
42        self.a = (value >> 8) as u8;
43        self.f.unpack(value as u8);
44    }
45
46    fn bc(&self) -> u16 {
47        ((self.b as u16) << 8) | (self.c as u16)
48    }
49
50    fn set_bc(&mut self, data: u16) {
51        self.b = (data >> 8) as u8;
52        self.c = (data & 0xFF) as u8;
53    }
54
55    fn de(&self) -> u16 {
56        ((self.d as u16) << 8) | (self.e as u16)
57    }
58
59    fn set_de(&mut self, data: u16) {
60        self.d = (data >> 8) as u8;
61        self.e = (data & 0xFF) as u8;
62    }
63
64    fn hl(&self) -> u16 {
65        ((self.h as u16) << 8) | (self.l as u16)
66    }
67
68    fn set_hl(&mut self, data: u16) {
69        self.h = (data >> 8) as u8;
70        self.l = (data & 0xFF) as u8;
71    }
72}
73
74#[derive(Default, Serialize, Deserialize)]
75pub struct Flag {
76    pub z: bool,
77    pub n: bool,
78    pub h: bool,
79    pub c: bool,
80}
81
82impl Flag {
83    pub fn pack(&self) -> u8 {
84        let mut data = 0;
85        let v = data.view_bits_mut::<Lsb0>();
86        v.set(7, self.z);
87        v.set(6, self.n);
88        v.set(5, self.h);
89        v.set(4, self.c);
90        data
91    }
92
93    pub fn unpack(&mut self, data: u8) {
94        let v = data.view_bits::<Lsb0>();
95        self.z = v[7];
96        self.n = v[6];
97        self.h = v[5];
98        self.c = v[4];
99    }
100}
101
102#[rustfmt::skip]
103macro_rules! instructions {
104    ($cont:ident) => { indexing! { $cont @start:
105        //       0 / 8       1 / 9      2 / A       3 / B      4 / C       5 / D      6 / E       7 / F
106        /* 00 */ NOP;        LD BC,nn;  LD (BC),A;  INC BC;    INC B;      DEC B;     LD B,n;     RLCA;
107        /* 08 */ LD (nn),SP; ADD HL,BC; LD A,(BC);  DEC BC;    INC C;      DEC C;     LD C,n;     RRCA;
108        /* 10 */ STOP;       LD DE,nn;  LD (DE),A;  INC DE;    INC D;      DEC D;     LD D,n;     RLA;
109        /* 18 */ JR r8;      ADD HL,DE; LD A,(DE);  DEC DE;    INC E;      DEC E;     LD E,n;     RRA;
110        /* 20 */ JR NZ,r8;   LD HL,nn;  LD (^HL),A; INC HL;    INC H;      DEC H;     LD H,n;     DAA;
111        /* 28 */ JR Z,r8;    ADD HL,HL; LD A,(^HL); DEC HL;    INC L;      DEC L;     LD L,n;     CPL;
112        /* 30 */ JR NC,r8;   LD SP,nn;  LD (-HL),A; INC SP;    INC (HL);   DEC (HL);  LD (HL),n;  SCF;
113        /* 38 */ JR C,r8;    ADD HL,SP; LD A,(-HL); DEC SP;    INC A;      DEC A;     LD A,n;     CCF;
114        /* 40 */ LD B,B;     LD B,C;    LD B,D;     LD B,E;    LD B,H;     LD B,L;    LD B,(HL);  LD B,A;
115        /* 48 */ LD C,B;     LD C,C;    LD C,D;     LD C,E;    LD C,H;     LD C,L;    LD C,(HL);  LD C,A;
116        /* 50 */ LD D,B;     LD D,C;    LD D,D;     LD D,E;    LD D,H;     LD D,L;    LD D,(HL);  LD D,A;
117        /* 58 */ LD E,B;     LD E,C;    LD E,D;     LD E,E;    LD E,H;     LD E,L;    LD E,(HL);  LD E,A;
118        /* 60 */ LD H,B;     LD H,C;    LD H,D;     LD H,E;    LD H,H;     LD H,L;    LD H,(HL);  LD H,A;
119        /* 68 */ LD L,B;     LD L,C;    LD L,D;     LD L,E;    LD L,H;     LD L,L;    LD L,(HL);  LD L,A;
120        /* 70 */ LD (HL),B;  LD (HL),C; LD (HL),D;  LD (HL),E; LD (HL),H;  LD (HL),L; HALT;       LD (HL),A;
121        /* 78 */ LD A,B;     LD A,C;    LD A,D;     LD A,E;    LD A,H;     LD A,L;    LD A,(HL);  LD A,A;
122        /* 80 */ ADD A,B;    ADD A,C;   ADD A,D;    ADD A,E;   ADD A,H;    ADD A,L;   ADD A,(HL); ADD A,A;
123        /* 88 */ ADC A,B;    ADC A,C;   ADC A,D;    ADC A,E;   ADC A,H;    ADC A,L;   ADC A,(HL); ADC A,A;
124        /* 90 */ SUB B;      SUB C;     SUB D;      SUB E;     SUB H;      SUB L;     SUB (HL);   SUB A;
125        /* 98 */ SBC A,B;    SBC A,C;   SBC A,D;    SBC A,E;   SBC A,H;    SBC A,L;   SBC A,(HL); SBC A,A;
126        /* A0 */ AND B;      AND C;     AND D;      AND E;     AND H;      AND L;     AND (HL);   AND A;
127        /* A8 */ XOR B;      XOR C;     XOR D;      XOR E;     XOR H;      XOR L;     XOR (HL);   XOR A;
128        /* B0 */ OR B;       OR C;      OR D;       OR E;      OR H;       OR L;      OR (HL);    OR A;
129        /* B8 */ CP B;       CP C;      CP D;       CP E;      CP H;       CP L;      CP (HL);    CP A;
130        /* C0 */ RET NZ;     POP BC;    JP NZ,nn;   JP nn;     CALL NZ,nn; PUSH BC;   ADD A,n;    RST 0x00;
131        /* C8 */ RET Z;      RET;       JP Z,nn;    CB;        CALL Z,nn;  CALL nn;   ADC A,n;    RST 0x08;
132        /* D0 */ RET NC;     POP DE;    JP NC,nn;   UNK;       CALL NC,nn; PUSH DE;   SUB n;      RST 0x10;
133        /* D8 */ RET C;      RETI;      JP C,nn;    UNK;       CALL C,nn;  UNK;       SBC A,n;    RST 0x18;
134        /* E0 */ LDH (n),A;  POP HL;    LD (C),A;   UNK;       UNK;        PUSH HL;   AND n;      RST 0x20;
135        /* E8 */ ADD SP,n;   JP (HL);   LD (nn),A;  UNK;       UNK;        UNK;       XOR n;      RST 0x28;
136        /* F0 */ LDH A,(n);  POP AF;    LD A,(C);   DI;        UNK;        PUSH AF;   OR n;       RST 0x30;
137        /* F8 */ LD HL,SPn;  LD SP,HL;  LD A,(nn);  EI;        UNK;        UNK;       CP n;       RST 0x38;
138    }};
139}
140
141#[rustfmt::skip]
142macro_rules! instructions_cb {
143    ($cont:ident) => { indexing! { $cont @start:
144        //       0 / 8       1 / 9      2 / A       3 / B      4 / C       5 / D      6 / E       7 / F
145        /* 00 */ RLC B;      RLC C;     RLC D;      RLC E;     RLC H;      RLC L;     RLC (HL);   RLC A;
146        /* 08 */ RRC B;      RRC C;     RRC D;      RRC E;     RRC H;      RRC L;     RRC (HL);   RRC A;
147        /* 10 */ RL B;       RL C;      RL D;       RL E;      RL H;       RL L;      RL (HL);    RL A;
148        /* 18 */ RR B;       RR C;      RR D;       RR E;      RR H;       RR L;      RR (HL);    RR A;
149        /* 20 */ SLA B;      SLA C;     SLA D;      SLA E;     SLA H;      SLA L;     SLA (HL);   SLA A;
150        /* 28 */ SRA B;      SRA C;     SRA D;      SRA E;     SRA H;      SRA L;     SRA (HL);   SRA A;
151        /* 30 */ SWAP B;     SWAP C;    SWAP D;     SWAP E;    SWAP H;     SWAP L;    SWAP (HL);  SWAP A;
152        /* 38 */ SRL B;      SRL C;     SRL D;      SRL E;     SRL H;      SRL L;     SRL (HL);   SRL A;
153        /* 40 */ BIT 0,B;    BIT 0,C;   BIT 0,D;    BIT 0,E;   BIT 0,H;    BIT 0,L;   BIT 0,(HL); BIT 0,A;
154        /* 48 */ BIT 1,B;    BIT 1,C;   BIT 1,D;    BIT 1,E;   BIT 1,H;    BIT 1,L;   BIT 1,(HL); BIT 1,A;
155        /* 50 */ BIT 2,B;    BIT 2,C;   BIT 2,D;    BIT 2,E;   BIT 2,H;    BIT 2,L;   BIT 2,(HL); BIT 2,A;
156        /* 58 */ BIT 3,B;    BIT 3,C;   BIT 3,D;    BIT 3,E;   BIT 3,H;    BIT 3,L;   BIT 3,(HL); BIT 3,A;
157        /* 60 */ BIT 4,B;    BIT 4,C;   BIT 4,D;    BIT 4,E;   BIT 4,H;    BIT 4,L;   BIT 4,(HL); BIT 4,A;
158        /* 68 */ BIT 5,B;    BIT 5,C;   BIT 5,D;    BIT 5,E;   BIT 5,H;    BIT 5,L;   BIT 5,(HL); BIT 5,A;
159        /* 70 */ BIT 6,B;    BIT 6,C;   BIT 6,D;    BIT 6,E;   BIT 6,H;    BIT 6,L;   BIT 6,(HL); BIT 6,A;
160        /* 78 */ BIT 7,B;    BIT 7,C;   BIT 7,D;    BIT 7,E;   BIT 7,H;    BIT 7,L;   BIT 7,(HL); BIT 7,A;
161        /* 80 */ RES 0,B;    RES 0,C;   RES 0,D;    RES 0,E;   RES 0,H;    RES 0,L;   RES 0,(HL); RES 0,A;
162        /* 88 */ RES 1,B;    RES 1,C;   RES 1,D;    RES 1,E;   RES 1,H;    RES 1,L;   RES 1,(HL); RES 1,A;
163        /* 90 */ RES 2,B;    RES 2,C;   RES 2,D;    RES 2,E;   RES 2,H;    RES 2,L;   RES 2,(HL); RES 2,A;
164        /* 98 */ RES 3,B;    RES 3,C;   RES 3,D;    RES 3,E;   RES 3,H;    RES 3,L;   RES 3,(HL); RES 3,A;
165        /* A0 */ RES 4,B;    RES 4,C;   RES 4,D;    RES 4,E;   RES 4,H;    RES 4,L;   RES 4,(HL); RES 4,A;
166        /* A8 */ RES 5,B;    RES 5,C;   RES 5,D;    RES 5,E;   RES 5,H;    RES 5,L;   RES 5,(HL); RES 5,A;
167        /* B0 */ RES 6,B;    RES 6,C;   RES 6,D;    RES 6,E;   RES 6,H;    RES 6,L;   RES 6,(HL); RES 6,A;
168        /* B8 */ RES 7,B;    RES 7,C;   RES 7,D;    RES 7,E;   RES 7,H;    RES 7,L;   RES 7,(HL); RES 7,A;
169        /* C0 */ SET 0,B;    SET 0,C;   SET 0,D;    SET 0,E;   SET 0,H;    SET 0,L;   SET 0,(HL); SET 0,A;
170        /* C8 */ SET 1,B;    SET 1,C;   SET 1,D;    SET 1,E;   SET 1,H;    SET 1,L;   SET 1,(HL); SET 1,A;
171        /* D0 */ SET 2,B;    SET 2,C;   SET 2,D;    SET 2,E;   SET 2,H;    SET 2,L;   SET 2,(HL); SET 2,A;
172        /* D8 */ SET 3,B;    SET 3,C;   SET 3,D;    SET 3,E;   SET 3,H;    SET 3,L;   SET 3,(HL); SET 3,A;
173        /* E0 */ SET 4,B;    SET 4,C;   SET 4,D;    SET 4,E;   SET 4,H;    SET 4,L;   SET 4,(HL); SET 4,A;
174        /* E8 */ SET 5,B;    SET 5,C;   SET 5,D;    SET 5,E;   SET 5,H;    SET 5,L;   SET 5,(HL); SET 5,A;
175        /* F0 */ SET 6,B;    SET 6,C;   SET 6,D;    SET 6,E;   SET 6,H;    SET 6,L;   SET 6,(HL); SET 6,A;
176        /* F8 */ SET 7,B;    SET 7,C;   SET 7,D;    SET 7,E;   SET 7,H;    SET 7,L;   SET 7,(HL); SET 7,A;
177    }};
178}
179
180macro_rules! indexing {
181    ($cont:ident @start: $($input:tt)*) => {
182        indexing!($cont @indexing: 0 => $($input)* @end_of_input)
183    };
184
185    ($cont:ident @indexing: $ix:expr => $mne:ident; $($rest:tt)*) => {
186        indexing!($cont @indexing: $ix + 1 => $($rest)* $ix => $mne [];)
187    };
188    ($cont:ident @indexing: $ix:expr => $mne:ident $opr:tt; $($rest:tt)*) => {
189        indexing!($cont @indexing: $ix + 1 => $($rest)* $ix => $mne [$opr];)
190    };
191    ($cont:ident @indexing: $ix:expr => $mne:ident $dst:tt, $src:tt; $($rest:tt)*) => {
192        indexing!($cont @indexing: $ix + 1 => $($rest)* $ix => $mne [$dst, $src];)
193    };
194
195    ($cont:ident @indexing: $_:expr => @end_of_input $($ix:expr => $mne:ident $opr:tt; )*) => {
196        $cont!($($ix => $mne $opr;)*)
197    };
198}
199
200impl Cpu {
201    pub fn new() -> Self {
202        Self::default()
203    }
204
205    pub fn register(&mut self) -> &mut Register {
206        &mut self.reg
207    }
208
209    pub fn step(&mut self, ctx: &mut impl Context) {
210        self.period += 1;
211        while self.cycle < self.period {
212            if ctx.check_stall_cpu() {
213                self.tick(ctx);
214                continue;
215            }
216
217            let wake = ctx.check_wake();
218
219            if self.halting {
220                // FIXME: halt bug?
221                if wake || ctx.interrupt_flag() & ctx.interrupt_enable() != 0 {
222                    self.halting = false;
223                    debug!("WAKE UP");
224                }
225                self.tick(ctx);
226                self.prev_interrupt_enable = self.interrupt_master_enable;
227                continue;
228            }
229
230            let pc = self.reg.pc;
231            let opc = self.fetch(ctx);
232            if self.process_interrupt(ctx, pc) {
233                continue;
234            }
235
236            if log_enabled!(Level::Trace) {
237                self.trace(ctx, pc, opc);
238            }
239            self.exec_instr(ctx, opc);
240        }
241    }
242
243    fn process_interrupt(&mut self, ctx: &mut impl Context, ret_addr: u16) -> bool {
244        let prev_interrupt_enable = self.prev_interrupt_enable;
245        self.prev_interrupt_enable = self.interrupt_master_enable;
246
247        if !prev_interrupt_enable {
248            return false;
249        }
250        if ctx.interrupt_flag() & ctx.interrupt_enable() == 0 {
251            return false;
252        }
253
254        let prev_if = ctx.interrupt_flag();
255        self.interrupt_master_enable = false;
256        self.prev_interrupt_enable = false;
257
258        self.push(ctx, (ret_addr >> 8) as u8);
259        // Dispatch interrupt vector at this timing
260        let addr = self.dispatch_interrupt(ctx);
261        self.push(ctx, (ret_addr & 0xff) as u8);
262
263        self.reg.pc = addr;
264        debug!(
265            "Interrupt occured: IE:{:02X}, IF:{:02X}->{:02X}, ADDR:{:04X}",
266            ctx.interrupt_enable(),
267            prev_if,
268            ctx.interrupt_flag(),
269            self.reg.pc
270        );
271
272        self.tick(ctx);
273        self.tick(ctx);
274        self.tick(ctx);
275        true
276    }
277
278    fn dispatch_interrupt(&mut self, ctx: &mut impl Context) -> u16 {
279        let b = ctx.interrupt_flag() & ctx.interrupt_enable();
280        if b == 0 {
281            // IE (=$FFFF) is written in pushing upper byte of PC, dispatching interrupt vector canceled
282            0x0000
283        } else {
284            let pos = b.trailing_zeros();
285            ctx.clear_interrupt_flag_bit(pos as _);
286            0x0040 + pos as u16 * 8
287        }
288    }
289
290    fn exec_instr(&mut self, ctx: &mut impl Context, opc: u8) {
291        macro_rules! load {
292            (n) => {
293                self.fetch(ctx)
294            };
295            (nn) => {
296                self.fetch_u16(ctx)
297            };
298
299            (A) => {
300                self.reg.a
301            };
302            (B) => {
303                self.reg.b
304            };
305            (C) => {
306                self.reg.c
307            };
308            (D) => {
309                self.reg.d
310            };
311            (E) => {
312                self.reg.e
313            };
314            (H) => {
315                self.reg.h
316            };
317            (L) => {
318                self.reg.l
319            };
320
321            (AF) => {
322                self.reg.af()
323            };
324            (BC) => {
325                self.reg.bc()
326            };
327            (DE) => {
328                self.reg.de()
329            };
330            (HL) => {
331                self.reg.hl()
332            };
333            (SP) => {
334                self.reg.sp
335            };
336            (SPn) => {{
337                let opr = self.fetch(ctx) as i8 as u16;
338                let dst = self.reg.sp;
339                let res = dst.wrapping_add(opr);
340                self.reg.f.z = false;
341                self.reg.f.n = false;
342                self.reg.f.h = (opr ^ dst ^ res) & 0x10 != 0;
343                self.reg.f.c = (opr ^ dst ^ res) & 0x100 != 0;
344                self.tick(ctx);
345                res
346            }};
347            (r8) => {{
348                self.fetch(ctx) as i8
349            }};
350
351            ((C)) => {
352                self.read(ctx, 0xFF00 | self.reg.c as u16)
353            };
354            ((BC)) => {
355                self.read(ctx, self.reg.bc())
356            };
357            ((DE)) => {
358                self.read(ctx, self.reg.de())
359            };
360            ((HL)) => {{
361                let hl = self.reg.hl();
362                self.read(ctx, hl)
363            }};
364            ((^HL)) => {{
365                let hl = self.reg.hl();
366                self.reg.set_hl(hl.wrapping_add(1));
367                self.read(ctx, hl)
368            }};
369            ((-HL)) => {{
370                let hl = self.reg.hl();
371                self.reg.set_hl(hl.wrapping_sub(1));
372                self.read(ctx, hl)
373            }};
374            ((nn)) => {{
375                let addr = self.fetch_u16(ctx);
376                self.read(ctx, addr)
377            }};
378        }
379
380        macro_rules! store {
381            (A, $data:ident) => {{
382                self.reg.a = $data;
383            }};
384            (B, $data:ident) => {{
385                self.reg.b = $data;
386            }};
387            (C, $data:ident) => {{
388                self.reg.c = $data;
389            }};
390            (D, $data:ident) => {{
391                self.reg.d = $data;
392            }};
393            (E, $data:ident) => {{
394                self.reg.e = $data;
395            }};
396            (H, $data:ident) => {{
397                self.reg.h = $data;
398            }};
399            (L, $data:ident) => {{
400                self.reg.l = $data;
401            }};
402
403            (AF, $data:ident) => {{
404                self.reg.set_af($data);
405            }};
406            (BC, $data:ident) => {
407                self.reg.set_bc($data)
408            };
409            (DE, $data:ident) => {
410                self.reg.set_de($data)
411            };
412            (HL, $data:ident) => {
413                self.reg.set_hl($data)
414            };
415            (SP, $data:ident) => {{
416                self.reg.sp = $data;
417            }};
418
419            ((C), $data:ident) => {
420                self.write(ctx, 0xFF00 | self.reg.c as u16, $data)
421            };
422            ((BC), $data:ident) => {
423                self.write(ctx, self.reg.bc(), $data)
424            };
425            ((DE), $data:ident) => {
426                self.write(ctx, self.reg.de(), $data)
427            };
428            ((HL), $data:ident) => {{
429                let hl = self.reg.hl();
430                self.write(ctx, hl, $data);
431            }};
432            ((^HL), $data:ident) => {{
433                let hl = self.reg.hl();
434                self.write(ctx, hl, $data);
435                self.reg.set_hl(hl.wrapping_add(1));
436            }};
437            ((-HL), $data:ident) => {{
438                let hl = self.reg.hl();
439                self.write(ctx, hl, $data);
440                self.reg.set_hl(hl.wrapping_sub(1));
441            }};
442            ((nn), $data:ident) => {{
443                let addr = self.fetch_u16(ctx);
444                if std::mem::size_of_val(&$data) == 1 {
445                    self.write(ctx, addr, $data as u8);
446                } else {
447                    self.write_u16(ctx, addr, $data as u16);
448                }
449            }};
450        }
451
452        macro_rules! cond {
453            (NZ) => {
454                !self.reg.f.z
455            };
456            (Z) => {
457                self.reg.f.z
458            };
459            (NC) => {
460                !self.reg.f.c
461            };
462            (C) => {
463                self.reg.f.c
464            };
465        }
466
467        macro_rules! gen_mne {
468            (LD SP, HL) => {{
469                self.reg.sp = self.reg.hl();
470                self.tick(ctx);
471            }};
472            (LD $dst:tt, $src:tt) => {{
473                let src = load!($src);
474                store!($dst, src);
475            }};
476            (LDH (n), $src:tt) => {{
477                let addr = 0xFF00 | self.fetch(ctx) as u16;
478                self.write(ctx, addr, load!($src))
479            }};
480            (LDH $dst:tt, (n)) => {{
481                let addr = 0xFF00 | self.fetch(ctx) as u16;
482                let data = self.read(ctx, addr);
483                store!($dst, data)
484            }};
485
486            (PUSH $opr:tt) => {{
487                let data = load!($opr);
488                self.tick(ctx);
489                self.push_u16(ctx, data);
490            }};
491            (POP $opr:tt) => {{
492                let data = self.pop_u16(ctx);
493                store!($opr, data);
494            }};
495
496            (ADD A, $opr:tt) => {{
497                let opr = load!($opr);
498                let (res, overflow) = self.reg.a.overflowing_add(opr);
499                self.reg.f.n = false;
500                self.reg.f.h = (self.reg.a ^ opr ^ res) & 0x10 != 0;
501                self.reg.f.c = overflow;
502                self.reg.f.z = res == 0;
503                self.reg.a = res;
504            }};
505            (ADD HL, $opr:tt) => {{
506                let opr = load!($opr);
507                self.tick(ctx);
508                let dst = self.reg.hl();
509                let (res, overflow) = dst.overflowing_add(opr);
510                self.reg.f.n = false;
511                self.reg.f.h = (opr ^ dst ^ res) & 0x1000 != 0;
512                self.reg.f.c = overflow;
513                self.reg.set_hl(res);
514            }};
515            (ADD SP, $opr:tt) => {{
516                let opr = load!($opr) as i8 as u16;
517                self.tick(ctx);
518                self.tick(ctx);
519                let dst = self.reg.sp;
520                let res = dst.wrapping_add(opr);
521                self.reg.f.z = false;
522                self.reg.f.n = false;
523                self.reg.f.h = (opr ^ dst ^ res) & 0x10 != 0;
524                self.reg.f.c = (opr ^ dst ^ res) & 0x100 != 0;
525                self.reg.sp = res;
526            }};
527            (ADC A, $opr:tt) => {{
528                let opr = load!($opr);
529                let (res, overflow1) = self.reg.a.overflowing_add(opr);
530                let (res, overflow2) = res.overflowing_add(self.reg.f.c as u8);
531                self.reg.f.n = false;
532                self.reg.f.h = (self.reg.a ^ opr ^ res) & 0x10 != 0;
533                self.reg.f.c = overflow1 | overflow2;
534                self.reg.f.z = res == 0;
535                self.reg.a = res;
536            }};
537            (SUB $opr:tt) => {{
538                let opr = load!($opr);
539                let (res, overflow) = self.reg.a.overflowing_sub(opr);
540                self.reg.f.n = true;
541                self.reg.f.h = (self.reg.a ^ opr ^ res) & 0x10 != 0;
542                self.reg.f.c = overflow;
543                self.reg.f.z = res == 0;
544                self.reg.a = res;
545            }};
546            (SBC A, $opr:tt) => {{
547                let opr = load!($opr);
548                let (res, overflow1) = self.reg.a.overflowing_sub(opr);
549                let (res, overflow2) = res.overflowing_sub(self.reg.f.c as u8);
550                self.reg.f.n = true;
551                self.reg.f.h = (self.reg.a ^ opr ^ res) & 0x10 != 0;
552                self.reg.f.c = overflow1 | overflow2;
553                self.reg.f.z = res == 0;
554                self.reg.a = res;
555            }};
556            (CP $opr:tt) => {{
557                let opr = load!($opr);
558                let (res, overflow) = self.reg.a.overflowing_sub(opr);
559                self.reg.f.n = true;
560                self.reg.f.h = (self.reg.a ^ opr ^ res) & 0x10 != 0;
561                self.reg.f.c = overflow;
562                self.reg.f.z = res == 0;
563            }};
564            (AND $opr:tt) => {{
565                let opr = load!($opr);
566                self.reg.a &= opr;
567                self.reg.f.z = self.reg.a == 0;
568                self.reg.f.n = false;
569                self.reg.f.h = true;
570                self.reg.f.c = false;
571            }};
572            (OR $opr:tt) => {{
573                let opr = load!($opr);
574                self.reg.a |= opr;
575                self.reg.f.z = self.reg.a == 0;
576                self.reg.f.n = false;
577                self.reg.f.h = false;
578                self.reg.f.c = false;
579            }};
580            (XOR $opr:tt) => {{
581                let opr = load!($opr);
582                self.reg.a ^= opr;
583                self.reg.f.z = self.reg.a == 0;
584                self.reg.f.n = false;
585                self.reg.f.h = false;
586                self.reg.f.c = false;
587            }};
588
589            (INC $opr:tt) => {{
590                let opr = load!($opr);
591                if std::mem::size_of_val(&opr) == 1 {
592                    let res = opr.wrapping_add(1);
593                    self.reg.f.z = res == 0;
594                    self.reg.f.n = false;
595                    self.reg.f.h = (opr ^ res) & 0x10 != 0;
596                    store!($opr, res);
597                } else {
598                    self.tick(ctx);
599                    let res = opr.wrapping_add(1);
600                    store!($opr, res);
601                }
602            }};
603            (DEC $opr:tt) => {{
604                let opr = load!($opr);
605                if std::mem::size_of_val(&opr) == 1 {
606                    let res = opr.wrapping_sub(1);
607                    self.reg.f.z = res == 0;
608                    self.reg.f.n = true;
609                    self.reg.f.h = (opr ^ res) & 0x10 != 0;
610                    store!($opr, res);
611                } else {
612                    self.tick(ctx);
613                    let res = opr.wrapping_sub(1);
614                    store!($opr, res);
615                }
616            }};
617
618            (SWAP $opr:tt) => {{
619                let opr = load!($opr);
620                let res = opr.rotate_left(4);
621                self.reg.f.z = res == 0;
622                self.reg.f.n = false;
623                self.reg.f.h = false;
624                self.reg.f.c = false;
625                store!($opr, res);
626            }};
627            (DAA) => {{
628                let mut adjust = 0;
629                adjust |= if self.reg.f.c { 0x60 } else { 0 };
630                adjust |= if self.reg.f.h { 0x06 } else { 0 };
631                let res = if !self.reg.f.n {
632                    adjust |= if self.reg.a & 0x0f > 0x09 { 0x06 } else { 0 };
633                    adjust |= if self.reg.a > 0x99 { 0x60 } else { 0 };
634                    self.reg.a.wrapping_add(adjust)
635                } else {
636                    self.reg.a.wrapping_sub(adjust)
637                };
638                self.reg.a = res;
639                self.reg.f.z = res == 0;
640                self.reg.f.h = false;
641                self.reg.f.c = adjust >= 0x60;
642            }};
643            (CPL) => {{
644                self.reg.a ^= 0xff;
645                self.reg.f.n = true;
646                self.reg.f.h = true;
647            }};
648            (CCF) => {{
649                self.reg.f.c = !self.reg.f.c;
650                self.reg.f.n = false;
651                self.reg.f.h = false;
652            }};
653            (SCF) => {{
654                self.reg.f.c = true;
655                self.reg.f.n = false;
656                self.reg.f.h = false;
657            }};
658            (NOP) => {{}};
659            (HALT) => {{
660                self.halting = true;
661                debug!("HALT");
662            }};
663            (STOP) => {{
664                self.halting = true;
665                ctx.stop();
666                debug!("STOP");
667            }};
668            (DI) => {{
669                self.prev_interrupt_enable = false;
670                self.interrupt_master_enable = false;
671            }};
672            (EI) => {{
673                self.interrupt_master_enable = true;
674            }};
675
676            (RLCA) => {
677                // RLCA always reset Z flag
678                // RLC A sets Z flag if result is zero
679                gen_mne!(RLC A, false)
680            };
681            (RLA) => {
682                gen_mne!(RL A, false)
683            };
684            (RRCA) => {
685                gen_mne!(RRC A, false)
686            };
687            (RRA) => {
688                gen_mne!(RR A, false)
689            };
690            (RLC $opr:tt $(, $f:literal)?) => {{
691                let opr = load!($opr);
692                let res = opr.rotate_left(1);
693                self.reg.f.z = res == 0 $(&& $f)*;
694                self.reg.f.n = false;
695                self.reg.f.h = false;
696                self.reg.f.c = (opr & 0x80) != 0;
697                store!($opr, res);
698            }};
699            (RL $opr:tt $(, $f:literal)?) => {{
700                let opr = load!($opr);
701                let res = opr << 1 | self.reg.f.c as u8;
702                self.reg.f.z = res == 0 $(&& $f)*;
703                self.reg.f.n = false;
704                self.reg.f.h = false;
705                self.reg.f.c = (opr & 0x80) != 0;
706                store!($opr, res);
707            }};
708            (RRC $opr:tt $(, $f:literal)?) => {{
709                let opr = load!($opr);
710                let res = opr.rotate_right(1);
711                self.reg.f.z = res == 0 $(&& $f)*;
712                self.reg.f.n = false;
713                self.reg.f.h = false;
714                self.reg.f.c = (opr & 0x01) != 0;
715                store!($opr, res);
716            }};
717            (RR $opr:tt $(, $f:literal)?) => {{
718                let opr = load!($opr);
719                let res = opr >> 1 | (self.reg.f.c as u8) << 7;
720                self.reg.f.z = res == 0 $(&& $f)*;
721                self.reg.f.n = false;
722                self.reg.f.h = false;
723                self.reg.f.c = (opr & 0x01) != 0;
724                store!($opr, res);
725            }};
726            (SLA $opr:tt) => {{
727                let opr = load!($opr);
728                let res = opr << 1;
729                self.reg.f.z = res == 0;
730                self.reg.f.n = false;
731                self.reg.f.h = false;
732                self.reg.f.c = (opr & 0x80) != 0;
733                store!($opr, res);
734            }};
735            (SRA $opr:tt) => {{
736                let opr = load!($opr);
737                let res = opr >> 1 | (opr & 0x80);
738                self.reg.f.z = res == 0;
739                self.reg.f.n = false;
740                self.reg.f.h = false;
741                self.reg.f.c = (opr & 0x01) != 0;
742                store!($opr, res);
743            }};
744            (SRL $opr:tt) => {{
745                let opr = load!($opr);
746                let res = opr >> 1;
747                self.reg.f.z = res == 0;
748                self.reg.f.n = false;
749                self.reg.f.h = false;
750                self.reg.f.c = (opr & 0x01) != 0;
751                store!($opr, res);
752            }};
753            (BIT $bit:literal, $opr:tt) => {{
754                let opr = load!($opr);
755                self.reg.f.z = (opr & (1 << $bit)) == 0;
756                self.reg.f.n = false;
757                self.reg.f.h = true;
758            }};
759            (SET $bit:literal, $opr:tt) => {{
760                let opr = load!($opr);
761                let res = opr | (1 << $bit);
762                store!($opr, res);
763            }};
764            (RES $bit:literal, $opr:tt) => {{
765                let opr = load!($opr);
766                let res = opr & !(1 << $bit);
767                store!($opr, res);
768            }};
769
770            (JP nn) => {{
771                self.reg.pc = load!(nn);
772                self.tick(ctx);
773            }};
774            (JP (HL)) => {{
775                self.reg.pc = self.reg.hl();
776            }};
777            (JP $cc:tt, nn) => {{
778                let addr = load!(nn);
779                if cond!($cc) {
780                    self.reg.pc = addr;
781                    self.tick(ctx);
782                }
783            }};
784            (JR $opr:tt) => {{
785                let r = load!($opr) as u16;
786                self.reg.pc = self.reg.pc.wrapping_add(r);
787                self.tick(ctx);
788            }};
789            (JR $cc:tt, $opr:tt) => {{
790                let r = load!($opr) as u16;
791                if cond!($cc) {
792                    self.reg.pc = self.reg.pc.wrapping_add(r);
793                    self.tick(ctx);
794                }
795            }};
796            (CALL $opr:tt) => {{
797                let addr = load!($opr);
798                self.tick(ctx);
799                self.push_u16(ctx, self.reg.pc);
800                self.reg.pc = addr;
801            }};
802            (CALL $cc:tt, $opr:tt) => {{
803                let addr = load!($opr);
804                if cond!($cc) {
805                    self.tick(ctx);
806                    self.push_u16(ctx, self.reg.pc);
807                    self.reg.pc = addr;
808                }
809            }};
810            (RST $opr:expr) => {{
811                self.tick(ctx);
812                self.push_u16(ctx, self.reg.pc);
813                self.reg.pc = $opr;
814            }};
815
816            (RET) => {{
817                self.reg.pc = self.pop_u16(ctx);
818                self.tick(ctx);
819            }};
820            (RET $cc:tt) => {{
821                self.tick(ctx);
822                if cond!($cc) {
823                    self.reg.pc = self.pop_u16(ctx);
824                    self.tick(ctx);
825                }
826            }};
827            (RETI) => {{
828                self.reg.pc = self.pop_u16(ctx);
829                self.tick(ctx);
830                self.interrupt_master_enable = true;
831            }};
832
833            (UNK) => {
834                panic!("Unknown instruction: ${opc:02X}")
835            };
836
837            (CB) => {
838                instructions_cb!(gen_code_cb)
839            };
840        }
841
842        macro_rules! gen_instr {
843            ($mne:ident []) => {
844                gen_mne!($mne)
845            };
846            ($mne:ident [$opr:tt]) => {{
847                gen_mne!($mne $opr)
848            }};
849            ($mne:ident [$dst:tt, $src:tt]) => {{
850                gen_mne!($mne $dst, $src)
851            }};
852        }
853
854        macro_rules! gen_code {
855            ($($ix:expr => $mne:ident $opr:tt;)*) => {
856                match opc {
857                    $( ConstEval::<{$ix}>::VALUE => gen_instr!($mne $opr), )*
858                }
859            };
860        }
861
862        macro_rules! gen_code_cb {
863            ($($ix:expr => $mne:ident $opr:tt;)*) => {{
864                let opc_cb = self.fetch(ctx);
865                match opc_cb {
866                    $( ConstEval::<{$ix}>::VALUE => gen_instr!($mne $opr), )*
867                }
868            }};
869        }
870
871        instructions!(gen_code);
872    }
873}
874
875impl Cpu {
876    fn tick(&mut self, ctx: &mut impl Context) {
877        self.cycle += 1;
878        ctx.tick();
879    }
880
881    fn read(&mut self, ctx: &mut impl Context, addr: u16) -> u8 {
882        let data = ctx.read(addr);
883        self.tick(ctx);
884        data
885    }
886
887    fn write(&mut self, ctx: &mut impl Context, addr: u16, data: u8) {
888        ctx.write(addr, data);
889        self.tick(ctx);
890    }
891
892    fn write_u16(&mut self, ctx: &mut impl Context, addr: u16, data: u16) {
893        self.write(ctx, addr, (data & 0xFF) as u8);
894        self.write(ctx, addr.wrapping_add(1), (data >> 8) as u8);
895    }
896
897    fn fetch(&mut self, ctx: &mut impl Context) -> u8 {
898        let ret = self.read(ctx, self.reg.pc);
899        self.reg.pc += 1;
900        ret
901    }
902
903    fn fetch_u16(&mut self, ctx: &mut impl Context) -> u16 {
904        let lo = self.fetch(ctx);
905        let hi = self.fetch(ctx);
906        lo as u16 | (hi as u16) << 8
907    }
908
909    fn push(&mut self, ctx: &mut impl Context, data: u8) {
910        self.reg.sp -= 1;
911        self.write(ctx, self.reg.sp, data);
912    }
913
914    fn push_u16(&mut self, ctx: &mut impl Context, data: u16) {
915        self.push(ctx, (data >> 8) as u8);
916        self.push(ctx, (data & 0xFF) as u8);
917    }
918
919    fn pop(&mut self, ctx: &mut impl Context) -> u8 {
920        let ret = self.read(ctx, self.reg.sp);
921        self.reg.sp += 1;
922        ret
923    }
924
925    fn pop_u16(&mut self, ctx: &mut impl Context) -> u16 {
926        let lo = self.pop(ctx);
927        let hi = self.pop(ctx);
928        lo as u16 | (hi as u16) << 8
929    }
930}
931
932impl Cpu {
933    fn trace(&mut self, ctx: &mut impl Context, pc: u16, opc: u8) {
934        let opr1 = ctx.read_immutable(pc.wrapping_add(1));
935        let opr2 = ctx.read_immutable(pc.wrapping_add(2));
936
937        let (asm, op_len) = disasm(pc, opc, opr1, opr2);
938
939        let tos = |mb: Option<u8>| mb.map_or("??".to_string(), |x| format!("{x:02X}"));
940        let bytes = match op_len {
941            1 => format!("{:02X}", opc),
942            2 => format!("{:02X} {}", opc, tos(opr1)),
943            3 => format!("{:02X} {} {}", opc, tos(opr1), tos(opr2)),
944            _ => unreachable!(),
945        };
946
947        use crate::consts::*;
948
949        trace!(
950            "{pc:04X}: {bytes:8} | {asm:20} | \
951            A:{a:02X} B:{b:02X} C:{c:02X} D:{d:02X} E:{e:02X} H:{h:02X} L:{l:02X} \
952            SP:{sp:04X} F:{zf}{nf}{hf}{cf} IME:{ime} IE:{ie:02X} IF:{inf:02X} CYC:{frm}:{ly:03}:{lx:03}",
953            a = self.reg.a,
954            b = self.reg.b,
955            c = self.reg.c,
956            d = self.reg.d,
957            e = self.reg.e,
958            h = self.reg.h,
959            l = self.reg.l,
960            sp = self.reg.sp,
961            zf = if self.reg.f.z { 'Z' } else { '.' },
962            nf = if self.reg.f.n { 'N' } else { '.' },
963            hf = if self.reg.f.h { 'H' } else { '.' },
964            cf = if self.reg.f.c { 'C' } else { '.' },
965            ime = self.interrupt_master_enable as u8,
966            ie = ctx.interrupt_enable(),
967            inf = ctx.interrupt_flag(),
968            frm = self.cycle / CPU_CLOCK_PER_LINE / LINES_PER_FRAME,
969            ly = self.cycle / CPU_CLOCK_PER_LINE % LINES_PER_FRAME,
970            lx = self.cycle % CPU_CLOCK_PER_LINE,
971        );
972    }
973}
974
975#[rustfmt::skip]
976const HWREG_NAME: &[(u16, &str)] = &[
977    (0xFF00, "P1"), (0xFF01, "SB"), (0xFF02, "SC"),
978    (0xFF04, "DIV"), (0xFF05, "TIMA"), (0xFF06, "TMA"), (0xFF07, "TAC"), (0xFF0F, "IF"),
979
980    (0xFF10, "NR10"), (0xFF11, "NR11"), (0xFF12, "NR12"), (0xFF13, "NR13"), (0xFF14, "NR14"),
981    (0xFF16, "NR21"), (0xFF17, "NR22"), (0xFF18, "NR23"), (0xFF19, "NR24"),
982    (0xFF1A, "NR30"), (0xFF1B, "NR31"), (0xFF1C, "NR32"), (0xFF1D, "NR33"), (0xFF1E, "NR34"),
983    (0xFF20, "NR41"), (0xFF21, "NR42"), (0xFF22, "NR43"), (0xFF23, "NR44"),
984    (0xFF24, "NR50"), (0xFF25, "NR51"), (0xFF26, "NR52"),
985
986    (0xFF40, "LCDC"), (0xFF41, "STAT"), (0xFF42, "SCY"), (0xFF43, "SCX"),
987    (0xFF44, "LY"), (0xFF45, "LYC"), (0xFF46, "DMA"), (0xFF47, "BGP"),
988    (0xFF48, "OBP0"), (0xFF49, "OBP1"), (0xFF4A, "WY"), (0xFF4B, "WX"), 
989
990    (0xFF4D, "KEY1"), (0xFF4F, "VBK"), (0xFF50, "BOOT"),
991    (0xFF51, "HDMA1"), (0xFF52, "HDMA2"), (0xFF53, "HDMA3"), (0xFF54, "HDMA4"), (0xFF55, "HDMA5"),
992    (0xFF56, "RP"),
993    
994    (0xFF68, "BCPS"), (0xFF69, "BCPD"), (0xFF6A, "OCPS"), (0xFF6B, "OCPD"),
995    (0xFF70, "SVBK"), (0xFF76, "PCM12"), (0xFF77, "PCM34"),
996    
997    (0xFFFF, "IE"),
998];
999
1000fn hwreg_name(addr: u8) -> Option<&'static str> {
1001    HWREG_NAME
1002        .iter()
1003        .find(|r| addr as u16 | 0xFF00 == r.0)
1004        .map(|r| r.1)
1005}
1006
1007fn disasm(pc: u16, opc: u8, opr1: Option<u8>, opr2: Option<u8>) -> (String, usize) {
1008    let opc = opc;
1009    let opr1 = opr1;
1010    let opr2 = opr2;
1011    let mut bytes = 1;
1012
1013    macro_rules! gen_opr {
1014        ((^HL)) => {
1015            "(HL+)"
1016        };
1017        ((-HL)) => {
1018            "(HL-)"
1019        };
1020
1021        (SPn) => {{
1022            bytes += 1;
1023            opr1.map_or_else(|| "SP+??".to_string(), |opr| format!("SP{:+}", opr as i8))
1024        }};
1025
1026        (n) => {{
1027            bytes += 1;
1028            opr1.map_or_else(|| "$??".to_string(), |opr| format!("${opr:02X}"))
1029        }};
1030        ((n)) => {{
1031            bytes += 1;
1032            opr1.map_or_else(
1033                || "($??)".to_string(),
1034                |opr| {
1035                    hwreg_name(opr).map_or_else(
1036                        || format!("(${opr:02X})"),
1037                        |name| format!("(<{name}=${opr:02X})"),
1038                    )
1039                },
1040            )
1041        }};
1042        (r8) => {{
1043            bytes += 1;
1044            opr1.map_or_else(
1045                || "$????".to_string(),
1046                |opr| format!("${:04X}", pc.wrapping_add(2).wrapping_add(opr as i8 as u16)),
1047            )
1048        }};
1049        (nn) => {{
1050            bytes += 2;
1051            opr1.and_then(|opr1| opr2.map(|opr2| format!("${:02X}{:02X}", opr2, opr1)))
1052                .unwrap_or_else(|| "$????".to_string())
1053        }};
1054        ((nn)) => {{
1055            bytes += 2;
1056            opr1.and_then(|opr1| opr2.map(|opr2| format!("(${:02X}{:02X})", opr2, opr1)))
1057                .unwrap_or_else(|| "($????)".to_string())
1058        }};
1059
1060        ($n:literal) => {
1061            format!("{:02X}H", $n)
1062        };
1063
1064        ($opr:ident) => {
1065            stringify!($opr)
1066        };
1067        (($opr:ident)) => {
1068            stringify!(($opr))
1069        };
1070    }
1071
1072    macro_rules! gen_disasm {
1073        ($($ix:expr => $mne:ident $opr:tt;)*) => {
1074            match opc {
1075                $( ConstEval::<{$ix}>::VALUE => {
1076                    let asm = gen_disasm!(@generate: $mne $opr);
1077                    (asm, bytes)
1078                })*
1079            }
1080        };
1081
1082        (@generate: CB []) => {
1083            instructions_cb!(gen_disasm_cb)
1084        };
1085
1086        (@generate: $mne:ident []) => {
1087            stringify!($mne).to_string()
1088        };
1089        (@generate: $mne:ident [$opr:tt]) => {
1090            format!("{} {}", stringify!($mne), gen_opr!($opr))
1091        };
1092        (@generate: $mne:ident [$dst:tt, $src:tt]) => {
1093            format!("{} {}, {}", stringify!($mne), gen_opr!($dst), gen_opr!($src))
1094        };
1095    }
1096
1097    macro_rules! gen_disasm_cb {
1098        ($($ix:expr => $mne:ident $opr:tt;)*) => {{
1099            bytes += 1;
1100            match opr1 {
1101                $( Some(ConstEval::<{$ix}>::VALUE) => {
1102                    gen_disasm_cb!(@generate: $mne $opr)
1103                })*
1104                None => format!("???"),
1105            }
1106        }};
1107
1108        (@generate: $mne:ident [$opr:tt]) => {
1109            format!("{} {}", stringify!($mne), gen_opr!($opr))
1110        };
1111        (@generate: $mne:ident [$n:literal, $opr:tt]) => {
1112            format!("{} {}, {}", stringify!($mne), $n, gen_opr!($opr))
1113        };
1114    }
1115
1116    instructions!(gen_disasm)
1117}