/*
* Z80SIM - a Z80-CPU simulator
*
* Copyright (C) 1987-92 by Udo Munk
*
* This module of the Z80-CPU simulator must not be modified by a user,
* see license agreement!
*
* History:
* 28-SEP-87 Development on TARGON/35 with AT&T Unix System V.3
* 11-JAN-89 Release 1.1
* 08-FEB-89 Release 1.2
* 13-MAR-89 Release 1.3
* 09-FEB-90 Release 1.4 Ported to TARGON/31 M10/30
* 20-DEC-90 Release 1.5 Ported to COHERENT 3.0
* 10-JUN-92 Release 1.6 long casting problem solved with COHERENT 3.2
* and some optimization
* 25-JUN-92 Release 1.7 comments in english
*/
/*
* Like the function "cpu()" this one emulates multi byte opcodes
* starting with 0xed
*/
#include "sim.h"
#include "simglb.h"
long op_ed_handel()
{
long trap_ed();
long op_im0(), op_im1(), op_im2();
long op_reti(), op_retn();
long op_neg();
long op_inaic(), op_inbic(), op_incic(), op_indic(), op_ineic();
long op_inhic(), op_inlic();
long op_outca(), op_outcb(), op_outcc(), op_outcd(), op_outce();
long op_outch(), op_outcl();
long op_ini(), op_inir(), op_ind(), op_indr();
long op_outi(), op_otir(), op_outd(), op_otdr();
long op_ldai(), op_ldar(), op_ldia(), op_ldra();
long op_ldbcinn(), op_lddeinn(), op_ldspinn();
long op_ldinbc(), op_ldinde(), op_ldinsp();
long op_adchb(), op_adchd(), op_adchh(), op_adchs();
long op_sbchb(), op_sbchd(), op_sbchh(), op_sbchs();
long op_ldi(), op_ldir(), op_ldd(), op_lddr();
long op_cpi(), op_cpir(), op_cpdop(), op_cpdr();
long op_oprld(), op_oprrd();
#ifdef WANT_TIM
register long t;
t = (*op_ed[*PC++]) (); /* execute next opcode */
#else
(*op_ed[*PC++]) ();
#endif
#ifdef WANT_PCC
if (PC > ram + 65535) /* correct PC overrun */
PC = ram;
#endif
#ifdef WANT_TIM
return(t);
#endif
}
/*
* This function traps all illegal opcodes following the
* initial 0xed of a multi byte opcode.
*/
static long trap_ed()
{
cpu_error = OPTRAP2;
cpu_state = STOPPED;
#ifdef WANT_TIM
return(0L);
#endif
}
static long op_im0() /* IM 0 */
{
int_mode = 0;
#ifdef WANT_TIM
return(8L);
#endif
}
static long op_im1() /* IM 1 */
{
int_mode = 1;
#ifdef WANT_TIM
return(8L);
#endif
}
static long op_im2() /* IM 2 */
{
int_mode = 2;
#ifdef WANT_TIM
return(8L);
#endif
}
static long op_reti() /* RETI */
{
register unsigned i;
i = *STACK++;
#ifdef WANT_SPC
if (STACK >= ram + 65536L)
STACK = ram;
#endif
i += *STACK++ << 8;
#ifdef WANT_SPC
if (STACK >= ram + 65536L)
STACK = ram;
#endif
PC = ram + i;
#ifdef WANT_TIM
return(14L);
#endif
}
static long op_retn() /* RETN */
{
register unsigned i;
static long op_ldi() /* LDI */
{
*(ram + (D << 8) + E) = *(ram + (H << 8) + L);
E++;
if (!E)
D++;
L++;
if (!L)
H++;
C--;
if (C == 0xff)
B--;
(B | C) ? (F |= P_FLAG) : (F &= ~P_FLAG);
F &= ~(N_FLAG | H_FLAG);
#ifdef WANT_TIM
return(16L);
#endif
}
static long op_ldir() /* LDIR */
{
#ifdef WANT_TIM
register long t = -21L;
#endif
register WORD i;
register BYTE *s, *d;
i = (B << 8) + C;
d = ram + (D << 8) + E;
s = ram + (H << 8) + L;
do {
*d++ = *s++;
#ifdef WANT_TIM
t += 21L;
#endif
} while (--i);
B = C = 0;
D = (d - ram) >> 8;
E = d - ram;
H = (s - ram) >> 8;
L = s - ram;
F &= ~(N_FLAG | P_FLAG | H_FLAG);
#ifdef WANT_TIM
return(t + 16L);
#endif
}
static long op_ldd() /* LDD */
{
*(ram + (D << 8) + E) = *(ram + (H << 8) + L);
E--;
if (E == 0xff)
D--;
L--;
if (L == 0xff)
H--;
C--;
if (C == 0xff)
B--;
(B | C) ? (F |= P_FLAG) : (F &= ~P_FLAG);
F &= ~(N_FLAG | H_FLAG);
#ifdef WANT_TIM
return(16L);
#endif
}
static long op_lddr() /* LDDR */
{
#ifdef WANT_TIM
register long t = -21L;
#endif
register WORD i;
register BYTE *s, *d;
i = (B << 8) + C;
d = ram + (D << 8) + E;
s = ram + (H << 8) + L;
do {
*d-- = *s--;
#ifdef WANT_TIM
t += 21L;
#endif
} while (--i);
B = C = 0;
D = (d - ram) >> 8;
E = d - ram;
H = (s - ram) >> 8;
L = s - ram;
F &= ~(N_FLAG | P_FLAG | H_FLAG);
#ifdef WANT_TIM
return(t + 16L);
#endif
}
static long op_cpi() /* CPI */
{ /* H flag isn't set here ! */
register BYTE i;
i = A - *(ram + (H << 8) + L);
L++;
if (!L)
H++;
C--;
if (C == 0xff)
B--;
F |= N_FLAG;
(B | C) ? (F |= P_FLAG) : (F &= ~P_FLAG);
(i) ? (F &= ~Z_FLAG) : (F |= Z_FLAG);
(i & 128) ? (F |= S_FLAG) : (F &= ~S_FLAG);
#ifdef WANT_TIM
return(16L);
#endif
}
static long op_cpir() /* CPIR */
{ /* H flag isn't set here ! */
#ifdef WANT_TIM
register long t = -21L;
#endif
register BYTE *s;
register BYTE d;
register WORD i;
i = (B << 8) + C;
s = ram + (H << 8) + L;
do {
d = A - *s++;
#ifdef WANT_TIM
t += 21L;
#endif
} while (--i && d);
F |= N_FLAG;
B = i >> 8;
C = i;
H = (s - ram) >> 8;
L = s - ram;
(i) ? (F |= P_FLAG) : (F &= ~P_FLAG);
(d) ? (F &= ~Z_FLAG) : (F |= Z_FLAG);
(d & 128) ? (F |= S_FLAG) : (F &= ~S_FLAG);
#ifdef WANT_TIM
return(t + 16L);
#endif
}
static long op_cpdop() /* CPD */
{ /* H flag isn't set here ! */
register BYTE i;
i = A - *(ram + (H << 8) + L);
L--;
if (L == 0xff)
H--;
C--;
if (C == 0xff)
B--;
F |= N_FLAG;
(B | C) ? (F |= P_FLAG) : (F &= ~P_FLAG);
(i) ? (F &= ~Z_FLAG) : (F |= Z_FLAG);
(i & 128) ? (F |= S_FLAG) : (F &= ~S_FLAG);
#ifdef WANT_TIM
return(16L);
#endif
}
static long op_cpdr() /* CPDR */
{ /* H flag isn't set here ! */
#ifdef WANT_TIM
register long t = -21L;
#endif
register BYTE *s;
register BYTE d;
register WORD i;
i = (B << 8) + C;
s = ram + (H << 8) + L;
do {
d = A - *s--;
#ifdef WANT_TIM
t += 21L;
#endif
} while (--i && d);
F |= N_FLAG;
B = i >> 8;
C = i;
H = (s - ram) >> 8;
L = s - ram;
(i) ? (F |= P_FLAG) : (F &= ~P_FLAG);
(d) ? (F &= ~Z_FLAG) : (F |= Z_FLAG);
(d & 128) ? (F |= S_FLAG) : (F &= ~S_FLAG);
#ifdef WANT_TIM
return(t + 16L);
#endif
}
static long op_oprld() /* RLD (HL) */
{
register int i, j;
i = *(ram + (H << 8) + L);
j = A & 0x0f;
A = (A & 0xf0) | (i >> 4);
i = (i << 4) | j;
*(ram + (H << 8) + L) = i;
F &= ~(H_FLAG | N_FLAG);
(A) ? (F &= ~Z_FLAG) : (F |= Z_FLAG);
(A & 128) ? (F |= S_FLAG) : (F &= ~S_FLAG);
(parrity[A]) ? (F &= ~P_FLAG) : (F |= P_FLAG);
#ifdef WANT_TIM
return(18L);
#endif
}
static long op_oprrd() /* RRD (HL) */
{
register int i, j;
i = *(ram + (H << 8) + L);
j = A & 0x0f;
A = (A & 0xf0) | (i & 0x0f);
i = (i >> 4) | (j << 4);
*(ram + (H << 8) + L) = i;
F &= ~(H_FLAG | N_FLAG);
(A) ? (F &= ~Z_FLAG) : (F |= Z_FLAG);
(A & 128) ? (F |= S_FLAG) : (F &= ~S_FLAG);
(parrity[A]) ? (F &= ~P_FLAG) : (F |= P_FLAG);
#ifdef WANT_TIM
return(18L);
#endif
}