cpu.c
  1  #include "defs.h"
  2  #include "regs.h"
  3  #include "hw.h"
  4  #include "cpu.h"
  5  #include "mem.h"
  6  #include "cpuregs.h"
  7  #include "cpucore.h"
  8  
  9  #ifdef USE_ASM
 10  #include "asm.h"
 11  #endif
 12  
 13  
 14  struct cpu cpu;
 15  
 16  
 17  
 18  
 19  #define ZFLAG(n) ( (n) ? 0 : FZ )
 20  
 21  
 22  #define PUSH(w) ( (SP -= 2), (writew(xSP, (w))) )
 23  #define POP(w) ( ((w) = readw(xSP)), (SP += 2) )
 24  
 25  
 26  //#define FETCH_OLD ( mbc.rmap[PC>>12] \
 27  //? mbc.rmap[PC>>12][PC++] \
 28  //: mem_read(PC++) )
 29  
 30  #define FETCH (readb(PC++))
 31  
 32  
 33  #define INC(r) { ((r)++); \
 34  F = (F & (FL|FC)) | incflag_table[(r)]; }
 35  
 36  #define DEC(r) { ((r)--); \
 37  F = (F & (FL|FC)) | decflag_table[(r)]; }
 38  
 39  #define INCW(r) ( (r)++ )
 40  
 41  #define DECW(r) ( (r)-- )
 42  
 43  #define ADD(n) { \
 44  W(acc) = (un16)A + (un16)(n); \
 45  F = (ZFLAG(LB(acc))) \
 46  | (FH & ((A ^ (n) ^ LB(acc)) << 1)) \
 47  | (HB(acc) << 4); \
 48  A = LB(acc); }
 49  
 50  #define ADC(n) { \
 51  W(acc) = (un16)A + (un16)(n) + (un16)((F&FC)>>4); \
 52  F = (ZFLAG(LB(acc))) \
 53  | (FH & ((A ^ (n) ^ LB(acc)) << 1)) \
 54  | (HB(acc) << 4); \
 55  A = LB(acc); }
 56  
 57  #define ADDW(n) { \
 58  DW(acc) = (un32)HL + (un32)(n); \
 59  F = (F & (FZ)) \
 60  | (FH & ((H ^ ((n)>>8) ^ HB(acc)) << 1)) \
 61  | (acc.b[HI][LO] << 4); \
 62  HL = W(acc); }
 63  
 64  #define ADDSP(n) { \
 65  DW(acc) = (un32)SP + (un32)(n8)(n); \
 66  F = (FH & (((SP>>8) ^ ((n)>>8) ^ HB(acc)) << 1)) \
 67  | (acc.b[HI][LO] << 4); \
 68  SP = W(acc); }
 69  
 70  #define LDHLSP(n) { \
 71  DW(acc) = (un32)SP + (un32)(n8)(n); \
 72  F = (FH & (((SP>>8) ^ ((n)>>8) ^ HB(acc)) << 1)) \
 73  | (acc.b[HI][LO] << 4); \
 74  HL = W(acc); }
 75  
 76  #define CP(n) { \
 77  W(acc) = (un16)A - (un16)(n); \
 78  F = FN \
 79  | (ZFLAG(LB(acc))) \
 80  | (FH & ((A ^ (n) ^ LB(acc)) << 1)) \
 81  | ((un8)(-(n8)HB(acc)) << 4); }
 82  
 83  #define SUB(n) { CP((n)); A = LB(acc); }
 84  
 85  #define SBC(n) { \
 86  W(acc) = (un16)A - (un16)(n) - (un16)((F&FC)>>4); \
 87  F = FN \
 88  | (ZFLAG((n8)LB(acc))) \
 89  | (FH & ((A ^ (n) ^ LB(acc)) << 1)) \
 90  | ((un8)(-(n8)HB(acc)) << 4); \
 91  A = LB(acc); }
 92  
 93  #define AND(n) { A &= (n); \
 94  F = ZFLAG(A) | FH; }
 95  
 96  #define XOR(n) { A ^= (n); \
 97  F = ZFLAG(A); }
 98  
 99  #define OR(n) { A |= (n); \
