- [FIX] SET_PARITY_FLAG() should work on the result

-[NEW] Implemented flag calculation for IN(), OUT(), INI(), IND(), OUTI(), OUTD()
- [FIX] Corrected flag calculation for CPI, CPD,
- [CHG] Renamed SWAP to EX
This commit is contained in:
2024-04-16 11:28:06 +02:00
parent aff713fc62
commit 3a6eef7cba

113
z80.cpp
View File

@@ -129,7 +129,7 @@ namespace z80
#define rPC (*_rPC)
#define SWAP(a,b) {auto temp=a;a=b;b=temp;}
#define EX(a,b) {auto temp=a;a=b;b=temp;}
uint8_t READ_MEM_8(const uint16_t addr)
{
@@ -204,11 +204,11 @@ namespace z80
rF |= (value & (fY | fX));
}
inline void SET_PARITY_FLAG()
inline void SET_PARITY_FLAG(const uint8_t value)
{
uint8_t count=0;
uint8_t f = rF;
while (f>0) { count+=(f&1); f=f>>1; }
uint8_t v = value;
while (v>0) { count+=(v&1); v=v>>1; }
if (!(count&1)) rF |= fP;
}
@@ -382,7 +382,7 @@ namespace z80
rA = rA & b;
rF=0;
FLAGS_SZXY(rA);
SET_PARITY_FLAG();
SET_PARITY_FLAG(rA);
SET_FLAGS(fH);
}
@@ -391,7 +391,7 @@ namespace z80
rA = rA ^ b;
rF=0;
FLAGS_SZXY(rA);
SET_PARITY_FLAG();
SET_PARITY_FLAG(rA);
}
void OR(uint8_t b)
@@ -399,7 +399,7 @@ namespace z80
rA = rA | b;
rF=0;
FLAGS_SZXY(rA);
SET_PARITY_FLAG();
SET_PARITY_FLAG(rA);
}
void CP(uint8_t b)
@@ -462,7 +462,7 @@ namespace z80
WRITE_MEM_8(rHL, hl);
KEEP_FLAGS(fC);
FLAGS_SZXY(rA);
SET_PARITY_FLAG();
SET_PARITY_FLAG(rA);
t+=4;
}
@@ -475,7 +475,7 @@ namespace z80
WRITE_MEM_8(rHL, hl);
KEEP_FLAGS(fC);
FLAGS_SZXY(rA);
SET_PARITY_FLAG();
SET_PARITY_FLAG(rA);
t+=4;
}
@@ -489,7 +489,7 @@ namespace z80
FLAGS_SZXY(rA);
if ( (rA & 0x0F) < (old & 0x0F) ) SET_FLAGS(fH);
if (carry_set) SET_FLAGS(fC);
SET_PARITY_FLAG();
SET_PARITY_FLAG(rA);
}
void CPL()
@@ -654,7 +654,7 @@ namespace z80
rF=0;
FLAGS_SZXY(res);
if (res&1) SET_FLAGS(fC);
SET_PARITY_FLAG();
SET_PARITY_FLAG(res);
return res;
}
@@ -664,7 +664,7 @@ namespace z80
rF=0;
FLAGS_SZXY(res);
if (res&0x80) SET_FLAGS(fC);
SET_PARITY_FLAG();
SET_PARITY_FLAG(res);
return res;
}
@@ -674,7 +674,7 @@ namespace z80
rF=0;
FLAGS_SZXY(res);
if (v&0x80) SET_FLAGS(fC);
SET_PARITY_FLAG();
SET_PARITY_FLAG(res);
return res;
}
@@ -684,7 +684,7 @@ namespace z80
rF=0;
FLAGS_SZXY(res);
if (v&1) SET_FLAGS(fC);
SET_PARITY_FLAG();
SET_PARITY_FLAG(res);
return res;
}
@@ -694,7 +694,7 @@ namespace z80
rF=0;
FLAGS_SZXY(res);
if (v&0x80) SET_FLAGS(fC);
SET_PARITY_FLAG();
SET_PARITY_FLAG(res);
return res;
}
@@ -704,7 +704,7 @@ namespace z80
rF=0;
FLAGS_SZXY(res);
if (v&1) SET_FLAGS(fC);
SET_PARITY_FLAG();
SET_PARITY_FLAG(res);
return res;
}
@@ -714,7 +714,7 @@ namespace z80
rF=0;
FLAGS_SZXY(res);
if (v&0x80) SET_FLAGS(fC);
SET_PARITY_FLAG();
SET_PARITY_FLAG(res);
return res;
}
@@ -724,7 +724,7 @@ namespace z80
rF=0;
FLAGS_SZXY(res);
if (v&1) SET_FLAGS(fC);
SET_PARITY_FLAG();
SET_PARITY_FLAG(res);
return res;
}
@@ -793,14 +793,15 @@ namespace z80
void CPI()
{
uint8_t old_fC = rF & fC;
bool keep_fC = (rF & fC);
CP(READ_MEM_8(rHL));
rHL++;
rBC--;
t+=2;
rF = (rF & 0xFD) | old_fC;
KEEP_FLAGS(fS | fZ | fH | fN);
if (keep_fC) SET_FLAGS(fC);
if (rBC!=0) SET_FLAGS(fP);
if (READ_MEM_8(rHL)==rA) SET_FLAGS(fZ);
//if (READ_MEM_8(rHL)==rA) SET_FLAGS(fZ);
}
void CPIR()
@@ -815,14 +816,14 @@ namespace z80
void CPD()
{
uint8_t old_fC = rF & fC;
bool keep_fC = (rF & fC);
CP(READ_MEM_8(rHL));
rHL--;
rBC--;
t+=2;
rF = (rF & 0xFD) | old_fC;
KEEP_FLAGS(fS | fZ | fH | fN);
if (keep_fC) SET_FLAGS(fC);
if (rBC!=0) SET_FLAGS(fP);
if (READ_MEM_8(rHL)==rA) SET_FLAGS(fZ);
}
void CPDR()
@@ -837,22 +838,26 @@ namespace z80
const uint8_t IN(int port = 0x10000)
{
bool set_flags=true;
t+=4;
if (port == 0x10000) {
port = rBC;
// [TODO] set flags acordingly
} else {
set_flags=false;
port = (rA<<8) | port;
// don't touch flags
}
if (in_ports[port&0xff]) {
const uint8_t val = (uint8_t)in_ports[port&0xff](port);
if (val != 0xff)
return val;
else
return 0xff;
if (set_flags) {
KEEP_FLAGS(fC);
SET_PARITY_FLAG(val);
FLAGS_SZXY(val);
}
return val;
} else
return 0x00;
return 0xff;
}
void OUT(uint8_t val, int port = 0x10000)
@@ -866,9 +871,17 @@ namespace z80
void INI()
{
WRITE_MEM_8(rHL, IN());
rHL++;
DEC8(_rB);
const uint8_t flags_after_dec = rF;
const uint8_t val = IN();
WRITE_MEM_8(rHL, val);
rHL++;
SET_FLAGS(flags_after_dec);
KEEP_FLAGS(fS | fZ | fY | fX);
if (val&0x80) SET_FLAGS(fN);
uint16_t k = val + ((rC+1)&255);
if (k>255) SET_FLAGS(fH | fC);
SET_PARITY_FLAG((k&7)^rB);
t+=5;
}
@@ -884,9 +897,17 @@ namespace z80
void IND()
{
WRITE_MEM_8(rHL, IN());
rHL--;
DEC8(_rB);
const uint8_t flags_after_dec = rF;
const uint8_t val = IN();
WRITE_MEM_8(rHL, val);
rHL--;
SET_FLAGS(flags_after_dec);
KEEP_FLAGS(fS | fZ | fY | fX);
if (val&0x80) SET_FLAGS(fN);
uint16_t k = val + ((rC-1)&255);
if (k>255) SET_FLAGS(fH | fC);
SET_PARITY_FLAG((k&7)^rB);
t+=5;
}
@@ -902,9 +923,15 @@ namespace z80
void OUTI()
{
OUT(READ_MEM_8(rHL));
const uint8_t val = READ_MEM_8(rHL);
OUT(val);
rHL++;
DEC8(_rB);
KEEP_FLAGS(fS | fZ | fY | fX);
if (val&0x80) SET_FLAGS(fN);
uint16_t k = rL+val;
if (k>255) SET_FLAGS(fH | fC);
SET_PARITY_FLAG((k&7)^rB);
t+=5;
}
@@ -919,9 +946,15 @@ namespace z80
}
void OUTD() {
OUT(READ_MEM_8(rHL));
const uint8_t val = READ_MEM_8(rHL);
OUT(val);
rHL--;
DEC8(_rB);
KEEP_FLAGS(fS | fZ | fY | fX);
if (val&0x80) SET_FLAGS(fN);
uint16_t k = rL+val;
if (k>255) SET_FLAGS(fH | fC);
SET_PARITY_FLAG((k&7)^rB);
t+=5;
}
@@ -982,7 +1015,7 @@ namespace z80
case 0x05: DEC8(_rB); break;
case 0x06: rB = READ_MEM_8(); break;
case 0x07: RLCA(); break;
case 0x08: SWAP(rAF, rAF2); break;
case 0x08: EX(rAF, rAF2); break;
case 0x09: ADD16(_rHL, rBC); break;
case 0x0A: rA = READ_MEM_8(rBC); break;
case 0x0B: DEC16(_rBC); break;
@@ -1204,7 +1237,7 @@ namespace z80
case 0xD6: SUB8(READ_MEM_8()); break;
case 0xD7: RST(0x10); break;
case 0xD8: RET(cC); break;
case 0xD9: SWAP(rBC, rBC2);SWAP(rDE, rDE2);SWAP(rHL, rHL2); break;
case 0xD9: EX(rBC, rBC2);EX(rDE, rDE2);EX(rHL, rHL2); break;
case 0xDA: JP(cC, READ_MEM_16()); break;
case 0xDB: rA = IN(READ_MEM_8()); break;
case 0xDC: CALL(cC, READ_MEM_16()); break;
@@ -1223,7 +1256,7 @@ namespace z80
case 0xE8: RET(cPE); break;
case 0xE9: JP(cNO, rHL); break;
case 0xEA: JP(cPE, READ_MEM_16()); break;
case 0xEB: SWAP(rDE, rHL); break;
case 0xEB: EX(rDE, rHL); break;
case 0xEC: CALL(cPE, READ_MEM_16()); break;
case 0xED: MISC_INSTRUCTIONS(); break;
case 0xEE: XOR(READ_MEM_8()); break;