/* -----------------------------------------------------------------------
*
* Z80C : Z80 Engine - GENERIC
*
* Copyright by Studio Milmake 1999-2000,2004
*
*------------------------------------------------------------------------ */
/* #define PCCOUNTER */
#if defined(TRACE) && defined(PCCOUNTER)
extern UINT pccnt;
extern UINT pccnt2;
extern UINT pccnt3;
extern UINT lastpc;
#endif
#define Z80_COUNT(clock) \
do { \
CPU_REMCLOCK -= (clock); \
} while (/*CONSTCOND*/ 0)
#if defined(TRACE) && defined(PCCOUNTER)
#define GET_PC_BYTE(b) \
do { \
if ((lastpc ^ R_Z80PC) & 0x8000) { \
TRACEOUT(("%.4x->%.4x", lastpc, R_Z80PC)); \
lastpc = R_Z80PC; \
pccnt2++; \
} \
pccnt++; \
(b) = mem_read8(R_Z80PC++); \
} while (/*CONSTCOND*/ 0)
#define GET_PC_WORD(w) \
do { \
pccnt3++; \
(w) = mem_read16(R_Z80PC); \
R_Z80PC += 2; \
} while (/*CONSTCOND*/ 0)
#else
#define GET_PC_BYTE(b) \
do { \
(b) = mem_read8(R_Z80PC++); \
} while (/*CONSTCOND*/ 0)
#define GET_PC_WORD(w) \
do { \
(w) = mem_read16(R_Z80PC); \
R_Z80PC += 2; \
} while (/*CONSTCOND*/ 0)
#endif
#define MCR_EX1(r1, r2) \
do { \
REG16 tmp; \
tmp = (r1); \
(r1) = (r2); \
(r2) = tmp; \
} while (/*CONSTCOND*/ 0)
#define JRBYFLAG(flg) \
do { \
if ((flg)) { \
SINT ofst; \
ofst = mem_read8s(R_Z80PC++); \
R_Z80PC += ofst; \
Z80_COUNT(5); \
} \
else { \
R_Z80PC++; \
} \
} while (/*CONSTCOND*/ 0)
#define LDW_w(reg) { \
(reg) = mem_read16(R_Z80PC); \
R_Z80PC += 2; \
}
#define LDx_B(dst, src) { \
mem_write8((dst), (src)); \
}
#define MCR_INC_W(reg) { \
(reg)++; \
}
#define MCR_INC(reg) { \
R_Z80F &= C_FLAG; \
R_Z80F |= z80inc_flag2[(reg)]; \
(reg)++; \
}
#define MCR_DEC(reg) { \
R_Z80F &= C_FLAG; \
R_Z80F |= z80dec_flag2[(reg)]; \
(reg)--; \
}
#define LDB_b(reg) { \
(reg) = mem_read8(R_Z80PC++); \
}
#define MCR_RLCA { \
REG8 tmp; \
tmp = (UINT8)(R_Z80A >> 7); \
R_Z80A = (R_Z80A << 1) | tmp; \
R_Z80F &= 0xec; \
R_Z80F |= tmp; \
}
#define MCR_EX(reg1, reg2) { \
MCR_EX1(reg1, reg2); \
}
#define MCR_ADD_W(dst, src) { \
UINT32 tmp; \
R_Z80F &= (S_FLAG | Z_FLAG | V_FLAG); \
tmp = (dst) + (src); \
R_Z80F |= (UINT8)(tmp >> 16); \
R_Z80F |= ((tmp ^ (dst) ^ (src)) >> 8) & H_FLAG; \
(dst) = (UINT16)tmp; \
}
#define LDB_x(b, w) { \
(b) = mem_read8((w)); \
}
#define MCR_DEC_W(reg) { \
(reg)--; \
}
#define MCR_RRCA { \
REG8 tmp; \
tmp = (UINT8)(R_Z80A & 1); \
R_Z80F &= 0xec; \
R_Z80F |= tmp; \
R_Z80A = (R_Z80A >> 1) | (tmp << 7); \
}
#define MCR_DJNZ { \
R_Z80B--; \
JRBYFLAG(R_Z80B); \
}
#define MCR_RLA { \
REG8 tmp; \
tmp = (UINT8)(R_Z80A >> 7); \
R_Z80A = (R_Z80A << 1) | (R_Z80F & 1); \
R_Z80F &= 0xec; \
R_Z80F |= tmp; \
}
#define MCR_JR { \
SINT ofst; \
ofst = mem_read8s(R_Z80PC++); \
R_Z80PC += ofst; \
Z80_COUNT(5); \
}
#define MCR_RRA { \
REG8 tmp; \
tmp = (UINT8)(R_Z80A & 1); \
R_Z80A = (R_Z80A >> 1) | (R_Z80F << 7); \
R_Z80F &= 0xec; \
R_Z80F |= tmp; \
}
#define MCR_JRNFLG(flg) { \
JRBYFLAG(!(R_Z80F & (flg))); \
}
#define LDx_W(reg) { \
UINT adrs; \
GET_PC_WORD(adrs); \
mem_write16(adrs, (reg)); \
}
#define MCR_DDA { \
SINT dst; \
REG8 flg; \
SINT alow; \
dst = R_Z80A; \
alow = R_Z80A & 0x0f; \
flg = R_Z80F & N_FLAG; \
if (!flg) { \
if (alow >= 10) { \
flg |= H_FLAG; \
dst += 6; \
} \
else if (R_Z80F & H_FLAG) { \
dst += 6; \
} \
if ((dst >= 0xa0) || (R_Z80F & C_FLAG)) { \
flg |= C_FLAG; \
dst += 0x60; \
} \
} \
else { \
if ((dst > 0x99) || (R_Z80F & C_FLAG)) { \
dst -= 0x60; \
flg |= C_FLAG; \
} \
if ((alow > 9) || (R_Z80F & H_FLAG)) { \
if (alow < 6) { \
flg |= H_FLAG; \
} \
dst -= 6; \
if ((dst < 0) && (!(R_Z80F & H_FLAG))) { \
flg |= C_FLAG; \
} \
} \
} \
R_Z80A = (UINT8)dst; \
R_Z80F = flg | z80szp_flag[dst & 0xff]; \
}
#define MCR_JRFLG(flg) { \
JRBYFLAG(R_Z80F & (flg)); \
}
#define MCR_ADDx2(reg) { \
R_Z80F &= (S_FLAG | Z_FLAG | V_FLAG); \
R_Z80F |= (UINT8)((reg) >> 15); \
(reg) <<= 1; \
R_Z80F |= ((reg) >> 8) & H_FLAG; \
}
#define LDW_x(reg) { \
UINT adrs; \
GET_PC_WORD(adrs); \
(reg) = mem_read16(adrs); \
}
#define MCR_CPL { \
R_Z80A = (UINT8)(~R_Z80A); \
R_Z80F |= (H_FLAG | N_FLAG); \
}
#define LDB_x_a { \
UINT adrs; \
GET_PC_WORD(adrs); \
mem_write8(adrs, R_Z80A); \
}
#define MCR_INC_MEM(adrs) { \
REG8 tmp; \
tmp = mem_read8((adrs)); \
R_Z80F &= C_FLAG; \
R_Z80F |= z80inc_flag2[tmp]; \
mem_write8((adrs), (REG8)(tmp + 1)); \
}
#define MCR_DEC_MEM(adrs) { \
REG8 tmp; \
tmp = mem_read8((adrs)); \
R_Z80F &= C_FLAG; \
R_Z80F |= z80dec_flag2[tmp]; \
mem_write8((adrs), (REG8)(tmp - 1)); \
}
#define LDB_xhl_b { \
REG8 tmp; \
GET_PC_BYTE(tmp); \
mem_write8(R_Z80HL, tmp); \
}
#define MCR_SCF { \
R_Z80F &= ~(H_FLAG | N_FLAG); \
R_Z80F |= C_FLAG; \
}
#define LDB_a_x { \
UINT adrs; \
GET_PC_WORD(adrs); \
R_Z80A = mem_read8(adrs); \
}
#define MCR_CCF { \
R_Z80F &= ~(H_FLAG | N_FLAG); \
if (R_Z80F & C_FLAG) { \
R_Z80F |= H_FLAG; \
} \
R_Z80F ^= C_FLAG; \
}
#define MCR_LD(d, s) { \
(d) = (s); \
}
#define MCR_HALT { \
R_Z80PC--; \
Z80_IFF |= (1 << IFF_HALT); \
CPU_REMCLOCK = 0; \
}
#define MCR_ADD(b) { \
UINT res; \
res = R_Z80A + (b); \
R_Z80F = z80szc_flag[res & 0x1ff]; \
R_Z80F |= (res ^ R_Z80A ^ (b)) & H_FLAG; \
R_Z80F |= (((res ^ R_Z80A) & (res ^ (b))) >> 5) & V_FLAG; \
R_Z80A = (UINT8)res; \
}
#define MCR_ADD_XHL { \
REG8 tmp; \
tmp = mem_read8(R_Z80HL); \
MCR_ADD(tmp) \
}
#define MCR_ADC(b) { \
UINT res; \
res = R_Z80A + (b) + (R_Z80F & 1); \
R_Z80F = z80szc_flag[res & 0x1ff]; \
R_Z80F |= (res ^ R_Z80A ^ (b)) & H_FLAG; \
R_Z80F |= (((res ^ R_Z80A) & (res ^ (b))) >> 5) & V_FLAG; \
R_Z80A = (UINT8)res; \
}
#define MCR_ADC_XHL { \
REG8 tmp; \
tmp = mem_read8(R_Z80HL); \
MCR_ADC(tmp) \
}
#define MCR_SUB(b) { \
UINT res; \
res = R_Z80A - (b); \
R_Z80F = z80szc_flag[res & 0x1ff] | N_FLAG; \
R_Z80F |= (res ^ R_Z80A ^ (b)) & H_FLAG; \
R_Z80F |= (((R_Z80A ^ res) & (R_Z80A ^ (b))) >> 5) & V_FLAG; \
R_Z80A = (UINT8)res; \
}
#define MCR_SUB_XHL { \
REG8 tmp; \
tmp = mem_read8(R_Z80HL); \
MCR_SUB(tmp) \
}
#define MCR_SBC(b) { \
UINT res; \
res = R_Z80A - (b) - (R_Z80F & 1); \
R_Z80F = z80szc_flag[res & 0x1ff] | N_FLAG; \
R_Z80F |= (res ^ R_Z80A ^ (b)) & H_FLAG; \
R_Z80F |= (((R_Z80A ^ res) & (R_Z80A ^ (b))) >> 5) & V_FLAG; \
R_Z80A = (UINT8)res; \
}
#define MCR_SBC_XHL { \
REG8 tmp; \
tmp = mem_read8(R_Z80HL); \
MCR_SBC(tmp) \
}
#define MCR_AND(b) { \
R_Z80A &= (b); \
R_Z80F = z80szp_flag[R_Z80A]; \
}
#define MCR_AND_XHL { \
REG8 tmp; \
tmp = mem_read8(R_Z80HL); \
MCR_AND(tmp) \
}
#define MCR_XOR(b) { \
R_Z80A ^= (b); \
R_Z80F = z80szp_flag[R_Z80A]; \
}
#define MCR_XOR_XHL { \
REG8 tmp; \
tmp = mem_read8(R_Z80HL); \
MCR_XOR(tmp) \
}
#define MCR_OR(b) { \
R_Z80A |= (b); \
R_Z80F = z80szp_flag[R_Z80A]; \
}
#define MCR_OR_XHL { \
REG8 tmp; \
tmp = mem_read8(R_Z80HL); \
MCR_OR(tmp) \
}
#define MCR_CP(b) { \
UINT res; \
res = R_Z80A - (b); \
R_Z80F = z80szc_flag[res & 0x1ff] | N_FLAG; \
R_Z80F |= (res ^ R_Z80A ^ (b)) & H_FLAG; \
R_Z80F |= (((R_Z80A ^ res) & (R_Z80A ^ (b))) >> 5) & V_FLAG; \
}
#define MCR_CP_XHL { \
REG8 tmp; \
tmp = mem_read8(R_Z80HL); \
MCR_CP(tmp) \
}
#define MCR_RETNFLG(flg) { \
if (!(R_Z80F & (flg))) { \
R_Z80PC = mem_read16(R_Z80SP); \
R_Z80SP += 2; \
Z80_COUNT(6); \
} \
}
#define MCR_POP(reg) { \
(reg) = mem_read16(R_Z80SP); \
R_Z80SP += 2; \
}
#define MCR_JPNFLG(flg) { \
if (!(R_Z80F & (flg))) { \
R_Z80PC = mem_read16(R_Z80PC); \
} \
else { \
R_Z80PC += 2; \
} \
}
#define MCR_JP { \
R_Z80PC = mem_read16(R_Z80PC); \
}
#define MCR_CALLNFLG(flg) { \
if (!(R_Z80F & (flg))) { \
REG16 tmp; \
GET_PC_WORD(tmp); \
R_Z80SP -= 2; \
mem_write16(R_Z80SP, R_Z80PC); \
R_Z80PC = tmp; \
Z80_COUNT(7); \
} \
else { \
R_Z80PC += 2; \
} \
}
#define MCR_PUSH(reg) { \
R_Z80SP -= 2; \
mem_write16(R_Z80SP, (reg)); \
}
#define MCR_ADD_BYTE { \
REG8 tmp; \
GET_PC_BYTE(tmp); \
MCR_ADD(tmp) \
}
#define MCR_RST(vect) { \
R_Z80SP -= 2; \
mem_write16(R_Z80SP, R_Z80PC); \
R_Z80PC = (vect); \
}
#define MCR_RETFLG(flg) { \
if (R_Z80F & (flg)) { \
R_Z80PC = mem_read16(R_Z80SP); \
R_Z80SP += 2; \
Z80_COUNT(6); \
} \
}
#define MCR_RET { \
R_Z80PC = mem_read16(R_Z80SP); \
R_Z80SP += 2; \
Z80_COUNT(6); \
}
#define MCR_JPFLG(flg) { \
if (R_Z80F & (flg)) { \
R_Z80PC = mem_read16(R_Z80PC); \
} \
else { \
R_Z80PC += 2; \
} \
}
#define MCR_CALLFLG(flg) { \
if (R_Z80F & (flg)) { \
REG16 tmp; \
GET_PC_WORD(tmp); \
R_Z80SP -= 2; \
mem_write16(R_Z80SP, R_Z80PC); \
R_Z80PC = tmp; \
Z80_COUNT(7); \
} \
else { \
R_Z80PC += 2; \
} \
}
#define MCR_CALL { \
REG16 tmp; \
GET_PC_WORD(tmp); \
R_Z80SP -= 2; \
mem_write16(R_Z80SP, R_Z80PC); \
R_Z80PC = tmp; \
Z80_COUNT(7); \
}
#define MCR_ADC_BYTE { \
REG8 tmp; \
GET_PC_BYTE(tmp); \
MCR_ADC(tmp) \
}
#define MCR_OUT_BYTE { \
REG8 tmp; \
GET_PC_BYTE(tmp); \
iocore_out((R_Z80A << 8) + tmp, tmp); \
}
#define MCR_SUB_BYTE { \
REG8 tmp; \
GET_PC_BYTE(tmp); \
MCR_SUB(tmp) \
}
#define MCR_EXX { \
MCR_EX(R_Z80BC, R_Z80BC2) \
MCR_EX(R_Z80DE, R_Z80DE2) \
MCR_EX(R_Z80HL, R_Z80HL2) \
}
#define MCR_IN_BYTE { \
REG8 tmp; \
GET_PC_BYTE(tmp); \
R_Z80A = iocore_inp((R_Z80A << 8) | tmp); \
}
#define MCR_SBC_BYTE { \
REG8 tmp; \
GET_PC_BYTE(tmp); \
MCR_SBC(tmp) \
}
#define MCR_EX_XSP(reg) { \
REG16 tmp; \
tmp = mem_read16(R_Z80SP); \
mem_write16(R_Z80SP, (reg)); \
(reg) = tmp; \
}
#define MCR_AND_BYTE { \
REG8 tmp; \
GET_PC_BYTE(tmp); \
MCR_AND(tmp) \
}
#define MCR_LD_W(dst, src) { \
(dst) = (src); \
}
#define MCR_XOR_BYTE { \
REG8 tmp; \
GET_PC_BYTE(tmp); \
MCR_XOR(tmp) \
}
#define MCR_DI { \
Z80_IFF |= (1 << IFF_IFLAG); \
}
#define MCR_OR_BYTE { \
REG8 tmp; \
GET_PC_BYTE(tmp); \
MCR_OR(tmp) \
}
#define MCR_EI { \
REG8 iff; \
SINT32 rem; \
iff = Z80_IFF; \
if (iff & (1 << IFF_IFLAG)) { \
Z80_IFF = (UINT8)(iff & (~(1 << IFF_IFLAG))); \
rem = CPU_REMCLOCK - 1; \
if ((rem < 0) || \
((!(iff & (1 << IFF_NMI))) && (CPU_REQIRQ != 0))) { \
CPU_BASECLOCK -= rem; \
CPU_REMCLOCK = 1; \
} \
} \
}
#define MCR_CP_BYTE { \
REG8 tmp; \
GET_PC_BYTE(tmp); \
MCR_CP(tmp) \
}
RetroPC.NET-CVS <cvs@retropc.net>