summaryrefslogtreecommitdiff
path: root/sux.c
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 /sux.c
parentf070b984f4d1af513d215bd24e6b1951e3ee86cb (diff)
The emulator is working!!!
Diffstat (limited to 'sux.c')
-rw-r--r--sux.c268
1 files changed, 242 insertions, 26 deletions
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;
+
+}