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.
18 # ifndef ZYMOSIS_INLINE
19 # define ZYMOSIS_INLINE static __attribute__((always_inline)) inline
22 # define ZYMOSIS_PURE __attribute__((pure))
24 # ifndef ZYMOSIS_CONST
25 # define ZYMOSIS_CONST __attribute__((const))
28 # define ZYMOSIS_FUNC __attribute__((warn_unused_result))
32 #ifndef ZYMOSIS_INLINE
33 # define ZYMOSIS_INLINE static
39 # define ZYMOSIS_CONST
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)))))
50 # define ZADD_WX(n,v) ((uint16_t)((uint16_t)(n) + (uint16_t)(v)))
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
) {
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
;
89 static __attribute__((constructor
)) void zym_init_tables_ctor (void) {
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
);
126 z80
->next_event_tstate
= -1;
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;
138 z80
->regI
= z80
->regR
= 0;
139 z80
->iff1
= z80
->iff2
= 0;
142 z80
->prev_was_EIDDR
= 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_)); \
188 #define z80_contention_by1ts(z80_,addr_,cnt_) do { \
189 const uint16_t xaddr_ = (addr_); \
190 uint32_t fcnt_ = (cnt_); \
193 (z80_)->mem_contention((z80_), xaddr_, ZYM_MEMIO_OTHER, ZYM_MREQ_NONE); \
194 (z80_)->tstates += 1; \
195 } while (fcnt_ != 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
) {
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
);
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
);
225 z80
->port_read_tstates
= z80
->tstates
-2;
226 value
= z80
->port_read(z80
, port
, ZYM_PORTIO_NORMAL
);
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);
241 z80
->port_write(z80
, port
, value
, ZYM_PORTIO_NORMAL
);
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 { \
258 if ((z80->tstates&0x01) != 0) z80->tstates += 1; \
263 # define EVEN_M1_TO_T3() do { \
265 z80->tstates = (int32_t)((uint32_t)(z80->tstates + 1) & ~(uint32_t)1); \
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
);
282 const uint8_t opc
= z80
->mem_read(z80
, z80
->pc
, ZYM_MEMIO_OPCEXT
);
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
295 // t1: setting /MREQ & /RD
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
);
303 const uint8_t res
= z80
->mem_read(z80
, addr
, ZYM_MEMIO_DATA
);
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
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
);
319 const uint8_t res
= z80
->mem_read(z80
, addr
, ZYM_MEMIO_OPCARG
);
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
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)
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
);
343 z80_pokeb(z80
, addr
, value
);
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
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
);
366 res
|= ((uint16_t)z80_mr_3ts_args(z80
, z80
->pc
))<<8;
367 if (wait1
) z80_contention_by1ts_pc(z80
, 1);
373 ZYMOSIS_INLINE
uint16_t z80_pop_6ts (zym_cpu_t
*z80
) {
374 uint16_t res
= z80_mr_3ts(z80
, z80
->sp
.w
);
376 res
|= ((uint16_t)z80_mr_3ts(z80
, z80
->sp
.w
))<<8;
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
) {
385 z80_pokeb_3ts(z80
, z80
->sp
.w
, (value
>>8)&0xffu
);
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
;
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
;
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
=
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
;
425 ZYMOSIS_INLINE
void ZYM_SUB_A (zym_cpu_t
*z80
, const uint8_t b
) {
426 z80
->af
.f
&= ~ZYM_FLAG_C
;
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
=
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
)|
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);
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);
597 z80
->flags_q
= z80
->af
.f
= (res
? z80
->af
.f
&(~ZYM_FLAG_Z
) : z80
->af
.f
|ZYM_FLAG_Z
);
601 ZYMOSIS_INLINE
void ZYM_BIT (zym_cpu_t
*z80
, const uint8_t bit
, const uint8_t num
, const zym_bool mptr
) {
604 (z80
->af
.f
&ZYM_FLAG_C
)|
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
);
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
);
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
) {
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 /******************************************************************************/
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; \
667 /* branch-less (assuming that `!` is branch-less) code */
668 static const uint8_t ccmask
[4] = {
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
) {
690 zym_bool gotDD
, trueCC
;
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 */
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.
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 */
729 /* this is prolly wrong: a pager should be called for "halted" state. but 'cmon! */
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 */
737 (void)z80
->mem_read(z80
, z80
->pc
+1u, ZYM_MEMIO_OPHLT
);
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 */
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 */
752 z80
->tstates
+= 2; // skip t3 and t4
754 z80
->pc
+= !z80
->halted
;
758 /* rollback tstates */
761 /* previous Q for SCF/CCF */
762 const uint8_t lastq
= z80
->flags_q
;
764 z80
->prev_was_EIDDR
= 0;
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
) {
772 z80
->dd
= (opcode
== 0xddu
? &z80
->ix
: &z80
->iy
);
773 /* we may need to rollback on double prefix */
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;
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 */
788 /* rollback tstates */
790 /* rollback R register */
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*/
796 /* restart main loop */
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*/
806 /* restart main loop */
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;
816 z80
->memptr
.w
= ZADD_WX(z80
->dd
->w
, disp
);
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
);
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
);
832 z80_contention_by1ts(z80
, z80
->de
.w
, 2);
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);
840 if (z80
->bc
.w
!= 0) {
842 z80_contention_by1ts(z80
, z80
->de
.w
, 5);
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
; }
853 /* CPI, CPIR, CPD, CPDR */
854 case 0xa1u
: case 0xb1u
: case 0xa9u
: case 0xb9u
:
855 tmpB
= z80_mr_3ts(z80
, z80
->hl
.w
);
857 z80_contention_by1ts(z80
, z80
->hl
.w
, 5);
859 z80
->af
.f
= /* BOO! FEAR THE MIGHTY BITS! */
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 */
872 if ((z80
->af
.f
&(ZYM_FLAG_Z
|ZYM_FLAG_PV
)) == ZYM_FLAG_PV
) {
874 z80_contention_by1ts(z80
, z80
->hl
.w
, 5);
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
));
882 /* new MEMPTR code */
883 //if (CBX_BACKWARD) --z80->memptr.w; else ++z80->memptr.w;
884 z80
->memptr
.w
+= tmpW
;
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;
894 /* OUTI, OTIR, OUTD, OTDR */
895 case 0xa3u
: case 0xb3u
: case 0xabu
: case 0xbbu
:
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
;
903 z80_contention_by1ts_ir(z80
, 1);
906 tmpB
= z80_mr_3ts(z80
, z80
->hl
.w
);/*MRD(3)*/
907 z80_port_write(z80
, z80
->bc
.w
, tmpB
);
909 if (CBX_BACKWARD
) --tmpW
; else ++tmpW
;
910 tmpC
= (tmpB
+tmpW
)&0xffu
;
913 tmpB
= z80_port_read(z80
, z80
->bc
.w
);
914 z80_pokeb_3ts(z80
, z80
->hl
.w
, tmpB
);/*MWR(3)*/
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
]|
924 /* repeating commands */
925 if (z80
->bc
.b
!= 0) {
926 uint16_t a
= (opcode
&0x01u
? z80
->bc
.w
: z80
->hl
.w
);
928 z80_contention_by1ts(z80
, a
, 5);
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
937 PF = PF ^ Parity((B - 1) & 0x7) ^ 1;
938 HF = (B & 0x0F) == 0x00;
940 PF = PF ^ Parity((B + 1) & 0x7) ^ 1;
941 HF = (B & 0x0F) == 0x0F;
944 PF = PF ^ Parity(B & 0x7) ^ 1;
947 if (z80
->af
.f
&ZYM_FLAG_C
) {
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);
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);
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
;
963 /* not strings, but some good instructions anyway */
965 if ((opcode
&0xc0u
) == 0x40u
) {
967 switch (opcode
&0x07u
) {
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 */
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
);
1000 /* SBC HL,rr/ADC HL,rr */
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
));
1012 /* LD (nn),rr/LD rr,(nn) */
1014 tmpW
= z80_getpcw(z80
, 0);
1015 z80
->memptr
.w
= tmpW
+1u;
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;
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;
1038 ZYM_SUB_A(z80
, tmpB
);
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
);
1048 if (z80
->trap_reti
!= NULL
) {
1049 z80
->trap_ts
= z80
->tstates
- tstart
;
1050 if (z80
->trap_reti(z80
, opcode
)) return z80
->tstates
- tstart
;
1054 if (z80
->trap_retn
!= NULL
) {
1055 z80
->trap_ts
= z80
->tstates
- tstart
;
1056 if (z80
->trap_retn(z80
, opcode
)) return z80
->tstates
- tstart
;
1063 case 0x56u
: case 0x76u
: z80
->im
= 1; break;
1064 case 0x5eu
: case 0x7eu
: z80
->im
= 2; break;
1065 default: z80
->im
= 0; break;
1074 z80_contention_by1ts_ir(z80
, 1);
1075 z80
->regI
= z80
->af
.a
;
1080 z80_contention_by1ts_ir(z80
, 1);
1081 z80
->regR
= z80
->af
.a
;
1084 case 0x57u
: ZYM_LD_A_IR(z80
, z80
->regI
); break;
1086 case 0x5fu
: ZYM_LD_A_IR(z80
, z80
->regR
); break;
1088 case 0x67u
: ZYM_RRD_A(z80
); break;
1090 case 0x6F: ZYM_RLD_A(z80
); break;
1094 /* slt and other traps */
1096 case 0xfb: // SLT trap
1097 if (z80
->trap_edfb(z80
, opcode
)) return z80
->tstates
- tstart
;
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
;
1110 /* CB-prefixed instructions */
1111 if (opcode
== 0xcbu
) {
1112 /* shifts and bit operations */
1113 /* read opcode -- OCR(4) */
1115 opcode
= zym_get_opcode_ext(z80
);
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
);
1121 opcode
= z80
->mem_read(z80
, z80
->pc
, ZYM_MEMIO_OPCEXT
);
1122 z80_contention_by1ts(z80
, z80
->pc
, 2);
1125 //FIXME: check if it really skips `INC_R`
1126 opcode
= zym_get_opcode_ext(z80
);
1131 tmpW
= ZADD_WX(z80
->dd
->w
, disp
);
1132 tmpB
= z80_mr_3ts(z80
, tmpW
);
1133 z80_contention_by1ts(z80
, tmpW
, 1);
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
);
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;
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 */
1168 if ((opcode
&0xc0u
) != 0x40u
) {
1169 /* BITs are not welcome here */
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;
1188 switch (opcode
&0xc0u
) {
1191 switch (opcode
&0x07u
) {
1192 /* misc,DJNZ,JR,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
));
1210 if ((opcode
&0x08u
) == 0) {
1213 z80_contention_by1ts_ir(z80
, 1);
1215 trueCC
= (z80
->bc
.b
!= 0);
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 */
1225 disp
= z80_mr_3ts_args(z80
, z80
->pc
);
1227 z80_contention(z80
, z80
->pc
, ZYM_MEMIO_OPCARG
, ZYM_MREQ_READ
);
1232 disp
= z80_mr_3ts_args(z80
, z80
->pc
);
1235 /* execute branch (relative) */
1237 if (disp
> 127) disp
-= 256; /* convert to int8_t */
1238 z80_contention_by1ts_pc(z80
, 5);
1240 z80
->memptr
.w
= z80
->pc
= ZADD_WX(z80
->pc
, disp
);
1245 /* EX AF,AF' or NOP */
1246 if (opcode
!= 0) zym_exaf_internal(z80
);
1249 /* LD rr,nn/ADD HL,rr */
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;
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;
1274 switch ((opcode
>>3)&0x07u
) {
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;
1278 case 1: z80
->af
.a
= z80_mr_3ts(z80
, z80
->bc
.w
); z80
->memptr
.w
= z80
->bc
.w
+1u; break;
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;
1282 case 3: z80
->af
.a
= z80_mr_3ts(z80
, z80
->de
.w
); z80
->memptr
.w
= z80
->de
.w
+1u; break;
1285 tmpW
= z80_getpcw(z80
, 0);
1286 z80
->memptr
.w
= tmpW
+1u;
1287 z80_pokew_6ts(z80
, tmpW
, z80
->dd
->w
);
1291 tmpW
= z80_getpcw(z80
, 0);
1292 z80
->memptr
.w
= tmpW
+1u;
1293 z80
->dd
->w
= z80_peekw_6ts(z80
, tmpW
);
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
);
1304 tmpW
= z80_getpcw(z80
, 0);
1305 z80
->memptr
.w
= tmpW
+1u;
1306 z80
->af
.a
= z80_mr_3ts(z80
, tmpW
);
1313 z80_contention_by1ts_ir(z80
, 2);
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;
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;
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;
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
);
1349 case 7: z80
->af
.a
= ZYM_INC8(z80
, z80
->af
.a
); break;
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;
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
);
1369 case 7: z80
->af
.a
= ZYM_DEC8(z80
, z80
->af
.a
); break;
1374 tmpB
= z80_mr_3ts_args(z80
, 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;
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
);
1388 case 7: z80
->af
.a
= tmpB
; break;
1391 /* swim-swim-hungry */
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;
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
));
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
;
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
);
1415 /* 0x40..0x7F (LD r8,r8) */
1417 if (opcode
== 0x76u
) {
1421 if (z80
->trap_halt
!= NULL
&& z80
->trap_halt(z80
)) return z80
->tstates
- tstart
;
1424 rsrc
= (opcode
&0x07u
);
1425 rdst
= ((opcode
>>3)&0x07u
);
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;
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
);
1438 case 7: tmpB
= z80
->af
.a
; break;
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;
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
);
1452 case 7: z80
->af
.a
= tmpB
; break;
1455 /* 0x80..0xBF (ALU A,r8) */
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;
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
);
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;
1484 switch (opcode
&0x07u
) {
1487 z80_contention_by1ts_ir(z80
, 1);
1489 if (trueCC
) z80
->memptr
.w
= z80
->pc
= z80_pop_6ts(z80
);
1491 /* POP rr/special0 */
1495 switch ((opcode
>>4)&0x03u
) {
1497 case 0: z80
->memptr
.w
= z80
->pc
= z80_pop_6ts(z80
); break;
1499 case 1: zym_exx_internal(z80
); break;
1501 case 2: z80
->pc
= z80
->dd
->w
; break;
1505 z80_contention_by1ts_ir(z80
, 2);
1506 z80
->sp
.w
= z80
->dd
->w
;
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;
1523 z80
->memptr
.w
= z80_getpcw(z80
, 0);
1524 if (trueCC
) z80
->pc
= z80
->memptr
.w
;
1526 /* special1/special3 */
1528 switch ((opcode
>>3)&0x07u
) {
1530 case 0: z80
->memptr
.w
= z80
->pc
= z80_getpcw(z80
, 0); break;
1533 tmpW
= z80_mr_3ts_args(z80
, 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
);
1542 tmpB
= z80_mr_3ts_args(z80
, z80
->pc
);
1543 tmpW
= (uint16_t)((((uint16_t)(z80
->af
.a
))<<8)|tmpB
);
1546 z80
->memptr
.h
= z80
->af
.a
;
1547 z80
->memptr
.w
+= tmpB
+1u;
1548 z80
->af
.a
= z80_port_read(z80
, tmpW
);
1553 tmpW
= z80_peekw_6ts(z80
, z80
->sp
.w
);
1554 z80_contention_by1ts(z80
, z80
->sp
.w
+1u, 1);
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
;
1563 z80
->de
.w
= z80
->hl
.w
;
1567 case 6: z80
->iff1
= z80
->iff2
= 0; break;
1569 case 7: z80
->iff1
= z80
->iff2
= 1; z80
->prev_was_EIDDR
= 1; break;
1575 /* MEMPTR docs says that it is like JP */
1576 z80
->memptr
.w
= z80_getpcw(z80
, trueCC
);
1578 z80_push_6ts(z80
, z80
->pc
);
1579 z80
->pc
= z80
->memptr
.w
;
1582 /* PUSH rr/special2 */
1585 if (((opcode
>>4)&0x03u
) == 0) {
1587 z80
->memptr
.w
= tmpW
= z80_getpcw(z80
, 1);
1588 z80_push_6ts(z80
, z80
->pc
);
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
);
1606 tmpB
= z80_mr_3ts_args(z80
, 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;
1622 z80_contention_by1ts_ir(z80
, 1);
1623 z80_push_6ts(z80
, z80
->pc
);
1624 z80
->memptr
.w
= z80
->pc
= opcode
&0x38u
;
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
;
1643 /******************************************************************************/
1644 /* changes z80->tstates if interrupt occurs */
1645 int32_t zym_intr (zym_cpu_t
*z80
) {
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 */
1657 //if (z80->halted) { z80->halted = 0; /* z80->pc += 1u;*/ }
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' */
1671 case 1: /* just do RST #38 */
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
;
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
);
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 */
1709 //if (z80->halted) { z80->halted = 0; /* z80->pc += 1;*/ }
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
);
1726 res
|= ((uint16_t)z80_peekb_i(z80
, z80
->sp
.w
))<<8;
1732 void zym_push (zym_cpu_t
*z80
, const uint16_t value
) {
1734 z80_pokeb_i(z80
, z80
->sp
.w
, (value
>>8)&0xffu
);
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
1798 ---------------------------------
1800 01 rrr rrr - LD r8,r8 (lo: src)
1802 ---------------------------------
1804 10 alu rrr - ALU a,r8
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
1833 aaa: RST addr=aaa<<3
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)
1902 01 001 110 -- IM 0/1
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
1920 r: repeating instruction? (1: yes)
1921 d: direction (0:inc; 1:dec)
1922 tt: instruction type
1949 ---------------------------------
1961 for bitops, xxx is bit number
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
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!)
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!)
2003 bit 1: flagN (see below)
2004 bit 2: parity/overflow
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 *******************************************************************************/