diff options
-rw-r--r-- | disasm.c | 4 | ||||
-rw-r--r-- | lexer.c | 2 | ||||
-rw-r--r-- | opcode.h | 8 | ||||
-rw-r--r-- | sux.c | 228 | ||||
-rw-r--r-- | sux.h | 338 |
5 files changed, 234 insertions, 346 deletions
@@ -31,8 +31,8 @@ void disasm(struct sux *cpu, uint64_t *operands, uint8_t lines, uint8_t opcode, case ZMX: case ZMY: switch (optype[opcode]) { - case ZMX: tmpaddr = address - cpu->x[thread]; break; - case ZMY: tmpaddr = address - cpu->y[thread]; break; + case ZMX: tmpaddr = address - cpu->x; break; + case ZMY: tmpaddr = address - cpu->y; 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; @@ -232,6 +232,7 @@ uint64_t lex(char *str, uint64_t address, uint8_t dbg) { last_line = l; } + l->addr = address; while (isdelm(str[i], dbg) != 1) { base = 0; space = 0; @@ -606,6 +607,5 @@ uint64_t lex(char *str, uint64_t address, uint8_t dbg) { linenum += 10; } } - l->addr = address; return address; } @@ -29,10 +29,10 @@ union reg { struct sux { union reg ps; /* The processor status register. */ - uint64_t a[8], b[8], y[8], x[8]; /* Registers A, B, X, and Y. */ - uint64_t pc[8]; /* Program counter. */ - uint16_t sp[8]; /* Stack pointer. */ - uint16_t stk_st[8]; /* Starting address of each threads stack. */ + uint64_t a, b, y, x; /* Registers A, B, X, and Y. */ + uint64_t pc; /* Program counter. */ + uint16_t sp; /* Stack pointer. */ + uint16_t stk_st; /* Starting address of each threads stack. */ uint8_t crt; /* Current running threads. */ }; @@ -84,12 +84,6 @@ void *run(void *args) { for (;;) { address.u64 = 0; value.u64 = 0; - prefix = addr[cpu->pc[thread]]; - if ((prefix & 0x03) != 0x03) { - prefix = 0; - } - cpu->pc[thread] += ((prefix & 0x03) == 0x03); - opcode = addr[cpu->pc[thread]]; #if debug && !bench if (lines > 24*(thread+1)) { lines = (24*thread)+2; @@ -103,39 +97,32 @@ void *run(void *args) { } wmove(scr, lines, 1); wclrtoeol(scr); - wprintw(scr, "pc: $%04"PRIX64 , cpu->pc[thread]); - wprintw(scr, ", a: $%016"PRIX64, cpu->a[thread]); - wprintw(scr, ", b: $%016"PRIX64, cpu->b[thread]); - wprintw(scr, ", x: $%016"PRIX64, cpu->x[thread]); - wprintw(scr, ", y: $%016"PRIX64, cpu->y[thread]); - wprintw(scr, ", sp: $%04X", cpu->sp[thread]); + wprintw(scr, "pc: $%04"PRIX64 , cpu->pc); + wprintw(scr, ", a: $%016"PRIX64, cpu->a); + wprintw(scr, ", b: $%016"PRIX64, cpu->b); + wprintw(scr, ", x: $%016"PRIX64, cpu->x); + wprintw(scr, ", y: $%016"PRIX64, cpu->y); + wprintw(scr, ", sp: $%04X", cpu->sp); wprintw(scr, ", ps: $%02X", cpu->ps.u8[thread]); wprintw(scr, ", inst: "); #if keypoll pthread_mutex_unlock(&mutex); #endif #endif - address.u64 = cpu->pc[thread]; - ++cpu->pc[thread]; + prefix = addr[cpu->pc]; + if ((prefix & 0x03) != 0x03) { + prefix = 0; + } + cpu->pc += ((prefix & 0x03) == 0x03); + opcode = addr[cpu->pc]; + address.u64 = cpu->pc; + ++cpu->pc; #if getclk ++iclk; #endif if (optype[opcode] != IMPL) { address.u64 = get_addr(cpu, &tmpaddr, opcode, prefix, thread); - /* Unroll Loop by implementing Duff's Device. */ - value.u8[0] = addr[address.u64]; - switch (1 << (prefix >> 4)) { - case 8: - value.u8[7] = addr[address.u64+7]; - value.u8[6] = addr[address.u64+6]; - value.u8[5] = addr[address.u64+5]; - value.u8[4] = addr[address.u64+4]; - case 4: - value.u8[3] = addr[address.u64+3]; - value.u8[2] = addr[address.u64+2]; - case 2: - value.u8[1] = addr[address.u64+1]; - } + setreg_sw(value.u8, 0, addr, address.u64, prefix, 0, RS); #if getclk ++iclk; #endif @@ -159,17 +146,17 @@ void *run(void *args) { cpu->ps.u64 = 0; break; case AAB: /* Add Accumulator with carry by B register. */ - value.u64 = cpu->b[thread]; /* Falls Through. */ + value.u64 = cpu->b; /* Falls Through. */ case ADC: /* ADC Immediate. */ case ADC_AB: /* ADC Absolute. */ case ADC_Z: /* ADC Zero Matrix. */ adc(cpu, value.u64, thread); break; - case PHP: push(cpu, value.u64, cpu->ps.u8[thread], thread); break; /* PusH Processor status to stack. */ - case PHA: push(cpu, value.u64, cpu->a[thread ], thread); break; /* PusH Accumulator to stack. */ - case PHB: push(cpu, value.u64, cpu->b[thread ], thread); break; /* PusH B register to stack. */ - case PHY: push(cpu, value.u64, cpu->y[thread ], thread); break; /* PusH Y register to stack. */ - case PHX: push(cpu, value.u64, cpu->x[thread ], thread); break; /* PusH X register to stack. */ + case PHP: push(cpu, value.u64, cpu->ps.u64, thread); break; /* PusH Processor status to stack. */ + case PHA: push(cpu, value.u64, cpu->a , thread); break; /* PusH Accumulator to stack. */ + case PHB: push(cpu, value.u64, cpu->b , thread); break; /* PusH B register to stack. */ + case PHY: push(cpu, value.u64, cpu->y , thread); break; /* PusH Y register to stack. */ + case PHX: push(cpu, value.u64, cpu->x , thread); break; /* PusH X register to stack. */ case TAY: /* Transfer Accumulator to Y. */ case TAX: /* Transfer Accumulator to Y. */ case TYX: /* Transfer Y to X. */ @@ -185,23 +172,23 @@ void *run(void *args) { case JMP: /* JMP Absolute. */ case JMP_Z: /* JMP Zero Matrix. */ case JMP_IN: /* JMP Indirect. */ - cpu->pc[thread] = address.u64; + cpu->pc = address.u64; break; case SAB: /* Subtract Accumulator with carry by B register. */ - value.u64 = cpu->b[thread]; /* Falls Through. */ + value.u64 = cpu->b; /* Falls Through. */ case SBC: /* SBC Immediate. */ case SBC_AB: /* SBC Absolute. */ case SBC_Z: /* SBC Zero Matrix. */ sbc(cpu, value.u64, thread); break; - case PLP: cpu->ps.u8[thread] = pull(cpu, value.u64, thread); break; /* PuLl Processor status from stack. */ - case PLA: cpu->a[thread ] = pull(cpu, value.u64, thread); break; /* PuLl Accumulator from stack. */ - case PLB: cpu->b[thread ] = pull(cpu, value.u64, thread); break; /* PuLl B register from stack. */ - case PLY: cpu->y[thread ] = pull(cpu, value.u64, thread); break; /* PuLl Y register from stack. */ - case PLX: cpu->x[thread ] = pull(cpu, value.u64, thread); break; /* PuLl X register from stack. */ + case PLP: cpu->ps.u64 = pull(cpu, value.u64, thread); break; /* PuLl Processor status from stack. */ + case PLA: cpu->a = pull(cpu, value.u64, thread); break; /* PuLl Accumulator from stack. */ + case PLB: cpu->b = pull(cpu, value.u64, thread); break; /* PuLl B register from stack. */ + case PLY: cpu->y = pull(cpu, value.u64, thread); break; /* PuLl Y register from stack. */ + case PLX: cpu->x = pull(cpu, value.u64, thread); break; /* PuLl X register from stack. */ break; case ABA: /* bitwise And with Accumulator, and B register. */ - value.u64 = cpu->b[thread]; /* Falls Through. */ + value.u64 = cpu->b; /* Falls Through. */ case AND: /* AND Immediate. */ case AND_AB: /* AND Absolute. */ case AND_Z: /* AND Zero Matrix. */ @@ -226,11 +213,11 @@ void *run(void *args) { case BPO: /* BPO Absolute. */ case BPO_Z: /* BPO Zero Matrix. */ if (!getflag(N)) { - cpu->pc[thread] = address.u64; + cpu->pc = address.u64; } break; case OAB: /* bitwise Or with Accumulator, and B register. */ - value.u64 = cpu->b[thread]; /* Falls Through. */ + value.u64 = cpu->b; /* Falls Through. */ case ORA: /* ORA Immediate. */ case ORA_AB: /* ORA Absolute. */ case ORA_Z: /* ORA Zero Matrix. */ @@ -242,11 +229,11 @@ void *run(void *args) { case BNG: /* BNG Absolute. */ case BNG_Z: /* BNG Zero Matrix. */ if (getflag(N)) { - cpu->pc[thread] = address.u64; + cpu->pc = address.u64; } break; case XAB: /* bitwise Xor with Accumulator, and B register. */ - value.u64 = cpu->b[thread]; /* Falls Through. */ + value.u64 = cpu->b; /* Falls Through. */ case XOR: /* XOR Immediate. */ case XOR_AB: /* XOR Absolute. */ case XOR_Z: /* XOR Zero Matrix. */ @@ -258,11 +245,11 @@ void *run(void *args) { case BCS: /* BCS Absolute. */ case BCS_Z: /* BCS Zero Matrix. */ if (getflag(C)) { - cpu->pc[thread] = address.u64; + cpu->pc = address.u64; } break; case LLB: /* Logical shift Left accumulator by B. */ - value.u64 = cpu->b[thread]; /* Falls Through. */ + value.u64 = cpu->b; /* Falls Through. */ case LSL: /* LSL Immediate. */ case LSL_AB: /* LSL Absolute. */ case LSL_Z: /* LSL Zero Matrix. */ @@ -278,19 +265,19 @@ void *run(void *args) { case STA_IN: /* STA Indirect. */ case STA_IX: /* STA Indexed Indirect. */ case STA_IY: /* STA Indirect Indexed. */ - store(cpu, address.u64, cpu->a[thread], prefix, thread); + store(cpu, address.u64, cpu->a, prefix, thread); break; case STY: /* STY Absolute. */ case STY_Z: /* STY Zero Matrix. */ case STY_ZX: /* STY Zero Matrix, Indexed with X. */ case STY_IN: /* STY Indirect. */ - store(cpu, address.u64, cpu->y[thread], prefix, thread); + store(cpu, address.u64, cpu->y, prefix, thread); break; case STX: /* STX Absolute. */ case STX_Z: /* STX Zero Matrix. */ case STX_ZY: /* STX Zero Matrix, Indexed with Y. */ case STX_IN: /* STX Indirect. */ - store(cpu, address.u64, cpu->x[thread], prefix, thread); + store(cpu, address.u64, cpu->x, prefix, thread); break; case STB: /* STB Absolute. */ case STB_Z: /* STB Zero Matrix. */ @@ -299,23 +286,23 @@ void *run(void *args) { case STB_IN: /* STB Indirect. */ case STB_IX: /* STB Indexed Indirect. */ case STB_IY: /* STB Indirect Indexed. */ - store(cpu, address.u64, cpu->b[thread], prefix, thread); + store(cpu, address.u64, cpu->b, prefix, thread); break; case BCC: /* BCC Absolute. */ case BCC_Z: /* BCC Zero Matrix. */ if (!getflag(C)) { - cpu->pc[thread] = address.u64; + cpu->pc = address.u64; } break; case LRB: /* Logical shift Right accumulator by B. */ - value.u64 = cpu->b[thread]; /* Falls Through. */ + value.u64 = cpu->b; /* Falls Through. */ case LSR: /* LSR Immediate. */ case LSR_AB: /* LSR Absolute. */ case LSR_Z: /* LSR Zero Matrix. */ lsr(cpu, value.u64, thread); break; case ARB: /* Arithmetic shift Right accumulator by B. */ - value.u64 = cpu->b[thread]; /* Falls Through. */ + value.u64 = cpu->b; /* Falls Through. */ case ASR: /* ASR Immediate. */ case ASR_AB: /* ASR Absolute. */ case ASR_Z: /* ASR Zero Matrix. */ @@ -332,7 +319,7 @@ void *run(void *args) { case LDB_IN: /* LDB Indirect. */ case LDB_IX: /* LDB Indexed Indirect. */ case LDB_IY: /* LDB Indirect Indexed. */ - cpu->b[thread] = load(cpu, address.u64, cpu->b[thread], prefix, thread); + cpu->b = load(cpu, address.u64, cpu->b, prefix, thread); break; case LDA: /* LDA Immediate. */ case LDA_AB: /* LDA Absolute. */ @@ -342,30 +329,30 @@ void *run(void *args) { case LDA_IN: /* LDA Indirect. */ case LDA_IX: /* LDA Indexed Indirect. */ case LDA_IY: /* LDA Indirect Indexed. */ - cpu->a[thread] = load(cpu, address.u64, cpu->a[thread], prefix, thread); + cpu->a = load(cpu, address.u64, cpu->a, prefix, thread); break; case LDY: /* LDY Immediate. */ case LDY_AB: /* LDY Absolute. */ case LDY_Z: /* LDY Zero Matrix. */ case LDY_ZX: /* LDY Zero Matrix, Indexed with X. */ case LDY_IN: /* LDY Indirect. */ - cpu->y[thread] = load(cpu, address.u64, cpu->y[thread], prefix, thread); + cpu->y = load(cpu, address.u64, cpu->y, prefix, thread); break; case LDX: /* LDX Immediate. */ case LDX_AB: /* LDX Absolute. */ case LDX_Z: /* LDX Zero Matrix. */ case LDX_ZY: /* LDX Zero Matrix, Indexed with Y. */ case LDX_IN: /* LDX Indirect. */ - cpu->x[thread] = load(cpu, address.u64, cpu->x[thread], prefix, thread); + cpu->x = load(cpu, address.u64, cpu->x, prefix, thread); break; case BEQ: /* BEQ Absolute. */ case BEQ_Z: /* BEQ Zero Matrix. */ if (getflag(Z)) { - cpu->pc[thread] = address.u64; + cpu->pc = address.u64; } break; case RLB: /* Rotate Left accumulator by B. */ - value.u64 = cpu->b[thread]; /* Falls Through. */ + value.u64 = cpu->b; /* Falls Through. */ case ROL: /* ROL Immediate. */ case ROL_AB: /* ROL Absolute. */ case ROL_Z: /* ROL Zero Matrix. */ @@ -374,11 +361,11 @@ void *run(void *args) { case BNE: /* BNE Absolute. */ case BNE_Z: /* BNE Zero Matrix. */ if (!getflag(Z)) { - cpu->pc[thread] = address.u64; + cpu->pc = address.u64; } break; case RRB: /* Rotate Right accumulator by B. */ - value.u64 = cpu->b[thread]; /* Falls Through. */ + value.u64 = cpu->b; /* Falls Through. */ case ROR: /* ROR Immediate. */ case ROR_AB: /* ROR Absolute. */ case ROR_Z: /* ROR Zero Matrix. */ @@ -387,11 +374,11 @@ void *run(void *args) { case BVS: /* BVS Absolute. */ case BVS_Z: /* BVS Zero Matrix. */ if (getflag(V)) { - cpu->pc[thread] = address.u64; + cpu->pc = address.u64; } break; case MAB: /* Multiply Accumulator by B. */ - value.u64 = cpu->b[thread]; /* Falls Through. */ + value.u64 = cpu->b; /* Falls Through. */ case MUL: /* MUL Immediate. */ case MUL_AB: /* MUL Absolute. */ case MUL_Z: /* MUL Zero Matrix. */ @@ -400,7 +387,7 @@ void *run(void *args) { case BVC: /* BVC Absolute. */ case BVC_Z: /* BVC Zero Matrix. */ if (!getflag(V)) { - cpu->pc[thread] = address.u64; + cpu->pc = address.u64; } break; case DIV: /* DIV Immediate. */ @@ -418,29 +405,29 @@ void *run(void *args) { case CPB_IN: /* CPB Indirect. */ case CPB_IX: /* CPB Indexed Indirect. */ case CPB_IY: /* CPB Indirect Indexed. */ - cmp(cpu, value.u64, cpu->b[thread], thread); + cmp(cpu, value.u64, cpu->b, thread); break; case CAB: /* Compare Accumulator, and B. */ - value.u64 = cpu->b[thread]; /* Falls Through. */ + value.u64 = cpu->b; /* Falls Through. */ case CMP: /* CMP Immediate. */ case CMP_AB: /* CMP Absolute. */ case CMP_Z: /* CMP Zero Matrix. */ case CMP_IN: /* CMP Indirect. */ case CMP_IX: /* CMP Indexed Indirect. */ case CMP_IY: /* CMP Indirect Indexed. */ - cmp(cpu, value.u64, cpu->a[thread], thread); + cmp(cpu, value.u64, cpu->a, thread); break; case CPY: /* CPY Immediate. */ case CPY_AB: /* CPY Absolute. */ case CPY_Z: /* CPY Zero Matrix. */ case CPY_IN: /* CPY Indirect. */ - cmp(cpu, value.u64, cpu->y[thread], thread); + cmp(cpu, value.u64, cpu->y, thread); break; case CPX: /* CPX Immediate. */ case CPX_AB: /* CPX Absolute. */ case CPX_Z: /* CPX Zero Matrix. */ case CPX_IN: /* CPX Indirect. */ - cmp(cpu, value.u64, cpu->x[thread], thread); + cmp(cpu, value.u64, cpu->x, thread); break; case ENT: /* ENd Thread. */ /* cpu->crt &= ~value; @@ -448,28 +435,21 @@ void *run(void *args) { if ((value >> i) & 1) cpu->pc[i+1] = cpu->pc[0]+(i+1);*/ break; - case INC: cpu->a[thread] = idr(cpu, cpu->a[thread], 1, thread); break; - case INB: cpu->b[thread] = idr(cpu, cpu->b[thread], 1, thread); break; - case INY: cpu->y[thread] = idr(cpu, cpu->y[thread], 1, thread); break; - case INX: cpu->x[thread] = idr(cpu, cpu->x[thread], 1, thread); break; - case DEC: cpu->a[thread] = idr(cpu, cpu->a[thread], 0, thread); break; - case DEB: cpu->b[thread] = idr(cpu, cpu->b[thread], 0, thread); break; - case DEY: cpu->y[thread] = idr(cpu, cpu->y[thread], 0, thread); break; - case DEX: cpu->x[thread] = idr(cpu, cpu->x[thread], 0, thread); break; + case INC: cpu->a = idr(cpu, cpu->a, 1, thread); break; + case INB: cpu->b = idr(cpu, cpu->b, 1, thread); break; + case INY: cpu->y = idr(cpu, cpu->y, 1, thread); break; + case INX: cpu->x = idr(cpu, cpu->x, 1, thread); break; + case DEC: cpu->a = idr(cpu, cpu->a, 0, thread); break; + case DEB: cpu->b = idr(cpu, cpu->b, 0, thread); break; + case DEY: cpu->y = idr(cpu, cpu->y, 0, thread); break; + case DEX: cpu->x = idr(cpu, cpu->x, 0, thread); break; case JSR_IN: /* JSR Indirect. */ case JSR: /* Jump to SubRoutine. */ case JSR_Z: /* JSR Zero Matrix. */ - value.u64 = cpu->pc[thread]; - addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-0] = value.u8[7]; - addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-1] = value.u8[6]; - addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-2] = value.u8[5]; - addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-3] = value.u8[4]; - addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-4] = value.u8[3]; - addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-5] = value.u8[2]; - addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-6] = value.u8[1]; - addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-7] = value.u8[0]; - cpu->sp[thread] -= 8; - cpu->pc[thread] = address.u64; + value.u64 = cpu->pc; + setreg(addr, -, (cpu->stk_st << 16)+cpu->sp, value.u8, +, 0, 7); + cpu->sp -= 8; + cpu->pc = address.u64; break; case INC_AB: /* INC Absolute. */ case INC_Z: /* INC Zero Matrix. */ @@ -478,19 +458,12 @@ void *run(void *args) { case NOP: /* No OPeration. */ break; case RTI: /* ReTurn from Interrupt routine. */ - cpu->sp[thread] += 1; - cpu->ps.u8[thread] = addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread])]; /* Falls through. */ + cpu->sp += 1; + cpu->ps.u8[thread] = addr[(cpu->stk_st << 16)+(cpu->sp)]; /* Falls through. */ case RTS: /* ReTurn from Subroutine. */ - cpu->sp[thread] += 8; - value.u8[0] = addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-7)]; - value.u8[1] = addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-6)]; - value.u8[2] = addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-5)]; - value.u8[3] = addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-4)]; - value.u8[4] = addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-3)]; - value.u8[5] = addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-2)]; - value.u8[6] = addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-1)]; - value.u8[7] = addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread] )]; - cpu->pc[thread] = value.u64; + cpu->sp += 8; + setreg(value.u8, +, 0, addr, -, (cpu->stk_st << 16)+cpu->sp, 7); + cpu->pc = value.u64; break; case DEC_AB: /* DEC Absolute. */ case DEC_Z: /* DEC Zero Matrix. */ @@ -506,39 +479,16 @@ void *run(void *args) { pthread_cond_wait(&cond, &mutex); pthread_mutex_unlock(&mutex); } - value.u64 = cpu->pc[thread]; - addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-0] = value.u8[7]; - addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-1] = value.u8[6]; - addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-2] = value.u8[5]; - addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-3] = value.u8[4]; - addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-4] = value.u8[3]; - addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-5] = value.u8[2]; - addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-6] = value.u8[1]; - addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-7] = value.u8[0]; - addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-8] = cpu->ps.u8[thread]; - cpu->sp[thread] -= 9; + value.u64 = cpu->pc; + setreg(addr, -, (cpu->stk_st << 16)+cpu->sp, value.u8, +, 0, 7); + addr[(cpu->stk_st << 16)+cpu->sp-8] = cpu->ps.u8[thread]; + cpu->sp -= 9; setflag(1, I); - if (opcode == BRK) { - value.u8[0] = addr[0xFFE0]; - value.u8[1] = addr[0xFFE1]; - value.u8[2] = addr[0xFFE2]; - value.u8[3] = addr[0xFFE3]; - value.u8[4] = addr[0xFFE4]; - value.u8[5] = addr[0xFFE5]; - value.u8[6] = addr[0xFFE6]; - value.u8[7] = addr[0xFFE7]; - } else { - value.u8[0] = addr[0xFFA0]; - value.u8[1] = addr[0xFFA1]; - value.u8[2] = addr[0xFFA2]; - value.u8[3] = addr[0xFFA3]; - value.u8[4] = addr[0xFFA4]; - value.u8[5] = addr[0xFFA5]; - value.u8[6] = addr[0xFFA6]; - value.u8[7] = addr[0xFFA7]; + setreg(value.u8, +, 0, addr, +, (opcode == BRK) ? 0xFFE0 : 0xFFA0, 7); + if (opcode == WAI) { kbd_rdy &= (uint8_t)~(1 << thread); } - cpu->pc[thread] = value.u64; + cpu->pc = value.u64; default: break; } @@ -636,15 +586,15 @@ int main(int argc, char **argv) { uint16_t vec = 0xFFC0; uint8_t offset; for (int i = 0; i < THREADS; i++) { - thr[i].sx.sp[i] = 0xFFFF; - thr[i].sx.stk_st[i] = i+1; + thr[i].sx.sp = 0xFFFF; + thr[i].sx.stk_st = i+1; offset = (i) ? ((i-1) << 3) : 0; vec = (i) ? 0xFF50 : 0xFFC0; - 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[vec+0+offset] + thr[i].sx.a = 0; + thr[i].sx.b = 0; + thr[i].sx.x = 0; + thr[i].sx.y = 0; + thr[i].sx.pc = (uint64_t)addr[vec+0+offset] | (uint64_t)addr[vec+1+offset] << 8 | (uint64_t)addr[vec+2+offset] << 16 | (uint64_t)addr[vec+3+offset] << 24 @@ -25,9 +25,37 @@ extern uint8_t subdbg; extern uint8_t step; extern uint8_t esc; +static inline uint8_t get_opsize(uint8_t prefix, uint8_t addrmode); + +enum sw_type {RS, AM, BYTE}; + #define setflag(flag, bit) ((flag)) ? (cpu->ps.u8[thread] |= bit) : (cpu->ps.u8[thread] &= ~bit) #define getflag(bit) (cpu->ps.u8[thread] & bit) +/* reg_expr, and val_expr are the arithmetic expressions + * that will be used for either the value, or register, such as '+', or '-'. + */ +#define setreg(reg, reg_expr, reg_idx, val, val_expr, val_idx, size) {\ + switch (size) {\ + case 7: reg[(reg_idx) reg_expr 7] = val[(val_idx) val_expr 7];\ + case 6: reg[(reg_idx) reg_expr 6] = val[(val_idx) val_expr 6];\ + case 5: reg[(reg_idx) reg_expr 5] = val[(val_idx) val_expr 5];\ + case 4: reg[(reg_idx) reg_expr 4] = val[(val_idx) val_expr 4];\ + case 3: reg[(reg_idx) reg_expr 3] = val[(val_idx) val_expr 3];\ + case 2: reg[(reg_idx) reg_expr 2] = val[(val_idx) val_expr 2];\ + case 1: reg[(reg_idx) reg_expr 1] = val[(val_idx) val_expr 1];\ + case 0: reg[(reg_idx) reg_expr 0] = val[(val_idx) val_expr 0];\ + }\ +} + +#define setreg_sw(reg, reg_idx, val, val_idx, prefix, addrmode, type) {\ + switch (type) {\ + case RS: setreg(reg, +, reg_idx, val, +, val_idx, (1 << (prefix >> 4))-1); break;\ + case AM: setreg(reg, +, reg_idx, val, +, val_idx, get_opsize(prefix, addrmode)); break;\ + }\ +} + + extern pthread_mutex_t mutex; extern pthread_mutex_t main_mutex; extern pthread_cond_t cond; @@ -39,6 +67,29 @@ extern void disasm(struct sux *cpu, uint64_t *operands, uint8_t lines, uint8_t o extern void io(uint64_t address, uint8_t rw); +static inline uint8_t get_opsize(uint8_t prefix, uint8_t addrmode) { + uint8_t id = (prefix & 0x0C) >> 2; + switch (addrmode) { + case ZM: + switch (id) { + case 2: return 5; + case 3: return 3; + case 1: return 2; + case 0: return 0; + } + break; + case ABS: + switch (id) { + case 3: return 7; + case 2: return 6; + case 1: return 4; + case 0: return 1; + } + break; + } + return 0; +} + static inline uint64_t get_addr(struct sux *cpu, uint64_t *tmpaddr, uint8_t opcode, uint8_t prefix, uint8_t thread) { union reg address; union reg value; @@ -49,7 +100,7 @@ static inline uint64_t get_addr(struct sux *cpu, uint64_t *tmpaddr, uint8_t opco case IMPL: break; case IMM: - address.u64 = cpu->pc[thread]; + address.u64 = cpu->pc; switch (opcode) { case PHB: case PHP: @@ -67,8 +118,8 @@ static inline uint64_t get_addr(struct sux *cpu, uint64_t *tmpaddr, uint8_t opco case ROL: case ROR: case ASR: - case ENT: ++cpu->pc[thread]; break; - default : cpu->pc[thread]+=(1 << (prefix >> 4)); + case ENT: ++cpu->pc; break; + default : cpu->pc+=(1 << (prefix >> 4)); /* Falls Through. */ case TXS: break; } break; @@ -79,21 +130,11 @@ static inline uint64_t get_addr(struct sux *cpu, uint64_t *tmpaddr, uint8_t opco case INDX: case INDY: tmp = 0; - address.u8[0] = addr[cpu->pc[thread]]; + address.u8[0] = addr[cpu->pc]; /* Unroll Loop by implementing Duff's Device. */ - switch ((prefix & 0x0C) >> 2) { - case 2: - address.u8[5] = addr[cpu->pc[thread]+5];++tmp; - address.u8[4] = addr[cpu->pc[thread]+4];++tmp; - case 3: - address.u8[3] = addr[cpu->pc[thread]+3];++tmp; - case 1: - address.u8[2] = addr[cpu->pc[thread]+2];++tmp; - address.u8[1] = addr[cpu->pc[thread]+1];++tmp; - case 0: - ++tmp; - } - cpu->pc[thread]+=tmp; + tmp = get_opsize(prefix, ZM)+1; + setreg_sw(address.u8, 0, addr, cpu->pc, prefix, ZM, AM); + cpu->pc+=tmp; #if debug && !bench *tmpaddr = address.u64; #endif @@ -103,43 +144,32 @@ static inline uint64_t get_addr(struct sux *cpu, uint64_t *tmpaddr, uint8_t opco uint64_t reg = 0; switch (optype[opcode]) { case ZMX: - address.u64 += cpu->x[thread]; + address.u64 += cpu->x; #if getclk iclk++; #endif break; case ZMY: - address.u64 += cpu->y[thread]; + address.u64 += cpu->y; #if getclk iclk++; #endif break; case INDX: - address.u64 += 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. */ + address.u64 += cpu->x; + #if getclk + iclk++; + #endif } else { - reg = cpu->y[thread]; /* No, so set reg to Y. */ + reg = cpu->y; #if getclk iclk++; #endif } - /* Falls Through. */ case IND: - value.u8[0] = addr[address.u64 ]; - value.u8[1] = addr[address.u64+1]; - value.u8[2] = addr[address.u64+2]; - value.u8[3] = addr[address.u64+3]; - value.u8[4] = addr[address.u64+4]; - value.u8[5] = addr[address.u64+5]; - value.u8[6] = addr[address.u64+6]; - value.u8[7] = addr[address.u64+7]; + setreg(value.u8, +, 0, addr, +, address.u64, 7); #if getclk iclk++; #endif @@ -149,26 +179,9 @@ static inline uint64_t get_addr(struct sux *cpu, uint64_t *tmpaddr, uint8_t opco } break; case ABS: - tmp = 0; - address.u8[0] = addr[cpu->pc[thread]];++tmp; - /* Unroll Loop by implementing Duff's Device. */ - switch ((prefix & 0x0C) >> 2) { - case 3: - address.u8[7] = addr[cpu->pc[thread]+7];++tmp; - case 2: - address.u8[6] = addr[cpu->pc[thread]+6];++tmp; - address.u8[5] = addr[cpu->pc[thread]+5];++tmp; - #if getclk - iclk++; - #endif - case 1: - address.u8[4] = addr[cpu->pc[thread]+4];++tmp; - address.u8[3] = addr[cpu->pc[thread]+3];++tmp; - address.u8[2] = addr[cpu->pc[thread]+2];++tmp; - case 0: - address.u8[1] = addr[cpu->pc[thread]+1];++tmp; - } - cpu->pc[thread]+=tmp; + tmp = get_opsize(prefix, ABS)+1; + setreg_sw(address.u8, 0, addr, cpu->pc, prefix, ABS, AM); + cpu->pc+=tmp; #if getclk iclk++; #endif @@ -179,39 +192,39 @@ static inline uint64_t get_addr(struct sux *cpu, uint64_t *tmpaddr, uint8_t opco } static inline void adc(struct sux *cpu, uint64_t value, uint8_t thread) { - uint64_t sum = cpu->a[thread]+value+getflag(C); + uint64_t sum = cpu->a+value+getflag(C); setflag(sum == 0, Z); setflag((sum >> 63), N); - setflag(((cpu->a[thread]^value) >> 63) && ((cpu->a[thread]^sum) >> 63), V); + setflag(((cpu->a^value) >> 63) && ((cpu->a^sum) >> 63), V); setflag((sum < value), C); - cpu->a[thread] = sum; + cpu->a = sum; } static inline void sbc(struct sux *cpu, uint64_t value, uint8_t thread) { - uint64_t sum = cpu->a[thread]-value-!getflag(C); + uint64_t sum = cpu->a-value-!getflag(C); setflag(sum == 0, Z); setflag(sum >> 63, N); - setflag(((cpu->a[thread]^value) >> 63) && ((cpu->a[thread]^sum) >> 63), V); + setflag(((cpu->a^value) >> 63) && ((cpu->a^sum) >> 63), V); setflag((sum > value), C); - cpu->a[thread] = sum; + cpu->a = sum; } static 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]; + case TBA: cpu->a = cpu->b; reg = cpu->a; break; + case TXA: cpu->a = cpu->x; reg = cpu->a; break; + case TYA: cpu->a = cpu->y; reg = cpu->a; break; + case TAB: cpu->b = cpu->a; reg = cpu->b; break; + case TAY: cpu->y = cpu->a; reg = cpu->y; break; + case TXY: cpu->y = cpu->x; reg = cpu->y; break; + case TAX: cpu->x = cpu->a; reg = cpu->x; break; + case TYX: cpu->x = cpu->y; reg = cpu->x; break; + case TSX: cpu->x = cpu->sp & 0xFFFF; cpu->x = cpu->stk_st << 16; break; + case TXS: cpu->sp = cpu->x; if (prefix == 0x13 && (value == thread+1 || value > 8)) { - cpu->stk_st[thread] = value & 0xFF; - cpu->stk_st[thread] += value << 16; - cpu->pc[thread]+=2; + cpu->stk_st = value & 0xFF; + cpu->stk_st += value << 16; + cpu->pc+=2; } break; } @@ -219,125 +232,100 @@ static inline void transfer(struct sux *cpu, uint64_t value, uint8_t opcode, uin setflag(reg >> 63, N); } -static inline void push(struct sux *cpu, uint64_t value, uint64_t reg, uint8_t thread) { - union { - uint64_t reg; - uint8_t byte[8]; - } r; - r.reg = reg; - uint8_t size = (value > 0) ? value-1 : 0; +static inline void push(struct sux *cpu, uint64_t size, uint64_t value, uint8_t thread) { + union reg reg; + reg.u64 = value; + size = (size > 0) ? size-1 : 0; uint8_t tmp = (size <= 7) ? size : 7; - /* 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]--; - } + setreg(addr, -, (cpu->stk_st << 16)+cpu->sp, reg.u8, +, 0, tmp); + cpu->sp -= (tmp+1); } -static inline uint64_t pull(struct sux *cpu, uint64_t value, uint8_t thread) { - union { - uint64_t reg; - uint8_t byte[8]; - } r; - r.reg = 0; - uint8_t size = (value > 0) ? value-1 : 0; +static inline uint64_t pull(struct sux *cpu, uint64_t size, uint8_t thread) { + union reg reg; + reg.u64 = 0; + size = (size > 0) ? size-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]]; - } - return r.reg; + cpu->sp += (tmp+1); + setreg(reg.u8, +, 0, addr, -, (cpu->stk_st << 16)+cpu->sp, tmp); + return reg.u64; } static 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); + cpu->a &= value; + setflag(cpu->a == 0, Z); + setflag(cpu->a >> 63, N); } static 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); + cpu->a |= value; + setflag(cpu->a == 0, Z); + setflag(cpu->a >> 63, N); } static 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); + cpu->a ^= value; + setflag(cpu->a == 0, Z); + setflag(cpu->a >> 63, N); } static inline void lsl(struct sux *cpu, uint64_t value, uint8_t thread) { - uint64_t sum = (value < 64) ? cpu->a[thread] << value : 0; + uint64_t sum = (value < 64) ? cpu->a << value : 0; setflag(sum == 0, Z); setflag(sum >> 63, N); - setflag(cpu->a[thread] >> (64-value), C); - cpu->a[thread] = sum; + setflag(cpu->a >> (64-value), C); + cpu->a = sum; } static inline void lsr(struct sux *cpu, uint64_t value, uint8_t thread) { - uint64_t sum = (value < 64) ? cpu->a[thread] >> value : 0; + uint64_t sum = (value < 64) ? cpu->a >> value : 0; setflag(sum == 0, Z); setflag(sum >> 63, N); - setflag(cpu->a[thread] & 1, C); - cpu->a[thread] = sum; + setflag(cpu->a & 1, C); + cpu->a = sum; } static 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; + uint8_t sign = cpu->a >> 63; + uint64_t sum = (value < 64) ? (cpu->a >> value) | ((uint64_t)sign << 63) : 0; setflag(sum == 0, Z); setflag(sum >> 63, N); - setflag(cpu->a[thread] & 1, C); - cpu->a[thread] = sum; + setflag(cpu->a & 1, C); + cpu->a = sum; } static inline void rol(struct sux *cpu, uint64_t value, uint8_t thread) { - uint64_t sum = cpu->a[thread] << value; + uint64_t sum = cpu->a << 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; + setflag(cpu->a >> (uint64_t)(64-value), C); + cpu->a = sum; } static inline void ror(struct sux *cpu, uint64_t value, uint8_t thread) { - uint64_t sum = cpu->a[thread] >> value; + uint64_t sum = cpu->a >> 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; + setflag(cpu->a & 1, C); + cpu->a = sum; } static inline void mul(struct sux *cpu, uint64_t value, uint8_t thread) { - uint64_t sum = cpu->a[thread]*value; - cpu->a[thread] = sum; + uint64_t sum = cpu->a*value; + cpu->a = sum; setflag(sum == 0, Z); setflag(sum >> 63, N); - setflag(!((cpu->a[thread]^value) >> 63) && ((cpu->a[thread]^sum) >> 63), V); + setflag(!((cpu->a^value) >> 63) && ((cpu->a^sum) >> 63), V); } static inline void divd(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread) { - uint64_t sum = cpu->a[thread]/value; + uint64_t sum = cpu->a/value; if (opcode != DAB) { - cpu->b[thread] = cpu->a[thread] % value; + cpu->b = cpu->a % value; } else { - value = cpu->b[thread]; - cpu->x[thread] = cpu->a[thread] % value; + value = cpu->b; + cpu->x = cpu->a % value; } - cpu->a[thread] = sum; + cpu->a = sum; setflag(sum == 0, Z); setflag((sum >> 63), N); } @@ -366,19 +354,7 @@ static inline void idm(struct sux *cpu, uint64_t address, uint8_t prefix, uint8_ union reg value; value.u64 = 0; /* Unroll Loop by implementing Duff's Device. */ - value.u8[0] = addr[address]; - switch (1 << (prefix >> 4)) { - case 8: - value.u8[7] = addr[address+7]; - value.u8[6] = addr[address+6]; - value.u8[5] = addr[address+5]; - value.u8[4] = addr[address+4]; - case 4: - value.u8[3] = addr[address+3]; - value.u8[2] = addr[address+2]; - case 2: - value.u8[1] = addr[address+1]; - } + setreg_sw(value.u8, 0, addr, address, prefix, 0, RS); if (inc) { value.u64++; } else { @@ -386,40 +362,15 @@ static inline void idm(struct sux *cpu, uint64_t address, uint8_t prefix, uint8_ } setflag(value.u64 == 0, Z); setflag(value.u64 >> 7, N); - addr[address] = value.u8[0]; + setreg_sw(addr, address, value.u8, 0, prefix, 0, RS); io(address, 0); - switch (1 << (prefix >> 4)) { - case 8: - addr[address+7] = value.u8[7]; - addr[address+6] = value.u8[6]; - addr[address+5] = value.u8[5]; - addr[address+4] = value.u8[4]; - case 4: - addr[address+3] = value.u8[3]; - addr[address+2] = value.u8[2]; - case 2: - addr[address+1] = value.u8[1]; - } } static inline uint64_t load(struct sux *cpu, uint64_t address, uint64_t reg, uint8_t prefix, uint8_t thread) { io(address, 1); union reg value; value.u64 = reg; - /* Unroll Loop by implementing Duff's Device. */ - value.u8[0] = addr[address]; - switch (1 << (prefix >> 4)) { - case 8: - value.u8[7] = addr[address+7]; - value.u8[6] = addr[address+6]; - value.u8[5] = addr[address+5]; - value.u8[4] = addr[address+4]; - case 4: - value.u8[3] = addr[address+3]; - value.u8[2] = addr[address+2]; - case 2: - value.u8[1] = addr[address+1]; - } + setreg_sw(value.u8, 0, addr, address, prefix, 0, RS); setflag(value.u64 == 0, Z); setflag(value.u64 >> 63, N); return value.u64; @@ -428,7 +379,7 @@ static inline uint64_t load(struct sux *cpu, uint64_t address, uint64_t reg, uin static inline void store(struct sux *cpu, uint64_t address, uint64_t reg, uint8_t prefix, uint8_t thread) { union reg value; value.u64 = reg; - addr[address] = value.u8[0]; + setreg_sw(addr, address, value.u8, 0, prefix, 0, RS); #if (IO || debug) && !branch #if keypoll pthread_mutex_lock(&mutex); @@ -438,18 +389,5 @@ static inline void store(struct sux *cpu, uint64_t address, uint64_t reg, uint8_ pthread_mutex_unlock(&mutex); #endif #endif - /* Unroll Loop by implementing Duff's Device. */ - switch (1 << (prefix >> 4)) { - case 8: - addr[address+7] = value.u8[7]; - addr[address+6] = value.u8[6]; - addr[address+5] = value.u8[5]; - addr[address+4] = value.u8[4]; - case 4: - addr[address+3] = value.u8[3]; - addr[address+2] = value.u8[2]; - case 2: - addr[address+1] = value.u8[1]; - } } |