1mod ld_tests;
2mod control_tests;
3mod alu_tests;
4mod jump_branch_tests;
5use crate::ram::{self, Ram};
6
7type Reg = usize;
8const REG_A:Reg = 0;
9const REG_B:Reg = 1;
10const REG_C:Reg = 2;
11const REG_D:Reg = 3;
12const REG_E:Reg = 4;
13const REG_F:Reg = 5;
14const REG_H:Reg = 6;
15const REG_L:Reg = 7;
16
17type Flag = u8;
20const FLAG_Z:Flag = 7;
21const FLAG_N:Flag = 6;
22const FLAG_H:Flag = 5;
23const FLAG_C:Flag = 4;
24
25const ZERO_INSTRUCTION_TIME_TABLE:[u8;0x100] = [1,3,2,2,1,1,2,1,5,2,2,2,1,1,2,1,
27 1,3,2,2,1,1,2,1,3,2,2,2,1,1,2,1,
28 2,3,2,2,1,1,2,1,2,2,2,2,1,1,2,1,
29 2,3,2,2,3,3,3,1,2,2,2,2,1,1,2,1,
30 1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,
31 1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,
32 1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,
33 2,2,2,2,2,2,1,2,1,1,1,1,1,1,2,1,
34 1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,
35 1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,
36 1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,
37 1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,
38 2,3,3,4,3,4,2,4,2,4,3,1,3,6,2,4,
39 1,3,3,0,3,4,2,4,2,4,3,0,3,0,2,4,
40 3,3,2,0,0,4,2,4,4,1,4,0,0,0,2,4,
41 3,3,2,1,0,4,2,4,3,2,4,1,0,0,2,4];
42
43const CB_INSTRUCTION_TIME_TABLE:[u8;0x100] = [2,2,2,2,2,2,4,2,2,2,2,2,2,2,4,2,
45 2,2,2,2,2,2,4,2,2,2,2,2,2,2,4,2,
46 2,2,2,2,2,2,4,2,2,2,2,2,2,2,4,2,
47 2,2,2,2,2,2,4,2,2,2,2,2,2,2,4,2,
48 2,2,2,2,2,2,3,2,2,2,2,2,2,2,3,2,
49 2,2,2,2,2,2,3,2,2,2,2,2,2,2,3,2,
50 2,2,2,2,2,2,3,2,2,2,2,2,2,2,3,2,
51 2,2,2,2,2,2,3,2,2,2,2,2,2,2,3,2,
52 2,2,2,2,2,2,4,2,2,2,2,2,2,2,4,2,
53 2,2,2,2,2,2,4,2,2,2,2,2,2,2,4,2,
54 2,2,2,2,2,2,4,2,2,2,2,2,2,2,4,2,
55 2,2,2,2,2,2,4,2,2,2,2,2,2,2,4,2,
56 2,2,2,2,2,2,4,2,2,2,2,2,2,2,4,2,
57 2,2,2,2,2,2,4,2,2,2,2,2,2,2,4,2,
58 2,2,2,2,2,2,4,2,2,2,2,2,2,2,4,2,
59 2,2,2,2,2,2,4,2,2,2,2,2,2,2,4,2];
60
61#[derive(Clone, Copy)]
62pub struct ProgramCounter
63{
64 pub reg: u16,
65 pub should_increment: bool,
66 pub current_instruction_width: u16,
67 pub current_instruction_cycles: u8
68}
69
70pub struct Cpu
71{
72 regs: [u8;8],
73 sp: u16,
74 pc: ProgramCounter,
75 ime: bool,
76 pub halted: bool,
77 pub stopped: bool
78}
79
80impl Cpu
81{
82 pub fn new() -> Cpu
83 {
84 Cpu
85 {
86 regs: [0x01, 0x00, 0x13, 0x00, 0xD8, 0xB0, 0x01, 0x4D],
87 sp: 0,
88 pc: ProgramCounter
89 {
90 reg: 0, should_increment: true, current_instruction_width: 1, current_instruction_cycles: 0
91 },
92 ime: false,
93 halted: false,
94 stopped: false
95 }
96 }
97 fn aux_read_flag(&self, param: Flag) -> bool
105 {
106 (self.regs[REG_F] & 1 << param) != 0
107 }
108
109 fn aux_write_flag(&mut self, param: Flag, data: bool)
110 {
111 if data
112 {
113 self.regs[REG_F] = self.regs[REG_F] | (1 << param);
114 }
115 else
116 {
117 self.regs[REG_F] = self.regs[REG_F] & (!(1 << param));
118 }
119 }
120
121 fn halt(&mut self)
122 {
123 self.halted = true;
124 }
125
126 fn stop(&mut self)
127 {
128 self.halted = true;
129 self.stopped = true;
130 }
131
132 fn ld_r16_16(&mut self, msh_reg: Reg, lsh_reg: Reg, msh_num: u8, lsh_num: u8)
133 {
134 self.regs[msh_reg] = msh_num;
135 self.regs[lsh_reg] = lsh_num;
136 }
137
138 fn ld_hl_sp_plus(&mut self, p1: i8)
139 {
140 let conv = p1.unsigned_abs() as u16;
141 let negative = p1 < 0;
142 if negative
143 {
144 let bytes = u16::to_le_bytes(self.sp - conv);
145 self.regs[REG_H] = bytes[1];
146 self.regs[REG_L] = bytes[0];
147 }
148 else
149 {
150 let bytes = u16::to_le_bytes(self.sp + conv);
151 self.regs[REG_H] = bytes[1];
152 self.regs[REG_L] = bytes[0];
153 }
154 }
155
156 fn ld_sp_16(&mut self, msh_num: u8, lsh_num: u8)
157 {
158 self.sp = u16::from_le_bytes([lsh_num, msh_num]);
159 }
160
161 fn ld_r8_8(&mut self, p1: Reg, p2: u8)
162 {
163 self.regs[p1] = p2;
164 }
165
166 fn ld_r16a_8(&mut self, ram: &mut Ram, msh: Reg, lsh: Reg, p2: u8)
167 {
168 ram.write_rp(self.regs[msh], self.regs[lsh], p2);
169 }
170
171 fn ld_16a_r8(&mut self, ram: &mut Ram, msh: u8, lsh: u8, p2: Reg)
172 {
173 ram.write_rp(msh, lsh, self.regs[p2]);
174 }
175
176 fn ld_16a_sp(&mut self, ram: &mut Ram, msh: u8, lsh: u8)
177 {
178 let bytes = self.sp.to_le_bytes();
179 ram.write_rp(msh, lsh, bytes[0]);
180
181 let result = self.aux_inc_16(msh, lsh);
182 ram.write_rp(result.1, result.0, bytes[1]);
183 }
184
185 fn ld_r8_r8(&mut self, p1: Reg, p2: Reg)
186 {
187 self.regs[p1] = self.regs[p2];
188 }
189
190 fn ld_sp_r16(&mut self, msh: Reg, lsh: Reg)
191 {
192 self.sp = u16::from_le_bytes([self.regs[lsh], self.regs[msh]]);
193 }
194
195 fn ld_r8_r16a(&mut self, ram: &mut Ram, p1: Reg, msh: Reg, lsh: Reg)
196 {
197 let x = ram.read_rp(self.regs[msh], self.regs[lsh]);
198 self.regs[p1] = x;
199 }
200
201 fn ld_r8_16a(&mut self, ram: &mut Ram, p1: Reg, msh: u8, lsh: u8)
202 {
203 let x = ram.read_rp(msh, lsh);
204 self.regs[p1] = x;
205 }
206
207 fn ld_r16a_r8(&mut self, ram: &mut Ram, msh: Reg, lsh: Reg, p2: Reg)
208 {
209 ram.write_rp(self.regs[msh], self.regs[lsh], self.regs[p2]);
210 }
211
212 fn aux_inc_16(&mut self, msh: u8, lsh: u8) -> (u8, u8)
216 {
217 let lsh_result = u8::overflowing_add(lsh, 1);
218 let msh_result = u8::overflowing_add(msh, lsh_result.1 as u8);
219 (lsh_result.0, msh_result.0)
220 }
221
222 fn inc_r16(&mut self, msh: Reg, lsh: Reg)
223 {
224 let lsh_result = u8::overflowing_add(self.regs[lsh], 1);
225 self.regs[lsh] = lsh_result.0;
226 let msh_result = u8::overflowing_add(self.regs[msh], lsh_result.1 as u8);
227 self.regs[msh] = msh_result.0;
228 }
229
230 fn inc_sp(&mut self)
231 {
232 let result = u16::overflowing_add(self.sp, 1);
233 self.sp = result.0;
234 }
235
236 fn inc_r8(&mut self, reg: Reg)
237 {
238 let result = u8::overflowing_add(self.regs[reg], 1);
239 self.regs[reg] = result.0;
240
241 self.aux_write_flag(FLAG_Z, result.0 == 0);
242 self.aux_write_flag(FLAG_N, false);
243 self.aux_write_flag(FLAG_H, result.1);
244 }
245
246 fn inc_r16a(&mut self, ram: &mut Ram, msh: Reg, lsh: Reg)
247 {
248 let result = ram.read_rp(
249 self.regs[msh], self.regs[lsh]).overflowing_add(1);
250 ram.write_rp(self.regs[msh], self.regs[lsh], result.0);
251
252 self.aux_write_flag(FLAG_Z, result.0 == 0);
253 self.aux_write_flag(FLAG_N, false);
254 self.aux_write_flag(FLAG_H, result.1);
255 }
256
257 fn dec_r8(&mut self, reg: Reg)
258 {
259 let result = u8::overflowing_sub(self.regs[reg], 1);
260 self.regs[reg] = result.0;
261
262 self.aux_write_flag(FLAG_Z, result.0 == 0);
263 self.aux_write_flag(FLAG_N, true);
264 self.aux_write_flag(FLAG_H, result.1);
265 }
266
267 fn dec_r16a(&mut self, ram: &mut Ram, msh: Reg, lsh: Reg)
268 {
269 let result = ram.read_rp(
270 self.regs[msh], self.regs[lsh]).overflowing_sub(1);
271 ram.write_rp(self.regs[msh], self.regs[lsh], result.0);
272
273 self.aux_write_flag(FLAG_Z, result.0 == 0);
274 self.aux_write_flag(FLAG_N, true);
275 self.aux_write_flag(FLAG_H, result.1);
276 }
277
278 fn dec_r16(&mut self, msh: Reg, lsh: Reg)
279 {
280 let lsh_result = u8::overflowing_sub(self.regs[lsh], 1);
281 self.regs[lsh] = lsh_result.0;
282 let msh_result = u8::overflowing_sub(self.regs[msh], lsh_result.1 as u8);
283 self.regs[msh] = msh_result.0;
284 }
285
286 fn dec_sp(&mut self)
287 {
288 let result = u16::overflowing_sub(self.sp, 1);
289 self.sp = result.0;
290 }
291
292 fn add_r8_r8(&mut self, p1: Reg, p2: Reg)
293 {
294 let half_carry_pre = ((self.regs[p1] ^ self.regs[p2]) >> 4) & 1;
295 let result = self.regs[p1].overflowing_add(self.regs[p2]);
296 self.regs[p1] = result.0;
297 let half_carry_post = (result.0 >> 4) & 1;
298
299 self.aux_write_flag(FLAG_Z, result.0 == 0);
300 self.aux_write_flag(FLAG_H, half_carry_pre != half_carry_post);
301 self.aux_write_flag(FLAG_N, false);
302 self.aux_write_flag(FLAG_C, result.1);
303 }
304
305 fn add_r8_8(&mut self, p1: Reg, p2: u8)
306 {
307 let half_carry_pre = ((self.regs[p1] ^ p2) >> 4) & 1;
308 let result = self.regs[p1].overflowing_add(p2);
309 self.regs[p1] = result.0;
310 let half_carry_post = (result.0 >> 4) & 1;
311
312 self.aux_write_flag(FLAG_Z, result.0 == 0);
313 self.aux_write_flag(FLAG_H, half_carry_pre != half_carry_post);
314 self.aux_write_flag(FLAG_N, false);
315 self.aux_write_flag(FLAG_C, result.1);
316 }
317
318 fn add_r16_r16(&mut self, p1_msh: Reg, p1_lsh: Reg, p2_msh: Reg, p2_lsh: Reg)
319 {
320 let z = self.aux_read_flag(FLAG_Z);
321 self.add_r8_r8(p1_lsh, p2_lsh);
322 self.adc_r8_r8(p1_msh, p2_msh);
323
324 self.aux_write_flag(FLAG_Z, z);
325 self.aux_write_flag(FLAG_N, false);
326 }
327
328 fn add_r16_sp(&mut self, p1_msh: Reg, p1_lsh: Reg)
329 {
330 let z = self.aux_read_flag(FLAG_Z);
331 let reg = self.sp.to_le_bytes();
332
333 let result = self.regs[p1_lsh].overflowing_add(reg[0]);
335 self.regs[p1_lsh] = result.0;
336 self.aux_write_flag(FLAG_C, result.1);
337
338 let carry = self.aux_read_flag(FLAG_C) as u8;
340 let half_carry_pre1 = ((self.regs[p1_msh] ^ reg[1]) >> 4) & 1;
341 let result1 = self.regs[p1_msh].overflowing_add(reg[1]);
342 let half_carry_post1 = (result1.0 >> 4) & 1;
343 let half_carry_pre2 = ((result1.0 ^ carry) >> 4) & 1;
344 let result2 = result1.0.overflowing_add(carry);
345 self.regs[p1_msh] = result2.0;
346 let half_carry_post2 = (result2.0 >> 4) & 1;
347
348 self.aux_write_flag(FLAG_H, half_carry_pre1 != half_carry_post1 || half_carry_pre2 != half_carry_post2);
349 self.aux_write_flag(FLAG_N, false);
350 self.aux_write_flag(FLAG_C, result1.1 || result2.1);
351 self.aux_write_flag(FLAG_Z, z);
352 }
353
354 fn add_r8_r16a(&mut self, ram: &mut Ram, p1: Reg, msh: Reg, lsh: Reg)
355 {
356 let p2 = ram.read_rp(self.regs[msh], self.regs[lsh]);
357 let half_carry_pre = ((self.regs[p1] ^ p2) >> 4) & 1;
358 let result = self.regs[p1].overflowing_add(p2);
359 self.regs[p1] = result.0;
360 let half_carry_post = (result.0 >> 4) & 1;
361
362 self.aux_write_flag(FLAG_Z, result.0 == 0);
363 self.aux_write_flag(FLAG_H, half_carry_pre == half_carry_post);
364 self.aux_write_flag(FLAG_N, false);
365 self.aux_write_flag(FLAG_C, result.1);
366 }
367
368 fn add_sp_i8(&mut self, p1: i8)
369 {
370 let conv = p1.unsigned_abs() as u16;
371 let negative = p1 < 0;
372 if negative
373 {
374 self.sp -= conv;
375 }
376 else
377 {
378 self.sp += conv;
379 }
380 }
381
382 fn adc_r8_r8(&mut self, p1: Reg, p2: Reg)
383 {
384 let carry = self.aux_read_flag(FLAG_C) as u8;
385 let half_carry_pre1 = ((self.regs[p1] ^ self.regs[p2]) >> 4) & 1;
386 let result1 = self.regs[p1].overflowing_add(self.regs[p2]);
387 let half_carry_post1 = (result1.0 >> 4) & 1;
388 let half_carry_pre2 = ((result1.0 ^ carry) >> 4) & 1;
389 let result2 = result1.0.overflowing_add(carry);
390 self.regs[p1] = result2.0;
391 let half_carry_post2 = (result2.0 >> 4) & 1;
392
393 self.aux_write_flag(FLAG_Z, result2.0 == 0);
394 self.aux_write_flag(FLAG_H, half_carry_pre1 != half_carry_post1 || half_carry_pre2 != half_carry_post2);
395 self.aux_write_flag(FLAG_N, false);
396 self.aux_write_flag(FLAG_C, result1.1 || result2.1);
397 }
398
399 fn adc_r8_8(&mut self, p1: Reg, p2: u8)
400 {
401 let carry = self.aux_read_flag(FLAG_C) as u8;
402 let half_carry_pre1 = ((self.regs[p1] ^ p2) >> 4) & 1;
403 let result1 = self.regs[p1].overflowing_add(p2);
404 let half_carry_post1 = (result1.0 >> 4) & 1;
405 let half_carry_pre2 = ((result1.0 ^ carry) >> 4) & 1;
406 let result2 = result1.0.overflowing_add(carry);
407 self.regs[p1] = result2.0;
408 let half_carry_post2 = (result2.0 >> 4) & 1;
409
410 self.aux_write_flag(FLAG_Z, result2.0 == 0);
411 self.aux_write_flag(FLAG_H, half_carry_pre1 != half_carry_post1 || half_carry_pre2 != half_carry_post2);
412 self.aux_write_flag(FLAG_N, false);
413 self.aux_write_flag(FLAG_C, result1.1 || result2.1);
414 }
415
416 fn adc_r8_r16a(&mut self, ram: &mut Ram, p1: Reg, msh: Reg, lsh: Reg)
417 {
418 let carry = self.aux_read_flag(FLAG_C) as u8;
419 let p2 = ram.read_rp(self.regs[msh], self.regs[lsh]);
420 let half_carry_pre1 = ((self.regs[p1] ^ p2) >> 4) & 1;
421 let result1 = self.regs[p1].overflowing_add(p2);
422 let half_carry_post1 = (result1.0 >> 4) & 1;
423 let half_carry_pre2 = ((result1.0 ^ carry) >> 4) & 1;
424 let result2 = result1.0.overflowing_add(carry);
425 self.regs[p1] = result2.0;
426 let half_carry_post2 = (result2.0 >> 4) & 1;
427
428 self.aux_write_flag(FLAG_Z, result2.0 == 0);
429 self.aux_write_flag(FLAG_H, half_carry_pre1 != half_carry_post1 || half_carry_pre2 != half_carry_post2);
430 self.aux_write_flag(FLAG_N, false);
431 self.aux_write_flag(FLAG_C, result1.1 || result2.1);
432 }
433
434 fn sub_r8_r8(&mut self, p1: Reg, p2: Reg)
436 {
437 let half_carry_pre = ((self.regs[p1] ^ self.regs[p2]) >> 4) & 1;
438 let result = self.regs[p1].overflowing_sub(self.regs[p2]);
439 self.regs[p1] = result.0;
440 let half_carry_post = (result.0 >> 4) & 1;
441
442 self.aux_write_flag(FLAG_Z, result.0 == 0);
443 self.aux_write_flag(FLAG_H, half_carry_pre != half_carry_post);
444 self.aux_write_flag(FLAG_N, true);
445 self.aux_write_flag(FLAG_C, result.1);
446 }
447
448 fn sub_r8_8(&mut self, p1: Reg, p2: u8)
449 {
450 let half_carry_pre = ((self.regs[p1] ^ p2) >> 4) & 1;
451 let result = self.regs[p1].overflowing_sub(p2);
452 self.regs[p1] = result.0;
453 let half_carry_post = (result.0 >> 4) & 1;
454
455 self.aux_write_flag(FLAG_Z, result.0 == 0);
456 self.aux_write_flag(FLAG_H, half_carry_pre != half_carry_post);
457 self.aux_write_flag(FLAG_N, true);
458 self.aux_write_flag(FLAG_C, result.1);
459 }
460
461 fn sub_r8_r16a(&mut self, ram: &mut Ram, p1: Reg, msh: Reg, lsh: Reg)
462 {
463 let p2 = ram.read_rp(self.regs[msh], self.regs[lsh]);
464 let half_carry_pre = ((self.regs[p1] ^ p2) >> 4) & 1;
465 let result = self.regs[p1].overflowing_add(p2);
466 self.regs[p1] = result.0;
467 let half_carry_post = (result.0 >> 4) & 1;
468
469 self.aux_write_flag(FLAG_Z, result.0 == 0);
470 self.aux_write_flag(FLAG_H, half_carry_pre != half_carry_post);
471 self.aux_write_flag(FLAG_N, true);
472 self.aux_write_flag(FLAG_C, result.1);
473 }
474
475 fn sbc_r8_r8(&mut self, p1: Reg, p2: Reg)
476 {
477 let carry = self.aux_read_flag(FLAG_C) as u8;
478 let half_carry_pre1 = ((self.regs[p1] ^ self.regs[p2]) >> 4) & 1;
479 let result1 = self.regs[p1].overflowing_sub(self.regs[p2]);
480 let half_carry_post1 = (result1.0 >> 4) & 1;
481 let half_carry_pre2 = ((result1.0 ^ carry) >> 4) & 1;
482 let result2 = result1.0.overflowing_sub(carry);
483 self.regs[p1] = result2.0;
484 let half_carry_post2 = (result2.0 >> 4) & 1;
485
486 self.aux_write_flag(FLAG_Z, result2.0 == 0);
487 self.aux_write_flag(FLAG_H, half_carry_pre1 != half_carry_post1 || half_carry_pre2 != half_carry_post2);
488 self.aux_write_flag(FLAG_N, true);
489 self.aux_write_flag(FLAG_C, result1.1 || result2.1);
490 }
491
492 fn sbc_r8_8(&mut self, p1: Reg, p2: u8)
493 {
494 let carry = self.aux_read_flag(FLAG_C) as u8;
495 let half_carry_pre1 = ((self.regs[p1] ^ p2) >> 4) & 1;
496 let result1 = self.regs[p1].overflowing_sub(p2);
497 let half_carry_post1 = (result1.0 >> 4) & 1;
498 let half_carry_pre2 = ((result1.0 ^ carry) >> 4) & 1;
499 let result2 = result1.0.overflowing_sub(carry);
500 self.regs[p1] = result2.0;
501 let half_carry_post2 = (result2.0 >> 4) & 1;
502
503 self.aux_write_flag(FLAG_Z, result2.0 == 0);
504 self.aux_write_flag(FLAG_H, half_carry_pre1 != half_carry_post1 || half_carry_pre2 != half_carry_post2);
505 self.aux_write_flag(FLAG_N, true);
506 self.aux_write_flag(FLAG_C, result1.1 || result2.1);
507 }
508
509 fn sbc_r8_r16a(&mut self, ram: &mut Ram, p1: Reg, msh: Reg, lsh: Reg)
510 {
511 let carry = self.aux_read_flag(FLAG_C) as u8;
512 let p2 = ram.read_rp(self.regs[msh], self.regs[lsh]);
513 let half_carry_pre1 = ((self.regs[p1] ^ p2) >> 4) & 1;
514 let result1 = self.regs[p1].overflowing_sub(p2);
515 let half_carry_post1 = (result1.0 >> 4) & 1;
516 let half_carry_pre2 = ((result1.0 ^ carry) >> 4) & 1;
517 let result2 = result1.0.overflowing_sub(carry);
518 self.regs[p1] = result2.0;
519 let half_carry_post2 = (result2.0 >> 4) & 1;
520
521 self.aux_write_flag(FLAG_Z, result2.0 == 0);
522 self.aux_write_flag(FLAG_H, half_carry_pre1 != half_carry_post1 || half_carry_pre2 != half_carry_post2);
523 self.aux_write_flag(FLAG_N, true);
524 self.aux_write_flag(FLAG_C, result1.1 || result2.1);
525 }
526
527 fn and_r8_r8(&mut self, p1: Reg, p2: Reg)
528 {
529 self.regs[p1] &= self.regs[p2];
530
531 self.aux_write_flag(FLAG_Z, self.regs[p1] == 0);
532 self.aux_write_flag(FLAG_H, true);
533 self.aux_write_flag(FLAG_N, false);
534 self.aux_write_flag(FLAG_C, false);
535 }
536
537 fn and_r8_8(&mut self, p1: Reg, p2: u8)
538 {
539 self.regs[p1] &= p2;
540
541 self.aux_write_flag(FLAG_Z, self.regs[p1] == 0);
542 self.aux_write_flag(FLAG_H, true);
543 self.aux_write_flag(FLAG_N, false);
544 self.aux_write_flag(FLAG_C, false);
545 }
546
547 fn and_r8_r16a(&mut self, ram: &mut Ram, p1: Reg, msh: Reg, lsh: Reg)
548 {
549 self.regs[p1] &= ram.read_rp(self.regs[msh], self.regs[lsh]);
550
551 self.aux_write_flag(FLAG_Z, self.regs[p1] == 0);
552 self.aux_write_flag(FLAG_H, true);
553 self.aux_write_flag(FLAG_N, false);
554 self.aux_write_flag(FLAG_C, false);
555 }
556
557 fn xor_r8_r8(&mut self, p1: Reg, p2: Reg)
558 {
559 self.regs[p1] ^= self.regs[p2];
560
561 self.aux_write_flag(FLAG_Z, self.regs[p1] == 0);
562 self.aux_write_flag(FLAG_H, false);
563 self.aux_write_flag(FLAG_N, false);
564 self.aux_write_flag(FLAG_C, false);
565 }
566
567 fn xor_r8_8(&mut self, p1: Reg, p2: u8)
568 {
569 self.regs[p1] ^= p2;
570
571 self.aux_write_flag(FLAG_Z, self.regs[p1] == 0);
572 self.aux_write_flag(FLAG_H, false);
573 self.aux_write_flag(FLAG_N, false);
574 self.aux_write_flag(FLAG_C, false);
575 }
576
577 fn xor_r8_r16a(&mut self, ram: &mut Ram, p1: Reg, msh: Reg, lsh: Reg)
578 {
579 self.regs[p1] ^= ram.read_rp(self.regs[msh], self.regs[lsh]);
580
581 self.aux_write_flag(FLAG_Z, self.regs[p1] == 0);
582 self.aux_write_flag(FLAG_H, false);
583 self.aux_write_flag(FLAG_N, false);
584 self.aux_write_flag(FLAG_C, false);
585 }
586
587 fn or_r8_r8(&mut self, p1: Reg, p2: Reg)
588 {
589 self.regs[p1] |= self.regs[p2];
590
591 self.aux_write_flag(FLAG_Z, self.regs[p1] == 0);
592 self.aux_write_flag(FLAG_H, false);
593 self.aux_write_flag(FLAG_N, false);
594 self.aux_write_flag(FLAG_C, false);
595 }
596
597 fn or_r8_8(&mut self, p1: Reg, p2: u8)
598 {
599 self.regs[p1] |= p2;
600
601 self.aux_write_flag(FLAG_Z, self.regs[p1] == 0);
602 self.aux_write_flag(FLAG_H, false);
603 self.aux_write_flag(FLAG_N, false);
604 self.aux_write_flag(FLAG_C, false);
605 }
606
607 fn or_r8_r16a(&mut self, ram: &mut Ram, p1: Reg, msh: Reg, lsh: Reg)
608 {
609 self.regs[p1] |= ram.read_rp(self.regs[msh], self.regs[lsh]);
610
611 self.aux_write_flag(FLAG_Z, self.regs[p1] == 0);
612 self.aux_write_flag(FLAG_H, false);
613 self.aux_write_flag(FLAG_N, false);
614 self.aux_write_flag(FLAG_C, false);
615 }
616
617 fn cp_r8_r8(&mut self, p1: Reg, p2: Reg)
618 {
619 let half_carry_pre = ((self.regs[p1] ^ self.regs[p2]) >> 4) & 1;
620 let result = self.regs[p1].overflowing_sub(self.regs[p2]);
621 self.regs[p1] = result.0;
622 let half_carry_post = (result.0 >> 4) & 1;
623
624 self.aux_write_flag(FLAG_Z, result.0 == 0);
625 self.aux_write_flag(FLAG_H, half_carry_pre != half_carry_post);
626 self.aux_write_flag(FLAG_N, true);
627 self.aux_write_flag(FLAG_C, result.1);
628 }
629
630 fn cp_r8_8(&mut self, p1: Reg, p2: u8)
631 {
632 let half_carry_pre = ((self.regs[p1] ^ p2) >> 4) & 1;
633 let result = self.regs[p1].overflowing_sub(p2);
634 self.regs[p1] = result.0;
635 let half_carry_post = (result.0 >> 4) & 1;
636
637 self.aux_write_flag(FLAG_Z, result.0 == 0);
638 self.aux_write_flag(FLAG_H, half_carry_pre != half_carry_post);
639 self.aux_write_flag(FLAG_N, true);
640 self.aux_write_flag(FLAG_C, result.1);
641 }
642
643 fn cp_r8_r16a(&mut self, ram: &mut Ram, p1: Reg, msh: Reg, lsh: Reg)
644 {
645 let p2 = ram.read_rp(self.regs[msh], self.regs[lsh]);
646 let half_carry_pre = ((self.regs[p1] ^ p2) >> 4) & 1;
647 let result = self.regs[p1].overflowing_add(p2);
648 self.regs[p1] = result.0;
649 let half_carry_post = (result.0 >> 4) & 1;
650
651 self.aux_write_flag(FLAG_Z, result.0 == 0);
652 self.aux_write_flag(FLAG_H, half_carry_pre != half_carry_post);
653 self.aux_write_flag(FLAG_N, true);
654 self.aux_write_flag(FLAG_C, result.1);
655 }
656
657 fn daa(&mut self)
658 {
659 let c_before = self.aux_read_flag(FLAG_C);
660 let bits_47 = (self.regs[REG_A] >> 4) & 0b00001111;
661 let h_before = self.aux_read_flag(FLAG_H);
662 let bits_03 = self.regs[REG_A] & 0b00001111;
663 if self.aux_read_flag(FLAG_N) == true {
665 match (c_before, bits_47, h_before, bits_03)
666 {
667 (false, 0x0..=0x9, false, 0x0..=0x9) => {
668 self.regs[REG_A] = self.regs[REG_A].wrapping_add(0x00);
669 self.aux_write_flag(FLAG_C, false);
670 },
671 (false, 0x0..=0x8, false, 0xA..=0xF) => {
672 self.regs[REG_A] = self.regs[REG_A].wrapping_add(0x06);
673 self.aux_write_flag(FLAG_C, false);
674 },
675 (false, 0x0..=0x9, true, 0x0..=0x3) => {
676 self.regs[REG_A] = self.regs[REG_A].wrapping_add(0x06);
677 self.aux_write_flag(FLAG_C, false);
678 },
679 (false, 0xA..=0xF, false, 0x0..=0x9) => {
680 self.regs[REG_A] = self.regs[REG_A].wrapping_add(0x60);
681 self.aux_write_flag(FLAG_C, true);
682 },
683 (false, 0x9..=0xF, false, 0xA..=0xF) => {
684 self.regs[REG_A] = self.regs[REG_A].wrapping_add(0x66);
685 self.aux_write_flag(FLAG_C, true);
686 },
687 (false, 0xA..=0xF, true, 0x0..=0x3) => {
688 self.regs[REG_A] = self.regs[REG_A].wrapping_add(0x66);
689 self.aux_write_flag(FLAG_C, true);
690 },
691 (true, 0x0..=0x2, false, 0x0..=0x9) => {
692 self.regs[REG_A] = self.regs[REG_A].wrapping_add(0x60);
693 self.aux_write_flag(FLAG_C, true);
694 },
695 (true, 0x0..=0x2, false, 0xA..=0xF) => {
696 self.regs[REG_A] = self.regs[REG_A].wrapping_add(0x66);
697 self.aux_write_flag(FLAG_C, true);
698 },
699 (true, 0x0..=0x3, true, 0x0..=0x3) => {
700 self.regs[REG_A] = self.regs[REG_A].wrapping_add(0x66);
701 self.aux_write_flag(FLAG_C, true);
702 },
703 _ => panic!("Invalid BDC conversion")
704 }
705 }
706 else {
708 match (c_before, bits_47, h_before, bits_03)
709 {
710 (false, 0x0..=0x9, false, 0x0..=0x9) => {
711 self.regs[REG_A] = self.regs[REG_A].wrapping_add(0x00);
712 self.aux_write_flag(FLAG_C, false);
713 },
714 (false, 0x0..=0x8, true, 0x6..=0xF) => {
715 self.regs[REG_A] = self.regs[REG_A].wrapping_add(0xFA);
716 self.aux_write_flag(FLAG_C, false);
717 },
718 (true, 0x7..=0xF, false, 0x0..=0x9) => {
719 self.regs[REG_A] = self.regs[REG_A].wrapping_add(0xA0);
720 self.aux_write_flag(FLAG_C, true);
721 },
722 (true, 0x6..=0xF, true, 0x6..=0xF) => {
723 self.regs[REG_A] = self.regs[REG_A].wrapping_add(0x9A);
724 self.aux_write_flag(FLAG_C, true);
725 },
726 _ => panic!("Invalid BDC conversion")
727 }
728 }
729 }
730
731 fn cpl(&mut self)
732 {
733 self.regs[REG_A] = !self.regs[REG_A];
734 self.aux_write_flag(FLAG_N, true);
735 self.aux_write_flag(FLAG_H, true);
736 }
737
738 fn ccf(&mut self)
739 {
740 self.aux_write_flag(FLAG_C, !self.aux_read_flag(FLAG_C));
741 self.aux_write_flag(FLAG_N, false);
742 self.aux_write_flag(FLAG_H, false);
743 }
744
745 fn scf(&mut self)
746 {
747 self.aux_write_flag(FLAG_C, true);
748 self.aux_write_flag(FLAG_N, false);
749 self.aux_write_flag(FLAG_H, false);
750 }
751
752 fn jp_pc_16(&mut self, msh: u8, lsh: u8)
753 {
754 self.pc.reg = u16::from_le_bytes([lsh, msh]);
755 self.pc.should_increment = false;
756 }
757
758 fn jp_flag_pc_16(&mut self, flag: Flag, msh: u8, lsh: u8)
759 {
760 if self.aux_read_flag(flag) == true
761 {
762 self.jp_pc_16(msh, lsh);
763 }
764 }
765
766 fn jp_nflag_pc_16(&mut self, flag: Flag, msh: u8, lsh: u8)
767 {
768 if self.aux_read_flag(flag) == false
769 {
770 self.jp_pc_16(msh, lsh);
771 }
772 }
773
774 fn jr_i8(&mut self, p1: i8)
775 {
776 let conv = p1.unsigned_abs() as u16;
777 let negative = p1 < 0;
778 if negative
779 {
780 self.pc.reg -= conv;
781 }
782 else
783 {
784 self.pc.reg += conv;
785 }
786 self.pc.should_increment = false;
787 }
788
789 fn jr_flag_i8(&mut self, flag: Flag, p1: i8)
790 {
791 if self.aux_read_flag(flag) == true
792 {
793 self.jr_i8(p1);
794 }
795 }
796
797 fn jr_nflag_i8(&mut self, flag: Flag, p1: i8)
798 {
799 if self.aux_read_flag(flag) == false
800 {
801 self.jr_i8(p1);
802 }
803 }
804
805 fn call_16(&mut self, ram: &mut Ram, msh: u8, lsh: u8)
806 {
807 let pc_bytes = self.pc.reg.to_le_bytes();
808 ram.write(self.sp - 1, pc_bytes[1]);
809 ram.write(self.sp - 2, pc_bytes[0]);
810 self.pc.reg = u16::from_le_bytes([lsh, msh]);
811 self.sp -= 2;
812 }
813
814 fn call_flag_16(&mut self, ram: &mut Ram, flag: Flag, msh: u8, lsh: u8)
815 {
816 if self.aux_read_flag(flag) == true
817 {
818 self.call_16(ram, msh, lsh);
819 }
820 }
821
822 fn call_nflag_16(&mut self, ram: &mut Ram, flag: Flag, msh: u8, lsh: u8)
823 {
824 if self.aux_read_flag(flag) == false
825 {
826 self.call_16(ram, msh, lsh);
827 }
828 }
829
830 fn ret(&mut self, ram: &mut Ram)
831 {
832 let sp_lsh = ram.read(self.sp);
833 let sp_msh = ram.read(self.sp + 1);
834 self.pc.reg = u16::from_le_bytes([sp_lsh, sp_msh]);
835 self.sp += 2;
836 }
837
838 fn ret_flag(&mut self, ram: &mut Ram, flag: Flag)
839 {
840 if self.aux_read_flag(flag) == true
841 {
842 self.ret(ram);
843 }
844 }
845
846 fn ret_nflag(&mut self, ram: &mut Ram, flag: Flag)
847 {
848 if self.aux_read_flag(flag) == false
849 {
850 self.ret(ram);
851 }
852 }
853
854 fn rst(&mut self, ram: &mut Ram, loc: u8)
855 {
856 let pc_bytes = self.pc.reg.to_le_bytes();
857 ram.write(self.sp - 1, pc_bytes[1]);
858 ram.write(self.sp - 2, pc_bytes[0]);
859 self.sp -= 2;
860 self.pc.reg = u16::from_le_bytes([loc, 0]);
861 }
862
863
864 fn rlc_r8(&mut self, p1: Reg)
867 {
868 self.aux_write_flag(FLAG_C, (self.regs[p1] >> 7) & 1 != 0);
869 self.regs[p1] = self.regs[p1].rotate_left(1);
870
871 self.aux_write_flag(FLAG_Z, self.regs[p1] == 0);
872 self.aux_write_flag(FLAG_N, false);
873 self.aux_write_flag(FLAG_H, false);
874 }
875
876 fn rlca(&mut self)
877 {
878 self.aux_write_flag(FLAG_C, (self.regs[REG_A] >> 7) & 1 != 0);
879 self.regs[REG_A] = self.regs[REG_A].rotate_left(1);
880
881 self.aux_write_flag(FLAG_Z, false);
882 self.aux_write_flag(FLAG_N, false);
883 self.aux_write_flag(FLAG_H, false);
884 }
885
886 fn rlc_r16a(&mut self, ram: &mut Ram, msh: Reg, lsh: Reg)
887 {
888 let p1 = ram.read_rp(self.regs[msh], self.regs[lsh]);
889 self.aux_write_flag(FLAG_C, (p1 >> 7) & 1 != 0);
890 let result = p1.rotate_left(1);
891 ram.write_rp(self.regs[msh], self.regs[lsh], result);
892
893 self.aux_write_flag(FLAG_Z, result == 0);
894 self.aux_write_flag(FLAG_N, false);
895 self.aux_write_flag(FLAG_H, false);
896 }
897
898 fn rrc_r8(&mut self, p1: Reg)
899 {
900 self.aux_write_flag(FLAG_C, self.regs[p1] & 1 != 0);
901 self.regs[p1] = self.regs[p1].rotate_right(1);
902
903 self.aux_write_flag(FLAG_Z, self.regs[p1] == 0);
904 self.aux_write_flag(FLAG_N, false);
905 self.aux_write_flag(FLAG_H, false);
906 }
907
908 fn rrca(&mut self)
909 {
910 self.aux_write_flag(FLAG_C, self.regs[REG_A] & 1 != 0);
911 self.regs[REG_A] = self.regs[REG_A].rotate_right(1);
912
913 self.aux_write_flag(FLAG_Z, false);
914 self.aux_write_flag(FLAG_N, false);
915 self.aux_write_flag(FLAG_H, false);
916 }
917
918 fn rrc_r16a(&mut self, ram: &mut Ram, msh: Reg, lsh: Reg)
919 {
920 let p1 = ram.read_rp(self.regs[msh], self.regs[lsh]);
921 self.aux_write_flag(FLAG_C, p1 & 1 != 0);
922 let result = p1.rotate_right(1);
923 ram.write_rp(self.regs[msh], self.regs[lsh], result);
924
925 self.aux_write_flag(FLAG_Z, result == 0);
926 self.aux_write_flag(FLAG_N, false);
927 self.aux_write_flag(FLAG_H, false);
928 }
929
930 fn rl_r8(&mut self, p1: Reg)
931 {
932 let cin = self.aux_read_flag(FLAG_C) as u8;
933 self.aux_write_flag(FLAG_C, (self.regs[p1] >> 7) & 1 != 0);
934 self.regs[p1] = (self.regs[p1] << 1u8) | cin;
935
936 self.aux_write_flag(FLAG_Z, self.regs[p1] == 0);
937 self.aux_write_flag(FLAG_N, false);
938 self.aux_write_flag(FLAG_H, false);
939 }
940
941 fn rla(&mut self)
942 {
943 let cin = self.aux_read_flag(FLAG_C) as u8;
944 self.aux_write_flag(FLAG_C, (self.regs[REG_A] >> 7) & 1 != 0);
945 self.regs[REG_A] = (self.regs[REG_A] << 1u8) | cin;
946
947 self.aux_write_flag(FLAG_Z, false);
948 self.aux_write_flag(FLAG_N, false);
949 self.aux_write_flag(FLAG_H, false);
950 }
951
952 fn rl_r16a(&mut self, ram: &mut Ram, msh: Reg, lsh: Reg)
953 {
954 let cin = self.aux_read_flag(FLAG_C) as u8;
955 let p1 = ram.read_rp(self.regs[msh], self.regs[lsh]);
956 self.aux_write_flag(FLAG_C, (p1 >> 7) & 1 != 0);
957 let result = (p1 << 1u8) | cin;
958 ram.write_rp(self.regs[msh], self.regs[lsh], result);
959
960 self.aux_write_flag(FLAG_Z, result == 0);
961 self.aux_write_flag(FLAG_N, false);
962 self.aux_write_flag(FLAG_H, false);
963 }
964
965 fn rr_r8(&mut self, p1: Reg)
966 {
967 let cin = self.aux_read_flag(FLAG_C) as u8;
968 self.aux_write_flag(FLAG_C, self.regs[p1] & 1 != 0);
969 self.regs[p1] = (self.regs[p1] >> 1u8) | (cin << 7u8);
970
971 self.aux_write_flag(FLAG_Z, self.regs[p1] == 0);
972 self.aux_write_flag(FLAG_N, false);
973 self.aux_write_flag(FLAG_H, false);
974 }
975
976 fn rra(&mut self)
977 {
978 let cin = self.aux_read_flag(FLAG_C) as u8;
979 self.aux_write_flag(FLAG_C, self.regs[REG_A] & 1 != 0);
980 self.regs[REG_A] = (self.regs[REG_A] >> 1u8) | (cin << 7u8);
981
982 self.aux_write_flag(FLAG_Z, false);
983 self.aux_write_flag(FLAG_N, false);
984 self.aux_write_flag(FLAG_H, false);
985 }
986
987 fn rr_r16a(&mut self, ram: &mut Ram, msh: Reg, lsh: Reg)
988 {
989 let cin = self.aux_read_flag(FLAG_C) as u8;
990 let p1 = ram.read_rp(self.regs[msh], self.regs[lsh]);
991 self.aux_write_flag(FLAG_C, p1 & 1 != 0);
992 let result = (p1 >> 1u8) | (cin << 7u8);
993 ram.write_rp(self.regs[msh], self.regs[lsh], result);
994
995 self.aux_write_flag(FLAG_Z, result == 0);
996 self.aux_write_flag(FLAG_N, false);
997 self.aux_write_flag(FLAG_H, false);
998 }
999
1000 fn sla_r8(&mut self, p1: Reg)
1001 {
1002 self.aux_write_flag(FLAG_C, (self.regs[p1] >> 7) & 1 != 0);
1003 self.regs[p1] <<= 1u8;
1004
1005 self.aux_write_flag(FLAG_Z, self.regs[p1] == 0);
1006 self.aux_write_flag(FLAG_N, false);
1007 self.aux_write_flag(FLAG_H, false);
1008 }
1009
1010 fn sla_r16a(&mut self, ram: &mut Ram, msh: Reg, lsh: Reg)
1011 {
1012 let p1 = ram.read_rp(self.regs[msh], self.regs[lsh]);
1013 self.aux_write_flag(FLAG_C, (p1 >> 7) & 1 != 0);
1014 let result = p1 << 1u8;
1015 ram.write_rp(self.regs[msh], self.regs[lsh], result);
1016
1017 self.aux_write_flag(FLAG_Z, result == 0);
1018 self.aux_write_flag(FLAG_N, false);
1019 self.aux_write_flag(FLAG_H, false);
1020 }
1021
1022 fn sra_r8(&mut self, p1: Reg)
1023 {
1024 self.aux_write_flag(FLAG_C, self.regs[p1] & 1 != 0);
1025 self.regs[p1] = (self.regs[p1] >> 1u8) | (self.regs[p1] & 0b10000000u8); self.aux_write_flag(FLAG_Z, self.regs[p1] == 0);
1028 self.aux_write_flag(FLAG_N, false);
1029 self.aux_write_flag(FLAG_H, false);
1030 }
1031
1032 fn sra_r16a(&mut self, ram: &mut Ram, msh: Reg, lsh: Reg)
1033 {
1034 let p1 = ram.read_rp(self.regs[msh], self.regs[lsh]);
1035 self.aux_write_flag(FLAG_C, p1 & 1 != 0);
1036 let result =( p1 >> 1u8) | (p1 | 0b10000000u8);
1037 ram.write_rp(self.regs[msh], self.regs[lsh], result);
1038
1039 self.aux_write_flag(FLAG_Z, result == 0);
1040 self.aux_write_flag(FLAG_N, false);
1041 self.aux_write_flag(FLAG_H, false);
1042 }
1043
1044 fn srl_r8(&mut self, p1: Reg)
1045 {
1046 self.aux_write_flag(FLAG_C, self.regs[p1] & 1 != 0);
1047 self.regs[p1] >>= 1u8; self.aux_write_flag(FLAG_Z, self.regs[p1] == 0);
1050 self.aux_write_flag(FLAG_N, false);
1051 self.aux_write_flag(FLAG_H, false);
1052 }
1053
1054 fn srl_r16a(&mut self, ram: &mut Ram, msh: Reg, lsh: Reg)
1055 {
1056 let p1 = ram.read_rp(self.regs[msh], self.regs[lsh]);
1057 self.aux_write_flag(FLAG_C, p1 & 1 != 0);
1058 let result = p1 >> 1u8;
1059 ram.write_rp(self.regs[msh], self.regs[lsh], result);
1060
1061 self.aux_write_flag(FLAG_Z, result == 0);
1062 self.aux_write_flag(FLAG_N, false);
1063 self.aux_write_flag(FLAG_H, false);
1064 }
1065
1066 fn swap_r8(&mut self, p1: Reg)
1067 {
1068 let lower_to_upper_half = self.regs[p1] << 4u8;
1069 let upper_to_lower_half = self.regs[p1] >> 4u8;
1070 self.regs[p1] = lower_to_upper_half | upper_to_lower_half;
1071 }
1072
1073 fn swap_r16a(&mut self, ram: &mut Ram, msh: Reg, lsh: Reg)
1074 {
1075 let p1 = ram.read_rp(self.regs[msh], self.regs[lsh]);
1076 let lower_to_upper_half = p1 << 4u8;
1077 let upper_to_lower_half = p1 >> 4u8;
1078 ram.write_rp(self.regs[msh], self.regs[lsh], lower_to_upper_half | upper_to_lower_half);
1079 }
1080
1081 fn bit_r8(&mut self, p1: u8, p2: Reg)
1082 {
1083 self.aux_write_flag(FLAG_H, true);
1084 self.aux_write_flag(FLAG_N, false);
1085 self.aux_write_flag(FLAG_Z, (self.regs[p2] & (1u8 << p1)) == 0);
1086 }
1087
1088 fn bit_r16a(&mut self, ram: &mut Ram, p1: u8, msh: Reg, lsh: Reg)
1089 {
1090 self.aux_write_flag(FLAG_H, true);
1091 self.aux_write_flag(FLAG_N, false);
1092 self.aux_write_flag(FLAG_Z,
1093 (ram.read_rp(self.regs[msh], self.regs[lsh]) & (1u8 << p1)) == 0);
1094 }
1095
1096 fn res_r8(&mut self, p1: u8, p2: Reg)
1097 {
1098 self.regs[p2] &= !(1u8 << p1);
1099 }
1100
1101 fn res_r16a(&mut self, ram: &mut Ram, p1: u8, msh: Reg, lsh: Reg)
1102 {
1103 ram.write_rp(self.regs[msh], self.regs[lsh],
1104 ram.read_rp(self.regs[msh], self.regs[lsh]) & (!(1u8 << p1)));
1105 }
1106
1107 fn set_r8(&mut self, p1: u8, p2: Reg)
1108 {
1109 self.regs[p2] |= 1u8 << p1;
1110 }
1111
1112 fn set_r16a(&mut self, ram: &mut Ram, p1: u8, msh: Reg, lsh: Reg)
1113 {
1114 ram.write_rp(self.regs[msh], self.regs[lsh],
1115 ram.read_rp(self.regs[msh], self.regs[lsh]) | (1u8 << p1));
1116 }
1117
1118 fn push_r16(&mut self, ram: &mut Ram, msh: Reg, lsh: Reg)
1119 {
1120 ram.write(self.sp - 1, self.regs[msh]);
1121 ram.write(self.sp - 2, self.regs[lsh]);
1122 self.sp -= 2;
1123 }
1124
1125 fn push_pc(&mut self, ram: &mut Ram)
1126 {
1127 let bytes = self.pc.reg.to_le_bytes();
1128 ram.write(self.sp - 1, bytes[1]);
1129 ram.write(self.sp - 2, bytes[0]);
1130 self.sp -= 2;
1131 }
1132
1133 fn pop_r16(&mut self, ram: &mut Ram, msh: Reg, lsh: Reg)
1134 {
1135 self.regs[lsh] = ram.read(self.sp);
1136 self.regs[msh] = ram.read(self.sp + 1);
1137 self.sp += 2;
1138 }
1139
1140 fn reti(&mut self, ram: &mut Ram)
1143 {
1144 let l_bytes = ram.read(self.sp);
1145 self.inc_sp();
1146 let h_bytes = ram.read(self.sp);
1147 self.inc_sp();
1148 self.pc.reg = u16::from_le_bytes([l_bytes, h_bytes]);
1149 self.ime = true;
1150 }
1151
1152 fn ei(&mut self)
1153 {
1154 self.ime = true;
1155 }
1156
1157 fn di(&mut self)
1158 {
1159 self.ime = false;
1160 }
1161
1162 fn aux_inc_pc(&mut self)
1165 {
1166 if self.pc.should_increment
1167 {
1168 self.pc.reg += 1;
1169 self.pc.current_instruction_width = 0;
1170 }
1171 else
1172 {
1173 self.pc.should_increment = true;
1174 }
1175 }
1176
1177 fn aux_read_pc(&self, ram: &mut Ram) -> u8
1178 {
1179 ram.read(self.pc.reg)
1180 }
1181
1182 fn aux_read_immediate_data(&mut self, ram: &mut Ram) -> u8
1183 {
1184 self.pc.reg += 1;
1185 self.pc.current_instruction_width += 1;
1186 ram.read(self.pc.reg)
1187 }
1188
1189 pub fn execute(&mut self, ram: &mut Ram)
1190 {
1191 if self.pc.current_instruction_cycles > 1
1192 {
1193 self.pc.current_instruction_cycles -= 1;
1194 return;
1195 }
1196
1197 let valid_interrupts = ram.read(ram::IF) & ram.read(ram::IE);
1199 if self.ime
1200 {
1201 if valid_interrupts != 0
1202 {
1203 self.ime = false;
1204 self.push_pc(ram);
1205 }
1206 if valid_interrupts & ram::INTERRUPT_VB != 0
1207 {
1208 self.pc.reg = 0x0040;
1209 }
1210 else if valid_interrupts & ram::INTERRUPT_LCDC != 0
1211 {
1212 self.pc.reg = 0x0048;
1213 }
1214 else if valid_interrupts & ram::INTERRUPT_TIMA != 0
1215 {
1216 self.pc.reg = 0x0050;
1217 }
1218 else if valid_interrupts & ram::INTERRUPT_SIO_TRANSFER_COMPLETE != 0
1219 {
1220 self.pc.reg = 0x0058;
1221 }
1222 else if valid_interrupts & ram::INTERRUPT_P1X_NEG_EDGE != 0
1223 {
1224 self.pc.reg = 0x0060;
1225 }
1226
1227 }
1228
1229 if self.halted
1230 {
1231 if valid_interrupts != 0
1232 {
1233 self.halted = false;
1234 }
1235 else
1236 {
1237 return;
1238 }
1239 }
1240
1241 let instruction = self.aux_read_pc(ram);
1242
1243 #[cfg(feature = "cpu-debug")]
1244 println!("Instruction: 0x{:02X?}, Program Counter: 0x{:02X?}", instruction, &self.pc.reg);
1245
1246 if instruction != 0xCB
1247 {
1248 match instruction
1249 {
1250 0x00 => {},
1251 0x01 => {
1252 let lsh = self.aux_read_immediate_data(ram);
1253 let msh = self.aux_read_immediate_data(ram);
1254 self.ld_r16_16(REG_B, REG_C, msh, lsh);
1255 },
1256 0x02 => {self.ld_r16a_r8(ram, REG_B, REG_C, REG_A);},
1257 0x03 => {self.inc_r16(REG_B, REG_C);},
1258 0x04 => {self.inc_r8(REG_B);},
1259 0x05 => {self.dec_r8(REG_B);},
1260 0x06 => {
1261 let num = self.aux_read_immediate_data(ram);
1262 self.ld_r8_8(REG_B, num);
1263 },
1264 0x07 => {self.rlca();},
1265 0x08 => {
1266 let lsh = self.aux_read_immediate_data(ram);
1267 let msh = self.aux_read_immediate_data(ram);
1268 self.ld_16a_sp(ram, msh, lsh);
1269 },
1270 0x09 => {self.add_r16_r16(REG_H, REG_L, REG_B, REG_C);},
1271 0x0A => {self.ld_r8_r16a(ram, REG_A, REG_B, REG_C);},
1272 0x0B => {self.dec_r16(REG_B, REG_C);},
1273 0x0C => {self.inc_r8(REG_C);},
1274 0x0D => {self.dec_r8(REG_C);},
1275 0x0E => {
1276 let num = self.aux_read_immediate_data(ram);
1277 self.ld_r8_8(REG_C, num);
1278 },
1279 0x0F => {self.rrca();},
1280 0x10 => {self.stop();},
1281 0x11 => {
1282 let lsh = self.aux_read_immediate_data(ram);
1283 let msh = self.aux_read_immediate_data(ram);
1284 self.ld_r16_16(REG_D, REG_E, msh, lsh);
1285 },
1286 0x12 => {self.ld_r16a_r8(ram, REG_D, REG_E, REG_A);},
1287 0x13 => {self.inc_r16(REG_D, REG_E);},
1288 0x14 => {self.inc_r8(REG_D);},
1289 0x15 => {self.dec_r8(REG_D);},
1290 0x16 => {
1291 let num = self.aux_read_immediate_data(ram);
1292 self.ld_r8_8(REG_D, num);
1293 },
1294 0x17 => {self.rla();},
1295 0x18 => {
1296 let immediate = self.aux_read_immediate_data(ram) as i8;
1297 self.jr_i8(immediate);
1298 },
1299 0x19 => {self.add_r16_r16(REG_H, REG_L, REG_D, REG_E);},
1300 0x1A => {self.ld_r8_r16a(ram, REG_A, REG_D, REG_E);},
1301 0x1B => {self.dec_r16(REG_D, REG_E);},
1302 0x1C => {self.inc_r8(REG_E);},
1303 0x1D => {self.dec_r8(REG_E);},
1304 0x1E => {
1305 let num = self.aux_read_immediate_data(ram);
1306 self.ld_r8_8(REG_E, num);
1307 },
1308 0x1F => {self.rra();},
1309 0x20 => {
1310 let immediate = self.aux_read_immediate_data(ram) as i8;
1311 self.jr_nflag_i8(FLAG_Z, immediate);
1312 },
1313 0x21 => {
1314 let lsh = self.aux_read_immediate_data(ram);
1315 let msh = self.aux_read_immediate_data(ram);
1316 self.ld_r16_16(REG_H, REG_L, msh, lsh);
1317 },
1318 0x22 => {
1319 self.ld_r16a_r8(ram, REG_H, REG_L, REG_A);
1320 self.inc_r16(REG_H, REG_L);
1321 },
1322 0x23 => {self.inc_r16(REG_H, REG_L);},
1323 0x24 => {self.inc_r8(REG_H);},
1324 0x25 => {self.dec_r8(REG_H);},
1325 0x26 => {
1326 let num = self.aux_read_immediate_data(ram);
1327 self.ld_r8_8(REG_H, num);
1328 },
1329 0x27 => {self.daa();},
1330 0x28 => {
1331 let immediate = self.aux_read_immediate_data(ram) as i8;
1332 self.jr_flag_i8(FLAG_Z, immediate);
1333 },
1334 0x29 => {self.add_r16_r16(REG_H, REG_L, REG_H, REG_L)},
1335 0x2A => {
1336 self.ld_r8_r16a(ram, REG_A, REG_H, REG_L);
1337 self.inc_r16(REG_H, REG_L);
1338 },
1339 0x2B => {self.dec_r16(REG_H, REG_L);},
1340 0x2C => {self.inc_r8(REG_L);},
1341 0x2D => {self.dec_r8(REG_L);},
1342 0x2E => {
1343 let num = self.aux_read_immediate_data(ram);
1344 self.ld_r8_8(REG_L, num);
1345 },
1346 0x2F => {self.cpl();},
1347 0x30 => {
1348 let immediate = self.aux_read_immediate_data(ram) as i8;
1349 self.jr_nflag_i8(FLAG_C, immediate);
1350 },
1351 0x31 => {
1352 let lsh = self.aux_read_immediate_data(ram);
1353 let msh = self.aux_read_immediate_data(ram);
1354 self.ld_sp_16( msh, lsh);
1355 },
1356 0x32 => {
1357 self.ld_r16a_r8(ram, REG_H, REG_L, REG_A);
1358 self.dec_r16(REG_H, REG_L);
1359 },
1360 0x33 => {self.inc_sp();},
1361 0x34 => {self.inc_r16a(ram, REG_H, REG_L);},
1362 0x35 => {self.dec_r16a(ram, REG_H, REG_L);},
1363 0x36 => {
1364 let num = self.aux_read_immediate_data(ram);
1365 self.ld_r16a_8(ram, REG_H, REG_L, num);
1366 },
1367 0x37 => {self.scf();},
1368 0x38 => {
1369 let immediate = self.aux_read_immediate_data(ram) as i8;
1370 self.jr_flag_i8(FLAG_C, immediate);
1371 },
1372 0x39 => {self.add_r16_sp(REG_H, REG_L);},
1373 0x3A => {
1374 self.ld_r8_r16a(ram, REG_A, REG_H, REG_L);
1375 self.dec_r16(REG_H, REG_L);
1376 },
1377 0x3B => {self.dec_sp();},
1378 0x3C => {self.inc_r8(REG_A);},
1379 0x3D => {self.dec_r8(REG_A);},
1380 0x3E => {
1381 let num = self.aux_read_immediate_data(ram);
1382 self.ld_r8_8(REG_A, num);
1383 },
1384 0x3F => {self.ccf();},
1385 0x40 => {self.ld_r8_r8(REG_B, REG_B);},
1386 0x41 => {self.ld_r8_r8(REG_B, REG_C);},
1387 0x42 => {self.ld_r8_r8(REG_B, REG_D);},
1388 0x43 => {self.ld_r8_r8(REG_B, REG_E);},
1389 0x44 => {self.ld_r8_r8(REG_B, REG_H);},
1390 0x45 => {self.ld_r8_r8(REG_B, REG_L);},
1391 0x46 => {self.ld_r8_r16a(ram, REG_B, REG_H, REG_L);},
1392 0x47 => {self.ld_r8_r8(REG_B, REG_A);},
1393 0x48 => {self.ld_r8_r8(REG_C, REG_B);},
1394 0x49 => {self.ld_r8_r8(REG_C, REG_C);},
1395 0x4A => {self.ld_r8_r8(REG_C, REG_D);},
1396 0x4B => {self.ld_r8_r8(REG_C, REG_E);},
1397 0x4C => {self.ld_r8_r8(REG_C, REG_H);},
1398 0x4D => {self.ld_r8_r8(REG_C, REG_L);},
1399 0x4E => {self.ld_r8_r16a(ram, REG_C, REG_H, REG_L);},
1400 0x4F => {self.ld_r8_r8(REG_C, REG_A);},
1401 0x50 => {self.ld_r8_r8(REG_D, REG_B);},
1402 0x51 => {self.ld_r8_r8(REG_D, REG_C);},
1403 0x52 => {self.ld_r8_r8(REG_D, REG_D);},
1404 0x53 => {self.ld_r8_r8(REG_D, REG_E);},
1405 0x54 => {self.ld_r8_r8(REG_D, REG_H);},
1406 0x55 => {self.ld_r8_r8(REG_D, REG_L);},
1407 0x56 => {self.ld_r8_r16a(ram, REG_D, REG_H, REG_L);},
1408 0x57 => {self.ld_r8_r8(REG_D, REG_A);},
1409 0x58 => {self.ld_r8_r8(REG_E, REG_B);},
1410 0x59 => {self.ld_r8_r8(REG_E, REG_C);},
1411 0x5A => {self.ld_r8_r8(REG_E, REG_D);},
1412 0x5B => {self.ld_r8_r8(REG_E, REG_E);},
1413 0x5C => {self.ld_r8_r8(REG_E, REG_H);},
1414 0x5D => {self.ld_r8_r8(REG_E, REG_L);},
1415 0x5E => {self.ld_r8_r16a(ram, REG_E, REG_H, REG_L);},
1416 0x5F => {self.ld_r8_r8(REG_E, REG_A);},
1417 0x60 => {self.ld_r8_r8(REG_H, REG_B);},
1418 0x61 => {self.ld_r8_r8(REG_H, REG_C);},
1419 0x62 => {self.ld_r8_r8(REG_H, REG_D);},
1420 0x63 => {self.ld_r8_r8(REG_H, REG_E);},
1421 0x64 => {self.ld_r8_r8(REG_H, REG_H);},
1422 0x65 => {self.ld_r8_r8(REG_H, REG_L);},
1423 0x66 => {self.ld_r8_r16a(ram, REG_H, REG_H, REG_L);},
1424 0x67 => {self.ld_r8_r8(REG_H, REG_A);},
1425 0x68 => {self.ld_r8_r8(REG_L, REG_B);},
1426 0x69 => {self.ld_r8_r8(REG_L, REG_C);},
1427 0x6A => {self.ld_r8_r8(REG_L, REG_D);},
1428 0x6B => {self.ld_r8_r8(REG_L, REG_E);},
1429 0x6C => {self.ld_r8_r8(REG_L, REG_H);},
1430 0x6D => {self.ld_r8_r8(REG_L, REG_L);},
1431 0x6E => {self.ld_r8_r16a(ram, REG_L, REG_H, REG_L);},
1432 0x6F => {self.ld_r8_r8(REG_L, REG_A);},
1433 0x70 => {self.ld_r16a_r8(ram, REG_H, REG_L, REG_B);},
1434 0x71 => {self.ld_r16a_r8(ram, REG_H, REG_L, REG_C);},
1435 0x72 => {self.ld_r16a_r8(ram, REG_H, REG_L, REG_D);},
1436 0x73 => {self.ld_r16a_r8(ram, REG_H, REG_L, REG_E);},
1437 0x74 => {self.ld_r16a_r8(ram, REG_H, REG_L, REG_H);},
1438 0x75 => {self.ld_r16a_r8(ram, REG_H, REG_L, REG_L);},
1439 0x76 => {self.halt();},
1440 0x77 => {self.ld_r16a_r8(ram, REG_H, REG_L, REG_A);},
1441 0x78 => {self.ld_r8_r8(REG_A, REG_B);},
1442 0x79 => {self.ld_r8_r8(REG_A, REG_C);},
1443 0x7A => {self.ld_r8_r8(REG_A, REG_D);},
1444 0x7B => {self.ld_r8_r8(REG_A, REG_E);},
1445 0x7C => {self.ld_r8_r8(REG_A, REG_H);},
1446 0x7D => {self.ld_r8_r8(REG_A, REG_L);},
1447 0x7E => {self.ld_r8_r16a(ram, REG_A, REG_H, REG_L);},
1448 0x7F => {self.ld_r8_r8(REG_A, REG_A);},
1449 0x80 => {self.add_r8_r8(REG_A, REG_B);},
1450 0x81 => {self.add_r8_r8(REG_A, REG_C);},
1451 0x82 => {self.add_r8_r8(REG_A, REG_D);},
1452 0x83 => {self.add_r8_r8(REG_A, REG_E);},
1453 0x84 => {self.add_r8_r8(REG_A, REG_H);},
1454 0x85 => {self.add_r8_r8(REG_A, REG_L);},
1455 0x86 => {self.add_r8_r16a(ram, REG_A, REG_H, REG_L);},
1456 0x87 => {self.add_r8_r8(REG_A, REG_A);},
1457 0x88 => {self.adc_r8_r8(REG_A, REG_B);},
1458 0x89 => {self.adc_r8_r8(REG_A, REG_C);},
1459 0x8A => {self.adc_r8_r8(REG_A, REG_D);},
1460 0x8B => {self.adc_r8_r8(REG_A, REG_E);},
1461 0x8C => {self.adc_r8_r8(REG_A, REG_H);},
1462 0x8D => {self.adc_r8_r8(REG_A, REG_L);},
1463 0x8E => {self.adc_r8_r16a(ram, REG_A, REG_H, REG_L);},
1464 0x8F => {self.adc_r8_r8(REG_A, REG_A);},
1465 0x90 => {self.sub_r8_r8(REG_A, REG_B);},
1466 0x91 => {self.sub_r8_r8(REG_A, REG_C);},
1467 0x92 => {self.sub_r8_r8(REG_A, REG_D);},
1468 0x93 => {self.sub_r8_r8(REG_A, REG_E);},
1469 0x94 => {self.sub_r8_r8(REG_A, REG_H);},
1470 0x95 => {self.sub_r8_r8(REG_A, REG_L);},
1471 0x96 => {self.sub_r8_r16a(ram, REG_A, REG_H, REG_L);},
1472 0x97 => {self.sub_r8_r8(REG_A, REG_A);},
1473 0x98 => {self.sbc_r8_r8(REG_A, REG_B);},
1474 0x99 => {self.sbc_r8_r8(REG_A, REG_C);},
1475 0x9A => {self.sbc_r8_r8(REG_A, REG_D);},
1476 0x9B => {self.sbc_r8_r8(REG_A, REG_E);},
1477 0x9C => {self.sbc_r8_r8(REG_A, REG_H);},
1478 0x9D => {self.sbc_r8_r8(REG_A, REG_L);},
1479 0x9E => {self.sbc_r8_r16a(ram, REG_A, REG_H, REG_L);},
1480 0x9F => {self.sbc_r8_r8(REG_A, REG_A);},
1481 0xA0 => {self.and_r8_r8(REG_A, REG_B);},
1482 0xA1 => {self.and_r8_r8(REG_A, REG_C);},
1483 0xA2 => {self.and_r8_r8(REG_A, REG_D);},
1484 0xA3 => {self.and_r8_r8(REG_A, REG_E);},
1485 0xA4 => {self.and_r8_r8(REG_A, REG_H);},
1486 0xA5 => {self.and_r8_r8(REG_A, REG_L);},
1487 0xA6 => {self.and_r8_r16a(ram, REG_A, REG_H, REG_L);},
1488 0xA7 => {self.and_r8_r8(REG_A, REG_A);},
1489 0xA8 => {self.xor_r8_r8(REG_A, REG_B);},
1490 0xA9 => {self.xor_r8_r8(REG_A, REG_C);},
1491 0xAA => {self.xor_r8_r8(REG_A, REG_D);},
1492 0xAB => {self.xor_r8_r8(REG_A, REG_E);},
1493 0xAC => {self.xor_r8_r8(REG_A, REG_H);},
1494 0xAD => {self.xor_r8_r8(REG_A, REG_L);},
1495 0xAE => {self.xor_r8_r16a(ram, REG_A, REG_H, REG_L);},
1496 0xAF => {self.xor_r8_r8(REG_A, REG_A);},
1497 0xB0 => {self.or_r8_r8(REG_A, REG_B);},
1498 0xB1 => {self.or_r8_r8(REG_A, REG_C);},
1499 0xB2 => {self.or_r8_r8(REG_A, REG_D);},
1500 0xB3 => {self.or_r8_r8(REG_A, REG_E);},
1501 0xB4 => {self.or_r8_r8(REG_A, REG_H);},
1502 0xB5 => {self.or_r8_r8(REG_A, REG_L);},
1503 0xB6 => {self.or_r8_r16a(ram, REG_A, REG_H, REG_L);},
1504 0xB7 => {self.or_r8_r8(REG_A, REG_A);},
1505 0xB8 => {self.cp_r8_r8(REG_A, REG_B);},
1506 0xB9 => {self.cp_r8_r8(REG_A, REG_C);},
1507 0xBA => {self.cp_r8_r8(REG_A, REG_D);},
1508 0xBB => {self.cp_r8_r8(REG_A, REG_E);},
1509 0xBC => {self.cp_r8_r8(REG_A, REG_H);},
1510 0xBD => {self.cp_r8_r8(REG_A, REG_L);},
1511 0xBE => {self.cp_r8_r16a(ram, REG_A, REG_H, REG_L);},
1512 0xBF => {self.cp_r8_r8(REG_A, REG_A);},
1513 0xC0 => {self.ret_nflag(ram, FLAG_Z);},
1514 0xC1 => {self.pop_r16(ram, REG_B, REG_C);},
1515 0xC2 => {
1516 let lsh = self.aux_read_immediate_data(ram);
1517 let msh = self.aux_read_immediate_data(ram);
1518 self.jp_nflag_pc_16(FLAG_Z, msh, lsh);
1519 },
1520 0xC3 => {
1521 let lsh = self.aux_read_immediate_data(ram);
1522 let msh = self.aux_read_immediate_data(ram);
1523 self.jp_pc_16(msh, lsh);
1524 },
1525 0xC4 => {
1526 let lsh = self.aux_read_immediate_data(ram);
1527 let msh = self.aux_read_immediate_data(ram);
1528 self.call_nflag_16(ram, FLAG_Z, msh, lsh);
1529 },
1530 0xC5 => {self.push_r16(ram, REG_B, REG_C);},
1531 0xC6 => {
1532 let num = self.aux_read_immediate_data(ram);
1533 self.add_r8_8(REG_A, num);
1534 },
1535 0xC7 => {self.rst(ram, 0x00);},
1536 0xC8 => {self.ret_flag(ram, FLAG_Z);},
1537 0xC9 => {self.ret(ram);},
1538 0xCA => {
1539 let lsh = self.aux_read_immediate_data(ram);
1540 let msh = self.aux_read_immediate_data(ram);
1541 self.jp_flag_pc_16(FLAG_Z, msh, lsh);
1542 },
1543 0xCB => {},
1544 0xCC => {
1545 let lsh = self.aux_read_immediate_data(ram);
1546 let msh = self.aux_read_immediate_data(ram);
1547 self.call_flag_16(ram, FLAG_Z, msh, lsh);
1548 },
1549 0xCD => {let lsh = self.aux_read_immediate_data(ram);
1550 let msh = self.aux_read_immediate_data(ram);
1551 self.call_16(ram, msh, lsh);},
1552 0xCE => {
1553 let num = self.aux_read_immediate_data(ram);
1554 self.adc_r8_8(REG_A, num);
1555 },
1556 0xCF => {self.rst(ram, 0x08);},
1557 0xD0 => {self.ret_nflag(ram, FLAG_C);},
1558 0xD1 => {self.pop_r16(ram, REG_D, REG_E);},
1559 0xD2 => {
1560 let lsh = self.aux_read_immediate_data(ram);
1561 let msh = self.aux_read_immediate_data(ram);
1562 self.jp_nflag_pc_16(FLAG_C, msh, lsh);
1563 },
1564 0xD3 => {self.invalid_instruction(0xD3);},
1565 0xD4 => {
1566 let lsh = self.aux_read_immediate_data(ram);
1567 let msh = self.aux_read_immediate_data(ram);
1568 self.call_nflag_16(ram, FLAG_C, msh, lsh);
1569 },
1570 0xD5 => {self.push_r16(ram, REG_D, REG_E);},
1571 0xD6 => {
1572 let num = self.aux_read_immediate_data(ram);
1573 self.sub_r8_8(REG_A, num);
1574 },
1575 0xD7 => {self.rst(ram, 0x10);},
1576 0xD8 => {self.ret_flag(ram, FLAG_C);},
1577 0xD9 => {self.reti(ram);},
1578 0xDA => {
1579 let lsh = self.aux_read_immediate_data(ram);
1580 let msh = self.aux_read_immediate_data(ram);
1581 self.jp_flag_pc_16(FLAG_C, msh, lsh);
1582 },
1583 0xDB => {self.invalid_instruction(0xDB);},
1584 0xDC => {
1585 let lsh = self.aux_read_immediate_data(ram);
1586 let msh = self.aux_read_immediate_data(ram);
1587 self.call_flag_16(ram, FLAG_C, msh, lsh);
1588 },
1589 0xDD => {self.invalid_instruction(0xDD);},
1590 0xDE => {
1591 let num = self.aux_read_immediate_data(ram);
1592 self.sbc_r8_8(REG_A, num);
1593 },
1594 0xDF => {self.rst(ram, 0x18);},
1595 0xE0 => {
1596 let lsh = self.aux_read_immediate_data(ram);
1597 self.ld_16a_r8(ram, 0xFF, lsh, REG_A);
1598 },
1599 0xE1 => {self.pop_r16(ram, REG_H, REG_L);},
1600 0xE2 => {self.ld_16a_r8(ram, 0xFF, self.regs[REG_C], REG_A);},
1601 0xE3 => {self.invalid_instruction(0xE3);},
1602 0xE4 => {self.invalid_instruction(0xE4);},
1603 0xE5 => {self.push_r16(ram, REG_H, REG_L);},
1604 0xE6 => {
1605 let num = self.aux_read_immediate_data(ram);
1606 self.and_r8_8(REG_A, num);
1607 },
1608 0xE7 => {self.rst(ram, 0x20);},
1609 0xE8 => {
1610 let immediate = self.aux_read_immediate_data(ram) as i8;
1611 self.add_sp_i8(immediate);
1612 },
1613 0xE9 => {self.jp_pc_16(self.regs[REG_H], self.regs[REG_L]);},
1614 0xEA => {
1615 let lsh = self.aux_read_immediate_data(ram);
1616 let msh = self.aux_read_immediate_data(ram);
1617 self.ld_16a_r8(ram, msh, lsh, REG_A);
1618 },
1619 0xEB => {self.invalid_instruction(0xEB);},
1620 0xEC => {self.invalid_instruction(0xEC);},
1621 0xED => {self.invalid_instruction(0xED);},
1622 0xEE => {
1623 let num = self.aux_read_immediate_data(ram);
1624 self.xor_r8_8(REG_A, num);
1625 },
1626 0xEF => {self.rst(ram, 0x28);},
1627 0xF0 => {
1628 let lsh = self.aux_read_immediate_data(ram);
1629 self.ld_r8_16a(ram, REG_A, 0xFF, lsh)
1630 },
1631 0xF1 => {self.pop_r16(ram, REG_A, REG_F);},
1632 0xF2 => {self.ld_r8_16a(ram, REG_A, 0xFF, self.regs[REG_C]);},
1633 0xF3 => {self.di();},
1634 0xF4 => {self.invalid_instruction(0xF4);},
1635 0xF5 => {self.push_r16(ram, REG_A, REG_F);},
1636 0xF6 => {
1637 let num = self.aux_read_immediate_data(ram);
1638 self.or_r8_8(REG_A, num);
1639 },
1640 0xF7 => {self.rst(ram, 0x30);},
1641 0xF8 => {
1642 let immediate = self.aux_read_immediate_data(ram) as i8;
1643 self.ld_hl_sp_plus(immediate);
1644 },
1645 0xF9 => {self.ld_sp_r16( REG_H, REG_L);},
1646 0xFA => {
1647 let lsh = self.aux_read_immediate_data(ram);
1648 let msh = self.aux_read_immediate_data(ram);
1649 self.ld_r8_16a(ram, REG_A, msh, lsh);
1650 },
1651 0xFB => {self.ei();},
1652 0xFC => {self.invalid_instruction(0xFC);},
1653 0xFD => {self.invalid_instruction(0xFD);},
1654 0xFE => {
1655 let num = self.aux_read_immediate_data(ram);
1656 self.cp_r8_8(REG_A, num);
1657 },
1658 0xFF => {self.rst(ram, 0x38);}
1659 }
1660
1661 self.pc.current_instruction_cycles += ZERO_INSTRUCTION_TIME_TABLE[instruction as usize];
1662 }
1663 else
1664 {
1665 let cb_instruction = self.aux_read_immediate_data(ram);
1666
1667 match cb_instruction {
1671 0x00 => {self.rlc_r8(REG_B);},
1672 0x01 => {self.rlc_r8(REG_C);},
1673 0x02 => {self.rlc_r8(REG_D);},
1674 0x03 => {self.rlc_r8(REG_E);},
1675 0x04 => {self.rlc_r8(REG_H);},
1676 0x05 => {self.rlc_r8(REG_L);},
1677 0x06 => {self.rlc_r16a(ram, REG_H, REG_L);},
1678 0x07 => {self.rlc_r8(REG_A);},
1679 0x08 => {self.rrc_r8(REG_B);},
1680 0x09 => {self.rrc_r8(REG_C);},
1681 0x0A => {self.rrc_r8(REG_D);},
1682 0x0B => {self.rrc_r8(REG_E);},
1683 0x0C => {self.rrc_r8(REG_H);},
1684 0x0D => {self.rrc_r8(REG_L);},
1685 0x0E => {self.rrc_r16a(ram, REG_H, REG_L);},
1686 0x0F => {self.rrc_r8(REG_A);},
1687 0x10 => {self.rl_r8(REG_B);},
1688 0x11 => {self.rl_r8(REG_C);},
1689 0x12 => {self.rl_r8(REG_D);},
1690 0x13 => {self.rl_r8(REG_E);},
1691 0x14 => {self.rl_r8(REG_H);},
1692 0x15 => {self.rl_r8(REG_L);},
1693 0x16 => {self.rl_r16a(ram, REG_H, REG_L);},
1694 0x17 => {self.rl_r8(REG_A);},
1695 0x18 => {self.rr_r8(REG_B);},
1696 0x19 => {self.rr_r8(REG_C);},
1697 0x1A => {self.rr_r8(REG_D);},
1698 0x1B => {self.rr_r8(REG_E);},
1699 0x1C => {self.rr_r8(REG_H);},
1700 0x1D => {self.rr_r8(REG_L);},
1701 0x1E => {self.rr_r16a(ram, REG_H, REG_L);},
1702 0x1F => {self.rr_r8(REG_A);},
1703 0x20 => {self.sla_r8(REG_B);},
1704 0x21 => {self.sla_r8(REG_C);},
1705 0x22 => {self.sla_r8(REG_D);},
1706 0x23 => {self.sla_r8(REG_E);},
1707 0x24 => {self.sla_r8(REG_H);},
1708 0x25 => {self.sla_r8(REG_L);},
1709 0x26 => {self.sla_r16a(ram, REG_H, REG_L);},
1710 0x27 => {self.sla_r8(REG_A);},
1711 0x28 => {self.sra_r8(REG_B);},
1712 0x29 => {self.sra_r8(REG_C);},
1713 0x2A => {self.sra_r8(REG_D);},
1714 0x2B => {self.sra_r8(REG_E);},
1715 0x2C => {self.sra_r8(REG_H);},
1716 0x2D => {self.sra_r8(REG_L);},
1717 0x2E => {self.sra_r16a(ram, REG_H, REG_L);},
1718 0x2F => {self.sra_r8(REG_A);},
1719 0x30 => {self.swap_r8(REG_B);},
1720 0x31 => {self.swap_r8(REG_C);},
1721 0x32 => {self.swap_r8(REG_D);},
1722 0x33 => {self.swap_r8(REG_E);},
1723 0x34 => {self.swap_r8(REG_H);},
1724 0x35 => {self.swap_r8(REG_L);},
1725 0x36 => {self.swap_r16a(ram, REG_H, REG_L);},
1726 0x37 => {self.swap_r8(REG_A);},
1727 0x38 => {self.srl_r8(REG_B);},
1728 0x39 => {self.srl_r8(REG_C);},
1729 0x3A => {self.srl_r8(REG_D);},
1730 0x3B => {self.srl_r8(REG_E);},
1731 0x3C => {self.srl_r8(REG_H);},
1732 0x3D => {self.srl_r8(REG_L);},
1733 0x3E => {self.srl_r16a(ram, REG_H, REG_L);},
1734 0x3F => {self.srl_r8(REG_A);},
1735 0x40 => {self.bit_r8(0, REG_B);},
1736 0x41 => {self.bit_r8(0, REG_C);},
1737 0x42 => {self.bit_r8(0, REG_D);},
1738 0x43 => {self.bit_r8(0, REG_E);},
1739 0x44 => {self.bit_r8(0, REG_H);},
1740 0x45 => {self.bit_r8(0, REG_L);},
1741 0x46 => {self.bit_r16a(ram, 0, REG_H, REG_L);},
1742 0x47 => {self.bit_r8(0, REG_A);},
1743 0x48 => {self.bit_r8(1, REG_B);},
1744 0x49 => {self.bit_r8(1, REG_C);},
1745 0x4A => {self.bit_r8(1, REG_D);},
1746 0x4B => {self.bit_r8(1, REG_E);},
1747 0x4C => {self.bit_r8(1, REG_H);},
1748 0x4D => {self.bit_r8(1, REG_L);},
1749 0x4E => {self.bit_r16a(ram, 1, REG_H, REG_L);},
1750 0x4F => {self.bit_r8(1, REG_A);},
1751 0x50 => {self.bit_r8(2, REG_B);},
1752 0x51 => {self.bit_r8(2, REG_C);},
1753 0x52 => {self.bit_r8(2, REG_D);},
1754 0x53 => {self.bit_r8(2, REG_E);},
1755 0x54 => {self.bit_r8(2, REG_H);},
1756 0x55 => {self.bit_r8(2, REG_L);},
1757 0x56 => {self.bit_r16a(ram, 2, REG_H, REG_L);},
1758 0x57 => {self.bit_r8(2, REG_A);},
1759 0x58 => {self.bit_r8(3, REG_B);},
1760 0x59 => {self.bit_r8(3, REG_C);},
1761 0x5A => {self.bit_r8(3, REG_D);},
1762 0x5B => {self.bit_r8(3, REG_E);},
1763 0x5C => {self.bit_r8(3, REG_H);},
1764 0x5D => {self.bit_r8(3, REG_L);},
1765 0x5E => {self.bit_r16a(ram, 3, REG_H, REG_L);},
1766 0x5F => {self.bit_r8(3, REG_A);},
1767 0x60 => {self.bit_r8(4, REG_B);},
1768 0x61 => {self.bit_r8(4, REG_C);},
1769 0x62 => {self.bit_r8(4, REG_D);},
1770 0x63 => {self.bit_r8(4, REG_E);},
1771 0x64 => {self.bit_r8(4, REG_H);},
1772 0x65 => {self.bit_r8(4, REG_L);},
1773 0x66 => {self.bit_r16a(ram, 4, REG_H, REG_L);},
1774 0x67 => {self.bit_r8(4, REG_A);},
1775 0x68 => {self.bit_r8(5, REG_B);},
1776 0x69 => {self.bit_r8(5, REG_C);},
1777 0x6A => {self.bit_r8(5, REG_D);},
1778 0x6B => {self.bit_r8(5, REG_E);},
1779 0x6C => {self.bit_r8(5, REG_H);},
1780 0x6D => {self.bit_r8(5, REG_L);},
1781 0x6E => {self.bit_r16a(ram, 5, REG_H, REG_L);},
1782 0x6F => {self.bit_r8(5, REG_A);},
1783 0x70 => {self.bit_r8(6, REG_B);},
1784 0x71 => {self.bit_r8(6, REG_C);},
1785 0x72 => {self.bit_r8(6, REG_D);},
1786 0x73 => {self.bit_r8(6, REG_E);},
1787 0x74 => {self.bit_r8(6, REG_H);},
1788 0x75 => {self.bit_r8(6, REG_L);},
1789 0x76 => {self.bit_r16a(ram, 6, REG_H, REG_L);},
1790 0x77 => {self.bit_r8(6, REG_A);},
1791 0x78 => {self.bit_r8(7, REG_B);},
1792 0x79 => {self.bit_r8(7, REG_C);},
1793 0x7A => {self.bit_r8(7, REG_D);},
1794 0x7B => {self.bit_r8(7, REG_E);},
1795 0x7C => {self.bit_r8(7, REG_H);},
1796 0x7D => {self.bit_r8(7, REG_L);},
1797 0x7E => {self.bit_r16a(ram, 7, REG_H, REG_L);},
1798 0x7F => {self.bit_r8(7, REG_A);},
1799 0x80 => {self.res_r8(0, REG_B);},
1800 0x81 => {self.res_r8(0, REG_C);},
1801 0x82 => {self.res_r8(0, REG_D);},
1802 0x83 => {self.res_r8(0, REG_E);},
1803 0x84 => {self.res_r8(0, REG_H);},
1804 0x85 => {self.res_r8(0, REG_L);},
1805 0x86 => {self.res_r16a(ram, 0, REG_H, REG_L);},
1806 0x87 => {self.res_r8(0, REG_A);},
1807 0x88 => {self.res_r8(1, REG_B);},
1808 0x89 => {self.res_r8(1, REG_C);},
1809 0x8A => {self.res_r8(1, REG_D);},
1810 0x8B => {self.res_r8(1, REG_E);},
1811 0x8C => {self.res_r8(1, REG_H);},
1812 0x8D => {self.res_r8(1, REG_L);},
1813 0x8E => {self.res_r16a(ram, 1, REG_H, REG_L);},
1814 0x8F => {self.res_r8(1, REG_A);},
1815 0x90 => {self.res_r8(2, REG_B);},
1816 0x91 => {self.res_r8(2, REG_C);},
1817 0x92 => {self.res_r8(2, REG_D);},
1818 0x93 => {self.res_r8(2, REG_E);},
1819 0x94 => {self.res_r8(2, REG_H);},
1820 0x95 => {self.res_r8(2, REG_L);},
1821 0x96 => {self.res_r16a(ram, 2, REG_H, REG_L);},
1822 0x97 => {self.res_r8(2, REG_A);},
1823 0x98 => {self.res_r8(3, REG_B);},
1824 0x99 => {self.res_r8(3, REG_C);},
1825 0x9A => {self.res_r8(3, REG_D);},
1826 0x9B => {self.res_r8(3, REG_E);},
1827 0x9C => {self.res_r8(3, REG_H);},
1828 0x9D => {self.res_r8(3, REG_L);},
1829 0x9E => {self.res_r16a(ram, 3, REG_H, REG_L);},
1830 0x9F => {self.res_r8(3, REG_A);},
1831 0xA0 => {self.res_r8(4, REG_B);},
1832 0xA1 => {self.res_r8(4, REG_C);},
1833 0xA2 => {self.res_r8(4, REG_D);},
1834 0xA3 => {self.res_r8(4, REG_E);},
1835 0xA4 => {self.res_r8(4, REG_H);},
1836 0xA5 => {self.res_r8(4, REG_L);},
1837 0xA6 => {self.res_r16a(ram, 4, REG_H, REG_L);},
1838 0xA7 => {self.res_r8(4, REG_A);},
1839 0xA8 => {self.res_r8(5, REG_B);},
1840 0xA9 => {self.res_r8(5, REG_C);},
1841 0xAA => {self.res_r8(5, REG_D);},
1842 0xAB => {self.res_r8(5, REG_E);},
1843 0xAC => {self.res_r8(5, REG_H);},
1844 0xAD => {self.res_r8(5, REG_L);},
1845 0xAE => {self.res_r16a(ram, 5, REG_H, REG_L);},
1846 0xAF => {self.res_r8(5, REG_A);},
1847 0xB0 => {self.res_r8(6, REG_B);},
1848 0xB1 => {self.res_r8(6, REG_C);},
1849 0xB2 => {self.res_r8(6, REG_D);},
1850 0xB3 => {self.res_r8(6, REG_E);},
1851 0xB4 => {self.res_r8(6, REG_H);},
1852 0xB5 => {self.res_r8(6, REG_L);},
1853 0xB6 => {self.res_r16a(ram, 6, REG_H, REG_L);},
1854 0xB7 => {self.res_r8(6, REG_A);},
1855 0xB8 => {self.res_r8(7, REG_B);},
1856 0xB9 => {self.res_r8(7, REG_C);},
1857 0xBA => {self.res_r8(7, REG_D);},
1858 0xBB => {self.res_r8(7, REG_E);},
1859 0xBC => {self.res_r8(7, REG_H);},
1860 0xBD => {self.res_r8(7, REG_L);},
1861 0xBE => {self.res_r16a(ram, 7, REG_H, REG_L);},
1862 0xBF => {self.res_r8(7, REG_A);},
1863 0xC0 => {self.set_r8(0, REG_B);},
1864 0xC1 => {self.set_r8(0, REG_C);},
1865 0xC2 => {self.set_r8(0, REG_D);},
1866 0xC3 => {self.set_r8(0, REG_E);},
1867 0xC4 => {self.set_r8(0, REG_H);},
1868 0xC5 => {self.set_r8(0, REG_L);},
1869 0xC6 => {self.set_r16a(ram, 0, REG_H, REG_L);},
1870 0xC7 => {self.set_r8(0, REG_A);},
1871 0xC8 => {self.set_r8(1, REG_B);},
1872 0xC9 => {self.set_r8(1, REG_C);},
1873 0xCA => {self.set_r8(1, REG_D);},
1874 0xCB => {self.set_r8(1, REG_E);},
1875 0xCC => {self.set_r8(1, REG_H);},
1876 0xCD => {self.set_r8(1, REG_L);},
1877 0xCE => {self.set_r16a(ram, 1, REG_H, REG_L);},
1878 0xCF => {self.set_r8(1, REG_A);},
1879 0xD0 => {self.set_r8(2, REG_B);},
1880 0xD1 => {self.set_r8(2, REG_C);},
1881 0xD2 => {self.set_r8(2, REG_D);},
1882 0xD3 => {self.set_r8(2, REG_E);},
1883 0xD4 => {self.set_r8(2, REG_H);},
1884 0xD5 => {self.set_r8(2, REG_L);},
1885 0xD6 => {self.set_r16a(ram, 2, REG_H, REG_L);},
1886 0xD7 => {self.set_r8(2, REG_A);},
1887 0xD8 => {self.set_r8(3, REG_B);},
1888 0xD9 => {self.set_r8(3, REG_C);},
1889 0xDA => {self.set_r8(3, REG_D);},
1890 0xDB => {self.set_r8(3, REG_E);},
1891 0xDC => {self.set_r8(3, REG_H);},
1892 0xDD => {self.set_r8(3, REG_L);},
1893 0xDE => {self.set_r16a(ram, 3, REG_H, REG_L);},
1894 0xDF => {self.set_r8(3, REG_A);},
1895 0xE0 => {self.set_r8(4, REG_B);},
1896 0xE1 => {self.set_r8(4, REG_C);},
1897 0xE2 => {self.set_r8(4, REG_D);},
1898 0xE3 => {self.set_r8(4, REG_E);},
1899 0xE4 => {self.set_r8(4, REG_H);},
1900 0xE5 => {self.set_r8(4, REG_L);},
1901 0xE6 => {self.set_r16a(ram, 4, REG_H, REG_L);},
1902 0xE7 => {self.set_r8(4, REG_A);},
1903 0xE8 => {self.set_r8(5, REG_B);},
1904 0xE9 => {self.set_r8(5, REG_C);},
1905 0xEA => {self.set_r8(5, REG_D);},
1906 0xEB => {self.set_r8(5, REG_E);},
1907 0xEC => {self.set_r8(5, REG_H);},
1908 0xED => {self.set_r8(5, REG_L);},
1909 0xEE => {self.set_r16a(ram, 5, REG_H, REG_L);},
1910 0xEF => {self.set_r8(5, REG_A);},
1911 0xF0 => {self.set_r8(6, REG_B);},
1912 0xF1 => {self.set_r8(6, REG_C);},
1913 0xF2 => {self.set_r8(6, REG_D);},
1914 0xF3 => {self.set_r8(6, REG_E);},
1915 0xF4 => {self.set_r8(6, REG_H);},
1916 0xF5 => {self.set_r8(6, REG_L);},
1917 0xF6 => {self.set_r16a(ram, 6, REG_H, REG_L);},
1918 0xF7 => {self.set_r8(6, REG_A);},
1919 0xF8 => {self.set_r8(7, REG_B);},
1920 0xF9 => {self.set_r8(7, REG_C);},
1921 0xFA => {self.set_r8(7, REG_D);},
1922 0xFB => {self.set_r8(7, REG_E);},
1923 0xFC => {self.set_r8(7, REG_H);},
1924 0xFD => {self.set_r8(7, REG_L);},
1925 0xFE => {self.set_r16a(ram, 7, REG_H, REG_L);},
1926 0xFF => {self.set_r8(7, REG_A);}
1927 }
1928
1929 self.pc.current_instruction_cycles += CB_INSTRUCTION_TIME_TABLE[cb_instruction as usize];
1930 }
1931
1932 self.aux_inc_pc();
1933 }
1934
1935 fn invalid_instruction(&self, opcode: u8)
1936 {
1937 panic!("Tried to execute invalid instruction {:X?}", opcode);
1938 }
1939
1940 #[allow(dead_code)]
1945 fn aux_get_reg(&self, regnum: usize) -> u8 { self.regs[regnum] }
1946 #[allow(dead_code)]
1947 fn aux_get_sp(&self) -> u16 { self.sp }
1948 #[allow(dead_code)]
1949 fn aux_get_pc(&self) -> ProgramCounter { self.pc }
1950
1951}