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 
27 namespace 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 
97 enum {
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 
192 enum {
193  Z80_INTERRUPT_MODE_0,
194  Z80_INTERRUPT_MODE_1,
195  Z80_INTERRUPT_MODE_2
196 };
197 
198 
199 
200 struct 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 };
218 
219 
223 class Z80 {
224 
225 public:
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 
275 private:
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 
Definition: canvas.cpp:36
Zilog Z80 CPU emulator.
Definition: Z80.h:223