2 * Z80 CPU emulation engine v0.1.1
3 * coded by Ketmar // Invisible Vector (psyc://ketmar.no-ip.org/~ketmar)
4 * Understanding is not required. Only obedience.
6 * This program is free software. It comes without any warranty, to
7 * the extent permitted by applicable law. You can redistribute it
8 * and/or modify it under the terms of the Do What The Fuck You Want
9 * To Public License, Version 2, as published by Sam Hocevar. See
10 * http://www.wtfpl.net/txt/copying/ for more details.
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 /******************************************************************************/
47 /* some funny tables */
48 static int tables_inited
= 0;
49 static uint8_t parity_tbl
[256];
50 static uint8_t sz53_tbl
[256]; /* bits 3, 5 and 7 of result, Z flag */
51 static uint8_t sz53p_tbl
[256]; /* bits 3, 5 and 7 of result, Z and P flags */
54 //**************************************************************************
56 // various initialisations
58 //**************************************************************************
60 // initialise internal flag tables
61 // WARNING! this is NOT thread-safe!
62 void zym_init_tables (void) {
63 if (tables_inited
) return;
64 for (unsigned f
= 0; f
< 256; ++f
) {
66 sz53_tbl
[f
] = (f
&ZYM_FLAG_S35
);
67 for (n
= f
, p
= 0; n
!= 0; n
>>= 1) p
^= n
&0x01u
;
68 parity_tbl
[f
] = (p
? 0 : ZYM_FLAG_PV
);
69 sz53p_tbl
[f
] = (sz53_tbl
[f
]|parity_tbl
[f
]);
71 sz53_tbl
[0] |= ZYM_FLAG_Z
;
72 sz53p_tbl
[0] |= ZYM_FLAG_Z
;
78 static __attribute__((constructor
)) void zym_init_tables_ctor (void) {
84 // should be called on new instance of zym_cpu_t to clear all callbacks
85 void zym_clear_callbacks (zym_cpu_t
*z80
) {
86 if (!tables_inited
) zym_init_tables();
88 z80
->mem_write
= NULL
;
89 z80
->mem_contention
= NULL
;
90 z80
->port_read
= NULL
;
91 z80
->port_write
= NULL
;
92 z80
->port_contention
= NULL
;
93 z80
->trap_reti
= NULL
;
94 z80
->trap_retn
= NULL
;
96 z80
->opc_pager
= NULL
;
100 // clear all flags and callbacks; will reset 'z80->user' too
101 void zym_init (zym_cpu_t
*z80
) {
102 if (!tables_inited
) zym_init_tables();
103 memset(z80
, 0, sizeof(*z80
));
104 zym_clear_callbacks(z80
);
106 z80
->next_event_tstate
= -1;
111 // seems that all regs (and memptr) should be set to 'all 1' here, but i don't care
112 void zym_reset (zym_cpu_t
*z80
) {
113 if (!tables_inited
) zym_init_tables();
114 z80
->bc
.w
= z80
->de
.w
= z80
->hl
.w
= z80
->af
.w
= z80
->sp
.w
= z80
->ix
.w
= z80
->iy
.w
= 0;
115 z80
->bcx
.w
= z80
->dex
.w
= z80
->hlx
.w
= z80
->afx
.w
= 0;
116 z80
->pc
= z80
->prev_pc
= z80
->org_pc
= 0;
118 z80
->regI
= z80
->regR
= 0;
119 z80
->iff1
= z80
->iff2
= 0;
122 z80
->prev_was_EIDDR
= 0;
129 //**************************************************************************
131 // alternate register set functions
133 //**************************************************************************
135 ZYMOSIS_INLINE
void zym_exx_internal (zym_cpu_t
*z80
) {
136 uint16_t t
= z80
->bc
.w
; z80
->bc
.w
= z80
->bcx
.w
; z80
->bcx
.w
= t
;
137 t
= z80
->de
.w
; z80
->de
.w
= z80
->dex
.w
; z80
->dex
.w
= t
;
138 t
= z80
->hl
.w
; z80
->hl
.w
= z80
->hlx
.w
; z80
->hlx
.w
= t
;
142 ZYMOSIS_INLINE
void zym_exaf_internal (zym_cpu_t
*z80
) {
143 const uint16_t t
= z80
->af
.w
; z80
->af
.w
= z80
->afx
.w
; z80
->afx
.w
= t
;
147 // swap normal and alternate register sets (except AF/AF')
148 void zym_exx (zym_cpu_t
*z80
) {
149 zym_exx_internal(z80
);
153 // swap normal and alternate AF
154 void zym_exaf (zym_cpu_t
*z80
) {
155 zym_exaf_internal(z80
);
159 /******************************************************************************/
160 /* simulate contented memory access */
161 /* (tstates = tstates+contention+1)*cnt */
162 /* (zym_cpu_t *z80, uint16_t addr, int tstates, zym_memio_t mio) */
163 #define z80_contention(z80_,addr_,tstates_,mio_,mrq_) do { \
164 if ((z80_)->mem_contention != NULL) (z80_)->mem_contention((z80_), (addr_), (tstates_), (mio_), (mrq_)); else (z80_)->tstates += (tstates_); \
168 #define z80_contention_by1ts(z80_,addr_,cnt_) do { \
169 if ((z80)->mem_contention != NULL) { \
170 for (unsigned fcnt = (cnt_); fcnt--; (z80_)->mem_contention((z80_), (addr_), 1, ZYM_MEMIO_OTHER, ZYM_MREQ_NONE)) {} \
172 (z80_)->tstates += (cnt_); \
177 #define z80_contention_by1ts_ir(z80_,cnt_) z80_contention_by1ts((z80_), (((uint16_t)(z80_)->regI)<<8)|((z80_)->regR), (cnt_))
178 #define z80_contention_by1ts_pc(z80_,cnt_) z80_contention_by1ts((z80_), (z80_)->pc, (cnt_))
181 /******************************************************************************/
182 ZYMOSIS_INLINE
uint8_t z80_port_read (zym_cpu_t
*z80
, const uint16_t port
) {
184 /* i don't really know: FUSE tester seems to do port read in-between contentions,
185 but the actual emulator code does it after all contentions are done.
186 i guess that doing it in-between is the right way.
187 note: ok, it broke floating bus emulation in ZXEmuT. oopsie!
189 if (z80
->port_contention
!= NULL
) {
190 z80
->port_contention(z80
, port
, 1, ZYM_PORTIO_FLAG_IN
|ZYM_PORTIO_FLAG_EARLY
);
191 z80
->port_read_tstates
= z80
->tstates
;
192 #ifdef ZYMOSIS_FUSE_TEST
193 /* for FUSE tests, it should be here */
194 value
= z80
->port_read(z80
, port
, ZYM_PORTIO_NORMAL
);
196 z80
->port_contention(z80
, port
, 2, ZYM_PORTIO_FLAG_IN
);
197 #ifndef ZYMOSIS_FUSE_TEST
198 /* for ZXEmuT floating bus emulation, it should be here */
199 value
= z80
->port_read(z80
, port
, ZYM_PORTIO_NORMAL
);
203 z80
->port_read_tstates
= z80
->tstates
-2;
204 value
= z80
->port_read(z80
, port
, ZYM_PORTIO_NORMAL
);
211 ZYMOSIS_INLINE
void z80_port_write (zym_cpu_t
*z80
, const uint16_t port
, const uint8_t value
) {
212 if (z80
->port_contention
!= NULL
) {
213 z80
->port_contention(z80
, port
, 1, ZYM_PORTIO_FLAG_EARLY
);
214 z80
->port_write(z80
, port
, value
, ZYM_PORTIO_NORMAL
);
215 z80
->port_contention(z80
, port
, 2, 0);
219 z80
->port_write(z80
, port
, value
, ZYM_PORTIO_NORMAL
);
225 /******************************************************************************/
226 #define z80_peekb_i(z80_,addr_) (z80_)->mem_read((z80_), (addr_), ZYM_MEMIO_OTHER)
227 #define z80_peekb(z80_,addr_) (z80_)->mem_read((z80_), (addr_), ZYM_MEMIO_DATA)
229 #define z80_pokeb_i(z80_,addr_,byte_) (z80_)->mem_write((z80_), (addr_), (byte_), ZYM_MEMIO_OTHER)
230 #define z80_pokeb(z80_,addr_,byte_) (z80_)->mem_write((z80_), (addr_), (byte_), ZYM_MEMIO_DATA)
233 /* t1: setting /MREQ & /RD */
234 /* t2: memory read */
235 ZYMOSIS_INLINE
uint8_t z80_peekb_3ts (zym_cpu_t
*z80
, const uint16_t addr
) {
236 z80_contention(z80
, addr
, 3, ZYM_MEMIO_DATA
, ZYM_MREQ_READ
);
237 return z80_peekb(z80
, addr
);
240 ZYMOSIS_INLINE
uint8_t z80_peekb_3ts_args (zym_cpu_t
*z80
, const uint16_t addr
) {
241 z80_contention(z80
, addr
, 3, ZYM_MEMIO_OPCARG
, ZYM_MREQ_READ
);
242 return z80_peekb(z80
, addr
);
245 ZYMOSIS_INLINE
void z80_peekb_3ts_args_noread (zym_cpu_t
*z80
, const uint16_t addr
) {
246 z80_contention(z80
, addr
, 3, ZYM_MEMIO_OPCARG
, ZYM_MREQ_READ
);
249 ZYMOSIS_INLINE
uint16_t z80_peekw_6ts (zym_cpu_t
*z80
, const uint16_t addr
) {
250 const uint16_t res
= z80_peekb_3ts(z80
, addr
);
251 return res
|(((uint16_t)z80_peekb_3ts(z80
, (addr
+1)&0xffffu
))<<8);
254 /* t1: setting /MREQ & /WR */
255 /* t2: memory write */
256 ZYMOSIS_INLINE
void z80_pokeb_3ts (zym_cpu_t
*z80
, const uint16_t addr
, const uint8_t value
) {
257 z80_contention(z80
, addr
, 3, ZYM_MEMIO_DATA
, ZYM_MREQ_WRITE
);
258 z80_pokeb(z80
, addr
, value
);
261 ZYMOSIS_INLINE
void z80_pokew_6ts (zym_cpu_t
*z80
, const uint16_t addr
, const uint16_t value
) {
262 z80_pokeb_3ts(z80
, addr
, value
&0xffu
);
263 z80_pokeb_3ts(z80
, (addr
+1)&0xffffu
, (value
>>8)&0xffu
);
266 ZYMOSIS_INLINE
void z80_pokew_6ts_inverted (zym_cpu_t
*z80
, const uint16_t addr
, const uint16_t value
) {
267 z80_pokeb_3ts(z80
, (addr
+1)&0xffffu
, (value
>>8)&0xffu
);
268 z80_pokeb_3ts(z80
, addr
, value
&0xffu
);
272 ZYMOSIS_INLINE
uint16_t z80_getpcw (zym_cpu_t
*z80
, const zym_bool wait1
) {
273 uint16_t res
= z80_peekb_3ts_args(z80
, z80
->pc
);
274 z80
->pc
= (z80
->pc
+1)&0xffffu
;
275 res
|= ((uint16_t)z80_peekb_3ts_args(z80
, z80
->pc
))<<8;
276 if (wait1
) z80_contention_by1ts_pc(z80
, 1);
277 z80
->pc
= (z80
->pc
+1)&0xffffu
;
282 ZYMOSIS_INLINE
uint16_t z80_pop_6ts (zym_cpu_t
*z80
) {
283 uint16_t res
= z80_peekb_3ts(z80
, z80
->sp
.w
);
284 z80
->sp
.w
= (z80
->sp
.w
+1)&0xffffu
;
285 res
|= ((uint16_t)z80_peekb_3ts(z80
, z80
->sp
.w
))<<8;
286 z80
->sp
.w
= (z80
->sp
.w
+1)&0xffffu
;
290 /* 3 T states write high byte of PC to the stack and decrement SP */
291 /* 3 T states write the low byte of PC and jump to #0066 */
292 ZYMOSIS_INLINE
void z80_push_6ts (zym_cpu_t
*z80
, uint16_t value
) {
293 z80
->sp
.w
= (((uint32_t)z80
->sp
.w
)-1u)&0xffffu
;
294 z80_pokeb_3ts(z80
, z80
->sp
.w
, (value
>>8)&0xffu
);
295 z80
->sp
.w
= (((uint32_t)z80
->sp
.w
)-1u)&0xffffu
;
296 z80_pokeb_3ts(z80
, z80
->sp
.w
, value
&0xffu
);
300 /******************************************************************************/
301 /* you are not expected to understand the following bit-mess */
302 /* the only thing you want to know that IT WORKS; just believe me and the testing suite */
303 /* ok, you can consult Z80 manuals to find the affected flags */
304 /* but believe me, it is unnecessary */
306 ZYMOSIS_INLINE
void ZYM_ADC_A (zym_cpu_t
*z80
, const uint8_t b
) {
307 const uint16_t o
= z80
->af
.a
;
309 z80
->af
.a
= (newv
= o
+b
+(z80
->af
.f
&ZYM_FLAG_C
))&0xffu
; /* ZYM_FLAG_C is 0x01u, so it's safe */
310 z80
->flags_q
= z80
->af
.f
=
311 sz53_tbl
[newv
&0xffu
]|
312 (newv
> 0xffu
? ZYM_FLAG_C
: 0)|
313 ((o
^(~b
))&(o
^newv
)&0x80u
? ZYM_FLAG_PV
: 0)|
314 ((o
&0x0fu
)+(b
&0x0fu
)+(z80
->af
.f
&ZYM_FLAG_C
) >= 0x10u
? ZYM_FLAG_H
: 0);
317 ZYMOSIS_INLINE
void ZYM_SBC_A (zym_cpu_t
*z80
, const uint8_t b
) {
318 const uint16_t o
= z80
->af
.a
;
320 z80
->af
.a
= (newv
= ((uint32_t)o
-(uint32_t)b
-(uint32_t)(z80
->af
.f
&ZYM_FLAG_C
))&0xffffu
)&0xffu
; /* ZYM_FLAG_C is 0x01u, so it's safe */
321 z80
->flags_q
= z80
->af
.f
=
323 sz53_tbl
[newv
&0xffu
]|
324 (newv
> 0xffu
? ZYM_FLAG_C
: 0)|
325 ((o
^b
)&(o
^newv
)&0x80u
? ZYM_FLAG_PV
: 0)|
326 ((int)(o
&0x0fu
)-(int)(b
&0x0fu
)-(int)(z80
->af
.f
&ZYM_FLAG_C
) < 0 ? ZYM_FLAG_H
: 0);
330 ZYMOSIS_INLINE
void ZYM_ADD_A (zym_cpu_t
*z80
, const uint8_t b
) {
331 z80
->af
.f
&= ~ZYM_FLAG_C
;
335 ZYMOSIS_INLINE
void ZYM_SUB_A (zym_cpu_t
*z80
, const uint8_t b
) {
336 z80
->af
.f
&= ~ZYM_FLAG_C
;
340 ZYMOSIS_INLINE
void ZYM_CP_A (zym_cpu_t
*z80
, const uint8_t b
) {
341 const uint8_t o
= z80
->af
.a
;
342 const uint8_t newv
= ((uint32_t)o
-(uint32_t)b
)&0xffu
;
343 z80
->flags_q
= z80
->af
.f
=
347 (newv
== 0 ? ZYM_FLAG_Z
: 0)|
348 (o
< b
? ZYM_FLAG_C
: 0)|
349 ((o
^b
)&(o
^newv
)&0x80u
? ZYM_FLAG_PV
: 0)|
350 ((int)(o
&0x0fu
)-(int)(b
&0x0fu
) < 0 ? ZYM_FLAG_H
: 0);
354 #define ZYM_AND_A(z80_,b_) ((z80_)->flags_q = (z80_)->af.f = sz53p_tbl[(z80_)->af.a&=(b_)]|ZYM_FLAG_H)
355 #define ZYM_OR_A(z80_,b_) ((z80_)->flags_q = (z80_)->af.f = sz53p_tbl[(z80_)->af.a|=(b_)])
356 #define ZYM_XOR_A(z80_,b_) ((z80_)->flags_q = (z80_)->af.f = sz53p_tbl[(z80_)->af.a^=(b_)])
359 /* carry unchanged */
360 ZYMOSIS_INLINE
uint8_t ZYM_DEC8 (zym_cpu_t
*z80
, const uint8_t b
) {
361 z80
->af
.f
&= ZYM_FLAG_C
;
362 z80
->af
.f
|= ZYM_FLAG_N
|
363 (b
== 0x80u
? ZYM_FLAG_PV
: 0)|
364 (b
&0x0fu
? 0 : ZYM_FLAG_H
)|
365 sz53_tbl
[(((uint32_t)b
)-1u)&0xffu
];
366 z80
->flags_q
= z80
->af
.f
;
367 return (((uint32_t)b
)-1u)&0xffu
;
370 /* carry unchanged */
371 ZYMOSIS_INLINE
uint8_t ZYM_INC8 (zym_cpu_t
*z80
, const uint8_t b
) {
372 z80
->af
.f
&= ZYM_FLAG_C
;
374 (b
== 0x7fu
? ZYM_FLAG_PV
: 0)|
375 ((b
+1u)&0x0fu
? 0 : ZYM_FLAG_H
)|
376 sz53_tbl
[(b
+1u)&0xffu
];
377 z80
->flags_q
= z80
->af
.f
;
378 return ((b
+1u)&0xffu
);
382 /* cyclic, carry reflects shifted bit */
383 ZYMOSIS_INLINE
void ZYM_RLCA (zym_cpu_t
*z80
) {
384 const uint8_t c
= ((z80
->af
.a
>>7)&0x01u
);
385 z80
->af
.a
= (z80
->af
.a
<<1)|c
;
386 z80
->flags_q
= z80
->af
.f
= c
|(z80
->af
.a
&ZYM_FLAG_35
)|(z80
->af
.f
&(ZYM_FLAG_PV
|ZYM_FLAG_Z
|ZYM_FLAG_S
));
389 /* cyclic, carry reflects shifted bit */
390 ZYMOSIS_INLINE
void ZYM_RRCA (zym_cpu_t
*z80
) {
391 const uint8_t c
= (z80
->af
.a
&0x01u
);
392 z80
->af
.a
= (z80
->af
.a
>>1)|(c
<<7);
393 z80
->flags_q
= z80
->af
.f
= c
|(z80
->af
.a
&ZYM_FLAG_35
)|(z80
->af
.f
&(ZYM_FLAG_PV
|ZYM_FLAG_Z
|ZYM_FLAG_S
));
397 /* cyclic thru carry */
398 ZYMOSIS_INLINE
void ZYM_RLA (zym_cpu_t
*z80
) {
399 const uint8_t c
= ((z80
->af
.a
>>7)&0x01u
);
400 z80
->af
.a
= (z80
->af
.a
<<1)|(z80
->af
.f
&ZYM_FLAG_C
);
401 z80
->flags_q
= z80
->af
.f
= c
|(z80
->af
.a
&ZYM_FLAG_35
)|(z80
->af
.f
&(ZYM_FLAG_PV
|ZYM_FLAG_Z
|ZYM_FLAG_S
));
404 /* cyclic thru carry */
405 ZYMOSIS_INLINE
void ZYM_RRA (zym_cpu_t
*z80
) {
406 const uint8_t c
= (z80
->af
.a
&0x01u
);
407 z80
->af
.a
= (z80
->af
.a
>>1)|((z80
->af
.f
&ZYM_FLAG_C
)<<7);
408 z80
->flags_q
= z80
->af
.f
= c
|(z80
->af
.a
&ZYM_FLAG_35
)|(z80
->af
.f
&(ZYM_FLAG_PV
|ZYM_FLAG_Z
|ZYM_FLAG_S
));
411 /* cyclic thru carry */
412 ZYMOSIS_INLINE
uint8_t ZYM_RL (zym_cpu_t
*z80
, uint8_t b
) {
413 const uint8_t c
= (b
>>7)&ZYM_FLAG_C
;
414 z80
->flags_q
= z80
->af
.f
= sz53p_tbl
[(b
= ((b
<<1)&0xffu
)|(z80
->af
.f
&ZYM_FLAG_C
))]|c
;
419 ZYMOSIS_INLINE
uint8_t ZYM_RR (zym_cpu_t
*z80
, uint8_t b
) {
420 const uint8_t c
= (b
&0x01u
);
421 z80
->flags_q
= z80
->af
.f
= sz53p_tbl
[(b
= (b
>>1)|((z80
->af
.f
&ZYM_FLAG_C
)<<7))]|c
;
425 /* cyclic, carry reflects shifted bit */
426 ZYMOSIS_INLINE
uint8_t ZYM_RLC (zym_cpu_t
*z80
, uint8_t b
) {
427 const uint8_t c
= ((b
>>7)&ZYM_FLAG_C
);
428 z80
->flags_q
= z80
->af
.f
= sz53p_tbl
[(b
= ((b
<<1)&0xffu
)|c
)]|c
;
432 /* cyclic, carry reflects shifted bit */
433 ZYMOSIS_INLINE
uint8_t ZYM_RRC (zym_cpu_t
*z80
, uint8_t b
) {
434 const uint8_t c
= (b
&0x01u
);
435 z80
->flags_q
= z80
->af
.f
= sz53p_tbl
[(b
= (b
>>1)|(c
<<7))]|c
;
439 /* shift left arithmetic, sets bit 0 to zero, carry reflects shifted bit */
440 ZYMOSIS_INLINE
uint8_t ZYM_SLA (zym_cpu_t
*z80
, uint8_t b
) {
441 uint8_t c
= ((b
>>7)&0x01u
);
442 z80
->flags_q
= z80
->af
.f
= sz53p_tbl
[(b
<<= 1)]|c
;
446 /* shift right arithmetic, sets bit 6 to bit 7, carry reflects shifted bit */
447 ZYMOSIS_INLINE
uint8_t ZYM_SRA (zym_cpu_t
*z80
, uint8_t b
) {
448 const uint8_t c
= (b
&0x01u
);
449 z80
->flags_q
= z80
->af
.f
= sz53p_tbl
[(b
= (b
>>1)|(b
&0x80u
))]|c
;
453 /* shift left logic, sets bit 0 to one, carry reflects shifted bit */
454 ZYMOSIS_INLINE
uint8_t ZYM_SLL (zym_cpu_t
*z80
, uint8_t b
) {
455 const uint8_t c
= ((b
>>7)&0x01u
);
456 z80
->flags_q
= z80
->af
.f
= sz53p_tbl
[(b
= (b
<<1)|0x01u
)]|c
;
460 /* shift right logic, sets bit 7 to zero, carry reflects shifted bit */
461 ZYMOSIS_INLINE
uint8_t ZYM_SRL (zym_cpu_t
*z80
, uint8_t b
) {
462 const uint8_t c
= (b
&0x01u
);
463 z80
->flags_q
= z80
->af
.f
= sz53p_tbl
[(b
>>= 1)]|c
;
469 ZYMOSIS_INLINE
uint16_t ZYM_ADD_DD (zym_cpu_t
*z80
, const uint16_t value
, const uint16_t ddvalue
) {
470 /* `static` is more restrective here, simple `const` should generate better code */
471 /*static*/ const uint8_t hct
[8] = { 0, ZYM_FLAG_H
, ZYM_FLAG_H
, ZYM_FLAG_H
, 0, 0, 0, ZYM_FLAG_H
};
472 const uint32_t res
= (uint32_t)value
+(uint32_t)ddvalue
;
473 const uint8_t b
= ((value
&0x0800u
)>>11)|((ddvalue
&0x0800u
)>>10)|((res
&0x0800u
)>>9);
474 z80
->memptr
.w
= (ddvalue
+1u)&0xffffu
;
475 z80
->flags_q
= z80
->af
.f
=
476 (z80
->af
.f
&(ZYM_FLAG_PV
|ZYM_FLAG_Z
|ZYM_FLAG_S
))|
477 (res
> 0xffffu
? ZYM_FLAG_C
: 0)|
478 ((res
>>8)&ZYM_FLAG_35
)|
484 ZYMOSIS_INLINE
uint16_t ZYM_ADC_DD (zym_cpu_t
*z80
, const uint16_t value
, const uint16_t ddvalue
) {
485 const uint8_t c
= (z80
->af
.f
&ZYM_FLAG_C
);
486 const uint32_t newv
= (uint32_t)value
+(uint32_t)ddvalue
+(uint32_t)c
;
487 const uint16_t res
= (newv
&0xffffu
);
488 z80
->memptr
.w
= (ddvalue
+1)&0xffffu
;
489 z80
->flags_q
= z80
->af
.f
=
490 ((res
>>8)&ZYM_FLAG_S35
)|
491 (res
== 0 ? ZYM_FLAG_Z
: 0)|
492 (newv
> 0xffffu
? ZYM_FLAG_C
: 0)|
493 ((value
^((~ddvalue
)&0xffffu
))&(value
^newv
)&0x8000u
? ZYM_FLAG_PV
: 0)|
494 ((value
&0x0fffu
)+(ddvalue
&0x0fffu
)+c
>= 0x1000u
? ZYM_FLAG_H
: 0);
499 ZYMOSIS_INLINE
uint16_t ZYM_SBC_DD (zym_cpu_t
*z80
, const uint16_t value
, const uint16_t ddvalue
) {
500 const uint8_t tmpB
= z80
->af
.a
;
501 z80
->memptr
.w
= (ddvalue
+1)&0xffffu
;
502 z80
->af
.a
= ddvalue
&0xffu
;
503 ZYM_SBC_A(z80
, value
&0xffu
);
504 uint16_t res
= z80
->af
.a
;
505 z80
->af
.a
= (ddvalue
>>8)&0xffu
;
506 ZYM_SBC_A(z80
, (value
>>8)&0xffu
);
507 res
|= (z80
->af
.a
<<8);
509 z80
->flags_q
= z80
->af
.f
= (res
? z80
->af
.f
&(~ZYM_FLAG_Z
) : z80
->af
.f
|ZYM_FLAG_Z
);
514 ZYMOSIS_INLINE
void ZYM_BIT (zym_cpu_t
*z80
, const uint8_t bit
, const uint8_t num
, const zym_bool mptr
) {
517 (z80
->af
.f
&ZYM_FLAG_C
)|
519 (num
&(1<<bit
) ? 0 : ZYM_FLAG_PV
|ZYM_FLAG_Z
)|
520 (bit
== 7 ? num
&ZYM_FLAG_S
: 0);
521 if (mptr
) z80
->af
.f
= (z80
->af
.f
&~ZYM_FLAG_35
)|(z80
->memptr
.h
&ZYM_FLAG_35
);
522 z80
->flags_q
= z80
->af
.f
;
526 /* we can do this with table lookup, but why bother? */
527 ZYMOSIS_INLINE
void ZYM_DAA (zym_cpu_t
*z80
) {
528 uint8_t tmpI
= 0, tmpC
= (z80
->af
.f
&ZYM_FLAG_C
), tmpA
= z80
->af
.a
;
529 if ((z80
->af
.f
&ZYM_FLAG_H
) || (tmpA
&0x0fu
) > 9) tmpI
= 6;
530 if (tmpC
!= 0 || tmpA
> 0x99u
) tmpI
|= 0x60u
;
531 if (tmpA
> 0x99u
) tmpC
= ZYM_FLAG_C
;
532 if (z80
->af
.f
&ZYM_FLAG_N
) ZYM_SUB_A(z80
, tmpI
); else ZYM_ADD_A(z80
, tmpI
);
533 z80
->flags_q
= z80
->af
.f
= (z80
->af
.f
&~(ZYM_FLAG_C
|ZYM_FLAG_PV
))|tmpC
|parity_tbl
[z80
->af
.a
];
537 ZYMOSIS_INLINE
void ZYM_RRD_A (zym_cpu_t
*z80
) {
538 const uint8_t tmpB
= z80_peekb_3ts(z80
, z80
->hl
.w
);
540 z80
->memptr
.w
= (z80
->hl
.w
+1)&0xffffu
;
541 z80_contention_by1ts(z80
, z80
->hl
.w
, 4);
542 z80_pokeb_3ts(z80
, z80
->hl
.w
, (z80
->af
.a
<<4)|(tmpB
>>4));
543 z80
->af
.a
= (z80
->af
.a
&0xf0u
)|(tmpB
&0x0fu
);
544 z80
->flags_q
= z80
->af
.f
= (z80
->af
.f
&ZYM_FLAG_C
)|sz53p_tbl
[z80
->af
.a
];
547 ZYMOSIS_INLINE
void ZYM_RLD_A (zym_cpu_t
*z80
) {
548 const uint8_t tmpB
= z80_peekb_3ts(z80
, z80
->hl
.w
);
550 z80
->memptr
.w
= (z80
->hl
.w
+1)&0xffffu
;
551 z80_contention_by1ts(z80
, z80
->hl
.w
, 4);
552 z80_pokeb_3ts(z80
, z80
->hl
.w
, (tmpB
<<4)|(z80
->af
.a
&0x0fu
));
553 z80
->af
.a
= (z80
->af
.a
&0xf0u
)|(tmpB
>>4);
554 z80
->flags_q
= z80
->af
.f
= (z80
->af
.f
&ZYM_FLAG_C
)|sz53p_tbl
[z80
->af
.a
];
558 ZYMOSIS_INLINE
void ZYM_LD_A_IR (zym_cpu_t
*z80
, const uint8_t ir
) {
560 z80
->prev_was_EIDDR
= -1;
561 z80_contention_by1ts_ir(z80
, 1);
562 z80
->flags_q
= z80
->af
.f
= sz53_tbl
[z80
->af
.a
]|(z80
->af
.f
&ZYM_FLAG_C
)|(z80
->iff2
? ZYM_FLAG_PV
: 0);
566 /******************************************************************************/
567 #define INC_R (z80->regR = ((z80->regR+1)&0x7fu)|(z80->regR&0x80u))
570 #define SET_TRUE_CC() do { \
571 switch ((opcode>>3)&0x07u) { \
572 case 0: trueCC = (z80->af.f&ZYM_FLAG_Z) == 0; break; \
573 case 1: trueCC = (z80->af.f&ZYM_FLAG_Z) != 0; break; \
574 case 2: trueCC = (z80->af.f&ZYM_FLAG_C) == 0; break; \
575 case 3: trueCC = (z80->af.f&ZYM_FLAG_C) != 0; break; \
576 case 4: trueCC = (z80->af.f&ZYM_FLAG_PV) == 0; break; \
577 case 5: trueCC = (z80->af.f&ZYM_FLAG_PV) != 0; break; \
578 case 6: trueCC = (z80->af.f&ZYM_FLAG_S) == 0; break; \
579 case 7: trueCC = (z80->af.f&ZYM_FLAG_S) != 0; break; \
584 /* branch-less (assuming that `!` is branch-less) code */
585 static const uint8_t ccmask
[4] = {
591 #define SET_TRUE_CC() trueCC = ((!(z80->af.f&ccmask[(opcode>>4)&0x03u]))^((opcode>>3)&0x01u))
594 #define INC_PC (z80->pc = (z80->pc+1u)&0xffffu)
595 #define DEC_PC (z80->pc = ((uint32_t)(z80->pc)-1u)&0xffffu)
597 #define INC_W(n) ((n) = ((n)+1u)&0xffffu)
598 #define DEC_W(n) ((n) = ((uint32_t)(n)-1u)&0xffffu)
600 /*#define XADD_W(n,v) ((n) = ((n)+(v))&0xffffu)*/
601 #define XSUB_W(n,v) ((n) = ((uint32_t)(n)-(uint32_t)(v))&0xffffu)
603 /* casting negative integer to unsigned is UB; sigh */
604 #define ZADD_W(n,v) ((n) = ((v) >= 0 ? ((uint32_t)(n)+(uint32_t)(v)) : ((uint32_t)(n)-(uint32_t)(-v)))&0xffffu)
606 /* casting negative integer to unsigned is UB; sigh */
607 #define ZADD_WX(n,v) (((v) >= 0 ? ((uint32_t)(n)+(uint32_t)(v)) : ((uint32_t)(n)-(uint32_t)(-v)))&0xffffu)
609 #define INC_B(n) ((n) = ((n)+1u)&0xffu)
610 #define DEC_B(n) ((n) = ((uint32_t)(n)-1u)&0xffu)
612 /* read opcode after prefix */
613 ZYMOSIS_INLINE
uint8_t zym_get_opcode_ext (zym_cpu_t
*z80
) {
614 z80_contention(z80
, z80
->pc
, 4, ZYM_MEMIO_OPCEXT
, ZYM_MREQ_READ
);
615 const uint8_t opc
= z80
->mem_read(z80
, z80
->pc
, ZYM_MEMIO_OPCEXT
);
616 z80
->pc
= (z80
->pc
+1)&0xffffu
;
617 z80
->regR
= ((z80
->regR
+1)&0x7fu
)|(z80
->regR
&0x80u
);
622 #define CBX_REPEATED (opcode&0x10u)
623 #define CBX_BACKWARD (opcode&0x08u)
626 int zym_exec_ex (zym_cpu_t
*z80
, int tscount
) {
628 zym_bool gotDD
, trueCC
;
630 int tstart
= z80
->tstates
;
631 uint8_t tmpB
, tmpC
, rsrc
, rdst
;
632 uint16_t tmpW
= 0; /* shut up the compiler; it's wrong but stubborn */
634 while ((z80
->next_event_tstate
< 0 || z80
->tstates
< z80
->next_event_tstate
) &&
635 (tscount
< 0 || z80
->tstates
-tstart
<= tscount
))
637 z80
->prev_pc
= z80
->org_pc
;
638 /* we should perform opcode fetching in loop, in case we need to refetch the opcode, or rollback on breakpoint */
641 if (z80
->bp_hit
) { z80
->bp_was_hit
= 1; z80
->bp_hit
= 0; return z80
->tstates
-tstart
; }
642 z80
->org_pc
= z80
->pc
;
643 const int ots
= z80
->tstates
;
644 /* call pager callback */
645 if (z80
->opc_pager
!= NULL
&& z80
->opc_pager(z80
)) return z80
->tstates
-tstart
;
646 /* read opcode -- OCR(4) */
647 /* t1: setting /MREQ & /RD */
648 /* t2: memory read */
649 /* t3, t4: decode command, increment R */
650 z80_contention(z80
, z80
->pc
, 4, ZYM_MEMIO_OPCODE
, ZYM_MREQ_READ
);
651 z80
->org_pc
= z80
->pc
; /* in case contention messed with it */
652 if (z80
->evenM1
&& (z80
->tstates
&0x01u
)) ++z80
->tstates
; /* emulate "even M1" if necessary */
653 opcode
= z80
->mem_read(z80
, z80
->pc
, ZYM_MEMIO_OPCODE
);
654 z80
->org_pc
= z80
->pc
; /* in case mem_read messed with it */
655 /* do we need to perform a rollback? */
656 if (!z80
->bp_hit
&& !z80
->refetch
) {
657 z80
->org_pc
= z80
->pc
;
658 z80
->pc
= (z80
->pc
+1u)&0xffffu
;
659 z80
->regR
= ((z80
->regR
+1u)&0x7fu
)|(z80
->regR
&0x80u
);
662 /* rollback tstates */
665 /* previous Q for SCF/CCF */
666 const uint8_t lastq
= z80
->flags_q
;
668 z80
->prev_was_EIDDR
= 0;
671 if (z80
->halted
) { DEC_W(z80
->pc
); continue; }
672 /* check for I[XY] prefix */
673 if (opcode
== 0xddu
|| opcode
== 0xfdu
) {
674 /* this is 256-bit bitmap indicates if the corresponding base opcode is using `(HL)` */
675 /* `static` is more restrective here, simple `const` should generate better code */
676 /*static*/ const uint32_t withIndexBmp
[8] = {0x00u
,0x700000u
,0x40404040u
,0x40bf4040u
,0x40404040u
,0x40404040u
,0x0800u
,0x00u
};
678 z80
->dd
= (opcode
== 0xddu
? &z80
->ix
: &z80
->iy
);
679 /* read opcode -- OCR(4) */
680 opcode
= zym_get_opcode_ext(z80
);
681 /* test if this instruction have (HL) */
682 if (withIndexBmp
[opcode
>>5]&(1u<<(opcode
&0x1fu
))) {
683 /* 3rd byte is always DISP here */
684 disp
= z80_peekb_3ts_args(z80
, z80
->pc
); if (disp
> 127) disp
-= 256;
686 z80
->memptr
.w
= ZADD_WX(z80
->dd
->w
, disp
);
687 } else if (opcode
== 0xddu
&& opcode
== 0xfdu
) {
688 /* double prefix; restart main loop */
689 /* double prefix works as NOP, and blocks /INT */
690 z80
->prev_was_EIDDR
= 1;
691 /*FIXME: logically this should reset our Q value, but i am not sure; anyway, this works*/
697 /* ED-prefixed instructions */
698 if (opcode
== 0xedu
) {
699 z80
->dd
= &z80
->hl
; /* ED-prefixed opcodes cannot use IX/IY */
700 /* read opcode -- OCR(4) */
701 opcode
= zym_get_opcode_ext(z80
);
703 /* LDI, LDIR, LDD, LDDR */
704 case 0xa0u
: case 0xb0u
: case 0xa8u
: case 0xb8u
:
705 tmpB
= z80_peekb_3ts(z80
, z80
->hl
.w
);
706 z80_pokeb_3ts(z80
, z80
->de
.w
, tmpB
);
708 z80_contention_by1ts(z80
, z80
->de
.w
, 2);
710 tmpB
= (tmpB
+z80
->af
.a
)&0xffu
;
711 z80
->flags_q
= z80
->af
.f
= /* BOO! FEAR THE MIGHTY BITS! */
712 (tmpB
&ZYM_FLAG_3
)|(z80
->af
.f
&(ZYM_FLAG_C
|ZYM_FLAG_Z
|ZYM_FLAG_S
))|
713 (z80
->bc
.w
!= 0 ? ZYM_FLAG_PV
: 0)|
714 (tmpB
&0x02u
? ZYM_FLAG_5
: 0);
716 if (z80
->bc
.w
!= 0) {
718 z80_contention_by1ts(z80
, z80
->de
.w
, 5);
721 z80
->memptr
.w
= (z80
->pc
+1)&0xffffu
;
724 if (!CBX_BACKWARD
) { INC_W(z80
->hl
.w
); INC_W(z80
->de
.w
); } else { DEC_W(z80
->hl
.w
); DEC_W(z80
->de
.w
); }
726 /* CPI, CPIR, CPD, CPDR */
727 case 0xa1u
: case 0xb1u
: case 0xa9u
: case 0xb9u
:
729 if (CBX_REPEATED
&& (!(z80
->bc
.w
== 1 || z80_peekb_i(z80
, z80
->hl
.w
) == z80
->af
.a
))) {
730 z80
->memptr
.w
= ZADD_WX(z80
->org_pc
, 1);
732 z80
->memptr
.w
= ZADD_WX(z80
->memptr
.w
, (CBX_BACKWARD
? -1 : 1));
734 tmpB
= z80_peekb_3ts(z80
, z80
->hl
.w
);
736 z80_contention_by1ts(z80
, z80
->hl
.w
, 5);
738 z80
->af
.f
= /* BOO! FEAR THE MIGHTY BITS! */
740 (z80
->af
.f
&ZYM_FLAG_C
)|
741 (z80
->bc
.w
!= 0 ? ZYM_FLAG_PV
: 0)|
742 ((int)(z80
->af
.a
&0x0fu
)-(int)(tmpB
&0x0fu
) < 0 ? ZYM_FLAG_H
: 0);
743 tmpB
= ((uint32_t)z80
->af
.a
-(uint32_t)tmpB
)&0xffu
;
744 z80
->af
.f
|= (tmpB
== 0 ? ZYM_FLAG_Z
: 0)|(tmpB
&ZYM_FLAG_S
);
745 if (z80
->af
.f
&ZYM_FLAG_H
) tmpB
= ((uint16_t)tmpB
-1)&0xffu
;
746 z80
->af
.f
|= (tmpB
&ZYM_FLAG_3
)|(tmpB
&0x02u
? ZYM_FLAG_5
: 0);
747 z80
->flags_q
= z80
->af
.f
;
750 if ((z80
->af
.f
&(ZYM_FLAG_Z
|ZYM_FLAG_PV
)) == ZYM_FLAG_PV
) {
752 z80_contention_by1ts(z80
, z80
->hl
.w
, 5);
757 if (CBX_BACKWARD
) DEC_W(z80
->hl
.w
); else INC_W(z80
->hl
.w
);
759 /* OUTI, OTIR, OUTD, OTDR */
760 case 0xa3u
: case 0xb3u
: case 0xabu
: case 0xbbu
:
763 /* INI, INIR, IND, INDR */
764 case 0xa2u
: case 0xb2u
: case 0xaau
: case 0xbau
:
765 z80
->memptr
.w
= ZADD_WX(z80
->bc
.w
, (CBX_BACKWARD
? -1 : 1));
767 z80_contention_by1ts_ir(z80
, 1);
770 tmpB
= z80_peekb_3ts(z80
, z80
->hl
.w
);/*MRD(3)*/
771 z80_port_write(z80
, z80
->bc
.w
, tmpB
);
772 tmpW
= ZADD_WX(z80
->hl
.w
, (CBX_BACKWARD
? -1 : 1));
773 tmpC
= (tmpB
+tmpW
)&0xffu
;
776 tmpB
= z80_port_read(z80
, z80
->bc
.w
);
777 z80_pokeb_3ts(z80
, z80
->hl
.w
, tmpB
);/*MWR(3)*/
779 if (CBX_BACKWARD
) tmpC
= ((uint32_t)tmpB
+(uint32_t)z80
->bc
.c
-1)&0xffu
; else tmpC
= (tmpB
+z80
->bc
.c
+1)&0xffu
;
781 z80
->flags_q
= z80
->af
.f
=
782 (tmpB
&0x80u
? ZYM_FLAG_N
: 0)|
783 (tmpC
< tmpB
? ZYM_FLAG_H
|ZYM_FLAG_C
: 0)|
784 parity_tbl
[(tmpC
&0x07u
)^z80
->bc
.b
]|
787 /* repeating commands */
788 if (z80
->bc
.b
!= 0) {
789 uint16_t a
= (opcode
&0x01u
? z80
->bc
.w
: z80
->hl
.w
);
791 z80_contention_by1ts(z80
, a
, 5);
796 if (CBX_BACKWARD
) DEC_W(z80
->hl
.w
); else INC_W(z80
->hl
.w
);
798 /* not strings, but some good instructions anyway */
800 if ((opcode
&0xc0u
) == 0x40u
) {
802 switch (opcode
&0x07u
) {
805 z80
->memptr
.w
= ZADD_WX(z80
->bc
.w
, 1);
806 tmpB
= z80_port_read(z80
, z80
->bc
.w
);
807 z80
->flags_q
= z80
->af
.f
= sz53p_tbl
[tmpB
]|(z80
->af
.f
&ZYM_FLAG_C
);
808 switch ((opcode
>>3)&0x07u
) {
809 case 0: z80
->bc
.b
= tmpB
; break;
810 case 1: z80
->bc
.c
= tmpB
; break;
811 case 2: z80
->de
.d
= tmpB
; break;
812 case 3: z80
->de
.e
= tmpB
; break;
813 case 4: z80
->hl
.h
= tmpB
; break;
814 case 5: z80
->hl
.l
= tmpB
; break;
815 case 7: z80
->af
.a
= tmpB
; break;
816 /* 6 affects only flags */
821 z80
->memptr
.w
= ZADD_WX(z80
->bc
.w
, 1);
822 switch ((opcode
>>3)&0x07u
) {
823 case 0: tmpB
= z80
->bc
.b
; break;
824 case 1: tmpB
= z80
->bc
.c
; break;
825 case 2: tmpB
= z80
->de
.d
; break;
826 case 3: tmpB
= z80
->de
.e
; break;
827 case 4: tmpB
= z80
->hl
.h
; break;
828 case 5: tmpB
= z80
->hl
.l
; break;
829 case 7: tmpB
= z80
->af
.a
; break;
830 /* 6 usually means (HL), but here it is 0xff for CMOS, and 0 for NMOS */
831 default: tmpB
= (!z80
->cmos
? 0x00u
: 0xffu
); break; /* `!` must tell the predictor our preferred path, NMOS */
833 z80_port_write(z80
, z80
->bc
.w
, tmpB
);
835 /* SBC HL,rr/ADC HL,rr */
838 z80_contention_by1ts_ir(z80
, 7);
839 switch ((opcode
>>4)&0x03u
) {
840 case 0: tmpW
= z80
->bc
.w
; break;
841 case 1: tmpW
= z80
->de
.w
; break;
842 case 2: tmpW
= z80
->hl
.w
; break;
843 default: tmpW
= z80
->sp
.w
; break;
845 z80
->hl
.w
= (opcode
&0x08u
? ZYM_ADC_DD(z80
, tmpW
, z80
->hl
.w
) : ZYM_SBC_DD(z80
, tmpW
, z80
->hl
.w
));
847 /* LD (nn),rr/LD rr,(nn) */
849 tmpW
= z80_getpcw(z80
, 0);
850 z80
->memptr
.w
= (tmpW
+1)&0xffffu
;
853 switch ((opcode
>>4)&0x03u
) {
854 case 0: z80
->bc
.w
= z80_peekw_6ts(z80
, tmpW
); break;
855 case 1: z80
->de
.w
= z80_peekw_6ts(z80
, tmpW
); break;
856 case 2: z80
->hl
.w
= z80_peekw_6ts(z80
, tmpW
); break;
857 case 3: z80
->sp
.w
= z80_peekw_6ts(z80
, tmpW
); break;
861 switch ((opcode
>>4)&0x03u
) {
862 case 0: z80_pokew_6ts(z80
, tmpW
, z80
->bc
.w
); break;
863 case 1: z80_pokew_6ts(z80
, tmpW
, z80
->de
.w
); break;
864 case 2: z80_pokew_6ts(z80
, tmpW
, z80
->hl
.w
); break;
865 case 3: z80_pokew_6ts(z80
, tmpW
, z80
->sp
.w
); break;
873 ZYM_SUB_A(z80
, tmpB
);
877 /*RETI: 0x4d, 0x5d, 0x6d, 0x7d*/
878 /*RETN: 0x45, 0x55, 0x65, 0x75*/
879 z80
->iff1
= z80
->iff2
;
880 z80
->memptr
.w
= z80
->pc
= z80_pop_6ts(z80
);
883 if (z80
->trap_reti
!= NULL
&& z80
->trap_reti(z80
, opcode
)) return z80
->tstates
-tstart
;
886 if (z80
->trap_retn
!= NULL
&& z80
->trap_retn(z80
, opcode
)) return z80
->tstates
-tstart
;
892 case 0x56u
: case 0x76u
: z80
->im
= 1; break;
893 case 0x5eu
: case 0x7eu
: z80
->im
= 2; break;
894 default: z80
->im
= 0; break;
903 z80_contention_by1ts_ir(z80
, 1);
904 z80
->regI
= z80
->af
.a
;
909 z80_contention_by1ts_ir(z80
, 1);
910 z80
->regR
= z80
->af
.a
;
913 case 0x57u
: ZYM_LD_A_IR(z80
, z80
->regI
); break;
915 case 0x5fu
: ZYM_LD_A_IR(z80
, z80
->regR
); break;
917 case 0x67u
: ZYM_RRD_A(z80
); break;
919 case 0x6F: ZYM_RLD_A(z80
); break;
923 /* slt and other traps */
924 if (z80
->trap_ed
!= NULL
&& z80
->trap_ed(z80
, opcode
)) return z80
->tstates
-tstart
;
930 /* CB-prefixed instructions */
931 if (opcode
== 0xcbu
) {
932 /* shifts and bit operations */
933 /* read opcode -- OCR(4) */
935 opcode
= zym_get_opcode_ext(z80
);
937 z80_contention(z80
, z80
->pc
, 3, ZYM_MEMIO_OPCEXT
, ZYM_MREQ_READ
);
938 opcode
= z80
->mem_read(z80
, z80
->pc
, ZYM_MEMIO_OPCEXT
);
939 z80_contention_by1ts_pc(z80
, 2);
943 tmpW
= ZADD_WX(z80
->dd
->w
, disp
);
944 tmpB
= z80_peekb_3ts(z80
, tmpW
);
945 z80_contention_by1ts(z80
, tmpW
, 1);
947 switch (opcode
&0x07u
) {
948 case 0: tmpB
= z80
->bc
.b
; break;
949 case 1: tmpB
= z80
->bc
.c
; break;
950 case 2: tmpB
= z80
->de
.d
; break;
951 case 3: tmpB
= z80
->de
.e
; break;
952 case 4: tmpB
= z80
->hl
.h
; break;
953 case 5: tmpB
= z80
->hl
.l
; break;
954 case 6: tmpB
= z80_peekb_3ts(z80
, z80
->hl
.w
); z80_contention(z80
, z80
->hl
.w
, 1, ZYM_MEMIO_DATA
, ZYM_MREQ_READ
); break;
955 case 7: tmpB
= z80
->af
.a
; break;
958 switch ((opcode
>>3)&0x1fu
) {
959 case 0: tmpB
= ZYM_RLC(z80
, tmpB
); break;
960 case 1: tmpB
= ZYM_RRC(z80
, tmpB
); break;
961 case 2: tmpB
= ZYM_RL(z80
, tmpB
); break;
962 case 3: tmpB
= ZYM_RR(z80
, tmpB
); break;
963 case 4: tmpB
= ZYM_SLA(z80
, tmpB
); break;
964 case 5: tmpB
= ZYM_SRA(z80
, tmpB
); break;
965 case 6: tmpB
= ZYM_SLL(z80
, tmpB
); break;
966 case 7: tmpB
= ZYM_SRL(z80
, tmpB
); break;
968 switch ((opcode
>>6)&0x03u
) {
969 case 1: ZYM_BIT(z80
, (opcode
>>3)&0x07u
, tmpB
, (gotDD
|| (opcode
&0x07u
) == 6)); break;
970 case 2: tmpB
&= ~(1<<((opcode
>>3)&0x07u
)); break; /* RES */
971 case 3: tmpB
|= (1<<((opcode
>>3)&0x07u
)); break; /* SET */
975 if ((opcode
&0xc0u
) != 0x40u
) {
976 /* BITs are not welcome here */
978 /* tmpW was set earlier */
979 if ((opcode
&0x07u
) != 6) z80_pokeb_3ts(z80
, tmpW
, tmpB
);
981 switch (opcode
&0x07u
) {
982 case 0: z80
->bc
.b
= tmpB
; break;
983 case 1: z80
->bc
.c
= tmpB
; break;
984 case 2: z80
->de
.d
= tmpB
; break;
985 case 3: z80
->de
.e
= tmpB
; break;
986 case 4: z80
->hl
.h
= tmpB
; break;
987 case 5: z80
->hl
.l
= tmpB
; break;
988 case 6: z80_pokeb_3ts(z80
, ZADD_WX(z80
->dd
->w
, disp
), tmpB
); break;
989 case 7: z80
->af
.a
= tmpB
; break;
995 switch (opcode
&0xc0u
) {
998 switch (opcode
&0x07u
) {
999 /* misc,DJNZ,JR,JR cc */
1006 switch ((opcode>>3)&0x03u) {
1007 case 0: trueCC = (z80->af.f&ZYM_FLAG_Z) == 0; break;
1008 case 1: trueCC = (z80->af.f&ZYM_FLAG_Z) != 0; break;
1009 case 2: trueCC = (z80->af.f&ZYM_FLAG_C) == 0; break;
1010 case 3: trueCC = (z80->af.f&ZYM_FLAG_C) != 0; break;
1011 default: trueCC = 0; break;
1014 trueCC
= ((!(z80
->af
.f
&ccmask
[(opcode
>>4)&0x01u
]))^((opcode
>>3)&0x01u
));
1017 if ((opcode
&0x08u
) == 0) {
1020 z80_contention_by1ts_ir(z80
, 1);
1022 trueCC
= (z80
->bc
.b
!= 0);
1028 /* `disp` is always read, but FUSE tests require it this way; sigh */
1030 /* execute branch (relative) */
1031 disp
= z80_peekb_3ts_args(z80
, z80
->pc
);
1033 if (disp
> 127) disp
-= 256; /* convert to int8_t */
1034 z80_contention_by1ts_pc(z80
, 5);
1036 ZADD_W(z80
->pc
, disp
);
1037 z80
->memptr
.w
= z80
->pc
;
1039 z80_peekb_3ts_args_noread(z80
, z80
->pc
);
1043 /* EX AF,AF' or NOP */
1044 if (opcode
!= 0) zym_exaf_internal(z80
);
1047 /* LD rr,nn/ADD HL,rr */
1052 z80_contention_by1ts_ir(z80
, 7);
1053 switch ((opcode
>>4)&0x03u
) {
1054 case 0: z80
->dd
->w
= ZYM_ADD_DD(z80
, z80
->bc
.w
, z80
->dd
->w
); break;
1055 case 1: z80
->dd
->w
= ZYM_ADD_DD(z80
, z80
->de
.w
, z80
->dd
->w
); break;
1056 case 2: z80
->dd
->w
= ZYM_ADD_DD(z80
, z80
->dd
->w
, z80
->dd
->w
); break;
1057 case 3: z80
->dd
->w
= ZYM_ADD_DD(z80
, z80
->sp
.w
, z80
->dd
->w
); break;
1061 tmpW
= z80_getpcw(z80
, 0);
1062 switch ((opcode
>>4)&0x03u
) {
1063 case 0: z80
->bc
.w
= tmpW
; break;
1064 case 1: z80
->de
.w
= tmpW
; break;
1065 case 2: z80
->dd
->w
= tmpW
; break;
1066 case 3: z80
->sp
.w
= tmpW
; break;
1072 switch ((opcode
>>3)&0x07u
) {
1074 case 0: z80_pokeb_3ts(z80
, z80
->bc
.w
, z80
->af
.a
); z80
->memptr
.l
= (z80
->bc
.c
+1)&0xffu
; z80
->memptr
.h
= z80
->af
.a
; break;
1076 case 1: z80
->af
.a
= z80_peekb_3ts(z80
, z80
->bc
.w
); z80
->memptr
.w
= (z80
->bc
.w
+1)&0xffffu
; break;
1078 case 2: z80_pokeb_3ts(z80
, z80
->de
.w
, z80
->af
.a
); z80
->memptr
.l
= (z80
->de
.e
+1)&0xffu
; z80
->memptr
.h
= z80
->af
.a
; break;
1080 case 3: z80
->af
.a
= z80_peekb_3ts(z80
, z80
->de
.w
); z80
->memptr
.w
= (z80
->de
.w
+1)&0xffffu
; break;
1083 tmpW
= z80_getpcw(z80
, 0);
1084 z80
->memptr
.w
= (tmpW
+1)&0xffffu
;
1085 z80_pokew_6ts(z80
, tmpW
, z80
->dd
->w
);
1089 tmpW
= z80_getpcw(z80
, 0);
1090 z80
->memptr
.w
= (tmpW
+1)&0xffffu
;
1091 z80
->dd
->w
= z80_peekw_6ts(z80
, tmpW
);
1095 tmpW
= z80_getpcw(z80
, 0);
1096 z80
->memptr
.l
= (tmpW
+1)&0xffu
;
1097 z80
->memptr
.h
= z80
->af
.a
;
1098 z80_pokeb_3ts(z80
, tmpW
, z80
->af
.a
);
1102 tmpW
= z80_getpcw(z80
, 0);
1103 z80
->memptr
.w
= (tmpW
+1)&0xffffu
;
1104 z80
->af
.a
= z80_peekb_3ts(z80
, tmpW
);
1111 z80_contention_by1ts_ir(z80
, 2);
1114 switch ((opcode
>>4)&0x03u
) {
1115 case 0: DEC_W(z80
->bc
.w
); break;
1116 case 1: DEC_W(z80
->de
.w
); break;
1117 case 2: DEC_W(z80
->dd
->w
); break;
1118 case 3: DEC_W(z80
->sp
.w
); break;
1122 switch ((opcode
>>4)&0x03u
) {
1123 case 0: INC_W(z80
->bc
.w
); break;
1124 case 1: INC_W(z80
->de
.w
); break;
1125 case 2: INC_W(z80
->dd
->w
); break;
1126 case 3: INC_W(z80
->sp
.w
); break;
1132 switch ((opcode
>>3)&0x07u
) {
1133 case 0: z80
->bc
.b
= ZYM_INC8(z80
, z80
->bc
.b
); break;
1134 case 1: z80
->bc
.c
= ZYM_INC8(z80
, z80
->bc
.c
); break;
1135 case 2: z80
->de
.d
= ZYM_INC8(z80
, z80
->de
.d
); break;
1136 case 3: z80
->de
.e
= ZYM_INC8(z80
, z80
->de
.e
); break;
1137 case 4: z80
->dd
->h
= ZYM_INC8(z80
, z80
->dd
->h
); break;
1138 case 5: z80
->dd
->l
= ZYM_INC8(z80
, z80
->dd
->l
); break;
1140 if (gotDD
) { DEC_PC
; z80_contention_by1ts_pc(z80
, 5); INC_PC
; }
1141 tmpW
= ZADD_WX(z80
->dd
->w
, disp
);
1142 tmpB
= z80_peekb_3ts(z80
, tmpW
);
1143 z80_contention_by1ts(z80
, tmpW
, 1);
1144 tmpB
= ZYM_INC8(z80
, tmpB
);
1145 z80_pokeb_3ts(z80
, tmpW
, tmpB
);
1147 case 7: z80
->af
.a
= ZYM_INC8(z80
, z80
->af
.a
); break;
1152 switch ((opcode
>>3)&0x07u
) {
1153 case 0: z80
->bc
.b
= ZYM_DEC8(z80
, z80
->bc
.b
); break;
1154 case 1: z80
->bc
.c
= ZYM_DEC8(z80
, z80
->bc
.c
); break;
1155 case 2: z80
->de
.d
= ZYM_DEC8(z80
, z80
->de
.d
); break;
1156 case 3: z80
->de
.e
= ZYM_DEC8(z80
, z80
->de
.e
); break;
1157 case 4: z80
->dd
->h
= ZYM_DEC8(z80
, z80
->dd
->h
); break;
1158 case 5: z80
->dd
->l
= ZYM_DEC8(z80
, z80
->dd
->l
); break;
1160 if (gotDD
) { DEC_PC
; z80_contention_by1ts_pc(z80
, 5); INC_PC
; }
1161 tmpW
= ZADD_WX(z80
->dd
->w
, disp
);
1162 tmpB
= z80_peekb_3ts(z80
, tmpW
);
1163 z80_contention_by1ts(z80
, tmpW
, 1);
1164 tmpB
= ZYM_DEC8(z80
, tmpB
);
1165 z80_pokeb_3ts(z80
, tmpW
, tmpB
);
1167 case 7: z80
->af
.a
= ZYM_DEC8(z80
, z80
->af
.a
); break;
1172 tmpB
= z80_peekb_3ts_args(z80
, z80
->pc
);
1174 switch ((opcode
>>3)&0x07u
) {
1175 case 0: z80
->bc
.b
= tmpB
; break;
1176 case 1: z80
->bc
.c
= tmpB
; break;
1177 case 2: z80
->de
.d
= tmpB
; break;
1178 case 3: z80
->de
.e
= tmpB
; break;
1179 case 4: z80
->dd
->h
= tmpB
; break;
1180 case 5: z80
->dd
->l
= tmpB
; break;
1182 if (gotDD
) { DEC_PC
; z80_contention_by1ts_pc(z80
, 2); INC_PC
; }
1183 tmpW
= ZADD_WX(z80
->dd
->w
, disp
);
1184 z80_pokeb_3ts(z80
, tmpW
, tmpB
);
1186 case 7: z80
->af
.a
= tmpB
; break;
1189 /* swim-swim-hungry */
1191 switch ((opcode
>>3)&0x07u
) {
1192 case 0: ZYM_RLCA(z80
); break;
1193 case 1: ZYM_RRCA(z80
); break;
1194 case 2: ZYM_RLA(z80
); break;
1195 case 3: ZYM_RRA(z80
); break;
1196 case 4: ZYM_DAA(z80
); break;
1199 z80
->flags_q
= z80
->af
.f
= (z80
->af
.a
&ZYM_FLAG_35
)|(ZYM_FLAG_N
|ZYM_FLAG_H
)|(z80
->af
.f
&(ZYM_FLAG_C
|ZYM_FLAG_PV
|ZYM_FLAG_Z
|ZYM_FLAG_S
));
1202 /* `!` must tell the predictor our preferred path, NMOS */
1203 z80
->flags_q
= z80
->af
.f
= (z80
->af
.f
&(ZYM_FLAG_PV
|ZYM_FLAG_Z
|ZYM_FLAG_S
))|((z80
->af
.a
|(!z80
->cmos
? lastq
^z80
->af
.f
: 0))&ZYM_FLAG_35
)|ZYM_FLAG_C
;
1206 /* `!` must tell the predictor our preferred path, NMOS */
1207 z80
->flags_q
= z80
->af
.f
= (z80
->af
.f
&(ZYM_FLAG_PV
|ZYM_FLAG_Z
|ZYM_FLAG_S
))|((z80
->af
.a
|(!z80
->cmos
? lastq
^z80
->af
.f
: 0))&ZYM_FLAG_35
)|(z80
->af
.f
&ZYM_FLAG_C
? ZYM_FLAG_H
: ZYM_FLAG_C
);
1213 /* 0x40..0x7F (LD r8,r8) */
1215 if (opcode
== 0x76u
) { z80
->halted
= 1; DEC_W(z80
->pc
); continue; } /* HALT */
1216 rsrc
= (opcode
&0x07u
);
1217 rdst
= ((opcode
>>3)&0x07u
);
1219 case 0: tmpB
= z80
->bc
.b
; break;
1220 case 1: tmpB
= z80
->bc
.c
; break;
1221 case 2: tmpB
= z80
->de
.d
; break;
1222 case 3: tmpB
= z80
->de
.e
; break;
1223 case 4: tmpB
= (gotDD
&& rdst
== 6 ? z80
->hl
.h
: z80
->dd
->h
); break;
1224 case 5: tmpB
= (gotDD
&& rdst
== 6 ? z80
->hl
.l
: z80
->dd
->l
); break;
1226 if (gotDD
) { DEC_PC
; z80_contention_by1ts_pc(z80
, 5); INC_PC
; }
1227 tmpW
= ZADD_WX(z80
->dd
->w
, disp
);
1228 tmpB
= z80_peekb_3ts(z80
, tmpW
);
1230 case 7: tmpB
= z80
->af
.a
; break;
1233 case 0: z80
->bc
.b
= tmpB
; break;
1234 case 1: z80
->bc
.c
= tmpB
; break;
1235 case 2: z80
->de
.d
= tmpB
; break;
1236 case 3: z80
->de
.e
= tmpB
; break;
1237 case 4: if (gotDD
&& rsrc
== 6) z80
->hl
.h
= tmpB
; else z80
->dd
->h
= tmpB
; break;
1238 case 5: if (gotDD
&& rsrc
== 6) z80
->hl
.l
= tmpB
; else z80
->dd
->l
= tmpB
; break;
1240 if (gotDD
) { DEC_PC
; z80_contention_by1ts_pc(z80
, 5); INC_PC
; }
1241 tmpW
= ZADD_WX(z80
->dd
->w
, disp
);
1242 z80_pokeb_3ts(z80
, tmpW
, tmpB
);
1244 case 7: z80
->af
.a
= tmpB
; break;
1247 /* 0x80..0xBF (ALU A,r8) */
1249 switch (opcode
&0x07u
) {
1250 case 0: tmpB
= z80
->bc
.b
; break;
1251 case 1: tmpB
= z80
->bc
.c
; break;
1252 case 2: tmpB
= z80
->de
.d
; break;
1253 case 3: tmpB
= z80
->de
.e
; break;
1254 case 4: tmpB
= z80
->dd
->h
; break;
1255 case 5: tmpB
= z80
->dd
->l
; break;
1257 if (gotDD
) { DEC_PC
; z80_contention_by1ts_pc(z80
, 5); INC_PC
; }
1258 tmpW
= ZADD_WX(z80
->dd
->w
, disp
);
1259 tmpB
= z80_peekb_3ts(z80
, tmpW
);
1261 case 7: tmpB
= z80
->af
.a
; break;
1263 switch ((opcode
>>3)&0x07u
) {
1264 case 0: ZYM_ADD_A(z80
, tmpB
); break;
1265 case 1: ZYM_ADC_A(z80
, tmpB
); break;
1266 case 2: ZYM_SUB_A(z80
, tmpB
); break;
1267 case 3: ZYM_SBC_A(z80
, tmpB
); break;
1268 case 4: ZYM_AND_A(z80
, tmpB
); break;
1269 case 5: ZYM_XOR_A(z80
, tmpB
); break;
1270 case 6: ZYM_OR_A(z80
, tmpB
); break;
1271 case 7: ZYM_CP_A(z80
, tmpB
); break;
1276 switch (opcode
&0x07u
) {
1279 z80_contention_by1ts_ir(z80
, 1);
1281 if (trueCC
) z80
->memptr
.w
= z80
->pc
= z80_pop_6ts(z80
);
1283 /* POP rr/special0 */
1287 switch ((opcode
>>4)&0x03u
) {
1289 case 0: z80
->memptr
.w
= z80
->pc
= z80_pop_6ts(z80
); break;
1291 case 1: zym_exx_internal(z80
); break;
1293 case 2: z80
->pc
= z80
->dd
->w
; break;
1297 z80_contention_by1ts_ir(z80
, 2);
1298 z80
->sp
.w
= z80
->dd
->w
;
1303 tmpW
= z80_pop_6ts(z80
);
1304 switch ((opcode
>>4)&0x03u
) {
1305 case 0: z80
->bc
.w
= tmpW
; break;
1306 case 1: z80
->de
.w
= tmpW
; break;
1307 case 2: z80
->dd
->w
= tmpW
; break;
1308 case 3: z80
->af
.w
= tmpW
; break;
1315 z80
->memptr
.w
= z80_getpcw(z80
, 0);
1316 if (trueCC
) z80
->pc
= z80
->memptr
.w
;
1318 /* special1/special3 */
1320 switch ((opcode
>>3)&0x07u
) {
1322 case 0: z80
->memptr
.w
= z80
->pc
= z80_getpcw(z80
, 0); break;
1325 tmpW
= z80_peekb_3ts_args(z80
, z80
->pc
);
1327 z80
->memptr
.l
= (tmpW
+1)&0xffu
;
1328 z80
->memptr
.h
= z80
->af
.a
;
1329 tmpW
|= (((uint16_t)(z80
->af
.a
))<<8);
1330 z80_port_write(z80
, tmpW
, z80
->af
.a
);
1334 tmpB
= z80_peekb_3ts_args(z80
, z80
->pc
);
1335 tmpW
= (uint16_t)((((uint16_t)(z80
->af
.a
))<<8)|tmpB
);
1337 z80
->memptr
.w
= (tmpW
+1)&0xffffu
;
1338 z80
->af
.a
= z80_port_read(z80
, tmpW
);
1343 tmpW
= z80_peekw_6ts(z80
, z80
->sp
.w
);
1344 z80_contention_by1ts(z80
, (z80
->sp
.w
+1)&0xffffu
, 1);
1346 z80_pokew_6ts_inverted(z80
, z80
->sp
.w
, z80
->dd
->w
);
1347 z80_contention_by1ts(z80
, z80
->sp
.w
, 2);
1348 z80
->memptr
.w
= z80
->dd
->w
= tmpW
;
1353 z80
->de
.w
= z80
->hl
.w
;
1357 case 6: z80
->iff1
= z80
->iff2
= 0; break;
1359 case 7: z80
->iff1
= z80
->iff2
= 1; z80
->prev_was_EIDDR
= 1; break;
1365 z80
->memptr
.w
= z80_getpcw(z80
, trueCC
);
1367 z80_push_6ts(z80
, z80
->pc
);
1368 z80
->pc
= z80
->memptr
.w
;
1371 /* PUSH rr/special2 */
1374 if (((opcode
>>4)&0x03u
) == 0) {
1376 z80
->memptr
.w
= tmpW
= z80_getpcw(z80
, 1);
1377 z80_push_6ts(z80
, z80
->pc
);
1383 z80_contention_by1ts_ir(z80
, 1);
1384 switch ((opcode
>>4)&0x03u
) {
1385 case 0: tmpW
= z80
->bc
.w
; break;
1386 case 1: tmpW
= z80
->de
.w
; break;
1387 case 2: tmpW
= z80
->dd
->w
; break;
1388 default: tmpW
= z80
->af
.w
; break;
1390 z80_push_6ts(z80
, tmpW
);
1395 tmpB
= z80_peekb_3ts_args(z80
, z80
->pc
);
1397 switch ((opcode
>>3)&0x07u
) {
1398 case 0: ZYM_ADD_A(z80
, tmpB
); break;
1399 case 1: ZYM_ADC_A(z80
, tmpB
); break;
1400 case 2: ZYM_SUB_A(z80
, tmpB
); break;
1401 case 3: ZYM_SBC_A(z80
, tmpB
); break;
1402 case 4: ZYM_AND_A(z80
, tmpB
); break;
1403 case 5: ZYM_XOR_A(z80
, tmpB
); break;
1404 case 6: ZYM_OR_A(z80
, tmpB
); break;
1405 case 7: ZYM_CP_A(z80
, tmpB
); break;
1411 z80_contention_by1ts_ir(z80
, 1);
1412 z80_push_6ts(z80
, z80
->pc
);
1413 z80
->memptr
.w
= z80
->pc
= opcode
&0x38u
;
1419 return z80
->tstates
-tstart
;
1423 int zym_exec_step (zym_cpu_t
*z80
) {
1424 const int32_t one
= z80
->next_event_tstate
;
1425 z80
->next_event_tstate
= -1;
1426 const int res
= zym_exec_ex(z80
, 1);
1427 z80
->next_event_tstate
= one
;
1432 /******************************************************************************/
1433 /* changes z80->tstates if interrupt occurs */
1434 int zym_intr (zym_cpu_t
*z80
) {
1436 const int32_t ots
= z80
->tstates
;
1437 /* emulate NMOS Z80 bug: interruptet LD A,<I|R> copies cleared flag */
1438 /*FIXME: what is the state of `z80->flags_q` here? */
1439 if (z80
->prev_was_EIDDR
< 0) { z80
->prev_was_EIDDR
= 0; if (!z80
->cmos
) z80
->flags_q
= (z80
->af
.f
&= ~ZYM_FLAG_PV
); }
1440 if (z80
->prev_was_EIDDR
|| !z80
->iff1
) return 0; /* not accepted */
1441 z80
->flags_q
= 0; /* we cannot do it earlier, because ignored interrupt won't reset flags */
1442 if (z80
->halted
) { z80
->halted
= 0; INC_PC
; }
1443 z80
->iff1
= z80
->iff2
= 0; /* disable interrupts */
1444 switch ((z80
->im
&= 0x03u
)) {
1445 case 3: /* ??? */ z80
->im
= 0; /* fallthru */
1446 case 0: /* take instruction from the bus (for now we assume that reading from bus always returns 0xff) */
1447 /* with a CALL nnnn on the data bus, it takes 19 cycles: */
1448 /* M1 cycle: 7 T to acknowledge interrupt (where exactly data bus reading occures?) */
1449 /* M2 cycle: 3 T to read low byte of 'nnnn' from data bus */
1450 /* M3 cycle: 3 T to read high byte of 'nnnn' and decrement SP */
1451 /* M4 cycle: 3 T to write high byte of PC to the stack and decrement SP */
1452 /* M5 cycle: 3 T to write low byte of PC and jump to 'nnnn' */
1455 case 1: /* just do RST #38 */
1457 z80
->tstates
+= 7; /* M1 cycle: 7 T to acknowledge interrupt and decrement SP */
1458 /* M2 cycle: 3 T states write high byte of PC to the stack and decrement SP */
1459 /* M3 cycle: 3 T states write the low byte of PC and jump to #0038 */
1460 z80_push_6ts(z80
, z80
->pc
);
1461 z80
->memptr
.w
= z80
->pc
= 0x38u
;
1465 z80
->tstates
+= 7; /* M1 cycle: 7 T to acknowledge interrupt and decrement SP */
1466 /* M2 cycle: 3 T states write high byte of PC to the stack and decrement SP */
1467 /* M3 cycle: 3 T states write the low byte of PC */
1468 z80_push_6ts(z80
, z80
->pc
);
1469 /* M4 cycle: 3 T to read high byte from the interrupt vector */
1470 /* M5 cycle: 3 T to read low byte from bus and jump to interrupt routine */
1471 a
= (((uint16_t)z80
->regI
)<<8)|0xffu
;
1472 z80
->memptr
.w
= z80
->pc
= z80_peekw_6ts(z80
, a
);
1475 return z80
->tstates
-ots
; /* accepted */
1479 /* changes z80->tstates if interrupt occurs */
1480 int zym_nmi (zym_cpu_t
*z80
) {
1481 const int32_t ots
= z80
->tstates
;
1482 /* emulate NMOS Z80 bug: interruptet LD A,<I|R> copies cleared flag */
1483 /*FIXME: what is the state of `z80->flags_q` here? */
1484 if (z80
->prev_was_EIDDR
< 0) { z80
->prev_was_EIDDR
= 0; if (!z80
->cmos
) z80
->flags_q
= (z80
->af
.f
&= ~ZYM_FLAG_PV
); }
1485 if (z80
->prev_was_EIDDR
) return 0;
1486 z80
->flags_q
= 0; /* we cannot do it earlier, because ignored interrupt won't reset flags */
1487 if (z80
->halted
) { z80
->halted
= 0; INC_PC
; }
1489 z80
->iff1
= 0; /* IFF2 is not changed */
1490 z80
->tstates
+= 5; /* M1 cycle: 5 T states to do an opcode read and decrement SP */
1491 /* M2 cycle: 3 T states write high byte of PC to the stack and decrement SP */
1492 /* M3 cycle: 3 T states write the low byte of PC and jump to #0066 */
1493 z80_push_6ts(z80
, z80
->pc
);
1494 z80
->memptr
.w
= z80
->pc
= 0x66u
;
1495 return z80
->tstates
-ots
;
1499 /******************************************************************************/
1500 unsigned zym_pop (zym_cpu_t
*z80
) {
1501 uint16_t res
= z80_peekb_i(z80
, z80
->sp
.w
);
1502 z80
->sp
.w
= (z80
->sp
.w
+1)&0xffffu
;
1503 res
|= ((uint16_t)z80_peekb_i(z80
, z80
->sp
.w
))<<8;
1504 z80
->sp
.w
= (z80
->sp
.w
+1)&0xffffu
;
1505 return (unsigned)res
;
1509 void zym_push (zym_cpu_t
*z80
, const uint16_t value
) {
1510 z80
->sp
.w
= (((uint32_t)z80
->sp
.w
)-1u)&0xffffu
;
1511 z80_pokeb_i(z80
, z80
->sp
.w
, (value
>>8)&0xffu
);
1512 z80
->sp
.w
= (((uint32_t)z80
->sp
.w
)-1u)&0xffffu
;
1513 z80_pokeb_i(z80
, z80
->sp
.w
, value
&0xffu
);
1517 /******************************************************************************
1518 instruction decoding
1519 ====================
1520 00 00y 000 -- special
1521 00 01g 000 -- DJNZ/JR
1522 00 1cc 000 -- JR cc,n
1523 00 rr0 001 -- LD rr,nn
1524 00 rr1 001 -- ADD HL,rr
1525 00 000 010 -- LD (BC),A
1526 00 001 010 -- LD A,(BC)
1527 00 010 010 -- LD (DE),A
1528 00 011 010 -- LD A,(DE)
1529 00 100 010 -- LD (nn),HL
1530 00 101 010 -- LD HL,(nn)
1531 00 110 010 -- LD (nn),A
1532 00 111 010 -- LD A,(nn)
1533 00 rr0 011 -- INC rr
1534 00 rr1 011 -- DEC rr
1535 00 rrr 100 -- INC r8
1536 00 rrr 101 -- DEC r8
1537 00 rrr 110 -- LD r8,n
1538 00 xxx 111 -- special
1575 ---------------------------------
1577 01 rrr rrr - LD r8,r8 (lo: src)
1579 ---------------------------------
1581 10 alu rrr - ALU a,r8
1592 ---------------------------------
1594 11 ccc 000 -- RET cc
1595 11 rr0 001 -- POP rr
1596 11 xx1 001 -- special0
1597 11 ccc 010 -- JP cc,nn
1598 11 yyy 011 -- special1
1599 11 ccc 100 -- CALL cc,nn
1600 11 rr0 101 -- PUSH rr
1601 11 zz1 101 -- special2
1602 11 alu 110 -- alu A,n
1603 11 aaa 111 -- RST nnn
1610 aaa: RST addr=aaa<<3
1650 ---------------------------------
1653 01 rrr 000 -- IN r8,(C)
1654 01 rrr 001 -- OUT (C),r8
1655 01 rr0 010 -- SBC HL,rr
1656 01 rr1 010 -- ADC HL,rr
1657 01 rr0 011 -- LD (nn),rr
1658 01 rr1 011 -- LD rr,(nn)
1679 01 001 110 -- IM 0/1
1686 01 000 111 -- LD I,A
1687 01 001 111 -- LD R,A
1688 01 010 111 -- LD A,I
1689 01 011 111 -- LD A,R
1697 r: repeating instruction? (1: yes)
1698 d: direction (0:inc; 1:dec)
1699 tt: instruction type
1726 ---------------------------------
1738 for bitops, xxx is bit number
1750 for DD/FD prefix, 3rd byte is always disp,
1751 and the result is always written to (I<X|Y>+disp)
1754 command reading cycles
1755 ======================
1756 the following is not 100% correct, but the position
1757 of the contention cycles is right
1759 m1 cycle (accoding to the official Zilog manual)
1760 t1: setting /MREQ & /RD
1762 here comes contetion (AFTER t2!)
1763 t3,t4: decode command, increment R
1765 memory read/write cycles (accoding to the official Zilog manual)
1766 t1,t2: memory address select
1767 here comes contetion (AFTER t2!)
1770 port i/o cycles (accoding to the official Zilog manual)
1771 t1,t2: port address select
1772 tw: automatic wait tick
1773 here comes contetion (AFTER t2!)
1780 bit 1: flagN (see below)
1781 bit 2: parity/overflow
1789 set if the last operation was a subtraction (used by DAA).
1791 P/V - parity or overflow
1792 parity set if even number of bits set
1793 overflow set if the 2-complement result does not fit in the register
1795 *******************************************************************************/