summaryrefslogtreecommitdiff
path: root/sux.h
diff options
context:
space:
mode:
Diffstat (limited to 'sux.h')
-rw-r--r--sux.h343
1 files changed, 212 insertions, 131 deletions
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);
}