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