#include "opcode.h"
#include <assert.h>
#include <ctype.h>
#include <string.h>
#include <pthread.h>
#define bench 0
#define debug 0
#define IO 1
#define keypoll 0
#if bench
#include <sys/time.h>
#else
#include <curses.h>
#endif
#define THREADS 1
#define BENCH_INST 100000000 << THREADS-1
#define CTRL_ADDR 0xC000
#define TX_ADDR 0xC001
#define RX_ADDR 0xC002
#define STEP_ADDR 0xC010
#define CURSES_BACKSPACE 0x7F
#define setflag(flag, bit) (flag) ? (cpu->ps |= (bit << (thread << 3))) : (cpu->ps &= ~(bit << (thread << 3)))
#define clearflags(thread) {\
cpu->c[thread] = 0;\
cpu->z[thread] = 0;\
cpu->i[thread] = 0;\
cpu->s[thread] = 0;\
cpu->v[thread] = 0;\
cpu->n[thread] = 0;\
}
uint64_t clk[THREADS];
uint64_t tclk;
uint64_t inst[THREADS];
uint64_t inss;
uint8_t threads_done = 0;
uint8_t kbd_rdy = 0;
uint8_t kbd_ln = 0;
uint8_t wai = 0;
uint8_t step = 0;
uint8_t irq = 0;
#if !bench
WINDOW *scr;
#endif
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t main_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_cond_t main_cond = PTHREAD_COND_INITIALIZER;
struct suxthr {
struct sux sx;
uint8_t th;
};
#if bench
double ipc;
struct timeval str[THREADS], en[THREADS];
#endif
void *run(void *args) {
struct suxthr *thr = (void *)args;
struct sux *cpu = &thr->sx;
uint8_t thread = thr->th;
uint64_t address = 0;
uint64_t tmpaddr = 0;
uint8_t prefix = 0;
uint8_t opcode = 0;
uint8_t end = 0;
uint8_t stksize;
uint64_t sum = 0;
uint64_t value = 0;
uint64_t reg = 0;
uint64_t iclk = 0;
uint64_t ins = 0;
uint64_t sign = 0;
uint8_t addrsize;
uint8_t rs;
uint8_t regsize;
uint8_t tmp;
uint8_t tmp2;
char *s = malloc(2048);
#if !bench
uint8_t lines = (6*thread)+2;
uint8_t bcd[4];
uint8_t idx = 3, iscol = 0;
int x = 0, y = 0;
uint8_t esc = 0;
#endif
uint16_t tv = 0xFF50;
#if bench
gettimeofday(&str[thread], 0);
#endif
#if debug && !bench
#if keypoll
pthread_mutex_lock(&mutex);
#endif
werase(scr);
#if keypoll
pthread_mutex_unlock(&mutex);
#endif
#endif
while (!end) {
address = 0;
if (wai) {
for (int8_t i = 56; i >= 0; i-=8) {
if (i)
addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread]-1 >> i;
else
addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread]-1 & 0xFF;
cpu->sp[thread]--;
}
addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->ps >> 8*thread;
cpu->sp[thread]--;
cpu->i[thread] = 1;
setflag(cpu->i[thread], I);
cpu->pc[thread] = (uint64_t)addr[0xFFA0]
| (uint64_t)addr[0xFFA1] << 8
| (uint64_t)addr[0xFFA2] << 16
| (uint64_t)addr[0xFFA3] << 24
| (uint64_t)addr[0xFFA4] << 32
| (uint64_t)addr[0xFFA5] << 40
| (uint64_t)addr[0xFFA6] << 48
| (uint64_t)addr[0xFFA7] << 56;
wai = 0;
kbd_rdy &= (uint8_t)~(1 << thread);
}
prefix = addr[cpu->pc[thread]];
if ((prefix & 0x03) == 0x03)
cpu->pc[thread]++;
else
prefix = 0;
opcode = addr[cpu->pc[thread]];
#if debug && !bench
if (lines > 24*(thread+1)) {
lines = (24*thread)+2;
}
#if keypoll
pthread_mutex_lock(&mutex);
#endif
mvwprintw(scr, lines, 0, "pc: $%08llx, a: $%016llx, b: $%016llx, x: $%016llx, y: $%016llx"
", sp: $%04lx, ps: $%016llx, prefix: $%02x, opcode: $%02x, inst: "
, cpu->pc[thread], cpu->a[thread], cpu->b[thread], cpu->x[thread], cpu->y[thread]
, cpu->sp[thread], cpu->ps, prefix, opcode);
#if keypoll
pthread_mutex_unlock(&mutex);
#endif
#endif
addrsize = (prefix & 0x0C) >> 2;
rs = (prefix & 0x30) >> 4;
if (rs)
regsize = (1 << rs);
else
regsize = 1;
address = cpu->pc[thread];
cpu->pc[thread]++;
iclk++;
switch (optype[opcode]) {
case IMPL:
break;
case IMM:
switch (opcode) {
case TXS:
break;
case PHB:
case PHP:
case PHA:
case PHY:
case PHX:
case PLB:
case PLP:
case PLA:
case PLY:
case PLX:
case STT:
case LSL:
case LSR:
case ROL:
case ROR:
case ASR:
case ENT:
address = cpu->pc[thread];
cpu->pc[thread]+=1;
break;
default:
address = cpu->pc[thread];
cpu->pc[thread]+=regsize;
break;
}
break;
case ZM:
case ZMX:
case ZMY:
address = addr[cpu->pc[thread]];
switch (addrsize) {
case 3:
address |= addr[cpu->pc[thread]+1] << 8;
address |= addr[cpu->pc[thread]+2] << 16;
address |= addr[cpu->pc[thread]+3] << 24;
cpu->pc[thread]+=4;
break;
case 2:
address |= addr[cpu->pc[thread]+1] << 8;
address |= addr[cpu->pc[thread]+2] << 16;
address |= addr[cpu->pc[thread]+3] << 24;
address |= (uint64_t)addr[cpu->pc[thread]+4] << 32;
address |= (uint64_t)addr[cpu->pc[thread]+5] << 40;
cpu->pc[thread]+=6;
break;
case 1:
address |= addr[cpu->pc[thread]+1] << 8;
address |= addr[cpu->pc[thread]+2] << 16;
cpu->pc[thread]+=3;
break;
case 0:
cpu->pc[thread]+=1;
break;
}
tmpaddr = address;
switch (optype[opcode]) {
case ZMX:
address += cpu->x[thread];
iclk++;
break;
case ZMY:
address += cpu->y[thread];
iclk++;
break;
}
iclk++;
break;
case IND:
case INDX:
case INDY:
address = addr[cpu->pc[thread]];
switch (addrsize) {
case 3:
address |= addr[cpu->pc[thread]+1] << 8;
address |= addr[cpu->pc[thread]+2] << 16;
address |= addr[cpu->pc[thread]+3] << 24;
cpu->pc[thread]+=4;
break;
case 2:
address |= addr[cpu->pc[thread]+1] << 8;
address |= addr[cpu->pc[thread]+2] << 16;
address |= addr[cpu->pc[thread]+3] << 24;
address |= (uint64_t)addr[cpu->pc[thread]+4] << 32;
address |= (uint64_t)addr[cpu->pc[thread]+5] << 40;
cpu->pc[thread]+=6;
break;
case 1:
address |= addr[cpu->pc[thread]+1] << 8;
address |= addr[cpu->pc[thread]+2] << 16;
cpu->pc[thread]+=3;
break;
case 0:
cpu->pc[thread]+=1;
break;
}
iclk++;
tmpaddr = address;
if (optype[opcode] == INDX) {
address += cpu->x[thread];
iclk++;
}
value = addr[address];
value |= addr[address+1] << 8;
value |= addr[address+2] << 16;
value |= addr[address+3] << 24;
value |= (uint64_t)addr[address+4] << 32;
value |= (uint64_t)addr[address+5] << 40;
value |= (uint64_t)addr[address+6] << 48;
value |= (uint64_t)addr[address+7] << 56;
iclk++;
if (optype[opcode] == INDY) {
value += cpu->y[thread];
iclk++;
}
address = value;
value = 0;
iclk++;
break;
case ABS:
address = addr[cpu->pc[thread]];
address |= addr[cpu->pc[thread]+1] << 8;
switch (addrsize) {
case 3:
address |= addr[cpu->pc[thread]+2] << 16;
address |= addr[cpu->pc[thread]+3] << 24;
address |= (uint64_t)addr[cpu->pc[thread]+4] << 32;
address |= (uint64_t)addr[cpu->pc[thread]+5] << 40;
address |= (uint64_t)addr[cpu->pc[thread]+6] << 48;
address |= (uint64_t)addr[cpu->pc[thread]+7] << 56;
cpu->pc[thread]+=8;
iclk++;
break;
case 2:
address |= addr[cpu->pc[thread]+2] << 16;
address |= addr[cpu->pc[thread]+3] << 24;
address |= (uint64_t)addr[cpu->pc[thread]+4] << 32;
address |= (uint64_t)addr[cpu->pc[thread]+5] << 40;
address |= (uint64_t)addr[cpu->pc[thread]+6] << 48;
cpu->pc[thread]+=7;
iclk++;
break;
case 1:
address |= addr[cpu->pc[thread]+2] << 16;
address |= addr[cpu->pc[thread]+3] << 24;
address |= (uint64_t)addr[cpu->pc[thread]+4] << 32;
cpu->pc[thread]+=5;
break;
case 0:
cpu->pc[thread]+=2;
break;
}
break;
}
value = addr[address];
switch (regsize) {
case 8:
value |= (uint64_t)addr[address+7] << 56;
value |= (uint64_t)addr[address+6] << 48;
value |= (uint64_t)addr[address+5] << 40;
value |= (uint64_t)addr[address+4] << 32;
case 4:
value |= addr[address+3] << 24;
value |= addr[address+2] << 16;
case 2:
value |= addr[address+1] << 8;
}
#if debug && !bench
int row, col;
#if keypoll
pthread_mutex_lock(&mutex);
#endif
getyx(scr,row, col);
char postfix[3];
char op[4];
op[0] = opname[opcode][0];
op[1] = opname[opcode][1];
op[2] = opname[opcode][2];
op[3] = '\0';
if (regsize == 1) {
postfix[0] = '\0';
postfix[1] = '\0';
postfix[2] = '\0';
} else {
postfix[0] = '.';
if (regsize == 2)
postfix[1] = 'W';
else if (regsize == 4)
postfix[1] = 'D';
else if (regsize == 8)
postfix[1] = 'Q';
postfix[2] = '\0';
}
switch (optype[opcode]) {
case IMPL:
mvwprintw(scr, lines, col, "%s \r" , opname[opcode]);
break;
case IMM:
if (regsize == 1) {
mvwprintw(scr, lines, col, "%s #$%02x \r" , op, value);
} else if (regsize == 2) {
mvwprintw(scr, lines, col, "%s%s #$%04x \r" , op, postfix, value);
} else if (regsize == 4) {
mvwprintw(scr, lines, col, "%s%s #$%08x \r" , op, postfix, value);
} else if (regsize == 8) {
mvwprintw(scr, lines, col, "%s%s #$%016llx\r" , op, postfix, value);
}
break;
case ZM:
case ZMX:
case ZMY:
if (optype[opcode] == ZMX)
tmpaddr = address - cpu->x[thread];
else if (optype[opcode] == ZMY)
tmpaddr = address - cpu->y[thread];
switch (addrsize) {
case 3:
mvwprintw(scr, lines, col, "%s%s $%08x%s \r" , op, postfix, tmpaddr, (optype[opcode] == ZM) ? "" : ((optype[opcode] == ZMX) ? ", x" : ", y"));
break;
case 2:
mvwprintw(scr, lines, col, "%s%s $%014llx%s \r" , op, postfix, tmpaddr, (optype[opcode] == ZM) ? "" : ((optype[opcode] == ZMX) ? ", x" : ", y"));
break;
case 1:
mvwprintw(scr, lines, col, "%s%s $%06x%s \r" , op, postfix, tmpaddr, (optype[opcode] == ZM) ? "" : ((optype[opcode] == ZMX) ? ", x" : ", y"));
break;
case 0:
mvwprintw(scr, lines, col, "%s%s $%02x%s \r" , op, postfix, tmpaddr, (optype[opcode] == ZM) ? "" : ((optype[opcode] == ZMX) ? ", x" : ", y"));
break;
}
break;
case IND:
case INDX:
case INDY:
switch (addrsize) {
case 3:
mvwprintw(scr, lines, col, "%s%s ($%08x%s \r" , op, postfix, tmpaddr, (optype[opcode] == IND) ? "" : ((optype[opcode] == INDX) ? ", x" : ", y"));
break;
case 2:
mvwprintw(scr, lines, col, "%s%s ($%012llx%s \r" , op, postfix, tmpaddr, (optype[opcode] == IND) ? "" : ((optype[opcode] == INDX) ? ", x" : ", y"));
break;
case 1:
mvwprintw(scr, lines, col, "%s%s ($%06x%s \r" , op, postfix, tmpaddr, (optype[opcode] == IND) ? "" : ((optype[opcode] == INDX) ? ", x" : ", y"));
break;
case 0:
mvwprintw(scr, lines, col, "%s%s ($%02x%s \r" , op, postfix, tmpaddr, (optype[opcode] == IND) ? "" : ((optype[opcode] == INDX) ? ", x" : ", y"));
break;
}
break;
case ABS:
tmpaddr = address;
switch (addrsize) {
case 3:
mvwprintw(scr, lines, col, "%s%s $%016x\r" , op, postfix, tmpaddr);
break;
case 2:
mvwprintw(scr, lines, col, "%s%s $%014llx \r" , op, postfix, tmpaddr);
break;
case 1:
mvwprintw(scr, lines, col, "%s%s $%010llx \r" , op, postfix, tmpaddr);
break;
case 0:
mvwprintw(scr, lines, col, "%s%s $%04x \r" , op, postfix, tmpaddr);
break;
}
break;
if (addrsize)
mvwprintw(scr, lines, col, "%s%s $%016llx\r" , op, postfix, value);
else
mvwprintw(scr, lines, col, "%s%s $%04x \r" , op, postfix, tmpaddr);
break;
}
mvwprintw(scr, 28, 0, "TX_ADDR: $%02X, RX_ADDR: $%02X\r", addr[TX_ADDR], addr[RX_ADDR]);
mvwprintw(scr, 29, 0, "address: $%016llx, scr_row: %02u, scr_col: %02u, scr_str: %02u, scr_end: %02u\r", address, addr[0], addr[1], addr[0x26], addr[0x27]);
mvwprintw(scr, 32, 0, "bitabl: %02x %02x %02x %02x %02x %02x %02x %02x "
"%02x %02x %02x %02x %02x %02x %02x %02x\r"
, addr[0x16], addr[0x17], addr[0x18], addr[0x19], addr[0x1A], addr[0x1B], addr[0x1C], addr[0x1D]
, addr[0x1E], addr[0x1F], addr[0x20], addr[0x21], addr[0x22], addr[0x23], addr[0x24], addr[0x25]);
mvwprintw(scr, 33, 0, "buffer:\r");
uint8_t ln = 34;
uint16_t tmpad = 0x2000;
for (uint16_t i = 0; i < 20; i+=2) {
mvwprintw(scr, ln++, 0, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x "
"%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x, i: %02x\r"
, addr[tmpad+(0x00)+(i*0x10)], addr[tmpad+(0x01)+(i*0x10)], addr[tmpad+(0x02)+(i*0x10)], addr[tmpad+(0x03)+(i*0x10)]
, addr[tmpad+(0x04)+(i*0x10)], addr[tmpad+(0x05)+(i*0x10)], addr[tmpad+(0x06)+(i*0x10)], addr[tmpad+(0x07)+(i*0x10)]
, addr[tmpad+(0x08)+(i*0x10)], addr[tmpad+(0x09)+(i*0x10)], addr[tmpad+(0x0A)+(i*0x10)], addr[tmpad+(0x0B)+(i*0x10)]
, addr[tmpad+(0x0C)+(i*0x10)], addr[tmpad+(0x0D)+(i*0x10)], addr[tmpad+(0x0E)+(i*0x10)], addr[tmpad+(0x0F)+(i*0x10)]
, addr[tmpad+(0x10)+(i*0x10)], addr[tmpad+(0x11)+(i*0x10)], addr[tmpad+(0x12)+(i*0x10)], addr[tmpad+(0x13)+(i*0x10)]
, addr[tmpad+(0x14)+(i*0x10)], addr[tmpad+(0x15)+(i*0x10)], addr[tmpad+(0x16)+(i*0x10)], addr[tmpad+(0x17)+(i*0x10)]
, addr[tmpad+(0x18)+(i*0x10)], addr[tmpad+(0x19)+(i*0x10)], addr[tmpad+(0x1A)+(i*0x10)], addr[tmpad+(0x1B)+(i*0x10)]
, addr[tmpad+(0x1C)+(i*0x10)], addr[tmpad+(0x1D)+(i*0x10)], addr[tmpad+(0x1E)+(i*0x10)], addr[tmpad+(0x1F)+(i*0x10)]
, i);
}
tmpad = 0x4000;
mvwprintw(scr, ln++, 0, "cmd_buf:\r");
for (uint16_t i = 0; i < 20; i+=2) {
mvwprintw(scr, ln++, 0, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x "
"%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x, i: %02x\r"
, addr[0x4000+(0x00)+(i*0x10)], addr[0x4000+(0x01)+(i*0x10)], addr[0x4000+(0x02)+(i*0x10)], addr[0x4000+(0x03)+(i*0x10)]
, addr[0x4000+(0x04)+(i*0x10)], addr[0x4000+(0x05)+(i*0x10)], addr[0x4000+(0x06)+(i*0x10)], addr[0x4000+(0x07)+(i*0x10)]
, addr[0x4000+(0x08)+(i*0x10)], addr[0x4000+(0x09)+(i*0x10)], addr[0x4000+(0x0A)+(i*0x10)], addr[0x4000+(0x0B)+(i*0x10)]
, addr[0x4000+(0x0C)+(i*0x10)], addr[0x4000+(0x0D)+(i*0x10)], addr[0x4000+(0x0E)+(i*0x10)], addr[0x4000+(0x0F)+(i*0x10)]
, addr[0x4000+(0x10)+(i*0x10)], addr[0x4000+(0x11)+(i*0x10)], addr[0x4000+(0x12)+(i*0x10)], addr[0x4000+(0x13)+(i*0x10)]
, addr[0x4000+(0x14)+(i*0x10)], addr[0x4000+(0x15)+(i*0x10)], addr[0x4000+(0x16)+(i*0x10)], addr[0x4000+(0x17)+(i*0x10)]
, addr[0x4000+(0x18)+(i*0x10)], addr[0x4000+(0x19)+(i*0x10)], addr[0x4000+(0x1A)+(i*0x10)], addr[0x4000+(0x1B)+(i*0x10)]
, addr[0x4000+(0x1C)+(i*0x10)], addr[0x4000+(0x1D)+(i*0x10)], addr[0x4000+(0x1E)+(i*0x10)], addr[0x4000+(0x1F)+(i*0x10)]
, i);
}
mvwprintw(scr, ln++, 0, "ptr: $%02x%02x%02x%02x%02x%02x%02x%02x\r"
, addr[0x30], addr[0x2F], addr[0x2E], addr[0x2D], addr[0x2C], addr[0x2B], addr[0x2A], addr[0x29]);
mvwprintw(scr, ln++, 0, "ptr2: $%02x%02x%02x%02x%02x%02x%02x%02x\r"
, addr[0x38], addr[0x37], addr[0x36], addr[0x35], addr[0x34], addr[0x33], addr[0x32], addr[0x31]);
mvwprintw(scr, ln++, 0, "ptr3: $%02x%02x%02x%02x%02x%02x%02x%02x\r"
, addr[0x40], addr[0x3F], addr[0x3E], addr[0x3D], addr[0x3C], addr[0x3B], addr[0x3A], addr[0x39]);
mvwprintw(scr, ln++, 0, "ptr4: $%02x%02x%02x%02x%02x%02x%02x%02x\r"
, addr[0x48], addr[0x47], addr[0x46], addr[0x45], addr[0x44], addr[0x43], addr[0x42], addr[0x41]);
mvwprintw(scr, ln++, 0, "ptr5: $%02x%02x%02x%02x%02x%02x%02x%02x\r"
, addr[0x50], addr[0x4F], addr[0x4E], addr[0x4D], addr[0x4C], addr[0x4B], addr[0x4A], addr[0x49]);
mvwprintw(scr, ln++, 0, "ptr6: $%02x%02x%02x%02x%02x%02x%02x%02x\r"
, addr[0x58], addr[0x57], addr[0x56], addr[0x55], addr[0x54], addr[0x53], addr[0x52], addr[0x51]);
wrefresh(scr);
#if keypoll
pthread_mutex_unlock(&mutex);
#endif
lines+=1;
#endif
switch(opcode) {
case CPS:
clearflags(0);
clearflags(1);
clearflags(2);
clearflags(3);
clearflags(4);
clearflags(5);
clearflags(6);
clearflags(7);
cpu->ps &= 0;
break;
case ADC:
case AAB:
case ADC_AB:
case ADC_Z:
if (opcode == AAB)
value = cpu->b[thread];
sum = cpu->a[thread]+value+cpu->c[thread];
cpu->a[thread] = sum;
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);
setflag(cpu->z[thread], Z);
setflag(cpu->n[thread], N);
setflag(cpu->v[thread], V);
setflag(cpu->c[thread], C);
setflag(cpu->i[thread], I);
break;
case PHB:
case PHP:
case PHA:
case PHY:
case PHX:
tmp = value;
if (opcode == PHB) {
reg = cpu->b[thread];
} else if (opcode == PHP) {
reg = cpu->ps;
} else if (opcode == PHA) {
reg = cpu->a[thread];
} else if (opcode == PHY) {
reg = cpu->y[thread];
} else if (opcode == PHX) {
reg = cpu->x[thread];
}
if (tmp > 7)
tmp = 7;
switch (tmp) {
case 7: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]--] = reg >> (tmp--<<3);
case 6: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]--] = reg >> (tmp--<<3);
case 5: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]--] = reg >> (tmp--<<3);
case 4: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]--] = reg >> (tmp--<<3);
case 3: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]--] = reg >> (tmp--<<3);
case 2: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]--] = reg >> (tmp--<<3);
case 1: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]--] = reg >> (tmp--<<3);
case 0: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]--] = reg & 0xFF;
}
break;
case TAY:
case TAX:
case TYX:
case TYA:
case TXA:
case TXY:
case TAB:
case TSX:
case TBA:
case TXS:
switch (opcode) {
case TAY:
cpu->y[thread] = cpu->a[thread];
break;
case TAX:
cpu->x[thread] = cpu->a[thread];
break;
case TYX:
cpu->x[thread] = cpu->y[thread];
break;
case TYA:
cpu->a[thread] = cpu->y[thread];
break;
case TXA:
cpu->a[thread] = cpu->x[thread];
break;
case TXY:
cpu->y[thread] = cpu->x[thread];
break;
case TAB:
cpu->b[thread] = cpu->a[thread];
cpu->z[thread] = (cpu->b[thread] == 0);
cpu->n[thread] = (cpu->b[thread] >> 63);
break;
case TSX:
cpu->x[thread] = cpu->sp[thread] & 0xFFFF;
cpu->x[thread] = cpu->stk_st[thread] << 16;
break;
case TBA:
cpu->a[thread] = cpu->b[thread];
break;
case TXS:
cpu->sp[thread] = cpu->x[thread];
if (prefix == 0x13 && (value == thread+1 || value > 8)) {
cpu->stk_st[thread] = value & 0xFF;
cpu->stk_st[thread] += value << 16;
cpu->pc[thread]+=2;
}
break;
}
switch (opcode) {
case TYA:
case TXA:
case TBA:
cpu->z[thread] = (cpu->a[thread] == 0);
cpu->n[thread] = (cpu->a[thread] >> 63);
break;
case TAY:
case TXY:
cpu->z[thread] = (cpu->y[thread] == 0);
cpu->n[thread] = (cpu->y[thread] >> 63);
break;
case TAX:
case TYX:
cpu->z[thread] = (cpu->x[thread] == 0);
cpu->n[thread] = (cpu->x[thread] >> 63);
break;
}
setflag(cpu->z[thread], Z);
setflag(cpu->n[thread], N);
break;
case JMP:
case JMP_Z:
case JMP_IN:
cpu->pc[thread] = address;
break;
case SBC:
case SAB:
case SBC_AB:
case SBC_Z:
if (opcode == SAB) {
value = cpu->b[thread];
}
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);
setflag(cpu->z[thread], Z);
setflag(cpu->n[thread], N);
setflag(cpu->v[thread], V);
setflag(cpu->c[thread], C);
cpu->a[thread] = sum;
break;
case PLB:
case PLP:
case PLA:
case PLY:
case PLX:
tmp = value;
if (opcode == PLB)
reg = cpu->b[thread];
else if (opcode == PLP)
reg = cpu->ps;
else if (opcode == PLA)
reg = cpu->a[thread];
else if (opcode == PLY)
reg = cpu->y[thread];
else if (opcode == PLX)
reg = cpu->x[thread];
if (tmp > 7)
tmp = 7;
tmp2 = 0;
cpu->sp[thread]++;reg = addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] & 0xFF;tmp2+=8;tmp--;
switch (tmp) {
case 6: cpu->sp[thread]++;reg += addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << tmp2;tmp2+=8;
case 5: cpu->sp[thread]++;reg += addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << tmp2;tmp2+=8;
case 4: cpu->sp[thread]++;reg += addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << tmp2;tmp2+=8;
case 3: cpu->sp[thread]++;reg += addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << tmp2;tmp2+=8;
case 2: cpu->sp[thread]++;reg += addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << tmp2;tmp2+=8;
case 1: cpu->sp[thread]++;reg += addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << tmp2;tmp2+=8;
case 0: cpu->sp[thread]++;reg += addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << tmp2;tmp2+=8;
}
if (opcode == PLB) {
cpu->b[thread] = reg;
} else if (opcode == PLP) {
cpu->ps = reg;
} else if (opcode == PLA) {
cpu->a[thread] = reg;
} else if (opcode == PLY) {
cpu->y[thread] = reg;
} else if (opcode == PLX) {
cpu->x[thread] = reg;
}
break;
case JSR_IN:
case JSR:
switch (addrsize) {
case 2:
addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] >> 40;cpu->sp[thread]--;
addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] >> 32;cpu->sp[thread]--;
case 3:
addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] >> 24;cpu->sp[thread]--;
case 1:
addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] >> 16;cpu->sp[thread]--;
addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] >> 8;cpu->sp[thread]--;
case 0:
addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] & 0xFF;cpu->sp[thread]--;
}
cpu->pc[thread] = address;
break;
case AND:
case ABA:
case AND_AB:
case AND_Z:
if (opcode == ABA) {
value = cpu->b[thread];
}
cpu->a[thread] &= value;
cpu->z[thread] = (value == 0);
cpu->n[thread] = (value >> 63);
setflag(cpu->z[thread], Z);
setflag(cpu->n[thread], N);
break;
case STT:
cpu->crt |= value;
for (uint8_t i = 0; i < 7; i++) {
if ((value >> i) & 1) {
address = (uint64_t)addr[tv+(i<<3)]
| (uint64_t)addr[tv+1+(i<<3)] << 8
| (uint64_t)addr[tv+2+(i<<3)] << 16
| (uint64_t)addr[tv+3+(i<<3)] << 24
| (uint64_t)addr[tv+4+(i<<3)] << 32
| (uint64_t)addr[tv+5+(i<<3)] << 40
| (uint64_t)addr[tv+6+(i<<3)] << 48
| (uint64_t)addr[tv+7+(i<<3)] << 56;
cpu->pc[i+1] = address;
}
}
break;
case BPO:
case BPO_Z:
if (!cpu->n[thread])
cpu->pc[thread] = address;
break;
case ORA:
case OAB:
case ORA_AB:
case ORA_Z:
if (opcode == OAB) {
value = cpu->b[thread];
}
cpu->a[thread] |= value;
cpu->z[thread] = (value == 0);
cpu->n[thread] = (value >> 63);
setflag(cpu->z[thread], Z);
setflag(cpu->n[thread], N);
break;
case SEI:
cpu->i[thread] = 1;
setflag(cpu->i[thread], I);
break;
case BNG:
case BNG_Z:
if (cpu->n[thread])
cpu->pc[thread] = address;
break;
case XOR:
case XAB:
case XOR_AB:
case XOR_Z:
if (opcode == XAB) {
value = cpu->b[thread];
}
cpu->a[thread] ^= value;
cpu->z[thread] = (value == 0);
cpu->n[thread] = (value >> 63);
setflag(cpu->z[thread], Z);
setflag(cpu->n[thread], N);
break;
case CLI:
cpu->i[thread] = 0;
setflag(cpu->i[thread], I);
break;
case BCS:
case BCS_Z:
if (cpu->c[thread])
cpu->pc[thread] = address;
break;
case LSL:
case LLB:
case LSL_AB:
case LSL_Z:
if (opcode == LLB) {
value = cpu->b[thread];
}
sum = (value < 64) ? cpu->a[thread] << value : 0;
cpu->z[thread] = (sum == 0);
cpu->n[thread] = (sum >> 63);
cpu->c[thread] = cpu->a[thread] >> 64-value;
cpu->a[thread] = sum;
setflag(cpu->z[thread], Z);
setflag(cpu->n[thread], N);
setflag(cpu->c[thread], C);
break;
case SEC:
cpu->c[thread] = 1;
setflag(cpu->c[thread], C);
break;
case STA:
case STY:
case STX:
case STB:
case STA_Z:
case STY_Z:
case STX_Z:
case STB_Z:
case STA_ZX:
case STY_ZX:
case STX_ZY:
case STB_ZX:
case STA_ZY:
case STB_ZY:
case STY_IN:
case STX_IN:
case STA_IN:
case STB_IN:
case STA_IX:
case STB_IX:
case STA_IY:
case STB_IY:
switch (opcode) {
case STB:
case STB_Z:
case STB_ZX:
case STB_ZY:
case STB_IN:
case STB_IX:
case STB_IY:
value = cpu->b[thread];
break;
case STA:
case STA_Z:
case STA_ZX:
case STA_ZY:
case STA_IN:
case STA_IX:
case STA_IY:
value = cpu->a[thread];
break;
case STY:
case STY_Z:
case STY_ZX:
case STY_IN:
value = cpu->y[thread];
break;
case STX:
case STX_Z:
case STX_ZY:
case STX_IN:
value = cpu->x[thread];
break;
}
addr[address] = value & 0xFF;
if (address == STEP_ADDR) {
step = addr[address];
}
#if IO
if (address == TX_ADDR) {
#if keypoll
pthread_mutex_lock(&mutex);
#endif
if (esc) {
switch(addr[address]) {
case 'A':
if (y > 0)
y--;
wmove(scr, y, x);
esc = 0;
break;
case 'B':
if (y < getmaxy(scr))
y++;
wmove(scr, y, x);
esc = 0;
break;
case 'C':
if (x < getmaxx(scr))
x++;
wmove(scr, y, x);
esc = 0;
break;
case 'D':
if (x > 0)
x--;
wmove(scr, y, x);
esc = 0;
break;
case 'H':
if (!bcd[2] && !bcd[3])
y = 0;
else
y = ((bcd[3]*10) + bcd[2]);
if (!bcd[0] && !bcd[1])
x = 0;
else
x = ((bcd[1]*10) + bcd[0]);
idx = 3;
wmove(scr, y, x);
bcd[0] = 0;
bcd[1] = 0;
bcd[2] = 0;
bcd[3] = 0;
esc = 0;
break;
case 'S':
wscrl(scr, -1);
esc = 0;
break;
case 'T':
wscrl(scr, 1);
esc = 0;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
bcd[idx--] = (addr[address] - '0');
break;
default:
iscol = (addr[address] == ';');
break;
}
} else {
if (addr[address] == 0xC) {
x=0,y=0;
wclear(scr);
wmove(scr, y, x);
} else if (addr[address] == 0x15) {
x=0;
wclrtoeol(scr);
wmove(scr, y, x);
} else if (addr[address] == CURSES_BACKSPACE || addr[address] == '\b') {
if (x > 0) {
x--;
wmove(scr, y, x);
}
wdelch(scr);
wrefresh(scr);
} else if (addr[address] == '\033') {
esc = 1;
} else {
wmove(scr, y, x);
waddch(scr, addr[address]);
wrefresh(scr);
if (addr[address] == '\n') {
x = 0;
y+=1;
} else {
x+=1;
}
}
}
#if keypoll
pthread_mutex_unlock(&mutex);
#endif
}
#else
#if !bench
if (address == TX_ADDR) {
if (esc) {
switch(addr[address]) {
case 'A':
if (y > 0)
y--;
esc = 0;
break;
case 'B':
if (y < getmaxy(scr))
y++;
esc = 0;
break;
case 'C':
if (x < getmaxx(scr))
x++;
esc = 0;
break;
case 'D':
if (x > 0)
x--;
esc = 0;
break;
case 'H':
if (!bcd[2] && !bcd[3])
y = 0;
else
y = ((bcd[3]*10) + bcd[2]);
if (!bcd[0] && !bcd[1])
x = 0;
else
x = ((bcd[1]*10) + bcd[0]);
mvwprintw(scr, 30, 0, "x: %i, y: %i ", x, y);
mvwprintw(scr, 31, 0, "bcd[3-2]: {%u, %u}, bcd[1-0]: {%u, %u}", bcd[3], bcd[2], bcd[1], bcd[0]);
wrefresh(scr);
idx = 3;
bcd[0] = 0;
bcd[1] = 0;
bcd[2] = 0;
bcd[3] = 0;
esc = 0;
break;
case 'S':
case 'T':
esc = 0;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
bcd[idx--] = (addr[address] - '0');
break;
default:
iscol = (addr[address] == ';');
break;
}
} else {
if (addr[address] == CURSES_BACKSPACE || addr[address] == '\b') {
if (x > 0) {
x--;
}
} else if (addr[address] == '\033') {
esc = 1;
} else {
if (addr[address] == '\n') {
x = 0;
y+=1;
} else {
x+=1;
}
}
}
}
#endif
#endif
if (regsize >= 2) {
addr[address+1] = value >> 8;
if (regsize >= 4) {
addr[address+2] = value >> 16;
addr[address+3] = value >> 24;
if (regsize >= 8) {
addr[address+4] = value >> 32;
addr[address+5] = value >> 40;
addr[address+6] = value >> 48;
addr[address+7] = value >> 56;
}
}
}
break;
case BCC:
case BCC_Z:
if (!cpu->c[thread])
cpu->pc[thread] = address;
break;
case LSR:
case LRB:
case LSR_AB:
case LSR_Z:
if (opcode == LRB) {
value = cpu->b[thread];
}
sum = (value < 64) ? cpu->a[thread] >> value : 0;
cpu->z[thread] = (sum == 0);
cpu->n[thread] = (sum >> 63);
cpu->c[thread] = cpu->a[thread] & 1;
cpu->a[thread] = sum;
setflag(cpu->z[thread], Z);
setflag(cpu->n[thread], N);
setflag(cpu->c[thread], C);
break;
case ASR:
case ARB:
case ASR_AB:
case ASR_Z:
if (opcode == ARB)
value = cpu->b[thread];
sign = cpu->a[thread] & 0x8000000000000000;
sum = (value < 64) ? (cpu->a[thread] >> value) | sign : 0;
cpu->z[thread] = (sum == 0);
cpu->n[thread] = (sum >> 63);
cpu->c[thread] = cpu->a[thread] & 1;
cpu->a[thread] = sum;
setflag(cpu->z[thread], Z);
setflag(cpu->n[thread], N);
setflag(cpu->c[thread], C);
break;
case CLC:
cpu->c[thread] = 0;
setflag(cpu->c[thread], C);
break;
case LDB:
case LDA:
case LDY:
case LDX:
case LDB_AB:
case LDA_AB:
case LDY_AB:
case LDX_AB:
case LDB_Z:
case LDA_Z:
case LDY_Z:
case LDX_Z:
case LDB_ZX:
case LDA_ZX:
case LDY_ZX:
case LDX_ZY:
case LDB_ZY:
case LDA_ZY:
case LDB_IN:
case LDA_IN:
case LDY_IN:
case LDX_IN:
case LDB_IX:
case LDA_IX:
case LDB_IY:
case LDA_IY:
if (address == CTRL_ADDR) {
kbd_rdy = 1;
pthread_mutex_lock(&main_mutex);
pthread_cond_signal(&main_cond);
pthread_mutex_unlock(&main_mutex);
#if !keypoll
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
#endif
kbd_rdy = 0;
}
value = addr[address];
switch (regsize) {
case 8:
value |= (uint64_t)addr[address+7] << 56;
value |= (uint64_t)addr[address+6] << 48;
value |= (uint64_t)addr[address+5] << 40;
value |= (uint64_t)addr[address+4] << 32;
case 4:
value |= addr[address+3] << 24;
value |= addr[address+2] << 16;
case 2:
value |= addr[address+1] << 8;
}
switch (opcode) {
case LDB:
case LDB_AB:
case LDB_Z:
case LDB_ZX:
case LDB_ZY:
case LDB_IN:
case LDB_IX:
case LDB_IY:
cpu->b[thread] = value;
break;
case LDA:
case LDA_AB:
case LDA_Z:
case LDA_ZX:
case LDA_ZY:
case LDA_IN:
case LDA_IX:
case LDA_IY:
cpu->a[thread] = value;
break;
case LDY:
case LDY_AB:
case LDY_Z:
case LDY_ZX:
case LDY_IN:
cpu->y[thread] = value;
break;
case LDX:
case LDX_AB:
case LDX_Z:
case LDX_ZY:
case LDX_IN:
cpu->x[thread] = value;
break;
}
cpu->z[thread] = (value == 0);
cpu->n[thread] = (value >> 63);
setflag(cpu->z[thread], Z);
setflag(cpu->n[thread], N);
break;
case BEQ:
case BEQ_Z:
if (cpu->z[thread])
cpu->pc[thread] = address;
break;
case ROL:
case RLB:
case ROL_AB:
case ROL_Z:
if (opcode == RLB) {
value = cpu->b[thread];
}
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;
setflag(cpu->z[thread], Z);
setflag(cpu->n[thread], N);
setflag(cpu->c[thread], C);
break;
case BNE:
case BNE_Z:
if (!cpu->z[thread])
cpu->pc[thread] = address;
break;
case ROR:
case RRB:
case ROR_AB:
case ROR_Z:
if (opcode == RRB) {
value = cpu->b[thread];
}
sum = cpu->a[thread] >> value;
sum |= (uint64_t)cpu->c[thread] << (uint64_t)64-value;
cpu->z[thread] = (sum == 0);
cpu->n[thread] = (sum >> 63);
cpu->c[thread] = cpu->a[thread] & 1;
cpu->a[thread] = sum;
setflag(cpu->z[thread], Z);
setflag(cpu->n[thread], N);
setflag(cpu->c[thread], C);
break;
case BVS:
case BVS_Z:
if (cpu->v[thread])
cpu->pc[thread] = address;
break;
case MUL:
case MAB:
case MUL_AB:
case MUL_Z:
if (opcode == MAB) {
value = cpu->b[thread];
}
sum = cpu->a[thread]*value+cpu->c[thread];
cpu->a[thread] = sum;
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)));
setflag(cpu->z[thread], Z);
setflag(cpu->n[thread], N);
setflag(cpu->v[thread], V);
setflag(cpu->c[thread], C);
break;
case BVC:
case BVC_Z:
if (!cpu->v[thread])
cpu->pc[thread] = address;
break;
case DIV:
case DAB:
case DIV_AB:
case DIV_Z:
if (opcode != DAB) {
cpu->b[thread] = cpu->a[thread] % value;
} else {
value = cpu->b[thread];
cpu->x[thread] = cpu->a[thread] % value;
}
sum = cpu->a[thread]/value;
cpu->a[thread] = sum;
cpu->z[thread] = (sum == 0);
cpu->n[thread] = (sum >> 63);
setflag(cpu->z[thread], Z);
setflag(cpu->n[thread], N);
break;
case CLV:
cpu->v[thread] = 0;
setflag(cpu->v[thread], V);
break;
case RTS:
cpu->sp[thread]++;cpu->pc[thread] = addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]];
switch (addrsize) {
case 1:
cpu->sp[thread]++;cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << 8;
cpu->sp[thread]++;cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << 16;
case 3:
cpu->sp[thread]++;cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << 24;
case 2:
cpu->sp[thread]++;cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << 32;
cpu->sp[thread]++;cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << 40;
}
break;
case CPB:
case CMP:
case CAB:
case CPY:
case CPX:
case CPY_AB:
case CPX_AB:
case CMP_AB:
case CPB_AB:
case CPY_Z:
case CPX_Z:
case CMP_Z:
case CPB_Z:
case CPY_IN:
case CPX_IN:
case CMP_IN:
case CPB_IN:
case CMP_IX:
case CPB_IX:
case CMP_IY:
case CPB_IY:
if (opcode == CAB) {
value = cpu->b[thread];
}
switch (opcode) {
case CPB:
case CPB_AB:
case CPB_Z:
case CPB_IN:
case CPB_IX:
case CPB_IY:
reg = cpu->b[thread];
break;
case CMP:
case CAB:
case CMP_AB:
case CMP_Z:
case CMP_IN:
case CMP_IX:
case CMP_IY:
reg = cpu->a[thread];
break;
case CPY:
case CPY_AB:
case CPY_Z:
case CPY_IN:
reg = cpu->y[thread];
break;
case CPX:
case CPX_AB:
case CPX_Z:
case CPX_IN:
reg = cpu->x[thread];
break;
}
sum = reg-value;
cpu->n[thread] = (sum & 0x8000000000000000);
cpu->v[thread] = ((reg^value) & 0x8000000000000000) && ((reg^sum) & 0x8000000000000000);
cpu->z[thread] = (sum == 0);
cpu->c[thread] = (reg >= value);
setflag(cpu->n[thread], N);
setflag(cpu->v[thread], V);
setflag(cpu->z[thread], Z);
setflag(cpu->c[thread], C);
break;
case ENT:
cpu->crt &= ~value;
for (uint8_t i = 0; i < 7; i++)
if ((value >> i) & 1)
cpu->pc[i+1] = cpu->pc[0]+(i+1);
break;
case RTI:
cpu->sp[thread]++;
cpu->ps = addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << 8*thread;
for (uint8_t i = 0; i < 64; i+=8) {
cpu->sp[thread]++;
if (i)
cpu->pc[thread] += addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << i;
else
cpu->pc[thread] = addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]];
}
break;
case INC:
case INB:
case INY:
case INX:
switch (opcode) {
case INC:
cpu->a[thread]+=1;
cpu->z[thread] = (cpu->a[thread] == 0);
cpu->n[thread] = (cpu->a[thread] >> 63);
break;
case INB:
cpu->b[thread]+=1;
cpu->z[thread] = (cpu->b[thread] == 0);
cpu->n[thread] = (cpu->b[thread] >> 63);
break;
case INY:
cpu->y[thread]+=1;
cpu->z[thread] = (cpu->y[thread] == 0);
cpu->n[thread] = (cpu->y[thread] >> 63);
break;
case INX:
cpu->x[thread]+=1;
cpu->z[thread] = (cpu->x[thread] == 0);
cpu->n[thread] = (cpu->x[thread] >> 63);
break;
}
setflag(cpu->z[thread], Z);
setflag(cpu->n[thread], N);
break;
case DEC:
case DEB:
case DEY:
case DEX:
switch (opcode) {
case DEC:
cpu->a[thread]-=1;
cpu->z[thread] = (cpu->a[thread] == 0);
cpu->n[thread] = (cpu->a[thread] >> 63);
break;
case DEB:
cpu->b[thread]-=1;
cpu->z[thread] = (cpu->b[thread] == 0);
cpu->n[thread] = (cpu->b[thread] >> 63);
break;
case DEY:
cpu->y[thread]-=1;
cpu->z[thread] = (cpu->y[thread] == 0);
cpu->n[thread] = (cpu->y[thread] >> 63);
break;
case DEX:
cpu->x[thread]-=1;
cpu->z[thread] = (cpu->x[thread] == 0);
cpu->n[thread] = (cpu->x[thread] >> 63);
break;
}
setflag(cpu->z[thread], Z);
setflag(cpu->n[thread], N);
break;
case JSL:
switch (addrsize) {
case 3:
addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] >> 56;cpu->sp[thread]--;
case 2:
addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] >> 48;cpu->sp[thread]--;
addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] >> 40;cpu->sp[thread]--;
case 1:
addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] >> 32;cpu->sp[thread]--;
addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] >> 24;cpu->sp[thread]--;
addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] >> 16;cpu->sp[thread]--;
case 0:
addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] >> 8;cpu->sp[thread]--;
addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] & 0xFF;cpu->sp[thread]--;
}
cpu->pc[thread] = address;
break;
case INC_AB:
case INC_Z:
addr[address]++;
cpu->z[thread] = (addr[address] == 0);
cpu->n[thread] = (addr[address] >> 7);
setflag(cpu->z[thread], Z);
setflag(cpu->n[thread], N);
break;
case NOP:
break;
case RTL:
cpu->sp[thread]++;cpu->pc[thread] = addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]];
cpu->sp[thread]++;cpu->pc[thread] += addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << 8;
switch (addrsize) {
case 1:
cpu->sp[thread]++;cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << 16;
cpu->sp[thread]++;cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << 24;
cpu->sp[thread]++;cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << 32;
case 2:
cpu->sp[thread]++;cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << 40;
cpu->sp[thread]++;cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << 48;
case 3:
cpu->sp[thread]++;cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << 56;
}
break;
case DEC_AB:
case DEC_Z:
addr[address]--;
cpu->z[thread] = (addr[address] == 0);
cpu->n[thread] = (addr[address] >> 7);
setflag(cpu->z[thread], Z);
setflag(cpu->n[thread], N);
break;
case BRK:
for (int8_t i = stksize; i >= 0; i-=8) {
if (i)
addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] >> i;
else
addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] & 0xFF;
cpu->sp[thread]--;
}
addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->ps >> thread << 3;
cpu->sp[thread]--;
cpu->i[thread] = 1;
setflag(cpu->i[thread], I);
cpu->pc[thread] = (uint64_t)addr[0xFFE0]
| (uint64_t)addr[0xFFE1] << 8
| (uint64_t)addr[0xFFE2] << 16
| (uint64_t)addr[0xFFE3] << 24
| (uint64_t)addr[0xFFE4] << 32
| (uint64_t)addr[0xFFE5] << 40
| (uint64_t)addr[0xFFE6] << 48
| (uint64_t)addr[0xFFE7] << 56;
break;
case WAI:
wai = 1;
pthread_mutex_lock(&main_mutex);
pthread_cond_signal(&main_cond);
pthread_mutex_unlock(&main_mutex);
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
break;
default:
break;
}
ins++;
if (step) {
pthread_mutex_lock(&main_mutex);
pthread_cond_signal(&main_cond);
pthread_mutex_unlock(&main_mutex);
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
}
if (!addr[CTRL_ADDR])
kbd_ln = 0;
else
kbd_ln = 1;
#if debug && !bench
#if keypoll
pthread_mutex_lock(&mutex);
#endif
mvwprintw(scr, (6*thread)+1, 0, "Instructions executed: %llu, Clock cycles: %llu\r", ins, iclk);
wrefresh(scr);
#if keypoll
pthread_mutex_unlock(&mutex);
#endif
#endif
#if bench
if (ins >= BENCH_INST) {
end = 1;
pthread_mutex_lock(&main_mutex);
threads_done++;
inst[thread] = ins;
clk[thread] = iclk;
pthread_cond_signal(&main_cond);
pthread_mutex_unlock(&main_mutex);
gettimeofday(&en[thread], 0);
}
#endif
}
free(s);
}
int main(int argc, char **argv) {
struct suxthr thr[THREADS];
char *tmp = malloc(2048);
ibcount = 0;
addr = malloc(0x04000000);
inss = 0;
int v = 0;
if (argc != 2) {
if (asmmon("stdin") == 2)
return 0;
} else {
if (asmmon(argv[1]) == 2)
return 0;
}
sprintf(tmp, "\033[2J\033[H");
fwrite(tmp, sizeof(char), strlen(tmp), stdout);
fflush(stdout);
#if !bench
if(!scr)
scr = initscr();
nodelay(stdscr, 0);
crmode();
noecho();
nl();
curs_set(1);
werase(scr);
scrollok(scr, 1);
wrefresh(scr);
start_color();
use_default_colors();
init_pair(1, COLOR_WHITE, -1);
attron(COLOR_PAIR(1) | A_BOLD);
wmove(scr, 0, 0);
#endif
for (int i = 0; i < THREADS; i++) {
thr[i].sx.sp[i] = 0xFFFF;
thr[i].sx.stk_st[i] = i+1;
if (i) {
thr[i].sx.a[i] = 0;
thr[i].sx.b[i] = 0;
thr[i].sx.x[i] = 0;
thr[i].sx.y[i] = 0;
thr[i].sx.pc[i] = (uint64_t)addr[0xFF50+(8*(i-1))]
| (uint64_t)addr[0xFF51+(8*(i-1))] << 8
| (uint64_t)addr[0xFF52+(8*(i-1))] << 16
| (uint64_t)addr[0xFF53+(8*(i-1))] << 24
| (uint64_t)addr[0xFF54+(8*(i-1))] << 32
| (uint64_t)addr[0xFF55+(8*(i-1))] << 40
| (uint64_t)addr[0xFF56+(8*(i-1))] << 48
| (uint64_t)addr[0xFF57+(8*(i-1))] << 56;
} else {
thr[i].sx.a[i] = 0;
thr[i].sx.b[i] = 0;
thr[i].sx.x[i] = 0;
thr[i].sx.y[i] = 0;
thr[i].sx.pc[i] = (uint64_t)addr[0xFFC0]
| (uint64_t)addr[0xFFC1] << 8
| (uint64_t)addr[0xFFC2] << 16
| (uint64_t)addr[0xFFC3] << 24
| (uint64_t)addr[0xFFC4] << 32
| (uint64_t)addr[0xFFC5] << 40
| (uint64_t)addr[0xFFC6] << 48
| (uint64_t)addr[0xFFC7] << 56;
}
thr[i].th = i;
}
pthread_t therads[THREADS];
int result;
for (int i = 0; i < THREADS; i++) {
inst[i] = 0;
}
for (int i = 0; i < THREADS; i++) {
result = pthread_create(&therads[i], NULL, run, &thr[i]);
assert(!result);
}
int c = 0;
uint8_t step_key = 0;
#if !bench
werase(scr);
#endif
while (threads_done < THREADS) {
#if !bench
int x, y, i = 0;
if ((step_key && step && !kbd_rdy) || !step || kbd_rdy) {
if ((c != EOF && c !=-1)) {
pthread_mutex_lock(&main_mutex);
curs_set(0);
pthread_cond_wait(&main_cond, &main_mutex);
pthread_mutex_unlock(&main_mutex);
curs_set(1);
c = 0;
step_key = 0;
addr[CTRL_ADDR] = 0;
kbd_ln = 0;
}
}
#if keypoll
pthread_mutex_lock(&mutex);
#endif
getyx(scr, y, x);
c = wgetch(scr);
if (c == 19) {
step = 1;
if (kbd_rdy)
c = wgetch(scr);
}
if (kbd_rdy) {
switch (c) {
case ERR:
addr[CTRL_ADDR] = 0;
wmove(scr, getmaxy(scr)-1, 0);
wprintw(scr, "c: %i, x: %i, y: %i, i: %i.", c, x, y, i++);
wmove(scr, y, x);
wrefresh(scr);
break;
default:
if (kbd_rdy && c < 0x100) {
addr[RX_ADDR] = (uint8_t)c;
addr[CTRL_ADDR] = 1;
#if debug && !bench
wmove(scr, getmaxy(scr)-1, 0);
wprintw(scr, "c: %i, x: %i, y: %i, i: %i.", c, x, y, i++);
wmove(scr, y, x);
wrefresh(scr);
#endif
}
if (c == '\n')
kbd_ln = 1;
#if !keypoll
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
#endif
break;
}
} else {
if ((c == 19 || c == 18) && step) {
if (c == 18)
step = 0;
else if (c == 19)
step_key = 1;
#if !keypoll
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
#endif
}
}
addr[STEP_ADDR] = step;
#if keypoll
pthread_mutex_unlock(&mutex);
#endif
#else
pthread_mutex_lock(&main_mutex);
pthread_cond_wait(&main_cond, &main_mutex);
pthread_mutex_unlock(&main_mutex);
#endif
}
#if bench
if (threads_done == THREADS) {
double tm_sec, tm_usec, tm[THREADS], ttm;
double clkspd;
double mhz;
double ips[THREADS];
double ipst;
for (int i = 0; i < THREADS; i++) {
tm_sec = (en[i].tv_sec - str[i].tv_sec);
tm_usec = (en[i].tv_usec-str[i].tv_usec);
tm[i] = (tm_sec*1000000)+(tm_usec);
ips[i] = inst[i]/tm[i];
if (i) {
inss += inst[i];
ttm += tm[i];
ipst += ips[i];
tclk += clk[i];
} else {
inss = inst[i];
ttm = tm[i];
ipst = ips[i];
tclk = clk[i];
}
clkspd = (tm[i]/1000000)*1000000/clk[i];
mhz = 1000000.0/clkspd/1000000;
sprintf(tmp, "Instructions executed for thread %i: %llu, Instructions per Second for thread %i in MIPS: %f, tm: %f\n", i, inst[i], i, ips[i], tm[i]/1000000);
fwrite(tmp, sizeof(char), strlen(tmp), stdout);
}
clkspd = (ttm/1000000)*1000000/tclk;
mhz = 1000000.0/clkspd/1000000;
sprintf(tmp, "Total Instructions executed: %llu, Total Instructions per Second in MIPS: %f, Clock cycles: %llu, Clock Speed in MHz: %f, tm: %f\n", inss, ipst, tclk, mhz, ttm/1000000);
fwrite(tmp, sizeof(char), strlen(tmp), stdout);
fflush(stdout);
free(tmp);
}
#endif
free(addr);
return 0;
}