#include "opcode.h" #include #include #include #define bench 0 #if bench #include #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]; 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; 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; 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; uint16_t tv = 0xFF50; /* Thread Vector. */ #if bench gettimeofday(&str[thread], 0); #endif while (!end) { prefix = addr[cpu->pc[thread]]; if ((prefix & 0x07) == 0x07) cpu->pc[thread]++; else prefix = 0; opcode = addr[cpu->pc[thread]]; #if !bench 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, prefix, opcode, thread, opname[opcode]); fflush(stdout); lines[thread]++; if (lines[thread] > 6*(thread+1)) lines[thread] = (6*thread)+2; #endif uint8_t rs = (prefix & 0x30) >> 4; uint8_t regsize = (1 << rs); uint8_t tmp; address = cpu->pc[thread]; cpu->pc[thread]++; iclk++; switch(opcode) { case CPS: /* Clear Processor Status. */ for (uint8_t i = 0; i < 8; i++) { cpu->c[i] = 0; cpu->z[i] = 0; cpu->i[i] = 0; cpu->s[i] = 0; cpu->v[i] = 0; cpu->n[i] = 0; } cpu->ps &= 0; break; 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) tmp = 7; for (int8_t i = tmp*8; i >= 0; i-=8) { if (i) addr[STK_STADDR+cpu->sp] = (uint64_t)cpu->ps >> i; else addr[STK_STADDR+cpu->sp] = (uint64_t)cpu->ps & 0xFF; cpu->sp--; addr[0xFF90] = cpu->sp & 0xFF; addr[0xFF91] = cpu->sp >> 8; } break; case PHA: /* PusH Accumulator to stack. */ tmp = addr[cpu->pc[thread]++]; if (tmp > 7) tmp = 7; for (int8_t i = tmp*8; i >= 0; i-=8) { if (i) addr[STK_STADDR+cpu->sp] = (uint64_t)cpu->a[thread] >> i; else addr[STK_STADDR+cpu->sp] = (uint64_t)cpu->a[thread] & 0xFF; cpu->sp--; addr[0xFF90] = cpu->sp & 0xFF; addr[0xFF91] = cpu->sp >> 8; } break; case PHY: /* PusH Y register to stack. */ tmp = addr[cpu->pc[thread]++]; if (tmp > 7) tmp = 7; for (int8_t i = tmp*8; i >= 0; i-=8) { if (i) addr[STK_STADDR+cpu->sp] = (uint64_t)cpu->y[thread] >> i; else addr[STK_STADDR+cpu->sp] = (uint64_t)cpu->y[thread] & 0xFF; cpu->sp--; addr[0xFF90] = cpu->sp & 0xFF; addr[0xFF91] = cpu->sp >> 8; } break; case PHX: /* PusH X register to stack. */ tmp = addr[cpu->pc[thread]++]; if (tmp > 7) tmp = 7; for (int8_t i = tmp*8; i >= 0; i-=8) { if (i) addr[STK_STADDR+cpu->sp] = (uint64_t)cpu->x[thread] >> i; else addr[STK_STADDR+cpu->sp] = (uint64_t)cpu->x[thread] & 0xFF; cpu->sp--; addr[0xFF90] = cpu->sp & 0xFF; addr[0xFF91] = cpu->sp >> 8; } break; case JMP: /* JMP Absolute. */ 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 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) tmp = 7; for (uint8_t i = 0; i < (tmp+1)*8; i+=8) { cpu->sp++; addr[0xFF90] = cpu->sp & 0xFF; addr[0xFF91] = cpu->sp >> 8; if (i) cpu->ps += (uint64_t)addr[STK_STADDR+cpu->sp] << i; else cpu->ps = (uint64_t)addr[STK_STADDR+cpu->sp] & 0xFF; } break; case PLA: /* PuLl Accumulator from stack. */ tmp = addr[cpu->pc[thread]++]; if (tmp > 7) tmp = 7; for (uint8_t i = 0; i < (tmp+1)*8; i+=8) { cpu->sp++; addr[0xFF90] = cpu->sp & 0xFF; addr[0xFF91] = cpu->sp >> 8; if (i) cpu->a[thread] += (uint64_t)addr[STK_STADDR+cpu->sp] << i; else cpu->a[thread] = (uint64_t)addr[STK_STADDR+cpu->sp] & 0xFF; } break; case PLY: /* PuLl Y register from stack. */ tmp = addr[cpu->pc[thread]++]; if (tmp > 7) tmp = 7; for (uint8_t i = 0; i < (tmp+1)*8; i+=8) { cpu->sp++; addr[0xFF90] = cpu->sp & 0xFF; addr[0xFF91] = cpu->sp >> 8; if (i) cpu->y[thread] += (uint64_t)addr[STK_STADDR+cpu->sp] << i; else cpu->y[thread] = (uint64_t)addr[STK_STADDR+cpu->sp] & 0xFF; } break; case PLX: /* PuLl X register from stack. */ tmp = addr[cpu->pc[thread]++]; if (tmp > 7) tmp = 7; for (uint8_t i = 0; i < (tmp+1)*8; i+=8) { cpu->sp++; addr[0xFF90] = cpu->sp & 0xFF; addr[0xFF91] = cpu->sp >> 8; if (i) cpu->x[thread] += (uint64_t)addr[STK_STADDR+cpu->sp] << i; else cpu->x[thread] = (uint64_t)addr[STK_STADDR+cpu->sp] & 0xFF; } break; case JSR: /* Jump to SubRoutine. */ 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; cpu->pc[thread]+=4; for (int8_t i = 24; i >= 0; i-=8) { if (i) addr[STK_STADDR+cpu->sp] = (uint64_t)cpu->pc[thread] >> i; else addr[STK_STADDR+cpu->sp] = (uint64_t)cpu->pc[thread] & 0xFF; cpu->sp--; addr[0xFF90] = cpu->sp & 0xFF; addr[0xFF91] = cpu->sp >> 8; } cpu->pc[thread] = address; break; case AND: /* AND Immediate. */ case 0x29: /* AND Absolute. */ case 0x2B: /* AND Zero Matrix. */ case ANY: /* ANY Immediate. */ case 0x52: /* ANY Absolute. */ case 0x82: /* ANY Zero Matrix. */ case ANX: /* ANX Immediate. */ case 0x54: /* ANX Absolute. */ case 0x84: /* ANX Zero Matrix. */ if (opcode == AND || opcode == ANY || opcode == ANX) { address = cpu->pc[thread]; cpu->pc[thread]+=regsize; } if (opcode == 0x29 || opcode == 0x52 || opcode == 0x54) { 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 == 0x2B || opcode == 0x82 || opcode == 0x84) { 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 == AND || opcode == 0x29 || opcode == 0x2B) cpu->a[thread] &= value; if (opcode == ANY || opcode == 0x52 || opcode == 0x82) cpu->y[thread] &= value; if (opcode == ANX || opcode == 0x54 || opcode == 0x84) 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 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 STT: /* STart Thread. */ address = cpu->pc[thread]; cpu->pc[thread]++; value = addr[address]; cpu->crt |= value; for (uint8_t i = 0; i < 7; i++) { if ((value >> i) & 1) { address = (uint64_t)addr[tv+(8*i)] | (uint64_t)addr[tv+1+(8*i)] << 8 | (uint64_t)addr[tv+2+(8*i)] << 16 | (uint64_t)addr[tv+3+(8*i)] << 24 | (uint64_t)addr[tv+4+(8*i)] << 32 | (uint64_t)addr[tv+5+(8*i)] << 40 | (uint64_t)addr[tv+6+(8*i)] << 48 | (uint64_t)addr[tv+7+(8*i)] << 56; cpu->pc[i+1] = address; } } break; 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: /* ORA Immediate. */ case 0x39: /* ORA Absolute. */ case 0x3B: /* ORA Zero Matrix. */ case ORY: /* ORY Immediate. */ case 0x62: /* ORY Absolute. */ case 0x92: /* ORY Zero Matrix. */ case ORX: /* ORX Immediate. */ case 0x64: /* ORX Absolute. */ case 0x94: /* ORX Zero Matrix. */ if (opcode == ORA || opcode == ORY || opcode == ORX) { address = cpu->pc[thread]; cpu->pc[thread]+=regsize; } if (opcode == 0x39 || opcode == 0x62 || opcode == 0x64) { 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 == 0x3B || opcode == 0x92 || opcode == 0x94) { 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 == ORA || opcode == 0x39 || opcode == 0x3B) cpu->a[thread] |= value; if (opcode == ORY || opcode == 0x62 || opcode == 0x92) cpu->y[thread] |= value; if (opcode == ORX || opcode == 0x64 || opcode == 0x94) 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 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; (cpu->ps |= (I << 8*thread)); break; 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 Immediate. */ case 0x49: /* XOR Absolute. */ case 0x4B: /* XOR Zero Matrix. */ case XRY: /* XRY Immediate. */ case 0x72: /* XRY Absolute. */ case 0xA2: /* XRY Zero Matrix. */ case XRX: /* XRX Immediate. */ case 0x74: /* XRX Absolute. */ case 0xA4: /* XRX Zero Matrix. */ if (opcode == XOR || opcode == XRY || opcode == XRX) { address = cpu->pc[thread]; cpu->pc[thread]+=regsize; } if (opcode == 0x49 || opcode == 0x72 || opcode == 0x74) { 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 == 0x4B || opcode == 0xA2 || opcode == 0xA4) { 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 == XOR || opcode == 0x49 || opcode == 0x4B) cpu->a[thread] ^= value; if (opcode == ORY || opcode == 0x72 || opcode == 0xA2) cpu->y[thread] ^= value; if (opcode == ORX || opcode == 0x74 || opcode == 0xA4) 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 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 CLI: /* CLear Interrupt. */ cpu->i[thread] = 0; (cpu->ps &= ~(I << 8*thread)); break; 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 SEC: /* SEt Carry flag.*/ cpu->c[thread] = 1; (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. */ case 0x8B: /* STA Zero Matrix, Indexed with X. */ case 0x8D: /* STY Zero Matrix, Indexed with X. */ case 0x9B: /* STA Zero Matrix, Indexed with Y. */ case 0x9E: /* STX Zero Matrix, Indexed with Y. */ 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 || opcode == 0x8B || opcode == 0x8D || opcode == 0x9B || opcode == 0x9E) { address = addr[cpu->pc[thread]] | addr[cpu->pc[thread]+1] << 8 | addr[cpu->pc[thread]+2] << 16 | addr[cpu->pc[thread]+3] << 24; if (opcode == 0x8B || opcode == 0x8D) address += cpu->x[thread]; if (opcode == 0x9B || opcode == 0x9E) address += cpu->y[thread]; 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 CLC: /* CLear Carry flag. */ cpu->c[thread] = 0; (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. */ case 0x89: /* LDA Zero Matrix, Indexed with X. */ case 0x8A: /* LDY Zero Matrix, Indexed with X. */ case 0x99: /* LDA Zero Matrix, Indexed with Y. */ case 0x9C: /* LDX Zero Matrix, Indexed with Y. */ 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 || opcode == 0x89 || opcode == 0x8A || opcode == 0x99 || opcode == 0x9C) { address = addr[cpu->pc[thread]] | addr[cpu->pc[thread]+1] << 8 | addr[cpu->pc[thread]+2] << 16 | addr[cpu->pc[thread]+3] << 24; if (opcode == 0x89 || opcode == 0x8A) address += cpu->x[thread]; if (opcode == 0x99 || opcode == 0x9C) address += cpu->y[thread]; 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 SSP: /* Set Stack Protection flag. */ cpu->s[thread] = 1; (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 CSP: /* Clear Stack Protection flag. */ cpu->s[thread] = 0; (cpu->ps &= ~(S << 8*thread)); break; 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 Immediate. */ case 0x93: /* MUL Absolute. */ case 0x95: /* MUL Zero Matrix. */ if (opcode == MUL) { address = cpu->pc[thread]; cpu->pc[thread]++; } if (opcode == 0x93) { 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 == 0x95) { 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] = (!((cpu->a[thread]^sum) && (cpu->a[thread]^value)) && (cpu->a[thread] >= ((uint64_t)1 << 32) && value >= ((uint64_t)1 << 32))); (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 SEV: /* SEt oVerflow flag. */ cpu->v[thread] = 1; (cpu->ps |= (V << 8*thread)); break; 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: /* DIV Immediate. */ case 0xA3: /* DIV Absolute. */ case 0xA5: /* DIV Zero Matrix. */ if (opcode == DIV) { address = cpu->pc[thread]; cpu->pc[thread]++; } if (opcode == 0xA3) { 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 == 0xA5) { 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->a[thread] = sum; 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 CLV: /* CLear oVerflow flag. */ cpu->v[thread] = 0; (cpu->ps &= ~(V << 8*thread)); break; case RTS: /* ReTurn from Subroutine. */ for (uint8_t i = 0; i < 32; i+=8) { cpu->sp++; addr[0xFF90] = cpu->sp & 0xFF; addr[0xFF91] = cpu->sp >> 8; if (i < 24) cpu->pc[thread] += addr[STK_STADDR+cpu->sp] << i; else if (i == 24) cpu->pc[thread] += addr[STK_STADDR+cpu->sp] << i +1; else cpu->pc[thread] = addr[STK_STADDR+cpu->sp]; } 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 = cpu->pc[thread]; cpu->pc[thread]++; } 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: /* ENd Thread. */ value = addr[address]; 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 Interupt routine. */ cpu->sp++; addr[0xFF90] = cpu->sp & 0xFF; addr[0xFF91] = cpu->sp >> 8; cpu->ps = addr[STK_STADDR+cpu->sp] << 8*thread; for (uint8_t i = 0; i < 64; i+=8) { cpu->sp++; addr[0xFF90] = cpu->sp & 0xFF; addr[0xFF91] = cpu->sp >> 8; if (i < 56) cpu->pc[thread] += addr[STK_STADDR+cpu->sp] << i; else if (i == 56) cpu->pc[thread] += addr[STK_STADDR+cpu->sp] << i +1; else cpu->pc[thread] = addr[STK_STADDR+cpu->sp]; } break; case INC: /* INC Accumulator. */ case INY: case IAY: case INX: case IAX: if (opcode == INC || opcode == IAY || opcode == IAX) { cpu->a[thread]+=1; cpu->z[thread] = (cpu->a[thread] == 0); cpu->n[thread] = (cpu->a[thread] >> 63); } if (opcode == INY || opcode == IAY) { cpu->y[thread]+=1; cpu->z[thread] = (cpu->y[thread] == 0); cpu->n[thread] = (cpu->y[thread] >> 63); } if (opcode == INX || opcode == IAX) { cpu->x[thread]+=1; cpu->z[thread] = (cpu->x[thread] == 0); cpu->n[thread] = (cpu->x[thread] >> 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 0xD0: /* JMP Zero Matrix. */ 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; case DEC: /* DEC Accumulator. */ case DEY: case DAY: case DEX: case DAX: if (opcode == DEC || opcode == DAY || opcode == DAX) { cpu->a[thread]-=1; cpu->z[thread] = (cpu->a[thread] == 0); cpu->n[thread] = (cpu->a[thread] >> 63); } if (opcode == DEY || opcode == DAY) { cpu->y[thread]-=1; cpu->z[thread] = (cpu->y[thread] == 0); cpu->n[thread] = (cpu->y[thread] >> 63); } if (opcode == DEX || opcode == DAX) { cpu->x[thread]-=1; cpu->z[thread] = (cpu->x[thread] == 0); cpu->n[thread] = (cpu->x[thread] >> 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 JSL: /* Jump to Subroutine Long. */ 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; for (int8_t i = 56; i >= 0; i-=8) { if (i) addr[STK_STADDR+cpu->sp] = (uint64_t)cpu->pc[thread] >> i; else addr[STK_STADDR+cpu->sp] = (uint64_t)cpu->pc[thread] & 0xFF; cpu->sp--; addr[0xFF90] = cpu->sp & 0xFF; addr[0xFF91] = cpu->sp >> 8; } cpu->pc[thread] = address; break; 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: /* No OPeration. */ break; case RTL: /* ReTurn from subroutine Long. */ for (uint8_t i = 0; i < 64; i+=8) { cpu->sp++; addr[0xFF90] = cpu->sp & 0xFF; addr[0xFF91] = cpu->sp >> 8; if (i < 56) cpu->pc[thread] = addr[STK_STADDR+cpu->sp] << i; else if (i == 56) cpu->pc[thread] = addr[STK_STADDR+cpu->sp] << i + 1; else cpu->pc[thread] = addr[STK_STADDR+cpu->sp]; } break; 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. */ for (uint8_t i = 56; i >= 0; i-=8) { if (i) addr[STK_STADDR+cpu->sp] = (uint64_t)cpu->pc[thread]-1 >> i; else addr[STK_STADDR+cpu->sp] = (uint64_t)cpu->pc[thread]-1 & 0xFF; cpu->sp--; addr[0xFF90] = cpu->sp & 0xFF; addr[0xFF91] = cpu->sp >> 8; } addr[STK_STADDR+cpu->sp] = (uint64_t)cpu->ps >> 8*thread; cpu->sp--; addr[0xFF90] = cpu->sp & 0xFF; addr[0xFF91] = cpu->sp >> 8; cpu->i[thread] = 1; setps(cpu, thread); 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; default: if(opcode != BRK) { printf("Cool, you inputed a non existent opcode, which means\n" "that you have now wasted clock cycles.\n" "Good job! *clap*\n"); } break; } ins++; #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 } } } int main(int argc, char **argv) { struct suxthr thr[THREADS]; ibcount = 0; addr = malloc(0x04000000); inss = 0; int v = 0; if (asmmon() == 2) return 0; for (int i = 0; i < THREADS; i++) { 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; puts("\033[2J\033[H"); for (int i = 0; i < THREADS; i++) { result = pthread_create(&therads[i], NULL, run, &thr[i]); assert(!result); } pthread_mutex_lock(&mutex); while (threads_done < THREADS) { pthread_cond_wait(&cond, &mutex); } pthread_mutex_unlock(&mutex); pthread_barrier_destroy(&bar); #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; 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("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(addr); return 0; }