#include "opcode.h" #include #include #include #include #define bench 0 #define debug 0 #define IO 1 #define keypoll 0 #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 clearflags(thread) {\ cpu->c[thread] = 0;\ cpu->z[thread] = 0;\ cpu->i[thread] = 0;\ cpu->s[thread] = 0;\ cpu->v[thread] = 0;\ cpu->n[thread] = 0;\ } uint64_t clk[THREADS]; /* Per Thread Clock cycles. */ uint64_t tclk; /* Total Clock cycles. */ uint64_t inst[THREADS]; uint64_t inss; uint8_t threads_done = 0; uint8_t kbd_rdy = 0; uint8_t kbd_ln = 0; uint8_t wai = 0; uint8_t step = 0; uint8_t irq = 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; uint64_t tmpaddr = 0; uint8_t prefix = 0; uint8_t opcode = 0; uint8_t end = 0; uint8_t stksize; uint64_t sum = 0; uint64_t value = 0; uint64_t reg = 0; uint64_t iclk = 0; uint64_t ins = 0; uint64_t sign = 0; uint8_t addrsize; uint8_t rs; uint8_t regsize; uint8_t tmp; char *s = malloc(2048); #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 uint16_t tv = 0xFF50; /* Starting address of the Thread Vectors. */ #if bench gettimeofday(&str[thread], 0); #endif while (!end) { address = 0; if (wai) { for (int8_t i = 56; i >= 0; i-=8) { if (i) addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread]-1 >> i; else addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread]-1 & 0xFF; cpu->sp[thread]--; } addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->ps >> 8*thread; cpu->sp[thread]--; cpu->i[thread] = 1; setflag(cpu->i[thread], I); 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; wai = 0; kbd_rdy &= (uint8_t)~(1 << thread); } prefix = addr[cpu->pc[thread]]; if ((prefix & 0x07) == 0x07) cpu->pc[thread]++; else prefix = 0; opcode = addr[cpu->pc[thread]]; #if debug && !bench if (lines > 24*(thread+1)) { lines = (24*thread)+2; } #if keypoll pthread_mutex_lock(&mutex); #endif /*mvwprintw(scr, lines, 0, "pc: $%08llx, a: $%016llx, b: $%016llx, x: $%016llx, y: $%016llx" ", sp: $%04lx, ps: $%016llx, prefix: $%02x, opcode: $%02x, thread: %u, inst: " , cpu->pc[thread], cpu->a[thread], cpu->b[thread], cpu->x[thread], cpu->y[thread] , cpu->sp[thread], cpu->ps, prefix, opcode, thread);*/ mvwprintw(scr, lines, 0, "pc: $%08llx, a: $%016llx, b: $%016llx, x: $%016llx, y: $%016llx" ", sp: $%04lx, ps: $%016llx, prefix: $%02x, opcode: $%02x, inst: " , cpu->pc[thread], cpu->a[thread], cpu->b[thread], cpu->x[thread], cpu->y[thread] , cpu->sp[thread], cpu->ps, prefix, opcode); #if keypoll pthread_mutex_unlock(&mutex); #endif #endif addrsize = (prefix & 8) == 8; rs = (prefix & 0x30) >> 4; regsize = (1 << rs); address = cpu->pc[thread]; cpu->pc[thread]++; iclk++; 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]+=1; break; default: address = cpu->pc[thread]; cpu->pc[thread]+=regsize; break; } break; case ZM: case ZMX: case ZMY: address = addr[cpu->pc[thread]]; if (addrsize) { address |= addr[cpu->pc[thread]+1] << 8; address |= addr[cpu->pc[thread]+2] << 16; address |= addr[cpu->pc[thread]+3] << 24; cpu->pc[thread]+=4; } else { cpu->pc[thread]+=1; } tmpaddr = address; switch (optype[opcode]) { case ZMX: address += cpu->x[thread]; iclk++; break; case ZMY: address += cpu->y[thread]; iclk++; break; } iclk++; break; case IND: case INDX: case INDY: address = addr[cpu->pc[thread]]; if (addrsize) { address |= addr[cpu->pc[thread]+1] << 8; address |= addr[cpu->pc[thread]+2] << 16; address |= addr[cpu->pc[thread]+3] << 24; cpu->pc[thread]+=4; } else { cpu->pc[thread]+=1; } iclk++; tmpaddr = address; if (optype[opcode] == INDX) { address += cpu->x[thread]; iclk++; } value = addr[address]; value |= addr[address+1] << 8; value |= addr[address+2] << 16; value |= addr[address+3] << 24; value |= (uint64_t)addr[address+4] << 32; value |= (uint64_t)addr[address+5] << 40; value |= (uint64_t)addr[address+6] << 48; value |= (uint64_t)addr[address+7] << 56; iclk++; if (optype[opcode] == INDY) { value += cpu->y[thread]; iclk++; } address = value; value = 0; iclk++; break; case ABS: address = addr[cpu->pc[thread]]; address |= addr[cpu->pc[thread]+1] << 8; if (addrsize) { address |= addr[cpu->pc[thread]+2] << 16; address |= addr[cpu->pc[thread]+3] << 24; address |= (uint64_t)addr[cpu->pc[thread]+4] << 32; address |= (uint64_t)addr[cpu->pc[thread]+5] << 40; address |= (uint64_t)addr[cpu->pc[thread]+6] << 48; address |= (uint64_t)addr[cpu->pc[thread]+7] << 56; cpu->pc[thread]+=8; iclk++; } else { cpu->pc[thread]+=2; } iclk++; break; } value = addr[address]; if (regsize >= 2) { value |= addr[address+1] << 8; if (regsize >= 4) { value |= addr[address+2] << 16; value |= addr[address+3] << 24; if (regsize >= 8) { 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 debug && !bench int row, col; #if keypoll pthread_mutex_lock(&mutex); #endif getyx(scr,row, col); char postfix[3]; char op[4]; op[0] = opname[opcode][0]; op[1] = opname[opcode][1]; op[2] = opname[opcode][2]; op[3] = '\0'; if (regsize == 1) { postfix[0] = '\0'; postfix[1] = '\0'; postfix[2] = '\0'; } else { postfix[0] = '.'; if (regsize == 2) postfix[1] = 'W'; else if (regsize == 4) postfix[1] = 'D'; else if (regsize == 8) postfix[1] = 'Q'; postfix[2] = '\0'; } switch (optype[opcode]) { case IMPL: mvwprintw(scr, lines, col, "%s \r" , opname[opcode]); break; case IMM: if (regsize == 1) { mvwprintw(scr, lines, col, "%s #$%02x \r" , op, value); } else if (regsize == 2) { mvwprintw(scr, lines, col, "%s%s #$%04x \r" , op, postfix, value); } else if (regsize == 4) { mvwprintw(scr, lines, col, "%s%s #$%08x \r" , op, postfix, value); } else if (regsize == 8) { mvwprintw(scr, lines, col, "%s%s #$%016llx\r" , op, postfix, value); } break; case ZM: case ZMX: case ZMY: if (optype[opcode] == ZMX) tmpaddr = address - cpu->x[thread]; else if (optype[opcode] == ZMY) tmpaddr = address - cpu->y[thread]; if (addrsize) mvwprintw(scr, lines, col, "%s%s $%08x%s \r" , op, postfix, tmpaddr, (optype[opcode] == ZM) ? "" : ((optype[opcode] == ZMX) ? ", x" : ", y")); else mvwprintw(scr, lines, col, "%s%s $%02x%s \r" , op, postfix, tmpaddr, (optype[opcode] == ZM) ? "" : ((optype[opcode] == ZMX) ? ", x" : ", y")); break; case IND: case INDX: case INDY: if (addrsize) mvwprintw(scr, lines, col, "%s%s ($%08x%s \r" , op, postfix, tmpaddr, (optype[opcode] == IND) ? ")" : ((optype[opcode] == INDX) ? ", x)" : "), y")); else mvwprintw(scr, lines, col, "%s%s ($%02x%s \r" , op, postfix, tmpaddr, (optype[opcode] == IND) ? ")" : ((optype[opcode] == INDX) ? ", x)" : "), y")); break; case ABS: tmpaddr = address; if (addrsize) mvwprintw(scr, lines, col, "%s%s $%016llx\r" , op, postfix, value); else mvwprintw(scr, lines, col, "%s%s $%04x \r" , op, postfix, tmpaddr); break; } mvwprintw(scr, 29, 0, "address: $%016llx, scr_row: %02u, scr_col: %02u, scr_str: %02u, scr_end: %02u\r", address, addr[0], addr[1], addr[0x4B], addr[0x4C]); mvwprintw(scr, 32, 0, "bitabl: %02x %02x %02x %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x %02x %02x\r" , addr[0x3B], addr[0x3C], addr[0x3D], addr[0x3E], addr[0x3F], addr[0x40], addr[0x41], addr[0x42] , addr[0x43], addr[0x44], addr[0x45], addr[0x46], addr[0x47], addr[0x48], addr[0x49], addr[0x4A]); mvwprintw(scr, 33, 0, "buffer:\r"); uint8_t ln = 34; uint16_t tmpad = 0x2000; for (uint16_t i = 0; i < 20; i+=2) { mvwprintw(scr, ln++, 0, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x, i: %02x\r" , addr[tmpad+(0x00)+(i*0x10)], addr[tmpad+(0x01)+(i*0x10)], addr[tmpad+(0x02)+(i*0x10)], addr[tmpad+(0x03)+(i*0x10)] , addr[tmpad+(0x04)+(i*0x10)], addr[tmpad+(0x05)+(i*0x10)], addr[tmpad+(0x06)+(i*0x10)], addr[tmpad+(0x07)+(i*0x10)] , addr[tmpad+(0x08)+(i*0x10)], addr[tmpad+(0x09)+(i*0x10)], addr[tmpad+(0x0A)+(i*0x10)], addr[tmpad+(0x0B)+(i*0x10)] , addr[tmpad+(0x0C)+(i*0x10)], addr[tmpad+(0x0D)+(i*0x10)], addr[tmpad+(0x0E)+(i*0x10)], addr[tmpad+(0x0F)+(i*0x10)] , addr[tmpad+(0x10)+(i*0x10)], addr[tmpad+(0x11)+(i*0x10)], addr[tmpad+(0x12)+(i*0x10)], addr[tmpad+(0x13)+(i*0x10)] , addr[tmpad+(0x14)+(i*0x10)], addr[tmpad+(0x15)+(i*0x10)], addr[tmpad+(0x16)+(i*0x10)], addr[tmpad+(0x17)+(i*0x10)] , addr[tmpad+(0x18)+(i*0x10)], addr[tmpad+(0x19)+(i*0x10)], addr[tmpad+(0x1A)+(i*0x10)], addr[tmpad+(0x1B)+(i*0x10)] , addr[tmpad+(0x1C)+(i*0x10)], addr[tmpad+(0x1D)+(i*0x10)], addr[tmpad+(0x1E)+(i*0x10)], addr[tmpad+(0x1F)+(i*0x10)] , i); } /*tmpad = 0x4000; mvwprintw(scr, ln++, 0, "cmd_buf:\r"); for (uint16_t i = 0; i < 20; i+=2) { mvwprintw(scr, ln++, 0, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x, i: %02x\r" , addr[tmpad+(0x00)+(i*0x10)], addr[tmpad+(0x01)+(i*0x10)], addr[tmpad+(0x02)+(i*0x10)], addr[tmpad+(0x03)+(i*0x10)] , addr[tmpad+(0x04)+(i*0x10)], addr[tmpad+(0x05)+(i*0x10)], addr[tmpad+(0x06)+(i*0x10)], addr[tmpad+(0x07)+(i*0x10)] , addr[tmpad+(0x08)+(i*0x10)], addr[tmpad+(0x09)+(i*0x10)], addr[tmpad+(0x0A)+(i*0x10)], addr[tmpad+(0x0B)+(i*0x10)] , addr[tmpad+(0x0C)+(i*0x10)], addr[tmpad+(0x0D)+(i*0x10)], addr[tmpad+(0x0E)+(i*0x10)], addr[tmpad+(0x0F)+(i*0x10)] , addr[tmpad+(0x10)+(i*0x10)], addr[tmpad+(0x11)+(i*0x10)], addr[tmpad+(0x12)+(i*0x10)], addr[tmpad+(0x13)+(i*0x10)] , addr[tmpad+(0x14)+(i*0x10)], addr[tmpad+(0x15)+(i*0x10)], addr[tmpad+(0x16)+(i*0x10)], addr[tmpad+(0x17)+(i*0x10)] , addr[tmpad+(0x18)+(i*0x10)], addr[tmpad+(0x19)+(i*0x10)], addr[tmpad+(0x1A)+(i*0x10)], addr[tmpad+(0x1B)+(i*0x10)] , addr[tmpad+(0x1C)+(i*0x10)], addr[tmpad+(0x1D)+(i*0x10)], addr[tmpad+(0x1E)+(i*0x10)], addr[tmpad+(0x1F)+(i*0x10)] , i); }*/ wrefresh(scr); #if keypoll pthread_mutex_unlock(&mutex); #endif lines+=1; #endif switch(opcode) { case CPS: /* Clear Processor Status. */ clearflags(0); clearflags(1); clearflags(2); clearflags(3); clearflags(4); clearflags(5); clearflags(6); clearflags(7); cpu->ps &= 0; break; case ADC: /* ADC Immediate. */ case AAB: /* Add Accumulator with carry by B register. */ case 0x03: /* ADC Absolute. */ case 0x05: /* ADC Zero Matrix. */ if (opcode == AAB) value = cpu->b[thread]; sum = cpu->a[thread]+value+cpu->c[thread]; cpu->a[thread] = sum; cpu->z[thread] = (sum == 0); cpu->n[thread] = (sum >> 63); cpu->v[thread] = !((cpu->a[thread]^value) & 0x8000000000000000) && ((cpu->a[thread]^sum) & 0x8000000000000000); cpu->c[thread] = (sum < value); setflag(cpu->z[thread], Z); setflag(cpu->n[thread], N); setflag(cpu->v[thread], V); setflag(cpu->c[thread], C); setflag(cpu->i[thread], I); 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; if (opcode == PHB) { reg = cpu->b[thread]; } else if (opcode == PHP) { reg = cpu->ps; } else if (opcode == PHA) { reg = cpu->a[thread]; } else if (opcode == PHY) { reg = cpu->y[thread]; } else if (opcode == PHX) { reg = cpu->x[thread]; } if (tmp > 7) tmp = 7; for (int8_t i = tmp<<3; i >= 0; i-=8) { if (i) addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = reg >> i; else 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 TAY: cpu->y[thread] = cpu->a[thread]; break; case TAX: cpu->x[thread] = cpu->a[thread]; break; case TYX: cpu->x[thread] = cpu->y[thread]; break; case TYA: cpu->a[thread] = cpu->y[thread]; break; case TXA: cpu->a[thread] = cpu->x[thread]; break; case TXY: cpu->y[thread] = cpu->x[thread]; break; case TAB: cpu->b[thread] = cpu->a[thread]; cpu->z[thread] = (cpu->b[thread] == 0); cpu->n[thread] = (cpu->b[thread] >> 63); break; case TSX: cpu->x[thread] = cpu->sp[thread] & 0xFFFF; cpu->x[thread] = cpu->stk_st[thread] << 16; break; case TBA: cpu->a[thread] = cpu->b[thread]; break; case TXS: cpu->sp[thread] = cpu->x[thread]; if (prefix == 0x17 && (value == thread+1 || value > 8)) { cpu->stk_st[thread] = value & 0xFF; cpu->stk_st[thread] += value << 16; cpu->pc[thread]+=2; } break; } switch (opcode) { case TYA: case TXA: case TBA: cpu->z[thread] = (cpu->a[thread] == 0); cpu->n[thread] = (cpu->a[thread] >> 63); break; case TAY: case TXY: cpu->z[thread] = (cpu->y[thread] == 0); cpu->n[thread] = (cpu->y[thread] >> 63); break; case TAX: case TYX: cpu->z[thread] = (cpu->x[thread] == 0); cpu->n[thread] = (cpu->x[thread] >> 63); break; } setflag(cpu->z[thread], Z); setflag(cpu->n[thread], N); break; case JMP: /* JMP Absolute. */ cpu->pc[thread] = address; break; case SBC: /* SBC Immediate. */ case SAB: /* Subtract Accumulator with carry by B register. */ case 0x13: /* SBC Absolute. */ case 0x15: /* SBC Zero Matrix. */ if (opcode == SAB) { value = cpu->b[thread]; } sum = cpu->a[thread]-value-!cpu->c[thread]; cpu->z[thread] = (sum == 0); cpu->n[thread] = (sum >> 63); cpu->v[thread] = ((cpu->a[thread]^value) & 0x8000000000000000) && ((cpu->a[thread]^sum) & 0x8000000000000000); cpu->c[thread] = (sum > value); setflag(cpu->z[thread], Z); setflag(cpu->n[thread], N); setflag(cpu->v[thread], V); setflag(cpu->c[thread], 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; if (opcode == PLB) reg = cpu->b[thread]; else if (opcode == PLP) reg = cpu->ps; else if (opcode == PLA) reg = cpu->a[thread]; else if (opcode == PLY) reg = cpu->y[thread]; else if (opcode == PLX) reg = cpu->x[thread]; if (tmp > 7) tmp = 7; for (uint8_t i = 0; i < (tmp+1)<<3; i+=8) { cpu->sp[thread]++; if (i) reg += addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << i; else reg = addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] & 0xFF; } if (opcode == PLB) { cpu->b[thread] = reg; } else if (opcode == PLP) { cpu->ps = reg; } else if (opcode == PLA) { cpu->a[thread] = reg; } else if (opcode == PLY) { cpu->y[thread] = reg; } else if (opcode == PLX) { cpu->x[thread] = reg; } break; case 0x34: /* JSR Indirect. */ case 0x44: /* JSR Indexed Indirect. */ case 0x54: /* JSR Indirect Indexed. */ case JSR: /* Jump to SubRoutine. */ if (addrsize) stksize = 24; else stksize = 0; for (int8_t i = stksize; i >= 0; i-=8) { if (i) addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] >> i; else addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] & 0xFF; cpu->sp[thread]--; } cpu->pc[thread] = address; break; case AND: /* AND Immediate. */ case ABA: /* bitwise And with Accumulator, and B register. */ case 0x23: /* AND Absolute. */ case 0x25: /* AND Zero Matrix. */ if (opcode == ABA) { value = cpu->b[thread]; } cpu->a[thread] &= value; cpu->z[thread] = (value == 0); cpu->n[thread] = (value >> 63); setflag(cpu->z[thread], Z); setflag(cpu->n[thread], 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 0x64: /* BPO Zero Matrix. */ if (!cpu->n[thread]) cpu->pc[thread] = address; break; case ORA: /* ORA Immediate. */ case OAB: /* bitwise Or with Accumulator, and B register. */ case 0x33: /* ORA Absolute. */ case 0x35: /* ORA Zero Matrix. */ if (opcode == OAB) { value = cpu->b[thread]; } cpu->a[thread] |= value; cpu->z[thread] = (value == 0); cpu->n[thread] = (value >> 63); setflag(cpu->z[thread], Z); setflag(cpu->n[thread], N); break; case SEI: /* SEt Interrupt. */ cpu->i[thread] = 1; setflag(cpu->i[thread], I); break; case BNG: /* BNG Absolute. */ case 0x74: /* BNG Zero Matrix. */ if (cpu->n[thread]) cpu->pc[thread] = address; break; case XOR: /* XOR Immediate. */ case XAB: /* bitwise Xor with Accumulator, and B register. */ case 0x43: /* XOR Absolute. */ case 0x45: /* XOR Zero Matrix. */ if (opcode == XAB) { value = cpu->b[thread]; } cpu->a[thread] ^= value; cpu->z[thread] = (value == 0); cpu->n[thread] = (value >> 63); setflag(cpu->z[thread], Z); setflag(cpu->n[thread], N); break; case CLI: /* CLear Interrupt. */ cpu->i[thread] = 0; setflag(cpu->i[thread], I); break; case BCS: /* BCS Absolute. */ case 0x84: /* BCS Zero Matrix. */ if (cpu->c[thread]) cpu->pc[thread] = address; break; case LSL: /* LSL Immediate. */ case LLB: /* Logical shift Left accumulator by B. */ case 0x53: /* LSL Absolute. */ case 0x55: /* LSL Zero Matrix. */ if (opcode == LLB) { value = cpu->b[thread]; } sum = (value < 64) ? cpu->a[thread] << value : 0; cpu->z[thread] = (sum == 0); cpu->n[thread] = (sum >> 63); cpu->c[thread] = cpu->a[thread] >> 64-value; cpu->a[thread] = sum; setflag(cpu->z[thread], Z); setflag(cpu->n[thread], N); setflag(cpu->c[thread], C); break; case SEC: /* SEt Carry flag.*/ cpu->c[thread] = 1; setflag(cpu->c[thread], C); break; case STA: /* STA Absolute. */ case STY: /* STY Absolute. */ case STX: /* STX Absolute. */ case STB: /* STB Absolute. */ case 0x49: /* STA Zero Matrix. */ case 0x4A: /* STY Zero Matrix. */ case 0x4B: /* STX Zero Matrix. */ case 0x4E: /* STB Zero Matrix. */ case 0x69: /* STA Zero Matrix, Indexed with X. */ case 0x6A: /* STY Zero Matrix, Indexed with X. */ case 0x6B: /* STX Zero Matrix, Indexed with Y. */ case 0x6E: /* STB Zero Matrix, Indexed with X. */ case 0x89: /* STA Zero Matrix, Indexed with Y. */ case 0x8A: /* STY Indirect. */ case 0x8B: /* STX Indirect. */ case 0x8E: /* STB Zero Matrix, Indexed with Y. */ case 0xA9: /* STA Indirect. */ case 0xAA: /* STY Indexed Indirect. */ case 0xAB: /* STX Indirect Indexed. */ case 0xAE: /* STB Indirect. */ case 0xC9: /* STA Indexed Indirect. */ case 0xCE: /* STB Indexed Indirect. */ case 0xE9: /* STA Indirect Indexed. */ case 0xEE: /* STB Indirect Indexed. */ switch (opcode) { case STB: case 0x4E: case 0x6E: case 0x8E: case 0xAE: case 0xCE: case 0xEE: value = cpu->b[thread]; break; case STA: case 0x49: case 0x69: case 0x89: case 0xA9: case 0xC9: case 0xE9: value = cpu->a[thread]; break; case STY: case 0x4A: case 0x6A: case 0x8A: case 0xAA: value = cpu->y[thread]; break; case STX: case 0x4B: case 0x6B: case 0x8B: case 0xAB: value = cpu->x[thread]; break; } addr[address] = value & 0xFF; if (address == STEP_ADDR) { step = addr[address]; } #if IO if (address == TX_ADDR) { #if keypoll pthread_mutex_lock(&mutex); #endif if (esc) { switch(addr[address]) { case 'A': if (y > 0) y--; wmove(scr, y, x); esc = 0; break; case 'B': if (y < getmaxy(scr)) y++; wmove(scr, y, x); esc = 0; break; case 'C': if (x < getmaxx(scr)) x++; wmove(scr, y, x); esc = 0; break; case 'D': if (x > 0) x--; wmove(scr, y, x); 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]); idx = 3; wmove(scr, y, x); bcd[0] = 0; bcd[1] = 0; bcd[2] = 0; bcd[3] = 0; esc = 0; break; case 'S': wscrl(scr, -1); esc = 0; break; case 'T': wscrl(scr, 1); 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 { if (addr[address] == 0xC) { x=0,y=0; wclear(scr); wmove(scr, y, x); } else if (addr[address] == CURSES_BACKSPACE || addr[address] == '\b') { if (x > 0) { x--; wmove(scr, y, x); } wdelch(scr); wrefresh(scr); } else if (addr[address] == '\033') { esc = 1; } else { wmove(scr, y, x); waddch(scr, addr[address]); wrefresh(scr); if (addr[address] == '\n') { x = 0; y+=1; } else { x+=1; } } } #if keypoll pthread_mutex_unlock(&mutex); #endif } #else #if !bench if (address == TX_ADDR) { if (esc) { switch(addr[address]) { case 'A': if (y > 0) y--; esc = 0; break; case 'B': if (y < getmaxy(scr)) y++; esc = 0; break; case 'C': if (x < getmaxx(scr)) x++; esc = 0; break; case 'D': if (x > 0) x--; 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]); 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]); wrefresh(scr); idx = 3; bcd[0] = 0; bcd[1] = 0; bcd[2] = 0; bcd[3] = 0; esc = 0; break; case 'S': case 'T': 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 { if (addr[address] == CURSES_BACKSPACE || addr[address] == '\b') { if (x > 0) { x--; } } else if (addr[address] == '\033') { esc = 1; } else { if (addr[address] == '\n') { x = 0; y+=1; } else { x+=1; } } } } #endif #endif if (regsize >= 2) { addr[address+1] = value >> 8; if (regsize >= 4) { addr[address+2] = value >> 16; addr[address+3] = value >> 24; if (regsize >= 8) { addr[address+4] = value >> 32; addr[address+5] = value >> 40; addr[address+6] = value >> 48; addr[address+7] = value >> 56; } } } break; case BCC: /* BCC Absolute. */ case 0x94: /* BCC Zero Matrix. */ if (!cpu->c[thread]) cpu->pc[thread] = address; break; case LSR: /* LSR Immediate. */ case LRB: /* Logical shift Right accumulator by B. */ case 0x63: /* LSR Absolute. */ case 0x65: /* LSR Zero Matrix. */ if (opcode == LRB) { value = cpu->b[thread]; } sum = (value < 64) ? cpu->a[thread] >> value : 0; cpu->z[thread] = (sum == 0); cpu->n[thread] = (sum >> 63); cpu->c[thread] = cpu->a[thread] & 1; cpu->a[thread] = sum; setflag(cpu->z[thread], Z); setflag(cpu->n[thread], N); setflag(cpu->c[thread], C); break; case ASR: /* ASR Immediate. */ case ARB: /* Arithmetic shift Right accumulator by B. */ case 0xE3: /* ASR Absolute. */ case 0xE5: /* ASR Zero Matrix. */ if (opcode == ARB) value = cpu->b[thread]; sign = cpu->a[thread] & 0x8000000000000000; sum = (value < 64) ? (cpu->a[thread] >> value) | sign : 0; cpu->z[thread] = (sum == 0); cpu->n[thread] = (sum >> 63); cpu->c[thread] = cpu->a[thread] & 1; cpu->a[thread] = sum; setflag(cpu->z[thread], Z); setflag(cpu->n[thread], N); setflag(cpu->c[thread], C); break; case CLC: /* CLear Carry flag. */ cpu->c[thread] = 0; setflag(cpu->c[thread], C); break; case LDB: /* LDB Immediate. */ case LDA: /* LDA Immediate. */ case LDY: /* LDY Immediate. */ case LDX: /* LDX Immediate. */ case 0x1E: /* LDB Absolute. */ case 0x19: /* LDA Absolute. */ case 0x1A: /* LDY Absolute. */ case 0x1B: /* LDX Absolute. */ case 0x3E: /* LDB Zero Matrix. */ case 0x39: /* LDA Zero Matrix. */ case 0x3A: /* LDY Zero Matrix. */ case 0x3B: /* LDX Zero Matrix. */ case 0x5E: /* LDB Zero Matrix, Indexed with X. */ case 0x59: /* LDA Zero Matrix, Indexed with X. */ case 0x5A: /* LDY Zero Matrix, Indexed with X. */ case 0x5B: /* LDX Zero Matrix, Indexed with Y. */ case 0x7E: /* LDB Zero Matrix, Indexed with Y. */ case 0x79: /* LDA Zero Matrix, Indexed with Y. */ case 0x7A: /* LDY Indirect. */ case 0x7B: /* LDX Indirect. */ case 0x9E: /* LDB Indirect. */ case 0x99: /* LDA Indirect. */ case 0x9A: /* LDY Indexed Indirect. */ case 0x9B: /* LDX Indirect Indexed. */ case 0xBE: /* LDB Indexed Indirect. */ case 0xB9: /* LDA Indexed Indirect. */ case 0xDE: /* LDB Indirect Indexed. */ case 0xD9: /* 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]; if (regsize >= 2) { value += addr[address+1] << 8; if (regsize >= 4) { value += addr[address+2] << 16; value += addr[address+3] << 24; if (regsize >= 8) { 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; } } } switch (opcode) { case LDB: case 0x1E: case 0x3E: case 0x5E: case 0x7E: case 0x9E: case 0xBE: case 0xDE: cpu->b[thread] = value; break; case LDA: case 0x19: case 0x39: case 0x59: case 0x79: case 0x99: case 0xB9: case 0xD9: cpu->a[thread] = value; break; case LDY: case 0x1A: case 0x3A: case 0x5A: case 0x7A: case 0x9A: cpu->y[thread] = value; break; case LDX: case 0x1B: case 0x3B: case 0x5B: case 0x7B: case 0x9B: cpu->x[thread] = value; break; } cpu->z[thread] = (value == 0); cpu->n[thread] = (value >> 63); setflag(cpu->z[thread], Z); setflag(cpu->n[thread], N); break; case BEQ: /* BEQ Absolute. */ case 0xA4: /* BEQ Zero Matrix. */ if (cpu->z[thread]) cpu->pc[thread] = address; break; case ROL: /* ROL Immediate. */ case RLB: /* Rotate Left accumulator by B. */ case 0x73: /* ROL Absolute. */ case 0x75: /* ROL Zero Matrix. */ if (opcode == RLB) { value = cpu->b[thread]; } sum = cpu->a[thread] << value; sum |= cpu->c[thread]; cpu->z[thread] = (sum == 0); cpu->n[thread] = (sum >> 63); cpu->c[thread] = cpu->a[thread] >> (uint64_t)64-value; cpu->a[thread] = sum; setflag(cpu->z[thread], Z); setflag(cpu->n[thread], N); setflag(cpu->c[thread], C); break; case SSP: /* Set Stack Protection flag. */ cpu->s[thread] = 1; setflag(cpu->s[thread], S); break; case BNE: /* BNE Absolute. */ case 0xB4: /* BNE Zero Matrix. */ if (!cpu->z[thread]) cpu->pc[thread] = address; break; case ROR: /* ROR Immediate. */ case RRB: /* Rotate Right accumulator by B. */ case 0x83: /* ROR Absolute. */ case 0x85: /* ROR Zero Matrix. */ if (opcode == RRB) { value = cpu->b[thread]; } sum = cpu->a[thread] >> value; sum |= (uint64_t)cpu->c[thread] << (uint64_t)64-value; cpu->z[thread] = (sum == 0); cpu->n[thread] = (sum >> 63); cpu->c[thread] = cpu->a[thread] & 1; cpu->a[thread] = sum; setflag(cpu->z[thread], Z); setflag(cpu->n[thread], N); setflag(cpu->c[thread], C); break; case CSP: /* Clear Stack Protection flag. */ cpu->s[thread] = 0; setflag(cpu->s[thread], S); break; case BVS: /* BVS Absolute. */ case 0xC4: /* BVS Zero Matrix. */ if (cpu->v[thread]) cpu->pc[thread] = address; break; case MUL: /* MUL Immediate. */ case MAB: /* Multiply Accumulator by B. */ case 0x93: /* MUL Absolute. */ case 0x95: /* MUL Zero Matrix. */ if (opcode == MAB) { value = cpu->b[thread]; } sum = cpu->a[thread]*value+cpu->c[thread]; cpu->a[thread] = sum; cpu->z[thread] = (sum == 0); cpu->n[thread] = (sum >> 63); cpu->v[thread] = !((cpu->a[thread]^value) & 0x8000000000000000) && ((cpu->a[thread]^sum) & 0x8000000000000000); cpu->c[thread] = (!((cpu->a[thread]^sum) && (cpu->a[thread]^value)) && (cpu->a[thread] >= ((uint64_t)1 << 32) && value >= ((uint64_t)1 << 32))); setflag(cpu->z[thread], Z); setflag(cpu->n[thread], N); setflag(cpu->v[thread], V); setflag(cpu->c[thread], C); break; case SEV: /* SEt oVerflow flag. */ cpu->v[thread] = 1; setflag(cpu->v[thread], V); break; case BVC: /* BVC Absolute. */ case 0xD4: /* BVC Zero Matrix. */ if (!cpu->v[thread]) cpu->pc[thread] = address; break; case DIV: /* DIV Immediate. */ case DAB: /* Divide Accumulator by B. */ case 0xA3: /* DIV Absolute. */ case 0xA5: /* DIV Zero Matrix. */ if (opcode != DAB) { cpu->b[thread] = cpu->a[thread] % value; } else { value = cpu->b[thread]; cpu->x[thread] = cpu->a[thread] % value; } sum = cpu->a[thread]/value; cpu->a[thread] = sum; cpu->z[thread] = (sum == 0); cpu->n[thread] = (sum >> 63); setflag(cpu->z[thread], Z); setflag(cpu->n[thread], N); break; case CLV: /* CLear oVerflow flag. */ cpu->v[thread] = 0; setflag(cpu->v[thread], V); break; case RTS: /* ReTurn from Subroutine. */ if (addrsize) stksize = 32; else stksize = 8; for (uint8_t i = 0; i < stksize; i+=8) { cpu->sp[thread]++; if (i) cpu->pc[thread] += addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << i; else cpu->pc[thread] = addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]]; } break; case CPB: /* CPB Immediate. */ case CMP: /* CMP Immediate. */ case CAB: /* Compare Accumulator, and B. */ case CPY: /* CPY Immediate. */ case CPX: /* CPX Immediate. */ case 0xCA: /* CPY Absolute. */ case 0xCB: /* CPX Absolute. */ case 0xB3: /* CMP Absolute. */ case 0x36: /* CPB Absolute. */ case 0xDA: /* CPY Zero Matrix. */ case 0xDB: /* CPX Zero Matrix. */ case 0xB5: /* CMP Zero Matrix. */ case 0x46: /* CPB Zero Matrix. */ case 0xF1: /* CMP Indirect. */ case 0xEA: /* CPY Indirect. */ case 0xEB: /* CPX Indirect. */ case 0x56: /* CPB Indirect. */ case 0xF3: /* CMP Indexed Indirect. */ case 0xFA: /* CPY Indexed Indirect. */ case 0x66: /* CPB Indexed Indirect. */ case 0xF5: /* CMP Indirect Indexed. */ case 0xFB: /* CPX Indirect Indexed. */ case 0x76: /* CPB Indirect Indexed. */ if (opcode == CAB) { value = cpu->b[thread]; } switch (opcode) { case CPB: case 0x36: case 0x46: case 0x56: case 0x66: case 0x76: reg = cpu->b[thread]; break; case CMP: case CAB: case 0xB3: case 0xB5: case 0xF1: case 0xF3: case 0xF5: reg = cpu->a[thread]; break; case CPY: case 0xCA: case 0xDA: case 0xEA: case 0xFA: reg = cpu->y[thread]; break; case LDX: case 0xCB: case 0xDB: case 0xEB: case 0xFB: reg = cpu->x[thread]; break; } sum = reg-value; cpu->n[thread] = (sum & 0x8000000000000000); cpu->v[thread] = ((reg^value) & 0x8000000000000000) && ((reg^sum) & 0x8000000000000000); cpu->z[thread] = (sum == 0); cpu->c[thread] = (reg >= value); setflag(cpu->n[thread], N); setflag(cpu->v[thread], V); setflag(cpu->z[thread], Z); setflag(cpu->c[thread], 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]++; cpu->ps = addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << 8*thread; for (uint8_t i = 0; i < 64; i+=8) { cpu->sp[thread]++; if (i) cpu->pc[thread] += addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << i; else cpu->pc[thread] = addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]]; } break; case INC: /* INC Accumulator. */ case IAB: case INY: case INX: if (opcode == INC || opcode == IAB) { cpu->a[thread]+=1; if (opcode == IAB) cpu->b[thread]+=1; cpu->z[thread] = (cpu->a[thread] == 0); cpu->n[thread] = (cpu->a[thread] >> 63); } else if (opcode == INY) { cpu->y[thread]+=1; cpu->z[thread] = (cpu->y[thread] == 0); cpu->n[thread] = (cpu->y[thread] >> 63); } else if (opcode == INX) { cpu->x[thread]+=1; cpu->z[thread] = (cpu->x[thread] == 0); cpu->n[thread] = (cpu->x[thread] >> 63); } setflag(cpu->z[thread], Z); setflag(cpu->n[thread], N); break; case 0x04: /* JMP Indirect. */ case 0x14: /* JMP Indexed Indirect. */ case 0x24: /* JMP Indirect Indexed. */ case 0xD0: /* JMP Zero Matrix. */ cpu->pc[thread] = address; break; case DEC: /* DEC Accumulator. */ case DBA: case DEY: case DEX: if (opcode == DEC || opcode == DBA) { cpu->a[thread]-=1; if (opcode == DBA) cpu->b[thread]-=1; cpu->z[thread] = (cpu->a[thread] == 0); cpu->n[thread] = (cpu->a[thread] >> 63); } else if (opcode == DEY) { cpu->y[thread]-=1; cpu->z[thread] = (cpu->y[thread] == 0); cpu->n[thread] = (cpu->y[thread] >> 63); } else if (opcode == DEX) { cpu->x[thread]-=1; cpu->z[thread] = (cpu->x[thread] == 0); cpu->n[thread] = (cpu->x[thread] >> 63); } setflag(cpu->z[thread], Z); setflag(cpu->n[thread], N); break; case JSL: /* Jump to Subroutine Long. */ if (addrsize) stksize = 56; else stksize = 8; for (int8_t i = stksize; i >= 0; i-=8) { if (i) addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] >> i; else addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] & 0xFF; cpu->sp[thread]--; } cpu->pc[thread] = address; break; case 0xC3: /* INC Absolute. */ case 0xC5: /* INC Zero Matrix. */ addr[address]++; cpu->z[thread] = (addr[address] == 0); cpu->n[thread] = (addr[address] >> 7); setflag(cpu->z[thread], Z); setflag(cpu->n[thread], N); break; case NOP: /* No OPeration. */ break; case RTL: /* ReTurn from subroutine Long. */ if (addrsize) stksize = 64; else stksize = 16; for (uint8_t i = 0; i < stksize; i+=8) { cpu->sp[thread]++; if (i) cpu->pc[thread] += addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] << i; else cpu->pc[thread] = addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]]; } break; case 0xD3: /* DEC Absolute. */ case 0xD5: /* DEC Zero Matrix. */ addr[address]--; cpu->z[thread] = (addr[address] == 0); cpu->n[thread] = (addr[address] >> 7); setflag(cpu->z[thread], Z); setflag(cpu->n[thread], N); break; case BRK: /* BReaK. */ for (int8_t i = stksize; i >= 0; i-=8) { if (i) addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] >> i; else addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->pc[thread] & 0xFF; cpu->sp[thread]--; } addr[(cpu->stk_st[thread] << 16)+cpu->sp[thread]] = (uint64_t)cpu->ps >> thread << 3; cpu->sp[thread]--; cpu->i[thread] = 1; setflag(cpu->i[thread], I); cpu->pc[thread] = (uint64_t)addr[0xFFE0] | (uint64_t)addr[0xFFE1] << 8 | (uint64_t)addr[0xFFE2] << 16 | (uint64_t)addr[0xFFE3] << 24 | (uint64_t)addr[0xFFE4] << 32 | (uint64_t)addr[0xFFE5] << 40 | (uint64_t)addr[0xFFE6] << 48 | (uint64_t)addr[0xFFE7] << 56; break; case WAI: /* WAit for Interrupt. */ wai = 1; 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); break; default: break; } ins++; 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 (!addr[CTRL_ADDR]) kbd_ln = 0; else kbd_ln = 1; /*if (kbd_ln) usleep(16666); usleep(500000);*/ #if debug && !bench #if keypoll pthread_mutex_lock(&mutex); #endif /*mvwprintw(scr, getmaxy(scr)-lines, 0, "Operand: $%llx" ", $%04llx: $%02x, $%04llx: $%02x" ", $1000: $%02x, $1001: $%02x " , value , RX_ADDR, addr[RX_ADDR], TX_ADDR, addr[TX_ADDR] , addr[0x1000], addr[0x1001]);*/ mvwprintw(scr, (6*thread)+1, 0, "Instructions executed: %llu, Clock cycles: %llu\r", ins, iclk); wrefresh(scr); #if keypoll pthread_mutex_unlock(&mutex); #endif #endif #if bench if (ins >= BENCH_INST) { end = 1; pthread_mutex_lock(&main_mutex); threads_done++; inst[thread] = ins; clk[thread] = iclk; pthread_cond_signal(&main_cond); pthread_mutex_unlock(&main_mutex); gettimeofday(&en[thread], 0); } #endif } free(s); } int main(int argc, char **argv) { struct suxthr thr[THREADS]; char *tmp = malloc(2048); ibcount = 0; addr = malloc(0x04000000); inss = 0; int v = 0; 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); wrefresh(scr); start_color(); use_default_colors(); init_pair(1, COLOR_WHITE, -1); attron(COLOR_PAIR(1) | A_BOLD); wmove(scr, 0, 0); #endif for (int i = 0; i < THREADS; i++) { thr[i].sx.sp[i] = 0xFFFF; thr[i].sx.stk_st[i] = i+1; if (i) { 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[0xFF50+(8*(i-1))] | (uint64_t)addr[0xFF51+(8*(i-1))] << 8 | (uint64_t)addr[0xFF52+(8*(i-1))] << 16 | (uint64_t)addr[0xFF53+(8*(i-1))] << 24 | (uint64_t)addr[0xFF54+(8*(i-1))] << 32 | (uint64_t)addr[0xFF55+(8*(i-1))] << 40 | (uint64_t)addr[0xFF56+(8*(i-1))] << 48 | (uint64_t)addr[0xFF57+(8*(i-1))] << 56; } else { 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[0xFFC0] | (uint64_t)addr[0xFFC1] << 8 | (uint64_t)addr[0xFFC2] << 16 | (uint64_t)addr[0xFFC3] << 24 | (uint64_t)addr[0xFFC4] << 32 | (uint64_t)addr[0xFFC5] << 40 | (uint64_t)addr[0xFFC6] << 48 | (uint64_t)addr[0xFFC7] << 56; } thr[i].th = i; } pthread_t therads[THREADS]; int result; for (int i = 0; i < THREADS; i++) { inst[i] = 0; } for (int i = 0; i < THREADS; i++) { 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, i = 0; if ((step_key && step && !kbd_rdy) || !step || kbd_rdy) { if ((c != EOF && c !=-1)) { 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; kbd_ln = 0; } } #if keypoll pthread_mutex_lock(&mutex); #endif getyx(scr, y, x); c = wgetch(scr); if (c == 19) { step = 1; if (kbd_rdy) c = wgetch(scr); } if (kbd_rdy) { switch (c) { case ERR: addr[CTRL_ADDR] = 0; wmove(scr, getmaxy(scr)-1, 0); wprintw(scr, "c: %i, x: %i, y: %i, i: %i.", c, x, y, i++); wmove(scr, y, x); wrefresh(scr); 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); wprintw(scr, "c: %i, x: %i, y: %i, i: %i.", c, x, y, i++); wmove(scr, y, x); wrefresh(scr); #endif } if (c == '\n') kbd_ln = 1; #if !keypoll pthread_mutex_lock(&mutex); pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); #endif break; } } else { if ((c == 19 || c == 18) && step) { if (c == 18) step = 0; else if (c == 19) step_key = 1; #if !keypoll pthread_mutex_lock(&mutex); pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); #endif } } 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; double clkspd; double mhz; 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]; tclk += clk[i]; } else { inss = inst[i]; ttm = tm[i]; ipst = ips[i]; tclk = clk[i]; } clkspd = (tm[i]/1000000)*1000000/clk[i]; mhz = 1000000.0/clkspd/1000000; sprintf(tmp, "Instructions executed for thread %i: %llu, 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); } clkspd = (ttm/1000000)*1000000/tclk; mhz = 1000000.0/clkspd/1000000; sprintf(tmp, "Total Instructions executed: %llu, Total Instructions per Second in MIPS: %f, Clock cycles: %llu, Clock Speed in MHz: %f, tm: %f\n", inss, ipst, tclk, mhz, ttm/1000000); fwrite(tmp, sizeof(char), strlen(tmp), stdout); fflush(stdout); free(tmp); } #endif free(addr); return 0; }