Improve labels in disassembler listing, add mlb file for nes
This commit is contained in:
parent
2959016496
commit
efff725745
|
@ -570,9 +570,9 @@ void flush_vram_update(unsigned char *buf)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (c < 0x80)
|
if (c < 0x80)
|
||||||
ppu.control = PPU_CTRL_VAR | 0x04;
|
|
||||||
else if (c != 0xff)
|
|
||||||
ppu.control = PPU_CTRL_VAR & ~0x04;
|
ppu.control = PPU_CTRL_VAR & ~0x04;
|
||||||
|
else if (c != 0xff)
|
||||||
|
ppu.control = PPU_CTRL_VAR | 0x04;
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -821,10 +821,14 @@ bool Compiler::WriteOutputFile(const char* targetPath, DiskImage * d64)
|
||||||
}
|
}
|
||||||
else if (mCompilerOptions & COPT_TARGET_NES)
|
else if (mCompilerOptions & COPT_TARGET_NES)
|
||||||
{
|
{
|
||||||
|
strcpy_s(lblPath, prgPath);
|
||||||
|
strcat_s(lblPath, "mlb");
|
||||||
|
|
||||||
strcat_s(prgPath, "nes");
|
strcat_s(prgPath, "nes");
|
||||||
if (mCompilerOptions & COPT_VERBOSE)
|
if (mCompilerOptions & COPT_VERBOSE)
|
||||||
printf("Writing <%s>\n", prgPath);
|
printf("Writing <%s>\n", prgPath);
|
||||||
mLinker->WriteNesFile(prgPath);
|
mLinker->WriteNesFile(prgPath);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -852,7 +856,11 @@ bool Compiler::WriteOutputFile(const char* targetPath, DiskImage * d64)
|
||||||
|
|
||||||
if (mCompilerOptions & COPT_VERBOSE)
|
if (mCompilerOptions & COPT_VERBOSE)
|
||||||
printf("Writing <%s>\n", lblPath);
|
printf("Writing <%s>\n", lblPath);
|
||||||
mLinker->WriteLblFile(lblPath);
|
|
||||||
|
if (mCompilerOptions & COPT_TARGET_NES)
|
||||||
|
mLinker->WriteMlbFile(lblPath);
|
||||||
|
else
|
||||||
|
mLinker->WriteLblFile(lblPath);
|
||||||
|
|
||||||
if (mCompilerOptions & COPT_VERBOSE)
|
if (mCompilerOptions & COPT_VERBOSE)
|
||||||
printf("Writing <%s>\n", intPath);
|
printf("Writing <%s>\n", intPath);
|
||||||
|
|
|
@ -756,7 +756,13 @@ const char* NativeCodeDisassembler::AddrName(int addr, char* buffer, Linker* lin
|
||||||
LinkerObject* obj = linker->FindObjectByAddr(addr);
|
LinkerObject* obj = linker->FindObjectByAddr(addr);
|
||||||
if (obj && obj->mIdent)
|
if (obj && obj->mIdent)
|
||||||
{
|
{
|
||||||
sprintf_s(buffer, 160, "; (%s + %d)", obj->mIdent->mString, addr - obj->mAddress);
|
int i = 0;
|
||||||
|
while (i < obj->mRanges.Size() && (addr - obj->mAddress < obj->mRanges[i].mOffset || addr - obj->mAddress - obj->mRanges[i].mOffset >= obj->mRanges[i].mSize))
|
||||||
|
i++;
|
||||||
|
if (i < obj->mRanges.Size())
|
||||||
|
sprintf_s(buffer, 160, "; (%s.%s + %d)", obj->mIdent->mString, obj->mRanges[i].mIdent->mString, addr - obj->mAddress - obj->mRanges[i].mOffset);
|
||||||
|
else
|
||||||
|
sprintf_s(buffer, 160, "; (%s + %d)", obj->mIdent->mString, addr - obj->mAddress);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,6 +238,82 @@ void InterCodeGenerator::InitLocalVariable(InterCodeProcedure* proc, Declaration
|
||||||
proc->mLocalVars[index]->mIdent = dec->mIdent;
|
proc->mLocalVars[index]->mIdent = dec->mIdent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static const Ident* StructIdent(const Ident* base, const Ident* item)
|
||||||
|
{
|
||||||
|
if (base)
|
||||||
|
{
|
||||||
|
char buffer[200];
|
||||||
|
strcpy_s(buffer, base->mString);
|
||||||
|
strcat_s(buffer, ".");
|
||||||
|
strcat_s(buffer, item->mString);
|
||||||
|
return Ident::Unique(buffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AddGlobalVariableRanges(LinkerObject* lo, Declaration* dec, int offset, const Ident* ident)
|
||||||
|
{
|
||||||
|
switch (dec->mType)
|
||||||
|
{
|
||||||
|
case DT_TYPE_STRUCT:
|
||||||
|
{
|
||||||
|
Declaration* deci = dec->mParams;
|
||||||
|
while (deci)
|
||||||
|
{
|
||||||
|
AddGlobalVariableRanges(lo, deci->mBase, offset + deci->mOffset, StructIdent(ident, deci->mIdent));
|
||||||
|
deci = deci->mNext;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case DT_TYPE_INTEGER:
|
||||||
|
case DT_TYPE_FLOAT:
|
||||||
|
case DT_TYPE_POINTER:
|
||||||
|
case DT_TYPE_BOOL:
|
||||||
|
case DT_TYPE_ENUM:
|
||||||
|
{
|
||||||
|
LinkerObjectRange range;
|
||||||
|
range.mOffset = offset;
|
||||||
|
range.mSize = dec->mStripe;
|
||||||
|
switch (dec->mSize)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
range.mIdent = ident;
|
||||||
|
lo->mRanges.Push(range);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
range.mIdent = StructIdent(ident, Ident::Unique("lo"));
|
||||||
|
lo->mRanges.Push(range);
|
||||||
|
range.mOffset += dec->mStripe;
|
||||||
|
range.mIdent = StructIdent(ident, Ident::Unique("hi"));
|
||||||
|
lo->mRanges.Push(range);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
range.mIdent = StructIdent(ident, Ident::Unique("b0"));
|
||||||
|
lo->mRanges.Push(range);
|
||||||
|
range.mOffset += dec->mStripe;
|
||||||
|
range.mIdent = StructIdent(ident, Ident::Unique("b1"));
|
||||||
|
lo->mRanges.Push(range);
|
||||||
|
range.mOffset += dec->mStripe;
|
||||||
|
range.mIdent = StructIdent(ident, Ident::Unique("b2"));
|
||||||
|
lo->mRanges.Push(range);
|
||||||
|
range.mOffset += dec->mStripe;
|
||||||
|
range.mIdent = StructIdent(ident, Ident::Unique("b3"));
|
||||||
|
lo->mRanges.Push(range);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (ident)
|
||||||
|
{
|
||||||
|
LinkerObjectRange range;
|
||||||
|
range.mIdent = ident;
|
||||||
|
range.mOffset = offset;
|
||||||
|
range.mSize = dec->mSize * dec->mStripe;
|
||||||
|
lo->mRanges.Push(range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void InterCodeGenerator::InitGlobalVariable(InterCodeModule * mod, Declaration* dec)
|
void InterCodeGenerator::InitGlobalVariable(InterCodeModule * mod, Declaration* dec)
|
||||||
{
|
{
|
||||||
|
@ -249,6 +325,13 @@ void InterCodeGenerator::InitGlobalVariable(InterCodeModule * mod, Declaration*
|
||||||
var->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mIdent, dec->mSection, LOT_DATA, dec->mAlignment);
|
var->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mIdent, dec->mSection, LOT_DATA, dec->mAlignment);
|
||||||
var->mIdent = dec->mIdent;
|
var->mIdent = dec->mIdent;
|
||||||
|
|
||||||
|
Declaration* decb = dec->mBase;
|
||||||
|
while (decb && decb->mType == DT_TYPE_ARRAY)
|
||||||
|
decb = decb->mBase;
|
||||||
|
|
||||||
|
if (decb && decb->mStripe != 1)
|
||||||
|
AddGlobalVariableRanges(var->mLinkerObject, decb, 0, nullptr);
|
||||||
|
|
||||||
Declaration* type = dec->mBase;
|
Declaration* type = dec->mBase;
|
||||||
while (type->mType == DT_TYPE_ARRAY)
|
while (type->mType == DT_TYPE_ARRAY)
|
||||||
type = type->mBase;
|
type = type->mBase;
|
||||||
|
|
|
@ -944,6 +944,49 @@ bool Linker::WriteMapFile(const char* filename)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Linker::WriteMlbFile(const char* filename)
|
||||||
|
{
|
||||||
|
FILE* file;
|
||||||
|
fopen_s(&file, filename, "wb");
|
||||||
|
if (file)
|
||||||
|
{
|
||||||
|
fprintf(file, "R:%02x-%02x:__ACCU\n", BC_REG_ACCU, BC_REG_ACCU + 3);
|
||||||
|
fprintf(file, "R:%02x-%02x:__ADDR\n", BC_REG_ADDR, BC_REG_ADDR + 1);
|
||||||
|
fprintf(file, "R:%02x-%02x:__IP\n", BC_REG_IP, BC_REG_IP + 1);
|
||||||
|
fprintf(file, "R:%02x-%02x:__SP\n", BC_REG_STACK, BC_REG_STACK + 1);
|
||||||
|
fprintf(file, "R:%02x-%02x:__FP\n", BC_REG_LOCALS, BC_REG_LOCALS + 1);
|
||||||
|
fprintf(file, "R:%02x-%02x:__P\n", BC_REG_FPARAMS, BC_REG_FPARAMS_END - 1);
|
||||||
|
fprintf(file, "R:%02x-%02x:__T\n", BC_REG_TMP, 0x7f);
|
||||||
|
|
||||||
|
for (int i = 0; i < mObjects.Size(); i++)
|
||||||
|
{
|
||||||
|
LinkerObject* obj = mObjects[i];
|
||||||
|
|
||||||
|
if ((obj->mFlags & LOBJF_REFERENCED) && obj->mIdent && obj->mSize > 0)
|
||||||
|
{
|
||||||
|
if (obj->mSection->mType == LST_BSS)
|
||||||
|
fprintf(file, "R:%04x-%04x:%s\n", obj->mAddress, obj->mAddress + obj->mSize - 1, obj->mIdent->mString);
|
||||||
|
else if (obj->mType == LOT_DATA)
|
||||||
|
{
|
||||||
|
if (!obj->mRegion->mCartridgeBanks)
|
||||||
|
fprintf(file, "P:%04x-%04x:%s\n", obj->mAddress - 0x8000, obj->mAddress - 0x8000 + obj->mSize - 1, obj->mIdent->mString);
|
||||||
|
}
|
||||||
|
else if (obj->mType == LOT_NATIVE_CODE)
|
||||||
|
{
|
||||||
|
if (!obj->mRegion->mCartridgeBanks)
|
||||||
|
fprintf(file, "P:%04x:%s\n", obj->mAddress - 0x8000, obj->mIdent->mString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool Linker::WriteLblFile(const char* filename)
|
bool Linker::WriteLblFile(const char* filename)
|
||||||
{
|
{
|
||||||
FILE* file;
|
FILE* file;
|
||||||
|
|
|
@ -151,24 +151,33 @@ static const uint32 LOBJF_RET_REG_A = 0x00010000;
|
||||||
static const uint32 LOBJF_RET_REG_X = 0x00020000;
|
static const uint32 LOBJF_RET_REG_X = 0x00020000;
|
||||||
|
|
||||||
|
|
||||||
|
class LinkerObjectRange
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const Ident * mIdent;
|
||||||
|
int mOffset, mSize;
|
||||||
|
};
|
||||||
|
|
||||||
class LinkerObject
|
class LinkerObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Location mLocation;
|
Location mLocation;
|
||||||
const Ident * mIdent;
|
const Ident * mIdent;
|
||||||
LinkerObjectType mType;
|
LinkerObjectType mType;
|
||||||
int mID;
|
int mID;
|
||||||
int mAddress, mRefAddress;
|
int mAddress, mRefAddress;
|
||||||
int mSize, mAlignment;
|
int mSize, mAlignment;
|
||||||
LinkerSection * mSection;
|
LinkerSection * mSection;
|
||||||
LinkerRegion * mRegion;
|
LinkerRegion * mRegion;
|
||||||
uint8 * mData;
|
uint8 * mData;
|
||||||
InterCodeProcedure * mProc;
|
InterCodeProcedure * mProc;
|
||||||
uint32 mFlags;
|
uint32 mFlags;
|
||||||
uint8 mTemporaries[16], mTempSizes[16];
|
uint8 mTemporaries[16], mTempSizes[16];
|
||||||
int mNumTemporaries;
|
int mNumTemporaries;
|
||||||
ZeroPageSet mZeroPageSet;
|
ZeroPageSet mZeroPageSet;
|
||||||
LinkerSection * mStackSection;
|
LinkerSection * mStackSection;
|
||||||
|
|
||||||
|
ExpandingArray<LinkerObjectRange> mRanges;
|
||||||
|
|
||||||
LinkerObject(void);
|
LinkerObject(void);
|
||||||
~LinkerObject(void);
|
~LinkerObject(void);
|
||||||
|
@ -230,6 +239,7 @@ public:
|
||||||
bool WriteCrtFile(const char* filename);
|
bool WriteCrtFile(const char* filename);
|
||||||
bool WriteBinFile(const char* filename);
|
bool WriteBinFile(const char* filename);
|
||||||
bool WriteNesFile(const char* filename);
|
bool WriteNesFile(const char* filename);
|
||||||
|
bool WriteMlbFile(const char* filename);
|
||||||
|
|
||||||
uint64 mCompilerOptions;
|
uint64 mCompilerOptions;
|
||||||
|
|
||||||
|
|
|
@ -3235,26 +3235,44 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ASMIT_TAX:
|
case ASMIT_TAX:
|
||||||
data.ResetX();
|
if (data.mRegs[CPU_REG_X].SameData(data.mRegs[CPU_REG_A]) && !(mLive & LIVE_CPU_REG_Z))
|
||||||
data.mRegs[CPU_REG_X] = data.mRegs[CPU_REG_A];
|
|
||||||
if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE)
|
|
||||||
{
|
{
|
||||||
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
mType = ASMIT_NOP;
|
||||||
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue;
|
mMode = ASMIM_IMPLIED;
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
data.mRegs[CPU_REG_Z].Reset();
|
{
|
||||||
|
data.ResetX();
|
||||||
|
data.mRegs[CPU_REG_X] = data.mRegs[CPU_REG_A];
|
||||||
|
if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE)
|
||||||
|
{
|
||||||
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
||||||
|
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
data.mRegs[CPU_REG_Z].Reset();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ASMIT_TAY:
|
case ASMIT_TAY:
|
||||||
data.ResetY();
|
if (data.mRegs[CPU_REG_Y].SameData(data.mRegs[CPU_REG_A]) && !(mLive & LIVE_CPU_REG_Z))
|
||||||
data.mRegs[CPU_REG_Y] = data.mRegs[CPU_REG_A];
|
|
||||||
if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE)
|
|
||||||
{
|
{
|
||||||
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
mType = ASMIT_NOP;
|
||||||
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue;
|
mMode = ASMIM_IMPLIED;
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
data.mRegs[CPU_REG_Z].Reset();
|
{
|
||||||
|
data.ResetY();
|
||||||
|
data.mRegs[CPU_REG_Y] = data.mRegs[CPU_REG_A];
|
||||||
|
if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE)
|
||||||
|
{
|
||||||
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
||||||
|
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
data.mRegs[CPU_REG_Z].Reset();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13139,6 +13157,202 @@ bool NativeCodeBasicBlock::ForwardZpYIndex(bool full)
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::CanCombineSameYtoX(int start, int end)
|
||||||
|
{
|
||||||
|
for (int i = start; i < end; i++)
|
||||||
|
{
|
||||||
|
NativeCodeInstruction& ins(mIns[i]);
|
||||||
|
|
||||||
|
if (ins.mMode == ASMIM_INDIRECT_Y)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ins.mMode == ASMIM_ABSOLUTE_Y && !HasAsmInstructionMode(ins.mType, ASMIM_ABSOLUTE_X))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::CanCombineSameXtoY(int start, int end)
|
||||||
|
{
|
||||||
|
for (int i = start; i < end; i++)
|
||||||
|
{
|
||||||
|
NativeCodeInstruction& ins(mIns[i]);
|
||||||
|
|
||||||
|
if (ins.mMode == ASMIM_INDIRECT_X)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ins.mMode == ASMIM_ABSOLUTE_X && !HasAsmInstructionMode(ins.mType, ASMIM_ABSOLUTE_Y))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::CombineSameXtoY(int xpos, int ypos, int end)
|
||||||
|
{
|
||||||
|
if (xpos < ypos)
|
||||||
|
{
|
||||||
|
if (CanCombineSameXtoY(xpos, ypos) &&
|
||||||
|
CanCombineSameXtoY(ypos, end))
|
||||||
|
{
|
||||||
|
ReplaceXRegWithYReg(xpos, ypos);
|
||||||
|
ReplaceXRegWithYReg(ypos, end);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (CanCombineSameXtoY(xpos, end))
|
||||||
|
{
|
||||||
|
ReplaceXRegWithYReg(xpos, end);
|
||||||
|
#if 0
|
||||||
|
if (!(mIns[xpos].mLive & LIVE_CPU_REG_Z))
|
||||||
|
{
|
||||||
|
mIns[xpos].mType = ASMIT_NOP;
|
||||||
|
mIns[xpos].mMode = ASMIM_IMPLIED;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::CombineSameYtoX(int xpos, int ypos, int end)
|
||||||
|
{
|
||||||
|
if (ypos < xpos)
|
||||||
|
{
|
||||||
|
if (CanCombineSameYtoX(ypos, xpos) &&
|
||||||
|
CanCombineSameYtoX(xpos + 1, end))
|
||||||
|
{
|
||||||
|
ReplaceYRegWithXReg(ypos, xpos);
|
||||||
|
ReplaceYRegWithXReg(xpos + 1, end);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (CanCombineSameYtoX(ypos, end))
|
||||||
|
{
|
||||||
|
ReplaceYRegWithXReg(ypos, end);
|
||||||
|
#if 0
|
||||||
|
if (!(mIns[ypos].mLive & LIVE_CPU_REG_Z))
|
||||||
|
{
|
||||||
|
mIns[ypos].mType = ASMIT_NOP;
|
||||||
|
mIns[ypos].mMode = ASMIM_IMPLIED;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::CombineSameXY(void)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
if (!mVisited)
|
||||||
|
{
|
||||||
|
mVisited = true;
|
||||||
|
|
||||||
|
int xreg = -1, yreg = -1;
|
||||||
|
int xpos, ypos;
|
||||||
|
bool samexy = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < mIns.Size(); i++)
|
||||||
|
{
|
||||||
|
NativeCodeInstruction& ins(mIns[i]);
|
||||||
|
|
||||||
|
if (ins.ChangesXReg())
|
||||||
|
{
|
||||||
|
if (samexy && CombineSameXtoY(xpos, ypos, i))
|
||||||
|
changed = true;
|
||||||
|
xreg = -1;
|
||||||
|
samexy = false;
|
||||||
|
}
|
||||||
|
if (ins.ChangesYReg())
|
||||||
|
{
|
||||||
|
if (samexy && CombineSameYtoX(ypos, xpos, i))
|
||||||
|
changed = true;
|
||||||
|
yreg = -1;
|
||||||
|
samexy = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ins.mType == ASMIT_TAX)
|
||||||
|
{
|
||||||
|
xreg = CPU_REG_A;
|
||||||
|
xpos = i;
|
||||||
|
samexy = yreg == xreg;
|
||||||
|
}
|
||||||
|
else if (ins.mType == ASMIT_TAY)
|
||||||
|
{
|
||||||
|
yreg = CPU_REG_A;
|
||||||
|
ypos = i;
|
||||||
|
samexy = xreg == yreg;
|
||||||
|
}
|
||||||
|
else if (ins.mType == ASMIT_LDX)
|
||||||
|
{
|
||||||
|
if (ins.mMode == ASMIM_ZERO_PAGE)
|
||||||
|
{
|
||||||
|
xreg = ins.mAddress;
|
||||||
|
xpos = i;
|
||||||
|
samexy = yreg == xreg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
xreg = -1;
|
||||||
|
}
|
||||||
|
else if (ins.mType == ASMIT_LDY)
|
||||||
|
{
|
||||||
|
if (ins.mMode == ASMIM_ZERO_PAGE)
|
||||||
|
{
|
||||||
|
yreg = ins.mAddress;
|
||||||
|
ypos = i;
|
||||||
|
samexy = xreg == yreg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
yreg = -1;
|
||||||
|
}
|
||||||
|
else if (ins.ChangesAccu())
|
||||||
|
{
|
||||||
|
if (xreg == CPU_REG_A)
|
||||||
|
xreg = -1;
|
||||||
|
if (yreg == CPU_REG_A)
|
||||||
|
yreg = -1;
|
||||||
|
}
|
||||||
|
else if (ins.mMode == ASMIM_ZERO_PAGE && ins.ChangesAddress())
|
||||||
|
{
|
||||||
|
if (xreg == ins.mAddress)
|
||||||
|
xreg = -1;
|
||||||
|
if (yreg == ins.mAddress)
|
||||||
|
yreg = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (samexy)
|
||||||
|
{
|
||||||
|
if (!mExitRequiredRegs[CPU_REG_X] && CombineSameXtoY(xpos, ypos, mIns.Size()))
|
||||||
|
changed = true;
|
||||||
|
else if (!mExitRequiredRegs[CPU_REG_Y] && CombineSameYtoX(xpos, ypos, mIns.Size()))
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTrueJump && mTrueJump->CombineSameXY())
|
||||||
|
changed = true;
|
||||||
|
if (mFalseJump && mFalseJump->CombineSameXY())
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
bool NativeCodeBasicBlock::RegisterValueForwarding(void)
|
bool NativeCodeBasicBlock::RegisterValueForwarding(void)
|
||||||
{
|
{
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
@ -14920,6 +15134,89 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mIns[i + 0].mType == ASMIT_TXA &&
|
||||||
|
mIns[i + 1].mType == ASMIT_CLC &&
|
||||||
|
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 1 &&
|
||||||
|
mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 3].mLive & LIVE_CPU_REG_X) &&
|
||||||
|
mIns[i + 4].mType == ASMIT_LDA &&
|
||||||
|
mIns[i + 5].mType == ASMIT_ADC && mIns[i + 5].mMode == ASMIM_IMMEDIATE && mIns[i + 5].mAddress == 0 &&
|
||||||
|
mIns[i + 6].mType == ASMIT_STA && mIns[i + 4].SameEffectiveAddress(mIns[i + 6]) &&
|
||||||
|
HasAsmInstructionMode(ASMIT_INC, mIns[i + 6].mMode) &&
|
||||||
|
!(mIns[i + 6].mLive & (LIVE_CPU_REG_C | LIVE_CPU_REG_Z)))
|
||||||
|
{
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
NativeCodeBasicBlock* iblock = proc->AllocateBlock();
|
||||||
|
NativeCodeBasicBlock* fblock = proc->AllocateBlock();
|
||||||
|
|
||||||
|
fblock->mTrueJump = mTrueJump;
|
||||||
|
fblock->mFalseJump = mFalseJump;
|
||||||
|
fblock->mBranch = mBranch;
|
||||||
|
|
||||||
|
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
|
||||||
|
mIns[i + 1].mType = ASMIT_NOP;
|
||||||
|
mIns[i + 2].mType = ASMIT_INX; mIns[i + 2].mLive |= LIVE_CPU_REG_Z | LIVE_CPU_REG_X;
|
||||||
|
mIns[i + 3].mType = ASMIT_STX; mIns[i + 3].mLive |= LIVE_CPU_REG_Z;
|
||||||
|
|
||||||
|
fblock->mIns.Push(mIns[i + 4]);
|
||||||
|
|
||||||
|
for (int j = i + 7; j < mIns.Size(); j++)
|
||||||
|
fblock->mIns.Push(mIns[j]);
|
||||||
|
iblock->mIns.Push(mIns[i + 6]);
|
||||||
|
|
||||||
|
|
||||||
|
mIns.SetSize(i + 4);
|
||||||
|
iblock->mIns[0].mType = ASMIT_INC;
|
||||||
|
|
||||||
|
iblock->mTrueJump = fblock;
|
||||||
|
iblock->mBranch = ASMIT_JMP;
|
||||||
|
|
||||||
|
mTrueJump = fblock;
|
||||||
|
mFalseJump = iblock;
|
||||||
|
mBranch = ASMIT_BNE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mIns[i + 0].mType == ASMIT_TYA &&
|
||||||
|
mIns[i + 1].mType == ASMIT_CLC &&
|
||||||
|
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 1 &&
|
||||||
|
mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 3].mLive & LIVE_CPU_REG_Y) &&
|
||||||
|
mIns[i + 4].mType == ASMIT_TXA &&
|
||||||
|
mIns[i + 5].mType == ASMIT_ADC && mIns[i + 5].mMode == ASMIM_IMMEDIATE && mIns[i + 5].mAddress == 0 &&
|
||||||
|
mIns[i + 6].mType == ASMIT_TAX &&
|
||||||
|
!(mIns[i + 6].mLive & (LIVE_CPU_REG_C | LIVE_CPU_REG_Z)))
|
||||||
|
{
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
NativeCodeBasicBlock* iblock = proc->AllocateBlock();
|
||||||
|
NativeCodeBasicBlock* fblock = proc->AllocateBlock();
|
||||||
|
|
||||||
|
fblock->mTrueJump = mTrueJump;
|
||||||
|
fblock->mFalseJump = mFalseJump;
|
||||||
|
fblock->mBranch = mBranch;
|
||||||
|
|
||||||
|
mIns[i + 0].mType = ASMIT_NOP;
|
||||||
|
mIns[i + 1].mType = ASMIT_NOP;
|
||||||
|
mIns[i + 2].mType = ASMIT_INY; mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mLive |= LIVE_CPU_REG_Z | LIVE_CPU_REG_Y;
|
||||||
|
mIns[i + 3].mType = ASMIT_STY; mIns[i + 3].mLive |= LIVE_CPU_REG_Z;
|
||||||
|
|
||||||
|
fblock->mIns.Push(NativeCodeInstruction(ASMIT_TXA));
|
||||||
|
|
||||||
|
for (int j = i + 7; j < mIns.Size(); j++)
|
||||||
|
fblock->mIns.Push(mIns[j]);
|
||||||
|
iblock->mIns.Push(NativeCodeInstruction(ASMIT_INX));
|
||||||
|
|
||||||
|
mIns.SetSize(i + 4);
|
||||||
|
|
||||||
|
iblock->mTrueJump = fblock;
|
||||||
|
iblock->mBranch = ASMIT_JMP;
|
||||||
|
|
||||||
|
mTrueJump = fblock;
|
||||||
|
mFalseJump = iblock;
|
||||||
|
mBranch = ASMIT_BNE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (mIns[i + 0].mType == ASMIT_TYA &&
|
if (mIns[i + 0].mType == ASMIT_TYA &&
|
||||||
mIns[i + 1].mType == ASMIT_CLC &&
|
mIns[i + 1].mType == ASMIT_CLC &&
|
||||||
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 1 &&
|
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 1 &&
|
||||||
|
@ -25686,6 +25983,50 @@ bool NativeCodeBasicBlock::OptimizeLoopCarryOver(void)
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sz = mIns.Size();
|
||||||
|
if (sz > 0)
|
||||||
|
{
|
||||||
|
hblock = nullptr;
|
||||||
|
|
||||||
|
if (mTrueJump->mLoopHead)
|
||||||
|
hblock = mTrueJump;
|
||||||
|
else if (mFalseJump->mLoopHead)
|
||||||
|
hblock = mFalseJump;
|
||||||
|
|
||||||
|
if (hblock && hblock->mIns.Size() > 0 && hblock->mNumEntries == 2)
|
||||||
|
{
|
||||||
|
NativeCodeBasicBlock* pblock;
|
||||||
|
if (hblock->mEntryBlocks[0] == this)
|
||||||
|
pblock = hblock->mEntryBlocks[1];
|
||||||
|
else
|
||||||
|
pblock = hblock->mEntryBlocks[0];
|
||||||
|
|
||||||
|
if (!pblock->mFalseJump)
|
||||||
|
{
|
||||||
|
if (hblock->mIns[0].mType == ASMIT_TAX && mIns[sz - 1].mType == ASMIT_TXA && !(hblock->mIns[0].mLive & LIVE_CPU_REG_Z))
|
||||||
|
{
|
||||||
|
pblock->mIns.Push(NativeCodeInstruction(ASMIT_TAX));
|
||||||
|
hblock->mIns.Remove(0);
|
||||||
|
|
||||||
|
pblock->mExitRequiredRegs += CPU_REG_X;
|
||||||
|
hblock->mEntryRequiredRegs += CPU_REG_X;
|
||||||
|
mExitRequiredRegs += CPU_REG_X;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else if (hblock->mIns[0].mType == ASMIT_TAY && mIns[sz - 1].mType == ASMIT_TYA && !(hblock->mIns[0].mLive & LIVE_CPU_REG_Z))
|
||||||
|
{
|
||||||
|
pblock->mIns.Push(NativeCodeInstruction(ASMIT_TAY));
|
||||||
|
hblock->mIns.Remove(0);
|
||||||
|
|
||||||
|
pblock->mExitRequiredRegs += CPU_REG_Y;
|
||||||
|
hblock->mEntryRequiredRegs += CPU_REG_Y;
|
||||||
|
mExitRequiredRegs += CPU_REG_Y;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mTrueJump && mTrueJump->OptimizeLoopCarryOver())
|
if (mTrueJump && mTrueJump->OptimizeLoopCarryOver())
|
||||||
|
@ -32212,6 +32553,14 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
|
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
else if (
|
||||||
|
mIns[i + 0].mType == ASMIT_SEC &&
|
||||||
|
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0xff &&
|
||||||
|
mIns[i + 2].mType == ASMIT_SBC)
|
||||||
|
{
|
||||||
|
mIns[i + 2].mType = ASMIT_EOR;
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
else if (
|
else if (
|
||||||
mIns[i + 0].mType == ASMIT_EOR && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0x80 &&
|
mIns[i + 0].mType == ASMIT_EOR && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0x80 &&
|
||||||
mIns[i + 1].mType == ASMIT_SEC &&
|
mIns[i + 1].mType == ASMIT_SEC &&
|
||||||
|
@ -37389,13 +37738,14 @@ void NativeCodeProcedure::Optimize(void)
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
if (mEntryBlock->MoveAccuTrainsDown())
|
if (mEntryBlock->MoveAccuTrainsDown())
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|
||||||
|
ResetVisited();
|
||||||
|
if (mEntryBlock->CombineSameXY())
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
if (step == 6)
|
if (step == 6)
|
||||||
{
|
{
|
||||||
|
|
|
@ -377,6 +377,11 @@ public:
|
||||||
bool ForwardZpXIndex(bool full);
|
bool ForwardZpXIndex(bool full);
|
||||||
|
|
||||||
bool RegisterValueForwarding(void);
|
bool RegisterValueForwarding(void);
|
||||||
|
bool CanCombineSameXtoY(int start, int end);
|
||||||
|
bool CanCombineSameYtoX(int start, int end);
|
||||||
|
bool CombineSameXY(void);
|
||||||
|
bool CombineSameXtoY(int xpos, int ypos, int end);
|
||||||
|
bool CombineSameYtoX(int xpos, int ypos, int end);
|
||||||
|
|
||||||
bool FindImmediateStore(int at, int reg, const NativeCodeInstruction*& ains);
|
bool FindImmediateStore(int at, int reg, const NativeCodeInstruction*& ains);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue