1 // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/
2 
3 /*
4 Last validated with zexall 2006.11.21 5:26 PM
5 * Doesn't implement the R register or immediate interrupt after EI.
6 * Address wrap-around isn't completely correct, but is prevented from crashing emulator.
7 */
8 
9 #include "Ay_Cpu.h"
10 
11 #include "blargg_endian.h"
12 #include <string.h>
13 
14 //#include "z80_cpu_log.h"
15 
16 /* Copyright (C) 2006 Shay Green. This module is free software; you
17 can redistribute it and/or modify it under the terms of the GNU Lesser
18 General Public License as published by the Free Software Foundation; either
19 version 2.1 of the License, or (at your option) any later version. This
20 module is distributed in the hope that it will be useful, but WITHOUT ANY
21 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
22 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
23 details. You should have received a copy of the GNU Lesser General Public
24 License along with this module; if not, write to the Free Software Foundation,
25 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
26 
27 #define SYNC_TIME()     (void) (s.time = s_time)
28 #define RELOAD_TIME()   (void) (s_time = s.time)
29 
30 // Callbacks to emulator
31 
32 #define CPU_OUT( cpu, addr, data, TIME )\
33 	ay_cpu_out( cpu, TIME, addr, data )
34 
35 #define CPU_IN( cpu, addr, TIME )\
36 	ay_cpu_in( cpu, addr )
37 
38 #include "blargg_source.h"
39 
40 // flags, named with hex value for clarity
41 int const S80 = 0x80;
42 int const Z40 = 0x40;
43 int const F20 = 0x20;
44 int const H10 = 0x10;
45 int const F08 = 0x08;
46 int const V04 = 0x04;
47 int const P04 = 0x04;
48 int const N02 = 0x02;
49 int const C01 = 0x01;
50 
51 #define SZ28P( n )  szpc [n]
52 #define SZ28PC( n ) szpc [n]
53 #define SZ28C( n )  (szpc [n] & ~P04)
54 #define SZ28( n )   SZ28C( n )
55 
56 #define SET_R( n )  (void) (r.r = n)
57 #define GET_R()     (r.r)
58 
Ay_Cpu()59 Ay_Cpu::Ay_Cpu()
60 {
61 	state = &state_;
62 	for ( int i = 0x100; --i >= 0; )
63 	{
64 		int even = 1;
65 		for ( int p = i; p; p >>= 1 )
66 			even ^= p;
67 		int n = (i & (S80 | F20 | F08)) | ((even & 1) * P04);
68 		szpc [i] = n;
69 		szpc [i + 0x100] = n | C01;
70 	}
71 	szpc [0x000] |= Z40;
72 	szpc [0x100] |= Z40;
73 }
74 
reset(void * m)75 void Ay_Cpu::reset( void* m )
76 {
77 	mem = (uint8_t*) m;
78 
79 	check( state == &state_ );
80 	state = &state_;
81 	state_.time = 0;
82 	state_.base = 0;
83 	end_time_   = 0;
84 
85 	memset( &r, 0, sizeof r );
86 }
87 
88 #define TIME                        (s_time + s.base)
89 #define READ_PROG( addr )           (mem [addr])
90 #define INSTR( offset )             READ_PROG( pc + (offset) )
91 #define GET_ADDR()                  GET_LE16( &READ_PROG( pc ) )
92 #define READ( addr )                READ_PROG( addr )
93 #define WRITE( addr, data )         (void) (READ_PROG( addr ) = data)
94 #define READ_WORD( addr )           GET_LE16( &READ_PROG( addr ) )
95 #define WRITE_WORD( addr, data )    SET_LE16( &READ_PROG( addr ), data )
96 #define IN( addr )                  CPU_IN( this, addr, TIME )
97 #define OUT( addr, data )           CPU_OUT( this, addr, data, TIME )
98 
99 #if BLARGG_BIG_ENDIAN
100 	#define R8( n, offset ) ((r8_ - offset) [n])
101 #elif BLARGG_LITTLE_ENDIAN
102 	#define R8( n, offset ) ((r8_ - offset) [(n) ^ 1])
103 #else
104 	#error "Byte order of CPU must be known"
105 #endif
106 
107 //#define R16( n, shift, offset )   (r16_ [((n) >> shift) - (offset >> shift)])
108 
109 // help compiler see that it can just adjust stack offset, saving an extra instruction
110 #define R16( n, shift, offset )\
111 	(*(uint16_t*) ((char*) r16_ - (offset >> (shift - 1)) + ((n) >> (shift - 1))))
112 
113 #define CASE5( a, b, c, d, e          ) case 0x##a:case 0x##b:case 0x##c:case 0x##d:case 0x##e
114 #define CASE6( a, b, c, d, e, f       ) CASE5( a, b, c, d, e       ): case 0x##f
115 #define CASE7( a, b, c, d, e, f, g    ) CASE6( a, b, c, d, e, f    ): case 0x##g
116 #define CASE8( a, b, c, d, e, f, g, h ) CASE7( a, b, c, d, e, f, g ): case 0x##h
117 
118 // high four bits are $ED time - 8, low four bits are $DD/$FD time - 8
119 static byte const ed_dd_timing [0x100] = {
120 //0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
121 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
122 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
123 0x00,0x06,0x0C,0x02,0x00,0x00,0x03,0x00,0x00,0x07,0x0C,0x02,0x00,0x00,0x03,0x00,
124 0x00,0x00,0x00,0x00,0x0F,0x0F,0x0B,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
125 0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
126 0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
127 0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,
128 0x4B,0x4B,0x7B,0xCB,0x0B,0x6B,0x00,0x0B,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x00,
129 0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
130 0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
131 0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,
132 0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,
133 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,
134 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
135 0x00,0x06,0x00,0x0F,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
136 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
137 };
138 
run(cpu_time_t end_time)139 bool Ay_Cpu::run( cpu_time_t end_time )
140 {
141 	set_end_time( end_time );
142 	state_t s = this->state_;
143 	this->state = &s;
144 	bool warning = false;
145 
146 	union {
147 		regs_t rg;
148 		pairs_t rp;
149 		uint8_t r8_ [8]; // indexed
150 		uint16_t r16_ [4];
151 	};
152 	rg = this->r.b;
153 
154 	cpu_time_t s_time = s.time;
155 	uint8_t* const mem = this->mem; // cache
156 	uint16_t pc = r.pc;
157 	uint16_t sp = r.sp;
158 	uint16_t ix = r.ix; // TODO: keep in memory for direct access?
159 	uint16_t iy = r.iy;
160 	int flags = r.b.flags;
161 
162 	goto loop;
163 jr_not_taken:
164 	s_time -= 5;
165 	goto loop;
166 call_not_taken:
167 	s_time -= 7;
168 jp_not_taken:
169 	pc += 2;
170 loop:
171 
172 	check( (unsigned long) pc < 0x10000 );
173 	check( (unsigned long) sp < 0x10000 );
174 	check( (unsigned) flags < 0x100 );
175 	check( (unsigned) ix < 0x10000 );
176 	check( (unsigned) iy < 0x10000 );
177 
178 	uint8_t opcode;
179 	opcode = READ_PROG( pc );
180 	pc++;
181 
182 	static byte const base_timing [0x100] = {
183 	//   0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
184 		 4,10, 7, 6, 4, 4, 7, 4, 4,11, 7, 6, 4, 4, 7, 4, // 0
185 		13,10, 7, 6, 4, 4, 7, 4,12,11, 7, 6, 4, 4, 7, 4, // 1
186 		12,10,16, 6, 4, 4, 7, 4,12,11,16, 6, 4, 4, 7, 4, // 2
187 		12,10,13, 6,11,11,10, 4,12,11,13, 6, 4, 4, 7, 4, // 3
188 		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 4
189 		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 5
190 		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 6
191 		 7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4, // 7
192 		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 8
193 		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 9
194 		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // A
195 		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // B
196 		11,10,10,10,17,11, 7,11,11,10,10, 8,17,17, 7,11, // C
197 		11,10,10,11,17,11, 7,11,11, 4,10,11,17, 8, 7,11, // D
198 		11,10,10,19,17,11, 7,11,11, 4,10, 4,17, 8, 7,11, // E
199 		11,10,10, 4,17,11, 7,11,11, 6,10, 4,17, 8, 7,11, // F
200 	};
201 
202 	uint16_t data;
203 	data = base_timing [opcode];
204 	if ( (s_time += data) >= 0 )
205 		goto possibly_out_of_time;
206 almost_out_of_time:
207 
208 	data = READ_PROG( pc );
209 
210 	#ifdef Z80_CPU_LOG_H
211 		//log_opcode( opcode, READ_PROG( pc ) );
212 		z80_log_regs( rg.a, rp.bc, rp.de, rp.hl, sp, ix, iy );
213 		z80_cpu_log( "new", pc - 1, opcode, READ_PROG( pc ),
214 				READ_PROG( pc + 1 ), READ_PROG( pc + 2 ) );
215 	#endif
216 
217 	switch ( opcode )
218 	{
219 possibly_out_of_time:
220 		if ( s_time < (int) data )
221 			goto almost_out_of_time;
222 		s_time -= data;
223 		goto out_of_time;
224 
225 // Common
226 
227 	case 0x00: // NOP
228 	CASE7( 40, 49, 52, 5B, 64, 6D, 7F ): // LD B,B etc.
229 		goto loop;
230 
231 	case 0x08:{// EX AF,AF'
232 		int temp = r.alt.b.a;
233 		r.alt.b.a = rg.a;
234 		rg.a = temp;
235 
236 		temp = r.alt.b.flags;
237 		r.alt.b.flags = flags;
238 		flags = temp;
239 		goto loop;
240 	}
241 
242 	case 0xD3: // OUT (imm),A
243 		pc++;
244 		OUT( data + rg.a * 0x100, rg.a );
245 		goto loop;
246 
247 	case 0x2E: // LD L,imm
248 		pc++;
249 		rg.l = data;
250 		goto loop;
251 
252 	case 0x3E: // LD A,imm
253 		pc++;
254 		rg.a = data;
255 		goto loop;
256 
257 	case 0x3A:{// LD A,(addr)
258 		uint16_t addr = GET_ADDR();
259 		pc += 2;
260 		rg.a = READ( addr );
261 		goto loop;
262 	}
263 
264 // Conditional
265 
266 #define ZERO    (flags & Z40)
267 #define CARRY   (flags & C01)
268 #define EVEN    (flags & P04)
269 #define MINUS   (flags & S80)
270 
271 // JR
272 #define JR( cond ) {\
273 	int disp = (int8_t) data;\
274 	pc++;\
275 	if ( !(cond) )\
276 		goto jr_not_taken;\
277 	pc += disp;\
278 	goto loop;\
279 }
280 
281 	case 0x20: JR( !ZERO  ) // JR NZ,disp
282 	case 0x28: JR(  ZERO  ) // JR Z,disp
283 	case 0x30: JR( !CARRY ) // JR NC,disp
284 	case 0x38: JR(  CARRY ) // JR C,disp
285 	case 0x18: JR(  true  ) // JR disp
286 
287 	case 0x10:{// DJNZ disp
288 		int temp = rg.b - 1;
289 		rg.b = temp;
290 		JR( temp )
291 	}
292 
293 // JP
294 #define JP( cond )  if ( !(cond) ) goto jp_not_taken; pc = GET_ADDR(); goto loop;
295 
296 	case 0xC2: JP( !ZERO  ) // JP NZ,addr
297 	case 0xCA: JP(  ZERO  ) // JP Z,addr
298 	case 0xD2: JP( !CARRY ) // JP NC,addr
299 	case 0xDA: JP(  CARRY ) // JP C,addr
300 	case 0xE2: JP( !EVEN  ) // JP PO,addr
301 	case 0xEA: JP(  EVEN  ) // JP PE,addr
302 	case 0xF2: JP( !MINUS ) // JP P,addr
303 	case 0xFA: JP(  MINUS ) // JP M,addr
304 
305 	case 0xC3: // JP addr
306 		pc = GET_ADDR();
307 		goto loop;
308 
309 	case 0xE9: // JP HL
310 		pc = rp.hl;
311 		goto loop;
312 
313 // RET
314 #define RET( cond ) if ( cond ) goto ret_taken; s_time -= 6; goto loop;
315 
316 	case 0xC0: RET( !ZERO  ) // RET NZ
317 	case 0xC8: RET(  ZERO  ) // RET Z
318 	case 0xD0: RET( !CARRY ) // RET NC
319 	case 0xD8: RET(  CARRY ) // RET C
320 	case 0xE0: RET( !EVEN  ) // RET PO
321 	case 0xE8: RET(  EVEN  ) // RET PE
322 	case 0xF0: RET( !MINUS ) // RET P
323 	case 0xF8: RET(  MINUS ) // RET M
324 
325 	case 0xC9: // RET
326 	ret_taken:
327 		pc = READ_WORD( sp );
328 		sp = uint16_t (sp + 2);
329 		goto loop;
330 
331 // CALL
332 #define CALL( cond ) if ( cond ) goto call_taken; goto call_not_taken;
333 
334 	case 0xC4: CALL( !ZERO  ) // CALL NZ,addr
335 	case 0xCC: CALL(  ZERO  ) // CALL Z,addr
336 	case 0xD4: CALL( !CARRY ) // CALL NC,addr
337 	case 0xDC: CALL(  CARRY ) // CALL C,addr
338 	case 0xE4: CALL( !EVEN  ) // CALL PO,addr
339 	case 0xEC: CALL(  EVEN  ) // CALL PE,addr
340 	case 0xF4: CALL( !MINUS ) // CALL P,addr
341 	case 0xFC: CALL(  MINUS ) // CALL M,addr
342 
343 	case 0xCD:{// CALL addr
344 	call_taken:
345 		uint16_t addr = pc + 2;
346 		pc = GET_ADDR();
347 		sp = uint16_t (sp - 2);
348 		WRITE_WORD( sp, addr );
349 		goto loop;
350 	}
351 
352 	case 0xFF: // RST
353 		if ( (pc - 1) > 0xFFFF )
354 		{
355 			pc = uint16_t (pc - 1);
356 			s_time -= 11;
357 			goto loop;
358 		}
359 	CASE7( C7, CF, D7, DF, E7, EF, F7 ):
360 		data = pc;
361 		pc = opcode & 0x38;
362 		goto push_data;
363 
364 // PUSH/POP
365 	case 0xF5: // PUSH AF
366 		data = rg.a * 0x100u + flags;
367 		goto push_data;
368 
369 	case 0xC5: // PUSH BC
370 	case 0xD5: // PUSH DE
371 	case 0xE5: // PUSH HL
372 		data = R16( opcode, 4, 0xC5 );
373 	push_data:
374 		sp = uint16_t (sp - 2);
375 		WRITE_WORD( sp, data );
376 		goto loop;
377 
378 	case 0xF1: // POP AF
379 		flags = READ( sp );
380 		rg.a = READ( sp + 1 );
381 		sp = uint16_t (sp + 2);
382 		goto loop;
383 
384 	case 0xC1: // POP BC
385 	case 0xD1: // POP DE
386 	case 0xE1: // POP HL
387 		R16( opcode, 4, 0xC1 ) = READ_WORD( sp );
388 		sp = uint16_t (sp + 2);
389 		goto loop;
390 
391 // ADC/ADD/SBC/SUB
392 	case 0x96: // SUB (HL)
393 	case 0x86: // ADD (HL)
394 		flags &= ~C01;
395 	case 0x9E: // SBC (HL)
396 	case 0x8E: // ADC (HL)
397 		data = READ( rp.hl );
398 		goto adc_data;
399 
400 	case 0xD6: // SUB A,imm
401 	case 0xC6: // ADD imm
402 		flags &= ~C01;
403 	case 0xDE: // SBC A,imm
404 	case 0xCE: // ADC imm
405 		pc++;
406 		goto adc_data;
407 
408 	CASE7( 90, 91, 92, 93, 94, 95, 97 ): // SUB r
409 	CASE7( 80, 81, 82, 83, 84, 85, 87 ): // ADD r
410 		flags &= ~C01;
411 	CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // SBC r
412 	CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // ADC r
413 		data = R8( opcode & 7, 0 );
414 	adc_data: {
415 		int result = data + (flags & C01);
416 		data ^= rg.a;
417 		flags = opcode >> 3 & N02; // bit 4 is set in subtract opcodes
418 		if ( flags )
419 			result = -result;
420 		result += rg.a;
421 		data ^= result;
422 		flags |=(data & H10) |
423 				((data - -0x80) >> 6 & V04) |
424 				SZ28C( result & 0x1FF );
425 		rg.a = result;
426 		goto loop;
427 	}
428 
429 // CP
430 	case 0xBE: // CP (HL)
431 		data = READ( rp.hl );
432 		goto cp_data;
433 
434 	case 0xFE: // CP imm
435 		pc++;
436 		goto cp_data;
437 
438 	CASE7( B8, B9, BA, BB, BC, BD, BF ): // CP r
439 		data = R8( opcode, 0xB8 );
440 	cp_data: {
441 		int result = rg.a - data;
442 		flags = N02 | (data & (F20 | F08)) | (result >> 8 & C01);
443 		data ^= rg.a;
444 		flags |=(((result ^ rg.a) & data) >> 5 & V04) |
445 				(((data & H10) ^ result) & (S80 | H10));
446 		if ( (uint8_t) result )
447 			goto loop;
448 		flags |= Z40;
449 		goto loop;
450 	}
451 
452 // ADD HL,rp
453 
454 	case 0x39: // ADD HL,SP
455 		data = sp;
456 		goto add_hl_data;
457 
458 	case 0x09: // ADD HL,BC
459 	case 0x19: // ADD HL,DE
460 	case 0x29: // ADD HL,HL
461 		data = R16( opcode, 4, 0x09 );
462 	add_hl_data: {
463 		blargg_ulong sum = rp.hl + data;
464 		data ^= rp.hl;
465 		rp.hl = sum;
466 		flags = (flags & (S80 | Z40 | V04)) |
467 				(sum >> 16) |
468 				(sum >> 8 & (F20 | F08)) |
469 				((data ^ sum) >> 8 & H10);
470 		goto loop;
471 	}
472 
473 	case 0x27:{// DAA
474 		int a = rg.a;
475 		if ( a > 0x99 )
476 			flags |= C01;
477 
478 		int adjust = 0x60 & -(flags & C01);
479 
480 		if ( flags & H10 || (a & 0x0F) > 9 )
481 			adjust |= 0x06;
482 
483 		if ( flags & N02 )
484 			adjust = -adjust;
485 		a += adjust;
486 
487 		flags = (flags & (C01 | N02)) |
488 				((rg.a ^ a) & H10) |
489 				SZ28P( (uint8_t) a );
490 		rg.a = a;
491 		goto loop;
492 	}
493 	/*
494 	case 0x27:{// DAA
495 		// more optimized, but probably not worth the obscurity
496 		int f = (rg.a + (0xFF - 0x99)) >> 8 | flags; // (a > 0x99 ? C01 : 0) | flags
497 		int adjust = 0x60 & -(f & C01); // f & C01 ? 0x60 : 0
498 
499 		if ( (((rg.a + (0x0F - 9)) ^ rg.a) | f) & H10 ) // flags & H10 || (rg.a & 0x0F) > 9
500 			adjust |= 0x06;
501 
502 		if ( f & N02 )
503 			adjust = -adjust;
504 		int a = rg.a + adjust;
505 
506 		flags = (f & (N02 | C01)) | ((rg.a ^ a) & H10) | SZ28P( (uint8_t) a );
507 		rg.a = a;
508 		goto loop;
509 	}
510 	*/
511 
512 // INC/DEC
513 	case 0x34: // INC (HL)
514 		data = READ( rp.hl ) + 1;
515 		WRITE( rp.hl, data );
516 		goto inc_set_flags;
517 
518 	CASE7( 04, 0C, 14, 1C, 24, 2C, 3C ): // INC r
519 		data = ++R8( opcode >> 3, 0 );
520 	inc_set_flags:
521 		flags = (flags & C01) |
522 				(((data & 0x0F) - 1) & H10) |
523 				SZ28( (uint8_t) data );
524 		if ( data != 0x80 )
525 			goto loop;
526 		flags |= V04;
527 		goto loop;
528 
529 	case 0x35: // DEC (HL)
530 		data = READ( rp.hl ) - 1;
531 		WRITE( rp.hl, data );
532 		goto dec_set_flags;
533 
534 	CASE7( 05, 0D, 15, 1D, 25, 2D, 3D ): // DEC r
535 		data = --R8( opcode >> 3, 0 );
536 	dec_set_flags:
537 		flags = (flags & C01) | N02 |
538 				(((data & 0x0F) + 1) & H10) |
539 				SZ28( (uint8_t) data );
540 		if ( data != 0x7F )
541 			goto loop;
542 		flags |= V04;
543 		goto loop;
544 
545 	case 0x03: // INC BC
546 	case 0x13: // INC DE
547 	case 0x23: // INC HL
548 		R16( opcode, 4, 0x03 )++;
549 		goto loop;
550 
551 	case 0x33: // INC SP
552 		sp = uint16_t (sp + 1);
553 		goto loop;
554 
555 	case 0x0B: // DEC BC
556 	case 0x1B: // DEC DE
557 	case 0x2B: // DEC HL
558 		R16( opcode, 4, 0x0B )--;
559 		goto loop;
560 
561 	case 0x3B: // DEC SP
562 		sp = uint16_t (sp - 1);
563 		goto loop;
564 
565 // AND
566 	case 0xA6: // AND (HL)
567 		data = READ( rp.hl );
568 		goto and_data;
569 
570 	case 0xE6: // AND imm
571 		pc++;
572 		goto and_data;
573 
574 	CASE7( A0, A1, A2, A3, A4, A5, A7 ): // AND r
575 		data = R8( opcode, 0xA0 );
576 	and_data:
577 		rg.a &= data;
578 		flags = SZ28P( rg.a ) | H10;
579 		goto loop;
580 
581 // OR
582 	case 0xB6: // OR (HL)
583 		data = READ( rp.hl );
584 		goto or_data;
585 
586 	case 0xF6: // OR imm
587 		pc++;
588 		goto or_data;
589 
590 	CASE7( B0, B1, B2, B3, B4, B5, B7 ): // OR r
591 		data = R8( opcode, 0xB0 );
592 	or_data:
593 		rg.a |= data;
594 		flags = SZ28P( rg.a );
595 		goto loop;
596 
597 // XOR
598 	case 0xAE: // XOR (HL)
599 		data = READ( rp.hl );
600 		goto xor_data;
601 
602 	case 0xEE: // XOR imm
603 		pc++;
604 		goto xor_data;
605 
606 	CASE7( A8, A9, AA, AB, AC, AD, AF ): // XOR r
607 		data = R8( opcode, 0xA8 );
608 	xor_data:
609 		rg.a ^= data;
610 		flags = SZ28P( rg.a );
611 		goto loop;
612 
613 // LD
614 	CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (HL),r
615 		WRITE( rp.hl, R8( opcode, 0x70 ) );
616 		goto loop;
617 
618 	CASE6( 41, 42, 43, 44, 45, 47 ): // LD B,r
619 	CASE6( 48, 4A, 4B, 4C, 4D, 4F ): // LD C,r
620 	CASE6( 50, 51, 53, 54, 55, 57 ): // LD D,r
621 	CASE6( 58, 59, 5A, 5C, 5D, 5F ): // LD E,r
622 	CASE6( 60, 61, 62, 63, 65, 67 ): // LD H,r
623 	CASE6( 68, 69, 6A, 6B, 6C, 6F ): // LD L,r
624 	CASE6( 78, 79, 7A, 7B, 7C, 7D ): // LD A,r
625 		R8( opcode >> 3 & 7, 0 ) = R8( opcode & 7, 0 );
626 		goto loop;
627 
628 	CASE5( 06, 0E, 16, 1E, 26 ): // LD r,imm
629 		R8( opcode >> 3, 0 ) = data;
630 		pc++;
631 		goto loop;
632 
633 	case 0x36: // LD (HL),imm
634 		pc++;
635 		WRITE( rp.hl, data );
636 		goto loop;
637 
638 	CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(HL)
639 		R8( opcode >> 3, 8 ) = READ( rp.hl );
640 		goto loop;
641 
642 	case 0x01: // LD rp,imm
643 	case 0x11:
644 	case 0x21:
645 		R16( opcode, 4, 0x01 ) = GET_ADDR();
646 		pc += 2;
647 		goto loop;
648 
649 	case 0x31: // LD sp,imm
650 		sp = GET_ADDR();
651 		pc += 2;
652 		goto loop;
653 
654 	case 0x2A:{// LD HL,(addr)
655 		uint16_t addr = GET_ADDR();
656 		pc += 2;
657 		rp.hl = READ_WORD( addr );
658 		goto loop;
659 	}
660 
661 	case 0x32:{// LD (addr),A
662 		uint16_t addr = GET_ADDR();
663 		pc += 2;
664 		WRITE( addr, rg.a );
665 		goto loop;
666 	}
667 
668 	case 0x22:{// LD (addr),HL
669 		uint16_t addr = GET_ADDR();
670 		pc += 2;
671 		WRITE_WORD( addr, rp.hl );
672 		goto loop;
673 	}
674 
675 	case 0x02: // LD (BC),A
676 	case 0x12: // LD (DE),A
677 		WRITE( R16( opcode, 4, 0x02 ), rg.a );
678 		goto loop;
679 
680 	case 0x0A: // LD A,(BC)
681 	case 0x1A: // LD A,(DE)
682 		rg.a = READ( R16( opcode, 4, 0x0A ) );
683 		goto loop;
684 
685 	case 0xF9: // LD SP,HL
686 		sp = rp.hl;
687 		goto loop;
688 
689 // Rotate
690 
691 	case 0x07:{// RLCA
692 		uint16_t temp = rg.a;
693 		temp = (temp << 1) | (temp >> 7);
694 		flags = (flags & (S80 | Z40 | P04)) |
695 				(temp & (F20 | F08 | C01));
696 		rg.a = temp;
697 		goto loop;
698 	}
699 
700 	case 0x0F:{// RRCA
701 		uint16_t temp = rg.a;
702 		flags = (flags & (S80 | Z40 | P04)) |
703 				(temp & C01);
704 		temp = (temp << 7) | (temp >> 1);
705 		flags |= temp & (F20 | F08);
706 		rg.a = temp;
707 		goto loop;
708 	}
709 
710 	case 0x17:{// RLA
711 		blargg_ulong temp = (rg.a << 1) | (flags & C01);
712 		flags = (flags & (S80 | Z40 | P04)) |
713 				(temp & (F20 | F08)) |
714 				(temp >> 8);
715 		rg.a = temp;
716 		goto loop;
717 	}
718 
719 	case 0x1F:{// RRA
720 		uint16_t temp = (flags << 7) | (rg.a >> 1);
721 		flags = (flags & (S80 | Z40 | P04)) |
722 				(temp & (F20 | F08)) |
723 				(rg.a & C01);
724 		rg.a = temp;
725 		goto loop;
726 	}
727 
728 // Misc
729 	case 0x2F:{// CPL
730 		uint16_t temp = ~rg.a;
731 		flags = (flags & (S80 | Z40 | P04 | C01)) |
732 				(temp & (F20 | F08)) |
733 				(H10 | N02);
734 		rg.a = temp;
735 		goto loop;
736 	}
737 
738 	case 0x3F:{// CCF
739 		flags = ((flags & (S80 | Z40 | P04 | C01)) ^ C01) |
740 				(flags << 4 & H10) |
741 				(rg.a & (F20 | F08));
742 		goto loop;
743 	}
744 
745 	case 0x37: // SCF
746 		flags = (flags & (S80 | Z40 | P04)) | C01 |
747 				(rg.a & (F20 | F08));
748 		goto loop;
749 
750 	case 0xDB: // IN A,(imm)
751 		pc++;
752 		rg.a = IN( data + rg.a * 0x100 );
753 		goto loop;
754 
755 	case 0xE3:{// EX (SP),HL
756 		uint16_t temp = READ_WORD( sp );
757 		WRITE_WORD( sp, rp.hl );
758 		rp.hl = temp;
759 		goto loop;
760 	}
761 
762 	case 0xEB:{// EX DE,HL
763 		uint16_t temp = rp.hl;
764 		rp.hl = rp.de;
765 		rp.de = temp;
766 		goto loop;
767 	}
768 
769 	case 0xD9:{// EXX DE,HL
770 		uint16_t temp = r.alt.w.bc;
771 		r.alt.w.bc = rp.bc;
772 		rp.bc = temp;
773 
774 		temp = r.alt.w.de;
775 		r.alt.w.de = rp.de;
776 		rp.de = temp;
777 
778 		temp = r.alt.w.hl;
779 		r.alt.w.hl = rp.hl;
780 		rp.hl = temp;
781 		goto loop;
782 	}
783 
784 	case 0xF3: // DI
785 		r.iff1 = 0;
786 		r.iff2 = 0;
787 		goto loop;
788 
789 	case 0xFB: // EI
790 		r.iff1 = 1;
791 		r.iff2 = 1;
792 		// TODO: delayed effect
793 		goto loop;
794 
795 	case 0x76: // HALT
796 		goto halt;
797 
798 //////////////////////////////////////// CB prefix
799 	{
800 	case 0xCB:
801 		unsigned data2;
802 		data2 = INSTR( 1 );
803 		(void) data2; // TODO is this the same as data in all cases?
804 		pc++;
805 		switch ( data )
806 		{
807 
808 	// Rotate left
809 
810 	#define RLC( read, write ) {\
811 		uint8_t result = read;\
812 		result = uint8_t (result << 1) | (result >> 7);\
813 		flags = SZ28P( result ) | (result & C01);\
814 		write;\
815 		goto loop;\
816 	}
817 
818 		case 0x06: // RLC (HL)
819 			s_time += 7;
820 			data = rp.hl;
821 		rlc_data_addr:
822 			RLC( READ( data ), WRITE( data, result ) )
823 
824 		CASE7( 00, 01, 02, 03, 04, 05, 07 ):{// RLC r
825 			uint8_t& reg = R8( data, 0 );
826 			RLC( reg, reg = result )
827 		}
828 
829 	#define RL( read, write ) {\
830 		uint16_t result = (read << 1) | (flags & C01);\
831 		flags = SZ28PC( result );\
832 		write;\
833 		goto loop;\
834 	}
835 
836 		case 0x16: // RL (HL)
837 			s_time += 7;
838 			data = rp.hl;
839 		rl_data_addr:
840 			RL( READ( data ), WRITE( data, result ) )
841 
842 		CASE7( 10, 11, 12, 13, 14, 15, 17 ):{// RL r
843 			uint8_t& reg = R8( data, 0x10 );
844 			RL( reg, reg = result )
845 		}
846 
847 	#define SLA( read, add, write ) {\
848 		uint16_t result = (read << 1) | add;\
849 		flags = SZ28PC( result );\
850 		write;\
851 		goto loop;\
852 	}
853 
854 		case 0x26: // SLA (HL)
855 			s_time += 7;
856 			data = rp.hl;
857 		sla_data_addr:
858 			SLA( READ( data ), 0, WRITE( data, result ) )
859 
860 		CASE7( 20, 21, 22, 23, 24, 25, 27 ):{// SLA r
861 			uint8_t& reg = R8( data, 0x20 );
862 			SLA( reg, 0, reg = result )
863 		}
864 
865 		case 0x36: // SLL (HL)
866 			s_time += 7;
867 			data = rp.hl;
868 		sll_data_addr:
869 			SLA( READ( data ), 1, WRITE( data, result ) )
870 
871 		CASE7( 30, 31, 32, 33, 34, 35, 37 ):{// SLL r
872 			uint8_t& reg = R8( data, 0x30 );
873 			SLA( reg, 1, reg = result )
874 		}
875 
876 	// Rotate right
877 
878 	#define RRC( read, write ) {\
879 		uint8_t result = read;\
880 		flags = result & C01;\
881 		result = uint8_t (result << 7) | (result >> 1);\
882 		flags |= SZ28P( result );\
883 		write;\
884 		goto loop;\
885 	}
886 
887 		case 0x0E: // RRC (HL)
888 			s_time += 7;
889 			data = rp.hl;
890 		rrc_data_addr:
891 			RRC( READ( data ), WRITE( data, result ) )
892 
893 		CASE7( 08, 09, 0A, 0B, 0C, 0D, 0F ):{// RRC r
894 			uint8_t& reg = R8( data, 0x08 );
895 			RRC( reg, reg = result )
896 		}
897 
898 	#define RR( read, write ) {\
899 		uint8_t result = read;\
900 		uint8_t temp = result & C01;\
901 		result = uint8_t (flags << 7) | (result >> 1);\
902 		flags = SZ28P( result ) | temp;\
903 		write;\
904 		goto loop;\
905 	}
906 
907 		case 0x1E: // RR (HL)
908 			s_time += 7;
909 			data = rp.hl;
910 		rr_data_addr:
911 			RR( READ( data ), WRITE( data, result ) )
912 
913 		CASE7( 18, 19, 1A, 1B, 1C, 1D, 1F ):{// RR r
914 			uint8_t& reg = R8( data, 0x18 );
915 			RR( reg, reg = result )
916 		}
917 
918 	#define SRA( read, write ) {\
919 		uint8_t result = read;\
920 		flags = result & C01;\
921 		result = (result & 0x80) | (result >> 1);\
922 		flags |= SZ28P( result );\
923 		write;\
924 		goto loop;\
925 	}
926 
927 		case 0x2E: // SRA (HL)
928 			data = rp.hl;
929 			s_time += 7;
930 		sra_data_addr:
931 			SRA( READ( data ), WRITE( data, result ) )
932 
933 		CASE7( 28, 29, 2A, 2B, 2C, 2D, 2F ):{// SRA r
934 			uint8_t& reg = R8( data, 0x28 );
935 			SRA( reg, reg = result )
936 		}
937 
938 	#define SRL( read, write ) {\
939 		uint8_t result = read;\
940 		flags = result & C01;\
941 		result >>= 1;\
942 		flags |= SZ28P( result );\
943 		write;\
944 		goto loop;\
945 	}
946 
947 		case 0x3E: // SRL (HL)
948 			s_time += 7;
949 			data = rp.hl;
950 		srl_data_addr:
951 			SRL( READ( data ), WRITE( data, result ) )
952 
953 		CASE7( 38, 39, 3A, 3B, 3C, 3D, 3F ):{// SRL r
954 			uint8_t& reg = R8( data, 0x38 );
955 			SRL( reg, reg = result )
956 		}
957 
958 	// BIT
959 		{
960 			unsigned temp;
961 		CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ): // BIT b,(HL)
962 			s_time += 4;
963 			temp = READ( rp.hl );
964 			flags &= C01;
965 			goto bit_temp;
966 		CASE7( 40, 41, 42, 43, 44, 45, 47 ): // BIT 0,r
967 		CASE7( 48, 49, 4A, 4B, 4C, 4D, 4F ): // BIT 1,r
968 		CASE7( 50, 51, 52, 53, 54, 55, 57 ): // BIT 2,r
969 		CASE7( 58, 59, 5A, 5B, 5C, 5D, 5F ): // BIT 3,r
970 		CASE7( 60, 61, 62, 63, 64, 65, 67 ): // BIT 4,r
971 		CASE7( 68, 69, 6A, 6B, 6C, 6D, 6F ): // BIT 5,r
972 		CASE7( 70, 71, 72, 73, 74, 75, 77 ): // BIT 6,r
973 		CASE7( 78, 79, 7A, 7B, 7C, 7D, 7F ): // BIT 7,r
974 			temp = R8( data & 7, 0 );
975 			flags = (flags & C01) | (temp & (F20 | F08));
976 		bit_temp:
977 			int masked = temp & 1 << (data >> 3 & 7);
978 			flags |=(masked & S80) | H10 |
979 					((masked - 1) >> 8 & (Z40 | P04));
980 			goto loop;
981 		}
982 
983 	// SET/RES
984 		CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(HL)
985 		CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(HL)
986 			s_time += 7;
987 			int temp = READ( rp.hl );
988 			int bit = 1 << (data >> 3 & 7);
989 			temp |= bit; // SET
990 			if ( !(data & 0x40) )
991 				temp ^= bit; // RES
992 			WRITE( rp.hl, temp );
993 			goto loop;
994 		}
995 
996 		CASE7( C0, C1, C2, C3, C4, C5, C7 ): // SET 0,r
997 		CASE7( C8, C9, CA, CB, CC, CD, CF ): // SET 1,r
998 		CASE7( D0, D1, D2, D3, D4, D5, D7 ): // SET 2,r
999 		CASE7( D8, D9, DA, DB, DC, DD, DF ): // SET 3,r
1000 		CASE7( E0, E1, E2, E3, E4, E5, E7 ): // SET 4,r
1001 		CASE7( E8, E9, EA, EB, EC, ED, EF ): // SET 5,r
1002 		CASE7( F0, F1, F2, F3, F4, F5, F7 ): // SET 6,r
1003 		CASE7( F8, F9, FA, FB, FC, FD, FF ): // SET 7,r
1004 			R8( data & 7, 0 ) |= 1 << (data >> 3 & 7);
1005 			goto loop;
1006 
1007 		CASE7( 80, 81, 82, 83, 84, 85, 87 ): // RES 0,r
1008 		CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // RES 1,r
1009 		CASE7( 90, 91, 92, 93, 94, 95, 97 ): // RES 2,r
1010 		CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // RES 3,r
1011 		CASE7( A0, A1, A2, A3, A4, A5, A7 ): // RES 4,r
1012 		CASE7( A8, A9, AA, AB, AC, AD, AF ): // RES 5,r
1013 		CASE7( B0, B1, B2, B3, B4, B5, B7 ): // RES 6,r
1014 		CASE7( B8, B9, BA, BB, BC, BD, BF ): // RES 7,r
1015 			R8( data & 7, 0 ) &= ~(1 << (data >> 3 & 7));
1016 			goto loop;
1017 		}
1018 		assert( false );
1019 	}
1020 
1021 //////////////////////////////////////// ED prefix
1022 	{
1023 	case 0xED:
1024 		pc++;
1025 		s_time += ed_dd_timing [data] >> 4;
1026 		switch ( data )
1027 		{
1028 		{
1029 			blargg_ulong temp;
1030 		case 0x72: // SBC HL,SP
1031 		case 0x7A: // ADC HL,SP
1032 			temp = sp;
1033 			if ( 0 )
1034 		case 0x42: // SBC HL,BC
1035 		case 0x52: // SBC HL,DE
1036 		case 0x62: // SBC HL,HL
1037 		case 0x4A: // ADC HL,BC
1038 		case 0x5A: // ADC HL,DE
1039 		case 0x6A: // ADC HL,HL
1040 				temp = R16( data >> 3 & 6, 1, 0 );
1041 			blargg_ulong sum = temp + (flags & C01);
1042 			flags = ~data >> 2 & N02;
1043 			if ( flags )
1044 				sum = -sum;
1045 			sum += rp.hl;
1046 			temp ^= rp.hl;
1047 			temp ^= sum;
1048 			flags |=(sum >> 16 & C01) |
1049 					(temp >> 8 & H10) |
1050 					(sum >> 8 & (S80 | F20 | F08)) |
1051 					((temp - -0x8000) >> 14 & V04);
1052 			rp.hl = sum;
1053 			if ( (uint16_t) sum )
1054 				goto loop;
1055 			flags |= Z40;
1056 			goto loop;
1057 		}
1058 
1059 		CASE8( 40, 48, 50, 58, 60, 68, 70, 78 ):{// IN r,(C)
1060 			int temp = IN( rp.bc );
1061 			R8( data >> 3, 8 ) = temp;
1062 			flags = (flags & C01) | SZ28P( temp );
1063 			goto loop;
1064 		}
1065 
1066 		case 0x71: // OUT (C),0
1067 			rg.flags = 0;
1068 		CASE7( 41, 49, 51, 59, 61, 69, 79 ): // OUT (C),r
1069 			OUT( rp.bc, R8( data >> 3, 8 ) );
1070 			goto loop;
1071 
1072 		{
1073 			unsigned temp;
1074 		case 0x73: // LD (ADDR),SP
1075 			temp = sp;
1076 			if ( 0 )
1077 		case 0x43: // LD (ADDR),BC
1078 		case 0x53: // LD (ADDR),DE
1079 				temp = R16( data, 4, 0x43 );
1080 			uint16_t addr = GET_ADDR();
1081 			pc += 2;
1082 			WRITE_WORD( addr, temp );
1083 			goto loop;
1084 		}
1085 
1086 		case 0x4B: // LD BC,(ADDR)
1087 		case 0x5B:{// LD DE,(ADDR)
1088 			uint16_t addr = GET_ADDR();
1089 			pc += 2;
1090 			R16( data, 4, 0x4B ) = READ_WORD( addr );
1091 			goto loop;
1092 		}
1093 
1094 		case 0x7B:{// LD SP,(ADDR)
1095 			uint16_t addr = GET_ADDR();
1096 			pc += 2;
1097 			sp = READ_WORD( addr );
1098 			goto loop;
1099 		}
1100 
1101 		case 0x67:{// RRD
1102 			uint8_t temp = READ( rp.hl );
1103 			WRITE( rp.hl, (rg.a << 4) | (temp >> 4) );
1104 			temp = (rg.a & 0xF0) | (temp & 0x0F);
1105 			flags = (flags & C01) | SZ28P( temp );
1106 			rg.a = temp;
1107 			goto loop;
1108 		}
1109 
1110 		case 0x6F:{// RLD
1111 			uint8_t temp = READ( rp.hl );
1112 			WRITE( rp.hl, (temp << 4) | (rg.a & 0x0F) );
1113 			temp = (rg.a & 0xF0) | (temp >> 4);
1114 			flags = (flags & C01) | SZ28P( temp );
1115 			rg.a = temp;
1116 			goto loop;
1117 		}
1118 
1119 		CASE8( 44, 4C, 54, 5C, 64, 6C, 74, 7C ): // NEG
1120 			opcode = 0x10; // flag to do SBC instead of ADC
1121 			flags &= ~C01;
1122 			data = rg.a;
1123 			rg.a = 0;
1124 			goto adc_data;
1125 
1126 		{
1127 			int inc;
1128 		case 0xA9: // CPD
1129 		case 0xB9: // CPDR
1130 			inc = -1;
1131 			if ( 0 )
1132 		case 0xA1: // CPI
1133 		case 0xB1: // CPIR
1134 				inc = +1;
1135 			uint16_t addr = rp.hl;
1136 			rp.hl = addr + inc;
1137 			int temp = READ( addr );
1138 
1139 			int result = rg.a - temp;
1140 			flags = (flags & C01) | N02 |
1141 					((((temp ^ rg.a) & H10) ^ result) & (S80 | H10));
1142 
1143 			if ( !(uint8_t) result ) flags |= Z40;
1144 			result -= (flags & H10) >> 4;
1145 			flags |= result & F08;
1146 			flags |= result << 4 & F20;
1147 			if ( !--rp.bc )
1148 				goto loop;
1149 
1150 			flags |= V04;
1151 			if ( flags & Z40 || data < 0xB0 )
1152 				goto loop;
1153 
1154 			pc -= 2;
1155 			s_time += 5;
1156 			goto loop;
1157 		}
1158 
1159 		{
1160 			int inc;
1161 		case 0xA8: // LDD
1162 		case 0xB8: // LDDR
1163 			inc = -1;
1164 			if ( 0 )
1165 		case 0xA0: // LDI
1166 		case 0xB0: // LDIR
1167 				inc = +1;
1168 			uint16_t addr = rp.hl;
1169 			rp.hl = addr + inc;
1170 			int temp = READ( addr );
1171 
1172 			addr = rp.de;
1173 			rp.de = addr + inc;
1174 			WRITE( addr, temp );
1175 
1176 			temp += rg.a;
1177 			flags = (flags & (S80 | Z40 | C01)) |
1178 					(temp & F08) | (temp << 4 & F20);
1179 			if ( !--rp.bc )
1180 				goto loop;
1181 
1182 			flags |= V04;
1183 			if ( data < 0xB0 )
1184 				goto loop;
1185 
1186 			pc -= 2;
1187 			s_time += 5;
1188 			goto loop;
1189 		}
1190 
1191 		{
1192 			int inc;
1193 		case 0xAB: // OUTD
1194 		case 0xBB: // OTDR
1195 			inc = -1;
1196 			if ( 0 )
1197 		case 0xA3: // OUTI
1198 		case 0xB3: // OTIR
1199 				inc = +1;
1200 			uint16_t addr = rp.hl;
1201 			rp.hl = addr + inc;
1202 			int temp = READ( addr );
1203 
1204 			int b = --rg.b;
1205 			flags = (temp >> 6 & N02) | SZ28( b );
1206 			if ( b && data >= 0xB0 )
1207 			{
1208 				pc -= 2;
1209 				s_time += 5;
1210 			}
1211 
1212 			OUT( rp.bc, temp );
1213 			goto loop;
1214 		}
1215 
1216 		{
1217 			int inc;
1218 		case 0xAA: // IND
1219 		case 0xBA: // INDR
1220 			inc = -1;
1221 			if ( 0 )
1222 		case 0xA2: // INI
1223 		case 0xB2: // INIR
1224 				inc = +1;
1225 
1226 			uint16_t addr = rp.hl;
1227 			rp.hl = addr + inc;
1228 
1229 			int temp = IN( rp.bc );
1230 
1231 			int b = --rg.b;
1232 			flags = (temp >> 6 & N02) | SZ28( b );
1233 			if ( b && data >= 0xB0 )
1234 			{
1235 				pc -= 2;
1236 				s_time += 5;
1237 			}
1238 
1239 			WRITE( addr, temp );
1240 			goto loop;
1241 		}
1242 
1243 		case 0x47: // LD I,A
1244 			r.i = rg.a;
1245 			goto loop;
1246 
1247 		case 0x4F: // LD R,A
1248 			SET_R( rg.a );
1249 			debug_printf( "LD R,A not supported\n" );
1250 			warning = true;
1251 			goto loop;
1252 
1253 		case 0x57: // LD A,I
1254 			rg.a = r.i;
1255 			goto ld_ai_common;
1256 
1257 		case 0x5F: // LD A,R
1258 			rg.a = GET_R();
1259 			debug_printf( "LD A,R not supported\n" );
1260 			warning = true;
1261 		ld_ai_common:
1262 			flags = (flags & C01) | SZ28( rg.a ) | (r.iff2 << 2 & V04);
1263 			goto loop;
1264 
1265 		CASE8( 45, 4D, 55, 5D, 65, 6D, 75, 7D ): // RETI/RETN
1266 			r.iff1 = r.iff2;
1267 			goto ret_taken;
1268 
1269 		case 0x46: case 0x4E: case 0x66: case 0x6E: // IM 0
1270 			r.im = 0;
1271 			goto loop;
1272 
1273 		case 0x56: case 0x76: // IM 1
1274 			r.im = 1;
1275 			goto loop;
1276 
1277 		case 0x5E: case 0x7E: // IM 2
1278 			r.im = 2;
1279 			goto loop;
1280 
1281 		default:
1282 			debug_printf( "Opcode $ED $%02X not supported\n", data );
1283 			warning = true;
1284 			goto loop;
1285 		}
1286 		assert( false );
1287 	}
1288 
1289 //////////////////////////////////////// DD/FD prefix
1290 	{
1291 	uint16_t ixy;
1292 	case 0xDD:
1293 		ixy = ix;
1294 		goto ix_prefix;
1295 	case 0xFD:
1296 		ixy = iy;
1297 	ix_prefix:
1298 		pc++;
1299 		unsigned data2 = READ_PROG( pc );
1300 		s_time += ed_dd_timing [data] & 0x0F;
1301 		switch ( data )
1302 		{
1303 	// TODO: more efficient way of avoid negative address
1304 	#define IXY_DISP( ixy, disp )   uint16_t ((ixy) + (disp))
1305 
1306 	#define SET_IXY( in ) if ( opcode == 0xDD ) ix = in; else iy = in;
1307 
1308 	// ADD/ADC/SUB/SBC
1309 
1310 		case 0x96: // SUB (IXY+disp)
1311 		case 0x86: // ADD (IXY+disp)
1312 			flags &= ~C01;
1313 		case 0x9E: // SBC (IXY+disp)
1314 		case 0x8E: // ADC (IXY+disp)
1315 			pc++;
1316 			opcode = data;
1317 			data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
1318 			goto adc_data;
1319 
1320 		case 0x94: // SUB HXY
1321 		case 0x84: // ADD HXY
1322 			flags &= ~C01;
1323 		case 0x9C: // SBC HXY
1324 		case 0x8C: // ADC HXY
1325 			opcode = data;
1326 			data = ixy >> 8;
1327 			goto adc_data;
1328 
1329 		case 0x95: // SUB LXY
1330 		case 0x85: // ADD LXY
1331 			flags &= ~C01;
1332 		case 0x9D: // SBC LXY
1333 		case 0x8D: // ADC LXY
1334 			opcode = data;
1335 			data = (uint8_t) ixy;
1336 			goto adc_data;
1337 
1338 		{
1339 			unsigned temp;
1340 		case 0x39: // ADD IXY,SP
1341 			temp = sp;
1342 			goto add_ixy_data;
1343 
1344 		case 0x29: // ADD IXY,HL
1345 			temp = ixy;
1346 			goto add_ixy_data;
1347 
1348 		case 0x09: // ADD IXY,BC
1349 		case 0x19: // ADD IXY,DE
1350 			temp = R16( data, 4, 0x09 );
1351 		add_ixy_data: {
1352 			blargg_ulong sum = ixy + temp;
1353 			temp ^= ixy;
1354 			ixy = (uint16_t) sum;
1355 			flags = (flags & (S80 | Z40 | V04)) |
1356 					(sum >> 16) |
1357 					(sum >> 8 & (F20 | F08)) |
1358 					((temp ^ sum) >> 8 & H10);
1359 			goto set_ixy;
1360 		}
1361 		}
1362 
1363 	// AND
1364 		case 0xA6: // AND (IXY+disp)
1365 			pc++;
1366 			data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
1367 			goto and_data;
1368 
1369 		case 0xA4: // AND HXY
1370 			data = ixy >> 8;
1371 			goto and_data;
1372 
1373 		case 0xA5: // AND LXY
1374 			data = (uint8_t) ixy;
1375 			goto and_data;
1376 
1377 	// OR
1378 		case 0xB6: // OR (IXY+disp)
1379 			pc++;
1380 			data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
1381 			goto or_data;
1382 
1383 		case 0xB4: // OR HXY
1384 			data = ixy >> 8;
1385 			goto or_data;
1386 
1387 		case 0xB5: // OR LXY
1388 			data = (uint8_t) ixy;
1389 			goto or_data;
1390 
1391 	// XOR
1392 		case 0xAE: // XOR (IXY+disp)
1393 			pc++;
1394 			data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
1395 			goto xor_data;
1396 
1397 		case 0xAC: // XOR HXY
1398 			data = ixy >> 8;
1399 			goto xor_data;
1400 
1401 		case 0xAD: // XOR LXY
1402 			data = (uint8_t) ixy;
1403 			goto xor_data;
1404 
1405 	// CP
1406 		case 0xBE: // CP (IXY+disp)
1407 			pc++;
1408 			data = READ( IXY_DISP( ixy, (int8_t) data2 )  );
1409 			goto cp_data;
1410 
1411 		case 0xBC: // CP HXY
1412 			data = ixy >> 8;
1413 			goto cp_data;
1414 
1415 		case 0xBD: // CP LXY
1416 			data = (uint8_t) ixy;
1417 			goto cp_data;
1418 
1419 	// LD
1420 		CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (IXY+disp),r
1421 			data = R8( data, 0x70 );
1422 			if ( 0 )
1423 		case 0x36: // LD (IXY+disp),imm
1424 				pc++, data = READ_PROG( pc );
1425 			pc++;
1426 			WRITE( IXY_DISP( ixy, (int8_t) data2 ), data );
1427 			goto loop;
1428 
1429 		CASE5( 44, 4C, 54, 5C, 7C ): // LD r,HXY
1430 			R8( data >> 3, 8 ) = ixy >> 8;
1431 			goto loop;
1432 
1433 		case 0x64: // LD HXY,HXY
1434 		case 0x6D: // LD LXY,LXY
1435 			goto loop;
1436 
1437 		CASE5( 45, 4D, 55, 5D, 7D ): // LD r,LXY
1438 			R8( data >> 3, 8 ) = ixy;
1439 			goto loop;
1440 
1441 		CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(IXY+disp)
1442 			pc++;
1443 			R8( data >> 3, 8 ) = READ( IXY_DISP( ixy, (int8_t) data2 ) );
1444 			goto loop;
1445 
1446 		case 0x26: // LD HXY,imm
1447 			pc++;
1448 			goto ld_hxy_data;
1449 
1450 		case 0x65: // LD HXY,LXY
1451 			data2 = (uint8_t) ixy;
1452 			goto ld_hxy_data;
1453 
1454 		CASE5( 60, 61, 62, 63, 67 ): // LD HXY,r
1455 			data2 = R8( data, 0x60 );
1456 		ld_hxy_data:
1457 			ixy = (uint8_t) ixy | (data2 << 8);
1458 			goto set_ixy;
1459 
1460 		case 0x2E: // LD LXY,imm
1461 			pc++;
1462 			goto ld_lxy_data;
1463 
1464 		case 0x6C: // LD LXY,HXY
1465 			data2 = ixy >> 8;
1466 			goto ld_lxy_data;
1467 
1468 		CASE5( 68, 69, 6A, 6B, 6F ): // LD LXY,r
1469 			data2 = R8( data, 0x68 );
1470 		ld_lxy_data:
1471 			ixy = (ixy & 0xFF00) | data2;
1472 		set_ixy:
1473 			if ( opcode == 0xDD )
1474 			{
1475 				ix = ixy;
1476 				goto loop;
1477 			}
1478 			iy = ixy;
1479 			goto loop;
1480 
1481 		case 0xF9: // LD SP,IXY
1482 			sp = ixy;
1483 			goto loop;
1484 
1485 		case 0x22:{// LD (ADDR),IXY
1486 			uint16_t addr = GET_ADDR();
1487 			pc += 2;
1488 			WRITE_WORD( addr, ixy );
1489 			goto loop;
1490 		}
1491 
1492 		case 0x21: // LD IXY,imm
1493 			ixy = GET_ADDR();
1494 			pc += 2;
1495 			goto set_ixy;
1496 
1497 		case 0x2A:{// LD IXY,(addr)
1498 			uint16_t addr = GET_ADDR();
1499 			ixy = READ_WORD( addr );
1500 			pc += 2;
1501 			goto set_ixy;
1502 		}
1503 
1504 	// DD/FD CB prefix
1505 		case 0xCB: {
1506 			data = IXY_DISP( ixy, (int8_t) data2 );
1507 			pc++;
1508 			data2 = READ_PROG( pc );
1509 			pc++;
1510 			switch ( data2 )
1511 			{
1512 			case 0x06: goto rlc_data_addr; // RLC (IXY)
1513 			case 0x16: goto rl_data_addr;  // RL (IXY)
1514 			case 0x26: goto sla_data_addr; // SLA (IXY)
1515 			case 0x36: goto sll_data_addr; // SLL (IXY)
1516 			case 0x0E: goto rrc_data_addr; // RRC (IXY)
1517 			case 0x1E: goto rr_data_addr;  // RR (IXY)
1518 			case 0x2E: goto sra_data_addr; // SRA (IXY)
1519 			case 0x3E: goto srl_data_addr; // SRL (IXY)
1520 
1521 			CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ):{// BIT b,(IXY+disp)
1522 				uint8_t temp = READ( data );
1523 				int masked = temp & 1 << (data2 >> 3 & 7);
1524 				flags = (flags & C01) | H10 |
1525 						(masked & S80) |
1526 						((masked - 1) >> 8 & (Z40 | P04));
1527 				goto loop;
1528 			}
1529 
1530 			CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(IXY+disp)
1531 			CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(IXY+disp)
1532 				int temp = READ( data );
1533 				int bit = 1 << (data2 >> 3 & 7);
1534 				temp |= bit; // SET
1535 				if ( !(data2 & 0x40) )
1536 					temp ^= bit; // RES
1537 				WRITE( data, temp );
1538 				goto loop;
1539 			}
1540 
1541 			default:
1542 				debug_printf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
1543 				warning = true;
1544 				goto loop;
1545 			}
1546 			assert( false );
1547 		}
1548 
1549 	// INC/DEC
1550 		case 0x23: // INC IXY
1551 			ixy = uint16_t (ixy + 1);
1552 			goto set_ixy;
1553 
1554 		case 0x2B: // DEC IXY
1555 			ixy = uint16_t (ixy - 1);
1556 			goto set_ixy;
1557 
1558 		case 0x34: // INC (IXY+disp)
1559 			ixy = IXY_DISP( ixy, (int8_t) data2 );
1560 			pc++;
1561 			data = READ( ixy ) + 1;
1562 			WRITE( ixy, data );
1563 			goto inc_set_flags;
1564 
1565 		case 0x35: // DEC (IXY+disp)
1566 			ixy = IXY_DISP( ixy, (int8_t) data2 );
1567 			pc++;
1568 			data = READ( ixy ) - 1;
1569 			WRITE( ixy, data );
1570 			goto dec_set_flags;
1571 
1572 		case 0x24: // INC HXY
1573 			ixy = uint16_t (ixy + 0x100);
1574 			data = ixy >> 8;
1575 			goto inc_xy_common;
1576 
1577 		case 0x2C: // INC LXY
1578 			data = uint8_t (ixy + 1);
1579 			ixy = (ixy & 0xFF00) | data;
1580 		inc_xy_common:
1581 			if ( opcode == 0xDD )
1582 			{
1583 				ix = ixy;
1584 				goto inc_set_flags;
1585 			}
1586 			iy = ixy;
1587 			goto inc_set_flags;
1588 
1589 		case 0x25: // DEC HXY
1590 			ixy = uint16_t (ixy - 0x100);
1591 			data = ixy >> 8;
1592 			goto dec_xy_common;
1593 
1594 		case 0x2D: // DEC LXY
1595 			data = uint8_t (ixy - 1);
1596 			ixy = (ixy & 0xFF00) | data;
1597 		dec_xy_common:
1598 			if ( opcode == 0xDD )
1599 			{
1600 				ix = ixy;
1601 				goto dec_set_flags;
1602 			}
1603 			iy = ixy;
1604 			goto dec_set_flags;
1605 
1606 	// PUSH/POP
1607 		case 0xE5: // PUSH IXY
1608 			data = ixy;
1609 			goto push_data;
1610 
1611 		case 0xE1:{// POP IXY
1612 			ixy = READ_WORD( sp );
1613 			sp = uint16_t (sp + 2);
1614 			goto set_ixy;
1615 		}
1616 
1617 	// Misc
1618 
1619 		case 0xE9: // JP (IXY)
1620 			pc = ixy;
1621 			goto loop;
1622 
1623 		case 0xE3:{// EX (SP),IXY
1624 			uint16_t temp = READ_WORD( sp );
1625 			WRITE_WORD( sp, ixy );
1626 			ixy = temp;
1627 			goto set_ixy;
1628 		}
1629 
1630 		default:
1631 			debug_printf( "Unnecessary DD/FD prefix encountered\n" );
1632 			warning = true;
1633 			pc--;
1634 			goto loop;
1635 		}
1636 		assert( false );
1637 	}
1638 
1639 	}
1640 	debug_printf( "Unhandled main opcode: $%02X\n", opcode );
1641 	assert( false );
1642 
1643 halt:
1644 	s_time &= 3; // increment by multiple of 4
1645 out_of_time:
1646 	pc--;
1647 
1648 	s.time   = s_time;
1649 	rg.flags = flags;
1650 	r.ix     = ix;
1651 	r.iy     = iy;
1652 	r.sp     = sp;
1653 	r.pc     = pc;
1654 	this->r.b = rg;
1655 	this->state_ = s;
1656 	this->state = &this->state_;
1657 
1658 	return warning;
1659 }
1660