public release of panzgb
This commit is contained in:
448
lib/gb-opcodes-impl.c
Executable file
448
lib/gb-opcodes-impl.c
Executable file
@@ -0,0 +1,448 @@
|
||||
#include "gb-impl.h"
|
||||
#include "gb-opcode.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define ROTATE_FLAG(cpu, bit, val) \
|
||||
{ \
|
||||
if (bit == 0) \
|
||||
RESET_CFLAG(cpu); \
|
||||
else \
|
||||
SET_CFLAG(cpu); \
|
||||
RESET_NFLAG(cpu); \
|
||||
RESET_HFLAG(cpu); \
|
||||
if (val == 0) \
|
||||
SET_ZFLAG(cpu); \
|
||||
else \
|
||||
RESET_ZFLAG(cpu); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
void LOAD_8BIT(BYTE *dest, BYTE src) {
|
||||
*dest = src;
|
||||
}
|
||||
|
||||
void LOAD_16BIT(BYTE *destA, BYTE *destB, WORD src) {
|
||||
*destB = src & 0xFF;
|
||||
*destA = (src >> 8) & 0xFF;
|
||||
}
|
||||
|
||||
void LDHL(gb *cpu) {
|
||||
uint32_t val;
|
||||
SIGNED_BYTE n;
|
||||
n = (SIGNED_BYTE)readMemory(cpu, cpu->progCounter);
|
||||
cpu->progCounter++;
|
||||
|
||||
// GET_BYTE_PC(cpu, n);
|
||||
val = (SIGNED_WORD)cpu->stack + (SIGNED_WORD)n;
|
||||
RESET_ZFLAG(cpu);
|
||||
RESET_NFLAG(cpu);
|
||||
|
||||
if (val > 0xFFFF)
|
||||
SET_CFLAG(cpu);
|
||||
else
|
||||
RESET_CFLAG(cpu);
|
||||
|
||||
WORD h = (val & 0x8FF);
|
||||
h += (cpu->stack & 0x8FF);
|
||||
|
||||
if (h > 0x8FF)
|
||||
SET_HFLAG(cpu);
|
||||
else
|
||||
RESET_HFLAG(cpu);
|
||||
|
||||
/*TODO check the flags*/
|
||||
cpu->L = val & 0xFF;
|
||||
cpu->H = (val >> 8) & 0xFF;
|
||||
}
|
||||
|
||||
void JMP(gb *cpu, WORD addr) {
|
||||
cpu->progCounter = addr;
|
||||
}
|
||||
|
||||
void ADD_8BIT(gb *cpu, BYTE *regA, BYTE regB) {
|
||||
WORD value = (*regA) + regB;
|
||||
|
||||
if (value > 255)
|
||||
SET_CFLAG(cpu);
|
||||
else
|
||||
RESET_CFLAG(cpu);
|
||||
|
||||
value &= 0xFF;
|
||||
RESET_NFLAG(cpu);
|
||||
if (value == 0)
|
||||
SET_ZFLAG(cpu);
|
||||
else
|
||||
RESET_ZFLAG(cpu);
|
||||
|
||||
WORD h = ((*regA) & 0xF);
|
||||
h += (regB & 0xF);
|
||||
|
||||
if (h > 0xF)
|
||||
SET_HFLAG(cpu);
|
||||
else
|
||||
RESET_HFLAG(cpu);
|
||||
*regA = value & 0xFF;
|
||||
}
|
||||
|
||||
void ADDC_8BIT(gb *cpu, BYTE *regA, BYTE regB) {
|
||||
ADD_8BIT(cpu, regA, (BYTE)(regB + ((cpu->F & 0x10) ? 1 : 0)));
|
||||
/* BYTE ret = regB + ((cpu->F &0x10)?1:0);
|
||||
WORD value = (*regA) + ret;
|
||||
//printf("(%x) %x +(%x) %x + %x (%x) = %x\n",i,*regA, (cpu->A),regB,
|
||||
((cpu->F &0x10)?1:0), cpu->F, value&0xff );
|
||||
|
||||
if(value > 0xff)
|
||||
SET_CFLAG(cpu);
|
||||
else
|
||||
RESET_CFLAG(cpu);
|
||||
|
||||
value &= 0xFF;
|
||||
RESET_NFLAG(cpu);
|
||||
if(value == 0)
|
||||
SET_ZFLAG(cpu);
|
||||
else
|
||||
RESET_ZFLAG(cpu);
|
||||
|
||||
WORD h = ((*(regA)) & 0xF) ;
|
||||
h += (ret & 0xF) ;
|
||||
|
||||
if (h > 0xF)
|
||||
SET_HFLAG(cpu);
|
||||
else
|
||||
RESET_HFLAG(cpu);
|
||||
*regA = value & 0xFF;*/
|
||||
}
|
||||
|
||||
void SUB_8BIT(gb *cpu, BYTE *regA, BYTE regB) {
|
||||
BYTE value = (*regA) - regB;
|
||||
SET_NFLAG(cpu);
|
||||
|
||||
if ((*regA) < regB)
|
||||
SET_CFLAG(cpu);
|
||||
else
|
||||
RESET_CFLAG(cpu);
|
||||
|
||||
value &= 0xFF;
|
||||
if (value == 0)
|
||||
SET_ZFLAG(cpu);
|
||||
else
|
||||
RESET_ZFLAG(cpu);
|
||||
|
||||
SIGNED_WORD h = ((*regA) & 0xF);
|
||||
h -= (regB & 0xF);
|
||||
|
||||
if (h < 0)
|
||||
SET_HFLAG(cpu);
|
||||
else
|
||||
RESET_HFLAG(cpu);
|
||||
*regA = (BYTE)value;
|
||||
}
|
||||
|
||||
void SUBC_8BIT(gb *cpu, BYTE *regA, BYTE regB) {
|
||||
SUB_8BIT(cpu, regA, (BYTE)(regB + ((cpu->F & 0x10) ? 1 : 0)));
|
||||
/*BYTE ret = regB + (SIGNED_BYTE)((cpu->F &0x10)?1:0);
|
||||
int32_t value = (*regA) - ret;
|
||||
|
||||
// printf("%x - %x - %x = %x\n",*regA, regB, ((cpu->F &0x10)?1:0), value );
|
||||
|
||||
SET_NFLAG(cpu);
|
||||
|
||||
if(value <0 ){
|
||||
SET_CFLAG(cpu);
|
||||
value+=256;
|
||||
}
|
||||
else
|
||||
RESET_CFLAG(cpu);
|
||||
|
||||
value &=0xFF;
|
||||
if(value == 0)
|
||||
SET_ZFLAG(cpu);
|
||||
else
|
||||
RESET_ZFLAG(cpu);
|
||||
|
||||
SIGNED_WORD h = (*regA & 0x0F) ;
|
||||
h -= (ret & 0x0F) ;
|
||||
|
||||
if ((ret & 0x0F) > (*regA & 0x0F) )
|
||||
SET_HFLAG(cpu);
|
||||
else
|
||||
RESET_HFLAG(cpu);
|
||||
*regA = value&0xff;*/
|
||||
}
|
||||
|
||||
void AND_8BIT(gb *cpu, BYTE *regA, BYTE regB) {
|
||||
BYTE val = *regA & regB;
|
||||
if (val == 0)
|
||||
SET_ZFLAG(cpu);
|
||||
else
|
||||
RESET_ZFLAG(cpu);
|
||||
RESET_NFLAG(cpu);
|
||||
SET_HFLAG(cpu);
|
||||
RESET_CFLAG(cpu);
|
||||
*regA = val;
|
||||
}
|
||||
|
||||
void OR_8BIT(gb *cpu, BYTE *regA, BYTE regB) {
|
||||
BYTE val = (*regA) | regB;
|
||||
if (val == 0)
|
||||
SET_ZFLAG(cpu);
|
||||
else
|
||||
RESET_ZFLAG(cpu);
|
||||
RESET_NFLAG(cpu);
|
||||
RESET_HFLAG(cpu);
|
||||
RESET_CFLAG(cpu);
|
||||
*regA = val;
|
||||
}
|
||||
|
||||
void XOR_8BIT(gb *cpu, BYTE *regA, BYTE regB) {
|
||||
BYTE val = (*regA) ^ regB;
|
||||
if (val == 0)
|
||||
SET_ZFLAG(cpu);
|
||||
else
|
||||
RESET_ZFLAG(cpu);
|
||||
RESET_NFLAG(cpu);
|
||||
RESET_HFLAG(cpu);
|
||||
RESET_CFLAG(cpu);
|
||||
*regA = val;
|
||||
}
|
||||
|
||||
void CP_8BIT(gb *cpu, BYTE regB) {
|
||||
BYTE temp = cpu->A;
|
||||
SUB_8BIT(cpu, &(cpu->A), regB);
|
||||
cpu->A = temp;
|
||||
}
|
||||
|
||||
void INC_8BIT(gb *cpu, BYTE *reg) {
|
||||
BYTE val = *reg;
|
||||
val++;
|
||||
if (((*reg) & 0xF) == 0)
|
||||
SET_HFLAG(cpu);
|
||||
else
|
||||
RESET_HFLAG(cpu);
|
||||
RESET_NFLAG(cpu);
|
||||
if (val == 0)
|
||||
SET_ZFLAG(cpu);
|
||||
else
|
||||
RESET_ZFLAG(cpu);
|
||||
*reg = val;
|
||||
}
|
||||
|
||||
void DEC_8BIT(gb *cpu, BYTE *reg) {
|
||||
BYTE val = *reg;
|
||||
val--;
|
||||
if (((*reg) & 0xF) == 0)
|
||||
SET_HFLAG(cpu);
|
||||
else
|
||||
RESET_HFLAG(cpu);
|
||||
SET_NFLAG(cpu);
|
||||
if (val == 0)
|
||||
SET_ZFLAG(cpu);
|
||||
else
|
||||
RESET_ZFLAG(cpu);
|
||||
*reg = val;
|
||||
}
|
||||
|
||||
void INC_16BIT(BYTE *regA, BYTE *regB) {
|
||||
WORD value = ((*regA) << 8) | (*regB);
|
||||
value++;
|
||||
*regA = (value >> 8) & 0xFF;
|
||||
*regB = value & 0xFF;
|
||||
}
|
||||
|
||||
void DEC_16BIT(BYTE *regA, BYTE *regB) {
|
||||
WORD value = ((*regA) << 8) | (*regB);
|
||||
value--;
|
||||
*regA = (value >> 8) & 0xFF;
|
||||
*regB = value & 0xFF;
|
||||
}
|
||||
|
||||
void SWAP_NIBBLES(gb *cpu, BYTE *reg) {
|
||||
BYTE val = *reg;
|
||||
val = ((val << 4) & 0xF0) | ((val >> 4) & 0xF);
|
||||
if (val == 0)
|
||||
SET_ZFLAG(cpu);
|
||||
else
|
||||
RESET_ZFLAG(cpu);
|
||||
RESET_NFLAG(cpu);
|
||||
RESET_HFLAG(cpu);
|
||||
RESET_CFLAG(cpu);
|
||||
*reg = val;
|
||||
}
|
||||
|
||||
void TEST_BIT(gb *cpu, BYTE val, BYTE numBit) {
|
||||
BYTE val2 = (val >> numBit) & 0x1;
|
||||
if (val2 == 0)
|
||||
SET_ZFLAG(cpu);
|
||||
else
|
||||
RESET_ZFLAG(cpu);
|
||||
RESET_NFLAG(cpu);
|
||||
SET_HFLAG(cpu);
|
||||
}
|
||||
|
||||
void RESET_BIT(gb *cpu, BYTE *val, BYTE numBit) {
|
||||
BYTE v = (*val) & (~(0x1 << numBit));
|
||||
*val = v;
|
||||
}
|
||||
|
||||
void SET_BIT(gb *cpu, BYTE *val, BYTE numBit) {
|
||||
BYTE v = (*val) | (0x1 << numBit);
|
||||
*val = v;
|
||||
}
|
||||
|
||||
void ADD_16BIT(gb *cpu, BYTE *regA, BYTE *regB, WORD src) {
|
||||
uint32_t val = (((*regA) << 8)) | ((*regB) & 0xFF);
|
||||
// uint32_t val = (((*regA)<<8)) | ((*regB) &0xFF);
|
||||
val += src;
|
||||
RESET_NFLAG(cpu);
|
||||
|
||||
if (val > 0xFFFF)
|
||||
SET_CFLAG(cpu);
|
||||
else
|
||||
RESET_CFLAG(cpu);
|
||||
|
||||
WORD h = (((((*regA) << 8)) | ((*regB) & 0xFF)) & 0x8FF);
|
||||
h += (src & 0x8FF);
|
||||
|
||||
if (h > 0x8FF)
|
||||
SET_HFLAG(cpu);
|
||||
else
|
||||
RESET_HFLAG(cpu);
|
||||
|
||||
*regA = (val >> 8) & 0xFF;
|
||||
*regB = (val & 0xFF);
|
||||
}
|
||||
|
||||
void ROTATE_LEFT(gb *cpu, BYTE *reg) {
|
||||
BYTE val = *reg;
|
||||
BYTE msb = (val >> 7) & 0x1;
|
||||
val <<= 1;
|
||||
val |= msb;
|
||||
cpu->F = 0;
|
||||
if (msb) {
|
||||
SET_CFLAG(cpu);
|
||||
} else {
|
||||
RESET_CFLAG(cpu);
|
||||
}
|
||||
if (val == 0)
|
||||
SET_ZFLAG(cpu);
|
||||
else
|
||||
RESET_ZFLAG(cpu);
|
||||
|
||||
*reg = val;
|
||||
}
|
||||
|
||||
void ROTATE_RIGHT(gb *cpu, BYTE *reg) {
|
||||
BYTE val = *reg;
|
||||
BYTE msb = (val & 0x1);
|
||||
cpu->F = 0;
|
||||
val >>= 1;
|
||||
if (msb) {
|
||||
val |= 0x80;
|
||||
SET_CFLAG(cpu);
|
||||
} else {
|
||||
val &= 0x7f;
|
||||
RESET_CFLAG(cpu);
|
||||
}
|
||||
if (val == 0)
|
||||
SET_ZFLAG(cpu);
|
||||
else
|
||||
RESET_ZFLAG(cpu);
|
||||
*reg = val;
|
||||
}
|
||||
|
||||
void ROTATE_LEFT_CARRY(gb *cpu, BYTE *reg) {
|
||||
BYTE val = *reg;
|
||||
BYTE msb = (val >> 7) & 0x1;
|
||||
val <<= 1;
|
||||
if (cpu->F & 0x10)
|
||||
val |= 0x1;
|
||||
if (msb)
|
||||
SET_CFLAG(cpu);
|
||||
else
|
||||
RESET_CFLAG(cpu);
|
||||
|
||||
if (val == 0)
|
||||
SET_ZFLAG(cpu);
|
||||
else
|
||||
RESET_ZFLAG(cpu);
|
||||
*reg = val;
|
||||
}
|
||||
|
||||
void ROTATE_RIGHT_CARRY(gb *cpu, BYTE *reg) {
|
||||
BYTE val = *reg;
|
||||
BYTE msb = val & 0x1;
|
||||
val >>= 1;
|
||||
if ((cpu->F & 0x10) != 0)
|
||||
val |= 0x80;
|
||||
else
|
||||
val &= 0x7f;
|
||||
if (msb)
|
||||
SET_CFLAG(cpu);
|
||||
else
|
||||
RESET_CFLAG(cpu);
|
||||
|
||||
if (val == 0)
|
||||
SET_ZFLAG(cpu);
|
||||
else
|
||||
RESET_ZFLAG(cpu);
|
||||
*reg = val;
|
||||
}
|
||||
|
||||
void SHIFT_LEFT(gb *cpu, BYTE *reg) {
|
||||
BYTE val = *reg;
|
||||
BYTE msb = (val >> 7) & 0x1;
|
||||
|
||||
val <<= 1;
|
||||
|
||||
ROTATE_FLAG(cpu, msb, val);
|
||||
*reg = val;
|
||||
}
|
||||
|
||||
void SHIFT_RIGHT_ARITH(gb *cpu, BYTE *reg) {
|
||||
BYTE val = *reg;
|
||||
BYTE lsb = (val)&0x1;
|
||||
BYTE msb = (val >> 7) & 0x1;
|
||||
|
||||
val >>= 1;
|
||||
val |= ((msb << 7));
|
||||
|
||||
ROTATE_FLAG(cpu, lsb, val);
|
||||
*reg = val;
|
||||
}
|
||||
|
||||
void SHIFT_RIGHT(gb *cpu, BYTE *reg) {
|
||||
BYTE val = *reg;
|
||||
BYTE lsb = (val)&0x1;
|
||||
|
||||
val >>= 1;
|
||||
|
||||
ROTATE_FLAG(cpu, lsb, val);
|
||||
*reg = val;
|
||||
}
|
||||
|
||||
void DAA(gb *cpu) {
|
||||
uint32_t a = cpu->A;
|
||||
|
||||
if (!(cpu->F & 0x40)) {
|
||||
if ((cpu->F & 0x20) || (a & 0xF) > 9)
|
||||
a += 0x06;
|
||||
if ((cpu->F & 0x10) || a > 0x9F)
|
||||
a += 0x60;
|
||||
} else {
|
||||
if ((cpu->F & 0x20) != 0)
|
||||
a -= 0x06;
|
||||
|
||||
if ((cpu->F & 0x10) != 0)
|
||||
a -= 0x60;
|
||||
}
|
||||
|
||||
cpu->F &= ~(0x20 | 0x80);
|
||||
if ((a & 0x100) == 0x100)
|
||||
SET_CFLAG(cpu);
|
||||
|
||||
a &= 0xFF;
|
||||
|
||||
if (a == 0)
|
||||
SET_ZFLAG(cpu);
|
||||
cpu->A = (BYTE)a;
|
||||
}
|
||||
Reference in New Issue
Block a user