#include "sux.h" #include #include #include #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 bench uint64_t inss; #endif #if debug uint8_t subdbg; #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; uint8_t *addr; uint8_t kbd_rdy; WINDOW *scr; 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; uint8_t prefix = 0; uint8_t opcode = 0; uint8_t esc = 0; union reg address; union reg value; #if getclk uint64_t iclk = 0; #endif #if !IO uint64_t ins = 0; #endif #if !bench uint8_t lines = (6*thread)+2; #endif #if debug && !bench 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 uint64_t tmpaddr = 0; #if bench gettimeofday(&str[thread], 0); #endif 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; } #if keypoll pthread_mutex_lock(&mutex); #endif for (uint8_t i = (24*thread)+2; i <= 24*(thread+1); i++) { wmove(scr, i, 0); waddch(scr, (i == lines) ? '>' : ' '); } 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, ", 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]; #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]; } #if getclk ++iclk; #endif } #if debug && !bench #if keypoll pthread_mutex_lock(&mutex); #endif uint64_t operands[3]; operands[0] = value.u64; operands[1] = address.u64; operands[2] = tmpaddr; disasm(cpu, operands, lines, opcode, prefix, thread); lines+=1; #if keypoll pthread_mutex_unlock(&mutex); #endif #endif switch(opcode) { case CPS: /* Clear Processor Status. */ cpu->ps.u64 = 0; break; case AAB: /* Add Accumulator with carry by B register. */ value.u64 = cpu->b[thread]; /* Falls Through. */ case ADC: /* ADC Immediate. */ case ADC_AB: /* ADC Absolute. */ case ADC_Z: /* ADC Zero Matrix. */ adc(cpu, value.u64, 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. */ push(cpu, value.u64, opcode, 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. */ transfer(cpu, value.u64, opcode, prefix, thread); break; case JMP: /* JMP Absolute. */ case JMP_Z: /* JMP Zero Matrix. */ case JMP_IN: /* JMP Indirect. */ cpu->pc[thread] = address.u64; break; case SAB: /* Subtract Accumulator with carry by B register. */ value.u64 = cpu->b[thread]; /* Falls Through. */ case SBC: /* SBC Immediate. */ case SBC_AB: /* SBC Absolute. */ case SBC_Z: /* SBC Zero Matrix. */ sbc(cpu, value.u64, 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. */ pull(cpu, value.u64, opcode, thread); break; case ABA: /* bitwise And with Accumulator, and B register. */ value.u64 = cpu->b[thread]; /* Falls Through. */ case AND: /* AND Immediate. */ case AND_AB: /* AND Absolute. */ case AND_Z: /* AND Zero Matrix. */ and(cpu, value.u64, thread); 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.u64; } break; case OAB: /* bitwise Or with Accumulator, and B register. */ value.u64 = cpu->b[thread]; /* Falls Through. */ case ORA: /* ORA Immediate. */ case ORA_AB: /* ORA Absolute. */ case ORA_Z: /* ORA Zero Matrix. */ or(cpu, value.u64, thread); 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.u64; } break; case XAB: /* bitwise Xor with Accumulator, and B register. */ value.u64 = cpu->b[thread]; /* Falls Through. */ case XOR: /* XOR Immediate. */ case XOR_AB: /* XOR Absolute. */ case XOR_Z: /* XOR Zero Matrix. */ xor(cpu, value.u64, thread); 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.u64; } break; case LLB: /* Logical shift Left accumulator by B. */ value.u64 = cpu->b[thread]; /* Falls Through. */ case LSL: /* LSL Immediate. */ case LSL_AB: /* LSL Absolute. */ case LSL_Z: /* LSL Zero Matrix. */ lsl(cpu, value.u64, thread); 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. */ store(cpu, address.u64, &esc, opcode, prefix, thread); 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.u64; } break; case LRB: /* Logical shift Right accumulator by B. */ value.u64 = cpu->b[thread]; /* 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. */ case ASR: /* ASR Immediate. */ case ASR_AB: /* ASR Absolute. */ case ASR_Z: /* ASR Zero Matrix. */ asr(cpu, value.u64, thread); 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. */ load(cpu, address.u64, &esc, opcode, prefix, thread); break; case BEQ: /* BEQ Absolute. */ case BEQ_Z: /* BEQ Zero Matrix. */ if (getflag(Z)) { cpu->pc[thread] = address.u64; } break; case RLB: /* Rotate Left accumulator by B. */ value.u64 = cpu->b[thread]; /* Falls Through. */ case ROL: /* ROL Immediate. */ case ROL_AB: /* ROL Absolute. */ case ROL_Z: /* ROL Zero Matrix. */ rol(cpu, value.u64, thread); break; case BNE: /* BNE Absolute. */ case BNE_Z: /* BNE Zero Matrix. */ if (!getflag(Z)) { cpu->pc[thread] = address.u64; } break; case RRB: /* Rotate Right accumulator by B. */ value.u64 = cpu->b[thread]; /* Falls Through. */ case ROR: /* ROR Immediate. */ case ROR_AB: /* ROR Absolute. */ case ROR_Z: /* ROR Zero Matrix. */ ror(cpu, value.u64, thread); break; case BVS: /* BVS Absolute. */ case BVS_Z: /* BVS Zero Matrix. */ if (getflag(V)) { cpu->pc[thread] = address.u64; } break; case MAB: /* Multiply Accumulator by B. */ value.u64 = cpu->b[thread]; /* Falls Through. */ case MUL: /* MUL Immediate. */ case MUL_AB: /* MUL Absolute. */ case MUL_Z: /* MUL Zero Matrix. */ mul(cpu, value.u64, thread); break; case BVC: /* BVC Absolute. */ case BVC_Z: /* BVC Zero Matrix. */ if (!getflag(V)) { cpu->pc[thread] = address.u64; } break; case DIV: /* DIV Immediate. */ case DAB: /* Divide Accumulator by B. */ case DIV_AB: /* DIV Absolute. */ case DIV_Z: /* DIV Zero Matrix. */ divd(cpu, value.u64, opcode, thread); break; case CLV: /* CLear oVerflow flag. */ setflag(0, V); break; case CAB: /* Compare Accumulator, and B. */ value.u64 = 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. */ cmp(cpu, value.u64, opcode, thread); 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 INC: /* INC Accumulator. */ case INB: case INY: case INX: incr(cpu, opcode, thread); break; case DEC: /* DEC Accumulator. */ case DEB: case DEY: case DEX: decr(cpu, opcode, 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; break; case INC_AB: /* INC Absolute. */ case INC_Z: /* INC Zero Matrix. */ incm(cpu, address.u64, thread); step = addr[STEP_ADDR] || cpu->pc[thread] == CTRL_ADDR; break; 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. */ 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; break; case DEC_AB: /* DEC Absolute. */ case DEC_Z: /* DEC Zero Matrix. */ decm(cpu, address.u64, thread); 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); } 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; 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]; kbd_rdy &= (uint8_t)~(1 << thread); } cpu->pc[thread] = value.u64; 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 (argc != 2) { if (asmmon("stdin") == 2) { return 0; } } else { #if debug subdbg = !strcmp(argv[1], "programs/subeditor.s"); #endif if (asmmon(argv[1]) == 2) { return 0; } } sprintf(tmp, "\033[2J\033[H"); fwrite(tmp, sizeof(char), strlen(tmp), stdout); fflush(stdout); 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); 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; uint8_t end = 0; werase(scr); while (threads_done < THREADS && !end) { #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 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) { 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 } endwin(); #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; }