comparison src/console/Gb_Cpu.cxx @ 12:3da1b8942b8b trunk

[svn] - remove src/Input src/Output src/Effect src/General src/Visualization src/Container
author nenolod
date Mon, 18 Sep 2006 03:14:20 -0700
parents src/Input/console/Gb_Cpu.cxx@13389e613d67
children fb513e10174e
comparison
equal deleted inserted replaced
11:cff1d04026ae 12:3da1b8942b8b
1
2 // Game_Music_Emu 0.3.0. http://www.slack.net/~ant/
3
4 #include "Gb_Cpu.h"
5
6 #include <string.h>
7 #include <limits.h>
8
9 #include "blargg_endian.h"
10
11 /* Copyright (C) 2003-2006 Shay Green. This module is free software; you
12 can redistribute it and/or modify it under the terms of the GNU Lesser
13 General Public License as published by the Free Software Foundation; either
14 version 2.1 of the License, or (at your option) any later version. This
15 module is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
18 more details. You should have received a copy of the GNU Lesser General
19 Public License along with this module; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
21
22 #include BLARGG_SOURCE_BEGIN
23
24 // Common instructions:
25 //
26 // 365880 FA LD A,IND16
27 // 355863 20 JR NZ
28 // 313655 21 LD HL,IMM
29 // 274580 28 JR Z
30 // 252878 FE CMP IMM
31 // 230541 7E LD A,(HL)
32 // 226209 2A LD A,(HL+)
33 // 217467 CD CALL
34 // 212034 C9 RET
35 // 208376 CB CB prefix
36 //
37 // 27486 CB 7E BIT 7,(HL)
38 // 15925 CB 76 BIT 6,(HL)
39 // 13035 CB 19 RR C
40 // 11557 CB 7F BIT 7,A
41 // 10898 CB 37 SWAP A
42 // 10208 CB 66 BIT 4,(HL)
43
44 #if BLARGG_NONPORTABLE
45 #define PAGE_OFFSET( addr ) (addr)
46 #else
47 #define PAGE_OFFSET( addr ) ((addr) & (page_size - 1))
48 #endif
49
50 Gb_Cpu::Gb_Cpu( Gbs_Emu* gbs_emu )
51 {
52 callback_data = gbs_emu;
53 rst_base = 0;
54 reset();
55 }
56
57 inline void Gb_Cpu::set_code_page( int i, uint8_t const* p )
58 {
59 code_map [i] = p - PAGE_OFFSET( i * page_size );
60 }
61
62 void Gb_Cpu::reset( const void* unmapped_code_page, reader_t read, writer_t write )
63 {
64 interrupts_enabled = false;
65 remain_ = 0;
66
67 r.pc = 0;
68 r.sp = 0;
69 r.flags = 0;
70 r.a = 0;
71 r.b = 0;
72 r.c = 0;
73 r.d = 0;
74 r.e = 0;
75 r.h = 0;
76 r.l = 0;
77
78 for ( int i = 0; i < page_count + 1; i++ )
79 {
80 set_code_page( i, (uint8_t*) unmapped_code_page );
81 data_reader [i] = read;
82 data_writer [i] = write;
83 }
84 }
85
86 void Gb_Cpu::map_code( gb_addr_t start, unsigned long size, const void* data )
87 {
88 // address range must begin and end on page boundaries
89 require( start % page_size == 0 );
90 require( size % page_size == 0 );
91
92 unsigned first_page = start / page_size;
93 for ( unsigned i = size / page_size; i--; )
94 set_code_page( first_page + i, (uint8_t*) data + i * page_size );
95 }
96
97 void Gb_Cpu::map_memory( gb_addr_t start, unsigned long size, reader_t read, writer_t write )
98 {
99 // address range must begin and end on page boundaries
100 require( start % page_size == 0 );
101 require( size % page_size == 0 );
102
103 unsigned first_page = start / page_size;
104 for ( unsigned i = size / page_size; i--; )
105 {
106 data_reader [first_page + i] = read;
107 data_writer [first_page + i] = write;
108 }
109 }
110
111 // Note: 'addr' is evaulated more than once in the following macros, so it
112 // must not contain side-effects.
113
114 #define READ( addr ) (data_reader [(addr) >> page_bits]( callback_data, addr ))
115 #define WRITE( addr, data ) (data_writer [(addr) >> page_bits]( callback_data, addr, data ))
116
117 #define READ_PROG( addr ) (code_map [(addr) >> page_bits] [PAGE_OFFSET( addr )])
118 #define READ_PROG16( addr ) GET_LE16( &READ_PROG( addr ) )
119
120 int Gb_Cpu::read( gb_addr_t addr )
121 {
122 return READ( addr );
123 }
124
125 void Gb_Cpu::write( gb_addr_t addr, int data )
126 {
127 WRITE( addr, data );
128 }
129
130 BOOST::uint8_t* Gb_Cpu::get_code( gb_addr_t addr )
131 {
132 return (uint8_t*) &READ_PROG( addr );
133 }
134
135 #ifndef GB_CPU_GLUE_ONLY
136
137 const unsigned z_flag = 0x80;
138 const unsigned n_flag = 0x40;
139 const unsigned h_flag = 0x20;
140 const unsigned c_flag = 0x10;
141
142 #include BLARGG_ENABLE_OPTIMIZER
143
144 Gb_Cpu::result_t Gb_Cpu::run( long cycle_count )
145 {
146 const int cycles_per_instruction = 4;
147
148 // to do: use cycle table
149 remain_ = cycle_count + cycles_per_instruction;
150
151 Gb_Cpu::result_t result = result_cycles;
152
153 #if BLARGG_CPU_POWERPC
154 const reader_t* data_reader = this->data_reader; // cache
155 const writer_t* data_writer = this->data_writer; // cache
156 #endif
157
158 union {
159 struct {
160 #if BLARGG_BIG_ENDIAN
161 uint8_t b, c, d, e, h, l, unused, a;
162 # define R8( n ) (r8_ [n])
163 #elif BLARGG_LITTLE_ENDIAN
164 uint8_t c, b, e, d, l, h, a, unused;
165 # define R8( n ) (r8_ [(n) ^ 1])
166 #else
167 # error "Byte order of CPU must be known"
168 #endif
169 } rg; // registers
170
171 struct {
172 BOOST::uint16_t bc, de, hl, unused; // pairs
173 } rp;
174
175 uint8_t r8_ [8]; // indexed registers (use R8 macro due to endian dependence)
176 BOOST::uint16_t r16 [4]; // indexed pairs
177 };
178 BOOST_STATIC_ASSERT( sizeof rg == 8 && sizeof rp == 8 );
179
180 rg.a = r.a;
181 rg.b = r.b;
182 rg.c = r.c;
183 rg.d = r.d;
184 rg.e = r.e;
185 rg.h = r.h;
186 rg.l = r.l;
187 unsigned pc = r.pc;
188 unsigned sp = r.sp;
189 unsigned flags = r.flags;
190
191 loop:
192
193 int new_remain = remain_ - cycles_per_instruction;
194
195 check( (unsigned) pc < 0x10000 );
196 check( (unsigned) sp < 0x10000 );
197 check( (flags & ~0xf0) == 0 );
198
199 uint8_t const* page = code_map [pc >> page_bits];
200 unsigned op = page [PAGE_OFFSET( pc )];
201 unsigned data = page [PAGE_OFFSET( pc ) + 1];
202 check( op == 0xC9 || &READ_PROG( pc + 1 ) == &page [PAGE_OFFSET( pc ) + 1] );
203
204 pc++;
205
206 remain_ = new_remain;
207 if ( new_remain <= 0 )
208 goto stop;
209
210 switch ( op )
211 {
212
213 #define BRANCH( cond ) \
214 { \
215 pc++; \
216 int offset = (BOOST::int8_t) data; \
217 if ( !(cond) ) goto loop; \
218 pc += offset; \
219 goto loop; \
220 }
221
222 // Most Common
223
224 case 0x20: // JR NZ
225 BRANCH( !(flags & z_flag) )
226
227 case 0x21: // LD HL,IMM (common)
228 rp.hl = READ_PROG16( pc );
229 pc += 2;
230 goto loop;
231
232 case 0x28: // JR Z
233 BRANCH( flags & z_flag )
234
235 {
236 unsigned temp;
237
238 case 0xF0: // LD A,(0xff00+imm)
239 temp = data + 0xff00;
240 pc++;
241 goto ld_a_ind_comm;
242
243 case 0xF2: // LD A,(0xff00+C)
244 temp = rg.c + 0xff00;
245 goto ld_a_ind_comm;
246
247 case 0x0A: // LD A,(BC)
248 temp = rp.bc;
249 goto ld_a_ind_comm;
250
251 case 0x3A: // LD A,(HL-)
252 temp = rp.hl;
253 rp.hl = temp - 1;
254 goto ld_a_ind_comm;
255
256 case 0x1A: // LD A,(DE)
257 temp = rp.de;
258 goto ld_a_ind_comm;
259
260 case 0x2A: // LD A,(HL+) (common)
261 temp = rp.hl;
262 rp.hl = temp + 1;
263 goto ld_a_ind_comm;
264
265 case 0xFA: // LD A,IND16 (common)
266 temp = READ_PROG16( pc );
267 pc += 2;
268 ld_a_ind_comm:
269 rg.a = READ( temp );
270 goto loop;
271 }
272
273 case 0xBE: // CMP (HL)
274 data = READ( rp.hl );
275 goto cmp_comm;
276
277 case 0xB8: // CMP B
278 case 0xB9: // CMP C
279 case 0xBA: // CMP D
280 case 0xBB: // CMP E
281 case 0xBC: // CMP H
282 case 0xBD: // CMP L
283 data = R8( op & 7 );
284 goto cmp_comm;
285
286 case 0xFE: // CMP IMM
287 pc++;
288 cmp_comm:
289 op = rg.a;
290 data = op - data;
291 sub_set_flags:
292 flags = ((op & 15) - (data & 15)) & h_flag;
293 flags |= (data >> 4) & c_flag;
294 flags |= n_flag;
295 if ( data & 0xff )
296 goto loop;
297 flags |= z_flag;
298 goto loop;
299
300 case 0x46: // LD B,(HL)
301 case 0x4E: // LD C,(HL)
302 case 0x56: // LD D,(HL)
303 case 0x5E: // LD E,(HL)
304 case 0x66: // LD H,(HL)
305 case 0x6E: // LD L,(HL)
306 case 0x7E: // LD A,(HL)
307 R8( (op >> 3) & 7 ) = READ( rp.hl );
308 goto loop;
309
310 case 0xC4: // CNZ (next-most-common)
311 pc += 2;
312 if ( flags & z_flag )
313 goto loop;
314 call:
315 pc -= 2;
316 case 0xCD: // CALL (most-common)
317 data = pc + 2;
318 pc = READ_PROG16( pc );
319 push:
320 sp = (sp - 1) & 0xFFFF;
321 WRITE( sp, data >> 8 );
322 sp = (sp - 1) & 0xFFFF;
323 WRITE( sp, data & 0xff );
324 goto loop;
325
326 case 0xC8: // RNZ (next-most-common)
327 if ( !(flags & z_flag) )
328 goto loop;
329 case 0xC9: // RET (most common)
330 ret:
331 pc = READ( sp );
332 pc += 0x100 * READ( (sp + 1) & 0xFFFF );
333 sp = (sp + 2) & 0xFFFF;
334 goto loop;
335
336 case 0x00: // NOP
337 case 0x40: // LD B,B
338 case 0x49: // LD C,C
339 case 0x52: // LD D,D
340 case 0x5B: // LD E,E
341 case 0x64: // LD H,H
342 case 0x6D: // LD L,L
343 case 0x7F: // LD A,A
344 goto loop;
345
346 // CB Instructions
347
348 case 0xCB:
349 pc++;
350 // now data is the opcode
351 switch ( data ) {
352
353 {
354 int temp;
355
356 case 0x46: // BIT b,(HL)
357 case 0x4E:
358 case 0x56:
359 case 0x5E:
360 case 0x66:
361 case 0x6E:
362 case 0x76:
363 case 0x7E:
364 temp = READ( rp.hl );
365 goto bit_comm;
366
367 case 0x40: case 0x41: case 0x42: case 0x43: // BIT b,r
368 case 0x44: case 0x45: case 0x47: case 0x48:
369 case 0x49: case 0x4A: case 0x4B: case 0x4C:
370 case 0x4D: case 0x4F: case 0x50: case 0x51:
371 case 0x52: case 0x53: case 0x54: case 0x55:
372 case 0x57: case 0x58: case 0x59: case 0x5A:
373 case 0x5B: case 0x5C: case 0x5D: case 0x5F:
374 case 0x60: case 0x61: case 0x62: case 0x63:
375 case 0x64: case 0x65: case 0x67: case 0x68:
376 case 0x69: case 0x6A: case 0x6B: case 0x6C:
377 case 0x6D: case 0x6F: case 0x70: case 0x71:
378 case 0x72: case 0x73: case 0x74: case 0x75:
379 case 0x77: case 0x78: case 0x79: case 0x7A:
380 case 0x7B: case 0x7C: case 0x7D: case 0x7F:
381 temp = R8( data & 7 );
382 bit_comm:
383 int bit = (~data >> 3) & 7;
384 flags &= ~n_flag;
385 flags |= h_flag | z_flag;
386 flags ^= (temp << bit) & z_flag;
387 goto loop;
388 }
389
390 case 0x86: // RES b,(HL)
391 case 0x8E:
392 case 0x96:
393 case 0x9E:
394 case 0xA6:
395 case 0xAE:
396 case 0xB6:
397 case 0xBE:
398 case 0xC6: // SET b,(HL)
399 case 0xCE:
400 case 0xD6:
401 case 0xDE:
402 case 0xE6:
403 case 0xEE:
404 case 0xF6:
405 case 0xFE: {
406 int temp = READ( rp.hl );
407 int bit = 1 << ((data >> 3) & 7);
408 temp &= ~bit;
409 if ( !(data & 0x40) )
410 bit = 0;
411 WRITE( rp.hl, temp | bit );
412 goto loop;
413 }
414
415 case 0xC0: case 0xC1: case 0xC2: case 0xC3: // SET b,r
416 case 0xC4: case 0xC5: case 0xC7: case 0xC8:
417 case 0xC9: case 0xCA: case 0xCB: case 0xCC:
418 case 0xCD: case 0xCF: case 0xD0: case 0xD1:
419 case 0xD2: case 0xD3: case 0xD4: case 0xD5:
420 case 0xD7: case 0xD8: case 0xD9: case 0xDA:
421 case 0xDB: case 0xDC: case 0xDD: case 0xDF:
422 case 0xE0: case 0xE1: case 0xE2: case 0xE3:
423 case 0xE4: case 0xE5: case 0xE7: case 0xE8:
424 case 0xE9: case 0xEA: case 0xEB: case 0xEC:
425 case 0xED: case 0xEF: case 0xF0: case 0xF1:
426 case 0xF2: case 0xF3: case 0xF4: case 0xF5:
427 case 0xF7: case 0xF8: case 0xF9: case 0xFA:
428 case 0xFB: case 0xFC: case 0xFD: case 0xFF:
429 R8( data & 7 ) |= 1 << ((data >> 3) & 7);
430 goto loop;
431
432 case 0x80: case 0x81: case 0x82: case 0x83: // RES b,r
433 case 0x84: case 0x85: case 0x87: case 0x88:
434 case 0x89: case 0x8A: case 0x8B: case 0x8C:
435 case 0x8D: case 0x8F: case 0x90: case 0x91:
436 case 0x92: case 0x93: case 0x94: case 0x95:
437 case 0x97: case 0x98: case 0x99: case 0x9A:
438 case 0x9B: case 0x9C: case 0x9D: case 0x9F:
439 case 0xA0: case 0xA1: case 0xA2: case 0xA3:
440 case 0xA4: case 0xA5: case 0xA7: case 0xA8:
441 case 0xA9: case 0xAA: case 0xAB: case 0xAC:
442 case 0xAD: case 0xAF: case 0xB0: case 0xB1:
443 case 0xB2: case 0xB3: case 0xB4: case 0xB5:
444 case 0xB7: case 0xB8: case 0xB9: case 0xBA:
445 case 0xBB: case 0xBC: case 0xBD: case 0xBF:
446 R8( data & 7 ) &= ~(1 << ((data >> 3) & 7));
447 goto loop;
448
449 {
450 int temp;
451 case 0x36: // SWAP (HL)
452 temp = READ( rp.hl );
453 goto swap_comm;
454
455 case 0x30: // SWAP B
456 case 0x31: // SWAP C
457 case 0x32: // SWAP D
458 case 0x33: // SWAP E
459 case 0x34: // SWAP H
460 case 0x35: // SWAP L
461 case 0x37: // SWAP A
462 temp = R8( data & 7 );
463 swap_comm:
464 op = (temp >> 4) | (temp << 4);
465 flags = 0;
466 goto shift_comm;
467 }
468
469 // Shift/Rotate
470
471 case 0x06: // RLC (HL)
472 case 0x16: // RL (HL)
473 case 0x26: // SLA (HL)
474 op = READ( rp.hl );
475 goto rl_comm;
476
477 case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x27: // SLA A
478 case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x07: // RLC A
479 case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x17: // RL A
480 op = R8( data & 7 );
481 goto rl_comm;
482
483 case 0x3E: // SRL (HL)
484 data += 0x10; // bump up to 0x4n to avoid preserving sign bit
485 case 0x1E: // RR (HL)
486 case 0x0E: // RRC (HL)
487 case 0x2E: // SRA (HL)
488 op = READ( rp.hl );
489 goto rr_comm;
490
491 case 0x38: case 0x39: case 0x3A: case 0x3B: case 0x3C: case 0x3D: case 0x3F: // SRL A
492 data += 0x10; // bump up to 0x4n
493 case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1F: // RR A
494 case 0x08: case 0x09: case 0x0A: case 0x0B: case 0x0C: case 0x0D: case 0x0F: // RRC A
495 case 0x28: case 0x29: case 0x2A: case 0x2B: case 0x2C: case 0x2D: case 0x2F: // SRA A
496 op = R8( data & 7 );
497 goto rr_comm;
498
499 } // CB op
500 assert( false ); // unhandled CB op
501
502 case 0x07: // RLCA
503 case 0x17: // RLA
504 data = op;
505 op = rg.a;
506 rl_comm:
507 op <<= 1;
508 op |= ((data & flags) >> 4) & 1; // RL and carry is set
509 flags = (op >> 4) & c_flag; // C = bit shifted out
510 if ( data < 0x10 ) // RLC
511 op |= op >> 8;
512 // SLA doesn't fill lower bit
513 goto shift_comm;
514
515 case 0x0F: // RRCA
516 case 0x1F: // RRA
517 data = op;
518 op = rg.a;
519 rr_comm:
520 op |= (data & flags) << 4; // RR and carry is set
521 flags = (op << 4) & c_flag; // C = bit shifted out
522 if ( data < 0x10 ) // RRC
523 op |= op << 8;
524 op >>= 1;
525 if ( data & 0x20 ) // SRA propagates sign bit
526 op |= (op << 1) & 0x80;
527 shift_comm:
528 data &= 7;
529 if ( !(op & 0xff) )
530 flags |= z_flag;
531 if ( data == 6 )
532 goto write_hl_op_ff;
533 R8( data ) = op;
534 goto loop;
535
536 // Load
537
538 case 0x70: // LD (HL),B
539 case 0x71: // LD (HL),C
540 case 0x72: // LD (HL),D
541 case 0x73: // LD (HL),E
542 case 0x74: // LD (HL),H
543 case 0x75: // LD (HL),L
544 case 0x77: // LD (HL),A
545 op = R8( op & 7 );
546 write_hl_op_ff:
547 WRITE( rp.hl, op & 0xff );
548 goto loop;
549
550 case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x47: // LD r,r
551 case 0x48: case 0x4A: case 0x4B: case 0x4C: case 0x4D: case 0x4F:
552 case 0x50: case 0x51: case 0x53: case 0x54: case 0x55: case 0x57:
553 case 0x58: case 0x59: case 0x5A: case 0x5C: case 0x5D: case 0x5F:
554 case 0x60: case 0x61: case 0x62: case 0x63: case 0x65: case 0x67:
555 case 0x68: case 0x69: case 0x6A: case 0x6B: case 0x6C: case 0x6F:
556 case 0x78: case 0x79: case 0x7A: case 0x7B: case 0x7C: case 0x7D:
557 R8( (op >> 3) & 7 ) = R8( op & 7 );
558 goto loop;
559
560 case 0x08: // LD IND16,SP
561 data = READ_PROG16( pc );
562 pc += 2;
563 WRITE( data, sp&0xff );
564 data++;
565 WRITE( data, sp >> 8 );
566 goto loop;
567
568 case 0xF9: // LD SP,HL
569 sp = rp.hl;
570 goto loop;
571
572 case 0x31: // LD SP,IMM
573 sp = READ_PROG16( pc );
574 pc += 2;
575 goto loop;
576
577 case 0x01: // LD BC,IMM
578 case 0x11: // LD DE,IMM
579 r16 [op >> 4] = READ_PROG16( pc );
580 pc += 2;
581 goto loop;
582
583 {
584 unsigned temp;
585 case 0xE0: // LD (0xff00+imm),A
586 temp = data + 0xff00;
587 pc++;
588 goto write_data_rg_a;
589
590 case 0xE2: // LD (0xff00+C),A
591 temp = rg.c + 0xff00;
592 goto write_data_rg_a;
593
594 case 0x32: // LD (HL-),A
595 temp = rp.hl;
596 rp.hl = temp - 1;
597 goto write_data_rg_a;
598
599 case 0x02: // LD (BC),A
600 temp = rp.bc;
601 goto write_data_rg_a;
602
603 case 0x12: // LD (DE),A
604 temp = rp.de;
605 goto write_data_rg_a;
606
607 case 0x22: // LD (HL+),A
608 temp = rp.hl;
609 rp.hl = temp + 1;
610 goto write_data_rg_a;
611
612 case 0xEA: // LD IND16,A (common)
613 temp = READ_PROG16( pc );
614 pc += 2;
615 write_data_rg_a:
616 WRITE( temp, rg.a );
617 goto loop;
618 }
619
620 case 0x06: // LD B,IMM
621 rg.b = data;
622 pc++;
623 goto loop;
624
625 case 0x0E: // LD C,IMM
626 rg.c = data;
627 pc++;
628 goto loop;
629
630 case 0x16: // LD D,IMM
631 rg.d = data;
632 pc++;
633 goto loop;
634
635 case 0x1E: // LD E,IMM
636 rg.e = data;
637 pc++;
638 goto loop;
639
640 case 0x26: // LD H,IMM
641 rg.h = data;
642 pc++;
643 goto loop;
644
645 case 0x2E: // LD L,IMM
646 rg.l = data;
647 pc++;
648 goto loop;
649
650 case 0x36: // LD (HL),IMM
651 WRITE( rp.hl, data );
652 pc++;
653 goto loop;
654
655 case 0x3E: // LD A,IMM
656 rg.a = data;
657 pc++;
658 goto loop;
659
660 // Increment/Decrement
661
662 case 0x03: // INC BC
663 case 0x13: // INC DE
664 case 0x23: // INC HL
665 r16 [op >> 4]++;
666 goto loop;
667
668 case 0x33: // INC SP
669 sp = (sp + 1) & 0xFFFF;
670 goto loop;
671
672 case 0x0B: // DEC BC
673 case 0x1B: // DEC DE
674 case 0x2B: // DEC HL
675 r16 [op >> 4]--;
676 goto loop;
677
678 case 0x3B: // DEC SP
679 sp = (sp - 1) & 0xFFFF;
680 goto loop;
681
682 case 0x34: // INC (HL)
683 op = rp.hl;
684 data = READ( op );
685 data++;
686 WRITE( op, data & 0xff );
687 goto inc_comm;
688
689 case 0x04: // INC B
690 case 0x0C: // INC C (common)
691 case 0x14: // INC D
692 case 0x1C: // INC E
693 case 0x24: // INC H
694 case 0x2C: // INC L
695 case 0x3C: // INC A
696 op = (op >> 3) & 7;
697 R8( op ) = data = R8( op ) + 1;
698 inc_comm:
699 flags = (flags & c_flag) | (((data & 15) - 1) & h_flag) | ((data >> 1) & z_flag);
700 goto loop;
701
702 case 0x35: // DEC (HL)
703 op = rp.hl;
704 data = READ( op );
705 data--;
706 WRITE( op, data & 0xff );
707 goto dec_comm;
708
709 case 0x05: // DEC B
710 case 0x0D: // DEC C
711 case 0x15: // DEC D
712 case 0x1D: // DEC E
713 case 0x25: // DEC H
714 case 0x2D: // DEC L
715 case 0x3D: // DEC A
716 op = (op >> 3) & 7;
717 data = R8( op ) - 1;
718 R8( op ) = data;
719 dec_comm:
720 flags = (flags & c_flag) | n_flag | (((data & 15) + 0x31) & h_flag);
721 if ( data & 0xff )
722 goto loop;
723 flags |= z_flag;
724 goto loop;
725
726 // Add 16-bit
727
728 {
729 unsigned long temp; // need more than 16 bits for carry
730 unsigned prev;
731
732 case 0xF8: // LD HL,SP+imm
733 temp = BOOST::int8_t (data); // sign-extend to 16 bits
734 pc++;
735 flags = 0;
736 temp += sp;
737 prev = sp;
738 goto add_16_hl;
739
740 case 0xE8: // ADD SP,IMM
741 temp = BOOST::int8_t (data); // sign-extend to 16 bits
742 pc++;
743 flags = 0;
744 temp += sp;
745 prev = sp;
746 sp = temp & 0xffff;
747 goto add_16_comm;
748
749 case 0x39: // ADD HL,SP
750 temp = sp;
751 goto add_hl_comm;
752
753 case 0x09: // ADD HL,BC
754 case 0x19: // ADD HL,DE
755 case 0x29: // ADD HL,HL
756 temp = r16 [op >> 4];
757 add_hl_comm:
758 prev = rp.hl;
759 temp += prev;
760 flags &= z_flag;
761 add_16_hl:
762 rp.hl = temp;
763 add_16_comm:
764 flags |= (temp >> 12) & c_flag;
765 flags |= (((temp & 0x0fff) - (prev & 0x0fff)) >> 7) & h_flag;
766 goto loop;
767 }
768
769 case 0x86: // ADD (HL)
770 data = READ( rp.hl );
771 goto add_comm;
772
773 case 0x80: // ADD B
774 case 0x81: // ADD C
775 case 0x82: // ADD D
776 case 0x83: // ADD E
777 case 0x84: // ADD H
778 case 0x85: // ADD L
779 case 0x87: // ADD A
780 data = R8( op & 7 );
781 goto add_comm;
782
783 case 0xC6: // ADD IMM
784 pc++;
785 add_comm:
786 flags = rg.a;
787 data += flags;
788 flags = ((data & 15) - (flags & 15)) & h_flag;
789 flags |= (data >> 4) & c_flag;
790 rg.a = data;
791 if ( data & 0xff )
792 goto loop;
793 flags |= z_flag;
794 goto loop;
795
796 // Add/Subtract
797
798 case 0x8E: // ADC (HL)
799 data = READ( rp.hl );
800 goto adc_comm;
801
802 case 0x88: // ADC B
803 case 0x89: // ADC C
804 case 0x8A: // ADC D
805 case 0x8B: // ADC E
806 case 0x8C: // ADC H
807 case 0x8D: // ADC L
808 case 0x8F: // ADC A
809 data = R8( op & 7 );
810 goto adc_comm;
811
812 case 0xCE: // ADC IMM
813 pc++;
814 adc_comm:
815 data += (flags >> 4) & 1;
816 data &= 0xff; // to do: does carry get set when sum + carry = 0x100?
817 goto add_comm;
818
819 case 0x96: // SUB (HL)
820 data = READ( rp.hl );
821 goto sub_comm;
822
823 case 0x90: // SUB B
824 case 0x91: // SUB C
825 case 0x92: // SUB D
826 case 0x93: // SUB E
827 case 0x94: // SUB H
828 case 0x95: // SUB L
829 case 0x97: // SUB A
830 data = R8( op & 7 );
831 goto sub_comm;
832
833 case 0xD6: // SUB IMM
834 pc++;
835 sub_comm:
836 op = rg.a;
837 data = op - data;
838 rg.a = data;
839 goto sub_set_flags;
840
841 case 0x9E: // SBC (HL)
842 data = READ( rp.hl );
843 goto sbc_comm;
844
845 case 0x98: // SBC B
846 case 0x99: // SBC C
847 case 0x9A: // SBC D
848 case 0x9B: // SBC E
849 case 0x9C: // SBC H
850 case 0x9D: // SBC L
851 case 0x9F: // SBC A
852 data = R8( op & 7 );
853 goto sbc_comm;
854
855 case 0xDE: // SBC IMM
856 pc++;
857 sbc_comm:
858 data += (flags >> 4) & 1;
859 data &= 0xff; // to do: does carry get set when sum + carry = 0x100?
860 goto sub_comm;
861
862 // Logical
863
864 case 0xA0: // AND B
865 case 0xA1: // AND C
866 case 0xA2: // AND D
867 case 0xA3: // AND E
868 case 0xA4: // AND H
869 case 0xA5: // AND L
870 data = R8( op & 7 );
871 goto and_comm;
872
873 case 0xA6: // AND (HL)
874 data = READ( rp.hl );
875 pc--;
876 case 0xE6: // AND IMM
877 pc++;
878 and_comm:
879 rg.a &= data;
880 case 0xA7: // AND A
881 flags = h_flag | (((rg.a - 1) >> 1) & z_flag);
882 goto loop;
883
884 case 0xB0: // OR B
885 case 0xB1: // OR C
886 case 0xB2: // OR D
887 case 0xB3: // OR E
888 case 0xB4: // OR H
889 case 0xB5: // OR L
890 data = R8( op & 7 );
891 goto or_comm;
892
893 case 0xB6: // OR (HL)
894 data = READ( rp.hl );
895 pc--;
896 case 0xF6: // OR IMM
897 pc++;
898 or_comm:
899 rg.a |= data;
900 case 0xB7: // OR A
901 flags = ((rg.a - 1) >> 1) & z_flag;
902 goto loop;
903
904 case 0xA8: // XOR B
905 case 0xA9: // XOR C
906 case 0xAA: // XOR D
907 case 0xAB: // XOR E
908 case 0xAC: // XOR H
909 case 0xAD: // XOR L
910 data = R8( op & 7 );
911 goto xor_comm;
912
913 case 0xAE: // XOR (HL)
914 data = READ( rp.hl );
915 pc--;
916 case 0xEE: // XOR IMM
917 pc++;
918 xor_comm:
919 data ^= rg.a;
920 rg.a = data;
921 data--;
922 flags = (data >> 1) & z_flag;
923 goto loop;
924
925 case 0xAF: // XOR A
926 rg.a = 0;
927 flags = z_flag;
928 goto loop;
929
930 // Stack
931
932 case 0xC1: // POP BC
933 case 0xD1: // POP DE
934 case 0xE1:{// POP HL (common)
935 int temp = READ( sp );
936 r16 [(op >> 4) & 3] = temp + 0x100 * READ( (sp + 1) & 0xFFFF );
937 sp = (sp + 2) & 0xFFFF;
938 goto loop;
939 }
940
941 case 0xF1: // POP FA
942 rg.a = READ( sp );
943 flags = READ( (sp + 1) & 0xFFFF ) & 0xf0;
944 sp = (sp + 2) & 0xFFFF;
945 goto loop;
946
947 case 0xC5: // PUSH BC
948 data = rp.bc;
949 goto push;
950
951 case 0xD5: // PUSH DE
952 data = rp.de;
953 goto push;
954
955 case 0xE5: // PUSH HL
956 data = rp.hl;
957 goto push;
958
959 case 0xF5: // PUSH FA
960 data = (flags << 8) | rg.a;
961 goto push;
962
963 // Flow control
964
965 case 0xC7: case 0xCF: case 0xD7: case 0xDF: // RST
966 case 0xE7: case 0xEF: case 0xF7: case 0xFF:
967 data = pc;
968 pc = (op & 0x38) + rst_base;
969 goto push;
970
971 case 0xCC: // CZ
972 pc += 2;
973 if ( flags & z_flag )
974 goto call;
975 goto loop;
976
977 case 0xD4: // CNC
978 pc += 2;
979 if ( !(flags & c_flag) )
980 goto call;
981 goto loop;
982
983 case 0xDC: // CC
984 pc += 2;
985 if ( flags & c_flag )
986 goto call;
987 goto loop;
988
989 case 0xD9: // RETI
990 Gb_Cpu::interrupts_enabled = 1;
991 goto ret;
992
993 case 0xC0: // RZ
994 if ( !(flags & z_flag) )
995 goto ret;
996 goto loop;
997
998 case 0xD0: // RNC
999 if ( !(flags & c_flag) )
1000 goto ret;
1001 goto loop;
1002
1003 case 0xD8: // RC
1004 if ( flags & c_flag )
1005 goto ret;
1006 goto loop;
1007
1008 case 0x18: // JR
1009 BRANCH( true )
1010
1011 case 0x30: // JR NC
1012 BRANCH( !(flags & c_flag) )
1013
1014 case 0x38: // JR C
1015 BRANCH( flags & c_flag )
1016
1017 case 0xE9: // JP_HL
1018 pc = rp.hl;
1019 goto loop;
1020
1021 case 0xC3: // JP (next-most-common)
1022 pc = READ_PROG16( pc );
1023 goto loop;
1024
1025 case 0xC2: // JP NZ
1026 pc += 2;
1027 if ( !(flags & z_flag) )
1028 goto jp_taken;
1029 goto loop;
1030
1031 case 0xCA: // JP Z (most common)
1032 pc += 2;
1033 if ( !(flags & z_flag) )
1034 goto loop;
1035 jp_taken:
1036 pc -= 2;
1037 pc = READ_PROG16( pc );
1038 goto loop;
1039
1040 case 0xD2: // JP NC
1041 pc += 2;
1042 if ( !(flags & c_flag) )
1043 goto jp_taken;
1044 goto loop;
1045
1046 case 0xDA: // JP C
1047 pc += 2;
1048 if ( flags & c_flag )
1049 goto jp_taken;
1050 goto loop;
1051
1052 // Flags
1053
1054 case 0x2F: // CPL
1055 rg.a = ~rg.a;
1056 flags |= n_flag | h_flag;
1057 goto loop;
1058
1059 case 0x3F: // CCF
1060 flags = (flags ^ c_flag) & ~(n_flag | h_flag);
1061 goto loop;
1062
1063 case 0x37: // SCF
1064 flags = (flags | c_flag) & ~(n_flag | h_flag);
1065 goto loop;
1066
1067 case 0xF3: // DI
1068 interrupts_enabled = 0;
1069 goto loop;
1070
1071 case 0xFB: // EI
1072 interrupts_enabled = 1;
1073 goto loop;
1074
1075 // Special
1076
1077 case 0xDD: case 0xD3: case 0xDB: case 0xE3: case 0xE4: // ?
1078 case 0xEB: case 0xEC: case 0xF4: case 0xFD: case 0xFC:
1079 case 0x10: // STOP
1080 case 0x27: // DAA (I'll have to implement this eventually...)
1081 case 0xBF:
1082 case 0xED: // Z80 prefix
1083 result = Gb_Cpu::result_badop;
1084 goto stop;
1085
1086 case 0x76: // HALT
1087 result = Gb_Cpu::result_halt;
1088 goto stop;
1089 }
1090
1091 // If this fails then the case above is missing an opcode
1092 assert( false );
1093
1094 stop:
1095 pc--;
1096
1097 // copy state back
1098 r.pc = pc;
1099 r.sp = sp;
1100 r.flags = flags;
1101 r.a = rg.a;
1102 r.b = rg.b;
1103 r.c = rg.c;
1104 r.d = rg.d;
1105 r.e = rg.e;
1106 r.h = rg.h;
1107 r.l = rg.l;
1108
1109 return result;
1110 }
1111
1112 #endif
1113