#include "sux.h" #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; uint8_t time_done = 0; #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; uint8_t end = 0; WINDOW *scr; struct suxthr { struct sux sx; uint8_t th; }; #if bench double ipc; #endif inline uint8_t get_addrsize(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 uint8_t isrw(uint8_t opcode) { switch (opcode) { case STA_AB: /* STA Absolute. */ case STA_Z: /* STA Zero Matrix. */ case STA_ZX: /* STA Zero Matrix, Indexed with X. */ case STA_ZY: /* STA Zero Matrix, Indexed with Y. */ case STA_IN: /* STA Indirect. */ case STA_IX: /* STA Indexed Indirect. */ case STA_IY: /* STA Indirect Indexed. */ case STY_AB: /* STY Absolute. */ case STY_Z: /* STY Zero Matrix. */ case STY_IN: /* STY Indirect. */ case STX_AB: /* STX Absolute. */ case STX_Z: /* STX Zero Matrix. */ case STX_IN: /* STX Indirect. */ case STB_AB: /* STB Absolute. */ case STB_Z: /* STB Zero Matrix. */ case STB_ZX: /* STB Zero Matrix, Indexed with X. */ case STB_ZY: /* STB Zero Matrix, Indexed with Y. */ case STB_IN: /* STB Indirect. */ case STB_IX: /* STB Indexed Indirect. */ case STB_IY: /* STB Indirect Indexed. */ case INC_AB: /* INC Absolute. */ case INC_Z: /* INC Zero Matrix. */ case DEC_AB: /* DEC Absolute. */ case DEC_Z: /* DEC Zero Matrix. */ return 0; /* Writing. */ default: return 1; /* Reading. */ } } static inline uint8_t isread(uint8_t opcode) { switch (opcode) { case LDA_IMM: /* LDA Immediate. */ case LDA_AB: /* LDA Absolute. */ case LDA_Z: /* LDA Zero Matrix. */ case LDA_ZX: /* LDA Zero Matrix, Indexed with X. */ case LDA_ZY: /* LDA Zero Matrix, Indexed with Y. */ case LDA_IN: /* LDA Indirect. */ case LDA_IX: /* LDA Indexed Indirect. */ case LDA_IY: /* LDA Indirect Indexed. */ case LDB_IMM: /* LDB Immediate. */ case LDB_AB: /* LDB Absolute. */ case LDB_Z: /* LDB Zero Matrix. */ case LDB_ZX: /* LDB Zero Matrix, Indexed with X. */ case LDB_ZY: /* LDB Zero Matrix, Indexed with Y. */ case LDB_IN: /* LDB Indirect. */ case LDB_IX: /* LDB Indexed Indirect. */ case LDB_IY: /* LDB Indirect Indexed. */ case LDY_IMM: /* LDY Immediate. */ case LDY_AB: /* LDY Absolute. */ case LDY_Z: /* LDY Zero Matrix. */ case LDY_IN: /* LDY Indirect. */ case LDX_IMM: /* LDX Immediate. */ case LDX_AB: /* LDX Absolute. */ case LDX_Z: /* LDX Zero Matrix. */ case LDX_IN: /* LDX Indirect. */ case JMP_AB: /* JMP Absolute. */ case JMP_Z: /* JMP Zero Matrix. */ case JMP_IN: /* JMP Indirect. */ case JSR_IN: /* JSR Indirect. */ case JSR_AB: /* Jump to SubRoutine. */ case JSR_Z: /* JSR Zero Matrix. */ return 0; default: return 1; } } #if bench void stop_timer() { time_done = 1; } void start_timer(int sec, int usec) { struct itimerval it_val; for (; usec > 1000000; sec++, usec -= 1000000); it_val.it_value.tv_sec = sec; it_val.it_value.tv_usec = usec; it_val.it_interval.tv_sec = 0; it_val.it_interval.tv_usec = 0; if (signal(SIGALRM, stop_timer) == SIG_ERR) { perror("Unable to catch SIGALRM."); exit(1); } if (setitimer(ITIMER_REAL, &it_val, NULL) == -1) { perror("Error calling setitimer()."); exit(1); } } #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; union reg address; union reg value; cpu->clk = 0; uint64_t *rem = NULL; #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 start_timer(1, 0); #endif for (;;) { #if !bench if (end) { pthread_mutex_lock(&main_mutex); pthread_cond_signal(&main_cond); pthread_mutex_unlock(&main_mutex); return NULL; } #endif address.u64 = 0; value.u64 = 0; #if debug && !bench if (lines > 24*(thread+1)) { lines = (24*thread)+2; } #if keypoll pthread_mutex_lock(&mutex); #endif print_regs(cpu, lines, thread); #if keypoll pthread_mutex_unlock(&mutex); #endif #endif uint16_t instr = read_value(cpu, 0, cpu->pc, 1, 1, 0); uint8_t *tmp_inst = (uint8_t *)&instr; prefix = ((instr & 3) == 3) ? *tmp_inst++ : 0; opcode = *tmp_inst; cpu->pc += ((instr & 3) == 3)+1; address.u64 = cpu->pc; uint8_t am = optype[opcode]; uint8_t rs = (prefix >> 4) & 3; uint8_t size = (/***/1 << rs) - 1; uint8_t check_io = (am != IMM); uint64_t sp = (cpu->sp & 0xFFFF) | (cpu->stk_st << 16); #if debug && !bench #if keypoll pthread_mutex_lock(&mutex); #endif disasm(cpu, lines, opcode, prefix, thread); lines+=1; #if keypoll pthread_mutex_unlock(&mutex); #endif #endif if (am != IMPL && am != BREG) { address.u64 = get_addr(cpu, opcode, prefix, 1, 1, thread); /*if (address.u64 > mem_size-1) { addr[STEP_ADDR] = 1; step = 1; }*/ if (isrw(opcode) && am != REL && isread(opcode)) { value.u64 = read_value(cpu, 0, address.u64, size, 1, check_io); } } switch (opcode) { case CPS_IMP: /* Clear Processor Status. */ cpu->ps.u64 = 0; break; case ADC_B: /* ADC B register. */ value.u64 = cpu->b; /* Falls Through. */ case ADC_IMM: /* ADC Immediate. */ case ADC_AB: /* ADC Absolute. */ case ADC_Z: /* ADC Zero Matrix. */ cpu->a = adc(cpu, cpu->a, value.u64, thread); break; case PHP_IMP: push(cpu, cpu->ps.u8[thread], 0, thread); break; /* PusH Processor status to stack. */ case PHA_IMP: push(cpu, cpu->a , size, thread); break; /* PusH Accumulator to stack. */ case PHB_IMP: push(cpu, cpu->b , size, thread); break; /* PusH B register to stack. */ case PHY_IMP: push(cpu, cpu->y , size, thread); break; /* PusH Y register to stack. */ case PHX_IMP: push(cpu, cpu->x , size, thread); break; /* PusH X register to stack. */ case TAY_IMP: cpu->y = transfer(cpu, cpu->a, value.u64, opcode, prefix, thread); break; /* Transfer Accumulator to Y. */ case TAX_IMP: cpu->x = transfer(cpu, cpu->a, value.u64, opcode, prefix, thread); break; /* Transfer Accumulator to Y. */ case TYX_IMP: cpu->x = transfer(cpu, cpu->y, value.u64, opcode, prefix, thread); break; /* Transfer Y to X. */ case TYA_IMP: cpu->a = transfer(cpu, cpu->y, value.u64, opcode, prefix, thread); break; /* Transfer Y to Accumulator. */ case TXA_IMP: cpu->a = transfer(cpu, cpu->x, value.u64, opcode, prefix, thread); break; /* Transfer X to Accumulator. */ case TXY_IMP: cpu->y = transfer(cpu, cpu->x, value.u64, opcode, prefix, thread); break; /* Transfer X to Y. */ case TAB_IMP: cpu->b = transfer(cpu, cpu->a, value.u64, opcode, prefix, thread); break; /* Transfer Accumulator to B. */ case TSX_IMP: cpu->x = transfer(cpu, sp, value.u64, opcode, prefix, thread); break; /* Transfer Stack pointer to X. */ case TBA_IMP: cpu->a = transfer(cpu, cpu->b, value.u64, opcode, prefix, thread); break; /* Transfer B to Accumulator. */ case TXS_IMM: cpu->sp = transfer(cpu, cpu->x, value.u64, opcode, prefix, thread); break; /* Transfer X to Stack pointer. */ case BRA_REL: /* BRA Relative. */ case JMP_AB: /* JMP Absolute. */ case JMP_Z: /* JMP Zero Matrix. */ case JMP_IN: /* JMP Indirect. */ cpu->pc = address.u64; break; case SBC_B: /* SBC B register. */ value.u64 = cpu->b; /* Falls Through. */ case SBC_IMM: /* SBC Immediate. */ case SBC_AB: /* SBC Absolute. */ case SBC_Z: /* SBC Zero Matrix. */ cpu->a = adc(cpu, cpu->a, ~value.u64, thread); break; case PLP_IMP: cpu->ps.u8[thread] = pull(cpu, 0, thread); break; /* PuLl Processor status from stack. */ case PLA_IMP: cpu->a = pull(cpu, size, thread); break; /* PuLl Accumulator from stack. */ case PLB_IMP: cpu->b = pull(cpu, size, thread); break; /* PuLl B register from stack. */ case PLY_IMP: cpu->y = pull(cpu, size, thread); break; /* PuLl Y register from stack. */ case PLX_IMP: cpu->x = pull(cpu, size, thread); break; /* PuLl X register from stack. */ break; case AND_B: /* AND B register. */ value.u64 = cpu->b; /* Falls Through. */ case AND_IMM: /* AND Immediate. */ case AND_AB: /* AND Absolute. */ case AND_Z: /* AND Zero Matrix. */ cpu->a = and(cpu, cpu->a, value.u64, thread); break; case BPO_REL: /* BPO Relative. */ if (!getflag(N)) { cpu->pc = address.u64; } break; case ORA_B: /* ORA B register. */ value.u64 = cpu->b; /* Falls Through. */ case ORA_IMM: /* ORA Immediate. */ case ORA_AB: /* ORA Absolute. */ case ORA_Z: /* ORA Zero Matrix. */ cpu->a = or(cpu, cpu->a, value.u64, thread); break; case SEI_IMP: /* SEt Interrupt. */ setflag(1, I); break; case BNG_REL: /* BNG Relative. */ if (getflag(N)) { cpu->pc = address.u64; } break; case XOR_B: /* XOR B register. */ value.u64 = cpu->b; /* Falls Through. */ case XOR_IMM: /* XOR Immediate. */ case XOR_AB: /* XOR Absolute. */ case XOR_Z: /* XOR Zero Matrix. */ cpu->a = xor(cpu, cpu->a, value.u64, thread); break; case CLI_IMP: /* CLear Interrupt. */ setflag(0, I); break; case BCS_REL: /* BCS Relative. */ if (getflag(C)) { cpu->pc = address.u64; } break; case LSL_B: /* LSL B register. */ value.u64 = cpu->b; /* Falls Through. */ case LSL_IMM: /* LSL Immediate. */ case LSL_AB: /* LSL Absolute. */ case LSL_Z: /* LSL Zero Matrix. */ cpu->a = lsl(cpu, cpu->a, value.u64, thread); break; case SEC_IMP: /* SEt Carry flag.*/ setflag(1, C); break; case STA_AB: /* STA Absolute. */ case STA_Z: /* STA Zero Matrix. */ case STA_ZX: /* STA Zero Matrix, Indexed with X. */ case STA_ZY: /* STA Zero Matrix, Indexed with Y. */ case STA_IN: /* STA Indirect. */ case STA_IX: /* STA Indexed Indirect. */ case STA_IY: /* STA Indirect Indexed. */ store(cpu, address.u64, cpu->a, prefix, thread); break; case STY_AB: /* STY Absolute. */ case STY_Z: /* STY Zero Matrix. */ case STY_IN: /* STY Indirect. */ store(cpu, address.u64, cpu->y, prefix, thread); break; case STX_AB: /* STX Absolute. */ case STX_Z: /* STX Zero Matrix. */ case STX_IN: /* STX Indirect. */ store(cpu, address.u64, cpu->x, prefix, thread); break; case STB_AB: /* STB Absolute. */ case STB_Z: /* STB Zero Matrix. */ case STB_ZX: /* STB Zero Matrix, Indexed with X. */ case STB_ZY: /* STB Zero Matrix, Indexed with Y. */ case STB_IN: /* STB Indirect. */ case STB_IX: /* STB Indexed Indirect. */ case STB_IY: /* STB Indirect Indexed. */ store(cpu, address.u64, cpu->b, prefix, thread); break; case BCC_REL: /* BCC Relative. */ if (!getflag(C)) { cpu->pc = address.u64; } break; case LSR_B: /* LSR B register. */ value.u64 = cpu->b; /* Falls Through. */ case LSR_IMM: /* LSR Immediate. */ case LSR_AB: /* LSR Absolute. */ case LSR_Z: /* LSR Zero Matrix. */ cpu->a = lsr(cpu, cpu->a, value.u64, thread); break; case ASR_B: /* ASR B register. */ value.u64 = cpu->b; /* Falls Through. */ case ASR_IMM: /* ASR Immediate. */ case ASR_AB: /* ASR Absolute. */ case ASR_Z: /* ASR Zero Matrix. */ cpu->a = asr(cpu, cpu->a, value.u64, thread); break; case CLC_IMP: /* CLear Carry flag. */ setflag(0, C); break; case LDB_IMM: /* LDB Immediate. */ case LDB_AB: /* LDB Absolute. */ case LDB_Z: /* LDB Zero Matrix. */ case LDB_ZX: /* LDB Zero Matrix, Indexed with X. */ case LDB_ZY: /* LDB Zero Matrix, Indexed with Y. */ case LDB_IN: /* LDB Indirect. */ case LDB_IX: /* LDB Indexed Indirect. */ case LDB_IY: /* LDB Indirect Indexed. */ cpu->b = load(cpu, cpu->b, address.u64, size, thread); break; case LDA_IMM: /* LDA Immediate. */ case LDA_AB: /* LDA Absolute. */ case LDA_Z: /* LDA Zero Matrix. */ case LDA_ZX: /* LDA Zero Matrix, Indexed with X. */ case LDA_ZY: /* LDA Zero Matrix, Indexed with Y. */ case LDA_IN: /* LDA Indirect. */ case LDA_IX: /* LDA Indexed Indirect. */ case LDA_IY: /* LDA Indirect Indexed. */ cpu->a = load(cpu, cpu->a, address.u64, size, thread); break; case LDY_IMM: /* LDY Immediate. */ case LDY_AB: /* LDY Absolute. */ case LDY_Z: /* LDY Zero Matrix. */ case LDY_IN: /* LDY Indirect. */ cpu->y = load(cpu, cpu->y, address.u64, size, thread); break; case LDX_IMM: /* LDX Immediate. */ case LDX_AB: /* LDX Absolute. */ case LDX_Z: /* LDX Zero Matrix. */ case LDX_IN: /* LDX Indirect. */ cpu->x = load(cpu, cpu->x, address.u64, size, thread); break; case BEQ_REL: /* BEQ Relative. */ if (getflag(Z)) { cpu->pc = address.u64; } break; case ROL_B: /* ROL B register. */ value.u64 = cpu->b; /* Falls Through. */ case ROL_IMM: /* ROL Immediate. */ case ROL_AB: /* ROL Absolute. */ case ROL_Z: /* ROL Zero Matrix. */ cpu->a = rol(cpu, cpu->a, value.u64, thread); break; case BNE_REL: /* BNE Relative. */ if (!getflag(Z)) { cpu->pc = address.u64; } break; case ROR_B: /* ROR B register. */ value.u64 = cpu->b; /* Falls Through. */ case ROR_IMM: /* ROR Immediate. */ case ROR_AB: /* ROR Absolute. */ case ROR_Z: /* ROR Zero Matrix. */ cpu->a = ror(cpu, cpu->a, value.u64, thread); break; case BVS_REL: /* BVS Relative. */ if (getflag(V)) { cpu->pc = address.u64; } break; case MUL_B: /* MUL B register. */ value.u64 = cpu->b; /* Falls Through. */ case MUL_IMM: /* MUL Immediate. */ case MUL_AB: /* MUL Absolute. */ case MUL_Z: /* MUL Zero Matrix. */ cpu->a = mul(cpu, cpu->a, value.u64, thread); break; case BVC_REL: /* BVC Relative. */ if (!getflag(V)) { cpu->pc = address.u64; } break; case DIV_B: /* DIV B register. */ case DIV_IMM: /* DIV Immediate. */ case DIV_AB: /* DIV Absolute. */ case DIV_Z: /* DIV Zero Matrix. */ rem = (opcode != DIV_B) ? &cpu->b : &cpu->x; cpu->a = divd(cpu, cpu->a, value.u64, rem, thread); break; case CLV_IMP: /* CLear oVerflow flag. */ setflag(0, V); break; case CPB_IMM: /* CPB Immediate. */ case CPB_AB: /* CPB Absolute. */ case CPB_Z: /* CPB Zero Matrix. */ case CPB_IN: /* CPB Indirect. */ case CPB_IX: /* CPB Indexed Indirect. */ case CPB_IY: /* CPB Indirect Indexed. */ cmp(cpu, value.u64, cpu->b, thread); break; case CMP_B: /* CMP B register. */ value.u64 = cpu->b; /* Falls Through. */ case CMP_IMM: /* 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); break; case CPY_IMM: /* CPY Immediate. */ case CPY_AB: /* CPY Absolute. */ case CPY_Z: /* CPY Zero Matrix. */ cmp(cpu, value.u64, cpu->y, thread); break; case CPX_IMM: /* CPX Immediate. */ case CPX_AB: /* CPX Absolute. */ case CPX_Z: /* CPX Zero Matrix. */ cmp(cpu, value.u64, cpu->x, thread); break; case INC_IMP: cpu->a = idr(cpu, cpu->a, 1, thread); break; case INB_IMP: cpu->b = idr(cpu, cpu->b, 1, thread); break; case INY_IMP: cpu->y = idr(cpu, cpu->y, 1, thread); break; case INX_IMP: cpu->x = idr(cpu, cpu->x, 1, thread); break; case DEC_IMP: cpu->a = idr(cpu, cpu->a, 0, thread); break; case DEB_IMP: cpu->b = idr(cpu, cpu->b, 0, thread); break; case DEY_IMP: cpu->y = idr(cpu, cpu->y, 0, thread); break; case DEX_IMP: cpu->x = idr(cpu, cpu->x, 0, thread); break; case JSR_IN: /* JSR Indirect. */ case JSR_AB: /* Jump to SubRoutine. */ case JSR_Z: /* JSR Zero Matrix. */ push(cpu, cpu->pc, (size) ? size : 7, thread); cpu->pc = address.u64; break; case INC_AB: /* INC Absolute. */ case INC_Z: /* INC Zero Matrix. */ idm(cpu, address.u64, prefix, 1, thread); break; case NOP_IMP: /* No OPeration. */ break; case RTI_IMP: /* ReTurn from Interrupt routine. */ cpu->ps.u8[thread] = pull(cpu, 0, thread); size = 0; case RTS_IMP: /* ReTurn from Subroutine. */ cpu->pc = pull(cpu, (size) ? size : 7, thread); break; case DEC_AB: /* DEC Absolute. */ case DEC_Z: /* DEC Zero Matrix. */ idm(cpu, address.u64, prefix, 0, thread); break; case BRK_IMP: /* BReaK. */ case WAI_IMP: /* WAit for Interrupt. */ if (opcode == WAI_IMP) { 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); } push(cpu, cpu->pc, 7, thread); push(cpu, cpu->ps.u8[thread], 0, thread); setflag(1, I); setreg(value.u8, +, 0, addr, +, (opcode == BRK) ? 0xFFE0 : 0xFFA0, 7); if (opcode == WAI_IMP) { kbd_rdy &= (uint8_t)~(1 << thread); } cpu->pc = value.u64; default: break; } #if !IO ins++; #endif #if !bench if (step) { int c = 0; #if debug wrefresh(scr); #endif for (; step && c != 19 && !end; c = get_key(scr)); #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, cpu->clk); #endif if (step || !subdbg) { wrefresh(scr); } #if keypoll pthread_mutex_unlock(&mutex); #endif #elif bench if (time_done) { pthread_mutex_lock(&main_mutex); threads_done++; inst[thread] = ins; #if getclk clk[thread] = cpu->clk; #endif pthread_cond_signal(&main_cond); pthread_mutex_unlock(&main_mutex); break; } #endif } return NULL; } void init_scr() { if (!scr) { scr = initscr(); } nodelay(scr, 0); keypad(scr, 1); crmode(); noecho(); nl(); curs_set(1); scrollok(scr, 1); start_color(); use_default_colors(); init_pair(1, COLOR_WHITE, -1); attron(COLOR_PAIR(1) | A_BOLD); } int main(int argc, char **argv) { struct suxthr thr[THREADS]; char *tmp = malloc(2048); addr = malloc(mem_size); #if bench inss = 0; struct timeval str, en; #endif int v = 0; if (argc != 2) { if (asmmon("stdin") == 2) { return 0; } } else { #if debug subdbg = !strcmp(argv[1], "programs/sub-suite/subsuite.s"); #endif if (asmmon(argv[1]) == 2) { return 0; } } sprintf(tmp, "\033[2J\033[H"); fwrite(tmp, sizeof(char), strlen(tmp), stdout); fflush(stdout); init_scr(); werase(scr); 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 = 0xFFFF; thr[i].sx.stk_st = i+1; offset = (i) ? ((i-1) << 3) : 0; vec = (i) ? 0xFF50 : 0xFFC0; 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 | (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); } werase(scr); #if bench endwin(); gettimeofday(&str, 0); double t = 0; double dt = 0; double t2 = 0; #endif while (threads_done < THREADS && !end) { #if !bench pthread_mutex_lock(&main_mutex); pthread_cond_wait(&main_cond, &main_mutex); pthread_mutex_unlock(&main_mutex); /*#if keypoll pthread_mutex_lock(&mutex); #endif #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 endwin(); #endif #if bench gettimeofday(&en, 0); if (threads_done == THREADS) { double tm_sec, tm_usec, tm; #if getclk double clkspd; double mhz; #endif double ips[THREADS]; double ipst; tm_sec = (en.tv_sec - str.tv_sec); tm_usec = (en.tv_usec-str.tv_usec); tm = (tm_sec*1000000)+(tm_usec); for (int i = 0; i < THREADS; i++) { ips[i] = inst[i]/tm; if (i) { inss += inst[i]; ipst += ips[i]; #if getclk tclk += clk[i]; #endif } else { inss = inst[i]; ipst = ips[i]; #if getclk tclk = clk[i]; #endif } #if getclk clkspd = (tm/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\n", i, inst[i], i, ips[i]); 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 = (tm/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", tm/1000000); fwrite(tmp, sizeof(char), strlen(tmp), stdout); fflush(stdout); free(tmp); } #endif free(addr); return 0; }