Coverage Report

Created: 2026-07-12 08:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/contrib/contrib-build/game-music-emu/gme/Gb_Cpu.cpp
Line
Count
Source
1
// Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/
2
3
#include "Gb_Cpu.h"
4
5
#include <string.h>
6
7
//#include "gb_cpu_log.h"
8
9
/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
10
can redistribute it and/or modify it under the terms of the GNU Lesser
11
General Public License as published by the Free Software Foundation; either
12
version 2.1 of the License, or (at your option) any later version. This
13
module is distributed in the hope that it will be useful, but WITHOUT ANY
14
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
16
details. You should have received a copy of the GNU Lesser General Public
17
License along with this module; if not, write to the Free Software Foundation,
18
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
19
20
#include "gb_cpu_io.h"
21
22
#include "blargg_source.h"
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
20.6G
  #define PAGE_OFFSET( addr ) ((addr) & (page_size - 1))
48
#endif
49
50
inline void Gb_Cpu::set_code_page( int i, uint8_t* p )
51
20.0M
{
52
20.0M
  state->code_map [i] = p - PAGE_OFFSET( i * (blargg_long) page_size );
53
20.0M
}
54
55
void Gb_Cpu::reset( void* unmapped )
56
1.46k
{
57
1.46k
  check( state == &state_ );
58
1.46k
  state = &state_;
59
60
1.46k
  state_.remain = 0;
61
62
14.6k
  for ( int i = 0; i < page_count + 1; i++ )
63
13.1k
    set_code_page( i, (uint8_t*) unmapped );
64
65
1.46k
  memset( &r, 0, sizeof r );
66
  //interrupts_enabled = false;
67
68
1.46k
  blargg_verify_byte_order();
69
1.46k
}
70
71
void Gb_Cpu::map_code( gb_addr_t start, unsigned size, void* data )
72
10.0M
{
73
  // address range must begin and end on page boundaries
74
10.0M
  require( start % page_size == 0 );
75
10.0M
  require( size % page_size == 0 );
76
77
10.0M
  unsigned first_page = start / page_size;
78
30.0M
  for ( unsigned i = size / page_size; i--; )
79
20.0M
    set_code_page( first_page + i, (uint8_t*) data + i * page_size );
80
10.0M
}
81
82
27.5M
#define READ( addr )            CPU_READ( this, (addr), s.remain )
83
821M
#define WRITE( addr, data )     {CPU_WRITE( this, (addr), (data), s.remain );}
84
45.7M
#define READ_FAST( addr, out )  CPU_READ_FAST( this, (addr), s.remain, out )
85
45.7M
#define READ_PROG( addr )       (s.code_map [(addr) >> page_shift] [PAGE_OFFSET( addr )])
86
87
88
static unsigned const z_flag = 0x80;
89
static unsigned const n_flag = 0x40;
90
static unsigned const h_flag = 0x20;
91
static unsigned const c_flag = 0x10;
92
93
bool Gb_Cpu::run( blargg_long cycle_count )
94
47.0M
{
95
47.0M
  state_.remain = blargg_ulong (cycle_count + clocks_per_instr) / clocks_per_instr;
96
47.0M
  state_t s;
97
47.0M
  this->state = &s;
98
47.0M
  memcpy( &s, &this->state_, sizeof s );
99
100
#if BLARGG_BIG_ENDIAN
101
  #define R8( n ) (r8_ [n])
102
#elif BLARGG_LITTLE_ENDIAN
103
2.73G
  #define R8( n ) (r8_ [(n) ^ 1])
104
#else
105
  #error "Byte order of CPU must be known"
106
#endif
107
108
47.0M
  union {
109
47.0M
    core_regs_t rg; // individual registers
110
111
47.0M
    struct {
112
47.0M
      uint16_t bc, de, hl, unused; // pairs
113
47.0M
    } rp;
114
115
47.0M
    uint8_t r8_ [8]; // indexed registers (use R8 macro due to endian dependence)
116
47.0M
    uint16_t r16 [4]; // indexed pairs
117
47.0M
  };
118
47.0M
  static_assert( sizeof rg == 8 && sizeof rp == 8, "Unhandled word size" );
119
120
47.0M
  rg = r;
121
47.0M
  unsigned pc = r.pc;
122
47.0M
  unsigned sp = r.sp;
123
47.0M
  unsigned flags = r.flags;
124
125
20.6G
loop:
126
127
20.6G
  check( (unsigned long) pc < 0x10000 );
128
20.6G
  check( (unsigned long) sp < 0x10000 );
129
20.6G
  check( (flags & ~0xF0) == 0 );
130
131
20.6G
  uint8_t const* instr = s.code_map [pc >> page_shift];
132
20.6G
  unsigned op;
133
134
  // TODO: eliminate this special case
135
  #if BLARGG_NONPORTABLE
136
    op = instr [pc];
137
    pc++;
138
    instr += pc;
139
  #else
140
20.6G
    instr += PAGE_OFFSET( pc );
141
20.6G
    op = *instr++;
142
20.6G
    pc++;
143
20.6G
  #endif
144
145
20.6G
#define GET_ADDR()  GET_LE16( instr )
146
147
20.6G
  if ( !--s.remain )
148
392k
    goto stop;
149
150
20.6G
  unsigned data;
151
20.6G
  data = *instr;
152
153
  #ifdef GB_CPU_LOG_H
154
    gb_cpu_log( "new", pc - 1, op, data, instr [1] );
155
  #endif
156
157
20.6G
  switch ( op )
158
20.6G
  {
159
160
// TODO: more efficient way to handle negative branch that wraps PC around
161
30.6M
#define BRANCH( cond )\
162
30.6M
{\
163
30.6M
  pc++;\
164
30.6M
  int offset = (int8_t) data;\
165
41.8M
  if ( !(cond) ) goto loop;\
166
30.6M
  pc = uint16_t (pc + offset);\
167
30.6M
  goto loop;\
168
30.6M
}
169
170
// Most Common
171
172
12.7M
  case 0x20: // JR NZ
173
12.7M
    BRANCH( !(flags & z_flag) )
174
175
529k
  case 0x21: // LD HL,IMM (common)
176
529k
    rp.hl = GET_ADDR();
177
529k
    pc += 2;
178
529k
    goto loop;
179
180
310k
  case 0x28: // JR Z
181
310k
    BRANCH( flags & z_flag )
182
183
0
  {
184
0
    unsigned temp;
185
666k
  case 0xF0: // LD A,(0xFF00+imm)
186
666k
    temp = data | 0xFF00;
187
666k
    pc++;
188
666k
    goto ld_a_ind_comm;
189
190
93.6k
  case 0xF2: // LD A,(0xFF00+C)
191
93.6k
    temp = rg.c | 0xFF00;
192
93.6k
    goto ld_a_ind_comm;
193
194
730k
  case 0x0A: // LD A,(BC)
195
730k
    temp = rp.bc;
196
730k
    goto ld_a_ind_comm;
197
198
6.30M
  case 0x3A: // LD A,(HL-)
199
6.30M
    temp = rp.hl;
200
6.30M
    rp.hl = temp - 1;
201
6.30M
    goto ld_a_ind_comm;
202
203
13.1M
  case 0x1A: // LD A,(DE)
204
13.1M
    temp = rp.de;
205
13.1M
    goto ld_a_ind_comm;
206
207
101k
  case 0x2A: // LD A,(HL+) (common)
208
101k
    temp = rp.hl;
209
101k
    rp.hl = temp + 1;
210
101k
    goto ld_a_ind_comm;
211
212
1.71M
  case 0xFA: // LD A,IND16 (common)
213
1.71M
    temp = GET_ADDR();
214
1.71M
    pc += 2;
215
22.7M
  ld_a_ind_comm:
216
22.7M
    READ_FAST( temp, rg.a );
217
22.7M
    goto loop;
218
1.71M
  }
219
220
61.2k
  case 0xBE: // CMP (HL)
221
61.2k
    data = READ( rp.hl );
222
61.2k
    goto cmp_comm;
223
224
733k
  case 0xB8: // CMP B
225
752k
  case 0xB9: // CMP C
226
4.30M
  case 0xBA: // CMP D
227
5.43M
  case 0xBB: // CMP E
228
5.45M
  case 0xBC: // CMP H
229
17.8M
  case 0xBD: // CMP L
230
17.8M
    data = R8( op & 7 );
231
17.8M
    goto cmp_comm;
232
233
16.8M
  case 0xFE: // CMP IMM
234
16.8M
    pc++;
235
34.7M
  cmp_comm:
236
34.7M
    op = rg.a;
237
34.7M
    data = op - data;
238
110M
  sub_set_flags:
239
110M
    flags = ((op & 15) - (data & 15)) & h_flag;
240
110M
    flags |= (data >> 4) & c_flag;
241
110M
    flags |= n_flag;
242
110M
    if ( data & 0xFF )
243
67.9M
      goto loop;
244
42.9M
    flags |= z_flag;
245
42.9M
    goto loop;
246
247
2.77M
  case 0x46: // LD B,(HL)
248
10.7M
  case 0x4E: // LD C,(HL)
249
16.0M
  case 0x56: // LD D,(HL)
250
16.0M
  case 0x5E: // LD E,(HL)
251
19.4M
  case 0x66: // LD H,(HL)
252
21.7M
  case 0x6E: // LD L,(HL)
253
22.9M
  case 0x7E:{// LD A,(HL)
254
22.9M
    unsigned addr = rp.hl;
255
22.9M
    READ_FAST( addr, R8( (op >> 3) & 7 ) );
256
22.9M
    goto loop;
257
21.7M
  }
258
259
213k
  case 0xC4: // CNZ (next-most-common)
260
213k
    pc += 2;
261
213k
    if ( flags & z_flag )
262
188k
      goto loop;
263
803k
  call:
264
803k
    pc -= 2; // FALLTHRU
265
901k
  case 0xCD: // CALL (most-common)
266
901k
    data = pc + 2;
267
901k
    pc = GET_ADDR();
268
396M
  push:
269
396M
    sp = (sp - 1) & 0xFFFF;
270
396M
    WRITE( sp, data >> 8 );
271
396M
    sp = (sp - 1) & 0xFFFF;
272
396M
    WRITE( sp, data & 0xFF );
273
396M
    goto loop;
274
275
128k
  case 0xC8: // RNZ (next-most-common)
276
128k
    if ( !(flags & z_flag) )
277
123k
      goto loop;
278
    // FALLTHRU
279
43.8k
  case 0xC9: // RET (most common)
280
2.25M
  ret:
281
2.25M
    pc = READ( sp );
282
2.25M
    pc += 0x100 * READ( sp + 1 );
283
2.25M
    sp = (sp + 2) & 0xFFFF;
284
2.25M
    goto loop;
285
286
17.8G
  case 0x00: // NOP
287
17.8G
  case 0x40: // LD B,B
288
17.8G
  case 0x49: // LD C,C
289
17.8G
  case 0x52: // LD D,D
290
17.8G
  case 0x5B: // LD E,E
291
17.8G
  case 0x64: // LD H,H
292
17.8G
  case 0x6D: // LD L,L
293
17.8G
  case 0x7F: // LD A,A
294
17.8G
    goto loop;
295
296
// CB Instructions
297
298
466k
  case 0xCB:
299
466k
    pc++;
300
    // now data is the opcode
301
466k
    switch ( data ) {
302
303
0
    {
304
0
      int temp;
305
0
    case 0x46: // BIT b,(HL)
306
0
    case 0x4E:
307
0
    case 0x56:
308
0
    case 0x5E:
309
0
    case 0x66:
310
0
    case 0x6E:
311
0
    case 0x76:
312
0
    case 0x7E:
313
0
      {
314
0
        unsigned addr = rp.hl;
315
0
        READ_FAST( addr, temp );
316
0
        goto bit_comm;
317
0
      }
318
319
0
    case 0x40: case 0x41: case 0x42: case 0x43: // BIT b,r
320
0
    case 0x44: case 0x45: case 0x47: case 0x48:
321
0
    case 0x49: case 0x4A: case 0x4B: case 0x4C:
322
0
    case 0x4D: case 0x4F: case 0x50: case 0x51:
323
0
    case 0x52: case 0x53: case 0x54: case 0x55:
324
0
    case 0x57: case 0x58: case 0x59: case 0x5A:
325
0
    case 0x5B: case 0x5C: case 0x5D: case 0x5F:
326
7.33k
    case 0x60: case 0x61: case 0x62: case 0x63:
327
7.33k
    case 0x64: case 0x65: case 0x67: case 0x68:
328
7.33k
    case 0x69: case 0x6A: case 0x6B: case 0x6C:
329
7.33k
    case 0x6D: case 0x6F: case 0x70: case 0x71:
330
7.33k
    case 0x72: case 0x73: case 0x74: case 0x75:
331
7.33k
    case 0x77: case 0x78: case 0x79: case 0x7A:
332
7.33k
    case 0x7B: case 0x7C: case 0x7D: case 0x7F:
333
7.33k
      temp = R8( data & 7 );
334
7.33k
    bit_comm:
335
7.33k
      int bit = (~data >> 3) & 7;
336
7.33k
      flags &= ~n_flag;
337
7.33k
      flags |= h_flag | z_flag;
338
7.33k
      flags ^= (temp << bit) & z_flag;
339
7.33k
      goto loop;
340
7.33k
    }
341
342
0
    case 0x86: // RES b,(HL)
343
0
    case 0x8E:
344
0
    case 0x96:
345
0
    case 0x9E:
346
0
    case 0xA6:
347
0
    case 0xAE:
348
0
    case 0xB6:
349
0
    case 0xBE:
350
0
    case 0xC6: // SET b,(HL)
351
0
    case 0xCE:
352
0
    case 0xD6:
353
0
    case 0xDE:
354
0
    case 0xE6:
355
0
    case 0xEE:
356
0
    case 0xF6:
357
0
    case 0xFE: {
358
0
      int temp = READ( rp.hl );
359
0
      int bit = 1 << ((data >> 3) & 7);
360
0
      temp &= ~bit;
361
0
      if ( !(data & 0x40) )
362
0
        bit = 0;
363
0
      WRITE( rp.hl, temp | bit );
364
0
      goto loop;
365
0
    }
366
367
0
    case 0xC0: case 0xC1: case 0xC2: case 0xC3: // SET b,r
368
0
    case 0xC4: case 0xC5: case 0xC7: case 0xC8:
369
12.1k
    case 0xC9: case 0xCA: case 0xCB: case 0xCC:
370
12.1k
    case 0xCD: case 0xCF: case 0xD0: case 0xD1:
371
12.1k
    case 0xD2: case 0xD3: case 0xD4: case 0xD5:
372
12.1k
    case 0xD7: case 0xD8: case 0xD9: case 0xDA:
373
12.1k
    case 0xDB: case 0xDC: case 0xDD: case 0xDF:
374
12.1k
    case 0xE0: case 0xE1: case 0xE2: case 0xE3:
375
12.1k
    case 0xE4: case 0xE5: case 0xE7: case 0xE8:
376
12.1k
    case 0xE9: case 0xEA: case 0xEB: case 0xEC:
377
12.1k
    case 0xED: case 0xEF: case 0xF0: case 0xF1:
378
12.1k
    case 0xF2: case 0xF3: case 0xF4: case 0xF5:
379
12.6k
    case 0xF7: case 0xF8: case 0xF9: case 0xFA:
380
58.3k
    case 0xFB: case 0xFC: case 0xFD: case 0xFF:
381
58.3k
      R8( data & 7 ) |= 1 << ((data >> 3) & 7);
382
58.3k
      goto loop;
383
384
0
    case 0x80: case 0x81: case 0x82: case 0x83: // RES b,r
385
0
    case 0x84: case 0x85: case 0x87: case 0x88:
386
0
    case 0x89: case 0x8A: case 0x8B: case 0x8C:
387
262k
    case 0x8D: case 0x8F: case 0x90: case 0x91:
388
262k
    case 0x92: case 0x93: case 0x94: case 0x95:
389
262k
    case 0x97: case 0x98: case 0x99: case 0x9A:
390
262k
    case 0x9B: case 0x9C: case 0x9D: case 0x9F:
391
293k
    case 0xA0: case 0xA1: case 0xA2: case 0xA3:
392
293k
    case 0xA4: case 0xA5: case 0xA7: case 0xA8:
393
293k
    case 0xA9: case 0xAA: case 0xAB: case 0xAC:
394
293k
    case 0xAD: case 0xAF: case 0xB0: case 0xB1:
395
293k
    case 0xB2: case 0xB3: case 0xB4: case 0xB5:
396
293k
    case 0xB7: case 0xB8: case 0xB9: case 0xBA:
397
293k
    case 0xBB: case 0xBC: case 0xBD: case 0xBF:
398
293k
      R8( data & 7 ) &= ~(1 << ((data >> 3) & 7));
399
293k
      goto loop;
400
401
0
    {
402
0
      int temp;
403
0
    case 0x36: // SWAP (HL)
404
0
      temp = READ( rp.hl );
405
0
      goto swap_comm;
406
407
0
    case 0x30: // SWAP B
408
0
    case 0x31: // SWAP C
409
0
    case 0x32: // SWAP D
410
0
    case 0x33: // SWAP E
411
0
    case 0x34: // SWAP H
412
0
    case 0x35: // SWAP L
413
0
    case 0x37: // SWAP A
414
0
      temp = R8( data & 7 );
415
0
    swap_comm:
416
0
      op = (temp >> 4) | (temp << 4);
417
0
      flags = 0;
418
0
      goto shift_comm;
419
0
    }
420
421
// Shift/Rotate
422
423
0
    case 0x06: // RLC (HL)
424
0
    case 0x16: // RL (HL)
425
0
    case 0x26: // SLA (HL)
426
0
      op = READ( rp.hl );
427
0
      goto rl_comm;
428
429
0
    case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x27: // SLA A
430
107k
    case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x07: // RLC A
431
107k
    case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x17: // RL A
432
107k
      op = R8( data & 7 );
433
107k
      goto rl_comm;
434
435
0
    case 0x3E: // SRL (HL)
436
0
      data += 0x10; /* fallthrough */ // bump up to 0x4n to avoid preserving sign bit
437
0
    case 0x1E: // RR (HL)
438
0
    case 0x0E: // RRC (HL)
439
0
    case 0x2E: // SRA (HL)
440
0
      op = READ( rp.hl );
441
0
      goto rr_comm;
442
443
0
    case 0x38: case 0x39: case 0x3A: case 0x3B: case 0x3C: case 0x3D: case 0x3F: // SRL A
444
0
      data += 0x10; /* fallthrough */ // bump up to 0x4n
445
0
    case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1F: // RR A
446
0
    case 0x08: case 0x09: case 0x0A: case 0x0B: case 0x0C: case 0x0D: case 0x0F: // RRC A
447
227
    case 0x28: case 0x29: case 0x2A: case 0x2B: case 0x2C: case 0x2D: case 0x2F: // SRA A
448
227
      op = R8( data & 7 );
449
227
      goto rr_comm;
450
451
466k
  } // CB op
452
466k
  assert( false ); // unhandled CB op
453
  // fallthrough
454
455
3.32M
  case 0x07: // RLCA
456
5.02M
  case 0x17: // RLA
457
5.02M
    data = op;
458
5.02M
    op = rg.a;
459
5.12M
  rl_comm:
460
5.12M
    op <<= 1;
461
5.12M
    op |= ((data & flags) >> 4) & 1; // RL and carry is set
462
5.12M
    flags = (op >> 4) & c_flag; // C = bit shifted out
463
5.12M
    if ( data < 0x10 ) // RLC
464
3.43M
      op |= op >> 8;
465
    // SLA doesn't fill lower bit
466
5.12M
    goto shift_comm;
467
468
679k
  case 0x0F: // RRCA
469
867k
  case 0x1F: // RRA
470
867k
    data = op;
471
867k
    op = rg.a;
472
868k
  rr_comm:
473
868k
    op |= (data & flags) << 4; // RR and carry is set
474
868k
    flags = (op << 4) & c_flag; // C = bit shifted out
475
868k
    if ( data < 0x10 ) // RRC
476
679k
      op |= op << 8;
477
868k
    op >>= 1;
478
868k
    if ( data & 0x20 ) // SRA propagates sign bit
479
227
      op |= (op << 1) & 0x80;
480
5.99M
  shift_comm:
481
5.99M
    data &= 7;
482
5.99M
    if ( !(op & 0xFF) )
483
4.42M
      flags |= z_flag;
484
5.99M
    if ( data == 6 )
485
0
      goto write_hl_op_ff;
486
5.99M
    R8( data ) = op;
487
5.99M
    goto loop;
488
489
// Load
490
491
1.23M
  case 0x70: // LD (HL),B
492
1.26M
  case 0x71: // LD (HL),C
493
1.79M
  case 0x72: // LD (HL),D
494
3.81M
  case 0x73: // LD (HL),E
495
4.41M
  case 0x74: // LD (HL),H
496
4.65M
  case 0x75: // LD (HL),L
497
4.88M
  case 0x77: // LD (HL),A
498
4.88M
    op = R8( op & 7 );
499
4.88M
  write_hl_op_ff:
500
4.88M
    WRITE( rp.hl, op & 0xFF );
501
4.88M
    goto loop;
502
503
56.5M
  case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x47: // LD r,r
504
76.3M
  case 0x48: case 0x4A: case 0x4B: case 0x4C: case 0x4D: case 0x4F:
505
120M
  case 0x50: case 0x51: case 0x53: case 0x54: case 0x55: case 0x57:
506
133M
  case 0x58: case 0x59: case 0x5A: case 0x5C: case 0x5D: case 0x5F:
507
1.03G
  case 0x60: case 0x61: case 0x62: case 0x63: case 0x65: case 0x67:
508
1.04G
  case 0x68: case 0x69: case 0x6A: case 0x6B: case 0x6C: case 0x6F:
509
1.04G
  case 0x78: case 0x79: case 0x7A: case 0x7B: case 0x7C: case 0x7D:
510
1.04G
    R8( (op >> 3) & 7 ) = R8( op & 7 );
511
1.04G
    goto loop;
512
513
6.56M
  case 0x08: // LD IND16,SP
514
6.56M
    data = GET_ADDR();
515
6.56M
    pc += 2;
516
6.56M
    WRITE( data, sp&0xFF );
517
6.56M
    data++;
518
6.56M
    WRITE( data, sp >> 8 );
519
6.56M
    goto loop;
520
521
10.2M
  case 0xF9: // LD SP,HL
522
10.2M
    sp = rp.hl;
523
10.2M
    goto loop;
524
525
3.65M
  case 0x31: // LD SP,IMM
526
3.65M
    sp = GET_ADDR();
527
3.65M
    pc += 2;
528
3.65M
    goto loop;
529
530
29.2M
  case 0x01: // LD BC,IMM
531
29.5M
  case 0x11: // LD DE,IMM
532
29.5M
    r16 [op >> 4] = GET_ADDR();
533
29.5M
    pc += 2;
534
29.5M
    goto loop;
535
536
0
  {
537
0
    unsigned temp;
538
590k
  case 0xE0: // LD (0xFF00+imm),A
539
590k
    temp = data | 0xFF00;
540
590k
    pc++;
541
590k
    goto write_data_rg_a;
542
543
898k
  case 0xE2: // LD (0xFF00+C),A
544
898k
    temp = rg.c | 0xFF00;
545
898k
    goto write_data_rg_a;
546
547
732k
  case 0x32: // LD (HL-),A
548
732k
    temp = rp.hl;
549
732k
    rp.hl = temp - 1;
550
732k
    goto write_data_rg_a;
551
552
4.17M
  case 0x02: // LD (BC),A
553
4.17M
    temp = rp.bc;
554
4.17M
    goto write_data_rg_a;
555
556
170k
  case 0x12: // LD (DE),A
557
170k
    temp = rp.de;
558
170k
    goto write_data_rg_a;
559
560
391k
  case 0x22: // LD (HL+),A
561
391k
    temp = rp.hl;
562
391k
    rp.hl = temp + 1;
563
391k
    goto write_data_rg_a;
564
565
210k
  case 0xEA: // LD IND16,A (common)
566
210k
    temp = GET_ADDR();
567
210k
    pc += 2;
568
7.16M
  write_data_rg_a:
569
7.16M
    WRITE( temp, rg.a );
570
7.16M
    goto loop;
571
210k
  }
572
573
7.34M
  case 0x06: // LD B,IMM
574
7.34M
    rg.b = data;
575
7.34M
    pc++;
576
7.34M
    goto loop;
577
578
126k
  case 0x0E: // LD C,IMM
579
126k
    rg.c = data;
580
126k
    pc++;
581
126k
    goto loop;
582
583
8.10k
  case 0x16: // LD D,IMM
584
8.10k
    rg.d = data;
585
8.10k
    pc++;
586
8.10k
    goto loop;
587
588
170k
  case 0x1E: // LD E,IMM
589
170k
    rg.e = data;
590
170k
    pc++;
591
170k
    goto loop;
592
593
482k
  case 0x26: // LD H,IMM
594
482k
    rg.h = data;
595
482k
    pc++;
596
482k
    goto loop;
597
598
1.02M
  case 0x2E: // LD L,IMM
599
1.02M
    rg.l = data;
600
1.02M
    pc++;
601
1.02M
    goto loop;
602
603
469k
  case 0x36: // LD (HL),IMM
604
469k
    WRITE( rp.hl, data );
605
469k
    pc++;
606
469k
    goto loop;
607
608
517k
  case 0x3E: // LD A,IMM
609
517k
    rg.a = data;
610
517k
    pc++;
611
517k
    goto loop;
612
613
// Increment/Decrement
614
615
2.11M
  case 0x03: // INC BC
616
2.20M
  case 0x13: // INC DE
617
2.67M
  case 0x23: // INC HL
618
2.67M
    r16 [op >> 4]++;
619
2.67M
    goto loop;
620
621
982k
  case 0x33: // INC SP
622
982k
    sp = (sp + 1) & 0xFFFF;
623
982k
    goto loop;
624
625
4.73k
  case 0x0B: // DEC BC
626
1.85M
  case 0x1B: // DEC DE
627
3.41M
  case 0x2B: // DEC HL
628
3.41M
    r16 [op >> 4]--;
629
3.41M
    goto loop;
630
631
1.20M
  case 0x3B: // DEC SP
632
1.20M
    sp = (sp - 1) & 0xFFFF;
633
1.20M
    goto loop;
634
635
541k
  case 0x34: // INC (HL)
636
541k
    op = rp.hl;
637
541k
    data = READ( op );
638
541k
    data++;
639
541k
    WRITE( op, data & 0xFF );
640
541k
    goto inc_comm;
641
642
49.6M
  case 0x04: // INC B
643
53.3M
  case 0x0C: // INC C (common)
644
56.8M
  case 0x14: // INC D
645
75.2M
  case 0x1C: // INC E
646
75.3M
  case 0x24: // INC H
647
92.0M
  case 0x2C: // INC L
648
92.7M
  case 0x3C: // INC A
649
92.7M
    op = (op >> 3) & 7;
650
92.7M
    R8( op ) = data = R8( op ) + 1;
651
93.2M
  inc_comm:
652
93.2M
    flags = (flags & c_flag) | (((data & 15) - 1) & h_flag) | ((data >> 1) & z_flag);
653
93.2M
    goto loop;
654
655
1.57M
  case 0x35: // DEC (HL)
656
1.57M
    op = rp.hl;
657
1.57M
    data = READ( op );
658
1.57M
    data--;
659
1.57M
    WRITE( op, data & 0xFF );
660
1.57M
    goto dec_comm;
661
662
79.7M
  case 0x05: // DEC B
663
81.6M
  case 0x0D: // DEC C
664
81.7M
  case 0x15: // DEC D
665
83.1M
  case 0x1D: // DEC E
666
83.6M
  case 0x25: // DEC H
667
88.6M
  case 0x2D: // DEC L
668
89.4M
  case 0x3D: // DEC A
669
89.4M
    op = (op >> 3) & 7;
670
89.4M
    data = R8( op ) - 1;
671
89.4M
    R8( op ) = data;
672
91.0M
  dec_comm:
673
91.0M
    flags = (flags & c_flag) | n_flag | (((data & 15) + 0x31) & h_flag);
674
91.0M
    if ( data & 0xFF )
675
90.5M
      goto loop;
676
464k
    flags |= z_flag;
677
464k
    goto loop;
678
679
// Add 16-bit
680
681
0
  {
682
0
    blargg_ulong temp; // need more than 16 bits for carry
683
0
    unsigned prev;
684
685
522M
  case 0xF8: // LD HL,SP+imm
686
522M
    temp = int8_t (data); // sign-extend to 16 bits
687
522M
    pc++;
688
522M
    flags = 0;
689
522M
    temp += sp;
690
522M
    prev = sp;
691
522M
    goto add_16_hl;
692
693
764k
  case 0xE8: // ADD SP,IMM
694
764k
    temp = int8_t (data); // sign-extend to 16 bits
695
764k
    pc++;
696
764k
    flags = 0;
697
764k
    temp += sp;
698
764k
    prev = sp;
699
764k
    sp = temp & 0xFFFF;
700
764k
    goto add_16_comm;
701
702
827k
  case 0x39: // ADD HL,SP
703
827k
    temp = sp;
704
827k
    goto add_hl_comm;
705
706
210k
  case 0x09: // ADD HL,BC
707
260k
  case 0x19: // ADD HL,DE
708
2.53M
  case 0x29: // ADD HL,HL
709
2.53M
    temp = r16 [op >> 4];
710
3.36M
  add_hl_comm:
711
3.36M
    prev = rp.hl;
712
3.36M
    temp += prev;
713
3.36M
    flags &= z_flag;
714
526M
  add_16_hl:
715
526M
    rp.hl = temp;
716
527M
  add_16_comm:
717
527M
    flags |= (temp >> 12) & c_flag;
718
527M
    flags |= (((temp & 0x0FFF) - (prev & 0x0FFF)) >> 7) & h_flag;
719
527M
    goto loop;
720
526M
  }
721
722
260k
  case 0x86: // ADD (HL)
723
260k
    data = READ( rp.hl );
724
260k
    goto add_comm;
725
726
6.11M
  case 0x80: // ADD B
727
25.0M
  case 0x81: // ADD C
728
25.0M
  case 0x82: // ADD D
729
25.3M
  case 0x83: // ADD E
730
25.5M
  case 0x84: // ADD H
731
26.2M
  case 0x85: // ADD L
732
26.2M
  case 0x87: // ADD A
733
26.2M
    data = R8( op & 7 );
734
26.2M
    goto add_comm;
735
736
6.37k
  case 0xC6: // ADD IMM
737
6.37k
    pc++;
738
126M
  add_comm:
739
126M
    flags = rg.a;
740
126M
    data += flags;
741
126M
    flags = ((data & 15) - (flags & 15)) & h_flag;
742
126M
    flags |= (data >> 4) & c_flag;
743
126M
    rg.a = data;
744
126M
    if ( data & 0xFF )
745
91.7M
      goto loop;
746
34.3M
    flags |= z_flag;
747
34.3M
    goto loop;
748
749
// Add/Subtract
750
751
44.1k
  case 0x8E: // ADC (HL)
752
44.1k
    data = READ( rp.hl );
753
44.1k
    goto adc_comm;
754
755
1.13M
  case 0x88: // ADC B
756
1.23M
  case 0x89: // ADC C
757
1.37M
  case 0x8A: // ADC D
758
2.20M
  case 0x8B: // ADC E
759
8.04M
  case 0x8C: // ADC H
760
98.4M
  case 0x8D: // ADC L
761
99.3M
  case 0x8F: // ADC A
762
99.3M
    data = R8( op & 7 );
763
99.3M
    goto adc_comm;
764
765
171k
  case 0xCE: // ADC IMM
766
171k
    pc++;
767
99.6M
  adc_comm:
768
99.6M
    data += (flags >> 4) & 1;
769
99.6M
    data &= 0xFF; // to do: does carry get set when sum + carry = 0x100?
770
99.6M
    goto add_comm;
771
772
210k
  case 0x96: // SUB (HL)
773
210k
    data = READ( rp.hl );
774
210k
    goto sub_comm;
775
776
3.21M
  case 0x90: // SUB B
777
4.40M
  case 0x91: // SUB C
778
8.87M
  case 0x92: // SUB D
779
8.93M
  case 0x93: // SUB E
780
10.4M
  case 0x94: // SUB H
781
56.0M
  case 0x95: // SUB L
782
56.0M
  case 0x97: // SUB A
783
56.0M
    data = R8( op & 7 );
784
56.0M
    goto sub_comm;
785
786
1.42M
  case 0xD6: // SUB IMM
787
1.42M
    pc++;
788
76.2M
  sub_comm:
789
76.2M
    op = rg.a;
790
76.2M
    data = op - data;
791
76.2M
    rg.a = data;
792
76.2M
    goto sub_set_flags;
793
794
3.27M
  case 0x9E: // SBC (HL)
795
3.27M
    data = READ( rp.hl );
796
3.27M
    goto sbc_comm;
797
798
298k
  case 0x98: // SBC B
799
1.49M
  case 0x99: // SBC C
800
1.49M
  case 0x9A: // SBC D
801
1.54M
  case 0x9B: // SBC E
802
11.4M
  case 0x9C: // SBC H
803
11.4M
  case 0x9D: // SBC L
804
15.0M
  case 0x9F: // SBC A
805
15.0M
    data = R8( op & 7 );
806
15.0M
    goto sbc_comm;
807
808
185k
  case 0xDE: // SBC IMM
809
185k
    pc++;
810
18.5M
  sbc_comm:
811
18.5M
    data += (flags >> 4) & 1;
812
18.5M
    data &= 0xFF; // to do: does carry get set when sum + carry = 0x100?
813
18.5M
    goto sub_comm;
814
815
// Logical
816
817
15.2M
  case 0xA0: // AND B
818
15.3M
  case 0xA1: // AND C
819
15.6M
  case 0xA2: // AND D
820
15.7M
  case 0xA3: // AND E
821
16.0M
  case 0xA4: // AND H
822
16.7M
  case 0xA5: // AND L
823
16.7M
    data = R8( op & 7 );
824
16.7M
    goto and_comm;
825
826
1.02M
  case 0xA6: // AND (HL)
827
1.02M
    data = READ( rp.hl );
828
1.02M
    pc--; // FALLTHRU
829
5.49M
  case 0xE6: // AND IMM
830
5.49M
    pc++;
831
22.2M
  and_comm:
832
22.2M
    rg.a &= data; // FALLTHRU
833
22.4M
  case 0xA7: // AND A
834
22.4M
    flags = h_flag | (((rg.a - 1) >> 1) & z_flag);
835
22.4M
    goto loop;
836
837
22.3k
  case 0xB0: // OR B
838
9.00M
  case 0xB1: // OR C
839
12.9M
  case 0xB2: // OR D
840
13.0M
  case 0xB3: // OR E
841
13.1M
  case 0xB4: // OR H
842
13.1M
  case 0xB5: // OR L
843
13.1M
    data = R8( op & 7 );
844
13.1M
    goto or_comm;
845
846
577k
  case 0xB6: // OR (HL)
847
577k
    data = READ( rp.hl );
848
577k
    pc--; // FALLTHRU
849
585k
  case 0xF6: // OR IMM
850
585k
    pc++;
851
13.7M
  or_comm:
852
13.7M
    rg.a |= data; // FALLTHRU
853
13.7M
  case 0xB7: // OR A
854
13.7M
    flags = ((rg.a - 1) >> 1) & z_flag;
855
13.7M
    goto loop;
856
857
2.57M
  case 0xA8: // XOR B
858
2.59M
  case 0xA9: // XOR C
859
9.80M
  case 0xAA: // XOR D
860
10.0M
  case 0xAB: // XOR E
861
14.0M
  case 0xAC: // XOR H
862
15.4M
  case 0xAD: // XOR L
863
15.4M
    data = R8( op & 7 );
864
15.4M
    goto xor_comm;
865
866
305k
  case 0xAE: // XOR (HL)
867
305k
    data = READ( rp.hl );
868
305k
    pc--; // FALLTHRU
869
531k
  case 0xEE: // XOR IMM
870
531k
    pc++;
871
15.9M
  xor_comm:
872
15.9M
    data ^= rg.a;
873
15.9M
    rg.a = data;
874
15.9M
    data--;
875
15.9M
    flags = (data >> 1) & z_flag;
876
15.9M
    goto loop;
877
878
5.83k
  case 0xAF: // XOR A
879
5.83k
    rg.a = 0;
880
5.83k
    flags = z_flag;
881
5.83k
    goto loop;
882
883
// Stack
884
885
1.15M
  case 0xF1: // POP AF
886
1.18M
  case 0xC1: // POP BC
887
3.20M
  case 0xD1: // POP DE
888
7.55M
  case 0xE1: // POP HL (common)
889
7.55M
    data = READ( sp );
890
7.55M
    r16 [(op >> 4) & 3] = data + 0x100 * READ( sp + 1 );
891
7.55M
    sp = (sp + 2) & 0xFFFF;
892
7.55M
    if ( op != 0xF1 )
893
6.40M
      goto loop;
894
1.15M
    flags = rg.a & 0xF0;
895
1.15M
    rg.a = rg.flags;
896
1.15M
    goto loop;
897
898
26.6k
  case 0xC5: // PUSH BC
899
26.6k
    data = rp.bc;
900
26.6k
    goto push;
901
902
790k
  case 0xD5: // PUSH DE
903
790k
    data = rp.de;
904
790k
    goto push;
905
906
524k
  case 0xE5: // PUSH HL
907
524k
    data = rp.hl;
908
524k
    goto push;
909
910
4.21M
  case 0xF5: // PUSH AF
911
4.21M
    data = (rg.a << 8) | flags;
912
4.21M
    goto push;
913
914
// Flow control
915
916
312M
  case 0xFF:
917
312M
    if ( pc == idle_addr + 1 )
918
46.1k
      goto stop;
919
    // FALLTHRU
920
360M
  case 0xC7: case 0xCF: case 0xD7: case 0xDF:  // RST
921
390M
  case 0xE7: case 0xEF: case 0xF7:
922
390M
    data = pc;
923
390M
    pc = (op & 0x38) + rst_base;
924
390M
    goto push;
925
926
568k
  case 0xCC: // CZ
927
568k
    pc += 2;
928
568k
    if ( flags & z_flag )
929
118k
      goto call;
930
450k
    goto loop;
931
932
610k
  case 0xD4: // CNC
933
610k
    pc += 2;
934
610k
    if ( !(flags & c_flag) )
935
591k
      goto call;
936
18.4k
    goto loop;
937
938
108k
  case 0xDC: // CC
939
108k
    pc += 2;
940
108k
    if ( flags & c_flag )
941
69.3k
      goto call;
942
39.5k
    goto loop;
943
944
42.2k
  case 0xD9: // RETI
945
    //interrupts_enabled = 1;
946
42.2k
    goto ret;
947
948
2.00M
  case 0xC0: // RZ
949
2.00M
    if ( !(flags & z_flag) )
950
1.57M
      goto ret;
951
421k
    goto loop;
952
953
588k
  case 0xD0: // RNC
954
588k
    if ( !(flags & c_flag) )
955
575k
      goto ret;
956
12.7k
    goto loop;
957
958
1.22M
  case 0xD8: // RC
959
1.22M
    if ( flags & c_flag )
960
17.9k
      goto ret;
961
1.20M
    goto loop;
962
963
6.66M
  case 0x18: // JR
964
6.66M
    BRANCH( true )
965
966
14.6M
  case 0x30: // JR NC
967
14.6M
    BRANCH( !(flags & c_flag) )
968
969
7.45M
  case 0x38: // JR C
970
7.45M
    BRANCH( flags & c_flag )
971
972
15.1M
  case 0xE9: // JP_HL
973
15.1M
    pc = rp.hl;
974
15.1M
    goto loop;
975
976
3.57M
  case 0xC3: // JP (next-most-common)
977
3.57M
    pc = GET_ADDR();
978
3.57M
    goto loop;
979
980
152k
  case 0xC2: // JP NZ
981
152k
    pc += 2;
982
152k
    if ( !(flags & z_flag) )
983
151k
      goto jp_taken;
984
921
    goto loop;
985
986
5.39M
  case 0xCA: // JP Z (most common)
987
5.39M
    pc += 2;
988
5.39M
    if ( !(flags & z_flag) )
989
419k
      goto loop;
990
8.76M
  jp_taken:
991
8.76M
    pc -= 2;
992
8.76M
    pc = GET_ADDR();
993
8.76M
    goto loop;
994
995
3.65M
  case 0xD2: // JP NC
996
3.65M
    pc += 2;
997
3.65M
    if ( !(flags & c_flag) )
998
3.62M
      goto jp_taken;
999
27.3k
    goto loop;
1000
1001
211k
  case 0xDA: // JP C
1002
211k
    pc += 2;
1003
211k
    if ( flags & c_flag )
1004
12.8k
      goto jp_taken;
1005
199k
    goto loop;
1006
1007
// Flags
1008
1009
14.0M
  case 0x2F: // CPL
1010
14.0M
    rg.a = ~rg.a;
1011
14.0M
    flags |= n_flag | h_flag;
1012
14.0M
    goto loop;
1013
1014
568k
  case 0x3F: // CCF
1015
568k
    flags = (flags ^ c_flag) & ~(n_flag | h_flag);
1016
568k
    goto loop;
1017
1018
2.08M
  case 0x37: // SCF
1019
2.08M
    flags = (flags | c_flag) & ~(n_flag | h_flag);
1020
2.08M
    goto loop;
1021
1022
5.60M
  case 0xF3: // DI
1023
    //interrupts_enabled = 0;
1024
5.60M
    goto loop;
1025
1026
340k
  case 0xFB: // EI
1027
    //interrupts_enabled = 1;
1028
340k
    goto loop;
1029
1030
// Special
1031
1032
17.6M
  case 0xDD: case 0xD3: case 0xDB: case 0xE3: case 0xE4: // ?
1033
39.7M
  case 0xEB: case 0xEC: case 0xF4: case 0xFD: case 0xFC:
1034
43.0M
  case 0x10: // STOP
1035
43.3M
  case 0x27: // DAA (I'll have to implement this eventually...)
1036
44.3M
  case 0xBF:
1037
46.2M
  case 0xED: // Z80 prefix
1038
46.6M
  case 0x76: // HALT
1039
46.6M
    s.remain++;
1040
46.6M
    goto stop;
1041
20.6G
  }
1042
1043
  // If this fails then the case above is missing an opcode
1044
20.6G
  assert( false );
1045
1046
47.0M
stop:
1047
47.0M
  pc--;
1048
1049
  // copy state back
1050
47.0M
  STATIC_CAST(core_regs_t&,r) = rg;
1051
47.0M
  r.pc = pc;
1052
47.0M
  r.sp = sp;
1053
47.0M
  r.flags = flags;
1054
1055
47.0M
  this->state = &state_;
1056
47.0M
  memcpy( &this->state_, &s, sizeof this->state_ );
1057
1058
47.0M
  return s.remain > 0;
1059
0
}