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
|
||||
{
|
||||
if (c < 0x80)
|
||||
ppu.control = PPU_CTRL_VAR | 0x04;
|
||||
else if (c != 0xff)
|
||||
ppu.control = PPU_CTRL_VAR & ~0x04;
|
||||
else if (c != 0xff)
|
||||
ppu.control = PPU_CTRL_VAR | 0x04;
|
||||
else
|
||||
return;
|
||||
|
||||
|
|
|
@ -821,10 +821,14 @@ bool Compiler::WriteOutputFile(const char* targetPath, DiskImage * d64)
|
|||
}
|
||||
else if (mCompilerOptions & COPT_TARGET_NES)
|
||||
{
|
||||
strcpy_s(lblPath, prgPath);
|
||||
strcat_s(lblPath, "mlb");
|
||||
|
||||
strcat_s(prgPath, "nes");
|
||||
if (mCompilerOptions & COPT_VERBOSE)
|
||||
printf("Writing <%s>\n", prgPath);
|
||||
mLinker->WriteNesFile(prgPath);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -852,7 +856,11 @@ bool Compiler::WriteOutputFile(const char* targetPath, DiskImage * d64)
|
|||
|
||||
if (mCompilerOptions & COPT_VERBOSE)
|
||||
printf("Writing <%s>\n", lblPath);
|
||||
mLinker->WriteLblFile(lblPath);
|
||||
|
||||
if (mCompilerOptions & COPT_TARGET_NES)
|
||||
mLinker->WriteMlbFile(lblPath);
|
||||
else
|
||||
mLinker->WriteLblFile(lblPath);
|
||||
|
||||
if (mCompilerOptions & COPT_VERBOSE)
|
||||
printf("Writing <%s>\n", intPath);
|
||||
|
|
|
@ -756,7 +756,13 @@ const char* NativeCodeDisassembler::AddrName(int addr, char* buffer, Linker* lin
|
|||
LinkerObject* obj = linker->FindObjectByAddr(addr);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -238,6 +238,82 @@ void InterCodeGenerator::InitLocalVariable(InterCodeProcedure* proc, Declaration
|
|||
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)
|
||||
{
|
||||
|
@ -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->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;
|
||||
while (type->mType == DT_TYPE_ARRAY)
|
||||
type = type->mBase;
|
||||
|
|
|
@ -944,6 +944,49 @@ bool Linker::WriteMapFile(const char* filename)
|
|||
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)
|
||||
{
|
||||
FILE* file;
|
||||
|
|
|
@ -151,24 +151,33 @@ static const uint32 LOBJF_RET_REG_A = 0x00010000;
|
|||
static const uint32 LOBJF_RET_REG_X = 0x00020000;
|
||||
|
||||
|
||||
class LinkerObjectRange
|
||||
{
|
||||
public:
|
||||
const Ident * mIdent;
|
||||
int mOffset, mSize;
|
||||
};
|
||||
|
||||
class LinkerObject
|
||||
{
|
||||
public:
|
||||
Location mLocation;
|
||||
const Ident * mIdent;
|
||||
LinkerObjectType mType;
|
||||
int mID;
|
||||
int mAddress, mRefAddress;
|
||||
int mSize, mAlignment;
|
||||
LinkerSection * mSection;
|
||||
LinkerRegion * mRegion;
|
||||
uint8 * mData;
|
||||
InterCodeProcedure * mProc;
|
||||
uint32 mFlags;
|
||||
uint8 mTemporaries[16], mTempSizes[16];
|
||||
int mNumTemporaries;
|
||||
ZeroPageSet mZeroPageSet;
|
||||
LinkerSection * mStackSection;
|
||||
Location mLocation;
|
||||
const Ident * mIdent;
|
||||
LinkerObjectType mType;
|
||||
int mID;
|
||||
int mAddress, mRefAddress;
|
||||
int mSize, mAlignment;
|
||||
LinkerSection * mSection;
|
||||
LinkerRegion * mRegion;
|
||||
uint8 * mData;
|
||||
InterCodeProcedure * mProc;
|
||||
uint32 mFlags;
|
||||
uint8 mTemporaries[16], mTempSizes[16];
|
||||
int mNumTemporaries;
|
||||
ZeroPageSet mZeroPageSet;
|
||||
LinkerSection * mStackSection;
|
||||
|
||||
ExpandingArray<LinkerObjectRange> mRanges;
|
||||
|
||||
LinkerObject(void);
|
||||
~LinkerObject(void);
|
||||
|
@ -230,6 +239,7 @@ public:
|
|||
bool WriteCrtFile(const char* filename);
|
||||
bool WriteBinFile(const char* filename);
|
||||
bool WriteNesFile(const char* filename);
|
||||
bool WriteMlbFile(const char* filename);
|
||||
|
||||
uint64 mCompilerOptions;
|
||||
|
||||
|
|
|
@ -3235,26 +3235,44 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
|
|||
}
|
||||
break;
|
||||
case ASMIT_TAX:
|
||||
data.ResetX();
|
||||
data.mRegs[CPU_REG_X] = data.mRegs[CPU_REG_A];
|
||||
if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE)
|
||||
if (data.mRegs[CPU_REG_X].SameData(data.mRegs[CPU_REG_A]) && !(mLive & LIVE_CPU_REG_Z))
|
||||
{
|
||||
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
||||
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue;
|
||||
mType = ASMIT_NOP;
|
||||
mMode = ASMIM_IMPLIED;
|
||||
changed = true;
|
||||
}
|
||||
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;
|
||||
case ASMIT_TAY:
|
||||
data.ResetY();
|
||||
data.mRegs[CPU_REG_Y] = data.mRegs[CPU_REG_A];
|
||||
if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE)
|
||||
if (data.mRegs[CPU_REG_Y].SameData(data.mRegs[CPU_REG_A]) && !(mLive & LIVE_CPU_REG_Z))
|
||||
{
|
||||
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
||||
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue;
|
||||
mType = ASMIT_NOP;
|
||||
mMode = ASMIM_IMPLIED;
|
||||
changed = true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -13139,6 +13157,202 @@ bool NativeCodeBasicBlock::ForwardZpYIndex(bool full)
|
|||
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 changed = false;
|
||||
|
@ -14920,6 +15134,89 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc)
|
|||
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 &&
|
||||
mIns[i + 1].mType == ASMIT_CLC &&
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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())
|
||||
|
@ -32212,6 +32553,14 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
|||
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
|
||||
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 (
|
||||
mIns[i + 0].mType == ASMIT_EOR && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0x80 &&
|
||||
mIns[i + 1].mType == ASMIT_SEC &&
|
||||
|
@ -37389,13 +37738,14 @@ void NativeCodeProcedure::Optimize(void)
|
|||
ResetVisited();
|
||||
if (mEntryBlock->MoveAccuTrainsDown())
|
||||
changed = true;
|
||||
|
||||
ResetVisited();
|
||||
if (mEntryBlock->CombineSameXY())
|
||||
changed = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#if 1
|
||||
if (step == 6)
|
||||
{
|
||||
|
|
|
@ -377,6 +377,11 @@ public:
|
|||
bool ForwardZpXIndex(bool full);
|
||||
|
||||
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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue