summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2020-08-13 17:25:09 -0400
committermrb0nk500 <b0nk@b0nk.xyz>2020-08-13 17:25:09 -0400
commit7e57608dff1e768d2ee5d6b6a28a319865530ed0 (patch)
tree26a0f3795c29f8fd9e55cf63bcac278ddf55302a
parenta9860417f53216a2f3b0b490afec46ab5db70181 (diff)
Refactored get_addr(), and all of the effective
address handling. It's now all done using several functions for each addressing mode, with the result being the effective address. I did this to make the codebase cleaner, and more readable.
-rw-r--r--Makefile8
-rw-r--r--disasm.c142
-rw-r--r--io.c14
-rw-r--r--opcode.h2
-rw-r--r--sux.c107
-rw-r--r--sux.h343
6 files changed, 333 insertions, 283 deletions
diff --git a/Makefile b/Makefile
index 454ea42..4f234e4 100644
--- a/Makefile
+++ b/Makefile
@@ -35,12 +35,18 @@ else
IO_CFLAGS=-DIO=0
endif
+ifdef GET_CLK
+CLK_CFLAGS=-Dgetclk=1
+else
+CLK_CFLAGS=-Dgetclk=0
+endif
+
OBJS = sux.o io.o $(DBG_OBJ) asmmon.o assemble.o lexer.o
OBJS2 = subasm.o subeditor.o
OBJS3 = opcode-gen.o csv-parse.o
-CFLAGS = $(PCC_CFLAGS) $(DBG_CFLAGS) $(IO_CFLAGS) $(BENCH_CFLAGS) $(CFLAGS_EXTRA)
+CFLAGS = $(PCC_CFLAGS) $(DBG_CFLAGS) $(IO_CFLAGS) $(CLK_CFLAGS) $(BENCH_CFLAGS) $(CFLAGS_EXTRA)
OBJ_NAME = cisc-0.2
OBJ_NAME2 = subeditor-c
diff --git a/disasm.c b/disasm.c
index 57cef04..3645ec3 100644
--- a/disasm.c
+++ b/disasm.c
@@ -2,24 +2,25 @@
#include "disasm.h"
#include <string.h>
-void disasm(struct sux *cpu, uint64_t *operands, uint8_t lines, uint8_t opcode, uint8_t prefix, uint8_t thread) {
- uint64_t value = operands[0];
- uint64_t address = operands[1];
- uint64_t tmpaddr = operands[2];
+void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint8_t thread) {
+ union reg value;
+ uint64_t address = get_addr(cpu, opcode, prefix, 0, 0, thread);
+ uint8_t rs = (prefix >> 4) & 3;
char *postfix;
char *of;
char op[4];
char *sign = "";
+ char *ind = "";
uint8_t tmp = 0;
union reg mask;
mask.u64 = 0;
memcpy(op, opname[opcode], 3);
op[3] = 0;
- switch ((1 << ((prefix >> 4) & 3))) {
- case 1: postfix = ""; break;
- case 2: postfix = ".W"; break;
- case 4: postfix = ".D"; break;
- case 8: postfix = ".Q"; break;
+ switch (rs) {
+ case 0: postfix = ""; break;
+ case 1: postfix = ".W"; break;
+ case 2: postfix = ".D"; break;
+ case 3: postfix = ".Q"; break;
}
if (prefix >> 6) {
tmp = 0;
@@ -29,7 +30,7 @@ void disasm(struct sux *cpu, uint64_t *operands, uint8_t lines, uint8_t opcode,
case 1 : of = "SP"; break;
case 2 : of = "PC"; break;
}
- uint8_t addrsize = 0xFF;
+ uint8_t addrsize = 0;
char *idx;
switch (optype[opcode]) {
case IND : idx = ")"; break;
@@ -39,106 +40,47 @@ void disasm(struct sux *cpu, uint64_t *operands, uint8_t lines, uint8_t opcode,
case ZMY : idx = ", y"; break;
default : idx = ""; break;
}
- if ((prefix >> 6) == 1 || (prefix >> 6) == 2) {
- switch (optype[opcode]) {
- case ZM :
- case ZMX :
- case ZMY :
- case IND :
- case INDX:
- case INDY: addrsize = get_addrsize(prefix, ZM); break;
- case ABS : addrsize = get_addrsize(prefix, ABS); break;
- }
- for (uint8_t i = 0; i < addrsize+1; i++) {
- mask.u8[i] = (i == addrsize && addrsize != 0xFF) ? 0x7F : 0xFF;
- }
+ switch (optype[opcode]) {
+ case ZM :
+ case ZMX :
+ case ZMY :
+ case IND :
+ case INDX:
+ case INDY: addrsize = get_addrsize(prefix, ZM); break;
+ case ABS : addrsize = get_addrsize(prefix, ABS); break;
+ case IMM :
+ case REL : addrsize = (1 << rs)-1; break;
+ }
+
+ for (uint8_t i = 0; i < addrsize+1; i++) {
+ mask.u8[i] = (i == addrsize && addrsize != 0xFF) ? 0x7F : 0xFF;
+ }
+ value = read_value(cpu, cpu->pc, addrsize, 0, 0);
+ if ((prefix >> 6) == 1 || (prefix >> 6) == 2 || optype[opcode] == REL) {
switch (addrsize) {
- case 0 : sign = ((int8_t )value < 0) ? "-" : "+"; break;
- case 1 : sign = ((int16_t)value < 0) ? "-" : "+"; break;
+ case 0 : sign = ((int8_t )value.u8 [0] < 0) ? "-" : "+"; break;
+ case 1 : sign = ((int16_t)value.u16[0] < 0) ? "-" : "+"; break;
case 2 :
- case 3 : sign = ((int32_t)value < 0) ? "-" : "+"; break;
+ case 3 : sign = ((int32_t)value.u32[0] < 0) ? "-" : "+"; break;
case 4 :
case 5 :
case 6 :
- case 7 : sign = ((int64_t)value < 0) ? "-" : "+"; break;
+ case 7 : sign = ((int64_t)value.u64 < 0) ? "-" : "+"; break;
}
+ value.u64 &= mask.u64;
}
-
switch (optype[opcode]) {
case BREG:
- case IMPL:
- wprintw(scr, "%s%s" , opname[opcode], postfix);
- break;
- case IMM:
- switch ((1 << ((prefix >> 4) & 3))) {
- case 1: wprintw(scr, "%s #$%02X" , op, value); break;
- case 2: wprintw(scr, "%s%s #$%04X" , op, postfix, value); break;
- case 4: wprintw(scr, "%s%s #$%08X" , op, postfix, value); break;
- case 8: wprintw(scr, "%s%s #$%016"PRIX64 , op, postfix, value); break;
- }
- break;
- case ZM:
- case ZMX:
- case ZMY:
- if ((prefix >> 6) == 1 || (prefix >> 6) == 2) {
- tmpaddr &= mask.u64;
- }
- switch (optype[opcode]) {
- case ZMX: tmpaddr = address - cpu->x; break;
- case ZMY: tmpaddr = address - cpu->y; break;
- }
- switch ((prefix & 0x0C) >> 2) {
- case 3: wprintw(scr, "%s%s %s%s$%08" PRIX64"%s" , op, postfix, of, sign, tmpaddr, idx); break;
- case 2: wprintw(scr, "%s%s %s%s$%014"PRIX64"%s" , op, postfix, of, sign, tmpaddr, idx); break;
- case 1: wprintw(scr, "%s%s %s%s$%06" PRIX64"%s" , op, postfix, of, sign, tmpaddr, idx); break;
- case 0: wprintw(scr, "%s%s %s%s$%02" PRIX64"%s" , op, postfix, of, sign, tmpaddr, idx); break;
- }
- break;
- case IND:
+ case IMPL: wprintw(scr, "%s%s" , opname[opcode], postfix); break;
+ case IMM : wprintw(scr, "%s%s #$%0*"PRIX64 , op, postfix, (addrsize+1) << 1, value.u64); break;
+ case IND :
case INDX:
- case INDY:
- if ((prefix >> 6) == 1 || (prefix >> 6) == 2) {
- tmpaddr &= mask.u64;
- }
- switch ((prefix & 0x0C) >> 2) {
- case 3: wprintw(scr, "%s%s (%s%s$%08" PRIX64"%s", op, postfix, of, sign, tmpaddr, idx); break;
- case 2: wprintw(scr, "%s%s (%s%s$%014"PRIX64"%s", op, postfix, of, sign, tmpaddr, idx); break;
- case 1: wprintw(scr, "%s%s (%s%s$%06" PRIX64"%s", op, postfix, of, sign, tmpaddr, idx); break;
- case 0: wprintw(scr, "%s%s (%s%s$%02" PRIX64"%s", op, postfix, of, sign, tmpaddr, idx); break;
- }
- break;
- case ABS:
- tmpaddr = address;
- if ((prefix >> 6) == 1 || (prefix >> 6) == 2) {
- tmpaddr &= mask.u64;
- }
- switch ((prefix & 0x0C) >> 2) {
- case 3: wprintw(scr, "%s%s %s%s$%016"PRIX64 , op, postfix, of, sign, tmpaddr); break;
- case 2: wprintw(scr, "%s%s %s%s$%014"PRIX64 , op, postfix, of, sign, tmpaddr); break;
- case 1: wprintw(scr, "%s%s %s%s$%010"PRIX64 , op, postfix, of, sign, tmpaddr); break;
- case 0: wprintw(scr, "%s%s %s%s$%04" PRIX64 , op, postfix, of, sign, tmpaddr); break;
- }
- break;
- case REL:
- switch((1 << ((prefix >> 4) & 3))) {
- case 1:
- sign = ((int8_t)value < 0) ? "-" : "+";
- wprintw(scr, "%s %s$%02X" , op, sign, value & 0x7F);
- break;
- case 2:
- sign = ((int16_t)value < 0) ? "-" : "+";
- wprintw(scr, "%s%s %s$%04X" , op, postfix, sign, value & ~(1 << 15));
- break;
- case 4:
- sign = ((int32_t)value < 0) ? "-" : "+";
- wprintw(scr, "%s%s %s$%08X" , op, postfix, sign, value & ~(1 << 31));
- break;
- case 8:
- sign = ((int64_t)value < 0) ? "-" : "+";
- wprintw(scr, "%s%s %s$%016"PRIX64 , op, postfix, sign, value & ~((uint64_t)1 << 63));
- break;
- }
- break;
+ case INDY: ind = "("; /* Falls through. */
+ case ZMX :
+ case ZMY :
+ case ZM :
+ case ABS : wprintw(scr, "%s%s %s%s%s$%0*" PRIX64"%s" , op, postfix, ind, of, sign, (addrsize+1) << 1, value.u64, idx); break;
+ case REL : wprintw(scr, "%s%s %s$%0*"PRIX64 , op, postfix, sign, (addrsize+1) << 1, value.u64); break;
}
if (address == TX_ADDR || address == RX_ADDR) {
diff --git a/io.c b/io.c
index 37116df..4e69f7e 100644
--- a/io.c
+++ b/io.c
@@ -231,6 +231,13 @@ void reset_esc() {
void handle_ctrlcode(int c) {
int x, y;
+ uint16_t scr_col = 0;
+ #if debug
+ if (!subdbg) {
+ scr_col = (addr[TX_ADDR] != 0x0C && addr[TX_ADDR] != '\n' && scr_col < 160) ? (addr[1] << 1)-2 : 0;
+ wmove(scr, 28, scr_col);
+ }
+ #endif
getyx(scr, y, x);
switch (c) {
case 0xC:
@@ -288,7 +295,6 @@ void handle_ctrlcode(int c) {
void io(uint64_t address, uint8_t rw) {
- uint16_t scr_col = 0;
/*step |= (!rw) ? (cpu->pc[thread] == CTRL_ADDR) : step;*/
switch (address) {
case STEP_ADDR: step = (!rw) ? addr[STEP_ADDR] : step; break;
@@ -305,12 +311,6 @@ void io(uint64_t address, uint8_t rw) {
if (rw) {
break;
}
- #if debug
- if (!subdbg) {
- scr_col = (addr[TX_ADDR] != 0x0C && addr[TX_ADDR] != '\n' && scr_col < 160) ? (addr[1] << 1)-2 : 0;
- wmove(scr, 28, scr_col);
- }
- #endif
if (esc) {
#if debug
if (!subdbg && addr[RX_ADDR] == '\n') {
diff --git a/opcode.h b/opcode.h
index 1c48b55..fc2c8e6 100644
--- a/opcode.h
+++ b/opcode.h
@@ -7,7 +7,6 @@
#include "tables.h"
-#define getclk 0
#define keypoll 0
#define OPNUM 74
@@ -58,6 +57,7 @@ struct sux {
uint64_t pc; /* Program counter. */
uint16_t sp; /* Stack pointer. */
uint16_t stk_st; /* Starting address of each threads stack. */
+ uint64_t clk; /* Number of clock cycles. */
uint8_t crt; /* Current running threads. */
};
diff --git a/sux.c b/sux.c
index d26118d..9442cd4 100644
--- a/sux.c
+++ b/sux.c
@@ -69,6 +69,38 @@ inline uint8_t get_addrsize(uint8_t prefix, uint8_t addrmode) {
return 0;
}
+static inline uint8_t isrw(uint8_t opcode) {
+ switch (opcode) {
+ case STA_AB: /* STA Absolute. */
+ case STA_Z: /* STA Zero Matrix. */
+ case STA_ZX: /* STA Zero Matrix, Indexed with X. */
+ case STA_ZY: /* STA Zero Matrix, Indexed with Y. */
+ case STA_IN: /* STA Indirect. */
+ case STA_IX: /* STA Indexed Indirect. */
+ case STA_IY: /* STA Indirect Indexed. */
+ case STY_AB: /* STY Absolute. */
+ case STY_Z: /* STY Zero Matrix. */
+ case STY_IN: /* STY Indirect. */
+ case STX_AB: /* STX Absolute. */
+ case STX_Z: /* STX Zero Matrix. */
+ case STX_IN: /* STX Indirect. */
+ case STB_AB: /* STB Absolute. */
+ case STB_Z: /* STB Zero Matrix. */
+ case STB_ZX: /* STB Zero Matrix, Indexed with X. */
+ case STB_ZY: /* STB Zero Matrix, Indexed with Y. */
+ case STB_IN: /* STB Indirect. */
+ case STB_IX: /* STB Indexed Indirect. */
+ case STB_IY: /* STB Indirect Indexed. */
+ case INC_AB: /* INC Absolute. */
+ case INC_Z: /* INC Zero Matrix. */
+ case DEC_AB: /* DEC Absolute. */
+ case DEC_Z: /* DEC Zero Matrix. */
+ return 0; /* Writing. */
+ default:
+ return 1; /* Reading. */
+ }
+}
+
void *run(void *args) {
struct suxthr *thr = (void *)args;
struct sux *cpu = &thr->sx;
@@ -77,9 +109,7 @@ void *run(void *args) {
uint8_t opcode = 0;
union reg address;
union reg value;
- #if getclk
- uint64_t iclk = 0;
- #endif
+ cpu->clk = 0;
#if !IO
uint64_t ins = 0;
#endif
@@ -104,6 +134,14 @@ void *run(void *args) {
gettimeofday(&str[thread], 0);
#endif
for (;;) {
+ #if !bench
+ if (end) {
+ pthread_mutex_lock(&main_mutex);
+ pthread_cond_signal(&main_cond);
+ pthread_mutex_unlock(&main_mutex);
+ return NULL;
+ }
+ #endif
address.u64 = 0;
value.u64 = 0;
#if debug && !bench
@@ -137,46 +175,35 @@ void *run(void *args) {
}
cpu->pc += ((prefix & 0x03) == 0x03);
opcode = addr[cpu->pc];
- address.u64 = cpu->pc;
++cpu->pc;
+ address.u64 = cpu->pc;
#if getclk
- ++iclk;
+ ++cpu->clk;
#endif
- if (optype[opcode] != IMPL) {
- address.u64 = get_addr(cpu, &tmpaddr, opcode, prefix, thread);
-
- if (address.u64 > mem_size-1) {
- addr[STEP_ADDR] = 1;
- step = 1;
- }
- setreg_sw(value.u8, 0, addr, address.u64, prefix, 0, RS);
- if (optype[opcode] == REL) {
- switch ((prefix >> 4) & 3) {
- default: address.u64 = cpu->pc + (int8_t )value.u8[0] ; break;
- case 1 : address.u64 = cpu->pc + (int16_t)value.u16[0]; break;
- case 2 : address.u64 = cpu->pc + (int32_t)value.u32[0]; break;
- case 3 : address.u64 = cpu->pc + (int64_t)value.u64 ; break;
- }
- }
- #if getclk
- ++iclk;
- #endif
- }
+ uint8_t am = optype[opcode];
+ uint8_t rs = (prefix >> 4) & 3;
+ uint8_t size = (/***/1 << rs) - 1;
+ uint8_t check_io = (am != IMM);
#if debug && !bench
#if keypoll
pthread_mutex_lock(&mutex);
#endif
- uint64_t operands[3];
- operands[0] = value.u64;
- operands[1] = address.u64;
- operands[2] = tmpaddr;
- disasm(cpu, operands, lines, opcode, prefix, thread);
+ disasm(cpu, lines, opcode, prefix, thread);
lines+=1;
#if keypoll
pthread_mutex_unlock(&mutex);
#endif
#endif
- uint8_t size = (1 << ((prefix >> 4) & 3))-1;
+ if (am != IMPL && am != BREG) {
+ address.u64 = get_addr(cpu, opcode, prefix, 1, 1, thread);
+ if (address.u64 > mem_size-1) {
+ addr[STEP_ADDR] = 1;
+ step = 1;
+ }
+ if (isrw(opcode) && am != REL) {
+ value = read_value(cpu, address.u64, size, 1, check_io);
+ }
+ }
switch(opcode) {
case CPS_IMP: /* Clear Processor Status. */
cpu->ps.u64 = 0;
@@ -334,7 +361,7 @@ void *run(void *args) {
case LDB_IN: /* LDB Indirect. */
case LDB_IX: /* LDB Indexed Indirect. */
case LDB_IY: /* LDB Indirect Indexed. */
- cpu->b = load(cpu, address.u64, cpu->b, prefix, thread);
+ cpu->b = load(cpu, value.u64, thread);
break;
case LDA_IMM: /* LDA Immediate. */
case LDA_AB: /* LDA Absolute. */
@@ -344,19 +371,19 @@ void *run(void *args) {
case LDA_IN: /* LDA Indirect. */
case LDA_IX: /* LDA Indexed Indirect. */
case LDA_IY: /* LDA Indirect Indexed. */
- cpu->a = load(cpu, address.u64, cpu->a, prefix, thread);
+ cpu->a = load(cpu, value.u64, thread);
break;
case LDY_IMM: /* LDY Immediate. */
case LDY_AB: /* LDY Absolute. */
case LDY_Z: /* LDY Zero Matrix. */
case LDY_IN: /* LDY Indirect. */
- cpu->y = load(cpu, address.u64, cpu->y, prefix, thread);
+ cpu->y = load(cpu, value.u64, thread);
break;
case LDX_IMM: /* LDX Immediate. */
case LDX_AB: /* LDX Absolute. */
case LDX_Z: /* LDX Zero Matrix. */
case LDX_IN: /* LDX Indirect. */
- cpu->x = load(cpu, address.u64, cpu->x, prefix, thread);
+ cpu->x = load(cpu, value.u64, thread);
break;
case BEQ_REL: /* BEQ Relative. */
if (getflag(Z)) {
@@ -490,12 +517,6 @@ void *run(void *args) {
ins++;
#endif
#if !bench
- if (end) {
- pthread_mutex_lock(&main_mutex);
- pthread_cond_signal(&main_cond);
- pthread_mutex_unlock(&main_mutex);
- return NULL;
- }
if (step) {
int c = 0;;
for (; step && c != 19 && !end; c = get_key(scr));
@@ -511,7 +532,7 @@ void *run(void *args) {
wmove(scr, (6*thread)+1, 0);
wprintw(scr, "Instructions executed: %"PRIu64, ins);
#if getclk
- wprintw(scr, ", Clock cycles: %"PRIu64, iclk);
+ wprintw(scr, ", Clock cycles: %"PRIu64, cpu->clk);
#endif
if (step && !subdbg) {
wrefresh(scr);
@@ -525,7 +546,7 @@ void *run(void *args) {
threads_done++;
inst[thread] = ins;
#if getclk
- clk[thread] = iclk;
+ clk[thread] = cpu->clk;
#endif
pthread_cond_signal(&main_cond);
pthread_mutex_unlock(&main_mutex);
diff --git a/sux.h b/sux.h
index b729550..3f53a4d 100644
--- a/sux.h
+++ b/sux.h
@@ -39,7 +39,7 @@ extern pthread_cond_t cond;
extern pthread_cond_t main_cond;
#if debug
-extern void disasm(struct sux *cpu, uint64_t *operands, uint8_t lines, uint8_t opcode, uint8_t prefix, uint8_t thread);
+extern void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint8_t thread);
#endif
/*#define KEYBUF_SIZE 0x40
@@ -49,7 +49,181 @@ extern int get_key(WINDOW *scr);
extern void io(uint64_t address, uint8_t rw);
extern void init_scr();
-static inline uint64_t get_addr(struct sux *cpu, uint64_t *tmpaddr, uint8_t opcode, uint8_t prefix, uint8_t thread) {
+static inline union reg read_value(struct sux *cpu, uint64_t address, uint8_t size, uint8_t inc_clk, uint8_t check_io) {
+ union reg value;
+ value.u64 = 0;
+ #if (IO || debug) && !branch
+ #if keypoll
+ pthread_mutex_lock(&mutex);
+ #endif
+ if (check_io) {
+ io(address, 1);
+ }
+ #if keypoll
+ pthread_mutex_unlock(&mutex);
+ #endif
+ #endif
+ switch (size) {
+ case 7: value.u8[7] = addr[address+7];
+ case 6: value.u8[6] = addr[address+6];
+ case 5: value.u8[5] = addr[address+5];
+ case 4: value.u8[4] = addr[address+4];
+ case 3: value.u8[3] = addr[address+3];
+ case 2: value.u8[2] = addr[address+2];
+ case 1: value.u8[1] = addr[address+1];
+ case 0: value.u8[0] = addr[address+0];
+ }
+ #if getclk
+ if (inc_clk) {
+ ++cpu->clk;
+ }
+ #endif
+ return value;
+}
+
+static inline void write_value(struct sux *cpu, union reg value, uint64_t address, uint8_t size, uint8_t inc_clk, uint8_t check_io) {
+ switch (size) {
+ case 7: addr[address+7] = value.u8[7];
+ case 6: addr[address+6] = value.u8[6];
+ case 5: addr[address+5] = value.u8[5];
+ case 4: addr[address+4] = value.u8[4];
+ case 3: addr[address+3] = value.u8[3];
+ case 2: addr[address+2] = value.u8[2];
+ case 1: addr[address+1] = value.u8[1];
+ case 0: addr[address+0] = value.u8[0];
+ }
+ #if (IO || debug) && !branch
+ #if keypoll
+ pthread_mutex_lock(&mutex);
+ #endif
+ if (check_io) {
+ io(address, 0);
+ }
+ #if keypoll
+ pthread_mutex_unlock(&mutex);
+ #endif
+ #endif
+ #if getclk
+ if (inc_clk) {
+ ++cpu->clk;
+ }
+ #endif
+}
+
+static inline uint64_t offset_addr(struct sux *cpu, union reg offset, uint8_t size, uint8_t inc_clk, uint8_t prefix) {
+ uint64_t of;
+ switch (prefix >> 6) {
+ case 1: of = ((cpu->stk_st << 16) | cpu->sp); break;
+ case 2: of = cpu->pc ; break;
+ }
+ #if getclk
+ if (inc_clk) {
+ ++cpu->clk;
+ }
+ #endif
+ switch (size) {
+ case 0: return of + (int8_t )offset.u8 [0];
+ case 1: return of + (int16_t)offset.u16[0];
+ case 2:
+ case 3: return of + (int32_t)offset.u32[0];
+ case 4:
+ case 5:
+ case 6:
+ case 7: return of + (int64_t)offset.u64 ;
+ }
+}
+
+static inline uint64_t imm_addr(struct sux *cpu) {
+ return cpu->pc;
+}
+
+static inline uint64_t zm_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) {
+ union reg address = read_value(cpu, cpu->pc, get_addrsize(prefix, ZM), inc_clk, 0);
+ if (prefix >> 6) {
+ address.u64 = offset_addr(cpu, address, get_addrsize(prefix, ZM), inc_clk, prefix);
+ }
+ if (inc_pc) {
+ cpu->pc += get_addrsize(prefix, ZM)+1;
+ }
+ return address.u64;
+}
+
+static inline uint64_t zmx_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) {
+ #if getclk
+ if (inc_clk) {
+ ++cpu->clk;
+ }
+ #endif
+ return zm_addr(cpu, prefix, inc_clk, inc_pc) + cpu->x;
+}
+
+static inline uint64_t zmy_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) {
+ #if getclk
+ if (inc_clk) {
+ ++cpu->clk;
+ }
+ #endif
+ return zm_addr(cpu, prefix, inc_clk, inc_pc) + cpu->y;
+}
+
+static inline uint64_t abs_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) {
+ union reg address = read_value(cpu, cpu->pc, get_addrsize(prefix, ABS), inc_clk, 0);
+ if (prefix >> 6) {
+ address.u64 = offset_addr(cpu, address, get_addrsize(prefix, ABS), inc_clk, prefix);
+ }
+ if (inc_pc) {
+ cpu->pc += get_addrsize(prefix, ABS)+1;
+ }
+ return address.u64;
+}
+
+static inline uint64_t ind_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) {
+ union reg address = read_value(cpu, zm_addr(cpu, prefix, inc_clk, inc_pc), 7, inc_clk, 0);
+ return address.u64;
+}
+
+static inline uint64_t indx_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) {
+ union reg address = read_value(cpu, zm_addr(cpu, prefix, inc_clk, inc_pc)+cpu->x, 7, inc_clk, 0);
+ #if getclk
+ if (inc_clk) {
+ ++cpu->clk;
+ }
+ #endif
+ return address.u64;
+}
+
+static inline uint64_t indy_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) {
+ #if getclk
+ if (inc_clk) {
+ ++cpu->clk;
+ }
+ #endif
+ return ind_addr(cpu, prefix, inc_clk, inc_pc) + cpu->y;
+}
+
+static inline uint64_t rel_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) {
+ uint8_t rs = (prefix >> 4) & 3;
+ uint8_t size = (1 << rs) - 1;
+ union reg offset = read_value(cpu, cpu->pc, size, inc_clk, 0);
+ uint64_t address;
+ if (inc_pc) {
+ cpu->pc += (size + 1);
+ }
+ switch (rs) {
+ default: address = cpu->pc + (int8_t )offset.u8 [0]; break;
+ case 1 : address = cpu->pc + (int16_t)offset.u16[0]; break;
+ case 2 : address = cpu->pc + (int32_t)offset.u32[0]; break;
+ case 3 : address = cpu->pc + (int64_t)offset.u64 ; break;
+ }
+ #if getclk
+ if (inc_clk) {
+ ++cpu->clk;
+ }
+ #endif
+ return address;
+}
+
+static inline uint64_t get_addr(struct sux *cpu, uint8_t opcode, uint8_t prefix, uint8_t inc_pc, uint8_t inc_clk, uint8_t thread) {
union reg address;
union reg value;
uint8_t tmp = 0;
@@ -62,116 +236,33 @@ static inline uint64_t get_addr(struct sux *cpu, uint64_t *tmpaddr, uint8_t opco
case IMPL:
break;
case IMM:
- address.u64 = cpu->pc;
+ address.u64 = imm_addr(cpu);
switch (opcode) {
case LSL_IMM:
case LSR_IMM:
case ROL_IMM:
case ROR_IMM:
- case ASR_IMM: ++cpu->pc; break;
- default : cpu->pc+=(1 << ((prefix >> 4) & 3)); /* Falls Through. */
- case TXS_IMM: break;
- }
- break;
- case ZM:
- case ZMX:
- case ZMY:
- case IND:
- case INDX:
- case INDY:
- tmp = 0;
- address.u8[0] = addr[cpu->pc];
- /* Unroll Loop by implementing Duff's Device. */
- tmp = get_addrsize(prefix, ZM)+1;
- setreg_sw(address.u8, 0, addr, cpu->pc, prefix, ZM, AM);
-
- cpu->pc+=tmp;
- #if debug && !bench
- *tmpaddr = address.u64;
- #endif
- #if getclk
- iclk++;
- #endif
- uint64_t reg = 0;
- saveaddr.u64 = 0;
- if (prefix >> 6) {
- switch (prefix >> 6) {
- case 1: tmp2 = ((cpu->stk_st << 16) | cpu->sp); break;
- case 2: tmp2 = cpu->pc ; break;
- }
- saveaddr = address;
- switch ((prefix & 0x0C) >> 2) {
- case 0: saveaddr.u64 = tmp2 + (int8_t )address.u8[0] ; break;
- case 2: saveaddr.u64 = tmp2 + (int64_t)address.u64 ; break;
- case 1:
- case 3: saveaddr.u64 = tmp2 + (int32_t)address.u32[0]; break;
- }
- address.u64 = saveaddr.u64;
- }
- switch (optype[opcode]) {
- case ZMX:
- address.u64 += cpu->x;
- #if getclk
- iclk++;
- #endif
- break;
- case ZMY:
- address.u64 += cpu->y;
- #if getclk
- iclk++;
- #endif
+ case ASR_IMM:
+ if (inc_pc) {
+ ++cpu->pc;
+ }
break;
- case INDX:
- case INDY:
- if (optype[opcode] == INDX) {
- address.u64 += cpu->x;
- #if getclk
- iclk++;
- #endif
- } else {
- reg += cpu->y;
- #if getclk
- iclk++;
- #endif
+ default:
+ if (inc_pc) {
+ cpu->pc+=(1 << ((prefix >> 4) & 3));
}
/* Falls Through. */
- case IND:
- setreg(value.u8, +, 0, addr, +, address.u64, 7);
- #if getclk
- iclk++;
- #endif
- value.u64 += reg;
- address.u64 = value.u64;
- break;
- }
- break;
- case ABS:
- tmp = get_addrsize(prefix, ABS)+1;
- setreg_sw(address.u8, 0, addr, cpu->pc, prefix, ABS, AM);
- cpu->pc+=tmp;
- #if getclk
- iclk++;
- #endif
- saveaddr.u64 = 0;
- if (prefix >> 6) {
- switch (prefix >> 6) {
- case 1: tmp2 = ((cpu->stk_st << 16) | cpu->sp); break;
- case 2: tmp2 = cpu->pc ; break;
- }
- saveaddr = address;
- switch ((prefix & 0x0C) >> 2) {
- case 0: saveaddr.u64 = tmp2 + (int16_t)address.u16[0]; break;
- case 1:
- case 2:
- case 3: saveaddr.u64 = tmp2 + (int64_t)address.u64 ; break;
- }
- address.u64 = saveaddr.u64;
+ case TXS_IMM: break;
}
break;
- case REL:
- address.u64 = cpu->pc;
- cpu->pc+=(1 << ((prefix >> 4) & 3));
- break;
+ case ZM : address.u64 = zm_addr(cpu, prefix, inc_clk, inc_pc); break;
+ case ZMX : address.u64 = zmx_addr(cpu, prefix, inc_clk, inc_pc); break;
+ case ZMY : address.u64 = zmy_addr(cpu, prefix, inc_clk, inc_pc); break;
+ case IND : address.u64 = ind_addr(cpu, prefix, inc_clk, inc_pc); break;
+ case INDX: address.u64 = indx_addr(cpu, prefix, inc_clk, inc_pc); break;
+ case INDY: address.u64 = indy_addr(cpu, prefix, inc_clk, inc_pc); break;
+ case ABS : address.u64 = abs_addr(cpu, prefix, inc_clk, inc_pc); break;
+ case REL : address.u64 = rel_addr(cpu, prefix, inc_clk, inc_pc); break;
}
return address.u64;
@@ -222,16 +313,14 @@ static inline void push(struct sux *cpu, uint64_t value, uint8_t size, uint8_t t
union reg reg;
reg.u64 = value;
uint64_t sbr = (cpu->stk_st << 16);
- setreg(addr, -, (sbr+cpu->sp), reg.u8, -, size, size);
+ write_value(cpu, reg, (sbr+cpu->sp)-size, size, 1, 0);
cpu->sp -= size+1;
}
static inline uint64_t pull(struct sux *cpu, uint8_t size, uint8_t thread) {
- union reg reg;
- reg.u64 = 0;
uint64_t sbr = (cpu->stk_st << 16);
+ union reg reg = read_value(cpu, sbr+cpu->sp+1, size, 1, 0);
cpu->sp += size+1;
- setreg(reg.u8, -, size, addr, -, (sbr+cpu->sp), size);
return reg.u64;
}
@@ -335,42 +424,34 @@ static inline uint64_t idr(struct sux *cpu, uint64_t reg, uint8_t inc, uint8_t t
/* Increment, or Decrement memory. */
static inline void idm(struct sux *cpu, uint64_t address, uint8_t prefix, uint8_t inc, uint8_t thread) {
- union reg value;
- value.u64 = 0;
- /* Unroll Loop by implementing Duff's Device. */
- setreg_sw(value.u8, 0, addr, address, prefix, 0, RS);
+ uint8_t size = (1 << ((prefix >> 4) & 3))-1;
+ union reg value = read_value(cpu, address, size, 1, 0);
if (inc) {
value.u64++;
} else {
value.u64--;
}
+ uint8_t sign = 0;
+ switch ((prefix >> 4) & 3) {
+ default: sign = 7; break;
+ case 1: sign = 15; break;
+ case 2: sign = 31; break;
+ case 3: sign = 63; break;
+ }
setflag(value.u64 == 0, Z);
- setflag(value.u64 >> 7, N);
- setreg_sw(addr, address, value.u8, 0, prefix, 0, RS);
- io(address, 0);
+ setflag(value.u64 >> sign, N);
+ write_value(cpu, value, address, size, 1, 1);
}
-static inline uint64_t load(struct sux *cpu, uint64_t address, uint64_t reg, uint8_t prefix, uint8_t thread) {
- io(address, 1);
- union reg value;
- value.u64 = reg;
- setreg_sw(value.u8, 0, addr, address, prefix, 0, RS);
- setflag(value.u64 == 0, Z);
- setflag(value.u64 >> 63, N);
- return value.u64;
+static inline uint64_t load(struct sux *cpu, uint64_t value, uint8_t thread) {
+ setflag(value == 0, Z);
+ setflag(value >> 63, N);
+ return value;
}
static inline void store(struct sux *cpu, uint64_t address, uint64_t reg, uint8_t prefix, uint8_t thread) {
+ uint8_t size = (1 << ((prefix >> 4) & 3))-1;
union reg value;
value.u64 = reg;
- setreg_sw(addr, address, value.u8, 0, prefix, 0, RS);
- #if (IO || debug) && !branch
- #if keypoll
- pthread_mutex_lock(&mutex);
- #endif
- io(address, 0);
- #if keypoll
- pthread_mutex_unlock(&mutex);
- #endif
- #endif
+ write_value(cpu, value, address, size, 1, 1);
}