16#pragma GCC optimize ("O2")
89#define Z80_READ_BYTE(address, x) \
91 (x) = (m_readByte(m_context, (address) & 0xffff)); \
94#define Z80_FETCH_BYTE(address, x) Z80_READ_BYTE((address), (x))
96#define Z80_READ_WORD(address, x) \
98 (x) = (m_readByte(m_context, (address) & 0xffff) | (m_readByte(m_context, ((address) + 1) & 0xffff) << 8)); \
101#define Z80_FETCH_WORD(address, x) Z80_READ_WORD((address), (x))
103#define Z80_WRITE_BYTE(address, x) \
105 m_writeByte(m_context, (address) & 0xffff, (x)); \
108#define Z80_WRITE_WORD(address, x) \
110 m_writeByte(m_context, (address) & 0xffff, (x)); \
111 m_writeByte(m_context, ((address) + 1) & 0xffff, (x) >> 8); \
114#define Z80_READ_WORD_INTERRUPT(address, x) Z80_READ_WORD((address), (x))
116#define Z80_WRITE_WORD_INTERRUPT(address, x) Z80_WRITE_WORD((address), (x))
118#define Z80_INPUT_BYTE(port, x) \
120 (x) = m_readIO(m_context, (port)); \
123#define Z80_OUTPUT_BYTE(port, x) \
125 m_writeIO(m_context, (port), (x)); \
137#define OPCODE_LD_A_I 0x57
138#define OPCODE_LD_I_A 0x47
140#define OPCODE_LDI 0xa0
141#define OPCODE_LDIR 0xb0
142#define OPCODE_CPI 0xa1
143#define OPCODE_CPIR 0xb1
145#define OPCODE_RLD 0x6f
147#if defined(Z80_CATCH_RETI) && defined(Z80_CATCH_RETN)
148# define OPCODE_RETI 0x4d
151#define OPCODE_INI 0xa2
152#define OPCODE_INIR 0xb2
153#define OPCODE_OUTI 0xa3
154#define OPCODE_OTIR 0xb3
370#define SZC_FLAGS (Z80_S_FLAG | Z80_Z_FLAG | Z80_C_FLAG)
371#define YX_FLAGS (Z80_Y_FLAG | Z80_X_FLAG)
372#define SZ_FLAGS (Z80_S_FLAG | Z80_Z_FLAG)
373#define SZPV_FLAGS (Z80_S_FLAG | Z80_Z_FLAG | Z80_PV_FLAG)
374#define SYX_FLAGS (Z80_S_FLAG | Z80_Y_FLAG | Z80_X_FLAG)
375#define HC_FLAGS (Z80_H_FLAG | Z80_C_FLAG)
377#define A (state.registers.byte[Z80_A])
378#define F (state.registers.byte[Z80_F])
379#define B (state.registers.byte[Z80_B])
380#define C (state.registers.byte[Z80_C])
382#define AF (state.registers.word[Z80_AF])
383#define BC (state.registers.word[Z80_BC])
384#define DE (state.registers.word[Z80_DE])
385#define HL (state.registers.word[Z80_HL])
386#define SP (state.registers.word[Z80_SP])
388#define HL_IX_IY *((unsigned short *) registers[6])
394#define Y(opcode) (((opcode) >> 3) & 0x07)
395#define Z(opcode) ((opcode) & 0x07)
396#define P(opcode) (((opcode) >> 4) & 0x03)
397#define Q(opcode) (((opcode) >> 3) & 0x03)
403#define R(r) *((unsigned char *) (registers[(r)]))
404#define S(s) *((unsigned char *) state.register_table[(s)])
405#define RR(rr) *((unsigned short *) registers[(rr) + 8])
406#define SS(ss) *((unsigned short *) registers[(ss) + 12])
407#define CC(cc) ((F ^ XOR_CONDITION_TABLE[(cc)]) \
408& AND_CONDITION_TABLE[(cc)])
415Z80_FETCH_BYTE(pc, (n)); \
417elapsed_cycles += 3; \
422Z80_FETCH_WORD(pc, (nn)); \
424elapsed_cycles += 6; \
429Z80_FETCH_BYTE(pc, (d)); \
430(d) = (signed char) (d); \
432elapsed_cycles += 3; \
437#define READ_BYTE(address, x) \
439Z80_READ_BYTE((address), (x)); \
440elapsed_cycles += 3; \
443#define WRITE_BYTE(address, x) \
445Z80_WRITE_BYTE((address), (x)); \
446elapsed_cycles += 3; \
449#define READ_WORD(address, x) \
451Z80_READ_WORD((address), (x)); \
452elapsed_cycles += 6; \
455#define WRITE_WORD(address, x) \
457Z80_WRITE_WORD((address), (x)); \
458elapsed_cycles += 6; \
465#define READ_INDIRECT_HL(x) \
467if (registers == state.register_table) { \
479elapsed_cycles += 5; \
484#define WRITE_INDIRECT_HL(x) \
486if (registers == state.register_table) { \
488WRITE_BYTE(HL, (x)); \
498elapsed_cycles += 5; \
508WRITE_WORD(SP, (x)); \
519#define EXCHANGE(a, b) \
539f |= SZYX_FLAGS_TABLE[z & 0xff]; \
540f |= OVERFLOW_TABLE[c >> 7]; \
541f |= z >> (8 - Z80_C_FLAG_SHIFT); \
552z = a + (x) + (F & Z80_C_FLAG); \
556f |= SZYX_FLAGS_TABLE[z & 0xff]; \
557f |= OVERFLOW_TABLE[c >> 7]; \
558f |= z >> (8 - Z80_C_FLAG_SHIFT); \
572f = Z80_N_FLAG | (c & Z80_H_FLAG); \
573f |= SZYX_FLAGS_TABLE[z & 0xff]; \
575f |= OVERFLOW_TABLE[c >> 7]; \
576f |= c >> (8 - Z80_C_FLAG_SHIFT); \
587z = a - (x) - (F & Z80_C_FLAG); \
590f = Z80_N_FLAG | (c & Z80_H_FLAG); \
591f |= SZYX_FLAGS_TABLE[z & 0xff]; \
593f |= OVERFLOW_TABLE[c >> 7]; \
594f |= c >> (8 - Z80_C_FLAG_SHIFT); \
602F = SZYXP_FLAGS_TABLE[A &= (x)] | Z80_H_FLAG; \
607F = SZYXP_FLAGS_TABLE[A |= (x)]; \
612F = SZYXP_FLAGS_TABLE[A ^= (x)]; \
623f = Z80_N_FLAG | (c & Z80_H_FLAG); \
624f |= SZYX_FLAGS_TABLE[z & 0xff] & SZ_FLAGS; \
625f |= (x) & YX_FLAGS; \
627f |= OVERFLOW_TABLE[c >> 7]; \
628f |= c >> (8 - Z80_C_FLAG_SHIFT); \
641f |= c & Z80_H_FLAG; \
642f |= SZYX_FLAGS_TABLE[z & 0xff]; \
643f |= OVERFLOW_TABLE[(c >> 7) & 0x03]; \
656f = Z80_N_FLAG | (F & Z80_C_FLAG); \
657f |= c & Z80_H_FLAG; \
658f |= SZYX_FLAGS_TABLE[z & 0xff]; \
659f |= OVERFLOW_TABLE[(c >> 7) & 0x03]; \
672(x) = ((x) << 1) | c; \
673F = SZYXP_FLAGS_TABLE[(x) & 0xff] | c; \
681(x) = ((x) << 1) | (F & Z80_C_FLAG); \
682F = SZYXP_FLAGS_TABLE[(x) & 0xff] | c; \
690(x) = ((x) >> 1) | (c << 7); \
691F = SZYXP_FLAGS_TABLE[(x) & 0xff] | c; \
694#define RR_INSTRUCTION(x) \
699(x) = ((x) >> 1) | ((F & Z80_C_FLAG) << 7); \
700F = SZYXP_FLAGS_TABLE[(x) & 0xff] | c; \
709F = SZYXP_FLAGS_TABLE[(x) & 0xff] | c; \
717(x) = ((x) << 1) | 0x01; \
718F = SZYXP_FLAGS_TABLE[(x) & 0xff] | c; \
726(x) = ((signed char) (x)) >> 1; \
727F = SZYXP_FLAGS_TABLE[(x) & 0xff] | c; \
736F = SZYXP_FLAGS_TABLE[(x) & 0xff] | c; \
745static const unsigned char INSTRUCTION_TABLE[256] = {
1038static const unsigned char CB_INSTRUCTION_TABLE[256] = {
1331static const unsigned char ED_INSTRUCTION_TABLE[256] = {
1623static const unsigned char SZYX_FLAGS_TABLE[256] = {
1625 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1626 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
1627 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1628 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
1629 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1630 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
1631 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1632 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
1633 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1634 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
1635 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1636 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
1637 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1638 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
1639 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1640 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
1641 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
1642 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
1643 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
1644 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
1645 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
1646 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
1647 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
1648 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
1649 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
1650 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
1651 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
1652 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
1653 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
1654 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
1655 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
1656 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
1660static const unsigned char SZYXP_FLAGS_TABLE[256] = {
1662 0x44, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00,
1663 0x08, 0x0c, 0x0c, 0x08, 0x0c, 0x08, 0x08, 0x0c,
1664 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04,
1665 0x0c, 0x08, 0x08, 0x0c, 0x08, 0x0c, 0x0c, 0x08,
1666 0x20, 0x24, 0x24, 0x20, 0x24, 0x20, 0x20, 0x24,
1667 0x2c, 0x28, 0x28, 0x2c, 0x28, 0x2c, 0x2c, 0x28,
1668 0x24, 0x20, 0x20, 0x24, 0x20, 0x24, 0x24, 0x20,
1669 0x28, 0x2c, 0x2c, 0x28, 0x2c, 0x28, 0x28, 0x2c,
1670 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04,
1671 0x0c, 0x08, 0x08, 0x0c, 0x08, 0x0c, 0x0c, 0x08,
1672 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00,
1673 0x08, 0x0c, 0x0c, 0x08, 0x0c, 0x08, 0x08, 0x0c,
1674 0x24, 0x20, 0x20, 0x24, 0x20, 0x24, 0x24, 0x20,
1675 0x28, 0x2c, 0x2c, 0x28, 0x2c, 0x28, 0x28, 0x2c,
1676 0x20, 0x24, 0x24, 0x20, 0x24, 0x20, 0x20, 0x24,
1677 0x2c, 0x28, 0x28, 0x2c, 0x28, 0x2c, 0x2c, 0x28,
1678 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84,
1679 0x8c, 0x88, 0x88, 0x8c, 0x88, 0x8c, 0x8c, 0x88,
1680 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80,
1681 0x88, 0x8c, 0x8c, 0x88, 0x8c, 0x88, 0x88, 0x8c,
1682 0xa4, 0xa0, 0xa0, 0xa4, 0xa0, 0xa4, 0xa4, 0xa0,
1683 0xa8, 0xac, 0xac, 0xa8, 0xac, 0xa8, 0xa8, 0xac,
1684 0xa0, 0xa4, 0xa4, 0xa0, 0xa4, 0xa0, 0xa0, 0xa4,
1685 0xac, 0xa8, 0xa8, 0xac, 0xa8, 0xac, 0xac, 0xa8,
1686 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80,
1687 0x88, 0x8c, 0x8c, 0x88, 0x8c, 0x88, 0x88, 0x8c,
1688 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84,
1689 0x8c, 0x88, 0x88, 0x8c, 0x88, 0x8c, 0x8c, 0x88,
1690 0xa0, 0xa4, 0xa4, 0xa0, 0xa4, 0xa0, 0xa0, 0xa4,
1691 0xac, 0xa8, 0xa8, 0xac, 0xa8, 0xac, 0xac, 0xa8,
1692 0xa4, 0xa0, 0xa0, 0xa4, 0xa0, 0xa4, 0xa4, 0xa0,
1693 0xa8, 0xac, 0xac, 0xa8, 0xac, 0xa8, 0xa8, 0xac,
1704#define INDIRECT_HL 0x06
1711static const int XOR_CONDITION_TABLE[8] = {
1723static const int AND_CONDITION_TABLE[8] = {
1737static const int RST_TABLE[8] = {
1753static const int OVERFLOW_TABLE[4] = {
1768 state.i = state.pc = state.iff1 = state.iff2 = 0;
1769 state.im = Z80_INTERRUPT_MODE_0;
1779 state.register_table[0] = &state.registers.byte[Z80_B];
1780 state.register_table[1] = &state.registers.byte[Z80_C];
1781 state.register_table[2] = &state.registers.byte[Z80_D];
1782 state.register_table[3] = &state.registers.byte[Z80_E];
1783 state.register_table[4] = &state.registers.byte[Z80_H];
1784 state.register_table[5] = &state.registers.byte[Z80_L];
1790 state.register_table[6] = &state.registers.word[Z80_HL];
1791 state.register_table[7] = &state.registers.byte[Z80_A];
1795 state.register_table[8] = &state.registers.word[Z80_BC];
1796 state.register_table[9] = &state.registers.word[Z80_DE];
1797 state.register_table[10] = &state.registers.word[Z80_HL];
1798 state.register_table[11] = &state.registers.word[Z80_SP];
1804 state.register_table[12] = &state.registers.word[Z80_BC];
1805 state.register_table[13] = &state.registers.word[Z80_DE];
1806 state.register_table[14] = &state.registers.word[Z80_HL];
1807 state.register_table[15] = &state.registers.word[Z80_AF];
1811 for (
int i = 0; i < 16; i++)
1812 state.dd_register_table[i] = state.fd_register_table[i] = state.register_table[i];
1814 state.dd_register_table[4] = &state.registers.byte[Z80_IXH];
1815 state.dd_register_table[5] = &state.registers.byte[Z80_IXL];
1816 state.dd_register_table[6] = &state.registers.word[Z80_IX];
1817 state.dd_register_table[10] = &state.registers.word[Z80_IX];
1818 state.dd_register_table[14] = &state.registers.word[Z80_IX];
1820 state.fd_register_table[4] = &state.registers.byte[Z80_IYH];
1821 state.fd_register_table[5] = &state.registers.byte[Z80_IYL];
1822 state.fd_register_table[6] = &state.registers.word[Z80_IY];
1823 state.fd_register_table[10] = &state.registers.word[Z80_IY];
1824 state.fd_register_table[14] = &state.registers.word[Z80_IY];
1829int Z80::IRQ(
int data_on_bus)
1834 state.iff1 = state.iff2 = 0;
1835 state.r = (state.r & 0x80) | ((state.r + 1) & 0x7f);
1838 case Z80_INTERRUPT_MODE_0: {
1845 return intemulate(data_on_bus, 2);
1849 case Z80_INTERRUPT_MODE_1: {
1855 Z80_WRITE_WORD_INTERRUPT(SP, state.pc);
1857 return elapsed_cycles + 13;
1861 case Z80_INTERRUPT_MODE_2:
1864 int elapsed_cycles, vector;
1868 Z80_WRITE_WORD_INTERRUPT(SP, state.pc);
1869 vector = state.i << 8 | data_on_bus;
1871#ifdef Z80_MASK_IM2_VECTOR_ADDRESS
1877 Z80_READ_WORD_INTERRUPT(vector, state.pc);
1878 return elapsed_cycles + 19;
1896 state.iff2 = state.iff1;
1898 state.r = (state.r & 0x80) | ((state.r + 1) & 0x7f);
1902 Z80_WRITE_WORD_INTERRUPT(SP, state.pc);
1905 return elapsed_cycles + 11;
1912 int elapsed_cycles = 0;
1915 Z80_FETCH_BYTE(pc, opcode);
1918 return intemulate(opcode, elapsed_cycles);
1926int Z80::intemulate(
int opcode,
int elapsed_cycles)
1929 int r = state.r & 0x7f;
1931 void * * registers = state.register_table;
1933 int instruction = INSTRUCTION_TABLE[opcode];
1941 elapsed_cycles += 4;
1943 switch (instruction) {
1949 R(
Y(opcode)) =
R(Z(opcode));
1956 READ_N(
R(
Y(opcode)));
1961 case LD_R_INDIRECT_HL: {
1963 if (registers == state.register_table) {
1965 READ_BYTE(HL,
R(
Y(opcode)));
1973 READ_BYTE(d, S(
Y(opcode)));
1975 elapsed_cycles += 5;
1982 case LD_INDIRECT_HL_R: {
1984 if (registers == state.register_table) {
1986 WRITE_BYTE(HL,
R(Z(opcode)));
1994 WRITE_BYTE(d, S(Z(opcode)));
1996 elapsed_cycles += 5;
2003 case LD_INDIRECT_HL_N: {
2007 if (registers == state.register_table) {
2021 elapsed_cycles += 2;
2029 case LD_A_INDIRECT_BC: {
2036 case LD_A_INDIRECT_DE: {
2043 case LD_A_INDIRECT_NN: {
2053 case LD_INDIRECT_BC_A: {
2060 case LD_INDIRECT_DE_A: {
2067 case LD_INDIRECT_NN_A: {
2077 case LD_A_I_LD_A_R: {
2081 a = opcode == OPCODE_LD_A_I
2083 : (state.r & 0x80) | (r & 0x7f);
2084 f = SZYX_FLAGS_TABLE[a];
2092 f |= state.iff2 << Z80_P_FLAG_SHIFT;
2093 f |= F & Z80_C_FLAG;
2103 case LD_I_A_LD_R_A: {
2105 if (opcode == OPCODE_LD_I_A)
2126 READ_NN(RR(P(opcode)));
2131 case LD_HL_INDIRECT_NN: {
2136 READ_WORD(nn, HL_IX_IY);
2141 case LD_RR_INDIRECT_NN: {
2146 READ_WORD(nn, RR(P(opcode)));
2151 case LD_INDIRECT_NN_HL: {
2156 WRITE_WORD(nn, HL_IX_IY);
2161 case LD_INDIRECT_NN_RR: {
2166 WRITE_WORD(nn, RR(P(opcode)));
2174 elapsed_cycles += 2;
2181 PUSH(SS(P(opcode)));
2203 case EX_AF_AF_PRIME: {
2205 EXCHANGE(AF, state.alternates[Z80_AF]);
2212 EXCHANGE(BC, state.alternates[Z80_BC]);
2213 EXCHANGE(DE, state.alternates[Z80_DE]);
2214 EXCHANGE(HL, state.alternates[Z80_HL]);
2219 case EX_INDIRECT_SP_HL: {
2224 WRITE_WORD(SP, HL_IX_IY);
2227 elapsed_cycles += 3;
2240 f |= --BC ? Z80_P_FLAG : 0;
2242 #ifndef Z80_DOCUMENTED_FLAGS_ONLY
2245 f |= n & Z80_X_FLAG;
2246 f |= (n << (Z80_Y_FLAG_SHIFT - 1))
2253 d = opcode == OPCODE_LDI ? +1 : -1;
2257 elapsed_cycles += 2;
2265 int d, f, bc, de, hl, n;
2267 #ifdef Z80_HANDLE_SELF_MODIFYING_CODE
2271 p = (pc - 2) & 0xffff;
2272 q = (pc - 1) & 0xffff;
2276 d = opcode == OPCODE_LDIR ? +1 : -1;
2284 elapsed_cycles -= 8;
2289 Z80_READ_BYTE(hl, n);
2290 Z80_WRITE_BYTE(de, n);
2297 elapsed_cycles += 21;
2301 elapsed_cycles += 16;
2306 #ifdef Z80_HANDLE_SELF_MODIFYING_CODE
2308 if (((de - d) & 0xffff) == p
2309 || ((de - d) & 0xffff) == q) {
2329 #ifndef Z80_DOCUMENTED_FLAGS_ONLY
2332 f |= n & Z80_X_FLAG;
2333 f |= (n << (Z80_Y_FLAG_SHIFT - 1))
2352 HL += opcode == OPCODE_CPI ? +1 : -1;
2354 f = (a ^ n ^ z) & Z80_H_FLAG;
2356 #ifndef Z80_DOCUMENTED_FLAGS_ONLY
2358 n = z - (f >> Z80_H_FLAG_SHIFT);
2359 f |= (n << (Z80_Y_FLAG_SHIFT - 1))
2361 f |= n & Z80_X_FLAG;
2365 f |= SZYX_FLAGS_TABLE[z & 0xff] & SZ_FLAGS;
2366 f |= --BC ? Z80_P_FLAG : 0;
2367 F = f | Z80_N_FLAG | (F & Z80_C_FLAG);
2369 elapsed_cycles += 5;
2377 int d, a, bc, hl, n, z, f;
2379 d = opcode == OPCODE_CPIR ? +1 : -1;
2386 elapsed_cycles -= 8;
2391 Z80_READ_BYTE(hl, n);
2397 elapsed_cycles += 21;
2401 elapsed_cycles += 16;
2414 f = (a ^ n ^ z) & Z80_H_FLAG;
2416 #ifndef Z80_DOCUMENTED_FLAGS_ONLY
2418 n = z - (f >> Z80_H_FLAG_SHIFT);
2419 f |= (n << (Z80_Y_FLAG_SHIFT - 1))
2421 f |= n & Z80_X_FLAG;
2425 f |= SZYX_FLAGS_TABLE[z & 0xff] & SZ_FLAGS;
2426 f |= bc ? Z80_P_FLAG : 0;
2427 F = f | Z80_N_FLAG | (F & Z80_C_FLAG);
2452 case ADD_INDIRECT_HL: {
2456 READ_INDIRECT_HL(x);
2479 case ADC_INDIRECT_HL: {
2483 READ_INDIRECT_HL(x);
2506 case SUB_INDIRECT_HL: {
2510 READ_INDIRECT_HL(x);
2533 case SBC_INDIRECT_HL: {
2537 READ_INDIRECT_HL(x);
2560 case AND_INDIRECT_HL: {
2564 READ_INDIRECT_HL(x);
2587 case OR_INDIRECT_HL: {
2591 READ_INDIRECT_HL(x);
2614 case XOR_INDIRECT_HL: {
2618 READ_INDIRECT_HL(x);
2641 case CP_INDIRECT_HL: {
2645 READ_INDIRECT_HL(x);
2658 case INC_INDIRECT_HL: {
2662 if (registers == state.register_table) {
2680 elapsed_cycles += 6;
2694 case DEC_INDIRECT_HL: {
2698 if (registers == state.register_table) {
2716 elapsed_cycles += 6;
2734 if (a > 0x99 || (F & Z80_C_FLAG)) {
2743 if ((a & 0x0f) > 0x09 || (F & Z80_H_FLAG))
2747 A += F & Z80_N_FLAG ? -d : +d;
2748 F = SZYXP_FLAGS_TABLE[A]
2749 | ((A ^ a) & Z80_H_FLAG)
2760 F = (F & (SZPV_FLAGS | Z80_C_FLAG))
2762 #ifndef Z80_DOCUMENTED_FLAGS_ONLY
2768 | Z80_H_FLAG | Z80_N_FLAG;
2782 f = Z80_N_FLAG | (c & Z80_H_FLAG);
2783 f |= SZYX_FLAGS_TABLE[z &= 0xff];
2785 f |= OVERFLOW_TABLE[c >> 7];
2786 f |= c >> (8 - Z80_C_FLAG_SHIFT);
2800 F = (F & SZPV_FLAGS)
2801 | (c << Z80_H_FLAG_SHIFT)
2803 #ifndef Z80_DOCUMENTED_FLAGS_ONLY
2817 F = (F & SZPV_FLAGS)
2819 #ifndef Z80_DOCUMENTED_FLAGS_ONLY
2839 #ifdef Z80_CATCH_HALT
2841 state.status = Z80_STATUS_HALT;
2851 state.iff1 = state.iff2 = 0;
2855 state.status = Z80_STATUS_DI;
2865 state.iff1 = state.iff2 = 1;
2869 state.status = Z80_STATUS_EI;
2883 if ((
Y(opcode) & 0x03) <= 0x01)
2885 state.im = Z80_INTERRUPT_MODE_0;
2887 else if (!(
Y(opcode) & 1))
2889 state.im = Z80_INTERRUPT_MODE_1;
2893 state.im = Z80_INTERRUPT_MODE_2;
2912 #ifndef Z80_DOCUMENTED_FLAGS_ONLY
2914 f |= (z >> 8) & YX_FLAGS;
2915 f |= (c >> 8) & Z80_H_FLAG;
2919 f |= c >> (16 - Z80_C_FLAG_SHIFT);
2924 elapsed_cycles += 7;
2936 z = x + y + (F & Z80_C_FLAG);
2940 ? (z >> 8) & SYX_FLAGS
2943 #ifndef Z80_DOCUMENTED_FLAGS_ONLY
2945 f |= (c >> 8) & Z80_H_FLAG;
2949 f |= OVERFLOW_TABLE[c >> 15];
2950 f |= z >> (16 - Z80_C_FLAG_SHIFT);
2955 elapsed_cycles += 7;
2967 z = x - y - (F & Z80_C_FLAG);
2972 ? (z >> 8) & SYX_FLAGS
2975 #ifndef Z80_DOCUMENTED_FLAGS_ONLY
2977 f |= (c >> 8) & Z80_H_FLAG;
2982 f |= OVERFLOW_TABLE[c >> 15];
2983 f |= c >> (16 - Z80_C_FLAG_SHIFT);
2988 elapsed_cycles += 7;
3002 elapsed_cycles += 2;
3016 elapsed_cycles += 2;
3026 A = (A << 1) | (A >> 7);
3027 F = (F & SZPV_FLAGS)
3028 | (A & (YX_FLAGS | Z80_C_FLAG));
3038 f = (F & SZPV_FLAGS)
3040 #ifndef Z80_DOCUMENTED_FLAGS_ONLY
3047 A = a | (F & Z80_C_FLAG);
3059 A = (A >> 1) | (A << 7);
3060 F = (F & SZPV_FLAGS)
3062 #ifndef Z80_DOCUMENTED_FLAGS_ONLY
3079 A = (A >> 1) | ((F & Z80_C_FLAG) << 7);
3080 F = (F & SZPV_FLAGS)
3082 #ifndef Z80_DOCUMENTED_FLAGS_ONLY
3101 case RLC_INDIRECT_HL: {
3105 if (registers == state.register_table) {
3117 Z80_FETCH_BYTE(pc, d);
3118 d = ((
signed char) d) + HL_IX_IY;
3124 if (Z(opcode) != INDIRECT_HL)
3130 elapsed_cycles += 5;
3145 case RL_INDIRECT_HL: {
3149 if (registers == state.register_table) {
3161 Z80_FETCH_BYTE(pc, d);
3162 d = ((
signed char) d) + HL_IX_IY;
3168 if (Z(opcode) != INDIRECT_HL)
3174 elapsed_cycles += 5;
3188 case RRC_INDIRECT_HL: {
3192 if (registers == state.register_table) {
3204 Z80_FETCH_BYTE(pc, d);
3205 d = ((
signed char) d) + HL_IX_IY;
3211 if (Z(opcode) != INDIRECT_HL)
3217 elapsed_cycles += 5;
3226 RR_INSTRUCTION(
R(Z(opcode)));
3231 case RR_INDIRECT_HL: {
3235 if (registers == state.register_table) {
3247 Z80_FETCH_BYTE(pc, d);
3248 d = ((
signed char) d) + HL_IX_IY;
3254 if (Z(opcode) != INDIRECT_HL)
3260 elapsed_cycles += 5;
3274 case SLA_INDIRECT_HL: {
3278 if (registers == state.register_table) {
3290 Z80_FETCH_BYTE(pc, d);
3291 d = ((
signed char) d) + HL_IX_IY;
3297 if (Z(opcode) != INDIRECT_HL)
3303 elapsed_cycles += 5;
3317 case SLL_INDIRECT_HL: {
3321 if (registers == state.register_table) {
3333 Z80_FETCH_BYTE(pc, d);
3334 d = ((
signed char) d) + HL_IX_IY;
3340 if (Z(opcode) != INDIRECT_HL)
3346 elapsed_cycles += 5;
3360 case SRA_INDIRECT_HL: {
3364 if (registers == state.register_table) {
3376 Z80_FETCH_BYTE(pc, d);
3377 d = ((
signed char) d) + HL_IX_IY;
3383 if (Z(opcode) != INDIRECT_HL)
3389 elapsed_cycles += 5;
3403 case SRL_INDIRECT_HL: {
3407 if (registers == state.register_table) {
3419 Z80_FETCH_BYTE(pc, d);
3420 d = ((
signed char) d) + HL_IX_IY;
3426 if (Z(opcode) != INDIRECT_HL)
3432 elapsed_cycles += 5;
3444 y = (A & 0xf0) << 8;
3445 y |= opcode == OPCODE_RLD
3446 ? (x << 4) | (A & 0x0f)
3454 F = SZYXP_FLAGS_TABLE[y] | (F & Z80_C_FLAG);
3456 elapsed_cycles += 4;
3468 x =
R(Z(opcode)) & (1 <<
Y(opcode));
3469 F = (x ? 0 : Z80_Z_FLAG | Z80_P_FLAG)
3471 #ifndef Z80_DOCUMENTED_FLAGS_ONLY
3474 | (
R(Z(opcode)) & YX_FLAGS)
3485 case BIT_B_INDIRECT_HL: {
3489 if (registers == state.register_table) {
3497 Z80_FETCH_BYTE(pc, d);
3498 d = ((
signed char) d) + HL_IX_IY;
3502 elapsed_cycles += 5;
3507 x &= 1 <<
Y(opcode);
3508 F = (x ? 0 : Z80_Z_FLAG | Z80_P_FLAG)
3510 #ifndef Z80_DOCUMENTED_FLAGS_ONLY
3526 R(Z(opcode)) |= 1 <<
Y(opcode);
3531 case SET_B_INDIRECT_HL: {
3535 if (registers == state.register_table) {
3538 x |= 1 <<
Y(opcode);
3547 Z80_FETCH_BYTE(pc, d);
3548 d = ((
signed char) d) + HL_IX_IY;
3551 x |= 1 <<
Y(opcode);
3554 if (Z(opcode) != INDIRECT_HL)
3560 elapsed_cycles += 5;
3569 R(Z(opcode)) &= ~(1 <<
Y(opcode));
3574 case RES_B_INDIRECT_HL: {
3578 if (registers == state.register_table) {
3581 x &= ~(1 <<
Y(opcode));
3590 Z80_FETCH_BYTE(pc, d);
3591 d = ((
signed char) d) + HL_IX_IY;
3594 x &= ~(1 <<
Y(opcode));
3597 if (Z(opcode) != INDIRECT_HL)
3603 elapsed_cycles += 5;
3616 Z80_FETCH_WORD(pc, nn);
3619 elapsed_cycles += 6;
3629 if (CC(
Y(opcode))) {
3631 Z80_FETCH_WORD(pc, nn);
3636 #ifdef Z80_FALSE_CONDITION_FETCH
3638 Z80_FETCH_WORD(pc, nn);
3646 elapsed_cycles += 6;
3656 Z80_FETCH_BYTE(pc, e);
3657 pc += ((
signed char) e) + 1;
3659 elapsed_cycles += 8;
3669 if (DD(Q(opcode))) {
3671 Z80_FETCH_BYTE(pc, e);
3672 pc += ((
signed char) e) + 1;
3674 elapsed_cycles += 8;
3678 #ifdef Z80_FALSE_CONDITION_FETCH
3680 Z80_FETCH_BYTE(pc, e);
3686 elapsed_cycles += 3;
3706 Z80_FETCH_BYTE(pc, e);
3707 pc += ((
signed char) e) + 1;
3709 elapsed_cycles += 9;
3713 #ifdef Z80_FALSE_CONDITION_FETCH
3715 Z80_FETCH_BYTE(pc, e);
3721 elapsed_cycles += 4;
3748 if (CC(
Y(opcode))) {
3758 #ifdef Z80_FALSE_CONDITION_FETCH
3760 Z80_FETCH_WORD(pc, nn);
3766 elapsed_cycles += 6;
3782 if (CC(
Y(opcode))) {
3794 state.iff1 = state.iff2;
3797 #if defined(Z80_CATCH_RETI) && defined(Z80_CATCH_RETN)
3799 state.status = opcode == OPCODE_RETI
3803 #elif defined(Z80_CATCH_RETI)
3805 state.status = Z80_STATUS_RETI;
3807 #elif defined(Z80_CATCH_RETN)
3809 state.status = Z80_STATUS_RETN;
3820 pc = RST_TABLE[
Y(opcode)];
3833 Z80_INPUT_BYTE(n, A);
3835 elapsed_cycles += 4;
3844 Z80_INPUT_BYTE(C, x);
3845 if (
Y(opcode) != INDIRECT_HL)
3849 F = SZYXP_FLAGS_TABLE[x] | (F & Z80_C_FLAG);
3851 elapsed_cycles += 4;
3868 Z80_INPUT_BYTE(C, x);
3871 f = SZYX_FLAGS_TABLE[--
B & 0xff]
3872 | (x >> (7 - Z80_N_FLAG_SHIFT));
3873 if (opcode == OPCODE_INI) {
3876 x += (C + 1) & 0xff;
3881 x += (C - 1) & 0xff;
3884 f |= x & 0x0100 ? HC_FLAGS : 0;
3885 f |= SZYXP_FLAGS_TABLE[(x & 0x07) ^
B]
3889 elapsed_cycles += 5;
3899 #ifdef Z80_HANDLE_SELF_MODIFYING_CODE
3903 p = (pc - 2) & 0xffff;
3904 q = (pc - 1) & 0xffff;
3908 d = opcode == OPCODE_INIR ? +1 : -1;
3914 elapsed_cycles -= 8;
3919 Z80_INPUT_BYTE(C, x);
3920 Z80_WRITE_BYTE(hl, x);
3926 elapsed_cycles += 21;
3931 elapsed_cycles += 16;
3936 #ifdef Z80_HANDLE_SELF_MODIFYING_CODE
3938 if (((hl - d) & 0xffff) == p
3939 || ((hl - d) & 0xffff) == q) {
3941 f = SZYX_FLAGS_TABLE[b];
3949 f = SZYX_FLAGS_TABLE[b];
3958 f |= x >> (7 - Z80_N_FLAG_SHIFT);
3959 x += (C + d) & 0xff;
3960 f |= x & 0x0100 ? HC_FLAGS : 0;
3961 f |= SZYXP_FLAGS_TABLE[(x & 0x07) ^ b]
3974 Z80_OUTPUT_BYTE(n, A);
3976 elapsed_cycles += 4;
3986 x =
Y(opcode) != INDIRECT_HL
3989 Z80_OUTPUT_BYTE(C, x);
3991 elapsed_cycles += 4;
4002 Z80_OUTPUT_BYTE(C, x);
4004 HL += opcode == OPCODE_OUTI ? +1 : -1;
4006 f = SZYX_FLAGS_TABLE[--
B & 0xff]
4007 | (x >> (7 - Z80_N_FLAG_SHIFT));
4009 f |= x & 0x0100 ? HC_FLAGS : 0;
4010 f |= SZYXP_FLAGS_TABLE[(x & 0x07) ^
B]
4022 d = opcode == OPCODE_OTIR ? +1 : -1;
4028 elapsed_cycles -= 8;
4033 Z80_READ_BYTE(hl, x);
4034 Z80_OUTPUT_BYTE(C, x);
4039 elapsed_cycles += 21;
4044 elapsed_cycles += 16;
4049 f = SZYX_FLAGS_TABLE[b];
4058 f |= x >> (7 - Z80_N_FLAG_SHIFT);
4060 f |= x & 0x0100 ? HC_FLAGS : 0;
4061 f |= SZYXP_FLAGS_TABLE[(x & 0x07) ^ b]
4077 if (registers != state.register_table) {
4085 Z80_FETCH_BYTE(pc + 1, opcode);
4089 Z80_FETCH_BYTE(pc, opcode);
4093 instruction = CB_INSTRUCTION_TABLE[opcode];
4102 registers = state.dd_register_table;
4104 Z80_FETCH_BYTE(pc, opcode);
4106 instruction = INSTRUCTION_TABLE[opcode];
4114 registers = state.fd_register_table;
4116 Z80_FETCH_BYTE(pc, opcode);
4118 instruction = INSTRUCTION_TABLE[opcode];
4126 registers = state.register_table;
4127 Z80_FETCH_BYTE(pc, opcode);
4129 instruction = ED_INSTRUCTION_TABLE[opcode];
4137 case ED_UNDEFINED: {
4139 #ifdef Z80_CATCH_ED_UNDEFINED
4141 state.status = Z80_STATUS_FLAG_ED_UNDEFINED;
4152 }
while (repeatLoop);
4154 state.r = (state.r & 0x80) | (r & 0x7f);
4155 state.pc = pc & 0xffff;
4157 return elapsed_cycles;
This file contains fabgl::Z80 definition.