diff options
author | mrb0nk500 <b0nk@b0nk.xyz> | 2020-08-13 17:25:09 -0400 |
---|---|---|
committer | mrb0nk500 <b0nk@b0nk.xyz> | 2020-08-13 17:25:09 -0400 |
commit | 7e57608dff1e768d2ee5d6b6a28a319865530ed0 (patch) | |
tree | 26a0f3795c29f8fd9e55cf63bcac278ddf55302a | |
parent | a9860417f53216a2f3b0b490afec46ab5db70181 (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-- | Makefile | 8 | ||||
-rw-r--r-- | disasm.c | 142 | ||||
-rw-r--r-- | io.c | 14 | ||||
-rw-r--r-- | opcode.h | 2 | ||||
-rw-r--r-- | sux.c | 107 | ||||
-rw-r--r-- | sux.h | 343 |
6 files changed, 333 insertions, 283 deletions
@@ -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 @@ -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) { @@ -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') { @@ -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. */ }; @@ -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); @@ -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); } |