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 NOP; LD BC,nn; LD (BC),A; INC BC; INC B; DEC B; LD B,n; RLCA;
107 LD (nn),SP; ADD HL,BC; LD A,(BC); DEC BC; INC C; DEC C; LD C,n; RRCA;
108 STOP; LD DE,nn; LD (DE),A; INC DE; INC D; DEC D; LD D,n; RLA;
109 JR r8; ADD HL,DE; LD A,(DE); DEC DE; INC E; DEC E; LD E,n; RRA;
110 JR NZ,r8; LD HL,nn; LD (^HL),A; INC HL; INC H; DEC H; LD H,n; DAA;
111 JR Z,r8; ADD HL,HL; LD A,(^HL); DEC HL; INC L; DEC L; LD L,n; CPL;
112 JR NC,r8; LD SP,nn; LD (-HL),A; INC SP; INC (HL); DEC (HL); LD (HL),n; SCF;
113 JR C,r8; ADD HL,SP; LD A,(-HL); DEC SP; INC A; DEC A; LD A,n; CCF;
114 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 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 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 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 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 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 LD (HL),B; LD (HL),C; LD (HL),D; LD (HL),E; LD (HL),H; LD (HL),L; HALT; LD (HL),A;
121 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 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 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 SUB B; SUB C; SUB D; SUB E; SUB H; SUB L; SUB (HL); SUB A;
125 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 AND B; AND C; AND D; AND E; AND H; AND L; AND (HL); AND A;
127 XOR B; XOR C; XOR D; XOR E; XOR H; XOR L; XOR (HL); XOR A;
128 OR B; OR C; OR D; OR E; OR H; OR L; OR (HL); OR A;
129 CP B; CP C; CP D; CP E; CP H; CP L; CP (HL); CP A;
130 RET NZ; POP BC; JP NZ,nn; JP nn; CALL NZ,nn; PUSH BC; ADD A,n; RST 0x00;
131 RET Z; RET; JP Z,nn; CB; CALL Z,nn; CALL nn; ADC A,n; RST 0x08;
132 RET NC; POP DE; JP NC,nn; UNK; CALL NC,nn; PUSH DE; SUB n; RST 0x10;
133 RET C; RETI; JP C,nn; UNK; CALL C,nn; UNK; SBC A,n; RST 0x18;
134 LDH (n),A; POP HL; LD (C),A; UNK; UNK; PUSH HL; AND n; RST 0x20;
135 ADD SP,n; JP (HL); LD (nn),A; UNK; UNK; UNK; XOR n; RST 0x28;
136 LDH A,(n); POP AF; LD A,(C); DI; UNK; PUSH AF; OR n; RST 0x30;
137 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 RLC B; RLC C; RLC D; RLC E; RLC H; RLC L; RLC (HL); RLC A;
146 RRC B; RRC C; RRC D; RRC E; RRC H; RRC L; RRC (HL); RRC A;
147 RL B; RL C; RL D; RL E; RL H; RL L; RL (HL); RL A;
148 RR B; RR C; RR D; RR E; RR H; RR L; RR (HL); RR A;
149 SLA B; SLA C; SLA D; SLA E; SLA H; SLA L; SLA (HL); SLA A;
150 SRA B; SRA C; SRA D; SRA E; SRA H; SRA L; SRA (HL); SRA A;
151 SWAP B; SWAP C; SWAP D; SWAP E; SWAP H; SWAP L; SWAP (HL); SWAP A;
152 SRL B; SRL C; SRL D; SRL E; SRL H; SRL L; SRL (HL); SRL A;
153 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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}