#include "opcode.h" #include #include #include #include #if bench #include #else #include #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. */ uint64_t tclk; /* Total Clock cycles. */ #endif const uint16_t tv = 0xFF50; /* Starting address of the Thread Vectors. */ #if !IO 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; struct suxthr { struct sux sx; uint8_t th; }; #if bench double ipc; struct timeval str[THREADS], en[THREADS]; #endif void *run(void *args) { struct suxthr *thr = (void *)args; struct sux *cpu = &thr->sx; uint8_t thread = thr->th; uint64_t address = 0; uint8_t prefix = 0; uint8_t opcode = 0; uint64_t sum = 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; } #if keypoll pthread_mutex_lock(&mutex); #endif werase(scr); #if keypoll pthread_mutex_unlock(&mutex); #endif #endif for (;;) { address = 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; } #if keypoll pthread_mutex_lock(&mutex); #endif wmove(scr, lines, 0); wclrtoeol(scr); wprintw(scr, "pc: $%04"PRIX64 ", a: $%016"PRIX64 ", b: $%016"PRIX64 ", x: $%016"PRIX64 ", y: $%016"PRIX64 , cpu->pc[thread] , cpu->a[thread] , cpu->b[thread] , cpu->x[thread] , cpu->y[thread]); wprintw(scr, ", sp: $%04X" ", ps: $%02"PRIX64 ", inst: " , cpu->sp[thread] , cpu->ps); #if keypoll pthread_mutex_unlock(&mutex); #endif #endif address = cpu->pc[thread]; ++cpu->pc[thread]; #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; } 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; } #if debug && !bench #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); } }*/ } #if keypoll pthread_mutex_unlock(&mutex); #endif lines+=1; #endif switch(opcode) { case CPS: /* Clear Processor Status. */ cpu->ps = 0; break; case AAB: /* Add Accumulator with carry by B register. */ value = cpu->b[thread]; /* Falls Through. */ 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); 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]--; } break; case TAY: /* Transfer Accumulator to Y. */ case TAX: /* Transfer Accumulator to Y. */ case TYX: /* Transfer Y to X. */ case TYA: /* Transfer Y to Accumulator. */ case TXA: /* Transfer X to Accumulator. */ case TXY: /* Transfer X to Y. */ case TAB: /* Transfer Accumulator to B. */ 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); break; case JMP: /* JMP Absolute. */ case JMP_Z: /* JMP Zero Matrix. */ case JMP_IN: /* JMP Indirect. */ cpu->pc[thread] = address; break; case SAB: /* Subtract Accumulator with carry by B register. */ value = cpu->b[thread]; /* Falls Through. */ 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; 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; } 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); break; case STT: /* STart Thread. */ cpu->crt |= value; for (uint8_t i = 0; i < 7; i++) { if ((value >> i) & 1) { address = (uint64_t)addr[tv+(i<<3)] | (uint64_t)addr[tv+1+(i<<3)] << 8 | (uint64_t)addr[tv+2+(i<<3)] << 16 | (uint64_t)addr[tv+3+(i<<3)] << 24 | (uint64_t)addr[tv+4+(i<<3)] << 32 | (uint64_t)addr[tv+5+(i<<3)] << 40 | (uint64_t)addr[tv+6+(i<<3)] << 48 | (uint64_t)addr[tv+7+(i<<3)] << 56; cpu->pc[i+1] = address; } } break; case BPO: /* BPO Absolute. */ case BPO_Z: /* BPO Zero Matrix. */ if (!getflag(N)) { cpu->pc[thread] = address; } break; case OAB: /* bitwise Or with Accumulator, and B register. */ value = cpu->b[thread]; /* Falls Through. */ 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); break; case SEI: /* SEt Interrupt. */ setflag(1, I); break; case BNG: /* BNG Absolute. */ case BNG_Z: /* BNG Zero Matrix. */ if (getflag(N)) { cpu->pc[thread] = address; } break; case XAB: /* bitwise Xor with Accumulator, and B register. */ value = cpu->b[thread]; /* Falls Through. */ 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); break; case CLI: /* CLear Interrupt. */ setflag(0, I); break; case BCS: /* BCS Absolute. */ case BCS_Z: /* BCS Zero Matrix. */ if (getflag(C)) { cpu->pc[thread] = address; } break; case LLB: /* Logical shift Left accumulator by B. */ value = cpu->b[thread]; /* Falls Through. */ 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; break; case SEC: /* SEt Carry flag.*/ setflag(1, C); break; case STA: /* STA Absolute. */ case STY: /* STY Absolute. */ case STX: /* STX Absolute. */ case STB: /* STB Absolute. */ case STA_Z: /* STA Zero Matrix. */ case STY_Z: /* STY Zero Matrix. */ case STX_Z: /* STX Zero Matrix. */ case STB_Z: /* STB Zero Matrix. */ case STA_ZX: /* STA Zero Matrix, Indexed with X. */ case STY_ZX: /* STY Zero Matrix, Indexed with X. */ case STX_ZY: /* STX Zero Matrix, Indexed with Y. */ case STB_ZX: /* STB Zero Matrix, Indexed with X. */ case STA_ZY: /* STA Zero Matrix, Indexed with Y. */ case STB_ZY: /* STB Zero Matrix, Indexed with Y. */ case STY_IN: /* STY Indirect. */ case STX_IN: /* STX Indirect. */ case STA_IN: /* STA Indirect. */ case STB_IN: /* STB Indirect. */ case STA_IX: /* STA Indexed Indirect. */ 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; } step = addr[STEP_ADDR] || cpu->pc[thread] == CTRL_ADDR; break; case BCC: /* BCC Absolute. */ case BCC_Z: /* BCC Zero Matrix. */ if (!getflag(C)) { cpu->pc[thread] = address; } break; case LRB: /* Logical shift Right accumulator by B. */ value = cpu->b[thread]; /* Falls Through. */ 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; 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; break; case CLC: /* CLear Carry flag. */ setflag(0, C); break; case LDB: /* LDB Immediate. */ case LDA: /* LDA Immediate. */ case LDY: /* LDY Immediate. */ case LDX: /* LDX Immediate. */ case LDB_AB: /* LDB Absolute. */ case LDA_AB: /* LDA Absolute. */ case LDY_AB: /* LDY Absolute. */ case LDX_AB: /* LDX Absolute. */ case LDB_Z: /* LDB Zero Matrix. */ case LDA_Z: /* LDA Zero Matrix. */ case LDY_Z: /* LDY Zero Matrix. */ case LDX_Z: /* LDX Zero Matrix. */ case LDB_ZX: /* LDB Zero Matrix, Indexed with X. */ case LDA_ZX: /* LDA Zero Matrix, Indexed with X. */ case LDY_ZX: /* LDY Zero Matrix, Indexed with X. */ case LDX_ZY: /* LDX Zero Matrix, Indexed with Y. */ case LDB_ZY: /* LDB Zero Matrix, Indexed with Y. */ case LDA_ZY: /* LDA Zero Matrix, Indexed with Y. */ case LDB_IN: /* LDY Indirect. */ case LDA_IN: /* LDX Indirect. */ case LDY_IN: /* LDB Indirect. */ case LDX_IN: /* LDA Indirect. */ case LDB_IX: /* LDB Indexed Indirect. */ 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); break; case BEQ: /* BEQ Absolute. */ case BEQ_Z: /* BEQ Zero Matrix. */ if (getflag(Z)) { cpu->pc[thread] = address; } break; case RLB: /* Rotate Left accumulator by B. */ value = cpu->b[thread]; /* Falls Through. */ 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; break; case BNE: /* BNE Absolute. */ case BNE_Z: /* BNE Zero Matrix. */ if (!getflag(Z)) { cpu->pc[thread] = address; } break; case RRB: /* Rotate Right accumulator by B. */ value = cpu->b[thread]; /* Falls Through. */ 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; break; case BVS: /* BVS Absolute. */ case BVS_Z: /* BVS Zero Matrix. */ if (getflag(V)) { cpu->pc[thread] = address; } break; case MAB: /* Multiply Accumulator by B. */ value = cpu->b[thread]; /* Falls Through. */ 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); break; case BVC: /* BVC Absolute. */ case BVC_Z: /* BVC Zero Matrix. */ if (!getflag(V)) { cpu->pc[thread] = address; } break; case DIV: /* DIV Immediate. */ 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); break; case CLV: /* CLear oVerflow flag. */ setflag(0, V); break; case CAB: /* Compare Accumulator, and B. */ value = cpu->b[thread]; /* Falls Through. */ case CPB: /* CPB Immediate. */ case CMP: /* CMP Immediate. */ case CPY: /* CPY Immediate. */ case CPX: /* CPX Immediate. */ case CPY_AB: /* CPY Absolute. */ case CPX_AB: /* CPX Absolute. */ case CMP_AB: /* CMP Absolute. */ case CPB_AB: /* CPB Absolute. */ case CPY_Z: /* CPY Zero Matrix. */ case CPX_Z: /* CPX Zero Matrix. */ case CMP_Z: /* CMP Zero Matrix. */ case CPB_Z: /* CPB Zero Matrix. */ case CPY_IN: /* CMP Indirect. */ case CPX_IN: /* CPY Indirect. */ case CMP_IN: /* CPX Indirect. */ case CPB_IN: /* CPB Indirect. */ case CMP_IX: /* CMP Indexed Indirect. */ 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); break; case ENT: /* ENd Thread. */ cpu->crt &= ~value; for (uint8_t i = 0; i < 7; i++) if ((value >> i) & 1) cpu->pc[i+1] = cpu->pc[0]+(i+1); break; case RTI: /* ReTurn from Interrupt routine. */ cpu->sp[thread] += 9; cpu->ps = addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-8)] << (thread << 3); cpu->pc[thread] = (uint64_t)addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-7)]; cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-6)] << 8; cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-5)] << 16; cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-4)] << 24; cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-3)] << 32; cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-2)] << 40; cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-1)] << 48; cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << 56; break; case INC: /* INC Accumulator. */ 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); 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); break; case JSR_IN: /* JSR Indirect. */ case JSR: /* Jump to SubRoutine. */ case JSL: /* Jump to Subroutine Long. */ addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-0] = (uint64_t)cpu->pc[thread] >> (7<<3); addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-1] = (uint64_t)cpu->pc[thread] >> (6<<3); addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-2] = (uint64_t)cpu->pc[thread] >> (5<<3); addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-3] = (uint64_t)cpu->pc[thread] >> (4<<3); addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-4] = (uint64_t)cpu->pc[thread] >> (3<<3); addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-5] = (uint64_t)cpu->pc[thread] >> (2<<3); addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-6] = (uint64_t)cpu->pc[thread] >> (1<<3); addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]-7] = (uint64_t)cpu->pc[thread] & (0xFF); cpu->sp[thread] -= 8; cpu->pc[thread] = address; break; case INC_AB: /* INC Absolute. */ case INC_Z: /* INC Zero Matrix. */ addr[address]++; setflag(addr[address] == 0, Z); setflag(addr[address] >> 7, N); step = addr[STEP_ADDR] || cpu->pc[thread] == CTRL_ADDR; break; case NOP: /* No OPeration. */ break; case RTS: /* ReTurn from Subroutine. */ case RTL: /* ReTurn from subroutine Long. */ cpu->sp[thread] += 8; cpu->pc[thread] = (uint64_t)addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-7)] & (0xFF); cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-6)] << (1<<3); cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-5)] << (2<<3); cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-4)] << (3<<3); cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-3)] << (4<<3); cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-2)] << (5<<3); cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-1)] << (6<<3); cpu->pc[thread] += (uint64_t)addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-0)] << (7<<3); break; case DEC_AB: /* DEC Absolute. */ case DEC_Z: /* DEC Zero Matrix. */ addr[address]--; setflag(addr[address] == 0, Z); setflag(addr[address] >> 7, N); step = addr[STEP_ADDR] || cpu->pc[thread] == CTRL_ADDR; break; case BRK: /* BReaK. */ case WAI: /* WAit for Interrupt. */ if (opcode == WAI) { pthread_mutex_lock(&main_mutex); pthread_cond_signal(&main_cond); pthread_mutex_unlock(&main_mutex); pthread_mutex_lock(&mutex); pthread_cond_wait(&cond, &mutex); pthread_mutex_unlock(&mutex); } addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] >> 56; addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-1)] = (uint64_t)cpu->pc[thread] >> 48; addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-2)] = (uint64_t)cpu->pc[thread] >> 40; addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-3)] = (uint64_t)cpu->pc[thread] >> 32; addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-4)] = (uint64_t)cpu->pc[thread] >> 24; addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-5)] = (uint64_t)cpu->pc[thread] >> 16; addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-6)] = (uint64_t)cpu->pc[thread] >> 8; addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-7)] = (uint64_t)cpu->pc[thread] & 0xFF; addr[(cpu->stk_st[thread] << 16)+(cpu->sp[thread]-8)] = (uint64_t)cpu->ps >> (thread << 3); cpu->sp[thread] -= 9; setflag(1, I); if (opcode == BRK) { cpu->pc[thread] = (uint64_t)addr[0xFFE0]; cpu->pc[thread] += (uint64_t)addr[0xFFE1] << 8; cpu->pc[thread] += (uint64_t)addr[0xFFE2] << 16; cpu->pc[thread] += (uint64_t)addr[0xFFE3] << 24; cpu->pc[thread] += (uint64_t)addr[0xFFE4] << 32; cpu->pc[thread] += (uint64_t)addr[0xFFE5] << 40; cpu->pc[thread] += (uint64_t)addr[0xFFE6] << 48; cpu->pc[thread] += (uint64_t)addr[0xFFE7] << 56; } else { cpu->pc[thread] = (uint64_t)addr[0xFFA0] | (uint64_t)addr[0xFFA1] << 8 | (uint64_t)addr[0xFFA2] << 16 | (uint64_t)addr[0xFFA3] << 24 | (uint64_t)addr[0xFFA4] << 32 | (uint64_t)addr[0xFFA5] << 40 | (uint64_t)addr[0xFFA6] << 48 | (uint64_t)addr[0xFFA7] << 56; kbd_rdy &= (uint8_t)~(1 << thread); } break; default: break; } #if !IO ins++; #endif #if !bench if (step) { pthread_mutex_lock(&main_mutex); pthread_cond_signal(&main_cond); pthread_mutex_unlock(&main_mutex); pthread_mutex_lock(&mutex); pthread_cond_wait(&cond, &mutex); pthread_mutex_unlock(&mutex); #if debug wrefresh(scr); #endif } #endif #if debug && !bench #if keypoll pthread_mutex_lock(&mutex); #endif wmove(scr, (6*thread)+1, 0); wprintw(scr, "Instructions executed: %"PRIu64, ins); #if getclk wprintw(scr, ", Clock cycles: %"PRIu64, iclk); #endif if (!step && !subdbg) { wrefresh(scr); } #if keypoll pthread_mutex_unlock(&mutex); #endif #elif bench if (ins >= BENCH_INST) { pthread_mutex_lock(&main_mutex); threads_done++; inst[thread] = ins; #if getclk clk[thread] = iclk; #endif pthread_cond_signal(&main_cond); pthread_mutex_unlock(&main_mutex); gettimeofday(&en[thread], 0); break; } #endif } return NULL; } int main(int argc, char **argv) { struct suxthr thr[THREADS]; char *tmp = malloc(2048); addr = malloc(0x04000000); #if bench inss = 0; #endif int v = 0; #if debug subdbg = !strcmp(argv[1], "programs/subeditor.s"); #endif if (argc != 2) { if (asmmon("stdin") == 2) { return 0; } } else { if (asmmon(argv[1]) == 2) { return 0; } } sprintf(tmp, "\033[2J\033[H"); fwrite(tmp, sizeof(char), strlen(tmp), stdout); fflush(stdout); #if !bench if(!scr) { scr = initscr(); } nodelay(stdscr, 0); crmode(); noecho(); nl(); curs_set(1); werase(scr); scrollok(scr, 1); start_color(); use_default_colors(); init_pair(1, COLOR_WHITE, -1); attron(COLOR_PAIR(1) | A_BOLD); wmove(scr, 0, 0); wrefresh(scr); #endif pthread_t therads[THREADS]; int result; 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; 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] | (uint64_t)addr[vec+1+offset] << 8 | (uint64_t)addr[vec+2+offset] << 16 | (uint64_t)addr[vec+3+offset] << 24 | (uint64_t)addr[vec+4+offset] << 32 | (uint64_t)addr[vec+5+offset] << 40 | (uint64_t)addr[vec+6+offset] << 48 | (uint64_t)addr[vec+7+offset] << 56; thr[i].th = i; #if !IO inst[i] = 0; #endif result = pthread_create(&therads[i], NULL, run, &thr[i]); assert(!result); } int c = 0; uint8_t step_key = 0; #if !bench werase(scr); #endif while (threads_done < THREADS) { #if !bench int x, y; if ((step_key && step && !kbd_rdy) || !step || kbd_rdy) { if ((c != EOF && c !=-1)) { #if !keypoll pthread_mutex_lock(&mutex); pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); #endif pthread_mutex_lock(&main_mutex); curs_set(0); pthread_cond_wait(&main_cond, &main_mutex); pthread_mutex_unlock(&main_mutex); curs_set(1); c = 0; step_key = 0; addr[CTRL_ADDR] = 0; wrefresh(scr); } } #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; } if (kbd_rdy) { switch (c) { case ERR: addr[CTRL_ADDR] = 0; break; default: if (kbd_rdy && c < 0x100) { addr[RX_ADDR] = (uint8_t)c; addr[CTRL_ADDR] = 1; #if debug && !bench wmove(scr, getmaxy(scr)-1, 0); wclrtoeol(scr); wprintw(scr, "c: %i", c); wmove(scr, y, x); #endif } break; } } else { if (step) { step = !(c == 18); step_key = (c == 19); } } addr[STEP_ADDR] = step; #if keypoll pthread_mutex_unlock(&mutex); #endif #else pthread_mutex_lock(&main_mutex); pthread_cond_wait(&main_cond, &main_mutex); pthread_mutex_unlock(&main_mutex); #endif } #if bench if (threads_done == THREADS) { double tm_sec, tm_usec, tm[THREADS], ttm; #if getclk double clkspd; double mhz; #endif double ips[THREADS]; double ipst; for (int i = 0; i < THREADS; i++) { tm_sec = (en[i].tv_sec - str[i].tv_sec); tm_usec = (en[i].tv_usec-str[i].tv_usec); tm[i] = (tm_sec*1000000)+(tm_usec); ips[i] = inst[i]/tm[i]; if (i) { inss += inst[i]; ttm += tm[i]; ipst += ips[i]; #if getclk tclk += clk[i]; #endif } else { inss = inst[i]; ttm = tm[i]; ipst = ips[i]; #if getclk tclk = clk[i]; #endif } #if getclk clkspd = (tm[i]/1000000)*1000000/clk[i]; mhz = 1000000.0/clkspd/1000000; #endif sprintf(tmp, "Instructions executed for thread %i: %"PRIu64", Instructions per Second for thread %i in MIPS: %f, tm: %f\n", i, inst[i], i, ips[i], tm[i]/1000000); fwrite(tmp, sizeof(char), strlen(tmp), stdout); } sprintf(tmp, "Total Instructions executed: %"PRIu64", Total Instructions per Second in MIPS: %f", inss, ipst); fwrite(tmp, sizeof(char), strlen(tmp), stdout); #if getclk clkspd = (ttm/1000000)*1000000/tclk; mhz = 1000000.0/clkspd/1000000; sprintf(tmp, ", Clock cycles: %"PRIu64", Clock Speed in MHz: %f", tclk, mhz); fwrite(tmp, sizeof(char), strlen(tmp), stdout); #endif sprintf(tmp, ", tm: %f\n", ttm/1000000); fwrite(tmp, sizeof(char), strlen(tmp), stdout); fflush(stdout); free(tmp); } #endif free(addr); return 0; }