2 * Simulator of microcontrollers (inst_ed.cc)
3 * ED escaped multi-byte opcodes for Z80.
5 * Copyright (C) 1999 Drotos Daniel
7 * To contact author send email to dr.dkdb@gmail.com
11 /* This file is part of microcontroller simulator: ucsim.
13 UCSIM is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
18 UCSIM is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with UCSIM; see the file COPYING. If not, write to the Free
25 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
29 //#include "ddconfig.h"
33 //#include "regsz80.h"
37 #define tst_A_bytereg(br) { \
38 ubtmp = regs.raf.A & (br); \
39 regs.raf.F &= ~(BIT_ALL); /* clear these */ \
40 regs.raf.F |= BIT_A; \
41 if (ubtmp == 0) regs.raf.F |= BIT_Z; \
42 if (ubtmp & 0x80) regs.raf.F |= BIT_S; \
43 if (parity(ubtmp)) regs.raf.F |= BIT_P; \
47 int cl_z80::inst_ed_(t_mem code
)
52 if (type
->type
== CPU_Z80N
)
55 if (inst_z80n(code
, &ret
))
61 if (!(type
->type
& (CPU_Z180
| CPU_EZ80
)))
64 switch ( code
& 0x07 )
68 reg_g_store( (code
>> 3) & 0x07, in_byte( ubtmp
) );
73 out_byte( ubtmp
, reg_g_read( (code
>> 3) & 0x07 ) );
77 tst_A_bytereg(reg_g_read( (code
>> 3) & 0x07 ));
87 case 0x40: // IN B,(C)
88 regs
.bc
.h
= inputs
->read((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.l
);
89 regs
.raf
.F
&= ~(BIT_N
| BIT_P
);
90 if (parity(regs
.bc
.h
)) regs
.raf
.F
|= BIT_P
;
95 case 0x41: // OUT (C),B
96 outputs
->write((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.l
, regs
.bc
.h
);
101 case 0x42: // SBC HL,BC
102 sbc_HL_wordreg(regs
.BC
);
106 case 0x43: // LD (nnnn),BC
114 regs
.raf
.F
&= ~(BIT_ALL
); /* clear these */
115 if (regs
.raf
.A
!= 0) regs
.raf
.F
|= BIT_C
;
116 if (regs
.raf
.A
== 0x80) regs
.raf
.F
|= BIT_P
;
117 if ((regs
.raf
.A
& 0x0F) != 0) regs
.raf
.F
|= BIT_A
;
118 regs
.raf
.A
= 0 - regs
.raf
.A
;
119 regs
.raf
.F
|= BIT_N
; /* not addition */
120 if (regs
.raf
.A
== 0) regs
.raf
.F
|= BIT_Z
;
121 if (regs
.raf
.A
& 0x80) regs
.raf
.F
|= BIT_S
;
125 case 0x45: // RETN (return from non-maskable interrupt)
134 /* interrupt device puts opcode on data bus */
139 case 0x47: // LD IV,A
140 regs
.iv
= regs
.raf
.A
;
144 case 0x48: // IN C,(C)
145 regs
.bc
.l
= inputs
->read((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.l
);
146 regs
.raf
.F
&= ~(BIT_N
| BIT_P
);
147 if (parity(regs
.bc
.l
)) regs
.raf
.F
|= BIT_P
;
152 case 0x49: // OUT (C),C
153 outputs
->write((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.l
, regs
.bc
.l
);
158 case 0x4A: // ADC HL,BC
159 adc_HL_wordreg(regs
.BC
);
163 case 0x4B: // LD BC,(nnnn)
171 if (!(type
->type
& (CPU_Z180
| CPU_EZ80
)))
173 regs
.BC
= (unsigned long)(regs
.bc
.h
) * (unsigned long)(regs
.bc
.l
);
176 case 0x4D: // RETI (return from interrupt)
189 case 0x50: // IN D,(C)
190 regs
.de
.h
= inputs
->read((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.l
);
191 regs
.raf
.F
&= ~(BIT_N
| BIT_P
);
192 if (parity(regs
.de
.h
)) regs
.raf
.F
|= BIT_P
;
197 case 0x51: // OUT (C),D
198 outputs
->write((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.l
, regs
.de
.h
);
203 case 0x52: // SBC HL,DE
204 sbc_HL_wordreg(regs
.DE
);
208 case 0x53: // LD (nnnn),DE
220 case 0x57: // LD A,IV
221 regs
.raf
.A
= regs
.iv
;
224 regs
.raf
.F
&= ~(BIT_A
| BIT_N
| BIT_P
);
225 if (IFF2
) regs
.raf
.F
|= BIT_P
;
229 case 0x58: // IN E,(C)
230 regs
.de
.l
= inputs
->read((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.l
);
231 regs
.raf
.F
&= ~(BIT_N
| BIT_P
);
232 if (parity(regs
.de
.l
)) regs
.raf
.F
|= BIT_P
;
237 case 0x59: // OUT (C),E
238 outputs
->write((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.l
, regs
.de
.l
);
243 case 0x5A: // ADC HL,DE
244 adc_HL_wordreg(regs
.DE
);
248 case 0x5B: // LD DE,(nnnn)
256 if (!(type
->type
& (CPU_Z180
| CPU_EZ80
)))
258 regs
.DE
= (unsigned long)(regs
.de
.h
) * (unsigned long)(regs
.de
.l
);
270 regs
.raf
.F
&= ~(BIT_A
| BIT_N
| BIT_P
);
271 if (IFF2
) regs
.raf
.F
|= BIT_P
;
275 case 0x60: // IN H,(C)
276 regs
.hl
.h
= inputs
->read((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.l
);
277 regs
.raf
.F
&= ~(BIT_N
| BIT_P
);
278 if (parity(regs
.hl
.h
)) regs
.raf
.F
|= BIT_P
;
283 case 0x61: // OUT (C),H
284 outputs
->write((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.l
, regs
.hl
.h
);
289 case 0x62: // SBC HL,HL
290 sbc_HL_wordreg(regs
.HL
);
294 case 0x63: // LD (nnnn),HL opcode 22 does the same faster
302 if (!(type
->type
& (CPU_Z180
| CPU_EZ80
)))
304 ubtmp
= fetch(); // TST A,n
305 tst_A_bytereg(ubtmp
);
309 ubtmp
= get1(regs
.HL
);
310 store1(regs
.HL
, (ubtmp
>> 4) | (regs
.raf
.A
<< 4));
311 regs
.raf
.A
= (regs
.raf
.A
& 0xf0) | (ubtmp
& 0x0f);
315 case 0x68: // IN L,(C)
316 regs
.hl
.l
= inputs
->read((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.l
);
317 regs
.raf
.F
&= ~(BIT_N
| BIT_P
);
318 if (parity(regs
.hl
.l
)) regs
.raf
.F
|= BIT_P
;
323 case 0x69: // OUT (C),L
324 outputs
->write((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.l
, regs
.hl
.l
);
329 case 0x6A: // ADC HL,HL
330 adc_HL_wordreg(regs
.HL
);
334 case 0x6B: // LD HL,(nnnn) opcode 2A does the same faster
342 if (!(type
->type
& (CPU_Z180
| CPU_EZ80
)))
344 regs
.HL
= (unsigned long)(regs
.hl
.h
) * (unsigned long)(regs
.hl
.l
);
348 ubtmp
= get1(regs
.HL
);
349 store1(regs
.HL
, (ubtmp
<< 4) | (regs
.raf
.A
& 0x0f));
350 regs
.raf
.A
= (regs
.raf
.A
& 0xf0) | (ubtmp
>> 4);
354 case 0x70: // IN (C) set flags only (TSTI)
356 u8_t x
= inputs
->read((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.l
);
357 regs
.raf
.F
&= ~(BIT_N
| BIT_P
);
358 if (parity(x
)) regs
.raf
.F
|= BIT_P
;
364 case 0x71: // OUT (C),0
365 outputs
->write((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.l
, 0);
370 case 0x72: // SBC HL,SP
371 sbc_HL_wordreg(regs
.SP
);
375 case 0x73: // LD (nnnn),SP
382 case 0x78: // IN A,(C)
383 regs
.raf
.A
= inputs
->read((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.l
);
384 regs
.raf
.F
&= ~(BIT_N
| BIT_P
);
385 if (parity(regs
.raf
.A
)) regs
.raf
.F
|= BIT_P
;
390 case 0x79: // OUT (C),A
391 outputs
->write((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.l
, regs
.raf
.A
);
396 case 0x7A: // ADC HL,SP
397 adc_HL_wordreg(regs
.SP
);
401 case 0x7B: // LD SP,(nnnn)
409 //if(type != CPU_Z180)
411 //regs.SP = (unsigned long)(regs.sp.h) * (unsigned long)(regs.sp.l);
415 // BC - count, source=HL, dest=DE. *DE++ = *HL++, --BC until zero
416 regs
.raf
.F
&= ~(BIT_P
| BIT_N
| BIT_A
); /* clear these */
417 store1(regs
.DE
, get1(regs
.HL
));
421 if (regs
.BC
!= 0) regs
.raf
.F
|= BIT_P
;
426 // compare acc with mem(HL), if ACC=0 set Z flag. Incr HL, decr BC.
433 if (regs
.BC
!= 0) regs
.raf
.F
|= BIT_P
;
439 this->store1(regs
.HL
, inputs
->read((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.l
));
442 if (type
->type
==CPU_Z80N
)
445 regs
.raf
.F
&= ~(BIT_N
);
454 outputs
->write((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.h
, this->get1(regs
.HL
));
458 if (type
->type
==CPU_Z80N
)
461 regs
.raf
.F
&= ~(BIT_N
);
467 // BC - count, source=HL, dest=DE. *DE-- = *HL--, --BC until zero
468 regs
.raf
.F
&= ~(BIT_P
| BIT_N
| BIT_A
); /* clear these */
469 store1(regs
.DE
, get1(regs
.HL
));
473 if (regs
.BC
!= 0) regs
.raf
.F
|= BIT_P
;
480 /* fixme: checkme, compare to other emul. */
482 regs
.raf
.F
&= ~(BIT_ALL
); /* clear these */
483 if ((regs
.raf
.A
- get1(regs
.HL
)) == 0) {
484 regs
.raf
.F
|= (BIT_Z
| BIT_P
);
488 if (regs
.BC
!= 0) regs
.raf
.F
|= BIT_P
;
494 this->store1(regs
.HL
, inputs
->read((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.l
));
497 if (type
->type
==CPU_Z80N
)
500 regs
.raf
.F
&= ~(BIT_N
);
508 outputs
->write((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.l
, this->get1(regs
.HL
));
511 if (type
->type
==CPU_Z80N
)
514 regs
.raf
.F
&= ~(BIT_N
);
521 // BC - count, source=HL, dest=DE. *DE++ = *HL++, --BC until zero
522 regs
.raf
.F
&= ~(BIT_P
| BIT_N
| BIT_A
); /* clear these */
524 store1(regs
.DE
, get1(regs
.HL
));
531 //if (regs.BC) //tick(5);
532 //} while (regs.BC != 0);
543 // compare acc with mem(HL), if ACC=0 set Z flag. Incr HL, decr BC.
544 regs
.raf
.F
&= ~(BIT_P
| BIT_A
| BIT_Z
| BIT_S
); /* clear these */
547 if((regs
.raf
.A
- get1(regs
.HL
)) == 0)
550 regs
.raf
.F
&= ~(BIT_Z
);
551 if((regs
.raf
.A
- get1(regs
.HL
)) & 0x80)
554 regs
.raf
.F
&= ~(BIT_S
);
555 /* fixme: set BIT_A correctly. */
560 //if (regs.BC) //tick(5);
561 //} while (regs.BC != 0 && (regs.raf.F & BIT_Z) == 0);
565 if (!(regs
.raf
.F
& BIT_Z
))
576 this->store1(regs
.HL
, inputs
->read((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.l
));
579 if (type
->type
==CPU_Z80N
)
582 regs
.raf
.F
&= ~(BIT_N
);
587 //if (regs.BC) //tick(5);
600 outputs
->write((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.h
, this->get1(regs
.HL
));
604 if (type
->type
==CPU_Z80N
)
607 regs
.raf
.F
&= ~(BIT_N
);
610 //if (regs.BC) //tick(5);
621 // BC - count, source=HL, dest=DE. *DE-- = *HL--, --BC until zero
622 regs
.raf
.F
&= ~(BIT_P
| BIT_N
| BIT_A
); /* clear these */
624 store1(regs
.DE
, get1(regs
.HL
));
631 //if (regs.BC) //tick(5);
632 //} while (regs.BC != 0);
643 // compare acc with mem(HL), if ACC=0 set Z flag. Incr HL, decr BC.
644 regs
.raf
.F
&= ~(BIT_ALL
); /* clear these */
646 if ((regs
.raf
.A
- get1(regs
.HL
)) == 0) {
647 regs
.raf
.F
|= (BIT_Z
| BIT_P
);
657 //if (regs.BC) //tick(5);
658 //} while (regs.BC != 0);
672 this->store1(regs
.HL
, inputs
->read((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.l
));
675 if (type
->type
==CPU_Z80N
)
678 regs
.raf
.F
&= ~(BIT_N
);
683 //if (regs.BC) //tick(5);
696 outputs
->write((type
->type
==CPU_Z80N
)?regs
.BC
:regs
.bc
.l
, this->get1(regs
.HL
));
699 if (type
->type
==CPU_Z80N
)
702 regs
.raf
.F
&= ~(BIT_N
);
706 //if (regs.BC) //tick(5);
734 /******** start ED codes *****************/
735 int cl_z80::inst_ed(t_mem prefix
)
740 return(resBREAKPOINT
);
742 return inst_ed_(code
);
745 /* End of z80.src/inst_ed.cc */