void CPU::process()

in cores/gb/libgambatte/src/cpu.cpp [489:1994]


void CPU::process(unsigned long const cycles) {
	mem_.setEndtime(cycleCounter_, cycles);
	mem_.updateInput();

	unsigned char a = a_;
	unsigned long cycleCounter = cycleCounter_;

	while (mem_.isActive()) {
		unsigned short pc = pc_;

#ifdef HAVE_NETWORK
		mem_.checkSerial(cycleCounter);
#endif

		if (mem_.halted()) {
			if (cycleCounter < mem_.nextEventTime()) {
				unsigned long cycles = mem_.nextEventTime() - cycleCounter;
				cycleCounter += cycles + (-cycles & 3);
			}
		} else while (cycleCounter < mem_.nextEventTime()) {
			unsigned char opcode;

			PC_READ(opcode);

			if (skip_) {
				pc = (pc - 1) & 0xFFFF;
				skip_ = false;
			}

			switch (opcode) {
			case 0x00:
				break;
			case 0x01:
				ld_rr_nn(b, c);
				break;
			case 0x02:
				WRITE(bc(), a);
				break;
			case 0x03:
				inc_rr(b, c);
				break;
			case 0x04:
				inc_r(b);
				break;
			case 0x05:
				dec_r(b); 
				break;
			case 0x06:
				PC_READ(b);
				break;

				// rlca (4 cycles):
				// Rotate 8-bit register A left, store old bit7 in CF. Reset SF, HCF, ZF:
			case 0x07:
				cf = a << 1;
				a = (cf | cf >> 8) & 0xFF;
				hf2 = 0;
				zf = 1;
				break;

				// ld (nn),SP (20 cycles):
				// Put value of SP into address given by next 2 bytes in memory:
			case 0x08:
				{
					unsigned imml, immh;
					PC_READ(imml);
					PC_READ(immh);

					unsigned const addr = immh << 8 | imml;
					WRITE(addr, sp & 0xFF);
					WRITE((addr + 1) & 0xFFFF, sp >> 8);
				}

				break;

			case 0x09:
				add_hl_rr(b, c);
				break;
			case 0x0A:
				READ(a, bc());
				break;
			case 0x0B:
				dec_rr(b, c);
				break;
			case 0x0C:
				inc_r(c);
				break;
			case 0x0D:
				dec_r(c);
				break;
			case 0x0E:
				PC_READ(c);
				break;

				// rrca (4 cycles):
				// Rotate 8-bit register A right, store old bit0 in CF. Reset SF, HCF, ZF:
			case 0x0F:
				cf = a << 8 | a;
				a = cf >> 1 & 0xFF;
				hf2 = 0;
				zf = 1;
				break;

				// stop (4 cycles):
				// Halt CPU and LCD display until button pressed:
			case 0x10:
				pc = (pc + 1) & 0xFFFF;

				cycleCounter = mem_.stop(cycleCounter);

				if (cycleCounter < mem_.nextEventTime()) {
					unsigned long cycles = mem_.nextEventTime() - cycleCounter;
					cycleCounter += cycles + (-cycles & 3);
				}

				break;

			case 0x11:
				ld_rr_nn(d, e);
				break;
			case 0x12:
				WRITE(de(), a);
				break;
			case 0x13:
				inc_rr(d, e);
				break;
			case 0x14:
				inc_r(d);
				break;
			case 0x15:
				dec_r(d);
				break;
			case 0x16:
				PC_READ(d);
				break;

				// rla (4 cycles):
				// Rotate 8-bit register A left through CF, store old bit7 in CF,
				// old CF value becomes bit0. Reset SF, HCF, ZF:
			case 0x17:
				{
					unsigned oldcf = cf >> 8 & 1;
					cf = a << 1;
					a = (cf | oldcf) & 0xFF;
				}

				hf2 = 0;
				zf = 1;
				break;

			case 0x18:
				jr_disp();
				break;
			case 0x19:
				add_hl_rr(d, e);
				break;
			case 0x1A:
				READ(a, de());
				break;
			case 0x1B:
				dec_rr(d, e);
				break;
			case 0x1C:
				inc_r(e);
				break;
			case 0x1D:
				dec_r(e);
				break;
			case 0x1E:
				PC_READ(e);
				break;

				// rra (4 cycles):
				// Rotate 8-bit register A right through CF, store old bit0 in CF,
				// old CF value becomes bit7. Reset SF, HCF, ZF:
			case 0x1F:
				{
					unsigned oldcf = cf & 0x100;
					cf = a << 8;
					a = (a | oldcf) >> 1;
				}

				hf2 = 0;
				zf = 1;
				break;

				// jr nz,disp (12;8 cycles):
				// Jump to value of next (signed) byte in memory+current address if ZF is unset:
			case 0x20:
				if (zf & 0xFF) {
					jr_disp();
				} else {
					PC_MOD((pc + 1) & 0xFFFF);
				}

				break;

			case 0x21: ld_rr_nn(h, l); break;

				// ldi (hl),a (8 cycles):
				// Put A into memory address in hl. Increment HL:
			case 0x22:
				{
					unsigned addr = hl();
					WRITE(addr, a);

					addr = (addr + 1) & 0xFFFF;
					l = addr;
					h = addr >> 8;
				}

				break;

			case 0x23:
				inc_rr(h, l);
				break;
			case 0x24:
				inc_r(h);
				break;
			case 0x25:
				dec_r(h);
				break;
			case 0x26:
				PC_READ(h);
				break;

				// daa (4 cycles):
				// Adjust register A to correctly represent a BCD. Check ZF, HF and CF:
			case 0x27:
				hf2 = updateHf2FromHf1(hf1, hf2);

				{
					unsigned correction = (cf & 0x100) ? 0x60 : 0x00;

					if (hf2 & hf2_hcf)
						correction |= 0x06;

					if (!(hf2 &= hf2_subf)) {
						if ((a & 0x0F) > 0x09)
							correction |= 0x06;
						if (a > 0x99)
							correction |= 0x60;

						a += correction;
					} else
						a -= correction;

					cf = correction << 2 & 0x100;
					zf = a;
					a &= 0xFF;
				}

				break;

				// jr z,disp (12;8 cycles):
				// Jump to value of next (signed) byte in memory+current address if ZF is set:
			case 0x28:
				if (zf & 0xFF) {
					PC_MOD((pc + 1) & 0xFFFF);
				} else {
					jr_disp();
				}

				break;

			case 0x29:
				add_hl_rr(h, l);
				break;

				// ldi a,(hl) (8 cycles):
				// Put value at address in hl into A. Increment HL:
			case 0x2A:
				{
					unsigned addr = hl();
					READ(a, addr);

					addr = (addr + 1) & 0xFFFF;
					l = addr;
					h = addr >> 8;
				}

				break;

			case 0x2B:
				dec_rr(h, l);
				break;
			case 0x2C:
				inc_r(l);
				break;
			case 0x2D:
				dec_r(l);
				break;
			case 0x2E:
				PC_READ(l);
				break;

				// cpl (4 cycles):
				// Complement register A. (Flip all bits), set SF and HCF:
			case 0x2F:
				hf2 = hf2_subf | hf2_hcf;
				a ^= 0xFF;
				break;

				// jr nc,disp (12;8 cycles):
				// Jump to value of next (signed) byte in memory+current address if CF is unset:
			case 0x30:
				if (cf & 0x100) {
					PC_MOD((pc + 1) & 0xFFFF);
				} else {
					jr_disp();
				}

				break;

				// ld sp,nn (12 cycles)
				// set sp to 16-bit value of next 2 bytes in memory
			case 0x31:
				{
					unsigned imml, immh;
					PC_READ(imml);
					PC_READ(immh);

					sp = immh << 8 | imml;
				}

				break;

				// ldd (hl),a (8 cycles):
				// Put A into memory address in hl. Decrement HL:
			case 0x32:
				{
					unsigned addr = hl();
					WRITE(addr, a);

					addr = (addr - 1) & 0xFFFF;
					l = addr;
					h = addr >> 8;
				}

				break;

			case 0x33:
				sp = (sp + 1) & 0xFFFF;
				cycleCounter += 4;
				break;

				// inc (hl) (12 cycles):
				// Increment value at address in hl, check flags except CF:
			case 0x34:
				{
					unsigned const addr = hl();
					READ(hf2, addr);
					zf = hf2 + 1;
					WRITE(addr, zf & 0xFF);
					hf2 |= hf2_incf;
				}

				break;

				// dec (hl) (12 cycles):
				// Decrement value at address in hl, check flags except CF:
			case 0x35:
				{
					unsigned const addr = hl();
					READ(hf2, addr);
					zf = hf2 - 1;
					WRITE(addr, zf & 0xFF);
					hf2 |= hf2_incf | hf2_subf;
				}

				break;

				// ld (hl),n (12 cycles):
				// set memory at address in hl to value of next byte in memory:
			case 0x36:
				{
					unsigned imm;
					PC_READ(imm);
					WRITE(hl(), imm);
				}

				break;

				// scf (4 cycles):
				// Set CF. Unset SF and HCF:
			case 0x37:
				cf = 0x100;
				hf2 = 0;
				break;

				// jr c,disp (12;8 cycles):
				// Jump to value of next (signed) byte in memory+current address if CF is set:
			case 0x38:
				if (cf & 0x100) {
					jr_disp();
				} else {
					PC_MOD((pc + 1) & 0xFFFF);
				}

				break;

				// add hl,sp (8 cycles):
				// add SP to HL, check flags except ZF:
			case 0x39:
				cf = l + sp;
				l = cf & 0xFF;
				hf1 = h;
				hf2 = ((cf ^ sp) & 0x100) | sp >> 8;
				cf >>= 8;
				cf += h;
				h = cf & 0xFF;
				cycleCounter += 4;
				break;

				// ldd a,(hl) (8 cycles):
				// Put value at address in hl into A. Decrement HL:
			case 0x3A:
				{
					unsigned addr = hl();
					a = mem_.read(addr, cycleCounter);
					cycleCounter += 4;

					addr = (addr - 1) & 0xFFFF;
					l = addr;
					h = addr >> 8;
				}

				break;

			case 0x3B:
				sp = (sp - 1) & 0xFFFF;
				cycleCounter += 4;
				break;

			case 0x3C:
				inc_r(a);
				break;
			case 0x3D:
				dec_r(a);
				break;
			case 0x3E:
				PC_READ(a);
				break;

				// ccf (4 cycles):
				// Complement CF (unset if set vv.) Unset SF and HCF.
			case 0x3F:
				cf ^= 0x100;
				hf2 = 0;
				break;

			case 0x40: /*b = b;*/ break;
			case 0x41: b = c; break;
			case 0x42: b = d; break;
			case 0x43: b = e; break;
			case 0x44: b = h; break;
			case 0x45: b = l; break;
			case 0x46: READ(b, hl()); break;
			case 0x47: b = a; break;

			case 0x48: c = b; break;
			case 0x49: /*c = c;*/ break;
			case 0x4A: c = d; break;
			case 0x4B: c = e; break;
			case 0x4C: c = h; break;
			case 0x4D: c = l; break;
			case 0x4E: READ(c, hl()); break;
			case 0x4F: c = a; break;

			case 0x50: d = b; break;
			case 0x51: d = c; break;
			case 0x52: /*d = d;*/ break;
			case 0x53: d = e; break;
			case 0x54: d = h; break;
			case 0x55: d = l; break;
			case 0x56: READ(d, hl()); break;
			case 0x57: d = a; break;

			case 0x58: e = b; break;
			case 0x59: e = c; break;
			case 0x5A: e = d; break;
			case 0x5B: /*e = e;*/ break;
			case 0x5C: e = h; break;
			case 0x5D: e = l; break;
			case 0x5E: READ(e, hl()); break;
			case 0x5F: e = a; break;

			case 0x60: h = b; break;
			case 0x61: h = c; break;
			case 0x62: h = d; break;
			case 0x63: h = e; break;
			case 0x64: /*h = h;*/ break;
			case 0x65: h = l; break;
			case 0x66: READ(h, hl()); break;
			case 0x67: h = a; break;

			case 0x68: l = b; break;
			case 0x69: l = c; break;
			case 0x6A: l = d; break;
			case 0x6B: l = e; break;
			case 0x6C: l = h; break;
			case 0x6D: /*l = l;*/ break;
			case 0x6E: READ(l, hl()); break;
			case 0x6F: l = a; break;

			case 0x70: WRITE(hl(), b); break;
			case 0x71: WRITE(hl(), c); break;
			case 0x72: WRITE(hl(), d); break;
			case 0x73: WRITE(hl(), e); break;
			case 0x74: WRITE(hl(), h); break;
			case 0x75: WRITE(hl(), l); break;

				// halt (4 cycles):
			case 0x76:
				if (!mem_.ime()
					&& (   mem_.ff_read(0x0F, cycleCounter)
					     & mem_.ff_read(0xFF, cycleCounter) & 0x1F)) {
					if (mem_.isCgb())
						cycleCounter += 4;
					else
						skip_ = true;
				} else {
					mem_.halt();

					if (cycleCounter < mem_.nextEventTime()) {
						unsigned long cycles = mem_.nextEventTime() - cycleCounter;
						cycleCounter += cycles + (-cycles & 3);
					}
				}

				break;

			case 0x77: WRITE(hl(), a); break;
			case 0x78: a = b; break;
			case 0x79: a = c; break;
			case 0x7A: a = d; break;
			case 0x7B: a = e; break;
			case 0x7C: a = h; break;
			case 0x7D: a = l; break;
			case 0x7E: READ(a, hl()); break;
			case 0x7F: /*a = a;*/ break;

			case 0x80: add_a_u8(b); break;
			case 0x81: add_a_u8(c); break;
			case 0x82: add_a_u8(d); break;
			case 0x83: add_a_u8(e); break;
			case 0x84: add_a_u8(h); break;
			case 0x85: add_a_u8(l); break;
			case 0x86: { unsigned data; READ(data, hl()); add_a_u8(data); } break;
			case 0x87: add_a_u8(a); break;

			case 0x88: adc_a_u8(b); break;
			case 0x89: adc_a_u8(c); break;
			case 0x8A: adc_a_u8(d); break;
			case 0x8B: adc_a_u8(e); break;
			case 0x8C: adc_a_u8(h); break;
			case 0x8D: adc_a_u8(l); break;
			case 0x8E: { unsigned data; READ(data, hl()); adc_a_u8(data); } break;
			case 0x8F: adc_a_u8(a); break;

			case 0x90: sub_a_u8(b); break;
			case 0x91: sub_a_u8(c); break;
			case 0x92: sub_a_u8(d); break;
			case 0x93: sub_a_u8(e); break;
			case 0x94: sub_a_u8(h); break;
			case 0x95: sub_a_u8(l); break;
			case 0x96: { unsigned data; READ(data, hl()); sub_a_u8(data); } break;

				// A-A is always 0:
			case 0x97:
				hf2 = hf2_subf;
				cf = zf = a = 0;
				break;

			case 0x98: sbc_a_u8(b); break;
			case 0x99: sbc_a_u8(c); break;
			case 0x9A: sbc_a_u8(d); break;
			case 0x9B: sbc_a_u8(e); break;
			case 0x9C: sbc_a_u8(h); break;
			case 0x9D: sbc_a_u8(l); break;
			case 0x9E: { unsigned data; READ(data, hl()); sbc_a_u8(data); } break;
			case 0x9F: sbc_a_u8(a); break;

			case 0xA0: and_a_u8(b); break;
			case 0xA1: and_a_u8(c); break;
			case 0xA2: and_a_u8(d); break;
			case 0xA3: and_a_u8(e); break;
			case 0xA4: and_a_u8(h); break;
			case 0xA5: and_a_u8(l); break;
			case 0xA6: { unsigned data; READ(data, hl()); and_a_u8(data); } break;

				// A&A will always be A:
			case 0xA7:
				zf = a;
				cf = 0;
				hf2 = hf2_hcf;
				break;

			case 0xA8: xor_a_u8(b); break;
			case 0xA9: xor_a_u8(c); break;
			case 0xAA: xor_a_u8(d); break;
			case 0xAB: xor_a_u8(e); break;
			case 0xAC: xor_a_u8(h); break;
			case 0xAD: xor_a_u8(l); break;
			case 0xAE: { unsigned data; READ(data, hl()); xor_a_u8(data); } break;

				// A^A will always be 0:
			case 0xAF: cf = hf2 = zf = a = 0; break;

			case 0xB0: or_a_u8(b); break;
			case 0xB1: or_a_u8(c); break;
			case 0xB2: or_a_u8(d); break;
			case 0xB3: or_a_u8(e); break;
			case 0xB4: or_a_u8(h); break;
			case 0xB5: or_a_u8(l); break;
			case 0xB6: { unsigned data; READ(data, hl()); or_a_u8(data); } break;

				// A|A will always be A:
			case 0xB7:
				zf = a;
				hf2 = cf = 0;
				break;

			case 0xB8: cp_a_u8(b); break;
			case 0xB9: cp_a_u8(c); break;
			case 0xBA: cp_a_u8(d); break;
			case 0xBB: cp_a_u8(e); break;
			case 0xBC: cp_a_u8(h); break;
			case 0xBD: cp_a_u8(l); break;
			case 0xBE: { unsigned data; READ(data, hl()); cp_a_u8(data); } break;

				// A always equals A:
			case 0xBF:
				cf = zf = 0;
				hf2 = hf2_subf;
				break;

				// ret nz (20;8 cycles):
				// Pop two bytes from the stack and jump to that address, if ZF is unset:
			case 0xC0:
				cycleCounter += 4;

				if (zf & 0xFF)
					ret();

				break;

			case 0xC1:
				pop_rr(b, c);
				break;

				// jp nz,nn (16;12 cycles):
				// Jump to address stored in next two bytes in memory if ZF is unset:
			case 0xC2:
				if (zf & 0xFF) {
					jp_nn();
				} else {
					PC_MOD((pc + 2) & 0xFFFF);
					cycleCounter += 4;
				}

				break;

			case 0xC3:
				jp_nn();
				break;

				// call nz,nn (24;12 cycles):
				// Push address of next instruction onto stack and then jump to
				// address stored in next two bytes in memory, if ZF is unset:
			case 0xC4:
				if (zf & 0xFF) {
					call_nn();
				} else {
					PC_MOD((pc + 2) & 0xFFFF);
					cycleCounter += 4;
				}

				break;

			case 0xC5:
				push_rr(b, c);
				break;
			case 0xC6:
				{
					unsigned data;
					PC_READ(data);
					add_a_u8(data);
				}

				break;

			case 0xC7:
				rst_n(0x00);
				break;

				// ret z (20;8 cycles):
				// Pop two bytes from the stack and jump to that address, if ZF is set:
			case 0xC8:
				cycleCounter += 4;

				if (!(zf & 0xFF))
					ret();

				break;

				// ret (16 cycles):
				// Pop two bytes from the stack and jump to that address:
			case 0xC9:
				ret();
				break;

				// jp z,nn (16;12 cycles):
				// Jump to address stored in next two bytes in memory if ZF is set:
			case 0xCA:
				if (zf & 0xFF) {
					PC_MOD((pc + 2) & 0xFFFF);
					cycleCounter += 4;
				} else {
					jp_nn();
				}

				break;


				// CB OPCODES (Shifts, rotates and bits):
			case 0xCB:
				PC_READ(opcode);

				switch (opcode) {
				case 0x00: rlc_r(b); break;
				case 0x01: rlc_r(c); break;
				case 0x02: rlc_r(d); break;
				case 0x03: rlc_r(e); break;
				case 0x04: rlc_r(h); break;
				case 0x05: rlc_r(l); break;

					// rlc (hl) (16 cycles):
					// Rotate 8-bit value stored at address in HL left, store old bit7 in CF.
					// Reset SF and HCF. Check ZF:
				case 0x06:
					{
						unsigned const addr = hl();
						READ(cf, addr);
						cf <<= 1;
						zf = cf | (cf >> 8);
						WRITE(addr, zf & 0xFF);
						hf2 = 0;
					}

					break;

				case 0x07: rlc_r(a); break;

				case 0x08: rrc_r(b); break;
				case 0x09: rrc_r(c); break;
				case 0x0A: rrc_r(d); break;
				case 0x0B: rrc_r(e); break;
				case 0x0C: rrc_r(h); break;
				case 0x0D: rrc_r(l); break;

					// rrc (hl) (16 cycles):
					// Rotate 8-bit value stored at address in HL right, store old bit0 in CF.
					// Reset SF and HCF. Check ZF:
				case 0x0E:
					{
						unsigned const addr = hl();
						READ(zf, addr);
						cf = zf << 8;
						WRITE(addr, (zf | cf) >> 1 & 0xFF);
						hf2 = 0;
					}

					break;

				case 0x0F: rrc_r(a); break;

				case 0x10: rl_r(b); break;
				case 0x11: rl_r(c); break;
				case 0x12: rl_r(d); break;
				case 0x13: rl_r(e); break;
				case 0x14: rl_r(h); break;
				case 0x15: rl_r(l); break;

					// rl (hl) (16 cycles):
					// Rotate 8-bit value stored at address in HL left thorugh CF,
					// store old bit7 in CF, old CF value becoms bit0. Reset SF and HCF. Check ZF:
				case 0x16:
					{
						unsigned const addr = hl();
						unsigned const oldcf = cf >> 8 & 1;
						READ(cf, addr);
						cf <<= 1;
						zf = cf | oldcf;
						WRITE(addr, zf & 0xFF);
						hf2 = 0;
					}
					break;

				case 0x17: rl_r(a); break;

				case 0x18: rr_r(b); break;
				case 0x19: rr_r(c); break;
				case 0x1A: rr_r(d); break;
				case 0x1B: rr_r(e); break;
				case 0x1C: rr_r(h); break;
				case 0x1D: rr_r(l); break;

					// rr (hl) (16 cycles):
					// Rotate 8-bit value stored at address in HL right thorugh CF,
					// store old bit0 in CF, old CF value becoms bit7. Reset SF and HCF. Check ZF:
				case 0x1E:
					{
						unsigned const addr = hl();
						READ(zf, addr);

						unsigned const oldcf = cf & 0x100;
						cf = zf << 8;
						zf = (zf | oldcf) >> 1;
						WRITE(addr, zf);
						hf2 = 0;
					}

					break;

				case 0x1F: rr_r(a); break;

				case 0x20: sla_r(b); break;
				case 0x21: sla_r(c); break;
				case 0x22: sla_r(d); break;
				case 0x23: sla_r(e); break;
				case 0x24: sla_r(h); break;
				case 0x25: sla_r(l); break;

					// sla (hl) (16 cycles):
					// Shift 8-bit value stored at address in HL left, store old bit7 in CF.
					// Reset SF and HCF. Check ZF:
				case 0x26:
					{
						unsigned const addr = hl();
						READ(cf, addr);
						cf <<= 1;
						zf = cf;
						WRITE(addr, zf & 0xFF);
						hf2 = 0;
					}

					break;

				case 0x27: sla_r(a); break;

				case 0x28: sra_r(b); break;
				case 0x29: sra_r(c); break;
				case 0x2A: sra_r(d); break;
				case 0x2B: sra_r(e); break;
				case 0x2C: sra_r(h); break;
				case 0x2D: sra_r(l); break;

					// sra (hl) (16 cycles):
					// Shift 8-bit value stored at address in HL right, store old bit0 in CF,
					// bit7=old bit7. Reset SF and HCF. Check ZF:
				case 0x2E:
					{
						unsigned const addr = hl();
						READ(cf, addr);
						zf = cf >> 1;
						WRITE(addr, zf | (cf & 0x80));
						cf <<= 8;
						hf2 = 0;
					}

					break;

				case 0x2F: sra_r(a); break;

				case 0x30: swap_r(b); break;
				case 0x31: swap_r(c); break;
				case 0x32: swap_r(d); break;
				case 0x33: swap_r(e); break;
				case 0x34: swap_r(h); break;
				case 0x35: swap_r(l); break;

					// swap (hl) (16 cycles):
					// Swap upper and lower nibbles of 8-bit value stored at address in HL,
					// reset flags, check zero flag:
				case 0x36:
					{
						unsigned const addr = hl();
						READ(zf, addr);
						WRITE(addr, (zf << 4 | zf >> 4) & 0xFF);
						cf = hf2 = 0;
					}

					break;

				case 0x37: swap_r(a); break;

				case 0x38: srl_r(b); break;
				case 0x39: srl_r(c); break;
				case 0x3A: srl_r(d); break;
				case 0x3B: srl_r(e); break;
				case 0x3C: srl_r(h); break;
				case 0x3D: srl_r(l); break;

					// srl (hl) (16 cycles):
					// Shift 8-bit value stored at address in HL right,
					// store old bit0 in CF. Reset SF and HCF. Check ZF:
				case 0x3E:
					{
						unsigned const addr = hl();
						READ(cf, addr);
						zf = cf >> 1;
						WRITE(addr, zf);
						cf <<= 8;
						hf2 = 0;
					}

					break;

				case 0x3F: srl_r(a); break;

				case 0x40: bit0_u8(b); break;
				case 0x41: bit0_u8(c); break;
				case 0x42: bit0_u8(d); break;
				case 0x43: bit0_u8(e); break;
				case 0x44: bit0_u8(h); break;
				case 0x45: bit0_u8(l); break;
				case 0x46: { unsigned data; READ(data, hl()); bit0_u8(data); } break;
				case 0x47: bit0_u8(a); break;

				case 0x48: bit1_u8(b); break;
				case 0x49: bit1_u8(c); break;
				case 0x4A: bit1_u8(d); break;
				case 0x4B: bit1_u8(e); break;
				case 0x4C: bit1_u8(h); break;
				case 0x4D: bit1_u8(l); break;
				case 0x4E: { unsigned data; READ(data, hl()); bit1_u8(data); } break;
				case 0x4F: bit1_u8(a); break;

				case 0x50: bit2_u8(b); break;
				case 0x51: bit2_u8(c); break;
				case 0x52: bit2_u8(d); break;
				case 0x53: bit2_u8(e); break;
				case 0x54: bit2_u8(h); break;
				case 0x55: bit2_u8(l); break;
				case 0x56: { unsigned data; READ(data, hl()); bit2_u8(data); } break;
				case 0x57: bit2_u8(a); break;

				case 0x58: bit3_u8(b); break;
				case 0x59: bit3_u8(c); break;
				case 0x5A: bit3_u8(d); break;
				case 0x5B: bit3_u8(e); break;
				case 0x5C: bit3_u8(h); break;
				case 0x5D: bit3_u8(l); break;
				case 0x5E: { unsigned data; READ(data, hl()); bit3_u8(data); } break;
				case 0x5F: bit3_u8(a); break;

				case 0x60: bit4_u8(b); break;
				case 0x61: bit4_u8(c); break;
				case 0x62: bit4_u8(d); break;
				case 0x63: bit4_u8(e); break;
				case 0x64: bit4_u8(h); break;
				case 0x65: bit4_u8(l); break;
				case 0x66: { unsigned data; READ(data, hl()); bit4_u8(data); } break;
				case 0x67: bit4_u8(a); break;

				case 0x68: bit5_u8(b); break;
				case 0x69: bit5_u8(c); break;
				case 0x6A: bit5_u8(d); break;
				case 0x6B: bit5_u8(e); break;
				case 0x6C: bit5_u8(h); break;
				case 0x6D: bit5_u8(l); break;
				case 0x6E: { unsigned data; READ(data, hl()); bit5_u8(data); } break;
				case 0x6F: bit5_u8(a); break;

				case 0x70: bit6_u8(b); break;
				case 0x71: bit6_u8(c); break;
				case 0x72: bit6_u8(d); break;
				case 0x73: bit6_u8(e); break;
				case 0x74: bit6_u8(h); break;
				case 0x75: bit6_u8(l); break;
				case 0x76: { unsigned data; READ(data, hl()); bit6_u8(data); } break;
				case 0x77: bit6_u8(a); break;

				case 0x78: bit7_u8(b); break;
				case 0x79: bit7_u8(c); break;
				case 0x7A: bit7_u8(d); break;
				case 0x7B: bit7_u8(e); break;
				case 0x7C: bit7_u8(h); break;
				case 0x7D: bit7_u8(l); break;
				case 0x7E: { unsigned data; READ(data, hl()); bit7_u8(data); } break;
				case 0x7F: bit7_u8(a); break;

				case 0x80: res0_r(b); break;
				case 0x81: res0_r(c); break;
				case 0x82: res0_r(d); break;
				case 0x83: res0_r(e); break;
				case 0x84: res0_r(h); break;
				case 0x85: res0_r(l); break;
				case 0x86: resn_mem_hl(0); break;
				case 0x87: res0_r(a); break;

				case 0x88: res1_r(b); break;
				case 0x89: res1_r(c); break;
				case 0x8A: res1_r(d); break;
				case 0x8B: res1_r(e); break;
				case 0x8C: res1_r(h); break;
				case 0x8D: res1_r(l); break;
				case 0x8E: resn_mem_hl(1); break;
				case 0x8F: res1_r(a); break;

				case 0x90: res2_r(b); break;
				case 0x91: res2_r(c); break;
				case 0x92: res2_r(d); break;
				case 0x93: res2_r(e); break;
				case 0x94: res2_r(h); break;
				case 0x95: res2_r(l); break;
				case 0x96: resn_mem_hl(2); break;
				case 0x97: res2_r(a); break;

				case 0x98: res3_r(b); break;
				case 0x99: res3_r(c); break;
				case 0x9A: res3_r(d); break;
				case 0x9B: res3_r(e); break;
				case 0x9C: res3_r(h); break;
				case 0x9D: res3_r(l); break;
				case 0x9E: resn_mem_hl(3); break;
				case 0x9F: res3_r(a); break;

				case 0xA0: res4_r(b); break;
				case 0xA1: res4_r(c); break;
				case 0xA2: res4_r(d); break;
				case 0xA3: res4_r(e); break;
				case 0xA4: res4_r(h); break;
				case 0xA5: res4_r(l); break;
				case 0xA6: resn_mem_hl(4); break;
				case 0xA7: res4_r(a); break;

				case 0xA8: res5_r(b); break;
				case 0xA9: res5_r(c); break;
				case 0xAA: res5_r(d); break;
				case 0xAB: res5_r(e); break;
				case 0xAC: res5_r(h); break;
				case 0xAD: res5_r(l); break;
				case 0xAE: resn_mem_hl(5); break;
				case 0xAF: res5_r(a); break;

				case 0xB0: res6_r(b); break;
				case 0xB1: res6_r(c); break;
				case 0xB2: res6_r(d); break;
				case 0xB3: res6_r(e); break;
				case 0xB4: res6_r(h); break;
				case 0xB5: res6_r(l); break;
				case 0xB6: resn_mem_hl(6); break;
				case 0xB7: res6_r(a); break;

				case 0xB8: res7_r(b); break;
				case 0xB9: res7_r(c); break;
				case 0xBA: res7_r(d); break;
				case 0xBB: res7_r(e); break;
				case 0xBC: res7_r(h); break;
				case 0xBD: res7_r(l); break;
				case 0xBE: resn_mem_hl(7); break;
				case 0xBF: res7_r(a); break;

				case 0xC0: set0_r(b); break;
				case 0xC1: set0_r(c); break;
				case 0xC2: set0_r(d); break;
				case 0xC3: set0_r(e); break;
				case 0xC4: set0_r(h); break;
				case 0xC5: set0_r(l); break;
				case 0xC6: setn_mem_hl(0); break;
				case 0xC7: set0_r(a); break;

				case 0xC8: set1_r(b); break;
				case 0xC9: set1_r(c); break;
				case 0xCA: set1_r(d); break;
				case 0xCB: set1_r(e); break;
				case 0xCC: set1_r(h); break;
				case 0xCD: set1_r(l); break;
				case 0xCE: setn_mem_hl(1); break;
				case 0xCF: set1_r(a); break;

				case 0xD0: set2_r(b); break;
				case 0xD1: set2_r(c); break;
				case 0xD2: set2_r(d); break;
				case 0xD3: set2_r(e); break;
				case 0xD4: set2_r(h); break;
				case 0xD5: set2_r(l); break;
				case 0xD6: setn_mem_hl(2); break;
				case 0xD7: set2_r(a); break;

				case 0xD8: set3_r(b); break;
				case 0xD9: set3_r(c); break;
				case 0xDA: set3_r(d); break;
				case 0xDB: set3_r(e); break;
				case 0xDC: set3_r(h); break;
				case 0xDD: set3_r(l); break;
				case 0xDE: setn_mem_hl(3); break;
				case 0xDF: set3_r(a); break;

				case 0xE0: set4_r(b); break;
				case 0xE1: set4_r(c); break;
				case 0xE2: set4_r(d); break;
				case 0xE3: set4_r(e); break;
				case 0xE4: set4_r(h); break;
				case 0xE5: set4_r(l); break;
				case 0xE6: setn_mem_hl(4); break;
				case 0xE7: set4_r(a); break;

				case 0xE8: set5_r(b); break;
				case 0xE9: set5_r(c); break;
				case 0xEA: set5_r(d); break;
				case 0xEB: set5_r(e); break;
				case 0xEC: set5_r(h); break;
				case 0xED: set5_r(l); break;
				case 0xEE: setn_mem_hl(5); break;
				case 0xEF: set5_r(a); break;

				case 0xF0: set6_r(b); break;
				case 0xF1: set6_r(c); break;
				case 0xF2: set6_r(d); break;
				case 0xF3: set6_r(e); break;
				case 0xF4: set6_r(h); break;
				case 0xF5: set6_r(l); break;
				case 0xF6: setn_mem_hl(6); break;
				case 0xF7: set6_r(a); break;

				case 0xF8: set7_r(b); break;
				case 0xF9: set7_r(c); break;
				case 0xFA: set7_r(d); break;
				case 0xFB: set7_r(e); break;
				case 0xFC: set7_r(h); break;
				case 0xFD: set7_r(l); break;
				case 0xFE: setn_mem_hl(7); break;
				case 0xFF: set7_r(a); break;
				}

				break;


				// call z,nn (24;12 cycles):
				// Push address of next instruction onto stack and then jump to
				// address stored in next two bytes in memory, if ZF is set:
			case 0xCC:
				if (zf & 0xFF) {
					PC_MOD((pc + 2) & 0xFFFF);
					cycleCounter += 4;
				} else {
					call_nn();
				}

				break;

			case 0xCD:
				call_nn();
				break;

			case 0xCE:
				{
					unsigned data;
					PC_READ(data);
					adc_a_u8(data);
				}

				break;

			case 0xCF:
				rst_n(0x08);
				break;

				// ret nc (20;8 cycles):
				// Pop two bytes from the stack and jump to that address, if CF is unset:
			case 0xD0:
				cycleCounter += 4;

				if (!(cf & 0x100))
					ret();

				break;

			case 0xD1:
				pop_rr(d, e);
				break;

				// jp nc,nn (16;12 cycles):
				// Jump to address stored in next two bytes in memory if CF is unset:
			case 0xD2:
				if (cf & 0x100) {
					PC_MOD((pc + 2) & 0xFFFF);
					cycleCounter += 4;
				} else {
					jp_nn();
				}

				break;

			case 0xD3: // not specified. should freeze.
				break;

				// call nc,nn (24;12 cycles):
				// Push address of next instruction onto stack and then jump to
				// address stored in next two bytes in memory, if CF is unset:
			case 0xD4:
				if (cf & 0x100) {
					PC_MOD((pc + 2) & 0xFFFF);
					cycleCounter += 4;
				} else {
					call_nn();
				}

				break;

			case 0xD5:
				push_rr(d, e);
				break;

			case 0xD6:
				{
					unsigned data;
					PC_READ(data);
					sub_a_u8(data);
				}

				break;

			case 0xD7:
				rst_n(0x10);
				break;

				// ret c (20;8 cycles):
				// Pop two bytes from the stack and jump to that address, if CF is set:
			case 0xD8:
				cycleCounter += 4;

				if (cf & 0x100)
					ret();

				break;

				// reti (16 cycles):
				// Pop two bytes from the stack and jump to that address, then enable interrupts:
			case 0xD9:
				{
					unsigned sl, sh;
					pop_rr(sh, sl);
					mem_.ei(cycleCounter);
					PC_MOD(sh << 8 | sl);
				}

				break;

				// jp c,nn (16;12 cycles):
				// Jump to address stored in next two bytes in memory if CF is set:
			case 0xDA:
				if (cf & 0x100) {
					jp_nn();
				} else {
					PC_MOD((pc + 2) & 0xFFFF);
					cycleCounter += 4;
				}

				break;

			case 0xDB: // not specified. should freeze.
				break;

				// call z,nn (24;12 cycles):
				// Push address of next instruction onto stack and then jump to
				// address stored in next two bytes in memory, if CF is set:
			case 0xDC:
				if (cf & 0x100) {
					call_nn();
				} else {
					PC_MOD((pc + 2) & 0xFFFF);
					cycleCounter += 4;
				}

				break;

			case 0xDE:
				{
					unsigned data;
					PC_READ(data);
					sbc_a_u8(data);
				}

				break;

			case 0xDF:
				rst_n(0x18);
				break;

				// ld ($FF00+n),a (12 cycles):
				// Put value in A into address (0xFF00 + next byte in memory):
			case 0xE0:
				{
					unsigned imm;
					PC_READ(imm);
					FF_WRITE(imm, a);
				}

				break;

			case 0xE1:
				pop_rr(h, l);
				break;

				// ld ($FF00+C),a (8 ycles):
				// Put A into address (0xFF00 + register C):
			case 0xE2:
				FF_WRITE(c, a);
				break;

			case 0xE3: // not specified. should freeze.
				break;
			case 0xE4: // not specified. should freeze.
				break;

			case 0xE5:
				push_rr(h, l);
				break;

			case 0xE6:
				{
					unsigned data;
					PC_READ(data);
					and_a_u8(data);
				}

				break;

			case 0xE7:
				rst_n(0x20);
				break;

				// add sp,n (16 cycles):
				// Add next (signed) byte in memory to SP, reset ZF and SF, check HCF and CF:
			case 0xE8:
				sp_plus_n(sp);
				cycleCounter += 4;
				break;

				// jp hl (4 cycles):
				// Jump to address in hl:
			case 0xE9:
				pc = hl();
				break;

				// ld (nn),a (16 cycles):
				// set memory at address given by the next 2 bytes to value in A:
				// Incrementing PC before call, because of possible interrupt.
			case 0xEA:
				{
					unsigned imml, immh;
					PC_READ(imml);
					PC_READ(immh);
					WRITE(immh << 8 | imml, a);
				}

				break;

			case 0xEB: // not specified. should freeze.
				break;
			case 0xEC: // not specified. should freeze.
				break;
			case 0xED: // not specified. should freeze.
				break;

			case 0xEE:
				{
					unsigned data;
					PC_READ(data);
					xor_a_u8(data);
				}

				break;

			case 0xEF:
				rst_n(0x28);
				break;

				// ld a,($FF00+n) (12 cycles):
				// Put value at address (0xFF00 + next byte in memory) into A:
			case 0xF0:
				{
					unsigned imm;
					PC_READ(imm);
					FF_READ(a, imm);
				}

				break;

			case 0xF1:
				{
					unsigned F;
					pop_rr(a, F);
					zf  =  zfFromF(F);
					hf2 = hf2FromF(F);
					cf  =  cfFromF(F);
				}

				break;

				// ld a,($FF00+C) (8 cycles):
				// Put value at address (0xFF00 + register C) into A:
			case 0xF2:
				FF_READ(a, c);
				break;

				// di (4 cycles):
			case 0xF3:
				mem_.di();
				break;

			case 0xF4: // not specified. should freeze.
				break;

			case 0xF5:
				hf2 = updateHf2FromHf1(hf1, hf2);

				{
					unsigned F = toF(hf2, cf, zf);
					push_rr(a, F);
				}

				break;

			case 0xF6:
				{
					unsigned data;
					PC_READ(data);
					or_a_u8(data);
				}

				break;

			case 0xF7:
				rst_n(0x30);
				break;

				// ldhl sp,n (12 cycles):
				// Put (sp+next (signed) byte in memory) into hl (unsets ZF and SF, may enable HF and CF):
			case 0xF8:
				{
					unsigned sum;
					sp_plus_n(sum);
					l = sum & 0xFF;
					h = sum >> 8;
				}

				break;

				// ld sp,hl (8 cycles):
				// Put value in HL into SP
			case 0xF9:
				sp = hl();
				cycleCounter += 4;
				break;

				// ld a,(nn) (16 cycles):
				// set A to value in memory at address given by the 2 next bytes.
			case 0xFA:
				{
					unsigned imml, immh;
					PC_READ(imml);
					PC_READ(immh);

					READ(a, immh << 8 | imml);
				}

				break;

				// ei (4 cycles):
				// Enable Interrupts after next instruction:
			case 0xFB:
				mem_.ei(cycleCounter);
				break;

			case 0xFC: // not specified. should freeze.
				break;
			case 0xFD: // not specified. should freeze
				break;
			case 0xFE:
				{
					unsigned data;
					PC_READ(data);

					cp_a_u8(data);
				}

				break;

			case 0xFF:
				rst_n(0x38);
				break;
			}
		}

		pc_ = pc;
		cycleCounter = mem_.event(cycleCounter);
	}

	a_ = a;
	cycleCounter_ = cycleCounter;
}