- Treballant en la CPU
This commit is contained in:
572
sm83.cpp
572
sm83.cpp
@@ -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()
|
||||
{
|
||||
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;
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user