- 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 "mem.h"
//#include "z80debug.h"
//#include "z80mem.h"
#include <stdio.h>
@@ -66,7 +67,7 @@ namespace sm83
#define rSP (*_rSP)
#define rPC (*_rPC)
#define im2 (*_rIME)
#define ime (*_rIME)
#define EX(a,b) {auto temp=a;a=b;b=temp;}
@@ -91,7 +92,7 @@ namespace sm83
}
*/
reading_m1 = false;
return z80mem::get()->readMem(addr);
return mem::readMem(addr);
}
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)
{
t+=4;
z80mem::get()->writeMem(addr, value);
mem::writeMem(addr, value);
/*
if (z80debug::isbreak(addr, 4)) z80debug::stop();
@@ -194,40 +195,12 @@ namespace sm83
*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)
{
uint8_t value = *reg + 1;
KEEP_FLAGS(fC);
FLAGS_SZXY(value);
if (value == 0x80) SET_FLAGS(fV);
if (value==0) SET_FLAGS(fZ);
if ( (value & 0x0f) == 0x00 ) SET_FLAGS(fH);
*reg = value;
@@ -238,9 +211,8 @@ namespace sm83
uint8_t value = *reg - 1;
KEEP_FLAGS(fC);
FLAGS_SZXY(value);
SET_FLAGS(fN);
if (value == 0x7f) SET_FLAGS(fV);
if (value==0) SET_FLAGS(fZ);
if ( (value & 0x0f) == 0x0f ) SET_FLAGS(fH);
*reg = value;
@@ -248,13 +220,11 @@ namespace sm83
void INCMEM8(const uint16_t addr)
{
t++;
uint8_t value = READ_MEM_8(addr);
value++;
KEEP_FLAGS(fC);
FLAGS_SZXY(value);
if (value == 0x80) SET_FLAGS(fV);
if (value==0) SET_FLAGS(fZ);
if ( (value & 0x0f) == 0x00 ) SET_FLAGS(fH);
WRITE_MEM_8(addr, value);
@@ -262,14 +232,12 @@ namespace sm83
void DECMEM8(const uint16_t addr)
{
t+=1;
uint8_t value = READ_MEM_8(addr);
value--;
KEEP_FLAGS(fC);
FLAGS_SZXY(value);
SET_FLAGS(fN);
if (value == 0x7f) SET_FLAGS(fV);
if (value==0) SET_FLAGS(fZ);
if ( (value & 0x0f) == 0x0f ) SET_FLAGS(fH);
WRITE_MEM_8(addr, value);
@@ -292,10 +260,9 @@ namespace sm83
else {
uint16_t res = rA + b + 1;
rF=0;
FLAGS_SZXY(res);
if (res==0) SET_FLAGS(fZ);
if ( (res & 0x0f) <= (rA & 0x0f) ) SET_FLAGS(fH);
if ( res > 255 ) SET_FLAGS(fC);
if ( (b^rA^0x80) & (b^res) & 0x80 ) SET_FLAGS(fV);
rA = (uint8_t)res;
}
}
@@ -304,11 +271,10 @@ namespace sm83
{
const uint8_t res = rA - b;
rF=0;
FLAGS_SZXY(res);
if (res==0) SET_FLAGS(fZ);
SET_FLAGS(fN);
if ( (res & 0x0f) > (rA & 0x0f) ) SET_FLAGS(fH);
if ( res > rA ) SET_FLAGS(fC);
if ( (b^rA) & (rA^res) & 0x80 ) SET_FLAGS(fV);
if (update) rA = (uint8_t)res;
}
@@ -319,45 +285,33 @@ namespace sm83
else {
const uint8_t res = rA - b - 1;
rF=0;
FLAGS_SZXY(res);
if (res==0) SET_FLAGS(fZ);
SET_FLAGS(fN);
if ( (res & 0x0f) >= (rA & 0x0f) ) SET_FLAGS(fH);
if ( res >= rA ) SET_FLAGS(fC);
if ( (b^rA) & (rA^res) & 0x80 ) SET_FLAGS(fV);
rA = (uint8_t)res;
}
}
void NEG()
{
uint8_t val = rA;
rA = 0;
SUB8(val);
}
void AND(uint8_t b)
{
rA = rA & b;
rF=0;
FLAGS_SZXY(rA);
SET_PARITY_FLAG(rA);
SET_FLAGS(fH);
rF=fH;
if (rA==0) SET_FLAGS(fZ);
}
void XOR(uint8_t b)
{
rA = rA ^ b;
rF=0;
FLAGS_SZXY(rA);
SET_PARITY_FLAG(rA);
if (rA==0) SET_FLAGS(fZ);
}
void OR(uint8_t b)
{
rA = rA | b;
rF=0;
FLAGS_SZXY(rA);
SET_PARITY_FLAG(rA);
if (rA==0) SET_FLAGS(fZ);
}
void CP(uint8_t b)
@@ -365,30 +319,11 @@ namespace sm83
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()
{
const bool should_carry = rA & 0x80;
rA = (rA>>7) | (rA<<1);
KEEP_FLAGS(fS | fZ | fP);
SET_FLAGS(rA & (fX | fY));
rF = 0;
if (should_carry) SET_FLAGS(fC);
}
@@ -396,8 +331,7 @@ namespace sm83
{
const bool should_carry = rA & 0x01;
rA = (rA<<7) | (rA>>1);
KEEP_FLAGS(fS | fZ | fP);
SET_FLAGS(rA & (fX | fY));
rF = 0;
if (should_carry) SET_FLAGS(fC);
}
@@ -405,8 +339,7 @@ namespace sm83
{
const bool should_carry = rA & 0x80;
rA = (rA<<1) | (rF&fC);
KEEP_FLAGS(fS | fZ | fP);
SET_FLAGS(rA & (fX | fY));
rF = 0;
if (should_carry) SET_FLAGS(fC);
}
@@ -414,37 +347,11 @@ namespace sm83
{
const bool should_carry = rA & 0x01;
rA = ((rF&fC)<<7) | (rA>>1);
KEEP_FLAGS(fS | fZ | fP);
SET_FLAGS(rA & (fX | fY));
rF = 0;
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()
{
uint8_t cf = rA > 0x99;
@@ -459,18 +366,10 @@ namespace sm83
SET_FLAGS((rA ^ diff) & fH);
SET_PARITY_FLAG(diff);
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;
t+=4;
}
*/
void DAA()
{
bool carry_set = false;
@@ -479,112 +378,87 @@ namespace sm83
rA += 0x06;
if ( (rA >> 4)>9 || (rF & fC) ) { rA += 0x60; carry_set = true; }
KEEP_FLAGS(fN);
FLAGS_SZXY(rA);
if (rA==0) SET_FLAGS(fZ);
if ( (rA & 0x0F) < (old & 0x0F) ) SET_FLAGS(fH);
if (carry_set) SET_FLAGS(fC);
SET_PARITY_FLAG(rA);
}
void CPL()
{
rA = ~rA;
KEEP_FLAGS(fS | fZ | fP | fC);
KEEP_FLAGS(fZ | fC);
SET_FLAGS(fH | fN);
SET_FLAGS(rA & (fX | fY));
}
void SCF()
{
KEEP_FLAGS( fS | fZ | fP );
KEEP_FLAGS( fZ );
SET_FLAGS(fC);
SET_FLAGS(rA & (fX | fY));
}
void CCF()
{
const bool carry = (rF & fC);
KEEP_FLAGS( fS | fZ | fP );
KEEP_FLAGS( fZ );
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();
rB--;
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 ||
if ( cond == cUnconditional ||
( (cond == cNZ) && !(rF & fZ) ) ||
( (cond == cZ) && (rF & fZ) ) ||
( (cond == cNC) && !(rF & fC) ) ||
( (cond == cC) && (rF & fC) ) )
{
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 == cZ) && (rF & fZ) ) ||
( (cond == cNC) && !(rF & fC) ) ||
( (cond == cC) && (rF & fC) ) ||
( (cond == cPO) && !(rF & fV) ) ||
( (cond == cPE) && (rF & fV) ) ||
( (cond == cM) && (rF & fS) ) ||
( (cond == cP) && !(rF & fS) ) )
( (cond == cC) && (rF & fC) ) )
rPC = addr;
if (!fast) t+=4;
}
void CALL(uint8_t cond, uint16_t addr)
{
if ( cond == cNO ||
if ( cond == cUnconditional ||
( (cond == cNZ) && !(rF & fZ) ) ||
( (cond == cZ) && (rF & fZ) ) ||
( (cond == cNC) && !(rF & fC) ) ||
( (cond == cC) && (rF & fC) ) ||
( (cond == cPO) && !(rF & fV) ) ||
( (cond == cPE) && (rF & fV) ) ||
( (cond == cM) && (rF & fS) ) ||
( (cond == cP) && !(rF & fS) ) )
( (cond == cC) && (rF & fC) ) )
{
PUSH(rPC);
rPC = addr;
if (options[Z80_OPTION_BREAK_ON_RET]) {
/*if (options[Z80_OPTION_BREAK_ON_RET]) {
calls_stacked++;
printf("CALL: calls stacked: %i", calls_stacked);
}
}*/
}
}
void RET(uint8_t cond)
{
if ( cond == cNO ||
t+=4;
if ( cond == cUnconditional ||
( (cond == cNZ) && !(rF & fZ) ) ||
( (cond == cZ) && (rF & fZ) ) ||
( (cond == cNC) && !(rF & fC) ) ||
( (cond == cC) && (rF & fC) ) ||
( (cond == cPO) && !(rF & fV) ) ||
( (cond == cPE) && (rF & fV) ) ||
( (cond == cM) && (rF & fS) ) ||
( (cond == cP) && !(rF & fS) ) )
( (cond == cC) && (rF & fC) ) )
{
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) {
calls_stacked--;
printf("RET: calls still stacked: %i\n", calls_stacked);
@@ -595,63 +469,70 @@ namespace sm83
z80debug::history::store();
z80debug::stop();
}
}
} else {
t++;
}*/
}
}
void RETN()
void processInterrupts()
{
POP(_rPC);
iff1 = iff2;
if (options[Z80_OPTION_BREAK_ON_RET]) {
options[Z80_OPTION_BREAK_ON_RET] = false;
const uint8_t IF = mem::readMem(0xff0f);
if ( (IF & 0x1f) == 0) return;
DI();
PUSH(rPC);
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::history::store();
z80debug::stop();
}
}*/
}
void RETI()
{
RETN();
RET(cUnconditional);
*_rIME = 1;
processInterrupts();
}
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);
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()
{
iff1 = iff2 = 0;
pending_ei = 0; // If interrupts are disabled right after enabling them, they keep disabled
*_rIME = 0;
}
void EI()
{
pending_ei=1;
pending_ei = 1; // Enabling interrupts is delayed by one instruction
}
void actualEI()
{
iff1 = iff2 = 1;
*_rIME = 1;
processInterrupts();
}
void HALT()
@@ -664,38 +545,21 @@ namespace sm83
}
}
void interrupt()
void interrupt(uint8_t type)
{
if (!iff1) return;
DI();
exit_from_halt = true;
PUSH(rPC);
uint16_t address;
if (im==1) {
rPC = 0x38;
} 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();
}
const uint8_t IE = mem::readMem(0xffff);
const uint8_t IF = mem::readMem(0xff0f);
mem::writeMem(0xff0f, IF || (IE & type));
processInterrupts();
}
static inline const uint8_t RLC(const uint8_t v)
{
const uint8_t res = (v>>7) | (v<<1);
rF=0;
FLAGS_SZXY(res);
if (res==0) SET_FLAGS(fZ);
if (res&1) SET_FLAGS(fC);
SET_PARITY_FLAG(res);
return res;
}
@@ -703,9 +567,8 @@ namespace sm83
{
const uint8_t res = (v<<7) | (v>>1);
rF=0;
FLAGS_SZXY(res);
if (res==0) SET_FLAGS(fZ);
if (res&0x80) SET_FLAGS(fC);
SET_PARITY_FLAG(res);
return res;
}
@@ -713,9 +576,8 @@ namespace sm83
{
const uint8_t res = (v<<1) | (rF&fC);
rF=0;
FLAGS_SZXY(res);
if (res==0) SET_FLAGS(fZ);
if (v&0x80) SET_FLAGS(fC);
SET_PARITY_FLAG(res);
return res;
}
@@ -723,9 +585,8 @@ namespace sm83
{
const uint8_t res = ((rF&fC)<<7) | (v>>1);
rF=0;
FLAGS_SZXY(res);
if (res==0) SET_FLAGS(fZ);
if (v&1) SET_FLAGS(fC);
SET_PARITY_FLAG(res);
return res;
}
@@ -733,9 +594,8 @@ namespace sm83
{
const uint8_t res = (v<<1);
rF=0;
FLAGS_SZXY(res);
if (res==0) SET_FLAGS(fZ);
if (v&0x80) SET_FLAGS(fC);
SET_PARITY_FLAG(res);
return res;
}
@@ -743,9 +603,8 @@ namespace sm83
{
const uint8_t res = (v&0x80) | (v>>1);
rF=0;
FLAGS_SZXY(res);
if (res==0) SET_FLAGS(fZ);
if (v&1) SET_FLAGS(fC);
SET_PARITY_FLAG(res);
return res;
}
@@ -753,9 +612,8 @@ namespace sm83
{
const uint8_t res = (v<<1) | 1;
rF=0;
FLAGS_SZXY(res);
if (res==0) SET_FLAGS(fZ);
if (v&0x80) SET_FLAGS(fC);
SET_PARITY_FLAG(res);
return res;
}
@@ -763,9 +621,8 @@ namespace sm83
{
const uint8_t res = (v>>1);
rF=0;
FLAGS_SZXY(res);
if (res==0) SET_FLAGS(fZ);
if (v&1) SET_FLAGS(fC);
SET_PARITY_FLAG(res);
return res;
}
@@ -774,10 +631,7 @@ namespace sm83
const uint8_t res = v & 1<<pos;
KEEP_FLAGS(fC);
SET_FLAGS(fH);
if (!res) SET_FLAGS(fZ | fP);
if (res&0x80) SET_FLAGS(fS);
if (res&0x20) SET_FLAGS(fY);
if (res&0x08) SET_FLAGS(fX);
if (res==0) SET_FLAGS(fZ);
}
static inline const uint8_t SET(uint8_t pos, const uint8_t v)
@@ -790,245 +644,42 @@ namespace sm83
return v & ~(1<<pos);
}
void LDI()
void LDI_A_HL()
{
WRITE_MEM_8(rDE, READ_MEM_8(rHL));
rDE++;
rA = READ_MEM_8(rHL);
rHL++;
rBC--;
t+=2;
KEEP_FLAGS(fS | fZ | fC);
if (rBC!=0) SET_FLAGS(fP);
}
void LDIR()
void LDI_HL_A()
{
LDI();
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);
WRITE_MEM_8(rHL, rA);
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();
if (rBC!=0 && hlmem!=rA)
{
rPC-=2;
t+=2;
}
}
void CPD()
{
bool keep_fC = (rF & fC);
CP(READ_MEM_8(rHL));
rA = READ_MEM_8(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()
void LDD_HL_A()
{
CPD();
if (rBC!=0 && READ_MEM_8(rHL)!=rA)
{
rPC-=2;
t+=2;
}
}
const uint8_t IN(int port = 0x10000)
{
bool set_flags=true;
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);
WRITE_MEM_8(rHL, rA);
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)
{
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()
{
for (int i=0; i<256; ++i)
{
in_ports[i] = nullptr;
out_ports[i] = nullptr;
}
mem::reset();
z80mem::get()->reset();
rPC = iff1 = iff2 = im = 0;
rAF = rAF2 = rBC = rBC2 = rDE = rDE2 = rHL = rHL2 = rIX = rIY = rSP = 0xffff;
rPC = ime = 0;
rAF = rBC = rDE = rHL = rSP = 0xffff;
t = 0;
}
@@ -1043,17 +694,6 @@ namespace sm83
}
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;
uint32_t step()
@@ -1064,14 +704,14 @@ namespace sm83
t = 0;
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) )
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;
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)
{
@@ -1322,7 +962,7 @@ namespace sm83
case 0xE6: AND(READ_MEM_8()); break;
case 0xE7: RST(0x20); 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 0xEB: EX(rDE, rHL); break;
case 0xEC: CALL(cPE, READ_MEM_16()); break;

8
sm83.h
View File

@@ -4,6 +4,12 @@
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_BREAK_ON_INTERRUPT 1
#define SM83_OPTION_BREAK_ON_RET 2
@@ -14,7 +20,7 @@ namespace sm83
void setClock(uint32_t freq);
uint32_t getClock();
void interrupt();
void interrupt(uint8_t type);
uint32_t step();