FabGL
ESP32 Display Controller and Graphics Library
Z80.h
Go to the documentation of this file.
1/*
2 Z80 emulator code derived from Lin Ke-Fong source. Copyright says:
3
4 Copyright (c) 2016, 2017 Lin Ke-Fong
5
6 This code is free, do whatever you want with it.
7
8 2020 adapted by Fabrizio Di Vittorio for fabgl ESP32 library
9 */
10
11
12#pragma once
13
14
23#include <stdint.h>
24
25
26
27namespace fabgl {
28
29
30/* Define this macro if the host processor is big endian. */
31
32/* #define Z80_BIG_ENDIAN */
33
34/* Emulation can be speed up a little bit by emulating only the documented
35 * flags.
36 */
37
38/* #define Z80_DOCUMENTED_FLAGS_ONLY */
39
40/* HALT, DI, EI, RETI, and RETN instructions can be catched. When such an
41 * instruction is catched, the emulator is stopped and the PC register points
42 * at the opcode to be executed next. The catched instruction can be determined
43 * from the Z80_STATE's status value. Keep in mind that no interrupt can be
44 * accepted at the instruction right after a DI or EI on an actual processor.
45 */
46
47
48 #define Z80_CATCH_HALT
49/*
50 #define Z80_CATCH_DI
51 #define Z80_CATCH_EI
52 #define Z80_CATCH_RETI
53 #define Z80_CATCH_RETN
54 */
55
56/* Undefined 0xed prefixed opcodes may be catched, otherwise they are treated
57 * like NOP instructions. When one is catched, Z80_STATUS_ED_UNDEFINED is set
58 * in Z80_STATE's status member and the PC register points at the 0xed prefix
59 * before the undefined opcode.
60 */
61
62/* #define Z80_CATCH_ED_UNDEFINED */
63
64/* By defining this macro, the emulator will always fetch the displacement or
65 * address of a conditionnal jump or call instruction, even if the condition
66 * is false and the fetch can be avoided. Define this macro if you need to
67 * account for memory wait states on code read.
68 */
69
70/* #define Z80_FALSE_CONDITION_FETCH */
71
72/* It may be possible to overwrite the opcode of the currently executing LDIR,
73 * LDDR, INIR, or OTDR instruction. Define this macro if you need to handle
74 * these pathological cases.
75 */
76
77/* #define Z80_HANDLE_SELF_MODIFYING_CODE */
78
79/* For interrupt mode 2, bit 0 of the 16-bit address to the interrupt vector
80 * can be masked to zero. Some documentation states that this bit is forced to
81 * zero. For instance, Zilog's application note about interrupts, states that
82 * "only 7 bits are required" and "the least significant bit is zero". Yet,
83 * this is quite unclear, even from Zilog's manuals. So this is left as an
84 * option.
85 */
86
87/* #define Z80_MASK_IM2_VECTOR_ADDRESS */
88
89
90
91
92
93
94/* If Z80_STATE's status is non-zero, the emulation has been stopped for some
95 * reason other than emulating the requested number of cycles.
96 */
97
98enum {
99
100 Z80_STATUS_HALT = 1,
101 Z80_STATUS_DI,
102 Z80_STATUS_EI,
103 Z80_STATUS_RETI,
104 Z80_STATUS_RETN,
105 Z80_STATUS_ED_UNDEFINED,
106 Z80_STATUS_PREFIX
107
108};
109
110
111
112/* The main registers are stored inside Z80_STATE as an union of arrays named
113 * registers. They are referenced using indexes. Words are stored in the
114 * endianness of the host processor. The alternate set of word registers AF',
115 * BC', DE', and HL' is stored in the alternates member of Z80_STATE, as an
116 * array using the same ordering.
117 */
118
119#ifdef Z80_BIG_ENDIAN
120
121# define Z80_B 0
122# define Z80_C 1
123# define Z80_D 2
124# define Z80_E 3
125# define Z80_H 4
126# define Z80_L 5
127# define Z80_A 6
128# define Z80_F 7
129
130# define Z80_IXH 8
131# define Z80_IXL 9
132# define Z80_IYH 10
133# define Z80_IYL 11
134
135#else
136
137# define Z80_B 1
138# define Z80_C 0
139# define Z80_D 3
140# define Z80_E 2
141# define Z80_H 5
142# define Z80_L 4
143# define Z80_A 7
144# define Z80_F 6
145
146# define Z80_IXH 9
147# define Z80_IXL 8
148# define Z80_IYH 11
149# define Z80_IYL 10
150
151#endif
152
153#define Z80_BC 0
154#define Z80_DE 1
155#define Z80_HL 2
156#define Z80_AF 3
157
158#define Z80_IX 4
159#define Z80_IY 5
160#define Z80_SP 6
161
162
163
164/* Z80's flags. */
165
166#define Z80_S_FLAG_SHIFT 7
167#define Z80_Z_FLAG_SHIFT 6
168#define Z80_Y_FLAG_SHIFT 5
169#define Z80_H_FLAG_SHIFT 4
170#define Z80_X_FLAG_SHIFT 3
171#define Z80_PV_FLAG_SHIFT 2
172#define Z80_N_FLAG_SHIFT 1
173#define Z80_C_FLAG_SHIFT 0
174
175#define Z80_S_FLAG (1 << Z80_S_FLAG_SHIFT)
176#define Z80_Z_FLAG (1 << Z80_Z_FLAG_SHIFT)
177#define Z80_Y_FLAG (1 << Z80_Y_FLAG_SHIFT)
178#define Z80_H_FLAG (1 << Z80_H_FLAG_SHIFT)
179#define Z80_X_FLAG (1 << Z80_X_FLAG_SHIFT)
180#define Z80_PV_FLAG (1 << Z80_PV_FLAG_SHIFT)
181#define Z80_N_FLAG (1 << Z80_N_FLAG_SHIFT)
182#define Z80_C_FLAG (1 << Z80_C_FLAG_SHIFT)
183
184#define Z80_P_FLAG_SHIFT Z80_PV_FLAG_SHIFT
185#define Z80_V_FLAG_SHIFT Z80_PV_FLAG_SHIFT
186#define Z80_P_FLAG Z80_PV_FLAG
187#define Z80_V_FLAG Z80_PV_FLAG
188
189
190
191/* Z80's three interrupt modes. */
192
193enum {
194 Z80_INTERRUPT_MODE_0,
195 Z80_INTERRUPT_MODE_1,
196 Z80_INTERRUPT_MODE_2
197};
198
199
200
201struct Z80_STATE {
202 int status;
203
204 union {
205 unsigned char byte[14];
206 unsigned short word[7];
207 } registers;
208
209 unsigned short alternates[4];
210
211 int i, r, pc, iff1, iff2, im;
212
213 /* Register decoding tables. */
214
215 void * register_table[16];
216 void * dd_register_table[16];
217 void * fd_register_table[16];
218};
219
224class Z80 {
225
226public:
227
228 // callbacks
229 typedef int (*ReadByteCallback)(void * context, int addr);
230 typedef void (*WriteByteCallback)(void * context, int addr, int value);
231 typedef int (*ReadWordCallback)(void * context, int addr);
232 typedef void (*WriteWordCallback)(void * context, int addr, int value);
233 typedef int (*ReadIOCallback)(void * context, int addr);
234 typedef void (*WriteIOCallback)(void * context, int addr, int value);
235
236 void setCallbacks(void * context, ReadByteCallback readByte, WriteByteCallback writeByte, ReadWordCallback readWord, WriteWordCallback writeWord, ReadIOCallback readIO, WriteIOCallback writeIO) {
237 m_context = context;
238 m_readByte = readByte;
239 m_writeByte = writeByte;
240 m_readWord = readWord;
241 m_writeWord = writeWord;
242 m_readIO = readIO;
243 m_writeIO = writeIO;
244 }
245
246 /* Initialize processor's state to power-on default. */
247 void reset();
248
249 /* Trigger an interrupt according to the current interrupt mode and return the
250 * number of cycles elapsed to accept it. If maskable interrupts are disabled,
251 * this will return zero. In interrupt mode 0, data_on_bus must be a single
252 * byte opcode.
253 */
254 int IRQ(int data_on_bus);
255
256 /* Trigger a non maskable interrupt, then return the number of cycles elapsed
257 * to accept it.
258 */
259 int NMI();
260
261 int step();
262
263
264 // CPU registers access
265
266 uint8_t readRegByte(int reg) { return state.registers.byte[reg]; }
267 void writeRegByte(int reg, uint8_t value) { state.registers.byte[reg] = value; }
268
269 uint16_t readRegWord(int reg) { return state.registers.word[reg]; }
270 void writeRegWord(int reg, uint16_t value) { state.registers.word[reg] = value; }
271
272 uint16_t getPC() { return state.pc; }
273 void setPC(uint16_t value) { state.pc = value; }
274
275 int getStatus() { return state.status; }
276 int getIM() { return state.im; }
277 int getIFF1() { return state.iff1; }
278 int getIFF2() { return state.iff2; }
279
280private:
281
282 int intemulate(int opcode, int elapsed_cycles);
283
284 Z80_STATE state;
285
286 // callbacks
287
288 void * m_context;
289
290 ReadByteCallback m_readByte;
291 WriteByteCallback m_writeByte;
292 ReadWordCallback m_readWord;
293 WriteWordCallback m_writeWord;
294 ReadIOCallback m_readIO;
295 WriteIOCallback m_writeIO;
296
297};
298
299
300}; // fabgl namespace
301
302
303
304
305
306
307
Zilog Z80 CPU emulator.
Definition: Z80.h:220