summaryrefslogtreecommitdiff
path: root/opcode.c
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2019-11-26 00:33:20 -0500
committermrb0nk500 <b0nk@b0nk.xyz>2019-11-26 00:33:20 -0500
commitc1e735ec8b0481c1ebc631cd495a10f72e47ba32 (patch)
treee43331c872a35790e070ad2daded086a5ef6f8c7 /opcode.c
parent988c81ae76ab0da47db8938c14865d6e5b3a8024 (diff)
Revamped the entire emulator.
I finally implemented the other addressing modes, and added a Makefile. Not sure when I will start work on rev2 of Sux, but it will be sometime soon.
Diffstat (limited to 'opcode.c')
-rw-r--r--opcode.c358
1 files changed, 358 insertions, 0 deletions
diff --git a/opcode.c b/opcode.c
new file mode 100644
index 0000000..ea3f726
--- /dev/null
+++ b/opcode.c
@@ -0,0 +1,358 @@
+#include "opcode.h"
+void setps(struct sux *cpu, uint8_t thread) {
+ (cpu->c[thread]) ? (cpu->ps |= (C << 8*thread)) : (cpu->ps &= ~(C << 8*thread));
+ (cpu->z[thread]) ? (cpu->ps |= (Z << 8*thread)) : (cpu->ps &= ~(Z << 8*thread));
+ (cpu->i[thread]) ? (cpu->ps |= (I << 8*thread)) : (cpu->ps &= ~(I << 8*thread));
+ (cpu->s[thread]) ? (cpu->ps |= (S << 8*thread)) : (cpu->ps &= ~(S << 8*thread));
+ (cpu->v[thread]) ? (cpu->ps |= (V << 8*thread)) : (cpu->ps &= ~(V << 8*thread));
+ (cpu->n[thread]) ? (cpu->ps |= (N << 8*thread)) : (cpu->ps &= ~(N << 8*thread));
+}
+
+void adc(struct sux *cpu, uint64_t adr, uint8_t thread) {
+ uint64_t value = (uint64_t)addr[adr]
+ | (uint64_t)addr[adr+1] << 8
+ | (uint64_t)addr[adr+2] << 16
+ | (uint64_t)addr[adr+3] << 24
+ | (uint64_t)addr[adr+4] << 32
+ | (uint64_t)addr[adr+5] << 40
+ | (uint64_t)addr[adr+6] << 48
+ | (uint64_t)addr[adr+7] << 56;
+ uint64_t sum = cpu->a[thread]+value+cpu->c[thread];
+ cpu->z[thread] = (sum == 0);
+ cpu->n[thread] = (sum >> 63);
+ cpu->v[thread] = !((cpu->a[thread]^value) & 0x8000000000000000) && ((cpu->a[thread]^sum) & 0x8000000000000000);
+ cpu->c[thread] = (sum < value);
+ cpu->a[thread] = sum;
+ setps(cpu, thread);
+}
+
+void sbc(struct sux *cpu, uint64_t adr, uint8_t thread) {
+ uint64_t value = (uint64_t)addr[adr]
+ | (uint64_t)addr[adr+1] << 8
+ | (uint64_t)addr[adr+2] << 16
+ | (uint64_t)addr[adr+3] << 24
+ | (uint64_t)addr[adr+4] << 32
+ | (uint64_t)addr[adr+5] << 40
+ | (uint64_t)addr[adr+6] << 48
+ | (uint64_t)addr[adr+7] << 56;
+ uint64_t sum = cpu->a[thread]-value-!cpu->c[thread];
+ cpu->z[thread] = (sum == 0);
+ cpu->n[thread] = (sum >> 63);
+ cpu->v[thread] = ((cpu->a[thread]^value) & 0x8000000000000000) && ((cpu->a[thread]^sum) & 0x8000000000000000);
+ cpu->c[thread] = (sum > value);
+ cpu->a[thread] = sum;
+ setps(cpu, thread);
+}
+
+void mul(struct sux *cpu, uint64_t adr, uint8_t thread) {
+ uint64_t value = (uint64_t)addr[adr]
+ | (uint64_t)addr[adr+1] << 8
+ | (uint64_t)addr[adr+2] << 16
+ | (uint64_t)addr[adr+3] << 24
+ | (uint64_t)addr[adr+4] << 32
+ | (uint64_t)addr[adr+5] << 40
+ | (uint64_t)addr[adr+6] << 48
+ | (uint64_t)addr[adr+7] << 56;
+ uint64_t sum = cpu->a[thread]*value+cpu->c[thread];
+ cpu->z[thread] = (sum == 0);
+ cpu->n[thread] = (sum >> 63);
+ cpu->v[thread] = !((cpu->a[thread]^value) & 0x8000000000000000) && ((cpu->a[thread]^sum) & 0x8000000000000000);
+ cpu->c[thread] = (!((cpu->a[thread]^sum) && (cpu->a[thread]^value)) || (cpu->a[thread] >= ((uint64_t)1 << 32) && value >= ((uint64_t)1 << 32)));
+ cpu->a[thread] = sum;
+ setps(cpu, thread);
+}
+
+void divd(struct sux *cpu, uint64_t adr, uint8_t thread) {
+ uint64_t value = (uint64_t)addr[adr]
+ | (uint64_t)addr[adr+1] << 8
+ | (uint64_t)addr[adr+2] << 16
+ | (uint64_t)addr[adr+3] << 24
+ | (uint64_t)addr[adr+4] << 32
+ | (uint64_t)addr[adr+5] << 40
+ | (uint64_t)addr[adr+6] << 48
+ | (uint64_t)addr[adr+7] << 56;
+ uint64_t sum = cpu->a[thread]/value;
+ cpu->z[thread] = (sum == 0);
+ cpu->v[thread] = !((cpu->a[thread]^value) & 0x8000000000000000) && ((cpu->a[thread]^sum) & 0x8000000000000000);
+ cpu->a[thread] = sum;
+ setps(cpu, thread);
+}
+
+uint64_t and(struct sux *cpu, uint64_t value, uint8_t thread) {
+ uint64_t sum;
+ sum &= value;
+ cpu->z[thread] = (sum == 0);
+ cpu->n[thread] = (sum >> 63);
+ setps(cpu, thread);
+ return sum;
+}
+
+void and_addr(struct sux *cpu, uint64_t* const reg, uint64_t adr, uint8_t thread) {
+ uint64_t value = (uint64_t)addr[adr]
+ | (uint64_t)addr[adr+1] << 8
+ | (uint64_t)addr[adr+2] << 16
+ | (uint64_t)addr[adr+3] << 24
+ | (uint64_t)addr[adr+4] << 32
+ | (uint64_t)addr[adr+5] << 40
+ | (uint64_t)addr[adr+6] << 48
+ | (uint64_t)addr[adr+7] << 56;
+ *reg &= value;
+ cpu->z[thread] = (*reg == 0);
+ cpu->n[thread] = (*reg >> 63);
+ setps(cpu, thread);
+}
+
+uint64_t or(struct sux *cpu, uint64_t value, uint8_t thread) {
+ uint64_t sum;
+ sum |= value;
+ cpu->z[thread] = (sum == 0);
+ cpu->n[thread] = (sum >> 63);
+ setps(cpu, thread);
+ return sum;
+}
+
+void or_addr(struct sux *cpu, uint64_t* const reg, uint64_t adr, uint8_t thread) {
+ uint64_t value = (uint64_t)addr[adr]
+ | (uint64_t)addr[adr+1] << 8
+ | (uint64_t)addr[adr+2] << 16
+ | (uint64_t)addr[adr+3] << 24
+ | (uint64_t)addr[adr+4] << 32
+ | (uint64_t)addr[adr+5] << 40
+ | (uint64_t)addr[adr+6] << 48
+ | (uint64_t)addr[adr+7] << 56;
+ *reg |= value;
+ cpu->z[thread] = (*reg == 0);
+ cpu->n[thread] = (*reg >> 63);
+ setps(cpu, thread);
+}
+
+uint64_t xor(struct sux *cpu, uint64_t value, uint8_t thread) {
+ uint64_t sum;
+ sum ^= value;
+ cpu->z[thread] = (sum == 0);
+ cpu->n[thread] = (sum >> 63);
+ setps(cpu, thread);
+ return sum;
+}
+
+void xor_addr(struct sux *cpu, uint64_t* const reg, uint64_t adr, uint8_t thread) {
+ uint64_t value = (uint64_t)addr[adr]
+ | (uint64_t)addr[adr+1] << 8
+ | (uint64_t)addr[adr+2] << 16
+ | (uint64_t)addr[adr+3] << 24
+ | (uint64_t)addr[adr+4] << 32
+ | (uint64_t)addr[adr+5] << 40
+ | (uint64_t)addr[adr+6] << 48
+ | (uint64_t)addr[adr+7] << 56;
+ *reg ^= value;
+ cpu->z[thread] = (*reg == 0);
+ cpu->n[thread] = (*reg >> 63);
+ setps(cpu, thread);
+}
+
+void rol(struct sux *cpu, uint64_t adr, uint8_t thread) {
+ uint64_t value = addr[adr];
+ uint64_t sum = cpu->a[thread] << value;
+ sum |= cpu->c[thread];
+ cpu->z[thread] = (sum == 0);
+ cpu->n[thread] = (sum >> 63);
+ cpu->c[thread] = cpu->a[thread] >> (uint64_t)64-value;
+ cpu->a[thread] = sum;
+ setps(cpu, thread);
+}
+
+void ror(struct sux *cpu, uint64_t adr, uint8_t thread) {
+ uint64_t value = addr[adr];
+ uint64_t sum = cpu->a[thread] >> value;
+ sum |= (uint64_t)cpu->c[thread] << (uint64_t)64-value;
+ cpu->c[thread] = cpu->a[thread] & 1;
+ cpu->a[thread] = sum;
+ setps(cpu, thread);
+}
+
+void lsl(struct sux *cpu, uint64_t adr, uint8_t thread) {
+ uint64_t value = addr[adr];
+ uint64_t sum = (value < 64) ? cpu->a[thread] << value : 0;
+ cpu->c[thread] = cpu->a[thread] >> 64-value;
+ cpu->a[thread] = sum;
+ setps(cpu, thread);
+}
+
+void lsr(struct sux *cpu, uint64_t adr, uint8_t thread) {
+ uint64_t value = addr[adr];
+ uint64_t sum = (value < 64) ? cpu->a[thread] >> value : 0;
+ cpu->c[thread] = cpu->a[thread] & 1;
+ cpu->a[thread] = sum;
+ setps(cpu, thread);
+}
+
+void inc(struct sux *cpu, uint64_t *reg, uint8_t thread) {
+ *reg += 1;
+ cpu->z[thread] = (*reg == 0);
+ cpu->n[thread] = (*reg >> 63);
+ setps(cpu, thread);
+}
+
+void inc_addr(struct sux *cpu, uint64_t adr, uint8_t thread) {
+ addr[adr]++;
+}
+
+void dec(struct sux *cpu, uint64_t *reg, uint8_t thread) {
+ *reg -= 1;
+ cpu->z[thread] = (*reg == 0);
+ cpu->n[thread] = (*reg >> 63);
+ setps(cpu, thread);
+}
+
+void dec_addr(struct sux *cpu, uint64_t adr, uint8_t thread) {
+ addr[adr]--;
+}
+
+void stt(struct sux* const cpu, uint8_t value) {
+ uint16_t tv = 0xFF50; /* Thread Vector. */
+ uint8_t t = addr[value];
+ cpu->crt |= t;
+ for (uint8_t i = 0; i < 7; i++)
+ if ((t >> i) & 1) {
+ uint64_t adr = (uint64_t)addr[tv+(8*i)]
+ | (uint64_t)addr[tv+1+(8*i)] << 8
+ | (uint64_t)addr[tv+2+(8*i)] << 16
+ | (uint64_t)addr[tv+3+(8*i)] << 24
+ | (uint64_t)addr[tv+4+(8*i)] << 32
+ | (uint64_t)addr[tv+5+(8*i)] << 40
+ | (uint64_t)addr[tv+6+(8*i)] << 48
+ | (uint64_t)addr[tv+7+(8*i)] << 56;
+ cpu->pc[i+1] = adr;
+ }
+}
+
+void ent(struct sux *cpu, uint8_t value) {
+ uint8_t t = addr[value];
+ cpu->crt &= ~t;
+ for (uint8_t i = 0; i < 7; i++)
+ if ((t >> i) & 1)
+ cpu->pc[i+1] = cpu->pc[0]+(i+1);
+}
+
+void ld(struct sux *cpu, uint64_t *reg, uint64_t adr, uint8_t thread) {
+ *reg = (uint64_t)addr[adr]
+ | (uint64_t)addr[adr+1] << 8
+ | (uint64_t)addr[adr+2] << 16
+ | (uint64_t)addr[adr+3] << 24
+ | (uint64_t)addr[adr+4] << 32
+ | (uint64_t)addr[adr+5] << 40
+ | (uint64_t)addr[adr+6] << 48
+ | (uint64_t)addr[adr+7] << 56;
+ cpu->z[thread] = (*reg == 0);
+ cpu->n[thread] = (*reg >> 63);
+ setps(cpu, thread);
+}
+
+void st(struct sux *cpu, uint64_t *reg, uint64_t adr, uint8_t thread) {
+ addr[adr] = *reg & 0xFF;
+ addr[adr+1] = *reg >> 8;
+ addr[adr+2] = *reg >> 16;
+ addr[adr+3] = *reg >> 24;
+ addr[adr+4] = *reg >> 32;
+ addr[adr+5] = *reg >> 40;
+ addr[adr+6] = *reg >> 48;
+ addr[adr+7] = *reg >> 56;
+}
+
+void push(struct sux *cpu, uint8_t value) {
+ addr[STK_STADDR+cpu->sp] = value;
+ cpu->sp--;
+ addr[0xFF90] = cpu->sp & 0xFF;
+ addr[0xFF91] = cpu->sp >> 8;
+}
+
+uint8_t pull(struct sux *cpu) {
+ cpu->sp++;
+ addr[0xFF90] = cpu->sp & 0xFF;
+ addr[0xFF91] = cpu->sp >> 8;
+ return addr[STK_STADDR+cpu->sp];
+}
+
+void cmp_addr(struct sux *cpu, uint64_t reg, uint64_t adr, uint8_t thread) {
+ uint64_t value = (uint64_t)addr[adr]
+ | (uint64_t)addr[adr+1] << 8
+ | (uint64_t)addr[adr+2] << 16
+ | (uint64_t)addr[adr+3] << 24
+ | (uint64_t)addr[adr+4] << 32
+ | (uint64_t)addr[adr+5] << 40
+ | (uint64_t)addr[adr+6] << 48
+ | (uint64_t)addr[adr+7] << 56;
+ uint64_t sum = reg-value;
+ cpu->n[thread] = (sum & 0x8000000000000000) ? 1 : 0;
+ cpu->z[thread] = (sum == 0) ? 1 : 0;
+ cpu->c[thread] = (sum > value) ? 1 : 0;
+ setps(cpu, thread);
+}
+
+void cmp(struct sux *cpu, uint64_t reg1, uint64_t reg2, uint8_t thread) {
+ uint64_t sum = reg1-reg2;
+ cpu->n[thread] = (sum & 0x8000000000000000) ? 1 : 0;
+ cpu->z[thread] = (sum == 0) ? 1 : 0;
+ cpu->c[thread] = (sum > reg2) ? 1 : 0;
+ setps(cpu, thread);
+}
+
+/* Branch if Flag Set. */
+void bfs(struct sux *cpu, uint8_t flag, uint64_t adr, uint8_t thread) {
+ if (flag)
+ cpu->pc[thread] = adr;
+}
+
+/* Branch if Flag Clear. */
+void bfc(struct sux *cpu, uint8_t flag, uint64_t adr, uint8_t thread) {
+ if (!flag)
+ cpu->pc[thread] = adr;
+}
+
+uint64_t immaddr(struct sux *cpu, uint8_t thread, uint8_t size) {
+ uint64_t adr = cpu->pc[thread];
+ cpu->pc[thread]+=size;
+ return adr;
+}
+
+uint64_t absaddr(struct sux *cpu, uint8_t thread) {
+ uint64_t adr = (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;
+ return adr;
+}
+
+uint32_t zeromtx(struct sux *cpu, uint8_t thread) {
+ uint32_t adr = (uint32_t)addr[cpu->pc[thread]]
+ | (uint32_t)addr[cpu->pc[thread]+1] << 8
+ | (uint32_t)addr[cpu->pc[thread]+2] << 16
+ | (uint32_t)addr[cpu->pc[thread]+3] << 24;
+ cpu->pc[thread]+=4;
+ return adr;
+}
+
+uint32_t zeromx(struct sux *cpu, uint8_t thread) {
+ uint32_t adr = (uint32_t)addr[cpu->pc[thread]]
+ | (uint32_t)addr[cpu->pc[thread]+1] << 8
+ | (uint32_t)addr[cpu->pc[thread]+2] << 16
+ | (uint32_t)addr[cpu->pc[thread]+3] << 24;
+ adr += cpu->x[thread];
+ cpu->pc[thread]+=4;
+ return adr;
+}
+
+uint32_t zeromy(struct sux *cpu, uint8_t thread) {
+ uint32_t adr = (uint32_t)addr[cpu->pc[thread]]
+ | (uint32_t)addr[cpu->pc[thread]+1] << 8
+ | (uint32_t)addr[cpu->pc[thread]+2] << 16
+ | (uint32_t)addr[cpu->pc[thread]+3] << 24;
+ adr += cpu->y[thread];
+ cpu->pc[thread]+=4;
+ return adr;
+}