#include "opcode.h"
#include <assert.h>
#include <string.h>
#include <pthread.h>
#define bench 0
#if bench
#include <time.h>
#endif
#define THREADS 1
uint64_t inst[THREADS];
uint64_t inss;
uint8_t lines[THREADS];
struct sux *cpu;
#if bench
double ipc;
time_t str, en;
#endif
void *run(void *args) {
uint8_t thread = *((uint8_t *) args);
uint64_t address;
uint8_t prefix = 0;
uint8_t opcode = 0;
uint8_t end = 0;
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\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]
, cpu->pc[thread], cpu->a[thread], cpu->x[thread], cpu->y[thread]
, cpu->sp, cpu->ps, 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]++;
clk++;
switch(opcode) {
case CPS:
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(cpu, immaddr(cpu, thread, regsize), thread, regsize); break;
case 0x03: adc(cpu, absaddr(cpu, thread), thread, regsize); break;
case 0x05: adc(cpu, zeromtx(cpu, thread), thread, regsize); break;
case PHP:
tmp = addr[cpu->pc[thread]++];
if (tmp > 7)
tmp = 7;
for (int8_t i = 8*tmp; i > 0; i-=8) {
push(cpu, cpu->ps >> i);
}
push(cpu, cpu->ps & 0xFF);
break;
case PHA:
tmp = addr[cpu->pc[thread]++];
if (tmp > 7)
tmp = 7;
for (int8_t i = 8*tmp; i > 0; i-=8) {
push(cpu, cpu->a[thread] >> i);
}
push(cpu, cpu->a[thread] & 0xFF);
break;
case PHY:
tmp = addr[cpu->pc[thread]++];
if (tmp > 7)
tmp = 7;
for (int8_t i = 8*tmp; i > 0; i-=8) {
push(cpu, cpu->y[thread] >> i);
}
push(cpu, cpu->y[thread] & 0xFF);
break;
case PHX:
tmp = addr[cpu->pc[thread]++];
if (tmp > 7)
tmp = 7;
for (int8_t i = 8*tmp; i > 0; i-=8) {
push(cpu, cpu->x[thread] >> i);
}
push(cpu, cpu->x[thread] & 0xFF);
break;
case JMP:
address = absaddr(cpu, thread);
cpu->pc[thread] = address;
break;
case SBC: sbc(cpu, immaddr(cpu, thread, regsize), thread, regsize); break;
case 0x13: sbc(cpu, absaddr(cpu, thread), thread, regsize); break;
case 0x15: sbc(cpu, zeromtx(cpu, thread), thread, regsize); break;
case PLP:
tmp = addr[cpu->pc[thread]++];
if (tmp > 7)
tmp = 7;
for (uint8_t i = 0; i <= 8*tmp; i+=8) {
if (!i)
cpu->ps = (uint64_t)pull(cpu);
else
cpu->ps += (uint64_t)pull(cpu) << i;
}
break;
case PLA:
tmp = addr[cpu->pc[thread]++];
if (tmp > 7)
tmp = 7;
for (uint8_t i = 0; i <= 8*tmp; i+=8) {
if (!i)
cpu->a[thread] = (uint64_t)pull(cpu);
else
cpu->a[thread] += (uint64_t)pull(cpu) << i;
}
break;
case PLY:
tmp = addr[cpu->pc[thread]++];
if (tmp > 7)
tmp = 7;
for (uint8_t i = 0; i <= 8*tmp; i+=8) {
if (!i)
cpu->y[thread] = (uint64_t)pull(cpu);
else
cpu->y[thread] += (uint64_t)pull(cpu) << i;
}
break;
case PLX:
tmp = addr[cpu->pc[thread]++];
if (tmp > 7)
tmp = 7;
for (uint8_t i = 0; i <= 8*tmp; i+=8) {
if (!i)
cpu->x[thread] = (uint64_t)pull(cpu);
else
cpu->x[thread] += (uint64_t)pull(cpu) << i;
}
break;
case JSR:
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;
push(cpu, (uint64_t)cpu->pc[thread] >> 24);
push(cpu, (uint64_t)cpu->pc[thread] >> 16);
push(cpu, (uint64_t)cpu->pc[thread] >> 8);
push(cpu, (uint64_t)cpu->pc[thread] & 0xFF);
cpu->pc[thread] = address;
break;
case AND: and_addr(cpu, &cpu->a[thread], immaddr(cpu, thread, regsize), thread, regsize); break;
case ANY: and_addr(cpu, &cpu->y[thread], immaddr(cpu, thread, regsize), thread, regsize); break;
case AAY: cpu->a[thread] = and(cpu, cpu->y[thread], thread); break;
case ANX: and_addr(cpu, &cpu->x[thread], immaddr(cpu, thread, regsize), thread, regsize); break;
case AAX: cpu->a[thread] = and(cpu, cpu->x[thread], thread); break;
case STT: stt(cpu, immaddr(cpu, thread, 1)); break;
case 0x29: and_addr(cpu, &cpu->a[thread], absaddr(cpu, thread), thread, regsize); break;
case 0x2B: and_addr(cpu, &cpu->a[thread], zeromtx(cpu, thread), thread, regsize); break;
case BPO: bfc(cpu, cpu->n[thread], absaddr(cpu, thread), thread); break;
case ORA: or_addr(cpu, &cpu->a[thread], immaddr(cpu, thread, regsize), thread, regsize); break;
case ORY: or_addr(cpu, &cpu->y[thread], immaddr(cpu, thread, regsize), thread, regsize); break;
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;
case OAX: cpu->a[thread] = or(cpu, cpu->x[thread], thread); break;
case SEI:
cpu->i[thread] = 1;
setps(cpu, thread);
break;
case 0x39: or_addr(cpu, &cpu->a[thread], absaddr(cpu, thread), thread, regsize); break;
case 0x3B: or_addr(cpu, &cpu->a[thread], zeromtx(cpu, thread), thread, regsize); break;
case BNG: bfs(cpu, cpu->n[thread], absaddr(cpu, thread), thread); break;
case XOR: xor_addr(cpu, &cpu->a[thread], immaddr(cpu, thread, regsize), thread, regsize); break;
case XRY: xor_addr(cpu, &cpu->y[thread], immaddr(cpu, thread, regsize), thread, regsize); break;
case XAY: cpu->a[thread] = xor(cpu, cpu->y[thread], thread); break;
case XRX: xor_addr(cpu, &cpu->x[thread], immaddr(cpu, thread, regsize), thread, regsize); break;
case XAX: cpu->a[thread] = xor(cpu, cpu->x[thread], thread); break;
case CLI:
cpu->i[thread] = 0;
setps(cpu, thread);
break;
case 0x49: xor_addr(cpu, &cpu->a[thread], absaddr(cpu, thread), thread, regsize); break;
case 0x4B: xor_addr(cpu, &cpu->a[thread], zeromtx(cpu, thread), thread, regsize); break;
case BCS: bfs(cpu, cpu->c[thread], absaddr(cpu, thread), thread); break;
case LSL: lsl(cpu, immaddr(cpu, thread, 1), thread); break;
case 0x52: and_addr(cpu, &cpu->y[thread], absaddr(cpu, thread), thread, regsize); break;
case 0x53: lsl(cpu, absaddr(cpu, thread), thread); break;
case 0x54: and_addr(cpu, &cpu->x[thread], absaddr(cpu, thread), thread, regsize); break;
case 0x55: lsl(cpu, zeromtx(cpu, thread), thread); break;
case SEC:
cpu->c[thread] = 1;
setps(cpu, thread);
break;
case 0x59: ld(cpu, &cpu->a[thread], absaddr(cpu, thread), thread, regsize); break;
case 0x5A: ld(cpu, &cpu->y[thread], absaddr(cpu, thread), thread, regsize); break;
case STA: st(cpu, &cpu->a[thread], absaddr(cpu, thread), thread, regsize); break;
case 0x5C: ld(cpu, &cpu->x[thread], absaddr(cpu, thread), thread, regsize); break;
case STY: st(cpu, &cpu->y[thread], absaddr(cpu, thread), thread, regsize); break;
case STX: st(cpu, &cpu->x[thread], absaddr(cpu, thread), thread, regsize); break;
case BCC: bfc(cpu, cpu->c[thread], absaddr(cpu, thread), thread); break;
case LSR: lsr(cpu, immaddr(cpu, thread, 1), thread); break;
case 0x62: or_addr(cpu, &cpu->y[thread], absaddr(cpu, thread), thread, regsize); break;
case 0x63: lsr(cpu, absaddr(cpu, thread), thread); break;
case 0x64: or_addr(cpu, &cpu->x[thread], absaddr(cpu, thread), thread, regsize); break;
case 0x65: lsr(cpu, zeromtx(cpu, thread), thread); break;
case CLC:
cpu->c[thread] = 0;
setps(cpu, thread);
break;
case LDA: ld(cpu, &cpu->a[thread], immaddr(cpu, thread, regsize), thread, regsize); break;
case LDY: ld(cpu, &cpu->y[thread], immaddr(cpu, thread, regsize), thread, regsize); break;
case LDX: ld(cpu, &cpu->x[thread], immaddr(cpu, thread, regsize), thread, regsize); break;
case BEQ: bfs(cpu, cpu->z[thread], absaddr(cpu, thread), thread); break;
case ROL: rol(cpu, immaddr(cpu, thread, 1), thread); break;
case 0x72: xor_addr(cpu, &cpu->y[thread], absaddr(cpu, thread), thread, regsize); break;
case 0x73: rol(cpu, absaddr(cpu, thread), thread); break;
case 0x74: xor_addr(cpu, &cpu->x[thread], absaddr(cpu, thread), thread, regsize); break;
case 0x75: rol(cpu, zeromtx(cpu, thread), thread); break;
case SSP:
cpu->s[thread] = 1;
setps(cpu, thread);
break;
case 0x79: ld(cpu, &cpu->a[thread], zeromtx(cpu, thread), thread, regsize); break;
case 0x7A: ld(cpu, &cpu->y[thread], zeromtx(cpu, thread), thread, regsize); break;
case 0x7B: st(cpu, &cpu->a[thread], zeromtx(cpu, thread), thread, regsize); break;
case 0x7C: ld(cpu, &cpu->x[thread], zeromtx(cpu, thread), thread, regsize); break;
case 0x7D: st(cpu, &cpu->y[thread], zeromtx(cpu, thread), thread, regsize); break;
case 0x7E: st(cpu, &cpu->x[thread], zeromtx(cpu, thread), thread, regsize); break;
case BNE: bfc(cpu, cpu->z[thread], absaddr(cpu, thread), thread); break;
case ROR: ror(cpu, immaddr(cpu, thread, 1), thread); break;
case 0x82: and_addr(cpu, &cpu->y[thread], zeromtx(cpu, thread), thread, regsize); break;
case 0x83: ror(cpu, absaddr(cpu, thread), thread); break;
case 0x84: and_addr(cpu, &cpu->x[thread], zeromtx(cpu, thread), thread, regsize); break;
case 0x85: ror(cpu, zeromtx(cpu, thread), thread); break;
case CSP:
cpu->s[thread] = 0;
setps(cpu, thread);
break;
case 0x89: ld(cpu, &cpu->a[thread], zeromx(cpu, thread), thread, regsize); break;
case 0x8A: ld(cpu, &cpu->y[thread], zeromx(cpu, thread), thread, regsize); break;
case 0x8B: st(cpu, &cpu->a[thread], zeromx(cpu, thread), thread, regsize); break;
case 0x8D: st(cpu, &cpu->y[thread], zeromx(cpu, thread), thread, regsize); break;
case BVS: bfs(cpu, cpu->v[thread], absaddr(cpu, thread), thread); break;
case MUL: mul(cpu, immaddr(cpu, thread, regsize), thread, regsize); break;
case 0x92: or_addr(cpu, &cpu->y[thread], zeromtx(cpu, thread), thread, regsize); break;
case 0x93: mul(cpu, absaddr(cpu, thread), thread, regsize); break;
case 0x94: or_addr(cpu, &cpu->x[thread], zeromtx(cpu, thread), thread, regsize); break;
case 0x95: mul(cpu, zeromtx(cpu, thread), thread, regsize); break;
case SEV:
cpu->v[thread] = 1;
setps(cpu, thread);
break;
case 0x99: ld(cpu, &cpu->a[thread], zeromy(cpu, thread), thread, regsize); break;
case 0x9B: ld(cpu, &cpu->x[thread], zeromy(cpu, thread), thread, regsize); break;
case 0x9C: st(cpu, &cpu->a[thread], zeromy(cpu, thread), thread, regsize); break;
case 0x9E: st(cpu, &cpu->x[thread], zeromy(cpu, thread), thread, regsize); break;
case BVC: bfc(cpu, cpu->z[thread], absaddr(cpu, thread), thread); break;
case DIV: divd(cpu, immaddr(cpu, thread, regsize), thread, regsize); break;
case 0xA2: xor_addr(cpu, &cpu->y[thread], zeromtx(cpu, thread), thread, regsize); break;
case 0xA3: divd(cpu, absaddr(cpu, thread), thread, regsize); break;
case 0xA4: xor_addr(cpu, &cpu->x[thread], zeromtx(cpu, thread), thread, regsize); break;
case 0xA5: divd(cpu, zeromtx(cpu, thread), thread, regsize); break;
case CLV:
cpu->v[thread] = 0;
setps(cpu, thread);
break;
case RTS:
cpu->pc[thread] = (uint64_t)pull(cpu);
cpu->pc[thread] += ((uint64_t)pull(cpu) << 8);
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;
case CPY: cmp_addr(cpu, cpu->y[thread], immaddr(cpu, thread, regsize), thread, regsize); break;
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;
case CAX: cmp(cpu, cpu->a[thread], cpu->x[thread], thread); break;
case ENT: ent(cpu, immaddr(cpu, thread, 1)); break;
case RTI:
cpu->ps = ((uint64_t)pull(cpu) << 8*thread);
cpu->pc[thread] = (uint64_t)pull(cpu);
cpu->pc[thread] += ((uint64_t)pull(cpu) << 8);
cpu->pc[thread] += ((uint64_t)pull(cpu) << 16);
cpu->pc[thread] += ((uint64_t)pull(cpu) << 24);
cpu->pc[thread] += ((uint64_t)pull(cpu) << 32);
cpu->pc[thread] += ((uint64_t)pull(cpu) << 40);
cpu->pc[thread] += ((uint64_t)pull(cpu) << 48);
cpu->pc[thread] += ((uint64_t)pull(cpu) << 56);
break;
case INC:
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:
address = zeromtx(cpu, thread);
cpu->pc[thread] = address;
break;
case DEC:
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:
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;
push(cpu, (uint64_t)cpu->pc[thread] >> 56);
push(cpu, (uint64_t)cpu->pc[thread] >> 48);
push(cpu, (uint64_t)cpu->pc[thread] >> 40);
push(cpu, (uint64_t)cpu->pc[thread] >> 32);
push(cpu, (uint64_t)cpu->pc[thread] >> 24);
push(cpu, (uint64_t)cpu->pc[thread] >> 16);
push(cpu, (uint64_t)cpu->pc[thread] >> 8);
push(cpu, (uint64_t)cpu->pc[thread] & 0xFF);
cpu->pc[thread] = address;
break;
case 0xE1: inc_addr(cpu, absaddr(cpu, thread), thread); break;
case 0xE2: cmp_addr(cpu, cpu->y[thread], absaddr(cpu, thread), thread, regsize); break;
case 0xE3: inc_addr(cpu, zeromtx(cpu, thread), thread); break;
case 0xE4: cmp_addr(cpu, cpu->x[thread], absaddr(cpu, thread), thread, regsize); break;
case 0xE5: cmp_addr(cpu, cpu->a[thread], absaddr(cpu, thread), thread, regsize); break;
case NOP: break;
case RTL:
cpu->pc[thread] = (uint64_t)pull(cpu);
cpu->pc[thread] += ((uint64_t)pull(cpu) << 8);
cpu->pc[thread] += ((uint64_t)pull(cpu) << 16);
cpu->pc[thread] += ((uint64_t)pull(cpu) << 24);
cpu->pc[thread] += ((uint64_t)pull(cpu) << 32);
cpu->pc[thread] += ((uint64_t)pull(cpu) << 40);
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;
case 0xF2: cmp_addr(cpu, cpu->y[thread], zeromtx(cpu, thread), thread, regsize); break;
case 0xF3: dec_addr(cpu, zeromtx(cpu, thread), thread); break;
case 0xF4: cmp_addr(cpu, cpu->x[thread], zeromtx(cpu, thread), thread, regsize); break;
case 0xF5: cmp_addr(cpu, cpu->a[thread], zeromtx(cpu, thread), thread, regsize); break;
case BRK:
push(cpu, (uint64_t)cpu->pc[thread]-1 >> 56);
push(cpu, (uint64_t)cpu->pc[thread]-1 >> 48);
push(cpu, (uint64_t)cpu->pc[thread]-1 >> 40);
push(cpu, (uint64_t)cpu->pc[thread]-1 >> 32);
push(cpu, (uint64_t)cpu->pc[thread]-1 >> 24);
push(cpu, (uint64_t)cpu->pc[thread]-1 >> 16);
push(cpu, (uint64_t)cpu->pc[thread]-1 >> 8);
push(cpu, (uint64_t)cpu->pc[thread]-1 & 0xFF);
push(cpu, (uint64_t)cpu->ps >> 8*thread);
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;
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;
}
inst[thread]++;
for (uint8_t i = 0; i < THREADS; i++) {
if (!i)
inss = inst[i];
else
inss += inst[i];
}
if (inss >= 100000000/THREADS) {
end = 1;
}
}
}
int main(int argc, char **argv) {
cpu = malloc(sizeof(struct sux));
cpu->sp = 0xFFFF;
ibcount = 0;
addr = malloc(0x04000000);
inss = 0;
int v = 0;
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;
}
for (int i = 0; i < THREADS; i++) {
lines[i] = (6*i)+2;
inst[i] = 0;
}
pthread_t therads[THREADS];
int result;
uint8_t throds[THREADS];
printf("\033[2J");
#if bench
str=clock();
#endif
for (int i = 0; i < THREADS; i++) {
throds[i] = i;
result = pthread_create(&therads[i], NULL, run, &throds[i]);
assert(!result);
}
for (int i = 0; i < THREADS; i++) {
result = pthread_join(therads[i], NULL);
assert(!result);
}
#if !bench
printf("\033[HInstructions executed: %llu, Clock cycles: %llu\n", inss, clk);
fflush(stdout);
#endif
#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);
#endif
free(cpu);
free(addr);
return 0;
}