- Treballant en la CPU

This commit is contained in:
2025-01-13 14:01:41 +01:00
parent 44c044d64e
commit 17cf6f3884
3 changed files with 122 additions and 467 deletions

9
mem.h Normal file
View File

@@ -0,0 +1,9 @@
#pragma once
#include <stdint.h>
namespace mem
{
void reset();
uint8_t readMem(uint16_t address);
void writeMem(uint16_t address, uint8_t value);
}

572
sm83.cpp
View File

@@ -1,4 +1,5 @@
#include "sm83.h" #include "sm83.h"
#include "mem.h"
//#include "z80debug.h" //#include "z80debug.h"
//#include "z80mem.h" //#include "z80mem.h"
#include <stdio.h> #include <stdio.h>
@@ -66,7 +67,7 @@ namespace sm83
#define rSP (*_rSP) #define rSP (*_rSP)
#define rPC (*_rPC) #define rPC (*_rPC)
#define im2 (*_rIME) #define ime (*_rIME)
#define EX(a,b) {auto temp=a;a=b;b=temp;} #define EX(a,b) {auto temp=a;a=b;b=temp;}
@@ -91,7 +92,7 @@ namespace sm83
} }
*/ */
reading_m1 = false; reading_m1 = false;
return z80mem::get()->readMem(addr); return mem::readMem(addr);
} }
uint8_t READ_MEM_8() uint8_t READ_MEM_8()
@@ -124,7 +125,7 @@ namespace sm83
const uint8_t WRITE_MEM_8(const uint16_t addr, const uint8_t value) const uint8_t WRITE_MEM_8(const uint16_t addr, const uint8_t value)
{ {
t+=4; t+=4;
z80mem::get()->writeMem(addr, value); mem::writeMem(addr, value);
/* /*
if (z80debug::isbreak(addr, 4)) z80debug::stop(); if (z80debug::isbreak(addr, 4)) z80debug::stop();
@@ -194,40 +195,12 @@ namespace sm83
*a = (uint16_t)res; *a = (uint16_t)res;
} }
void ADC16(uint16_t* a, uint16_t b)
{
t++;
const uint32_t res = *a + b + (rF & fC);
rF=0;
SET_FLAGS(((*a ^ res ^ b) >> 8) & fH);
SET_FLAGS((res >> 16) & fC);
SET_FLAGS((res >> 8) & (fS | fY | fX));
SET_FLAGS((res & 0xffff) ? 0 : fZ);
SET_FLAGS(((b ^ *a ^ 0x8000) & (b ^ res) & 0x8000) >> 13);
*a = (uint16_t)res;
}
void SBC16(uint16_t* a, uint16_t b)
{
t++;
const uint32_t res = *a - b - (rF & fC);
rF = 0;
SET_FLAGS(((*a ^ res ^ b) >> 8) & fH);
SET_FLAGS(fN);
SET_FLAGS((res >> 16) & fC);
SET_FLAGS((res >> 8) & (fS | fY | fX));
SET_FLAGS((res & 0xffff) ? 0 : fZ);
SET_FLAGS(((b ^ *a) & (*a ^ res) & 0x8000) >> 13);
*a = (uint16_t)res;
}
void INC8(uint8_t *reg) void INC8(uint8_t *reg)
{ {
uint8_t value = *reg + 1; uint8_t value = *reg + 1;
KEEP_FLAGS(fC); KEEP_FLAGS(fC);
FLAGS_SZXY(value); if (value==0) SET_FLAGS(fZ);
if (value == 0x80) SET_FLAGS(fV);
if ( (value & 0x0f) == 0x00 ) SET_FLAGS(fH); if ( (value & 0x0f) == 0x00 ) SET_FLAGS(fH);
*reg = value; *reg = value;
@@ -238,9 +211,8 @@ namespace sm83
uint8_t value = *reg - 1; uint8_t value = *reg - 1;
KEEP_FLAGS(fC); KEEP_FLAGS(fC);
FLAGS_SZXY(value);
SET_FLAGS(fN); SET_FLAGS(fN);
if (value == 0x7f) SET_FLAGS(fV); if (value==0) SET_FLAGS(fZ);
if ( (value & 0x0f) == 0x0f ) SET_FLAGS(fH); if ( (value & 0x0f) == 0x0f ) SET_FLAGS(fH);
*reg = value; *reg = value;
@@ -248,13 +220,11 @@ namespace sm83
void INCMEM8(const uint16_t addr) void INCMEM8(const uint16_t addr)
{ {
t++;
uint8_t value = READ_MEM_8(addr); uint8_t value = READ_MEM_8(addr);
value++; value++;
KEEP_FLAGS(fC); KEEP_FLAGS(fC);
FLAGS_SZXY(value); if (value==0) SET_FLAGS(fZ);
if (value == 0x80) SET_FLAGS(fV);
if ( (value & 0x0f) == 0x00 ) SET_FLAGS(fH); if ( (value & 0x0f) == 0x00 ) SET_FLAGS(fH);
WRITE_MEM_8(addr, value); WRITE_MEM_8(addr, value);
@@ -262,14 +232,12 @@ namespace sm83
void DECMEM8(const uint16_t addr) void DECMEM8(const uint16_t addr)
{ {
t+=1;
uint8_t value = READ_MEM_8(addr); uint8_t value = READ_MEM_8(addr);
value--; value--;
KEEP_FLAGS(fC); KEEP_FLAGS(fC);
FLAGS_SZXY(value);
SET_FLAGS(fN); SET_FLAGS(fN);
if (value == 0x7f) SET_FLAGS(fV); if (value==0) SET_FLAGS(fZ);
if ( (value & 0x0f) == 0x0f ) SET_FLAGS(fH); if ( (value & 0x0f) == 0x0f ) SET_FLAGS(fH);
WRITE_MEM_8(addr, value); WRITE_MEM_8(addr, value);
@@ -292,10 +260,9 @@ namespace sm83
else { else {
uint16_t res = rA + b + 1; uint16_t res = rA + b + 1;
rF=0; rF=0;
FLAGS_SZXY(res); if (res==0) SET_FLAGS(fZ);
if ( (res & 0x0f) <= (rA & 0x0f) ) SET_FLAGS(fH); if ( (res & 0x0f) <= (rA & 0x0f) ) SET_FLAGS(fH);
if ( res > 255 ) SET_FLAGS(fC); if ( res > 255 ) SET_FLAGS(fC);
if ( (b^rA^0x80) & (b^res) & 0x80 ) SET_FLAGS(fV);
rA = (uint8_t)res; rA = (uint8_t)res;
} }
} }
@@ -304,11 +271,10 @@ namespace sm83
{ {
const uint8_t res = rA - b; const uint8_t res = rA - b;
rF=0; rF=0;
FLAGS_SZXY(res); if (res==0) SET_FLAGS(fZ);
SET_FLAGS(fN); SET_FLAGS(fN);
if ( (res & 0x0f) > (rA & 0x0f) ) SET_FLAGS(fH); if ( (res & 0x0f) > (rA & 0x0f) ) SET_FLAGS(fH);
if ( res > rA ) SET_FLAGS(fC); if ( res > rA ) SET_FLAGS(fC);
if ( (b^rA) & (rA^res) & 0x80 ) SET_FLAGS(fV);
if (update) rA = (uint8_t)res; if (update) rA = (uint8_t)res;
} }
@@ -319,45 +285,33 @@ namespace sm83
else { else {
const uint8_t res = rA - b - 1; const uint8_t res = rA - b - 1;
rF=0; rF=0;
FLAGS_SZXY(res); if (res==0) SET_FLAGS(fZ);
SET_FLAGS(fN); SET_FLAGS(fN);
if ( (res & 0x0f) >= (rA & 0x0f) ) SET_FLAGS(fH); if ( (res & 0x0f) >= (rA & 0x0f) ) SET_FLAGS(fH);
if ( res >= rA ) SET_FLAGS(fC); if ( res >= rA ) SET_FLAGS(fC);
if ( (b^rA) & (rA^res) & 0x80 ) SET_FLAGS(fV);
rA = (uint8_t)res; rA = (uint8_t)res;
} }
} }
void NEG()
{
uint8_t val = rA;
rA = 0;
SUB8(val);
}
void AND(uint8_t b) void AND(uint8_t b)
{ {
rA = rA & b; rA = rA & b;
rF=0; rF=fH;
FLAGS_SZXY(rA); if (rA==0) SET_FLAGS(fZ);
SET_PARITY_FLAG(rA);
SET_FLAGS(fH);
} }
void XOR(uint8_t b) void XOR(uint8_t b)
{ {
rA = rA ^ b; rA = rA ^ b;
rF=0; rF=0;
FLAGS_SZXY(rA); if (rA==0) SET_FLAGS(fZ);
SET_PARITY_FLAG(rA);
} }
void OR(uint8_t b) void OR(uint8_t b)
{ {
rA = rA | b; rA = rA | b;
rF=0; rF=0;
FLAGS_SZXY(rA); if (rA==0) SET_FLAGS(fZ);
SET_PARITY_FLAG(rA);
} }
void CP(uint8_t b) void CP(uint8_t b)
@@ -365,30 +319,11 @@ namespace sm83
SUB8(b, false); SUB8(b, false);
} }
void LD_A_I()
{
t++;
rA = rI;
KEEP_FLAGS(fC);
FLAGS_SZXY(rA);
if (iff2) SET_FLAGS(fP);
}
void LD_A_R()
{
t++;
rA = rR;
KEEP_FLAGS(fC);
FLAGS_SZXY(rA);
if (iff2) SET_FLAGS(fP);
}
void RLCA() void RLCA()
{ {
const bool should_carry = rA & 0x80; const bool should_carry = rA & 0x80;
rA = (rA>>7) | (rA<<1); rA = (rA>>7) | (rA<<1);
KEEP_FLAGS(fS | fZ | fP); rF = 0;
SET_FLAGS(rA & (fX | fY));
if (should_carry) SET_FLAGS(fC); if (should_carry) SET_FLAGS(fC);
} }
@@ -396,8 +331,7 @@ namespace sm83
{ {
const bool should_carry = rA & 0x01; const bool should_carry = rA & 0x01;
rA = (rA<<7) | (rA>>1); rA = (rA<<7) | (rA>>1);
KEEP_FLAGS(fS | fZ | fP); rF = 0;
SET_FLAGS(rA & (fX | fY));
if (should_carry) SET_FLAGS(fC); if (should_carry) SET_FLAGS(fC);
} }
@@ -405,8 +339,7 @@ namespace sm83
{ {
const bool should_carry = rA & 0x80; const bool should_carry = rA & 0x80;
rA = (rA<<1) | (rF&fC); rA = (rA<<1) | (rF&fC);
KEEP_FLAGS(fS | fZ | fP); rF = 0;
SET_FLAGS(rA & (fX | fY));
if (should_carry) SET_FLAGS(fC); if (should_carry) SET_FLAGS(fC);
} }
@@ -414,37 +347,11 @@ namespace sm83
{ {
const bool should_carry = rA & 0x01; const bool should_carry = rA & 0x01;
rA = ((rF&fC)<<7) | (rA>>1); rA = ((rF&fC)<<7) | (rA>>1);
KEEP_FLAGS(fS | fZ | fP); rF = 0;
SET_FLAGS(rA & (fX | fY));
if (should_carry) SET_FLAGS(fC); if (should_carry) SET_FLAGS(fC);
} }
void RRD() /*
{
uint8_t a = rA;
uint8_t hl = READ_MEM_8(rHL);
rA = (rA & 0xF0) | (hl & 0x0F);
hl = (hl >> 4) | (a << 4);
WRITE_MEM_8(rHL, hl);
KEEP_FLAGS(fC);
FLAGS_SZXY(rA);
SET_PARITY_FLAG(rA);
t+=4;
}
void RLD()
{
uint8_t a = rA;
uint8_t hl = READ_MEM_8(rHL);
rA = (rA & 0xF0) | (hl >> 4);
hl = (hl << 4) | (a & 0x0F);
WRITE_MEM_8(rHL, hl);
KEEP_FLAGS(fC);
FLAGS_SZXY(rA);
SET_PARITY_FLAG(rA);
t+=4;
}
void new_DAA() void new_DAA()
{ {
uint8_t cf = rA > 0x99; uint8_t cf = rA > 0x99;
@@ -459,18 +366,10 @@ namespace sm83
SET_FLAGS((rA ^ diff) & fH); SET_FLAGS((rA ^ diff) & fH);
SET_PARITY_FLAG(diff); SET_PARITY_FLAG(diff);
SET_FLAGS(cf); SET_FLAGS(cf);
/* FLAGS = (zuint8)(
(F & (NF | CF)) | // NF unchanged; CF dominant
(t & SYXF) | // SF = sign; YF = Y; XF = X
ZF_ZERO(t) | // ZF = zero
((A ^ t) & HF) | // HF = Ai.4 != Ao.4
PF_PARITY(t) | // PF = parity
cf); // CF |= 1 (if BCD carry)
*/
rA = diff; rA = diff;
t+=4; t+=4;
} }
*/
void DAA() void DAA()
{ {
bool carry_set = false; bool carry_set = false;
@@ -479,112 +378,87 @@ namespace sm83
rA += 0x06; rA += 0x06;
if ( (rA >> 4)>9 || (rF & fC) ) { rA += 0x60; carry_set = true; } if ( (rA >> 4)>9 || (rF & fC) ) { rA += 0x60; carry_set = true; }
KEEP_FLAGS(fN); KEEP_FLAGS(fN);
FLAGS_SZXY(rA); if (rA==0) SET_FLAGS(fZ);
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(rA);
} }
void CPL() void CPL()
{ {
rA = ~rA; rA = ~rA;
KEEP_FLAGS(fS | fZ | fP | fC); KEEP_FLAGS(fZ | fC);
SET_FLAGS(fH | fN); SET_FLAGS(fH | fN);
SET_FLAGS(rA & (fX | fY));
} }
void SCF() void SCF()
{ {
KEEP_FLAGS( fS | fZ | fP ); KEEP_FLAGS( fZ );
SET_FLAGS(fC); SET_FLAGS(fC);
SET_FLAGS(rA & (fX | fY));
} }
void CCF() void CCF()
{ {
const bool carry = (rF & fC); const bool carry = (rF & fC);
KEEP_FLAGS( fS | fZ | fP ); KEEP_FLAGS( fZ );
SET_FLAGS(carry ? fH : fC); SET_FLAGS(carry ? fH : fC);
SET_FLAGS(rA & (fX | fY));
} }
void DJNZ() void JR(uint8_t cond = cUnconditional)
{ {
const int8_t d = (int8_t)READ_MEM_8(); const int8_t d = (int8_t)READ_MEM_8();
rB--; if ( cond == cUnconditional ||
if (rB!=0)
{
rPC = rPC + d;
t+=5;
}
}
void JR(uint8_t cond = cNO)
{
const int8_t d = (int8_t)READ_MEM_8();
if ( cond == cNO ||
( (cond == cNZ) && !(rF & fZ) ) || ( (cond == cNZ) && !(rF & fZ) ) ||
( (cond == cZ) && (rF & fZ) ) || ( (cond == cZ) && (rF & fZ) ) ||
( (cond == cNC) && !(rF & fC) ) || ( (cond == cNC) && !(rF & fC) ) ||
( (cond == cC) && (rF & fC) ) ) ( (cond == cC) && (rF & fC) ) )
{ {
rPC = rPC + d; rPC = rPC + d;
t+=5; t+=4;
} }
} }
void JP(uint8_t cond, uint16_t addr) void JP(uint8_t cond, uint16_t addr, const bool fast = false)
{ {
if ( cond == cNO || if ( cond == cUnconditional ||
( (cond == cNZ) && !(rF & fZ) ) || ( (cond == cNZ) && !(rF & fZ) ) ||
( (cond == cZ) && (rF & fZ) ) || ( (cond == cZ) && (rF & fZ) ) ||
( (cond == cNC) && !(rF & fC) ) || ( (cond == cNC) && !(rF & fC) ) ||
( (cond == cC) && (rF & fC) ) || ( (cond == cC) && (rF & fC) ) )
( (cond == cPO) && !(rF & fV) ) ||
( (cond == cPE) && (rF & fV) ) ||
( (cond == cM) && (rF & fS) ) ||
( (cond == cP) && !(rF & fS) ) )
rPC = addr; rPC = addr;
if (!fast) t+=4;
} }
void CALL(uint8_t cond, uint16_t addr) void CALL(uint8_t cond, uint16_t addr)
{ {
if ( cond == cNO || if ( cond == cUnconditional ||
( (cond == cNZ) && !(rF & fZ) ) || ( (cond == cNZ) && !(rF & fZ) ) ||
( (cond == cZ) && (rF & fZ) ) || ( (cond == cZ) && (rF & fZ) ) ||
( (cond == cNC) && !(rF & fC) ) || ( (cond == cNC) && !(rF & fC) ) ||
( (cond == cC) && (rF & fC) ) || ( (cond == cC) && (rF & fC) ) )
( (cond == cPO) && !(rF & fV) ) ||
( (cond == cPE) && (rF & fV) ) ||
( (cond == cM) && (rF & fS) ) ||
( (cond == cP) && !(rF & fS) ) )
{ {
PUSH(rPC); PUSH(rPC);
rPC = addr; rPC = addr;
if (options[Z80_OPTION_BREAK_ON_RET]) { /*if (options[Z80_OPTION_BREAK_ON_RET]) {
calls_stacked++; calls_stacked++;
printf("CALL: calls stacked: %i", calls_stacked); printf("CALL: calls stacked: %i", calls_stacked);
} }*/
} }
} }
void RET(uint8_t cond) void RET(uint8_t cond)
{ {
if ( cond == cNO || t+=4;
if ( cond == cUnconditional ||
( (cond == cNZ) && !(rF & fZ) ) || ( (cond == cNZ) && !(rF & fZ) ) ||
( (cond == cZ) && (rF & fZ) ) || ( (cond == cZ) && (rF & fZ) ) ||
( (cond == cNC) && !(rF & fC) ) || ( (cond == cNC) && !(rF & fC) ) ||
( (cond == cC) && (rF & fC) ) || ( (cond == cC) && (rF & fC) ) )
( (cond == cPO) && !(rF & fV) ) ||
( (cond == cPE) && (rF & fV) ) ||
( (cond == cM) && (rF & fS) ) ||
( (cond == cP) && !(rF & fS) ) )
{ {
POP(_rPC); POP(_rPC);
if (cond != cNO) t++; if (cond != cUnconditional) t += 4;
if (options[Z80_OPTION_BREAK_ON_RET]) { /*if (options[Z80_OPTION_BREAK_ON_RET]) {
if (calls_stacked>0) { if (calls_stacked>0) {
calls_stacked--; calls_stacked--;
printf("RET: calls still stacked: %i\n", calls_stacked); printf("RET: calls still stacked: %i\n", calls_stacked);
@@ -595,63 +469,70 @@ namespace sm83
z80debug::history::store(); z80debug::history::store();
z80debug::stop(); z80debug::stop();
} }
} }*/
} else {
t++;
} }
} }
void RETN() void processInterrupts()
{ {
POP(_rPC); const uint8_t IF = mem::readMem(0xff0f);
iff1 = iff2; if ( (IF & 0x1f) == 0) return;
DI();
if (options[Z80_OPTION_BREAK_ON_RET]) { PUSH(rPC);
options[Z80_OPTION_BREAK_ON_RET] = false; t+=20;
if (IF & INTERRUPT_VBLANK) {
rPC = 0x40;
mem::writeMem(0xff0f, IF & ~INTERRUPT_VBLANK);
} else if (IF & INTERRUPT_LCD) {
rPC = 0x40;
mem::writeMem(0xff0f, IF & ~INTERRUPT_LCD);
} else if (IF & INTERRUPT_TIMER) {
rPC = 0x40;
mem::writeMem(0xff0f, IF & ~INTERRUPT_TIMER);
} else if (IF & INTERRUPT_SERIAL) {
rPC = 0x40;
mem::writeMem(0xff0f, IF & ~INTERRUPT_SERIAL);
} else if (IF & INTERRUPT_JOYPAD) {
rPC = 0x40;
mem::writeMem(0xff0f, IF & ~INTERRUPT_JOYPAD);
}
/*if (options[Z80_OPTION_BREAK_ON_INTERRUPT]) {
printf("Break on interrupt! 0x%2x, PC: 0x%2x\n", address, rPC);
z80debug::setcursor(rPC); z80debug::setcursor(rPC);
z80debug::history::store(); z80debug::history::store();
z80debug::stop(); z80debug::stop();
} }*/
} }
void RETI() void RETI()
{ {
RETN(); RET(cUnconditional);
*_rIME = 1;
processInterrupts();
} }
void RST(uint8_t vec) void RST(uint8_t vec)
{ {
t-=4; // PUSH i RST duren el mateix en la gameboy, per tant llevem els 4 t que duiem de llegir el opcode
PUSH(rPC); PUSH(rPC);
rPC = vec; rPC = vec;
} }
void IM(uint8_t mode)
{
im = mode;
}
void EX_MEM(uint16_t *reg, uint16_t addr)
{
auto temp = *reg;
*reg = READ_MEM_16(addr);
WRITE_MEM_16(addr, temp);
t+=3;
}
void DI() void DI()
{ {
iff1 = iff2 = 0; pending_ei = 0; // If interrupts are disabled right after enabling them, they keep disabled
*_rIME = 0;
} }
void EI() void EI()
{ {
pending_ei=1; pending_ei = 1; // Enabling interrupts is delayed by one instruction
} }
void actualEI() void actualEI()
{ {
iff1 = iff2 = 1; *_rIME = 1;
processInterrupts();
} }
void HALT() void HALT()
@@ -664,38 +545,21 @@ namespace sm83
} }
} }
void interrupt() void interrupt(uint8_t type)
{ {
if (!iff1) return;
DI();
exit_from_halt = true; exit_from_halt = true;
PUSH(rPC); const uint8_t IE = mem::readMem(0xffff);
uint16_t address; const uint8_t IF = mem::readMem(0xff0f);
if (im==1) { mem::writeMem(0xff0f, IF || (IE & type));
rPC = 0x38; processInterrupts();
} else if (im==2) {
address = (rI<<8) | 0xFE;
rPC = READ_MEM_16(address);
} else if (im==0) {
printf("Interrupt mode 0!\n");
z80debug::stop();
return;
}
if (options[Z80_OPTION_BREAK_ON_INTERRUPT]) {
printf("Break on interrupt! 0x%2x, PC: 0x%2x\n", address, rPC);
z80debug::setcursor(rPC);
z80debug::history::store();
z80debug::stop();
}
} }
static inline const uint8_t RLC(const uint8_t v) static inline const uint8_t RLC(const uint8_t v)
{ {
const uint8_t res = (v>>7) | (v<<1); const uint8_t res = (v>>7) | (v<<1);
rF=0; rF=0;
FLAGS_SZXY(res); if (res==0) SET_FLAGS(fZ);
if (res&1) SET_FLAGS(fC); if (res&1) SET_FLAGS(fC);
SET_PARITY_FLAG(res);
return res; return res;
} }
@@ -703,9 +567,8 @@ namespace sm83
{ {
const uint8_t res = (v<<7) | (v>>1); const uint8_t res = (v<<7) | (v>>1);
rF=0; rF=0;
FLAGS_SZXY(res); if (res==0) SET_FLAGS(fZ);
if (res&0x80) SET_FLAGS(fC); if (res&0x80) SET_FLAGS(fC);
SET_PARITY_FLAG(res);
return res; return res;
} }
@@ -713,9 +576,8 @@ namespace sm83
{ {
const uint8_t res = (v<<1) | (rF&fC); const uint8_t res = (v<<1) | (rF&fC);
rF=0; rF=0;
FLAGS_SZXY(res); if (res==0) SET_FLAGS(fZ);
if (v&0x80) SET_FLAGS(fC); if (v&0x80) SET_FLAGS(fC);
SET_PARITY_FLAG(res);
return res; return res;
} }
@@ -723,9 +585,8 @@ namespace sm83
{ {
const uint8_t res = ((rF&fC)<<7) | (v>>1); const uint8_t res = ((rF&fC)<<7) | (v>>1);
rF=0; rF=0;
FLAGS_SZXY(res); if (res==0) SET_FLAGS(fZ);
if (v&1) SET_FLAGS(fC); if (v&1) SET_FLAGS(fC);
SET_PARITY_FLAG(res);
return res; return res;
} }
@@ -733,9 +594,8 @@ namespace sm83
{ {
const uint8_t res = (v<<1); const uint8_t res = (v<<1);
rF=0; rF=0;
FLAGS_SZXY(res); if (res==0) SET_FLAGS(fZ);
if (v&0x80) SET_FLAGS(fC); if (v&0x80) SET_FLAGS(fC);
SET_PARITY_FLAG(res);
return res; return res;
} }
@@ -743,9 +603,8 @@ namespace sm83
{ {
const uint8_t res = (v&0x80) | (v>>1); const uint8_t res = (v&0x80) | (v>>1);
rF=0; rF=0;
FLAGS_SZXY(res); if (res==0) SET_FLAGS(fZ);
if (v&1) SET_FLAGS(fC); if (v&1) SET_FLAGS(fC);
SET_PARITY_FLAG(res);
return res; return res;
} }
@@ -753,9 +612,8 @@ namespace sm83
{ {
const uint8_t res = (v<<1) | 1; const uint8_t res = (v<<1) | 1;
rF=0; rF=0;
FLAGS_SZXY(res); if (res==0) SET_FLAGS(fZ);
if (v&0x80) SET_FLAGS(fC); if (v&0x80) SET_FLAGS(fC);
SET_PARITY_FLAG(res);
return res; return res;
} }
@@ -763,9 +621,8 @@ namespace sm83
{ {
const uint8_t res = (v>>1); const uint8_t res = (v>>1);
rF=0; rF=0;
FLAGS_SZXY(res); if (res==0) SET_FLAGS(fZ);
if (v&1) SET_FLAGS(fC); if (v&1) SET_FLAGS(fC);
SET_PARITY_FLAG(res);
return res; return res;
} }
@@ -774,10 +631,7 @@ namespace sm83
const uint8_t res = v & 1<<pos; const uint8_t res = v & 1<<pos;
KEEP_FLAGS(fC); KEEP_FLAGS(fC);
SET_FLAGS(fH); SET_FLAGS(fH);
if (!res) SET_FLAGS(fZ | fP); if (res==0) SET_FLAGS(fZ);
if (res&0x80) SET_FLAGS(fS);
if (res&0x20) SET_FLAGS(fY);
if (res&0x08) SET_FLAGS(fX);
} }
static inline const uint8_t SET(uint8_t pos, const uint8_t v) static inline const uint8_t SET(uint8_t pos, const uint8_t v)
@@ -790,245 +644,42 @@ namespace sm83
return v & ~(1<<pos); return v & ~(1<<pos);
} }
void LDI() void LDI_A_HL()
{ {
WRITE_MEM_8(rDE, READ_MEM_8(rHL)); rA = READ_MEM_8(rHL);
rDE++;
rHL++; rHL++;
rBC--;
t+=2;
KEEP_FLAGS(fS | fZ | fC);
if (rBC!=0) SET_FLAGS(fP);
} }
void LDIR() void LDI_HL_A()
{ {
LDI(); WRITE_MEM_8(rHL, rA);
if (rBC!=0)
{
rPC-=2;
t+=5;
}
}
void LDD()
{
WRITE_MEM_8(rDE, READ_MEM_8(rHL));
rDE--;
rHL--;
rBC--;
t+=2;
KEEP_FLAGS(fS | fZ | fC);
if (rBC!=0) SET_FLAGS(fP);
}
void LDDR()
{
LDD();
if (rBC!=0)
{
rPC-=2;
t+=5;
}
}
uint8_t CPI()
{
bool keep_fC = (rF & fC);
const uint8_t hlmem = READ_MEM_8(rHL);
CP(hlmem);
rHL++; rHL++;
rBC--;
t+=2;
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);
return hlmem;
} }
void CPIR() void LDD_A_HL()
{ {
const uint8_t hlmem = CPI(); rA = READ_MEM_8(rHL);
if (rBC!=0 && hlmem!=rA)
{
rPC-=2;
t+=2;
}
}
void CPD()
{
bool keep_fC = (rF & fC);
CP(READ_MEM_8(rHL));
rHL--; rHL--;
rBC--;
t+=2;
KEEP_FLAGS(fS | fZ | fH | fN);
if (keep_fC) SET_FLAGS(fC);
if (rBC!=0) SET_FLAGS(fP);
}
void CPDR()
{
CPD();
if (rBC!=0 && READ_MEM_8(rHL)!=rA)
{
rPC-=2;
t+=2;
}
} }
const uint8_t IN(int port = 0x10000) void LDD_HL_A()
{ {
bool set_flags=true; WRITE_MEM_8(rHL, rA);
t+=4;
if (port == 0x10000) {
port = rBC;
} else {
set_flags=false;
port = (rA<<8) | port;
}
if (in_ports[port&0xff]) {
const uint8_t val = (uint8_t)in_ports[port&0xff](port);
if (set_flags) {
KEEP_FLAGS(fC);
SET_PARITY_FLAG(val);
FLAGS_SZXY(val);
}
return val;
} else
return 0xFF;
}
void OUT(uint8_t val, int port = 0x10000)
{
t+=4;
if (port == 0x10000) {
port = rBC;
if (rC==0xfe) port = 0xfe;
}
if (out_ports[port&0xff]) out_ports[port&0xff](port, val);
}
void INI()
{
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;
}
void INIR()
{
INI();
if (rB!=0)
{
rPC-=2;
t+=5;
}
}
void IND()
{
DEC8(_rB);
const uint8_t flags_after_dec = rF;
const uint8_t val = IN();
WRITE_MEM_8(rHL, val);
rHL--; 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;
}
void INDR()
{
IND();
if (rB!=0)
{
rPC-=2;
t+=5;
}
}
void OUTI()
{
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;
}
void OUTIR()
{
OUTI();
if (rB!=0)
{
rPC-=2;
t+=5;
}
}
void OUTD() {
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;
}
void OUTDR() {
OUTD();
if (rB!=0)
{
rPC-=2;
t+=5;
}
} }
void INVALID(uint8_t opcode) void INVALID(uint8_t opcode)
{ {
printf("INVALID OPCODE AT: %04x\n", current_opcode_address); printf("INVALID OPCODE AT: %04x\n", current_opcode_address);
if (options[Z80_OPTION_STOP_ON_INVALID]) z80debug::stop(); //if (options[Z80_OPTION_STOP_ON_INVALID]) z80debug::stop();
} }
void reset() void reset()
{ {
for (int i=0; i<256; ++i) mem::reset();
{
in_ports[i] = nullptr;
out_ports[i] = nullptr;
}
z80mem::get()->reset(); rPC = ime = 0;
rAF = rBC = rDE = rHL = rSP = 0xffff;
rPC = iff1 = iff2 = im = 0;
rAF = rAF2 = rBC = rBC2 = rDE = rDE2 = rHL = rHL2 = rIX = rIY = rSP = 0xffff;
t = 0; t = 0;
} }
@@ -1043,17 +694,6 @@ namespace sm83
} }
void BIT_INSTRUCTIONS(); void BIT_INSTRUCTIONS();
void IX_INSTRUCTIONS();
void IX_BIT_INSTRUCTIONS();
void MISC_INSTRUCTIONS();
void IY_INSTRUCTIONS();
void IY_BIT_INSTRUCTIONS();
void connect_port(int num, int (*in_ptr)(int), void (*out_ptr)(int,int))
{
if (in_ptr) in_ports[num] = in_ptr;
if (out_ptr) out_ports[num] = out_ptr;
}
bool opcode_ignored = false; bool opcode_ignored = false;
uint32_t step() uint32_t step()
@@ -1064,14 +704,14 @@ namespace sm83
t = 0; t = 0;
const uint8_t opcode = READ_M1(); const uint8_t opcode = READ_M1();
uint8_t tag = z80mem::get()->getTag(current_opcode_address); /*uint8_t tag = z80mem::get()->getTag(current_opcode_address);
if ( !(tag & MEMTAG_IGNORE) ) if ( !(tag & MEMTAG_IGNORE) )
tag = tag | MEMTAG_INST; tag = tag | MEMTAG_INST;
z80mem::get()->setTag(current_opcode_address, tag | (!(tag&MEMTAG_TOUCHED) ? MEMTAG_TREPEAT : MEMTAG_TINST) ); z80mem::get()->setTag(current_opcode_address, tag | (!(tag&MEMTAG_TOUCHED) ? MEMTAG_TREPEAT : MEMTAG_TINST) );*/
uint16_t tmp; uint16_t tmp;
if (opcode!=0xED && opcode!=0xCB && opcode!=0xDD && opcode!=0xFD ) z80debug::useOpcode(opcode, 0); //if (opcode!=0xED && opcode!=0xCB && opcode!=0xDD && opcode!=0xFD ) z80debug::useOpcode(opcode, 0);
switch (opcode) switch (opcode)
{ {
@@ -1322,7 +962,7 @@ namespace sm83
case 0xE6: AND(READ_MEM_8()); break; case 0xE6: AND(READ_MEM_8()); break;
case 0xE7: RST(0x20); break; case 0xE7: RST(0x20); break;
case 0xE8: RET(cPE); break; case 0xE8: RET(cPE); break;
case 0xE9: JP(cNO, rHL); break; case 0xE9: JP(cNO, rHL, true); break;
case 0xEA: JP(cPE, READ_MEM_16()); break; case 0xEA: JP(cPE, READ_MEM_16()); break;
case 0xEB: EX(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;

8
sm83.h
View File

@@ -4,6 +4,12 @@
namespace sm83 namespace sm83
{ {
#define INTERRUPT_VBLANK 0x01
#define INTERRUPT_LCD 0x02
#define INTERRUPT_TIMER 0x04
#define INTERRUPT_SERIAL 0x08
#define INTERRUPT_JOYPAD 0x10
#define SM83_OPTION_STOP_ON_INVALID 0 #define SM83_OPTION_STOP_ON_INVALID 0
#define SM83_OPTION_BREAK_ON_INTERRUPT 1 #define SM83_OPTION_BREAK_ON_INTERRUPT 1
#define SM83_OPTION_BREAK_ON_RET 2 #define SM83_OPTION_BREAK_ON_RET 2
@@ -14,7 +20,7 @@ namespace sm83
void setClock(uint32_t freq); void setClock(uint32_t freq);
uint32_t getClock(); uint32_t getClock();
void interrupt(); void interrupt(uint8_t type);
uint32_t step(); uint32_t step();