libzymosis: cosmetic comments
[zymosis.git] / src / libzymosis / zymosis.c
blobf477179371b52d2bb215fb80959a7cbc3c5e85c0
1 /*
2 * Z80 CPU emulation engine v0.1.1
3 * coded by Ketmar // Invisible Vector (psyc://ketmar.no-ip.org/~ketmar)
4 * Understanding is not required. Only obedience.
6 * This program is free software. It comes without any warranty, to
7 * the extent permitted by applicable law. You can redistribute it
8 * and/or modify it under the terms of the Do What The Fuck You Want
9 * To Public License, Version 2, as published by Sam Hocevar. See
10 * http://www.wtfpl.net/txt/copying/ for more details.
12 #include <stdlib.h>
13 #include <string.h>
15 #include "zymosis.h"
17 #if defined(__GNUC__)
18 # ifndef ZYMOSIS_INLINE
19 # define ZYMOSIS_INLINE static __attribute__((always_inline)) inline
20 # endif
21 # ifndef ZYMOSIS_PURE
22 # define ZYMOSIS_PURE __attribute__((pure))
23 # endif
24 # ifndef ZYMOSIS_CONST
25 # define ZYMOSIS_CONST __attribute__((const))
26 # endif
27 # ifndef ZYMOSIS_FUNC
28 # define ZYMOSIS_FUNC __attribute__((warn_unused_result))
29 # endif
30 #endif
32 #ifndef ZYMOSIS_INLINE
33 # define ZYMOSIS_INLINE static
34 #endif
35 #ifndef ZYMOSIS_PURE
36 # define ZYMOSIS_PURE
37 #endif
38 #ifndef ZYMOSIS_CONST
39 # define ZYMOSIS_CONST
40 #endif
41 #ifndef ZYMOSIS_FUNC
42 # define ZYMOSIS_FUNC
43 #endif
46 /******************************************************************************/
47 /* some funny tables */
48 static int tables_inited = 0;
49 static uint8_t parity_tbl[256];
50 static uint8_t sz53_tbl[256]; /* bits 3, 5 and 7 of result, Z flag */
51 static uint8_t sz53p_tbl[256]; /* bits 3, 5 and 7 of result, Z and P flags */
54 //**************************************************************************
56 // various initialisations
58 //**************************************************************************
60 // initialise internal flag tables
61 // WARNING! this is NOT thread-safe!
62 void zym_init_tables (void) {
63 if (tables_inited) return;
64 for (unsigned f = 0; f < 256; ++f) {
65 unsigned n, p;
66 sz53_tbl[f] = (f&ZYM_FLAG_S35);
67 for (n = f, p = 0; n != 0; n >>= 1) p ^= n&0x01u;
68 parity_tbl[f] = (p ? 0 : ZYM_FLAG_PV);
69 sz53p_tbl[f] = (sz53_tbl[f]|parity_tbl[f]);
71 sz53_tbl[0] |= ZYM_FLAG_Z;
72 sz53p_tbl[0] |= ZYM_FLAG_Z;
73 tables_inited = 1;
77 #if defined(__GNUC__)
78 static __attribute__((constructor)) void zym_init_tables_ctor (void) {
79 zym_init_tables();
81 #endif
84 // should be called on new instance of zym_cpu_t to clear all callbacks
85 void zym_clear_callbacks (zym_cpu_t *z80) {
86 if (!tables_inited) zym_init_tables();
87 z80->mem_read = NULL;
88 z80->mem_write = NULL;
89 z80->mem_contention = NULL;
90 z80->port_read = NULL;
91 z80->port_write = NULL;
92 z80->port_contention = NULL;
93 z80->trap_reti = NULL;
94 z80->trap_retn = NULL;
95 z80->trap_ed = NULL;
96 z80->opc_pager = NULL;
100 // clear all flags and callbacks; will reset 'z80->user' too
101 void zym_init (zym_cpu_t *z80) {
102 if (!tables_inited) zym_init_tables();
103 memset(z80, 0, sizeof(*z80));
104 zym_clear_callbacks(z80);
105 z80->user = NULL;
106 z80->next_event_tstate = -1;
110 // resets Z80 CPU
111 // seems that all regs (and memptr) should be set to 'all 1' here, but i don't care
112 void zym_reset (zym_cpu_t *z80) {
113 if (!tables_inited) zym_init_tables();
114 z80->bc.w = z80->de.w = z80->hl.w = z80->af.w = z80->sp.w = z80->ix.w = z80->iy.w = 0;
115 z80->bcx.w = z80->dex.w = z80->hlx.w = z80->afx.w = 0;
116 z80->pc = z80->prev_pc = z80->org_pc = 0;
117 z80->memptr.w = 0;
118 z80->regI = z80->regR = 0;
119 z80->iff1 = z80->iff2 = 0;
120 z80->im = 0;
121 z80->halted = 0;
122 z80->prev_was_EIDDR = 0;
123 z80->tstates = 0;
124 z80->dd = &z80->hl;
125 z80->flags_q = 0;
129 //**************************************************************************
131 // alternate register set functions
133 //**************************************************************************
135 ZYMOSIS_INLINE void zym_exx_internal (zym_cpu_t *z80) {
136 uint16_t t = z80->bc.w; z80->bc.w = z80->bcx.w; z80->bcx.w = t;
137 t = z80->de.w; z80->de.w = z80->dex.w; z80->dex.w = t;
138 t = z80->hl.w; z80->hl.w = z80->hlx.w; z80->hlx.w = t;
142 ZYMOSIS_INLINE void zym_exaf_internal (zym_cpu_t *z80) {
143 const uint16_t t = z80->af.w; z80->af.w = z80->afx.w; z80->afx.w = t;
147 // swap normal and alternate register sets (except AF/AF')
148 void zym_exx (zym_cpu_t *z80) {
149 zym_exx_internal(z80);
153 // swap normal and alternate AF
154 void zym_exaf (zym_cpu_t *z80) {
155 zym_exaf_internal(z80);
159 /******************************************************************************/
160 /* simulate contented memory access */
161 /* (tstates = tstates+contention+1)*cnt */
162 /* (zym_cpu_t *z80, uint16_t addr, int tstates, zym_memio_t mio) */
163 #define z80_contention(z80_,addr_,tstates_,mio_,mrq_) do { \
164 if ((z80_)->mem_contention != NULL) (z80_)->mem_contention((z80_), (addr_), (tstates_), (mio_), (mrq_)); else (z80_)->tstates += (tstates_); \
165 } while (0)
168 #define z80_contention_by1ts(z80_,addr_,cnt_) do { \
169 if ((z80)->mem_contention != NULL) { \
170 for (unsigned fcnt = (cnt_); fcnt--; (z80_)->mem_contention((z80_), (addr_), 1, ZYM_MEMIO_OTHER, ZYM_MREQ_NONE)) {} \
171 } else { \
172 (z80_)->tstates += (cnt_); \
174 } while (0)
177 #define z80_contention_by1ts_ir(z80_,cnt_) z80_contention_by1ts((z80_), (((uint16_t)(z80_)->regI)<<8)|((z80_)->regR), (cnt_))
178 #define z80_contention_by1ts_pc(z80_,cnt_) z80_contention_by1ts((z80_), (z80_)->pc, (cnt_))
181 /******************************************************************************/
182 ZYMOSIS_INLINE uint8_t z80_port_read (zym_cpu_t *z80, const uint16_t port) {
183 uint8_t value;
184 /* i don't really know: FUSE tester seems to do port read in-between contentions,
185 but the actual emulator code does it after all contentions are done.
186 i guess that doing it in-between is the right way.
187 note: ok, it broke floating bus emulation in ZXEmuT. oopsie!
189 if (z80->port_contention != NULL) {
190 z80->port_contention(z80, port, 1, ZYM_PORTIO_FLAG_IN|ZYM_PORTIO_FLAG_EARLY);
191 z80->port_read_tstates = z80->tstates;
192 #ifdef ZYMOSIS_FUSE_TEST
193 /* for FUSE tests, it should be here */
194 value = z80->port_read(z80, port, ZYM_PORTIO_NORMAL);
195 #endif
196 z80->port_contention(z80, port, 2, ZYM_PORTIO_FLAG_IN);
197 #ifndef ZYMOSIS_FUSE_TEST
198 /* for ZXEmuT floating bus emulation, it should be here */
199 value = z80->port_read(z80, port, ZYM_PORTIO_NORMAL);
200 #endif
201 } else {
202 z80->tstates += 3;
203 z80->port_read_tstates = z80->tstates-2;
204 value = z80->port_read(z80, port, ZYM_PORTIO_NORMAL);
206 ++z80->tstates;
207 return value;
211 ZYMOSIS_INLINE void z80_port_write (zym_cpu_t *z80, const uint16_t port, const uint8_t value) {
212 if (z80->port_contention != NULL) {
213 z80->port_contention(z80, port, 1, ZYM_PORTIO_FLAG_EARLY);
214 z80->port_write(z80, port, value, ZYM_PORTIO_NORMAL);
215 z80->port_contention(z80, port, 2, 0);
216 ++z80->tstates;
217 } else {
218 ++z80->tstates;
219 z80->port_write(z80, port, value, ZYM_PORTIO_NORMAL);
220 z80->tstates += 3;
225 /******************************************************************************/
226 #define z80_peekb_i(z80_,addr_) (z80_)->mem_read((z80_), (addr_), ZYM_MEMIO_OTHER)
227 #define z80_peekb(z80_,addr_) (z80_)->mem_read((z80_), (addr_), ZYM_MEMIO_DATA)
229 #define z80_pokeb_i(z80_,addr_,byte_) (z80_)->mem_write((z80_), (addr_), (byte_), ZYM_MEMIO_OTHER)
230 #define z80_pokeb(z80_,addr_,byte_) (z80_)->mem_write((z80_), (addr_), (byte_), ZYM_MEMIO_DATA)
233 /* t1: setting /MREQ & /RD */
234 /* t2: memory read */
235 ZYMOSIS_INLINE uint8_t z80_peekb_3ts (zym_cpu_t *z80, const uint16_t addr) {
236 z80_contention(z80, addr, 3, ZYM_MEMIO_DATA, ZYM_MREQ_READ);
237 return z80_peekb(z80, addr);
240 ZYMOSIS_INLINE uint8_t z80_peekb_3ts_args (zym_cpu_t *z80, const uint16_t addr) {
241 z80_contention(z80, addr, 3, ZYM_MEMIO_OPCARG, ZYM_MREQ_READ);
242 return z80_peekb(z80, addr);
245 ZYMOSIS_INLINE void z80_peekb_3ts_args_noread (zym_cpu_t *z80, const uint16_t addr) {
246 z80_contention(z80, addr, 3, ZYM_MEMIO_OPCARG, ZYM_MREQ_READ);
249 ZYMOSIS_INLINE uint16_t z80_peekw_6ts (zym_cpu_t *z80, const uint16_t addr) {
250 const uint16_t res = z80_peekb_3ts(z80, addr);
251 return res|(((uint16_t)z80_peekb_3ts(z80, (addr+1)&0xffffu))<<8);
254 /* t1: setting /MREQ & /WR */
255 /* t2: memory write */
256 ZYMOSIS_INLINE void z80_pokeb_3ts (zym_cpu_t *z80, const uint16_t addr, const uint8_t value) {
257 z80_contention(z80, addr, 3, ZYM_MEMIO_DATA, ZYM_MREQ_WRITE);
258 z80_pokeb(z80, addr, value);
261 ZYMOSIS_INLINE void z80_pokew_6ts (zym_cpu_t *z80, const uint16_t addr, const uint16_t value) {
262 z80_pokeb_3ts(z80, addr, value&0xffu);
263 z80_pokeb_3ts(z80, (addr+1)&0xffffu, (value>>8)&0xffu);
266 ZYMOSIS_INLINE void z80_pokew_6ts_inverted (zym_cpu_t *z80, const uint16_t addr, const uint16_t value) {
267 z80_pokeb_3ts(z80, (addr+1)&0xffffu, (value>>8)&0xffu);
268 z80_pokeb_3ts(z80, addr, value&0xffu);
272 ZYMOSIS_INLINE uint16_t z80_getpcw (zym_cpu_t *z80, const zym_bool wait1) {
273 uint16_t res = z80_peekb_3ts_args(z80, z80->pc);
274 z80->pc = (z80->pc+1)&0xffffu;
275 res |= ((uint16_t)z80_peekb_3ts_args(z80, z80->pc))<<8;
276 if (wait1) z80_contention_by1ts_pc(z80, 1);
277 z80->pc = (z80->pc+1)&0xffffu;
278 return res;
282 ZYMOSIS_INLINE uint16_t z80_pop_6ts (zym_cpu_t *z80) {
283 uint16_t res = z80_peekb_3ts(z80, z80->sp.w);
284 z80->sp.w = (z80->sp.w+1)&0xffffu;
285 res |= ((uint16_t)z80_peekb_3ts(z80, z80->sp.w))<<8;
286 z80->sp.w = (z80->sp.w+1)&0xffffu;
287 return res;
290 /* 3 T states write high byte of PC to the stack and decrement SP */
291 /* 3 T states write the low byte of PC and jump to #0066 */
292 ZYMOSIS_INLINE void z80_push_6ts (zym_cpu_t *z80, uint16_t value) {
293 z80->sp.w = (((uint32_t)z80->sp.w)-1u)&0xffffu;
294 z80_pokeb_3ts(z80, z80->sp.w, (value>>8)&0xffu);
295 z80->sp.w = (((uint32_t)z80->sp.w)-1u)&0xffffu;
296 z80_pokeb_3ts(z80, z80->sp.w, value&0xffu);
300 /******************************************************************************/
301 /* you are not expected to understand the following bit-mess */
302 /* the only thing you want to know that IT WORKS; just believe me and the testing suite */
303 /* ok, you can consult Z80 manuals to find the affected flags */
304 /* but believe me, it is unnecessary */
306 ZYMOSIS_INLINE void ZYM_ADC_A (zym_cpu_t *z80, const uint8_t b) {
307 const uint16_t o = z80->af.a;
308 uint16_t newv;
309 z80->af.a = (newv = o+b+(z80->af.f&ZYM_FLAG_C))&0xffu; /* ZYM_FLAG_C is 0x01u, so it's safe */
310 z80->flags_q = z80->af.f =
311 sz53_tbl[newv&0xffu]|
312 (newv > 0xffu ? ZYM_FLAG_C : 0)|
313 ((o^(~b))&(o^newv)&0x80u ? ZYM_FLAG_PV : 0)|
314 ((o&0x0fu)+(b&0x0fu)+(z80->af.f&ZYM_FLAG_C) >= 0x10u ? ZYM_FLAG_H : 0);
317 ZYMOSIS_INLINE void ZYM_SBC_A (zym_cpu_t *z80, const uint8_t b) {
318 const uint16_t o = z80->af.a;
319 uint16_t newv;
320 z80->af.a = (newv = ((uint32_t)o-(uint32_t)b-(uint32_t)(z80->af.f&ZYM_FLAG_C))&0xffffu)&0xffu; /* ZYM_FLAG_C is 0x01u, so it's safe */
321 z80->flags_q = z80->af.f =
322 ZYM_FLAG_N|
323 sz53_tbl[newv&0xffu]|
324 (newv > 0xffu ? ZYM_FLAG_C : 0)|
325 ((o^b)&(o^newv)&0x80u ? ZYM_FLAG_PV : 0)|
326 ((int)(o&0x0fu)-(int)(b&0x0fu)-(int)(z80->af.f&ZYM_FLAG_C) < 0 ? ZYM_FLAG_H : 0);
330 ZYMOSIS_INLINE void ZYM_ADD_A (zym_cpu_t *z80, const uint8_t b) {
331 z80->af.f &= ~ZYM_FLAG_C;
332 ZYM_ADC_A(z80, b);
335 ZYMOSIS_INLINE void ZYM_SUB_A (zym_cpu_t *z80, const uint8_t b) {
336 z80->af.f &= ~ZYM_FLAG_C;
337 ZYM_SBC_A(z80, b);
340 ZYMOSIS_INLINE void ZYM_CP_A (zym_cpu_t *z80, const uint8_t b) {
341 const uint8_t o = z80->af.a;
342 const uint8_t newv = ((uint32_t)o-(uint32_t)b)&0xffu;
343 z80->flags_q = z80->af.f =
344 ZYM_FLAG_N|
345 (newv&ZYM_FLAG_S)|
346 (b&ZYM_FLAG_35)|
347 (newv == 0 ? ZYM_FLAG_Z : 0)|
348 (o < b ? ZYM_FLAG_C : 0)|
349 ((o^b)&(o^newv)&0x80u ? ZYM_FLAG_PV : 0)|
350 ((int)(o&0x0fu)-(int)(b&0x0fu) < 0 ? ZYM_FLAG_H : 0);
354 #define ZYM_AND_A(z80_,b_) ((z80_)->flags_q = (z80_)->af.f = sz53p_tbl[(z80_)->af.a&=(b_)]|ZYM_FLAG_H)
355 #define ZYM_OR_A(z80_,b_) ((z80_)->flags_q = (z80_)->af.f = sz53p_tbl[(z80_)->af.a|=(b_)])
356 #define ZYM_XOR_A(z80_,b_) ((z80_)->flags_q = (z80_)->af.f = sz53p_tbl[(z80_)->af.a^=(b_)])
359 /* carry unchanged */
360 ZYMOSIS_INLINE uint8_t ZYM_DEC8 (zym_cpu_t *z80, const uint8_t b) {
361 z80->af.f &= ZYM_FLAG_C;
362 z80->af.f |= ZYM_FLAG_N|
363 (b == 0x80u ? ZYM_FLAG_PV : 0)|
364 (b&0x0fu ? 0 : ZYM_FLAG_H)|
365 sz53_tbl[(((uint32_t)b)-1u)&0xffu];
366 z80->flags_q = z80->af.f;
367 return (((uint32_t)b)-1u)&0xffu;
370 /* carry unchanged */
371 ZYMOSIS_INLINE uint8_t ZYM_INC8 (zym_cpu_t *z80, const uint8_t b) {
372 z80->af.f &= ZYM_FLAG_C;
373 z80->af.f |=
374 (b == 0x7fu ? ZYM_FLAG_PV : 0)|
375 ((b+1u)&0x0fu ? 0 : ZYM_FLAG_H)|
376 sz53_tbl[(b+1u)&0xffu];
377 z80->flags_q = z80->af.f;
378 return ((b+1u)&0xffu);
382 /* cyclic, carry reflects shifted bit */
383 ZYMOSIS_INLINE void ZYM_RLCA (zym_cpu_t *z80) {
384 const uint8_t c = ((z80->af.a>>7)&0x01u);
385 z80->af.a = (z80->af.a<<1)|c;
386 z80->flags_q = z80->af.f = c|(z80->af.a&ZYM_FLAG_35)|(z80->af.f&(ZYM_FLAG_PV|ZYM_FLAG_Z|ZYM_FLAG_S));
389 /* cyclic, carry reflects shifted bit */
390 ZYMOSIS_INLINE void ZYM_RRCA (zym_cpu_t *z80) {
391 const uint8_t c = (z80->af.a&0x01u);
392 z80->af.a = (z80->af.a>>1)|(c<<7);
393 z80->flags_q = z80->af.f = c|(z80->af.a&ZYM_FLAG_35)|(z80->af.f&(ZYM_FLAG_PV|ZYM_FLAG_Z|ZYM_FLAG_S));
397 /* cyclic thru carry */
398 ZYMOSIS_INLINE void ZYM_RLA (zym_cpu_t *z80) {
399 const uint8_t c = ((z80->af.a>>7)&0x01u);
400 z80->af.a = (z80->af.a<<1)|(z80->af.f&ZYM_FLAG_C);
401 z80->flags_q = z80->af.f = c|(z80->af.a&ZYM_FLAG_35)|(z80->af.f&(ZYM_FLAG_PV|ZYM_FLAG_Z|ZYM_FLAG_S));
404 /* cyclic thru carry */
405 ZYMOSIS_INLINE void ZYM_RRA (zym_cpu_t *z80) {
406 const uint8_t c = (z80->af.a&0x01u);
407 z80->af.a = (z80->af.a>>1)|((z80->af.f&ZYM_FLAG_C)<<7);
408 z80->flags_q = z80->af.f = c|(z80->af.a&ZYM_FLAG_35)|(z80->af.f&(ZYM_FLAG_PV|ZYM_FLAG_Z|ZYM_FLAG_S));
411 /* cyclic thru carry */
412 ZYMOSIS_INLINE uint8_t ZYM_RL (zym_cpu_t *z80, uint8_t b) {
413 const uint8_t c = (b>>7)&ZYM_FLAG_C;
414 z80->flags_q = z80->af.f = sz53p_tbl[(b = ((b<<1)&0xffu)|(z80->af.f&ZYM_FLAG_C))]|c;
415 return b;
419 ZYMOSIS_INLINE uint8_t ZYM_RR (zym_cpu_t *z80, uint8_t b) {
420 const uint8_t c = (b&0x01u);
421 z80->flags_q = z80->af.f = sz53p_tbl[(b = (b>>1)|((z80->af.f&ZYM_FLAG_C)<<7))]|c;
422 return b;
425 /* cyclic, carry reflects shifted bit */
426 ZYMOSIS_INLINE uint8_t ZYM_RLC (zym_cpu_t *z80, uint8_t b) {
427 const uint8_t c = ((b>>7)&ZYM_FLAG_C);
428 z80->flags_q = z80->af.f = sz53p_tbl[(b = ((b<<1)&0xffu)|c)]|c;
429 return b;
432 /* cyclic, carry reflects shifted bit */
433 ZYMOSIS_INLINE uint8_t ZYM_RRC (zym_cpu_t *z80, uint8_t b) {
434 const uint8_t c = (b&0x01u);
435 z80->flags_q = z80->af.f = sz53p_tbl[(b = (b>>1)|(c<<7))]|c;
436 return b;
439 /* shift left arithmetic, sets bit 0 to zero, carry reflects shifted bit */
440 ZYMOSIS_INLINE uint8_t ZYM_SLA (zym_cpu_t *z80, uint8_t b) {
441 uint8_t c = ((b>>7)&0x01u);
442 z80->flags_q = z80->af.f = sz53p_tbl[(b <<= 1)]|c;
443 return b;
446 /* shift right arithmetic, sets bit 6 to bit 7, carry reflects shifted bit */
447 ZYMOSIS_INLINE uint8_t ZYM_SRA (zym_cpu_t *z80, uint8_t b) {
448 const uint8_t c = (b&0x01u);
449 z80->flags_q = z80->af.f = sz53p_tbl[(b = (b>>1)|(b&0x80u))]|c;
450 return b;
453 /* shift left logic, sets bit 0 to one, carry reflects shifted bit */
454 ZYMOSIS_INLINE uint8_t ZYM_SLL (zym_cpu_t *z80, uint8_t b) {
455 const uint8_t c = ((b>>7)&0x01u);
456 z80->flags_q = z80->af.f = sz53p_tbl[(b = (b<<1)|0x01u)]|c;
457 return b;
460 /* shift right logic, sets bit 7 to zero, carry reflects shifted bit */
461 ZYMOSIS_INLINE uint8_t ZYM_SRL (zym_cpu_t *z80, uint8_t b) {
462 const uint8_t c = (b&0x01u);
463 z80->flags_q = z80->af.f = sz53p_tbl[(b >>= 1)]|c;
464 return b;
468 /* ddvalue+value */
469 ZYMOSIS_INLINE uint16_t ZYM_ADD_DD (zym_cpu_t *z80, const uint16_t value, const uint16_t ddvalue) {
470 /* `static` is more restrective here, simple `const` should generate better code */
471 /*static*/ const uint8_t hct[8] = { 0, ZYM_FLAG_H, ZYM_FLAG_H, ZYM_FLAG_H, 0, 0, 0, ZYM_FLAG_H };
472 const uint32_t res = (uint32_t)value+(uint32_t)ddvalue;
473 const uint8_t b = ((value&0x0800u)>>11)|((ddvalue&0x0800u)>>10)|((res&0x0800u)>>9);
474 z80->memptr.w = (ddvalue+1u)&0xffffu;
475 z80->flags_q = z80->af.f =
476 (z80->af.f&(ZYM_FLAG_PV|ZYM_FLAG_Z|ZYM_FLAG_S))|
477 (res > 0xffffu ? ZYM_FLAG_C : 0)|
478 ((res>>8)&ZYM_FLAG_35)|
479 hct[b];
480 return res;
483 /* ddvalue+value */
484 ZYMOSIS_INLINE uint16_t ZYM_ADC_DD (zym_cpu_t *z80, const uint16_t value, const uint16_t ddvalue) {
485 const uint8_t c = (z80->af.f&ZYM_FLAG_C);
486 const uint32_t newv = (uint32_t)value+(uint32_t)ddvalue+(uint32_t)c;
487 const uint16_t res = (newv&0xffffu);
488 z80->memptr.w = (ddvalue+1)&0xffffu;
489 z80->flags_q = z80->af.f =
490 ((res>>8)&ZYM_FLAG_S35)|
491 (res == 0 ? ZYM_FLAG_Z : 0)|
492 (newv > 0xffffu ? ZYM_FLAG_C : 0)|
493 ((value^((~ddvalue)&0xffffu))&(value^newv)&0x8000u ? ZYM_FLAG_PV : 0)|
494 ((value&0x0fffu)+(ddvalue&0x0fffu)+c >= 0x1000u ? ZYM_FLAG_H : 0);
495 return res;
498 /* ddvalue-value */
499 ZYMOSIS_INLINE uint16_t ZYM_SBC_DD (zym_cpu_t *z80, const uint16_t value, const uint16_t ddvalue) {
500 const uint8_t tmpB = z80->af.a;
501 z80->memptr.w = (ddvalue+1)&0xffffu;
502 z80->af.a = ddvalue&0xffu;
503 ZYM_SBC_A(z80, value&0xffu);
504 uint16_t res = z80->af.a;
505 z80->af.a = (ddvalue>>8)&0xffu;
506 ZYM_SBC_A(z80, (value>>8)&0xffu);
507 res |= (z80->af.a<<8);
508 z80->af.a = tmpB;
509 z80->flags_q = z80->af.f = (res ? z80->af.f&(~ZYM_FLAG_Z) : z80->af.f|ZYM_FLAG_Z);
510 return res;
514 ZYMOSIS_INLINE void ZYM_BIT (zym_cpu_t *z80, const uint8_t bit, const uint8_t num, const zym_bool mptr) {
515 z80->af.f =
516 ZYM_FLAG_H|
517 (z80->af.f&ZYM_FLAG_C)|
518 (num&ZYM_FLAG_35)|
519 (num&(1<<bit) ? 0 : ZYM_FLAG_PV|ZYM_FLAG_Z)|
520 (bit == 7 ? num&ZYM_FLAG_S : 0);
521 if (mptr) z80->af.f = (z80->af.f&~ZYM_FLAG_35)|(z80->memptr.h&ZYM_FLAG_35);
522 z80->flags_q = z80->af.f;
526 /* we can do this with table lookup, but why bother? */
527 ZYMOSIS_INLINE void ZYM_DAA (zym_cpu_t *z80) {
528 uint8_t tmpI = 0, tmpC = (z80->af.f&ZYM_FLAG_C), tmpA = z80->af.a;
529 if ((z80->af.f&ZYM_FLAG_H) || (tmpA&0x0fu) > 9) tmpI = 6;
530 if (tmpC != 0 || tmpA > 0x99u) tmpI |= 0x60u;
531 if (tmpA > 0x99u) tmpC = ZYM_FLAG_C;
532 if (z80->af.f&ZYM_FLAG_N) ZYM_SUB_A(z80, tmpI); else ZYM_ADD_A(z80, tmpI);
533 z80->flags_q = z80->af.f = (z80->af.f&~(ZYM_FLAG_C|ZYM_FLAG_PV))|tmpC|parity_tbl[z80->af.a];
537 ZYMOSIS_INLINE void ZYM_RRD_A (zym_cpu_t *z80) {
538 const uint8_t tmpB = z80_peekb_3ts(z80, z80->hl.w);
539 /*IOP(4)*/
540 z80->memptr.w = (z80->hl.w+1)&0xffffu;
541 z80_contention_by1ts(z80, z80->hl.w, 4);
542 z80_pokeb_3ts(z80, z80->hl.w, (z80->af.a<<4)|(tmpB>>4));
543 z80->af.a = (z80->af.a&0xf0u)|(tmpB&0x0fu);
544 z80->flags_q = z80->af.f = (z80->af.f&ZYM_FLAG_C)|sz53p_tbl[z80->af.a];
547 ZYMOSIS_INLINE void ZYM_RLD_A (zym_cpu_t *z80) {
548 const uint8_t tmpB = z80_peekb_3ts(z80, z80->hl.w);
549 /*IOP(4)*/
550 z80->memptr.w = (z80->hl.w+1)&0xffffu;
551 z80_contention_by1ts(z80, z80->hl.w, 4);
552 z80_pokeb_3ts(z80, z80->hl.w, (tmpB<<4)|(z80->af.a&0x0fu));
553 z80->af.a = (z80->af.a&0xf0u)|(tmpB>>4);
554 z80->flags_q = z80->af.f = (z80->af.f&ZYM_FLAG_C)|sz53p_tbl[z80->af.a];
558 ZYMOSIS_INLINE void ZYM_LD_A_IR (zym_cpu_t *z80, const uint8_t ir) {
559 z80->af.a = ir;
560 z80->prev_was_EIDDR = -1;
561 z80_contention_by1ts_ir(z80, 1);
562 z80->flags_q = z80->af.f = sz53_tbl[z80->af.a]|(z80->af.f&ZYM_FLAG_C)|(z80->iff2 ? ZYM_FLAG_PV : 0);
566 /******************************************************************************/
567 #define INC_R (z80->regR = ((z80->regR+1)&0x7fu)|(z80->regR&0x80u))
569 /* reference code:
570 #define SET_TRUE_CC() do { \
571 switch ((opcode>>3)&0x07u) { \
572 case 0: trueCC = (z80->af.f&ZYM_FLAG_Z) == 0; break; \
573 case 1: trueCC = (z80->af.f&ZYM_FLAG_Z) != 0; break; \
574 case 2: trueCC = (z80->af.f&ZYM_FLAG_C) == 0; break; \
575 case 3: trueCC = (z80->af.f&ZYM_FLAG_C) != 0; break; \
576 case 4: trueCC = (z80->af.f&ZYM_FLAG_PV) == 0; break; \
577 case 5: trueCC = (z80->af.f&ZYM_FLAG_PV) != 0; break; \
578 case 6: trueCC = (z80->af.f&ZYM_FLAG_S) == 0; break; \
579 case 7: trueCC = (z80->af.f&ZYM_FLAG_S) != 0; break; \
581 } while (0)
584 /* branch-less (assuming that `!` is branch-less) code */
585 static const uint8_t ccmask[4] = {
586 ZYM_FLAG_Z,
587 ZYM_FLAG_C,
588 ZYM_FLAG_PV,
589 ZYM_FLAG_S,
591 #define SET_TRUE_CC() trueCC = ((!(z80->af.f&ccmask[(opcode>>4)&0x03u]))^((opcode>>3)&0x01u))
594 #define INC_PC (z80->pc = (z80->pc+1u)&0xffffu)
595 #define DEC_PC (z80->pc = ((uint32_t)(z80->pc)-1u)&0xffffu)
597 #define INC_W(n) ((n) = ((n)+1u)&0xffffu)
598 #define DEC_W(n) ((n) = ((uint32_t)(n)-1u)&0xffffu)
600 /*#define XADD_W(n,v) ((n) = ((n)+(v))&0xffffu)*/
601 #define XSUB_W(n,v) ((n) = ((uint32_t)(n)-(uint32_t)(v))&0xffffu)
603 /* casting negative integer to unsigned is UB; sigh */
604 #define ZADD_W(n,v) ((n) = ((v) >= 0 ? ((uint32_t)(n)+(uint32_t)(v)) : ((uint32_t)(n)-(uint32_t)(-v)))&0xffffu)
606 /* casting negative integer to unsigned is UB; sigh */
607 #define ZADD_WX(n,v) (((v) >= 0 ? ((uint32_t)(n)+(uint32_t)(v)) : ((uint32_t)(n)-(uint32_t)(-v)))&0xffffu)
609 #define INC_B(n) ((n) = ((n)+1u)&0xffu)
610 #define DEC_B(n) ((n) = ((uint32_t)(n)-1u)&0xffu)
612 /* read opcode after prefix */
613 ZYMOSIS_INLINE uint8_t zym_get_opcode_ext (zym_cpu_t *z80) {
614 z80_contention(z80, z80->pc, 4, ZYM_MEMIO_OPCEXT, ZYM_MREQ_READ);
615 const uint8_t opc = z80->mem_read(z80, z80->pc, ZYM_MEMIO_OPCEXT);
616 z80->pc = (z80->pc+1)&0xffffu;
617 z80->regR = ((z80->regR+1)&0x7fu)|(z80->regR&0x80u);
618 return opc;
622 #define CBX_REPEATED (opcode&0x10u)
623 #define CBX_BACKWARD (opcode&0x08u)
626 int zym_exec_ex (zym_cpu_t *z80, int tscount) {
627 uint8_t opcode;
628 zym_bool gotDD, trueCC;
629 int disp;
630 int tstart = z80->tstates;
631 uint8_t tmpB, tmpC, rsrc, rdst;
632 uint16_t tmpW = 0; /* shut up the compiler; it's wrong but stubborn */
633 /* main loop */
634 while ((z80->next_event_tstate < 0 || z80->tstates < z80->next_event_tstate) &&
635 (tscount < 0 || z80->tstates-tstart <= tscount))
637 z80->prev_pc = z80->org_pc;
638 /* we should perform opcode fetching in loop, in case we need to refetch the opcode, or rollback on breakpoint */
639 for (;;) {
640 z80->refetch = 0;
641 if (z80->bp_hit) { z80->bp_was_hit = 1; z80->bp_hit = 0; return z80->tstates-tstart; }
642 z80->org_pc = z80->pc;
643 const int ots = z80->tstates;
644 /* call pager callback */
645 if (z80->opc_pager != NULL && z80->opc_pager(z80)) return z80->tstates-tstart;
646 /* read opcode -- OCR(4) */
647 /* t1: setting /MREQ & /RD */
648 /* t2: memory read */
649 /* t3, t4: decode command, increment R */
650 z80_contention(z80, z80->pc, 4, ZYM_MEMIO_OPCODE, ZYM_MREQ_READ);
651 z80->org_pc = z80->pc; /* in case contention messed with it */
652 if (z80->evenM1 && (z80->tstates&0x01u)) ++z80->tstates; /* emulate "even M1" if necessary */
653 opcode = z80->mem_read(z80, z80->pc, ZYM_MEMIO_OPCODE);
654 z80->org_pc = z80->pc; /* in case mem_read messed with it */
655 /* do we need to perform a rollback? */
656 if (!z80->bp_hit && !z80->refetch) {
657 z80->org_pc = z80->pc;
658 z80->pc = (z80->pc+1u)&0xffffu;
659 z80->regR = ((z80->regR+1u)&0x7fu)|(z80->regR&0x80u);
660 break;
662 /* rollback tstates */
663 z80->tstates = ots;
665 /* previous Q for SCF/CCF */
666 const uint8_t lastq = z80->flags_q;
667 z80->flags_q = 0;
668 z80->prev_was_EIDDR = 0;
669 disp = gotDD = 0;
670 z80->dd = &z80->hl;
671 if (z80->halted) { DEC_W(z80->pc); continue; }
672 /* check for I[XY] prefix */
673 if (opcode == 0xddu || opcode == 0xfdu) {
674 /* this is 256-bit bitmap indicates if the corresponding base opcode is using `(HL)` */
675 /* `static` is more restrective here, simple `const` should generate better code */
676 /*static*/ const uint32_t withIndexBmp[8] = {0x00u,0x700000u,0x40404040u,0x40bf4040u,0x40404040u,0x40404040u,0x0800u,0x00u};
677 /* IX/IY prefix */
678 z80->dd = (opcode == 0xddu ? &z80->ix : &z80->iy);
679 /* read opcode -- OCR(4) */
680 opcode = zym_get_opcode_ext(z80);
681 /* test if this instruction have (HL) */
682 if (withIndexBmp[opcode>>5]&(1u<<(opcode&0x1fu))) {
683 /* 3rd byte is always DISP here */
684 disp = z80_peekb_3ts_args(z80, z80->pc); if (disp > 127) disp -= 256;
685 INC_PC;
686 z80->memptr.w = ZADD_WX(z80->dd->w, disp);
687 } else if (opcode == 0xddu && opcode == 0xfdu) {
688 /* double prefix; restart main loop */
689 /* double prefix works as NOP, and blocks /INT */
690 z80->prev_was_EIDDR = 1;
691 /*FIXME: logically this should reset our Q value, but i am not sure; anyway, this works*/
692 z80->flags_q = 0;
693 continue;
695 gotDD = 1;
697 /* ED-prefixed instructions */
698 if (opcode == 0xedu) {
699 z80->dd = &z80->hl; /* ED-prefixed opcodes cannot use IX/IY */
700 /* read opcode -- OCR(4) */
701 opcode = zym_get_opcode_ext(z80);
702 switch (opcode) {
703 /* LDI, LDIR, LDD, LDDR */
704 case 0xa0u: case 0xb0u: case 0xa8u: case 0xb8u:
705 tmpB = z80_peekb_3ts(z80, z80->hl.w);
706 z80_pokeb_3ts(z80, z80->de.w, tmpB);
707 /*MWR(5)*/
708 z80_contention_by1ts(z80, z80->de.w, 2);
709 DEC_W(z80->bc.w);
710 tmpB = (tmpB+z80->af.a)&0xffu;
711 z80->flags_q = z80->af.f = /* BOO! FEAR THE MIGHTY BITS! */
712 (tmpB&ZYM_FLAG_3)|(z80->af.f&(ZYM_FLAG_C|ZYM_FLAG_Z|ZYM_FLAG_S))|
713 (z80->bc.w != 0 ? ZYM_FLAG_PV : 0)|
714 (tmpB&0x02u ? ZYM_FLAG_5 : 0);
715 if (CBX_REPEATED) {
716 if (z80->bc.w != 0) {
717 /*IOP(5)*/
718 z80_contention_by1ts(z80, z80->de.w, 5);
719 /* do it again */
720 XSUB_W(z80->pc, 2);
721 z80->memptr.w = (z80->pc+1)&0xffffu;
724 if (!CBX_BACKWARD) { INC_W(z80->hl.w); INC_W(z80->de.w); } else { DEC_W(z80->hl.w); DEC_W(z80->de.w); }
725 break;
726 /* CPI, CPIR, CPD, CPDR */
727 case 0xa1u: case 0xb1u: case 0xa9u: case 0xb9u:
728 /* MEMPTR */
729 if (CBX_REPEATED && (!(z80->bc.w == 1 || z80_peekb_i(z80, z80->hl.w) == z80->af.a))) {
730 z80->memptr.w = ZADD_WX(z80->org_pc, 1);
731 } else {
732 z80->memptr.w = ZADD_WX(z80->memptr.w, (CBX_BACKWARD ? -1 : 1));
734 tmpB = z80_peekb_3ts(z80, z80->hl.w);
735 /*IOP(5)*/
736 z80_contention_by1ts(z80, z80->hl.w, 5);
737 DEC_W(z80->bc.w);
738 z80->af.f = /* BOO! FEAR THE MIGHTY BITS! */
739 ZYM_FLAG_N|
740 (z80->af.f&ZYM_FLAG_C)|
741 (z80->bc.w != 0 ? ZYM_FLAG_PV : 0)|
742 ((int)(z80->af.a&0x0fu)-(int)(tmpB&0x0fu) < 0 ? ZYM_FLAG_H : 0);
743 tmpB = ((uint32_t)z80->af.a-(uint32_t)tmpB)&0xffu;
744 z80->af.f |= (tmpB == 0 ? ZYM_FLAG_Z : 0)|(tmpB&ZYM_FLAG_S);
745 if (z80->af.f&ZYM_FLAG_H) tmpB = ((uint16_t)tmpB-1)&0xffu;
746 z80->af.f |= (tmpB&ZYM_FLAG_3)|(tmpB&0x02u ? ZYM_FLAG_5 : 0);
747 z80->flags_q = z80->af.f;
748 if (CBX_REPEATED) {
749 /* repeated */
750 if ((z80->af.f&(ZYM_FLAG_Z|ZYM_FLAG_PV)) == ZYM_FLAG_PV) {
751 /*IOP(5)*/
752 z80_contention_by1ts(z80, z80->hl.w, 5);
753 /* do it again */
754 XSUB_W(z80->pc, 2);
757 if (CBX_BACKWARD) DEC_W(z80->hl.w); else INC_W(z80->hl.w);
758 break;
759 /* OUTI, OTIR, OUTD, OTDR */
760 case 0xa3u: case 0xb3u: case 0xabu: case 0xbbu:
761 DEC_B(z80->bc.b);
762 /* fallthru */
763 /* INI, INIR, IND, INDR */
764 case 0xa2u: case 0xb2u: case 0xaau: case 0xbau:
765 z80->memptr.w = ZADD_WX(z80->bc.w, (CBX_BACKWARD ? -1 : 1));
766 /*OCR(5)*/
767 z80_contention_by1ts_ir(z80, 1);
768 if (opcode&0x01u) {
769 /* OUT* */
770 tmpB = z80_peekb_3ts(z80, z80->hl.w);/*MRD(3)*/
771 z80_port_write(z80, z80->bc.w, tmpB);
772 tmpW = ZADD_WX(z80->hl.w, (CBX_BACKWARD ? -1 : 1));
773 tmpC = (tmpB+tmpW)&0xffu;
774 } else {
775 /* IN* */
776 tmpB = z80_port_read(z80, z80->bc.w);
777 z80_pokeb_3ts(z80, z80->hl.w, tmpB);/*MWR(3)*/
778 DEC_B(z80->bc.b);
779 if (CBX_BACKWARD) tmpC = ((uint32_t)tmpB+(uint32_t)z80->bc.c-1)&0xffu; else tmpC = (tmpB+z80->bc.c+1)&0xffu;
781 z80->flags_q = z80->af.f =
782 (tmpB&0x80u ? ZYM_FLAG_N : 0)|
783 (tmpC < tmpB ? ZYM_FLAG_H|ZYM_FLAG_C : 0)|
784 parity_tbl[(tmpC&0x07u)^z80->bc.b]|
785 sz53_tbl[z80->bc.b];
786 if (CBX_REPEATED) {
787 /* repeating commands */
788 if (z80->bc.b != 0) {
789 uint16_t a = (opcode&0x01u ? z80->bc.w : z80->hl.w);
790 /*IOP(5)*/
791 z80_contention_by1ts(z80, a, 5);
792 /* do it again */
793 XSUB_W(z80->pc, 2);
796 if (CBX_BACKWARD) DEC_W(z80->hl.w); else INC_W(z80->hl.w);
797 break;
798 /* not strings, but some good instructions anyway */
799 default:
800 if ((opcode&0xc0u) == 0x40u) {
801 /* 0x40...0x7f */
802 switch (opcode&0x07u) {
803 /* IN r8,(C) */
804 case 0:
805 z80->memptr.w = ZADD_WX(z80->bc.w, 1);
806 tmpB = z80_port_read(z80, z80->bc.w);
807 z80->flags_q = z80->af.f = sz53p_tbl[tmpB]|(z80->af.f&ZYM_FLAG_C);
808 switch ((opcode>>3)&0x07u) {
809 case 0: z80->bc.b = tmpB; break;
810 case 1: z80->bc.c = tmpB; break;
811 case 2: z80->de.d = tmpB; break;
812 case 3: z80->de.e = tmpB; break;
813 case 4: z80->hl.h = tmpB; break;
814 case 5: z80->hl.l = tmpB; break;
815 case 7: z80->af.a = tmpB; break;
816 /* 6 affects only flags */
818 break;
819 /* OUT (C),r8 */
820 case 1:
821 z80->memptr.w = ZADD_WX(z80->bc.w, 1);
822 switch ((opcode>>3)&0x07u) {
823 case 0: tmpB = z80->bc.b; break;
824 case 1: tmpB = z80->bc.c; break;
825 case 2: tmpB = z80->de.d; break;
826 case 3: tmpB = z80->de.e; break;
827 case 4: tmpB = z80->hl.h; break;
828 case 5: tmpB = z80->hl.l; break;
829 case 7: tmpB = z80->af.a; break;
830 /* 6 usually means (HL), but here it is 0xff for CMOS, and 0 for NMOS */
831 default: tmpB = (!z80->cmos ? 0x00u : 0xffu); break; /* `!` must tell the predictor our preferred path, NMOS */
833 z80_port_write(z80, z80->bc.w, tmpB);
834 break;
835 /* SBC HL,rr/ADC HL,rr */
836 case 2:
837 /*IOP(4),IOP(3)*/
838 z80_contention_by1ts_ir(z80, 7);
839 switch ((opcode>>4)&0x03u) {
840 case 0: tmpW = z80->bc.w; break;
841 case 1: tmpW = z80->de.w; break;
842 case 2: tmpW = z80->hl.w; break;
843 default: tmpW = z80->sp.w; break;
845 z80->hl.w = (opcode&0x08u ? ZYM_ADC_DD(z80, tmpW, z80->hl.w) : ZYM_SBC_DD(z80, tmpW, z80->hl.w));
846 break;
847 /* LD (nn),rr/LD rr,(nn) */
848 case 3:
849 tmpW = z80_getpcw(z80, 0);
850 z80->memptr.w = (tmpW+1)&0xffffu;
851 if (opcode&0x08u) {
852 /* LD rr,(nn) */
853 switch ((opcode>>4)&0x03u) {
854 case 0: z80->bc.w = z80_peekw_6ts(z80, tmpW); break;
855 case 1: z80->de.w = z80_peekw_6ts(z80, tmpW); break;
856 case 2: z80->hl.w = z80_peekw_6ts(z80, tmpW); break;
857 case 3: z80->sp.w = z80_peekw_6ts(z80, tmpW); break;
859 } else {
860 /* LD (nn),rr */
861 switch ((opcode>>4)&0x03u) {
862 case 0: z80_pokew_6ts(z80, tmpW, z80->bc.w); break;
863 case 1: z80_pokew_6ts(z80, tmpW, z80->de.w); break;
864 case 2: z80_pokew_6ts(z80, tmpW, z80->hl.w); break;
865 case 3: z80_pokew_6ts(z80, tmpW, z80->sp.w); break;
868 break;
869 /* NEG */
870 case 4:
871 tmpB = z80->af.a;
872 z80->af.a = 0;
873 ZYM_SUB_A(z80, tmpB);
874 break;
875 /* RETI/RETN */
876 case 5:
877 /*RETI: 0x4d, 0x5d, 0x6d, 0x7d*/
878 /*RETN: 0x45, 0x55, 0x65, 0x75*/
879 z80->iff1 = z80->iff2;
880 z80->memptr.w = z80->pc = z80_pop_6ts(z80);
881 if (opcode&0x08u) {
882 /* RETI */
883 if (z80->trap_reti != NULL && z80->trap_reti(z80, opcode)) return z80->tstates-tstart;
884 } else {
885 /* RETN */
886 if (z80->trap_retn != NULL && z80->trap_retn(z80, opcode)) return z80->tstates-tstart;
888 break;
889 /* IM n */
890 case 6:
891 switch (opcode) {
892 case 0x56u: case 0x76u: z80->im = 1; break;
893 case 0x5eu: case 0x7eu: z80->im = 2; break;
894 default: z80->im = 0; break;
896 break;
897 /* specials */
898 case 7:
899 switch (opcode) {
900 /* LD I,A */
901 case 0x47u:
902 /*OCR(5)*/
903 z80_contention_by1ts_ir(z80, 1);
904 z80->regI = z80->af.a;
905 break;
906 /* LD R,A */
907 case 0x4fu:
908 /*OCR(5)*/
909 z80_contention_by1ts_ir(z80, 1);
910 z80->regR = z80->af.a;
911 break;
912 /* LD A,I */
913 case 0x57u: ZYM_LD_A_IR(z80, z80->regI); break;
914 /* LD A,R */
915 case 0x5fu: ZYM_LD_A_IR(z80, z80->regR); break;
916 /* RRD */
917 case 0x67u: ZYM_RRD_A(z80); break;
918 /* RLD */
919 case 0x6F: ZYM_RLD_A(z80); break;
922 } else {
923 /* slt and other traps */
924 if (z80->trap_ed != NULL && z80->trap_ed(z80, opcode)) return z80->tstates-tstart;
926 break;
928 continue;
929 } /* 0xed done */
930 /* CB-prefixed instructions */
931 if (opcode == 0xcbu) {
932 /* shifts and bit operations */
933 /* read opcode -- OCR(4) */
934 if (!gotDD) {
935 opcode = zym_get_opcode_ext(z80);
936 } else {
937 z80_contention(z80, z80->pc, 3, ZYM_MEMIO_OPCEXT, ZYM_MREQ_READ);
938 opcode = z80->mem_read(z80, z80->pc, ZYM_MEMIO_OPCEXT);
939 z80_contention_by1ts_pc(z80, 2);
940 INC_PC;
942 if (gotDD) {
943 tmpW = ZADD_WX(z80->dd->w, disp);
944 tmpB = z80_peekb_3ts(z80, tmpW);
945 z80_contention_by1ts(z80, tmpW, 1);
946 } else {
947 switch (opcode&0x07u) {
948 case 0: tmpB = z80->bc.b; break;
949 case 1: tmpB = z80->bc.c; break;
950 case 2: tmpB = z80->de.d; break;
951 case 3: tmpB = z80->de.e; break;
952 case 4: tmpB = z80->hl.h; break;
953 case 5: tmpB = z80->hl.l; break;
954 case 6: tmpB = z80_peekb_3ts(z80, z80->hl.w); z80_contention(z80, z80->hl.w, 1, ZYM_MEMIO_DATA, ZYM_MREQ_READ); break;
955 case 7: tmpB = z80->af.a; break;
958 switch ((opcode>>3)&0x1fu) {
959 case 0: tmpB = ZYM_RLC(z80, tmpB); break;
960 case 1: tmpB = ZYM_RRC(z80, tmpB); break;
961 case 2: tmpB = ZYM_RL(z80, tmpB); break;
962 case 3: tmpB = ZYM_RR(z80, tmpB); break;
963 case 4: tmpB = ZYM_SLA(z80, tmpB); break;
964 case 5: tmpB = ZYM_SRA(z80, tmpB); break;
965 case 6: tmpB = ZYM_SLL(z80, tmpB); break;
966 case 7: tmpB = ZYM_SRL(z80, tmpB); break;
967 default:
968 switch ((opcode>>6)&0x03u) {
969 case 1: ZYM_BIT(z80, (opcode>>3)&0x07u, tmpB, (gotDD || (opcode&0x07u) == 6)); break;
970 case 2: tmpB &= ~(1<<((opcode>>3)&0x07u)); break; /* RES */
971 case 3: tmpB |= (1<<((opcode>>3)&0x07u)); break; /* SET */
973 break;
975 if ((opcode&0xc0u) != 0x40u) {
976 /* BITs are not welcome here */
977 if (gotDD) {
978 /* tmpW was set earlier */
979 if ((opcode&0x07u) != 6) z80_pokeb_3ts(z80, tmpW, tmpB);
981 switch (opcode&0x07u) {
982 case 0: z80->bc.b = tmpB; break;
983 case 1: z80->bc.c = tmpB; break;
984 case 2: z80->de.d = tmpB; break;
985 case 3: z80->de.e = tmpB; break;
986 case 4: z80->hl.h = tmpB; break;
987 case 5: z80->hl.l = tmpB; break;
988 case 6: z80_pokeb_3ts(z80, ZADD_WX(z80->dd->w, disp), tmpB); break;
989 case 7: z80->af.a = tmpB; break;
992 continue;
993 } /* 0xcb done */
994 /* normal things */
995 switch (opcode&0xc0u) {
996 /* 0x00..0x3F */
997 case 0x00u:
998 switch (opcode&0x07u) {
999 /* misc,DJNZ,JR,JR cc */
1000 case 0:
1001 if (opcode&0x30u) {
1002 /* branches */
1003 if (opcode&0x20u) {
1004 /* JR cc */
1006 switch ((opcode>>3)&0x03u) {
1007 case 0: trueCC = (z80->af.f&ZYM_FLAG_Z) == 0; break;
1008 case 1: trueCC = (z80->af.f&ZYM_FLAG_Z) != 0; break;
1009 case 2: trueCC = (z80->af.f&ZYM_FLAG_C) == 0; break;
1010 case 3: trueCC = (z80->af.f&ZYM_FLAG_C) != 0; break;
1011 default: trueCC = 0; break;
1014 trueCC = ((!(z80->af.f&ccmask[(opcode>>4)&0x01u]))^((opcode>>3)&0x01u));
1015 } else {
1016 /* DJNZ/JR */
1017 if ((opcode&0x08u) == 0) {
1018 /* DJNZ */
1019 /*OCR(5)*/
1020 z80_contention_by1ts_ir(z80, 1);
1021 DEC_B(z80->bc.b);
1022 trueCC = (z80->bc.b != 0);
1023 } else {
1024 /* JR */
1025 trueCC = 1;
1028 /* `disp` is always read, but FUSE tests require it this way; sigh */
1029 if (trueCC) {
1030 /* execute branch (relative) */
1031 disp = z80_peekb_3ts_args(z80, z80->pc);
1032 /*IOP(5)*/
1033 if (disp > 127) disp -= 256; /* convert to int8_t */
1034 z80_contention_by1ts_pc(z80, 5);
1035 INC_PC;
1036 ZADD_W(z80->pc, disp);
1037 z80->memptr.w = z80->pc;
1038 } else {
1039 z80_peekb_3ts_args_noread(z80, z80->pc);
1040 INC_PC;
1042 } else {
1043 /* EX AF,AF' or NOP */
1044 if (opcode != 0) zym_exaf_internal(z80);
1046 break;
1047 /* LD rr,nn/ADD HL,rr */
1048 case 1:
1049 if (opcode&0x08u) {
1050 /* ADD HL,rr */
1051 /*IOP(4),IOP(3)*/
1052 z80_contention_by1ts_ir(z80, 7);
1053 switch ((opcode>>4)&0x03u) {
1054 case 0: z80->dd->w = ZYM_ADD_DD(z80, z80->bc.w, z80->dd->w); break;
1055 case 1: z80->dd->w = ZYM_ADD_DD(z80, z80->de.w, z80->dd->w); break;
1056 case 2: z80->dd->w = ZYM_ADD_DD(z80, z80->dd->w, z80->dd->w); break;
1057 case 3: z80->dd->w = ZYM_ADD_DD(z80, z80->sp.w, z80->dd->w); break;
1059 } else {
1060 /* LD rr,nn */
1061 tmpW = z80_getpcw(z80, 0);
1062 switch ((opcode>>4)&0x03u) {
1063 case 0: z80->bc.w = tmpW; break;
1064 case 1: z80->de.w = tmpW; break;
1065 case 2: z80->dd->w = tmpW; break;
1066 case 3: z80->sp.w = tmpW; break;
1069 break;
1070 /* LD xxx,xxx */
1071 case 2:
1072 switch ((opcode>>3)&0x07u) {
1073 /* LD (BC),A */
1074 case 0: z80_pokeb_3ts(z80, z80->bc.w, z80->af.a); z80->memptr.l = (z80->bc.c+1)&0xffu; z80->memptr.h = z80->af.a; break;
1075 /* LD A,(BC) */
1076 case 1: z80->af.a = z80_peekb_3ts(z80, z80->bc.w); z80->memptr.w = (z80->bc.w+1)&0xffffu; break;
1077 /* LD (DE),A */
1078 case 2: z80_pokeb_3ts(z80, z80->de.w, z80->af.a); z80->memptr.l = (z80->de.e+1)&0xffu; z80->memptr.h = z80->af.a; break;
1079 /* LD A,(DE) */
1080 case 3: z80->af.a = z80_peekb_3ts(z80, z80->de.w); z80->memptr.w = (z80->de.w+1)&0xffffu; break;
1081 /* LD (nn),HL */
1082 case 4:
1083 tmpW = z80_getpcw(z80, 0);
1084 z80->memptr.w = (tmpW+1)&0xffffu;
1085 z80_pokew_6ts(z80, tmpW, z80->dd->w);
1086 break;
1087 /* LD HL,(nn) */
1088 case 5:
1089 tmpW = z80_getpcw(z80, 0);
1090 z80->memptr.w = (tmpW+1)&0xffffu;
1091 z80->dd->w = z80_peekw_6ts(z80, tmpW);
1092 break;
1093 /* LD (nn),A */
1094 case 6:
1095 tmpW = z80_getpcw(z80, 0);
1096 z80->memptr.l = (tmpW+1)&0xffu;
1097 z80->memptr.h = z80->af.a;
1098 z80_pokeb_3ts(z80, tmpW, z80->af.a);
1099 break;
1100 /* LD A,(nn) */
1101 case 7:
1102 tmpW = z80_getpcw(z80, 0);
1103 z80->memptr.w = (tmpW+1)&0xffffu;
1104 z80->af.a = z80_peekb_3ts(z80, tmpW);
1105 break;
1107 break;
1108 /* INC rr/DEC rr */
1109 case 3:
1110 /*OCR(6)*/
1111 z80_contention_by1ts_ir(z80, 2);
1112 if (opcode&0x08u) {
1113 /*DEC*/
1114 switch ((opcode>>4)&0x03u) {
1115 case 0: DEC_W(z80->bc.w); break;
1116 case 1: DEC_W(z80->de.w); break;
1117 case 2: DEC_W(z80->dd->w); break;
1118 case 3: DEC_W(z80->sp.w); break;
1120 } else {
1121 /*INC*/
1122 switch ((opcode>>4)&0x03u) {
1123 case 0: INC_W(z80->bc.w); break;
1124 case 1: INC_W(z80->de.w); break;
1125 case 2: INC_W(z80->dd->w); break;
1126 case 3: INC_W(z80->sp.w); break;
1129 break;
1130 /* INC r8 */
1131 case 4:
1132 switch ((opcode>>3)&0x07u) {
1133 case 0: z80->bc.b = ZYM_INC8(z80, z80->bc.b); break;
1134 case 1: z80->bc.c = ZYM_INC8(z80, z80->bc.c); break;
1135 case 2: z80->de.d = ZYM_INC8(z80, z80->de.d); break;
1136 case 3: z80->de.e = ZYM_INC8(z80, z80->de.e); break;
1137 case 4: z80->dd->h = ZYM_INC8(z80, z80->dd->h); break;
1138 case 5: z80->dd->l = ZYM_INC8(z80, z80->dd->l); break;
1139 case 6:
1140 if (gotDD) { DEC_PC; z80_contention_by1ts_pc(z80, 5); INC_PC; }
1141 tmpW = ZADD_WX(z80->dd->w, disp);
1142 tmpB = z80_peekb_3ts(z80, tmpW);
1143 z80_contention_by1ts(z80, tmpW, 1);
1144 tmpB = ZYM_INC8(z80, tmpB);
1145 z80_pokeb_3ts(z80, tmpW, tmpB);
1146 break;
1147 case 7: z80->af.a = ZYM_INC8(z80, z80->af.a); break;
1149 break;
1150 /* DEC r8 */
1151 case 5:
1152 switch ((opcode>>3)&0x07u) {
1153 case 0: z80->bc.b = ZYM_DEC8(z80, z80->bc.b); break;
1154 case 1: z80->bc.c = ZYM_DEC8(z80, z80->bc.c); break;
1155 case 2: z80->de.d = ZYM_DEC8(z80, z80->de.d); break;
1156 case 3: z80->de.e = ZYM_DEC8(z80, z80->de.e); break;
1157 case 4: z80->dd->h = ZYM_DEC8(z80, z80->dd->h); break;
1158 case 5: z80->dd->l = ZYM_DEC8(z80, z80->dd->l); break;
1159 case 6:
1160 if (gotDD) { DEC_PC; z80_contention_by1ts_pc(z80, 5); INC_PC; }
1161 tmpW = ZADD_WX(z80->dd->w, disp);
1162 tmpB = z80_peekb_3ts(z80, tmpW);
1163 z80_contention_by1ts(z80, tmpW, 1);
1164 tmpB = ZYM_DEC8(z80, tmpB);
1165 z80_pokeb_3ts(z80, tmpW, tmpB);
1166 break;
1167 case 7: z80->af.a = ZYM_DEC8(z80, z80->af.a); break;
1169 break;
1170 /* LD r8,n */
1171 case 6:
1172 tmpB = z80_peekb_3ts_args(z80, z80->pc);
1173 INC_PC;
1174 switch ((opcode>>3)&0x07u) {
1175 case 0: z80->bc.b = tmpB; break;
1176 case 1: z80->bc.c = tmpB; break;
1177 case 2: z80->de.d = tmpB; break;
1178 case 3: z80->de.e = tmpB; break;
1179 case 4: z80->dd->h = tmpB; break;
1180 case 5: z80->dd->l = tmpB; break;
1181 case 6:
1182 if (gotDD) { DEC_PC; z80_contention_by1ts_pc(z80, 2); INC_PC; }
1183 tmpW = ZADD_WX(z80->dd->w, disp);
1184 z80_pokeb_3ts(z80, tmpW, tmpB);
1185 break;
1186 case 7: z80->af.a = tmpB; break;
1188 break;
1189 /* swim-swim-hungry */
1190 case 7:
1191 switch ((opcode>>3)&0x07u) {
1192 case 0: ZYM_RLCA(z80); break;
1193 case 1: ZYM_RRCA(z80); break;
1194 case 2: ZYM_RLA(z80); break;
1195 case 3: ZYM_RRA(z80); break;
1196 case 4: ZYM_DAA(z80); break;
1197 case 5: /* CPL */
1198 z80->af.a ^= 0xffu;
1199 z80->flags_q = z80->af.f = (z80->af.a&ZYM_FLAG_35)|(ZYM_FLAG_N|ZYM_FLAG_H)|(z80->af.f&(ZYM_FLAG_C|ZYM_FLAG_PV|ZYM_FLAG_Z|ZYM_FLAG_S));
1200 break;
1201 case 6: /* SCF */
1202 /* `!` must tell the predictor our preferred path, NMOS */
1203 z80->flags_q = z80->af.f = (z80->af.f&(ZYM_FLAG_PV|ZYM_FLAG_Z|ZYM_FLAG_S))|((z80->af.a|(!z80->cmos ? lastq^z80->af.f : 0))&ZYM_FLAG_35)|ZYM_FLAG_C;
1204 break;
1205 case 7: /* CCF */
1206 /* `!` must tell the predictor our preferred path, NMOS */
1207 z80->flags_q = z80->af.f = (z80->af.f&(ZYM_FLAG_PV|ZYM_FLAG_Z|ZYM_FLAG_S))|((z80->af.a|(!z80->cmos ? lastq^z80->af.f : 0))&ZYM_FLAG_35)|(z80->af.f&ZYM_FLAG_C ? ZYM_FLAG_H : ZYM_FLAG_C);
1208 break;
1210 break;
1212 break;
1213 /* 0x40..0x7F (LD r8,r8) */
1214 case 0x40u:
1215 if (opcode == 0x76u) { z80->halted = 1; DEC_W(z80->pc); continue; } /* HALT */
1216 rsrc = (opcode&0x07u);
1217 rdst = ((opcode>>3)&0x07u);
1218 switch (rsrc) {
1219 case 0: tmpB = z80->bc.b; break;
1220 case 1: tmpB = z80->bc.c; break;
1221 case 2: tmpB = z80->de.d; break;
1222 case 3: tmpB = z80->de.e; break;
1223 case 4: tmpB = (gotDD && rdst == 6 ? z80->hl.h : z80->dd->h); break;
1224 case 5: tmpB = (gotDD && rdst == 6 ? z80->hl.l : z80->dd->l); break;
1225 case 6:
1226 if (gotDD) { DEC_PC; z80_contention_by1ts_pc(z80, 5); INC_PC; }
1227 tmpW = ZADD_WX(z80->dd->w, disp);
1228 tmpB = z80_peekb_3ts(z80, tmpW);
1229 break;
1230 case 7: tmpB = z80->af.a; break;
1232 switch (rdst) {
1233 case 0: z80->bc.b = tmpB; break;
1234 case 1: z80->bc.c = tmpB; break;
1235 case 2: z80->de.d = tmpB; break;
1236 case 3: z80->de.e = tmpB; break;
1237 case 4: if (gotDD && rsrc == 6) z80->hl.h = tmpB; else z80->dd->h = tmpB; break;
1238 case 5: if (gotDD && rsrc == 6) z80->hl.l = tmpB; else z80->dd->l = tmpB; break;
1239 case 6:
1240 if (gotDD) { DEC_PC; z80_contention_by1ts_pc(z80, 5); INC_PC; }
1241 tmpW = ZADD_WX(z80->dd->w, disp);
1242 z80_pokeb_3ts(z80, tmpW, tmpB);
1243 break;
1244 case 7: z80->af.a = tmpB; break;
1246 break;
1247 /* 0x80..0xBF (ALU A,r8) */
1248 case 0x80u:
1249 switch (opcode&0x07u) {
1250 case 0: tmpB = z80->bc.b; break;
1251 case 1: tmpB = z80->bc.c; break;
1252 case 2: tmpB = z80->de.d; break;
1253 case 3: tmpB = z80->de.e; break;
1254 case 4: tmpB = z80->dd->h; break;
1255 case 5: tmpB = z80->dd->l; break;
1256 case 6:
1257 if (gotDD) { DEC_PC; z80_contention_by1ts_pc(z80, 5); INC_PC; }
1258 tmpW = ZADD_WX(z80->dd->w, disp);
1259 tmpB = z80_peekb_3ts(z80, tmpW);
1260 break;
1261 case 7: tmpB = z80->af.a; break;
1263 switch ((opcode>>3)&0x07u) {
1264 case 0: ZYM_ADD_A(z80, tmpB); break;
1265 case 1: ZYM_ADC_A(z80, tmpB); break;
1266 case 2: ZYM_SUB_A(z80, tmpB); break;
1267 case 3: ZYM_SBC_A(z80, tmpB); break;
1268 case 4: ZYM_AND_A(z80, tmpB); break;
1269 case 5: ZYM_XOR_A(z80, tmpB); break;
1270 case 6: ZYM_OR_A(z80, tmpB); break;
1271 case 7: ZYM_CP_A(z80, tmpB); break;
1273 break;
1274 /* 0xC0..0xFF */
1275 case 0xC0:
1276 switch (opcode&0x07u) {
1277 /* RET cc */
1278 case 0:
1279 z80_contention_by1ts_ir(z80, 1);
1280 SET_TRUE_CC();
1281 if (trueCC) z80->memptr.w = z80->pc = z80_pop_6ts(z80);
1282 break;
1283 /* POP rr/special0 */
1284 case 1:
1285 if (opcode&0x08u) {
1286 /* special 0 */
1287 switch ((opcode>>4)&0x03u) {
1288 /* RET */
1289 case 0: z80->memptr.w = z80->pc = z80_pop_6ts(z80); break;
1290 /* EXX */
1291 case 1: zym_exx_internal(z80); break;
1292 /* JP (HL) */
1293 case 2: z80->pc = z80->dd->w; break;
1294 /* LD SP,HL */
1295 case 3:
1296 /*OCR(6)*/
1297 z80_contention_by1ts_ir(z80, 2);
1298 z80->sp.w = z80->dd->w;
1299 break;
1301 } else {
1302 /* POP rr */
1303 tmpW = z80_pop_6ts(z80);
1304 switch ((opcode>>4)&0x03u) {
1305 case 0: z80->bc.w = tmpW; break;
1306 case 1: z80->de.w = tmpW; break;
1307 case 2: z80->dd->w = tmpW; break;
1308 case 3: z80->af.w = tmpW; break;
1311 break;
1312 /* JP cc,nn */
1313 case 2:
1314 SET_TRUE_CC();
1315 z80->memptr.w = z80_getpcw(z80, 0);
1316 if (trueCC) z80->pc = z80->memptr.w;
1317 break;
1318 /* special1/special3 */
1319 case 3:
1320 switch ((opcode>>3)&0x07u) {
1321 /* JP nn */
1322 case 0: z80->memptr.w = z80->pc = z80_getpcw(z80, 0); break;
1323 /* OUT (n),A */
1324 case 2:
1325 tmpW = z80_peekb_3ts_args(z80, z80->pc);
1326 INC_PC;
1327 z80->memptr.l = (tmpW+1)&0xffu;
1328 z80->memptr.h = z80->af.a;
1329 tmpW |= (((uint16_t)(z80->af.a))<<8);
1330 z80_port_write(z80, tmpW, z80->af.a);
1331 break;
1332 /* IN A,(n) */
1333 case 3:
1334 tmpB = z80_peekb_3ts_args(z80, z80->pc);
1335 tmpW = (uint16_t)((((uint16_t)(z80->af.a))<<8)|tmpB);
1336 INC_PC;
1337 z80->memptr.w = (tmpW+1)&0xffffu;
1338 z80->af.a = z80_port_read(z80, tmpW);
1339 break;
1340 /* EX (SP),HL */
1341 case 4:
1342 /*SRL(3),SRH(4)*/
1343 tmpW = z80_peekw_6ts(z80, z80->sp.w);
1344 z80_contention_by1ts(z80, (z80->sp.w+1)&0xffffu, 1);
1345 /*SWL(3),SWH(5)*/
1346 z80_pokew_6ts_inverted(z80, z80->sp.w, z80->dd->w);
1347 z80_contention_by1ts(z80, z80->sp.w, 2);
1348 z80->memptr.w = z80->dd->w = tmpW;
1349 break;
1350 /* EX DE,HL */
1351 case 5:
1352 tmpW = z80->de.w;
1353 z80->de.w = z80->hl.w;
1354 z80->hl.w = tmpW;
1355 break;
1356 /* DI */
1357 case 6: z80->iff1 = z80->iff2 = 0; break;
1358 /* EI */
1359 case 7: z80->iff1 = z80->iff2 = 1; z80->prev_was_EIDDR = 1; break;
1361 break;
1362 /* CALL cc,nn */
1363 case 4:
1364 SET_TRUE_CC();
1365 z80->memptr.w = z80_getpcw(z80, trueCC);
1366 if (trueCC) {
1367 z80_push_6ts(z80, z80->pc);
1368 z80->pc = z80->memptr.w;
1370 break;
1371 /* PUSH rr/special2 */
1372 case 5:
1373 if (opcode&0x08u) {
1374 if (((opcode>>4)&0x03u) == 0) {
1375 /* CALL */
1376 z80->memptr.w = tmpW = z80_getpcw(z80, 1);
1377 z80_push_6ts(z80, z80->pc);
1378 z80->pc = tmpW;
1380 } else {
1381 /* PUSH rr */
1382 /*OCR(5)*/
1383 z80_contention_by1ts_ir(z80, 1);
1384 switch ((opcode>>4)&0x03u) {
1385 case 0: tmpW = z80->bc.w; break;
1386 case 1: tmpW = z80->de.w; break;
1387 case 2: tmpW = z80->dd->w; break;
1388 default: tmpW = z80->af.w; break;
1390 z80_push_6ts(z80, tmpW);
1392 break;
1393 /* ALU A,n */
1394 case 6:
1395 tmpB = z80_peekb_3ts_args(z80, z80->pc);
1396 INC_PC;
1397 switch ((opcode>>3)&0x07u) {
1398 case 0: ZYM_ADD_A(z80, tmpB); break;
1399 case 1: ZYM_ADC_A(z80, tmpB); break;
1400 case 2: ZYM_SUB_A(z80, tmpB); break;
1401 case 3: ZYM_SBC_A(z80, tmpB); break;
1402 case 4: ZYM_AND_A(z80, tmpB); break;
1403 case 5: ZYM_XOR_A(z80, tmpB); break;
1404 case 6: ZYM_OR_A(z80, tmpB); break;
1405 case 7: ZYM_CP_A(z80, tmpB); break;
1407 break;
1408 /* RST nnn */
1409 case 7:
1410 /*OCR(5)*/
1411 z80_contention_by1ts_ir(z80, 1);
1412 z80_push_6ts(z80, z80->pc);
1413 z80->memptr.w = z80->pc = opcode&0x38u;
1414 break;
1416 break;
1417 } /* end switch */
1419 return z80->tstates-tstart;
1423 int zym_exec_step (zym_cpu_t *z80) {
1424 const int32_t one = z80->next_event_tstate;
1425 z80->next_event_tstate = -1;
1426 const int res = zym_exec_ex(z80, 1);
1427 z80->next_event_tstate = one;
1428 return res;
1432 /******************************************************************************/
1433 /* changes z80->tstates if interrupt occurs */
1434 int zym_intr (zym_cpu_t *z80) {
1435 uint16_t a;
1436 const int32_t ots = z80->tstates;
1437 /* emulate NMOS Z80 bug: interruptet LD A,<I|R> copies cleared flag */
1438 /*FIXME: what is the state of `z80->flags_q` here? */
1439 if (z80->prev_was_EIDDR < 0) { z80->prev_was_EIDDR = 0; if (!z80->cmos) z80->flags_q = (z80->af.f &= ~ZYM_FLAG_PV); }
1440 if (z80->prev_was_EIDDR || !z80->iff1) return 0; /* not accepted */
1441 z80->flags_q = 0; /* we cannot do it earlier, because ignored interrupt won't reset flags */
1442 if (z80->halted) { z80->halted = 0; INC_PC; }
1443 z80->iff1 = z80->iff2 = 0; /* disable interrupts */
1444 switch ((z80->im &= 0x03u)) {
1445 case 3: /* ??? */ z80->im = 0; /* fallthru */
1446 case 0: /* take instruction from the bus (for now we assume that reading from bus always returns 0xff) */
1447 /* with a CALL nnnn on the data bus, it takes 19 cycles: */
1448 /* M1 cycle: 7 T to acknowledge interrupt (where exactly data bus reading occures?) */
1449 /* M2 cycle: 3 T to read low byte of 'nnnn' from data bus */
1450 /* M3 cycle: 3 T to read high byte of 'nnnn' and decrement SP */
1451 /* M4 cycle: 3 T to write high byte of PC to the stack and decrement SP */
1452 /* M5 cycle: 3 T to write low byte of PC and jump to 'nnnn' */
1453 z80->tstates += 6;
1454 /* fallthru */
1455 case 1: /* just do RST #38 */
1456 INC_R;
1457 z80->tstates += 7; /* M1 cycle: 7 T to acknowledge interrupt and decrement SP */
1458 /* M2 cycle: 3 T states write high byte of PC to the stack and decrement SP */
1459 /* M3 cycle: 3 T states write the low byte of PC and jump to #0038 */
1460 z80_push_6ts(z80, z80->pc);
1461 z80->memptr.w = z80->pc = 0x38u;
1462 break;
1463 case 2:
1464 INC_R;
1465 z80->tstates += 7; /* M1 cycle: 7 T to acknowledge interrupt and decrement SP */
1466 /* M2 cycle: 3 T states write high byte of PC to the stack and decrement SP */
1467 /* M3 cycle: 3 T states write the low byte of PC */
1468 z80_push_6ts(z80, z80->pc);
1469 /* M4 cycle: 3 T to read high byte from the interrupt vector */
1470 /* M5 cycle: 3 T to read low byte from bus and jump to interrupt routine */
1471 a = (((uint16_t)z80->regI)<<8)|0xffu;
1472 z80->memptr.w = z80->pc = z80_peekw_6ts(z80, a);
1473 break;
1475 return z80->tstates-ots; /* accepted */
1479 /* changes z80->tstates if interrupt occurs */
1480 int zym_nmi (zym_cpu_t *z80) {
1481 const int32_t ots = z80->tstates;
1482 /* emulate NMOS Z80 bug: interruptet LD A,<I|R> copies cleared flag */
1483 /*FIXME: what is the state of `z80->flags_q` here? */
1484 if (z80->prev_was_EIDDR < 0) { z80->prev_was_EIDDR = 0; if (!z80->cmos) z80->flags_q = (z80->af.f &= ~ZYM_FLAG_PV); }
1485 if (z80->prev_was_EIDDR) return 0;
1486 z80->flags_q = 0; /* we cannot do it earlier, because ignored interrupt won't reset flags */
1487 if (z80->halted) { z80->halted = 0; INC_PC; }
1488 INC_R;
1489 z80->iff1 = 0; /* IFF2 is not changed */
1490 z80->tstates += 5; /* M1 cycle: 5 T states to do an opcode read and decrement SP */
1491 /* M2 cycle: 3 T states write high byte of PC to the stack and decrement SP */
1492 /* M3 cycle: 3 T states write the low byte of PC and jump to #0066 */
1493 z80_push_6ts(z80, z80->pc);
1494 z80->memptr.w = z80->pc = 0x66u;
1495 return z80->tstates-ots;
1499 /******************************************************************************/
1500 unsigned zym_pop (zym_cpu_t *z80) {
1501 uint16_t res = z80_peekb_i(z80, z80->sp.w);
1502 z80->sp.w = (z80->sp.w+1)&0xffffu;
1503 res |= ((uint16_t)z80_peekb_i(z80, z80->sp.w))<<8;
1504 z80->sp.w = (z80->sp.w+1)&0xffffu;
1505 return (unsigned)res;
1509 void zym_push (zym_cpu_t *z80, const uint16_t value) {
1510 z80->sp.w = (((uint32_t)z80->sp.w)-1u)&0xffffu;
1511 z80_pokeb_i(z80, z80->sp.w, (value>>8)&0xffu);
1512 z80->sp.w = (((uint32_t)z80->sp.w)-1u)&0xffffu;
1513 z80_pokeb_i(z80, z80->sp.w, value&0xffu);
1517 /******************************************************************************
1518 instruction decoding
1519 ====================
1520 00 00y 000 -- special
1521 00 01g 000 -- DJNZ/JR
1522 00 1cc 000 -- JR cc,n
1523 00 rr0 001 -- LD rr,nn
1524 00 rr1 001 -- ADD HL,rr
1525 00 000 010 -- LD (BC),A
1526 00 001 010 -- LD A,(BC)
1527 00 010 010 -- LD (DE),A
1528 00 011 010 -- LD A,(DE)
1529 00 100 010 -- LD (nn),HL
1530 00 101 010 -- LD HL,(nn)
1531 00 110 010 -- LD (nn),A
1532 00 111 010 -- LD A,(nn)
1533 00 rr0 011 -- INC rr
1534 00 rr1 011 -- DEC rr
1535 00 rrr 100 -- INC r8
1536 00 rrr 101 -- DEC r8
1537 00 rrr 110 -- LD r8,n
1538 00 xxx 111 -- special
1541 0 - NOP
1542 1 - EX AF,AF'
1544 0 - DJNZ
1545 1 - JR
1547 00 - NZ
1548 01 - Z
1549 10 - NC
1550 11 - C
1551 xxx:
1552 000 - RLCA
1553 001 - RRCA
1554 010 - RLA
1555 011 - RRA
1556 100 - DAA
1557 101 - CPL
1558 110 - SCF
1559 111 - CCF
1560 rrr:
1561 000 - B
1562 001 - C
1563 010 - D
1564 011 - E
1565 100 - H
1566 101 - L
1567 110 - (HL)
1568 111 - A
1570 00 - BC
1571 01 - DE
1572 10 - HL
1573 11 - SP
1575 ---------------------------------
1577 01 rrr rrr - LD r8,r8 (lo: src)
1579 ---------------------------------
1581 10 alu rrr - ALU a,r8
1582 alu:
1583 000 - ADD
1584 001 - ADC
1585 010 - SUB
1586 011 - SBC
1587 100 - AND
1588 101 - XOR
1589 110 - OR
1590 111 - CP
1592 ---------------------------------
1594 11 ccc 000 -- RET cc
1595 11 rr0 001 -- POP rr
1596 11 xx1 001 -- special0
1597 11 ccc 010 -- JP cc,nn
1598 11 yyy 011 -- special1
1599 11 ccc 100 -- CALL cc,nn
1600 11 rr0 101 -- PUSH rr
1601 11 zz1 101 -- special2
1602 11 alu 110 -- alu A,n
1603 11 aaa 111 -- RST nnn
1606 00 - BC
1607 01 - DE
1608 10 - HL
1609 11 - AF
1610 aaa: RST addr=aaa<<3
1611 ccc:
1612 000 - NZ
1613 001 - Z
1614 010 - NC
1615 011 - C
1616 100 - PO
1617 101 - PE
1618 110 - P
1619 111 - M
1620 alu:
1621 000 - ADD
1622 001 - ADC
1623 010 - SUB
1624 011 - SBC
1625 100 - AND
1626 101 - XOR
1627 110 - OR
1628 111 - CP
1630 00 - RET
1631 01 - EXX
1632 10 - JP HL
1633 11 - LD SP,HL
1634 yyy:
1635 000 - JP nn
1636 001 - CB
1637 010 - OUT (n),A
1638 011 - IN A,(n)
1639 100 - EX (SP),HL
1640 101 - EX DE,HL
1641 110 - DI
1642 111 - EI
1644 00 - CALL nn
1645 01 - DD
1646 10 - ED
1647 11 - FD
1650 ---------------------------------
1653 01 rrr 000 -- IN r8,(C)
1654 01 rrr 001 -- OUT (C),r8
1655 01 rr0 010 -- SBC HL,rr
1656 01 rr1 010 -- ADC HL,rr
1657 01 rr0 011 -- LD (nn),rr
1658 01 rr1 011 -- LD rr,(nn)
1660 01 000 100 -- NEG
1661 01 001 100 -- NEG
1662 01 010 100 -- NEG
1663 01 011 100 -- NEG
1664 01 100 100 -- NEG
1665 01 101 100 -- NEG
1666 01 110 100 -- NEG
1667 01 111 100 -- NEG
1669 01 000 101 -- RETN
1670 01 001 101 -- RETI
1671 01 010 101 -- RETN
1672 01 011 101 -- RETI
1673 01 100 101 -- RETN
1674 01 101 101 -- RETI
1675 01 110 101 -- RETN
1676 01 111 101 -- RETI
1678 01 000 110 -- IM 0
1679 01 001 110 -- IM 0/1
1680 01 010 110 -- IM 1
1681 01 011 110 -- IM 2
1682 01 100 110 -- IM 0
1683 01 101 110 -- IM 0
1684 01 111 110 -- IM 2
1686 01 000 111 -- LD I,A
1687 01 001 111 -- LD R,A
1688 01 010 111 -- LD A,I
1689 01 011 111 -- LD A,R
1690 01 100 111 -- RRD
1691 01 101 111 -- RLD
1692 01 110 111 -- NOP
1693 01 111 111 -- NOP
1696 10 1rd 0tt
1697 r: repeating instruction? (1: yes)
1698 d: direction (0:inc; 1:dec)
1699 tt: instruction type
1700 00: LD
1701 01: CP
1702 10: IN
1703 11: OUT
1705 10 100 000 -- LDI
1706 10 110 000 -- LDIR
1707 10 101 000 -- LDD
1708 10 111 000 -- LDDR
1710 10 100 001 -- CPI
1711 10 110 001 -- CPIR
1712 10 101 001 -- CPD
1713 10 111 001 -- CPDR
1715 10 100 010 -- INI
1716 10 110 010 -- INIR
1717 10 101 010 -- IND
1718 10 111 010 -- INDR
1720 10 100 011 -- OUTI
1721 10 110 011 -- OTIR
1722 10 101 011 -- OUTD
1723 10 111 011 -- OTDR
1726 ---------------------------------
1728 zz xxx rrr
1730 rrr: the usual r8
1733 00 -- see below
1734 01 -- BIT n, r8
1735 10 -- RES n, r8
1736 11 -- SET n, r8
1738 for bitops, xxx is bit number
1740 xxx:
1741 000 - RLC r8
1742 001 - RRC r8
1743 010 - RL r8
1744 011 - RR r8
1745 100 - SLA r8
1746 101 - SRA r8
1747 110 - SLL r8
1748 111 - SRL r8
1750 for DD/FD prefix, 3rd byte is always disp,
1751 and the result is always written to (I<X|Y>+disp)
1754 command reading cycles
1755 ======================
1756 the following is not 100% correct, but the position
1757 of the contention cycles is right
1759 m1 cycle (accoding to the official Zilog manual)
1760 t1: setting /MREQ & /RD
1761 t2: memory read
1762 here comes contetion (AFTER t2!)
1763 t3,t4: decode command, increment R
1765 memory read/write cycles (accoding to the official Zilog manual)
1766 t1,t2: memory address select
1767 here comes contetion (AFTER t2!)
1768 t3: bus read/write
1770 port i/o cycles (accoding to the official Zilog manual)
1771 t1,t2: port address select
1772 tw: automatic wait tick
1773 here comes contetion (AFTER t2!)
1774 t3: bus read/write
1777 flag register bits
1778 ==================
1779 bit 0: carry
1780 bit 1: flagN (see below)
1781 bit 2: parity/overflow
1782 bit 3: bit3
1783 bit 4: half-carry
1784 bit 5: bit5
1785 bit 6: zero
1786 bit 7: sign
1788 flagN:
1789 set if the last operation was a subtraction (used by DAA).
1791 P/V - parity or overflow
1792 parity set if even number of bits set
1793 overflow set if the 2-complement result does not fit in the register
1795 *******************************************************************************/