#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <fcntl.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include "sym.h"
#include "decode.h"
#include "core.h"
#include "Scanalyzer.h"
#include "misc.h"
corebk *corehd = 0;
corebk *quikcore = 0;
int ctrace = 0;
uint32_t coremalloc = 0;
uint32_t corefree = 0;
corebk *getcore(void) {
corebk *xcore;
int i;
if((xcore = corehd)) corehd = xcore->core;
else {
xcore = malloc(sizeof(corebk));
if(!xcore) {
printf("Can't allocate core block\n");
exit(1);
}
coremalloc++;
}
bzero((void *)xcore, sizeof(corebk));
for(i = 0; i < 128; i++) xcore->trakBytes[i] = gTundef;
if(ctrace) printf("-----> getcore %08X\n", xcore);
return xcore;
}
void tosscore(regfile *rg) {
corebk *xcore;
int i;
while (rg->core) {
xcore = rg->core;
if(ctrace) printf("-----> tosscore %08X.%08X in %08X, level %d\n", (uint32_t)(rg->core->addr >> 32), (uint32_t)rg->core->addr, rg->core, rg->level);
if(quikcore == xcore) quikcore = 0;
rg->core = xcore->core;
for(i = 0; i < sizeof(corebk); i++) ((char *)xcore)[i] = 0x55;
xcore->core = corehd;
corehd = xcore;
}
}
void freecore(void) {
corebk *xcore;
int i;
while (corehd) {
if(ctrace) {
printf("-----> freecore %08X.%08X in %08X\n", (uint32_t)(corehd->addr >> 32), (uint32_t)corehd->addr, corehd);
fsync(stdout);
}
xcore = corehd;
corehd = corehd->core;
for(i = 0; i < sizeof(corebk); i++) {
if((i >= 8) && (i < 12)) continue;
if(((char *)xcore)[i] != 0x55) {
diedie("free core overlay found in freecore");
break;
}
}
free(xcore);
corefree++;
}
corehd = 0;
quikcore = 0;
}
void readcore(regfile *rg, uint64_t addr, uint32_t size, uint64_t addrmask, uint32_t flags, uint64_t *fetch, uint8_t *trak) {
corebk *core;
uint8_t trakFetch, trakAny;
int i, snko, srco, bleft, blen, xtrk;
union {
uint64_t dword;
uint8_t byte[8];
} mem;
addr &= addrmask;
if(ctrace) printf("******** reading %08X.%08X, current level = %d\n", (uint32_t)(addr >> 32), (uint32_t)addr, rg->level);
mem.dword = 0;
xtrk = 0;
snko = 8 - size;
trakFetch = gTundef;
while(size) {
addr &= addrmask;
blen = size;
bleft = 128 - ((int)addr & 127);
if(bleft < blen) {
blen = bleft;
if(ctrace) printf("******** Read spills %d bytes into next 128 byte line\n", size - blen);
}
core = findcore(rg, addr & -128ULL);
if(core) {
srco = addr & 127ULL;
if(!xtrk) trakFetch = 0xFF;
xtrk = 1;
trakAny = 0;
for(i = 0; i < blen; i++) {
mem.byte[snko + i] = core->bytes[srco + i];
trakFetch &= core->trakBytes[srco + i];
trakAny |= core->trakBytes[srco + i];
}
if(trakAny & gTundef) trakFetch = (trakFetch & gTset) | gTundef;
}
else {
for(i = 0; i < blen; i++) mem.byte[snko + i] = 0xAA;
trakFetch = (trakFetch & gTset) | gTundef;
xtrk = 1;
}
snko += blen;
addr += blen;
size -= blen;
}
*fetch = mem.dword;
*trak = trakFetch;
return;
}
void writecore(regfile *rg, uint64_t addr, uint32_t size, uint64_t addrmask, uint32_t flags, uint8_t *src, uint8_t trak) {
corebk *core;
int i, snko, srco, bleft, blen;
addr &= addrmask;
if(ctrace) printf("******** writing %08X.%08X (size = %d, trak = %02X), current level = %d\n", (uint32_t)(addr >> 32), (uint32_t)addr, size, trak, rg->level);
srco = 0;
while(size) {
addr &= addrmask;
blen = size;
bleft = 128 - ((int)addr & 127);
if(bleft < blen) {
blen = bleft;
if(ctrace) printf("******** Write spills %d bytes into next 128 byte line\n", size - blen);
}
core = promotecore(rg, addr & -128ULL);
if(core) {
snko = addr & 127ULL;
for(i = 0; i < blen; i++) {
core->bytes[snko + i] = src[srco + i];
core->trakBytes[snko + i] = trak;
}
}
srco += blen;
addr += blen;
size -= blen;
}
}
corebk *promotecore(regfile *rg, uint64_t addr) {
corebk *core, *newcore, *lastcore, *curcore;
core = findcore(rg, addr);
if(!core) return 0;
if(core->rg->level == rg->level) return core;
if(ctrace) printf("******** pulling %08X.%08X from level %d to level %d\n", (uint32_t)(addr >> 32), (uint32_t)addr, core->rg->level, rg->level);
newcore = getcore();
bcopy((void *)core, (void *)newcore, sizeof(corebk));
newcore->rg = rg;
curcore = rg->core;
lastcore = 0;
while(curcore) {
if(curcore->addr > addr) break;
lastcore = curcore;
curcore = curcore->core;
}
if(lastcore) {
newcore->core = lastcore->core;
lastcore->core = newcore;
}
else {
newcore->core = rg->core;
rg->core = newcore;
}
quikcore = newcore;
return newcore;
}
corebk *findcore(regfile *rg, uint64_t addr) {
corebk *lastcore;
regfile *rgc;
uint32_t ret;
int i;
lastcore = 0;
addr = addr & -128LL;
if(ctrace) printf("******** finding %08X.%08X\n", (uint32_t)(addr >> 32), (uint32_t)addr);
if(quikcore && (quikcore->rg->level == rg->level) && (quikcore->addr == addr)) {
if(ctrace) printf("******** found %08X.%08X in quikcore, corebk = %08X\n", (uint32_t)(addr >> 32), (uint32_t)addr, quikcore);
return quikcore;
}
rgc = rg;
while(rgc) {
quikcore = rgc->core;
lastcore = 0;
while(quikcore) {
if(quikcore->addr == addr) {
if(ctrace) printf("******** found %08X.%08X in level %d, corebk = %08X\n", (uint32_t)(addr >> 32), (uint32_t)addr, rgc->level, quikcore);
return quikcore;
}
if(quikcore->addr > addr) break;
lastcore = quikcore;
quikcore = quikcore->core;
}
if(!rgc->rgBack) break;
rgc = rgc->rgBack;
}
if(ctrace) printf("******** notfnd %08X.%08X\n", (uint32_t)(addr >> 32), (uint32_t)addr);
quikcore = getcore();
quikcore->addr = addr;
quikcore->rg = rgc;
if(lastcore) {
quikcore->core = lastcore->core;
lastcore->core = quikcore;
}
else {
quikcore->core = rgc->core;
rgc->core = quikcore;
}
ret = symfetch(addr, 128, 128, (char *)&quikcore->bytes[0]);
if(ret) {
if(ctrace) printf("******** loading %08X.%08X into level %d, ret = %d\n", (uint32_t)(quikcore->addr >> 32), (uint32_t)quikcore->addr, rgc->level, ret);
if(ctrace) pprint((char *)&quikcore->bytes[0], quikcore->addr, 128, 17);
for(i = 0; i < 128; i++) quikcore->trakBytes[i] = gTset;
return quikcore;
}
else {
if(ctrace) printf("******** filling %08X.%08X in level %d\n", (uint32_t)(quikcore->addr >> 32), (uint32_t)quikcore->addr, rgc->level);
for(i = 0; i < 128; i++) quikcore->trakBytes[i] = gTset;
return quikcore;
}
}