summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2019-11-17 23:04:31 -0500
committermrb0nk500 <b0nk@b0nk.xyz>2019-11-17 23:04:31 -0500
commitc42888e7e09b0a45c6b02534829eac06506834a6 (patch)
treefd720f5aca4e603efd4e549d798ab318e38c17fd
parentf070b984f4d1af513d215bd24e6b1951e3ee86cb (diff)
The emulator is working!!!
-rw-r--r--opcode.h92
-rw-r--r--sux.c268
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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#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;
+
+}