AltairZ80: Fix 8080 and Z80 CPU

This commit is contained in:
Peter Schorn 2024-07-16 16:22:22 +02:00 committed by Paul Koning
parent c831460ecb
commit 7b99876e1e
4 changed files with 376 additions and 122 deletions

View file

@ -1,6 +1,6 @@
/* altairz80_cpu.c: MITS Altair CPU (8080 and Z80) /* altairz80_cpu.c: MITS Altair CPU (8080 and Z80)
Copyright (c) 2002-2023, Peter Schorn Copyright (c) 2002-2024, Peter Schorn
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,11 @@
Based on work by Charles E Owen (c) 1997 Based on work by Charles E Owen (c) 1997
Code for Z80 CPU from Frank D. Cringle ((c) 1995 under GNU license) Code for Z80 CPU from Frank D. Cringle ((c) 1995 under GNU license)
Contributions from Thomas Eberhardt
- Fixed H flag handling for 8080 CPU
- Corrected parity flag computation for Z80 CPU for INI, OUTI, IND, OUTD,
INIR, OTIR, INDR and OTDR instructions
*/ */
#include "m68k/m68k.h" #include "m68k/m68k.h"
@ -53,31 +58,32 @@
#define FLAG_Z 64 #define FLAG_Z 64
#define FLAG_S 128 #define FLAG_S 128
#define SETFLAG(f,c) AF = (c) ? AF | FLAG_ ## f : AF & ~FLAG_ ## f #define SETFLAG(f,c) AF = (c) ? AF | FLAG_ ## f : AF & ~FLAG_ ## f
#define TSTFLAG(f) ((AF & FLAG_ ## f) != 0) #define TSTFLAG(f) ((AF & FLAG_ ## f) != 0)
#define TSTFLAG2(a, f) ((a & FLAG_ ## f) != 0) #define TSTFLAG2(a, f) ((a & FLAG_ ## f) != 0)
#define LOW_DIGIT(x) ((x) & 0xf) #define LOW_DIGIT(x) ((x) & 0xf)
#define HIGH_DIGIT(x) (((x) >> 4) & 0xf) #define HIGH_DIGIT(x) (((x) >> 4) & 0xf)
#define LOW_REGISTER(x) ((x) & 0xff) #define LOW_REGISTER(x) ((x) & 0xff)
#define HIGH_REGISTER(x) (((x) >> 8) & 0xff) #define HIGH_REGISTER(x) (((x) >> 8) & 0xff)
#define SET_LOW_REGISTER(x, v) x = (((x) & 0xff00) | ((v) & 0xff)) #define SET_LOW_REGISTER(x, v) x = (((x) & 0xff00) | ((v) & 0xff))
#define SET_HIGH_REGISTER(x, v) x = (((x) & 0xff) | (((v) & 0xff) << 8)) #define SET_HIGH_REGISTER(x, v) x = (((x) & 0xff) | (((v) & 0xff) << 8))
#define PARITY(x) parityTable[(x) & 0xff]
#define PARITY(x) parityTable[(x) & 0xff]
/* SET_PV and SET_PV2 are used to provide correct PARITY flag semantics for the 8080 in cases /* SET_PV and SET_PV2 are used to provide correct PARITY flag semantics for the 8080 in cases
where the Z80 uses the overflow flag where the Z80 uses the overflow flag.
*/ */
#define SET_PVS(s) ((chiptype == CHIP_TYPE_Z80) ? (((cbits >> 6) ^ (cbits >> 5)) & 4) : (PARITY(s))) #define SET_PVS(s) ((chiptype == CHIP_TYPE_Z80) ? (((cbits >> 6) ^ (cbits >> 5)) & 4) : (PARITY(s)))
#define SET_PV (SET_PVS(sum)) #define SET_PV (SET_PVS(sum))
#define SET_PV2(x) ((chiptype == CHIP_TYPE_Z80) ? (((temp == (x)) << 2)) : (PARITY(temp))) #define SET_PV2(x) ((chiptype == CHIP_TYPE_Z80) ? (((temp == (x)) << 2)) : (PARITY(temp)))
/* CHECK_CPU_8080 must be invoked whenever a Z80 only instruction is executed /* CHECK_CPU_8080 must be invoked whenever a Z80 only instruction is executed
In case a Z80 instruction is executed on an 8080 the following two cases exist: In case a Z80 instruction is executed on an 8080 there are two cases:
1) Trapping is enabled: execution stops 1) Trapping is enabled: execution stops
2) Trapping is not enabled: decoding continues with the next byte, i.e. interpret as NOP 2) Trapping is not enabled: decoding continues with the next byte, i.e. interpret as NOP
Note: in some cases different instructions need to be chosen on 8080 Note: in some cases different instructions need to be chosen on an 8080.
*/ */
#define CHECK_CPU_8080 \ #define CHECK_CPU_8080 \
if ((chiptype == CHIP_TYPE_8080) && (cpu_unit.flags & UNIT_CPU_OPSTOP)) { \ if ((chiptype == CHIP_TYPE_8080) && (cpu_unit.flags & UNIT_CPU_OPSTOP)) { \
@ -268,8 +274,8 @@ static uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue
static int32 pcq_p = 0; /* PC queue ptr */ static int32 pcq_p = 0; /* PC queue ptr */
static REG *pcq_r = NULL; /* PC queue reg ptr */ static REG *pcq_r = NULL; /* PC queue reg ptr */
#define HIST_MIN 16 #define HIST_MIN 16
#define HIST_MAX 8192 #define HIST_MAX 8192
typedef struct { typedef struct {
uint8 valid; uint8 valid;
@ -288,13 +294,13 @@ typedef struct {
t_value op[INST_MAX_BYTES]; t_value op[INST_MAX_BYTES];
} insthist_t; } insthist_t;
static uint32 hst_p = 0; /* history pointer */ static uint32 hst_p = 0; /* history pointer */
static uint32 hst_lnt = 0; /* history length */ static uint32 hst_lnt = 0; /* history length */
static insthist_t *hst = NULL; /* instruction history */ static insthist_t *hst = NULL; /* instruction history */
uint32 m68k_registers[M68K_REG_CPU_TYPE + 1]; /* M68K CPU registers */ uint32 m68k_registers[M68K_REG_CPU_TYPE + 1]; /* M68K CPU registers */
uint32 mmiobase = 0xff0000; /* M68K MMIO base address */ uint32 mmiobase = 0xff0000; /* M68K MMIO base address */
uint32 mmiosize = 0x10000; /* M68K MMIO window size */ uint32 mmiosize = 0x10000; /* M68K MMIO window size */
uint32 m68kvariant = M68K_CPU_TYPE_68000; uint32 m68kvariant = M68K_CPU_TYPE_68000;
/* data structure for IN/OUT instructions */ /* data structure for IN/OUT instructions */
@ -2093,7 +2099,6 @@ void PutByteDMA(const uint32 Addr, const uint32 Value) {
/* Macros for the IN/OUT instructions INI/INIR/IND/INDR/OUTI/OTIR/OUTD/OTDR /* Macros for the IN/OUT instructions INI/INIR/IND/INDR/OUTI/OTIR/OUTD/OTDR
Pre condition Pre condition
temp == value of register B at entry of the instruction
acu == value of transferred byte (IN or OUT) acu == value of transferred byte (IN or OUT)
Post condition Post condition
F is set correctly F is set correctly
@ -2107,15 +2112,18 @@ void PutByteDMA(const uint32 Addr, const uint32 Value) {
x == L for OUTI and OUTD x == L for OUTI and OUTD
x == (C - 1) & 0xff for IND x == (C - 1) & 0xff for IND
*/ */
#define INOUTFLAGS(syxz, x) \ #define INOUTFLAGS_ZERO(x) \
AF = (AF & 0xff00) | (syxz) | /* SF, YF, XF, ZF */ \ AF = (AF & 0xff00) | (FLAG_Z) | /* SF, YF, XF, ZF */ \
((acu & 0x80) >> 6) | /* NF */ \ ((acu & 0x80) >> 6) | /* NF */ \
((acu + (x)) > 0xff ? (FLAG_C | FLAG_H) : 0) | /* CF, HF */ \ ((acu + (x)) > 0xff ? (FLAG_C | FLAG_H) : 0) | /* CF, HF */ \
parityTable[((acu + (x)) & 7) ^ temp] /* PF */ parityTable[((acu + (x)) & 7)] /* PF */
#define INOUTFLAGS_ZERO(x) INOUTFLAGS(FLAG_Z, x)
#define INOUTFLAGS_NONZERO(x) \ #define INOUTFLAGS_NONZERO(x) \
INOUTFLAGS((HIGH_REGISTER(BC) & 0xa8) | ((HIGH_REGISTER(BC) == 0) << 6), x) AF = (AF & 0xff00) | (HIGH_REGISTER(BC) & 0xa8) | \
((HIGH_REGISTER(BC) == 0) << 6) | /* SF, YF, XF, ZF */ \
((acu & 0x80) >> 6) | /* NF */ \
((acu + (x)) > 0xff ? (FLAG_C | FLAG_H) : 0) | /* CF, HF */ \
parityTable[((acu + (x)) & 7) ^ HIGH_REGISTER(BC)] /* PF */
int32 switch_cpu_now = TRUE; int32 switch_cpu_now = TRUE;
@ -2422,6 +2430,8 @@ static t_stat sim_instr_mmu (void) {
BC -= 0x100; BC -= 0x100;
temp = HIGH_REGISTER(BC); temp = HIGH_REGISTER(BC);
AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */ AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x06: /* LD B,nn */ case 0x06: /* LD B,nn */
@ -2431,8 +2441,11 @@ static t_stat sim_instr_mmu (void) {
case 0x07: /* RLCA */ case 0x07: /* RLCA */
tStates += 4; /* RLC 4 */ tStates += 4; /* RLC 4 */
AF = ((AF >> 7) & 0x0128) | ((AF << 1) & ~0x1ff) | temp = ((AF >> 7) & 0x0128) | ((AF << 1) & ~0x1ff) |
(AF & 0xc4) | ((AF >> 15) & 1); (AF & 0xc4) | ((AF >> 15) & 1);
if (chiptype == CHIP_TYPE_8080)
temp = (temp & ~0x10) | (AF & 0x10);
AF = temp;
break; break;
case 0x08: /* EX AF,AF' */ case 0x08: /* EX AF,AF' */
@ -2448,7 +2461,10 @@ static t_stat sim_instr_mmu (void) {
HL &= ADDRMASK; HL &= ADDRMASK;
BC &= ADDRMASK; BC &= ADDRMASK;
sum = HL + BC; sum = HL + BC;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ BC ^ sum) >> 8]; temp = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ BC ^ sum) >> 8];
if (chiptype == CHIP_TYPE_8080)
temp = (temp & ~0x10) | (AF & 0x10);
AF = temp;
HL = sum; HL = sum;
break; break;
@ -2475,6 +2491,8 @@ static t_stat sim_instr_mmu (void) {
temp = LOW_REGISTER(BC) - 1; temp = LOW_REGISTER(BC) - 1;
SET_LOW_REGISTER(BC, temp); SET_LOW_REGISTER(BC, temp);
AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f); AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x0e: /* LD C,nn */ case 0x0e: /* LD C,nn */
@ -2484,7 +2502,10 @@ static t_stat sim_instr_mmu (void) {
case 0x0f: /* RRCA */ case 0x0f: /* RRCA */
tStates += 4; /* RRC 4 */ tStates += 4; /* RRC 4 */
AF = (AF & 0xc4) | rrcaTable[HIGH_REGISTER(AF)]; temp = (AF & 0xc4) | rrcaTable[HIGH_REGISTER(AF)];
if (chiptype == CHIP_TYPE_8080)
temp = (temp & ~0x10) | (AF & 0x10);
AF = temp;
break; break;
case 0x10: /* DJNZ dd */ case 0x10: /* DJNZ dd */
@ -2530,6 +2551,8 @@ static t_stat sim_instr_mmu (void) {
DE -= 0x100; DE -= 0x100;
temp = HIGH_REGISTER(DE); temp = HIGH_REGISTER(DE);
AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */ AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x16: /* LD D,nn */ case 0x16: /* LD D,nn */
@ -2539,8 +2562,11 @@ static t_stat sim_instr_mmu (void) {
case 0x17: /* RLA */ case 0x17: /* RLA */
tStates += 4; /* RAL 4 */ tStates += 4; /* RAL 4 */
AF = ((AF << 8) & 0x0100) | ((AF >> 7) & 0x28) | ((AF << 1) & ~0x01ff) | temp = ((AF << 8) & 0x0100) | ((AF >> 7) & 0x28) | ((AF << 1) & ~0x01ff) |
(AF & 0xc4) | ((AF >> 15) & 1); (AF & 0xc4) | ((AF >> 15) & 1);
if (chiptype == CHIP_TYPE_8080)
temp = (temp & ~0x10) | (AF & 0x10);
AF = temp;
break; break;
case 0x18: /* JR dd */ case 0x18: /* JR dd */
@ -2555,7 +2581,10 @@ static t_stat sim_instr_mmu (void) {
HL &= ADDRMASK; HL &= ADDRMASK;
DE &= ADDRMASK; DE &= ADDRMASK;
sum = HL + DE; sum = HL + DE;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ DE ^ sum) >> 8]; temp = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ DE ^ sum) >> 8];
if (chiptype == CHIP_TYPE_8080)
temp = (temp & ~0x10) | (AF & 0x10);
AF = temp;
HL = sum; HL = sum;
break; break;
@ -2582,6 +2611,8 @@ static t_stat sim_instr_mmu (void) {
temp = LOW_REGISTER(DE) - 1; temp = LOW_REGISTER(DE) - 1;
SET_LOW_REGISTER(DE, temp); SET_LOW_REGISTER(DE, temp);
AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f); AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x1e: /* LD E,nn */ case 0x1e: /* LD E,nn */
@ -2591,7 +2622,10 @@ static t_stat sim_instr_mmu (void) {
case 0x1f: /* RRA */ case 0x1f: /* RRA */
tStates += 4; /* RAR 4 */ tStates += 4; /* RAR 4 */
AF = ((AF & 1) << 15) | (AF & 0xc4) | rraTable[HIGH_REGISTER(AF)]; temp = ((AF & 1) << 15) | (AF & 0xc4) | rraTable[HIGH_REGISTER(AF)];
if (chiptype == CHIP_TYPE_8080)
temp = (temp & ~0x10) | (AF & 0x10);
AF = temp;
break; break;
case 0x20: /* JR NZ,dd */ case 0x20: /* JR NZ,dd */
@ -2639,6 +2673,8 @@ static t_stat sim_instr_mmu (void) {
HL -= 0x100; HL -= 0x100;
temp = HIGH_REGISTER(HL); temp = HIGH_REGISTER(HL);
AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */ AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x26: /* LD H,nn */ case 0x26: /* LD H,nn */
@ -2651,7 +2687,7 @@ static t_stat sim_instr_mmu (void) {
acu = HIGH_REGISTER(AF); acu = HIGH_REGISTER(AF);
temp = LOW_DIGIT(acu); temp = LOW_DIGIT(acu);
cbits = TSTFLAG(C); cbits = TSTFLAG(C);
if (TSTFLAG(N)) { /* last operation was a subtract */ if (chiptype == CHIP_TYPE_Z80 && TSTFLAG(N)) { /* last operation was a subtract */
int hd = cbits || acu > 0x99; int hd = cbits || acu > 0x99;
if (TSTFLAG(H) || (temp > 9)) { /* adjust low digit */ if (TSTFLAG(H) || (temp > 9)) { /* adjust low digit */
if (temp > 5) { if (temp > 5) {
@ -2691,7 +2727,10 @@ static t_stat sim_instr_mmu (void) {
tStates += (chiptype == CHIP_TYPE_8080 ? 10 : 11); /* DAD H 10 */ tStates += (chiptype == CHIP_TYPE_8080 ? 10 : 11); /* DAD H 10 */
HL &= ADDRMASK; HL &= ADDRMASK;
sum = HL + HL; sum = HL + HL;
AF = (AF & ~0x3b) | cbitsDup16Table[sum >> 8]; temp = (AF & ~0x3b) | cbitsDup16Table[sum >> 8];
if (chiptype == CHIP_TYPE_8080)
temp = (temp & ~0x10) | (AF & 0x10);
AF = temp;
HL = sum; HL = sum;
break; break;
@ -2720,6 +2759,8 @@ static t_stat sim_instr_mmu (void) {
temp = LOW_REGISTER(HL) - 1; temp = LOW_REGISTER(HL) - 1;
SET_LOW_REGISTER(HL, temp); SET_LOW_REGISTER(HL, temp);
AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f); AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x2e: /* LD L,nn */ case 0x2e: /* LD L,nn */
@ -2729,7 +2770,10 @@ static t_stat sim_instr_mmu (void) {
case 0x2f: /* CPL */ case 0x2f: /* CPL */
tStates += 4; /* CMA 4 */ tStates += 4; /* CMA 4 */
AF = (~AF & ~0xff) | (AF & 0xc5) | ((~AF >> 8) & 0x28) | 0x12; temp = (~AF & ~0xff) | (AF & 0xc5) | ((~AF >> 8) & 0x28) | 0x12;
if (chiptype == CHIP_TYPE_8080)
temp = (temp & ~0x10) | (AF & 0x10);
AF = temp;
break; break;
case 0x30: /* JR NC,dd */ case 0x30: /* JR NC,dd */
@ -2779,6 +2823,8 @@ static t_stat sim_instr_mmu (void) {
temp = GetBYTE(HL) - 1; temp = GetBYTE(HL) - 1;
PutBYTE(HL, temp); PutBYTE(HL, temp);
AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f); AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x36: /* LD (HL),nn */ case 0x36: /* LD (HL),nn */
@ -2789,7 +2835,10 @@ static t_stat sim_instr_mmu (void) {
case 0x37: /* SCF */ case 0x37: /* SCF */
tStates += 4; /* STC 4 */ tStates += 4; /* STC 4 */
AF = (AF & ~0x3b) | ((AF >> 8) & 0x28) | 1; temp = (AF & ~0x3b) | ((AF >> 8) & 0x28) | 1;
if (chiptype == CHIP_TYPE_8080)
temp = (temp & ~0x10) | (AF & 0x10);
AF = temp;
break; break;
case 0x38: /* JR C,dd */ case 0x38: /* JR C,dd */
@ -2811,7 +2860,10 @@ static t_stat sim_instr_mmu (void) {
HL &= ADDRMASK; HL &= ADDRMASK;
SP &= ADDRMASK; SP &= ADDRMASK;
sum = HL + SP; sum = HL + SP;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ SP ^ sum) >> 8]; temp = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ SP ^ sum) >> 8];
if (chiptype == CHIP_TYPE_8080)
temp = (temp & ~0x10) | (AF & 0x10);
AF = temp;
HL = sum; HL = sum;
break; break;
@ -2840,6 +2892,8 @@ static t_stat sim_instr_mmu (void) {
AF -= 0x100; AF -= 0x100;
temp = HIGH_REGISTER(AF); temp = HIGH_REGISTER(AF);
AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */ AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x3e: /* LD A,nn */ case 0x3e: /* LD A,nn */
@ -2849,7 +2903,10 @@ static t_stat sim_instr_mmu (void) {
case 0x3f: /* CCF */ case 0x3f: /* CCF */
tStates += 4; /* CMC 4 */ tStates += 4; /* CMC 4 */
AF = (AF & ~0x3b) | ((AF >> 8) & 0x28) | ((AF & 1) << 4) | (~AF & 1); temp = (AF & ~0x3b) | ((AF >> 8) & 0x28) | ((AF & 1) << 4) | (~AF & 1);
if (chiptype == CHIP_TYPE_8080)
temp = (temp & ~0x10) | (AF & 0x10);
AF = temp;
break; break;
case 0x40: /* LD B,B */ case 0x40: /* LD B,B */
@ -3332,6 +3389,8 @@ static t_stat sim_instr_mmu (void) {
sum = acu - temp; sum = acu - temp;
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x91: /* SUB C */ case 0x91: /* SUB C */
@ -3341,6 +3400,8 @@ static t_stat sim_instr_mmu (void) {
sum = acu - temp; sum = acu - temp;
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x92: /* SUB D */ case 0x92: /* SUB D */
@ -3350,6 +3411,8 @@ static t_stat sim_instr_mmu (void) {
sum = acu - temp; sum = acu - temp;
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x93: /* SUB E */ case 0x93: /* SUB E */
@ -3359,6 +3422,8 @@ static t_stat sim_instr_mmu (void) {
sum = acu - temp; sum = acu - temp;
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x94: /* SUB H */ case 0x94: /* SUB H */
@ -3368,6 +3433,8 @@ static t_stat sim_instr_mmu (void) {
sum = acu - temp; sum = acu - temp;
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x95: /* SUB L */ case 0x95: /* SUB L */
@ -3377,6 +3444,8 @@ static t_stat sim_instr_mmu (void) {
sum = acu - temp; sum = acu - temp;
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x96: /* SUB (HL) */ case 0x96: /* SUB (HL) */
@ -3387,11 +3456,13 @@ static t_stat sim_instr_mmu (void) {
sum = acu - temp; sum = acu - temp;
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x97: /* SUB A */ case 0x97: /* SUB A */
tStates += 4; /* SUB A 4 */ tStates += 4; /* SUB A 4 */
AF = (chiptype == CHIP_TYPE_Z80) ? 0x42 : 0x46; AF = (chiptype == CHIP_TYPE_Z80) ? 0x42 : 0x56;
break; break;
case 0x98: /* SBC A,B */ case 0x98: /* SBC A,B */
@ -3401,6 +3472,8 @@ static t_stat sim_instr_mmu (void) {
sum = acu - temp - TSTFLAG(C); sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x99: /* SBC A,C */ case 0x99: /* SBC A,C */
@ -3410,6 +3483,8 @@ static t_stat sim_instr_mmu (void) {
sum = acu - temp - TSTFLAG(C); sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x9a: /* SBC A,D */ case 0x9a: /* SBC A,D */
@ -3419,6 +3494,8 @@ static t_stat sim_instr_mmu (void) {
sum = acu - temp - TSTFLAG(C); sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x9b: /* SBC A,E */ case 0x9b: /* SBC A,E */
@ -3428,6 +3505,8 @@ static t_stat sim_instr_mmu (void) {
sum = acu - temp - TSTFLAG(C); sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x9c: /* SBC A,H */ case 0x9c: /* SBC A,H */
@ -3437,6 +3516,8 @@ static t_stat sim_instr_mmu (void) {
sum = acu - temp - TSTFLAG(C); sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x9d: /* SBC A,L */ case 0x9d: /* SBC A,L */
@ -3446,6 +3527,8 @@ static t_stat sim_instr_mmu (void) {
sum = acu - temp - TSTFLAG(C); sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x9e: /* SBC A,(HL) */ case 0x9e: /* SBC A,(HL) */
@ -3456,53 +3539,82 @@ static t_stat sim_instr_mmu (void) {
sum = acu - temp - TSTFLAG(C); sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x9f: /* SBC A,A */ case 0x9f: /* SBC A,A */
tStates += 4; /* SBB A 4 */ tStates += 4; /* SBB A 4 */
cbits = -TSTFLAG(C); cbits = -TSTFLAG(C);
AF = subTable[cbits & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PVS(cbits)); AF = subTable[cbits & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PVS(cbits));
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0xa0: /* AND B */ case 0xa0: /* AND B */
tStates += 4; /* ANA B 4 */ tStates += 4; /* ANA B 4 */
AF = andTable[((AF & BC) >> 8) & 0xff]; acu = andTable[((AF & BC) >> 8) & 0xff];
if (chiptype == CHIP_TYPE_8080 && ((AF | BC) & 0x0800) == 0)
acu &= ~0x10;
AF = acu;
break; break;
case 0xa1: /* AND C */ case 0xa1: /* AND C */
tStates += 4; /* ANA C 4 */ tStates += 4; /* ANA C 4 */
AF = andTable[((AF >> 8) & BC) & 0xff]; acu = andTable[((AF >> 8) & BC) & 0xff];
if (chiptype == CHIP_TYPE_8080 && (((AF >> 8) | BC) & 0x08) == 0)
acu &= ~0x10;
AF = acu;
break; break;
case 0xa2: /* AND D */ case 0xa2: /* AND D */
tStates += 4; /* ANA D 4 */ tStates += 4; /* ANA D 4 */
AF = andTable[((AF & DE) >> 8) & 0xff]; acu = andTable[((AF & DE) >> 8) & 0xff];
if (chiptype == CHIP_TYPE_8080 && ((AF | DE) & 0x0800) == 0)
acu &= ~0x10;
AF = acu;
break; break;
case 0xa3: /* AND E */ case 0xa3: /* AND E */
tStates += 4; /* ANA E 4 */ tStates += 4; /* ANA E 4 */
AF = andTable[((AF >> 8) & DE) & 0xff]; acu = andTable[((AF >> 8) & DE) & 0xff];
if (chiptype == CHIP_TYPE_8080 && (((AF >> 8) | DE) & 0x08) == 0)
acu &= ~0x10;
AF = acu;
break; break;
case 0xa4: /* AND H */ case 0xa4: /* AND H */
tStates += 4; /* ANA H 4 */ tStates += 4; /* ANA H 4 */
AF = andTable[((AF & HL) >> 8) & 0xff]; acu = andTable[((AF & HL) >> 8) & 0xff];
if (chiptype == CHIP_TYPE_8080 && ((AF | HL) & 0x0800) == 0)
acu &= ~0x10;
AF = acu;
break; break;
case 0xa5: /* AND L */ case 0xa5: /* AND L */
tStates += 4; /* ANA L 4 */ tStates += 4; /* ANA L 4 */
AF = andTable[((AF >> 8) & HL) & 0xff]; acu = andTable[((AF >> 8) & HL) & 0xff];
if (chiptype == CHIP_TYPE_8080 && (((AF >> 8) | HL) & 0x08) == 0)
acu &= ~0x10;
AF = acu;
break; break;
case 0xa6: /* AND (HL) */ case 0xa6: /* AND (HL) */
tStates += 7; /* ANA M 7 */ tStates += 7; /* ANA M 7 */
CHECK_BREAK_BYTE(HL); CHECK_BREAK_BYTE(HL);
AF = andTable[((AF >> 8) & GetBYTE(HL)) & 0xff]; temp = GetBYTE(HL);
acu = andTable[((AF >> 8) & temp) & 0xff];
if (chiptype == CHIP_TYPE_8080 && (((AF >> 8) | temp) & 0x08) == 0)
acu &= ~0x10;
AF = acu;
break; break;
case 0xa7: /* AND A */ case 0xa7: /* AND A */
tStates += 4; /* ANA A 4 */ tStates += 4; /* ANA A 4 */
AF = andTable[(AF >> 8) & 0xff]; acu = andTable[(AF >> 8) & 0xff];
if (chiptype == CHIP_TYPE_8080 && (AF & 0x0800) == 0)
acu &= ~0x10;
AF = acu;
break; break;
case 0xa8: /* XOR B */ case 0xa8: /* XOR B */
@ -3596,6 +3708,8 @@ static t_stat sim_instr_mmu (void) {
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) |
(SET_PV) | cbits2Table[cbits & 0x1ff]; (SET_PV) | cbits2Table[cbits & 0x1ff];
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0xb9: /* CP C */ case 0xb9: /* CP C */
@ -3607,6 +3721,8 @@ static t_stat sim_instr_mmu (void) {
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) |
(SET_PV) | cbits2Table[cbits & 0x1ff]; (SET_PV) | cbits2Table[cbits & 0x1ff];
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0xba: /* CP D */ case 0xba: /* CP D */
@ -3618,6 +3734,8 @@ static t_stat sim_instr_mmu (void) {
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) |
(SET_PV) | cbits2Table[cbits & 0x1ff]; (SET_PV) | cbits2Table[cbits & 0x1ff];
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0xbb: /* CP E */ case 0xbb: /* CP E */
@ -3629,6 +3747,8 @@ static t_stat sim_instr_mmu (void) {
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) |
(SET_PV) | cbits2Table[cbits & 0x1ff]; (SET_PV) | cbits2Table[cbits & 0x1ff];
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0xbc: /* CP H */ case 0xbc: /* CP H */
@ -3640,6 +3760,8 @@ static t_stat sim_instr_mmu (void) {
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) |
(SET_PV) | cbits2Table[cbits & 0x1ff]; (SET_PV) | cbits2Table[cbits & 0x1ff];
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0xbd: /* CP L */ case 0xbd: /* CP L */
@ -3651,6 +3773,8 @@ static t_stat sim_instr_mmu (void) {
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) |
(SET_PV) | cbits2Table[cbits & 0x1ff]; (SET_PV) | cbits2Table[cbits & 0x1ff];
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0xbe: /* CP (HL) */ case 0xbe: /* CP (HL) */
@ -3663,11 +3787,13 @@ static t_stat sim_instr_mmu (void) {
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) |
(SET_PV) | cbits2Table[cbits & 0x1ff]; (SET_PV) | cbits2Table[cbits & 0x1ff];
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0xbf: /* CP A */ case 0xbf: /* CP A */
tStates += 4; /* CMP A 4 */ tStates += 4; /* CMP A 4 */
SET_LOW_REGISTER(AF, (HIGH_REGISTER(AF) & 0x28) | (chiptype == CHIP_TYPE_Z80 ? 0x42 : 0x46)); SET_LOW_REGISTER(AF, (HIGH_REGISTER(AF) & 0x28) | (chiptype == CHIP_TYPE_Z80 ? 0x42 : 0x56));
break; break;
case 0xc0: /* RET NZ */ case 0xc0: /* RET NZ */
@ -3990,6 +4116,8 @@ static t_stat sim_instr_mmu (void) {
sum = acu - temp; sum = acu - temp;
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0xd7: /* RST 10H */ case 0xd7: /* RST 10H */
@ -4781,6 +4909,8 @@ static t_stat sim_instr_mmu (void) {
sum = acu - temp - TSTFLAG(C); sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0xdf: /* RST 18H */ case 0xdf: /* RST 18H */
@ -4832,7 +4962,11 @@ static t_stat sim_instr_mmu (void) {
case 0xe6: /* AND nn */ case 0xe6: /* AND nn */
tStates += 7; /* ANI nn 7 */ tStates += 7; /* ANI nn 7 */
AF = andTable[((AF >> 8) & RAM_PP(PC)) & 0xff]; temp = RAM_PP(PC);
acu = andTable[((AF >> 8) & temp) & 0xff];
if (chiptype == CHIP_TYPE_8080 && (((AF >> 8) | temp) & 0x08) == 0)
acu &= ~0x10;
AF = acu;
break; break;
case 0xe7: /* RST 20H */ case 0xe7: /* RST 20H */
@ -5266,7 +5400,6 @@ static t_stat sim_instr_mmu (void) {
acu = in(LOW_REGISTER(BC)); acu = in(LOW_REGISTER(BC));
PutBYTE(HL, acu); PutBYTE(HL, acu);
++HL; ++HL;
temp = HIGH_REGISTER(BC);
BC -= 0x100; BC -= 0x100;
INOUTFLAGS_NONZERO((LOW_REGISTER(BC) + 1) & 0xff); INOUTFLAGS_NONZERO((LOW_REGISTER(BC) + 1) & 0xff);
break; break;
@ -5285,7 +5418,6 @@ static t_stat sim_instr_mmu (void) {
acu = GetBYTE(HL); acu = GetBYTE(HL);
out(LOW_REGISTER(BC), acu); out(LOW_REGISTER(BC), acu);
++HL; ++HL;
temp = HIGH_REGISTER(BC);
BC -= 0x100; BC -= 0x100;
INOUTFLAGS_NONZERO(LOW_REGISTER(HL)); INOUTFLAGS_NONZERO(LOW_REGISTER(HL));
break; break;
@ -5328,7 +5460,6 @@ static t_stat sim_instr_mmu (void) {
acu = in(LOW_REGISTER(BC)); acu = in(LOW_REGISTER(BC));
PutBYTE(HL, acu); PutBYTE(HL, acu);
--HL; --HL;
temp = HIGH_REGISTER(BC);
BC -= 0x100; BC -= 0x100;
INOUTFLAGS_NONZERO((LOW_REGISTER(BC) - 1) & 0xff); INOUTFLAGS_NONZERO((LOW_REGISTER(BC) - 1) & 0xff);
break; break;
@ -5339,7 +5470,6 @@ static t_stat sim_instr_mmu (void) {
acu = GetBYTE(HL); acu = GetBYTE(HL);
out(LOW_REGISTER(BC), acu); out(LOW_REGISTER(BC), acu);
--HL; --HL;
temp = HIGH_REGISTER(BC);
BC -= 0x100; BC -= 0x100;
INOUTFLAGS_NONZERO(LOW_REGISTER(HL)); INOUTFLAGS_NONZERO(LOW_REGISTER(HL));
break; break;
@ -5396,7 +5526,6 @@ static t_stat sim_instr_mmu (void) {
PutBYTE(HL, acu); PutBYTE(HL, acu);
++HL; ++HL;
} while (--temp); } while (--temp);
temp = HIGH_REGISTER(BC);
SET_HIGH_REGISTER(BC, 0); SET_HIGH_REGISTER(BC, 0);
INOUTFLAGS_ZERO((LOW_REGISTER(BC) + 1) & 0xff); INOUTFLAGS_ZERO((LOW_REGISTER(BC) + 1) & 0xff);
break; break;
@ -5414,7 +5543,6 @@ static t_stat sim_instr_mmu (void) {
out(LOW_REGISTER(BC), acu); out(LOW_REGISTER(BC), acu);
++HL; ++HL;
} while (--temp); } while (--temp);
temp = HIGH_REGISTER(BC);
SET_HIGH_REGISTER(BC, 0); SET_HIGH_REGISTER(BC, 0);
INOUTFLAGS_ZERO(LOW_REGISTER(HL)); INOUTFLAGS_ZERO(LOW_REGISTER(HL));
break; break;
@ -5471,7 +5599,6 @@ static t_stat sim_instr_mmu (void) {
PutBYTE(HL, acu); PutBYTE(HL, acu);
--HL; --HL;
} while (--temp); } while (--temp);
temp = HIGH_REGISTER(BC);
SET_HIGH_REGISTER(BC, 0); SET_HIGH_REGISTER(BC, 0);
INOUTFLAGS_ZERO((LOW_REGISTER(BC) - 1) & 0xff); INOUTFLAGS_ZERO((LOW_REGISTER(BC) - 1) & 0xff);
break; break;
@ -5489,7 +5616,6 @@ static t_stat sim_instr_mmu (void) {
out(LOW_REGISTER(BC), acu); out(LOW_REGISTER(BC), acu);
--HL; --HL;
} while (--temp); } while (--temp);
temp = HIGH_REGISTER(BC);
SET_HIGH_REGISTER(BC, 0); SET_HIGH_REGISTER(BC, 0);
INOUTFLAGS_ZERO(LOW_REGISTER(HL)); INOUTFLAGS_ZERO(LOW_REGISTER(HL));
break; break;
@ -5545,7 +5671,7 @@ static t_stat sim_instr_mmu (void) {
case 0xf5: /* PUSH AF */ case 0xf5: /* PUSH AF */
tStates += 11; /* PUSH PSW 11 */ tStates += 11; /* PUSH PSW 11 */
CHECK_BREAK_WORD(SP - 2); CHECK_BREAK_WORD(SP - 2);
PUSH(AF); PUSH(chiptype == CHIP_TYPE_8080 ? (AF & ~0x28) | 0x02 : AF);
break; break;
case 0xf6: /* OR nn */ case 0xf6: /* OR nn */
@ -6323,6 +6449,8 @@ static t_stat sim_instr_mmu (void) {
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) |
(SET_PV) | cbits2Table[cbits & 0x1ff]; (SET_PV) | cbits2Table[cbits & 0x1ff];
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0xff: /* RST 38H */ case 0xff: /* RST 38H */
@ -6568,22 +6696,21 @@ typedef struct {
} CPUFLAG; } CPUFLAG;
const static CPUFLAG cpuflags8080[] = { const static CPUFLAG cpuflags8080[] = {
{1 << 7, "S"}, {FLAG_S, "S"},
{1 << 6, "Z"}, {FLAG_Z, "Z"},
{1 << 4, "H"}, {FLAG_H, "H"},
{1 << 3, "P"}, {FLAG_P, "P"},
{1 << 1, "N"}, {FLAG_C, "C"},
{1 << 0, "C"},
{0, 0} /* last mask must be 0 */ {0, 0} /* last mask must be 0 */
}; };
const static CPUFLAG cpuflagsZ80[] = { const static CPUFLAG cpuflagsZ80[] = {
{1 << 7, "S"}, {FLAG_S, "S"},
{1 << 6, "Z"}, {FLAG_Z, "Z"},
{1 << 4, "H"}, {FLAG_H, "H"},
{1 << 3, "V"}, {FLAG_P, "V"},
{1 << 1, "N"}, {FLAG_N, "N"},
{1 << 0, "C"}, {FLAG_C, "C"},
{0, 0} /* last mask must be 0 */ {0, 0} /* last mask must be 0 */
}; };

View file

@ -1,6 +1,6 @@
/* altairz80_cpu_opt.c: MITS Altair CPU (8080 and Z80) /* altairz80_cpu_opt.c: MITS Altair CPU (8080 and Z80)
Copyright (c) 2002-2023, Peter Schorn Copyright (c) 2002-2024, Peter Schorn
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,11 @@
Based on work by Charles E Owen (c) 1997 Based on work by Charles E Owen (c) 1997
Code for Z80 CPU from Frank D. Cringle ((c) 1995 under GNU license) Code for Z80 CPU from Frank D. Cringle ((c) 1995 under GNU license)
Contributions from Thomas Eberhardt
- Fixed H flag handling for 8080 CPU
- Corrected parity flag computation for Z80 CPU for INI, OUTI, IND, OUTD,
INIR, OTIR, INDR and OTDR instructions
*/ */
#include "altairz80_defs.h" #include "altairz80_defs.h"
@ -36,8 +41,8 @@
#define FLAG_Z 64 #define FLAG_Z 64
#define FLAG_S 128 #define FLAG_S 128
#define SETFLAG(f,c) AF = (c) ? AF | FLAG_ ## f : AF & ~FLAG_ ## f #define SETFLAG(f,c) AF = (c) ? AF | FLAG_ ## f : AF & ~FLAG_ ## f
#define TSTFLAG(f) ((AF & FLAG_ ## f) != 0) #define TSTFLAG(f) ((AF & FLAG_ ## f) != 0)
#define LOW_DIGIT(x) ((x) & 0xf) #define LOW_DIGIT(x) ((x) & 0xf)
#define HIGH_DIGIT(x) (((x) >> 4) & 0xf) #define HIGH_DIGIT(x) (((x) >> 4) & 0xf)
@ -56,8 +61,8 @@
#define SET_PV2(x) ((chiptype == CHIP_TYPE_Z80) ? (((temp == (x)) << 2)) : (PARITY(temp))) #define SET_PV2(x) ((chiptype == CHIP_TYPE_Z80) ? (((temp == (x)) << 2)) : (PARITY(temp)))
/* CHECK_CPU_8080 must be invoked whenever a Z80 only instruction is executed /* CHECK_CPU_8080 must be invoked whenever a Z80 only instruction is executed
In case a Z80 instruction is executed on an 8080 the following two cases exist: In case a Z80 instruction is executed on an 8080 there are two cases:
1) Trapping is enabled: execution stops 1) Trapping is enabled: execution stops
2) Trapping is not enabled: decoding continues with the next byte 2) Trapping is not enabled: decoding continues with the next byte
*/ */
#define CHECK_CPU_8080 \ #define CHECK_CPU_8080 \
@ -960,7 +965,6 @@ static uint16 GET_WORD(register uint32 a) {
/* Macros for the IN/OUT instructions INI/INIR/IND/INDR/OUTI/OTIR/OUTD/OTDR /* Macros for the IN/OUT instructions INI/INIR/IND/INDR/OUTI/OTIR/OUTD/OTDR
Pre condition Pre condition
temp == value of register B at entry of the instruction
acu == value of transferred byte (IN or OUT) acu == value of transferred byte (IN or OUT)
Post condition Post condition
F is set correctly F is set correctly
@ -974,15 +978,18 @@ static uint16 GET_WORD(register uint32 a) {
x == L for OUTI and OUTD x == L for OUTI and OUTD
x == (C - 1) & 0xff for IND x == (C - 1) & 0xff for IND
*/ */
#define INOUTFLAGS(syxz, x) \ #define INOUTFLAGS_ZERO(x) \
AF = (AF & 0xff00) | (syxz) | /* SF, YF, XF, ZF */ \ AF = (AF & 0xff00) | (FLAG_Z) | /* SF, YF, XF, ZF */ \
((acu & 0x80) >> 6) | /* NF */ \ ((acu & 0x80) >> 6) | /* NF */ \
((acu + (x)) > 0xff ? (FLAG_C | FLAG_H) : 0) | /* CF, HF */ \ ((acu + (x)) > 0xff ? (FLAG_C | FLAG_H) : 0) | /* CF, HF */ \
parityTable[((acu + (x)) & 7) ^ temp] /* PF */ parityTable[((acu + (x)) & 7)] /* PF */
#define INOUTFLAGS_ZERO(x) INOUTFLAGS(FLAG_Z, x)
#define INOUTFLAGS_NONZERO(x) \ #define INOUTFLAGS_NONZERO(x) \
INOUTFLAGS((HIGH_REGISTER(BC) & 0xa8) | ((HIGH_REGISTER(BC) == 0) << 6), x) AF = (AF & 0xff00) | (HIGH_REGISTER(BC) & 0xa8) | \
((HIGH_REGISTER(BC) == 0) << 6) | /* SF, YF, XF, ZF */ \
((acu & 0x80) >> 6) | /* NF */ \
((acu + (x)) > 0xff ? (FLAG_C | FLAG_H) : 0) | /* CF, HF */ \
parityTable[((acu + (x)) & 7) ^ HIGH_REGISTER(BC)] /* PF */
t_stat sim_instr_nommu(void) { t_stat sim_instr_nommu(void) {
int32 reason = SCPE_OK; int32 reason = SCPE_OK;
@ -1056,6 +1063,8 @@ t_stat sim_instr_nommu(void) {
BC -= 0x100; BC -= 0x100;
temp = HIGH_REGISTER(BC); temp = HIGH_REGISTER(BC);
AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */ AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x06: /* LD B,nn */ case 0x06: /* LD B,nn */
@ -1063,8 +1072,11 @@ t_stat sim_instr_nommu(void) {
break; break;
case 0x07: /* RLCA */ case 0x07: /* RLCA */
AF = ((AF >> 7) & 0x0128) | ((AF << 1) & ~0x1ff) | temp = ((AF >> 7) & 0x0128) | ((AF << 1) & ~0x1ff) |
(AF & 0xc4) | ((AF >> 15) & 1); (AF & 0xc4) | ((AF >> 15) & 1);
if (chiptype == CHIP_TYPE_8080)
temp = (temp & ~0x10) | (AF & 0x10);
AF = temp;
break; break;
case 0x08: /* EX AF,AF' */ case 0x08: /* EX AF,AF' */
@ -1078,7 +1090,10 @@ t_stat sim_instr_nommu(void) {
HL &= ADDRMASK; HL &= ADDRMASK;
BC &= ADDRMASK; BC &= ADDRMASK;
sum = HL + BC; sum = HL + BC;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ BC ^ sum) >> 8]; temp = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ BC ^ sum) >> 8];
if (chiptype == CHIP_TYPE_8080)
temp = (temp & ~0x10) | (AF & 0x10);
AF = temp;
HL = sum; HL = sum;
break; break;
@ -1100,6 +1115,8 @@ t_stat sim_instr_nommu(void) {
temp = LOW_REGISTER(BC) - 1; temp = LOW_REGISTER(BC) - 1;
SET_LOW_REGISTER(BC, temp); SET_LOW_REGISTER(BC, temp);
AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f); AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x0e: /* LD C,nn */ case 0x0e: /* LD C,nn */
@ -1107,7 +1124,10 @@ t_stat sim_instr_nommu(void) {
break; break;
case 0x0f: /* RRCA */ case 0x0f: /* RRCA */
AF = (AF & 0xc4) | rrcaTable[HIGH_REGISTER(AF)]; temp = (AF & 0xc4) | rrcaTable[HIGH_REGISTER(AF)];
if (chiptype == CHIP_TYPE_8080)
temp = (temp & ~0x10) | (AF & 0x10);
AF = temp;
break; break;
case 0x10: /* DJNZ dd */ case 0x10: /* DJNZ dd */
@ -1141,6 +1161,8 @@ t_stat sim_instr_nommu(void) {
DE -= 0x100; DE -= 0x100;
temp = HIGH_REGISTER(DE); temp = HIGH_REGISTER(DE);
AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */ AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x16: /* LD D,nn */ case 0x16: /* LD D,nn */
@ -1148,8 +1170,11 @@ t_stat sim_instr_nommu(void) {
break; break;
case 0x17: /* RLA */ case 0x17: /* RLA */
AF = ((AF << 8) & 0x0100) | ((AF >> 7) & 0x28) | ((AF << 1) & ~0x01ff) | temp = ((AF << 8) & 0x0100) | ((AF >> 7) & 0x28) | ((AF << 1) & ~0x01ff) |
(AF & 0xc4) | ((AF >> 15) & 1); (AF & 0xc4) | ((AF >> 15) & 1);
if (chiptype == CHIP_TYPE_8080)
temp = (temp & ~0x10) | (AF & 0x10);
AF = temp;
break; break;
case 0x18: /* JR dd */ case 0x18: /* JR dd */
@ -1161,7 +1186,10 @@ t_stat sim_instr_nommu(void) {
HL &= ADDRMASK; HL &= ADDRMASK;
DE &= ADDRMASK; DE &= ADDRMASK;
sum = HL + DE; sum = HL + DE;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ DE ^ sum) >> 8]; temp = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ DE ^ sum) >> 8];
if (chiptype == CHIP_TYPE_8080)
temp = (temp & ~0x10) | (AF & 0x10);
AF = temp;
HL = sum; HL = sum;
break; break;
@ -1183,6 +1211,8 @@ t_stat sim_instr_nommu(void) {
temp = LOW_REGISTER(DE) - 1; temp = LOW_REGISTER(DE) - 1;
SET_LOW_REGISTER(DE, temp); SET_LOW_REGISTER(DE, temp);
AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f); AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x1e: /* LD E,nn */ case 0x1e: /* LD E,nn */
@ -1190,7 +1220,10 @@ t_stat sim_instr_nommu(void) {
break; break;
case 0x1f: /* RRA */ case 0x1f: /* RRA */
AF = ((AF & 1) << 15) | (AF & 0xc4) | rraTable[HIGH_REGISTER(AF)]; temp = ((AF & 1) << 15) | (AF & 0xc4) | rraTable[HIGH_REGISTER(AF)];
if (chiptype == CHIP_TYPE_8080)
temp = (temp & ~0x10) | (AF & 0x10);
AF = temp;
break; break;
case 0x20: /* JR NZ,dd */ case 0x20: /* JR NZ,dd */
@ -1226,6 +1259,8 @@ t_stat sim_instr_nommu(void) {
HL -= 0x100; HL -= 0x100;
temp = HIGH_REGISTER(HL); temp = HIGH_REGISTER(HL);
AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */ AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x26: /* LD H,nn */ case 0x26: /* LD H,nn */
@ -1236,7 +1271,7 @@ t_stat sim_instr_nommu(void) {
acu = HIGH_REGISTER(AF); acu = HIGH_REGISTER(AF);
temp = LOW_DIGIT(acu); temp = LOW_DIGIT(acu);
cbits = TSTFLAG(C); cbits = TSTFLAG(C);
if (TSTFLAG(N)) { /* last operation was a subtract */ if (chiptype == CHIP_TYPE_Z80 && TSTFLAG(N)) { /* last operation was a subtract */
int hd = cbits || acu > 0x99; int hd = cbits || acu > 0x99;
if (TSTFLAG(H) || (temp > 9)) { /* adjust low digit */ if (TSTFLAG(H) || (temp > 9)) { /* adjust low digit */
if (temp > 5) if (temp > 5)
@ -1268,7 +1303,10 @@ t_stat sim_instr_nommu(void) {
case 0x29: /* ADD HL,HL */ case 0x29: /* ADD HL,HL */
HL &= ADDRMASK; HL &= ADDRMASK;
sum = HL + HL; sum = HL + HL;
AF = (AF & ~0x3b) | cbitsDup16Table[sum >> 8]; temp = (AF & ~0x3b) | cbitsDup16Table[sum >> 8];
if (chiptype == CHIP_TYPE_8080)
temp = (temp & ~0x10) | (AF & 0x10);
AF = temp;
HL = sum; HL = sum;
break; break;
@ -1292,6 +1330,8 @@ t_stat sim_instr_nommu(void) {
temp = LOW_REGISTER(HL) - 1; temp = LOW_REGISTER(HL) - 1;
SET_LOW_REGISTER(HL, temp); SET_LOW_REGISTER(HL, temp);
AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f); AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x2e: /* LD L,nn */ case 0x2e: /* LD L,nn */
@ -1299,7 +1339,10 @@ t_stat sim_instr_nommu(void) {
break; break;
case 0x2f: /* CPL */ case 0x2f: /* CPL */
AF = (~AF & ~0xff) | (AF & 0xc5) | ((~AF >> 8) & 0x28) | 0x12; temp = (~AF & ~0xff) | (AF & 0xc5) | ((~AF >> 8) & 0x28) | 0x12;
if (chiptype == CHIP_TYPE_8080)
temp = (temp & ~0x10) | (AF & 0x10);
AF = temp;
break; break;
case 0x30: /* JR NC,dd */ case 0x30: /* JR NC,dd */
@ -1335,6 +1378,8 @@ t_stat sim_instr_nommu(void) {
temp = GET_BYTE(HL) - 1; temp = GET_BYTE(HL) - 1;
PUT_BYTE(HL, temp); PUT_BYTE(HL, temp);
AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f); AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x36: /* LD (HL),nn */ case 0x36: /* LD (HL),nn */
@ -1342,7 +1387,10 @@ t_stat sim_instr_nommu(void) {
break; break;
case 0x37: /* SCF */ case 0x37: /* SCF */
AF = (AF & ~0x3b) | ((AF >> 8) & 0x28) | 1; temp = (AF & ~0x3b) | ((AF >> 8) & 0x28) | 1;
if (chiptype == CHIP_TYPE_8080)
temp = (temp & ~0x10) | (AF & 0x10);
AF = temp;
break; break;
case 0x38: /* JR C,dd */ case 0x38: /* JR C,dd */
@ -1357,7 +1405,10 @@ t_stat sim_instr_nommu(void) {
HL &= ADDRMASK; HL &= ADDRMASK;
SP &= ADDRMASK; SP &= ADDRMASK;
sum = HL + SP; sum = HL + SP;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ SP ^ sum) >> 8]; temp = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ SP ^ sum) >> 8];
if (chiptype == CHIP_TYPE_8080)
temp = (temp & ~0x10) | (AF & 0x10);
AF = temp;
HL = sum; HL = sum;
break; break;
@ -1381,6 +1432,8 @@ t_stat sim_instr_nommu(void) {
AF -= 0x100; AF -= 0x100;
temp = HIGH_REGISTER(AF); temp = HIGH_REGISTER(AF);
AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */ AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x3e: /* LD A,nn */ case 0x3e: /* LD A,nn */
@ -1388,7 +1441,10 @@ t_stat sim_instr_nommu(void) {
break; break;
case 0x3f: /* CCF */ case 0x3f: /* CCF */
AF = (AF & ~0x3b) | ((AF >> 8) & 0x28) | ((AF & 1) << 4) | (~AF & 1); temp = (AF & ~0x3b) | ((AF >> 8) & 0x28) | ((AF & 1) << 4) | (~AF & 1);
if (chiptype == CHIP_TYPE_8080)
temp = (temp & ~0x10) | (AF & 0x10);
AF = temp;
break; break;
case 0x40: /* LD B,B */ case 0x40: /* LD B,B */
@ -1773,6 +1829,8 @@ t_stat sim_instr_nommu(void) {
sum = acu - temp; sum = acu - temp;
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x91: /* SUB C */ case 0x91: /* SUB C */
@ -1781,6 +1839,8 @@ t_stat sim_instr_nommu(void) {
sum = acu - temp; sum = acu - temp;
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x92: /* SUB D */ case 0x92: /* SUB D */
@ -1789,6 +1849,8 @@ t_stat sim_instr_nommu(void) {
sum = acu - temp; sum = acu - temp;
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x93: /* SUB E */ case 0x93: /* SUB E */
@ -1797,6 +1859,8 @@ t_stat sim_instr_nommu(void) {
sum = acu - temp; sum = acu - temp;
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x94: /* SUB H */ case 0x94: /* SUB H */
@ -1805,6 +1869,8 @@ t_stat sim_instr_nommu(void) {
sum = acu - temp; sum = acu - temp;
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x95: /* SUB L */ case 0x95: /* SUB L */
@ -1813,6 +1879,8 @@ t_stat sim_instr_nommu(void) {
sum = acu - temp; sum = acu - temp;
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x96: /* SUB (HL) */ case 0x96: /* SUB (HL) */
@ -1821,10 +1889,12 @@ t_stat sim_instr_nommu(void) {
sum = acu - temp; sum = acu - temp;
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x97: /* SUB A */ case 0x97: /* SUB A */
AF = (chiptype == CHIP_TYPE_Z80) ? 0x42 : 0x46; AF = (chiptype == CHIP_TYPE_Z80) ? 0x42 : 0x56;
break; break;
case 0x98: /* SBC A,B */ case 0x98: /* SBC A,B */
@ -1833,6 +1903,8 @@ t_stat sim_instr_nommu(void) {
sum = acu - temp - TSTFLAG(C); sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x99: /* SBC A,C */ case 0x99: /* SBC A,C */
@ -1841,6 +1913,8 @@ t_stat sim_instr_nommu(void) {
sum = acu - temp - TSTFLAG(C); sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x9a: /* SBC A,D */ case 0x9a: /* SBC A,D */
@ -1849,6 +1923,8 @@ t_stat sim_instr_nommu(void) {
sum = acu - temp - TSTFLAG(C); sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x9b: /* SBC A,E */ case 0x9b: /* SBC A,E */
@ -1857,6 +1933,8 @@ t_stat sim_instr_nommu(void) {
sum = acu - temp - TSTFLAG(C); sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x9c: /* SBC A,H */ case 0x9c: /* SBC A,H */
@ -1865,6 +1943,8 @@ t_stat sim_instr_nommu(void) {
sum = acu - temp - TSTFLAG(C); sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x9d: /* SBC A,L */ case 0x9d: /* SBC A,L */
@ -1873,6 +1953,8 @@ t_stat sim_instr_nommu(void) {
sum = acu - temp - TSTFLAG(C); sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x9e: /* SBC A,(HL) */ case 0x9e: /* SBC A,(HL) */
@ -1881,43 +1963,72 @@ t_stat sim_instr_nommu(void) {
sum = acu - temp - TSTFLAG(C); sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0x9f: /* SBC A,A */ case 0x9f: /* SBC A,A */
cbits = -TSTFLAG(C); cbits = -TSTFLAG(C);
AF = subTable[cbits & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PVS(cbits)); AF = subTable[cbits & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PVS(cbits));
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0xa0: /* AND B */ case 0xa0: /* AND B */
AF = andTable[((AF & BC) >> 8) & 0xff]; acu = andTable[((AF & BC) >> 8) & 0xff];
if (chiptype == CHIP_TYPE_8080 && ((AF | BC) & 0x0800) == 0)
acu &= ~0x10;
AF = acu;
break; break;
case 0xa1: /* AND C */ case 0xa1: /* AND C */
AF = andTable[((AF >> 8) & BC) & 0xff]; acu = andTable[((AF >> 8) & BC) & 0xff];
if (chiptype == CHIP_TYPE_8080 && (((AF >> 8) | BC) & 0x08) == 0)
acu &= ~0x10;
AF = acu;
break; break;
case 0xa2: /* AND D */ case 0xa2: /* AND D */
AF = andTable[((AF & DE) >> 8) & 0xff]; acu = andTable[((AF & DE) >> 8) & 0xff];
if (chiptype == CHIP_TYPE_8080 && ((AF | DE) & 0x0800) == 0)
acu &= ~0x10;
AF = acu;
break; break;
case 0xa3: /* AND E */ case 0xa3: /* AND E */
AF = andTable[((AF >> 8) & DE) & 0xff]; acu = andTable[((AF >> 8) & DE) & 0xff];
if (chiptype == CHIP_TYPE_8080 && (((AF >> 8) | DE) & 0x08) == 0)
acu &= ~0x10;
AF = acu;
break; break;
case 0xa4: /* AND H */ case 0xa4: /* AND H */
AF = andTable[((AF & HL) >> 8) & 0xff]; acu = andTable[((AF & HL) >> 8) & 0xff];
if (chiptype == CHIP_TYPE_8080 && ((AF | HL) & 0x0800) == 0)
acu &= ~0x10;
AF = acu;
break; break;
case 0xa5: /* AND L */ case 0xa5: /* AND L */
AF = andTable[((AF >> 8) & HL) & 0xff]; acu = andTable[((AF >> 8) & HL) & 0xff];
if (chiptype == CHIP_TYPE_8080 && (((AF >> 8) | HL) & 0x08) == 0)
acu &= ~0x10;
AF = acu;
break; break;
case 0xa6: /* AND (HL) */ case 0xa6: /* AND (HL) */
AF = andTable[((AF >> 8) & GET_BYTE(HL)) & 0xff]; temp = GET_BYTE(HL);
acu = andTable[((AF >> 8) & temp) & 0xff];
if (chiptype == CHIP_TYPE_8080 && (((AF >> 8) | temp) & 0x08) == 0)
acu &= ~0x10;
AF = acu;
break; break;
case 0xa7: /* AND A */ case 0xa7: /* AND A */
AF = andTable[(AF >> 8) & 0xff]; acu = andTable[(AF >> 8) & 0xff];
if (chiptype == CHIP_TYPE_8080 && (AF & 0x0800) == 0)
acu &= ~0x10;
AF = acu;
break; break;
case 0xa8: /* XOR B */ case 0xa8: /* XOR B */
@ -1992,6 +2103,8 @@ t_stat sim_instr_nommu(void) {
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) |
(SET_PV) | cbits2Table[cbits & 0x1ff]; (SET_PV) | cbits2Table[cbits & 0x1ff];
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0xb9: /* CP C */ case 0xb9: /* CP C */
@ -2002,6 +2115,8 @@ t_stat sim_instr_nommu(void) {
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) |
(SET_PV) | cbits2Table[cbits & 0x1ff]; (SET_PV) | cbits2Table[cbits & 0x1ff];
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0xba: /* CP D */ case 0xba: /* CP D */
@ -2012,6 +2127,8 @@ t_stat sim_instr_nommu(void) {
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) |
(SET_PV) | cbits2Table[cbits & 0x1ff]; (SET_PV) | cbits2Table[cbits & 0x1ff];
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0xbb: /* CP E */ case 0xbb: /* CP E */
@ -2022,6 +2139,8 @@ t_stat sim_instr_nommu(void) {
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) |
(SET_PV) | cbits2Table[cbits & 0x1ff]; (SET_PV) | cbits2Table[cbits & 0x1ff];
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0xbc: /* CP H */ case 0xbc: /* CP H */
@ -2032,6 +2151,8 @@ t_stat sim_instr_nommu(void) {
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) |
(SET_PV) | cbits2Table[cbits & 0x1ff]; (SET_PV) | cbits2Table[cbits & 0x1ff];
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0xbd: /* CP L */ case 0xbd: /* CP L */
@ -2042,6 +2163,8 @@ t_stat sim_instr_nommu(void) {
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) |
(SET_PV) | cbits2Table[cbits & 0x1ff]; (SET_PV) | cbits2Table[cbits & 0x1ff];
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0xbe: /* CP (HL) */ case 0xbe: /* CP (HL) */
@ -2052,10 +2175,12 @@ t_stat sim_instr_nommu(void) {
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) |
(SET_PV) | cbits2Table[cbits & 0x1ff]; (SET_PV) | cbits2Table[cbits & 0x1ff];
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0xbf: /* CP A */ case 0xbf: /* CP A */
SET_LOW_REGISTER(AF, (HIGH_REGISTER(AF) & 0x28) | (chiptype == CHIP_TYPE_Z80 ? 0x42 : 0x46)); SET_LOW_REGISTER(AF, (HIGH_REGISTER(AF) & 0x28) | (chiptype == CHIP_TYPE_Z80 ? 0x42 : 0x56));
break; break;
case 0xc0: /* RET NZ */ case 0xc0: /* RET NZ */
@ -2309,6 +2434,8 @@ t_stat sim_instr_nommu(void) {
sum = acu - temp; sum = acu - temp;
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0xd7: /* RST 10H */ case 0xd7: /* RST 10H */
@ -2947,6 +3074,8 @@ t_stat sim_instr_nommu(void) {
sum = acu - temp - TSTFLAG(C); sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV);
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0xdf: /* RST 18H */ case 0xdf: /* RST 18H */
@ -2982,7 +3111,11 @@ t_stat sim_instr_nommu(void) {
break; break;
case 0xe6: /* AND nn */ case 0xe6: /* AND nn */
AF = andTable[((AF >> 8) & RAM_PP(PC)) & 0xff]; temp = RAM_PP(PC);
acu = andTable[((AF >> 8) & temp) & 0xff];
if (chiptype == CHIP_TYPE_8080 && (((AF >> 8) | temp) & 0x08) == 0)
acu &= ~0x10;
AF = acu;
break; break;
case 0xe7: /* RST 20H */ case 0xe7: /* RST 20H */
@ -3333,7 +3466,6 @@ t_stat sim_instr_nommu(void) {
acu = in(LOW_REGISTER(BC)); acu = in(LOW_REGISTER(BC));
PUT_BYTE(HL, acu); PUT_BYTE(HL, acu);
++HL; ++HL;
temp = HIGH_REGISTER(BC);
BC -= 0x100; BC -= 0x100;
INOUTFLAGS_NONZERO((LOW_REGISTER(BC) + 1) & 0xff); INOUTFLAGS_NONZERO((LOW_REGISTER(BC) + 1) & 0xff);
break; break;
@ -3350,7 +3482,6 @@ t_stat sim_instr_nommu(void) {
acu = GET_BYTE(HL); acu = GET_BYTE(HL);
out(LOW_REGISTER(BC), acu); out(LOW_REGISTER(BC), acu);
++HL; ++HL;
temp = HIGH_REGISTER(BC);
BC -= 0x100; BC -= 0x100;
INOUTFLAGS_NONZERO(LOW_REGISTER(HL)); INOUTFLAGS_NONZERO(LOW_REGISTER(HL));
break; break;
@ -3387,7 +3518,6 @@ t_stat sim_instr_nommu(void) {
acu = in(LOW_REGISTER(BC)); acu = in(LOW_REGISTER(BC));
PUT_BYTE(HL, acu); PUT_BYTE(HL, acu);
--HL; --HL;
temp = HIGH_REGISTER(BC);
BC -= 0x100; BC -= 0x100;
INOUTFLAGS_NONZERO((LOW_REGISTER(BC) - 1) & 0xff); INOUTFLAGS_NONZERO((LOW_REGISTER(BC) - 1) & 0xff);
break; break;
@ -3396,7 +3526,6 @@ t_stat sim_instr_nommu(void) {
acu = GET_BYTE(HL); acu = GET_BYTE(HL);
out(LOW_REGISTER(BC), acu); out(LOW_REGISTER(BC), acu);
--HL; --HL;
temp = HIGH_REGISTER(BC);
BC -= 0x100; BC -= 0x100;
INOUTFLAGS_NONZERO(LOW_REGISTER(HL)); INOUTFLAGS_NONZERO(LOW_REGISTER(HL));
break; break;
@ -3444,7 +3573,6 @@ t_stat sim_instr_nommu(void) {
PUT_BYTE(HL, acu); PUT_BYTE(HL, acu);
++HL; ++HL;
} while (--temp); } while (--temp);
temp = HIGH_REGISTER(BC);
SET_HIGH_REGISTER(BC, 0); SET_HIGH_REGISTER(BC, 0);
INOUTFLAGS_ZERO((LOW_REGISTER(BC) + 1) & 0xff); INOUTFLAGS_ZERO((LOW_REGISTER(BC) + 1) & 0xff);
break; break;
@ -3459,7 +3587,6 @@ t_stat sim_instr_nommu(void) {
out(LOW_REGISTER(BC), acu); out(LOW_REGISTER(BC), acu);
++HL; ++HL;
} while (--temp); } while (--temp);
temp = HIGH_REGISTER(BC);
SET_HIGH_REGISTER(BC, 0); SET_HIGH_REGISTER(BC, 0);
INOUTFLAGS_ZERO(LOW_REGISTER(HL)); INOUTFLAGS_ZERO(LOW_REGISTER(HL));
break; break;
@ -3507,7 +3634,6 @@ t_stat sim_instr_nommu(void) {
PUT_BYTE(HL, acu); PUT_BYTE(HL, acu);
--HL; --HL;
} while (--temp); } while (--temp);
temp = HIGH_REGISTER(BC);
SET_HIGH_REGISTER(BC, 0); SET_HIGH_REGISTER(BC, 0);
INOUTFLAGS_ZERO((LOW_REGISTER(BC) - 1) & 0xff); INOUTFLAGS_ZERO((LOW_REGISTER(BC) - 1) & 0xff);
break; break;
@ -3522,7 +3648,6 @@ t_stat sim_instr_nommu(void) {
out(LOW_REGISTER(BC), acu); out(LOW_REGISTER(BC), acu);
--HL; --HL;
} while (--temp); } while (--temp);
temp = HIGH_REGISTER(BC);
SET_HIGH_REGISTER(BC, 0); SET_HIGH_REGISTER(BC, 0);
INOUTFLAGS_ZERO(LOW_REGISTER(HL)); INOUTFLAGS_ZERO(LOW_REGISTER(HL));
break; break;
@ -3563,7 +3688,7 @@ t_stat sim_instr_nommu(void) {
break; break;
case 0xf5: /* PUSH AF */ case 0xf5: /* PUSH AF */
PUSH(AF); PUSH(chiptype == CHIP_TYPE_8080 ? (AF & ~0x28) | 0x02 : AF);
break; break;
case 0xf6: /* OR nn */ case 0xf6: /* OR nn */
@ -4199,6 +4324,8 @@ t_stat sim_instr_nommu(void) {
cbits = acu ^ temp ^ sum; cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) |
(SET_PV) | cbits2Table[cbits & 0x1ff]; (SET_PV) | cbits2Table[cbits & 0x1ff];
if (chiptype == CHIP_TYPE_8080)
AF ^= 0x10;
break; break;
case 0xff: /* RST 38H */ case 0xff: /* RST 38H */

View file

@ -1,6 +1,6 @@
/* altairz80_defs.h: MITS Altair simulator definitions /* altairz80_defs.h: MITS Altair simulator definitions
Copyright (c) 2002-2023, Peter Schorn Copyright (c) 2002-2024, Peter Schorn
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -64,11 +64,11 @@ typedef enum {
} ChipType; } ChipType;
/* simulator stop codes */ /* simulator stop codes */
#define STOP_IBKPT 1 /* breakpoint (program counter) */ #define STOP_IBKPT 1 /* breakpoint (program counter) */
#define STOP_MEM 2 /* breakpoint (memory access) */ #define STOP_MEM 2 /* breakpoint (memory access) */
#define STOP_INSTR 3 /* breakpoint (instruction access) */ #define STOP_INSTR 3 /* breakpoint (instruction access) */
#define STOP_OPCODE 4 /* invalid operation encountered (8080, Z80, 8086) */ #define STOP_OPCODE 4 /* invalid operation encountered (8080, Z80, 8086) */
#define STOP_HALT 5 /* HALT */ #define STOP_HALT 5 /* HALT */
#define UNIT_CPU_V_OPSTOP (UNIT_V_UF+0) /* stop on invalid operation */ #define UNIT_CPU_V_OPSTOP (UNIT_V_UF+0) /* stop on invalid operation */
#define UNIT_CPU_OPSTOP (1 << UNIT_CPU_V_OPSTOP) #define UNIT_CPU_OPSTOP (1 << UNIT_CPU_V_OPSTOP)

Binary file not shown.