100  F = ZFLAG(A); }
101  
102  #define RLCA(r) { (r) = ((r)>>7) | ((r)<<1); \
103  F = (((r)&0x01)<<4); }
104  
105  #define RRCA(r) { (r) = ((r)<<7) | ((r)>>1); \
106  F = (((r)&0x80)>>3); }
107  
108  #define RLA(r) { \
109  LB(acc) = (((r)&0x80)>>3); \
110  (r) = ((r)<<1) | ((F&FC)>>4); \
111  F = LB(acc); }
112  
113  #define RRA(r) { \
114  LB(acc) = (((r)&0x01)<<4); \
115  (r) = ((r)>>1) | ((F&FC)<<3); \
116  F = LB(acc); }
117  
118  #define RLC(r) { RLCA(r); F |= ZFLAG(r); }
119  #define RRC(r) { RRCA(r); F |= ZFLAG(r); }
120  #define RL(r) { RLA(r); F |= ZFLAG(r); }
121  #define RR(r) { RRA(r); F |= ZFLAG(r); }
122  
123  #define SLA(r) { \
124  LB(acc) = (((r)&0x80)>>3); \
125  (r) <<= 1; \
126  F = ZFLAG((r)) | LB(acc); }
127  
128  #define SRA(r) { \
129  LB(acc) = (((r)&0x01)<<4); \
130  (r) = (un8)(((n8)(r))>>1); \
131  F = ZFLAG((r)) | LB(acc); }
132  
133  #define SRL(r) { \
134  LB(acc) = (((r)&0x01)<<4); \
135  (r) >>= 1; \
136  F = ZFLAG((r)) | LB(acc); }
137  
138  #define CPL(r) { \
139  (r) = ~(r); \
140  F |= (FH|FN); }
141  
142  #define SCF { F = (F & (FZ)) | FC; }
143  
144  #define CCF { F = (F & (FZ|FC)) ^ FC; }
145  
146  #define DAA { \
147  A += (LB(acc) = daa_table[((((int)F)&0x70)<<4) | A]); \
148  F = (F & (FN)) | ZFLAG(A) | daa_carry_table[LB(acc)>>2]; }
149  
150  #define SWAP(r) { \
151  (r) = swap_table[(r)]; \
152  F = ZFLAG((r)); }
153  
154  #define BIT(n,r) { F = (F & FC) | ZFLAG(((r) & (1 << (n)))) | FH; }
155  #define RES(n,r) { (r) &= ~(1 << (n)); }
156  #define SET(n,r) { (r) |= (1 << (n)); }
157  
158  #define CB_REG_CASES(r, n) \
159  case 0x00|(n): RLC(r); break; \
160  case 0x08|(n): RRC(r); break; \
161  case 0x10|(n): RL(r); break; \
162  case 0x18|(n): RR(r); break; \
163  case 0x20|(n): SLA(r); break; \
164  case 0x28|(n): SRA(r); break; \
165  case 0x30|(n): SWAP(r); break; \
166  case 0x38|(n): SRL(r); break; \
167  case 0x40|(n): BIT(0, r); break; \
168  case 0x48|(n): BIT(1, r); break; \
169  case 0x50|(n): BIT(2, r); break; \
170  case 0x58|(n): BIT(3, r); break; \
171  case 0x60|(n): BIT(4, r); break; \
172  case 0x68|(n): BIT(5, r); break; \
173  case 0x70|(n): BIT(6, r); break; \
174  case 0x78|(n): BIT(7, r); break; \
175  case 0x80|(n): RES(0, r); break; \
176  case 0x88|(n): RES(1, r); break; \
177  case 0x90|(n): RES(2, r); break; \
178  case 0x98|(n): RES(3, r); break; \
179  case 0xA0|(n): RES(4, r); break; \
180  case 0xA8|(n): RES(5, r); break; \
181  case 0xB0|(n): RES(6, r); break; \
182  case 0xB8|(n): RES(7, r); break; \
183  case 0xC0|(n): SET(0, r); break; \
184  case 0xC8|(n): SET(1, r); break; \
185  case 0xD0|(n): SET(2, r); break; \
186  case 0xD8|(n): SET(3, r); break; \
187  case 0xE0|(n): SET(4, r); break; \
188  case 0xE8|(n): SET(5, r); break; \
189  case 0xF0|(n): SET(6, r); break; \
190  case 0xF8|(n): SET(7, r); break;
191  
192  
193  #define ALU_CASES(base, imm, op, label) \
194  case (imm): b = FETCH; goto label; \
195  case (base): b = B; goto label; \
196  case (base)+1: b = C; goto label; \
197  case (base)+2: b = D; goto label; \
198  case (base)+3: b = E; goto label; \
199  case (base)+4: b = H; goto label; \
200  case (base)+5: b = L; goto label; \
201  case (base)+6: b = readb(HL); goto label; \
202  case (base)+7: b = A; \
203  label: op(b); break;
204  
205  
206  
207  
208  
209  
210  
211  
212  #define JR ( PC += 1+(n8)readb(PC) )
213  #define JP ( PC = readw(PC) )
214  
215  #define CALL ( PUSH(PC+2), JP )
216  
217  #define NOJR ( clen--, PC++ )
218  #define NOJP ( clen--, PC+=2 )
219  #define NOCALL ( clen-=3, PC+=2 )
220  #define NORET ( clen-=3 )
221  
222  #define RST(n) { PUSH(PC); PC = (n); }
223  
224  #define RET ( POP(PC) )
225  
226  #define EI ( IMA = 1 )
227  #define DI ( cpu.halt = IMA = IME = 0 )
228  
229  
230  
231  #define PRE_INT ( DI, PUSH(PC) )
232  #define THROW_INT(n) ( (IF &= ~(1<<(n))), (PC = 0x40+((n)<<3)) )
233  
234  
235  
236  
237  void cpu_reset()
238  {
239  	cpu.speed = 0;
240  	cpu.halt = 0;
241  	cpu.div = 0;
242  	cpu.tim = 0;
243  	cpu.lcdc = 40;
244  
245  	IME = 0;
246  	IMA = 0;
247  	
248  	PC = 0x0100;
249  	SP = 0xFFFE;
250  	AF = 0x01B0;
251  	BC = 0x0013;
252  	DE = 0x00D8;
253  	HL = 0x014D;
254  	
255  	if (hw.cgb) A = 0x11;
256  	if (hw.gba) B = 0x01;
257  }
258  
259  
260  void div_advance(int cnt)
261  {
262  	cpu.div += (cnt<<1);
263  	if (cpu.div >= 256)
264  	{
265  		R_DIV += (cpu.div >> 8);
266  		cpu.div &= 0xff;
267  	}
268  }
269  
270  void timer_advance(int cnt)
271  {
272  	int unit, tima;
273  	
274  	if (!(R_TAC & 0x04)) return;
275  
276  	unit = ((-R_TAC) & 3) << 1;
277  	cpu.tim += (cnt<<unit);
278  
279  	if (cpu.tim >= 512)
280  	{
281  		tima = R_TIMA + (cpu.tim >> 9);
282  		cpu.tim &= 0x1ff;
283  		if (tima >= 256)
284  		{
285  			hw_interrupt(IF_TIMER, IF_TIMER);
286  			hw_interrupt(0, IF_TIMER);
287  		}
288  		while (tima >= 256)
289  			tima = tima - 256 + R_TMA;
290  		R_TIMA = tima;
291  	}
292  }
293  
294  void lcdc_advance(int cnt)
295  {
296  	cpu.lcdc -= cnt;
297  	if (cpu.lcdc <= 0) lcdc_trans();
298  }
299  
300  void sound_advance(int cnt)
301  {
302  	cpu.snd += cnt;
303  }
304  
305  void cpu_timers(int cnt)
306  {
307  	div_advance(cnt << cpu.speed);
308  	timer_advance(cnt << cpu.speed);
309  	lcdc_advance(cnt);
310         sound_advance(cnt);
311  }
312  
313  int cpu_idle(int max)
314  {
315  	int cnt, unit;
316  
317  	if (!(cpu.halt && IME)) return 0;
318  	if (R_IF & R_IE)
319  	{
320  		cpu.halt = 0;
321  		return 0;
322  	}
323  
324  	/* Make sure we don't miss lcdc status events! */
325  	if ((R_IE & (IF_VBLANK | IF_STAT)) && (max > cpu.lcdc))
326  		max = cpu.lcdc;
327  	
328  	/* If timer interrupt cannot happen, this is very simple! */
329  	if (!((R_IE & IF_TIMER) && (R_TAC & 0x04)))
330  	{
331  		cpu_timers(max);
332  		return max;
333  	}
334  
335  	/* Figure out when the next timer interrupt will happen */
336  	unit = ((-R_TAC) & 3) << 1;
337  	cnt = (511 - cpu.tim + (1<<unit)) >> unit;
338  	cnt += (255 - R_TIMA) << (9 - unit);
339  
340  	if (max < cnt)
341  		cnt = max;
342  	
343  	cpu_timers(cnt);
344  	return cnt;
345  }
346  
347  #ifndef ASM_CPU_EMULATE
348  
349  #ifdef DEBUG	
350  extern int debug_trace;
351  #endif
352  
353  int cpu_emulate(int cycles)
354  {
355  	int i;
356  	byte op, cbop;
357  	int clen;
358  	static union reg acc;
359  	static byte b;
360  	static word w;
361  
362  
363  	i = cycles;
364  next:
365  	if ((clen = cpu_idle(i)))
366  	{
367  		i -= clen;
368  		if (i > 0) goto next;
369  		return cycles-i;
370  	}
371  
372  	if (IME && (IF & IE))
373  	{
374  		PRE_INT;
375  		switch ((byte)(IF & IE))
376  		{
377  		case 0x01: case 0x03: case 0x05: case 0x07:
378  		case 0x09: case 0x0B: case 0x0D: case 0x0F:
379  		case 0x11: case 0x13: case 0x15: case 0x17:
380  		case 0x19: case 0x1B: case 0x1D: case 0x1F:
381  			THROW_INT(0); break;
382  		case 0x02: case 0x06: case 0x0A: case 0x0E:
383  		case 0x12: case 0x16: case 0x1A: case 0x1E:
384  			THROW_INT(1); break;
385  		case 0x04: case 0x0C: case 0x14: case 0x1C:
386  			THROW_INT(2); break;
387  		case 0x08: case 0x18:
388  			THROW_INT(3); break;
389  		case 0x10:
390  			THROW_INT(4); break;
391  		}
392  	}
393  	IME = IMA;
394  #ifdef DEBUG	
395  	if (debug_trace) debug_disassemble(PC, 1);
396  #endif	
397  	op = FETCH;
398  	clen = cycles_table[op];
399  
400  	switch(op)
401  	{
402  	case 0x00: /* NOP */
403  	case 0x40: /* LD B,B */
404  	case 0x49: /* LD C,C */
405  	case 0x52: /* LD D,D */
406  	case 0x5B: /* LD E,E */
407  	case 0x64: /* LD H,H */
408  	case 0x6D: /* LD L,L */
409  	case 0x7F: /* LD A,A */
410  		break;
411  			
412  	case 0x41: /* LD B,C */
413  		B = C; break;
414  	case 0x42: /* LD B,D */
415  		B = D; break;
416  	case 0x43: /* LD B,E */
417  		B = E; break;
418  	case 0x44: /* LD B,H */
419  		B = H; break;
420  	case 0x45: /* LD B,L */
421  		B = L; break;
422  	case 0x46: /* LD B,(HL) */
423  		B = readb(xHL); break;
424  	case 0x47: /* LD B,A */
425  		B = A; break;
426  
427  	case 0x48: /* LD C,B */
428  		C = B; break;
429  	case 0x4A: /* LD C,D */
430  		C = D; break;
431  	case 0x4B: /* LD C,E */
432  		C = E; break;
433  	case 0x4C: /* LD C,H */
434  		C = H; break;
435  	case 0x4D: /* LD C,L */
436  		C = L; break;
437  	case 0x4E: /* LD C,(HL) */
438  		C = readb(xHL); break;
439  	case 0x4F: /* LD C,A */
440  		C = A; break;
441  
442  	case 0x50: /* LD D,B */
443  		D = B; break;
444  	case 0x51: /* LD D,C */
445  		D = C; break;
446  	case 0x53: /* LD D,E */
447  		D = E; break;
448  	case 0x54: /* LD D,H */
449  		D = H; break;
450  	case 0x55: /* LD D,L */
451  		D = L; break;
452  	case 0x56: /* LD D,(HL) */
453  		D = readb(xHL); break;
454  	case 0x57: /* LD D,A */
455  		D = A; break;
456  
457  	case 0x58: /* LD E,B */
458  		E = B; break;
459  	case 0x59: /* LD E,C */
460  		E = C; break;
461  	case 0x5A: /* LD E,D */
462  		E = D; break;
463  	case 0x5C: /* LD E,H */
464  		E = H; break;
465  	case 0x5D: /* LD E,L */
466  		E = L; break;
467  	case 0x5E: /* LD E,(HL) */
468  		E = readb(xHL); break;
469  	case 0x5F: /* LD E,A */
470  		E = A; break;
471  
472  	case 0x60: /* LD H,B */
473  		H = B; break;
474  	case 0x61: /* LD H,C */
475  		H = C; break;
476  	case 0x62: /* LD H,D */
477  		H = D; break;
478  	case 0x63: /* LD H,E */
479  		H = E; break;
480  	case 0x65: /* LD H,L */
481  		H = L; break;
482  	case 0x66: /* LD H,(HL) */
483  		H = readb(xHL); break;
484  	case 0x67: /* LD H,A */
485  		H = A; break;
486  			
487  	case 0x68: /* LD L,B */
488  		L = B; break;
489  	case 0x69: /* LD L,C */
490  		L = C; break;
491  	case 0x6A: /* LD L,D */
492  		L = D; break;
493  	case 0x6B: /* LD L,E */
494  		L = E; break;
495  	case 0x6C: /* LD L,H */
496  		L = H; break;
497  	case 0x6E: /* LD L,(HL) */
498  		L = readb(xHL); break;
499  	case 0x6F: /* LD L,A */
500  		L = A; break;
501  			
502  	case 0x70: /* LD (HL),B */
503  		b = B; goto __LD_HL;
504  	case 0x71: /* LD (HL),C */
505  		b = C; goto __LD_HL;
506  	case 0x72: /* LD (HL),D */
507  		b = D; goto __LD_HL;
508  	case 0x73: /* LD (HL),E */
509  		b = E; goto __LD_HL;
510  	case 0x74: /* LD (HL),H */
511  		b = H; goto __LD_HL;
512  	case 0x75: /* LD (HL),L */
513  		b = L; goto __LD_HL;
514  	case 0x77: /* LD (HL),A */
515  		b = A;
516  	__LD_HL:
517  		writeb(xHL,b);
518  		break;
519  			
520  	case 0x78: /* LD A,B */
521  		A = B; break;
522  	case 0x79: /* LD A,C */
523  		A = C; break;
524  	case 0x7A: /* LD A,D */
525  		A = D; break;
526  	case 0x7B: /* LD A,E */
527  		A = E; break;
528  	case 0x7C: /* LD A,H */
529  		A = H; break;
530  	case 0x7D: /* LD A,L */
531  		A = L; break;
532  	case 0x7E: /* LD A,(HL) */
533  		A = readb(xHL); break;
534  
535  	case 0x01: /* LD BC,imm */
536  		BC = readw(xPC); PC += 2; break;
537  	case 0x11: /* LD DE,imm */
538  		DE = readw(xPC); PC += 2; break;
539  	case 0x21: /* LD HL,imm */
540  		HL = readw(xPC); PC += 2; break;
541  	case 0x31: /* LD SP,imm */
542  		SP = readw(xPC); PC += 2; break;
543  
544  	case 0x02: /* LD (BC),A */
545  		writeb(xBC, A); break;
546  	case 0x0A: /* LD A,(BC) */
547  		A = readb(xBC); break;
548  	case 0x12: /* LD (DE),A */
549  		writeb(xDE, A); break;
550  	case 0x1A: /* LD A,(DE) */
551  		A = readb(xDE); break;
552  
553  	case 0x22: /* LDI (HL),A */
554  		writeb(xHL, A); HL++; break;
555  	case 0x2A: /* LDI A,(HL) */
556  		A = readb(xHL); HL++; break;
557  	case 0x32: /* LDD (HL),A */
558  		writeb(xHL, A); HL--; break;
559  	case 0x3A: /* LDD A,(HL) */
560  		A = readb(xHL); HL--; break;
561  
562  	case 0x06: /* LD B,imm */
563  		B = FETCH; break;
564  	case 0x0E: /* LD C,imm */
565  		C = FETCH; break;
566  	case 0x16: /* LD D,imm */
567  		D = FETCH; break;
568  	case 0x1E: /* LD E,imm */
569  		E = FETCH; break;
570  	case 0x26: /* LD H,imm */
571  		H = FETCH; break;
572  	case 0x2E: /* LD L,imm */
573  		L = FETCH; break;
574  	case 0x36: /* LD (HL),imm */
575  		b = FETCH; writeb(xHL, b); break;
576  	case 0x3E: /* LD A,imm */
577  		A = FETCH; break;
578  
579  	case 0x08: /* LD (imm),SP */
580  		writew(readw(xPC), SP); PC += 2; break;
581  	case 0xEA: /* LD (imm),A */
582  		writeb(readw(xPC), A); PC += 2; break;
583  
584  	case 0xE0: /* LDH (imm),A */
585  		writehi(FETCH, A); break;
586  	case 0xE2: /* LDH (C),A */
587  		writehi(C, A); break;
588  	case 0xF0: /* LDH A,(imm) */
589  		A = readhi(FETCH); break;
590  	case 0xF2: /* LDH A,(C) (undocumented) */
591  		A = readhi(C); break;
592  			
593  
594  	case 0xF8: /* LD HL,SP+imm */
595  		b = FETCH; LDHLSP(b); break;
596  	case 0xF9: /* LD SP,HL */
597  		SP = HL; break;
598  	case 0xFA: /* LD A,(imm) */
599  		A = readb(readw(xPC)); PC += 2; break;
600  
601  		ALU_CASES(0x80, 0xC6, ADD, __ADD)
602  		ALU_CASES(0x88, 0xCE, ADC, __ADC)
603  		ALU_CASES(0x90, 0xD6, SUB, __SUB)
604  		ALU_CASES(0x98, 0xDE, SBC, __SBC)
605  		ALU_CASES(0xA0, 0xE6, AND, __AND)
606  		ALU_CASES(0xA8, 0xEE, XOR, __XOR)
607  		ALU_CASES(0xB0, 0xF6, OR, __OR)
608  		ALU_CASES(0xB8, 0xFE, CP, __CP)
609  
610  	case 0x09: /* ADD HL,BC */
611  		w = BC; goto __ADDW;
612  	case 0x19: /* ADD HL,DE */
613  		w = DE; goto __ADDW;
614  	case 0x39: /* ADD HL,SP */
615  		w = SP; goto __ADDW;
616  	case 0x29: /* ADD HL,HL */
617  		w = HL;
618  	__ADDW:
619  		ADDW(w);
620  		break;
621  
622  	case 0x04: /* INC B */
623  		INC(B); break;
624  	case 0x0C: /* INC C */
625  		INC(C); break;
626  	case 0x14: /* INC D */
627  		INC(D); break;
628  	case 0x1C: /* INC E */
629  		INC(E); break;
630  	case 0x24: /* INC H */
631  		INC(H); break;
632  	case 0x2C: /* INC L */
633  		INC(L); break;
634  	case 0x34: /* INC (HL) */
635  		b = readb(xHL);
636  		INC(b);
637  		writeb(xHL, b);
638  		break;
639  	case 0x3C: /* INC A */
640  		INC(A); break;
641  			
642  	case 0x03: /* INC BC */
643  		INCW(BC); break;
644  	case 0x13: /* INC DE */
645  		INCW(DE); break;
646  	case 0x23: /* INC HL */
647  		INCW(HL); break;
648  	case 0x33: /* INC SP */
649  		INCW(SP); break;
650  			
651  	case 0x05: /* DEC B */
652  		DEC(B); break;
653  	case 0x0D: /* DEC C */
654  		DEC(C); break;
655  	case 0x15: /* DEC D */
656  		DEC(D); break;
657  	case 0x1D: /* DEC E */
658  		DEC(E); break;
659  	case 0x25: /* DEC H */
660  		DEC(H); break;
661  	case 0x2D: /* DEC L */
662  		DEC(L); break;
663  	case 0x35: /* DEC (HL) */
664  		b = readb(xHL);
665  		DEC(b);
666  		writeb(xHL, b);
667  		break;
668  	case 0x3D: /* DEC A */
669  		DEC(A); break;
670  
671  	case 0x0B: /* DEC BC */
672  		DECW(BC); break;
673  	case 0x1B: /* DEC DE */
674  		DECW(DE); break;
675  	case 0x2B: /* DEC HL */
676  		DECW(HL); break;
677  	case 0x3B: /* DEC SP */
678  		DECW(SP); break;
679  
680  	case 0x07: /* RLCA */
681  		RLCA(A); break;
682  	case 0x0F: /* RRCA */
683  		RRCA(A); break;
684  	case 0x17: /* RLA */
685  		RLA(A); break;
686  	case 0x1F: /* RRA */
687  		RRA(A); break;
688  
689  	case 0x27: /* DAA */
690  		DAA; break;
691  	case 0x2F: /* CPL */
692  		CPL(A); break;
693  
694  	case 0x18: /* JR */
695  	__JR:
696  		JR; break;
697  	case 0x20: /* JR NZ */
698  		if (!(F&FZ)) goto __JR; NOJR; break;
699  	case 0x28: /* JR Z */
700  		if (F&FZ) goto __JR; NOJR; break;
701  	case 0x30: /* JR NC */
702  		if (!(F&FC)) goto __JR; NOJR; break;
703  	case 0x38: /* JR C */
704  		if (F&FC) goto __JR; NOJR; break;
705  
706  	case 0xC3: /* JP */
707  	__JP:
708  		JP; break;
709  	case 0xC2: /* JP NZ */
710  		if (!(F&FZ)) goto __JP; NOJP; break;
711  	case 0xCA: /* JP Z */
712  		if (F&FZ) goto __JP; NOJP; break;
713  	case 0xD2: /* JP NC */
714  		if (!(F&FC)) goto __JP; NOJP; break;
715  	case 0xDA: /* JP C */
716  		if (F&FC) goto __JP; NOJP; break;
717  	case 0xE9: /* JP HL */
718  		PC = HL; break;
719  
720  	case 0xC9: /* RET */
721  	__RET:
722  		RET; break;
723  	case 0xC0: /* RET NZ */
724  		if (!(F&FZ)) goto __RET; NORET; break;
725  	case 0xC8: /* RET Z */
726  		if (F&FZ) goto __RET; NORET; break;
727  	case 0xD0: /* RET NC */
728  		if (!(F&FC)) goto __RET; NORET; break;
729  	case 0xD8: /* RET C */
730  		if (F&FC) goto __RET; NORET; break;
731  	case 0xD9: /* RETI */
732  		IME = IMA = 1; goto __RET;
733  
734  	case 0xCD: /* CALL */
735  	__CALL:
736  		CALL; break;
737  	case 0xC4: /* CALL NZ */
738  		if (!(F&FZ)) goto __CALL; NOCALL; break;
739  	case 0xCC: /* CALL Z */
740  		if (F&FZ) goto __CALL; NOCALL; break;
741  	case 0xD4: /* CALL NC */
742  		if (!(F&FC)) goto __CALL; NOCALL; break;
743  	case 0xDC: /* CALL C */
744  		if (F&FC) goto __CALL; NOCALL; break;
745  
746  	case 0xC7: /* RST 0 */
747  		b = 0x00; goto __RST;
748  	case 0xCF: /* RST 8 */
749  		b = 0x08; goto __RST;
750  	case 0xD7: /* RST 10 */
751  		b = 0x10; goto __RST;
752  	case 0xDF: /* RST 18 */
753  		b = 0x18; goto __RST;
754  	case 0xE7: /* RST 20 */
755  		b = 0x20; goto __RST;
756  	case 0xEF: /* RST 28 */
757  		b = 0x28; goto __RST;
758  	case 0xF7: /* RST 30 */
759  		b = 0x30; goto __RST;
760  	case 0xFF: /* RST 38 */
761  		b = 0x38;
762  	__RST:
763  		RST(b); break;
764  			
765  	case 0xC1: /* POP BC */
766  		POP(BC); break;
767  	case 0xC5: /* PUSH BC */
768  		PUSH(BC); break;
769  	case 0xD1: /* POP DE */
770  		POP(DE); break;
771  	case 0xD5: /* PUSH DE */
772  		PUSH(DE); break;
773  	case 0xE1: /* POP HL */
774  		POP(HL); break;
775  	case 0xE5: /* PUSH HL */
776  		PUSH(HL); break;
777  	case 0xF1: /* POP AF */
778  		POP(AF); break;
779  	case 0xF5: /* PUSH AF */
780  		PUSH(AF); break;
781  
782  	case 0xE8: /* ADD SP,imm */
783  		b = FETCH; ADDSP(b); break;
784  
785  	case 0xF3: /* DI */
786  		DI; break;
787  	case 0xFB: /* EI */
788  		EI; break;
789  
790  	case 0x37: /* SCF */
791  		SCF; break;
792  	case 0x3F: /* CCF */
793  		CCF; break;
794  
795  	case 0x10: /* STOP */
796  		PC++;
797  		if (R_KEY1 & 1)
798  		{
799  			cpu.speed = cpu.speed ^ 1;
800  			R_KEY1 = (R_KEY1 & 0x7E) | (cpu.speed << 7);
801  			break;
802  		}
803  		/* NOTE - we do not implement dmg STOP whatsoever */
804  		break;
805  			
806  	case 0x76: /* HALT */
807                cpu.halt = 1;
808  		break;
809  
810  	case 0xCB: /* CB prefix */
811  		cbop = FETCH;
812  		clen = cb_cycles_table[cbop];
813  		switch (cbop)
814  		{
815  			CB_REG_CASES(B, 0);
816  			CB_REG_CASES(C, 1);
817  			CB_REG_CASES(D, 2);
818  			CB_REG_CASES(E, 3);
819  			CB_REG_CASES(H, 4);
820  			CB_REG_CASES(L, 5);
821  			CB_REG_CASES(A, 7);
822  		default:
823  			b = readb(xHL);
824  			switch(cbop)
825  			{
826  				CB_REG_CASES(b, 6);
827  			}
828  			if ((cbop & 0xC0) != 0x40) /* exclude BIT */
829  				writeb(xHL, b);
830  			break;
831  		}
832  		break;
833  			
834  	default:
835  		die(
836  			"invalid opcode 0x%02X at address 0x%04X, rombank = %d\n",
837  			op, (PC-1) & 0xffff, mbc.rombank);
838  		break;
839  	}
840  
841  	clen <<= 1;
842  	div_advance(clen);
843  	timer_advance(clen);
844  	clen >>= cpu.speed;
845  	lcdc_advance(clen);
846      sound_advance(clen);
847  
848  	i -= clen;
849  	if (i > 0) goto next;
850  	return cycles-i;
851  }
852  
853  #endif /* ASM_CPU_EMULATE */
854  
855  
856  #ifndef ASM_CPU_STEP
857  
858  int cpu_step(int max)
859  {
860  	int cnt;
861  	if ((cnt = cpu_idle(max))) return cnt;
862  	return cpu_emulate(1);
863  }
864  
865  #endif /* ASM_CPU_STEP */
866  
867  
868  
869  
870  
871  
872  
873  
874  
875  
876  
877