#include "opcode.h"
int run(struct sux *cpu, uint8_t opcode, uint8_t thread) {
uint64_t address;
uint8_t tmp;
address = cpu->pc[thread];
printf("pc: 0x%08llx, a: 0x%016llx, x: 0x%016llx, y: 0x%016llx"
", sp: 0x%04lx, carry: %u, opcode: 0x%02x, inst: %s\n"
, cpu->pc[thread], cpu->a[thread], cpu->x[thread], cpu->y[thread]
, cpu->sp, cpu->c[thread], opcode, opname[opcode]);
cpu->pc[thread]++;
switch(opcode) {
case CPS:
for (uint8_t i = 0; i < 8; i++) {
cpu->c[i] = 0;
cpu->z[i] = 0;
cpu->i[i] = 0;
cpu->s[i] = 0;
cpu->v[i] = 0;
cpu->n[i] = 0;
}
cpu->ps &= 0;
break;
case ADC: adc(cpu, immaddr(cpu, thread, 8), thread); break;
case 0x03: adc(cpu, absaddr(cpu, thread), thread); break;
case 0x05: adc(cpu, zeromtx(cpu, thread), thread); break;
case PHP:
tmp = addr[cpu->pc[thread]++];
if (tmp > 7)
tmp = 7;
for (int8_t i = 8*tmp; i > 0; i-=8) {
push(cpu, cpu->ps >> i);
}
push(cpu, cpu->ps & 0xFF);
break;
case PHA:
tmp = addr[cpu->pc[thread]++];
if (tmp > 7)
tmp = 7;
for (int8_t i = 8*tmp; i > 0; i-=8) {
push(cpu, cpu->a[thread] >> i);
}
push(cpu, cpu->a[thread] & 0xFF);
break;
case PHY:
tmp = addr[cpu->pc[thread]++];
if (tmp > 7)
tmp = 7;
for (int8_t i = 8*tmp; i > 0; i-=8) {
push(cpu, cpu->y[thread] >> i);
}
push(cpu, cpu->y[thread] & 0xFF);
break;
case PHX:
tmp = addr[cpu->pc[thread]++];
if (tmp > 7)
tmp = 7;
for (int8_t i = 8*tmp; i > 0; i-=8) {
push(cpu, cpu->x[thread] >> i);
}
push(cpu, cpu->x[thread] & 0xFF);
break;
case JMP:
address = absaddr(cpu, thread);
cpu->pc[thread] = address;
break;
case SBC: sbc(cpu, immaddr(cpu, thread, 8), thread); break;
case 0x13: sbc(cpu, absaddr(cpu, thread), thread); break;
case 0x15: sbc(cpu, zeromtx(cpu, thread), thread); break;
case PLP:
tmp = addr[cpu->pc[thread]++];
if (tmp > 7)
tmp = 7;
for (uint8_t i = 0; i <= 8*tmp; i+=8) {
if (!i)
cpu->ps = (uint64_t)pull(cpu);
else
cpu->ps += (uint64_t)pull(cpu) << i;
}
break;
case PLA:
tmp = addr[cpu->pc[thread]++];
if (tmp > 7)
tmp = 7;
for (uint8_t i = 0; i <= 8*tmp; i+=8) {
if (!i)
cpu->a[thread] = (uint64_t)pull(cpu);
else
cpu->a[thread] += (uint64_t)pull(cpu) << i;
}
break;
case PLY:
tmp = addr[cpu->pc[thread]++];
if (tmp > 7)
tmp = 7;
for (uint8_t i = 0; i <= 8*tmp; i+=8) {
if (!i)
cpu->y[thread] = (uint64_t)pull(cpu);
else
cpu->y[thread] += (uint64_t)pull(cpu) << i;
}
break;
case PLX:
tmp = addr[cpu->pc[thread]++];
if (tmp > 7)
tmp = 7;
for (uint8_t i = 0; i <= 8*tmp; i+=8) {
if (!i)
cpu->x[thread] = (uint64_t)pull(cpu);
else
cpu->x[thread] += (uint64_t)pull(cpu) << i;
}
break;
case JSR:
address = (uint64_t)addr[cpu->pc[thread]]
| (uint64_t)addr[cpu->pc[thread]+1] << 8
| (uint64_t)addr[cpu->pc[thread]+2] << 16
| (uint64_t)addr[cpu->pc[thread]+3] << 24
| (uint64_t)addr[cpu->pc[thread]+4] << 32
| (uint64_t)addr[cpu->pc[thread]+5] << 40
| (uint64_t)addr[cpu->pc[thread]+6] << 48
| (uint64_t)addr[cpu->pc[thread]+7] << 56;
cpu->pc[thread]+=8;
push(cpu, (uint64_t)cpu->pc[thread] >> 56);
push(cpu, (uint64_t)cpu->pc[thread] >> 48);
push(cpu, (uint64_t)cpu->pc[thread] >> 40);
push(cpu, (uint64_t)cpu->pc[thread] >> 32);
push(cpu, (uint64_t)cpu->pc[thread] >> 24);
push(cpu, (uint64_t)cpu->pc[thread] >> 16);
push(cpu, (uint64_t)cpu->pc[thread] >> 8);
push(cpu, (uint64_t)cpu->pc[thread] & 0xFF);
cpu->pc[thread] = address;
break;
case AND: and_addr(cpu, &cpu->a[thread], immaddr(cpu, thread, 8), thread); break;
case ANY: and_addr(cpu, &cpu->y[thread], immaddr(cpu, thread, 8), thread); break;
case AAY: cpu->a[thread] = and(cpu, cpu->y[thread], thread); break;
case ANX: and_addr(cpu, &cpu->x[thread], immaddr(cpu, thread, 8), thread); break;
case AAX: cpu->a[thread] = and(cpu, cpu->x[thread], thread); break;
case STT: stt(cpu, immaddr(cpu, thread, 1)); break;
case 0x29: and_addr(cpu, &cpu->a[thread], absaddr(cpu, thread), thread); break;
case 0x2B: and_addr(cpu, &cpu->a[thread], zeromtx(cpu, thread), thread); break;
case BPO: bfc(cpu, cpu->n[thread], absaddr(cpu, thread), thread); break;
case ORA: or_addr(cpu, &cpu->a[thread], immaddr(cpu, thread, 8), thread); break;
case ORY: or_addr(cpu, &cpu->y[thread], immaddr(cpu, thread, 8), thread); break;
case OAY: cpu->a[thread] = or(cpu, cpu->y[thread], thread); break;
case ORX: or_addr(cpu, &cpu->x[thread], immaddr(cpu, thread, 8), thread); break;
case OAX: cpu->a[thread] = or(cpu, cpu->x[thread], thread); break;
case SEI:
cpu->i[thread] = 1;
setps(cpu, thread);
cpu->pc[thread]++;
break;
case 0x39: or_addr(cpu, &cpu->a[thread], absaddr(cpu, thread), thread); break;
case 0x3B: or_addr(cpu, &cpu->a[thread], zeromtx(cpu, thread), thread); break;
case BNG: bfs(cpu, cpu->n[thread], absaddr(cpu, thread), thread); break;
case XOR: xor_addr(cpu, &cpu->a[thread], immaddr(cpu, thread, 8), thread); break;
case XRY: xor_addr(cpu, &cpu->y[thread], immaddr(cpu, thread, 8), thread); break;
case XAY: cpu->a[thread] = xor(cpu, cpu->y[thread], thread); break;
case XRX: xor_addr(cpu, &cpu->x[thread], immaddr(cpu, thread, 9), thread); break;
case XAX: cpu->a[thread] = xor(cpu, cpu->x[thread], thread); break;
case CLI:
cpu->i[thread] = 0;
setps(cpu, thread);
cpu->pc[thread]++;
break;
case 0x49: xor_addr(cpu, &cpu->a[thread], absaddr(cpu, thread), thread); break;
case 0x4B: xor_addr(cpu, &cpu->a[thread], zeromtx(cpu, thread), thread); break;
case BCS: bfs(cpu, cpu->c[thread], absaddr(cpu, thread), thread); break;
case LSL: lsl(cpu, immaddr(cpu, thread, 1), thread); break;
case 0x52: and_addr(cpu, &cpu->y[thread], absaddr(cpu, thread), thread); break;
case 0x53: lsl(cpu, absaddr(cpu, thread), thread); break;
case 0x54: and_addr(cpu, &cpu->x[thread], absaddr(cpu, thread), thread); break;
case 0x55: lsl(cpu, zeromtx(cpu, thread), thread); break;
case SEC:
cpu->c[thread] = 1;
setps(cpu, thread);
cpu->pc[thread]++;
break;
case 0x59: ld(cpu, &cpu->a[thread], absaddr(cpu, thread), thread); break;
case 0x5A: ld(cpu, &cpu->y[thread], absaddr(cpu, thread), thread); break;
case 0x5B: st(cpu, &cpu->a[thread], absaddr(cpu, thread), thread); break;
case 0x5C: ld(cpu, &cpu->x[thread], absaddr(cpu, thread), thread); break;
case 0x5D: st(cpu, &cpu->y[thread], absaddr(cpu, thread), thread); break;
case 0x5E: st(cpu, &cpu->x[thread], absaddr(cpu, thread), thread); break;
case BCC: bfc(cpu, cpu->c[thread], absaddr(cpu, thread), thread); break;
case LSR: lsr(cpu, immaddr(cpu, thread, 1), thread); break;
case 0x62: or_addr(cpu, &cpu->y[thread], absaddr(cpu, thread), thread); break;
case 0x63: lsr(cpu, absaddr(cpu, thread), thread); break;
case 0x64: or_addr(cpu, &cpu->x[thread], absaddr(cpu, thread), thread); break;
case 0x65: lsr(cpu, zeromtx(cpu, thread), thread); break;
case CLC:
cpu->c[thread] = 0;
setps(cpu, thread);
cpu->pc[thread]++;
break;
case LDA: ld(cpu, &cpu->a[thread], immaddr(cpu, thread, 8), thread); break;
case LDY: ld(cpu, &cpu->y[thread], immaddr(cpu, thread, 8), thread); break;
case STA: st(cpu, &cpu->a[thread], immaddr(cpu, thread, 8), thread); break;
case LDX: ld(cpu, &cpu->x[thread], immaddr(cpu, thread, 8), thread); break;
case STY: st(cpu, &cpu->y[thread], immaddr(cpu, thread, 8), thread); break;
case STX: st(cpu, &cpu->x[thread], immaddr(cpu, thread, 8), thread); break;
case BEQ: bfs(cpu, cpu->z[thread], absaddr(cpu, thread), thread); break;
case ROL: rol(cpu, immaddr(cpu, thread, 1), thread); break;
case 0x72: xor_addr(cpu, &cpu->y[thread], absaddr(cpu, thread), thread); break;
case 0x73: rol(cpu, absaddr(cpu, thread), thread); break;
case 0x74: xor_addr(cpu, &cpu->x[thread], absaddr(cpu, thread), thread); break;
case 0x75: rol(cpu, zeromtx(cpu, thread), thread); break;
case SSP:
cpu->s[thread] = 1;
setps(cpu, thread);
cpu->pc[thread]++;
break;
case 0x79: ld(cpu, &cpu->a[thread], zeromtx(cpu, thread), thread); break;
case 0x7A: ld(cpu, &cpu->y[thread], zeromtx(cpu, thread), thread); break;
case 0x7B: st(cpu, &cpu->a[thread], zeromtx(cpu, thread), thread); break;
case 0x7C: ld(cpu, &cpu->x[thread], zeromtx(cpu, thread), thread); break;
case 0x7D: st(cpu, &cpu->y[thread], zeromtx(cpu, thread), thread); break;
case 0x7E: st(cpu, &cpu->x[thread], zeromtx(cpu, thread), thread); break;
case BNE: bfc(cpu, cpu->z[thread], absaddr(cpu, thread), thread); break;
case ROR: ror(cpu, immaddr(cpu, thread, 1), thread); break;
case 0x82: and_addr(cpu, &cpu->y[thread], zeromtx(cpu, thread), thread); break;
case 0x83: ror(cpu, absaddr(cpu, thread), thread); break;
case 0x84: and_addr(cpu, &cpu->x[thread], zeromtx(cpu, thread), thread); break;
case 0x85: ror(cpu, zeromtx(cpu, thread), thread); break;
case CSP:
cpu->s[thread] = 0;
setps(cpu, thread);
cpu->pc[thread]++;
break;
case 0x89: ld(cpu, &cpu->a[thread], zeromx(cpu, thread), thread); break;
case 0x8A: ld(cpu, &cpu->y[thread], zeromx(cpu, thread), thread); break;
case 0x8B: st(cpu, &cpu->a[thread], zeromx(cpu, thread), thread); break;
case 0x8D: st(cpu, &cpu->y[thread], zeromx(cpu, thread), thread); break;
case BVS: bfs(cpu, cpu->v[thread], absaddr(cpu, thread), thread); break;
case MUL: mul(cpu, immaddr(cpu, thread, 8), thread); break;
case 0x92: or_addr(cpu, &cpu->y[thread], zeromtx(cpu, thread), thread); break;
case 0x93: mul(cpu, absaddr(cpu, thread), thread); break;
case 0x94: or_addr(cpu, &cpu->x[thread], zeromtx(cpu, thread), thread); break;
case 0x95: mul(cpu, zeromtx(cpu, thread), thread); break;
case SEV:
cpu->v[thread] = 1;
setps(cpu, thread);
cpu->pc[thread]++;
break;
case 0x99: ld(cpu, &cpu->a[thread], zeromy(cpu, thread), thread); break;
case 0x9B: ld(cpu, &cpu->x[thread], zeromy(cpu, thread), thread); break;
case 0x9C: st(cpu, &cpu->a[thread], zeromy(cpu, thread), thread); break;
case 0x9E: st(cpu, &cpu->x[thread], zeromy(cpu, thread), thread); break;
case BVC: bfc(cpu, cpu->z[thread], absaddr(cpu, thread), thread); break;
case DIV: divd(cpu, immaddr(cpu, thread, 8), thread); break;
case 0xA2: xor_addr(cpu, &cpu->y[thread], zeromtx(cpu, thread), thread); break;
case 0xA3: divd(cpu, absaddr(cpu, thread), thread); break;
case 0xA4: xor_addr(cpu, &cpu->x[thread], zeromtx(cpu, thread), thread); break;
case 0xA5: divd(cpu, zeromtx(cpu, thread), thread); break;
case CLV:
cpu->v[thread] = 0;
setps(cpu, thread);
cpu->pc[thread]++;
break;
case RTS:
cpu->pc[thread] = (uint64_t)pull(cpu);
cpu->pc[thread] += ((uint64_t)pull(cpu) << 8);
cpu->pc[thread] += ((uint64_t)pull(cpu) << 16);
cpu->pc[thread] += ((uint64_t)pull(cpu) << 24);
cpu->pc[thread] += ((uint64_t)pull(cpu) << 32);
cpu->pc[thread] += ((uint64_t)pull(cpu) << 40);
cpu->pc[thread] += ((uint64_t)pull(cpu) << 48);
cpu->pc[thread] += ((uint64_t)pull(cpu) << 56) + 1;
break;
case CMP: cmp_addr(cpu, cpu->a[thread], immaddr(cpu, thread, 8), thread); break;
case CPY: cmp_addr(cpu, cpu->y[thread], immaddr(cpu, thread, 8), thread); break;
case CAY: cmp(cpu, cpu->a[thread], cpu->y[thread], thread); break;
case CPX: cmp_addr(cpu, cpu->x[thread], immaddr(cpu, thread, 8), thread); break;
case CAX: cmp(cpu, cpu->a[thread], cpu->x[thread], thread); break;
case ENT: ent(cpu, immaddr(cpu, thread, 1)); break;
case RTI: break;
case INC:
inc(cpu, &cpu->a[thread], thread);
break;
case INY: inc(cpu, &cpu->y[thread], thread); break;
case IAY: inc(cpu, &cpu->a[thread], thread); inc(cpu, &cpu->y[thread], thread); break;
case INX: inc(cpu, &cpu->x[thread], thread); break;
case IAX: inc(cpu, &cpu->a[thread], thread); inc(cpu, &cpu->x[thread], thread); break;
case DEC: dec(cpu, &cpu->a[thread], thread); break;
case DEY: dec(cpu, &cpu->y[thread], thread); break;
case DAY: dec(cpu, &cpu->a[thread], thread); dec(cpu, &cpu->y[thread], thread); break;
case DEX: dec(cpu, &cpu->x[thread], thread); break;
case DAX: dec(cpu, &cpu->a[thread], thread); dec(cpu, &cpu->x[thread], thread); break;
case 0xE1: inc_addr(cpu, absaddr(cpu, thread), thread); break;
case 0xE2: cmp_addr(cpu, cpu->y[thread], absaddr(cpu, thread), thread); break;
case 0xE3: inc_addr(cpu, zeromtx(cpu, thread), thread); break;
case 0xE4: cmp_addr(cpu, cpu->x[thread], absaddr(cpu, thread), thread); break;
case 0xE5: cmp_addr(cpu, cpu->a[thread], absaddr(cpu, thread), thread); break;
case NOP: cpu->pc[thread]++; break;
case 0xF1: dec_addr(cpu, absaddr(cpu, thread), thread); break;
case 0xF2: cmp_addr(cpu, cpu->y[thread], zeromtx(cpu, thread), thread); break;
case 0xF3: dec_addr(cpu, zeromtx(cpu, thread), thread); break;
case 0xF4: cmp_addr(cpu, cpu->x[thread], zeromtx(cpu, thread), thread); break;
case 0xF5: cmp_addr(cpu, cpu->a[thread], zeromtx(cpu, thread), thread); break;
case BRK: break;
default:
printf("Cool, you inputed a non existent opcode, which means\n"
"that you have now wasted clock cycles.\n"
"Good job! *clap*\n");
break;
}
return 1;
}
int main(int argc, char **argv) {
struct sux cpu;
cpu.a[0] = 0;
cpu.x[0] = 0;
cpu.y[0] = 0;
cpu.sp = 0xFFFF;
addr = malloc(8*0x04000000);
int v = 0;
/
/
/
/
/
/
/
/
/
/
/
addr[0x8000] = 0x00;
addr[0x8001] = 0xC5;
addr[0x8002] = 0x10;
addr[0x8003] = 0x01;
addr[0x8004] = 0x80;
addr[0x8005] = 0x00;
addr[0x8006] = 0x00;
addr[0x8007] = 0x00;
addr[0x8008] = 0x00;
addr[0x8009] = 0x00;
addr[0x800A] = 0x00;
addr[0xFFC0] = 0x00;
addr[0xFFC1] = 0x80;
addr[0xFFC2] = 0x00;
addr[0xFFC3] = 0x00;
addr[0xFFD0] = 0x00;
addr[0xFFD1] = 0x00;
addr[0xFFD2] = 0x00;
addr[0xFFD3] = 0x00;
cpu.pc[0] = (uint64_t)addr[0xFFC0]
| (uint64_t)addr[0xFFC1] << 8
| (uint64_t)addr[0xFFC2] << 16
| (uint64_t)addr[0xFFC3] << 24
| (uint64_t)addr[0xFFD0] << 32
| (uint64_t)addr[0xFFD1] << 40
| (uint64_t)addr[0xFFD2] << 48
| (uint64_t)addr[0xFFD3] << 56;
uint64_t inst = 0;
uint8_t lines = 2;
uint8_t opcode = 0;
uint8_t end = 0;
printf("\033[2J");
while (!end) {
opcode = addr[cpu.pc[0]];
printf("\033[%uH\033[2K", lines);
lines++;
run(&cpu, opcode, 0);
if (lines > 50)
lines = 2;
printf("\033[HInstructions executed: %llu\n", inst++);
}
free(addr);
return 0;
}