scemu/cpu.c

718 lines
11 KiB
C

#include <u.h>
#include <libc.h>
#include "dat.h"
#include "fns.h"
u8int rA, rS, rX, rY, rP;
u16int pc;
int irq, nmi;
void
nz(u8int v)
{
rP &= ~(Negative | Zero);
if(v & 0x80)
rP |= Negative;
if(v == 0)
rP |= Zero;
}
void
adc(u8int d)
{
int r;
r = rA + d + (rP & Carry);
rP &= ~(Negative | Zero | Overflow | Carry);
if(r > 0xFF) rP |= Carry;
if(r & 0x80) rP |= Negative;
if((~(rA ^ d) & (rA ^ r)) & 0x80) rP |= Overflow;
rA = r;
if(rA == 0) rP |= Zero;
}
void
sbc(u8int d)
{
int r;
r = rA + (u8int)~d + (rP & Carry);
rP &= ~(Negative | Zero | Overflow | Carry);
if(r > 0xFF) rP |= Carry;
if((~(rA ^ d) & (rA ^ r)) & 0x80) rP |= Overflow;
rA = r;
if(rA == 0) rP |= Zero;
if(rA & 0x80) rP |= Negative;
}
void
asl(u16int a)
{
u8int v;
v = memread(a);
rP &= ~(Negative | Zero | Carry);
if(v & 0x80)
rP |= Carry;
v <<= 1;
if(v == 0)
rP |= Zero;
if(v & 0x80)
rP |= Negative;
memwrite(a, v);
}
void
lsr(u16int a)
{
u8int v;
v = memread(a);
rP &= ~(Negative | Zero | Carry);
rP |= v & 1;
v >>= 1;
if(v == 0) rP |= Zero;
if(v & 0x80) rP |= Negative;
memwrite(a, v);
}
void
rol(u16int a)
{
u8int v, b;
v = memread(a);
b = rP & Carry;
rP &= ~(Carry | Negative | Zero);
if(v & 0x80) rP |= Carry;
v = (v << 1) | b;
if(v & 0x80) rP |= Negative;
if(v == 0) rP |= Zero;
memwrite(a, v);
}
void
ror(u16int a)
{
u8int v, b;
v = memread(a);
b = rP & Carry;
rP &= ~(Carry | Negative | Zero);
rP |= v & 1;
v = (v >> 1) | (b << 7);
if(v & 0x80) rP |= Negative;
if(v == 0) rP |= Zero;
memwrite(a, v);
}
void
cmp(u8int A, u8int B)
{
rP &= ~(Negative | Zero | Carry);
if(A == B) rP |= Zero;
if(A >= B) rP |= Carry;
if((A - B) & 0x80) rP |= Negative;
}
void
inc(u16int a)
{
u8int v;
v = memread(a);
v++;
nz(v);
memwrite(a, v);
}
void
dec(u16int a)
{
u8int v;
v = memread(a);
v--;
nz(v);
memwrite(a, v);
}
int
branch(void)
{
s8int t;
u16int npc;
t = fetch8();
npc = pc+t;
if((npc ^ pc) >> 8){
pc = npc;
return 4;
}
pc = npc;
return 3;
}
u16int
aindX(void)
{
u8int r;
u16int b;
r = fetch8() + rX;
b = memread(r++);
b |= memread(r) << 8;
return b;
}
u16int
aindY(int *p)
{
u8int r;
u16int b;
r = fetch8();
b = memread(r++) + rY;
*p = b > 0xFF;
b += memread(r) << 8;
return b;
}
void
interrupt(int nmi, int brk)
{
push16(pc);
push8(rP | 0x20 | (brk << 4));
pc = memread(0xFFFA | (!nmi << 2));
pc |= memread(0xFFFB | (!nmi << 2)) << 8;
rP |= Interrupt;
}
#define zp() mem[fetch8()]
#define zpX() mem[(u8int)(fetch8()+rX)]
#define zpY() mem[(u8int)(fetch8()+rY)]
#define abso() mem[fetch16()]
#define absX() mem[a = fetch16()+rX]
#define absY() mem[a = fetch16()+rY]
#define indX() mem[aindX()]
#define indY(c) mem[aindY(c)]
int
step(void)
{
u8int op;
u16int a, v, cpc;
int c;
if(nmi)
if(--nmi == 0){
interrupt(1, 0);
nmi = 0;
return 7;
}
if(irq && (rP & Interrupt) == 0){
interrupt(0, 0);
return 7;
}
cpc = pc;
op = fetch8();
print("%02x %08b %08b %08b %08b %04x %02x\n",
op, rA, rX, rY, rP, cpc, rS);
switch(op){
case 0x00:
pc++;
interrupt(0, 1);
return 7;
case 0x01:
nz(rA |= indX());
return 6;
case 0x05:
nz(rA |= zp());
return 3;
case 0x06:
asl(fetch8());
return 5;
case 0x08:
push8(rP | 0x30);
return 3;
case 0x09:
nz(rA |= fetch8());
return 2;
case 0x0A:
rP &= ~(Negative | Zero | Carry);
if(rA & 0x80) rP |= Carry;
rA <<= 1;
if(rA == 0) rP |= Zero;
if(rA & 0x80) rP |= Negative;
return 2;
case 0x0D:
nz(rA |= abso());
return 4;
case 0x0E:
asl(fetch16());
return 6;
case 0x10:
if((rP & Negative) == 0) return branch();
pc++;
return 2;
case 0x11:
nz(rA |= indY(&c));
return 5+c;
case 0x15:
nz(rA |= zpX());
return 4;
case 0x16:
asl((u8int)(fetch8() + rX));
return 6;
case 0x18:
rP &= ~Carry;
return 2;
case 0x19:
nz(rA |= absY());
return 4 + ((u8int)a < rY);
case 0x1D:
nz(rA |= absX());
return 4 + ((u8int)a < rX);
case 0x1E:
asl(fetch16() + rX);
return 7;
case 0x20:
push16(pc+1);
pc = fetch16();
return 6;
case 0x21:
nz(rA &= indX());
return 6;
case 0x24:
a = mem[fetch8()];
rP &= ~(Negative | Zero | Overflow);
rP |= a & 0xC0;
if((a & rA) == 0) rP |= Zero;
return 3;
case 0x25:
nz(rA &= zp());
return 3;
case 0x26:
rol(fetch8());
return 5;
case 0x28:
rP = pop8() & 0xcf;
return 4;
case 0x29:
nz(rA &= fetch8());
return 2;
case 0x2A:
a = rP & Carry;
rP &= ~(Carry | Zero | Negative);
if(rA & 0x80) rP |= Carry;
rA = (rA << 1) | a;
if(rA & 0x80) rP |= Negative;
if(rA == 0) rP |= Zero;
return 2;
case 0x2C:
a = mem[fetch16()];
rP &= ~(Negative | Zero | Overflow);
rP |= a & 0xC0;
if((a & rA) == 0) rP |= Zero;
return 4;
case 0x2D:
nz(rA &= abso());
return 4;
case 0x2E:
rol(fetch16());
return 6;
case 0x30:
if((rP & Negative) != 0) return branch();
pc++;
return 3;
case 0x31:
nz(rA &= indY(&c));
return 5+c;
case 0x35:
nz(rA &= zpX());
return 4;
case 0x36:
rol((u8int)(fetch8() + rX));
return 6;
case 0x38:
rP |= Carry;
return 2;
case 0x39:
nz(rA &= absY());
return 4 + ((u8int)a < rY);
case 0x3E:
rol(fetch16() + rX);
return 7;
case 0x3D:
nz(rA &= absX());
return 4 + ((u8int)a < rX);
case 0x40:
rP = pop8() & 0xcf;
pc = pop16();
return 6;
case 0x41:
nz(rA ^= indX());
return 6;
case 0x45:
nz(rA ^= zp());
return 3;
case 0x46:
lsr(fetch8());
return 5;
case 0x48:
push8(rA);
return 3;
case 0x49:
nz(rA ^= fetch8());
return 2;
case 0x4A:
rP &= ~(Negative | Zero | Carry);
rP |= rA & 1;
rA >>= 1;
if(rA == 0) rP |= Zero;
if(rA & 0x80) rP |= Negative;
return 2;
case 0x4C:
pc = fetch16();
return 3;
case 0x4D:
nz(rA ^= abso());
return 4;
case 0x4E:
lsr(fetch16());
return 6;
case 0x51:
nz(rA ^= indY(&c));
return 5+c;
case 0x56:
lsr((u8int)(fetch8() + rX));
return 6;
case 0x58:
rP &= ~Interrupt;
return 2;
case 0x50:
if((rP & Overflow) == 0) return branch();
pc++;
return 3;
case 0x55:
nz(rA ^= zpX());
return 4;
case 0x59:
nz(rA ^= absY());
return 4 + ((u8int)a < rX);
case 0x5D:
nz(rA ^= absX());
return 4 + ((u8int)a < rX);
case 0x5E:
lsr(fetch16() + rX);
return 7;
case 0x60:
pc = pop16() + 1;
return 6;
case 0x61:
adc(indX());
return 6;
case 0x65:
adc(zp());
return 3;
case 0x66:
ror(fetch8());
return 5;
case 0x68:
nz(rA = pop8());
return 4;
case 0x69:
adc(fetch8());
return 2;
case 0x6A:
a = rP & Carry;
rP &= ~(Carry | Negative | Zero);
rP |= rA & 1;
rA = (rA >> 1) | (a << 7);
if(rA & 0x80) rP |= Negative;
if(rA == 0) rP |= Zero;
return 2;
case 0x6C:
v = fetch16();
pc = mem[v] | (mem[(v & 0xFF00) | (u8int)(v+1)] << 8);
return 5;
case 0x6D:
adc(abso());
return 4;
case 0x6E:
ror(fetch16());
return 6;
case 0x70:
if((rP & Overflow) != 0) return branch();
pc++;
return 3;
case 0x71:
adc(indY(&c));
return 5+c;
case 0x75:
adc(zpX());
return 4;
case 0x76:
ror((u8int)(fetch8() + rX));
return 6;
case 0x78:
rP |= Interrupt;
return 2;
case 0x79:
adc(absY());
return 4 + ((u8int)a < rY);
case 0x7D:
adc(absX());
return 4 + ((u8int)a < rX);
case 0x7E:
ror(fetch16() + rX);
return 7;
case 0x81:
mem[aindX()] = rA;
return 6;
case 0x84:
mem[fetch8()] = rY;
return 3;
case 0x85:
mem[fetch8()] = rA;
return 3;
case 0x86:
mem[fetch8()] = rX;
return 3;
case 0x88:
nz(--rY);
return 2;
case 0x8A:
nz(rA = rX);
return 2;
case 0x8C:
mem[fetch16()] = rY;
return 4;
case 0x8D:
mem[fetch16()] = rA;
return 4;
case 0x8E:
mem[fetch16()] = rX;
return 4;
case 0x90:
if((rP & Carry) == 0) return branch();
pc++;
return 3;
case 0x91:
mem[aindY(&c)] = rA;
return 6;
case 0x94:
mem[(u8int)(fetch8() + rX)] = rY;
return 4;
case 0x95:
mem[(u8int)(fetch8() + rX)] = rA;
return 4;
case 0x96:
mem[(u8int)(fetch8() + rY)] = rX;
return 4;
case 0x98:
nz(rA = rY);
return 2;
case 0x99:
mem[fetch16() + rY] = rA;
return 5;
case 0x9A:
rS = rX;
return 2;
case 0x9D:
mem[fetch16() + rX] = rA;
return 5;
case 0xA0:
nz(rY = fetch8());
return 2;
case 0xA1:
nz(rA = indX());
return 6;
case 0xA2:
nz(rX = fetch8());
return 2;
case 0xA4:
nz(rY = zp());
return 3;
case 0xA5:
nz(rA = zp());
return 3;
case 0xA6:
nz(rX = zp());
return 3;
case 0xA8:
nz(rY = rA);
return 2;
case 0xA9:
nz(rA = fetch8());
return 2;
case 0xAA:
nz(rX = rA);
return 2;
case 0xAC:
nz(rY = abso());
return 4;
case 0xAE:
nz(rX = abso());
return 4;
case 0xAD:
nz(rA = abso());
return 4;
case 0xB0:
if((rP & Carry) != 0) return branch();
pc++;
return 3;
case 0xB1:
nz(rA = indY(&c));
return 5+c;
case 0xB4:
nz(rY = zpX());
return 4;
case 0xB5:
nz(rA = zpX());
return 4;
case 0xB6:
nz(rX = zpY());
return 4;
case 0xB8:
rP &= ~Overflow;
return 2;
case 0xB9:
nz(rA = absY());
return 4 + ((u8int)a < rY);
case 0xBA:
nz(rX = rS);
return 2;
case 0xBC:
nz(rY = absX());
return 4 + ((u8int)a < rX);
case 0xBD:
nz(rA = absX());
return 4 + ((u8int)a < rX);
case 0xBE:
nz(rX = absY());
return 4 + ((u8int)a < rY);
case 0xC1:
cmp(rA, indX());
return 6;
case 0xC5:
cmp(rA, zp());
return 3;
case 0xC9:
cmp(rA, fetch8());
return 2;
case 0xCD:
cmp(rA, abso());
return 4;
case 0xD0:
if((rP & Zero) == 0) return branch();
pc++;
return 3;
case 0xD1:
cmp(rA, indY(&c));
return 5 + c;
case 0xD5:
cmp(rA, zpX());
return 4;
case 0xD8:
rP &= ~Decimal;
return 2;
case 0xD9:
cmp(rA, absY());
return 4 + ((u8int)a < rY);
case 0xDD:
cmp(rA, absX());
return 4 + ((u8int)a < rX);
case 0xC0:
cmp(rY, fetch8());
return 2;
case 0xC4:
cmp(rY, zp());
return 3;
case 0xC6:
dec(fetch8());
return 5;
case 0xC8:
nz(++rY);
return 2;
case 0xCA:
nz(--rX);
return 2;
case 0xCC:
cmp(rY, abso());
return 4;
case 0xCE:
dec(fetch16());
return 6;
case 0xD6:
dec((u8int)(fetch8() + rX));
return 6;
case 0xDE:
dec(fetch16() + rX);
return 7;
case 0xE0:
cmp(rX, fetch8());
return 2;
case 0xE1:
sbc(indX());
return 6;
case 0xE4:
cmp(rX, zp());
return 3;
case 0xE5:
sbc(zp());
return 3;
case 0xE6:
inc(fetch8());
return 5;
case 0xE8:
nz(++rX);
return 2;
case 0xE9:
sbc(fetch8());
return 2;
case 0xEA:
return 2;
case 0xEC:
cmp(rX, abso());
return 4;
case 0xED:
sbc(abso());
return 4;
case 0xEE:
inc(fetch16());
return 6;
case 0xF0:
if((rP & Zero) != 0) return branch();
pc++;
return 3;
case 0xF1:
sbc(indY(&c));
return 5+c;
case 0xF5:
sbc(zpX());
return 4;
case 0xF6:
inc((u8int)(fetch8() + rX));
return 6;
case 0xF8:
rP |= Decimal;
return 2;
case 0xF9:
sbc(absY());
return 4 + ((u8int)a < rY);
case 0xFD:
sbc(absX());
return 4 + ((u8int)a < rX);
case 0xFE:
inc(fetch16() + rX);
return 7;
default:
print("unimplemented %#02x\n", op);
exits(nil);
case 0xFF:
print("%s\n", (s8int*)mem+0x500);
exits(nil);
}
}