zymosis: renamed "SLL" to "SLS"
[zymosis.git] / src / libzymosis / zymosis.c
blob39dd95abb03db3106fd949038388e49af8f3e3a2
1 /*
2 * Z80 CPU emulation engine v0.1.2.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 /* casting negative integer to unsigned is UB; sigh */
47 #ifdef ZYMOSIS_TRY_TO_AVOID_UB
48 # define ZADD_WX(n,v) ((uint16_t)(((v) >= 0 ? ((uint32_t)(n)+(uint32_t)(v)) : ((uint32_t)(n)-(uint32_t)(-v)))))
49 #else
50 # define ZADD_WX(n,v) ((uint16_t)((uint16_t)(n) + (uint16_t)(v)))
51 #endif
53 #define INC_R (z80->regR = ((z80->regR+1u)&0x7fu)|(z80->regR&0x80u))
54 #define DEC_R (z80->regR = ((z80->regR-1u)&0x7fu)|(z80->regR&0x80u))
57 /******************************************************************************/
58 /* some funny tables */
59 static int32_t tables_inited = 0;
60 static uint8_t parity_tbl[256];
61 static uint8_t sz53_tbl[256]; /* bits 3, 5 and 7 of result, Z flag */
62 static uint8_t sz53p_tbl[256]; /* bits 3, 5 and 7 of result, Z and P flags */
65 //**************************************************************************
67 // various initialisations
69 //**************************************************************************
71 // initialise internal flag tables
72 // WARNING! this is NOT thread-safe!
73 void zym_init_tables (void) {
74 if (tables_inited) return;
75 for (unsigned f = 0; f < 256; ++f) {
76 unsigned n, p;
77 sz53_tbl[f] = (f&ZYM_FLAG_S35);
78 for (n = f, p = 0; n != 0; n >>= 1) p ^= n&0x01u;
79 parity_tbl[f] = (p ? 0 : ZYM_FLAG_PV);
80 sz53p_tbl[f] = (sz53_tbl[f]|parity_tbl[f]);
82 sz53_tbl[0] |= ZYM_FLAG_Z;
83 sz53p_tbl[0] |= ZYM_FLAG_Z;
84 tables_inited = 1;
88 #if defined(__GNUC__)
89 static __attribute__((constructor)) void zym_init_tables_ctor (void) {
90 zym_init_tables();
92 #endif
95 // "no memory contention" callback
96 void zym_no_mem_contention_cb (zym_cpu_t *z80, uint16_t addr,
97 zym_memio_t mio, zym_memreq_t mreq)
102 // should be called on new instance of zym_cpu_t to clear all callbacks
103 void zym_clear_callbacks (zym_cpu_t *z80) {
104 if (!tables_inited) zym_init_tables();
105 z80->mem_read = NULL;
106 z80->mem_write = NULL;
107 z80->mem_contention = &zym_no_mem_contention_cb;
108 z80->port_read = NULL;
109 z80->port_write = NULL;
110 z80->port_contention = NULL;
111 z80->trap_halt = NULL;
112 z80->trap_reti = NULL;
113 z80->trap_retn = NULL;
114 z80->trap_edfb = NULL;
115 z80->trap_edfe = NULL;
119 // clear all flags and callbacks; will reset 'z80->user' too
120 void zym_init (zym_cpu_t *z80) {
121 if (!tables_inited) zym_init_tables();
122 memset(z80, 0, sizeof(*z80));
123 // there is no guarantee that NULL is 0 in the standard (sigh)
124 zym_clear_callbacks(z80);
125 z80->user = NULL;
126 z80->next_event_tstate = -1;
130 // resets Z80 CPU
131 // seems that all regs (and memptr) should be set to 'all 1' here, but i don't care
132 void zym_reset (zym_cpu_t *z80) {
133 if (!tables_inited) zym_init_tables();
134 z80->bc.w = z80->de.w = z80->hl.w = z80->af.w = z80->sp.w = z80->ix.w = z80->iy.w = 0;
135 z80->bcx.w = z80->dex.w = z80->hlx.w = z80->afx.w = 0;
136 z80->pc = z80->prev_pc = z80->org_pc = 0;
137 z80->memptr.w = 0;
138 z80->regI = z80->regR = 0;
139 z80->iff1 = z80->iff2 = 0;
140 z80->im = 0;
141 z80->halted = 0;
142 z80->prev_was_EIDDR = 0;
143 z80->tstates = 0;
144 z80->dd = &z80->hl;
145 z80->flags_q = 0;
149 //**************************************************************************
151 // alternate register set functions
153 //**************************************************************************
155 ZYMOSIS_INLINE void zym_exx_internal (zym_cpu_t *z80) {
156 uint16_t t = z80->bc.w; z80->bc.w = z80->bcx.w; z80->bcx.w = t;
157 t = z80->de.w; z80->de.w = z80->dex.w; z80->dex.w = t;
158 t = z80->hl.w; z80->hl.w = z80->hlx.w; z80->hlx.w = t;
162 ZYMOSIS_INLINE void zym_exaf_internal (zym_cpu_t *z80) {
163 const uint16_t t = z80->af.w; z80->af.w = z80->afx.w; z80->afx.w = t;
167 // swap normal and alternate register sets (except AF/AF')
168 void zym_exx (zym_cpu_t *z80) {
169 zym_exx_internal(z80);
173 // swap normal and alternate AF
174 void zym_exaf (zym_cpu_t *z80) {
175 zym_exaf_internal(z80);
179 /******************************************************************************/
180 /* simulate contented memory access */
181 /* (tstates = tstates+contention+1)*cnt */
182 /* (zym_cpu_t *z80, uint16_t addr, int tstates, zym_memio_t mio) */
183 #define z80_contention(z80_,addr_,mio_,mrq_) do { \
184 (z80_)->mem_contention((z80_), (addr_), (mio_), (mrq_)); \
185 } while (0)
188 #define z80_contention_by1ts(z80_,addr_,cnt_) do { \
189 const uint16_t xaddr_ = (addr_); \
190 uint32_t fcnt_ = (cnt_); \
191 do { \
192 fcnt_ -= 1; \
193 (z80_)->mem_contention((z80_), xaddr_, ZYM_MEMIO_OTHER, ZYM_MREQ_NONE); \
194 (z80_)->tstates += 1; \
195 } while (fcnt_ != 0); \
196 } while (0)
199 #define z80_contention_by1ts_ir(z80_,cnt_) z80_contention_by1ts((z80_), (((uint16_t)(z80_)->regI)<<8)|((z80_)->regR), (cnt_))
200 #define z80_contention_by1ts_pc(z80_,cnt_) z80_contention_by1ts((z80_), (z80_)->pc, (cnt_))
203 /******************************************************************************/
204 ZYMOSIS_INLINE uint8_t z80_port_read (zym_cpu_t *z80, const uint16_t port) {
205 uint8_t value;
206 /* i don't really know: FUSE tester seems to do port read in-between contentions,
207 but the actual emulator code does it after all contentions are done.
208 i guess that doing it in-between is the right way.
209 note: ok, it broke floating bus emulation in ZXEmuT. oopsie!
211 if (z80->port_contention != NULL) {
212 z80->port_contention(z80, port, 1, ZYM_PORTIO_FLAG_IN|ZYM_PORTIO_FLAG_EARLY);
213 z80->port_read_tstates = z80->tstates;
214 #ifdef ZYMOSIS_FUSE_TEST
215 /* for FUSE tests, it should be here */
216 value = z80->port_read(z80, port, ZYM_PORTIO_NORMAL);
217 #endif
218 z80->port_contention(z80, port, 2, ZYM_PORTIO_FLAG_IN);
219 #ifndef ZYMOSIS_FUSE_TEST
220 /* for ZXEmuT floating bus emulation, it should be here */
221 value = z80->port_read(z80, port, ZYM_PORTIO_NORMAL);
222 #endif
223 } else {
224 z80->tstates += 3;
225 z80->port_read_tstates = z80->tstates-2;
226 value = z80->port_read(z80, port, ZYM_PORTIO_NORMAL);
228 ++z80->tstates;
229 return value;
233 ZYMOSIS_INLINE void z80_port_write (zym_cpu_t *z80, const uint16_t port, const uint8_t value) {
234 if (z80->port_contention != NULL) {
235 z80->port_contention(z80, port, 1, ZYM_PORTIO_FLAG_EARLY);
236 z80->port_write(z80, port, value, ZYM_PORTIO_NORMAL);
237 z80->port_contention(z80, port, 2, 0);
238 ++z80->tstates;
239 } else {
240 ++z80->tstates;
241 z80->port_write(z80, port, value, ZYM_PORTIO_NORMAL);
242 z80->tstates += 3;
247 /******************************************************************************/
248 #define z80_peekb_i(z80_,addr_) (z80_)->mem_read((z80_), (addr_), ZYM_MEMIO_OTHER)
249 #define z80_peekb(z80_,addr_) (z80_)->mem_read((z80_), (addr_), ZYM_MEMIO_DATA)
251 #define z80_pokeb_i(z80_,addr_,byte_) (z80_)->mem_write((z80_), (addr_), (byte_), ZYM_MEMIO_OTHER)
252 #define z80_pokeb(z80_,addr_,byte_) (z80_)->mem_write((z80_), (addr_), (byte_), ZYM_MEMIO_DATA)
255 #ifdef ZYMOSIS_TRY_TO_AVOID_UB
256 # define EVEN_M1_TO_T3() do { \
257 if (z80->evenM1) { \
258 if ((z80->tstates&0x01) != 0) z80->tstates += 1; \
260 z80->tstates += 2; \
261 while (0)
262 #else
263 # define EVEN_M1_TO_T3() do { \
264 if (z80->evenM1) { \
265 z80->tstates = (int32_t)((uint32_t)(z80->tstates + 1) & ~(uint32_t)1); \
267 z80->tstates += 2; \
268 } while (0)
269 #endif
271 /* read opcode after prefix */
272 /* read opcode -- OCR(4) */
273 /* t1: setting /MREQ & /RD */
274 /* t2: memory read */
275 /* t3: sampilng the data bus, command decoding, refresh, increment R */
276 /* t4: command decoding, refresh */
277 ZYMOSIS_INLINE uint8_t zym_get_opcode_ext (zym_cpu_t *z80) {
278 #ifdef ZYMOSIS_FUSE_TEST
279 /* for FUSE tests, it should be here */
280 z80_contention(z80, z80->pc, ZYM_MEMIO_OPCEXT, ZYM_MREQ_READ);
281 z80->tstates += 4;
282 const uint8_t opc = z80->mem_read(z80, z80->pc, ZYM_MEMIO_OPCEXT);
283 #else
284 EVEN_M1_TO_T3();
285 z80_contention(z80, z80->pc, ZYM_MEMIO_OPCEXT, ZYM_MREQ_READ);
286 const uint8_t opc = z80->mem_read(z80, z80->pc, ZYM_MEMIO_OPCEXT);
287 z80->tstates += 2; // skip t3 and t4
288 #endif
289 INC_R;
290 z80->pc += 1;
291 return opc;
295 // t1: setting /MREQ & /RD
296 // t2: wait
297 // t3: Z80 sampling the data bus
298 ZYMOSIS_INLINE uint8_t z80_mr_3ts (zym_cpu_t *z80, const uint16_t addr) {
299 #ifdef ZYMOSIS_FUSE_TEST
300 /* for FUSE tests, it should be here */
301 z80_contention(z80, addr, ZYM_MEMIO_DATA, ZYM_MREQ_READ);
302 z80->tstates += 3;
303 const uint8_t res = z80->mem_read(z80, addr, ZYM_MEMIO_DATA);
304 #else
305 z80->tstates += 2; // at t3
306 z80_contention(z80, addr, ZYM_MEMIO_DATA, ZYM_MREQ_READ);
307 const uint8_t res = z80->mem_read(z80, addr, ZYM_MEMIO_DATA);
308 z80->tstates += 1; // skip t3
309 #endif
310 return res;
313 // MR cycle for instruction arguments
314 ZYMOSIS_INLINE uint8_t z80_mr_3ts_args (zym_cpu_t *z80, const uint16_t addr) {
315 #ifdef ZYMOSIS_FUSE_TEST
316 /* for FUSE tests, it should be here */
317 z80_contention(z80, addr, ZYM_MEMIO_OPCARG, ZYM_MREQ_READ);
318 z80->tstates += 3;
319 const uint8_t res = z80->mem_read(z80, addr, ZYM_MEMIO_OPCARG);
320 #else
321 z80->tstates += 2; // at t3
322 z80_contention(z80, addr, ZYM_MEMIO_OPCARG, ZYM_MREQ_READ);
323 const uint8_t res = z80->mem_read(z80, addr, ZYM_MEMIO_OPCARG);
324 z80->tstates += 1; // skip t3
325 #endif
326 return res;
329 // 16-bit memory read: two MRs
330 ZYMOSIS_INLINE uint16_t z80_peekw_6ts (zym_cpu_t *z80, const uint16_t addr) {
331 const uint16_t res = z80_mr_3ts(z80, addr);
332 return (uint16_t)(res|(((uint16_t)z80_mr_3ts(z80, addr+1u))<<8));
335 // t1: setting /MREQ & /WR
336 // t2: wait (the data bus is set)
337 // t3: t3 ;-)
338 ZYMOSIS_INLINE void z80_pokeb_3ts (zym_cpu_t *z80, const uint16_t addr, const uint8_t value) {
339 #ifdef ZYMOSIS_FUSE_TEST
340 /* for FUSE tests, it should be here */
341 z80_contention(z80, addr, ZYM_MEMIO_DATA, ZYM_MREQ_WRITE);
342 z80->tstates += 3;
343 z80_pokeb(z80, addr, value);
344 #else
345 z80->tstates += 2; // at t3
346 z80_contention(z80, addr, ZYM_MEMIO_DATA, ZYM_MREQ_WRITE);
347 z80_pokeb(z80, addr, value);
348 z80->tstates += 1; // skip t3
349 #endif
352 ZYMOSIS_INLINE void z80_pokew_6ts (zym_cpu_t *z80, const uint16_t addr, const uint16_t value) {
353 z80_pokeb_3ts(z80, addr, value&0xffu);
354 z80_pokeb_3ts(z80, addr+1u, (value>>8)&0xffu);
357 ZYMOSIS_INLINE void z80_pokew_6ts_inverted (zym_cpu_t *z80, const uint16_t addr, const uint16_t value) {
358 z80_pokeb_3ts(z80, addr+1u, (value>>8)&0xffu);
359 z80_pokeb_3ts(z80, addr, value&0xffu);
362 // read 16-bit instruction argument
363 ZYMOSIS_INLINE uint16_t z80_getpcw (zym_cpu_t *z80, const zym_bool wait1) {
364 uint16_t res = z80_mr_3ts_args(z80, z80->pc);
365 z80->pc += 1u;
366 res |= ((uint16_t)z80_mr_3ts_args(z80, z80->pc))<<8;
367 if (wait1) z80_contention_by1ts_pc(z80, 1);
368 z80->pc += 1u;
369 return res;
373 ZYMOSIS_INLINE uint16_t z80_pop_6ts (zym_cpu_t *z80) {
374 uint16_t res = z80_mr_3ts(z80, z80->sp.w);
375 z80->sp.w += 1u;
376 res |= ((uint16_t)z80_mr_3ts(z80, z80->sp.w))<<8;
377 z80->sp.w += 1u;
378 return res;
381 /* 3 T states write high byte of PC to the stack and decrement SP */
382 /* 3 T states write the low byte of PC and jump to #0066 */
383 ZYMOSIS_INLINE void z80_push_6ts (zym_cpu_t *z80, uint16_t value) {
384 z80->sp.w -= 1u;
385 z80_pokeb_3ts(z80, z80->sp.w, (value>>8)&0xffu);
386 z80->sp.w -= 1u;
387 z80_pokeb_3ts(z80, z80->sp.w, value&0xffu);
391 /******************************************************************************/
392 /* you are not expected to understand the following bit-mess */
393 /* the only thing you want to know that IT WORKS; just believe me and the testing suite */
394 /* ok, you can consult Z80 manuals to find the affected flags */
395 /* but believe me, it is unnecessary */
397 ZYMOSIS_INLINE void ZYM_ADC_A (zym_cpu_t *z80, const uint8_t b) {
398 const uint16_t o = z80->af.a;
399 uint16_t newv;
400 z80->af.a = (newv = o+b+(z80->af.f&ZYM_FLAG_C))&0xffu; /* ZYM_FLAG_C is 0x01u, so it's safe */
401 z80->flags_q = z80->af.f =
402 sz53_tbl[newv&0xffu]|
403 (newv > 0xffu ? ZYM_FLAG_C : 0)|
404 ((o^(~b))&(o^newv)&0x80u ? ZYM_FLAG_PV : 0)|
405 ((o&0x0fu)+(b&0x0fu)+(z80->af.f&ZYM_FLAG_C) >= 0x10u ? ZYM_FLAG_H : 0);
408 ZYMOSIS_INLINE void ZYM_SBC_A (zym_cpu_t *z80, const uint8_t b) {
409 const uint16_t o = z80->af.a;
410 uint16_t newv;
411 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 */
412 z80->flags_q = z80->af.f =
413 ZYM_FLAG_N|
414 sz53_tbl[newv&0xffu]|
415 (newv > 0xffu ? ZYM_FLAG_C : 0)|
416 ((o^b)&(o^newv)&0x80u ? ZYM_FLAG_PV : 0)|
417 ((int32_t)(o&0x0fu)-(int32_t)(b&0x0fu)-(int32_t)(z80->af.f&ZYM_FLAG_C) < 0 ? ZYM_FLAG_H : 0);
420 ZYMOSIS_INLINE void ZYM_ADD_A (zym_cpu_t *z80, const uint8_t b) {
421 z80->af.f &= ~ZYM_FLAG_C;
422 ZYM_ADC_A(z80, b);
425 ZYMOSIS_INLINE void ZYM_SUB_A (zym_cpu_t *z80, const uint8_t b) {
426 z80->af.f &= ~ZYM_FLAG_C;
427 ZYM_SBC_A(z80, b);
430 ZYMOSIS_INLINE void ZYM_CP_A (zym_cpu_t *z80, const uint8_t b) {
431 const uint8_t o = z80->af.a;
432 const uint8_t newv = ((uint32_t)o-(uint32_t)b)&0xffu;
433 z80->flags_q = z80->af.f =
434 ZYM_FLAG_N|
435 (newv&ZYM_FLAG_S)|
436 (b&ZYM_FLAG_35)|
437 (newv == 0 ? ZYM_FLAG_Z : 0)|
438 (o < b ? ZYM_FLAG_C : 0)|
439 ((o^b)&(o^newv)&0x80u ? ZYM_FLAG_PV : 0)|
440 ((int32_t)(o&0x0fu)-(int32_t)(b&0x0fu) < 0 ? ZYM_FLAG_H : 0);
444 #define ZYM_AND_A(z80_,b_) ((z80_)->flags_q = (z80_)->af.f = sz53p_tbl[(z80_)->af.a&=(b_)]|ZYM_FLAG_H)
445 #define ZYM_OR_A(z80_,b_) ((z80_)->flags_q = (z80_)->af.f = sz53p_tbl[(z80_)->af.a|=(b_)])
446 #define ZYM_XOR_A(z80_,b_) ((z80_)->flags_q = (z80_)->af.f = sz53p_tbl[(z80_)->af.a^=(b_)])
449 /* carry unchanged */
450 ZYMOSIS_INLINE uint8_t ZYM_DEC8 (zym_cpu_t *z80, const uint8_t b) {
451 z80->af.f &= ZYM_FLAG_C;
452 z80->af.f |= ZYM_FLAG_N|
453 (b == 0x80u ? ZYM_FLAG_PV : 0)|
454 (b&0x0fu ? 0 : ZYM_FLAG_H)|
455 sz53_tbl[(((uint32_t)b)-1u)&0xffu];
456 z80->flags_q = z80->af.f;
457 return (((uint32_t)b)-1u)&0xffu;
460 /* carry unchanged */
461 ZYMOSIS_INLINE uint8_t ZYM_INC8 (zym_cpu_t *z80, const uint8_t b) {
462 z80->af.f &= ZYM_FLAG_C;
463 z80->af.f |=
464 (b == 0x7fu ? ZYM_FLAG_PV : 0)|
465 ((b+1u)&0x0fu ? 0 : ZYM_FLAG_H)|
466 sz53_tbl[(b+1u)&0xffu];
467 z80->flags_q = z80->af.f;
468 return ((b+1u)&0xffu);
471 /* cyclic, carry reflects shifted bit */
472 ZYMOSIS_INLINE void ZYM_RLCA (zym_cpu_t *z80) {
473 const uint8_t c = ((z80->af.a>>7)&0x01u);
474 z80->af.a = (z80->af.a<<1)|c;
475 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));
478 /* cyclic, carry reflects shifted bit */
479 ZYMOSIS_INLINE void ZYM_RRCA (zym_cpu_t *z80) {
480 const uint8_t c = (z80->af.a&0x01u);
481 z80->af.a = (z80->af.a>>1)|(c<<7);
482 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));
485 /* cyclic thru carry */
486 ZYMOSIS_INLINE void ZYM_RLA (zym_cpu_t *z80) {
487 const uint8_t c = ((z80->af.a>>7)&0x01u);
488 z80->af.a = (z80->af.a<<1)|(z80->af.f&ZYM_FLAG_C);
489 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));
492 /* cyclic thru carry */
493 ZYMOSIS_INLINE void ZYM_RRA (zym_cpu_t *z80) {
494 const uint8_t c = (z80->af.a&0x01u);
495 z80->af.a = (z80->af.a>>1)|((z80->af.f&ZYM_FLAG_C)<<7);
496 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));
499 /* cyclic thru carry */
500 ZYMOSIS_INLINE uint8_t ZYM_RL (zym_cpu_t *z80, uint8_t b) {
501 const uint8_t c = (b>>7)&ZYM_FLAG_C;
502 z80->flags_q = z80->af.f = sz53p_tbl[(b = ((b<<1)&0xffu)|(z80->af.f&ZYM_FLAG_C))]|c;
503 return b;
506 ZYMOSIS_INLINE uint8_t ZYM_RR (zym_cpu_t *z80, uint8_t b) {
507 const uint8_t c = (b&0x01u);
508 z80->flags_q = z80->af.f = sz53p_tbl[(b = (b>>1)|((z80->af.f&ZYM_FLAG_C)<<7))]|c;
509 return b;
512 /* cyclic, carry reflects shifted bit */
513 ZYMOSIS_INLINE uint8_t ZYM_RLC (zym_cpu_t *z80, uint8_t b) {
514 const uint8_t c = ((b>>7)&ZYM_FLAG_C);
515 z80->flags_q = z80->af.f = sz53p_tbl[(b = ((b<<1)&0xffu)|c)]|c;
516 return b;
519 /* cyclic, carry reflects shifted bit */
520 ZYMOSIS_INLINE uint8_t ZYM_RRC (zym_cpu_t *z80, uint8_t b) {
521 const uint8_t c = (b&0x01u);
522 z80->flags_q = z80->af.f = sz53p_tbl[(b = (b>>1)|(c<<7))]|c;
523 return b;
526 /* shift left arithmetic, sets bit 0 to zero, carry reflects shifted bit */
527 ZYMOSIS_INLINE uint8_t ZYM_SLA (zym_cpu_t *z80, uint8_t b) {
528 uint8_t c = ((b>>7)&0x01u);
529 z80->flags_q = z80->af.f = sz53p_tbl[(b <<= 1)]|c;
530 return b;
533 /* shift right arithmetic, sets bit 6 to bit 7, carry reflects shifted bit */
534 ZYMOSIS_INLINE uint8_t ZYM_SRA (zym_cpu_t *z80, uint8_t b) {
535 const uint8_t c = (b&0x01u);
536 z80->flags_q = z80->af.f = sz53p_tbl[(b = (b>>1)|(b&0x80u))]|c;
537 return b;
540 /* shift left "logic" (set), sets bit 0 to one, carry reflects shifted bit */
541 ZYMOSIS_INLINE uint8_t ZYM_SLS (zym_cpu_t *z80, uint8_t b) {
542 const uint8_t c = ((b>>7)&0x01u);
543 z80->flags_q = z80->af.f = sz53p_tbl[(b = (b<<1)|0x01u)]|c;
544 return b;
547 /* shift right logic, sets bit 7 to zero, carry reflects shifted bit */
548 ZYMOSIS_INLINE uint8_t ZYM_SRL (zym_cpu_t *z80, uint8_t b) {
549 const uint8_t c = (b&0x01u);
550 z80->flags_q = z80->af.f = sz53p_tbl[(b >>= 1)]|c;
551 return b;
554 /* ddvalue+value */
555 ZYMOSIS_INLINE uint16_t ZYM_ADD_DD (zym_cpu_t *z80, const uint16_t value, const uint16_t ddvalue) {
556 /* `static` is more restrective here, simple `const` should generate better code */
557 /*static*/ const uint8_t hct[8] = { 0, ZYM_FLAG_H, ZYM_FLAG_H, ZYM_FLAG_H, 0, 0, 0, ZYM_FLAG_H };
558 const uint32_t res = (uint32_t)value+(uint32_t)ddvalue;
559 const uint8_t b = ((value&0x0800u)>>11)|((ddvalue&0x0800u)>>10)|((res&0x0800u)>>9);
560 z80->memptr.w = ddvalue+1u;
561 z80->flags_q = z80->af.f =
562 (z80->af.f&(ZYM_FLAG_PV|ZYM_FLAG_Z|ZYM_FLAG_S))|
563 (res > 0xffffu ? ZYM_FLAG_C : 0)|
564 ((res>>8)&ZYM_FLAG_35)|
565 hct[b];
566 return res;
569 /* ddvalue+value */
570 ZYMOSIS_INLINE uint16_t ZYM_ADC_DD (zym_cpu_t *z80, const uint16_t value, const uint16_t ddvalue) {
571 const uint8_t c = (z80->af.f&ZYM_FLAG_C);
572 const uint32_t newv = (uint32_t)value+(uint32_t)ddvalue+(uint32_t)c;
573 const uint16_t res = (uint16_t)newv;
574 z80->memptr.w = ddvalue+1u;
575 z80->flags_q = z80->af.f =
576 ((res>>8)&ZYM_FLAG_S35)|
577 (res == 0 ? ZYM_FLAG_Z : 0)|
578 (newv > 0xffffu ? ZYM_FLAG_C : 0)|
579 ((value^((~ddvalue)&0xffffu))&(value^newv)&0x8000u ? ZYM_FLAG_PV : 0)|
580 ((value&0x0fffu)+(ddvalue&0x0fffu)+c >= 0x1000u ? ZYM_FLAG_H : 0);
581 return res;
584 /* ddvalue-value */
585 ZYMOSIS_INLINE uint16_t ZYM_SBC_DD (zym_cpu_t *z80, const uint16_t value, const uint16_t ddvalue) {
586 const uint8_t tmpB = z80->af.a;
587 //FIXME: MEMPTR docs says that it is still +1 here; why?
588 //FIXME: is this a typo, or is it really working like this?
589 z80->memptr.w = ddvalue+1u;
590 z80->af.a = ddvalue&0xffu;
591 ZYM_SBC_A(z80, value&0xffu);
592 uint16_t res = z80->af.a;
593 z80->af.a = (ddvalue>>8)&0xffu;
594 ZYM_SBC_A(z80, (value>>8)&0xffu);
595 res |= (z80->af.a<<8);
596 z80->af.a = tmpB;
597 z80->flags_q = z80->af.f = (res ? z80->af.f&(~ZYM_FLAG_Z) : z80->af.f|ZYM_FLAG_Z);
598 return res;
601 ZYMOSIS_INLINE void ZYM_BIT (zym_cpu_t *z80, const uint8_t bit, const uint8_t num, const zym_bool mptr) {
602 z80->af.f =
603 ZYM_FLAG_H|
604 (z80->af.f&ZYM_FLAG_C)|
605 (num&ZYM_FLAG_35)|
606 (num&(1<<bit) ? 0 : ZYM_FLAG_PV|ZYM_FLAG_Z)|
607 (bit == 7 ? num&ZYM_FLAG_S : 0);
608 if (mptr) z80->af.f = (z80->af.f&~ZYM_FLAG_35)|(z80->memptr.h&ZYM_FLAG_35);
609 z80->flags_q = z80->af.f;
612 /* we can do this with table lookup, but why bother? */
613 ZYMOSIS_INLINE void ZYM_DAA (zym_cpu_t *z80) {
614 uint8_t tmpI = 0, tmpC = (z80->af.f&ZYM_FLAG_C), tmpA = z80->af.a;
615 if ((z80->af.f&ZYM_FLAG_H) || (tmpA&0x0fu) > 9) tmpI = 6;
616 if (tmpC != 0 || tmpA > 0x99u) tmpI |= 0x60u;
617 if (tmpA > 0x99u) tmpC = ZYM_FLAG_C;
618 if (z80->af.f&ZYM_FLAG_N) ZYM_SUB_A(z80, tmpI); else ZYM_ADD_A(z80, tmpI);
619 z80->flags_q = z80->af.f = (z80->af.f&~(ZYM_FLAG_C|ZYM_FLAG_PV))|tmpC|parity_tbl[z80->af.a];
622 ZYMOSIS_INLINE void ZYM_RRD_A (zym_cpu_t *z80) {
623 const uint8_t tmpB = z80_mr_3ts(z80, z80->hl.w);
624 /*IOP(4)*/
625 z80->memptr.w = z80->hl.w+1u;
626 z80_contention_by1ts(z80, z80->hl.w, 4);
627 z80_pokeb_3ts(z80, z80->hl.w, (z80->af.a<<4)|(tmpB>>4));
628 z80->af.a = (z80->af.a&0xf0u)|(tmpB&0x0fu);
629 z80->flags_q = z80->af.f = (z80->af.f&ZYM_FLAG_C)|sz53p_tbl[z80->af.a];
632 ZYMOSIS_INLINE void ZYM_RLD_A (zym_cpu_t *z80) {
633 const uint8_t tmpB = z80_mr_3ts(z80, z80->hl.w);
634 /*IOP(4)*/
635 z80->memptr.w = z80->hl.w+1u;
636 z80_contention_by1ts(z80, z80->hl.w, 4);
637 z80_pokeb_3ts(z80, z80->hl.w, (tmpB<<4)|(z80->af.a&0x0fu));
638 z80->af.a = (z80->af.a&0xf0u)|(tmpB>>4);
639 z80->flags_q = z80->af.f = (z80->af.f&ZYM_FLAG_C)|sz53p_tbl[z80->af.a];
642 ZYMOSIS_INLINE void ZYM_LD_A_IR (zym_cpu_t *z80, const uint8_t ir) {
643 z80->af.a = ir;
644 z80->prev_was_EIDDR = -1;
645 z80_contention_by1ts_ir(z80, 1);
646 z80->flags_q = z80->af.f = sz53_tbl[z80->af.a]|(z80->af.f&ZYM_FLAG_C)|(z80->iff2 ? ZYM_FLAG_PV : 0);
650 /******************************************************************************/
652 /* reference code:
653 #define SET_TRUE_CC() do { \
654 switch ((opcode>>3)&0x07u) { \
655 case 0: trueCC = (z80->af.f&ZYM_FLAG_Z) == 0; break; \
656 case 1: trueCC = (z80->af.f&ZYM_FLAG_Z) != 0; break; \
657 case 2: trueCC = (z80->af.f&ZYM_FLAG_C) == 0; break; \
658 case 3: trueCC = (z80->af.f&ZYM_FLAG_C) != 0; break; \
659 case 4: trueCC = (z80->af.f&ZYM_FLAG_PV) == 0; break; \
660 case 5: trueCC = (z80->af.f&ZYM_FLAG_PV) != 0; break; \
661 case 6: trueCC = (z80->af.f&ZYM_FLAG_S) == 0; break; \
662 case 7: trueCC = (z80->af.f&ZYM_FLAG_S) != 0; break; \
664 } while (0)
667 /* branch-less (assuming that `!` is branch-less) code */
668 static const uint8_t ccmask[4] = {
669 ZYM_FLAG_Z,
670 ZYM_FLAG_C,
671 ZYM_FLAG_PV,
672 ZYM_FLAG_S,
674 #define SET_TRUE_CC() trueCC = ((!(z80->af.f&ccmask[(opcode>>4)&0x03u]))^((opcode>>3)&0x01u))
677 #define CBX_REPEATED (opcode&0x10u)
678 #define CBX_BACKWARD (opcode&0x08u)
681 /* this is 256-bit bitmap indicates if the corresponding base opcode is using `(HL)` */
682 static const uint32_t withIndexBmp[8] = {
683 0x00000000u,0x00700000u,0x40404040u,0x40bf4040u,
684 0x40404040u,0x40404040u,0x00000800u,0x00000000u
688 int32_t zym_exec_ex (zym_cpu_t *z80, int32_t tscount) {
689 uint8_t opcode;
690 zym_bool gotDD, trueCC;
691 int32_t disp;
692 int32_t tsts; /* trap tstates */
693 int32_t tstart = z80->tstates;
694 uint8_t tmpB, tmpC, rsrc, rdst;
695 uint16_t tmpW = 0; /* shut up the compiler; it's wrong but stubborn */
696 /* main loop */
697 while ((z80->next_event_tstate < 0 || z80->tstates < z80->next_event_tstate) &&
698 (tscount < 0 || z80->tstates-tstart <= tscount))
700 /* note that real Z80 process prefixes by setting internal flags,
701 blocking /INT for the next opc read, and reading the next opcode.
702 we cannot do that, because for us prefixed instructions are not "flagged".
703 this doesn't matter in practice for anything except the double IX/IY prefixes.
704 currently, we're doing a weird hack for such prefixes (rolling back).
705 double prefixes aren't used in any real code, tho, so this doesn't matter much.
707 z80->prev_pc = z80->org_pc;
708 tsts = z80->tstates; /* rememeber to compensate trap cost */
709 /* we should perform opcode fetching in loop, in case we need to
710 refetch the opcode, or rollback on breakpoint.
711 the exception is "halted" state: in this state Z80 fetches opcode
712 at "HALTPC+1", but performs "NOP" internally. we will emulate this
713 by advancing PC before fetching, and rolling it back.
714 note that pager, memory reading and contention callbacks should check
715 "halted" state if they want the real PC, and decrement it. yet this is
716 required only if you have some kind of breakpoints implementation there.
717 otherwise, the address (and PC) is correct for contention and paging.
719 for (;;) {
720 z80->refetch = 0;
721 if (z80->bp_hit) { z80->bp_was_hit = 1; z80->bp_hit = 0; return z80->tstates - tstart; }
722 z80->org_pc = z80->pc; /* for callbacks */
723 const int32_t ots = z80->tstates;
724 #ifdef ZYMOSIS_FUSE_TEST
725 /* for FUSE tests, we should do nothing here */
726 #else
727 EVEN_M1_TO_T3();
728 #endif
729 /* this is prolly wrong: a pager should be called for "halted" state. but 'cmon! */
730 if (z80->halted) {
731 z80_contention(z80, z80->pc+1u, ZYM_MEMIO_OPHLT, ZYM_MREQ_READ);
732 /* we are not interested in opcode */
733 #ifdef ZYMOSIS_FUSE_TEST
734 /* for FUSE tests, it should be here */
735 z80->tstates += 4;
736 #endif
737 (void)z80->mem_read(z80, z80->pc+1u, ZYM_MEMIO_OPHLT);
738 opcode = 0u;
739 } else {
740 z80_contention(z80, z80->pc, ZYM_MEMIO_OPCODE, ZYM_MREQ_READ);
741 #ifdef ZYMOSIS_FUSE_TEST
742 /* for FUSE tests, it should be here */
743 z80->tstates += 4;
744 #endif
745 opcode = z80->mem_read(z80, z80->pc, ZYM_MEMIO_OPCODE);
747 /* do we need to perform a rollback? */
748 if ((z80->bp_hit|z80->refetch) == 0) {
749 #ifdef ZYMOSIS_FUSE_TEST
750 /* for FUSE tests, we should do nothing here */
751 #else
752 z80->tstates += 2; // skip t3 and t4
753 #endif
754 z80->pc += !z80->halted;
755 INC_R;
756 break;
758 /* rollback tstates */
759 z80->tstates = ots;
761 /* previous Q for SCF/CCF */
762 const uint8_t lastq = z80->flags_q;
763 z80->flags_q = 0;
764 z80->prev_was_EIDDR = 0;
765 disp = gotDD = 0;
766 z80->dd = &z80->hl;
767 /* "HALT" simply executes "NOP" until interrupted */
768 if (z80->halted) { /*z80->pc -= 1u;*/ continue; }
769 /* check for I[XY] prefix */
770 if (opcode == 0xddu || opcode == 0xfdu) {
771 /* IX/IY prefix */
772 z80->dd = (opcode == 0xddu ? &z80->ix : &z80->iy);
773 /* we may need to rollback on double prefix */
774 #if 0
775 const int32_t ots = z80->tstates;
776 /* read opcode -- OCR(4) */
777 opcode = zym_get_opcode_ext(z80);
778 /* test if this instruction have (HL) */
779 if (withIndexBmp[opcode>>5]&(1u<<(opcode&0x1fu))) {
780 /* 3rd byte is always DISP here */
781 disp = z80_mr_3ts_args(z80, z80->pc); if (disp > 127) disp -= 256;
782 ++z80->pc;
783 z80->memptr.w = ZADD_WX(z80->dd->w, disp);
784 } else if (opcode == 0xddu || opcode == 0xfdu) {
785 /* rollback; this is not how real Z80 works, but meh... */
786 /* read second prefix again */
787 --z80->pc;
788 /* rollback tstates */
789 z80->tstates = ots;
790 /* rollback R register */
791 DEC_R;
792 /* double prefix works as NOP, and blocks /INT */
793 z80->prev_was_EIDDR = 1;
794 /*FIXME: logically this should reset our Q value, but i am not sure; anyway, this works*/
795 z80->flags_q = 0;
796 /* restart main loop */
797 continue;
799 #else
800 opcode = z80->mem_read(z80, z80->pc, ZYM_MEMIO_OTHER);
801 if (opcode == 0xddu || opcode == 0xfdu) {
802 /* double prefix works as NOP, and blocks /INT */
803 z80->prev_was_EIDDR = 1;
804 /*FIXME: logically this should reset our Q value, but i am not sure; anyway, this works*/
805 z80->flags_q = 0;
806 /* restart main loop */
807 continue;
809 /* read opcode -- OCR(4) */
810 opcode = zym_get_opcode_ext(z80);
811 /* test if this instruction have (HL) */
812 if (withIndexBmp[opcode>>5]&(1u<<(opcode&0x1fu))) {
813 /* 3rd byte is always DISP here */
814 disp = z80_mr_3ts_args(z80, z80->pc); if (disp > 127) disp -= 256;
815 z80->pc += 1u;
816 z80->memptr.w = ZADD_WX(z80->dd->w, disp);
818 #endif
819 gotDD = 1;
821 /* ED-prefixed instructions */
822 if (opcode == 0xedu) {
823 z80->dd = &z80->hl; /* ED-prefixed opcodes cannot use IX/IY */
824 /* read opcode -- OCR(4) */
825 opcode = zym_get_opcode_ext(z80);
826 switch (opcode) {
827 /* LDI, LDIR, LDD, LDDR */
828 case 0xa0u: case 0xb0u: case 0xa8u: case 0xb8u:
829 tmpB = z80_mr_3ts(z80, z80->hl.w);
830 z80_pokeb_3ts(z80, z80->de.w, tmpB);
831 /*MWR(5)*/
832 z80_contention_by1ts(z80, z80->de.w, 2);
833 --z80->bc.w;
834 tmpB = (tmpB+z80->af.a)&0xffu;
835 z80->flags_q = z80->af.f = /* BOO! FEAR THE MIGHTY BITS! */
836 (tmpB&ZYM_FLAG_3)|(z80->af.f&(ZYM_FLAG_C|ZYM_FLAG_Z|ZYM_FLAG_S))|
837 (z80->bc.w != 0 ? ZYM_FLAG_PV : 0)|
838 (tmpB&0x02u ? ZYM_FLAG_5 : 0);
839 if (CBX_REPEATED) {
840 if (z80->bc.w != 0) {
841 /*IOP(5)*/
842 z80_contention_by1ts(z80, z80->de.w, 5);
843 /* do it again */
844 z80->pc -= 2;
845 z80->memptr.w = z80->pc+1u;
846 /* this seems to be required too: bits 11 and 13 of PC goes to bits 3 and 5 of F */
847 z80->flags_q = z80->af.f = (z80->af.f&~(ZYM_FLAG_3|ZYM_FLAG_5))|
848 ((z80->pc>>8)&(ZYM_FLAG_3|ZYM_FLAG_5));
851 if (!CBX_BACKWARD) { ++z80->hl.w; ++z80->de.w; } else { --z80->hl.w; --z80->de.w; }
852 break;
853 /* CPI, CPIR, CPD, CPDR */
854 case 0xa1u: case 0xb1u: case 0xa9u: case 0xb9u:
855 tmpB = z80_mr_3ts(z80, z80->hl.w);
856 /*IOP(5)*/
857 z80_contention_by1ts(z80, z80->hl.w, 5);
858 --z80->bc.w;
859 z80->af.f = /* BOO! FEAR THE MIGHTY BITS! */
860 ZYM_FLAG_N|
861 (z80->af.f&ZYM_FLAG_C)|
862 (z80->bc.w != 0 ? ZYM_FLAG_PV : 0)|
863 ((int32_t)(z80->af.a&0x0fu)-(int32_t)(tmpB&0x0fu) < 0 ? ZYM_FLAG_H : 0);
864 tmpB = ((uint32_t)z80->af.a-(uint32_t)tmpB)&0xffu;
865 z80->af.f |= (tmpB == 0 ? ZYM_FLAG_Z : 0)|(tmpB&ZYM_FLAG_S);
866 if (z80->af.f&ZYM_FLAG_H) tmpB = ((uint16_t)tmpB-1u)&0xffu;
867 z80->af.f |= (tmpB&ZYM_FLAG_3)|(tmpB&0x02u ? ZYM_FLAG_5 : 0);
868 z80->flags_q = z80->af.f;
869 tmpW = (CBX_BACKWARD ? 0xffffU : 0x0001U); /* increment */
870 if (CBX_REPEATED) {
871 /* repeated */
872 if ((z80->af.f&(ZYM_FLAG_Z|ZYM_FLAG_PV)) == ZYM_FLAG_PV) {
873 /*IOP(5)*/
874 z80_contention_by1ts(z80, z80->hl.w, 5);
875 /* do it again */
876 z80->pc -= 2;
877 z80->memptr.w = z80->pc+1u;
878 /* this seems to be required too: bits 11 and 13 of PC goes to bits 3 and 5 of F */
879 z80->flags_q = z80->af.f = (z80->af.f&~(ZYM_FLAG_3|ZYM_FLAG_5))|
880 ((z80->pc>>8)&(ZYM_FLAG_3|ZYM_FLAG_5));
881 } else {
882 /* new MEMPTR code */
883 //if (CBX_BACKWARD) --z80->memptr.w; else ++z80->memptr.w;
884 z80->memptr.w += tmpW;
886 } else {
887 /* new MEMPTR code */
888 //if (CBX_BACKWARD) --z80->memptr.w; else ++z80->memptr.w;
889 z80->memptr.w += tmpW;
891 //if (CBX_BACKWARD) --z80->hl.w; else ++z80->hl.w;
892 z80->hl.w += tmpW;
893 break;
894 /* OUTI, OTIR, OUTD, OTDR */
895 case 0xa3u: case 0xb3u: case 0xabu: case 0xbbu:
896 --z80->bc.b;
897 /* fallthru */
898 /* INI, INIR, IND, INDR */
899 case 0xa2u: case 0xb2u: case 0xaau: case 0xbau:
900 z80->memptr.w = z80->bc.w;
901 if (CBX_BACKWARD) --z80->memptr.w; else ++z80->memptr.w;
902 /*OCR(5)*/
903 z80_contention_by1ts_ir(z80, 1);
904 if (opcode&0x01u) {
905 /* OUT* */
906 tmpB = z80_mr_3ts(z80, z80->hl.w);/*MRD(3)*/
907 z80_port_write(z80, z80->bc.w, tmpB);
908 tmpW = z80->hl.w;
909 if (CBX_BACKWARD) --tmpW; else ++tmpW;
910 tmpC = (tmpB+tmpW)&0xffu;
911 } else {
912 /* IN* */
913 tmpB = z80_port_read(z80, z80->bc.w);
914 z80_pokeb_3ts(z80, z80->hl.w, tmpB);/*MWR(3)*/
915 --z80->bc.b;
916 tmpC = (CBX_BACKWARD ? ((uint32_t)tmpB+(uint32_t)z80->bc.c-1u) : (tmpB+z80->bc.c+1u))&0xffu;
918 z80->flags_q = z80->af.f =
919 (tmpB&0x80u ? ZYM_FLAG_N : 0)|
920 (tmpC < tmpB ? ZYM_FLAG_H|ZYM_FLAG_C : 0)|
921 parity_tbl[(tmpC&0x07u)^z80->bc.b]|
922 sz53_tbl[z80->bc.b];
923 if (CBX_REPEATED) {
924 /* repeating commands */
925 if (z80->bc.b != 0) {
926 uint16_t a = (opcode&0x01u ? z80->bc.w : z80->hl.w);
927 /*IOP(5)*/
928 z80_contention_by1ts(z80, a, 5);
929 /* do it again */
930 z80->pc -= 2;
931 /* this seems to be required too: bits 11 and 13 of PC goes to bits 3 and 5 of F */
932 /*z80->flags_q =*/ z80->af.f = (z80->af.f&~(ZYM_FLAG_3|ZYM_FLAG_5))|
933 ((z80->pc>>8)&(ZYM_FLAG_3|ZYM_FLAG_5));
934 /* there are more; see https://github.com/hoglet67/Z80Decoder/wiki/Undocumented-Flags
935 if (CF) {
936 if (data & 0x80) {
937 PF = PF ^ Parity((B - 1) & 0x7) ^ 1;
938 HF = (B & 0x0F) == 0x00;
939 } else {
940 PF = PF ^ Parity((B + 1) & 0x7) ^ 1;
941 HF = (B & 0x0F) == 0x0F;
943 } else {
944 PF = PF ^ Parity(B & 0x7) ^ 1;
947 if (z80->af.f&ZYM_FLAG_C) {
948 if (tmpB&0x80u) {
949 z80->af.f ^= parity_tbl[(z80->bc.b-1u)&0x07u]^ZYM_FLAG_PV;
950 z80->af.f = (z80->af.f&~ZYM_FLAG_H)|((z80->bc.b&0x0fu) == 0x00u ? ZYM_FLAG_H : 0);
951 } else {
952 z80->af.f ^= parity_tbl[(z80->bc.b+1u)&0x07u]^ZYM_FLAG_PV;
953 z80->af.f = (z80->af.f&~ZYM_FLAG_H)|((z80->bc.b&0x0fu) == 0x0fu ? ZYM_FLAG_H : 0);
955 } else {
956 z80->af.f ^= parity_tbl[z80->bc.b&0x07u]^ZYM_FLAG_PV;
958 z80->flags_q = z80->af.f;
961 if (CBX_BACKWARD) --z80->hl.w; else ++z80->hl.w;
962 break;
963 /* not strings, but some good instructions anyway */
964 default:
965 if ((opcode&0xc0u) == 0x40u) {
966 /* 0x40...0x7f */
967 switch (opcode&0x07u) {
968 /* IN r8,(C) */
969 case 0:
970 z80->memptr.w = z80->bc.w+1u;
971 tmpB = z80_port_read(z80, z80->bc.w);
972 z80->flags_q = z80->af.f = sz53p_tbl[tmpB]|(z80->af.f&ZYM_FLAG_C);
973 switch ((opcode>>3)&0x07u) {
974 case 0: z80->bc.b = tmpB; break;
975 case 1: z80->bc.c = tmpB; break;
976 case 2: z80->de.d = tmpB; break;
977 case 3: z80->de.e = tmpB; break;
978 case 4: z80->hl.h = tmpB; break;
979 case 5: z80->hl.l = tmpB; break;
980 case 7: z80->af.a = tmpB; break;
981 /* 6 affects only flags */
983 break;
984 /* OUT (C),r8 */
985 case 1:
986 z80->memptr.w = z80->bc.w+1u;
987 switch ((opcode>>3)&0x07u) {
988 case 0: tmpB = z80->bc.b; break;
989 case 1: tmpB = z80->bc.c; break;
990 case 2: tmpB = z80->de.d; break;
991 case 3: tmpB = z80->de.e; break;
992 case 4: tmpB = z80->hl.h; break;
993 case 5: tmpB = z80->hl.l; break;
994 case 7: tmpB = z80->af.a; break;
995 /* 6 usually means (HL), but here it is 0xff for CMOS, and 0 for NMOS */
996 default: tmpB = (!z80->cmos ? 0x00u : 0xffu); break; /* `!` must tell the predictor our preferred path, NMOS */
998 z80_port_write(z80, z80->bc.w, tmpB);
999 break;
1000 /* SBC HL,rr/ADC HL,rr */
1001 case 2:
1002 /*IOP(4),IOP(3)*/
1003 z80_contention_by1ts_ir(z80, 7);
1004 switch ((opcode>>4)&0x03u) {
1005 case 0: tmpW = z80->bc.w; break;
1006 case 1: tmpW = z80->de.w; break;
1007 case 2: tmpW = z80->hl.w; break;
1008 default: tmpW = z80->sp.w; break;
1010 z80->hl.w = (opcode&0x08u ? ZYM_ADC_DD(z80, tmpW, z80->hl.w) : ZYM_SBC_DD(z80, tmpW, z80->hl.w));
1011 break;
1012 /* LD (nn),rr/LD rr,(nn) */
1013 case 3:
1014 tmpW = z80_getpcw(z80, 0);
1015 z80->memptr.w = tmpW+1u;
1016 if (opcode&0x08u) {
1017 /* LD rr,(nn) */
1018 switch ((opcode>>4)&0x03u) {
1019 case 0: z80->bc.w = z80_peekw_6ts(z80, tmpW); break;
1020 case 1: z80->de.w = z80_peekw_6ts(z80, tmpW); break;
1021 case 2: z80->hl.w = z80_peekw_6ts(z80, tmpW); break;
1022 case 3: z80->sp.w = z80_peekw_6ts(z80, tmpW); break;
1024 } else {
1025 /* LD (nn),rr */
1026 switch ((opcode>>4)&0x03u) {
1027 case 0: z80_pokew_6ts(z80, tmpW, z80->bc.w); break;
1028 case 1: z80_pokew_6ts(z80, tmpW, z80->de.w); break;
1029 case 2: z80_pokew_6ts(z80, tmpW, z80->hl.w); break;
1030 case 3: z80_pokew_6ts(z80, tmpW, z80->sp.w); break;
1033 break;
1034 /* NEG */
1035 case 4:
1036 tmpB = z80->af.a;
1037 z80->af.a = 0;
1038 ZYM_SUB_A(z80, tmpB);
1039 break;
1040 /* RETI/RETN */
1041 case 5:
1042 /*RETI: 0x4d, 0x5d, 0x6d, 0x7d*/
1043 /*RETN: 0x45, 0x55, 0x65, 0x75*/
1044 z80->iff1 = z80->iff2;
1045 z80->memptr.w = z80->pc = z80_pop_6ts(z80);
1046 if (opcode&0x08u) {
1047 /* RETI */
1048 if (z80->trap_reti != NULL) {
1049 z80->trap_ts = z80->tstates - tstart;
1050 if (z80->trap_reti(z80, opcode)) return z80->tstates - tstart;
1052 } else {
1053 /* RETN */
1054 if (z80->trap_retn != NULL) {
1055 z80->trap_ts = z80->tstates - tstart;
1056 if (z80->trap_retn(z80, opcode)) return z80->tstates - tstart;
1059 break;
1060 /* IM n */
1061 case 6:
1062 switch (opcode) {
1063 case 0x56u: case 0x76u: z80->im = 1; break;
1064 case 0x5eu: case 0x7eu: z80->im = 2; break;
1065 default: z80->im = 0; break;
1067 break;
1068 /* specials */
1069 case 7:
1070 switch (opcode) {
1071 /* LD I,A */
1072 case 0x47u:
1073 /*OCR(5)*/
1074 z80_contention_by1ts_ir(z80, 1);
1075 z80->regI = z80->af.a;
1076 break;
1077 /* LD R,A */
1078 case 0x4fu:
1079 /*OCR(5)*/
1080 z80_contention_by1ts_ir(z80, 1);
1081 z80->regR = z80->af.a;
1082 break;
1083 /* LD A,I */
1084 case 0x57u: ZYM_LD_A_IR(z80, z80->regI); break;
1085 /* LD A,R */
1086 case 0x5fu: ZYM_LD_A_IR(z80, z80->regR); break;
1087 /* RRD */
1088 case 0x67u: ZYM_RRD_A(z80); break;
1089 /* RLD */
1090 case 0x6F: ZYM_RLD_A(z80); break;
1093 } else {
1094 /* slt and other traps */
1095 switch (opcode) {
1096 case 0xfb: // SLT trap
1097 if (z80->trap_edfb(z80, opcode)) return z80->tstates - tstart;
1098 break;
1099 case 0xfe: // ZXEmuT trap
1100 z80->tstates = tsts; /* compensate trap cost */
1101 z80->trap_ts = z80->tstates - tstart;
1102 if (z80->trap_edfb(z80, opcode)) return z80->tstates - tstart;
1103 default: break;
1106 break;
1108 continue;
1109 } /* 0xed done */
1110 /* CB-prefixed instructions */
1111 if (opcode == 0xcbu) {
1112 /* shifts and bit operations */
1113 /* read opcode -- OCR(4) */
1114 if (!gotDD) {
1115 opcode = zym_get_opcode_ext(z80);
1116 } else {
1117 #ifdef ZYMOSIS_FUSE_TEST
1118 /* for FUSE tests, it should be here */
1119 z80_contention(z80, z80->pc, ZYM_MEMIO_OPCEXT, ZYM_MREQ_READ);
1120 z80->tstates += 3;
1121 opcode = z80->mem_read(z80, z80->pc, ZYM_MEMIO_OPCEXT);
1122 z80_contention_by1ts(z80, z80->pc, 2);
1123 z80->pc += 1u;
1124 #else
1125 //FIXME: check if it really skips `INC_R`
1126 opcode = zym_get_opcode_ext(z80);
1127 //DEC_R;
1128 #endif
1130 if (gotDD) {
1131 tmpW = ZADD_WX(z80->dd->w, disp);
1132 tmpB = z80_mr_3ts(z80, tmpW);
1133 z80_contention_by1ts(z80, tmpW, 1);
1134 } else {
1135 switch (opcode&0x07u) {
1136 case 0: tmpB = z80->bc.b; break;
1137 case 1: tmpB = z80->bc.c; break;
1138 case 2: tmpB = z80->de.d; break;
1139 case 3: tmpB = z80->de.e; break;
1140 case 4: tmpB = z80->hl.h; break;
1141 case 5: tmpB = z80->hl.l; break;
1142 case 6: tmpB = z80_mr_3ts(z80, z80->hl.w);
1143 //k8: i don't know why it is here, but it seems to be required
1144 // to properly emulate contended access.
1145 z80->mem_contention(z80, z80->hl.w, ZYM_MEMIO_DATA, ZYM_MREQ_READ);
1146 z80->tstates += 1;
1147 break;
1148 case 7: tmpB = z80->af.a; break;
1151 switch ((opcode>>3)&0x1fu) {
1152 case 0: tmpB = ZYM_RLC(z80, tmpB); break;
1153 case 1: tmpB = ZYM_RRC(z80, tmpB); break;
1154 case 2: tmpB = ZYM_RL(z80, tmpB); break;
1155 case 3: tmpB = ZYM_RR(z80, tmpB); break;
1156 case 4: tmpB = ZYM_SLA(z80, tmpB); break;
1157 case 5: tmpB = ZYM_SRA(z80, tmpB); break;
1158 case 6: tmpB = ZYM_SLS(z80, tmpB); break;
1159 case 7: tmpB = ZYM_SRL(z80, tmpB); break;
1160 default:
1161 switch ((opcode>>6)&0x03u) {
1162 case 1: ZYM_BIT(z80, (opcode>>3)&0x07u, tmpB, (gotDD || (opcode&0x07u) == 6)); break;
1163 case 2: tmpB &= ~(1<<((opcode>>3)&0x07u)); break; /* RES */
1164 case 3: tmpB |= (1<<((opcode>>3)&0x07u)); break; /* SET */
1166 break;
1168 if ((opcode&0xc0u) != 0x40u) {
1169 /* BITs are not welcome here */
1170 if (gotDD) {
1171 /* tmpW was set earlier */
1172 if ((opcode&0x07u) != 6) z80_pokeb_3ts(z80, tmpW, tmpB);
1174 switch (opcode&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->hl.h = tmpB; break;
1180 case 5: z80->hl.l = tmpB; break;
1181 case 6: z80_pokeb_3ts(z80, ZADD_WX(z80->dd->w, disp), tmpB); break;
1182 case 7: z80->af.a = tmpB; break;
1185 continue;
1186 } /* 0xcb done */
1187 /* normal things */
1188 switch (opcode&0xc0u) {
1189 /* 0x00..0x3F */
1190 case 0x00u:
1191 switch (opcode&0x07u) {
1192 /* misc,DJNZ,JR,JR cc */
1193 case 0:
1194 if (opcode&0x30u) {
1195 /* branches */
1196 if (opcode&0x20u) {
1197 /* JR cc */
1199 switch ((opcode>>3)&0x03u) {
1200 case 0: trueCC = (z80->af.f&ZYM_FLAG_Z) == 0; break;
1201 case 1: trueCC = (z80->af.f&ZYM_FLAG_Z) != 0; break;
1202 case 2: trueCC = (z80->af.f&ZYM_FLAG_C) == 0; break;
1203 case 3: trueCC = (z80->af.f&ZYM_FLAG_C) != 0; break;
1204 default: trueCC = 0; break;
1207 trueCC = ((!(z80->af.f&ccmask[(opcode>>4)&0x01u]))^((opcode>>3)&0x01u));
1208 } else {
1209 /* DJNZ/JR */
1210 if ((opcode&0x08u) == 0) {
1211 /* DJNZ */
1212 /*OCR(5)*/
1213 z80_contention_by1ts_ir(z80, 1);
1214 --z80->bc.b;
1215 trueCC = (z80->bc.b != 0);
1216 } else {
1217 /* JR */
1218 trueCC = 1;
1221 /* `disp` is always read, but FUSE tests require it this way; sigh */
1222 #ifdef ZYMOSIS_FUSE_TEST
1223 /* for FUSE tests, it should be like this */
1224 if (trueCC) {
1225 disp = z80_mr_3ts_args(z80, z80->pc);
1226 } else {
1227 z80_contention(z80, z80->pc, ZYM_MEMIO_OPCARG, ZYM_MREQ_READ);
1228 z80->tstates += 3;
1229 disp = 0;
1231 #else
1232 disp = z80_mr_3ts_args(z80, z80->pc);
1233 #endif
1234 if (trueCC) {
1235 /* execute branch (relative) */
1236 /*IOP(5)*/
1237 if (disp > 127) disp -= 256; /* convert to int8_t */
1238 z80_contention_by1ts_pc(z80, 5);
1239 z80->pc += 1u;
1240 z80->memptr.w = z80->pc = ZADD_WX(z80->pc, disp);
1241 } else {
1242 z80->pc += 1u;
1244 } else {
1245 /* EX AF,AF' or NOP */
1246 if (opcode != 0) zym_exaf_internal(z80);
1248 break;
1249 /* LD rr,nn/ADD HL,rr */
1250 case 1:
1251 if (opcode&0x08u) {
1252 /* ADD HL,rr */
1253 /*IOP(4),IOP(3)*/
1254 z80_contention_by1ts_ir(z80, 7);
1255 switch ((opcode>>4)&0x03u) {
1256 case 0: z80->dd->w = ZYM_ADD_DD(z80, z80->bc.w, z80->dd->w); break;
1257 case 1: z80->dd->w = ZYM_ADD_DD(z80, z80->de.w, z80->dd->w); break;
1258 case 2: z80->dd->w = ZYM_ADD_DD(z80, z80->dd->w, z80->dd->w); break;
1259 case 3: z80->dd->w = ZYM_ADD_DD(z80, z80->sp.w, z80->dd->w); break;
1261 } else {
1262 /* LD rr,nn */
1263 tmpW = z80_getpcw(z80, 0);
1264 switch ((opcode>>4)&0x03u) {
1265 case 0: z80->bc.w = tmpW; break;
1266 case 1: z80->de.w = tmpW; break;
1267 case 2: z80->dd->w = tmpW; break;
1268 case 3: z80->sp.w = tmpW; break;
1271 break;
1272 /* LD xxx,xxx */
1273 case 2:
1274 switch ((opcode>>3)&0x07u) {
1275 /* LD (BC),A */
1276 case 0: z80_pokeb_3ts(z80, z80->bc.w, z80->af.a); z80->memptr.l = (z80->bc.w+1u)&0xffu; z80->memptr.h = z80->af.a; break;
1277 /* LD A,(BC) */
1278 case 1: z80->af.a = z80_mr_3ts(z80, z80->bc.w); z80->memptr.w = z80->bc.w+1u; break;
1279 /* LD (DE),A */
1280 case 2: z80_pokeb_3ts(z80, z80->de.w, z80->af.a); z80->memptr.l = (z80->de.w+1u)&0xffu; z80->memptr.h = z80->af.a; break;
1281 /* LD A,(DE) */
1282 case 3: z80->af.a = z80_mr_3ts(z80, z80->de.w); z80->memptr.w = z80->de.w+1u; break;
1283 /* LD (nn),HL */
1284 case 4:
1285 tmpW = z80_getpcw(z80, 0);
1286 z80->memptr.w = tmpW+1u;
1287 z80_pokew_6ts(z80, tmpW, z80->dd->w);
1288 break;
1289 /* LD HL,(nn) */
1290 case 5:
1291 tmpW = z80_getpcw(z80, 0);
1292 z80->memptr.w = tmpW+1u;
1293 z80->dd->w = z80_peekw_6ts(z80, tmpW);
1294 break;
1295 /* LD (nn),A */
1296 case 6:
1297 tmpW = z80_getpcw(z80, 0);
1298 z80->memptr.l = (tmpW+1u)&0xffu;
1299 z80->memptr.h = z80->af.a;
1300 z80_pokeb_3ts(z80, tmpW, z80->af.a);
1301 break;
1302 /* LD A,(nn) */
1303 case 7:
1304 tmpW = z80_getpcw(z80, 0);
1305 z80->memptr.w = tmpW+1u;
1306 z80->af.a = z80_mr_3ts(z80, tmpW);
1307 break;
1309 break;
1310 /* INC rr/DEC rr */
1311 case 3:
1312 /*OCR(6)*/
1313 z80_contention_by1ts_ir(z80, 2);
1314 if (opcode&0x08u) {
1315 /*DEC*/
1316 switch ((opcode>>4)&0x03u) {
1317 case 0: --z80->bc.w; break;
1318 case 1: --z80->de.w; break;
1319 case 2: --z80->dd->w; break;
1320 case 3: --z80->sp.w; break;
1322 } else {
1323 /*INC*/
1324 switch ((opcode>>4)&0x03u) {
1325 case 0: ++z80->bc.w; break;
1326 case 1: ++z80->de.w; break;
1327 case 2: ++z80->dd->w; break;
1328 case 3: ++z80->sp.w; break;
1331 break;
1332 /* INC r8 */
1333 case 4:
1334 switch ((opcode>>3)&0x07u) {
1335 case 0: z80->bc.b = ZYM_INC8(z80, z80->bc.b); break;
1336 case 1: z80->bc.c = ZYM_INC8(z80, z80->bc.c); break;
1337 case 2: z80->de.d = ZYM_INC8(z80, z80->de.d); break;
1338 case 3: z80->de.e = ZYM_INC8(z80, z80->de.e); break;
1339 case 4: z80->dd->h = ZYM_INC8(z80, z80->dd->h); break;
1340 case 5: z80->dd->l = ZYM_INC8(z80, z80->dd->l); break;
1341 case 6:
1342 if (gotDD) { --z80->pc; z80_contention_by1ts_pc(z80, 5); ++z80->pc; }
1343 tmpW = ZADD_WX(z80->dd->w, disp);
1344 tmpB = z80_mr_3ts(z80, tmpW);
1345 z80_contention_by1ts(z80, tmpW, 1);
1346 tmpB = ZYM_INC8(z80, tmpB);
1347 z80_pokeb_3ts(z80, tmpW, tmpB);
1348 break;
1349 case 7: z80->af.a = ZYM_INC8(z80, z80->af.a); break;
1351 break;
1352 /* DEC r8 */
1353 case 5:
1354 switch ((opcode>>3)&0x07u) {
1355 case 0: z80->bc.b = ZYM_DEC8(z80, z80->bc.b); break;
1356 case 1: z80->bc.c = ZYM_DEC8(z80, z80->bc.c); break;
1357 case 2: z80->de.d = ZYM_DEC8(z80, z80->de.d); break;
1358 case 3: z80->de.e = ZYM_DEC8(z80, z80->de.e); break;
1359 case 4: z80->dd->h = ZYM_DEC8(z80, z80->dd->h); break;
1360 case 5: z80->dd->l = ZYM_DEC8(z80, z80->dd->l); break;
1361 case 6:
1362 if (gotDD) { --z80->pc; z80_contention_by1ts_pc(z80, 5); ++z80->pc; }
1363 tmpW = ZADD_WX(z80->dd->w, disp);
1364 tmpB = z80_mr_3ts(z80, tmpW);
1365 z80_contention_by1ts(z80, tmpW, 1);
1366 tmpB = ZYM_DEC8(z80, tmpB);
1367 z80_pokeb_3ts(z80, tmpW, tmpB);
1368 break;
1369 case 7: z80->af.a = ZYM_DEC8(z80, z80->af.a); break;
1371 break;
1372 /* LD r8,n */
1373 case 6:
1374 tmpB = z80_mr_3ts_args(z80, z80->pc);
1375 ++z80->pc;
1376 switch ((opcode>>3)&0x07u) {
1377 case 0: z80->bc.b = tmpB; break;
1378 case 1: z80->bc.c = tmpB; break;
1379 case 2: z80->de.d = tmpB; break;
1380 case 3: z80->de.e = tmpB; break;
1381 case 4: z80->dd->h = tmpB; break;
1382 case 5: z80->dd->l = tmpB; break;
1383 case 6:
1384 if (gotDD) { --z80->pc; z80_contention_by1ts_pc(z80, 2); ++z80->pc; }
1385 tmpW = ZADD_WX(z80->dd->w, disp);
1386 z80_pokeb_3ts(z80, tmpW, tmpB);
1387 break;
1388 case 7: z80->af.a = tmpB; break;
1390 break;
1391 /* swim-swim-hungry */
1392 case 7:
1393 switch ((opcode>>3)&0x07u) {
1394 case 0: ZYM_RLCA(z80); break;
1395 case 1: ZYM_RRCA(z80); break;
1396 case 2: ZYM_RLA(z80); break;
1397 case 3: ZYM_RRA(z80); break;
1398 case 4: ZYM_DAA(z80); break;
1399 case 5: /* CPL */
1400 z80->af.a ^= 0xffu;
1401 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));
1402 break;
1403 case 6: /* SCF */
1404 /* `!` must tell the predictor our preferred path, NMOS */
1405 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;
1406 break;
1407 case 7: /* CCF */
1408 /* `!` must tell the predictor our preferred path, NMOS */
1409 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);
1410 break;
1412 break;
1414 break;
1415 /* 0x40..0x7F (LD r8,r8) */
1416 case 0x40u:
1417 if (opcode == 0x76u) {
1418 /* HALT */
1419 z80->halted = 1;
1420 /* z80->pc -= 1u;*/
1421 if (z80->trap_halt != NULL && z80->trap_halt(z80)) return z80->tstates - tstart;
1422 continue;
1424 rsrc = (opcode&0x07u);
1425 rdst = ((opcode>>3)&0x07u);
1426 switch (rsrc) {
1427 case 0: tmpB = z80->bc.b; break;
1428 case 1: tmpB = z80->bc.c; break;
1429 case 2: tmpB = z80->de.d; break;
1430 case 3: tmpB = z80->de.e; break;
1431 case 4: tmpB = (gotDD && rdst == 6 ? z80->hl.h : z80->dd->h); break;
1432 case 5: tmpB = (gotDD && rdst == 6 ? z80->hl.l : z80->dd->l); break;
1433 case 6:
1434 if (gotDD) { --z80->pc; z80_contention_by1ts_pc(z80, 5); ++z80->pc; }
1435 tmpW = ZADD_WX(z80->dd->w, disp);
1436 tmpB = z80_mr_3ts(z80, tmpW);
1437 break;
1438 case 7: tmpB = z80->af.a; break;
1440 switch (rdst) {
1441 case 0: z80->bc.b = tmpB; break;
1442 case 1: z80->bc.c = tmpB; break;
1443 case 2: z80->de.d = tmpB; break;
1444 case 3: z80->de.e = tmpB; break;
1445 case 4: if (gotDD && rsrc == 6) z80->hl.h = tmpB; else z80->dd->h = tmpB; break;
1446 case 5: if (gotDD && rsrc == 6) z80->hl.l = tmpB; else z80->dd->l = tmpB; break;
1447 case 6:
1448 if (gotDD) { --z80->pc; z80_contention_by1ts_pc(z80, 5); ++z80->pc; }
1449 tmpW = ZADD_WX(z80->dd->w, disp);
1450 z80_pokeb_3ts(z80, tmpW, tmpB);
1451 break;
1452 case 7: z80->af.a = tmpB; break;
1454 break;
1455 /* 0x80..0xBF (ALU A,r8) */
1456 case 0x80u:
1457 switch (opcode&0x07u) {
1458 case 0: tmpB = z80->bc.b; break;
1459 case 1: tmpB = z80->bc.c; break;
1460 case 2: tmpB = z80->de.d; break;
1461 case 3: tmpB = z80->de.e; break;
1462 case 4: tmpB = z80->dd->h; break;
1463 case 5: tmpB = z80->dd->l; break;
1464 case 6:
1465 if (gotDD) { --z80->pc; z80_contention_by1ts_pc(z80, 5); ++z80->pc; }
1466 tmpW = ZADD_WX(z80->dd->w, disp);
1467 tmpB = z80_mr_3ts(z80, tmpW);
1468 break;
1469 case 7: tmpB = z80->af.a; break;
1471 switch ((opcode>>3)&0x07u) {
1472 case 0: ZYM_ADD_A(z80, tmpB); break;
1473 case 1: ZYM_ADC_A(z80, tmpB); break;
1474 case 2: ZYM_SUB_A(z80, tmpB); break;
1475 case 3: ZYM_SBC_A(z80, tmpB); break;
1476 case 4: ZYM_AND_A(z80, tmpB); break;
1477 case 5: ZYM_XOR_A(z80, tmpB); break;
1478 case 6: ZYM_OR_A(z80, tmpB); break;
1479 case 7: ZYM_CP_A(z80, tmpB); break;
1481 break;
1482 /* 0xC0..0xFF */
1483 case 0xC0:
1484 switch (opcode&0x07u) {
1485 /* RET cc */
1486 case 0:
1487 z80_contention_by1ts_ir(z80, 1);
1488 SET_TRUE_CC();
1489 if (trueCC) z80->memptr.w = z80->pc = z80_pop_6ts(z80);
1490 break;
1491 /* POP rr/special0 */
1492 case 1:
1493 if (opcode&0x08u) {
1494 /* special 0 */
1495 switch ((opcode>>4)&0x03u) {
1496 /* RET */
1497 case 0: z80->memptr.w = z80->pc = z80_pop_6ts(z80); break;
1498 /* EXX */
1499 case 1: zym_exx_internal(z80); break;
1500 /* JP (HL) */
1501 case 2: z80->pc = z80->dd->w; break;
1502 /* LD SP,HL */
1503 case 3:
1504 /*OCR(6)*/
1505 z80_contention_by1ts_ir(z80, 2);
1506 z80->sp.w = z80->dd->w;
1507 break;
1509 } else {
1510 /* POP rr */
1511 tmpW = z80_pop_6ts(z80);
1512 switch ((opcode>>4)&0x03u) {
1513 case 0: z80->bc.w = tmpW; break;
1514 case 1: z80->de.w = tmpW; break;
1515 case 2: z80->dd->w = tmpW; break;
1516 case 3: z80->af.w = tmpW; break;
1519 break;
1520 /* JP cc,nn */
1521 case 2:
1522 SET_TRUE_CC();
1523 z80->memptr.w = z80_getpcw(z80, 0);
1524 if (trueCC) z80->pc = z80->memptr.w;
1525 break;
1526 /* special1/special3 */
1527 case 3:
1528 switch ((opcode>>3)&0x07u) {
1529 /* JP nn */
1530 case 0: z80->memptr.w = z80->pc = z80_getpcw(z80, 0); break;
1531 /* OUT (n),A */
1532 case 2:
1533 tmpW = z80_mr_3ts_args(z80, z80->pc);
1534 ++z80->pc;
1535 z80->memptr.l = (tmpW+1u)&0xffu;
1536 z80->memptr.h = z80->af.a;
1537 tmpW |= (((uint16_t)(z80->af.a))<<8);
1538 z80_port_write(z80, tmpW, z80->af.a);
1539 break;
1540 /* IN A,(n) */
1541 case 3:
1542 tmpB = z80_mr_3ts_args(z80, z80->pc);
1543 tmpW = (uint16_t)((((uint16_t)(z80->af.a))<<8)|tmpB);
1544 ++z80->pc;
1545 z80->memptr.l = 0;
1546 z80->memptr.h = z80->af.a;
1547 z80->memptr.w += tmpB+1u;
1548 z80->af.a = z80_port_read(z80, tmpW);
1549 break;
1550 /* EX (SP),HL */
1551 case 4:
1552 /*SRL(3),SRH(4)*/
1553 tmpW = z80_peekw_6ts(z80, z80->sp.w);
1554 z80_contention_by1ts(z80, z80->sp.w+1u, 1);
1555 /*SWL(3),SWH(5)*/
1556 z80_pokew_6ts_inverted(z80, z80->sp.w, z80->dd->w);
1557 z80_contention_by1ts(z80, z80->sp.w, 2);
1558 z80->memptr.w = z80->dd->w = tmpW;
1559 break;
1560 /* EX DE,HL */
1561 case 5:
1562 tmpW = z80->de.w;
1563 z80->de.w = z80->hl.w;
1564 z80->hl.w = tmpW;
1565 break;
1566 /* DI */
1567 case 6: z80->iff1 = z80->iff2 = 0; break;
1568 /* EI */
1569 case 7: z80->iff1 = z80->iff2 = 1; z80->prev_was_EIDDR = 1; break;
1571 break;
1572 /* CALL cc,nn */
1573 case 4:
1574 SET_TRUE_CC();
1575 /* MEMPTR docs says that it is like JP */
1576 z80->memptr.w = z80_getpcw(z80, trueCC);
1577 if (trueCC) {
1578 z80_push_6ts(z80, z80->pc);
1579 z80->pc = z80->memptr.w;
1581 break;
1582 /* PUSH rr/special2 */
1583 case 5:
1584 if (opcode&0x08u) {
1585 if (((opcode>>4)&0x03u) == 0) {
1586 /* CALL */
1587 z80->memptr.w = tmpW = z80_getpcw(z80, 1);
1588 z80_push_6ts(z80, z80->pc);
1589 z80->pc = tmpW;
1591 } else {
1592 /* PUSH rr */
1593 /*OCR(5)*/
1594 z80_contention_by1ts_ir(z80, 1);
1595 switch ((opcode>>4)&0x03u) {
1596 case 0: tmpW = z80->bc.w; break;
1597 case 1: tmpW = z80->de.w; break;
1598 case 2: tmpW = z80->dd->w; break;
1599 default: tmpW = z80->af.w; break;
1601 z80_push_6ts(z80, tmpW);
1603 break;
1604 /* ALU A,n */
1605 case 6:
1606 tmpB = z80_mr_3ts_args(z80, z80->pc);
1607 ++z80->pc;
1608 switch ((opcode>>3)&0x07u) {
1609 case 0: ZYM_ADD_A(z80, tmpB); break;
1610 case 1: ZYM_ADC_A(z80, tmpB); break;
1611 case 2: ZYM_SUB_A(z80, tmpB); break;
1612 case 3: ZYM_SBC_A(z80, tmpB); break;
1613 case 4: ZYM_AND_A(z80, tmpB); break;
1614 case 5: ZYM_XOR_A(z80, tmpB); break;
1615 case 6: ZYM_OR_A(z80, tmpB); break;
1616 case 7: ZYM_CP_A(z80, tmpB); break;
1618 break;
1619 /* RST nnn */
1620 case 7:
1621 /*OCR(5)*/
1622 z80_contention_by1ts_ir(z80, 1);
1623 z80_push_6ts(z80, z80->pc);
1624 z80->memptr.w = z80->pc = opcode&0x38u;
1625 break;
1627 break;
1628 } /* end switch */
1630 return z80->tstates - tstart;
1634 int32_t zym_exec_step (zym_cpu_t *z80) {
1635 const int32_t one = z80->next_event_tstate;
1636 z80->next_event_tstate = -1;
1637 const int32_t res = zym_exec_ex(z80, 1);
1638 z80->next_event_tstate = one;
1639 return res;
1643 /******************************************************************************/
1644 /* changes z80->tstates if interrupt occurs */
1645 int32_t zym_intr (zym_cpu_t *z80) {
1646 uint16_t a;
1647 const int32_t ots = z80->tstates;
1648 /* emulate NMOS Z80 bug: interruptet LD A,<I|R> copies cleared flag */
1649 /*FIXME: what is the state of `z80->flags_q` here? */
1650 if (z80->prev_was_EIDDR < 0) {
1651 z80->prev_was_EIDDR = 0;
1652 if (!z80->cmos) z80->flags_q = (z80->af.f &= ~ZYM_FLAG_PV);
1654 if (z80->prev_was_EIDDR || !z80->iff1) return 0; /* not accepted */
1655 z80->flags_q = 0; /* we cannot do it earlier, because ignored interrupt won't reset flags */
1656 /* skip "HALT" */
1657 //if (z80->halted) { z80->halted = 0; /* z80->pc += 1u;*/ }
1658 z80->halted = 0;
1659 z80->iff1 = z80->iff2 = 0; /* disable interrupts */
1660 switch ((z80->im &= 0x03u)) {
1661 case 3: /* ??? */ z80->im = 0; /* fallthru */
1662 case 0: /* take instruction from the bus (for now we assume that reading from bus always returns 0xff) */
1663 /* with a CALL nnnn on the data bus, it takes 19 cycles: */
1664 /* M1 cycle: 7 T to acknowledge interrupt (where exactly data bus reading occurs?) */
1665 /* M2 cycle: 3 T to read low byte of 'nnnn' from data bus */
1666 /* M3 cycle: 3 T to read high byte of 'nnnn' and decrement SP */
1667 /* M4 cycle: 3 T to write high byte of PC to the stack and decrement SP */
1668 /* M5 cycle: 3 T to write low byte of PC and jump to 'nnnn' */
1669 z80->tstates += 6;
1670 /* fallthru */
1671 case 1: /* just do RST #38 */
1672 INC_R;
1673 z80->tstates += 7; /* M1 cycle: 7 T to acknowledge interrupt and decrement SP */
1674 /* M2 cycle: 3 T states write high byte of PC to the stack and decrement SP */
1675 /* M3 cycle: 3 T states write the low byte of PC and jump to #0038 */
1676 z80_push_6ts(z80, z80->pc);
1677 z80->memptr.w = z80->pc = 0x38u;
1678 break;
1679 case 2:
1680 INC_R;
1681 z80->tstates += 7; /* M1 cycle: 7 T to acknowledge interrupt and decrement SP */
1682 /* M2 cycle: 3 T states write high byte of PC to the stack and decrement SP */
1683 /* M3 cycle: 3 T states write the low byte of PC */
1684 z80_push_6ts(z80, z80->pc);
1685 /* M4 cycle: 3 T to read high byte from the interrupt vector */
1686 /* M5 cycle: 3 T to read low byte from bus and jump to interrupt routine */
1687 a = (((uint16_t)z80->regI)<<8)|0xffu;
1688 z80->memptr.w = z80->pc = z80_peekw_6ts(z80, a);
1689 break;
1691 return z80->tstates-ots; /* accepted */
1695 /* changes z80->tstates if interrupt occurs */
1696 int32_t zym_nmi (zym_cpu_t *z80) {
1697 const int32_t ots = z80->tstates;
1698 /* emulate NMOS Z80 bug: interruptet LD A,<I|R> copies cleared flag */
1699 /*FIXME: what is the state of `z80->flags_q` here? */
1700 if (z80->prev_was_EIDDR < 0) {
1701 z80->prev_was_EIDDR = 0;
1702 /* i was informed that NMI doesn't do this; dunno, let's fix it. ;-)
1703 if (!z80->cmos) z80->flags_q = (z80->af.f &= ~ZYM_FLAG_PV);
1706 if (z80->prev_was_EIDDR) return 0;
1707 z80->flags_q = 0; /* we cannot do it earlier, because ignored interrupt won't reset flags */
1708 /* skip "HALT" */
1709 //if (z80->halted) { z80->halted = 0; /* z80->pc += 1;*/ }
1710 z80->halted = 0;
1711 INC_R;
1712 z80->iff1 = 0; /* IFF2 is not changed */
1713 z80->tstates += 5; /* M1 cycle: 5 T states to do an opcode read and decrement SP */
1714 /* M2 cycle: 3 T states write high byte of PC to the stack and decrement SP */
1715 /* M3 cycle: 3 T states write the low byte of PC and jump to #0066 */
1716 z80_push_6ts(z80, z80->pc);
1717 z80->memptr.w = z80->pc = 0x66u;
1718 return z80->tstates-ots;
1722 /******************************************************************************/
1723 uint16_t zym_pop (zym_cpu_t *z80) {
1724 uint16_t res = z80_peekb_i(z80, z80->sp.w);
1725 ++z80->sp.w;
1726 res |= ((uint16_t)z80_peekb_i(z80, z80->sp.w))<<8;
1727 ++z80->sp.w;
1728 return res;
1732 void zym_push (zym_cpu_t *z80, const uint16_t value) {
1733 --z80->sp.w;
1734 z80_pokeb_i(z80, z80->sp.w, (value>>8)&0xffu);
1735 --z80->sp.w;
1736 z80_pokeb_i(z80, z80->sp.w, value&0xffu);
1740 /******************************************************************************
1741 instruction decoding
1742 ====================
1743 00 00y 000 -- special
1744 00 01g 000 -- DJNZ/JR
1745 00 1cc 000 -- JR cc,n
1746 00 rr0 001 -- LD rr,nn
1747 00 rr1 001 -- ADD HL,rr
1748 00 000 010 -- LD (BC),A
1749 00 001 010 -- LD A,(BC)
1750 00 010 010 -- LD (DE),A
1751 00 011 010 -- LD A,(DE)
1752 00 100 010 -- LD (nn),HL
1753 00 101 010 -- LD HL,(nn)
1754 00 110 010 -- LD (nn),A
1755 00 111 010 -- LD A,(nn)
1756 00 rr0 011 -- INC rr
1757 00 rr1 011 -- DEC rr
1758 00 rrr 100 -- INC r8
1759 00 rrr 101 -- DEC r8
1760 00 rrr 110 -- LD r8,n
1761 00 xxx 111 -- special
1764 0 - NOP
1765 1 - EX AF,AF'
1767 0 - DJNZ
1768 1 - JR
1770 00 - NZ
1771 01 - Z
1772 10 - NC
1773 11 - C
1774 xxx:
1775 000 - RLCA
1776 001 - RRCA
1777 010 - RLA
1778 011 - RRA
1779 100 - DAA
1780 101 - CPL
1781 110 - SCF
1782 111 - CCF
1783 rrr:
1784 000 - B
1785 001 - C
1786 010 - D
1787 011 - E
1788 100 - H
1789 101 - L
1790 110 - (HL)
1791 111 - A
1793 00 - BC
1794 01 - DE
1795 10 - HL
1796 11 - SP
1798 ---------------------------------
1800 01 rrr rrr - LD r8,r8 (lo: src)
1802 ---------------------------------
1804 10 alu rrr - ALU a,r8
1805 alu:
1806 000 - ADD
1807 001 - ADC
1808 010 - SUB
1809 011 - SBC
1810 100 - AND
1811 101 - XOR
1812 110 - OR
1813 111 - CP
1815 ---------------------------------
1817 11 ccc 000 -- RET cc
1818 11 rr0 001 -- POP rr
1819 11 xx1 001 -- special0
1820 11 ccc 010 -- JP cc,nn
1821 11 yyy 011 -- special1
1822 11 ccc 100 -- CALL cc,nn
1823 11 rr0 101 -- PUSH rr
1824 11 zz1 101 -- special2
1825 11 alu 110 -- alu A,n
1826 11 aaa 111 -- RST nnn
1829 00 - BC
1830 01 - DE
1831 10 - HL
1832 11 - AF
1833 aaa: RST addr=aaa<<3
1834 ccc:
1835 000 - NZ
1836 001 - Z
1837 010 - NC
1838 011 - C
1839 100 - PO
1840 101 - PE
1841 110 - P
1842 111 - M
1843 alu:
1844 000 - ADD
1845 001 - ADC
1846 010 - SUB
1847 011 - SBC
1848 100 - AND
1849 101 - XOR
1850 110 - OR
1851 111 - CP
1853 00 - RET
1854 01 - EXX
1855 10 - JP HL
1856 11 - LD SP,HL
1857 yyy:
1858 000 - JP nn
1859 001 - CB
1860 010 - OUT (n),A
1861 011 - IN A,(n)
1862 100 - EX (SP),HL
1863 101 - EX DE,HL
1864 110 - DI
1865 111 - EI
1867 00 - CALL nn
1868 01 - DD
1869 10 - ED
1870 11 - FD
1873 ---------------------------------
1876 01 rrr 000 -- IN r8,(C)
1877 01 rrr 001 -- OUT (C),r8
1878 01 rr0 010 -- SBC HL,rr
1879 01 rr1 010 -- ADC HL,rr
1880 01 rr0 011 -- LD (nn),rr
1881 01 rr1 011 -- LD rr,(nn)
1883 01 000 100 -- NEG
1884 01 001 100 -- NEG
1885 01 010 100 -- NEG
1886 01 011 100 -- NEG
1887 01 100 100 -- NEG
1888 01 101 100 -- NEG
1889 01 110 100 -- NEG
1890 01 111 100 -- NEG
1892 01 000 101 -- RETN
1893 01 001 101 -- RETI
1894 01 010 101 -- RETN
1895 01 011 101 -- RETI
1896 01 100 101 -- RETN
1897 01 101 101 -- RETI
1898 01 110 101 -- RETN
1899 01 111 101 -- RETI
1901 01 000 110 -- IM 0
1902 01 001 110 -- IM 0/1
1903 01 010 110 -- IM 1
1904 01 011 110 -- IM 2
1905 01 100 110 -- IM 0
1906 01 101 110 -- IM 0
1907 01 111 110 -- IM 2
1909 01 000 111 -- LD I,A
1910 01 001 111 -- LD R,A
1911 01 010 111 -- LD A,I
1912 01 011 111 -- LD A,R
1913 01 100 111 -- RRD
1914 01 101 111 -- RLD
1915 01 110 111 -- NOP
1916 01 111 111 -- NOP
1919 10 1rd 0tt
1920 r: repeating instruction? (1: yes)
1921 d: direction (0:inc; 1:dec)
1922 tt: instruction type
1923 00: LD
1924 01: CP
1925 10: IN
1926 11: OUT
1928 10 100 000 -- LDI
1929 10 110 000 -- LDIR
1930 10 101 000 -- LDD
1931 10 111 000 -- LDDR
1933 10 100 001 -- CPI
1934 10 110 001 -- CPIR
1935 10 101 001 -- CPD
1936 10 111 001 -- CPDR
1938 10 100 010 -- INI
1939 10 110 010 -- INIR
1940 10 101 010 -- IND
1941 10 111 010 -- INDR
1943 10 100 011 -- OUTI
1944 10 110 011 -- OTIR
1945 10 101 011 -- OUTD
1946 10 111 011 -- OTDR
1949 ---------------------------------
1951 zz xxx rrr
1953 rrr: the usual r8
1956 00 -- see below
1957 01 -- BIT n, r8
1958 10 -- RES n, r8
1959 11 -- SET n, r8
1961 for bitops, xxx is bit number
1963 xxx:
1964 000 - RLC r8
1965 001 - RRC r8
1966 010 - RL r8
1967 011 - RR r8
1968 100 - SLA r8
1969 101 - SRA r8
1970 110 - SLS r8
1971 111 - SRL r8
1973 for DD/FD prefix, 3rd byte is always disp,
1974 and the result is always written to (I<X|Y>+disp)
1977 command reading cycles
1978 ======================
1979 the following is not 100% correct, but the position
1980 of the contention cycles is right
1982 m1 cycle (accoding to the official Zilog manual)
1983 t1: setting /MREQ & /RD
1984 t2: memory read
1985 here comes contetion (AFTER t2!)
1986 t3,t4: decode command, increment R
1988 memory read/write cycles (accoding to the official Zilog manual)
1989 t1,t2: memory address select
1990 here comes contetion (AFTER t2!)
1991 t3: bus read/write
1993 port i/o cycles (accoding to the official Zilog manual)
1994 t1,t2: port address select
1995 tw: automatic wait tick
1996 here comes contetion (AFTER t2!)
1997 t3: bus read/write
2000 flag register bits
2001 ==================
2002 bit 0: carry
2003 bit 1: flagN (see below)
2004 bit 2: parity/overflow
2005 bit 3: bit3
2006 bit 4: half-carry
2007 bit 5: bit5
2008 bit 6: zero
2009 bit 7: sign
2011 flagN:
2012 set if the last operation was a subtraction (used by DAA).
2014 P/V - parity or overflow
2015 parity set if even number of bits set
2016 overflow set if the 2-complement result does not fit in the register
2018 *******************************************************************************/