From c42888e7e09b0a45c6b02534829eac06506834a6 Mon Sep 17 00:00:00 2001 From: mrb0nk500 Date: Sun, 17 Nov 2019 23:04:31 -0500 Subject: The emulator is working!!! --- opcode.h | 92 +++++++++++++++++++++- sux.c | 268 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 333 insertions(+), 27 deletions(-) diff --git a/opcode.h b/opcode.h index 1c17052..757850e 100644 --- a/opcode.h +++ b/opcode.h @@ -1,4 +1,4 @@ -#define OPNAME(opcode) #opcode /* Get name of Opcode, for dissambly. */ +#define OPNAME(opcode) [opcode] = #opcode /* Get name of Opcode, for dissambly. */ #define CPS 0x00 /* Clear Processor Status. */ #define ADC 0x01 /* ADd with Carry. */ #define PHP 0x08 /* PusH Processor status to stack. */ @@ -84,3 +84,93 @@ #define STX 0xF4 /* STore X register. */ #define SAX 0xF5 /* Store Accumulator, and X register. */ #define BRK 0xF8 /* BReaK. */ +#define STP 0xFF /* SToP. */ + +static const char *opname[0x100] = { + OPNAME(CPS), + OPNAME(ADC), + OPNAME(PHP), + OPNAME(PHA), + OPNAME(PHY), + OPNAME(PAY), + OPNAME(PHX), + OPNAME(PAX), + OPNAME(JMP), + OPNAME(SBC), + OPNAME(PLP), + OPNAME(PLA), + OPNAME(PLY), + OPNAME(PYA), + OPNAME(PLX), + OPNAME(PXA), + OPNAME(JSR), + OPNAME(AND), + OPNAME(ANY), + OPNAME(AAY), + OPNAME(ANX), + OPNAME(AAX), + OPNAME(STT), + OPNAME(BPO), + OPNAME(ORA), + OPNAME(ORY), + OPNAME(OAY), + OPNAME(ORX), + OPNAME(OAX), + OPNAME(SEI), + OPNAME(BNG), + OPNAME(XOR), + OPNAME(XRY), + OPNAME(XAY), + OPNAME(XRX), + OPNAME(XAX), + OPNAME(CLI), + OPNAME(BCS), + OPNAME(SLA), + OPNAME(SEC), + OPNAME(BCC), + OPNAME(SRA), + OPNAME(CLC), + OPNAME(BEQ), + OPNAME(ROL), + OPNAME(SSP), + OPNAME(BNE), + OPNAME(ROR), + OPNAME(CSP), + OPNAME(BVS), + OPNAME(MUL), + OPNAME(SEV), + OPNAME(BVC), + OPNAME(DIV), + OPNAME(CLV), + OPNAME(RTS), + OPNAME(CMP), + OPNAME(CPY), + OPNAME(CAY), + OPNAME(CPX), + OPNAME(CAX), + OPNAME(ENT), + OPNAME(RTI), + OPNAME(INC), + OPNAME(INY), + OPNAME(IAY), + OPNAME(INX), + OPNAME(IAX), + OPNAME(DEC), + OPNAME(DEY), + OPNAME(DAY), + OPNAME(DEX), + OPNAME(DAX), + OPNAME(LDA), + OPNAME(LDY), + OPNAME(LAY), + OPNAME(LDX), + OPNAME(LAX), + OPNAME(NOP), + OPNAME(STA), + OPNAME(STY), + OPNAME(SAY), + OPNAME(STX), + OPNAME(SAX), + OPNAME(BRK), + OPNAME(STP), +}; diff --git a/sux.c b/sux.c index 0c84a9a..b3e019d 100644 --- a/sux.c +++ b/sux.c @@ -1,7 +1,18 @@ #include "opcode.h" #include +#include +#include +#include +#define C (1 << 0) +#define Z (1 << 1) +#define I (1 << 2) +#define S (1 << 3) +#define V (1 << 6) +#define N (1 << 7) + #define STK_STADDR 0x010000 /* Starting address of the stack. */ uint8_t *addr; /* Address Space. */ +uint8_t update_pc = 1; /* Update the program counter. */ uint16_t sp; /* Stack pointer. */ uint64_t a[8]; /* Accumulator. */ uint64_t y[8]; /* Y index. */ @@ -126,19 +137,14 @@ int alu(uint8_t opcode, uint64_t value, uint8_t thread) { break; /* Shift accumulator left. */ case SLA: - c = (ps & (1 << thread)) >> thread; - if (value > 1) - c = ((a << value-1) & 0x8000000000000000) >> 63; sum = (value < 64) ? a[thread] << value : 0; + c = a[thread] >> 63; a[thread] = sum; break; /* Shift accumulator right. */ case SRA: - c = (ps & (1 << thread)) >> thread; - if (value > 1) - c = (a >> value-1) & 1; - sum = (value < 64) ? a << value : 0; - c = sum & 1; + sum = (value < 64) ? a[thread] >> value : 0; + c = a[thread] & 1; a[thread] = sum; break; /* Rotate accumulator left. */ @@ -156,7 +162,7 @@ int alu(uint8_t opcode, uint64_t value, uint8_t thread) { a[thread]++; if (opcode == IAY) y[thread]++; - if[opcode == IAX] + if (opcode == IAX) x[thread]++; break; /* Increment y register. */ @@ -174,7 +180,7 @@ int alu(uint8_t opcode, uint64_t value, uint8_t thread) { a[thread]--; if (opcode == DAY) y[thread]--; - if[opcode == DAX] + if (opcode == DAX) x[thread]--; break; /* Decrement y register. */ @@ -186,17 +192,17 @@ int alu(uint8_t opcode, uint64_t value, uint8_t thread) { x[thread]--; break; default: - printf("Cool, you inputed a non existent opcode, which means\n" + /*printf("Cool, you inputed a non existent opcode, which means\n" "that you have now wasted clock cycles.\n" - "Good job! *clap*\n"); + "Good job! *clap*\n");*/ break; } z = (a[thread] == 0); n = (a[thread] >> 63); - ps = (n) ? (ps | 1 << 7+thread) : (ps & ~(1 << 7+thread)); - ps = (v) ? (ps | 1 << 6+thread) : (ps & ~(1 << 6+thread)); - ps = (z) ? (ps | 1 << 1+thread) : (ps & ~(1 << 1+thread)); - ps = (c) ? (ps | 1 << thread) : (ps & ~(1 << thread)); + ps = (n) ? (ps | (uint64_t)N << 8*thread) : (ps & ~((uint64_t)N << 8*thread)); + ps = (v) ? (ps | (uint64_t)V << 8*thread) : (ps & ~((uint64_t)V << 8*thread)); + ps = (z) ? (ps | (uint64_t)Z << 8*thread) : (ps & ~((uint64_t)Z << 8*thread)); + ps = (c) ? (ps | (uint64_t)C << 8*thread) : (ps & ~((uint64_t)C << 8*thread)); return 1; } @@ -222,6 +228,7 @@ int threads(uint8_t opcode, uint64_t value) { } int branch(uint8_t opcode, uint64_t value, uint8_t thread) { + uint64_t dif; switch (opcode) { /* Jump. */ case JMP: @@ -236,6 +243,132 @@ int branch(uint8_t opcode, uint64_t value, uint8_t thread) { case RTS: pc[thread] = pull(8); break; + /* Branch if positive. */ + case BPO: + if (!(ps & ((uint64_t)N << 8*thread))) + pc[thread] = value; + else + pc[thread]+=0; + break; + /* Branch if negative. */ + case BNG: + if (ps & ((uint64_t)N << 8*thread)) + pc[thread] = value; + else + pc[thread]+=0; + break; + /* Branch if equal. */ + case BEQ: + if (ps & ((uint64_t)Z << 8*thread)) + pc[thread] = value; + else + pc[thread]+=0; + break; + /* Branch if not equal. */ + case BNE: + if (!(ps & ((uint64_t)Z << 8*thread))) + pc[thread] = value; + else + pc[thread]+=0; + break; + /* Branch if carry set. */ + case BCS: + if (ps & ((uint64_t)C << 8*thread)) + pc[thread] = value; + else + pc[thread]+=0; + break; + /* Branch if carry clear. */ + case BCC: + if (!(ps & ((uint64_t)C << 8*thread))) + pc[thread] = value; + else + pc[thread]+=0; + break; + /* Branch if overflow set. */ + case BVS: + if (ps & ((uint64_t)V << 8*thread)) + pc[thread] = value; + else + pc[thread]+=0; + break; + /* Branch if overflow clear. */ + case BVC: + if (!(ps & ((uint64_t)V << 8*thread))) + pc[thread] = value; + else + pc[thread]+=0; + break; + /* Compare accumulator. */ + case CMP: + case CAY: + case CAX: + if (opcode == CAY || opcode == CAX) { + dif = (opcode == CAY) ? a[thread]-y[thread] : a[thread]-x[thread]; + value = a[thread]; + } else { + dif = value-a[thread]; + } + ps = (dif & 0x8000000000000000) ? (ps | (uint64_t)N << 8*thread) : (ps & ~((uint64_t)N << 8*thread)); + ps = (dif == 0) ? (ps | (uint64_t)Z << 8*thread) : (ps & ~((uint64_t)Z << 8*thread)); + ps = (dif > value) ? (ps | (uint64_t)C << 8*thread) : (ps & ~((uint64_t)C << 8*thread)); + break; + /* Compare y register. */ + case CPY: + dif = value-y[thread]; + ps = (dif & 0x8000000000000000) ? (ps | (uint64_t)N << 8*thread) : (ps & ~((uint64_t)N << 8*thread)); + ps = (dif == 0) ? (ps | (uint64_t)Z << 8*thread) : (ps & ~((uint64_t)Z << 8*thread)); + ps = (dif > value) ? (ps | (uint64_t)C << 8*thread) : (ps & ~((uint64_t)C << 8*thread)); + break; + /* Compare x register. */ + case CPX: + dif = value-x[thread]; + ps = (dif & 0x8000000000000000) ? (ps | (uint64_t)N << 8*thread) : (ps & ~((uint64_t)N << 8*thread)); + ps = (dif == 0) ? (ps | (uint64_t)Z << 8*thread) : (ps & ~((uint64_t)Z << 8*thread)); + ps = (dif > value) ? (ps | (uint64_t)C << 8*thread) : (ps & ~((uint64_t)C << 8*thread)); + break; + } + return 1; +} + +int setflags(uint8_t opcode, uint8_t thread) { + switch (opcode) { + /* Clear processor status. */ + case CPS: + ps &= 0; + break; + /* Set interupt flag. */ + case SEI: + ps |= ((uint64_t)I << 8*thread); + break; + /* Clear interupt flag. */ + case CLI: + ps &= ~((uint64_t)I << 8*thread); + break; + /* Set carry flag. */ + case SEC: + ps |= ((uint64_t)C << 8*thread); + break; + /* Clear carry flag. */ + case CLC: + ps &= ~((uint64_t)C << 8*thread); + break; + /* Set stack protection flag. */ + case SSP: + ps |= ((uint64_t)S << 8*thread); + break; + /* Clear stack protection flag. */ + case CSP: + ps &= ~((uint64_t)S << 8*thread); + break; + /* Set overflow flag. */ + case SEV: + ps |= ((uint64_t)V << 8*thread); + break; + /* Clear overflow flag. */ + case CLV: + ps &= ~((uint64_t)V << 8*thread); + break; } return 1; } @@ -289,17 +422,17 @@ int memory(uint8_t opcode, uint64_t value, uint8_t thread) { case PHA: case PAY: case PAX: - push(a, value); + push(a[thread], value); if (opcode == PAY) - push(y, value); + push(y[thread], value); if (opcode == PAX) - push(x, value); + push(x[thread], value); break; case PHY: - push(y, value); + push(y[thread], value); break; case PHX: - push(x, value); + push(x[thread], value); break; /* Pull processor status. */ case PLP: @@ -309,20 +442,103 @@ int memory(uint8_t opcode, uint64_t value, uint8_t thread) { case PLA: case PYA: case PXA: - a = pull(value); + a[thread] = pull(value); if (opcode == PAY) - y = pull(value); + y[thread] = pull(value); if (opcode == PAX) - x = pull(value); + x[thread] = pull(value); break; /* Pull y register. */ case PLY: - y = pull(value); + y[thread] = pull(value); break; /* Pull x register. */ case PLX: - x = pull(value); + x[thread] = pull(value); break; } return 1; } + +int misc(uint8_t opcode, uint8_t thread) { + switch (opcode) { + /* No operation. */ + case NOP: + break; + /* TODO: Implement interupts. */ + case BRK: + break; + } + return 1; +} + +int main(int argc, char **argv) { + a[0] = 0; + x[0] = 0; + y[0] = 0; + addr = malloc(8*0x04000000); + int v = 0; + addr[0x8000] = 0x00; /* CPS */ + addr[0x8001] = 0xE1; /* LDA #$E1 */ + addr[0x8002] = 0x01; + addr[0x8003] = 0x51; /* SLA #$01 */ + addr[0x8004] = 0x01; + addr[0x8005] = 0xF1; /* STA $4000*/ + addr[0x8006] = 0x00; + addr[0x8007] = 0x40; + addr[0x8008] = 0x50; /* BCS $8001 */ + addr[0x8009] = 0x01; + addr[0x800A] = 0x80; + addr[0x800B] = 0x10; /* JMP $1003 */ + addr[0x800C] = 0x03; + addr[0x800D] = 0x80; + addr[0x8010] = 0xFF; /* STP */ + addr[0xFFFC] = 0x00; + addr[0xFFFD] = 0x80; + pc[0] = addr[0xFFFC] | (addr[0xFFFD] << 8); + uint64_t value = 0; + uint8_t end = 0; + uint8_t opcode = 0; + uint8_t size; + printf("\033[2J"); + while (!end) { + printf("pc: 0x%04llx, a: 0x%016llx, carry: %u, inst: %s, value: 0x%04llx, $%04llx: %02x\n", pc[0], a[0], ps & 1, opname[opcode], value, value, addr[value]); + opcode = addr[pc[0]]; + if (opcode == STA || opcode == JMP || opcode == BCS) + size = 2; + else if (opcode == CPS || opcode == NOP) + size = 0; + else if (opcode == STP) + end = 1, size = 0; + else + size = 1; + if(update_pc) + pc[0]++; + else + update_pc = 1; + if (size) { + int i = 0; + while (i < size) { + if (!i) + value = (addr[pc[0]]); + else + value |= (addr[pc[0]] << (8*i)); + printf("pc: 0x%04llx, a: 0x%016llx, carry: %u, inst: %s, value: 0x%04llx, $%04llx: %02x\n", pc[0], a[0], ps & 1, opname[opcode], value, value, addr[value]); + if (update_pc) + pc[0]++; + else + update_pc = 1; + i++; + } + } + if (opcode == SLA || opcode == ADC) + alu(opcode, value, 0); + if (opcode == JMP || opcode == BCS) + branch(opcode, value, 0); + memory(opcode, value, 0); + printf("pc: 0x%04llx, a: 0x%016llx, carry: %u, inst: %s, value: 0x%04llx, $%04llx: %02x\n", pc[0], a[0], ps & 1, opname[opcode], value, value, addr[value]); + } + free(addr); + return 0; + +} -- cgit v1.2.3-13-gbd6f