- FIX CIELOS
- FIX HUGE STACKS

BYE
This commit is contained in:
tildearrow 2025-04-11 20:21:46 -05:00
parent ca67378173
commit 2ea7bf65ea
4 changed files with 285 additions and 277 deletions

View file

@ -24,7 +24,7 @@
#include "../ta-log.h" #include "../ta-log.h"
bool DivCSChannelState::doCall(unsigned int addr) { bool DivCSChannelState::doCall(unsigned int addr) {
if (callStackPos>=16) { if (callStackPos>=DIV_MAX_CSSTACK) {
readPos=0; readPos=0;
return false; return false;
} }

View file

@ -24,6 +24,7 @@
#include "safeReader.h" #include "safeReader.h"
#define DIV_MAX_CSTRACE 64 #define DIV_MAX_CSTRACE 64
#define DIV_MAX_CSSTACK 128
class DivEngine; class DivEngine;
@ -39,7 +40,7 @@ struct DivCSChannelState {
int portaTarget, portaSpeed; int portaTarget, portaSpeed;
unsigned char arp, arpStage, arpTicks, loopCount; unsigned char arp, arpStage, arpTicks, loopCount;
unsigned int callStack[16]; unsigned int callStack[DIV_MAX_CSSTACK];
unsigned char callStackPos; unsigned char callStackPos;
unsigned int trace[DIV_MAX_CSTRACE]; unsigned int trace[DIV_MAX_CSTRACE];

View file

@ -662,6 +662,7 @@ SafeWriter* stripNops(SafeWriter* s) {
case 0xf5: // calli case 0xf5: // calli
case 0xfa: { // jmp case 0xfa: { // jmp
unsigned int addr=buf[i+1]|(buf[i+2]<<8)|(buf[i+3]<<16)|(buf[i+4]<<24); unsigned int addr=buf[i+1]|(buf[i+2]<<8)|(buf[i+3]<<16)|(buf[i+4]<<24);
assert(!(addr&7));
try { try {
addr=addrTable[addr]; addr=addrTable[addr];
buf[i+1]=addr&0xff; buf[i+1]=addr&0xff;
@ -780,14 +781,11 @@ struct BlockMatch {
// TODO: // TODO:
// - see if we can optimize even more // - see if we can optimize even more
SafeWriter* findSubBlocks(SafeWriter* stream, std::vector<SafeWriter*>& subBlocks, unsigned char* speedDial) { SafeWriter* findSubBlocks(SafeWriter* stream, std::vector<SafeWriter*>& subBlocks, unsigned char* speedDial, DivCSProgress* progress) {
unsigned char* buf=stream->getFinalBuf(); unsigned char* buf=stream->getFinalBuf();
size_t matchSize=MIN_MATCH_SIZE; size_t matchSize=MIN_MATCH_SIZE;
std::vector<BlockMatch> matches; std::vector<BlockMatch> matches;
// repeat until we run out of matches
while (true) {
matchSize=MIN_MATCH_SIZE;
matches.clear(); matches.clear();
// fast match algorithm // fast match algorithm
@ -842,6 +840,7 @@ SafeWriter* findSubBlocks(SafeWriter* stream, std::vector<SafeWriter*>& subBlock
// set done to false unless: // set done to false unless:
// - this match overlaps with itself // - this match overlaps with itself
// - this block only consists of calls // - this block only consists of calls
// - this block contains a ret or jmp
size_t nonOverlapCount=0; size_t nonOverlapCount=0;
for (BlockMatch& i: matches) { for (BlockMatch& i: matches) {
i.done=false; i.done=false;
@ -851,11 +850,20 @@ SafeWriter* findSubBlocks(SafeWriter* stream, std::vector<SafeWriter*>& subBlock
} else { } else {
bool onlyCalls=true; bool onlyCalls=true;
for (size_t j=i.orig; j<i.orig+i.len; j+=8) { for (size_t j=i.orig; j<i.orig+i.len; j+=8) {
if (buf[j]!=0xf4) { if (buf[j]!=0xf4 && buf[j]!=0xf5) {
onlyCalls=false; onlyCalls=false;
break; break;
} }
} }
if (!onlyCalls) {
// check whether there's call or ret
for (size_t j=i.orig; j<i.orig+i.len; j+=8) {
if (buf[j]==0xf9 || buf[j]==0xfa) {
onlyCalls=true;
break;
}
}
}
if (onlyCalls) { if (onlyCalls) {
i.done=true; i.done=true;
} else { } else {
@ -866,10 +874,14 @@ SafeWriter* findSubBlocks(SafeWriter* stream, std::vector<SafeWriter*>& subBlock
logD("%d good candidates",(int)nonOverlapCount); logD("%d good candidates",(int)nonOverlapCount);
if (progress!=NULL) {
progress->count=nonOverlapCount;
}
// NEW STUFF // NEW STUFF
// find and sort matches by benefit // find and sort matches by benefit
size_t bestBenefitIndex=0; size_t bestBenefitIndex=0;
int bestBenefit=-1000000; int bestBenefit=-1;
size_t lastOrig=SIZE_MAX; size_t lastOrig=SIZE_MAX;
size_t lastLen=SIZE_MAX; size_t lastLen=SIZE_MAX;
size_t lastOrigOff=0; size_t lastOrigOff=0;
@ -885,9 +897,11 @@ SafeWriter* findSubBlocks(SafeWriter* stream, std::vector<SafeWriter*>& subBlock
if (lastOrig!=SIZE_MAX) { if (lastOrig!=SIZE_MAX) {
// commit previous block and start new one // commit previous block and start new one
//logV("%x gains: %d",(int)lastOrig,gains); //logV("%x gains: %d",(int)lastOrig,gains);
if (gains>bestBenefit) { int finalBenefit=gains*2+lastLen*3;
if (gains<1) finalBenefit=-1;
if (finalBenefit>bestBenefit) {
bestBenefitIndex=lastOrigOff; bestBenefitIndex=lastOrigOff;
bestBenefit=gains; bestBenefit=finalBenefit;
} }
if (gains<=0) { if (gains<=0) {
// don't make a sub-block for these matches since we only have loss // don't make a sub-block for these matches since we only have loss
@ -1020,15 +1034,12 @@ SafeWriter* findSubBlocks(SafeWriter* stream, std::vector<SafeWriter*>& subBlock
logV("done!"); logV("done!");
// get out if we haven't made any blocks // get out if we haven't made any blocks
if (!newBlocks) break; if (!newBlocks) return stream;
// remove nop's // remove nop's
stream=stripNops(stream); stream=stripNops(stream);
buf=stream->getFinalBuf(); buf=stream->getFinalBuf();
logV("doing it again...");
}
return stream; return stream;
} }
@ -1059,19 +1070,20 @@ SafeWriter* packStream(SafeWriter* s, unsigned char* speedDial) {
try { try {
addr=addrTable[addr]; addr=addrTable[addr];
// check whether we have sufficient room to turn this into a 16-bit call // check whether we have sufficient room to turn this into a 16-bit call
/*
if (addr<0xff00) { if (addr<0xff00) {
buf[i]=0xf8; buf[i]=0xf8;
buf[i+1]=addr&0xff; buf[i+1]=addr&0xff;
buf[i+2]=(addr>>8)&0xff; buf[i+2]=(addr>>8)&0xff;
buf[i+3]=0xf1; buf[i+3]=0xf1;
buf[i+4]=0xf1; buf[i+4]=0xf1;
} else { } else {*/
buf[i]=0xf5; buf[i]=0xf5;
buf[i+1]=addr&0xff; buf[i+1]=addr&0xff;
buf[i+2]=(addr>>8)&0xff; buf[i+2]=(addr>>8)&0xff;
buf[i+3]=(addr>>16)&0xff; buf[i+3]=(addr>>16)&0xff;
buf[i+4]=(addr>>24)&0xff; buf[i+4]=(addr>>24)&0xff;
} //}
} catch (std::out_of_range& e) { } catch (std::out_of_range& e) {
logW("address %x is not mappable!",addr); logW("address %x is not mappable!",addr);
} }
@ -1458,21 +1470,15 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, unsigned int disable
// 6 is the minimum size that can be reliably optimized // 6 is the minimum size that can be reliably optimized
logI("finding sub-blocks"); logI("finding sub-blocks");
globalStream=findSubBlocks(globalStream,subBlocks,sortedCmd);
// find sub-blocks within sub-blocks
size_t subBlocksLast=0;
size_t subBlocksLen=subBlocks.size();
logI("finding sub-blocks within sub-blocks");
while (subBlocksLast!=subBlocksLen) {
logI("got %d blocks... starting from %d",(int)subBlocksLen,(int)subBlocksLast);
for (size_t i=subBlocksLast; i<subBlocksLen; i++) {
SafeWriter* newBlock=findSubBlocks(subBlocks[i],subBlocks,sortedCmd);
subBlocks[i]=newBlock;
}
subBlocksLast=subBlocksLen;
subBlocksLen=subBlocks.size();
}
bool haveBlocks=false;
subBlocks.clear();
// repeat until no more sub-blocks are produced
do {
logD("iteration...");
globalStream=findSubBlocks(globalStream,subBlocks,sortedCmd,progress);
haveBlocks=!subBlocks.empty();
// insert sub-blocks and resolve symbols // insert sub-blocks and resolve symbols
logI("%d sub-blocks total",(int)subBlocks.size()); logI("%d sub-blocks total",(int)subBlocks.size());
std::vector<size_t> blockOff; std::vector<size_t> blockOff;
@ -1528,6 +1534,7 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, unsigned int disable
} }
} }
} }
} while (haveBlocks);
size_t afterSize=globalStream->size(); size_t afterSize=globalStream->size();
logI("(before: %d - after: %d)",(int)beforeSize,(int)afterSize); logI("(before: %d - after: %d)",(int)beforeSize,(int)afterSize);

View file

@ -6064,7 +6064,7 @@ bool FurnaceGUI::loop() {
} }
} else { } else {
WAKE_UP; WAKE_UP;
ImGui::Text("Exporting..."); ImGui::Text("Exporting... %d",csProgress.count);
// check whether we're done // check whether we're done
if (csExportDone) { if (csExportDone) {