rosgb/cpu.c
2024-05-17 22:13:30 -05:00

2181 lines
50 KiB
C

#include<inttypes.h>
#include<stdio.h>
#include<stdlib.h>
#include"cpu.h"
#include"ppu.h"
/* static char log_buffer[10*128]={0}; */
/* static size_t log_buffer_line=0; */
static char log_buffer[128*10]={0};
/* #define qprintf(...) do{\ */
/* if(!quiet){\ */
/* if(log_buffer_line<10)\ */
/* sprintf(log_buffer+(log_buffer_line++),__VA_ARGS__);\ */
/* }}while(0) */
//#define qprintf(...) do{size_t __i=0;if(!quiet){__i=sprintf(log_buffer,"%#x:",(cpu)->pc);sprintf(log_buffer+__i,__VA_ARGS__);}}while(0)
// This causes memory problems, why?
//#define qprintf(...) do{if(!quiet){int __i=sprintf(log_buffer,"%#x:",(cpu)->pc);sprintf((log_buffer+__i),__VA_ARGS__);}}while(0)
#define qprintf(...) do{if(!quiet)sprintf(log_buffer,__VA_ARGS__);}while(0)
char*cpu_log(void)
{
return log_buffer;
}
void cpu_fetch8(Cpu*cpu,uint8_t*rom,uint8_t*u8)
{
*u8=rom[cpu->pc++];
}
void cpu_fetch16(Cpu*cpu,uint8_t*rom,uint16_t*u16)
{
*u16=rom[cpu->pc]|rom[cpu->pc+1]<<8;
cpu->pc+=2;
}
// cpu_write_ram Allow access to read/write to ram
// through a filter for interrupts
void cpu_write_ram(struct Ppu*ppu,uint16_t addr,uint8_t val,uint8_t*ram)
{
if(addr>0x7fff)//don't write into ROM
ram[addr]=val;
if(addr==0xff46)//DMA Transfer
{
//for(uint16_t i=0;i<-0x9f;i++)
for(uint16_t i=0;i<0x9f;i++)
for(uint16_t j=0xfe00;j<=0xfe9f;j++)
ram[j]=ram[val*0x100|i];//copy from DMA reg src to FExx
}
if(addr==0xff00)//JOYP INT
{
ppu_updatejoypad(ppu,ram);//this is distinct from interrupts (?)
// cpu->sp-=2;
// // cpu_write_ram(cpu->sp,(uint16_t)cpu->pc&0x00ff,cpu,ram);
// // cpu_write_ram(cpu->sp+1,(uint16_t)cpu->pc>>8,cpu,ram);
// ram[(uint16_t)cpu->pc&0x00ff]=cpu->sp;
// ram[(uint16_t)cpu->pc>>8]=cpu->sp+1;
}
//return ram+*(uint8_t*)&addr;
return;
}
void cpu_romhexdump(uint8_t *rom)
{
for(uint16_t i=0;i<0xffff;i++)printf("%.2x ",rom[i]);
}
// Normal instructions
void cpu_decexec(Cpu*cpu,struct Ppu*ppu,uint8_t*rom,uint8_t*op,uint8_t*ram,bool quiet)
{
uint16_t tmp;
uint8_t tmp8;
switch(*op)
{
case 0x01://ld bc,m16
cpu_fetch16(cpu,rom,(uint16_t*)&tmp);
cpu->b=tmp>>8;
cpu->c=tmp&0x00ff;
qprintf("ld bc,%.4xh",cpu->b<<8|cpu->c);
break;
case 0x02://ld (bc),a
// *_ram(cpu->b<<8|cpu->c,ram)=cpu->a;
// ram[cpu->b<<8|cpu->c]=cpu->a;
cpu_write_ram(ppu,cpu->b<<8|cpu->c,cpu->a,ram);
qprintf("ld (bc),a ;(%.4xh)=%.2xh",cpu->b<<8|cpu->c,cpu->a);
break;
case 0x03://inc bc
tmp=((uint16_t)cpu->b<<8|cpu->c)+1; //lsh lower pri than add
cpu->b=tmp>>8;
cpu->c=tmp&0x00ff;
qprintf("inc bc ;%.4xh",cpu->b<<8|cpu->c);
break;
case 0x04://inc b
//flags:
cpu->f&=~F_N;//N 0
if((cpu->b&0xf)==0xf)cpu->f|=F_H;//H
else cpu->f&=~F_H;
cpu->b++;
if(cpu->b==0)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
qprintf("inc b");
break;
case 0x05://dec b
if(cpu->b&0x10&&!(cpu->b&0x08))cpu->f|=F_H;//H
else cpu->f&=~F_H;
cpu->b--;
if(cpu->b==0)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f|=F_N;//N
qprintf("dec b");
break;
case 0x06://ld b,m8
cpu_fetch8(cpu,rom,&cpu->b);
qprintf("ld b,%.2xh",cpu->b);
break;
case 0x07://rlca
if(cpu->a&0x80)cpu->f|=F_C;else cpu->f&=~F_C;//C
cpu->f&=F_C;//N 0,Z 0,H 0
tmp8=cpu->a;
if(cpu->f&F_C)asm("stc");
else asm("clc");
asm("rclb %0":"=m"(tmp8));
cpu->a=tmp8;
qprintf("rlca ;%.2x",tmp8);
break;
case 0x08://ld (m16),sp
cpu_fetch16(cpu,rom,(uint16_t*)&tmp);
// ram[tmp]=cpu->sp;
cpu_write_ram(ppu,tmp,cpu->sp,ram);
qprintf("ld (%.4xh),sp",tmp);
break;
case 0x09://add hl,bc
tmp=cpu->h<<8|cpu->l;
tmp+=cpu->b<<8|cpu->c;
cpu->b=tmp>>8;
cpu->c=(uint8_t)tmp;//trunc
qprintf("add hl,bc");
if(tmp<(cpu->b<<8|cpu->c))cpu->f|=F_C;//C
else cpu->f&=~F_C;
cpu->f&=~F_N;//N
//H
// if(cpu->f==0)cpu->f|=F_Z;else cpu->f&=~F_Z;//Z -
break;
case 0x0a: //ld a,(bc)
cpu->a=ram[cpu->b<<8|cpu->c];
qprintf("ld a,(bc)");
break;
case 0x0b: //dec bc
tmp=((uint16_t)cpu->b<<8|cpu->c)-1;
cpu->b=tmp>>8;
cpu->c=(uint8_t)tmp;
qprintf("dec bc");
break;
case 0x0c: //inc c
cpu->c++;
if(cpu->c==0)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
if((cpu->c&0xf)==0xf)cpu->f|=F_H;//H
else cpu->f&=~F_H;
qprintf("inc c");
break;
case 0x0d: //dec c
if(cpu->c&0x10&&!(cpu->c&0x08))cpu->f|=F_H;//H
else cpu->f&=~F_H;
cpu->c--;
if(cpu->c==0)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f|=F_N;//N
qprintf("dec c ;%.2xh",cpu->c);
break;
case 0x0e: //ld c,m8
cpu_fetch8(cpu,rom,&cpu->c);
qprintf("ld c,%.2xh",cpu->c);
break;
case 0x0f: //rrca
if(cpu->a&0x01)cpu->f|=F_C;else cpu->f&=~F_C;//C
cpu->f&=F_C;//N 0,Z 0,H 0
tmp8=cpu->a;
tmp8=ror(tmp8,1);
//asm("rorb %0":"=m"(tmp8));
cpu->a=tmp8;
qprintf("rrca ;%.2xh",tmp8);
break;
case 0x10://stop 0x00
cpu_fetch8(cpu,rom,(uint8_t*)(uint8_t*)&tmp);//second byte of opcode
qprintf("stop %.2xh ;10h 00h",tmp);
break;
case 0x11://ld de,m16
cpu_fetch16(cpu,rom,(uint16_t*)&tmp);
cpu->d=tmp>>8;
cpu->e=tmp&0x00ff;
qprintf("ld de,%.4xh",tmp);
break;
case 0x12://ld (de),a
// ram[cpu->d<<8|cpu->e]=cpu->a;
cpu_write_ram(ppu,cpu->d<<8|cpu->e,cpu->a,ram);
qprintf("ld (de),a");
break;
case 0x13://inc de
tmp=((uint16_t)cpu->d<<8|cpu->e)+1;
cpu->d=tmp>>8;
cpu->e=tmp&0x00ff;
qprintf("inc de");
break;
case 0x14://inc d
cpu->d++;
if(cpu->d==0)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
if((cpu->d&0xf)==0xf)cpu->f|=F_H;//H
else cpu->f&=~F_H;
qprintf("inc d");
break;
case 0x15://dec d
if(cpu->d&0x10&&!(cpu->d&0x08))cpu->f|=F_H;//H
else cpu->f&=~F_H;
cpu->d--;
if(cpu->d==0)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f|=F_N;//N
qprintf("dec d");
break;
case 0x16://ld d,m8
cpu_fetch8(cpu,rom,&cpu->d);
qprintf("ld d,%.2xh",cpu->d);
break;
case 0x17://rla
if(cpu->a&0x80)cpu->f|=F_C;else cpu->f&=~F_C;//C
cpu->f&=F_C;//N 0,Z 0,H 0
tmp8=cpu->a;
asm("rolb %0":"=m"(tmp8));
cpu->a=tmp8;
qprintf("rla");
break;
case 0x18://jr m8 (signed)
cpu_fetch8(cpu,rom,(uint8_t*)(uint8_t*)&tmp);
cpu->pc+=(int8_t)tmp;//cast to signed int8, C will sign extend
qprintf("jr %.2xh ;%.2xh",(uint8_t)tmp,cpu->pc);
break;
case 0x19://add hl,de
tmp=cpu->h<<8|cpu->l;
tmp+=cpu->d<<8|cpu->e;
cpu->h=tmp>>8;
cpu->l=(uint8_t)tmp;//trunc
qprintf("add hl,de");
if(tmp<(cpu->d<<8|cpu->e))cpu->f|=F_C;else cpu->f&=~F_C;//C
cpu->f&=~F_N;//N
//H
// if(cpu->f==0)cpu->f|=F_Z;else cpu->f&=~F_Z;//Z -
break;
case 0x1a: //ld a,(de)
cpu->a=ram[cpu->d<<8|cpu->e];
qprintf("ld a,(de)");
break;
case 0x1b: //dec de
tmp=((uint16_t)cpu->d<<8|cpu->e)-1;
cpu->d=tmp>>8;
cpu->e=(uint8_t)tmp;
qprintf("dec de");
break;
case 0x1c: //inc e
cpu->e++;
if(cpu->e==0)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
if((cpu->e&0xf)==0xf)cpu->f|=F_H;//H
else cpu->f&=~F_H;
qprintf("inc e");
break;
case 0x1d: //dec e
if(cpu->e&0x10&&!(cpu->e&0x08))cpu->f|=F_H;
else cpu->f&=~F_H;//borrow H
cpu->e--;
if(cpu->e==0)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f|=F_N;//N
qprintf("dec c");
break;
case 0x1e: //ld e,m8
cpu_fetch8(cpu,rom,&cpu->e);
qprintf("ld e,%.2xh",cpu->e);
break;
case 0x1f: //rra //TODO: fix behavior of rotate
{
//create new call stack
uint8_t cf=cpu->f&F_C;
if(cpu->a&0x01)cpu->f|=F_C;else cpu->f&=~F_C;//C
cpu->f&=F_C;//Z 0,H 0,N 0
tmp=cpu->a;
tmp8=cpu->f&F_C;
if(cf)asm(" stc ");
else asm(" clc");
asm("rcrb %0":"=m"(tmp));
cpu->a=(uint8_t)tmp;
qprintf("rra ; %.2xh",(uint8_t)tmp);
break;
}
case 0x20://jr nz m8 (signed)
cpu_fetch8(cpu,rom,(uint8_t*)(uint8_t*)&tmp);
if(!(cpu->f&F_Z))
cpu->pc+=(int8_t)tmp;//m8 is signed!
qprintf("jr nz %.2xh%s",(uint8_t)tmp,(!(cpu->f&F_Z))?(""):(" ;skipped"));
break;
case 0x21://ld hl,m16
cpu_fetch16(cpu,rom,(uint16_t*)&tmp);
cpu->h=tmp>>8;
cpu->l=tmp&0x00ff;
qprintf("ld hl,%.4xh",tmp);
break;
case 0x22://ld (hli),a
tmp=(uint16_t)cpu->h<<8|cpu->l;
// ram[tmp]=cpu->a;
cpu_write_ram(ppu,tmp,cpu->a,ram);
tmp++;
cpu->h=tmp>>8;
cpu->l=tmp&0x00ff;
qprintf("ld (hli),a ;%.4x",tmp);
break;
case 0x23://inc hl
tmp=((uint16_t)cpu->h<<8|cpu->l)+1;
cpu->h=tmp>>8;
cpu->l=(uint8_t)tmp;//trunc
qprintf("inc hl");
break;
case 0x24: //inc h
cpu->h++;
qprintf("inc h");
if(cpu->h==0)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
if((cpu->h&0xf)==0xf)cpu->f|=F_H;//H
else cpu->f&=~F_H;
break;
case 0x25: //dec h
if(cpu->h&0x10&&!(cpu->h&0x08))cpu->f|=F_H;
else cpu->f&=~F_H;//borrow H
cpu->h--;
if(cpu->h==0)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f|=F_N;//N
qprintf("dec h");
break;
case 0x26://ld h,m8
cpu_fetch8(cpu,rom,&cpu->h);
qprintf("ld h,%.2xh",cpu->h);
break;
case 0x27://daa ;decimal adjust a (BCD)
qprintf("daa");
if(cpu->a==0)cpu->f|=F_Z;//Z
cpu->f&=~F_H;//H
//N -
//C
break;
case 0x28://jr z m8
cpu_fetch8(cpu,rom,(uint8_t*)(uint8_t*)&tmp);
if(cpu->f&F_Z)cpu->pc+=(int8_t)tmp;
qprintf("jr z %.2xh ;%.2xh%s",(uint8_t)tmp,cpu->pc,(cpu->f&F_Z)?(""):(" ;skipped"));
break;
case 0x29://add hl,hl
tmp=cpu->h<<8|cpu->l;
tmp+=tmp;
cpu->h=tmp>>8;
cpu->l=(uint8_t)tmp;
qprintf("add hl,hl ;%.4xh",tmp);
cpu->f&=~F_N;//N
//C
//H
break;
case 0x2a: //ld a,(hli) ld a,(hl) ; inc hl
tmp=(uint16_t)cpu->h<<8|cpu->l;
cpu->a=ram[tmp];
tmp++;
cpu->h=tmp>>8;
cpu->l=tmp&0x00ff;
qprintf("ld a,(hli) ;(%.4xh)",tmp);
break;
case 0x2b: //dec hl
tmp=((uint16_t)cpu->h<<8|cpu->l)-1;
cpu->h=tmp>>8;
cpu->l=(uint8_t)tmp;
qprintf("dec hl");
break;
case 0x2c: //inc l
cpu->l++;
if(cpu->l==0)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
qprintf("inc l");
break;
case 0x2d: //dec l
if(cpu->l&0x10&&!(cpu->l&0x08))cpu->f|=F_H;
else cpu->f&=~F_H;//H
cpu->l--;
if(cpu->l==0)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f|=F_N;//N
qprintf("dec l");
break;
case 0x2e: //ld l,m8
cpu_fetch8(cpu,rom,&cpu->l);
qprintf("ld l,%.2xh",cpu->l);
break;
case 0x2f: //cpl ;cpl a
cpu->a=~cpu->a;
cpu->f|=F_H;
cpu->f|=F_N;
qprintf("cpl ;cpl a");
break;
case 0x30://jr nc m8 (signed)
cpu_fetch8(cpu,rom,(uint8_t*)&tmp);
if(!(cpu->f&F_C))
cpu->pc+=(int8_t)tmp;//m8 is signed!
qprintf("jr nc %.2xh%s",(uint8_t)tmp,(!(cpu->f&F_C))?(""):(" ;skipped"));
break;
case 0x31://ld sp,m16
cpu_fetch16(cpu,rom,&cpu->sp);
qprintf("ld sp,%.4xh",cpu->sp);
break;
case 0x32://ld (hld),a ld (hl),a ; dec hl
tmp=(uint16_t)cpu->h<<8|cpu->l;
// ram[tmp]=cpu->a;
cpu_write_ram(ppu,tmp,cpu->a,ram);
tmp--;
cpu->h=tmp>>8;
cpu->l=tmp&0x00ff;
qprintf("ld (hld),a ;(%.4xh)",tmp);
break;
case 0x33://inc sp
cpu->sp++;
qprintf("inc sp");
break;
case 0x34://inc (hl)
tmp=cpu->h|cpu->l<<8;
// ram[tmp]++;
cpu_write_ram(ppu,tmp,ram[tmp]+1,ram);
qprintf("inc (hl) ;%.4xh",ram[tmp]);
break;
case 0x35://dec (hl)
tmp=cpu->h|cpu->l<<8;
// ram[tmp]--;
cpu_write_ram(ppu,tmp,ram[tmp]-1,ram);
qprintf("dec (hl) ;%.4xh",ram[tmp]);
break;
case 0x36://ld (hl),m8
cpu_fetch8(cpu,rom,(uint8_t*)&tmp);
// ram[cpu->h<<8|cpu->l]=(uint8_t)tmp;
cpu_write_ram(ppu,cpu->h<<8|cpu->l,(uint8_t)tmp,ram);
qprintf("ld (hl),%.2xh",(uint8_t)tmp);
break;
case 0x37://scf
cpu->f&=F_C|F_Z;//reset F_H,F_N
cpu->f|=F_C;//set F_C
qprintf("scf ;%.2xh",cpu->f);
break;
case 0x38://jr c,m8
cpu_fetch8(cpu,rom,(uint8_t*)&tmp);
if(cpu->f&F_C)
cpu->pc+=(int8_t)tmp;//m8 is signed!
qprintf("jr c %.2xh%s",(uint8_t)tmp,(!(cpu->f&F_C))?(""):(" ;skipped"));
break;
case 0x39://add hl,sp
tmp=cpu->h<<8|cpu->l;
tmp+=cpu->sp;
cpu->h=tmp>>8;
cpu->l=(uint8_t)tmp;//trunc
qprintf("add hl,sp");
break;
case 0x3a: //ld a,(hld) ld a,(hl) ; dec hl
tmp=(uint16_t)cpu->h<<8|cpu->l;
cpu->a=ram[tmp];
tmp--;
cpu->h=tmp>>8;
cpu->l=tmp|0x00ff;
qprintf("ld a,(hld) ;(%.4xh)",tmp);
break;
case 0x3b: //dec sp
cpu->sp--;
qprintf("dec sp");
break;
case 0x3c: //inc a
cpu->a++;
if(cpu->a==0)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
qprintf("inc a");
break;
case 0x3d: //dec a
cpu->a--;
if(!cpu->a)cpu->f|=F_Z;
else cpu->f&=~F_Z;
cpu->f|=F_N;
//F_H
qprintf("dec a");
break;
case 0x3e: //ld a,m8
cpu_fetch8(cpu,rom,&cpu->a);
qprintf("ld a,%.2xh",cpu->a);
break;
case 0x3f: //ccf ;complement F_C flag
//flags
cpu->f=(cpu->f&F_C)?cpu->f&~F_C:cpu->f|F_C;//cpl C
//Z -
cpu->f&=~(F_N|F_H);//N 0,H 0
qprintf("ccf ;%.2x",cpu->f&F_C);
break;
case 0x40://ld b,b
qprintf("ld b,b");
break;
case 0x41://ld b,c
cpu->b=cpu->c;
qprintf("ld b,c");
break;
case 0x42://ld b,d
cpu->b=cpu->d;
qprintf("ld b,d");
break;
case 0x43://ld b,e
cpu->b=cpu->e;
qprintf("ld b,e");
break;
case 0x44://ld b,h
cpu->b=cpu->h;
qprintf("ld b,h");
break;
case 0x45://ld b,l
cpu->b=cpu->l;
qprintf("ld b,l");
break;
case 0x46://ld b,(hl)
tmp=cpu->h<<8|cpu->l;
cpu->b=ram[tmp];
qprintf("ld b,(hl)");
break;
case 0x47://ld b,a
cpu->b=cpu->a;
qprintf("ld b,a");
break;
case 0x48://ld c,b
cpu->c=cpu->b;
qprintf("ld c,b");
break;
case 0x49://ld c,c
qprintf("ld c,c");
break;
case 0x4a: //ld c,d
cpu->c=cpu->d;
qprintf("ld c,d");
break;
case 0x4b: //ld c,e
cpu->c=cpu->e;
qprintf("ld c,e");
break;
case 0x4c: //ld c,h
cpu->c=cpu->h;
qprintf("ld c,h");
break;
case 0x4d: //ld c,l
cpu->c=cpu->l;
qprintf("ld c,l");
break;
case 0x4e: //ld c,(hl)
tmp=cpu->h<<8|cpu->l;
cpu->c=ram[tmp];
qprintf("ld c,(hl)");
break;
case 0x4f: //ld c,a
cpu->c=cpu->a;
qprintf("ld c,a");
break;
case 0x50: //ld d,b
cpu->d=cpu->b;
qprintf("ld d,b");
break;
case 0x51: //ld d,c
cpu->d=cpu->c;
qprintf("ld d,c");
break;
case 0x52: //ld d,d
qprintf("ld d,d");
break;
case 0x53: //ld d,e
cpu->d=cpu->e;
qprintf("ld d,e");
break;
case 0x54: //ld d,h
cpu->d=cpu->h;
qprintf("ld d,h");
break;
case 0x55: //ld d,l
cpu->d=cpu->l;
qprintf("ld d,l");
break;
case 0x56: //ld d,(hl)
tmp=cpu->h<<8|cpu->l;
cpu->d=ram[tmp];
qprintf("ld d,(hl)");
break;
case 0x57: //ld d,a
cpu->d=cpu->a;
qprintf("ld d,a");
break;
case 0x58: //ld e,b
cpu->e=cpu->b;
qprintf("ld e,b");
break;
case 0x59: //ld e,c
cpu->e=cpu->c;
qprintf("ld e,c");
break;
case 0x5a: //ld e,d
cpu->e=cpu->d;
qprintf("ld e,d");
break;
case 0x5b: //ld e,e
qprintf("ld e,e");
break;
case 0x5c: //ld e,h
cpu->e=cpu->h;
qprintf("ld e,h");
break;
case 0x5d: //ld e,l
cpu->e=cpu->l;
qprintf("ld e,l");
break;
case 0x5e: //ld e,(hl)
tmp=cpu->h<<8|cpu->l;
cpu->e=ram[tmp];
qprintf("ld e,(hl)");
break;
case 0x5f: //ld e,a
cpu->e=cpu->a;
qprintf("ld e,a");
break;
case 0x60: //ld h,b
cpu->h=cpu->b;
qprintf("ld h,b");
break;
case 0x61: //ld h,c
cpu->h=cpu->c;
qprintf("ld h,c");
break;
case 0x62: //ld h,d
cpu->h=cpu->d;
qprintf("ld h,d");
break;
case 0x63: //ld h,e
cpu->h=cpu->e;
qprintf("ld h,e");
break;
case 0x64: //ld h,h
qprintf("ld h,h");
break;
case 0x65: //ld h,l
cpu->h=cpu->l;
qprintf("ld h,l");
break;
case 0x66: //ld h,(hl)
tmp=cpu->h<<8|cpu->l;
cpu->h=ram[tmp];
qprintf("ld h,(hl)");
break;
case 0x67: //ld h,a
cpu->h=cpu->a;
qprintf("ld h,a");
break;
case 0x68: //ld l,b
cpu->l=cpu->b;
qprintf("ld l,b");
break;
case 0x69: //ld l,c
cpu->l=cpu->c;
qprintf("ld l,c");
break;
case 0x6a: //ld l,d
cpu->l=cpu->d;
qprintf("ld l,d");
break;
case 0x6b: //ld l,e
cpu->l=cpu->e;
qprintf("ld l,e");
break;
case 0x6c: //ld l,h
cpu->l=cpu->h;
qprintf("ld l,h");
break;
case 0x6d: //ld l,l
qprintf("ld l,l");
break;
case 0x6e: //ld l,(hl)
tmp=cpu->h<<8|cpu->l;
cpu->l=ram[tmp];
qprintf("ld l,(hl)");
break;
case 0x6f: //ld l,a
cpu->l=cpu->a;
qprintf("ld l,a");
break;
case 0x70: //ld (hl),b
tmp=cpu->h<<8|cpu->l;
// ram[tmp]=cpu->b;
cpu_write_ram(ppu,tmp,cpu->b,ram);
qprintf("ld (hl),b ;ld (%.4xh),%.2xh",tmp,cpu->b);
break;
case 0x71: //ld (hl),c
tmp=cpu->h<<8|cpu->l;
// ram[tmp]=cpu->c;
cpu_write_ram(ppu,tmp,cpu->c,ram);
qprintf("ld (hl),c");
break;
case 0x72: //ld (hl),d
tmp=cpu->h<<8|cpu->l;
// ram[tmp]=cpu->d;
cpu_write_ram(ppu,tmp,cpu->d,ram);
qprintf("ld (hl),d");
break;
case 0x73: //ld (hl),e
tmp=cpu->h<<8|cpu->l;
// ram[tmp]=cpu->e;
cpu_write_ram(ppu,tmp,cpu->e,ram);
qprintf("ld (hl),e");
break;
case 0x74: //ld (hl),h
tmp=cpu->h<<8|cpu->l;
// ram[tmp]=cpu->h;
cpu_write_ram(ppu,tmp,cpu->h,ram);
qprintf("ld (hl),h");
break;
case 0x75: //ld (hl),l
tmp=cpu->h<<8|cpu->l;
// ram[tmp]=cpu->l;
cpu_write_ram(ppu,tmp,cpu->l,ram);
qprintf("ld (hl),l");
break;
case 0x76: //halt
//if(cpu->ime)
cpu->pc--;//stay put
qprintf("halt%s",ram[0xffff]?"":"");
break;
case 0x77: //ld (hl),a
tmp=cpu->h<<8|cpu->l;
// ram[tmp]=cpu->a;
cpu_write_ram(ppu,tmp,cpu->a,ram);
qprintf("ld (hl),a ;ld (%.4xh),%.2xh",tmp,cpu->a);
break;
case 0x78: //ld a,b
cpu->a=cpu->b;
qprintf("ld a,b");
break;
case 0x79: //ld a,c
cpu->a=cpu->c;
qprintf("ld a,c");
break;
case 0x7a: //ld a,d
cpu->a=cpu->d;
qprintf("ld a,d");
break;
case 0x7b: //ld a,e
cpu->a=cpu->e;
qprintf("ld a,e");
break;
case 0x7c: //ld a,h
cpu->a=cpu->h;
qprintf("ld a,h");
break;
case 0x7d: //ld a,l
cpu->a=cpu->l;
qprintf("ld a,l");
break;
case 0x7e: //ld a,(hl)
tmp=cpu->h<<8|cpu->l;
cpu->a=ram[tmp];
qprintf("ld a,(hl)");
break;
case 0x7f: //ld a,a
qprintf("ld a,a");
break;
case 0x80://add b
cpu->a+=cpu->b;
cpu->f&=~F_N;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
//F_H
if(cpu->a<cpu->b)cpu->f|=F_C;//C
else cpu->f&=~F_C;
qprintf("add b");
break;
case 0x81://add c
cpu->a+=cpu->c;
cpu->f&=~F_N;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
//F_H
if(cpu->a<cpu->c)cpu->f|=F_C;//C
else cpu->f&=~F_C;
qprintf("add c");
break;
case 0x82://add d
cpu->a+=cpu->d;
cpu->f&=~F_N;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
//F_H
if(cpu->a<cpu->d)cpu->f|=F_C;//C
else cpu->f&=~F_C;
qprintf("add d");
break;
case 0x83://add e
cpu->a+=cpu->e;
cpu->f&=~F_N;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
//F_H
if(cpu->a<cpu->e)cpu->f|=F_C;//C
else cpu->f&=~F_C;
qprintf("add e");
break;
case 0x84://add h
cpu->a+=cpu->h;
cpu->f&=~F_N;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
//F_H
if(cpu->a<cpu->h)cpu->f|=F_C;//C
else cpu->f&=~F_C;
qprintf("add h");
break;
case 0x85://add l
cpu->a+=cpu->l;
cpu->f&=~F_N;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
//F_H
if(cpu->a<cpu->l)cpu->f|=F_C;//C
else cpu->f&=~F_C;
qprintf("add l ;%x",cpu->f&F_C);
break;
case 0x86://add (hl)
tmp=(uint16_t)cpu->h<<8|cpu->l;
cpu->a+=ram[tmp];
cpu->f&=~F_N;//N
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
//F_H
if(cpu->a<cpu->h)cpu->f|=F_C;//C
else cpu->f&=~F_C;
qprintf("add (hl) ;%.4xh",tmp);
break;
case 0x87://add a
tmp=cpu->a;
cpu->a+=cpu->a;
cpu->f&=~F_N;//N
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
//F_H
if(tmp<cpu->a)cpu->f|=F_C;//C
else cpu->f&=~F_C;
qprintf("add a");
break;
case 0x88://adc b
cpu->a+=cpu->b+(cpu->f&F_C)!=0;
cpu->f&=~F_N;//N
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
//F_H
if(cpu->a<cpu->b)cpu->f|=F_C;//C
else cpu->f&=~F_C;
qprintf("adc b");
break;
case 0x89://adc c
cpu->a+=cpu->c+(cpu->f&F_C)!=0;
cpu->f&=~F_N;//N
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
//F_H
if(cpu->a<cpu->c)cpu->f|=F_C;//C
else cpu->f&=~F_C;
qprintf("adc c");
break;
case 0x8a: //adc d
cpu->a+=cpu->d+(cpu->f&F_C)!=0;
cpu->f&=~F_N;//N
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
//F_H
if(cpu->a<cpu->d)cpu->f|=F_C;//C
else cpu->f&=~F_C;
qprintf("adc d");
break;
case 0x8b: //adc e
cpu->a+=cpu->e+(cpu->f&F_C)!=0;
cpu->f&=~F_N;//N
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
//F_H
if(cpu->a<cpu->e)cpu->f|=F_C;//C
else cpu->f&=~F_C;
qprintf("adc e");
break;
case 0x8c: //adc h
cpu->a+=cpu->h+(cpu->f&F_C)!=0;
cpu->f&=~F_N;//N
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
//F_H
if(cpu->a<cpu->h)cpu->f|=F_C;//C
else cpu->f&=~F_C;
qprintf("adc h ;%x",cpu->f&F_C);
break;
case 0x8d: //adc a,l
cpu->a+=cpu->l+!!(cpu->f&F_C);
cpu->f&=~F_N;
if(!cpu->a)cpu->f|=F_Z;
else cpu->f&=~F_Z;
//F_H
//F_C
qprintf("adc a,l");
break;
case 0x8e: //adc a,(hl)
tmp=cpu->h<<8|cpu->l;
cpu->a+=ram[tmp]+!!(cpu->f&F_C);
if(cpu->a==0)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
//F_H
//F_C
qprintf("adc a,(hl) ;%.4xh",tmp);
break;
case 0x8f: //adc a,a
cpu->a+=cpu->a+!!(cpu->f&F_C);
if(cpu->a==0)cpu->f|=F_Z;
cpu->f&=~F_N;
if(!cpu->a)cpu->f|=F_Z;
//F_H
//F_C
qprintf("adc a,a");
break;
case 0x90://sub b
if(cpu->a<cpu->b)cpu->f&=~F_C;//C
else cpu->f|=F_C;
cpu->a-=cpu->b;
if(!(cpu->a))cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f|=F_N;//N
qprintf("sub b");
break;
case 0x91://sub c
if(cpu->a<cpu->c)cpu->f&=~F_C;//C
else cpu->f|=F_C;
cpu->a-=cpu->c;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f|=F_N;//N
qprintf("sub c");
break;
case 0x92://sub d
if(cpu->a<cpu->d)cpu->f&=~F_C;//C //SUB CARRY IS REVERSED
else cpu->f|=F_C;
cpu->a-=cpu->d;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f|=F_N;//N
qprintf("sub d");
break;
case 0x93://sub e
if(cpu->a<cpu->e)cpu->f&=~F_C;//C //SUB CARRY IS REVERSED
else cpu->f|=F_C;
cpu->a-=cpu->e;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f|=F_N;//N
qprintf("sub e");
break;
case 0x94://sub h
if(cpu->a<cpu->h)cpu->f&=~F_C;//C
else cpu->f|=F_C;
cpu->a-=cpu->h;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f|=F_N;//N
qprintf("sub h");
break;
case 0x95://sub l
if(cpu->a<cpu->l)cpu->f&=~F_C;//C //SUB CARRY IS REVERSED
else cpu->f|=F_C;
cpu->a-=cpu->l;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f|=F_N;//N
qprintf("sub l ;CF:%x a:%.2x",(cpu->f&F_C),cpu->a);
break;
case 0x96://sub (hl)
tmp=(uint16_t)cpu->h<<8|cpu->l;
if(cpu->a<tmp)cpu->f&=~F_C;//C
else cpu->f|=F_C;
cpu->a-=ram[tmp];
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f|=F_N;//N
qprintf("sub (hl)");
break;
case 0x97://sub a
cpu->a-=cpu->a;
cpu->f&=~F_C;//C
cpu->f|=F_Z;//Z
cpu->f|=F_N;//N
qprintf("sub a");
break;
case 0x98://sbc b
tmp=cpu->a;
cpu->a-=cpu->b+!(cpu->f&F_C);
if(tmp<cpu->b)cpu->f&=~F_C;//C
else cpu->f|=F_C;
cpu->f|=F_Z;//zero flag
cpu->f|=F_N;//N
qprintf("sbc b");
break;
case 0x99://sbc c
tmp=cpu->a;
cpu->a-=cpu->c+!(cpu->f&F_C);
if(tmp<cpu->c)cpu->f&=~F_C;//C
else cpu->f|=F_C;
cpu->f|=F_Z;//zero flag
cpu->f|=F_N;
qprintf("sbc c");
break;
case 0x9a: //sbc d
tmp=cpu->a;
cpu->a-=cpu->d+!(cpu->f&F_C);
if(tmp<cpu->d)cpu->f&=~F_C;//C
else cpu->f|=F_C;
cpu->f|=F_Z;//zero flag
cpu->f|=F_N;
qprintf("sbc d");
break;
case 0x9b: //sbc e
tmp=cpu->a;
cpu->a-=cpu->e+!(cpu->f&F_C);
if(tmp<cpu->e)cpu->f&=~F_C;//C
else cpu->f|=F_C;
cpu->f|=F_Z;//zero flag
cpu->f|=F_N;
qprintf("sbc e");
break;
case 0x9c: //sbc h
tmp=cpu->a;
cpu->a-=cpu->h+!(cpu->f&F_C);
if(tmp<cpu->h)cpu->f&=~F_C;//C
else cpu->f|=F_C;
cpu->f|=F_Z;//zero flag
cpu->f|=F_N;
qprintf("sbc h ;C:%x",(cpu->f&F_C));
break;
case 0x9d: //sbc l
tmp=cpu->a;
cpu->a-=cpu->l+!(cpu->f&F_C);
if(tmp<cpu->l)cpu->f&=~F_C;//C
else cpu->f|=F_C;
cpu->f|=F_Z;//zero flag
cpu->f|=F_N;
qprintf("sbc l ;C:%u",(!!cpu->f)&F_C);
break;
case 0x9e: //sbc (hl)
tmp=(uint16_t)cpu->h<<8|cpu->l;
tmp8=cpu->a;
cpu->a-=ram[tmp]+!(cpu->f&F_C);
if(tmp8<ram[tmp])cpu->f&=~F_C;//C
else cpu->f|=F_C;
cpu->f|=F_Z;//zero flag
cpu->f|=F_N;
qprintf("sbc (hl)");
break;
case 0x9f: //sbc a
cpu->a-=cpu->a+!(cpu->f&F_C);
cpu->f|=F_C;//C
cpu->f|=F_Z;//Z
cpu->f|=F_N;//N
qprintf("sbc (hl)");
break;
case 0xa0://and b
cpu->a&=cpu->b;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f|=F_H;//H
cpu->f&=~F_C;//C
qprintf("and b");
break;
case 0xa1://and c
cpu->a&=cpu->c;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f|=F_H;//H
cpu->f&=~F_C;//C
qprintf("and c");
break;
case 0xa2://and d
cpu->a&=cpu->d;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f|=F_H;//H
cpu->f&=~F_C;//C
qprintf("and d");
break;
case 0xa3://and e
cpu->a&=cpu->e;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f|=F_H;//H
cpu->f&=~F_C;//C
qprintf("and e");
break;
case 0xa4://and h
cpu->a&=cpu->h;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f|=F_H;//H
cpu->f&=~F_C;//C
qprintf("and h");
break;
case 0xa5://and l
cpu->a&=cpu->l;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f|=F_H;//H
cpu->f&=~F_C;//C
qprintf("and l");
break;
case 0xa6://and (hl)
tmp=cpu->h<<8|cpu->l;
cpu->a&=ram[tmp];
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f|=F_H;//H
cpu->f&=~F_C;//C
qprintf("and (hl)");
break;
case 0xa7://and a
// cpu->a&=cpu->a;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f|=F_H;//H
cpu->f&=~F_C;//C
qprintf("and a");
break;
case 0xa8://xor b
cpu->a^=cpu->b;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
cpu->f&=~F_C;//C
qprintf("xor b");
break;
case 0xa9://xor c
cpu->a^=cpu->c;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
cpu->f&=~F_C;//C
qprintf("xor c");
break;
case 0xaa: //xor d
cpu->a^=cpu->d;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
cpu->f&=~F_C;//C
qprintf("xor d");
break;
case 0xab: //xor e
cpu->a^=cpu->e;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
cpu->f&=~F_C;//C
qprintf("xor e");
break;
case 0xac: //xor h
cpu->a^=cpu->h;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
cpu->f&=~F_C;//C
qprintf("xor h");
break;
case 0xad: //xor l
cpu->a^=cpu->l;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
cpu->f&=~F_C;//C
qprintf("xor l");
break;
case 0xae: //xor (hl)
tmp=cpu->h<<8|cpu->l;
cpu->a^=ram[tmp];
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
cpu->f&=~F_C;//C
qprintf("xor (hl)");
break;
case 0xaf: //xor a
cpu->a=0;//xor X,X is always zero
cpu->f|=F_Z;//Z
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
cpu->f&=~F_C;//C
qprintf("xor a");
break;
case 0xb0://or b
cpu->a|=cpu->b;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
cpu->f&=~F_C;//C
qprintf("or b");
break;
case 0xb1://or c
cpu->a|=cpu->c;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
cpu->f&=~F_C;//C
qprintf("or c");
break;
case 0xb2://or d
cpu->a|=cpu->d;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
cpu->f&=~F_C;//C
qprintf("or d");
break;
case 0xb3://or e
cpu->a|=cpu->e;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
cpu->f&=~F_C;//C
qprintf("or e");
break;
case 0xb4://or h
cpu->a|=cpu->h;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
cpu->f&=~F_C;//C
qprintf("or h");
break;
case 0xb5://or l
cpu->a|=cpu->l;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
cpu->f&=~F_C;//C
qprintf("or l");
break;
case 0xb6://or (hl)
tmp=cpu->h<<8|cpu->l;
cpu->a|=ram[tmp];
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
cpu->f&=~F_C;//C
qprintf("or (hl)");
break;
case 0xb7://or a
// cpu->a|=cpu->a;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
cpu->f&=~F_C;//C
qprintf("or a");
break;
case 0xb8://cp b
tmp=cpu->a-cpu->b;
if(!tmp)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f|=F_N;//N
//H
if(cpu->a<cpu->b)cpu->f|=F_C;//C
else cpu->f&=~F_C;//C
qprintf("cp b");
break;
case 0xb9://cp c
tmp=cpu->a-cpu->c;
if(!tmp)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f|=F_N;//N
//H
if(cpu->a<cpu->c)cpu->f|=F_C;//C
else cpu->f&=~F_C;//C
qprintf("cp c");
break;
case 0xba: //cp d
tmp=cpu->a-cpu->d;
if(!tmp)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f|=F_N;//N
//H
if(cpu->a<cpu->d)cpu->f|=F_C;//C
else cpu->f&=~F_C;//C
qprintf("cp d");
break;
case 0xbb: //cp e
tmp=cpu->a-cpu->e;
if(!tmp)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f|=F_N;//N
//H
if(cpu->a<cpu->e)cpu->f|=F_C;//C
else cpu->f&=~F_C;//C
qprintf("cp e");
break;
case 0xbc: //cp h
tmp=cpu->a-cpu->h;
if(!tmp)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f|=F_N;//N
//H
if(cpu->a<cpu->h)cpu->f|=F_C;//C
else cpu->f&=~F_C;//C
qprintf("cp h");
break;
case 0xbd: //cp l
tmp=cpu->a-cpu->l;
if(!tmp)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f|=F_N;//N
//H
if(cpu->a<cpu->l)cpu->f|=F_C;//C
else cpu->f&=~F_C;//C
qprintf("cp l");
break;
case 0xbe: //cp (hl)
tmp=ram[cpu->h<<8|cpu->l];
tmp8=cpu->a-tmp;
if(!tmp)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f|=F_N;//N
//H
if(cpu->a<tmp)cpu->f|=F_C;//C
else cpu->f&=~F_C;//C
qprintf("cp (hl)");
break;
case 0xbf: //cp a
cpu->f|=F_Z;//Z
cpu->f|=F_N;//N
//H
cpu->f&=~F_C;//C
qprintf("cp a");
break;
case 0xc0://ret nz
//pop ret val from stack!
if(!(cpu->f&F_Z))
{
cpu->pc=ram[cpu->sp]|ram[cpu->sp+1]<<8;
cpu->sp+=2;
}
qprintf("ret nz%s",cpu->f&F_Z?" ;skipped":"");
break;
case 0xc1://pop bc
cpu->c=ram[cpu->sp];//little-endian
cpu->b=ram[cpu->sp+1];
cpu->sp+=2;
qprintf("pop bc ;%.4xh",cpu->b<<8|cpu->c);
break;
case 0xc2://jp nz,m16
cpu_fetch16(cpu,rom,(uint16_t*)&tmp);
if(!(cpu->f&F_Z))cpu->pc=tmp;
qprintf("jp nz,%.4xh%s",tmp,!cpu->a?" ;skipped":"");
break;
case 0xc3://jp m16
cpu_fetch16(cpu,rom,&cpu->pc);
cpu->pc-=2;//fetch incr's pc
qprintf("jp %.4xh",cpu->pc);
break;
case 0xc4://call nz,m16
cpu_fetch16(cpu,rom,(uint16_t*)&tmp);
if(!(cpu->f&F_Z))
{
cpu->sp-=2;
// ram[cpu->sp] =(uint8_t)cpu->pc;//push pc
// ram[cpu->sp+1]=cpu->pc>>8;
cpu_write_ram(ppu,cpu->sp,(uint8_t)cpu->pc,ram);
cpu_write_ram(ppu,cpu->sp+1,cpu->pc>>8,ram);
cpu->pc=tmp;
}
qprintf("call nz,%.4xh%s",tmp,!cpu->a?" ;skipped":"");
break;
case 0xc5://push bc
cpu->sp-=2;
// ram[cpu->sp]=cpu->c;//little-endian
// ram[cpu->sp+1]=cpu->b;
cpu_write_ram(ppu,cpu->sp,cpu->c,ram);
cpu_write_ram(ppu,cpu->sp+1,cpu->b,ram);
qprintf("push bc ;%.4xh",cpu->b<<8|cpu->c);
break;
case 0xc6://add a,m8
cpu_fetch8(cpu,rom,(uint8_t*)&tmp);
if((cpu->a&0x0f)+((tmp&0x0f)&0x10))cpu->f|=F_H;//F_H
else cpu->f&=~F_H;
cpu->a+=tmp;
if(cpu->a==0)cpu->f|=F_Z;//Z
cpu->f&=~F_N;//N
if(cpu->a<tmp)cpu->f|=F_C;//C
else cpu->f&=~F_C;
qprintf("add a,%.2xh",tmp);
break;
case 0xc7: //rst 00h (call 0000h + 00h)
// cpu_fetch16(cpu,rom,(uint16_t*)&tmp);
cpu->sp-=2;//alloc
// ram[cpu->sp]=cpu->pc&0x00ff;
// ram[cpu->sp+1]=cpu->pc>>8;
cpu_write_ram(ppu,cpu->sp,cpu->pc&0x00ff,ram);
cpu_write_ram(ppu,cpu->sp+1,cpu->pc>>8,ram);
cpu->pc=0x0000;
qprintf("rst 00h ;ret to %.4xh",ram[cpu->sp]|ram[cpu->sp+1]<<8);
break;
case 0xc8: //ret z //ret addr stays on stack if skipped!
if(cpu->f&F_Z)
{
cpu->pc=ram[cpu->sp]|ram[cpu->sp+1]<<8;
cpu->sp+=2;
}
qprintf("ret z%s",cpu->f&F_Z?"":" ;skipped");
break;
case 0xc9://ret
//pop ret val from stack!
cpu->pc=ram[cpu->sp]|ram[cpu->sp+1]<<8;
cpu->sp+=2;
qprintf("ret");
break;
case 0xca: //jp z,m16
cpu_fetch16(cpu,rom,(uint16_t*)&tmp);
if(cpu->f&F_Z)cpu->pc=tmp;
qprintf("jp z%s",cpu->f&F_Z?"":" ;skipped");
break;
case 0xcb: //PREFIX CB
//IX CBPREF IX CBPREF IX CBPR EF IXCBPR EFIX CBPR
cpu_fetch8(cpu,rom,(uint8_t*)&tmp8);
qprintf("0x%.2x: ",tmp8);
cpu_decexecCB((uint8_t*)cpu,(uint8_t*)&tmp8,ram,quiet);
break;
case 0xcc: //call z,m16
cpu_fetch16(cpu,rom,(uint16_t*)&tmp);
if(cpu->f&F_Z)
{
cpu->sp-=2;
// ram[cpu->sp] =(uint8_t)cpu->pc;//push pc
// ram[cpu->sp+1]=cpu->pc>>8;
cpu_write_ram(ppu,cpu->sp,(uint8_t)cpu->pc,ram);
cpu_write_ram(ppu,cpu->sp+1,cpu->pc>>8,ram);
cpu->pc=tmp;
}
qprintf("call z,%.4xh%s",tmp,!cpu->a?"":" ;skipped");
break;
case 0xcd: //call m16
//push ret addr to stack!
cpu_fetch16(cpu,rom,(uint16_t*)&tmp);
cpu->sp-=2;//alloc
// ram[cpu->sp]=(uint16_t)cpu->pc&0x00ff;
// ram[cpu->sp+1]=(uint16_t)cpu->pc>>8;
cpu_write_ram(ppu,cpu->sp,(uint16_t)cpu->pc&0x00ff,ram);
cpu_write_ram(ppu,cpu->sp+1,(uint16_t)cpu->pc>>8,ram);
cpu->pc=tmp;
qprintf("call %.4xh ;ret to %.4xh",cpu->pc,ram[cpu->sp]|ram[cpu->sp+1]<<8);
break;
case 0xce: //adc a,m8
cpu_fetch8(cpu,rom,(uint8_t*)&tmp8);
cpu->a+=tmp8+!!(cpu->f&F_C);
cpu->f&=~F_N;//N
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
//F_H
if(cpu->a<tmp8)cpu->f|=F_C;//F_C
else cpu->f&=~F_C;
qprintf("adc a,%.2x",tmp8);
break;
case 0xcf: //rst 08h (call 0000h + 00h)
//MessageBoxA(NULL,"RST08","-",MB_OK);
// cpu_fetch16(cpu,rom,(uint16_t*)&tmp);
cpu->sp-=2;//alloc
// ram[cpu->sp]=cpu->pc&0x00ff;
// ram[cpu->sp+1]=cpu->pc>>8;
cpu_write_ram(ppu,cpu->sp,cpu->pc&0x00ff,ram);
cpu_write_ram(ppu,cpu->sp+1,cpu->pc>>8,ram);
cpu->pc=0x0008;
qprintf("rst 08h ;ret to %.4xh",ram[cpu->sp]|ram[cpu->sp+1]<<8);
break;
case 0xd0: //ret nc
if(!(cpu->f&F_C))
{
cpu->pc=ram[cpu->sp]|ram[cpu->sp+1]<<8;
cpu->sp+=2;
}
qprintf("ret nc%s",cpu->f&F_C?" ;skipped":"");
break;
case 0xd1: //pop de
cpu->e=ram[cpu->sp];//little-endian
cpu->d=ram[cpu->sp+1];
cpu->sp+=2;
qprintf("pop de ;%.4xh",cpu->d<<8|cpu->e);
break;
case 0xd2: //jp nc,m16
cpu_fetch16(cpu,rom,(uint16_t*)&tmp);
if(!(cpu->f&F_C))cpu->pc=tmp;
qprintf("jp nc,%.4xh%s",tmp,!cpu->a?" ;skipped":"");
break;
case 0xd4://call nc,m16
cpu_fetch16(cpu,rom,(uint16_t*)&tmp);
if(!(cpu->f&F_C))
{
cpu->sp-=2;
// ram[cpu->sp] =(uint8_t)cpu->pc;//push pc
// ram[cpu->sp+1]=cpu->pc>>8;
cpu_write_ram(ppu,cpu->sp,(uint8_t)cpu->pc,ram);
cpu_write_ram(ppu,cpu->sp+1,cpu->pc>>8,ram);
cpu->pc=tmp;
}
qprintf("call nc,%.4xh%s",tmp,cpu->f&F_C?" ;skipped":"");
break;
case 0xd5://push de
cpu->sp-=2;
// ram[cpu->sp]=cpu->e;//little-endian
// ram[cpu->sp+1]=cpu->d;
cpu_write_ram(ppu,cpu->sp,cpu->e,ram);
cpu_write_ram(ppu,cpu->sp+1,cpu->d,ram);
qprintf("push de ;%.4xh",cpu->d<<8|cpu->e);
break;
case 0xd6://sub m8
cpu_fetch8(cpu,rom,(uint8_t*)&tmp);
if(((cpu->a&0x0f)+(uint8_t)(tmp&0x0f))&0x10)cpu->f|=F_H;//H
else cpu->f&=~F_H;
cpu->a-=(uint8_t)tmp;//2's complement add/sub aren't signed
if(!(cpu->a))cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
if(cpu->a<(uint8_t)tmp)cpu->f|=F_C;//C
else cpu->f&=~F_C;
qprintf("sub %.2xh",(uint8_t)tmp);
break;
case 0xd7://rst 10h (call 0000h + 10h)
// cpu_fetch16(cpu,rom,(uint16_t*)&tmp);
cpu->sp-=2;//alloc
// ram[cpu->sp]=cpu->pc&0x00ff;
// ram[cpu->sp+1]=cpu->pc>>8;
cpu_write_ram(ppu,cpu->sp,cpu->pc&0x00ff,ram);
cpu_write_ram(ppu,cpu->sp+1,cpu->pc>>8,ram);
cpu->pc=0x0010;
qprintf("rst 10h ;ret to %.4xh",ram[cpu->sp]|ram[cpu->sp+1]<<8);
break;
case 0xd8: //ret c
if(cpu->f&F_C)
{
cpu->pc=ram[cpu->sp]|ram[cpu->sp+1]<<8;
cpu->sp+=2;
}
qprintf("ret c%s",cpu->f&F_C?"":" ;skipped");
break;
case 0xd9: //reti
//pop ret val from stack!
cpu->pc=ram[cpu->sp]|ram[cpu->sp+1]<<8;
cpu->sp+=2;
// ram[0xffff]=0x1f;//enable all interrupts
cpu_write_ram(ppu,0xffff,0x1f,ram);
qprintf("reti");
break;
case 0xda: //jp c,m16
cpu_fetch16(cpu,rom,(uint16_t*)&tmp);
if(cpu->f&F_C)cpu->pc=tmp;
qprintf("jp c%s",cpu->f&F_C?"":" ;skipped");
break;
case 0xdc: //call c,m16
cpu_fetch16(cpu,rom,(uint16_t*)&tmp);
if(cpu->f&F_C)
{
cpu->sp-=2;
// ram[cpu->sp] =(uint8_t)cpu->pc;//push pc
// ram[cpu->sp+1]=cpu->pc>>8;
cpu_write_ram(ppu,cpu->sp,(uint8_t)cpu->pc,ram);
cpu_write_ram(ppu,cpu->sp+1,cpu->pc>>8,ram);
cpu->pc=tmp;
}
qprintf("call c,%.4xh%s",tmp,!cpu->a?"":" ;skipped");
break;
case 0xde: //sbc a,m8
cpu_fetch8(cpu,rom,(uint8_t*)&tmp8);
tmp=cpu->a;
cpu->a-=tmp8+!(cpu->f&F_C);
if(tmp<tmp8)cpu->f&=~F_C;//C
else cpu->f|=F_C;
cpu->f|=F_Z;//Z
cpu->f|=F_N;//N
qprintf("sbc %.2x ;C:%x",tmp8,(cpu->f&F_C));
break;
case 0xdf: //rst 18h (call 0000h + 00h)
// cpu_fetch16(cpu,rom,(uint16_t*)&tmp);
cpu->sp-=2;//alloc
// ram[cpu->sp]=cpu->pc&0x00ff;
// ram[cpu->sp+1]=cpu->pc>>8;
cpu_write_ram(ppu,cpu->sp,cpu->pc&0x00ff,ram);
cpu_write_ram(ppu,cpu->sp+1,cpu->pc>>8,ram);
cpu->pc=0x0018;
qprintf("rst 18h ;ret to %.4xh",ram[cpu->sp]|ram[cpu->sp+1]<<8);
break;
case 0xe0://ldh (m8),a ---> ld (ff00 + m8),a
cpu_fetch8(cpu,rom,(uint8_t*)&tmp);
// ram[0xff00|tmp]=cpu->a;
cpu_write_ram(ppu,0xff00|tmp,cpu->a,ram);
qprintf("ldh (%.2xh),a ;ld (ff00h+%.2xh),a",tmp,tmp);
break;
case 0xe1://pop hl
cpu->l=ram[cpu->sp];
cpu->h=ram[cpu->sp+1];
cpu->sp+=2;
qprintf("pop hl ;%.4xh",cpu->h|cpu->l<<8);
break;
case 0xe2://ld (c),a
// cpu_fetch8(cpu,rom,(uint8_t*)&tmp8);
// ram[0xff00|(uint16_t)cpu->c]=cpu->a;
cpu_write_ram(ppu,0xff00|(uint16_t)cpu->c,cpu->a,ram);
qprintf("ld (c),a");
break;
case 0xe5://push hl
cpu->sp-=2;
// ram[cpu->sp]=cpu->h;
// ram[cpu->sp+1]=cpu->l;
cpu_write_ram(ppu,cpu->sp,cpu->h,ram);
cpu_write_ram(ppu,cpu->sp+1,cpu->l,ram);
qprintf("push hl ;%.4xh",cpu->h|cpu->l<<8);
break;
case 0xe6://and c ;and a,c
cpu->a&=cpu->c;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f|=F_H;//H
cpu->f&=~F_C;//C
cpu->f&=~F_N;//N
qprintf("and c");
break;
case 0xe7://rst 20h (call 0000h + 20h)
cpu->sp-=2;//alloc
// ram[cpu->sp]=cpu->pc&0x00ff;
// ram[cpu->sp+1]=cpu->pc>>8;
cpu_write_ram(ppu,cpu->sp,cpu->pc&0x00ff,ram);
cpu_write_ram(ppu,cpu->sp+1,cpu->pc>>8,ram);
cpu->pc=0x0020;
qprintf("rst 20h ;ret to %.4xh",ram[cpu->sp]|ram[cpu->sp+1]<<8);
break;
case 0xe8: //add sp,m8
cpu_fetch8(cpu,rom,(uint8_t*)&tmp8);
// tmp=cpu->sp;
cpu->sp+=tmp8;
cpu->f&=~F_Z;//Z
cpu->f&=~F_N;//N
if(cpu->sp<tmp8)cpu->f|=F_C;//C
else cpu->f&=~F_C;
if( ((cpu->sp&0x0f00)>>8) + ((tmp8&0x0f) & 0x10) )cpu->f|=F_H;
else cpu->f&=~F_H;
qprintf("add sp,%.2xh",tmp8);
break;
case 0xe9: //jp (hl)
cpu->pc=cpu->h<<8|cpu->l;
qprintf("jp (hl) ;%.4x",cpu->h<<8|cpu->l);
break;
case 0xea: //ld (m16),a
cpu_fetch16(cpu,rom,(uint16_t*)&tmp);
// ram[tmp]=cpu->a;
cpu_write_ram(ppu,tmp,cpu->a,ram);
qprintf("ld (%.4xh),a",tmp);
break;
case 0xee: //xor m8
cpu_fetch8(cpu,rom,(uint8_t*)&tmp8);
cpu->a^=tmp8;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
cpu->f&=~F_C;//C
qprintf("xor %.2xh",tmp8);
break;
case 0xef: //rst 28h (call 0000h + 00h)
cpu->sp-=2;//alloc
// ram[cpu->sp]=cpu->pc&0x00ff;
// ram[cpu->sp+1]=cpu->pc>>8;
cpu_write_ram(ppu,cpu->sp,cpu->pc&0x00ff,ram);
cpu_write_ram(ppu,cpu->sp+1,cpu->pc>>8,ram);
cpu->pc=0x0028;
qprintf("rst 28h ;ret to %.4xh",ram[cpu->sp]|ram[cpu->sp+1]<<8);
break;
case 0xf0://ldh a,(m8) ---> ld a,(ff00 + m8)
cpu_fetch8(cpu,rom,(uint8_t*)&tmp);
cpu->a=ram[0xff00|tmp];
qprintf("ldh a,(%.2xh) ;ld a,(ff00h+%.2xh)",tmp,tmp);
break;
case 0xf1://pop af
cpu->f=ram[cpu->sp];//little-endian
cpu->a=ram[cpu->sp+1];
cpu->sp+=2;
qprintf("pop bc ;%.4xh",cpu->a<<8|cpu->f);
break;
case 0xf2://ld a,(c)
cpu->a=ram[0xff00|(uint16_t)cpu->c];
qprintf("ld a,(c)");
break;
case 0xf3://di
//cpu_write_ram(ppu,0xffff,0x00,ram);
cpu->ime=0;
qprintf("di");
break;
case 0xf5://push af
cpu->sp-=2;
// ram[cpu->sp]=cpu->a;
// ram[cpu->sp+1]=cpu->f;
cpu_write_ram(ppu,cpu->sp,cpu->a,ram);
cpu_write_ram(ppu,cpu->sp+1,cpu->f,ram);
qprintf("push af ;%.4xh",cpu->a|cpu->f<<8);
break;
case 0xf6://or m8
cpu_fetch8(cpu,rom,(uint8_t*)&tmp8);
cpu->a|=tmp8;
if(!cpu->a)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
cpu->f&=~F_C;//C
qprintf("or %.2xh",tmp8);
break;
case 0xf7://rst 30h (call 0000h + 30h)
cpu->sp-=2;//alloc
// ram[cpu->sp]=cpu->pc&0x00ff;
// ram[cpu->sp+1]=cpu->pc>>8;
cpu_write_ram(ppu,cpu->sp,cpu->pc&0x00ff,ram);
cpu_write_ram(ppu,cpu->sp+1,cpu->pc>>8,ram);
cpu->pc=0x0030;
qprintf("rst 30h ;ret to %.4xh",ram[cpu->sp]|ram[cpu->sp+1]<<8);
break;
case 0xf8://ld hl,sp+m8
cpu_fetch8(cpu,rom,(uint8_t*)&tmp8);
tmp=cpu->sp+(int8_t)tmp8;//tmp8 needs to be sign-extended
cpu->h=tmp>>8;
cpu->l=(uint8_t)tmp;//trunc
cpu->f&=~F_Z;//Z
cpu->f&=~F_N;//N
if(tmp<tmp8)cpu->f|=F_C;//C
else cpu->f&=~F_C;
if((cpu->sp&0xff)+(tmp8&0xff))cpu->f|=F_H;//H
else cpu->f&=~F_H;
qprintf("ld hl,sp%+ih",(int8_t)tmp8);
break;
case 0xf9: //ld sp,hl
tmp=cpu->h<<8|cpu->l;
cpu->sp=tmp;
qprintf("ld sp,hl ;%.4xh",tmp);
break;
case 0xfa: //ld a,(m16)
cpu_fetch16(cpu,rom,(uint16_t*)&tmp);
cpu->a=ram[tmp];
qprintf("ld a,(%.2xh)",tmp);
break;
case 0xfb: //ei
//cpu_write_ram(ppu,0xffff,0x1f,ram);
cpu->ime=1;
qprintf("ei");
break;
case 0xfe: //cp m8
cpu_fetch8(cpu,rom,(uint8_t*)&tmp);
//flags:
if(cpu->a-tmp==0)cpu->f|=F_Z;else cpu->f&=~F_Z;//Z
cpu->f|=F_N;//N
if((cpu->a&0x0f)-(tmp&0xf))cpu->f|=F_H;//H
else cpu->f&=~F_H;
if(cpu->a<tmp)cpu->f|=F_C;//C
else cpu->f&=~F_C;
qprintf("cp %.2xh",tmp);
break;
case 0xff: //rst 38h (call 0000h + 38h)
//MessageBoxA(NULL,"RST38","-",MB_OK);
cpu->sp-=2;//alloc
cpu_write_ram(ppu,cpu->sp,cpu->pc&0x00ff,ram);
cpu_write_ram(ppu,cpu->sp+1,cpu->pc>>8,ram);
cpu->pc=0x0038;
qprintf("rst 38h ;ret to %.4xh",ram[cpu->sp]|ram[cpu->sp+1]<<8);
break;
case 0x00: //nop
case 0xd3: //nop
case 0xdb: //nop
case 0xdd: //nop
case 0xe3: //nop
case 0xe4: //nop
case 0xeb: //nop
case 0xec: //nop
case 0xed: //nop
case 0xf4: //nop
case 0xfc: //nop
case 0xfd: //nop
default:
qprintf("nop");
break;
}
}
// CB Prefix instructions
void cpu_decexecCB(uint8_t*cpua,uint8_t*op,uint8_t*ram,bool quiet)
{
static const uint8_t cbreg[]={2,3,4,5,6,7,0xff,0}; //(op&0xf)%8
static const char*cbrnm[]={"b","c","d","e","h","l","(hl)","a"};
uint16_t tmp;
uint8_t tmp8;
Cpu*cpu=(Cpu*)cpua;
//08h - 0fh RRC
if(*op>=0x08 && *op<=0x0f)
{
tmp8=(*op&0xf)%8;
if(tmp8==6)
{
if(ram[cpu->h<<8|cpu->l]&0x1)cpu->f|=F_C;//C
else cpu->f&=~F_C;
tmp=ram[cpu->h<<8|cpu->l];
if(cpu->f&F_C)asm(" stc");
else asm(" clc");
asm("mov %0,%%ax":"=m"(tmp));
asm("rcr %al");
asm("mov %%ax,%0":"=m"(tmp));
ram[cpu->h<<8|cpu->l]=(uint8_t)tmp;
}
else
{
if(cpua[cbreg[tmp8]]&0x1)cpu->f|=F_C;//C
else cpu->f&=~F_C;
tmp=cpua[cbreg[tmp8]];
if(cpu->f&F_C)asm(" stc");
else asm(" clc");
asm("mov %0,%%ax":"=m"(tmp));
asm("rcr %al");
asm("mov %%ax,%0":"=m"(tmp));
cpua[cbreg[tmp8]]=(uint8_t)tmp;
}
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
if(!(uint8_t)tmp)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
qprintf("rrc %s",cbrnm[(*op&0xf)%8]);
}
/*NOTE: For some reason, RRC/RLC doesn't use CF, but RR/RL does*/
//00h - 07h RLC
//if((*op>=0x00) && (*op<=0x07))
if(*op<=0x07)
{
tmp8=(*op&0xf)%8;
if(tmp8==6)
{
if(ram[cpu->h<<8|cpu->l]&0x80)cpu->f|=F_C;//C
else cpu->f&=~F_C;
tmp=ram[cpu->h<<8|cpu->l];
if(cpu->f&F_C)asm(" stc");
else asm("clc");
asm("mov %0,%%ax":"=m"(tmp));
asm("rcl %al");
asm("mov %%ax,%0":"=m"(tmp));
ram[cpu->h<<8|cpu->l]=(uint8_t)tmp;
}
else
{
if(cpua[cbreg[tmp8]]&0x80)cpu->f|=F_C;//C
else cpu->f&=~F_C;
tmp=cpua[cbreg[tmp8]];
if(cpu->f&F_C)asm(" stc");
else asm(" clc");
asm("mov %0,%%ax":"=m"(tmp));
asm("rcl %al");
asm("mov %%ax,%0":"=m"(tmp));
cpua[cbreg[tmp8]]=(uint8_t)tmp;
}
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
if(!(uint8_t)tmp)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
qprintf("rlc %s",cbrnm[(*op&0xf)%8]);
}
//18h - 1fh RR
if(*op>=0x18 && *op<=0x1f)
{
tmp8=(*op&0xf)%8;
if(tmp8==6)
{
uint8_t cf=cpu->f&F_C;
if(ram[cpu->h<<8|cpu->l]&0x1)cpu->f|=F_C;//C
else cpu->f&=~F_C;
tmp=ram[cpu->h<<8|cpu->l];
if(cf)asm("stc");
else asm("clc");
asm("mov %0,%%ax":"=m"(tmp));
asm("rcr %al");
asm("mov %%ax,%0":"=m"(tmp));
ram[cpu->h<<8|cpu->l]=(uint8_t)tmp;
}
else
{
uint8_t cf=cpu->f&F_C;
if(cpua[cbreg[tmp8]]&0x1)cpu->f|=F_C;//C
else cpu->f&=~F_C;
tmp=cpua[cbreg[tmp8]];
if(cf)asm(" stc");
else asm(" clc");
asm("mov %0,%%al":"=m"(tmp));
asm("rcr %al");
asm("mov %%al,%0":"=m"(tmp));
cpua[cbreg[tmp8]]=(uint8_t)tmp;
}
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
if(!(uint8_t)tmp)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
qprintf("rr %s",cbrnm[(*op&0xf)%8]);
}
//10h - 17h RL
if(*op>=0x10 && *op<=0x17)
{
tmp8=(*op&0xf)%8;
if(tmp8==6)
{
uint8_t cf=cpu->f&F_C;
if(ram[cpu->h<<8|cpu->l]&0x80)cpu->f|=F_C;//C
else cpu->f&=~F_C;
tmp=ram[cpu->h<<8|cpu->l];
if(cf)asm(" stc");
else asm(" clc");
asm("mov %0,%%al":"=m"(tmp));
asm("rcl %al");
asm("mov %%al,%0":"=m"(tmp));
ram[cpu->h<<8|cpu->l]=(uint8_t)tmp;
}
else
{
uint8_t cf=cpu->f&F_C;
if(cpua[cbreg[tmp8]]&0x80)cpu->f|=F_C;//C
else cpu->f&=~F_C;
tmp=cpua[cbreg[tmp8]];
if(cf)asm("stc");
else asm("clc");
asm("mov %0,%%al":"=m"(tmp));
asm("rcl %al");
asm("mov %%al,%0":"=m"(tmp));
cpua[cbreg[tmp8]]=(uint8_t)tmp;
}
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
if(!(uint8_t)tmp)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
qprintf("rl %s",cbrnm[(*op&0xf)%8]);
}
//28h - 2fh SRA
if(*op>=0x28 && *op<=0x2f)
{
tmp8=(*op&0xf)%8;
if(tmp8==6)
{
//NOTE: We are depending on arithmetic shift here,
// sra is a 'signed' operation
tmp=ram[cpu->h<<8|cpu->l]&0x1;
tmp8=ram[cpu->h<<8|cpu->l]>>=1;
}
else
{
tmp=cpua[cbreg[tmp8]]&0x1;
tmp8=cpua[cbreg[tmp8]]>>=1;
}
if(tmp)cpu->f|=F_C;//C
else cpu->f&=~F_C;
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
if(!tmp8)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
qprintf("sra %s",cbrnm[(*op&0xf)%8]);
}
//20h - 27h SLA
if(*op>=0x20 && *op<=0x27)
{
tmp8=(*op&0xf)%8;
if(tmp8==6)
{
tmp=ram[cpu->h<<8|cpu->l]&0x80;
tmp8=ram[cpu->h<<8|cpu->l]<<=1;
}
else
{
tmp=cpua[cbreg[tmp8]]&0x80;
tmp8=cpua[cbreg[tmp8]]<<=1;
}
if(tmp)cpu->f|=F_C;//C
else cpu->f&=~F_C;
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
if(!tmp8)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
qprintf("sla %s",cbrnm[(*op&0xf)%8]);
}
//30h - 3fh SRL
if(*op>=0x38 && *op<=0x3f)
{
tmp8=(*op&0xf)%8;
if(tmp8==6)
{
//NOTE: We are depending on logical shift here,
// srl is an 'unsigned' operation
tmp=ram[cpu->h<<8|cpu->l]&0x1;
tmp8=ram[cpu->h<<8|cpu->l]>>=1;
}
else
{
tmp=cpua[cbreg[tmp8]]&0x1;
tmp8=cpua[cbreg[tmp8]]>>=1;
}
if(tmp)cpu->f|=F_C;//C
else cpu->f&=~F_C;
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
if(!tmp8)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
qprintf("srl %s",cbrnm[(*op&0xf)%8]);
}
//30h - 37h SWAP
if(*op>=0x30 && *op<=0x37)
{
tmp8=(*op&0xf)%8;
if(tmp8==6)tmp=ram[cpu->h<<8|cpu->l];
else tmp=cpua[cbreg[tmp8]];//reg
asm("mov %0,%%al":"=m"(tmp));
tmp=ror(tmp,4);
//asm("rorb %0,%%al");
asm("mov %%al,%0":"=m"(tmp));
if(tmp8==6)ram[cpu->h<<8|cpu->l]=(uint8_t)tmp;
else cpua[cbreg[tmp8]]=(uint8_t)tmp;//reg
cpu->f&=~F_C;//C
cpu->f&=~F_N;//N
cpu->f&=~F_H;//H
if(!(uint8_t)tmp)cpu->f|=F_Z;//Z
else cpu->f&=~F_Z;
qprintf("swap %s ; %.2xh",cbrnm[(*op&0xf)%8],(uint8_t)tmp);
}
//40h - 7fh BIT
if(*op>=0x40 && *op<=0x80)
{
tmp=((*op&0xf0)>>4)%4*2+((*op&0x0f)>=8);//bit
tmp8=(*op&0xf)%8;
if(tmp8==6)tmp8=ram[cpu->h<<8|cpu->l];
else tmp8=cpua[cbreg[tmp8]];//reg
if(tmp8&0x1<<tmp)cpu->f&=~F_Z;//Z
else cpu->f|=F_Z;
cpu->f|=F_H;//H
cpu->f&=~F_N;//N
qprintf("bit %u,%s ;%x (%x)",tmp,cbrnm[(*op&0xf)%8],cpu->f&F_Z,tmp8&0x1<<tmp);
return;
}
//80h - bfh RES
if(*op>=0x80 && *op<=0xbf)
{
tmp=((*op&0xf0)>>4)%4*2+((*op&0x0f)>=8);//bit
tmp8=(*op&0xf)%8;
if(tmp8==6)ram[cpu->h<<8|cpu->l]&=~(1<<tmp);
else cpua[cbreg[tmp8]]&=~(1<<tmp);//reg
qprintf("res %u,%s",tmp,cbrnm[(*op&0xf)%8]);
return;
}
//c0h - ffh SET
//if(*op>=0xc0 && *op<=0xff)
if(*op>=0xc0)
{
tmp=((*op&0xf0)>>4)%4*2+((*op&0x0f)>=8);//bit
tmp8=(*op&0xf)%8;
if(tmp8==6)ram[cpu->h<<8|cpu->l]|=(1<<tmp);
else cpua[cbreg[tmp8]]|=(1<<tmp);//reg
qprintf("set %u,%s",tmp,cbrnm[(*op&0xf)%8]);
return;
}
}
void cpu_log_clear(void)
{
log_buffer[0]='\0';
}
#undef qprintf