gambatte-libretro/libgambatte/src/cpu.cpp
twinaphex 61a4c5ace2 (Android) Add JNI Makefiles - had to rename array.h and memory.h
to avoid system header include conflicts
2012-10-16 22:05:34 +02:00

2820 lines
50 KiB
C++

/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "cpu.h"
#include "gambatte-memory.h"
#include "savestate.h"
namespace gambatte {
CPU::CPU()
: memory(Interrupter(SP, PC_)),
cycleCounter_(0),
PC_(0x100),
SP(0xFFFE),
HF1(0xF),
HF2(0xF),
ZF(0),
CF(0x100),
A_(0x01),
B(0x00),
C(0x13),
D(0x00),
E(0xD8),
H(0x01),
L(0x4D),
skip(false)
{
}
long CPU::runFor(const unsigned long cycles) {
process(cycles/* << memory.isDoubleSpeed()*/);
const long csb = memory.cyclesSinceBlit(cycleCounter_);
if (cycleCounter_ & 0x80000000)
cycleCounter_ = memory.resetCounters(cycleCounter_);
return csb;
}
bool CPU::load(const void *romfile, unsigned romsize, const bool forceDmg) {
return memory.loadROM(romfile, romsize, forceDmg);
}
// (HF2 & 0x200) == true means HF is set.
// (HF2 & 0x400) marks the subtract flag.
// (HF2 & 0x800) is set for inc/dec.
// (HF2 & 0x100) is set if there's a carry to add.
static void calcHF(const unsigned HF1, unsigned& HF2) {
unsigned arg1 = HF1 & 0xF;
unsigned arg2 = (HF2 & 0xF) + (HF2 >> 8 & 1);
if (HF2 & 0x800) {
arg1 = arg2;
arg2 = 1;
}
if (HF2 & 0x400)
arg1 -= arg2;
else
arg1 = (arg1 + arg2) << 5;
HF2 |= arg1 & 0x200;
}
#define F() (((HF2 & 0x600) | (CF & 0x100)) >> 4 | ((ZF & 0xFF) ? 0 : 0x80))
#define FROM_F(f_in) do { \
unsigned from_f_var = f_in; \
\
ZF = ~from_f_var & 0x80; \
HF2 = from_f_var << 4 & 0x600; \
CF = from_f_var << 4 & 0x100; \
} while (0)
void CPU::setStatePtrs(SaveState &state) {
memory.setStatePtrs(state);
}
void CPU::saveState(SaveState &state) {
cycleCounter_ = memory.saveState(state, cycleCounter_);
calcHF(HF1, HF2);
state.cpu.cycleCounter = cycleCounter_;
state.cpu.PC = PC_;
state.cpu.SP = SP;
state.cpu.A = A_;
state.cpu.B = B;
state.cpu.C = C;
state.cpu.D = D;
state.cpu.E = E;
state.cpu.F = F();
state.cpu.H = H;
state.cpu.L = L;
state.cpu.skip = skip;
}
void CPU::loadState(const SaveState &state) {
memory.loadState(state/*, cycleCounter_*/);
cycleCounter_ = state.cpu.cycleCounter;
PC_ = state.cpu.PC;
SP = state.cpu.SP;
A_ = state.cpu.A;
B = state.cpu.B;
C = state.cpu.C;
D = state.cpu.D;
E = state.cpu.E;
FROM_F(state.cpu.F);
H = state.cpu.H;
L = state.cpu.L;
skip = state.cpu.skip;
}
#define BC() ( B << 8 | C )
#define DE() ( D << 8 | E )
#define HL() ( H << 8 | L )
#define READ(dest, addr) do { (dest) = memory.read(addr, cycleCounter); cycleCounter += 4; } while (0)
// #define PC_READ(dest, addr) do { (dest) = memory.pc_read(addr, cycleCounter); cycleCounter += 4; } while (0)
#define PC_READ(dest) do { (dest) = memory.read(PC, cycleCounter); PC = (PC + 1) & 0xFFFF; cycleCounter += 4; } while (0)
#define FF_READ(dest, addr) do { (dest) = memory.ff_read(addr, cycleCounter); cycleCounter += 4; } while (0)
#define WRITE(addr, data) do { memory.write(addr, data, cycleCounter); cycleCounter += 4; } while (0)
#define FF_WRITE(addr, data) do { memory.ff_write(addr, data, cycleCounter); cycleCounter += 4; } while (0)
#define PC_MOD(data) do { PC = data; cycleCounter += 4; } while (0)
#define PUSH(r1, r2) do { \
SP = (SP - 1) & 0xFFFF; \
WRITE(SP, (r1)); \
SP = (SP - 1) & 0xFFFF; \
WRITE(SP, (r2)); \
} while (0)
//CB OPCODES (Shifts, rotates and bits):
//swap r (8 cycles):
//Swap upper and lower nibbles of 8-bit register, reset flags, check zero flag:
#define swap_r(r) do { \
CF = HF2 = 0; \
ZF = (r); \
(r) = (ZF << 4 | ZF >> 4) & 0xFF; \
} while (0)
//rlc r (8 cycles):
//Rotate 8-bit register left, store old bit7 in CF. Reset SF and HCF, Check ZF:
#define rlc_r(r) do { \
CF = (r) << 1; \
ZF = CF | CF >> 8; \
(r) = ZF & 0xFF; \
HF2 = 0; \
} while (0)
//rl r (8 cycles):
//Rotate 8-bit register left through CF, store old bit7 in CF, old CF value becomes bit0. Reset SF and HCF, Check ZF:
#define rl_r(r) do { \
const unsigned rl_r_var_oldcf = CF >> 8 & 1; \
CF = (r) << 1; \
ZF = CF | rl_r_var_oldcf; \
(r) = ZF & 0xFF; \
HF2 = 0; \
} while (0)
//rrc r (8 cycles):
//Rotate 8-bit register right, store old bit0 in CF. Reset SF and HCF, Check ZF:
#define rrc_r(r) do { \
ZF = (r); \
CF = ZF << 8; \
(r) = (ZF | CF) >> 1 & 0xFF; \
HF2 = 0; \
} while (0)
//rr r (8 cycles):
//Rotate 8-bit register right through CF, store old bit0 in CF, old CF value becomes bit7. Reset SF and HCF, Check ZF:
#define rr_r(r) do { \
const unsigned rr_r_var_oldcf = CF & 0x100; \
CF = (r) << 8; \
(r) = ZF = ((r) | rr_r_var_oldcf) >> 1; \
HF2 = 0; \
} while (0)
//sla r (8 cycles):
//Shift 8-bit register left, store old bit7 in CF. Reset SF and HCF, Check ZF:
#define sla_r(r) do { \
ZF = CF = (r) << 1; \
(r) = ZF & 0xFF; \
HF2 = 0; \
} while (0)
//sra r (8 cycles):
//Shift 8-bit register right, store old bit0 in CF. bit7=old bit7. Reset SF and HCF, Check ZF:
#define sra_r(r) do { \
CF = (r) << 8; \
ZF = (r) >> 1; \
(r) = ZF | ((r) & 0x80); \
HF2 = 0; \
} while (0)
//srl r (8 cycles):
//Shift 8-bit register right, store old bit0 in CF. Reset SF and HCF, Check ZF:
#define srl_r(r) do { \
ZF = (r); \
CF = (r) << 8; \
ZF >>= 1; \
(r) = ZF; \
HF2 = 0; \
} while (0)
//bit n,r (8 cycles):
//bit n,(hl) (12 cycles):
//Test bitn in 8-bit value, check ZF, unset SF, set HCF:
#define bitn_u8(bitmask, u8) do { \
ZF = (u8) & (bitmask); \
HF2 = 0x200; \
} while (0)
#define bit0_u8(u8) bitn_u8(1, (u8))
#define bit1_u8(u8) bitn_u8(2, (u8))
#define bit2_u8(u8) bitn_u8(4, (u8))
#define bit3_u8(u8) bitn_u8(8, (u8))
#define bit4_u8(u8) bitn_u8(0x10, (u8))
#define bit5_u8(u8) bitn_u8(0x20, (u8))
#define bit6_u8(u8) bitn_u8(0x40, (u8))
#define bit7_u8(u8) bitn_u8(0x80, (u8))
//set n,r (8 cycles):
//Set bitn of 8-bit register:
#define set0_r(r) ( (r) |= 0x1 )
#define set1_r(r) ( (r) |= 0x2 )
#define set2_r(r) ( (r) |= 0x4 )
#define set3_r(r) ( (r) |= 0x8 )
#define set4_r(r) ( (r) |= 0x10 )
#define set5_r(r) ( (r) |= 0x20 )
#define set6_r(r) ( (r) |= 0x40 )
#define set7_r(r) ( (r) |= 0x80 )
//set n,(hl) (16 cycles):
//Set bitn of value at address stored in HL:
#define setn_mem_hl(n) do { \
const unsigned setn_mem_hl_var_addr = HL(); \
unsigned setn_mem_hl_var_tmp; \
\
READ(setn_mem_hl_var_tmp, setn_mem_hl_var_addr); \
setn_mem_hl_var_tmp |= 1 << (n); \
\
WRITE(setn_mem_hl_var_addr, setn_mem_hl_var_tmp); \
} while (0)
//res n,r (8 cycles):
//Unset bitn of 8-bit register:
#define res0_r(r) ( (r) &= 0xFE )
#define res1_r(r) ( (r) &= 0xFD )
#define res2_r(r) ( (r) &= 0xFB )
#define res3_r(r) ( (r) &= 0xF7 )
#define res4_r(r) ( (r) &= 0xEF )
#define res5_r(r) ( (r) &= 0xDF )
#define res6_r(r) ( (r) &= 0xBF )
#define res7_r(r) ( (r) &= 0x7F )
//res n,(hl) (16 cycles):
//Unset bitn of value at address stored in HL:
#define resn_mem_hl(n) do { \
const unsigned resn_mem_hl_var_addr = HL(); \
unsigned resn_mem_hl_var_tmp; \
\
READ(resn_mem_hl_var_tmp, resn_mem_hl_var_addr); \
resn_mem_hl_var_tmp &= ~(1 << (n)); \
\
WRITE(resn_mem_hl_var_addr, resn_mem_hl_var_tmp); \
} while (0)
//16-BIT LOADS:
//ld rr,nn (12 cycles)
//set rr to 16-bit value of next 2 bytes in memory
#define ld_rr_nn(r1, r2) do { \
PC_READ(r2); \
PC_READ(r1); \
} while (0)
//push rr (16 cycles):
//Push value of register pair onto stack:
#define push_rr(r1, r2) do { \
PUSH(r1, r2); \
cycleCounter += 4; \
} while (0)
//pop rr (12 cycles):
//Pop two bytes off stack into register pair:
#define pop_rr(r1, r2) do { \
READ(r2, SP); \
SP = (SP + 1) & 0xFFFF; \
READ(r1, SP); \
SP = (SP + 1) & 0xFFFF; \
} while (0)
//8-BIT ALU:
//add a,r (4 cycles):
//add a,(addr) (8 cycles):
//Add 8-bit value to A, check flags:
#define add_a_u8(u8) do { \
HF1 = A; \
HF2 = u8; \
ZF = CF = A + HF2; \
A = ZF & 0xFF; \
} while (0)
//adc a,r (4 cycles):
//adc a,(addr) (8 cycles):
//Add 8-bit value+CF to A, check flags:
#define adc_a_u8(u8) do { \
HF1 = A; \
HF2 = (CF & 0x100) | (u8); \
ZF = CF = (CF >> 8 & 1) + (u8) + A; \
A = ZF & 0xFF; \
} while (0)
//sub a,r (4 cycles):
//sub a,(addr) (8 cycles):
//Subtract 8-bit value from A, check flags:
#define sub_a_u8(u8) do { \
HF1 = A; \
HF2 = u8; \
ZF = CF = A - HF2; \
A = ZF & 0xFF; \
HF2 |= 0x400; \
} while (0)
//sbc a,r (4 cycles):
//sbc a,(addr) (8 cycles):
//Subtract CF and 8-bit value from A, check flags:
#define sbc_a_u8(u8) do { \
HF1 = A; \
HF2 = 0x400 | (CF & 0x100) | (u8); \
ZF = CF = A - ((CF >> 8) & 1) - (u8); \
A = ZF & 0xFF; \
} while (0)
//and a,r (4 cycles):
//and a,(addr) (8 cycles):
//bitwise and 8-bit value into A, check flags:
#define and_a_u8(u8) do { \
HF2 = 0x200; \
CF = 0; \
A &= (u8); \
ZF = A; \
} while (0)
//or a,r (4 cycles):
//or a,(hl) (8 cycles):
//bitwise or 8-bit value into A, check flags:
#define or_a_u8(u8) do { \
CF = HF2 = 0; \
A |= (u8); \
ZF = A; \
} while (0)
//xor a,r (4 cycles):
//xor a,(hl) (8 cycles):
//bitwise xor 8-bit value into A, check flags:
#define xor_a_u8(u8) do { \
CF = HF2 = 0; \
A ^= (u8); \
ZF = A; \
} while (0)
//cp a,r (4 cycles):
//cp a,(addr) (8 cycles):
//Compare (subtract without storing result) 8-bit value to A, check flags:
#define cp_a_u8(u8) do { \
HF1 = A; \
HF2 = u8; \
ZF = CF = A - HF2; \
HF2 |= 0x400; \
} while (0)
//inc r (4 cycles):
//Increment value of 8-bit register, check flags except CF:
#define inc_r(r) do { \
HF2 = (r) | 0x800; \
ZF = (r) + 1; \
(r) = ZF & 0xFF; \
} while (0)
//dec r (4 cycles):
//Decrement value of 8-bit register, check flags except CF:
#define dec_r(r) do { \
HF2 = (r) | 0xC00; \
ZF = (r) - 1; \
(r) = ZF & 0xFF; \
} while (0)
//16-BIT ARITHMETIC
//add hl,rr (8 cycles):
//add 16-bit register to HL, check flags except ZF:
/*#define add_hl_rr(rh, rl) do { \
L = HF1 = L + (rl); \
HF1 >>= 8; \
HF1 += H; \
HF2 = (rh); \
H = CF = HF1 + (rh); \
cycleCounter += 4; \
} while (0)*/
#define add_hl_rr(rh, rl) do { \
CF = L + (rl); \
L = CF & 0xFF; \
HF1 = H; \
HF2 = (CF & 0x100) | (rh); \
CF = H + (CF >> 8) + (rh); \
H = CF & 0xFF; \
cycleCounter += 4; \
} while (0)
//inc rr (8 cycles):
//Increment 16-bit register:
#define inc_rr(rh, rl) do { \
const unsigned inc_rr_var_tmp = (rl) + 1; \
(rl) = inc_rr_var_tmp & 0xFF; \
(rh) = ((rh) + (inc_rr_var_tmp >> 8)) & 0xFF; \
cycleCounter += 4; \
} while (0)
//dec rr (8 cycles):
//Decrement 16-bit register:
#define dec_rr(rh, rl) do { \
const unsigned dec_rr_var_tmp = (rl) - 1; \
(rl) = dec_rr_var_tmp & 0xFF; \
(rh) = ((rh) - (dec_rr_var_tmp >> 8 & 1)) & 0xFF; \
cycleCounter += 4; \
} while (0)
#define sp_plus_n(sumout) do { \
unsigned sp_plus_n_var_n; \
PC_READ(sp_plus_n_var_n); \
sp_plus_n_var_n = (sp_plus_n_var_n ^ 0x80) - 0x80; \
\
const unsigned sp_plus_n_var_sum = SP + sp_plus_n_var_n; \
CF = SP ^ sp_plus_n_var_n ^ sp_plus_n_var_sum; \
HF2 = CF << 5 & 0x200; \
ZF = 1; \
cycleCounter += 4; \
(sumout) = sp_plus_n_var_sum & 0xFFFF; \
} while (0)
//JUMPS:
//jp nn (16 cycles):
//Jump to address stored in the next two bytes in memory:
#define jp_nn() do { \
unsigned jp_nn_var_l, jp_nn_var_h; \
\
PC_READ(jp_nn_var_l); \
PC_READ(jp_nn_var_h); \
\
PC_MOD(jp_nn_var_h << 8 | jp_nn_var_l); \
} while (0)
//jr disp (12 cycles):
//Jump to value of next (signed) byte in memory+current address:
#define jr_disp() do { \
unsigned jr_disp_var_tmp; \
\
PC_READ(jr_disp_var_tmp); \
jr_disp_var_tmp = (jr_disp_var_tmp ^ 0x80) - 0x80; \
\
PC_MOD((PC + jr_disp_var_tmp) & 0xFFFF); \
} while (0)
//CALLS, RESTARTS AND RETURNS:
//call nn (24 cycles):
//Push address of next instruction onto stack and then jump to address stored in next two bytes in memory:
#define call_nn() do { \
PUSH(((PC + 2) >> 8) & 0xFF, (PC + 2) & 0xFF); \
jp_nn(); \
} while (0)
//rst n (16 Cycles):
//Push present address onto stack, jump to address n (one of 00h,08h,10h,18h,20h,28h,30h,38h):
#define rst_n(n) do { \
PUSH(PC >> 8, PC & 0xFF); \
PC_MOD(n); \
} while (0)
//ret (16 cycles):
//Pop two bytes from the stack and jump to that address:
#define ret() do { \
unsigned ret_var_l, ret_var_h; \
\
pop_rr(ret_var_h, ret_var_l); \
\
PC_MOD(ret_var_h << 8 | ret_var_l); \
} while (0)
void CPU::process(const unsigned long cycles) {
memory.setEndtime(cycleCounter_, cycles);
unsigned char A = A_;
unsigned long cycleCounter = cycleCounter_;
while (memory.isActive()) {
unsigned short PC = PC_;
if (memory.halted()) {
if (cycleCounter < memory.nextEventTime()) {
const unsigned long cycles = memory.nextEventTime() - cycleCounter;
cycleCounter += cycles + (-cycles & 3);
}
} else while (cycleCounter < memory.nextEventTime()) {
unsigned char opcode;
PC_READ(opcode);
if (skip) {
PC = (PC - 1) & 0xFFFF;
skip = false;
}
switch (opcode) {
//nop (4 cycles):
//Do nothing for 4 cycles:
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 l, h;
PC_READ(l);
PC_READ(h);
const unsigned addr = h << 8 | l;
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 = memory.stop(cycleCounter);
if (cycleCounter < memory.nextEventTime()) {
const unsigned long cycles = memory.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:
{
const 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:
{
const 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:
/*{
unsigned correction = ((A > 0x99) || (CF & 0x100)) ? 0x60 : 0x00;
calcHF(HF1, HF2);
if ((A & 0x0F) > 0x09 || (HF2 & 0x200))
correction |= 0x06;
HF1 = A;
HF2 = (HF2 & 0x400) | correction;
CF = (correction & 0x40) << 2;
A = (HF2 & 0x400) ? A - correction : (A + correction);
ZF = A;
}*/
calcHF(HF1, HF2);
{
unsigned correction = (CF & 0x100) ? 0x60 : 0x00;
if (HF2 & 0x200)
correction |= 0x06;
if (!(HF2 &= 0x400)) {
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;
//add hl,hl (8 cycles):
//add 16-bit register HL to HL, check flags except ZF:
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: /*setSubtractFlag(); setHalfCarryFlag();*/
HF2 = 0x600;
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 l, h;
PC_READ(l);
PC_READ(h);
SP = h << 8 | l;
}
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:
{
const unsigned addr = HL();
READ(HF2, addr);
ZF = HF2 + 1;
WRITE(addr, ZF & 0xFF);
HF2 |= 0x800;
}
break;
//dec (hl) (12 cycles):
//Decrement value at address in hl, check flags except CF:
case 0x35:
{
const unsigned addr = HL();
READ(HF2, addr);
ZF = HF2 - 1;
WRITE(addr, ZF & 0xFF);
HF2 |= 0xC00;
}
break;
//ld (hl),n (12 cycles):
//set memory at address in hl to value of next byte in memory:
case 0x36:
{
unsigned tmp;
PC_READ(tmp);
WRITE(HL(), tmp);
}
break;
//scf (4 cycles):
//Set CF. Unset SF and HCF:
case 0x37: /*setCarryFlag(); unsetSubtractFlag(); unsetHalfCarryFlag();*/
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: //PC+=(((int8_t)memory.read(PC++))*CarryFlag()); Cycles(8); break;
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: /*add_hl_rr(SP>>8, SP); break;*/
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 = memory.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: /*complementCarryFlag(); unsetSubtractFlag(); unsetHalfCarryFlag();*/
CF ^= 0x100;
HF2 = 0;
break;
//ld r,r (4 cycles):next_irqEventTime
//ld r,(r) (8 cycles):
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 (!memory.ime() && (memory.ff_read(0xFF0F, cycleCounter) & memory.ff_read(0xFFFF, cycleCounter) & 0x1F)) {
if (memory.isCgb())
cycleCounter += 4;
else
skip = true;
} else {
memory.halt();
if (cycleCounter < memory.nextEventTime()) {
const unsigned long cycles = memory.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 = 0x400;
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 = 0x200;
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 = 0x400;
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:
{
const unsigned 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:
{
const unsigned 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:
{
const unsigned addr = HL();
const unsigned 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:
{
const unsigned addr = HL();
READ(ZF, addr);
const unsigned 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:
{
const unsigned 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:
{
const unsigned 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:
{
const unsigned 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:
{
const unsigned 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;
// default: 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: /*doesn't exist*/
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 l, h;
pop_rr(h, l);
memory.ei(cycleCounter);
PC_MOD(h << 8 | l);
}
break;
//jp c,nn (16;12 cycles):
//Jump to address stored in next two bytes in memory if CF is set:
case 0xDA: //PC=( ((PC+2)*(1-CarryFlag())) + (((memory.read(PC+1)<<8)+memory.read(PC))*CarryFlag()) ); Cycles(12); break;
if (CF & 0x100) {
jp_nn();
} else {
PC_MOD((PC + 2) & 0xFFFF);
cycleCounter += 4;
}
break;
case 0xDB: /*doesn't exist*/
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 tmp;
PC_READ(tmp);
FF_WRITE(0xFF00 | tmp, 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(0xFF00 | C, A);
break;
case 0xE3: /*doesn't exist*/
break;
case 0xE4: /*doesn't exist*/
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:
/*{
int8_t tmp = int8_t(memory.pc_read(PC++, cycleCounter));
HF2 = (((SP & 0xFFF) + tmp) >> 3) & 0x200;
CF = SP + tmp;
SP = CF;
CF >>= 8;
ZF = 1;
cycleCounter += 12;
}*/
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 l, h;
PC_READ(l);
PC_READ(h);
WRITE(h << 8 | l, A);
}
break;
case 0xEB: /*doesn't exist*/
break;
case 0xEC: /*doesn't exist*/
break;
case 0xED: /*doesn't exist*/
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 tmp;
PC_READ(tmp);
FF_READ(A, 0xFF00 | tmp);
}
break;
case 0xF1: /*pop_rr(A, F); Cycles(12); break;*/
{
unsigned F;
pop_rr(A, F);
FROM_F(F);
}
break;
//ld a,($FF00+C) (8 cycles):
//Put value at address (0xFF00 + register C) into A:
case 0xF2:
FF_READ(A, 0xFF00 | C);
break;
//di (4 cycles):
case 0xF3:
memory.di();
break;
case 0xF4: /*doesn't exist*/
break;
case 0xF5: /*push_rr(A, F); Cycles(16); break;*/
calcHF(HF1, HF2);
{
unsigned F = F();
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:
/*{
int8_t tmp = int8_t(memory.pc_read(PC++, cycleCounter));
HF2 = (((SP & 0xFFF) + tmp) >> 3) & 0x200;
CF = SP + tmp;
L = CF;
CF >>= 8;
H = CF;
ZF = 1;
cycleCounter += 8;
}*/
{
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 l, h;
PC_READ(l);
PC_READ(h);
READ(A, h << 8 | l);
}
break;
//ei (4 cycles):
//Enable Interrupts after next instruction:
case 0xFB:
memory.ei(cycleCounter);
break;
case 0xFC: /*doesn't exist*/
break;
case 0xFD: /*doesn't exist*/
break;
case 0xFE:
{
unsigned data;
PC_READ(data);
cp_a_u8(data);
}
break;
case 0xFF:
rst_n(0x38);
break;
// default: break;
}
}
PC_ = PC;
cycleCounter = memory.event(cycleCounter);
}
A_ = A;
cycleCounter_ = cycleCounter;
}
}