0,0 → 1,1311 |
/********************************************************************************/ |
/* */ |
/* CZ80 opcode include source file */ |
/* C Z80 emulator version 0.91 */ |
/* Copyright 2004-2005 Stephane Dallongeville */ |
/* */ |
/********************************************************************************/ |
|
#if CZ80_USE_JUMPTABLE |
goto *JumpTable[Opcode]; |
#else |
switch (Opcode) |
{ |
#endif |
|
// 8 BITS LOAD |
|
OP(0x00): // NOP |
|
OP(0x40): // LD B,B |
OP(0x49): // LD C,C |
OP(0x52): // LD D,D |
OP(0x5b): // LD E,E |
OP(0x64): // LD H,H |
OP(0x6d): // LD L,L |
OP(0x7f): // LD A,A |
OP_NOP: |
RET(4) |
|
OP(0x41): // LD B,C |
OP(0x42): // LD B,D |
OP(0x43): // LD B,E |
OP(0x44): // LD B,H |
OP(0x45): // LD B,L |
OP(0x47): // LD B,A |
|
OP(0x48): // LD C,B |
OP(0x4a): // LD C,D |
OP(0x4b): // LD C,E |
OP(0x4c): // LD C,H |
OP(0x4d): // LD C,L |
OP(0x4f): // LD C,A |
|
OP(0x50): // LD D,B |
OP(0x51): // LD D,C |
OP(0x53): // LD D,E |
OP(0x54): // LD D,H |
OP(0x55): // LD D,L |
OP(0x57): // LD D,A |
|
OP(0x58): // LD E,B |
OP(0x59): // LD E,C |
OP(0x5a): // LD E,D |
OP(0x5c): // LD E,H |
OP(0x5d): // LD E,L |
OP(0x5f): // LD E,A |
|
OP(0x60): // LD H,B |
OP(0x61): // LD H,C |
OP(0x62): // LD H,D |
OP(0x63): // LD H,E |
OP(0x65): // LD H,L |
OP(0x67): // LD H,A |
|
OP(0x68): // LD L,B |
OP(0x69): // LD L,C |
OP(0x6a): // LD L,D |
OP(0x6b): // LD L,E |
OP(0x6c): // LD L,H |
OP(0x6f): // LD L,A |
|
OP(0x78): // LD A,B |
OP(0x79): // LD A,C |
OP(0x7a): // LD A,D |
OP(0x7b): // LD A,E |
OP(0x7c): // LD A,H |
OP(0x7d): // LD A,L |
OP_LD_R_R: |
zR8((Opcode >> 3) & 7) = zR8(Opcode & 7); |
RET(4) |
|
OP(0x06): // LD B,#imm |
OP(0x0e): // LD C,#imm |
OP(0x16): // LD D,#imm |
OP(0x1e): // LD E,#imm |
OP(0x26): // LD H,#imm |
OP(0x2e): // LD L,#imm |
OP(0x3e): // LD A,#imm |
OP_LD_R_imm: |
zR8(Opcode >> 3) = FETCH_BYTE; |
RET(7) |
|
OP(0x46): // LD B,(HL) |
OP(0x4e): // LD C,(HL) |
OP(0x56): // LD D,(HL) |
OP(0x5e): // LD E,(HL) |
OP(0x66): // LD H,(HL) |
OP(0x6e): // LD L,(HL) |
OP(0x7e): // LD A,(HL) |
/* OP_LD_R_mHL: */ |
PRE_IO |
READ_BYTE(zHL, zR8((Opcode >> 3) & 7)) |
POST_IO |
RET(7) |
|
OP(0x70): // LD (HL),B |
OP(0x71): // LD (HL),C |
OP(0x72): // LD (HL),D |
OP(0x73): // LD (HL),E |
OP(0x74): // LD (HL),H |
OP(0x75): // LD (HL),L |
OP(0x77): // LD (HL),A |
/* OP_LD_mHL_R: */ |
PRE_IO |
WRITE_BYTE(zHL, zR8(Opcode & 7)) |
POST_IO |
RET(7) |
|
OP(0x36): // LD (HL), #imm |
/* OP_LD_mHL_imm: */ |
PRE_IO |
WRITE_BYTE(zHL, FETCH_BYTE) |
POST_IO |
RET(10) |
|
{ |
uint16_t adr; |
|
OP(0x0a): // LD A,(BC) |
OP_LOAD_A_mBC: |
adr = zBC; |
goto OP_LOAD_A_mxx; |
|
OP(0x1a): // LD A,(DE) |
OP_LOAD_A_mDE: |
adr = zDE; |
|
OP_LOAD_A_mxx: |
PRE_IO |
READ_BYTE(adr, zA) |
POST_IO |
RET(7) |
|
OP(0x3a): // LD A,(nn) |
OP_LOAD_A_mNN: |
PRE_IO |
FETCH_WORD(adr) |
READ_BYTE(adr, zA) |
POST_IO |
RET(13) |
|
OP(0x02): // LD (BC),A |
OP_LOAD_mBC_A: |
adr = zBC; |
goto OP_LOAD_mxx_A; |
|
OP(0x12): // LD (DE),A |
OP_LOAD_mDE_A: |
adr = zDE; |
|
OP_LOAD_mxx_A: |
PRE_IO |
WRITE_BYTE(adr, zA) |
POST_IO |
RET(7) |
|
OP(0x32): // LD (nn),A |
OP_LOAD_mNN_A: |
PRE_IO |
FETCH_WORD(adr) |
WRITE_BYTE(adr, zA) |
POST_IO |
RET(13) |
} |
|
// 16 BITS LOAD |
|
OP(0x01): // LD BC,nn |
OP(0x11): // LD DE,nn |
OP(0x21): // LD HL,nn |
OP_LOAD_RR_imm16: |
FETCH_WORD(zR16(Opcode >> 4)) |
RET(10) |
|
OP(0x31): // LD SP,nn |
OP_LOAD_SP_imm16: |
FETCH_WORD(zSP) |
RET(10) |
|
OP(0xf9): // LD SP,HL |
OP_LD_SP_xx: |
zSP = data->W; |
RET(6) |
|
{ |
uint16_t adr; |
|
OP(0x2a): // LD HL,(nn) |
OP_LD_xx_mNN: |
PRE_IO |
FETCH_WORD(adr) |
READ_WORD_LE(adr, data->W) |
POST_IO |
RET(16) |
|
OP(0x22): // LD (nn),HL |
OP_LD_mNN_xx: |
PRE_IO |
FETCH_WORD(adr) |
WRITE_WORD_LE(adr, data->W) |
POST_IO |
RET(16) |
} |
|
// PUSH / POP |
|
OP(0xf1): // POP AF |
OP_POP_AF: |
{ |
uint16_t res; |
|
PRE_IO |
POP_16(res) |
zA = res >> 8; |
zF = res & 0xFF; |
POST_IO |
RET(10) |
} |
|
OP(0xc1): // POP BC |
OP(0xd1): // POP DE |
OP_POP_RR: |
data = pzR16((Opcode >> 4) & 3); |
|
OP(0xe1): // POP HL |
OP_POP: |
PRE_IO |
POP_16(data->W) |
POST_IO |
RET(10) |
|
OP(0xf5): // PUSH AF |
OP_PUSH_AF: |
PRE_IO |
PUSH_16((zA << 8) | zF); |
POST_IO |
RET(11) |
|
OP(0xc5): // PUSH BC |
OP(0xd5): // PUSH DE |
OP_PUSH_RR: |
data = pzR16((Opcode >> 4) & 3); |
|
OP(0xe5): // PUSH HL |
OP_PUSH: |
PRE_IO |
PUSH_16(data->W); |
POST_IO |
RET(11) |
|
// EXCHANGE & BLOCK TRANSFERT / SEARCH |
|
{ |
uint16_t tmp; |
|
OP(0x08): // EX AF,AF' |
OP_EX_AF_AF2: |
tmp = zFA; |
zFA = zFA2; |
zFA2 = tmp; |
RET(4) |
|
OP(0xeb): // EX DE,HL |
OP_EX_DE_HL: |
tmp = zDE; |
zDE = zHL; |
zHL = tmp; |
RET(4) |
|
OP(0xd9): // EXX |
OP_EXX: |
tmp = zBC; |
zBC = zBC2; |
zBC2 = tmp; |
tmp = zDE; |
zDE = zDE2; |
zDE2 = tmp; |
tmp = zHL; |
zHL = zHL2; |
zHL2 = tmp; |
RET(4) |
} |
|
OP(0xe3): // EX HL,(SP) |
{ |
uint16_t adr; |
uint16_t tmp; |
|
OP_EX_xx_mSP: |
PRE_IO |
adr = zSP; |
tmp = data->W; |
READ_WORD_LE(adr, data->W) |
WRITE_WORD_LE(adr, tmp) |
POST_IO |
RET(19) |
} |
|
// 8 BITS ARITHMETIC |
|
OP(0x04): // INC B |
OP(0x0c): // INC C |
OP(0x14): // INC D |
OP(0x1c): // INC E |
OP(0x24): // INC H |
OP(0x2c): // INC L |
OP(0x3c): // INC A |
OP_INC_R: |
zR8(Opcode >> 3)++; |
zF = (zF & CZ80_CF) | SZXYHV_inc[zR8(Opcode >> 3)]; |
RET(4) |
|
{ |
uint16_t adr; |
uint16_t res; |
|
OP_INC_mIx: |
adr = data->W + FETCH_BYTE_S; |
CCnt -= 11; |
goto OP_INC_m; |
|
OP(0x34): // INC (HL) |
adr = zHL; |
|
OP_INC_m: |
PRE_IO |
READ_BYTE(adr, res) |
res = (res + 1) & 0xFF; |
WRITE_BYTE(adr, res) |
zF = (zF & CZ80_CF) | SZXYHV_inc[res]; |
POST_IO |
RET(11) |
} |
|
OP(0x05): // DEC B |
OP(0x0d): // DEC C |
OP(0x15): // DEC D |
OP(0x1d): // DEC E |
OP(0x25): // DEC H |
OP(0x2d): // DEC L |
OP(0x3d): // DEC A |
OP_DEC_R: |
zR8(Opcode >> 3)--; |
zF = (zF & CZ80_CF) | SZXYHV_dec[zR8(Opcode >> 3)]; |
RET(4) |
|
{ |
uint16_t adr; |
uint16_t res; |
|
OP_DEC_mIx: |
adr = data->W + FETCH_BYTE_S; |
CCnt -= 11; |
goto OP_DEC_m; |
|
OP(0x35): // DEC (HL) |
adr = zHL; |
|
OP_DEC_m: |
PRE_IO |
READ_BYTE(adr, res) |
res = (res - 1) & 0xFF; |
WRITE_BYTE(adr, res) |
zF = (zF & CZ80_CF) | SZXYHV_dec[res]; |
POST_IO |
RET(11) |
} |
|
{ |
uint8_t val; |
uint16_t res; |
|
// ADD |
|
OP_ADD_mIx: |
PRE_IO |
READ_BYTE(data->W + FETCH_BYTE_S, val) |
POST_IO |
CCnt -= 11; |
goto OP_ADD; |
|
OP(0xc6): // ADD A,n |
OP_ADD_imm: |
val = FETCH_BYTE; |
CCnt -= 3; |
goto OP_ADD; |
|
OP(0x86): // ADD A,(HL) |
/* OP_ADD_mHL: */ |
PRE_IO |
READ_BYTE(zHL, val) |
POST_IO |
CCnt -= 3; |
goto OP_ADD; |
|
OP_ADD_IxH: |
val = data->B.H; |
goto OP_ADD; |
|
OP_ADD_IxL: |
val = data->B.L; |
goto OP_ADD; |
|
OP(0x80): // ADD A,B |
OP(0x81): // ADD A,C |
OP(0x82): // ADD A,D |
OP(0x83): // ADD A,E |
OP(0x84): // ADD A,H |
OP(0x85): // ADD A,L |
OP(0x87): // ADD A,A |
OP_ADD_R: |
val = zR8(Opcode & 7); |
|
OP_ADD: |
// bench : maybe use src instead of zA in zF calculation |
res = zA + val; |
zF = SZXY[res & 0xFF] | // S/Z/X/Y flag |
((zA ^ res ^ val) & CZ80_HF) | // H flag |
(((val ^ zA ^ 0x80) & (val ^ res) & 0x80) >> 5) | // V flag |
((res >> 8) & CZ80_CF); // C flag |
zA = res; |
RET(4) |
|
// ADC |
|
OP_ADC_mIx: |
PRE_IO |
READ_BYTE(data->W + FETCH_BYTE_S, val) |
POST_IO |
CCnt -= 11; |
goto OP_ADC; |
|
OP(0xce): // ADC A,n |
OP_ADC_imm: |
val = FETCH_BYTE; |
CCnt -= 3; |
goto OP_ADC; |
|
OP(0x8e): // ADC A,(HL) |
/* OP_ADC_mHL: */ |
PRE_IO |
READ_BYTE(zHL, val) |
POST_IO |
CCnt -= 3; |
goto OP_ADC; |
|
OP_ADC_IxH: |
val = data->B.H; |
goto OP_ADC; |
|
OP_ADC_IxL: |
val = data->B.L; |
goto OP_ADC; |
|
OP(0x88): // ADC A,B |
OP(0x89): // ADC A,C |
OP(0x8a): // ADC A,D |
OP(0x8b): // ADC A,E |
OP(0x8c): // ADC A,H |
OP(0x8d): // ADC A,L |
OP(0x8f): // ADC A,A |
OP_ADC_R: |
val = zR8(Opcode & 7); |
|
OP_ADC: |
// bench : maybe use src instead of zA in zF calculation |
res = (zA + val) + (zF & CZ80_CF); |
zF = SZXY[res & 0xFF] | // S/Z/X/Y flag |
((zA ^ res ^ val) & CZ80_HF) | // H flag |
(((val ^ zA ^ 0x80) & (val ^ res) & 0x80) >> 5) | // V flag |
((res >> 8) & CZ80_CF); // C flag |
zA = res; |
RET(4) |
|
// SUB |
|
OP_SUB_mIx: |
PRE_IO |
READ_BYTE(data->W + FETCH_BYTE_S, val) |
POST_IO |
CCnt -= 11; |
goto OP_SUB; |
|
OP(0xd6): // SUB A,n |
OP_SUB_imm: |
val = FETCH_BYTE; |
CCnt -= 3; |
goto OP_SUB; |
|
OP(0x96): // SUB (HL) |
/* OP_SUB_mHL: */ |
PRE_IO |
READ_BYTE(zHL, val) |
POST_IO |
CCnt -= 3; |
goto OP_SUB; |
|
OP_SUB_IxH: |
val = data->B.H; |
goto OP_SUB; |
|
OP_SUB_IxL: |
val = data->B.L; |
goto OP_SUB; |
|
OP(0x90): // SUB B |
OP(0x91): // SUB C |
OP(0x92): // SUB D |
OP(0x93): // SUB E |
OP(0x94): // SUB H |
OP(0x95): // SUB L |
OP(0x97): // SUB A |
OP_SUB_R: |
val = zR8(Opcode & 7); |
|
OP_SUB: |
// bench : maybe use src instead of zA in zF calculation |
res = zA - val; |
zF = SZXY[res & 0xFF] | // S/Z/X/Y flag |
((zA ^ res ^ val) & CZ80_HF) | // H flag |
(((val ^ zA) & (zA ^ res) & 0x80) >> 5) | // V flag |
((res >> 8) & CZ80_CF) | CZ80_NF; // C/N flag |
zA = res; |
RET(4) |
|
// SBC |
|
OP_SBC_mIx: |
PRE_IO |
READ_BYTE(data->W + FETCH_BYTE_S, val) |
POST_IO |
CCnt -= 11; |
goto OP_SBC; |
|
OP(0xde): // SBC A,n |
OP_SBC_imm: |
val = FETCH_BYTE; |
CCnt -= 3; |
goto OP_SBC; |
|
OP(0x9e): // SBC A,(HL) |
/* OP_SBC_mHL: */ |
PRE_IO |
READ_BYTE(zHL, val) |
POST_IO |
CCnt -= 3; |
goto OP_SBC; |
|
OP_SBC_IxH: |
val = data->B.H; |
goto OP_SBC; |
|
OP_SBC_IxL: |
val = data->B.L; |
goto OP_SBC; |
|
OP(0x98): // SBC A,B |
OP(0x99): // SBC A,C |
OP(0x9a): // SBC A,D |
OP(0x9b): // SBC A,E |
OP(0x9c): // SBC A,H |
OP(0x9d): // SBC A,L |
OP(0x9f): // SBC A,A |
OP_SBC_R: |
val = zR8(Opcode & 7); |
|
OP_SBC: |
// bench : maybe use src instead of zA in zF calculation |
res = zA - (val + (zF & CZ80_CF)); |
zF = SZXY[res & 0xFF] | // S/Z/X/Y flag |
((zA ^ res ^ val) & CZ80_HF) | // H flag |
(((val ^ zA) & (zA ^ res) & 0x80) >> 5) | // V flag |
((res >> 8) & CZ80_CF) | CZ80_NF; // C/N flag |
zA = res; |
RET(4) |
|
// CP |
|
OP_CP_mIx: |
PRE_IO |
READ_BYTE(data->W + FETCH_BYTE_S, val) |
POST_IO |
CCnt -= 11; |
goto OP_CP; |
|
OP(0xfe): // CP n |
OP_CP_imm: |
val = FETCH_BYTE; |
CCnt -= 3; |
goto OP_CP; |
|
OP(0xbe): // CP (HL) |
/* OP_CP_mHL: */ |
PRE_IO |
READ_BYTE(zHL, val) |
POST_IO |
CCnt -= 3; |
goto OP_CP; |
|
OP_CP_IxH: |
val = data->B.H; |
goto OP_CP; |
|
OP_CP_IxL: |
val = data->B.L; |
goto OP_CP; |
|
OP(0xb8): // CP B |
OP(0xb9): // CP C |
OP(0xba): // CP D |
OP(0xbb): // CP E |
OP(0xbc): // CP H |
OP(0xbd): // CP L |
OP(0xbf): // CP A |
OP_CP_R: |
val = zR8(Opcode & 7); |
|
OP_CP: |
// bench : maybe use src instead of zA in zF calculation |
res = zA - val; |
#if CZ80_DEBUG |
zF = SZXY[res & 0xFF] | // S/Z/X/Y flag |
((zA ^ res ^ val) & CZ80_HF) | // H flag |
(((val ^ zA) & (zA ^ res) & 0x80) >> 5) | // V flag |
((res >> 8) & CZ80_CF) | CZ80_NF; // C/N flag |
#else |
zF = (SZXY[res & 0xFF] & ~(CZ80_XF | CZ80_YF)) | // S/Z flag |
(val & (CZ80_XF | CZ80_YF)) | // X/Y flag |
((zA ^ res ^ val) & CZ80_HF) | // H flag |
(((val ^ zA) & (zA ^ res) & 0x80) >> 5) | // V flag |
((res >> 8) & CZ80_CF) | CZ80_NF; // C/N flag |
#endif |
RET(4) |
} |
|
// AND |
|
{ |
uint8_t val; |
|
OP(0xa6): // AND (HL) |
/* OP_AND_mHL: */ |
PRE_IO |
READ_BYTE(zHL, val) |
POST_IO |
goto OP_AND_; |
|
OP(0xe6): // AND A,n |
OP_AND_imm: |
val = FETCH_BYTE; |
|
OP_AND_: |
zA = zA & val; |
zF = SZXYP[zA] | CZ80_HF; |
RET(7) |
|
OP_AND_IxL: |
val = data->B.L; |
goto OP_AND; |
|
OP_AND_IxH: |
val = data->B.H; |
goto OP_AND; |
|
OP(0xa0): // AND B |
OP(0xa1): // AND C |
OP(0xa2): // AND D |
OP(0xa3): // AND E |
OP(0xa4): // AND H |
OP(0xa5): // AND L |
OP_AND_R: |
val = zR8(Opcode & 7); |
|
OP_AND: |
zA = zA & val; |
|
OP(0xa7): // AND A |
OP_AND_A: |
zF = SZXYP[zA] | CZ80_HF; |
RET(4) |
|
// XOR |
|
OP(0xae): // XOR (HL) |
/* OP_XOR_mHL: */ |
PRE_IO |
READ_BYTE(zHL, val) |
POST_IO |
goto OP_XOR_; |
|
OP(0xee): // XOR A,n |
OP_XOR_imm: |
val = FETCH_BYTE; |
|
OP_XOR_: |
zA = zA ^ val; |
zF = SZXYP[zA]; |
RET(7) |
|
OP_XOR_IxL: |
val = data->B.L; |
goto OP_XOR; |
|
OP_XOR_IxH: |
val = data->B.H; |
goto OP_XOR; |
|
OP(0xa8): // XOR B |
OP(0xa9): // XOR C |
OP(0xaa): // XOR D |
OP(0xab): // XOR E |
OP(0xac): // XOR H |
OP(0xad): // XOR L |
OP_XOR_R: |
val = zR8(Opcode & 7); |
|
OP_XOR: |
zA = zA ^ val; |
zF = SZXYP[zA]; |
RET(4) |
|
OP(0xaf): // XOR A |
OP_XOR_A: |
zA = 0; |
zF = SZXYP[zA]; |
RET(4) |
|
// OR |
|
OP(0xb6): // OR (HL) |
/* OP_OR_mHL: */ |
PRE_IO |
READ_BYTE(zHL, val) |
POST_IO |
goto OP_OR_; |
|
OP(0xf6): // OR A,n |
OP_OR_imm: |
val = FETCH_BYTE; |
|
OP_OR_: |
zA = zA | val; |
zF = SZXYP[zA]; |
RET(7) |
|
OP_OR_IxL: |
val = data->B.L; |
goto OP_OR; |
|
OP_OR_IxH: |
val = data->B.H; |
goto OP_OR; |
|
OP(0xb0): // OR B |
OP(0xb1): // OR C |
OP(0xb2): // OR D |
OP(0xb3): // OR E |
OP(0xb4): // OR H |
OP(0xb5): // OR L |
OP_OR_R: |
val = zR8(Opcode & 7); |
|
OP_OR: |
zA = zA | val; |
|
OP(0xb7): // OR A |
OP_OR_A: |
zF = SZXYP[zA]; |
RET(4) |
} |
|
|
// MISC ARITHMETIC & CPU CONTROL |
|
OP(0x27): // DAA |
OP_DAA: |
{ |
uint8_t _F; |
uint8_t cf, nf, hf, lo, hi, diff; |
|
_F = zF; |
cf = _F & CZ80_CF; |
nf = _F & CZ80_NF; |
hf = _F & CZ80_HF; |
lo = zA & 0x0F; |
hi = zA >> 4; |
|
if (cf) |
{ |
diff = (lo <= 9 && !hf) ? 0x60 : 0x66; |
} |
else |
{ |
if (lo >= 10) |
{ |
diff = hi <= 8 ? 0x06 : 0x66; |
} |
else |
{ |
if (hi >= 10) |
{ |
diff = hf ? 0x66 : 0x60; |
} |
else |
{ |
diff = hf ? 0x06 : 0x00; |
} |
} |
} |
if (nf) zA -= diff; |
else zA += diff; |
|
_F = SZXYP[zA] | (_F & CZ80_NF); |
if (cf || (lo <= 9 ? hi >= 10 : hi >= 9)) _F |= CZ80_CF; |
if (nf ? hf && lo <= 5 : lo >= 10) _F |= CZ80_HF; |
zF = _F; |
RET(4) |
} |
|
OP(0x2f): // CPL |
OP_CPL: |
zA ^= 0xFF; |
zF = (zF & (CZ80_SF | CZ80_ZF | CZ80_PF | CZ80_CF)) | |
CZ80_HF | CZ80_NF | |
(zA & (CZ80_XF | CZ80_YF)); |
RET(4) |
|
OP(0x37): // SCF |
OP_SCF: |
zF = (zF & (CZ80_SF | CZ80_ZF | CZ80_PF)) | |
(zA & (CZ80_XF | CZ80_YF)) | |
CZ80_CF; |
RET(4) |
|
OP(0x3f): // CCF |
OP_CCF: |
zF = ((zF & (CZ80_SF | CZ80_ZF | CZ80_PF | CZ80_CF)) | |
((zF & CZ80_CF) << 4) | |
(zA & (CZ80_XF | CZ80_YF))) ^ |
CZ80_CF; |
RET(4) |
|
OP(0x76): // HALT |
OP_HALT: |
// HALTED state |
CPU->Status |= CZ80_HALTED; |
// release remaining cycles... |
CCnt = 0; |
goto Cz80_Exec_Really_End; |
|
OP(0xf3): // DI |
OP_DI: |
zIFF = 0; |
#if CZ80_DEBUG |
RET(4) |
#else |
CCnt -= 4; |
// can't take interrupt after DI so we force next instruction execution |
goto Cz80_Exec; |
#endif |
|
OP(0xfb): // EI |
OP_EI: |
zIFF = CZ80_IFF | (CZ80_IFF << 8); |
#if CZ80_DEBUG |
RET(4) |
#else |
// release remaining cycles... |
CPU->CycleSup += CCnt - 4; |
CCnt = 0; |
// can't take interrupt after EI so we force next instruction execution |
goto Cz80_Exec; |
#endif |
|
// 16 BITS ARITHMETIC |
|
OP(0x03): // INC BC |
OP_INC_BC: |
zBC++; |
RET(6) |
|
OP(0x13): // INC DE |
OP_INC_DE: |
zDE++; |
RET(6) |
|
OP(0x23): // INC HL |
OP_INC_xx: |
data->W++; |
RET(6) |
|
OP(0x33): // INC SP |
OP_INC_SP: |
zSP++; |
RET(6) |
|
OP(0x0b): // DEC BC |
OP_DEC_BC: |
zBC--; |
RET(6) |
|
OP(0x1b): // DEC DE |
OP_DEC_DE: |
zDE--; |
RET(6) |
|
OP(0x2b): // DEC HL |
OP_DEC_xx: |
data->W--; |
RET(6) |
|
OP(0x3b): // DEC SP |
OP_DEC_SP: |
zSP--; |
RET(6) |
|
// ADD16 |
|
{ |
uint16_t src; |
uint32_t res; |
|
OP(0x39): // ADD xx,SP |
OP_ADD16_xx_SP: |
src = zSP; |
goto OP_ADD16; |
|
OP(0x29): // ADD xx,xx |
OP_ADD16_xx_xx: |
src = data->W; |
goto OP_ADD16; |
|
OP(0x09): // ADD xx,BC |
OP_ADD16_xx_BC: |
src = zBC; |
goto OP_ADD16; |
|
OP(0x19): // ADD xx,DE |
OP_ADD16_xx_DE: |
src = zDE; |
|
OP_ADD16: |
res = src + data->W; |
#if CZ80_DEBUG |
zF = (zF & (CZ80_SF | CZ80_ZF | CZ80_VF)) | // S/Z/V flag |
(((src ^ data->W ^ res) >> 8) & CZ80_HF) | // H flag |
((res >> 16) & CZ80_CF); // C flag |
#else |
zF = (zF & (CZ80_SF | CZ80_ZF | CZ80_VF)) | // S/Z/V flag |
(((src ^ data->W ^ res) >> 8) & CZ80_HF) | // H flag |
((res >> 8) & (CZ80_XF | CZ80_YF)) | // X/Y flag |
((res >> 16) & CZ80_CF); // C flag |
#endif |
data->W = res; |
RET(11) |
} |
|
// ROTATE |
|
{ |
uint8_t A; |
uint8_t F; |
|
OP(0x07): // RLCA |
OP_RLCA: |
A = zA; |
zA = (A << 1) | (A >> 7); |
zF = (zF & (CZ80_SF | CZ80_ZF | CZ80_PF)) | // S/Z/P flag |
(zA & (CZ80_XF | CZ80_YF | CZ80_CF)); // X/Y/C |
RET(4) |
|
OP(0x0f): // RRCA |
OP_RRCA: |
A = zA; |
zA = (A >> 1) | (A << 7); |
zF = (zF & (CZ80_SF | CZ80_ZF | CZ80_PF)) | // S/Z/P flag |
(zA & (CZ80_XF | CZ80_YF)) | // X/Y flag |
(A & CZ80_CF); // C flag |
RET(4) |
|
OP(0x17): // RLA |
OP_RLA: |
A = zA; |
F = zF; |
zA = (A << 1) | (F & CZ80_CF); |
zF = (F & (CZ80_SF | CZ80_ZF | CZ80_PF)) | // S/Z/P flag |
(zA & (CZ80_XF | CZ80_YF)) | // X/Y flag |
(A >> 7); // C flag |
RET(4) |
|
OP(0x1f): // RRA |
OP_RRA: |
A = zA; |
F = zF; |
zA = (A >> 1) | (F << 7); |
zF = (F & (CZ80_SF | CZ80_ZF | CZ80_PF)) | // S/Z/P flag |
(zA & (CZ80_XF | CZ80_YF)) | // X/Y flag |
(A & CZ80_CF); // C flag |
RET(4) |
} |
|
// JUMP |
|
OP(0xd2): // JP NC,nn |
OP_JP_NC: |
if (!(zF & CZ80_CF)) goto OP_JP; |
PC += 2; |
RET(10); |
|
OP(0xda): // JP C,nn |
OP_JP_C: |
if (zF & CZ80_CF) goto OP_JP; |
PC += 2; |
RET(10); |
|
OP(0xe2): // JP PO,nn |
OP_JP_PO: |
if (!(zF & CZ80_VF)) goto OP_JP; |
PC += 2; |
RET(10); |
|
OP(0xea): // JP PE,nn |
OP_JP_PE: |
if (zF & CZ80_VF) goto OP_JP; |
PC += 2; |
RET(10); |
|
OP(0xf2): // JP P,nn |
OP_JP_P: |
if (!(zF & CZ80_SF)) goto OP_JP; |
PC += 2; |
RET(10); |
|
OP(0xfa): // JP M,nn |
OP_JP_M: |
if (zF & CZ80_SF) goto OP_JP; |
PC += 2; |
RET(10); |
|
OP(0xca): // JP Z,nn |
OP_JP_Z: |
if (zF & CZ80_ZF) goto OP_JP; |
PC += 2; |
RET(10); |
|
OP(0xc2): // JP NZ,nn |
OP_JP_NZ: |
if (!(zF & CZ80_ZF)) goto OP_JP; |
PC += 2; |
RET(10); |
|
{ |
uint16_t newPC; |
|
OP(0xc3): // JP nn |
OP_JP: |
newPC = GET_WORD; |
SET_PC(newPC); |
RET(10) |
|
OP(0xe9): // JP (xx) |
OP_JP_xx: |
newPC = data->W; |
SET_PC(newPC); |
RET(4) |
} |
|
|
OP(0x38): // JR C,n |
OP_JR_C: |
if (zF & CZ80_CF) goto OP_JR; |
PC++; |
RET(7) |
|
OP(0x30): // JR NC,n |
OP_JR_NC: |
if (!(zF & CZ80_CF)) goto OP_JR; |
PC++; |
RET(7) |
|
OP(0x28): // JR Z,n |
OP_JR_Z: |
if (zF & CZ80_ZF) goto OP_JR; |
PC++; |
RET(7) |
|
OP(0x20): // JR NZ,n |
OP_JR_NZ: |
if (!(zF & CZ80_ZF)) goto OP_JR; |
PC++; |
RET(7) |
|
OP(0x10): // DJNZ n |
OP_DJNZ: |
CCnt--; |
if (--zB) goto OP_JR; |
PC++; |
RET(9) |
|
OP(0x18): // JR n |
OP_JR: |
{ |
uintptr_t adr; |
|
adr = FETCH_BYTE_S; |
// no rebase needed here... |
PC += adr; |
RET(12) |
} |
|
// CALL & RETURN |
|
OP(0xd4): // CALL NC,nn |
OP_CALL_NC: |
if (!(zF & CZ80_CF)) goto OP_CALL; |
PC += 2; |
RET(10) |
|
OP(0xdc): // CALL C,nn |
OP_CALL_C: |
if (zF & CZ80_CF) goto OP_CALL; |
PC += 2; |
RET(10) |
|
OP(0xe4): // CALL PO,nn |
OP_CALL_PO: |
if (!(zF & CZ80_VF)) goto OP_CALL; |
PC += 2; |
RET(10) |
|
OP(0xec): // CALL PE,nn |
OP_CALL_PE: |
if (zF & CZ80_VF) goto OP_CALL; |
PC += 2; |
RET(10) |
|
OP(0xf4): // CALL P,nn |
OP_CALL_P: |
if (!(zF & CZ80_SF)) goto OP_CALL; |
PC += 2; |
RET(10) |
|
OP(0xfc): // CALL M,nn |
OP_CALL_M: |
if (zF & CZ80_SF) goto OP_CALL; |
PC += 2; |
RET(10) |
|
OP(0xcc): // CALL Z,nn |
OP_CALL_Z: |
if (zF & CZ80_ZF) goto OP_CALL; |
PC += 2; |
RET(10) |
|
OP(0xc4): // CALL NZ,nn |
OP_CALL_NZ: |
if (!(zF & CZ80_ZF)) goto OP_CALL; |
PC += 2; |
RET(10) |
|
OP(0xcd): // CALL nn |
OP_CALL: |
{ |
uint16_t oldRPC; |
uint16_t newPC; |
|
PRE_IO |
FETCH_WORD(newPC); |
oldRPC = PC; |
PUSH_16(oldRPC); |
SET_PC(newPC); |
POST_IO |
RET(17) |
} |
|
OP(0xd0): // RET NC |
OP_RET_NC: |
if (!(zF & CZ80_CF)) goto OP_RET_COND; |
RET(5) |
|
OP(0xd8): // RET C |
OP_RET_C: |
if (zF & CZ80_CF) goto OP_RET_COND; |
RET(5) |
|
OP(0xe0): // RET PO |
OP_RET_PO: |
if (!(zF & CZ80_VF)) goto OP_RET_COND; |
RET(5) |
|
OP(0xe8): // RET PE |
OP_RET_PE: |
if (zF & CZ80_VF) goto OP_RET_COND; |
RET(5) |
|
OP(0xf0): // RET P |
OP_RET_P: |
if (!(zF & CZ80_SF)) goto OP_RET_COND; |
RET(5) |
|
OP(0xf8): // RET M |
OP_RET_M: |
if (zF & CZ80_SF) goto OP_RET_COND; |
RET(5) |
|
OP(0xc0): // RET NZ |
OP_RET_NZ: |
if (!(zF & CZ80_ZF)) goto OP_RET_COND; |
RET(5) |
|
OP(0xc8): // RET Z |
OP_RET_Z: |
if (zF & CZ80_ZF) goto OP_RET_COND; |
RET(5) |
|
OP_RET_COND: |
CCnt -= 7; |
|
OP(0xc9): // RET |
OP_RET: |
{ |
uint16_t newPC; |
|
PRE_IO |
POP_16(newPC); |
SET_PC(newPC); |
POST_IO |
RET(10) |
} |
|
|
OP(0xc7): // RST 0 |
OP(0xcf): // RST 1 |
OP(0xd7): // RST 2 |
OP(0xdf): // RST 3 |
OP(0xe7): // RST 4 |
OP(0xef): // RST 5 |
OP(0xf7): // RST 6 |
OP(0xff): // RST 7 |
OP_RST: |
{ |
uint16_t src; |
uint16_t newPC; |
|
src = PC; |
PUSH_16(src); |
newPC = Opcode & 0x38; |
SET_PC(newPC); |
RET(11) |
} |
|
// INPUT & OUTPUT |
|
{ |
uint16_t adr; |
|
OP(0xd3): // OUT (n),A |
OP_OUT_mN_A: |
adr = (zA << 8) | FETCH_BYTE; |
OUT(adr, zA) |
RET(11) |
|
OP(0xdb): // IN A,(n) |
OP_IN_A_mN: |
adr = (zA << 8) | FETCH_BYTE; |
IN(adr, zA) |
RET(11) |
} |
|
// PREFIXE |
|
OP(0xcb): // CB PREFIXE (BIT & SHIFT INSTRUCTIONS) |
/* CB_PREFIXE: */ |
Opcode = FETCH_BYTE; |
#include "cz80_opcb.inc" |
|
OP(0xed): // ED PREFIXE |
ED_PREFIXE: |
CCnt -= 4; |
Opcode = FETCH_BYTE; |
#include "cz80_oped.inc" |
|
OP(0xdd): // DD PREFIXE (IX) |
DD_PREFIXE: |
data = pzIX; |
goto XY_PREFIXE; |
|
OP(0xfd): // FD PREFIXE (IY) |
FD_PREFIXE: |
data = pzIY; |
|
XY_PREFIXE: |
CCnt -= 4; |
Opcode = FETCH_BYTE; |
#include "cz80_opxy.inc" |
|
#if CZ80_USE_JUMPTABLE |
#else |
} |
#endif |
|