diff options
author | mrb0nk500 <b0nk@b0nk.xyz> | 2020-05-03 15:51:57 -0400 |
---|---|---|
committer | mrb0nk500 <b0nk@b0nk.xyz> | 2020-05-03 15:51:57 -0400 |
commit | 1c622005c289ef1cd9feea277bd0ff46b19d15f0 (patch) | |
tree | b5258bd461ac2070c39e0eb437da676a10e295c3 | |
parent | ed88644ded82008577804c590bec7188ef0da011 (diff) |
Put the instruction, and I/O routines into separate
functions.
I did this to make it more readable, while still
making it fast, due to inlining it.
-rw-r--r-- | Makefile | 57 | ||||
-rw-r--r-- | asmmon.c | 2 | ||||
-rw-r--r-- | disasm.c | 136 | ||||
-rw-r--r-- | disasm.h | 187 | ||||
-rw-r--r-- | io.c | 181 | ||||
-rw-r--r-- | opcode.c | 25 | ||||
-rw-r--r-- | opcode.h | 193 | ||||
-rw-r--r-- | sux.c | 821 | ||||
-rw-r--r-- | sux.h | 554 |
9 files changed, 1168 insertions, 988 deletions
@@ -7,30 +7,53 @@ else PCC_CFLAGS= endif -CFLAGS = $(PCC_CFLAGS) $(CFLAGS_EXTRA) -OBJS = sux.o asmmon.o lexer.o +IO=1 + +ifdef BENCH +BENCH_CFLAGS=-Dbench=1 +IO= +else +BENCH_CFLAGS=-Dbench=0 +IO=1 +endif + +ifdef DEBUG +DBG_CFLAGS=-Ddebug=1 +IO= +DBG_OBJ=disasm.o +else +ifdef IO +IO=1 +endif +DBG_CFLAGS=-Ddebug=0 +DBG_OBJ= +endif + +ifdef IO +IO_CFLAGS=-DIO=1 +else +IO_CFLAGS=-DIO=0 +endif + + +OBJS = sux.o opcode.o io.o $(DBG_OBJ) asmmon.o lexer.o + +CFLAGS = $(PCC_CFLAGS) $(DBG_CFLAGS) $(IO_CFLAGS) $(BENCH_CFLAGS) $(CFLAGS_EXTRA) OBJS2 = subasm.o subeditor.o OBJ_NAME = cisc-0.2 OBJ_NAME2 = subeditor-c -all : clean clean_subeditor $(OBJ_NAME) -subeditor : clean_subeditor $(OBJS2) + +all : clean $(OBJ_NAME) + +subeditor : clean $(OBJS2) $(CC) $(OBJS2) $(CFLAGS) -lcurses -ltinfo -o $(OBJ_NAME2) cisc-0.2: $(OBJS) $(CC) $(OBJS) $(CFLAGS) -lpthread -lcurses -ltinfo -o $(OBJ_NAME) -sux.o : - $(CC) sux.c -c $(CFLAGS) -o sux.o -asmmon.o : - $(CC) asmmon.c -c $(CFLAGS) -o asmmon.o -lexer.o : - $(CC) lexer.c -c $(CFLAGS) -o lexer.o -subasm.o : - $(CC) programs/c-ports/subasm.c -c $(CFLAGS) -o subasm.o -subeditor.o : - $(CC) programs/c-ports/subeditor.c -c $(CFLAGS) -o subeditor.o + +%.o : %.c + $(CC) -c $< -o $@ $(CFLAGS) clean : - rm -f $(OBJ_NAME) $(OBJ_NAME2) $(OBJS) $(OBJS2) -clean_subeditor : - rm -f $(OBJ_NAME2) $(OBJS2) + rm -f $(OBJ_NAME) $(OBJ_NAME2) *.o install : install -D -m755 $(OBJ_NAME) $(BIN_DIR)/$(OBJ_NAME) uninstall : @@ -576,7 +576,7 @@ uint64_t assemble(struct line *line, uint8_t dbg) { int asmmon(const char *fn) { FILE *fp; - FILE *fp2; + FILE *fp2 = NULL; char *path = malloc(0x400); if (strcasecmp(fn, "stdin")) { uint16_t i = 0; diff --git a/disasm.c b/disasm.c new file mode 100644 index 0000000..c055d07 --- /dev/null +++ b/disasm.c @@ -0,0 +1,136 @@ +#include "sux.h" +#include "disasm.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]; + char postfix[3]; + char op[4]; + op[0] = opname[opcode][0]; + op[1] = opname[opcode][1]; + op[2] = opname[opcode][2]; + op[3] = '\0'; + switch(1 << (prefix >> 4)) { + case 1: postfix[0] = 0; postfix[1] = 0; postfix[2] = 0; break; + case 2: postfix[0] = '.'; postfix[1] = 'W'; postfix[2] = 0; break; + case 4: postfix[0] = '.'; postfix[1] = 'D'; postfix[2] = 0; break; + case 8: postfix[0] = '.'; postfix[1] = 'Q'; postfix[2] = 0; break; + } + switch (optype[opcode]) { + case IMPL: wprintw(scr, "%s\r" , opname[opcode]); break; + case IMM: + switch(1 << (prefix >> 4)) { + case 1: wprintw(scr, "%s #$%02X\r" , op, value); break; + case 2: wprintw(scr, "%s%s #$%04X\r" , op, postfix, value); break; + case 4: wprintw(scr, "%s%s #$%08X\r" , op, postfix, value); break; + case 8: wprintw(scr, "%s%s #$%016"PRIX64"\r" , op, postfix, value); break; + } + break; + case ZM: + case ZMX: + case ZMY: + switch (optype[opcode]) { + case ZMX: tmpaddr = address - cpu->x[thread]; break; + case ZMY: tmpaddr = address - cpu->y[thread]; break; + } + switch ((prefix & 0x0C) >> 2) { + case 3: wprintw(scr, "%s%s $%08X%s\r" , op, postfix, tmpaddr, (optype[opcode] == ZM) ? "" : ((optype[opcode] == ZMX) ? ", x" : ", y")); break; + case 2: wprintw(scr, "%s%s $%014"PRIX64"%s\r" , op, postfix, tmpaddr, (optype[opcode] == ZM) ? "" : ((optype[opcode] == ZMX) ? ", x" : ", y")); break; + case 1: wprintw(scr, "%s%s $%06X%s\r" , op, postfix, tmpaddr, (optype[opcode] == ZM) ? "" : ((optype[opcode] == ZMX) ? ", x" : ", y")); break; + case 0: wprintw(scr, "%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 ((prefix & 0x0C) >> 2) { + case 3: wprintw(scr, "%s%s ($%08X%s\r" , op, postfix, tmpaddr, (optype[opcode] == IND) ? ")" : ((optype[opcode] == INDX) ? ", x)" : "), y")); break; + case 2: wprintw(scr, "%s%s ($%012"PRIX64"%s\r" , op, postfix, tmpaddr, (optype[opcode] == IND) ? ")" : ((optype[opcode] == INDX) ? ", x)" : "), y")); break; + case 1: wprintw(scr, "%s%s ($%06X%s\r" , op, postfix, tmpaddr, (optype[opcode] == IND) ? ")" : ((optype[opcode] == INDX) ? ", x)" : "), y")); break; + case 0: wprintw(scr, "%s%s ($%02X%s\r" , op, postfix, tmpaddr, (optype[opcode] == IND) ? ")" : ((optype[opcode] == INDX) ? ", x)" : "), y")); break; + } + break; + case ABS: + tmpaddr = address; + switch ((prefix & 0x0C) >> 2) { + case 3: wprintw(scr, "%s%s $%016"PRIX64"\r" , op, postfix, tmpaddr); break; + case 2: wprintw(scr, "%s%s $%014"PRIX64"\r" , op, postfix, tmpaddr); break; + case 1: wprintw(scr, "%s%s $%010"PRIX64"\r" , op, postfix, tmpaddr); break; + case 0: wprintw(scr, "%s%s $%04" PRIX64"\r" , op, postfix, tmpaddr); break; + } + break; + } + + if (address == TX_ADDR || address == RX_ADDR) { + wmove(scr, 27, 0); + wprintw(scr, "TX_ADDR: $%02X, RX_ADDR: $%02X", addr[TX_ADDR], addr[RX_ADDR]); + } + if (subdbg) { + uint8_t ln = 33; + uint16_t line_idx = 0; + uint16_t tmpad = 0x2000; + int row, col; + uint8_t iscursor = 0; + uint64_t ptr; + uint8_t adr; + wmove(scr, 30, 0); + adr = 0x1F; + ptr = (uint64_t)addr[adr+0] << 0x00 | (uint64_t)addr[adr+1] << 0x08 | (uint64_t)addr[adr+2] << 0x10 | (uint64_t)addr[adr+3] << 0x18 | + (uint64_t)addr[adr+4] << 0x20 | (uint64_t)addr[adr+5] << 0x28 | (uint64_t)addr[adr+6] << 0x30 | (uint64_t)addr[adr+7] << 0x38; + wprintw(scr, "ptr1: $%04"PRIX64, ptr); + adr = 0x27; + ptr = (uint64_t)addr[adr+0] << 0x00 | (uint64_t)addr[adr+1] << 0x08 | (uint64_t)addr[adr+2] << 0x10 | (uint64_t)addr[adr+3] << 0x18 | + (uint64_t)addr[adr+4] << 0x20 | (uint64_t)addr[adr+5] << 0x28 | (uint64_t)addr[adr+6] << 0x30 | (uint64_t)addr[adr+7] << 0x38; + wprintw(scr, ", ptr2: $%04"PRIX64, ptr); + adr = 0x2F; + ptr = (uint64_t)addr[adr+0] << 0x00 | (uint64_t)addr[adr+1] << 0x08 | (uint64_t)addr[adr+2] << 0x10 | (uint64_t)addr[adr+3] << 0x18 | + (uint64_t)addr[adr+4] << 0x20 | (uint64_t)addr[adr+5] << 0x28 | (uint64_t)addr[adr+6] << 0x30 | (uint64_t)addr[adr+7] << 0x38; + wprintw(scr, ", ptr3: $%04"PRIX64, ptr); + if (address == CTRL_ADDR || addr[STEP_ADDR]) { + mvwprintw(scr, 29, 0, "address: $%04"PRIX64", scr_row: %02u, scr_col: %02u, scr_str: %02u, scr_end: %02u\r", address, addr[0], addr[1], addr[0x1C], addr[0x1D]); + mvwprintw(scr, 32, 0, "bitabl: %02X%02X%02X%02X%02X%02X%02X%02X" + "%02X%02X%02X%02X%02X%02X%02X%02X" + , addr[0x1000], addr[0x1001], addr[0x1002], addr[0x1003], addr[0x1004], addr[0x1005], addr[0x1006], addr[0x1007] + , addr[0x1008], addr[0x1009], addr[0x100A], addr[0x100B], addr[0x100C], addr[0x100D], addr[0x100E], addr[0x100F]); + mvwprintw(scr, ln++, 0, "buffer:\r"); + wmove(scr, ln++, 0); + for (uint8_t i = 0; i < 10; i++) { + line_idx = (i << 6) + (i << 4); + for (uint8_t j = 0; j < 0x50; j++) { + wprintw(scr, "%02X", addr[tmpad+j+line_idx]); + if ((addr[0]+addr[0x1C]) == i && addr[1] == j) { + iscursor=1; + getyx(scr,row, col); + wmove(scr, ln++, 0); + wclrtoeol(scr); + wmove(scr, row+1, col-2); + wprintw(scr, "/\\\r"); + wmove(scr, row, col); + } + } + wprintw(scr, ", i: %02X", i); + if (!iscursor) { + wmove(scr, ln, 0); + wclrtoeol(scr); + } + iscursor = 0; + wmove(scr, ln++, 0); + } + } + /*if (address == 0x4000 || tmpaddr == 0x4000 || addr[STEP_ADDR]) { + ln = 46; + tmpad = 0x4000; + line_idx = 0; + mvwprintw(scr, ln++, 0, "cmd_buf:"); + for (uint8_t i = 0; i < 5; i++) { + wmove(scr, ln++, 0); + line_idx = (i << 4)+(i << 6); + for (uint8_t j = 0; j < 0x50; j++) { + wprintw(scr, "%02X", addr[tmpad+j+line_idx]); + } + wprintw(scr, ", i: %02X", i); + } + }*/ + } +} diff --git a/disasm.h b/disasm.h new file mode 100644 index 0000000..8fe2b4c --- /dev/null +++ b/disasm.h @@ -0,0 +1,187 @@ +static const char *opname[0x100] = { + [0x00] = "CPS", + [0x01] = "ADC #", + [0x02] = "AAB", + [0x04] = "ADC a", + [0x05] = "LDA ind", + [0x06] = "ADC zm", + [0x08] = "PHP #", + [0x09] = "CPB #", + [0x0A] = "PHB #", + [0x0C] = "DEC a", + [0x0D] = "DEC zm", + [0x0E] = "JMP zm", + [0x10] = "JMP a", + [0x11] = "SBC #", + [0x12] = "SAB", + [0x14] = "SBC a", + [0x15] = "STA ind", + [0x16] = "SBC zm", + [0x18] = "ENT #", + [0x19] = "CPY #", + [0x1A] = "PLB #", + [0x1C] = "INC a", + [0x1D] = "INC zm", + [0x1E] = "JSR zm", + [0x20] = "JSL a", + [0x21] = "AND #", + [0x22] = "ABA", + [0x24] = "AND a", + [0x25] = "CMP ind", + [0x26] = "AND zm", + [0x28] = "PLP #", + [0x29] = "CPX #", + [0x2A] = "PHY #", + [0x2C] = "CPB a", + [0x2D] = "CPB zm", + [0x2E] = "BPO zm", + [0x30] = "BPO a", + [0x31] = "ORA #", + [0x32] = "OAB", + [0x34] = "ORA a", + [0x35] = "LDB ind", + [0x36] = "ORA zm", + [0x38] = "STT #", + [0x39] = "LDA zmy", + [0x3A] = "PLY #", + [0x3C] = "CPX a", + [0x3D] = "CPY zm", + [0x3E] = "BNG zm", + [0x40] = "BNG a", + [0x41] = "XOR #", + [0x42] = "XAB", + [0x44] = "XOR a", + [0x45] = "STB ind", + [0x46] = "XOR zm", + [0x48] = "PHA #", + [0x49] = "STA zmy", + [0x4A] = "PHX #", + [0x4C] = "CPY a", + [0x4D] = "CPX zm", + [0x4E] = "BCS zm", + [0x50] = "BCS a", + [0x51] = "LSL #", + [0x52] = "LLB", + [0x54] = "LSL a", + [0x55] = "CPB ind", + [0x56] = "LSL zm", + [0x58] = "CLC", + [0x59] = "LDB zmy", + [0x5A] = "PLX #", + [0x5C] = "LDA iny", + [0x5D] = "LDA inx", + [0x5E] = "BCC zm", + [0x60] = "BCC a", + [0x61] = "LSR #", + [0x62] = "LRB", + [0x64] = "LSR a", + [0x65] = "LDY ind", + [0x66] = "LSR zm", + [0x68] = "PLA #", + [0x69] = "STB zmy", + [0x6A] = "TAB", + [0x6C] = "STA iny", + [0x6D] = "STA inx", + [0x6E] = "BEQ zm", + [0x70] = "BEQ a", + [0x71] = "ROL #", + [0x72] = "RLB", + [0x74] = "ROL a", + [0x75] = "STY ind", + [0x76] = "ROL zm", + [0x78] = "SEC", + [0x79] = "LDA zmx", + [0x7A] = "TBA", + [0x7C] = "CMP iny", + [0x7D] = "CMP inx", + [0x7E] = "BNE zm", + [0x80] = "BNE a", + [0x81] = "ROR #", + [0x82] = "RRB", + [0x84] = "ROR a", + [0x85] = "CPY ind", + [0x86] = "ROR zm", + [0x88] = "DEY", + [0x89] = "STA zmx", + [0x8A] = "TAY", + [0x8C] = "LDB iny", + [0x8D] = "LDB inx", + [0x8E] = "BVS zm", + [0x90] = "BVS a", + [0x91] = "MUL #", + [0x92] = "MAB", + [0x94] = "MUL a", + [0x95] = "LDX ind", + [0x96] = "MUL zm", + [0x98] = "CLI", + [0x99] = "LDB zmx", + [0x9A] = "TYA", + [0x9C] = "STB iny", + [0x9D] = "STB inx", + [0x9E] = "BVC zm", + [0xA0] = "BVC a", + [0xA1] = "DIV #", + [0xA2] = "DAB", + [0xA4] = "DIV a", + [0xA5] = "STX ind", + [0xA6] = "DIV zm", + [0xA8] = "INY", + [0xA9] = "STB zmx", + [0xAA] = "TAX", + [0xAC] = "CPB iny", + [0xAD] = "CPB inx", + [0xAE] = "RTS", + [0xB0] = "RTL", + [0xB1] = "CMP #", + [0xB2] = "CAB", + [0xB4] = "CMP a", + [0xB5] = "CPX ind", + [0xB6] = "CMP zm", + [0xB8] = "SEI", + [0xB9] = "LDX #", + [0xBA] = "TXA", + [0xBC] = "LDX a", + [0xBD] = "LDX zm", + [0xBE] = "JSR ind", + [0xC0] = "RTI", + [0xC1] = "LDA #", + [0xC4] = "LDA a", + [0xC5] = "DEX", + [0xC6] = "LDA zm", + [0xC8] = "CLV", + [0xC9] = "LDX zmy", + [0xCA] = "TYX", + [0xCC] = "STA a", + [0xCD] = "STA zm", + [0xCE] = "JMP ind", + [0xD0] = "TSX", + [0xD1] = "LDB #", + [0xD4] = "LDB a", + [0xD5] = "INX", + [0xD6] = "LDB zm", + [0xD8] = "WAI", + [0xD9] = "STX zmy", + [0xDA] = "TXY", + [0xDC] = "STB a", + [0xDD] = "STB zm", + [0xE0] = "TXS #", + [0xE1] = "LDY #", + [0xE4] = "LDY a", + [0xE5] = "DEC A", + [0xE6] = "LDY zm", + [0xE8] = "BRK", + [0xE9] = "LDY zmx", + [0xEA] = "NOP", + [0xEC] = "STY a", + [0xED] = "STY zm", + [0xEE] = "DEB", + [0xF1] = "ASR #", + [0xF2] = "ARB", + [0xF4] = "ASR a", + [0xF5] = "INC A", + [0xF6] = "ASR zm", + [0xF9] = "STY zmx", + [0xFC] = "STX a", + [0xFD] = "STX zm", + [0xFE] = "INB" +}; @@ -0,0 +1,181 @@ +#include "sux.h" + +uint8_t iscol; +uint8_t idx = 3; +uint8_t bcd[4]; + +void io(uint64_t address, uint8_t *esc) { + int x, y; + uint16_t scr_col = 0; + switch (address) { + case 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; + break; + case TX_ADDR: + #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') { + wclrtoeol(scr); + } + #endif + switch (addr[TX_ADDR]) { + case 'A': + if (y > 0) + y--; + #if !debug + wmove(scr, y, x); + #endif + *esc = 0; + break; + case 'B': + if (y < getmaxy(scr)) + y++; + #if !debug + wmove(scr, y, x); + #endif + *esc = 0; + break; + case 'C': + if (x < getmaxx(scr)) + x++; + #if !debug + wmove(scr, y, x); + #endif + *esc = 0; + break; + case 'D': + if (x > 0) + x--; + #if !debug + wmove(scr, y, x); + #endif + *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]); + } + #if !debug + wmove(scr, y, x); + #else + 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]);*/ + #endif + idx = 3; + bcd[0] = 0; + bcd[1] = 0; + bcd[2] = 0; + bcd[3] = 0; + *esc = 0; + break; + case 'S': + #if !debug + wscrl(scr, -1); + #else + #endif + *esc = 0; + break; + case 'T': + #if !debug + wscrl(scr, 1); + #else + #endif + *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 { + switch (addr[TX_ADDR]) { + case 0xC: + x=0,y=0; + #if !debug + wclear(scr); + wmove(scr, y, x); + #endif + break; + case CURSES_BACKSPACE: + case '\b': + if (x > 0) { + x--; + #if !debug + wmove(scr, y, x); + #endif + } + #if !debug + wdelch(scr); + #else + if (!subdbg) { + scr_col++; + wmove(scr, 28, scr_col--); + wdelch(scr); + wmove(scr, 28, scr_col); + wdelch(scr); + } + #endif + break; + case '\033': + *esc = 1; + break; + case '\n': + x = 0; + y+=1; + #if !debug + wmove(scr, y, x); + #endif + break; + default: + #if !debug + /*wmove(scr, y, x);*/ + waddch(scr, addr[address]); + #else + if (!subdbg && scr_col < 160) { + if (addr[address] != ' ') { + wprintw(scr, "%02X", addr[address]); + } else { + wprintw(scr, " "); + } + } + #endif + x+=1; + break; + } + } + break; + } +} diff --git a/opcode.c b/opcode.c new file mode 100644 index 0000000..423da28 --- /dev/null +++ b/opcode.c @@ -0,0 +1,25 @@ +#include "sux.h" + +static inline uint64_t get_addr(struct sux *cpu, uint64_t *tmpaddr, uint8_t opcode, uint8_t prefix, uint8_t thread); +extern inline void adc(struct sux *cpu, uint64_t value, uint8_t thread); +extern inline void sbc(struct sux *cpu, uint64_t value, uint8_t thread); +extern inline void transfer(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t prefix, uint8_t thread); +extern inline void push(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread); +extern inline void pull(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread); +extern inline void and(struct sux *cpu, uint64_t value, uint8_t thread); +extern inline void or(struct sux *cpu, uint64_t value, uint8_t thread); +extern inline void xor(struct sux *cpu, uint64_t value, uint8_t thread); +extern inline void lsl(struct sux *cpu, uint64_t value, uint8_t thread); +extern inline void lsr(struct sux *cpu, uint64_t value, uint8_t thread); +extern inline void asr(struct sux *cpu, uint64_t value, uint8_t thread); +extern inline void rol(struct sux *cpu, uint64_t value, uint8_t thread); +extern inline void ror(struct sux *cpu, uint64_t value, uint8_t thread); +extern inline void mul(struct sux *cpu, uint64_t value, uint8_t thread); +extern inline void divd(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread); +extern inline void cmp(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread); +extern inline void incr(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread); +extern inline void decr(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread); +extern inline void incm(struct sux *cpu, uint64_t address, uint8_t thread); +extern inline void decm(struct sux *cpu, uint64_t address, uint8_t thread); +extern inline void load(struct sux *cpu, uint64_t address, uint8_t *esc, uint8_t opcode, uint8_t prefix, uint8_t thread); +extern inline void store(struct sux *cpu, uint64_t address, uint8_t *esc, uint8_t opcode, uint8_t prefix, uint8_t thread); @@ -4,9 +4,6 @@ #include <stdlib.h> #include <unistd.h> -#define bench 0 -#define debug 0 -#define IO 1 #define getclk 0 #define keypoll 0 @@ -405,194 +402,4 @@ static const uint8_t optype[0x100] = { [0xFE] = IMPL }; -#if debug -static const char *opname[0x100] = { - [0x00] = "CPS", - [0x01] = "ADC #", - [0x02] = "AAB", - [0x04] = "ADC a", - [0x05] = "LDA ind", - [0x06] = "ADC zm", - [0x08] = "PHP #", - [0x09] = "CPB #", - [0x0A] = "PHB #", - [0x0C] = "DEC a", - [0x0D] = "DEC zm", - [0x0E] = "JMP zm", - [0x10] = "JMP a", - [0x11] = "SBC #", - [0x12] = "SAB", - [0x14] = "SBC a", - [0x15] = "STA ind", - [0x16] = "SBC zm", - [0x18] = "ENT #", - [0x19] = "CPY #", - [0x1A] = "PLB #", - [0x1C] = "INC a", - [0x1D] = "INC zm", - [0x1E] = "JSR zm", - [0x20] = "JSL a", - [0x21] = "AND #", - [0x22] = "ABA", - [0x24] = "AND a", - [0x25] = "CMP ind", - [0x26] = "AND zm", - [0x28] = "PLP #", - [0x29] = "CPX #", - [0x2A] = "PHY #", - [0x2C] = "CPB a", - [0x2D] = "CPB zm", - [0x2E] = "BPO zm", - [0x30] = "BPO a", - [0x31] = "ORA #", - [0x32] = "OAB", - [0x34] = "ORA a", - [0x35] = "LDB ind", - [0x36] = "ORA zm", - [0x38] = "STT #", - [0x39] = "LDA zmy", - [0x3A] = "PLY #", - [0x3C] = "CPX a", - [0x3D] = "CPY zm", - [0x3E] = "BNG zm", - [0x40] = "BNG a", - [0x41] = "XOR #", - [0x42] = "XAB", - [0x44] = "XOR a", - [0x45] = "STB ind", - [0x46] = "XOR zm", - [0x48] = "PHA #", - [0x49] = "STA zmy", - [0x4A] = "PHX #", - [0x4C] = "CPY a", - [0x4D] = "CPX zm", - [0x4E] = "BCS zm", - [0x50] = "BCS a", - [0x51] = "LSL #", - [0x52] = "LLB", - [0x54] = "LSL a", - [0x55] = "CPB ind", - [0x56] = "LSL zm", - [0x58] = "CLC", - [0x59] = "LDB zmy", - [0x5A] = "PLX #", - [0x5C] = "LDA iny", - [0x5D] = "LDA inx", - [0x5E] = "BCC zm", - [0x60] = "BCC a", - [0x61] = "LSR #", - [0x62] = "LRB", - [0x64] = "LSR a", - [0x65] = "LDY ind", - [0x66] = "LSR zm", - [0x68] = "PLA #", - [0x69] = "STB zmy", - [0x6A] = "TAB", - [0x6C] = "STA iny", - [0x6D] = "STA inx", - [0x6E] = "BEQ zm", - [0x70] = "BEQ a", - [0x71] = "ROL #", - [0x72] = "RLB", - [0x74] = "ROL a", - [0x75] = "STY ind", - [0x76] = "ROL zm", - [0x78] = "SEC", - [0x79] = "LDA zmx", - [0x7A] = "TBA", - [0x7C] = "CMP iny", - [0x7D] = "CMP inx", - [0x7E] = "BNE zm", - [0x80] = "BNE a", - [0x81] = "ROR #", - [0x82] = "RRB", - [0x84] = "ROR a", - [0x85] = "CPY ind", - [0x86] = "ROR zm", - [0x88] = "DEY", - [0x89] = "STA zmx", - [0x8A] = "TAY", - [0x8C] = "LDB iny", - [0x8D] = "LDB inx", - [0x8E] = "BVS zm", - [0x90] = "BVS a", - [0x91] = "MUL #", - [0x92] = "MAB", - [0x94] = "MUL a", - [0x95] = "LDX ind", - [0x96] = "MUL zm", - [0x98] = "CLI", - [0x99] = "LDB zmx", - [0x9A] = "TYA", - [0x9C] = "STB iny", - [0x9D] = "STB inx", - [0x9E] = "BVC zm", - [0xA0] = "BVC a", - [0xA1] = "DIV #", - [0xA2] = "DAB", - [0xA4] = "DIV a", - [0xA5] = "STX ind", - [0xA6] = "DIV zm", - [0xA8] = "INY", - [0xA9] = "STB zmx", - [0xAA] = "TAX", - [0xAC] = "CPB iny", - [0xAD] = "CPB inx", - [0xAE] = "RTS", - [0xB0] = "RTL", - [0xB1] = "CMP #", - [0xB2] = "CAB", - [0xB4] = "CMP a", - [0xB5] = "CPX ind", - [0xB6] = "CMP zm", - [0xB8] = "SEI", - [0xB9] = "LDX #", - [0xBA] = "TXA", - [0xBC] = "LDX a", - [0xBD] = "LDX zm", - [0xBE] = "JSR ind", - [0xC0] = "RTI", - [0xC1] = "LDA #", - [0xC4] = "LDA a", - [0xC5] = "DEX", - [0xC6] = "LDA zm", - [0xC8] = "CLV", - [0xC9] = "LDX zmy", - [0xCA] = "TYX", - [0xCC] = "STA a", - [0xCD] = "STA zm", - [0xCE] = "JMP ind", - [0xD0] = "TSX", - [0xD1] = "LDB #", - [0xD4] = "LDB a", - [0xD5] = "INX", - [0xD6] = "LDB zm", - [0xD8] = "WAI", - [0xD9] = "STX zmy", - [0xDA] = "TXY", - [0xDC] = "STB a", - [0xDD] = "STB zm", - [0xE0] = "TXS #", - [0xE1] = "LDY #", - [0xE4] = "LDY a", - [0xE5] = "DEC A", - [0xE6] = "LDY zm", - [0xE8] = "BRK", - [0xE9] = "LDY zmx", - [0xEA] = "NOP", - [0xEC] = "STY a", - [0xED] = "STY zm", - [0xEE] = "DEB", - [0xF1] = "ASR #", - [0xF2] = "ARB", - [0xF4] = "ASR a", - [0xF5] = "INC A", - [0xF6] = "ASR zm", - [0xF9] = "STY zmx", - [0xFC] = "STX a", - [0xFD] = "STX zm", - [0xFE] = "INB" -}; -#endif - extern int asmmon(); @@ -1,25 +1,7 @@ -#include "opcode.h" +#include "sux.h" #include <assert.h> #include <ctype.h> #include <string.h> -#include <pthread.h> - -#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 getflag(bit) (cpu->ps & (bit << (thread << 3))) #if getclk uint64_t clk[THREADS]; /* Per Thread Clock cycles. */ @@ -32,28 +14,18 @@ const uint16_t tv = 0xFF50; /* Starting address of the Thread Vectors. */ uint64_t inst[THREADS]; #endif -#if debug -uint8_t subdbg = 0; -#endif - #if bench uint64_t inss; #endif -uint8_t threads_done = 0; -uint8_t kbd_rdy = 0; -uint8_t step = 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; +uint8_t threads_done = 0; +uint8_t step = 0; + struct suxthr { struct sux sx; uint8_t th; @@ -71,31 +43,18 @@ void *run(void *args) { uint64_t address = 0; uint8_t prefix = 0; uint8_t opcode = 0; - uint64_t sum = 0; + uint8_t esc = 0; uint64_t value = 0; - uint64_t reg = 0; #if getclk uint64_t iclk = 0; #endif #if !IO uint64_t ins = 0; #endif - uint8_t sign = 0; - uint8_t tmp; - uint8_t tmp2; #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 -#if bench - gettimeofday(&str[thread], 0); #endif #if debug && !bench - uint64_t tmpaddr = 0; - uint16_t scr_col = 0; if (!subdbg) { addr[STEP_ADDR] = 1; step = 1; @@ -108,6 +67,10 @@ void *run(void *args) { pthread_mutex_unlock(&mutex); #endif #endif + uint64_t tmpaddr = 0; +#if bench + gettimeofday(&str[thread], 0); +#endif for (;;) { address = 0; prefix = addr[cpu->pc[thread]]; @@ -151,141 +114,7 @@ void *run(void *args) { #if getclk ++iclk; #endif - 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]; - break; - default: - address = cpu->pc[thread]; - cpu->pc[thread]+=(1 << (prefix >> 4)); - break; - } - break; - case ZM: - case ZMX: - case ZMY: - case IND: - case INDX: - case INDY: - tmp = 0; - address = addr[cpu->pc[thread]]; - /* Unroll Loop by implementing Duff's Device. */ - switch ((prefix & 0x0C) >> 2) { - case 2: - address |= (uint64_t)addr[cpu->pc[thread]+5] << 40;++tmp; - address |= (uint64_t)addr[cpu->pc[thread]+4] << 32;++tmp; - case 3: - address |= (uint64_t)addr[cpu->pc[thread]+3] << 24;++tmp; - case 1: - address |= (uint64_t)addr[cpu->pc[thread]+2] << 16;++tmp; - address |= (uint64_t)addr[cpu->pc[thread]+1] << 8;++tmp; - case 0: - ++tmp; - } - cpu->pc[thread]+=tmp; - #if debug && !bench - tmpaddr = address; - #endif - #if getclk - iclk++; - #endif - reg = 0; - switch (optype[opcode]) { - case ZMX: - address += cpu->x[thread]; - #if getclk - iclk++; - #endif - break; - case ZMY: - address += cpu->y[thread]; - #if getclk - iclk++; - #endif - break; - case INDX: - address += cpu->x[thread]; - #if getclk - iclk++; - #endif - /* Falls Through. */ - case INDY: - /* Did we fall through? */ - if (optype[opcode] == INDX) { - reg = 0; /* Yes, so set reg back to zero. */ - } else { - reg = cpu->y[thread]; /* No, so set reg to Y. */ - #if getclk - iclk++; - #endif - } - /* Falls Through. */ - case IND: - value = (uint64_t)addr[address]; - value += (uint64_t)addr[address+1] << 8; - value += (uint64_t)addr[address+2] << 16; - value += (uint64_t)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; - #if getclk - iclk++; - #endif - value += reg; - address = value; - value = 0; - reg = 0; - break; - } - break; - case ABS: - tmp = 0; - address = addr[cpu->pc[thread]];++tmp; - /* Unroll Loop by implementing Duff's Device. */ - switch ((prefix & 0x0C) >> 2) { - case 3: - address |= (uint64_t)addr[cpu->pc[thread]+7] << 56;++tmp; - case 2: - address |= (uint64_t)addr[cpu->pc[thread]+6] << 48;++tmp; - address |= (uint64_t)addr[cpu->pc[thread]+5] << 40;++tmp; - #if getclk - iclk++; - #endif - case 1: - address |= (uint64_t)addr[cpu->pc[thread]+4] << 32;++tmp; - address |= (uint64_t)addr[cpu->pc[thread]+3] << 24;++tmp; - address |= (uint64_t)addr[cpu->pc[thread]+2] << 16;++tmp; - case 0: - address |= (uint64_t)addr[cpu->pc[thread]+1] << 8;++tmp; - } - cpu->pc[thread]+=tmp; - break; - - } + address = get_addr(cpu, &tmpaddr, opcode, prefix, thread); value = addr[address]; /* Unroll Loop by implementing Duff's Device. */ switch (1 << (prefix >> 4)) { @@ -304,138 +133,15 @@ void *run(void *args) { #if keypoll pthread_mutex_lock(&mutex); #endif - char postfix[3]; - char op[4]; - op[0] = opname[opcode][0]; - op[1] = opname[opcode][1]; - op[2] = opname[opcode][2]; - op[3] = '\0'; - switch(1 << (prefix >> 4)) { - case 1: postfix[0] = 0; postfix[1] = 0; postfix[2] = 0; break; - case 2: postfix[0] = '.'; postfix[1] = 'W'; postfix[2] = 0; break; - case 4: postfix[0] = '.'; postfix[1] = 'D'; postfix[2] = 0; break; - case 8: postfix[0] = '.'; postfix[1] = 'Q'; postfix[2] = 0; break; - } - switch (optype[opcode]) { - case IMPL: wprintw(scr, "%s\r" , opname[opcode]); break; - case IMM: - switch(1 << (prefix >> 4)) { - case 1: wprintw(scr, "%s #$%02X\r" , op, value); break; - case 2: wprintw(scr, "%s%s #$%04X\r" , op, postfix, value); break; - case 4: wprintw(scr, "%s%s #$%08X\r" , op, postfix, value); break; - case 8: wprintw(scr, "%s%s #$%016"PRIX64"\r" , op, postfix, value); break; - } - break; - case ZM: - case ZMX: - case ZMY: - switch (optype[opcode]) { - case ZMX: tmpaddr = address - cpu->x[thread]; break; - case ZMY: tmpaddr = address - cpu->y[thread]; break; - } - switch ((prefix & 0x0C) >> 2) { - case 3: wprintw(scr, "%s%s $%08X%s\r" , op, postfix, tmpaddr, (optype[opcode] == ZM) ? "" : ((optype[opcode] == ZMX) ? ", x" : ", y")); break; - case 2: wprintw(scr, "%s%s $%014"PRIX64"%s\r" , op, postfix, tmpaddr, (optype[opcode] == ZM) ? "" : ((optype[opcode] == ZMX) ? ", x" : ", y")); break; - case 1: wprintw(scr, "%s%s $%06X%s\r" , op, postfix, tmpaddr, (optype[opcode] == ZM) ? "" : ((optype[opcode] == ZMX) ? ", x" : ", y")); break; - case 0: wprintw(scr, "%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 ((prefix & 0x0C) >> 2) { - case 3: wprintw(scr, "%s%s ($%08X%s\r" , op, postfix, tmpaddr, (optype[opcode] == IND) ? ")" : ((optype[opcode] == INDX) ? ", x)" : "), y")); break; - case 2: wprintw(scr, "%s%s ($%012"PRIX64"%s\r" , op, postfix, tmpaddr, (optype[opcode] == IND) ? ")" : ((optype[opcode] == INDX) ? ", x)" : "), y")); break; - case 1: wprintw(scr, "%s%s ($%06X%s\r" , op, postfix, tmpaddr, (optype[opcode] == IND) ? ")" : ((optype[opcode] == INDX) ? ", x)" : "), y")); break; - case 0: wprintw(scr, "%s%s ($%02X%s\r" , op, postfix, tmpaddr, (optype[opcode] == IND) ? ")" : ((optype[opcode] == INDX) ? ", x)" : "), y")); break; - } - break; - case ABS: - tmpaddr = address; - switch ((prefix & 0x0C) >> 2) { - case 3: wprintw(scr, "%s%s $%016"PRIX64"\r" , op, postfix, tmpaddr); break; - case 2: wprintw(scr, "%s%s $%014"PRIX64"\r" , op, postfix, tmpaddr); break; - case 1: wprintw(scr, "%s%s $%010"PRIX64"\r" , op, postfix, tmpaddr); break; - case 0: wprintw(scr, "%s%s $%04" PRIX64"\r" , op, postfix, tmpaddr); break; - } - break; - } - - if (address == TX_ADDR || address == RX_ADDR) { - wmove(scr, 27, 0); - wprintw(scr, "TX_ADDR: $%02X, RX_ADDR: $%02X", addr[TX_ADDR], addr[RX_ADDR]); - } - if (subdbg) { - uint8_t ln = 33; - uint16_t line_idx = 0; - uint16_t tmpad = 0x2000; - int row, col; - uint8_t iscursor = 0; - uint64_t ptr; - uint8_t adr; - wmove(scr, 30, 0); - adr = 0x1F; - ptr = (uint64_t)addr[adr+0] << 0x00 | (uint64_t)addr[adr+1] << 0x08 | (uint64_t)addr[adr+2] << 0x10 | (uint64_t)addr[adr+3] << 0x18 | - (uint64_t)addr[adr+4] << 0x20 | (uint64_t)addr[adr+5] << 0x28 | (uint64_t)addr[adr+6] << 0x30 | (uint64_t)addr[adr+7] << 0x38; - wprintw(scr, "ptr1: $%04"PRIX64, ptr); - adr = 0x27; - ptr = (uint64_t)addr[adr+0] << 0x00 | (uint64_t)addr[adr+1] << 0x08 | (uint64_t)addr[adr+2] << 0x10 | (uint64_t)addr[adr+3] << 0x18 | - (uint64_t)addr[adr+4] << 0x20 | (uint64_t)addr[adr+5] << 0x28 | (uint64_t)addr[adr+6] << 0x30 | (uint64_t)addr[adr+7] << 0x38; - wprintw(scr, ", ptr2: $%04"PRIX64, ptr); - adr = 0x2F; - ptr = (uint64_t)addr[adr+0] << 0x00 | (uint64_t)addr[adr+1] << 0x08 | (uint64_t)addr[adr+2] << 0x10 | (uint64_t)addr[adr+3] << 0x18 | - (uint64_t)addr[adr+4] << 0x20 | (uint64_t)addr[adr+5] << 0x28 | (uint64_t)addr[adr+6] << 0x30 | (uint64_t)addr[adr+7] << 0x38; - wprintw(scr, ", ptr3: $%04"PRIX64, ptr); - if (address == CTRL_ADDR || addr[STEP_ADDR]) { - mvwprintw(scr, 29, 0, "address: $%04"PRIX64", scr_row: %02u, scr_col: %02u, scr_str: %02u, scr_end: %02u\r", address, addr[0], addr[1], addr[0x1C], addr[0x1D]); - mvwprintw(scr, 32, 0, "bitabl: %02X%02X%02X%02X%02X%02X%02X%02X" - "%02X%02X%02X%02X%02X%02X%02X%02X" - , addr[0x1000], addr[0x1001], addr[0x1002], addr[0x1003], addr[0x1004], addr[0x1005], addr[0x1006], addr[0x1007] - , addr[0x1008], addr[0x1009], addr[0x100A], addr[0x100B], addr[0x100C], addr[0x100D], addr[0x100E], addr[0x100F]); - mvwprintw(scr, ln++, 0, "buffer:\r"); - wmove(scr, ln++, 0); - for (uint8_t i = 0; i < 10; i++) { - line_idx = (i << 6) + (i << 4); - for (uint8_t j = 0; j < 0x50; j++) { - wprintw(scr, "%02X", addr[tmpad+j+line_idx]); - if ((addr[0]+addr[0x1C]) == i && addr[1] == j) { - iscursor=1; - getyx(scr,row, col); - wmove(scr, ln++, 0); - wclrtoeol(scr); - wmove(scr, row+1, col-2); - wprintw(scr, "/\\\r"); - wmove(scr, row, col); - } - } - wprintw(scr, ", i: %02X", i); - if (!iscursor) { - wmove(scr, ln, 0); - wclrtoeol(scr); - } - iscursor = 0; - wmove(scr, ln++, 0); - } - } - /*if (address == 0x4000 || tmpaddr == 0x4000 || addr[STEP_ADDR]) { - ln = 46; - tmpad = 0x4000; - line_idx = 0; - mvwprintw(scr, ln++, 0, "cmd_buf:"); - for (uint8_t i = 0; i < 5; i++) { - wmove(scr, ln++, 0); - line_idx = (i << 4)+(i << 6); - for (uint8_t j = 0; j < 0x50; j++) { - wprintw(scr, "%02X", addr[tmpad+j+line_idx]); - } - wprintw(scr, ", i: %02X", i); - } - }*/ - } + uint64_t operands[3]; + operands[0] = value; + operands[1] = address; + operands[2] = tmpaddr; + disasm(cpu, operands, lines, opcode, prefix, thread); + lines+=1; #if keypoll pthread_mutex_unlock(&mutex); #endif - lines+=1; #endif switch(opcode) { case CPS: /* Clear Processor Status. */ @@ -446,37 +152,14 @@ void *run(void *args) { case ADC: /* ADC Immediate. */ case ADC_AB: /* ADC Absolute. */ case ADC_Z: /* ADC Zero Matrix. */ - sum = cpu->a[thread]+value+getflag(C); - cpu->a[thread] = sum; - setflag(sum == 0, Z); - setflag((sum >> 63), N); - setflag(((cpu->a[thread]^value) >> 63) && ((cpu->a[thread]^sum) >> 63), V); - setflag((sum < value), C); + adc(cpu, value, thread); break; case PHB: /* PusH B register to stack. */ case PHP: /* PusH Processor status to stack. */ case PHA: /* PusH Accumulator to stack. */ case PHY: /* PusH Y register to stack. */ case PHX: /* PusH X register to stack. */ - tmp = (value <= 7) ? value : 7; - switch (opcode) { - case PHA: reg = cpu->a[thread]; break; - case PHB: reg = cpu->b[thread]; break; - case PHX: reg = cpu->x[thread]; break; - case PHY: reg = cpu->y[thread]; break; - case PHP: reg = cpu->ps; break; - } - /* Unroll Loop by implementing Duff's Device. */ - switch (tmp) { - case 7: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = reg >> (7<<3);cpu->sp[thread]--; - case 6: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = reg >> (6<<3);cpu->sp[thread]--; - case 5: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = reg >> (5<<3);cpu->sp[thread]--; - case 4: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = reg >> (4<<3);cpu->sp[thread]--; - case 3: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = reg >> (3<<3);cpu->sp[thread]--; - case 2: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = reg >> (2<<3);cpu->sp[thread]--; - case 1: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = reg >> (1<<3);cpu->sp[thread]--; - case 0: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = reg & (0xFF);cpu->sp[thread]--; - } + push(cpu, value, opcode, thread); break; case TAY: /* Transfer Accumulator to Y. */ case TAX: /* Transfer Accumulator to Y. */ @@ -488,26 +171,7 @@ void *run(void *args) { case TSX: /* Transfer Stack pointer to X. */ case TBA: /* Transfer B to Accumulator. */ case TXS: /* Transfer X to Stack pointer. */ - switch (opcode) { - case TBA: cpu->a[thread] = cpu->b[thread]; reg = cpu->a[thread]; break; - case TXA: cpu->a[thread] = cpu->x[thread]; reg = cpu->a[thread]; break; - case TYA: cpu->a[thread] = cpu->y[thread]; reg = cpu->a[thread]; break; - case TAB: cpu->b[thread] = cpu->a[thread]; reg = cpu->b[thread]; break; - case TAY: cpu->y[thread] = cpu->a[thread]; reg = cpu->y[thread]; break; - case TXY: cpu->y[thread] = cpu->x[thread]; reg = cpu->y[thread]; break; - case TAX: cpu->x[thread] = cpu->a[thread]; reg = cpu->x[thread]; break; - case TYX: cpu->x[thread] = cpu->y[thread]; reg = cpu->x[thread]; break; - case TSX: cpu->x[thread] = cpu->sp[thread] & 0xFFFF; cpu->x[thread] = cpu->stk_st[thread] << 16; 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; - } - setflag(reg == 0, Z); - setflag(reg >> 63, N); + transfer(cpu, value, opcode, prefix, thread); break; case JMP: /* JMP Absolute. */ case JMP_Z: /* JMP Zero Matrix. */ @@ -519,48 +183,21 @@ void *run(void *args) { case SBC: /* SBC Immediate. */ case SBC_AB: /* SBC Absolute. */ case SBC_Z: /* SBC Zero Matrix. */ - sum = cpu->a[thread]-value-!getflag(C); - setflag(sum == 0, Z); - setflag(sum >> 63, N); - setflag(((cpu->a[thread]^value) >> 63) && ((cpu->a[thread]^sum) >> 63), V); - setflag((sum > value), C); - cpu->a[thread] = sum; + sbc(cpu, value, thread); break; case PLB: /* PuLl B register from stack. */ case PLP: /* PuLl Processor status from stack. */ case PLA: /* PuLl Accumulator from stack. */ case PLY: /* PuLl Y register from stack. */ case PLX: /* PuLl X register from stack. */ - tmp = (value <= 7) ? value : 7; - reg = 0; - tmp2 = 0; - cpu->sp[thread]++;reg = addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] & 0xFF; - /* Unroll Loop by implementing Duff's Device. */ - switch (tmp) { - case 7: cpu->sp[thread]++;tmp2++;reg += (uint64_t)addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << (tmp2<<3); - case 6: cpu->sp[thread]++;tmp2++;reg += (uint64_t)addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << (tmp2<<3); - case 5: cpu->sp[thread]++;tmp2++;reg += (uint64_t)addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << (tmp2<<3); - case 4: cpu->sp[thread]++;tmp2++;reg += (uint64_t)addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << (tmp2<<3); - case 3: cpu->sp[thread]++;tmp2++;reg += (uint64_t)addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << (tmp2<<3); - case 2: cpu->sp[thread]++;tmp2++;reg += (uint64_t)addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << (tmp2<<3); - case 1: cpu->sp[thread]++;tmp2++;reg += (uint64_t)addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << (tmp2<<3); - } - switch (opcode) { - case PLA: cpu->a[thread] = reg; break; - case PLB: cpu->b[thread] = reg; break; - case PLX: cpu->x[thread] = reg; break; - case PLY: cpu->y[thread] = reg; break; - case PLP: cpu->ps = reg; break; - } + pull(cpu, value, opcode, thread); break; case ABA: /* bitwise And with Accumulator, and B register. */ value = cpu->b[thread]; /* Falls Through. */ case AND: /* AND Immediate. */ case AND_AB: /* AND Absolute. */ case AND_Z: /* AND Zero Matrix. */ - cpu->a[thread] &= value; - setflag(cpu->a[thread] == 0, Z); - setflag(cpu->a[thread] >> 63, N); + and(cpu, value, thread); break; case STT: /* STart Thread. */ cpu->crt |= value; @@ -589,9 +226,7 @@ void *run(void *args) { case ORA: /* ORA Immediate. */ case ORA_AB: /* ORA Absolute. */ case ORA_Z: /* ORA Zero Matrix. */ - cpu->a[thread] |= value; - setflag(cpu->a[thread] == 0, Z); - setflag(cpu->a[thread] >> 63, N); + or(cpu, value, thread); break; case SEI: /* SEt Interrupt. */ setflag(1, I); @@ -607,9 +242,7 @@ void *run(void *args) { case XOR: /* XOR Immediate. */ case XOR_AB: /* XOR Absolute. */ case XOR_Z: /* XOR Zero Matrix. */ - cpu->a[thread] ^= value; - setflag(cpu->a[thread] == 0, Z); - setflag(cpu->a[thread] >> 63, N); + xor(cpu, value, thread); break; case CLI: /* CLear Interrupt. */ setflag(0, I); @@ -625,11 +258,7 @@ void *run(void *args) { case LSL: /* LSL Immediate. */ case LSL_AB: /* LSL Absolute. */ case LSL_Z: /* LSL Zero Matrix. */ - sum = (value < 64) ? cpu->a[thread] << value : 0; - setflag(sum == 0, Z); - setflag(sum >> 63, N); - setflag(cpu->a[thread] >> (64-value), C); - cpu->a[thread] = sum; + lsl(cpu, value, thread); break; case SEC: /* SEt Carry flag.*/ setflag(1, C); @@ -656,219 +285,7 @@ void *run(void *args) { case STB_IX: /* STB Indexed Indirect. */ case STA_IY: /* STA Indirect Indexed. */ case STB_IY: /* STB Indirect Indexed. */ - 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 (IO || debug) && !branch - if (address == TX_ADDR) { - #if keypoll - pthread_mutex_lock(&mutex); - #endif - #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') { - wclrtoeol(scr); - } - #endif - switch (addr[TX_ADDR]) { - case 'A': - if (y > 0) - y--; - #if !debug - wmove(scr, y, x); - #endif - esc = 0; - break; - case 'B': - if (y < getmaxy(scr)) - y++; - #if !debug - wmove(scr, y, x); - #endif - esc = 0; - break; - case 'C': - if (x < getmaxx(scr)) - x++; - #if !debug - wmove(scr, y, x); - #endif - esc = 0; - break; - case 'D': - if (x > 0) - x--; - #if !debug - wmove(scr, y, x); - #endif - 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]); - } - #if !debug - wmove(scr, y, x); - #else - 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]);*/ - #endif - idx = 3; - bcd[0] = 0; - bcd[1] = 0; - bcd[2] = 0; - bcd[3] = 0; - esc = 0; - break; - case 'S': - #if !debug - wscrl(scr, -1); - #else - #endif - esc = 0; - break; - case 'T': - #if !debug - wscrl(scr, 1); - #else - #endif - 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 { - switch (addr[TX_ADDR]) { - case 0xC: - x=0,y=0; - #if !debug - wclear(scr); - wmove(scr, y, x); - #endif - break; - case CURSES_BACKSPACE: - case '\b': - if (x > 0) { - x--; - #if !debug - wmove(scr, y, x); - #endif - } - #if !debug - wdelch(scr); - #else - if (!subdbg) { - scr_col++; - wmove(scr, 28, scr_col--); - wdelch(scr); - wmove(scr, 28, scr_col); - wdelch(scr); - } - #endif - break; - case '\033': - esc = 1; - break; - case '\n': - #if !debug - wmove(scr, y, x); - waddch(scr, addr[address]); - #endif - x = 0; - y+=1; - break; - default: - #if !debug - wmove(scr, y, x); - waddch(scr, addr[address]); - #else - if (!subdbg && scr_col < 160) { - if (addr[address] != ' ') { - wprintw(scr, "%02X", addr[address]); - } else { - wprintw(scr, " "); - } - } - #endif - x+=1; - break; - } - } - #if keypoll - pthread_mutex_unlock(&mutex); - #endif - } - #endif - /* Unroll Loop by implementing Duff's Device. */ - switch (1 << (prefix >> 4)) { - case 8: - addr[address+7] = value >> 56; - addr[address+6] = value >> 48; - addr[address+5] = value >> 40; - addr[address+4] = value >> 32; - case 4: - addr[address+3] = value >> 24; - addr[address+2] = value >> 16; - case 2: - addr[address+1] = value >> 8; - } + store(cpu, address, &esc, opcode, prefix, thread); step = addr[STEP_ADDR] || cpu->pc[thread] == CTRL_ADDR; break; case BCC: /* BCC Absolute. */ @@ -882,23 +299,14 @@ void *run(void *args) { case LSR: /* LSR Immediate. */ case LSR_AB: /* LSR Absolute. */ case LSR_Z: /* LSR Zero Matrix. */ - sum = (value < 64) ? cpu->a[thread] >> value : 0; - setflag(sum == 0, Z); - setflag(sum >> 63, N); - setflag(cpu->a[thread] & 1, C); - cpu->a[thread] = sum; + lsr(cpu, value, thread); break; case ARB: /* Arithmetic shift Right accumulator by B. */ value = cpu->b[thread]; /* Falls Through. */ case ASR: /* ASR Immediate. */ case ASR_AB: /* ASR Absolute. */ case ASR_Z: /* ASR Zero Matrix. */ - sign = cpu->a[thread] >> 63; - sum = (value < 64) ? (cpu->a[thread] >> value) | ((uint64_t)sign << 63) : 0; - setflag(sum == 0, Z); - setflag(sum >> 63, N); - setflag(cpu->a[thread] & 1, C); - cpu->a[thread] = sum; + asr(cpu, value, thread); break; case CLC: /* CLear Carry flag. */ setflag(0, C); @@ -929,71 +337,7 @@ void *run(void *args) { case LDA_IX: /* LDA Indexed Indirect. */ case LDB_IY: /* LDB Indirect Indexed. */ case LDA_IY: /* LDA Indirect Indexed. */ - 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]; - /* Unroll Loop by implementing Duff's Device. */ - switch (1 << (prefix >> 4)) { - 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 |= (uint64_t)addr[address+3] << 24; - value |= (uint64_t)addr[address+2] << 16; - case 2: - value |= (uint64_t)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; - } - setflag(value == 0, Z); - setflag(value >> 63, N); + load(cpu, address, &esc, opcode, prefix, thread); break; case BEQ: /* BEQ Absolute. */ case BEQ_Z: /* BEQ Zero Matrix. */ @@ -1006,12 +350,7 @@ void *run(void *args) { case ROL: /* ROL Immediate. */ case ROL_AB: /* ROL Absolute. */ case ROL_Z: /* ROL Zero Matrix. */ - sum = cpu->a[thread] << value; - sum |= getflag(C); - setflag(sum == 0, Z); - setflag(sum >> 63, N); - setflag(cpu->a[thread] >> (uint64_t)(64-value), C); - cpu->a[thread] = sum; + rol(cpu, value, thread); break; case BNE: /* BNE Absolute. */ case BNE_Z: /* BNE Zero Matrix. */ @@ -1024,12 +363,7 @@ void *run(void *args) { case ROR: /* ROR Immediate. */ case ROR_AB: /* ROR Absolute. */ case ROR_Z: /* ROR Zero Matrix. */ - sum = cpu->a[thread] >> value; - sum |= (uint64_t)getflag(C) << (uint64_t)(64-value); - setflag(sum == 0, Z); - setflag(sum >> 63, N); - setflag(cpu->a[thread] & 1, C); - cpu->a[thread] = sum; + ror(cpu, value, thread); break; case BVS: /* BVS Absolute. */ case BVS_Z: /* BVS Zero Matrix. */ @@ -1042,11 +376,7 @@ void *run(void *args) { case MUL: /* MUL Immediate. */ case MUL_AB: /* MUL Absolute. */ case MUL_Z: /* MUL Zero Matrix. */ - sum = cpu->a[thread]*value; - cpu->a[thread] = sum; - setflag(sum == 0, Z); - setflag(sum >> 63, N); - setflag(!((cpu->a[thread]^value) >> 63) && ((cpu->a[thread]^sum) >> 63), V); + mul(cpu, value, thread); break; case BVC: /* BVC Absolute. */ case BVC_Z: /* BVC Zero Matrix. */ @@ -1058,16 +388,7 @@ void *run(void *args) { case DAB: /* Divide Accumulator by B. */ case DIV_AB: /* DIV Absolute. */ case DIV_Z: /* DIV Zero Matrix. */ - sum = cpu->a[thread]/value; - if (opcode != DAB) { - cpu->b[thread] = cpu->a[thread] % value; - } else { - value = cpu->b[thread]; - cpu->x[thread] = cpu->a[thread] % value; - } - cpu->a[thread] = sum; - setflag(sum == 0, Z); - setflag((sum >> 63), N); + divd(cpu, value, opcode, thread); break; case CLV: /* CLear oVerflow flag. */ setflag(0, V); @@ -1094,43 +415,7 @@ void *run(void *args) { case CPB_IX: /* CPB Indexed Indirect. */ case CMP_IY: /* CMP Indirect Indexed. */ case CPB_IY: /* CPB Indirect Indexed. */ - 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; - setflag(sum >> 63, N); - setflag(((reg^value) >> 63) && ((reg^sum) >> 63), V); - setflag(sum == 0, Z); - setflag(reg >= value, C); + cmp(cpu, value, opcode, thread); break; case ENT: /* ENd Thread. */ cpu->crt &= ~value; @@ -1154,27 +439,13 @@ void *run(void *args) { case INB: case INY: case INX: - switch (opcode) { - case INC: cpu->a[thread]+=1; reg = cpu->a[thread]; break; - case INB: cpu->b[thread]+=1; reg = cpu->b[thread]; break; - case INY: cpu->y[thread]+=1; reg = cpu->y[thread]; break; - case INX: cpu->x[thread]+=1; reg = cpu->x[thread]; break; - } - setflag(reg == 0, Z); - setflag(reg >> 63, N); + incr(cpu, value, opcode, thread); break; case DEC: /* DEC Accumulator. */ case DEB: case DEY: case DEX: - switch (opcode) { - case DEC: cpu->a[thread]-=1; reg = cpu->a[thread]; break; - case DEB: cpu->b[thread]-=1; reg = cpu->b[thread]; break; - case DEY: cpu->y[thread]-=1; reg = cpu->y[thread]; break; - case DEX: cpu->x[thread]-=1; reg = cpu->x[thread]; break; - } - setflag(reg == 0, Z); - setflag(reg >> 63, N); + decr(cpu, value, opcode, thread); break; case JSR_IN: /* JSR Indirect. */ case JSR: /* Jump to SubRoutine. */ @@ -1192,9 +463,7 @@ void *run(void *args) { break; case INC_AB: /* INC Absolute. */ case INC_Z: /* INC Zero Matrix. */ - addr[address]++; - setflag(addr[address] == 0, Z); - setflag(addr[address] >> 7, N); + incm(cpu, address, thread); step = addr[STEP_ADDR] || cpu->pc[thread] == CTRL_ADDR; break; case NOP: /* No OPeration. */ @@ -1213,9 +482,7 @@ void *run(void *args) { break; case DEC_AB: /* DEC Absolute. */ case DEC_Z: /* DEC Zero Matrix. */ - addr[address]--; - setflag(addr[address] == 0, Z); - setflag(addr[address] >> 7, N); + decm(cpu, address, thread); step = addr[STEP_ADDR] || cpu->pc[thread] == CTRL_ADDR; break; case BRK: /* BReaK. */ @@ -1335,7 +602,6 @@ int main(int argc, char **argv) { sprintf(tmp, "\033[2J\033[H"); fwrite(tmp, sizeof(char), strlen(tmp), stdout); fflush(stdout); - #if !bench if(!scr) { scr = initscr(); } @@ -1352,7 +618,6 @@ int main(int argc, char **argv) { attron(COLOR_PAIR(1) | A_BOLD); wmove(scr, 0, 0); wrefresh(scr); - #endif pthread_t therads[THREADS]; int result; uint16_t vec = 0xFFC0; @@ -1384,10 +649,9 @@ int main(int argc, char **argv) { } int c = 0; uint8_t step_key = 0; -#if !bench + uint8_t end = 0; werase(scr); -#endif - while (threads_done < THREADS) { + while (threads_done < THREADS && !end) { #if !bench int x, y; if ((step_key && step && !kbd_rdy) || !step || kbd_rdy) { @@ -1411,13 +675,15 @@ int main(int argc, char **argv) { #if keypoll pthread_mutex_lock(&mutex); #endif - getyx(scr, y, x); c = wgetch(scr); if (c == 19) { if (kbd_rdy) { c = wgetch(scr); } step = 1; + } else if (c == 0x11) { + end = 1; + continue; } if (kbd_rdy) { switch (c) { @@ -1453,6 +719,7 @@ int main(int argc, char **argv) { pthread_mutex_unlock(&main_mutex); #endif } + endwin(); #if bench if (threads_done == THREADS) { double tm_sec, tm_usec, tm[THREADS], ttm; @@ -0,0 +1,554 @@ +#include "opcode.h" +#include <pthread.h> + +#if bench +#include <sys/time.h> +#endif +#include <curses.h> + +#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 + +uint8_t kbd_rdy; + +#if debug +uint8_t subdbg; +#endif + +WINDOW *scr; + +#define setflag(flag, bit) ((flag)) ? (cpu->ps |= (bit << (thread << 3))) : (cpu->ps &= ~(bit << (thread << 3))) +#define getflag(bit) (cpu->ps & (bit << (thread << 3))) + +extern pthread_mutex_t mutex; +extern pthread_mutex_t main_mutex; +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); +#endif + +extern void io(uint64_t address, uint8_t *esc); + +static inline uint64_t get_addr(struct sux *cpu, uint64_t *tmpaddr, uint8_t opcode, uint8_t prefix, uint8_t thread) { + uint64_t address = 0; + uint64_t value = 0; + uint8_t tmp = 0; + 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]; + break; + default: + address = cpu->pc[thread]; + cpu->pc[thread]+=(1 << (prefix >> 4)); + break; + } + break; + case ZM: + case ZMX: + case ZMY: + case IND: + case INDX: + case INDY: + tmp = 0; + address = addr[cpu->pc[thread]]; + /* Unroll Loop by implementing Duff's Device. */ + switch ((prefix & 0x0C) >> 2) { + case 2: + address |= (uint64_t)addr[cpu->pc[thread]+5] << 40;++tmp; + address |= (uint64_t)addr[cpu->pc[thread]+4] << 32;++tmp; + case 3: + address |= addr[cpu->pc[thread]+3] << 24;++tmp; + case 1: + address |= addr[cpu->pc[thread]+2] << 16;++tmp; + address |= addr[cpu->pc[thread]+1] << 8;++tmp; + case 0: + ++tmp; + } + cpu->pc[thread]+=tmp; + #if debug && !bench + *tmpaddr = address; + #endif + #if getclk + iclk++; + #endif + uint64_t reg = 0; + switch (optype[opcode]) { + case ZMX: + address += cpu->x[thread]; + #if getclk + iclk++; + #endif + break; + case ZMY: + address += cpu->y[thread]; + #if getclk + iclk++; + #endif + break; + case INDX: + address += cpu->x[thread]; + #if getclk + iclk++; + #endif + /* Falls Through. */ + case INDY: + /* Did we fall through? */ + if (optype[opcode] == INDX) { + reg = 0; /* Yes, so set reg back to zero. */ + } else { + reg = cpu->y[thread]; /* No, so set reg to Y. */ + #if getclk + iclk++; + #endif + } + /* Falls Through. */ + case IND: + 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; + #if getclk + iclk++; + #endif + value += reg; + address = value; + value = 0; + reg = 0; + break; + } + break; + case ABS: + tmp = 0; + address = addr[cpu->pc[thread]];++tmp; + /* Unroll Loop by implementing Duff's Device. */ + switch ((prefix & 0x0C) >> 2) { + case 3: + address |= (uint64_t)addr[cpu->pc[thread]+7] << 56;++tmp; + case 2: + address |= (uint64_t)addr[cpu->pc[thread]+6] << 48;++tmp; + address |= (uint64_t)addr[cpu->pc[thread]+5] << 40;++tmp; + #if getclk + iclk++; + #endif + case 1: + address |= (uint64_t)addr[cpu->pc[thread]+4] << 32;++tmp; + address |= addr[cpu->pc[thread]+3] << 24;++tmp; + address |= addr[cpu->pc[thread]+2] << 16;++tmp; + case 0: + address |= addr[cpu->pc[thread]+1] << 8;++tmp; + } + cpu->pc[thread]+=tmp; + break; + + } + return address; +} + +inline void adc(struct sux *cpu, uint64_t value, uint8_t thread) { + uint64_t sum = cpu->a[thread]+value+getflag(C); + setflag(sum == 0, Z); + setflag((sum >> 63), N); + setflag(((cpu->a[thread]^value) >> 63) && ((cpu->a[thread]^sum) >> 63), V); + setflag((sum < value), C); + cpu->a[thread] = sum; +} +inline void sbc(struct sux *cpu, uint64_t value, uint8_t thread) { + uint64_t sum = cpu->a[thread]-value-!getflag(C); + setflag(sum == 0, Z); + setflag(sum >> 63, N); + setflag(((cpu->a[thread]^value) >> 63) && ((cpu->a[thread]^sum) >> 63), V); + setflag((sum > value), C); + cpu->a[thread] = sum; +} + +inline void transfer(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t prefix, uint8_t thread) { + uint64_t reg; + switch (opcode) { + case TBA: cpu->a[thread] = cpu->b[thread]; reg = cpu->a[thread]; break; + case TXA: cpu->a[thread] = cpu->x[thread]; reg = cpu->a[thread]; break; + case TYA: cpu->a[thread] = cpu->y[thread]; reg = cpu->a[thread]; break; + case TAB: cpu->b[thread] = cpu->a[thread]; reg = cpu->b[thread]; break; + case TAY: cpu->y[thread] = cpu->a[thread]; reg = cpu->y[thread]; break; + case TXY: cpu->y[thread] = cpu->x[thread]; reg = cpu->y[thread]; break; + case TAX: cpu->x[thread] = cpu->a[thread]; reg = cpu->x[thread]; break; + case TYX: cpu->x[thread] = cpu->y[thread]; reg = cpu->x[thread]; break; + case TSX: cpu->x[thread] = cpu->sp[thread] & 0xFFFF; cpu->x[thread] = cpu->stk_st[thread] << 16; 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; + } + setflag(reg == 0, Z); + setflag(reg >> 63, N); +} + +inline void push(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread) { + union { + uint64_t reg; + uint8_t byte[8]; + } r; + r.reg = 0; + uint8_t size = ((int8_t)value >= 0) ? value-1 : 0; + uint8_t tmp = (size <= 7) ? size : 7; + switch (opcode) { + case PHA: r.reg = cpu->a[thread]; break; + case PHB: r.reg = cpu->b[thread]; break; + case PHX: r.reg = cpu->x[thread]; break; + case PHY: r.reg = cpu->y[thread]; break; + case PHP: r.reg = cpu->ps; break; + } + /* Unroll Loop by implementing Duff's Device. */ + switch (tmp) { + case 7: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = r.byte[7];cpu->sp[thread]--; + case 6: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = r.byte[6];cpu->sp[thread]--; + case 5: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = r.byte[5];cpu->sp[thread]--; + case 4: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = r.byte[4];cpu->sp[thread]--; + case 3: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = r.byte[3];cpu->sp[thread]--; + case 2: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = r.byte[2];cpu->sp[thread]--; + case 1: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = r.byte[1];cpu->sp[thread]--; + case 0: addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = r.byte[0];cpu->sp[thread]--; + } +} + +inline void pull(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread) { + union { + uint64_t reg; + uint8_t byte[8]; + } r; + r.reg = 0; + uint8_t size = ((int8_t)value >= 0) ? value-1 : 0; + uint8_t tmp = (size <= 7) ? size : 7; + uint8_t tmp2 = 0; + /* Unroll Loop by implementing Duff's Device. */ + cpu->sp[thread]++;r.byte[tmp2] = addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]]; + switch (tmp) { + case 7: cpu->sp[thread]++;tmp2++;r.byte[tmp2] |= addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]]; + case 6: cpu->sp[thread]++;tmp2++;r.byte[tmp2] |= addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]]; + case 5: cpu->sp[thread]++;tmp2++;r.byte[tmp2] |= addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]]; + case 4: cpu->sp[thread]++;tmp2++;r.byte[tmp2] |= addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]]; + case 3: cpu->sp[thread]++;tmp2++;r.byte[tmp2] |= addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]]; + case 2: cpu->sp[thread]++;tmp2++;r.byte[tmp2] |= addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]]; + case 1: cpu->sp[thread]++;tmp2++;r.byte[tmp2] |= addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]]; + } + switch (opcode) { + case PLA: cpu->a[thread] = r.reg; break; + case PLB: cpu->b[thread] = r.reg; break; + case PLX: cpu->x[thread] = r.reg; break; + case PLY: cpu->y[thread] = r.reg; break; + case PLP: cpu->ps = r.reg; break; + } +} + +inline void and(struct sux *cpu, uint64_t value, uint8_t thread) { + cpu->a[thread] &= value; + setflag(cpu->a[thread] == 0, Z); + setflag(cpu->a[thread] >> 63, N); +} +inline void or(struct sux *cpu, uint64_t value, uint8_t thread) { + cpu->a[thread] |= value; + setflag(cpu->a[thread] == 0, Z); + setflag(cpu->a[thread] >> 63, N); +} +inline void xor(struct sux *cpu, uint64_t value, uint8_t thread) { + cpu->a[thread] ^= value; + setflag(cpu->a[thread] == 0, Z); + setflag(cpu->a[thread] >> 63, N); +} + +inline void lsl(struct sux *cpu, uint64_t value, uint8_t thread) { + uint64_t sum = (value < 64) ? cpu->a[thread] << value : 0; + setflag(sum == 0, Z); + setflag(sum >> 63, N); + setflag(cpu->a[thread] >> (64-value), C); + cpu->a[thread] = sum; +} + +inline void lsr(struct sux *cpu, uint64_t value, uint8_t thread) { + uint64_t sum = (value < 64) ? cpu->a[thread] >> value : 0; + setflag(sum == 0, Z); + setflag(sum >> 63, N); + setflag(cpu->a[thread] & 1, C); + cpu->a[thread] = sum; +} + +inline void asr(struct sux *cpu, uint64_t value, uint8_t thread) { + uint8_t sign = cpu->a[thread] >> 63; + uint64_t sum = (value < 64) ? (cpu->a[thread] >> value) | ((uint64_t)sign << 63) : 0; + setflag(sum == 0, Z); + setflag(sum >> 63, N); + setflag(cpu->a[thread] & 1, C); + cpu->a[thread] = sum; +} + +inline void rol(struct sux *cpu, uint64_t value, uint8_t thread) { + uint64_t sum = cpu->a[thread] << value; + sum |= getflag(C); + setflag(sum == 0, Z); + setflag(sum >> 63, N); + setflag(cpu->a[thread] >> (uint64_t)(64-value), C); + cpu->a[thread] = sum; +} + +inline void ror(struct sux *cpu, uint64_t value, uint8_t thread) { + uint64_t sum = cpu->a[thread] >> value; + sum |= (uint64_t)getflag(C) << (uint64_t)(64-value); + setflag(sum == 0, Z); + setflag(sum >> 63, N); + setflag(cpu->a[thread] & 1, C); + cpu->a[thread] = sum; +} +inline void mul(struct sux *cpu, uint64_t value, uint8_t thread) { + uint64_t sum = cpu->a[thread]*value; + cpu->a[thread] = sum; + setflag(sum == 0, Z); + setflag(sum >> 63, N); + setflag(!((cpu->a[thread]^value) >> 63) && ((cpu->a[thread]^sum) >> 63), V); +} + +inline void divd(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread) { + uint64_t sum = cpu->a[thread]/value; + if (opcode != DAB) { + cpu->b[thread] = cpu->a[thread] % value; + } else { + value = cpu->b[thread]; + cpu->x[thread] = cpu->a[thread] % value; + } + cpu->a[thread] = sum; + setflag(sum == 0, Z); + setflag((sum >> 63), N); +} +inline void cmp(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread) { + uint64_t reg; + 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; + } + uint64_t sum = reg-value; + setflag(sum >> 63, N); + setflag(((reg^value) >> 63) && ((reg^sum) >> 63), V); + setflag(sum == 0, Z); + setflag(reg >= value, C); +} + +inline void incr(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread) { + uint64_t reg; + switch (opcode) { + case INC: cpu->a[thread]+=1; reg = cpu->a[thread]; break; + case INB: cpu->b[thread]+=1; reg = cpu->b[thread]; break; + case INY: cpu->y[thread]+=1; reg = cpu->y[thread]; break; + case INX: cpu->x[thread]+=1; reg = cpu->x[thread]; break; + } + setflag(reg == 0, Z); + setflag(reg >> 63, N); +} + +inline void decr(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread) { + uint64_t reg; + switch (opcode) { + case DEC: cpu->a[thread]-=1; reg = cpu->a[thread]; break; + case DEB: cpu->b[thread]-=1; reg = cpu->b[thread]; break; + case DEY: cpu->y[thread]-=1; reg = cpu->y[thread]; break; + case DEX: cpu->x[thread]-=1; reg = cpu->x[thread]; break; + } + setflag(reg == 0, Z); + setflag(reg >> 63, N); +} + +inline void incm(struct sux *cpu, uint64_t address, uint8_t thread) { + addr[address]++; + setflag(addr[address] == 0, Z); + setflag(addr[address] >> 7, N); +} + +inline void decm(struct sux *cpu, uint64_t address, uint8_t thread) { + addr[address]--; + setflag(addr[address] == 0, Z); + setflag(addr[address] >> 7, N); +} + +inline void load(struct sux *cpu, uint64_t address, uint8_t *esc, uint8_t opcode, uint8_t prefix, uint8_t thread) { + if (address == CTRL_ADDR) { + io(address, esc); + } + uint64_t value = addr[address]; + /* Unroll Loop by implementing Duff's Device. */ + switch (1 << (prefix >> 4)) { + 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; + } + setflag(value == 0, Z); + setflag(value >> 63, N); +} + +inline void store(struct sux *cpu, uint64_t address, uint8_t *esc, uint8_t opcode, uint8_t prefix, uint8_t thread) { + uint64_t value; + 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 (IO || debug) && !branch + #if keypoll + pthread_mutex_lock(&mutex); + #endif + if (address != CTRL_ADDR && address == TX_ADDR) { + io(address, esc); + } + #if keypoll + pthread_mutex_unlock(&mutex); + #endif + #endif + /* Unroll Loop by implementing Duff's Device. */ + switch (1 << (prefix >> 4)) { + case 8: + addr[address+7] = value >> 56; + addr[address+6] = value >> 48; + addr[address+5] = value >> 40; + addr[address+4] = value >> 32; + case 4: + addr[address+3] = value >> 24; + addr[address+2] = value >> 16; + case 2: + addr[address+1] = value >> 8; + } +} + |