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 #define ZADD_WX(n,v) (uint16_t)(((v) >= 0 ? ((uint32_t)(n)+(uint32_t)(v)) : ((uint32_t)(n)-(uint32_t)(-v))))
50 /******************************************************************************/
51 /* some funny tables */
52 static int32_t tables_inited
= 0;
53 static uint8_t parity_tbl
[256];
54 static uint8_t sz53_tbl
[256]; /* bits 3, 5 and 7 of result, Z flag */
55 static uint8_t sz53p_tbl
[256]; /* bits 3, 5 and 7 of result, Z and P flags */
58 //**************************************************************************
60 // various initialisations
62 //**************************************************************************
64 // initialise internal flag tables
65 // WARNING! this is NOT thread-safe!
66 void zym_init_tables (void) {
67 if (tables_inited
) return;
68 for (unsigned f
= 0; f
< 256; ++f
) {
70 sz53_tbl
[f
] = (f
&ZYM_FLAG_S35
);
71 for (n
= f
, p
= 0; n
!= 0; n
>>= 1) p
^= n
&0x01u
;
72 parity_tbl
[f
] = (p
? 0 : ZYM_FLAG_PV
);
73 sz53p_tbl
[f
] = (sz53_tbl
[f
]|parity_tbl
[f
]);
75 sz53_tbl
[0] |= ZYM_FLAG_Z
;
76 sz53p_tbl
[0] |= ZYM_FLAG_Z
;
82 static __attribute__((constructor
)) void zym_init_tables_ctor (void) {
88 // should be called on new instance of zym_cpu_t to clear all callbacks
89 void zym_clear_callbacks (zym_cpu_t
*z80
) {
90 if (!tables_inited
) zym_init_tables();
92 z80
->mem_write
= NULL
;
93 z80
->mem_contention
= NULL
;
94 z80
->port_read
= NULL
;
95 z80
->port_write
= NULL
;
96 z80
->port_contention
= NULL
;
97 z80
->trap_reti
= NULL
;
98 z80
->trap_retn
= NULL
;
100 z80
->opc_pager
= NULL
;
104 // clear all flags and callbacks; will reset 'z80->user' too
105 void zym_init (zym_cpu_t
*z80
) {
106 if (!tables_inited
) zym_init_tables();
107 memset(z80
, 0, sizeof(*z80
));
108 // there is no guarantee that NULL is 0 in the standard (sigh)
109 zym_clear_callbacks(z80
);
111 z80
->next_event_tstate
= -1;
116 // seems that all regs (and memptr) should be set to 'all 1' here, but i don't care
117 void zym_reset (zym_cpu_t
*z80
) {
118 if (!tables_inited
) zym_init_tables();
119 z80
->bc
.w
= z80
->de
.w
= z80
->hl
.w
= z80
->af
.w
= z80
->sp
.w
= z80
->ix
.w
= z80
->iy
.w
= 0;
120 z80
->bcx
.w
= z80
->dex
.w
= z80
->hlx
.w
= z80
->afx
.w
= 0;
121 z80
->pc
= z80
->prev_pc
= z80
->org_pc
= 0;
123 z80
->regI
= z80
->regR
= 0;
124 z80
->iff1
= z80
->iff2
= 0;
127 z80
->prev_was_EIDDR
= 0;
134 //**************************************************************************
136 // alternate register set functions
138 //**************************************************************************
140 ZYMOSIS_INLINE
void zym_exx_internal (zym_cpu_t
*z80
) {
141 uint16_t t
= z80
->bc
.w
; z80
->bc
.w
= z80
->bcx
.w
; z80
->bcx
.w
= t
;
142 t
= z80
->de
.w
; z80
->de
.w
= z80
->dex
.w
; z80
->dex
.w
= t
;
143 t
= z80
->hl
.w
; z80
->hl
.w
= z80
->hlx
.w
; z80
->hlx
.w
= t
;
147 ZYMOSIS_INLINE
void zym_exaf_internal (zym_cpu_t
*z80
) {
148 const uint16_t t
= z80
->af
.w
; z80
->af
.w
= z80
->afx
.w
; z80
->afx
.w
= t
;
152 // swap normal and alternate register sets (except AF/AF')
153 void zym_exx (zym_cpu_t
*z80
) {
154 zym_exx_internal(z80
);
158 // swap normal and alternate AF
159 void zym_exaf (zym_cpu_t
*z80
) {
160 zym_exaf_internal(z80
);
164 /******************************************************************************/
165 /* simulate contented memory access */
166 /* (tstates = tstates+contention+1)*cnt */
167 /* (zym_cpu_t *z80, uint16_t addr, int tstates, zym_memio_t mio) */
168 #define z80_contention(z80_,addr_,tstates_,mio_,mrq_) do { \
169 if ((z80_)->mem_contention != NULL) (z80_)->mem_contention((z80_), (addr_), (tstates_), (mio_), (mrq_)); else (z80_)->tstates += (tstates_); \
173 #define z80_contention_by1ts(z80_,addr_,cnt_) do { \
174 if ((z80)->mem_contention != NULL) { \
175 for (unsigned fcnt = (cnt_); fcnt--; (z80_)->mem_contention((z80_), (addr_), 1, ZYM_MEMIO_OTHER, ZYM_MREQ_NONE)) {} \
177 (z80_)->tstates += (cnt_); \
182 #define z80_contention_by1ts_ir(z80_,cnt_) z80_contention_by1ts((z80_), (((uint16_t)(z80_)->regI)<<8)|((z80_)->regR), (cnt_))
183 #define z80_contention_by1ts_pc(z80_,cnt_) z80_contention_by1ts((z80_), (z80_)->pc, (cnt_))
186 /******************************************************************************/
187 ZYMOSIS_INLINE
uint8_t z80_port_read (zym_cpu_t
*z80
, const uint16_t port
) {
189 /* i don't really know: FUSE tester seems to do port read in-between contentions,
190 but the actual emulator code does it after all contentions are done.
191 i guess that doing it in-between is the right way.
192 note: ok, it broke floating bus emulation in ZXEmuT. oopsie!
194 if (z80
->port_contention
!= NULL
) {
195 z80
->port_contention(z80
, port
, 1, ZYM_PORTIO_FLAG_IN
|ZYM_PORTIO_FLAG_EARLY
);
196 z80
->port_read_tstates
= z80
->tstates
;
197 #ifdef ZYMOSIS_FUSE_TEST
198 /* for FUSE tests, it should be here */
199 value
= z80
->port_read(z80
, port
, ZYM_PORTIO_NORMAL
);
201 z80
->port_contention(z80
, port
, 2, ZYM_PORTIO_FLAG_IN
);
202 #ifndef ZYMOSIS_FUSE_TEST
203 /* for ZXEmuT floating bus emulation, it should be here */
204 value
= z80
->port_read(z80
, port
, ZYM_PORTIO_NORMAL
);
208 z80
->port_read_tstates
= z80
->tstates
-2;
209 value
= z80
->port_read(z80
, port
, ZYM_PORTIO_NORMAL
);
216 ZYMOSIS_INLINE
void z80_port_write (zym_cpu_t
*z80
, const uint16_t port
, const uint8_t value
) {
217 if (z80
->port_contention
!= NULL
) {
218 z80
->port_contention(z80
, port
, 1, ZYM_PORTIO_FLAG_EARLY
);
219 z80
->port_write(z80
, port
, value
, ZYM_PORTIO_NORMAL
);
220 z80
->port_contention(z80
, port
, 2, 0);
224 z80
->port_write(z80
, port
, value
, ZYM_PORTIO_NORMAL
);
230 /******************************************************************************/
231 #define z80_peekb_i(z80_,addr_) (z80_)->mem_read((z80_), (addr_), ZYM_MEMIO_OTHER)
232 #define z80_peekb(z80_,addr_) (z80_)->mem_read((z80_), (addr_), ZYM_MEMIO_DATA)
234 #define z80_pokeb_i(z80_,addr_,byte_) (z80_)->mem_write((z80_), (addr_), (byte_), ZYM_MEMIO_OTHER)
235 #define z80_pokeb(z80_,addr_,byte_) (z80_)->mem_write((z80_), (addr_), (byte_), ZYM_MEMIO_DATA)
238 /* t1: setting /MREQ & /RD */
239 /* t2: memory read */
240 ZYMOSIS_INLINE
uint8_t z80_peekb_3ts (zym_cpu_t
*z80
, const uint16_t addr
) {
241 z80_contention(z80
, addr
, 3, ZYM_MEMIO_DATA
, ZYM_MREQ_READ
);
242 return z80_peekb(z80
, addr
);
245 ZYMOSIS_INLINE
uint8_t z80_peekb_3ts_args (zym_cpu_t
*z80
, const uint16_t addr
) {
246 z80_contention(z80
, addr
, 3, ZYM_MEMIO_OPCARG
, ZYM_MREQ_READ
);
247 return z80_peekb(z80
, addr
);
250 ZYMOSIS_INLINE
void z80_peekb_3ts_args_noread (zym_cpu_t
*z80
, const uint16_t addr
) {
251 z80_contention(z80
, addr
, 3, ZYM_MEMIO_OPCARG
, ZYM_MREQ_READ
);
254 ZYMOSIS_INLINE
uint16_t z80_peekw_6ts (zym_cpu_t
*z80
, const uint16_t addr
) {
255 const uint16_t res
= z80_peekb_3ts(z80
, addr
);
256 return res
|(((uint16_t)z80_peekb_3ts(z80
, addr
+1u))<<8);
259 /* t1: setting /MREQ & /WR */
260 /* t2: memory write */
261 ZYMOSIS_INLINE
void z80_pokeb_3ts (zym_cpu_t
*z80
, const uint16_t addr
, const uint8_t value
) {
262 z80_contention(z80
, addr
, 3, ZYM_MEMIO_DATA
, ZYM_MREQ_WRITE
);
263 z80_pokeb(z80
, addr
, value
);
266 ZYMOSIS_INLINE
void z80_pokew_6ts (zym_cpu_t
*z80
, const uint16_t addr
, const uint16_t value
) {
267 z80_pokeb_3ts(z80
, addr
, value
&0xffu
);
268 z80_pokeb_3ts(z80
, addr
+1u, (value
>>8)&0xffu
);
271 ZYMOSIS_INLINE
void z80_pokew_6ts_inverted (zym_cpu_t
*z80
, const uint16_t addr
, const uint16_t value
) {
272 z80_pokeb_3ts(z80
, addr
+1u, (value
>>8)&0xffu
);
273 z80_pokeb_3ts(z80
, addr
, value
&0xffu
);
277 ZYMOSIS_INLINE
uint16_t z80_getpcw (zym_cpu_t
*z80
, const zym_bool wait1
) {
278 uint16_t res
= z80_peekb_3ts_args(z80
, z80
->pc
);
280 res
|= ((uint16_t)z80_peekb_3ts_args(z80
, z80
->pc
))<<8;
281 if (wait1
) z80_contention_by1ts_pc(z80
, 1);
287 ZYMOSIS_INLINE
uint16_t z80_pop_6ts (zym_cpu_t
*z80
) {
288 uint16_t res
= z80_peekb_3ts(z80
, z80
->sp
.w
);
290 res
|= ((uint16_t)z80_peekb_3ts(z80
, z80
->sp
.w
))<<8;
295 /* 3 T states write high byte of PC to the stack and decrement SP */
296 /* 3 T states write the low byte of PC and jump to #0066 */
297 ZYMOSIS_INLINE
void z80_push_6ts (zym_cpu_t
*z80
, uint16_t value
) {
299 z80_pokeb_3ts(z80
, z80
->sp
.w
, (value
>>8)&0xffu
);
301 z80_pokeb_3ts(z80
, z80
->sp
.w
, value
&0xffu
);
305 /******************************************************************************/
306 /* you are not expected to understand the following bit-mess */
307 /* the only thing you want to know that IT WORKS; just believe me and the testing suite */
308 /* ok, you can consult Z80 manuals to find the affected flags */
309 /* but believe me, it is unnecessary */
311 ZYMOSIS_INLINE
void ZYM_ADC_A (zym_cpu_t
*z80
, const uint8_t b
) {
312 const uint16_t o
= z80
->af
.a
;
314 z80
->af
.a
= (newv
= o
+b
+(z80
->af
.f
&ZYM_FLAG_C
))&0xffu
; /* ZYM_FLAG_C is 0x01u, so it's safe */
315 z80
->flags_q
= z80
->af
.f
=
316 sz53_tbl
[newv
&0xffu
]|
317 (newv
> 0xffu
? ZYM_FLAG_C
: 0)|
318 ((o
^(~b
))&(o
^newv
)&0x80u
? ZYM_FLAG_PV
: 0)|
319 ((o
&0x0fu
)+(b
&0x0fu
)+(z80
->af
.f
&ZYM_FLAG_C
) >= 0x10u
? ZYM_FLAG_H
: 0);
322 ZYMOSIS_INLINE
void ZYM_SBC_A (zym_cpu_t
*z80
, const uint8_t b
) {
323 const uint16_t o
= z80
->af
.a
;
325 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 */
326 z80
->flags_q
= z80
->af
.f
=
328 sz53_tbl
[newv
&0xffu
]|
329 (newv
> 0xffu
? ZYM_FLAG_C
: 0)|
330 ((o
^b
)&(o
^newv
)&0x80u
? ZYM_FLAG_PV
: 0)|
331 ((int32_t)(o
&0x0fu
)-(int32_t)(b
&0x0fu
)-(int32_t)(z80
->af
.f
&ZYM_FLAG_C
) < 0 ? ZYM_FLAG_H
: 0);
334 ZYMOSIS_INLINE
void ZYM_ADD_A (zym_cpu_t
*z80
, const uint8_t b
) {
335 z80
->af
.f
&= ~ZYM_FLAG_C
;
339 ZYMOSIS_INLINE
void ZYM_SUB_A (zym_cpu_t
*z80
, const uint8_t b
) {
340 z80
->af
.f
&= ~ZYM_FLAG_C
;
344 ZYMOSIS_INLINE
void ZYM_CP_A (zym_cpu_t
*z80
, const uint8_t b
) {
345 const uint8_t o
= z80
->af
.a
;
346 const uint8_t newv
= ((uint32_t)o
-(uint32_t)b
)&0xffu
;
347 z80
->flags_q
= z80
->af
.f
=
351 (newv
== 0 ? ZYM_FLAG_Z
: 0)|
352 (o
< b
? ZYM_FLAG_C
: 0)|
353 ((o
^b
)&(o
^newv
)&0x80u
? ZYM_FLAG_PV
: 0)|
354 ((int32_t)(o
&0x0fu
)-(int32_t)(b
&0x0fu
) < 0 ? ZYM_FLAG_H
: 0);
358 #define ZYM_AND_A(z80_,b_) ((z80_)->flags_q = (z80_)->af.f = sz53p_tbl[(z80_)->af.a&=(b_)]|ZYM_FLAG_H)
359 #define ZYM_OR_A(z80_,b_) ((z80_)->flags_q = (z80_)->af.f = sz53p_tbl[(z80_)->af.a|=(b_)])
360 #define ZYM_XOR_A(z80_,b_) ((z80_)->flags_q = (z80_)->af.f = sz53p_tbl[(z80_)->af.a^=(b_)])
363 /* carry unchanged */
364 ZYMOSIS_INLINE
uint8_t ZYM_DEC8 (zym_cpu_t
*z80
, const uint8_t b
) {
365 z80
->af
.f
&= ZYM_FLAG_C
;
366 z80
->af
.f
|= ZYM_FLAG_N
|
367 (b
== 0x80u
? ZYM_FLAG_PV
: 0)|
368 (b
&0x0fu
? 0 : ZYM_FLAG_H
)|
369 sz53_tbl
[(((uint32_t)b
)-1u)&0xffu
];
370 z80
->flags_q
= z80
->af
.f
;
371 return (((uint32_t)b
)-1u)&0xffu
;
374 /* carry unchanged */
375 ZYMOSIS_INLINE
uint8_t ZYM_INC8 (zym_cpu_t
*z80
, const uint8_t b
) {
376 z80
->af
.f
&= ZYM_FLAG_C
;
378 (b
== 0x7fu
? ZYM_FLAG_PV
: 0)|
379 ((b
+1u)&0x0fu
? 0 : ZYM_FLAG_H
)|
380 sz53_tbl
[(b
+1u)&0xffu
];
381 z80
->flags_q
= z80
->af
.f
;
382 return ((b
+1u)&0xffu
);
385 /* cyclic, carry reflects shifted bit */
386 ZYMOSIS_INLINE
void ZYM_RLCA (zym_cpu_t
*z80
) {
387 const uint8_t c
= ((z80
->af
.a
>>7)&0x01u
);
388 z80
->af
.a
= (z80
->af
.a
<<1)|c
;
389 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
));
392 /* cyclic, carry reflects shifted bit */
393 ZYMOSIS_INLINE
void ZYM_RRCA (zym_cpu_t
*z80
) {
394 const uint8_t c
= (z80
->af
.a
&0x01u
);
395 z80
->af
.a
= (z80
->af
.a
>>1)|(c
<<7);
396 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
));
399 /* cyclic thru carry */
400 ZYMOSIS_INLINE
void ZYM_RLA (zym_cpu_t
*z80
) {
401 const uint8_t c
= ((z80
->af
.a
>>7)&0x01u
);
402 z80
->af
.a
= (z80
->af
.a
<<1)|(z80
->af
.f
&ZYM_FLAG_C
);
403 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
));
406 /* cyclic thru carry */
407 ZYMOSIS_INLINE
void ZYM_RRA (zym_cpu_t
*z80
) {
408 const uint8_t c
= (z80
->af
.a
&0x01u
);
409 z80
->af
.a
= (z80
->af
.a
>>1)|((z80
->af
.f
&ZYM_FLAG_C
)<<7);
410 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
));
413 /* cyclic thru carry */
414 ZYMOSIS_INLINE
uint8_t ZYM_RL (zym_cpu_t
*z80
, uint8_t b
) {
415 const uint8_t c
= (b
>>7)&ZYM_FLAG_C
;
416 z80
->flags_q
= z80
->af
.f
= sz53p_tbl
[(b
= ((b
<<1)&0xffu
)|(z80
->af
.f
&ZYM_FLAG_C
))]|c
;
420 ZYMOSIS_INLINE
uint8_t ZYM_RR (zym_cpu_t
*z80
, uint8_t b
) {
421 const uint8_t c
= (b
&0x01u
);
422 z80
->flags_q
= z80
->af
.f
= sz53p_tbl
[(b
= (b
>>1)|((z80
->af
.f
&ZYM_FLAG_C
)<<7))]|c
;
426 /* cyclic, carry reflects shifted bit */
427 ZYMOSIS_INLINE
uint8_t ZYM_RLC (zym_cpu_t
*z80
, uint8_t b
) {
428 const uint8_t c
= ((b
>>7)&ZYM_FLAG_C
);
429 z80
->flags_q
= z80
->af
.f
= sz53p_tbl
[(b
= ((b
<<1)&0xffu
)|c
)]|c
;
433 /* cyclic, carry reflects shifted bit */
434 ZYMOSIS_INLINE
uint8_t ZYM_RRC (zym_cpu_t
*z80
, uint8_t b
) {
435 const uint8_t c
= (b
&0x01u
);
436 z80
->flags_q
= z80
->af
.f
= sz53p_tbl
[(b
= (b
>>1)|(c
<<7))]|c
;
440 /* shift left arithmetic, sets bit 0 to zero, carry reflects shifted bit */
441 ZYMOSIS_INLINE
uint8_t ZYM_SLA (zym_cpu_t
*z80
, uint8_t b
) {
442 uint8_t c
= ((b
>>7)&0x01u
);
443 z80
->flags_q
= z80
->af
.f
= sz53p_tbl
[(b
<<= 1)]|c
;
447 /* shift right arithmetic, sets bit 6 to bit 7, carry reflects shifted bit */
448 ZYMOSIS_INLINE
uint8_t ZYM_SRA (zym_cpu_t
*z80
, uint8_t b
) {
449 const uint8_t c
= (b
&0x01u
);
450 z80
->flags_q
= z80
->af
.f
= sz53p_tbl
[(b
= (b
>>1)|(b
&0x80u
))]|c
;
454 /* shift left logic, sets bit 0 to one, carry reflects shifted bit */
455 ZYMOSIS_INLINE
uint8_t ZYM_SLL (zym_cpu_t
*z80
, uint8_t b
) {
456 const uint8_t c
= ((b
>>7)&0x01u
);
457 z80
->flags_q
= z80
->af
.f
= sz53p_tbl
[(b
= (b
<<1)|0x01u
)]|c
;
461 /* shift right logic, sets bit 7 to zero, carry reflects shifted bit */
462 ZYMOSIS_INLINE
uint8_t ZYM_SRL (zym_cpu_t
*z80
, uint8_t b
) {
463 const uint8_t c
= (b
&0x01u
);
464 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;
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
= (uint16_t)newv
;
488 z80
->memptr
.w
= ddvalue
+1u;
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 //FIXME: MEMPTR docs says that it is still +1 here; why?
502 //FIXME: is this a typo, or is it really working like this?
503 z80
->memptr
.w
= ddvalue
+1u;
504 z80
->af
.a
= ddvalue
&0xffu
;
505 ZYM_SBC_A(z80
, value
&0xffu
);
506 uint16_t res
= z80
->af
.a
;
507 z80
->af
.a
= (ddvalue
>>8)&0xffu
;
508 ZYM_SBC_A(z80
, (value
>>8)&0xffu
);
509 res
|= (z80
->af
.a
<<8);
511 z80
->flags_q
= z80
->af
.f
= (res
? z80
->af
.f
&(~ZYM_FLAG_Z
) : z80
->af
.f
|ZYM_FLAG_Z
);
515 ZYMOSIS_INLINE
void ZYM_BIT (zym_cpu_t
*z80
, const uint8_t bit
, const uint8_t num
, const zym_bool mptr
) {
518 (z80
->af
.f
&ZYM_FLAG_C
)|
520 (num
&(1<<bit
) ? 0 : ZYM_FLAG_PV
|ZYM_FLAG_Z
)|
521 (bit
== 7 ? num
&ZYM_FLAG_S
: 0);
522 if (mptr
) z80
->af
.f
= (z80
->af
.f
&~ZYM_FLAG_35
)|(z80
->memptr
.h
&ZYM_FLAG_35
);
523 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
];
536 ZYMOSIS_INLINE
void ZYM_RRD_A (zym_cpu_t
*z80
) {
537 const uint8_t tmpB
= z80_peekb_3ts(z80
, z80
->hl
.w
);
539 z80
->memptr
.w
= z80
->hl
.w
+1u;
540 z80_contention_by1ts(z80
, z80
->hl
.w
, 4);
541 z80_pokeb_3ts(z80
, z80
->hl
.w
, (z80
->af
.a
<<4)|(tmpB
>>4));
542 z80
->af
.a
= (z80
->af
.a
&0xf0u
)|(tmpB
&0x0fu
);
543 z80
->flags_q
= z80
->af
.f
= (z80
->af
.f
&ZYM_FLAG_C
)|sz53p_tbl
[z80
->af
.a
];
546 ZYMOSIS_INLINE
void ZYM_RLD_A (zym_cpu_t
*z80
) {
547 const uint8_t tmpB
= z80_peekb_3ts(z80
, z80
->hl
.w
);
549 z80
->memptr
.w
= z80
->hl
.w
+1u;
550 z80_contention_by1ts(z80
, z80
->hl
.w
, 4);
551 z80_pokeb_3ts(z80
, z80
->hl
.w
, (tmpB
<<4)|(z80
->af
.a
&0x0fu
));
552 z80
->af
.a
= (z80
->af
.a
&0xf0u
)|(tmpB
>>4);
553 z80
->flags_q
= z80
->af
.f
= (z80
->af
.f
&ZYM_FLAG_C
)|sz53p_tbl
[z80
->af
.a
];
556 ZYMOSIS_INLINE
void ZYM_LD_A_IR (zym_cpu_t
*z80
, const uint8_t ir
) {
558 z80
->prev_was_EIDDR
= -1;
559 z80_contention_by1ts_ir(z80
, 1);
560 z80
->flags_q
= z80
->af
.f
= sz53_tbl
[z80
->af
.a
]|(z80
->af
.f
&ZYM_FLAG_C
)|(z80
->iff2
? ZYM_FLAG_PV
: 0);
564 /******************************************************************************/
565 #define INC_R (z80->regR = ((z80->regR+1u)&0x7fu)|(z80->regR&0x80u))
566 #define DEC_R (z80->regR = ((z80->regR-1u)&0x7fu)|(z80->regR&0x80u))
569 #define SET_TRUE_CC() do { \
570 switch ((opcode>>3)&0x07u) { \
571 case 0: trueCC = (z80->af.f&ZYM_FLAG_Z) == 0; break; \
572 case 1: trueCC = (z80->af.f&ZYM_FLAG_Z) != 0; break; \
573 case 2: trueCC = (z80->af.f&ZYM_FLAG_C) == 0; break; \
574 case 3: trueCC = (z80->af.f&ZYM_FLAG_C) != 0; break; \
575 case 4: trueCC = (z80->af.f&ZYM_FLAG_PV) == 0; break; \
576 case 5: trueCC = (z80->af.f&ZYM_FLAG_PV) != 0; break; \
577 case 6: trueCC = (z80->af.f&ZYM_FLAG_S) == 0; break; \
578 case 7: trueCC = (z80->af.f&ZYM_FLAG_S) != 0; break; \
583 /* branch-less (assuming that `!` is branch-less) code */
584 static const uint8_t ccmask
[4] = {
590 #define SET_TRUE_CC() trueCC = ((!(z80->af.f&ccmask[(opcode>>4)&0x03u]))^((opcode>>3)&0x01u))
593 /* read opcode after prefix */
594 /*FIXME: this should call a pager too, but meh...*/
595 ZYMOSIS_INLINE
uint8_t zym_get_opcode_ext (zym_cpu_t
*z80
) {
596 z80_contention(z80
, z80
->pc
, 4, ZYM_MEMIO_OPCEXT
, ZYM_MREQ_READ
);
597 const uint8_t opc
= z80
->mem_read(z80
, z80
->pc
, ZYM_MEMIO_OPCEXT
);
598 if (z80
->evenM1
&& (z80
->tstates
&0x01)) ++z80
->tstates
; /* emulate "even M1" if necessary */
605 #define CBX_REPEATED (opcode&0x10u)
606 #define CBX_BACKWARD (opcode&0x08u)
609 int32_t zym_exec_ex (zym_cpu_t
*z80
, int32_t tscount
) {
611 zym_bool gotDD
, trueCC
;
613 int32_t tsts
; // trap tstates
614 int32_t tstart
= z80
->tstates
;
615 uint8_t tmpB
, tmpC
, rsrc
, rdst
;
616 uint16_t tmpW
= 0; /* shut up the compiler; it's wrong but stubborn */
618 while ((z80
->next_event_tstate
< 0 || z80
->tstates
< z80
->next_event_tstate
) &&
619 (tscount
< 0 || z80
->tstates
-tstart
<= tscount
))
621 /* note that real Z80 process prefixes by setting internal flags, blocking /INT
622 for the next opc read, and reading the next opcode.
623 we cannot do that, because for us prefixed instructions are not "flagged".
624 this doesn't matter in practice for anything except double IX/IY prefixes.
625 currently, we're doing a weird hack for such prefixes (rolling back).
626 double prefixes aren't used in any real code, tho, so this doesn't matter much.
628 z80
->prev_pc
= z80
->org_pc
;
629 tsts
= z80
->tstates
; /* rememeber to compensate trap cost */
630 /* we should perform opcode fetching in loop, in case we need to
631 refetch the opcode, or rollback on breakpoint
635 if (z80
->bp_hit
) { z80
->bp_was_hit
= 1; z80
->bp_hit
= 0; return z80
->tstates
-tstart
; }
636 z80
->org_pc
= z80
->pc
; /* for callbacks */
637 const int32_t ots
= z80
->tstates
;
638 /* call pager callback */
639 if (z80
->opc_pager
!= NULL
) {
640 if (z80
->opc_pager(z80
)) return z80
->tstates
-tstart
;
642 /* read opcode -- OCR(4) */
643 /* t1: setting /MREQ & /RD */
644 /* t2: memory read */
645 /* t3, t4: decode command, increment R */
646 z80_contention(z80
, z80
->pc
, 4, ZYM_MEMIO_OPCODE
, ZYM_MREQ_READ
);
647 /* emulate "even M1" if necessary */
648 if (z80
->evenM1
&& (z80
->tstates
&0x01)) ++z80
->tstates
;
650 opcode
= z80
->mem_read(z80
, z80
->pc
, ZYM_MEMIO_OPCODE
);
651 /* do we need to perform a rollback? */
652 if (!(z80
->bp_hit
|z80
->refetch
)) {
653 z80
->org_pc
= z80
->pc
++; /* for more callbacks ;-) */
657 /* rollback tstates */
660 /* previous Q for SCF/CCF */
661 const uint8_t lastq
= z80
->flags_q
;
663 z80
->prev_was_EIDDR
= 0;
666 /* "HALT" simply executes "NOP" until interrupted */
667 /* check: i'm not sure if it really performs opcode reading */
668 if (z80
->halted
) { --z80
->pc
; continue; }
669 /* check for I[XY] prefix */
670 if (opcode
== 0xddu
|| opcode
== 0xfdu
) {
671 /* this is 256-bit bitmap indicates if the corresponding base opcode is using `(HL)` */
672 /* `static` is more restrictive here, simple `const` should generate better code */
673 /*static*/ const uint32_t withIndexBmp
[8] = {
674 0x00u
,0x700000u
,0x40404040u
,0x40bf4040u
,0x40404040u
,0x40404040u
,0x0800u
,0x00u
677 z80
->dd
= (opcode
== 0xddu
? &z80
->ix
: &z80
->iy
);
678 /* we may need to rollback on double prefix */
679 const int32_t ots
= z80
->tstates
;
680 /* read opcode -- OCR(4) */
681 opcode
= zym_get_opcode_ext(z80
);
682 /* test if this instruction have (HL) */
683 if (withIndexBmp
[opcode
>>5]&(1u<<(opcode
&0x1fu
))) {
684 /* 3rd byte is always DISP here */
685 disp
= z80_peekb_3ts_args(z80
, z80
->pc
); if (disp
> 127) disp
-= 256;
687 z80
->memptr
.w
= ZADD_WX(z80
->dd
->w
, disp
);
688 } else if (opcode
== 0xddu
|| opcode
== 0xfdu
) {
689 /* rollback; this is not how real Z80 works, but meh... */
690 /* read second prefix again */
692 /* rollback tstates */
694 /* rollback R register */
696 /* double prefix works as NOP, and blocks /INT */
697 z80
->prev_was_EIDDR
= 1;
698 /*FIXME: logically this should reset our Q value, but i am not sure; anyway, this works*/
700 /* restart main loop */
705 /* ED-prefixed instructions */
706 if (opcode
== 0xedu
) {
707 z80
->dd
= &z80
->hl
; /* ED-prefixed opcodes cannot use IX/IY */
708 /* read opcode -- OCR(4) */
709 opcode
= zym_get_opcode_ext(z80
);
711 /* LDI, LDIR, LDD, LDDR */
712 case 0xa0u
: case 0xb0u
: case 0xa8u
: case 0xb8u
:
713 tmpB
= z80_peekb_3ts(z80
, z80
->hl
.w
);
714 z80_pokeb_3ts(z80
, z80
->de
.w
, tmpB
);
716 z80_contention_by1ts(z80
, z80
->de
.w
, 2);
718 tmpB
= (tmpB
+z80
->af
.a
)&0xffu
;
719 z80
->flags_q
= z80
->af
.f
= /* BOO! FEAR THE MIGHTY BITS! */
720 (tmpB
&ZYM_FLAG_3
)|(z80
->af
.f
&(ZYM_FLAG_C
|ZYM_FLAG_Z
|ZYM_FLAG_S
))|
721 (z80
->bc
.w
!= 0 ? ZYM_FLAG_PV
: 0)|
722 (tmpB
&0x02u
? ZYM_FLAG_5
: 0);
724 if (z80
->bc
.w
!= 0) {
726 z80_contention_by1ts(z80
, z80
->de
.w
, 5);
729 z80
->memptr
.w
= z80
->pc
+1u;
732 if (!CBX_BACKWARD
) { ++z80
->hl
.w
; ++z80
->de
.w
; } else { --z80
->hl
.w
; --z80
->de
.w
; }
734 /* CPI, CPIR, CPD, CPDR */
735 case 0xa1u
: case 0xb1u
: case 0xa9u
: case 0xb9u
:
736 tmpB
= z80_peekb_3ts(z80
, z80
->hl
.w
);
738 z80_contention_by1ts(z80
, z80
->hl
.w
, 5);
740 z80
->af
.f
= /* BOO! FEAR THE MIGHTY BITS! */
742 (z80
->af
.f
&ZYM_FLAG_C
)|
743 (z80
->bc
.w
!= 0 ? ZYM_FLAG_PV
: 0)|
744 ((int32_t)(z80
->af
.a
&0x0fu
)-(int32_t)(tmpB
&0x0fu
) < 0 ? ZYM_FLAG_H
: 0);
745 tmpB
= ((uint32_t)z80
->af
.a
-(uint32_t)tmpB
)&0xffu
;
746 z80
->af
.f
|= (tmpB
== 0 ? ZYM_FLAG_Z
: 0)|(tmpB
&ZYM_FLAG_S
);
747 if (z80
->af
.f
&ZYM_FLAG_H
) tmpB
= ((uint16_t)tmpB
-1u)&0xffu
;
748 z80
->af
.f
|= (tmpB
&ZYM_FLAG_3
)|(tmpB
&0x02u
? ZYM_FLAG_5
: 0);
749 z80
->flags_q
= z80
->af
.f
;
752 if ((z80
->af
.f
&(ZYM_FLAG_Z
|ZYM_FLAG_PV
)) == ZYM_FLAG_PV
) {
754 z80_contention_by1ts(z80
, z80
->hl
.w
, 5);
757 z80
->memptr
.w
= z80
->pc
+1u;
762 --z80
->memptr
.w
; /* new MEMPTR code */
765 ++z80
->memptr
.w
; /* new MEMPTR code */
768 /* OUTI, OTIR, OUTD, OTDR */
769 case 0xa3u
: case 0xb3u
: case 0xabu
: case 0xbbu
:
772 /* INI, INIR, IND, INDR */
773 case 0xa2u
: case 0xb2u
: case 0xaau
: case 0xbau
:
774 z80
->memptr
.w
= z80
->bc
.w
;
775 if (CBX_BACKWARD
) --z80
->memptr
.w
; else ++z80
->memptr
.w
;
777 z80_contention_by1ts_ir(z80
, 1);
780 tmpB
= z80_peekb_3ts(z80
, z80
->hl
.w
);/*MRD(3)*/
781 z80_port_write(z80
, z80
->bc
.w
, tmpB
);
783 if (CBX_BACKWARD
) --tmpW
; else ++tmpW
;
784 tmpC
= (tmpB
+tmpW
)&0xffu
;
787 tmpB
= z80_port_read(z80
, z80
->bc
.w
);
788 z80_pokeb_3ts(z80
, z80
->hl
.w
, tmpB
);/*MWR(3)*/
790 tmpC
= (CBX_BACKWARD
? ((uint32_t)tmpB
+(uint32_t)z80
->bc
.c
-1u) : (tmpB
+z80
->bc
.c
+1u))&0xffu
;
792 z80
->flags_q
= z80
->af
.f
=
793 (tmpB
&0x80u
? ZYM_FLAG_N
: 0)|
794 (tmpC
< tmpB
? ZYM_FLAG_H
|ZYM_FLAG_C
: 0)|
795 parity_tbl
[(tmpC
&0x07u
)^z80
->bc
.b
]|
798 /* repeating commands */
799 if (z80
->bc
.b
!= 0) {
800 uint16_t a
= (opcode
&0x01u
? z80
->bc
.w
: z80
->hl
.w
);
802 z80_contention_by1ts(z80
, a
, 5);
807 if (CBX_BACKWARD
) --z80
->hl
.w
; else ++z80
->hl
.w
;
809 /* not strings, but some good instructions anyway */
811 if ((opcode
&0xc0u
) == 0x40u
) {
813 switch (opcode
&0x07u
) {
816 z80
->memptr
.w
= z80
->bc
.w
+1u;
817 tmpB
= z80_port_read(z80
, z80
->bc
.w
);
818 z80
->flags_q
= z80
->af
.f
= sz53p_tbl
[tmpB
]|(z80
->af
.f
&ZYM_FLAG_C
);
819 switch ((opcode
>>3)&0x07u
) {
820 case 0: z80
->bc
.b
= tmpB
; break;
821 case 1: z80
->bc
.c
= tmpB
; break;
822 case 2: z80
->de
.d
= tmpB
; break;
823 case 3: z80
->de
.e
= tmpB
; break;
824 case 4: z80
->hl
.h
= tmpB
; break;
825 case 5: z80
->hl
.l
= tmpB
; break;
826 case 7: z80
->af
.a
= tmpB
; break;
827 /* 6 affects only flags */
832 z80
->memptr
.w
= z80
->bc
.w
+1u;
833 switch ((opcode
>>3)&0x07u
) {
834 case 0: tmpB
= z80
->bc
.b
; break;
835 case 1: tmpB
= z80
->bc
.c
; break;
836 case 2: tmpB
= z80
->de
.d
; break;
837 case 3: tmpB
= z80
->de
.e
; break;
838 case 4: tmpB
= z80
->hl
.h
; break;
839 case 5: tmpB
= z80
->hl
.l
; break;
840 case 7: tmpB
= z80
->af
.a
; break;
841 /* 6 usually means (HL), but here it is 0xff for CMOS, and 0 for NMOS */
842 default: tmpB
= (!z80
->cmos
? 0x00u
: 0xffu
); break; /* `!` must tell the predictor our preferred path, NMOS */
844 z80_port_write(z80
, z80
->bc
.w
, tmpB
);
846 /* SBC HL,rr/ADC HL,rr */
849 z80_contention_by1ts_ir(z80
, 7);
850 switch ((opcode
>>4)&0x03u
) {
851 case 0: tmpW
= z80
->bc
.w
; break;
852 case 1: tmpW
= z80
->de
.w
; break;
853 case 2: tmpW
= z80
->hl
.w
; break;
854 default: tmpW
= z80
->sp
.w
; break;
856 z80
->hl
.w
= (opcode
&0x08u
? ZYM_ADC_DD(z80
, tmpW
, z80
->hl
.w
) : ZYM_SBC_DD(z80
, tmpW
, z80
->hl
.w
));
858 /* LD (nn),rr/LD rr,(nn) */
860 tmpW
= z80_getpcw(z80
, 0);
861 z80
->memptr
.w
= tmpW
+1u;
864 switch ((opcode
>>4)&0x03u
) {
865 case 0: z80
->bc
.w
= z80_peekw_6ts(z80
, tmpW
); break;
866 case 1: z80
->de
.w
= z80_peekw_6ts(z80
, tmpW
); break;
867 case 2: z80
->hl
.w
= z80_peekw_6ts(z80
, tmpW
); break;
868 case 3: z80
->sp
.w
= z80_peekw_6ts(z80
, tmpW
); break;
872 switch ((opcode
>>4)&0x03u
) {
873 case 0: z80_pokew_6ts(z80
, tmpW
, z80
->bc
.w
); break;
874 case 1: z80_pokew_6ts(z80
, tmpW
, z80
->de
.w
); break;
875 case 2: z80_pokew_6ts(z80
, tmpW
, z80
->hl
.w
); break;
876 case 3: z80_pokew_6ts(z80
, tmpW
, z80
->sp
.w
); break;
884 ZYM_SUB_A(z80
, tmpB
);
888 /*RETI: 0x4d, 0x5d, 0x6d, 0x7d*/
889 /*RETN: 0x45, 0x55, 0x65, 0x75*/
890 z80
->iff1
= z80
->iff2
;
891 z80
->memptr
.w
= z80
->pc
= z80_pop_6ts(z80
);
894 if (z80
->trap_reti
!= NULL
&& z80
->trap_reti(z80
, opcode
)) return z80
->tstates
-tstart
;
897 if (z80
->trap_retn
!= NULL
&& z80
->trap_retn(z80
, opcode
)) return z80
->tstates
-tstart
;
903 case 0x56u
: case 0x76u
: z80
->im
= 1; break;
904 case 0x5eu
: case 0x7eu
: z80
->im
= 2; break;
905 default: z80
->im
= 0; break;
914 z80_contention_by1ts_ir(z80
, 1);
915 z80
->regI
= z80
->af
.a
;
920 z80_contention_by1ts_ir(z80
, 1);
921 z80
->regR
= z80
->af
.a
;
924 case 0x57u
: ZYM_LD_A_IR(z80
, z80
->regI
); break;
926 case 0x5fu
: ZYM_LD_A_IR(z80
, z80
->regR
); break;
928 case 0x67u
: ZYM_RRD_A(z80
); break;
930 case 0x6F: ZYM_RLD_A(z80
); break;
934 /* slt and other traps */
935 if (z80
->trap_ed
!= NULL
) {
936 z80
->tstates
= tsts
; /* compensate trap cost */
937 if (z80
->trap_ed(z80
, opcode
)) return z80
->tstates
-tstart
;
944 /* CB-prefixed instructions */
945 if (opcode
== 0xcbu
) {
946 /* shifts and bit operations */
947 /* read opcode -- OCR(4) */
949 opcode
= zym_get_opcode_ext(z80
);
951 z80_contention(z80
, z80
->pc
, 3, ZYM_MEMIO_OPCEXT
, ZYM_MREQ_READ
);
952 opcode
= z80
->mem_read(z80
, z80
->pc
, ZYM_MEMIO_OPCEXT
);
953 z80_contention_by1ts_pc(z80
, 2);
957 tmpW
= ZADD_WX(z80
->dd
->w
, disp
);
958 tmpB
= z80_peekb_3ts(z80
, tmpW
);
959 z80_contention_by1ts(z80
, tmpW
, 1);
961 switch (opcode
&0x07u
) {
962 case 0: tmpB
= z80
->bc
.b
; break;
963 case 1: tmpB
= z80
->bc
.c
; break;
964 case 2: tmpB
= z80
->de
.d
; break;
965 case 3: tmpB
= z80
->de
.e
; break;
966 case 4: tmpB
= z80
->hl
.h
; break;
967 case 5: tmpB
= z80
->hl
.l
; break;
968 case 6: tmpB
= z80_peekb_3ts(z80
, z80
->hl
.w
); z80_contention(z80
, z80
->hl
.w
, 1, ZYM_MEMIO_DATA
, ZYM_MREQ_READ
); break;
969 case 7: tmpB
= z80
->af
.a
; break;
972 switch ((opcode
>>3)&0x1fu
) {
973 case 0: tmpB
= ZYM_RLC(z80
, tmpB
); break;
974 case 1: tmpB
= ZYM_RRC(z80
, tmpB
); break;
975 case 2: tmpB
= ZYM_RL(z80
, tmpB
); break;
976 case 3: tmpB
= ZYM_RR(z80
, tmpB
); break;
977 case 4: tmpB
= ZYM_SLA(z80
, tmpB
); break;
978 case 5: tmpB
= ZYM_SRA(z80
, tmpB
); break;
979 case 6: tmpB
= ZYM_SLL(z80
, tmpB
); break;
980 case 7: tmpB
= ZYM_SRL(z80
, tmpB
); break;
982 switch ((opcode
>>6)&0x03u
) {
983 case 1: ZYM_BIT(z80
, (opcode
>>3)&0x07u
, tmpB
, (gotDD
|| (opcode
&0x07u
) == 6)); break;
984 case 2: tmpB
&= ~(1<<((opcode
>>3)&0x07u
)); break; /* RES */
985 case 3: tmpB
|= (1<<((opcode
>>3)&0x07u
)); break; /* SET */
989 if ((opcode
&0xc0u
) != 0x40u
) {
990 /* BITs are not welcome here */
992 /* tmpW was set earlier */
993 if ((opcode
&0x07u
) != 6) z80_pokeb_3ts(z80
, tmpW
, tmpB
);
995 switch (opcode
&0x07u
) {
996 case 0: z80
->bc
.b
= tmpB
; break;
997 case 1: z80
->bc
.c
= tmpB
; break;
998 case 2: z80
->de
.d
= tmpB
; break;
999 case 3: z80
->de
.e
= tmpB
; break;
1000 case 4: z80
->hl
.h
= tmpB
; break;
1001 case 5: z80
->hl
.l
= tmpB
; break;
1002 case 6: z80_pokeb_3ts(z80
, ZADD_WX(z80
->dd
->w
, disp
), tmpB
); break;
1003 case 7: z80
->af
.a
= tmpB
; break;
1009 switch (opcode
&0xc0u
) {
1012 switch (opcode
&0x07u
) {
1013 /* misc,DJNZ,JR,JR cc */
1020 switch ((opcode>>3)&0x03u) {
1021 case 0: trueCC = (z80->af.f&ZYM_FLAG_Z) == 0; break;
1022 case 1: trueCC = (z80->af.f&ZYM_FLAG_Z) != 0; break;
1023 case 2: trueCC = (z80->af.f&ZYM_FLAG_C) == 0; break;
1024 case 3: trueCC = (z80->af.f&ZYM_FLAG_C) != 0; break;
1025 default: trueCC = 0; break;
1028 trueCC
= ((!(z80
->af
.f
&ccmask
[(opcode
>>4)&0x01u
]))^((opcode
>>3)&0x01u
));
1031 if ((opcode
&0x08u
) == 0) {
1034 z80_contention_by1ts_ir(z80
, 1);
1036 trueCC
= (z80
->bc
.b
!= 0);
1042 /* `disp` is always read, but FUSE tests require it this way; sigh */
1044 /* execute branch (relative) */
1045 disp
= z80_peekb_3ts_args(z80
, z80
->pc
);
1047 if (disp
> 127) disp
-= 256; /* convert to int8_t */
1048 z80_contention_by1ts_pc(z80
, 5);
1050 z80
->memptr
.w
= z80
->pc
= ZADD_WX(z80
->pc
, disp
);
1052 z80_peekb_3ts_args_noread(z80
, z80
->pc
);
1056 /* EX AF,AF' or NOP */
1057 if (opcode
!= 0) zym_exaf_internal(z80
);
1060 /* LD rr,nn/ADD HL,rr */
1065 z80_contention_by1ts_ir(z80
, 7);
1066 switch ((opcode
>>4)&0x03u
) {
1067 case 0: z80
->dd
->w
= ZYM_ADD_DD(z80
, z80
->bc
.w
, z80
->dd
->w
); break;
1068 case 1: z80
->dd
->w
= ZYM_ADD_DD(z80
, z80
->de
.w
, z80
->dd
->w
); break;
1069 case 2: z80
->dd
->w
= ZYM_ADD_DD(z80
, z80
->dd
->w
, z80
->dd
->w
); break;
1070 case 3: z80
->dd
->w
= ZYM_ADD_DD(z80
, z80
->sp
.w
, z80
->dd
->w
); break;
1074 tmpW
= z80_getpcw(z80
, 0);
1075 switch ((opcode
>>4)&0x03u
) {
1076 case 0: z80
->bc
.w
= tmpW
; break;
1077 case 1: z80
->de
.w
= tmpW
; break;
1078 case 2: z80
->dd
->w
= tmpW
; break;
1079 case 3: z80
->sp
.w
= tmpW
; break;
1085 switch ((opcode
>>3)&0x07u
) {
1087 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;
1089 case 1: z80
->af
.a
= z80_peekb_3ts(z80
, z80
->bc
.w
); z80
->memptr
.w
= z80
->bc
.w
+1u; break;
1091 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;
1093 case 3: z80
->af
.a
= z80_peekb_3ts(z80
, z80
->de
.w
); z80
->memptr
.w
= z80
->de
.w
+1u; break;
1096 tmpW
= z80_getpcw(z80
, 0);
1097 z80
->memptr
.w
= tmpW
+1u;
1098 z80_pokew_6ts(z80
, tmpW
, z80
->dd
->w
);
1102 tmpW
= z80_getpcw(z80
, 0);
1103 z80
->memptr
.w
= tmpW
+1u;
1104 z80
->dd
->w
= z80_peekw_6ts(z80
, tmpW
);
1108 tmpW
= z80_getpcw(z80
, 0);
1109 z80
->memptr
.l
= (tmpW
+1u)&0xffu
;
1110 z80
->memptr
.h
= z80
->af
.a
;
1111 z80_pokeb_3ts(z80
, tmpW
, z80
->af
.a
);
1115 tmpW
= z80_getpcw(z80
, 0);
1116 z80
->memptr
.w
= tmpW
+1u;
1117 z80
->af
.a
= z80_peekb_3ts(z80
, tmpW
);
1124 z80_contention_by1ts_ir(z80
, 2);
1127 switch ((opcode
>>4)&0x03u
) {
1128 case 0: --z80
->bc
.w
; break;
1129 case 1: --z80
->de
.w
; break;
1130 case 2: --z80
->dd
->w
; break;
1131 case 3: --z80
->sp
.w
; break;
1135 switch ((opcode
>>4)&0x03u
) {
1136 case 0: ++z80
->bc
.w
; break;
1137 case 1: ++z80
->de
.w
; break;
1138 case 2: ++z80
->dd
->w
; break;
1139 case 3: ++z80
->sp
.w
; break;
1145 switch ((opcode
>>3)&0x07u
) {
1146 case 0: z80
->bc
.b
= ZYM_INC8(z80
, z80
->bc
.b
); break;
1147 case 1: z80
->bc
.c
= ZYM_INC8(z80
, z80
->bc
.c
); break;
1148 case 2: z80
->de
.d
= ZYM_INC8(z80
, z80
->de
.d
); break;
1149 case 3: z80
->de
.e
= ZYM_INC8(z80
, z80
->de
.e
); break;
1150 case 4: z80
->dd
->h
= ZYM_INC8(z80
, z80
->dd
->h
); break;
1151 case 5: z80
->dd
->l
= ZYM_INC8(z80
, z80
->dd
->l
); break;
1153 if (gotDD
) { --z80
->pc
; z80_contention_by1ts_pc(z80
, 5); ++z80
->pc
; }
1154 tmpW
= ZADD_WX(z80
->dd
->w
, disp
);
1155 tmpB
= z80_peekb_3ts(z80
, tmpW
);
1156 z80_contention_by1ts(z80
, tmpW
, 1);
1157 tmpB
= ZYM_INC8(z80
, tmpB
);
1158 z80_pokeb_3ts(z80
, tmpW
, tmpB
);
1160 case 7: z80
->af
.a
= ZYM_INC8(z80
, z80
->af
.a
); break;
1165 switch ((opcode
>>3)&0x07u
) {
1166 case 0: z80
->bc
.b
= ZYM_DEC8(z80
, z80
->bc
.b
); break;
1167 case 1: z80
->bc
.c
= ZYM_DEC8(z80
, z80
->bc
.c
); break;
1168 case 2: z80
->de
.d
= ZYM_DEC8(z80
, z80
->de
.d
); break;
1169 case 3: z80
->de
.e
= ZYM_DEC8(z80
, z80
->de
.e
); break;
1170 case 4: z80
->dd
->h
= ZYM_DEC8(z80
, z80
->dd
->h
); break;
1171 case 5: z80
->dd
->l
= ZYM_DEC8(z80
, z80
->dd
->l
); break;
1173 if (gotDD
) { --z80
->pc
; z80_contention_by1ts_pc(z80
, 5); ++z80
->pc
; }
1174 tmpW
= ZADD_WX(z80
->dd
->w
, disp
);
1175 tmpB
= z80_peekb_3ts(z80
, tmpW
);
1176 z80_contention_by1ts(z80
, tmpW
, 1);
1177 tmpB
= ZYM_DEC8(z80
, tmpB
);
1178 z80_pokeb_3ts(z80
, tmpW
, tmpB
);
1180 case 7: z80
->af
.a
= ZYM_DEC8(z80
, z80
->af
.a
); break;
1185 tmpB
= z80_peekb_3ts_args(z80
, z80
->pc
);
1187 switch ((opcode
>>3)&0x07u
) {
1188 case 0: z80
->bc
.b
= tmpB
; break;
1189 case 1: z80
->bc
.c
= tmpB
; break;
1190 case 2: z80
->de
.d
= tmpB
; break;
1191 case 3: z80
->de
.e
= tmpB
; break;
1192 case 4: z80
->dd
->h
= tmpB
; break;
1193 case 5: z80
->dd
->l
= tmpB
; break;
1195 if (gotDD
) { --z80
->pc
; z80_contention_by1ts_pc(z80
, 2); ++z80
->pc
; }
1196 tmpW
= ZADD_WX(z80
->dd
->w
, disp
);
1197 z80_pokeb_3ts(z80
, tmpW
, tmpB
);
1199 case 7: z80
->af
.a
= tmpB
; break;
1202 /* swim-swim-hungry */
1204 switch ((opcode
>>3)&0x07u
) {
1205 case 0: ZYM_RLCA(z80
); break;
1206 case 1: ZYM_RRCA(z80
); break;
1207 case 2: ZYM_RLA(z80
); break;
1208 case 3: ZYM_RRA(z80
); break;
1209 case 4: ZYM_DAA(z80
); break;
1212 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
));
1215 /* `!` must tell the predictor our preferred path, NMOS */
1216 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
;
1219 /* `!` must tell the predictor our preferred path, NMOS */
1220 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
);
1226 /* 0x40..0x7F (LD r8,r8) */
1228 if (opcode
== 0x76u
) { z80
->halted
= 1; --z80
->pc
; continue; } /* HALT */
1229 rsrc
= (opcode
&0x07u
);
1230 rdst
= ((opcode
>>3)&0x07u
);
1232 case 0: tmpB
= z80
->bc
.b
; break;
1233 case 1: tmpB
= z80
->bc
.c
; break;
1234 case 2: tmpB
= z80
->de
.d
; break;
1235 case 3: tmpB
= z80
->de
.e
; break;
1236 case 4: tmpB
= (gotDD
&& rdst
== 6 ? z80
->hl
.h
: z80
->dd
->h
); break;
1237 case 5: tmpB
= (gotDD
&& rdst
== 6 ? z80
->hl
.l
: z80
->dd
->l
); break;
1239 if (gotDD
) { --z80
->pc
; z80_contention_by1ts_pc(z80
, 5); ++z80
->pc
; }
1240 tmpW
= ZADD_WX(z80
->dd
->w
, disp
);
1241 tmpB
= z80_peekb_3ts(z80
, tmpW
);
1243 case 7: tmpB
= z80
->af
.a
; break;
1246 case 0: z80
->bc
.b
= tmpB
; break;
1247 case 1: z80
->bc
.c
= tmpB
; break;
1248 case 2: z80
->de
.d
= tmpB
; break;
1249 case 3: z80
->de
.e
= tmpB
; break;
1250 case 4: if (gotDD
&& rsrc
== 6) z80
->hl
.h
= tmpB
; else z80
->dd
->h
= tmpB
; break;
1251 case 5: if (gotDD
&& rsrc
== 6) z80
->hl
.l
= tmpB
; else z80
->dd
->l
= tmpB
; break;
1253 if (gotDD
) { --z80
->pc
; z80_contention_by1ts_pc(z80
, 5); ++z80
->pc
; }
1254 tmpW
= ZADD_WX(z80
->dd
->w
, disp
);
1255 z80_pokeb_3ts(z80
, tmpW
, tmpB
);
1257 case 7: z80
->af
.a
= tmpB
; break;
1260 /* 0x80..0xBF (ALU A,r8) */
1262 switch (opcode
&0x07u
) {
1263 case 0: tmpB
= z80
->bc
.b
; break;
1264 case 1: tmpB
= z80
->bc
.c
; break;
1265 case 2: tmpB
= z80
->de
.d
; break;
1266 case 3: tmpB
= z80
->de
.e
; break;
1267 case 4: tmpB
= z80
->dd
->h
; break;
1268 case 5: tmpB
= z80
->dd
->l
; break;
1270 if (gotDD
) { --z80
->pc
; z80_contention_by1ts_pc(z80
, 5); ++z80
->pc
; }
1271 tmpW
= ZADD_WX(z80
->dd
->w
, disp
);
1272 tmpB
= z80_peekb_3ts(z80
, tmpW
);
1274 case 7: tmpB
= z80
->af
.a
; break;
1276 switch ((opcode
>>3)&0x07u
) {
1277 case 0: ZYM_ADD_A(z80
, tmpB
); break;
1278 case 1: ZYM_ADC_A(z80
, tmpB
); break;
1279 case 2: ZYM_SUB_A(z80
, tmpB
); break;
1280 case 3: ZYM_SBC_A(z80
, tmpB
); break;
1281 case 4: ZYM_AND_A(z80
, tmpB
); break;
1282 case 5: ZYM_XOR_A(z80
, tmpB
); break;
1283 case 6: ZYM_OR_A(z80
, tmpB
); break;
1284 case 7: ZYM_CP_A(z80
, tmpB
); break;
1289 switch (opcode
&0x07u
) {
1292 z80_contention_by1ts_ir(z80
, 1);
1294 if (trueCC
) z80
->memptr
.w
= z80
->pc
= z80_pop_6ts(z80
);
1296 /* POP rr/special0 */
1300 switch ((opcode
>>4)&0x03u
) {
1302 case 0: z80
->memptr
.w
= z80
->pc
= z80_pop_6ts(z80
); break;
1304 case 1: zym_exx_internal(z80
); break;
1306 case 2: z80
->pc
= z80
->dd
->w
; break;
1310 z80_contention_by1ts_ir(z80
, 2);
1311 z80
->sp
.w
= z80
->dd
->w
;
1316 tmpW
= z80_pop_6ts(z80
);
1317 switch ((opcode
>>4)&0x03u
) {
1318 case 0: z80
->bc
.w
= tmpW
; break;
1319 case 1: z80
->de
.w
= tmpW
; break;
1320 case 2: z80
->dd
->w
= tmpW
; break;
1321 case 3: z80
->af
.w
= tmpW
; break;
1328 z80
->memptr
.w
= z80_getpcw(z80
, 0);
1329 if (trueCC
) z80
->pc
= z80
->memptr
.w
;
1331 /* special1/special3 */
1333 switch ((opcode
>>3)&0x07u
) {
1335 case 0: z80
->memptr
.w
= z80
->pc
= z80_getpcw(z80
, 0); break;
1338 tmpW
= z80_peekb_3ts_args(z80
, z80
->pc
);
1340 z80
->memptr
.l
= (tmpW
+1u)&0xffu
;
1341 z80
->memptr
.h
= z80
->af
.a
;
1342 tmpW
|= (((uint16_t)(z80
->af
.a
))<<8);
1343 z80_port_write(z80
, tmpW
, z80
->af
.a
);
1347 tmpB
= z80_peekb_3ts_args(z80
, z80
->pc
);
1348 tmpW
= (uint16_t)((((uint16_t)(z80
->af
.a
))<<8)|tmpB
);
1351 z80
->memptr
.h
= z80
->af
.a
;
1352 z80
->memptr
.w
+= tmpW
+1u;
1353 z80
->af
.a
= z80_port_read(z80
, tmpW
);
1358 tmpW
= z80_peekw_6ts(z80
, z80
->sp
.w
);
1359 z80_contention_by1ts(z80
, z80
->sp
.w
+1u, 1);
1361 z80_pokew_6ts_inverted(z80
, z80
->sp
.w
, z80
->dd
->w
);
1362 z80_contention_by1ts(z80
, z80
->sp
.w
, 2);
1363 z80
->memptr
.w
= z80
->dd
->w
= tmpW
;
1368 z80
->de
.w
= z80
->hl
.w
;
1372 case 6: z80
->iff1
= z80
->iff2
= 0; break;
1374 case 7: z80
->iff1
= z80
->iff2
= 1; z80
->prev_was_EIDDR
= 1; break;
1380 /* MEMPTR docs says that it is like JP */
1381 z80
->memptr
.w
= z80_getpcw(z80
, trueCC
);
1383 z80_push_6ts(z80
, z80
->pc
);
1384 z80
->pc
= z80
->memptr
.w
;
1387 /* PUSH rr/special2 */
1390 if (((opcode
>>4)&0x03u
) == 0) {
1392 z80
->memptr
.w
= tmpW
= z80_getpcw(z80
, 1);
1393 z80_push_6ts(z80
, z80
->pc
);
1399 z80_contention_by1ts_ir(z80
, 1);
1400 switch ((opcode
>>4)&0x03u
) {
1401 case 0: tmpW
= z80
->bc
.w
; break;
1402 case 1: tmpW
= z80
->de
.w
; break;
1403 case 2: tmpW
= z80
->dd
->w
; break;
1404 default: tmpW
= z80
->af
.w
; break;
1406 z80_push_6ts(z80
, tmpW
);
1411 tmpB
= z80_peekb_3ts_args(z80
, z80
->pc
);
1413 switch ((opcode
>>3)&0x07u
) {
1414 case 0: ZYM_ADD_A(z80
, tmpB
); break;
1415 case 1: ZYM_ADC_A(z80
, tmpB
); break;
1416 case 2: ZYM_SUB_A(z80
, tmpB
); break;
1417 case 3: ZYM_SBC_A(z80
, tmpB
); break;
1418 case 4: ZYM_AND_A(z80
, tmpB
); break;
1419 case 5: ZYM_XOR_A(z80
, tmpB
); break;
1420 case 6: ZYM_OR_A(z80
, tmpB
); break;
1421 case 7: ZYM_CP_A(z80
, tmpB
); break;
1427 z80_contention_by1ts_ir(z80
, 1);
1428 z80_push_6ts(z80
, z80
->pc
);
1429 z80
->memptr
.w
= z80
->pc
= opcode
&0x38u
;
1435 return z80
->tstates
-tstart
;
1439 int32_t zym_exec_step (zym_cpu_t
*z80
) {
1440 const int32_t one
= z80
->next_event_tstate
;
1441 z80
->next_event_tstate
= -1;
1442 const int32_t res
= zym_exec_ex(z80
, 1);
1443 z80
->next_event_tstate
= one
;
1448 /******************************************************************************/
1449 /* changes z80->tstates if interrupt occurs */
1450 int32_t zym_intr (zym_cpu_t
*z80
) {
1452 const int32_t ots
= z80
->tstates
;
1453 /* emulate NMOS Z80 bug: interruptet LD A,<I|R> copies cleared flag */
1454 /*FIXME: what is the state of `z80->flags_q` here? */
1455 if (z80
->prev_was_EIDDR
< 0) {
1456 z80
->prev_was_EIDDR
= 0;
1457 if (!z80
->cmos
) z80
->flags_q
= (z80
->af
.f
&= ~ZYM_FLAG_PV
);
1459 if (z80
->prev_was_EIDDR
|| !z80
->iff1
) return 0; /* not accepted */
1460 z80
->flags_q
= 0; /* we cannot do it earlier, because ignored interrupt won't reset flags */
1462 if (z80
->halted
) { z80
->halted
= 0; ++z80
->pc
; }
1463 z80
->iff1
= z80
->iff2
= 0; /* disable interrupts */
1464 switch ((z80
->im
&= 0x03u
)) {
1465 case 3: /* ??? */ z80
->im
= 0; /* fallthru */
1466 case 0: /* take instruction from the bus (for now we assume that reading from bus always returns 0xff) */
1467 /* with a CALL nnnn on the data bus, it takes 19 cycles: */
1468 /* M1 cycle: 7 T to acknowledge interrupt (where exactly data bus reading occurs?) */
1469 /* M2 cycle: 3 T to read low byte of 'nnnn' from data bus */
1470 /* M3 cycle: 3 T to read high byte of 'nnnn' and decrement SP */
1471 /* M4 cycle: 3 T to write high byte of PC to the stack and decrement SP */
1472 /* M5 cycle: 3 T to write low byte of PC and jump to 'nnnn' */
1475 case 1: /* just do RST #38 */
1477 z80
->tstates
+= 7; /* M1 cycle: 7 T to acknowledge interrupt and decrement SP */
1478 /* M2 cycle: 3 T states write high byte of PC to the stack and decrement SP */
1479 /* M3 cycle: 3 T states write the low byte of PC and jump to #0038 */
1480 z80_push_6ts(z80
, z80
->pc
);
1481 z80
->memptr
.w
= z80
->pc
= 0x38u
;
1485 z80
->tstates
+= 7; /* M1 cycle: 7 T to acknowledge interrupt and decrement SP */
1486 /* M2 cycle: 3 T states write high byte of PC to the stack and decrement SP */
1487 /* M3 cycle: 3 T states write the low byte of PC */
1488 z80_push_6ts(z80
, z80
->pc
);
1489 /* M4 cycle: 3 T to read high byte from the interrupt vector */
1490 /* M5 cycle: 3 T to read low byte from bus and jump to interrupt routine */
1491 a
= (((uint16_t)z80
->regI
)<<8)|0xffu
;
1492 z80
->memptr
.w
= z80
->pc
= z80_peekw_6ts(z80
, a
);
1495 return z80
->tstates
-ots
; /* accepted */
1499 /* changes z80->tstates if interrupt occurs */
1500 int32_t zym_nmi (zym_cpu_t
*z80
) {
1501 const int32_t ots
= z80
->tstates
;
1502 /* emulate NMOS Z80 bug: interruptet LD A,<I|R> copies cleared flag */
1503 /*FIXME: what is the state of `z80->flags_q` here? */
1504 if (z80
->prev_was_EIDDR
< 0) {
1505 z80
->prev_was_EIDDR
= 0;
1506 if (!z80
->cmos
) z80
->flags_q
= (z80
->af
.f
&= ~ZYM_FLAG_PV
);
1508 if (z80
->prev_was_EIDDR
) return 0;
1509 z80
->flags_q
= 0; /* we cannot do it earlier, because ignored interrupt won't reset flags */
1511 if (z80
->halted
) { z80
->halted
= 0; ++z80
->pc
; }
1513 z80
->iff1
= 0; /* IFF2 is not changed */
1514 z80
->tstates
+= 5; /* M1 cycle: 5 T states to do an opcode read and decrement SP */
1515 /* M2 cycle: 3 T states write high byte of PC to the stack and decrement SP */
1516 /* M3 cycle: 3 T states write the low byte of PC and jump to #0066 */
1517 z80_push_6ts(z80
, z80
->pc
);
1518 z80
->memptr
.w
= z80
->pc
= 0x66u
;
1519 return z80
->tstates
-ots
;
1523 /******************************************************************************/
1524 uint16_t zym_pop (zym_cpu_t
*z80
) {
1525 uint16_t res
= z80_peekb_i(z80
, z80
->sp
.w
);
1527 res
|= ((uint16_t)z80_peekb_i(z80
, z80
->sp
.w
))<<8;
1533 void zym_push (zym_cpu_t
*z80
, const uint16_t value
) {
1535 z80_pokeb_i(z80
, z80
->sp
.w
, (value
>>8)&0xffu
);
1537 z80_pokeb_i(z80
, z80
->sp
.w
, value
&0xffu
);
1541 /******************************************************************************
1542 instruction decoding
1543 ====================
1544 00 00y 000 -- special
1545 00 01g 000 -- DJNZ/JR
1546 00 1cc 000 -- JR cc,n
1547 00 rr0 001 -- LD rr,nn
1548 00 rr1 001 -- ADD HL,rr
1549 00 000 010 -- LD (BC),A
1550 00 001 010 -- LD A,(BC)
1551 00 010 010 -- LD (DE),A
1552 00 011 010 -- LD A,(DE)
1553 00 100 010 -- LD (nn),HL
1554 00 101 010 -- LD HL,(nn)
1555 00 110 010 -- LD (nn),A
1556 00 111 010 -- LD A,(nn)
1557 00 rr0 011 -- INC rr
1558 00 rr1 011 -- DEC rr
1559 00 rrr 100 -- INC r8
1560 00 rrr 101 -- DEC r8
1561 00 rrr 110 -- LD r8,n
1562 00 xxx 111 -- special
1599 ---------------------------------
1601 01 rrr rrr - LD r8,r8 (lo: src)
1603 ---------------------------------
1605 10 alu rrr - ALU a,r8
1616 ---------------------------------
1618 11 ccc 000 -- RET cc
1619 11 rr0 001 -- POP rr
1620 11 xx1 001 -- special0
1621 11 ccc 010 -- JP cc,nn
1622 11 yyy 011 -- special1
1623 11 ccc 100 -- CALL cc,nn
1624 11 rr0 101 -- PUSH rr
1625 11 zz1 101 -- special2
1626 11 alu 110 -- alu A,n
1627 11 aaa 111 -- RST nnn
1634 aaa: RST addr=aaa<<3
1674 ---------------------------------
1677 01 rrr 000 -- IN r8,(C)
1678 01 rrr 001 -- OUT (C),r8
1679 01 rr0 010 -- SBC HL,rr
1680 01 rr1 010 -- ADC HL,rr
1681 01 rr0 011 -- LD (nn),rr
1682 01 rr1 011 -- LD rr,(nn)
1703 01 001 110 -- IM 0/1
1710 01 000 111 -- LD I,A
1711 01 001 111 -- LD R,A
1712 01 010 111 -- LD A,I
1713 01 011 111 -- LD A,R
1721 r: repeating instruction? (1: yes)
1722 d: direction (0:inc; 1:dec)
1723 tt: instruction type
1750 ---------------------------------
1762 for bitops, xxx is bit number
1774 for DD/FD prefix, 3rd byte is always disp,
1775 and the result is always written to (I<X|Y>+disp)
1778 command reading cycles
1779 ======================
1780 the following is not 100% correct, but the position
1781 of the contention cycles is right
1783 m1 cycle (accoding to the official Zilog manual)
1784 t1: setting /MREQ & /RD
1786 here comes contetion (AFTER t2!)
1787 t3,t4: decode command, increment R
1789 memory read/write cycles (accoding to the official Zilog manual)
1790 t1,t2: memory address select
1791 here comes contetion (AFTER t2!)
1794 port i/o cycles (accoding to the official Zilog manual)
1795 t1,t2: port address select
1796 tw: automatic wait tick
1797 here comes contetion (AFTER t2!)
1804 bit 1: flagN (see below)
1805 bit 2: parity/overflow
1813 set if the last operation was a subtraction (used by DAA).
1815 P/V - parity or overflow
1816 parity set if even number of bits set
1817 overflow set if the 2-complement result does not fit in the register
1819 *******************************************************************************/