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