diff options
Diffstat (limited to 'sux.c')
-rw-r--r-- | sux.c | 895 |
1 files changed, 767 insertions, 128 deletions
@@ -4,28 +4,47 @@ #include <pthread.h> #define bench 0 #if bench -#include <time.h> +#include <sys/time.h> #endif #define THREADS 1 +#define BENCH_INST 100000000*THREADS +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 lines[THREADS]; -struct sux *cpu; +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +pthread_barrier_t bar; +struct suxthr { + struct sux sx; + uint8_t th; +}; #if bench double ipc; -time_t str, en; +struct timeval str[THREADS], en[THREADS]; #endif void *run(void *args) { - uint8_t thread = *((uint8_t *) args); + struct suxthr *thr = (void *)args; + struct sux *cpu = &thr->sx; + uint8_t thread = thr->th; uint64_t address; uint8_t prefix = 0; uint8_t opcode = 0; uint8_t end = 0; + uint64_t sum = 0; + uint64_t value = 0; + uint64_t iclk = 0; + uint64_t ins = 0; + /*pthread_mutex_lock(&mutex);*/ +#if bench + gettimeofday(&str[thread], 0); +#endif while (!end) { prefix = addr[cpu->pc[thread]]; - if ((prefix & 0x07) == 0x07) cpu->pc[thread]++; else @@ -33,12 +52,11 @@ void *run(void *args) { opcode = addr[cpu->pc[thread]]; #if !bench - printf("\033[%uH\033[2K" - "pc: 0x%08llx, a: 0x%016llx, x: 0x%016llx, y: 0x%016llx" - ", sp: 0x%04lx, ps: 0x%016llx, opcode: 0x%02x, thread: %u, inst: %s\n" - , lines[thread] + printf("\033[%uH", lines[thread]); + printf("pc: 0x%08llx, a: 0x%016llx, x: 0x%016llx, y: 0x%016llx" + ", sp: 0x%04lx, ps: 0x%016llx, prefix: 0x%02x, opcode: 0x%02x, thread: %u, inst: %s \r" , cpu->pc[thread], cpu->a[thread], cpu->x[thread], cpu->y[thread] - , cpu->sp, cpu->ps, opcode, thread, opname[opcode]); + , cpu->sp, cpu->ps, prefix, opcode, thread, opname[opcode]); fflush(stdout); lines[thread]++; if (lines[thread] > 6*(thread+1)) @@ -50,7 +68,7 @@ void *run(void *args) { uint8_t tmp; address = cpu->pc[thread]; cpu->pc[thread]++; - clk++; + iclk++; switch(opcode) { case CPS: /* Clear Processor Status. */ for (uint8_t i = 0; i < 8; i++) { @@ -63,9 +81,58 @@ void *run(void *args) { } cpu->ps &= 0; break; - case ADC: adc(cpu, immaddr(cpu, thread, regsize), thread, regsize); break; /* ADC Immediate. */ - case 0x03: adc(cpu, absaddr(cpu, thread), thread, regsize); break; /* ADC Absolute. */ - case 0x05: adc(cpu, zeromtx(cpu, thread), thread, regsize); break; /* ADC Zero Matrix. */ + case ADC: /* ADC Immediate. */ + case 0x03: /* ADC Absolute. */ + case 0x05: /* ADC Zero Matrix. */ + if (opcode == ADC) { + address = cpu->pc[thread]; + cpu->pc[thread]++; + } + if (opcode == 0x03) { + address = (uint64_t)addr[cpu->pc[thread]] + | (uint64_t)addr[cpu->pc[thread]+1] << 8 + | (uint64_t)addr[cpu->pc[thread]+2] << 16 + | (uint64_t)addr[cpu->pc[thread]+3] << 24 + | (uint64_t)addr[cpu->pc[thread]+4] << 32 + | (uint64_t)addr[cpu->pc[thread]+5] << 40 + | (uint64_t)addr[cpu->pc[thread]+6] << 48 + | (uint64_t)addr[cpu->pc[thread]+7] << 56; + cpu->pc[thread]+=8; + iclk++; + } + if (opcode == 0x05) { + address = addr[cpu->pc[thread]] + | addr[cpu->pc[thread]+1] << 8 + | addr[cpu->pc[thread]+2] << 16 + | addr[cpu->pc[thread]+3] << 24; + cpu->pc[thread]+=4; + iclk++; + } + value = addr[address]; + if (regsize >= 2) { + value += (uint64_t)addr[address+1] << 8; + } + if (regsize >= 4) { + value += (uint64_t)addr[address+2] << 16; + value += (uint64_t)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; + } + 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); + (cpu->z[thread]) ? (cpu->ps |= (Z << 8*thread)) : (cpu->ps &= ~(Z << 8*thread)); + (cpu->n[thread]) ? (cpu->ps |= (N << 8*thread)) : (cpu->ps &= ~(N << 8*thread)); + (cpu->v[thread]) ? (cpu->ps |= (V << 8*thread)) : (cpu->ps &= ~(V << 8*thread)); + (cpu->c[thread]) ? (cpu->ps |= (C << 8*thread)) : (cpu->ps &= ~(C << 8*thread)); + break; case PHP: /* PusH Processor status to stack. */ tmp = addr[cpu->pc[thread]++]; if (tmp > 7) @@ -103,12 +170,70 @@ void *run(void *args) { push(cpu, cpu->x[thread] & 0xFF); break; case JMP: /* JMP Absolute. */ - address = absaddr(cpu, thread); + address = (uint64_t)addr[cpu->pc[thread]] + | (uint64_t)addr[cpu->pc[thread]+1] << 8 + | (uint64_t)addr[cpu->pc[thread]+2] << 16 + | (uint64_t)addr[cpu->pc[thread]+3] << 24 + | (uint64_t)addr[cpu->pc[thread]+4] << 32 + | (uint64_t)addr[cpu->pc[thread]+5] << 40 + | (uint64_t)addr[cpu->pc[thread]+6] << 48 + | (uint64_t)addr[cpu->pc[thread]+7] << 56; + cpu->pc[thread]+=8; + iclk++; cpu->pc[thread] = address; break; - case SBC: sbc(cpu, immaddr(cpu, thread, regsize), thread, regsize); break; /* SBC Immediate. */ - case 0x13: sbc(cpu, absaddr(cpu, thread), thread, regsize); break; /* SBC Absolute. */ - case 0x15: sbc(cpu, zeromtx(cpu, thread), thread, regsize); break; /* SBC Zero Matrix. */ + case SBC: /* SBC Immediate. */ + case 0x13: /* SBC Absolute. */ + case 0x15: /* SBC Zero Matrix. */ + if (opcode == SBC) { + address = cpu->pc[thread]; + cpu->pc[thread]++; + } + if (opcode == 0x13) { + address = (uint64_t)addr[cpu->pc[thread]] + | (uint64_t)addr[cpu->pc[thread]+1] << 8 + | (uint64_t)addr[cpu->pc[thread]+2] << 16 + | (uint64_t)addr[cpu->pc[thread]+3] << 24 + | (uint64_t)addr[cpu->pc[thread]+4] << 32 + | (uint64_t)addr[cpu->pc[thread]+5] << 40 + | (uint64_t)addr[cpu->pc[thread]+6] << 48 + | (uint64_t)addr[cpu->pc[thread]+7] << 56; + cpu->pc[thread]+=8; + iclk++; + } + if (opcode == 0x15) { + address = addr[cpu->pc[thread]] + | addr[cpu->pc[thread]+1] << 8 + | addr[cpu->pc[thread]+2] << 16 + | addr[cpu->pc[thread]+3] << 24; + cpu->pc[thread]+=4; + iclk++; + } + value = addr[address]; + if (regsize >= 2) { + value += (uint64_t)addr[address+1] << 8; + } + if (regsize >= 4) { + value += (uint64_t)addr[address+2] << 16; + value += (uint64_t)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; + } + 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); + (cpu->z[thread]) ? (cpu->ps |= (Z << 8*thread)) : (cpu->ps &= ~(Z << 8*thread)); + (cpu->n[thread]) ? (cpu->ps |= (N << 8*thread)) : (cpu->ps &= ~(N << 8*thread)); + (cpu->v[thread]) ? (cpu->ps |= (V << 8*thread)) : (cpu->ps &= ~(V << 8*thread)); + (cpu->c[thread]) ? (cpu->ps |= (C << 8*thread)) : (cpu->ps &= ~(C << 8*thread)); + cpu->a[thread] = sum; + break; case PLP: /* PuLl Processor status from stack. */ tmp = addr[cpu->pc[thread]++]; if (tmp > 7) @@ -167,96 +292,442 @@ void *run(void *args) { break; case AND: and_addr(cpu, &cpu->a[thread], immaddr(cpu, thread, regsize), thread, regsize); break; /* AND Immediate. */ case ANY: and_addr(cpu, &cpu->y[thread], immaddr(cpu, thread, regsize), thread, regsize); break; /* ANY Immediate. */ - case AAY: cpu->a[thread] = and(cpu, cpu->y[thread], thread); break; + case AAY: + case AAX: + if (opcode == AAY) + cpu->a[thread] &= cpu->y[thread]; + if (opcode == AAX) + cpu->a[thread] &= cpu->x[thread]; + cpu->z[thread] = (sum == 0); + cpu->n[thread] = (sum >> 63); + (cpu->z[thread]) ? (cpu->ps |= (Z << 8*thread)) : (cpu->ps &= ~(Z << 8*thread)); + (cpu->n[thread]) ? (cpu->ps |= (N << 8*thread)) : (cpu->ps &= ~(N << 8*thread)); + break; case ANX: and_addr(cpu, &cpu->x[thread], immaddr(cpu, thread, regsize), thread, regsize); break; /* ANX Immediate. */ - case AAX: cpu->a[thread] = and(cpu, cpu->x[thread], thread); break; case STT: stt(cpu, immaddr(cpu, thread, 1)); break; /* STart Thread. */ case 0x29: and_addr(cpu, &cpu->a[thread], absaddr(cpu, thread), thread, regsize); break; /* AND Absolute. */ case 0x2B: and_addr(cpu, &cpu->a[thread], zeromtx(cpu, thread), thread, regsize); break; /* AND Zero Matrix. */ - case BPO: bfc(cpu, cpu->n[thread], absaddr(cpu, thread), thread); break; /* Branch if POsitive. */ + case BPO: /* Branch if POsitive. */ + address = (uint64_t)addr[cpu->pc[thread]] + | (uint64_t)addr[cpu->pc[thread]+1] << 8 + | (uint64_t)addr[cpu->pc[thread]+2] << 16 + | (uint64_t)addr[cpu->pc[thread]+3] << 24 + | (uint64_t)addr[cpu->pc[thread]+4] << 32 + | (uint64_t)addr[cpu->pc[thread]+5] << 40 + | (uint64_t)addr[cpu->pc[thread]+6] << 48 + | (uint64_t)addr[cpu->pc[thread]+7] << 56; + cpu->pc[thread]+=8; + iclk++; + if (cpu->n[thread]) + cpu->pc[thread] = address; + break; case ORA: or_addr(cpu, &cpu->a[thread], immaddr(cpu, thread, regsize), thread, regsize); break; /* ORA Immediate. */ case ORY: or_addr(cpu, &cpu->y[thread], immaddr(cpu, thread, regsize), thread, regsize); break; /* ORY Immediate. */ - case OAY: cpu->a[thread] = or(cpu, cpu->y[thread], thread); break; case ORX: or_addr(cpu, &cpu->x[thread], immaddr(cpu, thread, regsize), thread, regsize); break; /* ORX Immediate. */ - case OAX: cpu->a[thread] = or(cpu, cpu->x[thread], thread); break; + case OAY: + case OAX: + if (opcode == OAY) + cpu->a[thread] |= cpu->y[thread]; + if (opcode == OAX) + cpu->a[thread] |= cpu->x[thread]; + cpu->z[thread] = (sum == 0); + cpu->n[thread] = (sum >> 63); + (cpu->z[thread]) ? (cpu->ps |= (Z << 8*thread)) : (cpu->ps &= ~(Z << 8*thread)); + (cpu->n[thread]) ? (cpu->ps |= (N << 8*thread)) : (cpu->ps &= ~(N << 8*thread)); + break; case SEI: /* SEt Interrupt. */ cpu->i[thread] = 1; - setps(cpu, thread); + (cpu->ps |= (I << 8*thread)); break; case 0x39: or_addr(cpu, &cpu->a[thread], absaddr(cpu, thread), thread, regsize); break; /* ORA Absolute. */ case 0x3B: or_addr(cpu, &cpu->a[thread], zeromtx(cpu, thread), thread, regsize); break; /* ORA Zero Matrix. */ - case BNG: bfs(cpu, cpu->n[thread], absaddr(cpu, thread), thread); break; /* Branch if NeGative. */ + case BNG: /* Branch if NeGative. */ + address = (uint64_t)addr[cpu->pc[thread]] + | (uint64_t)addr[cpu->pc[thread]+1] << 8 + | (uint64_t)addr[cpu->pc[thread]+2] << 16 + | (uint64_t)addr[cpu->pc[thread]+3] << 24 + | (uint64_t)addr[cpu->pc[thread]+4] << 32 + | (uint64_t)addr[cpu->pc[thread]+5] << 40 + | (uint64_t)addr[cpu->pc[thread]+6] << 48 + | (uint64_t)addr[cpu->pc[thread]+7] << 56; + cpu->pc[thread]+=8; + iclk++; + if (!cpu->n[thread]) + cpu->pc[thread] = address; + break; case XOR: xor_addr(cpu, &cpu->a[thread], immaddr(cpu, thread, regsize), thread, regsize); break; /* XOR Immediate. */ case XRY: xor_addr(cpu, &cpu->y[thread], immaddr(cpu, thread, regsize), thread, regsize); break; /* XRY Immediate. */ - case XAY: cpu->a[thread] = xor(cpu, cpu->y[thread], thread); break; + case XAY: + case XAX: + if (opcode == XAY) + cpu->a[thread] ^= cpu->y[thread]; + if (opcode == XAX) + cpu->a[thread] ^= cpu->x[thread]; + cpu->z[thread] = (sum == 0); + cpu->n[thread] = (sum >> 63); + (cpu->z[thread]) ? (cpu->ps |= (Z << 8*thread)) : (cpu->ps &= ~(Z << 8*thread)); + (cpu->n[thread]) ? (cpu->ps |= (N << 8*thread)) : (cpu->ps &= ~(N << 8*thread)); + break; case XRX: xor_addr(cpu, &cpu->x[thread], immaddr(cpu, thread, regsize), thread, regsize); break; /* XRX Immediate. */ - case XAX: cpu->a[thread] = xor(cpu, cpu->x[thread], thread); break; case CLI: /* CLear Interrupt. */ cpu->i[thread] = 0; - setps(cpu, thread); + (cpu->ps &= ~(I << 8*thread)); break; case 0x49: xor_addr(cpu, &cpu->a[thread], absaddr(cpu, thread), thread, regsize); break; /* XOR Absolute. */ case 0x4B: xor_addr(cpu, &cpu->a[thread], zeromtx(cpu, thread), thread, regsize); break; /* XOR Zero Matrix. */ - case BCS: bfs(cpu, cpu->c[thread], absaddr(cpu, thread), thread); break; /* Branch if Carry Set. */ - case LSL: lsl(cpu, immaddr(cpu, thread, 1), thread); break; /* LSL Immediate. */ + case BCS: /* Branch if Carry Set. */ + address = (uint64_t)addr[cpu->pc[thread]] + | (uint64_t)addr[cpu->pc[thread]+1] << 8 + | (uint64_t)addr[cpu->pc[thread]+2] << 16 + | (uint64_t)addr[cpu->pc[thread]+3] << 24 + | (uint64_t)addr[cpu->pc[thread]+4] << 32 + | (uint64_t)addr[cpu->pc[thread]+5] << 40 + | (uint64_t)addr[cpu->pc[thread]+6] << 48 + | (uint64_t)addr[cpu->pc[thread]+7] << 56; + cpu->pc[thread]+=8; + iclk++; + if (cpu->c[thread]) + cpu->pc[thread] = address; + break; + case LSL: /* LSL Immediate. */ + case 0x53: /* LSL Absolute. */ + case 0x55: /* LSL Zero Matrix. */ + if (opcode == LSL) { + address = cpu->pc[thread]; + cpu->pc[thread]++; + } + if (opcode == 0x53) { + address = (uint64_t)addr[cpu->pc[thread]] + | (uint64_t)addr[cpu->pc[thread]+1] << 8 + | (uint64_t)addr[cpu->pc[thread]+2] << 16 + | (uint64_t)addr[cpu->pc[thread]+3] << 24 + | (uint64_t)addr[cpu->pc[thread]+4] << 32 + | (uint64_t)addr[cpu->pc[thread]+5] << 40 + | (uint64_t)addr[cpu->pc[thread]+6] << 48 + | (uint64_t)addr[cpu->pc[thread]+7] << 56; + + cpu->pc[thread]+=8; + iclk++; + } + if (opcode == 0x55) { + address = addr[cpu->pc[thread]] + | addr[cpu->pc[thread]+1] << 8 + | addr[cpu->pc[thread]+2] << 16 + | addr[cpu->pc[thread]+3] << 24; + cpu->pc[thread]+=4; + iclk++; + } + value = addr[address]; + 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; + (cpu->z[thread]) ? (cpu->ps |= (Z << 8*thread)) : (cpu->ps &= ~(Z << 8*thread)); + (cpu->n[thread]) ? (cpu->ps |= (N << 8*thread)) : (cpu->ps &= ~(N << 8*thread)); + (cpu->c[thread]) ? (cpu->ps |= (C << 8*thread)) : (cpu->ps &= ~(C << 8*thread)); + break; case 0x52: and_addr(cpu, &cpu->y[thread], absaddr(cpu, thread), thread, regsize); break; /* ANY Absolute. */ - case 0x53: lsl(cpu, absaddr(cpu, thread), thread); break; /* LSL Absolute. */ case 0x54: and_addr(cpu, &cpu->x[thread], absaddr(cpu, thread), thread, regsize); break; /* ANX Absolute. */ - case 0x55: lsl(cpu, zeromtx(cpu, thread), thread); break; /* LSL Zero Matrix. */ case SEC: /* SEt Carry flag.*/ cpu->c[thread] = 1; - setps(cpu, thread); + (cpu->ps |= (C << 8*thread)); + break; + case STA: /* STA Absolute. */ + case STY: /* STY Absolute. */ + case STX: /* STX Absolute. */ + case 0x7B: /* STA Zero Matrix. */ + case 0x7D: /* STY Zero Matrix. */ + case 0x7E: /* STX Zero Matrix. */ + if (opcode == STA || opcode == STY || opcode == STX) { + address = (uint64_t)addr[cpu->pc[thread]] + | (uint64_t)addr[cpu->pc[thread]+1] << 8 + | (uint64_t)addr[cpu->pc[thread]+2] << 16 + | (uint64_t)addr[cpu->pc[thread]+3] << 24 + | (uint64_t)addr[cpu->pc[thread]+4] << 32 + | (uint64_t)addr[cpu->pc[thread]+5] << 40 + | (uint64_t)addr[cpu->pc[thread]+6] << 48 + | (uint64_t)addr[cpu->pc[thread]+7] << 56; + cpu->pc[thread]+=8; + iclk++; + } + if (opcode == 0x7B || opcode == 0x7D || opcode == 0x7E) { + address = addr[cpu->pc[thread]] + | addr[cpu->pc[thread]+1] << 8 + | addr[cpu->pc[thread]+2] << 16 + | addr[cpu->pc[thread]+3] << 24; + cpu->pc[thread]+=4; + iclk++; + } + if (opcode == STA || opcode == 0x7B) + value = cpu->a[thread]; + if (opcode == STY || opcode == 0x7D) + value = cpu->y[thread]; + if (opcode == STX || opcode == 0x7E) + value = cpu->x[thread]; + + addr[address] = value & 0xFF; + 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: /* Branch if Carry Clear. */ + address = (uint64_t)addr[cpu->pc[thread]] + | (uint64_t)addr[cpu->pc[thread]+1] << 8 + | (uint64_t)addr[cpu->pc[thread]+2] << 16 + | (uint64_t)addr[cpu->pc[thread]+3] << 24 + | (uint64_t)addr[cpu->pc[thread]+4] << 32 + | (uint64_t)addr[cpu->pc[thread]+5] << 40 + | (uint64_t)addr[cpu->pc[thread]+6] << 48 + | (uint64_t)addr[cpu->pc[thread]+7] << 56; + cpu->pc[thread]+=8; + iclk++; + if (!cpu->c[thread]) + cpu->pc[thread] = address; + break; + case LSR: /* LSR Immediate. */ + case 0x63: /* LSR Absolute. */ + case 0x65: /* LSR Zero Matrix. */ + if (opcode == LSR) { + address = cpu->pc[thread]; + cpu->pc[thread]++; + } + if (opcode == 0x63) { + address = (uint64_t)addr[cpu->pc[thread]] + | (uint64_t)addr[cpu->pc[thread]+1] << 8 + | (uint64_t)addr[cpu->pc[thread]+2] << 16 + | (uint64_t)addr[cpu->pc[thread]+3] << 24 + | (uint64_t)addr[cpu->pc[thread]+4] << 32 + | (uint64_t)addr[cpu->pc[thread]+5] << 40 + | (uint64_t)addr[cpu->pc[thread]+6] << 48 + | (uint64_t)addr[cpu->pc[thread]+7] << 56; + cpu->pc[thread]+=8; + iclk++; + } + if (opcode == 0x65) { + address = addr[cpu->pc[thread]] + | addr[cpu->pc[thread]+1] << 8 + | addr[cpu->pc[thread]+2] << 16 + | addr[cpu->pc[thread]+3] << 24; + cpu->pc[thread]+=4; + iclk++; + } + value = addr[address]; + 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; + (cpu->z[thread]) ? (cpu->ps |= (Z << 8*thread)) : (cpu->ps &= ~(Z << 8*thread)); + (cpu->n[thread]) ? (cpu->ps |= (N << 8*thread)) : (cpu->ps &= ~(N << 8*thread)); + (cpu->c[thread]) ? (cpu->ps |= (C << 8*thread)) : (cpu->ps &= ~(C << 8*thread)); break; - case 0x59: ld(cpu, &cpu->a[thread], absaddr(cpu, thread), thread, regsize); break; /* LDA Absolute. */ - case 0x5A: ld(cpu, &cpu->y[thread], absaddr(cpu, thread), thread, regsize); break; /* LDY Absolute. */ - case STA: st(cpu, &cpu->a[thread], absaddr(cpu, thread), thread, regsize); break; /* STA Absolute. */ - case 0x5C: ld(cpu, &cpu->x[thread], absaddr(cpu, thread), thread, regsize); break; /* LDX Absolute. */ - case STY: st(cpu, &cpu->y[thread], absaddr(cpu, thread), thread, regsize); break; /* STY Absolute. */ - case STX: st(cpu, &cpu->x[thread], absaddr(cpu, thread), thread, regsize); break; /* STX Absolute. */ - case BCC: bfc(cpu, cpu->c[thread], absaddr(cpu, thread), thread); break; /* Branch if Carry Clear. */ - case LSR: lsr(cpu, immaddr(cpu, thread, 1), thread); break; /* LSR Immediate. */ case 0x62: or_addr(cpu, &cpu->y[thread], absaddr(cpu, thread), thread, regsize); break; /* ORY Absolute. */ - case 0x63: lsr(cpu, absaddr(cpu, thread), thread); break; /* LSR Absolute. */ case 0x64: or_addr(cpu, &cpu->x[thread], absaddr(cpu, thread), thread, regsize); break; /* ORX Absolute. */ - case 0x65: lsr(cpu, zeromtx(cpu, thread), thread); break; /* LSR Zero Matrix. */ case CLC: /* CLear Carry flag. */ cpu->c[thread] = 0; - setps(cpu, thread); + (cpu->ps &= ~(C << 8*thread)); + break; + case 0x59: /* LDA Absolute. */ + case 0x5A: /* LDY Absolute. */ + case 0x5C: /* LDX Absolute. */ + case LDA: /* LDA Immediate. */ + case LDY: /* LDY Immediate. */ + case LDX: /* LDX Immediate. */ + case 0x79: /* LDA Zero Matrix. */ + case 0x7A: /* LDY Zero Matrix. */ + case 0x7C: /* LDX Zero Matrix. */ + if (opcode == LDA || opcode == LDY || opcode == LDX) { + address = cpu->pc[thread]; + cpu->pc[thread]+=regsize; + } + if (opcode == 0x59 || opcode == 0x5A || opcode == 0x5C) { + address = (uint64_t)addr[cpu->pc[thread]] + | (uint64_t)addr[cpu->pc[thread]+1] << 8 + | (uint64_t)addr[cpu->pc[thread]+2] << 16 + | (uint64_t)addr[cpu->pc[thread]+3] << 24 + | (uint64_t)addr[cpu->pc[thread]+4] << 32 + | (uint64_t)addr[cpu->pc[thread]+5] << 40 + | (uint64_t)addr[cpu->pc[thread]+6] << 48 + | (uint64_t)addr[cpu->pc[thread]+7] << 56; + cpu->pc[thread]+=8; + iclk++; + } + if (opcode == 0x79 || opcode == 0x7A || opcode == 0x7C) { + address = addr[cpu->pc[thread]] + | addr[cpu->pc[thread]+1] << 8 + | addr[cpu->pc[thread]+2] << 16 + | addr[cpu->pc[thread]+3] << 24; + cpu->pc[thread]+=4; + iclk++; + } + value = (uint64_t)addr[address]; + if (regsize >= 2) + value += (uint64_t)addr[address+1] << 8; + if (regsize >= 4) { + value += (uint64_t)addr[address+2] << 16; + value += (uint64_t)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 (opcode == LDA || opcode == 0x59 || opcode == 0x79) + cpu->a[thread] = value; + if (opcode == LDY || opcode == 0x5A || opcode == 0x7A) + cpu->y[thread] = value; + if (opcode == LDX || opcode == 0x5C || opcode == 0x7C) + cpu->x[thread] = value; + cpu->z[thread] = (value == 0); + cpu->n[thread] = (value >> 63); + (cpu->z[thread]) ? (cpu->ps |= (Z << 8*thread)) : (cpu->ps &= ~(Z << 8*thread)); + (cpu->n[thread]) ? (cpu->ps |= (N << 8*thread)) : (cpu->ps &= ~(N << 8*thread)); + break; + case BEQ: /* Branch if EQual. */ + address = (uint64_t)addr[cpu->pc[thread]] + | (uint64_t)addr[cpu->pc[thread]+1] << 8 + | (uint64_t)addr[cpu->pc[thread]+2] << 16 + | (uint64_t)addr[cpu->pc[thread]+3] << 24 + | (uint64_t)addr[cpu->pc[thread]+4] << 32 + | (uint64_t)addr[cpu->pc[thread]+5] << 40 + | (uint64_t)addr[cpu->pc[thread]+6] << 48 + | (uint64_t)addr[cpu->pc[thread]+7] << 56; + cpu->pc[thread]+=8; + iclk++; + if (cpu->z[thread]) + cpu->pc[thread] = address; + break; + case ROL: /* ROL Immediate. */ + case 0x73: /* ROL Absolute. */ + case 0x75: /* ROL Zero Matrix. */ + if (opcode == ROL) { + address = cpu->pc[thread]; + cpu->pc[thread]++; + } + if (opcode == 0x73) { + address = (uint64_t)addr[cpu->pc[thread]] + | (uint64_t)addr[cpu->pc[thread]+1] << 8 + | (uint64_t)addr[cpu->pc[thread]+2] << 16 + | (uint64_t)addr[cpu->pc[thread]+3] << 24 + | (uint64_t)addr[cpu->pc[thread]+4] << 32 + | (uint64_t)addr[cpu->pc[thread]+5] << 40 + | (uint64_t)addr[cpu->pc[thread]+6] << 48 + | (uint64_t)addr[cpu->pc[thread]+7] << 56; + cpu->pc[thread]+=8; + iclk++; + } + if (opcode == 0x75) { + address = addr[cpu->pc[thread]] + | addr[cpu->pc[thread]+1] << 8 + | addr[cpu->pc[thread]+2] << 16 + | addr[cpu->pc[thread]+3] << 24; + cpu->pc[thread]+=4; + iclk++; + } + value = addr[address]; + 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; + (cpu->z[thread]) ? (cpu->ps |= (Z << 8*thread)) : (cpu->ps &= ~(Z << 8*thread)); + (cpu->n[thread]) ? (cpu->ps |= (N << 8*thread)) : (cpu->ps &= ~(N << 8*thread)); + (cpu->c[thread]) ? (cpu->ps |= (C << 8*thread)) : (cpu->ps &= ~(C << 8*thread)); break; - case LDA: ld(cpu, &cpu->a[thread], immaddr(cpu, thread, regsize), thread, regsize); break; /* LDA Immediate. */ - case LDY: ld(cpu, &cpu->y[thread], immaddr(cpu, thread, regsize), thread, regsize); break; /* LDY Immediate. */ - case LDX: ld(cpu, &cpu->x[thread], immaddr(cpu, thread, regsize), thread, regsize); break; /* LDX Immediate. */ - case BEQ: bfs(cpu, cpu->z[thread], absaddr(cpu, thread), thread); break; /* Branch if EQual. */ - case ROL: rol(cpu, immaddr(cpu, thread, 1), thread); break; /* ROL Immediate. */ case 0x72: xor_addr(cpu, &cpu->y[thread], absaddr(cpu, thread), thread, regsize); break; /* XRY Absolute. */ - case 0x73: rol(cpu, absaddr(cpu, thread), thread); break; /* ROL Absolute. */ case 0x74: xor_addr(cpu, &cpu->x[thread], absaddr(cpu, thread), thread, regsize); break; /* XRX Absolute. */ - case 0x75: rol(cpu, zeromtx(cpu, thread), thread); break; /* ROL Zero Matrix. */ case SSP: /* Set Stack Protection flag. */ cpu->s[thread] = 1; - setps(cpu, thread); + (cpu->ps |= (S << 8*thread)); + break; + case BNE: /* Branch if Not Equal. */ + address = (uint64_t)addr[cpu->pc[thread]] + | (uint64_t)addr[cpu->pc[thread]+1] << 8 + | (uint64_t)addr[cpu->pc[thread]+2] << 16 + | (uint64_t)addr[cpu->pc[thread]+3] << 24 + | (uint64_t)addr[cpu->pc[thread]+4] << 32 + | (uint64_t)addr[cpu->pc[thread]+5] << 40 + | (uint64_t)addr[cpu->pc[thread]+6] << 48 + | (uint64_t)addr[cpu->pc[thread]+7] << 56; + cpu->pc[thread]+=8; + iclk++; + if (!cpu->z[thread]) + cpu->pc[thread] = address; + break; + case ROR: /* ROR Immediate. */ + case 0x83: /* ROR Absolute. */ + case 0x85: /* ROR Zero Matrix. */ + if (opcode == ROR) { + address = cpu->pc[thread]; + cpu->pc[thread]++; + } + if (opcode == 0x83) { + address = (uint64_t)addr[cpu->pc[thread]] + | (uint64_t)addr[cpu->pc[thread]+1] << 8 + | (uint64_t)addr[cpu->pc[thread]+2] << 16 + | (uint64_t)addr[cpu->pc[thread]+3] << 24 + | (uint64_t)addr[cpu->pc[thread]+4] << 32 + | (uint64_t)addr[cpu->pc[thread]+5] << 40 + | (uint64_t)addr[cpu->pc[thread]+6] << 48 + | (uint64_t)addr[cpu->pc[thread]+7] << 56; + cpu->pc[thread]+=8; + iclk++; + } + if (opcode == 0x85) { + address = addr[cpu->pc[thread]] + | addr[cpu->pc[thread]+1] << 8 + | addr[cpu->pc[thread]+2] << 16 + | addr[cpu->pc[thread]+3] << 24; + cpu->pc[thread]+=4; + iclk++; + } + value = addr[address]; + 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; + (cpu->z[thread]) ? (cpu->ps |= (Z << 8*thread)) : (cpu->ps &= ~(Z << 8*thread)); + (cpu->n[thread]) ? (cpu->ps |= (N << 8*thread)) : (cpu->ps &= ~(N << 8*thread)); + (cpu->c[thread]) ? (cpu->ps |= (C << 8*thread)) : (cpu->ps &= ~(C << 8*thread)); break; - case 0x79: ld(cpu, &cpu->a[thread], zeromtx(cpu, thread), thread, regsize); break; /* LDA Zero Matrix. */ - case 0x7A: ld(cpu, &cpu->y[thread], zeromtx(cpu, thread), thread, regsize); break; /* LDY Zero Matrix. */ - case 0x7B: st(cpu, &cpu->a[thread], zeromtx(cpu, thread), thread, regsize); break; /* STA Zero Matrix. */ - case 0x7C: ld(cpu, &cpu->x[thread], zeromtx(cpu, thread), thread, regsize); break; /* LDX Zero Matrix. */ - case 0x7D: st(cpu, &cpu->y[thread], zeromtx(cpu, thread), thread, regsize); break; /* STY Zero Matrix. */ - case 0x7E: st(cpu, &cpu->x[thread], zeromtx(cpu, thread), thread, regsize); break; /* STX Zero Matrix. */ - case BNE: bfc(cpu, cpu->z[thread], absaddr(cpu, thread), thread); break; /* Branch if Not Equal. */ - case ROR: ror(cpu, immaddr(cpu, thread, 1), thread); break; /* ROR Immediate. */ case 0x82: and_addr(cpu, &cpu->y[thread], zeromtx(cpu, thread), thread, regsize); break; /* ANY Zero Matrix. */ - case 0x83: ror(cpu, absaddr(cpu, thread), thread); break; /* ROR Absolute. */ case 0x84: and_addr(cpu, &cpu->x[thread], zeromtx(cpu, thread), thread, regsize); break; /* ANX Zero Matrix. */ - case 0x85: ror(cpu, zeromtx(cpu, thread), thread); break; /* ROR Zero Matrix. */ case CSP: /* Clear Stack Protection flag. */ cpu->s[thread] = 0; - setps(cpu, thread); + (cpu->ps &= ~(S << 8*thread)); break; case 0x89: ld(cpu, &cpu->a[thread], zeromx(cpu, thread), thread, regsize); break; /* LDA Zero Matrix, Indexed with X. */ case 0x8A: ld(cpu, &cpu->y[thread], zeromx(cpu, thread), thread, regsize); break; /* LDY Zero Matrix, Indexed with X. */ case 0x8B: st(cpu, &cpu->a[thread], zeromx(cpu, thread), thread, regsize); break; /* STA Zero Matrix, Indexed with X. */ case 0x8D: st(cpu, &cpu->y[thread], zeromx(cpu, thread), thread, regsize); break; /* STY Zero Matrix, Indexed with X. */ - case BVS: bfs(cpu, cpu->v[thread], absaddr(cpu, thread), thread); break; /* Branch if oVerflow Set. */ + case BVS: /* Branch if oVerflow Set. */ + address = (uint64_t)addr[cpu->pc[thread]] + | (uint64_t)addr[cpu->pc[thread]+1] << 8 + | (uint64_t)addr[cpu->pc[thread]+2] << 16 + | (uint64_t)addr[cpu->pc[thread]+3] << 24 + | (uint64_t)addr[cpu->pc[thread]+4] << 32 + | (uint64_t)addr[cpu->pc[thread]+5] << 40 + | (uint64_t)addr[cpu->pc[thread]+6] << 48 + | (uint64_t)addr[cpu->pc[thread]+7] << 56; + cpu->pc[thread]+=8; + iclk++; + if (cpu->v[thread]) + cpu->pc[thread] = address; + break; case MUL: mul(cpu, immaddr(cpu, thread, regsize), thread, regsize); break; /* MUL Immediate. */ case 0x92: or_addr(cpu, &cpu->y[thread], zeromtx(cpu, thread), thread, regsize); break; /* ORY Zero Matrix. */ case 0x93: mul(cpu, absaddr(cpu, thread), thread, regsize); break; /* MUL Absolute. */ @@ -264,13 +735,26 @@ void *run(void *args) { case 0x95: mul(cpu, zeromtx(cpu, thread), thread, regsize); break; /* MUL Zero Matrix. */ case SEV: /* SEt oVerflow flag. */ cpu->v[thread] = 1; - setps(cpu, thread); + (cpu->ps |= (V << 8*thread)); break; case 0x99: ld(cpu, &cpu->a[thread], zeromy(cpu, thread), thread, regsize); break; /* LDA Zero Matrix, Indexed with Y. */ case 0x9B: ld(cpu, &cpu->x[thread], zeromy(cpu, thread), thread, regsize); break; /* STA Zero Matrix, Indexed with Y. */ case 0x9C: st(cpu, &cpu->a[thread], zeromy(cpu, thread), thread, regsize); break; /* LDX Zero Matrix, Indexed with Y. */ case 0x9E: st(cpu, &cpu->x[thread], zeromy(cpu, thread), thread, regsize); break; /* STX Zero Matrix, Indexed with Y. */ - case BVC: bfc(cpu, cpu->z[thread], absaddr(cpu, thread), thread); break; /* Branch if oVerflow Clear. */ + case BVC: /* Branch if oVerflow Clear. */ + address = (uint64_t)addr[cpu->pc[thread]] + | (uint64_t)addr[cpu->pc[thread]+1] << 8 + | (uint64_t)addr[cpu->pc[thread]+2] << 16 + | (uint64_t)addr[cpu->pc[thread]+3] << 24 + | (uint64_t)addr[cpu->pc[thread]+4] << 32 + | (uint64_t)addr[cpu->pc[thread]+5] << 40 + | (uint64_t)addr[cpu->pc[thread]+6] << 48 + | (uint64_t)addr[cpu->pc[thread]+7] << 56; + cpu->pc[thread]+=8; + iclk++; + if (!cpu->v[thread]) + cpu->pc[thread] = address; + break; case DIV: divd(cpu, immaddr(cpu, thread, regsize), thread, regsize); break; /* DIV Immediate. */ case 0xA2: xor_addr(cpu, &cpu->y[thread], zeromtx(cpu, thread), thread, regsize); break; /* XRY Zero Matrix. */ case 0xA3: divd(cpu, absaddr(cpu, thread), thread, regsize); break; /* DIV Absolute. */ @@ -278,7 +762,7 @@ void *run(void *args) { case 0xA5: divd(cpu, zeromtx(cpu, thread), thread, regsize); break; /* DIV Zero Matrix. */ case CLV: /* CLear oVerflow flag. */ cpu->v[thread] = 0; - setps(cpu, thread); + (cpu->ps &= ~(V << 8*thread)); break; case RTS: /* ReTurn from Subroutine. */ cpu->pc[thread] = (uint64_t)pull(cpu); @@ -286,11 +770,79 @@ void *run(void *args) { cpu->pc[thread] += ((uint64_t)pull(cpu) << 16); cpu->pc[thread] += ((uint64_t)pull(cpu) << 24) + 1; break; - case CMP: cmp_addr(cpu, cpu->a[thread], immaddr(cpu, thread, regsize), thread, regsize); break; /* CMP Immediate. */ - case CPY: cmp_addr(cpu, cpu->y[thread], immaddr(cpu, thread, regsize), thread, regsize); break; /* CPY Immediate. */ - case CAY: cmp(cpu, cpu->a[thread], cpu->y[thread], thread); break; - case CPX: cmp_addr(cpu, cpu->x[thread], immaddr(cpu, thread, regsize), thread, regsize); break; /* CPX Immediate. */ - case CAX: cmp(cpu, cpu->a[thread], cpu->x[thread], thread); break; + case CMP: /* CMP Immediate. */ + case CPY: /* CPY Immediate. */ + case CPX: /* CPX Immediate. */ + case 0xE2: /* CPY Absolute. */ + case 0xE4: /* CPX Absolute. */ + case 0xE5: /* CMP Absolute. */ + case 0xF2: /* CPY Zero Matrix. */ + case 0xF4: /* CPX Zero Matrix. */ + case 0xF5: /* CMP Zero Matrix. */ + if (opcode == CMP || opcode == CPY || opcode == CPX) + address = immaddr(cpu, thread, regsize); + if (opcode == 0xE5 || opcode == 0xE2 || opcode == 0xE4) { + address = (uint64_t)addr[cpu->pc[thread]] + | (uint64_t)addr[cpu->pc[thread]+1] << 8 + | (uint64_t)addr[cpu->pc[thread]+2] << 16 + | (uint64_t)addr[cpu->pc[thread]+3] << 24 + | (uint64_t)addr[cpu->pc[thread]+4] << 32 + | (uint64_t)addr[cpu->pc[thread]+5] << 40 + | (uint64_t)addr[cpu->pc[thread]+6] << 48 + | (uint64_t)addr[cpu->pc[thread]+7] << 56; + cpu->pc[thread]+=8; + iclk++; + } + if (opcode == 0xF5 || opcode == 0xF2 || opcode == 0xF4) { + address = addr[cpu->pc[thread]] + | addr[cpu->pc[thread]+1] << 8 + | addr[cpu->pc[thread]+2] << 16 + | addr[cpu->pc[thread]+3] << 24; + cpu->pc[thread]+=4; + iclk++; + } + value = (uint64_t)addr[address]; + if (regsize >= 2) + value += (uint64_t)addr[address+1] << 8; + if (regsize >= 4) { + value += (uint64_t)addr[address+2] << 16; + value += (uint64_t)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 (opcode == CMP || opcode == 0xE5 || opcode == 0xF5) + sum = cpu->a[thread]-value; + if (opcode == CPY || opcode == 0xE2 || opcode == 0xF2) + sum = cpu->y[thread]-value; + if (opcode == CPX || opcode == 0xE4 || opcode == 0xF4) + sum = cpu->x[thread]-value; + cpu->n[thread] = (sum & 0x8000000000000000) ? 1 : 0; + cpu->z[thread] = (sum == 0) ? 1 : 0; + cpu->c[thread] = (sum > value) ? 1 : 0; + (cpu->z[thread]) ? (cpu->ps |= (Z << 8*thread)) : (cpu->ps &= ~(Z << 8*thread)); + (cpu->n[thread]) ? (cpu->ps |= (N << 8*thread)) : (cpu->ps &= ~(N << 8*thread)); + (cpu->c[thread]) ? (cpu->ps |= (C << 8*thread)) : (cpu->ps &= ~(C << 8*thread)); + break; + case CAY: + case CAX: + if (opcode == CAY) + sum = cpu->a[thread]-cpu->y[thread]; + if (opcode == CAX) + sum = cpu->a[thread]-cpu->x[thread]; + cpu->n[thread] = (sum & 0x8000000000000000) ? 1 : 0; + cpu->z[thread] = (sum == 0) ? 1 : 0; + if (opcode == CAY) + cpu->c[thread] = (sum > cpu->y[thread]) ? 1 : 0; + if (opcode == CAX) + cpu->c[thread] = (sum > cpu->x[thread]) ? 1 : 0; + (cpu->z[thread]) ? (cpu->ps |= (Z << 8*thread)) : (cpu->ps &= ~(Z << 8*thread)); + (cpu->n[thread]) ? (cpu->ps |= (N << 8*thread)) : (cpu->ps &= ~(N << 8*thread)); + (cpu->c[thread]) ? (cpu->ps |= (C << 8*thread)) : (cpu->ps &= ~(C << 8*thread)); + break; case ENT: ent(cpu, immaddr(cpu, thread, 1)); break; /* ENd Thread. */ case RTI: /* ReTurn from Interupt routine. */ cpu->ps = ((uint64_t)pull(cpu) << 8*thread); @@ -327,7 +879,12 @@ void *run(void *args) { (cpu->n[thread]) ? (cpu->ps |= (N << 8*thread)) : (cpu->ps &= ~(N << 8*thread)); break; case 0xD0: /* JMP Zero Matrix. */ - address = zeromtx(cpu, thread); + address = (uint32_t)addr[cpu->pc[thread]] + |(uint32_t)addr[cpu->pc[thread]+1] << 8 + |(uint32_t)addr[cpu->pc[thread]+2] << 16 + |(uint32_t)addr[cpu->pc[thread]+3] << 24; + cpu->pc[thread]+=4; + iclk++; cpu->pc[thread] = address; break; @@ -374,11 +931,30 @@ void *run(void *args) { push(cpu, (uint64_t)cpu->pc[thread] & 0xFF); cpu->pc[thread] = address; break; - case 0xE1: inc_addr(cpu, absaddr(cpu, thread), thread); break; /* INC Absolute. */ - case 0xE2: cmp_addr(cpu, cpu->y[thread], absaddr(cpu, thread), thread, regsize); break; /* CPY Absolute. */ - case 0xE3: inc_addr(cpu, zeromtx(cpu, thread), thread); break; /* INC Zero Matrix. */ - case 0xE4: cmp_addr(cpu, cpu->x[thread], absaddr(cpu, thread), thread, regsize); break; /* CPX Absolute. */ - case 0xE5: cmp_addr(cpu, cpu->a[thread], absaddr(cpu, thread), thread, regsize); break; /* CMP Absolute. */ + case 0xE1: /* INC Absolute. */ + case 0xE3: /* INC Zero Matrix. */ + if (opcode == 0xE1) { + address = (uint64_t)addr[cpu->pc[thread]] + | (uint64_t)addr[cpu->pc[thread]+1] << 8 + | (uint64_t)addr[cpu->pc[thread]+2] << 16 + | (uint64_t)addr[cpu->pc[thread]+3] << 24 + | (uint64_t)addr[cpu->pc[thread]+4] << 32 + | (uint64_t)addr[cpu->pc[thread]+5] << 40 + | (uint64_t)addr[cpu->pc[thread]+6] << 48 + | (uint64_t)addr[cpu->pc[thread]+7] << 56; + cpu->pc[thread]+=8; + iclk++; + } + if (opcode == 0xE3) { + address = addr[cpu->pc[thread]] + | addr[cpu->pc[thread]+1] << 8 + | addr[cpu->pc[thread]+2] << 16 + | addr[cpu->pc[thread]+3] << 24; + cpu->pc[thread]+=4; + iclk++; + } + addr[address]++; + break; case NOP: break; /* No OPeration. */ case RTL: /* ReTurn from subroutine Long. */ cpu->pc[thread] = (uint64_t)pull(cpu); @@ -390,11 +966,30 @@ void *run(void *args) { cpu->pc[thread] += ((uint64_t)pull(cpu) << 48); cpu->pc[thread] += ((uint64_t)pull(cpu) << 56) + 1; break; - case 0xF1: dec_addr(cpu, absaddr(cpu, thread), thread); break; /* DEC Absolute. */ - case 0xF2: cmp_addr(cpu, cpu->y[thread], zeromtx(cpu, thread), thread, regsize); break; /* CPY Zero Matrix. */ - case 0xF3: dec_addr(cpu, zeromtx(cpu, thread), thread); break; /* DEC Zero Matrix. */ - case 0xF4: cmp_addr(cpu, cpu->x[thread], zeromtx(cpu, thread), thread, regsize); break; /* CPX Zero Matrix. */ - case 0xF5: cmp_addr(cpu, cpu->a[thread], zeromtx(cpu, thread), thread, regsize); break; /* CMP Zero Matrix. */ + case 0xF1: /* DEC Absolute. */ + case 0xF3: /* DEC Zero Matrix. */ + if (opcode == 0xE1) { + address = (uint64_t)addr[cpu->pc[thread]] + | (uint64_t)addr[cpu->pc[thread]+1] << 8 + | (uint64_t)addr[cpu->pc[thread]+2] << 16 + | (uint64_t)addr[cpu->pc[thread]+3] << 24 + | (uint64_t)addr[cpu->pc[thread]+4] << 32 + | (uint64_t)addr[cpu->pc[thread]+5] << 40 + | (uint64_t)addr[cpu->pc[thread]+6] << 48 + | (uint64_t)addr[cpu->pc[thread]+7] << 56; + cpu->pc[thread]+=8; + iclk++; + } + if (opcode == 0xE3) { + address = addr[cpu->pc[thread]] + | addr[cpu->pc[thread]+1] << 8 + | addr[cpu->pc[thread]+2] << 16 + | addr[cpu->pc[thread]+3] << 24; + cpu->pc[thread]+=4; + iclk++; + } + addr[address]--; + break; case BRK: /* BReaK. */ push(cpu, (uint64_t)cpu->pc[thread]-1 >> 56); push(cpu, (uint64_t)cpu->pc[thread]-1 >> 48); @@ -423,23 +1018,36 @@ void *run(void *args) { } break; } - inst[thread]++; - for (uint8_t i = 0; i < THREADS; i++) { - if (!i) - inss = inst[i]; - else - inss += inst[i]; - } - if (inss >= 100000000/THREADS) { + ins++; + /*if (ins % 50000000 == 0) { + int r = pthread_barrier_wait(&bar); + if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD) { + printf("oof, throds not sinking.\n"); + exit(-1); + } + }*/ + #if !bench + printf("\033[%uHInstructions executed: %llu, Clock cycles: %llu\n", (6*thread)+1, ins, iclk); + fflush(stdout); + #endif + if (ins >= BENCH_INST) { end = 1; + pthread_mutex_lock(&mutex); + threads_done++; + inst[thread] = ins; + clk[thread] = iclk; + pthread_cond_signal(&cond); + pthread_mutex_unlock(&mutex); +#if bench + gettimeofday(&en[thread], 0); +#endif } } /*return 1;*/ } int main(int argc, char **argv) { - cpu = malloc(sizeof(struct sux)); - cpu->sp = 0xFFFF; + struct suxthr thr[THREADS]; ibcount = 0; addr = malloc(0x04000000); inss = 0; @@ -447,55 +1055,86 @@ int main(int argc, char **argv) { if (asmmon() == 2) return 0; - for (int i = 0; i < THREADS; i++) { - cpu->a[i] = 0; - cpu->x[i] = 0; - cpu->y[i] = 0; - cpu->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].sx.sp = 0xFFFF; + if (i) { + thr[i].sx.a[i] = 0; + thr[i].sx.x[i] = 0; + thr[i].sx.y[i] = 0; + thr[i].sx.pc[i] = (uint64_t)addr[0xFF50] + | (uint64_t)addr[0xFF51] << 8 + | (uint64_t)addr[0xFF52] << 16 + | (uint64_t)addr[0xFF53] << 24 + | (uint64_t)addr[0xFF54] << 32 + | (uint64_t)addr[0xFF55] << 40 + | (uint64_t)addr[0xFF56] << 48 + | (uint64_t)addr[0xFF57] << 56; + } else { + thr[i].sx.a[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; } for (int i = 0; i < THREADS; i++) { lines[i] = (6*i)+2; inst[i] = 0; } pthread_t therads[THREADS]; + pthread_barrier_init(&bar, NULL, THREADS); int result; - uint8_t throds[THREADS]; - printf("\033[2J"); -#if bench - str=clock(); -#endif + puts("\033[2J\033[H"); for (int i = 0; i < THREADS; i++) { - throds[i] = i; - result = pthread_create(&therads[i], NULL, run, &throds[i]); + result = pthread_create(&therads[i], NULL, run, &thr[i]); assert(!result); } - for (int i = 0; i < THREADS; i++) { - result = pthread_join(therads[i], NULL); - assert(!result); + pthread_mutex_lock(&mutex); + while (threads_done < THREADS) { + pthread_cond_wait(&cond, &mutex); } -#if !bench - printf("\033[HInstructions executed: %llu, Clock cycles: %llu\n", inss, clk); - fflush(stdout); -#endif + pthread_mutex_unlock(&mutex); + pthread_barrier_destroy(&bar); #if bench - en=clock(); - double tm = (en-str)/THREADS; - double clkspd = ((tm/CLOCKS_PER_SEC)*1000000)/clk; - double mhz = 1000000.0/clkspd/1000000; - double ips = (double)inss/(double)tm; - ipc=(double)inss/(double)clk; - printf("\033[2J"); - printf("Instructions executed: %llu, Instructions per Second in MIPS: %f, Clock cycles: %llu, Clock Speed in MHz: %f, tm: %f\n", inss, ips, clk, mhz, tm/CLOCKS_PER_SEC); + 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; + printf("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); + } + clkspd = (ttm/1000000)*1000000/tclk; + mhz = 1000000.0/clkspd/1000000; + /*printf("\033[2J");*/ + printf("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); + } #endif - free(cpu); free(addr); return 0; } |